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);
}
void VoxelSystem::setViewerAvatar(Avatar *newViewerAvatar) {
viewerAvatar = newViewerAvatar;
}
//////////////////////////////////////////////////////////////////////////////////////////
// Method: VoxelSystem::loadVoxelsFile()
// 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 voxelsAdded = 0;
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
glm::vec3 debugNodePosition;

View file

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

View file

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

View file

@ -84,9 +84,27 @@ int boundaryDistanceForRenderLevel(unsigned int renderLevel) {
case 7:
return 12;
break;
default:
case 8:
return 10;
break;
case 9:
return 6;
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);
inViewCount = insertIntoSortedArrays((void*)childNode, distance, i,
(void**)&inViewChildren, (float*)&distancesToChildren, (int*)&positionOfChildren,
inViewCount, MAX_CHILDREN);
if (distance < boundaryDistanceForRenderLevel(*childNode->octalCode + 1)) {
inViewCount = insertIntoSortedArrays((void*)childNode, distance, i,
(void**)&inViewChildren, (float*)&distancesToChildren, (int*)&positionOfChildren,
inViewCount, MAX_CHILDREN);
}
}
}
@ -920,6 +940,14 @@ int VoxelTree::encodeTreeBitstreamRecursion(int maxEncodeLevel, int& currentEnco
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!
// although technically, we really shouldn't ever be here, because our callers shouldn't be calling us if
// we're out of view
@ -954,26 +982,28 @@ int VoxelTree::encodeTreeBitstreamRecursion(int maxEncodeLevel, int& currentEnco
for (int i = 0; i < MAX_CHILDREN; i++) {
VoxelNode* childNode = node->children[i];
bool childExists = (childNode != NULL);
bool childIsColored = (childExists && childNode->isColored());
bool childIsInView = (childExists && childNode->isInView(viewFrustum));
bool childIsLeaf = (childExists && childNode->isLeaf());
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,
// we don't care about recursing deeper on them, and we don't consider their
// subtree to exist
if (!childIsLeaf) {
childrenExistBits += (1 << (7 - i));
inViewNotLeafCount++;
}
// 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
// subtree to exist
if (!(childExists && childNode->isLeaf())) {
childrenExistBits += (1 << (7 - i));
inViewNotLeafCount++;
}
// track children with actual color
if (childIsColored) {
childrenColoredBits += (1 << (7 - i));
inViewWithColorCount++;
// track children with actual color
if (childExists && childNode->isColored()) {
childrenColoredBits += (1 << (7 - i));
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
// this child.
// add our node the the list of extra nodes to output later...
bag.insert(node);
return 0;
}

View file

@ -38,7 +38,7 @@ const float DEATH_STAR_RADIUS = 4.0;
const float MAX_CUBE = 0.05f;
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;
@ -68,6 +68,16 @@ void addSphere(VoxelTree * tree,bool random, bool 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) {
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);
printf("one sphere added...\n");
tree->createSphere(0.030625,0.5,0.5,(0.25-0.06125),(1.0/(sphereBaseSize*2)),true,true);
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);
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);
printf("five spheres added...\n");
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");
}