394 lines
18 KiB
Ada
394 lines
18 KiB
Ada
with
|
|
gel.Sprite,
|
|
gel.Joint,
|
|
gel.World,
|
|
|
|
openGL,
|
|
openGL.Model,
|
|
openGL.Program,
|
|
|
|
ada.Strings.unbounded.Hash,
|
|
ada.Containers.Vectors,
|
|
ada.Containers.hashed_Maps;
|
|
|
|
private
|
|
with
|
|
collada.Library.visual_Scenes;
|
|
|
|
package gel.Rig
|
|
--
|
|
-- Provides GEL sprites which allow placing a collada skinned/rigged model into a GEL World.
|
|
--
|
|
-- The rig motion can be controlled either by normal dynamics or pre-canned animations.
|
|
--
|
|
is
|
|
type Item is tagged limited private;
|
|
type View is access all Item'Class;
|
|
|
|
type Views is array (Positive range <>) of View;
|
|
|
|
use Math;
|
|
|
|
|
|
--------------
|
|
--- Core Types
|
|
--
|
|
|
|
type motion_Mode is (Dynamics, Animation);
|
|
|
|
procedure motion_Mode_is (Self : in out Item; Now : in motion_Mode);
|
|
|
|
|
|
subtype bone_Id is ada.Strings.unbounded.unbounded_String;
|
|
|
|
null_Id : constant bone_Id := ada.Strings.unbounded.null_unbounded_String;
|
|
|
|
|
|
subtype controller_joint_Id is ada.Strings.unbounded.unbounded_String;
|
|
|
|
|
|
--------------
|
|
--- Containers
|
|
--
|
|
|
|
package inverse_bind_matrix_Vectors is new ada.Containers.Vectors (Positive, Matrix_4x4);
|
|
subtype inverse_bind_matrix_Vector is inverse_bind_matrix_Vectors.Vector;
|
|
|
|
|
|
--------------
|
|
--- Joints Ids
|
|
--
|
|
|
|
subtype gel_joint_Id is ada.Strings.unbounded.unbounded_String;
|
|
|
|
package gel_joint_id_Maps_of_gel_Joint is new ada.Containers.hashed_Maps (Key_type => gel_joint_Id,
|
|
Element_type => gel.Joint.view,
|
|
Hash => ada.Strings.unbounded.Hash,
|
|
equivalent_Keys => ada.Strings.unbounded."=",
|
|
"=" => gel.Joint."=");
|
|
subtype gel_joint_id_Map_of_gel_Joint is gel_joint_id_Maps_of_gel_Joint.Map;
|
|
|
|
|
|
package joint_Id_Maps_of_bone_site_offset is new ada.Containers.hashed_Maps (Key_type => controller_joint_Id,
|
|
Element_type => Vector_3,
|
|
Hash => ada.Strings.unbounded.Hash,
|
|
equivalent_Keys => ada.Strings.unbounded."=",
|
|
"=" => "=");
|
|
subtype joint_Id_Map_of_bone_site_offset is joint_Id_Maps_of_bone_site_offset.Map;
|
|
|
|
|
|
------------
|
|
--- Bone Ids
|
|
--
|
|
|
|
package bone_id_Maps_of_sprite is new ada.Containers.hashed_Maps (Key_type => bone_Id,
|
|
Element_type => gel.Sprite.view,
|
|
Hash => ada.Strings.unbounded.Hash,
|
|
equivalent_Keys => ada.Strings.unbounded."=",
|
|
"=" => gel.Sprite."=");
|
|
subtype bone_id_Map_of_sprite is bone_id_Maps_of_sprite.Map;
|
|
|
|
|
|
----------------
|
|
--- Bone Details
|
|
--
|
|
|
|
type bone_Details is
|
|
record
|
|
Length : math.Real := 1.0;
|
|
width_Factor,
|
|
depth_Factor : math.Real := 0.1; -- Factor * Length gives width and depth.
|
|
|
|
pitch_Limits,
|
|
yaw_Limits,
|
|
roll_Limits : gel.Sprite.DoF_Limits := (to_Radians (-15.0),
|
|
to_Radians ( 15.0));
|
|
end record;
|
|
|
|
Unspecified : constant := -1.0;
|
|
|
|
function to_Details (Length : Real := Unspecified;
|
|
width_Factor,
|
|
depth_Factor : Real := 0.1;
|
|
|
|
pitch_Limits,
|
|
yaw_Limits,
|
|
roll_Limits : gel.Sprite.DoF_Limits := (to_Radians (-15.0),
|
|
to_Radians ( 15.0))) return bone_Details;
|
|
|
|
package bone_id_Maps_of_details is new ada.Containers.hashed_Maps (Key_Type => bone_id,
|
|
Element_Type => bone_Details,
|
|
Hash => ada.Strings.unbounded.Hash,
|
|
Equivalent_Keys => ada.Strings.unbounded."=",
|
|
"=" => "=");
|
|
subtype bone_id_Map_of_details is bone_id_Maps_of_details.Map;
|
|
|
|
|
|
|
|
|
|
---------
|
|
--- Forge
|
|
--
|
|
|
|
package Forge
|
|
is
|
|
function new_Rig (in_World : in gel.World.view;
|
|
Model : in openGL.Model.view;
|
|
Mass : in Real := 0.0;
|
|
is_Kinematic : in Boolean := False) return Rig.view;
|
|
|
|
function new_Rig (bone_Sprites : in bone_id_Map_of_sprite;
|
|
joint_inv_bind_Matrices : in inverse_bind_matrix_Vector;
|
|
joint_site_Offets : in joint_Id_Map_of_bone_site_offset;
|
|
Model : in openGL.Model.view) return Rig.view;
|
|
end Forge;
|
|
|
|
|
|
procedure define (Self : in out Item; in_World : in gel.World.view;
|
|
Model : in openGL.Model.view;
|
|
Mass : in Real := 0.0;
|
|
is_Kinematic : in Boolean := False;
|
|
bone_Details : in bone_id_Map_of_details := bone_id_Maps_of_details.empty_Map);
|
|
|
|
|
|
--------------
|
|
--- Attributes
|
|
--
|
|
|
|
procedure Site_is (Self : in out Item; Now : in Vector_3);
|
|
procedure Spin_is (Self : in out Item; Now : in Matrix_3x3);
|
|
|
|
function bone_Sprites (Self : in Item) return bone_id_Map_of_sprite;
|
|
function skin_Sprite (Self : in Item'Class) return gel.Sprite.view;
|
|
function base_Sprite (Self : in Item'Class) return gel.Sprite.view;
|
|
function Sprite (Self : in Item'Class;
|
|
Bone : in bone_Id) return gel.Sprite.view;
|
|
|
|
function Joints (Self : in Item) return gel_joint_id_Map_of_gel_Joint;
|
|
|
|
procedure joint_inv_bind_Matrices_are (Self : in out Item'Class; Now : in inverse_bind_matrix_Vector);
|
|
function joint_inv_bind_Matrices (Self : in Item'Class) return inverse_bind_matrix_Vector;
|
|
|
|
function joint_site_Offets (Self : in Item'Class) return joint_Id_Map_of_bone_site_offset;
|
|
|
|
procedure assume_Pose (Self : in out Item);
|
|
procedure enable_Graphics (Self : in out Item);
|
|
procedure evolve (Self : in out Item'Class; world_Age : in Duration);
|
|
|
|
|
|
-------------
|
|
--- Animation
|
|
--
|
|
|
|
subtype scene_joint_Id is ada.Strings.unbounded.unbounded_String;
|
|
|
|
package bone_id_Maps_of_transform is new ada.Containers.hashed_Maps (Key_Type => bone_id,
|
|
Element_Type => Matrix_4x4,
|
|
Hash => ada.Strings.unbounded.Hash,
|
|
Equivalent_Keys => ada.Strings.unbounded."=",
|
|
"=" => "=");
|
|
subtype bone_id_Map_of_transform is bone_id_Maps_of_transform.Map;
|
|
|
|
procedure animation_Transforms_are (Self : in out Item'Class; Now : in bone_id_Map_of_transform);
|
|
|
|
|
|
type axis_Kind is (x_Axis, y_Axis, z_Axis);
|
|
|
|
procedure set_rotation_Angle (Self : in out Item'Class; for_Joint : in scene_joint_Id;
|
|
Axis : in Axis_Kind;
|
|
To : in Real); -- TODO: Use Radians type (and below).
|
|
procedure set_x_rotation_Angle (Self : in out Item'Class; for_Joint : in scene_joint_Id;
|
|
To : in Real);
|
|
procedure set_y_rotation_Angle (Self : in out Item'Class; for_Joint : in scene_joint_Id;
|
|
To : in Real);
|
|
procedure set_z_rotation_Angle (Self : in out Item'Class; for_Joint : in scene_joint_Id;
|
|
To : in Real);
|
|
|
|
procedure set_Location (Self : in out Item'Class; for_Joint : in scene_joint_Id;
|
|
To : in Vector_3);
|
|
procedure set_Location_x (Self : in out Item'Class; for_Joint : in scene_joint_Id;
|
|
To : in Real);
|
|
procedure set_Location_y (Self : in out Item'Class; for_Joint : in scene_joint_Id;
|
|
To : in Real);
|
|
procedure set_Location_z (Self : in out Item'Class; for_Joint : in scene_joint_Id;
|
|
To : in Real);
|
|
procedure set_Transform (Self : in out Item'Class; for_Joint : in scene_joint_Id;
|
|
To : in Matrix_4x4);
|
|
|
|
procedure update_all_global_Transforms (Self : in out Item'Class);
|
|
|
|
procedure animate (Self : in out Item; world_Age : in Duration);
|
|
procedure reset_Animation (Self : in out Item);
|
|
|
|
|
|
|
|
private
|
|
|
|
-- gl_transform_Vector
|
|
--
|
|
package gl_transform_Vectors is new ada.Containers.Vectors (Positive, openGL.Matrix_4x4);
|
|
subtype gl_transform_Vector is gl_transform_Vectors.Vector;
|
|
|
|
|
|
-- joint_id_Map_of_matrix_4x4
|
|
--
|
|
package joint_id_Maps_of_matrix_4x4 is new ada.Containers.hashed_Maps (Key_type => scene_joint_Id,
|
|
Element_type => Matrix_4x4,
|
|
Hash => ada.Strings.unbounded.Hash,
|
|
equivalent_Keys => ada.Strings.unbounded."=",
|
|
"=" => "=");
|
|
subtype joint_id_Map_of_matrix_4x4 is joint_id_Maps_of_matrix_4x4.Map;
|
|
|
|
|
|
-- joint_id_Map_of_scene_node
|
|
--
|
|
package joint_id_Maps_of_scene_node is new ada.Containers.hashed_Maps (Key_type => scene_joint_Id,
|
|
Element_type => collada.Library.visual_Scenes.Node_view,
|
|
Hash => ada.Strings.unbounded.Hash,
|
|
equivalent_Keys => ada.Strings.unbounded."=",
|
|
"=" => collada.Library.visual_Scenes."=");
|
|
subtype joint_id_Map_of_scene_node is joint_id_Maps_of_scene_node.Map;
|
|
|
|
|
|
-- joint_id_Map_of_slot
|
|
--
|
|
package joint_id_Maps_of_slot is new ada.Containers.hashed_Maps (Key_type => scene_joint_Id,
|
|
Element_type => Positive,
|
|
Hash => ada.Strings.unbounded.Hash,
|
|
equivalent_Keys => ada.Strings.unbounded."=",
|
|
"=" => "=");
|
|
subtype joint_id_Map_of_slot is joint_id_Maps_of_slot.Map;
|
|
|
|
|
|
-- skin_program_Parameters
|
|
--
|
|
type skin_program_Parameters is new opengl.Program.Parameters with
|
|
record
|
|
bone_Transforms : gl_transform_Vector;
|
|
joint_Map_of_slot : joint_id_Map_of_slot;
|
|
end record;
|
|
|
|
overriding
|
|
procedure enable (Self : in out skin_program_Parameters);
|
|
|
|
|
|
-- joint_id_Map_of_joint_id
|
|
--
|
|
package joint_id_Maps_of_joint_id is new ada.Containers.hashed_Maps (Key_type => scene_joint_Id,
|
|
Element_type => scene_joint_Id,
|
|
Hash => ada.Strings.unbounded.Hash,
|
|
equivalent_Keys => ada.Strings.unbounded."=",
|
|
"=" => ada.Strings.unbounded."=");
|
|
subtype joint_id_Map_of_joint_id is joint_id_Maps_of_joint_id.Map;
|
|
|
|
|
|
-- scene_Joint
|
|
--
|
|
type scene_Joint is
|
|
record
|
|
Node : collada.Library.visual_Scenes.Node_view;
|
|
Transform : Matrix_4x4;
|
|
end record;
|
|
|
|
package joint_id_Maps_of_scene_Joint is new ada.Containers.hashed_Maps (Key_type => scene_joint_Id,
|
|
Element_type => scene_Joint,
|
|
Hash => ada.Strings.unbounded.Hash,
|
|
equivalent_Keys => ada.Strings.unbounded."=",
|
|
"=" => "=");
|
|
subtype joint_id_Map_of_scene_Joint is joint_id_Maps_of_scene_Joint.Map;
|
|
|
|
|
|
-- Transform
|
|
--
|
|
type Transform is
|
|
record
|
|
Rotation : Quaternion := linear_Algebra_3D.to_Quaternion (linear_Algebra_3D.x_Rotation_from (0.0));
|
|
Translation : Vector_3 := [0.0, 0.0, 0.0];
|
|
end record;
|
|
|
|
type Transforms is array (Positive range <>) of Transform;
|
|
type Transforms_view is access all Transforms;
|
|
|
|
|
|
-- animation_Channel
|
|
--
|
|
type animation_Channel is
|
|
record
|
|
Target : access collada.Library.visual_Scenes.Transform;
|
|
target_Joint : scene_joint_Id;
|
|
|
|
Times : access collada.float_Array;
|
|
Values : access collada.float_Array;
|
|
|
|
Cursor : Index := 0; -- Current frame of the anmination.
|
|
|
|
initial_Angle : Real; -- For angle interpolation during 'rotation' animation.
|
|
current_Angle : Real := 0.0; --
|
|
interp_Delta : Real := 0.0; --
|
|
|
|
initial_Site : Vector_3; -- For location interpolation during 'translation' animation.
|
|
current_Site : Vector_3; --
|
|
site_interp_Delta : Vector_3; --
|
|
|
|
initial_Transform : Transform; -- For matrix interpolation during 'full_transform' animation.
|
|
current_Transform : Transform; --
|
|
slerp_Time : Real; -- Slerp Time (T) value in range '0.0 .. 1.0'. -- TODO: use 'unit_Interval' type.
|
|
Transforms : Transforms_view;
|
|
Transform_interp_Delta : Real; -- Rate at which the SLERP time parameter increases.
|
|
end record;
|
|
|
|
subtype channel_Id is scene_joint_Id;
|
|
package channel_id_Maps_of_animation_Channel is new ada.Containers.hashed_Maps (Key_Type => channel_Id,
|
|
Element_Type => animation_Channel,
|
|
Hash => ada.Strings.unbounded.Hash,
|
|
Equivalent_Keys => ada.Strings.unbounded."=",
|
|
"=" => "=");
|
|
subtype channel_id_Map_of_animation_Channel is channel_id_Maps_of_animation_Channel.Map;
|
|
|
|
|
|
-- Rig Item
|
|
--
|
|
type Item is tagged limited
|
|
record
|
|
Mode : motion_Mode := Dynamics;
|
|
|
|
joint_Sprites : bone_id_Map_of_sprite; -- Sprite to show location/rotation of joints (mainly for debugging).
|
|
bone_Sprites : bone_id_Map_of_sprite; -- A sprite for each bone.
|
|
skin_Sprite : gel.Sprite.view; -- A sprite for the skin.
|
|
|
|
bind_shape_Matrix : Matrix_4x4;
|
|
|
|
Joints : gel_joint_id_Map_of_gel_Joint;
|
|
joint_inv_bind_Matrices : inverse_bind_matrix_Vector; -- The joint inverse transforms when in the bind pose.
|
|
|
|
phys_joint_site_Offets : joint_Id_Map_of_bone_site_offset; -- Offset from the bone site to the joint site when in the bind pose.
|
|
anim_joint_site_Offets : joint_Id_Map_of_bone_site_offset; -- Offset from the bone site to the joint site when in the bind pose.
|
|
|
|
joint_pose_Transforms : joint_id_Map_of_matrix_4x4; -- The joint transforms when in the skeletal pose.
|
|
joint_Parent : joint_id_Map_of_joint_id;
|
|
|
|
collada_Joints : joint_id_Map_of_scene_node;
|
|
scene_Joints : joint_id_Map_of_scene_Joint;
|
|
root_Joint : collada.Library.visual_scenes.Node_view;
|
|
|
|
animation_Transforms : bone_id_Map_of_transform;
|
|
bone_pose_Transforms : bone_id_Map_of_transform; -- The bone transforms when in the skeletal pose.
|
|
|
|
Channels : channel_id_Map_of_animation_Channel;
|
|
start_Time : Duration := 0.0;
|
|
|
|
overall_Site : Vector_3 := [0.0, 0.0, 0.0];
|
|
|
|
Model : openGL.Model.view;
|
|
program_Parameters : aliased skin_program_Parameters;
|
|
end record;
|
|
|
|
|
|
function Parent_of (Self : in Item; the_Bone : in bone_Id) return bone_Id;
|
|
function joint_site_Offet (Self : in Item; for_Bone : in bone_Id) return Vector_3;
|
|
function joint_inv_bind_Matrix (Self : in Item; for_Bone : in bone_Id) return Matrix_4x4;
|
|
function joint_bind_Matrix (Self : in Item; for_Bone : in bone_Id) return Matrix_4x4;
|
|
|
|
|
|
end gel.Rig;
|