77#include < geometry/PxTriangleMeshGeometry.h>
88#include < PxPhysicsAPI.h>
99#include " ../../Content/Assets/ModelAsset.hpp"
10+ #include " ../../Logging/Warning.hpp"
1011
1112using namespace Engine3DRadSpace ;
1213using 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
105114void StaticMeshCollider::_setMass (float mass)
106115{
107- _mass = mass;
108- // static_cast<physx::PxRigidStatic*>(_rigidbody.get());
109116}
110117
111118float 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
164173void 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}
0 commit comments