From 078b15c02d1aeee7df0854e192dba815b9860e59 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Thu, 13 Feb 2014 16:20:43 -0800 Subject: [PATCH] Add some hysteresis on the LOD switching to prevent rapid switching back and forth. --- interface/src/renderer/GeometryCache.cpp | 21 ++++++++++++++++++--- interface/src/renderer/GeometryCache.h | 6 +++++- interface/src/renderer/Model.cpp | 3 ++- interface/src/renderer/Model.h | 4 +++- 4 files changed, 28 insertions(+), 6 deletions(-) diff --git a/interface/src/renderer/GeometryCache.cpp b/interface/src/renderer/GeometryCache.cpp index 28280395e4..c02f69b8fb 100644 --- a/interface/src/renderer/GeometryCache.cpp +++ b/interface/src/renderer/GeometryCache.cpp @@ -328,16 +328,30 @@ NetworkGeometry::~NetworkGeometry() { } } -QSharedPointer NetworkGeometry::getLODOrFallback(float distance) const { +QSharedPointer NetworkGeometry::getLODOrFallback(float distance, float& hysteresis) const { if (_lodParent.data() != this) { - return _lodParent.data()->getLODOrFallback(distance); + return _lodParent.data()->getLODOrFallback(distance, hysteresis); } if (_failedToLoad && _fallback) { return _fallback; } + QSharedPointer lod = _lodParent; + float lodDistance = 0.0f; QMap >::const_iterator it = _lods.upperBound(distance); - QSharedPointer lod = (it == _lods.constBegin()) ? _lodParent.toStrongRef() : *(it - 1); + if (it != _lods.constBegin()) { + it = it - 1; + lod = it.value(); + lodDistance = it.key(); + } + if (hysteresis != NO_HYSTERESIS && hysteresis != lodDistance) { + // if we previously selected a different distance, make sure we've moved far enough to justify switching + const float HYSTERESIS_PROPORTION = 0.1f; + if (glm::abs(distance - qMax(hysteresis, lodDistance)) / fabsf(hysteresis - lodDistance) < HYSTERESIS_PROPORTION) { + return getLODOrFallback(hysteresis, hysteresis); + } + } if (lod->isLoaded()) { + hysteresis = lodDistance; return lod; } // if the ideal LOD isn't loaded, we need to make sure it's started to load, and possibly return the closest loaded one @@ -356,6 +370,7 @@ QSharedPointer NetworkGeometry::getLODOrFallback(float distance closestDistance = distanceToLOD; } } + hysteresis = NO_HYSTERESIS; return lod; } diff --git a/interface/src/renderer/GeometryCache.h b/interface/src/renderer/GeometryCache.h index cd1972f413..110e2eec4c 100644 --- a/interface/src/renderer/GeometryCache.h +++ b/interface/src/renderer/GeometryCache.h @@ -62,6 +62,9 @@ class NetworkGeometry : public QObject { public: + /// A hysteresis value indicating that we have no state memory. + static const float NO_HYSTERESIS = -1.0f; + NetworkGeometry(const QUrl& url, const QSharedPointer& fallback, const QVariantHash& mapping = QVariantHash(), const QUrl& textureBase = QUrl()); ~NetworkGeometry(); @@ -70,7 +73,8 @@ public: bool isLoaded() const { return !_geometry.joints.isEmpty(); } /// Returns a pointer to the geometry appropriate for the specified distance. - QSharedPointer getLODOrFallback(float distance) const; + /// \param hysteresis a hysteresis parameter that prevents rapid model switching + QSharedPointer getLODOrFallback(float distance, float& hysteresis) const; const FBXGeometry& getFBXGeometry() const { return _geometry; } const QVector& getMeshes() const { return _meshes; } diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 869e89539e..5ea8ff33b4 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -93,7 +93,7 @@ void Model::simulate(float deltaTime) { // update our LOD if (_geometry) { QSharedPointer geometry = _geometry->getLODOrFallback(glm::distance(_translation, - Application::getInstance()->getCamera()->getPosition())); + glm::vec3() /* Application::getInstance()->getCamera()->getPosition() */), _lodHysteresis); if (_geometry != geometry) { deleteGeometry(); _dilatedTextures.clear(); @@ -419,6 +419,7 @@ void Model::setURL(const QUrl& url, const QUrl& fallback) { // delete our local geometry and custom textures deleteGeometry(); _dilatedTextures.clear(); + _lodHysteresis = NetworkGeometry::NO_HYSTERESIS; _baseGeometry = _geometry = Application::getInstance()->getGeometryCache()->getGeometry(url, fallback); } diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index 64ca789570..74283043cf 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -176,7 +176,6 @@ public: protected: - QSharedPointer _baseGeometry; QSharedPointer _geometry; glm::vec3 _translation; @@ -237,6 +236,9 @@ private: void deleteGeometry(); void renderMeshes(float alpha, bool translucent); + QSharedPointer _baseGeometry; + float _lodHysteresis; + float _pupilDilation; std::vector _blendshapeCoefficients;