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 derived_types() -> &'static [TypeId] {
75        &[]
76    }
77
78    fn query_derived_types(&self) -> &'static [TypeId] {
79        Self::derived_types()
80    }
81
82    fn type_name(&self) -> &'static str {
83        type_name::<Self>()
84    }
85
86    fn doc(&self) -> &'static str {
87        ""
88    }
89
90    fn assembly_name(&self) -> &'static str {
91        env!("CARGO_PKG_NAME")
92    }
93
94    fn type_assembly_name() -> &'static str {
95        env!("CARGO_PKG_NAME")
96    }
97
98    fn fields_ref(&self, func: &mut dyn FnMut(&[FieldRef])) {
99        func(&[
100            {
101                static METADATA: FieldMetadata = FieldMetadata {
102                    name: "Bone",
103                    display_name: "Bone",
104                    tag: "",
105                    read_only: false,
106                    immutable_collection: false,
107                    min_value: None,
108                    max_value: None,
109                    step: None,
110                    precision: None,
111                    doc: "",
112                };
113                FieldRef {
114                    metadata: &METADATA,
115                    value: &self.bone,
116                }
117            },
118            {
119                static METADATA: FieldMetadata = FieldMetadata {
120                    name: "PhysicalBone",
121                    display_name: "Physical Bone",
122                    tag: "",
123                    read_only: false,
124                    immutable_collection: false,
125                    min_value: None,
126                    max_value: None,
127                    step: None,
128                    precision: None,
129                    doc: "",
130                };
131                FieldRef {
132                    metadata: &METADATA,
133                    value: &self.physical_bone,
134                }
135            },
136            {
137                static METADATA: FieldMetadata = FieldMetadata {
138                    name: "Children",
139                    display_name: "Children",
140                    tag: "",
141                    read_only: false,
142                    immutable_collection: false,
143                    min_value: None,
144                    max_value: None,
145                    step: None,
146                    precision: None,
147                    doc: "",
148                };
149                FieldRef {
150                    metadata: &METADATA,
151                    value: &self.children,
152                }
153            },
154        ])
155    }
156
157    fn fields_mut(&mut self, func: &mut dyn FnMut(&mut [FieldMut])) {
158        func(&mut [
159            {
160                static METADATA: FieldMetadata = FieldMetadata {
161                    name: "Bone",
162                    display_name: "Bone",
163                    tag: "",
164                    read_only: false,
165                    immutable_collection: false,
166                    min_value: None,
167                    max_value: None,
168                    step: None,
169                    precision: None,
170                    doc: "",
171                };
172                FieldMut {
173                    metadata: &METADATA,
174                    value: &mut self.bone,
175                }
176            },
177            {
178                static METADATA: FieldMetadata = FieldMetadata {
179                    name: "PhysicalBone",
180                    display_name: "Physical Bone",
181                    tag: "",
182                    read_only: false,
183                    immutable_collection: false,
184                    min_value: None,
185                    max_value: None,
186                    step: None,
187                    precision: None,
188                    doc: "",
189                };
190                FieldMut {
191                    metadata: &METADATA,
192                    value: &mut self.physical_bone,
193                }
194            },
195            {
196                static METADATA: FieldMetadata = FieldMetadata {
197                    name: "Children",
198                    display_name: "Children",
199                    tag: "",
200                    read_only: false,
201                    immutable_collection: false,
202                    min_value: None,
203                    max_value: None,
204                    step: None,
205                    precision: None,
206                    doc: "",
207                };
208                FieldMut {
209                    metadata: &METADATA,
210                    value: &mut self.children,
211                }
212            },
213        ])
214    }
215
216    fn into_any(self: Box<Self>) -> Box<dyn Any> {
217        self
218    }
219
220    fn as_any(&self, func: &mut dyn FnMut(&dyn Any)) {
221        func(self)
222    }
223
224    fn as_any_mut(&mut self, func: &mut dyn FnMut(&mut dyn Any)) {
225        func(self)
226    }
227
228    fn as_reflect(&self, func: &mut dyn FnMut(&dyn Reflect)) {
229        func(self)
230    }
231
232    fn as_reflect_mut(&mut self, func: &mut dyn FnMut(&mut dyn Reflect)) {
233        func(self)
234    }
235
236    fn set(&mut self, value: Box<dyn Reflect>) -> Result<Box<dyn Reflect>, Box<dyn Reflect>> {
237        let this = std::mem::replace(self, value.take()?);
238        Ok(Box::new(this))
239    }
240
241    fn try_clone_box(&self) -> Option<Box<dyn Reflect>> {
242        Some(Box::new(self.clone()))
243    }
244}
245
246impl Visit for Limb {
247    fn visit(&mut self, name: &str, visitor: &mut Visitor) -> VisitResult {
248        let mut guard = visitor.enter_region(name)?;
249
250        self.bone.visit("Bone", &mut guard)?;
251        self.physical_bone.visit("PhysicalBone", &mut guard)?;
252        self.children.visit("Children", &mut guard)?;
253
254        Ok(())
255    }
256}
257
258impl Limb {
259    /// Iterates recursively across the entire tree of descendant limbs and does the specified action
260    /// with every limb along the way.
261    pub fn iterate_recursive<F>(&self, func: &mut F)
262    where
263        F: FnMut(&Self),
264    {
265        func(self);
266
267        for child in self.children.iter() {
268            child.iterate_recursive(func)
269        }
270    }
271}
272
273/// Ragdoll is a set of rigid bodies linked with various joints, which can control a set of bones
274/// of a mesh. Ragdolls are used mostly for body physics.
275///
276/// ## How to create
277///
278/// Usually, bodies have quite complex hierarchy of bones and total count of the bones could be 30+.
279/// Manual creation of such ragdoll is very tedious and counterproductive. That's why the best way
280/// to create a ragdoll is to use the editor, and the ragdoll wizard in particular. However, if
281/// you're brave enough you can read this code <https://github.com/FyroxEngine/Fyrox/blob/master/editor/src/utils/ragdoll.rs> -
282/// it creates a ragdoll using a humanoid skeleton.  
283#[derive(Clone, Reflect, Visit, Debug, Default, ComponentProvider)]
284#[reflect(derived_type = "Node")]
285#[visit(optional)]
286pub struct Ragdoll {
287    base: Base,
288    /// A handle to a main rigid body of the character to which this ragdoll belongs to. If set, the
289    /// ragdoll will take control over the collider and will move it together with the root limb.
290    pub character_rigid_body: InheritableVariable<Handle<Node>>,
291    /// A flag, that defines whether the ragdoll is active or not. Active ragdoll enables limb rigid
292    /// bodies and takes control over `character_rigid_body` (if set).
293    pub is_active: InheritableVariable<bool>,
294    /// Root limb of the ragdoll. Usually it is hips of the body and rest of the limbs are forming
295    /// the rest of the hierarchy.
296    pub root_limb: InheritableVariable<Limb>,
297    /// A flag, that defines whether the ragdoll will deactivate colliders when it is not active or not.
298    /// This option could be useful if you want to disable physics of limbs while the ragdoll is active.
299    pub deactivate_colliders: InheritableVariable<bool>,
300    #[reflect(hidden)]
301    prev_enabled: bool,
302}
303
304impl Deref for Ragdoll {
305    type Target = Base;
306
307    fn deref(&self) -> &Self::Target {
308        &self.base
309    }
310}
311
312impl DerefMut for Ragdoll {
313    fn deref_mut(&mut self) -> &mut Self::Target {
314        &mut self.base
315    }
316}
317
318impl TypeUuidProvider for Ragdoll {
319    fn type_uuid() -> Uuid {
320        uuid!("f4441683-dcef-472d-9d7d-4adca4579107")
321    }
322}
323
324impl ConstructorProvider<Node, Graph> for Ragdoll {
325    fn constructor() -> NodeConstructor {
326        NodeConstructor::new::<Self>()
327            .with_variant("Ragdoll", |_| {
328                RagdollBuilder::new(BaseBuilder::new().with_name("Ragdoll"))
329                    .build_node()
330                    .into()
331            })
332            .with_group("Physics")
333    }
334}
335
336impl NodeTrait for Ragdoll {
337    fn local_bounding_box(&self) -> AxisAlignedBoundingBox {
338        self.base.local_bounding_box()
339    }
340
341    fn world_bounding_box(&self) -> AxisAlignedBoundingBox {
342        self.base.world_bounding_box()
343    }
344
345    fn id(&self) -> Uuid {
346        Self::type_uuid()
347    }
348
349    fn update(&mut self, ctx: &mut UpdateContext) {
350        // Get linear and angular velocities of the character rigid body and transfer it onto rag doll bodies when it is just activated.
351        let mut new_lin_vel = None;
352        let mut new_ang_vel = None;
353        if *self.is_active && !self.prev_enabled {
354            if let Some(character_rigid_body) = ctx
355                .nodes
356                .try_borrow_mut(*self.character_rigid_body)
357                .and_then(|n| n.component_mut::<RigidBody>())
358            {
359                new_lin_vel = Some(character_rigid_body.lin_vel());
360                new_ang_vel = Some(character_rigid_body.ang_vel());
361            }
362        }
363        self.prev_enabled = *self.is_active;
364
365        self.root_limb.iterate_recursive(&mut |limb| {
366            let mbc = ctx.nodes.begin_multi_borrow();
367
368            let mut need_update_transform = false;
369
370            if let Ok(mut limb_body) =
371                mbc.try_get_component_of_type_mut::<RigidBody>(limb.physical_bone)
372            {
373                if *self.is_active {
374                    // Transfer linear and angular velocities to rag doll bodies.
375                    if let Some(lin_vel) = new_lin_vel {
376                        limb_body.set_lin_vel(lin_vel);
377                    }
378                    if let Some(ang_vel) = new_ang_vel {
379                        limb_body.set_ang_vel(ang_vel);
380                    }
381
382                    if limb_body.body_type() != RigidBodyType::Dynamic {
383                        limb_body.set_body_type(RigidBodyType::Dynamic);
384                    }
385
386                    if *self.deactivate_colliders {
387                        for child in limb_body.children() {
388                            if let Ok(mut collider) =
389                                mbc.try_get_component_of_type_mut::<Collider>(*child)
390                            {
391                                collider.set_is_sensor(false);
392                            }
393                        }
394                    }
395
396                    let body_transform = limb_body.global_transform();
397
398                    // Sync transform of the bone with respective body.
399                    let bone_parent = mbc.try_get(limb.bone).unwrap().parent();
400                    let transform: Matrix4<f32> = mbc
401                        .try_get(bone_parent)
402                        .unwrap()
403                        .global_transform()
404                        .try_inverse()
405                        .unwrap_or_else(Matrix4::identity)
406                        * body_transform;
407
408                    mbc.try_get_mut(limb.bone)
409                        .unwrap()
410                        .local_transform_mut()
411                        .set_position(Vector3::new(transform[12], transform[13], transform[14]))
412                        .set_pre_rotation(UnitQuaternion::identity())
413                        .set_post_rotation(UnitQuaternion::identity())
414                        .set_rotation(UnitQuaternion::from_matrix_eps(
415                            &transform.basis(),
416                            f32::EPSILON,
417                            16,
418                            Default::default(),
419                        ));
420
421                    need_update_transform = true;
422                } else {
423                    limb_body.set_body_type(RigidBodyType::KinematicPositionBased);
424                    limb_body.set_lin_vel(Default::default());
425                    limb_body.set_ang_vel(Default::default());
426
427                    if *self.deactivate_colliders {
428                        for child in limb_body.children() {
429                            if let Ok(mut collider) =
430                                mbc.try_get_component_of_type_mut::<Collider>(*child)
431                            {
432                                collider.set_is_sensor(true);
433                            }
434                        }
435                    }
436
437                    let self_transform_inverse =
438                        self.global_transform().try_inverse().unwrap_or_default();
439
440                    // Sync transform of the physical body with respective bone.
441                    if let Ok(bone) = mbc.try_get(limb.bone) {
442                        let relative_transform = self_transform_inverse * bone.global_transform();
443
444                        let position = Vector3::new(
445                            relative_transform[12],
446                            relative_transform[13],
447                            relative_transform[14],
448                        );
449                        let rotation = UnitQuaternion::from_matrix_eps(
450                            &relative_transform.basis(),
451                            f32::EPSILON,
452                            16,
453                            Default::default(),
454                        );
455                        limb_body
456                            .local_transform_mut()
457                            .set_position(position)
458                            .set_rotation(rotation);
459                    }
460                }
461            };
462
463            drop(mbc);
464
465            if need_update_transform {
466                // Calculate transform of the descendants explicitly, so the next bones in hierarchy will have new transform
467                // that can be used to calculate relative transform.
468                Graph::update_hierarchical_data_recursively(
469                    ctx.nodes,
470                    ctx.sound_context,
471                    ctx.physics,
472                    ctx.physics2d,
473                    limb.bone,
474                );
475            }
476        });
477
478        if let Some(root_limb_body) = ctx.nodes.try_borrow(self.root_limb.bone) {
479            let position = root_limb_body.global_position();
480            if let Some(character_rigid_body) = ctx
481                .nodes
482                .try_borrow_mut(*self.character_rigid_body)
483                .and_then(|n| n.component_mut::<RigidBody>())
484            {
485                if *self.is_active {
486                    character_rigid_body.set_lin_vel(Default::default());
487                    character_rigid_body.set_ang_vel(Default::default());
488                    character_rigid_body
489                        .local_transform_mut()
490                        .set_position(position);
491                    character_rigid_body.set_body_type(RigidBodyType::KinematicPositionBased);
492                } else {
493                    character_rigid_body.set_body_type(RigidBodyType::Dynamic);
494                }
495            }
496        }
497    }
498}
499
500/// Ragdoll builder creates [`Ragdoll`] scene nodes.
501pub struct RagdollBuilder {
502    base_builder: BaseBuilder,
503    character_rigid_body: Handle<Node>,
504    is_active: bool,
505    deactivate_colliders: bool,
506    root_limb: Limb,
507}
508
509impl RagdollBuilder {
510    /// Creates a new ragdoll builder.
511    pub fn new(base_builder: BaseBuilder) -> Self {
512        Self {
513            base_builder,
514            character_rigid_body: Default::default(),
515            is_active: true,
516            deactivate_colliders: false,
517            root_limb: Default::default(),
518        }
519    }
520
521    /// Sets the desired character rigid body.
522    pub fn with_character_rigid_body(mut self, handle: Handle<Node>) -> Self {
523        self.character_rigid_body = handle;
524        self
525    }
526
527    /// Sets whether the ragdoll is active or not.
528    pub fn with_active(mut self, active: bool) -> Self {
529        self.is_active = active;
530        self
531    }
532
533    /// Sets the desired root limb.
534    pub fn with_root_limb(mut self, root_limb: Limb) -> Self {
535        self.root_limb = root_limb;
536        self
537    }
538
539    /// Sets whether the ragdoll should deactivate colliders of its limbs when it is not active or not.
540    pub fn with_deactivate_colliders(mut self, value: bool) -> Self {
541        self.deactivate_colliders = value;
542        self
543    }
544
545    /// Builds the ragdoll.
546    pub fn build_ragdoll(self) -> Ragdoll {
547        Ragdoll {
548            base: self.base_builder.build_base(),
549            character_rigid_body: self.character_rigid_body.into(),
550            is_active: self.is_active.into(),
551            root_limb: self.root_limb.into(),
552            deactivate_colliders: self.deactivate_colliders.into(),
553            prev_enabled: self.is_active,
554        }
555    }
556
557    /// Creates ragdoll node, but does not add it to a graph.
558    pub fn build_node(self) -> Node {
559        Node::new(self.build_ragdoll())
560    }
561
562    /// Creates the ragdoll node and adds it to the given graph.
563    pub fn build(self, graph: &mut Graph) -> Handle<Node> {
564        graph.add_node(self.build_node())
565    }
566}