add locks and explicitly copy ViewFrustums

This commit is contained in:
Andrew Meadows 2016-03-07 10:04:54 -08:00
parent bcf2cc8074
commit 71b2d647e8
11 changed files with 148 additions and 86 deletions

View file

@ -141,6 +141,16 @@ void OctreeQueryNode::writeToPacket(const unsigned char* buffer, unsigned int by
} }
} }
void OctreeQueryNode::copyCurrentViewFrustum(ViewFrustum& viewOut) const {
QMutexLocker viewLocker(&_viewMutex);
viewOut = _currentViewFrustum;
}
void OctreeQueryNode::copyLastKnownViewFrustum(ViewFrustum& viewOut) const {
QMutexLocker viewLocker(&_viewMutex);
viewOut = _lastKnownViewFrustum;
}
bool OctreeQueryNode::updateCurrentViewFrustum() { bool OctreeQueryNode::updateCurrentViewFrustum() {
// if shutting down, return immediately // if shutting down, return immediately
if (_isShuttingDown) { if (_isShuttingDown) {
@ -171,12 +181,14 @@ bool OctreeQueryNode::updateCurrentViewFrustum() {
} }
// if there has been a change, then recalculate { // if there has been a change, then recalculate
QMutexLocker viewLocker(&_viewMutex);
if (!newestViewFrustum.isVerySimilar(_currentViewFrustum)) { if (!newestViewFrustum.isVerySimilar(_currentViewFrustum)) {
_currentViewFrustum = newestViewFrustum; _currentViewFrustum = newestViewFrustum;
_currentViewFrustum.calculate(); _currentViewFrustum.calculate();
currentViewFrustumChanged = true; currentViewFrustumChanged = true;
} }
}
// Also check for LOD changes from the client // Also check for LOD changes from the client
if (_lodInitialized) { if (_lodInitialized) {
@ -219,12 +231,15 @@ void OctreeQueryNode::updateLastKnownViewFrustum() {
return; return;
} }
{
QMutexLocker viewLocker(&_viewMutex);
bool frustumChanges = !_lastKnownViewFrustum.isVerySimilar(_currentViewFrustum); bool frustumChanges = !_lastKnownViewFrustum.isVerySimilar(_currentViewFrustum);
if (frustumChanges) { if (frustumChanges) {
// save our currentViewFrustum into our lastKnownViewFrustum // save our currentViewFrustum into our lastKnownViewFrustum
_lastKnownViewFrustum = _currentViewFrustum; _lastKnownViewFrustum = _currentViewFrustum;
} }
}
// save that we know the view has been sent. // save that we know the view has been sent.
setLastTimeBagEmpty(); setLastTimeBagEmpty();
@ -237,15 +252,13 @@ bool OctreeQueryNode::moveShouldDump() const {
return false; return false;
} }
QMutexLocker viewLocker(&_viewMutex);
glm::vec3 oldPosition = _lastKnownViewFrustum.getPosition(); glm::vec3 oldPosition = _lastKnownViewFrustum.getPosition();
glm::vec3 newPosition = _currentViewFrustum.getPosition(); glm::vec3 newPosition = _currentViewFrustum.getPosition();
// theoretically we could make this slightly larger but relative to avatar scale. // theoretically we could make this slightly larger but relative to avatar scale.
const float MAXIMUM_MOVE_WITHOUT_DUMP = 0.0f; const float MAXIMUM_MOVE_WITHOUT_DUMP = 0.0f;
if (glm::distance(newPosition, oldPosition) > MAXIMUM_MOVE_WITHOUT_DUMP) { return glm::distance(newPosition, oldPosition) > MAXIMUM_MOVE_WITHOUT_DUMP;
return true;
}
return false;
} }
void OctreeQueryNode::dumpOutOfView() { void OctreeQueryNode::dumpOutOfView() {
@ -257,8 +270,13 @@ void OctreeQueryNode::dumpOutOfView() {
int stillInView = 0; int stillInView = 0;
int outOfView = 0; int outOfView = 0;
OctreeElementBag tempBag; OctreeElementBag tempBag;
ViewFrustum viewCopy;
{
QMutexLocker viewLocker(&_viewMutex);
viewCopy = _currentViewFrustum;
}
while (OctreeElementPointer elementToCheck = elementBag.extract()) { while (OctreeElementPointer elementToCheck = elementBag.extract()) {
if (elementToCheck->isInView(_currentViewFrustum)) { if (elementToCheck->isInView(viewCopy)) {
tempBag.insert(elementToCheck); tempBag.insert(elementToCheck);
stillInView++; stillInView++;
} else { } else {
@ -267,7 +285,7 @@ void OctreeQueryNode::dumpOutOfView() {
} }
if (stillInView > 0) { if (stillInView > 0) {
while (OctreeElementPointer elementToKeepInBag = tempBag.extract()) { while (OctreeElementPointer elementToKeepInBag = tempBag.extract()) {
if (elementToKeepInBag->isInView(_currentViewFrustum)) { if (elementToKeepInBag->isInView(viewCopy)) {
elementBag.insert(elementToKeepInBag); elementBag.insert(elementToKeepInBag);
} }
} }

View file

@ -56,8 +56,8 @@ public:
OctreeElementBag elementBag; OctreeElementBag elementBag;
OctreeElementExtraEncodeData extraEncodeData; OctreeElementExtraEncodeData extraEncodeData;
const ViewFrustum& getCurrentViewFrustum() const { return _currentViewFrustum; } void copyCurrentViewFrustum(ViewFrustum& viewOut) const;
const ViewFrustum& getLastKnownViewFrustum() const { return _lastKnownViewFrustum; } void copyLastKnownViewFrustum(ViewFrustum& viewOut) const;
// These are not classic setters because they are calculating and maintaining state // These are not classic setters because they are calculating and maintaining state
// which is set asynchronously through the network receive // which is set asynchronously through the network receive
@ -114,6 +114,8 @@ private:
int _maxSearchLevel { 1 }; int _maxSearchLevel { 1 };
int _maxLevelReachedInLastSearch { 1 }; int _maxLevelReachedInLastSearch { 1 };
mutable QMutex _viewMutex { QMutex::Recursive };
ViewFrustum _currentViewFrustum; ViewFrustum _currentViewFrustum;
ViewFrustum _lastKnownViewFrustum; ViewFrustum _lastKnownViewFrustum;
quint64 _lastTimeBagEmpty { 0 }; quint64 _lastTimeBagEmpty { 0 };

View file

@ -427,9 +427,9 @@ int OctreeSendThread::packetDistributor(SharedNodePointer node, OctreeQueryNode*
nodeData->getLastTimeBagEmpty(), nodeData->getLastTimeBagEmpty(),
isFullScene, &nodeData->stats, _myServer->getJurisdiction(), isFullScene, &nodeData->stats, _myServer->getJurisdiction(),
&nodeData->extraEncodeData); &nodeData->extraEncodeData);
params.viewFrustum = nodeData->getCurrentViewFrustum(); nodeData->copyCurrentViewFrustum(params.viewFrustum);
if (viewFrustumChanged) { if (viewFrustumChanged) {
params.lastViewFrustum = nodeData->getLastKnownViewFrustum(); nodeData->copyLastKnownViewFrustum(params.lastViewFrustum);
} }
// Our trackSend() function is implemented by the server subclass, and will be called back // Our trackSend() function is implemented by the server subclass, and will be called back

View file

@ -1511,12 +1511,17 @@ void Application::paintGL() {
auto lodManager = DependencyManager::get<LODManager>(); auto lodManager = DependencyManager::get<LODManager>();
{
QMutexLocker viewLocker(&_viewMutex);
_viewFrustum.calculate(); _viewFrustum.calculate();
}
RenderArgs renderArgs(_gpuContext, getEntities(), lodManager->getOctreeSizeScale(), RenderArgs renderArgs(_gpuContext, getEntities(), lodManager->getOctreeSizeScale(),
lodManager->getBoundaryLevelAdjust(), RenderArgs::DEFAULT_RENDER_MODE, lodManager->getBoundaryLevelAdjust(), RenderArgs::DEFAULT_RENDER_MODE,
RenderArgs::MONO, RenderArgs::RENDER_DEBUG_NONE); RenderArgs::MONO, RenderArgs::RENDER_DEBUG_NONE);
renderArgs.setViewFrustum(getViewFrustum()); {
QMutexLocker viewLocker(&_viewMutex);
renderArgs.setViewFrustum(_viewFrustum);
}
PerformanceWarning::setSuppressShortTimings(Menu::getInstance()->isOptionChecked(MenuOption::SuppressShortTimings)); PerformanceWarning::setSuppressShortTimings(Menu::getInstance()->isOptionChecked(MenuOption::SuppressShortTimings));
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
@ -1813,7 +1818,10 @@ void Application::resizeGL() {
_myCamera.setProjection(glm::perspective(glm::radians(_fieldOfView.get()), aspectRatio, _myCamera.setProjection(glm::perspective(glm::radians(_fieldOfView.get()), aspectRatio,
DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP)); DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP));
// Possible change in aspect ratio // Possible change in aspect ratio
{
QMutexLocker viewLocker(&_viewMutex);
loadViewFrustum(_myCamera, _viewFrustum); loadViewFrustum(_myCamera, _viewFrustum);
}
auto offscreenUi = DependencyManager::get<OffscreenUi>(); auto offscreenUi = DependencyManager::get<OffscreenUi>();
auto uiSize = displayPlugin->getRecommendedUiSize(); auto uiSize = displayPlugin->getRecommendedUiSize();
@ -2140,6 +2148,7 @@ void Application::keyPressEvent(QKeyEvent* event) {
case Qt::Key_J: case Qt::Key_J:
if (isShifted) { if (isShifted) {
QMutexLocker viewLocker(&_viewMutex);
_viewFrustum.setFocalLength(_viewFrustum.getFocalLength() - 0.1f); _viewFrustum.setFocalLength(_viewFrustum.getFocalLength() - 0.1f);
} else { } else {
_myCamera.setEyeOffsetPosition(_myCamera.getEyeOffsetPosition() + glm::vec3(-0.001, 0, 0)); _myCamera.setEyeOffsetPosition(_myCamera.getEyeOffsetPosition() + glm::vec3(-0.001, 0, 0));
@ -2149,6 +2158,7 @@ void Application::keyPressEvent(QKeyEvent* event) {
case Qt::Key_M: case Qt::Key_M:
if (isShifted) { if (isShifted) {
QMutexLocker viewLocker(&_viewMutex);
_viewFrustum.setFocalLength(_viewFrustum.getFocalLength() + 0.1f); _viewFrustum.setFocalLength(_viewFrustum.getFocalLength() + 0.1f);
} else { } else {
_myCamera.setEyeOffsetPosition(_myCamera.getEyeOffsetPosition() + glm::vec3(0.001, 0, 0)); _myCamera.setEyeOffsetPosition(_myCamera.getEyeOffsetPosition() + glm::vec3(0.001, 0, 0));
@ -2997,7 +3007,10 @@ void Application::init() {
DependencyManager::get<NodeList>()->sendDomainServerCheckIn(); DependencyManager::get<NodeList>()->sendDomainServerCheckIn();
getEntities()->init(); getEntities()->init();
getEntities()->setViewFrustum(getViewFrustum()); {
QMutexLocker viewLocker(&_viewMutex);
getEntities()->setViewFrustum(_viewFrustum);
}
ObjectMotionState::setShapeManager(&_shapeManager); ObjectMotionState::setShapeManager(&_shapeManager);
_physicsEngine->init(); _physicsEngine->init();
@ -3017,7 +3030,10 @@ void Application::init() {
getEntities()->connectSignalsToSlots(entityScriptingInterface.data()); getEntities()->connectSignalsToSlots(entityScriptingInterface.data());
_entityClipboardRenderer.init(); _entityClipboardRenderer.init();
_entityClipboardRenderer.setViewFrustum(getViewFrustum()); {
QMutexLocker viewLocker(&_viewMutex);
_entityClipboardRenderer.setViewFrustum(_viewFrustum);
}
_entityClipboardRenderer.setTree(_entityClipboard); _entityClipboardRenderer.setTree(_entityClipboard);
// Make sure any new sounds are loaded as soon as know about them. // Make sure any new sounds are loaded as soon as know about them.
@ -3220,9 +3236,12 @@ void Application::resetPhysicsReadyInformation() {
void Application::reloadResourceCaches() { void Application::reloadResourceCaches() {
resetPhysicsReadyInformation(); resetPhysicsReadyInformation();
// Clear entities out of view frustum {
QMutexLocker viewLocker(&_viewMutex);
_viewFrustum.setPosition(glm::vec3(0.0f, 0.0f, TREE_SCALE)); _viewFrustum.setPosition(glm::vec3(0.0f, 0.0f, TREE_SCALE));
_viewFrustum.setOrientation(glm::quat()); _viewFrustum.setOrientation(glm::quat());
}
// Clear entities out of view frustum
queryOctree(NodeType::EntityServer, PacketType::EntityQuery, _entityServerJurisdictions); queryOctree(NodeType::EntityServer, PacketType::EntityQuery, _entityServerJurisdictions);
DependencyManager::get<AssetClient>()->clearCache(); DependencyManager::get<AssetClient>()->clearCache();
@ -3511,7 +3530,7 @@ void Application::update(float deltaTime) {
// actually need to calculate the view frustum planes to send these details // actually need to calculate the view frustum planes to send these details
// to the server. // to the server.
{ {
PerformanceTimer perfTimer("loadViewFrustum"); QMutexLocker viewLocker(&_viewMutex);
loadViewFrustum(_myCamera, _viewFrustum); loadViewFrustum(_myCamera, _viewFrustum);
} }
@ -3520,6 +3539,7 @@ void Application::update(float deltaTime) {
// Update my voxel servers with my current voxel query... // Update my voxel servers with my current voxel query...
{ {
PROFILE_RANGE_EX("QueryOctree", 0xffff0000, (uint64_t)getActiveDisplayPlugin()->presentCount()); PROFILE_RANGE_EX("QueryOctree", 0xffff0000, (uint64_t)getActiveDisplayPlugin()->presentCount());
QMutexLocker viewLocker(&_viewMutex);
PerformanceTimer perfTimer("queryOctree"); PerformanceTimer perfTimer("queryOctree");
quint64 sinceLastQuery = now - _lastQueriedTime; quint64 sinceLastQuery = now - _lastQueriedTime;
const quint64 TOO_LONG_SINCE_LAST_QUERY = 3 * USECS_PER_SECOND; const quint64 TOO_LONG_SINCE_LAST_QUERY = 3 * USECS_PER_SECOND;
@ -3631,14 +3651,19 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node
//qCDebug(interfaceapp) << ">>> inside... queryOctree()... _viewFrustum.getFieldOfView()=" << _viewFrustum.getFieldOfView(); //qCDebug(interfaceapp) << ">>> inside... queryOctree()... _viewFrustum.getFieldOfView()=" << _viewFrustum.getFieldOfView();
bool wantExtraDebugging = getLogger()->extraDebugging(); bool wantExtraDebugging = getLogger()->extraDebugging();
_octreeQuery.setCameraPosition(_viewFrustum.getPosition()); ViewFrustum viewFrustumCopy;
_octreeQuery.setCameraOrientation(_viewFrustum.getOrientation()); {
_octreeQuery.setCameraFov(_viewFrustum.getFieldOfView()); QMutexLocker viewLocker(&_viewMutex);
_octreeQuery.setCameraAspectRatio(_viewFrustum.getAspectRatio()); viewFrustumCopy = _viewFrustum;
_octreeQuery.setCameraNearClip(_viewFrustum.getNearClip()); }
_octreeQuery.setCameraFarClip(_viewFrustum.getFarClip()); _octreeQuery.setCameraPosition(viewFrustumCopy.getPosition());
_octreeQuery.setCameraOrientation(viewFrustumCopy.getOrientation());
_octreeQuery.setCameraFov(viewFrustumCopy.getFieldOfView());
_octreeQuery.setCameraAspectRatio(viewFrustumCopy.getAspectRatio());
_octreeQuery.setCameraNearClip(viewFrustumCopy.getNearClip());
_octreeQuery.setCameraFarClip(viewFrustumCopy.getFarClip());
_octreeQuery.setCameraEyeOffsetPosition(glm::vec3()); _octreeQuery.setCameraEyeOffsetPosition(glm::vec3());
_octreeQuery.setCameraCenterRadius(_viewFrustum.getCenterRadius()); _octreeQuery.setCameraCenterRadius(viewFrustumCopy.getCenterRadius());
auto lodManager = DependencyManager::get<LODManager>(); auto lodManager = DependencyManager::get<LODManager>();
_octreeQuery.setOctreeSizeScale(lodManager->getOctreeSizeScale()); _octreeQuery.setOctreeSizeScale(lodManager->getOctreeSizeScale());
_octreeQuery.setBoundaryLevelAdjust(lodManager->getBoundaryLevelAdjust()); _octreeQuery.setBoundaryLevelAdjust(lodManager->getBoundaryLevelAdjust());
@ -3674,7 +3699,7 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node
rootDetails.y * TREE_SCALE, rootDetails.y * TREE_SCALE,
rootDetails.z * TREE_SCALE) - glm::vec3(HALF_TREE_SCALE), rootDetails.z * TREE_SCALE) - glm::vec3(HALF_TREE_SCALE),
rootDetails.s * TREE_SCALE); rootDetails.s * TREE_SCALE);
if (_viewFrustum.cubeIntersectsKeyhole(serverBounds)) { if (viewFrustumCopy.cubeIntersectsKeyhole(serverBounds)) {
inViewServers++; inViewServers++;
} }
} }
@ -3740,7 +3765,7 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node
rootDetails.s * TREE_SCALE); rootDetails.s * TREE_SCALE);
inView = _viewFrustum.cubeIntersectsKeyhole(serverBounds); inView = viewFrustumCopy.cubeIntersectsKeyhole(serverBounds);
} else { } else {
if (wantExtraDebugging) { if (wantExtraDebugging) {
qCDebug(interfaceapp) << "Jurisdiction without RootCode for node " << *node << ". That's unusual!"; qCDebug(interfaceapp) << "Jurisdiction without RootCode for node " << *node << ". That's unusual!";
@ -3835,6 +3860,7 @@ QRect Application::getDesirableApplicationGeometry() const {
// or the "myCamera". // or the "myCamera".
// //
void Application::loadViewFrustum(Camera& camera, ViewFrustum& viewFrustum) { void Application::loadViewFrustum(Camera& camera, ViewFrustum& viewFrustum) {
PerformanceTimer perfTimer("loadViewFrustum");
PROFILE_RANGE(__FUNCTION__); PROFILE_RANGE(__FUNCTION__);
// We will use these below, from either the camera or head vectors calculated above // We will use these below, from either the camera or head vectors calculated above
viewFrustum.setProjection(camera.getProjection()); viewFrustum.setProjection(camera.getProjection());
@ -3863,7 +3889,8 @@ PickRay Application::computePickRay(float x, float y) const {
getApplicationCompositor().computeHmdPickRay(pickPoint, result.origin, result.direction); getApplicationCompositor().computeHmdPickRay(pickPoint, result.origin, result.direction);
} else { } else {
pickPoint /= getCanvasSize(); pickPoint /= getCanvasSize();
getViewFrustum().computePickRay(pickPoint.x, pickPoint.y, result.origin, result.direction); QMutexLocker viewLocker(&_viewMutex);
_viewFrustum.computePickRay(pickPoint.x, pickPoint.y, result.origin, result.direction);
} }
return result; return result;
} }
@ -3876,24 +3903,19 @@ glm::vec3 Application::getAvatarPosition() const {
return getMyAvatar()->getPosition(); return getMyAvatar()->getPosition();
} }
const ViewFrustum& Application::getViewFrustum() const { void Application::copyViewFrustum(ViewFrustum& viewOut) const {
#ifdef DEBUG QMutexLocker viewLocker(&_viewMutex);
if (QThread::currentThread() == activeRenderingThread) { viewOut = _viewFrustum;
// FIXME, figure out a better way to do this
//qWarning() << "Calling Application::getViewFrustum() from the active rendering thread, did you mean Application::getDisplayViewFrustum()?";
}
#endif
return _viewFrustum;
} }
const ViewFrustum& Application::getDisplayViewFrustum() const { void Application::copyDisplayViewFrustum(ViewFrustum& viewOut) const {
#ifdef DEBUG QMutexLocker viewLocker(&_viewMutex);
if (QThread::currentThread() != activeRenderingThread) { viewOut = _displayViewFrustum;
// FIXME, figure out a better way to do this }
// qWarning() << "Calling Application::getDisplayViewFrustum() from outside the active rendering thread or outside rendering, did you mean Application::getViewFrustum()?";
} void Application::copyShadowViewFrustum(ViewFrustum& viewOut) const {
#endif QMutexLocker viewLocker(&_viewMutex);
return _displayViewFrustum; viewOut = _shadowViewFrustum;
} }
// WorldBox Render Data & rendering functions // WorldBox Render Data & rendering functions
@ -4002,7 +4024,10 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "Application::displaySide()"); PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "Application::displaySide()");
// load the view frustum // load the view frustum
{
QMutexLocker viewLocker(&_viewMutex);
loadViewFrustum(theCamera, _displayViewFrustum); loadViewFrustum(theCamera, _displayViewFrustum);
}
// TODO fix shadows and make them use the GPU library // TODO fix shadows and make them use the GPU library
@ -4070,7 +4095,10 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se
{ {
PerformanceTimer perfTimer("EngineRun"); PerformanceTimer perfTimer("EngineRun");
renderArgs->setViewFrustum(getDisplayViewFrustum()); {
QMutexLocker viewLocker(&_viewMutex);
renderArgs->setViewFrustum(_displayViewFrustum);
}
_renderEngine->getRenderContext()->args = renderArgs; _renderEngine->getRenderContext()->args = renderArgs;
// Before the deferred pass, let's try to use the render engine // Before the deferred pass, let's try to use the render engine
@ -4496,6 +4524,11 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri
scriptEngine->registerGlobalObject("Reticle", getApplicationCompositor().getReticleInterface()); scriptEngine->registerGlobalObject("Reticle", getApplicationCompositor().getReticleInterface());
} }
void Application::copyCurrentViewFrustum(ViewFrustum& viewOut) const {
QMutexLocker viewLocker(&_viewMutex);
viewOut = _displayViewFrustum;
}
bool Application::canAcceptURL(const QString& urlString) const { bool Application::canAcceptURL(const QString& urlString) const {
QUrl url(urlString); QUrl url(urlString);
if (urlString.startsWith(HIFI_URL_SCHEME)) { if (urlString.startsWith(HIFI_URL_SCHEME)) {
@ -5200,10 +5233,10 @@ void Application::updateInputModes() {
} }
mat4 Application::getEyeProjection(int eye) const { mat4 Application::getEyeProjection(int eye) const {
QMutexLocker viewLocker(&_viewMutex);
if (isHMDMode()) { if (isHMDMode()) {
return getActiveDisplayPlugin()->getEyeProjection((Eye)eye, _viewFrustum.getProjection()); return getActiveDisplayPlugin()->getEyeProjection((Eye)eye, _viewFrustum.getProjection());
} }
return _viewFrustum.getProjection(); return _viewFrustum.getProjection();
} }

View file

@ -128,12 +128,12 @@ public:
Camera* getCamera() { return &_myCamera; } Camera* getCamera() { return &_myCamera; }
const Camera* getCamera() const { return &_myCamera; } const Camera* getCamera() const { return &_myCamera; }
// Represents the current view frustum of the avatar. // Represents the current view frustum of the avatar.
const ViewFrustum& getViewFrustum() const; void copyViewFrustum(ViewFrustum& viewOut) const;
// Represents the view frustum of the current rendering pass, // Represents the view frustum of the current rendering pass,
// which might be different from the viewFrustum, i.e. shadowmap // which might be different from the viewFrustum, i.e. shadowmap
// passes, mirror window passes, etc // passes, mirror window passes, etc
const ViewFrustum& getDisplayViewFrustum() const; void copyDisplayViewFrustum(ViewFrustum& viewOut) const;
const ViewFrustum& getShadowViewFrustum() override { return _shadowViewFrustum; } void copyShadowViewFrustum(ViewFrustum& viewOut) const override;
const OctreePacketProcessor& getOctreePacketProcessor() const { return _octreeProcessor; } const OctreePacketProcessor& getOctreePacketProcessor() const { return _octreeProcessor; }
EntityTreeRenderer* getEntities() const { return DependencyManager::get<EntityTreeRenderer>().data(); } EntityTreeRenderer* getEntities() const { return DependencyManager::get<EntityTreeRenderer>().data(); }
QUndoStack* getUndoStack() { return &_undoStack; } QUndoStack* getUndoStack() { return &_undoStack; }
@ -167,7 +167,7 @@ public:
virtual controller::ScriptingInterface* getControllerScriptingInterface() { return _controllerScriptingInterface; } virtual controller::ScriptingInterface* getControllerScriptingInterface() { return _controllerScriptingInterface; }
virtual void registerScriptEngineWithApplicationServices(ScriptEngine* scriptEngine) override; virtual void registerScriptEngineWithApplicationServices(ScriptEngine* scriptEngine) override;
virtual const ViewFrustum& getCurrentViewFrustum() override { return getDisplayViewFrustum(); } virtual void copyCurrentViewFrustum(ViewFrustum& viewOut) const override;
virtual QThread* getMainThread() override { return thread(); } virtual QThread* getMainThread() override { return thread(); }
virtual PickRay computePickRay(float x, float y) const override; virtual PickRay computePickRay(float x, float y) const override;
virtual glm::vec3 getAvatarPosition() const override; virtual glm::vec3 getAvatarPosition() const override;
@ -412,6 +412,7 @@ private:
EntityTreeRenderer _entityClipboardRenderer; EntityTreeRenderer _entityClipboardRenderer;
EntityTreePointer _entityClipboard; EntityTreePointer _entityClipboard;
mutable QMutex _viewMutex { QMutex::Recursive };
ViewFrustum _viewFrustum; // current state of view frustum, perspective, orientation, etc. ViewFrustum _viewFrustum; // current state of view frustum, perspective, orientation, etc.
ViewFrustum _lastQueriedViewFrustum; /// last view frustum used to query octree servers (voxels) ViewFrustum _lastQueriedViewFrustum; /// last view frustum used to query octree servers (voxels)
ViewFrustum _displayViewFrustum; ViewFrustum _displayViewFrustum;

View file

@ -172,7 +172,9 @@ void Avatar::simulate(float deltaTime) {
// update the shouldAnimate flag to match whether or not we will render the avatar. // update the shouldAnimate flag to match whether or not we will render the avatar.
const float MINIMUM_VISIBILITY_FOR_ON = 0.4f; const float MINIMUM_VISIBILITY_FOR_ON = 0.4f;
const float MAXIMUM_VISIBILITY_FOR_OFF = 0.6f; const float MAXIMUM_VISIBILITY_FOR_OFF = 0.6f;
float visibility = calculateRenderAccuracy(qApp->getViewFrustum().getPosition(), ViewFrustum viewFrustum;
qApp->copyViewFrustum(viewFrustum);
float visibility = calculateRenderAccuracy(viewFrustum.getPosition(),
getBounds(), DependencyManager::get<LODManager>()->getOctreeSizeScale()); getBounds(), DependencyManager::get<LODManager>()->getOctreeSizeScale());
if (!_shouldAnimate) { if (!_shouldAnimate) {
if (visibility > MINIMUM_VISIBILITY_FOR_ON) { if (visibility > MINIMUM_VISIBILITY_FOR_ON) {
@ -186,8 +188,9 @@ void Avatar::simulate(float deltaTime) {
// simple frustum check // simple frustum check
float boundingRadius = getBoundingRadius(); float boundingRadius = getBoundingRadius();
bool avatarPositionInView = qApp->getDisplayViewFrustum()->sphereIntersectsFrustum(getPosition(), boundingRadius); qApp->copyDisplayViewFrustum(viewFrustum);
bool avatarMeshInView = qApp->getDisplayViewFrustum()->boxIntersectsFrustum(_skeletonModel->getRenderableMeshBound()); bool avatarPositionInView = viewFrustum.sphereIntersectsFrustum(getPosition(), boundingRadius);
bool avatarMeshInView = viewFrustum.boxIntersectsFrustum(_skeletonModel->getRenderableMeshBound());
if (_shouldAnimate && !_shouldSkipRender && (avatarPositionInView || avatarMeshInView)) { if (_shouldAnimate && !_shouldSkipRender && (avatarPositionInView || avatarMeshInView)) {
{ {
@ -384,9 +387,12 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) {
} }
{ // simple frustum check { // simple frustum check
const ViewFrustum& frustum = renderArgs->_renderMode == RenderArgs::SHADOW_RENDER_MODE ? ViewFrustum frustum;
qApp->getShadowViewFrustum() : if (renderArgs->_renderMode == RenderArgs::SHADOW_RENDER_MODE) {
qApp->getDisplayViewFrustum(); qApp->copyShadowViewFrustum(frustum);
} else {
qApp->copyDisplayViewFrustum(frustum);
}
if (!frustum.sphereIntersectsFrustum(getPosition(), getBoundingRadius())) { if (!frustum.sphereIntersectsFrustum(getPosition(), getBoundingRadius())) {
return; return;
} }
@ -500,7 +506,7 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) {
auto cameraMode = qApp->getCamera()->getMode(); auto cameraMode = qApp->getCamera()->getMode();
if (!isMyAvatar() || cameraMode != CAMERA_MODE_FIRST_PERSON) { if (!isMyAvatar() || cameraMode != CAMERA_MODE_FIRST_PERSON) {
auto frustum = renderArgs->getViewFrustum(); ViewFrustum frustum = renderArgs->getViewFrustum();
auto textPosition = getDisplayNamePosition(); auto textPosition = getDisplayNamePosition();
if (frustum.pointIntersectsFrustum(textPosition)) { if (frustum.pointIntersectsFrustum(textPosition)) {
renderDisplayName(batch, frustum, textPosition); renderDisplayName(batch, frustum, textPosition);
@ -550,7 +556,7 @@ void Avatar::fixupModelsInScene() {
scene->enqueuePendingChanges(pendingChanges); scene->enqueuePendingChanges(pendingChanges);
} }
void Avatar::renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, float glowLevel) { void Avatar::renderBody(RenderArgs* renderArgs, float glowLevel) {
fixupModelsInScene(); fixupModelsInScene();
getHead()->renderLookAts(renderArgs); getHead()->renderLookAts(renderArgs);
} }

View file

@ -29,8 +29,6 @@ class Head : public HeadData {
public: public:
explicit Head(Avatar* owningAvatar); explicit Head(Avatar* owningAvatar);
Head(Avatar* owningAvatar);
void init(); void init();
void reset(); void reset();
void simulate(float deltaTime, bool isMine, bool billboard = false); void simulate(float deltaTime, bool isMine, bool billboard = false);

View file

@ -546,7 +546,9 @@ void MyAvatar::updateFromTrackers(float deltaTime) {
head->setDeltaYaw(estimatedRotation.y); head->setDeltaYaw(estimatedRotation.y);
head->setDeltaRoll(estimatedRotation.z); head->setDeltaRoll(estimatedRotation.z);
} else { } else {
float magnifyFieldOfView = qApp->getViewFrustum().getFieldOfView() / _realWorldFieldOfView.get(); ViewFrustum viewFrustum;
qApp->copyViewFrustum(viewFrustum);
float magnifyFieldOfView = viewFrustum.getFieldOfView() / _realWorldFieldOfView.get();
head->setDeltaPitch(estimatedRotation.x * magnifyFieldOfView); head->setDeltaPitch(estimatedRotation.x * magnifyFieldOfView);
head->setDeltaYaw(estimatedRotation.y * magnifyFieldOfView); head->setDeltaYaw(estimatedRotation.y * magnifyFieldOfView);
head->setDeltaRoll(estimatedRotation.z); head->setDeltaRoll(estimatedRotation.z);
@ -929,15 +931,17 @@ void MyAvatar::updateLookAtTargetAvatar() {
// (We will be adding that offset to the camera position, after making some other adjustments.) // (We will be adding that offset to the camera position, after making some other adjustments.)
glm::vec3 gazeOffset = lookAtPosition - getHead()->getEyePosition(); glm::vec3 gazeOffset = lookAtPosition - getHead()->getEyePosition();
ViewFrustum viewFrustum;
qApp->copyViewFrustum(viewFrustum);
// scale gazeOffset by IPD, if wearing an HMD. // scale gazeOffset by IPD, if wearing an HMD.
if (qApp->isHMDMode()) { if (qApp->isHMDMode()) {
glm::mat4 leftEye = qApp->getEyeOffset(Eye::Left); glm::mat4 leftEye = qApp->getEyeOffset(Eye::Left);
glm::mat4 rightEye = qApp->getEyeOffset(Eye::Right); glm::mat4 rightEye = qApp->getEyeOffset(Eye::Right);
glm::vec3 leftEyeHeadLocal = glm::vec3(leftEye[3]); glm::vec3 leftEyeHeadLocal = glm::vec3(leftEye[3]);
glm::vec3 rightEyeHeadLocal = glm::vec3(rightEye[3]); glm::vec3 rightEyeHeadLocal = glm::vec3(rightEye[3]);
auto humanSystem = qApp->getViewFrustum(); glm::vec3 humanLeftEye = viewFrustum.getPosition() + (viewFrustum.getOrientation() * leftEyeHeadLocal);
glm::vec3 humanLeftEye = humanSystem.getPosition() + (humanSystem.getOrientation() * leftEyeHeadLocal); glm::vec3 humanRightEye = viewFrustum.getPosition() + (viewFrustum.getOrientation() * rightEyeHeadLocal);
glm::vec3 humanRightEye = humanSystem.getPosition() + (humanSystem.getOrientation() * rightEyeHeadLocal);
auto hmdInterface = DependencyManager::get<HMDScriptingInterface>(); auto hmdInterface = DependencyManager::get<HMDScriptingInterface>();
float ipdScale = hmdInterface->getIPDScale(); float ipdScale = hmdInterface->getIPDScale();
@ -951,7 +955,7 @@ void MyAvatar::updateLookAtTargetAvatar() {
} }
// And now we can finally add that offset to the camera. // And now we can finally add that offset to the camera.
glm::vec3 corrected = qApp->getViewFrustum().getPosition() + gazeOffset; glm::vec3 corrected = viewFrustum.getPosition() + gazeOffset;
avatar->getHead()->setCorrectedLookAtPosition(corrected); avatar->getHead()->setCorrectedLookAtPosition(corrected);

View file

@ -28,11 +28,11 @@ class PickRay;
/// Interface provided by Application to other objects that need access to the current view state details /// Interface provided by Application to other objects that need access to the current view state details
class AbstractViewStateInterface { class AbstractViewStateInterface {
public: public:
/// gets the current view frustum for rendering the view state /// copies the current view frustum for rendering the view state
virtual const ViewFrustum& getCurrentViewFrustum() = 0; virtual void copyCurrentViewFrustum(ViewFrustum& viewOut) const = 0;
/// gets the shadow view frustum for rendering the view state /// copies the shadow view frustum for rendering the view state
virtual const ViewFrustum& getShadowViewFrustum() = 0; virtual void copyShadowViewFrustum(ViewFrustum& viewOut) const = 0;
virtual QThread* getMainThread() = 0; virtual QThread* getMainThread() = 0;

View file

@ -202,7 +202,7 @@ void DrawDeferred::run(const SceneContextPointer& sceneContext, const RenderCont
void DrawStateSortDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemBounds& inItems) { void DrawStateSortDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemBounds& inItems) {
assert(renderContext->args); assert(renderContext->args);
assert(renderContext->args->_viewFrustum); assert(renderContext->args->hasViewFrustum());
auto config = std::static_pointer_cast<Config>(renderContext->jobConfig); auto config = std::static_pointer_cast<Config>(renderContext->jobConfig);
@ -215,8 +215,8 @@ void DrawStateSortDeferred::run(const SceneContextPointer& sceneContext, const R
glm::mat4 projMat; glm::mat4 projMat;
Transform viewMat; Transform viewMat;
args->_viewFrustum->evalProjectionMatrix(projMat); args->getViewFrustum().evalProjectionMatrix(projMat);
args->_viewFrustum->evalViewTransform(viewMat); args->getViewFrustum().evalViewTransform(viewMat);
batch.setProjectionTransform(projMat); batch.setProjectionTransform(projMat);
batch.setViewTransform(viewMat); batch.setViewTransform(viewMat);

View file

@ -42,7 +42,7 @@ struct BackToFrontSort {
void render::depthSortItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, bool frontToBack, const ItemBounds& inItems, ItemBounds& outItems) { void render::depthSortItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, bool frontToBack, const ItemBounds& inItems, ItemBounds& outItems) {
assert(renderContext->args); assert(renderContext->args);
assert(renderContext->args->_viewFrustum); assert(renderContext->args->hasViewFrustum());
auto& scene = sceneContext->_scene; auto& scene = sceneContext->_scene;
RenderArgs* args = renderContext->args; RenderArgs* args = renderContext->args;
@ -60,7 +60,7 @@ void render::depthSortItems(const SceneContextPointer& sceneContext, const Rende
for (auto itemDetails : inItems) { for (auto itemDetails : inItems) {
auto item = scene->getItem(itemDetails.id); auto item = scene->getItem(itemDetails.id);
auto bound = itemDetails.bound; // item.getBound(); auto bound = itemDetails.bound; // item.getBound();
float distance = args->_viewFrustum->distanceToCamera(bound.calcCenter()); float distance = args->getViewFrustum().distanceToCamera(bound.calcCenter());
itemBoundSorts.emplace_back(ItemBoundSort(distance, distance, distance, itemDetails.id, bound)); itemBoundSorts.emplace_back(ItemBoundSort(distance, distance, distance, itemDetails.id, bound));
} }