Kamera (2)

Aus DGL Wiki
Wechseln zu: Navigation, Suche

unit Camera;

interface

Uses DglOpenGL, OpenGLUtil, Windows, Classes;

type

 TCameraMatrix=Class
   Matrix: TArrMatrix;
   InverseMatrix: TArrMatrix;
   procedure Identity;
   procedure Load(M: TArrMatrix);
   constructor Create;
 end;
 TCamera=Class
   CameraMatrix: TCameraMatrix;
   Enabled  : boolean;
   Initiated: boolean;
   constructor Create;
   destructor Destroy;
   function Position: TGLvector;
   function UpVector: TGLvector;
   function ViewDirection: TGLvector;
   procedure RestorePosition(pos: integer);
   procedure SavePosition(pos: integer);
   procedure RotateCamera(ix, iy, iz: TGLdouble);
   procedure TranslateCamera(ix, iy, iz: TGLdouble);
   procedure CameraHome;
   procedure PositionCamera(PositionVec: TGLvector; ViewVec: TGLvector; upVec: TGLvector);
   procedure Adjust;
   procedure Apply;
 private
   HomeMatrix: TCameraMatrix;
   PosArray: array [0..9] of TCameraMatrix;
   FPointOfRotation: TGLvector;
   procedure Identity;
   procedure RotateMatrix(ix, iy, iz: TGLdouble);
   procedure Offset(x, y, z: TGLfloat);
   procedure RotateRoundAxis(rx, ry, rz: TGLfloat);
 published
   property PointOfRotation: TGLvector read FPointOfRotation;
 end;
 TPCamera=^TCamera;

implementation

constructor TCameraMatrix.Create; begin

 Identity; // beim erzeugen der Matrix wird die Identitätsmatrix zugewiesen

end;

procedure TCameraMatrix.Identity; var

 i: integer;

begin

 Matrix := GetArrIdentity; // die Funktion GetArrIdentity findet Ihr in der Datei OpenGL.pas
 InverseMatrix := GetArrIdentity;

end;

procedure TCameraMatrix.Load(M: TArrMatrix); var

 i: integer;

begin

 for i:=0 to 15 do
   Matrix[i]:=M[i]; // die Matrix mit den Werten einer beliebigen anderen matrix füllen
 InvertMatrix (M, InverseMatrix); // die inverse Matrix erzeugen
 // die invertierte Matrix kann benutzt werden um Objkekte immer zum Benutzer auszurichten

end;

procedure TCamera.RotateRoundAxis(rx, ry, rz: TGLfloat); // hier drehen wir jetzt um die einzelnen Achsen. // die Parameter geben die "Drehgeschwindigkeit" vor. var

 newMatrix: TArrMatrix;

begin

 glMatrixMode (GL_MODELVIEW);
 glPushMatrix();
 glLoadMatrixf(@CameraMatrix.Matrix);  // aktuelle Position und Lage der Kamera herstellen
 if(rx <> 0) then
   glRotatef(rx,1,0,0);                // wenn gewünscht um die X-Achse drehen
 if(ry <> 0) then
   glRotatef(ry,0,1,0);                // wenn gewünscht um die Y-Achse drehen
 if(rz <> 0) then
   glRotatef(rz,0,0,1);                // wenn gewünscht um die Z-Achse drehen
 glGetFloatv(GL_MODELVIEW_MATRIX, @newMatrix); // die neu erzeugte Matrix auslesen
 CameraMatrix.Load(newMatrix);         // und in die Kameramatrix sichern
 glPopMatrix();

end;

constructor TCamera.Create; var

 i: integer;

begin

 // Initiated wird gebraucht um einmal alle Positionsspeicher 
 // mit der Anfangsposition zu belegen
 Initiated := false;
 // Kameramatrix anlegen
 CameraMatrix := TCameraMatrix.Create;
 // Matrix der letzten Position von PositionCamera anlegen
 HomeMatrix := TCameraMatrix.Create;
 // Positionsspeicher anlegen
 for i := 0 to 9 do
   PosArray[i] := TCameraMatrix.Create;

end;

procedure TCamera.Identity; begin

 CameraMatrix.Identity;
 HomeMatrix.Identity;
 Enabled := true;

end;

destructor TCamera.Destroy; var

 i: integer;

begin

 HomeMatrix.Free;
 CameraMatrix.Free;
 for i := 0 to 9 do
   PosArray[i].Free;

end;

procedure TCamera.Offset(x, y, z: TGLfloat); var

 newMatrix: TArrMatrix;

begin

 glMatrixMode (GL_MODELVIEW);
 glPushMatrix();
 glLoadIdentity;
 glTranslatef(x,y,z);
 glGetFloatv(GL_MODELVIEW_MATRIX, @newMatrix);
 // wenn ich mit der funktion glMultMatrixf arbeite, wird die zeichnung
 // immer entlang der richtigen achsen verschoben. wenn ich matrixmultiply
 // nehme, wird sie auf den bildschirmachsen verschoben. das ist angenehmer
 // zum arbeiten
 MatrixMultiply (newMatrix, CameraMatrix.Matrix, newMatrix);
 CameraMatrix.Load(newMatrix);
 glPopMatrix();

end;

procedure TCamera.PositionCamera(PositionVec: TGLvector; ViewVec: TGLvector; upVec: TGLvector); var

 newMatrix: TArrMatrix;
 i: integer;

begin

 Identity;
 FPointOfRotation := ViewVec;
 glMatrixMode (GL_MODELVIEW);
 glPushMatrix;
 glLoadIdentity;
 glTranslatef (PositionVec.X, PositionVec.Y, PositionVec.Z);
 gluLookAt (PositionVec.X, PositionVec.Y, PositionVec.Z,
            ViewVec.X, ViewVec.Y, ViewVec.Z,
            upVec.X, upVec.Y, upVec.Z);
 glGetFloatv(GL_MODELVIEW_MATRIX, @newMatrix);
 CameraMatrix.Load(newMatrix);
 HomeMatrix.Load(newMatrix);
 glPopMatrix;
 if not Initiated then
 begin
   for i := 0 to 9 do
     SavePosition (i);
   Initiated := true;
 end;

end;

procedure TCamera.CameraHome; // Move the camera to the home position begin

 CameraMatrix.Load(HomeMatrix.Matrix);

end;

procedure TCamera.SavePosition (pos: integer); begin

 if (pos < 0) or (pos > 9) then
   exit;
PosArray[pos].Load(CameraMatrix.Matrix);

end;

procedure TCamera.RestorePosition (pos: integer); begin

 if (pos < 0) or (pos > 9) then
   exit;
CameraMatrix.Load(PosArray[pos].Matrix);

end;

procedure TCamera.TranslateCamera(ix, iy, iz: TGLdouble); begin

 Offset (ix, iy, iz);

end;

procedure TCamera.RotateCamera(ix, iy, iz: TGLdouble); begin

 RotateMatrix (ix, iy, iz);

end;

procedure TCamera.Apply; begin

 if not Enabled then
   exit;

glMatrixMode (GL_MODELVIEW); glLoadMatrixf(@CameraMatrix.Matrix); glTranslatef (-PointOfRotation.X, -PointOfRotation.y, -PointOfRotation.Z);

end;

procedure TCamera.RotateMatrix (ix, iy, iz: TGLdouble); begin

 RotateRoundAxis (iy, ix, iz);

end;

function TCamera.Position: TGLvector; var

 return: TGLvector;

begin

 // position: letzte Spalte der Matrix
 InitVector (return,
             CameraMatrix.Matrix[12],
             CameraMatrix.Matrix[13],
             CameraMatrix.Matrix[14]);
 result := return;

end;

function TCamera.ViewDirection: TGLvector; var

 return: TGLvector;

begin

 // view direction: dritte Spalte der Matrix (Z-Achse)
 InitVector (return,
             CameraMatrix.Matrix[08],
             CameraMatrix.Matrix[09],
             CameraMatrix.Matrix[10]);
 result := return;

end;

function TCamera.UpVector: TGLvector; var

 return: TGLvector;

begin

 // upVector: zweite Spalte der Matrix (Y-Achse)
 InitVector (return,
             CameraMatrix.Matrix[04],
             CameraMatrix.Matrix[05],
             CameraMatrix.Matrix[06]);
result := return;

end;

procedure TCamera.Adjust; var

 temp: TArrMatrix;

begin

 // kamera senkrecht zur Y-Achse ausrichten
 // position beibehalten
 temp := GetArrIdentity;
 temp[12] := CameraMatrix.Matrix[12];
 temp[13] := CameraMatrix.Matrix[13];
 temp[14] := CameraMatrix.Matrix[14];
 temp[15] := CameraMatrix.Matrix[15];
 CameraMatrix.Load(temp);

end;

end.