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;