Showing the changes to interface/src/VoxelSystem.cpp (1 of 10 files). Show all
Unified · Split
| @@ -41,69 +41,53 @@ GLubyte identityIndices[] = { 0,2,1, 0,3,2, // Z- . · 40 unmodified lines | ||
| 41 | 41 | 4,5,6, 4,6,7 }; // Z+ . |
| 42 | 42 | |
| 43 | 43 | VoxelSystem::VoxelSystem() { |
| 44 | − voxelsRendered = 0; | |
| 45 | − tree = new VoxelTree(); | |
| 46 | − pthread_mutex_init(&bufferWriteLock, NULL); | |
| 44 | + _voxelsInArrays = _voxelsUpdated = 0; | |
| 45 | + _tree = new VoxelTree(); | |
| 46 | + pthread_mutex_init(&_bufferWriteLock, NULL); | |
| 47 | 47 | } |
| 48 | 48 | |
| 49 | 49 | VoxelSystem::~VoxelSystem() { |
| 50 | − delete[] readVerticesArray; | |
| 51 | − delete[] writeVerticesArray; | |
| 52 | − delete[] readColorsArray; | |
| 53 | − delete[] writeColorsArray; | |
| 54 | − delete tree; | |
| 55 | − pthread_mutex_destroy(&bufferWriteLock); | |
| 50 | + delete[] _readVerticesArray; | |
| 51 | + delete[] _writeVerticesArray; | |
| 52 | + delete[] _readColorsArray; | |
| 53 | + delete[] _writeColorsArray; | |
| 54 | + delete[] _voxelDirtyArray; | |
| 55 | + delete _tree; | |
| 56 | + pthread_mutex_destroy(&_bufferWriteLock); | |
| 56 | 57 | } |
| 57 | 58 | |
| 58 | −////////////////////////////////////////////////////////////////////////////////////////// | |
| 59 | −// Method: VoxelSystem::loadVoxelsFile() | |
| 60 | −// Description: Loads HiFidelity encoded Voxels from a binary file. The current file | |
| 61 | −// format is a stream of single voxels with NO color data. Currently | |
| 62 | −// colors are set randomly | |
| 63 | −// Complaints: Brad :) | |
| 64 | −// To Do: Need to add color data to the file. | |
| 65 | 59 | void VoxelSystem::loadVoxelsFile(const char* fileName, bool wantColorRandomizer) { |
| 66 | − | |
| 67 | − tree->loadVoxelsFile(fileName,wantColorRandomizer); | |
| 68 | − | |
| 60 | + _tree->loadVoxelsFile(fileName, wantColorRandomizer); | |
| 69 | 61 | copyWrittenDataToReadArrays(); |
| 70 | 62 | } |
| 71 | 63 | |
| 72 | −////////////////////////////////////////////////////////////////////////////////////////// | |
| 73 | −// Method: VoxelSystem::createSphere() | |
| 74 | −// Description: Creates a sphere of voxels in the local system at a given location/radius | |
| 75 | −// To Do: Move this function someplace better? I put it here because we need a | |
| 76 | −// mechanism to tell the system to redraw it's arrays after voxels are done | |
| 77 | −// being added. This is a concept mostly only understood by VoxelSystem. | |
| 78 | −// Complaints: Brad :) | |
| 79 | 64 | void VoxelSystem::createSphere(float r,float xc, float yc, float zc, float s, bool solid, bool wantColorRandomizer) { |
| 80 | − | |
| 81 | − tree->createSphere(r,xc,yc,zc,s,solid,wantColorRandomizer); | |
| 65 | + _tree->createSphere(r, xc, yc, zc, s, solid, wantColorRandomizer); | |
| 82 | 66 | setupNewVoxelsForDrawing(); |
| 83 | 67 | } |
| 84 | 68 | |
| 85 | 69 | long int VoxelSystem::getVoxelsCreated() { |
| 86 | − return tree->voxelsCreated; | |
| 70 | + return _tree->voxelsCreated; | |
| 87 | 71 | } |
| 88 | 72 | |
| 89 | 73 | float VoxelSystem::getVoxelsCreatedPerSecondAverage() { |
| 90 | − return (1 / tree->voxelsCreatedStats.getEventDeltaAverage()); | |
| 74 | + return (1 / _tree->voxelsCreatedStats.getEventDeltaAverage()); | |
| 91 | 75 | } |
| 92 | 76 | |
| 93 | 77 | long int VoxelSystem::getVoxelsColored() { |
| 94 | − return tree->voxelsColored; | |
| 78 | + return _tree->voxelsColored; | |
| 95 | 79 | } |
| 96 | 80 | |
| 97 | 81 | float VoxelSystem::getVoxelsColoredPerSecondAverage() { |
| 98 | − return (1 / tree->voxelsColoredStats.getEventDeltaAverage()); | |
| 82 | + return (1 / _tree->voxelsColoredStats.getEventDeltaAverage()); | |
| 99 | 83 | } |
| 100 | 84 | |
| 101 | 85 | long int VoxelSystem::getVoxelsBytesRead() { |
| 102 | − return tree->voxelsBytesRead; | |
| 86 | + return _tree->voxelsBytesRead; | |
| 103 | 87 | } |
| 104 | 88 | |
| 105 | 89 | float VoxelSystem::getVoxelsBytesReadPerSecondAverage() { |
| 106 | − return tree->voxelsBytesReadStats.getAverageSampleValuePerSecond(); | |
| 90 | + return _tree->voxelsBytesReadStats.getAverageSampleValuePerSecond(); | |
| 107 | 91 | } |
| 108 | 92 | |
| 109 | 93 | int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) { |
| @@ -114,11 +98,11 @@ int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) { · 4 unmodified lines | ||
| 114 | 98 | switch(command) { |
| 115 | 99 | case PACKET_HEADER_VOXEL_DATA: |
| 116 | 100 | // ask the VoxelTree to read the bitstream into the tree |
| 117 | − tree->readBitstreamToTree(voxelData, numBytes - 1); | |
| 101 | + _tree->readBitstreamToTree(voxelData, numBytes - 1); | |
| 118 | 102 | break; |
| 119 | 103 | case PACKET_HEADER_ERASE_VOXEL: |
| 120 | 104 | // ask the tree to read the "remove" bitstream |
| 121 | − tree->processRemoveVoxelBitstream(sourceBuffer, numBytes); | |
| 105 | + _tree->processRemoveVoxelBitstream(sourceBuffer, numBytes); | |
| 122 | 106 | break; |
| 123 | 107 | case PACKET_HEADER_Z_COMMAND: |
| 124 | 108 | |
| @@ -135,7 +119,8 @@ int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) { · 10 unmodified lines | ||
| 135 | 119 | while (totalLength <= numBytes) { |
| 136 | 120 | if (0==strcmp(command,(char*)"erase all")) { |
| 137 | 121 | printLog("got Z message == erase all\n"); |
| 138 | − tree->eraseAllVoxels(); | |
| 122 | + _tree->eraseAllVoxels(); | |
| 123 | + _voxelsInArrays = 0; // better way to do this?? | |
| 139 | 124 | } |
| 140 | 125 | if (0==strcmp(command,(char*)"add scene")) { |
| 141 | 126 | printLog("got Z message == add scene - NOT SUPPORTED ON INTERFACE\n"); |
| @@ -150,78 +135,87 @@ int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) { · 8 unmodified lines | ||
| 150 | 135 | } |
| 151 | 136 | |
| 152 | 137 | void VoxelSystem::setupNewVoxelsForDrawing() { |
| 153 | − // reset the verticesEndPointer so we're writing to the beginning of the array | |
| 154 | − writeVerticesEndPointer = writeVerticesArray; | |
| 155 | − // call recursive function to populate in memory arrays | |
| 156 | − // it will return the number of voxels added | |
| 157 | − glm::vec3 treeRoot = glm::vec3(0,0,0); | |
| 158 | − voxelsRendered = treeToArrays(tree->rootNode, treeRoot); | |
| 138 | + _voxelsUpdated = newTreeToArrays(_tree->rootNode); | |
| 139 | + if (_voxelsUpdated) { | |
| 140 | + _voxelsDirty=true; | |
| 141 | + } | |
| 142 | + | |
| 159 | 143 | // copy the newly written data to the arrays designated for reading |
| 160 | 144 | copyWrittenDataToReadArrays(); |
| 161 | 145 | } |
| 162 | 146 | |
| 163 | 147 | void VoxelSystem::copyWrittenDataToReadArrays() { |
| 164 | − // lock on the buffer write lock so we can't modify the data when the GPU is reading it | |
| 165 | − pthread_mutex_lock(&bufferWriteLock); | |
| 166 | − // store a pointer to the current end so it doesn't change during copy | |
| 167 | − GLfloat *endOfCurrentVerticesData = writeVerticesEndPointer; | |
| 168 | − // copy the vertices and colors | |
| 169 | − memcpy(readVerticesArray, writeVerticesArray, (endOfCurrentVerticesData - writeVerticesArray) * sizeof(GLfloat)); | |
| 170 | − memcpy(readColorsArray, writeColorsArray, (endOfCurrentVerticesData - writeVerticesArray) * sizeof(GLubyte)); | |
| 171 | − // set the read vertices end pointer to the correct spot so the GPU knows how much to pull | |
| 172 | − readVerticesEndPointer = readVerticesArray + (endOfCurrentVerticesData - writeVerticesArray); | |
| 173 | − pthread_mutex_unlock(&bufferWriteLock); | |
| 148 | + if (_voxelsDirty) { | |
| 149 | + // lock on the buffer write lock so we can't modify the data when the GPU is reading it | |
| 150 | + pthread_mutex_lock(&_bufferWriteLock); | |
| 151 | + int bytesOfVertices = (_voxelsInArrays * VERTEX_POINTS_PER_VOXEL) * sizeof(GLfloat); | |
| 152 | + int bytesOfColors = (_voxelsInArrays * VERTEX_POINTS_PER_VOXEL) * sizeof(GLubyte); | |
| 153 | + memcpy(_readVerticesArray, _writeVerticesArray, bytesOfVertices); | |
| 154 | + memcpy(_readColorsArray, _writeColorsArray, bytesOfColors ); | |
| 155 | + pthread_mutex_unlock(&_bufferWriteLock); | |
| 156 | + } | |
| 174 | 157 | } |
| 175 | 158 | |
| 176 | −int VoxelSystem::treeToArrays(VoxelNode* currentNode, const glm::vec3& nodePosition) { | |
| 177 | − int voxelsAdded = 0; | |
| 178 | − float halfUnitForVoxel = powf(0.5, *currentNode->octalCode) * (0.5 * TREE_SCALE); | |
| 179 | − glm::vec3 viewerPosition = _camera->getPosition(); //_viewerAvatar->getPosition(); | |
| 180 | − | |
| 181 | − // debug LOD code | |
| 182 | − glm::vec3 debugNodePosition; | |
| 183 | − copyFirstVertexForCode(currentNode->octalCode,(float*)&debugNodePosition); | |
| 184 | − | |
| 185 | − float distanceToVoxelCenter = sqrtf(powf(viewerPosition.x - nodePosition[0] - halfUnitForVoxel, 2) + | |
| 186 | − powf(viewerPosition.y - nodePosition[1] - halfUnitForVoxel, 2) + | |
| 187 | − powf(viewerPosition.z - nodePosition[2] - halfUnitForVoxel, 2)); | |
| 188 | − | |
| 189 | − int renderLevel = *currentNode->octalCode + 1; | |
| 190 | − int boundaryPosition = boundaryDistanceForRenderLevel(renderLevel); | |
| 191 | − bool alwaysDraw = false; // XXXBHG - temporary debug code. Flip this to true to disable LOD blurring | |
| 192 | − | |
| 193 | − if (alwaysDraw || distanceToVoxelCenter < boundaryPosition) { | |
| 194 | − for (int i = 0; i < 8; i++) { | |
| 195 | − // check if there is a child here | |
| 196 | − if (currentNode->children[i] != NULL) { | |
| 197 | − | |
| 198 | − glm::vec3 childNodePosition; | |
| 199 | − copyFirstVertexForCode(currentNode->children[i]->octalCode,(float*)&childNodePosition); | |
| 200 | − childNodePosition *= (float)TREE_SCALE; // scale it up | |
| 201 | − voxelsAdded += treeToArrays(currentNode->children[i], childNodePosition); | |
| 202 | − } | |
| 159 | +int VoxelSystem::newTreeToArrays(VoxelNode* node) { | |
| 160 | + assert(_viewFrustum); // you must set up _viewFrustum before calling this | |
| 161 | + int voxelsUpdated = 0; | |
| 162 | + float distanceToNode = node->distanceToCamera(*_viewFrustum); | |
| 163 | + float boundary = boundaryDistanceForRenderLevel(*node->octalCode + 1); | |
| 164 | + float childBoundary = boundaryDistanceForRenderLevel(*node->octalCode + 2); | |
| 165 | + bool inBoundary = (distanceToNode <= boundary); | |
| 166 | + bool inChildBoundary = (distanceToNode <= childBoundary); | |
| 167 | + bool shouldRender = node->isColored() && ((node->isLeaf() && inChildBoundary) || (inBoundary && !inChildBoundary)); | |
| 168 | + | |
| 169 | + node->setShouldRender(shouldRender); | |
| 170 | + // let children figure out their renderness | |
| 171 | + for (int i = 0; i < 8; i++) { | |
| 172 | + if (node->children[i]) { | |
| 173 | + voxelsUpdated += newTreeToArrays(node->children[i]); | |
| 203 | 174 | } |
| 204 | 175 | } |
| 176 | + | |
| 177 | + // Now, if we've changed any attributes (our renderness, our color, etc) then update the Arrays... for us | |
| 178 | + if (node->isDirty() && (shouldRender || node->isKnownBufferIndex())) { | |
| 179 | + glm::vec3 startVertex; | |
| 180 | + float voxelScale = 0; | |
| 181 | + | |
| 182 | + // If we're should render, use our legit location and scale, | |
| 183 | + if (node->getShouldRender()) { | |
| 184 | + copyFirstVertexForCode(node->octalCode, (float*)&startVertex); | |
| 185 | + voxelScale = (1 / powf(2, *node->octalCode)); | |
| 186 | + } else { | |
| 187 | + // if we shouldn't render then set out location to some infinitely distant location, | |
| 188 | + // and our scale as infinitely small | |
| 189 | + startVertex[0] = startVertex[1] = startVertex[2] = FLT_MAX; | |
| 190 | + voxelScale = 0; | |
| 191 | + } | |
| 205 | 192 | |
| 206 | − // if we didn't get any voxels added then we're a leaf | |
| 207 | − // add our vertex and color information to the interleaved array | |
| 208 | − if (voxelsAdded == 0 && currentNode->isColored()) { | |
| 209 | − float startVertex[3]; | |
| 210 | − copyFirstVertexForCode(currentNode->octalCode,(float*)&startVertex); | |
| 211 | − float voxelScale = 1 / powf(2, *currentNode->octalCode); | |
| 193 | + // If this node has not yet been written to the array, then add it to the end of the array. | |
| 194 | + glBufferIndex nodeIndex; | |
| 195 | + if (node->isKnownBufferIndex()) { | |
| 196 | + nodeIndex = node->getBufferIndex(); | |
| 197 | + } else { | |
| 198 | + nodeIndex = _voxelsInArrays; | |
| 199 | + } | |
| 200 | + | |
| 201 | + _voxelDirtyArray[nodeIndex] = true; | |
| 212 | 202 | |
| 213 | 203 | // populate the array with points for the 8 vertices |
| 214 | 204 | // and RGB color for each added vertex |
| 215 | 205 | for (int j = 0; j < VERTEX_POINTS_PER_VOXEL; j++ ) { |
| 216 | − *writeVerticesEndPointer = startVertex[j % 3] + (identityVertices[j] * voxelScale); | |
| 217 | − *(writeColorsArray + (writeVerticesEndPointer - writeVerticesArray)) = currentNode->getColor()[j % 3]; | |
| 218 | − | |
| 219 | − writeVerticesEndPointer++; | |
| 206 | + GLfloat* writeVerticesAt = _writeVerticesArray + (nodeIndex * VERTEX_POINTS_PER_VOXEL); | |
| 207 | + GLubyte* writeColorsAt = _writeColorsArray + (nodeIndex * VERTEX_POINTS_PER_VOXEL); | |
| 208 | + *(writeVerticesAt+j) = startVertex[j % 3] + (identityVertices[j] * voxelScale); | |
| 209 | + *(writeColorsAt +j) = node->getColor()[j % 3]; | |
| 210 | + } | |
| 211 | + if (!node->isKnownBufferIndex()) { | |
| 212 | + node->setBufferIndex(nodeIndex); | |
| 213 | + _voxelsInArrays++; // our know vertices in the arrays | |
| 220 | 214 | } |
| 221 | − voxelsAdded++; | |
| 215 | + voxelsUpdated++; | |
| 216 | + node->clearDirtyBit(); | |
| 222 | 217 | } |
| 223 | − | |
| 224 | − return voxelsAdded; | |
| 218 | + return voxelsUpdated; | |
| 225 | 219 | } |
| 226 | 220 | |
| 227 | 221 | VoxelSystem* VoxelSystem::clone() const { |
| @@ -230,20 +224,30 @@ VoxelSystem* VoxelSystem::clone() const { · 2 unmodified lines | ||
| 230 | 224 | } |
| 231 | 225 | |
| 232 | 226 | void VoxelSystem::init() { |
| 227 | + | |
| 228 | + // When we change voxels representations in the arrays, we'll update this | |
| 229 | + _voxelsDirty = false; | |
| 230 | + _voxelsInArrays = 0; | |
| 231 | + | |
| 232 | + // we will track individual dirty sections with this array of bools | |
| 233 | + _voxelDirtyArray = new bool[MAX_VOXELS_PER_SYSTEM]; | |
| 234 | + memset(_voxelDirtyArray, false, MAX_VOXELS_PER_SYSTEM * sizeof(bool)); | |
| 235 | + | |
| 233 | 236 | // prep the data structures for incoming voxel data |
| 234 | − writeVerticesEndPointer = writeVerticesArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * MAX_VOXELS_PER_SYSTEM]; | |
| 235 | − readVerticesEndPointer = readVerticesArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * MAX_VOXELS_PER_SYSTEM]; | |
| 236 | − writeColorsArray = new GLubyte[VERTEX_POINTS_PER_VOXEL * MAX_VOXELS_PER_SYSTEM]; | |
| 237 | − readColorsArray = new GLubyte[VERTEX_POINTS_PER_VOXEL * MAX_VOXELS_PER_SYSTEM]; | |
| 237 | + _writeVerticesArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * MAX_VOXELS_PER_SYSTEM]; | |
| 238 | + _readVerticesArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * MAX_VOXELS_PER_SYSTEM]; | |
| 239 | + | |
| 240 | + _writeColorsArray = new GLubyte[VERTEX_POINTS_PER_VOXEL * MAX_VOXELS_PER_SYSTEM]; | |
| 241 | + _readColorsArray = new GLubyte[VERTEX_POINTS_PER_VOXEL * MAX_VOXELS_PER_SYSTEM]; | |
| 238 | 242 | |
| 239 | − GLuint *indicesArray = new GLuint[INDICES_PER_VOXEL * MAX_VOXELS_PER_SYSTEM]; | |
| 243 | + GLuint* indicesArray = new GLuint[INDICES_PER_VOXEL * MAX_VOXELS_PER_SYSTEM]; | |
| 240 | 244 | |
| 241 | 245 | // populate the indicesArray |
| 242 | 246 | // this will not change given new voxels, so we can set it all up now |
| 243 | 247 | for (int n = 0; n < MAX_VOXELS_PER_SYSTEM; n++) { |
| 244 | 248 | // fill the indices array |
| 245 | 249 | int voxelIndexOffset = n * INDICES_PER_VOXEL; |
| 246 | − GLuint *currentIndicesPos = indicesArray + voxelIndexOffset; | |
| 250 | + GLuint* currentIndicesPos = indicesArray + voxelIndexOffset; | |
| 247 | 251 | int startIndex = (n * VERTICES_PER_VOXEL); |
| 248 | 252 | |
| 249 | 253 | for (int i = 0; i < INDICES_PER_VOXEL; i++) { |
| @@ -252,8 +256,8 @@ void VoxelSystem::init() { · 2 unmodified lines | ||
| 252 | 256 | } |
| 253 | 257 | } |
| 254 | 258 | |
| 255 | − GLfloat *normalsArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * MAX_VOXELS_PER_SYSTEM]; | |
| 256 | − GLfloat *normalsArrayEndPointer = normalsArray; | |
| 259 | + GLfloat* normalsArray = new GLfloat[VERTEX_POINTS_PER_VOXEL * MAX_VOXELS_PER_SYSTEM]; | |
| 260 | + GLfloat* normalsArrayEndPointer = normalsArray; | |
| 257 | 261 | |
| 258 | 262 | // populate the normalsArray |
| 259 | 263 | for (int n = 0; n < MAX_VOXELS_PER_SYSTEM; n++) { |
| @@ -263,25 +267,25 @@ void VoxelSystem::init() { · 3 unmodified lines | ||
| 263 | 267 | } |
| 264 | 268 | |
| 265 | 269 | // VBO for the verticesArray |
| 266 | − glGenBuffers(1, &vboVerticesID); | |
| 267 | − glBindBuffer(GL_ARRAY_BUFFER, vboVerticesID); | |
| 270 | + glGenBuffers(1, &_vboVerticesID); | |
| 271 | + glBindBuffer(GL_ARRAY_BUFFER, _vboVerticesID); | |
| 268 | 272 | glBufferData(GL_ARRAY_BUFFER, VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat) * MAX_VOXELS_PER_SYSTEM, NULL, GL_DYNAMIC_DRAW); |
| 269 | 273 | |
| 270 | 274 | // VBO for the normalsArray |
| 271 | − glGenBuffers(1, &vboNormalsID); | |
| 272 | − glBindBuffer(GL_ARRAY_BUFFER, vboNormalsID); | |
| 275 | + glGenBuffers(1, &_vboNormalsID); | |
| 276 | + glBindBuffer(GL_ARRAY_BUFFER, _vboNormalsID); | |
| 273 | 277 | glBufferData(GL_ARRAY_BUFFER, |
| 274 | 278 | VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat) * MAX_VOXELS_PER_SYSTEM, |
| 275 | 279 | normalsArray, GL_STATIC_DRAW); |
| 276 | 280 | |
| 277 | 281 | // VBO for colorsArray |
| 278 | − glGenBuffers(1, &vboColorsID); | |
| 279 | − glBindBuffer(GL_ARRAY_BUFFER, vboColorsID); | |
| 282 | + glGenBuffers(1, &_vboColorsID); | |
| 283 | + glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID); | |
| 280 | 284 | glBufferData(GL_ARRAY_BUFFER, VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte) * MAX_VOXELS_PER_SYSTEM, NULL, GL_DYNAMIC_DRAW); |
| 281 | 285 | |
| 282 | 286 | // VBO for the indicesArray |
| 283 | − glGenBuffers(1, &vboIndicesID); | |
| 284 | − glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboIndicesID); | |
| 287 | + glGenBuffers(1, &_vboIndicesID); | |
| 288 | + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vboIndicesID); | |
| 285 | 289 | glBufferData(GL_ELEMENT_ARRAY_BUFFER, |
| 286 | 290 | INDICES_PER_VOXEL * sizeof(GLuint) * MAX_VOXELS_PER_SYSTEM, |
| 287 | 291 | indicesArray, GL_STATIC_DRAW); |
| @@ -291,45 +295,68 @@ void VoxelSystem::init() { · 3 unmodified lines | ||
| 291 | 295 | delete[] normalsArray; |
| 292 | 296 | } |
| 293 | 297 | |
| 294 | −void VoxelSystem::render() { | |
| 295 | − | |
| 296 | − glPushMatrix(); | |
| 297 | − | |
| 298 | − if (readVerticesEndPointer != readVerticesArray) { | |
| 299 | − // try to lock on the buffer write | |
| 300 | − // just avoid pulling new data if it is currently being written | |
| 301 | − if (pthread_mutex_trylock(&bufferWriteLock) == 0) { | |
| 302 | − | |
| 303 | − glBindBuffer(GL_ARRAY_BUFFER, vboVerticesID); | |
| 304 | − glBufferSubData(GL_ARRAY_BUFFER, 0, (readVerticesEndPointer - readVerticesArray) * sizeof(GLfloat), readVerticesArray); | |
| 305 | − | |
| 306 | − glBindBuffer(GL_ARRAY_BUFFER, vboColorsID); | |
| 307 | − glBufferSubData(GL_ARRAY_BUFFER, 0, (readVerticesEndPointer - readVerticesArray) * sizeof(GLubyte), readColorsArray); | |
| 308 | − | |
| 309 | − readVerticesEndPointer = readVerticesArray; | |
| 310 | − | |
| 311 | − pthread_mutex_unlock(&bufferWriteLock); | |
| 298 | +void VoxelSystem::updateVBOs() { | |
| 299 | + if (_voxelsDirty) { | |
| 300 | + glBufferIndex segmentStart = 0; | |
| 301 | + glBufferIndex segmentEnd = 0; | |
| 302 | + | |
| 303 | + bool inSegment = false; | |
| 304 | + for (glBufferIndex i = 0; i < _voxelsInArrays; i++) { | |
| 305 | + if (!inSegment) { | |
| 306 | + if (_voxelDirtyArray[i]) { | |
| 307 | + segmentStart = i; | |
| 308 | + inSegment = true; | |
| 309 | + _voxelDirtyArray[i] = false; // consider us clean! | |
| 310 | + } | |
| 311 | + } else { | |
| 312 | + if (!_voxelDirtyArray[i] || (i == (_voxelsInArrays - 1)) ) { | |
| 313 | + segmentEnd = i; | |
| 314 | + inSegment = false; | |
| 315 | + int segmentLength = (segmentEnd - segmentStart) + 1; | |
| 316 | + | |
| 317 | + // vertices for segment - note: we might not need to do this | |
| 318 | + GLintptr segmentStartAt = segmentStart * VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat); | |
| 319 | + GLsizeiptr segmentSizeBytes = segmentLength * VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat); | |
| 320 | + GLfloat* readVerticesFrom = _readVerticesArray + (segmentStart * VERTEX_POINTS_PER_VOXEL); | |
| 321 | + | |
| 322 | + glBindBuffer(GL_ARRAY_BUFFER, _vboVerticesID); | |
| 323 | + glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readVerticesFrom); | |
| 324 | + | |
| 325 | + // colors for segment | |
| 326 | + segmentStartAt = segmentStart * VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte); | |
| 327 | + segmentSizeBytes = segmentLength * VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte); | |
| 328 | + GLubyte* readColorsFrom = _readColorsArray + (segmentStart * VERTEX_POINTS_PER_VOXEL); | |
| 329 | + | |
| 330 | + glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID); | |
| 331 | + glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readColorsFrom); | |
| 332 | + } | |
| 333 | + } | |
| 312 | 334 | } |
| 335 | + _voxelsDirty = false; | |
| 313 | 336 | } |
| 337 | +} | |
| 314 | 338 | |
| 339 | +void VoxelSystem::render() { | |
| 340 | + glPushMatrix(); | |
| 341 | + updateVBOs(); | |
| 315 | 342 | // tell OpenGL where to find vertex and color information |
| 316 | 343 | glEnableClientState(GL_VERTEX_ARRAY); |
| 317 | 344 | glEnableClientState(GL_NORMAL_ARRAY); |
| 318 | 345 | glEnableClientState(GL_COLOR_ARRAY); |
| 319 | 346 | |
| 320 | − glBindBuffer(GL_ARRAY_BUFFER, vboVerticesID); | |
| 347 | + glBindBuffer(GL_ARRAY_BUFFER, _vboVerticesID); | |
| 321 | 348 | glVertexPointer(3, GL_FLOAT, 0, 0); |
| 322 | 349 | |
| 323 | − glBindBuffer(GL_ARRAY_BUFFER, vboNormalsID); | |
| 350 | + glBindBuffer(GL_ARRAY_BUFFER, _vboNormalsID); | |
| 324 | 351 | glNormalPointer(GL_FLOAT, 0, 0); |
| 325 | 352 | |
| 326 | − glBindBuffer(GL_ARRAY_BUFFER, vboColorsID); | |
| 353 | + glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID); | |
| 327 | 354 | glColorPointer(3, GL_UNSIGNED_BYTE, 0, 0); |
| 328 | 355 | |
| 329 | 356 | // draw the number of voxels we have |
| 330 | − glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboIndicesID); | |
| 357 | + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vboIndicesID); | |
| 331 | 358 | glScalef(10, 10, 10); |
| 332 | − glDrawElements(GL_TRIANGLES, 36 * voxelsRendered, GL_UNSIGNED_INT, 0); | |
| 359 | + glDrawElements(GL_TRIANGLES, 36 * _voxelsInArrays, GL_UNSIGNED_INT, 0); | |
| 333 | 360 | |
| 334 | 361 | // deactivate vertex and color arrays after drawing |
| 335 | 362 | glDisableClientState(GL_VERTEX_ARRAY); |
| @@ -350,12 +377,7 @@ void VoxelSystem::simulate(float deltaTime) { · 14 unmodified lines | ||
| 350 | 377 | |
| 351 | 378 | int VoxelSystem::_nodeCount = 0; |
| 352 | 379 | |
| 353 | −bool VoxelSystem::randomColorOperation(VoxelNode* node, bool down, void* extraData) { | |
| 354 | − | |
| 355 | − // we do our operations on the way up! | |
| 356 | − if (down) { | |
| 357 | − return true; | |
| 358 | − } | |
| 380 | +bool VoxelSystem::randomColorOperation(VoxelNode* node, void* extraData) { | |
| 359 | 381 | |
| 360 | 382 | _nodeCount++; |
| 361 | 383 | if (node->isColored()) { |
| @@ -370,17 +392,12 @@ bool VoxelSystem::randomColorOperation(VoxelNode* node, bool down, void* extraDa · 8 unmodified lines | ||
| 370 | 392 | |
| 371 | 393 | void VoxelSystem::randomizeVoxelColors() { |
| 372 | 394 | _nodeCount = 0; |
| 373 | − tree->recurseTreeWithOperation(randomColorOperation); | |
| 395 | + _tree->recurseTreeWithOperation(randomColorOperation); | |
| 374 | 396 | printLog("setting randomized true color for %d nodes\n",_nodeCount); |
| 375 | 397 | setupNewVoxelsForDrawing(); |
| 376 | 398 | } |
| 377 | 399 | |
| 378 | −bool VoxelSystem::falseColorizeRandomOperation(VoxelNode* node, bool down, void* extraData) { | |
| 379 | − | |
| 380 | − // we do our operations on the way up! | |
| 381 | − if (down) { | |
| 382 | − return true; | |
| 383 | − } | |
| 400 | +bool VoxelSystem::falseColorizeRandomOperation(VoxelNode* node, void* extraData) { | |
| 384 | 401 | |
| 385 | 402 | _nodeCount++; |
| 386 | 403 | |
| @@ -395,18 +412,12 @@ bool VoxelSystem::falseColorizeRandomOperation(VoxelNode* node, bool down, void* · 8 unmodified lines | ||
| 395 | 412 | |
| 396 | 413 | void VoxelSystem::falseColorizeRandom() { |
| 397 | 414 | _nodeCount = 0; |
| 398 | − tree->recurseTreeWithOperation(falseColorizeRandomOperation); | |
| 415 | + _tree->recurseTreeWithOperation(falseColorizeRandomOperation); | |
| 399 | 416 | printLog("setting randomized false color for %d nodes\n",_nodeCount); |
| 400 | 417 | setupNewVoxelsForDrawing(); |
| 401 | 418 | } |
| 402 | 419 | |
| 403 | −bool VoxelSystem::trueColorizeOperation(VoxelNode* node, bool down, void* extraData) { | |
| 404 | − | |
| 405 | − // we do our operations on the way up! | |
| 406 | − if (down) { | |
| 407 | − return true; | |
| 408 | − } | |
| 409 | − | |
| 420 | +bool VoxelSystem::trueColorizeOperation(VoxelNode* node, void* extraData) { | |
| 410 | 421 | _nodeCount++; |
| 411 | 422 | node->setFalseColored(false); |
| 412 | 423 | return true; |
| @@ -414,19 +425,13 @@ bool VoxelSystem::trueColorizeOperation(VoxelNode* node, bool down, void* extraD · 1 unmodified line | ||
| 414 | 425 | |
| 415 | 426 | void VoxelSystem::trueColorize() { |
| 416 | 427 | _nodeCount = 0; |
| 417 | − tree->recurseTreeWithOperation(trueColorizeOperation); | |
| 428 | + _tree->recurseTreeWithOperation(trueColorizeOperation); | |
| 418 | 429 | printLog("setting true color for %d nodes\n",_nodeCount); |
| 419 | 430 | setupNewVoxelsForDrawing(); |
| 420 | 431 | } |
| 421 | 432 | |
| 422 | 433 | // Will false colorize voxels that are not in view |
| 423 | −bool VoxelSystem::falseColorizeInViewOperation(VoxelNode* node, bool down, void* extraData) { | |
| 424 | − | |
| 425 | − // we do our operations on the way up! | |
| 426 | − if (down) { | |
| 427 | − return true; | |
| 428 | − } | |
| 429 | − | |
| 434 | +bool VoxelSystem::falseColorizeInViewOperation(VoxelNode* node, void* extraData) { | |
| 430 | 435 | const ViewFrustum* viewFrustum = (const ViewFrustum*) extraData; |
| 431 | 436 | |
| 432 | 437 | _nodeCount++; |
| @@ -448,25 +453,17 @@ bool VoxelSystem::falseColorizeInViewOperation(VoxelNode* node, bool down, void* · 15 unmodified lines | ||
| 448 | 453 | |
| 449 | 454 | void VoxelSystem::falseColorizeInView(ViewFrustum* viewFrustum) { |
| 450 | 455 | _nodeCount = 0; |
| 451 | − tree->recurseTreeWithOperation(falseColorizeInViewOperation,(void*)viewFrustum); | |
| 456 | + _tree->recurseTreeWithOperation(falseColorizeInViewOperation,(void*)viewFrustum); | |
| 452 | 457 | printLog("setting in view false color for %d nodes\n",_nodeCount); |
| 453 | 458 | setupNewVoxelsForDrawing(); |
| 454 | 459 | } |
| 455 | 460 | |
| 456 | 461 | // Will false colorize voxels based on distance from view |
| 457 | −bool VoxelSystem::falseColorizeDistanceFromViewOperation(VoxelNode* node, bool down, void* extraData) { | |
| 458 | − | |
| 459 | − // we do our operations on the way up! | |
| 460 | − if (down) { | |
| 461 | − return true; | |
| 462 | − } | |
| 463 | − | |
| 462 | +bool VoxelSystem::falseColorizeDistanceFromViewOperation(VoxelNode* node, void* extraData) { | |
| 464 | 463 | ViewFrustum* viewFrustum = (ViewFrustum*) extraData; |
| 465 | 464 | |
| 466 | 465 | // only do this for truly colored voxels... |
| 467 | 466 | if (node->isColored()) { |
| 468 | − | |
| 469 | − // We need our distance for both up and down | |
| 470 | 467 | glm::vec3 nodePosition; |
| 471 | 468 | float* startVertex = firstVertexForCode(node->octalCode); |
| 472 | 469 | nodePosition.x = startVertex[0]; |
| @@ -508,13 +505,7 @@ float VoxelSystem::_minDistance = FLT_MAX; · 35 unmodified lines | ||
| 508 | 505 | // Helper function will get the distance from view range, would be nice if you could just keep track |
| 509 | 506 | // of this as voxels are created and/or colored... seems like some transform math could do that so |
| 510 | 507 | // we wouldn't need to do two passes of the tree |
| 511 | −bool VoxelSystem::getDistanceFromViewRangeOperation(VoxelNode* node, bool down, void* extraData) { | |
| 512 | − | |
| 513 | − // we do our operations on the way up! | |
| 514 | − if (down) { | |
| 515 | − return true; | |
| 516 | − } | |
| 517 | − | |
| 508 | +bool VoxelSystem::getDistanceFromViewRangeOperation(VoxelNode* node, void* extraData) { | |
| 518 | 509 | ViewFrustum* viewFrustum = (ViewFrustum*) extraData; |
| 519 | 510 | |
| 520 | 511 | // only do this for truly colored voxels... |
| @@ -538,7 +529,7 @@ bool VoxelSystem::getDistanceFromViewRangeOperation(VoxelNode* node, bool down, · 17 unmodified lines | ||
| 538 | 529 | powf(viewerPosition.y - nodePosition.y - halfUnitForVoxel, 2) + |
| 539 | 530 | powf(viewerPosition.z - nodePosition.z - halfUnitForVoxel, 2)); |
| 540 | 531 | |
| 541 | − // on way down, calculate the range of distances | |
| 532 | + // calculate the range of distances | |
| 542 | 533 | if (distance > _maxDistance) { |
| 543 | 534 | _maxDistance = distance; |
| 544 | 535 | } |
| @@ -556,12 +547,14 @@ void VoxelSystem::falseColorizeDistanceFromView(ViewFrustum* viewFrustum) { · 11 unmodified lines | ||
| 556 | 547 | |
| 557 | 548 | _maxDistance = 0.0; |
| 558 | 549 | _minDistance = FLT_MAX; |
| 559 | − tree->recurseTreeWithOperation(getDistanceFromViewRangeOperation,(void*)viewFrustum); | |
| 550 | + _tree->recurseTreeWithOperation(getDistanceFromViewRangeOperation,(void*)viewFrustum); | |
| 560 | 551 | printLog("determining distance range for %d nodes\n",_nodeCount); |
| 561 | 552 | |
| 562 | 553 | _nodeCount = 0; |
| 563 | 554 | |
| 564 | − tree->recurseTreeWithOperation(falseColorizeDistanceFromViewOperation,(void*)viewFrustum); | |
| 555 | + _tree->recurseTreeWithOperation(falseColorizeDistanceFromViewOperation,(void*)viewFrustum); | |
| 565 | 556 | printLog("setting in distance false color for %d nodes\n",_nodeCount); |
| 566 | 557 | setupNewVoxelsForDrawing(); |
| 567 | 558 | } |
| 559 | + | |
| 560 | + | |