fyrox_impl/scene/
ragdoll.rs

1// Copyright (c) 2019-present Dmitry Stepanov and Fyrox Engine contributors.
2//
3// Permission is hereby granted, free of charge, to any person obtaining a copy
4// of this software and associated documentation files (the "Software"), to deal
5// in the Software without restriction, including without limitation the rights
6// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7// copies of the Software, and to permit persons to whom the Software is
8// furnished to do so, subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included in all
11// copies or substantial portions of the Software.
12//
13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19// SOFTWARE.
20
21//! Ragdoll is a set of rigid bodies linked with various joints, which can control a set of bones
22//! of a mesh. Ragdolls are used mostly for body physics. See [`Ragdoll`] docs for more info and
23//! usage examples.
24
25use crate::scene::node::constructor::NodeConstructor;
26use crate::{
27    core::{
28        algebra::{Matrix4, UnitQuaternion, Vector3},
29        math::{aabb::AxisAlignedBoundingBox, Matrix4Ext},
30        pool::Handle,
31        reflect::prelude::*,
32        type_traits::prelude::*,
33        uuid::{uuid, Uuid},
34        uuid_provider,
35        variable::InheritableVariable,
36        visitor::prelude::*,
37    },
38    graph::BaseSceneGraph,
39    scene::{
40        base::{Base, BaseBuilder},
41        collider::Collider,
42        graph::Graph,
43        node::{Node, NodeTrait, UpdateContext},
44        rigidbody::{RigidBody, RigidBodyType},
45    },
46};
47use fyrox_graph::constructor::ConstructorProvider;
48use fyrox_graph::SceneGraphNode;
49use std::{
50    any::{type_name, Any, TypeId},
51    ops::{Deref, DerefMut},
52};
53
54/// A part of ragdoll, that has a physical rigid body, a bone and zero or more children limbs.
55/// Multiple limbs together forms a ragdoll.
56#[derive(Clone, Debug, PartialEq, Default)]
57pub struct Limb {
58    /// A handle of a scene node, that is used as a bone in some other scene node (mesh).
59    pub bone: Handle<Node>,
60    /// A handle to a rigid body scene node.
61    pub physical_bone: Handle<Node>,
62    /// A set of children limbs.
63    pub children: Vec<Limb>,
64}
65
66uuid_provider!(Limb = "6d5bc2f7-8acc-4b64-8e4b-65d4551150bf");
67
68// Rust has a compiler bug `overflow evaluating the requirement` that prevents deriving this impl.
69impl Reflect for Limb {
70    fn source_path() -> &'static str {
71        file!()
72    }
73
74    fn type_name(&self) -> &'static str {
75        type_name::<Self>()
76    }
77
78    fn doc(&self) -> &'static str {
79        ""
80    }
81
82    fn assembly_name(&self) -> &'static str {
83        env!("CARGO_PKG_NAME")
84    }
85
86    fn type_assembly_name() -> &'static str {
87        env!("CARGO_PKG_NAME")
88    }
89
90    fn fields_info(&self, func: &mut dyn FnMut(&[FieldInfo])) {
91        func(&[
92            FieldInfo {
93                owner_type_id: TypeId::of::<Self>(),
94                name: "Bone",
95                display_name: "Bone",
96                description: "",
97                tag: "",
98                type_name: type_name::<Handle<Node>>(),
99                value: &self.bone,
100                reflect_value: &self.bone,
101                read_only: false,
102                immutable_collection: false,
103                min_value: None,
104                max_value: None,
105                step: None,
106                precision: None,
107                doc: "",
108            },
109            FieldInfo {
110                owner_type_id: TypeId::of::<Self>(),
111                name: "PhysicalBone",
112                display_name: "Physical Bone",
113                description: "",
114                tag: "",
115                type_name: type_name::<Handle<Node>>(),
116                value: &self.physical_bone,
117                reflect_value: &self.physical_bone,
118                read_only: false,
119                immutable_collection: false,
120                min_value: None,
121                max_value: None,
122                step: None,
123                precision: None,
124                doc: "",
125            },
126            FieldInfo {
127                owner_type_id: TypeId::of::<Self>(),
128                name: "Children",
129                display_name: "Children",
130                description: "",
131                tag: "",
132                type_name: type_name::<Vec<Limb>>(),
133                value: &self.children,
134                reflect_value: &self.children,
135                read_only: false,
136                immutable_collection: false,
137                min_value: None,
138                max_value: None,
139                step: None,
140                precision: None,
141                doc: "",
142            },
143        ])
144    }
145
146    fn into_any(self: Box<Self>) -> Box<dyn Any> {
147        self
148    }
149
150    fn as_any(&self, func: &mut dyn FnMut(&dyn Any)) {
151        func(self)
152    }
153
154    fn as_any_mut(&mut self, func: &mut dyn FnMut(&mut dyn Any)) {
155        func(self)
156    }
157
158    fn as_reflect(&self, func: &mut dyn FnMut(&dyn Reflect)) {
159        func(self)
160    }
161
162    fn as_reflect_mut(&mut self, func: &mut dyn FnMut(&mut dyn Reflect)) {
163        func(self)
164    }
165
166    fn set(&mut self, value: Box<dyn Reflect>) -> Result<Box<dyn Reflect>, Box<dyn Reflect>> {
167        let this = std::mem::replace(self, value.take()?);
168        Ok(Box::new(this))
169    }
170
171    fn fields(&self, func: &mut dyn FnMut(&[&dyn Reflect])) {
172        func(&[&self.bone, &self.physical_bone, &self.children])
173    }
174
175    fn fields_mut(&mut self, func: &mut dyn FnMut(&mut [&mut dyn Reflect])) {
176        func(&mut [&mut self.bone, &mut self.physical_bone, &mut self.children])
177    }
178
179    fn field(&self, name: &str, func: &mut dyn FnMut(Option<&dyn Reflect>)) {
180        func(match name {
181            "Bone" => Some(&self.bone),
182            "PhysicalBone" => Some(&self.physical_bone),
183            "Children" => Some(&self.children),
184            _ => None,
185        })
186    }
187
188    fn field_mut(&mut self, name: &str, func: &mut dyn FnMut(Option<&mut dyn Reflect>)) {
189        func(match name {
190            "Bone" => Some(&mut self.bone),
191            "PhysicalBone" => Some(&mut self.physical_bone),
192            "Children" => Some(&mut self.children),
193            _ => None,
194        })
195    }
196}
197
198impl Visit for Limb {
199    fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
200        let mut guard = visitor.enter_region(name)?;
201
202        self.bone.visit("Bone", &mut guard)?;
203        self.physical_bone.visit("PhysicalBone", &mut guard)?;
204        self.children.visit("Children", &mut guard)?;
205
206        Ok(())
207    }
208}
209
210impl Limb {
211    /// Iterates recursively across the entire tree of descendant limbs and does the specified action
212    /// with every limb along the way.
213    pub fn iterate_recursive<F>(&self, func: &mut F)
214    where
215        F: FnMut(&Self),
216    {
217        func(self);
218
219        for child in self.children.iter() {
220            child.iterate_recursive(func)
221        }
222    }
223}
224
225/// Ragdoll is a set of rigid bodies linked with various joints, which can control a set of bones
226/// of a mesh. Ragdolls are used mostly for body physics.
227///
228/// ## How to create
229///
230/// Usually, bodies have quite complex hierarchy of bones and total count of the bones could be 30+.
231/// Manual creation of such ragdoll is very tedious and counterproductive. That's why the best way
232/// to create a ragdoll is to use the editor, and the ragdoll wizard in particular. However, if
233/// you're brave enough you can read this code <https://github.com/FyroxEngine/Fyrox/blob/master/editor/src/utils/ragdoll.rs> -
234/// it creates a ragdoll using a humanoid skeleton.  
235#[derive(Clone, Reflect, Visit, Debug, Default, ComponentProvider)]
236#[visit(optional)]
237pub struct Ragdoll {
238    base: Base,
239    /// A handle to a main rigid body of the character to which this ragdoll belongs to. If set, the
240    /// ragdoll will take control over the collider and will move it together with the root limb.
241    pub character_rigid_body: InheritableVariable<Handle<Node>>,
242    /// A flag, that defines whether the ragdoll is active or not. Active ragdoll enables limb rigid
243    /// bodies and takes control over `character_rigid_body` (if set).
244    pub is_active: InheritableVariable<bool>,
245    /// Root limb of the ragdoll. Usually it is hips of the body and rest of the limbs are forming
246    /// the rest of the hierarchy.
247    pub root_limb: InheritableVariable<Limb>,
248    /// A flag, that defines whether the ragdoll will deactivate colliders when it is not active or not.
249    /// This option could be useful if you want to disable physics of limbs while the ragdoll is active.
250    pub deactivate_colliders: InheritableVariable<bool>,
251    #[reflect(hidden)]
252    prev_enabled: bool,
253}
254
255impl Deref for Ragdoll {
256    type Target = Base;
257
258    fn deref(&self) -> &Self::Target {
259        &self.base
260    }
261}
262
263impl DerefMut for Ragdoll {
264    fn deref_mut(&mut self) -> &mut Self::Target {
265        &mut self.base
266    }
267}
268
269impl TypeUuidProvider for Ragdoll {
270    fn type_uuid() -> Uuid {
271        uuid!("f4441683-dcef-472d-9d7d-4adca4579107")
272    }
273}
274
275impl ConstructorProvider<Node, Graph> for Ragdoll {
276    fn constructor() -> NodeConstructor {
277        NodeConstructor::new::<Self>()
278            .with_variant("Ragdoll", |_| {
279                RagdollBuilder::new(BaseBuilder::new().with_name("Ragdoll"))
280                    .build_node()
281                    .into()
282            })
283            .with_group("Physics")
284    }
285}
286
287impl NodeTrait for Ragdoll {
288    fn local_bounding_box(&self) -> AxisAlignedBoundingBox {
289        self.base.local_bounding_box()
290    }
291
292    fn world_bounding_box(&self) -> AxisAlignedBoundingBox {
293        self.base.world_bounding_box()
294    }
295
296    fn id(&self) -> Uuid {
297        Self::type_uuid()
298    }
299
300    fn update(&mut self, ctx: &mut UpdateContext) {
301        // Get linear and angular velocities of the character rigid body and transfer it onto rag doll bodies when it is just activated.
302        let mut new_lin_vel = None;
303        let mut new_ang_vel = None;
304        if *self.is_active && !self.prev_enabled {
305            if let Some(character_rigid_body) = ctx
306                .nodes
307                .try_borrow_mut(*self.character_rigid_body)
308                .and_then(|n| n.component_mut::<RigidBody>())
309            {
310                new_lin_vel = Some(character_rigid_body.lin_vel());
311                new_ang_vel = Some(character_rigid_body.ang_vel());
312            }
313        }
314        self.prev_enabled = *self.is_active;
315
316        self.root_limb.iterate_recursive(&mut |limb| {
317            let mbc = ctx.nodes.begin_multi_borrow();
318
319            let mut need_update_transform = false;
320
321            if let Ok(mut limb_body) =
322                mbc.try_get_component_of_type_mut::<RigidBody>(limb.physical_bone)
323            {
324                if *self.is_active {
325                    // Transfer linear and angular velocities to rag doll bodies.
326                    if let Some(lin_vel) = new_lin_vel {
327                        limb_body.set_lin_vel(lin_vel);
328                    }
329                    if let Some(ang_vel) = new_ang_vel {
330                        limb_body.set_ang_vel(ang_vel);
331                    }
332
333                    if limb_body.body_type() != RigidBodyType::Dynamic {
334                        limb_body.set_body_type(RigidBodyType::Dynamic);
335                    }
336
337                    if *self.deactivate_colliders {
338                        for child in limb_body.children() {
339                            if let Ok(mut collider) =
340                                mbc.try_get_component_of_type_mut::<Collider>(*child)
341                            {
342                                collider.set_is_sensor(false);
343                            }
344                        }
345                    }
346
347                    let body_transform = limb_body.global_transform();
348
349                    // Sync transform of the bone with respective body.
350                    let bone_parent = mbc.try_get(limb.bone).unwrap().parent();
351                    let transform: Matrix4<f32> = mbc
352                        .try_get(bone_parent)
353                        .unwrap()
354                        .global_transform()
355                        .try_inverse()
356                        .unwrap_or_else(Matrix4::identity)
357                        * body_transform;
358
359                    mbc.try_get_mut(limb.bone)
360                        .unwrap()
361                        .local_transform_mut()
362                        .set_position(Vector3::new(transform[12], transform[13], transform[14]))
363                        .set_pre_rotation(UnitQuaternion::identity())
364                        .set_post_rotation(UnitQuaternion::identity())
365                        .set_rotation(UnitQuaternion::from_matrix_eps(
366                            &transform.basis(),
367                            f32::EPSILON,
368                            16,
369                            Default::default(),
370                        ));
371
372                    need_update_transform = true;
373                } else {
374                    limb_body.set_body_type(RigidBodyType::KinematicPositionBased);
375                    limb_body.set_lin_vel(Default::default());
376                    limb_body.set_ang_vel(Default::default());
377
378                    if *self.deactivate_colliders {
379                        for child in limb_body.children() {
380                            if let Ok(mut collider) =
381                                mbc.try_get_component_of_type_mut::<Collider>(*child)
382                            {
383                                collider.set_is_sensor(true);
384                            }
385                        }
386                    }
387
388                    let self_transform_inverse =
389                        self.global_transform().try_inverse().unwrap_or_default();
390
391                    // Sync transform of the physical body with respective bone.
392                    if let Ok(bone) = mbc.try_get(limb.bone) {
393                        let relative_transform = self_transform_inverse * bone.global_transform();
394
395                        let position = Vector3::new(
396                            relative_transform[12],
397                            relative_transform[13],
398                            relative_transform[14],
399                        );
400                        let rotation = UnitQuaternion::from_matrix_eps(
401                            &relative_transform.basis(),
402                            f32::EPSILON,
403                            16,
404                            Default::default(),
405                        );
406                        limb_body
407                            .local_transform_mut()
408                            .set_position(position)
409                            .set_rotation(rotation);
410                    }
411                }
412            };
413
414            drop(mbc);
415
416            if need_update_transform {
417                // Calculate transform of the descendants explicitly, so the next bones in hierarchy will have new transform
418                // that can be used to calculate relative transform.
419                Graph::update_hierarchical_data_recursively(
420                    ctx.nodes,
421                    ctx.sound_context,
422                    ctx.physics,
423                    ctx.physics2d,
424                    limb.bone,
425                );
426            }
427        });
428
429        if let Some(root_limb_body) = ctx.nodes.try_borrow(self.root_limb.bone) {
430            let position = root_limb_body.global_position();
431            if let Some(character_rigid_body) = ctx
432                .nodes
433                .try_borrow_mut(*self.character_rigid_body)
434                .and_then(|n| n.component_mut::<RigidBody>())
435            {
436                if *self.is_active {
437                    character_rigid_body.set_lin_vel(Default::default());
438                    character_rigid_body.set_ang_vel(Default::default());
439                    character_rigid_body
440                        .local_transform_mut()
441                        .set_position(position);
442                    character_rigid_body.set_body_type(RigidBodyType::KinematicPositionBased);
443                } else {
444                    character_rigid_body.set_body_type(RigidBodyType::Dynamic);
445                }
446            }
447        }
448    }
449}
450
451/// Ragdoll builder creates [`Ragdoll`] scene nodes.
452pub struct RagdollBuilder {
453    base_builder: BaseBuilder,
454    character_rigid_body: Handle<Node>,
455    is_active: bool,
456    deactivate_colliders: bool,
457    root_limb: Limb,
458}
459
460impl RagdollBuilder {
461    /// Creates a new ragdoll builder.
462    pub fn new(base_builder: BaseBuilder) -> Self {
463        Self {
464            base_builder,
465            character_rigid_body: Default::default(),
466            is_active: true,
467            deactivate_colliders: false,
468            root_limb: Default::default(),
469        }
470    }
471
472    /// Sets the desired character rigid body.
473    pub fn with_character_rigid_body(mut self, handle: Handle<Node>) -> Self {
474        self.character_rigid_body = handle;
475        self
476    }
477
478    /// Sets whether the ragdoll is active or not.
479    pub fn with_active(mut self, active: bool) -> Self {
480        self.is_active = active;
481        self
482    }
483
484    /// Sets the desired root limb.
485    pub fn with_root_limb(mut self, root_limb: Limb) -> Self {
486        self.root_limb = root_limb;
487        self
488    }
489
490    /// Sets whether the ragdoll should deactivate colliders of its limbs when it is not active or not.
491    pub fn with_deactivate_colliders(mut self, value: bool) -> Self {
492        self.deactivate_colliders = value;
493        self
494    }
495
496    /// Builds the ragdoll.
497    pub fn build_ragdoll(self) -> Ragdoll {
498        Ragdoll {
499            base: self.base_builder.build_base(),
500            character_rigid_body: self.character_rigid_body.into(),
501            is_active: self.is_active.into(),
502            root_limb: self.root_limb.into(),
503            deactivate_colliders: self.deactivate_colliders.into(),
504            prev_enabled: self.is_active,
505        }
506    }
507
508    /// Creates ragdoll node, but does not add it to a graph.
509    pub fn build_node(self) -> Node {
510        Node::new(self.build_ragdoll())
511    }
512
513    /// Creates the ragdoll node and adds it to the given graph.
514    pub fn build(self, graph: &mut Graph) -> Handle<Node> {
515        graph.add_node(self.build_node())
516    }
517}