/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ #include #include #include #include #include #include #include #include #include #include #include #include using namespace osgTerrain; #define NEW_COORD_CODE GeometryTechnique::GeometryTechnique(): _currentReadOnlyBuffer(1), _currentWriteBuffer(0) { setFilterBias(0); setFilterWidth(0.1); setFilterMatrixAs(GAUSSIAN); } GeometryTechnique::GeometryTechnique(const GeometryTechnique& gt,const osg::CopyOp& copyop): TerrainTechnique(gt,copyop), _currentReadOnlyBuffer(1), _currentWriteBuffer(0) { setFilterBias(gt._filterBias); setFilterWidth(gt._filterWidth); setFilterMatrix(gt._filterMatrix); } GeometryTechnique::~GeometryTechnique() { } void GeometryTechnique::swapBuffers() { std::swap(_currentReadOnlyBuffer,_currentWriteBuffer); } void GeometryTechnique::setFilterBias(float filterBias) { _filterBias = filterBias; if (!_filterBiasUniform) _filterBiasUniform = new osg::Uniform("filterBias",_filterBias); else _filterBiasUniform->set(filterBias); } void GeometryTechnique::setFilterWidth(float filterWidth) { _filterWidth = filterWidth; if (!_filterWidthUniform) _filterWidthUniform = new osg::Uniform("filterWidth",_filterWidth); else _filterWidthUniform->set(filterWidth); } void GeometryTechnique::setFilterMatrix(const osg::Matrix3& matrix) { _filterMatrix = matrix; if (!_filterMatrixUniform) _filterMatrixUniform = new osg::Uniform("filterMatrix",_filterMatrix); else _filterMatrixUniform->set(_filterMatrix); } void GeometryTechnique::setFilterMatrixAs(FilterType filterType) { switch(filterType) { case(SMOOTH): setFilterMatrix(osg::Matrix3(0.0, 0.5/2.5, 0.0, 0.5/2.5, 0.5/2.5, 0.5/2.5, 0.0, 0.5/2.5, 0.0)); break; case(GAUSSIAN): setFilterMatrix(osg::Matrix3(0.0, 1.0/8.0, 0.0, 1.0/8.0, 4.0/8.0, 1.0/8.0, 0.0, 1.0/8.0, 0.0)); break; case(SHARPEN): setFilterMatrix(osg::Matrix3(0.0, -1.0, 0.0, -1.0, 5.0, -1.0, 0.0, -1.0, 0.0)); break; }; } void GeometryTechnique::init() { OSG_INFO<<"Doing GeometryTechnique::init()"<setThreadSafeRefUnref(true); swapBuffers(); } Locator* GeometryTechnique::computeMasterLocator() { osgTerrain::Layer* elevationLayer = _terrainTile->getElevationLayer(); osgTerrain::Layer* colorLayer = _terrainTile->getColorLayer(0); Locator* elevationLocator = elevationLayer ? elevationLayer->getLocator() : 0; Locator* colorLocator = colorLayer ? colorLayer->getLocator() : 0; Locator* masterLocator = elevationLocator ? elevationLocator : colorLocator; if (!masterLocator) { OSG_NOTICE<<"Problem, no locator found in any of the terrain layers"<getElevationLayer(); osgTerrain::Layer* colorLayer = _terrainTile->getColorLayer(0); Locator* elevationLocator = elevationLayer ? elevationLayer->getLocator() : 0; Locator* colorLocator = colorLayer ? colorLayer->getLocator() : 0; if (!elevationLocator) elevationLocator = masterLocator; if (!colorLocator) colorLocator = masterLocator; osg::Vec3d bottomLeftNDC(DBL_MAX, DBL_MAX, 0.0); osg::Vec3d topRightNDC(-DBL_MAX, -DBL_MAX, 0.0); if (elevationLayer) { if (elevationLocator!= masterLocator) { masterLocator->computeLocalBounds(*elevationLocator, bottomLeftNDC, topRightNDC); } else { bottomLeftNDC.x() = osg::minimum(bottomLeftNDC.x(), 0.0); bottomLeftNDC.y() = osg::minimum(bottomLeftNDC.y(), 0.0); topRightNDC.x() = osg::maximum(topRightNDC.x(), 1.0); topRightNDC.y() = osg::maximum(topRightNDC.y(), 1.0); } } if (colorLayer) { if (colorLocator!= masterLocator) { masterLocator->computeLocalBounds(*colorLocator, bottomLeftNDC, topRightNDC); } else { bottomLeftNDC.x() = osg::minimum(bottomLeftNDC.x(), 0.0); bottomLeftNDC.y() = osg::minimum(bottomLeftNDC.y(), 0.0); topRightNDC.x() = osg::maximum(topRightNDC.x(), 1.0); topRightNDC.y() = osg::maximum(topRightNDC.y(), 1.0); } } OSG_INFO<<"bottomLeftNDC = "< builder = osgDB::Registry::instance()->getKdTreeBuilder()->clone(); buffer._geode->accept(*builder); //osg::Timer_t after = osg::Timer::instance()->tick(); //OSG_NOTICE<<"KdTree build time "<delta_m(before, after)< LayerToTextureMap; LayerToTextureMap layerToTextureMap; for(unsigned int layerNum=0; layerNum<_terrainTile->getNumColorLayers(); ++layerNum) { osgTerrain::Layer* colorLayer = _terrainTile->getColorLayer(layerNum); if (!colorLayer) continue; osgTerrain::SwitchLayer* switchLayer = dynamic_cast(colorLayer); if (switchLayer) { if (switchLayer->getActiveLayer()<0 || static_cast(switchLayer->getActiveLayer())>=switchLayer->getNumLayers()) { continue; } colorLayer = switchLayer->getLayer(switchLayer->getActiveLayer()); if (!colorLayer) continue; } osg::Image* image = colorLayer->getImage(); if (!image) continue; osgTerrain::ImageLayer* imageLayer = dynamic_cast(colorLayer); osgTerrain::ContourLayer* contourLayer = dynamic_cast(colorLayer); if (imageLayer) { osg::StateSet* stateset = buffer._geode->getOrCreateStateSet(); osg::Texture2D* texture2D = dynamic_cast(layerToTextureMap[colorLayer]); if (!texture2D) { texture2D = new osg::Texture2D; texture2D->setImage(image); texture2D->setMaxAnisotropy(16.0f); texture2D->setResizeNonPowerOfTwoHint(false); texture2D->setFilter(osg::Texture::MIN_FILTER, colorLayer->getMinFilter()); texture2D->setFilter(osg::Texture::MAG_FILTER, colorLayer->getMagFilter()); texture2D->setWrap(osg::Texture::WRAP_S,osg::Texture::CLAMP_TO_EDGE); texture2D->setWrap(osg::Texture::WRAP_T,osg::Texture::CLAMP_TO_EDGE); bool mipMapping = !(texture2D->getFilter(osg::Texture::MIN_FILTER)==osg::Texture::LINEAR || texture2D->getFilter(osg::Texture::MIN_FILTER)==osg::Texture::NEAREST); bool s_NotPowerOfTwo = image->s()==0 || (image->s() & (image->s() - 1)); bool t_NotPowerOfTwo = image->t()==0 || (image->t() & (image->t() - 1)); if (mipMapping && (s_NotPowerOfTwo || t_NotPowerOfTwo)) { OSG_INFO<<"Disabling mipmapping for non power of two tile size("<s()<<", "<t()<<")"<setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR); } layerToTextureMap[colorLayer] = texture2D; // OSG_NOTICE<<"Creating new ImageLayer texture "<s()="<s()<<" image->t()="<t()<setTextureAttributeAndModes(layerNum, texture2D, osg::StateAttribute::ON); } else if (contourLayer) { osg::StateSet* stateset = buffer._geode->getOrCreateStateSet(); osg::Texture1D* texture1D = dynamic_cast(layerToTextureMap[colorLayer]); if (!texture1D) { texture1D = new osg::Texture1D; texture1D->setImage(image); texture1D->setResizeNonPowerOfTwoHint(false); texture1D->setFilter(osg::Texture::MIN_FILTER, osg::Texture::NEAREST); texture1D->setFilter(osg::Texture::MAG_FILTER, colorLayer->getMagFilter()); layerToTextureMap[colorLayer] = texture1D; } stateset->setTextureAttributeAndModes(layerNum, texture1D, osg::StateAttribute::ON); } } } void GeometryTechnique::applyTransparency() { if (_terrainTile->getBlendingPolicy()==TerrainTile::DO_NOT_SET_BLENDING) { return; } bool enableBlending = false; if (_terrainTile->getBlendingPolicy()==TerrainTile::ENABLE_BLENDING) { enableBlending = true; } else if (_terrainTile->getBlendingPolicy()==TerrainTile::ENABLE_BLENDING_WHEN_ALPHA_PRESENT) { for(unsigned int i=0; i<_terrainTile->getNumColorLayers(); ++i) { osg::Image* image = (_terrainTile->getColorLayer(i)!=0) ? _terrainTile->getColorLayer(i)->getImage() : 0; if (image) { enableBlending = image->isImageTranslucent(); break; } } } if (enableBlending) { BufferData& buffer = getWriteBuffer(); osg::StateSet* stateset = buffer._geode->getOrCreateStateSet(); stateset->setMode(GL_BLEND, osg::StateAttribute::ON); stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN); } } void GeometryTechnique::smoothGeometry() { BufferData& buffer = getWriteBuffer(); if (buffer._geometry.valid()) { osgUtil::SmoothingVisitor smoother; smoother.smooth(*buffer._geometry); } } void GeometryTechnique::update(osgUtil::UpdateVisitor* uv) { if (_terrainTile) _terrainTile->osg::Group::traverse(*uv); } void GeometryTechnique::cull(osgUtil::CullVisitor* cv) { BufferData& buffer = getReadOnlyBuffer(); #if 0 if (buffer._terrainTile) buffer._terrainTile->osg::Group::traverse(*cv); #else if (buffer._transform.valid()) { buffer._transform->accept(*cv); } #endif } void GeometryTechnique::traverse(osg::NodeVisitor& nv) { if (!_terrainTile) return; // if app traversal update the frame count. if (nv.getVisitorType()==osg::NodeVisitor::UPDATE_VISITOR) { if (_terrainTile->getDirty()) _terrainTile->init(); osgUtil::UpdateVisitor* uv = dynamic_cast(&nv); if (uv) { update(uv); return; } } else if (nv.getVisitorType()==osg::NodeVisitor::CULL_VISITOR) { osgUtil::CullVisitor* cv = dynamic_cast(&nv); if (cv) { cull(cv); return; } } if (_terrainTile->getDirty()) { OSG_INFO<<"******* Doing init ***********"<init(); } BufferData& buffer = getReadOnlyBuffer(); if (buffer._transform.valid()) buffer._transform->accept(nv); } void GeometryTechnique::cleanSceneGraph() { } void GeometryTechnique::releaseGLObjects(osg::State* state) const { if (_bufferData[0]._transform.valid()) _bufferData[0]._transform->releaseGLObjects(state); if (_bufferData[1]._transform.valid()) _bufferData[1]._transform->releaseGLObjects(state); }