mirror of
https://github.com/overte-org/overte.git
synced 2025-08-06 18:50:00 +02:00
Merge pull request #96 from ZappoMan/view_frustum_work
Working on False Color Support & LOD Bug fix
This commit is contained in:
commit
6286e1b54f
16 changed files with 851 additions and 308 deletions
|
@ -161,9 +161,8 @@ void VoxelSystem::setupNewVoxelsForDrawing() {
|
||||||
writeVerticesEndPointer = writeVerticesArray;
|
writeVerticesEndPointer = writeVerticesArray;
|
||||||
// call recursive function to populate in memory arrays
|
// call recursive function to populate in memory arrays
|
||||||
// it will return the number of voxels added
|
// it will return the number of voxels added
|
||||||
float treeRoot[3] = {0,0,0};
|
glm::vec3 treeRoot = glm::vec3(0,0,0);
|
||||||
voxelsRendered = treeToArrays(tree->rootNode, treeRoot);
|
voxelsRendered = treeToArrays(tree->rootNode, treeRoot);
|
||||||
|
|
||||||
// copy the newly written data to the arrays designated for reading
|
// copy the newly written data to the arrays designated for reading
|
||||||
copyWrittenDataToReadArrays();
|
copyWrittenDataToReadArrays();
|
||||||
}
|
}
|
||||||
|
@ -176,42 +175,35 @@ void VoxelSystem::copyWrittenDataToReadArrays() {
|
||||||
// copy the vertices and colors
|
// copy the vertices and colors
|
||||||
memcpy(readVerticesArray, writeVerticesArray, (endOfCurrentVerticesData - writeVerticesArray) * sizeof(GLfloat));
|
memcpy(readVerticesArray, writeVerticesArray, (endOfCurrentVerticesData - writeVerticesArray) * sizeof(GLfloat));
|
||||||
memcpy(readColorsArray, writeColorsArray, (endOfCurrentVerticesData - writeVerticesArray) * sizeof(GLubyte));
|
memcpy(readColorsArray, writeColorsArray, (endOfCurrentVerticesData - writeVerticesArray) * sizeof(GLubyte));
|
||||||
|
|
||||||
// set the read vertices end pointer to the correct spot so the GPU knows how much to pull
|
// set the read vertices end pointer to the correct spot so the GPU knows how much to pull
|
||||||
readVerticesEndPointer = readVerticesArray + (endOfCurrentVerticesData - writeVerticesArray);
|
readVerticesEndPointer = readVerticesArray + (endOfCurrentVerticesData - writeVerticesArray);
|
||||||
pthread_mutex_unlock(&bufferWriteLock);
|
pthread_mutex_unlock(&bufferWriteLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
int VoxelSystem::treeToArrays(VoxelNode *currentNode, float nodePosition[3]) {
|
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 = viewerHead->getBodyPosition();
|
glm::vec3 viewerPosition = viewerHead->getBodyPosition();
|
||||||
|
|
||||||
// XXXBHG - Note: It appears as if the X and Z coordinates of Head or Agent are flip-flopped relative to the
|
// debug LOD code
|
||||||
// coords of the voxel space. This flip flop causes LOD behavior to be extremely odd. This is my temporary hack
|
glm::vec3 debugNodePosition;
|
||||||
// to fix this behavior. To disable this swap, set swapXandZ to false.
|
copyFirstVertexForCode(currentNode->octalCode,(float*)&debugNodePosition);
|
||||||
bool swapXandZ=true;
|
|
||||||
float viewerX = swapXandZ ? viewerPosition[2] : viewerPosition[0];
|
|
||||||
float viewerZ = swapXandZ ? viewerPosition[0] : viewerPosition[2];
|
|
||||||
|
|
||||||
// debugging code.
|
//printf("-----------------\n");
|
||||||
//printLog("treeToArrays() halfUnitForVoxel=%f\n",halfUnitForVoxel);
|
//printf("halfUnitForVoxel=%f\n",halfUnitForVoxel);
|
||||||
//printLog("treeToArrays() viewerPosition {x,y,z or [0],[1],[2]} ={%f,%f,%f}\n",
|
//printf("viewer.x=%f y=%f z=%f \n", viewerPosition.x, viewerPosition.y, viewerPosition.z);
|
||||||
// viewerPosition[0],viewerPosition[1],viewerPosition[2]);
|
//printf("node.x=%f y=%f z=%f \n", nodePosition[0], nodePosition[1], nodePosition[2]);
|
||||||
//printLog("treeToArrays() nodePosition {x,y,z or [0],[1],[2]} = {%f,%f,%f}\n",
|
//printf("debugNodePosition.x=%f y=%f z=%f \n", debugNodePosition[0], debugNodePosition[1], debugNodePosition[2]);
|
||||||
// nodePosition[0],nodePosition[1],nodePosition[2]);
|
|
||||||
//float* vertices = firstVertexForCode(currentNode->octalCode);
|
|
||||||
//printLog("treeToArrays() firstVerticesForCode(currentNode->octalCode)={x,y,z or [0],[1],[2]} = {%f,%f,%f}\n",
|
|
||||||
// vertices[0],vertices[1],vertices[2]);
|
|
||||||
//delete []vertices;
|
|
||||||
|
|
||||||
float distanceToVoxelCenter = sqrtf(powf(viewerX - nodePosition[0] - halfUnitForVoxel, 2) +
|
|
||||||
powf(viewerPosition[1] - nodePosition[1] - halfUnitForVoxel, 2) +
|
|
||||||
powf(viewerZ - nodePosition[2] - halfUnitForVoxel, 2));
|
|
||||||
|
|
||||||
int boundaryPosition = boundaryDistanceForRenderLevel(*currentNode->octalCode + 1);
|
float distanceToVoxelCenter = sqrtf(powf(viewerPosition.x - nodePosition[0] - halfUnitForVoxel, 2) +
|
||||||
//printLog("treeToArrays() distanceToVoxelCenter=%f boundaryPosition=%d\n",distanceToVoxelCenter,boundaryPosition);
|
powf(viewerPosition.y - nodePosition[1] - halfUnitForVoxel, 2) +
|
||||||
|
powf(viewerPosition.z - nodePosition[2] - halfUnitForVoxel, 2));
|
||||||
|
|
||||||
|
int renderLevel = *currentNode->octalCode + 1;
|
||||||
|
int boundaryPosition = boundaryDistanceForRenderLevel(renderLevel);
|
||||||
|
//printLog("treeToArrays() renderLevel=%d distanceToVoxelCenter=%f boundaryPosition=%d\n",
|
||||||
|
// renderLevel,distanceToVoxelCenter,boundaryPosition);
|
||||||
|
|
||||||
bool alwaysDraw = false; // XXXBHG - temporary debug code. Flip this to true to disable LOD blurring
|
bool alwaysDraw = false; // XXXBHG - temporary debug code. Flip this to true to disable LOD blurring
|
||||||
|
|
||||||
|
@ -220,43 +212,46 @@ int VoxelSystem::treeToArrays(VoxelNode *currentNode, float nodePosition[3]) {
|
||||||
// check if there is a child here
|
// check if there is a child here
|
||||||
if (currentNode->children[i] != NULL) {
|
if (currentNode->children[i] != NULL) {
|
||||||
|
|
||||||
// calculate the child's position based on the parent position
|
glm::vec3 childNodePosition;
|
||||||
float childNodePosition[3];
|
copyFirstVertexForCode(currentNode->children[i]->octalCode,(float*)&childNodePosition);
|
||||||
|
childNodePosition *= (float)TREE_SCALE; // scale it up
|
||||||
|
|
||||||
|
/**** disabled ************************************************************************************************
|
||||||
|
// Note: Stephen, I intentionally left this in so you would talk to me about it. Here's the deal, this code
|
||||||
|
// doesn't seem to work correctly. It returns X and Z flipped and the values are negative. Since we use the
|
||||||
|
// firstVertexForCode() function below to calculate the child vertex and that DOES work, I've decided to use
|
||||||
|
// that function to calculate our position for LOD handling.
|
||||||
|
//
|
||||||
|
// calculate the child's position based on the parent position
|
||||||
for (int j = 0; j < 3; j++) {
|
for (int j = 0; j < 3; j++) {
|
||||||
childNodePosition[j] = nodePosition[j];
|
childNodePosition[j] = nodePosition[j];
|
||||||
|
|
||||||
if (oneAtBit(branchIndexWithDescendant(currentNode->octalCode,
|
if (oneAtBit(branchIndexWithDescendant(currentNode->octalCode,currentNode->children[i]->octalCode),(7 - j))) {
|
||||||
currentNode->children[i]->octalCode),
|
|
||||||
(7 - j))) {
|
|
||||||
childNodePosition[j] -= (powf(0.5, *currentNode->children[i]->octalCode) * TREE_SCALE);
|
childNodePosition[j] -= (powf(0.5, *currentNode->children[i]->octalCode) * TREE_SCALE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
**** disabled ************************************************************************************************/
|
||||||
voxelsAdded += treeToArrays(currentNode->children[i], childNodePosition);
|
voxelsAdded += treeToArrays(currentNode->children[i], childNodePosition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// if we didn't get any voxels added then we're a leaf
|
// if we didn't get any voxels added then we're a leaf
|
||||||
// add our vertex and color information to the interleaved array
|
// add our vertex and color information to the interleaved array
|
||||||
if (voxelsAdded == 0 && currentNode->color[3] == 1) {
|
if (voxelsAdded == 0 && currentNode->isColored()) {
|
||||||
float * startVertex = firstVertexForCode(currentNode->octalCode);
|
float startVertex[3];
|
||||||
|
copyFirstVertexForCode(currentNode->octalCode,(float*)&startVertex);
|
||||||
float voxelScale = 1 / powf(2, *currentNode->octalCode);
|
float voxelScale = 1 / powf(2, *currentNode->octalCode);
|
||||||
|
|
||||||
// populate the array with points for the 8 vertices
|
// populate the array with points for the 8 vertices
|
||||||
// and RGB color for each added vertex
|
// and RGB color for each added vertex
|
||||||
for (int j = 0; j < VERTEX_POINTS_PER_VOXEL; j++ ) {
|
for (int j = 0; j < VERTEX_POINTS_PER_VOXEL; j++ ) {
|
||||||
*writeVerticesEndPointer = startVertex[j % 3] + (identityVertices[j] * voxelScale);
|
*writeVerticesEndPointer = startVertex[j % 3] + (identityVertices[j] * voxelScale);
|
||||||
*(writeColorsArray + (writeVerticesEndPointer - writeVerticesArray)) = currentNode->color[j % 3];
|
*(writeColorsArray + (writeVerticesEndPointer - writeVerticesArray)) = currentNode->getColor()[j % 3];
|
||||||
|
|
||||||
writeVerticesEndPointer++;
|
writeVerticesEndPointer++;
|
||||||
}
|
}
|
||||||
|
|
||||||
voxelsAdded++;
|
voxelsAdded++;
|
||||||
|
|
||||||
delete [] startVertex;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return voxelsAdded;
|
return voxelsAdded;
|
||||||
|
@ -363,4 +358,263 @@ void VoxelSystem::simulate(float deltaTime) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int VoxelSystem::_nodeCount = 0;
|
||||||
|
|
||||||
|
bool VoxelSystem::randomColorOperation(VoxelNode* node, bool down, void* extraData) {
|
||||||
|
|
||||||
|
// we do our operations on the way up!
|
||||||
|
if (down) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
_nodeCount++;
|
||||||
|
if (node->isColored()) {
|
||||||
|
nodeColor newColor = { 0,0,0,1 };
|
||||||
|
newColor[0] = randomColorValue(150);
|
||||||
|
newColor[1] = randomColorValue(150);
|
||||||
|
newColor[1] = randomColorValue(150);
|
||||||
|
|
||||||
|
//printf("randomize color node %d was %x,%x,%x NOW %x,%x,%x\n",
|
||||||
|
// _nodeCount,node->getTrueColor()[0],node->getTrueColor()[1],node->getTrueColor()[2],
|
||||||
|
// newColor[0],newColor[1],newColor[2]);
|
||||||
|
node->setColor(newColor);
|
||||||
|
} else {
|
||||||
|
//printf("not randomizing color node of %d since it has no color\n",_nodeCount);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VoxelSystem::randomizeVoxelColors() {
|
||||||
|
_nodeCount = 0;
|
||||||
|
tree->recurseTreeWithOperation(randomColorOperation);
|
||||||
|
printf("setting randomized true color for %d nodes\n",_nodeCount);
|
||||||
|
setupNewVoxelsForDrawing();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VoxelSystem::falseColorizeRandomOperation(VoxelNode* node, bool down, void* extraData) {
|
||||||
|
|
||||||
|
// we do our operations on the way up!
|
||||||
|
if (down) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
_nodeCount++;
|
||||||
|
|
||||||
|
// always false colorize
|
||||||
|
unsigned char newR = randomColorValue(150);
|
||||||
|
unsigned char newG = randomColorValue(150);
|
||||||
|
unsigned char newB = randomColorValue(150);
|
||||||
|
|
||||||
|
printf("randomize FALSE color node %d was %x,%x,%x NOW %x,%x,%x\n",
|
||||||
|
_nodeCount,node->getTrueColor()[0],node->getTrueColor()[1],node->getTrueColor()[2],
|
||||||
|
newR,newG,newB);
|
||||||
|
node->setFalseColor(newR,newG,newB);
|
||||||
|
|
||||||
|
return true; // keep going!
|
||||||
|
}
|
||||||
|
|
||||||
|
void VoxelSystem::falseColorizeRandom() {
|
||||||
|
_nodeCount = 0;
|
||||||
|
tree->recurseTreeWithOperation(falseColorizeRandomOperation);
|
||||||
|
printf("setting randomized false color for %d nodes\n",_nodeCount);
|
||||||
|
setupNewVoxelsForDrawing();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VoxelSystem::trueColorizeOperation(VoxelNode* node, bool down, void* extraData) {
|
||||||
|
|
||||||
|
// we do our operations on the way up!
|
||||||
|
if (down) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
_nodeCount++;
|
||||||
|
node->setFalseColored(false);
|
||||||
|
//printf("setting true color for node %d\n",_nodeCount);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VoxelSystem::trueColorize() {
|
||||||
|
_nodeCount = 0;
|
||||||
|
tree->recurseTreeWithOperation(trueColorizeOperation);
|
||||||
|
printf("setting true color for %d nodes\n",_nodeCount);
|
||||||
|
setupNewVoxelsForDrawing();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Will false colorize voxels that are not in view
|
||||||
|
bool VoxelSystem::falseColorizeInViewOperation(VoxelNode* node, bool down, void* extraData) {
|
||||||
|
|
||||||
|
// we do our operations on the way up!
|
||||||
|
if (down) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ViewFrustum* viewFrustum = (ViewFrustum*) extraData;
|
||||||
|
|
||||||
|
_nodeCount++;
|
||||||
|
|
||||||
|
// only do this for truely colored voxels...
|
||||||
|
if (node->isColored()) {
|
||||||
|
// first calculate the AAbox for the voxel
|
||||||
|
AABox voxelBox;
|
||||||
|
node->getAABox(voxelBox);
|
||||||
|
|
||||||
|
voxelBox.scale(TREE_SCALE);
|
||||||
|
|
||||||
|
printf("voxelBox corner=(%f,%f,%f) x=%f\n",
|
||||||
|
voxelBox.getCorner().x, voxelBox.getCorner().y, voxelBox.getCorner().z,
|
||||||
|
voxelBox.getSize().x);
|
||||||
|
|
||||||
|
// If the voxel is outside of the view frustum, then false color it red
|
||||||
|
if (ViewFrustum::OUTSIDE == viewFrustum->pointInFrustum(voxelBox.getCorner())) {
|
||||||
|
// Out of view voxels are colored RED
|
||||||
|
unsigned char newR = 255;
|
||||||
|
unsigned char newG = 0;
|
||||||
|
unsigned char newB = 0;
|
||||||
|
|
||||||
|
//printf("voxel OUTSIDE view - FALSE colorizing node %d TRUE color is %x,%x,%x \n",
|
||||||
|
// _nodeCount,node->getTrueColor()[0],node->getTrueColor()[1],node->getTrueColor()[2]);
|
||||||
|
node->setFalseColor(newR,newG,newB);
|
||||||
|
} else {
|
||||||
|
printf("voxel NOT OUTSIDE view\n");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
printf("voxel not colored, don't consider it\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return true; // keep going!
|
||||||
|
}
|
||||||
|
|
||||||
|
void VoxelSystem::falseColorizeInView(ViewFrustum* viewFrustum) {
|
||||||
|
_nodeCount = 0;
|
||||||
|
tree->recurseTreeWithOperation(falseColorizeInViewOperation,(void*)viewFrustum);
|
||||||
|
printf("setting in view false color for %d nodes\n",_nodeCount);
|
||||||
|
setupNewVoxelsForDrawing();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Will false colorize voxels based on distance from view
|
||||||
|
bool VoxelSystem::falseColorizeDistanceFromViewOperation(VoxelNode* node, bool down, void* extraData) {
|
||||||
|
|
||||||
|
//printf("falseColorizeDistanceFromViewOperation() down=%s\n",(down ? "TRUE" : "FALSE"));
|
||||||
|
|
||||||
|
// we do our operations on the way up!
|
||||||
|
if (down) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ViewFrustum* viewFrustum = (ViewFrustum*) extraData;
|
||||||
|
|
||||||
|
// only do this for truly colored voxels...
|
||||||
|
if (node->isColored()) {
|
||||||
|
|
||||||
|
// We need our distance for both up and down
|
||||||
|
glm::vec3 nodePosition;
|
||||||
|
float* startVertex = firstVertexForCode(node->octalCode);
|
||||||
|
nodePosition.x = startVertex[0];
|
||||||
|
nodePosition.y = startVertex[1];
|
||||||
|
nodePosition.z = startVertex[2];
|
||||||
|
delete startVertex;
|
||||||
|
|
||||||
|
// scale up the node position
|
||||||
|
nodePosition = nodePosition*(float)TREE_SCALE;
|
||||||
|
|
||||||
|
float halfUnitForVoxel = powf(0.5, *node->octalCode) * (0.5 * TREE_SCALE);
|
||||||
|
glm::vec3 viewerPosition = viewFrustum->getPosition();
|
||||||
|
|
||||||
|
//printf("halfUnitForVoxel=%f\n",halfUnitForVoxel);
|
||||||
|
//printf("viewer.x=%f y=%f z=%f \n", viewerPosition.x, viewerPosition.y, viewerPosition.z);
|
||||||
|
//printf("node.x=%f y=%f z=%f \n", nodePosition.x, nodePosition.y, nodePosition.z);
|
||||||
|
|
||||||
|
float distance = sqrtf(powf(viewerPosition.x - nodePosition.x - halfUnitForVoxel, 2) +
|
||||||
|
powf(viewerPosition.y - nodePosition.y - halfUnitForVoxel, 2) +
|
||||||
|
powf(viewerPosition.z - nodePosition.z - halfUnitForVoxel, 2));
|
||||||
|
|
||||||
|
// actually colorize
|
||||||
|
_nodeCount++;
|
||||||
|
|
||||||
|
float distanceRatio = (_minDistance==_maxDistance) ? 1 : (distance - _minDistance)/(_maxDistance - _minDistance);
|
||||||
|
|
||||||
|
// We want to colorize this in 16 bug chunks of color
|
||||||
|
const unsigned char maxColor = 255;
|
||||||
|
const unsigned char colorBands = 16;
|
||||||
|
const unsigned char gradientOver = 128;
|
||||||
|
unsigned char colorBand = (colorBands*distanceRatio);
|
||||||
|
unsigned char newR = (colorBand*(gradientOver/colorBands))+(maxColor-gradientOver);
|
||||||
|
unsigned char newG = 0;
|
||||||
|
unsigned char newB = 0;
|
||||||
|
//printf("Setting color down=%s distance=%f min=%f max=%f distanceRatio=%f color=%d \n",
|
||||||
|
// (down ? "TRUE" : "FALSE"), distance, _minDistance, _maxDistance, distanceRatio, (int)newR);
|
||||||
|
|
||||||
|
node->setFalseColor(newR,newG,newB);
|
||||||
|
} else {
|
||||||
|
//printf("voxel not colored, don't consider it - down=%s\n",(down ? "TRUE" : "FALSE"));
|
||||||
|
}
|
||||||
|
return true; // keep going!
|
||||||
|
}
|
||||||
|
|
||||||
|
float VoxelSystem::_maxDistance = 0.0;
|
||||||
|
float VoxelSystem::_minDistance = FLT_MAX;
|
||||||
|
|
||||||
|
// Helper function will get the distance from view range, would be nice if you could just keep track
|
||||||
|
// of this as voxels are created and/or colored... seems like some transform math could do that so
|
||||||
|
// we wouldn't need to do two passes of the tree
|
||||||
|
bool VoxelSystem::getDistanceFromViewRangeOperation(VoxelNode* node, bool down, void* extraData) {
|
||||||
|
|
||||||
|
// we do our operations on the way up!
|
||||||
|
if (down) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//printf("getDistanceFromViewRangeOperation() down=%s\n",(down ? "TRUE" : "FALSE"));
|
||||||
|
|
||||||
|
ViewFrustum* viewFrustum = (ViewFrustum*) extraData;
|
||||||
|
|
||||||
|
// only do this for truly colored voxels...
|
||||||
|
if (node->isColored()) {
|
||||||
|
|
||||||
|
// We need our distance for both up and down
|
||||||
|
glm::vec3 nodePosition;
|
||||||
|
float* startVertex = firstVertexForCode(node->octalCode);
|
||||||
|
nodePosition.x = startVertex[0];
|
||||||
|
nodePosition.y = startVertex[1];
|
||||||
|
nodePosition.z = startVertex[2];
|
||||||
|
delete startVertex;
|
||||||
|
|
||||||
|
// scale up the node position
|
||||||
|
nodePosition = nodePosition*(float)TREE_SCALE;
|
||||||
|
|
||||||
|
float halfUnitForVoxel = powf(0.5, *node->octalCode) * (0.5 * TREE_SCALE);
|
||||||
|
glm::vec3 viewerPosition = viewFrustum->getPosition();
|
||||||
|
|
||||||
|
float distance = sqrtf(powf(viewerPosition.x - nodePosition.x - halfUnitForVoxel, 2) +
|
||||||
|
powf(viewerPosition.y - nodePosition.y - halfUnitForVoxel, 2) +
|
||||||
|
powf(viewerPosition.z - nodePosition.z - halfUnitForVoxel, 2));
|
||||||
|
|
||||||
|
// on way down, calculate the range of distances
|
||||||
|
if (distance > _maxDistance) {
|
||||||
|
_maxDistance = distance;
|
||||||
|
//printf("new maxDistance=%f down=%s\n",_maxDistance, (down ? "TRUE" : "FALSE"));
|
||||||
|
}
|
||||||
|
if (distance < _minDistance) {
|
||||||
|
_minDistance = distance;
|
||||||
|
//printf("new minDistance=%f down=%s\n",_minDistance, (down ? "TRUE" : "FALSE"));
|
||||||
|
}
|
||||||
|
|
||||||
|
_nodeCount++;
|
||||||
|
}
|
||||||
|
return true; // keep going!
|
||||||
|
}
|
||||||
|
|
||||||
|
void VoxelSystem::falseColorizeDistanceFromView(ViewFrustum* viewFrustum) {
|
||||||
|
_nodeCount = 0;
|
||||||
|
|
||||||
|
_maxDistance = 0.0;
|
||||||
|
_minDistance = FLT_MAX;
|
||||||
|
tree->recurseTreeWithOperation(getDistanceFromViewRangeOperation,(void*)viewFrustum);
|
||||||
|
printf("determining distance range for %d nodes\n",_nodeCount);
|
||||||
|
|
||||||
|
_nodeCount = 0;
|
||||||
|
|
||||||
|
tree->recurseTreeWithOperation(falseColorizeDistanceFromViewOperation,(void*)viewFrustum);
|
||||||
|
printf("setting in distance false color for %d nodes\n",_nodeCount);
|
||||||
|
setupNewVoxelsForDrawing();
|
||||||
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include <UDPSocket.h>
|
#include <UDPSocket.h>
|
||||||
#include <AgentData.h>
|
#include <AgentData.h>
|
||||||
#include <VoxelTree.h>
|
#include <VoxelTree.h>
|
||||||
|
#include <ViewFrustum.h>
|
||||||
#include "Head.h"
|
#include "Head.h"
|
||||||
#include "Util.h"
|
#include "Util.h"
|
||||||
#include "world.h"
|
#include "world.h"
|
||||||
|
@ -44,7 +45,27 @@ public:
|
||||||
float getVoxelsColoredPerSecondAverage();
|
float getVoxelsColoredPerSecondAverage();
|
||||||
float getVoxelsBytesReadPerSecondAverage();
|
float getVoxelsBytesReadPerSecondAverage();
|
||||||
|
|
||||||
|
// Methods that recurse tree
|
||||||
|
void randomizeVoxelColors();
|
||||||
|
void falseColorizeRandom();
|
||||||
|
void trueColorize();
|
||||||
|
void falseColorizeInView(ViewFrustum* viewFrustum);
|
||||||
|
void falseColorizeDistanceFromView(ViewFrustum* viewFrustum);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// Operation functions for tree recursion methods
|
||||||
|
static int _nodeCount;
|
||||||
|
static bool randomColorOperation(VoxelNode* node, bool down, void* extraData);
|
||||||
|
static bool falseColorizeRandomOperation(VoxelNode* node, bool down, void* extraData);
|
||||||
|
static bool trueColorizeOperation(VoxelNode* node, bool down, void* extraData);
|
||||||
|
static bool falseColorizeInViewOperation(VoxelNode* node, bool down, void* extraData);
|
||||||
|
static bool falseColorizeDistanceFromViewOperation(VoxelNode* node, bool down, void* extraData);
|
||||||
|
static bool getDistanceFromViewRangeOperation(VoxelNode* node, bool down, void* extraData);
|
||||||
|
|
||||||
|
// these are kinda hacks, used by getDistanceFromViewRangeOperation() probably shouldn't be here
|
||||||
|
static float _maxDistance;
|
||||||
|
static float _minDistance;
|
||||||
|
|
||||||
int voxelsRendered;
|
int voxelsRendered;
|
||||||
Head *viewerHead;
|
Head *viewerHead;
|
||||||
VoxelTree *tree;
|
VoxelTree *tree;
|
||||||
|
@ -59,7 +80,7 @@ private:
|
||||||
GLuint vboIndicesID;
|
GLuint vboIndicesID;
|
||||||
pthread_mutex_t bufferWriteLock;
|
pthread_mutex_t bufferWriteLock;
|
||||||
|
|
||||||
int treeToArrays(VoxelNode *currentNode, float nodePosition[3]);
|
int treeToArrays(VoxelNode *currentNode, const glm::vec3& nodePosition);
|
||||||
void setupNewVoxelsForDrawing();
|
void setupNewVoxelsForDrawing();
|
||||||
void copyWrittenDataToReadArrays();
|
void copyWrittenDataToReadArrays();
|
||||||
};
|
};
|
||||||
|
|
|
@ -341,11 +341,15 @@ void displayStats(void)
|
||||||
|
|
||||||
Agent *avatarMixer = AgentList::getInstance()->soloAgentOfType(AGENT_TYPE_AVATAR_MIXER);
|
Agent *avatarMixer = AgentList::getInstance()->soloAgentOfType(AGENT_TYPE_AVATAR_MIXER);
|
||||||
char avatarMixerStats[200];
|
char avatarMixerStats[200];
|
||||||
sprintf(avatarMixerStats, "Avatar Mixer - %.f kbps, %.f pps",
|
if (avatarMixer) {
|
||||||
roundf(avatarMixer->getAverageKilobitsPerSecond()),
|
sprintf(avatarMixerStats, "Avatar Mixer - %.f kbps, %.f pps",
|
||||||
roundf(avatarMixer->getAveragePacketsPerSecond()));
|
roundf(avatarMixer->getAverageKilobitsPerSecond()),
|
||||||
|
roundf(avatarMixer->getAveragePacketsPerSecond()));
|
||||||
|
} else {
|
||||||
|
sprintf(avatarMixerStats, "No Avatar Mixer");
|
||||||
|
}
|
||||||
drawtext(10, statsVerticalOffset + 330, 0.10f, 0, 1.0, 0, avatarMixerStats);
|
drawtext(10, statsVerticalOffset + 330, 0.10f, 0, 1.0, 0, avatarMixerStats);
|
||||||
|
|
||||||
if (::perfStatsOn) {
|
if (::perfStatsOn) {
|
||||||
// Get the PerfStats group details. We need to allocate and array of char* long enough to hold 1+groups
|
// Get the PerfStats group details. We need to allocate and array of char* long enough to hold 1+groups
|
||||||
char** perfStatLinesArray = new char*[PerfStat::getGroupCount()+1];
|
char** perfStatLinesArray = new char*[PerfStat::getGroupCount()+1];
|
||||||
|
@ -555,34 +559,14 @@ void updateAvatar(float frametime)
|
||||||
}
|
}
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
// render_view_frustum()
|
// renderViewFrustum()
|
||||||
//
|
//
|
||||||
// Description: this will render the view frustum bounds for EITHER the head
|
// Description: this will load the view frustum bounds for EITHER the head
|
||||||
// or the "myCamera".
|
// or the "myCamera".
|
||||||
//
|
//
|
||||||
// Frustum rendering mode. For debug purposes, we allow drawing the frustum in a couple of different ways.
|
|
||||||
// We can draw it with each of these parts:
|
|
||||||
// * Origin Direction/Up/Right vectors - these will be drawn at the point of the camera
|
|
||||||
// * Near plane - this plane is drawn very close to the origin point.
|
|
||||||
// * Right/Left planes - these two planes are drawn between the near and far planes.
|
|
||||||
// * Far plane - the plane is drawn in the distance.
|
|
||||||
// Modes - the following modes, will draw the following parts.
|
|
||||||
// * All - draws all the parts listed above
|
|
||||||
// * Planes - draws the planes but not the origin vectors
|
|
||||||
// * Origin Vectors - draws the origin vectors ONLY
|
|
||||||
// * Near Plane - draws only the near plane
|
|
||||||
// * Far Plane - draws only the far plane
|
|
||||||
#define FRUSTUM_DRAW_MODE_ALL 0
|
|
||||||
#define FRUSTUM_DRAW_MODE_VECTORS 1
|
|
||||||
#define FRUSTUM_DRAW_MODE_PLANES 2
|
|
||||||
#define FRUSTUM_DRAW_MODE_NEAR_PLANE 3
|
|
||||||
#define FRUSTUM_DRAW_MODE_FAR_PLANE 4
|
|
||||||
#define FRUSTUM_DRAW_MODE_COUNT 5
|
|
||||||
|
|
||||||
// These global scoped variables are used by our render_view_frustum() function below, but are also available as globals
|
// These global scoped variables are used by our loadViewFrustum() and renderViewFrustum functions below, but are also
|
||||||
// so that the keyboard and menu can manipulate them.
|
// available as globals so that the keyboard and menu can manipulate them.
|
||||||
|
|
||||||
int frustumDrawingMode = FRUSTUM_DRAW_MODE_ALL; // the mode we're drawing the frustum in, see notes above
|
|
||||||
|
|
||||||
bool frustumOn = false; // Whether or not to display the debug view frustum
|
bool frustumOn = false; // Whether or not to display the debug view frustum
|
||||||
bool cameraFrustum = true; // which frustum to look at
|
bool cameraFrustum = true; // which frustum to look at
|
||||||
|
@ -594,8 +578,7 @@ float viewFrustumOffsetRoll = 0.0;
|
||||||
float viewFrustumOffsetDistance = 25.0;
|
float viewFrustumOffsetDistance = 25.0;
|
||||||
float viewFrustumOffsetUp = 0.0;
|
float viewFrustumOffsetUp = 0.0;
|
||||||
|
|
||||||
void render_view_frustum() {
|
void loadViewFrustum(ViewFrustum& viewFrustum) {
|
||||||
|
|
||||||
// We will use these below, from either the camera or head vectors calculated above
|
// We will use these below, from either the camera or head vectors calculated above
|
||||||
glm::vec3 position;
|
glm::vec3 position;
|
||||||
glm::vec3 direction;
|
glm::vec3 direction;
|
||||||
|
@ -654,8 +637,44 @@ void render_view_frustum() {
|
||||||
|
|
||||||
// Ask the ViewFrustum class to calculate our corners
|
// Ask the ViewFrustum class to calculate our corners
|
||||||
viewFrustum.calculate();
|
viewFrustum.calculate();
|
||||||
|
}
|
||||||
//viewFrustum.dump();
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// renderViewFrustum()
|
||||||
|
//
|
||||||
|
// Description: this will render the view frustum bounds for EITHER the head
|
||||||
|
// or the "myCamera".
|
||||||
|
//
|
||||||
|
// Frustum rendering mode. For debug purposes, we allow drawing the frustum in a couple of different ways.
|
||||||
|
// We can draw it with each of these parts:
|
||||||
|
// * Origin Direction/Up/Right vectors - these will be drawn at the point of the camera
|
||||||
|
// * Near plane - this plane is drawn very close to the origin point.
|
||||||
|
// * Right/Left planes - these two planes are drawn between the near and far planes.
|
||||||
|
// * Far plane - the plane is drawn in the distance.
|
||||||
|
// Modes - the following modes, will draw the following parts.
|
||||||
|
// * All - draws all the parts listed above
|
||||||
|
// * Planes - draws the planes but not the origin vectors
|
||||||
|
// * Origin Vectors - draws the origin vectors ONLY
|
||||||
|
// * Near Plane - draws only the near plane
|
||||||
|
// * Far Plane - draws only the far plane
|
||||||
|
#define FRUSTUM_DRAW_MODE_ALL 0
|
||||||
|
#define FRUSTUM_DRAW_MODE_VECTORS 1
|
||||||
|
#define FRUSTUM_DRAW_MODE_PLANES 2
|
||||||
|
#define FRUSTUM_DRAW_MODE_NEAR_PLANE 3
|
||||||
|
#define FRUSTUM_DRAW_MODE_FAR_PLANE 4
|
||||||
|
#define FRUSTUM_DRAW_MODE_COUNT 5
|
||||||
|
|
||||||
|
int frustumDrawingMode = FRUSTUM_DRAW_MODE_ALL; // the mode we're drawing the frustum in, see notes above
|
||||||
|
|
||||||
|
void renderViewFrustum(ViewFrustum& viewFrustum) {
|
||||||
|
|
||||||
|
// Load it with the latest details!
|
||||||
|
loadViewFrustum(viewFrustum);
|
||||||
|
|
||||||
|
glm::vec3 position = viewFrustum.getPosition();
|
||||||
|
glm::vec3 direction = viewFrustum.getDirection();
|
||||||
|
glm::vec3 up = viewFrustum.getUp();
|
||||||
|
glm::vec3 right = viewFrustum.getRight();
|
||||||
|
|
||||||
// Get ready to draw some lines
|
// Get ready to draw some lines
|
||||||
glDisable(GL_LIGHTING);
|
glDisable(GL_LIGHTING);
|
||||||
|
@ -816,7 +835,7 @@ void display(void)
|
||||||
// is the viewFrustumOffsetCamera. But theoretically, we could use this same mechanism
|
// is the viewFrustumOffsetCamera. But theoretically, we could use this same mechanism
|
||||||
// to add other cameras.
|
// to add other cameras.
|
||||||
//
|
//
|
||||||
// Why have two cameras? Well, one reason is that because in the case of the render_view_frustum()
|
// Why have two cameras? Well, one reason is that because in the case of the renderViewFrustum()
|
||||||
// code, we want to keep the state of "myCamera" intact, so we can render what the view frustum of
|
// code, we want to keep the state of "myCamera" intact, so we can render what the view frustum of
|
||||||
// myCamera is. But we also want to do meaningful camera transforms on OpenGL for the offset camera
|
// myCamera is. But we also want to do meaningful camera transforms on OpenGL for the offset camera
|
||||||
Camera whichCamera = myCamera;
|
Camera whichCamera = myCamera;
|
||||||
|
@ -910,7 +929,7 @@ void display(void)
|
||||||
if (!displayHead && statsOn) render_world_box();
|
if (!displayHead && statsOn) render_world_box();
|
||||||
|
|
||||||
// brad's frustum for debugging
|
// brad's frustum for debugging
|
||||||
if (::frustumOn) render_view_frustum();
|
if (::frustumOn) renderViewFrustum(::viewFrustum);
|
||||||
|
|
||||||
//Render my own avatar
|
//Render my own avatar
|
||||||
myAvatar.render(true);
|
myAvatar.render(true);
|
||||||
|
@ -1090,6 +1109,46 @@ int setFrustumRenderMode(int state) {
|
||||||
return ::frustumDrawingMode;
|
return ::frustumDrawingMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int doRandomizeVoxelColors(int state) {
|
||||||
|
if (state == MENU_ROW_PICKED) {
|
||||||
|
::voxels.randomizeVoxelColors();
|
||||||
|
}
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int doFalseRandomizeVoxelColors(int state) {
|
||||||
|
if (state == MENU_ROW_PICKED) {
|
||||||
|
::voxels.falseColorizeRandom();
|
||||||
|
}
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
int doTrueVoxelColors(int state) {
|
||||||
|
if (state == MENU_ROW_PICKED) {
|
||||||
|
::voxels.trueColorize();
|
||||||
|
}
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
int doFalseColorizeByDistance(int state) {
|
||||||
|
if (state == MENU_ROW_PICKED) {
|
||||||
|
loadViewFrustum(::viewFrustum);
|
||||||
|
voxels.falseColorizeDistanceFromView(&::viewFrustum);
|
||||||
|
}
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
int doFalseColorizeInView(int state) {
|
||||||
|
if (state == MENU_ROW_PICKED) {
|
||||||
|
loadViewFrustum(::viewFrustum);
|
||||||
|
// we probably want to make sure the viewFrustum is initialized first
|
||||||
|
voxels.falseColorizeInView(&::viewFrustum);
|
||||||
|
}
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const char* modeAll = " - All ";
|
const char* modeAll = " - All ";
|
||||||
const char* modeVectors = " - Vectors ";
|
const char* modeVectors = " - Vectors ";
|
||||||
const char* modePlanes = " - Planes ";
|
const char* modePlanes = " - Planes ";
|
||||||
|
@ -1144,7 +1203,11 @@ void initMenu() {
|
||||||
|
|
||||||
// Debug
|
// Debug
|
||||||
menuColumnDebug = menu.addColumn("Debug");
|
menuColumnDebug = menu.addColumn("Debug");
|
||||||
|
menuColumnDebug->addRow("Randomize Voxel TRUE Colors", doRandomizeVoxelColors);
|
||||||
|
menuColumnDebug->addRow("FALSE Color Voxels Randomly", doFalseRandomizeVoxelColors);
|
||||||
|
menuColumnDebug->addRow("FALSE Color Voxels by Distance", doFalseColorizeByDistance);
|
||||||
|
menuColumnDebug->addRow("FALSE Color Voxel Out of View", doFalseColorizeInView);
|
||||||
|
menuColumnDebug->addRow("Show TRUE Colors", doTrueVoxelColors);
|
||||||
}
|
}
|
||||||
|
|
||||||
void testPointToVoxel()
|
void testPointToVoxel()
|
||||||
|
@ -1308,7 +1371,7 @@ void key(unsigned char k, int x, int y)
|
||||||
// if (k == '\\') ViewFrustum::fovAngleAdust += 0.05;
|
// if (k == '\\') ViewFrustum::fovAngleAdust += 0.05;
|
||||||
|
|
||||||
if (k == 'R') setFrustumRenderMode(MENU_ROW_PICKED);
|
if (k == 'R') setFrustumRenderMode(MENU_ROW_PICKED);
|
||||||
|
|
||||||
if (k == '&') {
|
if (k == '&') {
|
||||||
::paintOn = !::paintOn; // toggle paint
|
::paintOn = !::paintOn; // toggle paint
|
||||||
::setupPaintingVoxel(); // also randomizes colors
|
::setupPaintingVoxel(); // also randomizes colors
|
||||||
|
|
|
@ -104,9 +104,8 @@ unsigned char * childOctalCode(unsigned char * parentOctalCode, char childNumber
|
||||||
return newCode;
|
return newCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
float * firstVertexForCode(unsigned char * octalCode) {
|
void copyFirstVertexForCode(unsigned char * octalCode, float* output) {
|
||||||
float * firstVertex = new float[3];
|
memset(output, 0, 3 * sizeof(float));
|
||||||
memset(firstVertex, 0, 3 * sizeof(float));
|
|
||||||
|
|
||||||
float currentScale = 0.5;
|
float currentScale = 0.5;
|
||||||
|
|
||||||
|
@ -114,11 +113,16 @@ float * firstVertexForCode(unsigned char * octalCode) {
|
||||||
int sectionIndex = sectionValue(octalCode + 1 + (3 * i / 8), (3 * i) % 8);
|
int sectionIndex = sectionValue(octalCode + 1 + (3 * i / 8), (3 * i) % 8);
|
||||||
|
|
||||||
for (int j = 0; j < 3; j++) {
|
for (int j = 0; j < 3; j++) {
|
||||||
firstVertex[j] += currentScale * (int)oneAtBit(sectionIndex, 5 + j);
|
output[j] += currentScale * (int)oneAtBit(sectionIndex, 5 + j);
|
||||||
}
|
}
|
||||||
|
|
||||||
currentScale *= 0.5;
|
currentScale *= 0.5;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float * firstVertexForCode(unsigned char * octalCode) {
|
||||||
|
float * firstVertex = new float[3];
|
||||||
|
copyFirstVertexForCode(octalCode, firstVertex);
|
||||||
return firstVertex;
|
return firstVertex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,11 @@ int bytesRequiredForCodeLength(unsigned char threeBitCodes);
|
||||||
bool isDirectParentOfChild(unsigned char *parentOctalCode, unsigned char * childOctalCode);
|
bool isDirectParentOfChild(unsigned char *parentOctalCode, unsigned char * childOctalCode);
|
||||||
int branchIndexWithDescendant(unsigned char * ancestorOctalCode, unsigned char * descendantOctalCode);
|
int branchIndexWithDescendant(unsigned char * ancestorOctalCode, unsigned char * descendantOctalCode);
|
||||||
unsigned char * childOctalCode(unsigned char * parentOctalCode, char childNumber);
|
unsigned char * childOctalCode(unsigned char * parentOctalCode, char childNumber);
|
||||||
|
|
||||||
|
|
||||||
|
// Note: copyFirstVertexForCode() is preferred because it doesn't allocate memory for the return
|
||||||
|
// but other than that these do the same thing.
|
||||||
float * firstVertexForCode(unsigned char * octalCode);
|
float * firstVertexForCode(unsigned char * octalCode);
|
||||||
|
void copyFirstVertexForCode(unsigned char * octalCode, float* output);
|
||||||
|
|
||||||
#endif /* defined(__hifi__OctalCode__) */
|
#endif /* defined(__hifi__OctalCode__) */
|
||||||
|
|
|
@ -1,76 +1,68 @@
|
||||||
/* ------------------------------------------------------
|
//
|
||||||
|
// AABox.h - Axis Aligned Boxes
|
||||||
Axis Aligned Boxes - Lighthouse3D
|
// hifi
|
||||||
|
//
|
||||||
-----------------------------------------------------*/
|
// Added by Brad Hefta-Gaub on 04/11/13.
|
||||||
|
// Originally from lighthouse3d. Modified to utilize glm::vec3 and clean up to our coding standards
|
||||||
|
//
|
||||||
|
// Simple axis aligned box class.
|
||||||
|
//
|
||||||
|
|
||||||
#include "AABox.h"
|
#include "AABox.h"
|
||||||
|
|
||||||
|
|
||||||
AABox::AABox(const glm::vec3& corner, float x, float y, float z) {
|
void AABox::scale(float scale) {
|
||||||
setBox(corner,x,y,z);
|
_corner = _corner*scale;
|
||||||
|
_size = _size*scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
AABox::AABox(void) {
|
|
||||||
corner.x = 0; corner.y = 0; corner.z = 0;
|
|
||||||
x = 1.0f;
|
|
||||||
y = 1.0f;
|
|
||||||
z = 1.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
AABox::~AABox() {}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void AABox::setBox(const glm::vec3& corner, float x, float y, float z) {
|
void AABox::setBox(const glm::vec3& corner, const glm::vec3& size) {
|
||||||
this->corner = corner;
|
_corner = corner;
|
||||||
if (x < 0.0) {
|
_size = size;
|
||||||
x = -x;
|
|
||||||
this->corner.x -= x;
|
// In the event that the caller gave us negative sizes, fix things up to be reasonable
|
||||||
|
if (_size.x < 0.0) {
|
||||||
|
_size.x = -size.x;
|
||||||
|
_corner.x -= _size.x;
|
||||||
}
|
}
|
||||||
if (y < 0.0) {
|
if (_size.y < 0.0) {
|
||||||
y = -y;
|
_size.y = -size.y;
|
||||||
this->corner.y -= y;
|
_corner.y -= _size.y;
|
||||||
}
|
}
|
||||||
if (z < 0.0) {
|
if (_size.z < 0.0) {
|
||||||
z = -z;
|
_size.z = -size.z;
|
||||||
this->corner.z -= z;
|
_corner.z -= _size.z;
|
||||||
}
|
}
|
||||||
this->x = x;
|
|
||||||
this->y = y;
|
|
||||||
this->z = z;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
glm::vec3 AABox::getVertexP(const glm::vec3 &normal) const {
|
||||||
|
glm::vec3 res = _corner;
|
||||||
glm::vec3 AABox::getVertexP(const glm::vec3 &normal) {
|
|
||||||
glm::vec3 res = corner;
|
|
||||||
if (normal.x > 0)
|
if (normal.x > 0)
|
||||||
res.x += x;
|
res.x += _size.x;
|
||||||
|
|
||||||
if (normal.y > 0)
|
if (normal.y > 0)
|
||||||
res.y += y;
|
res.y += _size.y;
|
||||||
|
|
||||||
if (normal.z > 0)
|
if (normal.z > 0)
|
||||||
res.z += z;
|
res.z += _size.z;
|
||||||
|
|
||||||
return(res);
|
return(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
glm::vec3 AABox::getVertexN(const glm::vec3 &normal) {
|
glm::vec3 AABox::getVertexN(const glm::vec3 &normal) const {
|
||||||
glm::vec3 res = corner;
|
glm::vec3 res = _corner;
|
||||||
|
|
||||||
if (normal.x < 0)
|
if (normal.x < 0)
|
||||||
res.x += x;
|
res.x += _size.x;
|
||||||
|
|
||||||
if (normal.y < 0)
|
if (normal.y < 0)
|
||||||
res.y += y;
|
res.y += _size.y;
|
||||||
|
|
||||||
if (normal.z < 0)
|
if (normal.z < 0)
|
||||||
res.z += z;
|
res.z += _size.z;
|
||||||
|
|
||||||
return(res);
|
return(res);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
/* ------------------------------------------------------
|
//
|
||||||
|
// AABox.h - Axis Aligned Boxes
|
||||||
Axis Aligned Boxes - Lighthouse3D
|
// hifi
|
||||||
|
//
|
||||||
-----------------------------------------------------*/
|
// Added by Brad Hefta-Gaub on 04/11/13.
|
||||||
|
// Originally from lighthouse3d. Modified to utilize glm::vec3 and clean up to our coding standards
|
||||||
|
//
|
||||||
|
// Simple axis aligned box class.
|
||||||
|
//
|
||||||
|
|
||||||
#ifndef _AABOX_
|
#ifndef _AABOX_
|
||||||
#define _AABOX_
|
#define _AABOX_
|
||||||
|
@ -15,18 +18,26 @@ class AABox
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
glm::vec3 corner;
|
AABox(const glm::vec3& corner, float x, float y, float z) : _corner(corner), _size(x,y,z) { };
|
||||||
float x,y,z;
|
AABox(const glm::vec3& corner, const glm::vec3& size) : _corner(corner), _size(size) { };
|
||||||
|
AABox() : _corner(0,0,0), _size(0,0,0) { }
|
||||||
|
~AABox() { }
|
||||||
|
|
||||||
AABox(const glm::vec3 &corner, float x, float y, float z);
|
void setBox(const glm::vec3& corner, float x, float y, float z) { setBox(corner,glm::vec3(x,y,z)); };
|
||||||
AABox(void);
|
void setBox(const glm::vec3& corner, const glm::vec3& size);
|
||||||
~AABox();
|
|
||||||
|
|
||||||
void setBox(const glm::vec3& corner, float x, float y, float z);
|
|
||||||
|
|
||||||
// for use in frustum computations
|
// for use in frustum computations
|
||||||
glm::vec3 getVertexP(const glm::vec3& normal);
|
glm::vec3 getVertexP(const glm::vec3& normal) const;
|
||||||
glm::vec3 getVertexN(const glm::vec3& normal);
|
glm::vec3 getVertexN(const glm::vec3& normal) const;
|
||||||
|
|
||||||
|
void scale(float scale);
|
||||||
|
|
||||||
|
const glm::vec3& getCorner() const { return _corner; };
|
||||||
|
const glm::vec3& getSize() const { return _size; };
|
||||||
|
|
||||||
|
private:
|
||||||
|
glm::vec3 _corner;
|
||||||
|
glm::vec3 _size;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,12 @@
|
||||||
// Plane.cpp
|
|
||||||
//
|
//
|
||||||
//////////////////////////////////////////////////////////////////////
|
// Plane.h
|
||||||
|
// hifi
|
||||||
|
//
|
||||||
|
// Created by Brad Hefta-Gaub on 04/11/13.
|
||||||
|
// Originally from lighthouse3d. Modified to utilize glm::vec3 and clean up to our coding standards
|
||||||
|
//
|
||||||
|
// Simple plane class.
|
||||||
|
//
|
||||||
|
|
||||||
#include "Plane.h"
|
#include "Plane.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -10,78 +16,55 @@
|
||||||
using voxels_lib::printLog;
|
using voxels_lib::printLog;
|
||||||
|
|
||||||
// These are some useful utilities that vec3 is missing
|
// These are some useful utilities that vec3 is missing
|
||||||
float vec3_length(const glm::vec3& v) {
|
void printVec3(const char* name, const glm::vec3& v) {
|
||||||
return((float)sqrt(v.x*v.x + v.y*v.y + v.z*v.z));
|
printf("%s x=%f y=%f z=%f\n", name, v.x, v.y, v.z);
|
||||||
}
|
}
|
||||||
|
|
||||||
void vec3_normalize(glm::vec3& v) {
|
|
||||||
|
|
||||||
float len;
|
|
||||||
|
|
||||||
len = vec3_length(v);
|
|
||||||
if (len) {
|
|
||||||
v.x /= len;;
|
|
||||||
v.y /= len;
|
|
||||||
v.z /= len;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
float vec3_innerProduct(const glm::vec3& v1,const glm::vec3& v2) {
|
|
||||||
|
|
||||||
return (v1.x * v2.x + v1.y * v2.y + v1.z * v2.z);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Plane::Plane(const glm::vec3 &v1, const glm::vec3 &v2, const glm::vec3 &v3) {
|
|
||||||
|
|
||||||
set3Points(v1,v2,v3);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Plane::Plane() {}
|
|
||||||
|
|
||||||
Plane::~Plane() {}
|
|
||||||
|
|
||||||
|
|
||||||
void Plane::set3Points(const glm::vec3 &v1, const glm::vec3 &v2, const glm::vec3 &v3) {
|
void Plane::set3Points(const glm::vec3 &v1, const glm::vec3 &v2, const glm::vec3 &v3) {
|
||||||
|
glm::vec3 linev1v2, linev1v3;
|
||||||
|
|
||||||
|
linev1v2 = v2 - v1;
|
||||||
|
linev1v3 = v3 - v1;
|
||||||
|
|
||||||
glm::vec3 aux1, aux2;
|
// this will be perpendicular to both lines
|
||||||
|
_normal = glm::cross(linev1v2,linev1v3);
|
||||||
|
glm::normalize(_normal);
|
||||||
|
|
||||||
aux1 = v1 - v2;
|
// this is a point on the plane
|
||||||
aux2 = v3 - v2;
|
_point = v2;
|
||||||
|
|
||||||
normal = aux2 * aux1;
|
// the D coefficient from the form Ax+By+Cz=D
|
||||||
|
_dCoefficient = -(glm::dot(_normal,_point));
|
||||||
vec3_normalize(normal);
|
|
||||||
point = v2;
|
|
||||||
d = -(vec3_innerProduct(normal,point));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Plane::setNormalAndPoint(const glm::vec3 &normal, const glm::vec3 &point) {
|
void Plane::setNormalAndPoint(const glm::vec3 &normal, const glm::vec3 &point) {
|
||||||
|
_point = point;
|
||||||
|
_normal = normal;
|
||||||
|
glm::normalize(_normal);
|
||||||
|
|
||||||
this->normal = normal;
|
// the D coefficient from the form Ax+By+Cz=D
|
||||||
vec3_normalize(this->normal);
|
_dCoefficient = -(glm::dot(_normal,_point));
|
||||||
d = -(vec3_innerProduct(this->normal,point));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Plane::setCoefficients(float a, float b, float c, float d) {
|
void Plane::setCoefficients(float a, float b, float c, float d) {
|
||||||
|
// set the normal vector
|
||||||
|
_normal = glm::vec3(a,b,c);
|
||||||
|
|
||||||
// set the normal vector
|
//compute the lenght of the vector
|
||||||
normal = glm::vec3(a,b,c);
|
float l = glm::length(_normal);
|
||||||
//compute the lenght of the vector
|
|
||||||
float l = normal.length();
|
// normalize the vector
|
||||||
// normalize the vector
|
_normal = glm::vec3(a/l,b/l,c/l);
|
||||||
normal = glm::vec3(a/l,b/l,c/l);
|
|
||||||
// and divide d by th length as well
|
// and divide d by th length as well
|
||||||
this->d = d/l;
|
_dCoefficient = d/l;
|
||||||
}
|
}
|
||||||
|
|
||||||
float Plane::distance(const glm::vec3 &p) {
|
float Plane::distance(const glm::vec3 &point) const {
|
||||||
return (d + vec3_innerProduct(normal,p));
|
return (_dCoefficient + glm::dot(_normal,point));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Plane::print() {
|
void Plane::print() const {
|
||||||
//printLog("Plane(");normal.print();printLog("# %f)",d);
|
printf("Plane - point (x=%f y=%f z=%f) normal (x=%f y=%f z=%f) d=%f\n",
|
||||||
|
_point.x, _point.y, _point.z, _normal.x, _normal.y, _normal.z, _dCoefficient);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,34 +1,43 @@
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
// Plane.h - inspired and modified from lighthouse3d.com
|
|
||||||
//
|
//
|
||||||
|
// Plane.h
|
||||||
|
// hifi
|
||||||
|
//
|
||||||
|
// Created by Brad Hefta-Gaub on 04/11/13.
|
||||||
|
// Originally from lighthouse3d. Modified to utilize glm::vec3 and clean up to our coding standards
|
||||||
|
//
|
||||||
|
// Simple plane class.
|
||||||
|
//
|
||||||
|
|
||||||
#ifndef _PLANE_
|
#ifndef _PLANE_
|
||||||
#define _PLANE_
|
#define _PLANE_
|
||||||
|
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
|
|
||||||
class Plane
|
class Plane
|
||||||
{
|
{
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
Plane(const glm::vec3 &v1, const glm::vec3 &v2, const glm::vec3 &v3) { set3Points(v1,v2,v3); }
|
||||||
|
Plane() : _normal(0,0,0), _point(0,0,0), _dCoefficient(0) {};
|
||||||
|
~Plane() {} ;
|
||||||
|
|
||||||
glm::vec3 normal,point;
|
// methods for defining the plane
|
||||||
float d;
|
|
||||||
|
|
||||||
|
|
||||||
Plane(const glm::vec3 &v1, const glm::vec3 &v2, const glm::vec3 &v3);
|
|
||||||
Plane(void);
|
|
||||||
~Plane();
|
|
||||||
|
|
||||||
void set3Points(const glm::vec3 &v1, const glm::vec3 &v2, const glm::vec3 &v3);
|
void set3Points(const glm::vec3 &v1, const glm::vec3 &v2, const glm::vec3 &v3);
|
||||||
void setNormalAndPoint(const glm::vec3 &normal, const glm::vec3 &point);
|
void setNormalAndPoint(const glm::vec3 &normal, const glm::vec3 &point);
|
||||||
void setCoefficients(float a, float b, float c, float d);
|
void setCoefficients(float a, float b, float c, float d);
|
||||||
float distance(const glm::vec3 &p);
|
|
||||||
|
|
||||||
void print();
|
// getters
|
||||||
|
const glm::vec3& getNormal() const { return _normal; };
|
||||||
|
const glm::vec3& getPoint() const { return _point; };
|
||||||
|
float getDCoefficient() const { return _dCoefficient; };
|
||||||
|
|
||||||
|
// utilities
|
||||||
|
float distance(const glm::vec3 &point) const;
|
||||||
|
void print() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
glm::vec3 _normal;
|
||||||
|
glm::vec3 _point;
|
||||||
|
float _dCoefficient;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -53,102 +53,126 @@ void ViewFrustum::calculate() {
|
||||||
glm::vec3 front = _direction;
|
glm::vec3 front = _direction;
|
||||||
|
|
||||||
// Calculating field of view.
|
// Calculating field of view.
|
||||||
float fovInRadians = this->_fieldOfView * PI_OVER_180;
|
float fovInRadians = _fieldOfView * PI_OVER_180;
|
||||||
|
|
||||||
float twoTimesTanHalfFOV = 2.0f * tan(fovInRadians/2.0f);
|
float twoTimesTanHalfFOV = 2.0f * tan(fovInRadians/2.0f);
|
||||||
|
|
||||||
// Do we need this?
|
// Do we need this?
|
||||||
//tang = (float)tan(ANG2RAD * angle * 0.5) ;
|
//tang = (float)tan(ANG2RAD * angle * 0.5) ;
|
||||||
|
|
||||||
float nearClip = this->_nearClip;
|
float nearClip = _nearClip;
|
||||||
float farClip = this->_farClip;
|
float farClip = _farClip;
|
||||||
|
|
||||||
this->_nearHeight = (twoTimesTanHalfFOV * nearClip);
|
_nearHeight = (twoTimesTanHalfFOV * nearClip);
|
||||||
this->_nearWidth = this->_nearHeight * this->_aspectRatio;
|
_nearWidth = _nearHeight * _aspectRatio;
|
||||||
this->_farHeight = (twoTimesTanHalfFOV * farClip);
|
_farHeight = (twoTimesTanHalfFOV * farClip);
|
||||||
this->_farWidth = this->_farHeight * this->_aspectRatio;
|
_farWidth = _farHeight * _aspectRatio;
|
||||||
|
|
||||||
float farHalfHeight = (this->_farHeight * 0.5f);
|
float farHalfHeight = (_farHeight * 0.5f);
|
||||||
float farHalfWidth = (this->_farWidth * 0.5f);
|
float farHalfWidth = (_farWidth * 0.5f);
|
||||||
this->_farCenter = this->_position+front * farClip;
|
_farCenter = _position+front * farClip;
|
||||||
this->_farTopLeft = this->_farCenter + (this->_up * farHalfHeight) - (this->_right * farHalfWidth);
|
_farTopLeft = _farCenter + (_up * farHalfHeight) - (_right * farHalfWidth);
|
||||||
this->_farTopRight = this->_farCenter + (this->_up * farHalfHeight) + (this->_right * farHalfWidth);
|
_farTopRight = _farCenter + (_up * farHalfHeight) + (_right * farHalfWidth);
|
||||||
this->_farBottomLeft = this->_farCenter - (this->_up * farHalfHeight) - (this->_right * farHalfWidth);
|
_farBottomLeft = _farCenter - (_up * farHalfHeight) - (_right * farHalfWidth);
|
||||||
this->_farBottomRight = this->_farCenter - (this->_up * farHalfHeight) + (this->_right * farHalfWidth);
|
_farBottomRight = _farCenter - (_up * farHalfHeight) + (_right * farHalfWidth);
|
||||||
|
|
||||||
float nearHalfHeight = (this->_nearHeight * 0.5f);
|
float nearHalfHeight = (_nearHeight * 0.5f);
|
||||||
float nearHalfWidth = (this->_nearWidth * 0.5f);
|
float nearHalfWidth = (_nearWidth * 0.5f);
|
||||||
this->_nearCenter = this->_position+front * nearClip;
|
_nearCenter = _position+front * nearClip;
|
||||||
this->_nearTopLeft = this->_nearCenter + (this->_up * nearHalfHeight) - (this->_right * nearHalfWidth);
|
_nearTopLeft = _nearCenter + (_up * nearHalfHeight) - (_right * nearHalfWidth);
|
||||||
this->_nearTopRight = this->_nearCenter + (this->_up * nearHalfHeight) + (this->_right * nearHalfWidth);
|
_nearTopRight = _nearCenter + (_up * nearHalfHeight) + (_right * nearHalfWidth);
|
||||||
this->_nearBottomLeft = this->_nearCenter - (this->_up * nearHalfHeight) - (this->_right * nearHalfWidth);
|
_nearBottomLeft = _nearCenter - (_up * nearHalfHeight) - (_right * nearHalfWidth);
|
||||||
this->_nearBottomRight = this->_nearCenter - (this->_up * nearHalfHeight) + (this->_right * nearHalfWidth);
|
_nearBottomRight = _nearCenter - (_up * nearHalfHeight) + (_right * nearHalfWidth);
|
||||||
|
|
||||||
// compute the six planes
|
// compute the six planes
|
||||||
// the function set3Points assumes that the points
|
// The planes are defined such that the normal points towards the inside of the view frustum.
|
||||||
// are given in counter clockwise order
|
// Testing if an object is inside the view frustum is performed by computing on which side of
|
||||||
this->_planes[TOPP].set3Points(this->_nearTopRight,this->_nearTopLeft,this->_farTopLeft);
|
// the plane the object resides. This can be done computing the signed distance from the point
|
||||||
this->_planes[BOTTOMP].set3Points(this->_nearBottomLeft,this->_nearBottomRight,this->_farBottomRight);
|
// to the plane. If it is on the side that the normal is pointing, i.e. the signed distance
|
||||||
this->_planes[LEFTP].set3Points(this->_nearTopLeft,this->_nearBottomLeft,this->_farBottomLeft);
|
// is positive, then it is on the right side of the respective plane. If an object is on the
|
||||||
this->_planes[RIGHTP].set3Points(this->_nearBottomRight,this->_nearTopRight,this->_farBottomRight);
|
// right side of all six planes then the object is inside the frustum.
|
||||||
this->_planes[NEARP].set3Points(this->_nearTopLeft,this->_nearTopRight,this->_nearBottomRight);
|
|
||||||
this->_planes[FARP].set3Points(this->_farTopRight,this->_farTopLeft,this->_farBottomLeft);
|
// the function set3Points assumes that the points are given in counter clockwise order, assume you
|
||||||
|
// are inside the frustum, facing the plane. Start with any point, and go counter clockwise for
|
||||||
|
// three consecutive points
|
||||||
|
|
||||||
|
_planes[TOP_PLANE ].set3Points(_nearTopRight,_nearTopLeft,_farTopLeft);
|
||||||
|
_planes[BOTTOM_PLANE].set3Points(_nearBottomLeft,_nearBottomRight,_farBottomRight);
|
||||||
|
_planes[LEFT_PLANE ].set3Points(_nearBottomLeft,_farBottomLeft,_farTopLeft);
|
||||||
|
_planes[RIGHT_PLANE ].set3Points(_farBottomRight,_nearBottomRight,_nearTopRight);
|
||||||
|
_planes[NEAR_PLANE ].set3Points(_nearBottomRight,_nearBottomLeft,_nearTopLeft);
|
||||||
|
_planes[FAR_PLANE ].set3Points(_farBottomLeft,_farBottomRight,_farTopRight);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ViewFrustum::dump() {
|
void ViewFrustum::dump() {
|
||||||
|
|
||||||
printLog("position.x=%f, position.y=%f, position.z=%f\n", this->_position.x, this->_position.y, this->_position.z);
|
printLog("position.x=%f, position.y=%f, position.z=%f\n", _position.x, _position.y, _position.z);
|
||||||
printLog("direction.x=%f, direction.y=%f, direction.z=%f\n", this->_direction.x, this->_direction.y, this->_direction.z);
|
printLog("direction.x=%f, direction.y=%f, direction.z=%f\n", _direction.x, _direction.y, _direction.z);
|
||||||
printLog("up.x=%f, up.y=%f, up.z=%f\n", this->_up.x, this->_up.y, this->_up.z);
|
printLog("up.x=%f, up.y=%f, up.z=%f\n", _up.x, _up.y, _up.z);
|
||||||
printLog("right.x=%f, right.y=%f, right.z=%f\n", this->_right.x, this->_right.y, this->_right.z);
|
printLog("right.x=%f, right.y=%f, right.z=%f\n", _right.x, _right.y, _right.z);
|
||||||
|
|
||||||
printLog("farDist=%f\n", this->_farClip);
|
printLog("farDist=%f\n", _farClip);
|
||||||
printLog("farHeight=%f\n", this->_farHeight);
|
printLog("farHeight=%f\n", _farHeight);
|
||||||
printLog("farWidth=%f\n", this->_farWidth);
|
printLog("farWidth=%f\n", _farWidth);
|
||||||
|
|
||||||
printLog("nearDist=%f\n", this->_nearClip);
|
printLog("nearDist=%f\n", _nearClip);
|
||||||
printLog("nearHeight=%f\n", this->_nearHeight);
|
printLog("nearHeight=%f\n", _nearHeight);
|
||||||
printLog("nearWidth=%f\n", this->_nearWidth);
|
printLog("nearWidth=%f\n", _nearWidth);
|
||||||
|
|
||||||
printLog("farCenter.x=%f, farCenter.y=%f, farCenter.z=%f\n",
|
printLog("farCenter.x=%f, farCenter.y=%f, farCenter.z=%f\n",
|
||||||
this->_farCenter.x, this->_farCenter.y, this->_farCenter.z);
|
_farCenter.x, _farCenter.y, _farCenter.z);
|
||||||
printLog("farTopLeft.x=%f, farTopLeft.y=%f, farTopLeft.z=%f\n",
|
printLog("farTopLeft.x=%f, farTopLeft.y=%f, farTopLeft.z=%f\n",
|
||||||
this->_farTopLeft.x, this->_farTopLeft.y, this->_farTopLeft.z);
|
_farTopLeft.x, _farTopLeft.y, _farTopLeft.z);
|
||||||
printLog("farTopRight.x=%f, farTopRight.y=%f, farTopRight.z=%f\n",
|
printLog("farTopRight.x=%f, farTopRight.y=%f, farTopRight.z=%f\n",
|
||||||
this->_farTopRight.x, this->_farTopRight.y, this->_farTopRight.z);
|
_farTopRight.x, _farTopRight.y, _farTopRight.z);
|
||||||
printLog("farBottomLeft.x=%f, farBottomLeft.y=%f, farBottomLeft.z=%f\n",
|
printLog("farBottomLeft.x=%f, farBottomLeft.y=%f, farBottomLeft.z=%f\n",
|
||||||
this->_farBottomLeft.x, this->_farBottomLeft.y, this->_farBottomLeft.z);
|
_farBottomLeft.x, _farBottomLeft.y, _farBottomLeft.z);
|
||||||
printLog("farBottomRight.x=%f, farBottomRight.y=%f, farBottomRight.z=%f\n",
|
printLog("farBottomRight.x=%f, farBottomRight.y=%f, farBottomRight.z=%f\n",
|
||||||
this->_farBottomRight.x, this->_farBottomRight.y, this->_farBottomRight.z);
|
_farBottomRight.x, _farBottomRight.y, _farBottomRight.z);
|
||||||
|
|
||||||
printLog("nearCenter.x=%f, nearCenter.y=%f, nearCenter.z=%f\n",
|
printLog("nearCenter.x=%f, nearCenter.y=%f, nearCenter.z=%f\n",
|
||||||
this->_nearCenter.x, this->_nearCenter.y, this->_nearCenter.z);
|
_nearCenter.x, _nearCenter.y, _nearCenter.z);
|
||||||
printLog("nearTopLeft.x=%f, nearTopLeft.y=%f, nearTopLeft.z=%f\n",
|
printLog("nearTopLeft.x=%f, nearTopLeft.y=%f, nearTopLeft.z=%f\n",
|
||||||
this->_nearTopLeft.x, this->_nearTopLeft.y, this->_nearTopLeft.z);
|
_nearTopLeft.x, _nearTopLeft.y, _nearTopLeft.z);
|
||||||
printLog("nearTopRight.x=%f, nearTopRight.y=%f, nearTopRight.z=%f\n",
|
printLog("nearTopRight.x=%f, nearTopRight.y=%f, nearTopRight.z=%f\n",
|
||||||
this->_nearTopRight.x, this->_nearTopRight.y, this->_nearTopRight.z);
|
_nearTopRight.x, _nearTopRight.y, _nearTopRight.z);
|
||||||
printLog("nearBottomLeft.x=%f, nearBottomLeft.y=%f, nearBottomLeft.z=%f\n",
|
printLog("nearBottomLeft.x=%f, nearBottomLeft.y=%f, nearBottomLeft.z=%f\n",
|
||||||
this->_nearBottomLeft.x, this->_nearBottomLeft.y, this->_nearBottomLeft.z);
|
_nearBottomLeft.x, _nearBottomLeft.y, _nearBottomLeft.z);
|
||||||
printLog("nearBottomRight.x=%f, nearBottomRight.y=%f, nearBottomRight.z=%f\n",
|
printLog("nearBottomRight.x=%f, nearBottomRight.y=%f, nearBottomRight.z=%f\n",
|
||||||
this->_nearBottomRight.x, this->_nearBottomRight.y, this->_nearBottomRight.z);
|
_nearBottomRight.x, _nearBottomRight.y, _nearBottomRight.z);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int ViewFrustum::pointInFrustum(glm::vec3 &p) {
|
//enum { TOP_PLANE = 0, BOTTOM_PLANE, LEFT_PLANE, RIGHT_PLANE, NEAR_PLANE, FAR_PLANE };
|
||||||
|
const char* ViewFrustum::debugPlaneName (int plane) const {
|
||||||
|
switch (plane) {
|
||||||
|
case TOP_PLANE: return "Top Plane";
|
||||||
|
case BOTTOM_PLANE: return "Bottom Plane";
|
||||||
|
case LEFT_PLANE: return "Left Plane";
|
||||||
|
case RIGHT_PLANE: return "Right Plane";
|
||||||
|
case NEAR_PLANE: return "Near Plane";
|
||||||
|
case FAR_PLANE: return "Far Plane";
|
||||||
|
}
|
||||||
|
return "Unknown";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int ViewFrustum::pointInFrustum(const glm::vec3& point) {
|
||||||
int result = INSIDE;
|
int result = INSIDE;
|
||||||
for(int i=0; i < 6; i++) {
|
for(int i=0; i < 6; i++) {
|
||||||
if (this->_planes[i].distance(p) < 0)
|
if (_planes[i].distance(point) < 0) {
|
||||||
return OUTSIDE;
|
return OUTSIDE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return(result);
|
return(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
int ViewFrustum::sphereInFrustum(glm::vec3 ¢er, float radius) {
|
int ViewFrustum::sphereInFrustum(const glm::vec3& center, float radius) {
|
||||||
int result = INSIDE;
|
int result = INSIDE;
|
||||||
float distance;
|
float distance;
|
||||||
for(int i=0; i < 6; i++) {
|
for(int i=0; i < 6; i++) {
|
||||||
distance = this->_planes[i].distance(center);
|
distance = _planes[i].distance(center);
|
||||||
if (distance < -radius)
|
if (distance < -radius)
|
||||||
return OUTSIDE;
|
return OUTSIDE;
|
||||||
else if (distance < radius)
|
else if (distance < radius)
|
||||||
|
@ -158,13 +182,39 @@ int ViewFrustum::sphereInFrustum(glm::vec3 ¢er, float radius) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int ViewFrustum::boxInFrustum(AABox &b) {
|
int ViewFrustum::boxInFrustum(const AABox& box) {
|
||||||
|
|
||||||
|
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;
|
int result = INSIDE;
|
||||||
for(int i=0; i < 6; i++) {
|
for(int i=0; i < 6; i++) {
|
||||||
if (this->_planes[i].distance(b.getVertexP(this->_planes[i].normal)) < 0)
|
|
||||||
|
printf("plane[%d] -- point(%f,%f,%f) normal(%f,%f,%f) d=%f \n",i,
|
||||||
|
_planes[i].getPoint().x, _planes[i].getPoint().y, _planes[i].getPoint().z,
|
||||||
|
_planes[i].getNormal().x, _planes[i].getNormal().y, _planes[i].getNormal().z,
|
||||||
|
_planes[i].getDCoefficient()
|
||||||
|
);
|
||||||
|
|
||||||
|
glm::vec3 normal = _planes[i].getNormal();
|
||||||
|
glm::vec3 boxVertexP = box.getVertexP(normal);
|
||||||
|
float planeToBoxVertexPDistance = _planes[i].distance(boxVertexP);
|
||||||
|
|
||||||
|
glm::vec3 boxVertexN = box.getVertexN(normal);
|
||||||
|
float planeToBoxVertexNDistance = _planes[i].distance(boxVertexN);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
printf("plane[%d] normal=(%f,%f,%f) bVertexP=(%f,%f,%f) planeToBoxVertexPDistance=%f boxVertexN=(%f,%f,%f) planeToBoxVertexNDistance=%f\n",i,
|
||||||
|
normal.x,normal.y,normal.z,
|
||||||
|
boxVertexP.x,boxVertexP.y,boxVertexP.z,planeToBoxVertexPDistance,
|
||||||
|
boxVertexN.x,boxVertexN.y,boxVertexN.z,planeToBoxVertexNDistance
|
||||||
|
);
|
||||||
|
|
||||||
|
if (planeToBoxVertexPDistance < 0) {
|
||||||
return OUTSIDE;
|
return OUTSIDE;
|
||||||
else if (this->_planes[i].distance(b.getVertexN(this->_planes[i].normal)) < 0)
|
} else if (planeToBoxVertexNDistance < 0) {
|
||||||
result = INTERSECT;
|
result = INTERSECT;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return(result);
|
return(result);
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,15 +45,23 @@ private:
|
||||||
glm::vec3 _nearTopRight;
|
glm::vec3 _nearTopRight;
|
||||||
glm::vec3 _nearBottomLeft;
|
glm::vec3 _nearBottomLeft;
|
||||||
glm::vec3 _nearBottomRight;
|
glm::vec3 _nearBottomRight;
|
||||||
enum { TOPP = 0, BOTTOMP, LEFTP, RIGHTP, NEARP, FARP };
|
enum { TOP_PLANE = 0, BOTTOM_PLANE, LEFT_PLANE, RIGHT_PLANE, NEAR_PLANE, FAR_PLANE };
|
||||||
Plane _planes[6]; // How will this be used?
|
Plane _planes[6]; // How will this be used?
|
||||||
|
|
||||||
|
const char* debugPlaneName (int plane) const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// setters for camera attributes
|
// setters for camera attributes
|
||||||
void setPosition (const glm::vec3& p) { _position = p; }
|
void setPosition (const glm::vec3& p) { _position = p; }
|
||||||
void setOrientation (const glm::vec3& d, const glm::vec3& u, const glm::vec3& r )
|
void setOrientation (const glm::vec3& d, const glm::vec3& u, const glm::vec3& r )
|
||||||
{ _direction = d; _up = u; _right = r; }
|
{ _direction = d; _up = u; _right = r; }
|
||||||
|
|
||||||
|
// getters for camera attributes
|
||||||
|
const glm::vec3& getPosition() const { return _position; };
|
||||||
|
const glm::vec3& getDirection() const { return _direction; };
|
||||||
|
const glm::vec3& getUp() const { return _up; };
|
||||||
|
const glm::vec3& getRight() const { return _right; };
|
||||||
|
|
||||||
// setters for lens attributes
|
// setters for lens attributes
|
||||||
void setFieldOfView ( float f ) { _fieldOfView = f; }
|
void setFieldOfView ( float f ) { _fieldOfView = f; }
|
||||||
void setAspectRatio ( float a ) { _aspectRatio = a; }
|
void setAspectRatio ( float a ) { _aspectRatio = a; }
|
||||||
|
@ -86,9 +94,9 @@ public:
|
||||||
|
|
||||||
enum {OUTSIDE, INTERSECT, INSIDE};
|
enum {OUTSIDE, INTERSECT, INSIDE};
|
||||||
|
|
||||||
int pointInFrustum(glm::vec3 &p);
|
int pointInFrustum(const glm::vec3& point);
|
||||||
int sphereInFrustum(glm::vec3 ¢er, float radius);
|
int sphereInFrustum(const glm::vec3& center, float radius);
|
||||||
int boxInFrustum(AABox &b);
|
int boxInFrustum(const AABox& box);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -6,17 +6,23 @@
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include "SharedUtil.h"
|
#include "SharedUtil.h"
|
||||||
//#include "voxels_Log.h"
|
//#include "voxels_Log.h"
|
||||||
#include "VoxelNode.h"
|
#include "VoxelNode.h"
|
||||||
#include "OctalCode.h"
|
#include "OctalCode.h"
|
||||||
|
#include "AABox.h"
|
||||||
|
|
||||||
// using voxels_lib::printLog;
|
// using voxels_lib::printLog;
|
||||||
|
|
||||||
VoxelNode::VoxelNode() {
|
VoxelNode::VoxelNode() {
|
||||||
octalCode = NULL;
|
octalCode = NULL;
|
||||||
|
|
||||||
|
#ifdef HAS_FALSE_COLOR
|
||||||
|
_falseColored = false; // assume true color
|
||||||
|
#endif
|
||||||
|
|
||||||
// default pointers to child nodes to NULL
|
// default pointers to child nodes to NULL
|
||||||
for (int i = 0; i < 8; i++) {
|
for (int i = 0; i < 8; i++) {
|
||||||
children[i] = NULL;
|
children[i] = NULL;
|
||||||
|
@ -28,10 +34,27 @@ VoxelNode::~VoxelNode() {
|
||||||
|
|
||||||
// delete all of this node's children
|
// delete all of this node's children
|
||||||
for (int i = 0; i < 8; i++) {
|
for (int i = 0; i < 8; i++) {
|
||||||
delete children[i];
|
if (children[i]) {
|
||||||
|
delete children[i];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VoxelNode::getAABox(AABox& box) const {
|
||||||
|
|
||||||
|
glm::vec3 corner;
|
||||||
|
glm::vec3 size;
|
||||||
|
|
||||||
|
// copy corner into box
|
||||||
|
copyFirstVertexForCode(octalCode,(float*)&corner);
|
||||||
|
|
||||||
|
// this tells you the "size" of the voxel
|
||||||
|
float voxelScale = 1 / powf(2, *octalCode);
|
||||||
|
size = glm::vec3(voxelScale,voxelScale,voxelScale);
|
||||||
|
|
||||||
|
box.setBox(corner,size);
|
||||||
|
}
|
||||||
|
|
||||||
void VoxelNode::addChildAtIndex(int childIndex) {
|
void VoxelNode::addChildAtIndex(int childIndex) {
|
||||||
children[childIndex] = new VoxelNode();
|
children[childIndex] = new VoxelNode();
|
||||||
|
|
||||||
|
@ -43,30 +66,60 @@ void VoxelNode::addChildAtIndex(int childIndex) {
|
||||||
void VoxelNode::setColorFromAverageOfChildren() {
|
void VoxelNode::setColorFromAverageOfChildren() {
|
||||||
int colorArray[4] = {0,0,0,0};
|
int colorArray[4] = {0,0,0,0};
|
||||||
for (int i = 0; i < 8; i++) {
|
for (int i = 0; i < 8; i++) {
|
||||||
if (children[i] != NULL && children[i]->color[3] == 1) {
|
if (children[i] != NULL && children[i]->isColored()) {
|
||||||
for (int j = 0; j < 3; j++) {
|
for (int j = 0; j < 3; j++) {
|
||||||
colorArray[j] += children[i]->color[j];
|
colorArray[j] += children[i]->getTrueColor()[j]; // color averaging should always be based on true colors
|
||||||
}
|
}
|
||||||
colorArray[3]++;
|
colorArray[3]++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nodeColor newColor = { 0, 0, 0, 0};
|
||||||
if (colorArray[3] > 4) {
|
if (colorArray[3] > 4) {
|
||||||
// we need at least 4 colored children to have an average color value
|
// we need at least 4 colored children to have an average color value
|
||||||
// or if we have none we generate random values
|
// or if we have none we generate random values
|
||||||
for (int c = 0; c < 3; c++) {
|
for (int c = 0; c < 3; c++) {
|
||||||
// set the average color value
|
// set the average color value
|
||||||
color[c] = colorArray[c] / colorArray[3];
|
newColor[c] = colorArray[c] / colorArray[3];
|
||||||
}
|
}
|
||||||
// set the alpha to 1 to indicate that this isn't transparent
|
// set the alpha to 1 to indicate that this isn't transparent
|
||||||
color[3] = 1;
|
newColor[3] = 1;
|
||||||
} else {
|
}
|
||||||
// some children, but not enough
|
// actually set our color, note, if we didn't have enough children
|
||||||
// set this node's alpha to 0
|
// this will be the default value all zeros, and therefore be marked as
|
||||||
color[3] = 0;
|
// transparent with a 4th element of 0
|
||||||
}
|
setColor(newColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Note: !NO_FALSE_COLOR implementations of setFalseColor(), setFalseColored(), and setColor() here.
|
||||||
|
// the actual NO_FALSE_COLOR version are inline in the VoxelNode.h
|
||||||
|
#ifndef NO_FALSE_COLOR // !NO_FALSE_COLOR means, does have false color
|
||||||
|
void VoxelNode::setFalseColor(colorPart red, colorPart green, colorPart blue) {
|
||||||
|
_falseColored=true;
|
||||||
|
_currentColor[0] = red;
|
||||||
|
_currentColor[1] = green;
|
||||||
|
_currentColor[2] = blue;
|
||||||
|
_currentColor[3] = 1; // XXXBHG - False colors are always considered set
|
||||||
|
}
|
||||||
|
|
||||||
|
void VoxelNode::setFalseColored(bool isFalseColored) {
|
||||||
|
// if we were false colored, and are no longer false colored, then swap back
|
||||||
|
if (_falseColored && !isFalseColored) {
|
||||||
|
memcpy(&_currentColor,&_trueColor,sizeof(nodeColor));
|
||||||
|
}
|
||||||
|
_falseColored = isFalseColored;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void VoxelNode::setColor(const nodeColor& color) {
|
||||||
|
//printf("VoxelNode::setColor() isFalseColored=%s\n",_falseColored ? "Yes" : "No");
|
||||||
|
memcpy(&_trueColor,&color,sizeof(nodeColor));
|
||||||
|
if (!_falseColored) {
|
||||||
|
memcpy(&_currentColor,&color,sizeof(nodeColor));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// will detect if children are leaves AND the same color
|
// will detect if children are leaves AND the same color
|
||||||
// and in that case will delete the children and make this node
|
// and in that case will delete the children and make this node
|
||||||
// a leaf, returns TRUE if all the leaves are collapsed into a
|
// a leaf, returns TRUE if all the leaves are collapsed into a
|
||||||
|
@ -77,16 +130,17 @@ bool VoxelNode::collapseIdenticalLeaves() {
|
||||||
int red,green,blue;
|
int red,green,blue;
|
||||||
for (int i = 0; i < 8; i++) {
|
for (int i = 0; i < 8; i++) {
|
||||||
// if no child, or child doesn't have a color
|
// if no child, or child doesn't have a color
|
||||||
if (children[i] == NULL || children[i]->color[3] != 1) {
|
if (children[i] == NULL || !children[i]->isColored()) {
|
||||||
allChildrenMatch=false;
|
allChildrenMatch=false;
|
||||||
//printLog("SADNESS child missing or not colored! i=%d\n",i);
|
//printLog("SADNESS child missing or not colored! i=%d\n",i);
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
if (i==0) {
|
if (i==0) {
|
||||||
red = children[i]->color[0];
|
red = children[i]->getColor()[0];
|
||||||
green = children[i]->color[1];
|
green = children[i]->getColor()[1];
|
||||||
blue = children[i]->color[2];
|
blue = children[i]->getColor()[2];
|
||||||
} else if (red != children[i]->color[0] || green != children[i]->color[1] || blue != children[i]->color[2]) {
|
} else if (red != children[i]->getColor()[0] ||
|
||||||
|
green != children[i]->getColor()[1] || blue != children[i]->getColor()[2]) {
|
||||||
allChildrenMatch=false;
|
allChildrenMatch=false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -100,18 +154,22 @@ bool VoxelNode::collapseIdenticalLeaves() {
|
||||||
delete children[i]; // delete all the child nodes
|
delete children[i]; // delete all the child nodes
|
||||||
children[i]=NULL; // set it to NULL
|
children[i]=NULL; // set it to NULL
|
||||||
}
|
}
|
||||||
color[0]=red;
|
nodeColor collapsedColor;
|
||||||
color[1]=green;
|
collapsedColor[0]=red;
|
||||||
color[2]=blue;
|
collapsedColor[1]=green;
|
||||||
color[3]=1; // color is set
|
collapsedColor[2]=blue;
|
||||||
|
collapsedColor[3]=1; // color is set
|
||||||
|
setColor(collapsedColor);
|
||||||
}
|
}
|
||||||
return allChildrenMatch;
|
return allChildrenMatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoxelNode::setRandomColor(int minimumBrightness) {
|
void VoxelNode::setRandomColor(int minimumBrightness) {
|
||||||
|
nodeColor newColor;
|
||||||
for (int c = 0; c < 3; c++) {
|
for (int c = 0; c < 3; c++) {
|
||||||
color[c] = randomColorValue(minimumBrightness);
|
newColor[c] = randomColorValue(minimumBrightness);
|
||||||
}
|
}
|
||||||
|
|
||||||
color[3] = 1;
|
newColor[3] = 1;
|
||||||
|
setColor(newColor);
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,18 @@
|
||||||
#ifndef __hifi__VoxelNode__
|
#ifndef __hifi__VoxelNode__
|
||||||
#define __hifi__VoxelNode__
|
#define __hifi__VoxelNode__
|
||||||
|
|
||||||
|
#include "AABox.h"
|
||||||
|
|
||||||
|
typedef unsigned char colorPart;
|
||||||
|
typedef unsigned char nodeColor[4];
|
||||||
|
|
||||||
class VoxelNode {
|
class VoxelNode {
|
||||||
|
private:
|
||||||
|
nodeColor _trueColor;
|
||||||
|
#ifndef NO_FALSE_COLOR // !NO_FALSE_COLOR means, does have false color
|
||||||
|
nodeColor _currentColor;
|
||||||
|
bool _falseColored;
|
||||||
|
#endif
|
||||||
public:
|
public:
|
||||||
VoxelNode();
|
VoxelNode();
|
||||||
~VoxelNode();
|
~VoxelNode();
|
||||||
|
@ -20,8 +31,27 @@ public:
|
||||||
bool collapseIdenticalLeaves();
|
bool collapseIdenticalLeaves();
|
||||||
|
|
||||||
unsigned char *octalCode;
|
unsigned char *octalCode;
|
||||||
unsigned char color[4];
|
|
||||||
VoxelNode *children[8];
|
VoxelNode *children[8];
|
||||||
|
|
||||||
|
bool isColored() const { return (_trueColor[3]==1); };
|
||||||
|
|
||||||
|
#ifndef NO_FALSE_COLOR // !NO_FALSE_COLOR means, does have false color
|
||||||
|
void setFalseColor(colorPart red, colorPart green, colorPart blue);
|
||||||
|
void setFalseColored(bool isFalseColored);
|
||||||
|
bool getFalseColored() { return _falseColored; };
|
||||||
|
void setColor(const nodeColor& color);
|
||||||
|
const nodeColor& getTrueColor() const { return _trueColor; };
|
||||||
|
const nodeColor& getColor() const { return _currentColor; };
|
||||||
|
#else
|
||||||
|
void setFalseColor(colorPart red, colorPart green, colorPart blue) { /* no op */ };
|
||||||
|
void setFalseColored(bool isFalseColored) { /* no op */ };
|
||||||
|
bool getFalseColored() { return false; };
|
||||||
|
void setColor(const nodeColor& color) { memcpy(_trueColor,color,sizeof(nodeColor)); };
|
||||||
|
const nodeColor& getTrueColor() const { return _trueColor; };
|
||||||
|
const nodeColor& getColor() const { return _trueColor; };
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void getAABox(AABox& box) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* defined(__hifi__VoxelNode__) */
|
#endif /* defined(__hifi__VoxelNode__) */
|
||||||
|
|
|
@ -66,6 +66,27 @@ VoxelTree::~VoxelTree() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Recurses voxel tree calling the RecurseVoxelTreeOperation function for each node.
|
||||||
|
// stops recursion if operation function returns false.
|
||||||
|
void VoxelTree::recurseTreeWithOperation(RecurseVoxelTreeOperation operation, void* extraData) {
|
||||||
|
recurseNodeWithOperation(rootNode, operation,extraData);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Recurses voxel node with an operation function
|
||||||
|
void VoxelTree::recurseNodeWithOperation(VoxelNode* node,RecurseVoxelTreeOperation operation, void* extraData) {
|
||||||
|
// call the operation function going "down" first, stop deeper recursion if function returns false
|
||||||
|
if (operation(node,true,extraData)) {
|
||||||
|
for (int i = 0; i < sizeof(node->children)/sizeof(node->children[0]); i++) {
|
||||||
|
VoxelNode* child = node->children[i];
|
||||||
|
if (child) {
|
||||||
|
recurseNodeWithOperation(child,operation,extraData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// call operation on way back up
|
||||||
|
operation(node,false,extraData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
VoxelNode * VoxelTree::nodeForOctalCode(VoxelNode *ancestorNode, unsigned char * needleCode, VoxelNode** parentOfFoundNode) {
|
VoxelNode * VoxelTree::nodeForOctalCode(VoxelNode *ancestorNode, unsigned char * needleCode, VoxelNode** parentOfFoundNode) {
|
||||||
// find the appropriate branch index based on this ancestorNode
|
// find the appropriate branch index based on this ancestorNode
|
||||||
if (*needleCode > 0) {
|
if (*needleCode > 0) {
|
||||||
|
@ -127,8 +148,10 @@ int VoxelTree::readNodeData(VoxelNode *destinationNode,
|
||||||
}
|
}
|
||||||
|
|
||||||
// pull the color for this child
|
// pull the color for this child
|
||||||
memcpy(destinationNode->children[i]->color, nodeData + bytesRead, 3);
|
nodeColor newColor;
|
||||||
destinationNode->children[i]->color[3] = 1;
|
memcpy(newColor, nodeData + bytesRead, 3);
|
||||||
|
newColor[3] = 1;
|
||||||
|
destinationNode->children[i]->setColor(newColor);
|
||||||
this->voxelsColored++;
|
this->voxelsColored++;
|
||||||
this->voxelsColoredStats.updateAverage(1);
|
this->voxelsColoredStats.updateAverage(1);
|
||||||
|
|
||||||
|
@ -233,8 +256,11 @@ void VoxelTree::readCodeColorBufferToTree(unsigned char *codeColorBuffer) {
|
||||||
|
|
||||||
// give this node its color
|
// give this node its color
|
||||||
int octalCodeBytes = bytesRequiredForCodeLength(*codeColorBuffer);
|
int octalCodeBytes = bytesRequiredForCodeLength(*codeColorBuffer);
|
||||||
memcpy(lastCreatedNode->color, codeColorBuffer + octalCodeBytes, 3);
|
|
||||||
lastCreatedNode->color[3] = 1;
|
nodeColor newColor;
|
||||||
|
memcpy(newColor, codeColorBuffer + octalCodeBytes, 3);
|
||||||
|
newColor[3] = 1;
|
||||||
|
lastCreatedNode->setColor(newColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char * VoxelTree::loadBitstreamBuffer(unsigned char *& bitstreamBuffer,
|
unsigned char * VoxelTree::loadBitstreamBuffer(unsigned char *& bitstreamBuffer,
|
||||||
|
@ -273,7 +299,7 @@ unsigned char * VoxelTree::loadBitstreamBuffer(unsigned char *& bitstreamBuffer,
|
||||||
// coords of the voxel space. This flip flop causes LOD behavior to be extremely odd. This is my temporary hack
|
// coords of the voxel space. This flip flop causes LOD behavior to be extremely odd. This is my temporary hack
|
||||||
// to fix this behavior. To disable this swap, set swapXandZ to false.
|
// to fix this behavior. To disable this swap, set swapXandZ to false.
|
||||||
// XXXBHG - 2013/04/11 - adding a note to my branch, I think this code is now broken.
|
// XXXBHG - 2013/04/11 - adding a note to my branch, I think this code is now broken.
|
||||||
bool swapXandZ=true;
|
bool swapXandZ=false;
|
||||||
float agentX = swapXandZ ? agentPosition[2] : agentPosition[0];
|
float agentX = swapXandZ ? agentPosition[2] : agentPosition[0];
|
||||||
float agentZ = swapXandZ ? agentPosition[0] : agentPosition[2];
|
float agentZ = swapXandZ ? agentPosition[0] : agentPosition[2];
|
||||||
|
|
||||||
|
@ -317,10 +343,10 @@ unsigned char * VoxelTree::loadBitstreamBuffer(unsigned char *& bitstreamBuffer,
|
||||||
|
|
||||||
// check if the child exists and is not transparent
|
// check if the child exists and is not transparent
|
||||||
if (currentVoxelNode->children[i] != NULL
|
if (currentVoxelNode->children[i] != NULL
|
||||||
&& currentVoxelNode->children[i]->color[3] != 0) {
|
&& currentVoxelNode->children[i]->isColored()) {
|
||||||
|
|
||||||
// copy in the childs color to bitstreamBuffer
|
// copy in the childs color to bitstreamBuffer
|
||||||
memcpy(colorPointer, currentVoxelNode->children[i]->color, 3);
|
memcpy(colorPointer, currentVoxelNode->children[i]->getTrueColor(), 3);
|
||||||
colorPointer += 3;
|
colorPointer += 3;
|
||||||
|
|
||||||
// set the colorMask by bitshifting the value of childExists
|
// set the colorMask by bitshifting the value of childExists
|
||||||
|
@ -358,9 +384,19 @@ unsigned char * VoxelTree::loadBitstreamBuffer(unsigned char *& bitstreamBuffer,
|
||||||
currentMarkerNode->children[i] = new MarkerNode();
|
currentMarkerNode->children[i] = new MarkerNode();
|
||||||
}
|
}
|
||||||
|
|
||||||
// calculate the child's position based on the parent position
|
|
||||||
float childNodePosition[3];
|
float childNodePosition[3];
|
||||||
|
copyFirstVertexForCode(currentVoxelNode->children[i]->octalCode,(float*)&childNodePosition);
|
||||||
|
childNodePosition[0] *= TREE_SCALE; // scale it up
|
||||||
|
childNodePosition[1] *= TREE_SCALE; // scale it up
|
||||||
|
childNodePosition[2] *= TREE_SCALE; // scale it up
|
||||||
|
|
||||||
|
/**** disabled *****************************************************************************************
|
||||||
|
// Note: Stephen, I intentionally left this in so you would talk to me about it. Here's the deal, this
|
||||||
|
// code doesn't seem to work correctly. It returns X and Z flipped and the values are negative. Since
|
||||||
|
// we use the firstVertexForCode() function in VoxelSystem to calculate the child vertex and that DOES
|
||||||
|
// work, I've decided to use that function to calculate our position for LOD handling.
|
||||||
|
//
|
||||||
|
// calculate the child's position based on the parent position
|
||||||
for (int j = 0; j < 3; j++) {
|
for (int j = 0; j < 3; j++) {
|
||||||
childNodePosition[j] = thisNodePosition[j];
|
childNodePosition[j] = thisNodePosition[j];
|
||||||
|
|
||||||
|
@ -370,6 +406,7 @@ unsigned char * VoxelTree::loadBitstreamBuffer(unsigned char *& bitstreamBuffer,
|
||||||
childNodePosition[j] -= (powf(0.5, *currentVoxelNode->children[i]->octalCode) * TREE_SCALE);
|
childNodePosition[j] -= (powf(0.5, *currentVoxelNode->children[i]->octalCode) * TREE_SCALE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
**** disabled *****************************************************************************************/
|
||||||
|
|
||||||
// ask the child to load the bitstream buffer with their data
|
// ask the child to load the bitstream buffer with their data
|
||||||
childStopOctalCode = loadBitstreamBuffer(bitstreamBuffer,
|
childStopOctalCode = loadBitstreamBuffer(bitstreamBuffer,
|
||||||
|
@ -437,7 +474,7 @@ void VoxelTree::printTreeForDebugging(VoxelNode *startNode) {
|
||||||
|
|
||||||
// create the color mask
|
// create the color mask
|
||||||
for (int i = 0; i < 8; i++) {
|
for (int i = 0; i < 8; i++) {
|
||||||
if (startNode->children[i] != NULL && startNode->children[i]->color[3] != 0) {
|
if (startNode->children[i] != NULL && startNode->children[i]->isColored()) {
|
||||||
colorMask += (1 << (7 - i));
|
colorMask += (1 << (7 - i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -446,9 +483,9 @@ void VoxelTree::printTreeForDebugging(VoxelNode *startNode) {
|
||||||
|
|
||||||
// output the colors we have
|
// output the colors we have
|
||||||
for (int j = 0; j < 8; j++) {
|
for (int j = 0; j < 8; j++) {
|
||||||
if (startNode->children[j] != NULL && startNode->children[j]->color[3] != 0) {
|
if (startNode->children[j] != NULL && startNode->children[j]->isColored()) {
|
||||||
for (int c = 0; c < 3; c++) {
|
for (int c = 0; c < 3; c++) {
|
||||||
outputBits(startNode->children[j]->color[c]);
|
outputBits(startNode->children[j]->getTrueColor()[c]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,9 @@ const int MAX_VOXEL_PACKET_SIZE = 1492;
|
||||||
const int MAX_TREE_SLICE_BYTES = 26;
|
const int MAX_TREE_SLICE_BYTES = 26;
|
||||||
const int TREE_SCALE = 10;
|
const int TREE_SCALE = 10;
|
||||||
|
|
||||||
|
// Callback function, for recuseTreeWithOperation
|
||||||
|
typedef bool (*RecurseVoxelTreeOperation)(VoxelNode* node, bool down, void* extraData);
|
||||||
|
|
||||||
class VoxelTree {
|
class VoxelTree {
|
||||||
public:
|
public:
|
||||||
// when a voxel is created in the tree (object new'd)
|
// when a voxel is created in the tree (object new'd)
|
||||||
|
@ -53,7 +56,11 @@ public:
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
|
void recurseTreeWithOperation(RecurseVoxelTreeOperation operation, void* extraData=NULL);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void recurseNodeWithOperation(VoxelNode* node,RecurseVoxelTreeOperation operation, void* extraData);
|
||||||
VoxelNode * nodeForOctalCode(VoxelNode *ancestorNode, unsigned char * needleCode, VoxelNode** parentOfFoundNode);
|
VoxelNode * nodeForOctalCode(VoxelNode *ancestorNode, unsigned char * needleCode, VoxelNode** parentOfFoundNode);
|
||||||
VoxelNode * createMissingNode(VoxelNode *lastParentNode, unsigned char *deepestCodeToCreate);
|
VoxelNode * createMissingNode(VoxelNode *lastParentNode, unsigned char *deepestCodeToCreate);
|
||||||
int readNodeData(VoxelNode *destinationNode, unsigned char * nodeData, int bufferSizeBytes);
|
int readNodeData(VoxelNode *destinationNode, unsigned char * nodeData, int bufferSizeBytes);
|
||||||
|
|
|
@ -5,6 +5,14 @@ set(TARGET_NAME voxel-server)
|
||||||
set(ROOT_DIR ..)
|
set(ROOT_DIR ..)
|
||||||
set(MACRO_DIR ${ROOT_DIR}/cmake/macros)
|
set(MACRO_DIR ${ROOT_DIR}/cmake/macros)
|
||||||
|
|
||||||
|
# setup for find modules
|
||||||
|
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../cmake/modules/")
|
||||||
|
set(GLM_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external)
|
||||||
|
|
||||||
|
# set up the external glm library
|
||||||
|
include(${MACRO_DIR}/IncludeGLM.cmake)
|
||||||
|
include_glm(${TARGET_NAME} ${ROOT_DIR})
|
||||||
|
|
||||||
include(${MACRO_DIR}/SetupHifiProject.cmake)
|
include(${MACRO_DIR}/SetupHifiProject.cmake)
|
||||||
|
|
||||||
setup_hifi_project(${TARGET_NAME})
|
setup_hifi_project(${TARGET_NAME})
|
||||||
|
@ -14,4 +22,7 @@ include(${MACRO_DIR}/LinkHifiLibrary.cmake)
|
||||||
link_hifi_library(shared ${TARGET_NAME} ${ROOT_DIR})
|
link_hifi_library(shared ${TARGET_NAME} ${ROOT_DIR})
|
||||||
|
|
||||||
# link in the hifi voxels library
|
# link in the hifi voxels library
|
||||||
link_hifi_library(voxels ${TARGET_NAME} ${ROOT_DIR})
|
link_hifi_library(voxels ${TARGET_NAME} ${ROOT_DIR})
|
||||||
|
|
||||||
|
# find required libraries
|
||||||
|
find_package(GLM REQUIRED)
|
||||||
|
|
Loading…
Reference in a new issue