virtual bool CookConvex(FName Format, const TArray<FVector>& SrcBuffer, TArray<uint8>& OutBuffer, bool bDeformableMesh = false) const override { #if WITH_PHYSX PxPlatform::Enum PhysXFormat = PxPlatform::ePC; bool bIsPhysXFormatValid = GetPhysXFormat(Format, PhysXFormat); check(bIsPhysXFormatValid); PxConvexMeshDesc PConvexMeshDesc; PConvexMeshDesc.points.data = SrcBuffer.GetData(); PConvexMeshDesc.points.count = SrcBuffer.Num(); PConvexMeshDesc.points.stride = sizeof(FVector); if (bDeformableMesh) { PConvexMeshDesc.flags = PxConvexFlag::eCOMPUTE_CONVEX | PxConvexFlag::eINFLATE_CONVEX; } else { PConvexMeshDesc.flags = PxConvexFlag::eCOMPUTE_CONVEX; } // Set up cooking const PxCookingParams Params = PhysXCooking->getParams(); PxCookingParams NewParams = Params; NewParams.targetPlatform = PhysXFormat; if (bDeformableMesh) { // Meshes which can be deformed need different cooking parameters to inhibit vertex welding and add an extra skin around the collision mesh for safety. // We need to set the meshWeldTolerance to zero, even when disabling 'clean mesh' as PhysX will attempt to perform mesh cleaning anyway according to this meshWeldTolerance // if the convex hull is not well formed. // Set the skin thickness as a proportion of the overall size of the mesh as PhysX's internal tolerances also use the overall size to calculate the epsilon used. const FBox Bounds(SrcBuffer); const float MaxExtent = (Bounds.Max - Bounds.Min).Size(); NewParams.skinWidth = MaxExtent / 512.0f; NewParams.meshPreprocessParams = PxMeshPreprocessingFlags(PxMeshPreprocessingFlag::eDISABLE_CLEAN_MESH); NewParams.areaTestEpsilon = 0.0f; NewParams.meshWeldTolerance = 0.0f; PhysXCooking->setParams(NewParams); } // Cook the convex mesh to a temp buffer TArray<uint8> CookedMeshBuffer; FPhysXOutputStream Buffer(&CookedMeshBuffer); bool Result = PhysXCooking->cookConvexMesh(PConvexMeshDesc, Buffer); // Return default cooking params to normal if (bDeformableMesh) { PhysXCooking->setParams(Params); } if( Result && CookedMeshBuffer.Num() > 0 ) { // Append the cooked data into cooked buffer OutBuffer.Append( CookedMeshBuffer ); return true; } #endif // WITH_PHYSX return false; }
virtual bool CookTriMesh(FName Format, int32 RuntimeCookFlags, const TArray<FVector>& SrcVertices, const TArray<FTriIndices>& SrcIndices, const TArray<uint16>& SrcMaterialIndices, const bool FlipNormals, TArray<uint8>& OutBuffer, bool bDeformableMesh = false) const override { #if WITH_PHYSX PxPlatform::Enum PhysXFormat = PxPlatform::ePC; bool bIsPhysXFormatValid = GetPhysXFormat(Format, PhysXFormat); check(bIsPhysXFormatValid); PxTriangleMeshDesc PTriMeshDesc; PTriMeshDesc.points.data = SrcVertices.GetData(); PTriMeshDesc.points.count = SrcVertices.Num(); PTriMeshDesc.points.stride = sizeof(FVector); PTriMeshDesc.triangles.data = SrcIndices.GetData(); PTriMeshDesc.triangles.count = SrcIndices.Num(); PTriMeshDesc.triangles.stride = sizeof(FTriIndices); PTriMeshDesc.materialIndices.data = SrcMaterialIndices.GetData(); PTriMeshDesc.materialIndices.stride = sizeof(PxMaterialTableIndex); PTriMeshDesc.flags = FlipNormals ? PxMeshFlag::eFLIPNORMALS : (PxMeshFlags)0; // Set up cooking const PxCookingParams& Params = PhysXCooking->getParams(); PxCookingParams NewParams = Params; NewParams.targetPlatform = PhysXFormat; PxMeshPreprocessingFlags OldCookingFlags = NewParams.meshPreprocessParams; if (RuntimeCookFlags & ERuntimePhysxCookOptimizationFlags::SuppressFaceRemapTable) { NewParams.suppressTriangleMeshRemapTable = true; } if (bDeformableMesh) { // In the case of a deformable mesh, we have to change the cook params NewParams.meshPreprocessParams = PxMeshPreprocessingFlag::eDISABLE_CLEAN_MESH; } PhysXCooking->setParams(NewParams); // Cook TriMesh Data FPhysXOutputStream Buffer(&OutBuffer); bool Result = PhysXCooking->cookTriangleMesh(PTriMeshDesc, Buffer); if (bDeformableMesh) //restore old params { NewParams.meshPreprocessParams = OldCookingFlags; PhysXCooking->setParams(NewParams); } return Result; #else return false; #endif // WITH_PHYSX }
virtual bool CookHeightField(FName Format, FIntPoint HFSize, float Thickness, const void* Samples, uint32 SamplesStride, TArray<uint8>& OutBuffer) const override { #if WITH_PHYSX PxPlatform::Enum PhysXFormat = PxPlatform::ePC; bool bIsPhysXFormatValid = GetPhysXFormat(Format, PhysXFormat); check(bIsPhysXFormatValid); PxHeightFieldDesc HFDesc; HFDesc.format = PxHeightFieldFormat::eS16_TM; HFDesc.nbColumns = HFSize.X; HFDesc.nbRows = HFSize.Y; HFDesc.samples.data = Samples; HFDesc.samples.stride = SamplesStride; HFDesc.flags = PxHeightFieldFlag::eNO_BOUNDARY_EDGES; HFDesc.thickness = Thickness; // Set up cooking const PxCookingParams& Params = PhysXCooking->getParams(); PxCookingParams NewParams = Params; NewParams.targetPlatform = PhysXFormat; PhysXCooking->setParams(NewParams); // Cook to a temp buffer TArray<uint8> CookedBuffer; FPhysXOutputStream Buffer(&CookedBuffer); if (PhysXCooking->cookHeightField(HFDesc, Buffer) && CookedBuffer.Num() > 0) { // Append the cooked data into cooked buffer OutBuffer.Append(CookedBuffer); return true; } return false; #else return false; #endif // WITH_PHYSX }
virtual EPhysXCookingResult CookConvex(FName Format, int32 RuntimeCookFlags, const TArray<FVector>& SrcBuffer, TArray<uint8>& OutBuffer, bool bDeformableMesh = false) const override { EPhysXCookingResult CookResult = EPhysXCookingResult::Failed; #if WITH_PHYSX PxPlatform::Enum PhysXFormat = PxPlatform::ePC; bool bIsPhysXFormatValid = GetPhysXFormat(Format, PhysXFormat); check(bIsPhysXFormatValid); PxConvexMeshDesc PConvexMeshDesc; PConvexMeshDesc.points.data = SrcBuffer.GetData(); PConvexMeshDesc.points.count = SrcBuffer.Num(); PConvexMeshDesc.points.stride = sizeof(FVector); PConvexMeshDesc.flags = PxConvexFlag::eCOMPUTE_CONVEX; // Set up cooking const PxCookingParams Params = PhysXCooking->getParams(); PxCookingParams NewParams = Params; NewParams.targetPlatform = PhysXFormat; if(RuntimeCookFlags & ERuntimePhysxCookOptimizationFlags::SuppressFaceRemapTable) { NewParams.suppressTriangleMeshRemapTable = true; } if (bDeformableMesh) { // Meshes which can be deformed need different cooking parameters to inhibit vertex welding and add an extra skin around the collision mesh for safety. // We need to set the meshWeldTolerance to zero, even when disabling 'clean mesh' as PhysX will attempt to perform mesh cleaning anyway according to this meshWeldTolerance // if the convex hull is not well formed. // Set the skin thickness as a proportion of the overall size of the mesh as PhysX's internal tolerances also use the overall size to calculate the epsilon used. const FBox Bounds(SrcBuffer); const float MaxExtent = (Bounds.Max - Bounds.Min).Size(); NewParams.meshPreprocessParams = PxMeshPreprocessingFlags(PxMeshPreprocessingFlag::eDISABLE_CLEAN_MESH); NewParams.meshWeldTolerance = 0.0f; } PhysXCooking->setParams(NewParams); // Cook the convex mesh to a temp buffer TArray<uint8> CookedMeshBuffer; FPhysXOutputStream Buffer(&CookedMeshBuffer); if (PhysXCooking->cookConvexMesh(PConvexMeshDesc, Buffer)) { CookResult = EPhysXCookingResult::Succeeded; } else { if (!(PConvexMeshDesc.flags & PxConvexFlag::eINFLATE_CONVEX)) { // We failed to cook without inflating convex. Let's try again with inflation //This is not ideal since it makes the collision less accurate. It's needed if given verts are extremely close. PConvexMeshDesc.flags |= PxConvexFlag::eINFLATE_CONVEX; if (PhysXCooking->cookConvexMesh(PConvexMeshDesc, Buffer)) { CookResult = EPhysXCookingResult::SucceededWithInflation; } } } // Return default cooking params to normal if (bDeformableMesh) { PhysXCooking->setParams(Params); } if (CookedMeshBuffer.Num() == 0) { CookResult = EPhysXCookingResult::Failed; } if (CookResult != EPhysXCookingResult::Failed) { // Append the cooked data into cooked buffer OutBuffer.Append( CookedMeshBuffer ); } #endif // WITH_PHYSX return CookResult; }