bool TileNode::shouldSubDivide(TerrainCuller* culler, const SelectionInfo& selectionInfo) { unsigned currLOD = _key.getLOD(); EngineContext* context = culler->getEngineContext(); if (context->getOptions().rangeMode() == osg::LOD::PIXEL_SIZE_ON_SCREEN) { float pixelSize = -1.0; if (context->getEngine()->getComputeRangeCallback()) { pixelSize = (*context->getEngine()->getComputeRangeCallback())(this, *culler->_cv); } if (pixelSize <= 0.0) { pixelSize = culler->clampedPixelSize(getBound()); } return (pixelSize > context->getOptions().tilePixelSize().get() * 4); } else { float range = (float)selectionInfo.visParameters(currLOD+1)._visibilityRange2; if (currLOD < selectionInfo.getNumLODs() && currLOD != selectionInfo.getNumLODs()-1) { return _surface->anyChildBoxIntersectsSphere( culler->getViewPointLocal(), range, culler->getLODScale()); } } return false; }
bool TileNode::shouldSubDivide(osgUtil::CullVisitor* cv, const SelectionInfo& selectionInfo) { unsigned currLOD = _key.getLOD(); if (currLOD < selectionInfo.numLods() && currLOD != selectionInfo.numLods()-1) { return _surface->anyChildBoxIntersectsSphere( cv->getViewPointLocal(), (float)selectionInfo.visParameters(currLOD+1)._visibilityRange2, cv->getLODScale()); } return false; }
bool TileNode::shouldSubDivide(osg::NodeVisitor& nv, const SelectionInfo& selectionInfo, float lodScale) { unsigned currLOD = _key.getLOD(); if ( currLOD < selectionInfo.numLods() && currLOD != selectionInfo.numLods()-1) { osg::Vec3 cameraPos = nv.getViewPoint(); float radius2 = (float)selectionInfo.visParameters(currLOD+1)._visibilityRange2; return _surface->anyChildBoxIntersectsSphere(cameraPos, radius2, lodScale); } return false; }
void TileNode::updateTileUniforms(const SelectionInfo& selectionInfo) { //assert(_surface.valid()); // update the tile key uniform const osg::BoundingBox& bbox = _surface->getAlignedBoundingBox(); float width = std::max( (bbox.xMax()-bbox.xMin()), (bbox.yMax()-bbox.yMin()) ); unsigned tw, th; _key.getProfile()->getNumTiles(_key.getLOD(), tw, th); _tileKeyUniform->set(osg::Vec4f(_key.getTileX(), th-_key.getTileY()-1.0f, _key.getLOD(), width)); // update the morph constants float fStart = (float)selectionInfo.visParameters(_key.getLOD())._fMorphStart; float fEnd = (float)selectionInfo.visParameters(_key.getLOD())._fMorphEnd; float one_by_end_minus_start = fEnd - fStart; one_by_end_minus_start = 1.0f/one_by_end_minus_start; osg::Vec4f morphConstants( fStart , one_by_end_minus_start , fEnd * one_by_end_minus_start , one_by_end_minus_start ); _tileMorphUniform->set( morphConstants ); // Update grid dims float fGridDims = selectionInfo.gridDimX()-1; _tileGridDimsUniform->set(osg::Vec4f( fGridDims, fGridDims*0.5f, 2.0/fGridDims, selectionInfo.lodForMorphing(_key.getProfile()->getSRS()->isProjected()))); // update tile extents float fXExtents = fabs(bbox.xMax()-bbox.xMin()); float fYExtents = fabs(bbox.yMax()-bbox.yMin()); _tileExtentsUniform->set(osg::Vec4f(fXExtents,fYExtents,0,0)); const osg::Image* er = getElevationRaster(); if ( er ) { getOrCreateStateSet()->getOrCreateUniform("oe_tile_elevationSize", osg::Uniform::FLOAT)->set( (float)er->s() ); } }
void TileNode::updateTileUniforms(const SelectionInfo& selectionInfo) { //assert(_surface.valid()); // update the tile key uniform const osg::BoundingBox& bbox = _surface->getAlignedBoundingBox(); float width = std::max( (bbox.xMax()-bbox.xMin()), (bbox.yMax()-bbox.yMin()) ); unsigned tw, th; _key.getProfile()->getNumTiles(_key.getLOD(), tw, th); _tileKeyUniform->set(osg::Vec4f(_key.getTileX(), th-_key.getTileY()-1.0f, _key.getLOD(), width)); // update the morph constants float start = (float)selectionInfo.visParameters(_key.getLOD())._fMorphStart; float end = (float)selectionInfo.visParameters(_key.getLOD())._fMorphEnd; float one_by_end_minus_start = end - start; one_by_end_minus_start = 1.0f/one_by_end_minus_start; osg::Vec2f morphConstants( end * one_by_end_minus_start, one_by_end_minus_start ); _tileMorphUniform->set( morphConstants ); const osg::Image* er = getElevationRaster(); if ( er ) { // pre-calculate texel-sampling scale and bias coefficients that allow us to sample // elevation textures on texel-center instead of edge: float size = (float)er->s(); osg::Vec2f elevTexelOffsets( (size-1.0f)/size, 0.5/size ); getOrCreateStateSet()->getOrCreateUniform("oe_tile_elevTexelCoeff", osg::Uniform::FLOAT_VEC2)->set(elevTexelOffsets); } }
bool TileNode::shouldSubDivide(osg::NodeVisitor& nv, const SelectionInfo& selectionInfo, float zoomFactor) { unsigned currLOD = _key.getLOD(); if ( currLOD < selectionInfo.numLods() && currLOD != selectionInfo.numLods()-1) { osg::Vec3 cameraPos = nv.getViewPoint(); #if OSGEARTH_REX_TILE_NODE_DEBUG_TRAVERSAL OE_INFO << LC <<cameraPos.x()<<" "<<cameraPos.y()<<" "<<cameraPos.z()<<" "<<std::endl; OE_INFO << LC <<"LOD Scale: "<<fZoomFactor<<std::endl; #endif float radius = (float)selectionInfo.visParameters(currLOD+1)._fVisibility; bool anyChildVisible = _surface->anyChildBoxIntersectsSphere(cameraPos, radius*radius, zoomFactor); return anyChildVisible; } return false; }
IntRect RenderView::selectionBounds(bool clipToVisibleContent) const { document()->updateRendering(); typedef HashMap<RenderObject*, SelectionInfo*> SelectionMap; SelectionMap selectedObjects; RenderObject* os = m_selectionStart; RenderObject* stop = rendererAfterPosition(m_selectionEnd, m_selectionEndPos); while (os && os != stop) { if ((os->canBeSelectionLeaf() || os == m_selectionStart || os == m_selectionEnd) && os->selectionState() != SelectionNone) { // Blocks are responsible for painting line gaps and margin gaps. They must be examined as well. selectedObjects.set(os, new SelectionInfo(os, clipToVisibleContent)); RenderBlock* cb = os->containingBlock(); while (cb && !cb->isRenderView()) { SelectionInfo* blockInfo = selectedObjects.get(cb); if (blockInfo) break; selectedObjects.set(cb, new SelectionInfo(cb, clipToVisibleContent)); cb = cb->containingBlock(); } } os = os->nextInPreOrder(); } // Now create a single bounding box rect that encloses the whole selection. IntRect selRect; SelectionMap::iterator end = selectedObjects.end(); for (SelectionMap::iterator i = selectedObjects.begin(); i != end; ++i) { SelectionInfo* info = i->second; selRect.unite(info->rect()); delete info; } return selRect; }
void RenderView::setSelection(RenderObject* start, int startPos, RenderObject* end, int endPos) { // Make sure both our start and end objects are defined. // Check www.msnbc.com and try clicking around to find the case where this happened. if ((start && !end) || (end && !start)) return; // Just return if the selection hasn't changed. if (m_selectionStart == start && m_selectionStartPos == startPos && m_selectionEnd == end && m_selectionEndPos == endPos) return; // Record the old selected objects. These will be used later // when we compare against the new selected objects. int oldStartPos = m_selectionStartPos; int oldEndPos = m_selectionEndPos; // Objects each have a single selection rect to examine. typedef HashMap<RenderObject*, SelectionInfo*> SelectedObjectMap; SelectedObjectMap oldSelectedObjects; SelectedObjectMap newSelectedObjects; // Blocks contain selected objects and fill gaps between them, either on the left, right, or in between lines and blocks. // In order to get the repaint rect right, we have to examine left, middle, and right rects individually, since otherwise // the union of those rects might remain the same even when changes have occurred. typedef HashMap<RenderBlock*, BlockSelectionInfo*> SelectedBlockMap; SelectedBlockMap oldSelectedBlocks; SelectedBlockMap newSelectedBlocks; RenderObject* os = m_selectionStart; RenderObject* stop = rendererAfterPosition(m_selectionEnd, m_selectionEndPos); while (os && os != stop) { if ((os->canBeSelectionLeaf() || os == m_selectionStart || os == m_selectionEnd) && os->selectionState() != SelectionNone) { // Blocks are responsible for painting line gaps and margin gaps. They must be examined as well. oldSelectedObjects.set(os, new SelectionInfo(os, true)); RenderBlock* cb = os->containingBlock(); while (cb && !cb->isRenderView()) { BlockSelectionInfo* blockInfo = oldSelectedBlocks.get(cb); if (blockInfo) break; oldSelectedBlocks.set(cb, new BlockSelectionInfo(cb)); cb = cb->containingBlock(); } } os = os->nextInPreOrder(); } // Now clear the selection. SelectedObjectMap::iterator oldObjectsEnd = oldSelectedObjects.end(); for (SelectedObjectMap::iterator i = oldSelectedObjects.begin(); i != oldObjectsEnd; ++i) i->first->setSelectionState(SelectionNone); // set selection start and end m_selectionStart = start; m_selectionStartPos = startPos; m_selectionEnd = end; m_selectionEndPos = endPos; // Update the selection status of all objects between m_selectionStart and m_selectionEnd if (start && start == end) start->setSelectionState(SelectionBoth); else { if (start) start->setSelectionState(SelectionStart); if (end) end->setSelectionState(SelectionEnd); } RenderObject* o = start; stop = rendererAfterPosition(end, endPos); while (o && o != stop) { if (o != start && o != end && o->canBeSelectionLeaf()) o->setSelectionState(SelectionInside); o = o->nextInPreOrder(); } // Now that the selection state has been updated for the new objects, walk them again and // put them in the new objects list. o = start; while (o && o != stop) { if ((o->canBeSelectionLeaf() || o == start || o == end) && o->selectionState() != SelectionNone) { newSelectedObjects.set(o, new SelectionInfo(o, true)); RenderBlock* cb = o->containingBlock(); while (cb && !cb->isRenderView()) { BlockSelectionInfo* blockInfo = newSelectedBlocks.get(cb); if (blockInfo) break; newSelectedBlocks.set(cb, new BlockSelectionInfo(cb)); cb = cb->containingBlock(); } } o = o->nextInPreOrder(); } if (!m_frameView) { // We built the maps, but we aren't going to use them. // We need to delete the values, otherwise they'll all leak! deleteAllValues(oldSelectedObjects); deleteAllValues(newSelectedObjects); deleteAllValues(oldSelectedBlocks); deleteAllValues(newSelectedBlocks); return; } // Have any of the old selected objects changed compared to the new selection? for (SelectedObjectMap::iterator i = oldSelectedObjects.begin(); i != oldObjectsEnd; ++i) { RenderObject* obj = i->first; SelectionInfo* newInfo = newSelectedObjects.get(obj); SelectionInfo* oldInfo = i->second; if (!newInfo || oldInfo->rect() != newInfo->rect() || oldInfo->state() != newInfo->state() || (m_selectionStart == obj && oldStartPos != m_selectionStartPos) || (m_selectionEnd == obj && oldEndPos != m_selectionEndPos)) { repaintViewRectangle(oldInfo->rect()); if (newInfo) { repaintViewRectangle(newInfo->rect()); newSelectedObjects.remove(obj); delete newInfo; } } delete oldInfo; } // Any new objects that remain were not found in the old objects dict, and so they need to be updated. SelectedObjectMap::iterator newObjectsEnd = newSelectedObjects.end(); for (SelectedObjectMap::iterator i = newSelectedObjects.begin(); i != newObjectsEnd; ++i) { SelectionInfo* newInfo = i->second; repaintViewRectangle(newInfo->rect()); delete newInfo; } // Have any of the old blocks changed? SelectedBlockMap::iterator oldBlocksEnd = oldSelectedBlocks.end(); for (SelectedBlockMap::iterator i = oldSelectedBlocks.begin(); i != oldBlocksEnd; ++i) { RenderBlock* block = i->first; BlockSelectionInfo* newInfo = newSelectedBlocks.get(block); BlockSelectionInfo* oldInfo = i->second; if (!newInfo || oldInfo->rects() != newInfo->rects() || oldInfo->state() != newInfo->state()) { repaintViewRectangle(oldInfo->rects()); if (newInfo) { repaintViewRectangle(newInfo->rects()); newSelectedBlocks.remove(block); delete newInfo; } } delete oldInfo; } // Any new blocks that remain were not found in the old blocks dict, and so they need to be updated. SelectedBlockMap::iterator newBlocksEnd = newSelectedBlocks.end(); for (SelectedBlockMap::iterator i = newSelectedBlocks.begin(); i != newBlocksEnd; ++i) { BlockSelectionInfo* newInfo = i->second; repaintViewRectangle(newInfo->rects()); delete newInfo; } }