Add CollisionData.GetModelTriangle to retrieve source geometry triangle index from the raycast hit info

This commit is contained in:
Wojtek Figat
2021-11-05 11:49:10 +01:00
parent 3793630375
commit e0d8a5be5d
4 changed files with 74 additions and 17 deletions

View File

@@ -366,6 +366,7 @@ bool CollisionCooking::CookCollision(const Argument& arg, CollisionData::Seriali
outputOptions.ModelLodIndex = arg.ModelLodIndex;
outputOptions.ConvexFlags = arg.ConvexFlags;
outputOptions.ConvexVertexLimit = arg.ConvexVertexLimit;
outputOptions.MaterialSlotsMask = arg.MaterialSlotsMask;
return false;
}

View File

@@ -133,6 +133,53 @@ bool CollisionData::CookCollision(CollisionDataType type, ModelData* modelData,
#endif
bool CollisionData::GetModelTriangle(uint32 faceIndex, MeshBase*& mesh, uint32& meshTriangleIndex) const
{
mesh = nullptr;
meshTriangleIndex = MAX_uint32;
if (!IsLoaded())
return false;
ScopeLock lock(Locker);
if (_triangleMesh && faceIndex < _triangleMesh->getNbTriangles())
{
if (const PxU32* remap = _triangleMesh->getTrianglesRemap())
{
// Get source triangle index from the triangle mesh
meshTriangleIndex = remap[faceIndex];
// Check if model was used when cooking
AssetReference<ModelBase> model;
model = _options.Model;
if (!model)
return true;
// Follow code-path similar to CollisionCooking.cpp to pick a mesh that contains this triangle (collision is cooked from merged all source meshes from the model)
if (model->WaitForLoaded())
return false;
const int32 lodIndex = Math::Clamp(_options.ModelLodIndex, 0, model->GetLODsCount());
Array<MeshBase*> meshes;
model->GetMeshes(meshes, lodIndex);
uint32 triangleCounter = 0;
for (int32 meshIndex = 0; meshIndex < meshes.Count(); meshIndex++)
{
MeshBase* m = meshes[meshIndex];
if ((_options.MaterialSlotsMask & (1 << m->GetMaterialSlotIndex())) == 0)
continue;
const uint32 count = m->GetTriangleCount();
if (meshTriangleIndex - triangleCounter <= count)
{
mesh = m;
meshTriangleIndex -= triangleCounter;
return true;
}
triangleCounter += count;
}
}
}
return false;
}
void CollisionData::ExtractGeometry(Array<Vector3>& vertexBuffer, Array<int32>& indexBuffer) const
{
vertexBuffer.Clear();
@@ -298,6 +345,7 @@ CollisionData::LoadResult CollisionData::load(const SerializedOptions* options,
_options.ModelLodIndex = options->ModelLodIndex;
_options.ConvexFlags = options->ConvexFlags;
_options.ConvexVertexLimit = options->ConvexVertexLimit < 4 ? 255 : options->ConvexVertexLimit;
_options.MaterialSlotsMask = options->MaterialSlotsMask == 0 ? MAX_uint32 : options->MaterialSlotsMask;
// Load data (rest of the chunk is a cooked collision data)
if (_options.Type == CollisionDataType::None && dataSize > 0)

View File

@@ -8,6 +8,7 @@
class Model;
class ModelBase;
class ModelData;
class MeshBase;
namespace physx
{
@@ -104,42 +105,37 @@ DECLARE_SCRIPTING_TYPE_NO_SPAWN(CollisionDataOptions);
/// <summary>
/// The data type.
/// </summary>
API_FIELD() CollisionDataType Type;
API_FIELD() CollisionDataType Type = CollisionDataType::None;
/// <summary>
/// The source model asset id.
/// </summary>
API_FIELD() Guid Model;
API_FIELD() Guid Model = Guid::Empty;
/// <summary>
/// The source model LOD index.
/// </summary>
API_FIELD() int32 ModelLodIndex;
API_FIELD() int32 ModelLodIndex = 0;
/// <summary>
/// The cooked collision bounds.
/// </summary>
API_FIELD() BoundingBox Box;
API_FIELD() BoundingBox Box = BoundingBox::Zero;
/// <summary>
/// The convex generation flags.
/// </summary>
API_FIELD() ConvexMeshGenerationFlags ConvexFlags;
API_FIELD() ConvexMeshGenerationFlags ConvexFlags = ConvexMeshGenerationFlags::None;
/// <summary>
/// The convex vertices limit (maximum amount).
/// </summary>
API_FIELD() int32 ConvexVertexLimit;
API_FIELD() int32 ConvexVertexLimit = 0;
CollisionDataOptions()
{
Type = CollisionDataType::None;
Model = Guid::Empty;
ModelLodIndex = 0;
Box = BoundingBox::Zero;
ConvexFlags = ConvexMeshGenerationFlags::None;
ConvexVertexLimit = 0;
}
/// <summary>
/// The source model material slots mask. One bit per-slot. Can be used to exclude particular material slots from collision cooking.
/// </summary>
API_FIELD() uint32 MaterialSlotsMask = MAX_uint32;
};
/// <summary>
@@ -160,7 +156,8 @@ public:
int32 ModelLodIndex;
ConvexMeshGenerationFlags ConvexFlags;
int32 ConvexVertexLimit;
byte Padding[96];
uint32 MaterialSlotsMask;
byte Padding[92];
};
static_assert(sizeof(SerializedOptions) == 128, "Invalid collision data options size. Change the padding.");
@@ -259,6 +256,16 @@ public:
#endif
/// <summary>
/// Extracts the triangle index of the original mesh data used for cooking this collision data. Can be used to get vertex attributes of the triangle mesh hit by the raycast.
/// </summary>
/// <remarks>Supported only for collision data built as triangle mesh and without <see cref="ConvexMeshGenerationFlags.SuppressFaceRemapTable"/> flag set.</remarks>
/// <param name="faceIndex">The face index of the collision mesh.</param>
/// <param name="mesh">The result source mesh used to build this collision data (can be null if collision data was cooked using custom geometry without source Model set).</param>
/// <param name="meshTriangleIndex">The result triangle index of the source geometry used to build this collision data.</param>
/// <returns>True if got a valid triangle index, otherwise false.</returns>
API_FUNCTION() bool GetModelTriangle(uint32 faceIndex, API_PARAM(Out) MeshBase*& mesh, API_PARAM(Out) uint32& meshTriangleIndex) const;
/// <summary>
/// Extracts the collision data geometry into list of triangles.
/// </summary>

View File

@@ -23,7 +23,7 @@ DECLARE_SCRIPTING_TYPE_NO_SPAWN(RayCastHit);
/// <summary>
/// The collider that was hit.
/// </summary>
API_FIELD() PhysicsColliderActor* Collider;
API_FIELD() PhysicsColliderActor* Collider = nullptr;
/// <summary>
/// The normal of the surface the ray hit.
@@ -43,6 +43,7 @@ DECLARE_SCRIPTING_TYPE_NO_SPAWN(RayCastHit);
/// <summary>
/// The index of the face that was hit. Valid only for convex mesh (polygon index), triangle mesh (triangle index) and height field (triangle index).
/// </summary>
/// <seealso cref="CollisionData.GetModelTriangle" />
API_FIELD() uint32 FaceIndex;
/// <summary>