PxTriangleMesh* PhysicsSystem::cookTriangleMesh(Mesh& mesh) { FDUint nbVerts = mesh.getVertexCount(); FDUint triCount = mesh.getIndexCount() / 3; void* verts = mesh.getSourceData(); void* indices = mesh.getSourceIndexData(); PxTriangleMeshDesc meshDesc; meshDesc.flags |= PxMeshFlag::e16_BIT_INDICES; meshDesc.points.count = nbVerts; meshDesc.points.stride = mesh.getDescriptor()->getVertexSize(); meshDesc.points.data = verts; meshDesc.triangles.count = triCount; meshDesc.triangles.stride = 3*sizeof(PxU16); meshDesc.triangles.data = indices; PxDefaultMemoryOutputStream writeBuffer; FDbool status = cooking->cookTriangleMesh(meshDesc, writeBuffer); if (!status) { FD_THROW(GenericException("Cooking failed.")); } PxDefaultMemoryInputData readBuffer(writeBuffer.getData(), writeBuffer.getSize()); PxTriangleMesh* physicalMesh = physics->createTriangleMesh(readBuffer); return physicalMesh; }
PxTriangleMesh* Physx::createTriangleMesh( const vector<vec3>& positions, size_t numTriangles, vector<uint32_t> indices ) { if ( positions.empty() ) { return nullptr; } if ( indices.empty() ) { CI_ASSERT( positions.size() % 3 == 0 ); uint32_t count = (uint32_t)positions.size(); for ( uint32_t i = 0; i < count; ++i ) { indices.push_back( i ); } numTriangles = indices.size() / 3; } PxTriangleMeshDesc desc; desc.points.count = (PxU32)positions.size(); desc.points.data = (PxVec3*)&positions[ 0 ]; desc.points.stride = sizeof( PxVec3 ); desc.triangles.count = (PxU32)numTriangles; desc.triangles.data = (PxU32*)&indices[ 0 ]; desc.triangles.stride = sizeof( PxU32 ) * 3; PxDefaultMemoryOutputStream writeBuffer; if ( !mCooking->cookTriangleMesh( desc, writeBuffer ) ) { return nullptr; } PxDefaultMemoryInputData readBuffer( writeBuffer.getData(), writeBuffer.getSize() ); return mPhysics->createTriangleMesh( readBuffer ); }
physx::PxInputStream* PhysXRigidManager::getTriangleMeshGeo(PxScene *world, physx::PxCooking* mCooking, ExternalInfo externInfo, bool isStatic) { PxPhysics *gPhysics = &(world->getPhysics()); PxDefaultMemoryOutputStream *writeBuffer = new PxDefaultMemoryOutputStream(); bool status; if (isStatic) { PxTriangleMeshDesc meshDesc; meshDesc.points.count = externInfo.nbVertices; meshDesc.points.stride = 4 * sizeof(float); meshDesc.points.data = externInfo.vertices; meshDesc.triangles.count = static_cast<int> (externInfo.nbIndices / 3); meshDesc.triangles.stride = 3 * sizeof(unsigned int); meshDesc.triangles.data = externInfo.indices; status = mCooking->cookTriangleMesh(meshDesc, *writeBuffer); } else { PxConvexMeshDesc meshDesc2; meshDesc2.points.count = externInfo.nbVertices; meshDesc2.points.stride = 4 * sizeof(float); meshDesc2.points.data = externInfo.vertices; meshDesc2.flags |= PxConvexFlag::eCOMPUTE_CONVEX | PxConvexFlag::eINFLATE_CONVEX; meshDesc2.vertexLimit = 256; status = mCooking->cookConvexMesh(meshDesc2, *writeBuffer); } return new PxDefaultMemoryInputData(writeBuffer->getData(), writeBuffer->getSize()); }
PxGeometry& Camera::getPixelFrustum(FDreal pixelXSize, FDreal pixelYSize) { if (pixelFrustum.isValid()) { return pixelFrustum; } Vector3 proj1(-pixelXSize / 2, -pixelYSize / 2, 1); Vector3 proj2(-pixelXSize / 2, pixelYSize / 2, 1); Vector3 proj3(pixelXSize / 2, -pixelYSize / 2, 1); Vector3 proj4(pixelXSize / 2, pixelYSize / 2, 1); fdmath::Matrix44 projInverse; fdmath::gluInvertMatrix44(projection, projInverse); FDreal len = -100.0f; Vector3 view1 = projInverse.transform(proj1).getNormalized() * len; Vector3 view2 = projInverse.transform(proj2).getNormalized() * len; Vector3 view3 = projInverse.transform(proj3).getNormalized() * len; Vector3 view4 = projInverse.transform(proj4).getNormalized() * len; static const PxVec3 convexVerts[] = {PxVec3(0,0,0), view1, view2, view3, view4}; PhysicsSystem* physics = FreeThread__getWorld(). getSystem<PhysicsSystem>(); PxConvexMeshDesc convexDesc; convexDesc.points.count = 5; convexDesc.points.stride = sizeof(PxVec3); convexDesc.points.data = convexVerts; convexDesc.flags = PxConvexFlag::eCOMPUTE_CONVEX; convexDesc.vertexLimit = 256; PxDefaultMemoryOutputStream buf; if (!physics->cooking->cookConvexMesh(convexDesc, buf)) { FD_THROW(GenericException("Unable to cook convex pixel mesh!")); } PxDefaultMemoryInputData input(buf.getData(), buf.getSize()); PxConvexMesh* convexMesh = physics->physics->createConvexMesh(input); pixelFrustum = PxConvexMeshGeometry(convexMesh); return pixelFrustum; }
static PxConvexMesh* createConvexMesh(const PxVec3* verts, const PxU32 numVerts, PxPhysics& physics, PxCooking& cooking) { // Create descriptor for convex mesh PxConvexMeshDesc convexDesc; convexDesc.points.count = numVerts; convexDesc.points.stride = sizeof(PxVec3); convexDesc.points.data = verts; convexDesc.flags = PxConvexFlag::eCOMPUTE_CONVEX | PxConvexFlag::eINFLATE_CONVEX; PxConvexMesh* convexMesh = NULL; PxDefaultMemoryOutputStream buf; if(cooking.cookConvexMesh(convexDesc, buf)) { PxDefaultMemoryInputData id(buf.getData(), buf.getSize()); convexMesh = physics.createConvexMesh(id); } return convexMesh; }
PxConvexMesh* ConvexHull::compute(fdcore::Array<fdmath::Vector3> points, PhysicsSystem& physicsSystem) { PxConvexMeshDesc convexDesc; convexDesc.points.count = points.length; convexDesc.points.stride = sizeof(PxVec3); convexDesc.points.data = points.elements; convexDesc.flags = PxConvexFlag::eCOMPUTE_CONVEX; convexDesc.vertexLimit = 256; PxDefaultMemoryOutputStream buf; if (!physicsSystem.cooking->cookConvexMesh(convexDesc, buf)) { FD_THROW(GenericException("Unable to cook convex pixel mesh!")); } PxDefaultMemoryInputData input(buf.getData(), buf.getSize()); PxConvexMesh* convexMesh = physicsSystem.physics->createConvexMesh(input); return convexMesh; }
PxConvexMesh* Physx::createConvexMesh( const vector<vec3>& positions, PxConvexFlags flags ) { if ( positions.empty() ) { return nullptr; } PxConvexMeshDesc desc; desc.points.count = (PxU32)positions.size(); desc.points.data = (PxVec3*)&positions[ 0 ]; desc.points.stride = sizeof( PxVec3 ); desc.flags = flags; PxDefaultMemoryOutputStream buffer; if ( !mCooking->cookConvexMesh( desc, buffer ) ) { return nullptr; } PxDefaultMemoryInputData input( buffer.getData(), buffer.getSize() ); return mPhysics->createConvexMesh( input ); }
//PxTriangleMesh* PxDefaultMemoryInputData getTriangleMeshGeo(PxScene *m_pDynamicsWorld, std::shared_ptr<nau::scene::IScene> &aScene, bool isStatic=true) { PxPhysics *gPhysics = &(m_pDynamicsWorld->getPhysics()); std::shared_ptr<nau::scene::SceneObject> &aObject = aScene->getSceneObject(0); std::shared_ptr<VertexData> &vd = aObject->getRenderable()->getVertexData(); std::vector<std::shared_ptr<MaterialGroup>> &matGroups = aObject->getRenderable()->getMaterialGroups(); std::vector<std::shared_ptr<MaterialGroup>>::iterator matGroupsIter; PxDefaultMemoryOutputStream writeBuffer; PxTriangleMeshDesc meshDesc; matGroupsIter = matGroups.begin(); for (; matGroupsIter != matGroups.end(); matGroupsIter++) { if ((*matGroupsIter)->getIndexData()->getIndexSize()) { std::shared_ptr<std::vector<unsigned int>> &indexes = (*matGroupsIter)->getIndexData()->getIndexData(); meshDesc.points.count = static_cast<int> (vd->getDataOf(VertexData::GetAttribIndex(std::string("position")))->size()); meshDesc.points.stride = 4 * sizeof(float); meshDesc.points.data = reinterpret_cast<const unsigned char *>(&(vd->getDataOf(VertexData::GetAttribIndex(std::string("position")))->at(0))); meshDesc.triangles.count = static_cast<int> (indexes->size() / 3); meshDesc.triangles.stride = 3 * sizeof(unsigned int); meshDesc.triangles.data = reinterpret_cast<const unsigned char *>(&((*indexes)[0])); } } bool status; if (isStatic) { //PxToolkit::MemoryOutputStream writeBuffer; status = mCooking->cookTriangleMesh(meshDesc, writeBuffer); //if (!status) // return NULL; } else { PxConvexMeshDesc meshDesc2; /*PxU32 nbVerts = 0; PxVec3 * vertices; PxU32 nbIndices = 0 ; PxU32 * indices; PxU32 nbPolygons = 0; PxHullPolygon * hullPolygons; if (mCooking->computeHullPolygons(meshDesc, gAllocator, nbVerts, vertices, nbIndices, indices, nbPolygons, hullPolygons)) { meshDesc2.points.count = nbVerts; meshDesc2.points.data = vertices; meshDesc2.points.stride = sizeof(PxVec3); meshDesc2.indices.count = nbIndices; meshDesc2.indices.data = indices; meshDesc2.indices.stride = sizeof(PxU32); meshDesc2.polygons.count = nbPolygons; meshDesc2.polygons.data = hullPolygons; meshDesc2.polygons.stride = sizeof(PxHullPolygon); meshDesc2.flags = PxConvexFlag::eINFLATE_CONVEX; } else {*/ meshDesc2.points.count = meshDesc.points.count; meshDesc2.points.stride = meshDesc.points.stride; meshDesc2.points.data = meshDesc.points.data; meshDesc2.flags |= PxConvexFlag::eCOMPUTE_CONVEX | PxConvexFlag::eINFLATE_CONVEX; meshDesc2.vertexLimit = 256; //} /*PxConvexMeshDesc meshDesc; matGroupsIter = matGroups.begin(); for (; matGroupsIter != matGroups.end(); matGroupsIter++) { if ((*matGroupsIter)->getIndexData()->getIndexSize()) { std::shared_ptr<std::vector<unsigned int>> &indexes = (*matGroupsIter)->getIndexData()->getIndexData(); meshDesc.points.count = static_cast<int> (vd->getDataOf(VertexData::GetAttribIndex(std::string("position")))->size()); meshDesc.points.stride = 4 * sizeof(float); meshDesc.points.data = reinterpret_cast<const unsigned char *>(&(vd->getDataOf(VertexData::GetAttribIndex(std::string("position")))->at(0))); meshDesc.flags = PxConvexFlag::eCOMPUTE_CONVEX | PxConvexFlag::eINFLATE_CONVEX; meshDesc.vertexLimit = 256; } }*/ status = mCooking->cookConvexMesh(meshDesc2, writeBuffer); } //PxToolkit::PxInputStream readBuffer(writeBuffer.getData(), writeBuffer.getSize()); PxDefaultMemoryInputData readBuffer(writeBuffer.getData(), writeBuffer.getSize()); return readBuffer; //return gPhysics->createTriangleMesh(readBuffer); }
/** * Attempts to cook a triangle or convex mesh from the provided mesh data. Will log a warning and return false if it is * unable to cook the mesh. If the method returns true the resulting convex mesh will be output in the @p data buffer, * and its size in @p size. The data buffer will be allocated used the generic allocator and is up to the caller to * free it. */ bool cookMesh(const SPtr<MeshData>& meshData, PhysicsMeshType type, UINT8** data, UINT32& size) { if (meshData == nullptr) return false; PxCooking* cooking = gPhysX().getCooking(); if (cooking == nullptr) { LOGWRN("Attempting to cook a physics mesh but cooking is not enabled globally."); return false; } SPtr<VertexDataDesc> vertexDesc = meshData->getVertexDesc(); if (!vertexDesc->hasElement(VES_POSITION)) { LOGWRN("Provided PhysicsMesh mesh data has no vertex positions."); return false; } if (type == PhysicsMeshType::Convex) { if(!cookConvex(cooking, meshData, data, size)) { LOGWRN("Failed cooking a convex mesh. Perpahs it is too complex? Maximum number of convex vertices is 256."); return false; } } else { PxTriangleMeshDesc meshDesc; meshDesc.points.count = meshData->getNumVertices(); meshDesc.points.stride = vertexDesc->getVertexStride(); meshDesc.points.data = meshData->getElementData(VES_POSITION); meshDesc.triangles.count = meshData->getNumIndices() / 3; meshDesc.flags |= PxMeshFlag::eFLIPNORMALS; IndexType indexType = meshData->getIndexType(); if (indexType == IT_32BIT) { meshDesc.triangles.stride = 3 * sizeof(PxU32); meshDesc.triangles.data = meshData->getIndices32(); } else { meshDesc.triangles.stride = 3 * sizeof(PxU16); meshDesc.triangles.data = meshData->getIndices16(); meshDesc.flags |= PxMeshFlag::e16_BIT_INDICES; } PxDefaultMemoryOutputStream output; if (!cooking->cookTriangleMesh(meshDesc, output)) return false; size = output.getSize(); *data = (UINT8*)bs_alloc(size); memcpy(*data, output.getData(), size); } return true; }
/** * Attempts to cook a convex mesh from the provided mesh data. Assumes the mesh data is not null and contains vertex * positions as well as face indices. If the method returns true the resulting convex mesh will be output in the @p * data buffer, and its size in @p size. The data buffer will be allocated used the generic allocator and is up to the * caller to free it. */ bool cookConvex(PxCooking* cooking, const SPtr<MeshData>& meshData, UINT8** data, UINT32& size) { SPtr<VertexDataDesc> vertexDesc = meshData->getVertexDesc(); // Try to create hull from points PxConvexMeshDesc convexDesc; convexDesc.points.count = meshData->getNumVertices(); convexDesc.points.stride = vertexDesc->getVertexStride(); convexDesc.points.data = meshData->getElementData(VES_POSITION); convexDesc.flags |= PxConvexFlag::eCOMPUTE_CONVEX; PxDefaultMemoryOutputStream output; if (cooking->cookConvexMesh(convexDesc, output)) { size = output.getSize(); *data = (UINT8*)bs_alloc(size); memcpy(*data, output.getData(), size); return true; } // Try inflating the convex mesh convexDesc.flags |= PxConvexFlag::eINFLATE_CONVEX; if (cooking->cookConvexMesh(convexDesc, output)) { size = output.getSize(); *data = (UINT8*)bs_alloc(size); memcpy(*data, output.getData(), size); return true; } // Nothing works, just compute an AABB AABox box; auto vertIter = meshData->getVec3DataIter(VES_POSITION); do { box.merge(vertIter.getValue()); } while (vertIter.moveNext()); Vector3 aabbVerts[8]; aabbVerts[0] = box.getCorner(AABox::FAR_LEFT_BOTTOM); aabbVerts[1] = box.getCorner(AABox::FAR_RIGHT_BOTTOM); aabbVerts[2] = box.getCorner(AABox::FAR_RIGHT_TOP); aabbVerts[3] = box.getCorner(AABox::FAR_LEFT_TOP); aabbVerts[4] = box.getCorner(AABox::NEAR_LEFT_BOTTOM); aabbVerts[5] = box.getCorner(AABox::NEAR_RIGHT_BOTTOM); aabbVerts[6] = box.getCorner(AABox::NEAR_RIGHT_TOP); aabbVerts[7] = box.getCorner(AABox::NEAR_LEFT_TOP); convexDesc.points.count = 8; convexDesc.points.stride = sizeof(Vector3); convexDesc.points.data = &aabbVerts[0]; convexDesc.flags &= ~PxConvexFlag::eINFLATE_CONVEX; if (cooking->cookConvexMesh(convexDesc, output)) { size = output.getSize(); *data = (UINT8*)bs_alloc(size); memcpy(*data, output.getData(), size); return true; } return false; }