diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index a5e75f760b..35a07353d1 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -417,6 +417,26 @@ const Model* EntityTreeRenderer::getModelForEntityItem(const EntityItem* entityI return result; } +const FBXGeometry* EntityTreeRenderer::getCollisionGeometryForEntity(const EntityItem* entityItem) { + const FBXGeometry* result = NULL; + + if (entityItem->getType() == EntityTypes::Model) { + const RenderableModelEntityItem* constModelEntityItem = dynamic_cast(entityItem); + if (constModelEntityItem->hasCollisionModel()) { + RenderableModelEntityItem* modelEntityItem = const_cast(constModelEntityItem); + assert(modelEntityItem); // we need this!!! Why?!! + Model* model = modelEntityItem->getModel(this); + if (model) { + const QSharedPointer collisionNetworkGeometry = model->getCollisionGeometry(); + if (!collisionNetworkGeometry.isNull()) { + result = &collisionNetworkGeometry->getFBXGeometry(); + } + } + } + } + return result; +} + void EntityTreeRenderer::renderElementProxy(EntityTreeElement* entityTreeElement) { glm::vec3 elementCenter = entityTreeElement->getAACube().calcCenter(); float elementSize = entityTreeElement->getScale(); @@ -591,7 +611,7 @@ void EntityTreeRenderer::processEraseMessage(const QByteArray& dataByteArray, co static_cast(_tree)->processEraseMessage(dataByteArray, sourceNode); } -Model* EntityTreeRenderer::allocateModel(const QString& url) { +Model* EntityTreeRenderer::allocateModel(const QString& url, const QString& collisionUrl) { Model* model = NULL; // Make sure we only create and delete models on the thread that owns the EntityTreeRenderer if (QThread::currentThread() != thread()) { @@ -604,10 +624,11 @@ Model* EntityTreeRenderer::allocateModel(const QString& url) { model = new Model(); model->init(); model->setURL(QUrl(url)); + model->setCollisionModelURL(QUrl(collisionUrl)); return model; } -Model* EntityTreeRenderer::updateModel(Model* original, const QString& newUrl) { +Model* EntityTreeRenderer::updateModel(Model* original, const QString& newUrl, const QString& collisionUrl) { Model* model = NULL; // The caller shouldn't call us if the URL doesn't need to change. But if they @@ -636,6 +657,7 @@ Model* EntityTreeRenderer::updateModel(Model* original, const QString& newUrl) { model = new Model(); model->init(); model->setURL(QUrl(newUrl)); + model->setCollisionModelURL(QUrl(collisionUrl)); return model; } diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.h b/libraries/entities-renderer/src/EntityTreeRenderer.h index 0da85f360b..c4aa5a42d0 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.h +++ b/libraries/entities-renderer/src/EntityTreeRenderer.h @@ -59,15 +59,16 @@ public: virtual const FBXGeometry* getGeometryForEntity(const EntityItem* entityItem); virtual const Model* getModelForEntityItem(const EntityItem* entityItem); + virtual const FBXGeometry* getCollisionGeometryForEntity(const EntityItem* entityItem); /// clears the tree virtual void clear(); /// if a renderable entity item needs a model, we will allocate it for them - Q_INVOKABLE Model* allocateModel(const QString& url); + Q_INVOKABLE Model* 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); + Q_INVOKABLE Model* updateModel(Model* 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); diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 7e57323d68..7bd94df386 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -223,10 +223,10 @@ Model* RenderableModelEntityItem::getModel(EntityTreeRenderer* renderer) { // if we have a previously allocated model, but it's URL doesn't match // then we need to let our renderer update our model for us. if (_model && QUrl(getModelURL()) != _model->getURL()) { - result = _model = _myRenderer->updateModel(_model, getModelURL()); + result = _model = _myRenderer->updateModel(_model, getModelURL(), getCollisionModelURL()); _needsInitialSimulation = true; } else if (!_model) { // if we don't yet have a model, then we want our renderer to allocate one - result = _model = _myRenderer->allocateModel(getModelURL()); + result = _model = _myRenderer->allocateModel(getModelURL(), getCollisionModelURL()); _needsInitialSimulation = true; } else { // we already have the model we want... result = _model; @@ -267,36 +267,46 @@ bool RenderableModelEntityItem::findDetailedRayIntersection(const glm::vec3& ori } bool RenderableModelEntityItem::isReadyToComputeShape() { - if (_collisionModelURL == "") { + + if (!_model) { + qDebug() << "O#O#O#O#O#O RenderableModelEntityItem::isReadyToComputeShape --> no _model, false"; + return false; // hmm... + } + + if (_model->getCollisionURL().toString() == "") { + qDebug() << "O#O#O#O#O#O RenderableModelEntityItem::isReadyToComputeShape --> no _model->_collisionUrl, true"; // no model url, so we're ready to compute a shape. return true; } - if (! _collisionNetworkGeometry.isNull() && _collisionNetworkGeometry->isLoadedWithTextures()) { - // we have a _collisionModelURL AND a _collisionNetworkGeometry AND it's fully loaded. + const QSharedPointer collisionNetworkGeometry = _model->getCollisionGeometry(); + if (! collisionNetworkGeometry.isNull() && collisionNetworkGeometry->isLoadedWithTextures()) { + // we have a _collisionModelURL AND a collisionNetworkGeometry AND it's fully loaded. + qDebug() << "O#O#O#O#O#O RenderableModelEntityItem::isReadyToComputeShape --> model is ready, true"; return true; } - if (_collisionNetworkGeometry.isNull()) { - // we have a _collisionModelURL but we don't yet have a _collisionNetworkGeometry. - _collisionNetworkGeometry = - DependencyManager::get()->getGeometry(_collisionModelURL, QUrl(), false, false); - - if (! _collisionNetworkGeometry.isNull() && _collisionNetworkGeometry->isLoadedWithTextures()) { - // shortcut in case it's already loaded. - return true; - } + if (collisionNetworkGeometry.isNull()) { + qDebug() << "O#O#O#O#O#O RenderableModelEntityItem::isReadyToComputeShape --> started download, false"; + // we have a _collisionModelURL but we don't yet have a collisionNetworkGeometry. + // kick-off the download so that we'll have it at some future re-attempt. + DependencyManager::get()->getGeometry(_collisionModelURL, QUrl(), false, false); + return false; } // the model is still being downloaded. + qDebug() << "O#O#O#O#O#O RenderableModelEntityItem::isReadyToComputeShape --> model not ready, false"; return false; } void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& info) { - if (_collisionModelURL == "") { + if (_model->getCollisionURL().toString() == "") { + qDebug() << "O#O#O#O#O#O RenderableModelEntityItem::computeShapeInfo --> default"; info.setParams(getShapeType(), 0.5f * getDimensions()); } else { - const FBXGeometry& fbxGeometry = _collisionNetworkGeometry->getFBXGeometry(); + qDebug() << "O#O#O#O#O#O RenderableModelEntityItem::computeShapeInfo --> hull points"; + const QSharedPointer collisionNetworkGeometry = _model->getCollisionGeometry(); + const FBXGeometry& fbxGeometry = collisionNetworkGeometry->getFBXGeometry(); _points.clear(); foreach (const FBXMesh& mesh, fbxGeometry.meshes) { @@ -310,9 +320,11 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& info) { ShapeType RenderableModelEntityItem::getShapeType() const { // XXX make hull an option in edit.js ? - if (_collisionModelURL != "") { - return SHAPE_TYPE_CONVEX_HULL; - } else { + if (!_model || _model->getCollisionURL().toString() == "") { + qDebug() << "O#O#O#O#O#O RenderableModelEntityItem::getShapeType -->" << _shapeType; return _shapeType; + } else { + qDebug() << "O#O#O#O#O#O RenderableModelEntityItem::getShapeType -->" << SHAPE_TYPE_CONVEX_HULL; + return SHAPE_TYPE_CONVEX_HULL; } } diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index 6d50a52a95..08adb3e9a6 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -30,8 +30,7 @@ public: _needsInitialSimulation(true), _needsModelReload(true), _myRenderer(NULL), - _originalTexturesRead(false), - _collisionNetworkGeometry(QSharedPointer()) { } + _originalTexturesRead(false) { } virtual ~RenderableModelEntityItem(); @@ -68,7 +67,7 @@ private: QStringList _originalTextures; bool _originalTexturesRead; - QSharedPointer _collisionNetworkGeometry; + // QSharedPointer _collisionNetworkGeometry; QVector _points; }; diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index e1521ebd50..8536e74e9a 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -31,6 +31,7 @@ class EntityItemFBXService { public: virtual const FBXGeometry* getGeometryForEntity(const EntityItem* entityItem) = 0; virtual const Model* getModelForEntityItem(const EntityItem* entityItem) = 0; + virtual const FBXGeometry* getCollisionGeometryForEntity(const EntityItem* entityItem) = 0; }; diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index d5e15ed2c8..5f9feaa49f 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -1087,6 +1087,7 @@ int Model::getLastFreeJointIndex(int jointIndex) const { } void Model::setURL(const QUrl& url, const QUrl& fallback, bool retainCurrent, bool delayLoad) { + qDebug() << "|||||||||||||| Model::setURL" << url.toString(); // don't recreate the geometry if it's the same URL if (_url == url) { return; @@ -1102,6 +1103,7 @@ void Model::setURL(const QUrl& url, const QUrl& fallback, bool retainCurrent, bo } void Model::setCollisionModelURL(const QUrl& url, const QUrl& fallback, bool delayLoad) { + qDebug() << "|||||||||||||| Model::setCollisionModelURL" << url.toString(); if (_collisionUrl == url) { return; } diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index f95c87e99f..890ea87d25 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -106,11 +106,11 @@ public: /// \param delayLoad if true, don't load the model immediately; wait until actually requested Q_INVOKABLE void setURL(const QUrl& url, const QUrl& fallback = QUrl(), bool retainCurrent = false, bool delayLoad = false); + const QUrl& getURL() const { return _url; } // Set the model to use for collisions Q_INVOKABLE void setCollisionModelURL(const QUrl& url, const QUrl& fallback = QUrl(), bool delayLoad = false); - - const QUrl& getURL() const { return _url; } + const QUrl& getCollisionURL() const { return _collisionUrl; } /// Sets the distance parameter used for LOD computations. void setLODDistance(float distance) { _lodDistance = distance; } @@ -132,6 +132,9 @@ public: /// Returns a reference to the shared geometry. const QSharedPointer& getGeometry() const { return _geometry; } + + /// Returns a reference to the shared collision geometry. + const QSharedPointer getCollisionGeometry() {return _collisionGeometry; } /// Returns the number of joint states in the model. int getJointStateCount() const { return _jointStates.size(); }