Kamera (2): Unterschied zwischen den Versionen

Aus DGL Wiki
Wechseln zu: Navigation, Suche
K
Zeile 51: Zeile 51:
  
 
constructor TCameraMatrix.Create;
 
constructor TCameraMatrix.Create;
 +
// beim erzeugen der Matrix wird die Identitätsmatrix zugewiesen
 
begin
 
begin
   Identity; // beim erzeugen der Matrix wird die Identitätsmatrix zugewiesen
+
   Identity;
 
end;
 
end;
  
 
procedure TCameraMatrix.Identity;
 
procedure TCameraMatrix.Identity;
 +
// die Funktion GetArrIdentity findet Ihr in der Datei OpenGL.pas
 
var
 
var
 
   i: integer;
 
   i: integer;
 
begin
 
begin
   Matrix := GetArrIdentity; // die Funktion GetArrIdentity findet Ihr in der Datei OpenGL.pas
+
   Matrix := GetArrIdentity;  
 
   InverseMatrix := GetArrIdentity;
 
   InverseMatrix := GetArrIdentity;
 
end;
 
end;
  
 
procedure TCameraMatrix.Load(M: TArrMatrix);
 
procedure TCameraMatrix.Load(M: TArrMatrix);
 +
// die Matrix mit den Werten einer beliebigen anderen matrix füllen
 
var
 
var
 
   i: integer;
 
   i: integer;
 
begin
 
begin
 
   for i:=0 to 15 do
 
   for i:=0 to 15 do
     Matrix[i]:=M[i]; // die Matrix mit den Werten einer beliebigen anderen matrix füllen
+
     Matrix[i]:=M[i];  
 +
  // die invertierte Matrix kann benutzt werden um Objkekte z.B.
 +
  // immer zum Benutzer auszurichten
 
   InvertMatrix (M, InverseMatrix); // die inverse Matrix erzeugen
 
   InvertMatrix (M, InverseMatrix); // die inverse Matrix erzeugen
  // die invertierte Matrix kann benutzt werden um Objkekte immer zum Benutzer auszurichten
 
 
end;
 
end;
  
Zeile 81: Zeile 85:
 
   glMatrixMode (GL_MODELVIEW);
 
   glMatrixMode (GL_MODELVIEW);
 
   glPushMatrix();
 
   glPushMatrix();
   glLoadMatrixf(@CameraMatrix.Matrix);  // aktuelle Position und Lage der Kamera herstellen
+
  // aktuelle Position und Lage der Kamera herstellen
 +
   glLoadMatrixf(@CameraMatrix.Matrix);   
 +
  // wenn gewünscht um die X-Achse drehen
 
   if(rx <> 0) then
 
   if(rx <> 0) then
     glRotatef(rx,1,0,0);                // wenn gewünscht um die X-Achse drehen
+
     glRotatef(rx,1,0,0);                 
 +
  // wenn gewünscht um die Y-Achse drehen
 
   if(ry <> 0) then
 
   if(ry <> 0) then
     glRotatef(ry,0,1,0);                // wenn gewünscht um die Y-Achse drehen
+
     glRotatef(ry,0,1,0);                 
 +
  // wenn gewünscht um die Z-Achse drehen
 
   if(rz <> 0) then
 
   if(rz <> 0) then
     glRotatef(rz,0,0,1);                // wenn gewünscht um die Z-Achse drehen
+
     glRotatef(rz,0,0,1);                 
   glGetFloatv(GL_MODELVIEW_MATRIX, @newMatrix); // die neu erzeugte Matrix auslesen
+
  // die neu erzeugte Matrix auslesen
   CameraMatrix.Load(newMatrix);        // und in die Kameramatrix sichern
+
   glGetFloatv(GL_MODELVIEW_MATRIX, @newMatrix);  
 +
  // und in die Kameramatrix sichern
 +
   CameraMatrix.Load(newMatrix);         
 
   glPopMatrix();
 
   glPopMatrix();
 
end;
 
end;
Zeile 118: Zeile 128:
  
 
destructor TCamera.Destroy;
 
destructor TCamera.Destroy;
 +
// alle belegten Resourcen wieder freigeben
 
var
 
var
 
   i: integer;
 
   i: integer;
Zeile 128: Zeile 139:
  
 
procedure TCamera.Offset(x, y, z: TGLfloat);
 
procedure TCamera.Offset(x, y, z: TGLfloat);
 +
// verschieben der Kamera auf einer beliebigen Achse
 
var
 
var
 
   newMatrix: TArrMatrix;
 
   newMatrix: TArrMatrix;
Zeile 146: Zeile 158:
  
 
procedure TCamera.PositionCamera(PositionVec: TGLvector; ViewVec: TGLvector; upVec: TGLvector);
 
procedure TCamera.PositionCamera(PositionVec: TGLvector; ViewVec: TGLvector; upVec: TGLvector);
 +
// erstes positionieren der kamera. hierbei werden einige initialisierungen vorgenommen
 
var
 
var
 
   newMatrix: TArrMatrix;
 
   newMatrix: TArrMatrix;
 
   i: integer;
 
   i: integer;
 
begin
 
begin
 +
  // alle kameraeinstellungen zurücknehmen
 
   Identity;
 
   Identity;
 +
  // den aktuellen drehpunkt setzen
 
   FPointOfRotation := ViewVec;
 
   FPointOfRotation := ViewVec;
 +
  // an die arbeit...
 
   glMatrixMode (GL_MODELVIEW);
 
   glMatrixMode (GL_MODELVIEW);
 
   glPushMatrix;
 
   glPushMatrix;
Zeile 163: Zeile 179:
 
   HomeMatrix.Load(newMatrix);
 
   HomeMatrix.Load(newMatrix);
 
   glPopMatrix;
 
   glPopMatrix;
 +
  // alle positionsspeicher mit der Kameraposition, Blickrichtung und dem
 +
  // upVector belegen. Nur beim ersten Aufruf von PositionCamera
 
   if not Initiated then
 
   if not Initiated then
 
   begin
 
   begin
Zeile 172: Zeile 190:
  
 
procedure TCamera.CameraHome;
 
procedure TCamera.CameraHome;
// Move the camera to the home position
+
// Kamera in die beim letzten Aufruf von PositionCamera übergebene
 +
// Position/Lage bringen
 
begin
 
begin
 
   CameraMatrix.Load(HomeMatrix.Matrix);
 
   CameraMatrix.Load(HomeMatrix.Matrix);
Zeile 178: Zeile 197:
  
 
procedure TCamera.SavePosition (pos: integer);
 
procedure TCamera.SavePosition (pos: integer);
 +
// wie der Prozedurname schon sagt...
 
begin
 
begin
 
   if (pos < 0) or (pos > 9) then
 
   if (pos < 0) or (pos > 9) then
Zeile 185: Zeile 205:
  
 
procedure TCamera.RestorePosition (pos: integer);
 
procedure TCamera.RestorePosition (pos: integer);
 +
// wie der Prozedurname schon sagt...
 
begin
 
begin
 
   if (pos < 0) or (pos > 9) then
 
   if (pos < 0) or (pos > 9) then
Zeile 202: Zeile 223:
  
 
procedure TCamera.Apply;
 
procedure TCamera.Apply;
 +
// hier wird die Kamera eingeschaltet. Nach dem Aufruf dieser Prozedur sollte die Szene
 +
// mit allen benötigten Drehungen, Verschiebungen gezeichnet werden.
 
begin
 
begin
 
   if not Enabled then
 
   if not Enabled then
Zeile 216: Zeile 239:
  
 
function TCamera.Position: TGLvector;
 
function TCamera.Position: TGLvector;
 +
// mit dieser Funktion kann die aktuelle Position der Kamera abgefragt werden
 
var
 
var
 
   return: TGLvector;
 
   return: TGLvector;
Zeile 228: Zeile 252:
  
 
function TCamera.ViewDirection: TGLvector;
 
function TCamera.ViewDirection: TGLvector;
 +
// mit dieser Funktion kann die aktuelle Blickrichtung der Kamera abgefragt werden
 
var
 
var
 
   return: TGLvector;
 
   return: TGLvector;
Zeile 240: Zeile 265:
  
 
function TCamera.UpVector: TGLvector;
 
function TCamera.UpVector: TGLvector;
 +
// mit dieser Funktion kann die aktuelle Ausrichtung der Kamera abgefragt werden
 
var
 
var
 
   return: TGLvector;
 
   return: TGLvector;
Zeile 252: Zeile 278:
  
 
procedure TCamera.Adjust;
 
procedure TCamera.Adjust;
 +
// mit dieser Prozedur kann die Kamera zu jeder Zeit, unabhängig von Drehung und Position,
 +
// senkrecht zur Y-Achse ausgerichtet werden. Die aktuelle Position wird dabei beibehalten.
 
var
 
var
 
   temp: TArrMatrix;
 
   temp: TArrMatrix;

Version vom 17. Oktober 2005, 09:45 Uhr

Eine Beschreibung findet ihr unter Kamera (1).
Die verwendete Toolsammlung findet ihr unter Kamera (3).

unit Camera;

interface

Uses DglOpenGL, OpenGLUtil, Windows, Classes;<br>

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]; 
  // die invertierte Matrix kann benutzt werden um Objkekte z.B.
  // immer zum Benutzer auszurichten
  InvertMatrix (M, InverseMatrix); // die inverse Matrix erzeugen
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;
// alle belegten Resourcen wieder freigeben
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);
// verschieben der Kamera auf einer beliebigen Achse
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);
// erstes positionieren der kamera. hierbei werden einige initialisierungen vorgenommen
var
  newMatrix: TArrMatrix;
  i: integer;
begin
  // alle kameraeinstellungen zurücknehmen
  Identity;
  // den aktuellen drehpunkt setzen
  FPointOfRotation := ViewVec;
  // an die arbeit...
  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;
  // alle positionsspeicher mit der Kameraposition, Blickrichtung und dem
  // upVector belegen. Nur beim ersten Aufruf von PositionCamera
  if not Initiated then
  begin
    for i := 0 to 9 do
      SavePosition (i);
    Initiated := true;
  end;
end;

procedure TCamera.CameraHome;
// Kamera in die beim letzten Aufruf von PositionCamera übergebene
// Position/Lage bringen
begin
  CameraMatrix.Load(HomeMatrix.Matrix);
end;

procedure TCamera.SavePosition (pos: integer);
// wie der Prozedurname schon sagt...
begin
  if (pos < 0) or (pos > 9) then
    exit;<br>
  PosArray[pos].Load(CameraMatrix.Matrix);
end;

procedure TCamera.RestorePosition (pos: integer);
// wie der Prozedurname schon sagt...
begin
  if (pos < 0) or (pos > 9) then
    exit;<br>
  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;
// hier wird die Kamera eingeschaltet. Nach dem Aufruf dieser Prozedur sollte die Szene 
// mit allen benötigten Drehungen, Verschiebungen gezeichnet werden.
begin
  if not Enabled then
    exit;<br><br>
  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;
// mit dieser Funktion kann die aktuelle Position der Kamera abgefragt werden
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;
// mit dieser Funktion kann die aktuelle Blickrichtung der Kamera abgefragt werden
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;
// mit dieser Funktion kann die aktuelle Ausrichtung der Kamera abgefragt werden
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;
// mit dieser Prozedur kann die Kamera zu jeder Zeit, unabhängig von Drehung und Position,
// senkrecht zur Y-Achse ausgerichtet werden. Die aktuelle Position wird dabei beibehalten.
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.