proper pre-computing of mesh views (with equally horrid code)
This commit is contained in:
parent
16062f8135
commit
58dee945f8
@ -6,7 +6,7 @@
|
|||||||
"metadata": {
|
"metadata": {
|
||||||
"holdable": true,
|
"holdable": true,
|
||||||
"physics": {
|
"physics": {
|
||||||
"mass": 5,
|
"mass": 10000,
|
||||||
"type": "bounding box"
|
"type": "bounding box"
|
||||||
// "type": "mesh"
|
// "type": "mesh"
|
||||||
}
|
}
|
||||||
|
@ -11,12 +11,9 @@
|
|||||||
#include <uf/utils/memory/unordered_set.h>
|
#include <uf/utils/memory/unordered_set.h>
|
||||||
|
|
||||||
#include <uf/engine/object/object.h>
|
#include <uf/engine/object/object.h>
|
||||||
|
#include <uf/utils/mesh/mesh.h>
|
||||||
#include <cfloat>
|
#include <cfloat>
|
||||||
|
|
||||||
namespace uf {
|
|
||||||
class Mesh;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace pod {
|
namespace pod {
|
||||||
enum class ShapeType {
|
enum class ShapeType {
|
||||||
AABB,
|
AABB,
|
||||||
@ -107,6 +104,7 @@ namespace pod {
|
|||||||
struct MeshBVH {
|
struct MeshBVH {
|
||||||
pod::BVH* bvh;
|
pod::BVH* bvh;
|
||||||
const uf::Mesh* mesh;
|
const uf::Mesh* mesh;
|
||||||
|
const uf::Mesh::views_t* views;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef uint32_t CollisionMask;
|
typedef uint32_t CollisionMask;
|
||||||
|
@ -163,19 +163,19 @@ namespace uf {
|
|||||||
struct AttributeView {
|
struct AttributeView {
|
||||||
Attribute attribute;
|
Attribute attribute;
|
||||||
|
|
||||||
const void* data(size_t first = 0) const {
|
const void* data(size_t first = 0) const {
|
||||||
if ( !valid() ) return NULL;
|
if ( !valid() ) return NULL;
|
||||||
return static_cast<const uint8_t*>(attribute.pointer) + attribute.stride * first;
|
return static_cast<const uint8_t*>(attribute.pointer) + attribute.stride * first;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
const T* get(size_t first = 0) const {
|
const T* get(size_t first = 0) const {
|
||||||
return reinterpret_cast<const T*>(data(first));
|
return reinterpret_cast<const T*>(data(first));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool valid() const { return attribute.pointer != NULL; }
|
bool valid() const { return attribute.pointer != NULL; }
|
||||||
size_t stride() const { return attribute.stride; }
|
size_t stride() const { return attribute.stride; }
|
||||||
size_t components() const { return attribute.descriptor.components; }
|
size_t components() const { return attribute.descriptor.components; }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct View {
|
struct View {
|
||||||
@ -186,11 +186,12 @@ namespace uf {
|
|||||||
uf::stl::unordered_map<uf::stl::string, uf::Mesh::AttributeView> attributes;
|
uf::stl::unordered_map<uf::stl::string, uf::Mesh::AttributeView> attributes;
|
||||||
|
|
||||||
const AttributeView& operator[](const uf::stl::string& name) const {
|
const AttributeView& operator[](const uf::stl::string& name) const {
|
||||||
static AttributeView null{};
|
static AttributeView null{};
|
||||||
if ( auto it = attributes.find(name); it != attributes.end() ) return it->second;
|
if ( auto it = attributes.find(name); it != attributes.end() ) return it->second;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
typedef uf::stl::vector<uf::Mesh::View> views_t;
|
||||||
|
|
||||||
uf::stl::vector<buffer_t> buffers;
|
uf::stl::vector<buffer_t> buffers;
|
||||||
|
|
||||||
|
@ -212,7 +212,7 @@ namespace {
|
|||||||
bvh.dirty = false;
|
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;
|
uint32_t triangles = mesh.index.count / 3;
|
||||||
|
|
||||||
bvh.indices.clear();
|
bvh.indices.clear();
|
||||||
@ -223,7 +223,6 @@ namespace {
|
|||||||
uf::stl::vector<pod::AABB> bounds;
|
uf::stl::vector<pod::AABB> bounds;
|
||||||
bounds.reserve( triangles );
|
bounds.reserve( triangles );
|
||||||
|
|
||||||
auto views = mesh.makeViews({"position"});
|
|
||||||
UF_ASSERT( !views.empty() );
|
UF_ASSERT( !views.empty() );
|
||||||
|
|
||||||
// populate initial indices and bounds
|
// 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;
|
uint32_t triangles = mesh.index.count / 3;
|
||||||
|
|
||||||
uf::stl::vector<pod::AABB> bounds;
|
uf::stl::vector<pod::AABB> bounds;
|
||||||
bounds.reserve( triangles );
|
bounds.reserve( triangles );
|
||||||
|
|
||||||
auto views = mesh.makeViews({"position"});
|
|
||||||
UF_ASSERT( !views.empty() );
|
UF_ASSERT( !views.empty() );
|
||||||
|
|
||||||
// populate initial indices and bounds
|
// populate initial indices and bounds
|
||||||
|
@ -9,8 +9,8 @@ namespace {
|
|||||||
bool blockContactSolver = true; // use BlockNxN solvers (where N = number of contacts for a manifold)
|
bool blockContactSolver = true; // use BlockNxN solvers (where N = number of contacts for a manifold)
|
||||||
bool psgContactSolver = true; // use PSG contact solver
|
bool psgContactSolver = true; // use PSG contact solver
|
||||||
bool useGjk = false; // currently don't have a way to broadphase mesh => narrowphase tri via GJK
|
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
|
bool fixedStep = false; // 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
|
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
|
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
|
// increasing these make things lag for reasons I can imagine why
|
||||||
@ -22,7 +22,7 @@ namespace {
|
|||||||
bool flattenBvhMeshes = true;
|
bool flattenBvhMeshes = true;
|
||||||
|
|
||||||
// use surface area heuristics for building the BVH, rather than naive splits
|
// 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 useBvhSahMeshes = true;
|
||||||
|
|
||||||
bool useSplitBvhs = true; // creates separate BVHs for static / dynamic objects
|
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 );
|
auto& body = uf::physics::impl::create( world, object, mass, offset );
|
||||||
body.collider.type = pod::ShapeType::MESH;
|
body.collider.type = pod::ShapeType::MESH;
|
||||||
body.collider.mesh.mesh = &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;
|
body.collider.mesh.bvh = new pod::BVH;
|
||||||
auto& bvh = *body.collider.mesh.bvh;
|
auto& bvh = *body.collider.mesh.bvh;
|
||||||
::buildMeshBVH( bvh, mesh, ::meshBvhCapacity );
|
::buildMeshBVH( bvh, mesh, views, ::meshBvhCapacity );
|
||||||
|
|
||||||
body.bounds = ::computeAABB( body );
|
body.bounds = ::computeAABB( body );
|
||||||
uf::physics::impl::updateInertia( body );
|
uf::physics::impl::updateInertia( body );
|
||||||
@ -458,6 +459,7 @@ void uf::physics::impl::destroy( pod::PhysicsBody& body ) {
|
|||||||
// remove any pointered collider data
|
// remove any pointered collider data
|
||||||
if ( body.collider.type == pod::ShapeType::MESH ) {
|
if ( body.collider.type == pod::ShapeType::MESH ) {
|
||||||
if ( body.collider.mesh.bvh ) delete body.collider.mesh.bvh;
|
if ( body.collider.mesh.bvh ) delete body.collider.mesh.bvh;
|
||||||
|
if ( body.collider.mesh.views ) delete body.collider.mesh.views;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@ namespace {
|
|||||||
|
|
||||||
const auto& bvh = *mesh.collider.mesh.bvh;
|
const auto& bvh = *mesh.collider.mesh.bvh;
|
||||||
const auto& meshData = *mesh.collider.mesh.mesh;
|
const auto& meshData = *mesh.collider.mesh.mesh;
|
||||||
|
const auto& meshViews = *mesh.collider.mesh.views;
|
||||||
|
|
||||||
// transform to local space for BVH query
|
// transform to local space for BVH query
|
||||||
auto bounds = ::transformAabbToLocal( aabb.bounds, ::getTransform( mesh ) );
|
auto bounds = ::transformAabbToLocal( aabb.bounds, ::getTransform( mesh ) );
|
||||||
@ -31,7 +32,7 @@ namespace {
|
|||||||
bool hit = false;
|
bool hit = false;
|
||||||
// do collision per triangle
|
// do collision per triangle
|
||||||
for ( auto triID : candidates ) {
|
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;
|
if ( !::triangleAabb( tri, aabb, manifold, eps ) ) continue;
|
||||||
hit = true;
|
hit = true;
|
||||||
}
|
}
|
||||||
@ -45,6 +46,7 @@ namespace {
|
|||||||
|
|
||||||
const auto& bvh = *mesh.collider.mesh.bvh;
|
const auto& bvh = *mesh.collider.mesh.bvh;
|
||||||
const auto& meshData = *mesh.collider.mesh.mesh;
|
const auto& meshData = *mesh.collider.mesh.mesh;
|
||||||
|
const auto& meshViews = *mesh.collider.mesh.views;
|
||||||
|
|
||||||
// transform to local space for BVH query
|
// transform to local space for BVH query
|
||||||
auto bounds = ::transformAabbToLocal( sphere.bounds, ::getTransform( mesh ) );
|
auto bounds = ::transformAabbToLocal( sphere.bounds, ::getTransform( mesh ) );
|
||||||
@ -55,7 +57,7 @@ namespace {
|
|||||||
bool hit = false;
|
bool hit = false;
|
||||||
// do collision per triangle
|
// do collision per triangle
|
||||||
for ( auto triID : candidates ) {
|
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;
|
if ( !::triangleSphere( tri, sphere, manifold, eps ) ) continue;
|
||||||
hit = true;
|
hit = true;
|
||||||
}
|
}
|
||||||
@ -71,6 +73,7 @@ namespace {
|
|||||||
|
|
||||||
const auto& bvh = *mesh.collider.mesh.bvh;
|
const auto& bvh = *mesh.collider.mesh.bvh;
|
||||||
const auto& meshData = *mesh.collider.mesh.mesh;
|
const auto& meshData = *mesh.collider.mesh.mesh;
|
||||||
|
const auto& meshViews = *mesh.collider.mesh.views;
|
||||||
|
|
||||||
// transform to local space for BVH query
|
// transform to local space for BVH query
|
||||||
auto bounds = ::transformAabbToLocal( plane.bounds, ::getTransform( mesh ) );
|
auto bounds = ::transformAabbToLocal( plane.bounds, ::getTransform( mesh ) );
|
||||||
@ -81,7 +84,7 @@ namespace {
|
|||||||
bool hit = false;
|
bool hit = false;
|
||||||
// do collision per triangle
|
// do collision per triangle
|
||||||
for ( auto triID : candidates ) {
|
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;
|
if ( !::trianglePlane( tri, plane, manifold, eps ) ) continue;
|
||||||
hit = true;
|
hit = true;
|
||||||
}
|
}
|
||||||
@ -96,6 +99,7 @@ namespace {
|
|||||||
|
|
||||||
const auto& bvh = *mesh.collider.mesh.bvh;
|
const auto& bvh = *mesh.collider.mesh.bvh;
|
||||||
const auto& meshData = *mesh.collider.mesh.mesh;
|
const auto& meshData = *mesh.collider.mesh.mesh;
|
||||||
|
const auto& meshViews = *mesh.collider.mesh.views;
|
||||||
|
|
||||||
// transform to local space for BVH query
|
// transform to local space for BVH query
|
||||||
auto bounds = ::transformAabbToLocal( capsule.bounds, ::getTransform( mesh ) );
|
auto bounds = ::transformAabbToLocal( capsule.bounds, ::getTransform( mesh ) );
|
||||||
@ -106,7 +110,7 @@ namespace {
|
|||||||
bool hit = false;
|
bool hit = false;
|
||||||
// do collision per triangle
|
// do collision per triangle
|
||||||
for ( auto triID : candidates ) {
|
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;
|
if ( !::triangleCapsule( tri, capsule, manifold, eps ) ) continue;
|
||||||
hit = true;
|
hit = true;
|
||||||
}
|
}
|
||||||
@ -119,9 +123,11 @@ namespace {
|
|||||||
|
|
||||||
const auto& bvhA = *a.collider.mesh.bvh;
|
const auto& bvhA = *a.collider.mesh.bvh;
|
||||||
const auto& meshA = *a.collider.mesh.mesh;
|
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& 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
|
// compute overlaps between one BVH and another BVH
|
||||||
thread_local pod::BVH::pairs_t pairs;
|
thread_local pod::BVH::pairs_t pairs;
|
||||||
@ -131,8 +137,8 @@ namespace {
|
|||||||
bool hit = false;
|
bool hit = false;
|
||||||
// do collision per triangle
|
// do collision per triangle
|
||||||
for (auto [ idA, idB] : pairs ) {
|
for (auto [ idA, idB] : pairs ) {
|
||||||
auto tA = ::fetchTriangle( meshA, idA, a ); // transform triangles to world space
|
auto tA = ::fetchTriangle( meshA, viewsA, idA, a ); // transform triangles to world space
|
||||||
auto tB = ::fetchTriangle( meshB, idB, b );
|
auto tB = ::fetchTriangle( meshB, viewsB, idB, b );
|
||||||
|
|
||||||
if ( !::triangleTriangle( tA, tB, manifold, eps ) ) continue;
|
if ( !::triangleTriangle( tA, tB, manifold, eps ) ) continue;
|
||||||
hit = true;
|
hit = true;
|
||||||
|
@ -193,8 +193,9 @@ namespace {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool rayMesh( const pod::Ray& r, const pod::PhysicsBody& body, pod::RayQuery& rayHit ) {
|
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& bvh = *body.collider.mesh.bvh;
|
||||||
|
const auto& meshData = *body.collider.mesh.mesh;
|
||||||
|
const auto& meshViews = *body.collider.mesh.views;
|
||||||
|
|
||||||
const auto transform = ::getTransform( body );
|
const auto transform = ::getTransform( body );
|
||||||
|
|
||||||
@ -207,7 +208,7 @@ namespace {
|
|||||||
::queryBVH( bvh, ray, candidates );
|
::queryBVH( bvh, ray, candidates );
|
||||||
|
|
||||||
for ( auto triID : candidates ) {
|
for ( auto triID : candidates ) {
|
||||||
auto tri = ::fetchTriangle( meshData, triID );
|
auto tri = ::fetchTriangle( meshData, meshViews, triID );
|
||||||
|
|
||||||
float t, u, v;
|
float t, u, v;
|
||||||
if ( !::rayTriangleIntersect( ray, tri, t, u, v ) ) continue;
|
if ( !::rayTriangleIntersect( ray, tri, t, u, v ) ) continue;
|
||||||
|
@ -91,10 +91,7 @@ namespace {
|
|||||||
return tri;
|
return tri;
|
||||||
}
|
}
|
||||||
|
|
||||||
pod::TriangleWithNormal fetchTriangle( const uf::Mesh& mesh, size_t triID ) {
|
pod::TriangleWithNormal fetchTriangle( const uf::Mesh& mesh, const uf::Mesh::views_t& views, size_t triID ) {
|
||||||
static thread_local uf::stl::unordered_map<const uf::Mesh*, uf::stl::vector<uf::Mesh::View>> cachedViews;
|
|
||||||
if ( cachedViews.count(&mesh) == 0 ) cachedViews[&mesh] = mesh.makeViews({"position"});
|
|
||||||
auto& views = cachedViews[&mesh];
|
|
||||||
UF_ASSERT(!views.empty());
|
UF_ASSERT(!views.empty());
|
||||||
|
|
||||||
// find which view contains this triangle index.
|
// 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
|
// 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 ) {
|
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, triID );
|
auto tri = ::fetchTriangle( mesh, views, triID );
|
||||||
|
|
||||||
auto transform = ::getTransform( body );
|
auto transform = ::getTransform( body );
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user