Skip to content

Commit

Permalink
fixed transform syncing of colliders
Browse files Browse the repository at this point in the history
  • Loading branch information
mrDIMAS committed Oct 29, 2024
1 parent 4dfccfa commit fd182e5
Show file tree
Hide file tree
Showing 14 changed files with 86 additions and 44 deletions.
2 changes: 1 addition & 1 deletion fyrox-impl/src/engine/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2201,7 +2201,7 @@ impl Engine {
// "teleportation" bug (when an object is drawn at (0,0,0) for one frame and on the one
// draws where it should be).
for scene in self.scenes.iter_mut() {
scene.graph.process_node_messages();
scene.graph.process_node_messages(None);
}

ctx.renderer.render_and_swap_buffers(
Expand Down
4 changes: 0 additions & 4 deletions fyrox-impl/src/scene/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -468,9 +468,6 @@ pub struct Base {
#[reflect(setter = "set_frustum_culling")]
frustum_culling: InheritableVariable<bool>,

#[reflect(hidden)]
pub(crate) transform_modified: Cell<bool>,

// When `true` it means that this node is instance of `resource`.
// More precisely - this node is root of whole descendant nodes
// hierarchy which was instantiated from resource.
Expand Down Expand Up @@ -1396,7 +1393,6 @@ impl BaseBuilder {
mobility: self.mobility.into(),
tag: self.tag.into(),
properties: Default::default(),
transform_modified: Cell::new(false),
frustum_culling: self.frustum_culling.into(),
cast_shadows: self.cast_shadows.into(),
scripts: self.scripts,
Expand Down
14 changes: 14 additions & 0 deletions fyrox-impl/src/scene/collider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ use crate::{
Scene,
},
};
use fyrox_core::algebra::{Isometry3, Translation3};
use fyrox_core::uuid_provider;
use fyrox_graph::BaseSceneGraph;
use rapier3d::geometry::{self, ColliderHandle};
Expand Down Expand Up @@ -879,6 +880,19 @@ impl NodeTrait for Collider {
}
}

fn on_local_transform_changed(&self, context: &mut SyncContext) {
if self.native.get() != ColliderHandle::invalid() {
if let Some(native) = context.physics.colliders.get_mut(self.native.get()) {
native.set_position_wrt_parent(Isometry3 {
rotation: **self.local_transform().rotation(),
translation: Translation3 {
vector: **self.local_transform().position(),
},
});
}
}
}

fn sync_native(&self, self_handle: Handle<Node>, context: &mut SyncContext) {
context
.physics
Expand Down
16 changes: 16 additions & 0 deletions fyrox-impl/src/scene/dim2/collider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ use crate::{
Scene,
},
};
use fyrox_core::algebra::{Isometry2, Translation2, UnitComplex};
use fyrox_core::uuid_provider;
use fyrox_graph::BaseSceneGraph;
use rapier2d::geometry::ColliderHandle;
Expand Down Expand Up @@ -596,6 +597,21 @@ impl NodeTrait for Collider {
}
}

fn on_local_transform_changed(&self, context: &mut SyncContext) {
if self.native.get() != ColliderHandle::invalid() {
if let Some(native) = context.physics2d.colliders.get_mut(self.native.get()) {
native.set_position_wrt_parent(Isometry2 {
rotation: UnitComplex::from_angle(
self.local_transform().rotation().euler_angles().2,
),
translation: Translation2 {
vector: self.local_transform().position().xy(),
},
});
}
}
}

fn sync_native(&self, self_handle: Handle<Node>, context: &mut SyncContext) {
context
.physics2d
Expand Down
6 changes: 5 additions & 1 deletion fyrox-impl/src/scene/dim2/joint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,11 @@ impl NodeTrait for Joint {
.sync_to_joint_node(context.nodes, self_handle, self);
}

fn sync_transform(&self, new_global_transform: &Matrix4<f32>, _context: &mut SyncContext) {
fn on_global_transform_changed(
&self,
new_global_transform: &Matrix4<f32>,
_context: &mut SyncContext,
) {
if !m4x4_approx_eq(new_global_transform, &self.global_transform()) {
self.local_frames.borrow_mut().take();
}
Expand Down
16 changes: 2 additions & 14 deletions fyrox-impl/src/scene/dim2/physics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -485,7 +485,7 @@ pub struct PhysicsWorld {
// A container of colliders.
#[visit(skip)]
#[reflect(hidden)]
colliders: ColliderSet,
pub(crate) colliders: ColliderSet,
// A container of impulse joints.
#[visit(skip)]
#[reflect(hidden)]
Expand Down Expand Up @@ -1094,8 +1094,7 @@ impl PhysicsWorld {
return;
}

let anything_changed =
collider_node.transform_modified.get() || collider_node.needs_sync_model();
let anything_changed = collider_node.needs_sync_model();

// Important notes!
// 1) The collider node may lack backing native physics collider in case if it
Expand All @@ -1105,17 +1104,6 @@ impl PhysicsWorld {
if collider_node.native.get() != ColliderHandle::invalid() {
if anything_changed {
if let Some(native) = self.colliders.get_mut(collider_node.native.get()) {
if collider_node.transform_modified.get() {
native.set_position_wrt_parent(Isometry2 {
rotation: UnitComplex::from_angle(
collider_node.local_transform().rotation().euler_angles().2,
),
translation: Translation2 {
vector: collider_node.local_transform().position().xy(),
},
});
}

collider_node
.restitution
.try_sync_model(|v| native.set_restitution(v));
Expand Down
6 changes: 5 additions & 1 deletion fyrox-impl/src/scene/dim2/rigidbody.rs
Original file line number Diff line number Diff line change
Expand Up @@ -449,7 +449,11 @@ impl NodeTrait for RigidBody {
context.physics2d.sync_to_rigid_body_node(self_handle, self);
}

fn sync_transform(&self, new_global_transform: &Matrix4<f32>, context: &mut SyncContext) {
fn on_global_transform_changed(
&self,
new_global_transform: &Matrix4<f32>,
context: &mut SyncContext,
) {
if !m4x4_approx_eq(new_global_transform, &self.global_transform()) {
context
.physics2d
Expand Down
21 changes: 16 additions & 5 deletions fyrox-impl/src/scene/graph/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -875,7 +875,7 @@ impl Graph {
let new_global_transform = parent_global_transform * node.local_transform().matrix();

// TODO: Detect changes from user code here.
node.sync_transform(
node.on_global_transform_changed(
&new_global_transform,
&mut SyncContext {
nodes,
Expand Down Expand Up @@ -956,7 +956,7 @@ impl Graph {
// Performance of this method is detached from the amount of scene nodes in the graph and only
// correlates with the amount of changing nodes, allowing to have large scene graphs with tons
// of static nodes.
pub(crate) fn process_node_messages(&mut self) {
pub(crate) fn process_node_messages(&mut self, switches: Option<&GraphUpdateSwitches>) {
bitflags! {
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
struct Flags: u8 {
Expand All @@ -971,6 +971,19 @@ impl Graph {
let mut roots = FxHashMap::default();

while let Ok(message) = self.message_receiver.try_recv() {
if let NodeMessageKind::TransformChanged = message.kind {
if let Some(node) = self.pool.try_borrow(message.node) {
node.on_local_transform_changed(&mut SyncContext {
nodes: &self.pool,
physics: &mut self.physics,
physics2d: &mut self.physics2d,
sound_context: &mut self.sound_context,
switches,
})
}
}

// Prepare for hierarchy propagation.
let message_flag = match message.kind {
NodeMessageKind::TransformChanged => Flags::TRANSFORM_CHANGED,
NodeMessageKind::VisibilityChanged => Flags::VISIBILITY_CHANGED,
Expand Down Expand Up @@ -1063,8 +1076,6 @@ impl Graph {
delete_dead_nodes: bool,
) {
if let Some((ticket, mut node)) = self.pool.try_take_reserve(handle) {
node.transform_modified.set(false);

let mut is_alive = node.is_alive();

if node.is_globally_enabled() {
Expand Down Expand Up @@ -1109,7 +1120,7 @@ impl Graph {
}

let last_time = instant::Instant::now();
self.process_node_messages();
self.process_node_messages(Some(&switches));
self.performance_statistics.hierarchical_properties_time =
instant::Instant::now() - last_time;

Expand Down
14 changes: 2 additions & 12 deletions fyrox-impl/src/scene/graph/physics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -995,7 +995,7 @@ pub struct PhysicsWorld {
// A container of colliders.
#[visit(skip)]
#[reflect(hidden)]
colliders: ColliderSet,
pub(crate) colliders: ColliderSet,
// A container of impulse joints.
#[visit(skip)]
#[reflect(hidden)]
Expand Down Expand Up @@ -1627,8 +1627,7 @@ impl PhysicsWorld {
return;
}

let anything_changed =
collider_node.transform_modified.get() || collider_node.needs_sync_model();
let anything_changed = collider_node.needs_sync_model();

// Important notes!
// 1) The collider node may lack backing native physics collider in case if it
Expand All @@ -1638,15 +1637,6 @@ impl PhysicsWorld {
if collider_node.native.get() != ColliderHandle::invalid() {
if anything_changed {
if let Some(native) = self.colliders.get_mut(collider_node.native.get()) {
if collider_node.transform_modified.get() {
native.set_position_wrt_parent(Isometry3 {
rotation: **collider_node.local_transform().rotation(),
translation: Translation3 {
vector: **collider_node.local_transform().position(),
},
});
}

collider_node
.restitution
.try_sync_model(|v| native.set_restitution(v));
Expand Down
6 changes: 5 additions & 1 deletion fyrox-impl/src/scene/joint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -383,7 +383,11 @@ impl NodeTrait for Joint {
.sync_to_joint_node(context.nodes, self_handle, self);
}

fn sync_transform(&self, new_global_transform: &Matrix4<f32>, _context: &mut SyncContext) {
fn on_global_transform_changed(
&self,
new_global_transform: &Matrix4<f32>,
_context: &mut SyncContext,
) {
if *self.auto_rebind && !m4x4_approx_eq(new_global_transform, &self.global_transform()) {
self.local_frames.borrow_mut().take();
}
Expand Down
6 changes: 5 additions & 1 deletion fyrox-impl/src/scene/mesh/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -575,7 +575,11 @@ impl NodeTrait for Mesh {
Self::type_uuid()
}

fn sync_transform(&self, _new_global_transform: &Matrix4<f32>, context: &mut SyncContext) {
fn on_global_transform_changed(
&self,
_new_global_transform: &Matrix4<f32>,
context: &mut SyncContext,
) {
if self.surfaces.iter().any(|s| !s.bones.is_empty()) {
let mut world_aabb = self
.local_bounding_box()
Expand Down
7 changes: 5 additions & 2 deletions fyrox-impl/src/scene/node/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,13 +181,16 @@ pub trait NodeTrait: BaseNodeTrait + Reflect + Visit + ComponentProvider {
}

/// Called when node's global transform changes.
fn sync_transform(
fn on_global_transform_changed(
&self,
#[allow(unused_variables)] new_global_transform: &Matrix4<f32>,
_context: &mut SyncContext,
#[allow(unused_variables)] context: &mut SyncContext,
) {
}

/// Called when node's local transform changed.
fn on_local_transform_changed(&self, #[allow(unused_variables)] context: &mut SyncContext) {}

/// The methods is used to manage lifetime of scene nodes, depending on their internal logic.
fn is_alive(&self) -> bool {
true
Expand Down
6 changes: 5 additions & 1 deletion fyrox-impl/src/scene/rigidbody.rs
Original file line number Diff line number Diff line change
Expand Up @@ -553,7 +553,11 @@ impl NodeTrait for RigidBody {
context.physics.sync_to_rigid_body_node(self_handle, self);
}

fn sync_transform(&self, new_global_transform: &Matrix4<f32>, context: &mut SyncContext) {
fn on_global_transform_changed(
&self,
new_global_transform: &Matrix4<f32>,
context: &mut SyncContext,
) {
if !m4x4_approx_eq(new_global_transform, &self.global_transform()) {
context
.physics
Expand Down
6 changes: 5 additions & 1 deletion fyrox-impl/src/scene/sound/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -414,7 +414,11 @@ impl NodeTrait for Sound {
)
}

fn sync_transform(&self, new_global_transform: &Matrix4<f32>, context: &mut SyncContext) {
fn on_global_transform_changed(
&self,
new_global_transform: &Matrix4<f32>,
context: &mut SyncContext,
) {
if !m4x4_approx_eq(new_global_transform, &self.global_transform()) {
context.sound_context.set_sound_position(self);
}
Expand Down

0 comments on commit fd182e5

Please sign in to comment.