Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Philip Rosedale 2013-05-08 17:27:31 -07:00
commit 08c48bf6a7
8 changed files with 130 additions and 23 deletions

View file

@ -139,22 +139,22 @@ void VoxelSystem::setupNewVoxelsForDrawing() {
double start = usecTimestampNow();
double sinceLastTime = (start - _setupNewVoxelsForDrawingLastFinished) / 1000.0;
if (sinceLastTime <= std::max(_setupNewVoxelsForDrawingLastElapsed,SIXTY_FPS_IN_MILLISECONDS)) {
if (sinceLastTime <= std::max(_setupNewVoxelsForDrawingLastElapsed, SIXTY_FPS_IN_MILLISECONDS)) {
return; // bail early, it hasn't been long enough since the last time we ran
}
double sinceLastViewCulling = (start - _lastViewCulling) / 1000.0;
// If the view frustum has changed, since last time, then remove nodes that are out of view
if ((sinceLastViewCulling >= VIEW_CULLING_RATE_IN_MILLISECONDS) && hasViewChanged()) {
if ((sinceLastViewCulling >= std::max(_lastViewCullingElapsed, VIEW_CULLING_RATE_IN_MILLISECONDS)) && hasViewChanged()) {
_lastViewCulling = start;
removeOutOfView();
double endViewCulling = usecTimestampNow();
_lastViewCullingElapsed = (endViewCulling - start) / 1000.0;
}
if (_tree->isDirty()) {
PerformanceWarning warn(_renderWarningsOn, "calling... newTreeToArrays()");
_callsToTreesToArrays++;
if (_alwaysRenderFullVBO) {
_voxelsInWriteArrays = 0; // reset our VBO
}
@ -171,7 +171,7 @@ void VoxelSystem::setupNewVoxelsForDrawing() {
copyWrittenDataToReadArrays();
double end = usecTimestampNow();
double elapsedmsec = (end - start)/1000.0;
double elapsedmsec = (end - start) / 1000.0;
_setupNewVoxelsForDrawingLastFinished = end;
_setupNewVoxelsForDrawingLastElapsed = elapsedmsec;
}
@ -294,7 +294,7 @@ void VoxelSystem::init() {
_callsToTreesToArrays = 0;
_setupNewVoxelsForDrawingLastFinished = 0;
_setupNewVoxelsForDrawingLastElapsed = 0;
_lastViewCulling = 0;
_lastViewCullingElapsed = _lastViewCulling = 0;
// When we change voxels representations in the arrays, we'll update this
_voxelsDirty = false;
@ -583,17 +583,71 @@ void VoxelSystem::falseColorizeDistanceFromView(ViewFrustum* viewFrustum) {
setupNewVoxelsForDrawing();
}
// combines the removeOutOfView args into a single class
class removeOutOfViewArgs {
public:
VoxelSystem* thisVoxelSystem;
VoxelNodeBag dontRecurseBag;
unsigned long nodesScanned;
unsigned long nodesRemoved;
unsigned long nodesInside;
unsigned long nodesIntersect;
unsigned long nodesOutside;
removeOutOfViewArgs(VoxelSystem* voxelSystem) :
thisVoxelSystem(voxelSystem),
dontRecurseBag(),
nodesScanned(0),
nodesRemoved(0),
nodesInside(0),
nodesIntersect(0),
nodesOutside(0)
{ }
};
// "Remove" voxels from the tree that are not in view. We don't actually delete them,
// we remove them from the tree and place them into a holding area for later deletion
bool VoxelSystem::removeOutOfViewOperation(VoxelNode* node, void* extraData) {
VoxelSystem* thisVoxelSystem = (VoxelSystem*) extraData;
_nodeCount++;
removeOutOfViewArgs* args = (removeOutOfViewArgs*)extraData;
// If our node was previously added to the don't recurse bag, then return false to
// stop the further recursion. This means that the whole node and it's children are
// known to be in view, so don't recurse them
if (args->dontRecurseBag.contains(node)) {
args->dontRecurseBag.remove(node);
return false; // stop recursion
}
VoxelSystem* thisVoxelSystem = args->thisVoxelSystem;
args->nodesScanned++;
// Need to operate on our child nodes, so we can remove them
for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {
VoxelNode* childNode = node->getChildAtIndex(i);
if (childNode && !childNode->isInView(*thisVoxelSystem->_viewFrustum)) {
node->removeChildAtIndex(i);
thisVoxelSystem->_removedVoxels.insert(childNode);
if (childNode) {
ViewFrustum::location inFrustum = childNode->inFrustum(*thisVoxelSystem->_viewFrustum);
switch (inFrustum) {
case ViewFrustum::OUTSIDE: {
args->nodesOutside++;
args->nodesRemoved++;
node->removeChildAtIndex(i);
thisVoxelSystem->_removedVoxels.insert(childNode);
// by removing the child, it will not get recursed!
} break;
case ViewFrustum::INSIDE: {
// if the child node is fully INSIDE the view, then there's no need to recurse it
// because we know all it's children will also be in the view, so we want to
// tell the caller to NOT recurse this child
args->nodesInside++;
args->dontRecurseBag.insert(childNode);
} break;
case ViewFrustum::INTERSECT: {
// if the child node INTERSECTs the view, then we don't want to remove it because
// it is at least partially in view. But we DO want to recurse the children because
// some of them may not be in view... nothing specifically to do, just keep iterating
// the children
args->nodesIntersect++;
} break;
}
}
}
return true; // keep going!
@ -609,7 +663,14 @@ bool VoxelSystem::hasViewChanged() {
}
void VoxelSystem::removeOutOfView() {
PerformanceWarning warn(_renderWarningsOn, "removeOutOfView()"); // would like to include removedCount, _nodeCount, _removedVoxels.count()
_nodeCount = 0;
_tree->recurseTreeWithOperation(removeOutOfViewOperation,(void*)this);
PerformanceWarning warn(_renderWarningsOn, "removeOutOfView()");
removeOutOfViewArgs args(this);
_tree->recurseTreeWithOperation(removeOutOfViewOperation,(void*)&args);
if (_renderWarningsOn) {
printLog("removeOutOfView() scanned=%ld removed=%ld inside=%ld intersect=%ld outside=%ld bag.count()=%d \n",
args.nodesScanned, args.nodesRemoved, args.nodesInside,
args.nodesIntersect, args.nodesOutside, args.dontRecurseBag.count()
);
}
}

View file

@ -104,6 +104,7 @@ private:
double _setupNewVoxelsForDrawingLastElapsed;
double _setupNewVoxelsForDrawingLastFinished;
double _lastViewCulling;
double _lastViewCullingElapsed;
GLuint _vboVerticesID;
GLuint _vboNormalsID;

View file

@ -158,12 +158,12 @@ const char* ViewFrustum::debugPlaneName (int plane) const {
}
int ViewFrustum::pointInFrustum(const glm::vec3& point) const {
ViewFrustum::location ViewFrustum::pointInFrustum(const glm::vec3& point) const {
//printf("ViewFrustum::pointInFrustum() point=%f,%f,%f\n",point.x,point.y,point.z);
//dump();
int result = INSIDE;
ViewFrustum::location result = INSIDE;
for(int i=0; i < 6; i++) {
float distance = _planes[i].distance(point);
@ -176,8 +176,8 @@ int ViewFrustum::pointInFrustum(const glm::vec3& point) const {
return(result);
}
int ViewFrustum::sphereInFrustum(const glm::vec3& center, float radius) const {
int result = INSIDE;
ViewFrustum::location ViewFrustum::sphereInFrustum(const glm::vec3& center, float radius) const {
ViewFrustum::location result = INSIDE;
float distance;
for(int i=0; i < 6; i++) {
distance = _planes[i].distance(center);
@ -190,11 +190,11 @@ int ViewFrustum::sphereInFrustum(const glm::vec3& center, float radius) const {
}
int ViewFrustum::boxInFrustum(const AABox& box) const {
ViewFrustum::location ViewFrustum::boxInFrustum(const AABox& box) const {
//printf("ViewFrustum::boxInFrustum() box.corner=%f,%f,%f x=%f\n",
// box.getCorner().x,box.getCorner().y,box.getCorner().z,box.getSize().x);
int result = INSIDE;
ViewFrustum::location result = INSIDE;
for(int i=0; i < 6; i++) {
//printf("plane[%d] -- point(%f,%f,%f) normal(%f,%f,%f) d=%f \n",i,

View file

@ -94,9 +94,9 @@ public:
typedef enum {OUTSIDE, INTERSECT, INSIDE} location;
int pointInFrustum(const glm::vec3& point) const;
int sphereInFrustum(const glm::vec3& center, float radius) const;
int boxInFrustum(const AABox& box) const;
ViewFrustum::location pointInFrustum(const glm::vec3& point) const;
ViewFrustum::location sphereInFrustum(const glm::vec3& center, float radius) const;
ViewFrustum::location boxInFrustum(const AABox& box) const;
// some frustum comparisons
bool matches(const ViewFrustum& compareTo) const;

View file

@ -259,6 +259,12 @@ bool VoxelNode::isInView(const ViewFrustum& viewFrustum) const {
return inView;
}
ViewFrustum::location VoxelNode::inFrustum(const ViewFrustum& viewFrustum) const {
AABox box = _box; // use temporary box so we can scale it
box.scale(TREE_SCALE);
return viewFrustum.boxInFrustum(box);
}
float VoxelNode::distanceToCamera(const ViewFrustum& viewFrustum) const {
glm::vec3 center = _box.getCenter() * (float)TREE_SCALE;
float distanceToVoxelCenter = sqrtf(powf(viewFrustum.getPosition().x - center.x, 2) +

View file

@ -57,6 +57,7 @@ public:
bool isColored() const { return (_trueColor[3]==1); };
bool isInView(const ViewFrustum& viewFrustum) const;
ViewFrustum::location inFrustum(const ViewFrustum& viewFrustum) const;
float distanceToCamera(const ViewFrustum& viewFrustum) const;
bool isLeaf() const;
void printDebugDetails(const char* label) const;

View file

@ -82,3 +82,39 @@ VoxelNode* VoxelNodeBag::extract() {
}
return NULL;
}
bool VoxelNodeBag::contains(VoxelNode* node) {
for (int i = 0; i < _elementsInUse; i++) {
// just compare the pointers... that's good enough
if (_bagElements[i] == node) {
return true; // exit early!!
}
// if we're past where it should be, then it's not here!
if (_bagElements[i] > node) {
return false;
}
}
// if we made it through the entire bag, it's not here!
return false;
}
void VoxelNodeBag::remove(VoxelNode* node) {
int foundAt = -1;
for (int i = 0; i < _elementsInUse; i++) {
// just compare the pointers... that's good enough
if (_bagElements[i] == node) {
foundAt = i;
break;
}
// if we're past where it should be, then it's not here!
if (_bagElements[i] > node) {
break;
}
}
// if we found it, then we need to remove it....
if (foundAt != -1) {
memmove(&_bagElements[foundAt], &_bagElements[foundAt + 1], (_elementsInUse - foundAt) * sizeof(VoxelNode*));
_elementsInUse--;
}
}

View file

@ -28,6 +28,8 @@ public:
void insert(VoxelNode* node); // put a node into the bag
VoxelNode* extract(); // pull a node out of the bag (could come in any order)
bool contains(VoxelNode* node); // is this node in the bag?
void remove(VoxelNode* node); // remove a specific item from the bag
bool isEmpty() const { return (_elementsInUse == 0); };
int count() const { return _elementsInUse; };