Files |  Tutorials |  Articles |  Links |  Home |  Team |  Forum |  Wiki |  Impressum

Aktuelle Zeit: Mi Jul 09, 2025 14:22

Foren-Übersicht » Programmierung » Einsteiger-Fragen
Unbeantwortete Themen | Aktive Themen



Ein neues Thema erstellen Auf das Thema antworten  [ 6 Beiträge ] 
Autor Nachricht
 Betreff des Beitrags: Möglichkeiten der Kameraeinstellung
BeitragVerfasst: Do Aug 16, 2007 10:15 
Offline
DGL Member

Registriert: Mi Mär 28, 2007 17:45
Beiträge: 131
Hallo,

ich erkunde zur Zeit, welche Möglichkeiten es gibt, die Kamera zu verstellen, also praktisch in der Szenerie herumzuwandern. Dabei ist mir noch unklar, welche Vor- und Nachteile die verschiedenen Ansätze haben. Vielleicht könnt Ihr mir ein paar Tips dazu geben.

1. Bevor die Szenerie gezeichnet wird, rotiere und verschiebe ich das Ganze mit glRotate und glTranslate, wobei nach meiner Beobachtung diese Reihenfolge eingehalten werden muss. Damit habe ich, wenn ich das richtig verstanden habe, so etwas wie eine Grundmatrix erzeugt, auf der dann alles aufbaut. Offensichtlich muss ich anschließend glLoadIdentiy meiden.

2. In einem DGL-Wiki fand ich den Ansatz, nicht die Modelview-Matrix, sondern die Projektionsmatrix zu änderen, also glTranslate und glRotate direkt nach dem üblichen gluPerspective aufzurufen. Die Ergebnisse sind bei mir noch ein bisschen kraus, aber ich hab's auch noch nicht systematisch untersucht.

3. Ja, und dann fand ich bei einem Blick in ein anderes Programm noch folgende Methode: Aus Kameraposition und Blickrichtung wird eine 4x4-GL-Matrix berechnet (verdammt kompliziert) und dann mittels glMultMatrix mit der Identity-Matrix multipliziert. Die Wirkung scheint dieselbe zu sein wie beim Ansatz 1.

Gibt es Gründe, die eine oder andere Methode zu bevorzugen oder zu meiden? Oder gibt es noch andere Methoden (kleiner Tip genügt, untersuchen kann ich es selber).


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Do Aug 16, 2007 10:25 
Offline
DGL Member
Benutzeravatar

Registriert: Do Sep 02, 2004 19:42
Beiträge: 4158
Programmiersprache: FreePascal, C++
Ich kann, vorallem, wenn du später noch kompliziertere Sachen, wie z.B. Shader, vorhast, die 2. Methode empfehlen. Denn sonst könnte es später schwierig werden, die glRotate/glTranslate-Aufrufe, die du für die Kamera gemacht hast, von denen zu trennen, die für Rotation oder Translation der einzelnen Modelle zuständig sind.

Da du gesagt hattest, dass du damit probleme hast, kann ich dir hier mal einen kleinen Tipp geben, der vorallem auch die Performance steigert:
Wenn du jetzt beim resize-Event (in der VCL OnResize) oder beim Initialisieren deine Projektionsmatrix setzt, speicherst du das, was da nach gluPerspective drin steht erstmal in eine Variable. Dazu gibt es glGetFloatv:
Code:
  1.  
  2. var
  3.   ProjMatrix: array [0..3, 0..3] of Single; // Sollte eine globale Variable oder eine Variable von TForm1 oder wie auch immer du deine Fensterklasse genannt hast sein.
  4.  
  5. ...
  6.  
  7. glMatrixMode(GL_PROJECTION);
  8.   glLoadIdentity;
  9.   gluPerspective(...); //das, was du für deinen gluPerspective-Aufruf brauchst
  10.   glGetFloatv(GL_PROJECTION_MATRIX, @ProjMatrix); // Die Projektionsmatrix in die Variable schreiben
  11. glMatrixMode(GL_MODEL_VIEW);
  12.  

An der stelle, wo du während dem Rendern deine Kamera setzt, tust du jetzt folgendes:
Code:
  1.  
  2. glMatrixMode(GL_PROJECTION);
  3.   glLoadIdentity;
  4.   glLoadMatrixf(@ProjMatrix);
  5.   // Und jetzt die Aufrufe, die du für deine Kamera brauchst.
  6. glMatrixMode(GL_MODEL_VIEW);
  7. glLoadIdentity; // Zu guter letzt die Modelviewmatrix zurücksetzen,
  8.                 //kannst du auch weglassen, sollte man am Anfang vom Rendern dennoch tun.
  9.  


Jetzt kannst du auch während dem Rendern, solange du in der ModelViewMatrix bleibst, nach belieben glLoadIdentity aufrufen, die Projektionsmatrix bleibt davon verschont.

Gruß Lord Horazont

_________________
If you find any deadlinks, please send me a notification – Wenn du tote Links findest, sende mir eine Benachrichtigung.
current projects: ManiacLab; aioxmpp
zombofant networkmy photostream
„Writing code is like writing poetry“ - source unknown


„Give a man a fish, and you feed him for a day. Teach a man to fish and you feed him for a lifetime. “ ~ A Chinese Proverb


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Do Aug 16, 2007 10:45 
Offline
DGL Member
Benutzeravatar

Registriert: Mo Jan 31, 2005 11:02
Beiträge: 432
Wohnort: Rheinlandpfalz
@Lord Horazont:
Wie viel Performance gewinnt man denn dadurch? Wenn sich das lohnt, ist es eine gute Idee, dann werde ich das ab sofort auch so machen ;)

@erin:
Ja, ich empfehle auch die Speicherung der Kamera in der Projektionsmatrix. Aber wenn du nicht vorhast mit shadern zu arbeiten, dann kannst du das auch in der ModelviewMatrix machen (hat den Vortel, dass die Projektionsmatrix gleich bleibt und du somit wiederum etwas Performance gewinnst).

Eine Matrix musst du nicht unbedingt erstellen (wie in 3.). Ich mache es zurzeit auch so, dass ich mit glrotate und gltranslate arbeite. Aber so eine Kamera-Matrix kann natürlich für spätere Effekte sinnvoll zu gebrauchen sein. Aber wenn du momentan keinen Vorteil darin siehst kannst du es auch wie in Punkt 1 machen.

_________________
http://texelviews.delphigl.com


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Do Aug 16, 2007 11:12 
Offline
DGL Member

Registriert: So Aug 20, 2006 23:19
Beiträge: 564
Also ich hatte auch mal die dritte Variante mit der Berechnung der Matrix aus Translationsvektoren und Blickwinkeln mit einer ganzen Menge Cos und Sin... Das war sehr kompliziert und im Endeffekt war die Modifizierung sauanstrengend, deswegen bin ich nun auch wieder bei eine Translationsvektor und zwei Blickwinkeln, die ich dann per glTranslate und glRotate einsetze.

Du kannst sehr wohl glLoadidentity benutzen, nur musst du vorher die Matrix speichern.
Das könnte dann so aussehen:

Code:
  1.  
  2.   glLoadIdentity;
  3.   glRotatef(Rotation[0],1,0,0);
  4.   glRotatef(Rotation[1],0,1,0);
  5.   glTranslatef(Translation[0],Translation[1],Translation[2]);
  6.  
  7. ...
  8.  
  9.  
  10.  glPushMatrix;
  11.  glLoadIdentity;
  12.  ....
  13.  glPopMatrix;
  14.  


So funktioniert das auch. Also ich hatte bisher noch nie Probleme bei der Positionierung von Modellen ueber diese Variante, wenn man etwas dreht, sichert man eben kurz die Matrix und restored sie danach wieder und alles ist wunderbar. Mit Translate und Rotate kann man sich zuweilen sogar sehr umständliche Rechnungen ersparen, da man letztlich nur die Differenzwerte zwischen dem aktuellen Objekt und dem zuletzt gerenderten benötigt; ruft man stattdessen dazwischen immer glLoadIdentity auf, müsste man immer wieder die absoluten (also auf den Nullpunkt bezogenen) Koordinaten einsetzen.

Vor allem, wenn du Camerabewegungen- und Drehungen simulieren willst, ist diese Variante über Rotate und Translate meiner Meinung nach hübsch einfach; vor einigen Wochen hatte ich das alles mal über selbsterrechnete Matrizen gelöst und als ich dann Camerapathmovements einbauen wollte, bin ich beinahe wahnsinnig geworden und hab alles wieder umgeschrieben.

Meine Meinung ;)


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Do Aug 16, 2007 11:31 
Offline
DGL Member
Benutzeravatar

Registriert: Do Sep 02, 2004 19:42
Beiträge: 4158
Programmiersprache: FreePascal, C++
Soweit hat die Methode auch kein Problem, aber sobald du dann versuchst, Modelkoordinaten mit Shadern zu verarbeiten wirds haarig, weil du die Kamerabewegungen wieder wegbekommen musst, ohne aber gleich die ganze Modelmatrix wegzulassen, da das Modell z.B. auch gedreht sein könnte.

Solange man keine Shader benutzt, ist die Methode einwandfrei. Aber es ist vielleicht besser, sich jetzt schonmal das andere anzugewöhnen, wenn man später irgendwann mit shadern arbeiten will.

Meine Meinung :wink:²

Gruß Lord Horazont

_________________
If you find any deadlinks, please send me a notification – Wenn du tote Links findest, sende mir eine Benachrichtigung.
current projects: ManiacLab; aioxmpp
zombofant networkmy photostream
„Writing code is like writing poetry“ - source unknown


„Give a man a fish, and you feed him for a day. Teach a man to fish and you feed him for a lifetime. “ ~ A Chinese Proverb


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Fr Aug 17, 2007 09:23 
Offline
DGL Member

Registriert: Mi Mär 28, 2007 17:45
Beiträge: 131
Vielen Dank für Eure Antworten, sie haben mir sehr geholfen, und ich sehe nun deutlich klarer. Ich bin ein Verfechter von möglichst einfachen, gradlinigen Verfahren und werde deshalb die beiden Ansätze mit glRotate und glTranslate gründlich untersuchen.

Trotzdem möchte ich das Matrix-Verfahren nicht ganz unter den Tisch fallen lassen, auch deshalb, weil man eine Menge daran lernen kann. Nicht zuletzt hat sich die Funktion erwiesenermaßen bewährt (sie stammt aus Tuxracer) und ist vor allem geeignet, wenn die Kamera z.B. einem bewegten Objekt folgen soll. Ich gebe den Code hier mal wieder. Es ist zwar C-Code, aber auch für einen Pascaller problemlos zu lesen. Außerdem lässt er sich fast 1 : 1 nach Pascal übersetzen.

Code:
  1.  
  2. static TVector viewdir;
  3. static TVector viewup;
  4. static TPoint viewpos;
  5.  
  6. void CalcViewMatrix () {
  7.     TMatrix viewmat, vmat;
  8.     TVector vx, vy, vz;
  9.     TPoint vpoint;
  10.  
  11.     vz = ScaleVector (-1, viewdir);
  12.     vx = CrossProduct (viewup, vz);
  13.     vy = CrossProduct (vz, vx);
  14.     NormalizeVector (&vz);
  15.     NormalizeVector (&vx);
  16.     NormalizeVector (&vy);
  17.  
  18.     MakeIdentityMatrix (viewmat);
  19.  
  20.     viewmat[0][0] = vx.x;
  21.     viewmat[0][1] = vx.y;
  22.     viewmat[0][2] = vx.z;
  23.  
  24.     viewmat[1][0] = vy.x;
  25.     viewmat[1][1] = vy.y;
  26.     viewmat[1][2] = vy.z;
  27.  
  28.     viewmat[2][0] = vz.x;
  29.     viewmat[2][1] = vz.y;
  30.     viewmat[2][2] = vz.z;
  31.  
  32.     viewmat[3][0] = viewpos.x;
  33.     viewmat[3][1] = viewpos.y;
  34.     viewmat[3][2] = viewpos.z;
  35.     viewmat[3][3] = 1;
  36.    
  37.     TransposeMatrix (viewmat, vmat);
  38.  
  39.     vmat[0][3] = 0;
  40.     vmat[1][3] = 0;
  41.     vmat[2][3] = 0;
  42.    
  43.     vpoint = TransformPoint (vmat, viewpos);
  44.     vmat[3][0] = -vpoint.x;
  45.     vmat[3][1] = -vpoint.y;
  46.     vmat[3][2] = -vpoint.z;
  47.    
  48.     glLoadIdentity();
  49.     glMultMatrixd ((double*)vmat);
  50. }
  51.  


Ich habe die Funktion mal in einem kleinen C-Testprogramm ausprobiert und war insofern begeistert, als man hier alle Bewegungsfreiheiten hat. Für die Kamerabewegung mit Tastatur oder Joystick ist sie jedoch nicht geeignet. Zwar kann man die Kamera sehr schön in allen drei Dimensionen verschieben, aber es hapert bei der Rotation. Der Blickwinkel wird hier als Vektor verarbeitet (viewdir). Die Vektor-Komponenten zu verstellen, hat keinen Sinn. Erstens ist die Rotation dabei nicht linear, zweitens ist bei 90° Drehung Schluss, d.h. dier Winkel nähert sich asymptotisch der 90°-Grenze.

Das Fehlen von "griffigen" Rotationswinkeln macht sich ferner bei Bewegungen nach einer Rotation bemerkbar. Ich will mich ja vorwärts in Blickrichtung bewegen und nicht stur längs der Z-Achse. Für die Positionskorrektur brauche ich aber die Drehwinkel, oder?

Egal, ich werde auch dieses Teil demnächst nach Delphi umschreiben und für Fälle bereitstellen, wo sich die Blickrichtung als Vektor ergibt.

Gruß
Reinhard


Nach oben
 Profil  
Mit Zitat antworten  
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 6 Beiträge ] 
Foren-Übersicht » Programmierung » Einsteiger-Fragen


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 13 Gäste


Du darfst keine neuen Themen in diesem Forum erstellen.
Du darfst keine Antworten zu Themen in diesem Forum erstellen.
Du darfst deine Beiträge in diesem Forum nicht ändern.
Du darfst deine Beiträge in diesem Forum nicht löschen.
Du darfst keine Dateianhänge in diesem Forum erstellen.

Suche nach:
Gehe zu:  
  Powered by phpBB® Forum Software © phpBB Group
Deutsche Übersetzung durch phpBB.de
[ Time : 0.009s | 16 Queries | GZIP : On ]