fold kinematic hold into normal hold (disabled by default, an argument enables)

This commit is contained in:
Seth Alves 2015-10-15 20:23:06 -07:00
parent 0964180f2c
commit 359a318568
7 changed files with 90 additions and 247 deletions

View file

@ -12,7 +12,6 @@
#include <avatar/AvatarActionHold.h>
#include <avatar/AvatarActionKinematicHold.h>
#include <ObjectActionOffset.h>
#include <ObjectActionSpring.h>
@ -29,8 +28,6 @@ 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);

View file

@ -75,12 +75,54 @@ void AvatarActionHold::updateActionWorker(float deltaTimeStep) {
_active = true;
});
if (gotLock) {
ObjectActionSpring::updateActionWorker(deltaTimeStep);
if (_kinematic) {
doKinematicUpdate(deltaTimeStep);
} else {
ObjectActionSpring::updateActionWorker(deltaTimeStep);
}
}
}
}
}
void AvatarActionHold::doKinematicUpdate(float deltaTimeStep) {
auto ownerEntity = _ownerEntity.lock();
if (!ownerEntity) {
qDebug() << "AvatarActionHold::doKinematicUpdate -- no owning entity";
return;
}
void* physicsInfo = ownerEntity->getPhysicsInfo();
if (!physicsInfo) {
qDebug() << "AvatarActionHold::doKinematicUpdate -- no owning physics info";
return;
}
ObjectMotionState* motionState = static_cast<ObjectMotionState*>(physicsInfo);
btRigidBody* rigidBody = motionState ? motionState->getRigidBody() : nullptr;
if (!rigidBody) {
qDebug() << "AvatarActionHold::doKinematicUpdate -- no rigidBody";
return;
}
withWriteLock([&]{
if (_kinematicSetVelocity) {
if (_previousSet) {
glm::vec3 positionalVelocity = (_positionalTarget - _previousPositionalTarget) / deltaTimeStep;
rigidBody->setLinearVelocity(glmToBullet(positionalVelocity));
// back up along velocity a bit in order to smooth out a "vibrating" appearance
_positionalTarget -= positionalVelocity * deltaTimeStep / 2.0f;
}
}
btTransform worldTrans = rigidBody->getWorldTransform();
worldTrans.setOrigin(glmToBullet(_positionalTarget));
worldTrans.setRotation(glmToBullet(_rotationalTarget));
rigidBody->setWorldTransform(worldTrans);
_previousPositionalTarget = _positionalTarget;
_previousRotationalTarget = _rotationalTarget;
_previousSet = true;
});
}
bool AvatarActionHold::updateArguments(QVariantMap arguments) {
glm::vec3 relativePosition;
@ -88,6 +130,8 @@ bool AvatarActionHold::updateArguments(QVariantMap arguments) {
float timeScale;
QString hand;
QUuid holderID;
bool kinematic;
bool kinematicSetVelocity;
bool needUpdate = false;
bool somethingChanged = ObjectAction::updateArguments(arguments);
@ -120,12 +164,27 @@ bool AvatarActionHold::updateArguments(QVariantMap arguments) {
auto myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
holderID = myAvatar->getSessionUUID();
ok = true;
kinematic = EntityActionInterface::extractBooleanArgument("hold", arguments, "kinematic", ok, false);
if (!ok) {
_kinematic = false;
}
ok = true;
kinematicSetVelocity = EntityActionInterface::extractBooleanArgument("hold", arguments,
"kinematic-set-velocity", ok, false);
if (!ok) {
_kinematicSetVelocity = false;
}
if (somethingChanged ||
relativePosition != _relativePosition ||
relativeRotation != _relativeRotation ||
timeScale != _linearTimeScale ||
hand != _hand ||
holderID != _holderID) {
holderID != _holderID ||
kinematic != _kinematic ||
kinematicSetVelocity != _kinematicSetVelocity) {
needUpdate = true;
}
});
@ -139,6 +198,8 @@ bool AvatarActionHold::updateArguments(QVariantMap arguments) {
_angularTimeScale = _linearTimeScale;
_hand = hand;
_holderID = holderID;
_kinematic = kinematic;
_kinematicSetVelocity = kinematicSetVelocity;
_active = true;
auto ownerEntity = _ownerEntity.lock();

View file

@ -39,6 +39,13 @@ private:
glm::quat _relativeRotation;
QString _hand;
QUuid _holderID;
void doKinematicUpdate(float deltaTimeStep);
bool _kinematic = false;
bool _kinematicSetVelocity = false;
bool _previousSet = false;
glm::vec3 _previousPositionalTarget;
glm::quat _previousRotationalTarget;
};
#endif // hifi_AvatarActionHold_h

View file

@ -1,188 +0,0 @@
//
// 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),
_previousPositionalTarget(Vectors::ZERO),
_previousRotationalTarget(Quaternions::IDENTITY)
{
_type = ACTION_TYPE_KINEMATIC_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;
}
assert(deltaTimeStep > 0.0f);
glm::quat rotation;
glm::vec3 position;
glm::vec3 offset;
bool gotLock = withTryReadLock([&]{
auto myAvatar = DependencyManager::get<AvatarManager>()->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<ObjectMotionState*>(physicsInfo);
btRigidBody* rigidBody = motionState ? motionState->getRigidBody() : nullptr;
if (!rigidBody) {
qDebug() << "ObjectActionSpring::updateActionWorker no rigidBody";
return;
}
if (_setVelocity) {
if (_previousSet) {
glm::vec3 positionalVelocity = (_positionalTarget - _previousPositionalTarget) / deltaTimeStep;
rigidBody->setLinearVelocity(glmToBullet(positionalVelocity));
// back up along velocity a bit in order to smooth out a "vibrating" appearance
_positionalTarget -= positionalVelocity * deltaTimeStep / 2.0f;
}
}
btTransform worldTrans = rigidBody->getWorldTransform();
worldTrans.setOrigin(glmToBullet(_positionalTarget));
worldTrans.setRotation(glmToBullet(_rotationalTarget));
rigidBody->setWorldTransform(worldTrans);
_previousPositionalTarget = _positionalTarget;
_previousRotationalTarget = _rotationalTarget;
_previousSet = true;
}
}
}
});
}
if (gotLock) {
ObjectActionSpring::updateActionWorker(deltaTimeStep);
}
}
bool AvatarActionKinematicHold::updateArguments(QVariantMap arguments) {
if (!ObjectAction::updateArguments(arguments)) {
return false;
}
bool ok = true;
glm::vec3 relativePosition =
EntityActionInterface::extractVec3Argument("kinematic-hold", arguments, "relativePosition", ok, false);
if (!ok) {
relativePosition = _relativePosition;
}
ok = true;
glm::quat relativeRotation =
EntityActionInterface::extractQuatArgument("kinematic-hold", arguments, "relativeRotation", ok, false);
if (!ok) {
relativeRotation = _relativeRotation;
}
ok = true;
QString hand =
EntityActionInterface::extractStringArgument("kinematic-hold", arguments, "hand", ok, false);
if (!ok || !(hand == "left" || hand == "right")) {
hand = _hand;
}
ok = true;
int setVelocity =
EntityActionInterface::extractIntegerArgument("kinematic-hold", arguments, "setVelocity", ok, false);
if (!ok) {
setVelocity = false;
}
if (relativePosition != _relativePosition
|| relativeRotation != _relativeRotation
|| hand != _hand) {
withWriteLock([&] {
_relativePosition = relativePosition;
_relativeRotation = relativeRotation;
_hand = hand;
_setVelocity = setVelocity;
_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["setVelocity"] = _setVelocity;
arguments["hand"] = _hand;
});
return arguments;
}
void AvatarActionKinematicHold::deserialize(QByteArray serializedArguments) {
if (!_mine) {
ObjectActionSpring::deserialize(serializedArguments);
}
}

View file

@ -1,47 +0,0 @@
//
// 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 <QUuid>
#include <EntityItem.h>
#include <ObjectActionSpring.h>
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;
bool _previousSet = false;
glm::vec3 _previousPositionalTarget;
glm::quat _previousRotationalTarget;
bool _setVelocity = false;
};
#endif // hifi_AvatarActionKinematicHold_h

View file

@ -100,9 +100,6 @@ EntityActionType EntityActionInterface::actionTypeFromString(QString actionTypeS
if (normalizedActionTypeString == "hold") {
return ACTION_TYPE_HOLD;
}
if (normalizedActionTypeString == "kinematichold") {
return ACTION_TYPE_KINEMATIC_HOLD;
}
qDebug() << "Warning -- EntityActionInterface::actionTypeFromString got unknown action-type name" << actionTypeString;
return ACTION_TYPE_NONE;
@ -118,8 +115,6 @@ 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";
@ -286,6 +281,23 @@ QString EntityActionInterface::extractStringArgument(QString objectName, QVarian
return v;
}
bool EntityActionInterface::extractBooleanArgument(QString objectName, QVariantMap arguments,
QString argumentName, bool& ok, bool required) {
if (!arguments.contains(argumentName)) {
if (required) {
qDebug() << objectName << "requires argument:" << argumentName;
}
ok = false;
return false;
}
QVariant vV = arguments[argumentName];
bool v = vV.toBool();
return v;
}
QDataStream& operator<<(QDataStream& stream, const EntityActionType& entityActionType)
{
return stream << (quint16)entityActionType;

View file

@ -23,8 +23,7 @@ enum EntityActionType {
ACTION_TYPE_NONE = 0,
ACTION_TYPE_OFFSET = 1000,
ACTION_TYPE_SPRING = 2000,
ACTION_TYPE_HOLD = 3000,
ACTION_TYPE_KINEMATIC_HOLD = 4000
ACTION_TYPE_HOLD = 3000
};
@ -66,6 +65,8 @@ public:
QString argumentName, bool& ok, bool required = true);
static QString extractStringArgument(QString objectName, QVariantMap arguments,
QString argumentName, bool& ok, bool required = true);
static bool extractBooleanArgument(QString objectName, QVariantMap arguments,
QString argumentName, bool& ok, bool required = true);
protected:
virtual glm::vec3 getPosition() = 0;