Path: blob/master/thirdparty/jolt_physics/Jolt/Physics/Collision/Shape/RotatedTranslatedShape.cpp
9913 views
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)1// SPDX-FileCopyrightText: 2021 Jorrit Rouwe2// SPDX-License-Identifier: MIT34#include <Jolt/Jolt.h>56#include <Jolt/Physics/Collision/Shape/RotatedTranslatedShape.h>7#include <Jolt/Physics/Collision/CollisionDispatch.h>8#include <Jolt/Physics/Collision/RayCast.h>9#include <Jolt/Physics/Collision/ShapeCast.h>10#include <Jolt/Physics/Collision/TransformedShape.h>11#include <Jolt/Core/StreamIn.h>12#include <Jolt/Core/StreamOut.h>13#include <Jolt/ObjectStream/TypeDeclarations.h>1415JPH_NAMESPACE_BEGIN1617JPH_IMPLEMENT_SERIALIZABLE_VIRTUAL(RotatedTranslatedShapeSettings)18{19JPH_ADD_BASE_CLASS(RotatedTranslatedShapeSettings, DecoratedShapeSettings)2021JPH_ADD_ATTRIBUTE(RotatedTranslatedShapeSettings, mPosition)22JPH_ADD_ATTRIBUTE(RotatedTranslatedShapeSettings, mRotation)23}2425ShapeSettings::ShapeResult RotatedTranslatedShapeSettings::Create() const26{27if (mCachedResult.IsEmpty())28Ref<Shape> shape = new RotatedTranslatedShape(*this, mCachedResult);29return mCachedResult;30}3132RotatedTranslatedShape::RotatedTranslatedShape(const RotatedTranslatedShapeSettings &inSettings, ShapeResult &outResult) :33DecoratedShape(EShapeSubType::RotatedTranslated, inSettings, outResult)34{35if (outResult.HasError())36return;3738// Calculate center of mass position39mCenterOfMass = inSettings.mPosition + inSettings.mRotation * mInnerShape->GetCenterOfMass();4041// Store rotation (position is always zero because we center around the center of mass)42mRotation = inSettings.mRotation;43mIsRotationIdentity = mRotation.IsClose(Quat::sIdentity());4445outResult.Set(this);46}4748RotatedTranslatedShape::RotatedTranslatedShape(Vec3Arg inPosition, QuatArg inRotation, const Shape *inShape) :49DecoratedShape(EShapeSubType::RotatedTranslated, inShape)50{51// Calculate center of mass position52mCenterOfMass = inPosition + inRotation * mInnerShape->GetCenterOfMass();5354// Store rotation (position is always zero because we center around the center of mass)55mRotation = inRotation;56mIsRotationIdentity = mRotation.IsClose(Quat::sIdentity());57}5859MassProperties RotatedTranslatedShape::GetMassProperties() const60{61// Rotate inertia of child into place62MassProperties p = mInnerShape->GetMassProperties();63p.Rotate(Mat44::sRotation(mRotation));64return p;65}6667AABox RotatedTranslatedShape::GetLocalBounds() const68{69return mInnerShape->GetLocalBounds().Transformed(Mat44::sRotation(mRotation));70}7172AABox RotatedTranslatedShape::GetWorldSpaceBounds(Mat44Arg inCenterOfMassTransform, Vec3Arg inScale) const73{74Mat44 transform = inCenterOfMassTransform * Mat44::sRotation(mRotation);75return mInnerShape->GetWorldSpaceBounds(transform, TransformScale(inScale));76}7778TransformedShape RotatedTranslatedShape::GetSubShapeTransformedShape(const SubShapeID &inSubShapeID, Vec3Arg inPositionCOM, QuatArg inRotation, Vec3Arg inScale, SubShapeID &outRemainder) const79{80// We don't use any bits in the sub shape ID81outRemainder = inSubShapeID;8283TransformedShape ts(RVec3(inPositionCOM), inRotation * mRotation, mInnerShape, BodyID());84ts.SetShapeScale(TransformScale(inScale));85return ts;86}8788Vec3 RotatedTranslatedShape::GetSurfaceNormal(const SubShapeID &inSubShapeID, Vec3Arg inLocalSurfacePosition) const89{90// Transform surface position to local space and pass call on91Mat44 transform = Mat44::sRotation(mRotation.Conjugated());92Vec3 normal = mInnerShape->GetSurfaceNormal(inSubShapeID, transform * inLocalSurfacePosition);9394// Transform normal to this shape's space95return transform.Multiply3x3Transposed(normal);96}9798void RotatedTranslatedShape::GetSupportingFace(const SubShapeID &inSubShapeID, Vec3Arg inDirection, Vec3Arg inScale, Mat44Arg inCenterOfMassTransform, SupportingFace &outVertices) const99{100Mat44 transform = Mat44::sRotation(mRotation);101mInnerShape->GetSupportingFace(inSubShapeID, transform.Multiply3x3Transposed(inDirection), TransformScale(inScale), inCenterOfMassTransform * transform, outVertices);102}103104void RotatedTranslatedShape::GetSubmergedVolume(Mat44Arg inCenterOfMassTransform, Vec3Arg inScale, const Plane &inSurface, float &outTotalVolume, float &outSubmergedVolume, Vec3 &outCenterOfBuoyancy JPH_IF_DEBUG_RENDERER(, RVec3Arg inBaseOffset)) const105{106// Get center of mass transform of child107Mat44 transform = inCenterOfMassTransform * Mat44::sRotation(mRotation);108109// Recurse to child110mInnerShape->GetSubmergedVolume(transform, TransformScale(inScale), inSurface, outTotalVolume, outSubmergedVolume, outCenterOfBuoyancy JPH_IF_DEBUG_RENDERER(, inBaseOffset));111}112113#ifdef JPH_DEBUG_RENDERER114void RotatedTranslatedShape::Draw(DebugRenderer *inRenderer, RMat44Arg inCenterOfMassTransform, Vec3Arg inScale, ColorArg inColor, bool inUseMaterialColors, bool inDrawWireframe) const115{116mInnerShape->Draw(inRenderer, inCenterOfMassTransform * Mat44::sRotation(mRotation), TransformScale(inScale), inColor, inUseMaterialColors, inDrawWireframe);117}118119void RotatedTranslatedShape::DrawGetSupportFunction(DebugRenderer *inRenderer, RMat44Arg inCenterOfMassTransform, Vec3Arg inScale, ColorArg inColor, bool inDrawSupportDirection) const120{121mInnerShape->DrawGetSupportFunction(inRenderer, inCenterOfMassTransform * Mat44::sRotation(mRotation), TransformScale(inScale), inColor, inDrawSupportDirection);122}123124void RotatedTranslatedShape::DrawGetSupportingFace(DebugRenderer *inRenderer, RMat44Arg inCenterOfMassTransform, Vec3Arg inScale) const125{126mInnerShape->DrawGetSupportingFace(inRenderer, inCenterOfMassTransform * Mat44::sRotation(mRotation), TransformScale(inScale));127}128#endif // JPH_DEBUG_RENDERER129130bool RotatedTranslatedShape::CastRay(const RayCast &inRay, const SubShapeIDCreator &inSubShapeIDCreator, RayCastResult &ioHit) const131{132// Transform the ray133Mat44 transform = Mat44::sRotation(mRotation.Conjugated());134RayCast ray = inRay.Transformed(transform);135136return mInnerShape->CastRay(ray, inSubShapeIDCreator, ioHit);137}138139void RotatedTranslatedShape::CastRay(const RayCast &inRay, const RayCastSettings &inRayCastSettings, const SubShapeIDCreator &inSubShapeIDCreator, CastRayCollector &ioCollector, const ShapeFilter &inShapeFilter) const140{141// Test shape filter142if (!inShapeFilter.ShouldCollide(this, inSubShapeIDCreator.GetID()))143return;144145// Transform the ray146Mat44 transform = Mat44::sRotation(mRotation.Conjugated());147RayCast ray = inRay.Transformed(transform);148149return mInnerShape->CastRay(ray, inRayCastSettings, inSubShapeIDCreator, ioCollector, inShapeFilter);150}151152void RotatedTranslatedShape::CollidePoint(Vec3Arg inPoint, const SubShapeIDCreator &inSubShapeIDCreator, CollidePointCollector &ioCollector, const ShapeFilter &inShapeFilter) const153{154// Test shape filter155if (!inShapeFilter.ShouldCollide(this, inSubShapeIDCreator.GetID()))156return;157158// Transform the point159Mat44 transform = Mat44::sRotation(mRotation.Conjugated());160mInnerShape->CollidePoint(transform * inPoint, inSubShapeIDCreator, ioCollector, inShapeFilter);161}162163void RotatedTranslatedShape::CollideSoftBodyVertices(Mat44Arg inCenterOfMassTransform, Vec3Arg inScale, const CollideSoftBodyVertexIterator &inVertices, uint inNumVertices, int inCollidingShapeIndex) const164{165mInnerShape->CollideSoftBodyVertices(inCenterOfMassTransform * Mat44::sRotation(mRotation), inScale, inVertices, inNumVertices, inCollidingShapeIndex);166}167168void RotatedTranslatedShape::CollectTransformedShapes(const AABox &inBox, Vec3Arg inPositionCOM, QuatArg inRotation, Vec3Arg inScale, const SubShapeIDCreator &inSubShapeIDCreator, TransformedShapeCollector &ioCollector, const ShapeFilter &inShapeFilter) const169{170// Test shape filter171if (!inShapeFilter.ShouldCollide(this, inSubShapeIDCreator.GetID()))172return;173174mInnerShape->CollectTransformedShapes(inBox, inPositionCOM, inRotation * mRotation, TransformScale(inScale), inSubShapeIDCreator, ioCollector, inShapeFilter);175}176177void RotatedTranslatedShape::TransformShape(Mat44Arg inCenterOfMassTransform, TransformedShapeCollector &ioCollector) const178{179mInnerShape->TransformShape(inCenterOfMassTransform * Mat44::sRotation(mRotation), ioCollector);180}181182void RotatedTranslatedShape::sCollideRotatedTranslatedVsShape(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)183{184JPH_ASSERT(inShape1->GetSubType() == EShapeSubType::RotatedTranslated);185const RotatedTranslatedShape *shape1 = static_cast<const RotatedTranslatedShape *>(inShape1);186187// Get world transform of 1188Mat44 transform1 = inCenterOfMassTransform1 * Mat44::sRotation(shape1->mRotation);189190CollisionDispatch::sCollideShapeVsShape(shape1->mInnerShape, inShape2, shape1->TransformScale(inScale1), inScale2, transform1, inCenterOfMassTransform2, inSubShapeIDCreator1, inSubShapeIDCreator2, inCollideShapeSettings, ioCollector, inShapeFilter);191}192193void RotatedTranslatedShape::sCollideShapeVsRotatedTranslated(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)194{195JPH_ASSERT(inShape2->GetSubType() == EShapeSubType::RotatedTranslated);196const RotatedTranslatedShape *shape2 = static_cast<const RotatedTranslatedShape *>(inShape2);197198// Get world transform of 2199Mat44 transform2 = inCenterOfMassTransform2 * Mat44::sRotation(shape2->mRotation);200201CollisionDispatch::sCollideShapeVsShape(inShape1, shape2->mInnerShape, inScale1, shape2->TransformScale(inScale2), inCenterOfMassTransform1, transform2, inSubShapeIDCreator1, inSubShapeIDCreator2, inCollideShapeSettings, ioCollector, inShapeFilter);202}203204void RotatedTranslatedShape::sCollideRotatedTranslatedVsRotatedTranslated(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)205{206JPH_ASSERT(inShape1->GetSubType() == EShapeSubType::RotatedTranslated);207const RotatedTranslatedShape *shape1 = static_cast<const RotatedTranslatedShape *>(inShape1);208JPH_ASSERT(inShape2->GetSubType() == EShapeSubType::RotatedTranslated);209const RotatedTranslatedShape *shape2 = static_cast<const RotatedTranslatedShape *>(inShape2);210211// Get world transform of 1 and 2212Mat44 transform1 = inCenterOfMassTransform1 * Mat44::sRotation(shape1->mRotation);213Mat44 transform2 = inCenterOfMassTransform2 * Mat44::sRotation(shape2->mRotation);214215CollisionDispatch::sCollideShapeVsShape(shape1->mInnerShape, shape2->mInnerShape, shape1->TransformScale(inScale1), shape2->TransformScale(inScale2), transform1, transform2, inSubShapeIDCreator1, inSubShapeIDCreator2, inCollideShapeSettings, ioCollector, inShapeFilter);216}217218void RotatedTranslatedShape::sCastRotatedTranslatedVsShape(const ShapeCast &inShapeCast, const ShapeCastSettings &inShapeCastSettings, const Shape *inShape, Vec3Arg inScale, const ShapeFilter &inShapeFilter, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, CastShapeCollector &ioCollector)219{220// Fetch rotated translated shape from cast shape221JPH_ASSERT(inShapeCast.mShape->GetSubType() == EShapeSubType::RotatedTranslated);222const RotatedTranslatedShape *shape1 = static_cast<const RotatedTranslatedShape *>(inShapeCast.mShape);223224// Transform the shape cast and update the shape225Mat44 transform = inShapeCast.mCenterOfMassStart * Mat44::sRotation(shape1->mRotation);226Vec3 scale = shape1->TransformScale(inShapeCast.mScale);227ShapeCast shape_cast(shape1->mInnerShape, scale, transform, inShapeCast.mDirection);228229CollisionDispatch::sCastShapeVsShapeLocalSpace(shape_cast, inShapeCastSettings, inShape, inScale, inShapeFilter, inCenterOfMassTransform2, inSubShapeIDCreator1, inSubShapeIDCreator2, ioCollector);230}231232void RotatedTranslatedShape::sCastShapeVsRotatedTranslated(const ShapeCast &inShapeCast, const ShapeCastSettings &inShapeCastSettings, const Shape *inShape, Vec3Arg inScale, const ShapeFilter &inShapeFilter, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, CastShapeCollector &ioCollector)233{234JPH_ASSERT(inShape->GetSubType() == EShapeSubType::RotatedTranslated);235const RotatedTranslatedShape *shape = static_cast<const RotatedTranslatedShape *>(inShape);236237// Determine the local transform238Mat44 local_transform = Mat44::sRotation(shape->mRotation);239240// Transform the shape cast241ShapeCast shape_cast = inShapeCast.PostTransformed(local_transform.Transposed3x3());242243CollisionDispatch::sCastShapeVsShapeLocalSpace(shape_cast, inShapeCastSettings, shape->mInnerShape, shape->TransformScale(inScale), inShapeFilter, inCenterOfMassTransform2 * local_transform, inSubShapeIDCreator1, inSubShapeIDCreator2, ioCollector);244}245246void RotatedTranslatedShape::sCastRotatedTranslatedVsRotatedTranslated(const ShapeCast &inShapeCast, const ShapeCastSettings &inShapeCastSettings, const Shape *inShape, Vec3Arg inScale, const ShapeFilter &inShapeFilter, Mat44Arg inCenterOfMassTransform2, const SubShapeIDCreator &inSubShapeIDCreator1, const SubShapeIDCreator &inSubShapeIDCreator2, CastShapeCollector &ioCollector)247{248JPH_ASSERT(inShapeCast.mShape->GetSubType() == EShapeSubType::RotatedTranslated);249const RotatedTranslatedShape *shape1 = static_cast<const RotatedTranslatedShape *>(inShapeCast.mShape);250JPH_ASSERT(inShape->GetSubType() == EShapeSubType::RotatedTranslated);251const RotatedTranslatedShape *shape2 = static_cast<const RotatedTranslatedShape *>(inShape);252253// Determine the local transform of shape 2254Mat44 local_transform2 = Mat44::sRotation(shape2->mRotation);255Mat44 local_transform2_transposed = local_transform2.Transposed3x3();256257// Transform the shape cast and update the shape258Mat44 transform = (local_transform2_transposed * inShapeCast.mCenterOfMassStart) * Mat44::sRotation(shape1->mRotation);259Vec3 scale = shape1->TransformScale(inShapeCast.mScale);260ShapeCast shape_cast(shape1->mInnerShape, scale, transform, local_transform2_transposed.Multiply3x3(inShapeCast.mDirection));261262CollisionDispatch::sCastShapeVsShapeLocalSpace(shape_cast, inShapeCastSettings, shape2->mInnerShape, shape2->TransformScale(inScale), inShapeFilter, inCenterOfMassTransform2 * local_transform2, inSubShapeIDCreator1, inSubShapeIDCreator2, ioCollector);263}264265void RotatedTranslatedShape::SaveBinaryState(StreamOut &inStream) const266{267DecoratedShape::SaveBinaryState(inStream);268269inStream.Write(mCenterOfMass);270inStream.Write(mRotation);271}272273void RotatedTranslatedShape::RestoreBinaryState(StreamIn &inStream)274{275DecoratedShape::RestoreBinaryState(inStream);276277inStream.Read(mCenterOfMass);278inStream.Read(mRotation);279mIsRotationIdentity = mRotation.IsClose(Quat::sIdentity());280}281282bool RotatedTranslatedShape::IsValidScale(Vec3Arg inScale) const283{284if (!Shape::IsValidScale(inScale))285return false;286287if (mIsRotationIdentity || ScaleHelpers::IsUniformScale(inScale))288return mInnerShape->IsValidScale(inScale);289290if (!ScaleHelpers::CanScaleBeRotated(mRotation, inScale))291return false;292293return mInnerShape->IsValidScale(ScaleHelpers::RotateScale(mRotation, inScale));294}295296Vec3 RotatedTranslatedShape::MakeScaleValid(Vec3Arg inScale) const297{298Vec3 scale = ScaleHelpers::MakeNonZeroScale(inScale);299300if (mIsRotationIdentity || ScaleHelpers::IsUniformScale(scale))301return mInnerShape->MakeScaleValid(scale);302303if (ScaleHelpers::CanScaleBeRotated(mRotation, scale))304return ScaleHelpers::RotateScale(mRotation.Conjugated(), mInnerShape->MakeScaleValid(ScaleHelpers::RotateScale(mRotation, scale)));305306Vec3 abs_uniform_scale = ScaleHelpers::MakeUniformScale(scale.Abs());307Vec3 uniform_scale = scale.GetSign() * abs_uniform_scale;308if (ScaleHelpers::CanScaleBeRotated(mRotation, uniform_scale))309return uniform_scale;310311return Sign(scale.GetX()) * abs_uniform_scale;312}313314void RotatedTranslatedShape::sRegister()315{316ShapeFunctions &f = ShapeFunctions::sGet(EShapeSubType::RotatedTranslated);317f.mConstruct = []() -> Shape * { return new RotatedTranslatedShape; };318f.mColor = Color::sBlue;319320for (EShapeSubType s : sAllSubShapeTypes)321{322CollisionDispatch::sRegisterCollideShape(EShapeSubType::RotatedTranslated, s, sCollideRotatedTranslatedVsShape);323CollisionDispatch::sRegisterCollideShape(s, EShapeSubType::RotatedTranslated, sCollideShapeVsRotatedTranslated);324CollisionDispatch::sRegisterCastShape(EShapeSubType::RotatedTranslated, s, sCastRotatedTranslatedVsShape);325CollisionDispatch::sRegisterCastShape(s, EShapeSubType::RotatedTranslated, sCastShapeVsRotatedTranslated);326}327328CollisionDispatch::sRegisterCollideShape(EShapeSubType::RotatedTranslated, EShapeSubType::RotatedTranslated, sCollideRotatedTranslatedVsRotatedTranslated);329CollisionDispatch::sRegisterCastShape(EShapeSubType::RotatedTranslated, EShapeSubType::RotatedTranslated, sCastRotatedTranslatedVsRotatedTranslated);330}331332JPH_NAMESPACE_END333334335