bool ForestTechniqueManager::Cell::divide(unsigned int maxNumTreesPerCell) { if (_trees.size()<=maxNumTreesPerCell) return false; computeBound(); float radius = _bb.radius(); float divide_distance = radius*0.7f; if (divide((_bb.xMax()-_bb.xMin())>divide_distance,(_bb.yMax()-_bb.yMin())>divide_distance,(_bb.zMax()-_bb.zMin())>divide_distance)) { // recusively divide the new cells till maxNumTreesPerCell is met. for(CellList::iterator citr=_cells.begin(); citr!=_cells.end(); ++citr) { (*citr)->divide(maxNumTreesPerCell); } return true; } else { return false; } }
void ChunkLodDrawable::drawImplementation(osg::RenderInfo& info) const { static int frame = 0; _triangles_rendered = 0; _triangles_per_second = 0; if (_tree != NULL) { if (_lastBoundIndex != _tree->getBoundIndex()) { computeBound(); _lastBoundIndex = _tree->getBoundIndex(); } ChunkLodTree *tree = const_cast<ChunkLodTree*>(_tree); osg::Matrix mv = info.getState()->getModelViewMatrix(); mv.invert(mv); osg::Vec3 viewpoint = mv.getTrans(); info.getState()->disableTexCoordPointersAboveAndIncluding(0); // NEW info.getState()->disableAllVertexArrays(); _details->enable(*info.getState()); osg::Timer t; osg::Timer_t update_t = t.tick(); tree->update(viewpoint, *info.getState()); //osg::Timer_t render_t = t.tick(); _triangles_rendered = tree->render(*info.getState(), *_details); _triangle_count += _triangles_rendered; float dt = t.delta_s(update_t, t.tick()); if (dt > 0.0030) { //float utime = t.delta_s(update_t, render_t) * 1000.0; dt *= 1000.0; //std::cout << "PAUSE c-lod render " << dt << " ms (" << utime << ", " << (dt - utime) << ")\n"; } // stats float d = t.delta_s(_last_tick, t.tick()); if (d > 1.0f) { //std::cout << "update tree for view from " << viewpoint << "\n"; //std::cout << _triangles_rendered << " triangles rendered\n"; _triangles_per_second = static_cast<unsigned long>(_triangle_count / d); _last_tick = t.tick(); _triangle_count = 0; } _details->disable(*info.getState()); info.getState()->disableAllVertexArrays(); info.getState()->dirtyTexCoordPointersAboveAndIncluding(0); info.getState()->setActiveTextureUnit(0); frame++; } }
void Diamond::activate() { // this can only be called once all ancestors are established _status = ACTIVE; computeBound(); if ( _hasGeometry ) { // assign this diamond the stateset of the appropriate quadtree ancestor: int stateSetLevel = (int)_level; if ( stateSetLevel < (int)_mesh->_minActiveLevel ) stateSetLevel = _mesh->_minActiveLevel; // obtain a pointer to the Diamond that owns the StateSet we wish to use: _targetStateSetOwner = this; while( _targetStateSetOwner->_level > stateSetLevel ) _targetStateSetOwner = _targetStateSetOwner->_a[QUADTREE].get(); // since that StateSet might not be populated yet, backtrack from there to find the // first available populated StateSet. This will serve as a temporary "placeholder" // until our target stateset is ready (i.e. the textures etc are loaded). _currentStateSetOwner = _targetStateSetOwner; while( !_currentStateSetOwner->_hasFinalImage && _currentStateSetOwner->_level > _mesh->_minActiveLevel ) { _currentStateSetOwner = _currentStateSetOwner->_a[QUADTREE].get(); } // assign the stateset to this Diamond's geometry. _amrDrawable->_stateSet = _currentStateSetOwner->_stateSet.get(); // synchronize with the target state set. By doing this, we will detect when the target stateset // does finally get populated, and at that point we can replace the placeholder stateset with // the final stateset. (This check occurs in Diamond::cull.) _targetStateSetOwner->_stateSet->sync( _targetStateSetRevision ); #ifdef USE_TEXTURES // finally, queue up a request to populate the stateset if necessary. if ( !_targetStateSetOwner->_hasFinalImage ) { _mesh->queueForImage( _targetStateSetOwner, 1.0f ); } #endif } }
void CallbackDrawable::updateBoundingBox() { computeBound(); dirtyBound(); }