bool ResourceCache::getOrCreateLineTexture(const URI& uri, osg::ref_ptr<osg::Texture>& output, const osgDB::Options* readOptions) { Threading::ScopedMutexLock lock(_texMutex); TextureCache::Record rec; if (_texCache.get(uri.full(), rec) && rec.value().valid()) { output = rec.value().get(); } else { osg::ref_ptr<osg::Image> image = uri.getImage(readOptions); if (image.valid()) { osg::Texture2D* tex = new osg::Texture2D(image); tex->setWrap( osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE ); tex->setWrap( osg::Texture::WRAP_T, osg::Texture::REPEAT ); tex->setFilter( osg::Texture::MIN_FILTER, osg::Texture::LINEAR_MIPMAP_LINEAR ); tex->setFilter( osg::Texture::MAG_FILTER, osg::Texture::LINEAR); tex->setMaxAnisotropy( 4.0f ); tex->setResizeNonPowerOfTwoHint( false ); output = tex; _texCache.insert(uri.full(), output.get()); } } return output.valid(); }
bool LandCoverBiome::configure(const ConfigOptions& conf, const osgDB::Options* dbo) { LandCoverBiomeOptions in( conf ); if ( in.biomeClasses().isSet() ) setClasses( in.biomeClasses().get() ); for(SymbolVector::const_iterator i = in.symbols().begin(); i != in.symbols().end(); ++i) { const BillboardSymbol* bs = dynamic_cast<BillboardSymbol*>( i->get() ); if ( bs ) { URI imageURI = bs->url()->evalURI(); osg::Image* image = const_cast<osg::Image*>( bs->getImage() ); if ( !image ) { image = imageURI.getImage(dbo); } if ( image ) { getBillboards().push_back( LandCoverBillboard(image, bs->width().get(), bs->height().get()) ); } else { OE_WARN << LC << "Failed to load billboard image from \"" << imageURI.full() << "\"\n"; } } else { OE_WARN << LC << "Unrecognized symbol in land cover biome\n"; } } if ( getBillboards().size() == 0 ) { OE_WARN << LC << "A biome failed to install any billboards.\n"; return false; } return true; }
void PlaceNode::init(const osgDB::Options* dbOptions) { _geode = new osg::Geode(); osg::Drawable* text = 0L; // If there's no explicit text, look to the text symbol for content. if ( _text.empty() && _style.has<TextSymbol>() ) _text = _style.get<TextSymbol>()->content()->eval(); osg::ref_ptr<const InstanceSymbol> instance = _style.get<InstanceSymbol>(); // backwards compability, support for deprecated MarkerSymbol if ( !instance.valid() && _style.has<MarkerSymbol>() ) instance = _style.get<MarkerSymbol>()->convertToInstanceSymbol(); const IconSymbol* icon = instance->asIcon(); if ( !_image.valid() ) { URI imageURI; if ( icon ) { if ( icon->url().isSet() ) { imageURI = URI( icon->url()->eval(), icon->url()->uriContext() ); } } if ( !imageURI.empty() ) { _image = imageURI.getImage( dbOptions ); } } // found an image; now format it: if ( _image.get() ) { // this offset anchors the image at the bottom osg::Vec2s offset; if ( !icon || !icon->alignment().isSet() ) { // default to bottom center offset.set(0.0, (_image->t() / 2.0)); } else { // default to bottom center switch (icon->alignment().value()) { case IconSymbol::ALIGN_LEFT_TOP: offset.set((_image->s() / 2.0), -(_image->t() / 2.0)); break; case IconSymbol::ALIGN_LEFT_CENTER: offset.set((_image->s() / 2.0), 0.0); break; case IconSymbol::ALIGN_LEFT_BOTTOM: offset.set((_image->s() / 2.0), (_image->t() / 2.0)); break; case IconSymbol::ALIGN_CENTER_TOP: offset.set(0.0, -(_image->t() / 2.0)); break; case IconSymbol::ALIGN_CENTER_CENTER: offset.set(0.0, 0.0); break; case IconSymbol::ALIGN_CENTER_BOTTOM: default: offset.set(0.0, (_image->t() / 2.0)); break; case IconSymbol::ALIGN_RIGHT_TOP: offset.set(-(_image->s() / 2.0), -(_image->t() / 2.0)); break; case IconSymbol::ALIGN_RIGHT_CENTER: offset.set(-(_image->s() / 2.0), 0.0); break; case IconSymbol::ALIGN_RIGHT_BOTTOM: offset.set(-(_image->s() / 2.0), (_image->t() / 2.0)); break; } } // Apply a rotation to the marker if requested: double heading = 0.0; if ( icon && icon->heading().isSet() ) { heading = osg::DegreesToRadians( icon->heading()->eval() ); } //We must actually rotate the geometry itself and not use a MatrixTransform b/c the //decluttering doesn't respect Transforms above the drawable. osg::Geometry* imageGeom = AnnotationUtils::createImageGeometry( _image.get(), offset, 0, heading ); if ( imageGeom ) _geode->addDrawable( imageGeom ); text = AnnotationUtils::createTextDrawable( _text, _style.get<TextSymbol>(), osg::Vec3( (offset.x() + (_image->s() / 2.0) + 2), offset.y(), 0 ) ); } else { text = AnnotationUtils::createTextDrawable( _text, _style.get<TextSymbol>(), osg::Vec3( 0, 0, 0 ) ); } if ( text ) _geode->addDrawable( text ); osg::StateSet* stateSet = _geode->getOrCreateStateSet(); stateSet->setAttributeAndModes( new osg::Depth(osg::Depth::ALWAYS, 0, 1, false), 1 ); getAttachPoint()->addChild( _geode ); // for clamping applyStyle( _style ); setLightingIfNotSet( false ); ShaderGenerator gen( Registry::stateSetCache() ); this->accept( gen ); }
void PlaceNode::init() { //reset. this->clearDecoration(); getAttachPoint()->removeChildren(0, getAttachPoint()->getNumChildren()); _geode = new osg::Geode(); osg::Drawable* text = 0L; // If there's no explicit text, look to the text symbol for content. if ( _text.empty() && _style.has<TextSymbol>() ) { _text = _style.get<TextSymbol>()->content()->eval(); } osg::ref_ptr<const InstanceSymbol> instance = _style.get<InstanceSymbol>(); // backwards compability, support for deprecated MarkerSymbol if ( !instance.valid() && _style.has<MarkerSymbol>() ) { instance = _style.get<MarkerSymbol>()->convertToInstanceSymbol(); } const IconSymbol* icon = instance->asIcon(); if ( !_image.valid() ) { URI imageURI; if ( icon ) { if ( icon->url().isSet() ) { imageURI = URI( icon->url()->eval(), icon->url()->uriContext() ); } } if ( !imageURI.empty() ) { _image = imageURI.getImage( _dbOptions.get() ); } } // found an image; now format it: if ( _image.get() ) { // Scale the icon if necessary double scale = 1.0; if ( icon && icon->scale().isSet() ) { scale = icon->scale()->eval(); } double s = scale * _image->s(); double t = scale * _image->t(); // this offset anchors the image at the bottom osg::Vec2s offset; if ( !icon || !icon->alignment().isSet() ) { // default to bottom center offset.set(0.0, t / 2.0); } else { // default to bottom center switch (icon->alignment().value()) { case IconSymbol::ALIGN_LEFT_TOP: offset.set((s / 2.0), -(t / 2.0)); break; case IconSymbol::ALIGN_LEFT_CENTER: offset.set((s / 2.0), 0.0); break; case IconSymbol::ALIGN_LEFT_BOTTOM: offset.set((s / 2.0), (t / 2.0)); break; case IconSymbol::ALIGN_CENTER_TOP: offset.set(0.0, -(t / 2.0)); break; case IconSymbol::ALIGN_CENTER_CENTER: offset.set(0.0, 0.0); break; case IconSymbol::ALIGN_CENTER_BOTTOM: default: offset.set(0.0, (t / 2.0)); break; case IconSymbol::ALIGN_RIGHT_TOP: offset.set(-(s / 2.0), -(t / 2.0)); break; case IconSymbol::ALIGN_RIGHT_CENTER: offset.set(-(s / 2.0), 0.0); break; case IconSymbol::ALIGN_RIGHT_BOTTOM: offset.set(-(s / 2.0), (t / 2.0)); break; } } // Apply a rotation to the marker if requested: double heading = 0.0; if ( icon && icon->heading().isSet() ) { heading = osg::DegreesToRadians( icon->heading()->eval() ); } //We must actually rotate the geometry itself and not use a MatrixTransform b/c the //decluttering doesn't respect Transforms above the drawable. osg::Geometry* imageGeom = AnnotationUtils::createImageGeometry( _image.get(), offset, 0, heading, scale ); if ( imageGeom ) { _geode->addDrawable( imageGeom ); } text = AnnotationUtils::createTextDrawable( _text, _style.get<TextSymbol>(), osg::Vec3( (offset.x() + (s / 2.0) + 2), offset.y(), 0 ) ); } else { text = AnnotationUtils::createTextDrawable( _text, _style.get<TextSymbol>(), osg::Vec3( 0, 0, 0 ) ); } if ( text ) _geode->addDrawable( text ); osg::StateSet* stateSet = _geode->getOrCreateStateSet(); stateSet->setAttributeAndModes( new osg::Depth(osg::Depth::ALWAYS, 0, 1, false), 1 ); getAttachPoint()->addChild( _geode ); // for clamping and occlusion culling //OE_WARN << LC << "PlaceNode::applyStyle: " << _style.getConfig().toJSON(true) << std::endl; applyStyle( _style ); setLightingIfNotSet( false ); ShaderGenerator gen; gen.setProgramName( "osgEarth.PlaceNode" ); gen.run( this, Registry::stateSetCache() ); // re-apply annotation drawable-level stuff as neccesary. AnnotationData* ad = getAnnotationData(); if ( ad ) setAnnotationData( ad ); if ( _dynamic ) setDynamic( _dynamic ); }
void PlaceNode::init() { Decluttering::setEnabled( this->getOrCreateStateSet(), true ); osgEarth::clearChildren( getPositionAttitudeTransform() ); _geode = new osg::Geode(); // ensure that (0,0,0) is the bounding sphere control/center point. // useful for things like horizon culling. _geode->setComputeBoundingSphereCallback(new ControlPointCallback()); osg::Drawable* text = 0L; // If there's no explicit text, look to the text symbol for content. if ( _text.empty() && _style.has<TextSymbol>() ) { _text = _style.get<TextSymbol>()->content()->eval(); } osg::ref_ptr<const InstanceSymbol> instance = _style.get<InstanceSymbol>(); // backwards compability, support for deprecated MarkerSymbol if ( !instance.valid() && _style.has<MarkerSymbol>() ) { instance = _style.get<MarkerSymbol>()->convertToInstanceSymbol(); } const IconSymbol* icon = instance->asIcon(); if ( !_image.valid() ) { URI imageURI; if ( icon ) { if ( icon->url().isSet() ) { imageURI = icon->url()->evalURI(); } else if (icon->getImage()) { _image = icon->getImage(); } } if ( !imageURI.empty() ) { _image = imageURI.getImage( _dbOptions.get() ); } } osg::BoundingBox imageBox(0,0,0,0,0,0); // found an image; now format it: if ( _image.get() ) { // Scale the icon if necessary double scale = 1.0; if ( icon && icon->scale().isSet() ) { scale = icon->scale()->eval(); } double s = scale * _image->s(); double t = scale * _image->t(); // this offset anchors the image at the bottom osg::Vec2s offset; if ( !icon || !icon->alignment().isSet() ) { // default to bottom center offset.set(0.0, t / 2.0); } else { // default to bottom center switch (icon->alignment().value()) { case IconSymbol::ALIGN_LEFT_TOP: offset.set((s / 2.0), -(t / 2.0)); break; case IconSymbol::ALIGN_LEFT_CENTER: offset.set((s / 2.0), 0.0); break; case IconSymbol::ALIGN_LEFT_BOTTOM: offset.set((s / 2.0), (t / 2.0)); break; case IconSymbol::ALIGN_CENTER_TOP: offset.set(0.0, -(t / 2.0)); break; case IconSymbol::ALIGN_CENTER_CENTER: offset.set(0.0, 0.0); break; case IconSymbol::ALIGN_CENTER_BOTTOM: default: offset.set(0.0, (t / 2.0)); break; case IconSymbol::ALIGN_RIGHT_TOP: offset.set(-(s / 2.0), -(t / 2.0)); break; case IconSymbol::ALIGN_RIGHT_CENTER: offset.set(-(s / 2.0), 0.0); break; case IconSymbol::ALIGN_RIGHT_BOTTOM: offset.set(-(s / 2.0), (t / 2.0)); break; } } // Apply a rotation to the marker if requested: double heading = 0.0; if ( icon && icon->heading().isSet() ) { heading = osg::DegreesToRadians( icon->heading()->eval() ); } //We must actually rotate the geometry itself and not use a MatrixTransform b/c the //decluttering doesn't respect Transforms above the drawable. osg::Geometry* imageGeom = AnnotationUtils::createImageGeometry( _image.get(), offset, 0, heading, scale ); if ( imageGeom ) { _geode->addDrawable( imageGeom ); imageBox = osgEarth::Utils::getBoundingBox( imageGeom ); } } if ( _image.valid() ) { TextSymbol* textSymbol = _style.getOrCreate<TextSymbol>(); if ( !textSymbol->alignment().isSet() ) textSymbol->alignment() = textSymbol->ALIGN_LEFT_CENTER; } text = AnnotationUtils::createTextDrawable( _text, _style.get<TextSymbol>(), imageBox ); if ( text ) _geode->addDrawable( text ); osg::StateSet* stateSet = _geode->getOrCreateStateSet(); stateSet->setAttributeAndModes( new osg::Depth(osg::Depth::ALWAYS, 0, 1, false), 1 ); getPositionAttitudeTransform()->addChild( _geode ); // for clamping and occlusion culling //OE_WARN << LC << "PlaceNode::applyStyle: " << _style.getConfig().toJSON(true) << std::endl; applyStyle( _style ); setLightingIfNotSet( false ); // generate shaders: Registry::shaderGenerator().run( this, "osgEarth.PlaceNode", Registry::stateSetCache() ); setPriority(getPriority()); if ( _dynamic ) setDynamic( _dynamic ); updateLayoutData(); }