Files
UnrealEngineUWP/Engine/Source/Developer/PhysXFormats/Private/PhysXFormats.cpp
Ori Cohen 0b8fd4467c Disable PhysX cleaning of mesh for per poly skeletal mesh case.
[CL 2107509 by Ori Cohen in Main branch]
2014-06-16 18:02:40 -04:00

256 lines
6.7 KiB
C++

// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved.
#include "Core.h"
#include "ModuleInterface.h"
#include "ModuleManager.h"
#include "Engine.h"
#include "PhysicsPublic.h"
#include "TargetPlatform.h"
#include "PhysXFormats.h"
static_assert(WITH_PHYSX, "No point in compiling PhysX cooker, if we don't have PhysX.");
static FName NAME_PhysXPC(TEXT("PhysXPC"));
static FName NAME_PhysXXboxOne(TEXT("PhysXXboxOne"));
static FName NAME_PhysXPS4(TEXT("PhysXPS4"));
/**
* FPhysXFormats. Cooks physics data.
**/
class FPhysXFormats : public IPhysXFormat
{
enum
{
/** Version for PhysX format, this becomes part of the DDC key. */
UE_PHYSX_PC_VER = 0,
};
PxCooking* PhysXCooking;
/**
* Validates format name and returns its PhysX enum value.
*
* @param InFormatName PhysX format name.
* @param OutFormat PhysX enum
* @return true if InFormatName is a valid and supported PhysX format
*/
bool GetPhysXFormat(FName InFormatName, PxPlatform::Enum& OutFormat) const
{
if ((InFormatName == NAME_PhysXPC) || (InFormatName == NAME_PhysXXboxOne) || (InFormatName == NAME_PhysXPS4))
{
OutFormat = PxPlatform::ePC;
}
else
{
return false;
}
return true;
}
/**
* Valudates PhysX format name.
*/
bool CheckPhysXFormat(FName InFormatName) const
{
PxPlatform::Enum PhysXFormat = PxPlatform::ePC;
return GetPhysXFormat(InFormatName, PhysXFormat);
}
public:
FPhysXFormats( PxCooking* InCooking )
: PhysXCooking( InCooking )
{}
virtual bool AllowParallelBuild() const
{
return false;
}
virtual uint16 GetVersion(FName Format) const override
{
check(CheckPhysXFormat(Format));
return UE_PHYSX_PC_VER;
}
virtual void GetSupportedFormats(TArray<FName>& OutFormats) const
{
OutFormats.Add(NAME_PhysXPC);
OutFormats.Add(NAME_PhysXXboxOne);
OutFormats.Add(NAME_PhysXPS4);
}
virtual bool CookConvex(FName Format, const TArray<FVector>& SrcBuffer, TArray<uint8>& OutBuffer) 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);
PConvexMeshDesc.flags = PxConvexFlag::eCOMPUTE_CONVEX;
// Set up cooking
const PxCookingParams& Params = PhysXCooking->getParams();
PxCookingParams NewParams = Params;
NewParams.targetPlatform = PhysXFormat;
PhysXCooking->setParams(NewParams);
// Cook the convex mesh to a temp buffer
TArray<uint8> CookedMeshBuffer;
FPhysXOutputStream Buffer(&CookedMeshBuffer);
bool Result = PhysXCooking->cookConvexMesh(PConvexMeshDesc, Buffer);
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, const TArray<FVector>& SrcVertices, const TArray<FTriIndices>& SrcIndices, const TArray<uint16>& SrcMaterialIndices, const bool FlipNormals, TArray<uint8>& OutBuffer, bool bPerPolySkeletalMesh = 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 (bPerPolySkeletalMesh)
{
//per poly skeletal mesh requires deforming mesh. This is a very special case so 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 (bPerPolySkeletalMesh) //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
}
};
/**
* Module for PhysX cooking
*/
static IPhysXFormat* Singleton = NULL;
class FPhysXPlatformModule : public IPhysXFormatModule
{
public:
FPhysXPlatformModule()
{
}
virtual ~FPhysXPlatformModule()
{
ShutdownPhysXCooking();
delete Singleton;
Singleton = NULL;
}
virtual IPhysXFormat* GetPhysXFormat()
{
if (!Singleton)
{
InitPhysXCooking();
Singleton = new FPhysXFormats(GPhysXCooking);
}
return Singleton;
}
private:
/**
* Load the required modules for PhysX
*/
void InitPhysXCooking()
{
// Make sure PhysX libs are loaded
LoadPhysXModules();
}
void ShutdownPhysXCooking()
{
// Ideally PhysX cooking should be initialized in InitPhysXCooking and released here
// but Apex is still being setup in the engine and it also requires PhysX cooking singleton.
}
};
IMPLEMENT_MODULE( FPhysXPlatformModule, PhysXFormats );