X-Plane 11 Instanced Drawing Sample

Note: We've created a compatibility wrapper for X-Plane 10 plugins that want to migrate to the new instancing API. This is useful if your plugin supports both X-Plane 10 and 11, and you want to use the same code for both---just set up the compatibility wrapper for the X-Plane 10 version only, and you'll get the performance benefits of the new API in your X-Plane 11 version.

#include <XPLMInstance.h>
#include <XPLMDisplay.h>
#include <XPLMGraphics.h>
#include <XPLMMenus.h>
#include <XPLMUtilities.h>
#include <XPLMPlugin.h>
#include <XPLMDataAccess.h>
#include <cstdio>
#include <cstring>

#if !XPLM300
	#error This plugin requires version 300 of the SDK
#endif

const char * g_objPath = "lib/airport/vehicles/pushback/tug.obj";
XPLMObjectRef g_object = NULL;
XPLMInstanceRef g_instance[3] = {NULL};

static void load_cb(const char * real_path, void * ref)
{
	XPLMObjectRef * dest = (XPLMObjectRef *) ref;
	if(*dest == NULL)
	{
		*dest = XPLMLoadObject(real_path);
	}
}

static void menu_cb(
					void *               inMenuRef,
					void *				inItemRef)
{
	if(!g_object)
	{
		XPLMLookupObjects(g_objPath, 0, 0, load_cb, &g_object);
	}
	if(g_object)
	{
		const char * drefs[] = { "sim/graphics/animation/ground_traffic/tire_steer_deg", NULL };
		if(!g_instance[0])
		{
			g_instance[0] = XPLMCreateInstance(g_object, drefs);
		}
		else if(!g_instance[1])
		{
			g_instance[1] = XPLMCreateInstance(g_object, drefs);
		}
		else if(!g_instance[2])
		{
			g_instance[2] = XPLMCreateInstance(g_object, drefs);
		}
	}
	
	static XPLMDataRef x = XPLMFindDataRef("sim/flightmodel/position/local_x");
	static XPLMDataRef y = XPLMFindDataRef("sim/flightmodel/position/local_y");
	static XPLMDataRef z = XPLMFindDataRef("sim/flightmodel/position/local_z");
	static XPLMDataRef heading = XPLMFindDataRef("sim/flightmodel/position/psi");
	static XPLMDataRef pitch = XPLMFindDataRef("sim/flightmodel/position/theta");
	static XPLMDataRef roll = XPLMFindDataRef("sim/flightmodel/position/phi");
	
	static float tire = 0.0;
	tire += 10.0;
	if(tire > 45.0) tire -= 90.0;
	
	XPLMDrawInfo_t		dr;
	dr.structSize = sizeof(dr);
	dr.x = XPLMGetDataf(x);
	dr.y = XPLMGetDataf(y);
	dr.z = XPLMGetDataf(z);
	dr.pitch = XPLMGetDataf(pitch);
	dr.heading = XPLMGetDataf(heading);
	dr.roll = XPLMGetDataf(roll);
	
	if(g_instance[0] || g_instance[1] || g_instance[2])
	{
		XPLMInstanceSetPosition(g_instance[2] ? g_instance[2] : (g_instance[1] ? g_instance[1] : g_instance[0]), &dr, &tire);
	}
}


PLUGIN_API int XPluginStart(char* outName, char* outSig, char* outDesc)
{
	std::strcpy(outName, "ObjTest2");
	std::strcpy(outSig, "lr.tests.obtest2");
	std::strcpy(outDesc, "Minimal test case for new API + compatibility code");
	
	XPLMEnableFeature("XPLM_WANTS_REFLECTIONS",1);
	
	int my_slot = XPLMAppendMenuItem(XPLMFindPluginsMenu(), "obj_test", NULL, 0);
	XPLMMenuID m = XPLMCreateMenu("obj_test",XPLMFindPluginsMenu(), my_slot, menu_cb, NULL);
	XPLMAppendMenuItem(m, "add instance", NULL, 0);
	return 1;
}

PLUGIN_API void	XPluginStop(void)
{
	for(int i = 0; i < 3; ++i)
	{
		if(g_instance[i])
			XPLMDestroyInstance(g_instance[i]);
	}
	if(g_object)
		XPLMUnloadObject(g_object);
}

PLUGIN_API int XPluginEnable(void)
{
	return 1;
}

PLUGIN_API void XPluginDisable(void)
{
}

PLUGIN_API void XPluginReceiveMessage(XPLMPluginID, long, void*)
{
}



  • Facebook
  • Reddit
  • Twitter
  • LinkedIn

About Tyler Young

Tyler is a software developer for X-Plane. Among other projects, he was in charge of the new X-Plane 11 user interface.
Bookmark the permalink.

3 Responses to X-Plane 11 Instanced Drawing Sample

  1. saar says:

    Thanks for the example.
    I have a question though. I use 3D objects in my plugin to represent physical "staff" in X-Plane 3D space. I manage and "drive" them through the plugin code and not through any dataref (since they are not manipulators or scenery objects, they are "mission" 3D objects).
    For example: to draw a moving 3D object, I calculate their delta location between each frame and then call the "draw" command with the "new" location in mind.
    Will this drawing technique fail tot work on XP11.10 without the wrapper ? Will "you" break this kind of code ?
    Currently I prefer not to invest to much energy on the "old" Mission-X plugin version since I'm writing it from scratch for XP11 and with future XPSDK300 features in mind (when they will be available).

    Another thing, when I click the Download links above, I receive "page not found".
    Thanks for the code example though, It will save much needed time if I'll be force to "fix" the old drawing calls.

    Cheers
    Saar

    • Ben Supnik says:

      This kind of code will keep working as long as you are using a GL-based X-Plane. But it will not work on a Vulkan-based X-PLane, so once we offer both, if the user picks Vulkan, you'll be toast.

      This code path is better handled via the new instance-based object...you'd push new location data to us per frame and let us sort out when to call draw. This works even if you don't use any datarefs - you always provide position and orientation.

    • Tyler Young says:

      Re: the broken code sample download, this will be fixed once we have an 11.10 beta ready.

Leave a Reply

Your email address will not be published. Required fields are marked *