// *************************************************
// DRAW TERRAIN OBJECT
//
// This example illustrates drawing a terrain object that moves in relation to the aircraft.  In this case 
// the object is located directly forward of the cockpit.  
// 
// For this example to work it is necessary to create an object in the aircraft folder.  Example:
// "Aircraft/General Aviation/FP404/objects/TestObject.obj".  See line 143.
//
// To turn the object on and off it is nececssary to place generic triggers on the panel of your aircraft keyed 
// to the command: BSUB/ShowObject/TestObject and BSUB/HideObject/TestObject.  
//
// Blue Side Up, 
// Bob.  
//
// Bob@RogerThat.ca
// 
// *************************************************
 
#include "XPLMPlugin.h"
#include "XPLMDisplay.h"
#include "XPLMGraphics.h"
#include "XPLMProcessing.h"
#include "XPLMDataAccess.h"
#include "XPLMMenus.h"
#include "XPLMUtilities.h"
#include "XPWidgets.h"
#include "XPStandardWidgets.h"
#include "XPLMScenery.h"
#include 
#include 
#include 
#include 

char gBob_debstr[128];

XPLMDataRef  gHeadingDataRef = NULL;
XPLMDataRef  gPitchDataRef = NULL;
XPLMDataRef  gRollDataRef = NULL;
XPLMDataRef  CofG_refx = NULL;
XPLMDataRef  CofG_refy = NULL;
XPLMDataRef  CofG_refz = NULL;

XPLMCommandRef ShowObjectCommand = NULL;
XPLMCommandRef HideObjectCommand = NULL;

int	ShowObjectCommandHandler(XPLMCommandRef   inCommand,    
                          XPLMCommandPhase      inPhase,    
                          void *                inRefcon);

int	HideObjectCommandHandler(XPLMCommandRef   inCommand,    
                          XPLMCommandPhase      inPhase,    
                          void *                inRefcon);


// Used by the Draw Objects test
XPLMObjectRef     gTestObject=NULL;


const float Pi = 3.14159265358979;
const float RadToDeg = 180.0 / Pi;
const float DegToRad = 1.0 / RadToDeg;


// Prototype for Draw Object tests
int     DrawTestObject(XPLMDrawingPhase     inPhase,    
                      int                  inIsBefore,    
                      void *               inRefcon);

PLUGIN_API int XPluginStart(
                            char *     outName,
                            char *     outSig,
                            char *     outDesc)
{
    // Plugin Info 
    strcpy(outName, "DrawTerrainObject");
    strcpy(outSig, "BlueSideUpBob.Example.DrawTerrainObject");
    strcpy(outDesc, "Draw, hide, and show a terrain object that moves along with aircraft.");

    // Create the test commands; these will Show/Hide the test object.
    ShowObjectCommand = XPLMCreateCommand("BSUB/ShowObject/TestObject", "Show TestObject");
    HideObjectCommand = XPLMCreateCommand("BSUB/HideObject/TestObject", "Hide TestObject");

    // Register our custom commands
    XPLMRegisterCommandHandler(ShowObjectCommand,          // in Command name
                           ShowObjectCommandHandler,       // in Handler
                           1,                              // Receive input before plugin windows.
                           (void *) 0);                    // inRefcon. 

    XPLMRegisterCommandHandler(HideObjectCommand,          // in Command name
                           HideObjectCommandHandler,       // in Handler
                           1,                              // Receive input before plugin windows.
                           (void *) 0);                    // inRefcon. 

    // Get the aicraft position
    CofG_refx = XPLMFindDataRef("sim/flightmodel/position/local_x");
    CofG_refy = XPLMFindDataRef("sim/flightmodel/position/local_y");
    CofG_refz = XPLMFindDataRef("sim/flightmodel/position/local_z");

    gHeadingDataRef = XPLMFindDataRef ("sim/flightmodel/position/psi");
    gRollDataRef = XPLMFindDataRef ("sim/flightmodel/position/phi");
    gPitchDataRef = XPLMFindDataRef ("sim/flightmodel/position/theta");

    // This used to draw the test object.
    XPLMRegisterDrawCallback( DrawTestObject, xplm_Phase_Objects, 0, 0 );
    return 1;
}


PLUGIN_API void	XPluginStop(void)
{
    XPLMUnregisterCommandHandler(ShowObjectCommand, ShowObjectCommandHandler, 0, 0);	
    XPLMUnregisterCommandHandler(HideObjectCommand, HideObjectCommandHandler, 0, 0);		
}


PLUGIN_API void XPluginDisable(void)
{
}


PLUGIN_API int XPluginEnable(void)
{
    return 1;
}


PLUGIN_API void XPluginReceiveMessage(
                                      XPLMPluginID   inFromWho,
                                      long           inMessage,
                                      void *         inParam)
{
}



int	ShowObjectCommandHandler( XPLMCommandRef     inCommand,    
                                XPLMCommandPhase   inPhase,    
                                void *             inRefcon)
{
    if (inPhase == 0)
       {	
             gTestObject = XPLMLoadObject("Aircraft/General Aviation/FP404Master/objects/TestObject.obj");
             if (gTestObject == NULL) 	
                {
                     sprintf(gBob_debstr,"Test Object not found, inPhase %d \n", inPhase);
                     XPLMDebugString(gBob_debstr);
                }
       }

    // Return 1 to pass the command to plugin windows and X-Plane.  
    // Returning 0 disables further processing by X-Plane.	 
    // In this case we might return 0 or 1 because X-Plane does not duplicate our command. 
    return 0;
}

int	HideObjectCommandHandler(  XPLMCommandRef     inCommand,    
                                 XPLMCommandPhase    inPhase,    
                                 void *              inRefcon)

{
       if (inPhase == 0)
       {
            // Unload the imported object
            XPLMUnloadObject(gTestObject);
       }

   return 0;
}


// Function for Draw Object tests
int	DrawTestObject( XPLMDrawingPhase inPhase,    
                      int              inIsBefore,    
                      void *           inRefcon)
{	 
    static float LongitudinalOffset = -20.0;
   static float VerticalOffset = 2.0;
   float AircraftHeading;

    // Draw the imported object.  Only do this if we have everything we need.
    if (gTestObject && CofG_refx && CofG_refy && CofG_refz)
    //Locate the test object by its heading.
    { 
           AircraftHeading = XPLMGetDataf(gHeadingDataRef);
 					
            if (AircraftHeading <= 90)
            {
                XPLMDrawInfo_t	locations[1] = { 0 };
                locations[0].structSize = sizeof(XPLMDrawInfo_t);
                locations[0].x = XPLMGetDatad(CofG_refx) - LongitudinalOffset * sin (AircraftHeading * DegToRad);
                locations[0].y = XPLMGetDatad(CofG_refy) + VerticalOffset;
                locations[0].z = XPLMGetDatad(CofG_refz) + LongitudinalOffset * cos (AircraftHeading * DegToRad);
                locations[0].pitch = XPLMGetDataf(gPitchDataRef);
                locations[0].heading = AircraftHeading;
                locations[0].roll = XPLMGetDataf(gRollDataRef);
                // Draw the object 
                XPLMDrawObjects(gTestObject, 1, locations, 0, 0);
 
               return 1;
           }
 
          if (AircraftHeading <= 180)
           {
                XPLMDrawInfo_t	locations[1] = { 0 };
                locations[0].structSize = sizeof(XPLMDrawInfo_t);
                locations[0].x = XPLMGetDatad(CofG_refx) - LongitudinalOffset * sin ((180 - AircraftHeading) * DegToRad);
                locations[0].y = XPLMGetDatad(CofG_refy) + VerticalOffset;
                locations[0].z = XPLMGetDatad(CofG_refz) - LongitudinalOffset * cos ((180 - AircraftHeading) * DegToRad);
                locations[0].pitch = XPLMGetDataf(gPitchDataRef);
                locations[0].heading = AircraftHeading;
                locations[0].roll = XPLMGetDataf(gRollDataRef);
                // Draw the object 
               XPLMDrawObjects(gTestObject, 1, locations, 0, 0);
 
               return 1;
            }

           if (AircraftHeading <= 270) 
           {
                XPLMDrawInfo_t	locations[1] = { 0 };
                locations[0].structSize = sizeof(XPLMDrawInfo_t);
                locations[0].x = XPLMGetDatad(CofG_refx) + LongitudinalOffset * cos ((270 - AircraftHeading) * DegToRad);
                locations[0].y = XPLMGetDatad(CofG_refy) + VerticalOffset;
                locations[0].z = XPLMGetDatad(CofG_refz) - LongitudinalOffset * sin ((270 - AircraftHeading) * DegToRad);
                locations[0].pitch = XPLMGetDataf(gPitchDataRef);
                locations[0].heading = AircraftHeading;
                locations[0].roll = XPLMGetDataf(gRollDataRef);
                // Draw the object 
               XPLMDrawObjects(gTestObject, 1, locations, 0, 0);
 
               return 1;
           }

          if (AircraftHeading <= 360) 
          {
                XPLMDrawInfo_t	locations[1] = { 0 };
                locations[0].structSize = sizeof(XPLMDrawInfo_t);
                locations[0].x = XPLMGetDatad(CofG_refx) + LongitudinalOffset * sin ((360 - AircraftHeading) * DegToRad);
                locations[0].y = XPLMGetDatad(CofG_refy) + VerticalOffset;
                locations[0].z = XPLMGetDatad(CofG_refz) + LongitudinalOffset * cos ((360 - AircraftHeading) * DegToRad);
                locations[0].pitch = XPLMGetDataf(gPitchDataRef);
                locations[0].heading = AircraftHeading;
                locations[0].roll = XPLMGetDataf(gRollDataRef);
                // Draw the object 
               XPLMDrawObjects(gTestObject, 1, locations, 0, 0);
 
               return 1;
            }
    }

    return 1;
}

4 comments on “Draw Terrain Object

  1. What happened to the source code? Looks like someone checked the HTML format converted version. What is shown on this page is the same that is downloaded in the .zip file.

  2. Wow @Laminar, it’s been 2 years since the last person asked a valid question about the broken source code in this example (HTML entities sneaked into the source code, for example & instead of & to mention one) with neither a response, nor a correction given.

    This example code which most people consider to be representative, does not even comply to your own recommendation of using instancing, and instead uses deprecated methods ( XPLMDrawObjects). As you may imagine, this will stop 99% of the people who are trying to learn something about development for this simulator.

Leave a Reply

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

Please do not report bugs in the blog comments.
Only bugs reported via the X-Plane Bug Reporter are tracked.