diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 10866fa9ca..2bc7e788ad 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -823,7 +823,7 @@ QVector Avatar::getJointRotations() const { } QVector jointRotations(_skeletonModel.getJointStateCount()); for (int i = 0; i < _skeletonModel.getJointStateCount(); ++i) { - _skeletonModel.getJointState(i, jointRotations[i]); + _skeletonModel.getJointRotation(i, jointRotations[i]); } return jointRotations; } @@ -833,7 +833,7 @@ glm::quat Avatar::getJointRotation(int index) const { return AvatarData::getJointRotation(index); } glm::quat rotation; - _skeletonModel.getJointState(index, rotation); + _skeletonModel.getJointRotation(index, rotation); return rotation; } diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 56f5241316..178ebc0487 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -216,10 +216,10 @@ void MyAvatar::simulate(float deltaTime) { { PerformanceTimer perfTimer("joints"); // copy out the skeleton joints from the model - _jointData.resize(_skeletonModel.getJointStateCount()); + _jointData.resize(_rig->getJointStateCount()); for (int i = 0; i < _jointData.size(); i++) { JointData& data = _jointData[i]; - data.valid = _skeletonModel.getJointState(i, data.rotation); + data.valid = _rig->getJointStateRotation(i, data.rotation); } } diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 12bfd606da..0a889fce88 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -41,6 +41,14 @@ bool Rig::isRunningAnimation(AnimationHandlePointer animationHandle) { return _runningAnimations.contains(animationHandle); } +void Rig::deleteAnimations() { + for (QSet::iterator it = _animationHandles.begin(); it != _animationHandles.end(); ) { + (*it)->clearJoints(); + it = _animationHandles.erase(it); + } +} + + float Rig::initJointStates(QVector states, glm::mat4 parentTransform) { _jointStates = states; initJointTransforms(parentTransform); @@ -235,7 +243,12 @@ glm::mat4 Rig::getJointVisibleTransform(int jointIndex) const { return _jointStates[jointIndex].getVisibleTransform(); } -void Rig::simulateInternal(glm::mat4 parentTransform) { +void Rig::simulateInternal(float deltaTime, glm::mat4 parentTransform) { + // update animations + foreach (const AnimationHandlePointer& handle, _runningAnimations) { + handle->simulate(deltaTime); + } + for (int i = 0; i < _jointStates.size(); i++) { updateJointState(i, parentTransform); } diff --git a/libraries/animation/src/Rig.h b/libraries/animation/src/Rig.h index 6d282bf8f4..e60116a35e 100644 --- a/libraries/animation/src/Rig.h +++ b/libraries/animation/src/Rig.h @@ -49,6 +49,7 @@ public: void addRunningAnimation(AnimationHandlePointer animationHandle); bool isRunningAnimation(AnimationHandlePointer animationHandle); const QList& getRunningAnimations() const { return _runningAnimations; } + void deleteAnimations(); float initJointStates(QVector states, glm::mat4 parentTransform); bool jointStatesEmpty() { return _jointStates.isEmpty(); }; @@ -81,7 +82,7 @@ public: void setJointTransform(int jointIndex, glm::mat4 newTransform); glm::mat4 getJointVisibleTransform(int jointIndex) const; void setJointVisibleTransform(int jointIndex, glm::mat4 newTransform); - void simulateInternal(glm::mat4 parentTransform); + void simulateInternal(float deltaTime, glm::mat4 parentTransform); bool setJointPosition(int jointIndex, const glm::vec3& position, const glm::quat& rotation, bool useRotation, int lastFreeIndex, bool allIntermediatesFree, const glm::vec3& alignment, float priority, const QVector& freeLineage, glm::mat4 parentTransform); diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index af60c91664..bd33e75207 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -1365,18 +1365,13 @@ void Model::updateClusterMatrices() { void Model::simulateInternal(float deltaTime) { // update the world space transforms for all joints - - // update animations - foreach (const AnimationHandlePointer& handle, _runningAnimations) { - handle->simulate(deltaTime); - } const FBXGeometry& geometry = _geometry->getFBXGeometry(); glm::mat4 parentTransform = glm::scale(_scale) * glm::translate(_offset) * geometry.offset; - _rig->simulateInternal(parentTransform); + _rig->simulateInternal(deltaTime, parentTransform); _shapesAreDirty = !_shapes.isEmpty(); - + glm::mat4 modelToWorld = glm::mat4_cast(_rotation); for (int i = 0; i < _meshStates.size(); i++) { MeshState& state = _meshStates[i]; @@ -1512,21 +1507,13 @@ void Model::deleteGeometry() { _rig->clearJointStates(); _meshStates.clear(); clearShapes(); - - for (QSet::iterator it = _animationHandles.begin(); it != _animationHandles.end(); ) { - AnimationHandlePointer handle = it->lock(); - if (handle) { - handle->clearJoints(); - it++; - } else { - it = _animationHandles.erase(it); - } - } - + + _rig->deleteAnimations(); + if (_geometry) { _geometry->clearLoadPriority(this); } - + _blendedBlendshapeCoefficients.clear(); } diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index f8d8cbbd74..30c5211990 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -57,7 +57,7 @@ inline uint qHash(const std::shared_ptr& a, uint seed) { /// A generic 3D model displaying geometry loaded from a URL. class Model : public QObject, public PhysicsEntity { Q_OBJECT - + public: typedef RenderArgs::RenderMode RenderMode; @@ -66,58 +66,7 @@ public: Model(RigPointer rig, QObject* parent = nullptr); virtual ~Model(); - - /// enables/disables scale to fit behavior, the model will be automatically scaled to the specified largest dimension - void setScaleToFit(bool scaleToFit, float largestDimension = 0.0f, bool forceRescale = false); - bool getScaleToFit() const { return _scaleToFit; } /// is scale to fit enabled - bool getIsScaledToFit() const { return _scaledToFit; } /// is model scaled to fit - const glm::vec3& getScaleToFitDimensions() const { return _scaleToFitDimensions; } /// the dimensions model is scaled to - void setScaleToFit(bool scaleToFit, const glm::vec3& dimensions); - void setSnapModelToCenter(bool snapModelToCenter) { - setSnapModelToRegistrationPoint(snapModelToCenter, glm::vec3(0.5f,0.5f,0.5f)); - }; - bool getSnapModelToCenter() { - return _snapModelToRegistrationPoint && _registrationPoint == glm::vec3(0.5f,0.5f,0.5f); - } - - void setSnapModelToRegistrationPoint(bool snapModelToRegistrationPoint, const glm::vec3& registrationPoint); - bool getSnapModelToRegistrationPoint() { return _snapModelToRegistrationPoint; } - - void setScale(const glm::vec3& scale); - const glm::vec3& getScale() const { return _scale; } - - void setOffset(const glm::vec3& offset); - const glm::vec3& getOffset() const { return _offset; } - - void setPupilDilation(float dilation) { _pupilDilation = dilation; } - float getPupilDilation() const { return _pupilDilation; } - - void setBlendshapeCoefficients(const QVector& coefficients) { _blendshapeCoefficients = coefficients; } - const QVector& getBlendshapeCoefficients() const { return _blendshapeCoefficients; } - - bool isActive() const { return _geometry && _geometry->isLoaded(); } - - bool isRenderable() const { return !_meshStates.isEmpty() || (isActive() && _geometry->getMeshes().isEmpty()); } - - void setVisibleInScene(bool newValue, std::shared_ptr scene); - bool isVisible() const { return _isVisible; } - - bool isLoaded() const { return _geometry && _geometry->isLoaded(); } - bool isLoadedWithTextures() const { return _geometry && _geometry->isLoadedWithTextures(); } - - void init(); - void reset(); - virtual void simulate(float deltaTime, bool fullUpdate = true); - - void renderSetup(RenderArgs* args); - - // new Scene/Engine rendering support - bool needsFixupInScene() { return !_readyWhenAdded && readyToAddToScene(); } - bool readyToAddToScene(RenderArgs* renderArgs = nullptr) { return !_needsReload && isRenderable() && isActive() && isLoaded(); } - bool addToScene(std::shared_ptr scene, render::PendingChanges& pendingChanges); - bool addToScene(std::shared_ptr scene, render::PendingChanges& pendingChanges, render::Item::Status::Getters& statusGetters); - void removeFromScene(std::shared_ptr scene, render::PendingChanges& pendingChanges); /// Sets the URL of the model to render. /// \param fallback the URL of a fallback model to render if the requested model fails to load @@ -127,22 +76,127 @@ public: bool retainCurrent = false, bool delayLoad = false); const QUrl& getURL() const { return _url; } + // new Scene/Engine rendering support + void setVisibleInScene(bool newValue, std::shared_ptr scene); + bool needsFixupInScene() { return !_readyWhenAdded && readyToAddToScene(); } + bool readyToAddToScene(RenderArgs* renderArgs = nullptr) { + return !_needsReload && isRenderable() && isActive() && isLoaded(); + } + bool initWhenReady(render::ScenePointer scene); + bool addToScene(std::shared_ptr scene, render::PendingChanges& pendingChanges); + bool addToScene(std::shared_ptr scene, + render::PendingChanges& pendingChanges, + render::Item::Status::Getters& statusGetters); + void removeFromScene(std::shared_ptr scene, render::PendingChanges& pendingChanges); + void renderSetup(RenderArgs* args); + bool isRenderable() const { return !_meshStates.isEmpty() || (isActive() && _geometry->getMeshes().isEmpty()); } + virtual void renderJointCollisionShapes(float alpha); + + bool isVisible() const { return _isVisible; } + + AABox getPartBounds(int meshIndex, int partIndex); + void renderPart(RenderArgs* args, int meshIndex, int partIndex, bool translucent); + + bool maybeStartBlender(); + + /// Sets blended vertices computed in a separate thread. + void setBlendedVertices(int blendNumber, const QWeakPointer& geometry, + const QVector& vertices, const QVector& normals); + + bool isLoaded() const { return _geometry && _geometry->isLoaded(); } + bool isLoadedWithTextures() const { return _geometry && _geometry->isLoadedWithTextures(); } + + void setIsWireframe(bool isWireframe) { _isWireframe = isWireframe; } + bool isWireframe() const { return _isWireframe; } + + void init(); + void reset(); + + void setScaleToFit(bool scaleToFit, const glm::vec3& dimensions); + + void setSnapModelToRegistrationPoint(bool snapModelToRegistrationPoint, const glm::vec3& registrationPoint); + bool getSnapModelToRegistrationPoint() { return _snapModelToRegistrationPoint; } + + virtual void simulate(float deltaTime, bool fullUpdate = true); + + /// Returns a reference to the shared geometry. + const QSharedPointer& getGeometry() const { return _geometry; } + + bool isActive() const { return _geometry && _geometry->isLoaded(); } + + Q_INVOKABLE void setTextureWithNameToURL(const QString& name, const QUrl& url) + { _geometry->setTextureWithNameToURL(name, url); } + + bool convexHullContains(glm::vec3 point); + + QStringList getJointNames() const; + + /// Sets the joint state at the specified index. + void setJointState(int index, bool valid, const glm::quat& rotation = glm::quat(), float priority = 1.0f); + + bool findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const glm::vec3& direction, float& distance, + BoxFace& face, QString& extraInfo, bool pickAgainstTriangles = false); + // Set the model to use for collisions Q_INVOKABLE void setCollisionModelURL(const QUrl& url); const QUrl& getCollisionURL() const { return _collisionUrl; } - - void setIsWireframe(bool isWireframe) { _isWireframe = isWireframe; } - bool isWireframe() const { return _isWireframe; } - + + /// Returns a reference to the shared collision geometry. + const QSharedPointer getCollisionGeometry(bool delayLoad = true); + + void setOffset(const glm::vec3& offset); + const glm::vec3& getOffset() const { return _offset; } + /// Sets the distance parameter used for LOD computations. void setLODDistance(float distance) { _lodDistance = distance; } - + + const QList& getRunningAnimations() const { return _rig->getRunningAnimations(); } + /// Clear the joint animation priority + void clearJointAnimationPriority(int index); + + void setScaleToFit(bool scaleToFit, float largestDimension = 0.0f, bool forceRescale = false); + bool getScaleToFit() const { return _scaleToFit; } /// is scale to fit enabled + + void setSnapModelToCenter(bool snapModelToCenter) { + setSnapModelToRegistrationPoint(snapModelToCenter, glm::vec3(0.5f,0.5f,0.5f)); + }; + bool getSnapModelToCenter() { + return _snapModelToRegistrationPoint && _registrationPoint == glm::vec3(0.5f,0.5f,0.5f); + } + + /// Returns the number of joint states in the model. + int getJointStateCount() const { return _rig->getJointStateCount(); } + bool getJointPositionInWorldFrame(int jointIndex, glm::vec3& position) const; + bool getJointRotationInWorldFrame(int jointIndex, glm::quat& rotation) const; + bool getJointCombinedRotation(int jointIndex, glm::quat& rotation) const; + /// \param jointIndex index of joint in model structure + /// \param rotation[out] rotation of joint in model-frame + /// \return true if joint exists + bool getJointRotation(int jointIndex, glm::quat& rotation) const; + + void inverseKinematics(int jointIndex, glm::vec3 position, const glm::quat& rotation, float priority); + /// Returns the extents of the model in its bind pose. Extents getBindExtents() const; /// Returns the extents of the model's mesh Extents getMeshExtents() const; + void setScale(const glm::vec3& scale); + const glm::vec3& getScale() const { return _scale; } + + /// enables/disables scale to fit behavior, the model will be automatically scaled to the specified largest dimension + bool getIsScaledToFit() const { return _scaledToFit; } /// is model scaled to fit + const glm::vec3& getScaleToFitDimensions() const { return _scaleToFitDimensions; } /// the dimensions model is scaled to + +protected: + + void setPupilDilation(float dilation) { _pupilDilation = dilation; } + float getPupilDilation() const { return _pupilDilation; } + + void setBlendshapeCoefficients(const QVector& coefficients) { _blendshapeCoefficients = coefficients; } + const QVector& getBlendshapeCoefficients() const { return _blendshapeCoefficients; } + /// Returns the unscaled extents of the model's mesh Extents getUnscaledMeshExtents() const; @@ -155,15 +209,6 @@ public: /// Returns the scaled equivalent of a point in model space. glm::vec3 calculateScaledOffsetPoint(const glm::vec3& point) const; - /// Returns a reference to the shared geometry. - const QSharedPointer& getGeometry() const { return _geometry; } - - /// Returns a reference to the shared collision geometry. - const QSharedPointer getCollisionGeometry(bool delayLoad = true); - - /// Returns the number of joint states in the model. - int getJointStateCount() const { return _rig->getJointStateCount(); } - /// Fetches the joint state at the specified index. /// \return whether or not the joint state is "valid" (that is, non-default) bool getJointState(int index, glm::quat& rotation) const; @@ -171,25 +216,15 @@ public: /// Fetches the visible joint state at the specified index. /// \return whether or not the joint state is "valid" (that is, non-default) bool getVisibleJointState(int index, glm::quat& rotation) const; - + /// Clear the joint states void clearJointState(int index); - - /// Clear the joint animation priority - void clearJointAnimationPriority(int index); - - /// Sets the joint state at the specified index. - void setJointState(int index, bool valid, const glm::quat& rotation = glm::quat(), float priority = 1.0f); - + /// Returns the index of the parent of the indexed joint, or -1 if not found. int getParentJointIndex(int jointIndex) const; - + /// Returns the index of the last free ancestor of the indexed joint, or -1 if not found. int getLastFreeJointIndex(int jointIndex) const; - - bool getJointPositionInWorldFrame(int jointIndex, glm::vec3& position) const; - bool getJointRotationInWorldFrame(int jointIndex, glm::quat& rotation) const; - bool getJointCombinedRotation(int jointIndex, glm::quat& rotation) const; bool getVisibleJointPositionInWorldFrame(int jointIndex, glm::vec3& position) const; bool getVisibleJointRotationInWorldFrame(int jointIndex, glm::quat& rotation) const; @@ -199,52 +234,15 @@ public: /// \return true if joint exists bool getJointPosition(int jointIndex, glm::vec3& position) const; - /// \param jointIndex index of joint in model structure - /// \param rotation[out] rotation of joint in model-frame - /// \return true if joint exists - bool getJointRotation(int jointIndex, glm::quat& rotation) const; - - QStringList getJointNames() const; - - AnimationHandlePointer createAnimationHandle(); - - const QList& getRunningAnimations() const { return _runningAnimations; } - // virtual overrides from PhysicsEntity virtual void buildShapes(); virtual void updateShapePositions(); - virtual void renderJointCollisionShapes(float alpha); - - bool maybeStartBlender(); - - /// Sets blended vertices computed in a separate thread. - void setBlendedVertices(int blendNumber, const QWeakPointer& geometry, - const QVector& vertices, const QVector& normals); - void setShowTrueJointTransforms(bool show) { _showTrueJointTransforms = show; } - // QVector& getJointStates() { return _rig->getJointStates(); } - // const QVector& getJointStates() const { return _jointStates; } - - void inverseKinematics(int jointIndex, glm::vec3 position, const glm::quat& rotation, float priority); - - Q_INVOKABLE void setTextureWithNameToURL(const QString& name, const QUrl& url) - { _geometry->setTextureWithNameToURL(name, url); } - - bool findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const glm::vec3& direction, float& distance, - BoxFace& face, QString& extraInfo, bool pickAgainstTriangles = false); - bool convexHullContains(glm::vec3 point); - - AABox getPartBounds(int meshIndex, int partIndex); - void renderPart(RenderArgs* args, int meshIndex, int partIndex, bool translucent); - - bool initWhenReady(render::ScenePointer scene); - -protected: QSharedPointer _geometry; void setGeometry(const QSharedPointer& newGeometry); - + glm::vec3 _scale; glm::vec3 _offset; @@ -257,21 +255,21 @@ protected: bool _snapModelToRegistrationPoint; /// is the model's offset automatically adjusted to a registration point in model space bool _snappedToRegistrationPoint; /// are we currently snapped to a registration point glm::vec3 _registrationPoint = glm::vec3(0.5f); /// the point in model space our center is snapped to - + bool _showTrueJointTransforms; class MeshState { public: QVector clusterMatrices; }; - + QVector _meshStates; - + // returns 'true' if needs fullUpdate after geometry change bool updateGeometry(); virtual void initJointStates(QVector states); - + void setScaleInternal(const glm::vec3& scale); void scaleToFit(); void snapToRegistrationPoint(); @@ -298,11 +296,11 @@ protected: /// the original position /// \return true if the joint was found bool restoreJointPosition(int jointIndex, float fraction = 1.0f, float priority = 0.0f); - + /// Computes and returns the extended length of the limb terminating at the specified joint and starting at the joint's /// first free ancestor. float getLimbLength(int jointIndex) const; - + /// Allow sub classes to force invalidating the bboxes void invalidCalculatedMeshBoxes() { _calculatedMeshBoxesValid = false; @@ -316,28 +314,25 @@ protected: // hook for derived classes to be notified when setUrl invalidates the current model. virtual void onInvalidate() {}; -protected slots: void geometryRefreshed(); - + private: - - friend class AnimationHandle; - + void applyNextGeometry(); void deleteGeometry(); QVector createJointStates(const FBXGeometry& geometry); void initJointTransforms(); - + QSharedPointer _nextGeometry; float _lodDistance; float _lodHysteresis; float _nextLODHysteresis; QSharedPointer _collisionGeometry; - + float _pupilDilation; QVector _blendshapeCoefficients; - + QUrl _url; QUrl _collisionUrl; bool _isVisible; @@ -347,10 +342,6 @@ private: gpu::Batch _renderBatch; QVector > > _dilatedTextures; - - QSet _animationHandles; - - QList _runningAnimations; QVector _blendedBlendshapeCoefficients; int _blendNumber; @@ -375,12 +366,12 @@ private: QHash, AABox> _calculatedMeshPartBoxes; // world coordinate AABoxes for all sub mesh part boxes QHash, qint64> _calculatedMeshPartOffset; bool _calculatedMeshPartOffsetValid; - - + + bool _calculatedMeshPartBoxesValid; QVector _calculatedMeshBoxes; // world coordinate AABoxes for all sub mesh boxes bool _calculatedMeshBoxesValid; - + QVector< QVector > _calculatedMeshTriangles; // world coordinate triangles for all sub meshes bool _calculatedMeshTrianglesValid; QMutex _mutex; @@ -420,10 +411,10 @@ private: IS_SHADOW_FLAG, IS_MIRROR_FLAG, //THis means that the mesh is rendered mirrored, not the same as "Rear view mirror" IS_WIREFRAME_FLAG, - + NUM_FLAGS, }; - + enum Flag { IS_TRANSLUCENT = (1 << IS_TRANSLUCENT_FLAG), HAS_LIGHTMAP = (1 << HAS_LIGHTMAP_FLAG), @@ -489,7 +480,7 @@ private: RenderKey(int bitmask) : _flags(bitmask) {} }; - + class RenderPipeline { public: gpu::PipelinePointer _pipeline; @@ -503,7 +494,7 @@ private: public: typedef RenderKey Key; - + void addRenderPipeline(Key key, gpu::ShaderPointer& vertexShader, gpu::ShaderPointer& pixelShader); void initLocations(gpu::ShaderPointer& program, Locations& locations); @@ -511,8 +502,8 @@ private: static RenderPipelineLib _renderPipelineLib; bool _renderCollisionHull; - - + + QSet> _transparentRenderItems; QSet> _opaqueRenderItems; QMap _renderItems;