mirror of
https://github.com/lubosz/overte.git
synced 2025-04-24 11:43:16 +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;
|
||||
// call recursive function to populate in memory arrays
|
||||
// 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);
|
||||
|
||||
// copy the newly written data to the arrays designated for reading
|
||||
copyWrittenDataToReadArrays();
|
||||
}
|
||||
|
@ -176,42 +175,35 @@ void VoxelSystem::copyWrittenDataToReadArrays() {
|
|||
// copy the vertices and colors
|
||||
memcpy(readVerticesArray, writeVerticesArray, (endOfCurrentVerticesData - writeVerticesArray) * sizeof(GLfloat));
|
||||
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
|
||||
readVerticesEndPointer = readVerticesArray + (endOfCurrentVerticesData - writeVerticesArray);
|
||||
pthread_mutex_unlock(&bufferWriteLock);
|
||||
}
|
||||
|
||||
int VoxelSystem::treeToArrays(VoxelNode *currentNode, float nodePosition[3]) {
|
||||
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 = viewerHead->getBodyPosition();
|
||||
|
||||
// XXXBHG - Note: It appears as if the X and Z coordinates of Head or Agent are flip-flopped relative to the
|
||||
// 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.
|
||||
bool swapXandZ=true;
|
||||
float viewerX = swapXandZ ? viewerPosition[2] : viewerPosition[0];
|
||||
float viewerZ = swapXandZ ? viewerPosition[0] : viewerPosition[2];
|
||||
// debug LOD code
|
||||
glm::vec3 debugNodePosition;
|
||||
copyFirstVertexForCode(currentNode->octalCode,(float*)&debugNodePosition);
|
||||
|
||||
// debugging code.
|
||||
//printLog("treeToArrays() halfUnitForVoxel=%f\n",halfUnitForVoxel);
|
||||
//printLog("treeToArrays() viewerPosition {x,y,z or [0],[1],[2]} ={%f,%f,%f}\n",
|
||||
// viewerPosition[0],viewerPosition[1],viewerPosition[2]);
|
||||
//printLog("treeToArrays() nodePosition {x,y,z or [0],[1],[2]} = {%f,%f,%f}\n",
|
||||
// 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));
|
||||
//printf("-----------------\n");
|
||||
//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[0], nodePosition[1], nodePosition[2]);
|
||||
//printf("debugNodePosition.x=%f y=%f z=%f \n", debugNodePosition[0], debugNodePosition[1], debugNodePosition[2]);
|
||||
|
||||
int boundaryPosition = boundaryDistanceForRenderLevel(*currentNode->octalCode + 1);
|
||||
//printLog("treeToArrays() distanceToVoxelCenter=%f boundaryPosition=%d\n",distanceToVoxelCenter,boundaryPosition);
|
||||
float distanceToVoxelCenter = sqrtf(powf(viewerPosition.x - nodePosition[0] - halfUnitForVoxel, 2) +
|
||||
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
|
||||
|
||||
|
@ -220,43 +212,46 @@ int VoxelSystem::treeToArrays(VoxelNode *currentNode, float nodePosition[3]) {
|
|||
// check if there is a child here
|
||||
if (currentNode->children[i] != NULL) {
|
||||
|
||||
// calculate the child's position based on the parent position
|
||||
float childNodePosition[3];
|
||||
glm::vec3 childNodePosition;
|
||||
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++) {
|
||||
childNodePosition[j] = nodePosition[j];
|
||||
|
||||
if (oneAtBit(branchIndexWithDescendant(currentNode->octalCode,
|
||||
currentNode->children[i]->octalCode),
|
||||
(7 - j))) {
|
||||
if (oneAtBit(branchIndexWithDescendant(currentNode->octalCode,currentNode->children[i]->octalCode),(7 - j))) {
|
||||
childNodePosition[j] -= (powf(0.5, *currentNode->children[i]->octalCode) * TREE_SCALE);
|
||||
}
|
||||
}
|
||||
**** disabled ************************************************************************************************/
|
||||
voxelsAdded += treeToArrays(currentNode->children[i], childNodePosition);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// if we didn't get any voxels added then we're a leaf
|
||||
// add our vertex and color information to the interleaved array
|
||||
if (voxelsAdded == 0 && currentNode->color[3] == 1) {
|
||||
float * startVertex = firstVertexForCode(currentNode->octalCode);
|
||||
if (voxelsAdded == 0 && currentNode->isColored()) {
|
||||
float startVertex[3];
|
||||
copyFirstVertexForCode(currentNode->octalCode,(float*)&startVertex);
|
||||
float voxelScale = 1 / powf(2, *currentNode->octalCode);
|
||||
|
||||
// populate the array with points for the 8 vertices
|
||||
// and RGB color for each added vertex
|
||||
for (int j = 0; j < VERTEX_POINTS_PER_VOXEL; j++ ) {
|
||||
*writeVerticesEndPointer = startVertex[j % 3] + (identityVertices[j] * voxelScale);
|
||||
*(writeColorsArray + (writeVerticesEndPointer - writeVerticesArray)) = currentNode->color[j % 3];
|
||||
*(writeColorsArray + (writeVerticesEndPointer - writeVerticesArray)) = currentNode->getColor()[j % 3];
|
||||
|
||||
writeVerticesEndPointer++;
|
||||
}
|
||||
|
||||
voxelsAdded++;
|
||||
|
||||
delete [] startVertex;
|
||||
}
|
||||
|
||||
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 <AgentData.h>
|
||||
#include <VoxelTree.h>
|
||||
#include <ViewFrustum.h>
|
||||
#include "Head.h"
|
||||
#include "Util.h"
|
||||
#include "world.h"
|
||||
|
@ -44,7 +45,27 @@ public:
|
|||
float getVoxelsColoredPerSecondAverage();
|
||||
float getVoxelsBytesReadPerSecondAverage();
|
||||
|
||||
// Methods that recurse tree
|
||||
void randomizeVoxelColors();
|
||||
void falseColorizeRandom();
|
||||
void trueColorize();
|
||||
void falseColorizeInView(ViewFrustum* viewFrustum);
|
||||
void falseColorizeDistanceFromView(ViewFrustum* viewFrustum);
|
||||
|
||||
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;
|
||||
Head *viewerHead;
|
||||
VoxelTree *tree;
|
||||
|
@ -59,7 +80,7 @@ private:
|
|||
GLuint vboIndicesID;
|
||||
pthread_mutex_t bufferWriteLock;
|
||||
|
||||
int treeToArrays(VoxelNode *currentNode, float nodePosition[3]);
|
||||
int treeToArrays(VoxelNode *currentNode, const glm::vec3& nodePosition);
|
||||
void setupNewVoxelsForDrawing();
|
||||
void copyWrittenDataToReadArrays();
|
||||
};
|
||||
|
|
|
@ -341,11 +341,15 @@ void displayStats(void)
|
|||
|
||||
Agent *avatarMixer = AgentList::getInstance()->soloAgentOfType(AGENT_TYPE_AVATAR_MIXER);
|
||||
char avatarMixerStats[200];
|
||||
sprintf(avatarMixerStats, "Avatar Mixer - %.f kbps, %.f pps",
|
||||
roundf(avatarMixer->getAverageKilobitsPerSecond()),
|
||||
roundf(avatarMixer->getAveragePacketsPerSecond()));
|
||||
if (avatarMixer) {
|
||||
sprintf(avatarMixerStats, "Avatar Mixer - %.f kbps, %.f pps",
|
||||
roundf(avatarMixer->getAverageKilobitsPerSecond()),
|
||||
roundf(avatarMixer->getAveragePacketsPerSecond()));
|
||||
} else {
|
||||
sprintf(avatarMixerStats, "No Avatar Mixer");
|
||||
}
|
||||
drawtext(10, statsVerticalOffset + 330, 0.10f, 0, 1.0, 0, avatarMixerStats);
|
||||
|
||||
|
||||
if (::perfStatsOn) {
|
||||
// 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];
|
||||
|
@ -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".
|
||||
//
|
||||
// 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
|
||||
// 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
|
||||
// These global scoped variables are used by our loadViewFrustum() and renderViewFrustum functions below, but are also
|
||||
// available as globals so that the keyboard and menu can manipulate them.
|
||||
|
||||
bool frustumOn = false; // Whether or not to display the debug view frustum
|
||||
bool cameraFrustum = true; // which frustum to look at
|
||||
|
@ -594,8 +578,7 @@ float viewFrustumOffsetRoll = 0.0;
|
|||
float viewFrustumOffsetDistance = 25.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
|
||||
glm::vec3 position;
|
||||
glm::vec3 direction;
|
||||
|
@ -654,8 +637,44 @@ void render_view_frustum() {
|
|||
|
||||
// Ask the ViewFrustum class to calculate our corners
|
||||
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
|
||||
glDisable(GL_LIGHTING);
|
||||
|
@ -816,7 +835,7 @@ void display(void)
|
|||
// is the viewFrustumOffsetCamera. But theoretically, we could use this same mechanism
|
||||
// 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
|
||||
// myCamera is. But we also want to do meaningful camera transforms on OpenGL for the offset camera
|
||||
Camera whichCamera = myCamera;
|
||||
|
@ -910,7 +929,7 @@ void display(void)
|
|||
if (!displayHead && statsOn) render_world_box();
|
||||
|
||||
// brad's frustum for debugging
|
||||
if (::frustumOn) render_view_frustum();
|
||||
if (::frustumOn) renderViewFrustum(::viewFrustum);
|
||||
|
||||
//Render my own avatar
|
||||
myAvatar.render(true);
|
||||
|
@ -1090,6 +1109,46 @@ int setFrustumRenderMode(int state) {
|
|||
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* modeVectors = " - Vectors ";
|
||||
const char* modePlanes = " - Planes ";
|
||||
|
@ -1144,7 +1203,11 @@ void initMenu() {
|
|||
|
||||
// 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()
|
||||
|
@ -1308,7 +1371,7 @@ void key(unsigned char k, int x, int y)
|
|||
// if (k == '\\') ViewFrustum::fovAngleAdust += 0.05;
|
||||
|
||||
if (k == 'R') setFrustumRenderMode(MENU_ROW_PICKED);
|
||||
|
||||
|
||||
if (k == '&') {
|
||||
::paintOn = !::paintOn; // toggle paint
|
||||
::setupPaintingVoxel(); // also randomizes colors
|
||||
|
|
|
@ -104,9 +104,8 @@ unsigned char * childOctalCode(unsigned char * parentOctalCode, char childNumber
|
|||
return newCode;
|
||||
}
|
||||
|
||||
float * firstVertexForCode(unsigned char * octalCode) {
|
||||
float * firstVertex = new float[3];
|
||||
memset(firstVertex, 0, 3 * sizeof(float));
|
||||
void copyFirstVertexForCode(unsigned char * octalCode, float* output) {
|
||||
memset(output, 0, 3 * sizeof(float));
|
||||
|
||||
float currentScale = 0.5;
|
||||
|
||||
|
@ -114,11 +113,16 @@ float * firstVertexForCode(unsigned char * octalCode) {
|
|||
int sectionIndex = sectionValue(octalCode + 1 + (3 * i / 8), (3 * i) % 8);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
float * firstVertexForCode(unsigned char * octalCode) {
|
||||
float * firstVertex = new float[3];
|
||||
copyFirstVertexForCode(octalCode, firstVertex);
|
||||
return firstVertex;
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,11 @@ int bytesRequiredForCodeLength(unsigned char threeBitCodes);
|
|||
bool isDirectParentOfChild(unsigned char *parentOctalCode, unsigned char * childOctalCode);
|
||||
int branchIndexWithDescendant(unsigned char * ancestorOctalCode, unsigned char * descendantOctalCode);
|
||||
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);
|
||||
void copyFirstVertexForCode(unsigned char * octalCode, float* output);
|
||||
|
||||
#endif /* defined(__hifi__OctalCode__) */
|
||||
|
|
|
@ -1,76 +1,68 @@
|
|||
/* ------------------------------------------------------
|
||||
|
||||
Axis Aligned Boxes - Lighthouse3D
|
||||
|
||||
-----------------------------------------------------*/
|
||||
//
|
||||
// AABox.h - Axis Aligned Boxes
|
||||
// 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"
|
||||
|
||||
|
||||
AABox::AABox(const glm::vec3& corner, float x, float y, float z) {
|
||||
setBox(corner,x,y,z);
|
||||
void AABox::scale(float scale) {
|
||||
_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) {
|
||||
this->corner = corner;
|
||||
if (x < 0.0) {
|
||||
x = -x;
|
||||
this->corner.x -= x;
|
||||
void AABox::setBox(const glm::vec3& corner, const glm::vec3& size) {
|
||||
_corner = corner;
|
||||
_size = size;
|
||||
|
||||
// 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) {
|
||||
y = -y;
|
||||
this->corner.y -= y;
|
||||
if (_size.y < 0.0) {
|
||||
_size.y = -size.y;
|
||||
_corner.y -= _size.y;
|
||||
}
|
||||
if (z < 0.0) {
|
||||
z = -z;
|
||||
this->corner.z -= z;
|
||||
if (_size.z < 0.0) {
|
||||
_size.z = -size.z;
|
||||
_corner.z -= _size.z;
|
||||
}
|
||||
this->x = x;
|
||||
this->y = y;
|
||||
this->z = z;
|
||||
}
|
||||
|
||||
|
||||
|
||||
glm::vec3 AABox::getVertexP(const glm::vec3 &normal) {
|
||||
glm::vec3 res = corner;
|
||||
glm::vec3 AABox::getVertexP(const glm::vec3 &normal) const {
|
||||
glm::vec3 res = _corner;
|
||||
if (normal.x > 0)
|
||||
res.x += x;
|
||||
res.x += _size.x;
|
||||
|
||||
if (normal.y > 0)
|
||||
res.y += y;
|
||||
res.y += _size.y;
|
||||
|
||||
if (normal.z > 0)
|
||||
res.z += z;
|
||||
res.z += _size.z;
|
||||
|
||||
return(res);
|
||||
}
|
||||
|
||||
|
||||
|
||||
glm::vec3 AABox::getVertexN(const glm::vec3 &normal) {
|
||||
glm::vec3 res = corner;
|
||||
glm::vec3 AABox::getVertexN(const glm::vec3 &normal) const {
|
||||
glm::vec3 res = _corner;
|
||||
|
||||
if (normal.x < 0)
|
||||
res.x += x;
|
||||
res.x += _size.x;
|
||||
|
||||
if (normal.y < 0)
|
||||
res.y += y;
|
||||
res.y += _size.y;
|
||||
|
||||
if (normal.z < 0)
|
||||
res.z += z;
|
||||
res.z += _size.z;
|
||||
|
||||
return(res);
|
||||
}
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
/* ------------------------------------------------------
|
||||
|
||||
Axis Aligned Boxes - Lighthouse3D
|
||||
|
||||
-----------------------------------------------------*/
|
||||
|
||||
//
|
||||
// AABox.h - Axis Aligned Boxes
|
||||
// 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_
|
||||
#define _AABOX_
|
||||
|
@ -15,18 +18,26 @@ class AABox
|
|||
|
||||
public:
|
||||
|
||||
glm::vec3 corner;
|
||||
float x,y,z;
|
||||
AABox(const glm::vec3& corner, float x, float y, float z) : _corner(corner), _size(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);
|
||||
AABox(void);
|
||||
~AABox();
|
||||
|
||||
void setBox(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)); };
|
||||
void setBox(const glm::vec3& corner, const glm::vec3& size);
|
||||
|
||||
// for use in frustum computations
|
||||
glm::vec3 getVertexP(const glm::vec3& normal);
|
||||
glm::vec3 getVertexN(const glm::vec3& normal);
|
||||
glm::vec3 getVertexP(const glm::vec3& normal) const;
|
||||
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 <stdio.h>
|
||||
|
@ -10,78 +16,55 @@
|
|||
using voxels_lib::printLog;
|
||||
|
||||
// These are some useful utilities that vec3 is missing
|
||||
float vec3_length(const glm::vec3& v) {
|
||||
return((float)sqrt(v.x*v.x + v.y*v.y + v.z*v.z));
|
||||
void printVec3(const char* name, const glm::vec3& v) {
|
||||
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) {
|
||||
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;
|
||||
aux2 = v3 - v2;
|
||||
// this is a point on the plane
|
||||
_point = v2;
|
||||
|
||||
normal = aux2 * aux1;
|
||||
|
||||
vec3_normalize(normal);
|
||||
point = v2;
|
||||
d = -(vec3_innerProduct(normal,point));
|
||||
// the D coefficient from the form Ax+By+Cz=D
|
||||
_dCoefficient = -(glm::dot(_normal,_point));
|
||||
}
|
||||
|
||||
void Plane::setNormalAndPoint(const glm::vec3 &normal, const glm::vec3 &point) {
|
||||
_point = point;
|
||||
_normal = normal;
|
||||
glm::normalize(_normal);
|
||||
|
||||
this->normal = normal;
|
||||
vec3_normalize(this->normal);
|
||||
d = -(vec3_innerProduct(this->normal,point));
|
||||
// the D coefficient from the form Ax+By+Cz=D
|
||||
_dCoefficient = -(glm::dot(_normal,_point));
|
||||
}
|
||||
|
||||
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
|
||||
normal = glm::vec3(a,b,c);
|
||||
//compute the lenght of the vector
|
||||
float l = normal.length();
|
||||
// normalize the vector
|
||||
normal = glm::vec3(a/l,b/l,c/l);
|
||||
// and divide d by th length as well
|
||||
this->d = d/l;
|
||||
//compute the lenght of the vector
|
||||
float l = glm::length(_normal);
|
||||
|
||||
// normalize the vector
|
||||
_normal = glm::vec3(a/l,b/l,c/l);
|
||||
|
||||
// and divide d by th length as well
|
||||
_dCoefficient = d/l;
|
||||
}
|
||||
|
||||
float Plane::distance(const glm::vec3 &p) {
|
||||
return (d + vec3_innerProduct(normal,p));
|
||||
float Plane::distance(const glm::vec3 &point) const {
|
||||
return (_dCoefficient + glm::dot(_normal,point));
|
||||
}
|
||||
|
||||
void Plane::print() {
|
||||
//printLog("Plane(");normal.print();printLog("# %f)",d);
|
||||
void Plane::print() const {
|
||||
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_
|
||||
#define _PLANE_
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
|
||||
class Plane
|
||||
{
|
||||
|
||||
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;
|
||||
float d;
|
||||
|
||||
|
||||
Plane(const glm::vec3 &v1, const glm::vec3 &v2, const glm::vec3 &v3);
|
||||
Plane(void);
|
||||
~Plane();
|
||||
|
||||
// methods for defining the plane
|
||||
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 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;
|
||||
|
||||
// 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);
|
||||
|
||||
// Do we need this?
|
||||
//tang = (float)tan(ANG2RAD * angle * 0.5) ;
|
||||
|
||||
float nearClip = this->_nearClip;
|
||||
float farClip = this->_farClip;
|
||||
float nearClip = _nearClip;
|
||||
float farClip = _farClip;
|
||||
|
||||
this->_nearHeight = (twoTimesTanHalfFOV * nearClip);
|
||||
this->_nearWidth = this->_nearHeight * this->_aspectRatio;
|
||||
this->_farHeight = (twoTimesTanHalfFOV * farClip);
|
||||
this->_farWidth = this->_farHeight * this->_aspectRatio;
|
||||
_nearHeight = (twoTimesTanHalfFOV * nearClip);
|
||||
_nearWidth = _nearHeight * _aspectRatio;
|
||||
_farHeight = (twoTimesTanHalfFOV * farClip);
|
||||
_farWidth = _farHeight * _aspectRatio;
|
||||
|
||||
float farHalfHeight = (this->_farHeight * 0.5f);
|
||||
float farHalfWidth = (this->_farWidth * 0.5f);
|
||||
this->_farCenter = this->_position+front * farClip;
|
||||
this->_farTopLeft = this->_farCenter + (this->_up * farHalfHeight) - (this->_right * farHalfWidth);
|
||||
this->_farTopRight = this->_farCenter + (this->_up * farHalfHeight) + (this->_right * farHalfWidth);
|
||||
this->_farBottomLeft = this->_farCenter - (this->_up * farHalfHeight) - (this->_right * farHalfWidth);
|
||||
this->_farBottomRight = this->_farCenter - (this->_up * farHalfHeight) + (this->_right * farHalfWidth);
|
||||
float farHalfHeight = (_farHeight * 0.5f);
|
||||
float farHalfWidth = (_farWidth * 0.5f);
|
||||
_farCenter = _position+front * farClip;
|
||||
_farTopLeft = _farCenter + (_up * farHalfHeight) - (_right * farHalfWidth);
|
||||
_farTopRight = _farCenter + (_up * farHalfHeight) + (_right * farHalfWidth);
|
||||
_farBottomLeft = _farCenter - (_up * farHalfHeight) - (_right * farHalfWidth);
|
||||
_farBottomRight = _farCenter - (_up * farHalfHeight) + (_right * farHalfWidth);
|
||||
|
||||
float nearHalfHeight = (this->_nearHeight * 0.5f);
|
||||
float nearHalfWidth = (this->_nearWidth * 0.5f);
|
||||
this->_nearCenter = this->_position+front * nearClip;
|
||||
this->_nearTopLeft = this->_nearCenter + (this->_up * nearHalfHeight) - (this->_right * nearHalfWidth);
|
||||
this->_nearTopRight = this->_nearCenter + (this->_up * nearHalfHeight) + (this->_right * nearHalfWidth);
|
||||
this->_nearBottomLeft = this->_nearCenter - (this->_up * nearHalfHeight) - (this->_right * nearHalfWidth);
|
||||
this->_nearBottomRight = this->_nearCenter - (this->_up * nearHalfHeight) + (this->_right * nearHalfWidth);
|
||||
float nearHalfHeight = (_nearHeight * 0.5f);
|
||||
float nearHalfWidth = (_nearWidth * 0.5f);
|
||||
_nearCenter = _position+front * nearClip;
|
||||
_nearTopLeft = _nearCenter + (_up * nearHalfHeight) - (_right * nearHalfWidth);
|
||||
_nearTopRight = _nearCenter + (_up * nearHalfHeight) + (_right * nearHalfWidth);
|
||||
_nearBottomLeft = _nearCenter - (_up * nearHalfHeight) - (_right * nearHalfWidth);
|
||||
_nearBottomRight = _nearCenter - (_up * nearHalfHeight) + (_right * nearHalfWidth);
|
||||
|
||||
// compute the six planes
|
||||
// the function set3Points assumes that the points
|
||||
// are given in counter clockwise order
|
||||
this->_planes[TOPP].set3Points(this->_nearTopRight,this->_nearTopLeft,this->_farTopLeft);
|
||||
this->_planes[BOTTOMP].set3Points(this->_nearBottomLeft,this->_nearBottomRight,this->_farBottomRight);
|
||||
this->_planes[LEFTP].set3Points(this->_nearTopLeft,this->_nearBottomLeft,this->_farBottomLeft);
|
||||
this->_planes[RIGHTP].set3Points(this->_nearBottomRight,this->_nearTopRight,this->_farBottomRight);
|
||||
this->_planes[NEARP].set3Points(this->_nearTopLeft,this->_nearTopRight,this->_nearBottomRight);
|
||||
this->_planes[FARP].set3Points(this->_farTopRight,this->_farTopLeft,this->_farBottomLeft);
|
||||
// The planes are defined such that the normal points towards the inside of the view frustum.
|
||||
// Testing if an object is inside the view frustum is performed by computing on which side of
|
||||
// the plane the object resides. This can be done computing the signed distance from the point
|
||||
// to the plane. If it is on the side that the normal is pointing, i.e. the signed distance
|
||||
// is positive, then it is on the right side of the respective plane. If an object is on the
|
||||
// right side of all six planes then the object is inside the frustum.
|
||||
|
||||
// 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() {
|
||||
|
||||
printLog("position.x=%f, position.y=%f, position.z=%f\n", this->_position.x, this->_position.y, this->_position.z);
|
||||
printLog("direction.x=%f, direction.y=%f, direction.z=%f\n", this->_direction.x, this->_direction.y, this->_direction.z);
|
||||
printLog("up.x=%f, up.y=%f, up.z=%f\n", this->_up.x, this->_up.y, this->_up.z);
|
||||
printLog("right.x=%f, right.y=%f, right.z=%f\n", this->_right.x, this->_right.y, this->_right.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", _direction.x, _direction.y, _direction.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", _right.x, _right.y, _right.z);
|
||||
|
||||
printLog("farDist=%f\n", this->_farClip);
|
||||
printLog("farHeight=%f\n", this->_farHeight);
|
||||
printLog("farWidth=%f\n", this->_farWidth);
|
||||
printLog("farDist=%f\n", _farClip);
|
||||
printLog("farHeight=%f\n", _farHeight);
|
||||
printLog("farWidth=%f\n", _farWidth);
|
||||
|
||||
printLog("nearDist=%f\n", this->_nearClip);
|
||||
printLog("nearHeight=%f\n", this->_nearHeight);
|
||||
printLog("nearWidth=%f\n", this->_nearWidth);
|
||||
printLog("nearDist=%f\n", _nearClip);
|
||||
printLog("nearHeight=%f\n", _nearHeight);
|
||||
printLog("nearWidth=%f\n", _nearWidth);
|
||||
|
||||
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",
|
||||
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",
|
||||
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",
|
||||
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",
|
||||
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",
|
||||
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",
|
||||
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",
|
||||
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",
|
||||
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",
|
||||
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;
|
||||
for(int i=0; i < 6; i++) {
|
||||
if (this->_planes[i].distance(p) < 0)
|
||||
if (_planes[i].distance(point) < 0) {
|
||||
return OUTSIDE;
|
||||
}
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
int ViewFrustum::sphereInFrustum(glm::vec3 ¢er, float radius) {
|
||||
int ViewFrustum::sphereInFrustum(const glm::vec3& center, float radius) {
|
||||
int result = INSIDE;
|
||||
float distance;
|
||||
for(int i=0; i < 6; i++) {
|
||||
distance = this->_planes[i].distance(center);
|
||||
distance = _planes[i].distance(center);
|
||||
if (distance < -radius)
|
||||
return OUTSIDE;
|
||||
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;
|
||||
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;
|
||||
else if (this->_planes[i].distance(b.getVertexN(this->_planes[i].normal)) < 0)
|
||||
} else if (planeToBoxVertexNDistance < 0) {
|
||||
result = INTERSECT;
|
||||
}
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
|
|
@ -45,15 +45,23 @@ private:
|
|||
glm::vec3 _nearTopRight;
|
||||
glm::vec3 _nearBottomLeft;
|
||||
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?
|
||||
|
||||
const char* debugPlaneName (int plane) const;
|
||||
|
||||
public:
|
||||
// setters for camera attributes
|
||||
void setPosition (const glm::vec3& p) { _position = p; }
|
||||
void setOrientation (const glm::vec3& d, const glm::vec3& u, const glm::vec3& 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
|
||||
void setFieldOfView ( float f ) { _fieldOfView = f; }
|
||||
void setAspectRatio ( float a ) { _aspectRatio = a; }
|
||||
|
@ -86,9 +94,9 @@ public:
|
|||
|
||||
enum {OUTSIDE, INTERSECT, INSIDE};
|
||||
|
||||
int pointInFrustum(glm::vec3 &p);
|
||||
int sphereInFrustum(glm::vec3 ¢er, float radius);
|
||||
int boxInFrustum(AABox &b);
|
||||
int pointInFrustum(const glm::vec3& point);
|
||||
int sphereInFrustum(const glm::vec3& center, float radius);
|
||||
int boxInFrustum(const AABox& box);
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -6,17 +6,23 @@
|
|||
//
|
||||
//
|
||||
|
||||
#include <stdio.h>
|
||||
#include <cstring>
|
||||
#include "SharedUtil.h"
|
||||
//#include "voxels_Log.h"
|
||||
#include "VoxelNode.h"
|
||||
#include "OctalCode.h"
|
||||
#include "AABox.h"
|
||||
|
||||
// using voxels_lib::printLog;
|
||||
|
||||
VoxelNode::VoxelNode() {
|
||||
octalCode = NULL;
|
||||
|
||||
#ifdef HAS_FALSE_COLOR
|
||||
_falseColored = false; // assume true color
|
||||
#endif
|
||||
|
||||
// default pointers to child nodes to NULL
|
||||
for (int i = 0; i < 8; i++) {
|
||||
children[i] = NULL;
|
||||
|
@ -28,10 +34,27 @@ VoxelNode::~VoxelNode() {
|
|||
|
||||
// delete all of this node's children
|
||||
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) {
|
||||
children[childIndex] = new VoxelNode();
|
||||
|
||||
|
@ -43,30 +66,60 @@ void VoxelNode::addChildAtIndex(int childIndex) {
|
|||
void VoxelNode::setColorFromAverageOfChildren() {
|
||||
int colorArray[4] = {0,0,0,0};
|
||||
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++) {
|
||||
colorArray[j] += children[i]->color[j];
|
||||
colorArray[j] += children[i]->getTrueColor()[j]; // color averaging should always be based on true colors
|
||||
}
|
||||
colorArray[3]++;
|
||||
}
|
||||
}
|
||||
|
||||
nodeColor newColor = { 0, 0, 0, 0};
|
||||
if (colorArray[3] > 4) {
|
||||
// we need at least 4 colored children to have an average color value
|
||||
// or if we have none we generate random values
|
||||
for (int c = 0; c < 3; c++) {
|
||||
// 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
|
||||
color[3] = 1;
|
||||
} else {
|
||||
// some children, but not enough
|
||||
// set this node's alpha to 0
|
||||
color[3] = 0;
|
||||
}
|
||||
newColor[3] = 1;
|
||||
}
|
||||
// actually set our color, note, if we didn't have enough children
|
||||
// this will be the default value all zeros, and therefore be marked as
|
||||
// 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
|
||||
// and in that case will delete the children and make this node
|
||||
// a leaf, returns TRUE if all the leaves are collapsed into a
|
||||
|
@ -77,16 +130,17 @@ bool VoxelNode::collapseIdenticalLeaves() {
|
|||
int red,green,blue;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
// 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;
|
||||
//printLog("SADNESS child missing or not colored! i=%d\n",i);
|
||||
break;
|
||||
} else {
|
||||
if (i==0) {
|
||||
red = children[i]->color[0];
|
||||
green = children[i]->color[1];
|
||||
blue = children[i]->color[2];
|
||||
} else if (red != children[i]->color[0] || green != children[i]->color[1] || blue != children[i]->color[2]) {
|
||||
red = children[i]->getColor()[0];
|
||||
green = children[i]->getColor()[1];
|
||||
blue = children[i]->getColor()[2];
|
||||
} else if (red != children[i]->getColor()[0] ||
|
||||
green != children[i]->getColor()[1] || blue != children[i]->getColor()[2]) {
|
||||
allChildrenMatch=false;
|
||||
break;
|
||||
}
|
||||
|
@ -100,18 +154,22 @@ bool VoxelNode::collapseIdenticalLeaves() {
|
|||
delete children[i]; // delete all the child nodes
|
||||
children[i]=NULL; // set it to NULL
|
||||
}
|
||||
color[0]=red;
|
||||
color[1]=green;
|
||||
color[2]=blue;
|
||||
color[3]=1; // color is set
|
||||
nodeColor collapsedColor;
|
||||
collapsedColor[0]=red;
|
||||
collapsedColor[1]=green;
|
||||
collapsedColor[2]=blue;
|
||||
collapsedColor[3]=1; // color is set
|
||||
setColor(collapsedColor);
|
||||
}
|
||||
return allChildrenMatch;
|
||||
}
|
||||
|
||||
void VoxelNode::setRandomColor(int minimumBrightness) {
|
||||
nodeColor newColor;
|
||||
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__
|
||||
#define __hifi__VoxelNode__
|
||||
|
||||
#include "AABox.h"
|
||||
|
||||
typedef unsigned char colorPart;
|
||||
typedef unsigned char nodeColor[4];
|
||||
|
||||
class VoxelNode {
|
||||
private:
|
||||
nodeColor _trueColor;
|
||||
#ifndef NO_FALSE_COLOR // !NO_FALSE_COLOR means, does have false color
|
||||
nodeColor _currentColor;
|
||||
bool _falseColored;
|
||||
#endif
|
||||
public:
|
||||
VoxelNode();
|
||||
~VoxelNode();
|
||||
|
@ -20,8 +31,27 @@ public:
|
|||
bool collapseIdenticalLeaves();
|
||||
|
||||
unsigned char *octalCode;
|
||||
unsigned char color[4];
|
||||
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__) */
|
||||
|
|
|
@ -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) {
|
||||
// find the appropriate branch index based on this ancestorNode
|
||||
if (*needleCode > 0) {
|
||||
|
@ -127,8 +148,10 @@ int VoxelTree::readNodeData(VoxelNode *destinationNode,
|
|||
}
|
||||
|
||||
// pull the color for this child
|
||||
memcpy(destinationNode->children[i]->color, nodeData + bytesRead, 3);
|
||||
destinationNode->children[i]->color[3] = 1;
|
||||
nodeColor newColor;
|
||||
memcpy(newColor, nodeData + bytesRead, 3);
|
||||
newColor[3] = 1;
|
||||
destinationNode->children[i]->setColor(newColor);
|
||||
this->voxelsColored++;
|
||||
this->voxelsColoredStats.updateAverage(1);
|
||||
|
||||
|
@ -233,8 +256,11 @@ void VoxelTree::readCodeColorBufferToTree(unsigned char *codeColorBuffer) {
|
|||
|
||||
// give this node its color
|
||||
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,
|
||||
|
@ -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
|
||||
// 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.
|
||||
bool swapXandZ=true;
|
||||
bool swapXandZ=false;
|
||||
float agentX = swapXandZ ? agentPosition[2] : agentPosition[0];
|
||||
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
|
||||
if (currentVoxelNode->children[i] != NULL
|
||||
&& currentVoxelNode->children[i]->color[3] != 0) {
|
||||
&& currentVoxelNode->children[i]->isColored()) {
|
||||
|
||||
// copy in the childs color to bitstreamBuffer
|
||||
memcpy(colorPointer, currentVoxelNode->children[i]->color, 3);
|
||||
memcpy(colorPointer, currentVoxelNode->children[i]->getTrueColor(), 3);
|
||||
colorPointer += 3;
|
||||
|
||||
// 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();
|
||||
}
|
||||
|
||||
// calculate the child's position based on the parent position
|
||||
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++) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
**** disabled *****************************************************************************************/
|
||||
|
||||
// ask the child to load the bitstream buffer with their data
|
||||
childStopOctalCode = loadBitstreamBuffer(bitstreamBuffer,
|
||||
|
@ -437,7 +474,7 @@ void VoxelTree::printTreeForDebugging(VoxelNode *startNode) {
|
|||
|
||||
// create the color mask
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
@ -446,9 +483,9 @@ void VoxelTree::printTreeForDebugging(VoxelNode *startNode) {
|
|||
|
||||
// output the colors we have
|
||||
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++) {
|
||||
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 TREE_SCALE = 10;
|
||||
|
||||
// Callback function, for recuseTreeWithOperation
|
||||
typedef bool (*RecurseVoxelTreeOperation)(VoxelNode* node, bool down, void* extraData);
|
||||
|
||||
class VoxelTree {
|
||||
public:
|
||||
// when a voxel is created in the tree (object new'd)
|
||||
|
@ -53,7 +56,11 @@ public:
|
|||
|
||||
void loadVoxelsFile(const char* fileName, 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:
|
||||
void recurseNodeWithOperation(VoxelNode* node,RecurseVoxelTreeOperation operation, void* extraData);
|
||||
VoxelNode * nodeForOctalCode(VoxelNode *ancestorNode, unsigned char * needleCode, VoxelNode** parentOfFoundNode);
|
||||
VoxelNode * createMissingNode(VoxelNode *lastParentNode, unsigned char *deepestCodeToCreate);
|
||||
int readNodeData(VoxelNode *destinationNode, unsigned char * nodeData, int bufferSizeBytes);
|
||||
|
|
|
@ -5,6 +5,14 @@ set(TARGET_NAME voxel-server)
|
|||
set(ROOT_DIR ..)
|
||||
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)
|
||||
|
||||
setup_hifi_project(${TARGET_NAME})
|
||||
|
@ -14,4 +22,7 @@ include(${MACRO_DIR}/LinkHifiLibrary.cmake)
|
|||
link_hifi_library(shared ${TARGET_NAME} ${ROOT_DIR})
|
||||
|
||||
# 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