Merge pull request #7827 from AndrewMeadows/threadsafe-viewfrustum

resurrection of threadsafe ViewFrustum
This commit is contained in:
Brad Hefta-Gaub 2016-05-10 09:06:38 -07:00
commit d7eee98acc
51 changed files with 623 additions and 553 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() {
// if shutting down, return immediately
if (_isShuttingDown) {
@ -171,11 +181,13 @@ bool OctreeQueryNode::updateCurrentViewFrustum() {
}
// if there has been a change, then recalculate
if (!newestViewFrustum.isVerySimilar(_currentViewFrustum)) {
_currentViewFrustum = newestViewFrustum;
_currentViewFrustum.calculate();
currentViewFrustumChanged = true;
{ // if there has been a change, then recalculate
QMutexLocker viewLocker(&_viewMutex);
if (!newestViewFrustum.isVerySimilar(_currentViewFrustum)) {
_currentViewFrustum = newestViewFrustum;
_currentViewFrustum.calculate();
currentViewFrustumChanged = true;
}
}
// Also check for LOD changes from the client
@ -219,11 +231,14 @@ void OctreeQueryNode::updateLastKnownViewFrustum() {
return;
}
bool frustumChanges = !_lastKnownViewFrustum.isVerySimilar(_currentViewFrustum);
{
QMutexLocker viewLocker(&_viewMutex);
bool frustumChanges = !_lastKnownViewFrustum.isVerySimilar(_currentViewFrustum);
if (frustumChanges) {
// save our currentViewFrustum into our lastKnownViewFrustum
_lastKnownViewFrustum = _currentViewFrustum;
if (frustumChanges) {
// save our currentViewFrustum into our lastKnownViewFrustum
_lastKnownViewFrustum = _currentViewFrustum;
}
}
// save that we know the view has been sent.
@ -237,15 +252,13 @@ bool OctreeQueryNode::moveShouldDump() const {
return false;
}
QMutexLocker viewLocker(&_viewMutex);
glm::vec3 oldPosition = _lastKnownViewFrustum.getPosition();
glm::vec3 newPosition = _currentViewFrustum.getPosition();
// theoretically we could make this slightly larger but relative to avatar scale.
const float MAXIMUM_MOVE_WITHOUT_DUMP = 0.0f;
if (glm::distance(newPosition, oldPosition) > MAXIMUM_MOVE_WITHOUT_DUMP) {
return true;
}
return false;
return glm::distance(newPosition, oldPosition) > MAXIMUM_MOVE_WITHOUT_DUMP;
}
void OctreeQueryNode::dumpOutOfView() {
@ -257,8 +270,10 @@ void OctreeQueryNode::dumpOutOfView() {
int stillInView = 0;
int outOfView = 0;
OctreeElementBag tempBag;
ViewFrustum viewCopy;
copyCurrentViewFrustum(viewCopy);
while (OctreeElementPointer elementToCheck = elementBag.extract()) {
if (elementToCheck->isInView(_currentViewFrustum)) {
if (elementToCheck->isInView(viewCopy)) {
tempBag.insert(elementToCheck);
stillInView++;
} else {
@ -267,7 +282,7 @@ void OctreeQueryNode::dumpOutOfView() {
}
if (stillInView > 0) {
while (OctreeElementPointer elementToKeepInBag = tempBag.extract()) {
if (elementToKeepInBag->isInView(_currentViewFrustum)) {
if (elementToKeepInBag->isInView(viewCopy)) {
elementBag.insert(elementToKeepInBag);
}
}

View file

@ -44,7 +44,7 @@ public:
bool packetIsDuplicate() const;
bool shouldSuppressDuplicatePacket();
unsigned int getAvailable() const { return _octreePacket->bytesAvailableForWrite(); }
int getMaxSearchLevel() const { return _maxSearchLevel; }
void resetMaxSearchLevel() { _maxSearchLevel = 1; }
@ -56,8 +56,8 @@ public:
OctreeElementBag elementBag;
OctreeElementExtraEncodeData extraEncodeData;
ViewFrustum& getCurrentViewFrustum() { return _currentViewFrustum; }
ViewFrustum& getLastKnownViewFrustum() { return _lastKnownViewFrustum; }
void copyCurrentViewFrustum(ViewFrustum& viewOut) const;
void copyLastKnownViewFrustum(ViewFrustum& viewOut) const;
// These are not classic setters because they are calculating and maintaining state
// which is set asynchronously through the network receive
@ -114,6 +114,8 @@ private:
int _maxSearchLevel { 1 };
int _maxLevelReachedInLastSearch { 1 };
mutable QMutex _viewMutex { QMutex::Recursive };
ViewFrustum _currentViewFrustum;
ViewFrustum _lastKnownViewFrustum;
quint64 _lastTimeBagEmpty { 0 };
@ -139,7 +141,7 @@ private:
QQueue<OCTREE_PACKET_SEQUENCE> _nackedSequenceNumbers;
quint64 _sceneSendStartTime = 0;
std::array<char, udt::MAX_PACKET_SIZE> _lastOctreePayload;
};

View file

@ -338,8 +338,6 @@ int OctreeSendThread::packetDistributor(SharedNodePointer node, OctreeQueryNode*
_packetData.changeSettings(true, targetSize); // FIXME - eventually support only compressed packets
const ViewFrustum* lastViewFrustum = viewFrustumChanged ? &nodeData->getLastKnownViewFrustum() : NULL;
// If the current view frustum has changed OR we have nothing to send, then search against
// the current view frustum for things to send.
if (viewFrustumChanged || nodeData->elementBag.isEmpty()) {
@ -417,7 +415,7 @@ int OctreeSendThread::packetDistributor(SharedNodePointer node, OctreeQueryNode*
quint64 lockWaitEnd = usecTimestampNow();
lockWaitElapsedUsec = (float)(lockWaitEnd - lockWaitStart);
quint64 encodeStart = usecTimestampNow();
OctreeElementPointer subTree = nodeData->elementBag.extract();
if (!subTree) {
return;
@ -426,18 +424,22 @@ int OctreeSendThread::packetDistributor(SharedNodePointer node, OctreeQueryNode*
float octreeSizeScale = nodeData->getOctreeSizeScale();
int boundaryLevelAdjustClient = nodeData->getBoundaryLevelAdjust();
int boundaryLevelAdjust = boundaryLevelAdjustClient +
int boundaryLevelAdjust = boundaryLevelAdjustClient +
(viewFrustumChanged ? LOW_RES_MOVING_ADJUST : NO_BOUNDARY_ADJUST);
EncodeBitstreamParams params(INT_MAX, &nodeData->getCurrentViewFrustum(),
WANT_EXISTS_BITS, DONT_CHOP, viewFrustumChanged, lastViewFrustum,
EncodeBitstreamParams params(INT_MAX, WANT_EXISTS_BITS, DONT_CHOP,
viewFrustumChanged,
boundaryLevelAdjust, octreeSizeScale,
nodeData->getLastTimeBagEmpty(),
isFullScene, &nodeData->stats, _myServer->getJurisdiction(),
&nodeData->extraEncodeData);
nodeData->copyCurrentViewFrustum(params.viewFrustum);
if (viewFrustumChanged) {
nodeData->copyLastKnownViewFrustum(params.lastViewFrustum);
}
// Our trackSend() function is implemented by the server subclass, and will be called back
// during the encodeTreeBitstream() as new entities/data elements are sent
// during the encodeTreeBitstream() as new entities/data elements are sent
params.trackSend = [this, node](const QUuid& dataID, quint64 dataEdited) {
_myServer->trackSend(dataID, dataEdited, node->getUUID());
};

View file

@ -1481,10 +1481,17 @@ void Application::paintGL() {
auto lodManager = DependencyManager::get<LODManager>();
RenderArgs renderArgs(_gpuContext, getEntities(), getViewFrustum(), lodManager->getOctreeSizeScale(),
{
QMutexLocker viewLocker(&_viewMutex);
_viewFrustum.calculate();
}
RenderArgs renderArgs(_gpuContext, getEntities(), lodManager->getOctreeSizeScale(),
lodManager->getBoundaryLevelAdjust(), RenderArgs::DEFAULT_RENDER_MODE,
RenderArgs::MONO, RenderArgs::RENDER_DEBUG_NONE);
{
QMutexLocker viewLocker(&_viewMutex);
renderArgs.setViewFrustum(_viewFrustum);
}
PerformanceWarning::setSuppressShortTimings(Menu::getInstance()->isOptionChecked(MenuOption::SuppressShortTimings));
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
@ -1651,7 +1658,7 @@ void Application::paintGL() {
renderArgs._context->enableStereo(true);
mat4 eyeOffsets[2];
mat4 eyeProjections[2];
auto baseProjection = renderArgs._viewFrustum->getProjection();
auto baseProjection = renderArgs.getViewFrustum().getProjection();
auto hmdInterface = DependencyManager::get<HMDScriptingInterface>();
float IPDScale = hmdInterface->getIPDScale();
mat4 headPose = displayPlugin->getHeadPose();
@ -1781,7 +1788,10 @@ void Application::resizeGL() {
_myCamera.setProjection(glm::perspective(glm::radians(_fieldOfView.get()), aspectRatio,
DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP));
// Possible change in aspect ratio
loadViewFrustum(_myCamera, _viewFrustum);
{
QMutexLocker viewLocker(&_viewMutex);
loadViewFrustum(_myCamera, _viewFrustum);
}
auto offscreenUi = DependencyManager::get<OffscreenUi>();
auto uiSize = displayPlugin->getRecommendedUiSize();
@ -2108,6 +2118,7 @@ void Application::keyPressEvent(QKeyEvent* event) {
case Qt::Key_J:
if (isShifted) {
QMutexLocker viewLocker(&_viewMutex);
_viewFrustum.setFocalLength(_viewFrustum.getFocalLength() - 0.1f);
} else {
_myCamera.setEyeOffsetPosition(_myCamera.getEyeOffsetPosition() + glm::vec3(-0.001, 0, 0));
@ -2117,6 +2128,7 @@ void Application::keyPressEvent(QKeyEvent* event) {
case Qt::Key_M:
if (isShifted) {
QMutexLocker viewLocker(&_viewMutex);
_viewFrustum.setFocalLength(_viewFrustum.getFocalLength() + 0.1f);
} else {
_myCamera.setEyeOffsetPosition(_myCamera.getEyeOffsetPosition() + glm::vec3(0.001, 0, 0));
@ -2965,7 +2977,10 @@ void Application::init() {
DependencyManager::get<NodeList>()->sendDomainServerCheckIn();
getEntities()->init();
getEntities()->setViewFrustum(getViewFrustum());
{
QMutexLocker viewLocker(&_viewMutex);
getEntities()->setViewFrustum(_viewFrustum);
}
ObjectMotionState::setShapeManager(&_shapeManager);
_physicsEngine->init();
@ -2985,7 +3000,10 @@ void Application::init() {
getEntities()->connectSignalsToSlots(entityScriptingInterface.data());
_entityClipboardRenderer.init();
_entityClipboardRenderer.setViewFrustum(getViewFrustum());
{
QMutexLocker viewLocker(&_viewMutex);
_entityClipboardRenderer.setViewFrustum(_viewFrustum);
}
_entityClipboardRenderer.setTree(_entityClipboard);
// Make sure any new sounds are loaded as soon as know about them.
@ -3199,9 +3217,12 @@ void Application::resetPhysicsReadyInformation() {
void Application::reloadResourceCaches() {
resetPhysicsReadyInformation();
{
QMutexLocker viewLocker(&_viewMutex);
_viewFrustum.setPosition(glm::vec3(0.0f, 0.0f, TREE_SCALE));
_viewFrustum.setOrientation(glm::quat());
}
// Clear entities out of view frustum
_viewFrustum.setPosition(glm::vec3(0.0f, 0.0f, TREE_SCALE));
_viewFrustum.setOrientation(glm::quat());
queryOctree(NodeType::EntityServer, PacketType::EntityQuery, _entityServerJurisdictions);
DependencyManager::get<AssetClient>()->clearCache();
@ -3490,7 +3511,7 @@ void Application::update(float deltaTime) {
// actually need to calculate the view frustum planes to send these details
// to the server.
{
PerformanceTimer perfTimer("loadViewFrustum");
QMutexLocker viewLocker(&_viewMutex);
loadViewFrustum(_myCamera, _viewFrustum);
}
@ -3499,6 +3520,7 @@ void Application::update(float deltaTime) {
// Update my voxel servers with my current voxel query...
{
PROFILE_RANGE_EX("QueryOctree", 0xffff0000, (uint64_t)getActiveDisplayPlugin()->presentCount());
QMutexLocker viewLocker(&_viewMutex);
PerformanceTimer perfTimer("queryOctree");
quint64 sinceLastQuery = now - _lastQueriedTime;
const quint64 TOO_LONG_SINCE_LAST_QUERY = 3 * USECS_PER_SECOND;
@ -3610,14 +3632,16 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node
//qCDebug(interfaceapp) << ">>> inside... queryOctree()... _viewFrustum.getFieldOfView()=" << _viewFrustum.getFieldOfView();
bool wantExtraDebugging = getLogger()->extraDebugging();
_octreeQuery.setCameraPosition(_viewFrustum.getPosition());
_octreeQuery.setCameraOrientation(_viewFrustum.getOrientation());
_octreeQuery.setCameraFov(_viewFrustum.getFieldOfView());
_octreeQuery.setCameraAspectRatio(_viewFrustum.getAspectRatio());
_octreeQuery.setCameraNearClip(_viewFrustum.getNearClip());
_octreeQuery.setCameraFarClip(_viewFrustum.getFarClip());
ViewFrustum viewFrustum;
copyViewFrustum(viewFrustum);
_octreeQuery.setCameraPosition(viewFrustum.getPosition());
_octreeQuery.setCameraOrientation(viewFrustum.getOrientation());
_octreeQuery.setCameraFov(viewFrustum.getFieldOfView());
_octreeQuery.setCameraAspectRatio(viewFrustum.getAspectRatio());
_octreeQuery.setCameraNearClip(viewFrustum.getNearClip());
_octreeQuery.setCameraFarClip(viewFrustum.getFarClip());
_octreeQuery.setCameraEyeOffsetPosition(glm::vec3());
_octreeQuery.setCameraCenterRadius(_viewFrustum.getCenterRadius());
_octreeQuery.setCameraCenterRadius(viewFrustum.getCenterRadius());
auto lodManager = DependencyManager::get<LODManager>();
_octreeQuery.setOctreeSizeScale(lodManager->getOctreeSizeScale());
_octreeQuery.setBoundaryLevelAdjust(lodManager->getBoundaryLevelAdjust());
@ -3653,7 +3677,7 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node
rootDetails.y * TREE_SCALE,
rootDetails.z * TREE_SCALE) - glm::vec3(HALF_TREE_SCALE),
rootDetails.s * TREE_SCALE);
if (_viewFrustum.cubeIntersectsKeyhole(serverBounds)) {
if (viewFrustum.cubeIntersectsKeyhole(serverBounds)) {
inViewServers++;
}
}
@ -3719,11 +3743,9 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node
rootDetails.s * TREE_SCALE);
inView = _viewFrustum.cubeIntersectsKeyhole(serverBounds);
} else {
if (wantExtraDebugging) {
qCDebug(interfaceapp) << "Jurisdiction without RootCode for node " << *node << ". That's unusual!";
}
inView = viewFrustum.cubeIntersectsKeyhole(serverBounds);
} else if (wantExtraDebugging) {
qCDebug(interfaceapp) << "Jurisdiction without RootCode for node " << *node << ". That's unusual!";
}
}
@ -3814,6 +3836,7 @@ QRect Application::getDesirableApplicationGeometry() const {
// or the "myCamera".
//
void Application::loadViewFrustum(Camera& camera, ViewFrustum& viewFrustum) {
PerformanceTimer perfTimer("loadViewFrustum");
PROFILE_RANGE(__FUNCTION__);
// We will use these below, from either the camera or head vectors calculated above
viewFrustum.setProjection(camera.getProjection());
@ -3842,7 +3865,8 @@ PickRay Application::computePickRay(float x, float y) const {
getApplicationCompositor().computeHmdPickRay(pickPoint, result.origin, result.direction);
} else {
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;
}
@ -3855,44 +3879,19 @@ glm::vec3 Application::getAvatarPosition() const {
return getMyAvatar()->getPosition();
}
ViewFrustum* Application::getViewFrustum() {
#ifdef DEBUG
if (QThread::currentThread() == activeRenderingThread) {
// 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;
void Application::copyViewFrustum(ViewFrustum& viewOut) const {
QMutexLocker viewLocker(&_viewMutex);
viewOut = _viewFrustum;
}
const ViewFrustum* Application::getViewFrustum() const {
#ifdef DEBUG
if (QThread::currentThread() == activeRenderingThread) {
// 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;
void Application::copyDisplayViewFrustum(ViewFrustum& viewOut) const {
QMutexLocker viewLocker(&_viewMutex);
viewOut = _displayViewFrustum;
}
ViewFrustum* Application::getDisplayViewFrustum() {
#ifdef DEBUG
if (QThread::currentThread() != activeRenderingThread) {
// 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()?";
}
#endif
return &_displayViewFrustum;
}
const ViewFrustum* Application::getDisplayViewFrustum() const {
#ifdef DEBUG
if (QThread::currentThread() != activeRenderingThread) {
// 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()?";
}
#endif
return &_displayViewFrustum;
void Application::copyShadowViewFrustum(ViewFrustum& viewOut) const {
QMutexLocker viewLocker(&_viewMutex);
viewOut = _shadowViewFrustum;
}
// WorldBox Render Data & rendering functions
@ -3957,7 +3956,7 @@ namespace render {
auto skybox = skyStage->getSkybox();
if (skybox) {
PerformanceTimer perfTimer("skybox");
skybox->render(batch, *(args->_viewFrustum));
skybox->render(batch, args->getViewFrustum());
break;
}
}
@ -4001,7 +4000,10 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "Application::displaySide()");
// load the view frustum
loadViewFrustum(theCamera, _displayViewFrustum);
{
QMutexLocker viewLocker(&_viewMutex);
loadViewFrustum(theCamera, _displayViewFrustum);
}
// TODO fix shadows and make them use the GPU library
@ -4069,7 +4071,10 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se
{
PerformanceTimer perfTimer("EngineRun");
renderArgs->_viewFrustum = getDisplayViewFrustum();
{
QMutexLocker viewLocker(&_viewMutex);
renderArgs->setViewFrustum(_displayViewFrustum);
}
_renderEngine->getRenderContext()->args = renderArgs;
// Before the deferred pass, let's try to use the render engine
@ -5199,10 +5204,10 @@ void Application::updateInputModes() {
}
mat4 Application::getEyeProjection(int eye) const {
QMutexLocker viewLocker(&_viewMutex);
if (isHMDMode()) {
return getActiveDisplayPlugin()->getEyeProjection((Eye)eye, _viewFrustum.getProjection());
}
return _viewFrustum.getProjection();
}

View file

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

View file

@ -10,6 +10,7 @@
//
#include <SettingHandle.h>
#include <OctreeUtils.h>
#include <Util.h>
#include "Application.h"
@ -216,7 +217,7 @@ QString LODManager::getLODFeedbackText() {
bool LODManager::shouldRender(const RenderArgs* args, const AABox& bounds) {
// FIXME - eventually we want to use the render accuracy as an indicator for the level of detail
// to use in rendering.
float renderAccuracy = args->_viewFrustum->calculateRenderAccuracy(bounds, args->_sizeScale, args->_boundaryLevelAdjust);
float renderAccuracy = calculateRenderAccuracy(args->getViewFrustum().getPosition(), bounds, args->_sizeScale, args->_boundaryLevelAdjust);
return (renderAccuracy > 0.0f);
};
@ -228,7 +229,6 @@ void LODManager::setBoundaryLevelAdjust(int boundaryLevelAdjust) {
_boundaryLevelAdjust = boundaryLevelAdjust;
}
void LODManager::loadSettings() {
setDesktopLODDecreaseFPS(desktopLODDecreaseFPS.get());
setHMDLODDecreaseFPS(hmdLODDecreaseFPS.get());
@ -239,4 +239,3 @@ void LODManager::saveSettings() {
hmdLODDecreaseFPS.set(getHMDLODDecreaseFPS());
}

View file

@ -194,8 +194,8 @@ void Stars::render(RenderArgs* renderArgs, float alpha) {
gpu::Batch& batch = *renderArgs->_batch;
batch.setViewTransform(Transform());
batch.setProjectionTransform(renderArgs->_viewFrustum->getProjection());
batch.setModelTransform(Transform().setRotation(glm::inverse(renderArgs->_viewFrustum->getOrientation()) *
batch.setProjectionTransform(renderArgs->getViewFrustum().getProjection());
batch.setModelTransform(Transform().setRotation(glm::inverse(renderArgs->getViewFrustum().getOrientation()) *
quat(vec3(TILT, 0, 0))));
batch.setResourceTexture(0, textureCache->getWhiteTexture());

View file

@ -25,6 +25,7 @@
#include <LODManager.h>
#include <NodeList.h>
#include <NumericalConstants.h>
#include <OctreeUtils.h>
#include <udt/PacketHeaders.h>
#include <PerfStat.h>
#include <SharedUtil.h>
@ -171,7 +172,10 @@ void Avatar::simulate(float deltaTime) {
// update the shouldAnimate flag to match whether or not we will render the avatar.
const float MINIMUM_VISIBILITY_FOR_ON = 0.4f;
const float MAXIMUM_VISIBILITY_FOR_OFF = 0.6f;
float visibility = qApp->getViewFrustum()->calculateRenderAccuracy(getBounds(), DependencyManager::get<LODManager>()->getOctreeSizeScale());
ViewFrustum viewFrustum;
qApp->copyViewFrustum(viewFrustum);
float visibility = calculateRenderAccuracy(viewFrustum.getPosition(),
getBounds(), DependencyManager::get<LODManager>()->getOctreeSizeScale());
if (!_shouldAnimate) {
if (visibility > MINIMUM_VISIBILITY_FOR_ON) {
_shouldAnimate = true;
@ -184,8 +188,9 @@ void Avatar::simulate(float deltaTime) {
// simple frustum check
float boundingRadius = getBoundingRadius();
bool avatarPositionInView = qApp->getDisplayViewFrustum()->sphereIntersectsFrustum(getPosition(), boundingRadius);
bool avatarMeshInView = qApp->getDisplayViewFrustum()->boxIntersectsFrustum(_skeletonModel->getRenderableMeshBound());
qApp->copyDisplayViewFrustum(viewFrustum);
bool avatarPositionInView = viewFrustum.sphereIntersectsFrustum(getPosition(), boundingRadius);
bool avatarMeshInView = viewFrustum.boxIntersectsFrustum(_skeletonModel->getRenderableMeshBound());
if (_shouldAnimate && !_shouldSkipRender && (avatarPositionInView || avatarMeshInView)) {
{
@ -381,17 +386,16 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) {
}
}
// simple frustum check
float boundingRadius = getBoundingRadius();
ViewFrustum* frustum = nullptr;
if (renderArgs->_renderMode == RenderArgs::SHADOW_RENDER_MODE) {
frustum = qApp->getShadowViewFrustum();
} else {
frustum = qApp->getDisplayViewFrustum();
}
if (!frustum->sphereIntersectsFrustum(getPosition(), boundingRadius)) {
return;
{ // simple frustum check
ViewFrustum frustum;
if (renderArgs->_renderMode == RenderArgs::SHADOW_RENDER_MODE) {
qApp->copyShadowViewFrustum(frustum);
} else {
qApp->copyDisplayViewFrustum(frustum);
}
if (!frustum.sphereIntersectsFrustum(getPosition(), getBoundingRadius())) {
return;
}
}
glm::vec3 toTarget = cameraPosition - getPosition();
@ -413,7 +417,7 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) {
: GLOW_FROM_AVERAGE_LOUDNESS;
// render body
renderBody(renderArgs, frustum, glowLevel);
renderBody(renderArgs, glowLevel);
if (renderArgs->_renderMode != RenderArgs::SHADOW_RENDER_MODE) {
// add local lights
@ -502,9 +506,8 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) {
auto cameraMode = qApp->getCamera()->getMode();
if (!isMyAvatar() || cameraMode != CAMERA_MODE_FIRST_PERSON) {
auto& frustum = *renderArgs->_viewFrustum;
auto& frustum = renderArgs->getViewFrustum();
auto textPosition = getDisplayNamePosition();
if (frustum.pointIntersectsFrustum(textPosition)) {
renderDisplayName(batch, frustum, textPosition);
}
@ -553,7 +556,7 @@ void Avatar::fixupModelsInScene() {
scene->enqueuePendingChanges(pendingChanges);
}
void Avatar::renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, float glowLevel) {
void Avatar::renderBody(RenderArgs* renderArgs, float glowLevel) {
fixupModelsInScene();
getHead()->renderLookAts(renderArgs);
}

View file

@ -232,7 +232,7 @@ protected:
Transform calculateDisplayNameTransform(const ViewFrustum& view, const glm::vec3& textPosition) const;
void renderDisplayName(gpu::Batch& batch, const ViewFrustum& view, const glm::vec3& textPosition) const;
virtual void renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, float glowLevel = 0.0f);
virtual void renderBody(RenderArgs* renderArgs, float glowLevel = 0.0f);
virtual bool shouldRenderHead(const RenderArgs* renderArgs) const;
virtual void fixupModelsInScene();

View file

@ -316,9 +316,6 @@ void Head::relaxLean(float deltaTime) {
_deltaLeanForward *= relaxationFactor;
}
void Head::render(RenderArgs* renderArgs, float alpha, ViewFrustum* renderFrustum) {
}
void Head::renderLookAts(RenderArgs* renderArgs) {
renderLookAts(renderArgs, _leftEyePosition, _rightEyePosition);
}

View file

@ -28,11 +28,10 @@ class Avatar;
class Head : public HeadData {
public:
explicit Head(Avatar* owningAvatar);
void init();
void reset();
void simulate(float deltaTime, bool isMine, bool billboard = false);
void render(RenderArgs* renderArgs, float alpha, ViewFrustum* renderFrustum);
void setScale(float scale);
void setPosition(glm::vec3 position) { _position = position; }
void setAverageLoudness(float averageLoudness) { _averageLoudness = averageLoudness; }
@ -44,7 +43,7 @@ public:
/// \return orientationBase+Delta
glm::quat getFinalOrientationInLocalFrame() const;
/// \return orientationBody * (orientationBase+Delta)
glm::quat getFinalOrientationInWorldFrame() const;

View file

@ -545,7 +545,9 @@ void MyAvatar::updateFromTrackers(float deltaTime) {
head->setDeltaYaw(estimatedRotation.y);
head->setDeltaRoll(estimatedRotation.z);
} 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->setDeltaYaw(estimatedRotation.y * magnifyFieldOfView);
head->setDeltaRoll(estimatedRotation.z);
@ -928,15 +930,17 @@ void MyAvatar::updateLookAtTargetAvatar() {
// (We will be adding that offset to the camera position, after making some other adjustments.)
glm::vec3 gazeOffset = lookAtPosition - getHead()->getEyePosition();
ViewFrustum viewFrustum;
qApp->copyViewFrustum(viewFrustum);
// scale gazeOffset by IPD, if wearing an HMD.
if (qApp->isHMDMode()) {
glm::mat4 leftEye = qApp->getEyeOffset(Eye::Left);
glm::mat4 rightEye = qApp->getEyeOffset(Eye::Right);
glm::vec3 leftEyeHeadLocal = glm::vec3(leftEye[3]);
glm::vec3 rightEyeHeadLocal = glm::vec3(rightEye[3]);
auto humanSystem = qApp->getViewFrustum();
glm::vec3 humanLeftEye = humanSystem->getPosition() + (humanSystem->getOrientation() * leftEyeHeadLocal);
glm::vec3 humanRightEye = humanSystem->getPosition() + (humanSystem->getOrientation() * rightEyeHeadLocal);
glm::vec3 humanLeftEye = viewFrustum.getPosition() + (viewFrustum.getOrientation() * leftEyeHeadLocal);
glm::vec3 humanRightEye = viewFrustum.getPosition() + (viewFrustum.getOrientation() * rightEyeHeadLocal);
auto hmdInterface = DependencyManager::get<HMDScriptingInterface>();
float ipdScale = hmdInterface->getIPDScale();
@ -950,7 +954,7 @@ void MyAvatar::updateLookAtTargetAvatar() {
}
// 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);
@ -1266,7 +1270,7 @@ void MyAvatar::attach(const QString& modelURL, const QString& jointName,
Avatar::attach(modelURL, jointName, translation, rotation, scale, isSoft, allowDuplicates, useSaved);
}
void MyAvatar::renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, float glowLevel) {
void MyAvatar::renderBody(RenderArgs* renderArgs, float glowLevel) {
if (!_skeletonModel->isRenderable()) {
return; // wait until all models are loaded
@ -1274,11 +1278,6 @@ void MyAvatar::renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, fl
fixupModelsInScene();
// Render head so long as the camera isn't inside it
if (shouldRenderHead(renderArgs)) {
getHead()->render(renderArgs, 1.0f, renderFrustum);
}
// This is drawing the lookat vectors from our avatar to wherever we're looking.
if (qApp->isHMDMode()) {
glm::vec3 cameraPosition = qApp->getCamera()->getPosition();
@ -1359,7 +1358,6 @@ void MyAvatar::destroyAnimGraph() {
void MyAvatar::preRender(RenderArgs* renderArgs) {
render::ScenePointer scene = qApp->getMain3DScene();
const bool shouldDrawHead = shouldRenderHead(renderArgs);
if (_skeletonModel->initWhenReady(scene)) {
initHeadBones();
@ -1411,6 +1409,7 @@ void MyAvatar::preRender(RenderArgs* renderArgs) {
DebugDraw::getInstance().updateMyAvatarPos(getPosition());
DebugDraw::getInstance().updateMyAvatarRot(getOrientation());
const bool shouldDrawHead = shouldRenderHead(renderArgs);
if (shouldDrawHead != _prevShouldDrawHead) {
_skeletonModel->setCauterizeBones(!shouldDrawHead);
}

View file

@ -310,7 +310,7 @@ private:
void simulate(float deltaTime);
void updateFromTrackers(float deltaTime);
virtual void render(RenderArgs* renderArgs, const glm::vec3& cameraPositio) override;
virtual void renderBody(RenderArgs* renderArgs, ViewFrustum* renderFrustum, float glowLevel = 0.0f) override;
virtual void renderBody(RenderArgs* renderArgs, float glowLevel = 0.0f) override;
virtual bool shouldRenderHead(const RenderArgs* renderArgs) const override;
void setShouldRenderLocally(bool shouldRender) { _shouldRender = shouldRender; setEnableMeshVisible(shouldRender); }
bool getShouldRenderLocally() const { return _shouldRender; }

View file

@ -65,7 +65,7 @@ void Grid3DOverlay::render(RenderArgs* args) {
// Get the camera position rounded to the nearest major grid line
// This grid is for UI and should lie on worldlines
auto cameraPosition =
(float)_majorGridEvery * glm::round(args->_viewFrustum->getPosition() / (float)_majorGridEvery);
(float)_majorGridEvery * glm::round(args->getViewFrustum().getPosition() / (float)_majorGridEvery);
position += glm::vec3(cameraPosition.x, 0.0f, cameraPosition.z);
}

View file

@ -37,10 +37,10 @@ void LocalModelsOverlay::render(RenderArgs* args) {
auto batch = args ->_batch;
Transform transform = Transform();
transform.setTranslation(args->_viewFrustum->getPosition() + getPosition());
transform.setTranslation(args->getViewFrustum().getPosition() + getPosition());
batch->setViewTransform(transform);
_entityTreeRenderer->render(args);
transform.setTranslation(args->_viewFrustum->getPosition());
transform.setTranslation(args->getViewFrustum().getPosition());
batch->setViewTransform(transform);
}
}

View file

@ -51,7 +51,7 @@ void RenderableTextEntityItem::render(RenderArgs* args) {
}
if (getFaceCamera()) {
//rotate about vertical to face the camera
glm::vec3 dPosition = args->_viewFrustum->getPosition() - getPosition();
glm::vec3 dPosition = args->getViewFrustum().getPosition() - getPosition();
// If x and z are 0, atan(x, z) is undefined, so default to 0 degrees
float yawRotation = dPosition.x == 0.0f && dPosition.z == 0.0f ? 0.0f : glm::atan(dPosition.x, dPosition.z);
glm::quat orientation = glm::quat(glm::vec3(0.0f, yawRotation, 0.0f));

View file

@ -13,6 +13,7 @@
#include <FBXReader.h>
#include <GeometryUtil.h>
#include <OctreeUtils.h>
#include "EntitiesLogging.h"
#include "EntityItemProperties.h"
@ -295,7 +296,7 @@ OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData
entityTreeElementExtraEncodeData->entities.contains(entity->getEntityItemID());
}
if (includeThisEntity && params.viewFrustum) {
if (includeThisEntity || params.recurseEverything) {
// we want to use the maximum possible box for this, so that we don't have to worry about the nuance of
// simulation changing what's visible. consider the case where the entity contains an angular velocity
@ -303,7 +304,7 @@ OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData
// frustum culling on rendering.
bool success;
AACube entityCube = entity->getQueryAACube(success);
if (!success || !params.viewFrustum->cubeIntersectsKeyhole(entityCube)) {
if (!success || !params.viewFrustum.cubeIntersectsKeyhole(entityCube)) {
includeThisEntity = false; // out of view, don't include it
} else {
// Check the size of the entity, it's possible that a "too small to see" entity is included in a
@ -320,9 +321,10 @@ OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData
// AABox. If this happens, fall back to the queryAACube.
entityBounds = AABox(entityCube);
}
auto renderAccuracy = params.viewFrustum->calculateRenderAccuracy(entityBounds,
params.octreeElementSizeScale,
params.boundaryLevelAdjust);
auto renderAccuracy = calculateRenderAccuracy(params.viewFrustum.getPosition(),
entityBounds,
params.octreeElementSizeScale,
params.boundaryLevelAdjust);
if (renderAccuracy <= 0.0f) {
includeThisEntity = false; // too small, don't include it

View file

@ -33,6 +33,7 @@
#include <QString>
#include <GeometryUtil.h>
#include <Gzip.h>
#include <LogHandler.h>
#include <NetworkAccessManager.h>
#include <OctalCode.h>
@ -40,12 +41,12 @@
#include <ResourceManager.h>
#include <SharedUtil.h>
#include <PathUtils.h>
#include <Gzip.h>
#include <ViewFrustum.h>
#include "OctreeConstants.h"
#include "OctreeElementBag.h"
#include "Octree.h"
#include "ViewFrustum.h"
#include "OctreeUtils.h"
#include "OctreeLogging.h"
@ -898,7 +899,7 @@ int Octree::encodeTreeBitstream(OctreeElementPointer element,
}
// If we're at a element that is out of view, then we can return, because no nodes below us will be in view!
if (params.viewFrustum && !element->isInView(*params.viewFrustum)) {
if (!params.recurseEverything && !element->isInView(params.viewFrustum)) {
params.stopReason = EncodeBitstreamParams::OUT_OF_VIEW;
return bytesWritten;
}
@ -1014,15 +1015,12 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element,
}
ViewFrustum::intersection nodeLocationThisView = ViewFrustum::INSIDE; // assume we're inside
// caller can pass NULL as viewFrustum if they want everything
if (params.viewFrustum) {
float distance = element->distanceToCamera(*params.viewFrustum);
if (!params.recurseEverything) {
float boundaryDistance = boundaryDistanceForRenderLevel(element->getLevel() + params.boundaryLevelAdjust,
params.octreeElementSizeScale);
// If we're too far away for our render level, then just return
if (distance >= boundaryDistance) {
if (element->distanceToCamera(params.viewFrustum) >= boundaryDistance) {
if (params.stats) {
params.stats->skippedDistance(element);
}
@ -1034,7 +1032,7 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element,
// if we are INSIDE, INTERSECT, or OUTSIDE
if (parentLocationThisView != ViewFrustum::INSIDE) {
assert(parentLocationThisView != ViewFrustum::OUTSIDE); // we shouldn't be here if our parent was OUTSIDE!
nodeLocationThisView = element->computeViewIntersection(*params.viewFrustum);
nodeLocationThisView = element->computeViewIntersection(params.viewFrustum);
}
// If we're at a element that is out of view, then we can return, because no nodes below us will be in view!
@ -1052,8 +1050,8 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element,
// because we don't send nodes from the previously know in view frustum.
bool wasInView = false;
if (params.deltaViewFrustum && params.lastViewFrustum) {
ViewFrustum::intersection location = element->computeViewIntersection(*params.lastViewFrustum);
if (params.deltaView) {
ViewFrustum::intersection location = element->computeViewIntersection(params.lastViewFrustum);
// If we're a leaf, then either intersect or inside is considered "formerly in view"
if (element->isLeaf()) {
@ -1067,10 +1065,9 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element,
// to it, and so therefore it may now be visible from an LOD perspective, in which case we don't consider it
// as "was in view"...
if (wasInView) {
float distance = element->distanceToCamera(*params.lastViewFrustum);
float boundaryDistance = boundaryDistanceForRenderLevel(element->getLevel() + params.boundaryLevelAdjust,
params.octreeElementSizeScale);
if (distance >= boundaryDistance) {
if (element->distanceToCamera(params.lastViewFrustum) >= boundaryDistance) {
// This would have been invisible... but now should be visible (we wouldn't be here otherwise)...
wasInView = false;
}
@ -1078,9 +1075,9 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element,
}
// If we were previously in the view, then we normally will return out of here and stop recursing. But
// if we're in deltaViewFrustum mode, and this element has changed since it was last sent, then we do
// if we're in deltaView mode, and this element has changed since it was last sent, then we do
// need to send it.
if (wasInView && !(params.deltaViewFrustum && element->hasChangedSince(params.lastViewFrustumSent - CHANGE_FUDGE))) {
if (wasInView && !(params.deltaView && element->hasChangedSince(params.lastViewFrustumSent - CHANGE_FUDGE))) {
if (params.stats) {
params.stats->skippedWasInView(element);
}
@ -1090,7 +1087,7 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element,
// If we're not in delta sending mode, and we weren't asked to do a force send, and the voxel hasn't changed,
// then we can also bail early and save bits
if (!params.forceSendScene && !params.deltaViewFrustum &&
if (!params.forceSendScene && !params.deltaView &&
!element->hasChangedSince(params.lastViewFrustumSent - CHANGE_FUDGE)) {
if (params.stats) {
params.stats->skippedNoChange(element);
@ -1179,10 +1176,10 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element,
int originalIndex = indexOfChildren[i];
bool childIsInView = (childElement &&
( !params.viewFrustum || // no view frustum was given, everything is assumed in view
(nodeLocationThisView == ViewFrustum::INSIDE) || // parent was fully in view, we can assume ALL children are
(params.recurseEverything ||
(nodeLocationThisView == ViewFrustum::INSIDE) || // parent was fully in view, we can assume ALL children are
(nodeLocationThisView == ViewFrustum::INTERSECT &&
childElement->isInView(*params.viewFrustum)) // the parent intersects and the child is in view
childElement->isInView(params.viewFrustum)) // the parent intersects and the child is in view
));
if (!childIsInView) {
@ -1192,12 +1189,11 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element,
}
} else {
// Before we consider this further, let's see if it's in our LOD scope...
float distance = distancesToChildren[i];
float boundaryDistance = !params.viewFrustum ? 1 :
boundaryDistanceForRenderLevel(childElement->getLevel() + params.boundaryLevelAdjust,
float boundaryDistance = params.recurseEverything ? 1 :
boundaryDistanceForRenderLevel(childElement->getLevel() + params.boundaryLevelAdjust,
params.octreeElementSizeScale);
if (!(distance < boundaryDistance)) {
if (!(distancesToChildren[i] < boundaryDistance)) {
// don't need to check childElement here, because we can't get here with no childElement
if (params.stats) {
params.stats->skippedDistance(childElement);
@ -1215,10 +1211,9 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element,
bool childIsOccluded = false; // assume it's not occluded
bool shouldRender = !params.viewFrustum
? true
: childElement->calculateShouldRender(params.viewFrustum,
params.octreeElementSizeScale, params.boundaryLevelAdjust);
bool shouldRender = params.recurseEverything ||
childElement->calculateShouldRender(params.viewFrustum,
params.octreeElementSizeScale, params.boundaryLevelAdjust);
// track some stats
if (params.stats) {
@ -1236,8 +1231,8 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element,
if (shouldRender && !childIsOccluded) {
bool childWasInView = false;
if (childElement && params.deltaViewFrustum && params.lastViewFrustum) {
ViewFrustum::intersection location = childElement->computeViewIntersection(*params.lastViewFrustum);
if (childElement && params.deltaView) {
ViewFrustum::intersection location = childElement->computeViewIntersection(params.lastViewFrustum);
// If we're a leaf, then either intersect or inside is considered "formerly in view"
if (childElement->isLeaf()) {
@ -1251,7 +1246,7 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element,
// Or if we were previously in the view, but this element has changed since it was last sent, then we do
// need to send it.
if (!childWasInView ||
(params.deltaViewFrustum &&
(params.deltaView &&
childElement->hasChangedSince(params.lastViewFrustumSent - CHANGE_FUDGE))){
childrenDataBits += (1 << (7 - originalIndex));
@ -1456,7 +1451,7 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element,
// called databits), then we wouldn't send the children. So those types of Octree's should tell us to keep
// recursing, by returning TRUE in recurseChildrenWithData().
if (recurseChildrenWithData() || !params.viewFrustum || !oneAtBit(childrenDataBits, originalIndex)) {
if (params.recurseEverything || recurseChildrenWithData() || !oneAtBit(childrenDataBits, originalIndex)) {
// Allow the datatype a chance to determine if it really wants to recurse this tree. Usually this
// will be true. But if the tree has already been encoded, we will skip this.
@ -1978,7 +1973,8 @@ void Octree::writeToSVOFile(const char* fileName, OctreeElementPointer element)
bool lastPacketWritten = false;
while (OctreeElementPointer subTree = elementBag.extract()) {
EncodeBitstreamParams params(INT_MAX, IGNORE_VIEW_FRUSTUM, NO_EXISTS_BITS);
EncodeBitstreamParams params(INT_MAX, NO_EXISTS_BITS);
params.recurseEverything = true;
withReadLock([&] {
params.extraEncodeData = &extraEncodeData;
bytesWritten = encodeTreeBitstream(subTree, &packetData, elementBag, params);

View file

@ -20,9 +20,9 @@
#include <shared/ReadWriteLockable.h>
#include <SimpleMovingAverage.h>
#include <ViewFrustum.h>
#include "JurisdictionMap.h"
#include "ViewFrustum.h"
#include "OctreeElement.h"
#include "OctreeElementBag.h"
#include "OctreePacketData.h"
@ -61,22 +61,22 @@ const int LOW_RES_MOVING_ADJUST = 1;
const quint64 IGNORE_LAST_SENT = 0;
#define IGNORE_SCENE_STATS NULL
#define IGNORE_VIEW_FRUSTUM NULL
#define IGNORE_COVERAGE_MAP NULL
#define IGNORE_JURISDICTION_MAP NULL
class EncodeBitstreamParams {
public:
ViewFrustum viewFrustum;
ViewFrustum lastViewFrustum;
quint64 lastViewFrustumSent;
int maxEncodeLevel;
int maxLevelReached;
const ViewFrustum* viewFrustum;
bool includeExistsBits;
int chopLevels;
bool deltaViewFrustum;
const ViewFrustum* lastViewFrustum;
bool deltaView;
bool recurseEverything { false };
int boundaryLevelAdjust;
float octreeElementSizeScale;
quint64 lastViewFrustumSent;
bool forceSendScene;
OctreeSceneStats* stats;
JurisdictionMap* jurisdictionMap;
@ -99,11 +99,9 @@ public:
EncodeBitstreamParams(
int maxEncodeLevel = INT_MAX,
const ViewFrustum* viewFrustum = IGNORE_VIEW_FRUSTUM,
bool includeExistsBits = WANT_EXISTS_BITS,
int chopLevels = 0,
bool deltaViewFrustum = false,
const ViewFrustum* lastViewFrustum = IGNORE_VIEW_FRUSTUM,
bool useDeltaView = false,
int boundaryLevelAdjust = NO_BOUNDARY_ADJUST,
float octreeElementSizeScale = DEFAULT_OCTREE_SIZE_SCALE,
quint64 lastViewFrustumSent = IGNORE_LAST_SENT,
@ -111,22 +109,22 @@ public:
OctreeSceneStats* stats = IGNORE_SCENE_STATS,
JurisdictionMap* jurisdictionMap = IGNORE_JURISDICTION_MAP,
OctreeElementExtraEncodeData* extraEncodeData = NULL) :
lastViewFrustumSent(lastViewFrustumSent),
maxEncodeLevel(maxEncodeLevel),
maxLevelReached(0),
viewFrustum(viewFrustum),
includeExistsBits(includeExistsBits),
chopLevels(chopLevels),
deltaViewFrustum(deltaViewFrustum),
lastViewFrustum(lastViewFrustum),
deltaView(useDeltaView),
boundaryLevelAdjust(boundaryLevelAdjust),
octreeElementSizeScale(octreeElementSizeScale),
lastViewFrustumSent(lastViewFrustumSent),
forceSendScene(forceSendScene),
stats(stats),
jurisdictionMap(jurisdictionMap),
extraEncodeData(extraEncodeData),
stopReason(UNKNOWN)
{}
{
lastViewFrustum.invalidate();
}
void displayStopReason() {
printf("StopReason: ");
@ -341,7 +339,7 @@ public:
bool getIsClient() const { return !_isServer; } /// Is this a client based tree. Allows guards for certain operations
void setIsClient(bool isClient) { _isServer = !isClient; }
virtual void dumpTree() { }
virtual void pruneTree() { }
@ -352,7 +350,6 @@ public:
virtual quint64 getAverageCreateTime() const { return 0; }
virtual quint64 getAverageLoggingTime() const { return 0; }
signals:
void importSize(float x, float y, float z);
void importProgress(int progress);

View file

@ -22,10 +22,11 @@
#include "AACube.h"
#include "OctalCode.h"
#include "Octree.h"
#include "OctreeConstants.h"
#include "OctreeElement.h"
#include "Octree.h"
#include "OctreeLogging.h"
#include "OctreeUtils.h"
#include "SharedUtil.h"
AtomicUIntStat OctreeElement::_octreeMemoryUsage { 0 };
@ -471,11 +472,11 @@ ViewFrustum::intersection OctreeElement::computeViewIntersection(const ViewFrust
// Since, if we know the camera position and orientation, we can know which of the corners is the "furthest"
// corner. We can use we can use this corner as our "voxel position" to do our distance calculations off of.
// By doing this, we don't need to test each child voxel's position vs the LOD boundary
bool OctreeElement::calculateShouldRender(const ViewFrustum* viewFrustum, float voxelScaleSize, int boundaryLevelAdjust) const {
bool OctreeElement::calculateShouldRender(const ViewFrustum& viewFrustum, float voxelScaleSize, int boundaryLevelAdjust) const {
bool shouldRender = false;
if (hasContent()) {
float furthestDistance = furthestDistanceToCamera(*viewFrustum);
float furthestDistance = furthestDistanceToCamera(viewFrustum);
float childBoundary = boundaryDistanceForRenderLevel(getLevel() + 1 + boundaryLevelAdjust, voxelScaleSize);
bool inChildBoundary = (furthestDistance <= childBoundary);
if (hasDetailedContent() && inChildBoundary) {

View file

@ -21,9 +21,9 @@
#include <OctalCode.h>
#include <SharedUtil.h>
#include <ViewFrustum.h>
#include "AACube.h"
#include "ViewFrustum.h"
#include "OctreeConstants.h"
using AtomicUIntStat = std::atomic<uintmax_t>;
@ -139,7 +139,7 @@ public:
float distanceToCamera(const ViewFrustum& viewFrustum) const;
float furthestDistanceToCamera(const ViewFrustum& viewFrustum) const;
bool calculateShouldRender(const ViewFrustum* viewFrustum,
bool calculateShouldRender(const ViewFrustum& viewFrustum,
float voxelSizeScale = DEFAULT_OCTREE_SIZE_SCALE, int boundaryLevelAdjust = 0) const;
// points are assumed to be in Voxel Coordinates (not TREE_SCALE'd)

View file

@ -14,14 +14,12 @@
#include "OctreeLogging.h"
#include "OctreeHeadlessViewer.h"
OctreeHeadlessViewer::OctreeHeadlessViewer() : OctreeRenderer()
{
OctreeHeadlessViewer::OctreeHeadlessViewer() : OctreeRenderer() {
_viewFrustum.setProjection(glm::perspective(glm::radians(DEFAULT_FIELD_OF_VIEW_DEGREES), DEFAULT_ASPECT_RATIO, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP));
}
void OctreeHeadlessViewer::init() {
OctreeRenderer::init();
setViewFrustum(&_viewFrustum);
}
void OctreeHeadlessViewer::queryOctree() {

View file

@ -14,6 +14,7 @@
#include <udt/PacketHeaders.h>
#include <SharedUtil.h>
#include <ViewFrustum.h>
#include "JurisdictionListener.h"
#include "Octree.h"
@ -22,7 +23,6 @@
#include "OctreeRenderer.h"
#include "OctreeSceneStats.h"
#include "Octree.h"
#include "ViewFrustum.h"
// Generic client side Octree renderer class.
class OctreeHeadlessViewer : public OctreeRenderer {
@ -66,7 +66,6 @@ public slots:
unsigned getOctreeElementsCount() const { return _tree->getOctreeElementsCount(); }
private:
ViewFrustum _viewFrustum;
JurisdictionListener* _jurisdictionListener = nullptr;
OctreeQuery _octreeQuery;

View file

@ -120,4 +120,3 @@ glm::vec3 OctreeQuery::calculateCameraDirection() const {
glm::vec3 direction = glm::vec3(_cameraOrientation * glm::vec4(IDENTITY_FRONT, 0.0f));
return direction;
}

View file

@ -22,8 +22,7 @@
OctreeRenderer::OctreeRenderer() :
_tree(NULL),
_managedTree(false),
_viewFrustum(NULL)
_managedTree(false)
{
}
@ -201,9 +200,9 @@ void OctreeRenderer::processDatagram(ReceivedMessage& message, SharedNodePointer
bool OctreeRenderer::renderOperation(OctreeElementPointer element, void* extraData) {
RenderArgs* args = static_cast<RenderArgs*>(extraData);
if (element->isInView(*args->_viewFrustum)) {
if (element->isInView(args->getViewFrustum())) {
if (element->hasContent()) {
if (element->calculateShouldRender(args->_viewFrustum, args->_sizeScale, args->_boundaryLevelAdjust)) {
if (element->calculateShouldRender(args->getViewFrustum(), args->_sizeScale, args->_boundaryLevelAdjust)) {
args->_renderer->renderElement(element, args);
} else {
return false; // if we shouldn't render, then we also should stop recursing.

View file

@ -20,10 +20,10 @@
#include <udt/PacketHeaders.h>
#include <RenderArgs.h>
#include <SharedUtil.h>
#include <ViewFrustum.h>
#include "Octree.h"
#include "OctreePacketData.h"
#include "ViewFrustum.h"
class OctreeRenderer;
@ -51,8 +51,8 @@ public:
/// render the content of the octree
virtual void render(RenderArgs* renderArgs);
ViewFrustum* getViewFrustum() const { return _viewFrustum; }
void setViewFrustum(ViewFrustum* viewFrustum) { _viewFrustum = viewFrustum; }
const ViewFrustum& getViewFrustum() const { return _viewFrustum; }
void setViewFrustum(const ViewFrustum& viewFrustum) { _viewFrustum = viewFrustum; }
static bool renderOperation(OctreeElementPointer element, void* extraData);
@ -75,7 +75,7 @@ protected:
OctreePointer _tree;
bool _managedTree;
ViewFrustum* _viewFrustum;
ViewFrustum _viewFrustum;
SimpleMovingAverage _elementsPerPacket;
SimpleMovingAverage _entitiesPerPacket;

View file

@ -0,0 +1,71 @@
//
// OctreeUtils.cpp
// libraries/octree/src
//
// Created by Andrew Meadows 2016.03.04
// Copyright 2016 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "OctreeUtils.h"
#include <mutex>
#include <glm/glm.hpp>
#include <AABox.h>
float calculateRenderAccuracy(const glm::vec3& position,
const AABox& bounds,
float octreeSizeScale,
int boundaryLevelAdjust) {
float largestDimension = bounds.getLargestDimension();
const float maxScale = (float)TREE_SCALE;
float visibleDistanceAtMaxScale = boundaryDistanceForRenderLevel(boundaryLevelAdjust, octreeSizeScale) / OCTREE_TO_MESH_RATIO;
static std::once_flag once;
static QMap<float, float> shouldRenderTable;
std::call_once(once, [&] {
float SMALLEST_SCALE_IN_TABLE = 0.001f; // 1mm is plenty small
float scale = maxScale;
float factor = 1.0f;
while (scale > SMALLEST_SCALE_IN_TABLE) {
scale /= 2.0f;
factor /= 2.0f;
shouldRenderTable[scale] = factor;
}
});
float closestScale = maxScale;
float visibleDistanceAtClosestScale = visibleDistanceAtMaxScale;
QMap<float, float>::const_iterator lowerBound = shouldRenderTable.lowerBound(largestDimension);
if (lowerBound != shouldRenderTable.constEnd()) {
closestScale = lowerBound.key();
visibleDistanceAtClosestScale = visibleDistanceAtMaxScale * lowerBound.value();
}
if (closestScale < largestDimension) {
visibleDistanceAtClosestScale *= 2.0f;
}
// FIXME - for now, it's either visible or not visible. We want to adjust this to eventually return
// a floating point for objects that have small angular size to indicate that they may be rendered
// with lower preciscion
float distanceToCamera = glm::length(bounds.calcCenter() - position);
return (distanceToCamera <= visibleDistanceAtClosestScale) ? 1.0f : 0.0f;
}
float boundaryDistanceForRenderLevel(unsigned int renderLevel, float voxelSizeScale) {
return voxelSizeScale / powf(2.0f, renderLevel);
}
float getAccuracyAngle(float octreeSizeScale, int boundaryLevelAdjust) {
const float maxScale = (float)TREE_SCALE;
float visibleDistanceAtMaxScale = boundaryDistanceForRenderLevel(boundaryLevelAdjust, octreeSizeScale) / OCTREE_TO_MESH_RATIO;
return atan(maxScale / visibleDistanceAtMaxScale);
}

View file

@ -0,0 +1,30 @@
//
// OctreeUtils.h
// libraries/octree/src
//
// Created by Andrew Meadows 2016.03.04
// Copyright 2016 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_OctreeUtils_h
#define hifi_OctreeUtils_h
#include "OctreeConstants.h"
class AABox;
/// renderAccuracy represents a floating point "visibility" of an object based on it's view from the camera. At a simple
/// level it returns 0.0f for things that are so small for the current settings that they could not be visible.
float calculateRenderAccuracy(const glm::vec3& position,
const AABox& bounds,
float octreeSizeScale = DEFAULT_OCTREE_SIZE_SCALE,
int boundaryLevelAdjust = 0);
float boundaryDistanceForRenderLevel(unsigned int renderLevel, float voxelSizeScale);
float getAccuracyAngle(float octreeSizeScale, int boundaryLevelAdjust);
#endif // hifi_OctreeUtils_h

View file

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

View file

@ -284,7 +284,7 @@ void AmbientOcclusionEffect::updateGaussianDistribution() {
void AmbientOcclusionEffect::run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext) {
assert(renderContext->args);
assert(renderContext->args->_viewFrustum);
assert(renderContext->args->hasViewFrustum());
RenderArgs* args = renderContext->args;
@ -309,7 +309,7 @@ void AmbientOcclusionEffect::run(const render::SceneContextPointer& sceneContext
auto resolutionLevel = getResolutionLevel();
// Update the depth info with near and far (same for stereo)
setDepthInfo(args->_viewFrustum->getNearClip(), args->_viewFrustum->getFarClip());
setDepthInfo(args->getViewFrustum().getNearClip(), args->getViewFrustum().getFarClip());
_frameTransformBuffer.edit<FrameTransform>().pixelInfo = args->_viewport;
//_parametersBuffer.edit<Parameters>()._ditheringInfo.y += 0.25f;
@ -319,7 +319,7 @@ void AmbientOcclusionEffect::run(const render::SceneContextPointer& sceneContext
if (!isStereo) {
// Eval the mono projection
mat4 monoProjMat;
args->_viewFrustum->evalProjectionMatrix(monoProjMat);
args->getViewFrustum().evalProjectionMatrix(monoProjMat);
_frameTransformBuffer.edit<FrameTransform>().projection[0] = monoProjMat;
_frameTransformBuffer.edit<FrameTransform>().stereoInfo = glm::vec4(0.0f, (float)args->_viewport.z, 0.0f, 0.0f);
@ -365,7 +365,7 @@ void AmbientOcclusionEffect::run(const render::SceneContextPointer& sceneContext
// Pyramid pass
batch.setFramebuffer(pyramidFBO);
batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, glm::vec4(args->_viewFrustum->getFarClip(), 0.0f, 0.0f, 0.0f));
batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, glm::vec4(args->getViewFrustum().getFarClip(), 0.0f, 0.0f, 0.0f));
batch.setPipeline(pyramidPipeline);
batch.setResourceTexture(AmbientOcclusionEffect_DepthMapSlot, depthBuffer);
batch.draw(gpu::TRIANGLE_STRIP, 4);

View file

@ -94,7 +94,7 @@ const gpu::PipelinePointer& Antialiasing::getBlendPipeline() {
void Antialiasing::run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext) {
assert(renderContext->args);
assert(renderContext->args->_viewFrustum);
assert(renderContext->args->hasViewFrustum());
RenderArgs* args = renderContext->args;
@ -118,8 +118,8 @@ void Antialiasing::run(const render::SceneContextPointer& sceneContext, const re
glm::mat4 projMat;
Transform viewMat;
args->_viewFrustum->evalProjectionMatrix(projMat);
args->_viewFrustum->evalViewTransform(viewMat);
args->getViewFrustum().evalProjectionMatrix(projMat);
args->getViewFrustum().evalViewTransform(viewMat);
batch.setProjectionTransform(projMat);
batch.setViewTransform(viewMat);
batch.setModelTransform(Transform());
@ -134,7 +134,7 @@ void Antialiasing::run(const render::SceneContextPointer& sceneContext, const re
float left, right, bottom, top, nearVal, farVal;
glm::vec4 nearClipPlane, farClipPlane;
args->_viewFrustum->computeOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane);
args->getViewFrustum().computeOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane);
// float depthScale = (farVal - nearVal) / farVal;
// float nearScale = -1.0f / nearVal;

View file

@ -275,7 +275,7 @@ void DebugDeferredBuffer::configure(const Config& config) {
void DebugDeferredBuffer::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
assert(renderContext->args);
assert(renderContext->args->_viewFrustum);
assert(renderContext->args->hasViewFrustum());
RenderArgs* args = renderContext->args;
gpu::doInBatch(args->_context, [&](gpu::Batch& batch) {
@ -283,20 +283,20 @@ void DebugDeferredBuffer::run(const SceneContextPointer& sceneContext, const Ren
const auto framebufferCache = DependencyManager::get<FramebufferCache>();
const auto textureCache = DependencyManager::get<TextureCache>();
const auto& lightStage = DependencyManager::get<DeferredLightingEffect>()->getLightStage();
glm::mat4 projMat;
Transform viewMat;
args->_viewFrustum->evalProjectionMatrix(projMat);
args->_viewFrustum->evalViewTransform(viewMat);
args->getViewFrustum().evalProjectionMatrix(projMat);
args->getViewFrustum().evalViewTransform(viewMat);
batch.setProjectionTransform(projMat);
batch.setViewTransform(viewMat);
batch.setModelTransform(Transform());
// TODO REMOVE: Temporary until UI
auto first = _customPipelines.begin()->first;
batch.setPipeline(getPipeline(_mode, first));
batch.setResourceTexture(Albedo, framebufferCache->getDeferredColorTexture());
batch.setResourceTexture(Normal, framebufferCache->getDeferredNormalTexture());
batch.setResourceTexture(Specular, framebufferCache->getDeferredSpecularTexture());

View file

@ -218,15 +218,15 @@ void DeferredLightingEffect::render(const render::RenderContextPointer& renderCo
float tHeight = args->_viewport.w / (float)framebufferSize.height();
// The view frustum is the mono frustum base
auto viewFrustum = args->_viewFrustum;
auto viewFrustum = args->getViewFrustum();
// Eval the mono projection
mat4 monoProjMat;
viewFrustum->evalProjectionMatrix(monoProjMat);
viewFrustum.evalProjectionMatrix(monoProjMat);
// The mono view transform
Transform monoViewTransform;
viewFrustum->evalViewTransform(monoViewTransform);
viewFrustum.evalViewTransform(monoViewTransform);
// THe mono view matrix coming from the mono view transform
glm::mat4 monoViewMat;
@ -296,8 +296,8 @@ void DeferredLightingEffect::render(const render::RenderContextPointer& renderCo
fetchTexcoordRects[0] = glm::vec4(sMin, tMin, sWidth, tHeight);
}
auto eyePoint = viewFrustum->getPosition();
float nearRadius = glm::distance(eyePoint, viewFrustum->getNearTopLeft());
auto eyePoint = viewFrustum.getPosition();
float nearRadius = glm::distance(eyePoint, viewFrustum.getNearTopLeft());
for (int side = 0; side < numPasses; side++) {

View file

@ -62,19 +62,19 @@ const gpu::PipelinePointer& HitEffect::getHitEffectPipeline() {
void HitEffect::run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext) {
assert(renderContext->args);
assert(renderContext->args->_viewFrustum);
assert(renderContext->args->hasViewFrustum());
RenderArgs* args = renderContext->args;
gpu::doInBatch(args->_context, [&](gpu::Batch& batch) {
glm::mat4 projMat;
Transform viewMat;
args->_viewFrustum->evalProjectionMatrix(projMat);
args->_viewFrustum->evalViewTransform(viewMat);
args->getViewFrustum().evalProjectionMatrix(projMat);
args->getViewFrustum().evalViewTransform(viewMat);
batch.setProjectionTransform(projMat);
batch.setViewTransform(viewMat);
batch.setModelTransform(Transform());
batch.setPipeline(getHitEffectPipeline());
glm::vec4 color(0.0f, 0.0f, 0.0f, 1.0f);

View file

@ -20,7 +20,7 @@ LightStage::Shadow::Shadow(model::LightPointer light) : _light{ light}, _frustum
_schemaBuffer = std::make_shared<gpu::Buffer>(sizeof(Schema), (const gpu::Byte*) &schema);
}
void LightStage::Shadow::setKeylightFrustum(ViewFrustum* viewFrustum, float nearDepth, float farDepth) {
void LightStage::Shadow::setKeylightFrustum(const ViewFrustum& viewFrustum, float nearDepth, float farDepth) {
assert(nearDepth < farDepth);
// Orient the keylight frustum
@ -38,14 +38,13 @@ void LightStage::Shadow::setKeylightFrustum(ViewFrustum* viewFrustum, float near
_frustum->setOrientation(orientation);
// Position the keylight frustum
_frustum->setPosition(viewFrustum->getPosition() - (nearDepth + farDepth)*direction);
_frustum->setPosition(viewFrustum.getPosition() - (nearDepth + farDepth)*direction);
const Transform view{ _frustum->getView()};
const Transform viewInverse{ view.getInverseMatrix() };
viewFrustum->calculate();
auto nearCorners = viewFrustum->getCorners(nearDepth);
auto farCorners = viewFrustum->getCorners(farDepth);
auto nearCorners = viewFrustum.getCorners(nearDepth);
auto farCorners = viewFrustum.getCorners(farDepth);
vec3 min{ viewInverse.transform(nearCorners.bottomLeft) };
vec3 max{ min };

View file

@ -28,7 +28,7 @@ public:
Shadow(model::LightPointer light);
void setKeylightFrustum(ViewFrustum* viewFrustum, float nearDepth, float farDepth);
void setKeylightFrustum(const ViewFrustum& viewFrustum, float nearDepth, float farDepth);
const std::shared_ptr<ViewFrustum> getFrustum() const { return _frustum; }

View file

@ -163,7 +163,7 @@ void RenderDeferredTask::run(const SceneContextPointer& sceneContext, const Rend
// Is it possible that we render without a viewFrustum ?
if (!(renderContext->args && renderContext->args->_viewFrustum)) {
if (!(renderContext->args && renderContext->args->hasViewFrustum())) {
return;
}
@ -174,7 +174,7 @@ void RenderDeferredTask::run(const SceneContextPointer& sceneContext, const Rend
void DrawDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemBounds& inItems) {
assert(renderContext->args);
assert(renderContext->args->_viewFrustum);
assert(renderContext->args->hasViewFrustum());
auto config = std::static_pointer_cast<Config>(renderContext->jobConfig);
@ -187,8 +187,8 @@ void DrawDeferred::run(const SceneContextPointer& sceneContext, const RenderCont
glm::mat4 projMat;
Transform viewMat;
args->_viewFrustum->evalProjectionMatrix(projMat);
args->_viewFrustum->evalViewTransform(viewMat);
args->getViewFrustum().evalProjectionMatrix(projMat);
args->getViewFrustum().evalViewTransform(viewMat);
batch.setProjectionTransform(projMat);
batch.setViewTransform(viewMat);
@ -202,7 +202,7 @@ void DrawDeferred::run(const SceneContextPointer& sceneContext, const RenderCont
void DrawStateSortDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemBounds& inItems) {
assert(renderContext->args);
assert(renderContext->args->_viewFrustum);
assert(renderContext->args->hasViewFrustum());
auto config = std::static_pointer_cast<Config>(renderContext->jobConfig);
@ -215,8 +215,8 @@ void DrawStateSortDeferred::run(const SceneContextPointer& sceneContext, const R
glm::mat4 projMat;
Transform viewMat;
args->_viewFrustum->evalProjectionMatrix(projMat);
args->_viewFrustum->evalViewTransform(viewMat);
args->getViewFrustum().evalProjectionMatrix(projMat);
args->getViewFrustum().evalViewTransform(viewMat);
batch.setProjectionTransform(projMat);
batch.setViewTransform(viewMat);
@ -240,7 +240,7 @@ DrawOverlay3D::DrawOverlay3D(bool opaque) :
void DrawOverlay3D::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const render::ItemBounds& inItems) {
assert(renderContext->args);
assert(renderContext->args->_viewFrustum);
assert(renderContext->args->hasViewFrustum());
auto config = std::static_pointer_cast<Config>(renderContext->jobConfig);
@ -268,8 +268,8 @@ void DrawOverlay3D::run(const SceneContextPointer& sceneContext, const RenderCon
glm::mat4 projMat;
Transform viewMat;
args->_viewFrustum->evalProjectionMatrix(projMat);
args->_viewFrustum->evalViewTransform(viewMat);
args->getViewFrustum().evalProjectionMatrix(projMat);
args->getViewFrustum().evalViewTransform(viewMat);
batch.setProjectionTransform(projMat);
batch.setViewTransform(viewMat);
@ -290,7 +290,7 @@ const gpu::PipelinePointer& DrawStencilDeferred::getOpaquePipeline() {
void DrawStencilDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
assert(renderContext->args);
assert(renderContext->args->_viewFrustum);
assert(renderContext->args->hasViewFrustum());
// from the touched pixel generate the stencil buffer
RenderArgs* args = renderContext->args;
@ -316,7 +316,7 @@ void DrawStencilDeferred::run(const SceneContextPointer& sceneContext, const Ren
void DrawBackgroundDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemBounds& inItems) {
assert(renderContext->args);
assert(renderContext->args->_viewFrustum);
assert(renderContext->args->hasViewFrustum());
RenderArgs* args = renderContext->args;
doInBatch(args->_context, [&](gpu::Batch& batch) {
@ -334,8 +334,8 @@ void DrawBackgroundDeferred::run(const SceneContextPointer& sceneContext, const
glm::mat4 projMat;
Transform viewMat;
args->_viewFrustum->evalProjectionMatrix(projMat);
args->_viewFrustum->evalViewTransform(viewMat);
args->getViewFrustum().evalProjectionMatrix(projMat);
args->getViewFrustum().evalViewTransform(viewMat);
batch.setProjectionTransform(projMat);
batch.setViewTransform(viewMat);

View file

@ -34,7 +34,7 @@ using namespace render;
void RenderShadowMap::run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext,
const render::ShapeBounds& inShapes) {
assert(renderContext->args);
assert(renderContext->args->_viewFrustum);
assert(renderContext->args->hasViewFrustum());
const auto& lightStage = DependencyManager::get<DeferredLightingEffect>()->getLightStage();
const auto globalLight = lightStage.lights[0];
@ -146,16 +146,15 @@ void RenderShadowTask::run(const SceneContextPointer& sceneContext, const render
}
// Cache old render args
ViewFrustum* viewFrustum = args->_viewFrustum;
RenderArgs::RenderMode mode = args->_renderMode;
auto nearClip = viewFrustum->getNearClip();
auto nearClip = args->getViewFrustum().getNearClip();
float nearDepth = -args->_boomOffset.z;
const int SHADOW_FAR_DEPTH = 20;
globalLight->shadow.setKeylightFrustum(viewFrustum, nearDepth, nearClip + SHADOW_FAR_DEPTH);
globalLight->shadow.setKeylightFrustum(args->getViewFrustum(), nearDepth, nearClip + SHADOW_FAR_DEPTH);
// Set the keylight render args
args->_viewFrustum = globalLight->shadow.getFrustum().get();
args->pushViewFrustum(*(globalLight->shadow.getFrustum()));
args->_renderMode = RenderArgs::SHADOW_RENDER_MODE;
// TODO: Allow runtime manipulation of culling ShouldRenderFunctor
@ -165,6 +164,6 @@ void RenderShadowTask::run(const SceneContextPointer& sceneContext, const render
}
// Reset the render args
args->_viewFrustum = viewFrustum;
args->popViewFrustum();
args->_renderMode = mode;
};

View file

@ -14,6 +14,7 @@
#include <algorithm>
#include <assert.h>
#include <OctreeUtils.h>
#include <PerfStat.h>
#include <ViewFrustum.h>
#include <gpu/Context.h>
@ -23,10 +24,10 @@ using namespace render;
void render::cullItems(const RenderContextPointer& renderContext, const CullFunctor& cullFunctor, RenderDetails::Item& details,
const ItemBounds& inItems, ItemBounds& outItems) {
assert(renderContext->args);
assert(renderContext->args->_viewFrustum);
assert(renderContext->args->hasViewFrustum());
RenderArgs* args = renderContext->args;
ViewFrustum* frustum = args->_viewFrustum;
const ViewFrustum& frustum = args->getViewFrustum();
details._considered += (int)inItems.size();
@ -42,7 +43,7 @@ void render::cullItems(const RenderContextPointer& renderContext, const CullFunc
bool inView;
{
PerformanceTimer perfTimer("boxIntersectsFrustum");
inView = frustum->boxIntersectsFrustum(item.bound);
inView = frustum.boxIntersectsFrustum(item.bound);
}
if (inView) {
bool bigEnoughToRender;
@ -64,7 +65,7 @@ void render::cullItems(const RenderContextPointer& renderContext, const CullFunc
void FetchNonspatialItems::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, ItemBounds& outItems) {
assert(renderContext->args);
assert(renderContext->args->_viewFrustum);
assert(renderContext->args->hasViewFrustum());
auto& scene = sceneContext->_scene;
outItems.clear();
@ -85,7 +86,7 @@ void FetchSpatialTree::configure(const Config& config) {
void FetchSpatialTree::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, ItemSpatialTree::ItemSelection& outSelection) {
assert(renderContext->args);
assert(renderContext->args->_viewFrustum);
assert(renderContext->args->hasViewFrustum());
RenderArgs* args = renderContext->args;
auto& scene = sceneContext->_scene;
@ -93,22 +94,18 @@ void FetchSpatialTree::run(const SceneContextPointer& sceneContext, const Render
outSelection.clear();
// Eventually use a frozen frustum
auto queryFrustum = *args->_viewFrustum;
auto queryFrustum = args->getViewFrustum();
if (_freezeFrustum) {
if (_justFrozeFrustum) {
_justFrozeFrustum = false;
_frozenFrutstum = *args->_viewFrustum;
_frozenFrutstum = args->getViewFrustum();
}
queryFrustum = _frozenFrutstum;
}
// Octree selection!
float angle = glm::degrees(queryFrustum.getAccuracyAngle(args->_sizeScale, args->_boundaryLevelAdjust));
float angle = glm::degrees(getAccuracyAngle(args->_sizeScale, args->_boundaryLevelAdjust));
scene->getSpatialTree().selectCellItems(outSelection, _filter, queryFrustum, angle);
}
void CullSpatialSelection::configure(const Config& config) {
@ -120,7 +117,7 @@ void CullSpatialSelection::configure(const Config& config) {
void CullSpatialSelection::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext,
const ItemSpatialTree::ItemSelection& inSelection, ItemBounds& outItems) {
assert(renderContext->args);
assert(renderContext->args->_viewFrustum);
assert(renderContext->args->hasViewFrustum());
RenderArgs* args = renderContext->args;
auto& scene = sceneContext->_scene;
@ -128,13 +125,12 @@ void CullSpatialSelection::run(const SceneContextPointer& sceneContext, const Re
details._considered += (int)inSelection.numItems();
// Eventually use a frozen frustum
auto argFrustum = args->_viewFrustum;
if (_freezeFrustum) {
if (_justFrozeFrustum) {
_justFrozeFrustum = false;
_frozenFrutstum = *args->_viewFrustum;
_frozenFrutstum = args->getViewFrustum();
}
args->_viewFrustum = &_frozenFrutstum; // replace the true view frustum by the frozen one
args->pushViewFrustum(_frozenFrutstum); // replace the true view frustum by the frozen one
}
// Culling Frustum / solidAngle test helper class
@ -151,8 +147,8 @@ void CullSpatialSelection::run(const SceneContextPointer& sceneContext, const Re
_renderDetails(renderDetails)
{
// FIXME: Keep this code here even though we don't use it yet
/*_eyePos = _args->_viewFrustum->getPosition();
float a = glm::degrees(_args->_viewFrustum->getAccuracyAngle(_args->_sizeScale, _args->_boundaryLevelAdjust));
/*_eyePos = _args->getViewFrustum().getPosition();
float a = glm::degrees(Octree::getAccuracyAngle(_args->_sizeScale, _args->_boundaryLevelAdjust));
auto angle = std::min(glm::radians(45.0f), a); // no worse than 45 degrees
angle = std::max(glm::radians(1.0f / 60.0f), a); // no better than 1 minute of degree
auto tanAlpha = tan(angle);
@ -161,7 +157,7 @@ void CullSpatialSelection::run(const SceneContextPointer& sceneContext, const Re
}
bool frustumTest(const AABox& bound) {
if (!_args->_viewFrustum->boxIntersectsFrustum(bound)) {
if (!_args->getViewFrustum().boxIntersectsFrustum(bound)) {
_renderDetails._outOfView++;
return false;
}
@ -305,7 +301,7 @@ void CullSpatialSelection::run(const SceneContextPointer& sceneContext, const Re
// Restore frustum if using the frozen one:
if (_freezeFrustum) {
args->_viewFrustum = argFrustum;
args->popViewFrustum();
}
std::static_pointer_cast<Config>(renderContext->jobConfig)->numItems = (int)outItems.size();

View file

@ -14,6 +14,7 @@
#include <algorithm>
#include <assert.h>
#include <OctreeUtils.h>
#include <PerfStat.h>
#include <RenderArgs.h>
@ -86,7 +87,7 @@ void DrawSceneOctree::configure(const Config& config) {
void DrawSceneOctree::run(const SceneContextPointer& sceneContext,
const RenderContextPointer& renderContext, const ItemSpatialTree::ItemSelection& inSelection) {
assert(renderContext->args);
assert(renderContext->args->_viewFrustum);
assert(renderContext->args->hasViewFrustum());
RenderArgs* args = renderContext->args;
auto& scene = sceneContext->_scene;
@ -97,8 +98,8 @@ void DrawSceneOctree::run(const SceneContextPointer& sceneContext,
gpu::doInBatch(args->_context, [&](gpu::Batch& batch) {
glm::mat4 projMat;
Transform viewMat;
args->_viewFrustum->evalProjectionMatrix(projMat);
args->_viewFrustum->evalViewTransform(viewMat);
args->getViewFrustum().evalProjectionMatrix(projMat);
args->getViewFrustum().evalViewTransform(viewMat);
batch.setViewportTransform(args->_viewport);
batch.setProjectionTransform(projMat);
@ -148,7 +149,7 @@ void DrawSceneOctree::run(const SceneContextPointer& sceneContext,
}
// Draw the LOD Reticle
{
float angle = glm::degrees(args->_viewFrustum->getAccuracyAngle(args->_sizeScale, args->_boundaryLevelAdjust));
float angle = glm::degrees(getAccuracyAngle(args->_sizeScale, args->_boundaryLevelAdjust));
Transform crosshairModel;
crosshairModel.setTranslation(glm::vec3(0.0, 0.0, -1000.0));
crosshairModel.setScale(1000.0 * tan(glm::radians(angle))); // Scaling at the actual tan of the lod angle => Multiplied by TWO
@ -198,15 +199,15 @@ void DrawItemSelection::configure(const Config& config) {
void DrawItemSelection::run(const SceneContextPointer& sceneContext,
const RenderContextPointer& renderContext, const ItemSpatialTree::ItemSelection& inSelection) {
assert(renderContext->args);
assert(renderContext->args->_viewFrustum);
assert(renderContext->args->hasViewFrustum());
RenderArgs* args = renderContext->args;
auto& scene = sceneContext->_scene;
gpu::doInBatch(args->_context, [&](gpu::Batch& batch) {
glm::mat4 projMat;
Transform viewMat;
args->_viewFrustum->evalProjectionMatrix(projMat);
args->_viewFrustum->evalViewTransform(viewMat);
args->getViewFrustum().evalProjectionMatrix(projMat);
args->getViewFrustum().evalViewTransform(viewMat);
batch.setViewportTransform(args->_viewport);
batch.setProjectionTransform(projMat);

View file

@ -107,7 +107,7 @@ void DrawStatus::run(const SceneContextPointer& sceneContext,
const RenderContextPointer& renderContext,
const ItemBounds& inItems) {
assert(renderContext->args);
assert(renderContext->args->_viewFrustum);
assert(renderContext->args->hasViewFrustum());
RenderArgs* args = renderContext->args;
auto& scene = sceneContext->_scene;
const int NUM_STATUS_VEC4_PER_ITEM = 2;
@ -183,8 +183,8 @@ void DrawStatus::run(const SceneContextPointer& sceneContext,
gpu::doInBatch(args->_context, [&](gpu::Batch& batch) {
glm::mat4 projMat;
Transform viewMat;
args->_viewFrustum->evalProjectionMatrix(projMat);
args->_viewFrustum->evalViewTransform(viewMat);
args->getViewFrustum().evalProjectionMatrix(projMat);
args->getViewFrustum().evalViewTransform(viewMat);
batch.setViewportTransform(args->_viewport);
batch.setProjectionTransform(projMat);

View file

@ -120,7 +120,7 @@ void render::renderStateSortShapes(const SceneContextPointer& sceneContext, cons
void DrawLight::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemBounds& inLights) {
assert(renderContext->args);
assert(renderContext->args->_viewFrustum);
assert(renderContext->args->hasViewFrustum());
RenderArgs* args = renderContext->args;
// render lights

View file

@ -1,5 +1,5 @@
//
// CullTask.cpp
// SortTask.cpp
// render/src/render
//
// Created by Sam Gateau on 2/2/16.
@ -42,7 +42,7 @@ struct BackToFrontSort {
void render::depthSortItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, bool frontToBack, const ItemBounds& inItems, ItemBounds& outItems) {
assert(renderContext->args);
assert(renderContext->args->_viewFrustum);
assert(renderContext->args->hasViewFrustum());
auto& scene = sceneContext->_scene;
RenderArgs* args = renderContext->args;
@ -60,7 +60,7 @@ void render::depthSortItems(const SceneContextPointer& sceneContext, const Rende
for (auto itemDetails : inItems) {
auto item = scene->getItem(itemDetails.id);
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));
}

View file

@ -1,6 +1,6 @@
//
// OctreeProjectedPolygon.cpp
// libraries/octree/src
// CubeProjectedPolygon.cpp
// libraries/shared/src
//
// Created by Brad Hefta-Gaub on 06/11/13.
// Copyright 2013 High Fidelity, Inc.
@ -15,50 +15,50 @@
#include "GeometryUtil.h"
#include "SharedUtil.h"
#include "OctreeLogging.h"
#include "OctreeProjectedPolygon.h"
#include "SharedLogging.h"
#include "CubeProjectedPolygon.h"
glm::vec2 BoundingBox::getVertex(int vertexNumber) const {
glm::vec2 BoundingRectangle::getVertex(int vertexNumber) const {
switch (vertexNumber) {
case BoundingBox::BOTTOM_LEFT:
case BoundingRectangle::BOTTOM_LEFT:
return corner;
case BoundingBox::TOP_LEFT:
case BoundingRectangle::TOP_LEFT:
return glm::vec2(corner.x, corner.y + size.y);
case BoundingBox::BOTTOM_RIGHT:
case BoundingRectangle::BOTTOM_RIGHT:
return glm::vec2(corner.x + size.x, corner.y);
case BoundingBox::TOP_RIGHT:
case BoundingRectangle::TOP_RIGHT:
return corner + size;
}
assert(false); // not allowed
return glm::vec2(0,0);
}
BoundingBox BoundingBox::topHalf() const {
BoundingRectangle BoundingRectangle::topHalf() const {
float halfY = size.y/2.0f;
BoundingBox result(glm::vec2(corner.x,corner.y + halfY), glm::vec2(size.x, halfY));
BoundingRectangle result(glm::vec2(corner.x,corner.y + halfY), glm::vec2(size.x, halfY));
return result;
}
BoundingBox BoundingBox::bottomHalf() const {
BoundingRectangle BoundingRectangle::bottomHalf() const {
float halfY = size.y/2.0f;
BoundingBox result(corner, glm::vec2(size.x, halfY));
BoundingRectangle result(corner, glm::vec2(size.x, halfY));
return result;
}
BoundingBox BoundingBox::leftHalf() const {
BoundingRectangle BoundingRectangle::leftHalf() const {
float halfX = size.x/2.0f;
BoundingBox result(corner, glm::vec2(halfX, size.y));
BoundingRectangle result(corner, glm::vec2(halfX, size.y));
return result;
}
BoundingBox BoundingBox::rightHalf() const {
BoundingRectangle BoundingRectangle::rightHalf() const {
float halfX = size.x/2.0f;
BoundingBox result(glm::vec2(corner.x + halfX , corner.y), glm::vec2(halfX, size.y));
BoundingRectangle result(glm::vec2(corner.x + halfX , corner.y), glm::vec2(halfX, size.y));
return result;
}
bool BoundingBox::contains(const BoundingBox& box) const {
bool BoundingRectangle::contains(const BoundingRectangle& box) const {
return ( _set &&
(box.corner.x >= corner.x) &&
(box.corner.y >= corner.y) &&
@ -67,7 +67,7 @@ bool BoundingBox::contains(const BoundingBox& box) const {
);
}
bool BoundingBox::contains(const glm::vec2& point) const {
bool BoundingRectangle::contains(const glm::vec2& point) const {
return ( _set &&
(point.x > corner.x) &&
(point.y > corner.y) &&
@ -76,7 +76,7 @@ bool BoundingBox::contains(const glm::vec2& point) const {
);
}
void BoundingBox::explandToInclude(const BoundingBox& box) {
void BoundingRectangle::explandToInclude(const BoundingRectangle& box) {
if (!_set) {
corner = box.corner;
size = box.size;
@ -94,20 +94,20 @@ void BoundingBox::explandToInclude(const BoundingBox& box) {
}
void BoundingBox::printDebugDetails(const char* label) const {
qCDebug(octree, "%s _set=%s\n corner=%f,%f size=%f,%f\n bounds=[(%f,%f) to (%f,%f)]",
(label ? label : "BoundingBox"),
void BoundingRectangle::printDebugDetails(const char* label) const {
qCDebug(shared, "%s _set=%s\n corner=%f,%f size=%f,%f\n bounds=[(%f,%f) to (%f,%f)]",
(label ? label : "BoundingRectangle"),
debug::valueOf(_set), (double)corner.x, (double)corner.y, (double)size.x, (double)size.y,
(double)corner.x, (double)corner.y, (double)(corner.x+size.x), (double)(corner.y+size.y));
}
long OctreeProjectedPolygon::pointInside_calls = 0;
long OctreeProjectedPolygon::occludes_calls = 0;
long OctreeProjectedPolygon::intersects_calls = 0;
long CubeProjectedPolygon::pointInside_calls = 0;
long CubeProjectedPolygon::occludes_calls = 0;
long CubeProjectedPolygon::intersects_calls = 0;
OctreeProjectedPolygon::OctreeProjectedPolygon(const BoundingBox& box) :
CubeProjectedPolygon::CubeProjectedPolygon(const BoundingRectangle& box) :
_vertexCount(4),
_maxX(-FLT_MAX), _maxY(-FLT_MAX), _minX(FLT_MAX), _minY(FLT_MAX),
_distance(0)
@ -118,7 +118,7 @@ OctreeProjectedPolygon::OctreeProjectedPolygon(const BoundingBox& box) :
}
void OctreeProjectedPolygon::setVertex(int vertex, const glm::vec2& point) {
void CubeProjectedPolygon::setVertex(int vertex, const glm::vec2& point) {
_vertices[vertex] = point;
// keep track of our bounding box
@ -138,9 +138,9 @@ void OctreeProjectedPolygon::setVertex(int vertex, const glm::vec2& point) {
}
// can be optimized with new pointInside()
bool OctreeProjectedPolygon::occludes(const OctreeProjectedPolygon& occludee, bool checkAllInView) const {
bool CubeProjectedPolygon::occludes(const CubeProjectedPolygon& occludee, bool checkAllInView) const {
OctreeProjectedPolygon::occludes_calls++;
CubeProjectedPolygon::occludes_calls++;
// if we are completely out of view, then we definitely don't occlude!
// if the occludee is completely out of view, then we also don't occlude it
@ -197,12 +197,12 @@ bool OctreeProjectedPolygon::occludes(const OctreeProjectedPolygon& occludee, bo
return false; // if we got this far, then we're not occluded
}
bool OctreeProjectedPolygon::occludes(const BoundingBox& boxOccludee) const {
OctreeProjectedPolygon testee(boxOccludee);
bool CubeProjectedPolygon::occludes(const BoundingRectangle& boxOccludee) const {
CubeProjectedPolygon testee(boxOccludee);
return occludes(testee);
}
bool OctreeProjectedPolygon::matches(const OctreeProjectedPolygon& testee) const {
bool CubeProjectedPolygon::matches(const CubeProjectedPolygon& testee) const {
if (testee.getVertexCount() != getVertexCount()) {
return false;
}
@ -231,14 +231,14 @@ bool OctreeProjectedPolygon::matches(const OctreeProjectedPolygon& testee) const
return true; // all of our vertices match, therefore we're the same
}
bool OctreeProjectedPolygon::matches(const BoundingBox& box) const {
OctreeProjectedPolygon testee(box);
bool CubeProjectedPolygon::matches(const BoundingRectangle& box) const {
CubeProjectedPolygon testee(box);
return matches(testee);
}
bool OctreeProjectedPolygon::pointInside(const glm::vec2& point, bool* matchesVertex) const {
bool CubeProjectedPolygon::pointInside(const glm::vec2& point, bool* matchesVertex) const {
OctreeProjectedPolygon::pointInside_calls++;
CubeProjectedPolygon::pointInside_calls++;
// first check the bounding boxes, the point must be fully within the boounding box of this polygon
if ((point.x > getMaxX()) ||
@ -264,23 +264,23 @@ bool OctreeProjectedPolygon::pointInside(const glm::vec2& point, bool* matchesVe
return true;
}
void OctreeProjectedPolygon::printDebugDetails() const {
qCDebug(octree, "OctreeProjectedPolygon..."
void CubeProjectedPolygon::printDebugDetails() const {
qCDebug(shared, "CubeProjectedPolygon..."
" minX=%f maxX=%f minY=%f maxY=%f", (double)getMinX(), (double)getMaxX(), (double)getMinY(), (double)getMaxY());
qCDebug(octree, " vertex count=%d distance=%f", getVertexCount(), (double)getDistance());
qCDebug(shared, " vertex count=%d distance=%f", getVertexCount(), (double)getDistance());
for (int i = 0; i < getVertexCount(); i++) {
glm::vec2 point = getVertex(i);
qCDebug(octree, " vertex[%d] = %f, %f ", i, (double)point.x, (double)point.y);
qCDebug(shared, " vertex[%d] = %f, %f ", i, (double)point.x, (double)point.y);
}
}
bool OctreeProjectedPolygon::intersects(const BoundingBox& box) const {
OctreeProjectedPolygon testee(box);
bool CubeProjectedPolygon::intersects(const BoundingRectangle& box) const {
CubeProjectedPolygon testee(box);
return intersects(testee);
}
bool OctreeProjectedPolygon::intersects(const OctreeProjectedPolygon& testee) const {
OctreeProjectedPolygon::intersects_calls++;
bool CubeProjectedPolygon::intersects(const CubeProjectedPolygon& testee) const {
CubeProjectedPolygon::intersects_calls++;
return intersectsOnAxes(testee) && testee.intersectsOnAxes(*this);
}
@ -294,7 +294,7 @@ bool OctreeProjectedPolygon::intersects(const OctreeProjectedPolygon& testee) co
// Note: this only works on convex polygons
//
//
bool OctreeProjectedPolygon::intersectsOnAxes(const OctreeProjectedPolygon& testee) const {
bool CubeProjectedPolygon::intersectsOnAxes(const CubeProjectedPolygon& testee) const {
// consider each edge of this polygon as a potential separating axis
for (int i = 0; i < getVertexCount(); i++) {
@ -324,7 +324,7 @@ bool OctreeProjectedPolygon::intersectsOnAxes(const OctreeProjectedPolygon& test
return true;
}
bool OctreeProjectedPolygon::canMerge(const OctreeProjectedPolygon& that) const {
bool CubeProjectedPolygon::canMerge(const CubeProjectedPolygon& that) const {
// RIGHT/NEAR
// LEFT/NEAR
@ -642,7 +642,7 @@ bool OctreeProjectedPolygon::canMerge(const OctreeProjectedPolygon& that) const
}
void OctreeProjectedPolygon::merge(const OctreeProjectedPolygon& that) {
void CubeProjectedPolygon::merge(const CubeProjectedPolygon& that) {
// RIGHT/NEAR
// LEFT/NEAR

View file

@ -1,55 +1,55 @@
//
// OctreeProjectedPolygon.h
// libraries/octree/src
// CubeProjectedPolygon.h
// libraries/shared/src
//
// Created by Brad Hefta-Gaub on 06/11/13.
// Copyright 2013 High Fidelity, Inc.
//
// The projected shadow (on the 2D view plane) for a voxel
// The projected shadow (on the 2D view plane) for a cube
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_OctreeProjectedPolygon_h
#define hifi_OctreeProjectedPolygon_h
#ifndef hifi_CubeProjectedPolygon_h
#define hifi_CubeProjectedPolygon_h
#include <glm/glm.hpp>
// there's a max of 6 vertices of a project polygon, and a max of twice that when clipped to the screen
const int MAX_PROJECTED_POLYGON_VERTEX_COUNT = 6;
const int MAX_CLIPPED_PROJECTED_POLYGON_VERTEX_COUNT = MAX_PROJECTED_POLYGON_VERTEX_COUNT * 2;
const int MAX_PROJECTED_POLYGON_VERTEX_COUNT = 6;
const int MAX_CLIPPED_PROJECTED_POLYGON_VERTEX_COUNT = MAX_PROJECTED_POLYGON_VERTEX_COUNT * 2;
typedef glm::vec2 ProjectedVertices[MAX_CLIPPED_PROJECTED_POLYGON_VERTEX_COUNT];
class BoundingBox {
class BoundingRectangle {
public:
enum { BOTTOM_LEFT, BOTTOM_RIGHT, TOP_RIGHT, TOP_LEFT, VERTEX_COUNT };
BoundingBox(const glm::vec2 corner, const glm::vec2 size) : corner(corner), size(size), _set(true) {}
BoundingBox() : _set(false) {}
BoundingRectangle(const glm::vec2 corner, const glm::vec2 size) : corner(corner), size(size), _set(true) {}
BoundingRectangle() : _set(false) {}
glm::vec2 corner;
glm::vec2 size;
bool contains(const BoundingBox& box) const;
bool contains(const BoundingRectangle& box) const;
bool contains(const glm::vec2& point) const;
bool pointInside(const glm::vec2& point) const { return contains(point); }
void explandToInclude(const BoundingBox& box);
void explandToInclude(const BoundingRectangle& box);
float area() const { return size.x * size.y; }
int getVertexCount() const { return VERTEX_COUNT; }
glm::vec2 getVertex(int vertexNumber) const;
BoundingBox topHalf() const;
BoundingBox bottomHalf() const;
BoundingBox leftHalf() const;
BoundingBox rightHalf() const;
BoundingRectangle topHalf() const;
BoundingRectangle bottomHalf() const;
BoundingRectangle leftHalf() const;
BoundingRectangle rightHalf() const;
float getMaxX() const { return corner.x + size.x; }
float getMaxY() const { return corner.y + size.y; }
float getMinX() const { return corner.x; }
float getMinY() const { return corner.y; }
void printDebugDetails(const char* label=NULL) const;
private:
bool _set;
@ -63,18 +63,18 @@ const int PROJECTION_NEAR = 16;
const int PROJECTION_FAR = 32;
const int PROJECTION_CLIPPED = 64;
class OctreeProjectedPolygon {
class CubeProjectedPolygon {
public:
OctreeProjectedPolygon(const BoundingBox& box);
CubeProjectedPolygon(const BoundingRectangle& box);
OctreeProjectedPolygon(int vertexCount = 0) :
_vertexCount(vertexCount),
CubeProjectedPolygon(int vertexCount = 0) :
_vertexCount(vertexCount),
_maxX(-FLT_MAX), _maxY(-FLT_MAX), _minX(FLT_MAX), _minY(FLT_MAX),
_distance(0)
{ }
~OctreeProjectedPolygon() { }
~CubeProjectedPolygon() { }
const ProjectedVertices& getVertices() const { return _vertices; }
const glm::vec2& getVertex(int i) const { return _vertices[i]; }
void setVertex(int vertex, const glm::vec2& point);
@ -92,28 +92,28 @@ public:
bool pointInside(const glm::vec2& point, bool* matchesVertex = NULL) const;
bool occludes(const OctreeProjectedPolygon& occludee, bool checkAllInView = false) const;
bool occludes(const BoundingBox& occludee) const;
bool intersects(const OctreeProjectedPolygon& testee) const;
bool intersects(const BoundingBox& box) const;
bool matches(const OctreeProjectedPolygon& testee) const;
bool matches(const BoundingBox& testee) const;
bool intersectsOnAxes(const OctreeProjectedPolygon& testee) const;
bool occludes(const CubeProjectedPolygon& occludee, bool checkAllInView = false) const;
bool occludes(const BoundingRectangle& occludee) const;
bool intersects(const CubeProjectedPolygon& testee) const;
bool intersects(const BoundingRectangle& box) const;
bool matches(const CubeProjectedPolygon& testee) const;
bool matches(const BoundingRectangle& testee) const;
bool intersectsOnAxes(const CubeProjectedPolygon& testee) const;
bool canMerge(const CubeProjectedPolygon& that) const;
void merge(const CubeProjectedPolygon& that); // replaces vertices of this with new merged version
bool canMerge(const OctreeProjectedPolygon& that) const;
void merge(const OctreeProjectedPolygon& that); // replaces vertices of this with new merged version
float getMaxX() const { return _maxX; }
float getMaxY() const { return _maxY; }
float getMinX() const { return _minX; }
float getMinY() const { return _minY; }
BoundingBox getBoundingBox() const {
return BoundingBox(glm::vec2(_minX,_minY), glm::vec2(_maxX - _minX, _maxY - _minY));
BoundingRectangle getBoundingBox() const {
return BoundingRectangle(glm::vec2(_minX,_minY), glm::vec2(_maxX - _minX, _maxY - _minY));
}
void printDebugDetails() const;
static long pointInside_calls;
static long occludes_calls;
static long intersects_calls;
@ -132,4 +132,4 @@ private:
};
#endif // hifi_OctreeProjectedPolygon_h
#endif // hifi_CubeProjectedPolygon_h

View file

@ -35,7 +35,7 @@ float PIDController::update(float measuredValue, float dt, bool resetAccumulator
updateHistory(measuredValue, dt, error, accumulatedError, changeInError, p, i, d, computedValue);
}
Q_ASSERT(!glm::isnan(computedValue));
// update state for next time
_lastError = error;
_lastAccumulation = accumulatedError;

View file

@ -1,6 +1,6 @@
//
// Plane.cpp
// libraries/octree/src/
// libraries/shared/src/
//
// Created by Brad Hefta-Gaub on 04/11/13.
// Copyright 2013 High Fidelity, Inc.
@ -13,12 +13,12 @@
//
#include "Plane.h"
#include "OctreeLogging.h"
#include <QtCore/QDebug>
#include <stdio.h>
#include <QtCore/QDebug>
#include "SharedLogging.h"
void Plane::set3Points(const glm::vec3 &v1, const glm::vec3 &v2, const glm::vec3 &v3) {
glm::vec3 linev1v2, linev1v3;
@ -65,7 +65,7 @@ float Plane::distance(const glm::vec3 &point) const {
}
void Plane::print() const {
qCDebug(octree, "Plane - point (x=%f y=%f z=%f) normal (x=%f y=%f z=%f) d=%f",
qCDebug(shared, "Plane - point (x=%f y=%f z=%f) normal (x=%f y=%f z=%f) d=%f",
(double)_point.x, (double)_point.y, (double)_point.z,
(double)_normal.x, (double)_normal.y, (double)_normal.z, (double)_dCoefficient);
}

View file

@ -1,6 +1,6 @@
//
// Plane.h
// libraries/octree/src/
// libraries/shared/src/
//
// Created by Brad Hefta-Gaub on 04/11/13.
// Copyright 2013 High Fidelity, Inc.
@ -20,7 +20,7 @@
class Plane {
public:
Plane(const glm::vec3 &v1, const glm::vec3 &v2, const glm::vec3 &v3) { set3Points(v1,v2,v3); }
Plane() : _normal(0,0,0), _point(0,0,0), _dCoefficient(0) {};
Plane() : _normal(0.0f), _point(0.0f), _dCoefficient(0.0f) {};
~Plane() {} ;
// methods for defining the plane
@ -28,12 +28,13 @@ public:
void setNormalAndPoint(const glm::vec3 &normal, const glm::vec3 &point);
void setCoefficients(float a, float b, float c, float d);
// getters
// getters
const glm::vec3& getNormal() const { return _normal; };
const glm::vec3& getPoint() const { return _point; };
float getDCoefficient() const { return _dCoefficient; };
// utilities
void invalidate() { _normal = glm::vec3(0.0f), _dCoefficient = 1.0e6f; } // distance() never less than 10^6
float distance(const glm::vec3 &point) const;
void print() const;
@ -44,4 +45,4 @@ private:
};
#endif // hifi_Plane_h
#endif // hifi_Plane_h

View file

@ -14,12 +14,15 @@
#include <functional>
#include <memory>
#include "GLMHelpers.h"
#include <stack>
#include <GLMHelpers.h>
#include <ViewFrustum.h>
class AABox;
class OctreeRenderer;
class ViewFrustum;
namespace gpu {
class Batch;
@ -39,21 +42,21 @@ public:
SHADOW,
OTHER
};
struct Item {
int _considered = 0;
int _outOfView = 0;
int _tooSmall = 0;
int _rendered = 0;
};
int _materialSwitches = 0;
int _trianglesRendered = 0;
Item _item;
Item _shadow;
Item _other;
Item& edit(Type type) {
switch (type) {
case SHADOW:
@ -77,7 +80,6 @@ public:
RenderArgs(std::shared_ptr<gpu::Context> context = nullptr,
OctreeRenderer* renderer = nullptr,
ViewFrustum* viewFrustum = nullptr,
float sizeScale = 1.0f,
int boundaryLevelAdjust = 0,
RenderMode renderMode = DEFAULT_RENDER_MODE,
@ -86,7 +88,6 @@ public:
gpu::Batch* batch = nullptr) :
_context(context),
_renderer(renderer),
_viewFrustum(viewFrustum),
_sizeScale(sizeScale),
_boundaryLevelAdjust(boundaryLevelAdjust),
_renderMode(renderMode),
@ -95,11 +96,22 @@ public:
_batch(batch) {
}
bool hasViewFrustum() const { return _viewFrustums.size() > 0; }
void setViewFrustum(const ViewFrustum& viewFrustum) {
while (_viewFrustums.size() > 0) {
_viewFrustums.pop();
}
_viewFrustums.push(viewFrustum);
}
const ViewFrustum& getViewFrustum() const { assert(_viewFrustums.size() > 0); return _viewFrustums.top(); }
void pushViewFrustum(const ViewFrustum& viewFrustum) { _viewFrustums.push(viewFrustum); }
void popViewFrustum() { _viewFrustums.pop(); }
std::shared_ptr<gpu::Context> _context = nullptr;
std::shared_ptr<gpu::Framebuffer> _blitFramebuffer = nullptr;
std::shared_ptr<render::ShapePipeline> _pipeline = nullptr;
OctreeRenderer* _renderer = nullptr;
ViewFrustum* _viewFrustum = nullptr;
std::stack<ViewFrustum> _viewFrustums;
glm::ivec4 _viewport{ 0.0f, 0.0f, 1.0f, 1.0f };
glm::vec3 _boomOffset{ 0.0f, 0.0f, 1.0f };
float _sizeScale = 1.0f;
@ -108,7 +120,7 @@ public:
RenderSide _renderSide = MONO;
DebugFlags _debugFlags = RENDER_DEBUG_NONE;
gpu::Batch* _batch = nullptr;
std::shared_ptr<gpu::Texture> _whiteTexture;
RenderDetails _details;

View file

@ -1,6 +1,6 @@
//
// ViewFrustum.cpp
// libraries/octree/src
// libraries/shared/src
//
// Created by Brad Hefta-Gaub on 04/11/13.
// Copyright 2013 High Fidelity, Inc.
@ -17,13 +17,13 @@
#include <glm/gtx/vector_angle.hpp>
#include <QtCore/QDebug>
#include <NumericalConstants.h>
#include "GeometryUtil.h"
#include "GLMHelpers.h"
#include "NumericalConstants.h"
#include "SharedLogging.h"
//#include "OctreeConstants.h"
#include "ViewFrustum.h"
#include "OctreeLogging.h"
#include "OctreeConstants.h"
using namespace std;
@ -41,24 +41,24 @@ void ViewFrustum::setPosition(const glm::vec3& position) {
}
// Order cooresponds to the order defined in the BoxVertex enum.
static const glm::vec4 NDC_VALUES[8] = {
glm::vec4(-1, -1, -1, 1),
glm::vec4(1, -1, -1, 1),
glm::vec4(1, 1, -1, 1),
glm::vec4(-1, 1, -1, 1),
glm::vec4(-1, -1, 1, 1),
glm::vec4(1, -1, 1, 1),
glm::vec4(1, 1, 1, 1),
glm::vec4(-1, 1, 1, 1),
static const glm::vec4 NDC_VALUES[NUM_FRUSTUM_CORNERS] = {
glm::vec4(-1.0f, -1.0f, -1.0f, 1.0f),
glm::vec4(1.0f, -1.0f, -1.0f, 1.0f),
glm::vec4(1.0f, 1.0f, -1.0f, 1.0f),
glm::vec4(-1.0f, 1.0f, -1.0f, 1.0f),
glm::vec4(-1.0f, -1.0f, 1.0f, 1.0f),
glm::vec4(1.0f, -1.0f, 1.0f, 1.0f),
glm::vec4(1.0f, 1.0f, 1.0f, 1.0f),
glm::vec4(-1.0f, 1.0f, 1.0f, 1.0f),
};
void ViewFrustum::setProjection(const glm::mat4& projection) {
_projection = projection;
_inverseProjection = glm::inverse(projection);
glm::mat4 inverseProjection = glm::inverse(projection);
// compute our dimensions the usual way
for (int i = 0; i < 8; ++i) {
_corners[i] = _inverseProjection * NDC_VALUES[i];
for (int i = 0; i < NUM_FRUSTUM_CORNERS; ++i) {
_corners[i] = inverseProjection * NDC_VALUES[i];
_corners[i] /= _corners[i].w;
}
_nearClip = -_corners[BOTTOM_LEFT_NEAR].z;
@ -66,12 +66,12 @@ void ViewFrustum::setProjection(const glm::mat4& projection) {
_aspectRatio = (_corners[TOP_RIGHT_NEAR].x - _corners[BOTTOM_LEFT_NEAR].x) /
(_corners[TOP_RIGHT_NEAR].y - _corners[BOTTOM_LEFT_NEAR].y);
glm::vec4 top = _inverseProjection * vec4(0, 1, -1, 1);
glm::vec4 top = inverseProjection * vec4(0.0f, 1.0f, -1.0f, 1.0f);
top /= top.w;
_fieldOfView = abs(glm::degrees(2.0f * abs(glm::angle(vec3(0, 0, -1), glm::normalize(vec3(top))))));
_fieldOfView = abs(glm::degrees(2.0f * abs(glm::angle(vec3(0.0f, 0.0f, -1.0f), glm::normalize(vec3(top))))));
}
// ViewFrustum::calculateViewFrustum()
// ViewFrustum::calculate()
//
// Description: this will calculate the view frustum bounds for a given position and direction
//
@ -84,7 +84,7 @@ void ViewFrustum::calculate() {
// then transform them to world space
glm::mat4 worldMatrix = glm::translate(_position) * glm::mat4(glm::mat3(_right, _up, -_direction));
glm::vec4 v;
for (int i = 0; i < 8; ++i) {
for (int i = 0; i < NUM_FRUSTUM_CORNERS; ++i) {
v = worldMatrix * _corners[i];
v /= v.w;
_cornersWorld[i] = glm::vec3(v);
@ -133,7 +133,7 @@ const char* ViewFrustum::debugPlaneName (int plane) const {
ViewFrustum::intersection ViewFrustum::calculateCubeFrustumIntersection(const AACube& cube) const {
// only check against frustum
ViewFrustum::intersection result = INSIDE;
for(int i=0; i < 6; i++) {
for(int i = 0; i < NUM_FRUSTUM_PLANES; i++) {
const glm::vec3& normal = _planes[i].getNormal();
// check distance to farthest cube point
if ( _planes[i].distance(cube.getFarthestVertex(normal)) < 0.0f) {
@ -178,7 +178,7 @@ ViewFrustum::intersection ViewFrustum::calculateCubeKeyholeIntersection(const AA
bool ViewFrustum::pointIntersectsFrustum(const glm::vec3& point) const {
// only check against frustum
for(int i = 0; i < 6; ++i) {
for(int i = 0; i < NUM_FRUSTUM_PLANES; ++i) {
float distance = _planes[i].distance(point);
if (distance < 0.0f) {
return false;
@ -189,7 +189,7 @@ bool ViewFrustum::pointIntersectsFrustum(const glm::vec3& point) const {
bool ViewFrustum::sphereIntersectsFrustum(const glm::vec3& center, float radius) const {
// only check against frustum
for(int i=0; i < 6; i++) {
for(int i = 0; i < NUM_FRUSTUM_PLANES; i++) {
float distance = _planes[i].distance(center);
if (distance < -radius) {
// This is outside the regular frustum, so just return the value from checking the keyhole
@ -201,7 +201,7 @@ bool ViewFrustum::sphereIntersectsFrustum(const glm::vec3& center, float radius)
bool ViewFrustum::boxIntersectsFrustum(const AABox& box) const {
// only check against frustum
for(int i=0; i < 6; i++) {
for(int i = 0; i < NUM_FRUSTUM_PLANES; i++) {
const glm::vec3& normal = _planes[i].getNormal();
// check distance to farthest box point
if ( _planes[i].distance(box.getFarthestVertex(normal)) < 0.0f) {
@ -217,7 +217,7 @@ bool ViewFrustum::sphereIntersectsKeyhole(const glm::vec3& center, float radius)
return true;
}
// check negative touches against frustum planes
for(int i=0; i < 6; i++) {
for(int i = 0; i < NUM_FRUSTUM_PLANES; i++) {
if ( _planes[i].distance(center) < -radius) {
return false;
}
@ -231,7 +231,7 @@ bool ViewFrustum::cubeIntersectsKeyhole(const AACube& cube) const {
return true;
}
// check negative touches against frustum planes
for(int i=0; i < 6; i++) {
for(int i = 0; i < NUM_FRUSTUM_PLANES; i++) {
const glm::vec3& normal = _planes[i].getNormal();
if ( _planes[i].distance(cube.getFarthestVertex(normal)) < 0.0f) {
return false;
@ -246,7 +246,7 @@ bool ViewFrustum::boxIntersectsKeyhole(const AABox& box) const {
return true;
}
// check negative touches against frustum planes
for(int i=0; i < 6; i++) {
for(int i = 0; i < NUM_FRUSTUM_PLANES; i++) {
const glm::vec3& normal = _planes[i].getNormal();
if ( _planes[i].distance(box.getFarthestVertex(normal)) < 0.0f) {
return false;
@ -281,36 +281,36 @@ bool ViewFrustum::matches(const ViewFrustum& compareTo, bool debug) const {
testMatches(compareTo._focalLength, _focalLength);
if (!result && debug) {
qCDebug(octree, "ViewFrustum::matches()... result=%s", debug::valueOf(result));
qCDebug(octree, "%s -- compareTo._position=%f,%f,%f _position=%f,%f,%f",
qCDebug(shared, "ViewFrustum::matches()... result=%s", debug::valueOf(result));
qCDebug(shared, "%s -- compareTo._position=%f,%f,%f _position=%f,%f,%f",
(testMatches(compareTo._position,_position) ? "MATCHES " : "NO MATCH"),
(double)compareTo._position.x, (double)compareTo._position.y, (double)compareTo._position.z,
(double)_position.x, (double)_position.y, (double)_position.z);
qCDebug(octree, "%s -- compareTo._direction=%f,%f,%f _direction=%f,%f,%f",
qCDebug(shared, "%s -- compareTo._direction=%f,%f,%f _direction=%f,%f,%f",
(testMatches(compareTo._direction, _direction) ? "MATCHES " : "NO MATCH"),
(double)compareTo._direction.x, (double)compareTo._direction.y, (double)compareTo._direction.z,
(double)_direction.x, (double)_direction.y, (double)_direction.z );
qCDebug(octree, "%s -- compareTo._up=%f,%f,%f _up=%f,%f,%f",
qCDebug(shared, "%s -- compareTo._up=%f,%f,%f _up=%f,%f,%f",
(testMatches(compareTo._up, _up) ? "MATCHES " : "NO MATCH"),
(double)compareTo._up.x, (double)compareTo._up.y, (double)compareTo._up.z,
(double)_up.x, (double)_up.y, (double)_up.z );
qCDebug(octree, "%s -- compareTo._right=%f,%f,%f _right=%f,%f,%f",
qCDebug(shared, "%s -- compareTo._right=%f,%f,%f _right=%f,%f,%f",
(testMatches(compareTo._right, _right) ? "MATCHES " : "NO MATCH"),
(double)compareTo._right.x, (double)compareTo._right.y, (double)compareTo._right.z,
(double)_right.x, (double)_right.y, (double)_right.z );
qCDebug(octree, "%s -- compareTo._fieldOfView=%f _fieldOfView=%f",
qCDebug(shared, "%s -- compareTo._fieldOfView=%f _fieldOfView=%f",
(testMatches(compareTo._fieldOfView, _fieldOfView) ? "MATCHES " : "NO MATCH"),
(double)compareTo._fieldOfView, (double)_fieldOfView);
qCDebug(octree, "%s -- compareTo._aspectRatio=%f _aspectRatio=%f",
qCDebug(shared, "%s -- compareTo._aspectRatio=%f _aspectRatio=%f",
(testMatches(compareTo._aspectRatio, _aspectRatio) ? "MATCHES " : "NO MATCH"),
(double)compareTo._aspectRatio, (double)_aspectRatio);
qCDebug(octree, "%s -- compareTo._nearClip=%f _nearClip=%f",
qCDebug(shared, "%s -- compareTo._nearClip=%f _nearClip=%f",
(testMatches(compareTo._nearClip, _nearClip) ? "MATCHES " : "NO MATCH"),
(double)compareTo._nearClip, (double)_nearClip);
qCDebug(octree, "%s -- compareTo._farClip=%f _farClip=%f",
qCDebug(shared, "%s -- compareTo._farClip=%f _farClip=%f",
(testMatches(compareTo._farClip, _farClip) ? "MATCHES " : "NO MATCH"),
(double)compareTo._farClip, (double)_farClip);
qCDebug(octree, "%s -- compareTo._focalLength=%f _focalLength=%f",
qCDebug(shared, "%s -- compareTo._focalLength=%f _focalLength=%f",
(testMatches(compareTo._focalLength, _focalLength) ? "MATCHES " : "NO MATCH"),
(double)compareTo._focalLength, (double)_focalLength);
}
@ -342,34 +342,34 @@ bool ViewFrustum::isVerySimilar(const ViewFrustum& compareTo, bool debug) const
if (!result && debug) {
qCDebug(octree, "ViewFrustum::isVerySimilar()... result=%s\n", debug::valueOf(result));
qCDebug(octree, "%s -- compareTo._position=%f,%f,%f _position=%f,%f,%f",
qCDebug(shared, "ViewFrustum::isVerySimilar()... result=%s\n", debug::valueOf(result));
qCDebug(shared, "%s -- compareTo._position=%f,%f,%f _position=%f,%f,%f",
(testMatches(compareTo._position,_position, POSITION_SIMILAR_ENOUGH) ?
"IS SIMILAR ENOUGH " : "IS NOT SIMILAR ENOUGH"),
(double)compareTo._position.x, (double)compareTo._position.y, (double)compareTo._position.z,
(double)_position.x, (double)_position.y, (double)_position.z );
qCDebug(octree, "%s -- positionDistance=%f",
qCDebug(shared, "%s -- positionDistance=%f",
(testMatches(0,positionDistance, POSITION_SIMILAR_ENOUGH) ? "IS SIMILAR ENOUGH " : "IS NOT SIMILAR ENOUGH"),
(double)positionDistance);
qCDebug(octree, "%s -- angleOrientation=%f",
qCDebug(shared, "%s -- angleOrientation=%f",
(testMatches(0, angleOrientation, ORIENTATION_SIMILAR_ENOUGH) ? "IS SIMILAR ENOUGH " : "IS NOT SIMILAR ENOUGH"),
(double)angleOrientation);
qCDebug(octree, "%s -- compareTo._fieldOfView=%f _fieldOfView=%f",
qCDebug(shared, "%s -- compareTo._fieldOfView=%f _fieldOfView=%f",
(testMatches(compareTo._fieldOfView, _fieldOfView) ? "MATCHES " : "NO MATCH"),
(double)compareTo._fieldOfView, (double)_fieldOfView);
qCDebug(octree, "%s -- compareTo._aspectRatio=%f _aspectRatio=%f",
qCDebug(shared, "%s -- compareTo._aspectRatio=%f _aspectRatio=%f",
(testMatches(compareTo._aspectRatio, _aspectRatio) ? "MATCHES " : "NO MATCH"),
(double)compareTo._aspectRatio, (double)_aspectRatio);
qCDebug(octree, "%s -- compareTo._nearClip=%f _nearClip=%f",
qCDebug(shared, "%s -- compareTo._nearClip=%f _nearClip=%f",
(testMatches(compareTo._nearClip, _nearClip) ? "MATCHES " : "NO MATCH"),
(double)compareTo._nearClip, (double)_nearClip);
qCDebug(octree, "%s -- compareTo._farClip=%f _farClip=%f",
qCDebug(shared, "%s -- compareTo._farClip=%f _farClip=%f",
(testMatches(compareTo._farClip, _farClip) ? "MATCHES " : "NO MATCH"),
(double)compareTo._farClip, (double)_farClip);
qCDebug(octree, "%s -- compareTo._focalLength=%f _focalLength=%f",
qCDebug(shared, "%s -- compareTo._focalLength=%f _focalLength=%f",
(testMatches(compareTo._focalLength, _focalLength) ? "MATCHES " : "NO MATCH"),
(double)compareTo._focalLength, (double)_focalLength);
}
@ -394,7 +394,7 @@ void ViewFrustum::computeOffAxisFrustum(float& left, float& right, float& bottom
// find the minimum and maximum z values, which will be our near and far clip distances
nearValue = FLT_MAX;
farValue = -FLT_MAX;
for (int i = 0; i < 8; i++) {
for (int i = 0; i < NUM_FRUSTUM_CORNERS; i++) {
nearValue = min(nearValue, -_corners[i].z);
farValue = max(farValue, -_corners[i].z);
}
@ -427,17 +427,17 @@ void ViewFrustum::computeOffAxisFrustum(float& left, float& right, float& bottom
}
void ViewFrustum::printDebugDetails() const {
qCDebug(octree, "ViewFrustum::printDebugDetails()...");
qCDebug(octree, "_position=%f,%f,%f", (double)_position.x, (double)_position.y, (double)_position.z );
qCDebug(octree, "_direction=%f,%f,%f", (double)_direction.x, (double)_direction.y, (double)_direction.z );
qCDebug(octree, "_up=%f,%f,%f", (double)_up.x, (double)_up.y, (double)_up.z );
qCDebug(octree, "_right=%f,%f,%f", (double)_right.x, (double)_right.y, (double)_right.z );
qCDebug(octree, "_fieldOfView=%f", (double)_fieldOfView);
qCDebug(octree, "_aspectRatio=%f", (double)_aspectRatio);
qCDebug(octree, "_centerSphereRadius=%f", (double)_centerSphereRadius);
qCDebug(octree, "_nearClip=%f", (double)_nearClip);
qCDebug(octree, "_farClip=%f", (double)_farClip);
qCDebug(octree, "_focalLength=%f", (double)_focalLength);
qCDebug(shared, "ViewFrustum::printDebugDetails()...");
qCDebug(shared, "_position=%f,%f,%f", (double)_position.x, (double)_position.y, (double)_position.z );
qCDebug(shared, "_direction=%f,%f,%f", (double)_direction.x, (double)_direction.y, (double)_direction.z );
qCDebug(shared, "_up=%f,%f,%f", (double)_up.x, (double)_up.y, (double)_up.z );
qCDebug(shared, "_right=%f,%f,%f", (double)_right.x, (double)_right.y, (double)_right.z );
qCDebug(shared, "_fieldOfView=%f", (double)_fieldOfView);
qCDebug(shared, "_aspectRatio=%f", (double)_aspectRatio);
qCDebug(shared, "_centerSphereRadius=%f", (double)_centerSphereRadius);
qCDebug(shared, "_nearClip=%f", (double)_nearClip);
qCDebug(shared, "_farClip=%f", (double)_farClip);
qCDebug(shared, "_focalLength=%f", (double)_focalLength);
}
glm::vec2 ViewFrustum::projectPoint(glm::vec3 point, bool& pointInView) const {
@ -536,7 +536,7 @@ const int hullVertexLookup[MAX_POSSIBLE_COMBINATIONS][MAX_PROJECTED_POLYGON_VERT
{6, TOP_RIGHT_NEAR, TOP_RIGHT_FAR, BOTTOM_RIGHT_FAR, BOTTOM_LEFT_FAR, BOTTOM_LEFT_NEAR, TOP_LEFT_NEAR}, // back, top, left
};
OctreeProjectedPolygon ViewFrustum::getProjectedPolygon(const AACube& box) const {
CubeProjectedPolygon ViewFrustum::getProjectedPolygon(const AACube& box) const {
const glm::vec3& bottomNearRight = box.getCorner();
glm::vec3 topFarLeft = box.calcTopFarLeft();
@ -549,7 +549,7 @@ OctreeProjectedPolygon ViewFrustum::getProjectedPolygon(const AACube& box) const
int vertexCount = hullVertexLookup[lookUp][0]; //look up number of vertices
OctreeProjectedPolygon projectedPolygon(vertexCount);
CubeProjectedPolygon projectedPolygon(vertexCount);
bool pointInView = true;
bool allPointsInView = false; // assume the best, but wait till we know we have a vertex
@ -630,7 +630,7 @@ void ViewFrustum::getFurthestPointFromCamera(const AACube& box, glm::vec3& furth
}
}
const ViewFrustum::Corners ViewFrustum::getCorners(const float& depth) {
const ViewFrustum::Corners ViewFrustum::getCorners(const float& depth) const {
glm::vec3 normal = glm::normalize(_direction);
auto getCorner = [&](enum::BoxVertex nearCorner, enum::BoxVertex farCorner) {
@ -662,51 +662,10 @@ void ViewFrustum::evalViewTransform(Transform& view) const {
view.setRotation(getOrientation());
}
float ViewFrustum::calculateRenderAccuracy(const AABox& bounds, float octreeSizeScale, int boundaryLevelAdjust) const {
float distanceToCamera = glm::length(bounds.calcCenter() - getPosition());
float largestDimension = bounds.getLargestDimension();
const float maxScale = (float)TREE_SCALE;
float visibleDistanceAtMaxScale = boundaryDistanceForRenderLevel(boundaryLevelAdjust, octreeSizeScale) / OCTREE_TO_MESH_RATIO;
static std::once_flag once;
static QMap<float, float> shouldRenderTable;
std::call_once(once, [&] {
float SMALLEST_SCALE_IN_TABLE = 0.001f; // 1mm is plenty small
float scale = maxScale;
float factor = 1.0f;
while (scale > SMALLEST_SCALE_IN_TABLE) {
scale /= 2.0f;
factor /= 2.0f;
shouldRenderTable[scale] = factor;
}
});
float closestScale = maxScale;
float visibleDistanceAtClosestScale = visibleDistanceAtMaxScale;
QMap<float, float>::const_iterator lowerBound = shouldRenderTable.lowerBound(largestDimension);
if (lowerBound != shouldRenderTable.constEnd()) {
closestScale = lowerBound.key();
visibleDistanceAtClosestScale = visibleDistanceAtMaxScale * lowerBound.value();
void ViewFrustum::invalidate() {
// these setting should make nearly all intersection tests fail
for (int i = 0; i < NUM_FRUSTUM_PLANES; ++i) {
_planes[i].invalidate();
}
if (closestScale < largestDimension) {
visibleDistanceAtClosestScale *= 2.0f;
}
// FIXME - for now, it's either visible or not visible. We want to adjust this to eventually return
// a floating point for objects that have small angular size to indicate that they may be rendered
// with lower preciscion
return (distanceToCamera <= visibleDistanceAtClosestScale) ? 1.0f : 0.0f;
}
float boundaryDistanceForRenderLevel(unsigned int renderLevel, float voxelSizeScale) {
return voxelSizeScale / powf(2, renderLevel);
}
float ViewFrustum::getAccuracyAngle(float octreeSizeScale, int boundaryLevelAdjust) const {
const float maxScale = (float)TREE_SCALE;
float visibleDistanceAtMaxScale = boundaryDistanceForRenderLevel(boundaryLevelAdjust, octreeSizeScale) / OCTREE_TO_MESH_RATIO;
return atan(maxScale / visibleDistanceAtMaxScale);
_centerSphereRadius = -1.0e6f; // -10^6 should be negative enough
}

View file

@ -1,6 +1,6 @@
//
// ViewFrustum.h
// libraries/octree/src
// libraries/shared/src
//
// Created by Brad Hefta-Gaub on 04/11/13.
// Copyright 2013 High Fidelity, Inc.
@ -17,21 +17,21 @@
#include <glm/glm.hpp>
#include <glm/gtc/quaternion.hpp>
#include <GLMHelpers.h>
#include <RegisteredMetaTypes.h>
#include "Transform.h"
#include "AABox.h"
#include "AACube.h"
#include "CubeProjectedPolygon.h"
#include "Plane.h"
#include "OctreeConstants.h"
#include "OctreeProjectedPolygon.h"
#include "RegisteredMetaTypes.h"
#include "Transform.h"
const int NUM_FRUSTUM_CORNERS = 8;
const int NUM_FRUSTUM_PLANES = 6;
const float DEFAULT_CENTER_SPHERE_RADIUS = 3.0f;
const float DEFAULT_FIELD_OF_VIEW_DEGREES = 45.0f;
const float DEFAULT_ASPECT_RATIO = 16.0f/9.0f;
const float DEFAULT_NEAR_CLIP = 0.08f;
const float DEFAULT_FAR_CLIP = (float)HALF_TREE_SCALE;
const float DEFAULT_FAR_CLIP = 16384.0f;
// the "ViewFrustum" has a "keyhole" shape: a regular frustum for stuff that is "visible" with
// a central sphere for stuff that is nearby (for physics simulation).
@ -74,7 +74,7 @@ public:
glm::vec3 bottomRight;
// Get the corners depth units from frustum position, along frustum orientation
};
const Corners getCorners(const float& depth);
const Corners getCorners(const float& depth) const;
// getters for corners
const glm::vec3& getFarTopLeft() const { return _cornersWorld[TOP_LEFT_FAR]; }
@ -123,7 +123,7 @@ public:
void printDebugDetails() const;
glm::vec2 projectPoint(glm::vec3 point, bool& pointInView) const;
OctreeProjectedPolygon getProjectedPolygon(const AACube& box) const;
CubeProjectedPolygon getProjectedPolygon(const AACube& box) const;
void getFurthestPointFromCamera(const AACube& box, glm::vec3& furthestPoint) const;
float distanceToCamera(const glm::vec3& point) const;
@ -131,44 +131,37 @@ public:
void evalProjectionMatrix(glm::mat4& proj) const;
void evalViewTransform(Transform& view) const;
/// renderAccuracy represents a floating point "visibility" of an object based on it's view from the camera. At a simple
/// level it returns 0.0f for things that are so small for the current settings that they could not be visible.
float calculateRenderAccuracy(const AABox& bounds, float octreeSizeScale = DEFAULT_OCTREE_SIZE_SCALE,
int boundaryLevelAdjust = 0) const;
float getAccuracyAngle(float octreeSizeScale = DEFAULT_OCTREE_SIZE_SCALE, int boundaryLevelAdjust = 0) const;
enum PlaneIndex { TOP_PLANE = 0, BOTTOM_PLANE, LEFT_PLANE, RIGHT_PLANE, NEAR_PLANE, FAR_PLANE, NUM_PLANES };
const ::Plane* getPlanes() const { return _planes; }
private:
// camera location/orientation attributes
glm::vec3 _position; // the position in world-frame
glm::quat _orientation;
glm::mat4 _view;
// Lens attributes
void invalidate(); // causes all reasonable intersection tests to fail
private:
glm::mat4 _view;
glm::mat4 _projection;
// calculated for orientation
::Plane _planes[NUM_FRUSTUM_PLANES]; // plane normals point inside frustum
glm::vec3 _position; // position in world-frame
glm::quat _orientation; // orientation in world-frame
// calculated from orientation
glm::vec3 _direction = IDENTITY_FRONT;
glm::vec3 _up = IDENTITY_UP;
glm::vec3 _right = IDENTITY_RIGHT;
// calculated from projection
glm::vec4 _corners[NUM_FRUSTUM_CORNERS];
glm::vec3 _cornersWorld[NUM_FRUSTUM_CORNERS];
float _centerSphereRadius = DEFAULT_CENTER_SPHERE_RADIUS;
float _width { 1.0f };
float _height { 1.0f };
float _aspectRatio { 1.0f };
float _focalLength { 0.25f };
float _fieldOfView { DEFAULT_FIELD_OF_VIEW_DEGREES };
// Calculated values
glm::mat4 _inverseProjection;
float _width = 1.0f;
float _height = 1.0f;
float _aspectRatio = 1.0f;
float _nearClip = DEFAULT_NEAR_CLIP;
float _farClip = DEFAULT_FAR_CLIP;
float _focalLength = 0.25f;
float _fieldOfView = DEFAULT_FIELD_OF_VIEW_DEGREES;
glm::vec4 _corners[8];
glm::vec3 _cornersWorld[8];
::Plane _planes[6]; // plane normals point inside frustum
float _nearClip { DEFAULT_NEAR_CLIP };
float _farClip { DEFAULT_FAR_CLIP };
const char* debugPlaneName (int plane) const;
@ -177,6 +170,4 @@ private:
};
using ViewFrustumPointer = std::shared_ptr<ViewFrustum>;
float boundaryDistanceForRenderLevel(unsigned int renderLevel, float voxelSizeScale);
#endif // hifi_ViewFrustum_h