Add some hysteresis on the LOD switching to prevent rapid switching back

and forth.
This commit is contained in:
Andrzej Kapolka 2014-02-13 16:20:43 -08:00
parent ff01470850
commit 078b15c02d
4 changed files with 28 additions and 6 deletions

View file

@ -328,16 +328,30 @@ NetworkGeometry::~NetworkGeometry() {
}
}
QSharedPointer<NetworkGeometry> NetworkGeometry::getLODOrFallback(float distance) const {
QSharedPointer<NetworkGeometry> 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<NetworkGeometry> lod = _lodParent;
float lodDistance = 0.0f;
QMap<float, QSharedPointer<NetworkGeometry> >::const_iterator it = _lods.upperBound(distance);
QSharedPointer<NetworkGeometry> 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> NetworkGeometry::getLODOrFallback(float distance
closestDistance = distanceToLOD;
}
}
hysteresis = NO_HYSTERESIS;
return lod;
}

View file

@ -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<NetworkGeometry>& 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<NetworkGeometry> getLODOrFallback(float distance) const;
/// \param hysteresis a hysteresis parameter that prevents rapid model switching
QSharedPointer<NetworkGeometry> getLODOrFallback(float distance, float& hysteresis) const;
const FBXGeometry& getFBXGeometry() const { return _geometry; }
const QVector<NetworkMesh>& getMeshes() const { return _meshes; }

View file

@ -93,7 +93,7 @@ void Model::simulate(float deltaTime) {
// update our LOD
if (_geometry) {
QSharedPointer<NetworkGeometry> 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);
}

View file

@ -176,7 +176,6 @@ public:
protected:
QSharedPointer<NetworkGeometry> _baseGeometry;
QSharedPointer<NetworkGeometry> _geometry;
glm::vec3 _translation;
@ -237,6 +236,9 @@ private:
void deleteGeometry();
void renderMeshes(float alpha, bool translucent);
QSharedPointer<NetworkGeometry> _baseGeometry;
float _lodHysteresis;
float _pupilDilation;
std::vector<float> _blendshapeCoefficients;