Node Copied to Clipboard!

How-to Articles


How to use custom C/C++ DLL assemblies in the Storyboarder

In this tutorial you will learn how to load a custom C/C++ DLL's into Modest3D and execute code in this assembly from the Storyboarder.

The full source code for this lesson, including the Modest3D project can be found in the Samples project on modest3d.com. The project is named "Simulator DLL Loading" and the source for the C/C++ is included as a zip file in the project.

Step 1: Follow other article.

Follow all the steps outlined in the article "How to use custom .NET DLL assemblies in the Storyboarder"

Step 2: Create C/C++ DLL

We cannot directly load C/C++ DLLs in Modest3D. However, we can load a .NET DLL which then uses P/Invoke to call methods within a C/C++ DLL. The .NET code therefore can serve as a "wrapper" for the C/C++ side which handles most of the simulation logic.

For this example, let's move the logic of the Car Simulator to C++.

Create a new C or C++ project with the following files:

CarSimulator.h

#define EXPORT_API __declspec(dllexport) // Visual Studio needs annotating exported functions with this

extern "C"
{
    extern EXPORT_API float CarGetPosition();
    extern EXPORT_API float CarGetSpeed();
    extern EXPORT_API void CarUpdate(float deltaTime);
    extern EXPORT_API void CarSetAcceleratorDown(bool value);
    extern EXPORT_API void CarSetBrakeDown(bool value);
}

Car.cpp

#include "Car.h"
float AcceleratorSpeed = 10;
float BrakeSpeed = 0.8f;
float _speed = 0;
float _position = 0;
bool _isAcceleratorDown = false;
bool _isBrakeDown = false;
void CarSetBrakeDown(bool value)
{
    _isBrakeDown = value;
}
void CarSetAcceleratorDown(bool value)
{
    _isAcceleratorDown = value;
}
float CarGetSpeed()
{
    return _speed;
}
void CarUpdate(float deltaTime)
{
    _position += _speed * deltaTime;
    if (_isAcceleratorDown)
    {
        _speed += AcceleratorSpeed * deltaTime;
    }
    if (_isBrakeDown)
    {
        _speed *= BrakeSpeed;
    }
}
float CarGetPosition()
{
    return _position;
}

Step 3: Create .NET DLL

Update our C# file to the following:

using System;
using System.Linq;
using System.Runtime.InteropServices;

namespace Sim1
{
    public static class CarControls
    {
        [DllImport(@"CarSimulator.dll")]
        private static extern void CarSetAcceleratorDown(bool value);

        [DllImport(@"CarSimulator.dll")]
        private static extern void CarSetBrakeDown(bool value);

        public static void SetBrakeDown(bool value)
        {
            CarSetBrakeDown(value);
        }

        public static void SetAcceleratorDown(bool value)
        {
            CarSetAcceleratorDown(value);
        }
    }

    public static class CarSimulator
    {
        [DllImport(@"CarSimulator.dll")]
        private static extern float CarGetPosition();

        [DllImport(@"CarSimulator.dll")]
        private static extern void CarUpdate(float deltaTime);

        [DllImport(@"CarSimulator.dll")]
        private static extern float CarGetSpeed();

        const float AcceleratorSpeed = 10;
        const float BrakeSpeed = 0.8f;

        static float _speed = 0;
        static float _position = 0;

        public static float GetSpeed()
        {
            return CarGetSpeed();
        }

        public static float GetPosition()
        {
            return CarGetPosition();
        }

        public static void Update(float deltaTime)
        {
            CarUpdate(deltaTime);
        }
    }
}

Step 4: Copy the DLLs to Modest3D

Copy the C# DLL to the project folder.

Note: Do not place the C/C++ DLL here. The C/C++ DLL must be placed in the same directory as the Modest3D executable (By default this is at "C:\Program Files (x86)\Modest Tree\Modest 3D Cloud" for cloud or "C:\Program Files (x86)\Modest Tree\Modest 3D" for the offline standalone version of Modest3D)

Step 5: Open Modest3D

If you open the lesson you created based on the linked article, you should find there are a few errors in the Console tab. This is because we've changed the CarControls class to use methods instead of fields. Update these issues to use the new method.

Step 6: Run the lesson

If you run the lesson again, you should observe similar behavior as before. Pressing Up arrow moves our model forward, pressing down stops it. Only now, the logic is entirely controlled from within native C/C++.