mirror of
https://github.com/overte-org/overte.git
synced 2025-08-08 13:58:51 +02:00
Added distance-based LOD
This commit is contained in:
parent
57a2ebb800
commit
8b648408fd
5 changed files with 116 additions and 11 deletions
|
@ -6829,7 +6829,8 @@ void Application::updateRenderArgs(float deltaTime) {
|
||||||
_viewFrustum.calculate();
|
_viewFrustum.calculate();
|
||||||
}
|
}
|
||||||
appRenderArgs._renderArgs = RenderArgs(_graphicsEngine.getGPUContext(), lodManager->getVisibilityDistance(),
|
appRenderArgs._renderArgs = RenderArgs(_graphicsEngine.getGPUContext(), lodManager->getVisibilityDistance(),
|
||||||
lodManager->getBoundaryLevelAdjust(), lodManager->getLODHalfAngleTan(), RenderArgs::DEFAULT_RENDER_MODE,
|
lodManager->getBoundaryLevelAdjust(), lodManager->getLODFarHalfAngleTan(), lodManager->getLODNearHalfAngleTan(),
|
||||||
|
lodManager->getLODFarDistance(), lodManager->getLODNearDistance(), RenderArgs::DEFAULT_RENDER_MODE,
|
||||||
RenderArgs::MONO, RenderArgs::DEFERRED, RenderArgs::RENDER_DEBUG_NONE);
|
RenderArgs::MONO, RenderArgs::DEFERRED, RenderArgs::RENDER_DEBUG_NONE);
|
||||||
appRenderArgs._renderArgs._scene = getMain3DScene();
|
appRenderArgs._renderArgs._scene = getMain3DScene();
|
||||||
|
|
||||||
|
|
|
@ -172,7 +172,8 @@ void LODManager::autoAdjustLOD(float realTimeDelta) {
|
||||||
_pidOutputs.w = output;
|
_pidOutputs.w = output;
|
||||||
|
|
||||||
// And now add the output of the controller to the LODAngle where we will guarantee it is in the proper range
|
// And now add the output of the controller to the LODAngle where we will guarantee it is in the proper range
|
||||||
setLODAngleDeg(oldLODAngle + output);
|
float newLODAngle = std::min(oldLODAngle + output, glm::degrees(_farMaxAngle));
|
||||||
|
setLODAngleDeg(newLODAngle);
|
||||||
|
|
||||||
if (oldLODAngle != getLODAngleDeg()) {
|
if (oldLODAngle != getLODAngleDeg()) {
|
||||||
auto lodToolsDialog = DependencyManager::get<DialogsManager>()->getLodToolsDialog();
|
auto lodToolsDialog = DependencyManager::get<DialogsManager>()->getLodToolsDialog();
|
||||||
|
@ -185,6 +186,16 @@ void LODManager::autoAdjustLOD(float realTimeDelta) {
|
||||||
float LODManager::getLODHalfAngleTan() const {
|
float LODManager::getLODHalfAngleTan() const {
|
||||||
return tan(_lodHalfAngle);
|
return tan(_lodHalfAngle);
|
||||||
}
|
}
|
||||||
|
float LODManager::getLODFarHalfAngleTan() const {
|
||||||
|
return tan(std::min(_lodHalfAngle, _farMaxAngle / 2.0f));
|
||||||
|
}
|
||||||
|
float LODManager::getLODNearHalfAngleTan() const {
|
||||||
|
if (_farMaxAngle > 0) {
|
||||||
|
return tan(std::min(_lodHalfAngle / (_farMaxAngle / 2.0f) * (_nearMaxAngle / 2.0f), _nearMaxAngle / 2.0f));
|
||||||
|
} else {
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
float LODManager::getLODAngle() const {
|
float LODManager::getLODAngle() const {
|
||||||
return 2.0f * _lodHalfAngle;
|
return 2.0f * _lodHalfAngle;
|
||||||
}
|
}
|
||||||
|
@ -192,6 +203,37 @@ float LODManager::getLODAngleDeg() const {
|
||||||
return glm::degrees(getLODAngle());
|
return glm::degrees(getLODAngle());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LODManager::setLODFarDistance(float value) {
|
||||||
|
_farDistance = value;
|
||||||
|
updateLODAfterSettingsChange();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LODManager::setLODNearDistance(float value) {
|
||||||
|
_nearDistance = value;
|
||||||
|
updateLODAfterSettingsChange();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LODManager::setLODFarMaxAngleDeg(float value) {
|
||||||
|
_farMaxAngle = glm::radians(value);
|
||||||
|
updateLODAfterSettingsChange();
|
||||||
|
}
|
||||||
|
|
||||||
|
float LODManager::getLODFarMaxAngleDeg() const {
|
||||||
|
return glm::degrees(_farMaxAngle);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LODManager::setLODNearMaxAngle(float value) {
|
||||||
|
_nearMaxAngle = glm::radians(value);
|
||||||
|
updateLODAfterSettingsChange();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LODManager::updateLODAfterSettingsChange() {}
|
||||||
|
|
||||||
|
float LODManager::getLODNearMaxAngle() const {
|
||||||
|
return glm::degrees(_nearMaxAngle);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
float LODManager::getVisibilityDistance() const {
|
float LODManager::getVisibilityDistance() const {
|
||||||
float systemDistance = getVisibilityDistanceFromHalfAngle(_lodHalfAngle);
|
float systemDistance = getVisibilityDistanceFromHalfAngle(_lodHalfAngle);
|
||||||
// Maintain behavior with deprecated _boundaryLevelAdjust property
|
// Maintain behavior with deprecated _boundaryLevelAdjust property
|
||||||
|
@ -274,9 +316,19 @@ bool LODManager::shouldRender(const RenderArgs* args, const AABox& bounds) {
|
||||||
// we are comparing the square of the half tangent apparent angle for the bound against the LODAngle Half tangent square
|
// we are comparing the square of the half tangent apparent angle for the bound against the LODAngle Half tangent square
|
||||||
// if smaller, the bound is too small and we should NOT render it, return true otherwise.
|
// if smaller, the bound is too small and we should NOT render it, return true otherwise.
|
||||||
|
|
||||||
|
// TODO: maybe include avatar size in calculating near and far distance?
|
||||||
|
|
||||||
// Tangent Adjacent side is eye to bound center vector length
|
// Tangent Adjacent side is eye to bound center vector length
|
||||||
auto pos = args->getViewFrustum().getPosition() - bounds.calcCenter();
|
auto pos = args->getViewFrustum().getPosition() - bounds.calcCenter();
|
||||||
auto halfTanAdjacentSq = glm::dot(pos, pos);
|
auto halfTanAdjacentSq = glm::dot(pos, pos);
|
||||||
|
auto distSq = halfTanAdjacentSq;
|
||||||
|
|
||||||
|
if (distSq <= args->_lodNearDistSq) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
float farNearRatio = (distSq > args->_lodFarDistSq) ? 1.0f : (distSq - args->_lodNearDistSq)/(args->_lodFarDistSq - args->_lodNearDistSq);
|
||||||
|
float lodAngleHalfTanSq = (farNearRatio * (args->_lodFarAngleHalfTanSq - args->_lodNearAngleHalfTanSq)) + args->_lodNearAngleHalfTanSq;
|
||||||
|
|
||||||
// Tangent Opposite side is the half length of the dimensions vector of the bound
|
// Tangent Opposite side is the half length of the dimensions vector of the bound
|
||||||
auto dim = bounds.getDimensions();
|
auto dim = bounds.getDimensions();
|
||||||
|
@ -286,7 +338,7 @@ bool LODManager::shouldRender(const RenderArgs* args, const AABox& bounds) {
|
||||||
// isVisible = halfTanSq >= lodHalfTanSq = (halfTanOppositeSq / halfTanAdjacentSq) >= lodHalfTanSq
|
// isVisible = halfTanSq >= lodHalfTanSq = (halfTanOppositeSq / halfTanAdjacentSq) >= lodHalfTanSq
|
||||||
// which we express as below to avoid division
|
// which we express as below to avoid division
|
||||||
// (halfTanOppositeSq) >= lodHalfTanSq * halfTanAdjacentSq
|
// (halfTanOppositeSq) >= lodHalfTanSq * halfTanAdjacentSq
|
||||||
return (halfTanOppositeSq >= args->_lodAngleHalfTanSq * halfTanAdjacentSq);
|
return (halfTanOppositeSq >= lodAngleHalfTanSq * halfTanAdjacentSq);
|
||||||
};
|
};
|
||||||
|
|
||||||
void LODManager::setOctreeSizeScale(float sizeScale) {
|
void LODManager::setOctreeSizeScale(float sizeScale) {
|
||||||
|
|
|
@ -49,7 +49,7 @@ enum WorldDetailQuality {
|
||||||
};
|
};
|
||||||
Q_DECLARE_METATYPE(WorldDetailQuality);
|
Q_DECLARE_METATYPE(WorldDetailQuality);
|
||||||
|
|
||||||
const bool DEFAULT_LOD_AUTO_ADJUST = false; // true for auto, false for manual.
|
const bool DEFAULT_LOD_AUTO_ADJUST = true; // true for auto, false for manual.
|
||||||
|
|
||||||
#ifdef Q_OS_ANDROID
|
#ifdef Q_OS_ANDROID
|
||||||
const float DEFAULT_LOD_QUALITY_LEVEL = 0.2f; // default quality level setting is High (lower framerate)
|
const float DEFAULT_LOD_QUALITY_LEVEL = 0.2f; // default quality level setting is High (lower framerate)
|
||||||
|
@ -120,6 +120,17 @@ class AABox;
|
||||||
* @property {number} lodAngleDeg - The minimum angular dimension (relative to the camera position) of an entity in order for
|
* @property {number} lodAngleDeg - The minimum angular dimension (relative to the camera position) of an entity in order for
|
||||||
* it to be rendered, in degrees. The angular dimension is calculated as a sphere of radius half the diagonal of the
|
* it to be rendered, in degrees. The angular dimension is calculated as a sphere of radius half the diagonal of the
|
||||||
* entity's AA box.
|
* entity's AA box.
|
||||||
|
|
||||||
|
* @property {number} lodFarMaxAngleDeg - The upper limit of how big the minimum angular dimension (relative to the camera position)
|
||||||
|
* of an entity in order for it to be rendered, in degrees at distance specified by lodFarDistance. The angular dimension is
|
||||||
|
* calculated as a sphere of radius half the diagonal of the entity's AA box.
|
||||||
|
* @property {number} lodNearMaxAngleDeg - The upper limit of how big the minimum angular dimension (relative to the camera position)
|
||||||
|
* of an entity in order for it to be rendered, in degrees at distance specified by lodFarDistance. The angular dimension is
|
||||||
|
* calculated as a sphere of radius half the diagonal of the entity's AA box.
|
||||||
|
|
||||||
|
* @property {number} lodFarDistance - Distance for which lodFarMaxAngleDeg limit is applied
|
||||||
|
* @property {number} lodNearDistance - Distance for which lodNearMaxAngleDeg limit is applied
|
||||||
|
|
||||||
*
|
*
|
||||||
* @property {number} pidKp - <em>Not used.</em>
|
* @property {number} pidKp - <em>Not used.</em>
|
||||||
* @property {number} pidKi - <em>Not used.</em>
|
* @property {number} pidKi - <em>Not used.</em>
|
||||||
|
@ -157,6 +168,11 @@ class LODManager : public QObject, public Dependency {
|
||||||
|
|
||||||
Q_PROPERTY(float lodAngleDeg READ getLODAngleDeg WRITE setLODAngleDeg)
|
Q_PROPERTY(float lodAngleDeg READ getLODAngleDeg WRITE setLODAngleDeg)
|
||||||
|
|
||||||
|
Q_PROPERTY(float lodFarMaxAngleDeg READ getLODFarMaxAngleDeg WRITE setLODFarMaxAngleDeg)
|
||||||
|
Q_PROPERTY(float lodNearMaxAngleDeg READ getLODNearMaxAngle WRITE setLODNearMaxAngle)
|
||||||
|
Q_PROPERTY(float lodFarDistance READ getLODFarDistance WRITE setLODFarDistance)
|
||||||
|
Q_PROPERTY(float lodNearDistance READ getLODNearDistance WRITE setLODNearDistance)
|
||||||
|
|
||||||
Q_PROPERTY(float pidKp READ getPidKp WRITE setPidKp)
|
Q_PROPERTY(float pidKp READ getPidKp WRITE setPidKp)
|
||||||
Q_PROPERTY(float pidKi READ getPidKi WRITE setPidKi)
|
Q_PROPERTY(float pidKi READ getPidKi WRITE setPidKi)
|
||||||
Q_PROPERTY(float pidKd READ getPidKd WRITE setPidKd)
|
Q_PROPERTY(float pidKd READ getPidKd WRITE setPidKd)
|
||||||
|
@ -292,7 +308,8 @@ public:
|
||||||
|
|
||||||
float getLODAngleDeg() const;
|
float getLODAngleDeg() const;
|
||||||
void setLODAngleDeg(float lodAngle);
|
void setLODAngleDeg(float lodAngle);
|
||||||
float getLODHalfAngleTan() const;
|
float getLODFarHalfAngleTan() const;
|
||||||
|
float getLODNearHalfAngleTan() const;
|
||||||
float getLODAngle() const;
|
float getLODAngle() const;
|
||||||
float getVisibilityDistance() const;
|
float getVisibilityDistance() const;
|
||||||
void setVisibilityDistance(float distance);
|
void setVisibilityDistance(float distance);
|
||||||
|
@ -311,6 +328,15 @@ public:
|
||||||
float getPidOd() const;
|
float getPidOd() const;
|
||||||
float getPidO() const;
|
float getPidO() const;
|
||||||
|
|
||||||
|
void setLODFarDistance(float value);
|
||||||
|
float getLODFarDistance() const { return _farDistance; }
|
||||||
|
void setLODNearDistance(float value);
|
||||||
|
float getLODNearDistance() const { return _nearDistance; }
|
||||||
|
void setLODFarMaxAngleDeg(float value);
|
||||||
|
float getLODFarMaxAngleDeg() const;
|
||||||
|
void setLODNearMaxAngle(float value);
|
||||||
|
float getLODNearMaxAngle() const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
||||||
/*@jsdoc
|
/*@jsdoc
|
||||||
|
@ -354,7 +380,9 @@ signals:
|
||||||
private:
|
private:
|
||||||
LODManager();
|
LODManager();
|
||||||
|
|
||||||
|
float getLODHalfAngleTan() const;
|
||||||
void setWorldDetailQuality(WorldDetailQuality quality, bool isHMDMode);
|
void setWorldDetailQuality(WorldDetailQuality quality, bool isHMDMode);
|
||||||
|
void updateLODAfterSettingsChange();
|
||||||
|
|
||||||
std::mutex _automaticLODLock;
|
std::mutex _automaticLODLock;
|
||||||
bool _automaticLODAdjust = DEFAULT_LOD_AUTO_ADJUST;
|
bool _automaticLODAdjust = DEFAULT_LOD_AUTO_ADJUST;
|
||||||
|
@ -364,6 +392,11 @@ private:
|
||||||
float _batchTime{ 0.0f }; // msec
|
float _batchTime{ 0.0f }; // msec
|
||||||
float _gpuTime{ 0.0f }; // msec
|
float _gpuTime{ 0.0f }; // msec
|
||||||
|
|
||||||
|
float _farDistance{ 200.0f };
|
||||||
|
float _nearDistance{ 4.0f };
|
||||||
|
float _farMaxAngle{ 15.0f / 180.f * (float)M_PI };
|
||||||
|
float _nearMaxAngle{ 1.0f / 180.f * (float)M_PI };
|
||||||
|
|
||||||
float _nowRenderTime{ 0.0f }; // msec
|
float _nowRenderTime{ 0.0f }; // msec
|
||||||
float _smoothScale{ 10.0f }; // smooth is evaluated over 10 times longer than now
|
float _smoothScale{ 10.0f }; // smooth is evaluated over 10 times longer than now
|
||||||
float _smoothRenderTime{ 0.0f }; // msec
|
float _smoothRenderTime{ 0.0f }; // msec
|
||||||
|
|
|
@ -76,7 +76,11 @@ namespace render {
|
||||||
Args(const gpu::ContextPointer& context,
|
Args(const gpu::ContextPointer& context,
|
||||||
float sizeScale = 1.0f,
|
float sizeScale = 1.0f,
|
||||||
int boundaryLevelAdjust = 0,
|
int boundaryLevelAdjust = 0,
|
||||||
float lodAngleHalfTan = 0.1f,
|
float lodFarAngleHalfTan = 0.1f,
|
||||||
|
float lodNearAngleHalfTan = 0.01f,
|
||||||
|
//float lodAngleHalfTan = 0.1f,
|
||||||
|
float lodFarDist = 200.0f,
|
||||||
|
float lodNearDist = 4.0f,
|
||||||
RenderMode renderMode = DEFAULT_RENDER_MODE,
|
RenderMode renderMode = DEFAULT_RENDER_MODE,
|
||||||
DisplayMode displayMode = MONO,
|
DisplayMode displayMode = MONO,
|
||||||
RenderMethod renderMethod = DEFERRED,
|
RenderMethod renderMethod = DEFERRED,
|
||||||
|
@ -85,8 +89,14 @@ namespace render {
|
||||||
_context(context),
|
_context(context),
|
||||||
_sizeScale(sizeScale),
|
_sizeScale(sizeScale),
|
||||||
_boundaryLevelAdjust(boundaryLevelAdjust),
|
_boundaryLevelAdjust(boundaryLevelAdjust),
|
||||||
_lodAngleHalfTan(lodAngleHalfTan),
|
_lodFarAngleHalfTan(lodFarAngleHalfTan),
|
||||||
_lodAngleHalfTanSq(lodAngleHalfTan * lodAngleHalfTan),
|
_lodFarAngleHalfTanSq(lodFarAngleHalfTan * lodFarAngleHalfTan),
|
||||||
|
_lodNearAngleHalfTan(lodNearAngleHalfTan),
|
||||||
|
_lodNearAngleHalfTanSq(lodNearAngleHalfTan * lodNearAngleHalfTan),
|
||||||
|
_lodFarDist(lodFarDist),
|
||||||
|
_lodNearDist(lodNearDist),
|
||||||
|
_lodFarDistSq(lodFarDist * lodFarDist),
|
||||||
|
_lodNearDistSq(lodNearDist * lodNearDist),
|
||||||
_renderMode(renderMode),
|
_renderMode(renderMode),
|
||||||
_displayMode(displayMode),
|
_displayMode(displayMode),
|
||||||
_renderMethod(renderMethod),
|
_renderMethod(renderMethod),
|
||||||
|
@ -116,8 +126,14 @@ namespace render {
|
||||||
|
|
||||||
float _sizeScale { 1.0f };
|
float _sizeScale { 1.0f };
|
||||||
int _boundaryLevelAdjust { 0 };
|
int _boundaryLevelAdjust { 0 };
|
||||||
float _lodAngleHalfTan{ 0.1f };
|
float _lodFarAngleHalfTan{ 0.1f };
|
||||||
float _lodAngleHalfTanSq{ _lodAngleHalfTan * _lodAngleHalfTan };
|
float _lodFarAngleHalfTanSq{ _lodFarAngleHalfTan * _lodFarAngleHalfTan };
|
||||||
|
float _lodNearAngleHalfTan{ 0.01f };
|
||||||
|
float _lodNearAngleHalfTanSq{ _lodNearAngleHalfTan * _lodNearAngleHalfTan };
|
||||||
|
float _lodFarDist { 200.0f };
|
||||||
|
float _lodNearDist { 4.0f };
|
||||||
|
float _lodFarDistSq { _lodFarDist * _lodFarDist };
|
||||||
|
float _lodNearDistSq { _lodNearDist * _lodNearDist };
|
||||||
|
|
||||||
RenderMode _renderMode { DEFAULT_RENDER_MODE };
|
RenderMode _renderMode { DEFAULT_RENDER_MODE };
|
||||||
DisplayMode _displayMode { MONO };
|
DisplayMode _displayMode { MONO };
|
||||||
|
|
|
@ -127,7 +127,10 @@ void FetchSpatialTree::run(const RenderContextPointer& renderContext, const Inpu
|
||||||
// Octree selection!
|
// Octree selection!
|
||||||
float threshold = 0.0f;
|
float threshold = 0.0f;
|
||||||
if (queryFrustum.isPerspective()) {
|
if (queryFrustum.isPerspective()) {
|
||||||
threshold = args->_lodAngleHalfTan;
|
//TODO: It was:
|
||||||
|
// threshold = args->_lodFarAngleHalfTan;
|
||||||
|
// But now should be dependent on distance
|
||||||
|
threshold = args->_lodFarAngleHalfTan;
|
||||||
if (frustumResolution.y > 0) {
|
if (frustumResolution.y > 0) {
|
||||||
threshold = glm::max(queryFrustum.getFieldOfView() / frustumResolution.y, threshold);
|
threshold = glm::max(queryFrustum.getFieldOfView() / frustumResolution.y, threshold);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue