diff --git a/core/src/objects/joint/jointinstance.cpp b/core/src/objects/joint/jointinstance.cpp index a8c1364..dc7cbec 100644 --- a/core/src/objects/joint/jointinstance.cpp +++ b/core/src/objects/joint/jointinstance.cpp @@ -17,6 +17,9 @@ void JointInstance::OnAncestryChanged(nullable std::shared_ptr, nullab Update(); } +void JointInstance::OnPartParamsUpdated() { +} + void JointInstance::Update() { // 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 diff --git a/core/src/objects/joint/jointinstance.h b/core/src/objects/joint/jointinstance.h index 95bec5d..e06b1c2 100644 --- a/core/src/objects/joint/jointinstance.h +++ b/core/src/objects/joint/jointinstance.h @@ -3,7 +3,6 @@ #include "objects/base/instance.h" #include "../annotation.h" #include -#include #include "datatypes/cframe.h" #include "physics/world.h" @@ -12,6 +11,8 @@ #include "objects/part/part.h" #endif +#define DEF_PROP_PHYS DEF_PROP_(on_update=onUpdated) + class BasePart; class Workspace; @@ -33,12 +34,15 @@ protected: virtual void buildJoint() = 0; public: void Update(); + virtual void OnPartParamsUpdated(); - DEF_PROP_(on_update=onUpdated) std::weak_ptr part0; - DEF_PROP_(on_update=onUpdated) std::weak_ptr part1; - DEF_PROP_(on_update=onUpdated) CFrame c0; - DEF_PROP_(on_update=onUpdated) CFrame c1; + DEF_PROP_PHYS std::weak_ptr part0; + DEF_PROP_PHYS std::weak_ptr part1; + DEF_PROP_PHYS CFrame c0; + DEF_PROP_PHYS CFrame c1; JointInstance(const InstanceType*); ~JointInstance(); -}; \ No newline at end of file +}; + +#undef DEF_PROP_PHYS \ No newline at end of file diff --git a/core/src/objects/joint/rotatev.cpp b/core/src/objects/joint/rotatev.cpp index c049814..669913b 100644 --- a/core/src/objects/joint/rotatev.cpp +++ b/core/src/objects/joint/rotatev.cpp @@ -21,8 +21,14 @@ void RotateV::buildJoint() { CFrame newFrame = part0.lock()->cframe * (c0 * c1.Inverse()); part1.lock()->cframe = newFrame; // 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()); jointWorkspace = workspace; +} + +void RotateV::OnPartParamsUpdated() { + float vel = part0.lock()->GetSurfaceParamB(-c0.LookVector().Unit()) * 6.28; + this->joint.setAngularVelocity(vel); } \ No newline at end of file diff --git a/core/src/objects/joint/rotatev.h b/core/src/objects/joint/rotatev.h index 1175244..e53fece 100644 --- a/core/src/objects/joint/rotatev.h +++ b/core/src/objects/joint/rotatev.h @@ -13,6 +13,8 @@ public: RotateV(); ~RotateV(); + void OnPartParamsUpdated() override; + static inline std::shared_ptr New() { return std::make_shared(); }; static inline std::shared_ptr Create() { return std::make_shared(); }; }; \ No newline at end of file diff --git a/core/src/objects/part/basepart.cpp b/core/src/objects/part/basepart.cpp index 5e770f2..ee15df8 100644 --- a/core/src/objects/part/basepart.cpp +++ b/core/src/objects/part/basepart.cpp @@ -70,6 +70,15 @@ void BasePart::onUpdated(std::string property) { BreakJoints(); } +void BasePart::onParamUpdated(std::string property) { + // Send signal to joints to update themselves + for (std::weak_ptr joint : primaryJoints) { + if (joint.expired()) continue; + + joint.lock()->OnPartParamsUpdated(); + } +} + // Expands provided extents to fit 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())); diff --git a/core/src/objects/part/basepart.h b/core/src/objects/part/basepart.h index 5da89d0..6b9cc52 100644 --- a/core/src/objects/part/basepart.h +++ b/core/src/objects/part/basepart.h @@ -14,6 +14,10 @@ #include "objects/pvinstance.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? struct PartConstructParams { Vector3 position; @@ -51,19 +55,20 @@ protected: virtual void OnWorkspaceRemoved(std::shared_ptr oldWorkspace) override; void OnAncestryChanged(nullable std::shared_ptr child, nullable std::shared_ptr newParent) override; void onUpdated(std::string); + void onParamUpdated(std::string); BasePart(const InstanceType*); BasePart(const InstanceType*, PartConstructParams params); public: 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") ]] CFrame cframe; DEF_PROP_CATEGORY(PART) // Special compatibility changes for this property were made in // Instance::Serialize - DEF_PROP_(on_update=onUpdated) Vector3 size; + DEF_PROP_PHYS Vector3 size; DEF_PROP_CATEGORY(APPEARANCE) DEF_PROP Color3 color; @@ -71,8 +76,8 @@ public: DEF_PROP float reflectance = 0.f; DEF_PROP_CATEGORY(BEHAVIOR) - DEF_PROP_(on_update=onUpdated) bool anchored = false; - DEF_PROP_(on_update=onUpdated) bool canCollide = true; + DEF_PROP_PHYS bool anchored = false; + DEF_PROP_PHYS bool canCollide = true; DEF_PROP bool locked = false; DEF_PROP_CATEGORY(SURFACE) @@ -84,19 +89,19 @@ public: DEF_PROP SurfaceType backSurface = SurfaceType::Smooth; DEF_PROP_CATEGORY(SURFACE_INPUT) - DEF_PROP float topParamA = -0.5; - DEF_PROP float bottomParamA = -0.5; - DEF_PROP float leftParamA = -0.5; - DEF_PROP float rightParamA = -0.5; - DEF_PROP float frontParamA = -0.5; - DEF_PROP float backParamA = -0.5; + DEF_PROP_PHYSPARAM float topParamA = -0.5; + DEF_PROP_PHYSPARAM float bottomParamA = -0.5; + DEF_PROP_PHYSPARAM float leftParamA = -0.5; + DEF_PROP_PHYSPARAM float rightParamA = -0.5; + DEF_PROP_PHYSPARAM float frontParamA = -0.5; + DEF_PROP_PHYSPARAM float backParamA = -0.5; - DEF_PROP float topParamB = 0.5; - DEF_PROP float bottomParamB = 0.5; - DEF_PROP float leftParamB = 0.5; - DEF_PROP float rightParamB = 0.5; - DEF_PROP float frontParamB = 0.5; - DEF_PROP float backParamB = 0.5; + DEF_PROP_PHYSPARAM float topParamB = 0.5; + DEF_PROP_PHYSPARAM float bottomParamB = 0.5; + DEF_PROP_PHYSPARAM float leftParamB = 0.5; + DEF_PROP_PHYSPARAM float rightParamB = 0.5; + DEF_PROP_PHYSPARAM float frontParamB = 0.5; + DEF_PROP_PHYSPARAM float backParamB = 0.5; DEF_SIGNAL SignalSource Touched; DEF_SIGNAL SignalSource TouchEnded; @@ -117,4 +122,7 @@ public: // Calculate size of axis-aligned bounding box Vector3 GetAABB(); -}; \ No newline at end of file +}; + +#undef DEF_PROP_PHYS +#undef DEF_PROP_PHYSPARAM \ No newline at end of file diff --git a/core/src/physics/world.cpp b/core/src/physics/world.cpp index e3697d7..06f3ab0 100644 --- a/core/src/physics/world.cpp +++ b/core/src/physics/world.cpp @@ -229,9 +229,8 @@ PhysJoint PhysWorld::createJoint(PhysJointInfo& type, std::shared_ptr // settings.mMotorSettings = JPH::MotorSettings(1.0f, 1.0f); constraint = settings.Create(*part0->rigidBody.bodyImpl, *part1->rigidBody.bodyImpl); if (info->motorized) { - float vel = part0->GetSurfaceParamB(-info->c0.LookVector().Unit()) * 6.28; static_cast(constraint)->SetMotorState(JPH::EMotorState::Velocity); - static_cast(constraint)->SetTargetAngularVelocity(-vel); + static_cast(constraint)->SetTargetAngularVelocity(-info->initialVelocity); } } else { panic(); @@ -241,6 +240,14 @@ PhysJoint PhysWorld::createJoint(PhysJointInfo& type, std::shared_ptr 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(jointImpl); + if (!constraint) return; + constraint->SetTargetAngularVelocity(-velocity); +} + void PhysWorld::destroyJoint(PhysJoint joint) { worldImpl.RemoveConstraint(joint.jointImpl); } diff --git a/core/src/physics/world.h b/core/src/physics/world.h index 231457f..5612555 100644 --- a/core/src/physics/world.h +++ b/core/src/physics/world.h @@ -17,13 +17,30 @@ class BasePart; class PhysWorld; 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; struct PhysJoint { public: JPH::TwoBodyConstraint* jointImpl; + + void setAngularVelocity(float velocity); }; struct RaycastResult;