fix update logic of ObjectActionOffset

This commit is contained in:
Andrew Meadows 2015-07-09 11:32:30 -07:00
parent 46bca30698
commit 612e9649d8
2 changed files with 61 additions and 44 deletions

View file

@ -16,7 +16,11 @@
const uint16_t ObjectActionOffset::offsetVersion = 1; const uint16_t ObjectActionOffset::offsetVersion = 1;
ObjectActionOffset::ObjectActionOffset(const QUuid& id, EntityItemPointer ownerEntity) : ObjectActionOffset::ObjectActionOffset(const QUuid& id, EntityItemPointer ownerEntity) :
ObjectAction(ACTION_TYPE_OFFSET, id, ownerEntity) { ObjectAction(ACTION_TYPE_OFFSET, id, ownerEntity),
_pointToOffsetFrom(0.f),
_linearDistance(0.0f),
_linearTimeScale(FLT_MAX),
_positionalTargetSet(false) {
#if WANT_DEBUG #if WANT_DEBUG
qDebug() << "ObjectActionOffset::ObjectActionOffset"; qDebug() << "ObjectActionOffset::ObjectActionOffset";
#endif #endif
@ -44,6 +48,7 @@ void ObjectActionOffset::updateActionWorker(btScalar deltaTimeStep) {
unlock(); unlock();
return; return;
} }
ObjectMotionState* motionState = static_cast<ObjectMotionState*>(physicsInfo); ObjectMotionState* motionState = static_cast<ObjectMotionState*>(physicsInfo);
btRigidBody* rigidBody = motionState->getRigidBody(); btRigidBody* rigidBody = motionState->getRigidBody();
if (!rigidBody) { if (!rigidBody) {
@ -52,21 +57,32 @@ void ObjectActionOffset::updateActionWorker(btScalar deltaTimeStep) {
return; return;
} }
if (_positionalTargetSet) { const float MAX_LINEAR_TIMESCALE = 600.0f; // 10 minutes is a long time
glm::vec3 offset = _pointToOffsetFrom - bulletToGLM(rigidBody->getCenterOfMassPosition()); if (_positionalTargetSet && _linearTimeScale < MAX_LINEAR_TIMESCALE) {
float offsetLength = glm::length(offset); if (_needsActivation) {
float offsetError = _linearDistance - offsetLength;
// if (glm::abs(offsetError) > IGNORE_POSITION_DELTA) {
if (glm::abs(offsetError) > 0.0f) {
float offsetErrorAbs = glm::abs(offsetError);
float offsetErrorDirection = - offsetError / offsetErrorAbs;
glm::vec3 previousVelocity = bulletToGLM(rigidBody->getLinearVelocity());
glm::vec3 velocityAdjustment = glm::normalize(offset) * offsetErrorDirection * offsetErrorAbs / _linearTimeScale;
rigidBody->setLinearVelocity(glmToBullet(previousVelocity + velocityAdjustment));
// rigidBody->setLinearVelocity(glmToBullet(velocityAdjustment));
rigidBody->activate(); rigidBody->activate();
_needsActivation = false;
}
glm::vec3 objectPosition = bulletToGLM(rigidBody->getCenterOfMassPosition());
glm::vec3 springAxis = objectPosition - _pointToOffsetFrom; // from anchor to object
float distance = glm::length(springAxis);
if (distance > FLT_EPSILON) {
springAxis /= distance; // normalize springAxis
// compute (critically damped) target velocity of spring relaxation
glm::vec3 offset = (distance - _linearDistance) * springAxis;
glm::vec3 targetVelocity = (-1.0f / _linearTimeScale) * offset;
// compute current velocity and its parallel component
glm::vec3 currentVelocity = bulletToGLM(rigidBody->getLinearVelocity());
glm::vec3 parallelVelocity = glm::dot(currentVelocity, springAxis) * springAxis;
// we blend the parallel component with the spring's target velocity to get the new velocity
float blend = deltaTimeStep / _linearTimeScale;
if (blend > 1.0f) {
blend = 1.0f;
}
rigidBody->setLinearVelocity(glmToBullet(currentVelocity + blend * (targetVelocity - parallelVelocity));
} }
} }
@ -75,45 +91,45 @@ void ObjectActionOffset::updateActionWorker(btScalar deltaTimeStep) {
bool ObjectActionOffset::updateArguments(QVariantMap arguments) { bool ObjectActionOffset::updateArguments(QVariantMap arguments) {
bool pOk0 = true; bool ok = true;
glm::vec3 pointToOffsetFrom = glm::vec3 pointToOffsetFrom =
EntityActionInterface::extractVec3Argument("offset action", arguments, "pointToOffsetFrom", pOk0, true); EntityActionInterface::extractVec3Argument("offset action", arguments, "pointToOffsetFrom", ok, true);
if (!ok) {
return false;
}
bool pOk1 = true; ok = true;
float linearTimeScale = float linearTimeScale =
EntityActionInterface::extractFloatArgument("offset action", arguments, "linearTimeScale", pOk1, false); EntityActionInterface::extractFloatArgument("offset action", arguments, "linearTimeScale", ok, false);
if (ok) {
if (linearTimeScale <= 0.0f) {
qDebug() << "offset action -- linearTimeScale must be greater than zero.";
return false;
}
} else {
linearTimeScale = 0.1f;
}
bool pOk2 = true; ok = true;
float linearDistance = float linearDistance =
EntityActionInterface::extractFloatArgument("offset action", arguments, "linearDistance", pOk2, false); EntityActionInterface::extractFloatArgument("offset action", arguments, "linearDistance", ok, false);
if (!ok) {
if (!pOk0) { linearDistance = 0.0f;
return false;
}
if (pOk1 && linearTimeScale <= 0.0f) {
qDebug() << "offset action -- linearTimeScale must be greater than zero.";
return false;
} }
lockForWrite(); // only change stuff if something actually changed
if (_pointToOffsetFrom != pointToOffsetFrom
_pointToOffsetFrom = pointToOffsetFrom; || _linearTimeScale != linearTimeScale
_positionalTargetSet = true; || _linearDistance != linearDistance) {
lockForWrite();
if (pOk1) { _pointToOffsetFrom = pointToOffsetFrom;
_linearTimeScale = linearTimeScale; _linearTimeScale = linearTimeScale;
} else {
_linearTimeScale = 0.1f;
}
if (pOk2) {
_linearDistance = linearDistance; _linearDistance = linearDistance;
} else { _positionalTargetSet = true;
_linearDistance = 1.0f; _active = true;
_needsActivation = true;
unlock();
} }
_active = true;
unlock();
return true; return true;
} }

View file

@ -36,6 +36,7 @@ public:
float _linearDistance; float _linearDistance;
float _linearTimeScale; float _linearTimeScale;
bool _positionalTargetSet; bool _positionalTargetSet;
bool _needsActivation = true;
}; };
#endif // hifi_ObjectActionOffset_h #endif // hifi_ObjectActionOffset_h