From 84bcfb7d7142648a27db9595d9d0eab06b09551c Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 22 Dec 2015 17:43:01 -0800 Subject: [PATCH 01/34] hook up a way for scripts to set model-entity joint state --- libraries/animation/src/Rig.cpp | 8 +++++ libraries/animation/src/Rig.h | 2 ++ .../src/RenderableModelEntityItem.cpp | 34 +++++++++++++++++-- .../src/RenderableModelEntityItem.h | 9 +++++ libraries/entities/src/EntityItem.h | 2 ++ .../entities/src/EntityScriptingInterface.cpp | 20 +++++++++++ .../entities/src/EntityScriptingInterface.h | 2 ++ libraries/entities/src/ModelEntityItem.h | 1 - libraries/render-utils/src/Model.cpp | 8 +++++ libraries/render-utils/src/Model.h | 3 ++ libraries/shared/src/SpatiallyNestable.h | 4 ++- 11 files changed, 89 insertions(+), 4 deletions(-) diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 68f382d2d9..4b2d4facc8 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -386,6 +386,10 @@ bool Rig::getAbsoluteJointRotationInRigFrame(int jointIndex, glm::quat& rotation } } +bool Rig::setAbsoluteJointRotationInRigFrame(int jointIndex, glm::quat& rotation) { + return false; +} + bool Rig::getJointTranslation(int jointIndex, glm::vec3& translation) const { QReadLocker readLock(&_externalPoseSetLock); if (jointIndex >= 0 && jointIndex < (int)_externalPoseSet._relativePoses.size()) { @@ -406,6 +410,10 @@ bool Rig::getAbsoluteJointTranslationInRigFrame(int jointIndex, glm::vec3& trans } } +bool Rig::setAbsoluteJointTranslationInRigFrame(int jointIndex, glm::vec3& translation) { + return false; +} + bool Rig::getJointCombinedRotation(int jointIndex, glm::quat& result, const glm::quat& rotation) const { // AJT: TODO: used by attachments ASSERT(false); diff --git a/libraries/animation/src/Rig.h b/libraries/animation/src/Rig.h index 9faf93e40b..3881b35dfb 100644 --- a/libraries/animation/src/Rig.h +++ b/libraries/animation/src/Rig.h @@ -134,6 +134,8 @@ public: // rig space (thread-safe) bool getAbsoluteJointRotationInRigFrame(int jointIndex, glm::quat& rotation) const; bool getAbsoluteJointTranslationInRigFrame(int jointIndex, glm::vec3& translation) const; + bool setAbsoluteJointRotationInRigFrame(int jointIndex, glm::quat& rotation); + bool setAbsoluteJointTranslationInRigFrame(int jointIndex, glm::vec3& translation); // legacy bool getJointCombinedRotation(int jointIndex, glm::quat& result, const glm::quat& rotation) const; diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 9127e4ca22..61ad4d2c2a 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -292,7 +292,21 @@ void RenderableModelEntityItem::render(RenderArgs* args) { } if (_model) { - // handle animations.. + // handle script updates... + _scriptSetFrameDataLock.withWriteLock([&] { + while (!_scriptSetFrameDataRotationsIndexes.empty()) { + int index = _scriptSetFrameDataRotationsIndexes.dequeue(); + glm::quat rotation = _scriptSetFrameDataRotations.dequeue(); + _model->setJointRotation(index, true, rotation, 1.0f); + } + while (!_scriptSetFrameDataTranslationsIndexes.empty()) { + int index = _scriptSetFrameDataTranslationsIndexes.dequeue(); + glm::vec3 translation = _scriptSetFrameDataTranslations.dequeue(); + _model->setJointTranslation(index, true, translation, 1.0f); + } + }); + + // handle animations... if (hasAnimation()) { if (!jointsMapped()) { QStringList modelJointNames = _model->getJointNames(); @@ -600,7 +614,7 @@ bool RenderableModelEntityItem::contains(const glm::vec3& point) const { const FBXGeometry& collisionGeometry = collisionNetworkGeometry->getFBXGeometry(); return collisionGeometry.convexHullContains(worldToEntity(point)); } - + return false; } @@ -624,6 +638,22 @@ glm::vec3 RenderableModelEntityItem::getAbsoluteJointTranslationInObjectFrame(in return glm::vec3(0.0f); } +bool RenderableModelEntityItem::setAbsoluteJointRotationInObjectFrame(int index, glm::quat& rotation) { + _scriptSetFrameDataLock.withWriteLock([&] { + _scriptSetFrameDataRotationsIndexes.enqueue(index); + _scriptSetFrameDataRotations.enqueue(rotation); + }); + return true; +} + +bool RenderableModelEntityItem::setAbsoluteJointTranslationInObjectFrame(int index, glm::vec3& translation) { + _scriptSetFrameDataLock.withWriteLock([&] { + _scriptSetFrameDataTranslationsIndexes.enqueue(index); + _scriptSetFrameDataTranslations.enqueue(translation); + }); + return true; +} + void RenderableModelEntityItem::locationChanged() { EntityItem::locationChanged(); if (_model && _model->isActive()) { diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index cf948bd7a0..d0847b66cb 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -71,6 +71,8 @@ public: // these are in the frame of this object (model space) virtual glm::quat getAbsoluteJointRotationInObjectFrame(int index) const override; virtual glm::vec3 getAbsoluteJointTranslationInObjectFrame(int index) const override; + virtual bool setAbsoluteJointRotationInObjectFrame(int index, glm::quat& rotation) override; + virtual bool setAbsoluteJointTranslationInObjectFrame(int index, glm::vec3& translation) override; virtual void loader() override; virtual void locationChanged() override; @@ -91,6 +93,13 @@ private: render::ItemID _myMetaItem; bool _showCollisionHull = false; + + // these are used to let scripts set ModelEntityItem joint data + ReadWriteLockable _scriptSetFrameDataLock; + QQueue _scriptSetFrameDataRotations; + QQueue _scriptSetFrameDataRotationsIndexes; + QQueue _scriptSetFrameDataTranslations; + QQueue _scriptSetFrameDataTranslationsIndexes; }; #endif // hifi_RenderableModelEntityItem_h diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 244198f7b8..841f68ddc1 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -381,6 +381,8 @@ public: // these are in the frame of this object virtual glm::quat getAbsoluteJointRotationInObjectFrame(int index) const override { return glm::quat(); } virtual glm::vec3 getAbsoluteJointTranslationInObjectFrame(int index) const override { return glm::vec3(0.0f); } + virtual bool setAbsoluteJointRotationInObjectFrame(int index, glm::quat& rotation) override { return false; } + virtual bool setAbsoluteJointTranslationInObjectFrame(int index, glm::vec3& translation) override { return false; } virtual void loader() {} // called indirectly when urls for geometry are updated diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index a0a6719521..c20db60601 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -826,3 +826,23 @@ glm::quat EntityScriptingInterface::getAbsoluteJointRotationInObjectFrame(const return glm::quat(); } } + +bool EntityScriptingInterface::setAbsoluteJointTranslationInObjectFrame(const QUuid& entityID, + int jointIndex, glm::vec3 translation) { + if (auto entity = checkForTreeEntityAndTypeMatch(entityID, EntityTypes::Model)) { + auto modelEntity = std::dynamic_pointer_cast(entity); + return modelEntity->setAbsoluteJointTranslationInObjectFrame(jointIndex, translation); + } else { + return false; + } +} + +bool EntityScriptingInterface::setAbsoluteJointRotationInObjectFrame(const QUuid& entityID, + int jointIndex, glm::quat rotation) { + if (auto entity = checkForTreeEntityAndTypeMatch(entityID, EntityTypes::Model)) { + auto modelEntity = std::dynamic_pointer_cast(entity); + return modelEntity->setAbsoluteJointRotationInObjectFrame(jointIndex, rotation); + } else { + return false; + } +} diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index f745b6b644..5d56ea2b99 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -151,6 +151,8 @@ public slots: Q_INVOKABLE glm::vec3 getAbsoluteJointTranslationInObjectFrame(const QUuid& entityID, int jointIndex); Q_INVOKABLE glm::quat getAbsoluteJointRotationInObjectFrame(const QUuid& entityID, int jointIndex); + Q_INVOKABLE bool setAbsoluteJointTranslationInObjectFrame(const QUuid& entityID, int jointIndex, glm::vec3 translation); + Q_INVOKABLE bool setAbsoluteJointRotationInObjectFrame(const QUuid& entityID, int jointIndex, glm::quat rotation); signals: void collisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, const Collision& collision); diff --git a/libraries/entities/src/ModelEntityItem.h b/libraries/entities/src/ModelEntityItem.h index b08fed5970..9978f3359a 100644 --- a/libraries/entities/src/ModelEntityItem.h +++ b/libraries/entities/src/ModelEntityItem.h @@ -129,7 +129,6 @@ protected: QVector _lastKnownFrameDataTranslations; int _lastKnownCurrentFrame; - bool isAnimatingSomething() const; rgbColor _color; diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index dbd3a6289f..91ca8e60cb 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -699,6 +699,14 @@ void Model::setJointTranslation(int index, bool valid, const glm::vec3& translat _rig->setJointTranslation(index, valid, translation, priority); } +bool Model::setAbsoluteJointRotationInRigFrame(int jointIndex, glm::quat& rotation) { + return _rig->setAbsoluteJointRotationInRigFrame(jointIndex, rotation); +} + +bool Model::setAbsoluteJointTranslationInRigFrame(int jointIndex, glm::vec3& translation) { + return _rig->setAbsoluteJointTranslationInRigFrame(jointIndex, translation); +} + int Model::getParentJointIndex(int jointIndex) const { return (isActive() && jointIndex != -1) ? _geometry->getFBXGeometry().joints.at(jointIndex).parentIndex : -1; } diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index a93338e41a..327583c212 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -170,6 +170,9 @@ public: bool getAbsoluteJointRotationInRigFrame(int jointIndex, glm::quat& rotationOut) const; bool getAbsoluteJointTranslationInRigFrame(int jointIndex, glm::vec3& translationOut) const; + bool setAbsoluteJointRotationInRigFrame(int jointIndex, glm::quat& rotation); + bool setAbsoluteJointTranslationInRigFrame(int jointIndex, glm::vec3& translation); + bool getRelativeDefaultJointRotation(int jointIndex, glm::quat& rotationOut) const; bool getRelativeDefaultJointTranslation(int jointIndex, glm::vec3& translationOut) const; diff --git a/libraries/shared/src/SpatiallyNestable.h b/libraries/shared/src/SpatiallyNestable.h index 7a43e2a563..f6a9678d34 100644 --- a/libraries/shared/src/SpatiallyNestable.h +++ b/libraries/shared/src/SpatiallyNestable.h @@ -91,7 +91,9 @@ public: virtual const Transform getAbsoluteJointTransformInObjectFrame(int jointIndex) const; virtual glm::quat getAbsoluteJointRotationInObjectFrame(int index) const { assert(false); return glm::quat(); } virtual glm::vec3 getAbsoluteJointTranslationInObjectFrame(int index) const { assert(false); return glm::vec3(); } - + virtual bool setAbsoluteJointRotationInObjectFrame(int index, glm::quat& rotation) { assert(false); return false; } + virtual bool setAbsoluteJointTranslationInObjectFrame(int index, glm::vec3& translation) { assert(false); return false; } + SpatiallyNestablePointer getThisPointer() const; protected: From 1a51c9ddbeebbb45dac5b8cfba9ec0e24a1f88ba Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 22 Dec 2015 17:56:12 -0800 Subject: [PATCH 02/34] remove some unused stuff --- libraries/animation/src/Rig.cpp | 8 -------- libraries/animation/src/Rig.h | 2 -- libraries/render-utils/src/Model.cpp | 8 -------- libraries/render-utils/src/Model.h | 3 --- 4 files changed, 21 deletions(-) diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 4b2d4facc8..68f382d2d9 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -386,10 +386,6 @@ bool Rig::getAbsoluteJointRotationInRigFrame(int jointIndex, glm::quat& rotation } } -bool Rig::setAbsoluteJointRotationInRigFrame(int jointIndex, glm::quat& rotation) { - return false; -} - bool Rig::getJointTranslation(int jointIndex, glm::vec3& translation) const { QReadLocker readLock(&_externalPoseSetLock); if (jointIndex >= 0 && jointIndex < (int)_externalPoseSet._relativePoses.size()) { @@ -410,10 +406,6 @@ bool Rig::getAbsoluteJointTranslationInRigFrame(int jointIndex, glm::vec3& trans } } -bool Rig::setAbsoluteJointTranslationInRigFrame(int jointIndex, glm::vec3& translation) { - return false; -} - bool Rig::getJointCombinedRotation(int jointIndex, glm::quat& result, const glm::quat& rotation) const { // AJT: TODO: used by attachments ASSERT(false); diff --git a/libraries/animation/src/Rig.h b/libraries/animation/src/Rig.h index 3881b35dfb..9faf93e40b 100644 --- a/libraries/animation/src/Rig.h +++ b/libraries/animation/src/Rig.h @@ -134,8 +134,6 @@ public: // rig space (thread-safe) bool getAbsoluteJointRotationInRigFrame(int jointIndex, glm::quat& rotation) const; bool getAbsoluteJointTranslationInRigFrame(int jointIndex, glm::vec3& translation) const; - bool setAbsoluteJointRotationInRigFrame(int jointIndex, glm::quat& rotation); - bool setAbsoluteJointTranslationInRigFrame(int jointIndex, glm::vec3& translation); // legacy bool getJointCombinedRotation(int jointIndex, glm::quat& result, const glm::quat& rotation) const; diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 91ca8e60cb..dbd3a6289f 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -699,14 +699,6 @@ void Model::setJointTranslation(int index, bool valid, const glm::vec3& translat _rig->setJointTranslation(index, valid, translation, priority); } -bool Model::setAbsoluteJointRotationInRigFrame(int jointIndex, glm::quat& rotation) { - return _rig->setAbsoluteJointRotationInRigFrame(jointIndex, rotation); -} - -bool Model::setAbsoluteJointTranslationInRigFrame(int jointIndex, glm::vec3& translation) { - return _rig->setAbsoluteJointTranslationInRigFrame(jointIndex, translation); -} - int Model::getParentJointIndex(int jointIndex) const { return (isActive() && jointIndex != -1) ? _geometry->getFBXGeometry().joints.at(jointIndex).parentIndex : -1; } diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 327583c212..a93338e41a 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -170,9 +170,6 @@ public: bool getAbsoluteJointRotationInRigFrame(int jointIndex, glm::quat& rotationOut) const; bool getAbsoluteJointTranslationInRigFrame(int jointIndex, glm::vec3& translationOut) const; - bool setAbsoluteJointRotationInRigFrame(int jointIndex, glm::quat& rotation); - bool setAbsoluteJointTranslationInRigFrame(int jointIndex, glm::vec3& translation); - bool getRelativeDefaultJointRotation(int jointIndex, glm::quat& rotationOut) const; bool getRelativeDefaultJointTranslation(int jointIndex, glm::vec3& translationOut) const; From d878dde952669660023f3336e8b5275bc5797e6b Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 22 Dec 2015 17:57:25 -0800 Subject: [PATCH 03/34] whitespace --- libraries/entities/src/ModelEntityItem.h | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/entities/src/ModelEntityItem.h b/libraries/entities/src/ModelEntityItem.h index 9978f3359a..b08fed5970 100644 --- a/libraries/entities/src/ModelEntityItem.h +++ b/libraries/entities/src/ModelEntityItem.h @@ -129,6 +129,7 @@ protected: QVector _lastKnownFrameDataTranslations; int _lastKnownCurrentFrame; + bool isAnimatingSomething() const; rgbColor _color; From 83f60d6e97b5f9a01f3610d917267250b3f772b7 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 23 Dec 2015 15:43:50 -0800 Subject: [PATCH 04/34] make entity properties for model-entity joint-states --- .../src/RenderableModelEntityItem.cpp | 151 +++++++++++++---- .../src/RenderableModelEntityItem.h | 25 ++- .../entities/src/EntityItemProperties.cpp | 26 +++ libraries/entities/src/EntityItemProperties.h | 5 + .../entities/src/EntityItemPropertiesMacros.h | 14 ++ libraries/entities/src/EntityPropertyFlags.h | 6 + libraries/entities/src/ModelEntityItem.cpp | 155 +++++++++++------- libraries/entities/src/ModelEntityItem.h | 29 +++- .../networking/src/udt/PacketHeaders.cpp | 2 +- libraries/networking/src/udt/PacketHeaders.h | 1 + libraries/octree/src/OctreePacketData.cpp | 46 +++++- libraries/octree/src/OctreePacketData.h | 18 +- libraries/shared/src/RegisteredMetaTypes.cpp | 98 +++++++++-- libraries/shared/src/RegisteredMetaTypes.h | 8 + 14 files changed, 449 insertions(+), 135 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 61ad4d2c2a..c77a274692 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -13,6 +13,7 @@ #include #include +#include #include #include @@ -230,8 +231,8 @@ bool RenderableModelEntityItem::addToScene(EntityItemPointer self, std::shared_p return true; } - -void RenderableModelEntityItem::removeFromScene(EntityItemPointer self, std::shared_ptr scene, + +void RenderableModelEntityItem::removeFromScene(EntityItemPointer self, std::shared_ptr scene, render::PendingChanges& pendingChanges) { pendingChanges.removeItem(_myMetaItem); if (_model) { @@ -239,6 +240,80 @@ void RenderableModelEntityItem::removeFromScene(EntityItemPointer self, std::sha } } +void RenderableModelEntityItem::resizeJointArrays(int newSize) { + if (newSize < 0) { + if (_model && _model->isActive() && _model->isLoaded() && !_needsInitialSimulation) { + newSize = _model->getJointStateCount(); + } + } + ModelEntityItem::resizeJointArrays(newSize); +} + +bool RenderableModelEntityItem::getAnimationFrame() { + bool newFrame = false; + + if (!_model || !_model->isActive() || !_model->isLoaded() || _needsInitialSimulation) { + return false; + } + + if (!hasAnimation() || !_jointMappingCompleted) { + return false; + } + AnimationPointer myAnimation = getAnimation(_animationProperties.getURL()); // FIXME: this could be optimized + if (myAnimation && myAnimation->isLoaded()) { + + const QVector& frames = myAnimation->getFramesReference(); // NOTE: getFrames() is too heavy + auto& fbxJoints = myAnimation->getGeometry().joints; + + int frameCount = frames.size(); + if (frameCount > 0) { + int animationCurrentFrame = (int)(glm::floor(getAnimationCurrentFrame())) % frameCount; + if (animationCurrentFrame < 0 || animationCurrentFrame > frameCount) { + animationCurrentFrame = 0; + } + + if (animationCurrentFrame != _lastKnownCurrentFrame) { + _lastKnownCurrentFrame = animationCurrentFrame; + newFrame = true; + + resizeJointArrays(); + if (_jointMapping.size() != _model->getJointStateCount()) { + qDebug() << "BLERG" << _jointMapping.size() << _model->getJointStateCount(); + assert(false); + } + for (int j = 0; j < _jointMapping.size(); j++) { + int index = _jointMapping[j]; + if (index >= 0) { + if (index >= frames[animationCurrentFrame].rotations.size() || + index >= frames[animationCurrentFrame].translations.size()) { + return false; + } + const glm::quat rotation = frames[animationCurrentFrame].rotations[index]; + const glm::vec3 translation = frames[animationCurrentFrame].translations[index]; + + glm::mat4 translationMat = glm::translate(translation); + glm::mat4 rotationMat = glm::mat4_cast(rotation); + glm::mat4 finalMat = (translationMat * fbxJoints[index].preTransform * + rotationMat * fbxJoints[index].postTransform); + _absoluteJointTranslationsInObjectFrame[j] = extractTranslation(finalMat); + _absoluteJointTranslationsInObjectFrameSet[j] = true; + _absoluteJointTranslationsInObjectFrameDirty[j] = true; + + // XXX Tony will fix this better in some other PR + // _absoluteJointRotationsInObjectFrame[j] = glmExtractRotation(finalMat); + _absoluteJointRotationsInObjectFrame[j] = fbxJoints[index].preRotation * rotation; + // XXX + + _absoluteJointRotationsInObjectFrameSet[j] = true; + _absoluteJointRotationsInObjectFrameDirty[j] = true; + } + } + } + } + } + + return newFrame; +} // NOTE: this only renders the "meta" portion of the Model, namely it renders debugging items, and it handles // the per frame simulation/update that might be required if the models properties changed. @@ -292,40 +367,32 @@ void RenderableModelEntityItem::render(RenderArgs* args) { } if (_model) { - // handle script updates... - _scriptSetFrameDataLock.withWriteLock([&] { - while (!_scriptSetFrameDataRotationsIndexes.empty()) { - int index = _scriptSetFrameDataRotationsIndexes.dequeue(); - glm::quat rotation = _scriptSetFrameDataRotations.dequeue(); - _model->setJointRotation(index, true, rotation, 1.0f); - } - while (!_scriptSetFrameDataTranslationsIndexes.empty()) { - int index = _scriptSetFrameDataTranslationsIndexes.dequeue(); - glm::vec3 translation = _scriptSetFrameDataTranslations.dequeue(); - _model->setJointTranslation(index, true, translation, 1.0f); - } - }); - - // handle animations... if (hasAnimation()) { if (!jointsMapped()) { QStringList modelJointNames = _model->getJointNames(); mapJoints(modelJointNames); } + } - if (jointsMapped()) { - bool newFrame; - QVector frameDataRotations; - QVector frameDataTranslations; - getAnimationFrame(newFrame, frameDataRotations, frameDataTranslations); - assert(frameDataRotations.size() == frameDataTranslations.size()); - if (newFrame) { - for (int i = 0; i < frameDataRotations.size(); i++) { - _model->setJointState(i, true, frameDataRotations[i], frameDataTranslations[i], 1.0f); - } + _jointDataLock.withWriteLock([&] { + getAnimationFrame(); + + // relay any inbound joint changes from scripts/animation/network to the model/rig + for (int index = 0; index < _absoluteJointRotationsInObjectFrame.size(); index++) { + if (_absoluteJointRotationsInObjectFrameDirty[index]) { + glm::quat rotation = _absoluteJointRotationsInObjectFrame[index]; + _model->setJointRotation(index, true, rotation, 1.0f); + _absoluteJointRotationsInObjectFrameDirty[index] = false; } } - } + for (int index = 0; index < _absoluteJointTranslationsInObjectFrame.size(); index++) { + if (_absoluteJointTranslationsInObjectFrameDirty[index]) { + glm::vec3 translation = _absoluteJointTranslationsInObjectFrame[index]; + _model->setJointTranslation(index, true, translation, 1.0f); + _absoluteJointTranslationsInObjectFrameDirty[index] = false; + } + } + }); bool movingOrAnimating = isMoving() || isAnimatingSomething(); if ((movingOrAnimating || @@ -639,19 +706,31 @@ glm::vec3 RenderableModelEntityItem::getAbsoluteJointTranslationInObjectFrame(in } bool RenderableModelEntityItem::setAbsoluteJointRotationInObjectFrame(int index, glm::quat& rotation) { - _scriptSetFrameDataLock.withWriteLock([&] { - _scriptSetFrameDataRotationsIndexes.enqueue(index); - _scriptSetFrameDataRotations.enqueue(rotation); + bool result = false; + _jointDataLock.withWriteLock([&] { + resizeJointArrays(); + if (index >= 0 && index < _absoluteJointRotationsInObjectFrame.size()) { + _absoluteJointRotationsInObjectFrame[index] = rotation; + _absoluteJointRotationsInObjectFrameSet[index] = true; + _absoluteJointRotationsInObjectFrameDirty[index] = true; + result = true; + } }); - return true; + return result; } bool RenderableModelEntityItem::setAbsoluteJointTranslationInObjectFrame(int index, glm::vec3& translation) { - _scriptSetFrameDataLock.withWriteLock([&] { - _scriptSetFrameDataTranslationsIndexes.enqueue(index); - _scriptSetFrameDataTranslations.enqueue(translation); + bool result = false; + _jointDataLock.withWriteLock([&] { + resizeJointArrays(); + if (index >= 0 && index < _absoluteJointTranslationsInObjectFrame.size()) { + _absoluteJointTranslationsInObjectFrame[index] = translation; + _absoluteJointTranslationsInObjectFrameSet[index] = true; + _absoluteJointTranslationsInObjectFrameDirty[index] = true; + result = true; + } }); - return true; + return result; } void RenderableModelEntityItem::locationChanged() { diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index d0847b66cb..afb26d632d 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -33,15 +33,15 @@ public: virtual EntityItemProperties getProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags()) const override; virtual bool setProperties(const EntityItemProperties& properties) override; - virtual int readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead, + virtual int readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead, ReadBitstreamToTreeParams& args, EntityPropertyFlags& propertyFlags, bool overwriteLocalData, bool& somethingChanged) override; - + virtual void somethingChangedNotification() override { // FIX ME: this is overly aggressive. We only really need to simulate() if something about // the world space transform has changed and/or if some animation is occurring. - _needsInitialSimulation = true; + _needsInitialSimulation = true; } virtual bool readyToAddToScene(RenderArgs* renderArgs = nullptr); @@ -52,12 +52,12 @@ public: virtual void render(RenderArgs* args) override; virtual bool supportsDetailedRayIntersection() const override { return true; } virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction, - bool& keepSearching, OctreeElementPointer& element, float& distance, + bool& keepSearching, OctreeElementPointer& element, float& distance, BoxFace& face, glm::vec3& surfaceNormal, void** intersectedObject, bool precisionPicking) const override; Model* getModel(EntityTreeRenderer* renderer); - + virtual bool needsToCallUpdate() const override; virtual void update(const quint64& now) override; @@ -65,7 +65,7 @@ public: virtual bool isReadyToComputeShape() override; virtual void computeShapeInfo(ShapeInfo& info) override; - + virtual bool contains(const glm::vec3& point) const override; // these are in the frame of this object (model space) @@ -77,9 +77,11 @@ public: virtual void loader() override; virtual void locationChanged() override; + virtual void resizeJointArrays(int newSize = -1) override; + private: void remapTextures(); - + Model* _model = nullptr; bool _needsInitialSimulation = true; bool _needsModelReload = true; @@ -89,17 +91,12 @@ private: bool _originalTexturesRead = false; QVector> _points; bool _dimensionsInitialized = true; - + render::ItemID _myMetaItem; bool _showCollisionHull = false; - // these are used to let scripts set ModelEntityItem joint data - ReadWriteLockable _scriptSetFrameDataLock; - QQueue _scriptSetFrameDataRotations; - QQueue _scriptSetFrameDataRotationsIndexes; - QQueue _scriptSetFrameDataTranslations; - QQueue _scriptSetFrameDataTranslationsIndexes; + bool getAnimationFrame(); }; #endif // hifi_RenderableModelEntityItem_h diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 3a2fdf55d4..ef373bc206 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -262,6 +262,10 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_Z_P_NEIGHBOR_ID, zPNeighborID); CHECK_PROPERTY_CHANGE(PROP_PARENT_ID, parentID); CHECK_PROPERTY_CHANGE(PROP_PARENT_JOINT_INDEX, parentJointIndex); + CHECK_PROPERTY_CHANGE(PROP_JOINT_ROTATIONS_SET, jointRotationsSet); + CHECK_PROPERTY_CHANGE(PROP_JOINT_ROTATIONS, jointRotations); + CHECK_PROPERTY_CHANGE(PROP_JOINT_TRANSLATIONS_SET, jointTranslationsSet); + CHECK_PROPERTY_CHANGE(PROP_JOINT_TRANSLATIONS, jointTranslations); changedProperties += _animation.getChangedProperties(); changedProperties += _keyLight.getChangedProperties(); @@ -363,6 +367,10 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool if (_type == EntityTypes::Model) { COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MODEL_URL, modelURL); _animation.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties); + COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_JOINT_ROTATIONS_SET, jointRotationsSet); + COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_JOINT_ROTATIONS, jointRotations); + COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_JOINT_TRANSLATIONS_SET, jointTranslationsSet); + COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_JOINT_TRANSLATIONS, jointTranslations); } if (_type == EntityTypes::Model || _type == EntityTypes::Zone || _type == EntityTypes::ParticleEffect) { @@ -739,6 +747,14 @@ void EntityItemProperties::entityPropertyFlagsFromScriptValue(const QScriptValue ADD_PROPERTY_TO_MAP(PROP_Y_P_NEIGHBOR_ID, YPNeighborID, yPNeighborID, EntityItemID); ADD_PROPERTY_TO_MAP(PROP_Z_P_NEIGHBOR_ID, ZPNeighborID, zPNeighborID, EntityItemID); + ADD_PROPERTY_TO_MAP(PROP_PARENT_ID, ParentID, parentID, QUuid); + ADD_PROPERTY_TO_MAP(PROP_PARENT_JOINT_INDEX, ParentJointIndex, parentJointIndex, uint16_t); + + ADD_PROPERTY_TO_MAP(PROP_JOINT_ROTATIONS_SET, JointRotationsSet, jointRotationsSet, QVector); + ADD_PROPERTY_TO_MAP(PROP_JOINT_ROTATIONS, JointRotations, jointRotations, QVector); + ADD_PROPERTY_TO_MAP(PROP_JOINT_TRANSLATIONS_SET, JointTranslationsSet, jointTranslationsSet, QVector); + ADD_PROPERTY_TO_MAP(PROP_JOINT_TRANSLATIONS, JointTranslations, jointTranslations, QVector); + ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_URL, Animation, animation, URL, url); ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_FPS, Animation, animation, FPS, fps); ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_FRAME_INDEX, Animation, animation, CurrentFrame, currentFrame); @@ -943,6 +959,11 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType command, EntityItem _staticAnimation.setProperties(properties); _staticAnimation.appendToEditPacket(packetData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState); + + APPEND_ENTITY_PROPERTY(PROP_JOINT_ROTATIONS_SET, properties.getJointRotationsSet()); + APPEND_ENTITY_PROPERTY(PROP_JOINT_ROTATIONS, properties.getJointRotations()); + APPEND_ENTITY_PROPERTY(PROP_JOINT_TRANSLATIONS_SET, properties.getJointTranslationsSet()); + APPEND_ENTITY_PROPERTY(PROP_JOINT_TRANSLATIONS, properties.getJointTranslations()); } if (properties.getType() == EntityTypes::Light) { @@ -1228,6 +1249,11 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SHAPE_TYPE, ShapeType, setShapeType); properties.getAnimation().decodeFromEditPacket(propertyFlags, dataAt, processedBytes); + + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_JOINT_ROTATIONS_SET, QVector, setJointRotationsSet); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_JOINT_ROTATIONS, QVector, setJointRotations); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_JOINT_TRANSLATIONS_SET, QVector, setJointTranslationsSet); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_JOINT_TRANSLATIONS, QVector, setJointTranslations); } if (properties.getType() == EntityTypes::Light) { diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 5420e75aed..f8bdfcc0dd 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -198,6 +198,11 @@ public: DEFINE_PROPERTY_REF(PROP_LOCAL_POSITION, LocalPosition, localPosition, glmVec3, ENTITY_ITEM_ZERO_VEC3); DEFINE_PROPERTY_REF(PROP_LOCAL_ROTATION, LocalRotation, localRotation, glmQuat, ENTITY_ITEM_DEFAULT_ROTATION); + DEFINE_PROPERTY_REF(PROP_JOINT_ROTATIONS_SET, JointRotationsSet, jointRotationsSet, QVector, QVector()); + DEFINE_PROPERTY_REF(PROP_JOINT_ROTATIONS, JointRotations, jointRotations, QVector, QVector()); + DEFINE_PROPERTY_REF(PROP_JOINT_TRANSLATIONS_SET, JointTranslationsSet, jointTranslationsSet, QVector, QVector()); + DEFINE_PROPERTY_REF(PROP_JOINT_TRANSLATIONS, JointTranslations, jointTranslations, QVector, QVector()); + static QString getBackgroundModeString(BackgroundMode mode); diff --git a/libraries/entities/src/EntityItemPropertiesMacros.h b/libraries/entities/src/EntityItemPropertiesMacros.h index 304e6f672c..a8aa23a5c9 100644 --- a/libraries/entities/src/EntityItemPropertiesMacros.h +++ b/libraries/entities/src/EntityItemPropertiesMacros.h @@ -113,6 +113,8 @@ inline QScriptValue convertScriptValue(QScriptEngine* e, const xColor& v) { retu inline QScriptValue convertScriptValue(QScriptEngine* e, const glm::quat& v) { return quatToScriptValue(e, v); } inline QScriptValue convertScriptValue(QScriptEngine* e, const QScriptValue& v) { return v; } inline QScriptValue convertScriptValue(QScriptEngine* e, const QVector& v) {return qVectorVec3ToScriptValue(e, v); } +inline QScriptValue convertScriptValue(QScriptEngine* e, const QVector& v) {return qVectorQuatToScriptValue(e, v); } +inline QScriptValue convertScriptValue(QScriptEngine* e, const QVector& v) {return qVectorBoolToScriptValue(e, v); } inline QScriptValue convertScriptValue(QScriptEngine* e, const QVector& v) { return qVectorFloatToScriptValue(e, v); } inline QScriptValue convertScriptValue(QScriptEngine* e, const QByteArray& v) { @@ -173,6 +175,8 @@ inline QScriptValue convertScriptValue(QScriptEngine* e, const EntityItemID& v) typedef glm::vec3 glmVec3; typedef glm::quat glmQuat; typedef QVector qVectorVec3; +typedef QVector qVectorQuat; +typedef QVector qVectorBool; typedef QVector qVectorFloat; inline float float_convertFromScriptValue(const QScriptValue& v, bool& isValid) { return v.toVariant().toFloat(&isValid); } inline quint64 quint64_convertFromScriptValue(const QScriptValue& v, bool& isValid) { return v.toVariant().toULongLong(&isValid); } @@ -235,6 +239,16 @@ inline qVectorVec3 qVectorVec3_convertFromScriptValue(const QScriptValue& v, boo return qVectorVec3FromScriptValue(v); } +inline qVectorQuat qVectorQuat_convertFromScriptValue(const QScriptValue& v, bool& isValid) { + isValid = true; + return qVectorQuatFromScriptValue(v); +} + +inline qVectorBool qVectorBool_convertFromScriptValue(const QScriptValue& v, bool& isValid) { + isValid = true; + return qVectorBoolFromScriptValue(v); +} + inline glmQuat glmQuat_convertFromScriptValue(const QScriptValue& v, bool& isValid) { isValid = false; /// assume it can't be converted QScriptValue x = v.property("x"); diff --git a/libraries/entities/src/EntityPropertyFlags.h b/libraries/entities/src/EntityPropertyFlags.h index 2ba86a491e..5e38e8bd7c 100644 --- a/libraries/entities/src/EntityPropertyFlags.h +++ b/libraries/entities/src/EntityPropertyFlags.h @@ -157,6 +157,12 @@ enum EntityPropertyList { PROP_LOCAL_POSITION, // only used to convert values to and from scripts PROP_LOCAL_ROTATION, // only used to convert values to and from scripts + // ModelEntity joint state + PROP_JOINT_ROTATIONS_SET, + PROP_JOINT_ROTATIONS, + PROP_JOINT_TRANSLATIONS_SET, + PROP_JOINT_TRANSLATIONS, + //////////////////////////////////////////////////////////////////////////////////////////////////// // ATTENTION: add new properties to end of list just ABOVE this line PROP_AFTER_LAST_ITEM, diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp index a1f16ee251..4f8ba1cc6c 100644 --- a/libraries/entities/src/ModelEntityItem.cpp +++ b/libraries/entities/src/ModelEntityItem.cpp @@ -133,6 +133,11 @@ int ModelEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, somethingChanged = true; } + READ_ENTITY_PROPERTY(PROP_JOINT_ROTATIONS_SET, QVector, setJointRotationsSet); + READ_ENTITY_PROPERTY(PROP_JOINT_ROTATIONS, QVector, setJointRotations); + READ_ENTITY_PROPERTY(PROP_JOINT_TRANSLATIONS_SET, QVector, setJointTranslationsSet); + READ_ENTITY_PROPERTY(PROP_JOINT_TRANSLATIONS, QVector, setJointTranslations); + return bytesRead; } @@ -145,6 +150,10 @@ EntityPropertyFlags ModelEntityItem::getEntityProperties(EncodeBitstreamParams& requestedProperties += PROP_TEXTURES; requestedProperties += PROP_SHAPE_TYPE; requestedProperties += _animationProperties.getEntityProperties(params); + requestedProperties += PROP_JOINT_ROTATIONS_SET; + requestedProperties += PROP_JOINT_ROTATIONS; + requestedProperties += PROP_JOINT_TRANSLATIONS_SET; + requestedProperties += PROP_JOINT_TRANSLATIONS; return requestedProperties; } @@ -168,6 +177,11 @@ void ModelEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBit propertyFlags, propertiesDidntFit, propertyCount, appendState); APPEND_ENTITY_PROPERTY(PROP_SHAPE_TYPE, (uint32_t)getShapeType()); + + APPEND_ENTITY_PROPERTY(PROP_JOINT_ROTATIONS_SET, getJointRotationsSet()); + APPEND_ENTITY_PROPERTY(PROP_JOINT_ROTATIONS, getJointRotations()); + APPEND_ENTITY_PROPERTY(PROP_JOINT_TRANSLATIONS_SET, getJointTranslationsSet()); + APPEND_ENTITY_PROPERTY(PROP_JOINT_TRANSLATIONS, getJointTranslations()); } @@ -214,62 +228,6 @@ void ModelEntityItem::mapJoints(const QStringList& modelJointNames) { } } -void ModelEntityItem::getAnimationFrame(bool& newFrame, - QVector& rotationsResult, QVector& translationsResult) { - newFrame = false; - - if (!hasAnimation() || !_jointMappingCompleted) { - rotationsResult = _lastKnownFrameDataRotations; - translationsResult = _lastKnownFrameDataTranslations; - } - AnimationPointer myAnimation = getAnimation(_animationProperties.getURL()); // FIXME: this could be optimized - if (myAnimation && myAnimation->isLoaded()) { - - const QVector& frames = myAnimation->getFramesReference(); // NOTE: getFrames() is too heavy - auto& fbxJoints = myAnimation->getGeometry().joints; - - int frameCount = frames.size(); - if (frameCount > 0) { - int animationCurrentFrame = (int)(glm::floor(getAnimationCurrentFrame())) % frameCount; - if (animationCurrentFrame < 0 || animationCurrentFrame > frameCount) { - animationCurrentFrame = 0; - } - - if (animationCurrentFrame != _lastKnownCurrentFrame) { - _lastKnownCurrentFrame = animationCurrentFrame; - newFrame = true; - - const QVector& rotations = frames[animationCurrentFrame].rotations; - const QVector& translations = frames[animationCurrentFrame].translations; - - _lastKnownFrameDataRotations.resize(_jointMapping.size()); - _lastKnownFrameDataTranslations.resize(_jointMapping.size()); - - for (int j = 0; j < _jointMapping.size(); j++) { - int index = _jointMapping[j]; - if (index >= 0) { - glm::mat4 translationMat; - if (index < translations.size()) { - translationMat = glm::translate(translations[index]); - } - glm::mat4 rotationMat; - if (index < rotations.size()) { - rotationMat = glm::mat4_cast(rotations[index]); - } - glm::mat4 finalMat = (translationMat * fbxJoints[index].preTransform * - rotationMat * fbxJoints[index].postTransform); - _lastKnownFrameDataTranslations[j] = extractTranslation(finalMat); - _lastKnownFrameDataRotations[j] = glmExtractRotation(finalMat); - } - } - } - } - } - - rotationsResult = _lastKnownFrameDataRotations; - translationsResult = _lastKnownFrameDataTranslations; -} - bool ModelEntityItem::isAnimatingSomething() const { return getAnimationIsPlaying() && getAnimationFPS() != 0.0f && @@ -412,3 +370,88 @@ void ModelEntityItem::setAnimationFPS(float value) { bool ModelEntityItem::shouldBePhysical() const { return getShapeType() != SHAPE_TYPE_NONE; } + +void ModelEntityItem::resizeJointArrays(int newSize) { + if (newSize >= 0 && newSize > _absoluteJointRotationsInObjectFrame.size()) { + _absoluteJointRotationsInObjectFrame.resize(newSize); + _absoluteJointRotationsInObjectFrameSet.resize(newSize); + _absoluteJointRotationsInObjectFrameDirty.resize(newSize); + _absoluteJointTranslationsInObjectFrame.resize(newSize); + _absoluteJointTranslationsInObjectFrameSet.resize(newSize); + _absoluteJointTranslationsInObjectFrameDirty.resize(newSize); + } +} + +void ModelEntityItem::setJointRotations(const QVector& rotations) { + _jointDataLock.withWriteLock([&] { + resizeJointArrays(rotations.size()); + for (int index = 0; index < rotations.size(); index++) { + if (_absoluteJointRotationsInObjectFrameSet[index]) { + _absoluteJointRotationsInObjectFrame[index] = rotations[index]; + _absoluteJointRotationsInObjectFrameDirty[index] = true; + } + } + }); +} + +void ModelEntityItem::setJointRotationsSet(const QVector& rotationsSet) { + _jointDataLock.withWriteLock([&] { + resizeJointArrays(rotationsSet.size()); + for (int index = 0; index < rotationsSet.size(); index++) { + _absoluteJointRotationsInObjectFrameSet[index] = rotationsSet[index]; + } + }); +} + +void ModelEntityItem::setJointTranslations(const QVector& translations) { + _jointDataLock.withWriteLock([&] { + resizeJointArrays(translations.size()); + for (int index = 0; index < translations.size(); index++) { + if (_absoluteJointTranslationsInObjectFrameSet[index]) { + _absoluteJointTranslationsInObjectFrame[index] = translations[index]; + _absoluteJointTranslationsInObjectFrameSet[index] = true; + } + } + }); +} + +void ModelEntityItem::setJointTranslationsSet(const QVector& translationsSet) { + _jointDataLock.withWriteLock([&] { + resizeJointArrays(translationsSet.size()); + for (int index = 0; index < translationsSet.size(); index++) { + _absoluteJointTranslationsInObjectFrameSet[index] = translationsSet[index]; + } + }); +} + +QVector ModelEntityItem::getJointRotations() const { + QVector result; + _jointDataLock.withReadLock([&] { + result = _absoluteJointRotationsInObjectFrame; + }); + return result; +} + +QVector ModelEntityItem::getJointRotationsSet() const { + QVector result; + _jointDataLock.withReadLock([&] { + result = _absoluteJointRotationsInObjectFrameSet; + }); + return result; +} + +QVector ModelEntityItem::getJointTranslations() const { + QVector result; + _jointDataLock.withReadLock([&] { + result = _absoluteJointTranslationsInObjectFrame; + }); + return result; +} + +QVector ModelEntityItem::getJointTranslationsSet() const { + QVector result; + _jointDataLock.withReadLock([&] { + result = _absoluteJointTranslationsInObjectFrameSet; + }); + return result; +} diff --git a/libraries/entities/src/ModelEntityItem.h b/libraries/entities/src/ModelEntityItem.h index b08fed5970..232c5c677a 100644 --- a/libraries/entities/src/ModelEntityItem.h +++ b/libraries/entities/src/ModelEntityItem.h @@ -103,7 +103,6 @@ public: float getAnimationLastFrame() const { return _animationLoop.getLastFrame(); } void mapJoints(const QStringList& modelJointNames); - void getAnimationFrame(bool& newFrame, QVector& rotationsResult, QVector& translationsResult); bool jointsMapped() const { return _jointMappingURL == getAnimationURL() && _jointMappingCompleted; } bool getAnimationIsPlaying() const { return _animationLoop.getRunning(); } @@ -121,14 +120,34 @@ public: virtual glm::vec3 getJointPosition(int jointIndex) const { return glm::vec3(); } virtual glm::quat getJointRotation(int jointIndex) const { return glm::quat(); } + void setJointRotations(const QVector& rotations); + void setJointRotationsSet(const QVector& rotationsSet); + void setJointTranslations(const QVector& translations); + void setJointTranslationsSet(const QVector& translationsSet); + QVector getJointRotations() const; + QVector getJointRotationsSet() const; + QVector getJointTranslations() const; + QVector getJointTranslationsSet() const; + private: void setAnimationSettings(const QString& value); // only called for old bitstream format protected: - QVector _lastKnownFrameDataRotations; - QVector _lastKnownFrameDataTranslations; + // these are used: + // - to bounce joint data from an animation into the model/rig. + // - to relay changes from scripts to model/rig. + // - to relay between network and model/rig + // they aren't currently updated from data in the model/rig, and they don't have a direct effect + // on what's rendered. + ReadWriteLockable _jointDataLock; + QVector _absoluteJointRotationsInObjectFrame; + QVector _absoluteJointRotationsInObjectFrameSet; // ever set? + QVector _absoluteJointRotationsInObjectFrameDirty; // needs a relay to model/rig? + QVector _absoluteJointTranslationsInObjectFrame; + QVector _absoluteJointTranslationsInObjectFrameSet; // ever set? + QVector _absoluteJointTranslationsInObjectFrameDirty; // needs a relay to model/rig? int _lastKnownCurrentFrame; - + virtual void resizeJointArrays(int newSize = -1); bool isAnimatingSomething() const; @@ -145,7 +164,7 @@ protected: // used on client side bool _jointMappingCompleted; - QVector _jointMapping; + QVector _jointMapping; // domain is index into model-joints, range is index into animation-joints QString _jointMappingURL; static AnimationPointer getAnimation(const QString& url); diff --git a/libraries/networking/src/udt/PacketHeaders.cpp b/libraries/networking/src/udt/PacketHeaders.cpp index 4daf7f83b6..7a428aa0f2 100644 --- a/libraries/networking/src/udt/PacketHeaders.cpp +++ b/libraries/networking/src/udt/PacketHeaders.cpp @@ -41,7 +41,7 @@ PacketVersion versionForPacketType(PacketType packetType) { case PacketType::EntityAdd: case PacketType::EntityEdit: case PacketType::EntityData: - return VERSION_ENTITIES_REMOVED_START_AUTOMATICALLY_FROM_ANIMATION_PROPERTY_GROUP; + return VERSION_MODEL_ENTITIES_JOINTS_ON_WIRE; case PacketType::AvatarData: case PacketType::BulkAvatarData: return 17; diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index 5daa185af4..869da542e9 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -162,5 +162,6 @@ const PacketVersion VERSION_ENTITIES_PARTICLES_ADDITIVE_BLENDING = 49; const PacketVersion VERSION_ENTITIES_POLYLINE_TEXTURE = 50; const PacketVersion VERSION_ENTITIES_HAVE_PARENTS = 51; const PacketVersion VERSION_ENTITIES_REMOVED_START_AUTOMATICALLY_FROM_ANIMATION_PROPERTY_GROUP = 52; +const PacketVersion VERSION_MODEL_ENTITIES_JOINTS_ON_WIRE = 53; #endif // hifi_PacketHeaders_h diff --git a/libraries/octree/src/OctreePacketData.cpp b/libraries/octree/src/OctreePacketData.cpp index f063c60fd7..d515244f64 100644 --- a/libraries/octree/src/OctreePacketData.cpp +++ b/libraries/octree/src/OctreePacketData.cpp @@ -392,6 +392,19 @@ bool OctreePacketData::appendValue(const QVector& value) { return success; } +bool OctreePacketData::appendValue(const QVector& value) { + uint16_t qVecSize = value.size(); + bool success = appendValue(qVecSize); + if (success) { + success = append((const unsigned char*)value.constData(), qVecSize * sizeof(glm::quat)); + if (success) { + _bytesOfValues += qVecSize * sizeof(glm::quat); + _totalBytesOfValues += qVecSize * sizeof(glm::quat); + } + } + return success; +} + bool OctreePacketData::appendValue(const QVector& value) { uint16_t qVecSize = value.size(); bool success = appendValue(qVecSize); @@ -405,6 +418,19 @@ bool OctreePacketData::appendValue(const QVector& value) { return success; } +bool OctreePacketData::appendValue(const QVector& value) { + uint16_t qVecSize = value.size(); + bool success = appendValue(qVecSize); + if (success) { + success = append((const unsigned char*)value.constData(), qVecSize * sizeof(bool)); + if (success) { + _bytesOfValues += qVecSize * sizeof(bool); + _totalBytesOfValues += qVecSize * sizeof(bool); + } + } + return success; +} + bool OctreePacketData::appendValue(const glm::quat& value) { const size_t VALUES_PER_QUAT = 4; const size_t PACKED_QUAT_SIZE = sizeof(uint16_t) * VALUES_PER_QUAT; @@ -621,6 +647,15 @@ int OctreePacketData::unpackDataFromBytes(const unsigned char *dataBytes, QVecto return sizeof(uint16_t) + length * sizeof(glm::vec3); } +int OctreePacketData::unpackDataFromBytes(const unsigned char *dataBytes, QVector& result) { + uint16_t length; + memcpy(&length, dataBytes, sizeof(uint16_t)); + dataBytes += sizeof(length); + result.resize(length); + memcpy(result.data(), dataBytes, length * sizeof(glm::quat)); + return sizeof(uint16_t) + length * sizeof(glm::quat); +} + int OctreePacketData::unpackDataFromBytes(const unsigned char* dataBytes, QVector& result) { uint16_t length; memcpy(&length, dataBytes, sizeof(uint16_t)); @@ -630,7 +665,16 @@ int OctreePacketData::unpackDataFromBytes(const unsigned char* dataBytes, QVecto return sizeof(uint16_t) + length * sizeof(float); } -int OctreePacketData::unpackDataFromBytes(const unsigned char* dataBytes, QByteArray& result) { +int OctreePacketData::unpackDataFromBytes(const unsigned char* dataBytes, QVector& result) { + uint16_t length; + memcpy(&length, dataBytes, sizeof(uint16_t)); + dataBytes += sizeof(length); + result.resize(length); + memcpy(result.data(), dataBytes, length * sizeof(bool)); + return sizeof(uint16_t) + length * sizeof(bool); +} + +int OctreePacketData::unpackDataFromBytes(const unsigned char* dataBytes, QByteArray& result) { uint16_t length; memcpy(&length, dataBytes, sizeof(length)); dataBytes += sizeof(length); diff --git a/libraries/octree/src/OctreePacketData.h b/libraries/octree/src/OctreePacketData.h index 2c86d518ad..d87a456be5 100644 --- a/libraries/octree/src/OctreePacketData.h +++ b/libraries/octree/src/OctreePacketData.h @@ -165,19 +165,25 @@ public: /// appends a non-position vector to the end of the stream, may fail if new data stream is too long to fit in packet bool appendValue(const glm::vec3& value); - - //appends a QVector of vec3's to the end of the stream, may fail if new data stream is too long to fit in packet + + /// appends a QVector of vec3s to the end of the stream, may fail if new data stream is too long to fit in packet bool appendValue(const QVector& value); - - //appends a QVector of floats to the end of the stream, may fail if new data stream is too long to fit in packet + + /// appends a QVector of quats to the end of the stream, may fail if new data stream is too long to fit in packet + bool appendValue(const QVector& value); + + /// appends a QVector of floats to the end of the stream, may fail if new data stream is too long to fit in packet bool appendValue(const QVector& value); + /// appends a QVector of bools to the end of the stream, may fail if new data stream is too long to fit in packet + bool appendValue(const QVector& value); + /// appends a packed quat to the end of the stream, may fail if new data stream is too long to fit in packet bool appendValue(const glm::quat& value); /// appends a bool value to the end of the stream, may fail if new data stream is too long to fit in packet bool appendValue(bool value); - + /// appends a string value to the end of the stream, may fail if new data stream is too long to fit in packet bool appendValue(const QString& string); @@ -251,7 +257,9 @@ public: static int unpackDataFromBytes(const unsigned char* dataBytes, QUuid& result); static int unpackDataFromBytes(const unsigned char* dataBytes, xColor& result); static int unpackDataFromBytes(const unsigned char* dataBytes, QVector& result); + static int unpackDataFromBytes(const unsigned char* dataBytes, QVector& result); static int unpackDataFromBytes(const unsigned char* dataBytes, QVector& result); + static int unpackDataFromBytes(const unsigned char* dataBytes, QVector& result); static int unpackDataFromBytes(const unsigned char* dataBytes, QByteArray& result); private: diff --git a/libraries/shared/src/RegisteredMetaTypes.cpp b/libraries/shared/src/RegisteredMetaTypes.cpp index 008ac238d5..d37cf4c73f 100644 --- a/libraries/shared/src/RegisteredMetaTypes.cpp +++ b/libraries/shared/src/RegisteredMetaTypes.cpp @@ -20,6 +20,8 @@ static int vec4MetaTypeId = qRegisterMetaType(); static int vec3MetaTypeId = qRegisterMetaType(); static int qVectorVec3MetaTypeId = qRegisterMetaType>(); +static int qVectorQuatMetaTypeId = qRegisterMetaType>(); +static int qVectorBoolMetaTypeId = qRegisterMetaType>(); static int vec2MetaTypeId = qRegisterMetaType(); static int quatMetaTypeId = qRegisterMetaType(); static int xColorMetaTypeId = qRegisterMetaType(); @@ -31,6 +33,8 @@ void registerMetaTypes(QScriptEngine* engine) { qScriptRegisterMetaType(engine, vec4toScriptValue, vec4FromScriptValue); qScriptRegisterMetaType(engine, vec3toScriptValue, vec3FromScriptValue); qScriptRegisterMetaType(engine, qVectorVec3ToScriptValue, qVectorVec3FromScriptValue); + qScriptRegisterMetaType(engine, qVectorQuatToScriptValue, qVectorQuatFromScriptValue); + qScriptRegisterMetaType(engine, qVectorBoolToScriptValue, qVectorBoolFromScriptValue); qScriptRegisterMetaType(engine, qVectorFloatToScriptValue, qVectorFloatFromScriptValue); qScriptRegisterMetaType(engine, vec2toScriptValue, vec2FromScriptValue); qScriptRegisterMetaType(engine, quatToScriptValue, quatFromScriptValue); @@ -87,6 +91,42 @@ QScriptValue qVectorVec3ToScriptValue(QScriptEngine* engine, const QVectornewObject(); + if (quat.x != quat.x || quat.y != quat.y || quat.z != quat.z || quat.w != quat.w) { + // if quat contains a NaN don't try to convert it + return obj; + } + obj.setProperty("x", quat.x); + obj.setProperty("y", quat.y); + obj.setProperty("z", quat.z); + obj.setProperty("w", quat.w); + return obj; +} + +void quatFromScriptValue(const QScriptValue &object, glm::quat &quat) { + quat.x = object.property("x").toVariant().toFloat(); + quat.y = object.property("y").toVariant().toFloat(); + quat.z = object.property("z").toVariant().toFloat(); + quat.w = object.property("w").toVariant().toFloat(); +} + +QScriptValue qVectorQuatToScriptValue(QScriptEngine* engine, const QVector& vector) { + QScriptValue array = engine->newArray(); + for (int i = 0; i < vector.size(); i++) { + array.setProperty(i, quatToScriptValue(engine, vector.at(i))); + } + return array; +} + +QScriptValue qVectorBoolToScriptValue(QScriptEngine* engine, const QVector& vector) { + QScriptValue array = engine->newArray(); + for (int i = 0; i < vector.size(); i++) { + array.setProperty(i, vector.at(i)); + } + return array; +} + QVector qVectorFloatFromScriptValue(const QScriptValue& array) { if(!array.isArray()) { return QVector(); @@ -149,7 +189,7 @@ QVector qVectorVec3FromScriptValue(const QScriptValue& array){ void qVectorVec3FromScriptValue(const QScriptValue& array, QVector& vector ) { int length = array.property("length").toInteger(); - + for (int i = 0; i < length; i++) { glm::vec3 newVec3 = glm::vec3(); vec3FromScriptValue(array.property(i), newVec3); @@ -157,6 +197,46 @@ void qVectorVec3FromScriptValue(const QScriptValue& array, QVector& v } } +QVector qVectorQuatFromScriptValue(const QScriptValue& array){ + QVector newVector; + int length = array.property("length").toInteger(); + + for (int i = 0; i < length; i++) { + glm::quat newQuat = glm::quat(); + quatFromScriptValue(array.property(i), newQuat); + newVector << newQuat; + } + return newVector; +} + +void qVectorQuatFromScriptValue(const QScriptValue& array, QVector& vector ) { + int length = array.property("length").toInteger(); + + for (int i = 0; i < length; i++) { + glm::quat newQuat = glm::quat(); + quatFromScriptValue(array.property(i), newQuat); + vector << newQuat; + } +} + +QVector qVectorBoolFromScriptValue(const QScriptValue& array){ + QVector newVector; + int length = array.property("length").toInteger(); + + for (int i = 0; i < length; i++) { + newVector << array.property(i).toBool(); + } + return newVector; +} + +void qVectorBoolFromScriptValue(const QScriptValue& array, QVector& vector ) { + int length = array.property("length").toInteger(); + + for (int i = 0; i < length; i++) { + vector << array.property(i).toBool(); + } +} + QScriptValue vec2toScriptValue(QScriptEngine* engine, const glm::vec2 &vec2) { QScriptValue obj = engine->newObject(); obj.setProperty("x", vec2.x); @@ -169,22 +249,6 @@ void vec2FromScriptValue(const QScriptValue &object, glm::vec2 &vec2) { vec2.y = object.property("y").toVariant().toFloat(); } -QScriptValue quatToScriptValue(QScriptEngine* engine, const glm::quat& quat) { - QScriptValue obj = engine->newObject(); - obj.setProperty("x", quat.x); - obj.setProperty("y", quat.y); - obj.setProperty("z", quat.z); - obj.setProperty("w", quat.w); - return obj; -} - -void quatFromScriptValue(const QScriptValue &object, glm::quat& quat) { - quat.x = object.property("x").toVariant().toFloat(); - quat.y = object.property("y").toVariant().toFloat(); - quat.z = object.property("z").toVariant().toFloat(); - quat.w = object.property("w").toVariant().toFloat(); -} - QScriptValue qRectToScriptValue(QScriptEngine* engine, const QRect& rect) { QScriptValue obj = engine->newObject(); obj.setProperty("x", rect.x()); diff --git a/libraries/shared/src/RegisteredMetaTypes.h b/libraries/shared/src/RegisteredMetaTypes.h index cd1e3b0d3e..a2941803ca 100644 --- a/libraries/shared/src/RegisteredMetaTypes.h +++ b/libraries/shared/src/RegisteredMetaTypes.h @@ -61,6 +61,14 @@ QScriptValue qVectorVec3ToScriptValue(QScriptEngine* engine, const QVector& vector); QVector qVectorVec3FromScriptValue(const QScriptValue& array); +QScriptValue qVectorQuatToScriptValue(QScriptEngine* engine, const QVector& vector); +void qVectorQuatFromScriptValue(const QScriptValue& array, QVector& vector); +QVector qVectorQuatFromScriptValue(const QScriptValue& array); + +QScriptValue qVectorBoolToScriptValue(QScriptEngine* engine, const QVector& vector); +void qVectorBoolFromScriptValue(const QScriptValue& array, QVector& vector); +QVector qVectorBoolFromScriptValue(const QScriptValue& array); + QScriptValue qVectorFloatToScriptValue(QScriptEngine* engine, const QVector& vector); void qVectorFloatFromScriptValue(const QScriptValue& array, QVector& vector); QVector qVectorFloatFromScriptValue(const QScriptValue& array); From 175506bbf1d4739e02c7976e588cdc22f2f66608 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 23 Dec 2015 16:06:04 -0800 Subject: [PATCH 05/34] when a script sets joint-data on a model-entity, send an edit packet --- libraries/entities/src/EntityItemProperties.h | 7 ++-- .../entities/src/EntityScriptingInterface.cpp | 34 +++++++++++++++---- 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index f8bdfcc0dd..9b8142d4c2 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -265,10 +265,13 @@ public: void setActionDataDirty() { _actionDataChanged = true; } QList listChangedProperties(); - + bool getDimensionsInitialized() const { return _dimensionsInitialized; } void setDimensionsInitialized(bool dimensionsInitialized) { _dimensionsInitialized = dimensionsInitialized; } - + + void setJointRotationsDirty() { _jointRotationsSetChanged = true; _jointRotationsChanged = true; } + void setJointTranslationsDirty() { _jointTranslationsSetChanged = true; _jointTranslationsChanged = true; } + private: QUuid _id; bool _idSet; diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index c20db60601..9dc899e535 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -831,18 +831,40 @@ bool EntityScriptingInterface::setAbsoluteJointTranslationInObjectFrame(const QU int jointIndex, glm::vec3 translation) { if (auto entity = checkForTreeEntityAndTypeMatch(entityID, EntityTypes::Model)) { auto modelEntity = std::dynamic_pointer_cast(entity); - return modelEntity->setAbsoluteJointTranslationInObjectFrame(jointIndex, translation); - } else { - return false; + bool result = modelEntity->setAbsoluteJointTranslationInObjectFrame(jointIndex, translation); + if (result) { + EntityItemProperties properties; + _entityTree->withReadLock([&] { + properties = entity->getProperties(); + }); + + properties.setJointTranslationsDirty(); + auto now = usecTimestampNow(); + properties.setLastEdited(now); + queueEntityMessage(PacketType::EntityEdit, entityID, properties); + return true; + } } + return false; } bool EntityScriptingInterface::setAbsoluteJointRotationInObjectFrame(const QUuid& entityID, int jointIndex, glm::quat rotation) { if (auto entity = checkForTreeEntityAndTypeMatch(entityID, EntityTypes::Model)) { auto modelEntity = std::dynamic_pointer_cast(entity); - return modelEntity->setAbsoluteJointRotationInObjectFrame(jointIndex, rotation); - } else { - return false; + bool result = modelEntity->setAbsoluteJointRotationInObjectFrame(jointIndex, rotation); + if (result) { + EntityItemProperties properties; + _entityTree->withReadLock([&] { + properties = entity->getProperties(); + }); + + properties.setJointRotationsDirty(); + auto now = usecTimestampNow(); + properties.setLastEdited(now); + queueEntityMessage(PacketType::EntityEdit, entityID, properties); + return true; + } } + return false; } From 3f73f83cf1322e05c1f570cfc57241660607c045 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Sun, 27 Dec 2015 11:23:54 -0800 Subject: [PATCH 06/34] add doppelganger --- .../example/avatarcontrol/doppelganger.js | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 examples/example/avatarcontrol/doppelganger.js diff --git a/examples/example/avatarcontrol/doppelganger.js b/examples/example/avatarcontrol/doppelganger.js new file mode 100644 index 0000000000..6fb7026ea1 --- /dev/null +++ b/examples/example/avatarcontrol/doppelganger.js @@ -0,0 +1,84 @@ +var TEST_MODEL_URL = ''; + +var doppelgangers = []; + +function Doppelganger(avatar) { + this.initialProperties = { + name: 'Hifi-Doppelganger', + type: 'Model', + modelURL: TEST_MODEL_URL, + dimensions: getAvatarDimensions(avatar), + position: putDoppelgangerAcrossFromAvatar(this, avatar), + rotation: rotateDoppelgangerTowardAvatar(this, avatar), + }; + + this.id = createDoppelgangerEntity(this); + this.avatar = avatar; + return this; +} + +function getJointData() { + return jointData; +} + +function setJointData(doppelganger, jointData) { + return true; +} + +function mirrorJointData() { + return mirroredJointData; +} + +function createDoppelganger(avatar) { + return new Doppelganger(avatar); +} + +function createDoppelgangerEntity(doppelganger) { + return Entities.addEntitiy(doppelganger.initialProperties); +} + +function putDoppelgangerAcrossFromAvatar(doppelganger, avatar) { + return position; +} + +function getAvatarDimensions(avatar) { + return dimensions; +} + +function rotateDoppelgangerTowardAvatar(doppelganger, avatar) { + return rotation; +} + +function connectDoppelgangerUpdates() { + Script.update.connect(updateDoppelganger); +} + +function disconnectDoppelgangerUpdates() { + Script.update.disconnect(updateDoppelganger); +} + +function updateDoppelganger() { + doppelgangers.forEach(function(doppelganger) { + var joints = getJointData(doppelganger.avatar.id); + var mirroredJoints = mirrorJointData(joints); + setJointData(doppelganger, mirroredJoints); + }); + +} + +function makeDoppelgangerForMyAvatar() { + var doppelganger = createDoppelganger(MyAvatar); + doppelgangers.push(doppelganger); + connectDoppelgangerUpdates(); +} + +function cleanup() { + disconnectDoppelgangerUpdates(); + + doppelgangers.forEach(function(doppelganger) { + Entities.deleteEntity(doppelganger); + }); + +} + +Script.scriptEnding.connect(cleanup); \ No newline at end of file From 5e6e2bd11c60b88b69ed7f531dae857e930fee63 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Mon, 28 Dec 2015 13:06:43 -0800 Subject: [PATCH 07/34] work --- .../example/avatarcontrol/doppelganger.js | 41 ++++++++++++++----- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/examples/example/avatarcontrol/doppelganger.js b/examples/example/avatarcontrol/doppelganger.js index 6fb7026ea1..11b29cbb2a 100644 --- a/examples/example/avatarcontrol/doppelganger.js +++ b/examples/example/avatarcontrol/doppelganger.js @@ -1,4 +1,4 @@ -var TEST_MODEL_URL = ''; +var TEST_MODEL_URL = 'http://hifi-content.s3.amazonaws.com/james/avatars/Jack_Skellington/Jack_Skellington.fbx'; var doppelgangers = []; @@ -7,7 +7,7 @@ function Doppelganger(avatar) { name: 'Hifi-Doppelganger', type: 'Model', modelURL: TEST_MODEL_URL, - dimensions: getAvatarDimensions(avatar), + // dimensions: getAvatarDimensions(avatar), position: putDoppelgangerAcrossFromAvatar(this, avatar), rotation: rotateDoppelgangerTowardAvatar(this, avatar), }; @@ -17,8 +17,17 @@ function Doppelganger(avatar) { return this; } -function getJointData() { - return jointData; +function getJointData(avatar) { + var allJointData; + var jointNames = MyAvatar.jointNames; + + jointNames.forEach(function(joint) { + print('getting info for joint:' + joint); + var jointData = MyAvatar.getJointPosition(joint); + print('joint data:'+JSON.stringify(jointData)); + }); + + return allJointData; } function setJointData(doppelganger, jointData) { @@ -34,11 +43,13 @@ function createDoppelganger(avatar) { } function createDoppelgangerEntity(doppelganger) { - return Entities.addEntitiy(doppelganger.initialProperties); + return Entities.addEntity(doppelganger.initialProperties); } function putDoppelgangerAcrossFromAvatar(doppelganger, avatar) { - return position; + var avatarRot = Quat.fromPitchYawRollDegrees(0, avatar.bodyYaw, 0.0); + var basePosition = Vec3.sum(avatar.position, Vec3.multiply(1.5, Quat.getFront(avatarRot))); + return basePosition; } function getAvatarDimensions(avatar) { @@ -46,7 +57,9 @@ function getAvatarDimensions(avatar) { } function rotateDoppelgangerTowardAvatar(doppelganger, avatar) { - return rotation; + var avatarRot = Quat.fromPitchYawRollDegrees(0, avatar.bodyYaw, 0.0); + avatarRot = Vec3.multiply(-1,avatarRot); + return avatarRot; } function connectDoppelgangerUpdates() { @@ -59,7 +72,7 @@ function disconnectDoppelgangerUpdates() { function updateDoppelganger() { doppelgangers.forEach(function(doppelganger) { - var joints = getJointData(doppelganger.avatar.id); + var joints = getJointData(MyAvatar); var mirroredJoints = mirrorJointData(joints); setJointData(doppelganger, mirroredJoints); }); @@ -69,9 +82,12 @@ function updateDoppelganger() { function makeDoppelgangerForMyAvatar() { var doppelganger = createDoppelganger(MyAvatar); doppelgangers.push(doppelganger); - connectDoppelgangerUpdates(); + // connectDoppelgangerUpdates(); } + +makeDoppelgangerForMyAvatar(); + function cleanup() { disconnectDoppelgangerUpdates(); @@ -81,4 +97,9 @@ function cleanup() { } -Script.scriptEnding.connect(cleanup); \ No newline at end of file +Script.scriptEnding.connect(cleanup); + +// APPEND_ENTITY_PROPERTY(PROP_JOINT_ROTATIONS_SET, getJointRotationsSet()); +// APPEND_ENTITY_PROPERTY(PROP_JOINT_ROTATIONS, getJointRotations()); +// APPEND_ENTITY_PROPERTY(PROP_JOINT_TRANSLATIONS_SET, getJointTranslationsSet()); +// APPEND_ENTITY_PROPERTY(PROP_JOINT_TRANSLATIONS, getJointTranslations()); \ No newline at end of file From d8ef19a01960d8b114a92cc8d1d5a667ed0e7573 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Mon, 28 Dec 2015 18:32:49 -0800 Subject: [PATCH 08/34] working!! --- .../example/avatarcontrol/doppelganger.js | 60 ++++++++++++++----- 1 file changed, 45 insertions(+), 15 deletions(-) diff --git a/examples/example/avatarcontrol/doppelganger.js b/examples/example/avatarcontrol/doppelganger.js index 11b29cbb2a..f8a1103772 100644 --- a/examples/example/avatarcontrol/doppelganger.js +++ b/examples/example/avatarcontrol/doppelganger.js @@ -1,3 +1,15 @@ +// +// doppelganger.js +// +// Created by James B. Pollack @imgntn on 12/28/2015 +// Copyright 2015 High Fidelity, Inc. +// +// This script shows how to hook up a model entity to your avatar to act as a doppelganger. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + var TEST_MODEL_URL = 'http://hifi-content.s3.amazonaws.com/james/avatars/Jack_Skellington/Jack_Skellington.fbx'; var doppelgangers = []; @@ -7,7 +19,7 @@ function Doppelganger(avatar) { name: 'Hifi-Doppelganger', type: 'Model', modelURL: TEST_MODEL_URL, - // dimensions: getAvatarDimensions(avatar), + // dimensions: getAvatarDimensions(avatar), position: putDoppelgangerAcrossFromAvatar(this, avatar), rotation: rotateDoppelgangerTowardAvatar(this, avatar), }; @@ -18,19 +30,39 @@ function Doppelganger(avatar) { } function getJointData(avatar) { - var allJointData; + var allJointData = []; var jointNames = MyAvatar.jointNames; - - jointNames.forEach(function(joint) { - print('getting info for joint:' + joint); - var jointData = MyAvatar.getJointPosition(joint); - print('joint data:'+JSON.stringify(jointData)); + jointNames.forEach(function(joint, index) { + var translation = MyAvatar.getJointTranslation(index); + var rotation = MyAvatar.getJointRotation(index) + allJointData.push({ + joint: joint, + index: index, + translation: translation, + rotation: rotation + }) }); return allJointData; } -function setJointData(doppelganger, jointData) { +function setJointData(doppelganger, allJointData) { + var jointRotationsSet = []; + var jointTranslationsSet = []; + var jointRotations = []; + var jointTranslations = []; + + allJointData.forEach(function(jointData, index) { + jointRotationsSet[index] = true; + jointTranslationsSet[index] = true; + jointRotations.push(jointData.rotation); + jointTranslations.push(jointData.translation); + + Entities.setAbsoluteJointTranslationInObjectFrame(doppelganger.id, index, jointData.translation); + Entities.setAbsoluteJointRotationInObjectFrame(doppelganger.id, index, jointData.rotation); + + }); + return true; } @@ -57,8 +89,8 @@ function getAvatarDimensions(avatar) { } function rotateDoppelgangerTowardAvatar(doppelganger, avatar) { - var avatarRot = Quat.fromPitchYawRollDegrees(0, avatar.bodyYaw, 0.0); - avatarRot = Vec3.multiply(-1,avatarRot); + var avatarRot = Quat.fromPitchYawRollDegrees(0, avatar.bodyYaw, 0.0); + avatarRot = Vec3.multiply(-1, avatarRot); return avatarRot; } @@ -73,8 +105,8 @@ function disconnectDoppelgangerUpdates() { function updateDoppelganger() { doppelgangers.forEach(function(doppelganger) { var joints = getJointData(MyAvatar); - var mirroredJoints = mirrorJointData(joints); - setJointData(doppelganger, mirroredJoints); + //var mirroredJoints = mirrorJointData(joints); + setJointData(doppelganger, joints); }); } @@ -82,10 +114,9 @@ function updateDoppelganger() { function makeDoppelgangerForMyAvatar() { var doppelganger = createDoppelganger(MyAvatar); doppelgangers.push(doppelganger); - // connectDoppelgangerUpdates(); + connectDoppelgangerUpdates(); } - makeDoppelgangerForMyAvatar(); function cleanup() { @@ -94,7 +125,6 @@ function cleanup() { doppelgangers.forEach(function(doppelganger) { Entities.deleteEntity(doppelganger); }); - } Script.scriptEnding.connect(cleanup); From bf296a36edea4f3cf4775d6974ad059634a5ade3 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Mon, 28 Dec 2015 18:38:09 -0800 Subject: [PATCH 09/34] cleanup change model --- examples/example/avatarcontrol/doppelganger.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/example/avatarcontrol/doppelganger.js b/examples/example/avatarcontrol/doppelganger.js index f8a1103772..ed4079a211 100644 --- a/examples/example/avatarcontrol/doppelganger.js +++ b/examples/example/avatarcontrol/doppelganger.js @@ -9,8 +9,9 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +// To-Do: mirror joints, rotate avatar fully, automatically get avatar fbx, make sure dimensions for avatar are right when u bring it in -var TEST_MODEL_URL = 'http://hifi-content.s3.amazonaws.com/james/avatars/Jack_Skellington/Jack_Skellington.fbx'; +var TEST_MODEL_URL = 'https://s3.amazonaws.com/hifi-public/ozan/avatars/albert/albert/albert.fbx'; var doppelgangers = []; From a2d21ed5cbf78cb2d202673b78ac3245a684dc79 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Mon, 28 Dec 2015 21:42:54 -0800 Subject: [PATCH 10/34] Update doppelganger.js delete correct id --- examples/example/avatarcontrol/doppelganger.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/example/avatarcontrol/doppelganger.js b/examples/example/avatarcontrol/doppelganger.js index ed4079a211..f5878f0763 100644 --- a/examples/example/avatarcontrol/doppelganger.js +++ b/examples/example/avatarcontrol/doppelganger.js @@ -124,7 +124,7 @@ function cleanup() { disconnectDoppelgangerUpdates(); doppelgangers.forEach(function(doppelganger) { - Entities.deleteEntity(doppelganger); + Entities.deleteEntity(doppelganger.id); }); } @@ -133,4 +133,4 @@ Script.scriptEnding.connect(cleanup); // APPEND_ENTITY_PROPERTY(PROP_JOINT_ROTATIONS_SET, getJointRotationsSet()); // APPEND_ENTITY_PROPERTY(PROP_JOINT_ROTATIONS, getJointRotations()); // APPEND_ENTITY_PROPERTY(PROP_JOINT_TRANSLATIONS_SET, getJointTranslationsSet()); -// APPEND_ENTITY_PROPERTY(PROP_JOINT_TRANSLATIONS, getJointTranslations()); \ No newline at end of file +// APPEND_ENTITY_PROPERTY(PROP_JOINT_TRANSLATIONS, getJointTranslations()); From 4e312dd8f801ec3184078110ff762d2b06719f61 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 30 Dec 2015 12:45:19 -0800 Subject: [PATCH 11/34] undo temporary hack --- .../entities-renderer/src/RenderableModelEntityItem.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index c77a274692..f12e00fa1a 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -299,10 +299,7 @@ bool RenderableModelEntityItem::getAnimationFrame() { _absoluteJointTranslationsInObjectFrameSet[j] = true; _absoluteJointTranslationsInObjectFrameDirty[j] = true; - // XXX Tony will fix this better in some other PR - // _absoluteJointRotationsInObjectFrame[j] = glmExtractRotation(finalMat); - _absoluteJointRotationsInObjectFrame[j] = fbxJoints[index].preRotation * rotation; - // XXX + _absoluteJointRotationsInObjectFrame[j] = glmExtractRotation(finalMat); _absoluteJointRotationsInObjectFrameSet[j] = true; _absoluteJointRotationsInObjectFrameDirty[j] = true; From 9e49fcf0a4041e74b3a12c8d0022fdc32dd86b77 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 4 Jan 2016 11:29:01 -0800 Subject: [PATCH 12/34] include model-joints in debugging output --- libraries/entities/src/EntityItemProperties.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index ef373bc206..a540bc1476 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -1811,6 +1811,18 @@ QList EntityItemProperties::listChangedProperties() { if (parentJointIndexChanged()) { out += "parentJointIndex"; } + if (jointRotationsSetChanged()) { + out += "jointRotationsSet"; + } + if (jointRotationsChanged()) { + out += "jointRotations"; + } + if (jointTranslationsSetChanged()) { + out += "jointTranslationsSet"; + } + if (jointTranslationsChanged()) { + out += "jointTranslations"; + } getAnimation().listChangedProperties(out); getKeyLight().listChangedProperties(out); From 768934ae11b9e0373d559f06f733a45f25b308a7 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 4 Jan 2016 11:29:15 -0800 Subject: [PATCH 13/34] update entity timestamps when sending joint information --- libraries/entities/src/EntityScriptingInterface.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 8df5d86ddd..10f74ef5cc 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -832,16 +832,18 @@ glm::quat EntityScriptingInterface::getAbsoluteJointRotationInObjectFrame(const bool EntityScriptingInterface::setAbsoluteJointTranslationInObjectFrame(const QUuid& entityID, int jointIndex, glm::vec3 translation) { if (auto entity = checkForTreeEntityAndTypeMatch(entityID, EntityTypes::Model)) { + auto now = usecTimestampNow(); auto modelEntity = std::dynamic_pointer_cast(entity); bool result = modelEntity->setAbsoluteJointTranslationInObjectFrame(jointIndex, translation); if (result) { EntityItemProperties properties; _entityTree->withReadLock([&] { properties = entity->getProperties(); + entity->setLastEdited(now); + entity->setLastBroadcast(now); }); properties.setJointTranslationsDirty(); - auto now = usecTimestampNow(); properties.setLastEdited(now); queueEntityMessage(PacketType::EntityEdit, entityID, properties); return true; @@ -853,16 +855,18 @@ bool EntityScriptingInterface::setAbsoluteJointTranslationInObjectFrame(const QU bool EntityScriptingInterface::setAbsoluteJointRotationInObjectFrame(const QUuid& entityID, int jointIndex, glm::quat rotation) { if (auto entity = checkForTreeEntityAndTypeMatch(entityID, EntityTypes::Model)) { + auto now = usecTimestampNow(); auto modelEntity = std::dynamic_pointer_cast(entity); bool result = modelEntity->setAbsoluteJointRotationInObjectFrame(jointIndex, rotation); if (result) { EntityItemProperties properties; _entityTree->withReadLock([&] { properties = entity->getProperties(); + entity->setLastEdited(now); + entity->setLastBroadcast(now); }); properties.setJointRotationsDirty(); - auto now = usecTimestampNow(); properties.setLastEdited(now); queueEntityMessage(PacketType::EntityEdit, entityID, properties); return true; From ef7438958bcfb9d7832d07599186369782b5fdf6 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 4 Jan 2016 12:30:55 -0800 Subject: [PATCH 14/34] better debugging prints for model joints --- libraries/entities/src/EntityTree.cpp | 29 +++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index f0a03623c2..51c53a4e93 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -757,6 +757,35 @@ void EntityTree::fixupTerseEditLogging(EntityItemProperties& properties, QList= 0) { + auto value = properties.getJointRotationsSet().size(); + changedProperties[index] = QString("jointRotationsSet:") + QString::number((int)value); + } + } + if (properties.jointRotationsChanged()) { + int index = changedProperties.indexOf("jointRotations"); + if (index >= 0) { + auto value = properties.getJointRotations().size(); + changedProperties[index] = QString("jointRotations:") + QString::number((int)value); + } + } + if (properties.jointTranslationsSetChanged()) { + int index = changedProperties.indexOf("jointTranslationsSet"); + if (index >= 0) { + auto value = properties.getJointTranslationsSet().size(); + changedProperties[index] = QString("jointTranslationsSet:") + QString::number((int)value); + } + } + if (properties.jointTranslationsChanged()) { + int index = changedProperties.indexOf("jointTranslations"); + if (index >= 0) { + auto value = properties.getJointTranslations().size(); + changedProperties[index] = QString("jointTranslations:") + QString::number((int)value); + } + } } int EntityTree::processEditPacketData(ReceivedMessage& message, const unsigned char* editData, int maxLength, From c9ed36f9a6513d204687761f376ce991dad3a57a Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 4 Jan 2016 12:31:45 -0800 Subject: [PATCH 15/34] include joint data in script properties --- libraries/entities/src/ModelEntityItem.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp index 4f8ba1cc6c..709cd67ef5 100644 --- a/libraries/entities/src/ModelEntityItem.cpp +++ b/libraries/entities/src/ModelEntityItem.cpp @@ -50,6 +50,11 @@ EntityItemProperties ModelEntityItem::getProperties(EntityPropertyFlags desiredP COPY_ENTITY_PROPERTY_TO_PROPERTIES(glowLevel, getGlowLevel); COPY_ENTITY_PROPERTY_TO_PROPERTIES(textures, getTextures); COPY_ENTITY_PROPERTY_TO_PROPERTIES(shapeType, getShapeType); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(jointRotationsSet, getJointRotationsSet); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(jointRotations, getJointRotations); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(jointTranslationsSet, getJointTranslationsSet); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(jointTranslations, getJointTranslations); + _animationProperties.getProperties(properties); return properties; } @@ -63,6 +68,10 @@ bool ModelEntityItem::setProperties(const EntityItemProperties& properties) { SET_ENTITY_PROPERTY_FROM_PROPERTIES(compoundShapeURL, setCompoundShapeURL); SET_ENTITY_PROPERTY_FROM_PROPERTIES(textures, setTextures); SET_ENTITY_PROPERTY_FROM_PROPERTIES(shapeType, updateShapeType); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(jointRotationsSet, setJointRotationsSet); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(jointRotations, setJointRotations); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(jointTranslationsSet, setJointTranslationsSet); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(jointTranslations, setJointTranslations); bool somethingChangedInAnimations = _animationProperties.setProperties(properties); From 2147b0d78ee68cbfee7829cecf3d5de412f83779 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 4 Jan 2016 12:31:58 -0800 Subject: [PATCH 16/34] fix locking --- libraries/entities/src/EntityScriptingInterface.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 10f74ef5cc..4904d7ae51 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -837,9 +837,8 @@ bool EntityScriptingInterface::setAbsoluteJointTranslationInObjectFrame(const QU bool result = modelEntity->setAbsoluteJointTranslationInObjectFrame(jointIndex, translation); if (result) { EntityItemProperties properties; - _entityTree->withReadLock([&] { + _entityTree->withWriteLock([&] { properties = entity->getProperties(); - entity->setLastEdited(now); entity->setLastBroadcast(now); }); @@ -860,9 +859,8 @@ bool EntityScriptingInterface::setAbsoluteJointRotationInObjectFrame(const QUuid bool result = modelEntity->setAbsoluteJointRotationInObjectFrame(jointIndex, rotation); if (result) { EntityItemProperties properties; - _entityTree->withReadLock([&] { + _entityTree->withWriteLock([&] { properties = entity->getProperties(); - entity->setLastEdited(now); entity->setLastBroadcast(now); }); From 7f2e0cd1032eb5638f43399af13933c4c5b7e1c7 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 4 Jan 2016 14:13:08 -0800 Subject: [PATCH 17/34] expose a way to set translation and rotation of all model joints at once --- .../src/RenderableModelEntityItem.cpp | 10 +++--- .../src/RenderableModelEntityItem.h | 4 +-- libraries/entities/src/EntityItem.h | 4 +-- .../entities/src/EntityScriptingInterface.cpp | 31 +++++++++++++++++++ .../entities/src/EntityScriptingInterface.h | 3 ++ libraries/shared/src/SpatiallyNestable.h | 4 +-- 6 files changed, 46 insertions(+), 10 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 45350893fb..a5dbdb463c 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -709,11 +709,12 @@ glm::vec3 RenderableModelEntityItem::getAbsoluteJointTranslationInObjectFrame(in return glm::vec3(0.0f); } -bool RenderableModelEntityItem::setAbsoluteJointRotationInObjectFrame(int index, glm::quat& rotation) { +bool RenderableModelEntityItem::setAbsoluteJointRotationInObjectFrame(int index, const glm::quat& rotation) { bool result = false; _jointDataLock.withWriteLock([&] { resizeJointArrays(); - if (index >= 0 && index < _absoluteJointRotationsInObjectFrame.size()) { + if (index >= 0 && index < _absoluteJointRotationsInObjectFrame.size() && + _absoluteJointRotationsInObjectFrame[index] != rotation) { _absoluteJointRotationsInObjectFrame[index] = rotation; _absoluteJointRotationsInObjectFrameSet[index] = true; _absoluteJointRotationsInObjectFrameDirty[index] = true; @@ -723,11 +724,12 @@ bool RenderableModelEntityItem::setAbsoluteJointRotationInObjectFrame(int index, return result; } -bool RenderableModelEntityItem::setAbsoluteJointTranslationInObjectFrame(int index, glm::vec3& translation) { +bool RenderableModelEntityItem::setAbsoluteJointTranslationInObjectFrame(int index, const glm::vec3& translation) { bool result = false; _jointDataLock.withWriteLock([&] { resizeJointArrays(); - if (index >= 0 && index < _absoluteJointTranslationsInObjectFrame.size()) { + if (index >= 0 && index < _absoluteJointTranslationsInObjectFrame.size() && + _absoluteJointTranslationsInObjectFrame[index] != translation) { _absoluteJointTranslationsInObjectFrame[index] = translation; _absoluteJointTranslationsInObjectFrameSet[index] = true; _absoluteJointTranslationsInObjectFrameDirty[index] = true; diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index afb26d632d..eb7958ed47 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -71,8 +71,8 @@ public: // these are in the frame of this object (model space) virtual glm::quat getAbsoluteJointRotationInObjectFrame(int index) const override; virtual glm::vec3 getAbsoluteJointTranslationInObjectFrame(int index) const override; - virtual bool setAbsoluteJointRotationInObjectFrame(int index, glm::quat& rotation) override; - virtual bool setAbsoluteJointTranslationInObjectFrame(int index, glm::vec3& translation) override; + virtual bool setAbsoluteJointRotationInObjectFrame(int index, const glm::quat& rotation) override; + virtual bool setAbsoluteJointTranslationInObjectFrame(int index, const glm::vec3& translation) override; virtual void loader() override; virtual void locationChanged() override; diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 841f68ddc1..00780501fa 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -381,8 +381,8 @@ public: // these are in the frame of this object virtual glm::quat getAbsoluteJointRotationInObjectFrame(int index) const override { return glm::quat(); } virtual glm::vec3 getAbsoluteJointTranslationInObjectFrame(int index) const override { return glm::vec3(0.0f); } - virtual bool setAbsoluteJointRotationInObjectFrame(int index, glm::quat& rotation) override { return false; } - virtual bool setAbsoluteJointTranslationInObjectFrame(int index, glm::vec3& translation) override { return false; } + virtual bool setAbsoluteJointRotationInObjectFrame(int index, const glm::quat& rotation) override { return false; } + virtual bool setAbsoluteJointTranslationInObjectFrame(int index, const glm::vec3& translation) override { return false; } virtual void loader() {} // called indirectly when urls for geometry are updated diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 4904d7ae51..ac5a9b754c 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -872,3 +872,34 @@ bool EntityScriptingInterface::setAbsoluteJointRotationInObjectFrame(const QUuid } return false; } + + +bool EntityScriptingInterface::setAbsoluteJointsDataInObjectFrame(const QUuid& entityID, + const QVector& rotations, + const QVector& translations) { + if (auto entity = checkForTreeEntityAndTypeMatch(entityID, EntityTypes::Model)) { + auto now = usecTimestampNow(); + auto modelEntity = std::dynamic_pointer_cast(entity); + + int count = glm::max(rotations.size(), translations.size()); + bool result = false; + for (int index = 0; index < count; index++) { + result |= modelEntity->setAbsoluteJointRotationInObjectFrame(index, rotations[index]); + result |= modelEntity->setAbsoluteJointTranslationInObjectFrame(index, translations[index]); + } + if (result) { + EntityItemProperties properties; + _entityTree->withWriteLock([&] { + properties = entity->getProperties(); + entity->setLastBroadcast(now); + }); + + properties.setJointRotationsDirty(); + properties.setJointTranslationsDirty(); + properties.setLastEdited(now); + queueEntityMessage(PacketType::EntityEdit, entityID, properties); + return true; + } + } + return false; +} diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index 4adbedc5bd..f0751d74b6 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -153,6 +153,9 @@ public slots: Q_INVOKABLE glm::quat getAbsoluteJointRotationInObjectFrame(const QUuid& entityID, int jointIndex); Q_INVOKABLE bool setAbsoluteJointTranslationInObjectFrame(const QUuid& entityID, int jointIndex, glm::vec3 translation); Q_INVOKABLE bool setAbsoluteJointRotationInObjectFrame(const QUuid& entityID, int jointIndex, glm::quat rotation); + Q_INVOKABLE bool setAbsoluteJointsDataInObjectFrame(const QUuid& entityID, + const QVector& rotations, + const QVector& translations); signals: void collisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, const Collision& collision); diff --git a/libraries/shared/src/SpatiallyNestable.h b/libraries/shared/src/SpatiallyNestable.h index f6a9678d34..a858fa2e97 100644 --- a/libraries/shared/src/SpatiallyNestable.h +++ b/libraries/shared/src/SpatiallyNestable.h @@ -91,8 +91,8 @@ public: virtual const Transform getAbsoluteJointTransformInObjectFrame(int jointIndex) const; virtual glm::quat getAbsoluteJointRotationInObjectFrame(int index) const { assert(false); return glm::quat(); } virtual glm::vec3 getAbsoluteJointTranslationInObjectFrame(int index) const { assert(false); return glm::vec3(); } - virtual bool setAbsoluteJointRotationInObjectFrame(int index, glm::quat& rotation) { assert(false); return false; } - virtual bool setAbsoluteJointTranslationInObjectFrame(int index, glm::vec3& translation) { assert(false); return false; } + virtual bool setAbsoluteJointRotationInObjectFrame(int index, const glm::quat& rotation) { assert(false); return false; } + virtual bool setAbsoluteJointTranslationInObjectFrame(int index, const glm::vec3& translation) { assert(false); return false; } SpatiallyNestablePointer getThisPointer() const; From 9a979f4abfb618e7b531a2d915bfe89c7359e965 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 4 Jan 2016 14:18:24 -0800 Subject: [PATCH 18/34] update doppelganger script --- .../example/avatarcontrol/doppelganger.js | 20 ++----------------- 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/examples/example/avatarcontrol/doppelganger.js b/examples/example/avatarcontrol/doppelganger.js index f5878f0763..f918dd85e9 100644 --- a/examples/example/avatarcontrol/doppelganger.js +++ b/examples/example/avatarcontrol/doppelganger.js @@ -48,20 +48,9 @@ function getJointData(avatar) { } function setJointData(doppelganger, allJointData) { - var jointRotationsSet = []; - var jointTranslationsSet = []; - var jointRotations = []; - var jointTranslations = []; - allJointData.forEach(function(jointData, index) { - jointRotationsSet[index] = true; - jointTranslationsSet[index] = true; - jointRotations.push(jointData.rotation); - jointTranslations.push(jointData.translation); - Entities.setAbsoluteJointTranslationInObjectFrame(doppelganger.id, index, jointData.translation); Entities.setAbsoluteJointRotationInObjectFrame(doppelganger.id, index, jointData.rotation); - }); return true; @@ -96,7 +85,8 @@ function rotateDoppelgangerTowardAvatar(doppelganger, avatar) { } function connectDoppelgangerUpdates() { - Script.update.connect(updateDoppelganger); + // Script.update.connect(updateDoppelganger); + Script.setInterval(updateDoppelganger, 500); } function disconnectDoppelgangerUpdates() { @@ -109,7 +99,6 @@ function updateDoppelganger() { //var mirroredJoints = mirrorJointData(joints); setJointData(doppelganger, joints); }); - } function makeDoppelgangerForMyAvatar() { @@ -129,8 +118,3 @@ function cleanup() { } Script.scriptEnding.connect(cleanup); - -// APPEND_ENTITY_PROPERTY(PROP_JOINT_ROTATIONS_SET, getJointRotationsSet()); -// APPEND_ENTITY_PROPERTY(PROP_JOINT_ROTATIONS, getJointRotations()); -// APPEND_ENTITY_PROPERTY(PROP_JOINT_TRANSLATIONS_SET, getJointTranslationsSet()); -// APPEND_ENTITY_PROPERTY(PROP_JOINT_TRANSLATIONS, getJointTranslations()); From 6c8eb90ee03cafc9596ec34fcfda07ad71f76507 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 4 Jan 2016 14:42:37 -0800 Subject: [PATCH 19/34] debugging --- .../entities-renderer/src/RenderableModelEntityItem.cpp | 8 ++++---- libraries/entities/src/EntityScriptingInterface.cpp | 1 + 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index a5dbdb463c..5e0682bd93 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -713,8 +713,8 @@ bool RenderableModelEntityItem::setAbsoluteJointRotationInObjectFrame(int index, bool result = false; _jointDataLock.withWriteLock([&] { resizeJointArrays(); - if (index >= 0 && index < _absoluteJointRotationsInObjectFrame.size() && - _absoluteJointRotationsInObjectFrame[index] != rotation) { + if (index >= 0 && index < _absoluteJointRotationsInObjectFrame.size() /* && + _absoluteJointRotationsInObjectFrame[index] != rotation*/) { _absoluteJointRotationsInObjectFrame[index] = rotation; _absoluteJointRotationsInObjectFrameSet[index] = true; _absoluteJointRotationsInObjectFrameDirty[index] = true; @@ -728,8 +728,8 @@ bool RenderableModelEntityItem::setAbsoluteJointTranslationInObjectFrame(int ind bool result = false; _jointDataLock.withWriteLock([&] { resizeJointArrays(); - if (index >= 0 && index < _absoluteJointTranslationsInObjectFrame.size() && - _absoluteJointTranslationsInObjectFrame[index] != translation) { + if (index >= 0 && index < _absoluteJointTranslationsInObjectFrame.size() /* && + _absoluteJointTranslationsInObjectFrame[index] != translation*/) { _absoluteJointTranslationsInObjectFrame[index] = translation; _absoluteJointTranslationsInObjectFrameSet[index] = true; _absoluteJointTranslationsInObjectFrameDirty[index] = true; diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index ac5a9b754c..f759afe288 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -891,6 +891,7 @@ bool EntityScriptingInterface::setAbsoluteJointsDataInObjectFrame(const QUuid& e EntityItemProperties properties; _entityTree->withWriteLock([&] { properties = entity->getProperties(); + entity->setLastEdited(now); entity->setLastBroadcast(now); }); From 9a708f2e7421127464d056395a8a34f4310e8cb8 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 4 Jan 2016 14:48:49 -0800 Subject: [PATCH 20/34] try splitting edit into 2 packets --- .../entities/src/EntityScriptingInterface.cpp | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index f759afe288..94c68bfe78 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -885,7 +885,6 @@ bool EntityScriptingInterface::setAbsoluteJointsDataInObjectFrame(const QUuid& e bool result = false; for (int index = 0; index < count; index++) { result |= modelEntity->setAbsoluteJointRotationInObjectFrame(index, rotations[index]); - result |= modelEntity->setAbsoluteJointTranslationInObjectFrame(index, translations[index]); } if (result) { EntityItemProperties properties; @@ -896,6 +895,23 @@ bool EntityScriptingInterface::setAbsoluteJointsDataInObjectFrame(const QUuid& e }); properties.setJointRotationsDirty(); + properties.setLastEdited(now); + queueEntityMessage(PacketType::EntityEdit, entityID, properties); + return true; + } + + result = false; + for (int index = 0; index < count; index++) { + result |= modelEntity->setAbsoluteJointTranslationInObjectFrame(index, translations[index]); + } + if (result) { + EntityItemProperties properties; + _entityTree->withWriteLock([&] { + properties = entity->getProperties(); + entity->setLastEdited(now); + entity->setLastBroadcast(now); + }); + properties.setJointTranslationsDirty(); properties.setLastEdited(now); queueEntityMessage(PacketType::EntityEdit, entityID, properties); From cd92a9fa1ad1c00620a76123f49b3c5201ac22d1 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 4 Jan 2016 14:51:43 -0800 Subject: [PATCH 21/34] adjust timestamps --- libraries/entities/src/EntityScriptingInterface.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 94c68bfe78..7837e1c59d 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -895,7 +895,7 @@ bool EntityScriptingInterface::setAbsoluteJointsDataInObjectFrame(const QUuid& e }); properties.setJointRotationsDirty(); - properties.setLastEdited(now); + // properties.setLastEdited(now); queueEntityMessage(PacketType::EntityEdit, entityID, properties); return true; } @@ -904,11 +904,12 @@ bool EntityScriptingInterface::setAbsoluteJointsDataInObjectFrame(const QUuid& e for (int index = 0; index < count; index++) { result |= modelEntity->setAbsoluteJointTranslationInObjectFrame(index, translations[index]); } + now = usecTimestampNow(); if (result) { EntityItemProperties properties; _entityTree->withWriteLock([&] { properties = entity->getProperties(); - entity->setLastEdited(now); + // entity->setLastEdited(now); entity->setLastBroadcast(now); }); From ef8673610fdddaa28dda7de75a1f4a23db648c04 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 4 Jan 2016 14:58:13 -0800 Subject: [PATCH 22/34] debugging --- .../entities-renderer/src/RenderableModelEntityItem.cpp | 8 ++++---- libraries/entities/src/EntityScriptingInterface.cpp | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 5e0682bd93..a5dbdb463c 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -713,8 +713,8 @@ bool RenderableModelEntityItem::setAbsoluteJointRotationInObjectFrame(int index, bool result = false; _jointDataLock.withWriteLock([&] { resizeJointArrays(); - if (index >= 0 && index < _absoluteJointRotationsInObjectFrame.size() /* && - _absoluteJointRotationsInObjectFrame[index] != rotation*/) { + if (index >= 0 && index < _absoluteJointRotationsInObjectFrame.size() && + _absoluteJointRotationsInObjectFrame[index] != rotation) { _absoluteJointRotationsInObjectFrame[index] = rotation; _absoluteJointRotationsInObjectFrameSet[index] = true; _absoluteJointRotationsInObjectFrameDirty[index] = true; @@ -728,8 +728,8 @@ bool RenderableModelEntityItem::setAbsoluteJointTranslationInObjectFrame(int ind bool result = false; _jointDataLock.withWriteLock([&] { resizeJointArrays(); - if (index >= 0 && index < _absoluteJointTranslationsInObjectFrame.size() /* && - _absoluteJointTranslationsInObjectFrame[index] != translation*/) { + if (index >= 0 && index < _absoluteJointTranslationsInObjectFrame.size() && + _absoluteJointTranslationsInObjectFrame[index] != translation) { _absoluteJointTranslationsInObjectFrame[index] = translation; _absoluteJointTranslationsInObjectFrameSet[index] = true; _absoluteJointTranslationsInObjectFrameDirty[index] = true; diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 7837e1c59d..26e0eb3ff5 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -908,10 +908,10 @@ bool EntityScriptingInterface::setAbsoluteJointsDataInObjectFrame(const QUuid& e if (result) { EntityItemProperties properties; _entityTree->withWriteLock([&] { - properties = entity->getProperties(); - // entity->setLastEdited(now); - entity->setLastBroadcast(now); - }); + properties = entity->getProperties(); + entity->setLastEdited(now); + entity->setLastBroadcast(now); + }); properties.setJointTranslationsDirty(); properties.setLastEdited(now); From bd35532c5dcd8fb201c2433c8782272d574ddb6d Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 4 Jan 2016 15:02:45 -0800 Subject: [PATCH 23/34] debugging --- libraries/entities/src/EntityScriptingInterface.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 26e0eb3ff5..5a82460634 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -890,7 +890,7 @@ bool EntityScriptingInterface::setAbsoluteJointsDataInObjectFrame(const QUuid& e EntityItemProperties properties; _entityTree->withWriteLock([&] { properties = entity->getProperties(); - entity->setLastEdited(now); + // entity->setLastEdited(now); entity->setLastBroadcast(now); }); @@ -909,7 +909,7 @@ bool EntityScriptingInterface::setAbsoluteJointsDataInObjectFrame(const QUuid& e EntityItemProperties properties; _entityTree->withWriteLock([&] { properties = entity->getProperties(); - entity->setLastEdited(now); + // entity->setLastEdited(now); entity->setLastBroadcast(now); }); From 5beba58e5f6a39f98c7cb17d364cd2da3441f8bf Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 4 Jan 2016 15:05:08 -0800 Subject: [PATCH 24/34] debugging --- libraries/entities/src/EntityScriptingInterface.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 5a82460634..4f4b801ac1 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -895,7 +895,7 @@ bool EntityScriptingInterface::setAbsoluteJointsDataInObjectFrame(const QUuid& e }); properties.setJointRotationsDirty(); - // properties.setLastEdited(now); + properties.setLastEdited(now); queueEntityMessage(PacketType::EntityEdit, entityID, properties); return true; } From 9304477233369fb88a11b0061b8b41cfaf7b1021 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 4 Jan 2016 15:29:06 -0800 Subject: [PATCH 25/34] split out calls for rotation and translation --- .../example/avatarcontrol/doppelganger.js | 7 ++-- .../entities/src/EntityScriptingInterface.cpp | 35 +++++++++++++------ .../entities/src/EntityScriptingInterface.h | 4 +++ 3 files changed, 33 insertions(+), 13 deletions(-) diff --git a/examples/example/avatarcontrol/doppelganger.js b/examples/example/avatarcontrol/doppelganger.js index f918dd85e9..ffd24f09b2 100644 --- a/examples/example/avatarcontrol/doppelganger.js +++ b/examples/example/avatarcontrol/doppelganger.js @@ -48,10 +48,11 @@ function getJointData(avatar) { } function setJointData(doppelganger, allJointData) { + var jointRotations = []; allJointData.forEach(function(jointData, index) { - Entities.setAbsoluteJointTranslationInObjectFrame(doppelganger.id, index, jointData.translation); - Entities.setAbsoluteJointRotationInObjectFrame(doppelganger.id, index, jointData.rotation); + jointRotations.push(jointData.rotation); }); + Entities.setAbsoluteJointRotationsInObjectFrame(doppelganger.id, jointRotations); return true; } @@ -86,7 +87,7 @@ function rotateDoppelgangerTowardAvatar(doppelganger, avatar) { function connectDoppelgangerUpdates() { // Script.update.connect(updateDoppelganger); - Script.setInterval(updateDoppelganger, 500); + Script.setInterval(updateDoppelganger, 100); } function disconnectDoppelgangerUpdates() { diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 4f4b801ac1..4f10139372 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -874,23 +874,21 @@ bool EntityScriptingInterface::setAbsoluteJointRotationInObjectFrame(const QUuid } -bool EntityScriptingInterface::setAbsoluteJointsDataInObjectFrame(const QUuid& entityID, - const QVector& rotations, - const QVector& translations) { + +bool EntityScriptingInterface::setAbsoluteJointRotationsInObjectFrame(const QUuid& entityID, + const QVector& rotations) { if (auto entity = checkForTreeEntityAndTypeMatch(entityID, EntityTypes::Model)) { auto now = usecTimestampNow(); auto modelEntity = std::dynamic_pointer_cast(entity); - int count = glm::max(rotations.size(), translations.size()); bool result = false; - for (int index = 0; index < count; index++) { + for (int index = 0; index < rotations.size(); index++) { result |= modelEntity->setAbsoluteJointRotationInObjectFrame(index, rotations[index]); } if (result) { EntityItemProperties properties; _entityTree->withWriteLock([&] { properties = entity->getProperties(); - // entity->setLastEdited(now); entity->setLastBroadcast(now); }); @@ -899,17 +897,25 @@ bool EntityScriptingInterface::setAbsoluteJointsDataInObjectFrame(const QUuid& e queueEntityMessage(PacketType::EntityEdit, entityID, properties); return true; } + } + return false; +} - result = false; - for (int index = 0; index < count; index++) { + +bool EntityScriptingInterface::setAbsoluteJointTranslationsInObjectFrame(const QUuid& entityID, + const QVector& translations) { + if (auto entity = checkForTreeEntityAndTypeMatch(entityID, EntityTypes::Model)) { + auto now = usecTimestampNow(); + auto modelEntity = std::dynamic_pointer_cast(entity); + + bool result = false; + for (int index = 0; index < translations.size(); index++) { result |= modelEntity->setAbsoluteJointTranslationInObjectFrame(index, translations[index]); } - now = usecTimestampNow(); if (result) { EntityItemProperties properties; _entityTree->withWriteLock([&] { properties = entity->getProperties(); - // entity->setLastEdited(now); entity->setLastBroadcast(now); }); @@ -921,3 +927,12 @@ bool EntityScriptingInterface::setAbsoluteJointsDataInObjectFrame(const QUuid& e } return false; } + + +bool EntityScriptingInterface::setAbsoluteJointsDataInObjectFrame(const QUuid& entityID, + const QVector& rotations, + const QVector& translations) { + // for a model with 80 joints, sending both these in one edit packet causes the packet to be too large. + return setAbsoluteJointRotationsInObjectFrame(entityID, rotations) || + setAbsoluteJointTranslationsInObjectFrame(entityID, translations); +} diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index f0751d74b6..5c22d7f6b8 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -153,6 +153,10 @@ public slots: Q_INVOKABLE glm::quat getAbsoluteJointRotationInObjectFrame(const QUuid& entityID, int jointIndex); Q_INVOKABLE bool setAbsoluteJointTranslationInObjectFrame(const QUuid& entityID, int jointIndex, glm::vec3 translation); Q_INVOKABLE bool setAbsoluteJointRotationInObjectFrame(const QUuid& entityID, int jointIndex, glm::quat rotation); + Q_INVOKABLE bool setAbsoluteJointRotationsInObjectFrame(const QUuid& entityID, + const QVector& rotations); + Q_INVOKABLE bool setAbsoluteJointTranslationsInObjectFrame(const QUuid& entityID, + const QVector& translations); Q_INVOKABLE bool setAbsoluteJointsDataInObjectFrame(const QUuid& entityID, const QVector& rotations, const QVector& translations); From ccf29e37725a811f9fb105651b3be6bbcc858bcd Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 4 Jan 2016 15:52:58 -0800 Subject: [PATCH 26/34] debugging --- libraries/entities/src/EntityScriptingInterface.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 4f10139372..ba47a84311 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -888,8 +888,9 @@ bool EntityScriptingInterface::setAbsoluteJointRotationsInObjectFrame(const QUui if (result) { EntityItemProperties properties; _entityTree->withWriteLock([&] { - properties = entity->getProperties(); + entity->setLastEdited(now); entity->setLastBroadcast(now); + properties = entity->getProperties(); }); properties.setJointRotationsDirty(); @@ -915,8 +916,9 @@ bool EntityScriptingInterface::setAbsoluteJointTranslationsInObjectFrame(const Q if (result) { EntityItemProperties properties; _entityTree->withWriteLock([&] { - properties = entity->getProperties(); + entity->setLastEdited(now); entity->setLastBroadcast(now); + properties = entity->getProperties(); }); properties.setJointTranslationsDirty(); From 202a6ae29437d9d331bacd186d0fe170595b1e65 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 4 Jan 2016 15:56:08 -0800 Subject: [PATCH 27/34] debugging --- libraries/entities/src/EntityScriptingInterface.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index ba47a84311..0000e7f85f 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -888,7 +888,7 @@ bool EntityScriptingInterface::setAbsoluteJointRotationsInObjectFrame(const QUui if (result) { EntityItemProperties properties; _entityTree->withWriteLock([&] { - entity->setLastEdited(now); + // entity->setLastEdited(now); entity->setLastBroadcast(now); properties = entity->getProperties(); }); @@ -916,7 +916,7 @@ bool EntityScriptingInterface::setAbsoluteJointTranslationsInObjectFrame(const Q if (result) { EntityItemProperties properties; _entityTree->withWriteLock([&] { - entity->setLastEdited(now); + // entity->setLastEdited(now); entity->setLastBroadcast(now); properties = entity->getProperties(); }); From 3026415f0333fb16fb5f6f8e80a5ebe7143f8886 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 4 Jan 2016 16:17:00 -0800 Subject: [PATCH 28/34] add some missing property handling boilerplate --- libraries/entities/src/EntityItemProperties.cpp | 15 +++++++++++++++ .../entities/src/EntityScriptingInterface.cpp | 4 ++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index a540bc1476..fadf0200f2 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -485,6 +485,11 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_LOCAL_POSITION, localPosition); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_LOCAL_ROTATION, localRotation); + COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_JOINT_ROTATIONS_SET, jointRotationsSet); + COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_JOINT_ROTATIONS, jointRotations); + COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_JOINT_TRANSLATIONS_SET, jointTranslationsSet); + COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_JOINT_TRANSLATIONS, jointTranslations); + // FIXME - I don't think these properties are supported any more //COPY_PROPERTY_TO_QSCRIPTVALUE(glowLevel); //COPY_PROPERTY_TO_QSCRIPTVALUE(localRenderAlpha); @@ -613,6 +618,11 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool COPY_PROPERTY_FROM_QSCRIPTVALUE(localPosition, glmVec3, setLocalPosition); COPY_PROPERTY_FROM_QSCRIPTVALUE(localRotation, glmQuat, setLocalRotation); + COPY_PROPERTY_FROM_QSCRIPTVALUE(jointRotationsSet, qVectorBool, setJointRotationsSet); + COPY_PROPERTY_FROM_QSCRIPTVALUE(jointRotations, qVectorQuat, setJointRotations); + COPY_PROPERTY_FROM_QSCRIPTVALUE(jointTranslationsSet, qVectorBool, setJointTranslationsSet); + COPY_PROPERTY_FROM_QSCRIPTVALUE(jointTranslations, qVectorVec3, setJointTranslations); + _lastEdited = usecTimestampNow(); } @@ -1486,6 +1496,11 @@ void EntityItemProperties::markAllChanged() { _parentIDChanged = true; _parentJointIndexChanged = true; + + _jointRotationsSetChanged = true; + _jointRotationsChanged = true; + _jointTranslationsSetChanged = true; + _jointTranslationsChanged = true; } /// The maximum bounding cube for the entity, independent of it's rotation. diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 0000e7f85f..ba47a84311 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -888,7 +888,7 @@ bool EntityScriptingInterface::setAbsoluteJointRotationsInObjectFrame(const QUui if (result) { EntityItemProperties properties; _entityTree->withWriteLock([&] { - // entity->setLastEdited(now); + entity->setLastEdited(now); entity->setLastBroadcast(now); properties = entity->getProperties(); }); @@ -916,7 +916,7 @@ bool EntityScriptingInterface::setAbsoluteJointTranslationsInObjectFrame(const Q if (result) { EntityItemProperties properties; _entityTree->withWriteLock([&] { - // entity->setLastEdited(now); + entity->setLastEdited(now); entity->setLastBroadcast(now); properties = entity->getProperties(); }); From 69839b4b16462e401eca672a84a04a89fe725f73 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 4 Jan 2016 17:50:25 -0800 Subject: [PATCH 29/34] better packing of qvector of quats --- libraries/octree/src/OctreePacketData.cpp | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/libraries/octree/src/OctreePacketData.cpp b/libraries/octree/src/OctreePacketData.cpp index d515244f64..909e0889c3 100644 --- a/libraries/octree/src/OctreePacketData.cpp +++ b/libraries/octree/src/OctreePacketData.cpp @@ -395,13 +395,17 @@ bool OctreePacketData::appendValue(const QVector& value) { bool OctreePacketData::appendValue(const QVector& value) { uint16_t qVecSize = value.size(); bool success = appendValue(qVecSize); + if (success) { - success = append((const unsigned char*)value.constData(), qVecSize * sizeof(glm::quat)); - if (success) { - _bytesOfValues += qVecSize * sizeof(glm::quat); - _totalBytesOfValues += qVecSize * sizeof(glm::quat); + QByteArray dataByteArray(udt::MAX_PACKET_SIZE, 0); + unsigned char* start = reinterpret_cast(dataByteArray.data()); + unsigned char* destinationBuffer = start; + for (int index = 0; index < value.size(); index++) { + destinationBuffer += packOrientationQuatToBytes(destinationBuffer, value[index]); } + success = append(start, destinationBuffer - start); } + return success; } @@ -649,11 +653,16 @@ int OctreePacketData::unpackDataFromBytes(const unsigned char *dataBytes, QVecto int OctreePacketData::unpackDataFromBytes(const unsigned char *dataBytes, QVector& result) { uint16_t length; + const unsigned char *start = dataBytes; memcpy(&length, dataBytes, sizeof(uint16_t)); dataBytes += sizeof(length); result.resize(length); - memcpy(result.data(), dataBytes, length * sizeof(glm::quat)); - return sizeof(uint16_t) + length * sizeof(glm::quat); + + for (int i = 0; i < length; i++) { + dataBytes += unpackOrientationQuatFromBytes(dataBytes, result[i]); + } + + return dataBytes - start; } int OctreePacketData::unpackDataFromBytes(const unsigned char* dataBytes, QVector& result) { From 0b9f92e50f99f2e51e2879f728dc358766ca8d4e Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 4 Jan 2016 18:01:48 -0800 Subject: [PATCH 30/34] fix quat (un)packing --- libraries/octree/src/OctreePacketData.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/libraries/octree/src/OctreePacketData.cpp b/libraries/octree/src/OctreePacketData.cpp index 909e0889c3..87a2b9ccae 100644 --- a/libraries/octree/src/OctreePacketData.cpp +++ b/libraries/octree/src/OctreePacketData.cpp @@ -403,7 +403,12 @@ bool OctreePacketData::appendValue(const QVector& value) { for (int index = 0; index < value.size(); index++) { destinationBuffer += packOrientationQuatToBytes(destinationBuffer, value[index]); } - success = append(start, destinationBuffer - start); + int quatsSize = destinationBuffer - start; + success = append(start, quatsSize); + if (success) { + _bytesOfValues += quatsSize; + _totalBytesOfValues += quatsSize; + } } return success; @@ -653,16 +658,16 @@ int OctreePacketData::unpackDataFromBytes(const unsigned char *dataBytes, QVecto int OctreePacketData::unpackDataFromBytes(const unsigned char *dataBytes, QVector& result) { uint16_t length; - const unsigned char *start = dataBytes; memcpy(&length, dataBytes, sizeof(uint16_t)); dataBytes += sizeof(length); result.resize(length); + const unsigned char *start = dataBytes; for (int i = 0; i < length; i++) { dataBytes += unpackOrientationQuatFromBytes(dataBytes, result[i]); } - return dataBytes - start; + return (dataBytes - start) + sizeof(uint16_t); } int OctreePacketData::unpackDataFromBytes(const unsigned char* dataBytes, QVector& result) { From 2d246a840f7207ddaaaafda5e1e8024108a4592b Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 4 Jan 2016 18:14:29 -0800 Subject: [PATCH 31/34] better packing for qvector of bools --- libraries/octree/src/OctreePacketData.cpp | 37 ++++++++++++++++++++--- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/libraries/octree/src/OctreePacketData.cpp b/libraries/octree/src/OctreePacketData.cpp index 87a2b9ccae..a3fa99c5b9 100644 --- a/libraries/octree/src/OctreePacketData.cpp +++ b/libraries/octree/src/OctreePacketData.cpp @@ -14,6 +14,7 @@ #include "OctreeLogging.h" #include "OctreePacketData.h" +#include "NumericalConstants.h" bool OctreePacketData::_debug = false; AtomicUIntStat OctreePacketData::_totalBytesOfOctalCodes { 0 }; @@ -430,11 +431,26 @@ bool OctreePacketData::appendValue(const QVector& value) { bool OctreePacketData::appendValue(const QVector& value) { uint16_t qVecSize = value.size(); bool success = appendValue(qVecSize); + if (success) { - success = append((const unsigned char*)value.constData(), qVecSize * sizeof(bool)); + QByteArray dataByteArray(udt::MAX_PACKET_SIZE, 0); + unsigned char* start = reinterpret_cast(dataByteArray.data()); + unsigned char* destinationBuffer = start; + int bit = 0; + for (int index = 0; index < value.size(); index++) { + if (value[index]) { + (*destinationBuffer) |= (1 << bit); + } + if (++bit == BITS_IN_BYTE) { + destinationBuffer++; + bit = 0; + } + } + int boolsSize = destinationBuffer - start; + success = append(start, boolsSize); if (success) { - _bytesOfValues += qVecSize * sizeof(bool); - _totalBytesOfValues += qVecSize * sizeof(bool); + _bytesOfValues += boolsSize; + _totalBytesOfValues += boolsSize; } } return success; @@ -684,8 +700,19 @@ int OctreePacketData::unpackDataFromBytes(const unsigned char* dataBytes, QVecto memcpy(&length, dataBytes, sizeof(uint16_t)); dataBytes += sizeof(length); result.resize(length); - memcpy(result.data(), dataBytes, length * sizeof(bool)); - return sizeof(uint16_t) + length * sizeof(bool); + + int bit = 0; + unsigned char current = 0; + const unsigned char *start = dataBytes; + for (int i = 0; i < length; i ++) { + if (bit == 0) { + current = *dataBytes++; + } + result[i] = (bool)(current & (1 << bit)); + bit = (bit + 1) % BITS_IN_BYTE; + } + + return (dataBytes - start) + sizeof(uint16_t); } int OctreePacketData::unpackDataFromBytes(const unsigned char* dataBytes, QByteArray& result) { From 3db68e31510c47c357e64e2e6fc7eeac3d6e3d06 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 4 Jan 2016 18:16:20 -0800 Subject: [PATCH 32/34] add model joints to debugging --- libraries/entities/src/EntityItemProperties.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 9b8142d4c2..bfd2d405ef 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -406,6 +406,11 @@ inline QDebug operator<<(QDebug debug, const EntityItemProperties& properties) { DEBUG_PROPERTY_IF_CHANGED(debug, properties, ParentID, parentID, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, ParentJointIndex, parentJointIndex, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, JointRotationsSet, jointRotationsSet, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, JointRotations, jointRotations, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, JointTranslationsSet, jointTranslationsSet, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, JointTranslations, jointTranslations, ""); + properties.getAnimation().debugDump(); properties.getAtmosphere().debugDump(); properties.getSkybox().debugDump(); From b222c1285787925891b2da6c4801621c7c1763ca Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 5 Jan 2016 12:21:50 -0800 Subject: [PATCH 33/34] unmangle merge --- interface/src/avatar/Avatar.h | 2 ++ libraries/avatars/src/AvatarData.h | 2 ++ 2 files changed, 4 insertions(+) diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index 8f89027d2f..a9a3bd14f4 100644 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -112,6 +112,8 @@ public: virtual glm::quat getAbsoluteJointRotationInObjectFrame(int index) const override; virtual glm::vec3 getAbsoluteJointTranslationInObjectFrame(int index) const override; + virtual bool setAbsoluteJointRotationInObjectFrame(int index, const glm::quat& rotation) override { return false; } + virtual bool setAbsoluteJointTranslationInObjectFrame(int index, const glm::vec3& translation) override { return false; } virtual void setFaceModelURL(const QUrl& faceModelURL) override; virtual void setSkeletonModelURL(const QUrl& skeletonModelURL) override; diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index c0fe62c7c4..f19164fe45 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -358,6 +358,8 @@ public slots: virtual glm::quat getAbsoluteJointRotationInObjectFrame(int index) const override; virtual glm::vec3 getAbsoluteJointTranslationInObjectFrame(int index) const override; + virtual bool setAbsoluteJointRotationInObjectFrame(int index, const glm::quat& rotation) override { return false; } + virtual bool setAbsoluteJointTranslationInObjectFrame(int index, const glm::vec3& translation) override { return false; } protected: glm::vec3 _handPosition; From f7041136ff07f30d18ab198cf9a7b38d0aef44e6 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 5 Jan 2016 13:26:16 -0800 Subject: [PATCH 34/34] put new property in right place --- libraries/entities/src/EntityPropertyFlags.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/entities/src/EntityPropertyFlags.h b/libraries/entities/src/EntityPropertyFlags.h index 9b605f864e..c59ed7141b 100644 --- a/libraries/entities/src/EntityPropertyFlags.h +++ b/libraries/entities/src/EntityPropertyFlags.h @@ -157,14 +157,14 @@ enum EntityPropertyList { PROP_LOCAL_POSITION, // only used to convert values to and from scripts PROP_LOCAL_ROTATION, // only used to convert values to and from scripts + PROP_QUERY_AA_CUBE, // how the EntityTree considers the size and position on an entity + // ModelEntity joint state PROP_JOINT_ROTATIONS_SET, PROP_JOINT_ROTATIONS, PROP_JOINT_TRANSLATIONS_SET, PROP_JOINT_TRANSLATIONS, - PROP_QUERY_AA_CUBE, // how the EntityTree considers the size and position on an entity - //////////////////////////////////////////////////////////////////////////////////////////////////// // ATTENTION: add new properties to end of list just ABOVE this line PROP_AFTER_LAST_ITEM,