fix(physics): motor joint updates with paramB
This commit is contained in:
parent
3a6fb2ada2
commit
78d2466efd
8 changed files with 84 additions and 28 deletions
|
@ -17,6 +17,9 @@ void JointInstance::OnAncestryChanged(nullable std::shared_ptr<Instance>, nullab
|
||||||
Update();
|
Update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void JointInstance::OnPartParamsUpdated() {
|
||||||
|
}
|
||||||
|
|
||||||
void JointInstance::Update() {
|
void JointInstance::Update() {
|
||||||
// To keep it simple compared to our previous algorithm, this one is pretty barebones:
|
// To keep it simple compared to our previous algorithm, this one is pretty barebones:
|
||||||
// 1. Every time we update, (whether our parent changed, or a property), destroy the current joints
|
// 1. Every time we update, (whether our parent changed, or a property), destroy the current joints
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
#include "objects/base/instance.h"
|
#include "objects/base/instance.h"
|
||||||
#include "../annotation.h"
|
#include "../annotation.h"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <optional>
|
|
||||||
#include "datatypes/cframe.h"
|
#include "datatypes/cframe.h"
|
||||||
#include "physics/world.h"
|
#include "physics/world.h"
|
||||||
|
|
||||||
|
@ -12,6 +11,8 @@
|
||||||
#include "objects/part/part.h"
|
#include "objects/part/part.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define DEF_PROP_PHYS DEF_PROP_(on_update=onUpdated)
|
||||||
|
|
||||||
class BasePart;
|
class BasePart;
|
||||||
class Workspace;
|
class Workspace;
|
||||||
|
|
||||||
|
@ -33,12 +34,15 @@ protected:
|
||||||
virtual void buildJoint() = 0;
|
virtual void buildJoint() = 0;
|
||||||
public:
|
public:
|
||||||
void Update();
|
void Update();
|
||||||
|
virtual void OnPartParamsUpdated();
|
||||||
|
|
||||||
DEF_PROP_(on_update=onUpdated) std::weak_ptr<BasePart> part0;
|
DEF_PROP_PHYS std::weak_ptr<BasePart> part0;
|
||||||
DEF_PROP_(on_update=onUpdated) std::weak_ptr<BasePart> part1;
|
DEF_PROP_PHYS std::weak_ptr<BasePart> part1;
|
||||||
DEF_PROP_(on_update=onUpdated) CFrame c0;
|
DEF_PROP_PHYS CFrame c0;
|
||||||
DEF_PROP_(on_update=onUpdated) CFrame c1;
|
DEF_PROP_PHYS CFrame c1;
|
||||||
|
|
||||||
JointInstance(const InstanceType*);
|
JointInstance(const InstanceType*);
|
||||||
~JointInstance();
|
~JointInstance();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#undef DEF_PROP_PHYS
|
|
@ -21,8 +21,14 @@ void RotateV::buildJoint() {
|
||||||
CFrame newFrame = part0.lock()->cframe * (c0 * c1.Inverse());
|
CFrame newFrame = part0.lock()->cframe * (c0 * c1.Inverse());
|
||||||
part1.lock()->cframe = newFrame;
|
part1.lock()->cframe = newFrame;
|
||||||
// Do NOT use Abs() in this scenario. For some reason that breaks it
|
// Do NOT use Abs() in this scenario. For some reason that breaks it
|
||||||
PhysRotatingJointInfo jointInfo(c0, c1, true);
|
float vel = part0.lock()->GetSurfaceParamB(-c0.LookVector().Unit()) * 6.28;
|
||||||
|
PhysRotatingJointInfo jointInfo(c0, c1, vel);
|
||||||
|
|
||||||
this->joint = workspace->CreateJoint(jointInfo, part0.lock(), part1.lock());
|
this->joint = workspace->CreateJoint(jointInfo, part0.lock(), part1.lock());
|
||||||
jointWorkspace = workspace;
|
jointWorkspace = workspace;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RotateV::OnPartParamsUpdated() {
|
||||||
|
float vel = part0.lock()->GetSurfaceParamB(-c0.LookVector().Unit()) * 6.28;
|
||||||
|
this->joint.setAngularVelocity(vel);
|
||||||
|
}
|
|
@ -13,6 +13,8 @@ public:
|
||||||
RotateV();
|
RotateV();
|
||||||
~RotateV();
|
~RotateV();
|
||||||
|
|
||||||
|
void OnPartParamsUpdated() override;
|
||||||
|
|
||||||
static inline std::shared_ptr<RotateV> New() { return std::make_shared<RotateV>(); };
|
static inline std::shared_ptr<RotateV> New() { return std::make_shared<RotateV>(); };
|
||||||
static inline std::shared_ptr<Instance> Create() { return std::make_shared<RotateV>(); };
|
static inline std::shared_ptr<Instance> Create() { return std::make_shared<RotateV>(); };
|
||||||
};
|
};
|
|
@ -70,6 +70,15 @@ void BasePart::onUpdated(std::string property) {
|
||||||
BreakJoints();
|
BreakJoints();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BasePart::onParamUpdated(std::string property) {
|
||||||
|
// Send signal to joints to update themselves
|
||||||
|
for (std::weak_ptr<JointInstance> joint : primaryJoints) {
|
||||||
|
if (joint.expired()) continue;
|
||||||
|
|
||||||
|
joint.lock()->OnPartParamsUpdated();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Expands provided extents to fit point
|
// Expands provided extents to fit point
|
||||||
static void expandMaxExtents(Vector3* min, Vector3* max, Vector3 point) {
|
static void expandMaxExtents(Vector3* min, Vector3* max, Vector3 point) {
|
||||||
*min = Vector3(glm::min(min->X(), point.X()), glm::min(min->Y(), point.Y()), glm::min(min->Z(), point.Z()));
|
*min = Vector3(glm::min(min->X(), point.X()), glm::min(min->Y(), point.Y()), glm::min(min->Z(), point.Z()));
|
||||||
|
|
|
@ -14,6 +14,10 @@
|
||||||
#include "objects/pvinstance.h"
|
#include "objects/pvinstance.h"
|
||||||
#include "physics/world.h"
|
#include "physics/world.h"
|
||||||
|
|
||||||
|
// Common macro for part properties
|
||||||
|
#define DEF_PROP_PHYS DEF_PROP_(on_update=onUpdated)
|
||||||
|
#define DEF_PROP_PHYSPARAM DEF_PROP_(on_update=onParamUpdated)
|
||||||
|
|
||||||
// For easy construction from C++. Maybe should be removed?
|
// For easy construction from C++. Maybe should be removed?
|
||||||
struct PartConstructParams {
|
struct PartConstructParams {
|
||||||
Vector3 position;
|
Vector3 position;
|
||||||
|
@ -51,19 +55,20 @@ protected:
|
||||||
virtual void OnWorkspaceRemoved(std::shared_ptr<Workspace> oldWorkspace) override;
|
virtual void OnWorkspaceRemoved(std::shared_ptr<Workspace> oldWorkspace) override;
|
||||||
void OnAncestryChanged(nullable std::shared_ptr<Instance> child, nullable std::shared_ptr<Instance> newParent) override;
|
void OnAncestryChanged(nullable std::shared_ptr<Instance> child, nullable std::shared_ptr<Instance> newParent) override;
|
||||||
void onUpdated(std::string);
|
void onUpdated(std::string);
|
||||||
|
void onParamUpdated(std::string);
|
||||||
|
|
||||||
BasePart(const InstanceType*);
|
BasePart(const InstanceType*);
|
||||||
BasePart(const InstanceType*, PartConstructParams params);
|
BasePart(const InstanceType*, PartConstructParams params);
|
||||||
public:
|
public:
|
||||||
DEF_PROP_CATEGORY(DATA)
|
DEF_PROP_CATEGORY(DATA)
|
||||||
DEF_PROP_(on_update=onUpdated) Vector3 velocity;
|
DEF_PROP_PHYS Vector3 velocity;
|
||||||
[[ def_prop(name="CFrame", on_update=onUpdated), cframe_position_prop(name="Position"), cframe_rotation_prop(name="Rotation") ]]
|
[[ def_prop(name="CFrame", on_update=onUpdated), cframe_position_prop(name="Position"), cframe_rotation_prop(name="Rotation") ]]
|
||||||
CFrame cframe;
|
CFrame cframe;
|
||||||
|
|
||||||
DEF_PROP_CATEGORY(PART)
|
DEF_PROP_CATEGORY(PART)
|
||||||
// Special compatibility changes for this property were made in
|
// Special compatibility changes for this property were made in
|
||||||
// Instance::Serialize
|
// Instance::Serialize
|
||||||
DEF_PROP_(on_update=onUpdated) Vector3 size;
|
DEF_PROP_PHYS Vector3 size;
|
||||||
|
|
||||||
DEF_PROP_CATEGORY(APPEARANCE)
|
DEF_PROP_CATEGORY(APPEARANCE)
|
||||||
DEF_PROP Color3 color;
|
DEF_PROP Color3 color;
|
||||||
|
@ -71,8 +76,8 @@ public:
|
||||||
DEF_PROP float reflectance = 0.f;
|
DEF_PROP float reflectance = 0.f;
|
||||||
|
|
||||||
DEF_PROP_CATEGORY(BEHAVIOR)
|
DEF_PROP_CATEGORY(BEHAVIOR)
|
||||||
DEF_PROP_(on_update=onUpdated) bool anchored = false;
|
DEF_PROP_PHYS bool anchored = false;
|
||||||
DEF_PROP_(on_update=onUpdated) bool canCollide = true;
|
DEF_PROP_PHYS bool canCollide = true;
|
||||||
DEF_PROP bool locked = false;
|
DEF_PROP bool locked = false;
|
||||||
|
|
||||||
DEF_PROP_CATEGORY(SURFACE)
|
DEF_PROP_CATEGORY(SURFACE)
|
||||||
|
@ -84,19 +89,19 @@ public:
|
||||||
DEF_PROP SurfaceType backSurface = SurfaceType::Smooth;
|
DEF_PROP SurfaceType backSurface = SurfaceType::Smooth;
|
||||||
|
|
||||||
DEF_PROP_CATEGORY(SURFACE_INPUT)
|
DEF_PROP_CATEGORY(SURFACE_INPUT)
|
||||||
DEF_PROP float topParamA = -0.5;
|
DEF_PROP_PHYSPARAM float topParamA = -0.5;
|
||||||
DEF_PROP float bottomParamA = -0.5;
|
DEF_PROP_PHYSPARAM float bottomParamA = -0.5;
|
||||||
DEF_PROP float leftParamA = -0.5;
|
DEF_PROP_PHYSPARAM float leftParamA = -0.5;
|
||||||
DEF_PROP float rightParamA = -0.5;
|
DEF_PROP_PHYSPARAM float rightParamA = -0.5;
|
||||||
DEF_PROP float frontParamA = -0.5;
|
DEF_PROP_PHYSPARAM float frontParamA = -0.5;
|
||||||
DEF_PROP float backParamA = -0.5;
|
DEF_PROP_PHYSPARAM float backParamA = -0.5;
|
||||||
|
|
||||||
DEF_PROP float topParamB = 0.5;
|
DEF_PROP_PHYSPARAM float topParamB = 0.5;
|
||||||
DEF_PROP float bottomParamB = 0.5;
|
DEF_PROP_PHYSPARAM float bottomParamB = 0.5;
|
||||||
DEF_PROP float leftParamB = 0.5;
|
DEF_PROP_PHYSPARAM float leftParamB = 0.5;
|
||||||
DEF_PROP float rightParamB = 0.5;
|
DEF_PROP_PHYSPARAM float rightParamB = 0.5;
|
||||||
DEF_PROP float frontParamB = 0.5;
|
DEF_PROP_PHYSPARAM float frontParamB = 0.5;
|
||||||
DEF_PROP float backParamB = 0.5;
|
DEF_PROP_PHYSPARAM float backParamB = 0.5;
|
||||||
|
|
||||||
DEF_SIGNAL SignalSource Touched;
|
DEF_SIGNAL SignalSource Touched;
|
||||||
DEF_SIGNAL SignalSource TouchEnded;
|
DEF_SIGNAL SignalSource TouchEnded;
|
||||||
|
@ -118,3 +123,6 @@ public:
|
||||||
// Calculate size of axis-aligned bounding box
|
// Calculate size of axis-aligned bounding box
|
||||||
Vector3 GetAABB();
|
Vector3 GetAABB();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#undef DEF_PROP_PHYS
|
||||||
|
#undef DEF_PROP_PHYSPARAM
|
|
@ -229,9 +229,8 @@ PhysJoint PhysWorld::createJoint(PhysJointInfo& type, std::shared_ptr<BasePart>
|
||||||
// settings.mMotorSettings = JPH::MotorSettings(1.0f, 1.0f);
|
// settings.mMotorSettings = JPH::MotorSettings(1.0f, 1.0f);
|
||||||
constraint = settings.Create(*part0->rigidBody.bodyImpl, *part1->rigidBody.bodyImpl);
|
constraint = settings.Create(*part0->rigidBody.bodyImpl, *part1->rigidBody.bodyImpl);
|
||||||
if (info->motorized) {
|
if (info->motorized) {
|
||||||
float vel = part0->GetSurfaceParamB(-info->c0.LookVector().Unit()) * 6.28;
|
|
||||||
static_cast<JPH::HingeConstraint*>(constraint)->SetMotorState(JPH::EMotorState::Velocity);
|
static_cast<JPH::HingeConstraint*>(constraint)->SetMotorState(JPH::EMotorState::Velocity);
|
||||||
static_cast<JPH::HingeConstraint*>(constraint)->SetTargetAngularVelocity(-vel);
|
static_cast<JPH::HingeConstraint*>(constraint)->SetTargetAngularVelocity(-info->initialVelocity);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
panic();
|
panic();
|
||||||
|
@ -241,6 +240,14 @@ PhysJoint PhysWorld::createJoint(PhysJointInfo& type, std::shared_ptr<BasePart>
|
||||||
return { constraint };
|
return { constraint };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WATCH OUT! This should only be called for HingeConstraints.
|
||||||
|
// Can't use dynamic_cast because TwoBodyConstraint is not virtual
|
||||||
|
void PhysJoint::setAngularVelocity(float velocity) {
|
||||||
|
JPH::HingeConstraint* constraint = static_cast<JPH::HingeConstraint*>(jointImpl);
|
||||||
|
if (!constraint) return;
|
||||||
|
constraint->SetTargetAngularVelocity(-velocity);
|
||||||
|
}
|
||||||
|
|
||||||
void PhysWorld::destroyJoint(PhysJoint joint) {
|
void PhysWorld::destroyJoint(PhysJoint joint) {
|
||||||
worldImpl.RemoveConstraint(joint.jointImpl);
|
worldImpl.RemoveConstraint(joint.jointImpl);
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,13 +17,30 @@ class BasePart;
|
||||||
class PhysWorld;
|
class PhysWorld;
|
||||||
|
|
||||||
struct PhysJointInfo { virtual ~PhysJointInfo() = default; protected: PhysJointInfo() = default; };
|
struct PhysJointInfo { virtual ~PhysJointInfo() = default; protected: PhysJointInfo() = default; };
|
||||||
struct PhysFixedJointInfo : PhysJointInfo { CFrame c0; CFrame c1; inline PhysFixedJointInfo(CFrame c0, CFrame c1) : c0(c0), c1(c1) {} };
|
|
||||||
struct PhysRotatingJointInfo : PhysJointInfo { CFrame c0; CFrame c1; bool motorized; inline PhysRotatingJointInfo(CFrame c0, CFrame c1, bool motorized = false) : c0(c0), c1(c1), motorized(motorized) {} };
|
struct PhysFixedJointInfo : PhysJointInfo {
|
||||||
|
CFrame c0;
|
||||||
|
CFrame c1;
|
||||||
|
|
||||||
|
inline PhysFixedJointInfo(CFrame c0, CFrame c1) : c0(c0), c1(c1) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PhysRotatingJointInfo : PhysJointInfo {
|
||||||
|
CFrame c0;
|
||||||
|
CFrame c1;
|
||||||
|
bool motorized;
|
||||||
|
float initialVelocity;
|
||||||
|
|
||||||
|
inline PhysRotatingJointInfo(CFrame c0, CFrame c1) : c0(c0), c1(c1), motorized(false), initialVelocity(0.f){}
|
||||||
|
inline PhysRotatingJointInfo(CFrame c0, CFrame c1, float initialVelocity) : c0(c0), c1(c1), motorized(true), initialVelocity(initialVelocity) {}
|
||||||
|
};
|
||||||
|
|
||||||
class PhysWorld;
|
class PhysWorld;
|
||||||
struct PhysJoint {
|
struct PhysJoint {
|
||||||
public:
|
public:
|
||||||
JPH::TwoBodyConstraint* jointImpl;
|
JPH::TwoBodyConstraint* jointImpl;
|
||||||
|
|
||||||
|
void setAngularVelocity(float velocity);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct RaycastResult;
|
struct RaycastResult;
|
||||||
|
|
Loading…
Add table
Reference in a new issue