unit Camera;

interface

uses Windows, SysUtils, Math3D, GL, GLu;

type
  TCamera = class
  protected
    FCameraPosition     : TVector3;
    FCameraDirection    : TVector3;
    FCameraOrientation  : TVector3;
    FCameraRotation     : TVector3;
    FCameraHorizont     : TVector3;
    FModelviewMatrix    : TMatrix4x4;
    procedure SetPosition(pos: TVector3); virtual;
    procedure SetDirection(dir: TVector3); virtual;
    procedure SetOrientation(ori: TVector3); virtual;
    procedure SetRotation(up: TVector3); virtual;
  public
    constructor Create; virtual;
    destructor Destroy; override;
    procedure Apply; virtual;
    procedure MoveForward(amount: single); virtual; abstract;
    procedure MoveBackward(amount: single); virtual; abstract;
    procedure MoveLeft(amount: single); virtual; abstract;
    procedure MoveRight(amount: single); virtual; abstract;
    procedure MoveUp(amount: single); virtual; abstract;
    procedure MoveDown(amount: single); virtual; abstract;
    procedure TurnLeft(degree: single); virtual; abstract;
    procedure TurnRight(degree: single); virtual; abstract;
    procedure BendDown(degree: single); virtual; abstract;
    procedure BendUp(degree: single); virtual; abstract;
    procedure LeanLeft(degree: single); virtual; abstract;
    procedure LeanRight(degree: single); virtual; abstract;
    property Position: TVector3 read FCameraPosition write SetPosition;
    property Direction: TVector3 read FCameraDirection write SetDirection;
    property Orientation: TVector3 read FCameraOrientation write SetOrientation;
    property Rotation: TVector3 read FCameraRotation write SetRotation;
    property ModelviewMatrix: TMatrix4x4 read FModelviewMatrix;
  end;

implementation

constructor TCamera.Create;
begin
  inherited Create;

  FCameraPosition       := Vector3(0, 0, 0);
  FCameraDirection      := Vector3(0, 0,-1);
  FCameraOrientation    := Vector3(0, 0,-1);
  FCameraRotation       := Vector3(0, 1, 0);
  FCameraHorizont       := VecCross3(FCameraDirection, FCameraRotation);
end;

destructor TCamera.Destroy;
begin
  inherited Destroy;
end;

procedure TCamera.Apply;
begin
  glLoadIdentity;
  gluLookAt(FCameraPosition.x,
            FCameraPosition.y,
            FCameraPosition.z,
            FCameraOrientation.x,
            FCameraOrientation.y,
            FCameraOrientation.z,
            FCameraRotation.x,
            FCameraRotation.y,
            FCameraRotation.z);
  glGetFloatv(GL_MODELVIEW_MATRIX, @FModelviewMatrix);
end;

procedure TCamera.SetPosition;
begin
  FCameraPosition := pos;
  FCameraOrientation := VecAdd3(FCameraPosition, FCameraDirection);
end;

procedure TCamera.SetDirection;
begin
  VecNormalize3(dir);
  FCameraDirection := dir;
  FCameraOrientation := VecAdd3(FCameraPosition, FCameraDirection);
  FCameraHorizont := VecCross3(FCameraDirection, FCameraRotation);
end;

procedure TCamera.SetOrientation;
begin
  FCameraOrientation := ori;
  FCameraDirection := VecSubtract3(FCameraOrientation, FCameraPosition);
  VecNormalize3(FCameraDirection);
  FCameraHorizont := VecCross3(FCameraDirection, FCameraRotation);
end;

procedure TCamera.SetRotation;
begin
  VecNormalize3(up);
  FCameraRotation := up;
  FCameraHorizont := VecCross3(FCameraDirection, FCameraRotation);
end;

end.
