Showing the changes to interface/src/VoxelSystem.cpp (1 of 5 files). Show all
Unified · Split
| @@ -268,6 +268,7 @@ int VoxelSystem::updateNodeInArraysAsFullVBO(VoxelNode* node) { · 267 unmodified lines | |||
| 268 | *(writeColorsAt +j) = node->getColor()[j % 3]; | 268 | *(writeColorsAt +j) = node->getColor()[j % 3]; |
| 269 | } | 269 | } |
| 270 | node->setBufferIndex(nodeIndex); | 270 | node->setBufferIndex(nodeIndex); |
| 271 | _voxelDirtyArray[nodeIndex] = true; // just in case we switch to Partial mode | ||
| 271 | _voxelsInWriteArrays++; // our know vertices in the arrays | 272 | _voxelsInWriteArrays++; // our know vertices in the arrays |
| 272 | return 1; // rendered | 273 | return 1; // rendered |
| 273 | } | 274 | } |
| @@ -280,8 +281,8 @@ int VoxelSystem::updateNodeInArraysAsPartialVBO(VoxelNode* node) { · 6 unmodified lines | |||
| 280 | return 0; | 281 | return 0; |
| 281 | } | 282 | } |
| 282 | 283 | ||
| 283 | // Now, if we've changed any attributes (our renderness, our color, etc) then update the Arrays... for us | 284 | // Now, if we've changed any attributes (our renderness, our color, etc) then update the Arrays... |
| 284 | if (node->isDirty() && (node->getShouldRender() || node->isKnownBufferIndex())) { | 285 | if (node->isDirty()) { |
| 285 | glm::vec3 startVertex; | 286 | glm::vec3 startVertex; |
| 286 | float voxelScale = 0; | 287 | float voxelScale = 0; |
| 287 | // If we're should render, use our legit location and scale, | 288 | // If we're should render, use our legit location and scale, |
| @@ -301,8 +302,9 @@ int VoxelSystem::updateNodeInArraysAsPartialVBO(VoxelNode* node) { · 13 unmodified lines | |||
| 301 | nodeIndex = node->getBufferIndex(); | 302 | nodeIndex = node->getBufferIndex(); |
| 302 | } else { | 303 | } else { |
| 303 | nodeIndex = _voxelsInWriteArrays; | 304 | nodeIndex = _voxelsInWriteArrays; |
| 305 | node->setBufferIndex(nodeIndex); | ||
| 306 | _voxelsInWriteArrays++; | ||
| 304 | } | 307 | } |
| 305 | |||
| 306 | _voxelDirtyArray[nodeIndex] = true; | 308 | _voxelDirtyArray[nodeIndex] = true; |
| 307 | 309 | ||
| 308 | // populate the array with points for the 8 vertices | 310 | // populate the array with points for the 8 vertices |
| @@ -313,10 +315,6 @@ int VoxelSystem::updateNodeInArraysAsPartialVBO(VoxelNode* node) { · 4 unmodified lines | |||
| 313 | *(writeVerticesAt+j) = startVertex[j % 3] + (identityVertices[j] * voxelScale); | 315 | *(writeVerticesAt+j) = startVertex[j % 3] + (identityVertices[j] * voxelScale); |
| 314 | *(writeColorsAt +j) = node->getColor()[j % 3]; | 316 | *(writeColorsAt +j) = node->getColor()[j % 3]; |
| 315 | } | 317 | } |
| 316 | if (!node->isKnownBufferIndex()) { | ||
| 317 | node->setBufferIndex(nodeIndex); | ||
| 318 | _voxelsInWriteArrays++; // our know vertices in the arrays | ||
| 319 | } | ||
| 320 | return 1; // updated! | 318 | return 1; // updated! |
| 321 | } | 319 | } |
| 322 | return 0; // not-updated | 320 | return 0; // not-updated |
| @@ -424,11 +422,10 @@ void VoxelSystem::updateFullVBOs() { · 101 unmodified lines | |||
| 424 | glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readColorsFrom); | 422 | glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readColorsFrom); |
| 425 | 423 | ||
| 426 | // consider the _voxelDirtyArray[] clean! | 424 | // consider the _voxelDirtyArray[] clean! |
| 427 | memset(_voxelDirtyArray, false, MAX_VOXELS_PER_SYSTEM * sizeof(bool)); | 425 | memset(_voxelDirtyArray, false, _voxelsInWriteArrays * sizeof(bool)); |
| 428 | } | 426 | } |
| 429 | 427 | ||
| 430 | void VoxelSystem::updatePartialVBOs() { | 428 | void VoxelSystem::updatePartialVBOs() { |
| 431 | int segmentCount = 0; | ||
| 432 | glBufferIndex segmentStart = 0; | 429 | glBufferIndex segmentStart = 0; |
| 433 | glBufferIndex segmentEnd = 0; | 430 | glBufferIndex segmentEnd = 0; |
| 434 | bool inSegment = false; | 431 | bool inSegment = false; |
| @@ -457,11 +454,6 @@ void VoxelSystem::updatePartialVBOs() { · 22 unmodified lines | |||
| 457 | GLubyte* readColorsFrom = _readColorsArray + (segmentStart * VERTEX_POINTS_PER_VOXEL); | 454 | GLubyte* readColorsFrom = _readColorsArray + (segmentStart * VERTEX_POINTS_PER_VOXEL); |
| 458 | glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID); | 455 | glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID); |
| 459 | glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readColorsFrom); | 456 | glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readColorsFrom); |
| 460 | |||
| 461 | // debug | ||
| 462 | segmentCount++; | ||
| 463 | printLog("updatePartialVBOs() start=%ld, end=%ld, length=%ld, segmentCount=%d \n", | ||
| 464 | segmentStart, segmentEnd, segmentLength, segmentCount); | ||
| 465 | } | 457 | } |
| 466 | _voxelDirtyArray[i] = false; // consider us clean! | 458 | _voxelDirtyArray[i] = false; // consider us clean! |
| 467 | } | 459 | } |
| @@ -482,43 +474,7 @@ void VoxelSystem::updatePartialVBOs() { · 14 unmodified lines | |||
| 482 | GLubyte* readColorsFrom = _readColorsArray + (segmentStart * VERTEX_POINTS_PER_VOXEL); | 474 | GLubyte* readColorsFrom = _readColorsArray + (segmentStart * VERTEX_POINTS_PER_VOXEL); |
| 483 | glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID); | 475 | glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID); |
| 484 | glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readColorsFrom); | 476 | glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readColorsFrom); |
| 485 | 477 | } | |
| 486 | // debug | ||
| 487 | segmentCount++; | ||
| 488 | printLog("updatePartialVBOs() start=%ld, end=%ld, length=%ld, segmentCount=%d \n", | ||
| 489 | segmentStart, segmentEnd, segmentLength, segmentCount); | ||
| 490 | } | ||
| 491 | } | ||
| 492 | |||
| 493 | void debugOpenGLError(const char* label) { | ||
| 494 | GLenum error = glGetError(); | ||
| 495 | const char* errorMessage; | ||
| 496 | switch (error) { | ||
| 497 | case GL_NO_ERROR: | ||
| 498 | return; | ||
| 499 | case GL_INVALID_ENUM: | ||
| 500 | errorMessage = "GL_INVALID_ENUM"; | ||
| 501 | break; | ||
| 502 | case GL_INVALID_VALUE: | ||
| 503 | errorMessage = "GL_INVALID_VALUE"; | ||
| 504 | break; | ||
| 505 | case GL_INVALID_OPERATION: | ||
| 506 | errorMessage = "GL_INVALID_OPERATION"; | ||
| 507 | break; | ||
| 508 | case GL_STACK_OVERFLOW: | ||
| 509 | errorMessage = "GL_STACK_OVERFLOW"; | ||
| 510 | break; | ||
| 511 | case GL_STACK_UNDERFLOW: | ||
| 512 | errorMessage = "GL_STACK_UNDERFLOW"; | ||
| 513 | break; | ||
| 514 | case GL_OUT_OF_MEMORY: | ||
| 515 | errorMessage = "GL_OUT_OF_MEMORY"; | ||
| 516 | break; | ||
| 517 | case GL_INVALID_FRAMEBUFFER_OPERATION: | ||
| 518 | errorMessage = "GL_INVALID_FRAMEBUFFER_OPERATION"; | ||
| 519 | break; | ||
| 520 | } | ||
| 521 | printLog("%s generated %s", label, errorMessage); | ||
| 522 | } | 478 | } |
| 523 | 479 | ||
| 524 | void VoxelSystem::updateJustEnoughVBOs() { | 480 | void VoxelSystem::updateJustEnoughVBOs() { |
| @@ -538,31 +494,17 @@ void VoxelSystem::updateJustEnoughVBOs() { · 13 unmodified lines | |||
| 538 | if (somethingDirty) { | 494 | if (somethingDirty) { |
| 539 | glBufferIndex segmentStart = minDirty; | 495 | glBufferIndex segmentStart = minDirty; |
| 540 | glBufferIndex segmentEnd = maxDirty; | 496 | glBufferIndex segmentEnd = maxDirty; |
| 541 | |||
| 542 | glGetError(); // clear errors | ||
| 543 | |||
| 544 | int segmentLength = (segmentEnd - segmentStart) + 1; | 497 | int segmentLength = (segmentEnd - segmentStart) + 1; |
| 545 | GLintptr segmentStartAt = segmentStart * VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat); | 498 | GLintptr segmentStartAt = segmentStart * VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat); |
| 546 | GLsizeiptr segmentSizeBytes = segmentLength * VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat); | 499 | GLsizeiptr segmentSizeBytes = segmentLength * VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat); |
| 547 | GLfloat* readVerticesFrom = _readVerticesArray + (segmentStart * VERTEX_POINTS_PER_VOXEL); | 500 | GLfloat* readVerticesFrom = _readVerticesArray + (segmentStart * VERTEX_POINTS_PER_VOXEL); |
| 548 | glBindBuffer(GL_ARRAY_BUFFER, _vboVerticesID); | 501 | glBindBuffer(GL_ARRAY_BUFFER, _vboVerticesID); |
| 549 | debugOpenGLError("glBindBuffer(GL_ARRAY_BUFFER, _vboVerticesID)"); | ||
| 550 | |||
| 551 | glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readVerticesFrom); | 502 | glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readVerticesFrom); |
| 552 | debugOpenGLError("glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readVerticesFrom)"); | ||
| 553 | |||
| 554 | segmentStartAt = segmentStart * VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte); | 503 | segmentStartAt = segmentStart * VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte); |
| 555 | segmentSizeBytes = segmentLength * VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte); | 504 | segmentSizeBytes = segmentLength * VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte); |
| 556 | GLubyte* readColorsFrom = _readColorsArray + (segmentStart * VERTEX_POINTS_PER_VOXEL); | 505 | GLubyte* readColorsFrom = _readColorsArray + (segmentStart * VERTEX_POINTS_PER_VOXEL); |
| 557 | |||
| 558 | glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID); | 506 | glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID); |
| 559 | debugOpenGLError("glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID)"); | ||
| 560 | |||
| 561 | glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readColorsFrom); | 507 | glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readColorsFrom); |
| 562 | debugOpenGLError("glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readColorsFrom)"); | ||
| 563 | |||
| 564 | // debug | ||
| 565 | printLog("updateJustEnoughVBOs() start=%ld, end=%ld, length=%ld, \n", segmentStart, segmentEnd, segmentLength); | ||
| 566 | } | 508 | } |
| 567 | } | 509 | } |
| 568 | 510 | ||
| @@ -574,8 +516,7 @@ void VoxelSystem::updateVBOs() { · 5 unmodified lines | |||
| 574 | PerformanceWarning warn(_renderWarningsOn, buffer); // would like to include _callsToTreesToArrays | 516 | PerformanceWarning warn(_renderWarningsOn, buffer); // would like to include _callsToTreesToArrays |
| 575 | if (_voxelsDirty) { | 517 | if (_voxelsDirty) { |
| 576 | // updatePartialVBOs() is not yet working. For now, ALWAYS call updateFullVBOs() | 518 | // updatePartialVBOs() is not yet working. For now, ALWAYS call updateFullVBOs() |
| 577 | bool alwaysRenderFullVBO = true; | 519 | if (_renderFullVBO) { |
| 578 | if (alwaysRenderFullVBO || _renderFullVBO) { | ||
| 579 | updateFullVBOs(); | 520 | updateFullVBOs(); |
| 580 | } else { | 521 | } else { |
| 581 | updateJustEnoughVBOs(); | 522 | updateJustEnoughVBOs(); |
| @@ -832,6 +773,9 @@ void VoxelSystem::removeOutOfView() { · 250 unmodified lines | |||
| 832 | removeOutOfViewArgs args(this); | 773 | removeOutOfViewArgs args(this); |
| 833 | _tree->recurseTreeWithOperation(removeOutOfViewOperation,(void*)&args); | 774 | _tree->recurseTreeWithOperation(removeOutOfViewOperation,(void*)&args); |
| 834 | 775 | ||
| 776 | if (args.nodesRemoved) { | ||
| 777 | _tree->setDirtyBit(); | ||
| 778 | } | ||
| 835 | bool showRemoveDebugDetails = false; | 779 | bool showRemoveDebugDetails = false; |
| 836 | if (showRemoveDebugDetails) { | 780 | if (showRemoveDebugDetails) { |
| 837 | printLog("removeOutOfView() scanned=%ld removed=%ld inside=%ld intersect=%ld outside=%ld _removedVoxels.count()=%d \n", | 781 | printLog("removeOutOfView() scanned=%ld removed=%ld inside=%ld intersect=%ld outside=%ld _removedVoxels.count()=%d \n", |
| @@ -841,6 +785,22 @@ void VoxelSystem::removeOutOfView() { · 3 unmodified lines | |||
| 841 | } | 785 | } |
| 842 | } | 786 | } |
| 843 | 787 | ||
| 788 | bool VoxelSystem::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, | ||
| 789 | VoxelDetail& detail, float& distance, BoxFace& face) { | ||
| 790 | VoxelNode* node; | ||
| 791 | if (!_tree->findRayIntersection(origin, direction, node, distance, face)) { | ||
| 792 | return false; | ||
| 793 | } | ||
| 794 | detail.x = node->getCorner().x; | ||
| 795 | detail.y = node->getCorner().y; | ||
| 796 | detail.z = node->getCorner().z; | ||
| 797 | detail.s = node->getScale(); | ||
| 798 | detail.red = node->getColor()[0]; | ||
| 799 | detail.green = node->getColor()[1]; | ||
| 800 | detail.blue = node->getColor()[2]; | ||
| 801 | return true; | ||
| 802 | } | ||
| 803 | |||
| 844 | class falseColorizeRandomEveryOtherArgs { | 804 | class falseColorizeRandomEveryOtherArgs { |
| 845 | public: | 805 | public: |
| 846 | falseColorizeRandomEveryOtherArgs() : totalNodes(0), colorableNodes(0), coloredNodes(0), colorThis(true) {}; | 806 | falseColorizeRandomEveryOtherArgs() : totalNodes(0), colorableNodes(0), coloredNodes(0), colorThis(true) {}; |
| @@ -872,19 +832,101 @@ void VoxelSystem::falseColorizeRandomEveryOther() { · 25 unmodified lines | |||
| 872 | setupNewVoxelsForDrawing(); | 832 | setupNewVoxelsForDrawing(); |
| 873 | } | 833 | } |
| 874 | 834 | ||
| 875 | bool VoxelSystem::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, | 835 | class collectStatsForTreesAndVBOsArgs { |
| 876 | VoxelDetail& detail, float& distance, BoxFace& face) { | 836 | public: |
| 877 | VoxelNode* node; | 837 | collectStatsForTreesAndVBOsArgs() : |
| 878 | if (!_tree->findRayIntersection(origin, direction, node, distance, face)) { | 838 | totalNodes(0), |
| 879 | return false; | 839 | dirtyNodes(0), |
| 840 | shouldRenderNodes(0), | ||
| 841 | coloredNodes(0), | ||
| 842 | nodesInVBO(0), | ||
| 843 | nodesInVBOOverExpectedMax(0), | ||
| 844 | duplicateVBOIndex(0) | ||
| 845 | { | ||
| 846 | memset(hasIndexFound, false, MAX_VOXELS_PER_SYSTEM * sizeof(bool)); | ||
| 847 | }; | ||
| 848 | |||
| 849 | unsigned long totalNodes; | ||
| 850 | unsigned long dirtyNodes; | ||
| 851 | unsigned long shouldRenderNodes; | ||
| 852 | unsigned long coloredNodes; | ||
| 853 | unsigned long nodesInVBO; | ||
| 854 | unsigned long nodesInVBOOverExpectedMax; | ||
| 855 | unsigned long duplicateVBOIndex; | ||
| 856 | unsigned long expectedMax; | ||
| 857 | |||
| 858 | bool colorThis; | ||
| 859 | bool hasIndexFound[MAX_VOXELS_PER_SYSTEM]; | ||
| 860 | }; | ||
| 861 | |||
| 862 | bool VoxelSystem::collectStatsForTreesAndVBOsOperation(VoxelNode* node, void* extraData) { | ||
| 863 | collectStatsForTreesAndVBOsArgs* args = (collectStatsForTreesAndVBOsArgs*)extraData; | ||
| 864 | args->totalNodes++; | ||
| 865 | |||
| 866 | if (node->isColored()) { | ||
| 867 | args->coloredNodes++; | ||
| 880 | } | 868 | } |
| 881 | detail.x = node->getCorner().x; | 869 | |
| 882 | detail.y = node->getCorner().y; | 870 | if (node->getShouldRender()) { |
| 883 | detail.z = node->getCorner().z; | 871 | args->shouldRenderNodes++; |
| 884 | detail.s = node->getScale(); | 872 | } |
| 885 | detail.red = node->getColor()[0]; | 873 | |
| 886 | detail.green = node->getColor()[1]; | 874 | if (node->isDirty()) { |
| 887 | detail.blue = node->getColor()[2]; | 875 | args->dirtyNodes++; |
| 888 | return true; | 876 | } |
| 877 | |||
| 878 | if (node->isKnownBufferIndex()) { | ||
| 879 | args->nodesInVBO++; | ||
| 880 | unsigned long nodeIndex = node->getBufferIndex(); | ||
| 881 | if (args->hasIndexFound[nodeIndex]) { | ||
| 882 | args->duplicateVBOIndex++; | ||
| 883 | printLog("duplicateVBO found... index=%ld, isDirty=%s, shouldRender=%s \n", nodeIndex, | ||
| 884 | node->isDirty() ? "yes" : "no" , node->getShouldRender() ? "yes" : "no" ); | ||
| 885 | } else { | ||
| 886 | args->hasIndexFound[nodeIndex] = true; | ||
| 887 | } | ||
| 888 | if (nodeIndex > args->expectedMax) { | ||
| 889 | args->nodesInVBOOverExpectedMax++; | ||
| 890 | } | ||
| 891 | } | ||
| 892 | |||
| 893 | return true; // keep going! | ||
| 889 | } | 894 | } |
| 890 | 895 | ||
| 896 | void VoxelSystem::collectStatsForTreesAndVBOs() { | ||
| 897 | |||
| 898 | glBufferIndex minDirty = GLBUFFER_INDEX_UNKNOWN; | ||
| 899 | glBufferIndex maxDirty = 0; | ||
| 900 | |||
| 901 | for (glBufferIndex i = 0; i < _voxelsInWriteArrays; i++) { | ||
| 902 | if (_voxelDirtyArray[i]) { | ||
| 903 | minDirty = std::min(minDirty,i); | ||
| 904 | maxDirty = std::max(maxDirty,i); | ||
| 905 | } | ||
| 906 | } | ||
| 907 | |||
| 908 | collectStatsForTreesAndVBOsArgs args; | ||
| 909 | args.expectedMax = _voxelsInWriteArrays; | ||
| 910 | _tree->recurseTreeWithOperation(collectStatsForTreesAndVBOsOperation,&args); | ||
| 911 | |||
| 912 | printLog("_voxelsDirty=%s _voxelsInWriteArrays=%ld minDirty=%ld maxDirty=%ld \n", (_voxelsDirty ? "yes" : "no"), | ||
| 913 | _voxelsInWriteArrays, minDirty, maxDirty); | ||
| 914 | |||
| 915 | printLog("stats: total %ld, dirty %ld, colored %ld, shouldRender %ld, inVBO %ld, nodesInVBOOverExpectedMax %ld, duplicateVBOIndex %ld\n", | ||
| 916 | args.totalNodes, args.dirtyNodes, args.coloredNodes, args.shouldRenderNodes, | ||
| 917 | args.nodesInVBO, args.nodesInVBOOverExpectedMax, args.duplicateVBOIndex); | ||
| 918 | |||
| 919 | glBufferIndex minInVBO = GLBUFFER_INDEX_UNKNOWN; | ||
| 920 | glBufferIndex maxInVBO = 0; | ||
| 921 | |||
| 922 | for (glBufferIndex i = 0; i < MAX_VOXELS_PER_SYSTEM; i++) { | ||
| 923 | if (args.hasIndexFound[i]) { | ||
| 924 | minInVBO = std::min(minInVBO,i); | ||
| 925 | maxInVBO = std::max(maxInVBO,i); | ||
| 926 | } | ||
| 927 | } | ||
| 928 | |||
| 929 | printLog("minInVBO=%ld maxInVBO=%ld _voxelsInWriteArrays=%ld _voxelsInReadArrays=%ld\n", | ||
| 930 | minInVBO, maxInVBO, _voxelsInWriteArrays, _voxelsInReadArrays); | ||
| 931 | |||
| 932 | } | ||