Kamera (1): Unterschied zwischen den Versionen

Aus DGL Wiki
Wechseln zu: Navigation, Suche
(Danke)
 
(23 dazwischenliegende Versionen von 3 Benutzern werden nicht angezeigt)
Zeile 1: Zeile 1:
 
==Danke==
 
==Danke==
Nachdem ich viel Zeit damit verbracht habe eine funktionierende Kamera zu bauen und es nun endlich geschafft habe, wollte ich diese Funktionalität auch anderen zur Verfügung stellen.
+
Nachdem ich viel Zeit damit verbracht habe, eine funktionierende Kamera zu bauen und es nun endlich geschafft habe, wollte ich diese Funktionalität auch Anderen zur Verfügung stellen.
Da mir schon viel geholfen wurde, kann ich so einen Teil meiner "Schuld" zurück zahlen.
+
Da mir schon viel geholfen wurde, kann ich so einen Teil meiner "Schuld" zurückzahlen.
  
Bitte seht ab und zu mal hier nach ob es für diese Kamera updates gibt. Sollte es so sein, habe ich das im Code ([[Kamera (2)]]) vermerkt. Ladet in diesem Fall bitte den Source Code der Kamera !und! die Utilities herunter.
+
Bitte seht ab und zu mal hier nach, ob es für diese Kamera Updates gibt. Sollte es so sein, habe ich das im Code ([[Kamera (2)]]) vermerkt. Ladet in diesem Fall bitte den Source Code der Kamera und(!) die Utilities herunter.
  
 
==Meine Kamera==
 
==Meine Kamera==
Die folgend beschriebene Kamera kann sich um alle drei Achsen drehen und sich
+
Die wie folgend beschriebene Kamera kann sich um alle drei Achsen drehen und sich in allen Ebenen bewegen. Der Drehpunkt um den sich die Kamera dreht wird mit dem Aufruf der Prozedur PositionCamera festgelegt. Sollte man diesen Drehpunkt benötigen (z.B. zum Anzeigen eines Koordinatenkreuzes, ...), so kann man auf die Property PointOfRotation zugreifen (read only).
in allen Ebenen bewegen. Der Drehpunkt um den sich die Kamera dreht wird mit
 
dem Aufruf der Prozedur PositionCamera festgelegt. Sollte man diesen Drehpunkt benötigen (z.B. zum anzeigen eines Koordinatenkreuzes, ...) so kann man
 
auf die Property PointOfRotation zugreifen (read only).
 
  
Die Kamera kann bis zu zehn Positionen speichern und auch wieder herstellen.
+
Die Kamera kann bis zu zehn Positionen speichern und auch wiederherstellen. (SavePosition, RestorePosition)
(SavePosition, RestorePosition)
 
  
Die Kamera kann sich selber zu jeder Zeit unter Beibehaltung der aktuellen Position senkrecht zur Welt ausrichten.
+
Die Kamera kann sich selber zu jeder Zeit unter Beibehaltung der aktuellen Position senkrecht zur Welt ausrichten. (Adjust)
(Adjust)
 
  
Um sicher zu sein, dass auch alle nötigen Definitionen und Funktionen zur  
+
Um sicher zu sein, dass auch alle nötigen Definitionen und Funktionen zur Verfügung stehen, habe ich einfach mal einen Großteil meiner Funktionssammlung beigefügt ([[Kamera (3)]]). Diese Funktionen/Prozeduren werden so oder in leicht abgeänderter Form wohl bei jedem OpenGL Programmierer existieren.
Verfügung stehen habe ich einfach mal einen Großteil meiner Funktionssammlung
 
beigefügt (OpenGLUtil.pas). Diese Funktionen/Prozeduren werden so oder in leicht
 
abgeänderter Form wohl bei jedem OpenGL Programmierer existieren.
 
  
Sollte es noch irgendwelche Fragen zu diesem Modul geben so stehe ich gerne
+
Sollte es noch irgendwelche Fragen zu diesem Modul geben, so stehe ich gerne zur Verfügung.
zur Verfügung.
 
  
 
==Gebrauch der Funktionen:==
 
==Gebrauch der Funktionen:==
 +
 +
Die hier vorzufindende Beschreibung stellt keine komplette Anleitung für die Verwendung der Kamera dar. Um bis in die "Tiefen" des Objekts hinabzusteigen seht Euch bitte das von mir bereit gestellte Beispielprogramm an ([[Kamera]]). Wenn Ihr das herunterladet habt Ihr auch auf jeden Fall die neueste Version der Sourcen, die ich zuletzt am 26.12.2007 aktualisert habe. Diese Sourcen vereinfachen die Verarbeitung von Tastatur- und Mausevents. Die u.a. Anleitung entspricht daher nicht mehr dem aktuellen Vorgehen, kann aber auch weiterhin so angewendet werden.
  
 
1.
 
1.
PositionCamera mit Vektoren für Position, Blickrichtung und Ausrichtung
+
PositionCamera mit Vektoren für Position, Blickpunkt und Ausrichtung aufrufen. Die Blickrichtung gibt auch gleichzeitig den Drehpunkt der Szene an, um den dann mit RotateCamera gedreht werden kann. PositionCamera positioniert den angegebenen Blickpunkt in der Mitte des Bildschirms. PositionCamera sollte nur zur Positionierung der Kamera benutzt werden, also einmal am Anfang. Alle weiteren Kameraveränderungen sollten mit den zur Verfügung gestellten Methoden durchgeführt werden.
aufrufen. Die Blickrichtung gibt auch gleichzeitig den Drehpunkt der Szene
 
an um den dann mit RotateCamera gedreht werden kann.
 
  
 
2.   
 
2.   
Aufruf der Funktionen RotateCamera und TranslateCamera um die Ausrichtung/Lage der
+
Aufruf der Funktionen RotateCamera und TranslateCamera um die Ausrichtung/Lage der Kamera zu verändern. Um das unten angegebene Beispiel implementieren zu können, müssen folgende Variablen im aktuellen Modul definiert werden:
Kamera zu verändern. z.B.:
 
  
 +
FMousePosX, FMousePosY,
 +
FMousePressX, FMousePressY,
 
FRightMousePressed, FLeftMousePressed,
 
FRightMousePressed, FLeftMousePressed,
 
FxDelta, FyDelta, FxStart, FyStart,
 
FxDelta, FyDelta, FxStart, FyStart,
FxRot und FyRot sind als var im aktuellen Modul definiert.
+
FxRot und FyRot (sind alle als var im aktuellen Modul definiert)
  
FRightMousePressed und FLeftMousePressed müssen in der Prozedur MouseDown/MouseUp
+
FRightMousePressed und FLeftMousePressed müssen in der Prozedur MouseDown/MouseUp gesetzt werden.
gesetzt werden.
 
  
 
FxRot und FyRot müssen mit 0 initialisiert werden.
 
FxRot und FyRot müssen mit 0 initialisiert werden.
<pascal>
+
 
procedure TExample.FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
+
<source lang="pascal">
 +
unit Example;
 +
 
 +
interface
 +
 
 +
uses
 +
  Windows, ...
 +
 
 +
type
 +
  TFExample = class(TForm)
 +
    .
 +
    .
 +
    .
 +
  private
 +
    FCamera: TCamera;
 +
 
 +
    FglDC: HDC;              // device context der aktuellen komponente
 +
    FglRC: HGLRC;            // rendering kontext der aktuellen komponente
 +
 
 +
    ClearAlpha: GLclampd;    // alpha wert der hintergrundfarbe
 +
    ClearRed: GLclampd;      // rotanteil der hintergrundfarbe
 +
    ClearGreen: GLclampd;    // grünanteil der hintergrundfarbe
 +
    ClearBlue: GLclampd;      // blauanteil der hintergrundfarbe
 +
  public
 +
    .
 +
    .
 +
    .
 +
  published
 +
    .
 +
    .
 +
    .
 +
 
 +
var
 +
  FExample: TFExample;
 +
 
 +
  FxStart,                    // berechnung der mausbewegungen.
 +
  FxDelta,                    // delta = aktuelle position minus start
 +
  FyStart,                    // start wird erfasst sobald eine maustaste
 +
  FyDelta:integer;            // gedrückt wird.
 +
 
 +
  FxRot,                      // umrechnung von delta in rotation wenn
 +
  FyRot:double;                // drehung gewünscht ist (je nach taste)
 +
 
 +
  FMousePressX,                // aktuelle mausposition, wenn maustaste gedrückt wird
 +
  FMousePressY: integer;
 +
  FMousePosX,                  // aktuelle mausposition
 +
  FMousePosY: integer;
 +
 
 +
  //mausaktivität überprüfen
 +
  FRightMousePressed:boolean;  // ist die rechte maustaste gedrückt?
 +
  FLeftMousePressed:boolean;  // ist die linke maustaste gedrückt?
 +
 
 +
const
 +
  crCursorMove = 1;
 +
  crCursorRotate = 2;
 +
  crCursorSelect = 3;
 +
 
 +
implementation
 +
 
 +
uses ...
 +
 
 +
{$R *.dfm}
 +
{$R cursors.res}
 +
</source>
 +
<source lang="pascal">
 +
procedure TFExample.FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
 
begin
 
begin
 +
  // mausposition merken
 +
  FMousePosX := X;
 +
  FMousePosY := Y;
 +
 
   //das Ziehen der Szene kann nur bei gedrückter Maustaste passieren
 
   //das Ziehen der Szene kann nur bei gedrückter Maustaste passieren
 
   if not (FRightMousePressed or FLeftMousePressed) then exit;
 
   if not (FRightMousePressed or FLeftMousePressed) then exit;
Zeile 58: Zeile 118:
 
   Fyrot := FyRot - FxDelta/20;
 
   Fyrot := FyRot - FxDelta/20;
  
   //das nächste mal ist das hier unser startpunkt:
+
   //das naechste mal ist das hier unser startpunkt:
 
   FxStart := X;
 
   FxStart := X;
 
   FyStart := Y;
 
   FyStart := Y;
Zeile 77: Zeile 137:
 
   FyRot := 0;
 
   FyRot := 0;
 
end;
 
end;
</pascal>
+
</source>
Dieses Beispiel ist vereinfacht dargestellt und es kann sein, dass man
+
<source lang="pascal">
daran noch etwas herumspielen muss. Ich habe noch das Mausrad eingesetzt
+
procedure TFExample.FormMouseDown(Sender: TObject; Button: TMouseButton;
um in den Bildschirm hinein- oder aus ihm herauszuzoomen (TranslateCamera(0,0,?)).
+
                                Shift: TShiftState; X, Y: Integer);
Durch modifizieren der Geschwindigkeit (+/-) für die einzelnen Achsen, die an die
+
begin
Prozeduren TranslateCamera und RotateCamera übergeben werden kann man entweder
+
  if Button = mbRight then
die Szene oder die Kamera bewegen.
+
  begin
 +
    //rechte maustaste gedrückt
 +
    FRightMousePressed:=true;
 +
    //Startposition merken
 +
    FxStart:=X;
 +
    FyStart:=Y;
 +
    Screen.Cursor := crCursorRotate;
 +
  end
 +
  else if Button = mbLeft then
 +
  begin
 +
    //rechte maustaste gedrückt
 +
    FLeftMousePressed:=true;
 +
    //Startposition merken
 +
    FxStart:=X;
 +
    FyStart:=Y;
 +
    Screen.Cursor := crCursorMove;
 +
  end;
 +
  // aktuelle Mouseposition festhalten. so kann z.B. überprüft werden
 +
  // welches Objekt an der aktuellen Mausposition liegt
 +
  FMousePressX := X;
 +
  FMousePressY := Y;
 +
end;
 +
</source>
 +
<source lang="pascal">
 +
procedure TFExample.FormMouseUp(Sender: TObject; Button: TMouseButton;
 +
                              Shift: TShiftState; X, Y: Integer);
 +
begin
 +
  if Button = mbRight then
 +
  begin
 +
    FRightMousePressed:=false;
 +
  end;
 +
  if Button = mbLeft then
 +
  begin
 +
    FLeftMousePressed:=false;
 +
  end;
 +
  if not (FRightMousePressed or FLeftMousePressed) then
 +
    Screen.Cursor := crCursorSelect;
 +
end;
 +
</source>
 +
<source lang="pascal">
 +
procedure TFExample.FormCreate(Sender: TObject);
 +
resourcestring
 +
  ResStrRCfailed = 'CreateRenderingContext failed ';
 +
  ResStrWGLfailed = 'wglMakeCurrent failed ';
 +
begin
 +
  inherited;
  
3.
+
  // wenn das grafiksystem von OpenGL nicht aktiviert werden kann,
 +
  // müssen wir das programm beenden
 +
  if not InitOpenGL then
 +
  begin
 +
    raise Exception.Create('InitOpenGL failed '+IntToStr(GetLastError));
 +
    halt (100);
 +
  end;
  
Szene zeichnen:
+
  FglDC := getDC(self.WindowHandle);
 +
  FglRC := CreateRenderingContext(FglDC,
 +
                                  [opDoubleBuffered],
 +
                                  32, 24, 0,0,0,0);
 +
 
 +
  if FglRC=0 then
 +
  begin
 +
    raise Exception.Create(ResStrRCfailed + IntToStr(GetLastError));
 +
    halt (100);
 +
  end;
 +
 
 +
  if not wglMakeCurrent(FglDC, FglRC) then
 +
    raise Exception.Create(ResStrWGLfailed + IntToStr(GetLastError));
 +
 
 +
  FxRot:=0;
 +
  FyRot:=0;
 +
 
 +
  FRightMousePressed := false;
 +
  FLeftMousePressed := false;
 +
 
 +
  Screen.Cursors[crCursorMove]  := LoadCursor(HInstance,'MOVE');
 +
  Screen.Cursors[crCursorRotate] := LoadCursor(HInstance,'ROTATE');
 +
  Screen.Cursors[crCursorSelect] := LoadCursor(HInstance,'SELECT');
 +
  Screen.Cursor                  := crCursorSelect;
 +
 
 +
  ClearAlpha := 1;        // bildschirm immer mit weiß löschen
 +
  ClearRed:= 1;            // bildschirm immer mit weiß löschen
 +
  ClearGreen:= 1;          // bildschirm immer mit weiß löschen
 +
  ClearBlue:= 1;          // bildschirm immer mit weiß löschen
 +
 
 +
  FCamera := TCamera.Create;
 +
end;
 +
</source>
 +
 
 +
Das mit den unterschiedlichen Cursordarstellungen habe ich nur als Hinweis gelassen. Diese Anweisungen müsst Ihr rausnehmen es sei denn, dass Ihr eine Resourcendatei mit drei unterschiedlichen Cursorarten erstellt und sie unter "Cursors.res" abspeichert.
 +
 
 +
Dieses Beispiel ist vereinfacht dargestellt und es ist sehr wahrscheinlich, dass Ihr daran noch etwas herumspielen müsst. Ich habe noch das Mausrad eingesetzt um in den Bildschirm hinein- oder aus ihm herauszuzoomen (TranslateCamera(0,0,?)).
 +
Durch modifizieren der Geschwindigkeit (+/-) für die einzelnen Achsen, die an die Prozeduren TranslateCamera und RotateCamera übergeben werden kann man entweder die Szene oder die Kamera bewegen.
 +
 
 +
3. Szene zeichnen:
  
 
Lichteigenschaften setzen
 
Lichteigenschaften setzen
 +
 
Materialeigenschaften setzen
 
Materialeigenschaften setzen
halt die üblichen Vorbereitungen treffen
+
 
 +
... (die üblichen Vorbereitungen treffen)
  
 
FCamera.Apply
 
FCamera.Apply
  
 
Szene zeichnen
 
Szene zeichnen
 +
 +
wenn Terrain gewünscht:
 +
  FCamera.ApplyForTerrain
 +
  Terrain zeichnen
 +
ende wenn
  
 
Swapbuffers...
 
Swapbuffers...
  
 
usw.
 
usw.
 +
 +
<source lang="pascal">
 +
procedure TFExample.Render;  // wird aus der Methode Paint aufgerufen
 +
resourcestring
 +
  RestStrWGLfailed = 'TFExample.Render: wglMakeCurrent failed with ';
 +
begin
 +
  // da mehrere fenster möglich sind, muss immer der aktuelle
 +
  // ausgabekontext ausgewählt werden
 +
  if wglMakeCurrent(FglDC,FglRC) then
 +
  begin
 +
    glMatrixMode (GL_MODELVIEW);
 +
 +
    glClearColor(ClearRed, ClearGreen, ClearBlue, ClearAlpha);
 +
    glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
 +
 +
    // View setzen
 +
 +
    Camera1.Apply;
 +
 +
    // Szene jetzt zeichnen
 +
 +
    glFlush;              // bearbeitung der GL-befehle beginnen
 +
    glFinish;            // warten bis alle befehle ausgeführt sind
 +
 +
    SwapBuffers(FglDC);  // flackern verhindern
 +
  end
 +
  else
 +
  begin
 +
    raise Exception.Create(RestStrWGLfailed + IntToStr(GetLastError));
 +
  end;
 +
end;
 +
</source>
  
 
Den Kameracode findet ihr unter [[Kamera (2)]].<br>  
 
Den Kameracode findet ihr unter [[Kamera (2)]].<br>  

Aktuelle Version vom 30. Januar 2022, 12:59 Uhr

Danke

Nachdem ich viel Zeit damit verbracht habe, eine funktionierende Kamera zu bauen und es nun endlich geschafft habe, wollte ich diese Funktionalität auch Anderen zur Verfügung stellen. Da mir schon viel geholfen wurde, kann ich so einen Teil meiner "Schuld" zurückzahlen.

Bitte seht ab und zu mal hier nach, ob es für diese Kamera Updates gibt. Sollte es so sein, habe ich das im Code (Kamera (2)) vermerkt. Ladet in diesem Fall bitte den Source Code der Kamera und(!) die Utilities herunter.

Meine Kamera

Die wie folgend beschriebene Kamera kann sich um alle drei Achsen drehen und sich in allen Ebenen bewegen. Der Drehpunkt um den sich die Kamera dreht wird mit dem Aufruf der Prozedur PositionCamera festgelegt. Sollte man diesen Drehpunkt benötigen (z.B. zum Anzeigen eines Koordinatenkreuzes, ...), so kann man auf die Property PointOfRotation zugreifen (read only).

Die Kamera kann bis zu zehn Positionen speichern und auch wiederherstellen. (SavePosition, RestorePosition)

Die Kamera kann sich selber zu jeder Zeit unter Beibehaltung der aktuellen Position senkrecht zur Welt ausrichten. (Adjust)

Um sicher zu sein, dass auch alle nötigen Definitionen und Funktionen zur Verfügung stehen, habe ich einfach mal einen Großteil meiner Funktionssammlung beigefügt (Kamera (3)). Diese Funktionen/Prozeduren werden so oder in leicht abgeänderter Form wohl bei jedem OpenGL Programmierer existieren.

Sollte es noch irgendwelche Fragen zu diesem Modul geben, so stehe ich gerne zur Verfügung.

Gebrauch der Funktionen:

Die hier vorzufindende Beschreibung stellt keine komplette Anleitung für die Verwendung der Kamera dar. Um bis in die "Tiefen" des Objekts hinabzusteigen seht Euch bitte das von mir bereit gestellte Beispielprogramm an (Kamera). Wenn Ihr das herunterladet habt Ihr auch auf jeden Fall die neueste Version der Sourcen, die ich zuletzt am 26.12.2007 aktualisert habe. Diese Sourcen vereinfachen die Verarbeitung von Tastatur- und Mausevents. Die u.a. Anleitung entspricht daher nicht mehr dem aktuellen Vorgehen, kann aber auch weiterhin so angewendet werden.

1. PositionCamera mit Vektoren für Position, Blickpunkt und Ausrichtung aufrufen. Die Blickrichtung gibt auch gleichzeitig den Drehpunkt der Szene an, um den dann mit RotateCamera gedreht werden kann. PositionCamera positioniert den angegebenen Blickpunkt in der Mitte des Bildschirms. PositionCamera sollte nur zur Positionierung der Kamera benutzt werden, also einmal am Anfang. Alle weiteren Kameraveränderungen sollten mit den zur Verfügung gestellten Methoden durchgeführt werden.

2. Aufruf der Funktionen RotateCamera und TranslateCamera um die Ausrichtung/Lage der Kamera zu verändern. Um das unten angegebene Beispiel implementieren zu können, müssen folgende Variablen im aktuellen Modul definiert werden:

FMousePosX, FMousePosY, FMousePressX, FMousePressY, FRightMousePressed, FLeftMousePressed, FxDelta, FyDelta, FxStart, FyStart, FxRot und FyRot (sind alle als var im aktuellen Modul definiert)

FRightMousePressed und FLeftMousePressed müssen in der Prozedur MouseDown/MouseUp gesetzt werden.

FxRot und FyRot müssen mit 0 initialisiert werden.

unit Example;

interface

uses
  Windows, ...

type
  TFExample = class(TForm)
    .
    .
    .
  private
    FCamera: TCamera;

    FglDC: HDC;               // device context der aktuellen komponente
    FglRC: HGLRC;             // rendering kontext der aktuellen komponente

    ClearAlpha: GLclampd;     // alpha wert der hintergrundfarbe
    ClearRed: GLclampd;       // rotanteil der hintergrundfarbe
    ClearGreen: GLclampd;     // grünanteil der hintergrundfarbe
    ClearBlue: GLclampd;      // blauanteil der hintergrundfarbe
  public
    .
    .
    .
  published
    .
    .
    .

var
  FExample: TFExample;

  FxStart,                     // berechnung der mausbewegungen.
  FxDelta,                     // delta = aktuelle position minus start
  FyStart,                     // start wird erfasst sobald eine maustaste
  FyDelta:integer;             // gedrückt wird.

  FxRot,                       // umrechnung von delta in rotation wenn
  FyRot:double;                // drehung gewünscht ist (je nach taste)

  FMousePressX,                // aktuelle mausposition, wenn maustaste gedrückt wird
  FMousePressY: integer;
  FMousePosX,                  // aktuelle mausposition
  FMousePosY: integer;

  //mausaktivität überprüfen
  FRightMousePressed:boolean;  // ist die rechte maustaste gedrückt?
  FLeftMousePressed:boolean;   // ist die linke maustaste gedrückt?

const
  crCursorMove = 1;
  crCursorRotate = 2;
  crCursorSelect = 3;

implementation

uses ...

{$R *.dfm}
{$R cursors.res}
procedure TFExample.FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
begin
  // mausposition merken
  FMousePosX := X;
  FMousePosY := Y;

   //das Ziehen der Szene kann nur bei gedrückter Maustaste passieren
  if not (FRightMousePressed or FLeftMousePressed) then exit;

   //ausrechenen um wieviel der Mauszeiger bewegt wurde
   FxDelta := FxStart-X;
   FyDelta := FyStart-Y;

   //Rotation anpassen, damit es nicht zu schnell wird
   FxRot := FxRot - FyDelta/20;
   Fyrot := FyRot - FxDelta/20;

   //das naechste mal ist das hier unser startpunkt:
   FxStart := X;
   FyStart := Y;

   if FRightMousePressed then
   begin
     if FxRot <> 0 then FCamera.RotateCamera (FxRot, 0, 0);
     if FyRot <> 0 then FCamera.RotateCamera (0, FyRot, 0);
   end;
   if FLeftMousePressed then
   begin
     if FxRot <> 0 then FCamera.TranslateCamera (FxRot, 0, 0);
     if FyRot <> 0 then FCamera.TranslateCamera (0, FyRot, 0);
   end;
   Paint;

   FxRot := 0;
   FyRot := 0;
end;
procedure TFExample.FormMouseDown(Sender: TObject; Button: TMouseButton;
                                 Shift: TShiftState; X, Y: Integer);
begin
  if Button = mbRight then
  begin
    //rechte maustaste gedrückt
    FRightMousePressed:=true;
    //Startposition merken
    FxStart:=X;
    FyStart:=Y;
    Screen.Cursor := crCursorRotate;
  end
  else if Button = mbLeft then
  begin
    //rechte maustaste gedrückt
    FLeftMousePressed:=true;
    //Startposition merken
    FxStart:=X;
    FyStart:=Y;
    Screen.Cursor := crCursorMove;
  end;
  // aktuelle Mouseposition festhalten. so kann z.B. überprüft werden 
  // welches Objekt an der aktuellen Mausposition liegt
  FMousePressX := X;
  FMousePressY := Y;
end;
procedure TFExample.FormMouseUp(Sender: TObject; Button: TMouseButton;
                               Shift: TShiftState; X, Y: Integer);
begin
  if Button = mbRight then
  begin
    FRightMousePressed:=false;
  end;
  if Button = mbLeft then
  begin
    FLeftMousePressed:=false;
  end;
  if not (FRightMousePressed or FLeftMousePressed) then
    Screen.Cursor := crCursorSelect;
end;
procedure TFExample.FormCreate(Sender: TObject);
resourcestring
  ResStrRCfailed = 'CreateRenderingContext failed ';
  ResStrWGLfailed = 'wglMakeCurrent failed ';
begin
  inherited;

  // wenn das grafiksystem von OpenGL nicht aktiviert werden kann,
  // müssen wir das programm beenden
  if not InitOpenGL then
  begin
    raise Exception.Create('InitOpenGL failed '+IntToStr(GetLastError));
    halt (100);
  end;

  FglDC := getDC(self.WindowHandle);
  FglRC := CreateRenderingContext(FglDC,
                                  [opDoubleBuffered],
                                  32, 24, 0,0,0,0);

  if FglRC=0 then
  begin
    raise Exception.Create(ResStrRCfailed + IntToStr(GetLastError));
    halt (100);
  end;

  if not wglMakeCurrent(FglDC, FglRC) then
    raise Exception.Create(ResStrWGLfailed + IntToStr(GetLastError));

  FxRot:=0;
  FyRot:=0;

  FRightMousePressed := false;
  FLeftMousePressed := false;

  Screen.Cursors[crCursorMove]   := LoadCursor(HInstance,'MOVE');
  Screen.Cursors[crCursorRotate] := LoadCursor(HInstance,'ROTATE');
  Screen.Cursors[crCursorSelect] := LoadCursor(HInstance,'SELECT');
  Screen.Cursor                  := crCursorSelect;

  ClearAlpha := 1;         // bildschirm immer mit weiß löschen
  ClearRed:= 1;            // bildschirm immer mit weiß löschen
  ClearGreen:= 1;          // bildschirm immer mit weiß löschen
  ClearBlue:= 1;           // bildschirm immer mit weiß löschen

  FCamera := TCamera.Create;
end;

Das mit den unterschiedlichen Cursordarstellungen habe ich nur als Hinweis gelassen. Diese Anweisungen müsst Ihr rausnehmen es sei denn, dass Ihr eine Resourcendatei mit drei unterschiedlichen Cursorarten erstellt und sie unter "Cursors.res" abspeichert.

Dieses Beispiel ist vereinfacht dargestellt und es ist sehr wahrscheinlich, dass Ihr daran noch etwas herumspielen müsst. Ich habe noch das Mausrad eingesetzt um in den Bildschirm hinein- oder aus ihm herauszuzoomen (TranslateCamera(0,0,?)). Durch modifizieren der Geschwindigkeit (+/-) für die einzelnen Achsen, die an die Prozeduren TranslateCamera und RotateCamera übergeben werden kann man entweder die Szene oder die Kamera bewegen.

3. Szene zeichnen:

Lichteigenschaften setzen

Materialeigenschaften setzen

... (die üblichen Vorbereitungen treffen)

FCamera.Apply

Szene zeichnen

wenn Terrain gewünscht:

 FCamera.ApplyForTerrain
 Terrain zeichnen

ende wenn

Swapbuffers...

usw.

procedure TFExample.Render;  // wird aus der Methode Paint aufgerufen
resourcestring
  RestStrWGLfailed = 'TFExample.Render: wglMakeCurrent failed with ';
begin
  // da mehrere fenster möglich sind, muss immer der aktuelle
  // ausgabekontext ausgewählt werden
  if wglMakeCurrent(FglDC,FglRC) then
  begin
    glMatrixMode (GL_MODELVIEW);

    glClearColor(ClearRed, ClearGreen, ClearBlue, ClearAlpha);
    glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);

    // View setzen

    Camera1.Apply;

    // Szene jetzt zeichnen

    glFlush;              // bearbeitung der GL-befehle beginnen
    glFinish;             // warten bis alle befehle ausgeführt sind

    SwapBuffers(FglDC);   // flackern verhindern
  end
  else
  begin
    raise Exception.Create(RestStrWGLfailed + IntToStr(GetLastError));
  end;
end;

Den Kameracode findet ihr unter Kamera (2).
Die verwendete Toolsammlung findet ihr unter Kamera (3).