diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index e8a91fb08b..9a51b102dc 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -5369,15 +5369,20 @@ void Application::update(float deltaTime) { _physicsEngine->dumpStatsIfNecessary(); } auto t1 = std::chrono::high_resolution_clock::now(); - workload::Timings timings(1); - timings[0] = float(std::chrono::nanoseconds(t1 - t0).count() * 0.000001); - _gameWorkload.updateSimulationTimings(timings); if (!_aboutToQuit) { // NOTE: the getEntities()->update() call below will wait for lock // and will provide non-physical entity motion getEntities()->update(true); // update the models... } + + auto t2 = std::chrono::high_resolution_clock::now(); + + workload::Timings timings(2); + timings[0] = (t1 - t0); + timings[1] = (t2 - t1); + _gameWorkload.updateSimulationTimings(timings); + } } } else { diff --git a/interface/src/workload/GameWorkload.cpp b/interface/src/workload/GameWorkload.cpp index 332cc9fb5c..16a7098aa3 100644 --- a/interface/src/workload/GameWorkload.cpp +++ b/interface/src/workload/GameWorkload.cpp @@ -39,20 +39,18 @@ void ControlViews::run(const workload::WorkloadContextPointer& runContext, const } } -float wtf_adjust(float current, float timing) { - float error = -((timing) - 2.0f); - if (error < 0.0f) { - current += 0.2f * (error) / 16.0f; - } else { - current += 0.1f * (error) / 16.0f; - } +glm::vec2 Regulator::run(const Timing_ns& regulationDuration, const Timing_ns& measured, const glm::vec2& current) { + glm::vec2 next = current; - if (current > 100.0f) { - current = 100.0f; - } else if (current < 5.0f) { - current = 5.0f; - } - return current; + // Regulate next value based on current moving toward the goal budget + float error_ms = std::chrono::duration(_budget - measured).count(); + float coef = error_ms / std::chrono::duration(regulationDuration).count(); + next += coef * (error_ms < 0.0 ? _speedDown : _speedUp); + + // Clamp to min max + next = glm::clamp(next, _minRange, _maxRange); + + return next; } void ControlViews::regulateViews(workload::Views& outViews, const workload::Timings& timings) { @@ -63,12 +61,16 @@ void ControlViews::regulateViews(workload::Views& outViews, const workload::Timi } } + auto loopDuration = std::chrono::nanoseconds{ std::chrono::milliseconds(16) }; + regionBackFronts[workload::Region::R2] = regionRegulators[workload::Region::R2].run(loopDuration, timings[0], regionBackFronts[workload::Region::R2]); + regionBackFronts[workload::Region::R3] = regionRegulators[workload::Region::R3].run(loopDuration, timings[1], regionBackFronts[workload::Region::R3]); + int i = 0; for (auto& outView : outViews) { - auto current = regionBackFronts[workload::Region::R2].y; - auto newCurrent = wtf_adjust(current, timings[0]); - regionBackFronts[workload::Region::R2].y = newCurrent; - outView.regionBackFronts[workload::Region::R2].y = newCurrent; + outView.regionBackFronts[workload::Region::R1] = regionBackFronts[workload::Region::R1]; + outView.regionBackFronts[workload::Region::R2] = regionBackFronts[workload::Region::R2]; + outView.regionBackFronts[workload::Region::R3] = regionBackFronts[workload::Region::R3]; + workload::View::updateRegionsFromBackFronts(outView); } } diff --git a/interface/src/workload/GameWorkload.h b/interface/src/workload/GameWorkload.h index 7dffd6ac58..e3c050afc9 100644 --- a/interface/src/workload/GameWorkload.h +++ b/interface/src/workload/GameWorkload.h @@ -60,6 +60,21 @@ signals: void dirty(); }; +struct Regulator { + using Timing_ns = std::chrono::nanoseconds; + Timing_ns _budget{ std::chrono::milliseconds(2) }; + glm::vec2 _minRange{ 2.0f, 5.0f }; + glm::vec2 _maxRange{ 50.0f, 100.0f }; + + glm::vec2 _speedDown{ 0.2f }; + glm::vec2 _speedUp{ 0.1f }; + + + Regulator() {} + + glm::vec2 run(const Timing_ns& regulationDuration, const Timing_ns& measured, const glm::vec2& current); +}; + class ControlViews { public: using Config = ControlViewsConfig; @@ -71,8 +86,9 @@ public: void configure(const Config& config); void run(const workload::WorkloadContextPointer& runContext, const Input& inputs, Output& outputs); - glm::vec2 regionBackFronts[workload::Region::NUM_VIEW_REGIONS + 1]; + std::array regionBackFronts; + std::array regionRegulators; void regulateViews(workload::Views& views, const workload::Timings& timings); diff --git a/libraries/physics/src/PhysicalEntitySimulation.cpp b/libraries/physics/src/PhysicalEntitySimulation.cpp index e91d7cfdc6..22737afe30 100644 --- a/libraries/physics/src/PhysicalEntitySimulation.cpp +++ b/libraries/physics/src/PhysicalEntitySimulation.cpp @@ -50,12 +50,13 @@ void PhysicalEntitySimulation::addEntityInternal(EntityItemPointer entity) { assert(!entity->isDead()); uint8_t region = _space->getRegion(entity->getSpaceIndex()); bool shouldBePhysical = region < workload::Region::R3 && entity->shouldBePhysical(); + bool canBeKinematic = region <= workload::Region::R3; if (shouldBePhysical) { EntityMotionState* motionState = static_cast(entity->getPhysicsInfo()); if (!motionState) { _entitiesToAddToPhysics.insert(entity); } - } else if (entity->isMovingRelativeToParent()) { + } else if (canBeKinematic && entity->isMovingRelativeToParent()) { _simpleKinematicEntities.insert(entity); } } @@ -124,6 +125,7 @@ void PhysicalEntitySimulation::changeEntityInternal(EntityItemPointer entity) { EntityMotionState* motionState = static_cast(entity->getPhysicsInfo()); uint8_t region = _space->getRegion(entity->getSpaceIndex()); bool shouldBePhysical = region < workload::Region::R3 && entity->shouldBePhysical(); + bool canBeKinematic = region <= workload::Region::R3; if (motionState) { if (!shouldBePhysical) { // the entity should be removed from the physical simulation @@ -131,7 +133,7 @@ void PhysicalEntitySimulation::changeEntityInternal(EntityItemPointer entity) { _physicalObjects.remove(motionState); removeOwnershipData(motionState); _entitiesToRemoveFromPhysics.insert(entity); - if (entity->isMovingRelativeToParent()) { + if (canBeKinematic && entity->isMovingRelativeToParent()) { _simpleKinematicEntities.insert(entity); } } else { @@ -142,7 +144,7 @@ void PhysicalEntitySimulation::changeEntityInternal(EntityItemPointer entity) { // Perhaps it's shape has changed and it can now be added? _entitiesToAddToPhysics.insert(entity); _simpleKinematicEntities.remove(entity); // just in case it's non-physical-kinematic - } else if (entity->isMovingRelativeToParent()) { + } else if (canBeKinematic && entity->isMovingRelativeToParent()) { _simpleKinematicEntities.insert(entity); } else { _simpleKinematicEntities.remove(entity); // just in case it's non-physical-kinematic diff --git a/libraries/workload/src/workload/Space.h b/libraries/workload/src/workload/Space.h index ab7dd02134..960c905f7c 100644 --- a/libraries/workload/src/workload/Space.h +++ b/libraries/workload/src/workload/Space.h @@ -70,7 +70,7 @@ private: using SpacePointer = std::shared_ptr; using Changes = std::vector; using IndexVectors = std::vector; -using Timings = std::vector; +using Timings = std::vector; } // namespace workload