Add support for generating Collision Data from Skinned Models

This commit is contained in:
Wojtek Figat
2021-03-30 17:58:24 +02:00
parent e01a0585a8
commit a6d488c4ef
8 changed files with 160 additions and 33 deletions

View File

@@ -5,6 +5,7 @@
#include "CollisionCooking.h"
#include "Engine/Threading/Task.h"
#include "Engine/Graphics/Async/GPUTask.h"
#include "Engine/Graphics/Models/MeshBase.h"
#include "Engine/Core/Log.h"
#include "Physics.h"
#include <ThirdParty/PhysX/cooking/PxCooking.h>
@@ -186,14 +187,15 @@ bool CollisionCooking::CookCollision(const Argument& arg, CollisionData::Seriali
}
// Pick a proper model LOD
const int32 lodIndex = Math::Clamp(arg.ModelLodIndex, 0, arg.Model->LODs.Count());
auto lod = &arg.Model->LODs[lodIndex];
const int32 lodIndex = Math::Clamp(arg.ModelLodIndex, 0, arg.Model->GetLODsCount());
Array<MeshBase*> meshes;
arg.Model->GetMeshes(meshes, lodIndex);
// Download model LOD data from the GPU.
// It's easier than reading internal, versioned mesh storage format.
// Also it works with virtual assets that have no dedicated storage.
// Note: request all meshes data at once and wait for the tasks to be done.
const int32 meshesCount = lod->Meshes.Count();
const int32 meshesCount = meshes.Count();
Array<BytesContainer> vertexBuffers;
Array<BytesContainer> indexBuffers;
vertexBuffers.Resize(meshesCount);
@@ -205,9 +207,9 @@ bool CollisionCooking::CookCollision(const Argument& arg, CollisionData::Seriali
Array<Task*> tasks(meshesCount + meshesCount);
for (int32 i = 0; i < meshesCount; i++)
{
const auto& mesh = lod->Meshes[i];
const auto& mesh = *meshes[i];
auto task = mesh.ExtractDataAsync(MeshBufferType::Vertex0, vertexBuffers[i]);
auto task = mesh.DownloadDataGPUAsync(MeshBufferType::Vertex0, vertexBuffers[i]);
if (task == nullptr)
return true;
task->Start();
@@ -216,7 +218,7 @@ bool CollisionCooking::CookCollision(const Argument& arg, CollisionData::Seriali
if (needIndexBuffer)
{
task = mesh.ExtractDataAsync(MeshBufferType::Index, indexBuffers[i]);
task = mesh.DownloadDataGPUAsync(MeshBufferType::Index, indexBuffers[i]);
if (task == nullptr)
return true;
task->Start();
@@ -236,7 +238,7 @@ bool CollisionCooking::CookCollision(const Argument& arg, CollisionData::Seriali
int32 vertexCounter = 0, indexCounter = 0;
for (int32 i = 0; i < meshesCount; i++)
{
const auto& mesh = lod->Meshes[i];
const auto& mesh = *meshes[i];
const auto& vData = vertexBuffers[i];
const int32 firstVertexIndex = vertexCounter;
@@ -251,7 +253,7 @@ bool CollisionCooking::CookCollision(const Argument& arg, CollisionData::Seriali
if (mesh.Use16BitIndexBuffer())
{
auto dst = finalIndexData.Get() + indexCounter;
auto src = (uint16*)iData.Get();
auto src = iData.Get<uint16>();
for (int32 j = 0; j < indexCount; j++)
{
*dst++ = firstVertexIndex + *src++;
@@ -261,7 +263,7 @@ bool CollisionCooking::CookCollision(const Argument& arg, CollisionData::Seriali
else
{
auto dst = finalIndexData.Get() + indexCounter;
auto src = (uint32*)iData.Get();
auto src = iData.Get<uint32>();
for (int32 j = 0; j < indexCount; j++)
{
*dst++ = firstVertexIndex + *src++;

View File

@@ -7,7 +7,7 @@
#include "Engine/Core/Types/DataContainer.h"
#include "Engine/Physics/CollisionData.h"
#include "Engine/Graphics/Models/ModelData.h"
#include "Engine/Content/Assets/Model.h"
#include "Engine/Content/Assets/ModelBase.h"
namespace physx
{
@@ -40,7 +40,7 @@ public:
{
CollisionDataType Type = CollisionDataType::None;
ModelData* OverrideModelData = nullptr;
AssetReference<Model> Model;
AssetReference<ModelBase> Model;
int32 ModelLodIndex = 0;
ConvexMeshGenerationFlags ConvexFlags = ConvexMeshGenerationFlags::None;
int32 ConvexVertexLimit = 255;

View File

@@ -23,7 +23,7 @@ CollisionData::CollisionData(const SpawnParams& params, const AssetInfo* info)
#if COMPILE_WITH_PHYSICS_COOKING
bool CollisionData::CookCollision(CollisionDataType type, Model* modelObj, int32 modelLodIndex, ConvexMeshGenerationFlags convexFlags, int32 convexVertexLimit)
bool CollisionData::CookCollision(CollisionDataType type, ModelBase* modelObj, int32 modelLodIndex, ConvexMeshGenerationFlags convexFlags, int32 convexVertexLimit)
{
// Validate state
if (!IsVirtual())

View File

@@ -4,11 +4,17 @@
#include "Engine/Content/BinaryAsset.h"
#include "Engine/Core/Math/BoundingBox.h"
#include "Engine/Physics/Types.h"
class Model;
class ModelBase;
class ModelData;
namespace physx
{
class PxConvexMesh;
class PxTriangleMesh;
}
/// <summary>
/// A <see cref="CollisionData"/> storage data type.
/// </summary>
@@ -156,8 +162,8 @@ public:
private:
CollisionDataOptions _options;
PxConvexMesh* _convexMesh;
PxTriangleMesh* _triangleMesh;
physx::PxConvexMesh* _convexMesh;
physx::PxTriangleMesh* _triangleMesh;
public:
@@ -173,8 +179,7 @@ public:
/// <summary>
/// Gets the convex mesh object (valid only if asset is loaded and has cooked convex data).
/// </summary>
/// <returns>The convex mesh</returns>
FORCE_INLINE PxConvexMesh* GetConvex() const
FORCE_INLINE physx::PxConvexMesh* GetConvex() const
{
return _convexMesh;
}
@@ -182,8 +187,7 @@ public:
/// <summary>
/// Gets the triangle mesh object (valid only if asset is loaded and has cooked triangle data).
/// </summary>
/// <returns>The triangle mesh</returns>
FORCE_INLINE PxTriangleMesh* GetTriangle() const
FORCE_INLINE physx::PxTriangleMesh* GetTriangle() const
{
return _triangleMesh;
}
@@ -203,7 +207,7 @@ public:
/// <param name="modelLodIndex">The source model LOD index.</param>
/// <param name="convexFlags">The convex mesh generation flags.</param>
/// <param name="convexVertexLimit">The convex mesh vertex limit. Use values in range [8;255]</param>
API_FUNCTION() bool CookCollision(CollisionDataType type, Model* model, int32 modelLodIndex = 0, ConvexMeshGenerationFlags convexFlags = ConvexMeshGenerationFlags::None, int32 convexVertexLimit = 255);
API_FUNCTION() bool CookCollision(CollisionDataType type, ModelBase* model, int32 modelLodIndex = 0, ConvexMeshGenerationFlags convexFlags = ConvexMeshGenerationFlags::None, int32 convexVertexLimit = 255);
/// <summary>
/// Cooks the mesh collision data and updates the virtual asset. action cannot be performed on a main thread.