Add LOD culling to the server protocol.

- Add LOD/distance culling to VoxelTree:encodeTreeBitstreamRecursion()
  and VoxelTree::searchForColoredNodesRecursion()
- added new levels to boundaryDistanceForRenderLevel()
- added more spheres to the scene to get a better sense of LOD behavior
This commit is contained in:
ZappoMan 2013-04-29 17:38:52 -07:00
parent a638542aa0
commit accda966d5
5 changed files with 90 additions and 30 deletions

View file

@ -55,10 +55,6 @@ VoxelSystem::~VoxelSystem() {
pthread_mutex_destroy(&bufferWriteLock); pthread_mutex_destroy(&bufferWriteLock);
} }
void VoxelSystem::setViewerAvatar(Avatar *newViewerAvatar) {
viewerAvatar = newViewerAvatar;
}
////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////
// Method: VoxelSystem::loadVoxelsFile() // Method: VoxelSystem::loadVoxelsFile()
// Description: Loads HiFidelity encoded Voxels from a binary file. The current file // Description: Loads HiFidelity encoded Voxels from a binary file. The current file
@ -180,7 +176,7 @@ void VoxelSystem::copyWrittenDataToReadArrays() {
int VoxelSystem::treeToArrays(VoxelNode* currentNode, const glm::vec3& nodePosition) { int VoxelSystem::treeToArrays(VoxelNode* currentNode, const glm::vec3& nodePosition) {
int voxelsAdded = 0; int voxelsAdded = 0;
float halfUnitForVoxel = powf(0.5, *currentNode->octalCode) * (0.5 * TREE_SCALE); float halfUnitForVoxel = powf(0.5, *currentNode->octalCode) * (0.5 * TREE_SCALE);
glm::vec3 viewerPosition = viewerAvatar->getPosition(); glm::vec3 viewerPosition = _camera->getPosition(); //_viewerAvatar->getPosition();
// debug LOD code // debug LOD code
glm::vec3 debugNodePosition; glm::vec3 debugNodePosition;

View file

@ -16,6 +16,7 @@
#include <VoxelTree.h> #include <VoxelTree.h>
#include <ViewFrustum.h> #include <ViewFrustum.h>
#include "Avatar.h" #include "Avatar.h"
#include "Camera.h"
#include "Util.h" #include "Util.h"
#include "world.h" #include "world.h"
@ -34,7 +35,8 @@ public:
void render(); void render();
void setVoxelsRendered(int v) {voxelsRendered = v;}; void setVoxelsRendered(int v) {voxelsRendered = v;};
int getVoxelsRendered() {return voxelsRendered;}; int getVoxelsRendered() {return voxelsRendered;};
void setViewerAvatar(Avatar *newViewerAvatar); void setViewerAvatar(Avatar *newViewerAvatar) { _viewerAvatar = newViewerAvatar; };
void setCamera(Camera* newCamera) { _camera = newCamera; };
void loadVoxelsFile(const char* fileName,bool wantColorRandomizer); void loadVoxelsFile(const char* fileName,bool wantColorRandomizer);
void createSphere(float r,float xc, float yc, float zc, float s, bool solid, bool wantColorRandomizer); void createSphere(float r,float xc, float yc, float zc, float s, bool solid, bool wantColorRandomizer);
@ -67,7 +69,8 @@ private:
static float _minDistance; static float _minDistance;
int voxelsRendered; int voxelsRendered;
Avatar *viewerAvatar; Avatar* _viewerAvatar;
Camera* _camera;
VoxelTree *tree; VoxelTree *tree;
GLfloat *readVerticesArray; GLfloat *readVerticesArray;
GLubyte *readColorsArray; GLubyte *readColorsArray;

View file

@ -299,6 +299,7 @@ void init(void)
{ {
voxels.init(); voxels.init();
voxels.setViewerAvatar(&myAvatar); voxels.setViewerAvatar(&myAvatar);
voxels.setCamera(&myCamera);
handControl.setScreenDimensions(WIDTH, HEIGHT); handControl.setScreenDimensions(WIDTH, HEIGHT);

View file

@ -84,9 +84,27 @@ int boundaryDistanceForRenderLevel(unsigned int renderLevel) {
case 7: case 7:
return 12; return 12;
break; break;
default: case 8:
return 10;
break;
case 9:
return 6; return 6;
break; break;
case 10:
return 4.5;
break;
case 11:
return 3;
break;
case 12:
return 2.25;
break;
case 13:
return 1.5;
break;
default:
return 1;
break;
} }
} }
@ -817,10 +835,12 @@ int VoxelTree::searchForColoredNodesRecursion(int maxSearchLevel, int& currentSe
} }
float distance = childNode->distanceToCamera(viewFrustum); float distance = childNode->distanceToCamera(viewFrustum);
inViewCount = insertIntoSortedArrays((void*)childNode, distance, i, if (distance < boundaryDistanceForRenderLevel(*childNode->octalCode + 1)) {
(void**)&inViewChildren, (float*)&distancesToChildren, (int*)&positionOfChildren, inViewCount = insertIntoSortedArrays((void*)childNode, distance, i,
inViewCount, MAX_CHILDREN); (void**)&inViewChildren, (float*)&distancesToChildren, (int*)&positionOfChildren,
inViewCount, MAX_CHILDREN);
}
} }
} }
@ -920,6 +940,14 @@ int VoxelTree::encodeTreeBitstreamRecursion(int maxEncodeLevel, int& currentEnco
return bytesAtThisLevel; return bytesAtThisLevel;
} }
float distance = node->distanceToCamera(viewFrustum);
float boundaryDistance = boundaryDistanceForRenderLevel(*node->octalCode + 1);
// If we're too far away for our render level, then just return
if (distance >= boundaryDistance) {
return bytesAtThisLevel;
}
// If we're at a node that is out of view, then we can return, because no nodes below us will be in view! // If we're at a node that is out of view, then we can return, because no nodes below us will be in view!
// although technically, we really shouldn't ever be here, because our callers shouldn't be calling us if // although technically, we really shouldn't ever be here, because our callers shouldn't be calling us if
// we're out of view // we're out of view
@ -954,26 +982,28 @@ int VoxelTree::encodeTreeBitstreamRecursion(int maxEncodeLevel, int& currentEnco
for (int i = 0; i < MAX_CHILDREN; i++) { for (int i = 0; i < MAX_CHILDREN; i++) {
VoxelNode* childNode = node->children[i]; VoxelNode* childNode = node->children[i];
bool childExists = (childNode != NULL); bool childExists = (childNode != NULL);
bool childIsColored = (childExists && childNode->isColored());
bool childIsInView = (childExists && childNode->isInView(viewFrustum)); bool childIsInView = (childExists && childNode->isInView(viewFrustum));
bool childIsLeaf = (childExists && childNode->isLeaf());
if (childIsInView) { if (childIsInView) {
inViewCount++; // Before we determine consider this further, let's see if it's in our LOD scope...
float distance = childNode->distanceToCamera(viewFrustum);
float boundaryDistance = boundaryDistanceForRenderLevel(*childNode->octalCode + 1);
if (distance < boundaryDistance) {
inViewCount++;
// track children in view as existing and not a leaf, if they're a leaf, // track children in view as existing and not a leaf, if they're a leaf,
// we don't care about recursing deeper on them, and we don't consider their // we don't care about recursing deeper on them, and we don't consider their
// subtree to exist // subtree to exist
if (!childIsLeaf) { if (!(childExists && childNode->isLeaf())) {
childrenExistBits += (1 << (7 - i)); childrenExistBits += (1 << (7 - i));
inViewNotLeafCount++; inViewNotLeafCount++;
} }
// track children with actual color // track children with actual color
if (childIsColored) { if (childExists && childNode->isColored()) {
childrenColoredBits += (1 << (7 - i)); childrenColoredBits += (1 << (7 - i));
inViewWithColorCount++; inViewWithColorCount++;
}
} }
} }
} }
@ -1016,7 +1046,6 @@ int VoxelTree::encodeTreeBitstreamRecursion(int maxEncodeLevel, int& currentEnco
// of handling things. For example, in case of child iteration, it needs to unset the child exist bit for // of handling things. For example, in case of child iteration, it needs to unset the child exist bit for
// this child. // this child.
// add our node the the list of extra nodes to output later... // add our node the the list of extra nodes to output later...
bag.insert(node); bag.insert(node);
return 0; return 0;
} }

View file

@ -38,7 +38,7 @@ const float DEATH_STAR_RADIUS = 4.0;
const float MAX_CUBE = 0.05f; const float MAX_CUBE = 0.05f;
const int VOXEL_SEND_INTERVAL_USECS = 100 * 1000; const int VOXEL_SEND_INTERVAL_USECS = 100 * 1000;
const int PACKETS_PER_CLIENT_PER_INTERVAL = 5; const int PACKETS_PER_CLIENT_PER_INTERVAL = 2;
const int MAX_VOXEL_TREE_DEPTH_LEVELS = 4; const int MAX_VOXEL_TREE_DEPTH_LEVELS = 4;
@ -68,6 +68,16 @@ void addSphere(VoxelTree * tree,bool random, bool wantColorRandomizer) {
tree->createSphere(r,xc,yc,zc,s,solid,wantColorRandomizer); tree->createSphere(r,xc,yc,zc,s,solid,wantColorRandomizer);
} }
int _nodeCount=0;
bool countVoxelsOperation(VoxelNode* node, bool down, void* extraData) {
if (down) {
if (node->isColored()){
_nodeCount++;
}
}
return true; // keep going
}
void addSphereScene(VoxelTree * tree, bool wantColorRandomizer) { void addSphereScene(VoxelTree * tree, bool wantColorRandomizer) {
printf("adding scene of spheres...\n"); printf("adding scene of spheres...\n");
@ -80,6 +90,8 @@ void addSphereScene(VoxelTree * tree, bool wantColorRandomizer) {
tree->createSphere(0.25,0.5,0.5,0.5,(1.0/sphereBaseSize),true,wantColorRandomizer); tree->createSphere(0.25,0.5,0.5,0.5,(1.0/sphereBaseSize),true,wantColorRandomizer);
printf("one sphere added...\n"); printf("one sphere added...\n");
tree->createSphere(0.030625,0.5,0.5,(0.25-0.06125),(1.0/(sphereBaseSize*2)),true,true); tree->createSphere(0.030625,0.5,0.5,(0.25-0.06125),(1.0/(sphereBaseSize*2)),true,true);
printf("two spheres added...\n"); printf("two spheres added...\n");
tree->createSphere(0.030625,(1.0-0.030625),(1.0-0.030625),(1.0-0.06125),(1.0/(sphereBaseSize*2)),true,true); tree->createSphere(0.030625,(1.0-0.030625),(1.0-0.030625),(1.0-0.06125),(1.0/(sphereBaseSize*2)),true,true);
printf("three spheres added...\n"); printf("three spheres added...\n");
@ -88,6 +100,25 @@ void addSphereScene(VoxelTree * tree, bool wantColorRandomizer) {
tree->createSphere(0.030625,(1.0-0.030625),0.06125,(1.0-0.06125),(1.0/(sphereBaseSize*2)),true,true); tree->createSphere(0.030625,(1.0-0.030625),0.06125,(1.0-0.06125),(1.0/(sphereBaseSize*2)),true,true);
printf("five spheres added...\n"); printf("five spheres added...\n");
tree->createSphere(0.06125,0.125,0.125,(1.0-0.125),(1.0/(sphereBaseSize*2)),true,true); tree->createSphere(0.06125,0.125,0.125,(1.0-0.125),(1.0/(sphereBaseSize*2)),true,true);
float radius = 0.0125f;
printf("6 spheres added...\n");
tree->createSphere(radius,0.25,radius*5.0f,0.25,(1.0/(4096)),true,true);
printf("7 spheres added...\n");
tree->createSphere(radius,0.125,radius*5.0f,0.25,(1.0/(4096)),true,true);
printf("8 spheres added...\n");
tree->createSphere(radius,0.075,radius*5.0f,0.25,(1.0/(4096)),true,true);
printf("9 spheres added...\n");
tree->createSphere(radius,0.05,radius*5.0f,0.25,(1.0/(4096)),true,true);
printf("10 spheres added...\n");
tree->createSphere(radius,0.025,radius*5.0f,0.25,(1.0/(4096)),true,true);
printf("11 spheres added...\n");
_nodeCount=0;
tree->recurseTreeWithOperation(countVoxelsOperation);
printf("Nodes after adding scene %d nodes\n",_nodeCount);
printf("DONE adding scene of spheres...\n"); printf("DONE adding scene of spheres...\n");
} }