Files
2025-09-18 17:55:52 -04:00

212 lines
4.9 KiB
C++

#include "stdafx.h"
#include "V8Kernel/Connector.h"
#include "V8Kernel/Point.h"
#include "V8Kernel/Constants.h"
#include "V8Kernel/Body.h"
#include "Util/Math.h"
namespace RBX {
bool Connector::computeCanThrottle()
{
return (getBody(body0)->getCanThrottle() && getBody(body1)->getCanThrottle());
}
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
void PointToPointBreakConnector::forceToPoints(const G3D::Vector3& force)
{
point0->accumulateForce(-force);
point1->accumulateForce(force);
RBXASSERT_SLOW(force.magnitude() < Math::inf());
}
Body* PointToPointBreakConnector::getBody(BodyIndex id)
{
return (id == body0) ? point0->getBody() : point1->getBody();
}
/////////////////////////////////////////////////
RotateConnector::RotateConnector(
Body* _b0,
Body* _b1,
const CoordinateFrame& _j0,
const CoordinateFrame& _j1,
float _baseAngle,
float kValue,
float armLength)
: b0(_b0)
, b1(_b1)
, j0(_j0)
, j1(_j1)
, baseRotation(_baseAngle)
, k(kValue * armLength * armLength)
, currentAngle(0.0f)
, desiredAngle(0.0f)
, increment(0.0f)
, zeroVelocity(false)
{
reset();
}
void RotateConnector::reset() // occurs after networking read;
{
Vector3 tempNormal;
desiredAngle = computeNormalRotationFromBase(tempNormal); // reset to match current rotation
}
Body* RotateConnector::getBody(BodyIndex id)
{
return (id == body0) ? b0 : b1;
}
float RotateConnector::computeNormalRotationFromBase(Vector3& normal)
{
float angle = computeJointAngle( b0->getCoordinateFrame(),
b1->getCoordinateFrame(),
j0,
j1,
normal);
float answer = angle - baseRotation;
RBXASSERT_FISHING(fabs(answer) <= Math::twoPif());
return answer;
}
float RotateConnector::computeNormalRotationFromBaseFast(Vector3& normal)
{
float angle = computeJointAngle( b0->getCoordinateFrameFast(),
b1->getCoordinateFrameFast(),
j0,
j1,
normal);
float answer = angle - baseRotation;
RBXASSERT(fabs(answer) <= Math::twoPif());
return answer;
}
float RotateConnector::computeJointAngle(const CoordinateFrame& b0,
const CoordinateFrame& b1,
const CoordinateFrame& j0,
const CoordinateFrame& j1,
Vector3& normal)
{
/*
CoordinateFrame j0World = b0 * j0;
CoordinateFrame j1World = b1 * j1;
CoordinateFrame j1Inj0 = j0World.toObjectSpace(j1World);
normal = j0World.rotation.getColumn(2);
float rot = Math::zAxisAngle(j1Inj0);
*/
Matrix3 j0World = b0.rotation * j0.rotation;
Matrix3 j1World = b1.rotation * j1.rotation;
Matrix3 j1Inj0 = j0World.transpose() * j1World;
normal = j0World.column(2);
float rot = Math::zAxisAngle(j1Inj0);
return rot;
}
void RotateConnector::setRotationalGoal(float newGoal)
{
float normalizedGoal = static_cast<float>(Math::radWrap(newGoal));
float deltaRotation = Math::deltaRotationClose(normalizedGoal, desiredAngle);
increment = deltaRotation / Constants::kernelStepsPerWorldStep();
}
void RotateConnector::setVelocityGoal(float velocity)
{
// velocity unit: radian per long ui step
increment = velocity * Constants::longUiStepsPerSec() * Constants::kernelDt();
if (velocity == 0.0)
{
zeroVelocity = true;
}
}
void RotateConnector::stepGoals()
{
if (zeroVelocity)
{
zeroVelocity = false;
desiredAngle = Math::averageRotationClose(currentAngle, desiredAngle);
}
desiredAngle += increment;
}
void RotateConnector::computeForce(bool throttling)
{
Vector3 normal;
currentAngle = computeNormalRotationFromBaseFast(normal); // between -2pi and 2pi
stepGoals(); // between -pi and pi
float deltaRotation = Math::deltaRotationClose(desiredAngle, currentAngle); // between -pi and pi;
RBXASSERT(fabs(deltaRotation) <= Math::pif());
float torqueVal = k * deltaRotation;
Vector3 torque = normal * torqueVal;
b0->accumulateTorque(-torque);
b1->accumulateTorque(torque);
}
/////////////////////////////////////////////////
float PointToPointBreakConnector::potentialEnergy()
{
Vector3 delta = point1->getWorldPos() - point0->getWorldPos();
float length = delta.length();
return length * length * k * 0.5f;
}
void PointToPointBreakConnector::computeForce(bool throttling)
{
Vector3 force = -k * (point1->getWorldPos() - point0->getWorldPos());
float mag = Math::taxiCabMagnitude(force);
forceToPoints(force);
broken = (mag > breakForce);
}
/////////////////////////////////////////////////
// normal direction is "out" from the body surface
// delta = P1 - P0, where P0 is the body with the normal direction
//
void NormalBreakConnector::computeForce(bool throttling)
{
Vector3 normal = Math::getWorldNormal( normalIdBody0,
point0->getBody()->getCoordinateFrameFast().rotation);
Vector3 force = -k * (point1->getWorldPos() - point0->getWorldPos());
float magApart = -normal.dot(force);
forceToPoints(force);
broken = (magApart > breakForce);
}
} // namespace