Path: blob/master/thirdparty/jolt_physics/Jolt/Physics/Collision/Shape/MeshShape.h
9913 views
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)1// SPDX-FileCopyrightText: 2021 Jorrit Rouwe2// SPDX-License-Identifier: MIT34#pragma once56#include <Jolt/Physics/Collision/Shape/Shape.h>7#include <Jolt/Physics/Collision/PhysicsMaterial.h>8#include <Jolt/Core/ByteBuffer.h>9#include <Jolt/Geometry/Triangle.h>10#include <Jolt/Geometry/IndexedTriangle.h>11#ifdef JPH_DEBUG_RENDERER12#include <Jolt/Renderer/DebugRenderer.h>13#endif // JPH_DEBUG_RENDERER1415JPH_NAMESPACE_BEGIN1617class ConvexShape;18class CollideShapeSettings;1920/// Class that constructs a MeshShape21class JPH_EXPORT MeshShapeSettings final : public ShapeSettings22{23JPH_DECLARE_SERIALIZABLE_VIRTUAL(JPH_EXPORT, MeshShapeSettings)2425public:26/// Default constructor for deserialization27MeshShapeSettings() = default;2829/// Create a mesh shape.30MeshShapeSettings(const TriangleList &inTriangles, PhysicsMaterialList inMaterials = PhysicsMaterialList());31MeshShapeSettings(VertexList inVertices, IndexedTriangleList inTriangles, PhysicsMaterialList inMaterials = PhysicsMaterialList());3233/// Sanitize the mesh data. Remove duplicate and degenerate triangles. This is called automatically when constructing the MeshShapeSettings with a list of (indexed-) triangles.34void Sanitize();3536// See: ShapeSettings37virtual ShapeResult Create() const override;3839/// Vertices belonging to mIndexedTriangles40VertexList mTriangleVertices;4142/// Original list of indexed triangles (triangles will be reordered internally in the mesh shape).43/// Triangles must be provided in counter clockwise order.44/// Degenerate triangles will automatically be removed during mesh creation but no other mesh simplifications are performed, use an external library if this is desired.45/// For simulation, the triangles are considered to be single sided.46/// For ray casts you can choose to make triangles double sided by setting RayCastSettings::mBackFaceMode to EBackFaceMode::CollideWithBackFaces.47/// For collide shape tests you can use CollideShapeSettings::mBackFaceMode and for shape casts you can use ShapeCastSettings::mBackFaceModeTriangles.48IndexedTriangleList mIndexedTriangles;4950/// Materials assigned to the triangles. Each triangle specifies which material it uses through its mMaterialIndex51PhysicsMaterialList mMaterials;5253/// Maximum number of triangles in each leaf of the axis aligned box tree. This is a balance between memory and performance. Can be in the range [1, MeshShape::MaxTrianglesPerLeaf].54/// Sensible values are between 4 (for better performance) and 8 (for less memory usage).55uint mMaxTrianglesPerLeaf = 8;5657/// Cosine of the threshold angle (if the angle between the two triangles is bigger than this, the edge is active, note that a concave edge is always inactive).58/// Setting this value too small can cause ghost collisions with edges, setting it too big can cause depenetration artifacts (objects not depenetrating quickly).59/// Valid ranges are between cos(0 degrees) and cos(90 degrees). The default value is cos(5 degrees).60/// Negative values will make all edges active and causes EActiveEdgeMode::CollideOnlyWithActive to behave as EActiveEdgeMode::CollideWithAll.61/// This speeds up the build process but will require all bodies that can interact with the mesh to use BodyCreationSettings::mEnhancedInternalEdgeRemoval = true.62float mActiveEdgeCosThresholdAngle = 0.996195f; // cos(5 degrees)6364/// When true, we store the user data coming from Triangle::mUserData or IndexedTriangle::mUserData in the mesh shape.65/// This can be used to store additional data like the original index of the triangle in the mesh.66/// Can be retrieved using MeshShape::GetTriangleUserData.67/// Turning this on increases the memory used by the MeshShape by roughly 25%.68bool mPerTriangleUserData = false;6970enum class EBuildQuality71{72FavorRuntimePerformance, ///< Favor runtime performance, takes more time to build the MeshShape but performs better73FavorBuildSpeed, ///< Favor build speed, build the tree faster but the MeshShape will be slower74};7576/// Determines the quality of the tree building process.77EBuildQuality mBuildQuality = EBuildQuality::FavorRuntimePerformance;78};7980/// A mesh shape, consisting of triangles. Mesh shapes are mostly used for static geometry.81/// They can be used by dynamic or kinematic objects but only if they don't collide with other mesh or heightfield shapes as those collisions are currently not supported.82/// Note that if you make a mesh shape a dynamic or kinematic object, you need to provide a mass yourself as mesh shapes don't need to form a closed hull so don't have a well defined volume from which the mass can be calculated.83class JPH_EXPORT MeshShape final : public Shape84{85public:86JPH_OVERRIDE_NEW_DELETE8788/// Constructor89MeshShape() : Shape(EShapeType::Mesh, EShapeSubType::Mesh) { }90MeshShape(const MeshShapeSettings &inSettings, ShapeResult &outResult);9192// See Shape::MustBeStatic93virtual bool MustBeStatic() const override { return true; }9495// See Shape::GetLocalBounds96virtual AABox GetLocalBounds() const override;9798// See Shape::GetSubShapeIDBitsRecursive99virtual uint GetSubShapeIDBitsRecursive() const override;100101// See Shape::GetInnerRadius102virtual float GetInnerRadius() const override { return 0.0f; }103104// See Shape::GetMassProperties105virtual MassProperties GetMassProperties() const override;106107// See Shape::GetMaterial108virtual const PhysicsMaterial * GetMaterial(const SubShapeID &inSubShapeID) const override;109110/// Get the list of all materials111const PhysicsMaterialList & GetMaterialList() const { return mMaterials; }112113/// Determine which material index a particular sub shape uses (note that if there are no materials this function will return 0 so check the array size)114/// Note: This could for example be used to create a decorator shape around a mesh shape that overrides the GetMaterial call to replace a material with another material.115uint GetMaterialIndex(const SubShapeID &inSubShapeID) const;116117// See Shape::GetSurfaceNormal118virtual Vec3 GetSurfaceNormal(const SubShapeID &inSubShapeID, Vec3Arg inLocalSurfacePosition) const override;119120// See Shape::GetSupportingFace121virtual void GetSupportingFace(const SubShapeID &inSubShapeID, Vec3Arg inDirection, Vec3Arg inScale, Mat44Arg inCenterOfMassTransform, SupportingFace &outVertices) const override;122123#ifdef JPH_DEBUG_RENDERER124// See Shape::Draw125virtual void Draw(DebugRenderer *inRenderer, RMat44Arg inCenterOfMassTransform, Vec3Arg inScale, ColorArg inColor, bool inUseMaterialColors, bool inDrawWireframe) const override;126#endif // JPH_DEBUG_RENDERER127128// See Shape::CastRay129virtual bool CastRay(const RayCast &inRay, const SubShapeIDCreator &inSubShapeIDCreator, RayCastResult &ioHit) const override;130virtual void CastRay(const RayCast &inRay, const RayCastSettings &inRayCastSettings, const SubShapeIDCreator &inSubShapeIDCreator, CastRayCollector &ioCollector, const ShapeFilter &inShapeFilter = { }) const override;131132/// See: Shape::CollidePoint133/// Note that for CollidePoint to work for a mesh shape, the mesh needs to be closed (a manifold) or multiple non-intersecting manifolds. Triangles may be facing the interior of the manifold.134/// Insideness is tested by counting the amount of triangles encountered when casting an infinite ray from inPoint. If the number of hits is odd we're inside, if it's even we're outside.135virtual void CollidePoint(Vec3Arg inPoint, const SubShapeIDCreator &inSubShapeIDCreator, CollidePointCollector &ioCollector, const ShapeFilter &inShapeFilter = { }) const override;136137// See: Shape::CollideSoftBodyVertices138virtual void CollideSoftBodyVertices(Mat44Arg inCenterOfMassTransform, Vec3Arg inScale, const CollideSoftBodyVertexIterator &inVertices, uint inNumVertices, int inCollidingShapeIndex) const override;139140// See Shape::GetTrianglesStart141virtual void GetTrianglesStart(GetTrianglesContext &ioContext, const AABox &inBox, Vec3Arg inPositionCOM, QuatArg inRotation, Vec3Arg inScale) const override;142143// See Shape::GetTrianglesNext144virtual int GetTrianglesNext(GetTrianglesContext &ioContext, int inMaxTrianglesRequested, Float3 *outTriangleVertices, const PhysicsMaterial **outMaterials = nullptr) const override;145146// See Shape::GetSubmergedVolume147virtual void GetSubmergedVolume(Mat44Arg inCenterOfMassTransform, Vec3Arg inScale, const Plane &inSurface, float &outTotalVolume, float &outSubmergedVolume, Vec3 &outCenterOfBuoyancy JPH_IF_DEBUG_RENDERER(, RVec3Arg inBaseOffset)) const override { JPH_ASSERT(false, "Not supported"); }148149// See Shape150virtual void SaveBinaryState(StreamOut &inStream) const override;151virtual void SaveMaterialState(PhysicsMaterialList &outMaterials) const override;152virtual void RestoreMaterialState(const PhysicsMaterialRefC *inMaterials, uint inNumMaterials) override;153154// See Shape::GetStats155virtual Stats GetStats() const override;156157// See Shape::GetVolume158virtual float GetVolume() const override { return 0; }159160// When MeshShape::mPerTriangleUserData is true, this function can be used to retrieve the user data that was stored in the mesh shape.161uint32 GetTriangleUserData(const SubShapeID &inSubShapeID) const;162163#ifdef JPH_DEBUG_RENDERER164// Settings165static bool sDrawTriangleGroups;166static bool sDrawTriangleOutlines;167#endif // JPH_DEBUG_RENDERER168169// Register shape functions with the registry170static void sRegister();171172protected:173// See: Shape::RestoreBinaryState174virtual void RestoreBinaryState(StreamIn &inStream) override;175176private:177struct MSGetTrianglesContext; ///< Context class for GetTrianglesStart/Next178179static constexpr int NumTriangleBits = 3; ///< How many bits to reserve to encode the triangle index180static constexpr int MaxTrianglesPerLeaf = 1 << NumTriangleBits; ///< Number of triangles that are stored max per leaf aabb node181182/// Find and flag active edges183static void sFindActiveEdges(const MeshShapeSettings &inSettings, IndexedTriangleList &ioIndices);184185/// Visit the entire tree using a visitor pattern186template <class Visitor>187void WalkTree(Visitor &ioVisitor) const;188189/// Same as above but with a callback per triangle instead of per block of triangles190template <class Visitor>191void WalkTreePerTriangle(const SubShapeIDCreator &inSubShapeIDCreator2, Visitor &ioVisitor) const;192193/// Decode a sub shape ID194inline void DecodeSubShapeID(const SubShapeID &inSubShapeID, const void *&outTriangleBlock, uint32 &outTriangleIndex) const;195196// Helper functions called by CollisionDispatch197static void sCollideConvexVsMesh(const Shape *inShape1, const Shape *inShape2, Vec3Arg inScale1, Vec3Arg inScale2, Mat44Arg inCenterOfMassTransform1, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, const CollideShapeSettings &inCollideShapeSettings, CollideShapeCollector &ioCollector, const ShapeFilter &inShapeFilter);198static void sCollideSphereVsMesh(const Shape *inShape1, const Shape *inShape2, Vec3Arg inScale1, Vec3Arg inScale2, Mat44Arg inCenterOfMassTransform1, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, const CollideShapeSettings &inCollideShapeSettings, CollideShapeCollector &ioCollector, const ShapeFilter &inShapeFilter);199static void sCastConvexVsMesh(const ShapeCast &inShapeCast, const ShapeCastSettings &inShapeCastSettings, const Shape *inShape, Vec3Arg inScale, const ShapeFilter &inShapeFilter, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, CastShapeCollector &ioCollector);200static void sCastSphereVsMesh(const ShapeCast &inShapeCast, const ShapeCastSettings &inShapeCastSettings, const Shape *inShape, Vec3Arg inScale, const ShapeFilter &inShapeFilter, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, CastShapeCollector &ioCollector);201202/// Materials assigned to the triangles. Each triangle specifies which material it uses through its mMaterialIndex203PhysicsMaterialList mMaterials;204205ByteBuffer mTree; ///< Resulting packed data structure206207/// 8 bit flags stored per triangle208enum ETriangleFlags209{210/// Material index211FLAGS_MATERIAL_BITS = 5,212FLAGS_MATERIAL_MASK = (1 << FLAGS_MATERIAL_BITS) - 1,213214/// Active edge bits215FLAGS_ACTIVE_EGDE_SHIFT = FLAGS_MATERIAL_BITS,216FLAGS_ACTIVE_EDGE_BITS = 3,217FLAGS_ACTIVE_EDGE_MASK = (1 << FLAGS_ACTIVE_EDGE_BITS) - 1218};219220#ifdef JPH_DEBUG_RENDERER221mutable DebugRenderer::GeometryRef mGeometry; ///< Debug rendering data222mutable bool mCachedTrianglesColoredPerGroup = false; ///< This is used to regenerate the triangle batch if the drawing settings change223mutable bool mCachedUseMaterialColors = false; ///< This is used to regenerate the triangle batch if the drawing settings change224#endif // JPH_DEBUG_RENDERER225};226227JPH_NAMESPACE_END228229230