From 74c0a70cb042cc96de6c6087f55249ec33f30dd0 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 11 Apr 2017 20:39:13 -0700 Subject: [PATCH 01/26] rename base action classes to dynamics, start on constraints --- assignment-client/src/AssignmentAction.cpp | 91 ------ .../src/AssignmentActionFactory.cpp | 48 ---- .../src/AssignmentActionFactory.h | 29 -- assignment-client/src/AssignmentClient.cpp | 6 +- assignment-client/src/AssignmentDynamic.cpp | 91 ++++++ ...AssignmentAction.h => AssignmentDynamic.h} | 18 +- .../src/AssignmentDynamicFactory.cpp | 48 ++++ .../src/AssignmentDynamicFactory.h | 29 ++ interface/src/Application.cpp | 12 +- interface/src/InterfaceActionFactory.cpp | 82 ------ interface/src/InterfaceDynamicFactory.cpp | 85 ++++++ ...ionFactory.h => InterfaceDynamicFactory.h} | 20 +- interface/src/avatar/AvatarActionHold.cpp | 24 +- ...face.h => EntityDynamicFactoryInterface.h} | 20 +- ...terface.cpp => EntityDynamicInterface.cpp} | 171 ++++++------ ...onInterface.h => EntityDynamicInterface.h} | 49 ++-- libraries/entities/src/EntityItem.cpp | 98 +++---- libraries/entities/src/EntityItem.h | 36 +-- .../entities/src/EntityScriptingInterface.cpp | 12 +- libraries/entities/src/EntitySimulation.cpp | 20 +- libraries/entities/src/EntitySimulation.h | 14 +- libraries/entities/src/EntityTree.cpp | 2 +- libraries/physics/src/EntityMotionState.cpp | 16 +- libraries/physics/src/ObjectAction.cpp | 244 +---------------- libraries/physics/src/ObjectAction.h | 52 +--- libraries/physics/src/ObjectActionOffset.cpp | 16 +- libraries/physics/src/ObjectActionSpring.cpp | 26 +- .../src/ObjectActionTravelOriented.cpp | 14 +- libraries/physics/src/ObjectConstraint.cpp | 21 ++ libraries/physics/src/ObjectConstraint.h | 29 ++ .../physics/src/ObjectConstraintHinge.cpp | 160 +++++++++++ libraries/physics/src/ObjectConstraintHinge.h | 39 +++ libraries/physics/src/ObjectDynamic.cpp | 259 ++++++++++++++++++ libraries/physics/src/ObjectDynamic.h | 70 +++++ .../physics/src/PhysicalEntitySimulation.cpp | 26 +- .../physics/src/PhysicalEntitySimulation.h | 4 +- libraries/physics/src/PhysicsEngine.cpp | 66 +++-- libraries/physics/src/PhysicsEngine.h | 11 +- tests/render-perf/src/main.cpp | 14 +- 39 files changed, 1200 insertions(+), 872 deletions(-) delete mode 100644 assignment-client/src/AssignmentAction.cpp delete mode 100644 assignment-client/src/AssignmentActionFactory.cpp delete mode 100644 assignment-client/src/AssignmentActionFactory.h create mode 100644 assignment-client/src/AssignmentDynamic.cpp rename assignment-client/src/{AssignmentAction.h => AssignmentDynamic.h} (75%) create mode 100644 assignment-client/src/AssignmentDynamicFactory.cpp create mode 100644 assignment-client/src/AssignmentDynamicFactory.h delete mode 100644 interface/src/InterfaceActionFactory.cpp create mode 100644 interface/src/InterfaceDynamicFactory.cpp rename interface/src/{InterfaceActionFactory.h => InterfaceDynamicFactory.h} (51%) rename libraries/entities/src/{EntityActionFactoryInterface.h => EntityDynamicFactoryInterface.h} (56%) rename libraries/entities/src/{EntityActionInterface.cpp => EntityDynamicInterface.cpp} (53%) rename libraries/entities/src/{EntityActionInterface.h => EntityDynamicInterface.h} (72%) create mode 100644 libraries/physics/src/ObjectConstraint.cpp create mode 100644 libraries/physics/src/ObjectConstraint.h create mode 100644 libraries/physics/src/ObjectConstraintHinge.cpp create mode 100644 libraries/physics/src/ObjectConstraintHinge.h create mode 100644 libraries/physics/src/ObjectDynamic.cpp create mode 100644 libraries/physics/src/ObjectDynamic.h diff --git a/assignment-client/src/AssignmentAction.cpp b/assignment-client/src/AssignmentAction.cpp deleted file mode 100644 index 8d296cd6ab..0000000000 --- a/assignment-client/src/AssignmentAction.cpp +++ /dev/null @@ -1,91 +0,0 @@ -// -// AssignmentAction.cpp -// assignment-client/src/ -// -// Created by Seth Alves 2015-6-19 -// 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 "EntitySimulation.h" - -#include "AssignmentAction.h" - -AssignmentAction::AssignmentAction(EntityActionType type, const QUuid& id, EntityItemPointer ownerEntity) : - EntityActionInterface(type, id), - _data(QByteArray()), - _active(false), - _ownerEntity(ownerEntity) { -} - -AssignmentAction::~AssignmentAction() { -} - -void AssignmentAction::removeFromSimulation(EntitySimulationPointer simulation) const { - withReadLock([&]{ - simulation->removeAction(_id); - simulation->applyActionChanges(); - }); -} - -QByteArray AssignmentAction::serialize() const { - QByteArray result; - withReadLock([&]{ - result = _data; - }); - return result; -} - -void AssignmentAction::deserialize(QByteArray serializedArguments) { - withWriteLock([&]{ - _data = serializedArguments; - }); -} - -bool AssignmentAction::updateArguments(QVariantMap arguments) { - qDebug() << "UNEXPECTED -- AssignmentAction::updateArguments called in assignment-client."; - return false; -} - -QVariantMap AssignmentAction::getArguments() { - qDebug() << "UNEXPECTED -- AssignmentAction::getArguments called in assignment-client."; - return QVariantMap(); -} - -glm::vec3 AssignmentAction::getPosition() { - qDebug() << "UNEXPECTED -- AssignmentAction::getPosition called in assignment-client."; - return glm::vec3(0.0f); -} - -void AssignmentAction::setPosition(glm::vec3 position) { - qDebug() << "UNEXPECTED -- AssignmentAction::setPosition called in assignment-client."; -} - -glm::quat AssignmentAction::getRotation() { - qDebug() << "UNEXPECTED -- AssignmentAction::getRotation called in assignment-client."; - return glm::quat(); -} - -void AssignmentAction::setRotation(glm::quat rotation) { - qDebug() << "UNEXPECTED -- AssignmentAction::setRotation called in assignment-client."; -} - -glm::vec3 AssignmentAction::getLinearVelocity() { - qDebug() << "UNEXPECTED -- AssignmentAction::getLinearVelocity called in assignment-client."; - return glm::vec3(0.0f); -} - -void AssignmentAction::setLinearVelocity(glm::vec3 linearVelocity) { - qDebug() << "UNEXPECTED -- AssignmentAction::setLinearVelocity called in assignment-client."; -} - -glm::vec3 AssignmentAction::getAngularVelocity() { - qDebug() << "UNEXPECTED -- AssignmentAction::getAngularVelocity called in assignment-client."; - return glm::vec3(0.0f); -} - -void AssignmentAction::setAngularVelocity(glm::vec3 angularVelocity) { - qDebug() << "UNEXPECTED -- AssignmentAction::setAngularVelocity called in assignment-client."; -} diff --git a/assignment-client/src/AssignmentActionFactory.cpp b/assignment-client/src/AssignmentActionFactory.cpp deleted file mode 100644 index f99e712b72..0000000000 --- a/assignment-client/src/AssignmentActionFactory.cpp +++ /dev/null @@ -1,48 +0,0 @@ -// -// AssignmentActionFactory.cpp -// assignment-client/src/ -// -// Created by Seth Alves on 2015-6-19 -// 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 "AssignmentActionFactory.h" - - -EntityActionPointer assignmentActionFactory(EntityActionType type, const QUuid& id, EntityItemPointer ownerEntity) { - return EntityActionPointer(new AssignmentAction(type, id, ownerEntity)); -} - -EntityActionPointer AssignmentActionFactory::factory(EntityActionType type, - const QUuid& id, - EntityItemPointer ownerEntity, - QVariantMap arguments) { - EntityActionPointer action = assignmentActionFactory(type, id, ownerEntity); - if (action) { - bool ok = action->updateArguments(arguments); - if (ok) { - return action; - } - } - return nullptr; -} - - -EntityActionPointer AssignmentActionFactory::factoryBA(EntityItemPointer ownerEntity, QByteArray data) { - QDataStream serializedActionDataStream(data); - EntityActionType type; - QUuid id; - - serializedActionDataStream >> type; - serializedActionDataStream >> id; - - EntityActionPointer action = assignmentActionFactory(type, id, ownerEntity); - - if (action) { - action->deserialize(data); - } - return action; -} diff --git a/assignment-client/src/AssignmentActionFactory.h b/assignment-client/src/AssignmentActionFactory.h deleted file mode 100644 index 87970c9431..0000000000 --- a/assignment-client/src/AssignmentActionFactory.h +++ /dev/null @@ -1,29 +0,0 @@ -// -// AssignmentActionFactory.cpp -// assignment-client/src/ -// -// Created by Seth Alves on 2015-6-19 -// 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_AssignmentActionFactory_h -#define hifi_AssignmentActionFactory_h - -#include "EntityActionFactoryInterface.h" -#include "AssignmentAction.h" - -class AssignmentActionFactory : public EntityActionFactoryInterface { -public: - AssignmentActionFactory() : EntityActionFactoryInterface() { } - virtual ~AssignmentActionFactory() { } - virtual EntityActionPointer factory(EntityActionType type, - const QUuid& id, - EntityItemPointer ownerEntity, - QVariantMap arguments) override; - virtual EntityActionPointer factoryBA(EntityItemPointer ownerEntity, QByteArray data) override; -}; - -#endif // hifi_AssignmentActionFactory_h diff --git a/assignment-client/src/AssignmentClient.cpp b/assignment-client/src/AssignmentClient.cpp index fe565b62f4..eb0ffefe47 100644 --- a/assignment-client/src/AssignmentClient.cpp +++ b/assignment-client/src/AssignmentClient.cpp @@ -32,7 +32,7 @@ #include #include "AssignmentFactory.h" -#include "AssignmentActionFactory.h" +#include "AssignmentDynamicFactory.h" #include "AssignmentClient.h" #include "AssignmentClientLogging.h" @@ -63,8 +63,8 @@ AssignmentClient::AssignmentClient(Assignment::Type requestAssignmentType, QStri auto animationCache = DependencyManager::set(); auto entityScriptingInterface = DependencyManager::set(false); - DependencyManager::registerInheritance(); - auto actionFactory = DependencyManager::set(); + DependencyManager::registerInheritance(); + auto dynamicFactory = DependencyManager::set(); DependencyManager::set(); // setup a thread for the NodeList and its PacketReceiver diff --git a/assignment-client/src/AssignmentDynamic.cpp b/assignment-client/src/AssignmentDynamic.cpp new file mode 100644 index 0000000000..c9b8d3d8c4 --- /dev/null +++ b/assignment-client/src/AssignmentDynamic.cpp @@ -0,0 +1,91 @@ +// +// AssignmentDynamic.cpp +// assignment-client/src/ +// +// Created by Seth Alves 2015-6-19 +// 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 "EntitySimulation.h" + +#include "AssignmentDynamic.h" + +AssignmentDynamic::AssignmentDynamic(EntityDynamicType type, const QUuid& id, EntityItemPointer ownerEntity) : + EntityDynamicInterface(type, id), + _data(QByteArray()), + _active(false), + _ownerEntity(ownerEntity) { +} + +AssignmentDynamic::~AssignmentDynamic() { +} + +void AssignmentDynamic::removeFromSimulation(EntitySimulationPointer simulation) const { + withReadLock([&]{ + simulation->removeDynamic(_id); + simulation->applyDynamicChanges(); + }); +} + +QByteArray AssignmentDynamic::serialize() const { + QByteArray result; + withReadLock([&]{ + result = _data; + }); + return result; +} + +void AssignmentDynamic::deserialize(QByteArray serializedArguments) { + withWriteLock([&]{ + _data = serializedArguments; + }); +} + +bool AssignmentDynamic::updateArguments(QVariantMap arguments) { + qDebug() << "UNEXPECTED -- AssignmentDynamic::updateArguments called in assignment-client."; + return false; +} + +QVariantMap AssignmentDynamic::getArguments() { + qDebug() << "UNEXPECTED -- AssignmentDynamic::getArguments called in assignment-client."; + return QVariantMap(); +} + +glm::vec3 AssignmentDynamic::getPosition() { + qDebug() << "UNEXPECTED -- AssignmentDynamic::getPosition called in assignment-client."; + return glm::vec3(0.0f); +} + +void AssignmentDynamic::setPosition(glm::vec3 position) { + qDebug() << "UNEXPECTED -- AssignmentDynamic::setPosition called in assignment-client."; +} + +glm::quat AssignmentDynamic::getRotation() { + qDebug() << "UNEXPECTED -- AssignmentDynamic::getRotation called in assignment-client."; + return glm::quat(); +} + +void AssignmentDynamic::setRotation(glm::quat rotation) { + qDebug() << "UNEXPECTED -- AssignmentDynamic::setRotation called in assignment-client."; +} + +glm::vec3 AssignmentDynamic::getLinearVelocity() { + qDebug() << "UNEXPECTED -- AssignmentDynamic::getLinearVelocity called in assignment-client."; + return glm::vec3(0.0f); +} + +void AssignmentDynamic::setLinearVelocity(glm::vec3 linearVelocity) { + qDebug() << "UNEXPECTED -- AssignmentDynamic::setLinearVelocity called in assignment-client."; +} + +glm::vec3 AssignmentDynamic::getAngularVelocity() { + qDebug() << "UNEXPECTED -- AssignmentDynamic::getAngularVelocity called in assignment-client."; + return glm::vec3(0.0f); +} + +void AssignmentDynamic::setAngularVelocity(glm::vec3 angularVelocity) { + qDebug() << "UNEXPECTED -- AssignmentDynamic::setAngularVelocity called in assignment-client."; +} diff --git a/assignment-client/src/AssignmentAction.h b/assignment-client/src/AssignmentDynamic.h similarity index 75% rename from assignment-client/src/AssignmentAction.h rename to assignment-client/src/AssignmentDynamic.h index 98504b3545..91a1e15ebc 100644 --- a/assignment-client/src/AssignmentAction.h +++ b/assignment-client/src/AssignmentDynamic.h @@ -1,5 +1,5 @@ // -// AssignmentAction.h +// AssignmentDynamic.h // assignment-client/src/ // // Created by Seth Alves 2015-6-19 @@ -8,21 +8,21 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -// http://bulletphysics.org/Bullet/BulletFull/classbtActionInterface.html +// http://bulletphysics.org/Bullet/BulletFull/classbtDynamicInterface.html -#ifndef hifi_AssignmentAction_h -#define hifi_AssignmentAction_h +#ifndef hifi_AssignmentDynamic_h +#define hifi_AssignmentDynamic_h #include #include -#include "EntityActionInterface.h" +#include "EntityDynamicInterface.h" -class AssignmentAction : public EntityActionInterface, public ReadWriteLockable { +class AssignmentDynamic : public EntityDynamicInterface, public ReadWriteLockable { public: - AssignmentAction(EntityActionType type, const QUuid& id, EntityItemPointer ownerEntity); - virtual ~AssignmentAction(); + AssignmentDynamic(EntityDynamicType type, const QUuid& id, EntityItemPointer ownerEntity); + virtual ~AssignmentDynamic(); virtual void removeFromSimulation(EntitySimulationPointer simulation) const override; virtual EntityItemWeakPointer getOwnerEntity() const override { return _ownerEntity; } @@ -50,4 +50,4 @@ protected: EntityItemWeakPointer _ownerEntity; }; -#endif // hifi_AssignmentAction_h +#endif // hifi_AssignmentDynamic_h diff --git a/assignment-client/src/AssignmentDynamicFactory.cpp b/assignment-client/src/AssignmentDynamicFactory.cpp new file mode 100644 index 0000000000..88c7f6e06c --- /dev/null +++ b/assignment-client/src/AssignmentDynamicFactory.cpp @@ -0,0 +1,48 @@ +// +// AssignmentDynamcFactory.cpp +// assignment-client/src/ +// +// Created by Seth Alves on 2015-6-19 +// 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 "AssignmentDynamicFactory.h" + + +EntityDynamicPointer assignmentDynamicFactory(EntityDynamicType type, const QUuid& id, EntityItemPointer ownerEntity) { + return EntityDynamicPointer(new AssignmentDynamic(type, id, ownerEntity)); +} + +EntityDynamicPointer AssignmentDynamicFactory::factory(EntityDynamicType type, + const QUuid& id, + EntityItemPointer ownerEntity, + QVariantMap arguments) { + EntityDynamicPointer dynamic = assignmentDynamicFactory(type, id, ownerEntity); + if (dynamic) { + bool ok = dynamic->updateArguments(arguments); + if (ok) { + return dynamic; + } + } + return nullptr; +} + + +EntityDynamicPointer AssignmentDynamicFactory::factoryBA(EntityItemPointer ownerEntity, QByteArray data) { + QDataStream serializedDynamicDataStream(data); + EntityDynamicType type; + QUuid id; + + serializedDynamicDataStream >> type; + serializedDynamicDataStream >> id; + + EntityDynamicPointer dynamic = assignmentDynamicFactory(type, id, ownerEntity); + + if (dynamic) { + dynamic->deserialize(data); + } + return dynamic; +} diff --git a/assignment-client/src/AssignmentDynamicFactory.h b/assignment-client/src/AssignmentDynamicFactory.h new file mode 100644 index 0000000000..cdb9b6ae71 --- /dev/null +++ b/assignment-client/src/AssignmentDynamicFactory.h @@ -0,0 +1,29 @@ +// +// AssignmentDynamicFactory.cpp +// assignment-client/src/ +// +// Created by Seth Alves on 2015-6-19 +// 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_AssignmentDynamicFactory_h +#define hifi_AssignmentDynamicFactory_h + +#include "EntityDynamicFactoryInterface.h" +#include "AssignmentDynamic.h" + +class AssignmentDynamicFactory : public EntityDynamicFactoryInterface { +public: + AssignmentDynamicFactory() : EntityDynamicFactoryInterface() { } + virtual ~AssignmentDynamicFactory() { } + virtual EntityDynamicPointer factory(EntityDynamicType type, + const QUuid& id, + EntityItemPointer ownerEntity, + QVariantMap arguments) override; + virtual EntityDynamicPointer factoryBA(EntityItemPointer ownerEntity, QByteArray data) override; +}; + +#endif // hifi_AssignmentDynamicFactory_h diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 99af5b1578..6ea279111e 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -137,7 +137,7 @@ #include "devices/Leapmotion.h" #include "DiscoverabilityManager.h" #include "GLCanvas.h" -#include "InterfaceActionFactory.h" +#include "InterfaceDynamicFactory.h" #include "InterfaceLogging.h" #include "LODManager.h" #include "ModelPackager.h" @@ -459,7 +459,7 @@ bool setupEssentials(int& argc, char** argv) { DependencyManager::registerInheritance(); DependencyManager::registerInheritance(); - DependencyManager::registerInheritance(); + DependencyManager::registerInheritance(); DependencyManager::registerInheritance(); // Set dependencies @@ -512,7 +512,7 @@ bool setupEssentials(int& argc, char** argv) { DependencyManager::set(); DependencyManager::set(); DependencyManager::set(); - DependencyManager::set(); + DependencyManager::set(); DependencyManager::set(); DependencyManager::set(); controller::StateController::setStateVariables({ { STATE_IN_HMD, STATE_CAMERA_FULL_SCREEN_MIRROR, @@ -4423,7 +4423,7 @@ void Application::update(float deltaTime) { _entitySimulation->setObjectsToChange(stillNeedChange); }); - _entitySimulation->applyActionChanges(); + _entitySimulation->applyDynamicChanges(); avatarManager->getObjectsToRemoveFromPhysics(motionStates); _physicsEngine->removeObjects(motionStates); @@ -4433,8 +4433,8 @@ void Application::update(float deltaTime) { _physicsEngine->changeObjects(motionStates); myAvatar->prepareForPhysicsSimulation(); - _physicsEngine->forEachAction([&](EntityActionPointer action) { - action->prepareForPhysicsSimulation(); + _physicsEngine->forEachDynamic([&](EntityDynamicPointer dynamic) { + dynamic->prepareForPhysicsSimulation(); }); } { diff --git a/interface/src/InterfaceActionFactory.cpp b/interface/src/InterfaceActionFactory.cpp deleted file mode 100644 index 2bc4608e86..0000000000 --- a/interface/src/InterfaceActionFactory.cpp +++ /dev/null @@ -1,82 +0,0 @@ -// -// InterfaceActionFactory.cpp -// libraries/entities/src -// -// Created by Seth Alves on 2015-6-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 -// - - - -#include -#include -#include -#include -#include - -#include "InterfaceActionFactory.h" - - -EntityActionPointer interfaceActionFactory(EntityActionType type, const QUuid& id, EntityItemPointer ownerEntity) { - switch (type) { - case ACTION_TYPE_NONE: - return EntityActionPointer(); - case ACTION_TYPE_OFFSET: - return std::make_shared(id, ownerEntity); - case ACTION_TYPE_SPRING: - return std::make_shared(id, ownerEntity); - case ACTION_TYPE_HOLD: - return std::make_shared(id, ownerEntity); - case ACTION_TYPE_TRAVEL_ORIENTED: - return std::make_shared(id, ownerEntity); - } - - Q_ASSERT_X(false, Q_FUNC_INFO, "Unknown entity action type"); - return EntityActionPointer(); -} - - -EntityActionPointer InterfaceActionFactory::factory(EntityActionType type, - const QUuid& id, - EntityItemPointer ownerEntity, - QVariantMap arguments) { - EntityActionPointer action = interfaceActionFactory(type, id, ownerEntity); - if (action) { - bool ok = action->updateArguments(arguments); - if (ok) { - if (action->lifetimeIsOver()) { - return nullptr; - } - return action; - } - } - return nullptr; -} - - -EntityActionPointer InterfaceActionFactory::factoryBA(EntityItemPointer ownerEntity, QByteArray data) { - QDataStream serializedArgumentStream(data); - EntityActionType type; - QUuid id; - - serializedArgumentStream >> type; - serializedArgumentStream >> id; - - EntityActionPointer action = interfaceActionFactory(type, id, ownerEntity); - - if (action) { - action->deserialize(data); - if (action->lifetimeIsOver()) { - static QString repeatedMessage = - LogHandler::getInstance().addRepeatedMessageRegex(".*factoryBA lifetimeIsOver during action creation.*"); - qDebug() << "InterfaceActionFactory::factoryBA lifetimeIsOver during action creation --" - << action->getExpires() << "<" << usecTimestampNow(); - return nullptr; - } - } - - return action; -} diff --git a/interface/src/InterfaceDynamicFactory.cpp b/interface/src/InterfaceDynamicFactory.cpp new file mode 100644 index 0000000000..ed6d35c69b --- /dev/null +++ b/interface/src/InterfaceDynamicFactory.cpp @@ -0,0 +1,85 @@ +// +// InterfaceDynamicFactory.cpp +// libraries/entities/src +// +// Created by Seth Alves on 2015-6-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 +// + + + +#include +#include +#include +#include +#include +#include + +#include "InterfaceDynamicFactory.h" + + +EntityDynamicPointer interfaceDynamicFactory(EntityDynamicType type, const QUuid& id, EntityItemPointer ownerEntity) { + switch (type) { + case DYNAMIC_TYPE_NONE: + return EntityDynamicPointer(); + case DYNAMIC_TYPE_OFFSET: + return std::make_shared(id, ownerEntity); + case DYNAMIC_TYPE_SPRING: + return std::make_shared(id, ownerEntity); + case DYNAMIC_TYPE_HOLD: + return std::make_shared(id, ownerEntity); + case DYNAMIC_TYPE_TRAVEL_ORIENTED: + return std::make_shared(id, ownerEntity); + case DYNAMIC_TYPE_HINGE: + return std::make_shared(id, ownerEntity); + } + + Q_ASSERT_X(false, Q_FUNC_INFO, "Unknown entity dynamic type"); + return EntityDynamicPointer(); +} + + +EntityDynamicPointer InterfaceDynamicFactory::factory(EntityDynamicType type, + const QUuid& id, + EntityItemPointer ownerEntity, + QVariantMap arguments) { + EntityDynamicPointer dynamic = interfaceDynamicFactory(type, id, ownerEntity); + if (dynamic) { + bool ok = dynamic->updateArguments(arguments); + if (ok) { + if (dynamic->lifetimeIsOver()) { + return nullptr; + } + return dynamic; + } + } + return nullptr; +} + + +EntityDynamicPointer InterfaceDynamicFactory::factoryBA(EntityItemPointer ownerEntity, QByteArray data) { + QDataStream serializedArgumentStream(data); + EntityDynamicType type; + QUuid id; + + serializedArgumentStream >> type; + serializedArgumentStream >> id; + + EntityDynamicPointer dynamic = interfaceDynamicFactory(type, id, ownerEntity); + + if (dynamic) { + dynamic->deserialize(data); + if (dynamic->lifetimeIsOver()) { + static QString repeatedMessage = + LogHandler::getInstance().addRepeatedMessageRegex(".*factoryBA lifetimeIsOver during dynamic creation.*"); + qDebug() << "InterfaceDynamicFactory::factoryBA lifetimeIsOver during dynamic creation --" + << dynamic->getExpires() << "<" << usecTimestampNow(); + return nullptr; + } + } + + return dynamic; +} diff --git a/interface/src/InterfaceActionFactory.h b/interface/src/InterfaceDynamicFactory.h similarity index 51% rename from interface/src/InterfaceActionFactory.h rename to interface/src/InterfaceDynamicFactory.h index 3e8a17d871..b0696442cb 100644 --- a/interface/src/InterfaceActionFactory.h +++ b/interface/src/InterfaceDynamicFactory.h @@ -1,5 +1,5 @@ // -// InterfaceActionFactory.cpp +// InterfaceDynamicFactory.cpp // interface/src/ // // Created by Seth Alves on 2015-6-10 @@ -9,21 +9,21 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#ifndef hifi_InterfaceActionFactory_h -#define hifi_InterfaceActionFactory_h +#ifndef hifi_InterfaceDynamicFactory_h +#define hifi_InterfaceDynamicFactory_h -#include "EntityActionFactoryInterface.h" +#include "EntityDynamicFactoryInterface.h" -class InterfaceActionFactory : public EntityActionFactoryInterface { +class InterfaceDynamicFactory : public EntityDynamicFactoryInterface { public: - InterfaceActionFactory() : EntityActionFactoryInterface() { } - virtual ~InterfaceActionFactory() { } - virtual EntityActionPointer factory(EntityActionType type, + InterfaceDynamicFactory() : EntityDynamicFactoryInterface() { } + virtual ~InterfaceDynamicFactory() { } + virtual EntityDynamicPointer factory(EntityDynamicType type, const QUuid& id, EntityItemPointer ownerEntity, QVariantMap arguments) override; - virtual EntityActionPointer factoryBA(EntityItemPointer ownerEntity, + virtual EntityDynamicPointer factoryBA(EntityItemPointer ownerEntity, QByteArray data) override; }; -#endif // hifi_InterfaceActionFactory_h +#endif // hifi_InterfaceDynamicFactory_h diff --git a/interface/src/avatar/AvatarActionHold.cpp b/interface/src/avatar/AvatarActionHold.cpp index 7f58c86aec..e468911daf 100644 --- a/interface/src/avatar/AvatarActionHold.cpp +++ b/interface/src/avatar/AvatarActionHold.cpp @@ -23,7 +23,7 @@ const int AvatarActionHold::velocitySmoothFrames = 6; AvatarActionHold::AvatarActionHold(const QUuid& id, EntityItemPointer ownerEntity) : ObjectActionSpring(id, ownerEntity) { - _type = ACTION_TYPE_HOLD; + _type = DYNAMIC_TYPE_HOLD; _measuredLinearVelocities.resize(AvatarActionHold::velocitySmoothFrames); auto myAvatar = DependencyManager::get()->getMyAvatar(); @@ -326,25 +326,25 @@ bool AvatarActionHold::updateArguments(QVariantMap arguments) { bool somethingChanged = ObjectAction::updateArguments(arguments); withReadLock([&]{ bool ok = true; - relativePosition = EntityActionInterface::extractVec3Argument("hold", arguments, "relativePosition", ok, false); + relativePosition = EntityDynamicInterface::extractVec3Argument("hold", arguments, "relativePosition", ok, false); if (!ok) { relativePosition = _relativePosition; } ok = true; - relativeRotation = EntityActionInterface::extractQuatArgument("hold", arguments, "relativeRotation", ok, false); + relativeRotation = EntityDynamicInterface::extractQuatArgument("hold", arguments, "relativeRotation", ok, false); if (!ok) { relativeRotation = _relativeRotation; } ok = true; - timeScale = EntityActionInterface::extractFloatArgument("hold", arguments, "timeScale", ok, false); + timeScale = EntityDynamicInterface::extractFloatArgument("hold", arguments, "timeScale", ok, false); if (!ok) { timeScale = _linearTimeScale; } ok = true; - hand = EntityActionInterface::extractStringArgument("hold", arguments, "hand", ok, false); + hand = EntityDynamicInterface::extractStringArgument("hold", arguments, "hand", ok, false); if (!ok || !(hand == "left" || hand == "right")) { hand = _hand; } @@ -353,20 +353,20 @@ bool AvatarActionHold::updateArguments(QVariantMap arguments) { holderID = myAvatar->getSessionUUID(); ok = true; - kinematic = EntityActionInterface::extractBooleanArgument("hold", arguments, "kinematic", ok, false); + kinematic = EntityDynamicInterface::extractBooleanArgument("hold", arguments, "kinematic", ok, false); if (!ok) { kinematic = _kinematic; } ok = true; - kinematicSetVelocity = EntityActionInterface::extractBooleanArgument("hold", arguments, + kinematicSetVelocity = EntityDynamicInterface::extractBooleanArgument("hold", arguments, "kinematicSetVelocity", ok, false); if (!ok) { kinematicSetVelocity = _kinematicSetVelocity; } ok = true; - ignoreIK = EntityActionInterface::extractBooleanArgument("hold", arguments, "ignoreIK", ok, false); + ignoreIK = EntityDynamicInterface::extractBooleanArgument("hold", arguments, "ignoreIK", ok, false); if (!ok) { ignoreIK = _ignoreIK; } @@ -400,8 +400,8 @@ bool AvatarActionHold::updateArguments(QVariantMap arguments) { auto ownerEntity = _ownerEntity.lock(); if (ownerEntity) { - ownerEntity->setActionDataDirty(true); - ownerEntity->setActionDataNeedsTransmit(true); + ownerEntity->setDynamicDataDirty(true); + ownerEntity->setDynamicDataNeedsTransmit(true); } }); } @@ -429,7 +429,7 @@ QByteArray AvatarActionHold::serialize() const { QDataStream dataStream(&serializedActionArguments, QIODevice::WriteOnly); withReadLock([&]{ - dataStream << ACTION_TYPE_HOLD; + dataStream << DYNAMIC_TYPE_HOLD; dataStream << getID(); dataStream << AvatarActionHold::holdVersion; @@ -451,7 +451,7 @@ QByteArray AvatarActionHold::serialize() const { void AvatarActionHold::deserialize(QByteArray serializedArguments) { QDataStream dataStream(serializedArguments); - EntityActionType type; + EntityDynamicType type; dataStream >> type; assert(type == getType()); diff --git a/libraries/entities/src/EntityActionFactoryInterface.h b/libraries/entities/src/EntityDynamicFactoryInterface.h similarity index 56% rename from libraries/entities/src/EntityActionFactoryInterface.h rename to libraries/entities/src/EntityDynamicFactoryInterface.h index adff1a53ba..7d44b0a5e9 100644 --- a/libraries/entities/src/EntityActionFactoryInterface.h +++ b/libraries/entities/src/EntityDynamicFactoryInterface.h @@ -1,5 +1,5 @@ // -// EntityActionFactoryInterface.cpp +// EntityDynamicFactoryInterface.cpp // libraries/entities/src // // Created by Seth Alves on 2015-6-2 @@ -9,26 +9,26 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#ifndef hifi_EntityActionFactoryInterface_h -#define hifi_EntityActionFactoryInterface_h +#ifndef hifi_EntityDynamicFactoryInterface_h +#define hifi_EntityDynamicFactoryInterface_h #include -#include "EntityActionInterface.h" +#include "EntityDynamicInterface.h" -class EntityActionFactoryInterface : public QObject, public Dependency { +class EntityDynamicFactoryInterface : public QObject, public Dependency { Q_OBJECT SINGLETON_DEPENDENCY public: - EntityActionFactoryInterface() { } - virtual ~EntityActionFactoryInterface() { } - virtual EntityActionPointer factory(EntityActionType type, + EntityDynamicFactoryInterface() { } + virtual ~EntityDynamicFactoryInterface() { } + virtual EntityDynamicPointer factory(EntityDynamicType type, const QUuid& id, EntityItemPointer ownerEntity, QVariantMap arguments) { assert(false); return nullptr; } - virtual EntityActionPointer factoryBA(EntityItemPointer ownerEntity, + virtual EntityDynamicPointer factoryBA(EntityItemPointer ownerEntity, QByteArray data) { assert(false); return nullptr; } }; -#endif // hifi_EntityActionFactoryInterface_h +#endif // hifi_EntityDynamicFactoryInterface_h diff --git a/libraries/entities/src/EntityActionInterface.cpp b/libraries/entities/src/EntityDynamicInterface.cpp similarity index 53% rename from libraries/entities/src/EntityActionInterface.cpp rename to libraries/entities/src/EntityDynamicInterface.cpp index 23e6fc0202..053e51cf9c 100644 --- a/libraries/entities/src/EntityActionInterface.cpp +++ b/libraries/entities/src/EntityDynamicInterface.cpp @@ -1,5 +1,5 @@ // -// EntityActionInterface.cpp +// EntityDynamicInterface.cpp // libraries/entities/src // // Created by Seth Alves on 2015-6-4 @@ -16,66 +16,66 @@ - +-----------------------+ +-------------------+ +------------------------------+ - | | | | | | - | EntityActionInterface | | btActionInterface | | EntityActionFactoryInterface | - | (entities) | | (bullet) | | (entities) | - +-----------------------+ +-------------------+ +------------------------------+ - | | | | | - +----+ +--+ +----------+ | | - | | | | | - +-------------------+ +--------------+ +------------------------+ +-------------------------+ - | | | | | | | | - | AssignmentAction | | ObjectAction | | InterfaceActionFactory | | AssignmentActionFactory | - |(assignment client)| | (physics) | | (interface) | | (assignment client) | - +-------------------+ +--------------+ +------------------------+ +-------------------------+ + +-----------------------+ +-------------------+ +---------------------------------+ + | | | | | | + | EntityDynamicInterface | | btDynamicInterface | | EntityDynamicFactoryInterface | + | (entities) | | (bullet) | | (entities) | + +-----------------------+ +-------------------+ +---------------------------------+ + | | | | | + +----+ +--+ +----------+ | | + | | | | | + +-------------------+ +--------------+ +---------------------------+ +--------------------------+ + | | | | | | | | + | AssignmentDynamic | | ObjectDynamic | | InterfaceDynamicFactory | | AssignmentDynamicFactory | + |(assignment client)| | (physics) | | (interface) | | (assignment client) | + +-------------------+ +--------------+ +---------------------------+ +--------------------------+ | | | +--------------------+ | | - | ObjectActionSpring | + | ObjectDynamicSpring | | (physics) | +--------------------+ -An action is a callback which is registered with bullet. An action is called-back every physics +An dynamic is a callback which is registered with bullet. An dynamic is called-back every physics simulation step and can do whatever it wants with the various datastructures it has available. An -action, for example, can pull an EntityItem toward a point as if that EntityItem were connected to that +dynamic, for example, can pull an EntityItem toward a point as if that EntityItem were connected to that point by a spring. -In this system, an action is a property of an EntityItem (rather, an EntityItem has a property which -encodes a list of actions). Each action has a type and some arguments. Actions can be created by a +In this system, an dynamic is a property of an EntityItem (rather, an EntityItem has a property which +encodes a list of dynamics). Each dynamic has a type and some arguments. Dynamics can be created by a script or when receiving information via an EntityTree data-stream (either over the network or from an svo file). -In the interface, if an EntityItem has actions, this EntityItem will have pointers to ObjectAction -subclass (like ObjectActionSpring) instantiations. Code in the entities library affects an action-object -via the EntityActionInterface (which knows nothing about bullet). When the ObjectAction subclass -instance is created, it is registered as an action with bullet. Bullet will call into code in this -instance with the btActionInterface every physics-simulation step. +In the interface, if an EntityItem has dynamics, this EntityItem will have pointers to ObjectDynamic +subclass (like ObjectDynamicSpring) instantiations. Code in the entities library affects an dynamic-object +via the EntityDynamicInterface (which knows nothing about bullet). When the ObjectDynamic subclass +instance is created, it is registered as an dynamic with bullet. Bullet will call into code in this +instance with the btDynamicInterface every physics-simulation step. -Because the action can exist next to the interface's EntityTree or the entity-server's EntityTree, -parallel versions of the factories and actions are needed. +Because the dynamic can exist next to the interface's EntityTree or the entity-server's EntityTree, +parallel versions of the factories and dynamics are needed. -In an entity-server, any type of action is instantiated as an AssignmentAction. This action isn't called +In an entity-server, any type of dynamic is instantiated as an AssignmentDynamic. This dynamic isn't called by bullet (which isn't part of an assignment-client). It does nothing but remember its type and its arguments. This may change as we try to make the entity-server's simple physics simulation better, but -right now the AssignmentAction class is a place-holder. +right now the AssignmentDynamic class is a place-holder. -The action-objects are instantiated by singleton (dependecy) subclasses of EntityActionFactoryInterface. -In the interface, the subclass is an InterfaceActionFactory and it will produce things like -ObjectActionSpring. In an entity-server the subclass is an AssignmentActionFactory and it always -produces AssignmentActions. +The dynamic-objects are instantiated by singleton (dependecy) subclasses of EntityDynamicFactoryInterface. +In the interface, the subclass is an InterfaceDynamicFactory and it will produce things like +ObjectDynamicSpring. In an entity-server the subclass is an AssignmentDynamicFactory and it always +produces AssignmentDynamics. -Depending on the action's type, it will have various arguments. When a script changes an argument of an -action, the argument-holding member-variables of ObjectActionSpring (in this example) are updated and -also serialized into _actionData in the EntityItem. Each subclass of ObjectAction knows how to serialize -and deserialize its own arguments. _actionData is what gets sent over the wire or saved in an svo file. -When a packet-reader receives data for _actionData, it will save it in the EntityItem; this causes the -deserializer in the ObjectAction subclass to be called with the new data, thereby updating its argument +Depending on the dynamic's type, it will have various arguments. When a script changes an argument of an +dynamic, the argument-holding member-variables of ObjectDynamicSpring (in this example) are updated and +also serialized into _dynamicData in the EntityItem. Each subclass of ObjectDynamic knows how to serialize +and deserialize its own arguments. _dynamicData is what gets sent over the wire or saved in an svo file. +When a packet-reader receives data for _dynamicData, it will save it in the EntityItem; this causes the +deserializer in the ObjectDynamic subclass to be called with the new data, thereby updating its argument variables. These argument variables are used by the code which is run when bullet does a callback. @@ -83,49 +83,54 @@ variables. These argument variables are used by the code which is run when bull #include "EntityItem.h" -#include "EntityActionInterface.h" +#include "EntityDynamicInterface.h" -EntityActionType EntityActionInterface::actionTypeFromString(QString actionTypeString) { - QString normalizedActionTypeString = actionTypeString.toLower().remove('-').remove('_'); - if (normalizedActionTypeString == "none") { - return ACTION_TYPE_NONE; +EntityDynamicType EntityDynamicInterface::dynamicTypeFromString(QString dynamicTypeString) { + QString normalizedDynamicTypeString = dynamicTypeString.toLower().remove('-').remove('_'); + if (normalizedDynamicTypeString == "none") { + return DYNAMIC_TYPE_NONE; } - if (normalizedActionTypeString == "offset") { - return ACTION_TYPE_OFFSET; + if (normalizedDynamicTypeString == "offset") { + return DYNAMIC_TYPE_OFFSET; } - if (normalizedActionTypeString == "spring") { - return ACTION_TYPE_SPRING; + if (normalizedDynamicTypeString == "spring") { + return DYNAMIC_TYPE_SPRING; } - if (normalizedActionTypeString == "hold") { - return ACTION_TYPE_HOLD; + if (normalizedDynamicTypeString == "hold") { + return DYNAMIC_TYPE_HOLD; } - if (normalizedActionTypeString == "traveloriented") { - return ACTION_TYPE_TRAVEL_ORIENTED; + if (normalizedDynamicTypeString == "traveloriented") { + return DYNAMIC_TYPE_TRAVEL_ORIENTED; + } + if (normalizedDynamicTypeString == "hinge") { + return DYNAMIC_TYPE_HINGE; } - qCDebug(entities) << "Warning -- EntityActionInterface::actionTypeFromString got unknown action-type name" << actionTypeString; - return ACTION_TYPE_NONE; + qCDebug(entities) << "Warning -- EntityDynamicInterface::dynamicTypeFromString got unknown dynamic-type name" << dynamicTypeString; + return DYNAMIC_TYPE_NONE; } -QString EntityActionInterface::actionTypeToString(EntityActionType actionType) { - switch(actionType) { - case ACTION_TYPE_NONE: +QString EntityDynamicInterface::dynamicTypeToString(EntityDynamicType dynamicType) { + switch(dynamicType) { + case DYNAMIC_TYPE_NONE: return "none"; - case ACTION_TYPE_OFFSET: + case DYNAMIC_TYPE_OFFSET: return "offset"; - case ACTION_TYPE_SPRING: + case DYNAMIC_TYPE_SPRING: return "spring"; - case ACTION_TYPE_HOLD: + case DYNAMIC_TYPE_HOLD: return "hold"; - case ACTION_TYPE_TRAVEL_ORIENTED: + case DYNAMIC_TYPE_TRAVEL_ORIENTED: return "travel-oriented"; + case DYNAMIC_TYPE_HINGE: + return "hinge"; } assert(false); return "none"; } -glm::vec3 EntityActionInterface::extractVec3Argument(QString objectName, QVariantMap arguments, +glm::vec3 EntityDynamicInterface::extractVec3Argument(QString objectName, QVariantMap arguments, QString argumentName, bool& ok, bool required) { if (!arguments.contains(argumentName)) { if (required) { @@ -174,7 +179,7 @@ glm::vec3 EntityActionInterface::extractVec3Argument(QString objectName, QVarian return glm::vec3(x, y, z); } -glm::quat EntityActionInterface::extractQuatArgument(QString objectName, QVariantMap arguments, +glm::quat EntityDynamicInterface::extractQuatArgument(QString objectName, QVariantMap arguments, QString argumentName, bool& ok, bool required) { if (!arguments.contains(argumentName)) { if (required) { @@ -227,7 +232,7 @@ glm::quat EntityActionInterface::extractQuatArgument(QString objectName, QVarian return glm::normalize(glm::quat(w, x, y, z)); } -float EntityActionInterface::extractFloatArgument(QString objectName, QVariantMap arguments, +float EntityDynamicInterface::extractFloatArgument(QString objectName, QVariantMap arguments, QString argumentName, bool& ok, bool required) { if (!arguments.contains(argumentName)) { if (required) { @@ -249,7 +254,7 @@ float EntityActionInterface::extractFloatArgument(QString objectName, QVariantMa return value; } -int EntityActionInterface::extractIntegerArgument(QString objectName, QVariantMap arguments, +int EntityDynamicInterface::extractIntegerArgument(QString objectName, QVariantMap arguments, QString argumentName, bool& ok, bool required) { if (!arguments.contains(argumentName)) { if (required) { @@ -271,7 +276,7 @@ int EntityActionInterface::extractIntegerArgument(QString objectName, QVariantMa return value; } -QString EntityActionInterface::extractStringArgument(QString objectName, QVariantMap arguments, +QString EntityDynamicInterface::extractStringArgument(QString objectName, QVariantMap arguments, QString argumentName, bool& ok, bool required) { if (!arguments.contains(argumentName)) { if (required) { @@ -283,7 +288,7 @@ QString EntityActionInterface::extractStringArgument(QString objectName, QVarian return arguments[argumentName].toString(); } -bool EntityActionInterface::extractBooleanArgument(QString objectName, QVariantMap arguments, +bool EntityDynamicInterface::extractBooleanArgument(QString objectName, QVariantMap arguments, QString argumentName, bool& ok, bool required) { if (!arguments.contains(argumentName)) { if (required) { @@ -297,35 +302,35 @@ bool EntityActionInterface::extractBooleanArgument(QString objectName, QVariantM -QDataStream& operator<<(QDataStream& stream, const EntityActionType& entityActionType) +QDataStream& operator<<(QDataStream& stream, const EntityDynamicType& entityDynamicType) { - return stream << (quint16)entityActionType; + return stream << (quint16)entityDynamicType; } -QDataStream& operator>>(QDataStream& stream, EntityActionType& entityActionType) +QDataStream& operator>>(QDataStream& stream, EntityDynamicType& entityDynamicType) { - quint16 actionTypeAsInt; - stream >> actionTypeAsInt; - entityActionType = (EntityActionType)actionTypeAsInt; + quint16 dynamicTypeAsInt; + stream >> dynamicTypeAsInt; + entityDynamicType = (EntityDynamicType)dynamicTypeAsInt; return stream; } -QString serializedActionsToDebugString(QByteArray data) { +QString serializedDynamicsToDebugString(QByteArray data) { if (data.size() == 0) { return QString(); } - QVector serializedActions; - QDataStream serializedActionsStream(data); - serializedActionsStream >> serializedActions; + QVector serializedDynamics; + QDataStream serializedDynamicsStream(data); + serializedDynamicsStream >> serializedDynamics; QString result; - foreach(QByteArray serializedAction, serializedActions) { - QDataStream serializedActionStream(serializedAction); - EntityActionType actionType; - QUuid actionID; - serializedActionStream >> actionType; - serializedActionStream >> actionID; - result += EntityActionInterface::actionTypeToString(actionType) + "-" + actionID.toString() + " "; + foreach(QByteArray serializedDynamic, serializedDynamics) { + QDataStream serializedDynamicStream(serializedDynamic); + EntityDynamicType dynamicType; + QUuid dynamicID; + serializedDynamicStream >> dynamicType; + serializedDynamicStream >> dynamicID; + result += EntityDynamicInterface::dynamicTypeToString(dynamicType) + "-" + dynamicID.toString() + " "; } return result; diff --git a/libraries/entities/src/EntityActionInterface.h b/libraries/entities/src/EntityDynamicInterface.h similarity index 72% rename from libraries/entities/src/EntityActionInterface.h rename to libraries/entities/src/EntityDynamicInterface.h index d9a901f1f6..f6dba84fc5 100644 --- a/libraries/entities/src/EntityActionInterface.h +++ b/libraries/entities/src/EntityDynamicInterface.h @@ -1,5 +1,5 @@ // -// EntityActionInterface.h +// EntityDynamicInterface.h // libraries/entities/src // // Created by Seth Alves on 2015-6-2 @@ -9,8 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#ifndef hifi_EntityActionInterface_h -#define hifi_EntityActionInterface_h +#ifndef hifi_EntityDynamicInterface_h +#define hifi_EntityDynamicInterface_h #include #include @@ -23,22 +23,25 @@ using EntityItemWeakPointer = std::weak_ptr; class EntitySimulation; using EntitySimulationPointer = std::shared_ptr; -enum EntityActionType { - // keep these synchronized with actionTypeFromString and actionTypeToString - ACTION_TYPE_NONE = 0, - ACTION_TYPE_OFFSET = 1000, - ACTION_TYPE_SPRING = 2000, - ACTION_TYPE_HOLD = 3000, - ACTION_TYPE_TRAVEL_ORIENTED = 4000 +enum EntityDynamicType { + // keep these synchronized with dynamicTypeFromString and dynamicTypeToString + DYNAMIC_TYPE_NONE = 0, + DYNAMIC_TYPE_OFFSET = 1000, + DYNAMIC_TYPE_SPRING = 2000, + DYNAMIC_TYPE_HOLD = 3000, + DYNAMIC_TYPE_TRAVEL_ORIENTED = 4000, + DYNAMIC_TYPE_HINGE = 5000 }; -class EntityActionInterface { +class EntityDynamicInterface { public: - EntityActionInterface(EntityActionType type, const QUuid& id) : _id(id), _type(type) { } - virtual ~EntityActionInterface() { } + EntityDynamicInterface(EntityDynamicType type, const QUuid& id) : _id(id), _type(type) { } + virtual ~EntityDynamicInterface() { } const QUuid& getID() const { return _id; } - EntityActionType getType() const { return _type; } + EntityDynamicType getType() const { return _type; } + virtual bool isAction() const { return false; } + virtual bool isConstraint() const { return false; } bool isActive() { return _active; } @@ -51,8 +54,8 @@ public: virtual QByteArray serialize() const = 0; virtual void deserialize(QByteArray serializedArguments) = 0; - static EntityActionType actionTypeFromString(QString actionTypeString); - static QString actionTypeToString(EntityActionType actionType); + static EntityDynamicType dynamicTypeFromString(QString dynamicTypeString); + static QString dynamicTypeToString(EntityDynamicType dynamicType); virtual bool lifetimeIsOver() { return false; } virtual quint64 getExpires() { return 0; } @@ -91,17 +94,17 @@ protected: virtual void setAngularVelocity(glm::vec3 angularVelocity) = 0; QUuid _id; - EntityActionType _type; + EntityDynamicType _type; bool _active { false }; - bool _isMine { false }; // did this interface create / edit this action? + bool _isMine { false }; // did this interface create / edit this dynamic? }; -typedef std::shared_ptr EntityActionPointer; +typedef std::shared_ptr EntityDynamicPointer; -QDataStream& operator<<(QDataStream& stream, const EntityActionType& entityActionType); -QDataStream& operator>>(QDataStream& stream, EntityActionType& entityActionType); +QDataStream& operator<<(QDataStream& stream, const EntityDynamicType& entityDynamicType); +QDataStream& operator>>(QDataStream& stream, EntityDynamicType& entityDynamicType); -QString serializedActionsToDebugString(QByteArray data); +QString serializedDynamicsToDebugString(QByteArray data); -#endif // hifi_EntityActionInterface_h +#endif // hifi_EntityDynamicInterface_h diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 3f732e26cb..500e4c30fe 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -30,7 +30,7 @@ #include "EntitiesLogging.h" #include "EntityTree.h" #include "EntitySimulation.h" -#include "EntityActionFactoryInterface.h" +#include "EntityDynamicFactoryInterface.h" int EntityItem::_maxActionsDataSize = 800; @@ -280,7 +280,7 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet APPEND_ENTITY_PROPERTY(PROP_COLLISION_SOUND_URL, getCollisionSoundURL()); APPEND_ENTITY_PROPERTY(PROP_HREF, getHref()); APPEND_ENTITY_PROPERTY(PROP_DESCRIPTION, getDescription()); - APPEND_ENTITY_PROPERTY(PROP_ACTION_DATA, getActionData()); + APPEND_ENTITY_PROPERTY(PROP_ACTION_DATA, getDynamicData()); // convert AVATAR_SELF_ID to actual sessionUUID. QUuid actualParentID = getParentID(); @@ -821,7 +821,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef READ_ENTITY_PROPERTY(PROP_COLLISION_SOUND_URL, QString, setCollisionSoundURL); READ_ENTITY_PROPERTY(PROP_HREF, QString, setHref); READ_ENTITY_PROPERTY(PROP_DESCRIPTION, QString, setDescription); - READ_ENTITY_PROPERTY(PROP_ACTION_DATA, QByteArray, setActionData); + READ_ENTITY_PROPERTY(PROP_ACTION_DATA, QByteArray, setDynamicData); { // parentID and parentJointIndex are also protected by simulation ownership bool oldOverwrite = overwriteLocalData; @@ -1251,7 +1251,7 @@ EntityItemProperties EntityItem::getProperties(EntityPropertyFlags desiredProper COPY_ENTITY_PROPERTY_TO_PROPERTIES(name, getName); COPY_ENTITY_PROPERTY_TO_PROPERTIES(href, getHref); COPY_ENTITY_PROPERTY_TO_PROPERTIES(description, getDescription); - COPY_ENTITY_PROPERTY_TO_PROPERTIES(actionData, getActionData); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(actionData, getDynamicData); COPY_ENTITY_PROPERTY_TO_PROPERTIES(parentID, getParentID); COPY_ENTITY_PROPERTY_TO_PROPERTIES(parentJointIndex, getParentJointIndex); COPY_ENTITY_PROPERTY_TO_PROPERTIES(queryAACube, getQueryAACube); @@ -1358,7 +1358,7 @@ bool EntityItem::setProperties(const EntityItemProperties& properties) { SET_ENTITY_PROPERTY_FROM_PROPERTIES(name, setName); SET_ENTITY_PROPERTY_FROM_PROPERTIES(href, setHref); SET_ENTITY_PROPERTY_FROM_PROPERTIES(description, setDescription); - SET_ENTITY_PROPERTY_FROM_PROPERTIES(actionData, setActionData); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(actionData, setDynamicData); SET_ENTITY_PROPERTY_FROM_PROPERTIES(parentID, updateParentID); SET_ENTITY_PROPERTY_FROM_PROPERTIES(parentJointIndex, setParentJointIndex); SET_ENTITY_PROPERTY_FROM_PROPERTIES(queryAACube, setQueryAACube); @@ -1872,10 +1872,10 @@ void EntityItem::computeCollisionGroupAndFinalMask(int16_t& group, int16_t& mask iAmHoldingThis = true; } // also, don't bootstrap our own avatar with a hold action - QList holdActions = getActionsOfType(ACTION_TYPE_HOLD); - QList::const_iterator i = holdActions.begin(); + QList holdActions = getActionsOfType(DYNAMIC_TYPE_HOLD); + QList::const_iterator i = holdActions.begin(); while (i != holdActions.end()) { - EntityActionPointer action = *i; + EntityDynamicPointer action = *i; if (action->isMine()) { iAmHoldingThis = true; break; @@ -1941,18 +1941,18 @@ void EntityItem::rememberHasSimulationOwnershipBid() const { QString EntityItem::actionsToDebugString() { QString result; QVector serializedActions; - QHash::const_iterator i = _objectActions.begin(); + QHash::const_iterator i = _objectActions.begin(); while (i != _objectActions.end()) { const QUuid id = i.key(); - EntityActionPointer action = _objectActions[id]; - EntityActionType actionType = action->getType(); + EntityDynamicPointer action = _objectActions[id]; + EntityDynamicType actionType = action->getType(); result += QString("") + actionType + ":" + action->getID().toString() + " "; i++; } return result; } -bool EntityItem::addAction(EntitySimulationPointer simulation, EntityActionPointer action) { +bool EntityItem::addAction(EntitySimulationPointer simulation, EntityDynamicPointer action) { bool result; withWriteLock([&] { checkWaitingToRemove(simulation); @@ -1960,7 +1960,7 @@ bool EntityItem::addAction(EntitySimulationPointer simulation, EntityActionPoint result = addActionInternal(simulation, action); if (result) { action->setIsMine(true); - _actionDataDirty = true; + _dynamicDataDirty = true; } else { removeActionInternal(action->getID()); } @@ -1969,7 +1969,7 @@ bool EntityItem::addAction(EntitySimulationPointer simulation, EntityActionPoint return result; } -bool EntityItem::addActionInternal(EntitySimulationPointer simulation, EntityActionPointer action) { +bool EntityItem::addActionInternal(EntitySimulationPointer simulation, EntityDynamicPointer action) { assert(action); assert(simulation); auto actionOwnerEntity = action->getOwnerEntity().lock(); @@ -1979,7 +1979,7 @@ bool EntityItem::addActionInternal(EntitySimulationPointer simulation, EntityAct const QUuid& actionID = action->getID(); assert(!_objectActions.contains(actionID) || _objectActions[actionID] == action); _objectActions[actionID] = action; - simulation->addAction(action); + simulation->addDynamic(action); bool success; QByteArray newDataCache; @@ -2003,7 +2003,7 @@ bool EntityItem::updateAction(EntitySimulationPointer simulation, const QUuid& a return; } - EntityActionPointer action = _objectActions[actionID]; + EntityDynamicPointer action = _objectActions[actionID]; success = action->updateArguments(arguments); if (success) { @@ -2035,7 +2035,7 @@ bool EntityItem::removeActionInternal(const QUuid& actionID, EntitySimulationPoi simulation = entityTree ? entityTree->getSimulation() : nullptr; } - EntityActionPointer action = _objectActions[actionID]; + EntityDynamicPointer action = _objectActions[actionID]; action->setOwnerEntity(nullptr); action->setIsMine(false); @@ -2049,7 +2049,7 @@ bool EntityItem::removeActionInternal(const QUuid& actionID, EntitySimulationPoi serializeActions(success, _allActionsDataCache); _dirtyFlags |= Simulation::DIRTY_PHYSICS_ACTIVATION; _dirtyFlags |= Simulation::DIRTY_COLLISION_GROUP; // may need to not collide with own avatar - setActionDataNeedsTransmit(true); + setDynamicDataNeedsTransmit(true); return success; } return false; @@ -2057,10 +2057,10 @@ bool EntityItem::removeActionInternal(const QUuid& actionID, EntitySimulationPoi bool EntityItem::clearActions(EntitySimulationPointer simulation) { withWriteLock([&] { - QHash::iterator i = _objectActions.begin(); + QHash::iterator i = _objectActions.begin(); while (i != _objectActions.end()) { const QUuid id = i.key(); - EntityActionPointer action = _objectActions[id]; + EntityDynamicPointer action = _objectActions[id]; i = _objectActions.erase(i); action->setOwnerEntity(nullptr); action->removeFromSimulation(simulation); @@ -2101,12 +2101,12 @@ void EntityItem::deserializeActionsInternal() { serializedActionsStream >> serializedActions; } - // Keep track of which actions got added or updated by the new actionData + // Keep track of which actions got added or updated by the new dynamicData QSet updated; foreach(QByteArray serializedAction, serializedActions) { QDataStream serializedActionStream(serializedAction); - EntityActionType actionType; + EntityDynamicType actionType; QUuid actionID; serializedActionStream >> actionType; serializedActionStream >> actionID; @@ -2115,7 +2115,7 @@ void EntityItem::deserializeActionsInternal() { } if (_objectActions.contains(actionID)) { - EntityActionPointer action = _objectActions[actionID]; + EntityDynamicPointer action = _objectActions[actionID]; // TODO: make sure types match? there isn't currently a way to // change the type of an existing action. if (!action->isMine()) { @@ -2123,9 +2123,9 @@ void EntityItem::deserializeActionsInternal() { } updated << actionID; } else { - auto actionFactory = DependencyManager::get(); + auto actionFactory = DependencyManager::get(); EntityItemPointer entity = getThisPointer(); - EntityActionPointer action = actionFactory->factoryBA(entity, serializedAction); + EntityDynamicPointer action = actionFactory->factoryBA(entity, serializedAction); if (action) { entity->addActionInternal(simulation, action); updated << actionID; @@ -2140,15 +2140,15 @@ void EntityItem::deserializeActionsInternal() { } // remove any actions that weren't included in the new data. - QHash::const_iterator i = _objectActions.begin(); + QHash::const_iterator i = _objectActions.begin(); while (i != _objectActions.end()) { QUuid id = i.key(); if (!updated.contains(id)) { - EntityActionPointer action = i.value(); + EntityDynamicPointer action = i.value(); if (action->isMine()) { // we just received an update that didn't include one of our actions. tell the server about it (again). - setActionDataNeedsTransmit(true); + setDynamicDataNeedsTransmit(true); } else { // don't let someone else delete my action. _actionsToRemove << id; @@ -2167,7 +2167,7 @@ void EntityItem::deserializeActionsInternal() { } } - _actionDataDirty = true; + _dynamicDataDirty = true; return; } @@ -2179,15 +2179,15 @@ void EntityItem::checkWaitingToRemove(EntitySimulationPointer simulation) { _actionsToRemove.clear(); } -void EntityItem::setActionData(QByteArray actionData) { +void EntityItem::setDynamicData(QByteArray dynamicData) { withWriteLock([&] { - setActionDataInternal(actionData); + setDynamicDataInternal(dynamicData); }); } -void EntityItem::setActionDataInternal(QByteArray actionData) { - if (_allActionsDataCache != actionData) { - _allActionsDataCache = actionData; +void EntityItem::setDynamicDataInternal(QByteArray dynamicData) { + if (_allActionsDataCache != dynamicData) { + _allActionsDataCache = dynamicData; deserializeActionsInternal(); } checkWaitingToRemove(); @@ -2201,10 +2201,10 @@ void EntityItem::serializeActions(bool& success, QByteArray& result) const { } QVector serializedActions; - QHash::const_iterator i = _objectActions.begin(); + QHash::const_iterator i = _objectActions.begin(); while (i != _objectActions.end()) { const QUuid id = i.key(); - EntityActionPointer action = _objectActions[id]; + EntityDynamicPointer action = _objectActions[id]; QByteArray bytesForAction = action->serialize(); serializedActions << bytesForAction; i++; @@ -2224,23 +2224,23 @@ void EntityItem::serializeActions(bool& success, QByteArray& result) const { return; } -const QByteArray EntityItem::getActionDataInternal() const { - if (_actionDataDirty) { +const QByteArray EntityItem::getDynamicDataInternal() const { + if (_dynamicDataDirty) { bool success; serializeActions(success, _allActionsDataCache); if (success) { - _actionDataDirty = false; + _dynamicDataDirty = false; } } return _allActionsDataCache; } -const QByteArray EntityItem::getActionData() const { +const QByteArray EntityItem::getDynamicData() const { QByteArray result; - if (_actionDataDirty) { + if (_dynamicDataDirty) { withWriteLock([&] { - getActionDataInternal(); + getDynamicDataInternal(); result = _allActionsDataCache; }); } else { @@ -2255,9 +2255,9 @@ QVariantMap EntityItem::getActionArguments(const QUuid& actionID) const { QVariantMap result; withReadLock([&] { if (_objectActions.contains(actionID)) { - EntityActionPointer action = _objectActions[actionID]; + EntityDynamicPointer action = _objectActions[actionID]; result = action->getArguments(); - result["type"] = EntityActionInterface::actionTypeToString(action->getType()); + result["type"] = EntityDynamicInterface::dynamicTypeToString(action->getType()); } }); @@ -2265,7 +2265,7 @@ QVariantMap EntityItem::getActionArguments(const QUuid& actionID) const { } bool EntityItem::shouldSuppressLocationEdits() const { - QHash::const_iterator i = _objectActions.begin(); + QHash::const_iterator i = _objectActions.begin(); while (i != _objectActions.end()) { if (i.value()->shouldSuppressLocationEdits()) { return true; @@ -2276,12 +2276,12 @@ bool EntityItem::shouldSuppressLocationEdits() const { return false; } -QList EntityItem::getActionsOfType(EntityActionType typeToGet) const { - QList result; +QList EntityItem::getActionsOfType(EntityDynamicType typeToGet) const { + QList result; - QHash::const_iterator i = _objectActions.begin(); + QHash::const_iterator i = _objectActions.begin(); while (i != _objectActions.end()) { - EntityActionPointer action = i.value(); + EntityDynamicPointer action = i.value(); if (action->getType() == typeToGet && action->isActive()) { result += action; } diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 1ce916de66..3e1724d1ad 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -36,17 +36,17 @@ #include "EntityTypes.h" #include "SimulationOwner.h" #include "SimulationFlags.h" -#include "EntityActionInterface.h" +#include "EntityDynamicInterface.h" class EntitySimulation; class EntityTreeElement; class EntityTreeElementExtraEncodeData; -class EntityActionInterface; +class EntityDynamicInterface; class EntityItemProperties; class EntityTree; class btCollisionShape; typedef std::shared_ptr EntityTreePointer; -typedef std::shared_ptr EntityActionPointer; +typedef std::shared_ptr EntityDynamicPointer; typedef std::shared_ptr EntityTreeElementPointer; using EntityTreeElementExtraEncodeDataPointer = std::shared_ptr; @@ -398,22 +398,22 @@ public: void flagForMotionStateChange() { _dirtyFlags |= Simulation::DIRTY_MOTION_TYPE; } QString actionsToDebugString(); - bool addAction(EntitySimulationPointer simulation, EntityActionPointer action); + bool addAction(EntitySimulationPointer simulation, EntityDynamicPointer action); bool updateAction(EntitySimulationPointer simulation, const QUuid& actionID, const QVariantMap& arguments); bool removeAction(EntitySimulationPointer simulation, const QUuid& actionID); bool clearActions(EntitySimulationPointer simulation); - void setActionData(QByteArray actionData); - const QByteArray getActionData() const; + void setDynamicData(QByteArray dynamicData); + const QByteArray getDynamicData() const; bool hasActions() const { return !_objectActions.empty(); } QList getActionIDs() const { return _objectActions.keys(); } QVariantMap getActionArguments(const QUuid& actionID) const; void deserializeActions(); - void setActionDataDirty(bool value) const { _actionDataDirty = value; } - bool actionDataDirty() const { return _actionDataDirty; } + void setDynamicDataDirty(bool value) const { _dynamicDataDirty = value; } + bool dynamicDataDirty() const { return _dynamicDataDirty; } - void setActionDataNeedsTransmit(bool value) const { _actionDataNeedsTransmit = value; } - bool actionDataNeedsTransmit() const { return _actionDataNeedsTransmit; } + void setDynamicDataNeedsTransmit(bool value) const { _dynamicDataNeedsTransmit = value; } + bool dynamicDataNeedsTransmit() const { return _dynamicDataNeedsTransmit; } bool shouldSuppressLocationEdits() const; @@ -421,7 +421,7 @@ public: const QUuid& getSourceUUID() const { return _sourceUUID; } bool matchesSourceUUID(const QUuid& sourceUUID) const { return _sourceUUID == sourceUUID; } - QList getActionsOfType(EntityActionType typeToGet) const; + QList getActionsOfType(EntityDynamicType typeToGet) const; // these are in the frame of this object virtual glm::quat getAbsoluteJointRotationInObjectFrame(int index) const override { return glm::quat(); } @@ -479,8 +479,8 @@ protected: void setSimulated(bool simulated) { _simulated = simulated; } - const QByteArray getActionDataInternal() const; - void setActionDataInternal(QByteArray actionData); + const QByteArray getDynamicDataInternal() const; + void setDynamicDataInternal(QByteArray dynamicData); virtual void locationChanged(bool tellPhysics = true) override; virtual void dimensionsChanged() override; @@ -570,22 +570,22 @@ protected: void* _physicsInfo { nullptr }; // set by EntitySimulation bool _simulated; // set by EntitySimulation - bool addActionInternal(EntitySimulationPointer simulation, EntityActionPointer action); + bool addActionInternal(EntitySimulationPointer simulation, EntityDynamicPointer action); bool removeActionInternal(const QUuid& actionID, EntitySimulationPointer simulation = nullptr); void deserializeActionsInternal(); void serializeActions(bool& success, QByteArray& result) const; - QHash _objectActions; + QHash _objectActions; static int _maxActionsDataSize; mutable QByteArray _allActionsDataCache; - // when an entity-server starts up, EntityItem::setActionData is called before the entity-tree is + // when an entity-server starts up, EntityItem::setDynamicData is called before the entity-tree is // ready. This means we can't find our EntityItemPointer or add the action to the simulation. These // are used to keep track of and work around this situation. void checkWaitingToRemove(EntitySimulationPointer simulation = nullptr); mutable QSet _actionsToRemove; - mutable bool _actionDataDirty { false }; - mutable bool _actionDataNeedsTransmit { false }; + mutable bool _dynamicDataDirty { false }; + mutable bool _dynamicDataNeedsTransmit { false }; // _previouslyDeletedActions is used to avoid an action being re-added due to server round-trip lag static quint64 _rememberDeletedActionTime; mutable QHash _previouslyDeletedActions; diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 2c332e8d05..10479e931c 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -24,8 +24,8 @@ #include #include "EntitiesLogging.h" -#include "EntityActionFactoryInterface.h" -#include "EntityActionInterface.h" +#include "EntityDynamicFactoryInterface.h" +#include "EntityDynamicInterface.h" #include "EntitySimulation.h" #include "EntityTree.h" #include "LightEntityItem.h" @@ -1133,7 +1133,7 @@ QUuid EntityScriptingInterface::addAction(const QString& actionTypeString, PROFILE_RANGE(script_entities, __FUNCTION__); QUuid actionID = QUuid::createUuid(); - auto actionFactory = DependencyManager::get(); + auto actionFactory = DependencyManager::get(); bool success = false; actionWorker(entityID, [&](EntitySimulationPointer simulation, EntityItemPointer entity) { // create this action even if the entity doesn't have physics info. it will often be the @@ -1142,11 +1142,11 @@ QUuid EntityScriptingInterface::addAction(const QString& actionTypeString, // if (!entity->getPhysicsInfo()) { // return false; // } - EntityActionType actionType = EntityActionInterface::actionTypeFromString(actionTypeString); - if (actionType == ACTION_TYPE_NONE) { + EntityDynamicType dynamicType = EntityDynamicInterface::dynamicTypeFromString(actionTypeString); + if (dynamicType == DYNAMIC_TYPE_NONE) { return false; } - EntityActionPointer action = actionFactory->factory(actionType, actionID, entity, arguments); + EntityDynamicPointer action = actionFactory->factory(dynamicType, actionID, entity, arguments); if (!action) { return false; } diff --git a/libraries/entities/src/EntitySimulation.cpp b/libraries/entities/src/EntitySimulation.cpp index a29ea8e2c8..fbbc1bde71 100644 --- a/libraries/entities/src/EntitySimulation.cpp +++ b/libraries/entities/src/EntitySimulation.cpp @@ -279,25 +279,25 @@ void EntitySimulation::moveSimpleKinematics(const quint64& now) { } } -void EntitySimulation::addAction(EntityActionPointer action) { +void EntitySimulation::addDynamic(EntityDynamicPointer dynamic) { QMutexLocker lock(&_mutex); - _actionsToAdd += action; + _dynamicsToAdd += dynamic; } -void EntitySimulation::removeAction(const QUuid actionID) { +void EntitySimulation::removeDynamic(const QUuid dynamicID) { QMutexLocker lock(&_mutex); - _actionsToRemove += actionID; + _dynamicsToRemove += dynamicID; } -void EntitySimulation::removeActions(QList actionIDsToRemove) { +void EntitySimulation::removeDynamics(QList dynamicIDsToRemove) { QMutexLocker lock(&_mutex); - foreach(QUuid uuid, actionIDsToRemove) { - _actionsToRemove.insert(uuid); + foreach(QUuid uuid, dynamicIDsToRemove) { + _dynamicsToRemove.insert(uuid); } } -void EntitySimulation::applyActionChanges() { +void EntitySimulation::applyDynamicChanges() { QMutexLocker lock(&_mutex); - _actionsToAdd.clear(); - _actionsToRemove.clear(); + _dynamicsToAdd.clear(); + _dynamicsToRemove.clear(); } diff --git a/libraries/entities/src/EntitySimulation.h b/libraries/entities/src/EntitySimulation.h index f8f506ac70..84d30c495d 100644 --- a/libraries/entities/src/EntitySimulation.h +++ b/libraries/entities/src/EntitySimulation.h @@ -18,7 +18,7 @@ #include -#include "EntityActionInterface.h" +#include "EntityDynamicInterface.h" #include "EntityItem.h" #include "EntityTree.h" @@ -59,10 +59,10 @@ public: // friend class EntityTree; - virtual void addAction(EntityActionPointer action); - virtual void removeAction(const QUuid actionID); - virtual void removeActions(QList actionIDsToRemove); - virtual void applyActionChanges(); + virtual void addDynamic(EntityDynamicPointer dynamic); + virtual void removeDynamic(const QUuid dynamicID); + virtual void removeDynamics(QList dynamicIDsToRemove); + virtual void applyDynamicChanges(); /// \param entity pointer to EntityItem to be added /// \sideeffect sets relevant backpointers in entity, but maybe later when appropriate data structures are locked @@ -103,8 +103,8 @@ protected: SetOfEntities _entitiesToSort; // entities moved by simulation (and might need resort in EntityTree) SetOfEntities _simpleKinematicEntities; // entities undergoing non-colliding kinematic motion - QList _actionsToAdd; - QSet _actionsToRemove; + QList _dynamicsToAdd; + QSet _dynamicsToRemove; protected: SetOfEntities _entitiesToDelete; // entities simulation decided needed to be deleted (EntityTree will actually delete) diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index f544a4e5c7..3ad5cc92a5 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -808,7 +808,7 @@ void EntityTree::fixupTerseEditLogging(EntityItemProperties& properties, QList= 0) { QByteArray value = properties.getActionData(); - QString changeHint = serializedActionsToDebugString(value); + QString changeHint = serializedDynamicsToDebugString(value); changedProperties[index] = QString("actionData:") + changeHint; } } diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index d383f4c199..0c804fb5b7 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -94,7 +94,7 @@ void EntityMotionState::updateServerPhysicsVariables() { _serverPosition = localTransform.getTranslation(); _serverRotation = localTransform.getRotation(); _serverAcceleration = _entity->getAcceleration(); - _serverActionData = _entity->getActionData(); + _serverActionData = _entity->getDynamicData(); } void EntityMotionState::handleDeactivation() { @@ -309,7 +309,7 @@ bool EntityMotionState::isCandidateForOwnership() const { assert(entityTreeIsLocked()); return _outgoingPriority != 0 || Physics::getSessionUUID() == _entity->getSimulatorID() - || _entity->actionDataNeedsTransmit(); + || _entity->dynamicDataNeedsTransmit(); } bool EntityMotionState::remoteSimulationOutOfSync(uint32_t simulationStep) { @@ -335,7 +335,7 @@ bool EntityMotionState::remoteSimulationOutOfSync(uint32_t simulationStep) { _serverAcceleration = Vectors::ZERO; _serverAngularVelocity = worldVelocityToLocal.transform(bulletToGLM(_body->getAngularVelocity())); _lastStep = simulationStep; - _serverActionData = _entity->getActionData(); + _serverActionData = _entity->getDynamicData(); _numInactiveUpdates = 1; return false; } @@ -387,7 +387,7 @@ bool EntityMotionState::remoteSimulationOutOfSync(uint32_t simulationStep) { } } - if (_entity->actionDataNeedsTransmit()) { + if (_entity->dynamicDataNeedsTransmit()) { _outgoingPriority = _entity->hasActions() ? SCRIPT_GRAB_SIMULATION_PRIORITY : SCRIPT_POKE_SIMULATION_PRIORITY; return true; } @@ -474,7 +474,7 @@ bool EntityMotionState::shouldSendUpdate(uint32_t simulationStep) { return false; } - if (_entity->actionDataNeedsTransmit()) { + if (_entity->dynamicDataNeedsTransmit()) { return true; } @@ -551,7 +551,7 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_ _serverPosition = localTransform.getTranslation(); _serverRotation = localTransform.getRotation(); _serverAcceleration = _entity->getAcceleration(); - _serverActionData = _entity->getActionData(); + _serverActionData = _entity->getDynamicData(); EntityItemProperties properties; @@ -562,8 +562,8 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, uint32_ properties.setVelocity(_serverVelocity); properties.setAcceleration(_serverAcceleration); properties.setAngularVelocity(_serverAngularVelocity); - if (_entity->actionDataNeedsTransmit()) { - _entity->setActionDataNeedsTransmit(false); + if (_entity->dynamicDataNeedsTransmit()) { + _entity->setDynamicDataNeedsTransmit(false); properties.setActionData(_serverActionData); } diff --git a/libraries/physics/src/ObjectAction.cpp b/libraries/physics/src/ObjectAction.cpp index 95448ad029..f14070fde6 100644 --- a/libraries/physics/src/ObjectAction.cpp +++ b/libraries/physics/src/ObjectAction.cpp @@ -16,13 +16,10 @@ #include "PhysicsLogging.h" -ObjectAction::ObjectAction(EntityActionType type, const QUuid& id, EntityItemPointer ownerEntity) : +ObjectAction::ObjectAction(EntityDynamicType type, const QUuid& id, EntityItemPointer ownerEntity) : btActionInterface(), - EntityActionInterface(type, id), - _ownerEntity(ownerEntity) { -} - -ObjectAction::~ObjectAction() { + ObjectDynamic(type, id, ownerEntity) +{ } void ObjectAction::updateAction(btCollisionWorld* collisionWorld, btScalar deltaTimeStep) { @@ -64,240 +61,5 @@ void ObjectAction::updateAction(btCollisionWorld* collisionWorld, btScalar delta updateActionWorker(deltaTimeStep); } -qint64 ObjectAction::getEntityServerClockSkew() const { - auto nodeList = DependencyManager::get(); - - auto ownerEntity = _ownerEntity.lock(); - if (!ownerEntity) { - return 0; - } - - const QUuid& entityServerNodeID = ownerEntity->getSourceUUID(); - auto entityServerNode = nodeList->nodeWithUUID(entityServerNodeID); - if (entityServerNode) { - return entityServerNode->getClockSkewUsec(); - } - return 0; -} - -bool ObjectAction::updateArguments(QVariantMap arguments) { - bool somethingChanged = false; - - withWriteLock([&]{ - quint64 previousExpires = _expires; - QString previousTag = _tag; - - bool ttlSet = true; - float ttl = EntityActionInterface::extractFloatArgument("action", arguments, "ttl", ttlSet, false); - if (ttlSet) { - quint64 now = usecTimestampNow(); - _expires = now + (quint64)(ttl * USECS_PER_SECOND); - } else { - _expires = 0; - } - - bool tagSet = true; - QString tag = EntityActionInterface::extractStringArgument("action", arguments, "tag", tagSet, false); - if (tagSet) { - _tag = tag; - } else { - tag = ""; - } - - if (previousExpires != _expires || previousTag != _tag) { - somethingChanged = true; - } - }); - - return somethingChanged; -} - -QVariantMap ObjectAction::getArguments() { - QVariantMap arguments; - withReadLock([&]{ - if (_expires == 0) { - arguments["ttl"] = 0.0f; - } else { - quint64 now = usecTimestampNow(); - arguments["ttl"] = (float)(_expires - now) / (float)USECS_PER_SECOND; - } - arguments["tag"] = _tag; - - EntityItemPointer entity = _ownerEntity.lock(); - if (entity) { - ObjectMotionState* motionState = static_cast(entity->getPhysicsInfo()); - if (motionState) { - arguments["::active"] = motionState->isActive(); - arguments["::motion-type"] = motionTypeToString(motionState->getMotionType()); - } else { - arguments["::no-motion-state"] = true; - } - } - arguments["isMine"] = isMine(); - }); - return arguments; -} - - void ObjectAction::debugDraw(btIDebugDraw* debugDrawer) { } - -void ObjectAction::removeFromSimulation(EntitySimulationPointer simulation) const { - QUuid myID; - withReadLock([&]{ - myID = _id; - }); - simulation->removeAction(myID); -} - -btRigidBody* ObjectAction::getRigidBody() { - ObjectMotionState* motionState = nullptr; - withReadLock([&]{ - auto ownerEntity = _ownerEntity.lock(); - if (!ownerEntity) { - return; - } - void* physicsInfo = ownerEntity->getPhysicsInfo(); - if (!physicsInfo) { - return; - } - motionState = static_cast(physicsInfo); - }); - if (motionState) { - return motionState->getRigidBody(); - } - return nullptr; -} - -glm::vec3 ObjectAction::getPosition() { - auto rigidBody = getRigidBody(); - if (!rigidBody) { - return glm::vec3(0.0f); - } - return bulletToGLM(rigidBody->getCenterOfMassPosition()); -} - -void ObjectAction::setPosition(glm::vec3 position) { - auto rigidBody = getRigidBody(); - if (!rigidBody) { - return; - } - // XXX - // void setWorldTransform (const btTransform &worldTrans) - assert(false); - rigidBody->activate(); -} - -glm::quat ObjectAction::getRotation() { - auto rigidBody = getRigidBody(); - if (!rigidBody) { - return glm::quat(0.0f, 0.0f, 0.0f, 1.0f); - } - return bulletToGLM(rigidBody->getOrientation()); -} - -void ObjectAction::setRotation(glm::quat rotation) { - auto rigidBody = getRigidBody(); - if (!rigidBody) { - return; - } - // XXX - // void setWorldTransform (const btTransform &worldTrans) - assert(false); - rigidBody->activate(); -} - -glm::vec3 ObjectAction::getLinearVelocity() { - auto rigidBody = getRigidBody(); - if (!rigidBody) { - return glm::vec3(0.0f); - } - return bulletToGLM(rigidBody->getLinearVelocity()); -} - -void ObjectAction::setLinearVelocity(glm::vec3 linearVelocity) { - auto rigidBody = getRigidBody(); - if (!rigidBody) { - return; - } - rigidBody->setLinearVelocity(glmToBullet(glm::vec3(0.0f))); - rigidBody->activate(); -} - -glm::vec3 ObjectAction::getAngularVelocity() { - auto rigidBody = getRigidBody(); - if (!rigidBody) { - return glm::vec3(0.0f); - } - return bulletToGLM(rigidBody->getAngularVelocity()); -} - -void ObjectAction::setAngularVelocity(glm::vec3 angularVelocity) { - auto rigidBody = getRigidBody(); - if (!rigidBody) { - return; - } - rigidBody->setAngularVelocity(glmToBullet(angularVelocity)); - rigidBody->activate(); -} - -void ObjectAction::activateBody(bool forceActivation) { - auto rigidBody = getRigidBody(); - if (rigidBody) { - rigidBody->activate(forceActivation); - } else { - qCDebug(physics) << "ObjectAction::activateBody -- no rigid body" << (void*)rigidBody; - } -} - -void ObjectAction::forceBodyNonStatic() { - auto ownerEntity = _ownerEntity.lock(); - if (!ownerEntity) { - return; - } - void* physicsInfo = ownerEntity->getPhysicsInfo(); - ObjectMotionState* motionState = static_cast(physicsInfo); - if (motionState && motionState->getMotionType() == MOTION_TYPE_STATIC) { - ownerEntity->flagForMotionStateChange(); - } -} - -bool ObjectAction::lifetimeIsOver() { - if (_expires == 0) { - return false; - } - - quint64 now = usecTimestampNow(); - if (now >= _expires) { - return true; - } - return false; -} - -quint64 ObjectAction::localTimeToServerTime(quint64 timeValue) const { - // 0 indicates no expiration - if (timeValue == 0) { - return 0; - } - - qint64 serverClockSkew = getEntityServerClockSkew(); - if (serverClockSkew < 0 && timeValue <= (quint64)(-serverClockSkew)) { - return 1; // non-zero but long-expired value to avoid negative roll-over - } - - return timeValue + serverClockSkew; -} - -quint64 ObjectAction::serverTimeToLocalTime(quint64 timeValue) const { - // 0 indicates no expiration - if (timeValue == 0) { - return 0; - } - - qint64 serverClockSkew = getEntityServerClockSkew(); - if (serverClockSkew > 0 && timeValue <= (quint64)serverClockSkew) { - return 1; // non-zero but long-expired value to avoid negative roll-over - } - - return timeValue - serverClockSkew; -} diff --git a/libraries/physics/src/ObjectAction.h b/libraries/physics/src/ObjectAction.h index 43330269ac..9dbebea95e 100644 --- a/libraries/physics/src/ObjectAction.h +++ b/libraries/physics/src/ObjectAction.h @@ -14,63 +14,19 @@ #define hifi_ObjectAction_h #include - #include +#include "ObjectDynamic.h" -#include - -#include "ObjectMotionState.h" -#include "BulletUtil.h" -#include "EntityActionInterface.h" - - -class ObjectAction : public btActionInterface, public EntityActionInterface, public ReadWriteLockable { +class ObjectAction : public btActionInterface, public ObjectDynamic { public: - ObjectAction(EntityActionType type, const QUuid& id, EntityItemPointer ownerEntity); - virtual ~ObjectAction(); - - virtual void removeFromSimulation(EntitySimulationPointer simulation) const override; - virtual EntityItemWeakPointer getOwnerEntity() const override { return _ownerEntity; } - virtual void setOwnerEntity(const EntityItemPointer ownerEntity) override { _ownerEntity = ownerEntity; } - - virtual bool updateArguments(QVariantMap arguments) override; - virtual QVariantMap getArguments() override; + ObjectAction(EntityDynamicType type, const QUuid& id, EntityItemPointer ownerEntity); // this is called from updateAction and should be overridden by subclasses virtual void updateActionWorker(float deltaTimeStep) = 0; - // these are from btActionInterface + // these are from btDynamicInterface virtual void updateAction(btCollisionWorld* collisionWorld, btScalar deltaTimeStep) override; virtual void debugDraw(btIDebugDraw* debugDrawer) override; - - virtual QByteArray serialize() const override = 0; - virtual void deserialize(QByteArray serializedArguments) override = 0; - - virtual bool lifetimeIsOver() override; - virtual quint64 getExpires() override { return _expires; } - -protected: - quint64 localTimeToServerTime(quint64 timeValue) const; - quint64 serverTimeToLocalTime(quint64 timeValue) const; - - virtual btRigidBody* getRigidBody(); - virtual glm::vec3 getPosition() override; - virtual void setPosition(glm::vec3 position) override; - virtual glm::quat getRotation() override; - virtual void setRotation(glm::quat rotation) override; - virtual glm::vec3 getLinearVelocity() override; - virtual void setLinearVelocity(glm::vec3 linearVelocity) override; - virtual glm::vec3 getAngularVelocity() override; - virtual void setAngularVelocity(glm::vec3 angularVelocity) override; - virtual void activateBody(bool forceActivation = false); - virtual void forceBodyNonStatic(); - - EntityItemWeakPointer _ownerEntity; - QString _tag; - quint64 _expires { 0 }; // in seconds since epoch - -private: - qint64 getEntityServerClockSkew() const; }; #endif // hifi_ObjectAction_h diff --git a/libraries/physics/src/ObjectActionOffset.cpp b/libraries/physics/src/ObjectActionOffset.cpp index f23b3985de..c011a2db4d 100644 --- a/libraries/physics/src/ObjectActionOffset.cpp +++ b/libraries/physics/src/ObjectActionOffset.cpp @@ -19,7 +19,7 @@ const uint16_t ObjectActionOffset::offsetVersion = 1; ObjectActionOffset::ObjectActionOffset(const QUuid& id, EntityItemPointer ownerEntity) : - ObjectAction(ACTION_TYPE_OFFSET, id, ownerEntity), + ObjectAction(DYNAMIC_TYPE_OFFSET, id, ownerEntity), _pointToOffsetFrom(0.0f), _linearDistance(0.0f), _linearTimeScale(FLT_MAX), @@ -93,21 +93,21 @@ bool ObjectActionOffset::updateArguments(QVariantMap arguments) { withReadLock([&]{ bool ok = true; pointToOffsetFrom = - EntityActionInterface::extractVec3Argument("offset action", arguments, "pointToOffsetFrom", ok, true); + EntityDynamicInterface::extractVec3Argument("offset action", arguments, "pointToOffsetFrom", ok, true); if (!ok) { pointToOffsetFrom = _pointToOffsetFrom; } ok = true; linearTimeScale = - EntityActionInterface::extractFloatArgument("offset action", arguments, "linearTimeScale", ok, false); + EntityDynamicInterface::extractFloatArgument("offset action", arguments, "linearTimeScale", ok, false); if (!ok) { linearTimeScale = _linearTimeScale; } ok = true; linearDistance = - EntityActionInterface::extractFloatArgument("offset action", arguments, "linearDistance", ok, false); + EntityDynamicInterface::extractFloatArgument("offset action", arguments, "linearDistance", ok, false); if (!ok) { linearDistance = _linearDistance; } @@ -132,8 +132,8 @@ bool ObjectActionOffset::updateArguments(QVariantMap arguments) { auto ownerEntity = _ownerEntity.lock(); if (ownerEntity) { - ownerEntity->setActionDataDirty(true); - ownerEntity->setActionDataNeedsTransmit(true); + ownerEntity->setDynamicDataDirty(true); + ownerEntity->setDynamicDataNeedsTransmit(true); } }); activateBody(); @@ -155,7 +155,7 @@ QVariantMap ObjectActionOffset::getArguments() { QByteArray ObjectActionOffset::serialize() const { QByteArray ba; QDataStream dataStream(&ba, QIODevice::WriteOnly); - dataStream << ACTION_TYPE_OFFSET; + dataStream << DYNAMIC_TYPE_OFFSET; dataStream << getID(); dataStream << ObjectActionOffset::offsetVersion; @@ -174,7 +174,7 @@ QByteArray ObjectActionOffset::serialize() const { void ObjectActionOffset::deserialize(QByteArray serializedArguments) { QDataStream dataStream(serializedArguments); - EntityActionType type; + EntityDynamicType type; dataStream >> type; assert(type == getType()); diff --git a/libraries/physics/src/ObjectActionSpring.cpp b/libraries/physics/src/ObjectActionSpring.cpp index b22b3c3368..ac92384101 100644 --- a/libraries/physics/src/ObjectActionSpring.cpp +++ b/libraries/physics/src/ObjectActionSpring.cpp @@ -21,7 +21,7 @@ const uint16_t ObjectActionSpring::springVersion = 1; ObjectActionSpring::ObjectActionSpring(const QUuid& id, EntityItemPointer ownerEntity) : - ObjectAction(ACTION_TYPE_SPRING, id, ownerEntity), + ObjectAction(DYNAMIC_TYPE_SPRING, id, ownerEntity), _positionalTarget(glm::vec3(0.0f)), _desiredPositionalTarget(glm::vec3(0.0f)), _linearTimeScale(FLT_MAX), @@ -64,11 +64,11 @@ bool ObjectActionSpring::prepareForSpringUpdate(btScalar deltaTimeStep) { bool valid = false; int springCount = 0; - QList springDerivedActions; - springDerivedActions.append(ownerEntity->getActionsOfType(ACTION_TYPE_SPRING)); - springDerivedActions.append(ownerEntity->getActionsOfType(ACTION_TYPE_HOLD)); + QList springDerivedActions; + springDerivedActions.append(ownerEntity->getActionsOfType(DYNAMIC_TYPE_SPRING)); + springDerivedActions.append(ownerEntity->getActionsOfType(DYNAMIC_TYPE_HOLD)); - foreach (EntityActionPointer action, springDerivedActions) { + foreach (EntityDynamicPointer action, springDerivedActions) { std::shared_ptr springAction = std::static_pointer_cast(action); glm::quat rotationForAction; glm::vec3 positionForAction; @@ -194,25 +194,25 @@ bool ObjectActionSpring::updateArguments(QVariantMap arguments) { withReadLock([&]{ // targets are required, spring-constants are optional bool ok = true; - positionalTarget = EntityActionInterface::extractVec3Argument("spring action", arguments, "targetPosition", ok, false); + positionalTarget = EntityDynamicInterface::extractVec3Argument("spring action", arguments, "targetPosition", ok, false); if (!ok) { positionalTarget = _desiredPositionalTarget; } ok = true; - linearTimeScale = EntityActionInterface::extractFloatArgument("spring action", arguments, "linearTimeScale", ok, false); + linearTimeScale = EntityDynamicInterface::extractFloatArgument("spring action", arguments, "linearTimeScale", ok, false); if (!ok || linearTimeScale <= 0.0f) { linearTimeScale = _linearTimeScale; } ok = true; - rotationalTarget = EntityActionInterface::extractQuatArgument("spring action", arguments, "targetRotation", ok, false); + rotationalTarget = EntityDynamicInterface::extractQuatArgument("spring action", arguments, "targetRotation", ok, false); if (!ok) { rotationalTarget = _desiredRotationalTarget; } ok = true; angularTimeScale = - EntityActionInterface::extractFloatArgument("spring action", arguments, "angularTimeScale", ok, false); + EntityDynamicInterface::extractFloatArgument("spring action", arguments, "angularTimeScale", ok, false); if (!ok) { angularTimeScale = _angularTimeScale; } @@ -237,8 +237,8 @@ bool ObjectActionSpring::updateArguments(QVariantMap arguments) { auto ownerEntity = _ownerEntity.lock(); if (ownerEntity) { - ownerEntity->setActionDataDirty(true); - ownerEntity->setActionDataNeedsTransmit(true); + ownerEntity->setDynamicDataDirty(true); + ownerEntity->setDynamicDataNeedsTransmit(true); } }); activateBody(); @@ -263,7 +263,7 @@ QByteArray ObjectActionSpring::serialize() const { QByteArray serializedActionArguments; QDataStream dataStream(&serializedActionArguments, QIODevice::WriteOnly); - dataStream << ACTION_TYPE_SPRING; + dataStream << DYNAMIC_TYPE_SPRING; dataStream << getID(); dataStream << ObjectActionSpring::springVersion; @@ -284,7 +284,7 @@ QByteArray ObjectActionSpring::serialize() const { void ObjectActionSpring::deserialize(QByteArray serializedArguments) { QDataStream dataStream(serializedArguments); - EntityActionType type; + EntityDynamicType type; dataStream >> type; assert(type == getType()); diff --git a/libraries/physics/src/ObjectActionTravelOriented.cpp b/libraries/physics/src/ObjectActionTravelOriented.cpp index 8f6d45c6f1..f2b841c9da 100644 --- a/libraries/physics/src/ObjectActionTravelOriented.cpp +++ b/libraries/physics/src/ObjectActionTravelOriented.cpp @@ -19,7 +19,7 @@ const uint16_t ObjectActionTravelOriented::actionVersion = 1; ObjectActionTravelOriented::ObjectActionTravelOriented(const QUuid& id, EntityItemPointer ownerEntity) : - ObjectAction(ACTION_TYPE_TRAVEL_ORIENTED, id, ownerEntity) { + ObjectAction(DYNAMIC_TYPE_TRAVEL_ORIENTED, id, ownerEntity) { #if WANT_DEBUG qCDebug(physics) << "ObjectActionTravelOriented::ObjectActionTravelOriented"; #endif @@ -109,13 +109,13 @@ bool ObjectActionTravelOriented::updateArguments(QVariantMap arguments) { bool somethingChanged = ObjectAction::updateArguments(arguments); withReadLock([&]{ bool ok = true; - forward = EntityActionInterface::extractVec3Argument("travel oriented action", arguments, "forward", ok, true); + forward = EntityDynamicInterface::extractVec3Argument("travel oriented action", arguments, "forward", ok, true); if (!ok) { forward = _forward; } ok = true; angularTimeScale = - EntityActionInterface::extractFloatArgument("travel oriented action", arguments, "angularTimeScale", ok, false); + EntityDynamicInterface::extractFloatArgument("travel oriented action", arguments, "angularTimeScale", ok, false); if (!ok) { angularTimeScale = _angularTimeScale; } @@ -136,8 +136,8 @@ bool ObjectActionTravelOriented::updateArguments(QVariantMap arguments) { auto ownerEntity = _ownerEntity.lock(); if (ownerEntity) { - ownerEntity->setActionDataDirty(true); - ownerEntity->setActionDataNeedsTransmit(true); + ownerEntity->setDynamicDataDirty(true); + ownerEntity->setDynamicDataNeedsTransmit(true); } }); activateBody(); @@ -159,7 +159,7 @@ QByteArray ObjectActionTravelOriented::serialize() const { QByteArray serializedActionArguments; QDataStream dataStream(&serializedActionArguments, QIODevice::WriteOnly); - dataStream << ACTION_TYPE_TRAVEL_ORIENTED; + dataStream << DYNAMIC_TYPE_TRAVEL_ORIENTED; dataStream << getID(); dataStream << ObjectActionTravelOriented::actionVersion; @@ -177,7 +177,7 @@ QByteArray ObjectActionTravelOriented::serialize() const { void ObjectActionTravelOriented::deserialize(QByteArray serializedArguments) { QDataStream dataStream(serializedArguments); - EntityActionType type; + EntityDynamicType type; dataStream >> type; assert(type == getType()); diff --git a/libraries/physics/src/ObjectConstraint.cpp b/libraries/physics/src/ObjectConstraint.cpp new file mode 100644 index 0000000000..e8f1a6d9fd --- /dev/null +++ b/libraries/physics/src/ObjectConstraint.cpp @@ -0,0 +1,21 @@ +// +// ObjectConstraint.cpp +// libraries/physcis/src +// +// Created by Seth Alves 2015-6-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 +// + +#include "EntitySimulation.h" + +#include "ObjectConstraint.h" + +#include "PhysicsLogging.h" + +ObjectConstraint::ObjectConstraint(EntityDynamicType type, const QUuid& id, EntityItemPointer ownerEntity) : + ObjectDynamic(type, id, ownerEntity) +{ +} diff --git a/libraries/physics/src/ObjectConstraint.h b/libraries/physics/src/ObjectConstraint.h new file mode 100644 index 0000000000..8e39fd0a35 --- /dev/null +++ b/libraries/physics/src/ObjectConstraint.h @@ -0,0 +1,29 @@ +// +// ObjectConstraint.h +// libraries/physcis/src +// +// Created by Seth Alves 2017-4-11 +// 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 +// +// http://bulletphysics.org/Bullet/BulletFull/classbtConstraintInterface.html + +#ifndef hifi_ObjectConstraint_h +#define hifi_ObjectConstraint_h + +#include +#include +#include "ObjectDynamic.h" + +class ObjectConstraint : public ObjectDynamic +{ +public: + ObjectConstraint(EntityDynamicType type, const QUuid& id, EntityItemPointer ownerEntity); + virtual btTypedConstraint* getConstraint() = 0; +protected: + btTypedConstraint* _constraint { nullptr }; +}; + +#endif // hifi_ObjectConstraint_h diff --git a/libraries/physics/src/ObjectConstraintHinge.cpp b/libraries/physics/src/ObjectConstraintHinge.cpp new file mode 100644 index 0000000000..d151ffeb6f --- /dev/null +++ b/libraries/physics/src/ObjectConstraintHinge.cpp @@ -0,0 +1,160 @@ +// +// ObjectConstraintHinge.cpp +// libraries/physics/src +// +// Created by Seth Alves 2017-4-11 +// Copyright 2017 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 "ObjectConstraintHinge.h" + +#include "PhysicsLogging.h" + + +const uint16_t ObjectConstraintHinge::constraintVersion = 1; + + +ObjectConstraintHinge::ObjectConstraintHinge(const QUuid& id, EntityItemPointer ownerEntity) : + ObjectConstraint(DYNAMIC_TYPE_HINGE, id, ownerEntity), + _rbATranslation(glm::vec3(0.0f)), + _rbARotation(glm::quat()) +{ + #if WANT_DEBUG + qCDebug(physics) << "ObjectConstraintHinge::ObjectConstraintHinge"; + #endif +} + +ObjectConstraintHinge::~ObjectConstraintHinge() { + #if WANT_DEBUG + qCDebug(physics) << "ObjectConstraintHinge::~ObjectConstraintHinge"; + #endif +} + +btTypedConstraint* ObjectConstraintHinge::getConstraint() { + if (_constraint) { + return _constraint; + } + + btRigidBody* rigidBodyA = getRigidBody(); + if (!rigidBodyA) { + return nullptr; + } + + bool useReferenceFrameA { false }; + + btTransform rigidBodyAFrame(glmToBullet(_rbARotation), glmToBullet(_rbATranslation)); + + _constraint = new btHingeConstraint(*rigidBodyA, rigidBodyAFrame, useReferenceFrameA); + return _constraint; +} + + +bool ObjectConstraintHinge::updateArguments(QVariantMap arguments) { + glm::vec3 rbATranslation; + glm::quat rbARotation; + + bool needUpdate = false; + bool somethingChanged = ObjectConstraint::updateArguments(arguments); + withReadLock([&]{ + // targets are required, hinge-constants are optional + bool ok = true; + rbATranslation = EntityDynamicInterface::extractVec3Argument("hinge constraint", arguments, "targetPosition", ok, false); + if (!ok) { + rbATranslation = _rbATranslation; + } + + ok = true; + rbARotation = EntityDynamicInterface::extractQuatArgument("hinge constraint", arguments, "targetRotation", ok, false); + if (!ok) { + rbARotation = _rbARotation; + } + + if (somethingChanged || + rbATranslation != _rbATranslation || + rbARotation != _rbARotation) { + // something changed + needUpdate = true; + } + }); + + if (needUpdate) { + withWriteLock([&] { + _rbATranslation = rbATranslation; + _rbARotation = rbARotation; + _active = true; + + auto ownerEntity = _ownerEntity.lock(); + if (ownerEntity) { + ownerEntity->setDynamicDataDirty(true); + ownerEntity->setDynamicDataNeedsTransmit(true); + } + }); + activateBody(); + } + + return true; +} + +QVariantMap ObjectConstraintHinge::getArguments() { + QVariantMap arguments = ObjectConstraint::getArguments(); + withReadLock([&] { + arguments["targetPosition"] = glmToQMap(_rbATranslation); + arguments["targetRotation"] = glmToQMap(_rbARotation); + }); + return arguments; +} + +QByteArray ObjectConstraintHinge::serialize() const { + QByteArray serializedConstraintArguments; + QDataStream dataStream(&serializedConstraintArguments, QIODevice::WriteOnly); + + dataStream << DYNAMIC_TYPE_HINGE; + dataStream << getID(); + dataStream << ObjectConstraintHinge::constraintVersion; + + withReadLock([&] { + dataStream << _rbATranslation; + dataStream << _rbARotation; + dataStream << localTimeToServerTime(_expires); + dataStream << _tag; + }); + + return serializedConstraintArguments; +} + +void ObjectConstraintHinge::deserialize(QByteArray serializedArguments) { + QDataStream dataStream(serializedArguments); + + EntityDynamicType type; + dataStream >> type; + assert(type == getType()); + + QUuid id; + dataStream >> id; + assert(id == getID()); + + uint16_t serializationVersion; + dataStream >> serializationVersion; + if (serializationVersion != ObjectConstraintHinge::constraintVersion) { + assert(false); + return; + } + + withWriteLock([&] { + dataStream >> _rbATranslation; + dataStream >> _rbARotation; + + quint64 serverExpires; + dataStream >> serverExpires; + _expires = serverTimeToLocalTime(serverExpires); + + dataStream >> _tag; + + _active = true; + }); +} diff --git a/libraries/physics/src/ObjectConstraintHinge.h b/libraries/physics/src/ObjectConstraintHinge.h new file mode 100644 index 0000000000..e4e5c392ae --- /dev/null +++ b/libraries/physics/src/ObjectConstraintHinge.h @@ -0,0 +1,39 @@ +// +// ObjectConstraintHinge.h +// libraries/physics/src +// +// Created by Seth Alves 2017-4-11 +// Copyright 2017 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_ObjectConstraintHinge_h +#define hifi_ObjectConstraintHinge_h + +#include "ObjectConstraint.h" + +// http://bulletphysics.org/Bullet/BulletFull/classbtHingeConstraint.html + +class ObjectConstraintHinge : public ObjectConstraint { +public: + ObjectConstraintHinge(const QUuid& id, EntityItemPointer ownerEntity); + virtual ~ObjectConstraintHinge(); + + virtual bool updateArguments(QVariantMap arguments) override; + virtual QVariantMap getArguments() override; + + virtual QByteArray serialize() const override; + virtual void deserialize(QByteArray serializedArguments) override; + + virtual btTypedConstraint* getConstraint() override; + +protected: + static const uint16_t constraintVersion; + + glm::vec3 _rbATranslation; + glm::quat _rbARotation; +}; + +#endif // hifi_ObjectConstraintHinge_h diff --git a/libraries/physics/src/ObjectDynamic.cpp b/libraries/physics/src/ObjectDynamic.cpp new file mode 100644 index 0000000000..f887cc42dc --- /dev/null +++ b/libraries/physics/src/ObjectDynamic.cpp @@ -0,0 +1,259 @@ +// +// ObjectDynamic.cpp +// libraries/physcis/src +// +// Created by Seth Alves 2015-6-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 +// + +#include "EntitySimulation.h" + +#include "ObjectDynamic.h" + +#include "PhysicsLogging.h" + + +ObjectDynamic::ObjectDynamic(EntityDynamicType type, const QUuid& id, EntityItemPointer ownerEntity) : + EntityDynamicInterface(type, id), + _ownerEntity(ownerEntity) { +} + +ObjectDynamic::~ObjectDynamic() { +} + +qint64 ObjectDynamic::getEntityServerClockSkew() const { + auto nodeList = DependencyManager::get(); + + auto ownerEntity = _ownerEntity.lock(); + if (!ownerEntity) { + return 0; + } + + const QUuid& entityServerNodeID = ownerEntity->getSourceUUID(); + auto entityServerNode = nodeList->nodeWithUUID(entityServerNodeID); + if (entityServerNode) { + return entityServerNode->getClockSkewUsec(); + } + return 0; +} + +bool ObjectDynamic::updateArguments(QVariantMap arguments) { + bool somethingChanged = false; + + withWriteLock([&]{ + quint64 previousExpires = _expires; + QString previousTag = _tag; + + bool ttlSet = true; + float ttl = EntityDynamicInterface::extractFloatArgument("dynamic", arguments, "ttl", ttlSet, false); + if (ttlSet) { + quint64 now = usecTimestampNow(); + _expires = now + (quint64)(ttl * USECS_PER_SECOND); + } else { + _expires = 0; + } + + bool tagSet = true; + QString tag = EntityDynamicInterface::extractStringArgument("dynamic", arguments, "tag", tagSet, false); + if (tagSet) { + _tag = tag; + } else { + tag = ""; + } + + if (previousExpires != _expires || previousTag != _tag) { + somethingChanged = true; + } + }); + + return somethingChanged; +} + +QVariantMap ObjectDynamic::getArguments() { + QVariantMap arguments; + withReadLock([&]{ + if (_expires == 0) { + arguments["ttl"] = 0.0f; + } else { + quint64 now = usecTimestampNow(); + arguments["ttl"] = (float)(_expires - now) / (float)USECS_PER_SECOND; + } + arguments["tag"] = _tag; + + EntityItemPointer entity = _ownerEntity.lock(); + if (entity) { + ObjectMotionState* motionState = static_cast(entity->getPhysicsInfo()); + if (motionState) { + arguments["::active"] = motionState->isActive(); + arguments["::motion-type"] = motionTypeToString(motionState->getMotionType()); + } else { + arguments["::no-motion-state"] = true; + } + } + arguments["isMine"] = isMine(); + }); + return arguments; +} + +void ObjectDynamic::removeFromSimulation(EntitySimulationPointer simulation) const { + QUuid myID; + withReadLock([&]{ + myID = _id; + }); + simulation->removeDynamic(myID); +} + +btRigidBody* ObjectDynamic::getRigidBody() { + ObjectMotionState* motionState = nullptr; + withReadLock([&]{ + auto ownerEntity = _ownerEntity.lock(); + if (!ownerEntity) { + return; + } + void* physicsInfo = ownerEntity->getPhysicsInfo(); + if (!physicsInfo) { + return; + } + motionState = static_cast(physicsInfo); + }); + if (motionState) { + return motionState->getRigidBody(); + } + return nullptr; +} + +glm::vec3 ObjectDynamic::getPosition() { + auto rigidBody = getRigidBody(); + if (!rigidBody) { + return glm::vec3(0.0f); + } + return bulletToGLM(rigidBody->getCenterOfMassPosition()); +} + +void ObjectDynamic::setPosition(glm::vec3 position) { + auto rigidBody = getRigidBody(); + if (!rigidBody) { + return; + } + // XXX + // void setWorldTransform (const btTransform &worldTrans) + assert(false); + rigidBody->activate(); +} + +glm::quat ObjectDynamic::getRotation() { + auto rigidBody = getRigidBody(); + if (!rigidBody) { + return glm::quat(0.0f, 0.0f, 0.0f, 1.0f); + } + return bulletToGLM(rigidBody->getOrientation()); +} + +void ObjectDynamic::setRotation(glm::quat rotation) { + auto rigidBody = getRigidBody(); + if (!rigidBody) { + return; + } + // XXX + // void setWorldTransform (const btTransform &worldTrans) + assert(false); + rigidBody->activate(); +} + +glm::vec3 ObjectDynamic::getLinearVelocity() { + auto rigidBody = getRigidBody(); + if (!rigidBody) { + return glm::vec3(0.0f); + } + return bulletToGLM(rigidBody->getLinearVelocity()); +} + +void ObjectDynamic::setLinearVelocity(glm::vec3 linearVelocity) { + auto rigidBody = getRigidBody(); + if (!rigidBody) { + return; + } + rigidBody->setLinearVelocity(glmToBullet(glm::vec3(0.0f))); + rigidBody->activate(); +} + +glm::vec3 ObjectDynamic::getAngularVelocity() { + auto rigidBody = getRigidBody(); + if (!rigidBody) { + return glm::vec3(0.0f); + } + return bulletToGLM(rigidBody->getAngularVelocity()); +} + +void ObjectDynamic::setAngularVelocity(glm::vec3 angularVelocity) { + auto rigidBody = getRigidBody(); + if (!rigidBody) { + return; + } + rigidBody->setAngularVelocity(glmToBullet(angularVelocity)); + rigidBody->activate(); +} + +void ObjectDynamic::activateBody(bool forceActivation) { + auto rigidBody = getRigidBody(); + if (rigidBody) { + rigidBody->activate(forceActivation); + } else { + qCDebug(physics) << "ObjectDynamic::activateBody -- no rigid body" << (void*)rigidBody; + } +} + +void ObjectDynamic::forceBodyNonStatic() { + auto ownerEntity = _ownerEntity.lock(); + if (!ownerEntity) { + return; + } + void* physicsInfo = ownerEntity->getPhysicsInfo(); + ObjectMotionState* motionState = static_cast(physicsInfo); + if (motionState && motionState->getMotionType() == MOTION_TYPE_STATIC) { + ownerEntity->flagForMotionStateChange(); + } +} + +bool ObjectDynamic::lifetimeIsOver() { + if (_expires == 0) { + return false; + } + + quint64 now = usecTimestampNow(); + if (now >= _expires) { + return true; + } + return false; +} + +quint64 ObjectDynamic::localTimeToServerTime(quint64 timeValue) const { + // 0 indicates no expiration + if (timeValue == 0) { + return 0; + } + + qint64 serverClockSkew = getEntityServerClockSkew(); + if (serverClockSkew < 0 && timeValue <= (quint64)(-serverClockSkew)) { + return 1; // non-zero but long-expired value to avoid negative roll-over + } + + return timeValue + serverClockSkew; +} + +quint64 ObjectDynamic::serverTimeToLocalTime(quint64 timeValue) const { + // 0 indicates no expiration + if (timeValue == 0) { + return 0; + } + + qint64 serverClockSkew = getEntityServerClockSkew(); + if (serverClockSkew > 0 && timeValue <= (quint64)serverClockSkew) { + return 1; // non-zero but long-expired value to avoid negative roll-over + } + + return timeValue - serverClockSkew; +} diff --git a/libraries/physics/src/ObjectDynamic.h b/libraries/physics/src/ObjectDynamic.h new file mode 100644 index 0000000000..3f81cbc037 --- /dev/null +++ b/libraries/physics/src/ObjectDynamic.h @@ -0,0 +1,70 @@ +// +// ObjectDynamic.h +// libraries/physcis/src +// +// Created by Seth Alves 2015-6-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 +// +// http://bulletphysics.org/Bullet/BulletFull/classbtDynamicInterface.html + +#ifndef hifi_ObjectDynamic_h +#define hifi_ObjectDynamic_h + +#include + +#include + +#include + +#include "ObjectMotionState.h" +#include "BulletUtil.h" +#include "EntityDynamicInterface.h" + + +class ObjectDynamic : public EntityDynamicInterface, public ReadWriteLockable { +public: + ObjectDynamic(EntityDynamicType type, const QUuid& id, EntityItemPointer ownerEntity); + virtual ~ObjectDynamic(); + + virtual void removeFromSimulation(EntitySimulationPointer simulation) const override; + virtual EntityItemWeakPointer getOwnerEntity() const override { return _ownerEntity; } + virtual void setOwnerEntity(const EntityItemPointer ownerEntity) override { _ownerEntity = ownerEntity; } + + virtual bool updateArguments(QVariantMap arguments) override; + virtual QVariantMap getArguments() override; + + + virtual QByteArray serialize() const override = 0; + virtual void deserialize(QByteArray serializedArguments) override = 0; + + virtual bool lifetimeIsOver() override; + virtual quint64 getExpires() override { return _expires; } + +protected: + quint64 localTimeToServerTime(quint64 timeValue) const; + quint64 serverTimeToLocalTime(quint64 timeValue) const; + + virtual btRigidBody* getRigidBody(); + virtual glm::vec3 getPosition() override; + virtual void setPosition(glm::vec3 position) override; + virtual glm::quat getRotation() override; + virtual void setRotation(glm::quat rotation) override; + virtual glm::vec3 getLinearVelocity() override; + virtual void setLinearVelocity(glm::vec3 linearVelocity) override; + virtual glm::vec3 getAngularVelocity() override; + virtual void setAngularVelocity(glm::vec3 angularVelocity) override; + virtual void activateBody(bool forceActivation = false); + virtual void forceBodyNonStatic(); + + EntityItemWeakPointer _ownerEntity; + QString _tag; + quint64 _expires { 0 }; // in seconds since epoch + +private: + qint64 getEntityServerClockSkew() const; +}; + +#endif // hifi_ObjectDynamic_h diff --git a/libraries/physics/src/PhysicalEntitySimulation.cpp b/libraries/physics/src/PhysicalEntitySimulation.cpp index 6f5b474810..3ba1744abc 100644 --- a/libraries/physics/src/PhysicalEntitySimulation.cpp +++ b/libraries/physics/src/PhysicalEntitySimulation.cpp @@ -330,33 +330,33 @@ void PhysicalEntitySimulation::handleCollisionEvents(const CollisionEvents& coll } -void PhysicalEntitySimulation::addAction(EntityActionPointer action) { +void PhysicalEntitySimulation::addDynamic(EntityDynamicPointer dynamic) { if (_physicsEngine) { // FIXME put fine grain locking into _physicsEngine { QMutexLocker lock(&_mutex); - const QUuid& actionID = action->getID(); - if (_physicsEngine->getActionByID(actionID)) { - qCDebug(physics) << "warning -- PhysicalEntitySimulation::addAction -- adding an " - "action that was already in _physicsEngine"; + const QUuid& dynamicID = dynamic->getID(); + if (_physicsEngine->getDynamicByID(dynamicID)) { + qCDebug(physics) << "warning -- PhysicalEntitySimulation::addDynamic -- adding an " + "dynamic that was already in _physicsEngine"; } } - EntitySimulation::addAction(action); + EntitySimulation::addDynamic(dynamic); } } -void PhysicalEntitySimulation::applyActionChanges() { +void PhysicalEntitySimulation::applyDynamicChanges() { if (_physicsEngine) { // FIXME put fine grain locking into _physicsEngine QMutexLocker lock(&_mutex); - foreach(QUuid actionToRemove, _actionsToRemove) { - _physicsEngine->removeAction(actionToRemove); + foreach(QUuid dynamicToRemove, _dynamicsToRemove) { + _physicsEngine->removeDynamic(dynamicToRemove); } - foreach (EntityActionPointer actionToAdd, _actionsToAdd) { - if (!_actionsToRemove.contains(actionToAdd->getID())) { - _physicsEngine->addAction(actionToAdd); + foreach (EntityDynamicPointer dynamicToAdd, _dynamicsToAdd) { + if (!_dynamicsToRemove.contains(dynamicToAdd->getID())) { + _physicsEngine->addDynamic(dynamicToAdd); } } } - EntitySimulation::applyActionChanges(); + EntitySimulation::applyDynamicChanges(); } diff --git a/libraries/physics/src/PhysicalEntitySimulation.h b/libraries/physics/src/PhysicalEntitySimulation.h index 5f6185add3..e0b15440bb 100644 --- a/libraries/physics/src/PhysicalEntitySimulation.h +++ b/libraries/physics/src/PhysicalEntitySimulation.h @@ -34,8 +34,8 @@ public: void init(EntityTreePointer tree, PhysicsEnginePointer engine, EntityEditPacketSender* packetSender); - virtual void addAction(EntityActionPointer action) override; - virtual void applyActionChanges() override; + virtual void addDynamic(EntityDynamicPointer dynamic) override; + virtual void applyDynamicChanges() override; virtual void takeEntitiesToDelete(VectorOfEntities& entitiesToDelete) override; diff --git a/libraries/physics/src/PhysicsEngine.cpp b/libraries/physics/src/PhysicsEngine.cpp index a8a8e6acfd..fd82b05fa5 100644 --- a/libraries/physics/src/PhysicsEngine.cpp +++ b/libraries/physics/src/PhysicsEngine.cpp @@ -548,42 +548,62 @@ void PhysicsEngine::setCharacterController(CharacterController* character) { } } -EntityActionPointer PhysicsEngine::getActionByID(const QUuid& actionID) const { - if (_objectActions.contains(actionID)) { - return _objectActions[actionID]; +EntityDynamicPointer PhysicsEngine::getDynamicByID(const QUuid& dynamicID) const { + if (_objectDynamics.contains(dynamicID)) { + return _objectDynamics[dynamicID]; } return nullptr; } -void PhysicsEngine::addAction(EntityActionPointer action) { - assert(action); - const QUuid& actionID = action->getID(); - if (_objectActions.contains(actionID)) { - if (_objectActions[actionID] == action) { +void PhysicsEngine::addDynamic(EntityDynamicPointer dynamic) { + assert(dynamic); + const QUuid& dynamicID = dynamic->getID(); + if (_objectDynamics.contains(dynamicID)) { + if (_objectDynamics[dynamicID] == dynamic) { return; } - removeAction(action->getID()); + removeDynamic(dynamic->getID()); } - _objectActions[actionID] = action; + _objectDynamics[dynamicID] = dynamic; - // bullet needs a pointer to the action, but it doesn't use shared pointers. + // bullet needs a pointer to the dynamic, but it doesn't use shared pointers. // is there a way to bump the reference count? - ObjectAction* objectAction = static_cast(action.get()); - _dynamicsWorld->addAction(objectAction); -} - -void PhysicsEngine::removeAction(const QUuid actionID) { - if (_objectActions.contains(actionID)) { - EntityActionPointer action = _objectActions[actionID]; - ObjectAction* objectAction = static_cast(action.get()); - _dynamicsWorld->removeAction(objectAction); - _objectActions.remove(actionID); + if (dynamic->isAction()) { + ObjectAction* objectAction = static_cast(dynamic.get()); + _dynamicsWorld->addAction(objectAction); + } else if (dynamic->isConstraint()) { + ObjectConstraint* objectConstraint = static_cast(dynamic.get()); + btTypedConstraint* constraint = objectConstraint->getConstraint(); + if (constraint) { + _dynamicsWorld->addConstraint(constraint); + } else { + qDebug() << "PhysicsEngine::addDynamic of constraint failed"; // XXX + } } } -void PhysicsEngine::forEachAction(std::function actor) { - QHashIterator iter(_objectActions); +void PhysicsEngine::removeDynamic(const QUuid dynamicID) { + if (_objectDynamics.contains(dynamicID)) { + EntityDynamicPointer dynamic = _objectDynamics[dynamicID]; + if (dynamic->isAction()) { + ObjectAction* objectAction = static_cast(dynamic.get()); + _dynamicsWorld->removeAction(objectAction); + } else { + ObjectConstraint* objectConstraint = static_cast(dynamic.get()); + btTypedConstraint* constraint = objectConstraint->getConstraint(); + if (constraint) { + _dynamicsWorld->removeConstraint(constraint); + } else { + qDebug() << "PhysicsEngine::removeDynamic of constraint failed"; // XXX + } + } + _objectDynamics.remove(dynamicID); + } +} + +void PhysicsEngine::forEachDynamic(std::function actor) { + QHashIterator iter(_objectDynamics); while (iter.hasNext()) { iter.next(); actor(iter.value()); diff --git a/libraries/physics/src/PhysicsEngine.h b/libraries/physics/src/PhysicsEngine.h index b2ebe58f08..ec36286dd8 100644 --- a/libraries/physics/src/PhysicsEngine.h +++ b/libraries/physics/src/PhysicsEngine.h @@ -24,6 +24,7 @@ #include "ObjectMotionState.h" #include "ThreadSafeDynamicsWorld.h" #include "ObjectAction.h" +#include "ObjectConstraint.h" const float HALF_SIMULATION_EXTENT = 512.0f; // meters @@ -84,10 +85,10 @@ public: void dumpNextStats() { _dumpNextStats = true; } - EntityActionPointer getActionByID(const QUuid& actionID) const; - void addAction(EntityActionPointer action); - void removeAction(const QUuid actionID); - void forEachAction(std::function actor); + EntityDynamicPointer getDynamicByID(const QUuid& dynamicID) const; + void addDynamic(EntityDynamicPointer dynamic); + void removeDynamic(const QUuid dynamicID); + void forEachDynamic(std::function actor); private: void addObjectToDynamicsWorld(ObjectMotionState* motionState); @@ -110,7 +111,7 @@ private: ContactMap _contactMap; CollisionEvents _collisionEvents; - QHash _objectActions; + QHash _objectDynamics; std::vector _activeStaticBodies; glm::vec3 _originOffset; diff --git a/tests/render-perf/src/main.cpp b/tests/render-perf/src/main.cpp index b76776b1ab..3f4f53c104 100644 --- a/tests/render-perf/src/main.cpp +++ b/tests/render-perf/src/main.cpp @@ -48,8 +48,8 @@ #include #include -#include -#include +#include +#include #include #include #include @@ -365,17 +365,17 @@ public: } }; -class TestActionFactory : public EntityActionFactoryInterface { +class TestActionFactory : public EntityDynamicFactoryInterface { public: - virtual EntityActionPointer factory(EntityActionType type, + virtual EntityDynamicPointer factory(EntityDynamicType type, const QUuid& id, EntityItemPointer ownerEntity, QVariantMap arguments) override { - return EntityActionPointer(); + return EntityDynamicPointer(); } - virtual EntityActionPointer factoryBA(EntityItemPointer ownerEntity, QByteArray data) override { + virtual EntityDynamicPointer factoryBA(EntityItemPointer ownerEntity, QByteArray data) override { return nullptr; } }; @@ -475,7 +475,7 @@ protected: public: //"/-17.2049,-8.08629,-19.4153/0,0.881994,0,-0.47126" static void setup() { - DependencyManager::registerInheritance(); + DependencyManager::registerInheritance(); DependencyManager::registerInheritance(); DependencyManager::registerInheritance(); DependencyManager::set(); From 2b0315645c1a37498ada3ce28edd870f8d3e0b39 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 11 Apr 2017 21:11:03 -0700 Subject: [PATCH 02/26] actions work again --- libraries/physics/src/ObjectAction.h | 4 +++- libraries/physics/src/ObjectConstraint.h | 3 +++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/libraries/physics/src/ObjectAction.h b/libraries/physics/src/ObjectAction.h index 9dbebea95e..8e2f0e3383 100644 --- a/libraries/physics/src/ObjectAction.h +++ b/libraries/physics/src/ObjectAction.h @@ -21,10 +21,12 @@ class ObjectAction : public btActionInterface, public ObjectDynamic { public: ObjectAction(EntityDynamicType type, const QUuid& id, EntityItemPointer ownerEntity); + virtual bool isAction() const override { return true; } + // this is called from updateAction and should be overridden by subclasses virtual void updateActionWorker(float deltaTimeStep) = 0; - // these are from btDynamicInterface + // these are from btActionInterface virtual void updateAction(btCollisionWorld* collisionWorld, btScalar deltaTimeStep) override; virtual void debugDraw(btIDebugDraw* debugDrawer) override; }; diff --git a/libraries/physics/src/ObjectConstraint.h b/libraries/physics/src/ObjectConstraint.h index 8e39fd0a35..9136b5b38c 100644 --- a/libraries/physics/src/ObjectConstraint.h +++ b/libraries/physics/src/ObjectConstraint.h @@ -22,6 +22,9 @@ class ObjectConstraint : public ObjectDynamic public: ObjectConstraint(EntityDynamicType type, const QUuid& id, EntityItemPointer ownerEntity); virtual btTypedConstraint* getConstraint() = 0; + + virtual bool isConstraint() const override { return true; } + protected: btTypedConstraint* _constraint { nullptr }; }; From cc77fce95f8d7d731e7f2d5731edb831981e9d8b Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 12 Apr 2017 07:12:05 -0700 Subject: [PATCH 03/26] hinge is sort-of working --- interface/src/avatar/AvatarActionHold.cpp | 4 ++-- libraries/physics/src/ObjectActionOffset.cpp | 4 ++-- libraries/physics/src/ObjectActionSpring.cpp | 4 ++-- .../src/ObjectActionTravelOriented.cpp | 4 ++-- .../physics/src/ObjectConstraintHinge.cpp | 22 ++++++++++++------- 5 files changed, 22 insertions(+), 16 deletions(-) diff --git a/interface/src/avatar/AvatarActionHold.cpp b/interface/src/avatar/AvatarActionHold.cpp index e468911daf..98ff687eb3 100644 --- a/interface/src/avatar/AvatarActionHold.cpp +++ b/interface/src/avatar/AvatarActionHold.cpp @@ -323,7 +323,7 @@ bool AvatarActionHold::updateArguments(QVariantMap arguments) { bool ignoreIK; bool needUpdate = false; - bool somethingChanged = ObjectAction::updateArguments(arguments); + bool somethingChanged = ObjectDynamic::updateArguments(arguments); withReadLock([&]{ bool ok = true; relativePosition = EntityDynamicInterface::extractVec3Argument("hold", arguments, "relativePosition", ok, false); @@ -410,7 +410,7 @@ bool AvatarActionHold::updateArguments(QVariantMap arguments) { } QVariantMap AvatarActionHold::getArguments() { - QVariantMap arguments = ObjectAction::getArguments(); + QVariantMap arguments = ObjectDynamic::getArguments(); withReadLock([&]{ arguments["holderID"] = _holderID; arguments["relativePosition"] = glmToQMap(_relativePosition); diff --git a/libraries/physics/src/ObjectActionOffset.cpp b/libraries/physics/src/ObjectActionOffset.cpp index c011a2db4d..c1fb397e19 100644 --- a/libraries/physics/src/ObjectActionOffset.cpp +++ b/libraries/physics/src/ObjectActionOffset.cpp @@ -88,7 +88,7 @@ bool ObjectActionOffset::updateArguments(QVariantMap arguments) { float linearDistance; bool needUpdate = false; - bool somethingChanged = ObjectAction::updateArguments(arguments); + bool somethingChanged = ObjectDynamic::updateArguments(arguments); withReadLock([&]{ bool ok = true; @@ -143,7 +143,7 @@ bool ObjectActionOffset::updateArguments(QVariantMap arguments) { } QVariantMap ObjectActionOffset::getArguments() { - QVariantMap arguments = ObjectAction::getArguments(); + QVariantMap arguments = ObjectDynamic::getArguments(); withReadLock([&] { arguments["pointToOffsetFrom"] = glmToQMap(_pointToOffsetFrom); arguments["linearTimeScale"] = _linearTimeScale; diff --git a/libraries/physics/src/ObjectActionSpring.cpp b/libraries/physics/src/ObjectActionSpring.cpp index ac92384101..2faa681c1d 100644 --- a/libraries/physics/src/ObjectActionSpring.cpp +++ b/libraries/physics/src/ObjectActionSpring.cpp @@ -190,7 +190,7 @@ bool ObjectActionSpring::updateArguments(QVariantMap arguments) { float angularTimeScale; bool needUpdate = false; - bool somethingChanged = ObjectAction::updateArguments(arguments); + bool somethingChanged = ObjectDynamic::updateArguments(arguments); withReadLock([&]{ // targets are required, spring-constants are optional bool ok = true; @@ -248,7 +248,7 @@ bool ObjectActionSpring::updateArguments(QVariantMap arguments) { } QVariantMap ObjectActionSpring::getArguments() { - QVariantMap arguments = ObjectAction::getArguments(); + QVariantMap arguments = ObjectDynamic::getArguments(); withReadLock([&] { arguments["linearTimeScale"] = _linearTimeScale; arguments["targetPosition"] = glmToQMap(_desiredPositionalTarget); diff --git a/libraries/physics/src/ObjectActionTravelOriented.cpp b/libraries/physics/src/ObjectActionTravelOriented.cpp index f2b841c9da..8ab24511d7 100644 --- a/libraries/physics/src/ObjectActionTravelOriented.cpp +++ b/libraries/physics/src/ObjectActionTravelOriented.cpp @@ -106,7 +106,7 @@ bool ObjectActionTravelOriented::updateArguments(QVariantMap arguments) { float angularTimeScale; bool needUpdate = false; - bool somethingChanged = ObjectAction::updateArguments(arguments); + bool somethingChanged = ObjectDynamic::updateArguments(arguments); withReadLock([&]{ bool ok = true; forward = EntityDynamicInterface::extractVec3Argument("travel oriented action", arguments, "forward", ok, true); @@ -147,7 +147,7 @@ bool ObjectActionTravelOriented::updateArguments(QVariantMap arguments) { } QVariantMap ObjectActionTravelOriented::getArguments() { - QVariantMap arguments = ObjectAction::getArguments(); + QVariantMap arguments = ObjectDynamic::getArguments(); withReadLock([&] { arguments["forward"] = glmToQMap(_forward); arguments["angularTimeScale"] = _angularTimeScale; diff --git a/libraries/physics/src/ObjectConstraintHinge.cpp b/libraries/physics/src/ObjectConstraintHinge.cpp index d151ffeb6f..7ecce9bc49 100644 --- a/libraries/physics/src/ObjectConstraintHinge.cpp +++ b/libraries/physics/src/ObjectConstraintHinge.cpp @@ -42,6 +42,7 @@ btTypedConstraint* ObjectConstraintHinge::getConstraint() { btRigidBody* rigidBodyA = getRigidBody(); if (!rigidBodyA) { + qCDebug(physics) << "ObjectConstraintHinge::getConstraint -- no rigidBodyA"; return nullptr; } @@ -49,8 +50,14 @@ btTypedConstraint* ObjectConstraintHinge::getConstraint() { btTransform rigidBodyAFrame(glmToBullet(_rbARotation), glmToBullet(_rbATranslation)); - _constraint = new btHingeConstraint(*rigidBodyA, rigidBodyAFrame, useReferenceFrameA); - return _constraint; + btHingeConstraint* constraint = new btHingeConstraint(*rigidBodyA, rigidBodyAFrame, useReferenceFrameA); + _constraint = constraint; + // constraint->setAngularOnly(true); + + btVector3 axisInA = glmToBullet(glm::vec3(0.0f, 1.0f, 0.0f)); + constraint->setAxis(axisInA); + + return constraint; } @@ -61,15 +68,14 @@ bool ObjectConstraintHinge::updateArguments(QVariantMap arguments) { bool needUpdate = false; bool somethingChanged = ObjectConstraint::updateArguments(arguments); withReadLock([&]{ - // targets are required, hinge-constants are optional bool ok = true; - rbATranslation = EntityDynamicInterface::extractVec3Argument("hinge constraint", arguments, "targetPosition", ok, false); + rbATranslation = EntityDynamicInterface::extractVec3Argument("hinge constraint", arguments, "aTranslation", ok, false); if (!ok) { rbATranslation = _rbATranslation; } ok = true; - rbARotation = EntityDynamicInterface::extractQuatArgument("hinge constraint", arguments, "targetRotation", ok, false); + rbARotation = EntityDynamicInterface::extractQuatArgument("hinge constraint", arguments, "aRotation", ok, false); if (!ok) { rbARotation = _rbARotation; } @@ -94,7 +100,7 @@ bool ObjectConstraintHinge::updateArguments(QVariantMap arguments) { ownerEntity->setDynamicDataNeedsTransmit(true); } }); - activateBody(); + // activateBody(); } return true; @@ -103,8 +109,8 @@ bool ObjectConstraintHinge::updateArguments(QVariantMap arguments) { QVariantMap ObjectConstraintHinge::getArguments() { QVariantMap arguments = ObjectConstraint::getArguments(); withReadLock([&] { - arguments["targetPosition"] = glmToQMap(_rbATranslation); - arguments["targetRotation"] = glmToQMap(_rbARotation); + arguments["aTranslation"] = glmToQMap(_rbATranslation); + arguments["aRotation"] = glmToQMap(_rbARotation); }); return arguments; } From 53cb192af1784729779c6815e592d3c1ecd8be06 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 12 Apr 2017 07:22:27 -0700 Subject: [PATCH 04/26] fixed names of pivot and axis --- .../physics/src/ObjectConstraintHinge.cpp | 40 +++++++++---------- libraries/physics/src/ObjectConstraintHinge.h | 4 +- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/libraries/physics/src/ObjectConstraintHinge.cpp b/libraries/physics/src/ObjectConstraintHinge.cpp index 7ecce9bc49..9823cf4882 100644 --- a/libraries/physics/src/ObjectConstraintHinge.cpp +++ b/libraries/physics/src/ObjectConstraintHinge.cpp @@ -21,8 +21,8 @@ const uint16_t ObjectConstraintHinge::constraintVersion = 1; ObjectConstraintHinge::ObjectConstraintHinge(const QUuid& id, EntityItemPointer ownerEntity) : ObjectConstraint(DYNAMIC_TYPE_HINGE, id, ownerEntity), - _rbATranslation(glm::vec3(0.0f)), - _rbARotation(glm::quat()) + _pivotInA(glm::vec3(0.0f)), + _axis(glm::vec3(0.0f)) { #if WANT_DEBUG qCDebug(physics) << "ObjectConstraintHinge::ObjectConstraintHinge"; @@ -48,13 +48,13 @@ btTypedConstraint* ObjectConstraintHinge::getConstraint() { bool useReferenceFrameA { false }; - btTransform rigidBodyAFrame(glmToBullet(_rbARotation), glmToBullet(_rbATranslation)); + btTransform rigidBodyAFrame(btQuaternion(0.0f, 0.0f, 0.0f, 1.0f), glmToBullet(_pivotInA)); btHingeConstraint* constraint = new btHingeConstraint(*rigidBodyA, rigidBodyAFrame, useReferenceFrameA); _constraint = constraint; // constraint->setAngularOnly(true); - btVector3 axisInA = glmToBullet(glm::vec3(0.0f, 1.0f, 0.0f)); + btVector3 axisInA = glmToBullet(_axis); constraint->setAxis(axisInA); return constraint; @@ -62,27 +62,27 @@ btTypedConstraint* ObjectConstraintHinge::getConstraint() { bool ObjectConstraintHinge::updateArguments(QVariantMap arguments) { - glm::vec3 rbATranslation; - glm::quat rbARotation; + glm::vec3 pivotInA; + glm::vec3 axis; bool needUpdate = false; bool somethingChanged = ObjectConstraint::updateArguments(arguments); withReadLock([&]{ bool ok = true; - rbATranslation = EntityDynamicInterface::extractVec3Argument("hinge constraint", arguments, "aTranslation", ok, false); + pivotInA = EntityDynamicInterface::extractVec3Argument("hinge constraint", arguments, "pivot", ok, false); if (!ok) { - rbATranslation = _rbATranslation; + pivotInA = _pivotInA; } ok = true; - rbARotation = EntityDynamicInterface::extractQuatArgument("hinge constraint", arguments, "aRotation", ok, false); + axis = EntityDynamicInterface::extractVec3Argument("hinge constraint", arguments, "axis", ok, false); if (!ok) { - rbARotation = _rbARotation; + axis = _axis; } if (somethingChanged || - rbATranslation != _rbATranslation || - rbARotation != _rbARotation) { + pivotInA != _pivotInA || + axis != _axis) { // something changed needUpdate = true; } @@ -90,8 +90,8 @@ bool ObjectConstraintHinge::updateArguments(QVariantMap arguments) { if (needUpdate) { withWriteLock([&] { - _rbATranslation = rbATranslation; - _rbARotation = rbARotation; + _pivotInA = pivotInA; + _axis = axis; _active = true; auto ownerEntity = _ownerEntity.lock(); @@ -109,8 +109,8 @@ bool ObjectConstraintHinge::updateArguments(QVariantMap arguments) { QVariantMap ObjectConstraintHinge::getArguments() { QVariantMap arguments = ObjectConstraint::getArguments(); withReadLock([&] { - arguments["aTranslation"] = glmToQMap(_rbATranslation); - arguments["aRotation"] = glmToQMap(_rbARotation); + arguments["pivot"] = glmToQMap(_pivotInA); + arguments["axis"] = glmToQMap(_axis); }); return arguments; } @@ -124,8 +124,8 @@ QByteArray ObjectConstraintHinge::serialize() const { dataStream << ObjectConstraintHinge::constraintVersion; withReadLock([&] { - dataStream << _rbATranslation; - dataStream << _rbARotation; + dataStream << _pivotInA; + dataStream << _axis; dataStream << localTimeToServerTime(_expires); dataStream << _tag; }); @@ -152,8 +152,8 @@ void ObjectConstraintHinge::deserialize(QByteArray serializedArguments) { } withWriteLock([&] { - dataStream >> _rbATranslation; - dataStream >> _rbARotation; + dataStream >> _pivotInA; + dataStream >> _axis; quint64 serverExpires; dataStream >> serverExpires; diff --git a/libraries/physics/src/ObjectConstraintHinge.h b/libraries/physics/src/ObjectConstraintHinge.h index e4e5c392ae..ba451937ca 100644 --- a/libraries/physics/src/ObjectConstraintHinge.h +++ b/libraries/physics/src/ObjectConstraintHinge.h @@ -32,8 +32,8 @@ public: protected: static const uint16_t constraintVersion; - glm::vec3 _rbATranslation; - glm::quat _rbARotation; + glm::vec3 _pivotInA; + glm::vec3 _axis; }; #endif // hifi_ObjectConstraintHinge_h From 9f252f04e7d1e23af7b478bad7b55556f6d34ac6 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 12 Apr 2017 07:25:23 -0700 Subject: [PATCH 05/26] cleanups --- libraries/physics/src/ObjectConstraintHinge.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/physics/src/ObjectConstraintHinge.cpp b/libraries/physics/src/ObjectConstraintHinge.cpp index 9823cf4882..ec27ead647 100644 --- a/libraries/physics/src/ObjectConstraintHinge.cpp +++ b/libraries/physics/src/ObjectConstraintHinge.cpp @@ -51,12 +51,12 @@ btTypedConstraint* ObjectConstraintHinge::getConstraint() { btTransform rigidBodyAFrame(btQuaternion(0.0f, 0.0f, 0.0f, 1.0f), glmToBullet(_pivotInA)); btHingeConstraint* constraint = new btHingeConstraint(*rigidBodyA, rigidBodyAFrame, useReferenceFrameA); - _constraint = constraint; // constraint->setAngularOnly(true); btVector3 axisInA = glmToBullet(_axis); constraint->setAxis(axisInA); + _constraint = constraint; return constraint; } @@ -66,7 +66,7 @@ bool ObjectConstraintHinge::updateArguments(QVariantMap arguments) { glm::vec3 axis; bool needUpdate = false; - bool somethingChanged = ObjectConstraint::updateArguments(arguments); + bool somethingChanged = ObjectDynamic::updateArguments(arguments); withReadLock([&]{ bool ok = true; pivotInA = EntityDynamicInterface::extractVec3Argument("hinge constraint", arguments, "pivot", ok, false); @@ -107,7 +107,7 @@ bool ObjectConstraintHinge::updateArguments(QVariantMap arguments) { } QVariantMap ObjectConstraintHinge::getArguments() { - QVariantMap arguments = ObjectConstraint::getArguments(); + QVariantMap arguments = ObjectDynamic::getArguments(); withReadLock([&] { arguments["pivot"] = glmToQMap(_pivotInA); arguments["axis"] = glmToQMap(_axis); From 507f658a5f0f858552c06b6569b5e88567eb1870 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 12 Apr 2017 07:37:41 -0700 Subject: [PATCH 06/26] update comment --- .../entities/src/EntityDynamicInterface.cpp | 58 +++++++++++-------- 1 file changed, 33 insertions(+), 25 deletions(-) diff --git a/libraries/entities/src/EntityDynamicInterface.cpp b/libraries/entities/src/EntityDynamicInterface.cpp index 053e51cf9c..5ad608f45f 100644 --- a/libraries/entities/src/EntityDynamicInterface.cpp +++ b/libraries/entities/src/EntityDynamicInterface.cpp @@ -13,31 +13,39 @@ /* - - - - +-----------------------+ +-------------------+ +---------------------------------+ - | | | | | | - | EntityDynamicInterface | | btDynamicInterface | | EntityDynamicFactoryInterface | - | (entities) | | (bullet) | | (entities) | - +-----------------------+ +-------------------+ +---------------------------------+ - | | | | | - +----+ +--+ +----------+ | | - | | | | | - +-------------------+ +--------------+ +---------------------------+ +--------------------------+ - | | | | | | | | - | AssignmentDynamic | | ObjectDynamic | | InterfaceDynamicFactory | | AssignmentDynamicFactory | - |(assignment client)| | (physics) | | (interface) | | (assignment client) | - +-------------------+ +--------------+ +---------------------------+ +--------------------------+ - | - | - | - +--------------------+ - | | - | ObjectDynamicSpring | - | (physics) | - +--------------------+ - + +-------------------------+ +--------------------------------+ + | | | | + | EntityDynamicsInterface | | EntityDynamicsFactoryInterface | + | (entities) | | (entities) | + +-------------------------+ +--------------------------------+ + | | | | + +----+ +--+ | | + | | | | + +---------------------+ +----------------+ +--------------------------+ +---------------------------+ + | | | | | | | | + | AssignmentDynamics | | ObjectDynamics | | InterfaceDynamicsFactory | | AssignmentDynamicsFactory | + |(assignment client) | | (physics) | | (interface) | | (assignment client) | + +---------------------+ +----------------+ +--------------------------+ +---------------------------+ + | | + | | + +---------------------+ | | + | | | | + | btActionInterface | | | + | (bullet) | | | + +---------------------+ | | + | | | + +--------------+ +------------------+ +-------------------+ + | | | | | | + | ObjectAction | | ObjectConstraint | | btTypedConstraint | + | (physics) | | (physics) --|--->| (bullet) | + +--------------+ +------------------+ +-------------------+ + | | + | | + +--------------------+ +-----------------------+ + | | | | + | ObjectActionSpring | | ObjectConstraintHinge | + | (physics) | | (physics) | + +--------------------+ +-----------------------+ From 026dde2e6873afd88ef51701a8e259e41f269374 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 12 Apr 2017 10:14:16 -0700 Subject: [PATCH 07/26] allow kinematic near-grab to be turned on or off for a given entity --- scripts/system/controllers/handControllerGrab.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/scripts/system/controllers/handControllerGrab.js b/scripts/system/controllers/handControllerGrab.js index d1c00a9d81..0dfe64bbaa 100644 --- a/scripts/system/controllers/handControllerGrab.js +++ b/scripts/system/controllers/handControllerGrab.js @@ -2741,7 +2741,7 @@ function MyController(hand) { relativePosition: this.offsetPosition, relativeRotation: this.offsetRotation, ttl: ACTION_TTL, - kinematic: NEAR_GRABBING_KINEMATIC, + kinematic: this.kinematicGrab, kinematicSetVelocity: true, ignoreIK: this.ignoreIK }); @@ -2838,12 +2838,14 @@ function MyController(hand) { this.ignoreIK = true; } else { grabbedProperties = Entities.getEntityProperties(this.grabbedThingID, GRABBABLE_PROPERTIES); + var grabbableData = getEntityCustomData(GRABBABLE_DATA_KEY, this.grabbedThingID, DEFAULT_GRABBABLE_DATA); if (FORCE_IGNORE_IK) { this.ignoreIK = true; } else { - var grabbableData = getEntityCustomData(GRABBABLE_DATA_KEY, this.grabbedThingID, DEFAULT_GRABBABLE_DATA); this.ignoreIK = (grabbableData.ignoreIK !== undefined) ? grabbableData.ignoreIK : true; } + + this.kinematicGrab = (grabbableData.kinematic !== undefined) ? grabbableData.kinematic : NEAR_GRABBING_KINEMATIC; } var handRotation; @@ -3207,7 +3209,7 @@ function MyController(hand) { relativePosition: this.offsetPosition, relativeRotation: this.offsetRotation, ttl: ACTION_TTL, - kinematic: NEAR_GRABBING_KINEMATIC, + kinematic: this.kinematicGrab, kinematicSetVelocity: true, ignoreIK: this.ignoreIK }); From 9b12956909bf2ccedea917fc17aaaaba5f790142 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 12 Apr 2017 16:34:34 -0700 Subject: [PATCH 08/26] formatting --- .../entities/src/EntityDynamicInterface.cpp | 27 +++++++++---------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/libraries/entities/src/EntityDynamicInterface.cpp b/libraries/entities/src/EntityDynamicInterface.cpp index 5ad608f45f..b7160bbcb6 100644 --- a/libraries/entities/src/EntityDynamicInterface.cpp +++ b/libraries/entities/src/EntityDynamicInterface.cpp @@ -87,7 +87,7 @@ deserializer in the ObjectDynamic subclass to be called with the new data, there variables. These argument variables are used by the code which is run when bullet does a callback. - */ +*/ #include "EntityItem.h" @@ -115,7 +115,8 @@ EntityDynamicType EntityDynamicInterface::dynamicTypeFromString(QString dynamicT return DYNAMIC_TYPE_HINGE; } - qCDebug(entities) << "Warning -- EntityDynamicInterface::dynamicTypeFromString got unknown dynamic-type name" << dynamicTypeString; + qCDebug(entities) << "Warning -- EntityDynamicInterface::dynamicTypeFromString got unknown dynamic-type name" + << dynamicTypeString; return DYNAMIC_TYPE_NONE; } @@ -139,7 +140,7 @@ QString EntityDynamicInterface::dynamicTypeToString(EntityDynamicType dynamicTyp } glm::vec3 EntityDynamicInterface::extractVec3Argument(QString objectName, QVariantMap arguments, - QString argumentName, bool& ok, bool required) { + QString argumentName, bool& ok, bool required) { if (!arguments.contains(argumentName)) { if (required) { qCDebug(entities) << objectName << "requires argument:" << argumentName; @@ -188,7 +189,7 @@ glm::vec3 EntityDynamicInterface::extractVec3Argument(QString objectName, QVaria } glm::quat EntityDynamicInterface::extractQuatArgument(QString objectName, QVariantMap arguments, - QString argumentName, bool& ok, bool required) { + QString argumentName, bool& ok, bool required) { if (!arguments.contains(argumentName)) { if (required) { qCDebug(entities) << objectName << "requires argument:" << argumentName; @@ -226,7 +227,7 @@ glm::quat EntityDynamicInterface::extractQuatArgument(QString objectName, QVaria float w = wV.toFloat(&wOk); if (!xOk || !yOk || !zOk || !wOk) { qCDebug(entities) << objectName << "argument" << argumentName - << "must be a map with keys: x, y, z, and w of type float."; + << "must be a map with keys: x, y, z, and w of type float."; ok = false; return glm::quat(); } @@ -241,7 +242,7 @@ glm::quat EntityDynamicInterface::extractQuatArgument(QString objectName, QVaria } float EntityDynamicInterface::extractFloatArgument(QString objectName, QVariantMap arguments, - QString argumentName, bool& ok, bool required) { + QString argumentName, bool& ok, bool required) { if (!arguments.contains(argumentName)) { if (required) { qCDebug(entities) << objectName << "requires argument:" << argumentName; @@ -263,7 +264,7 @@ float EntityDynamicInterface::extractFloatArgument(QString objectName, QVariantM } int EntityDynamicInterface::extractIntegerArgument(QString objectName, QVariantMap arguments, - QString argumentName, bool& ok, bool required) { + QString argumentName, bool& ok, bool required) { if (!arguments.contains(argumentName)) { if (required) { qCDebug(entities) << objectName << "requires argument:" << argumentName; @@ -285,7 +286,7 @@ int EntityDynamicInterface::extractIntegerArgument(QString objectName, QVariantM } QString EntityDynamicInterface::extractStringArgument(QString objectName, QVariantMap arguments, - QString argumentName, bool& ok, bool required) { + QString argumentName, bool& ok, bool required) { if (!arguments.contains(argumentName)) { if (required) { qCDebug(entities) << objectName << "requires argument:" << argumentName; @@ -297,7 +298,7 @@ QString EntityDynamicInterface::extractStringArgument(QString objectName, QVaria } bool EntityDynamicInterface::extractBooleanArgument(QString objectName, QVariantMap arguments, - QString argumentName, bool& ok, bool required) { + QString argumentName, bool& ok, bool required) { if (!arguments.contains(argumentName)) { if (required) { qCDebug(entities) << objectName << "requires argument:" << argumentName; @@ -308,15 +309,11 @@ bool EntityDynamicInterface::extractBooleanArgument(QString objectName, QVariant return arguments[argumentName].toBool(); } - - -QDataStream& operator<<(QDataStream& stream, const EntityDynamicType& entityDynamicType) -{ +QDataStream& operator<<(QDataStream& stream, const EntityDynamicType& entityDynamicType) { return stream << (quint16)entityDynamicType; } -QDataStream& operator>>(QDataStream& stream, EntityDynamicType& entityDynamicType) -{ +QDataStream& operator>>(QDataStream& stream, EntityDynamicType& entityDynamicType) { quint16 dynamicTypeAsInt; stream >> dynamicTypeAsInt; entityDynamicType = (EntityDynamicType)dynamicTypeAsInt; From 1ab3a1eb60986f4ac058d3bba2b0ff80b7b0b7d0 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 12 Apr 2017 16:36:04 -0700 Subject: [PATCH 09/26] bump entity-protocol version --- libraries/networking/src/udt/PacketHeaders.cpp | 2 +- libraries/networking/src/udt/PacketHeaders.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/networking/src/udt/PacketHeaders.cpp b/libraries/networking/src/udt/PacketHeaders.cpp index 246821908a..12bec7f607 100644 --- a/libraries/networking/src/udt/PacketHeaders.cpp +++ b/libraries/networking/src/udt/PacketHeaders.cpp @@ -49,7 +49,7 @@ PacketVersion versionForPacketType(PacketType packetType) { case PacketType::EntityEdit: case PacketType::EntityData: case PacketType::EntityPhysics: - return VERSION_ENTITIES_ZONE_FILTERS; + return VERSION_ENTITIES_HINGE_DYNAMIC; case PacketType::EntityQuery: return static_cast(EntityQueryPacketVersion::JSONFilterWithFamilyTree); case PacketType::AvatarIdentity: diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index 03a773f24f..e411bd1868 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -206,6 +206,7 @@ const PacketVersion VERSION_ENTITIES_LAST_EDITED_BY = 65; const PacketVersion VERSION_ENTITIES_SERVER_SCRIPTS = 66; const PacketVersion VERSION_ENTITIES_PHYSICS_PACKET = 67; const PacketVersion VERSION_ENTITIES_ZONE_FILTERS = 68; +const PacketVersion VERSION_ENTITIES_HINGE_DYNAMIC = 69; enum class EntityQueryPacketVersion: PacketVersion { JSONFilter = 18, From 7695d2ac052ea8066a693c52ee1a46f6e82810cd Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 13 Apr 2017 11:29:40 -0700 Subject: [PATCH 10/26] put the protocol version back to what's in master, for now --- libraries/networking/src/udt/PacketHeaders.cpp | 2 +- libraries/networking/src/udt/PacketHeaders.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/networking/src/udt/PacketHeaders.cpp b/libraries/networking/src/udt/PacketHeaders.cpp index 12bec7f607..7d0f36ff6e 100644 --- a/libraries/networking/src/udt/PacketHeaders.cpp +++ b/libraries/networking/src/udt/PacketHeaders.cpp @@ -49,7 +49,7 @@ PacketVersion versionForPacketType(PacketType packetType) { case PacketType::EntityEdit: case PacketType::EntityData: case PacketType::EntityPhysics: - return VERSION_ENTITIES_HINGE_DYNAMIC; + return VERSION_ENTITIES_MORE_DYNAMICS; case PacketType::EntityQuery: return static_cast(EntityQueryPacketVersion::JSONFilterWithFamilyTree); case PacketType::AvatarIdentity: diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index e411bd1868..75984211e2 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -207,6 +207,7 @@ const PacketVersion VERSION_ENTITIES_SERVER_SCRIPTS = 66; const PacketVersion VERSION_ENTITIES_PHYSICS_PACKET = 67; const PacketVersion VERSION_ENTITIES_ZONE_FILTERS = 68; const PacketVersion VERSION_ENTITIES_HINGE_DYNAMIC = 69; +const PacketVersion VERSION_ENTITIES_MORE_DYNAMICS = 68; // XXX enum class EntityQueryPacketVersion: PacketVersion { JSONFilter = 18, From afa8fc161b3c58d672b2c93981941c0308af645d Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 13 Apr 2017 15:37:28 -0700 Subject: [PATCH 11/26] allow hinge constraint between two entities --- .../entities/src/EntityDynamicInterface.h | 1 + .../physics/src/ObjectConstraintHinge.cpp | 132 +++++++++++++++--- libraries/physics/src/ObjectConstraintHinge.h | 7 +- libraries/physics/src/ObjectDynamic.cpp | 14 ++ libraries/physics/src/ObjectDynamic.h | 1 + .../physics/src/PhysicalEntitySimulation.cpp | 10 +- libraries/physics/src/PhysicsEngine.cpp | 14 +- libraries/physics/src/PhysicsEngine.h | 2 +- 8 files changed, 156 insertions(+), 25 deletions(-) diff --git a/libraries/entities/src/EntityDynamicInterface.h b/libraries/entities/src/EntityDynamicInterface.h index f6dba84fc5..f4b7efc7a6 100644 --- a/libraries/entities/src/EntityDynamicInterface.h +++ b/libraries/entities/src/EntityDynamicInterface.h @@ -42,6 +42,7 @@ public: EntityDynamicType getType() const { return _type; } virtual bool isAction() const { return false; } virtual bool isConstraint() const { return false; } + virtual bool isReadyForAdd() const { return true; } bool isActive() { return _active; } diff --git a/libraries/physics/src/ObjectConstraintHinge.cpp b/libraries/physics/src/ObjectConstraintHinge.cpp index ec27ead647..b6c19e96ce 100644 --- a/libraries/physics/src/ObjectConstraintHinge.cpp +++ b/libraries/physics/src/ObjectConstraintHinge.cpp @@ -11,8 +11,8 @@ #include "QVariantGLM.h" +#include "EntityTree.h" #include "ObjectConstraintHinge.h" - #include "PhysicsLogging.h" @@ -22,7 +22,7 @@ const uint16_t ObjectConstraintHinge::constraintVersion = 1; ObjectConstraintHinge::ObjectConstraintHinge(const QUuid& id, EntityItemPointer ownerEntity) : ObjectConstraint(DYNAMIC_TYPE_HINGE, id, ownerEntity), _pivotInA(glm::vec3(0.0f)), - _axis(glm::vec3(0.0f)) + _axisInA(glm::vec3(0.0f)) { #if WANT_DEBUG qCDebug(physics) << "ObjectConstraintHinge::ObjectConstraintHinge"; @@ -36,8 +36,23 @@ ObjectConstraintHinge::~ObjectConstraintHinge() { } btTypedConstraint* ObjectConstraintHinge::getConstraint() { - if (_constraint) { - return _constraint; + btHingeConstraint* constraint { nullptr }; + QUuid otherEntityID; + glm::vec3 pivotInA; + glm::vec3 axisInA; + glm::vec3 pivotInB; + glm::vec3 axisInB; + + withReadLock([&]{ + constraint = static_cast(_constraint); + pivotInA = _pivotInA; + axisInA = _axisInA; + otherEntityID = _otherEntityID; + pivotInB = _pivotInB; + axisInB = _axisInB; + }); + if (constraint) { + return constraint; } btRigidBody* rigidBodyA = getRigidBody(); @@ -48,22 +63,67 @@ btTypedConstraint* ObjectConstraintHinge::getConstraint() { bool useReferenceFrameA { false }; - btTransform rigidBodyAFrame(btQuaternion(0.0f, 0.0f, 0.0f, 1.0f), glmToBullet(_pivotInA)); + if (!otherEntityID.isNull()) { + // This hinge is between two entities... find the other rigid body. + EntityItemPointer otherEntity = getEntityByID(otherEntityID); + if (!otherEntity) { + return nullptr; + } - btHingeConstraint* constraint = new btHingeConstraint(*rigidBodyA, rigidBodyAFrame, useReferenceFrameA); - // constraint->setAngularOnly(true); + void* otherPhysicsInfo = otherEntity->getPhysicsInfo(); + if (!otherPhysicsInfo) { + return nullptr; + } + ObjectMotionState* otherMotionState = static_cast(otherPhysicsInfo); + if (!otherMotionState) { + return nullptr; + } + btRigidBody* rigidBodyB = otherMotionState->getRigidBody(); + if (!rigidBodyB) { + return nullptr; + } - btVector3 axisInA = glmToBullet(_axis); - constraint->setAxis(axisInA); + btTransform rigidBodyAFrame(btQuaternion(0.0f, 0.0f, 0.0f, 1.0f), glmToBullet(pivotInA)); + btTransform rigidBodyBFrame(btQuaternion(0.0f, 0.0f, 0.0f, 1.0f), glmToBullet(pivotInB)); - _constraint = constraint; - return constraint; + constraint = new btHingeConstraint(*rigidBodyA, *rigidBodyB, + rigidBodyAFrame, rigidBodyBFrame, + useReferenceFrameA); + + btVector3 bulletAxisInA = glmToBullet(axisInA); + constraint->setAxis(bulletAxisInA); + + withWriteLock([&]{ + _otherEntity = otherEntity; // save weak-pointer to the other entity + _constraint = constraint; + }); + + return constraint; + } else { + // This hinge is between an entity and the world-frame. + btTransform rigidBodyAFrame(btQuaternion(0.0f, 0.0f, 0.0f, 1.0f), glmToBullet(pivotInA)); + + constraint = new btHingeConstraint(*rigidBodyA, rigidBodyAFrame, useReferenceFrameA); + // constraint->setAngularOnly(true); + + btVector3 bulletAxisInA = glmToBullet(axisInA); + constraint->setAxis(bulletAxisInA); + + withWriteLock([&]{ + _otherEntity.reset(); + _constraint = constraint; + }); + return constraint; + } } bool ObjectConstraintHinge::updateArguments(QVariantMap arguments) { glm::vec3 pivotInA; - glm::vec3 axis; + glm::vec3 axisInA; + QUuid otherEntityID; + glm::vec3 pivotInB; + glm::vec3 axisInB; bool needUpdate = false; bool somethingChanged = ObjectDynamic::updateArguments(arguments); @@ -75,14 +135,35 @@ bool ObjectConstraintHinge::updateArguments(QVariantMap arguments) { } ok = true; - axis = EntityDynamicInterface::extractVec3Argument("hinge constraint", arguments, "axis", ok, false); + axisInA = EntityDynamicInterface::extractVec3Argument("hinge constraint", arguments, "axis", ok, false); if (!ok) { - axis = _axis; + axisInA = _axisInA; + } + + ok = true; + otherEntityID = QUuid(EntityDynamicInterface::extractStringArgument("hinge constraint", + arguments, "otherEntityID", ok, false)); + if (!ok) { + otherEntityID = QUuid(); + } + + ok = true; + pivotInB = EntityDynamicInterface::extractVec3Argument("hinge constraint", arguments, "otherPivot", ok, false); + if (!ok) { + pivotInB = _pivotInB; + } + + ok = true; + axisInB = EntityDynamicInterface::extractVec3Argument("hinge constraint", arguments, "otherAxis", ok, false); + if (!ok) { + axisInB = _axisInB; } if (somethingChanged || pivotInA != _pivotInA || - axis != _axis) { + axisInA != _axisInA || + pivotInB != _pivotInB || + axisInB != _axisInB) { // something changed needUpdate = true; } @@ -91,7 +172,11 @@ bool ObjectConstraintHinge::updateArguments(QVariantMap arguments) { if (needUpdate) { withWriteLock([&] { _pivotInA = pivotInA; - _axis = axis; + _axisInA = axisInA; + _otherEntityID = otherEntityID; + _pivotInB = pivotInB; + _axisInB = axisInB; + _active = true; auto ownerEntity = _ownerEntity.lock(); @@ -110,7 +195,10 @@ QVariantMap ObjectConstraintHinge::getArguments() { QVariantMap arguments = ObjectDynamic::getArguments(); withReadLock([&] { arguments["pivot"] = glmToQMap(_pivotInA); - arguments["axis"] = glmToQMap(_axis); + arguments["axis"] = glmToQMap(_axisInA); + arguments["otherEntityID"] = _otherEntityID; + arguments["otherPivot"] = glmToQMap(_pivotInB); + arguments["otherAxis"] = glmToQMap(_axisInB); }); return arguments; } @@ -125,7 +213,10 @@ QByteArray ObjectConstraintHinge::serialize() const { withReadLock([&] { dataStream << _pivotInA; - dataStream << _axis; + dataStream << _axisInA; + dataStream << _otherEntityID; + dataStream << _pivotInB; + dataStream << _axisInB; dataStream << localTimeToServerTime(_expires); dataStream << _tag; }); @@ -153,7 +244,10 @@ void ObjectConstraintHinge::deserialize(QByteArray serializedArguments) { withWriteLock([&] { dataStream >> _pivotInA; - dataStream >> _axis; + dataStream >> _axisInA; + dataStream >> _otherEntityID; + dataStream >> _pivotInB; + dataStream >> _axisInB; quint64 serverExpires; dataStream >> serverExpires; diff --git a/libraries/physics/src/ObjectConstraintHinge.h b/libraries/physics/src/ObjectConstraintHinge.h index ba451937ca..7823b85758 100644 --- a/libraries/physics/src/ObjectConstraintHinge.h +++ b/libraries/physics/src/ObjectConstraintHinge.h @@ -33,7 +33,12 @@ protected: static const uint16_t constraintVersion; glm::vec3 _pivotInA; - glm::vec3 _axis; + glm::vec3 _axisInA; + + QUuid _otherEntityID; + EntityItemWeakPointer _otherEntity; + glm::vec3 _pivotInB; + glm::vec3 _axisInB; }; #endif // hifi_ObjectConstraintHinge_h diff --git a/libraries/physics/src/ObjectDynamic.cpp b/libraries/physics/src/ObjectDynamic.cpp index f887cc42dc..4831c44705 100644 --- a/libraries/physics/src/ObjectDynamic.cpp +++ b/libraries/physics/src/ObjectDynamic.cpp @@ -106,6 +106,20 @@ void ObjectDynamic::removeFromSimulation(EntitySimulationPointer simulation) con simulation->removeDynamic(myID); } +EntityItemPointer ObjectDynamic::getEntityByID(EntityItemID entityID) const { + EntityItemPointer ownerEntity; + withReadLock([&]{ + ownerEntity = _ownerEntity.lock(); + }); + EntityTreeElementPointer element = ownerEntity ? ownerEntity->getElement() : nullptr; + EntityTreePointer tree = element ? element->getTree() : nullptr; + if (!tree) { + return nullptr; + } + return tree->findEntityByID(entityID); +} + + btRigidBody* ObjectDynamic::getRigidBody() { ObjectMotionState* motionState = nullptr; withReadLock([&]{ diff --git a/libraries/physics/src/ObjectDynamic.h b/libraries/physics/src/ObjectDynamic.h index 3f81cbc037..1ffc13239c 100644 --- a/libraries/physics/src/ObjectDynamic.h +++ b/libraries/physics/src/ObjectDynamic.h @@ -47,6 +47,7 @@ protected: quint64 localTimeToServerTime(quint64 timeValue) const; quint64 serverTimeToLocalTime(quint64 timeValue) const; + EntityItemPointer getEntityByID(EntityItemID entityID) const; virtual btRigidBody* getRigidBody(); virtual glm::vec3 getPosition() override; virtual void setPosition(glm::vec3 position) override; diff --git a/libraries/physics/src/PhysicalEntitySimulation.cpp b/libraries/physics/src/PhysicalEntitySimulation.cpp index 3ba1744abc..5081f981d4 100644 --- a/libraries/physics/src/PhysicalEntitySimulation.cpp +++ b/libraries/physics/src/PhysicalEntitySimulation.cpp @@ -346,6 +346,7 @@ void PhysicalEntitySimulation::addDynamic(EntityDynamicPointer dynamic) { } void PhysicalEntitySimulation::applyDynamicChanges() { + QList dynamicsFailedToAdd; if (_physicsEngine) { // FIXME put fine grain locking into _physicsEngine QMutexLocker lock(&_mutex); @@ -354,9 +355,16 @@ void PhysicalEntitySimulation::applyDynamicChanges() { } foreach (EntityDynamicPointer dynamicToAdd, _dynamicsToAdd) { if (!_dynamicsToRemove.contains(dynamicToAdd->getID())) { - _physicsEngine->addDynamic(dynamicToAdd); + if (!_physicsEngine->addDynamic(dynamicToAdd)) { + dynamicsFailedToAdd += dynamicToAdd; + } } } } + // applyDynamicChanges will clear _dynamicsToRemove and _dynamicsToAdd EntitySimulation::applyDynamicChanges(); + // put back the ones that couldn't yet be added + foreach (EntityDynamicPointer dynamicFailedToAdd, dynamicsFailedToAdd) { + addDynamic(dynamicFailedToAdd); + } } diff --git a/libraries/physics/src/PhysicsEngine.cpp b/libraries/physics/src/PhysicsEngine.cpp index fd82b05fa5..3cd6abb839 100644 --- a/libraries/physics/src/PhysicsEngine.cpp +++ b/libraries/physics/src/PhysicsEngine.cpp @@ -555,12 +555,17 @@ EntityDynamicPointer PhysicsEngine::getDynamicByID(const QUuid& dynamicID) const return nullptr; } -void PhysicsEngine::addDynamic(EntityDynamicPointer dynamic) { +bool PhysicsEngine::addDynamic(EntityDynamicPointer dynamic) { assert(dynamic); + + if (!dynamic->isReadyForAdd()) { + return false; + } + const QUuid& dynamicID = dynamic->getID(); if (_objectDynamics.contains(dynamicID)) { if (_objectDynamics[dynamicID] == dynamic) { - return; + return true; } removeDynamic(dynamic->getID()); } @@ -572,13 +577,16 @@ void PhysicsEngine::addDynamic(EntityDynamicPointer dynamic) { if (dynamic->isAction()) { ObjectAction* objectAction = static_cast(dynamic.get()); _dynamicsWorld->addAction(objectAction); + return true; } else if (dynamic->isConstraint()) { ObjectConstraint* objectConstraint = static_cast(dynamic.get()); btTypedConstraint* constraint = objectConstraint->getConstraint(); if (constraint) { _dynamicsWorld->addConstraint(constraint); + return true; } else { - qDebug() << "PhysicsEngine::addDynamic of constraint failed"; // XXX + // perhaps not all the rigid bodies are available, yet + return false; } } } diff --git a/libraries/physics/src/PhysicsEngine.h b/libraries/physics/src/PhysicsEngine.h index ec36286dd8..d9f70efc3e 100644 --- a/libraries/physics/src/PhysicsEngine.h +++ b/libraries/physics/src/PhysicsEngine.h @@ -86,7 +86,7 @@ public: void dumpNextStats() { _dumpNextStats = true; } EntityDynamicPointer getDynamicByID(const QUuid& dynamicID) const; - void addDynamic(EntityDynamicPointer dynamic); + bool addDynamic(EntityDynamicPointer dynamic); void removeDynamic(const QUuid dynamicID); void forEachDynamic(std::function actor); From 52aee63e0524862d69b268f65eccb9292133154c Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 14 Apr 2017 06:08:58 -0700 Subject: [PATCH 12/26] keep track of objectDynamics per rigidBody --- .../physics/src/ObjectConstraintHinge.cpp | 30 +++++++++---------- libraries/physics/src/ObjectConstraintHinge.h | 4 +-- libraries/physics/src/ObjectDynamic.cpp | 25 ++++++++++++++++ libraries/physics/src/ObjectDynamic.h | 3 ++ libraries/physics/src/PhysicsEngine.cpp | 20 +++++++------ libraries/physics/src/PhysicsEngine.h | 2 ++ 6 files changed, 57 insertions(+), 27 deletions(-) diff --git a/libraries/physics/src/ObjectConstraintHinge.cpp b/libraries/physics/src/ObjectConstraintHinge.cpp index b6c19e96ce..cdd4ba490c 100644 --- a/libraries/physics/src/ObjectConstraintHinge.cpp +++ b/libraries/physics/src/ObjectConstraintHinge.cpp @@ -35,6 +35,19 @@ ObjectConstraintHinge::~ObjectConstraintHinge() { #endif } +QList ObjectConstraintHinge::getRigidBodies() { + QList result; + result += getRigidBody(); + QUuid otherEntityID; + withReadLock([&]{ + otherEntityID = _otherEntityID; + }); + if (!otherEntityID.isNull()) { + result += getOtherRigidBody(otherEntityID); + } + return result; +} + btTypedConstraint* ObjectConstraintHinge::getConstraint() { btHingeConstraint* constraint { nullptr }; QUuid otherEntityID; @@ -65,20 +78,7 @@ btTypedConstraint* ObjectConstraintHinge::getConstraint() { if (!otherEntityID.isNull()) { // This hinge is between two entities... find the other rigid body. - EntityItemPointer otherEntity = getEntityByID(otherEntityID); - if (!otherEntity) { - return nullptr; - } - - void* otherPhysicsInfo = otherEntity->getPhysicsInfo(); - if (!otherPhysicsInfo) { - return nullptr; - } - ObjectMotionState* otherMotionState = static_cast(otherPhysicsInfo); - if (!otherMotionState) { - return nullptr; - } - btRigidBody* rigidBodyB = otherMotionState->getRigidBody(); + btRigidBody* rigidBodyB = getOtherRigidBody(otherEntityID); if (!rigidBodyB) { return nullptr; } @@ -94,7 +94,6 @@ btTypedConstraint* ObjectConstraintHinge::getConstraint() { constraint->setAxis(bulletAxisInA); withWriteLock([&]{ - _otherEntity = otherEntity; // save weak-pointer to the other entity _constraint = constraint; }); @@ -110,7 +109,6 @@ btTypedConstraint* ObjectConstraintHinge::getConstraint() { constraint->setAxis(bulletAxisInA); withWriteLock([&]{ - _otherEntity.reset(); _constraint = constraint; }); return constraint; diff --git a/libraries/physics/src/ObjectConstraintHinge.h b/libraries/physics/src/ObjectConstraintHinge.h index 7823b85758..2bdbeab0aa 100644 --- a/libraries/physics/src/ObjectConstraintHinge.h +++ b/libraries/physics/src/ObjectConstraintHinge.h @@ -27,6 +27,7 @@ public: virtual QByteArray serialize() const override; virtual void deserialize(QByteArray serializedArguments) override; + virtual QList getRigidBodies() override; virtual btTypedConstraint* getConstraint() override; protected: @@ -35,8 +36,7 @@ protected: glm::vec3 _pivotInA; glm::vec3 _axisInA; - QUuid _otherEntityID; - EntityItemWeakPointer _otherEntity; + EntityItemID _otherEntityID; glm::vec3 _pivotInB; glm::vec3 _axisInB; }; diff --git a/libraries/physics/src/ObjectDynamic.cpp b/libraries/physics/src/ObjectDynamic.cpp index 4831c44705..3e5c9f3f9b 100644 --- a/libraries/physics/src/ObjectDynamic.cpp +++ b/libraries/physics/src/ObjectDynamic.cpp @@ -271,3 +271,28 @@ quint64 ObjectDynamic::serverTimeToLocalTime(quint64 timeValue) const { return timeValue - serverClockSkew; } + +btRigidBody* ObjectDynamic::getOtherRigidBody(EntityItemID otherEntityID) { + EntityItemPointer otherEntity = getEntityByID(otherEntityID); + if (!otherEntity) { + return nullptr; + } + + void* otherPhysicsInfo = otherEntity->getPhysicsInfo(); + if (!otherPhysicsInfo) { + return nullptr; + } + + ObjectMotionState* otherMotionState = static_cast(otherPhysicsInfo); + if (!otherMotionState) { + return nullptr; + } + + return otherMotionState->getRigidBody(); +} + +QList ObjectDynamic::getRigidBodies() { + QList result; + result += getRigidBody(); + return result; +} diff --git a/libraries/physics/src/ObjectDynamic.h b/libraries/physics/src/ObjectDynamic.h index 1ffc13239c..c8e809cfe1 100644 --- a/libraries/physics/src/ObjectDynamic.h +++ b/libraries/physics/src/ObjectDynamic.h @@ -43,10 +43,13 @@ public: virtual bool lifetimeIsOver() override; virtual quint64 getExpires() override { return _expires; } + virtual QList getRigidBodies(); + protected: quint64 localTimeToServerTime(quint64 timeValue) const; quint64 serverTimeToLocalTime(quint64 timeValue) const; + btRigidBody* getOtherRigidBody(EntityItemID otherEntityID); EntityItemPointer getEntityByID(EntityItemID entityID) const; virtual btRigidBody* getRigidBody(); virtual glm::vec3 getPosition() override; diff --git a/libraries/physics/src/PhysicsEngine.cpp b/libraries/physics/src/PhysicsEngine.cpp index 3cd6abb839..8a9a5edfb2 100644 --- a/libraries/physics/src/PhysicsEngine.cpp +++ b/libraries/physics/src/PhysicsEngine.cpp @@ -570,25 +570,27 @@ bool PhysicsEngine::addDynamic(EntityDynamicPointer dynamic) { removeDynamic(dynamic->getID()); } - _objectDynamics[dynamicID] = dynamic; - - // bullet needs a pointer to the dynamic, but it doesn't use shared pointers. - // is there a way to bump the reference count? + bool success { false }; if (dynamic->isAction()) { ObjectAction* objectAction = static_cast(dynamic.get()); _dynamicsWorld->addAction(objectAction); - return true; + success = true; } else if (dynamic->isConstraint()) { ObjectConstraint* objectConstraint = static_cast(dynamic.get()); btTypedConstraint* constraint = objectConstraint->getConstraint(); if (constraint) { _dynamicsWorld->addConstraint(constraint); - return true; - } else { - // perhaps not all the rigid bodies are available, yet - return false; + success = true; + } // else perhaps not all the rigid bodies are available, yet + } + + if (success) { + _objectDynamics[dynamicID] = dynamic; + foreach(btRigidBody* rigidBody, std::static_pointer_cast(dynamic)->getRigidBodies()) { + _objectDynamicsByBody[rigidBody] = dynamic; } } + return success; } void PhysicsEngine::removeDynamic(const QUuid dynamicID) { diff --git a/libraries/physics/src/PhysicsEngine.h b/libraries/physics/src/PhysicsEngine.h index d9f70efc3e..ba30375e73 100644 --- a/libraries/physics/src/PhysicsEngine.h +++ b/libraries/physics/src/PhysicsEngine.h @@ -112,6 +112,7 @@ private: ContactMap _contactMap; CollisionEvents _collisionEvents; QHash _objectDynamics; + QHash _objectDynamicsByBody; std::vector _activeStaticBodies; glm::vec3 _originOffset; @@ -123,6 +124,7 @@ private: bool _dumpNextStats = false; bool _hasOutgoingChanges = false; + }; typedef std::shared_ptr PhysicsEnginePointer; From f5a5369055f53a50f71436e62d07c21638f67356 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 14 Apr 2017 07:06:53 -0700 Subject: [PATCH 13/26] attempt to remove dynamics associated with a rigid-body before removing the rigid-body --- libraries/physics/src/ObjectConstraint.cpp | 4 +++ libraries/physics/src/ObjectConstraint.h | 1 + libraries/physics/src/ObjectDynamic.h | 4 +++ libraries/physics/src/PhysicsEngine.cpp | 32 ++++++++++++++++++++-- libraries/physics/src/PhysicsEngine.h | 3 +- 5 files changed, 40 insertions(+), 4 deletions(-) diff --git a/libraries/physics/src/ObjectConstraint.cpp b/libraries/physics/src/ObjectConstraint.cpp index e8f1a6d9fd..54fd4777e0 100644 --- a/libraries/physics/src/ObjectConstraint.cpp +++ b/libraries/physics/src/ObjectConstraint.cpp @@ -19,3 +19,7 @@ ObjectConstraint::ObjectConstraint(EntityDynamicType type, const QUuid& id, Enti ObjectDynamic(type, id, ownerEntity) { } + +void ObjectConstraint::invalidate() { + _constraint = nullptr; +} diff --git a/libraries/physics/src/ObjectConstraint.h b/libraries/physics/src/ObjectConstraint.h index 9136b5b38c..13aa871d98 100644 --- a/libraries/physics/src/ObjectConstraint.h +++ b/libraries/physics/src/ObjectConstraint.h @@ -24,6 +24,7 @@ public: virtual btTypedConstraint* getConstraint() = 0; virtual bool isConstraint() const override { return true; } + virtual void invalidate() override; protected: btTypedConstraint* _constraint { nullptr }; diff --git a/libraries/physics/src/ObjectDynamic.h b/libraries/physics/src/ObjectDynamic.h index c8e809cfe1..6ea90bdba0 100644 --- a/libraries/physics/src/ObjectDynamic.h +++ b/libraries/physics/src/ObjectDynamic.h @@ -33,6 +33,8 @@ public: virtual EntityItemWeakPointer getOwnerEntity() const override { return _ownerEntity; } virtual void setOwnerEntity(const EntityItemPointer ownerEntity) override { _ownerEntity = ownerEntity; } + virtual void invalidate() {}; + virtual bool updateArguments(QVariantMap arguments) override; virtual QVariantMap getArguments() override; @@ -71,4 +73,6 @@ private: qint64 getEntityServerClockSkew() const; }; +typedef std::shared_ptr ObjectDynamicPointer; + #endif // hifi_ObjectDynamic_h diff --git a/libraries/physics/src/PhysicsEngine.cpp b/libraries/physics/src/PhysicsEngine.cpp index 8a9a5edfb2..432f4287ea 100644 --- a/libraries/physics/src/PhysicsEngine.cpp +++ b/libraries/physics/src/PhysicsEngine.cpp @@ -142,6 +142,18 @@ void PhysicsEngine::addObjectToDynamicsWorld(ObjectMotionState* motionState) { motionState->clearIncomingDirtyFlags(); } +QList PhysicsEngine::removeDynamicsForBody(btRigidBody* body) { + // remove dynamics that are attached to this body + QList removedDynamics; + QMutableSetIterator i(_objectDynamicsByBody[body]); + while (i.hasNext()) { + EntityDynamicPointer dynamic = i.next(); + removeDynamic(dynamic->getID()); + removedDynamics += dynamic; + } + return removedDynamics; +} + void PhysicsEngine::removeObjects(const VectorOfMotionStates& objects) { // bump and prune contacts for all objects in the list for (auto object : objects) { @@ -175,6 +187,7 @@ void PhysicsEngine::removeObjects(const VectorOfMotionStates& objects) { for (auto object : objects) { btRigidBody* body = object->getRigidBody(); if (body) { + removeDynamicsForBody(body); _dynamicsWorld->removeRigidBody(body); // NOTE: setRigidBody() modifies body->m_userPointer so we should clear the MotionState's body BEFORE deleting it. @@ -191,6 +204,7 @@ void PhysicsEngine::removeObjects(const SetOfMotionStates& objects) { for (auto object : objects) { btRigidBody* body = object->getRigidBody(); if (body) { + removeDynamicsForBody(body); _dynamicsWorld->removeRigidBody(body); // NOTE: setRigidBody() modifies body->m_userPointer so we should clear the MotionState's body BEFORE deleting it. @@ -239,10 +253,17 @@ void PhysicsEngine::reinsertObject(ObjectMotionState* object) { bumpAndPruneContacts(object); btRigidBody* body = object->getRigidBody(); if (body) { + QList removedDynamics = removeDynamicsForBody(body); _dynamicsWorld->removeRigidBody(body); // add it back addObjectToDynamicsWorld(object); + foreach(EntityDynamicPointer dynamic, removedDynamics) { + bool success = addDynamic(dynamic); + if (!success) { + qCDebug(physics) << "PhysicsEngine::reinsertObject failed to recreate dynamic"; + } + } } } @@ -587,7 +608,7 @@ bool PhysicsEngine::addDynamic(EntityDynamicPointer dynamic) { if (success) { _objectDynamics[dynamicID] = dynamic; foreach(btRigidBody* rigidBody, std::static_pointer_cast(dynamic)->getRigidBodies()) { - _objectDynamicsByBody[rigidBody] = dynamic; + _objectDynamicsByBody[rigidBody] += dynamic; } } return success; @@ -595,7 +616,8 @@ bool PhysicsEngine::addDynamic(EntityDynamicPointer dynamic) { void PhysicsEngine::removeDynamic(const QUuid dynamicID) { if (_objectDynamics.contains(dynamicID)) { - EntityDynamicPointer dynamic = _objectDynamics[dynamicID]; + ObjectDynamicPointer dynamic = std::static_pointer_cast(_objectDynamics[dynamicID]); + QList rigidBodies = dynamic->getRigidBodies(); if (dynamic->isAction()) { ObjectAction* objectAction = static_cast(dynamic.get()); _dynamicsWorld->removeAction(objectAction); @@ -605,10 +627,14 @@ void PhysicsEngine::removeDynamic(const QUuid dynamicID) { if (constraint) { _dynamicsWorld->removeConstraint(constraint); } else { - qDebug() << "PhysicsEngine::removeDynamic of constraint failed"; // XXX + qCDebug(physics) << "PhysicsEngine::removeDynamic of constraint failed"; } } _objectDynamics.remove(dynamicID); + foreach(btRigidBody* rigidBody, rigidBodies) { + _objectDynamicsByBody[rigidBody].remove(dynamic); + } + dynamic->invalidate(); } } diff --git a/libraries/physics/src/PhysicsEngine.h b/libraries/physics/src/PhysicsEngine.h index ba30375e73..33d60997a8 100644 --- a/libraries/physics/src/PhysicsEngine.h +++ b/libraries/physics/src/PhysicsEngine.h @@ -91,6 +91,7 @@ public: void forEachDynamic(std::function actor); private: + QList removeDynamicsForBody(btRigidBody* body); void addObjectToDynamicsWorld(ObjectMotionState* motionState); void recursivelyHarvestPerformanceStats(CProfileIterator* profileIterator, QString contextName); @@ -112,7 +113,7 @@ private: ContactMap _contactMap; CollisionEvents _collisionEvents; QHash _objectDynamics; - QHash _objectDynamicsByBody; + QHash> _objectDynamicsByBody; std::vector _activeStaticBodies; glm::vec3 _originOffset; From 2dab3069daee47774c308ed5015c2f0141fa52da Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 14 Apr 2017 11:06:40 -0700 Subject: [PATCH 14/26] fix bug that was causing spring action to cause constant re-insertion of its rigidbody into bullet. store UUIDs rather than shared pointers in _objectDynamicsByBody so that refcounting works right and actions get their destructors called. --- libraries/entities/src/EntityItem.cpp | 1 - libraries/physics/src/ObjectAction.cpp | 2 +- libraries/physics/src/ObjectAction.h | 1 + libraries/physics/src/ObjectConstraint.h | 2 ++ libraries/physics/src/PhysicsEngine.cpp | 24 +++++++++++++++++------- libraries/physics/src/PhysicsEngine.h | 2 +- 6 files changed, 22 insertions(+), 10 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 500e4c30fe..f5b2214273 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -2010,7 +2010,6 @@ bool EntityItem::updateAction(EntitySimulationPointer simulation, const QUuid& a action->setIsMine(true); serializeActions(success, _allActionsDataCache); _dirtyFlags |= Simulation::DIRTY_PHYSICS_ACTIVATION; - _dirtyFlags |= Simulation::DIRTY_COLLISION_GROUP; // may need to not collide with own avatar } else { qCDebug(entities) << "EntityItem::updateAction failed"; } diff --git a/libraries/physics/src/ObjectAction.cpp b/libraries/physics/src/ObjectAction.cpp index f14070fde6..5f5f763ca6 100644 --- a/libraries/physics/src/ObjectAction.cpp +++ b/libraries/physics/src/ObjectAction.cpp @@ -32,7 +32,7 @@ void ObjectAction::updateAction(btCollisionWorld* collisionWorld, btScalar delta }); if (!ownerEntity) { - qCDebug(physics) << "warning -- action with no entity removing self from btCollisionWorld."; + qCDebug(physics) << "warning -- action [" << _tag << "] with no entity removing self from btCollisionWorld."; btDynamicsWorld* dynamicsWorld = static_cast(collisionWorld); if (dynamicsWorld) { dynamicsWorld->removeAction(this); diff --git a/libraries/physics/src/ObjectAction.h b/libraries/physics/src/ObjectAction.h index 8e2f0e3383..fb141a4620 100644 --- a/libraries/physics/src/ObjectAction.h +++ b/libraries/physics/src/ObjectAction.h @@ -20,6 +20,7 @@ class ObjectAction : public btActionInterface, public ObjectDynamic { public: ObjectAction(EntityDynamicType type, const QUuid& id, EntityItemPointer ownerEntity); + virtual ~ObjectAction() {} virtual bool isAction() const override { return true; } diff --git a/libraries/physics/src/ObjectConstraint.h b/libraries/physics/src/ObjectConstraint.h index 13aa871d98..711daea812 100644 --- a/libraries/physics/src/ObjectConstraint.h +++ b/libraries/physics/src/ObjectConstraint.h @@ -21,6 +21,8 @@ class ObjectConstraint : public ObjectDynamic { public: ObjectConstraint(EntityDynamicType type, const QUuid& id, EntityItemPointer ownerEntity); + virtual ~ObjectConstraint() {} + virtual btTypedConstraint* getConstraint() = 0; virtual bool isConstraint() const override { return true; } diff --git a/libraries/physics/src/PhysicsEngine.cpp b/libraries/physics/src/PhysicsEngine.cpp index 432f4287ea..0c4290eff2 100644 --- a/libraries/physics/src/PhysicsEngine.cpp +++ b/libraries/physics/src/PhysicsEngine.cpp @@ -145,10 +145,18 @@ void PhysicsEngine::addObjectToDynamicsWorld(ObjectMotionState* motionState) { QList PhysicsEngine::removeDynamicsForBody(btRigidBody* body) { // remove dynamics that are attached to this body QList removedDynamics; - QMutableSetIterator i(_objectDynamicsByBody[body]); + QMutableSetIterator i(_objectDynamicsByBody[body]); + while (i.hasNext()) { - EntityDynamicPointer dynamic = i.next(); - removeDynamic(dynamic->getID()); + QUuid dynamicID = i.next(); + if (dynamicID.isNull()) { + continue; + } + EntityDynamicPointer dynamic = _objectDynamics[dynamicID]; + if (!dynamic) { + continue; + } + removeDynamic(dynamicID); removedDynamics += dynamic; } return removedDynamics; @@ -608,7 +616,7 @@ bool PhysicsEngine::addDynamic(EntityDynamicPointer dynamic) { if (success) { _objectDynamics[dynamicID] = dynamic; foreach(btRigidBody* rigidBody, std::static_pointer_cast(dynamic)->getRigidBodies()) { - _objectDynamicsByBody[rigidBody] += dynamic; + _objectDynamicsByBody[rigidBody] += dynamic->getID(); } } return success; @@ -632,16 +640,18 @@ void PhysicsEngine::removeDynamic(const QUuid dynamicID) { } _objectDynamics.remove(dynamicID); foreach(btRigidBody* rigidBody, rigidBodies) { - _objectDynamicsByBody[rigidBody].remove(dynamic); + _objectDynamicsByBody[rigidBody].remove(dynamic->getID()); } dynamic->invalidate(); } } void PhysicsEngine::forEachDynamic(std::function actor) { - QHashIterator iter(_objectDynamics); + QMutableHashIterator iter(_objectDynamics); while (iter.hasNext()) { iter.next(); - actor(iter.value()); + if (iter.value()) { + actor(iter.value()); + } } } diff --git a/libraries/physics/src/PhysicsEngine.h b/libraries/physics/src/PhysicsEngine.h index 33d60997a8..9f2f1aff5c 100644 --- a/libraries/physics/src/PhysicsEngine.h +++ b/libraries/physics/src/PhysicsEngine.h @@ -113,7 +113,7 @@ private: ContactMap _contactMap; CollisionEvents _collisionEvents; QHash _objectDynamics; - QHash> _objectDynamicsByBody; + QHash> _objectDynamicsByBody; std::vector _activeStaticBodies; glm::vec3 _originOffset; From b1dc5be316914934549043f304d4f780981873eb Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 14 Apr 2017 11:48:06 -0700 Subject: [PATCH 15/26] make far-grab it's own action (which is just like spring) in order to avoid bootstrapping own avatar --- interface/src/InterfaceDynamicFactory.cpp | 3 + interface/src/avatar/AvatarActionFarGrab.cpp | 61 +++++++++++++++++++ interface/src/avatar/AvatarActionFarGrab.h | 27 ++++++++ .../entities/src/EntityDynamicInterface.cpp | 5 ++ .../entities/src/EntityDynamicInterface.h | 3 +- libraries/entities/src/EntityItem.cpp | 10 +++ libraries/physics/src/ObjectActionSpring.cpp | 58 ++++++++++-------- libraries/physics/src/ObjectActionSpring.h | 3 + 8 files changed, 144 insertions(+), 26 deletions(-) create mode 100644 interface/src/avatar/AvatarActionFarGrab.cpp create mode 100644 interface/src/avatar/AvatarActionFarGrab.h diff --git a/interface/src/InterfaceDynamicFactory.cpp b/interface/src/InterfaceDynamicFactory.cpp index ed6d35c69b..5951ccef9e 100644 --- a/interface/src/InterfaceDynamicFactory.cpp +++ b/interface/src/InterfaceDynamicFactory.cpp @@ -12,6 +12,7 @@ #include +#include #include #include #include @@ -35,6 +36,8 @@ EntityDynamicPointer interfaceDynamicFactory(EntityDynamicType type, const QUuid return std::make_shared(id, ownerEntity); case DYNAMIC_TYPE_HINGE: return std::make_shared(id, ownerEntity); + case DYNAMIC_TYPE_FAR_GRAB: + return std::make_shared(id, ownerEntity); } Q_ASSERT_X(false, Q_FUNC_INFO, "Unknown entity dynamic type"); diff --git a/interface/src/avatar/AvatarActionFarGrab.cpp b/interface/src/avatar/AvatarActionFarGrab.cpp new file mode 100644 index 0000000000..bcc89c973a --- /dev/null +++ b/interface/src/avatar/AvatarActionFarGrab.cpp @@ -0,0 +1,61 @@ +// +// AvatarActionFarGrab.cpp +// interface/src/avatar/ +// +// Created by Seth Alves 2017-4-14 +// Copyright 2017 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 "AvatarActionFarGrab.h" + +AvatarActionFarGrab::AvatarActionFarGrab(const QUuid& id, EntityItemPointer ownerEntity) : + ObjectActionSpring(id, ownerEntity) { + _type = DYNAMIC_TYPE_FAR_GRAB; +#if WANT_DEBUG + qCDebug(physics) << "AvatarActionFarGrab::AvatarActionFarGrab"; +#endif +} + +AvatarActionFarGrab::~AvatarActionFarGrab() { +#if WANT_DEBUG + qCDebug(physics) << "AvatarActionFarGrab::~AvatarActionFarGrab"; +#endif +} + + +QByteArray AvatarActionFarGrab::serialize() const { + QByteArray serializedActionArguments; + QDataStream dataStream(&serializedActionArguments, QIODevice::WriteOnly); + + dataStream << DYNAMIC_TYPE_FAR_GRAB; + dataStream << getID(); + dataStream << AvatarActionFarGrab::springVersion; + + serializeParameters(dataStream); + + return serializedActionArguments; +} + +void AvatarActionFarGrab::deserialize(QByteArray serializedArguments) { + QDataStream dataStream(serializedArguments); + + EntityDynamicType type; + dataStream >> type; + assert(type == getType()); + + QUuid id; + dataStream >> id; + assert(id == getID()); + + uint16_t serializationVersion; + dataStream >> serializationVersion; + if (serializationVersion != AvatarActionFarGrab::springVersion) { + assert(false); + return; + } + + deserializeParameters(serializedArguments, dataStream); +} diff --git a/interface/src/avatar/AvatarActionFarGrab.h b/interface/src/avatar/AvatarActionFarGrab.h new file mode 100644 index 0000000000..46c9f65dcf --- /dev/null +++ b/interface/src/avatar/AvatarActionFarGrab.h @@ -0,0 +1,27 @@ +// +// AvatarActionFarGrab.h +// interface/src/avatar/ +// +// Created by Seth Alves 2017-4-14 +// Copyright 2017 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_AvatarActionFarGrab_h +#define hifi_AvatarActionFarGrab_h + +#include +#include + +class AvatarActionFarGrab : public ObjectActionSpring { +public: + AvatarActionFarGrab(const QUuid& id, EntityItemPointer ownerEntity); + virtual ~AvatarActionFarGrab(); + + QByteArray serialize() const override; + virtual void deserialize(QByteArray serializedArguments) override; +}; + +#endif // hifi_AvatarActionFarGrab_h diff --git a/libraries/entities/src/EntityDynamicInterface.cpp b/libraries/entities/src/EntityDynamicInterface.cpp index b7160bbcb6..bed3185b8f 100644 --- a/libraries/entities/src/EntityDynamicInterface.cpp +++ b/libraries/entities/src/EntityDynamicInterface.cpp @@ -114,6 +114,9 @@ EntityDynamicType EntityDynamicInterface::dynamicTypeFromString(QString dynamicT if (normalizedDynamicTypeString == "hinge") { return DYNAMIC_TYPE_HINGE; } + if (normalizedDynamicTypeString == "fargrab") { + return DYNAMIC_TYPE_FAR_GRAB; + } qCDebug(entities) << "Warning -- EntityDynamicInterface::dynamicTypeFromString got unknown dynamic-type name" << dynamicTypeString; @@ -134,6 +137,8 @@ QString EntityDynamicInterface::dynamicTypeToString(EntityDynamicType dynamicTyp return "travel-oriented"; case DYNAMIC_TYPE_HINGE: return "hinge"; + case DYNAMIC_TYPE_FAR_GRAB: + return "far-grab"; } assert(false); return "none"; diff --git a/libraries/entities/src/EntityDynamicInterface.h b/libraries/entities/src/EntityDynamicInterface.h index f4b7efc7a6..900c5554a4 100644 --- a/libraries/entities/src/EntityDynamicInterface.h +++ b/libraries/entities/src/EntityDynamicInterface.h @@ -30,7 +30,8 @@ enum EntityDynamicType { DYNAMIC_TYPE_SPRING = 2000, DYNAMIC_TYPE_HOLD = 3000, DYNAMIC_TYPE_TRAVEL_ORIENTED = 4000, - DYNAMIC_TYPE_HINGE = 5000 + DYNAMIC_TYPE_HINGE = 5000, + DYNAMIC_TYPE_FAR_GRAB = 6000 }; diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index f5b2214273..a6de541958 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -1882,6 +1882,16 @@ void EntityItem::computeCollisionGroupAndFinalMask(int16_t& group, int16_t& mask } i++; } + QList farGrabActions = getActionsOfType(DYNAMIC_TYPE_FAR_GRAB); + i = farGrabActions.begin(); + while (i != farGrabActions.end()) { + EntityDynamicPointer action = *i; + if (action->isMine()) { + iAmHoldingThis = true; + break; + } + i++; + } if (iAmHoldingThis) { userMask &= ~USER_COLLISION_GROUP_MY_AVATAR; diff --git a/libraries/physics/src/ObjectActionSpring.cpp b/libraries/physics/src/ObjectActionSpring.cpp index 2faa681c1d..b75d6a3c16 100644 --- a/libraries/physics/src/ObjectActionSpring.cpp +++ b/libraries/physics/src/ObjectActionSpring.cpp @@ -259,14 +259,7 @@ QVariantMap ObjectActionSpring::getArguments() { return arguments; } -QByteArray ObjectActionSpring::serialize() const { - QByteArray serializedActionArguments; - QDataStream dataStream(&serializedActionArguments, QIODevice::WriteOnly); - - dataStream << DYNAMIC_TYPE_SPRING; - dataStream << getID(); - dataStream << ObjectActionSpring::springVersion; - +QByteArray ObjectActionSpring::serializeParameters(QDataStream& dataStream) const { withReadLock([&] { dataStream << _desiredPositionalTarget; dataStream << _linearTimeScale; @@ -277,10 +270,41 @@ QByteArray ObjectActionSpring::serialize() const { dataStream << localTimeToServerTime(_expires); dataStream << _tag; }); +} + +QByteArray ObjectActionSpring::serialize() const { + QByteArray serializedActionArguments; + QDataStream dataStream(&serializedActionArguments, QIODevice::WriteOnly); + + dataStream << DYNAMIC_TYPE_SPRING; + dataStream << getID(); + dataStream << ObjectActionSpring::springVersion; + + serializeParameters(dataStream); return serializedActionArguments; } +void ObjectActionSpring::deserializeParameters(QByteArray serializedArguments, QDataStream& dataStream) { + withWriteLock([&] { + dataStream >> _desiredPositionalTarget; + dataStream >> _linearTimeScale; + dataStream >> _positionalTargetSet; + + dataStream >> _desiredRotationalTarget; + dataStream >> _angularTimeScale; + dataStream >> _rotationalTargetSet; + + quint64 serverExpires; + dataStream >> serverExpires; + _expires = serverTimeToLocalTime(serverExpires); + + dataStream >> _tag; + + _active = true; + }); +} + void ObjectActionSpring::deserialize(QByteArray serializedArguments) { QDataStream dataStream(serializedArguments); @@ -299,21 +323,5 @@ void ObjectActionSpring::deserialize(QByteArray serializedArguments) { return; } - withWriteLock([&] { - dataStream >> _desiredPositionalTarget; - dataStream >> _linearTimeScale; - dataStream >> _positionalTargetSet; - - dataStream >> _desiredRotationalTarget; - dataStream >> _angularTimeScale; - dataStream >> _rotationalTargetSet; - - quint64 serverExpires; - dataStream >> serverExpires; - _expires = serverTimeToLocalTime(serverExpires); - - dataStream >> _tag; - - _active = true; - }); + deserializeParameters(serializedArguments, dataStream); } diff --git a/libraries/physics/src/ObjectActionSpring.h b/libraries/physics/src/ObjectActionSpring.h index 498bb6c1f5..efc41a59a9 100644 --- a/libraries/physics/src/ObjectActionSpring.h +++ b/libraries/physics/src/ObjectActionSpring.h @@ -47,6 +47,9 @@ protected: glm::vec3 _angularVelocityTarget; virtual bool prepareForSpringUpdate(btScalar deltaTimeStep); + + QByteArray serializeParameters(QDataStream& dataStream) const; + void deserializeParameters(QByteArray serializedArguments, QDataStream& dataStream); }; #endif // hifi_ObjectActionSpring_h From 1009182c06e1a63db3f52327fdd7c49206c0c523 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 14 Apr 2017 11:52:07 -0700 Subject: [PATCH 16/26] grab and handControllerGrab use new far-grab action --- scripts/system/controllers/grab.js | 2 +- scripts/system/controllers/handControllerGrab.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/system/controllers/grab.js b/scripts/system/controllers/grab.js index 10f477b3af..811799917d 100644 --- a/scripts/system/controllers/grab.js +++ b/scripts/system/controllers/grab.js @@ -529,7 +529,7 @@ Grabber.prototype.moveEvent = function(event) { if (!this.actionID) { if (!entityIsGrabbedByOther(this.entityID)) { - this.actionID = Entities.addAction("spring", this.entityID, actionArgs); + this.actionID = Entities.addAction("far-grab", this.entityID, actionArgs); } } else { Entities.updateAction(this.entityID, this.actionID, actionArgs); diff --git a/scripts/system/controllers/handControllerGrab.js b/scripts/system/controllers/handControllerGrab.js index 0dfe64bbaa..fc16d7d1c5 100644 --- a/scripts/system/controllers/handControllerGrab.js +++ b/scripts/system/controllers/handControllerGrab.js @@ -2527,7 +2527,7 @@ function MyController(hand) { var timeScale = this.distanceGrabTimescale(this.mass, distanceToObject); this.actionID = NULL_UUID; - this.actionID = Entities.addAction("spring", this.grabbedThingID, { + this.actionID = Entities.addAction("far-grab", this.grabbedThingID, { targetPosition: this.currentObjectPosition, linearTimeScale: timeScale, targetRotation: this.currentObjectRotation, From d0144f41104a3113bc9e0a98f123c03b72656b50 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 14 Apr 2017 12:44:54 -0700 Subject: [PATCH 17/26] avatar-action-far-grab works now --- interface/src/avatar/AvatarActionFarGrab.cpp | 8 ++++---- libraries/physics/src/ObjectActionSpring.cpp | 3 ++- libraries/physics/src/ObjectActionSpring.h | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/interface/src/avatar/AvatarActionFarGrab.cpp b/interface/src/avatar/AvatarActionFarGrab.cpp index bcc89c973a..28f7f2abf7 100644 --- a/interface/src/avatar/AvatarActionFarGrab.cpp +++ b/interface/src/avatar/AvatarActionFarGrab.cpp @@ -15,13 +15,13 @@ AvatarActionFarGrab::AvatarActionFarGrab(const QUuid& id, EntityItemPointer owne ObjectActionSpring(id, ownerEntity) { _type = DYNAMIC_TYPE_FAR_GRAB; #if WANT_DEBUG - qCDebug(physics) << "AvatarActionFarGrab::AvatarActionFarGrab"; + qDebug() << "AvatarActionFarGrab::AvatarActionFarGrab"; #endif } AvatarActionFarGrab::~AvatarActionFarGrab() { #if WANT_DEBUG - qCDebug(physics) << "AvatarActionFarGrab::~AvatarActionFarGrab"; + qDebug() << "AvatarActionFarGrab::~AvatarActionFarGrab"; #endif } @@ -32,7 +32,7 @@ QByteArray AvatarActionFarGrab::serialize() const { dataStream << DYNAMIC_TYPE_FAR_GRAB; dataStream << getID(); - dataStream << AvatarActionFarGrab::springVersion; + dataStream << ObjectActionSpring::springVersion; serializeParameters(dataStream); @@ -52,7 +52,7 @@ void AvatarActionFarGrab::deserialize(QByteArray serializedArguments) { uint16_t serializationVersion; dataStream >> serializationVersion; - if (serializationVersion != AvatarActionFarGrab::springVersion) { + if (serializationVersion != ObjectActionSpring::springVersion) { assert(false); return; } diff --git a/libraries/physics/src/ObjectActionSpring.cpp b/libraries/physics/src/ObjectActionSpring.cpp index b75d6a3c16..df7e5f87a3 100644 --- a/libraries/physics/src/ObjectActionSpring.cpp +++ b/libraries/physics/src/ObjectActionSpring.cpp @@ -66,6 +66,7 @@ bool ObjectActionSpring::prepareForSpringUpdate(btScalar deltaTimeStep) { QList springDerivedActions; springDerivedActions.append(ownerEntity->getActionsOfType(DYNAMIC_TYPE_SPRING)); + springDerivedActions.append(ownerEntity->getActionsOfType(DYNAMIC_TYPE_FAR_GRAB)); springDerivedActions.append(ownerEntity->getActionsOfType(DYNAMIC_TYPE_HOLD)); foreach (EntityDynamicPointer action, springDerivedActions) { @@ -259,7 +260,7 @@ QVariantMap ObjectActionSpring::getArguments() { return arguments; } -QByteArray ObjectActionSpring::serializeParameters(QDataStream& dataStream) const { +void ObjectActionSpring::serializeParameters(QDataStream& dataStream) const { withReadLock([&] { dataStream << _desiredPositionalTarget; dataStream << _linearTimeScale; diff --git a/libraries/physics/src/ObjectActionSpring.h b/libraries/physics/src/ObjectActionSpring.h index efc41a59a9..de9562d3fa 100644 --- a/libraries/physics/src/ObjectActionSpring.h +++ b/libraries/physics/src/ObjectActionSpring.h @@ -48,7 +48,7 @@ protected: virtual bool prepareForSpringUpdate(btScalar deltaTimeStep); - QByteArray serializeParameters(QDataStream& dataStream) const; + void serializeParameters(QDataStream& dataStream) const; void deserializeParameters(QByteArray serializedArguments, QDataStream& dataStream); }; From 07b23b8235d13febf555a719208ea5c37ea709b2 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 14 Apr 2017 13:28:25 -0700 Subject: [PATCH 18/26] expose other hinge-constraint parameters to javascript --- .../physics/src/ObjectConstraintHinge.cpp | 126 ++++++++++++++---- libraries/physics/src/ObjectConstraintHinge.h | 6 + 2 files changed, 109 insertions(+), 23 deletions(-) diff --git a/libraries/physics/src/ObjectConstraintHinge.cpp b/libraries/physics/src/ObjectConstraintHinge.cpp index cdd4ba490c..aeda8d5963 100644 --- a/libraries/physics/src/ObjectConstraintHinge.cpp +++ b/libraries/physics/src/ObjectConstraintHinge.cpp @@ -55,6 +55,11 @@ btTypedConstraint* ObjectConstraintHinge::getConstraint() { glm::vec3 axisInA; glm::vec3 pivotInB; glm::vec3 axisInB; + float low; + float high; + float softness; + float biasFactor; + float relaxationFactor; withReadLock([&]{ constraint = static_cast(_constraint); @@ -63,6 +68,11 @@ btTypedConstraint* ObjectConstraintHinge::getConstraint() { otherEntityID = _otherEntityID; pivotInB = _pivotInB; axisInB = _axisInB; + low = _low; + high = _high; + softness = _softness; + biasFactor = _biasFactor; + relaxationFactor = _relaxationFactor; }); if (constraint) { return constraint; @@ -90,29 +100,22 @@ btTypedConstraint* ObjectConstraintHinge::getConstraint() { rigidBodyAFrame, rigidBodyBFrame, useReferenceFrameA); - btVector3 bulletAxisInA = glmToBullet(axisInA); - constraint->setAxis(bulletAxisInA); - - withWriteLock([&]{ - _constraint = constraint; - }); - - return constraint; } else { // This hinge is between an entity and the world-frame. btTransform rigidBodyAFrame(btQuaternion(0.0f, 0.0f, 0.0f, 1.0f), glmToBullet(pivotInA)); constraint = new btHingeConstraint(*rigidBodyA, rigidBodyAFrame, useReferenceFrameA); - // constraint->setAngularOnly(true); - - btVector3 bulletAxisInA = glmToBullet(axisInA); - constraint->setAxis(bulletAxisInA); - - withWriteLock([&]{ - _constraint = constraint; - }); - return constraint; } + + btVector3 bulletAxisInA = glmToBullet(axisInA); + constraint->setAxis(bulletAxisInA); + constraint->setLimit(low, high, softness, biasFactor, relaxationFactor); + + withWriteLock([&]{ + _constraint = constraint; + }); + + return constraint; } @@ -122,6 +125,13 @@ bool ObjectConstraintHinge::updateArguments(QVariantMap arguments) { QUuid otherEntityID; glm::vec3 pivotInB; glm::vec3 axisInB; + float low; + float high; + float softness; + float biasFactor; + float relaxationFactor; + float angle; + float angleSet { false }; bool needUpdate = false; bool somethingChanged = ObjectDynamic::updateArguments(arguments); @@ -157,11 +167,55 @@ bool ObjectConstraintHinge::updateArguments(QVariantMap arguments) { axisInB = _axisInB; } + ok = true; + low = EntityDynamicInterface::extractFloatArgument("hinge constraint", arguments, "low", ok, false); + if (!ok) { + low = _low; + } + + ok = true; + high = EntityDynamicInterface::extractFloatArgument("hinge constraint", arguments, "high", ok, false); + if (!ok) { + high = _high; + } + + ok = true; + softness = EntityDynamicInterface::extractFloatArgument("hinge constraint", arguments, "softness", ok, false); + if (!ok) { + softness = _softness; + } + + ok = true; + biasFactor = EntityDynamicInterface::extractFloatArgument("hinge constraint", arguments, "biasFactor", ok, false); + if (!ok) { + biasFactor = _biasFactor; + } + + ok = true; + relaxationFactor = EntityDynamicInterface::extractFloatArgument("hinge constraint", arguments, + "relaxationFactor", ok, false); + if (!ok) { + relaxationFactor = _relaxationFactor; + } + + ok = true; + angle = EntityDynamicInterface::extractFloatArgument("hinge constraint", arguments, "angle", ok, false); + if (ok) { + angleSet = true; + } + + if (somethingChanged || pivotInA != _pivotInA || axisInA != _axisInA || pivotInB != _pivotInB || - axisInB != _axisInB) { + axisInB != _axisInB || + low != _low || + high != _high || + softness != _softness || + biasFactor != _biasFactor || + relaxationFactor != _relaxationFactor || + angleSet) { // something changed needUpdate = true; } @@ -174,6 +228,11 @@ bool ObjectConstraintHinge::updateArguments(QVariantMap arguments) { _otherEntityID = otherEntityID; _pivotInB = pivotInB; _axisInB = axisInB; + _low = low; + _high = high; + _softness = softness; + _biasFactor = biasFactor; + _relaxationFactor = relaxationFactor; _active = true; @@ -182,6 +241,8 @@ bool ObjectConstraintHinge::updateArguments(QVariantMap arguments) { ownerEntity->setDynamicDataDirty(true); ownerEntity->setDynamicDataNeedsTransmit(true); } + + // _constraint->setAngle(angle); }); // activateBody(); } @@ -192,11 +253,19 @@ bool ObjectConstraintHinge::updateArguments(QVariantMap arguments) { QVariantMap ObjectConstraintHinge::getArguments() { QVariantMap arguments = ObjectDynamic::getArguments(); withReadLock([&] { - arguments["pivot"] = glmToQMap(_pivotInA); - arguments["axis"] = glmToQMap(_axisInA); - arguments["otherEntityID"] = _otherEntityID; - arguments["otherPivot"] = glmToQMap(_pivotInB); - arguments["otherAxis"] = glmToQMap(_axisInB); + if (_constraint) { + arguments["pivot"] = glmToQMap(_pivotInA); + arguments["axis"] = glmToQMap(_axisInA); + arguments["otherEntityID"] = _otherEntityID; + arguments["otherPivot"] = glmToQMap(_pivotInB); + arguments["otherAxis"] = glmToQMap(_axisInB); + arguments["low"] = _low; + arguments["high"] = _high; + arguments["softness"] = _softness; + arguments["biasFactor"] = _biasFactor; + arguments["relaxationFactor"] = _relaxationFactor; + arguments["angle"] = static_cast(_constraint)->getHingeAngle(); // [-PI,PI] + } }); return arguments; } @@ -215,6 +284,12 @@ QByteArray ObjectConstraintHinge::serialize() const { dataStream << _otherEntityID; dataStream << _pivotInB; dataStream << _axisInB; + dataStream << _low; + dataStream << _high; + dataStream << _softness; + dataStream << _biasFactor; + dataStream << _relaxationFactor; + dataStream << localTimeToServerTime(_expires); dataStream << _tag; }); @@ -246,6 +321,11 @@ void ObjectConstraintHinge::deserialize(QByteArray serializedArguments) { dataStream >> _otherEntityID; dataStream >> _pivotInB; dataStream >> _axisInB; + dataStream >> _low; + dataStream >> _high; + dataStream >> _softness; + dataStream >> _biasFactor; + dataStream >> _relaxationFactor; quint64 serverExpires; dataStream >> serverExpires; diff --git a/libraries/physics/src/ObjectConstraintHinge.h b/libraries/physics/src/ObjectConstraintHinge.h index 2bdbeab0aa..520cbb4323 100644 --- a/libraries/physics/src/ObjectConstraintHinge.h +++ b/libraries/physics/src/ObjectConstraintHinge.h @@ -39,6 +39,12 @@ protected: EntityItemID _otherEntityID; glm::vec3 _pivotInB; glm::vec3 _axisInB; + + float _low { -2 * PI }; + float _high { 2 * PI }; + float _softness { 0.9f }; + float _biasFactor { 0.3f }; + float _relaxationFactor { 1.0f }; }; #endif // hifi_ObjectConstraintHinge_h From 708008d8a52aaa445b55b8ebcdd1dafa800dae4e Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 14 Apr 2017 13:43:48 -0700 Subject: [PATCH 19/26] cleanups --- libraries/physics/src/ObjectConstraintHinge.cpp | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/libraries/physics/src/ObjectConstraintHinge.cpp b/libraries/physics/src/ObjectConstraintHinge.cpp index aeda8d5963..d8270ba8ff 100644 --- a/libraries/physics/src/ObjectConstraintHinge.cpp +++ b/libraries/physics/src/ObjectConstraintHinge.cpp @@ -130,8 +130,6 @@ bool ObjectConstraintHinge::updateArguments(QVariantMap arguments) { float softness; float biasFactor; float relaxationFactor; - float angle; - float angleSet { false }; bool needUpdate = false; bool somethingChanged = ObjectDynamic::updateArguments(arguments); @@ -198,24 +196,17 @@ bool ObjectConstraintHinge::updateArguments(QVariantMap arguments) { relaxationFactor = _relaxationFactor; } - ok = true; - angle = EntityDynamicInterface::extractFloatArgument("hinge constraint", arguments, "angle", ok, false); - if (ok) { - angleSet = true; - } - - if (somethingChanged || pivotInA != _pivotInA || axisInA != _axisInA || + otherEntityID != _otherEntityID || pivotInB != _pivotInB || axisInB != _axisInB || low != _low || high != _high || softness != _softness || biasFactor != _biasFactor || - relaxationFactor != _relaxationFactor || - angleSet) { + relaxationFactor != _relaxationFactor) { // something changed needUpdate = true; } @@ -241,10 +232,7 @@ bool ObjectConstraintHinge::updateArguments(QVariantMap arguments) { ownerEntity->setDynamicDataDirty(true); ownerEntity->setDynamicDataNeedsTransmit(true); } - - // _constraint->setAngle(angle); }); - // activateBody(); } return true; From f08fecbfa75355858519dcd60823e740a86e796b Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 14 Apr 2017 16:25:27 -0700 Subject: [PATCH 20/26] make sure new constraint data gets transmitted over network --- libraries/physics/src/ObjectConstraintHinge.cpp | 4 ++++ libraries/physics/src/PhysicsEngine.cpp | 3 +++ 2 files changed, 7 insertions(+) diff --git a/libraries/physics/src/ObjectConstraintHinge.cpp b/libraries/physics/src/ObjectConstraintHinge.cpp index d8270ba8ff..82a793ddaa 100644 --- a/libraries/physics/src/ObjectConstraintHinge.cpp +++ b/libraries/physics/src/ObjectConstraintHinge.cpp @@ -115,6 +115,10 @@ btTypedConstraint* ObjectConstraintHinge::getConstraint() { _constraint = constraint; }); + // if we don't wake up rigidBodyA, we may not send the dynamicData property over the network + forceBodyNonStatic(); + activateBody(); + return constraint; } diff --git a/libraries/physics/src/PhysicsEngine.cpp b/libraries/physics/src/PhysicsEngine.cpp index 0c4290eff2..141f70b971 100644 --- a/libraries/physics/src/PhysicsEngine.cpp +++ b/libraries/physics/src/PhysicsEngine.cpp @@ -625,6 +625,9 @@ bool PhysicsEngine::addDynamic(EntityDynamicPointer dynamic) { void PhysicsEngine::removeDynamic(const QUuid dynamicID) { if (_objectDynamics.contains(dynamicID)) { ObjectDynamicPointer dynamic = std::static_pointer_cast(_objectDynamics[dynamicID]); + if (!dynamic) { + return; + } QList rigidBodies = dynamic->getRigidBodies(); if (dynamic->isAction()) { ObjectAction* objectAction = static_cast(dynamic.get()); From 41fb05ecf7f5af5a427c5227d206da06d063a96d Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 14 Apr 2017 16:26:54 -0700 Subject: [PATCH 21/26] bump protocol version --- libraries/networking/src/udt/PacketHeaders.cpp | 2 +- libraries/networking/src/udt/PacketHeaders.h | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/libraries/networking/src/udt/PacketHeaders.cpp b/libraries/networking/src/udt/PacketHeaders.cpp index 7d0f36ff6e..3ad4dbf28d 100644 --- a/libraries/networking/src/udt/PacketHeaders.cpp +++ b/libraries/networking/src/udt/PacketHeaders.cpp @@ -49,7 +49,7 @@ PacketVersion versionForPacketType(PacketType packetType) { case PacketType::EntityEdit: case PacketType::EntityData: case PacketType::EntityPhysics: - return VERSION_ENTITIES_MORE_DYNAMICS; + return VERSION_ENTITIES_HINGE_CONSTRAINT; case PacketType::EntityQuery: return static_cast(EntityQueryPacketVersion::JSONFilterWithFamilyTree); case PacketType::AvatarIdentity: diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index 75984211e2..074876862f 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -206,8 +206,7 @@ const PacketVersion VERSION_ENTITIES_LAST_EDITED_BY = 65; const PacketVersion VERSION_ENTITIES_SERVER_SCRIPTS = 66; const PacketVersion VERSION_ENTITIES_PHYSICS_PACKET = 67; const PacketVersion VERSION_ENTITIES_ZONE_FILTERS = 68; -const PacketVersion VERSION_ENTITIES_HINGE_DYNAMIC = 69; -const PacketVersion VERSION_ENTITIES_MORE_DYNAMICS = 68; // XXX +const PacketVersion VERSION_ENTITIES_HINGE_CONSTRAINT = 69; enum class EntityQueryPacketVersion: PacketVersion { JSONFilter = 18, From d42970d4803a5428f214fd3b1bb43c124224044c Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Sat, 15 Apr 2017 08:51:08 -0700 Subject: [PATCH 22/26] fix hinge-constraint constructors to use otherAxis --- .../physics/src/ObjectConstraintHinge.cpp | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/libraries/physics/src/ObjectConstraintHinge.cpp b/libraries/physics/src/ObjectConstraintHinge.cpp index 82a793ddaa..f52bb80151 100644 --- a/libraries/physics/src/ObjectConstraintHinge.cpp +++ b/libraries/physics/src/ObjectConstraintHinge.cpp @@ -84,31 +84,24 @@ btTypedConstraint* ObjectConstraintHinge::getConstraint() { return nullptr; } - bool useReferenceFrameA { false }; - if (!otherEntityID.isNull()) { // This hinge is between two entities... find the other rigid body. btRigidBody* rigidBodyB = getOtherRigidBody(otherEntityID); if (!rigidBodyB) { return nullptr; } - - btTransform rigidBodyAFrame(btQuaternion(0.0f, 0.0f, 0.0f, 1.0f), glmToBullet(pivotInA)); - btTransform rigidBodyBFrame(btQuaternion(0.0f, 0.0f, 0.0f, 1.0f), glmToBullet(pivotInB)); - constraint = new btHingeConstraint(*rigidBodyA, *rigidBodyB, - rigidBodyAFrame, rigidBodyBFrame, - useReferenceFrameA); + glmToBullet(pivotInA), glmToBullet(pivotInB), + glmToBullet(axisInA), glmToBullet(axisInB), + true); // useReferenceFrameA } else { // This hinge is between an entity and the world-frame. - btTransform rigidBodyAFrame(btQuaternion(0.0f, 0.0f, 0.0f, 1.0f), glmToBullet(pivotInA)); - - constraint = new btHingeConstraint(*rigidBodyA, rigidBodyAFrame, useReferenceFrameA); + constraint = new btHingeConstraint(*rigidBodyA, + glmToBullet(pivotInA), glmToBullet(axisInA), + true); // useReferenceFrameA } - btVector3 bulletAxisInA = glmToBullet(axisInA); - constraint->setAxis(bulletAxisInA); constraint->setLimit(low, high, softness, biasFactor, relaxationFactor); withWriteLock([&]{ From b4ff3a86918b669a66e0c79a0e5e17c1750d8a4b Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Sat, 15 Apr 2017 21:08:59 -0700 Subject: [PATCH 23/26] don't destroy and recreate constraints when reinserting rigid body --- libraries/physics/src/PhysicsEngine.cpp | 8 -------- 1 file changed, 8 deletions(-) diff --git a/libraries/physics/src/PhysicsEngine.cpp b/libraries/physics/src/PhysicsEngine.cpp index 141f70b971..ca6889485a 100644 --- a/libraries/physics/src/PhysicsEngine.cpp +++ b/libraries/physics/src/PhysicsEngine.cpp @@ -261,17 +261,9 @@ void PhysicsEngine::reinsertObject(ObjectMotionState* object) { bumpAndPruneContacts(object); btRigidBody* body = object->getRigidBody(); if (body) { - QList removedDynamics = removeDynamicsForBody(body); _dynamicsWorld->removeRigidBody(body); - // add it back addObjectToDynamicsWorld(object); - foreach(EntityDynamicPointer dynamic, removedDynamics) { - bool success = addDynamic(dynamic); - if (!success) { - qCDebug(physics) << "PhysicsEngine::reinsertObject failed to recreate dynamic"; - } - } } } From fbd4677a9a5fc47e85cbaeb8f70f06c9654befc7 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Sat, 15 Apr 2017 21:10:02 -0700 Subject: [PATCH 24/26] add a way to set hinge-constraint motor speed from javascript --- .../physics/src/ObjectConstraintHinge.cpp | 69 +++++++++++++++---- libraries/physics/src/ObjectConstraintHinge.h | 3 + 2 files changed, 58 insertions(+), 14 deletions(-) diff --git a/libraries/physics/src/ObjectConstraintHinge.cpp b/libraries/physics/src/ObjectConstraintHinge.cpp index f52bb80151..6d609493d5 100644 --- a/libraries/physics/src/ObjectConstraintHinge.cpp +++ b/libraries/physics/src/ObjectConstraintHinge.cpp @@ -48,6 +48,40 @@ QList ObjectConstraintHinge::getRigidBodies() { return result; } +void ObjectConstraintHinge::updateHinge() { + btHingeConstraint* constraint { nullptr }; + float low; + float high; + float softness; + float biasFactor; + float relaxationFactor; + float motorVelocity; + + withReadLock([&]{ + constraint = static_cast(_constraint); + low = _low; + high = _high; + softness = _softness; + biasFactor = _biasFactor; + relaxationFactor = _relaxationFactor; + motorVelocity = _motorVelocity; + }); + + if (!constraint) { + return; + } + + constraint->setLimit(low, high, softness, biasFactor, relaxationFactor); + if (motorVelocity != 0.0f) { + qDebug() << "setting motor velocity on" << _tag << "to" << motorVelocity; + constraint->setMotorTargetVelocity(motorVelocity); + constraint->enableMotor(true); + } else { + constraint->enableMotor(false); + } +} + + btTypedConstraint* ObjectConstraintHinge::getConstraint() { btHingeConstraint* constraint { nullptr }; QUuid otherEntityID; @@ -55,11 +89,6 @@ btTypedConstraint* ObjectConstraintHinge::getConstraint() { glm::vec3 axisInA; glm::vec3 pivotInB; glm::vec3 axisInB; - float low; - float high; - float softness; - float biasFactor; - float relaxationFactor; withReadLock([&]{ constraint = static_cast(_constraint); @@ -68,11 +97,6 @@ btTypedConstraint* ObjectConstraintHinge::getConstraint() { otherEntityID = _otherEntityID; pivotInB = _pivotInB; axisInB = _axisInB; - low = _low; - high = _high; - softness = _softness; - biasFactor = _biasFactor; - relaxationFactor = _relaxationFactor; }); if (constraint) { return constraint; @@ -102,8 +126,6 @@ btTypedConstraint* ObjectConstraintHinge::getConstraint() { true); // useReferenceFrameA } - constraint->setLimit(low, high, softness, biasFactor, relaxationFactor); - withWriteLock([&]{ _constraint = constraint; }); @@ -112,6 +134,8 @@ btTypedConstraint* ObjectConstraintHinge::getConstraint() { forceBodyNonStatic(); activateBody(); + updateHinge(); + return constraint; } @@ -127,6 +151,7 @@ bool ObjectConstraintHinge::updateArguments(QVariantMap arguments) { float softness; float biasFactor; float relaxationFactor; + float motorVelocity; bool needUpdate = false; bool somethingChanged = ObjectDynamic::updateArguments(arguments); @@ -147,7 +172,7 @@ bool ObjectConstraintHinge::updateArguments(QVariantMap arguments) { otherEntityID = QUuid(EntityDynamicInterface::extractStringArgument("hinge constraint", arguments, "otherEntityID", ok, false)); if (!ok) { - otherEntityID = QUuid(); + otherEntityID = _otherEntityID; } ok = true; @@ -193,6 +218,13 @@ bool ObjectConstraintHinge::updateArguments(QVariantMap arguments) { relaxationFactor = _relaxationFactor; } + ok = true; + motorVelocity = EntityDynamicInterface::extractFloatArgument("hinge constraint", arguments, + "motorVelocity", ok, false); + if (!ok) { + motorVelocity = _motorVelocity; + } + if (somethingChanged || pivotInA != _pivotInA || axisInA != _axisInA || @@ -203,7 +235,8 @@ bool ObjectConstraintHinge::updateArguments(QVariantMap arguments) { high != _high || softness != _softness || biasFactor != _biasFactor || - relaxationFactor != _relaxationFactor) { + relaxationFactor != _relaxationFactor || + motorVelocity != _motorVelocity) { // something changed needUpdate = true; } @@ -221,6 +254,7 @@ bool ObjectConstraintHinge::updateArguments(QVariantMap arguments) { _softness = softness; _biasFactor = biasFactor; _relaxationFactor = relaxationFactor; + _motorVelocity = motorVelocity; _active = true; @@ -230,6 +264,8 @@ bool ObjectConstraintHinge::updateArguments(QVariantMap arguments) { ownerEntity->setDynamicDataNeedsTransmit(true); } }); + + updateHinge(); } return true; @@ -249,6 +285,7 @@ QVariantMap ObjectConstraintHinge::getArguments() { arguments["softness"] = _softness; arguments["biasFactor"] = _biasFactor; arguments["relaxationFactor"] = _relaxationFactor; + arguments["motorVelocity"] = _motorVelocity; arguments["angle"] = static_cast(_constraint)->getHingeAngle(); // [-PI,PI] } }); @@ -277,6 +314,8 @@ QByteArray ObjectConstraintHinge::serialize() const { dataStream << localTimeToServerTime(_expires); dataStream << _tag; + + dataStream << _motorVelocity; }); return serializedConstraintArguments; @@ -318,6 +357,8 @@ void ObjectConstraintHinge::deserialize(QByteArray serializedArguments) { dataStream >> _tag; + dataStream >> _motorVelocity; + _active = true; }); } diff --git a/libraries/physics/src/ObjectConstraintHinge.h b/libraries/physics/src/ObjectConstraintHinge.h index 520cbb4323..28665dffe7 100644 --- a/libraries/physics/src/ObjectConstraintHinge.h +++ b/libraries/physics/src/ObjectConstraintHinge.h @@ -33,6 +33,8 @@ public: protected: static const uint16_t constraintVersion; + void updateHinge(); + glm::vec3 _pivotInA; glm::vec3 _axisInA; @@ -45,6 +47,7 @@ protected: float _softness { 0.9f }; float _biasFactor { 0.3f }; float _relaxationFactor { 1.0f }; + float _motorVelocity { 0.0f }; }; #endif // hifi_ObjectConstraintHinge_h From d077c9f1dee6f95c513e946cd21cd3e9f2a3ed5a Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 18 Apr 2017 11:58:56 -0700 Subject: [PATCH 25/26] print rather than crash in what should be an impossible situation --- interface/src/avatar/AvatarActionFarGrab.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/interface/src/avatar/AvatarActionFarGrab.cpp b/interface/src/avatar/AvatarActionFarGrab.cpp index 28f7f2abf7..afa21e58d7 100644 --- a/interface/src/avatar/AvatarActionFarGrab.cpp +++ b/interface/src/avatar/AvatarActionFarGrab.cpp @@ -44,11 +44,14 @@ void AvatarActionFarGrab::deserialize(QByteArray serializedArguments) { EntityDynamicType type; dataStream >> type; - assert(type == getType()); QUuid id; dataStream >> id; - assert(id == getID()); + + if (type != getType() || id != getID()) { + qDebug() << "AvatarActionFarGrab::deserialize type or ID don't match." << type << id << getID(); + return; + } uint16_t serializationVersion; dataStream >> serializationVersion; From 21ca767b7c605fb908258f59b071635f97ebcf71 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 18 Apr 2017 11:59:16 -0700 Subject: [PATCH 26/26] remove setPosition and setRotation for actions because they were never finished and never used. --- assignment-client/src/AssignmentDynamic.cpp | 8 ------- assignment-client/src/AssignmentDynamic.h | 2 -- .../entities/src/EntityDynamicInterface.h | 4 ++-- .../physics/src/ObjectConstraintHinge.cpp | 1 - libraries/physics/src/ObjectConstraintHinge.h | 4 ++-- libraries/physics/src/ObjectDynamic.cpp | 22 ------------------- libraries/physics/src/ObjectDynamic.h | 2 -- 7 files changed, 4 insertions(+), 39 deletions(-) diff --git a/assignment-client/src/AssignmentDynamic.cpp b/assignment-client/src/AssignmentDynamic.cpp index c9b8d3d8c4..026bc120bb 100644 --- a/assignment-client/src/AssignmentDynamic.cpp +++ b/assignment-client/src/AssignmentDynamic.cpp @@ -59,19 +59,11 @@ glm::vec3 AssignmentDynamic::getPosition() { return glm::vec3(0.0f); } -void AssignmentDynamic::setPosition(glm::vec3 position) { - qDebug() << "UNEXPECTED -- AssignmentDynamic::setPosition called in assignment-client."; -} - glm::quat AssignmentDynamic::getRotation() { qDebug() << "UNEXPECTED -- AssignmentDynamic::getRotation called in assignment-client."; return glm::quat(); } -void AssignmentDynamic::setRotation(glm::quat rotation) { - qDebug() << "UNEXPECTED -- AssignmentDynamic::setRotation called in assignment-client."; -} - glm::vec3 AssignmentDynamic::getLinearVelocity() { qDebug() << "UNEXPECTED -- AssignmentDynamic::getLinearVelocity called in assignment-client."; return glm::vec3(0.0f); diff --git a/assignment-client/src/AssignmentDynamic.h b/assignment-client/src/AssignmentDynamic.h index 91a1e15ebc..35db8b1524 100644 --- a/assignment-client/src/AssignmentDynamic.h +++ b/assignment-client/src/AssignmentDynamic.h @@ -38,9 +38,7 @@ private: protected: virtual glm::vec3 getPosition() override; - virtual void setPosition(glm::vec3 position) override; virtual glm::quat getRotation() override; - virtual void setRotation(glm::quat rotation) override; virtual glm::vec3 getLinearVelocity() override; virtual void setLinearVelocity(glm::vec3 linearVelocity) override; virtual glm::vec3 getAngularVelocity() override; diff --git a/libraries/entities/src/EntityDynamicInterface.h b/libraries/entities/src/EntityDynamicInterface.h index 900c5554a4..93d9ffa43e 100644 --- a/libraries/entities/src/EntityDynamicInterface.h +++ b/libraries/entities/src/EntityDynamicInterface.h @@ -87,9 +87,9 @@ public: protected: virtual glm::vec3 getPosition() = 0; - virtual void setPosition(glm::vec3 position) = 0; + // virtual void setPosition(glm::vec3 position) = 0; virtual glm::quat getRotation() = 0; - virtual void setRotation(glm::quat rotation) = 0; + // virtual void setRotation(glm::quat rotation) = 0; virtual glm::vec3 getLinearVelocity() = 0; virtual void setLinearVelocity(glm::vec3 linearVelocity) = 0; virtual glm::vec3 getAngularVelocity() = 0; diff --git a/libraries/physics/src/ObjectConstraintHinge.cpp b/libraries/physics/src/ObjectConstraintHinge.cpp index 6d609493d5..6c55d9c5dd 100644 --- a/libraries/physics/src/ObjectConstraintHinge.cpp +++ b/libraries/physics/src/ObjectConstraintHinge.cpp @@ -73,7 +73,6 @@ void ObjectConstraintHinge::updateHinge() { constraint->setLimit(low, high, softness, biasFactor, relaxationFactor); if (motorVelocity != 0.0f) { - qDebug() << "setting motor velocity on" << _tag << "to" << motorVelocity; constraint->setMotorTargetVelocity(motorVelocity); constraint->enableMotor(true); } else { diff --git a/libraries/physics/src/ObjectConstraintHinge.h b/libraries/physics/src/ObjectConstraintHinge.h index 28665dffe7..7d2cac7511 100644 --- a/libraries/physics/src/ObjectConstraintHinge.h +++ b/libraries/physics/src/ObjectConstraintHinge.h @@ -42,8 +42,8 @@ protected: glm::vec3 _pivotInB; glm::vec3 _axisInB; - float _low { -2 * PI }; - float _high { 2 * PI }; + float _low { -2.0f * PI }; + float _high { 2.0f * PI }; float _softness { 0.9f }; float _biasFactor { 0.3f }; float _relaxationFactor { 1.0f }; diff --git a/libraries/physics/src/ObjectDynamic.cpp b/libraries/physics/src/ObjectDynamic.cpp index 3e5c9f3f9b..3cb9f5b405 100644 --- a/libraries/physics/src/ObjectDynamic.cpp +++ b/libraries/physics/src/ObjectDynamic.cpp @@ -147,17 +147,6 @@ glm::vec3 ObjectDynamic::getPosition() { return bulletToGLM(rigidBody->getCenterOfMassPosition()); } -void ObjectDynamic::setPosition(glm::vec3 position) { - auto rigidBody = getRigidBody(); - if (!rigidBody) { - return; - } - // XXX - // void setWorldTransform (const btTransform &worldTrans) - assert(false); - rigidBody->activate(); -} - glm::quat ObjectDynamic::getRotation() { auto rigidBody = getRigidBody(); if (!rigidBody) { @@ -166,17 +155,6 @@ glm::quat ObjectDynamic::getRotation() { return bulletToGLM(rigidBody->getOrientation()); } -void ObjectDynamic::setRotation(glm::quat rotation) { - auto rigidBody = getRigidBody(); - if (!rigidBody) { - return; - } - // XXX - // void setWorldTransform (const btTransform &worldTrans) - assert(false); - rigidBody->activate(); -} - glm::vec3 ObjectDynamic::getLinearVelocity() { auto rigidBody = getRigidBody(); if (!rigidBody) { diff --git a/libraries/physics/src/ObjectDynamic.h b/libraries/physics/src/ObjectDynamic.h index 6ea90bdba0..dcd0103a55 100644 --- a/libraries/physics/src/ObjectDynamic.h +++ b/libraries/physics/src/ObjectDynamic.h @@ -55,9 +55,7 @@ protected: EntityItemPointer getEntityByID(EntityItemID entityID) const; virtual btRigidBody* getRigidBody(); virtual glm::vec3 getPosition() override; - virtual void setPosition(glm::vec3 position) override; virtual glm::quat getRotation() override; - virtual void setRotation(glm::quat rotation) override; virtual glm::vec3 getLinearVelocity() override; virtual void setLinearVelocity(glm::vec3 linearVelocity) override; virtual glm::vec3 getAngularVelocity() override;