Back to... GLOBE_3D

Source file : actors.adb


with GL, GL.Math;
with GLOBE_3D.Math;

package body Actors is

  use GLOBE_3D, GLOBE_3D.Math, GLOBE_3D.REF, Game_control, GL, GL.Math;

  procedure Limited_Translation(
    actor         : in out GLOBE_3D.Camera;
    gc            : Game_control.Command_set;
    gx,gy         : GLOBE_3D.Real;
    unitary_change: GLOBE_3D.Real;
    deceleration  : GLOBE_3D.Real;
    time_step     : GLOBE_3D.Real
  )
  is
    unitary_movement, eye_movement: Real;
    step: Vector_3D;
  begin
    if gc( run_mode ) then
      unitary_movement:= 300.0;
    else
      unitary_movement:= 100.0;
    end if;
    unitary_movement:= unitary_movement * unitary_change;
    eye_movement:= unitary_movement * 2.0;

    if gc( go_forward ) then
      actor.speed(2):= actor.speed(2) - eye_movement;
    elsif gc( go_backwards ) then
      actor.speed(2):= actor.speed(2) + eye_movement;
    end if;

    if gc( slide_vertical_graduated ) then
      actor.speed(1):= actor.speed(1) + gy * 2.0 * unitary_movement;
    elsif gc( slide_down ) then
      actor.speed(1):= actor.speed(1) - eye_movement;
    elsif gc( slide_up ) then
      actor.speed(1):= actor.speed(1) + eye_movement;
    end if;

    if gc( slide_lateral_graduated ) then
      actor.speed(0):= actor.speed(0) + gx * 2.0 * unitary_movement;
    elsif gc( slide_left ) then
      actor.speed(0):= actor.speed(0) - eye_movement;
    elsif gc( slide_right ) then
      actor.speed(0):= actor.speed(0) + eye_movement;
    end if;

    step:=
      time_step * (Transpose(actor.world_rotation) * actor.speed);
      --  ( speed(0),    -- lateral sliding
      --    speed(1),    -- vertical sliding
      --    speed(2) );  -- forward/backwards
      --   -- ^ vector in the local referential

    Limiting(step);

    actor.clipper.eye_position:= actor.clipper.eye_position + step;

    actor.speed:= deceleration * actor.speed;

  end Limited_Translation;

  procedure No_Limitation(step: in out GLOBE_3D.Vector_3D) is
  null;

  procedure Translation_inst is new Limited_Translation(No_Limitation);

  procedure Translation(
    actor         : in out GLOBE_3D.Camera;
    gc            : Game_control.Command_set;
    gx,gy         : GLOBE_3D.Real;
    unitary_change: GLOBE_3D.Real;
    deceleration  : GLOBE_3D.Real;
    time_step     : GLOBE_3D.Real
  )
  renames Translation_inst;

  procedure Rotation(
    actor         : in out GLOBE_3D.Camera;
    gc            : Game_control.Command_set;
    gx,gy         : GLOBE_3D.Real;
    unitary_change: GLOBE_3D.Real;
    deceleration  : GLOBE_3D.Real;
    time_step     : GLOBE_3D.Real
  )
  is
    incremental_rotation: Vector_3D := (0.0, 0.0, 0.0);
  begin
    Abstract_rotation(
      gc,gx,gy,
      unitary_change, deceleration, incremental_rotation, time_step,
      actor.rotation_speed
    );
    actor.rotation:= actor.rotation + incremental_rotation;
    if actor.compose_rotations then
      actor.world_rotation:=
        XYZ_rotation(incremental_rotation) * actor.world_rotation;
      Re_Orthonormalize(actor.world_rotation);
    else
      declare
        r: Vector_3D renames actor.rotation;
        -- We need to turn around the axes in this order: Y, X, Z
      begin
        actor.world_rotation:=
          XYZ_rotation(  0.0,  0.0, r(2) ) *  -- 3) turn around the nose
          XYZ_rotation( r(0),  0.0,  0.0 ) *  -- 2) lift or lower the head
          XYZ_rotation(  0.0, r(1),  0.0 )    -- 1) pivotate around the feet
        ;
      end;
    end if;
  end Rotation;

  procedure Abstract_rotation(
    gc            : Game_control.Command_set;
    gx,gy         : GLOBE_3D.Real;
    unitary_change: GLOBE_3D.Real;
    deceleration  : GLOBE_3D.Real;
    vector        : in out GLOBE_3D.Vector_3D;
    time_step     : GLOBE_3D.Real;
    rotation_speed: in out GLOBE_3D.Vector_3D
  )
  is
    unitary_movement, mouse_rotation, key_rotation: Real;
  begin
    if gc( run_mode ) then
      unitary_movement:= 40.0;
    else
      unitary_movement:= 20.0;
    end if;
    unitary_movement:= unitary_movement * unitary_change;
    mouse_rotation:= 2.0  * unitary_movement;
    key_rotation  := 0.17 * unitary_movement;

    if gc( swing_plus  ) then rotation_speed(2):= rotation_speed(2) + key_rotation; end if;
    if gc( swing_minus ) then rotation_speed(2):= rotation_speed(2) - key_rotation; end if;
    if gc( turn_left   ) then rotation_speed(1):= rotation_speed(1) + key_rotation; end if;
    if gc( turn_right  ) then rotation_speed(1):= rotation_speed(1) - key_rotation; end if;
    if gc( turn_up     ) then rotation_speed(0):= rotation_speed(0) - key_rotation; end if;
    if gc( turn_down   ) then rotation_speed(0):= rotation_speed(0) + key_rotation; end if;
    if gc( turn_lateral_graduated ) then
      rotation_speed(1):= rotation_speed(1) - gx * mouse_rotation;
    end if;
    if gc( turn_vertical_graduated ) then
      rotation_speed(0):= rotation_speed(0) - gy * mouse_rotation;
    end if;
    vector:= vector + time_step * rotation_speed;
    rotation_speed:= deceleration * rotation_speed;
  end Abstract_rotation;

  procedure Abstract_rotation(
    gc            : Game_control.Command_set;
    gx,gy         : GLOBE_3D.Real;
    unitary_change: GLOBE_3D.Real;
    deceleration  : GLOBE_3D.Real;
    matrix        : in out GLOBE_3D.Matrix_33;
    time_step     : GLOBE_3D.Real;
    rotation_speed: in out GLOBE_3D.Vector_3D
  )
  is
    incremental_rotation: Vector_3D := (0.0, 0.0, 0.0);
  begin
    Abstract_rotation(
      gc, gx,gy,
      unitary_change, deceleration, incremental_rotation, time_step,
      rotation_speed
    );
    matrix:= matrix * XYZ_rotation(incremental_rotation);
  end Abstract_rotation;

end Actors;

GLOBE_3D: Ada library for real-time 3D rendering. Ada programming.