/** * Perform any cleanup of physics engine resources. * This is deferred because when closing down the game, you want to make sure you are not destroying a mesh after the physics SDK has been shut down. */ void DeferredPhysResourceCleanup() { #if WITH_PHYSX // Release all tri meshes and reset array for(int32 MeshIdx=0; MeshIdx<GPhysXPendingKillTriMesh.Num(); MeshIdx++) { PxTriangleMesh* PTriMesh = GPhysXPendingKillTriMesh[MeshIdx]; check(PTriMesh); PTriMesh->release(); GPhysXPendingKillTriMesh[MeshIdx] = NULL; } GPhysXPendingKillTriMesh.Reset(); // Release all convex meshes and reset array for(int32 MeshIdx=0; MeshIdx<GPhysXPendingKillConvex.Num(); MeshIdx++) { PxConvexMesh* PConvexMesh = GPhysXPendingKillConvex[MeshIdx]; check(PConvexMesh); PConvexMesh->release(); GPhysXPendingKillConvex[MeshIdx] = NULL; } GPhysXPendingKillConvex.Reset(); // Release all heightfields and reset array for(int32 HfIdx=0; HfIdx<GPhysXPendingKillHeightfield.Num(); HfIdx++) { PxHeightField* PHeightfield = GPhysXPendingKillHeightfield[HfIdx]; check(PHeightfield); PHeightfield->release(); GPhysXPendingKillHeightfield[HfIdx] = NULL; } GPhysXPendingKillHeightfield.Reset(); // Release all materials and reset array for(int32 MeshIdx=0; MeshIdx<GPhysXPendingKillMaterial.Num(); MeshIdx++) { PxMaterial* PMaterial = GPhysXPendingKillMaterial[MeshIdx]; check(PMaterial); PMaterial->release(); GPhysXPendingKillMaterial[MeshIdx] = NULL; } GPhysXPendingKillMaterial.Reset(); #endif }
bool CreateGeometryFromPhysxGeometry(PxTriangleMeshGeometry &g, const PxTransform &globalPose, LevelGeometry::Mesh &mesh) { PxTriangleMesh *tm = g.triangleMesh; const PxU32 nbVerts = tm->getNbVertices(); const PxVec3* verts = tm->getVertices(); PxU32 nbTris = tm->getNbTriangles(); const void* typelessTris = tm->getTriangles(); PxU32 numIndices = nbTris * 3; mesh.indices.Resize(numIndices); if (tm->has16BitTriangleIndices()) { // Convert indices to 32 bit const short *i16 = reinterpret_cast<const short*>(typelessTris); for (PxU32 i = 0; i < numIndices; ++i) { mesh.indices[i] = i16[i]; } } else { int size = numIndices * sizeof(mesh.indices[0]); memcpy_s(&mesh.indices[0], size, typelessTris, size); } // Transform vertices to world space mesh.vertices.Resize(nbVerts); for (PxU32 i = 0; i < nbVerts; ++i) { PxVec3 pos = globalPose.transform(verts[i]); mesh.vertices[i].Assign(pos.x, pos.y, pos.z); } // Reject out-of-regions triangles numIndices = gConvexRegionsManager.FilterOutsideTriangles(&mesh.vertices[0], &mesh.indices[0], numIndices); r3d_assert(numIndices % 3 == 0); mesh.indices.Resize(numIndices); return true; }
osg::Node* createNodeForActor( PxRigidActor* actor ) { if ( !actor ) return NULL; std::vector<PxShape*> shapes( actor->getNbShapes() ); osg::ref_ptr<osg::MatrixTransform> transform = new osg::MatrixTransform; transform->setMatrix( toMatrix(PxMat44(actor->getGlobalPose())) ); osg::ref_ptr<osg::Geode> geode = new osg::Geode; transform->addChild( geode.get() ); PxU32 num = actor->getShapes( &(shapes[0]), actor->getNbShapes() ); for ( PxU32 i=0; i<num; ++i ) { PxShape* shape = shapes[i]; osg::Matrix localMatrix = toMatrix( PxMat44(actor->getGlobalPose()) ); osg::Vec3 localPos = toVec3( shape->getLocalPose().p ); osg::Quat localQuat(shape->getLocalPose().q.x, shape->getLocalPose().q.y, shape->getLocalPose().q.z, shape->getLocalPose().q.w); switch ( shape->getGeometryType() ) { case PxGeometryType::eSPHERE: { PxSphereGeometry sphere; shape->getSphereGeometry( sphere ); osg::Sphere* sphereShape = new osg::Sphere(localPos, sphere.radius); geode->addDrawable( new osg::ShapeDrawable(sphereShape) ); } break; case PxGeometryType::ePLANE: // TODO break; case PxGeometryType::eCAPSULE: { PxCapsuleGeometry capsule; shape->getCapsuleGeometry( capsule ); osg::Capsule* capsuleShape = new osg::Capsule( localPos, capsule.radius, capsule.halfHeight * 2.0f); capsuleShape->setRotation( localQuat ); geode->addDrawable( new osg::ShapeDrawable(capsuleShape) ); } break; case PxGeometryType::eBOX: { PxBoxGeometry box; shape->getBoxGeometry( box ); osg::Box* boxShape = new osg::Box(localPos, box.halfExtents[0] * 2.0f, box.halfExtents[1] * 2.0f, box.halfExtents[2] * 2.0f); boxShape->setRotation( localQuat ); geode->addDrawable( new osg::ShapeDrawable(boxShape) ); } break; case PxGeometryType::eCONVEXMESH: { PxConvexMeshGeometry convexMeshGeom; shape->getConvexMeshGeometry( convexMeshGeom ); // TODO: consider convexMeshGeom.scale PxConvexMesh* convexMesh = convexMeshGeom.convexMesh; if ( convexMesh ) { /*for ( unsigned int i=0; i<convexMesh->getNbPolygons(); ++i ) { }*/ // TODO } } break; case PxGeometryType::eTRIANGLEMESH: { PxTriangleMeshGeometry triangleMeshGeom; shape->getTriangleMeshGeometry( triangleMeshGeom ); // TODO: consider triangleMeshGeom.scale PxTriangleMesh* triangleMesh = triangleMeshGeom.triangleMesh; if ( triangleMesh ) { osg::ref_ptr<osg::Vec3Array> va = new osg::Vec3Array( triangleMesh->getNbVertices() ); for ( unsigned int i=0; i<va->size(); ++i ) (*va)[i] = toVec3( *(triangleMesh->getVertices() + i) ) * localMatrix; osg::ref_ptr<osg::DrawElements> de; if ( triangleMesh->getTriangleMeshFlags()&PxTriangleMeshFlag::eHAS_16BIT_TRIANGLE_INDICES ) { osg::DrawElementsUShort* de16 = new osg::DrawElementsUShort(GL_TRIANGLES); de = de16; const PxU16* indices = (const PxU16*)triangleMesh->getTriangles(); for ( unsigned int i=0; i<triangleMesh->getNbTriangles(); ++i ) { de16->push_back( indices[3 * i + 0] ); de16->push_back( indices[3 * i + 1] ); de16->push_back( indices[3 * i + 2] ); } } else { osg::DrawElementsUInt* de32 = new osg::DrawElementsUInt(GL_TRIANGLES); de = de32; const PxU32* indices = (const PxU32*)triangleMesh->getTriangles(); for ( unsigned int i=0; i<triangleMesh->getNbTriangles(); ++i ) { de32->push_back( indices[3 * i + 0] ); de32->push_back( indices[3 * i + 1] ); de32->push_back( indices[3 * i + 2] ); } } geode->addDrawable( createGeometry(va.get(), NULL, NULL, de.get()) ); } } break; case PxGeometryType::eHEIGHTFIELD: { PxHeightFieldGeometry hfGeom; shape->getHeightFieldGeometry( hfGeom ); // TODO: consider hfGeom.*scale PxHeightField* heightField = hfGeom.heightField; if ( heightField ) { // TODO } } break; } } return transform.release(); }
/** * Perform any cleanup of physics engine resources. * This is deferred because when closing down the game, you want to make sure you are not destroying a mesh after the physics SDK has been shut down. */ void DeferredPhysResourceCleanup() { #if WITH_PHYSX // Release all tri meshes and reset array for(int32 MeshIdx=0; MeshIdx<GPhysXPendingKillTriMesh.Num(); MeshIdx++) { PxTriangleMesh* PTriMesh = GPhysXPendingKillTriMesh[MeshIdx]; // Check this as it shouldn't be null, but then gate on it so we can // avoid a crash if we end up in this state in shipping check(PTriMesh); if(PTriMesh) { PTriMesh->release(); if(GPhysXPendingKillTriMesh.IsValidIndex(MeshIdx)) { GPhysXPendingKillTriMesh[MeshIdx] = NULL; } else { UE_LOG(LogPhysics, Warning, TEXT("DeferredPhysResourceCleanup found invalid index into GPhysXPendingKillTriMesh, another thread may have modified the array."), MeshIdx); } } else { UE_LOG(LogPhysics, Warning, TEXT("DeferredPhysResourceCleanup found null PxTriangleMesh in pending kill array, another thread may have modified the array."), MeshIdx); } } GPhysXPendingKillTriMesh.Reset(); // Release all convex meshes and reset array for(int32 MeshIdx=0; MeshIdx<GPhysXPendingKillConvex.Num(); MeshIdx++) { PxConvexMesh* PConvexMesh = GPhysXPendingKillConvex[MeshIdx]; // Check this as it shouldn't be null, but then gate on it so we can // avoid a crash if we end up in this state in shipping check(PConvexMesh); if(PConvexMesh) { PConvexMesh->release(); if(GPhysXPendingKillConvex.IsValidIndex(MeshIdx)) { GPhysXPendingKillConvex[MeshIdx] = NULL; } else { UE_LOG(LogPhysics, Warning, TEXT("DeferredPhysResourceCleanup found invalid index into GPhysXPendingKillConvex (%d), another thread may have modified the array."), MeshIdx); } } else { UE_LOG(LogPhysics, Warning, TEXT("DeferredPhysResourceCleanup found null PxConvexMesh in pending kill array (at %d), another thread may have modified the array."), MeshIdx); } } GPhysXPendingKillConvex.Reset(); // Release all heightfields and reset array for(int32 HfIdx=0; HfIdx<GPhysXPendingKillHeightfield.Num(); HfIdx++) { PxHeightField* PHeightfield = GPhysXPendingKillHeightfield[HfIdx]; // Check this as it shouldn't be null, but then gate on it so we can // avoid a crash if we end up in this state in shipping check(PHeightfield); if(PHeightfield) { PHeightfield->release(); if(GPhysXPendingKillHeightfield.IsValidIndex(HfIdx)) { GPhysXPendingKillHeightfield[HfIdx] = NULL; } else { UE_LOG(LogPhysics, Warning, TEXT("DeferredPhysResourceCleanup found invalid index into GPhysXPendingKillHeightfield (%d), another thread may have modified the array."), HfIdx); } } else { UE_LOG(LogPhysics, Warning, TEXT("DeferredPhysResourceCleanup found null PxHeightField in pending kill array (at %d), another thread may have modified the array."), HfIdx); } } GPhysXPendingKillHeightfield.Reset(); // Release all materials and reset array for(int32 MeshIdx=0; MeshIdx<GPhysXPendingKillMaterial.Num(); MeshIdx++) { PxMaterial* PMaterial = GPhysXPendingKillMaterial[MeshIdx]; // Check this as it shouldn't be null, but then gate on it so we can // avoid a crash if we end up in this state in shipping check(PMaterial); if(PMaterial) { PMaterial->release(); if(GPhysXPendingKillMaterial.IsValidIndex(MeshIdx)) { GPhysXPendingKillMaterial[MeshIdx] = NULL; } else { UE_LOG(LogPhysics, Warning, TEXT("DeferredPhysResourceCleanup found invalid index into GPhysXPendingKillMaterial(%d), another thread may have modified the array."), MeshIdx); } } else { UE_LOG(LogPhysics, Warning, TEXT("DeferredPhysResourceCleanup found null PxMaterial in pending kill array (at %d), another thread may have modified the array."), MeshIdx); } } GPhysXPendingKillMaterial.Reset(); #endif }