/* -*-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 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) { } 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::notify(osg::NOTICE)<<"Doing GeometryTechnique::init()"<setThreadSafeRefUnref(true); _dirty = false; swapBuffers(); } Locator* GeometryTechnique::computeMasterLocator() { osgTerrain::Layer* elevationLayer = _terrain->getElevationLayer(); osgTerrain::Layer* colorLayer = _terrain->getColorLayer(0); Locator* elevationLocator = elevationLayer ? elevationLayer->getLocator() : 0; Locator* colorLocator = colorLayer ? colorLayer->getLocator() : 0; Locator* masterLocator = elevationLocator ? elevationLocator : colorLocator; if (!masterLocator) { osg::notify(osg::NOTICE)<<"Problem, no locator found in any of the terrain layers"<getElevationLayer(); osgTerrain::Layer* colorLayer = _terrain->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::notify(osg::INFO)<<"bottomLeftNDC = "<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->getFilter()==Layer::LINEAR ? osg::Texture::LINEAR : osg::Texture::NEAREST); layerToTextureMap[colorLayer] = texture1D; } stateset->setTextureAttributeAndModes(layerNum, texture1D, osg::StateAttribute::ON); } } } void GeometryTechnique::applyTransparency() { BufferData& buffer = getWriteBuffer(); bool containsTransparency = false; for(unsigned int i=0; i<_terrain->getNumColorLayers(); ++i) { osg::Image* image = _terrain->getColorLayer(i)->getImage(); if (image) { containsTransparency = image->isImageTranslucent(); break; } } if (containsTransparency) { 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 (_terrain) _terrain->osg::Group::traverse(*uv); } void GeometryTechnique::cull(osgUtil::CullVisitor* cv) { BufferData& buffer = getReadOnlyBuffer(); #if 0 if (buffer._terrain) buffer._terrain->osg::Group::traverse(*cv); #else if (buffer._transform.valid()) { buffer._transform->accept(*cv); } #endif } void GeometryTechnique::traverse(osg::NodeVisitor& nv) { if (!_terrain) return; // if app traversal update the frame count. if (nv.getVisitorType()==osg::NodeVisitor::UPDATE_VISITOR) { if (_dirty) _terrain->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 (_dirty) { osg::notify(osg::INFO)<<"******* Doing init ***********"<init(); } BufferData& buffer = getReadOnlyBuffer(); if (buffer._transform.valid()) buffer._transform->accept(nv); } void GeometryTechnique::cleanSceneGraph() { } void GeometryTechnique::dirty() { TerrainTechnique::dirty(); }