From b3bc9c3ef05d871b5b6dfc0cc0b2378b2192636e Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 8 Jun 2015 17:10:13 -0700 Subject: [PATCH] first attempt at getting spring-action to handle rotation --- .../entities/src/EntityActionInterface.cpp | 20 ++-- .../entities/src/EntityActionInterface.h | 9 +- libraries/physics/src/ObjectActionSpring.cpp | 96 +++++++++++-------- libraries/physics/src/ObjectActionSpring.h | 6 +- 4 files changed, 80 insertions(+), 51 deletions(-) diff --git a/libraries/entities/src/EntityActionInterface.cpp b/libraries/entities/src/EntityActionInterface.cpp index d92771fce1..b3e774df96 100644 --- a/libraries/entities/src/EntityActionInterface.cpp +++ b/libraries/entities/src/EntityActionInterface.cpp @@ -44,9 +44,11 @@ QString EntityActionInterface::actionTypeToString(EntityActionType actionType) { } glm::vec3 EntityActionInterface::extractVec3Argument(QString objectName, QVariantMap arguments, - QString argumentName, bool& ok) { + QString argumentName, bool& ok, bool required) { if (!arguments.contains(argumentName)) { - qDebug() << objectName << "requires argument:" << argumentName; + if (required) { + qDebug() << objectName << "requires argument:" << argumentName; + } ok = false; return glm::vec3(); } @@ -86,16 +88,18 @@ glm::vec3 EntityActionInterface::extractVec3Argument(QString objectName, QVarian glm::quat EntityActionInterface::extractQuatArgument(QString objectName, QVariantMap arguments, - QString argumentName, bool& ok) { + QString argumentName, bool& ok, bool required) { if (!arguments.contains(argumentName)) { - qDebug() << objectName << "requires argument:" << argumentName; + if (required) { + qDebug() << objectName << "requires argument:" << argumentName; + } ok = false; return glm::quat(); } QVariant resultV = arguments[argumentName]; if (resultV.type() != (QVariant::Type) QMetaType::QVariantMap) { - qDebug() << objectName << "argument" << argumentName << "must be a map"; + qDebug() << objectName << "argument" << argumentName << "must be a map, not" << resultV.typeName(); ok = false; return glm::quat(); } @@ -133,9 +137,11 @@ glm::quat EntityActionInterface::extractQuatArgument(QString objectName, QVarian float EntityActionInterface::extractFloatArgument(QString objectName, QVariantMap arguments, - QString argumentName, bool& ok) { + QString argumentName, bool& ok, bool required) { if (!arguments.contains(argumentName)) { - qDebug() << objectName << "requires argument:" << argumentName; + if (required) { + qDebug() << objectName << "requires argument:" << argumentName; + } ok = false; return 0.0f; } diff --git a/libraries/entities/src/EntityActionInterface.h b/libraries/entities/src/EntityActionInterface.h index 3baee06c3e..a0a3db9b68 100644 --- a/libraries/entities/src/EntityActionInterface.h +++ b/libraries/entities/src/EntityActionInterface.h @@ -41,9 +41,12 @@ public: protected: - static glm::vec3 extractVec3Argument(QString objectName, QVariantMap arguments, QString argumentName, bool& ok); - static glm::quat extractQuatArgument(QString objectName, QVariantMap arguments, QString argumentName, bool& ok); - static float extractFloatArgument(QString objectName, QVariantMap arguments, QString argumentName, bool& ok); + static glm::vec3 extractVec3Argument (QString objectName, QVariantMap arguments, + QString argumentName, bool& ok, bool required = true); + static glm::quat extractQuatArgument (QString objectName, QVariantMap arguments, + QString argumentName, bool& ok, bool required = true); + static float extractFloatArgument(QString objectName, QVariantMap arguments, + QString argumentName, bool& ok, bool required = true); }; typedef std::shared_ptr EntityActionPointer; diff --git a/libraries/physics/src/ObjectActionSpring.cpp b/libraries/physics/src/ObjectActionSpring.cpp index 8a436096a8..665ec352fe 100644 --- a/libraries/physics/src/ObjectActionSpring.cpp +++ b/libraries/physics/src/ObjectActionSpring.cpp @@ -38,27 +38,30 @@ void ObjectActionSpring::updateAction(btCollisionWorld* collisionWorld, btScalar ObjectMotionState* motionState = static_cast(physicsInfo); btRigidBody* rigidBody = motionState->getRigidBody(); if (rigidBody) { - glm::vec3 offset = _positionalTarget - bulletToGLM(rigidBody->getCenterOfMassPosition()); + // handle the linear part + if (_positionalTargetSet) { + glm::vec3 offset = _positionalTarget - bulletToGLM(rigidBody->getCenterOfMassPosition()); + float offsetLength = glm::length(offset); + float speed = offsetLength / _linearTimeScale; + if (offsetLength > IGNORE_POSITION_DELTA) { + glm::vec3 newVelocity = glm::normalize(offset) * speed; + rigidBody->setLinearVelocity(glmToBullet(newVelocity)); + // void setAngularVelocity (const btVector3 &ang_vel); + rigidBody->activate(); + } else { + rigidBody->setLinearVelocity(glmToBullet(glm::vec3())); + } + } - // btQuaternion getOrientation() const; - // const btTransform& getCenterOfMassTransform() const; - - float offsetLength = glm::length(offset); - float speed = offsetLength; // XXX use _positionalSpringConstant - - float interpolation_value = 0.5; // XXX - const glm::quat slerped_quat = glm::slerp(bulletToGLM(rigidBody->getOrientation()), - _rotationalTarget, - interpolation_value); - - if (offsetLength > IGNORE_POSITION_DELTA) { - glm::vec3 newVelocity = glm::normalize(offset) * speed; - rigidBody->setLinearVelocity(glmToBullet(newVelocity)); - // void setAngularVelocity (const btVector3 &ang_vel); - rigidBody->activate(); - } else { - rigidBody->setLinearVelocity(glmToBullet(glm::vec3())); + // handle rotation + if (_rotationalTargetSet) { + glm::quat qZeroInverse = glm::inverse(bulletToGLM(rigidBody->getOrientation())); + glm::quat deltaQ = _rotationalTarget * qZeroInverse; + glm::vec3 axis = glm::axis(deltaQ); + float angle = glm::angle(deltaQ); + glm::vec3 newAngularVelocity = (-angle / _angularTimeScale) * glm::normalize(axis); + rigidBody->setAngularVelocity(glmToBullet(newAngularVelocity)); } } } @@ -68,37 +71,52 @@ void ObjectActionSpring::updateAction(btCollisionWorld* collisionWorld, btScalar bool ObjectActionSpring::updateArguments(QVariantMap arguments) { // targets are required, spring-constants are optional - bool ok = true; + bool ptOk = true; glm::vec3 positionalTarget = - EntityActionInterface::extractVec3Argument("spring action", arguments, "positionalTarget", ok); - bool pscOK = true; - float positionalSpringConstant = - EntityActionInterface::extractFloatArgument("spring action", arguments, "positionalSpringConstant", pscOK); + EntityActionInterface::extractVec3Argument("spring action", arguments, "targetPosition", ptOk, false); + bool pscOk = true; + float linearTimeScale = + EntityActionInterface::extractFloatArgument("spring action", arguments, "linearTimeScale", pscOk, false); + if (ptOk && pscOk && linearTimeScale <= 0.0f) { + qDebug() << "spring action -- linearTimeScale must be greater than zero."; + return false; + } + bool rtOk = true; glm::quat rotationalTarget = - EntityActionInterface::extractQuatArgument("spring action", arguments, "rotationalTarget", ok); - bool rscOK = true; - float rotationalSpringConstant = - EntityActionInterface::extractFloatArgument("spring action", arguments, "rotationalSpringConstant", rscOK); + EntityActionInterface::extractQuatArgument("spring action", arguments, "targetRotation", rtOk, false); + bool rscOk = true; + float angularTimeScale = + EntityActionInterface::extractFloatArgument("spring action", arguments, "angularTimeScale", rscOk, false); - if (!ok) { + if (!ptOk && !rtOk) { + qDebug() << "spring action requires either targetPosition or targetRotation argument"; return false; } lockForWrite(); - _positionalTarget = positionalTarget; - if (pscOK) { - _positionalSpringConstant = positionalSpringConstant; - } else { - _positionalSpringConstant = 0.5; // XXX pick a good default; + _positionalTargetSet = _rotationalTargetSet = false; + + if (ptOk) { + _positionalTarget = positionalTarget; + _positionalTargetSet = true; + + if (pscOk) { + _linearTimeScale = linearTimeScale; + } else { + _linearTimeScale = 0.1; + } } - _rotationalTarget = rotationalTarget; - if (rscOK) { - _rotationalSpringConstant = rotationalSpringConstant; - } else { - _rotationalSpringConstant = 0.5; // XXX pick a good default; + if (rtOk) { + _rotationalTarget = rotationalTarget; + + if (rscOk) { + _angularTimeScale = angularTimeScale; + } else { + _angularTimeScale = 0.1; + } } _active = true; diff --git a/libraries/physics/src/ObjectActionSpring.h b/libraries/physics/src/ObjectActionSpring.h index 77502e8544..b211259866 100644 --- a/libraries/physics/src/ObjectActionSpring.h +++ b/libraries/physics/src/ObjectActionSpring.h @@ -28,10 +28,12 @@ public: private: glm::vec3 _positionalTarget; - float _positionalSpringConstant; + float _linearTimeScale; + bool _positionalTargetSet; glm::quat _rotationalTarget; - float _rotationalSpringConstant; + float _angularTimeScale; + bool _rotationalTargetSet; }; #endif // hifi_ObjectActionSpring_h