void TileDrawable::accept(osg::PrimitiveFunctor& f) const { if ( !_elevationRaster.valid() ) return; const osg::Vec3Array* verts = static_cast<osg::Vec3Array*>(_geom->getVertexArray()); const osg::Vec3Array* normals = static_cast<osg::Vec3Array*>(_geom->getNormalArray()); ImageUtils::PixelReader elevation(_elevationRaster.get()); float scaleU = _elevationScaleBias(0,0), scaleV = _elevationScaleBias(1,1), biasU = _elevationScaleBias(3,0), biasV = _elevationScaleBias(3,1); for(int t=0; t<_tileSize-1; ++t) { float v = (float)t / (float)(_tileSize-1); float v1 = (float)(t+1) / (float)(_tileSize-1); f.begin( GL_QUAD_STRIP ); for(int s=0; s<_tileSize; ++s) { float u = (float)s / (float)(_tileSize-1); int index = t*_tileSize + s; { const osg::Vec3f& vert = (*verts)[index]; const osg::Vec3f& normal = (*normals)[index]; float h = elevation(u*scaleU+biasU, v*scaleV+biasV).r(); f.vertex( vert + normal*h ); } index += _tileSize; { const osg::Vec3f& vert = (*verts)[index]; const osg::Vec3f& normal = (*normals)[index]; float h = elevation(u*scaleU+biasU, v1*scaleV+biasV).r(); f.vertex( vert + normal*h ); } } f.end(); } }
// Functor supplies triangles to things like IntersectionVisitor, ComputeBoundsVisitor, etc. void TileDrawable::accept(osg::PrimitiveFunctor& f) const { #if 1 // triangles (OSG-stats-friendly) //TODO: improve by caching the entire Vec3f, not just the height. f.begin(GL_TRIANGLES); for(int t=0; t<_tileSize-1; ++t) { for(int s=0; s<_tileSize-1; ++s) { int i00 = t*_tileSize + s; int i10 = i00 + 1; int i01 = i00 + _tileSize; int i11 = i01 + 1; f.vertex(_mesh[i00]); f.vertex(_mesh[i01]); f.vertex(_mesh[i10]); f.vertex(_mesh[i10]); f.vertex(_mesh[i01]); f.vertex(_mesh[i11]); } } f.end(); #else // triangle-strips (faster? but not stats-friendly; will cause the OSG stats // to report _tileSize-1 primitive sets per TileDrawable even though there // is only one. for(int t=0; t<_tileSize-1; ++t) { f.begin( GL_TRIANGLE_STRIP ); for(int s=0; s<_tileSize; ++s) { int i = t*_tileSize + s; f.vertex( _mesh[i] ); i += _tileSize; f.vertex( _mesh[i] ); } f.end(); } #endif }
// Functor supplies triangles to things like IntersectionVisitor, ComputeBoundsVisitor, etc. void TileDrawable::accept(osg::PrimitiveFunctor& f) const { const osg::Vec3Array& verts = *static_cast<osg::Vec3Array*>(_geom->getVertexArray()); const osg::Vec3Array& normals = *static_cast<osg::Vec3Array*>(_geom->getNormalArray()); #if 1 // triangles (OSG-stats-friendly) //TODO: improve by caching the entire Vec3f, not just the height. f.begin(GL_TRIANGLES); for(int t=0; t<_tileSize-1; ++t) { for(int s=0; s<_tileSize-1; ++s) { int i00 = t*_tileSize + s; int i10 = i00 + 1; int i01 = i00 + _tileSize; int i11 = i01 + 1; osg::Vec3d v01 = verts[i01] + normals[i01] * _heightCache[i01]; osg::Vec3d v10 = verts[i10] + normals[i10] * _heightCache[i10]; f.vertex( verts[i00] + normals[i00] * _heightCache[i00] ); f.vertex( v01 ); f.vertex( v10 ); f.vertex( v10 ); f.vertex( v01 ); f.vertex( verts[i11] + normals[i11] * _heightCache[i11] ); } } f.end(); #else // triangle-strips (faster? but not stats-friendly; will cause the OSG stats // to report _tileSize-1 primitive sets per TileDrawable even though there // is only one. for(int t=0; t<_tileSize-1; ++t) { f.begin( GL_TRIANGLE_STRIP ); for(int s=0; s<_tileSize; ++s) { int i = t*_tileSize + s; f.vertex( verts[i] + normals[i] * _heightCache[i] ); i += _tileSize; f.vertex( verts[i] + normals[i] * _heightCache[i] ); } f.end(); } #endif }
void TileDrawable::accept(osg::PrimitiveFunctor& f) const { const osg::Vec3Array* verts = static_cast<osg::Vec3Array*>(_geom->getVertexArray()); const osg::Vec3Array* normals = static_cast<osg::Vec3Array*>(_geom->getNormalArray()); if ( _elevationRaster.valid() ) { ImageUtils::PixelReader elevation(_elevationRaster.get()); elevation.setBilinear(true); float scaleU = _elevationScaleBias(0,0), scaleV = _elevationScaleBias(1,1), biasU = _elevationScaleBias(3,0), biasV = _elevationScaleBias(3,1); //float // texelScale = (float)(_elevationRaster->s()-1)/(float)_elevationRaster->s(), // texelBias = 0.5f/(float)(_elevationRaster->s()); if ( osg::equivalent(scaleU, 0.0f) || osg::equivalent(scaleV, 0.0f) ) { OE_WARN << LC << "Precision loss in tile " << _key.str() << "\n"; } for(int t=0; t<_tileSize-1; ++t) { float v0 = (float)t / (float)(_tileSize-1); float v1 = (float)(t+1) / (float)(_tileSize-1); v0 = v0*scaleV + biasV; v1 = v1*scaleV + biasV; f.begin( GL_QUAD_STRIP ); for(int s=0; s<_tileSize; ++s) { float u = (float)s / (float)(_tileSize-1); u = u*scaleU + biasU; int index = t*_tileSize + s; { const osg::Vec3f& vert = (*verts)[index]; const osg::Vec3f& normal = (*normals)[index]; float h = elevation(u, v0).r(); f.vertex( vert + normal*h ); } index += _tileSize; { const osg::Vec3f& vert = (*verts)[index]; const osg::Vec3f& normal = (*normals)[index]; float h = elevation(u, v1).r(); f.vertex( vert + normal*h ); } } f.end(); } } // no elevation else { for(int t=0; t<_tileSize-1; ++t) { f.begin( GL_QUAD_STRIP ); for(int s=0; s<_tileSize; ++s) { int index = t*_tileSize + s; f.vertex( (*verts)[index] ); f.vertex( (*verts)[index + _tileSize] ); } f.end(); } } }