mirror of
https://github.com/overte-org/overte.git
synced 2025-04-23 00:54:08 +02:00
Merge pull request #11611 from AndrewMeadows/faster-update-renderables
Faster renderables update
This commit is contained in:
commit
d6ad389dab
15 changed files with 183 additions and 95 deletions
BUILD.md
interface/src
libraries
animation/src
entities-renderer/src
EntityTreeRenderer.cppRenderableEntityItem.cppRenderableModelEntityItem.cppRenderableModelEntityItem.h
entities/src
render-utils/src
shared/src
2
BUILD.md
2
BUILD.md
|
@ -25,7 +25,7 @@ The above dependencies will be downloaded, built, linked and included automatica
|
|||
|
||||
These are not placed in your normal build tree when doing an out of source build so that they do not need to be re-downloaded and re-compiled every time the CMake build folder is cleared. Should you want to force a re-download and re-compile of a specific external, you can simply remove that directory from the appropriate subfolder in `build/ext`. Should you want to force a re-download and re-compile of all externals, just remove the `build/ext` folder.
|
||||
|
||||
If you would like to use a specific install of a dependency instead of the version that would be grabbed as a CMake ExternalProject, you can pass -DUSE_LOCAL_$NAME=0 (where $NAME is the name of the subfolder in [cmake/externals](cmake/externals)) when you run CMake to tell it not to get that dependency as an external project.
|
||||
If you would like to use a specific install of a dependency instead of the version that would be grabbed as a CMake ExternalProject, you can pass -DUSE\_LOCAL\_$NAME=0 (where $NAME is the name of the subfolder in [cmake/externals](cmake/externals)) when you run CMake to tell it not to get that dependency as an external project.
|
||||
|
||||
### OS Specific Build Guides
|
||||
|
||||
|
|
|
@ -2392,8 +2392,8 @@ void Application::initializeUi() {
|
|||
}
|
||||
|
||||
void Application::updateCamera(RenderArgs& renderArgs) {
|
||||
PROFILE_RANGE(render, "/updateCamera");
|
||||
PerformanceTimer perfTimer("CameraUpdates");
|
||||
PROFILE_RANGE(render, __FUNCTION__);
|
||||
PerformanceTimer perfTimer("updateCamera");
|
||||
|
||||
glm::vec3 boomOffset;
|
||||
auto myAvatar = getMyAvatar();
|
||||
|
@ -2609,7 +2609,7 @@ void Application::resizeGL() {
|
|||
}
|
||||
|
||||
void Application::handleSandboxStatus(QNetworkReply* reply) {
|
||||
PROFILE_RANGE(render, "HandleSandboxStatus");
|
||||
PROFILE_RANGE(render, __FUNCTION__);
|
||||
|
||||
bool sandboxIsRunning = SandboxUtils::readStatus(reply->readAll());
|
||||
qDebug() << "HandleSandboxStatus" << sandboxIsRunning;
|
||||
|
@ -4638,7 +4638,6 @@ void Application::updateDialogs(float deltaTime) const {
|
|||
static bool domainLoadingInProgress = false;
|
||||
|
||||
void Application::update(float deltaTime) {
|
||||
|
||||
PROFILE_RANGE_EX(app, __FUNCTION__, 0xffff0000, (uint64_t)_renderFrameCount + 1);
|
||||
|
||||
if (!_physicsEnabled) {
|
||||
|
@ -4833,11 +4832,11 @@ void Application::update(float deltaTime) {
|
|||
QSharedPointer<AvatarManager> avatarManager = DependencyManager::get<AvatarManager>();
|
||||
|
||||
{
|
||||
PROFILE_RANGE_EX(simulation_physics, "Physics", 0xffff0000, (uint64_t)getActiveDisplayPlugin()->presentCount());
|
||||
PROFILE_RANGE(simulation_physics, "Physics");
|
||||
PerformanceTimer perfTimer("physics");
|
||||
if (_physicsEnabled) {
|
||||
{
|
||||
PROFILE_RANGE_EX(simulation_physics, "UpdateStates", 0xffffff00, (uint64_t)getActiveDisplayPlugin()->presentCount());
|
||||
PROFILE_RANGE(simulation_physics, "PreStep");
|
||||
|
||||
PerformanceTimer perfTimer("updateStates)");
|
||||
static VectorOfMotionStates motionStates;
|
||||
|
@ -4871,14 +4870,14 @@ void Application::update(float deltaTime) {
|
|||
});
|
||||
}
|
||||
{
|
||||
PROFILE_RANGE_EX(simulation_physics, "StepSimulation", 0xffff8000, (uint64_t)getActiveDisplayPlugin()->presentCount());
|
||||
PROFILE_RANGE(simulation_physics, "Step");
|
||||
PerformanceTimer perfTimer("stepSimulation");
|
||||
getEntities()->getTree()->withWriteLock([&] {
|
||||
_physicsEngine->stepSimulation();
|
||||
});
|
||||
}
|
||||
{
|
||||
PROFILE_RANGE_EX(simulation_physics, "HarvestChanges", 0xffffff00, (uint64_t)getActiveDisplayPlugin()->presentCount());
|
||||
PROFILE_RANGE(simulation_physics, "PostStep");
|
||||
PerformanceTimer perfTimer("harvestChanges");
|
||||
if (_physicsEngine->hasOutgoingChanges()) {
|
||||
// grab the collision events BEFORE handleOutgoingChanges() because at this point
|
||||
|
@ -4886,6 +4885,7 @@ void Application::update(float deltaTime) {
|
|||
auto& collisionEvents = _physicsEngine->getCollisionEvents();
|
||||
|
||||
getEntities()->getTree()->withWriteLock([&] {
|
||||
PROFILE_RANGE(simulation_physics, "Harvest");
|
||||
PerformanceTimer perfTimer("handleOutgoingChanges");
|
||||
|
||||
const VectorOfMotionStates& outgoingChanges = _physicsEngine->getChangedMotionStates();
|
||||
|
@ -4898,18 +4898,25 @@ void Application::update(float deltaTime) {
|
|||
|
||||
if (!_aboutToQuit) {
|
||||
// handleCollisionEvents() AFTER handleOutgoinChanges()
|
||||
PerformanceTimer perfTimer("entities");
|
||||
avatarManager->handleCollisionEvents(collisionEvents);
|
||||
// Collision events (and their scripts) must not be handled when we're locked, above. (That would risk
|
||||
// deadlock.)
|
||||
_entitySimulation->handleCollisionEvents(collisionEvents);
|
||||
{
|
||||
PROFILE_RANGE(simulation_physics, "CollisionEvents");
|
||||
PerformanceTimer perfTimer("entities");
|
||||
avatarManager->handleCollisionEvents(collisionEvents);
|
||||
// Collision events (and their scripts) must not be handled when we're locked, above. (That would risk
|
||||
// deadlock.)
|
||||
_entitySimulation->handleCollisionEvents(collisionEvents);
|
||||
}
|
||||
|
||||
PROFILE_RANGE(simulation_physics, "UpdateEntities");
|
||||
// NOTE: the getEntities()->update() call below will wait for lock
|
||||
// and will simulate entity motion (the EntityTree has been given an EntitySimulation).
|
||||
getEntities()->update(true); // update the models...
|
||||
}
|
||||
|
||||
myAvatar->harvestResultsFromPhysicsSimulation(deltaTime);
|
||||
{
|
||||
PROFILE_RANGE(simulation_physics, "MyAvatar");
|
||||
myAvatar->harvestResultsFromPhysicsSimulation(deltaTime);
|
||||
}
|
||||
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::DisplayDebugTimingDetails) &&
|
||||
Menu::getInstance()->isOptionChecked(MenuOption::ExpandPhysicsSimulationTiming)) {
|
||||
|
@ -4928,13 +4935,13 @@ void Application::update(float deltaTime) {
|
|||
// AvatarManager update
|
||||
{
|
||||
{
|
||||
PROFILE_RANGE(simulation, "OtherAvatars");
|
||||
PerformanceTimer perfTimer("otherAvatars");
|
||||
PROFILE_RANGE_EX(simulation, "OtherAvatars", 0xffff00ff, (uint64_t)getActiveDisplayPlugin()->presentCount());
|
||||
avatarManager->updateOtherAvatars(deltaTime);
|
||||
}
|
||||
|
||||
{
|
||||
PROFILE_RANGE_EX(simulation, "MyAvatar", 0xffff00ff, (uint64_t)getActiveDisplayPlugin()->presentCount());
|
||||
PROFILE_RANGE(simulation, "MyAvatar");
|
||||
PerformanceTimer perfTimer("MyAvatar");
|
||||
qApp->updateMyAvatarLookAtPosition();
|
||||
avatarManager->updateMyAvatar(deltaTime);
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "AnimUtil.h"
|
||||
#include "IKTarget.h"
|
||||
|
||||
|
||||
static int nextRigId = 1;
|
||||
static std::map<int, Rig*> rigRegistry;
|
||||
static std::mutex rigRegistryMutex;
|
||||
|
@ -999,14 +1000,13 @@ void Rig::updateAnimationStateHandlers() { // called on avatar update thread (wh
|
|||
}
|
||||
|
||||
void Rig::updateAnimations(float deltaTime, const glm::mat4& rootTransform, const glm::mat4& rigToWorldTransform) {
|
||||
|
||||
PROFILE_RANGE_EX(simulation_animation_detail, __FUNCTION__, 0xffff00ff, 0);
|
||||
PerformanceTimer perfTimer("updateAnimations");
|
||||
DETAILED_PROFILE_RANGE_EX(simulation_animation_detail, __FUNCTION__, 0xffff00ff, 0);
|
||||
DETAILED_PERFORMANCE_TIMER("updateAnimations");
|
||||
|
||||
setModelOffset(rootTransform);
|
||||
|
||||
if (_animNode && _enabledAnimations) {
|
||||
PerformanceTimer perfTimer("handleTriggers");
|
||||
DETAILED_PERFORMANCE_TIMER("handleTriggers");
|
||||
|
||||
updateAnimationStateHandlers();
|
||||
_animVars.setRigToGeometryTransform(_rigToGeometryTransform);
|
||||
|
@ -1658,7 +1658,7 @@ bool Rig::getModelRegistrationPoint(glm::vec3& modelRegistrationPointOut) const
|
|||
}
|
||||
|
||||
void Rig::applyOverridePoses() {
|
||||
PerformanceTimer perfTimer("override");
|
||||
DETAILED_PERFORMANCE_TIMER("override");
|
||||
if (_numOverrides == 0 || !_animSkeleton) {
|
||||
return;
|
||||
}
|
||||
|
@ -1675,7 +1675,7 @@ void Rig::applyOverridePoses() {
|
|||
}
|
||||
|
||||
void Rig::buildAbsoluteRigPoses(const AnimPoseVec& relativePoses, AnimPoseVec& absolutePosesOut) {
|
||||
PerformanceTimer perfTimer("buildAbsolute");
|
||||
DETAILED_PERFORMANCE_TIMER("buildAbsolute");
|
||||
if (!_animSkeleton) {
|
||||
return;
|
||||
}
|
||||
|
@ -1730,8 +1730,9 @@ void Rig::copyJointsIntoJointData(QVector<JointData>& jointDataVec) const {
|
|||
}
|
||||
|
||||
void Rig::copyJointsFromJointData(const QVector<JointData>& jointDataVec) {
|
||||
PerformanceTimer perfTimer("copyJoints");
|
||||
PROFILE_RANGE(simulation_animation_detail, "copyJoints");
|
||||
DETAILED_PROFILE_RANGE(simulation_animation_detail, "copyJoints");
|
||||
DETAILED_PERFORMANCE_TIMER("copyJoints");
|
||||
|
||||
if (!_animSkeleton) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -160,6 +160,8 @@ void EntityTreeRenderer::shutdown() {
|
|||
}
|
||||
|
||||
void EntityTreeRenderer::addPendingEntities(const render::ScenePointer& scene, render::Transaction& transaction) {
|
||||
PROFILE_RANGE_EX(simulation_physics, "Add", 0xffff00ff, (uint64_t)_entitiesToAdd.size());
|
||||
PerformanceTimer pt("add");
|
||||
// Clear any expired entities
|
||||
// FIXME should be able to use std::remove_if, but it fails due to some
|
||||
// weird compilation error related to EntityItemID assignment operators
|
||||
|
@ -203,6 +205,8 @@ void EntityTreeRenderer::addPendingEntities(const render::ScenePointer& scene, r
|
|||
}
|
||||
|
||||
void EntityTreeRenderer::updateChangedEntities(const render::ScenePointer& scene, render::Transaction& transaction) {
|
||||
PROFILE_RANGE_EX(simulation_physics, "Change", 0xffff00ff, (uint64_t)_changedEntities.size());
|
||||
PerformanceTimer pt("change");
|
||||
std::unordered_set<EntityItemID> changedEntities;
|
||||
_changedEntitiesGuard.withWriteLock([&] {
|
||||
#if 0
|
||||
|
@ -223,6 +227,7 @@ void EntityTreeRenderer::updateChangedEntities(const render::ScenePointer& scene
|
|||
}
|
||||
|
||||
if (!_renderablesToUpdate.empty()) {
|
||||
PROFILE_RANGE_EX(simulation_physics, "UpdateRenderables", 0xffff00ff, (uint64_t)_renderablesToUpdate.size());
|
||||
for (const auto& entry : _renderablesToUpdate) {
|
||||
const auto& renderable = entry.second;
|
||||
renderable->updateInScene(scene, transaction);
|
||||
|
@ -232,6 +237,7 @@ void EntityTreeRenderer::updateChangedEntities(const render::ScenePointer& scene
|
|||
}
|
||||
|
||||
void EntityTreeRenderer::update(bool simulate) {
|
||||
PROFILE_RANGE(simulation_physics, "ETR::update");
|
||||
PerformanceTimer perfTimer("ETRupdate");
|
||||
if (_tree && !_shuttingDown) {
|
||||
EntityTreePointer tree = std::static_pointer_cast<EntityTree>(_tree);
|
||||
|
@ -239,22 +245,14 @@ void EntityTreeRenderer::update(bool simulate) {
|
|||
|
||||
// Update the rendereable entities as needed
|
||||
{
|
||||
PROFILE_RANGE(simulation_physics, "Scene");
|
||||
PerformanceTimer sceneTimer("scene");
|
||||
auto scene = _viewState->getMain3DScene();
|
||||
if (scene) {
|
||||
render::Transaction transaction;
|
||||
{
|
||||
PerformanceTimer pt("add");
|
||||
addPendingEntities(scene, transaction);
|
||||
}
|
||||
{
|
||||
PerformanceTimer pt("change");
|
||||
updateChangedEntities(scene, transaction);
|
||||
}
|
||||
{
|
||||
PerformanceTimer pt("enqueue");
|
||||
scene->enqueueTransaction(transaction);
|
||||
}
|
||||
addPendingEntities(scene, transaction);
|
||||
updateChangedEntities(scene, transaction);
|
||||
scene->enqueueTransaction(transaction);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -336,7 +334,8 @@ bool EntityTreeRenderer::findBestZoneAndMaybeContainingEntities(QVector<EntityIt
|
|||
}
|
||||
|
||||
bool EntityTreeRenderer::checkEnterLeaveEntities() {
|
||||
PerformanceTimer perfTimer("checkEnterLeaveEntities");
|
||||
PROFILE_RANGE(simulation_physics, "EnterLeave");
|
||||
PerformanceTimer perfTimer("enterLeave");
|
||||
auto now = usecTimestampNow();
|
||||
bool didUpdate = false;
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "RenderableWebEntityItem.h"
|
||||
#include "RenderableZoneEntityItem.h"
|
||||
|
||||
|
||||
using namespace render;
|
||||
using namespace render::entities;
|
||||
|
||||
|
@ -271,6 +272,7 @@ void EntityRenderer::removeFromScene(const ScenePointer& scene, Transaction& tra
|
|||
}
|
||||
|
||||
void EntityRenderer::updateInScene(const ScenePointer& scene, Transaction& transaction) {
|
||||
DETAILED_PROFILE_RANGE(simulation_physics, __FUNCTION__);
|
||||
if (!isValidRenderItem()) {
|
||||
return;
|
||||
}
|
||||
|
@ -330,6 +332,7 @@ bool EntityRenderer::needsRenderUpdateFromEntity(const EntityItemPointer& entity
|
|||
}
|
||||
|
||||
void EntityRenderer::doRenderUpdateSynchronous(const ScenePointer& scene, Transaction& transaction, const EntityItemPointer& entity) {
|
||||
DETAILED_PROFILE_RANGE(simulation_physics, __FUNCTION__);
|
||||
withWriteLock([&] {
|
||||
auto transparent = isTransparent();
|
||||
if (_prevIsTransparent && !transparent) {
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include "EntityTreeRenderer.h"
|
||||
#include "EntitiesRendererLogging.h"
|
||||
|
||||
|
||||
static CollisionRenderMeshCache collisionMeshCache;
|
||||
|
||||
void ModelEntityWrapper::setModel(const ModelPointer& model) {
|
||||
|
@ -107,6 +108,7 @@ QVariantMap parseTexturesToMap(QString textures, const QVariantMap& defaultTextu
|
|||
}
|
||||
|
||||
void RenderableModelEntityItem::doInitialModelSimulation() {
|
||||
DETAILED_PROFILE_RANGE(simulation_physics, __FUNCTION__);
|
||||
ModelPointer model = getModel();
|
||||
if (!model) {
|
||||
return;
|
||||
|
@ -123,11 +125,11 @@ void RenderableModelEntityItem::doInitialModelSimulation() {
|
|||
model->setSnapModelToRegistrationPoint(true, getRegistrationPoint());
|
||||
model->setRotation(getRotation());
|
||||
model->setTranslation(getPosition());
|
||||
{
|
||||
PerformanceTimer perfTimer("model->simulate");
|
||||
|
||||
if (_needsInitialSimulation) {
|
||||
model->simulate(0.0f);
|
||||
_needsInitialSimulation = false;
|
||||
}
|
||||
_needsInitialSimulation = false;
|
||||
}
|
||||
|
||||
void RenderableModelEntityItem::autoResizeJointArrays() {
|
||||
|
@ -138,6 +140,7 @@ void RenderableModelEntityItem::autoResizeJointArrays() {
|
|||
}
|
||||
|
||||
bool RenderableModelEntityItem::needsUpdateModelBounds() const {
|
||||
DETAILED_PROFILE_RANGE(simulation_physics, __FUNCTION__);
|
||||
ModelPointer model = getModel();
|
||||
if (!hasModel() || !model) {
|
||||
return false;
|
||||
|
@ -151,7 +154,7 @@ bool RenderableModelEntityItem::needsUpdateModelBounds() const {
|
|||
return true;
|
||||
}
|
||||
|
||||
if (isMovingRelativeToParent() || isAnimatingSomething()) {
|
||||
if (isAnimatingSomething()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -178,13 +181,61 @@ bool RenderableModelEntityItem::needsUpdateModelBounds() const {
|
|||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return model->needsReload();
|
||||
}
|
||||
|
||||
void RenderableModelEntityItem::updateModelBounds() {
|
||||
if (needsUpdateModelBounds()) {
|
||||
doInitialModelSimulation();
|
||||
DETAILED_PROFILE_RANGE(simulation_physics, "updateModelBounds");
|
||||
|
||||
if (!_dimensionsInitialized || !hasModel()) {
|
||||
return;
|
||||
}
|
||||
|
||||
ModelPointer model = getModel();
|
||||
if (!model || !model->isLoaded()) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool updateRenderItems = false;
|
||||
if (model->needsReload()) {
|
||||
model->updateGeometry();
|
||||
updateRenderItems = true;
|
||||
}
|
||||
|
||||
if (model->getScaleToFitDimensions() != getDimensions() ||
|
||||
model->getRegistrationPoint() != getRegistrationPoint()) {
|
||||
// The machinery for updateModelBounds will give existing models the opportunity to fix their
|
||||
// translation/rotation/scale/registration. The first two are straightforward, but the latter two
|
||||
// have guards to make sure they don't happen after they've already been set. Here we reset those guards.
|
||||
// This doesn't cause the entity values to change -- it just allows the model to match once it comes in.
|
||||
model->setScaleToFit(false, getDimensions());
|
||||
model->setSnapModelToRegistrationPoint(false, getRegistrationPoint());
|
||||
|
||||
// now recalculate the bounds and registration
|
||||
model->setScaleToFit(true, getDimensions());
|
||||
model->setSnapModelToRegistrationPoint(true, getRegistrationPoint());
|
||||
updateRenderItems = true;
|
||||
}
|
||||
|
||||
bool success;
|
||||
auto transform = getTransform(success);
|
||||
if (success && (model->getTranslation() != transform.getTranslation() ||
|
||||
model->getRotation() != transform.getRotation())) {
|
||||
model->setTransformNoUpdateRenderItems(transform);
|
||||
updateRenderItems = true;
|
||||
}
|
||||
|
||||
if (_needsInitialSimulation || _needsJointSimulation || isAnimatingSomething()) {
|
||||
// NOTE: on isAnimatingSomething() we need to call Model::simulate() which calls Rig::updateRig()
|
||||
// TODO: there is opportunity to further optimize the isAnimatingSomething() case.
|
||||
model->simulate(0.0f);
|
||||
_needsInitialSimulation = false;
|
||||
_needsJointSimulation = false;
|
||||
updateRenderItems = true;
|
||||
}
|
||||
|
||||
if (updateRenderItems) {
|
||||
model->updateRenderItems();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -293,7 +344,7 @@ bool RenderableModelEntityItem::isReadyToComputeShape() const {
|
|||
// we have both URLs AND both geometries AND they are both fully loaded.
|
||||
if (_needsInitialSimulation) {
|
||||
// the _model's offset will be wrong until _needsInitialSimulation is false
|
||||
PerformanceTimer perfTimer("_model->simulate");
|
||||
DETAILED_PERFORMANCE_TIMER("_model->simulate");
|
||||
const_cast<RenderableModelEntityItem*>(this)->doInitialModelSimulation();
|
||||
}
|
||||
return true;
|
||||
|
@ -839,7 +890,7 @@ void RenderableModelEntityItem::setJointTranslationsSet(const QVector<bool>& tra
|
|||
}
|
||||
|
||||
void RenderableModelEntityItem::locationChanged(bool tellPhysics) {
|
||||
PerformanceTimer pertTimer("locationChanged");
|
||||
DETAILED_PERFORMANCE_TIMER("locationChanged");
|
||||
EntityItem::locationChanged(tellPhysics);
|
||||
auto model = getModel();
|
||||
if (model && model->isLoaded()) {
|
||||
|
@ -880,7 +931,6 @@ void RenderableModelEntityItem::copyAnimationJointDataToModel() {
|
|||
return;
|
||||
}
|
||||
|
||||
|
||||
// relay any inbound joint changes from scripts/animation/network to the model/rig
|
||||
_jointDataLock.withWriteLock([&] {
|
||||
for (int index = 0; index < _localJointData.size(); ++index) {
|
||||
|
@ -897,10 +947,6 @@ void RenderableModelEntityItem::copyAnimationJointDataToModel() {
|
|||
});
|
||||
}
|
||||
|
||||
bool RenderableModelEntityItem::isAnimatingSomething() const {
|
||||
return !getAnimationURL().isEmpty() && getAnimationIsPlaying() && getAnimationFPS() != 0.0f;
|
||||
}
|
||||
|
||||
using namespace render;
|
||||
using namespace render::entities;
|
||||
|
||||
|
@ -1124,6 +1170,7 @@ bool ModelEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPoin
|
|||
}
|
||||
|
||||
void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) {
|
||||
DETAILED_PROFILE_RANGE(simulation_physics, __FUNCTION__);
|
||||
if (_hasModel != entity->hasModel()) {
|
||||
_hasModel = entity->hasModel();
|
||||
}
|
||||
|
@ -1202,9 +1249,7 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce
|
|||
}
|
||||
}
|
||||
|
||||
if (entity->needsUpdateModelBounds()) {
|
||||
entity->updateModelBounds();
|
||||
}
|
||||
entity->updateModelBounds();
|
||||
|
||||
if (model->isVisible() != _visible) {
|
||||
// FIXME: this seems like it could be optimized if we tracked our last known visible state in
|
||||
|
@ -1212,13 +1257,16 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce
|
|||
// so most of the time we don't do anything in this function.
|
||||
model->setVisibleInScene(_visible, scene);
|
||||
}
|
||||
// TODO? early exit here when not visible?
|
||||
|
||||
//entity->doInitialModelSimulation();
|
||||
if (model->needsFixupInScene()) {
|
||||
model->removeFromScene(scene, transaction);
|
||||
render::Item::Status::Getters statusGetters;
|
||||
makeStatusGetters(entity, statusGetters);
|
||||
model->addToScene(scene, transaction, statusGetters);
|
||||
{
|
||||
DETAILED_PROFILE_RANGE(simulation_physics, "Fixup");
|
||||
if (model->needsFixupInScene()) {
|
||||
model->removeFromScene(scene, transaction);
|
||||
render::Item::Status::Getters statusGetters;
|
||||
makeStatusGetters(entity, statusGetters);
|
||||
model->addToScene(scene, transaction, statusGetters);
|
||||
}
|
||||
}
|
||||
|
||||
// When the individual mesh parts of a model finish fading, they will mark their Model as needing updating
|
||||
|
@ -1227,16 +1275,20 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce
|
|||
model->updateRenderItems();
|
||||
}
|
||||
|
||||
// make a copy of the animation properites
|
||||
auto newAnimationProperties = entity->getAnimationProperties();
|
||||
if (newAnimationProperties != _renderAnimationProperties) {
|
||||
withWriteLock([&] {
|
||||
_renderAnimationProperties = newAnimationProperties;
|
||||
_currentFrame = _renderAnimationProperties.getCurrentFrame();
|
||||
});
|
||||
{
|
||||
DETAILED_PROFILE_RANGE(simulation_physics, "CheckAnimation");
|
||||
// make a copy of the animation properites
|
||||
auto newAnimationProperties = entity->getAnimationProperties();
|
||||
if (newAnimationProperties != _renderAnimationProperties) {
|
||||
withWriteLock([&] {
|
||||
_renderAnimationProperties = newAnimationProperties;
|
||||
_currentFrame = _renderAnimationProperties.getCurrentFrame();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (_animating) {
|
||||
DETAILED_PROFILE_RANGE(simulation_physics, "Animate");
|
||||
if (!jointsMapped()) {
|
||||
mapJoints(entity, model->getJointNames());
|
||||
}
|
||||
|
@ -1247,8 +1299,8 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce
|
|||
|
||||
// NOTE: this only renders the "meta" portion of the Model, namely it renders debugging items
|
||||
void ModelEntityRenderer::doRender(RenderArgs* args) {
|
||||
PROFILE_RANGE(render_detail, "MetaModelRender");
|
||||
PerformanceTimer perfTimer("RMEIrender");
|
||||
DETAILED_PROFILE_RANGE(render_detail, "MetaModelRender");
|
||||
DETAILED_PERFORMANCE_TIMER("RMEIrender");
|
||||
|
||||
ModelPointer model;
|
||||
withReadLock([&]{
|
||||
|
|
|
@ -108,7 +108,6 @@ public:
|
|||
|
||||
private:
|
||||
bool needsUpdateModelBounds() const;
|
||||
bool isAnimatingSomething() const;
|
||||
void autoResizeJointArrays();
|
||||
void copyAnimationJointDataToModel();
|
||||
|
||||
|
|
|
@ -9,9 +9,11 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include <AACube.h>
|
||||
|
||||
#include "EntitySimulation.h"
|
||||
|
||||
#include <AACube.h>
|
||||
#include <Profile.h>
|
||||
|
||||
#include "EntitiesLogging.h"
|
||||
#include "MovingEntitiesOperator.h"
|
||||
|
||||
|
@ -27,6 +29,7 @@ void EntitySimulation::setEntityTree(EntityTreePointer tree) {
|
|||
}
|
||||
|
||||
void EntitySimulation::updateEntities() {
|
||||
PROFILE_RANGE(simulation_physics, "ES::updateEntities");
|
||||
QMutexLocker lock(&_mutex);
|
||||
quint64 now = usecTimestampNow();
|
||||
|
||||
|
@ -35,8 +38,12 @@ void EntitySimulation::updateEntities() {
|
|||
callUpdateOnEntitiesThatNeedIt(now);
|
||||
moveSimpleKinematics(now);
|
||||
updateEntitiesInternal(now);
|
||||
PerformanceTimer perfTimer("sortingEntities");
|
||||
sortEntitiesThatMoved();
|
||||
|
||||
{
|
||||
PROFILE_RANGE(simulation_physics, "Sort");
|
||||
PerformanceTimer perfTimer("sortingEntities");
|
||||
sortEntitiesThatMoved();
|
||||
}
|
||||
}
|
||||
|
||||
void EntitySimulation::takeEntitiesToDelete(VectorOfEntities& entitiesToDelete) {
|
||||
|
@ -258,6 +265,7 @@ void EntitySimulation::clearEntities() {
|
|||
}
|
||||
|
||||
void EntitySimulation::moveSimpleKinematics(const quint64& now) {
|
||||
PROFILE_RANGE_EX(simulation_physics, "Kinematics", 0xffff00ff, (uint64_t)_simpleKinematicEntities.size());
|
||||
SetOfEntities::iterator itemItr = _simpleKinematicEntities.begin();
|
||||
while (itemItr != _simpleKinematicEntities.end()) {
|
||||
EntityItemPointer entity = *itemItr;
|
||||
|
|
|
@ -15,8 +15,9 @@
|
|||
|
||||
#include <QtScript/QScriptEngine>
|
||||
|
||||
#include <PerfStat.h>
|
||||
#include <Extents.h>
|
||||
#include <PerfStat.h>
|
||||
#include <Profile.h>
|
||||
|
||||
#include "EntitySimulation.h"
|
||||
#include "VariantMapToScriptValue.h"
|
||||
|
@ -1370,6 +1371,7 @@ void EntityTree::entityChanged(EntityItemPointer entity) {
|
|||
|
||||
|
||||
void EntityTree::fixupNeedsParentFixups() {
|
||||
PROFILE_RANGE(simulation_physics, "FixupParents");
|
||||
MovingEntitiesOperator moveOperator;
|
||||
|
||||
QWriteLocker locker(&_needsParentFixupLock);
|
||||
|
@ -1459,6 +1461,7 @@ void EntityTree::addToNeedsParentFixupList(EntityItemPointer entity) {
|
|||
}
|
||||
|
||||
void EntityTree::update(bool simulate) {
|
||||
PROFILE_RANGE(simulation_physics, "ET::update");
|
||||
fixupNeedsParentFixups();
|
||||
if (simulate && _simulation) {
|
||||
withWriteLock([&] {
|
||||
|
|
|
@ -557,12 +557,6 @@ void ModelEntityItem::setAnimationLoop(bool loop) {
|
|||
});
|
||||
}
|
||||
|
||||
bool ModelEntityItem::getAnimationLoop() const {
|
||||
return resultWithReadLock<bool>([&] {
|
||||
return _animationProperties.getLoop();
|
||||
});
|
||||
}
|
||||
|
||||
void ModelEntityItem::setAnimationHold(bool hold) {
|
||||
withWriteLock([&] {
|
||||
_animationProperties.setHold(hold);
|
||||
|
@ -610,8 +604,10 @@ float ModelEntityItem::getAnimationCurrentFrame() const {
|
|||
});
|
||||
}
|
||||
|
||||
float ModelEntityItem::getAnimationFPS() const {
|
||||
bool ModelEntityItem::isAnimatingSomething() const {
|
||||
return resultWithReadLock<float>([&] {
|
||||
return _animationProperties.getFPS();
|
||||
});
|
||||
return !_animationProperties.getURL().isEmpty() &&
|
||||
_animationProperties.getRunning() &&
|
||||
(_animationProperties.getFPS() != 0.0f);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -90,7 +90,6 @@ public:
|
|||
bool getAnimationAllowTranslation() const { return _animationProperties.getAllowTranslation(); };
|
||||
|
||||
void setAnimationLoop(bool loop);
|
||||
bool getAnimationLoop() const;
|
||||
|
||||
void setAnimationHold(bool hold);
|
||||
bool getAnimationHold() const;
|
||||
|
@ -101,10 +100,9 @@ public:
|
|||
void setAnimationLastFrame(float lastFrame);
|
||||
float getAnimationLastFrame() const;
|
||||
|
||||
|
||||
bool getAnimationIsPlaying() const;
|
||||
float getAnimationCurrentFrame() const;
|
||||
float getAnimationFPS() const;
|
||||
bool isAnimatingSomething() const;
|
||||
|
||||
static const QString DEFAULT_TEXTURES;
|
||||
const QString getTextures() const;
|
||||
|
@ -123,7 +121,6 @@ public:
|
|||
QVector<bool> getJointRotationsSet() const;
|
||||
QVector<glm::vec3> getJointTranslations() const;
|
||||
QVector<bool> getJointTranslationsSet() const;
|
||||
bool isAnimatingSomething() const;
|
||||
|
||||
private:
|
||||
void setAnimationSettings(const QString& value); // only called for old bitstream format
|
||||
|
|
|
@ -121,8 +121,6 @@ bool Model::needsFixupInScene() const {
|
|||
return (_needsFixupInScene || !_addedToScene) && !_needsReload && isLoaded();
|
||||
}
|
||||
|
||||
// TODO?: should we combine translation and rotation into single method to avoid double-work?
|
||||
// (figure out where we call these)
|
||||
void Model::setTranslation(const glm::vec3& translation) {
|
||||
_translation = translation;
|
||||
updateRenderItems();
|
||||
|
@ -133,6 +131,14 @@ void Model::setRotation(const glm::quat& rotation) {
|
|||
updateRenderItems();
|
||||
}
|
||||
|
||||
// temporary HACK: set transform while avoiding implicit calls to updateRenderItems()
|
||||
// TODO: make setRotation() and friends set flag to be used later to decide to updateRenderItems()
|
||||
void Model::setTransformNoUpdateRenderItems(const Transform& transform) {
|
||||
_translation = transform.getTranslation();
|
||||
_rotation = transform.getRotation();
|
||||
// DO NOT call updateRenderItems() here!
|
||||
}
|
||||
|
||||
Transform Model::getTransform() const {
|
||||
if (_spatiallyNestableOverride) {
|
||||
bool success;
|
||||
|
@ -957,7 +963,7 @@ Blender::Blender(ModelPointer model, int blendNumber, const Geometry::WeakPointe
|
|||
}
|
||||
|
||||
void Blender::run() {
|
||||
PROFILE_RANGE_EX(simulation_animation, __FUNCTION__, 0xFFFF0000, 0, { { "url", _model->getURL().toString() } });
|
||||
DETAILED_PROFILE_RANGE_EX(simulation_animation, __FUNCTION__, 0xFFFF0000, 0, { { "url", _model->getURL().toString() } });
|
||||
QVector<glm::vec3> vertices, normals;
|
||||
if (_model) {
|
||||
int offset = 0;
|
||||
|
@ -1078,8 +1084,7 @@ void Model::snapToRegistrationPoint() {
|
|||
}
|
||||
|
||||
void Model::simulate(float deltaTime, bool fullUpdate) {
|
||||
PROFILE_RANGE(simulation_detail, __FUNCTION__);
|
||||
PerformanceTimer perfTimer("Model::simulate");
|
||||
DETAILED_PROFILE_RANGE(simulation_detail, __FUNCTION__);
|
||||
fullUpdate = updateGeometry() || fullUpdate || (_scaleToFit && !_scaledToFit)
|
||||
|| (_snapModelToRegistrationPoint && !_snappedToRegistrationPoint);
|
||||
|
||||
|
@ -1117,7 +1122,7 @@ void Model::computeMeshPartLocalBounds() {
|
|||
|
||||
// virtual
|
||||
void Model::updateClusterMatrices() {
|
||||
PerformanceTimer perfTimer("Model::updateClusterMatrices");
|
||||
DETAILED_PERFORMANCE_TIMER("Model::updateClusterMatrices");
|
||||
|
||||
if (!_needsUpdateClusterMatrices || !isLoaded()) {
|
||||
return;
|
||||
|
|
|
@ -206,6 +206,7 @@ public:
|
|||
|
||||
void setTranslation(const glm::vec3& translation);
|
||||
void setRotation(const glm::quat& rotation);
|
||||
void setTransformNoUpdateRenderItems(const Transform& transform); // temporary HACK
|
||||
|
||||
const glm::vec3& getTranslation() const { return _translation; }
|
||||
const glm::quat& getRotation() const { return _rotation; }
|
||||
|
|
|
@ -97,5 +97,12 @@ private:
|
|||
static QMap<QString, PerformanceTimerRecord> _records;
|
||||
};
|
||||
|
||||
// uncomment WANT_DETAILED_PERFORMANCE_TIMERS definition to enable performance timers in high-frequency contexts
|
||||
//#define WANT_DETAILED_PERFORMANCE_TIMERS
|
||||
#ifdef WANT_DETAILED_PERFORMANCE_TIMERS
|
||||
#define DETAILED_PERFORMANCE_TIMER(name) PerformanceTimer detailedPerformanceTimer(name);
|
||||
#else // WANT_DETAILED_PERFORMANCE_TIMERS
|
||||
#define DETAILED_PERFORMANCE_TIMER(name) ; // no-op
|
||||
#endif // WANT_DETAILED_PERFORMANCE_TIMERS
|
||||
|
||||
#endif // hifi_PerfStat_h
|
||||
|
|
|
@ -108,4 +108,14 @@ inline void metadata(const QString& metadataType, const QVariantMap& args) {
|
|||
#define SAMPLE_PROFILE_COUNTER(chance, category, name, ...) if (randFloat() <= chance) { PROFILE_COUNTER(category, name, ##__VA_ARGS__); }
|
||||
#define SAMPLE_PROFILE_INSTANT(chance, category, name, ...) if (randFloat() <= chance) { PROFILE_INSTANT(category, name, ##__VA_ARGS__); }
|
||||
|
||||
// uncomment WANT_DETAILED_PROFILING definition to enable profiling in high-frequency contexts
|
||||
//#define WANT_DETAILED_PROFILING
|
||||
#ifdef WANT_DETAILED_PROFILING
|
||||
#define DETAILED_PROFILE_RANGE(category, name) Duration profileRangeThis(trace_##category(), name);
|
||||
#define DETAILED_PROFILE_RANGE_EX(category, name, argbColor, payload, ...) Duration profileRangeThis(trace_##category(), name, argbColor, (uint64_t)payload, ##__VA_ARGS__);
|
||||
#else // WANT_DETAILED_PROFILING
|
||||
#define DETAILED_PROFILE_RANGE(category, name) ; // no-op
|
||||
#define DETAILED_PROFILE_RANGE_EX(category, name, argbColor, payload, ...) ; // no-op
|
||||
#endif // WANT_DETAILED_PROFILING
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue