C++ Question Communication between 2 VESSEL3 derived classes

dumbo2007

Crazy about real time sims
Joined
Nov 29, 2009
Messages
675
Reaction score
0
Points
0
Location
India
Ok..fresh challenge. I have got 2 VESSEL3 derived classes.One is supposed to represent a base and is called BulletBase, another a vehicle(BulletBaseVehicle). The vehicle's position is controlled by the base through DefSetState().

I need the vehicle to be able to send values to the bases. So when the vehicle object is instantiated then I get a VESSEL pointer to the base by searching the list of objects in the scene(in clbkSetClasCaps()). After I obtain a pointer to the base VESSEL I cast it to the BulletBase type.

Now if the vehicle vessel has focus and the user presses the up key then I update a static variable in the base class BulletBase (derived from VESSEL3).

Here is the header code for BulletBase : BulletBase.h:
Code:
#ifndef BULLETBASE_H
#define BULLETBASE_H

#include "orbitersdk.h"

class BulletBase: public VESSEL3 {

    VESSEL * hBase;
    BulletBase *bb;
    char output[100];
    

public:
    BulletBase (OBJHANDLE hVessel, int flightmodel)
        : VESSEL3 (hVessel, flightmodel) {}
    void    clbkSetClassCaps (FILEHANDLE cfg);
    void    clbkPreStep(double SimT, double SimDT, double MJD);    
    
    static int k;
};

#endif //BULLETBASE_H
And the definitions in BulletBase.cpp
Code:
// ==============================================================
//                 ORBITER MODULE: BulletBase
//                  Part of the ORBITER SDK
//          Copyright (C) 2002-2004 Martin Schweiger
//                   All rights reserved
//
// BulletBase.cpp
// Control module for BulletBase vessel class
//
// Notes:
// This is an example for a "minimal" vessel implementation which
// only overloads the clbkSetClassCaps method to define vessel
// capabilities and otherwise uses the default VESSEL class
// behaviour.
// ==============================================================

#define STRICT
#define ORBITER_MODULE

#include "BulletBase.h"


// --------------------------------------------------------------
// Set the capabilities of the vessel class
// --------------------------------------------------------------
void BulletBase::clbkSetClassCaps (FILEHANDLE cfg)
{
    // physical specs
    SetSize (1.2);
    SetClipRadius(0.5);     
    SetPMI (_V(0.61,0.01,0.62));
    SetEmptyMass(100);    
    SetTouchdownPoints( _V(-0.1, 0, -0.07), _V(0.1, 0, -0.07), _V(0.0, 0, 0.170) );

    VECTOR3 ofs = _V(0,0,0);    
    AddMesh("Ferrari",&ofs); 
    

    sprintf(output, "BulletBase: clbkSetClassCaps called");
    oapiWriteLog(output);

}

// --------------------------------------------------------------
// Vessel initialisation
// --------------------------------------------------------------
DLLCLBK VESSEL *ovcInit (OBJHANDLE hvessel, int flightmodel)
{
    return new BulletBase (hvessel, flightmodel);
}

// --------------------------------------------------------------
// Vessel cleanup
// --------------------------------------------------------------
DLLCLBK void ovcExit (VESSEL *vessel)
{
    if (vessel) delete (BulletBase*)vessel;
    oapiWriteLog("BulletBase: ovcExit called");
}


int BulletBase::k;
void BulletBase::clbkPreStep(double SimT, double SimDT, double MJD) 
{
    unsigned int i;
    sprintf(oapiDebugString(),"k = %d", BulletBase::k );
    

}
Here is the code for BulletBaseVehicle : BulletBaseVehicle.cpp :
Code:
#define STRICT
#define ORBITER_MODULE

#include "orbitersdk.h"
#include "BulletBase.h"


// ==============================================================
// BulletBaseVehicle class interface
// ==============================================================

int BulletBase::k;

class BulletBaseVehicle: public VESSEL3 {

    //All below properties must be made virtual later: they shud be set by derived class-------------
    char baseName[20];

    VESSEL * hBase;
    BulletBase *bb;
    char name[20];
    //------------------------------------------------------------
    char output[1000];
    bool vesselInited;

public:
    BulletBaseVehicle (OBJHANDLE hVessel, int flightmodel)
        : VESSEL3 (hVessel, flightmodel) {}
    void    clbkSetClassCaps (FILEHANDLE cfg);
    void    clbkPreStep(double SimT, double SimDT, double MJD);
    int        clbkConsumeBufferedKey(DWORD key, bool down, char *kstate);        
};

// ==============================================================
// Overloaded callback functions
// ==============================================================

// --------------------------------------------------------------
// Set the capabilities of the vessel class
// --------------------------------------------------------------
void BulletBaseVehicle::clbkSetClassCaps (FILEHANDLE cfg)
{
    // physical specs
    SetSize (1.2);
    SetClipRadius(0.5);     
    SetPMI (_V(0.61,0.01,0.62));
    SetEmptyMass(100);    
    SetTouchdownPoints( _V(-0.1, 0, -0.07), _V(0.1, 0, -0.07), _V(0.0, 0, 0.170) );

    VECTOR3 ofs = _V(0,0,0);
    strcpy(name, GetName());    
    AddMesh(name,&ofs);   //car mesh of same name as vessel name in scenario
    

    //Car specs here
    strcpy(baseName, "Brighton2");     //this is imp
    vesselInited = false;

}

// --------------------------------------------------------------
// Vessel initialisation
// --------------------------------------------------------------
DLLCLBK VESSEL *ovcInit (OBJHANDLE hvessel, int flightmodel)
{
    return new BulletBaseVehicle (hvessel, flightmodel);
}

// --------------------------------------------------------------
// Vessel cleanup
// --------------------------------------------------------------
DLLCLBK void ovcExit (VESSEL *vessel)
{
    if (vessel) delete (BulletBaseVehicle*)vessel;
    oapiWriteLog("BulletBaseVehicle: ovcExit called for all cars");
}


void BulletBaseVehicle::clbkPreStep(double SimT, double SimDT, double MJD) 
{
    unsigned int i;
    
    //Find and store the base pointers to vehicle data
    if(vesselInited == false){
        unsigned int numObj = oapiGetVesselCount();
        OBJHANDLE *hObj = new OBJHANDLE[numObj];        
        char strObj[20]; 
        
        for (i = 0; i < numObj; i++) {
            hObj[i] = oapiGetVesselByIndex(i);        
            oapiGetObjectName(hObj[i], strObj, 20);

            if(strcmp(strObj, baseName) == 0){
                hBase = oapiGetVesselInterface(hObj[i]);
                bb = (BulletBase*) hBase;                    
                break;
            }
                
        }
        vesselInited = true;
    }

}


int BulletBaseVehicle::clbkConsumeBufferedKey(DWORD key, bool down, char *kstate) {
    
    //if(strcmp(name, "Ferrari") == 0)
    //    sprintf(oapiDebugString(),"Function called : %f, %f, %d", *ptrEngineForce, *ptrBreakingForce, BulletBase::k );
    
    if (down){    //key is pressed
        if (KEYMOD_SHIFT (kstate)) { //Shift key has also been pressed

        } 
        else {
            switch (key) {            
                case OAPI_KEY_UP:
                    //*ptrEngineForce = maxEngineForce;
                    /*bb->setEngineForce(maxEngineForce);*/
                    //*ptrBreakingForce = 0.f;
                    bb->k = 2;
                    return 1;

            }
        }
    }

    return 0;
}

Well it does not work. I dont see the value of k changing when I print it in BulletBase even though the value should have arrived there as the static variable is common for all objects in the class. I do see it changing when I print bb->k in BulletBaseVehicle.

Does each VESSEL3 have its own copy of static variables ? Is there any other way I can pass information between 2 VESSEL3 derived classes ?

Thanks
 
Last edited:
almost correct: Each DLL has its own set of static variables. Even worse. A DLL can even have multiple sets of static variables, one per instance of the DLL (one DLL linked by different processes).

So, if you set k in one DLL, the other must not be aware of it in it own context.

Better use clbkGeneric or object variables for such data exchanges.
 
One way to do it is to use shared memory to communicate between DLL instances. Details here: Using Shared Memory in a Dynamic-Link Library.

Wouldn't help in this case, since the variable is defined in two different DLLs... but generally this is a good knowledge for any module developer anyway (For example for loading some data only once). Thank you for posting it.
 
Yes I do use shared memory but between 2 different applications. The Bullet physics engine which simulates a car runs in a separate physics thread which is started by the Base Vessel class when its loaded. This physics thread sends physics world transformations of the various objects to a shared memory file during each iteration. This can then be read by a separate viewer OpenGL application to enable me to see whats happening in the physics world at the same time. Works quite smoothly and in real time too.
 
Back
Top