mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 11:45:36 +02:00
attempt to make hinge motor work better
This commit is contained in:
parent
17b83dd64c
commit
59950236d3
2 changed files with 144 additions and 9 deletions
|
@ -48,6 +48,50 @@ QList<btRigidBody*> ObjectConstraintHinge::getRigidBodies() {
|
|||
return result;
|
||||
}
|
||||
|
||||
void ObjectConstraintHinge::prepareForPhysicsSimulation() {
|
||||
// setting the motor velocity doesn't appear to work for anyone. constantly adjusting the
|
||||
// target angle seems to work.
|
||||
// https://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?f=9&t=7020
|
||||
uint64_t now = usecTimestampNow();
|
||||
withWriteLock([&]{
|
||||
btHingeConstraint* constraint = static_cast<btHingeConstraint*>(_constraint);
|
||||
if (!constraint) {
|
||||
return;
|
||||
}
|
||||
if (_previousMotorTime == 0) {
|
||||
_previousMotorTime = now;
|
||||
return;
|
||||
}
|
||||
if (_motorVelocity != 0.0f) {
|
||||
if (_startMotorTime == 0) {
|
||||
_startMotorTime = now;
|
||||
}
|
||||
float dt = (float)(now - _previousMotorTime) / (float)USECS_PER_SECOND;
|
||||
float t = (float)(now - _startMotorTime) / (float)USECS_PER_SECOND;
|
||||
float motorTarget = _motorVelocity * t;
|
||||
while (motorTarget > PI) {
|
||||
motorTarget -= PI;
|
||||
}
|
||||
while (motorTarget < PI) {
|
||||
motorTarget += PI;
|
||||
}
|
||||
if (!_motorEnabled) {
|
||||
constraint->enableMotor(true);
|
||||
_motorEnabled = true;
|
||||
}
|
||||
constraint->setMaxMotorImpulse(_maxImpulse);
|
||||
constraint->setMotorTarget(motorTarget, dt);
|
||||
} else if (_motorTargetTimeScale > 0.0f) {
|
||||
// XXX
|
||||
} else if (_motorEnabled) {
|
||||
constraint->enableMotor(false);
|
||||
_motorEnabled = false;
|
||||
_startMotorTime = 0;
|
||||
}
|
||||
_previousMotorTime = now;
|
||||
});
|
||||
}
|
||||
|
||||
void ObjectConstraintHinge::updateHinge() {
|
||||
btHingeConstraint* constraint { nullptr };
|
||||
float low;
|
||||
|
@ -56,28 +100,45 @@ void ObjectConstraintHinge::updateHinge() {
|
|||
float biasFactor;
|
||||
float relaxationFactor;
|
||||
float motorVelocity;
|
||||
float motorTarget;
|
||||
float motorTargetTimeScale;
|
||||
float maxImpulse;
|
||||
|
||||
withReadLock([&]{
|
||||
constraint = static_cast<btHingeConstraint*>(_constraint);
|
||||
low = _low;
|
||||
high = _high;
|
||||
softness = _softness;
|
||||
maxImpulse = _maxImpulse;
|
||||
biasFactor = _biasFactor;
|
||||
relaxationFactor = _relaxationFactor;
|
||||
|
||||
// under the hood, motorTarget sets a veloctiy and must be called repeatedly to maintain
|
||||
// a velocity. _motorTargetTimeScale of 0.0f means the target isn't set. motorVelocity is
|
||||
// only considered when motorTarget isn't set.
|
||||
motorVelocity = _motorVelocity;
|
||||
motorTarget = _motorTarget;
|
||||
motorTargetTimeScale = _motorTargetTimeScale;
|
||||
softness = _softness;
|
||||
});
|
||||
|
||||
if (!constraint) {
|
||||
return;
|
||||
}
|
||||
|
||||
constraint->setLimit(low, high, softness, biasFactor, relaxationFactor);
|
||||
if (motorVelocity != 0.0f) {
|
||||
constraint->setMotorTargetVelocity(motorVelocity);
|
||||
constraint->enableMotor(true);
|
||||
} else {
|
||||
constraint->enableMotor(false);
|
||||
}
|
||||
// constraint->setLimit(low, high, softness, biasFactor, relaxationFactor);
|
||||
// if (motorTargetTimeScale > 0.0f) {
|
||||
// qDebug() << "--- setting motor target:" << motorTarget << motorTargetTimeScale;
|
||||
// constraint->setMotorTarget(motorTarget, motorTargetTimeScale);
|
||||
// constraint->enableMotor(true);
|
||||
// withWriteLock([&]{
|
||||
// _motorTargetTimeScale = 0.0f; // it's a one-shot.
|
||||
// });
|
||||
// } else if (motorVelocity != 0.0f) {
|
||||
// // constraint->setMotorTargetVelocity(motorVelocity);
|
||||
// // constraint->enableMotor(true);
|
||||
// } else {
|
||||
// constraint->enableMotor(false);
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
|
@ -151,6 +212,9 @@ bool ObjectConstraintHinge::updateArguments(QVariantMap arguments) {
|
|||
float biasFactor;
|
||||
float relaxationFactor;
|
||||
float motorVelocity;
|
||||
float motorTarget;
|
||||
float motorTargetTimeScale;
|
||||
float maxImpulse;
|
||||
|
||||
bool needUpdate = false;
|
||||
bool somethingChanged = ObjectDynamic::updateArguments(arguments);
|
||||
|
@ -224,6 +288,27 @@ bool ObjectConstraintHinge::updateArguments(QVariantMap arguments) {
|
|||
motorVelocity = _motorVelocity;
|
||||
}
|
||||
|
||||
ok = true;
|
||||
motorTarget = EntityDynamicInterface::extractFloatArgument("hinge constraint", arguments,
|
||||
"motorTarget", ok, false);
|
||||
if (!ok) {
|
||||
motorTarget = _motorTarget;
|
||||
}
|
||||
|
||||
ok = true;
|
||||
motorTargetTimeScale = EntityDynamicInterface::extractFloatArgument("hinge constraint", arguments,
|
||||
"motorTargetTimeScale", ok, false);
|
||||
if (!ok) {
|
||||
motorTargetTimeScale = _motorTargetTimeScale;
|
||||
}
|
||||
|
||||
ok = true;
|
||||
maxImpulse = EntityDynamicInterface::extractFloatArgument("hinge constraint", arguments, "maxImpulse", ok, false);
|
||||
if (!ok) {
|
||||
maxImpulse = _maxImpulse;
|
||||
}
|
||||
|
||||
|
||||
if (somethingChanged ||
|
||||
pivotInA != _pivotInA ||
|
||||
axisInA != _axisInA ||
|
||||
|
@ -235,7 +320,10 @@ bool ObjectConstraintHinge::updateArguments(QVariantMap arguments) {
|
|||
softness != _softness ||
|
||||
biasFactor != _biasFactor ||
|
||||
relaxationFactor != _relaxationFactor ||
|
||||
motorVelocity != _motorVelocity) {
|
||||
motorVelocity != _motorVelocity ||
|
||||
motorTarget != _motorTarget ||
|
||||
motorTargetTimeScale != _motorTargetTimeScale ||
|
||||
maxImpulse != _maxImpulse) {
|
||||
// something changed
|
||||
needUpdate = true;
|
||||
}
|
||||
|
@ -254,6 +342,9 @@ bool ObjectConstraintHinge::updateArguments(QVariantMap arguments) {
|
|||
_biasFactor = biasFactor;
|
||||
_relaxationFactor = relaxationFactor;
|
||||
_motorVelocity = motorVelocity;
|
||||
_motorTarget = motorTarget;
|
||||
_motorTargetTimeScale = motorTargetTimeScale;
|
||||
_maxImpulse = maxImpulse;
|
||||
|
||||
_active = true;
|
||||
|
||||
|
@ -285,6 +376,9 @@ QVariantMap ObjectConstraintHinge::getArguments() {
|
|||
arguments["biasFactor"] = _biasFactor;
|
||||
arguments["relaxationFactor"] = _relaxationFactor;
|
||||
arguments["motorVelocity"] = _motorVelocity;
|
||||
arguments["motorTarget"] = _motorTarget;
|
||||
arguments["motorTargetTimeScale"] = _motorTargetTimeScale;
|
||||
arguments["maxImpulse"] = _maxImpulse;
|
||||
arguments["angle"] = static_cast<btHingeConstraint*>(_constraint)->getHingeAngle(); // [-PI,PI]
|
||||
}
|
||||
});
|
||||
|
@ -315,6 +409,9 @@ QByteArray ObjectConstraintHinge::serialize() const {
|
|||
dataStream << _tag;
|
||||
|
||||
dataStream << _motorVelocity;
|
||||
dataStream << _motorTarget;
|
||||
dataStream << _motorTargetTimeScale;
|
||||
dataStream << _maxImpulse;
|
||||
});
|
||||
|
||||
return serializedConstraintArguments;
|
||||
|
@ -357,6 +454,9 @@ void ObjectConstraintHinge::deserialize(QByteArray serializedArguments) {
|
|||
dataStream >> _tag;
|
||||
|
||||
dataStream >> _motorVelocity;
|
||||
dataStream >> _motorTarget;
|
||||
dataStream >> _motorTargetTimeScale;
|
||||
dataStream >> _maxImpulse;
|
||||
|
||||
_active = true;
|
||||
});
|
||||
|
|
|
@ -21,6 +21,8 @@ public:
|
|||
ObjectConstraintHinge(const QUuid& id, EntityItemPointer ownerEntity);
|
||||
virtual ~ObjectConstraintHinge();
|
||||
|
||||
virtual void prepareForPhysicsSimulation() override;
|
||||
|
||||
virtual bool updateArguments(QVariantMap arguments) override;
|
||||
virtual QVariantMap getArguments() override;
|
||||
|
||||
|
@ -44,10 +46,43 @@ protected:
|
|||
|
||||
float _low { -2.0f * PI };
|
||||
float _high { 2.0f * PI };
|
||||
|
||||
// https://gamedev.stackexchange.com/questions/71436/what-are-the-parameters-for-bthingeconstraintsetlimit
|
||||
//
|
||||
// softness: a negative measure of the friction that determines how much the hinge rotates for a given force. A high
|
||||
// softness would make the hinge rotate easily like it's oiled then.
|
||||
// biasFactor: an offset for the relaxed rotation of the hinge. It won't be right in the middle of the low and high angles
|
||||
// anymore. 1.0f is the neural value.
|
||||
// relaxationFactor: a measure of how much force is applied internally to bring the hinge in its central rotation.
|
||||
// This is right in the middle of the low and high angles. For example, consider a western swing door. After
|
||||
// walking through it will swing in both directions but at the end it stays right in the middle.
|
||||
|
||||
// http://javadoc.jmonkeyengine.org/com/jme3/bullet/joints/HingeJoint.html
|
||||
//
|
||||
// _softness - the factor at which the velocity error correction starts operating, i.e. a softness of 0.9 means that
|
||||
// the vel. corr starts at 90% of the limit range.
|
||||
// _biasFactor - the magnitude of the position correction. It tells you how strictly the position error (drift) is
|
||||
// corrected.
|
||||
// _relaxationFactor - the rate at which velocity errors are corrected. This can be seen as the strength of the
|
||||
// limits. A low value will make the the limits more spongy.
|
||||
|
||||
|
||||
float _maxImpulse { 1.0f };
|
||||
|
||||
float _softness { 0.9f };
|
||||
|
||||
float _biasFactor { 0.3f };
|
||||
|
||||
float _relaxationFactor { 1.0f };
|
||||
|
||||
float _motorVelocity { 0.0f };
|
||||
float _motorTarget { 0.0f };
|
||||
float _motorTargetTimeScale { 0.0f };
|
||||
|
||||
uint64_t _startMotorTime { 0 };
|
||||
uint64_t _previousMotorTime { 0 };
|
||||
|
||||
bool _motorEnabled { false };
|
||||
};
|
||||
|
||||
#endif // hifi_ObjectConstraintHinge_h
|
||||
|
|
Loading…
Reference in a new issue