0
votes

I'm new here and not so familiar with display programming. I have a c-Program that calls a doStep-function every 40ms. Within this function I have C++ Code, which runs a glut display to visualize a 3D-environment. The doStep function passes new position information of my 3D Objects from outside into my C++ 3D-environment.

The problem is, that my c-code gets locked by the glut display loop, so that I can't update the positions in the environment any more. Should I use a seperate thread for the display loop for solving this issue? I know that glutPostRedisplay() can be used to redraw my scene, but I don't know how to separate my display loop to maintain control of the doStep function.

Thanks in advance


Ok since my post was unclear and without code, I will try to specify the issue. I'm using Nvidia OptiX Raytracing for rendering a scene. The visual output is created by a GLUTDisplay class in C++. I created a separate thread for my display and detached it, so that I have further control of the program. I know that one can share a class between threads, so it was possible for me to create a separate thread for the display and calling GLUTDisplay::postRedisplay(); in my other thread to update the context. To run my program I use 3 c-functions:

extern "C" {

extern void* create(const char* filename, double* inputArray, double* outputArray, int argc, char** argv);
extern void  trace(void* scene_obj);
extern void  exitScene(void* scene_obj);

}

Here's my implementation of them:

void * create( const char* filename, double* inputArray, double* outputArray, int argc, char** argv ){
    OptixScene* scene = new OptixScene(filename);
    scene->routeInput(inputArray);       //routing my inputs and outputs
    scene->routeOutput(outputArray);     //from a simulation model

    std::thread display_thread(&OptixScene::createDisplayThread, scene, argc, argv); // this starts the display loop
    display_thread.detach();    // detach display thread to get control back

    return (void *)scene;
}

void trace( void* scene_obj ){
    OptixScene* scene = static_cast<OptixScene*> (scene_obj);
    scene->readInputs();
    scene->updateMatrix();
    scene->renderImage();      // GLUTDisplay::postRedisplay() in here
    scene->writeOutputs();
}

void exitScene(void* scene_obj){
    OptixScene* scene = static_cast<OptixScene*> (sensor);
    try{
        scene->cleanUp();
        if (scene->getContext().get() != 0)
              {
                sutilReportError( "Scene class failed to clean up!" );
                exit(2);
              }
        exit(0);
    }
    catch( Exception& e ){
        sutilReportError( e.getErrorString().c_str() );
        exit(2);
    } 
}

At the beginning I call create() once and then every 40ms I call trace() to update my scene. Is this a safe thread implementation for the dislay loop? After a while running my progam, my scene won't update itself anymore. Only if I'm moving my mouse over the window, the scene gets updated. Is this caused by my thread implementation?

1
I have a c-Program ... Within this function I have C++ Code What? - flau
Maybe you could start your own thread before glut gets into its loop. - byxor
Your post is unclear. You should edit it and show some code - rgmt
Sorry if my explainations aren't so clear. I started programming with c++ not so long ago. I will show some pseudo code tomorrow when I have access to my program again. - Michael O

1 Answers

1
votes

To mix C code with C++ code, use the extern keyword.

extern "C"{
   void externalDoStep() {

    // your algorithm here

   }   
}

However when you say that your function is being blocked, i think you should do this:

Try plugging your doStep() function into this GLUT callback function just to see..

glutIdleFunc( doStep );

or any other GLUT callback function.

If you dont put your functions in a GLUT callback function, your function will not be run by GLUT.

The main important part of GLUT are the callbacks. These are functions that will handle the GLUT events generated when you change the size of the window or press a key.

It works like this. You create your own functions and plug those function into these main GLUT callback functions. They must be in the main()

   glutReshapeFunc(your reshape function);
   glutDisplayFunc(your display function);
   glutIdleFunc(your idle function);
   glutKeyboardFunc(your keyboard function);

Full Code listing:

#include <windows.h>
#include <string.h>
#include <GL\glut.h>
#include <iostream.h>
#include <fstream.h>

#pragma comment(lib, "glu32.lib")

int ii=0;
int iex=0;

extern "C"{
   void externalDoStep() {

    // your algorithm here
       iex++;
       cout<<iex<<" externalDoStep \n";
   }   
}

void doStep (void){
    // your algorithm here
  ii++;
  cout<<ii<<" doStep () is running \n";
  glutPostRedisplay();
}

void RenderToDisplay(){
    // your algorithm here   
}

void myDisplayFunction(void){
    // your algorithm here     
}

void myReshapeFunction(int w, int h){
    // your algorithm here
}

int main(){

    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
    glutInitWindowSize(800, 400);
    glutCreateWindow("dostep");
    glClearColor(0.0, 0.0, 0.0, 1.0);
    glLineWidth(3);

    glutDisplayFunc( myDisplayFunction );
    glutReshapeFunc( myReshapeFunction );
    glutIdleFunc( doStep );
    glutMainLoop();

    return 0;
}