History

second cut at view culling voxels

ZappoMan committed 13 years ago

Commit 09923d11 parent 89226b12 files · +115 −51Browse files

Showing the changes to interface/src/VoxelSystem.cpp (1 of 2 files). Show all

Unified · Split

interface/src/VoxelSystem.cpp+107−49
@@ -42,7 +42,8 @@ GLubyte identityIndices[] = { 0,2,1, 0,3,2, // Z- . · 41 unmodified lines
42 4,5,6, 4,6,7 }; // Z+ .42 4,5,6, 4,6,7 }; // Z+ .
43 43
44VoxelSystem::VoxelSystem() {44VoxelSystem::VoxelSystem() {
45 _voxelsInArrays = _voxelsUpdated = 0;45 _voxelsInReadArrays = _voxelsInWriteArrays = _voxelsUpdated = 0;
46 _alwaysRenderFullVBO = true;
46 _tree = new VoxelTree();47 _tree = new VoxelTree();
47 pthread_mutex_init(&_bufferWriteLock, NULL);48 pthread_mutex_init(&_bufferWriteLock, NULL);
48 pthread_mutex_init(&_voxelCleanupLock, NULL);49 pthread_mutex_init(&_voxelCleanupLock, NULL);
@@ -61,7 +62,7 @@ VoxelSystem::~VoxelSystem() { · 12 unmodified lines
61 62
62void VoxelSystem::loadVoxelsFile(const char* fileName, bool wantColorRandomizer) {63void VoxelSystem::loadVoxelsFile(const char* fileName, bool wantColorRandomizer) {
63 _tree->loadVoxelsFile(fileName, wantColorRandomizer);64 _tree->loadVoxelsFile(fileName, wantColorRandomizer);
64 copyWrittenDataToReadArrays();65 setupNewVoxelsForDrawing();
65}66}
66 67
67void VoxelSystem::createSphere(float r,float xc, float yc, float zc, float s, bool solid, bool wantColorRandomizer) {68void VoxelSystem::createSphere(float r,float xc, float yc, float zc, float s, bool solid, bool wantColorRandomizer) {
@@ -130,7 +131,7 @@ int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) { · 62 unmodified lines
130 if (0==strcmp(command,(char*)"erase all")) {131 if (0==strcmp(command,(char*)"erase all")) {
131 printLog("got Z message == erase all\n");132 printLog("got Z message == erase all\n");
132 _tree->eraseAllVoxels();133 _tree->eraseAllVoxels();
133 _voxelsInArrays = 0; // better way to do this??134 _voxelsInReadArrays = _voxelsInWriteArrays = 0; // better way to do this??
134 }135 }
135 if (0==strcmp(command,(char*)"add scene")) {136 if (0==strcmp(command,(char*)"add scene")) {
136 printLog("got Z message == add scene - NOT SUPPORTED ON INTERFACE\n");137 printLog("got Z message == add scene - NOT SUPPORTED ON INTERFACE\n");
@@ -145,34 +146,41 @@ int VoxelSystem::parseData(unsigned char* sourceBuffer, int numBytes) { · 8 unmodified lines
145}146}
146 147
147void VoxelSystem::setupNewVoxelsForDrawing() {148void VoxelSystem::setupNewVoxelsForDrawing() {
148 PerformanceWarning warn(_renderWarningsOn, "copyWrittenDataToReadArrays()"); // would like to include _voxelsInArrays, _voxelsUpdated149 PerformanceWarning warn(_renderWarningsOn, "setupNewVoxelsForDrawing()"); // would like to include _voxelsInArrays, _voxelsUpdated
149 double start = usecTimestampNow();150 double start = usecTimestampNow();
150 double sinceLastTime = (start - _setupNewVoxelsForDrawingLastFinished);151 double sinceLastTime = (start - _setupNewVoxelsForDrawingLastFinished) / 1000.0;
151 152
152 if (sinceLastTime <= std::max(_setupNewVoxelsForDrawingLastElapsed,SIXTY_FPS_IN_MILLISECONDS)) {153 if (sinceLastTime <= std::max(_setupNewVoxelsForDrawingLastElapsed,SIXTY_FPS_IN_MILLISECONDS)) {
153 return; // bail early, it hasn't been long enough since the last time we ran154 return; // bail early, it hasn't been long enough since the last time we ran
154 }155 }
156
157 double sinceLastViewCulling = (start - _lastViewCulling) / 1000.0;
155 158
156 // If the view frustum has changed, since last time, then remove nodes that are out of view159 // If the view frustum has changed, since last time, then remove nodes that are out of view
157 //if (hasViewChanged()) {160 if ((sinceLastViewCulling >= VIEW_CULLING_RATE_IN_MILLISECONDS) && hasViewChanged()) {
158 // removeOutOfView();161 _lastViewCulling = start;
159 //} 162 removeOutOfView();
163 }
160 164
161 if (_tree->isDirty()) {165 if (_tree->isDirty()) {
166 PerformanceWarning warn(_renderWarningsOn, "calling... newTreeToArrays()");
162 _callsToTreesToArrays++;167 _callsToTreesToArrays++;
168
169 if (_alwaysRenderFullVBO) {
170 _voxelsInWriteArrays = 0; // reset our VBO
171 }
163 _voxelsUpdated = newTreeToArrays(_tree->rootNode);172 _voxelsUpdated = newTreeToArrays(_tree->rootNode);
164 _tree->clearDirtyBit(); // after we pull the trees into the array, we can consider the tree clean173 _tree->clearDirtyBit(); // after we pull the trees into the array, we can consider the tree clean
165 } else {174 } else {
166 _voxelsUpdated = 0;175 _voxelsUpdated = 0;
167 }176 }
177 //printLog("setupNewVoxelsForDrawing() AFTER treeToArray _voxelsUpdated=%ld _voxelsDirty=%s\n", _voxelsUpdated, (_voxelsDirty ? "yes" : "no"));
168 if (_voxelsUpdated) {178 if (_voxelsUpdated) {
169 _voxelsDirty=true;179 _voxelsDirty=true;
170 }180 }
171 181
172 if (_voxelsDirty) {182 // copy the newly written data to the arrays designated for reading, only does something if _voxelsDirty && _voxelsUpdated
173 // copy the newly written data to the arrays designated for reading183 copyWrittenDataToReadArrays();
174 copyWrittenDataToReadArrays();
175 }
176 184
177 double end = usecTimestampNow();185 double end = usecTimestampNow();
178 double elapsedmsec = (end - start)/1000.0;186 double elapsedmsec = (end - start)/1000.0;
@@ -185,16 +193,18 @@ void VoxelSystem::copyWrittenDataToReadArrays() { · 6 unmodified lines
185 if (_voxelsDirty && _voxelsUpdated) {193 if (_voxelsDirty && _voxelsUpdated) {
186 // lock on the buffer write lock so we can't modify the data when the GPU is reading it194 // lock on the buffer write lock so we can't modify the data when the GPU is reading it
187 pthread_mutex_lock(&_bufferWriteLock);195 pthread_mutex_lock(&_bufferWriteLock);
188 int bytesOfVertices = (_voxelsInArrays * VERTEX_POINTS_PER_VOXEL) * sizeof(GLfloat);196 int bytesOfVertices = (_voxelsInWriteArrays * VERTEX_POINTS_PER_VOXEL) * sizeof(GLfloat);
189 int bytesOfColors = (_voxelsInArrays * VERTEX_POINTS_PER_VOXEL) * sizeof(GLubyte);197 int bytesOfColors = (_voxelsInWriteArrays * VERTEX_POINTS_PER_VOXEL) * sizeof(GLubyte);
190 memcpy(_readVerticesArray, _writeVerticesArray, bytesOfVertices);198 memcpy(_readVerticesArray, _writeVerticesArray, bytesOfVertices);
191 memcpy(_readColorsArray, _writeColorsArray, bytesOfColors );199 memcpy(_readColorsArray, _writeColorsArray, bytesOfColors );
200 _voxelsInReadArrays = _voxelsInWriteArrays;
192 pthread_mutex_unlock(&_bufferWriteLock);201 pthread_mutex_unlock(&_bufferWriteLock);
193 }202 }
194}203}
195 204
196int VoxelSystem::newTreeToArrays(VoxelNode* node) {205int VoxelSystem::newTreeToArrays(VoxelNode* node) {
197 assert(_viewFrustum); // you must set up _viewFrustum before calling this206 assert(_viewFrustum); // you must set up _viewFrustum before calling this
207
198 int voxelsUpdated = 0;208 int voxelsUpdated = 0;
199 bool shouldRender = false; // assume we don't need to render it209 bool shouldRender = false; // assume we don't need to render it
200 210
@@ -217,9 +227,39 @@ int VoxelSystem::newTreeToArrays(VoxelNode* node) { · 16 unmodified lines
217 voxelsUpdated += newTreeToArrays(node->getChildAtIndex(i));227 voxelsUpdated += newTreeToArrays(node->getChildAtIndex(i));
218 }228 }
219 }229 }
220 230
231 if (_alwaysRenderFullVBO) {
232 voxelsUpdated += newway__updateNodeInArray(node);
233 } else {
234 voxelsUpdated += oldway__updateNodeInArray(node);
235 }
236 node->clearDirtyBit(); // always clear the dirty bit, even if it doesn't need to be rendered
237 return voxelsUpdated;
238}
239
240int VoxelSystem::newway__updateNodeInArray(VoxelNode* node) {
241 if (node->getShouldRender()) {
242 glm::vec3 startVertex = node->getCorner();
243 float voxelScale = node->getScale();
244 glBufferIndex nodeIndex = _voxelsInWriteArrays;
245
246 // populate the array with points for the 8 vertices
247 // and RGB color for each added vertex
248 for (int j = 0; j < VERTEX_POINTS_PER_VOXEL; j++ ) {
249 GLfloat* writeVerticesAt = _writeVerticesArray + (nodeIndex * VERTEX_POINTS_PER_VOXEL);
250 GLubyte* writeColorsAt = _writeColorsArray + (nodeIndex * VERTEX_POINTS_PER_VOXEL);
251 *(writeVerticesAt+j) = startVertex[j % 3] + (identityVertices[j] * voxelScale);
252 *(writeColorsAt +j) = node->getColor()[j % 3];
253 }
254 _voxelsInWriteArrays++; // our know vertices in the arrays
255 return 1; // rendered
256 }
257 return 0; // not-rendered
258}
259
260int VoxelSystem::oldway__updateNodeInArray(VoxelNode* node) {
221 // Now, if we've changed any attributes (our renderness, our color, etc) then update the Arrays... for us261 // Now, if we've changed any attributes (our renderness, our color, etc) then update the Arrays... for us
222 if (node->isDirty() && (shouldRender || node->isKnownBufferIndex())) {262 if (node->isDirty() && (node->getShouldRender() || node->isKnownBufferIndex())) {
223 glm::vec3 startVertex;263 glm::vec3 startVertex;
224 float voxelScale = 0;264 float voxelScale = 0;
225 265
@@ -239,7 +279,7 @@ int VoxelSystem::newTreeToArrays(VoxelNode* node) { · 13 unmodified lines
239 if (node->isKnownBufferIndex()) {279 if (node->isKnownBufferIndex()) {
240 nodeIndex = node->getBufferIndex();280 nodeIndex = node->getBufferIndex();
241 } else {281 } else {
242 nodeIndex = _voxelsInArrays;282 nodeIndex = _voxelsInWriteArrays;
243 }283 }
244 284
245 _voxelDirtyArray[nodeIndex] = true;285 _voxelDirtyArray[nodeIndex] = true;
@@ -254,12 +294,11 @@ int VoxelSystem::newTreeToArrays(VoxelNode* node) { · 8 unmodified lines
254 }294 }
255 if (!node->isKnownBufferIndex()) {295 if (!node->isKnownBufferIndex()) {
256 node->setBufferIndex(nodeIndex);296 node->setBufferIndex(nodeIndex);
257 _voxelsInArrays++; // our know vertices in the arrays297 _voxelsInWriteArrays++; // our know vertices in the arrays
258 }298 }
259 voxelsUpdated++;299 return 1; // updated!
260 }300 }
261 node->clearDirtyBit(); // always clear the dirty bit, even if it doesn't need to be rendered301 return 0; // not-updated
262 return voxelsUpdated;
263}302}
264 303
265VoxelSystem* VoxelSystem::clone() const {304VoxelSystem* VoxelSystem::clone() const {
@@ -273,10 +312,12 @@ void VoxelSystem::init() { · 7 unmodified lines
273 _callsToTreesToArrays = 0;312 _callsToTreesToArrays = 0;
274 _setupNewVoxelsForDrawingLastFinished = 0;313 _setupNewVoxelsForDrawingLastFinished = 0;
275 _setupNewVoxelsForDrawingLastElapsed = 0;314 _setupNewVoxelsForDrawingLastElapsed = 0;
315 _lastViewCulling = 0;
276 316
277 // When we change voxels representations in the arrays, we'll update this317 // When we change voxels representations in the arrays, we'll update this
278 _voxelsDirty = false;318 _voxelsDirty = false;
279 _voxelsInArrays = 0;319 _voxelsInWriteArrays = 0;
320 _voxelsInReadArrays = 0;
280 _unusedArraySpace = 0;321 _unusedArraySpace = 0;
281 322
282 // we will track individual dirty sections with this array of bools323 // we will track individual dirty sections with this array of bools
@@ -348,31 +389,48 @@ void VoxelSystem::init() { · 65 unmodified lines
348void VoxelSystem::updateVBOs() {389void VoxelSystem::updateVBOs() {
349 PerformanceWarning warn(_renderWarningsOn, "updateVBOs()"); // would like to include _callsToTreesToArrays390 PerformanceWarning warn(_renderWarningsOn, "updateVBOs()"); // would like to include _callsToTreesToArrays
350 if (_voxelsDirty) {391 if (_voxelsDirty) {
351 glBufferIndex segmentStart = 0;392 if (_alwaysRenderFullVBO) {
352 glBufferIndex segmentEnd = 0;393 glBufferIndex segmentStart = 0;
353 bool inSegment = false;394 glBufferIndex segmentEnd = _voxelsInWriteArrays;
354 for (glBufferIndex i = 0; i < _voxelsInArrays; i++) {395
355 if (!inSegment) {396 int segmentLength = (segmentEnd - segmentStart) + 1;
356 if (_voxelDirtyArray[i]) {397 GLintptr segmentStartAt = segmentStart * VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat);
357 segmentStart = i;398 GLsizeiptr segmentSizeBytes = segmentLength * VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat);
358 inSegment = true;399 GLfloat* readVerticesFrom = _readVerticesArray + (segmentStart * VERTEX_POINTS_PER_VOXEL);
359 _voxelDirtyArray[i] = false; // consider us clean!400 glBindBuffer(GL_ARRAY_BUFFER, _vboVerticesID);
360 }401 glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readVerticesFrom);
361 } else {402 segmentStartAt = segmentStart * VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte);
362 if (!_voxelDirtyArray[i] || (i == (_voxelsInArrays - 1)) ) {403 segmentSizeBytes = segmentLength * VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte);
363 segmentEnd = i;404 GLubyte* readColorsFrom = _readColorsArray + (segmentStart * VERTEX_POINTS_PER_VOXEL);
364 inSegment = false;405 glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID);
365 int segmentLength = (segmentEnd - segmentStart) + 1;406 glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readColorsFrom);
366 GLintptr segmentStartAt = segmentStart * VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat);407 } else {
367 GLsizeiptr segmentSizeBytes = segmentLength * VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat);408 glBufferIndex segmentStart = 0;
368 GLfloat* readVerticesFrom = _readVerticesArray + (segmentStart * VERTEX_POINTS_PER_VOXEL);409 glBufferIndex segmentEnd = 0;
369 glBindBuffer(GL_ARRAY_BUFFER, _vboVerticesID);410 bool inSegment = false;
370 glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readVerticesFrom);411 for (glBufferIndex i = 0; i < _voxelsInWriteArrays; i++) {
371 segmentStartAt = segmentStart * VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte);412 if (!inSegment) {
372 segmentSizeBytes = segmentLength * VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte);413 if (_voxelDirtyArray[i]) {
373 GLubyte* readColorsFrom = _readColorsArray + (segmentStart * VERTEX_POINTS_PER_VOXEL);414 segmentStart = i;
374 glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID);415 inSegment = true;
375 glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readColorsFrom);416 _voxelDirtyArray[i] = false; // consider us clean!
417 }
418 } else {
419 if (!_voxelDirtyArray[i] || (i == (_voxelsInWriteArrays - 1)) ) {
420 segmentEnd = i;
421 inSegment = false;
422 int segmentLength = (segmentEnd - segmentStart) + 1;
423 GLintptr segmentStartAt = segmentStart * VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat);
424 GLsizeiptr segmentSizeBytes = segmentLength * VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat);
425 GLfloat* readVerticesFrom = _readVerticesArray + (segmentStart * VERTEX_POINTS_PER_VOXEL);
426 glBindBuffer(GL_ARRAY_BUFFER, _vboVerticesID);
427 glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readVerticesFrom);
428 segmentStartAt = segmentStart * VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte);
429 segmentSizeBytes = segmentLength * VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte);
430 GLubyte* readColorsFrom = _readColorsArray + (segmentStart * VERTEX_POINTS_PER_VOXEL);
431 glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID);
432 glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readColorsFrom);
433 }
376 }434 }
377 }435 }
378 }436 }
@@ -403,7 +461,7 @@ void VoxelSystem::render() { · 24 unmodified lines
403 // draw the number of voxels we have461 // draw the number of voxels we have
404 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vboIndicesID);462 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vboIndicesID);
405 glScalef(TREE_SCALE, TREE_SCALE, TREE_SCALE);463 glScalef(TREE_SCALE, TREE_SCALE, TREE_SCALE);
406 glDrawElements(GL_TRIANGLES, 36 * _voxelsInArrays, GL_UNSIGNED_INT, 0);464 glDrawElements(GL_TRIANGLES, 36 * _voxelsInReadArrays, GL_UNSIGNED_INT, 0);
407 465
408 // deactivate vertex and color arrays after drawing466 // deactivate vertex and color arrays after drawing
409 glDisableClientState(GL_VERTEX_ARRAY);467 glDisableClientState(GL_VERTEX_ARRAY);
@@ -422,7 +480,7 @@ int VoxelSystem::_nodeCount = 0; · 12 unmodified lines
422 480
423void VoxelSystem::killLocalVoxels() {481void VoxelSystem::killLocalVoxels() {
424 _tree->eraseAllVoxels();482 _tree->eraseAllVoxels();
425 _voxelsInArrays = 0; // better way to do this??483 _voxelsInWriteArrays = _voxelsInReadArrays = 0; // better way to do this??
426 //setupNewVoxelsForDrawing();484 //setupNewVoxelsForDrawing();
427}485}
428 486