2016-08-24 2 views
0

Je suis nouveau ici et pas si familier avec la programmation d'affichage. J'ai un c-programme qui appelle une fonction doStep toutes les 40ms. Dans cette fonction j'ai le code C++, qui exécute un affichage de surabondance pour visualiser un environnement 3D. La fonction doStep transmet de l'extérieur les nouvelles informations de position de mes objets 3D dans mon environnement C++ 3D.Comment appeler une fonction c externe, alors qu'une boucle d'affichage GLUT verrouille ma ligne C++?

Le problème est, que mon code-c est verrouillé par la boucle d'affichage de l'encombrement, de sorte que je ne peux plus mettre à jour les positions dans l'environnement. Devrais-je utiliser un thread séparé pour la boucle d'affichage pour résoudre ce problème? Je sais que glutPostRedisplay() peut être utilisé pour redessiner ma scène, mais je ne sais pas comment séparer ma boucle d'affichage pour garder le contrôle de la fonction doStep.

Merci à l'avance


Ok depuis mon poste était peu clair et sans code, je vais essayer de préciser la question. J'utilise Nvidia OptiX Raytracing pour rendre une scène. La sortie visuelle est créée par une classe GLUTDisplay en C++. J'ai créé un fil séparé pour mon affichage et l'ai détaché, de sorte que j'ai plus de contrôle sur le programme. Je sais que l'on peut partager une classe entre les threads, donc il m'est possible de créer un thread séparé pour l'affichage et d'appeler GLUTDisplay::postRedisplay(); dans mon autre thread pour mettre à jour le contexte. Pour exécuter mon programme que j'utilise 3 c-fonctions:

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); 

} 

Voici ma mise en œuvre d'entre eux:

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); 
    } 
} 

Au début, j'appelle create() une fois, puis toutes les 40 ms j'appelle trace() de mettre à jour ma scène. Est-ce une implémentation de thread sûre pour la boucle dislay? Après un certain temps à exécuter mon programme, ma scène ne se mettra plus à jour. Seulement si je déplace ma souris sur la fenêtre, la scène est mise à jour. Est-ce causé par mon implémentation de threads?

+6

'j'ai un c-programme ... Dans cette fonction, j'ai C++ Qu'est-ce recueil HSC? – Caw

+0

Peut-être que vous pourriez commencer votre propre fil avant que la surabondance entre dans sa boucle. – byxor

+1

Votre message n'est pas clair. Vous devriez le modifier et montrer du code – wasthishelpful

Répondre

1

Pour mélanger le code C avec le code C++, utilisez le mot-clé extern.

extern "C"{ 
    void externalDoStep() { 

    // your algorithm here 

    } 
} 

Toutefois, lorsque vous dites que votre fonction est bloquée, je pense que vous devriez faire ceci:

Essayez de brancher votre fonction doStep() dans cette fonction de rappel GLUT juste pour voir ..

glutIdleFunc(doStep);

ou toute autre fonction de rappel GLUT.

Si vous ne mettez pas vos fonctions dans une fonction de rappel GLUT, votre fonction ne sera pas exécutée par GLUT.

La principale partie de GLUT est le callbacks. Ce sont des fonctions qui gèrent les événements GLUT générés lorsque vous modifiez la taille de la fenêtre ou appuyez sur une touche.

Cela fonctionne comme ceci. Vous créez vos propres fonctions et branchez ces fonctions dans ces fonctions de rappel GLUT principales.Ils doivent être dans le main()

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

liste complet Code:

#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; 
} 
+0

Merci beaucoup pour cette explication détaillée! J'aurais dû mentionner que j'utilise déjà external pour mixer mes codes c et C++. Si je branche la fonction doStep dans le rappel inactif, il ne serait pas appelé toutes les 40 ms depuis mon c-main() mais plus fréquemment. Le programme est un peu plus complexe, je vais essayer de vous donner un pseudo code demain, quand j'aurai accès à mon code. –