forked from hertog/godot-module-template
542 lines
19 KiB
C++
542 lines
19 KiB
C++
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
|
|
// SPDX-FileCopyrightText: 2024 Jorrit Rouwe
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
#include <Jolt/Jolt.h>
|
|
|
|
#include <Jolt/Physics/Collision/Shape/PlaneShape.h>
|
|
#include <Jolt/Physics/Collision/Shape/ConvexShape.h>
|
|
#include <Jolt/Physics/Collision/Shape/ScaleHelpers.h>
|
|
#include <Jolt/Physics/Collision/RayCast.h>
|
|
#include <Jolt/Physics/Collision/ShapeCast.h>
|
|
#include <Jolt/Physics/Collision/ShapeFilter.h>
|
|
#include <Jolt/Physics/Collision/CastResult.h>
|
|
#include <Jolt/Physics/Collision/CollisionDispatch.h>
|
|
#include <Jolt/Physics/Collision/TransformedShape.h>
|
|
#include <Jolt/Physics/Collision/CollidePointResult.h>
|
|
#include <Jolt/Physics/Collision/CollideSoftBodyVertexIterator.h>
|
|
#include <Jolt/Core/Profiler.h>
|
|
#include <Jolt/Core/StreamIn.h>
|
|
#include <Jolt/Core/StreamOut.h>
|
|
#include <Jolt/Geometry/Plane.h>
|
|
#include <Jolt/ObjectStream/TypeDeclarations.h>
|
|
#ifdef JPH_DEBUG_RENDERER
|
|
#include <Jolt/Renderer/DebugRenderer.h>
|
|
#endif // JPH_DEBUG_RENDERER
|
|
|
|
JPH_NAMESPACE_BEGIN
|
|
|
|
JPH_IMPLEMENT_SERIALIZABLE_VIRTUAL(PlaneShapeSettings)
|
|
{
|
|
JPH_ADD_BASE_CLASS(PlaneShapeSettings, ShapeSettings)
|
|
|
|
JPH_ADD_ATTRIBUTE(PlaneShapeSettings, mPlane)
|
|
JPH_ADD_ATTRIBUTE(PlaneShapeSettings, mMaterial)
|
|
JPH_ADD_ATTRIBUTE(PlaneShapeSettings, mHalfExtent)
|
|
}
|
|
|
|
ShapeSettings::ShapeResult PlaneShapeSettings::Create() const
|
|
{
|
|
if (mCachedResult.IsEmpty())
|
|
Ref<Shape> shape = new PlaneShape(*this, mCachedResult);
|
|
return mCachedResult;
|
|
}
|
|
|
|
inline static void sPlaneGetOrthogonalBasis(Vec3Arg inNormal, Vec3 &outPerp1, Vec3 &outPerp2)
|
|
{
|
|
outPerp1 = inNormal.Cross(Vec3::sAxisY()).NormalizedOr(Vec3::sAxisX());
|
|
outPerp2 = outPerp1.Cross(inNormal).Normalized();
|
|
outPerp1 = inNormal.Cross(outPerp2);
|
|
}
|
|
|
|
void PlaneShape::GetVertices(Vec3 *outVertices) const
|
|
{
|
|
// Create orthogonal basis
|
|
Vec3 normal = mPlane.GetNormal();
|
|
Vec3 perp1, perp2;
|
|
sPlaneGetOrthogonalBasis(normal, perp1, perp2);
|
|
|
|
// Scale basis
|
|
perp1 *= mHalfExtent;
|
|
perp2 *= mHalfExtent;
|
|
|
|
// Calculate corners
|
|
Vec3 point = -normal * mPlane.GetConstant();
|
|
outVertices[0] = point + perp1 + perp2;
|
|
outVertices[1] = point + perp1 - perp2;
|
|
outVertices[2] = point - perp1 - perp2;
|
|
outVertices[3] = point - perp1 + perp2;
|
|
}
|
|
|
|
void PlaneShape::CalculateLocalBounds()
|
|
{
|
|
// Get the vertices of the plane
|
|
Vec3 vertices[4];
|
|
GetVertices(vertices);
|
|
|
|
// Encapsulate the vertices and a point mHalfExtent behind the plane
|
|
mLocalBounds = AABox();
|
|
Vec3 normal = mPlane.GetNormal();
|
|
for (const Vec3 &v : vertices)
|
|
{
|
|
mLocalBounds.Encapsulate(v);
|
|
mLocalBounds.Encapsulate(v - mHalfExtent * normal);
|
|
}
|
|
}
|
|
|
|
PlaneShape::PlaneShape(const PlaneShapeSettings &inSettings, ShapeResult &outResult) :
|
|
Shape(EShapeType::Plane, EShapeSubType::Plane, inSettings, outResult),
|
|
mPlane(inSettings.mPlane),
|
|
mMaterial(inSettings.mMaterial),
|
|
mHalfExtent(inSettings.mHalfExtent)
|
|
{
|
|
if (!mPlane.GetNormal().IsNormalized())
|
|
{
|
|
outResult.SetError("Plane normal needs to be normalized!");
|
|
return;
|
|
}
|
|
|
|
CalculateLocalBounds();
|
|
|
|
outResult.Set(this);
|
|
}
|
|
|
|
MassProperties PlaneShape::GetMassProperties() const
|
|
{
|
|
// Object should always be static, return default mass properties
|
|
return MassProperties();
|
|
}
|
|
|
|
void PlaneShape::GetSupportingFace(const SubShapeID &inSubShapeID, Vec3Arg inDirection, Vec3Arg inScale, Mat44Arg inCenterOfMassTransform, SupportingFace &outVertices) const
|
|
{
|
|
// Get the vertices of the plane
|
|
Vec3 vertices[4];
|
|
GetVertices(vertices);
|
|
|
|
// Reverse if scale is inside out
|
|
if (ScaleHelpers::IsInsideOut(inScale))
|
|
{
|
|
std::swap(vertices[0], vertices[3]);
|
|
std::swap(vertices[1], vertices[2]);
|
|
}
|
|
|
|
// Transform them to world space
|
|
outVertices.clear();
|
|
Mat44 com = inCenterOfMassTransform.PreScaled(inScale);
|
|
for (const Vec3 &v : vertices)
|
|
outVertices.push_back(com * v);
|
|
}
|
|
|
|
#ifdef JPH_DEBUG_RENDERER
|
|
void PlaneShape::Draw(DebugRenderer *inRenderer, RMat44Arg inCenterOfMassTransform, Vec3Arg inScale, ColorArg inColor, bool inUseMaterialColors, bool inDrawWireframe) const
|
|
{
|
|
// Get the vertices of the plane
|
|
Vec3 local_vertices[4];
|
|
GetVertices(local_vertices);
|
|
|
|
// Reverse if scale is inside out
|
|
if (ScaleHelpers::IsInsideOut(inScale))
|
|
{
|
|
std::swap(local_vertices[0], local_vertices[3]);
|
|
std::swap(local_vertices[1], local_vertices[2]);
|
|
}
|
|
|
|
// Transform them to world space
|
|
RMat44 com = inCenterOfMassTransform.PreScaled(inScale);
|
|
RVec3 vertices[4];
|
|
for (uint i = 0; i < 4; ++i)
|
|
vertices[i] = com * local_vertices[i];
|
|
|
|
// Determine the color
|
|
Color color = inUseMaterialColors? GetMaterial(SubShapeID())->GetDebugColor() : inColor;
|
|
|
|
// Draw the plane
|
|
if (inDrawWireframe)
|
|
{
|
|
inRenderer->DrawWireTriangle(vertices[0], vertices[1], vertices[2], color);
|
|
inRenderer->DrawWireTriangle(vertices[0], vertices[2], vertices[3], color);
|
|
}
|
|
else
|
|
{
|
|
inRenderer->DrawTriangle(vertices[0], vertices[1], vertices[2], color, DebugRenderer::ECastShadow::On);
|
|
inRenderer->DrawTriangle(vertices[0], vertices[2], vertices[3], color, DebugRenderer::ECastShadow::On);
|
|
}
|
|
}
|
|
#endif // JPH_DEBUG_RENDERER
|
|
|
|
bool PlaneShape::CastRay(const RayCast &inRay, const SubShapeIDCreator &inSubShapeIDCreator, RayCastResult &ioHit) const
|
|
{
|
|
JPH_PROFILE_FUNCTION();
|
|
|
|
// Test starting inside of negative half space
|
|
float distance = mPlane.SignedDistance(inRay.mOrigin);
|
|
if (distance <= 0.0f)
|
|
{
|
|
ioHit.mFraction = 0.0f;
|
|
ioHit.mSubShapeID2 = inSubShapeIDCreator.GetID();
|
|
return true;
|
|
}
|
|
|
|
// Test ray parallel to plane
|
|
float dot = inRay.mDirection.Dot(mPlane.GetNormal());
|
|
if (dot == 0.0f)
|
|
return false;
|
|
|
|
// Calculate hit fraction
|
|
float fraction = -distance / dot;
|
|
if (fraction >= 0.0f && fraction < ioHit.mFraction)
|
|
{
|
|
ioHit.mFraction = fraction;
|
|
ioHit.mSubShapeID2 = inSubShapeIDCreator.GetID();
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void PlaneShape::CastRay(const RayCast &inRay, const RayCastSettings &inRayCastSettings, const SubShapeIDCreator &inSubShapeIDCreator, CastRayCollector &ioCollector, const ShapeFilter &inShapeFilter) const
|
|
{
|
|
JPH_PROFILE_FUNCTION();
|
|
|
|
// Test shape filter
|
|
if (!inShapeFilter.ShouldCollide(this, inSubShapeIDCreator.GetID()))
|
|
return;
|
|
|
|
// Inside solid half space?
|
|
float distance = mPlane.SignedDistance(inRay.mOrigin);
|
|
if (inRayCastSettings.mTreatConvexAsSolid
|
|
&& distance <= 0.0f // Inside plane
|
|
&& ioCollector.GetEarlyOutFraction() > 0.0f) // Willing to accept hits at fraction 0
|
|
{
|
|
// Hit at fraction 0
|
|
RayCastResult hit;
|
|
hit.mBodyID = TransformedShape::sGetBodyID(ioCollector.GetContext());
|
|
hit.mFraction = 0.0f;
|
|
hit.mSubShapeID2 = inSubShapeIDCreator.GetID();
|
|
ioCollector.AddHit(hit);
|
|
}
|
|
|
|
float dot = inRay.mDirection.Dot(mPlane.GetNormal());
|
|
if (dot != 0.0f // Parallel ray will not hit plane
|
|
&& (inRayCastSettings.mBackFaceModeConvex == EBackFaceMode::CollideWithBackFaces || dot < 0.0f)) // Back face culling
|
|
{
|
|
// Calculate hit with plane
|
|
float fraction = -distance / dot;
|
|
if (fraction >= 0.0f && fraction < ioCollector.GetEarlyOutFraction())
|
|
{
|
|
RayCastResult hit;
|
|
hit.mBodyID = TransformedShape::sGetBodyID(ioCollector.GetContext());
|
|
hit.mFraction = fraction;
|
|
hit.mSubShapeID2 = inSubShapeIDCreator.GetID();
|
|
ioCollector.AddHit(hit);
|
|
}
|
|
}
|
|
}
|
|
|
|
void PlaneShape::CollidePoint(Vec3Arg inPoint, const SubShapeIDCreator &inSubShapeIDCreator, CollidePointCollector &ioCollector, const ShapeFilter &inShapeFilter) const
|
|
{
|
|
JPH_PROFILE_FUNCTION();
|
|
|
|
// Test shape filter
|
|
if (!inShapeFilter.ShouldCollide(this, inSubShapeIDCreator.GetID()))
|
|
return;
|
|
|
|
// Check if the point is inside the plane
|
|
if (mPlane.SignedDistance(inPoint) < 0.0f)
|
|
ioCollector.AddHit({ TransformedShape::sGetBodyID(ioCollector.GetContext()), inSubShapeIDCreator.GetID() });
|
|
}
|
|
|
|
void PlaneShape::CollideSoftBodyVertices(Mat44Arg inCenterOfMassTransform, Vec3Arg inScale, const CollideSoftBodyVertexIterator &inVertices, uint inNumVertices, int inCollidingShapeIndex) const
|
|
{
|
|
JPH_PROFILE_FUNCTION();
|
|
|
|
// Convert plane to world space
|
|
Plane plane = mPlane.Scaled(inScale).GetTransformed(inCenterOfMassTransform);
|
|
|
|
for (CollideSoftBodyVertexIterator v = inVertices, sbv_end = inVertices + inNumVertices; v != sbv_end; ++v)
|
|
if (v.GetInvMass() > 0.0f)
|
|
{
|
|
// Calculate penetration
|
|
float penetration = -plane.SignedDistance(v.GetPosition());
|
|
if (v.UpdatePenetration(penetration))
|
|
v.SetCollision(plane, inCollidingShapeIndex);
|
|
}
|
|
}
|
|
|
|
// This is a version of GetSupportingFace that returns a face that is large enough to cover the shape we're colliding with but not as large as the regular GetSupportedFace to avoid numerical precision issues
|
|
inline static void sGetSupportingFace(const ConvexShape *inShape, Vec3Arg inShapeCOM, const Plane &inPlane, Mat44Arg inPlaneToWorld, ConvexShape::SupportingFace &outPlaneFace)
|
|
{
|
|
// Project COM of shape onto plane
|
|
Plane world_plane = inPlane.GetTransformed(inPlaneToWorld);
|
|
Vec3 center = world_plane.ProjectPointOnPlane(inShapeCOM);
|
|
|
|
// Create orthogonal basis for the plane
|
|
Vec3 normal = world_plane.GetNormal();
|
|
Vec3 perp1, perp2;
|
|
sPlaneGetOrthogonalBasis(normal, perp1, perp2);
|
|
|
|
// Base the size of the face on the bounding box of the shape, ensuring that it is large enough to cover the entire shape
|
|
float size = inShape->GetLocalBounds().GetSize().Length();
|
|
perp1 *= size;
|
|
perp2 *= size;
|
|
|
|
// Emit the vertices
|
|
outPlaneFace.resize(4);
|
|
outPlaneFace[0] = center + perp1 + perp2;
|
|
outPlaneFace[1] = center + perp1 - perp2;
|
|
outPlaneFace[2] = center - perp1 - perp2;
|
|
outPlaneFace[3] = center - perp1 + perp2;
|
|
}
|
|
|
|
void PlaneShape::sCastConvexVsPlane(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)
|
|
{
|
|
JPH_PROFILE_FUNCTION();
|
|
|
|
// Get the shapes
|
|
JPH_ASSERT(inShapeCast.mShape->GetType() == EShapeType::Convex);
|
|
JPH_ASSERT(inShape->GetType() == EShapeType::Plane);
|
|
const ConvexShape *convex_shape = static_cast<const ConvexShape *>(inShapeCast.mShape);
|
|
const PlaneShape *plane_shape = static_cast<const PlaneShape *>(inShape);
|
|
|
|
// Shape cast is provided relative to COM of inShape, so all we need to do is transform our plane with inScale
|
|
Plane plane = plane_shape->mPlane.Scaled(inScale);
|
|
Vec3 normal = plane.GetNormal();
|
|
|
|
// Get support function
|
|
ConvexShape::SupportBuffer shape1_support_buffer;
|
|
const ConvexShape::Support *shape1_support = convex_shape->GetSupportFunction(ConvexShape::ESupportMode::Default, shape1_support_buffer, inShapeCast.mScale);
|
|
|
|
// Get the support point of the convex shape in the opposite direction of the plane normal in our local space
|
|
Vec3 normal_in_convex_shape_space = inShapeCast.mCenterOfMassStart.Multiply3x3Transposed(normal);
|
|
Vec3 support_point = inShapeCast.mCenterOfMassStart * shape1_support->GetSupport(-normal_in_convex_shape_space);
|
|
float signed_distance = plane.SignedDistance(support_point);
|
|
float convex_radius = shape1_support->GetConvexRadius();
|
|
float penetration_depth = -signed_distance + convex_radius;
|
|
float dot = inShapeCast.mDirection.Dot(normal);
|
|
|
|
// Collision output
|
|
Mat44 com_hit;
|
|
Vec3 point1, point2;
|
|
float fraction;
|
|
|
|
// Do we start in collision?
|
|
if (penetration_depth > 0.0f)
|
|
{
|
|
// Back face culling?
|
|
if (inShapeCastSettings.mBackFaceModeConvex == EBackFaceMode::IgnoreBackFaces && dot > 0.0f)
|
|
return;
|
|
|
|
// Shallower hit?
|
|
if (penetration_depth <= -ioCollector.GetEarlyOutFraction())
|
|
return;
|
|
|
|
// We're hitting at fraction 0
|
|
fraction = 0.0f;
|
|
|
|
// Get contact point
|
|
com_hit = inCenterOfMassTransform2;
|
|
point1 = inCenterOfMassTransform2 * (support_point - normal * convex_radius);
|
|
point2 = inCenterOfMassTransform2 * (support_point - normal * signed_distance);
|
|
}
|
|
else if (dot < 0.0f) // Moving towards the plane?
|
|
{
|
|
// Calculate hit fraction
|
|
fraction = penetration_depth / dot;
|
|
JPH_ASSERT(fraction >= 0.0f);
|
|
|
|
// Further than early out fraction?
|
|
if (fraction >= ioCollector.GetEarlyOutFraction())
|
|
return;
|
|
|
|
// Get contact point
|
|
com_hit = inCenterOfMassTransform2.PostTranslated(fraction * inShapeCast.mDirection);
|
|
point1 = point2 = com_hit * (support_point - normal * convex_radius);
|
|
}
|
|
else
|
|
{
|
|
// Moving away from the plane
|
|
return;
|
|
}
|
|
|
|
// Create cast result
|
|
Vec3 penetration_axis_world = com_hit.Multiply3x3(-normal);
|
|
bool back_facing = dot > 0.0f;
|
|
ShapeCastResult result(fraction, point1, point2, penetration_axis_world, back_facing, inSubShapeIDCreator1.GetID(), inSubShapeIDCreator2.GetID(), TransformedShape::sGetBodyID(ioCollector.GetContext()));
|
|
|
|
// Gather faces
|
|
if (inShapeCastSettings.mCollectFacesMode == ECollectFacesMode::CollectFaces)
|
|
{
|
|
// Get supporting face of convex shape
|
|
Mat44 shape_to_world = com_hit * inShapeCast.mCenterOfMassStart;
|
|
convex_shape->GetSupportingFace(SubShapeID(), normal_in_convex_shape_space, inShapeCast.mScale, shape_to_world, result.mShape1Face);
|
|
|
|
// Get supporting face of plane
|
|
if (!result.mShape1Face.empty())
|
|
sGetSupportingFace(convex_shape, shape_to_world.GetTranslation(), plane, inCenterOfMassTransform2, result.mShape2Face);
|
|
}
|
|
|
|
// Notify the collector
|
|
JPH_IF_TRACK_NARROWPHASE_STATS(TrackNarrowPhaseCollector track;)
|
|
ioCollector.AddHit(result);
|
|
}
|
|
|
|
struct PlaneShape::PSGetTrianglesContext
|
|
{
|
|
Float3 mVertices[4];
|
|
bool mDone = false;
|
|
};
|
|
|
|
void PlaneShape::GetTrianglesStart(GetTrianglesContext &ioContext, const AABox &inBox, Vec3Arg inPositionCOM, QuatArg inRotation, Vec3Arg inScale) const
|
|
{
|
|
static_assert(sizeof(PSGetTrianglesContext) <= sizeof(GetTrianglesContext), "GetTrianglesContext too small");
|
|
JPH_ASSERT(IsAligned(&ioContext, alignof(PSGetTrianglesContext)));
|
|
|
|
PSGetTrianglesContext *context = new (&ioContext) PSGetTrianglesContext();
|
|
|
|
// Get the vertices of the plane
|
|
Vec3 vertices[4];
|
|
GetVertices(vertices);
|
|
|
|
// Reverse if scale is inside out
|
|
if (ScaleHelpers::IsInsideOut(inScale))
|
|
{
|
|
std::swap(vertices[0], vertices[3]);
|
|
std::swap(vertices[1], vertices[2]);
|
|
}
|
|
|
|
// Transform them to world space
|
|
Mat44 com = Mat44::sRotationTranslation(inRotation, inPositionCOM).PreScaled(inScale);
|
|
for (uint i = 0; i < 4; ++i)
|
|
(com * vertices[i]).StoreFloat3(&context->mVertices[i]);
|
|
}
|
|
|
|
int PlaneShape::GetTrianglesNext(GetTrianglesContext &ioContext, int inMaxTrianglesRequested, Float3 *outTriangleVertices, const PhysicsMaterial **outMaterials) const
|
|
{
|
|
static_assert(cGetTrianglesMinTrianglesRequested >= 2, "cGetTrianglesMinTrianglesRequested is too small");
|
|
JPH_ASSERT(inMaxTrianglesRequested >= cGetTrianglesMinTrianglesRequested);
|
|
|
|
// Check if we're done
|
|
PSGetTrianglesContext &context = (PSGetTrianglesContext &)ioContext;
|
|
if (context.mDone)
|
|
return 0;
|
|
context.mDone = true;
|
|
|
|
// 1st triangle
|
|
outTriangleVertices[0] = context.mVertices[0];
|
|
outTriangleVertices[1] = context.mVertices[1];
|
|
outTriangleVertices[2] = context.mVertices[2];
|
|
|
|
// 2nd triangle
|
|
outTriangleVertices[3] = context.mVertices[0];
|
|
outTriangleVertices[4] = context.mVertices[2];
|
|
outTriangleVertices[5] = context.mVertices[3];
|
|
|
|
if (outMaterials != nullptr)
|
|
{
|
|
// Get material
|
|
const PhysicsMaterial *material = GetMaterial(SubShapeID());
|
|
outMaterials[0] = material;
|
|
outMaterials[1] = material;
|
|
}
|
|
|
|
return 2;
|
|
}
|
|
|
|
void PlaneShape::sCollideConvexVsPlane(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)
|
|
{
|
|
JPH_PROFILE_FUNCTION();
|
|
|
|
// Get the shapes
|
|
JPH_ASSERT(inShape1->GetType() == EShapeType::Convex);
|
|
JPH_ASSERT(inShape2->GetType() == EShapeType::Plane);
|
|
const ConvexShape *shape1 = static_cast<const ConvexShape *>(inShape1);
|
|
const PlaneShape *shape2 = static_cast<const PlaneShape *>(inShape2);
|
|
|
|
// Transform the plane to the space of the convex shape
|
|
Plane scaled_plane = shape2->mPlane.Scaled(inScale2);
|
|
Plane plane = scaled_plane.GetTransformed(inCenterOfMassTransform1.InversedRotationTranslation() * inCenterOfMassTransform2);
|
|
Vec3 normal = plane.GetNormal();
|
|
|
|
// Get support function
|
|
ConvexShape::SupportBuffer shape1_support_buffer;
|
|
const ConvexShape::Support *shape1_support = shape1->GetSupportFunction(ConvexShape::ESupportMode::Default, shape1_support_buffer, inScale1);
|
|
|
|
// Get the support point of the convex shape in the opposite direction of the plane normal
|
|
Vec3 support_point = shape1_support->GetSupport(-normal);
|
|
float signed_distance = plane.SignedDistance(support_point);
|
|
float convex_radius = shape1_support->GetConvexRadius();
|
|
float penetration_depth = -signed_distance + convex_radius;
|
|
if (penetration_depth > -inCollideShapeSettings.mMaxSeparationDistance)
|
|
{
|
|
// Get contact point
|
|
Vec3 point1 = inCenterOfMassTransform1 * (support_point - normal * convex_radius);
|
|
Vec3 point2 = inCenterOfMassTransform1 * (support_point - normal * signed_distance);
|
|
Vec3 penetration_axis_world = inCenterOfMassTransform1.Multiply3x3(-normal);
|
|
|
|
// Create collision result
|
|
CollideShapeResult result(point1, point2, penetration_axis_world, penetration_depth, inSubShapeIDCreator1.GetID(), inSubShapeIDCreator2.GetID(), TransformedShape::sGetBodyID(ioCollector.GetContext()));
|
|
|
|
// Gather faces
|
|
if (inCollideShapeSettings.mCollectFacesMode == ECollectFacesMode::CollectFaces)
|
|
{
|
|
// Get supporting face of shape 1
|
|
shape1->GetSupportingFace(SubShapeID(), normal, inScale1, inCenterOfMassTransform1, result.mShape1Face);
|
|
|
|
// Get supporting face of shape 2
|
|
if (!result.mShape1Face.empty())
|
|
sGetSupportingFace(shape1, inCenterOfMassTransform1.GetTranslation(), scaled_plane, inCenterOfMassTransform2, result.mShape2Face);
|
|
}
|
|
|
|
// Notify the collector
|
|
JPH_IF_TRACK_NARROWPHASE_STATS(TrackNarrowPhaseCollector track;)
|
|
ioCollector.AddHit(result);
|
|
}
|
|
}
|
|
|
|
void PlaneShape::SaveBinaryState(StreamOut &inStream) const
|
|
{
|
|
Shape::SaveBinaryState(inStream);
|
|
|
|
inStream.Write(mPlane);
|
|
inStream.Write(mHalfExtent);
|
|
}
|
|
|
|
void PlaneShape::RestoreBinaryState(StreamIn &inStream)
|
|
{
|
|
Shape::RestoreBinaryState(inStream);
|
|
|
|
inStream.Read(mPlane);
|
|
inStream.Read(mHalfExtent);
|
|
|
|
CalculateLocalBounds();
|
|
}
|
|
|
|
void PlaneShape::SaveMaterialState(PhysicsMaterialList &outMaterials) const
|
|
{
|
|
outMaterials = { mMaterial };
|
|
}
|
|
|
|
void PlaneShape::RestoreMaterialState(const PhysicsMaterialRefC *inMaterials, uint inNumMaterials)
|
|
{
|
|
JPH_ASSERT(inNumMaterials == 1);
|
|
mMaterial = inMaterials[0];
|
|
}
|
|
|
|
void PlaneShape::sRegister()
|
|
{
|
|
ShapeFunctions &f = ShapeFunctions::sGet(EShapeSubType::Plane);
|
|
f.mConstruct = []() -> Shape * { return new PlaneShape; };
|
|
f.mColor = Color::sDarkRed;
|
|
|
|
for (EShapeSubType s : sConvexSubShapeTypes)
|
|
{
|
|
CollisionDispatch::sRegisterCollideShape(s, EShapeSubType::Plane, sCollideConvexVsPlane);
|
|
CollisionDispatch::sRegisterCastShape(s, EShapeSubType::Plane, sCastConvexVsPlane);
|
|
|
|
CollisionDispatch::sRegisterCastShape(EShapeSubType::Plane, s, CollisionDispatch::sReversedCastShape);
|
|
CollisionDispatch::sRegisterCollideShape(EShapeSubType::Plane, s, CollisionDispatch::sReversedCollideShape);
|
|
}
|
|
}
|
|
|
|
JPH_NAMESPACE_END
|