GLUT (OpenGL Utility Toolkit) in eine Klasse



  • 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.

    1. 3D-Objekte laden können? Das Laden von 3D-Modellein die Fensterklasse zu stecken ist wirklich extrem gottklassenmäßig
    2. 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
    3. 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?


Anmelden zum Antworten