Skip to content

Commit

Permalink
Read back translation etc. from world to physx. Fixes #57
Browse files Browse the repository at this point in the history
  • Loading branch information
FredrikNoren committed Feb 13, 2023
1 parent 8de55a2 commit cafd188
Show file tree
Hide file tree
Showing 11 changed files with 112 additions and 180 deletions.
2 changes: 1 addition & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
"DIMS_DISABLE_TIMEOUT": "true"
},
"args": [
"--project-path=guest/rust/examples/skinmesh",
"--project-path=guest/rust/examples/physics",
"run"
],
"cwd": "${workspaceFolder}",
Expand Down
50 changes: 28 additions & 22 deletions crates/editor/src/intents.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,13 @@ use glam::{Mat4, Quat, Vec3, Vec3Swizzles};
use itertools::{izip, process_results, Itertools};
use kiwi_core::{
self, selectable, snap_to_ground,
transform::{get_world_transform, translation},
transform::{get_world_transform, rotation, scale, translation},
};
use kiwi_ecs::{components, EntityData, EntityId, World};
use kiwi_intent::{use_old_state, IntentContext, IntentRegistry};
use kiwi_network::get_player_by_user_id;
use kiwi_physics::{
collider::collider_shapes_convex,
helpers::{transform_entity, transform_entity_parts},
main_physics_scene,
physx::rigid_actor,
PxShapeUserData,
};
use kiwi_physics::{collider::collider_shapes_convex, main_physics_scene, physx::rigid_actor, PxShapeUserData};

use kiwi_std::{
log_result,
shapes::{Ray, Shape, AABB},
Expand Down Expand Up @@ -45,7 +40,10 @@ fn undo_transform(ctx: IntentContext, undo_state: Vec<IntentTransformRevert>) ->
world.remove_component(id, snap_to_ground()).expect("Invalid entity")
}

transform_entity(world, id, state.transform, false).ok();
let (scl, rot, pos) = state.transform.to_scale_rotation_translation();
world.set_if_changed(id, translation(), pos);
world.set_if_changed(id, rotation(), rot);
world.set_if_changed(id, scale(), scl);
}

Ok(())
Expand Down Expand Up @@ -320,17 +318,17 @@ pub fn register_intents(reg: &mut IntentRegistry) {
{
let old_snap_to_ground = world.get(id, snap_to_ground()).ok();

let (scale, rot, pos) = transform.to_scale_rotation_translation();
let (scl, rot, pos) = transform.to_scale_rotation_translation();

// World space position
let new_pos = pos - midpoint + target;
tracing::debug!(?midpoint, "Moving {uid} {pos} => {new_pos}");

update_snap_to_ground(world, id, pos);

let res = transform_entity_parts(world, id, new_pos, rot, scale).context("Failed to transform entity {id}");

log_result!(res);
world.set_if_changed(id, translation(), new_pos);
world.set_if_changed(id, rotation(), rot);
world.set_if_changed(id, scale(), scl);

Ok(IntentTransformRevert { snap_to_ground: old_snap_to_ground, transform, uid })
}
Expand Down Expand Up @@ -375,17 +373,17 @@ pub fn register_intents(reg: &mut IntentRegistry) {
.map(|(uid, id, transform): (_, _, Mat4)| {
let old_snap_to_ground = world.get(id, snap_to_ground()).ok();

let (scale, rot, pos) = transform.to_scale_rotation_translation();
let (scl, rot, pos) = transform.to_scale_rotation_translation();

// World space position
let new_pos = pos - midpoint + position;
tracing::debug!(?midpoint, "Moving {uid} {pos} => {new_pos}");

update_snap_to_ground(world, id, pos);

let res = transform_entity_parts(world, id, new_pos, rot, scale).context("Failed to transform entity {id}");

log_result!(res);
world.set_if_changed(id, translation(), new_pos);
world.set_if_changed(id, rotation(), rot);
world.set_if_changed(id, scale(), scl);

Ok(IntentTransformRevert { snap_to_ground: old_snap_to_ground, transform, uid })
})
Expand All @@ -407,13 +405,15 @@ pub fn register_intents(reg: &mut IntentRegistry) {
.map(|(&id, transform)| {
let old_transform = get_world_transform(world, id).context("No transform")?;

let (scale, rot, pos) = transform.to_scale_rotation_translation();
let (scl, rot, pos) = transform.to_scale_rotation_translation();

let old_snap_to_ground = world.get(id, snap_to_ground()).ok();

update_snap_to_ground(world, id, pos);

transform_entity_parts(world, id, pos, rot, scale).context("Failed to transform entity")?;
world.set_if_changed(id, translation(), pos);
world.set_if_changed(id, rotation(), rot);
world.set_if_changed(id, scale(), scl);

Ok(IntentTransformRevert { transform: old_transform, snap_to_ground: old_snap_to_ground, uid: id })
})
Expand All @@ -429,7 +429,10 @@ pub fn register_intents(reg: &mut IntentRegistry) {
world.remove_component(id, snap_to_ground()).expect("Invalid entity")
}

transform_entity(world, id, old_state.transform, false).ok();
let (scl, rot, pos) = old_state.transform.to_scale_rotation_translation();
world.set_if_changed(id, translation(), pos);
world.set_if_changed(id, rotation(), rot);
world.set_if_changed(id, scale(), scl);
}
Ok(())
},
Expand All @@ -446,12 +449,15 @@ pub fn register_intents(reg: &mut IntentRegistry) {
.iter()
.map(|&id| {
let transform = get_world_transform(world, id).context("No transform")?;
let (scale, rot, pos) = transform.to_scale_rotation_translation();
let (scl, rot, pos) = transform.to_scale_rotation_translation();

set_snap_to_ground(world, id, intent.1);

let old_snap_to_ground = world.get(id, snap_to_ground()).ok();
transform_entity_parts(world, id, pos, rot, scale).context("Failed to transform")?;

world.set_if_changed(id, translation(), pos);
world.set_if_changed(id, rotation(), rot);
world.set_if_changed(id, scale(), scl);
Ok((id, old_snap_to_ground)) as anyhow::Result<_>
})
.collect::<Result<Vec<_>, _>>()
Expand Down
68 changes: 7 additions & 61 deletions crates/physics/src/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,16 @@ use itertools::Itertools;
use kiwi_core::transform::{get_world_position, get_world_transform, rotation, scale, translation};
use kiwi_ecs::{query, ECSError, EntityId, World};
use physxx::{
AsPxActor, AsPxRigidActor, PxActor, PxActorTypeFlag, PxBase, PxBoxGeometry, PxConvexMeshGeometry, PxJoint, PxMeshScale, PxOverlapCallback, PxQueryFilterData, PxQueryFlag, PxRevoluteJointRef, PxRigidActor, PxRigidActorRef, PxRigidBody, PxRigidBodyFlag, PxRigidDynamicRef, PxRigidStaticRef, PxSceneRef, PxShape, PxSphereGeometry, PxTransform, PxTriangleMeshGeometry, PxUserData
AsPxActor, AsPxRigidActor, PxActor, PxActorTypeFlag, PxBase, PxBoxGeometry, PxConvexMeshGeometry, PxJoint, PxMeshScale,
PxOverlapCallback, PxQueryFilterData, PxQueryFlag, PxRevoluteJointRef, PxRigidActor, PxRigidActorRef, PxRigidBody, PxRigidBodyFlag,
PxRigidDynamicRef, PxRigidStaticRef, PxSceneRef, PxShape, PxSphereGeometry, PxTransform, PxTriangleMeshGeometry, PxUserData,
};

use crate::{
collider::{collider_shapes_convex, collider_type}, main_physics_scene, physx::{character_controller, physics, physics_controlled, physics_shape, revolute_joint, rigid_dynamic, rigid_static}, unit_mass, unit_velocity, unit_yaw, ColliderScene, PxActorUserData, PxShapeUserData
collider::{collider_shapes_convex, collider_type},
main_physics_scene,
physx::{character_controller, physics, physics_controlled, physics_shape, revolute_joint, rigid_dynamic, rigid_static},
unit_mass, unit_velocity, unit_yaw, ColliderScene, PxActorUserData, PxShapeUserData,
};

pub fn convert_rigid_static_to_dynamic(world: &mut World, id: EntityId) {
Expand Down Expand Up @@ -108,65 +113,6 @@ pub fn get_shapes(world: &World, id: EntityId) -> impl Iterator<Item = PxShape>
.chain(world.get_ref(id, collider_shapes_convex()).into_iter().flatten().cloned())
}

/// Transform an entity to a new position while handling physxx velocities and
/// collider scaling.
///
/// The position is absolute
#[tracing::instrument(skip(world), level = "info")]
pub fn transform_entity_parts(world: &mut World, id: EntityId, pos: Vec3, rot: Quat, scl: Vec3) -> Result<(), ECSError> {
world.set(id, translation(), pos)?;
world.set(id, rotation(), rot)?;
if let Ok(body) = world.get(id, rigid_dynamic()) {
body.set_global_pose(&PxTransform::new(pos, rot), true);
body.set_linear_velocity(Vec3::ZERO, true);
body.set_angular_velocity(Vec3::ZERO, true);
} else if let Ok(body) = world.get(id, rigid_static()) {
body.set_global_pose(&PxTransform::new(pos, rot), true);
} else if let Ok(shape) = world.get_mut(id, physics_shape()) {
let actor = shape.get_actor().unwrap();

let old_scale = world.get(id, scale());

if let Ok(old_scale) = old_scale {
if old_scale.distance(scl) > 0.01 {
for shape in get_shapes(world, id) {
scale_shape(shape, scl);
}
}
} else {
// Handled by `initial_scale` system
}

actor.set_global_pose(&PxTransform::new(pos, rot), true);
if let Some(body) = actor.to_rigid_dynamic() {
// Stop any rb movement when translating
body.set_linear_velocity(Vec3::ZERO, true);
body.set_angular_velocity(Vec3::ZERO, true);
} else {
// update_actor_entity_transforms(world, actor);
}
} else if let Ok(controller) = world.get(id, character_controller()) {
controller.set_position(pos.as_dvec3());
let (_, _, z) = rot.to_euler(EulerRot::XYZ);
world.set(id, unit_yaw(), z).ok();
}
// ignore scale if not present
world.set(id, scale(), scl).ok();
Ok(())
}

pub fn transform_entity(world: &mut World, id: EntityId, transformation: Mat4, relative: bool) -> Result<(), ECSError> {
let new_transform = if relative {
let prev_transform = get_world_transform(world, id)?;
transformation * prev_transform
} else {
transformation
};

let (scl, rot, pos) = new_transform.to_scale_rotation_translation();
transform_entity_parts(world, id, pos, rot, scl)
}

pub fn scale_shape(shape: PxShape, scale: Vec3) {
tracing::debug!("Scaling shape");
let geo = shape.get_geometry();
Expand Down
67 changes: 64 additions & 3 deletions crates/physics/src/physx.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
use glam::{Quat, Vec3};
use kiwi_core::transform::{rotation, translation};
use kiwi_ecs::{components, query, Debuggable, Description, Name, Networked, Resource, Store, SystemGroup};
use crate::{
helpers::{get_shapes, scale_shape},
unit_yaw,
};
use glam::{EulerRot, Quat, Vec3};
use kiwi_core::transform::{rotation, scale, translation};
use kiwi_ecs::{components, query, Debuggable, Description, FnSystem, Name, Networked, QueryState, Resource, Store, SystemGroup};
use kiwi_std::asset_cache::SyncAssetKey;
use parking_lot::Mutex;
use physxx::{articulation_reduced_coordinate::*, *};
use std::sync::Arc;

components!("physics", {
@[Resource]
Expand Down Expand Up @@ -84,6 +90,14 @@ pub fn sync_ecs_physics() -> SystemGroup {
let mut new_positions = Vec::new();
let mut new_rotations = Vec::new();

let translation_rotation_qs = Arc::new(Mutex::new(QueryState::new()));
let translation_rotation_q = query((translation().changed(), rotation().changed())).incl(physics_controlled());
let translation_rotation_q2 = translation_rotation_q.query.clone();

let scale_qs = Arc::new(Mutex::new(QueryState::new()));
let scale_q = query(scale().changed()).incl(physics_controlled());
let scale_q2 = scale_q.query.clone();

SystemGroup::new(
"sync_ecs_physics",
vec![
Expand All @@ -97,6 +111,46 @@ pub fn sync_ecs_physics() -> SystemGroup {
world.add_component(id, rotation(), Quat::IDENTITY).unwrap();
}
}),
translation_rotation_q.to_system({
let translation_rotation_qs = translation_rotation_qs.clone();
move |q, world, _, _| {
// Read back any changes that have happened during the frame to physx
let mut qs = translation_rotation_qs.lock();
for (id, (&pos, &rot)) in q.iter(world, Some(&mut *qs)) {
if let Ok(body) = world.get(id, rigid_dynamic()) {
body.set_global_pose(&PxTransform::new(pos, rot), true);
body.set_linear_velocity(Vec3::ZERO, true);
body.set_angular_velocity(Vec3::ZERO, true);
} else if let Ok(body) = world.get(id, rigid_static()) {
body.set_global_pose(&PxTransform::new(pos, rot), true);
} else if let Ok(shape) = world.get_ref(id, physics_shape()) {
let actor = shape.get_actor().unwrap();

actor.set_global_pose(&PxTransform::new(pos, rot), true);
if let Some(body) = actor.to_rigid_dynamic() {
// Stop any rb movement when translating
body.set_linear_velocity(Vec3::ZERO, true);
body.set_angular_velocity(Vec3::ZERO, true);
} else {
// update_actor_entity_transforms(world, actor);
}
} else if let Ok(controller) = world.get(id, character_controller()) {
controller.set_position(pos.as_dvec3());
}
}
}
}),
scale_q.to_system({
let scale_qs = scale_qs.clone();
move |q, world, _, _| {
let mut qs = scale_qs.lock();
for (id, &scl) in q.iter(world, Some(&mut *qs)) {
for shape in get_shapes(world, id) {
scale_shape(shape, scl);
}
}
}
}),
// Updates ecs position from physx
query((rigid_dynamic(), translation(), rotation())).incl(physics_controlled()).to_system(|q, world, qs, _| {
for (id, (rigid_dynamic, pos, rot)) in q.collect_cloned(world, qs) {
Expand Down Expand Up @@ -166,6 +220,13 @@ pub fn sync_ecs_physics() -> SystemGroup {
}
}
}),
Box::new(FnSystem::new(move |world, _| {
// Fast forward queries
let mut translation_rotation_qs = translation_rotation_qs.lock();
translation_rotation_q2.iter(world, Some(&mut *translation_rotation_qs));
let mut scale_qs = scale_qs.lock();
scale_q2.iter(world, Some(&mut *scale_qs));
})),
],
)
}
8 changes: 4 additions & 4 deletions crates/terrain/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ use kiwi_gpu::{
use kiwi_meshes::{GridMesh, GridMeshKey};
use kiwi_physics::{
collider::{collider_type, ColliderType},
helpers::transform_entity_parts,
main_physics_scene,
physx::{character_controller, physics, physics_shape, rigid_static, Physics},
PxActorUserData, PxShapeUserData,
Expand Down Expand Up @@ -226,9 +225,10 @@ pub fn server_systems() -> SystemGroup {
}
}

for (id, _, pos, rot, scale) in new_transform {
let _old_pos = world.get(id, translation()).unwrap();
log_result!(transform_entity_parts(world, id, pos, rot, scale));
for (id, _, pos, rot, scl) in new_transform {
world.set_if_changed(id, translation(), pos);
world.set_if_changed(id, rotation(), rot);
world.set_if_changed(id, scale(), scl);
}
}),
],
Expand Down
15 changes: 0 additions & 15 deletions crates/wasm/src/server/bindings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,21 +105,6 @@ impl host::Host for Bindings {
.unwrap()
}

fn entity_set_transform(
&mut self,
entity: host::EntityId,
transform: host::Mat4,
relative: bool,
) {
esei::entity::set_transform(
&mut self.world_mut(),
entity.from_bindgen(),
transform.from_bindgen(),
relative,
)
.unwrap();
}

fn entity_get_linear_velocity(&mut self, entity: host::EntityId) -> Option<host::Vec3> {
esei::entity::get_linear_velocity(&mut self.world_mut(), entity.from_bindgen())
.ok()
Expand Down
9 changes: 0 additions & 9 deletions crates/wasm/src/server/implementation/entity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,6 @@ pub fn despawn(world: &mut World, entity: EntityId) -> Option<EntityId> {
world.despawn(entity).and_then(|ed| Some(entity))
}

pub fn set_transform(
world: &mut World,
entity: EntityId,
transform: Mat4,
relative: bool,
) -> anyhow::Result<()> {
Ok(eph::transform_entity(world, entity, transform, relative)?)
}

pub fn get_linear_velocity(world: &mut World, entity: EntityId) -> anyhow::Result<Vec3> {
Ok(eph::get_linear_velocity(world, entity)?)
}
Expand Down
1 change: 0 additions & 1 deletion crates/wasm/wit/host.wit
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,6 @@ record player-raw-input {
entity-spawn: func(data: components, persistent: bool) -> entity-id
entity-despawn: func(entity: entity-id) -> bool
entity-set-animation-controller: func(entity: entity-id, animation-controller: animation-controller)
entity-set-transform: func(entity: entity-id, transform: mat4, relative: bool)
entity-get-linear-velocity: func(entity: entity-id) -> option<vec3>
entity-in-area: func(position: vec3, radius: float32) -> list<entity-id>

Expand Down
Loading

0 comments on commit cafd188

Please sign in to comment.