Files
UnrealEngine/Engine/Plugins/Runtime/GeometryProcessing/Source/DynamicMesh/Public/ShapeApproximation/SimpleShapeSet3.h
2025-05-18 13:04:45 +08:00

225 lines
5.3 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "OrientedBoxTypes.h"
#include "SegmentTypes.h"
#include "CapsuleTypes.h"
#include "SphereTypes.h"
#include "DynamicMesh/DynamicMesh3.h"
#include "Spatial/DenseGrid3.h"
#include "TransformTypes.h"
#include "TransformSequence.h"
#define UE_API DYNAMICMESH_API
namespace UE {
namespace Geometry {
/**
* Supported/known types of Simple Shapes
*/
enum class ESimpleShapeType
{
Sphere = 2,
Box = 4,
Capsule = 8,
Convex = 16,
LevelSet = 32
};
ENUM_CLASS_FLAGS(ESimpleShapeType);
/**
* FSphereShape is a 3D sphere
*/
class FSphereShape3d
{
public:
FSphere3d Sphere;
FSphereShape3d() = default;
FSphereShape3d(const FSphere3d& SphereIn)
: Sphere(SphereIn)
{
}
ESimpleShapeType GetShapeType() const { return ESimpleShapeType::Sphere; }
};
/**
* FBoxShape is a 3D oriented box
*/
struct FBoxShape3d
{
FOrientedBox3d Box;
FBoxShape3d() = default;
FBoxShape3d(const FOrientedBox3d& BoxIn)
: Box(BoxIn)
{
}
ESimpleShapeType GetShapeType() const { return ESimpleShapeType::Box; }
};
/**
* FCapsuleShape is a 3D oriented capsule/sphyl
*/
struct FCapsuleShape3d
{
FCapsule3d Capsule;
FCapsuleShape3d() = default;
FCapsuleShape3d(const FCapsule3d& CapsuleIn)
: Capsule(CapsuleIn)
{
}
ESimpleShapeType GetShapeType() const { return ESimpleShapeType::Capsule; }
};
/**
* FConvexShape is a 3D convex hull, currently stored as a triangle mesh
*/
struct FConvexShape3d
{
FDynamicMesh3 Mesh;
FConvexShape3d() = default;
FConvexShape3d(const FDynamicMesh3& MeshIn)
: Mesh(MeshIn)
{
}
FConvexShape3d(FDynamicMesh3&& MeshIn)
: Mesh(MoveTemp(MeshIn))
{
}
ESimpleShapeType GetShapeType() const { return ESimpleShapeType::Convex; }
};
/**
* FLevelSetShape is a 3D signed distance function sampled on a regular grid
*/
struct FLevelSetShape3d
{
FTransform3d GridTransform;
FDenseGrid3f Grid;
float CellSize;
FLevelSetShape3d() = default;
FLevelSetShape3d(const FTransform3d& GridTransform, const FDenseGrid3f& Grid, float CellSize) :
GridTransform(GridTransform),
Grid(Grid),
CellSize(CellSize)
{
}
FLevelSetShape3d(FTransform3d&& GridTransform, FDenseGrid3f&& Grid, float CellSize) :
GridTransform(MoveTemp(GridTransform)),
Grid(MoveTemp(Grid)),
CellSize(CellSize)
{
}
ESimpleShapeType GetShapeType() const { return ESimpleShapeType::LevelSet; }
FOrientedBox3d GetGridBox() const
{
const UE::Geometry::FVector3i& Dims = Grid.GetDimensions();
const FVector3d BoxExtents = (0.5 * CellSize) * FVector3d(Dims[0], Dims[1], Dims[2]);
const FFrame3d BoxFrame(GridTransform.GetTranslation(), GridTransform.GetRotation());
return FOrientedBox3d(BoxFrame, BoxExtents);
}
};
/**
* FSimpleShapeSet stores a set of simple geometry shapes useful for things like collision detection/etc.
* Various functions set-processing operations are supported.
*/
struct FSimpleShapeSet3d
{
TArray<FSphereShape3d> Spheres;
TArray<FBoxShape3d> Boxes;
TArray<UE::Geometry::FCapsuleShape3d> Capsules;
TArray<FConvexShape3d> Convexes;
TArray<FLevelSetShape3d> LevelSets;
/** @return total number of elements in all sets */
int32 TotalElementsNum() const { return Spheres.Num() + Boxes.Num() + Capsules.Num() + Convexes.Num() + LevelSets.Num(); }
/**
* Append elements of another shape set
*/
UE_API void Append(const FSimpleShapeSet3d& OtherShapeSet);
/**
* Append elements of another shape set with given transform applied
*/
UE_API void Append(const FSimpleShapeSet3d& OtherShapeSet, const FTransform3d& Transform);
/**
* Append elements of another shape set with given transforms applied
*/
UE_API void Append(const FSimpleShapeSet3d& OtherShapeSet, const TArray<FTransform3d>& TransformSequence);
/**
* Append elements of another shape set with given transforms applied
*/
UE_API void Append(const FSimpleShapeSet3d& OtherShapeSet, const FTransformSequence3d& TransformSequence);
/**
* Remove any of the elements that are fully contained in larger elements
*/
UE_API void RemoveContainedGeometry();
/**
* Sort the elements by volume and then discard all but the largest MaximumCount elements
*/
UE_API void FilterByVolume(int32 MaximumCount);
struct FMergeShapesSettings
{
/** Whether to use the negative space protection settings when merging collision shapes */
bool bMergeShapesProtectNegativeSpace = false;
/** Negative space closer to the input than this tolerance distance can be filled in */
double NegativeSpaceTolerance = 3;
/** Minimum radius of negative space to protect; tunnels with radius smaller than this could be filled in */
double NegativeSpaceMinRadius = 10;
/** Whether to ignore negative space that is not accessible by traversing from the convex hull (via paths w/ radius of at least Negative Space Tolerance) */
bool bIgnoreInternalNegativeSpace = true;
};
// Attempt to reduce the number of simple collision shapes by merging neighboring shapes, while still optionally protecting negative space
UE_API bool MergeShapes(int32 MergeAboveCount, const FMergeShapesSettings& MergeSettings);
/**
* Transform shape elements. This will be a best-effort as if there is non-uniform scaling only Convexes can be transformed correctly
*/
UE_API void ApplyTransform(const FTransform3d& Transform);
};
} // end namespace UE::Geometry
} // end namespace UE
#undef UE_API