ZappoManCR feedbackddd551013 years agoHistory
1025 lines · 40.6 KB · C++
RawDownload
    glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID);    glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readColorsFrom);        // consider the _voxelDirtyArray[] clean!    memset(_voxelDirtyArray, false, _voxelsInWriteArrays * sizeof(bool));} void VoxelSystem::updatePartialVBOs() {    glBufferIndex segmentStart = 0;    glBufferIndex segmentEnd = 0;    bool inSegment = false;    for (glBufferIndex i = 0; i < _voxelsInWriteArrays; i++) {        bool thisVoxelDirty = _voxelDirtyArray[i];        if (!inSegment) {            if (thisVoxelDirty) {                segmentStart = i;                inSegment = true;                _voxelDirtyArray[i] = false; // consider us clean!            }        } else {            if (!thisVoxelDirty) {                // If we got here because because this voxel is NOT dirty, so the last dirty voxel was the one before                // this one and so that's where the "segment" ends                segmentEnd = i - 1;                 inSegment = false;                int segmentLength = (segmentEnd - segmentStart) + 1;                GLintptr   segmentStartAt   = segmentStart * VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat);                GLsizeiptr segmentSizeBytes = segmentLength * VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat);                GLfloat* readVerticesFrom   = _readVerticesArray + (segmentStart * VERTEX_POINTS_PER_VOXEL);                glBindBuffer(GL_ARRAY_BUFFER, _vboVerticesID);                glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readVerticesFrom);                segmentStartAt          = segmentStart * VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte);                segmentSizeBytes        = segmentLength * VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte);                GLubyte* readColorsFrom = _readColorsArray   + (segmentStart * VERTEX_POINTS_PER_VOXEL);                glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID);                glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readColorsFrom);            }            _voxelDirtyArray[i] = false; // consider us clean!        }    }        // if we got to the end of the array, and we're in an active dirty segment...    if (inSegment) {        segmentEnd = _voxelsInWriteArrays - 1;         inSegment = false;        int segmentLength = (segmentEnd - segmentStart) + 1;        GLintptr   segmentStartAt   = segmentStart * VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat);        GLsizeiptr segmentSizeBytes = segmentLength * VERTEX_POINTS_PER_VOXEL * sizeof(GLfloat);        GLfloat* readVerticesFrom   = _readVerticesArray + (segmentStart * VERTEX_POINTS_PER_VOXEL);        glBindBuffer(GL_ARRAY_BUFFER, _vboVerticesID);        glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readVerticesFrom);        segmentStartAt          = segmentStart * VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte);        segmentSizeBytes        = segmentLength * VERTEX_POINTS_PER_VOXEL * sizeof(GLubyte);        GLubyte* readColorsFrom = _readColorsArray   + (segmentStart * VERTEX_POINTS_PER_VOXEL);        glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID);        glBufferSubData(GL_ARRAY_BUFFER, segmentStartAt, segmentSizeBytes, readColorsFrom);    }} void VoxelSystem::updateVBOs() {    static char buffer[40] = { 0 };    if (_renderWarningsOn) {         sprintf(buffer, "updateVBOs() _renderFullVBO=%s", (_renderFullVBO ? "yes" : "no"));     };    PerformanceWarning warn(_renderWarningsOn, buffer); // would like to include _callsToTreesToArrays    if (_voxelsDirty) {        if (_renderFullVBO) {            updateFullVBOs();        } else {            updatePartialVBOs();        }        _voxelsDirty = false;    }    _callsToTreesToArrays = 0; // clear it} void VoxelSystem::render() {    PerformanceWarning warn(_renderWarningsOn, "render()");    glPushMatrix();    updateVBOs();    // tell OpenGL where to find vertex and color information    glEnableClientState(GL_VERTEX_ARRAY);    glEnableClientState(GL_NORMAL_ARRAY);    glEnableClientState(GL_COLOR_ARRAY);     glBindBuffer(GL_ARRAY_BUFFER, _vboVerticesID);    glVertexPointer(3, GL_FLOAT, 0, 0);     glBindBuffer(GL_ARRAY_BUFFER, _vboNormalsID);    glNormalPointer(GL_FLOAT, 0, 0);     glBindBuffer(GL_ARRAY_BUFFER, _vboColorsID);    glColorPointer(3, GL_UNSIGNED_BYTE, 0, 0);     // draw the number of voxels we have    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vboIndicesID);    glScalef(TREE_SCALE, TREE_SCALE, TREE_SCALE);    glDrawElements(GL_TRIANGLES, 36 * _voxelsInReadArrays, GL_UNSIGNED_INT, 0);     // deactivate vertex and color arrays after drawing    glDisableClientState(GL_VERTEX_ARRAY);    glDisableClientState(GL_NORMAL_ARRAY);    glDisableClientState(GL_COLOR_ARRAY);     // bind with 0 to switch back to normal operation    glBindBuffer(GL_ARRAY_BUFFER, 0);    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);     // scale back down to 1 so heads aren't massive    glPopMatrix();} int VoxelSystem::_nodeCount = 0; void VoxelSystem::killLocalVoxels() {    _tree->eraseAllVoxels();    _voxelsInWriteArrays = _voxelsInReadArrays = 0; // better way to do this??    //setupNewVoxelsForDrawing();}  bool VoxelSystem::randomColorOperation(VoxelNode* node, void* extraData) {    _nodeCount++;    if (node->isColored()) {        nodeColor newColor = { 255, randomColorValue(150), randomColorValue(150), 1 };        node->setColor(newColor);    }    return true;} void VoxelSystem::randomizeVoxelColors() {    _nodeCount = 0;    _tree->recurseTreeWithOperation(randomColorOperation);    printLog("setting randomized true color for %d nodes\n", _nodeCount);    setupNewVoxelsForDrawing();} bool VoxelSystem::falseColorizeRandomOperation(VoxelNode* node, void* extraData) {    _nodeCount++;    // always false colorize    node->setFalseColor(255, randomColorValue(150), randomColorValue(150));    return true; // keep going!} void VoxelSystem::falseColorizeRandom() {    _nodeCount = 0;    _tree->recurseTreeWithOperation(falseColorizeRandomOperation);    printLog("setting randomized false color for %d nodes\n", _nodeCount);    setupNewVoxelsForDrawing();} bool VoxelSystem::trueColorizeOperation(VoxelNode* node, void* extraData) {    _nodeCount++;    node->setFalseColored(false);    return true;} void VoxelSystem::trueColorize() {    PerformanceWarning warn(true, "trueColorize()",true);    _nodeCount = 0;    _tree->recurseTreeWithOperation(trueColorizeOperation);    printLog("setting true color for %d nodes\n", _nodeCount);    setupNewVoxelsForDrawing();} // Will false colorize voxels that are not in viewbool VoxelSystem::falseColorizeInViewOperation(VoxelNode* node, void* extraData) {    const ViewFrustum* viewFrustum = (const ViewFrustum*) extraData;    _nodeCount++;    if (node->isColored()) {        if (!node->isInView(*viewFrustum)) {            // Out of view voxels are colored RED            node->setFalseColor(255, 0, 0);        }    }    return true; // keep going!} void VoxelSystem::falseColorizeInView(ViewFrustum* viewFrustum) {    _nodeCount = 0;    _tree->recurseTreeWithOperation(falseColorizeInViewOperation,(void*)viewFrustum);    printLog("setting in view false color for %d nodes\n", _nodeCount);    setupNewVoxelsForDrawing();} // Will false colorize voxels based on distance from viewbool VoxelSystem::falseColorizeDistanceFromViewOperation(VoxelNode* node, void* extraData) {    ViewFrustum* viewFrustum = (ViewFrustum*) extraData;    if (node->isColored()) {        float distance = node->distanceToCamera(*viewFrustum);        _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);        node->setFalseColor((colorBand * (gradientOver / colorBands)) + (maxColor - gradientOver), 0, 0);    }    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 treebool VoxelSystem::getDistanceFromViewRangeOperation(VoxelNode* node, void* extraData) {    ViewFrustum* viewFrustum = (ViewFrustum*) extraData;    // only do this for truly colored voxels...    if (node->isColored()) {        float distance = node->distanceToCamera(*viewFrustum);        // calculate the range of distances        if (distance > _maxDistance) {            _maxDistance = distance;        }        if (distance < _minDistance) {            _minDistance = distance;        }        _nodeCount++;    }    return true; // keep going!} void VoxelSystem::falseColorizeDistanceFromView(ViewFrustum* viewFrustum) {    _nodeCount = 0;    _maxDistance = 0.0;    _minDistance = FLT_MAX;    _tree->recurseTreeWithOperation(getDistanceFromViewRangeOperation,(void*)viewFrustum);    printLog("determining distance range for %d nodes\n", _nodeCount);    _nodeCount = 0;    _tree->recurseTreeWithOperation(falseColorizeDistanceFromViewOperation,(void*)viewFrustum);    printLog("setting in distance false color for %d nodes\n", _nodeCount);    setupNewVoxelsForDrawing();} // combines the removeOutOfView args into a single classclass removeOutOfViewArgs {public:    VoxelSystem*    thisVoxelSystem;    VoxelNodeBag    dontRecurseBag;    unsigned long   nodesScanned;    unsigned long   nodesRemoved;    unsigned long   nodesInside;    unsigned long   nodesIntersect;    unsigned long   nodesOutside;        removeOutOfViewArgs(VoxelSystem* voxelSystem) :        thisVoxelSystem(voxelSystem),        dontRecurseBag(),        nodesScanned(0),        nodesRemoved(0),        nodesInside(0),        nodesIntersect(0),        nodesOutside(0)    { }}; // "Remove" voxels from the tree that are not in view. We don't actually delete them,// we remove them from the tree and place them into a holding area for later deletionbool VoxelSystem::removeOutOfViewOperation(VoxelNode* node, void* extraData) {    removeOutOfViewArgs* args = (removeOutOfViewArgs*)extraData;     // If our node was previously added to the don't recurse bag, then return false to    // stop the further recursion. This means that the whole node and it's children are    // known to be in view, so don't recurse them    if (args->dontRecurseBag.contains(node)) {        args->dontRecurseBag.remove(node);        return false; // stop recursion    }        VoxelSystem* thisVoxelSystem = args->thisVoxelSystem;    args->nodesScanned++;    // Need to operate on our child nodes, so we can remove them    for (int i = 0; i < NUMBER_OF_CHILDREN; i++) {        VoxelNode* childNode = node->getChildAtIndex(i);        if (childNode) {            ViewFrustum::location inFrustum = childNode->inFrustum(*thisVoxelSystem->_viewFrustum);            switch (inFrustum) {                case ViewFrustum::OUTSIDE: {                    args->nodesOutside++;                    args->nodesRemoved++;                    node->removeChildAtIndex(i);                    thisVoxelSystem->_removedVoxels.insert(childNode);                    // by removing the child, it will not get recursed!                } break;                case ViewFrustum::INSIDE: {                    // if the child node is fully INSIDE the view, then there's no need to recurse it                    // because we know all it's children will also be in the view, so we want to                     // tell the caller to NOT recurse this child                    args->nodesInside++;                    args->dontRecurseBag.insert(childNode);                } break;                case ViewFrustum::INTERSECT: {                    // if the child node INTERSECTs the view, then we don't want to remove it because                    // it is at least partially in view. But we DO want to recurse the children because                    // some of them may not be in view... nothing specifically to do, just keep iterating                    // the children                    args->nodesIntersect++;                } break;            }        }    }    return true; // keep going!} bool VoxelSystem::hasViewChanged() {    bool result = false; // assume the best    if (_viewFrustum && !_lastKnowViewFrustum.matches(_viewFrustum)) {        result = true;        _lastKnowViewFrustum = *_viewFrustum; // save last known    }    return result;} void VoxelSystem::removeOutOfView() {    PerformanceWarning warn(_renderWarningsOn, "removeOutOfView()");    removeOutOfViewArgs args(this);    _tree->recurseTreeWithOperation(removeOutOfViewOperation,(void*)&args);     if (args.nodesRemoved) {        _tree->setDirtyBit();    }    bool showRemoveDebugDetails = false;    if (showRemoveDebugDetails) {        printLog("removeOutOfView() scanned=%ld removed=%ld inside=%ld intersect=%ld outside=%ld _removedVoxels.count()=%d \n",                 args.nodesScanned, args.nodesRemoved, args.nodesInside,                 args.nodesIntersect, args.nodesOutside, _removedVoxels.count()            );    }} bool VoxelSystem::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,                                      VoxelDetail& detail, float& distance, BoxFace& face) {    VoxelNode* node;    if (!_tree->findRayIntersection(origin, direction, node, distance, face)) {        return false;    }    detail.x = node->getCorner().x;    detail.y = node->getCorner().y;    detail.z = node->getCorner().z;    detail.s = node->getScale();    detail.red = node->getColor()[0];    detail.green = node->getColor()[1];    detail.blue = node->getColor()[2];    return true;} class falseColorizeRandomEveryOtherArgs {public:    falseColorizeRandomEveryOtherArgs() : totalNodes(0), colorableNodes(0), coloredNodes(0), colorThis(true) {};    unsigned long totalNodes;    unsigned long colorableNodes;    unsigned long coloredNodes;    bool colorThis;}; bool VoxelSystem::falseColorizeRandomEveryOtherOperation(VoxelNode* node, void* extraData) {    falseColorizeRandomEveryOtherArgs* args = (falseColorizeRandomEveryOtherArgs*)extraData;    args->totalNodes++;    if (node->isColored()) {        args->colorableNodes++;        if (args->colorThis) {            args->coloredNodes++;            node->setFalseColor(255, randomColorValue(150), randomColorValue(150));        }        args->colorThis = !args->colorThis;    }    return true; // keep going!} void VoxelSystem::falseColorizeRandomEveryOther() {    falseColorizeRandomEveryOtherArgs args;    _tree->recurseTreeWithOperation(falseColorizeRandomEveryOtherOperation,&args);    printLog("randomized false color for every other node: total %ld, colorable %ld, colored %ld\n",         args.totalNodes, args.colorableNodes, args.coloredNodes);    setupNewVoxelsForDrawing();} class collectStatsForTreesAndVBOsArgs {public:    collectStatsForTreesAndVBOsArgs() :         totalNodes(0),         dirtyNodes(0),         shouldRenderNodes(0),        coloredNodes(0),        nodesInVBO(0),        nodesInVBOOverExpectedMax(0),        duplicateVBOIndex(0),        leafNodes(0)        {            memset(hasIndexFound, false, MAX_VOXELS_PER_SYSTEM * sizeof(bool));        };     unsigned long totalNodes;    unsigned long dirtyNodes;    unsigned long shouldRenderNodes;    unsigned long coloredNodes;    unsigned long nodesInVBO;    unsigned long nodesInVBOOverExpectedMax;    unsigned long duplicateVBOIndex;    unsigned long leafNodes;     unsigned long expectedMax;        bool hasIndexFound[MAX_VOXELS_PER_SYSTEM];}; bool VoxelSystem::collectStatsForTreesAndVBOsOperation(VoxelNode* node, void* extraData) {    collectStatsForTreesAndVBOsArgs* args = (collectStatsForTreesAndVBOsArgs*)extraData;    args->totalNodes++;     if (node->isLeaf()) {        args->leafNodes++;    }     if (node->isColored()) {        args->coloredNodes++;    }     if (node->getShouldRender()) {        args->shouldRenderNodes++;    }     if (node->isDirty()) {        args->dirtyNodes++;    }     if (node->isKnownBufferIndex()) {        args->nodesInVBO++;        unsigned long nodeIndex = node->getBufferIndex();        if (args->hasIndexFound[nodeIndex]) {            args->duplicateVBOIndex++;            printLog("duplicateVBO found... index=%ld, isDirty=%s, shouldRender=%s \n", nodeIndex,                     node->isDirty() ? "yes" : "no" , node->getShouldRender()  ? "yes" : "no" );        } else {            args->hasIndexFound[nodeIndex] = true;        }        if (nodeIndex > args->expectedMax) {            args->nodesInVBOOverExpectedMax++;        }    }     return true; // keep going!} void VoxelSystem::collectStatsForTreesAndVBOs() {    PerformanceWarning warn(true, "collectStatsForTreesAndVBOs()", true);     glBufferIndex minDirty = GLBUFFER_INDEX_UNKNOWN;    glBufferIndex maxDirty = 0;     for (glBufferIndex i = 0; i < _voxelsInWriteArrays; i++) {        if (_voxelDirtyArray[i]) {            minDirty = std::min(minDirty,i);            maxDirty = std::max(maxDirty,i);        }    }     collectStatsForTreesAndVBOsArgs args;    args.expectedMax = _voxelsInWriteArrays;    _tree->recurseTreeWithOperation(collectStatsForTreesAndVBOsOperation,&args);     printLog("_voxelsDirty=%s _voxelsInWriteArrays=%ld minDirty=%ld maxDirty=%ld \n", (_voxelsDirty ? "yes" : "no"),         _voxelsInWriteArrays, minDirty, maxDirty);     printLog("stats: total %ld, leaves %ld, dirty %ld, colored %ld, shouldRender %ld, inVBO %ld\n",        args.totalNodes, args.leafNodes, args.dirtyNodes, args.coloredNodes, args.shouldRenderNodes);     printLog("inVBO %ld, nodesInVBOOverExpectedMax %ld, duplicateVBOIndex %ld\n",         args.nodesInVBO, args.nodesInVBOOverExpectedMax, args.duplicateVBOIndex);     glBufferIndex minInVBO = GLBUFFER_INDEX_UNKNOWN;    glBufferIndex maxInVBO = 0;     for (glBufferIndex i = 0; i < MAX_VOXELS_PER_SYSTEM; i++) {        if (args.hasIndexFound[i]) {            minInVBO = std::min(minInVBO,i);            maxInVBO = std::max(maxInVBO,i);        }    }     printLog("minInVBO=%ld maxInVBO=%ld _voxelsInWriteArrays=%ld _voxelsInReadArrays=%ld\n",             minInVBO, maxInVBO, _voxelsInWriteArrays, _voxelsInReadArrays); }  void VoxelSystem::deleteVoxelAt(float x, float y, float z, float s) {     printLog("VoxelSystem::deleteVoxelAt(%f,%f,%f,%f)\n",x,y,z,s);     VoxelNode* node = _tree->getVoxelAt(x, y, z, s);    if (node) {        // tell the node we want it deleted        node->stageForDeletion();                // tree is now dirty        _tree->setDirtyBit();

Lines 501–1000 of 1025. Previous lines