mirror of
https://github.com/overte-org/overte.git
synced 2025-04-21 08:04:01 +02:00
Rebuild on a new branch after original stopped building.
This commit is contained in:
parent
9a651c6194
commit
fee13d4375
9 changed files with 127 additions and 5 deletions
|
@ -40,7 +40,7 @@ Item {
|
|||
Text {
|
||||
color: root.fontColor;
|
||||
font.pixelSize: root.fontSize
|
||||
text: "Avatars: " + root.avatarCount
|
||||
text: "Avatars: " + root.avatarCount + ", " + root.avatarRenderedCount + " w/in " + root.avatarRenderDistance + "m"
|
||||
}
|
||||
Text {
|
||||
color: root.fontColor;
|
||||
|
|
|
@ -1061,8 +1061,10 @@ void Application::paintGL() {
|
|||
uint64_t now = usecTimestampNow();
|
||||
static uint64_t lastPaintBegin{ now };
|
||||
uint64_t diff = now - lastPaintBegin;
|
||||
float instantaneousFps = 0.0f;
|
||||
if (diff != 0) {
|
||||
_framesPerSecond.updateAverage((float)USECS_PER_SECOND / (float)diff);
|
||||
instantaneousFps = (float)USECS_PER_SECOND / (float)diff;
|
||||
_framesPerSecond.updateAverage(_lastInstantaneousFps);
|
||||
}
|
||||
|
||||
lastPaintBegin = now;
|
||||
|
@ -1326,6 +1328,7 @@ void Application::paintGL() {
|
|||
// Ensure all operations from the previous context are complete before we try to read the fbo
|
||||
glWaitSync(sync, 0, GL_TIMEOUT_IGNORED);
|
||||
glDeleteSync(sync);
|
||||
uint64_t displayStart = usecTimestampNow();
|
||||
|
||||
{
|
||||
PROFILE_RANGE(__FUNCTION__ "/pluginDisplay");
|
||||
|
@ -1338,6 +1341,20 @@ void Application::paintGL() {
|
|||
PerformanceTimer perfTimer("bufferSwap");
|
||||
displayPlugin->finishFrame();
|
||||
}
|
||||
uint64_t displayEnd = usecTimestampNow();
|
||||
// Store together, without Application::idle happening in between setting fps and period.
|
||||
_lastInstantaneousFps = instantaneousFps;
|
||||
const float displayPeriodUsec = (float)(displayEnd - displayStart); // usecs
|
||||
_lastPaintWait = displayPeriodUsec / (float)USECS_PER_SECOND;
|
||||
const float targetPeriod = isHMDMode() ? 1.0f/75.0f : 1.0f/60.0f;
|
||||
const float actualPeriod = 1.0f / instantaneousFps;
|
||||
const float nSyncsByFrameRate = round(actualPeriod / targetPeriod);
|
||||
const float accuracyAllowance = 0.0005;
|
||||
const float nSyncsByPaintWait = floor((_lastPaintWait + accuracyAllowance) / targetPeriod); // sometimes paint goes over and it isn't reflected in actualPeriod
|
||||
const float modularPeriod = (nSyncsByFrameRate + nSyncsByPaintWait) * targetPeriod;
|
||||
const float deducedNonVSyncPeriod = modularPeriod - _lastPaintWait;
|
||||
_lastDeducedNonVSyncFps = 1.0f / deducedNonVSyncPeriod;
|
||||
|
||||
}
|
||||
|
||||
{
|
||||
|
|
|
@ -159,6 +159,9 @@ public:
|
|||
bool isForeground() const { return _isForeground; }
|
||||
|
||||
float getFps() const { return _fps; }
|
||||
float getLastInstanteousFps() const { return _lastInstantaneousFps; }
|
||||
float getLastPaintWait() const { return _lastPaintWait; };
|
||||
float getLastDeducedNonVSyncFps() const { return _lastDeducedNonVSyncFps; }
|
||||
|
||||
float getFieldOfView() { return _fieldOfView.get(); }
|
||||
void setFieldOfView(float fov);
|
||||
|
@ -430,6 +433,9 @@ private:
|
|||
float _fps;
|
||||
QElapsedTimer _timerStart;
|
||||
QElapsedTimer _lastTimeUpdated;
|
||||
float _lastInstantaneousFps { 0.0f };
|
||||
float _lastPaintWait { 0.0f };
|
||||
float _lastDeducedNonVSyncFps { 0.0f };
|
||||
|
||||
ShapeManager _shapeManager;
|
||||
PhysicalEntitySimulation _entitySimulation;
|
||||
|
|
|
@ -97,6 +97,7 @@ Avatar::Avatar(RigPointer rig) :
|
|||
_moving(false),
|
||||
_initialized(false),
|
||||
_shouldRenderBillboard(true),
|
||||
_shouldSkipRender(true),
|
||||
_voiceSphereID(GeometryCache::UNKNOWN_ID)
|
||||
{
|
||||
// we may have been created in the network thread, but we live in the main thread
|
||||
|
@ -114,7 +115,7 @@ Avatar::~Avatar() {
|
|||
}
|
||||
}
|
||||
|
||||
const float BILLBOARD_LOD_DISTANCE = 40.0f;
|
||||
/*const fixme*/ float BILLBOARD_LOD_DISTANCE = 40.0f;
|
||||
|
||||
void Avatar::init() {
|
||||
getHead()->init();
|
||||
|
@ -181,12 +182,36 @@ void Avatar::simulate(float deltaTime) {
|
|||
|
||||
// update the billboard render flag
|
||||
const float BILLBOARD_HYSTERESIS_PROPORTION = 0.1f;
|
||||
BILLBOARD_LOD_DISTANCE = DependencyManager::get<AvatarManager>()->getFIXMEupdate();
|
||||
if (_shouldRenderBillboard) {
|
||||
if (getLODDistance() < BILLBOARD_LOD_DISTANCE * (1.0f - BILLBOARD_HYSTERESIS_PROPORTION)) {
|
||||
_shouldRenderBillboard = false;
|
||||
qCDebug(interfaceapp) << "Unbillboarding" << (isMyAvatar() ? "myself" : getSessionUUID()) << "for LOD" << getLODDistance();
|
||||
}
|
||||
} else if (getLODDistance() > BILLBOARD_LOD_DISTANCE * (1.0f + BILLBOARD_HYSTERESIS_PROPORTION)) {
|
||||
_shouldRenderBillboard = true;
|
||||
qCDebug(interfaceapp) << "Billboarding" << (isMyAvatar() ? "myself" : getSessionUUID()) << "for LOD" << getLODDistance();
|
||||
}
|
||||
#define PID_TUNING 1
|
||||
#ifdef PID_TUNING
|
||||
const float SKIP_HYSTERESIS_PROPORTION = 0.0f;
|
||||
#else
|
||||
const float SKIP_HYSTERESIS_PROPORTION = BILLBOARD_HYSTERESIS_PROPORTION;
|
||||
#endif
|
||||
float renderDistance = DependencyManager::get<AvatarManager>()->getRenderDistance();
|
||||
float distance = glm::distance(qApp->getCamera()->getPosition(), _position);
|
||||
if (_shouldSkipRender) {
|
||||
if (distance < renderDistance * (1.0f - SKIP_HYSTERESIS_PROPORTION)) {
|
||||
_shouldSkipRender = false;
|
||||
#ifndef PID_TUNING
|
||||
qCDebug(interfaceapp) << "Rerendering" << (isMyAvatar() ? "myself" : getSessionUUID()) << "for LOD" << getLODDistance();
|
||||
#endif
|
||||
}
|
||||
} else if (distance > renderDistance * (1.0f + SKIP_HYSTERESIS_PROPORTION)) {
|
||||
_shouldSkipRender = true;
|
||||
#ifndef PID_TUNING
|
||||
qCDebug(interfaceapp) << "Unrendering" << (isMyAvatar() ? "myself" : getSessionUUID()) << "for LOD" << getLODDistance();
|
||||
#endif
|
||||
}
|
||||
|
||||
// simple frustum check
|
||||
|
@ -199,7 +224,7 @@ void Avatar::simulate(float deltaTime) {
|
|||
getHand()->simulate(deltaTime, false);
|
||||
}
|
||||
|
||||
if (!_shouldRenderBillboard && inViewFrustum) {
|
||||
if (!_shouldRenderBillboard && !_shouldSkipRender && inViewFrustum) {
|
||||
{
|
||||
PerformanceTimer perfTimer("skeleton");
|
||||
for (int i = 0; i < _jointData.size(); i++) {
|
||||
|
@ -585,10 +610,13 @@ glm::quat Avatar::computeRotationFromBodyToWorldUp(float proportion) const {
|
|||
}
|
||||
|
||||
void Avatar::fixupModelsInScene() {
|
||||
|
||||
// check to see if when we added our models to the scene they were ready, if they were not ready, then
|
||||
// fix them up in the scene
|
||||
render::ScenePointer scene = qApp->getMain3DScene();
|
||||
_skeletonModel.setVisibleInScene(!_shouldSkipRender, scene);
|
||||
if (_shouldSkipRender) {
|
||||
return;
|
||||
}
|
||||
render::PendingChanges pendingChanges;
|
||||
if (_skeletonModel.isRenderable() && _skeletonModel.needsFixupInScene()) {
|
||||
_skeletonModel.removeFromScene(scene, pendingChanges);
|
||||
|
|
|
@ -140,6 +140,8 @@ public:
|
|||
Q_INVOKABLE glm::vec3 getAngularVelocity() const { return _angularVelocity; }
|
||||
Q_INVOKABLE glm::vec3 getAngularAcceleration() const { return _angularAcceleration; }
|
||||
|
||||
Q_INVOKABLE bool getShouldSkipRendering() const { return _shouldSkipRender; }
|
||||
|
||||
/// Scales a world space position vector relative to the avatar position and scale
|
||||
/// \param vector position to be scaled. Will store the result
|
||||
void scaleVectorRelativeToPosition(glm::vec3 &positionToScale) const;
|
||||
|
@ -226,6 +228,7 @@ private:
|
|||
bool _initialized;
|
||||
NetworkTexturePointer _billboardTexture;
|
||||
bool _shouldRenderBillboard;
|
||||
bool _shouldSkipRender { false };
|
||||
bool _isLookAtTarget;
|
||||
|
||||
void renderBillboard(RenderArgs* renderArgs);
|
||||
|
|
|
@ -61,12 +61,34 @@ void AvatarManager::registerMetaTypes(QScriptEngine* engine) {
|
|||
qScriptRegisterSequenceMetaType<QVector<AvatarManager::LocalLight> >(engine);
|
||||
}
|
||||
|
||||
#define TARGET_FPS 60.0f
|
||||
#define TARGET_PERIOD_MS (1000.0f / TARGET_FPS)
|
||||
AvatarManager::AvatarManager(QObject* parent) :
|
||||
_avatarFades()
|
||||
{
|
||||
// register a meta type for the weak pointer we'll use for the owning avatar mixer for each avatar
|
||||
qRegisterMetaType<QWeakPointer<Node> >("NodeWeakPointer");
|
||||
_myAvatar = std::make_shared<MyAvatar>(std::make_shared<AvatarRig>());
|
||||
_renderDistanceController.setMeasuredValueSetpoint(TARGET_FPS); //FIXME
|
||||
const float TREE_SCALE = 32768.0f; // Not in shared library, alas.
|
||||
const float SMALLEST_REASONABLE_HORIZON = 0.5f; // FIXME 5
|
||||
_renderDistanceController.setControlledValueHighLimit(1.0f/SMALLEST_REASONABLE_HORIZON);
|
||||
_renderDistanceController.setControlledValueLowLimit(1.0f/TREE_SCALE);
|
||||
|
||||
// Advice for tuning parameters:
|
||||
// See PIDController.h. There's a sectionon tuning in the reference.
|
||||
// Turn off HYSTERESIS_PROPORTION and extra logging by defining PID_TUNING in Avatar.cpp.
|
||||
// Turn on logging with the following:
|
||||
_renderDistanceController.setHistorySize("avatar render", TARGET_FPS * 4); // FIXME
|
||||
// KP is usually tuned by setting the other constants to zero, finding the maximum value that doesn't oscillate,
|
||||
// and taking about 0.6 of that. A typical osciallation would be with error=37fps with avatars 10m away, so
|
||||
// KP*37=1/10 => KP(oscillating)=0.1/37 = 0.0027
|
||||
_renderDistanceController.setKP(0.0012f);
|
||||
// alt:
|
||||
// Our anti-windup limits accumulated error to 10*targetFrameRate, so the sanity check on KI is
|
||||
// KI*750=controlledValueHighLimit=1 => KI=1/750.
|
||||
_renderDistanceController.setKI(0.001);
|
||||
_renderDistanceController.setKD(0.0001); // a touch of kd increases the speed by which we get there
|
||||
|
||||
auto& packetReceiver = DependencyManager::get<NodeList>()->getPacketReceiver();
|
||||
packetReceiver.registerListener(PacketType::BulkAvatarData, this, "processAvatarDataPacket");
|
||||
|
@ -117,9 +139,26 @@ void AvatarManager::updateOtherAvatars(float deltaTime) {
|
|||
PerformanceWarning warn(showWarnings, "Application::updateAvatars()");
|
||||
|
||||
PerformanceTimer perfTimer("otherAvatars");
|
||||
const float FEED_FORWARD_RANGE = 2;
|
||||
const float fps = qApp->getLastInstanteousFps();
|
||||
const float paintWait = qApp->getLastPaintWait();
|
||||
//const float modularizedPeriod = floor((1000.0f / std::min(fps, TARGET_FPS)) / TARGET_PERIOD_MS) * TARGET_PERIOD_MS;
|
||||
// measured value: 1) bigger => more desirable plant activity (i.e., more rendering), 2) setpoint=TARGET_PERIOD_MS=13.333
|
||||
// single vsync: no load=>1or2. high load=>12or13
|
||||
// over vsync: just over: 13. way over: 14...15...16
|
||||
//const float effective = ((1000.0f / fps) < TARGET_PERIOD_MS) ? (TARGET_PERIOD_MS - paintWait) : ((2.0f * TARGET_PERIOD_MS) - paintWait);
|
||||
const float deduced = qApp->getLastDeducedNonVSyncFps();
|
||||
const bool isAtSetpoint = false; //FIXME fabsf(effectiveFps - _renderDistanceController.getMeasuredValueSetpoint()) < FEED_FORWARD_RANGE;
|
||||
const float distance = 1.0f / _renderDistanceController.update(deduced + (isAtSetpoint ? _renderFeedForward : 0.0f), deltaTime, isAtSetpoint, fps, paintWait);
|
||||
|
||||
const float RENDER_DISTANCE_DEADBAND = 0.0f; //FIXME 0.3f; // meters
|
||||
if (fabsf(distance - _renderDistance) > RENDER_DISTANCE_DEADBAND) {
|
||||
_renderDistance = distance;
|
||||
}
|
||||
|
||||
// simulate avatars
|
||||
AvatarHash::iterator avatarIterator = _avatarHash.begin();
|
||||
int renderableCount = 0;
|
||||
while (avatarIterator != _avatarHash.end()) {
|
||||
auto avatar = std::dynamic_pointer_cast<Avatar>(avatarIterator.value());
|
||||
|
||||
|
@ -135,10 +174,14 @@ void AvatarManager::updateOtherAvatars(float deltaTime) {
|
|||
} else {
|
||||
avatar->startUpdate();
|
||||
avatar->simulate(deltaTime);
|
||||
if (!avatar->getShouldSkipRendering()) {
|
||||
renderableCount++;
|
||||
}
|
||||
avatar->endUpdate();
|
||||
++avatarIterator;
|
||||
}
|
||||
}
|
||||
_renderedAvatarCount = renderableCount;
|
||||
|
||||
// simulate avatar fades
|
||||
simulateAvatarFades(deltaTime);
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
#include <AvatarHashMap.h>
|
||||
#include <PhysicsEngine.h>
|
||||
#include <PIDController.h>
|
||||
|
||||
#include "Avatar.h"
|
||||
#include "AvatarMotionState.h"
|
||||
|
@ -43,6 +44,7 @@ public:
|
|||
void clearOtherAvatars();
|
||||
|
||||
bool shouldShowReceiveStats() const { return _shouldShowReceiveStats; }
|
||||
PIDController& getRenderDistanceController() { return _renderDistanceController; }
|
||||
|
||||
class LocalLight {
|
||||
public:
|
||||
|
@ -64,6 +66,17 @@ public:
|
|||
void handleCollisionEvents(const CollisionEvents& collisionEvents);
|
||||
|
||||
void updateAvatarPhysicsShape(const QUuid& id);
|
||||
Q_INVOKABLE int getNumberRendered() { return _renderedAvatarCount; }
|
||||
Q_INVOKABLE float getRenderDistance() { return _renderDistance; }
|
||||
Q_INVOKABLE float getFIXMEupdate() { return _fixmeUpdate; }
|
||||
Q_INVOKABLE void setFIXMEupdate(float f) { _fixmeUpdate = f; }
|
||||
Q_INVOKABLE void setFIXMEkp(float f) { _renderDistanceController.setKP(f); }
|
||||
Q_INVOKABLE void setFIXMEki(float f) { _renderDistanceController.setKI(f); }
|
||||
Q_INVOKABLE void setFIXMEkd(float f) { _renderDistanceController.setKD(f); }
|
||||
Q_INVOKABLE void setFIXMEbias(float f) { _renderDistanceController.setBias(f); }
|
||||
Q_INVOKABLE void setFIXMElow(float f) { _renderDistanceController.setControlledValueLowLimit(f); }
|
||||
Q_INVOKABLE void setFIXMEhigh(float f) { _renderDistanceController.setControlledValueHighLimit(f); }
|
||||
Q_INVOKABLE void setFIXMEfeedForward(float f) { _renderFeedForward = f; }
|
||||
|
||||
public slots:
|
||||
void setShouldShowReceiveStats(bool shouldShowReceiveStats) { _shouldShowReceiveStats = shouldShowReceiveStats; }
|
||||
|
@ -88,6 +101,12 @@ private:
|
|||
QVector<AvatarManager::LocalLight> _localLights;
|
||||
|
||||
bool _shouldShowReceiveStats = false;
|
||||
float _fixmeUpdate = 40.0f;
|
||||
float _renderDistance { 40.0f };
|
||||
float _renderFeedForward { 5.0f };
|
||||
int _renderedAvatarCount {0};
|
||||
PIDController _renderDistanceController {};
|
||||
|
||||
|
||||
SetOfAvatarMotionStates _avatarMotionStates;
|
||||
SetOfMotionStates _motionStatesToAdd;
|
||||
|
|
|
@ -115,6 +115,8 @@ void Stats::updateStats(bool force) {
|
|||
auto avatarManager = DependencyManager::get<AvatarManager>();
|
||||
// we need to take one avatar out so we don't include ourselves
|
||||
STAT_UPDATE(avatarCount, avatarManager->size() - 1);
|
||||
STAT_UPDATE(avatarRenderedCount, avatarManager->getNumberRendered());
|
||||
STAT_UPDATE(avatarRenderDistance, (int) round(avatarManager->getRenderDistance())); // deliberately truncating
|
||||
STAT_UPDATE(serverCount, nodeList->size());
|
||||
STAT_UPDATE(framerate, (int)qApp->getFps());
|
||||
STAT_UPDATE(simrate, (int)qApp->getAverageSimsPerSecond());
|
||||
|
|
|
@ -36,6 +36,8 @@ class Stats : public QQuickItem {
|
|||
STATS_PROPERTY(int, simrate, 0)
|
||||
STATS_PROPERTY(int, avatarSimrate, 0)
|
||||
STATS_PROPERTY(int, avatarCount, 0)
|
||||
STATS_PROPERTY(int, avatarRenderedCount, 0)
|
||||
STATS_PROPERTY(int, avatarRenderDistance, 0)
|
||||
STATS_PROPERTY(int, packetInCount, 0)
|
||||
STATS_PROPERTY(int, packetOutCount, 0)
|
||||
STATS_PROPERTY(float, mbpsIn, 0)
|
||||
|
@ -117,6 +119,8 @@ signals:
|
|||
void simrateChanged();
|
||||
void avatarSimrateChanged();
|
||||
void avatarCountChanged();
|
||||
void avatarRenderedCountChanged();
|
||||
void avatarRenderDistanceChanged();
|
||||
void packetInCountChanged();
|
||||
void packetOutCountChanged();
|
||||
void mbpsInChanged();
|
||||
|
|
Loading…
Reference in a new issue