How to place an Image inside an Image?

classic Classic list List threaded Threaded
5 messages Options
joseph joseph
Reply | Threaded
Open this post in threaded view
|

How to place an Image inside an Image?

Hello Everyone!

Ok, so I need to place an image inside an image, such that, any transparent pixels of the inner image 'cut a hole' past the outer image (subsequently displaying the background layer behind both images).

I can do this in OSG using Stencils (applied to a Geode), but it seems osgEarth only uses the ImageOverlay class to display Images.  So my question is either:

a) How to apply an osg::Stenicl/osg::Geode to an osgEarth::ImageOverlay?

or, b) Does ImageOverlay have its own method of Stenciling, or is there a way to 'cut a hole' in an existing ImageOverlay?

or c) Some other method I'm not aware of?


I'm coding in C++

Thank you so much for sharing your wisdom & insight!

// joe
gwaldron gwaldron
Reply | Threaded
Open this post in threaded view
|

Re: How to place an Image inside an Image?

Hi Joseph,

The ImageOverlay is just a wrapper around the more generic DrapeableNode, which renders its subgraph to a texture and then projects that texture on to the earth's surface. Maybe that will work for you.
Glenn Waldron / Pelican Mapping
joseph joseph
Reply | Threaded
Open this post in threaded view
|

Re: How to place an Image inside an Image?

Thank you for your response Glenn.

Can you help me understand how to use DrapeableNode to achieve stenciling or placing an image inside an image?  DrapeableNode appears to simply have a method for setting mapNode and not much else.

Many thanks in advance!

// joe
gwaldron gwaldron
Reply | Threaded
Open this post in threaded view
|

Re: How to place an Image inside an Image?

What is your final objective? i.e. Why are you trying to do this? Some context will help answer your question. Thanks.
Glenn Waldron / Pelican Mapping
joseph joseph
Reply | Threaded
Open this post in threaded view
|

Re: How to place an Image inside an Image?

Hello again Glenn!

I have a smaller image whose color is blending with the color of the larger image behind it.
In my image attached, you can see 2 shades of red - the green color should of the outer image should not be influencing the red color of the inner image.



Here is my current code:
------------------------------------------------------------------------------------------------------------------

    osgEarth::MapNode* mapNode = inMapNode; // passed in by method argument
    osg::Group* _rootNode = inRootNode; // passed in by method argument
    osg::Group* _viewGroup = inViewGroup; // passed in by method argument

    osg::ref_ptr<osg::Group> group_overlay = new osg::Group();
    osg::ref_ptr<osg::Group> group_outer = new osg::Group();
    osg::ref_ptr<osg::Group> group_inner = new osg::Group();

    _rootNode->addChild(group_overlay);
    group_overlay->addChild(group_outer);
    group_overlay->addChild(group_inner);

    // make sure that the global color mask exists.
    osg::ColorMask* rootColorMask = new osg::ColorMask;
    rootColorMask->setMask(true,true,true,true);

    // set up depth to be inherited by the rest of the scene unless
    // overridden. this is overridden in goup_inner.
    osg::Depth* rootDepth = new osg::Depth;
    rootDepth->setFunction(osg::Depth::LESS);
    rootDepth->setRange(0.0,1.0);

    osg::StateSet* rootStateSet = new osg::StateSet();
    rootStateSet->setAttribute(rootColorMask);
    rootStateSet->setAttribute(rootDepth);

    group_overlay->setStateSet(rootStateSet);

        ////////////////////////////////////////////////////////////////////////////////

    // Assign pseudo colored image
    osg::ref_ptr<osg::Image> result = new osg::Image;
    result->setImage(width, height, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, new_png, osg::Image::NO_DELETE);

    osg::ref_ptr<osgEarth::Annotation::ImageOverlay> innerImageOverlay = nullptr;
    innerImageOverlay = new osgEarth::Annotation::ImageOverlay( mapNode, result );
    innerImageOverlay->setBounds( osgEarth::Bounds( lon1_deg, lat1_deg, lon2_deg, lat2_deg) );
    innerImageOverlay->setDraped(false);

    // set up depth so all writing to depth goes to maximum depth.
    osg::Depth* depth = new osg::Depth;
    depth->setFunction(osg::Depth::ALWAYS);
    depth->setRange(1.0,1.0);

    // set up the stencil ops so that only operator on this mirrors stencil value.
    osg::Stencil* stencil = new osg::Stencil;
    stencil->setFunction(osg::Stencil::ALWAYS,1,~0u);
    stencil->setOperation(osg::Stencil::REPLACE, osg::Stencil::REPLACE, osg::Stencil::REPLACE);

    // set up additive blending.
    osg::BlendFunc* trans = new osg::BlendFunc;
    trans->setFunction(osg::BlendFunc::ONE,osg::BlendFunc::ONE);

    osg::StateSet* state = new osg::StateSet;
    state->setMode(GL_CULL_FACE,osg::StateAttribute::OFF|osg::StateAttribute::PROTECTED);

    state->setRenderBinDetails(107, "RenderBin");
    state->setMode(GL_CULL_FACE,osg::StateAttribute::OFF);
    state->setAttributeAndModes(stencil,osg::StateAttribute::ON);
    state->setAttributeAndModes(trans,osg::StateAttribute::ON);
    state->setAttribute(depth);

    group_inner->setStateSet(state);
    group_inner->addChild( innerImageOverlay );
       
        ///////////////////////////////////////////////////////////////////////////////
       
    // Convert png data to osg::Image
    std::string dataBuffer( (char*)outer_overlay.png, outer_overlay.png_size );
    std::istringstream inputStream(dataBuffer);
    std::string dbOptionsStr = "";
    osgDB::Options *dbOptions = new osgDB::Options( dbOptionsStr );
    osg::ref_ptr<osg::Image> result = osgEarth::ImageUtils::readStream( inputStream, dbOptions );
       
    osg::ref_ptr<osgEarth::Annotation::ImageOverlay> outerImageOverlay = nullptr;
    outerImageOverlay = new osgEarth::Annotation::ImageOverlay(mapNode, result);
    outerImageOverlay->setDraped(false);

    // set up depth so all writing to depth goes to maximum depth.
    osg::Depth* depth = new osg::Depth;
    depth->setFunction(osg::Depth::ALWAYS);

    osg::Stencil* stencil = new osg::Stencil;
    stencil->setFunction(osg::Stencil::NOTEQUAL,1,~0u);
    stencil->setOperation(osg::Stencil::KEEP, osg::Stencil::KEEP, osg::Stencil::KEEP);

    osg::StateSet* state = new osg::StateSet;
    state->setMode(GL_CULL_FACE,osg::StateAttribute::OFF|osg::StateAttribute::PROTECTED);
    state->setRenderBinDetails(106,"RenderBin");
    state->setMode(GL_CULL_FACE,osg::StateAttribute::OFF);
    state->setAttributeAndModes(stencil,osg::StateAttribute::ON);
    state->setAttribute(depth);

    group_outer->setStateSet(state);
    group_outer->addChild( outerImageOverlay );
------------------------------------------------------------------------------------------------------------------

Thank you so much for your assistance :)