Merge pull request #7126 from AndrewMeadows/cleanup

cleanup ViewFrustum method names
This commit is contained in:
Brad Hefta-Gaub 2016-02-25 16:12:25 -08:00
commit 202a456e1a
11 changed files with 124 additions and 135 deletions

View file

@ -425,11 +425,11 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
_maxOctreePPS(maxOctreePacketsPerSecond.get()), _maxOctreePPS(maxOctreePacketsPerSecond.get()),
_lastFaceTrackerUpdate(0) _lastFaceTrackerUpdate(0)
{ {
// FIXME this may be excessivly conservative. On the other hand // FIXME this may be excessivly conservative. On the other hand
// maybe I'm used to having an 8-core machine // maybe I'm used to having an 8-core machine
// Perhaps find the ideal thread count and subtract 2 or 3 // Perhaps find the ideal thread count and subtract 2 or 3
// (main thread, present thread, random OS load) // (main thread, present thread, random OS load)
// More threads == faster concurrent loads, but also more concurrent // More threads == faster concurrent loads, but also more concurrent
// load on the GPU until we can serialize GPU transfers (off the main thread) // load on the GPU until we can serialize GPU transfers (off the main thread)
QThreadPool::globalInstance()->setMaxThreadCount(2); QThreadPool::globalInstance()->setMaxThreadCount(2);
thread()->setPriority(QThread::HighPriority); thread()->setPriority(QThread::HighPriority);
@ -559,7 +559,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
auto discoverabilityManager = DependencyManager::get<DiscoverabilityManager>(); auto discoverabilityManager = DependencyManager::get<DiscoverabilityManager>();
connect(&locationUpdateTimer, &QTimer::timeout, discoverabilityManager.data(), &DiscoverabilityManager::updateLocation); connect(&locationUpdateTimer, &QTimer::timeout, discoverabilityManager.data(), &DiscoverabilityManager::updateLocation);
connect(&locationUpdateTimer, &QTimer::timeout, connect(&locationUpdateTimer, &QTimer::timeout,
DependencyManager::get<AddressManager>().data(), &AddressManager::storeCurrentAddress); DependencyManager::get<AddressManager>().data(), &AddressManager::storeCurrentAddress);
locationUpdateTimer.start(DATA_SERVER_LOCATION_CHANGE_UPDATE_MSECS); locationUpdateTimer.start(DATA_SERVER_LOCATION_CHANGE_UPDATE_MSECS);
@ -604,7 +604,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
connect(addressManager.data(), &AddressManager::hostChanged, this, &Application::updateWindowTitle); connect(addressManager.data(), &AddressManager::hostChanged, this, &Application::updateWindowTitle);
connect(this, &QCoreApplication::aboutToQuit, addressManager.data(), &AddressManager::storeCurrentAddress); connect(this, &QCoreApplication::aboutToQuit, addressManager.data(), &AddressManager::storeCurrentAddress);
// Save avatar location immediately after a teleport. // Save avatar location immediately after a teleport.
connect(getMyAvatar(), &MyAvatar::positionGoneTo, connect(getMyAvatar(), &MyAvatar::positionGoneTo,
DependencyManager::get<AddressManager>().data(), &AddressManager::storeCurrentAddress); DependencyManager::get<AddressManager>().data(), &AddressManager::storeCurrentAddress);
@ -625,7 +625,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
getEntities()->reloadEntityScripts(); getEntities()->reloadEntityScripts();
}, Qt::QueuedConnection); }, Qt::QueuedConnection);
connect(scriptEngines, &ScriptEngines::scriptLoadError, connect(scriptEngines, &ScriptEngines::scriptLoadError,
scriptEngines, [](const QString& filename, const QString& error){ scriptEngines, [](const QString& filename, const QString& error){
OffscreenUi::warning(nullptr, "Error Loading Script", filename + " failed to load."); OffscreenUi::warning(nullptr, "Error Loading Script", filename + " failed to load.");
}, Qt::QueuedConnection); }, Qt::QueuedConnection);
@ -972,7 +972,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer) :
disconnect(_idleTimer); disconnect(_idleTimer);
}); });
// Setting the interval to zero forces this to get called whenever there are no messages // Setting the interval to zero forces this to get called whenever there are no messages
// in the queue, which can be pretty damn frequent. Hence the idle function has a bunch // in the queue, which can be pretty damn frequent. Hence the idle function has a bunch
// of logic to abort early if it's being called too often. // of logic to abort early if it's being called too often.
_idleTimer->start(0); _idleTimer->start(0);
} }
@ -1020,7 +1020,7 @@ void Application::cleanupBeforeQuit() {
getEntities()->shutdown(); // tell the entities system we're shutting down, so it will stop running scripts getEntities()->shutdown(); // tell the entities system we're shutting down, so it will stop running scripts
DependencyManager::get<ScriptEngines>()->saveScripts(); DependencyManager::get<ScriptEngines>()->saveScripts();
DependencyManager::get<ScriptEngines>()->shutdownScripting(); // stop all currently running global scripts DependencyManager::get<ScriptEngines>()->shutdownScripting(); // stop all currently running global scripts
DependencyManager::destroy<ScriptEngines>(); DependencyManager::destroy<ScriptEngines>();
// first stop all timers directly or by invokeMethod // first stop all timers directly or by invokeMethod
// depending on what thread they run in // depending on what thread they run in
@ -1209,10 +1209,10 @@ void Application::initializeUi() {
setupPreferences(); setupPreferences();
// For some reason there is already an "Application" object in the QML context, // For some reason there is already an "Application" object in the QML context,
// though I can't find it. Hence, "ApplicationInterface" // though I can't find it. Hence, "ApplicationInterface"
rootContext->setContextProperty("SnapshotUploader", new SnapshotUploader()); rootContext->setContextProperty("SnapshotUploader", new SnapshotUploader());
rootContext->setContextProperty("ApplicationInterface", this); rootContext->setContextProperty("ApplicationInterface", this);
rootContext->setContextProperty("AnimationCache", DependencyManager::get<AnimationCache>().data()); rootContext->setContextProperty("AnimationCache", DependencyManager::get<AnimationCache>().data());
rootContext->setContextProperty("Audio", &AudioScriptingInterface::getInstance()); rootContext->setContextProperty("Audio", &AudioScriptingInterface::getInstance());
rootContext->setContextProperty("Controller", DependencyManager::get<controller::ScriptingInterface>().data()); rootContext->setContextProperty("Controller", DependencyManager::get<controller::ScriptingInterface>().data());
@ -2432,7 +2432,7 @@ void Application::idle(uint64_t now) {
if (_aboutToQuit) { if (_aboutToQuit) {
return; // bail early, nothing to do here. return; // bail early, nothing to do here.
} }
auto displayPlugin = getActiveDisplayPlugin(); auto displayPlugin = getActiveDisplayPlugin();
// depending on whether we're throttling or not. // depending on whether we're throttling or not.
// Once rendering is off on another thread we should be able to have Application::idle run at start(0) in // Once rendering is off on another thread we should be able to have Application::idle run at start(0) in
@ -2456,7 +2456,7 @@ void Application::idle(uint64_t now) {
// Nested ifs are for clarity in the logic. Don't collapse them into a giant single if. // Nested ifs are for clarity in the logic. Don't collapse them into a giant single if.
// Don't saturate the main thread with rendering, no paint calls until the last one is complete // Don't saturate the main thread with rendering, no paint calls until the last one is complete
if (!_pendingPaint) { if (!_pendingPaint) {
// Also no paint calls until the display plugin has increased by at least one frame // Also no paint calls until the display plugin has increased by at least one frame
// (don't render at 90fps if the display plugin only goes at 60) // (don't render at 90fps if the display plugin only goes at 60)
if (_renderedFrameIndex == INVALID_FRAME || presentCount > _renderedFrameIndex) { if (_renderedFrameIndex == INVALID_FRAME || presentCount > _renderedFrameIndex) {
// Record what present frame we're on // Record what present frame we're on
@ -2466,14 +2466,14 @@ void Application::idle(uint64_t now) {
// But when we DO request a paint, get to it as soon as possible: high priority // But when we DO request a paint, get to it as soon as possible: high priority
postEvent(this, new QEvent(static_cast<QEvent::Type>(Paint)), Qt::HighEventPriority); postEvent(this, new QEvent(static_cast<QEvent::Type>(Paint)), Qt::HighEventPriority);
} }
} }
// For the rest of idle, we want to cap at the max sim rate, so we might not call // For the rest of idle, we want to cap at the max sim rate, so we might not call
// the remaining idle work every paint frame, or vice versa // the remaining idle work every paint frame, or vice versa
// In theory this means we could call idle processing more often than painting, // In theory this means we could call idle processing more often than painting,
// but in practice, when the paintGL calls aren't keeping up, there's no room left // but in practice, when the paintGL calls aren't keeping up, there's no room left
// in the main thread to call idle more often than paint. // in the main thread to call idle more often than paint.
// This check is mostly to keep idle from burning up CPU cycles by running at // This check is mostly to keep idle from burning up CPU cycles by running at
// hundreds of idles per second when the rendering is that fast // hundreds of idles per second when the rendering is that fast
if ((timeSinceLastUpdateUs / USECS_PER_MSEC) < CAPPED_SIM_FRAME_PERIOD_MS) { if ((timeSinceLastUpdateUs / USECS_PER_MSEC) < CAPPED_SIM_FRAME_PERIOD_MS) {
// No paint this round, but might be time for a new idle, otherwise return // No paint this round, but might be time for a new idle, otherwise return
@ -3420,7 +3420,7 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node
rootDetails.y * TREE_SCALE, rootDetails.y * TREE_SCALE,
rootDetails.z * TREE_SCALE) - glm::vec3(HALF_TREE_SCALE), rootDetails.z * TREE_SCALE) - glm::vec3(HALF_TREE_SCALE),
rootDetails.s * TREE_SCALE); rootDetails.s * TREE_SCALE);
ViewFrustum::location serverFrustumLocation = _viewFrustum.cubeInFrustum(serverBounds); ViewFrustum::location serverFrustumLocation = _viewFrustum.computeCubeViewLocation(serverBounds);
if (serverFrustumLocation != ViewFrustum::OUTSIDE) { if (serverFrustumLocation != ViewFrustum::OUTSIDE) {
inViewServers++; inViewServers++;
@ -3488,7 +3488,7 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node
rootDetails.s * TREE_SCALE); rootDetails.s * TREE_SCALE);
ViewFrustum::location serverFrustumLocation = _viewFrustum.cubeInFrustum(serverBounds); ViewFrustum::location serverFrustumLocation = _viewFrustum.computeCubeViewLocation(serverBounds);
if (serverFrustumLocation != ViewFrustum::OUTSIDE) { if (serverFrustumLocation != ViewFrustum::OUTSIDE) {
inView = true; inView = true;
} else { } else {
@ -4702,7 +4702,7 @@ static void addDisplayPluginToMenu(DisplayPluginPointer displayPlugin, bool acti
groupingMenu = "Developer"; groupingMenu = "Developer";
break; break;
default: default:
groupingMenu = "Standard"; groupingMenu = "Standard";
break; break;
} }

View file

@ -136,7 +136,7 @@ glm::quat Avatar::getWorldAlignedOrientation () const {
AABox Avatar::getBounds() const { AABox Avatar::getBounds() const {
// Our skeleton models are rigged, and this method call safely produces the static bounds of the model. // Our skeleton models are rigged, and this method call safely produces the static bounds of the model.
// Except, that getPartBounds produces an infinite, uncentered bounding box when the model is not yet parsed, // Except, that getPartBounds produces an infinite, uncentered bounding box when the model is not yet parsed,
// and we want a centered one. NOTE: There is code that may never try to render, and thus never load and get the // and we want a centered one. NOTE: There is code that may never try to render, and thus never load and get the
// real model bounds, if this is unrealistically small. // real model bounds, if this is unrealistically small.
if (!_skeletonModel.isRenderable()) { if (!_skeletonModel.isRenderable()) {
@ -188,7 +188,7 @@ void Avatar::simulate(float deltaTime) {
// simple frustum check // simple frustum check
float boundingRadius = getBoundingRadius(); float boundingRadius = getBoundingRadius();
bool inViewFrustum = qApp->getViewFrustum()->sphereInFrustum(getPosition(), boundingRadius) != bool inViewFrustum = qApp->getViewFrustum()->computeSphereViewLocation(getPosition(), boundingRadius) !=
ViewFrustum::OUTSIDE; ViewFrustum::OUTSIDE;
{ {
@ -401,7 +401,7 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) {
frustum = qApp->getDisplayViewFrustum(); frustum = qApp->getDisplayViewFrustum();
} }
if (frustum->sphereInFrustum(getPosition(), boundingRadius) == ViewFrustum::OUTSIDE) { if (frustum->computeSphereViewLocation(getPosition(), boundingRadius) == ViewFrustum::OUTSIDE) {
endRender(); endRender();
return; return;
} }
@ -517,7 +517,7 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) {
auto& frustum = *renderArgs->_viewFrustum; auto& frustum = *renderArgs->_viewFrustum;
auto textPosition = getDisplayNamePosition(); auto textPosition = getDisplayNamePosition();
if (frustum.pointInFrustum(textPosition, true) == ViewFrustum::INSIDE) { if (frustum.computePointFrustumLocation(textPosition) == ViewFrustum::INSIDE) {
renderDisplayName(batch, frustum, textPosition); renderDisplayName(batch, frustum, textPosition);
} }
} }
@ -671,7 +671,7 @@ glm::vec3 Avatar::getDisplayNamePosition() const {
} }
Transform Avatar::calculateDisplayNameTransform(const ViewFrustum& frustum, const glm::vec3& textPosition) const { Transform Avatar::calculateDisplayNameTransform(const ViewFrustum& frustum, const glm::vec3& textPosition) const {
Q_ASSERT_X(frustum.pointInFrustum(textPosition, true) == ViewFrustum::INSIDE, Q_ASSERT_X(frustum.computePointFrustumLocation(textPosition) == ViewFrustum::INSIDE,
"Avatar::calculateDisplayNameTransform", "Text not in viewfrustum."); "Avatar::calculateDisplayNameTransform", "Text not in viewfrustum.");
glm::vec3 toFrustum = frustum.getPosition() - textPosition; glm::vec3 toFrustum = frustum.getPosition() - textPosition;

View file

@ -85,7 +85,7 @@ void EntityTreeElement::initializeExtraEncodeData(EncodeBitstreamParams& params)
forEachEntity([&](EntityItemPointer entity) { forEachEntity([&](EntityItemPointer entity) {
entityTreeElementExtraEncodeData->entities.insert(entity->getEntityItemID(), entity->getEntityProperties(params)); entityTreeElementExtraEncodeData->entities.insert(entity->getEntityItemID(), entity->getEntityProperties(params));
}); });
// TODO: some of these inserts might be redundant!!! // TODO: some of these inserts might be redundant!!!
extraEncodeData->insert(this, entityTreeElementExtraEncodeData); extraEncodeData->insert(this, entityTreeElementExtraEncodeData);
} }
@ -96,39 +96,39 @@ bool EntityTreeElement::shouldIncludeChildData(int childIndex, EncodeBitstreamPa
assert(extraEncodeData); // EntityTrees always require extra encode data on their encoding passes assert(extraEncodeData); // EntityTrees always require extra encode data on their encoding passes
if (extraEncodeData->contains(this)) { if (extraEncodeData->contains(this)) {
EntityTreeElementExtraEncodeData* entityTreeElementExtraEncodeData EntityTreeElementExtraEncodeData* entityTreeElementExtraEncodeData
= static_cast<EntityTreeElementExtraEncodeData*>(extraEncodeData->value(this)); = static_cast<EntityTreeElementExtraEncodeData*>(extraEncodeData->value(this));
bool childCompleted = entityTreeElementExtraEncodeData->childCompleted[childIndex]; bool childCompleted = entityTreeElementExtraEncodeData->childCompleted[childIndex];
// If we haven't completely sent the child yet, then we should include it // If we haven't completely sent the child yet, then we should include it
return !childCompleted; return !childCompleted;
} }
// I'm not sure this should ever happen, since we should have the extra encode data if we're considering // I'm not sure this should ever happen, since we should have the extra encode data if we're considering
// the child data for this element // the child data for this element
assert(false); assert(false);
return false; return false;
} }
bool EntityTreeElement::shouldRecurseChildTree(int childIndex, EncodeBitstreamParams& params) const { bool EntityTreeElement::shouldRecurseChildTree(int childIndex, EncodeBitstreamParams& params) const {
EntityTreeElementPointer childElement = getChildAtIndex(childIndex); EntityTreeElementPointer childElement = getChildAtIndex(childIndex);
if (childElement->alreadyFullyEncoded(params)) { if (childElement->alreadyFullyEncoded(params)) {
return false; return false;
} }
return true; // if we don't know otherwise than recurse! return true; // if we don't know otherwise than recurse!
} }
bool EntityTreeElement::alreadyFullyEncoded(EncodeBitstreamParams& params) const { bool EntityTreeElement::alreadyFullyEncoded(EncodeBitstreamParams& params) const {
OctreeElementExtraEncodeData* extraEncodeData = params.extraEncodeData; OctreeElementExtraEncodeData* extraEncodeData = params.extraEncodeData;
assert(extraEncodeData); // EntityTrees always require extra encode data on their encoding passes assert(extraEncodeData); // EntityTrees always require extra encode data on their encoding passes
if (extraEncodeData->contains(this)) { if (extraEncodeData->contains(this)) {
EntityTreeElementExtraEncodeData* entityTreeElementExtraEncodeData EntityTreeElementExtraEncodeData* entityTreeElementExtraEncodeData
= static_cast<EntityTreeElementExtraEncodeData*>(extraEncodeData->value(this)); = static_cast<EntityTreeElementExtraEncodeData*>(extraEncodeData->value(this));
// If we know that ALL subtrees below us have already been recursed, then we don't // If we know that ALL subtrees below us have already been recursed, then we don't
// need to recurse this child. // need to recurse this child.
return entityTreeElementExtraEncodeData->subtreeCompleted; return entityTreeElementExtraEncodeData->subtreeCompleted;
} }
@ -139,7 +139,7 @@ void EntityTreeElement::updateEncodedData(int childIndex, AppendState childAppen
OctreeElementExtraEncodeData* extraEncodeData = params.extraEncodeData; OctreeElementExtraEncodeData* extraEncodeData = params.extraEncodeData;
assert(extraEncodeData); // EntityTrees always require extra encode data on their encoding passes assert(extraEncodeData); // EntityTrees always require extra encode data on their encoding passes
if (extraEncodeData->contains(this)) { if (extraEncodeData->contains(this)) {
EntityTreeElementExtraEncodeData* entityTreeElementExtraEncodeData EntityTreeElementExtraEncodeData* entityTreeElementExtraEncodeData
= static_cast<EntityTreeElementExtraEncodeData*>(extraEncodeData->value(this)); = static_cast<EntityTreeElementExtraEncodeData*>(extraEncodeData->value(this));
if (childAppendState == OctreeElement::COMPLETED) { if (childAppendState == OctreeElement::COMPLETED) {
@ -155,7 +155,7 @@ void EntityTreeElement::updateEncodedData(int childIndex, AppendState childAppen
void EntityTreeElement::elementEncodeComplete(EncodeBitstreamParams& params) const { void EntityTreeElement::elementEncodeComplete(EncodeBitstreamParams& params) const {
const bool wantDebug = false; const bool wantDebug = false;
if (wantDebug) { if (wantDebug) {
qCDebug(entities) << "EntityTreeElement::elementEncodeComplete() element:" << _cube; qCDebug(entities) << "EntityTreeElement::elementEncodeComplete() element:" << _cube;
} }
@ -188,7 +188,7 @@ void EntityTreeElement::elementEncodeComplete(EncodeBitstreamParams& params) con
// If we've encoding this element before... but we're coming back a second time in an attempt to // If we've encoding this element before... but we're coming back a second time in an attempt to
// encoud our parent... this might happen. // encoud our parent... this might happen.
if (extraEncodeData->contains(childElement.get())) { if (extraEncodeData->contains(childElement.get())) {
EntityTreeElementExtraEncodeData* childExtraEncodeData EntityTreeElementExtraEncodeData* childExtraEncodeData
= static_cast<EntityTreeElementExtraEncodeData*>(extraEncodeData->value(childElement.get())); = static_cast<EntityTreeElementExtraEncodeData*>(extraEncodeData->value(childElement.get()));
if (wantDebug) { if (wantDebug) {
@ -197,7 +197,7 @@ void EntityTreeElement::elementEncodeComplete(EncodeBitstreamParams& params) con
qCDebug(entities) << " childExtraEncodeData->elementCompleted:" << childExtraEncodeData->elementCompleted; qCDebug(entities) << " childExtraEncodeData->elementCompleted:" << childExtraEncodeData->elementCompleted;
qCDebug(entities) << " childExtraEncodeData->subtreeCompleted:" << childExtraEncodeData->subtreeCompleted; qCDebug(entities) << " childExtraEncodeData->subtreeCompleted:" << childExtraEncodeData->subtreeCompleted;
} }
if (childElement->isLeaf() && childExtraEncodeData->elementCompleted) { if (childElement->isLeaf() && childExtraEncodeData->elementCompleted) {
if (wantDebug) { if (wantDebug) {
qCDebug(entities) << " CHILD IS LEAF -- AND CHILD ELEMENT DATA COMPLETED!!!"; qCDebug(entities) << " CHILD IS LEAF -- AND CHILD ELEMENT DATA COMPLETED!!!";
@ -217,24 +217,24 @@ void EntityTreeElement::elementEncodeComplete(EncodeBitstreamParams& params) con
qCDebug(entities) << " WAS elementCompleted:" << thisExtraEncodeData->elementCompleted; qCDebug(entities) << " WAS elementCompleted:" << thisExtraEncodeData->elementCompleted;
qCDebug(entities) << " WAS subtreeCompleted:" << thisExtraEncodeData->subtreeCompleted; qCDebug(entities) << " WAS subtreeCompleted:" << thisExtraEncodeData->subtreeCompleted;
} }
thisExtraEncodeData->subtreeCompleted = !someChildTreeNotComplete; thisExtraEncodeData->subtreeCompleted = !someChildTreeNotComplete;
if (wantDebug) { if (wantDebug) {
qCDebug(entities) << " NOW elementCompleted:" << thisExtraEncodeData->elementCompleted; qCDebug(entities) << " NOW elementCompleted:" << thisExtraEncodeData->elementCompleted;
qCDebug(entities) << " NOW subtreeCompleted:" << thisExtraEncodeData->subtreeCompleted; qCDebug(entities) << " NOW subtreeCompleted:" << thisExtraEncodeData->subtreeCompleted;
if (thisExtraEncodeData->subtreeCompleted) { if (thisExtraEncodeData->subtreeCompleted) {
qCDebug(entities) << " YEAH!!!!! >>>>>>>>>>>>>> NOW subtreeCompleted:" << thisExtraEncodeData->subtreeCompleted; qCDebug(entities) << " YEAH!!!!! >>>>>>>>>>>>>> NOW subtreeCompleted:" << thisExtraEncodeData->subtreeCompleted;
} }
} }
} }
OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData* packetData, OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData* packetData,
EncodeBitstreamParams& params) const { EncodeBitstreamParams& params) const {
OctreeElement::AppendState appendElementState = OctreeElement::COMPLETED; // assume the best... OctreeElement::AppendState appendElementState = OctreeElement::COMPLETED; // assume the best...
// first, check the params.extraEncodeData to see if there's any partial re-encode data for this element // first, check the params.extraEncodeData to see if there's any partial re-encode data for this element
OctreeElementExtraEncodeData* extraEncodeData = params.extraEncodeData; OctreeElementExtraEncodeData* extraEncodeData = params.extraEncodeData;
EntityTreeElementExtraEncodeData* entityTreeElementExtraEncodeData = NULL; EntityTreeElementExtraEncodeData* entityTreeElementExtraEncodeData = NULL;
@ -280,7 +280,7 @@ OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData
QVector<uint16_t> indexesOfEntitiesToInclude; QVector<uint16_t> indexesOfEntitiesToInclude;
// It's possible that our element has been previous completed. In this case we'll simply not include any of our // It's possible that our element has been previous completed. In this case we'll simply not include any of our
// entities for encoding. This is needed because we encode the element data at the "parent" level, and so we // entities for encoding. This is needed because we encode the element data at the "parent" level, and so we
// need to handle the case where our sibling elements need encoding but we don't. // need to handle the case where our sibling elements need encoding but we don't.
if (!entityTreeElementExtraEncodeData->elementCompleted) { if (!entityTreeElementExtraEncodeData->elementCompleted) {
for (uint16_t i = 0; i < _entityItems.size(); i++) { for (uint16_t i = 0; i < _entityItems.size(); i++) {
@ -304,7 +304,7 @@ OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData
// frustum culling on rendering. // frustum culling on rendering.
bool success; bool success;
AACube entityCube = entity->getQueryAACube(success); AACube entityCube = entity->getQueryAACube(success);
if (!success || params.viewFrustum->cubeInFrustum(entityCube) == ViewFrustum::OUTSIDE) { if (!success || params.viewFrustum->computeCubeViewLocation(entityCube) == ViewFrustum::OUTSIDE) {
includeThisEntity = false; // out of view, don't include it includeThisEntity = false; // out of view, don't include it
} }
@ -397,7 +397,7 @@ OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData
// this octree element. // this octree element.
if (extraEncodeData && entityTreeElementExtraEncodeData) { if (extraEncodeData && entityTreeElementExtraEncodeData) {
// After processing, if we are PARTIAL or COMPLETED then we need to re-include our extra data. // After processing, if we are PARTIAL or COMPLETED then we need to re-include our extra data.
// Only our parent can remove our extra data in these cases and only after it knows that all of its // Only our parent can remove our extra data in these cases and only after it knows that all of its
// children have been encoded. // children have been encoded.
// If we weren't able to encode ANY data about ourselves, then we go ahead and remove our element data // If we weren't able to encode ANY data about ourselves, then we go ahead and remove our element data
@ -412,7 +412,7 @@ OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData
extraEncodeData->insert(this, entityTreeElementExtraEncodeData); extraEncodeData->insert(this, entityTreeElementExtraEncodeData);
} }
} else { } else {
// If we weren't previously completed, check to see if we are // If we weren't previously completed, check to see if we are
if (!entityTreeElementExtraEncodeData->elementCompleted) { if (!entityTreeElementExtraEncodeData->elementCompleted) {
// If all of our items have been encoded, then we are complete as an element. // If all of our items have been encoded, then we are complete as an element.
@ -426,9 +426,9 @@ OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData
} }
} }
// Determine if no entities at all were able to fit // Determine if no entities at all were able to fit
bool noEntitiesFit = (numberOfEntities > 0 && actualNumberOfEntities == 0); bool noEntitiesFit = (numberOfEntities > 0 && actualNumberOfEntities == 0);
// If we wrote fewer entities than we expected, update the number of entities in our packet // If we wrote fewer entities than we expected, update the number of entities in our packet
bool successUpdateEntityCount = true; bool successUpdateEntityCount = true;
if (numberOfEntities != actualNumberOfEntities) { if (numberOfEntities != actualNumberOfEntities) {
@ -504,7 +504,7 @@ bool EntityTreeElement::bestFitBounds(const glm::vec3& minPoint, const glm::vec3
glm::vec3 clampedMax = glm::clamp(maxPoint, (float)-HALF_TREE_SCALE, (float)HALF_TREE_SCALE); glm::vec3 clampedMax = glm::clamp(maxPoint, (float)-HALF_TREE_SCALE, (float)HALF_TREE_SCALE);
if (_cube.contains(clampedMin) && _cube.contains(clampedMax)) { if (_cube.contains(clampedMin) && _cube.contains(clampedMax)) {
// If our child would be smaller than our smallest reasonable element, then we are the best fit. // If our child would be smaller than our smallest reasonable element, then we are the best fit.
float childScale = _cube.getScale() / 2.0f; float childScale = _cube.getScale() / 2.0f;
if (childScale <= SMALLEST_REASONABLE_OCTREE_ELEMENT_SCALE) { if (childScale <= SMALLEST_REASONABLE_OCTREE_ELEMENT_SCALE) {
@ -524,7 +524,7 @@ bool EntityTreeElement::bestFitBounds(const glm::vec3& minPoint, const glm::vec3
bool EntityTreeElement::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, bool EntityTreeElement::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
bool& keepSearching, OctreeElementPointer& element, float& distance, bool& keepSearching, OctreeElementPointer& element, float& distance,
BoxFace& face, glm::vec3& surfaceNormal, const QVector<EntityItemID>& entityIdsToInclude, BoxFace& face, glm::vec3& surfaceNormal, const QVector<EntityItemID>& entityIdsToInclude,
const QVector<EntityItemID>& entityIdsToDiscard, void** intersectedObject, bool precisionPicking) { const QVector<EntityItemID>& entityIdsToDiscard, void** intersectedObject, bool precisionPicking) {
keepSearching = true; // assume that we will continue searching after this. keepSearching = true; // assume that we will continue searching after this.
@ -607,7 +607,7 @@ bool EntityTreeElement::findDetailedRayIntersection(const glm::vec3& origin, con
// we can use the AABox's ray intersection by mapping our origin and direction into the entity frame // we can use the AABox's ray intersection by mapping our origin and direction into the entity frame
// and testing intersection there. // and testing intersection there.
if (entityFrameBox.findRayIntersection(entityFrameOrigin, entityFrameDirection, localDistance, if (entityFrameBox.findRayIntersection(entityFrameOrigin, entityFrameDirection, localDistance,
localFace, localSurfaceNormal)) { localFace, localSurfaceNormal)) {
if (localDistance < distance) { if (localDistance < distance) {
// now ask the entity if we actually intersect // now ask the entity if we actually intersect
@ -862,12 +862,12 @@ int EntityTreeElement::readElementDataFromBuffer(const unsigned char* data, int
if (this == _myTree->getRoot().get() && args.bitstreamVersion < VERSION_ROOT_ELEMENT_HAS_DATA) { if (this == _myTree->getRoot().get() && args.bitstreamVersion < VERSION_ROOT_ELEMENT_HAS_DATA) {
return 0; return 0;
} }
const unsigned char* dataAt = data; const unsigned char* dataAt = data;
int bytesRead = 0; int bytesRead = 0;
uint16_t numberOfEntities = 0; uint16_t numberOfEntities = 0;
int expectedBytesPerEntity = EntityItem::expectedBytes(); int expectedBytesPerEntity = EntityItem::expectedBytes();
args.elementsPerPacket++; args.elementsPerPacket++;
if (bytesLeftToRead >= (int)sizeof(numberOfEntities)) { if (bytesLeftToRead >= (int)sizeof(numberOfEntities)) {
@ -947,7 +947,7 @@ int EntityTreeElement::readElementDataFromBuffer(const unsigned char* data, int
entityItem->recordCreationTime(); entityItem->recordCreationTime();
} }
} else { } else {
qDebug() << "Recieved packet for previously deleted entity [" << qDebug() << "Recieved packet for previously deleted entity [" <<
entityItem->getID() << "] ignoring. (inside " << __FUNCTION__ << ")"; entityItem->getID() << "] ignoring. (inside " << __FUNCTION__ << ")";
} }
} }
@ -959,7 +959,7 @@ int EntityTreeElement::readElementDataFromBuffer(const unsigned char* data, int
} }
} }
} }
return bytesRead; return bytesRead;
} }
@ -990,7 +990,7 @@ bool EntityTreeElement::pruneChildren() {
bool somethingPruned = false; bool somethingPruned = false;
for (int childIndex = 0; childIndex < NUMBER_OF_CHILDREN; childIndex++) { for (int childIndex = 0; childIndex < NUMBER_OF_CHILDREN; childIndex++) {
EntityTreeElementPointer child = getChildAtIndex(childIndex); EntityTreeElementPointer child = getChildAtIndex(childIndex);
// if my child is a leaf, but has no entities, then it's safe to delete my child // if my child is a leaf, but has no entities, then it's safe to delete my child
if (child && child->isLeaf() && !child->hasEntities()) { if (child && child->isLeaf() && !child->hasEntities()) {
deleteChildAtIndex(childIndex); deleteChildAtIndex(childIndex);
@ -1040,4 +1040,4 @@ void EntityTreeElement::debugDump() {
} }
}); });
} }

View file

@ -1034,7 +1034,7 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element,
// if we are INSIDE, INTERSECT, or OUTSIDE // if we are INSIDE, INTERSECT, or OUTSIDE
if (parentLocationThisView != ViewFrustum::INSIDE) { if (parentLocationThisView != ViewFrustum::INSIDE) {
assert(parentLocationThisView != ViewFrustum::OUTSIDE); // we shouldn't be here if our parent was OUTSIDE! assert(parentLocationThisView != ViewFrustum::OUTSIDE); // we shouldn't be here if our parent was OUTSIDE!
nodeLocationThisView = element->inFrustum(*params.viewFrustum); nodeLocationThisView = element->computeViewLocation(*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! // If we're at a element that is out of view, then we can return, because no nodes below us will be in view!
@ -1053,7 +1053,7 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element,
bool wasInView = false; bool wasInView = false;
if (params.deltaViewFrustum && params.lastViewFrustum) { if (params.deltaViewFrustum && params.lastViewFrustum) {
ViewFrustum::location location = element->inFrustum(*params.lastViewFrustum); ViewFrustum::location location = element->computeViewLocation(*params.lastViewFrustum);
// If we're a leaf, then either intersect or inside is considered "formerly in view" // If we're a leaf, then either intersect or inside is considered "formerly in view"
if (element->isLeaf()) { if (element->isLeaf()) {
@ -1237,7 +1237,7 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element,
bool childWasInView = false; bool childWasInView = false;
if (childElement && params.deltaViewFrustum && params.lastViewFrustum) { if (childElement && params.deltaViewFrustum && params.lastViewFrustum) {
ViewFrustum::location location = childElement->inFrustum(*params.lastViewFrustum); ViewFrustum::location location = childElement->computeViewLocation(*params.lastViewFrustum);
// If we're a leaf, then either intersect or inside is considered "formerly in view" // If we're a leaf, then either intersect or inside is considered "formerly in view"
if (childElement->isLeaf()) { if (childElement->isLeaf()) {

View file

@ -458,8 +458,8 @@ float OctreeElement::getEnclosingRadius() const {
return getScale() * sqrtf(3.0f) / 2.0f; return getScale() * sqrtf(3.0f) / 2.0f;
} }
ViewFrustum::location OctreeElement::inFrustum(const ViewFrustum& viewFrustum) const { ViewFrustum::location OctreeElement::computeViewLocation(const ViewFrustum& viewFrustum) const {
return viewFrustum.cubeInFrustum(_cube); return viewFrustum.computeCubeViewLocation(_cube);
} }
// There are two types of nodes for which we want to "render" // There are two types of nodes for which we want to "render"

View file

@ -49,20 +49,20 @@ protected:
OctreeElement(); OctreeElement();
virtual OctreeElementPointer createNewElement(unsigned char * octalCode = NULL) = 0; virtual OctreeElementPointer createNewElement(unsigned char * octalCode = NULL) = 0;
public: public:
virtual void init(unsigned char * octalCode); /// Your subclass must call init on construction. virtual void init(unsigned char * octalCode); /// Your subclass must call init on construction.
virtual ~OctreeElement(); virtual ~OctreeElement();
// methods you can and should override to implement your tree functionality // methods you can and should override to implement your tree functionality
/// Adds a child to the current element. Override this if there is additional child initialization your class needs. /// Adds a child to the current element. Override this if there is additional child initialization your class needs.
virtual OctreeElementPointer addChildAtIndex(int childIndex); virtual OctreeElementPointer addChildAtIndex(int childIndex);
/// Override this to implement LOD averaging on changes to the tree. /// Override this to implement LOD averaging on changes to the tree.
virtual void calculateAverageFromChildren() { } virtual void calculateAverageFromChildren() { }
/// Override this to implement LOD collapsing and identical child pruning on changes to the tree. /// Override this to implement LOD collapsing and identical child pruning on changes to the tree.
virtual bool collapseChildren() { return false; } virtual bool collapseChildren() { return false; }
/// Should this element be considered to have content in it. This will be used in collision and ray casting methods. /// Should this element be considered to have content in it. This will be used in collision and ray casting methods.
@ -72,12 +72,12 @@ public:
/// Should this element be considered to have detailed content in it. Specifically should it be rendered. /// Should this element be considered to have detailed content in it. Specifically should it be rendered.
/// By default we assume that only leaves have detailed content, but some octrees may have different semantics. /// By default we assume that only leaves have detailed content, but some octrees may have different semantics.
virtual bool hasDetailedContent() const { return isLeaf(); } virtual bool hasDetailedContent() const { return isLeaf(); }
/// Override this to break up large octree elements when an edit operation is performed on a smaller octree element. /// Override this to break up large octree elements when an edit operation is performed on a smaller octree element.
/// For example, if the octrees represent solid cubes and a delete of a smaller octree element is done then the /// For example, if the octrees represent solid cubes and a delete of a smaller octree element is done then the
/// meaningful split would be to break the larger cube into smaller cubes of the same color/texture. /// meaningful split would be to break the larger cube into smaller cubes of the same color/texture.
virtual void splitChildren() { } virtual void splitChildren() { }
/// Override to indicate that this element requires a split before editing lower elements in the octree /// Override to indicate that this element requires a split before editing lower elements in the octree
virtual bool requiresSplit() const { return false; } virtual bool requiresSplit() const { return false; }
@ -88,17 +88,17 @@ public:
virtual void initializeExtraEncodeData(EncodeBitstreamParams& params) { } virtual void initializeExtraEncodeData(EncodeBitstreamParams& params) { }
virtual bool shouldIncludeChildData(int childIndex, EncodeBitstreamParams& params) const { return true; } virtual bool shouldIncludeChildData(int childIndex, EncodeBitstreamParams& params) const { return true; }
virtual bool shouldRecurseChildTree(int childIndex, EncodeBitstreamParams& params) const { return true; } virtual bool shouldRecurseChildTree(int childIndex, EncodeBitstreamParams& params) const { return true; }
virtual void updateEncodedData(int childIndex, AppendState childAppendState, EncodeBitstreamParams& params) const { } virtual void updateEncodedData(int childIndex, AppendState childAppendState, EncodeBitstreamParams& params) const { }
virtual void elementEncodeComplete(EncodeBitstreamParams& params) const { } virtual void elementEncodeComplete(EncodeBitstreamParams& params) const { }
/// Override to serialize the state of this element. This is used for persistance and for transmission across the network. /// Override to serialize the state of this element. This is used for persistance and for transmission across the network.
virtual AppendState appendElementData(OctreePacketData* packetData, EncodeBitstreamParams& params) const virtual AppendState appendElementData(OctreePacketData* packetData, EncodeBitstreamParams& params) const
{ return COMPLETED; } { return COMPLETED; }
/// Override to deserialize the state of this element. This is used for loading from a persisted file or from reading /// Override to deserialize the state of this element. This is used for loading from a persisted file or from reading
/// from the network. /// from the network.
virtual int readElementDataFromBuffer(const unsigned char* data, int bytesLeftToRead, ReadBitstreamToTreeParams& args) virtual int readElementDataFromBuffer(const unsigned char* data, int bytesLeftToRead, ReadBitstreamToTreeParams& args)
{ return 0; } { return 0; }
/// Override to indicate that the item is currently rendered in the rendering engine. By default we assume that if /// Override to indicate that the item is currently rendered in the rendering engine. By default we assume that if
@ -106,7 +106,7 @@ public:
/// where an element is not actually rendering all should render elements. If the isRendered() state doesn't match the /// where an element is not actually rendering all should render elements. If the isRendered() state doesn't match the
/// shouldRender() state, the tree will remark elements as changed even in cases there the elements have not changed. /// shouldRender() state, the tree will remark elements as changed even in cases there the elements have not changed.
virtual bool isRendered() const { return getShouldRender(); } virtual bool isRendered() const { return getShouldRender(); }
virtual bool deleteApproved() const { return true; } virtual bool deleteApproved() const { return true; }
virtual bool canRayIntersect() const { return isLeaf(); } virtual bool canRayIntersect() const { return isLeaf(); }
@ -114,7 +114,7 @@ public:
/// \param radius radius of sphere in meters /// \param radius radius of sphere in meters
/// \param[out] penetration pointing into cube from sphere /// \param[out] penetration pointing into cube from sphere
/// \param penetratedObject unused /// \param penetratedObject unused
virtual bool findSpherePenetration(const glm::vec3& center, float radius, virtual bool findSpherePenetration(const glm::vec3& center, float radius,
glm::vec3& penetration, void** penetratedObject) const; glm::vec3& penetration, void** penetratedObject) const;
// Base class methods you don't need to implement // Base class methods you don't need to implement
@ -125,7 +125,7 @@ public:
bool isParentOf(OctreeElementPointer possibleChild) const; bool isParentOf(OctreeElementPointer possibleChild) const;
/// handles deletion of all descendants, returns false if delete not approved /// handles deletion of all descendants, returns false if delete not approved
bool safeDeepDeleteChildAtIndex(int childIndex, int recursionCount = 0); bool safeDeepDeleteChildAtIndex(int childIndex, int recursionCount = 0);
const AACube& getAACube() const { return _cube; } const AACube& getAACube() const { return _cube; }
@ -134,8 +134,8 @@ public:
int getLevel() const { return numberOfThreeBitSectionsInCode(getOctalCode()) + 1; } int getLevel() const { return numberOfThreeBitSectionsInCode(getOctalCode()) + 1; }
float getEnclosingRadius() const; float getEnclosingRadius() const;
bool isInView(const ViewFrustum& viewFrustum) const { return inFrustum(viewFrustum) != ViewFrustum::OUTSIDE; } bool isInView(const ViewFrustum& viewFrustum) const { return computeViewLocation(viewFrustum) != ViewFrustum::OUTSIDE; }
ViewFrustum::location inFrustum(const ViewFrustum& viewFrustum) const; ViewFrustum::location computeViewLocation(const ViewFrustum& viewFrustum) const;
float distanceToCamera(const ViewFrustum& viewFrustum) const; float distanceToCamera(const ViewFrustum& viewFrustum) const;
float furthestDistanceToCamera(const ViewFrustum& viewFrustum) const; float furthestDistanceToCamera(const ViewFrustum& viewFrustum) const;
@ -257,7 +257,7 @@ protected:
static std::map<QString, uint16_t> _mapSourceUUIDsToKeys; static std::map<QString, uint16_t> _mapSourceUUIDsToKeys;
static std::map<uint16_t, QString> _mapKeysToSourceUUIDs; static std::map<uint16_t, QString> _mapKeysToSourceUUIDs;
unsigned char _childBitmask; // 1 byte unsigned char _childBitmask; // 1 byte
bool _falseColored : 1, /// Client only, is this voxel false colored, 1 bit bool _falseColored : 1, /// Client only, is this voxel false colored, 1 bit
_isDirty : 1, /// Client only, has this voxel changed since being rendered, 1 bit _isDirty : 1, /// Client only, has this voxel changed since being rendered, 1 bit

View file

@ -27,9 +27,9 @@ void OctreeHeadlessViewer::init() {
void OctreeHeadlessViewer::queryOctree() { void OctreeHeadlessViewer::queryOctree() {
char serverType = getMyNodeType(); char serverType = getMyNodeType();
PacketType packetType = getMyQueryMessageType(); PacketType packetType = getMyQueryMessageType();
NodeToJurisdictionMap& jurisdictions = *_jurisdictionListener->getJurisdictions(); NodeToJurisdictionMap& jurisdictions = *_jurisdictionListener->getJurisdictions();
bool wantExtraDebugging = false; bool wantExtraDebugging = false;
if (wantExtraDebugging) { if (wantExtraDebugging) {
@ -77,7 +77,7 @@ void OctreeHeadlessViewer::queryOctree() {
if (jurisdictions.find(nodeUUID) == jurisdictions.end()) { if (jurisdictions.find(nodeUUID) == jurisdictions.end()) {
unknownJurisdictionServers++; unknownJurisdictionServers++;
return; return;
} }
const JurisdictionMap& map = (jurisdictions)[nodeUUID]; const JurisdictionMap& map = (jurisdictions)[nodeUUID];
unsigned char* rootCode = map.getRootOctalCode(); unsigned char* rootCode = map.getRootOctalCode();
@ -91,7 +91,7 @@ void OctreeHeadlessViewer::queryOctree() {
if (foundRootDetails) { if (foundRootDetails) {
AACube serverBounds(glm::vec3(rootDetails.x, rootDetails.y, rootDetails.z), rootDetails.s); AACube serverBounds(glm::vec3(rootDetails.x, rootDetails.y, rootDetails.z), rootDetails.s);
ViewFrustum::location serverFrustumLocation = _viewFrustum.cubeInFrustum(serverBounds); ViewFrustum::location serverFrustumLocation = _viewFrustum.computeCubeViewLocation(serverBounds);
if (serverFrustumLocation != ViewFrustum::OUTSIDE) { if (serverFrustumLocation != ViewFrustum::OUTSIDE) {
inViewServers++; inViewServers++;
@ -165,7 +165,7 @@ void OctreeHeadlessViewer::queryOctree() {
if (foundRootDetails) { if (foundRootDetails) {
AACube serverBounds(glm::vec3(rootDetails.x, rootDetails.y, rootDetails.z), rootDetails.s); AACube serverBounds(glm::vec3(rootDetails.x, rootDetails.y, rootDetails.z), rootDetails.s);
ViewFrustum::location serverFrustumLocation = _viewFrustum.cubeInFrustum(serverBounds); ViewFrustum::location serverFrustumLocation = _viewFrustum.computeCubeViewLocation(serverBounds);
if (serverFrustumLocation != ViewFrustum::OUTSIDE) { if (serverFrustumLocation != ViewFrustum::OUTSIDE) {
inView = true; inView = true;
} else { } else {
@ -208,7 +208,7 @@ void OctreeHeadlessViewer::queryOctree() {
// setup the query packet // setup the query packet
auto queryPacket = NLPacket::create(packetType); auto queryPacket = NLPacket::create(packetType);
// read the data to our packet and set the payload size to fit the query // read the data to our packet and set the payload size to fit the query
int querySize = _octreeQuery.getBroadcastData(reinterpret_cast<unsigned char*>(queryPacket->getPayload())); int querySize = _octreeQuery.getBroadcastData(reinterpret_cast<unsigned char*>(queryPacket->getPayload()));
queryPacket->setPayloadSize(querySize); queryPacket->setPayloadSize(querySize);

View file

@ -241,30 +241,18 @@ ViewFrustum::location ViewFrustum::boxInKeyhole(const AABox& box) const {
return result; return result;
} }
ViewFrustum::location ViewFrustum::pointInFrustum(const glm::vec3& point, bool ignoreKeyhole) const { ViewFrustum::location ViewFrustum::computePointFrustumLocation(const glm::vec3& point) const {
ViewFrustum::location regularResult = INSIDE; // only checks against frustum, not sphere
ViewFrustum::location keyholeResult = OUTSIDE;
// If we have a keyholeRadius, check that first, since it's cheaper
if (!ignoreKeyhole && _keyholeRadius >= 0.0f) {
keyholeResult = pointInKeyhole(point);
if (keyholeResult == INSIDE) {
return keyholeResult;
}
}
// If we're not known to be INSIDE the keyhole, then check the regular frustum
for(int i = 0; i < 6; ++i) { for(int i = 0; i < 6; ++i) {
float distance = _planes[i].distance(point); float distance = _planes[i].distance(point);
if (distance < 0) { if (distance < 0.0f) {
return keyholeResult; // escape early will be the value from checking the keyhole return OUTSIDE;
} }
} }
return regularResult; return INSIDE;
} }
ViewFrustum::location ViewFrustum::sphereInFrustum(const glm::vec3& center, float radius) const { ViewFrustum::location ViewFrustum::computeSphereViewLocation(const glm::vec3& center, float radius) const {
ViewFrustum::location regularResult = INSIDE; ViewFrustum::location regularResult = INSIDE;
ViewFrustum::location keyholeResult = OUTSIDE; ViewFrustum::location keyholeResult = OUTSIDE;
@ -291,7 +279,7 @@ ViewFrustum::location ViewFrustum::sphereInFrustum(const glm::vec3& center, floa
} }
ViewFrustum::location ViewFrustum::cubeInFrustum(const AACube& cube) const { ViewFrustum::location ViewFrustum::computeCubeViewLocation(const AACube& cube) const {
ViewFrustum::location regularResult = INSIDE; ViewFrustum::location regularResult = INSIDE;
ViewFrustum::location keyholeResult = OUTSIDE; ViewFrustum::location keyholeResult = OUTSIDE;
@ -326,7 +314,7 @@ ViewFrustum::location ViewFrustum::cubeInFrustum(const AACube& cube) const {
return regularResult; return regularResult;
} }
ViewFrustum::location ViewFrustum::boxInFrustum(const AABox& box) const { ViewFrustum::location ViewFrustum::computeBoxViewLocation(const AABox& box) const {
ViewFrustum::location regularResult = INSIDE; ViewFrustum::location regularResult = INSIDE;
ViewFrustum::location keyholeResult = OUTSIDE; ViewFrustum::location keyholeResult = OUTSIDE;
@ -490,7 +478,7 @@ PickRay ViewFrustum::computePickRay(float x, float y) {
} }
void ViewFrustum::computePickRay(float x, float y, glm::vec3& origin, glm::vec3& direction) const { void ViewFrustum::computePickRay(float x, float y, glm::vec3& origin, glm::vec3& direction) const {
origin = _cornersWorld[TOP_LEFT_NEAR] + x * (_cornersWorld[TOP_RIGHT_NEAR] - _cornersWorld[TOP_LEFT_NEAR]) + origin = _cornersWorld[TOP_LEFT_NEAR] + x * (_cornersWorld[TOP_RIGHT_NEAR] - _cornersWorld[TOP_LEFT_NEAR]) +
y * (_cornersWorld[BOTTOM_LEFT_NEAR] - _cornersWorld[TOP_LEFT_NEAR]); y * (_cornersWorld[BOTTOM_LEFT_NEAR] - _cornersWorld[TOP_LEFT_NEAR]);
direction = glm::normalize(origin - _position); direction = glm::normalize(origin - _position);
} }
@ -804,7 +792,7 @@ float ViewFrustum::calculateRenderAccuracy(const AABox& bounds, float octreeSize
// FIXME - for now, it's either visible or not visible. We want to adjust this to eventually return // 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 // a floating point for objects that have small angular size to indicate that they may be rendered
// with lower preciscion // with lower preciscion
return (distanceToCamera <= visibleDistanceAtClosestScale) ? 1.0f : 0.0f; return (distanceToCamera <= visibleDistanceAtClosestScale) ? 1.0f : 0.0f;
} }
float boundaryDistanceForRenderLevel(unsigned int renderLevel, float voxelSizeScale) { float boundaryDistanceForRenderLevel(unsigned int renderLevel, float voxelSizeScale) {

View file

@ -91,10 +91,11 @@ public:
typedef enum {OUTSIDE, INTERSECT, INSIDE} location; typedef enum {OUTSIDE, INTERSECT, INSIDE} location;
ViewFrustum::location pointInFrustum(const glm::vec3& point, bool ignoreKeyhole = false) const; ViewFrustum::location computePointFrustumLocation(const glm::vec3& point) const;
ViewFrustum::location sphereInFrustum(const glm::vec3& center, float radius) const;
ViewFrustum::location cubeInFrustum(const AACube& cube) const; ViewFrustum::location computeSphereViewLocation(const glm::vec3& center, float radius) const;
ViewFrustum::location boxInFrustum(const AABox& box) const; ViewFrustum::location computeCubeViewLocation(const AACube& cube) const;
ViewFrustum::location computeBoxViewLocation(const AABox& box) const;
// some frustum comparisons // some frustum comparisons
bool matches(const ViewFrustum& compareTo, bool debug = false) const; bool matches(const ViewFrustum& compareTo, bool debug = false) const;
@ -114,15 +115,15 @@ public:
glm::vec2 projectPoint(glm::vec3 point, bool& pointInView) const; glm::vec2 projectPoint(glm::vec3 point, bool& pointInView) const;
OctreeProjectedPolygon getProjectedPolygon(const AACube& box) const; OctreeProjectedPolygon getProjectedPolygon(const AACube& box) const;
void getFurthestPointFromCamera(const AACube& box, glm::vec3& furthestPoint) const; void getFurthestPointFromCamera(const AACube& box, glm::vec3& furthestPoint) const;
float distanceToCamera(const glm::vec3& point) const; float distanceToCamera(const glm::vec3& point) const;
void evalProjectionMatrix(glm::mat4& proj) const; void evalProjectionMatrix(glm::mat4& proj) const;
void evalViewTransform(Transform& view) 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 /// 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. /// 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, float calculateRenderAccuracy(const AABox& bounds, float octreeSizeScale = DEFAULT_OCTREE_SIZE_SCALE,
int boundaryLevelAdjust = 0) const; int boundaryLevelAdjust = 0) const;
float getAccuracyAngle(float octreeSizeScale = DEFAULT_OCTREE_SIZE_SCALE, int boundaryLevelAdjust = 0) const; float getAccuracyAngle(float octreeSizeScale = DEFAULT_OCTREE_SIZE_SCALE, int boundaryLevelAdjust = 0) const;

View file

@ -413,9 +413,9 @@ ShapeKey ModelMeshPartPayload::getShapeKey() const {
void ModelMeshPartPayload::bindMesh(gpu::Batch& batch) const { void ModelMeshPartPayload::bindMesh(gpu::Batch& batch) const {
if (!_isBlendShaped) { if (!_isBlendShaped) {
batch.setIndexBuffer(gpu::UINT32, (_drawMesh->getIndexBuffer()._buffer), 0); batch.setIndexBuffer(gpu::UINT32, (_drawMesh->getIndexBuffer()._buffer), 0);
batch.setInputFormat((_drawMesh->getVertexFormat())); batch.setInputFormat((_drawMesh->getVertexFormat()));
batch.setInputStream(0, _drawMesh->getVertexStream()); batch.setInputStream(0, _drawMesh->getVertexStream());
} else { } else {
batch.setIndexBuffer(gpu::UINT32, (_drawMesh->getIndexBuffer()._buffer), 0); batch.setIndexBuffer(gpu::UINT32, (_drawMesh->getIndexBuffer()._buffer), 0);
@ -426,7 +426,7 @@ void ModelMeshPartPayload::bindMesh(gpu::Batch& batch) const {
batch.setInputBuffer(1, _model->_blendedVertexBuffers[_meshIndex], _drawMesh->getNumVertices() * sizeof(glm::vec3), sizeof(glm::vec3)); batch.setInputBuffer(1, _model->_blendedVertexBuffers[_meshIndex], _drawMesh->getNumVertices() * sizeof(glm::vec3), sizeof(glm::vec3));
batch.setInputStream(2, _drawMesh->getVertexStream().makeRangedStream(2)); batch.setInputStream(2, _drawMesh->getVertexStream().makeRangedStream(2));
} }
// TODO: Get rid of that extra call // TODO: Get rid of that extra call
if (!_hasColorAttrib) { if (!_hasColorAttrib) {
batch._glColor4f(1.0f, 1.0f, 1.0f, 1.0f); batch._glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
@ -474,8 +474,8 @@ void ModelMeshPartPayload::render(RenderArgs* args) const {
#ifdef DEBUG_BOUNDING_PARTS #ifdef DEBUG_BOUNDING_PARTS
{ {
AABox partBounds = getPartBounds(_meshIndex, partIndex); AABox partBounds = getPartBounds(_meshIndex, partIndex);
bool inView = args->_viewFrustum->boxInFrustum(partBounds) != ViewFrustum::OUTSIDE; bool inView = args->_viewFrustum->computeBoxViewLocation(partBounds) != ViewFrustum::OUTSIDE;
glm::vec4 cubeColor; glm::vec4 cubeColor;
if (isSkinned) { if (isSkinned) {
cubeColor = glm::vec4(0.0f, 1.0f, 1.0f, 1.0f); cubeColor = glm::vec4(0.0f, 1.0f, 1.0f, 1.0f);
@ -484,7 +484,7 @@ void ModelMeshPartPayload::render(RenderArgs* args) const {
} else { } else {
cubeColor = glm::vec4(1.0f, 1.0f, 0.0f, 1.0f); cubeColor = glm::vec4(1.0f, 1.0f, 0.0f, 1.0f);
} }
Transform transform; Transform transform;
transform.setTranslation(partBounds.calcCenter()); transform.setTranslation(partBounds.calcCenter());
transform.setScale(partBounds.getDimensions()); transform.setScale(partBounds.getDimensions());
@ -492,7 +492,7 @@ void ModelMeshPartPayload::render(RenderArgs* args) const {
DependencyManager::get<GeometryCache>()->renderWireCube(batch, 1.0f, cubeColor); DependencyManager::get<GeometryCache>()->renderWireCube(batch, 1.0f, cubeColor);
} }
#endif //def DEBUG_BOUNDING_PARTS #endif //def DEBUG_BOUNDING_PARTS
auto locations = args->_pipeline->locations; auto locations = args->_pipeline->locations;
assert(locations); assert(locations);
@ -500,23 +500,23 @@ void ModelMeshPartPayload::render(RenderArgs* args) const {
bool canCauterize = args->_renderMode != RenderArgs::SHADOW_RENDER_MODE; bool canCauterize = args->_renderMode != RenderArgs::SHADOW_RENDER_MODE;
_model->updateClusterMatrices(_transform.getTranslation(), _transform.getRotation()); _model->updateClusterMatrices(_transform.getTranslation(), _transform.getRotation());
bindTransform(batch, locations, canCauterize); bindTransform(batch, locations, canCauterize);
//Bind the index buffer and vertex buffer and Blend shapes if needed //Bind the index buffer and vertex buffer and Blend shapes if needed
bindMesh(batch); bindMesh(batch);
// apply material properties // apply material properties
bindMaterial(batch, locations); bindMaterial(batch, locations);
if (args) { if (args) {
args->_details._materialSwitches++; args->_details._materialSwitches++;
} }
// Draw! // Draw!
{ {
PerformanceTimer perfTimer("batch.drawIndexed()"); PerformanceTimer perfTimer("batch.drawIndexed()");
drawCall(batch); drawCall(batch);
} }
if (args) { if (args) {
const int INDICES_PER_TRIANGLE = 3; const int INDICES_PER_TRIANGLE = 3;
args->_details._trianglesRendered += _drawPart._numIndices / INDICES_PER_TRIANGLE; args->_details._trianglesRendered += _drawPart._numIndices / INDICES_PER_TRIANGLE;

View file

@ -29,7 +29,7 @@ void render::cullItems(const RenderContextPointer& renderContext, const CullFunc
ViewFrustum* frustum = args->_viewFrustum; ViewFrustum* frustum = args->_viewFrustum;
details._considered += (int)inItems.size(); details._considered += (int)inItems.size();
// Culling / LOD // Culling / LOD
for (auto item : inItems) { for (auto item : inItems) {
if (item.bound.isNull()) { if (item.bound.isNull()) {
@ -41,8 +41,8 @@ void render::cullItems(const RenderContextPointer& renderContext, const CullFunc
// when they are outside of the view frustum... // when they are outside of the view frustum...
bool outOfView; bool outOfView;
{ {
PerformanceTimer perfTimer("boxInFrustum"); PerformanceTimer perfTimer("computeBoxViewLocation");
outOfView = frustum->boxInFrustum(item.bound) == ViewFrustum::OUTSIDE; outOfView = frustum->computeBoxViewLocation(item.bound) == ViewFrustum::OUTSIDE;
} }
if (!outOfView) { if (!outOfView) {
bool bigEnoughToRender; bool bigEnoughToRender;
@ -88,10 +88,10 @@ struct BackToFrontSort {
void render::depthSortItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, bool frontToBack, const ItemBounds& inItems, ItemBounds& outItems) { void render::depthSortItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, bool frontToBack, const ItemBounds& inItems, ItemBounds& outItems) {
assert(renderContext->args); assert(renderContext->args);
assert(renderContext->args->_viewFrustum); assert(renderContext->args->_viewFrustum);
auto& scene = sceneContext->_scene; auto& scene = sceneContext->_scene;
RenderArgs* args = renderContext->args; RenderArgs* args = renderContext->args;
// Allocate and simply copy // Allocate and simply copy
outItems.clear(); outItems.clear();
@ -237,8 +237,8 @@ void CullSpatialSelection::run(const SceneContextPointer& sceneContext, const Re
*/ */
} }
bool frustumTest(const AABox& bound) { bool viewTest(const AABox& bound) {
if (_args->_viewFrustum->boxInFrustum(bound) == ViewFrustum::OUTSIDE) { if (_args->_viewFrustum->computeBoxViewLocation(bound) == ViewFrustum::OUTSIDE) {
_renderDetails._outOfView++; _renderDetails._outOfView++;
return false; return false;
} }
@ -302,7 +302,7 @@ void CullSpatialSelection::run(const SceneContextPointer& sceneContext, const Re
auto& item = scene->getItem(id); auto& item = scene->getItem(id);
if (_filter.test(item.getKey())) { if (_filter.test(item.getKey())) {
ItemBound itemBound(id, item.getBound()); ItemBound itemBound(id, item.getBound());
if (test.frustumTest(itemBound.bound)) { if (test.viewTest(itemBound.bound)) {
outItems.emplace_back(itemBound); outItems.emplace_back(itemBound);
} }
} }
@ -316,7 +316,7 @@ void CullSpatialSelection::run(const SceneContextPointer& sceneContext, const Re
auto& item = scene->getItem(id); auto& item = scene->getItem(id);
if (_filter.test(item.getKey())) { if (_filter.test(item.getKey())) {
ItemBound itemBound(id, item.getBound()); ItemBound itemBound(id, item.getBound());
if (test.frustumTest(itemBound.bound)) { if (test.viewTest(itemBound.bound)) {
if (test.solidAngleTest(itemBound.bound)) { if (test.solidAngleTest(itemBound.bound)) {
outItems.emplace_back(itemBound); outItems.emplace_back(itemBound);
} }