Cocoa OpenGL Rendern mit Timer / Idle?

S

SchodMC

Mitglied
Thread Starter
Dabei seit
27.08.2009
Beiträge
29
Reaktionspunkte
0
Hallo,

ich habe eine Frage zum Thema OpenGL und Cocoa. Bisher bin ich OpenGL Programmierung "nur" unter Windows gewöhnt. Dort habe ich die Funktion zum Rendern immer innerhalb der Main-Loop bzw. in der Idle Funktion (die von der Main-Loop nach der Abarbeitung aller anstehenden Windows-Nachrichten aufgerufen wurde) plaziert.

In den Beispielen von Apple und diversen Tutorials hab ich gesehen, dass die Render-Funktion unter Cocoa von einem Timer aufgerufen wird.

Daher meine Frage: gibt es eine Möglichkeit, sich in die Main-Loop einzuhängen? Ich weiß, dass dies mit dem Timer irgendwie der Fall ist, aber der Aufruf erfolgt eben "nur" nach einer bestimmten Zeit und nicht immer. Zwar mag das den Vorteil haben, dass die CPU nicht auf Max. läuft. Aber es dürfte doch einiges an Resourcen für das Rendern verschwendet werden, da der Timer das ganze doch ausbremst. Mag natürlich sein, dass ich den Timer falsch verstehen...

Auf der anderen Seite: soweit ich das verstanden hab ist Cocoa nicht einfach nur ein Objekt-Orientierer Aufsatz für eine API wie die MFC unter Windows sondern die "native" GUI Schnittstelle für Mac OSX. Liege ich damit richtig oder gibt es noch ein andere Möglichkeit, ein Fenster zu erstellen und zur OpenGL Ausgabe zu verwenden (ähnlich der Windows API bei der man seine Main-Loop dann alleine erstellt).

Und bevor es Missverständnisse gibt: nein, ich weine nicht der Windows-API hinterher. Im Gegenteil, ich finde es sehr angenehm, vom System eine gut durchdachte Objekt-Orientierte API zu bekommen. Ich hab halt nur Anfragen bzgl. der Performance, zumal Objective-C an sich schon etwas langsamer sein soll als C++ (laut diversen Internet-Aussagen, wobei ich einfach mal davon ausgehe, dass das mittlerweile zu vernachlässigen ist).

Gruß Marc
 
Ja, Timer sind auf der Run Loop. Ich denke, wenn Du noch tiefer runter willst musst Du an den Scheduler selbst gehen. Das willst Du sicher nicht.

Timer haben eine Auflösung von 50 - 100 Millisekunden, das reicht für die meisten Dinge...

Wenn Du die RunLoop blockierst dann wird man auch nicht sehen, was Du zeichnest.

Richtig ist auch, dass Cocoa das native GUI zu OS X ist. Es ist aber sehr einfach, in Cocoa OpenGL einzubauen.

Alex
 
ich weiß ja nicht, was du da rendern willst, dass du da die ganze CPU blockieren willst ;)
der timer ist ja auch eher dafür da, dass du deine gewünschte framerate einhalten kannst, der bremst dich nicht aus...
in cocoa/obj-c läuft auch vieles über messaging/trigger/events, du hast da nicht wirklich eine main wie bei C/C++ ...
 
ich weiß ja nicht, was du da rendern willst, dass du da die ganze CPU blockieren willst ;).

Na ja, von Blockieren kann ja keine Rede sein. Unter Windows jedenfalls wurde das so gemacht. Kann natürlich sein, dass das nun einiges erklärt. ;)

Abe rim Ernst: dann scheint der Timer ja die eigentliche Variante zu sein. Wie macht id-Software das eigentlich bei Quake? Denn dort ist mir positiv aufgefallen, dass das Game auf meinem MacBook Pro (late 2009) flüssig lief und die CPU trotzdem nicht voll ausgelastet war.

Das heißt dann letztlich, dass ich hier über die internen Design-Unterschiede von Mac OS und Windows gestolpert bin. Muss mich wohl in die interne Architektur noch etwas tiefer einarbeiten.

Thnx & Gruß Marc
 
quake ist kein gutes beispiel, das war ja bestimmt noch carbon/corefoundation und nicht cocoa ;)
aber die quake sourcen sind ja inzwischen frei, da kannst du ja auch mal einen blick rein werfen...
 
Ist ein guter Hinweis, danke. Momentan beiß ich mich durch die Beispiele von Apple. Dabei ist mir aufgefallen, dass die Render-Funktion nicht ein Teil des Objektes ist, sondern eine normale C Funktion. Warum? Ich kann mir keinen bestimmten Grund vorstellen, aber da ich relativ neu bei Cocoa und Objective-C bin, kann es natürlich auch sein, dass ich was überseh.
 
Weil OpenGL ja C ist.

Alex
 
Ok, das hinder mich ja nicht daran, von einer Objective-C Funktion die Render Funktionen von OpenGL aufzurufen.
 
Hmm, könnt ihr mir bitte nochmal helfen? Ich hab folgenden Code geschrieben:

Code:
@implementation OpenGLView

-(void) awakeFromNib;
{
	// Den Timer erstellen, der für das Rendern zuständig ist.
	renderTimer = [NSTimer timerWithTimeInterval:(1.0f / 60.0f) target:self selector:@selector(timerEvent:) userInfo:nil repeats:YES];
	[[NSRunLoop currentRunLoop] addTimer:renderTimer forMode:NSDefaultRunLoopMode];
	[[NSRunLoop currentRunLoop] addTimer:renderTimer forMode:NSEventTrackingRunLoopMode];
}

-(void)timerEvent:(NSTimer *)sender
{
    glClearColor(0, 0, 0, 0);
    glClear(GL_COLOR_BUFFER_BIT);
 
    glRotatef(1.0f, 0.0f, 0.0f, 1.0f);
    glColor3f(1.0f, 0.85f, 0.35f);
    glBegin(GL_TRIANGLES);
    {
        glVertex3f(  0.0,  0.6, 0.0);
        glVertex3f( -0.2, -0.3, 0.0);
        glVertex3f(  0.2, -0.3 ,0.0);
    }
    glEnd();
	
    glFlush();	
    [[self openGLContext] flushBuffer];
}

Es funktioniert auch, ich sehe ein sich drehendes Dreieck. Allerdings muss ich dazu das Fenster mindestens einmal bewegen, damit es sichtbar wird. Solange das Fenster nicht mindestens einmal bewegt wird, bleibt es weis. Was mache ich falsch?

Gruß Marc
 
könnte daran liegen, dass du den timer in awakeFromNIB feuerst.
probier es mal in der init oder in der applicationDidFinishLaunching.
 
Nein, daran liegt es nicht. Denn erstens hat das Apple-Beispiel das ebenso gemacht und zweitens wird timerEvent aufgerufen (geprüft per Debugger sowie per NSLog). Nur das Render-Ergebnis wird nicht ausgegeben. Bis ich eben das Fenster verschiebe oder in der Größe änder. Ab dann läuft das ganze Problemlos. Verwirrend. Muss ich irgendwie noch ein Refresh des Fensters vor dem ersten Rendern machen oder sonst sowas in die Richtung?
 
Du solltest das Rendering nicht über einen Timer machen, sondern mittels eines sog. Displaylinks mit dem display-refresh synchronisieren. Denn alles Zeichnen, welches häufiger als die refreshrate passiert, kostet nur sinnlos CPU-Zeit und Batterielaufzeit.

Hier gibt es details: http://developer.apple.com/library/mac/#qa/qa2004/qa1385.html

Viele Grüße, SMJ
 
Zurück
Oben Unten