ClipPlane and ClipNode do not work with MapNode

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

ClipPlane and ClipNode do not work with MapNode

Hello everyone,

I'm trying to use a ClipNode and ClipPlanes with a MapNode in order to clip some portions of the Earth and its children, however it seems that ClipNode and ClipPlanes have no effect on the osgEarth::MapNode and none of its children.

A simple code reproducing my problem is the following:

------------------------------------------
osg::Node*        l_pNode(NULL);
osg::ClipNode*   l_pClip = new osg::ClipNode;
osg::Group*       l_pRoot = new osg::Group;
osg::ClipPlane*   l_pPlane = new osg::ClipPlane;

l_pNode = osgDB::readNodeFile("data/arcgisonline.earth");

l_pPlane->setClipPlane(0,0,1,0);
l_pPlane->setClipPlaneNum(0);

l_pClip->addClipPlane(l_pPlane);

l_pRoot->addChild(l_pClip);
l_pClip->addChild(l_pNode);

---------------------------------------

If instead of arcgisonline.earth I read another file like, for instance, cow.osgt everything works as expected and the object is properly clipped.

Is there something I have to set in the MapNode StateSet? Is there another better way to clip the MapNode and its children?

Some details about my system:
 - osgEarth version: 2.10.1
 - osg version:         3.4.0
 - Compiler:            MSVC2015 x64

Thanks very much in advance.

Andrea
gwaldron gwaldron
Reply | Threaded
Open this post in threaded view
|

Re: ClipPlane and ClipNode do not work with MapNode

AndreaB,

Clip nodes are FFP (fixed function pipeline) so they will not work in osgEarth. Instead you need to use a shader. Basically you need to pass your clip plane data to the shader and then set the built-in gl_ClipDistance variable. Look in osgEarth::HorizonClipPlane::operator() to see an example.

Hope this helps!
Glenn Waldron / Pelican Mapping
AndreaB AndreaB
Reply | Threaded
Open this post in threaded view
|

Re: ClipPlane and ClipNode do not work with MapNode

Hi Glenn,

many thanks for your reply. I have looked at HorizonClipPlane::operator() and I've tried to implement that mechanism. However it seems that no clipping is performed yet.

In order to avoid conflicts with other osgEarth-related shaders I have created my own (simplified) shader and linked to this.

The important parts of my code are the following:

-----------------
MyClipPlane.glsl

#version 330
#pragma vp_name       MyClipPlane.glsl
#pragma vp_entryPoint MyClipPlaneVS
#pragma vp_location    vertex_view
#pragma vp_order       last

// OSG built-in to transform from view to world
uniform mat4 osg_ViewMatrixInverse;

// clipping plane
uniform vec4 my_plane;

void MyClipPlaneVS(inout vec4 vertex_view)
{
#ifndef GL_ES
    gl_ClipDistance[0] = dot(osg_ViewMatrixInverse * vertex_view, my_plane);
#endif
}

----------
main.cpp

class MyClipPlane : public osg::NodeCallback
{
public:

    MyClipPlane()
    {
        m_pStateSet = new osg::StateSet;
        m_pUniform = new osg::Uniform("my_plane", osg::Vec4f());
        m_pStateSet->addUniform(m_pUniform);

        m_Shaders.ClipPlane = "./shaders/MyClipPlane.glsl";

        m_pVP = osgEarth::VirtualProgram::getOrCreate(m_pStateSet);
        m_pVP->setName("MyClipPlane");
        m_Shaders.load(m_pVP, m_Shaders.ClipPlane);

        m_pUniform->set(osg::Vec4f(0, 0, 1, 0));
    }

    void operator ()(osg::Node* p_pNode, osg::NodeVisitor* p_pNodeVisitor)
    {
        osgUtil::CullVisitor* l_pCullVisitor(NULL);

        l_pCullVisitor = static_cast<osgUtil::CullVisitor*>(p_pNodeVisitor);
        l_pCullVisitor->pushStateSet(m_pStateSet);
        p_pNodeVisitor->traverse(*p_pNode);
        l_pCullVisitor->popStateSet();
    }

protected:

    osg::ref_ptr<osg::StateSet>             m_pStateSet;
    osg::ref_ptr<osg::Uniform>              m_pUniform;
    osg::ref_ptr<osgEarth::VirtualProgram>  m_pVP;
    osgEarth::Shaders                       m_Shaders;
};

int main(...)
{
    ....loading the osgEarth::MapNode here.....
   
    l_pMapNode->addCullCallback(new MyClipPlane);
   
    ....remaining code....
}

---------------------------

I'm sure that the shader is loaded since if I intentionally introduce a syntax error in it I get many error messages, and I have verified that the callback is properly called.

Am I missing something in my configuration? I would expect to see "half Earth" due to the clipping plane (0, 0, 1, 0).

Thanks in advance. Best regards.

Andrea
gwaldron gwaldron
Reply | Threaded
Open this post in threaded view
|

Re: ClipPlane and ClipNode do not work with MapNode

Andrea,

My apologies. You also need to enable clipping in a stateset by calling

stateSet->setMode(GL_CLIP_DISTANCE0, 1);

Hope this helps.
Glenn Waldron / Pelican Mapping
AndreaB AndreaB
Reply | Threaded
Open this post in threaded view
|

Re: ClipPlane and ClipNode do not work with MapNode

Yes! That was the missing part.

After adding

m_pStateSet->setMode(GL_CLIP_PLANE0, 1);

to my code I was able to view the clipped MapNode together with its children.

I did not found GL_CLIP_DISTANCE0...instead I found GL_CLIP_PLANE0...maybe I'm using an older version...

Many thanks again Glenn.

Best regards.

Andrea