Path: blob/master/thirdparty/jolt_physics/Jolt/Physics/Constraints/RackAndPinionConstraint.cpp
9912 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/Constraints/RackAndPinionConstraint.h>7#include <Jolt/Physics/Constraints/HingeConstraint.h>8#include <Jolt/Physics/Constraints/SliderConstraint.h>9#include <Jolt/Physics/Body/Body.h>10#include <Jolt/ObjectStream/TypeDeclarations.h>11#include <Jolt/Core/StreamIn.h>12#include <Jolt/Core/StreamOut.h>13#ifdef JPH_DEBUG_RENDERER14#include <Jolt/Renderer/DebugRenderer.h>15#endif // JPH_DEBUG_RENDERER1617JPH_NAMESPACE_BEGIN1819JPH_IMPLEMENT_SERIALIZABLE_VIRTUAL(RackAndPinionConstraintSettings)20{21JPH_ADD_BASE_CLASS(RackAndPinionConstraintSettings, TwoBodyConstraintSettings)2223JPH_ADD_ENUM_ATTRIBUTE(RackAndPinionConstraintSettings, mSpace)24JPH_ADD_ATTRIBUTE(RackAndPinionConstraintSettings, mHingeAxis)25JPH_ADD_ATTRIBUTE(RackAndPinionConstraintSettings, mSliderAxis)26JPH_ADD_ATTRIBUTE(RackAndPinionConstraintSettings, mRatio)27}2829void RackAndPinionConstraintSettings::SaveBinaryState(StreamOut &inStream) const30{31ConstraintSettings::SaveBinaryState(inStream);3233inStream.Write(mSpace);34inStream.Write(mHingeAxis);35inStream.Write(mSliderAxis);36inStream.Write(mRatio);37}3839void RackAndPinionConstraintSettings::RestoreBinaryState(StreamIn &inStream)40{41ConstraintSettings::RestoreBinaryState(inStream);4243inStream.Read(mSpace);44inStream.Read(mHingeAxis);45inStream.Read(mSliderAxis);46inStream.Read(mRatio);47}4849TwoBodyConstraint *RackAndPinionConstraintSettings::Create(Body &inBody1, Body &inBody2) const50{51return new RackAndPinionConstraint(inBody1, inBody2, *this);52}5354RackAndPinionConstraint::RackAndPinionConstraint(Body &inBody1, Body &inBody2, const RackAndPinionConstraintSettings &inSettings) :55TwoBodyConstraint(inBody1, inBody2, inSettings),56mLocalSpaceHingeAxis(inSettings.mHingeAxis),57mLocalSpaceSliderAxis(inSettings.mSliderAxis),58mRatio(inSettings.mRatio)59{60if (inSettings.mSpace == EConstraintSpace::WorldSpace)61{62// If all properties were specified in world space, take them to local space now63mLocalSpaceHingeAxis = inBody1.GetInverseCenterOfMassTransform().Multiply3x3(mLocalSpaceHingeAxis).Normalized();64mLocalSpaceSliderAxis = inBody2.GetInverseCenterOfMassTransform().Multiply3x3(mLocalSpaceSliderAxis).Normalized();65}66}6768void RackAndPinionConstraint::CalculateConstraintProperties(Mat44Arg inRotation1, Mat44Arg inRotation2)69{70// Calculate world space normals71mWorldSpaceHingeAxis = inRotation1 * mLocalSpaceHingeAxis;72mWorldSpaceSliderAxis = inRotation2 * mLocalSpaceSliderAxis;7374mRackAndPinionConstraintPart.CalculateConstraintProperties(*mBody1, mWorldSpaceHingeAxis, *mBody2, mWorldSpaceSliderAxis, mRatio);75}7677void RackAndPinionConstraint::SetupVelocityConstraint(float inDeltaTime)78{79// Calculate constraint properties that are constant while bodies don't move80Mat44 rotation1 = Mat44::sRotation(mBody1->GetRotation());81Mat44 rotation2 = Mat44::sRotation(mBody2->GetRotation());82CalculateConstraintProperties(rotation1, rotation2);83}8485void RackAndPinionConstraint::ResetWarmStart()86{87mRackAndPinionConstraintPart.Deactivate();88}8990void RackAndPinionConstraint::WarmStartVelocityConstraint(float inWarmStartImpulseRatio)91{92// Warm starting: Apply previous frame impulse93mRackAndPinionConstraintPart.WarmStart(*mBody1, *mBody2, inWarmStartImpulseRatio);94}9596bool RackAndPinionConstraint::SolveVelocityConstraint(float inDeltaTime)97{98return mRackAndPinionConstraintPart.SolveVelocityConstraint(*mBody1, mWorldSpaceHingeAxis, *mBody2, mWorldSpaceSliderAxis, mRatio);99}100101bool RackAndPinionConstraint::SolvePositionConstraint(float inDeltaTime, float inBaumgarte)102{103if (mRackConstraint == nullptr || mPinionConstraint == nullptr)104return false;105106float rotation;107if (mPinionConstraint->GetSubType() == EConstraintSubType::Hinge)108{109rotation = StaticCast<HingeConstraint>(mPinionConstraint)->GetCurrentAngle();110}111else112{113JPH_ASSERT(false, "Unsupported");114return false;115}116117float translation;118if (mRackConstraint->GetSubType() == EConstraintSubType::Slider)119{120translation = StaticCast<SliderConstraint>(mRackConstraint)->GetCurrentPosition();121}122else123{124JPH_ASSERT(false, "Unsupported");125return false;126}127128float error = CenterAngleAroundZero(fmod(rotation - mRatio * translation, 2.0f * JPH_PI));129if (error == 0.0f)130return false;131132Mat44 rotation1 = Mat44::sRotation(mBody1->GetRotation());133Mat44 rotation2 = Mat44::sRotation(mBody2->GetRotation());134CalculateConstraintProperties(rotation1, rotation2);135return mRackAndPinionConstraintPart.SolvePositionConstraint(*mBody1, *mBody2, error, inBaumgarte);136}137138#ifdef JPH_DEBUG_RENDERER139void RackAndPinionConstraint::DrawConstraint(DebugRenderer *inRenderer) const140{141RMat44 transform1 = mBody1->GetCenterOfMassTransform();142RMat44 transform2 = mBody2->GetCenterOfMassTransform();143144// Draw constraint axis145inRenderer->DrawArrow(transform1.GetTranslation(), transform1 * mLocalSpaceHingeAxis, Color::sGreen, 0.01f);146inRenderer->DrawArrow(transform2.GetTranslation(), transform2 * mLocalSpaceSliderAxis, Color::sBlue, 0.01f);147}148149#endif // JPH_DEBUG_RENDERER150151void RackAndPinionConstraint::SaveState(StateRecorder &inStream) const152{153TwoBodyConstraint::SaveState(inStream);154155mRackAndPinionConstraintPart.SaveState(inStream);156}157158void RackAndPinionConstraint::RestoreState(StateRecorder &inStream)159{160TwoBodyConstraint::RestoreState(inStream);161162mRackAndPinionConstraintPart.RestoreState(inStream);163}164165Ref<ConstraintSettings> RackAndPinionConstraint::GetConstraintSettings() const166{167RackAndPinionConstraintSettings *settings = new RackAndPinionConstraintSettings;168ToConstraintSettings(*settings);169settings->mSpace = EConstraintSpace::LocalToBodyCOM;170settings->mHingeAxis = mLocalSpaceHingeAxis;171settings->mSliderAxis = mLocalSpaceSliderAxis;172settings->mRatio = mRatio;173return settings;174}175176Mat44 RackAndPinionConstraint::GetConstraintToBody1Matrix() const177{178Vec3 perp = mLocalSpaceHingeAxis.GetNormalizedPerpendicular();179return Mat44(Vec4(mLocalSpaceHingeAxis, 0), Vec4(perp, 0), Vec4(mLocalSpaceHingeAxis.Cross(perp), 0), Vec4(0, 0, 0, 1));180}181182Mat44 RackAndPinionConstraint::GetConstraintToBody2Matrix() const183{184Vec3 perp = mLocalSpaceSliderAxis.GetNormalizedPerpendicular();185return Mat44(Vec4(mLocalSpaceSliderAxis, 0), Vec4(perp, 0), Vec4(mLocalSpaceSliderAxis.Cross(perp), 0), Vec4(0, 0, 0, 1));186}187188JPH_NAMESPACE_END189190191