From cf8955a8c5801dbf38f62926861030752b745dce Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 2 Oct 2015 15:27:01 -0700 Subject: [PATCH] kinematic grab --- interface/src/InterfaceActionFactory.cpp | 3 + .../src/avatar/AvatarActionKinematicHold.cpp | 162 ++++++++++++++++++ .../src/avatar/AvatarActionKinematicHold.h | 41 +++++ .../entities/src/EntityActionInterface.cpp | 5 + .../entities/src/EntityActionInterface.h | 3 +- 5 files changed, 213 insertions(+), 1 deletion(-) create mode 100644 interface/src/avatar/AvatarActionKinematicHold.cpp create mode 100644 interface/src/avatar/AvatarActionKinematicHold.h diff --git a/interface/src/InterfaceActionFactory.cpp b/interface/src/InterfaceActionFactory.cpp index 2879c19eaa..b4bd7c45ae 100644 --- a/interface/src/InterfaceActionFactory.cpp +++ b/interface/src/InterfaceActionFactory.cpp @@ -12,6 +12,7 @@ #include +#include #include #include @@ -28,6 +29,8 @@ EntityActionPointer interfaceActionFactory(EntityActionType type, const QUuid& i return (EntityActionPointer) new ObjectActionSpring(id, ownerEntity); case ACTION_TYPE_HOLD: return (EntityActionPointer) new AvatarActionHold(id, ownerEntity); + case ACTION_TYPE_KINEMATIC_HOLD: + return (EntityActionPointer) new AvatarActionKinematicHold(id, ownerEntity); } assert(false); diff --git a/interface/src/avatar/AvatarActionKinematicHold.cpp b/interface/src/avatar/AvatarActionKinematicHold.cpp new file mode 100644 index 0000000000..14b80efd64 --- /dev/null +++ b/interface/src/avatar/AvatarActionKinematicHold.cpp @@ -0,0 +1,162 @@ +// +// AvatarActionKinematicHold.cpp +// interface/src/avatar/ +// +// Created by Seth Alves 2015-6-9 +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "QVariantGLM.h" +#include "avatar/MyAvatar.h" +#include "avatar/AvatarManager.h" + +#include "AvatarActionKinematicHold.h" + +const uint16_t AvatarActionKinematicHold::holdVersion = 1; + +AvatarActionKinematicHold::AvatarActionKinematicHold(const QUuid& id, EntityItemPointer ownerEntity) : + ObjectActionSpring(id, ownerEntity), + _relativePosition(glm::vec3(0.0f)), + _relativeRotation(glm::quat()), + _hand("right"), + _mine(false) +{ + _type = ACTION_TYPE_HOLD; + #if WANT_DEBUG + qDebug() << "AvatarActionKinematicHold::AvatarActionKinematicHold"; + #endif +} + +AvatarActionKinematicHold::~AvatarActionKinematicHold() { + #if WANT_DEBUG + qDebug() << "AvatarActionKinematicHold::~AvatarActionKinematicHold"; + #endif +} + +void AvatarActionKinematicHold::updateActionWorker(float deltaTimeStep) { + if (!_mine) { + // if a local script isn't updating this, then we are just getting spring-action data over the wire. + // let the super-class handle it. + ObjectActionSpring::updateActionWorker(deltaTimeStep); + return; + } + + glm::quat rotation; + glm::vec3 position; + glm::vec3 offset; + bool gotLock = withTryReadLock([&]{ + auto myAvatar = DependencyManager::get()->getMyAvatar(); + glm::vec3 palmPosition; + glm::quat palmRotation; + if (_hand == "right") { + palmPosition = myAvatar->getRightPalmPosition(); + palmRotation = myAvatar->getRightPalmRotation(); + } else { + palmPosition = myAvatar->getLeftPalmPosition(); + palmRotation = myAvatar->getLeftPalmRotation(); + } + + rotation = palmRotation * _relativeRotation; + offset = rotation * _relativePosition; + position = palmPosition + offset; + }); + + if (gotLock) { + gotLock = withTryWriteLock([&]{ + if (_positionalTarget != position || _rotationalTarget != rotation) { + _positionalTarget = position; + _rotationalTarget = rotation; + auto ownerEntity = _ownerEntity.lock(); + if (ownerEntity) { + ownerEntity->setActionDataDirty(true); + void* physicsInfo = ownerEntity->getPhysicsInfo(); + if (physicsInfo) { + ObjectMotionState* motionState = static_cast(physicsInfo); + btRigidBody* rigidBody = motionState->getRigidBody(); + if (!rigidBody) { + qDebug() << "ObjectActionSpring::updateActionWorker no rigidBody"; + return; + } + + btTransform worldTrans; + worldTrans.setOrigin(glmToBullet(_positionalTarget)); + worldTrans.setRotation(glmToBullet(_rotationalTarget)); + rigidBody->setWorldTransform(worldTrans); + } + } + } + }); + } + + if (gotLock) { + ObjectActionSpring::updateActionWorker(deltaTimeStep); + } +} + + +bool AvatarActionKinematicHold::updateArguments(QVariantMap arguments) { + if (!ObjectAction::updateArguments(arguments)) { + return false; + } + bool ok = true; + glm::vec3 relativePosition = + EntityActionInterface::extractVec3Argument("hold", arguments, "relativePosition", ok, false); + if (!ok) { + relativePosition = _relativePosition; + } + + ok = true; + glm::quat relativeRotation = + EntityActionInterface::extractQuatArgument("hold", arguments, "relativeRotation", ok, false); + if (!ok) { + relativeRotation = _relativeRotation; + } + + ok = true; + QString hand = + EntityActionInterface::extractStringArgument("hold", arguments, "hand", ok, false); + if (!ok || !(hand == "left" || hand == "right")) { + hand = _hand; + } + + if (relativePosition != _relativePosition + || relativeRotation != _relativeRotation + || hand != _hand) { + withWriteLock([&] { + _relativePosition = relativePosition; + _relativeRotation = relativeRotation; + _hand = hand; + + _mine = true; + _active = true; + activateBody(); + }); + } + return true; +} + + +QVariantMap AvatarActionKinematicHold::getArguments() { + QVariantMap arguments = ObjectAction::getArguments(); + withReadLock([&]{ + if (!_mine) { + arguments = ObjectActionSpring::getArguments(); + return; + } + + arguments["relativePosition"] = glmToQMap(_relativePosition); + arguments["relativeRotation"] = glmToQMap(_relativeRotation); + arguments["hand"] = _hand; + }); + return arguments; +} + + +void AvatarActionKinematicHold::deserialize(QByteArray serializedArguments) { + if (!_mine) { + ObjectActionSpring::deserialize(serializedArguments); + } +} diff --git a/interface/src/avatar/AvatarActionKinematicHold.h b/interface/src/avatar/AvatarActionKinematicHold.h new file mode 100644 index 0000000000..6bd7dca01a --- /dev/null +++ b/interface/src/avatar/AvatarActionKinematicHold.h @@ -0,0 +1,41 @@ +// +// AvatarActionKinematicHold.h +// interface/src/avatar/ +// +// Created by Seth Alves 2015-10-2 +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_AvatarActionKinematicHold_h +#define hifi_AvatarActionKinematicHold_h + +#include + +#include +#include + +class AvatarActionKinematicHold : public ObjectActionSpring { +public: + AvatarActionKinematicHold(const QUuid& id, EntityItemPointer ownerEntity); + virtual ~AvatarActionKinematicHold(); + + virtual bool updateArguments(QVariantMap arguments); + virtual QVariantMap getArguments(); + + virtual void updateActionWorker(float deltaTimeStep); + + virtual void deserialize(QByteArray serializedArguments); + +private: + static const uint16_t holdVersion; + + glm::vec3 _relativePosition; + glm::quat _relativeRotation; + QString _hand; + bool _mine = false; +}; + +#endif // hifi_AvatarActionKinematicHold_h diff --git a/libraries/entities/src/EntityActionInterface.cpp b/libraries/entities/src/EntityActionInterface.cpp index ba7f3afea4..d821dcdc2f 100644 --- a/libraries/entities/src/EntityActionInterface.cpp +++ b/libraries/entities/src/EntityActionInterface.cpp @@ -100,6 +100,9 @@ EntityActionType EntityActionInterface::actionTypeFromString(QString actionTypeS if (normalizedActionTypeString == "hold") { return ACTION_TYPE_HOLD; } + if (normalizedActionTypeString == "kinematic-hold") { + return ACTION_TYPE_KINEMATIC_HOLD; + } qDebug() << "Warning -- EntityActionInterface::actionTypeFromString got unknown action-type name" << actionTypeString; return ACTION_TYPE_NONE; @@ -115,6 +118,8 @@ QString EntityActionInterface::actionTypeToString(EntityActionType actionType) { return "spring"; case ACTION_TYPE_HOLD: return "hold"; + case ACTION_TYPE_KINEMATIC_HOLD: + return "kinematic-hold"; } assert(false); return "none"; diff --git a/libraries/entities/src/EntityActionInterface.h b/libraries/entities/src/EntityActionInterface.h index e61019c98c..567b88d4b0 100644 --- a/libraries/entities/src/EntityActionInterface.h +++ b/libraries/entities/src/EntityActionInterface.h @@ -23,7 +23,8 @@ enum EntityActionType { ACTION_TYPE_NONE = 0, ACTION_TYPE_OFFSET = 1000, ACTION_TYPE_SPRING = 2000, - ACTION_TYPE_HOLD = 3000 + ACTION_TYPE_HOLD = 3000, + ACTION_TYPE_KINEMATIC_HOLD = 4000 };