remove coverage map and occulusion culling, since it was always disabled

This commit is contained in:
Brad Hefta-Gaub 2015-12-03 10:20:04 -08:00
parent 65334659ae
commit 0c05ffe9ce
12 changed files with 6 additions and 1107 deletions

View file

@ -14,7 +14,6 @@
#include <iostream>
#include <CoverageMap.h>
#include <NodeData.h>
#include <OctreeConstants.h>
#include <OctreeElementBag.h>
@ -55,7 +54,6 @@ public:
void setMaxLevelReached(int maxLevelReached) { _maxLevelReachedInLastSearch = maxLevelReached; }
OctreeElementBag elementBag;
CoverageMap map;
OctreeElementExtraEncodeData extraEncodeData;
ViewFrustum& getCurrentViewFrustum() { return _currentViewFrustum; }

View file

@ -350,7 +350,6 @@ int OctreeSendThread::packetDistributor(OctreeQueryNode* nodeData, bool viewFrus
if (nodeData->moveShouldDump() || nodeData->hasLodChanged()) {
nodeData->dumpOutOfView();
}
nodeData->map.erase();
}
if (!viewFrustumChanged && !nodeData->getWantDelta()) {
@ -451,9 +450,6 @@ int OctreeSendThread::packetDistributor(OctreeQueryNode* nodeData, bool viewFrus
}
*/
bool wantOcclusionCulling = nodeData->getWantOcclusionCulling();
CoverageMap* coverageMap = wantOcclusionCulling ? &nodeData->map : IGNORE_COVERAGE_MAP;
float octreeSizeScale = nodeData->getOctreeSizeScale();
int boundaryLevelAdjustClient = nodeData->getBoundaryLevelAdjust();
@ -462,7 +458,7 @@ int OctreeSendThread::packetDistributor(OctreeQueryNode* nodeData, bool viewFrus
EncodeBitstreamParams params(INT_MAX, &nodeData->getCurrentViewFrustum(), wantColor,
WANT_EXISTS_BITS, DONT_CHOP, wantDelta, lastViewFrustum,
wantOcclusionCulling, coverageMap, boundaryLevelAdjust, octreeSizeScale,
boundaryLevelAdjust, octreeSizeScale,
nodeData->getLastTimeBagEmpty(),
isFullScene, &nodeData->stats, _myServer->getJurisdiction(),
&nodeData->extraEncodeData);
@ -634,7 +630,6 @@ int OctreeSendThread::packetDistributor(OctreeQueryNode* nodeData, bool viewFrus
if (nodeData->elementBag.isEmpty()) {
nodeData->updateLastKnownViewFrustum();
nodeData->setViewSent(true);
nodeData->map.erase(); // It would be nice if we could save this, and only reset it when the view frustum changes
}
} // end if bag wasn't empty, and so we sent stuff...

View file

@ -3076,7 +3076,6 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node
_octreeQuery.setWantLowResMoving(true);
_octreeQuery.setWantColor(true);
_octreeQuery.setWantDelta(true);
_octreeQuery.setWantOcclusionCulling(false);
_octreeQuery.setWantCompression(true);
_octreeQuery.setCameraPosition(_viewFrustum.getPosition());

View file

@ -1,542 +0,0 @@
//
// CoverageMap.cpp
// libraries/octree/src
//
// Created by Brad Hefta-Gaub on 06/11/13.
// Copyright 2013 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 <cstring>
#include <QtCore/QDebug>
#include <SharedUtil.h>
#include "OctreeLogging.h"
#include "CoverageMap.h"
int CoverageMap::_mapCount = 0;
int CoverageMap::_checkMapRootCalls = 0;
int CoverageMap::_notAllInView = 0;
bool CoverageMap::wantDebugging = false;
const int MAX_POLYGONS_PER_REGION = 50;
const BoundingBox CoverageMap::ROOT_BOUNDING_BOX = BoundingBox(glm::vec2(-1.0f,-1.0f), glm::vec2(2.0f,2.0f));
// Coverage Map's polygon coordinates are from -1 to 1 in the following mapping to screen space.
//
// (0,0) (windowWidth, 0)
// -1,1 1,1
// +-----------------------+
// | | |
// | | |
// | -1,0 | |
// |-----------+-----------|
// | 0,0 |
// | | |
// | | |
// | | |
// +-----------------------+
// -1,-1 1,-1
// (0,windowHeight) (windowWidth,windowHeight)
//
// Choosing a minimum sized polygon. Since we know a typical window is approximately 1500 pixels wide
// then a pixel on our screen will be ~ 2.0/1500 or 0.0013 "units" wide, similarly pixels are typically
// about that tall as well. If we say that polygons should be at least 10x10 pixels to be considered "big enough"
// then we can calculate a reasonable polygon area
const int TYPICAL_SCREEN_WIDTH_IN_PIXELS = 1500;
const int MINIMUM_POLYGON_AREA_SIDE_IN_PIXELS = 10;
const float TYPICAL_SCREEN_PIXEL_WIDTH = (2.0f / TYPICAL_SCREEN_WIDTH_IN_PIXELS);
const float CoverageMap::MINIMUM_POLYGON_AREA_TO_STORE = (TYPICAL_SCREEN_PIXEL_WIDTH * MINIMUM_POLYGON_AREA_SIDE_IN_PIXELS) *
(TYPICAL_SCREEN_PIXEL_WIDTH * MINIMUM_POLYGON_AREA_SIDE_IN_PIXELS);
CoverageMap::CoverageMap(BoundingBox boundingBox, bool isRoot, bool managePolygons) :
_isRoot(isRoot),
_myBoundingBox(boundingBox),
_managePolygons(managePolygons),
_topHalf (boundingBox.topHalf() , false, managePolygons, TOP_HALF ),
_bottomHalf (boundingBox.bottomHalf(), false, managePolygons, BOTTOM_HALF ),
_leftHalf (boundingBox.leftHalf() , false, managePolygons, LEFT_HALF ),
_rightHalf (boundingBox.rightHalf() , false, managePolygons, RIGHT_HALF ),
_remainder (boundingBox, isRoot, managePolygons, REMAINDER )
{
_mapCount++;
init();
};
CoverageMap::~CoverageMap() {
erase();
};
void CoverageMap::printStats() {
qCDebug(octree, "CoverageMap::printStats()...");
qCDebug(octree, "MINIMUM_POLYGON_AREA_TO_STORE=%f", (double)MINIMUM_POLYGON_AREA_TO_STORE);
qCDebug(octree, "_mapCount=%d",_mapCount);
qCDebug(octree, "_checkMapRootCalls=%d",_checkMapRootCalls);
qCDebug(octree, "_notAllInView=%d",_notAllInView);
qCDebug(octree, "_maxPolygonsUsed=%d",CoverageRegion::_maxPolygonsUsed);
qCDebug(octree, "_totalPolygons=%d",CoverageRegion::_totalPolygons);
qCDebug(octree, "_occlusionTests=%d",CoverageRegion::_occlusionTests);
qCDebug(octree, "_regionSkips=%d",CoverageRegion::_regionSkips);
qCDebug(octree, "_tooSmallSkips=%d",CoverageRegion::_tooSmallSkips);
qCDebug(octree, "_regionFullSkips=%d",CoverageRegion::_regionFullSkips);
qCDebug(octree, "_outOfOrderPolygon=%d",CoverageRegion::_outOfOrderPolygon);
qCDebug(octree, "_clippedPolygons=%d",CoverageRegion::_clippedPolygons);
}
void CoverageMap::erase() {
// tell our regions to erase()
_topHalf.erase();
_bottomHalf.erase();
_leftHalf.erase();
_rightHalf.erase();
_remainder.erase();
for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
if (_childMaps[i]) {
delete _childMaps[i];
_childMaps[i] = NULL;
}
}
if (_isRoot && wantDebugging) {
qCDebug(octree, "CoverageMap last to be deleted...");
printStats();
CoverageRegion::_maxPolygonsUsed = 0;
CoverageRegion::_totalPolygons = 0;
CoverageRegion::_occlusionTests = 0;
CoverageRegion::_regionSkips = 0;
CoverageRegion::_tooSmallSkips = 0;
CoverageRegion::_regionFullSkips = 0;
CoverageRegion::_outOfOrderPolygon = 0;
CoverageRegion::_clippedPolygons = 0;
_mapCount = 0;
_checkMapRootCalls = 0;
_notAllInView = 0;
}
}
void CoverageMap::init() {
memset(_childMaps,0,sizeof(_childMaps));
}
// 0 = bottom, right
// 1 = bottom, left
// 2 = top, right
// 3 = top, left
BoundingBox CoverageMap::getChildBoundingBox(int childIndex) {
const int LEFT_BIT = 1;
const int TOP_BIT = 2;
// initialize to our corner, and half our size
BoundingBox result(_myBoundingBox.corner,_myBoundingBox.size/2.0f);
// if our "left" bit is set, then add size.x to the corner
if ((childIndex & LEFT_BIT) == LEFT_BIT) {
result.corner.x += result.size.x;
}
// if our "top" bit is set, then add size.y to the corner
if ((childIndex & TOP_BIT) == TOP_BIT) {
result.corner.y += result.size.y;
}
return result;
}
int CoverageMap::getPolygonCount() const {
return (_topHalf.getPolygonCount() +
_bottomHalf.getPolygonCount() +
_leftHalf.getPolygonCount() +
_rightHalf.getPolygonCount() +
_remainder.getPolygonCount());
}
OctreeProjectedPolygon* CoverageMap::getPolygon(int index) const {
int base = 0;
if ((index - base) < _topHalf.getPolygonCount()) {
return _topHalf.getPolygon((index - base));
}
base += _topHalf.getPolygonCount();
if ((index - base) < _bottomHalf.getPolygonCount()) {
return _bottomHalf.getPolygon((index - base));
}
base += _bottomHalf.getPolygonCount();
if ((index - base) < _leftHalf.getPolygonCount()) {
return _leftHalf.getPolygon((index - base));
}
base += _leftHalf.getPolygonCount();
if ((index - base) < _rightHalf.getPolygonCount()) {
return _rightHalf.getPolygon((index - base));
}
base += _rightHalf.getPolygonCount();
if ((index - base) < _remainder.getPolygonCount()) {
return _remainder.getPolygon((index - base));
}
return NULL;
}
// possible results = STORED/NOT_STORED, OCCLUDED, DOESNT_FIT
CoverageMapStorageResult CoverageMap::checkMap(OctreeProjectedPolygon* polygon, bool storeIt) {
if (_isRoot) {
_checkMapRootCalls++;
}
// short circuit: we don't handle polygons that aren't all in view, so, if the polygon in question is
// not in view, then we just discard it with a DOESNT_FIT, this saves us time checking values later.
if (!polygon->getAllInView()) {
_notAllInView++;
return DOESNT_FIT;
}
BoundingBox polygonBox(polygon->getBoundingBox());
if (_isRoot || _myBoundingBox.contains(polygonBox)) {
CoverageMapStorageResult result = NOT_STORED;
CoverageRegion* storeIn = &_remainder;
// Check each half of the box independently
const bool useRegions = true; // for now we will continue to use regions
if (useRegions) {
if (_topHalf.contains(polygonBox)) {
result = _topHalf.checkRegion(polygon, polygonBox, storeIt);
storeIn = &_topHalf;
} else if (_bottomHalf.contains(polygonBox)) {
result = _bottomHalf.checkRegion(polygon, polygonBox, storeIt);
storeIn = &_bottomHalf;
} else if (_leftHalf.contains(polygonBox)) {
result = _leftHalf.checkRegion(polygon, polygonBox, storeIt);
storeIn = &_leftHalf;
} else if (_rightHalf.contains(polygonBox)) {
result = _rightHalf.checkRegion(polygon, polygonBox, storeIt);
storeIn = &_rightHalf;
}
}
// if we got this far, there are one of two possibilities, either a polygon doesn't fit
// in one of the halves, or it did fit, but it wasn't occluded by anything only in that
// half. In either of these cases, we want to check our remainder region to see if its
// occluded by anything there
if (!(result == STORED || result == OCCLUDED)) {
result = _remainder.checkRegion(polygon, polygonBox, storeIt);
}
// It's possible that this first set of checks might have resulted in an out of order polygon
// in which case we just return..
if (result == STORED || result == OCCLUDED) {
/*
if (result == STORED)
qCDebug(octree, "CoverageMap2::checkMap()... STORED\n");
else
qCDebug(octree, "CoverageMap2::checkMap()... OCCLUDED\n");
*/
return result;
}
// if we made it here, then it means the polygon being stored is not occluded
// at this level of the quad tree, so we can continue to insert it into the map.
// First we check to see if it fits in any of our sub maps
const bool useChildMaps = true; // for now we will continue to use child maps
if (useChildMaps) {
for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
BoundingBox childMapBoundingBox = getChildBoundingBox(i);
if (childMapBoundingBox.contains(polygon->getBoundingBox())) {
// if no child map exists yet, then create it
if (!_childMaps[i]) {
_childMaps[i] = new CoverageMap(childMapBoundingBox, NOT_ROOT, _managePolygons);
}
result = _childMaps[i]->checkMap(polygon, storeIt);
/*
switch (result) {
case STORED:
qCDebug(octree, "checkMap() = STORED\n");
break;
case NOT_STORED:
qCDebug(octree, "checkMap() = NOT_STORED\n");
break;
case OCCLUDED:
qCDebug(octree, "checkMap() = OCCLUDED\n");
break;
default:
qCDebug(octree, "checkMap() = ????? \n");
break;
}
*/
return result;
}
}
}
// if we got this far, then the polygon is in our bounding box, but doesn't fit in
// any of our child bounding boxes, so we should add it here.
if (storeIt) {
if (polygon->getBoundingBox().area() > CoverageMap::MINIMUM_POLYGON_AREA_TO_STORE) {
if (storeIn->getPolygonCount() < MAX_POLYGONS_PER_REGION) {
storeIn->storeInArray(polygon);
return STORED;
} else {
CoverageRegion::_regionFullSkips++;
return NOT_STORED;
}
} else {
CoverageRegion::_tooSmallSkips++;
return NOT_STORED;
}
} else {
return NOT_STORED;
}
}
return DOESNT_FIT;
}
CoverageRegion::CoverageRegion(BoundingBox boundingBox, bool isRoot, bool managePolygons, RegionName regionName) :
_isRoot(isRoot),
_myBoundingBox(boundingBox),
_managePolygons(managePolygons),
_regionName(regionName)
{
init();
};
CoverageRegion::~CoverageRegion() {
erase();
};
void CoverageRegion::init() {
_polygonCount = 0;
_polygonArraySize = 0;
_polygons = NULL;
_polygonDistances = NULL;
_polygonSizes = NULL;
}
void CoverageRegion::erase() {
/**
if (_polygonCount) {
qCDebug(octree, "CoverageRegion::erase()...\n");
qCDebug(octree, "_polygonCount=%d\n",_polygonCount);
_myBoundingBox.printDebugDetails(getRegionName());
//for (int i = 0; i < _polygonCount; i++) {
// qCDebug(octree, "_polygons[%d]=",i);
// _polygons[i]->getBoundingBox().printDebugDetails();
//}
}
**/
// If we're in charge of managing the polygons, then clean them up first
if (_polygons && _managePolygons) {
for (int i = 0; i < _polygonCount; i++) {
delete _polygons[i];
_polygons[i] = NULL; // do we need to do this?
}
}
// Now, clean up our local storage
_polygonCount = 0;
_polygonArraySize = 0;
if (_polygons) {
delete[] _polygons;
_polygons = NULL;
}
if (_polygonDistances) {
delete[] _polygonDistances;
_polygonDistances = NULL;
}
if (_polygonSizes) {
delete[] _polygonSizes;
_polygonSizes = NULL;
}
}
void CoverageRegion::growPolygonArray() {
OctreeProjectedPolygon** newPolygons = new OctreeProjectedPolygon*[_polygonArraySize + DEFAULT_GROW_SIZE];
float* newDistances = new float[_polygonArraySize + DEFAULT_GROW_SIZE];
float* newSizes = new float[_polygonArraySize + DEFAULT_GROW_SIZE];
if (_polygons) {
memcpy(newPolygons, _polygons, sizeof(OctreeProjectedPolygon*) * _polygonCount);
delete[] _polygons;
memcpy(newDistances, _polygonDistances, sizeof(float) * _polygonCount);
delete[] _polygonDistances;
memcpy(newSizes, _polygonSizes, sizeof(float) * _polygonCount);
delete[] _polygonSizes;
}
_polygons = newPolygons;
_polygonDistances = newDistances;
_polygonSizes = newSizes;
_polygonArraySize = _polygonArraySize + DEFAULT_GROW_SIZE;
}
const char* CoverageRegion::getRegionName() const {
switch (_regionName) {
case TOP_HALF:
return "TOP_HALF";
case BOTTOM_HALF:
return "BOTTOM_HALF";
case LEFT_HALF:
return "LEFT_HALF";
case RIGHT_HALF:
return "RIGHT_HALF";
default:
case REMAINDER:
return "REMAINDER";
}
return "REMAINDER";
}
int CoverageRegion::_maxPolygonsUsed = 0;
int CoverageRegion::_totalPolygons = 0;
int CoverageRegion::_occlusionTests = 0;
int CoverageRegion::_regionSkips = 0;
int CoverageRegion::_tooSmallSkips = 0;
int CoverageRegion::_regionFullSkips = 0;
int CoverageRegion::_outOfOrderPolygon = 0;
int CoverageRegion::_clippedPolygons = 0;
bool CoverageRegion::mergeItemsInArray(OctreeProjectedPolygon* seed, bool seedInArray) {
for (int i = 0; i < _polygonCount; i++) {
OctreeProjectedPolygon* otherPolygon = _polygons[i];
if (otherPolygon->canMerge(*seed)) {
otherPolygon->merge(*seed);
if (seedInArray) {
int* IGNORED_ADDRESS = NULL;
// remove this otherOtherPolygon for our polygon array
_polygonCount = removeFromSortedArrays((void*)seed,
(void**)_polygons, _polygonDistances, IGNORED_ADDRESS,
_polygonCount, _polygonArraySize);
_totalPolygons--;
}
// clean up
if (_managePolygons) {
delete seed;
}
// Now run again using our newly merged polygon as the seed
mergeItemsInArray(otherPolygon, true);
return true;
}
}
return false;
}
// just handles storage in the array, doesn't test for occlusion or
// determining if this is the correct map to store in!
void CoverageRegion::storeInArray(OctreeProjectedPolygon* polygon) {
_currentCoveredBounds.explandToInclude(polygon->getBoundingBox());
// Before we actually store this polygon in the array, check to see if this polygon can be merged to any of the existing
// polygons already in our array.
if (mergeItemsInArray(polygon, false)) {
return; // exit early
}
// only after we attempt to merge!
_totalPolygons++;
if (_polygonArraySize < _polygonCount + 1) {
growPolygonArray();
}
// As an experiment we're going to see if we get an improvement by storing the polygons in coverage area sorted order
// this means the bigger polygons are earlier in the array. We should have a higher probability of being occluded earlier
// in the list. We still check to see if the polygon is "in front" of the target polygon before we test occlusion. Since
// sometimes things come out of order.
const bool SORT_BY_SIZE = false;
const int IGNORED = 0;
int* IGNORED_ADDRESS = NULL;
if (SORT_BY_SIZE) {
// This old code assumes that polygons will always be added in z-buffer order, but that doesn't seem to
// be a good assumption. So instead, we will need to sort this by distance. Use a binary search to find the
// insertion point in this array, and shift the array accordingly
float area = polygon->getBoundingBox().area();
float reverseArea = 4.0f - area;
_polygonCount = insertIntoSortedArrays((void*)polygon, reverseArea, IGNORED,
(void**)_polygons, _polygonSizes, IGNORED_ADDRESS,
_polygonCount, _polygonArraySize);
} else {
_polygonCount = insertIntoSortedArrays((void*)polygon, polygon->getDistance(), IGNORED,
(void**)_polygons, _polygonDistances, IGNORED_ADDRESS,
_polygonCount, _polygonArraySize);
}
// Debugging and Optimization Tuning code.
if (_polygonCount > _maxPolygonsUsed) {
_maxPolygonsUsed = _polygonCount;
}
}
CoverageMapStorageResult CoverageRegion::checkRegion(OctreeProjectedPolygon* polygon, const BoundingBox& polygonBox, bool storeIt) {
CoverageMapStorageResult result = DOESNT_FIT;
if (_isRoot || _myBoundingBox.contains(polygonBox)) {
result = NOT_STORED; // if we got here, then we DO fit...
// only actually check the polygons if this polygon is in the covered bounds for this region
if (!_currentCoveredBounds.contains(polygonBox)) {
_regionSkips += _polygonCount;
} else {
// check to make sure this polygon isn't occluded by something at this level
for (int i = 0; i < _polygonCount; i++) {
OctreeProjectedPolygon* polygonAtThisLevel = _polygons[i];
// Check to make sure that the polygon in question is "behind" the polygon in the list
// otherwise, we don't need to test it's occlusion (although, it means we've potentially
// added an item previously that may be occluded??? Is that possible? Maybe not, because two
// voxels can't have the exact same outline. So one occludes the other, they can't both occlude
// each other.
_occlusionTests++;
if (polygonAtThisLevel->occludes(*polygon)) {
// if the polygonAtThisLevel is actually behind the one we're inserting, then we don't
// want to report our inserted one as occluded, but we do want to add our inserted one.
if (polygonAtThisLevel->getDistance() >= polygon->getDistance()) {
_outOfOrderPolygon++;
if (storeIt) {
if (polygon->getBoundingBox().area() > CoverageMap::MINIMUM_POLYGON_AREA_TO_STORE) {
if (getPolygonCount() < MAX_POLYGONS_PER_REGION) {
storeInArray(polygon);
return STORED;
} else {
CoverageRegion::_regionFullSkips++;
return NOT_STORED;
}
} else {
_tooSmallSkips++;
return NOT_STORED;
}
} else {
return NOT_STORED;
}
}
// this polygon is occluded by a closer polygon, so don't store it, and let the caller know
return OCCLUDED;
}
}
}
}
return result;
}

View file

@ -1,120 +0,0 @@
//
// CoverageMap.h
// libraries/octree/src
//
// Created by Brad Hefta-Gaub on 06/11/13.
// Copyright 2013 High Fidelity, Inc.
//
// 2D CoverageMap Quad tree for storage of OctreeProjectedPolygons
//
// 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_CoverageMap_h
#define hifi_CoverageMap_h
#include <glm/glm.hpp>
#include "OctreeProjectedPolygon.h"
typedef enum {STORED, OCCLUDED, DOESNT_FIT, NOT_STORED} CoverageMapStorageResult;
typedef enum {TOP_HALF, BOTTOM_HALF, LEFT_HALF, RIGHT_HALF, REMAINDER} RegionName;
class CoverageRegion {
public:
CoverageRegion(BoundingBox boundingBox, bool isRoot, bool managePolygons = true, RegionName regionName = REMAINDER);
~CoverageRegion();
CoverageMapStorageResult checkRegion(OctreeProjectedPolygon* polygon, const BoundingBox& polygonBox, bool storeIt);
void storeInArray(OctreeProjectedPolygon* polygon);
bool contains(const BoundingBox& box) const { return _myBoundingBox.contains(box); };
void erase(); // erase the coverage region
static int _maxPolygonsUsed;
static int _totalPolygons;
static int _occlusionTests;
static int _regionSkips;
static int _tooSmallSkips;
static int _regionFullSkips;
static int _outOfOrderPolygon;
static int _clippedPolygons;
const char* getRegionName() const;
int getPolygonCount() const { return _polygonCount; };
OctreeProjectedPolygon* getPolygon(int index) const { return _polygons[index]; };
private:
void init();
bool _isRoot; // is this map the root, if so, it never returns DOESNT_FIT
BoundingBox _myBoundingBox;
BoundingBox _currentCoveredBounds; // area in this region currently covered by some polygon
bool _managePolygons; // will the coverage map delete the polygons on destruct
RegionName _regionName;
int _polygonCount; // how many polygons at this level
int _polygonArraySize; // how much room is there to store polygons at this level
OctreeProjectedPolygon** _polygons;
// we will use one or the other of these depending on settings in the code.
float* _polygonDistances;
float* _polygonSizes;
void growPolygonArray();
static const int DEFAULT_GROW_SIZE = 100;
bool mergeItemsInArray(OctreeProjectedPolygon* seed, bool seedInArray);
};
class CoverageMap {
public:
static const int NUMBER_OF_CHILDREN = 4;
static const bool NOT_ROOT=false;
static const bool IS_ROOT=true;
static const BoundingBox ROOT_BOUNDING_BOX;
static const float MINIMUM_POLYGON_AREA_TO_STORE;
CoverageMap(BoundingBox boundingBox = ROOT_BOUNDING_BOX, bool isRoot = IS_ROOT, bool managePolygons = true);
~CoverageMap();
CoverageMapStorageResult checkMap(OctreeProjectedPolygon* polygon, bool storeIt = true);
BoundingBox getChildBoundingBox(int childIndex);
void erase(); // erase the coverage map
void printStats();
static bool wantDebugging;
int getPolygonCount() const;
OctreeProjectedPolygon* getPolygon(int index) const;
CoverageMap* getChild(int childIndex) const { return _childMaps[childIndex]; };
private:
void init();
bool _isRoot; // is this map the root, if so, it never returns DOESNT_FIT
BoundingBox _myBoundingBox;
CoverageMap* _childMaps[NUMBER_OF_CHILDREN];
bool _managePolygons; // will the coverage map delete the polygons on destruct
// We divide the map into 5 regions representing each possible half of the map, and the whole map
// this allows us to keep the list of polygons shorter
CoverageRegion _topHalf;
CoverageRegion _bottomHalf;
CoverageRegion _leftHalf;
CoverageRegion _rightHalf;
CoverageRegion _remainder;
static int _mapCount;
static int _checkMapRootCalls;
static int _notAllInView;
};
#endif // hifi_CoverageMap_h

View file

@ -1,251 +0,0 @@
//
// CoverageMapV2.cpp
// libraries/octree/src
//
// Created by Brad Hefta-Gaub on 06/11/13.
// Copyright 2013 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 <algorithm>
#include <cstring>
#include <QtCore/QDebug>
#include <SharedUtil.h>
#include "OctreeLogging.h"
#include "CoverageMapV2.h"
int CoverageMapV2::_mapCount = 0;
int CoverageMapV2::_checkMapRootCalls = 0;
int CoverageMapV2::_notAllInView = 0;
bool CoverageMapV2::wantDebugging = false;
const BoundingBox CoverageMapV2::ROOT_BOUNDING_BOX = BoundingBox(glm::vec2(-1.0f,-1.0f), glm::vec2(2.0f,2.0f));
// Coverage Map's polygon coordinates are from -1 to 1 in the following mapping to screen space.
//
// (0,0) (windowWidth, 0)
// -1,1 1,1
// +-----------------------+
// | | |
// | | |
// | -1,0 | |
// |-----------+-----------|
// | 0,0 |
// | | |
// | | |
// | | |
// +-----------------------+
// -1,-1 1,-1
// (0,windowHeight) (windowWidth,windowHeight)
//
// Choosing a minimum sized polygon. Since we know a typical window is approximately 1500 pixels wide
// then a pixel on our screen will be ~ 2.0/1500 or 0.0013 "units" wide, similarly pixels are typically
// about that tall as well. If we say that polygons should be at least 10x10 pixels to be considered "big enough"
// then we can calculate a reasonable polygon area
const int TYPICAL_SCREEN_WIDTH_IN_PIXELS = 1500;
const int MINIMUM_POLYGON_AREA_SIDE_IN_PIXELS = 10;
const float TYPICAL_SCREEN_PIXEL_WIDTH = (2.0f / TYPICAL_SCREEN_WIDTH_IN_PIXELS);
const float CoverageMapV2::MINIMUM_POLYGON_AREA_TO_STORE = (TYPICAL_SCREEN_PIXEL_WIDTH * MINIMUM_POLYGON_AREA_SIDE_IN_PIXELS) *
(TYPICAL_SCREEN_PIXEL_WIDTH * MINIMUM_POLYGON_AREA_SIDE_IN_PIXELS);
const float CoverageMapV2::NOT_COVERED = FLT_MAX;
const float CoverageMapV2::MINIMUM_OCCLUSION_CHECK_AREA = MINIMUM_POLYGON_AREA_TO_STORE/10.0f; // one quarter the size of poly
CoverageMapV2::CoverageMapV2(BoundingBox boundingBox, bool isRoot, bool isCovered, float coverageDistance) :
_isRoot(isRoot),
_myBoundingBox(boundingBox),
_isCovered(isCovered),
_coveredDistance(coverageDistance)
{
_mapCount++;
init();
};
CoverageMapV2::~CoverageMapV2() {
erase();
};
void CoverageMapV2::erase() {
for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
if (_childMaps[i]) {
delete _childMaps[i];
_childMaps[i] = NULL;
}
}
if (_isRoot && wantDebugging) {
qCDebug(octree, "CoverageMapV2 last to be deleted...");
qCDebug(octree, "MINIMUM_POLYGON_AREA_TO_STORE=%f", (double)MINIMUM_POLYGON_AREA_TO_STORE);
qCDebug(octree, "_mapCount=%d",_mapCount);
qCDebug(octree, "_checkMapRootCalls=%d",_checkMapRootCalls);
qCDebug(octree, "_notAllInView=%d",_notAllInView);
_mapCount = 0;
_checkMapRootCalls = 0;
_notAllInView = 0;
}
}
void CoverageMapV2::init() {
memset(_childMaps,0,sizeof(_childMaps));
}
// 0 = bottom, left
// 1 = bottom, right
// 2 = top, left
// 3 = top, right
BoundingBox CoverageMapV2::getChildBoundingBox(int childIndex) {
const int RIGHT_BIT = 1;
const int TOP_BIT = 2;
// initialize to our corner, and half our size
BoundingBox result(_myBoundingBox.corner,_myBoundingBox.size/2.0f);
// if our "right" bit is set, then add size.x to the corner
if ((childIndex & RIGHT_BIT) == RIGHT_BIT) {
result.corner.x += result.size.x;
}
// if our "top" bit is set, then add size.y to the corner
if ((childIndex & TOP_BIT) == TOP_BIT) {
result.corner.y += result.size.y;
}
return result;
}
// possible results = STORED/NOT_STORED, OCCLUDED, DOESNT_FIT
CoverageMapV2StorageResult CoverageMapV2::checkMap(const OctreeProjectedPolygon* polygon, bool storeIt) {
assert(_isRoot); // you can only call this on the root map!!!
_checkMapRootCalls++;
// short circuit: if we're the root node (only case we're here), and we're covered, and this polygon is deeper than our
// covered depth, then this polygon is occluded!
if (_isCovered && _coveredDistance < polygon->getDistance()) {
return V2_OCCLUDED;
}
// short circuit: we don't handle polygons that aren't all in view, so, if the polygon in question is
// not in view, then we just discard it with a DOESNT_FIT, this saves us time checking values later.
if (!polygon->getAllInView()) {
_notAllInView++;
return V2_DOESNT_FIT;
}
// Here's where we recursively check the polygon against the coverage map. We need to maintain two pieces of state.
// The first state is: have we seen at least one "fully occluded" map items. If we haven't then we don't track the covered
// state of the polygon.
// The second piece of state is: Are all of our "fully occluded" map items "covered". If even one of these occluded map
// items is not covered, then our polygon is not covered.
bool seenOccludedMapNodes = false;
bool allOccludedMapNodesCovered = false;
recurseMap(polygon, storeIt, seenOccludedMapNodes, allOccludedMapNodesCovered);
// Ok, no matter how we were called, if all our occluded map nodes are covered, then we know this polygon
// is occluded, otherwise, we will report back to the caller about whether or not we stored the polygon
if (allOccludedMapNodesCovered) {
return V2_OCCLUDED;
}
if (storeIt) {
return V2_STORED; // otherwise report that we STORED it
}
return V2_NOT_STORED; // unless we weren't asked to store it, then we didn't
}
void CoverageMapV2::recurseMap(const OctreeProjectedPolygon* polygon, bool storeIt,
bool& seenOccludedMapNodes, bool& allOccludedMapNodesCovered) {
// if we are really small, then we act like we don't intersect, this allows us to stop
// recusing as we get to the smalles edge of the polygon
if (_myBoundingBox.area() < MINIMUM_OCCLUSION_CHECK_AREA) {
return; // stop recursion, we're done!
}
// Determine if this map node intersects the polygon and/or is fully covered by the polygon
// There are a couple special cases: If we're the root, we are assumed to intersect with all
// polygons. Also, any map node that is fully occluded also intersects.
bool nodeIsCoveredByPolygon = polygon->occludes(_myBoundingBox);
bool nodeIsIntersectedByPolygon = nodeIsCoveredByPolygon || _isRoot || polygon->intersects(_myBoundingBox);
// If we don't intersect, then we can just return, we're done recursing
if (!nodeIsIntersectedByPolygon) {
return; // stop recursion, we're done!
}
// At this point, we know our node intersects with the polygon. If this node is covered, then we want to treat it
// as if the node was fully covered, because this allows us to short circuit further recursion...
if (_isCovered && _coveredDistance < polygon->getDistance()) {
nodeIsCoveredByPolygon = true; // fake it till you make it
}
// If this node in the map is fully covered by our polygon, then we don't need to recurse any further, but
// we do need to do some bookkeeping.
if (nodeIsCoveredByPolygon) {
// If this is the very first fully covered node we've seen, then we're initialize our allOccludedMapNodesCovered
// to be our current covered state. This has the following effect: if this node isn't already covered, then by
// definition, we know that at least one node for this polygon isn't covered, and therefore we aren't fully covered.
if (!seenOccludedMapNodes) {
allOccludedMapNodesCovered = (_isCovered && _coveredDistance < polygon->getDistance());
// We need to mark that we've seen at least one node of our polygon! ;)
seenOccludedMapNodes = true;
} else {
// If this is our second or later node of our polygon, then we need to track our allOccludedMapNodesCovered state
allOccludedMapNodesCovered = allOccludedMapNodesCovered &&
(_isCovered && _coveredDistance < polygon->getDistance());
}
// if we're in store mode then we want to record that this node is covered.
if (storeIt) {
_isCovered = true;
// store the minimum distance of our previous known distance, or our current polygon's distance. This is because
// we know that we're at least covered at this distance, but if we had previously identified that we're covered
// at a shallower distance, then we want to maintain that distance
_coveredDistance = std::min(polygon->getDistance(), _coveredDistance);
// Note: this might be a good chance to delete child maps, but we're not going to do that at this point because
// we're trying to maintain the known distances in the lower portion of the tree.
}
// and since this node of the quad map is covered, we can safely stop recursion. because we know all smaller map
// nodes will also be covered.
return;
}
// If we got here, then it means we know that this node is not fully covered by the polygon, but it does intersect
// with the polygon.
// Another case is that we aren't yet marked as covered, and so we should recurse and process smaller quad tree nodes.
// Note: we use this to determine if we can collapse the child quad trees and mark this node as covered
bool allChildrenOccluded = true;
float maxChildCoveredDepth = NOT_COVERED;
for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
BoundingBox childMapBoundingBox = getChildBoundingBox(i);
// if no child map exists yet, then create it
if (!_childMaps[i]) {
// children get created with the coverage state of their parent.
_childMaps[i] = new CoverageMapV2(childMapBoundingBox, NOT_ROOT, _isCovered, _coveredDistance);
}
_childMaps[i]->recurseMap(polygon, storeIt, seenOccludedMapNodes, allOccludedMapNodesCovered);
// if so far, all of our children are covered, then record our furthest coverage distance
if (allChildrenOccluded && _childMaps[i]->_isCovered) {
maxChildCoveredDepth = std::max(maxChildCoveredDepth, _childMaps[i]->_coveredDistance);
} else {
// otherwise, at least one of our children is not covered, so not all are covered
allChildrenOccluded = false;
}
}
// if all the children are covered, this makes our quad tree "shallower" because it records that
// entire quad is covered, it uses the "furthest" z-order so that if a shalower polygon comes through
// we won't assume its occluded
if (allChildrenOccluded && storeIt) {
_isCovered = true;
_coveredDistance = maxChildCoveredDepth;
}
// normal exit case... return...
}

View file

@ -1,72 +0,0 @@
//
// CoverageMapV2.h
// libraries/octree/src
//
// Created by Brad Hefta-Gaub on 06/11/13.
// Copyright 2013 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_CoverageMapV2_h
#define hifi_CoverageMapV2_h
#include <glm/glm.hpp>
#include "OctreeProjectedPolygon.h"
typedef enum {
V2_DOESNT_FIT, V2_STORED, V2_NOT_STORED,
V2_INTERSECT, V2_NO_INTERSECT,
V2_OCCLUDED, V2_NOT_OCCLUDED
} CoverageMapV2StorageResult;
class CoverageMapV2 {
public:
static const int NUMBER_OF_CHILDREN = 4;
static const bool NOT_ROOT = false;
static const bool IS_ROOT = true;
static const BoundingBox ROOT_BOUNDING_BOX;
static const float MINIMUM_POLYGON_AREA_TO_STORE;
static const float NOT_COVERED;
static const float MINIMUM_OCCLUSION_CHECK_AREA;
static bool wantDebugging;
CoverageMapV2(BoundingBox boundingBox = ROOT_BOUNDING_BOX, bool isRoot = IS_ROOT,
bool isCovered = false, float coverageDistance = NOT_COVERED);
~CoverageMapV2();
CoverageMapV2StorageResult checkMap(const OctreeProjectedPolygon* polygon, bool storeIt = true);
BoundingBox getChildBoundingBox(int childIndex);
const BoundingBox& getBoundingBox() const { return _myBoundingBox; };
CoverageMapV2* getChild(int childIndex) const { return _childMaps[childIndex]; };
bool isCovered() const { return _isCovered; };
void erase(); // erase the coverage map
void render();
private:
void recurseMap(const OctreeProjectedPolygon* polygon, bool storeIt,
bool& seenOccludedMapNodes, bool& allOccludedMapNodesCovered);
void init();
bool _isRoot;
BoundingBox _myBoundingBox;
CoverageMapV2* _childMaps[NUMBER_OF_CHILDREN];
bool _isCovered;
float _coveredDistance;
static int _mapCount;
static int _checkMapRootCalls;
static int _notAllInView;
};
#endif // hifi_CoverageMapV2_h

View file

@ -41,7 +41,6 @@
#include <PathUtils.h>
#include <Gzip.h>
#include "CoverageMap.h"
#include "OctreeConstants.h"
#include "OctreeElementBag.h"
#include "Octree.h"
@ -1103,31 +1102,6 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element,
params.stopReason = EncodeBitstreamParams::NO_CHANGE;
return bytesAtThisLevel;
}
// If the user also asked for occlusion culling, check if this element is occluded, but only if it's not a leaf.
// leaf occlusion is handled down below when we check child nodes
if (params.wantOcclusionCulling && !element->isLeaf()) {
OctreeProjectedPolygon* voxelPolygon =
new OctreeProjectedPolygon(params.viewFrustum->getProjectedPolygon(element->getAACube()));
// In order to check occlusion culling, the shadow has to be "all in view" otherwise, we will ignore occlusion
// culling and proceed as normal
if (voxelPolygon->getAllInView()) {
CoverageMapStorageResult result = params.map->checkMap(voxelPolygon, false);
delete voxelPolygon; // cleanup
if (result == OCCLUDED) {
if (params.stats) {
params.stats->skippedOccluded(element);
}
params.stopReason = EncodeBitstreamParams::OCCLUDED;
return bytesAtThisLevel;
}
} else {
// If this shadow wasn't "all in view" then we ignored it for occlusion culling, but
// we do need to clean up memory and proceed as normal...
delete voxelPolygon;
}
}
}
bool keepDiggingDeeper = true; // Assuming we're in view we have a great work ethic, we're always ready for more!
@ -1190,20 +1164,10 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element,
}
}
if (params.wantOcclusionCulling) {
if (childElement) {
float distance = params.viewFrustum ? childElement->distanceToCamera(*params.viewFrustum) : 0;
currentCount = insertOctreeElementIntoSortedArrays(childElement, distance, i,
sortedChildren, (float*)&distancesToChildren,
(int*)&indexOfChildren, currentCount, NUMBER_OF_CHILDREN);
}
} else {
sortedChildren[i] = childElement;
indexOfChildren[i] = i;
distancesToChildren[i] = 0.0f;
currentCount++;
}
sortedChildren[i] = childElement;
indexOfChildren[i] = i;
distancesToChildren[i] = 0.0f;
currentCount++;
// track stats
// must check childElement here, because it could be we got here with no childElement
@ -1255,36 +1219,6 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element,
bool childIsOccluded = false; // assume it's not occluded
// If the user also asked for occlusion culling, check if this element is occluded
if (params.wantOcclusionCulling && childElement->isLeaf()) {
// Don't check occlusion here, just add them to our distance ordered array...
// FIXME params.ViewFrustum is used here, but later it is checked against nullptr.
OctreeProjectedPolygon* voxelPolygon = new OctreeProjectedPolygon(
params.viewFrustum->getProjectedPolygon(childElement->getAACube()));
// In order to check occlusion culling, the shadow has to be "all in view" otherwise, we ignore occlusion
// culling and proceed as normal
if (voxelPolygon->getAllInView()) {
CoverageMapStorageResult result = params.map->checkMap(voxelPolygon, true);
// In all cases where the shadow wasn't stored, we need to free our own memory.
// In the case where it is stored, the CoverageMap will free memory for us later.
if (result != STORED) {
delete voxelPolygon;
}
// If while attempting to add this voxel's shadow, we determined it was occluded, then
// we don't need to process it further and we can exit early.
if (result == OCCLUDED) {
childIsOccluded = true;
}
} else {
delete voxelPolygon;
}
} // wants occlusion culling & isLeaf()
bool shouldRender = !params.viewFrustum
? true
: childElement->calculateShouldRender(params.viewFrustum,
@ -1613,33 +1547,6 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element,
} // end if (childTreeBytesOut == 0)
} // end if (oneAtBit(childrenExistInPacketBits, originalIndex))
} // end for
// reshuffle here...
if (continueThisLevel && params.wantOcclusionCulling) {
unsigned char tempReshuffleBuffer[MAX_OCTREE_UNCOMRESSED_PACKET_SIZE];
unsigned char* tempBufferTo = &tempReshuffleBuffer[0]; // this is our temporary destination
// iterate through our childrenExistInPacketBits, these will be the sections of the packet that we copied subTree
// details into. Unfortunately, they're in distance sorted order, not original index order. we need to put them
// back into original distance order
for (int originalIndex = 0; originalIndex < NUMBER_OF_CHILDREN; originalIndex++) {
if (oneAtBit(childrenExistInPacketBits, originalIndex)) {
int thisSliceSize = recursiveSliceSizes[originalIndex];
const unsigned char* thisSliceStarts = recursiveSliceStarts[originalIndex];
memcpy(tempBufferTo, thisSliceStarts, thisSliceSize);
tempBufferTo += thisSliceSize;
}
}
// now that all slices are back in the correct order, copy them to the correct output buffer
continueThisLevel = packetData->updatePriorBytes(firstRecursiveSliceOffset, &tempReshuffleBuffer[0], allSlicesSize);
if (!continueThisLevel) {
qCDebug(octree) << "WARNING UNEXPECTED CASE: Failed to update recursive slice!!!";
qCDebug(octree) << "This is not expected!!!! -- continueThisLevel=FALSE....";
}
}
} // end keepDiggingDeeper
// If we made it this far, then we've written all of our child data... if this element is the root

View file

@ -28,7 +28,6 @@
#include "OctreePacketData.h"
#include "OctreeSceneStats.h"
class CoverageMap;
class ReadBitstreamToTreeParams;
class Octree;
class OctreeElement;
@ -57,8 +56,6 @@ const bool NO_COLOR = false;
const bool WANT_COLOR = true;
const bool COLLAPSE_EMPTY_TREE = true;
const bool DONT_COLLAPSE = false;
const bool NO_OCCLUSION_CULLING = false;
const bool WANT_OCCLUSION_CULLING = true;
const int DONT_CHOP = 0;
const int NO_BOUNDARY_ADJUST = 0;
@ -80,13 +77,11 @@ public:
int chopLevels;
bool deltaViewFrustum;
const ViewFrustum* lastViewFrustum;
bool wantOcclusionCulling;
int boundaryLevelAdjust;
float octreeElementSizeScale;
quint64 lastViewFrustumSent;
bool forceSendScene;
OctreeSceneStats* stats;
CoverageMap* map;
JurisdictionMap* jurisdictionMap;
OctreeElementExtraEncodeData* extraEncodeData;
@ -113,8 +108,6 @@ public:
int chopLevels = 0,
bool deltaViewFrustum = false,
const ViewFrustum* lastViewFrustum = IGNORE_VIEW_FRUSTUM,
bool wantOcclusionCulling = NO_OCCLUSION_CULLING,
CoverageMap* map = IGNORE_COVERAGE_MAP,
int boundaryLevelAdjust = NO_BOUNDARY_ADJUST,
float octreeElementSizeScale = DEFAULT_OCTREE_SIZE_SCALE,
quint64 lastViewFrustumSent = IGNORE_LAST_SENT,
@ -130,13 +123,11 @@ public:
chopLevels(chopLevels),
deltaViewFrustum(deltaViewFrustum),
lastViewFrustum(lastViewFrustum),
wantOcclusionCulling(wantOcclusionCulling),
boundaryLevelAdjust(boundaryLevelAdjust),
octreeElementSizeScale(octreeElementSizeScale),
lastViewFrustumSent(lastViewFrustumSent),
forceSendScene(forceSendScene),
stats(stats),
map(map),
jurisdictionMap(jurisdictionMap),
extraEncodeData(extraEncodeData),
stopReason(UNKNOWN)

View file

@ -53,7 +53,6 @@ void OctreeHeadlessViewer::queryOctree() {
_octreeQuery.setWantLowResMoving(true);
_octreeQuery.setWantColor(true);
_octreeQuery.setWantDelta(true);
_octreeQuery.setWantOcclusionCulling(false);
_octreeQuery.setWantCompression(true); // TODO: should be on by default
_octreeQuery.setCameraPosition(_viewFrustum.getPosition());

View file

@ -43,7 +43,6 @@ int OctreeQuery::getBroadcastData(unsigned char* destinationBuffer) {
if (_wantLowResMoving) { setAtBit(bitItems, WANT_LOW_RES_MOVING_BIT); }
if (_wantColor) { setAtBit(bitItems, WANT_COLOR_AT_BIT); }
if (_wantDelta) { setAtBit(bitItems, WANT_DELTA_AT_BIT); }
if (_wantOcclusionCulling) { setAtBit(bitItems, WANT_OCCLUSION_CULLING_BIT); }
if (_wantCompression) { setAtBit(bitItems, WANT_COMPRESSION); }
*destinationBuffer++ = bitItems;
@ -86,7 +85,6 @@ int OctreeQuery::parseData(NLPacket& packet) {
_wantLowResMoving = oneAtBit(bitItems, WANT_LOW_RES_MOVING_BIT);
_wantColor = oneAtBit(bitItems, WANT_COLOR_AT_BIT);
_wantDelta = oneAtBit(bitItems, WANT_DELTA_AT_BIT);
_wantOcclusionCulling = oneAtBit(bitItems, WANT_OCCLUSION_CULLING_BIT);
_wantCompression = oneAtBit(bitItems, WANT_COMPRESSION);
// desired Max Octree PPS

View file

@ -37,7 +37,7 @@ typedef unsigned long long quint64;
const int WANT_LOW_RES_MOVING_BIT = 0;
const int WANT_COLOR_AT_BIT = 1;
const int WANT_DELTA_AT_BIT = 2;
const int WANT_OCCLUSION_CULLING_BIT = 3;
const int UNUSED_BIT = 3; // unused... available for new feature
const int WANT_COMPRESSION = 4; // 5th bit
class OctreeQuery : public NodeData {
@ -74,7 +74,6 @@ public:
bool getWantColor() const { return _wantColor; }
bool getWantDelta() const { return _wantDelta; }
bool getWantLowResMoving() const { return _wantLowResMoving; }
bool getWantOcclusionCulling() const { return _wantOcclusionCulling; }
bool getWantCompression() const { return _wantCompression; }
int getMaxQueryPacketsPerSecond() const { return _maxQueryPPS; }
float getOctreeSizeScale() const { return _octreeElementSizeScale; }
@ -84,7 +83,6 @@ public slots:
void setWantLowResMoving(bool wantLowResMoving) { _wantLowResMoving = wantLowResMoving; }
void setWantColor(bool wantColor) { _wantColor = wantColor; }
void setWantDelta(bool wantDelta) { _wantDelta = wantDelta; }
void setWantOcclusionCulling(bool wantOcclusionCulling) { _wantOcclusionCulling = wantOcclusionCulling; }
void setWantCompression(bool wantCompression) { _wantCompression = wantCompression; }
void setMaxQueryPacketsPerSecond(int maxQueryPPS) { _maxQueryPPS = maxQueryPPS; }
void setOctreeSizeScale(float octreeSizeScale) { _octreeElementSizeScale = octreeSizeScale; }
@ -104,7 +102,6 @@ protected:
bool _wantColor = true;
bool _wantDelta = true;
bool _wantLowResMoving = true;
bool _wantOcclusionCulling = false;
bool _wantCompression = false;
int _maxQueryPPS = DEFAULT_MAX_OCTREE_PPS;
float _octreeElementSizeScale = DEFAULT_OCTREE_SIZE_SCALE; /// used for LOD calculations