From 5f61c0491241b1f62266e0d521c2e315b2c5b8e3 Mon Sep 17 00:00:00 2001 From: Daniel Bross Date: Fri, 11 Jul 2025 01:39:46 +0200 Subject: [PATCH] PhysX work --- core/entity.jai | 5 +- core/scene.jai | 6 +- core/transform.jai | 10 ++++ module.jai | 6 +- physics/physx.jai | 143 ++++++++++++++++++++++++++++++++++----------- 5 files changed, 129 insertions(+), 41 deletions(-) diff --git a/core/entity.jai b/core/entity.jai index 9f14261..71f983a 100644 --- a/core/entity.jai +++ b/core/entity.jai @@ -81,8 +81,9 @@ Entity :: struct { // Physics body : Physics_Body; collider : Collider; - physx_static: *PhysX.PxRigidStatic; - physx_dynamic: *PhysX.PxRigidDynamic; + + physx_handle: PhysX_Handle; + velocity: Vector3; // End physics diff --git a/core/scene.jai b/core/scene.jai index 17528b0..771b6f0 100644 --- a/core/scene.jai +++ b/core/scene.jai @@ -22,7 +22,7 @@ Scene :: struct { mode: Engine_Mode; - physx_scene: *PhysX.PxScene; + physx_scene: PhysX_Scene; using custom_fields: _Custom_Scene_Fields; } @@ -144,7 +144,7 @@ unload_scene :: (scene: *Scene) { destroy_entity(e); } - PhysX.PxScene_release(scene.physx_scene); + deinit_physx_scene(scene); free(scene.name); fini(*scene.pool); @@ -195,7 +195,7 @@ create_scene :: (name: string = "", max_entities: s64 = 256) -> *Scene { array_reserve(*scene.entities, max_entities); - scene.physx_scene = create_physx_scene(); + init_physx_scene(scene); scene.directional_light.color_and_intensity = .{1,1,1,2}; scene.directional_light.direction = to_v4(normalize(Vector3.{0.4, -0.7, 0.4})); diff --git a/core/transform.jai b/core/transform.jai index d92eb87..aa744bf 100644 --- a/core/transform.jai +++ b/core/transform.jai @@ -170,6 +170,16 @@ set_scale :: (transform: *Transform, scale: float, calculate_matrix: bool = true if calculate_matrix update_matrix(transform); } +set_position_rotation :: (transform: *Transform, position: Vector3, rotation: Quaternion, calculate_matrix: bool = true) { + transform.position = position; + transform.orientation = rotation; + if calculate_matrix update_matrix(transform); +} + +set_position_rotation :: (e: *Entity, position: Vector3, rotation: Quaternion, calculate_matrix: bool = true) { + set_position_rotation(*e.transform, position, rotation, calculate_matrix); +} + set_position_rotation_scale :: (transform: *Transform, position: Vector3, rotation: Quaternion, scale: Vector3, calculate_matrix: bool = true) { transform.position = position; transform.orientation = rotation; diff --git a/module.jai b/module.jai index 6e5aef0..8726fb0 100644 --- a/module.jai +++ b/module.jai @@ -159,7 +159,11 @@ coven_run :: (game_update_proc: (float), game_editor_update_proc: (float), game_ update_animators(clamped_dt); update_mesh_colliders(engine.current_scene); update_physics(engine.current_scene, clamped_dt); - tick_physx(engine.current_scene.physx_scene, clamped_dt); + + pre_physx_sync(engine.current_scene); + tick_physx(*engine.current_scene.physx_scene, clamped_dt); + post_physx_sync(engine.current_scene); + game_update_post_physics_proc(clamped_dt); } } else { diff --git a/physics/physx.jai b/physics/physx.jai index 313b575..2c1281a 100644 --- a/physics/physx.jai +++ b/physics/physx.jai @@ -1,3 +1,19 @@ +PHYSX_TEST :: false; +PHYSX_DEFAULT_SHAPE_FLAGS :: cast(u8)(PhysX.PxShapeFlags.Visualization | PhysX.PxShapeFlags.SceneQueryShape | PhysX.PxShapeFlags.SimulationShape); + +PhysX_Handle :: #type, distinct u32; +PhysX_Actor :: struct { + union { + static: *PhysX.PxRigidStatic; + dynamic: *PhysX.PxRigidDynamic; + } +} + +PhysX_Scene :: struct { + scene: *PhysX.PxScene; + actors : PArray(PhysX_Actor, PhysX_Handle); +} + init_physx :: () { default_allocator = PhysX.get_default_allocator(); default_error_callback = PhysX.get_default_error_callback(); @@ -21,14 +37,12 @@ init_physx :: () { material = PhysX.PxPhysics_createMaterial(physics, 0.5, 0.5, 0.6); } -tick_physx :: (scene: *PhysX.PxScene, dt: float) { - PhysX.PxScene_simulate(scene, 1.0/60.0, null, null, 0, true); - PhysX.PxScene_fetchResults(scene, true, null); +tick_physx :: (scene: *PhysX_Scene, dt: float) { + PhysX.PxScene_simulate(scene.scene, dt, null, null, 0, true); + PhysX.PxScene_fetchResults(scene.scene, true, null); } -plane : Plane3; - -create_physx_scene :: () -> *PhysX.PxScene { +init_physx_scene :: (game_scene: *Scene) { tolerance_scale : PhysX.PxTolerancesScale; tolerance_scale.length = 1; tolerance_scale.speed = 10; @@ -48,41 +62,100 @@ create_physx_scene :: () -> *PhysX.PxScene { PhysX.PxPvdSceneClient_setScenePvdFlag(pvd_client, xx PhysX.PxPvdSceneFlag.TRANSMIT_CONTACTS, true); PhysX.PxPvdSceneClient_setScenePvdFlag(pvd_client, xx PhysX.PxPvdSceneFlag.TRANSMIT_SCENEQUERIES, true); } - { - plane_point := Vector3.{0,0,0}; - plane_normal := Vector3.{0,1,0}; - plane = PhysX.PxPlane_new(*plane_point, *plane_normal); - ground_plane := PhysX.PxCreatePlane(physics, *plane, material); - PhysX.PxScene_addActor(scene, ground_plane, null); + + { + plane_point := Vector3.{0,10.5,0}; + plane_normal := Vector3.{0,1,0}; + plane := PhysX.PxPlane_new(*plane_point, *plane_normal); + ground_plane := PhysX.PxCreatePlane(physics, *plane, material); + PhysX.PxScene_addActor(scene, ground_plane, null); + } + #if PHYSX_TEST { + + stack_z := 0.0; + for i: 0..4 { + stack_pos := Vector3.{0,10,stack_z}; + stack_z -= 10.0; + create_stack(scene, PhysX.PxTransform_new(*stack_pos), 10, 2.0); + } + + { + pos := Vector3.{0,20,100}; + geo := PhysX.PxSphereGeometry_new(5); + vel := Vector3.{0,-25,-100}; + + ball := create_dynamic(scene, PhysX.PxTransform_new(*pos), *geo, vel); + density := 1000.0; + PhysX.PxRigidBodyExt_updateMassAndInertia(ball, density, null, true); + } } - stack_z := 0.0; - for i: 0..4 { - stack_pos := Vector3.{0,10,stack_z}; - stack_z -= 10.0; - create_stack(scene, PhysX.PxTransform_new(*stack_pos), 10, 2.0); - } + physx_scene : PhysX_Scene; + physx_scene.scene = scene; + physx_scene.actors.data.allocator = game_scene.allocator; + physx_scene.actors.indices.allocator = game_scene.allocator; - { - pos := Vector3.{0,20,100}; - geo := PhysX.PxSphereGeometry_new(5); - vel := Vector3.{0,-25,-100}; - - ball := create_dynamic(scene, PhysX.PxTransform_new(*pos), *geo, vel); - density := 1000.0; - PhysX.PxRigidBodyExt_updateMassAndInertia(ball, density, null, true); - } - - return scene; + game_scene.physx_scene = physx_scene; } -PxShapeFlags :: enum_flags u8 { - SimulationShape :: 1 << 0; - SceneQueryShape :: 1 << 1; - TriggerShape :: 1 << 2; - Visualization :: 1 << 3; + +deinit_physx_scene :: (game_scene: *Scene) { + PhysX.PxScene_release(game_scene.physx_scene.scene); } + +pre_physx_sync :: (game_scene: *Scene) { + for game_scene.entities { + if it.physx_handle != 0 { + // @Incomplete: Update the transform! + physx_actor := parray_get(*game_scene.physx_scene.actors, it.physx_handle); + PhysX.PxRigidDynamic_setLinearVelocity(physx_actor.dynamic, *it.velocity, true); + } + } +} + +post_physx_sync :: (game_scene: *Scene) { + for game_scene.entities { + if it.physx_handle != 0 { + physx_actor := parray_get(*game_scene.physx_scene.actors, it.physx_handle); + vel := PhysX.PxRigidDynamic_getLinearVelocity(physx_actor.dynamic); + transform := PhysX.PxRigidActor_getGlobalPose(physx_actor.dynamic); + it.velocity = vel; + set_position_rotation(it, transform.p, transform.q); + } + } +} + +add_physx_capsule :: (entity: *Entity, half_height: float, radius: float) -> PhysX_Handle { + geo := PhysX.PxCapsuleGeometry_new(radius, half_height); + transform := PhysX.PxTransform_new(*entity.transform.position); + actor := PhysX.PxPhysics_createRigidDynamic(physics, *transform); + PhysX.PxRigidDynamic_setRigidDynamicLockFlag(actor, xx PhysX.PxRigidDynamicLockFlags.LockAngularX, true); + PhysX.PxRigidDynamic_setRigidDynamicLockFlag(actor, xx PhysX.PxRigidDynamicLockFlags.LockAngularY, true); + PhysX.PxRigidDynamic_setRigidDynamicLockFlag(actor, xx PhysX.PxRigidDynamicLockFlags.LockAngularZ, true); + + material := PhysX.PxPhysics_createMaterial(physics, 0.5, 0.5, 0.0); + + PhysX.PxMaterial_setRestitutionCombineMode(material,1); // Turn off restitution no matter the other material + + shape := PhysX.PxPhysics_createShape(physics, *geo, material, false, PHYSX_DEFAULT_SHAPE_FLAGS); + PhysX.PxRigidActor_attachShape(actor, shape); + + + PhysX.PxRigidBodyExt_updateMassAndInertia(actor, 10, null, false); + PhysX.PxScene_addActor(entity.scene.physx_scene.scene, actor, null); + + PhysX.PxShape_release(shape); + // @Incomplete + //PhysX.PxMaterial_release(material); + + physics_actor : PhysX_Actor; + physics_actor.dynamic = actor; + + entity.physx_handle = parray_add(*entity.scene.physx_scene.actors, physics_actor); + return entity.physx_handle; +} + create_stack :: (scene: *PhysX.PxScene, t: PhysX.PxTransform, size: u32, half_extent: float) { - shape := PhysX.PxPhysics_createShape(physics, PhysX.PxBoxGeometry_new(half_extent, half_extent, half_extent), material, false, xx (PhysX.PxShapeFlags.Visualization | PhysX.PxShapeFlags.SceneQueryShape | PhysX.PxShapeFlags.SimulationShape)); + shape := PhysX.PxPhysics_createShape(physics, PhysX.PxBoxGeometry_new(half_extent, half_extent, half_extent), material, false, PHYSX_DEFAULT_SHAPE_FLAGS); for i: 0..size-1 { for j: 0..size-i-1 { pos := Vector3.{cast(float)(j*2) - cast(float)(size-i), cast(float)(i*2+1), 0} * half_extent;