From 58dee945f82d356bff2c3a83fec8a7d4ee3ec0fe Mon Sep 17 00:00:00 2001 From: ecker Date: Mon, 15 Sep 2025 18:05:15 -0500 Subject: [PATCH] proper pre-computing of mesh views (with equally horrid code) --- bin/data/entities/prop.json | 2 +- engine/inc/uf/utils/math/physics/impl.h | 6 ++--- engine/inc/uf/utils/mesh/mesh.h | 31 +++++++++++----------- engine/src/utils/math/physics/bvh.inl | 6 ++--- engine/src/utils/math/physics/impl.cpp | 10 ++++--- engine/src/utils/math/physics/mesh.inl | 20 +++++++++----- engine/src/utils/math/physics/ray.inl | 5 ++-- engine/src/utils/math/physics/triangle.inl | 9 +++---- 8 files changed, 46 insertions(+), 43 deletions(-) diff --git a/bin/data/entities/prop.json b/bin/data/entities/prop.json index 2186f06f..8d0caa60 100644 --- a/bin/data/entities/prop.json +++ b/bin/data/entities/prop.json @@ -6,7 +6,7 @@ "metadata": { "holdable": true, "physics": { - "mass": 5, + "mass": 10000, "type": "bounding box" // "type": "mesh" } diff --git a/engine/inc/uf/utils/math/physics/impl.h b/engine/inc/uf/utils/math/physics/impl.h index bd6b305a..70a7e2b2 100644 --- a/engine/inc/uf/utils/math/physics/impl.h +++ b/engine/inc/uf/utils/math/physics/impl.h @@ -11,12 +11,9 @@ #include #include +#include #include -namespace uf { - class Mesh; -} - namespace pod { enum class ShapeType { AABB, @@ -107,6 +104,7 @@ namespace pod { struct MeshBVH { pod::BVH* bvh; const uf::Mesh* mesh; + const uf::Mesh::views_t* views; }; typedef uint32_t CollisionMask; diff --git a/engine/inc/uf/utils/mesh/mesh.h b/engine/inc/uf/utils/mesh/mesh.h index f12be968..9cd2a53b 100644 --- a/engine/inc/uf/utils/mesh/mesh.h +++ b/engine/inc/uf/utils/mesh/mesh.h @@ -163,19 +163,19 @@ namespace uf { struct AttributeView { Attribute attribute; - const void* data(size_t first = 0) const { - if ( !valid() ) return NULL; - return static_cast(attribute.pointer) + attribute.stride * first; - } + const void* data(size_t first = 0) const { + if ( !valid() ) return NULL; + return static_cast(attribute.pointer) + attribute.stride * first; + } - template - const T* get(size_t first = 0) const { - return reinterpret_cast(data(first)); - } + template + const T* get(size_t first = 0) const { + return reinterpret_cast(data(first)); + } - bool valid() const { return attribute.pointer != NULL; } - size_t stride() const { return attribute.stride; } - size_t components() const { return attribute.descriptor.components; } + bool valid() const { return attribute.pointer != NULL; } + size_t stride() const { return attribute.stride; } + size_t components() const { return attribute.descriptor.components; } }; struct View { @@ -186,11 +186,12 @@ namespace uf { uf::stl::unordered_map attributes; const AttributeView& operator[](const uf::stl::string& name) const { - static AttributeView null{}; - if ( auto it = attributes.find(name); it != attributes.end() ) return it->second; - return null; - } + static AttributeView null{}; + if ( auto it = attributes.find(name); it != attributes.end() ) return it->second; + return null; + } }; + typedef uf::stl::vector views_t; uf::stl::vector buffers; diff --git a/engine/src/utils/math/physics/bvh.inl b/engine/src/utils/math/physics/bvh.inl index 6b9e26e8..ecdf4eed 100644 --- a/engine/src/utils/math/physics/bvh.inl +++ b/engine/src/utils/math/physics/bvh.inl @@ -212,7 +212,7 @@ namespace { bvh.dirty = false; } - void buildMeshBVH( pod::BVH& bvh, const uf::Mesh& mesh, pod::BVH::index_t capacity = 4 ) { + void buildMeshBVH( pod::BVH& bvh, const uf::Mesh& mesh, const uf::Mesh::views_t& views, pod::BVH::index_t capacity = 4 ) { uint32_t triangles = mesh.index.count / 3; bvh.indices.clear(); @@ -223,7 +223,6 @@ namespace { uf::stl::vector bounds; bounds.reserve( triangles ); - auto views = mesh.makeViews({"position"}); UF_ASSERT( !views.empty() ); // populate initial indices and bounds @@ -376,13 +375,12 @@ namespace { } } - void refitBVH( pod::BVH& bvh, const uf::Mesh& mesh ) { + void refitBVH( pod::BVH& bvh, const uf::Mesh& mesh, const uf::Mesh::views_t& views ) { uint32_t triangles = mesh.index.count / 3; uf::stl::vector bounds; bounds.reserve( triangles ); - auto views = mesh.makeViews({"position"}); UF_ASSERT( !views.empty() ); // populate initial indices and bounds diff --git a/engine/src/utils/math/physics/impl.cpp b/engine/src/utils/math/physics/impl.cpp index 2c2068f5..60f3f9ac 100644 --- a/engine/src/utils/math/physics/impl.cpp +++ b/engine/src/utils/math/physics/impl.cpp @@ -9,8 +9,8 @@ namespace { bool blockContactSolver = true; // use BlockNxN solvers (where N = number of contacts for a manifold) bool psgContactSolver = true; // use PSG contact solver bool useGjk = false; // currently don't have a way to broadphase mesh => narrowphase tri via GJK - bool fixedStep = true; // run physics simulation with a fixed delta time (with accumulation), rather than rely on actual engine deltatime - uint32_t substeps = 0; // number of substeps per frame tick + bool fixedStep = false; // run physics simulation with a fixed delta time (with accumulation), rather than rely on actual engine deltatime + uint32_t substeps = 4; // number of substeps per frame tick uint32_t reserveCount = 32; // amount of elements to reserve for vectors used in this system, to-do: have it tie to a memory pool allocator // increasing these make things lag for reasons I can imagine why @@ -22,7 +22,7 @@ namespace { bool flattenBvhMeshes = true; // use surface area heuristics for building the BVH, rather than naive splits - bool useBvhSahBodies = true; // it actually seems slower to use these...... + bool useBvhSahBodies = false; // it actually seems slower to use these...... bool useBvhSahMeshes = true; bool useSplitBvhs = true; // creates separate BVHs for static / dynamic objects @@ -396,10 +396,11 @@ pod::PhysicsBody& uf::physics::impl::create( pod::World& world, uf::Object& obje auto& body = uf::physics::impl::create( world, object, mass, offset ); body.collider.type = pod::ShapeType::MESH; body.collider.mesh.mesh = &mesh; + auto& views = *(body.collider.mesh.views = new uf::Mesh::views_t(mesh.makeViews({"position", "normal"}))); body.collider.mesh.bvh = new pod::BVH; auto& bvh = *body.collider.mesh.bvh; - ::buildMeshBVH( bvh, mesh, ::meshBvhCapacity ); + ::buildMeshBVH( bvh, mesh, views, ::meshBvhCapacity ); body.bounds = ::computeAABB( body ); uf::physics::impl::updateInertia( body ); @@ -458,6 +459,7 @@ void uf::physics::impl::destroy( pod::PhysicsBody& body ) { // remove any pointered collider data if ( body.collider.type == pod::ShapeType::MESH ) { if ( body.collider.mesh.bvh ) delete body.collider.mesh.bvh; + if ( body.collider.mesh.views ) delete body.collider.mesh.views; } } diff --git a/engine/src/utils/math/physics/mesh.inl b/engine/src/utils/math/physics/mesh.inl index 83362502..725165a4 100644 --- a/engine/src/utils/math/physics/mesh.inl +++ b/engine/src/utils/math/physics/mesh.inl @@ -21,6 +21,7 @@ namespace { const auto& bvh = *mesh.collider.mesh.bvh; const auto& meshData = *mesh.collider.mesh.mesh; + const auto& meshViews = *mesh.collider.mesh.views; // transform to local space for BVH query auto bounds = ::transformAabbToLocal( aabb.bounds, ::getTransform( mesh ) ); @@ -31,7 +32,7 @@ namespace { bool hit = false; // do collision per triangle for ( auto triID : candidates ) { - auto tri = ::fetchTriangle( meshData, triID, mesh ); // transform triangle to world space + auto tri = ::fetchTriangle( meshData, meshViews, triID, mesh ); // transform triangle to world space if ( !::triangleAabb( tri, aabb, manifold, eps ) ) continue; hit = true; } @@ -45,6 +46,7 @@ namespace { const auto& bvh = *mesh.collider.mesh.bvh; const auto& meshData = *mesh.collider.mesh.mesh; + const auto& meshViews = *mesh.collider.mesh.views; // transform to local space for BVH query auto bounds = ::transformAabbToLocal( sphere.bounds, ::getTransform( mesh ) ); @@ -55,7 +57,7 @@ namespace { bool hit = false; // do collision per triangle for ( auto triID : candidates ) { - auto tri = ::fetchTriangle( meshData, triID, mesh ); // transform triangle to world space + auto tri = ::fetchTriangle( meshData, meshViews, triID, mesh ); // transform triangle to world space if ( !::triangleSphere( tri, sphere, manifold, eps ) ) continue; hit = true; } @@ -71,6 +73,7 @@ namespace { const auto& bvh = *mesh.collider.mesh.bvh; const auto& meshData = *mesh.collider.mesh.mesh; + const auto& meshViews = *mesh.collider.mesh.views; // transform to local space for BVH query auto bounds = ::transformAabbToLocal( plane.bounds, ::getTransform( mesh ) ); @@ -81,7 +84,7 @@ namespace { bool hit = false; // do collision per triangle for ( auto triID : candidates ) { - auto tri = ::fetchTriangle( meshData, triID, mesh ); // transform triangle to world space + auto tri = ::fetchTriangle( meshData, meshViews, triID, mesh ); // transform triangle to world space if ( !::trianglePlane( tri, plane, manifold, eps ) ) continue; hit = true; } @@ -96,6 +99,7 @@ namespace { const auto& bvh = *mesh.collider.mesh.bvh; const auto& meshData = *mesh.collider.mesh.mesh; + const auto& meshViews = *mesh.collider.mesh.views; // transform to local space for BVH query auto bounds = ::transformAabbToLocal( capsule.bounds, ::getTransform( mesh ) ); @@ -106,7 +110,7 @@ namespace { bool hit = false; // do collision per triangle for ( auto triID : candidates ) { - auto tri = ::fetchTriangle( meshData, triID, mesh ); // transform triangle to world space + auto tri = ::fetchTriangle( meshData, meshViews, triID, mesh ); // transform triangle to world space if ( !::triangleCapsule( tri, capsule, manifold, eps ) ) continue; hit = true; } @@ -119,9 +123,11 @@ namespace { const auto& bvhA = *a.collider.mesh.bvh; const auto& meshA = *a.collider.mesh.mesh; + const auto& viewsA = *a.collider.mesh.views; - const auto& meshB = *b.collider.mesh.mesh; const auto& bvhB = *b.collider.mesh.bvh; + const auto& meshB = *b.collider.mesh.mesh; + const auto& viewsB = *b.collider.mesh.views; // compute overlaps between one BVH and another BVH thread_local pod::BVH::pairs_t pairs; @@ -131,8 +137,8 @@ namespace { bool hit = false; // do collision per triangle for (auto [ idA, idB] : pairs ) { - auto tA = ::fetchTriangle( meshA, idA, a ); // transform triangles to world space - auto tB = ::fetchTriangle( meshB, idB, b ); + auto tA = ::fetchTriangle( meshA, viewsA, idA, a ); // transform triangles to world space + auto tB = ::fetchTriangle( meshB, viewsB, idB, b ); if ( !::triangleTriangle( tA, tB, manifold, eps ) ) continue; hit = true; diff --git a/engine/src/utils/math/physics/ray.inl b/engine/src/utils/math/physics/ray.inl index 0b198313..b1ee2b12 100644 --- a/engine/src/utils/math/physics/ray.inl +++ b/engine/src/utils/math/physics/ray.inl @@ -193,8 +193,9 @@ namespace { } bool rayMesh( const pod::Ray& r, const pod::PhysicsBody& body, pod::RayQuery& rayHit ) { - const auto& meshData = *body.collider.mesh.mesh; const auto& bvh = *body.collider.mesh.bvh; + const auto& meshData = *body.collider.mesh.mesh; + const auto& meshViews = *body.collider.mesh.views; const auto transform = ::getTransform( body ); @@ -207,7 +208,7 @@ namespace { ::queryBVH( bvh, ray, candidates ); for ( auto triID : candidates ) { - auto tri = ::fetchTriangle( meshData, triID ); + auto tri = ::fetchTriangle( meshData, meshViews, triID ); float t, u, v; if ( !::rayTriangleIntersect( ray, tri, t, u, v ) ) continue; diff --git a/engine/src/utils/math/physics/triangle.inl b/engine/src/utils/math/physics/triangle.inl index 70d71a84..fc75b814 100644 --- a/engine/src/utils/math/physics/triangle.inl +++ b/engine/src/utils/math/physics/triangle.inl @@ -91,10 +91,7 @@ namespace { return tri; } - pod::TriangleWithNormal fetchTriangle( const uf::Mesh& mesh, size_t triID ) { - static thread_local uf::stl::unordered_map> cachedViews; - if ( cachedViews.count(&mesh) == 0 ) cachedViews[&mesh] = mesh.makeViews({"position"}); - auto& views = cachedViews[&mesh]; + pod::TriangleWithNormal fetchTriangle( const uf::Mesh& mesh, const uf::Mesh::views_t& views, size_t triID ) { UF_ASSERT(!views.empty()); // find which view contains this triangle index. @@ -121,8 +118,8 @@ namespace { } // if body is a mesh, apply its transform to the triangles, else reorient the normal with respect to the body - pod::TriangleWithNormal fetchTriangle( const uf::Mesh& mesh, size_t triID, const pod::PhysicsBody& body, bool fast = false ) { - auto tri = ::fetchTriangle( mesh, triID ); + pod::TriangleWithNormal fetchTriangle( const uf::Mesh& mesh, const uf::Mesh::views_t& views, size_t triID, const pod::PhysicsBody& body, bool fast = false ) { + auto tri = ::fetchTriangle( mesh, views, triID ); auto transform = ::getTransform( body );