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; // beim erzeugen der Matrix wird die Identitätsmatrix zugewiesen begin

 Identity;

end;
procedure TCameraMatrix.Identity; // die Funktion GetArrIdentity findet Ihr in der Datei OpenGL.pas var

 i: integer;

begin

 Matrix := GetArrIdentity;
 InverseMatrix := GetArrIdentity;

end;
procedure TCameraMatrix.Load(M: TArrMatrix); // die Matrix mit den Werten einer beliebigen anderen matrix füllen var

 i: integer;

begin

 for i:=0 to 15 do
   Matrix[i]:=M[i];
 InvertMatrix (M, InverseMatrix);

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