Sorry for the glut of posts this week. I hadn’t been able to write much, but there were still interesting topics and questions coming up and I’m trying to address that backlog now. So, without further ado:
It is possible to host VE3D in a variety of contexts, and so far we’ve seen WinForms, WPF, and the browser. It is also possible to host in straight native code. In this sample, I address the COM interactions needed to host VE3D, and use OpenGL as an example hosting environment.
Download the code here.
This sample demonstrates four concepts:
Interaction with native code.
Back buffer retrieval.
Direct camera control.
Managed code provides easy and convenient methods for exposing your code to COM, and hence to native callers.
From the managed side, check “Register for COM interop” in your project’s Build tab. Decorate an interface
with ComVisible(true) and provide a guid, and the backing class with the interface type as shown. Your types
are now visible and callable.
On the native side, you can now instantiate your managed code using typical COM calls, as shown. It can then
be called similarly to any other object.
To add a new function to the interface, simply add it to the interface file and the backing .cs file, then
recompile. By designing your interface in appropriately, you can then decide whether to do most of your logic
in native or managed code, depending on where you feel more comfortable.
The Render function provides the most efficient way of pulling VE3D’s back buffer into main memory. In general
it is better to not do this, rather let the hardware render to the screen directly, but some situations demand
using the scene in some other fashion. Here, we get the memory as a direct pointer. Note that this approach
assumes that you are handling any format and stride issues yourself.
It is also possible to get a graphics object from systemMemorySurface, an HDC from that, and then use functions
like BitBlt to copy out data and handle some of these issues for you.
Direct camera control:
Most samples thus far have demonstrated use of bindings and actions, or deriving camera controller. The
CameraController class here shows how to write a controller that can react directly to user input, modifying
camera values directly. The “best practices” method is to wrap your input device in a EventSource, and use
bindings and actions to communicate the information to your controller. These structures provide simple
remapping of inputs, if necessary, and handle any threading or marshalling issues.
However, it is also possible and sometimes appropriate to take the simpler approach used here.
It is possible to integrate VE3D into an existing OpenGL application. Using the Render method described above,
the pointer produced is suitable for direct consumption by OpenGL. There are differences in how textures are
handled by the two APIs, but these are fairly simple to overcome, and are described in DrawOpenGLWindow().
Note that there is nothing that limits this sample to OpenGL, anything that can consume the buffer as provided
can host VE3D in the exact same manner.
Note on debugging:
The Visual Studio debugger requires some direction on how to deal with mixed native and managed code.
In the VE3DOpenGL properties page, expand Configuration Properties, click Debugging, then choose Debugger
Type. You can elect to only attach to native, only to managed, or to both (“mixed”). “Auto” in this case
will be native-only. If you find your breakpoints are not hitting, it is likely this setting.
Note on glut.h:
For some reason, in the release version only, I managed to get it thinking that it needed glut and I haven’t
been able to figure out why. If you encounter problems while compiling due to glut, just run in debug mode.
This is a problem that is specific to the sample app, not the methodology used.
Enjoy, and as usual please let me know about any questions or problems you may have.