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

1657 lines
65 KiB
Ada

with
gel.Forge,
gel.Conversions,
physics.Model,
openGL.Model.any,
opengl.Palette,
opengl.Program .lit.colored_textured_skinned,
opengl.Geometry.lit_colored_textured_skinned,
collada.Document,
collada.Library,
collada.Library.controllers,
collada.Library.animations,
ada.Strings.unbounded,
ada.Strings.Maps;
package body gel.Rig
is
use linear_Algebra_3D;
-----------
--- Utility
--
function "+" (From : in ada.strings.unbounded.unbounded_String) return String
renames ada.strings.unbounded.to_String;
function "+" (From : in String) return ada.strings.unbounded.unbounded_String
renames ada.strings.unbounded.to_unbounded_String;
function to_gel_joint_Id (Parent, Child : in bone_Id) return gel_joint_Id
is
use ada.Strings.unbounded;
begin
return Parent & "_to_" & Child;
end to_gel_joint_Id;
function to_Math (From : in collada.Matrix_4x4) return math.Matrix_4x4
is
begin
return [1 => [From (1, 1), From (1, 2), From (1, 3), From (1, 4)],
2 => [From (2, 1), From (2, 2), From (2, 3), From (2, 4)],
3 => [From (3, 1), From (3, 2), From (3, 3), From (3, 4)],
4 => [From (4, 1), From (4, 2), From (4, 3), From (4, 4)]];
end to_Math;
pragma Unreferenced (to_Math);
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
is
begin
return (Length, width_Factor, depth_Factor,
pitch_Limits, yaw_Limits, roll_Limits);
end to_Details;
---------
--- Forge
--
package body 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
is
Self : constant Rig.view := new Rig.item;
begin
Self.define (in_World, Model, Mass, is_Kinematic);
return Self;
end new_Rig;
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
is
the_Box : constant Rig.View := new Rig.item;
begin
the_Box.bone_Sprites := bone_Sprites;
the_Box.joint_inv_bind_Matrices := joint_inv_bind_Matrices;
the_Box.phys_joint_site_Offets := joint_site_Offets;
the_Box.Model := Model;
return the_Box;
end new_Rig;
end Forge;
---------------------------
--- Skin program parameters
--
overriding
procedure enable (Self : in out skin_program_Parameters)
is
use joint_id_Maps_of_slot;
subtype Program_view is openGL.Program.lit.colored_textured_skinned.view;
Cursor : joint_id_Maps_of_slot.Cursor := Self.joint_Map_of_slot.First;
Slot : Integer;
begin
while has_Element (Cursor)
loop
Slot := Element (Cursor);
Program_view (Self.Program).bone_Transform_is (Which => Slot,
Now => Self.bone_Transforms.Element (Slot));
next (Cursor);
end loop;
end enable;
-------------
--- Animation
--
procedure define_global_Transform_for (Self : in out Item'Class; the_Joint : in collada.Library.visual_scenes.Node_view;
Slot : in out Positive)
is
use collada.Library;
which_Joint : constant scene_joint_Id := the_Joint.Id;
child_Joints : constant visual_scenes.Nodes := the_Joint.Children;
default_scene_Joint : scene_Joint;
the_global_Transform : constant Matrix_4x4 := Transpose (the_Joint.global_Transform); -- Transpose to convert to row-major.
begin
Self.joint_pose_Transforms.insert (which_Joint, the_global_Transform);
Self.collada_Joints .insert (which_Joint, the_Joint);
default_scene_Joint.Node := the_Joint;
Self.scene_Joints.insert (which_Joint, default_scene_Joint);
for i in child_Joints'Range
loop
Slot := Slot + 1;
define_global_Transform_for (Self, child_Joints (i), Slot); -- Recurse over children.
end loop;
end define_global_Transform_for;
procedure update_global_Transform_for (Self : in out Item'Class; the_Joint : in collada.Library.visual_scenes.Node_view)
is
use collada.Library,
ada.Strings.unbounded;
which_Joint : constant scene_joint_Id := the_Joint.Id;
child_Joints : constant visual_scenes.Nodes := the_Joint.Children;
the_global_Transform : constant Matrix_4x4 := math.Transpose (the_Joint.global_Transform); -- Transpose to convert to row-major.
joint_site_Offet : Vector_3;
begin
if which_Joint = Self.root_Joint.Name
then joint_site_Offet := [0.0, 0.0, 0.0];
else joint_site_Offet := Self.anim_joint_site_Offets (which_Joint);
end if;
Self.joint_pose_Transforms.replace (which_Joint, (the_global_Transform));
Self.scene_Joints (which_Joint).Transform := the_global_Transform;
declare
use type gel.Sprite.view;
the_bone_Id : constant bone_Id := which_Joint;
Site : Vector_3;
Rotation : Matrix_3x3;
begin
if Self.bone_Sprites (the_bone_Id) /= null
then
Site := get_Translation (the_global_Transform);
Site := Site - joint_site_Offet * (get_Rotation (the_global_Transform));
Site := Site * Inverse (Self.base_Sprite.Spin);
Site := Site + Self.overall_Site;
Rotation := Inverse (get_Rotation (the_global_Transform));
Rotation := Self.base_Sprite.Spin * Rotation;
Self.bone_Sprites (the_bone_Id).all.Site_is (Site);
if which_Joint /= Self.root_Joint.Name
then
Self.bone_Sprites (the_bone_Id).all.Spin_is (Rotation);
end if;
end if;
end;
for i in child_Joints'Range
loop
Self.update_global_Transform_for (child_Joints (i)); -- Recurse over children.
end loop;
end update_global_Transform_for;
procedure update_all_global_Transforms (Self : in out Item'Class)
is
begin
Self.update_global_Transform_for (Self.root_Joint); -- Re-determine all joint transforms, recursively.
end update_all_global_Transforms;
procedure set_rotation_Angle (Self : in out Item'Class; for_Joint : in scene_joint_Id;
Axis : in axis_Kind;
To : in Real)
is
begin
case Axis is
when x_Axis => Self.set_x_rotation_Angle (for_Joint, To);
when y_Axis => Self.set_y_rotation_Angle (for_Joint, To);
when z_Axis => Self.set_z_rotation_Angle (for_Joint, To);
end case;
end set_rotation_Angle;
procedure set_Location (Self : in out Item'Class; for_Joint : in scene_joint_Id;
To : in Vector_3)
is
begin
Self.scene_Joints (for_Joint).Node.set_Location (To);
end set_Location;
procedure set_Location_x (Self : in out Item'Class; for_Joint : in scene_joint_Id;
To : in Real)
is
begin
Self.scene_Joints (for_Joint).Node.set_Location_x (To);
end set_Location_x;
procedure set_Location_y (Self : in out Item'Class; for_Joint : in scene_joint_Id;
To : in Real)
is
begin
Self.scene_Joints (for_Joint).Node.set_Location_y (To);
end set_Location_y;
procedure set_Location_z (Self : in out Item'Class; for_Joint : in scene_joint_Id;
To : in Real)
is
begin
Self.scene_Joints (for_Joint).Node.set_Location_z (To);
end set_location_z;
procedure set_Transform (Self : in out Item'Class; for_Joint : in scene_joint_Id;
To : in Matrix_4x4)
is
begin
Self.scene_Joints (for_Joint).Node.set_Transform (To);
end set_Transform;
procedure set_x_rotation_Angle (Self : in out Item'Class; for_Joint : in scene_joint_Id;
To : in Real)
is
begin
Self.scene_Joints (for_Joint).Node.set_x_rotation_Angle (To);
end set_x_rotation_Angle;
procedure set_y_rotation_Angle (Self : in out Item'Class; for_Joint : in scene_joint_Id;
To : in Real)
is
begin
Self.scene_Joints (for_Joint).Node.set_y_rotation_Angle (To);
end set_y_rotation_Angle;
procedure set_z_rotation_Angle (Self : in out Item'Class; for_Joint : in scene_joint_Id;
To : in Real)
is
begin
Self.scene_Joints (for_Joint).Node.set_z_rotation_Angle (To);
end set_z_rotation_Angle;
----------
--- Define
--
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)
is
use collada.Document,
collada.Library,
collada.Library.visual_Scenes,
ada.Strings.unbounded,
ada.Strings;
type any_Model_view is access all openGL.Model.any.item;
the_Model : constant any_Model_view := any_Model_view (Model);
the_Document : constant collada.Document.item := to_Document (openGL.to_String (the_Model.model_Name));
function get_root_Joint return visual_Scenes.Node_view
is
begin
if the_Document.Libraries.visual_Scenes.skeletal_Root = ""
then
return the_Document.Libraries.visual_Scenes.Contents (1).root_Node;
else
return the_Document.Libraries.visual_Scenes.Contents (1).root_Node.Child (1);
end if;
end get_root_Joint;
the_root_Joint : constant visual_scenes.Node_view := get_root_Joint;
prior_bone_Length : Real := 1.0;
package joint_id_Maps_of_vector_3 is new ada.Containers.hashed_Maps (Key_type => scene_joint_Id,
Element_type => Vector_3,
Hash => ada.Strings.unbounded.Hash,
equivalent_Keys => ada.Strings.unbounded."=",
"=" => "=");
subtype joint_id_Map_of_vector_3 is joint_id_Maps_of_vector_3.Map;
joint_Sites : joint_id_Map_of_vector_3;
procedure set_Site_for (the_Joint : in visual_Scenes.Node_view)
is
which_Joint : constant scene_joint_Id := the_Joint.Id;
child_Joints : constant visual_Scenes.Nodes := the_Joint.Children;
begin
if which_Joint = Self.root_Joint.Name
then
joint_Sites.insert (which_Joint,
[0.0, 0.0, 0.0]);
else
joint_Sites.insert (which_Joint,
get_Translation (Self.joint_bind_Matrix (which_Joint)));
end if;
for i in child_Joints'Range
loop
set_Site_for (child_Joints (i)); -- Recurse over children.
end loop;
end set_Site_for;
procedure create_Bone (the_Bone : in bone_Id;
start_Joint : in scene_joint_Id;
end_Point : in Vector_3;
Scale : in Vector_3;
Mass : in Real)
is
pragma Unreferenced (Mass);
use opengl.Palette;
new_Sprite : gel.Sprite.view;
the_bone_Site : constant Vector_3 := midPoint (joint_Sites (start_Joint),
end_Point);
begin
if the_Bone = Self.root_Joint.Name
then
declare
use standard.physics.Model;
Size : constant Vector_3 := [0.1, 0.1, 0.1];
physics_Model : constant standard.physics.Model.View
:= standard.physics.Model.Forge.new_physics_Model (shape_Info => (Kind => Cube,
half_Extents => Size / 2.0),
Mass => 1.0);
begin
new_Sprite := gel.Sprite.Forge.new_Sprite ("Skin Sprite",
gel.sprite.World_view (in_World),
math.Origin_3D,
Model,
physics_Model,
is_Kinematic => is_Kinematic);
end;
new_Sprite.Site_is ([0.0, 0.0, 0.0]);
new_Sprite.Spin_is (Identity_3x3);
Self.bone_pose_Transforms.insert (the_Bone, Identity_4x4);
Self.skin_Sprite := new_Sprite;
else
new_Sprite := gel.Forge.new_box_Sprite (in_World => in_World.all'Access,
Mass => 1.0,
Size => Scale,
Colors => [1 => Black,
3 => Green,
4 => Blue,
others => Red],
is_Kinematic => is_Kinematic);
new_Sprite.Site_is (the_bone_Site);
new_Sprite.Spin_is (Inverse (get_Rotation (Self.joint_bind_Matrix (start_Joint))));
new_Sprite.is_Visible (False);
Self.anim_joint_site_Offets.insert (the_Bone, Inverse (get_Rotation (Self.joint_inv_bind_Matrix (start_Joint)))
* (joint_Sites (start_Joint) - the_bone_Site));
Self.phys_joint_site_Offets.insert (the_Bone, joint_Sites (start_Joint) - the_bone_Site);
Self.bone_pose_Transforms .insert (the_Bone, to_transform_Matrix (Rotation => get_Rotation (Self.joint_pose_Transforms (start_Joint)),
Translation => the_bone_Site));
end if;
Self.bone_Sprites.insert (the_Bone, new_Sprite);
declare
new_Sprite : constant gel.Sprite.view := gel.Forge.new_box_Sprite (in_World => in_World,
Mass => 0.0,
Size => [0.02, 0.02, 0.02],
Colors => [others => Yellow],
is_Kinematic => True);
begin
Self.joint_Sprites.insert (the_Bone, new_Sprite);
end;
end create_Bone;
procedure create_Bone_for (the_Joint : in visual_Scenes.Node_view; Parent : in bone_Id)
is
use bone_id_Maps_of_details;
which_Joint : constant scene_joint_Id := the_Joint.Id;
child_Joints : constant visual_Scenes.Nodes := the_Joint.Children;
the_bone_Details : Rig.bone_Details;
bone_Length : Real;
end_Point : Vector_3;
new_Joint : gel.Joint.view;
function guessed_bone_Length return Real
is
begin
if child_Joints'Length = 0
then
return prior_bone_Length;
else
if which_Joint = Self.root_Joint.Name
then
return Distance (joint_Sites.Element (which_Joint),
joint_Sites.Element (child_Joints (child_Joints'First).Id));
else
return Distance (joint_Sites.Element (which_Joint),
joint_Sites.Element (child_Joints (child_Joints'Last).Id));
end if;
end if;
end guessed_bone_Length;
begin
if bone_Details.contains (which_Joint)
then
the_bone_Details := bone_Details.Element (which_Joint);
if the_bone_Details.Length = Unspecified
then bone_Length := guessed_bone_Length;
else bone_Length := the_bone_Details.Length;
end if;
else
bone_Length := guessed_bone_Length;
end if;
end_Point := joint_Sites.Element (which_Joint)
+ [0.0, bone_Length, 0.0] * get_Rotation (Self.joint_bind_Matrix (which_Joint));
prior_bone_Length := bone_Length;
Self.joint_Parent.insert (which_Joint, Parent);
create_Bone (which_Joint,
which_Joint,
end_Point,
[the_bone_Details.width_Factor * bone_Length,
bone_Length * 0.90,
the_bone_Details.depth_Factor * bone_Length],
1.0);
if Parent /= (+"")
then
Self.Sprite (Parent).attach_via_ball_Socket (Self.bone_Sprites (which_Joint),
pivot_Axis => x_Rotation_from (0.0),
pivot_Anchor => joint_Sites.Element (which_Joint),
pitch_Limits => the_bone_Details.pitch_Limits,
yaw_Limits => the_bone_Details. yaw_Limits,
roll_Limits => the_bone_Details. roll_Limits,
new_Joint => new_Joint);
Self.Joints.insert (to_gel_joint_Id (Parent, which_Joint),
new_Joint);
end if;
for i in child_Joints'Range
loop
create_Bone_for (child_Joints (i), -- Recurse over children.
parent => which_Joint);
end loop;
end create_Bone_for;
use collada.Library.Controllers;
global_transform_Slot : Positive := 1;
begin
Self.root_Joint := the_root_Joint; -- Remember our root joint.
Self.Model := Model.all'unchecked_Access; -- Remember our model.
--- Parse Controllers.
--
-- Set the bind shape matrix.
--
Self.bind_shape_Matrix := Transpose (bind_shape_Matrix_of (the_Document.Libraries.Controllers.Contents (1).Skin));
-- Set the joint slots.
--
declare
the_Skin : constant Controllers.Skin := the_Document.Libraries.Controllers.Contents (1).Skin;
the_joint_Names : constant collada.Text_array := joint_Names_of (the_Skin);
begin
for i in 1 .. Integer (the_joint_Names'Length)
loop
Self.program_Parameters.joint_Map_of_slot.insert (the_joint_Names (i),
i);
end loop;
end;
-- Set the inverse bind matrices for all joints.
--
declare
the_Skin : constant Controllers.Skin := the_Document.Libraries.Controllers.Contents (1).Skin;
the_bind_Poses : constant collada.Matrix_4x4_array := bind_Poses_of (the_Skin);
begin
for i in 1 .. Integer (the_bind_Poses'Length)
loop
Self.joint_inv_bind_Matrices .append (Transpose (the_bind_Poses (i))); -- Transpose corrects for collada column vectors.
Self.program_Parameters.bone_Transforms.append (Identity_4x4);
end loop;
end;
--- Parse Visual Scene.
--
Self.define_global_Transform_for (the_root_Joint, -- Determine all joint transforms, recursively.
Slot => global_transform_Slot);
set_Site_for (the_root_Joint);
create_Bone_for (the_root_Joint, Parent => +""); -- Create all other bones, recursively.
--- Parse the Collada animations file.
--
declare
use collada.Library.Animations;
the_Animations : constant access Animation_array := the_Document.Libraries.Animations.Contents;
begin
if the_Animations /= null
then
for Each in the_Animations'Range
loop
declare
the_Animation : constant animations.Animation := the_Animations (Each);
the_Inputs : access collada.float_Array := Inputs_of (the_Animation);
procedure common_setup (Channel : in channel_Id;
scene_Joint : in scene_Joint_Id;
Sid : in String)
is
default_scene_Joint : rig.scene_Joint;
default_Channel : animation_Channel;
begin
Self.Channels.insert (Channel, default_Channel);
Self.Channels (Channel).Target := Self.scene_Joints (scene_Joint).Node.fetch_Transform (Sid);
Self.Channels (Channel).target_Joint := scene_Joint;
Self.Channels (Channel).Times := Inputs_of (the_Animation);
Self.Channels (Channel).Values := Outputs_of (the_Animation);
end common_setup;
procedure setup_Rotation (Channel : in channel_Id;
scene_Joint : in scene_Joint_Id;
Sid : in String)
is
begin
common_setup (Channel, scene_Joint, Sid);
-- For angle interpolation during 'rotation' animation.
--
Self.Channels (Channel).initial_Angle := Self.Channels (Channel).Values (1);
Self.Channels (Channel).current_Angle := Self.Channels (Channel).initial_Angle;
end setup_Rotation;
pragma Unreferenced (setup_Rotation);
procedure setup_Location (Channel : in channel_Id;
scene_Joint : in scene_Joint_Id;
Sid : in String)
is
begin
common_setup (Channel, scene_Joint, Sid);
-- For location interpolation during 'translation' animation.
--
Self.Channels (Channel).current_Site := [Self.Channels (Channel).Values (1),
Self.Channels (Channel).Values (2),
Self.Channels (Channel).Values (3)];
Self.Channels (Channel).initial_Site := Self.Channels (Channel).current_Site;
end setup_Location;
pragma Unreferenced (setup_Location);
procedure setup_Location_x (Channel : in channel_Id;
scene_Joint : in scene_Joint_Id;
Sid : in String)
is
begin
common_setup (Channel, scene_Joint, Sid);
-- For matrix interpolation during 'full_transform' animation.
--
Self.Channels (Channel).Transforms := new Transforms (1 .. Self.Channels (Channel).Values'Length);
for i in Self.Channels (Channel).Transforms'Range
loop
declare
the_X_Value : constant Real := Self.Channels (Channel).Values (i);
begin
Self.Channels (Channel).Transforms (i) := (Rotation => to_Quaternion (Identity_3x3),
Translation => [the_X_Value, 0.0, 0.0]);
end;
end loop;
Self.Channels (Channel).initial_Transform := Self.Channels (Channel).Transforms (1);
Self.Channels (Channel).current_Transform := Self.Channels (Channel).initial_Transform;
Self.Channels (Channel).current_Site := Self.Channels (Channel).initial_Transform.Translation;
Self.Channels (Channel).initial_Site := Self.Channels (Channel).current_Site;
end setup_Location_x;
procedure setup_Location_y (Channel : in channel_Id;
scene_Joint : in scene_Joint_Id;
Sid : in String)
is
begin
common_setup (Channel, scene_Joint, Sid);
-- For matrix interpolation during 'full_transform' animation.
--
Self.Channels (Channel).Transforms := new Transforms (1 .. Self.Channels (Channel).Values'Length);
for i in Self.Channels (Channel).Transforms'Range
loop
declare
the_Y_Value : constant Real := Self.Channels (Channel).Values (i);
begin
Self.Channels (Channel).Transforms (i) := (rotation => to_Quaternion (Identity_3x3),
translation => [0.0, the_Y_Value, 0.0]);
end;
end loop;
Self.Channels (Channel).initial_Transform := Self.Channels (Channel).Transforms (1);
Self.Channels (Channel).current_Transform := Self.Channels (Channel).initial_Transform;
Self.Channels (Channel).current_Site := Self.Channels (Channel).initial_Transform.Translation;
Self.Channels (Channel).initial_Site := Self.Channels (Channel).current_Site;
end setup_Location_y;
procedure setup_Location_z (Channel : in channel_Id;
scene_Joint : in scene_Joint_Id;
Sid : in String)
is
begin
common_setup (Channel, scene_Joint, Sid);
-- For matrix interpolation during 'full_transform' animation.
--
Self.Channels (Channel).Transforms := new Transforms (1 .. Self.Channels (Channel).Values'Length);
for i in Self.Channels (Channel).Transforms'Range
loop
declare
the_Z_Value : constant Real := Self.Channels (Channel).Values (i);
begin
Self.Channels (Channel).Transforms (i) := (rotation => to_Quaternion (Identity_3x3),
translation => [0.0, 0.0, the_Z_Value]);
end;
end loop;
Self.Channels (Channel).initial_Transform := Self.Channels (Channel).Transforms (1);
Self.Channels (Channel).current_Transform := Self.Channels (Channel).initial_Transform;
Self.Channels (Channel).current_Site := Self.Channels (Channel).initial_Transform.Translation;
Self.Channels (Channel).initial_Site := Self.Channels (Channel).current_Site;
end setup_Location_z;
procedure setup_full_Transform (Channel : in channel_Id;
scene_Joint : in scene_Joint_Id;
Sid : in String)
is
begin
common_setup (Channel, scene_Joint, Sid);
-- For matrix interpolation during 'full_transform' animation.
--
Self.Channels (Channel).Transforms := new Transforms (1 .. Collada.matrix_Count (Self.Channels (Channel).Values.all));
for i in Self.Channels (Channel).Transforms'Range
loop
declare
the_Matrix : constant math.Matrix_4x4 := Transpose (Collada.get_Matrix (Self.Channels (Channel).Values.all,
which => i));
begin
Self.Channels (Channel).Transforms (i) := (Rotation => to_Quaternion (get_Rotation (the_Matrix)),
Translation => get_Translation (the_Matrix));
end;
end loop;
Self.Channels (Channel).initial_Transform := Self.Channels (Channel).Transforms (1);
Self.Channels (Channel).current_Transform := Self.Channels (Channel).initial_Transform;
Self.Channels (Channel).current_Site := Self.Channels (Channel).initial_Transform.Translation;
Self.Channels (Channel).initial_Site := Self.Channels (Channel).current_Site;
end setup_full_Transform;
function Index (Source : in unbounded_String;
Pattern : in String;
Going : in Direction := Forward;
Mapping : in Maps.character_Mapping := ada.Strings.Maps.Identity) return Natural
renames ada.Strings.unbounded.Index;
begin
if Index (the_Animation.Channel.Target, "hips/transform") /= 0 then
setup_full_Transform (+"hips", +"hips", "transform");
elsif Index (the_Animation.Channel.Target, "thigh_L/transform") /= 0 then
setup_full_Transform (+"thigh_L", +"thigh_L", "transform");
elsif Index (the_Animation.Channel.Target, "shin_L/transform") /= 0 then
setup_full_Transform (+"shin_L", +"shin_L", "transform");
elsif Index (the_Animation.Channel.Target, "foot_L/transform") /= 0 then
setup_full_Transform (+"foot_L", +"foot_L", "transform");
elsif Index (the_Animation.Channel.Target, "toe_L/transform") /= 0 then
setup_full_Transform (+"toe_L", +"toe_L", "transform");
elsif Index (the_Animation.Channel.Target, "thigh_R/transform") /= 0 then
setup_full_Transform (+"thigh_R", +"thigh_R", "transform");
elsif Index (the_Animation.Channel.Target, "shin_R/transform") /= 0 then
setup_full_Transform (+"shin_R", +"shin_R", "transform");
elsif Index (the_Animation.Channel.Target, "foot_R/transform") /= 0 then
setup_full_Transform (+"foot_R", +"foot_R", "transform");
elsif Index (the_Animation.Channel.Target, "toe_R/transform") /= 0 then
setup_full_Transform (+"toe_R", +"toe_R", "transform");
elsif Index (the_Animation.Channel.Target, "spine/transform") /= 0 then
setup_full_Transform (+"spine", +"spine", "transform");
elsif Index (the_Animation.Channel.Target, "chest/transform") /= 0 then
setup_full_Transform (+"chest", +"chest", "transform");
elsif Index (the_Animation.Channel.Target, "clavicle_R/transform") /= 0 then
setup_full_Transform (+"clavicle_R", +"clavicle_R", "transform");
elsif Index (the_Animation.Channel.Target, "upper_arm_R/transform") /= 0 then
setup_full_Transform (+"upper_arm_R", +"upper_arm_R", "transform");
elsif Index (the_Animation.Channel.Target, "forearm_R/transform") /= 0 then
setup_full_Transform (+"forearm_R", +"forearm_R", "transform");
elsif Index (the_Animation.Channel.Target, "hand_R/transform") /= 0 then
setup_full_Transform (+"hand_R", +"hand_R", "transform");
elsif Index (the_Animation.Channel.Target, "thumb_02_R/transform") /= 0 then
setup_full_Transform (+"thumb_02_R", +"thumb_02_R", "transform");
elsif Index (the_Animation.Channel.Target, "thumb_03_R/transform") /= 0 then
setup_full_Transform (+"thumb_03_R", +"thumb_03_R", "transform");
elsif Index (the_Animation.Channel.Target, "f_ring_01_R/transform") /= 0 then
setup_full_Transform (+"f_ring_01_R", +"f_ring_01_R", "transform");
elsif Index (the_Animation.Channel.Target, "f_index_01_R/transform") /= 0 then
setup_full_Transform (+"f_index_01_R", +"f_index_01_R", "transform");
elsif Index (the_Animation.Channel.Target, "clavicle_L/transform") /= 0 then
setup_full_Transform (+"clavicle_L", +"clavicle_L", "transform");
elsif Index (the_Animation.Channel.Target, "upper_arm_L/transform") /= 0 then
setup_full_Transform (+"upper_arm_L", +"upper_arm_L", "transform");
elsif Index (the_Animation.Channel.Target, "forearm_L/transform") /= 0 then
setup_full_Transform (+"forearm_L", +"forearm_L", "transform");
elsif Index (the_Animation.Channel.Target, "hand_L/transform") /= 0 then
setup_full_Transform (+"hand_L", +"hand_L", "transform");
elsif Index (the_Animation.Channel.Target, "thumb_02_L/transform") /= 0 then
setup_full_Transform (+"thumb_02_L", +"thumb_02_L", "transform");
elsif Index (the_Animation.Channel.Target, "thumb_03_L/transform") /= 0 then
setup_full_Transform (+"thumb_03_L", +"thumb_03_L", "transform");
elsif Index (the_Animation.Channel.Target, "f_ring_01_L/transform") /= 0 then
setup_full_Transform (+"f_ring_01_L", +"f_ring_01_L", "transform");
elsif Index (the_Animation.Channel.Target, "f_index_01_L/transform") /= 0 then
setup_full_Transform (+"f_index_01_L", +"f_index_01_L", "transform");
elsif Index (the_Animation.Channel.Target, "neck/transform") /= 0 then
setup_full_Transform (+"neck", +"neck", "transform");
elsif Index (the_Animation.Channel.Target, "head/transform") /= 0 then
setup_full_Transform (+"head", +"head", "transform");
elsif Index (the_Animation.Channel.Target, "jaw/transform") /= 0 then
setup_full_Transform (+"jaw", +"jaw", "transform");
elsif Index (the_Animation.Channel.Target, "eye_R/transform") /= 0 then
setup_full_Transform (+"eye_R", +"eye_R", "transform");
elsif Index (the_Animation.Channel.Target, "eye_L/transform") /= 0 then
setup_full_Transform (+"eye_L", +"eye_L", "transform");
elsif Index (the_Animation.Channel.Target, "stride_bone/location.X") /= 0 then
-- setup_Location_x (+"stride_bone_x", +"stride_bone", "x");
setup_Location_x (+"stride_bone_x", +"human", "x");
elsif Index (the_Animation.Channel.Target, "stride_bone/location.Y") /= 0 then
-- setup_Location_y (+"stride_bone_y", +"stride_bone", "y");
setup_Location_y (+"stride_bone_y", +"human", "y");
elsif Index (the_Animation.Channel.Target, "stride_bone/location.Z") /= 0 then
-- setup_Location_z (+"stride_bone_z", +"stride_bone", "z");
setup_Location_z (+"stride_bone_z", +"human", "z");
else
raise constraint_Error with +the_Animation.Channel.Target & " not handled";
end if;
end;
end loop;
end if;
end;
end define;
procedure enable_Graphics (Self : in out Item)
is
begin
Self .program_Parameters.Program_is (opengl.Program.view (opengl.Geometry.lit_colored_textured_skinned.Program));
Self.skin_Sprite.program_Parameters_are (Self.program_Parameters'unchecked_Access);
end enable_Graphics;
function Joints (Self : in Item) return gel_joint_id_Map_of_gel_Joint
is
begin
return Self.Joints;
end Joints;
function joint_inv_bind_Matrices (Self : in Item'Class) return inverse_bind_matrix_Vector
is
begin
return Self.joint_inv_bind_Matrices;
end joint_inv_bind_Matrices;
procedure joint_inv_bind_Matrices_are (Self : in out Item'Class; Now : in inverse_bind_matrix_Vector)
is
begin
Self.joint_inv_bind_Matrices := Now;
end joint_inv_bind_Matrices_are;
function joint_site_Offets (Self : in Item'Class) return joint_Id_Map_of_bone_site_offset
is
begin
return Self.phys_joint_site_Offets;
end joint_site_Offets;
--------------
--- Attributes
--
procedure Site_is (Self :in out Item; Now : in Vector_3)
is
begin
Self.base_Sprite.move (to_Site => Now);
Self.overall_Site := Now;
end Site_is;
procedure Spin_is (Self :in out Item; Now : in Matrix_3x3)
is
begin
Self.base_Sprite.rotate (to_Spin => Now);
end Spin_is;
function Sprite (Self : in Item'Class; Bone : in bone_Id) return gel.Sprite.view
is
begin
return Self.bone_Sprites (Bone);
end Sprite;
function base_Sprite (Self : in Item'Class) return gel.Sprite.view
is
begin
return Self.bone_Sprites.Element (Self.root_Joint.Name);
end base_Sprite;
function skin_Sprite (Self : in Item'Class) return gel.Sprite.view
is
begin
return Self.skin_Sprite;
end skin_Sprite;
function bone_Sprites (Self : in Item) return bone_id_Map_of_sprite
is
begin
return Self.bone_Sprites;
end bone_Sprites;
procedure set_GL_program_Parameters (Self : in out Item'Class; for_Bone : in controller_joint_Id;
To : in Matrix_4x4)
is
use gel.Conversions;
bone_Slot : constant Positive := Self.program_Parameters.joint_Map_of_slot.Element (for_Bone);
begin
Self.program_Parameters.bone_Transforms.replace_Element (bone_Slot,
to_GL (To));
end set_GL_program_Parameters;
procedure animation_Transforms_are (Self : in out Item'Class; Now : in bone_id_Map_of_transform)
is
begin
Self.animation_Transforms := Now;
end animation_Transforms_are;
procedure motion_Mode_is (Self : in out Item; Now : in motion_Mode)
is
begin
Self.Mode := Now;
end motion_Mode_is;
--------------
--- Operations
--
procedure evolve (Self : in out Item'Class; world_Age : in Duration)
is
function get_root_Transform return Matrix_4x4
is
begin
case Self.Mode
is
when Dynamics =>
return Self.base_Sprite.Transform;
when Animation =>
declare
the_Transform : Matrix_4x4;
begin
set_Rotation (the_Transform, x_Rotation_from (to_Radians (0.0)));
set_Translation (the_Transform, -get_Translation (Inverse (Self.joint_pose_Transforms (Self.root_Joint.Name))));
return the_Transform;
end;
end case;
end get_root_Transform;
root_Transform : constant Matrix_4x4 := get_root_Transform;
inv_root_Transform : constant Matrix_4x4 := Inverse (root_Transform);
function joint_Transform_for (the_collada_Joint : in controller_joint_Id) return Matrix_4x4
is
begin
case Self.Mode
is
when Dynamics =>
declare
the_bone_Transform : constant Matrix_4x4 := Self.Sprite (the_collada_Joint).Transform;
the_joint_site_Offset : Vector_3 := Self.phys_joint_site_Offets (the_collada_Joint);
the_joint_Transform : Matrix_4x4;
begin
the_joint_site_Offset := the_joint_site_Offset
* get_Rotation (Self.joint_inv_bind_Matrix (the_collada_Joint))
* get_Rotation (the_bone_Transform);
set_Translation (the_joint_Transform, get_Translation (the_bone_Transform) + the_joint_site_Offset);
set_Rotation (the_joint_Transform, get_Rotation (the_bone_Transform));
Self.joint_Sprites (the_collada_Joint).all.Site_is (get_Translation (the_joint_Transform));
return the_joint_Transform;
end;
when Animation =>
Self.joint_Sprites (the_collada_Joint).all.Site_is ( get_Translation (Self.scene_Joints (the_collada_Joint).Transform));
Self.joint_Sprites (the_collada_Joint).all.Spin_is (Inverse (get_Rotation (Self.scene_Joints (the_collada_Joint).Transform)));
return Self.scene_Joints (the_collada_Joint).Transform;
end case;
end joint_Transform_for;
procedure set_Transform_for (the_Bone : in controller_joint_Id)
is
the_Slot : constant Positive := Self.program_Parameters.joint_Map_of_slot (the_Bone);
begin
Self.set_GL_program_Parameters (for_Bone => the_Bone,
To => Self.bind_shape_Matrix
* Self.joint_inv_bind_Matrices.Element (the_Slot)
* joint_Transform_for (the_Bone)
* inv_root_Transform);
end set_Transform_for;
procedure set_proxy_Transform_for (the_Bone : in controller_joint_Id; the_Proxy : in controller_joint_Id)
is
the_Slot : constant Positive := Self.program_Parameters.joint_Map_of_slot (the_Proxy);
begin
Self.set_GL_program_Parameters (for_bone => the_Bone,
to => Self.bind_shape_Matrix
* Self.joint_inv_bind_Matrices .Element (the_Slot)
* joint_Transform_for (the_Proxy)
* inv_root_Transform);
end set_proxy_Transform_for;
pragma Unreferenced (set_proxy_Transform_for);
use joint_Id_Maps_of_bone_site_offset;
Cursor : joint_Id_Maps_of_bone_site_offset.Cursor := Self.phys_joint_site_Offets.First;
begin
if Self.Mode = Animation
then
Self.animate (world_Age);
end if;
while has_Element (Cursor)
loop
if Self.program_Parameters.joint_Map_of_slot.Contains (Key (Cursor))
then
set_Transform_for (Key (Cursor)); -- Updates gl skin program params.
end if;
next (Cursor);
end loop;
end evolve;
procedure assume_Pose (Self : in out Item)
is
use bone_id_Maps_of_transform;
the_Bone : gel.Sprite.view;
Cursor : bone_id_Maps_of_transform.Cursor := Self.bone_pose_Transforms.First;
begin
while has_Element (Cursor)
loop
the_Bone := Self.bone_Sprites (Key (Cursor));
the_Bone.Transform_is (Element (Cursor));
next (Cursor);
end loop;
end assume_Pose;
function Parent_of (Self : in Item; the_Bone : in bone_Id) return bone_Id
is
begin
if Self.joint_Parent.Contains (the_Bone)
then
return Self.joint_Parent.Element (the_Bone);
else
return null_Id;
end if;
end Parent_of;
function joint_site_Offet (Self : in Item; for_Bone : in bone_Id) return math.Vector_3
is
begin
return Self.phys_joint_site_Offets.Element (for_Bone);
end joint_site_Offet;
function joint_inv_bind_Matrix (Self : in Item; for_Bone : in bone_Id) return math.Matrix_4x4
is
use ada.Strings.unbounded;
begin
if for_Bone = Self.root_Joint.Name
then
return math.Identity_4x4;
else
return Self.joint_inv_bind_Matrices.Element (Self.program_Parameters.joint_Map_of_slot.Element (for_Bone));
end if;
end joint_inv_bind_Matrix;
function joint_bind_Matrix (Self : in Item; for_Bone : in bone_Id) return Matrix_4x4
is
begin
return Inverse (Self.joint_inv_bind_Matrix (for_Bone));
end joint_bind_Matrix;
-------------
--- Animation
--
procedure animate (Self : in out Item; world_Age : in Duration)
is
Now : Duration;
Elapsed : Duration;
procedure update_rotation_Animation (for_Channel : in channel_Id;
for_Joint : in scene_joint_Id;
for_Axis : in axis_Kind)
is
the_Channel : animation_Channel renames Self.Channels (for_Channel);
Cursor : math.Index renames the_Channel.Cursor;
function Reduced (Angle : in Real) return Real -- TODO: Use Degrees type.
is
begin
if Angle > 180.0 then return -360.0 + Angle;
elsif Angle < -180.0 then return 360.0 + Angle;
else return Angle;
end if;
end Reduced;
begin
if Cursor < the_Channel.Times'Last
then
if Cursor = 0
or else Elapsed > Duration (the_Channel.Times (Cursor))
then
Cursor := Cursor + 1;
if Cursor = 1
then
if the_Channel.Times (Cursor) = 0.0
then
the_Channel.interp_Delta := Reduced (the_Channel.Values (Cursor) - the_Channel.current_Angle);
else
the_Channel.interp_Delta := Reduced (the_Channel.Values (Cursor) - the_Channel.current_Angle)
/ (the_Channel.Times (Cursor));
end if;
else
the_Channel.interp_Delta := Reduced (the_Channel.Values (Cursor) - the_Channel.current_Angle)
/ (the_Channel.Times (Cursor) - the_Channel.Times (Cursor - 1));
end if;
the_Channel.interp_Delta := the_Channel.interp_Delta / 60.0; -- 60.0 is frames/sec.
end if;
end if;
if Elapsed < Duration (the_Channel.Times (the_Channel.Times'Last))
then
the_Channel.current_Angle := Reduced ( the_Channel.current_Angle
+ the_Channel.interp_Delta);
Self.set_rotation_Angle (for_Joint,
for_Axis,
To => to_Radians (Degrees (the_Channel.current_Angle)));
end if;
end update_rotation_Animation;
pragma Unreferenced (update_rotation_Animation);
procedure update_location_Animation (for_Channel : in channel_Id;
for_Joint : in scene_joint_Id)
is
pragma Unreferenced (for_Joint);
the_Channel : animation_Channel renames Self.Channels (for_Channel);
Cursor : Index renames the_Channel.Cursor;
Elapsed : constant Duration := Now - Self.start_Time;
function site_X return Real is begin return the_Channel.Values ((Cursor - 1) * 3 + 1); end site_X;
function site_Y return Real is begin return the_Channel.Values ((Cursor - 1) * 3 + 2); end site_Y;
function site_Z return Real is begin return the_Channel.Values ((Cursor - 1) * 3 + 3); end site_Z;
begin
if Cursor < the_Channel.Times'Last
then
if Cursor = 0
or else Elapsed > Duration (the_Channel.Times (Cursor))
then
Cursor := Cursor + 1;
if Cursor = 1
then
if the_Channel.Times (Cursor) = 0.0
then
the_Channel.site_interp_Delta (1) := site_X - the_Channel.current_Site (1);
the_Channel.site_interp_Delta (2) := site_Y - the_Channel.current_Site (2);
the_Channel.site_interp_Delta (3) := site_Z - the_Channel.current_Site (3);
else
the_Channel.site_interp_Delta (1) := (site_X - the_Channel.current_Site (1))
/ (the_Channel.Times (Cursor));
the_Channel.site_interp_Delta (2) := (site_Y - the_Channel.current_Site (2))
/ (the_Channel.Times (Cursor));
the_Channel.site_interp_Delta (3) := (site_Z - the_Channel.current_Site (3))
/ (the_Channel.Times (Cursor));
end if;
else
the_Channel.site_interp_Delta (1) := (site_X - the_Channel.current_Site (1))
/ (the_Channel.Times (Cursor) - the_Channel.Times (Cursor - 1));
the_Channel.site_interp_Delta (2) := (site_Y - the_Channel.current_Site (2))
/ (the_Channel.Times (Cursor) - the_Channel.Times (Cursor - 1));
the_Channel.site_interp_Delta (3) := (site_Z - the_Channel.current_Site (3))
/ (the_Channel.Times (Cursor) - the_Channel.Times (Cursor - 1));
end if;
the_Channel.site_interp_Delta (1) := the_Channel.site_interp_Delta (1) / 60.0; -- 60.0 is frames/sec.
the_Channel.site_interp_Delta (2) := the_Channel.site_interp_Delta (2) / 60.0; --
the_Channel.site_interp_Delta (3) := the_Channel.site_interp_Delta (3) / 60.0; --
end if;
Self.set_Location (the_Channel.target_Joint, to => the_Channel.current_Site);
the_Channel.current_Site (1) := the_Channel.current_Site (1) + the_Channel.site_interp_Delta (1);
the_Channel.current_Site (2) := the_Channel.current_Site (2) + the_Channel.site_interp_Delta (2);
the_Channel.current_Site (3) := the_Channel.current_Site (3) + the_Channel.site_interp_Delta (3);
end if;
end update_location_Animation;
pragma Unreferenced (update_location_Animation);
procedure update_location_X_Animation (for_Channel : in channel_Id;
for_Joint : in scene_joint_Id)
is
pragma Unreferenced (for_Joint);
the_Channel : animation_Channel renames Self.Channels (for_Channel);
Cursor : Index renames the_Channel.Cursor;
Elapsed : constant Duration := Now - Self.start_Time;
function site_X return Real is begin return the_Channel.Values (Cursor); end site_X;
begin
if Cursor < the_Channel.Times'Last
then
if Cursor = 0
or else Elapsed > Duration (the_Channel.Times (Cursor))
then
Cursor := Cursor + 1;
if Cursor = 1
then
if the_Channel.Times (Cursor) = 0.0
then
the_Channel.site_interp_Delta (1) := site_X - the_Channel.current_Site (1);
else
the_Channel.site_interp_Delta (1) := (site_X - the_Channel.current_Site (1))
/ (the_Channel.Times (Cursor));
end if;
else
the_Channel.site_interp_Delta (1) := (site_X - the_Channel.current_Site (1))
/ (the_Channel.Times (Cursor) - the_Channel.Times (Cursor - 1));
end if;
the_Channel.site_interp_Delta (1) := the_Channel.site_interp_Delta (1) / 60.0; -- 60.0 is frames/sec.
end if;
Self.set_Location_x (the_Channel.target_Joint, To => the_Channel.current_Site (1));
the_Channel.current_Site (1) := the_Channel.current_Site (1) + the_Channel.site_interp_Delta (1);
end if;
end update_location_X_Animation;
procedure update_location_Y_Animation (for_Channel : in channel_Id;
for_Joint : in scene_joint_Id)
is
pragma Unreferenced (for_Joint);
the_Channel : animation_Channel renames Self.Channels (for_Channel);
Cursor : Index renames the_Channel.Cursor;
Elapsed : constant Duration := Now - Self.start_Time;
function site_Y return math.Real is begin return the_Channel.Values (Cursor); end site_Y;
begin
if Cursor < the_Channel.Times'Last
then
if Cursor = 0
or else Elapsed > Duration (the_Channel.Times (Cursor))
then
Cursor := Cursor + 1;
if Cursor = 1
then
if the_Channel.Times (Cursor) = 0.0
then
the_Channel.site_interp_Delta (2) := site_Y - the_Channel.current_Site (2);
else
the_Channel.site_interp_Delta (2) := (site_Y - the_Channel.current_Site (2))
/ (the_Channel.Times (Cursor));
end if;
else
the_Channel.site_interp_Delta (2) := (site_Y - the_Channel.current_Site (2))
/ (the_Channel.Times (Cursor) - the_Channel.Times (Cursor - 1));
end if;
the_Channel.site_interp_Delta (2) := the_Channel.site_interp_Delta (2) / 60.0; -- 60.0 is frames/sec
end if;
Self.set_Location_y (the_Channel.target_Joint, To => the_Channel.current_Site (2));
the_Channel.current_Site (2) := the_Channel.current_Site (2) + the_Channel.site_interp_Delta (2);
end if;
end update_location_Y_Animation;
procedure update_location_Z_Animation (for_Channel : in channel_Id;
for_Joint : in scene_joint_Id)
is
pragma Unreferenced (for_Joint);
the_Channel : animation_Channel renames Self.Channels (for_Channel);
Cursor : math.Index renames the_Channel.Cursor;
Elapsed : constant Duration := Now - Self.start_Time;
function site_Z return math.Real is begin return the_Channel.Values (Cursor); end site_Z;
begin
if Cursor < the_Channel.Times'Last
then
if Cursor = 0
or else Elapsed > Duration (the_Channel.Times (Cursor))
then
Cursor := Cursor + 1;
if Cursor = 1
then
if the_Channel.Times (Cursor) = 0.0
then
the_Channel.site_interp_Delta (3) := site_Z - the_Channel.current_Site (3);
else
the_Channel.site_interp_Delta (3) := (site_Z - the_Channel.current_Site (3))
/ (the_Channel.Times (Cursor));
end if;
else
the_Channel.site_interp_Delta (3) := (site_Z - the_Channel.current_Site (3))
/ (the_Channel.Times (Cursor) - the_Channel.Times (Cursor - 1));
end if;
the_Channel.site_interp_Delta (3) := the_Channel.site_interp_Delta (3) / 60.0; -- 60.0 is frames/sec
end if;
Self.set_Location_z (the_Channel.target_Joint, To => the_Channel.current_Site (3));
the_Channel.current_Site (3) := the_Channel.current_Site (3) + the_Channel.site_interp_Delta (3);
end if;
end update_location_Z_Animation;
procedure update_full_transform_Animation (for_Channel : in channel_Id;
for_Joint : in scene_joint_Id)
is
pragma Unreferenced (for_Joint);
the_Channel : animation_Channel renames Self.Channels (for_Channel);
Cursor : Index renames the_Channel.Cursor;
Cursor_updated : Boolean := False;
new_Transform : Matrix_4x4 := Identity_4x4;
begin
if Cursor = the_Channel.Times'Last
then
Cursor := 0;
Self.start_Time := Now;
end if;
-- Rotation
--
declare
Initial : Transform;
begin
if Cursor < the_Channel.Times'Last
then
if Cursor = 0
or else Elapsed > Duration (the_Channel.Times (Cursor))
then
Cursor := Cursor + 1;
Cursor_updated := True;
if Cursor = 1
then
Initial := the_Channel.current_Transform;
if the_Channel.Times (Cursor) = 0.0
then
the_Channel.Transform_interp_Delta := 1.0 / 60.0;
else
the_Channel.Transform_interp_Delta := the_Channel.Times (Cursor);
end if;
else
Initial := the_Channel.Transforms (Cursor - 1);
the_Channel.Transform_interp_Delta := the_Channel.Times (Cursor) - the_Channel.Times (Cursor - 1);
end if;
the_Channel.current_Transform := the_Channel.Transforms (Cursor);
the_Channel.Transform_interp_Delta := 1.0 / (the_Channel.Transform_interp_Delta * 60.0); -- 60.0 is frames/sec.
the_Channel.slerp_Time := 0.0;
else
if Cursor > 1
then Initial := the_Channel.Transforms (Cursor - 1);
else Initial := the_Channel.Transforms (Cursor);
end if;
end if;
else
Initial := the_Channel.Transforms (1);
end if;
if Elapsed < Duration (the_Channel.Times (the_Channel.Times'Last))
then
set_Rotation (new_Transform, to_Matrix (Interpolated (Initial.Rotation,
the_Channel.current_Transform.Rotation,
Percent => to_Percentage (the_Channel.slerp_Time))));
the_Channel.slerp_Time := the_Channel.slerp_Time
+ the_Channel.Transform_interp_Delta;
end if;
end;
-- Location
--
declare
desired_Site : constant Vector_3 := the_Channel.Transforms (Cursor).Translation;
begin
if Cursor < the_Channel.Times'Last
then
if Cursor_updated
then
if Cursor = 1
then
if the_Channel.Times (Cursor) = 0.0
then
the_Channel.site_interp_Delta := desired_Site - the_Channel.current_Site;
else
the_Channel.site_interp_Delta := (desired_Site - the_Channel.current_Site)
/ (the_Channel.Times (Cursor));
end if;
else
the_Channel.site_interp_Delta := (desired_Site - the_Channel.current_Site)
/ (the_Channel.Times (Cursor) - the_Channel.Times (Cursor - 1));
end if;
the_Channel.site_interp_Delta := the_Channel.site_interp_Delta / 60.0; -- 60.0 is frames/sec.
end if;
the_Channel.current_Site := the_Channel.current_Site + the_Channel.site_interp_Delta;
set_Translation (new_Transform, To => the_Channel.current_Site);
end if;
end;
-- Scale
--
-- (TODO)
-- Store the new transform.
--
Self.set_Transform (the_Channel.target_Joint,
To => Transpose (new_Transform)); -- Transpose to convert to collada column vectors.
end update_full_transform_Animation;
begin
Now := world_Age;
if Self.start_Time = 0.0 then
Self.start_Time := Now;
end if;
Elapsed := Now - Self.start_Time;
declare
use channel_id_Maps_of_animation_Channel,
ada.Strings.Unbounded;
Cursor : channel_id_Maps_of_animation_Channel.Cursor := Self.Channels.First;
begin
while has_Element (Cursor)
loop
if Key (Cursor) = (+"stride_bone_x")
then
update_location_X_Animation (Key (Cursor),
Key (Cursor));
elsif Key (Cursor) = (+"stride_bone_y")
then
update_location_Y_Animation (Key (Cursor),
Key (Cursor));
elsif Key (Cursor) = (+"stride_bone_z")
then
update_location_Z_Animation (Key (Cursor),
Key (Cursor));
else
update_full_transform_Animation (Key (Cursor),
Key (Cursor));
end if;
next (Cursor);
end loop;
end;
Self.update_all_global_Transforms;
end animate;
procedure reset_Animation (Self : in out Item)
is
use channel_id_Maps_of_animation_Channel;
Cursor : channel_id_Maps_of_animation_Channel.Cursor := Self.Channels.First;
the_Channel : animation_Channel;
begin
Self.start_Time := 0.0;
while has_Element (Cursor)
loop
the_Channel := Element (Cursor);
the_Channel.Cursor := 0;
the_Channel.current_Angle := the_Channel.initial_Angle;
the_Channel.current_Site := the_Channel.initial_Site;
the_Channel.interp_Delta := 0.0;
Self.Channels.replace_Element (Cursor, the_Channel);
next (Cursor);
end loop;
end reset_Animation;
end gel.Rig;