Kamera (2)
Aus DGL Wiki
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;
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;<br>
PosArray[pos].Load(CameraMatrix.Matrix);
end;
procedure TCamera.RestorePosition (pos: integer);
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;
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;
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.