0

I rendered a scene having earth and a satellite. The position of the satellite is collected and updated by a thread. The position data is provided by an background calculation program.

// main.cpp
void CollectCraft(void)
{
    SetupChannel();
    int iFlag = 1;
    while(iFlag > 0)
    {
        iFlag = CollectData();
        Sleep(10);
    }
    CloseChannel();
}

int main(void)
{
    CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)CollectCraft, 0, NULL, NULL); // in collect.cpp
    RenderMainWindow(); // in render.cpp
    return 1;
}

The CollectCraft function receives data from a background program. Once it receives any data, it stores in a double

// collect.cpp
double Craft_R[3] = {0.0};
...
int CollectData(void)
{
    char chrMessage[255] = {0};
    int iFlag = CollectSocket(&sListen, &sServer, chrMessage);
    if (iFlag <= 0) return iFlag;
    else
    {
        unsigned char i = 0, j = 0;
        unsigned short usLength = 0;
        for ( i = 0; i < dimCraft; i++)
        {
            for (j=0; j<3; j++)
            {
                memcpy(&Craft_R[j], &chrMessage[usLength], 8);
                usLength += 8;
            }
        }
    }
    return iFlag;
}

I fixed my camera on one of the satellite (following it and staring at it). It updates its position and the view matrix according to the position of the satellite.

The satellite updated it's position according to the latest received data (I simply get it through a extern double Craft_R).

// render.cpp
extern double Craft_R[3]; // directly get latest satellite position data
...
RenderMainWindow()
{
    ...
    while (!glfwWindowShouldClose(MainWindow))
    {
        glm::dmat4 view = camera.GetViewMatrix();
        ...
        Sate1Pos = glm::dvec3(Craft_R[0], Craft_R[1], Craft_R[2]); // update satellite position
        glm::dmat4 model_sate1(1.0);
        model_sate1 = glm::translate(model_sate1, Sate1Pos);
        ...
        switch (CameraPosID)
        {
        case 0:
            camera.Focus(EarthPos);
            break;
        case 1:
            camera.Focus(Sate1Pos); // update camera position
        }
        glfwSwapBuffers(MainWindow);
        glfwPollEvents();
    }
}

The problem is, the collection of the latest satellite position data always happens BETWEEN the update of the camera position and the update of the satellite position. It means my satellite flies to the latest position but my camera still stays at the last position. After glfwSwapBuffers(), the next while (!glfwWindowShouldClose(MainWindow)) will render the satellite far away out of the field of view of the camera. And it will last until the next while for the camera to update its position and get the satellite back to its field of view.

If the background program keeps sending the satellite position, the scene will render as if the satellite is blinking. And if the background program stops sending the satellite position, everything is ok and stable. If I control the background program to send the satellite position once, the satellite in the scene will blink one time and then remains stable.

My question is if there is a way to simultaneously update position of the camera and the satellite? Many thanks and sorry for my poor English since it is not my mother tongue.

abmin
  • 133
  • 2
  • 12
  • you should render all the objects of the scene in the same simulation time... Camera is also an object (represented by a matrix). Multithreading might look as a good idea at start but OpenGL API is not MultiThreaded and you need to render from single thread or switch contexts and that is not stable on some cards like Intel... So either synchronize simulation and rendering or use buffering (you know have a 2 copy of scene one is used to compute next time stamp and the other for rendering once rendered and fully computed swap them ...) and by copy I mean transform matrix ... – Spektre May 29 '20 at 14:27
  • @Spektre Thanks. I got much from your answer. I've partly solved it by adding `glfwSwapInterval(5);` before `while`. I know this is not a good method but anyway it effectively eliminate the blinking. – abmin May 29 '20 at 14:58
  • You can also use `glFinish()` ... but I would do some CPU work or `Sleep()` before that so you do not waste CPU time while waiting on GPU. – Spektre May 29 '20 at 15:00

0 Answers0