On screen text display in VR

SDK supports Prepar3D’s philosophy of an open development architecture and encourages third parties to bring new innovations with improved add-ons and training content.
Post Reply
MicMac44
Posts: 25
Joined: Fri Feb 15, 2019 5:48 pm

On screen text display in VR

Post by MicMac44 »

Has anyone found a way to display text on-screen that is viewable in VR similar to the SimDirector's "OnScreenText" Object? I know there are a few SimConnect_Text option but they don't seem to be viewable in VR nor can I control the offset.
User avatar
Kayla Dillon
Posts: 1316
Joined: Mon Aug 01, 2016 5:59 pm

Re: On screen text display in VR

Post by Kayla Dillon »

Hello,

You should be able to use the DrawText3D function in the PDK through the ObjectRenderer service.
https://www.prepar3d.com/SDKv4/sdk/pdk_ ... derer_v440

Regards,
Kayla
Prepar3D® Software Engineer
MicMac44
Posts: 25
Joined: Fri Feb 15, 2019 5:48 pm

Re: On screen text display in VR

Post by MicMac44 »

Kayla Kinzel wrote: Wed Mar 13, 2019 11:07 am Hello,

You should be able to use the DrawText3D function in the PDK through the ObjectRenderer service.
https://www.prepar3d.com/SDKv4/sdk/pdk_ ... derer_v440

Regards,
Kayla
Excellent! Thank you! I'm not familiar with the PDK so I'm working through it now. The idea is to grab the FCS targeting info and other weapon system info for easy display in VR. Can the PDK grab this info on the USER ship?
MicMac44
Posts: 25
Joined: Fri Feb 15, 2019 5:48 pm

Re: On screen text display in VR

Post by MicMac44 »

Is there an example of passing data from a SimConnect project to a PDK project? I have the text rendering but I have not been able to access the user's FCS target info nor any weapon info. I've seen a few posts mentioning you can use SimConnect_SetClientData and then have your PDK read in that client data. Is there an example of this?
Clifton Crane
Lockheed Martin
Posts: 1207
Joined: Tue Sep 25, 2012 2:34 pm

Re: On screen text display in VR

Post by Clifton Crane »

Hi MicMac,

A PDK plugin is capable of creating a SimConnect instance, however this shouldn't be necessary. You can use the PDK's ISimObjectManager and IBaseObject interfaces to get data from the user object.

You first need to QueryService the PDK to get the ISimObjectManager. Once you have the ISimObjectManager you can call GetUserObject to get the user's IBaseObject interface. Using the IBaseObject interface you can call GetProperty to get the FCS information.

If you search the SDK Samples solution for "GetUserObject", the TargetingPodSample would be a good sample to look at.
Clifton Crane
Prepar3D® Software Engineer Sr.
MicMac44
Posts: 25
Joined: Fri Feb 15, 2019 5:48 pm

Re: On screen text display in VR

Post by MicMac44 »

Clifton Crane wrote: Tue Mar 19, 2019 6:11 pm You first need to QueryService the PDK to get the ISimObjectManager. Once you have the ISimObjectManager you can call GetUserObject to get the user's IBaseObject interface. Using the IBaseObject interface you can call GetProperty to get the FCS information.
I should have responded earlier! I figured out how to access the FCS through the PDK. It's working perfectly.

I am still wondering how to send data. I have certain aircraft from another simulation being transmitted in DIS. I would like to grab the location of those DIS entities. My idea was to have a SimConnect plug-in grab that relevant information on certain DIS entities and then have the PDK grab that information from the SimConnect instance.

I am able to get the information in SimConnect, the only part I'm missing is being able to send it to my PDK.
MicMac44
Posts: 25
Joined: Fri Feb 15, 2019 5:48 pm

Re: On screen text display in VR

Post by MicMac44 »

Okay so I'm almost there!
I have the SimConnect instance up and running. Now I'm trying to create a block of data on the server that my clients can write to (sorry for the wall of text):
enum SIMCONNECT_CLIENT_DATA_DEFINITION_ID {
LASER_FIRING_DATA_ID,
};

enum DATA_REQUEST_ID
{
REQUEST_DATA,
};

void StartSimConnect() {
// Initialize Client
HRESULT hr;
hSimConnect = NULL;
if (SUCCEEDED(SimConnect_Open(&hSimConnect, "DISPlugin - SimConnectClient", NULL, 0, NULL, 0)))
{
printf("Connected to Prepar3D!");

double *testVar = new double(4.00);

SimConnect_AddToClientDataDefinition(hSimConnect, LASER_FIRING_DATA_ID, SIMCONNECT_CLIENTDATAOFFSET_AUTO, SIMCONNECT_CLIENTDATATYPE_FLOAT64);

SimConnect_MapClientDataNameToID(hSimConnect, "IsLaserFiring\0", ClientID);

SimConnect_CreateClientData(hSimConnect, ClientID, sizeof(testVar), SIMCONNECT_CREATE_CLIENT_DATA_FLAG_DEFAULT);

SimConnect_RequestClientData(hSimConnect, ClientID, REQUEST_DATA, LASER_FIRING_DATA_ID, SIMCONNECT_CLIENT_DATA_PERIOD_ON_SET, SIMCONNECT_CLIENT_DATA_REQUEST_FLAG_CHANGED);

SimConnect_SetClientData(hSimConnect, ClientID, LASER_FIRING_DATA_ID, NULL, 0, sizeof(testVar), (void*)&testVar);
}
}

extern "C" __declspec(dllexport) void __stdcall DLLStart(__in __notnull IPdk* pPdk) {
PdkServices::Init(pPdk);
StartSimConnect();
}

extern "C" __declspec(dllexport) void __stdcall DLLStop(void)
{
PdkServices::Shutdown();
}
When I process my 'SIMCONNECT_RECV_CLIENT_DATA' in 'MyDispatchProc' (the CALLBACK) I am not being returned the value of *testVar. I believe the issue is coming from the last parameter in "SimConnect_SetClientData()" since it wants a pointer to the block of client data.

Does this relate to SIMCONNECT_CLIENTDATAOFFSET_AUTO when I called "SimConnect_AddToClientDataDefinition()"?
How do I point to the create block of client data?
Clifton Crane
Lockheed Martin
Posts: 1207
Joined: Tue Sep 25, 2012 2:34 pm

Re: On screen text display in VR

Post by Clifton Crane »

Hi MicMac44,

Do you receive any SimConnect exceptions? When you say you aren't being returned the value of *testVar, do you mean the value is returned but incorrect?

One thing to point out is that you are calling sizeof(testVar), this will return the size of a pointer. In this case, both the pointer and double are 8 bytes, but this will be wrong if you attempted to use a struct. To correctly get the size, you would need to dereference the pointer in the sizeof call:
MyStruct* p = new MyStruct();
unsigned int cbBytes = sizeof(*p);
Clifton Crane
Prepar3D® Software Engineer Sr.
MicMac44
Posts: 25
Joined: Fri Feb 15, 2019 5:48 pm

Re: On screen text display in VR

Post by MicMac44 »

Clifton,

Thank you for the tip! I will be moving to more complicated data types but I wanted to start with something simpler. I guess I got lucky on that!

Here's the callback code that waits for changes in the block data:
case SIMCONNECT_RECV_ID_CLIENT_DATA:
{
SIMCONNECT_RECV_CLIENT_DATA *pObjData = (SIMCONNECT_RECV_CLIENT_DATA*)pData;

switch (pObjData->dwRequestID)
{
case REQUEST_DATA:
printf("\nData request returned: %f\n", pObjData->dwData);
break;

default:
printf("Default data request returned: %ld\n", pObjData->dwData);
break;
}
break;
}
So my understanding is if I call SimConnect_SetClientData() and pass in a double, when my REQUEST_DATA is called I should be able to grab the double that was set with SimConnect_SetClientData(). I get no SimConnect exceptions but when I display dwData it is "0.000000".

I'm very new to C++ so I'm thinking this could be that I'm not accessing/casting the data correctly.
Clifton Crane
Lockheed Martin
Posts: 1207
Joined: Tue Sep 25, 2012 2:34 pm

Re: On screen text display in VR

Post by Clifton Crane »

You could try casting the variable in your printf to double* and then dereference it:
case REQUEST_DATA:
printf("\nData request returned: %f\n", *(double*)pObjData->dwData);
break;
Clifton Crane
Prepar3D® Software Engineer Sr.
MicMac44
Posts: 25
Joined: Fri Feb 15, 2019 5:48 pm

Re: On screen text display in VR

Post by MicMac44 »

Thank you! That worked!

I did have to change it just a little to:
case REQUEST_DATA:
printf("\nData request returned: %f\n", *(double*)&pObjData->dwData);
break;
MicMac44
Posts: 25
Joined: Fri Feb 15, 2019 5:48 pm

Re: On screen text display in VR

Post by MicMac44 »

How does the SetClientData change when the data is a struct (composed of doubles) instead of a double? I'm not getting my callback to fire when I change a piece of my struct and then SetClientData.

I looked at the TaggedData.cpp but I don't think a struct will act in the same way as the enums do after calling AddDataToDefinition.

I'll keep messing with it and post an update when I figure it out.
JB3DG
Posts: 609
Joined: Mon Jan 09, 2012 6:44 pm

Re: On screen text display in VR

Post by JB3DG »

The size will be the same of the total number of doubles in the struct. Eg a struct composed of only one double will have the same size as a straight double.

When using sizeof with a struct, I would use the struct's name definition, rather than your instance of the struct as the parameter for sizeof.
Jonathan Bleeker
Milviz systems dev

Formerly known as Naruto-kun
MicMac44
Posts: 25
Joined: Fri Feb 15, 2019 5:48 pm

Re: On screen text display in VR

Post by MicMac44 »

I've figured out the sizing and it seems to be working (returning a size of 24 for my 3 doubles, thank you JB3DG and Clifton). My issue is pulling the information out in the MyDispatchProc. I'm not getting newStruct->Lon or newStruct->Alt to return the numbers I set for them before the SimConnect_SetClientData call, all I get is 0.000000.

Again, I'm thinking the issue lies with how I'm passing the struct into SimConnect_SetClientData or how I am extracting the data in the REQUEST_STRUCT case. I'm still playing around with the proper way to pass the struct, I'll figure it out eventually!
DWORD ClientIDStruct = 9999;

struct laserTargetLLA{
double Lat;
double Lon;
double Alt;
};

void CALLBACK MyDispatchProc(SIMCONNECT_RECV* pData, DWORD cbData, void *pContext)
{
HRESULT hr;

switch (pData->dwID)
{
case SIMCONNECT_RECV_ID_CLIENT_DATA:
{
SIMCONNECT_RECV_CLIENT_DATA *pObjData = (SIMCONNECT_RECV_CLIENT_DATA*)pData;
//double *returnVar = *(double*)pObjData->dwData;
switch (pObjData->dwRequestID)
{

case REQUEST_STRUCT:
{
laserTargetLLA *pS = (laserTargetLLA*)&pObjData->dwData;
printf("pObjData->dwDefineCount: %i\n",pObjData->dwDefineCount);
printf("IN CALLBACK-> Lat: %f Lon: %f Alt: %f\n", pS->Lat, pS->Lon, pS->Alt);


break;
}
}
}
}
}

void StartSimConnect()
{
// Initialize Client
HRESULT hr;
hSimConnect = NULL;
if (SUCCEEDED(SimConnect_Open(&hSimConnect, "DISPlugin - SimConnectClient", NULL, 0, NULL, 0)))
{
laserTargetLLA* newStruct = new laserTargetLLA();
unsigned int cbBytesStruct = sizeof(laserTargetLLA);
newStruct->Lon = 200.214;
newStruct->Lat = 20.1;
newStruct->Alt = 1240.1235;
printf("BEFORE CALLBACK:: Lat: %f, Lon: %f, Alt: %f\n", newStruct->Lat, newStruct->Lon, newStruct->Alt);
SimConnect_SetClientData(hSimConnect, ClientIDStruct, LASER_FIRING_DATA_ID2, NULL, 0, cbBytesStruct, (void*)newStruct);
}
}
MicMac44
Posts: 25
Joined: Fri Feb 15, 2019 5:48 pm

Re: On screen text display in VR

Post by MicMac44 »

Okay I figured it out. Didn't copy all my code so the error wasn't easily available. I was using the wrong SIMCONNECT_CLIENT_DATA_DEFINITION_ID in my SimConnect_RequestClientData call. The corrected code if anyone cares:
MicMac44 wrote: DWORD ClientIDStruct = 9999;

enum DATA_DEFINE_ID {
LASER_FIRING_DATA_ID2,
};

enum DATA_REQUEST_ID
{
REQUEST_STRUCT,
};
struct laserTargetLLA{
double Lat;
double Lon;
double Alt;
};

void CALLBACK MyDispatchProc(SIMCONNECT_RECV* pData, DWORD cbData, void *pContext)
{
HRESULT hr;

switch (pData->dwID)
{
case SIMCONNECT_RECV_ID_CLIENT_DATA:
{
SIMCONNECT_RECV_CLIENT_DATA *pObjData = (SIMCONNECT_RECV_CLIENT_DATA*)pData;
switch (pObjData->dwRequestID)
{

case REQUEST_STRUCT:
{
laserTargetLLA *pS = (laserTargetLLA*)&pObjData->dwData;
printf("IN CALLBACK-> Lat: %f Lon: %f Alt: %f\n", pS->Lat, pS->Lon, pS->Alt);

break;
}
}
}
}
}

void StartSimConnect()
{
// Initialize Client
HRESULT hr;
hSimConnect = NULL;
if (SUCCEEDED(SimConnect_Open(&hSimConnect, "DISPlugin - SimConnectClient", NULL, 0, NULL, 0)))
{
laserTargetLLA* newStruct = new laserTargetLLA();
unsigned int cbBytesStruct = sizeof(laserTargetLLA);

SimConnect_AddToClientDataDefinition(hSimConnect, LASER_FIRING_DATA_ID2, SIMCONNECT_CLIENTDATAOFFSET_AUTO, cbBytesStruct);
SimConnect_MapClientDataNameToID(hSimConnect, "StructData\0", ClientIDStruct);
SimConnect_CreateClientData(hSimConnect, ClientIDStruct, cbBytesStruct, SIMCONNECT_CREATE_CLIENT_DATA_FLAG_DEFAULT);
SimConnect_RequestClientData(hSimConnect, ClientIDStruct, REQUEST_STRUCT, LASER_FIRING_DATA_ID2, SIMCONNECT_CLIENT_DATA_PERIOD_ON_SET, SIMCONNECT_CLIENT_DATA_REQUEST_FLAG_CHANGED);

newStruct->Lat = 200.214;
newStruct->Lon = 20.1;
newStruct->Alt = 1240.1235;
printf("BEFORE CALLBACK:: Lat: %f, Lon: %f, Alt: %f\n", newStruct->Lat, newStruct->Lon, newStruct->Alt);
SimConnect_SetClientData(hSimConnect, ClientIDStruct, LASER_FIRING_DATA_ID2, NULL, 0, cbBytesStruct, (void*)newStruct);
}
}
Post Reply