GLUT (OpenGL Utility Toolkit) in eine Klasse
-
Hallo zusammen,
ich habe eine Klasse geschrieben, die die notwendigen Anweisungen von GLUT enthalten, um 3D-Graphiken in ein Fenster darzustellen. Da die Ereignis-Funktionen aus der GLUT-Bibliothek keine Klassen kennen, musste ich einen Umweg gehen und die Ereignis-Funktionen als statisch definieren. Das Problem war, dass ich unbedingt ein This-Zeiger brauchte, um auf die Aktuelle Position des Spielers zuzugreifen, deshalb habe ich mich entschlossen in der Klasse ein Objekt von der Klasse selbst zu erstellen. Ich dann alles so geschrieben, wie ich es mir überlegt habe, und es hat auch funktioniert.
Ich habe aber irgendwie ein ethisches Gefühl, zur meine Klasse, dass irgendetwas noch fehlt. Den die Klasse selbst noch mal in der Klasse zu definieren ist schon ein wenig verwirrend.
Ich wollte euch deshalb fragen, was ihr über die folgende Klasse denkt. Hier ist mein C++-Quelltext:
//////////////////////////////////////////////////////////////////////////////// /// Die srWindow-Schablone //////////////////////////////////////////////////////////////////////////////// #ifndef _srWindow_h_ #define _srWindow_h_ #include <cmath> #include <GL/freeglut.h> #include <unistd.h> #include "graphics.h" class srWindow { private: const float piover180; bool axis; bool game; bool mesh; bool motion; float posX; float posY; float rotateX; float rotateY; float translateX; float translateY; float translateZ; float walk; int window; void DrawScene(); void InitOpenGL(int width, int height); void MoveBackwards(); void MoveForward(); void MoveLeft(); void MoveRight(); void RotateDown(); void RotateLeft(); void RotateRight(); void RotateUp(); static srWindow *srInstance; static void KeyPress(unsigned char key, int x, int y); static void Mouse(int button, int state, int x, int y); static void MouseMotion(int x, int y); static void Navigate(int key, int x, int y); static void Render(); static void Resize(int width, int height); srGraphics *srGraphic; public: srWindow(const std::string &stdpath); ~srWindow(); enum { srROTATE_X, srROTATE_Y, srTRANSLATE_X, srTRANSLATE_Y, srTRANSLATE_Z, srAXIS, srGAME, srMESH, srHIDE_AXIS_MODE, srHIDE_GAME_MODE, srHIDE_MESH_MODE, srSHOW_AXIS_MODE, srSHOW_GAME_MODE, srSHOW_MESH_MODE }; bool IsShow(int code); float GetValue(int code); void Show(); void SwitchMode(int code); }; #endif//////////////////////////////////////////////////////////////////////////////// /// Die srWindow-Implementierung //////////////////////////////////////////////////////////////////////////////// #include "window.h" int main(int argc, char **argv) { //////////////////////////////////////////////////////////////////////////////// /// Das Grundgerüst //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////// std::string stdpath = get_current_dir_name(); unsigned int end = stdpath.find("/bin"); stdpath = stdpath.substr(0, end); srWindow* openGL = new srWindow(stdpath); openGL->Show(); delete openGL; return 0; //////////////////////////////////////// } srWindow* srWindow::srInstance = NULL; srWindow::srWindow(const std::string &stdpath) : piover180(0.0174532925f), axis(false), game(true), mesh(false), motion(false), posX(0.0f), posY(0.0f), rotateX(0.0f), rotateY(0.0f), translateX(0.0f), translateY(-0.25f), translateZ(-2.2f), walk(0.0f) { //////////////////////////////////////////////////////////////////////////////// /// Die Konfiguration //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////// int argc = 1; char *argv[] = {const_cast<char*>("opengl")}; this->srInstance = this; this->srGraphic = new srGraphics(stdpath); glutInit(&argc, argv); glutInitDisplayMode(GLUT_ALPHA|GLUT_RGBA|GLUT_DEPTH|GLUT_DOUBLE|GLUT_STENCIL); glutInitWindowPosition(0, 0); glutInitWindowSize(800, 600); this->window = glutCreateWindow("OpenGL"); glutDisplayFunc(&this->Render); glutIdleFunc(&this->Render); glutKeyboardFunc(&this->KeyPress); glutMouseFunc(&this->Mouse); glutMotionFunc(&this->MouseMotion); glutReshapeFunc(&this->Resize); glutSpecialFunc(&this->Navigate); this->InitOpenGL(800, 600); //////////////////////////////////////// } srWindow::~srWindow() { //////////////////////////////////////////////////////////////////////////////// /// Die Aufräumarbeiten //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////// delete this->srInstance; delete this->srGraphic; //////////////////////////////////////// } bool srWindow::IsShow(int code) { //////////////////////////////////////////////////////////////////////////////// /// Den Anzeigemouds überprüfen //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////// switch(code) { case srAXIS: return this->axis; case srGAME: return this->game; case srMESH: return this->mesh; default: return false; } //////////////////////////////////////// } float srWindow::GetValue(int code) { //////////////////////////////////////////////////////////////////////////////// /// Der Wert-Akzessor //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////// switch(code) { case srROTATE_X: return this->rotateX; case srROTATE_Y: return this->rotateY; case srTRANSLATE_X: return this->translateX; case srTRANSLATE_Y: return this->translateY; case srTRANSLATE_Z: return this->translateZ; default: return 0.0f; } //////////////////////////////////////// } void srWindow::DrawScene() { //////////////////////////////////////////////////////////////////////////////// /// Die Szene zeichnen //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////// this->srGraphic->DrawScene(this->mesh, this->axis); //////////////////////////////////////// } void srWindow::InitOpenGL(int width, int height) { //////////////////////////////////////////////////////////////////////////////// /// OpenGL einrichten //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////// float ratioWidthHeight = static_cast<float>(width)/static_cast<float>(height); glEnable(GL_BLEND); glEnable(GL_COLOR_MATERIAL); glEnable(GL_DEPTH_TEST); glEnable(GL_TEXTURE_2D); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glClearColor(0.92f, 0.92f, 0.92f, 0.0f); glClearDepth(1.0f); glDepthFunc(GL_LEQUAL); glShadeModel(GL_SMOOTH); glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); glViewport(0, 0, width, height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45.0f, ratioWidthHeight, 0.1f, 200.0f); glMatrixMode(GL_MODELVIEW); this->srGraphic->LoadTextures(); //////////////////////////////////////// } void srWindow::KeyPress(unsigned char key, int x, int y) { //////////////////////////////////////////////////////////////////////////////// /// Das Objekt mit der Tastertur steuern (Buchstabentasten) //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////// switch(key) { case 27: exit(0); case 'a': case 'A': srInstance->MoveLeft(); break; case 'd': case 'D': srInstance->MoveRight(); break; case 's': case 'S': srInstance->MoveBackwards(); break; case 'w': case 'W': srInstance->MoveForward(); break; } glutPostRedisplay(); //////////////////////////////////////// } void srWindow::Mouse(int button, int state, int x, int y) { //////////////////////////////////////////////////////////////////////////////// /// Die Mausposition speichern //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////// if(button == GLUT_LEFT_BUTTON) { if(state == GLUT_DOWN) { srInstance->motion = true; srInstance->posX = x; srInstance->posY = y; } if(state == GLUT_UP) { srInstance->motion = false; } } glutPostRedisplay(); //////////////////////////////////////// } void srWindow::MouseMotion(int x, int y) { //////////////////////////////////////////////////////////////////////////////// /// Das Objekt mit der Maus drehen //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////// if(srInstance->motion) { srInstance->rotateX+=(y-srInstance->posY)/10.0f; srInstance->rotateY-=(x-srInstance->posX)/10.0f; glutPostRedisplay(); } //////////////////////////////////////// } void srWindow::MoveBackwards() { //////////////////////////////////////////////////////////////////////////////// /// Das Objekt nach hinten verschieben //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////// if(this->game) { this->translateX-=0.05f*std::sin(this->rotateY*this->piover180); this->translateZ-=0.05f*std::cos(this->rotateY*this->piover180); if(this->walk<1.0f) { this->walk = 359.0f; } else { this->walk-=10.0f; } this->translateY = -std::sin(this->walk*this->piover180)/20.0f-0.25f; } else { this->translateX-=0.05f*std::cos(this->rotateX*this->piover180) *std::cos(this->rotateY*this->piover180-M_PI/2.0f); this->translateY-=0.05f*std::sin(this->rotateX*this->piover180); this->translateZ-=0.05f*std::cos(this->rotateX*this->piover180) *std::sin(this->rotateY*this->piover180+M_PI/2.0f); } //////////////////////////////////////// } void srWindow::MoveForward() { //////////////////////////////////////////////////////////////////////////////// /// Das Objekt nach vorne verschieben //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////// if(this->game) { this->translateX+=0.05f*std::sin(this->rotateY*this->piover180); this->translateZ+=0.05f*std::cos(this->rotateY*this->piover180); if(this->walk>358.0f) { this->walk = 0.0f; } else { this->walk+=10.0f; } this->translateY = -std::sin(this->walk*this->piover180)/20.0f-0.25f; } else { this->translateX+=0.05f*std::cos(this->rotateX*this->piover180) *std::cos(this->rotateY*this->piover180-M_PI/2.0f); this->translateY+=0.05f*std::sin(this->rotateX*this->piover180); this->translateZ+=0.05f*std::cos(this->rotateX*this->piover180) *std::sin(this->rotateY*this->piover180+M_PI/2.0f); } //////////////////////////////////////// } void srWindow::MoveLeft() { //////////////////////////////////////////////////////////////////////////////// /// Das Objekt nach links verschieben //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////// this->translateX-=0.05f*std::sin(this->rotateY*this->piover180-M_PI/2.0f); this->translateZ-=0.05f*std::cos(this->rotateY*this->piover180-M_PI/2.0f); if(this->game) { if(this->walk<1.0f) { this->walk = 359.0f; } else { this->walk-=10.0f; } this->translateY = -std::sin(this->walk*this->piover180)/20.0f-0.25f; } //////////////////////////////////////// } void srWindow::MoveRight() { //////////////////////////////////////////////////////////////////////////////// /// Das Objekt nach rechts verschieben //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////// this->translateX+=0.05f*std::sin(this->rotateY*this->piover180-M_PI/2.0f); this->translateZ+=0.05f*std::cos(this->rotateY*this->piover180-M_PI/2.0f); if(this->game) { if(this->walk>358.0f) { this->walk = 0.0f; } else { this->walk+=10.0f; } this->translateY = -std::sin(this->walk*this->piover180)/20.0f-0.25f; } //////////////////////////////////////// } void srWindow::Navigate(int key, int x, int y) { //////////////////////////////////////////////////////////////////////////////// /// Das Objekt mit der Tastertur steuern (Pfeil- und Funktionstasten) //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////// switch(key) { case GLUT_KEY_F1: if(srInstance->IsShow(srAXIS)) { srInstance->SwitchMode(srHIDE_AXIS_MODE); } else { srInstance->SwitchMode(srSHOW_AXIS_MODE); } break; case GLUT_KEY_F2: if(srInstance->IsShow(srGAME)) { srInstance->SwitchMode(srHIDE_GAME_MODE); } else { srInstance->SwitchMode(srSHOW_GAME_MODE); srInstance->translateY = -0.25f; } break; case GLUT_KEY_F3: if(srInstance->IsShow(srMESH)) { srInstance->SwitchMode(srHIDE_MESH_MODE); } else { srInstance->SwitchMode(srSHOW_MESH_MODE); } break; case GLUT_KEY_DOWN: srInstance->RotateDown(); break; case GLUT_KEY_LEFT: srInstance->RotateLeft(); break; case GLUT_KEY_RIGHT: srInstance->RotateRight(); break; case GLUT_KEY_UP: srInstance->RotateUp(); break; } glutPostRedisplay(); //////////////////////////////////////// } void srWindow::Render() { //////////////////////////////////////////////////////////////////////////////// /// Die 3D-Objekte rendern //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////// glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT); glLoadIdentity(); srInstance->srGraphic->Fog(!srInstance->mesh); glPushMatrix(); glRotatef(srInstance->GetValue(srROTATE_X), 1.0f, 0.0f, 0.0f); glRotatef((360.0f-srInstance->GetValue(srROTATE_Y)), 0.0f, 1.0f, 0.0f); glTranslatef(srInstance->GetValue(srTRANSLATE_X), srInstance->GetValue(srTRANSLATE_Y), srInstance->GetValue(srTRANSLATE_Z)); srInstance->DrawScene(); glPopMatrix(); glutSwapBuffers(); //////////////////////////////////////// } void srWindow::Resize(int width, int height) { //////////////////////////////////////////////////////////////////////////////// /// OpenGL im Panel anpassen //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////// float ratioWidthHeight = static_cast<float>(width)/static_cast<float>(height); glViewport(0, 0, width, height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45.0f, ratioWidthHeight, 0.1f, 200.0f); glMatrixMode(GL_MODELVIEW); //////////////////////////////////////// } void srWindow::RotateDown() { //////////////////////////////////////////////////////////////////////////////// /// Das Objekt nach unten drehen //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////// if(rotateX>358.0f) { this->rotateX = 0.0f; } else { this->rotateX++; } //////////////////////////////////////// } void srWindow::RotateLeft() { //////////////////////////////////////////////////////////////////////////////// /// Das Objekt nach links drehen //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////// if(rotateY>358.0f) { this->rotateY = 0.0f; } else { this->rotateY++; } //////////////////////////////////////// } void srWindow::RotateRight() { //////////////////////////////////////////////////////////////////////////////// /// Das Objekt nach rechts drehen //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////// if(this->rotateY<1.0f) { this->rotateY = 359.0f; } else { this->rotateY--; } //////////////////////////////////////// } void srWindow::RotateUp() { //////////////////////////////////////////////////////////////////////////////// /// Das Objekt nach oben drehen //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////// if(this->rotateX<1.0f) { this->rotateX = 359.0f; } else { this->rotateX--; } //////////////////////////////////////// } void srWindow::Show() { //////////////////////////////////////////////////////////////////////////////// /// Das Fenster anzeigen //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////// while(true) { glutMainLoopEvent(); } glutLeaveMainLoop(); //////////////////////////////////////// } void srWindow::SwitchMode(int code) { //////////////////////////////////////////////////////////////////////////////// /// Den Anzeigemouds ändern //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////// switch(code) { case srHIDE_AXIS_MODE: this->axis = false; break; case srHIDE_GAME_MODE: this->game = false; break; case srHIDE_MESH_MODE: this->mesh = false; break; case srSHOW_AXIS_MODE: this->axis = true; break; case srSHOW_GAME_MODE: this->game = true; break; case srSHOW_MESH_MODE: this->mesh = true; break; } //////////////////////////////////////// }Abgesehen davon, ist mir aufgefallen, dass mein CPU bis zu 90% ausgelastet ist (bei wxWidgets waren es höchstens 15%).
Gruß,
littletux
-
littletux schrieb:
Hallo zusammen,
ich habe eine Klasse geschrieben, die die notwendigen Anweisungen von GLUT enthalten, um 3D-Graphiken in ein Fenster darzustellen. Da die Ereignis-Funktionen aus der GLUT-Bibliothek keine Klassen kennen, musste ich einen Umweg gehen und die Ereignis-Funktionen als statisch definieren.
Was hat die Implementierung deiner Klasse damit zu tun, ob die GLU-Lib Klassen kennt?
Das Problem war, dass ich unbedingt ein This-Zeiger brauchte, um auf die Aktuelle Position des Spielers zuzugreifen, deshalb habe ich mich entschlossen in der Klasse ein Objekt von der Klasse selbst zu erstellen. Ich dann alles so geschrieben, wie ich es mir überlegt habe, und es hat auch funktioniert.
Klingt irgendwie wirr. In der Klasse ein Objekt der Klasse, das passt irgendwie nicht, klingt nach Designfehler.
Ich habe aber irgendwie ein ethisches Gefühl, zur meine Klasse, dass irgendetwas noch fehlt. Den die Klasse selbst noch mal in der Klasse zu definieren ist schon ein wenig verwirrend.
Was das mit Ethik zu tun hat ist mir zwar schleierhaft, aber da fehlt wohl ein durchdachtes Design, wie deine Klasse mit der Bibliothek zusammenarbeitet. Nach dem was ich bisher gelesen hab hast du erstmal drauflos gecodet und die auftauchenden Probleme durch irgendwelche Krummen Workarounds zu beheben versucht.
Hier ist mein C++-Quelltext:
Glaubst du wirklich, dass sich jemand >500 Zeilen Code durchliest?
Ich hab mir nur den Header angeschaut, und mir ist aufgefallen, dass du völlig unnötig Header eingebunden hast, die du im Header garnicht brauchst. Sowas gehört in die .cpp
Private statische Funktionen brauchst du auch nicht im Header zu deklarieren, die kannst du als freie Funktionen mit internal linkage (static oder besser in einem anonymen namespace) in der .cpp definieren, da du sie woanders eh nicht benutzen kannst.
-
Statt "rotatex()" würde ich vielleicht ne extra Matrixklasse schreiben, das ist ja überhässlich so...
-
Ich glaub, der beste Tipp hier ist, sich die Verantwortlichkeiten zu überlegen: Was repräsentiert die Klasse, wozu wird sie verwendet?
Wenn man das nicht in einem knappen Satz formulieren kann, ist das Ding wohl zu voll. Vermutlich lassen sich über 5 Klassen aus dem Gerät basteln.
-
Der Hauptgrund, warum ich die Klasse selbst in der Klasse definiert habe war, dass ich alle Funktionen kapseln wollte. Ich habe die Funktionen glut...Func() anfangs in die Main-Funktion rein geschrieben, wie es bei den Beispielen von Nehe auch zu sehen ist.
Ich habe es später aber versucht in eine Klasse zu packen, weil ich geglaubt habe, es wäre besser alle Funktionen zu kapseln.
Was die Klasse srWindow repräsentiert und wofür sie verwendet wird ist einfach zu beantworten. Sie soll ein einfaches Fenster auf die Arbeitsobfläche zeichnen und die 3D-Objekte aus der srGraphics-Klasse laden und rendern können, sowie auf Ereignisse (Repaint, Tastertur und Maus) reagieren.
Danke für eure Meinungen!
Ich werde
1. Alle Ereignisse (statische Funktionen) wieder in die Main-Funktion packen.
2. Eine Strukur Namens srPoint erstellen, die die Werte x, y, z speichern kann
3. Die srWindow-Klasse ganz auflösen, da sie eigentlich nicht mehr gebraucht wird
4. Das ganze im Namespace verpacken.
-
Vielleicht interessiert dich das hier:
-
Also waren meine Überlegungen mit Klasse, die sich selbst aufruft, doch nicht verkehrt

Also könnte ich meine Klasse so lassen (abgesehen von einigen Kritikpunkten)? Ich habe jetzt auch mittlerweile herausgefunden, warum mein CPU auf 90% kommt. es liegt dran:
while(true) { glutMainLoopEvent(); } glutLeaveMainLoop();ich habe es durch
glutMainLoop()ersetzt. Jetzt ist mein CPU nur noch mit 4% ausgelastet. Ich habe jetzt eine Strucktur Namens srPoint geschrieben die im Namespace srGraphic zu finden ist.
Was meint Ihr ist jetzt besser? Die Klasse wegen der Kapselung aufheben oder lieber die statische Funktionen in einem Namespace packen, um die Übersicht zu behalten?
-
Die neue freeGlut akzeptiert bald einen Userpointer für die Callbacks. Damit kann man das ganze dann auch sauber in eine Klasse packen ohne Singleton.
Nur als Info :).
-
Sie soll ein einfaches Fenster auf die Arbeitsobfläche zeichnen und die 3D-Objekte aus der srGraphics-Klasse laden und rendern können, sowie auf Ereignisse (Repaint, Tastertur und Maus) reagieren.
Du siehst, das sind schon viele Dinge.
- 3D-Objekte laden können? Das Laden von 3D-Modellein die Fensterklasse zu stecken ist wirklich extrem gottklassenmäßig
- 3D-Objekte rendern; das wüdre ich wahrscheinlich auch auslagern. Vielleicht lassen sich Dinge auch in andere Viewports oder so rendern? Auf alle Fälle solltest Du eine eigene Modellklasse haben
- Ereignisse würde ich auch auslagern; zum Teil eignen sich geeignete Funktionen, Du kannst aber auch einen EventManager basteln, der zentral auf Ereignisse eingeht. Ich weiß nicht, wo die Ereignisse genau hinlaufen. Wenn das wirklich 1:1 zu einem Fenster ist, kannst Du es auch integrieren. Oder Du verbindest das über eine EventManager-Klasse pro Fenster, die Du aber trotzdem 1:1 einbindest:
class Window { private: EventManager events; };Mainloop gehört dann nicht in ein Fenster, finde ich. Wenn es mehrere Fenster gäbe, dann würde es ja vermutlich trotzdem nur eine Mainloop geben, oder?
Daten zu Position, Rotation etc. verstehe ich im Kontext eines Fenster gar nicht. Sind das Kamerakoordinaten? Sauber wäre so etwas in einer Kamera-Klasse aufgehoben oder in eine Art RenderContext, der aber nicht zwangsläufig zu einem Fenster gehören muss. Und selbst wenn: Ich würde es trotzdem auslagern und wieder 1:1 (siehe Code oben) einbinden, weil Du Dir dann mehr offen hältst.
Ich würde Position, Rotation, Skalierung außerdem auch oft in eine eigene Struktur auslagern, die Du wiederverwenden kannst.
Fazit: Entweder, Du überlegst Dir eine saubere Architektur, bei der Du bedenkst, wo Du was erweitern und ändern können willst, damit Dein Entwicklungsaufwand auch wirklich zurückgeht, wenn Du ein zweites Projekt anfasst, oder Du schreibst die Dinge halt so wie in den Tutorials in den Code.
Meine Erfahrung ist, dass es eigentlich zum Einarbeiten nicht so sehr auf den sauberen Code ankommt. Und wenn Du später eine Engine bastelst (eine kleine), dann solltest Du Dir eh nochmal Gedanken machen. Und falls Du eine fremde Engine nutzt und ein eigenes Projekt entwickelst, hast Du wiederum andere Gesichtspunkte.
Hoffe, das hilft Dir etwas weiter.
-
Ich habe meine Klasse neu strukturiert. Es klappt alles, aber GLUT-Ereignis bereiten mir große sorgen. Irgendwie ist mein CPU immer auf 90% ausgelastet ich weis nicht warum.
Ich habe anfangs geglaubt, es liegt am folgenden Code:
while(true) { glutMainLoopEvent(); } glutLeaveMainLoop();Dies ist aber nicht so. Vielleicht liegt es an meinen Notebook. Aber es dürfte nicht sein, da mein Notebook mit AMD Turion 64 X2 TL-64 (Doppelkernprozessor) und eine Grafikkarte von Nvidia (nForce 630M) läuft.
Wenn ich aber anstelle GLUT den wxWidgets-Framework benutze ist die CPU Auslastung nicht so wild.
//////////////////////////////////////////////////////////////////////////////// /// Die srBase-Schablone //////////////////////////////////////////////////////////////////////////////// #ifndef _srBase_h_ #define _srBase_h_ #include "graphic.h" namespace srBase { class srWindow { private: bool axis; bool mesh; bool motion; srGraphic::srPoint pos; srGraphic::srPoint rotate; srGraphic::srPoint translate; void DrawScene(); void InitOpenGL(int width, int height); static srWindow *srInstance; static void Keyboard(unsigned char key, int x, int y); static void Mouse(int button, int state, int x, int y); static void Motion(int x, int y); static void Render(); static void Reshape(int width, int height); static void Special(int key, int x, int y); srGraphic::srCamera *srPlayer; srGraphic::srDeviceContext *srDC; public: srWindow(const std::string &stdpath); ~srWindow(); enum { srROTATE_X, srROTATE_Y, srTRANSLATE_X, srTRANSLATE_Y, srTRANSLATE_Z, srAXIS, srMESH, srHIDE_AXIS_MODE, srHIDE_MESH_MODE, srSHOW_AXIS_MODE, srSHOW_MESH_MODE }; bool IsShow(int code); float GetValue(int code); void Show(); void SwitchMode(int code); }; } #endif
-
littletux schrieb:
Ich habe anfangs geglaubt, es liegt am folgenden Code:
...Dies ist aber nicht so.
Was hat dir gezeigt, dass es nicht daran liegt? Hast du mal einen Profiler bemüht um zu gucken wo dein Programm die meiste Zeit verbringt?
-
Ich habe mit den InputOutput-Stream beobachtet was passiert, wenn ich den Code verwende:
while(true) { glutMainLoopEvent(); } glutLeaveMainLoop();Dort läuft alles Normal ab:
Die GUI-App ruft die Funktion Render auf wartet bis ein Ereignis passiert, dann wird die Render-Funktion erneut aufgerufen (um das Objekt richtig zu positionieren), wie erwartet.
Wenn ich aber anstelle der obere Anweisung
glutMainLoop()verwende, dann wird die Render-Funktion sehr oft aufgerufen. Also könnte man sagen, die Anweisungen
while(true) { glutMainLoopEvent(); } glutLeaveMainLoop();eignen sich besser, wenn man das Fenster dauerhaft, bis zur Beendigung anzeigen möchte.
Da sich die Ereignisse dauerhaft mit der Render-Funktion befassen, muss es mit einer der folgenden Funktionen zu tuen haben:
1:glutDisplayFunc(&this->Render); 2:glutIdleFunc(&this->Render);Frage mich was die mit Idle meinen. Mit Display denke ich, meint GLUT das Fenster.
-
Ich habe glutIdleFunc(&this->Render); auskommentiert. Ich glaube es hat irgendwas mit Leerlauf zu tuen, wenn kein Ereignis stattfindet, aber mein CPU ist immer noch ausgelastet, bei der Ausführung...
-
littletux schrieb:
Ich habe glutIdleFunc(&this->Render); auskommentiert. Ich glaube es hat irgendwas mit Leerlauf zu tuen, wenn kein Ereignis stattfindet, aber mein CPU ist immer noch ausgelastet, bei der Ausführung...
glutIdleFunc sets the global idle callback to be func so a GLUT program can perform background processing tasks or continuous animation when window system events are not being received. If enabled, the idle callback is continuously called when events are not being received. The callback routine has no parameters. The current window and current menu will not be changed before the idle callback. Programs with multiple windows and/or menus should explicitly set the current window and/or current menu and not rely on its current setting.
The amount of computation and rendering done in an idle callback should be minimized to avoid affecting the program's interactive response. In general, not more than a single frame of rendering should be done in an idle callback.
Passing NULL to glutIdleFunc disables the generation of the idle callback.
http://www.opengl.org/resources/libraries/glut/spec3/node63.html
-
Ich habe was anderes ausprobiert:
while(true) { usleep(500); glutMainLoopEvent(); } glutLeaveMainLoop();Wenn ich usleep einbaue wird der CPU so gut wie kaum ausgelastet.
-
Jetzt scheint meine App zu funktionieren

Ich werde aber noch ein wenig an meinen Code arbeiten, damit es ganz strukturiert aussieht und mit wenig Code wie möglich auskommt.Wie ist es eigentlich wenn ich mein Programm für Windows oder Apple global machen möchte, welche Header-Dateien muss ich einbinden und was muss ich nach #ifdef schreiben?