Skip to content

Commit 70288b6

Browse files
committed
Fix RigidStatic intersetion at initial pose
Fixes include: - Buffer sizes corrections in the triangle mesh descriptor - Raycasting against the object itself, and not over the PxScene. - Updating object pose - Changing initialization order in Games between ObjectList and Physics to prevent double freeing of physics objects - Triangle mesh post processing(physx::PxMeshPreprocessingFlag::eWELD_VERTICES)
1 parent 4acac3c commit 70288b6

12 files changed

Lines changed: 186 additions & 105 deletions

File tree

3DRadSpace/Engine3DRadSpace/Games/Game.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -80,19 +80,19 @@ IService* Game::RequireService(const std::type_index& type)
8080

8181
Game::Game(const std::string &title, size_t width, size_t height) :
8282
Window(std::make_unique<Native::Window>(title, width, height)),
83-
Objects(std::make_unique<ObjectList>(this)),
8483
Keyboard(Window->GetKeyboardState()),
85-
Mouse(Window->GetMouseState())
84+
Mouse(Window->GetMouseState()),
85+
Objects(std::make_unique<ObjectList>(this))
8686
{
8787
Device = GameFactory::CreateGraphicsDevice("", Window->NativeHandle(), width, height);
8888
_initialize();
8989
}
9090

9191
Game::Game(Native::Window &&window) :
9292
Window(std::make_unique<Native::Window>(std::move(window))),
93-
Objects(std::make_unique<ObjectList>(this)),
9493
Keyboard(Window->GetKeyboardState()),
95-
Mouse(Window->GetMouseState())
94+
Mouse(Window->GetMouseState()),
95+
Objects(std::make_unique<ObjectList>(this))
9696
{
9797
Math::Point size = Window->Size();
9898

3DRadSpace/Engine3DRadSpace/Games/Game.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ namespace Engine3DRadSpace
4242

4343
std::unique_ptr<Native::Window> Window;
4444
std::unique_ptr<Graphics::IGraphicsDevice> Device;
45-
std::unique_ptr<Objects::ObjectList> Objects;
4645

4746
Math::Matrix4x4 View;
4847
Math::Matrix4x4 Projection;
@@ -60,6 +59,8 @@ namespace Engine3DRadSpace
6059
std::unique_ptr<Audio::IAudioEngine> Audio;
6160
std::unique_ptr<Graphics::Rendering::PostProcessCollection> PostProcesses;
6261

62+
std::unique_ptr<Objects::ObjectList> Objects;
63+
6364
IService* RequireService(const std::type_index& type);
6465

6566
double Draw_dt = 0;

3DRadSpace/Engine3DRadSpace/Graphics/DirectX11/VertexBuffer.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ size_t VertexBuffer::ReadData(void** data)
7373
_device->_context->Map(_buffer.Get(), 0, D3D11_MAP_READ, 0, &res);
7474

7575
*data = res.pData;
76-
return size_t(res.DepthPitch);
76+
return _numVerts * _structSize;
7777
}
7878

7979
void VertexBuffer::EndRead()

3DRadSpace/Engine3DRadSpace/Physics/ICollider.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ namespace Engine3DRadSpace::Physics
2525

2626
virtual std::optional<float> Intersects(const Math::Ray& r) = 0;
2727
virtual void UpdateTransform() = 0;
28+
virtual void UpdateTransform(const Math::Vector3& position, const Math::Quaternion& rotation) = 0;
2829

2930
virtual ~ICollider() = default;
3031
};

3DRadSpace/Engine3DRadSpace/Physics/NVPhysX/DynamicCollider.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,10 @@ void DynamicCollider::UpdateTransform()
120120

121121
}
122122

123+
void DynamicCollider::UpdateTransform(const Math::Vector3 & position, const Math::Quaternion & rotation)
124+
{
125+
}
126+
123127
std::optional<float> DynamicCollider::Intersects(const Math::Ray& r)
124128
{
125129
return 0.0f;

3DRadSpace/Engine3DRadSpace/Physics/NVPhysX/DynamicCollider.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ namespace Engine3DRadSpace::Physics::NVPhysX
4444

4545
std::optional<float> Intersects(const Math::Ray& r) override;
4646
void UpdateTransform() override;
47+
void UpdateTransform(const Math::Vector3& position, const Math::Quaternion& rotation) override;
4748

4849
friend class PhysicsEngine;
4950

3DRadSpace/Engine3DRadSpace/Physics/NVPhysX/PhysicsEngine.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -101,9 +101,12 @@ PhysicsEngine::~PhysicsEngine()
101101
PX_RELEASE(_cpuDispatcher);
102102
PX_RELEASE(_physics);
103103

104-
auto transport = _pvd->getTransport();
105-
PX_RELEASE(transport);
106-
PX_RELEASE(_pvd);
104+
if(_pvd)
105+
{
106+
auto transport = _pvd->getTransport();
107+
PX_RELEASE(transport);
108+
PX_RELEASE(_pvd);
109+
}
107110

108111
PX_RELEASE(_foundation);
109112
}

3DRadSpace/Engine3DRadSpace/Physics/NVPhysX/PhysicsEngine.hpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,13 @@ namespace Engine3DRadSpace::Physics::NVPhysX
2424
std::unique_ptr<physx::PxDefaultAllocator> _allocator;
2525
std::unique_ptr<physx::PxErrorCallback> _errCallback;
2626

27-
physx::PxFoundation* _foundation;
28-
physx::PxPvd* _pvd;
29-
physx::PxPvdTransport* _pvdTransport;
27+
physx::PxFoundation* _foundation = nullptr;
28+
physx::PxPvd* _pvd = nullptr;
29+
physx::PxPvdTransport* _pvdTransport = nullptr;
3030

31-
physx::PxPhysics* _physics;
32-
physx::PxDefaultCpuDispatcher* _cpuDispatcher;
33-
physx::PxScene* _scene;
31+
physx::PxPhysics* _physics = nullptr;
32+
physx::PxDefaultCpuDispatcher* _cpuDispatcher = nullptr;
33+
physx::PxScene* _scene = nullptr;
3434

3535
double _accTimer = 0;
3636
double _timeStep;

3DRadSpace/Engine3DRadSpace/Physics/NVPhysX/StaticMeshCollider.cpp

Lines changed: 83 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <geometry/PxTriangleMeshGeometry.h>
88
#include <PxPhysicsAPI.h>
99
#include "../../Content/Assets/ModelAsset.hpp"
10+
#include "../../Logging/Warning.hpp"
1011

1112
using namespace Engine3DRadSpace;
1213
using namespace Engine3DRadSpace::Content::Assets;
@@ -31,52 +32,60 @@ void StaticMeshCollider::_generateRigidbody()
3132

3233
physx::PxTolerancesScale toleranceScale;
3334
physx::PxCookingParams cookParams(toleranceScale);
35+
cookParams.meshPreprocessParams |= physx::PxMeshPreprocessingFlag::eWELD_VERTICES;
36+
cookParams.meshWeldTolerance = 0.001f;
3437

3538
for(auto &mesh : *_model)
3639
{
3740
for(auto &part : *mesh.get())
3841
{
42+
auto [vertexBuffer, indexBuffer] = part->CreateStagingBuffers();
43+
3944
void* verts;
40-
size_t structSize = part->VertexBuffer->StructSize();
41-
size_t numVertices = part->VertexBuffer->NumVertices();
42-
4345
void* indices;
44-
part->VertexBuffer->ReadData(&verts);
45-
46-
//create a copy of the position vertices.
47-
std::unique_ptr<Vector3[]> vertices = std::make_unique<Vector3[]>(numVertices);
48-
for(size_t i = 0; i < numVertices; ++i)
46+
47+
size_t structSize = vertexBuffer->StructSize();
48+
std::ignore = vertexBuffer->ReadData(&verts);
49+
size_t numVertices = vertexBuffer->NumVertices();
50+
51+
std::unique_ptr<Vector3[]> vertices = std::make_unique<Vector3[]>(numVertices);
52+
for(size_t i = 0; i < numVertices; i++)
4953
{
54+
//Assume VS_Position as first element of the declaration.
5055
vertices[i] = *reinterpret_cast<Vector3*>((static_cast<std::byte*>(verts) + (structSize * i)));
5156
}
5257

53-
part->VertexBuffer->EndRead();
54-
part->IndexBuffer->ReadData(&indices);
58+
std::ignore = indexBuffer->ReadData(&indices);
59+
size_t numIndices = indexBuffer->NumIndices();
5560

56-
physx::PxTriangleMeshDesc meshDesc;
61+
physx::PxTriangleMeshDesc meshDesc{};
62+
meshDesc.setToDefault();
5763

5864
meshDesc.points.count = numVertices;
5965
meshDesc.points.data = vertices.get();
60-
meshDesc.points.stride = part->VertexBuffer->StructSize();
66+
meshDesc.points.stride = sizeof(Vector3);
6167

62-
meshDesc.triangles.count = part->IndexBuffer->NumIndices();
68+
meshDesc.triangles.count = numIndices / 3;
6369
meshDesc.triangles.data = indices;
64-
meshDesc.triangles.stride = sizeof(unsigned);
70+
meshDesc.triangles.stride = 3 * sizeof(unsigned);
6571

6672
#if _DEBUG
67-
auto b = PxValidateTriangleMesh(cookParams, meshDesc);
68-
PX_ASSERT(b);
69-
assert(b);
73+
if(!PxValidateTriangleMesh(cookParams, meshDesc))
74+
Logging::SetLastWarning("PhysX: PxValidateTriangleMesh failed!");
7075
#endif
71-
meshes.push_back(
72-
PxCreateTriangleMesh(
73-
cookParams,
74-
meshDesc,
75-
nvPhysics->getPhysicsInsertionCallback()
76-
)
76+
auto cookedMesh = PxCreateTriangleMesh(
77+
cookParams,
78+
meshDesc,
79+
nvPhysics->getPhysicsInsertionCallback()
7780
);
7881

79-
part->IndexBuffer->EndRead();
82+
vertexBuffer->EndRead();
83+
indexBuffer->EndRead();
84+
85+
if(cookedMesh != nullptr)
86+
meshes.push_back(cookedMesh);
87+
else
88+
Logging::SetLastWarning("PhysX: PxCreateTriangleMesh failed!");
8089
}
8190
}
8291

@@ -104,8 +113,6 @@ float StaticMeshCollider::_getMass()
104113

105114
void StaticMeshCollider::_setMass(float mass)
106115
{
107-
_mass = mass;
108-
//static_cast<physx::PxRigidStatic*>(_rigidbody.get());
109116
}
110117

111118
float StaticMeshCollider::_getLinearDamping()
@@ -156,76 +163,70 @@ StaticMeshCollider::StaticMeshCollider(
156163
IPhysicsEngine* physics,
157164
Graphics::Model3D* model,
158165
const Math::Vector3 scale
159-
) : IStaticCollider(physics)
166+
) : IStaticCollider(physics),
167+
_model(model),
168+
_scale(scale)
160169
{
161170
_generateRigidbody();
162171
}
163172

164173
void StaticMeshCollider::UpdateTransform()
165174
{
166-
auto rigidbody = static_cast<physx::PxRigidStatic*>(_rigidbody.get());
167-
auto tr = rigidbody->getGlobalPose();
168-
169-
_position = Vector3(
170-
tr.p.x,
171-
tr.p.y,
172-
tr.p.z
173-
);
174-
175-
_rotation = Quaternion(
176-
tr.q.x,
177-
tr.q.y,
178-
tr.q.z,
179-
tr.q.w
180-
);
181175
}
182176

183-
std::optional<float> StaticMeshCollider::Intersects(const Math::Ray &r)
177+
void StaticMeshCollider::UpdateTransform(const Math::Vector3 &position, const Math::Quaternion &rotation)
184178
{
185-
if(_physics == nullptr) return std::nullopt;
186-
187-
auto scene = static_cast<physx::PxScene*>(_physics->GetScene());
188-
189-
auto origin = physx::PxVec3(r.Origin.X, r.Origin.Y, r.Origin.Z);
190-
auto dir = physx::PxVec3(r.Direction.X, r.Direction.Y, r.Direction.Z);
191-
192-
physx::PxRaycastBuffer buffer;
193-
194-
bool result = scene->raycast(
195-
origin,
196-
dir,
197-
std::numeric_limits<float>::infinity(),
198-
buffer
199-
);
200-
if(!result || !buffer.hasBlock) return std::nullopt;
201-
202-
if(buffer.block.actor != static_cast<physx::PxRigidStatic*>(_rigidbody.get())) return false;
203-
else return buffer.block.distance;
179+
_rigidbody->setGlobalPose(physx::PxTransform(
180+
physx::PxVec3(_position.X, _position.Y, _position.Z),
181+
physx::PxQuat(_rotation.X, _rotation.Y, _rotation.Z, _rotation.W)
182+
));
204183
}
205184

206-
void StaticMeshCollider::SetPosition(const Vector3& pos, bool wake)
185+
std::optional<float> StaticMeshCollider::Intersects(const Math::Ray &r)
207186
{
208-
auto rigidbody = static_cast<physx::PxRigidStatic*>(_rigidbody.get());
209-
auto tr = rigidbody->getGlobalPose();
187+
if(_rigidbody == nullptr) return std::nullopt;
210188

211-
tr.p = physx::PxVec3(pos.X, pos.Y, pos.Z);
212-
rigidbody->setGlobalPose(physx::PxTransform(tr));
213-
}
189+
auto* actor = static_cast<physx::PxRigidStatic*>(_rigidbody.get());
214190

215-
void StaticMeshCollider::SetRotation(const Math::Quaternion & newQuat, bool wake)
216-
{
217-
auto rigidbody = static_cast<physx::PxRigidStatic*>(_rigidbody.get());
218-
auto tr = rigidbody->getGlobalPose();
219-
220-
tr.q = physx::PxQuat(newQuat.X, newQuat.Y, newQuat.Z, newQuat.W);
221-
rigidbody->setGlobalPose(physx::PxTransform(tr));
222-
}
191+
physx::PxVec3 origin(r.Origin.X, r.Origin.Y, r.Origin.Z);
192+
physx::PxVec3 dir(r.Direction.X, r.Direction.Y, r.Direction.Z);
223193

224-
void StaticMeshCollider::SetPositionRotation(const Math::Vector3 & newPos, const Math::Vector3 & newQuat, bool wake)
225-
{
226-
physx::PxTransform tr;
227-
tr.p = { _position.X, _position.Y, _position.Z};
228-
tr.q = {_rotation.X, _rotation.Y, _rotation.Z, _rotation.W};
194+
if(dir.normalize() == 0.0f) return std::nullopt;
195+
196+
physx::PxU32 numShapes = actor->getNbShapes();
197+
if(numShapes == 0)
198+
{
199+
Logging::SetLastWarning("PhysX: StaticMeshCollider::Intersects - no shapes attached (mesh cooking may have failed).");
200+
return std::nullopt;
201+
}
202+
203+
std::vector<physx::PxShape*> shapes(numShapes);
204+
actor->getShapes(shapes.data(), numShapes);
205+
206+
float closestDist = PX_MAX_F32;
207+
bool hasHit = false;
208+
209+
for(auto* shape : shapes)
210+
{
211+
physx::PxTransform pose = actor->getGlobalPose() * shape->getLocalPose();
212+
physx::PxRaycastHit hit;
213+
214+
physx::PxU32 hitCount = physx::PxGeometryQuery::raycast(
215+
origin, dir,
216+
shape->getGeometry(),
217+
pose,
218+
PX_MAX_F32,
219+
physx::PxHitFlag::eDEFAULT | physx::PxHitFlag::eMESH_BOTH_SIDES,
220+
1,
221+
&hit
222+
);
223+
224+
if(hitCount > 0 && hit.distance < closestDist)
225+
{
226+
closestDist = hit.distance;
227+
hasHit = true;
228+
}
229+
}
229230

230-
static_cast<physx::PxRigidStatic*>(_rigidbody.get())->setGlobalPose(tr);
231+
return hasHit ? std::optional<float>(closestDist) : std::nullopt;
231232
}

3DRadSpace/Engine3DRadSpace/Physics/NVPhysX/StaticMeshCollider.hpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,12 +52,9 @@ namespace Engine3DRadSpace::Physics::NVPhysX
5252
StaticMeshCollider(StaticMeshCollider&& rb) noexcept = default;
5353
StaticMeshCollider& operator=(StaticMeshCollider&& rb) noexcept = default;
5454

55-
void SetPosition(const Math::Vector3& newPos, bool wake = false);
56-
void SetRotation(const Math::Quaternion& newQuat, bool wake = false);
57-
void SetPositionRotation(const Math::Vector3& newPos, const Math::Vector3& newQuat, bool wake);
58-
5955
std::optional<float> Intersects(const Math::Ray& r) override;
6056
void UpdateTransform() override;
57+
void UpdateTransform(const Math::Vector3& position, const Math::Quaternion& rotation) override;
6158

6259
friend class PhysicsEngine;
6360

0 commit comments

Comments
 (0)