diff --git a/libraries/model-networking/src/model-networking/ModelCache.cpp b/libraries/model-networking/src/model-networking/ModelCache.cpp index 40388e6123..afe86e0d1e 100644 --- a/libraries/model-networking/src/model-networking/ModelCache.cpp +++ b/libraries/model-networking/src/model-networking/ModelCache.cpp @@ -70,7 +70,7 @@ void GeometryMappingResource::downloadFinished(const QByteArray& data) { auto modelCache = DependencyManager::get(); GeometryExtra extra{ mapping, _textureBaseUrl }; - // Get the raw GeometryResource, not the wrapped NetworkGeometry + // Get the raw GeometryResource _geometryResource = modelCache->getResource(url, QUrl(), &extra).staticCast(); // Avoid caching nested resources - their references will be held by the parent _geometryResource->_isCacheable = false; @@ -90,8 +90,8 @@ void GeometryMappingResource::downloadFinished(const QByteArray& data) { void GeometryMappingResource::onGeometryMappingLoaded(bool success) { if (success && _geometryResource) { - _geometry = _geometryResource->_geometry; - _shapes = _geometryResource->_shapes; + _fbxGeometry = _geometryResource->_fbxGeometry; + _meshParts = _geometryResource->_meshParts; _meshes = _geometryResource->_meshes; _materials = _geometryResource->_materials; @@ -200,31 +200,31 @@ void GeometryDefinitionResource::downloadFinished(const QByteArray& data) { void GeometryDefinitionResource::setGeometryDefinition(FBXGeometry::Pointer fbxGeometry) { // Assume ownership of the geometry pointer - _geometry = fbxGeometry; + _fbxGeometry = fbxGeometry; // Copy materials QHash materialIDAtlas; - for (const FBXMaterial& material : _geometry->materials) { + for (const FBXMaterial& material : _fbxGeometry->materials) { materialIDAtlas[material.materialID] = _materials.size(); _materials.push_back(std::make_shared(material, _textureBaseUrl)); } - std::shared_ptr meshes = std::make_shared(); - std::shared_ptr shapes = std::make_shared(); + std::shared_ptr meshes = std::make_shared(); + std::shared_ptr shapes = std::make_shared(); int meshID = 0; - for (const FBXMesh& mesh : _geometry->meshes) { + for (const FBXMesh& mesh : _fbxGeometry->meshes) { // Copy mesh pointers meshes->emplace_back(mesh._mesh); int partID = 0; for (const FBXMeshPart& part : mesh.parts) { // Construct local shapes - shapes->push_back(std::make_shared(meshID, partID, (int)materialIDAtlas[part.materialID])); + shapes->push_back(std::make_shared(meshID, partID, (int)materialIDAtlas[part.materialID])); partID++; } meshID++; } _meshes = meshes; - _shapes = shapes; + _meshParts = shapes; finishedLoading(true); } @@ -250,17 +250,15 @@ QSharedPointer ModelCache::createResource(const QUrl& url, const QShar return QSharedPointer(resource, &Resource::deleter); } -std::shared_ptr ModelCache::getGeometry(const QUrl& url, const QVariantHash& mapping, const QUrl& textureBaseUrl) { +GeometryResource::Pointer ModelCache::fetchResource(const QUrl& url, const QVariantHash& mapping, const QUrl& textureBaseUrl) { GeometryExtra geometryExtra = { mapping, textureBaseUrl }; GeometryResource::Pointer resource = getResource(url, QUrl(), &geometryExtra).staticCast(); if (resource) { if (resource->isLoaded() && resource->shouldSetTextures()) { resource->setTextures(); } - return std::make_shared(resource); - } else { - return NetworkGeometry::Pointer(); } + return resource; } const QVariantMap Geometry::getTextures() const { @@ -278,9 +276,9 @@ const QVariantMap Geometry::getTextures() const { // FIXME: The materials should only be copied when modified, but the Model currently caches the original Geometry::Geometry(const Geometry& geometry) { - _geometry = geometry._geometry; + _fbxGeometry = geometry._fbxGeometry; _meshes = geometry._meshes; - _shapes = geometry._shapes; + _meshParts = geometry._meshParts; _materials.reserve(geometry._materials.size()); for (const auto& material : geometry._materials) { @@ -337,8 +335,8 @@ bool Geometry::areTexturesLoaded() const { } const std::shared_ptr Geometry::getShapeMaterial(int shapeID) const { - if ((shapeID >= 0) && (shapeID < (int)_shapes->size())) { - int materialID = _shapes->at(shapeID)->materialID; + if ((shapeID >= 0) && (shapeID < (int)_meshParts->size())) { + int materialID = _meshParts->at(shapeID)->materialID; if ((materialID >= 0) && (materialID < (int)_materials.size())) { return _materials[materialID]; } @@ -352,7 +350,7 @@ void GeometryResource::deleter() { } void GeometryResource::setTextures() { - for (const FBXMaterial& material : _geometry->materials) { + for (const FBXMaterial& material : _fbxGeometry->materials) { _materials.push_back(std::make_shared(material, _textureBaseUrl)); } } @@ -361,26 +359,40 @@ void GeometryResource::resetTextures() { _materials.clear(); } -NetworkGeometry::NetworkGeometry(const GeometryResource::Pointer& networkGeometry) : _resource(networkGeometry) { - connect(_resource.data(), &Resource::finished, this, &NetworkGeometry::resourceFinished); - connect(_resource.data(), &Resource::onRefresh, this, &NetworkGeometry::resourceRefreshed); +void GeometryResourceWatcher::startWatching() { + connect(_resource.data(), &Resource::finished, this, &GeometryResourceWatcher::resourceFinished); + connect(_resource.data(), &Resource::onRefresh, this, &GeometryResourceWatcher::resourceRefreshed); if (_resource->isLoaded()) { resourceFinished(!_resource->getURL().isEmpty()); } } -void NetworkGeometry::resourceFinished(bool success) { - // FIXME: Model is not set up to handle a refresh - if (_instance) { - return; - } - if (success) { - _instance = std::make_shared(*_resource); - } - emit finished(success); +void GeometryResourceWatcher::stopWatching() { + disconnect(_resource.data(), &Resource::finished, this, &GeometryResourceWatcher::resourceFinished); + disconnect(_resource.data(), &Resource::onRefresh, this, &GeometryResourceWatcher::resourceRefreshed); } -void NetworkGeometry::resourceRefreshed() { +void GeometryResourceWatcher::setResource(GeometryResource::Pointer resource) { + if (_resource) { + stopWatching(); + } + _resource = resource; + if (_resource) { + if (_resource->isLoaded()) { + _geometryRef = std::make_shared(*_resource); + } else { + startWatching(); + } + } +} + +void GeometryResourceWatcher::resourceFinished(bool success) { + if (success) { + _geometryRef = std::make_shared(*_resource); + } +} + +void GeometryResourceWatcher::resourceRefreshed() { // FIXME: Model is not set up to handle a refresh // _instance.reset(); } diff --git a/libraries/model-networking/src/model-networking/ModelCache.h b/libraries/model-networking/src/model-networking/ModelCache.h index f15e1106e2..c450f96846 100644 --- a/libraries/model-networking/src/model-networking/ModelCache.h +++ b/libraries/model-networking/src/model-networking/ModelCache.h @@ -22,52 +22,30 @@ #include "TextureCache.h" // Alias instead of derive to avoid copying -using NetworkMesh = model::Mesh; class NetworkTexture; class NetworkMaterial; -class NetworkShape; -class NetworkGeometry; +class MeshPart; class GeometryMappingResource; -/// Stores cached model geometries. -class ModelCache : public ResourceCache, public Dependency { - Q_OBJECT - SINGLETON_DEPENDENCY - -public: - /// Loads a model geometry from the specified URL. - std::shared_ptr getGeometry(const QUrl& url, - const QVariantHash& mapping = QVariantHash(), const QUrl& textureBaseUrl = QUrl()); - -protected: - friend class GeometryMappingResource; - - virtual QSharedPointer createResource(const QUrl& url, const QSharedPointer& fallback, - const void* extra); - -private: - ModelCache(); - virtual ~ModelCache() = default; -}; - class Geometry { public: using Pointer = std::shared_ptr; + using WeakPointer = std::weak_ptr; Geometry() = default; Geometry(const Geometry& geometry); // Immutable over lifetime - using NetworkMeshes = std::vector>; - using NetworkShapes = std::vector>; + using GeometryMeshes = std::vector>; + using GeometryMeshParts = std::vector>; // Mutable, but must retain structure of vector using NetworkMaterials = std::vector>; - const FBXGeometry& getGeometry() const { return *_geometry; } - const NetworkMeshes& getMeshes() const { return *_meshes; } + const FBXGeometry& getFBXGeometry() const { return *_fbxGeometry; } + const GeometryMeshes& getMeshes() const { return *_meshes; } const std::shared_ptr getShapeMaterial(int shapeID) const; const QVariantMap getTextures() const; @@ -79,9 +57,9 @@ protected: friend class GeometryMappingResource; // Shared across all geometries, constant throughout lifetime - std::shared_ptr _geometry; - std::shared_ptr _meshes; - std::shared_ptr _shapes; + std::shared_ptr _fbxGeometry; + std::shared_ptr _meshes; + std::shared_ptr _meshParts; // Copied to each geometry, mutable throughout lifetime via setTextures NetworkMaterials _materials; @@ -108,7 +86,7 @@ protected: // Geometries may not hold onto textures while cached - that is for the texture cache // Instead, these methods clear and reset textures from the geometry when caching/loading - bool shouldSetTextures() const { return _geometry && _materials.empty(); } + bool shouldSetTextures() const { return _fbxGeometry && _materials.empty(); } void setTextures(); void resetTextures(); @@ -118,22 +96,21 @@ protected: bool _isCacheable { true }; }; -class NetworkGeometry : public QObject { +class GeometryResourceWatcher : public QObject { Q_OBJECT public: - using Pointer = std::shared_ptr; + using Pointer = std::shared_ptr; - NetworkGeometry() = delete; - NetworkGeometry(const GeometryResource::Pointer& networkGeometry); + GeometryResourceWatcher() = delete; + GeometryResourceWatcher(Geometry::Pointer& geometryPtr) : _geometryRef(geometryPtr) {} - const QUrl& getURL() { return _resource->getURL(); } + void setResource(GeometryResource::Pointer resource); - /// Returns the geometry, if it is loaded (must be checked!) - const Geometry::Pointer& getGeometry() { return _instance; } + const QUrl& getURL() const { return _resource->getURL(); } -signals: - /// Emitted when the NetworkGeometry loads (or fails to) - void finished(bool success); +private: + void startWatching(); + void stopWatching(); private slots: void resourceFinished(bool success); @@ -141,7 +118,27 @@ private slots: private: GeometryResource::Pointer _resource; - Geometry::Pointer _instance { nullptr }; + Geometry::Pointer& _geometryRef; +}; + +/// Stores cached model geometries. +class ModelCache : public ResourceCache, public Dependency { + Q_OBJECT + SINGLETON_DEPENDENCY + +public: + GeometryResource::Pointer fetchResource(const QUrl& url, + const QVariantHash& mapping = QVariantHash(), const QUrl& textureBaseUrl = QUrl()); + +protected: + friend class GeometryMappingResource; + + virtual QSharedPointer createResource(const QUrl& url, const QSharedPointer& fallback, + const void* extra); + +private: + ModelCache(); + virtual ~ModelCache() = default; }; class NetworkMaterial : public model::Material { @@ -185,9 +182,9 @@ private: bool _isOriginal { true }; }; -class NetworkShape { +class MeshPart { public: - NetworkShape(int mesh, int part, int material) : meshID { mesh }, partID { part }, materialID { material } {} + MeshPart(int mesh, int part, int material) : meshID { mesh }, partID { part }, materialID { material } {} int meshID { -1 }; int partID { -1 }; int materialID { -1 }; diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 08c8dc23b4..4746b5a0c5 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -310,7 +310,7 @@ ModelMeshPartPayload::ModelMeshPartPayload(Model* model, int _meshIndex, int par _shapeID(shapeIndex) { assert(_model && _model->isLoaded()); - auto& modelMesh = _model->getGeometry()->getGeometry()->getMeshes().at(_meshIndex); + auto& modelMesh = _model->getGeometry()->getMeshes().at(_meshIndex); updateMeshPart(modelMesh, partIndex); updateTransform(transform, offsetTransform); @@ -331,7 +331,7 @@ void ModelMeshPartPayload::initCache() { _isBlendShaped = !mesh.blendshapes.isEmpty(); } - auto networkMaterial = _model->getGeometry()->getGeometry()->getShapeMaterial(_shapeID); + auto networkMaterial = _model->getGeometry()->getShapeMaterial(_shapeID); if (networkMaterial) { _drawMaterial = networkMaterial; }; @@ -384,7 +384,7 @@ ItemKey ModelMeshPartPayload::getKey() const { ShapeKey ModelMeshPartPayload::getShapeKey() const { assert(_model->isLoaded()); const FBXGeometry& geometry = _model->getFBXGeometry(); - const auto& networkMeshes = _model->getGeometry()->getGeometry()->getMeshes(); + const auto& networkMeshes = _model->getGeometry()->getMeshes(); // guard against partially loaded meshes if (_meshIndex >= (int)networkMeshes.size() || _meshIndex >= (int)geometry.meshes.size() || _meshIndex >= (int)_model->_meshStates.size()) { diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 43eced3107..ab9e0e7403 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -31,7 +31,7 @@ using namespace std; int nakedModelPointerTypeId = qRegisterMetaType(); -int weakNetworkGeometryPointerTypeId = qRegisterMetaType >(); +int weakGeometryResourceBridgePointerTypeId = qRegisterMetaType(); int vec3VectorTypeId = qRegisterMetaType >(); float Model::FAKE_DIMENSION_PLACEHOLDER = -1.0f; #define HTTP_INVALID_COM "http://invalid.com" @@ -79,6 +79,10 @@ void initCollisionHullMaterials() { Model::Model(RigPointer rig, QObject* parent) : QObject(parent), + _renderGeometry(), + _collisionGeometry(), + _renderWatcher(_renderGeometry), + _collisionWatcher(_collisionGeometry), _translation(0.0f), _rotation(), _scale(1.0f, 1.0f, 1.0f), @@ -98,7 +102,6 @@ Model::Model(RigPointer rig, QObject* parent) : _calculatedMeshTrianglesValid(false), _meshGroupsKnown(false), _isWireframe(false), - _renderCollisionHull(false), _rig(rig) { // we may have been created in the network thread, but we live in the main thread if (_viewState) { @@ -116,7 +119,7 @@ AbstractViewStateInterface* Model::_viewState = NULL; bool Model::needsFixupInScene() const { if (readyToAddToScene()) { - if (_needsUpdateTextures && _geometry->getGeometry()->areTexturesLoaded()) { + if (_needsUpdateTextures && _renderGeometry->areTexturesLoaded()) { _needsUpdateTextures = false; return true; } @@ -793,13 +796,13 @@ int Model::getLastFreeJointIndex(int jointIndex) const { void Model::setTextures(const QVariantMap& textures) { if (isLoaded()) { _needsUpdateTextures = true; - _geometry->getGeometry()->setTextures(textures); + _renderGeometry->setTextures(textures); } } void Model::setURL(const QUrl& url) { // don't recreate the geometry if it's the same URL - if (_url == url && _geometry && _geometry->getURL() == url) { + if (_url == url && _renderWatcher.getURL() == url) { return; } @@ -818,7 +821,7 @@ void Model::setURL(const QUrl& url) { invalidCalculatedMeshBoxes(); deleteGeometry(); - _geometry = DependencyManager::get()->getGeometry(url); + _renderWatcher.setResource(DependencyManager::get()->fetchResource(url)); onInvalidate(); } @@ -827,7 +830,7 @@ void Model::setCollisionModelURL(const QUrl& url) { return; } _collisionUrl = url; - _collisionGeometry = DependencyManager::get()->getGeometry(url); + _collisionWatcher.setResource(DependencyManager::get()->fetchResource(url)); } bool Model::getJointPositionInWorldFrame(int jointIndex, glm::vec3& position) const { @@ -883,7 +886,7 @@ QStringList Model::getJointNames() const { class Blender : public QRunnable { public: - Blender(ModelPointer model, int blendNumber, const std::weak_ptr& geometry, + Blender(ModelPointer model, int blendNumber, const Geometry::WeakPointer& geometry, const QVector& meshes, const QVector& blendshapeCoefficients); virtual void run(); @@ -892,12 +895,12 @@ private: ModelPointer _model; int _blendNumber; - std::weak_ptr _geometry; + Geometry::WeakPointer _geometry; QVector _meshes; QVector _blendshapeCoefficients; }; -Blender::Blender(ModelPointer model, int blendNumber, const std::weak_ptr& geometry, +Blender::Blender(ModelPointer model, int blendNumber, const Geometry::WeakPointer& geometry, const QVector& meshes, const QVector& blendshapeCoefficients) : _model(model), _blendNumber(blendNumber), @@ -940,7 +943,7 @@ void Blender::run() { // post the result to the geometry cache, which will dispatch to the model if still alive QMetaObject::invokeMethod(DependencyManager::get().data(), "setBlendedVertices", Q_ARG(ModelPointer, _model), Q_ARG(int, _blendNumber), - Q_ARG(const std::weak_ptr&, _geometry), Q_ARG(const QVector&, vertices), + Q_ARG(const Geometry::WeakPointer&, _geometry), Q_ARG(const QVector&, vertices), Q_ARG(const QVector&, normals)); } @@ -1151,7 +1154,7 @@ bool Model::maybeStartBlender() { if (isLoaded()) { const FBXGeometry& fbxGeometry = getFBXGeometry(); if (fbxGeometry.hasBlendedMeshes()) { - QThreadPool::globalInstance()->start(new Blender(getThisPointer(), ++_blendNumber, _geometry, + QThreadPool::globalInstance()->start(new Blender(getThisPointer(), ++_blendNumber, _renderGeometry, fbxGeometry.meshes, _blendshapeCoefficients)); return true; } @@ -1159,10 +1162,10 @@ bool Model::maybeStartBlender() { return false; } -void Model::setBlendedVertices(int blendNumber, const std::weak_ptr& geometry, +void Model::setBlendedVertices(int blendNumber, const Geometry::WeakPointer& geometry, const QVector& vertices, const QVector& normals) { auto geometryRef = geometry.lock(); - if (!geometryRef || _geometry != geometryRef || _blendedVertexBuffers.empty() || blendNumber < _appliedBlendNumber) { + if (!geometryRef || _renderGeometry != geometryRef || _blendedVertexBuffers.empty() || blendNumber < _appliedBlendNumber) { return; } _appliedBlendNumber = blendNumber; @@ -1205,27 +1208,23 @@ AABox Model::getRenderableMeshBound() const { } void Model::segregateMeshGroups() { - NetworkGeometry::Pointer networkGeometry; + Geometry::Pointer geometry; bool showingCollisionHull = false; if (_showCollisionHull && _collisionGeometry) { if (isCollisionLoaded()) { - networkGeometry = _collisionGeometry; + geometry = _collisionGeometry; showingCollisionHull = true; } else { return; } } else { assert(isLoaded()); - networkGeometry = _geometry; + geometry = _renderGeometry; } - const FBXGeometry& geometry = networkGeometry->getGeometry()->getGeometry(); - const auto& networkMeshes = networkGeometry->getGeometry()->getMeshes(); + const auto& meshes = geometry->getMeshes(); // all of our mesh vectors must match in size - auto geoMeshesSize = geometry.meshes.size(); - if ((int)networkMeshes.size() != geoMeshesSize || - // geometry.meshes.size() != _meshStates.size()) { - geoMeshesSize > _meshStates.size()) { + if ((int)meshes.size() != _meshStates.size()) { qDebug() << "WARNING!!!! Mesh Sizes don't match! We will not segregate mesh groups yet."; return; } @@ -1249,23 +1248,25 @@ void Model::segregateMeshGroups() { // Run through all of the meshes, and place them into their segregated, but unsorted buckets int shapeID = 0; - for (int i = 0; i < (int)networkMeshes.size(); i++) { - const FBXMesh& mesh = geometry.meshes.at(i); - const auto& networkMesh = networkMeshes.at(i); + uint32_t numMeshes = (uint32_t)meshes.size(); + for (uint32_t i = 0; i < numMeshes; i++) { + const auto& mesh = meshes.at(i); + if (mesh) { - // Create the render payloads - int totalParts = mesh.parts.size(); - for (int partIndex = 0; partIndex < totalParts; partIndex++) { - if (showingCollisionHull) { - if (_collisionHullMaterials.empty()) { - initCollisionHullMaterials(); + // Create the render payloads + int numParts = (int)mesh->getNumParts(); + for (int partIndex = 0; partIndex < numParts; partIndex++) { + if (showingCollisionHull) { + if (_collisionHullMaterials.empty()) { + initCollisionHullMaterials(); + } + _collisionRenderItemsSet << std::make_shared(mesh, partIndex, _collisionHullMaterials[partIndex % NUM_COLLISION_HULL_COLORS], transform, offset); + } else { + _modelMeshRenderItemsSet << std::make_shared(this, i, partIndex, shapeID, transform, offset); } - _collisionRenderItemsSet << std::make_shared(networkMesh, partIndex, _collisionHullMaterials[partIndex % NUM_COLLISION_HULL_COLORS], transform, offset); - } else { - _modelMeshRenderItemsSet << std::make_shared(this, i, partIndex, shapeID, transform, offset); - } - shapeID++; + shapeID++; + } } } _meshGroupsKnown = true; @@ -1328,7 +1329,7 @@ void ModelBlender::noteRequiresBlend(ModelPointer model) { } void ModelBlender::setBlendedVertices(ModelPointer model, int blendNumber, - const std::weak_ptr& geometry, const QVector& vertices, const QVector& normals) { + const Geometry::WeakPointer& geometry, const QVector& vertices, const QVector& normals) { if (model) { model->setBlendedVertices(blendNumber, geometry, vertices, normals); } diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 6a7c9ec560..aa0c49f720 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -97,7 +97,7 @@ public: bool showCollisionHull = false); void removeFromScene(std::shared_ptr scene, render::PendingChanges& pendingChanges); void renderSetup(RenderArgs* args); - bool isRenderable() const { return !_meshStates.isEmpty() || (isActive() && getGeometry()->getGeometry()->getMeshes().empty()); } + bool isRenderable() const { return !_meshStates.isEmpty() || (isActive() && _renderGeometry->getMeshes().empty()); } bool isVisible() const { return _isVisible; } @@ -107,11 +107,11 @@ public: bool maybeStartBlender(); /// Sets blended vertices computed in a separate thread. - void setBlendedVertices(int blendNumber, const std::weak_ptr& geometry, + void setBlendedVertices(int blendNumber, const Geometry::WeakPointer& geometry, const QVector& vertices, const QVector& normals); - bool isLoaded() const { return _geometry && _geometry->getGeometry(); } - bool isCollisionLoaded() const { return _collisionGeometry && _collisionGeometry->getGeometry(); } + bool isLoaded() const { return (bool)_renderGeometry; } + bool isCollisionLoaded() const { return (bool)_collisionGeometry; } void setIsWireframe(bool isWireframe) { _isWireframe = isWireframe; } bool isWireframe() const { return _isWireframe; } @@ -128,18 +128,18 @@ public: virtual void updateClusterMatrices(glm::vec3 modelPosition, glm::quat modelOrientation); /// Returns a reference to the shared geometry. - const NetworkGeometry::Pointer& getGeometry() const { return _geometry; } + const Geometry::Pointer& getGeometry() const { return _renderGeometry; } /// Returns a reference to the shared collision geometry. - const NetworkGeometry::Pointer& getCollisionGeometry() const { return _collisionGeometry; } + const Geometry::Pointer& getCollisionGeometry() const { return _collisionGeometry; } - const QVariantMap getTextures() const { assert(isLoaded()); return _geometry->getGeometry()->getTextures(); } + const QVariantMap getTextures() const { assert(isLoaded()); return _renderGeometry->getTextures(); } void setTextures(const QVariantMap& textures); /// Provided as a convenience, will crash if !isLoaded() // And so that getGeometry() isn't chained everywhere - const FBXGeometry& getFBXGeometry() const { assert(isLoaded()); return getGeometry()->getGeometry()->getGeometry(); } + const FBXGeometry& getFBXGeometry() const { assert(isLoaded()); return _renderGeometry->getFBXGeometry(); } /// Provided as a convenience, will crash if !isCollisionLoaded() - const FBXGeometry& getCollisionFBXGeometry() const { assert(isCollisionLoaded()); return getCollisionGeometry()->getGeometry()->getGeometry(); } + const FBXGeometry& getCollisionFBXGeometry() const { assert(isCollisionLoaded()); return _collisionGeometry->getFBXGeometry(); } // Set the model to use for collisions. // Should only be called from the model's rendering thread to avoid access violations of changed geometry. @@ -263,7 +263,11 @@ protected: /// \return true if joint exists bool getJointPosition(int jointIndex, glm::vec3& position) const; - NetworkGeometry::Pointer _geometry; + Geometry::Pointer _renderGeometry; // only ever set by its watcher + Geometry::Pointer _collisionGeometry; // only ever set by its watcher + + GeometryResourceWatcher _renderWatcher; + GeometryResourceWatcher _collisionWatcher; glm::vec3 _translation; glm::quat _rotation; @@ -330,8 +334,6 @@ protected: void deleteGeometry(); void initJointTransforms(); - NetworkGeometry::Pointer _collisionGeometry; - float _pupilDilation; QVector _blendshapeCoefficients; @@ -373,9 +375,6 @@ protected: static AbstractViewStateInterface* _viewState; - bool _renderCollisionHull; - - QSet> _collisionRenderItemsSet; QMap _collisionRenderItems; @@ -395,7 +394,7 @@ protected: }; Q_DECLARE_METATYPE(ModelPointer) -Q_DECLARE_METATYPE(std::weak_ptr) +Q_DECLARE_METATYPE(Geometry::WeakPointer) /// Handle management of pending models that need blending class ModelBlender : public QObject, public Dependency { @@ -408,7 +407,7 @@ public: void noteRequiresBlend(ModelPointer model); public slots: - void setBlendedVertices(ModelPointer model, int blendNumber, const std::weak_ptr& geometry, + void setBlendedVertices(ModelPointer model, int blendNumber, const Geometry::WeakPointer& geometry, const QVector& vertices, const QVector& normals); private: