Path: blob/master/thirdparty/jolt_physics/Jolt/Physics/Constraints/GearConstraint.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/GearConstraint.h>7#include <Jolt/Physics/Constraints/HingeConstraint.h>8#include <Jolt/Physics/Body/Body.h>9#include <Jolt/ObjectStream/TypeDeclarations.h>10#include <Jolt/Core/StreamIn.h>11#include <Jolt/Core/StreamOut.h>12#ifdef JPH_DEBUG_RENDERER13#include <Jolt/Renderer/DebugRenderer.h>14#endif // JPH_DEBUG_RENDERER1516JPH_NAMESPACE_BEGIN1718JPH_IMPLEMENT_SERIALIZABLE_VIRTUAL(GearConstraintSettings)19{20JPH_ADD_BASE_CLASS(GearConstraintSettings, TwoBodyConstraintSettings)2122JPH_ADD_ENUM_ATTRIBUTE(GearConstraintSettings, mSpace)23JPH_ADD_ATTRIBUTE(GearConstraintSettings, mHingeAxis1)24JPH_ADD_ATTRIBUTE(GearConstraintSettings, mHingeAxis2)25JPH_ADD_ATTRIBUTE(GearConstraintSettings, mRatio)26}2728void GearConstraintSettings::SaveBinaryState(StreamOut &inStream) const29{30ConstraintSettings::SaveBinaryState(inStream);3132inStream.Write(mSpace);33inStream.Write(mHingeAxis1);34inStream.Write(mHingeAxis2);35inStream.Write(mRatio);36}3738void GearConstraintSettings::RestoreBinaryState(StreamIn &inStream)39{40ConstraintSettings::RestoreBinaryState(inStream);4142inStream.Read(mSpace);43inStream.Read(mHingeAxis1);44inStream.Read(mHingeAxis2);45inStream.Read(mRatio);46}4748TwoBodyConstraint *GearConstraintSettings::Create(Body &inBody1, Body &inBody2) const49{50return new GearConstraint(inBody1, inBody2, *this);51}5253GearConstraint::GearConstraint(Body &inBody1, Body &inBody2, const GearConstraintSettings &inSettings) :54TwoBodyConstraint(inBody1, inBody2, inSettings),55mLocalSpaceHingeAxis1(inSettings.mHingeAxis1),56mLocalSpaceHingeAxis2(inSettings.mHingeAxis2),57mRatio(inSettings.mRatio)58{59if (inSettings.mSpace == EConstraintSpace::WorldSpace)60{61// If all properties were specified in world space, take them to local space now62mLocalSpaceHingeAxis1 = inBody1.GetInverseCenterOfMassTransform().Multiply3x3(mLocalSpaceHingeAxis1).Normalized();63mLocalSpaceHingeAxis2 = inBody2.GetInverseCenterOfMassTransform().Multiply3x3(mLocalSpaceHingeAxis2).Normalized();64}65}6667void GearConstraint::CalculateConstraintProperties(Mat44Arg inRotation1, Mat44Arg inRotation2)68{69// Calculate world space normals70mWorldSpaceHingeAxis1 = inRotation1 * mLocalSpaceHingeAxis1;71mWorldSpaceHingeAxis2 = inRotation2 * mLocalSpaceHingeAxis2;7273mGearConstraintPart.CalculateConstraintProperties(*mBody1, mWorldSpaceHingeAxis1, *mBody2, mWorldSpaceHingeAxis2, mRatio);74}7576void GearConstraint::SetupVelocityConstraint(float inDeltaTime)77{78// Calculate constraint properties that are constant while bodies don't move79Mat44 rotation1 = Mat44::sRotation(mBody1->GetRotation());80Mat44 rotation2 = Mat44::sRotation(mBody2->GetRotation());81CalculateConstraintProperties(rotation1, rotation2);82}8384void GearConstraint::ResetWarmStart()85{86mGearConstraintPart.Deactivate();87}8889void GearConstraint::WarmStartVelocityConstraint(float inWarmStartImpulseRatio)90{91// Warm starting: Apply previous frame impulse92mGearConstraintPart.WarmStart(*mBody1, *mBody2, inWarmStartImpulseRatio);93}9495bool GearConstraint::SolveVelocityConstraint(float inDeltaTime)96{97return mGearConstraintPart.SolveVelocityConstraint(*mBody1, mWorldSpaceHingeAxis1, *mBody2, mWorldSpaceHingeAxis2, mRatio);98}99100bool GearConstraint::SolvePositionConstraint(float inDeltaTime, float inBaumgarte)101{102if (mGear1Constraint == nullptr || mGear2Constraint == nullptr)103return false;104105float gear1rot;106if (mGear1Constraint->GetSubType() == EConstraintSubType::Hinge)107{108gear1rot = StaticCast<HingeConstraint>(mGear1Constraint)->GetCurrentAngle();109}110else111{112JPH_ASSERT(false, "Unsupported");113return false;114}115116float gear2rot;117if (mGear2Constraint->GetSubType() == EConstraintSubType::Hinge)118{119gear2rot = StaticCast<HingeConstraint>(mGear2Constraint)->GetCurrentAngle();120}121else122{123JPH_ASSERT(false, "Unsupported");124return false;125}126127float error = CenterAngleAroundZero(fmod(gear1rot + mRatio * gear2rot, 2.0f * JPH_PI));128if (error == 0.0f)129return false;130131Mat44 rotation1 = Mat44::sRotation(mBody1->GetRotation());132Mat44 rotation2 = Mat44::sRotation(mBody2->GetRotation());133CalculateConstraintProperties(rotation1, rotation2);134return mGearConstraintPart.SolvePositionConstraint(*mBody1, *mBody2, error, inBaumgarte);135}136137#ifdef JPH_DEBUG_RENDERER138void GearConstraint::DrawConstraint(DebugRenderer *inRenderer) const139{140RMat44 transform1 = mBody1->GetCenterOfMassTransform();141RMat44 transform2 = mBody2->GetCenterOfMassTransform();142143// Draw constraint axis144inRenderer->DrawArrow(transform1.GetTranslation(), transform1 * mLocalSpaceHingeAxis1, Color::sGreen, 0.01f);145inRenderer->DrawArrow(transform2.GetTranslation(), transform2 * mLocalSpaceHingeAxis2, Color::sBlue, 0.01f);146}147148#endif // JPH_DEBUG_RENDERER149150void GearConstraint::SaveState(StateRecorder &inStream) const151{152TwoBodyConstraint::SaveState(inStream);153154mGearConstraintPart.SaveState(inStream);155}156157void GearConstraint::RestoreState(StateRecorder &inStream)158{159TwoBodyConstraint::RestoreState(inStream);160161mGearConstraintPart.RestoreState(inStream);162}163164Ref<ConstraintSettings> GearConstraint::GetConstraintSettings() const165{166GearConstraintSettings *settings = new GearConstraintSettings;167ToConstraintSettings(*settings);168settings->mSpace = EConstraintSpace::LocalToBodyCOM;169settings->mHingeAxis1 = mLocalSpaceHingeAxis1;170settings->mHingeAxis2 = mLocalSpaceHingeAxis2;171settings->mRatio = mRatio;172return settings;173}174175Mat44 GearConstraint::GetConstraintToBody1Matrix() const176{177Vec3 perp = mLocalSpaceHingeAxis1.GetNormalizedPerpendicular();178return Mat44(Vec4(mLocalSpaceHingeAxis1, 0), Vec4(perp, 0), Vec4(mLocalSpaceHingeAxis1.Cross(perp), 0), Vec4(0, 0, 0, 1));179}180181Mat44 GearConstraint::GetConstraintToBody2Matrix() const182{183Vec3 perp = mLocalSpaceHingeAxis2.GetNormalizedPerpendicular();184return Mat44(Vec4(mLocalSpaceHingeAxis2, 0), Vec4(perp, 0), Vec4(mLocalSpaceHingeAxis2.Cross(perp), 0), Vec4(0, 0, 0, 1));185}186187JPH_NAMESPACE_END188189190