Brainer
02-12-2007, 10:11 AM
System: Windows XP SP1, Pentium D 805 2,66 GHz 2 GB RAM, GeForce 7600 GS
Compiler/IDE: Delphi 2007
Libraries/API: JEDI-SDL
---
Hello again. :)
This time I've got a different problem. I want to make a camera class for my engine. So far, I've got this:
type
{ .: TCoordinates :. }
TCoordinates = class(TPersistent)
private
{ Private declarations }
FVec: TAffineVector;
function GetVecAsString(): String;
public
{ Public declarations }
constructor Create();
procedure Assign(Source: TPersistent); override;
property X: Single read FVec[0] write FVec[0];
property Y: Single read FVec[1] write FVec[1];
property Z: Single read FVec[2] write FVec[2];
property AsVector: TAffineVector read FVec;
property AsString: String read GetVecAsString;
end;
{ .: TCamera :. }
TCamera = class(TPersistent)
private
{ Private declarations }
FRight: TCoordinates;
FViewDir: TCoordinates;
FUp: TCoordinates;
FPos: TCoordinates;
procedure SetPos(const Value: TCoordinates);
procedure SetRight(const Value: TCoordinates);
procedure SetUp(const Value: TCoordinates);
procedure SetViewDir(const Value: TCoordinates);
protected
{ Protected declarations }
RotatedX, RotatedY, RotatedZ: Single;
public
{ Public declarations }
constructor Create();
destructor Destroy(); override;
procedure Assign(Source: TPersistent); override;
procedure Move(const ADirection: TAffineVector);
procedure RotateX(const ARotAngle: Single);
procedure RotateY(const ARotAngle: Single);
procedure RotateZ(const ARotAngle: Single);
procedure MoveForward(const ADistance: Single);
procedure MoveUpward(const ADistance: Single);
procedure StrafeRight(const ADistance: Single);
procedure Render();
property Position: TCoordinates read FPos write SetPos;
property ViewDirection: TCoordinates read FViewDir write SetViewDir;
property Right: TCoordinates read FRight write SetRight;
property Up: TCoordinates read FUp write SetUp;
end;
{ TCamera }
procedure TCamera.Assign(Source: TPersistent);
begin
if (Source is TCamera) then
begin
FPos.Assign(TCamera(Source).Position);
FViewDir.Assign(TCamera(Source).ViewDirection);
FRight.Assign(TCamera(Source).Right);
FUp.Assign(TCamera(Source).Up);
end else
inherited;
end;
constructor TCamera.Create;
begin
inherited Create();
FPos := TCoordinates.Create();
FViewDir := TCoordinates.Create();
FViewDir.Z := -1.0;
FRight := TCoordinates.Create();
FRight.X := 1.0;
FUp := TCoordinates.Create();
FUp.Y := 1.0;
RotatedX := 0.0;
RotatedY := 0.0;
RotatedZ := 0.0;
end;
destructor TCamera.Destroy;
begin
FPos.Free();
FViewDir.Free();
FRight.Free();
FUp.Free();
inherited Destroy();
end;
procedure TCamera.Move(const ADirection: TAffineVector);
begin
with FPos do
begin
X := X + ADirection[0];
Y := Y + ADirection[1];
Z := Z + ADirection[2];
end;
end;
procedure TCamera.MoveForward(const ADistance: Single);
var
V: TAffineVector;
begin
V := FPos.AsVector;
V := VectorAdd(V, VectorScale(FViewDir.AsVector, -ADistance));
FPos.X := V[0];
FPos.Y := V[1];
FPos.Z := V[2];
end;
procedure TCamera.MoveUpward(const ADistance: Single);
var
V: TAffineVector;
begin
V := FPos.AsVector;
V := VectorAdd(V, VectorScale(FUp.AsVector, ADistance));
FPos.X := V[0];
FPos.Y := V[1];
FPos.Z := V[2];
end;
procedure TCamera.Render;
var
V: TAffineVector;
begin
V := VectorAdd(FPos.AsVector, FViewDir.AsVector);
gluLookAt(FPos.X, FPos.Y, FPos.Z, V[0], V[1], V[2], FUp.X, FUp.Y, FUp.Z);
end;
procedure TCamera.RotateX(const ARotAngle: Single);
var
V, V1, V2: TAffineVector;
begin
RotatedX := RotatedX + ARotAngle;
V := FViewDir.AsVector;
V1 := FUp.AsVector;
V := VectorScale(V, Cos(ARotAngle * PIDIV180));
V1 := VectorScale(V1, Sin(ARotAngle * PIDIV180));
V := VectorNormalize(VectorAdd(V, V1));
V2 := VectorCrossProduct(V, FRight.AsVector);
V2 := VectorScale(V2, -1.0);
FViewDir.X := V[0];
FViewDir.Y := V[1];
FViewDir.Z := V[2];
FUp.X := V2[0];
FUp.Y := V2[1];
FUp.Z := V2[2];
end;
procedure TCamera.RotateY(const ARotAngle: Single);
var
V, V1, V2: TAffineVector;
begin
RotatedY := RotatedY + ARotAngle;
V := FViewDir.AsVector;
V1 := FRight.AsVector;
V := VectorScale(V, Cos(ARotAngle * PIDIV180));
V1 := VectorScale(V1, Sin(ARotAngle * PIDIV180));
V := VectorNormalize(VectorSubtract(V, V1));
V2 := VectorCrossProduct(V, FUp.AsVector);
FViewDir.X := V[0];
FViewDir.Y := V[1];
FViewDir.Z := V[2];
FRight.X := V2[0];
FRight.Y := V2[1];
FRight.Z := V2[2];
end;
procedure TCamera.RotateZ(const ARotAngle: Single);
var
V, V1, V2: TAffineVector;
begin
RotatedZ := RotatedZ + ARotAngle;
V := FRight.AsVector;
V1 := FUp.AsVector;
V := VectorScale(V, Cos(ARotAngle * PIDIV180));
V1 := VectorScale(V1, Sin(ARotAngle * PIDIV180));
V := VectorNormalize(VectorAdd(V, V1));
V2 := VectorCrossProduct(FViewDir.AsVector, V);
V2 := VectorScale(V2, -1.0);
FRight.X := V[0];
FRight.Y := V[1];
FRight.Z := V[2];
FUp.X := V2[0];
FUp.Y := V2[1];
FUp.Z := V2[2];
end;
procedure TCamera.SetPos(const Value: TCoordinates);
begin
FPos := Value;
end;
procedure TCamera.SetRight(const Value: TCoordinates);
begin
FRight := Value;
end;
procedure TCamera.SetUp(const Value: TCoordinates);
begin
FUp := Value;
end;
procedure TCamera.SetViewDir(const Value: TCoordinates);
begin
FViewDir := Value;
end;
procedure TCamera.StrafeRight(const ADistance: Single);
var
V: TAffineVector;
begin
V := FPos.AsVector;
V := VectorAdd(V, VectorScale(FRight.AsVector, ADistance));
FPos.X := V[0];
FPos.Y := V[1];
FPos.Z := V[2];
end;
But this class is working wrong for me. Could you fix it for me, please? :wink: Or maybe you know other solutions of the problem? :? I've heard that a quaternion-based camera system is good and the most efficient. Is that true?
Thank you in advance
Compiler/IDE: Delphi 2007
Libraries/API: JEDI-SDL
---
Hello again. :)
This time I've got a different problem. I want to make a camera class for my engine. So far, I've got this:
type
{ .: TCoordinates :. }
TCoordinates = class(TPersistent)
private
{ Private declarations }
FVec: TAffineVector;
function GetVecAsString(): String;
public
{ Public declarations }
constructor Create();
procedure Assign(Source: TPersistent); override;
property X: Single read FVec[0] write FVec[0];
property Y: Single read FVec[1] write FVec[1];
property Z: Single read FVec[2] write FVec[2];
property AsVector: TAffineVector read FVec;
property AsString: String read GetVecAsString;
end;
{ .: TCamera :. }
TCamera = class(TPersistent)
private
{ Private declarations }
FRight: TCoordinates;
FViewDir: TCoordinates;
FUp: TCoordinates;
FPos: TCoordinates;
procedure SetPos(const Value: TCoordinates);
procedure SetRight(const Value: TCoordinates);
procedure SetUp(const Value: TCoordinates);
procedure SetViewDir(const Value: TCoordinates);
protected
{ Protected declarations }
RotatedX, RotatedY, RotatedZ: Single;
public
{ Public declarations }
constructor Create();
destructor Destroy(); override;
procedure Assign(Source: TPersistent); override;
procedure Move(const ADirection: TAffineVector);
procedure RotateX(const ARotAngle: Single);
procedure RotateY(const ARotAngle: Single);
procedure RotateZ(const ARotAngle: Single);
procedure MoveForward(const ADistance: Single);
procedure MoveUpward(const ADistance: Single);
procedure StrafeRight(const ADistance: Single);
procedure Render();
property Position: TCoordinates read FPos write SetPos;
property ViewDirection: TCoordinates read FViewDir write SetViewDir;
property Right: TCoordinates read FRight write SetRight;
property Up: TCoordinates read FUp write SetUp;
end;
{ TCamera }
procedure TCamera.Assign(Source: TPersistent);
begin
if (Source is TCamera) then
begin
FPos.Assign(TCamera(Source).Position);
FViewDir.Assign(TCamera(Source).ViewDirection);
FRight.Assign(TCamera(Source).Right);
FUp.Assign(TCamera(Source).Up);
end else
inherited;
end;
constructor TCamera.Create;
begin
inherited Create();
FPos := TCoordinates.Create();
FViewDir := TCoordinates.Create();
FViewDir.Z := -1.0;
FRight := TCoordinates.Create();
FRight.X := 1.0;
FUp := TCoordinates.Create();
FUp.Y := 1.0;
RotatedX := 0.0;
RotatedY := 0.0;
RotatedZ := 0.0;
end;
destructor TCamera.Destroy;
begin
FPos.Free();
FViewDir.Free();
FRight.Free();
FUp.Free();
inherited Destroy();
end;
procedure TCamera.Move(const ADirection: TAffineVector);
begin
with FPos do
begin
X := X + ADirection[0];
Y := Y + ADirection[1];
Z := Z + ADirection[2];
end;
end;
procedure TCamera.MoveForward(const ADistance: Single);
var
V: TAffineVector;
begin
V := FPos.AsVector;
V := VectorAdd(V, VectorScale(FViewDir.AsVector, -ADistance));
FPos.X := V[0];
FPos.Y := V[1];
FPos.Z := V[2];
end;
procedure TCamera.MoveUpward(const ADistance: Single);
var
V: TAffineVector;
begin
V := FPos.AsVector;
V := VectorAdd(V, VectorScale(FUp.AsVector, ADistance));
FPos.X := V[0];
FPos.Y := V[1];
FPos.Z := V[2];
end;
procedure TCamera.Render;
var
V: TAffineVector;
begin
V := VectorAdd(FPos.AsVector, FViewDir.AsVector);
gluLookAt(FPos.X, FPos.Y, FPos.Z, V[0], V[1], V[2], FUp.X, FUp.Y, FUp.Z);
end;
procedure TCamera.RotateX(const ARotAngle: Single);
var
V, V1, V2: TAffineVector;
begin
RotatedX := RotatedX + ARotAngle;
V := FViewDir.AsVector;
V1 := FUp.AsVector;
V := VectorScale(V, Cos(ARotAngle * PIDIV180));
V1 := VectorScale(V1, Sin(ARotAngle * PIDIV180));
V := VectorNormalize(VectorAdd(V, V1));
V2 := VectorCrossProduct(V, FRight.AsVector);
V2 := VectorScale(V2, -1.0);
FViewDir.X := V[0];
FViewDir.Y := V[1];
FViewDir.Z := V[2];
FUp.X := V2[0];
FUp.Y := V2[1];
FUp.Z := V2[2];
end;
procedure TCamera.RotateY(const ARotAngle: Single);
var
V, V1, V2: TAffineVector;
begin
RotatedY := RotatedY + ARotAngle;
V := FViewDir.AsVector;
V1 := FRight.AsVector;
V := VectorScale(V, Cos(ARotAngle * PIDIV180));
V1 := VectorScale(V1, Sin(ARotAngle * PIDIV180));
V := VectorNormalize(VectorSubtract(V, V1));
V2 := VectorCrossProduct(V, FUp.AsVector);
FViewDir.X := V[0];
FViewDir.Y := V[1];
FViewDir.Z := V[2];
FRight.X := V2[0];
FRight.Y := V2[1];
FRight.Z := V2[2];
end;
procedure TCamera.RotateZ(const ARotAngle: Single);
var
V, V1, V2: TAffineVector;
begin
RotatedZ := RotatedZ + ARotAngle;
V := FRight.AsVector;
V1 := FUp.AsVector;
V := VectorScale(V, Cos(ARotAngle * PIDIV180));
V1 := VectorScale(V1, Sin(ARotAngle * PIDIV180));
V := VectorNormalize(VectorAdd(V, V1));
V2 := VectorCrossProduct(FViewDir.AsVector, V);
V2 := VectorScale(V2, -1.0);
FRight.X := V[0];
FRight.Y := V[1];
FRight.Z := V[2];
FUp.X := V2[0];
FUp.Y := V2[1];
FUp.Z := V2[2];
end;
procedure TCamera.SetPos(const Value: TCoordinates);
begin
FPos := Value;
end;
procedure TCamera.SetRight(const Value: TCoordinates);
begin
FRight := Value;
end;
procedure TCamera.SetUp(const Value: TCoordinates);
begin
FUp := Value;
end;
procedure TCamera.SetViewDir(const Value: TCoordinates);
begin
FViewDir := Value;
end;
procedure TCamera.StrafeRight(const ADistance: Single);
var
V: TAffineVector;
begin
V := FPos.AsVector;
V := VectorAdd(V, VectorScale(FRight.AsVector, ADistance));
FPos.X := V[0];
FPos.Y := V[1];
FPos.Z := V[2];
end;
But this class is working wrong for me. Could you fix it for me, please? :wink: Or maybe you know other solutions of the problem? :? I've heard that a quaternion-based camera system is good and the most efficient. Is that true?
Thank you in advance