Example #1
0
FByteBulkData* UBodySetup::GetCookedData(FName Format)
{
	if (IsTemplate())
	{
		return NULL;
	}

	IInterface_CollisionDataProvider* CDP = Cast<IInterface_CollisionDataProvider>(GetOuter());

	// If there is nothing to cook or if we are reading data from a cooked package for an asset with no collision, 
	// we want to return here
	if ((AggGeom.ConvexElems.Num() == 0 && CDP == NULL) || !bHasCookedCollisionData)
	{
		return NULL;
	}

	FFormatContainer* UseCookedData = CookedFormatDataOverride ? CookedFormatDataOverride : &CookedFormatData;

	bool bContainedData = UseCookedData->Contains(Format);
	FByteBulkData* Result = &UseCookedData->GetFormat(Format);
#if WITH_PHYSX
	if (!bContainedData)
	{
		if (FPlatformProperties::RequiresCookedData())
		{
			UE_LOG(LogPhysics, Error, TEXT("Attempt to build physics data for %s when we are unable to. This platform requires cooked packages."), *GetPathName());
		}

		if (AggGeom.ConvexElems.Num() == 0 && (CDP == NULL || CDP->ContainsPhysicsTriMeshData(bMeshCollideAll) == false))
		{
			return NULL;
		}

#if WITH_RUNTIME_PHYSICS_COOKING || WITH_EDITOR
		TArray<uint8> OutData;
		FDerivedDataPhysXCooker* DerivedPhysXData = new FDerivedDataPhysXCooker(Format, this);
		if (DerivedPhysXData->CanBuild())
		{
		#if WITH_EDITOR
			GetDerivedDataCacheRef().GetSynchronous(DerivedPhysXData, OutData);
		#elif WITH_RUNTIME_PHYSICS_COOKING
			DerivedPhysXData->Build(OutData);
		#endif
			if (OutData.Num())
			{
				Result->Lock(LOCK_READ_WRITE);
				FMemory::Memcpy(Result->Realloc(OutData.Num()), OutData.GetData(), OutData.Num());
				Result->Unlock();
			}
		}
		else
#endif
		{
			UE_LOG(LogPhysics, Warning, TEXT("Attempt to build physics data for %s when we are unable to."), *GetPathName());
		}
	}
#endif // WITH_PHYSX
	check(Result);
	return Result->GetBulkDataSize() > 0 ? Result : NULL; // we don't return empty bulk data...but we save it to avoid thrashing the DDC
}
Example #2
0
bool FDerivedDataPhysXCooker::ShouldGenerateTriMeshData(bool InUseAllTriData)
{
	check(Cooker != NULL);

	IInterface_CollisionDataProvider* CDP = Cast<IInterface_CollisionDataProvider>(CollisionDataProvider);
	const bool bPerformCook = ( CDP != NULL ) ? CDP->ContainsPhysicsTriMeshData(InUseAllTriData) : false;
	return bPerformCook;
}
Example #3
0
bool FDerivedDataPhysXCooker::BuildTriMesh( TArray<uint8>& OutData, bool bInMirrored, bool InUseAllTriData )
{
	check(Cooker != NULL);

	bool bResult = false;
	FTriMeshCollisionData TriangleMeshDesc;
	IInterface_CollisionDataProvider* CDP = Cast<IInterface_CollisionDataProvider>(CollisionDataProvider);
	check(CDP != NULL); // It's all been checked before getting into this function
		
	bool bHaveTriMeshData = CDP->GetPhysicsTriMeshData(&TriangleMeshDesc, InUseAllTriData);
	if(bHaveTriMeshData)
	{
		// If any of the below checks gets hit this usually means 
		// IInterface_CollisionDataProvider::ContainsPhysicsTriMeshData did not work properly.
		const int32 NumIndices = TriangleMeshDesc.Indices.Num();
		const int32 NumVerts = TriangleMeshDesc.Vertices.Num();
		if(NumIndices == 0 || NumVerts == 0 || TriangleMeshDesc.MaterialIndices.Num() > NumIndices)
		{
			UE_LOG(LogPhysics, Warning, TEXT("FDerivedDataPhysXCooker::BuildTriMesh: Triangle data from '%s' invalid (%d verts, %d indices)."), *CollisionDataProvider->GetPathName(), NumVerts, NumIndices );
			return bResult;
		}

		TArray<FVector>* MeshVertices = NULL;
		TArray<FVector> MirroredVerts;

		if( bInMirrored )
		{
			MirroredVerts.AddUninitialized(NumVerts);
			for(int32 VertIdx=0; VertIdx<NumVerts; VertIdx++)
			{
				MirroredVerts[VertIdx] = TriangleMeshDesc.Vertices[VertIdx] * FVector(-1,1,1);
			}
			MeshVertices = &MirroredVerts;
		}
		else
		{
			MeshVertices = &TriangleMeshDesc.Vertices;
		}

		UE_LOG(LogPhysics, Log, TEXT("Cook TriMesh: %s (FlipX: %d)"), *CollisionDataProvider->GetPathName(), bInMirrored);
		bool bPerPolySkeletalMesh = false;
		if (USkeletalMesh* SkeletalMesh = Cast<USkeletalMesh>(CollisionDataProvider))
		{
			ensure(SkeletalMesh->bEnablePerPolyCollision);
			bPerPolySkeletalMesh = true;
		}
		bResult = Cooker->CookTriMesh( Format, *MeshVertices, TriangleMeshDesc.Indices, TriangleMeshDesc.MaterialIndices, bInMirrored ? !TriangleMeshDesc.bFlipNormals : TriangleMeshDesc.bFlipNormals, OutData, bPerPolySkeletalMesh );
		if( !bResult )
		{
			UE_LOG(LogPhysics, Warning, TEXT("Failed to cook TriMesh: %s (FlipX:%d)."), *CollisionDataProvider->GetPathName(), bInMirrored );
		}
	}

	return bResult;
}
Example #4
0
FDerivedDataNavCollisionCooker::FDerivedDataNavCollisionCooker(FName InFormat, UNavCollision* InInstance)
	: NavCollisionInstance(InInstance)
	, CollisionDataProvider( NULL )
	, Format( InFormat )
{
	check(NavCollisionInstance != NULL);
	CollisionDataProvider = NavCollisionInstance->GetOuter();
	DataGuid = NavCollisionInstance->GetGuid();
	IInterface_CollisionDataProvider* CDP = Cast<IInterface_CollisionDataProvider>(CollisionDataProvider);
	if (CDP)
	{
		CDP->GetMeshId(MeshId);
	}
}
Example #5
0
FDerivedDataPhysXCooker::FDerivedDataPhysXCooker( FName InFormat, UBodySetup* InBodySetup )
	: BodySetup( InBodySetup )
	, CollisionDataProvider( NULL )
	, Format( InFormat )
	, Cooker( NULL )
{
	check( BodySetup != NULL );
	CollisionDataProvider = BodySetup->GetOuter();
	DataGuid = BodySetup->BodySetupGuid;
	bGenerateNormalMesh = BodySetup->bGenerateNonMirroredCollision;
	bGenerateMirroredMesh = BodySetup->bGenerateMirroredCollision;
	IInterface_CollisionDataProvider* CDP = Cast<IInterface_CollisionDataProvider>(CollisionDataProvider);
	if (CDP)
	{
		CDP->GetMeshId(MeshId);
	}
	InitCooker();
}
int32 FDerivedDataPhysXCooker::BuildTriMesh( TArray<uint8>& OutData, bool InUseAllTriData )
{
	check(Cooker != NULL);

	bool bResult = false;
	FTriMeshCollisionData TriangleMeshDesc;
	IInterface_CollisionDataProvider* CDP = Cast<IInterface_CollisionDataProvider>(CollisionDataProvider);
	check(CDP != NULL); // It's all been checked before getting into this function
		
	bool bHaveTriMeshData = CDP->GetPhysicsTriMeshData(&TriangleMeshDesc, InUseAllTriData);
	if(bHaveTriMeshData)
	{
		// If any of the below checks gets hit this usually means 
		// IInterface_CollisionDataProvider::ContainsPhysicsTriMeshData did not work properly.
		const int32 NumIndices = TriangleMeshDesc.Indices.Num();
		const int32 NumVerts = TriangleMeshDesc.Vertices.Num();
		if(NumIndices == 0 || NumVerts == 0 || TriangleMeshDesc.MaterialIndices.Num() > NumIndices)
		{
			UE_LOG(LogPhysics, Warning, TEXT("FDerivedDataPhysXCooker::BuildTriMesh: Triangle data from '%s' invalid (%d verts, %d indices)."), *CollisionDataProvider->GetPathName(), NumVerts, NumIndices );
			return bResult;
		}

		TArray<FVector>* MeshVertices = NULL;
		MeshVertices = &TriangleMeshDesc.Vertices;
		
		UE_LOG(LogPhysics, Log, TEXT("Cook TriMesh: %s"), *CollisionDataProvider->GetPathName());
		bool bDeformableMesh = CollisionDataProvider->IsA(USplineMeshComponent::StaticClass());
		if (USkeletalMesh* SkeletalMesh = Cast<USkeletalMesh>(CollisionDataProvider))
		{
			ensure(SkeletalMesh->bEnablePerPolyCollision);
			bDeformableMesh = true;
		}
		bResult = Cooker->CookTriMesh( Format, RuntimeCookFlags, *MeshVertices, TriangleMeshDesc.Indices, TriangleMeshDesc.MaterialIndices, TriangleMeshDesc.bFlipNormals, OutData, bDeformableMesh );
		if( !bResult )
		{
			UE_LOG(LogPhysics, Warning, TEXT("Failed to cook TriMesh: %s."), *CollisionDataProvider->GetPathName());
		}
	}

	return bResult == true ? 1 : 0;	//the cooker only generates 1 or 0 trimeshes. We return an int because we support multiple trimeshes for welding and we might want to do this per static mesh in the future.
}
Example #7
0
bool FDerivedDataPhysXCooker::ShouldGenerateNegXTriMeshData()
{
	IInterface_CollisionDataProvider* CDP = Cast<IInterface_CollisionDataProvider>(CollisionDataProvider);
	const bool bWantsNegX = ( CDP != NULL ) ? CDP->WantsNegXTriMesh() : false;
	return bWantsNegX;
}