make entity properties for model-entity joint-states

This commit is contained in:
Seth Alves 2015-12-23 15:43:50 -08:00
parent 29e79c0672
commit 83f60d6e97
14 changed files with 449 additions and 135 deletions

View file

@ -13,6 +13,7 @@
#include <QJsonDocument>
#include <QtCore/QThread>
#include <glm/gtx/transform.hpp>
#include <AbstractViewStateInterface.h>
#include <DeferredLightingEffect.h>
@ -230,8 +231,8 @@ bool RenderableModelEntityItem::addToScene(EntityItemPointer self, std::shared_p
return true;
}
void RenderableModelEntityItem::removeFromScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene,
void RenderableModelEntityItem::removeFromScene(EntityItemPointer self, std::shared_ptr<render::Scene> 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<FBXAnimationFrame>& 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<glm::quat> frameDataRotations;
QVector<glm::vec3> 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() {

View file

@ -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<QVector<glm::vec3>> _points;
bool _dimensionsInitialized = true;
render::ItemID _myMetaItem;
bool _showCollisionHull = false;
// these are used to let scripts set ModelEntityItem joint data
ReadWriteLockable _scriptSetFrameDataLock;
QQueue<glm::quat> _scriptSetFrameDataRotations;
QQueue<int> _scriptSetFrameDataRotationsIndexes;
QQueue<glm::vec3> _scriptSetFrameDataTranslations;
QQueue<int> _scriptSetFrameDataTranslationsIndexes;
bool getAnimationFrame();
};
#endif // hifi_RenderableModelEntityItem_h

View file

@ -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<bool>);
ADD_PROPERTY_TO_MAP(PROP_JOINT_ROTATIONS, JointRotations, jointRotations, QVector<glm::quat>);
ADD_PROPERTY_TO_MAP(PROP_JOINT_TRANSLATIONS_SET, JointTranslationsSet, jointTranslationsSet, QVector<bool>);
ADD_PROPERTY_TO_MAP(PROP_JOINT_TRANSLATIONS, JointTranslations, jointTranslations, QVector<glm::vec3>);
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<bool>, setJointRotationsSet);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_JOINT_ROTATIONS, QVector<glm::quat>, setJointRotations);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_JOINT_TRANSLATIONS_SET, QVector<bool>, setJointTranslationsSet);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_JOINT_TRANSLATIONS, QVector<glm::vec3>, setJointTranslations);
}
if (properties.getType() == EntityTypes::Light) {

View file

@ -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<bool>, QVector<bool>());
DEFINE_PROPERTY_REF(PROP_JOINT_ROTATIONS, JointRotations, jointRotations, QVector<glm::quat>, QVector<glm::quat>());
DEFINE_PROPERTY_REF(PROP_JOINT_TRANSLATIONS_SET, JointTranslationsSet, jointTranslationsSet, QVector<bool>, QVector<bool>());
DEFINE_PROPERTY_REF(PROP_JOINT_TRANSLATIONS, JointTranslations, jointTranslations, QVector<glm::vec3>, QVector<glm::vec3>());
static QString getBackgroundModeString(BackgroundMode mode);

View file

@ -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<glm::vec3>& v) {return qVectorVec3ToScriptValue(e, v); }
inline QScriptValue convertScriptValue(QScriptEngine* e, const QVector<glm::quat>& v) {return qVectorQuatToScriptValue(e, v); }
inline QScriptValue convertScriptValue(QScriptEngine* e, const QVector<bool>& v) {return qVectorBoolToScriptValue(e, v); }
inline QScriptValue convertScriptValue(QScriptEngine* e, const QVector<float>& 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<glm::vec3> qVectorVec3;
typedef QVector<glm::quat> qVectorQuat;
typedef QVector<bool> qVectorBool;
typedef QVector<float> 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");

View file

@ -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,

View file

@ -133,6 +133,11 @@ int ModelEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data,
somethingChanged = true;
}
READ_ENTITY_PROPERTY(PROP_JOINT_ROTATIONS_SET, QVector<bool>, setJointRotationsSet);
READ_ENTITY_PROPERTY(PROP_JOINT_ROTATIONS, QVector<glm::quat>, setJointRotations);
READ_ENTITY_PROPERTY(PROP_JOINT_TRANSLATIONS_SET, QVector<bool>, setJointTranslationsSet);
READ_ENTITY_PROPERTY(PROP_JOINT_TRANSLATIONS, QVector<glm::vec3>, 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<glm::quat>& rotationsResult, QVector<glm::vec3>& 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<FBXAnimationFrame>& 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<glm::quat>& rotations = frames[animationCurrentFrame].rotations;
const QVector<glm::vec3>& 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<glm::quat>& 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<bool>& rotationsSet) {
_jointDataLock.withWriteLock([&] {
resizeJointArrays(rotationsSet.size());
for (int index = 0; index < rotationsSet.size(); index++) {
_absoluteJointRotationsInObjectFrameSet[index] = rotationsSet[index];
}
});
}
void ModelEntityItem::setJointTranslations(const QVector<glm::vec3>& 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<bool>& translationsSet) {
_jointDataLock.withWriteLock([&] {
resizeJointArrays(translationsSet.size());
for (int index = 0; index < translationsSet.size(); index++) {
_absoluteJointTranslationsInObjectFrameSet[index] = translationsSet[index];
}
});
}
QVector<glm::quat> ModelEntityItem::getJointRotations() const {
QVector<glm::quat> result;
_jointDataLock.withReadLock([&] {
result = _absoluteJointRotationsInObjectFrame;
});
return result;
}
QVector<bool> ModelEntityItem::getJointRotationsSet() const {
QVector<bool> result;
_jointDataLock.withReadLock([&] {
result = _absoluteJointRotationsInObjectFrameSet;
});
return result;
}
QVector<glm::vec3> ModelEntityItem::getJointTranslations() const {
QVector<glm::vec3> result;
_jointDataLock.withReadLock([&] {
result = _absoluteJointTranslationsInObjectFrame;
});
return result;
}
QVector<bool> ModelEntityItem::getJointTranslationsSet() const {
QVector<bool> result;
_jointDataLock.withReadLock([&] {
result = _absoluteJointTranslationsInObjectFrameSet;
});
return result;
}

View file

@ -103,7 +103,6 @@ public:
float getAnimationLastFrame() const { return _animationLoop.getLastFrame(); }
void mapJoints(const QStringList& modelJointNames);
void getAnimationFrame(bool& newFrame, QVector<glm::quat>& rotationsResult, QVector<glm::vec3>& 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<glm::quat>& rotations);
void setJointRotationsSet(const QVector<bool>& rotationsSet);
void setJointTranslations(const QVector<glm::vec3>& translations);
void setJointTranslationsSet(const QVector<bool>& translationsSet);
QVector<glm::quat> getJointRotations() const;
QVector<bool> getJointRotationsSet() const;
QVector<glm::vec3> getJointTranslations() const;
QVector<bool> getJointTranslationsSet() const;
private:
void setAnimationSettings(const QString& value); // only called for old bitstream format
protected:
QVector<glm::quat> _lastKnownFrameDataRotations;
QVector<glm::vec3> _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<glm::quat> _absoluteJointRotationsInObjectFrame;
QVector<bool> _absoluteJointRotationsInObjectFrameSet; // ever set?
QVector<bool> _absoluteJointRotationsInObjectFrameDirty; // needs a relay to model/rig?
QVector<glm::vec3> _absoluteJointTranslationsInObjectFrame;
QVector<bool> _absoluteJointTranslationsInObjectFrameSet; // ever set?
QVector<bool> _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<int> _jointMapping;
QVector<int> _jointMapping; // domain is index into model-joints, range is index into animation-joints
QString _jointMappingURL;
static AnimationPointer getAnimation(const QString& url);

View file

@ -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;

View file

@ -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

View file

@ -392,6 +392,19 @@ bool OctreePacketData::appendValue(const QVector<glm::vec3>& value) {
return success;
}
bool OctreePacketData::appendValue(const QVector<glm::quat>& 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<float>& value) {
uint16_t qVecSize = value.size();
bool success = appendValue(qVecSize);
@ -405,6 +418,19 @@ bool OctreePacketData::appendValue(const QVector<float>& value) {
return success;
}
bool OctreePacketData::appendValue(const QVector<bool>& 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<glm::quat>& 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<float>& 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<bool>& 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);

View file

@ -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<glm::vec3>& 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<glm::quat>& 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<float>& 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<bool>& 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<glm::vec3>& result);
static int unpackDataFromBytes(const unsigned char* dataBytes, QVector<glm::quat>& result);
static int unpackDataFromBytes(const unsigned char* dataBytes, QVector<float>& result);
static int unpackDataFromBytes(const unsigned char* dataBytes, QVector<bool>& result);
static int unpackDataFromBytes(const unsigned char* dataBytes, QByteArray& result);
private:

View file

@ -20,6 +20,8 @@
static int vec4MetaTypeId = qRegisterMetaType<glm::vec4>();
static int vec3MetaTypeId = qRegisterMetaType<glm::vec3>();
static int qVectorVec3MetaTypeId = qRegisterMetaType<QVector<glm::vec3>>();
static int qVectorQuatMetaTypeId = qRegisterMetaType<QVector<glm::quat>>();
static int qVectorBoolMetaTypeId = qRegisterMetaType<QVector<bool>>();
static int vec2MetaTypeId = qRegisterMetaType<glm::vec2>();
static int quatMetaTypeId = qRegisterMetaType<glm::quat>();
static int xColorMetaTypeId = qRegisterMetaType<xColor>();
@ -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 QVector<glm::
return array;
}
QScriptValue quatToScriptValue(QScriptEngine* engine, const glm::quat &quat) {
QScriptValue obj = engine->newObject();
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<glm::quat>& 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<bool>& vector) {
QScriptValue array = engine->newArray();
for (int i = 0; i < vector.size(); i++) {
array.setProperty(i, vector.at(i));
}
return array;
}
QVector<float> qVectorFloatFromScriptValue(const QScriptValue& array) {
if(!array.isArray()) {
return QVector<float>();
@ -149,7 +189,7 @@ QVector<glm::vec3> qVectorVec3FromScriptValue(const QScriptValue& array){
void qVectorVec3FromScriptValue(const QScriptValue& array, QVector<glm::vec3>& 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<glm::vec3>& v
}
}
QVector<glm::quat> qVectorQuatFromScriptValue(const QScriptValue& array){
QVector<glm::quat> 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<glm::quat>& 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<bool> qVectorBoolFromScriptValue(const QScriptValue& array){
QVector<bool> 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<bool>& 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());

View file

@ -61,6 +61,14 @@ QScriptValue qVectorVec3ToScriptValue(QScriptEngine* engine, const QVector<glm::
void qVectorVec3FromScriptValue(const QScriptValue& array, QVector<glm::vec3>& vector);
QVector<glm::vec3> qVectorVec3FromScriptValue(const QScriptValue& array);
QScriptValue qVectorQuatToScriptValue(QScriptEngine* engine, const QVector<glm::quat>& vector);
void qVectorQuatFromScriptValue(const QScriptValue& array, QVector<glm::quat>& vector);
QVector<glm::quat> qVectorQuatFromScriptValue(const QScriptValue& array);
QScriptValue qVectorBoolToScriptValue(QScriptEngine* engine, const QVector<bool>& vector);
void qVectorBoolFromScriptValue(const QScriptValue& array, QVector<bool>& vector);
QVector<bool> qVectorBoolFromScriptValue(const QScriptValue& array);
QScriptValue qVectorFloatToScriptValue(QScriptEngine* engine, const QVector<float>& vector);
void qVectorFloatFromScriptValue(const QScriptValue& array, QVector<float>& vector);
QVector<float> qVectorFloatFromScriptValue(const QScriptValue& array);