From 5309c5ad8bd0e7228c4b23a98e76d68d1b4d9ba0 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 12 May 2014 13:44:44 -0700 Subject: [PATCH] add more properties to animated models --- examples/placeModelsWithHands.js | 1 + libraries/models/src/ModelItem.cpp | 132 +++++++++++++++++- libraries/models/src/ModelItem.h | 19 ++- .../models/src/ModelsScriptingInterface.h | 14 ++ 4 files changed, 159 insertions(+), 7 deletions(-) diff --git a/examples/placeModelsWithHands.js b/examples/placeModelsWithHands.js index f16945472d..bd0915da54 100644 --- a/examples/placeModelsWithHands.js +++ b/examples/placeModelsWithHands.js @@ -231,6 +231,7 @@ function checkControllerSide(whichSide) { if (animationURLs[currentModelURL] !== "") { properties.animationURL = animationURLs[currentModelURL]; + properties.isAnimationPlaying = true; } debugPrint("modelRadius=" +modelRadius); diff --git a/libraries/models/src/ModelItem.cpp b/libraries/models/src/ModelItem.cpp index aedd1fef47..9dd1173259 100644 --- a/libraries/models/src/ModelItem.cpp +++ b/libraries/models/src/ModelItem.cpp @@ -88,7 +88,9 @@ ModelItem::ModelItem(const ModelItemID& modelItemID, const ModelItemProperties& // animation related _animationURL = MODEL_DEFAULT_ANIMATION_URL; + _isAnimationPlaying = false; _frameIndex = 0.0f; + _jointMappingCompleted = false; _lastAnimated = now; @@ -119,6 +121,7 @@ void ModelItem::init(glm::vec3 position, float radius, rgbColor color, uint32_t // animation related _animationURL = MODEL_DEFAULT_ANIMATION_URL; + _isAnimationPlaying = false; _frameIndex = 0.0f; _jointMappingCompleted = false; _lastAnimated = now; @@ -172,6 +175,16 @@ bool ModelItem::appendModelData(OctreePacketData* packetData) const { } } + // isAnimationPlaying + if (success) { + success = packetData->appendValue(getIsAnimationPlaying()); + } + + // frameIndex + if (success) { + success = packetData->appendValue(getFrameIndex()); + } + return success; } @@ -259,6 +272,17 @@ int ModelItem::readModelDataFromBuffer(const unsigned char* data, int bytesLeftT bytesRead += animationURLLength; qDebug() << "readModelDataFromBuffer()... animationURL=" << qPrintable(animationURLString); + + // isAnimationPlaying + memcpy(&_isAnimationPlaying, dataAt, sizeof(_isAnimationPlaying)); + dataAt += sizeof(_isAnimationPlaying); + bytesRead += sizeof(_isAnimationPlaying); + + // frameIndex + memcpy(&_frameIndex, dataAt, sizeof(_frameIndex)); + dataAt += sizeof(_frameIndex); + bytesRead += sizeof(_frameIndex); + } else { qDebug() << "readModelDataFromBuffer()... this model didn't have animation details"; } @@ -395,9 +419,25 @@ ModelItem ModelItem::fromEditPacket(const unsigned char* data, int length, int& newModelItem._animationURL = tempString; dataAt += animationURLLength; processedBytes += animationURLLength; - qDebug() << "fromEditPacket()... animationURL=" << qPrintable(tempString); + } + // isAnimationPlaying + if (isNewModelItem || ((packetContainsBits & + MODEL_PACKET_CONTAINS_ANIMATION_PLAYING) == MODEL_PACKET_CONTAINS_ANIMATION_PLAYING)) { + + memcpy(&newModelItem._isAnimationPlaying, dataAt, sizeof(newModelItem._isAnimationPlaying)); + dataAt += sizeof(newModelItem._isAnimationPlaying); + processedBytes += sizeof(newModelItem._isAnimationPlaying); + } + + // frameIndex + if (isNewModelItem || ((packetContainsBits & + MODEL_PACKET_CONTAINS_ANIMATION_FRAME) == MODEL_PACKET_CONTAINS_ANIMATION_FRAME)) { + + memcpy(&newModelItem._frameIndex, dataAt, sizeof(newModelItem._frameIndex)); + dataAt += sizeof(newModelItem._frameIndex); + processedBytes += sizeof(newModelItem._frameIndex); } const bool wantDebugging = false; @@ -545,6 +585,30 @@ qDebug() << "encodeModelItemEditMessageDetails()... animationURL=" << qPrintable } + // isAnimationPlaying + if (isNewModelItem || ((packetContainsBits & + MODEL_PACKET_CONTAINS_ANIMATION_PLAYING) == MODEL_PACKET_CONTAINS_ANIMATION_PLAYING)) { + + bool isAnimationPlaying = properties.getIsAnimationPlaying(); + memcpy(copyAt, &isAnimationPlaying, sizeof(isAnimationPlaying)); + copyAt += sizeof(isAnimationPlaying); + sizeOut += sizeof(isAnimationPlaying); + + +qDebug() << "encodeModelItemEditMessageDetails()... isAnimationPlaying=" << isAnimationPlaying; + } + + // frameIndex + if (isNewModelItem || ((packetContainsBits & + MODEL_PACKET_CONTAINS_ANIMATION_FRAME) == MODEL_PACKET_CONTAINS_ANIMATION_FRAME)) { + + float frameIndex = properties.getFrameIndex(); + memcpy(copyAt, &frameIndex, sizeof(frameIndex)); + copyAt += sizeof(frameIndex); + sizeOut += sizeof(frameIndex); + +qDebug() << "encodeModelItemEditMessageDetails()... frameIndex=" << frameIndex; + } bool wantDebugging = false; if (wantDebugging) { @@ -631,11 +695,16 @@ void ModelItem::mapJoints(const QStringList& modelJointNames) { QVector ModelItem::getAnimationFrame() { QVector frameData; if (hasAnimation() && _jointMappingCompleted) { - quint64 now = usecTimestampNow(); - float deltaTime = (float)(now - _lastAnimated) / (float)USECS_PER_SECOND; - _lastAnimated = now; - const float FRAME_RATE = 10.0f; - _frameIndex += deltaTime * FRAME_RATE; + + // only advance the frame index if we're playing + if (getIsAnimationPlaying()) { + quint64 now = usecTimestampNow(); + float deltaTime = (float)(now - _lastAnimated) / (float)USECS_PER_SECOND; + _lastAnimated = now; + const float FRAME_RATE = 10.0f; + _frameIndex += deltaTime * FRAME_RATE; + } + Animation* myAnimation = getAnimation(_animationURL); QVector frames = myAnimation->getFrames(); int frameIndex = (int)std::floor(_frameIndex) % frames.size(); @@ -678,6 +747,8 @@ ModelItemProperties::ModelItemProperties() : _modelURL(""), _modelRotation(MODEL_DEFAULT_MODEL_ROTATION), _animationURL(""), + _isAnimationPlaying(false), + _frameIndex(0.0), _id(UNKNOWN_MODEL_ID), _idSet(false), @@ -690,6 +761,8 @@ ModelItemProperties::ModelItemProperties() : _modelURLChanged(false), _modelRotationChanged(false), _animationURLChanged(false), + _isAnimationPlayingChanged(false), + _frameIndexChanged(false), _defaultSettings(true) { } @@ -725,6 +798,13 @@ uint16_t ModelItemProperties::getChangedBits() const { changedBits += MODEL_PACKET_CONTAINS_ANIMATION_URL; } + if (_isAnimationPlayingChanged) { + changedBits += MODEL_PACKET_CONTAINS_ANIMATION_PLAYING; + } + + if (_frameIndexChanged) { + changedBits += MODEL_PACKET_CONTAINS_ANIMATION_FRAME; + } return changedBits; } @@ -749,6 +829,8 @@ QScriptValue ModelItemProperties::copyToScriptValue(QScriptEngine* engine) const properties.setProperty("modelRotation", modelRotation); properties.setProperty("animationURL", _animationURL); + properties.setProperty("isAnimationPlaying", _isAnimationPlaying); + properties.setProperty("frameIndex", _frameIndex); if (_idSet) { properties.setProperty("id", _id); @@ -855,6 +937,26 @@ void ModelItemProperties::copyFromScriptValue(const QScriptValue &object) { } } + QScriptValue isAnimationPlaying = object.property("isAnimationPlaying"); + if (isAnimationPlaying.isValid()) { + bool newIsAnimationPlaying; + newIsAnimationPlaying = isAnimationPlaying.toVariant().toBool(); + if (_defaultSettings || newIsAnimationPlaying != _isAnimationPlaying) { + _isAnimationPlaying = newIsAnimationPlaying; + _isAnimationPlayingChanged = true; + } + } + + QScriptValue frameIndex = object.property("frameIndex"); + if (frameIndex.isValid()) { + float newFrameIndex; + newFrameIndex = frameIndex.toVariant().toFloat(); + if (_defaultSettings || newFrameIndex != _frameIndex) { + _frameIndex = newFrameIndex; + _frameIndexChanged = true; + } + } + _lastEdited = usecTimestampNow(); } @@ -897,6 +999,20 @@ void ModelItemProperties::copyToModelItem(ModelItem& modelItem) const { qDebug() << "ModelItemProperties::copyToModelItem()... modelItem.setAnimationURL(_animationURL)=" << _animationURL; } + if (_isAnimationPlayingChanged) { + modelItem.setIsAnimationPlaying(_isAnimationPlaying); + somethingChanged = true; + +qDebug() << "ModelItemProperties::copyToModelItem()... _isAnimationPlaying=" << _isAnimationPlaying; + } + + if (_frameIndexChanged) { + modelItem.setFrameIndex(_frameIndex); + somethingChanged = true; + +qDebug() << "ModelItemProperties::copyToModelItem()... _frameIndex=" << _frameIndex; + } + if (somethingChanged) { bool wantDebug = false; if (wantDebug) { @@ -917,6 +1033,8 @@ void ModelItemProperties::copyFromModelItem(const ModelItem& modelItem) { _modelURL = modelItem.getModelURL(); _modelRotation = modelItem.getModelRotation(); _animationURL = modelItem.getAnimationURL(); + _isAnimationPlaying = modelItem.getIsAnimationPlaying(); + _frameIndex = modelItem.getFrameIndex(); _id = modelItem.getID(); _idSet = true; @@ -929,6 +1047,8 @@ void ModelItemProperties::copyFromModelItem(const ModelItem& modelItem) { _modelURLChanged = false; _modelRotationChanged = false; _animationURLChanged = false; + _isAnimationPlayingChanged = false; + _frameIndexChanged = false; _defaultSettings = false; } diff --git a/libraries/models/src/ModelItem.h b/libraries/models/src/ModelItem.h index cafd150e6d..a6c317d122 100644 --- a/libraries/models/src/ModelItem.h +++ b/libraries/models/src/ModelItem.h @@ -44,6 +44,8 @@ const uint16_t MODEL_PACKET_CONTAINS_SHOULDDIE = 8; const uint16_t MODEL_PACKET_CONTAINS_MODEL_URL = 16; const uint16_t MODEL_PACKET_CONTAINS_MODEL_ROTATION = 32; const uint16_t MODEL_PACKET_CONTAINS_ANIMATION_URL = 64; +const uint16_t MODEL_PACKET_CONTAINS_ANIMATION_PLAYING = 128; +const uint16_t MODEL_PACKET_CONTAINS_ANIMATION_FRAME = 256; const float MODEL_DEFAULT_RADIUS = 0.1f / TREE_SCALE; const float MINIMUM_MODEL_ELEMENT_SIZE = (1.0f / 100000.0f) / TREE_SCALE; // smallest size container @@ -75,6 +77,8 @@ public: const QString& getModelURL() const { return _modelURL; } const glm::quat& getModelRotation() const { return _modelRotation; } const QString& getAnimationURL() const { return _animationURL; } + float getFrameIndex() const { return _frameIndex; } + bool getIsAnimationPlaying() const { return _isAnimationPlaying; } quint64 getLastEdited() const { return _lastEdited; } uint16_t getChangedBits() const; @@ -89,6 +93,8 @@ public: void setModelURL(const QString& url) { _modelURL = url; _modelURLChanged = true; } void setModelRotation(const glm::quat& rotation) { _modelRotation = rotation; _modelRotationChanged = true; } void setAnimationURL(const QString& url) { _animationURL = url; _animationURLChanged = true; } + void setFrameIndex(float value) { _frameIndex = value; _frameIndexChanged = true; } + void setIsAnimationPlaying(bool value) { _isAnimationPlaying = value; _isAnimationPlayingChanged = true; } /// used by ModelScriptingInterface to return ModelItemProperties for unknown models void setIsUnknownID() { _id = UNKNOWN_MODEL_ID; _idSet = true; } @@ -105,6 +111,8 @@ private: QString _modelURL; glm::quat _modelRotation; QString _animationURL; + bool _isAnimationPlaying; + float _frameIndex; uint32_t _id; bool _idSet; @@ -118,6 +126,8 @@ private: bool _modelURLChanged; bool _modelRotationChanged; bool _animationURLChanged; + bool _isAnimationPlayingChanged; + bool _frameIndexChanged; bool _defaultSettings; }; Q_DECLARE_METATYPE(ModelItemProperties); @@ -228,6 +238,8 @@ public: void setModelURL(const QString& url) { _modelURL = url; } void setModelRotation(const glm::quat& rotation) { _modelRotation = rotation; } void setAnimationURL(const QString& url) { _animationURL = url; } + void setFrameIndex(float value) { _frameIndex = value; } + void setIsAnimationPlaying(bool value) { _isAnimationPlaying = value; } void setProperties(const ModelItemProperties& properties); @@ -254,7 +266,10 @@ public: void mapJoints(const QStringList& modelJointNames); QVector getAnimationFrame(); - bool jointsMapped() const { return _jointMappingCompleted; }; + bool jointsMapped() const { return _jointMappingCompleted; } + + bool getIsAnimationPlaying() const { return _isAnimationPlaying; } + float getFrameIndex() const { return _frameIndex; } protected: glm::vec3 _position; @@ -277,6 +292,8 @@ protected: QString _animationURL; float _frameIndex; // we keep this as a float and round to int only when we need the exact index + bool _isAnimationPlaying; + bool _jointMappingCompleted; QVector _jointMapping; diff --git a/libraries/models/src/ModelsScriptingInterface.h b/libraries/models/src/ModelsScriptingInterface.h index bf8e193f25..f08ec715a9 100644 --- a/libraries/models/src/ModelsScriptingInterface.h +++ b/libraries/models/src/ModelsScriptingInterface.h @@ -59,6 +59,20 @@ public slots: /// this function will not find any models in script engine contexts which don't have access to models QVector findModels(const glm::vec3& center, float radius) const; + /* + /// pauses the model animation. + ModelItemID pauseModelAnimation(ModelItemID modelID); + + /// plays the model animation. + ModelItemID playModelAnimation(ModelItemID modelID); + + /// gets the current frame of the model animation. + float getModelAnimationFrame(ModelItemID modelID); + + /// gets the current frame of the model animation. + void setModelAnimationFrame(ModelItemID modelID, float frame); + */ + signals: void modelCollisionWithVoxel(const ModelItemID& modelID, const VoxelDetail& voxel, const CollisionInfo& collision); void modelCollisionWithModel(const ModelItemID& idA, const ModelItemID& idB, const CollisionInfo& collision);