Files
lace/4-high/gel/source/gel-rig.ads
2022-07-31 17:34:54 +10:00

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;