Path: blob/master/thirdparty/jolt_physics/Jolt/Physics/SoftBody/SoftBodyShape.cpp
9913 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();8586const Array<SoftBodyVertex> &vertices = mSoftBodyMotionProperties->GetVertices();87for (const SoftBodyMotionProperties::Face &f : mSoftBodyMotionProperties->GetFaces())88{89Vec3 x1 = vertices[f.mVertex[0]].mPosition;90Vec3 x2 = vertices[f.mVertex[1]].mPosition;91Vec3 x3 = vertices[f.mVertex[2]].mPosition;9293// Back facing check94if (inRayCastSettings.mBackFaceModeTriangles == EBackFaceMode::IgnoreBackFaces && (x2 - x1).Cross(x3 - x1).Dot(inRay.mDirection) > 0.0f)95continue;9697// Test ray against triangle98float fraction = RayTriangle(inRay.mOrigin, inRay.mDirection, x1, x2, x3);99if (fraction < ioCollector.GetEarlyOutFraction())100{101// Better hit than the current hit102RayCastResult hit;103hit.mBodyID = TransformedShape::sGetBodyID(ioCollector.GetContext());104hit.mFraction = fraction;105hit.mSubShapeID2 = inSubShapeIDCreator.PushID(uint(&f - mSoftBodyMotionProperties->GetFaces().data()), num_triangle_bits).GetID();106ioCollector.AddHit(hit);107}108}109}110111void SoftBodyShape::CollidePoint(Vec3Arg inPoint, const SubShapeIDCreator &inSubShapeIDCreator, CollidePointCollector &ioCollector, const ShapeFilter &inShapeFilter) const112{113sCollidePointUsingRayCast(*this, inPoint, inSubShapeIDCreator, ioCollector, inShapeFilter);114}115116void SoftBodyShape::CollideSoftBodyVertices(Mat44Arg inCenterOfMassTransform, Vec3Arg inScale, const CollideSoftBodyVertexIterator &inVertices, uint inNumVertices, int inCollidingShapeIndex) const117{118/* Not implemented */119}120121const PhysicsMaterial *SoftBodyShape::GetMaterial(const SubShapeID &inSubShapeID) const122{123SubShapeID remainder;124uint triangle_idx = inSubShapeID.PopID(GetSubShapeIDBits(), remainder);125JPH_ASSERT(remainder.IsEmpty());126127const SoftBodyMotionProperties::Face &f = mSoftBodyMotionProperties->GetFace(triangle_idx);128return mSoftBodyMotionProperties->GetMaterials()[f.mMaterialIndex];129}130131Vec3 SoftBodyShape::GetSurfaceNormal(const SubShapeID &inSubShapeID, Vec3Arg inLocalSurfacePosition) const132{133SubShapeID remainder;134uint triangle_idx = inSubShapeID.PopID(GetSubShapeIDBits(), remainder);135JPH_ASSERT(remainder.IsEmpty());136137const SoftBodyMotionProperties::Face &f = mSoftBodyMotionProperties->GetFace(triangle_idx);138const Array<SoftBodyVertex> &vertices = mSoftBodyMotionProperties->GetVertices();139140Vec3 x1 = vertices[f.mVertex[0]].mPosition;141Vec3 x2 = vertices[f.mVertex[1]].mPosition;142Vec3 x3 = vertices[f.mVertex[2]].mPosition;143144return (x2 - x1).Cross(x3 - x1).NormalizedOr(Vec3::sAxisY());145}146147void SoftBodyShape::GetSupportingFace(const SubShapeID &inSubShapeID, Vec3Arg inDirection, Vec3Arg inScale, Mat44Arg inCenterOfMassTransform, SupportingFace &outVertices) const148{149SubShapeID remainder;150uint triangle_idx = inSubShapeID.PopID(GetSubShapeIDBits(), remainder);151JPH_ASSERT(remainder.IsEmpty());152153const SoftBodyMotionProperties::Face &f = mSoftBodyMotionProperties->GetFace(triangle_idx);154const Array<SoftBodyVertex> &vertices = mSoftBodyMotionProperties->GetVertices();155156for (uint32 i : f.mVertex)157outVertices.push_back(inCenterOfMassTransform * (inScale * vertices[i].mPosition));158}159160void SoftBodyShape::GetSubmergedVolume(Mat44Arg inCenterOfMassTransform, Vec3Arg inScale, const Plane &inSurface, float &outTotalVolume, float &outSubmergedVolume, Vec3 &outCenterOfBuoyancy JPH_IF_DEBUG_RENDERER(, RVec3Arg inBaseOffset)) const161{162outSubmergedVolume = 0.0f;163outTotalVolume = mSoftBodyMotionProperties->GetVolume();164outCenterOfBuoyancy = Vec3::sZero();165}166167#ifdef JPH_DEBUG_RENDERER168169void SoftBodyShape::Draw(DebugRenderer *inRenderer, RMat44Arg inCenterOfMassTransform, Vec3Arg inScale, ColorArg inColor, bool inUseMaterialColors, bool inDrawWireframe) const170{171const Array<SoftBodyVertex> &vertices = mSoftBodyMotionProperties->GetVertices();172for (const SoftBodyMotionProperties::Face &f : mSoftBodyMotionProperties->GetFaces())173{174RVec3 x1 = inCenterOfMassTransform * vertices[f.mVertex[0]].mPosition;175RVec3 x2 = inCenterOfMassTransform * vertices[f.mVertex[1]].mPosition;176RVec3 x3 = inCenterOfMassTransform * vertices[f.mVertex[2]].mPosition;177178inRenderer->DrawTriangle(x1, x2, x3, inColor, DebugRenderer::ECastShadow::On);179}180}181182#endif // JPH_DEBUG_RENDERER183184struct SoftBodyShape::SBSGetTrianglesContext185{186Mat44 mCenterOfMassTransform;187int mTriangleIndex;188};189190void SoftBodyShape::GetTrianglesStart(GetTrianglesContext &ioContext, [[maybe_unused]] const AABox &inBox, Vec3Arg inPositionCOM, QuatArg inRotation, Vec3Arg inScale) const191{192SBSGetTrianglesContext &context = reinterpret_cast<SBSGetTrianglesContext &>(ioContext);193context.mCenterOfMassTransform = Mat44::sRotationTranslation(inRotation, inPositionCOM) * Mat44::sScale(inScale);194context.mTriangleIndex = 0;195}196197int SoftBodyShape::GetTrianglesNext(GetTrianglesContext &ioContext, int inMaxTrianglesRequested, Float3 *outTriangleVertices, const PhysicsMaterial **outMaterials) const198{199SBSGetTrianglesContext &context = reinterpret_cast<SBSGetTrianglesContext &>(ioContext);200201const Array<SoftBodyMotionProperties::Face> &faces = mSoftBodyMotionProperties->GetFaces();202const Array<SoftBodyVertex> &vertices = mSoftBodyMotionProperties->GetVertices();203const PhysicsMaterialList &materials = mSoftBodyMotionProperties->GetMaterials();204205int num_triangles = min(inMaxTrianglesRequested, (int)faces.size() - context.mTriangleIndex);206for (int i = 0; i < num_triangles; ++i)207{208const SoftBodyMotionProperties::Face &f = faces[context.mTriangleIndex + i];209210Vec3 x1 = context.mCenterOfMassTransform * vertices[f.mVertex[0]].mPosition;211Vec3 x2 = context.mCenterOfMassTransform * vertices[f.mVertex[1]].mPosition;212Vec3 x3 = context.mCenterOfMassTransform * vertices[f.mVertex[2]].mPosition;213214x1.StoreFloat3(outTriangleVertices++);215x2.StoreFloat3(outTriangleVertices++);216x3.StoreFloat3(outTriangleVertices++);217218if (outMaterials != nullptr)219*outMaterials++ = materials[f.mMaterialIndex];220}221222context.mTriangleIndex += num_triangles;223return num_triangles;224}225226Shape::Stats SoftBodyShape::GetStats() const227{228return Stats(sizeof(*this), (uint)mSoftBodyMotionProperties->GetFaces().size());229}230231float SoftBodyShape::GetVolume() const232{233return mSoftBodyMotionProperties->GetVolume();234}235236void 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)237{238JPH_ASSERT(inShape1->GetType() == EShapeType::Convex);239const ConvexShape *shape1 = static_cast<const ConvexShape *>(inShape1);240JPH_ASSERT(inShape2->GetSubType() == EShapeSubType::SoftBody);241const SoftBodyShape *shape2 = static_cast<const SoftBodyShape *>(inShape2);242243const Array<SoftBodyVertex> &vertices = shape2->mSoftBodyMotionProperties->GetVertices();244const Array<SoftBodyMotionProperties::Face> &faces = shape2->mSoftBodyMotionProperties->GetFaces();245uint num_triangle_bits = shape2->GetSubShapeIDBits();246247CollideConvexVsTriangles collider(shape1, inScale1, inScale2, inCenterOfMassTransform1, inCenterOfMassTransform2, inSubShapeIDCreator1.GetID(), inCollideShapeSettings, ioCollector);248for (const SoftBodyMotionProperties::Face &f : faces)249{250Vec3 x1 = vertices[f.mVertex[0]].mPosition;251Vec3 x2 = vertices[f.mVertex[1]].mPosition;252Vec3 x3 = vertices[f.mVertex[2]].mPosition;253254collider.Collide(x1, x2, x3, 0b111, inSubShapeIDCreator2.PushID(uint(&f - faces.data()), num_triangle_bits).GetID());255}256}257258void 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)259{260JPH_ASSERT(inShape1->GetSubType() == EShapeSubType::Sphere);261const SphereShape *shape1 = static_cast<const SphereShape *>(inShape1);262JPH_ASSERT(inShape2->GetSubType() == EShapeSubType::SoftBody);263const SoftBodyShape *shape2 = static_cast<const SoftBodyShape *>(inShape2);264265const Array<SoftBodyVertex> &vertices = shape2->mSoftBodyMotionProperties->GetVertices();266const Array<SoftBodyMotionProperties::Face> &faces = shape2->mSoftBodyMotionProperties->GetFaces();267uint num_triangle_bits = shape2->GetSubShapeIDBits();268269CollideSphereVsTriangles collider(shape1, inScale1, inScale2, inCenterOfMassTransform1, inCenterOfMassTransform2, inSubShapeIDCreator1.GetID(), inCollideShapeSettings, ioCollector);270for (const SoftBodyMotionProperties::Face &f : faces)271{272Vec3 x1 = vertices[f.mVertex[0]].mPosition;273Vec3 x2 = vertices[f.mVertex[1]].mPosition;274Vec3 x3 = vertices[f.mVertex[2]].mPosition;275276collider.Collide(x1, x2, x3, 0b111, inSubShapeIDCreator2.PushID(uint(&f - faces.data()), num_triangle_bits).GetID());277}278}279280void 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)281{282JPH_ASSERT(inShape->GetSubType() == EShapeSubType::SoftBody);283const SoftBodyShape *shape = static_cast<const SoftBodyShape *>(inShape);284285const Array<SoftBodyVertex> &vertices = shape->mSoftBodyMotionProperties->GetVertices();286const Array<SoftBodyMotionProperties::Face> &faces = shape->mSoftBodyMotionProperties->GetFaces();287uint num_triangle_bits = shape->GetSubShapeIDBits();288289CastConvexVsTriangles caster(inShapeCast, inShapeCastSettings, inScale, inCenterOfMassTransform2, inSubShapeIDCreator1, ioCollector);290for (const SoftBodyMotionProperties::Face &f : faces)291{292Vec3 x1 = vertices[f.mVertex[0]].mPosition;293Vec3 x2 = vertices[f.mVertex[1]].mPosition;294Vec3 x3 = vertices[f.mVertex[2]].mPosition;295296caster.Cast(x1, x2, x3, 0b111, inSubShapeIDCreator2.PushID(uint(&f - faces.data()), num_triangle_bits).GetID());297}298}299300void 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)301{302JPH_ASSERT(inShape->GetSubType() == EShapeSubType::SoftBody);303const SoftBodyShape *shape = static_cast<const SoftBodyShape *>(inShape);304305const Array<SoftBodyVertex> &vertices = shape->mSoftBodyMotionProperties->GetVertices();306const Array<SoftBodyMotionProperties::Face> &faces = shape->mSoftBodyMotionProperties->GetFaces();307uint num_triangle_bits = shape->GetSubShapeIDBits();308309CastSphereVsTriangles caster(inShapeCast, inShapeCastSettings, inScale, inCenterOfMassTransform2, inSubShapeIDCreator1, ioCollector);310for (const SoftBodyMotionProperties::Face &f : faces)311{312Vec3 x1 = vertices[f.mVertex[0]].mPosition;313Vec3 x2 = vertices[f.mVertex[1]].mPosition;314Vec3 x3 = vertices[f.mVertex[2]].mPosition;315316caster.Cast(x1, x2, x3, 0b111, inSubShapeIDCreator2.PushID(uint(&f - faces.data()), num_triangle_bits).GetID());317}318}319320void SoftBodyShape::sRegister()321{322ShapeFunctions &f = ShapeFunctions::sGet(EShapeSubType::SoftBody);323f.mConstruct = nullptr; // Not supposed to be constructed by users!324f.mColor = Color::sDarkGreen;325326for (EShapeSubType s : sConvexSubShapeTypes)327{328CollisionDispatch::sRegisterCollideShape(s, EShapeSubType::SoftBody, sCollideConvexVsSoftBody);329CollisionDispatch::sRegisterCastShape(s, EShapeSubType::SoftBody, sCastConvexVsSoftBody);330331CollisionDispatch::sRegisterCollideShape(EShapeSubType::SoftBody, s, CollisionDispatch::sReversedCollideShape);332CollisionDispatch::sRegisterCastShape(EShapeSubType::SoftBody, s, CollisionDispatch::sReversedCastShape);333}334335// Specialized collision functions336CollisionDispatch::sRegisterCollideShape(EShapeSubType::Sphere, EShapeSubType::SoftBody, sCollideSphereVsSoftBody);337CollisionDispatch::sRegisterCastShape(EShapeSubType::Sphere, EShapeSubType::SoftBody, sCastSphereVsSoftBody);338}339340JPH_NAMESPACE_END341342343