diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index 1955b8f0c8..2734cdf01f 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -222,7 +222,6 @@ void Agent::executeScript() { scriptedAvatar->setForceFaceTrackerConnected(true); // call model URL setters with empty URLs so our avatar, if user, will have the default models - scriptedAvatar->setFaceModelURL(QUrl()); scriptedAvatar->setSkeletonModelURL(QUrl()); // give this AvatarData object to the script engine diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 2a94ed30e2..2c53847925 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -296,7 +296,6 @@ bool Avatar::addToScene(AvatarSharedPointer self, std::shared_ptr _renderItemID = scene->allocateID(); pendingChanges.resetItem(_renderItemID, avatarPayloadPointer); _skeletonModel.addToScene(scene, pendingChanges); - getHead()->getFaceModel().addToScene(scene, pendingChanges); for (auto& attachmentModel : _attachmentModels) { attachmentModel->addToScene(scene, pendingChanges); @@ -309,7 +308,6 @@ void Avatar::removeFromScene(AvatarSharedPointer self, std::shared_ptrgetFaceModel().removeFromScene(scene, pendingChanges); for (auto& attachmentModel : _attachmentModels) { attachmentModel->removeFromScene(scene, pendingChanges); } @@ -426,7 +424,7 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) { const float LIGHT_EXPONENT = 1.0f; const float LIGHT_CUTOFF = glm::radians(80.0f); float distance = BASE_LIGHT_DISTANCE * getUniformScale(); - glm::vec3 position = glm::mix(_skeletonModel.getTranslation(), getHead()->getFaceModel().getTranslation(), 0.9f); + glm::vec3 position = _skeletonModel.getTranslation(); glm::quat orientation = getOrientation(); foreach (const AvatarManager::LocalLight& light, DependencyManager::get()->getLocalLights()) { glm::vec3 direction = orientation * light.direction; @@ -543,11 +541,6 @@ void Avatar::fixupModelsInScene() { _skeletonModel.removeFromScene(scene, pendingChanges); _skeletonModel.addToScene(scene, pendingChanges); } - Model& faceModel = getHead()->getFaceModel(); - if (faceModel.isRenderable() && faceModel.needsFixupInScene()) { - faceModel.removeFromScene(scene, pendingChanges); - faceModel.addToScene(scene, pendingChanges); - } for (auto& attachmentModel : _attachmentModels) { if (attachmentModel->isRenderable() && attachmentModel->needsFixupInScene()) { attachmentModel->removeFromScene(scene, pendingChanges); @@ -564,14 +557,7 @@ void Avatar::fixupModelsInScene() { } void Avatar::renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, float glowLevel) { - fixupModelsInScene(); - - { - if (_skeletonModel.isRenderable() && getHead()->getFaceModel().isRenderable()) { - getHead()->render(renderArgs, 1.0f, renderFrustum); - } - } getHead()->renderLookAts(renderArgs); } @@ -872,11 +858,6 @@ void Avatar::scaleVectorRelativeToPosition(glm::vec3 &positionToScale) const { positionToScale = getPosition() + getUniformScale() * (positionToScale - getPosition()); } -void Avatar::setFaceModelURL(const QUrl& faceModelURL) { - AvatarData::setFaceModelURL(faceModelURL); - getHead()->getFaceModel().setURL(_faceModelURL); -} - void Avatar::setSkeletonModelURL(const QUrl& skeletonModelURL) { AvatarData::setSkeletonModelURL(skeletonModelURL); _skeletonModel.setURL(_skeletonModelURL); @@ -1009,17 +990,7 @@ float Avatar::getSkeletonHeight() const { } float Avatar::getHeadHeight() const { - Extents extents = getHead()->getFaceModel().getMeshExtents(); - if (!extents.isEmpty() && extents.isValid()) { - - // HACK: We have a really odd case when fading out for some models where this value explodes - float result = extents.maximum.y - extents.minimum.y; - if (result >= 0.0f && result < 100.0f * getUniformScale() ) { - return result; - } - } - - extents = _skeletonModel.getMeshExtents(); + Extents extents = _skeletonModel.getMeshExtents(); glm::vec3 neckPosition; if (!extents.isEmpty() && extents.isValid() && _skeletonModel.getNeckPosition(neckPosition)) { return extents.maximum.y / 2.0f - neckPosition.y + getPosition().y; diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index 01548c9066..5860760659 100644 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -114,7 +114,6 @@ public: 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; virtual void setAttachmentData(const QVector& attachmentData) override; diff --git a/interface/src/avatar/FaceModel.cpp b/interface/src/avatar/FaceModel.cpp deleted file mode 100644 index 9c22fc17ac..0000000000 --- a/interface/src/avatar/FaceModel.cpp +++ /dev/null @@ -1,58 +0,0 @@ -// -// FaceModel.cpp -// interface/src/avatar -// -// Created by Andrzej Kapolka on 9/16/13. -// Copyright 2013 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include - -#include "Avatar.h" -#include "FaceModel.h" -#include "Head.h" -#include "Menu.h" - -FaceModel::FaceModel(Head* owningHead, RigPointer rig) : - Model(rig, nullptr), - _owningHead(owningHead) -{ - assert(_rig); -} - -void FaceModel::simulate(float deltaTime, bool fullUpdate) { - updateGeometry(); - - Avatar* owningAvatar = static_cast(_owningHead->_owningAvatar); - glm::vec3 neckPosition; - if (!owningAvatar->getSkeletonModel().getNeckPosition(neckPosition)) { - neckPosition = owningAvatar->getPosition(); - } - setTranslation(neckPosition); - glm::quat neckParentRotation = owningAvatar->getOrientation(); - setRotation(neckParentRotation); - setScale(glm::vec3(1.0f, 1.0f, 1.0f) * _owningHead->getScale()); - - setPupilDilation(_owningHead->getPupilDilation()); - setBlendshapeCoefficients(_owningHead->getBlendshapeCoefficients()); - - // FIXME - this is very expensive, we shouldn't do it if we don't have to - //invalidCalculatedMeshBoxes(); - - if (isActive()) { - setOffset(-_geometry->getFBXGeometry().neckPivot); - Model::simulateInternal(deltaTime); - } -} - -bool FaceModel::getEyePositions(glm::vec3& firstEyePosition, glm::vec3& secondEyePosition) const { - if (!isActive()) { - return false; - } - const FBXGeometry& geometry = _geometry->getFBXGeometry(); - return getJointPositionInWorldFrame(geometry.leftEyeJointIndex, firstEyePosition) && - getJointPositionInWorldFrame(geometry.rightEyeJointIndex, secondEyePosition); -} diff --git a/interface/src/avatar/FaceModel.h b/interface/src/avatar/FaceModel.h deleted file mode 100644 index 5a19a8ea29..0000000000 --- a/interface/src/avatar/FaceModel.h +++ /dev/null @@ -1,38 +0,0 @@ -// -// FaceModel.h -// interface/src/avatar -// -// Created by Andrzej Kapolka on 9/16/13. -// Copyright 2013 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_FaceModel_h -#define hifi_FaceModel_h - -#include - -class Head; - -/// A face formed from a linear mix of blendshapes according to a set of coefficients. -class FaceModel : public Model { - Q_OBJECT - -public: - - FaceModel(Head* owningHead, RigPointer rig); - - virtual void simulate(float deltaTime, bool fullUpdate = true); - - /// Retrieve the positions of up to two eye meshes. - /// \return whether or not both eye meshes were found - bool getEyePositions(glm::vec3& firstEyePosition, glm::vec3& secondEyePosition) const; - -private: - - Head* _owningHead; -}; - -#endif // hifi_FaceModel_h diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index b97fd2b0ea..5524b928de 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -62,20 +62,17 @@ Head::Head(Avatar* owningAvatar) : _isLookingAtMe(false), _lookingAtMeStarted(0), _wasLastLookingAtMe(0), - _faceModel(this, std::make_shared()), _leftEyeLookAtID(DependencyManager::get()->allocateID()), _rightEyeLookAtID(DependencyManager::get()->allocateID()) { } void Head::init() { - _faceModel.init(); } void Head::reset() { _baseYaw = _basePitch = _baseRoll = 0.0f; _leanForward = _leanSideways = 0.0f; - _faceModel.reset(); } void Head::simulate(float deltaTime, bool isMine, bool billboard) { @@ -233,12 +230,6 @@ void Head::simulate(float deltaTime, bool isMine, bool billboard) { } _leftEyePosition = _rightEyePosition = getPosition(); - if (!billboard) { - _faceModel.simulate(deltaTime); - if (!_faceModel.getEyePositions(_leftEyePosition, _rightEyePosition)) { - static_cast(_owningAvatar)->getSkeletonModel().getEyePositions(_leftEyePosition, _rightEyePosition); - } - } _eyePosition = calculateAverageEyePosition(); } @@ -411,7 +402,7 @@ glm::quat Head::getEyeRotation(const glm::vec3& eyePosition) const { } glm::vec3 Head::getScalePivot() const { - return _faceModel.isActive() ? _faceModel.getTranslation() : _position; + return _position; } void Head::setFinalPitch(float finalPitch) { diff --git a/interface/src/avatar/Head.h b/interface/src/avatar/Head.h index 614e286329..d0bd4fdb77 100644 --- a/interface/src/avatar/Head.h +++ b/interface/src/avatar/Head.h @@ -18,7 +18,6 @@ #include -#include "FaceModel.h" #include "world.h" @@ -76,9 +75,6 @@ public: glm::vec3 getLeftEarPosition() const { return _leftEyePosition + (getRightDirection() * -EYE_EAR_GAP) + (getFrontDirection() * -EYE_EAR_GAP); } glm::vec3 getMouthPosition() const { return _eyePosition - getUpDirection() * glm::length(_rightEyePosition - _leftEyePosition); } - FaceModel& getFaceModel() { return _faceModel; } - const FaceModel& getFaceModel() const { return _faceModel; } - bool getReturnToCenter() const { return _returnHeadToCenter; } // Do you want head to try to return to center (depends on interface detected) float getAverageLoudness() const { return _averageLoudness; } /// \return the point about which scaling occurs. @@ -150,7 +146,6 @@ private: bool _isLookingAtMe; quint64 _lookingAtMeStarted; quint64 _wasLastLookingAtMe; - FaceModel _faceModel; glm::vec3 _correctedLookAtPosition; @@ -162,8 +157,6 @@ private: void renderLookatTarget(RenderArgs* renderArgs, glm::vec3 lookatPosition); void calculateMouthShapes(); void applyEyelidOffset(glm::quat headOrientation); - - friend class FaceModel; }; #endif // hifi_Head_h diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 7198f32422..fa8e94e4a4 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -167,11 +167,6 @@ MyAvatar::MyAvatar(RigPointer rig) : } auto recordingInterface = DependencyManager::get(); - if (recordingInterface->getPlayerUseHeadModel() && dummyAvatar.getFaceModelURL().isValid() && - (dummyAvatar.getFaceModelURL() != getFaceModelURL())) { - // FIXME - //myAvatar->setFaceModelURL(_dummyAvatar.getFaceModelURL()); - } if (recordingInterface->getPlayerUseSkeletonModel() && dummyAvatar.getSkeletonModelURL().isValid() && (dummyAvatar.getSkeletonModelURL() != getSkeletonModelURL())) { @@ -1009,13 +1004,6 @@ void MyAvatar::clearJointsData() { _rig->clearJointStates(); } -void MyAvatar::setFaceModelURL(const QUrl& faceModelURL) { - - Avatar::setFaceModelURL(faceModelURL); - render::ScenePointer scene = qApp->getMain3DScene(); - getHead()->getFaceModel().setVisibleInScene(_prevShouldDrawHead, scene); -} - void MyAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) { Avatar::setSkeletonModelURL(skeletonModelURL); @@ -1051,10 +1039,6 @@ void MyAvatar::useFullAvatarURL(const QUrl& fullAvatarURL, const QString& modelN } } - if (!getFaceModelURLString().isEmpty()) { - setFaceModelURL(QString()); - } - const QString& urlString = fullAvatarURL.toString(); if (urlString.isEmpty() || (fullAvatarURL != getSkeletonModelURL())) { qApp->setRawAvatarUpdateThreading(false); diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 37a2e752e6..79cad466e6 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -178,8 +178,6 @@ public: Q_INVOKABLE float getHeadFinalRoll() const { return getHead()->getFinalRoll(); } Q_INVOKABLE float getHeadFinalPitch() const { return getHead()->getFinalPitch(); } Q_INVOKABLE float getHeadDeltaPitch() const { return getHead()->getDeltaPitch(); } - Q_INVOKABLE int getFaceBlendCoefNum() const { return getHead()->getFaceModel().getBlendshapeCoefficientsNum(); } - Q_INVOKABLE float getFaceBlendCoef(int index) const { return getHead()->getFaceModel().getBlendshapeCoefficient(index); } Q_INVOKABLE glm::vec3 getEyePosition() const { return getHead()->getEyePosition(); } @@ -328,7 +326,6 @@ private: bool cameraInsideHead() const; // These are made private for MyAvatar so that you will use the "use" methods instead - virtual void setFaceModelURL(const QUrl& faceModelURL) override; virtual void setSkeletonModelURL(const QUrl& skeletonModelURL) override; void setVisibleInSceneIfReady(Model* model, render::ScenePointer scene, bool visiblity); diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index adb942417d..9ab6b3b89c 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -57,7 +57,6 @@ AvatarData::AvatarData() : _hasNewJointRotations(true), _hasNewJointTranslations(true), _headData(NULL), - _faceModelURL("http://invalid.com"), _displayNameTargetAlpha(1.0f), _displayNameAlpha(1.0f), _billboard(), @@ -989,18 +988,14 @@ bool AvatarData::hasIdentityChangedAfterParsing(const QByteArray& data) { QDataStream packetStream(data); QUuid avatarUUID; - QUrl faceModelURL, skeletonModelURL; + QUrl unusedModelURL; // legacy faceModel support + QUrl skeletonModelURL; QVector attachmentData; QString displayName; - packetStream >> avatarUUID >> faceModelURL >> skeletonModelURL >> attachmentData >> displayName; + packetStream >> avatarUUID >> unusedModelURL >> skeletonModelURL >> attachmentData >> displayName; bool hasIdentityChanged = false; - if (faceModelURL != _faceModelURL) { - setFaceModelURL(faceModelURL); - hasIdentityChanged = true; - } - if (skeletonModelURL != _skeletonModelURL) { setSkeletonModelURL(skeletonModelURL); hasIdentityChanged = true; @@ -1025,7 +1020,9 @@ QByteArray AvatarData::identityByteArray() { QUrl emptyURL(""); const QUrl& urlToSend = (_skeletonModelURL == AvatarData::defaultFullAvatarModelUrl()) ? emptyURL : _skeletonModelURL; - identityStream << QUuid() << _faceModelURL << urlToSend << _attachmentData << _displayName; + QUrl unusedModelURL("http://invalid.com"); // legacy faceModel support + + identityStream << QUuid() << unusedModelURL << urlToSend << _attachmentData << _displayName; return identityData; } @@ -1038,12 +1035,6 @@ bool AvatarData::hasBillboardChangedAfterParsing(const QByteArray& data) { return true; } -void AvatarData::setFaceModelURL(const QUrl& faceModelURL) { - _faceModelURL = faceModelURL; - - qCDebug(avatars) << "Changing face model for avatar to" << _faceModelURL.toString(); -} - void AvatarData::setSkeletonModelURL(const QUrl& skeletonModelURL) { const QUrl& expanded = skeletonModelURL.isEmpty() ? AvatarData::defaultFullAvatarModelUrl() : skeletonModelURL; if (expanded == _skeletonModelURL) { @@ -1445,9 +1436,6 @@ JointData jointDataFromJsonValue(const QJsonValue& json) { QJsonObject AvatarData::toJson() const { QJsonObject root; - if (!getFaceModelURL().isEmpty()) { - root[JSON_AVATAR_HEAD_MODEL] = getFaceModelURL().toString(); - } if (!getSkeletonModelURL().isEmpty()) { root[JSON_AVATAR_BODY_MODEL] = getSkeletonModelURL().toString(); } @@ -1514,15 +1502,6 @@ void AvatarData::fromJson(const QJsonObject& json) { _headData->fromJson(json[JSON_AVATAR_HEAD].toObject()); } - if (json.contains(JSON_AVATAR_HEAD_MODEL)) { - auto faceModelURL = json[JSON_AVATAR_HEAD_MODEL].toString(); - if (faceModelURL != getFaceModelURL().toString()) { - QUrl faceModel(faceModelURL); - if (faceModel.isValid()) { - setFaceModelURL(faceModel); - } - } - } if (json.contains(JSON_AVATAR_BODY_MODEL)) { auto bodyModelURL = json[JSON_AVATAR_BODY_MODEL].toString(); if (bodyModelURL != getSkeletonModelURL().toString()) { diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 6ffcaed0da..25ee93485b 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -158,7 +158,6 @@ class AvatarData : public QObject, public SpatiallyNestable { Q_PROPERTY(float audioAverageLoudness READ getAudioAverageLoudness WRITE setAudioAverageLoudness) Q_PROPERTY(QString displayName READ getDisplayName WRITE setDisplayName) - Q_PROPERTY(QString faceModelURL READ getFaceModelURLFromScript WRITE setFaceModelURLFromScript) Q_PROPERTY(QString skeletonModelURL READ getSkeletonModelURLFromScript WRITE setSkeletonModelURLFromScript) Q_PROPERTY(QVector attachmentData READ getAttachmentData WRITE setAttachmentData) Q_PROPERTY(QString billboardURL READ getBillboardURL WRITE setBillboardFromURL) @@ -296,11 +295,8 @@ public: bool hasBillboardChangedAfterParsing(const QByteArray& data); - const QUrl& getFaceModelURL() const { return _faceModelURL; } - QString getFaceModelURLString() const { return _faceModelURL.toString(); } const QUrl& getSkeletonModelURL() const { return _skeletonModelURL; } const QString& getDisplayName() const { return _displayName; } - virtual void setFaceModelURL(const QUrl& faceModelURL); virtual void setSkeletonModelURL(const QUrl& skeletonModelURL); virtual void setDisplayName(const QString& displayName); @@ -322,9 +318,6 @@ public: void setBillboardFromURL(const QString& billboardURL); const QString& getBillboardURL() { return _billboardURL; } - QString getFaceModelURLFromScript() const { return _faceModelURL.toString(); } - void setFaceModelURLFromScript(const QString& faceModelString) { setFaceModelURL(faceModelString); } - QString getSkeletonModelURLFromScript() const { return _skeletonModelURL.toString(); } void setSkeletonModelURLFromScript(const QString& skeletonModelString) { setSkeletonModelURL(QUrl(skeletonModelString)); } @@ -383,7 +376,6 @@ protected: HeadData* _headData; - QUrl _faceModelURL; // These need to be empty so that on first time setting them they will not short circuit QUrl _skeletonModelURL; // These need to be empty so that on first time setting them they will not short circuit QUrl _skeletonFBXURL; QVector _attachmentData; diff --git a/libraries/avatars/src/AvatarHashMap.cpp b/libraries/avatars/src/AvatarHashMap.cpp index ef7ff9684a..75fb5e6028 100644 --- a/libraries/avatars/src/AvatarHashMap.cpp +++ b/libraries/avatars/src/AvatarHashMap.cpp @@ -122,10 +122,6 @@ void AvatarHashMap::processAvatarIdentityPacket(QSharedPointer // mesh URL for a UUID, find avatar in our list auto avatar = newOrExistingAvatar(sessionUUID, sendingNode); - if (avatar->getFaceModelURL() != faceMeshURL) { - avatar->setFaceModelURL(faceMeshURL); - } - if (avatar->getSkeletonModelURL().isEmpty() || (avatar->getSkeletonModelURL() != skeletonURL)) { avatar->setSkeletonModelURL(skeletonURL); // Will expand "" to default and so will not continuously fire } diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index ece43f3ab3..3285a1c661 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -419,7 +419,7 @@ const FBXGeometry* EntityTreeRenderer::getGeometryForEntity(EntityItemPointer en std::shared_ptr modelEntityItem = std::dynamic_pointer_cast(entityItem); assert(modelEntityItem); // we need this!!! - Model* model = modelEntityItem->getModel(this); + ModelPointer model = modelEntityItem->getModel(this); if (model) { result = &model->getGeometry()->getFBXGeometry(); } @@ -427,8 +427,8 @@ const FBXGeometry* EntityTreeRenderer::getGeometryForEntity(EntityItemPointer en return result; } -const Model* EntityTreeRenderer::getModelForEntityItem(EntityItemPointer entityItem) { - const Model* result = NULL; +ModelPointer EntityTreeRenderer::getModelForEntityItem(EntityItemPointer entityItem) { + ModelPointer result = nullptr; if (entityItem->getType() == EntityTypes::Model) { std::shared_ptr modelEntityItem = std::dynamic_pointer_cast(entityItem); @@ -444,7 +444,7 @@ const FBXGeometry* EntityTreeRenderer::getCollisionGeometryForEntity(EntityItemP std::shared_ptr modelEntityItem = std::dynamic_pointer_cast(entityItem); if (modelEntityItem->hasCompoundShapeURL()) { - Model* model = modelEntityItem->getModel(this); + ModelPointer model = modelEntityItem->getModel(this); if (model) { const QSharedPointer collisionNetworkGeometry = model->getCollisionGeometry(); if (collisionNetworkGeometry && collisionNetworkGeometry->isLoaded()) { @@ -460,25 +460,25 @@ void EntityTreeRenderer::processEraseMessage(ReceivedMessage& message, const Sha std::static_pointer_cast(_tree)->processEraseMessage(message, sourceNode); } -Model* EntityTreeRenderer::allocateModel(const QString& url, const QString& collisionUrl) { - Model* model = NULL; +ModelPointer EntityTreeRenderer::allocateModel(const QString& url, const QString& collisionUrl) { + ModelPointer model = nullptr; // Make sure we only create and delete models on the thread that owns the EntityTreeRenderer if (QThread::currentThread() != thread()) { QMetaObject::invokeMethod(this, "allocateModel", Qt::BlockingQueuedConnection, - Q_RETURN_ARG(Model*, model), + Q_RETURN_ARG(ModelPointer, model), Q_ARG(const QString&, url)); return model; } - model = new Model(std::make_shared()); + model = std::make_shared(std::make_shared()); model->init(); model->setURL(QUrl(url)); model->setCollisionModelURL(QUrl(collisionUrl)); return model; } -Model* EntityTreeRenderer::updateModel(Model* original, const QString& newUrl, const QString& collisionUrl) { - Model* model = NULL; +ModelPointer EntityTreeRenderer::updateModel(ModelPointer original, const QString& newUrl, const QString& collisionUrl) { + ModelPointer model = nullptr; // The caller shouldn't call us if the URL doesn't need to change. But if they // do, we just return their original back to them. @@ -489,8 +489,8 @@ Model* EntityTreeRenderer::updateModel(Model* original, const QString& newUrl, c // Before we do any creating or deleting, make sure we're on our renderer thread if (QThread::currentThread() != thread()) { QMetaObject::invokeMethod(this, "updateModel", Qt::BlockingQueuedConnection, - Q_RETURN_ARG(Model*, model), - Q_ARG(Model*, original), + Q_RETURN_ARG(ModelPointer, model), + Q_ARG(ModelPointer, original), Q_ARG(const QString&, newUrl)); return model; @@ -499,11 +499,11 @@ Model* EntityTreeRenderer::updateModel(Model* original, const QString& newUrl, c // at this point we know we need to replace the model, and we know we're on the // correct thread, so we can do all our work. if (original) { - delete original; // delete the old model... + original.reset(); // delete the old model... } // create the model and correctly initialize it with the new url - model = new Model(std::make_shared()); + model = std::make_shared(std::make_shared()); model->init(); model->setURL(QUrl(newUrl)); model->setCollisionModelURL(QUrl(collisionUrl)); @@ -511,19 +511,19 @@ Model* EntityTreeRenderer::updateModel(Model* original, const QString& newUrl, c return model; } -void EntityTreeRenderer::releaseModel(Model* model) { +void EntityTreeRenderer::releaseModel(ModelPointer model) { // If we're not on the renderer's thread, then remember this model to be deleted later if (QThread::currentThread() != thread()) { _releasedModels << model; } else { // otherwise just delete it right away - delete model; + model.reset(); } } void EntityTreeRenderer::deleteReleasedModels() { if (_releasedModels.size() > 0) { - foreach(Model* model, _releasedModels) { - delete model; + foreach(ModelPointer model, _releasedModels) { + model.reset(); } _releasedModels.clear(); } diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.h b/libraries/entities-renderer/src/EntityTreeRenderer.h index 8534be852d..095723dc9a 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.h +++ b/libraries/entities-renderer/src/EntityTreeRenderer.h @@ -29,6 +29,9 @@ class Model; class ScriptEngine; class ZoneEntityItem; +class Model; +using ModelPointer = std::shared_ptr; +using ModelWeakPointer = std::weak_ptr; // Generic client side Octree renderer class. class EntityTreeRenderer : public OctreeRenderer, public EntityItemFBXService, public Dependency { @@ -53,7 +56,7 @@ public: virtual void init(); virtual const FBXGeometry* getGeometryForEntity(EntityItemPointer entityItem); - virtual const Model* getModelForEntityItem(EntityItemPointer entityItem); + virtual ModelPointer getModelForEntityItem(EntityItemPointer entityItem); virtual const FBXGeometry* getCollisionGeometryForEntity(EntityItemPointer entityItem); /// clears the tree @@ -63,13 +66,13 @@ public: void reloadEntityScripts(); /// if a renderable entity item needs a model, we will allocate it for them - Q_INVOKABLE Model* allocateModel(const QString& url, const QString& collisionUrl); + Q_INVOKABLE ModelPointer allocateModel(const QString& url, const QString& collisionUrl); /// if a renderable entity item needs to update the URL of a model, we will handle that for the entity - Q_INVOKABLE Model* updateModel(Model* original, const QString& newUrl, const QString& collisionUrl); + Q_INVOKABLE ModelPointer updateModel(ModelPointer original, const QString& newUrl, const QString& collisionUrl); /// if a renderable entity item is done with a model, it should return it to us - void releaseModel(Model* model); + void releaseModel(ModelPointer model); void deleteReleasedModels(); @@ -129,7 +132,7 @@ private: void applyZonePropertiesToScene(std::shared_ptr zone); void checkAndCallPreload(const EntityItemID& entityID, const bool reload = false); - QList _releasedModels; + QList _releasedModels; RayToEntityIntersectionResult findRayIntersectionWorker(const PickRay& ray, Octree::lockType lockType, bool precisionPicking, const QVector& entityIdsToInclude = QVector(), const QVector& entityIdsToDiscard = QVector()); diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index e2c7bb56c1..ff4ed28150 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -463,8 +463,8 @@ void RenderableModelEntityItem::render(RenderArgs* args) { } } -Model* RenderableModelEntityItem::getModel(EntityTreeRenderer* renderer) { - Model* result = NULL; +ModelPointer RenderableModelEntityItem::getModel(EntityTreeRenderer* renderer) { + ModelPointer result = nullptr; if (!renderer) { return result; @@ -506,7 +506,7 @@ Model* RenderableModelEntityItem::getModel(EntityTreeRenderer* renderer) { // release interest _myRenderer->releaseModel(_model); - result = _model = NULL; + result = _model = nullptr; _needsInitialSimulation = true; } diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index 69c1c13151..03226342da 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -57,7 +57,7 @@ public: BoxFace& face, glm::vec3& surfaceNormal, void** intersectedObject, bool precisionPicking) const override; - Model* getModel(EntityTreeRenderer* renderer); + ModelPointer getModel(EntityTreeRenderer* renderer); virtual bool needsToCallUpdate() const override; virtual void update(const quint64& now) override; @@ -87,7 +87,7 @@ private: QVariantMap parseTexturesToMap(QString textures); void remapTextures(); - Model* _model = nullptr; + ModelPointer _model = nullptr; bool _needsInitialSimulation = true; bool _needsModelReload = true; EntityTreeRenderer* _myRenderer = nullptr; diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index 1c5a696b17..677ab93b79 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -25,6 +25,9 @@ typedef std::shared_ptr EntityTreePointer; #include "DeleteEntityOperator.h" class Model; +using ModelPointer = std::shared_ptr; +using ModelWeakPointer = std::weak_ptr; + class EntitySimulation; class NewlyCreatedEntityHook { @@ -35,7 +38,7 @@ public: class EntityItemFBXService { public: virtual const FBXGeometry* getGeometryForEntity(EntityItemPointer entityItem) = 0; - virtual const Model* getModelForEntityItem(EntityItemPointer entityItem) = 0; + virtual ModelPointer getModelForEntityItem(EntityItemPointer entityItem) = 0; virtual const FBXGeometry* getCollisionGeometryForEntity(EntityItemPointer entityItem) = 0; }; @@ -171,7 +174,7 @@ public: const FBXGeometry* getGeometryForEntity(EntityItemPointer entityItem) { return _fbxService ? _fbxService->getGeometryForEntity(entityItem) : NULL; } - const Model* getModelForEntityItem(EntityItemPointer entityItem) { + ModelPointer getModelForEntityItem(EntityItemPointer entityItem) { return _fbxService ? _fbxService->getModelForEntityItem(entityItem) : NULL; } diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index a63cf78393..09aa4d5f59 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -48,9 +48,11 @@ QStringList FBXGeometry::getJointNames() const { } bool FBXGeometry::hasBlendedMeshes() const { - foreach (const FBXMesh& mesh, meshes) { - if (!mesh.blendshapes.isEmpty()) { - return true; + if (!meshes.isEmpty()) { + foreach (const FBXMesh& mesh, meshes) { + if (!mesh.blendshapes.isEmpty()) { + return true; + } } } return false; diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index e90d51813b..58189c0d1e 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -50,8 +50,13 @@ inline uint qHash(const std::shared_ptr& a, uint seed) { return qHash(a.get(), seed); } +class Model; +using ModelPointer = std::shared_ptr; +using ModelWeakPointer = std::weak_ptr; + + /// A generic 3D model displaying geometry loaded from a URL. -class Model : public QObject { +class Model : public QObject, public std::enable_shared_from_this { Q_OBJECT public: @@ -63,6 +68,9 @@ public: Model(RigPointer rig, QObject* parent = nullptr); virtual ~Model(); + inline ModelPointer getThisPointer() const { + return std::static_pointer_cast(std::const_pointer_cast(shared_from_this())); + } /// Sets the URL of the model to render. Q_INVOKABLE void setURL(const QUrl& url);