bool OctreeQueryNode::updateCurrentViewFrustum() {
    // if shutting down, return immediately
    if (_isShuttingDown) {
        return false;
    }

    bool currentViewFrustumChanged = false;
    ViewFrustum newestViewFrustum;
    // get position and orientation details from the camera
    newestViewFrustum.setPosition(getCameraPosition());
    newestViewFrustum.setOrientation(getCameraOrientation());

    // Also make sure it's got the correct lens details from the camera
    float originalFOV = getCameraFov();
    float wideFOV = originalFOV + VIEW_FRUSTUM_FOV_OVERSEND;

    newestViewFrustum.setFieldOfView(wideFOV); // hack
    newestViewFrustum.setAspectRatio(getCameraAspectRatio());
    newestViewFrustum.setNearClip(getCameraNearClip());
    newestViewFrustum.setFarClip(getCameraFarClip());
    newestViewFrustum.setEyeOffsetPosition(getCameraEyeOffsetPosition());

    // if there has been a change, then recalculate
    if (!newestViewFrustum.isVerySimilar(_currentViewFrustum)) {
        _currentViewFrustum = newestViewFrustum;
        _currentViewFrustum.calculate();
        currentViewFrustumChanged = true;
    }

    // Also check for LOD changes from the client
    if (_lodInitialized) {
        if (_lastClientBoundaryLevelAdjust != getBoundaryLevelAdjust()) {
            _lastClientBoundaryLevelAdjust = getBoundaryLevelAdjust();
            _lodChanged = true;
        }
        if (_lastClientOctreeSizeScale != getOctreeSizeScale()) {
            _lastClientOctreeSizeScale = getOctreeSizeScale();
            _lodChanged = true;
        }
    } else {
        _lodInitialized = true;
        _lastClientOctreeSizeScale = getOctreeSizeScale();
        _lastClientBoundaryLevelAdjust = getBoundaryLevelAdjust();
        _lodChanged = false;
    }

    // When we first detect that the view stopped changing, we record this.
    // but we don't change it back to false until we've completely sent this
    // scene.
    if (_viewFrustumChanging && !currentViewFrustumChanged) {
        _viewFrustumJustStoppedChanging = true;
    }
    _viewFrustumChanging = currentViewFrustumChanged;
    return currentViewFrustumChanged;
}
Beispiel #2
0
QString LODManager::getLODFeedbackText() {
    // determine granularity feedback
    int boundaryLevelAdjust = getBoundaryLevelAdjust();
    QString granularityFeedback;
    
    switch (boundaryLevelAdjust) {
        case 0: {
            granularityFeedback = QString(".");
        } break;
        case 1: {
            granularityFeedback = QString(" at half of standard granularity.");
        } break;
        case 2: {
            granularityFeedback = QString(" at a third of standard granularity.");
        } break;
        default: {
            granularityFeedback = QString(" at 1/%1th of standard granularity.").arg(boundaryLevelAdjust + 1);
        } break;
    }
    
    // distance feedback
    float octreeSizeScale = getOctreeSizeScale();
    float relativeToDefault = octreeSizeScale / DEFAULT_OCTREE_SIZE_SCALE;
    int relativeToTwentyTwenty = 20 / relativeToDefault;

    QString result;
    if (relativeToDefault > 1.01f) {
        result = QString("20:%1 or %2 times further than average vision%3").arg(relativeToTwentyTwenty).arg(relativeToDefault,0,'f',2).arg(granularityFeedback);
    } else if (relativeToDefault > 0.99f) {
        result = QString("20:20 or the default distance for average vision%1").arg(granularityFeedback);
    } else if (relativeToDefault > 0.01f) {
        result = QString("20:%1 or %2 of default distance for average vision%3").arg(relativeToTwentyTwenty).arg(relativeToDefault,0,'f',3).arg(granularityFeedback);
    } else {
        result = QString("%2 of default distance for average vision%3").arg(relativeToDefault,0,'f',3).arg(granularityFeedback);
    }
    return result;
}
Beispiel #3
0
// TODO: This is essentially the same logic used to render octree cells, but since models are more detailed then octree cells
//       I've added a voxelToModelRatio that adjusts how much closer to a model you have to be to see it.
bool LODManager::shouldRenderMesh(float largestDimension, float distanceToCamera) {
    const float octreeToMeshRatio = 4.0f; // must be this many times closer to a mesh than a voxel to see it.
    float octreeSizeScale = getOctreeSizeScale();
    int boundaryLevelAdjust = getBoundaryLevelAdjust();
    float maxScale = (float)TREE_SCALE;
    float visibleDistanceAtMaxScale = boundaryDistanceForRenderLevel(boundaryLevelAdjust, octreeSizeScale) / octreeToMeshRatio;
    
    if (_shouldRenderTableNeedsRebuilding) {
        _shouldRenderTable.clear();
        
        float SMALLEST_SCALE_IN_TABLE = 0.001f; // 1mm is plenty small
        float scale = maxScale;
        float visibleDistanceAtScale = visibleDistanceAtMaxScale;
        
        while (scale > SMALLEST_SCALE_IN_TABLE) {
            scale /= 2.0f;
            visibleDistanceAtScale /= 2.0f;
            _shouldRenderTable[scale] = visibleDistanceAtScale;
        }
        _shouldRenderTableNeedsRebuilding = false;
    }
    
    float closestScale = maxScale;
    float visibleDistanceAtClosestScale = visibleDistanceAtMaxScale;
    QMap<float, float>::const_iterator lowerBound = _shouldRenderTable.lowerBound(largestDimension);
    if (lowerBound != _shouldRenderTable.constEnd()) {
        closestScale = lowerBound.key();
        visibleDistanceAtClosestScale = lowerBound.value();
    }
    
    if (closestScale < largestDimension) {
        visibleDistanceAtClosestScale *= 2.0f;
    }
    
    return (distanceToCamera <= visibleDistanceAtClosestScale);
}
Beispiel #4
0
bool OctreeQueryNode::updateCurrentViewFrustum() {
    // if shutting down, return immediately
    if (_isShuttingDown) {
        return false;
    }
    
    if (!_usesFrustum) {
        // this client does not use a view frustum so the view frustum for this query has not changed
        return false;
    } else {
        bool currentViewFrustumChanged = false;
        
        ViewFrustum newestViewFrustum;
        // get position and orientation details from the camera
        newestViewFrustum.setPosition(getCameraPosition());
        newestViewFrustum.setOrientation(getCameraOrientation());
        
        newestViewFrustum.setCenterRadius(getCameraCenterRadius());
        
        // Also make sure it's got the correct lens details from the camera
        float originalFOV = getCameraFov();
        float wideFOV = originalFOV + VIEW_FRUSTUM_FOV_OVERSEND;
        
        if (0.0f != getCameraAspectRatio() &&
            0.0f != getCameraNearClip() &&
            0.0f != getCameraFarClip() &&
            getCameraNearClip() != getCameraFarClip()) {
            newestViewFrustum.setProjection(glm::perspective(
                                                             glm::radians(wideFOV), // hack
                                                             getCameraAspectRatio(),
                                                             getCameraNearClip(),
                                                             getCameraFarClip()));
            newestViewFrustum.calculate();
        }
        
        
        { // if there has been a change, then recalculate
            QMutexLocker viewLocker(&_viewMutex);
            if (!newestViewFrustum.isVerySimilar(_currentViewFrustum)) {
                _currentViewFrustum = newestViewFrustum;
                currentViewFrustumChanged = true;
            }
        }
        
        // Also check for LOD changes from the client
        if (_lodInitialized) {
            if (_lastClientBoundaryLevelAdjust != getBoundaryLevelAdjust()) {
                _lastClientBoundaryLevelAdjust = getBoundaryLevelAdjust();
                _lodChanged = true;
            }
            if (_lastClientOctreeSizeScale != getOctreeSizeScale()) {
                _lastClientOctreeSizeScale = getOctreeSizeScale();
                _lodChanged = true;
            }
        } else {
            _lodInitialized = true;
            _lastClientOctreeSizeScale = getOctreeSizeScale();
            _lastClientBoundaryLevelAdjust = getBoundaryLevelAdjust();
            _lodChanged = false;
        }
        
        // When we first detect that the view stopped changing, we record this.
        // but we don't change it back to false until we've completely sent this
        // scene.
        if (_viewFrustumChanging && !currentViewFrustumChanged) {
            _viewFrustumJustStoppedChanging = true;
        }
        _viewFrustumChanging = currentViewFrustumChanged;
        return currentViewFrustumChanged;
    }
}