Path: blob/master/thirdparty/jolt_physics/Jolt/Physics/SoftBody/SoftBodyShape.cpp
21350 views
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)1// SPDX-FileCopyrightText: 2023 Jorrit Rouwe2// SPDX-License-Identifier: MIT34#include <Jolt/Jolt.h>56#include <Jolt/Physics/SoftBody/SoftBodyShape.h>7#include <Jolt/Core/Profiler.h>8#include <Jolt/Geometry/RayTriangle.h>9#include <Jolt/Physics/Collision/RayCast.h>10#include <Jolt/Physics/Collision/CastResult.h>11#include <Jolt/Physics/Collision/TransformedShape.h>12#include <Jolt/Physics/SoftBody/SoftBodyMotionProperties.h>13#include <Jolt/Physics/Collision/CastConvexVsTriangles.h>14#include <Jolt/Physics/Collision/CastSphereVsTriangles.h>15#include <Jolt/Physics/Collision/CollideConvexVsTriangles.h>16#include <Jolt/Physics/Collision/CollideSphereVsTriangles.h>17#include <Jolt/Physics/Collision/CollisionDispatch.h>18#ifdef JPH_DEBUG_RENDERER19#include <Jolt/Renderer/DebugRenderer.h>20#endif // JPH_DEBUG_RENDERER2122JPH_NAMESPACE_BEGIN2324uint SoftBodyShape::GetSubShapeIDBits() const25{26// Ensure we have enough bits to encode our shape [0, n - 1]27uint32 n = (uint32)mSoftBodyMotionProperties->GetFaces().size() - 1;28return 32 - CountLeadingZeros(n);29}3031uint32 SoftBodyShape::GetFaceIndex(const SubShapeID &inSubShapeID) const32{33SubShapeID remainder;34uint32 face_index = inSubShapeID.PopID(GetSubShapeIDBits(), remainder);35JPH_ASSERT(remainder.IsEmpty());36return face_index;37}3839AABox SoftBodyShape::GetLocalBounds() const40{41return mSoftBodyMotionProperties->GetLocalBounds();42}4344bool SoftBodyShape::CastRay(const RayCast &inRay, const SubShapeIDCreator &inSubShapeIDCreator, RayCastResult &ioHit) const45{46JPH_PROFILE_FUNCTION();4748uint num_triangle_bits = GetSubShapeIDBits();49uint triangle_idx = uint(-1);5051const Array<SoftBodyVertex> &vertices = mSoftBodyMotionProperties->GetVertices();52for (const SoftBodyMotionProperties::Face &f : mSoftBodyMotionProperties->GetFaces())53{54Vec3 x1 = vertices[f.mVertex[0]].mPosition;55Vec3 x2 = vertices[f.mVertex[1]].mPosition;56Vec3 x3 = vertices[f.mVertex[2]].mPosition;5758float fraction = RayTriangle(inRay.mOrigin, inRay.mDirection, x1, x2, x3);59if (fraction < ioHit.mFraction)60{61// Store fraction62ioHit.mFraction = fraction;6364// Store triangle index65triangle_idx = uint(&f - mSoftBodyMotionProperties->GetFaces().data());66}67}6869if (triangle_idx == uint(-1))70return false;7172ioHit.mSubShapeID2 = inSubShapeIDCreator.PushID(triangle_idx, num_triangle_bits).GetID();73return true;74}7576void SoftBodyShape::CastRay(const RayCast &inRay, const RayCastSettings &inRayCastSettings, const SubShapeIDCreator &inSubShapeIDCreator, CastRayCollector &ioCollector, const ShapeFilter &inShapeFilter) const77{78JPH_PROFILE_FUNCTION();7980// Test shape filter81if (!inShapeFilter.ShouldCollide(this, inSubShapeIDCreator.GetID()))82return;8384uint num_triangle_bits = GetSubShapeIDBits();85bool check_backfaces = inRayCastSettings.mBackFaceModeTriangles == EBackFaceMode::IgnoreBackFaces && !mSoftBodyMotionProperties->GetFacesDoubleSided();8687const Array<SoftBodyVertex> &vertices = mSoftBodyMotionProperties->GetVertices();88for (const SoftBodyMotionProperties::Face &f : mSoftBodyMotionProperties->GetFaces())89{90Vec3 x1 = vertices[f.mVertex[0]].mPosition;91Vec3 x2 = vertices[f.mVertex[1]].mPosition;92Vec3 x3 = vertices[f.mVertex[2]].mPosition;9394// Back facing check95if (check_backfaces && (x2 - x1).Cross(x3 - x1).Dot(inRay.mDirection) > 0.0f)96continue;9798// Test ray against triangle99float fraction = RayTriangle(inRay.mOrigin, inRay.mDirection, x1, x2, x3);100if (fraction < ioCollector.GetEarlyOutFraction())101{102// Better hit than the current hit103RayCastResult hit;104hit.mBodyID = TransformedShape::sGetBodyID(ioCollector.GetContext());105hit.mFraction = fraction;106hit.mSubShapeID2 = inSubShapeIDCreator.PushID(uint(&f - mSoftBodyMotionProperties->GetFaces().data()), num_triangle_bits).GetID();107ioCollector.AddHit(hit);108}109}110}111112void SoftBodyShape::CollidePoint(Vec3Arg inPoint, const SubShapeIDCreator &inSubShapeIDCreator, CollidePointCollector &ioCollector, const ShapeFilter &inShapeFilter) const113{114sCollidePointUsingRayCast(*this, inPoint, inSubShapeIDCreator, ioCollector, inShapeFilter);115}116117void SoftBodyShape::CollideSoftBodyVertices(Mat44Arg inCenterOfMassTransform, Vec3Arg inScale, const CollideSoftBodyVertexIterator &inVertices, uint inNumVertices, int inCollidingShapeIndex) const118{119/* Not implemented */120}121122const PhysicsMaterial *SoftBodyShape::GetMaterial(const SubShapeID &inSubShapeID) const123{124SubShapeID remainder;125uint triangle_idx = inSubShapeID.PopID(GetSubShapeIDBits(), remainder);126JPH_ASSERT(remainder.IsEmpty());127128const SoftBodyMotionProperties::Face &f = mSoftBodyMotionProperties->GetFace(triangle_idx);129return mSoftBodyMotionProperties->GetMaterials()[f.mMaterialIndex];130}131132Vec3 SoftBodyShape::GetSurfaceNormal(const SubShapeID &inSubShapeID, Vec3Arg inLocalSurfacePosition) const133{134SubShapeID remainder;135uint triangle_idx = inSubShapeID.PopID(GetSubShapeIDBits(), remainder);136JPH_ASSERT(remainder.IsEmpty());137138const SoftBodyMotionProperties::Face &f = mSoftBodyMotionProperties->GetFace(triangle_idx);139const Array<SoftBodyVertex> &vertices = mSoftBodyMotionProperties->GetVertices();140141Vec3 x1 = vertices[f.mVertex[0]].mPosition;142Vec3 x2 = vertices[f.mVertex[1]].mPosition;143Vec3 x3 = vertices[f.mVertex[2]].mPosition;144145return (x2 - x1).Cross(x3 - x1).NormalizedOr(Vec3::sAxisY());146}147148void SoftBodyShape::GetSupportingFace(const SubShapeID &inSubShapeID, Vec3Arg inDirection, Vec3Arg inScale, Mat44Arg inCenterOfMassTransform, SupportingFace &outVertices) const149{150SubShapeID remainder;151uint triangle_idx = inSubShapeID.PopID(GetSubShapeIDBits(), remainder);152JPH_ASSERT(remainder.IsEmpty());153154const SoftBodyMotionProperties::Face &f = mSoftBodyMotionProperties->GetFace(triangle_idx);155const Array<SoftBodyVertex> &vertices = mSoftBodyMotionProperties->GetVertices();156157for (uint32 i : f.mVertex)158outVertices.push_back(inCenterOfMassTransform * (inScale * vertices[i].mPosition));159}160161void SoftBodyShape::GetSubmergedVolume(Mat44Arg inCenterOfMassTransform, Vec3Arg inScale, const Plane &inSurface, float &outTotalVolume, float &outSubmergedVolume, Vec3 &outCenterOfBuoyancy JPH_IF_DEBUG_RENDERER(, RVec3Arg inBaseOffset)) const162{163outSubmergedVolume = 0.0f;164outTotalVolume = mSoftBodyMotionProperties->GetVolume();165outCenterOfBuoyancy = Vec3::sZero();166}167168#ifdef JPH_DEBUG_RENDERER169170void SoftBodyShape::Draw(DebugRenderer *inRenderer, RMat44Arg inCenterOfMassTransform, Vec3Arg inScale, ColorArg inColor, bool inUseMaterialColors, bool inDrawWireframe) const171{172const Array<SoftBodyVertex> &vertices = mSoftBodyMotionProperties->GetVertices();173for (const SoftBodyMotionProperties::Face &f : mSoftBodyMotionProperties->GetFaces())174{175RVec3 x1 = inCenterOfMassTransform * vertices[f.mVertex[0]].mPosition;176RVec3 x2 = inCenterOfMassTransform * vertices[f.mVertex[1]].mPosition;177RVec3 x3 = inCenterOfMassTransform * vertices[f.mVertex[2]].mPosition;178179inRenderer->DrawTriangle(x1, x2, x3, inColor, DebugRenderer::ECastShadow::On);180}181}182183#endif // JPH_DEBUG_RENDERER184185struct SoftBodyShape::SBSGetTrianglesContext186{187Mat44 mCenterOfMassTransform;188int mTriangleIndex;189};190191void SoftBodyShape::GetTrianglesStart(GetTrianglesContext &ioContext, [[maybe_unused]] const AABox &inBox, Vec3Arg inPositionCOM, QuatArg inRotation, Vec3Arg inScale) const192{193SBSGetTrianglesContext &context = reinterpret_cast<SBSGetTrianglesContext &>(ioContext);194context.mCenterOfMassTransform = Mat44::sRotationTranslation(inRotation, inPositionCOM) * Mat44::sScale(inScale);195context.mTriangleIndex = 0;196}197198int SoftBodyShape::GetTrianglesNext(GetTrianglesContext &ioContext, int inMaxTrianglesRequested, Float3 *outTriangleVertices, const PhysicsMaterial **outMaterials) const199{200SBSGetTrianglesContext &context = reinterpret_cast<SBSGetTrianglesContext &>(ioContext);201202const Array<SoftBodyMotionProperties::Face> &faces = mSoftBodyMotionProperties->GetFaces();203const Array<SoftBodyVertex> &vertices = mSoftBodyMotionProperties->GetVertices();204const PhysicsMaterialList &materials = mSoftBodyMotionProperties->GetMaterials();205206int num_triangles = min(inMaxTrianglesRequested, (int)faces.size() - context.mTriangleIndex);207for (int i = 0; i < num_triangles; ++i)208{209const SoftBodyMotionProperties::Face &f = faces[context.mTriangleIndex + i];210211Vec3 x1 = context.mCenterOfMassTransform * vertices[f.mVertex[0]].mPosition;212Vec3 x2 = context.mCenterOfMassTransform * vertices[f.mVertex[1]].mPosition;213Vec3 x3 = context.mCenterOfMassTransform * vertices[f.mVertex[2]].mPosition;214215x1.StoreFloat3(outTriangleVertices++);216x2.StoreFloat3(outTriangleVertices++);217x3.StoreFloat3(outTriangleVertices++);218219if (outMaterials != nullptr)220*outMaterials++ = materials[f.mMaterialIndex];221}222223context.mTriangleIndex += num_triangles;224return num_triangles;225}226227Shape::Stats SoftBodyShape::GetStats() const228{229return Stats(sizeof(*this), (uint)mSoftBodyMotionProperties->GetFaces().size());230}231232float SoftBodyShape::GetVolume() const233{234return mSoftBodyMotionProperties->GetVolume();235}236237void SoftBodyShape::sCollideConvexVsSoftBody(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, [[maybe_unused]] const ShapeFilter &inShapeFilter)238{239JPH_ASSERT(inShape1->GetType() == EShapeType::Convex);240const ConvexShape *shape1 = static_cast<const ConvexShape *>(inShape1);241JPH_ASSERT(inShape2->GetSubType() == EShapeSubType::SoftBody);242const SoftBodyShape *shape2 = static_cast<const SoftBodyShape *>(inShape2);243244const Array<SoftBodyVertex> &vertices = shape2->mSoftBodyMotionProperties->GetVertices();245const Array<SoftBodyMotionProperties::Face> &faces = shape2->mSoftBodyMotionProperties->GetFaces();246uint num_triangle_bits = shape2->GetSubShapeIDBits();247248CollideShapeSettings settings(inCollideShapeSettings);249if (shape2->mSoftBodyMotionProperties->GetFacesDoubleSided())250settings.mBackFaceMode = EBackFaceMode::CollideWithBackFaces;251CollideConvexVsTriangles collider(shape1, inScale1, inScale2, inCenterOfMassTransform1, inCenterOfMassTransform2, inSubShapeIDCreator1.GetID(), settings, ioCollector);252for (const SoftBodyMotionProperties::Face &f : faces)253{254Vec3 x1 = vertices[f.mVertex[0]].mPosition;255Vec3 x2 = vertices[f.mVertex[1]].mPosition;256Vec3 x3 = vertices[f.mVertex[2]].mPosition;257258collider.Collide(x1, x2, x3, 0b111, inSubShapeIDCreator2.PushID(uint(&f - faces.data()), num_triangle_bits).GetID());259}260}261262void SoftBodyShape::sCollideSphereVsSoftBody(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, [[maybe_unused]] const ShapeFilter &inShapeFilter)263{264JPH_ASSERT(inShape1->GetSubType() == EShapeSubType::Sphere);265const SphereShape *shape1 = static_cast<const SphereShape *>(inShape1);266JPH_ASSERT(inShape2->GetSubType() == EShapeSubType::SoftBody);267const SoftBodyShape *shape2 = static_cast<const SoftBodyShape *>(inShape2);268269const Array<SoftBodyVertex> &vertices = shape2->mSoftBodyMotionProperties->GetVertices();270const Array<SoftBodyMotionProperties::Face> &faces = shape2->mSoftBodyMotionProperties->GetFaces();271uint num_triangle_bits = shape2->GetSubShapeIDBits();272273CollideShapeSettings settings(inCollideShapeSettings);274if (shape2->mSoftBodyMotionProperties->GetFacesDoubleSided())275settings.mBackFaceMode = EBackFaceMode::CollideWithBackFaces;276CollideSphereVsTriangles collider(shape1, inScale1, inScale2, inCenterOfMassTransform1, inCenterOfMassTransform2, inSubShapeIDCreator1.GetID(), settings, ioCollector);277for (const SoftBodyMotionProperties::Face &f : faces)278{279Vec3 x1 = vertices[f.mVertex[0]].mPosition;280Vec3 x2 = vertices[f.mVertex[1]].mPosition;281Vec3 x3 = vertices[f.mVertex[2]].mPosition;282283collider.Collide(x1, x2, x3, 0b111, inSubShapeIDCreator2.PushID(uint(&f - faces.data()), num_triangle_bits).GetID());284}285}286287void SoftBodyShape::sCastConvexVsSoftBody(const ShapeCast &inShapeCast, const ShapeCastSettings &inShapeCastSettings, const Shape *inShape, Vec3Arg inScale, [[maybe_unused]] const ShapeFilter &inShapeFilter, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, CastShapeCollector &ioCollector)288{289JPH_ASSERT(inShape->GetSubType() == EShapeSubType::SoftBody);290const SoftBodyShape *shape = static_cast<const SoftBodyShape *>(inShape);291292const Array<SoftBodyVertex> &vertices = shape->mSoftBodyMotionProperties->GetVertices();293const Array<SoftBodyMotionProperties::Face> &faces = shape->mSoftBodyMotionProperties->GetFaces();294uint num_triangle_bits = shape->GetSubShapeIDBits();295296ShapeCastSettings settings(inShapeCastSettings);297if (shape->mSoftBodyMotionProperties->GetFacesDoubleSided())298settings.mBackFaceModeTriangles = EBackFaceMode::CollideWithBackFaces;299CastConvexVsTriangles caster(inShapeCast, settings, inScale, inCenterOfMassTransform2, inSubShapeIDCreator1, ioCollector);300for (const SoftBodyMotionProperties::Face &f : faces)301{302Vec3 x1 = vertices[f.mVertex[0]].mPosition;303Vec3 x2 = vertices[f.mVertex[1]].mPosition;304Vec3 x3 = vertices[f.mVertex[2]].mPosition;305306caster.Cast(x1, x2, x3, 0b111, inSubShapeIDCreator2.PushID(uint(&f - faces.data()), num_triangle_bits).GetID());307}308}309310void SoftBodyShape::sCastSphereVsSoftBody(const ShapeCast &inShapeCast, const ShapeCastSettings &inShapeCastSettings, const Shape *inShape, Vec3Arg inScale, [[maybe_unused]] const ShapeFilter &inShapeFilter, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, CastShapeCollector &ioCollector)311{312JPH_ASSERT(inShape->GetSubType() == EShapeSubType::SoftBody);313const SoftBodyShape *shape = static_cast<const SoftBodyShape *>(inShape);314315const Array<SoftBodyVertex> &vertices = shape->mSoftBodyMotionProperties->GetVertices();316const Array<SoftBodyMotionProperties::Face> &faces = shape->mSoftBodyMotionProperties->GetFaces();317uint num_triangle_bits = shape->GetSubShapeIDBits();318319ShapeCastSettings settings(inShapeCastSettings);320if (shape->mSoftBodyMotionProperties->GetFacesDoubleSided())321settings.mBackFaceModeTriangles = EBackFaceMode::CollideWithBackFaces;322CastSphereVsTriangles caster(inShapeCast, settings, inScale, inCenterOfMassTransform2, inSubShapeIDCreator1, ioCollector);323for (const SoftBodyMotionProperties::Face &f : faces)324{325Vec3 x1 = vertices[f.mVertex[0]].mPosition;326Vec3 x2 = vertices[f.mVertex[1]].mPosition;327Vec3 x3 = vertices[f.mVertex[2]].mPosition;328329caster.Cast(x1, x2, x3, 0b111, inSubShapeIDCreator2.PushID(uint(&f - faces.data()), num_triangle_bits).GetID());330}331}332333void SoftBodyShape::sRegister()334{335ShapeFunctions &f = ShapeFunctions::sGet(EShapeSubType::SoftBody);336f.mConstruct = nullptr; // Not supposed to be constructed by users!337f.mColor = Color::sDarkGreen;338339for (EShapeSubType s : sConvexSubShapeTypes)340{341CollisionDispatch::sRegisterCollideShape(s, EShapeSubType::SoftBody, sCollideConvexVsSoftBody);342CollisionDispatch::sRegisterCastShape(s, EShapeSubType::SoftBody, sCastConvexVsSoftBody);343344CollisionDispatch::sRegisterCollideShape(EShapeSubType::SoftBody, s, CollisionDispatch::sReversedCollideShape);345CollisionDispatch::sRegisterCastShape(EShapeSubType::SoftBody, s, CollisionDispatch::sReversedCastShape);346}347348// Specialized collision functions349CollisionDispatch::sRegisterCollideShape(EShapeSubType::Sphere, EShapeSubType::SoftBody, sCollideSphereVsSoftBody);350CollisionDispatch::sRegisterCastShape(EShapeSubType::Sphere, EShapeSubType::SoftBody, sCastSphereVsSoftBody);351}352353JPH_NAMESPACE_END354355356