From 894938a7bb7d0d30c0b21905d296163d6070aa74 Mon Sep 17 00:00:00 2001 From: Johannes Date: Sun, 12 Nov 2023 18:47:59 +0100 Subject: [PATCH] Physics heightfields (#198) - update vs build settings to disable LTCG and select WASAPI soloud backend by default - add support for loading physx heightfields from R16_UNORM textures - made physics run with actual physics framerate instead --- code/physics/physics/physxstate.cc | 18 ++++- code/physics/physics/streamactorpool.cc | 70 +++++++++++++++++++- code/physics/physicsinterface.h | 1 + fips-files/configs/win64-vstudio-debug.yml | 3 + fips-files/configs/win64-vstudio-release.yml | 3 + syswork/data/flatbuffer/physics/actor.fbs | 10 ++- syswork/data/flatbuffer/physics/material.fbs | 6 +- 7 files changed, 103 insertions(+), 8 deletions(-) diff --git a/code/physics/physics/physxstate.cc b/code/physics/physics/physxstate.cc index f2704e6d4..00a1ff071 100644 --- a/code/physics/physics/physxstate.cc +++ b/code/physics/physics/physxstate.cc @@ -275,9 +275,14 @@ PhysxState::BeginSimulating(Timing::Time delta, IndexT sceneId) n_assert(this->activeSceneIds.FindIndex(sceneId) != InvalidIndex); Physics::Scene& scene = this->activeScenes[sceneId]; + n_assert(scene.isSimulating == false); scene.time -= delta; + + if (scene.time < -PHYSICS_RATE) + { + scene.isSimulating = scene.scene->simulate(PHYSICS_RATE); + } - scene.scene->simulate(PHYSICS_RATE); N_MARKER_END(); } @@ -287,11 +292,17 @@ PhysxState::BeginSimulating(Timing::Time delta, IndexT sceneId) void PhysxState::EndSimulating(IndexT sceneId) { - N_MARKER_BEGIN(EndSimulating, Physics); n_assert(this->activeSceneIds.FindIndex(sceneId) != InvalidIndex); Physics::Scene& scene = this->activeScenes[sceneId]; + if (!scene.isSimulating) + { + return; + } + + N_MARKER_BEGIN(EndSimulating, Physics); scene.scene->fetchResults(true); + scene.time += PHYSICS_RATE; Util::Set modifiedActors; if (scene.updateFunction != nullptr) @@ -301,7 +312,7 @@ PhysxState::EndSimulating(IndexT sceneId) // we limit the simulation to 5 frames scene.time = Math::max(scene.time, -5.0 * PHYSICS_RATE); - while (scene.time < PHYSICS_RATE) + while (scene.time < 0.0f) { // simulate synchronously until we are in sync again scene.scene->simulate(PHYSICS_RATE); @@ -318,6 +329,7 @@ PhysxState::EndSimulating(IndexT sceneId) (*scene.updateFunction)(actor); } } + scene.isSimulating = false; N_MARKER_END(); } diff --git a/code/physics/physics/streamactorpool.cc b/code/physics/physics/streamactorpool.cc index f3333de95..8f56fb200 100644 --- a/code/physics/physics/streamactorpool.cc +++ b/code/physics/physics/streamactorpool.cc @@ -16,6 +16,7 @@ #include "flat/physics/actor.h" #include "coregraphics/nvx3fileformatstructs.h" #include "coregraphics/primitivegroup.h" +#include "coregraphics/load/glimltypes.h" __ImplementClass(Physics::StreamActorPool, 'PSAP', Resources::ResourceLoader); @@ -363,6 +364,68 @@ AddMeshColliders(PhysicsResource::MeshColliderT* colliderNode, Math::mat4 const& nvx3Reader->Close(); } +//------------------------------------------------------------------------------ +/** +*/ +static void +AddHeightField(PhysicsResource::HeightFieldColliderT* colliderNode, Math::mat4 const& nodeTransform, Util::String nodeName, IndexT materialIdx, const Util::StringAtom& tag, Ids::Id32 entry, ActorInfo& targetActor) +{ + Ptr stream = IO::IoServer::Instance()->CreateStream(IO::URI(colliderNode->file)); + stream->SetAccessMode(IO::Stream::ReadAccess); + if (stream->Open()) + { + void* heightData = stream->MemoryMap(); + uint heightSize = stream->GetSize(); + n_assert(heightData != nullptr); + + gliml::context ctx; + if (ctx.load_dds(heightData, heightSize)) + { + int depth = ctx.image_depth(0, 0); + int width = ctx.image_width(0, 0); + int height = ctx.image_height(0, 0); + + CoreGraphics::PixelFormat::Code format = CoreGraphics::Gliml::ToPixelFormat(ctx); + n_assert(format == CoreGraphics::PixelFormat::R16); + + PxHeightFieldSample* heightSamples = (PxHeightFieldSample*)Memory::Alloc(Memory::PhysicsHeap, width * height * sizeof(PxHeightFieldSample)); + n_assert(heightSamples != nullptr); + Memory::Clear(heightSamples, width * height * sizeof(PxHeightFieldSample)); + + uint16_t* heightBuffer = (uint16_t*)ctx.image_data(0, 0); + + // need to flip to be in same orientation with rendering + for (int i = 0; i < width; i++) + { + for (int j = 0; j < height; j++) + { + heightSamples[i * width + j].height = heightBuffer[j * width + i]; + } + } + + PxHeightFieldDesc hfDesc; + hfDesc.format = PxHeightFieldFormat::eS16_TM; + hfDesc.nbColumns = width; + hfDesc.nbRows = height; + hfDesc.samples.data = heightSamples; + hfDesc.samples.stride = sizeof(PxHeightFieldSample); + + PxHeightField* physxHeightField = PxCreateHeightField(hfDesc); + + float sh = colliderNode->height_range / 65536.0f; + float sx = colliderNode->target_size_x / (float)width; + float sy = colliderNode->target_size_y / (float)height; + PxHeightFieldGeometry hfGeom(physxHeightField, PxMeshGeometryFlags(), sh, sx, sy); + Math::mat4 offsetTransform = Math::mat4::identity; + offsetTransform.position = Math::vec4(-0.5f * colliderNode->target_size_x, 0.0f, -0.5f * colliderNode->target_size_y, 1.0f); + physx::PxGeometryHolder holder = hfGeom; + AddCollider(holder, materialIdx, offsetTransform, colliderNode->file.AsCharPtr(), nodeName, targetActor, tag, entry); + Memory::Free(Memory::HeapType::PhysicsHeap, heightSamples); + } + stream->MemoryUnmap(); + stream->Close(); + } +} //------------------------------------------------------------------------------ /** @@ -435,8 +498,13 @@ StreamActorPool::LoadFromStream(const Ids::Id32 entry, const Util::StringAtom & */ } break; + case ColliderType_HeightField: + { + AddHeightField(collider->data.AsHeightFieldCollider(), shape->transform, collider->name, material, tag, entry, actorInfo); + } + break; default: - n_assert("unknown collider type") + n_error("unknown collider type"); } } diff --git a/code/physics/physicsinterface.h b/code/physics/physicsinterface.h index 4b8a868c9..505d8971a 100644 --- a/code/physics/physicsinterface.h +++ b/code/physics/physicsinterface.h @@ -73,6 +73,7 @@ struct Scene physx::PxDefaultCpuDispatcher *dispatcher; UpdateFunctionType updateFunction = nullptr; Timing::Time time; + bool isSimulating = false; }; /// initialize the physics subsystem and create a default scene diff --git a/fips-files/configs/win64-vstudio-debug.yml b/fips-files/configs/win64-vstudio-debug.yml index 66996887e..6484301c2 100644 --- a/fips-files/configs/win64-vstudio-debug.yml +++ b/fips-files/configs/win64-vstudio-debug.yml @@ -6,5 +6,8 @@ build_type: Debug defines: N_USE_VULKAN: ON __X64__: ON + FIPS_MSVC_LTCG: OFF N_DEBUG_SYMBOLS: ON PX_TARGET: win.x86_64.vc143.mt + SOLOUD_BACKEND_WASAPI: ON + SOLOUD_BACKEND_NULL: OFF diff --git a/fips-files/configs/win64-vstudio-release.yml b/fips-files/configs/win64-vstudio-release.yml index 01d2f6c45..879478668 100644 --- a/fips-files/configs/win64-vstudio-release.yml +++ b/fips-files/configs/win64-vstudio-release.yml @@ -5,5 +5,8 @@ build_tool: cmake build_type: Release defines: N_USE_VULKAN: ON + FIPS_MSVC_LTCG: OFF __X64__: ON PX_TARGET: win.x86_64.vc143.mt + SOLOUD_BACKEND_WASAPI: ON + SOLOUD_BACKEND_NULL: OFF \ No newline at end of file diff --git a/syswork/data/flatbuffer/physics/actor.fbs b/syswork/data/flatbuffer/physics/actor.fbs index 17b529744..2a1794819 100644 --- a/syswork/data/flatbuffer/physics/actor.fbs +++ b/syswork/data/flatbuffer/physics/actor.fbs @@ -38,9 +38,17 @@ table BoxCollider extents : Flat.Vec3 (native_inline); } +table HeightFieldCollider +{ + height_range : float; + target_size_x : float; + target_size_y : float; + file : string; +} + union ColliderData { - BoxCollider, SphereCollider, CapsuleCollider, MeshCollider + BoxCollider, SphereCollider, CapsuleCollider, MeshCollider, HeightFieldCollider } table Collider diff --git a/syswork/data/flatbuffer/physics/material.fbs b/syswork/data/flatbuffer/physics/material.fbs index 0954481c1..77a92ee52 100644 --- a/syswork/data/flatbuffer/physics/material.fbs +++ b/syswork/data/flatbuffer/physics/material.fbs @@ -19,8 +19,7 @@ enum MeshTopology : byte Convex = 0, ConvexHull = 1, Triangles = 2, - HeightField = 3, - ApproxSkin = 4, + ApproxSkin = 3 } enum ColliderType : byte @@ -29,7 +28,8 @@ enum ColliderType : byte Cube = 1, Capsule = 2, Plane = 3, - Mesh = 4 + Mesh = 4, + HeightField = 5 } table MaterialDefinition