ModelNode question

classic Classic list List threaded Threaded
13 messages Options
jeladi jeladi
Reply | Threaded
Open this post in threaded view
|

ModelNode question

When upgrading my osgEarth-based application from 2.8 to 3.0 I am having issues with some of my models.  In the 2.8 version I placed all my models for vehicles into LocalGeometryNodes and everything worked fine.  I didn't see how to do that with the newer API so I switched to using ModelNode.  Unfortunately now the models do not look right.  They look fine in osgViewer so I am assuming it is my usage of the ModelNode API.  Here is what the differences look like.  Any thoughts as to what I am missing?

2.8 Model Example

3.0 Model Example
jeladi jeladi
Reply | Threaded
Open this post in threaded view
|

Re: ModelNode question

I don't know if this will help in debugging but if I do the following the display issue goes away:

osgEarth::Config cfg;
cfg.set("shader_policy", "disable");
m_modelNode = new osgEarth::ModelNode(cfg, 0L);

The downside of doing that is the RTTPicker no longer works so I can't use this as a solution.  I need the shader to do the object id-related stuff so the picker works but not whatever is changing the appearance of the model.
gwaldron gwaldron
Reply | Threaded
Open this post in threaded view
|

Re: ModelNode question

Did you try running the shader generator on your model?
How are you creating this ModelNode?
Why can't you still use a LocalGeometryNode or just a GeoTransform?
Glenn Waldron / Pelican Mapping
jeladi jeladi
Reply | Threaded
Open this post in threaded view
|

Re: ModelNode question

Yes I am running the ShaderGenerator.  Here is how I read in the model file and invoke the shader generator.  I have not changed any of this code in the migration to 3.0:

Asset::Asset(const std::string &filename) :
    m_node(osgDB::readNodeFile(filename)), ...
{
    ...

    m_node->getOrCreateStateSet()->setMode(GL_RESCALE_NORMAL,
                                           osg::StateAttribute::ON);
    m_node->getOrCreateStateSet()->setMode(GL_LIGHTING,
                                           osg::StateAttribute::ON);
    m_node->getOrCreateStateSet()->setMode(GL_BLEND,
                                           osg::StateAttribute::ON);
    m_node->getOrCreateStateSet()->setRenderingHint(osg::StateSet::OPAQUE_BIN);

    ...

    m_node->getOrCreateStateSet()->setAttributeAndModes(m_cullFace.get(), osg::StateAttribute::ON);

    osgEarth::ShaderGenerator gen;
    m_node->accept(gen);

    osgDB::Registry::instance()->getOrCreateSharedStateManager()->share(m_node.get());
}

Then I have another class that handles the stuff dealing with the ModelNode.  It takes the m_node.get() value from Asset into its constructor:

AssetInstance::AssetInstance(...)
    m_node(node), ...
{
   ...

   m_style.getOrCreate<osgEarth::ModelSymbol>()->setModel(m_node.get());

    osgEarth::Config cfg;
    cfg.set("shader_policy", "generate");
    m_modelNode = new osgEarth::ModelNode(cfg, 0L);

    m_modelNode->setMapNode(mapNode);
    m_modelNode->setStyle(m_style);
    m_modelNode->setScale(osg::Vec3f(m_currentScale, m_currentScale, m_currentScale));
    m_modelNode->setDynamic(true);

    osgEarth::Registry::objectIndex()->tagNode(m_modelNode.get(), m_modelNode.get());

    ...

    mapNode->addChild(m_modelNode.get());

}

In the 2.8 version I did this to create the model node:

m_modelNode = new osgEarth::Annotation::LocalGeometryNode(mapNode, m_node.get(), m_style);

which used this constructor:

LocalGeometryNode(
            MapNode*     mapNode,
            osg::Node*   node,
            const Style& style  =Style() );

That constructor is gone in the 3.0 version which is why I haven't used it.  Should I be doing something more like the osgearth_transform example instead?
gwaldron gwaldron
Reply | Threaded
Open this post in threaded view
|

Re: ModelNode question

ModelNode, LocalGeometrynode, et al are really there to support the Annotation subsystem. If you don't need symbology, it would indeed be simpler and more straightforward to just use GeoTransform as in the osgearth_transform example.

Also, modes like GL_RESCALE_NORMAL and GL_LIGHTING are unnecessary since the osgEarth shader pipeline will take care of that stuff.
Glenn Waldron / Pelican Mapping
jeladi jeladi
Reply | Threaded
Open this post in threaded view
|

Re: ModelNode question

Thanks for the tip on GeoTransform.  I have got that route that mostly working although my models still don't look right.  For some reason it's only the models that were originally in FBX format that have this issue.  Other models where I started out with OBJ or 3DS first before converting to IVE look fine.

After the mod to use GeoTransform I am doing almost nothing to manipulate the node for the model after it is read in from the file.  Now I call readDB(),  do an

m_node->clone(osg::CopyOp::Options::DEEP_COPY_NODES)->asNode()

to pass the data in to another class, and do m_node.accept() with the ShaderGenerator.  It shows correctly in osgViewer so I will just have to trace through the code and see what's different about the various settings.  I thought I remembered seeing something about the IVE format being deprecated now but if that was the issue it seems like it wouldn't display correctly in the viewer.

Right now I am only using symbology for the terrain clamping in the AltitudeSymbol. I have some older code that can do it via an osgEarth::TerrainCallback instead so I can migrate that to 3.0 if the classes it uses are still available.
gwaldron gwaldron
Reply | Threaded
Open this post in threaded view
|

Re: ModelNode question

GeoTransform supports clamping if you call setTerrain().

osgviewer uses the FFP so there can certainly be differences. Is there any chance you can share one of your models so we can investigate?
Glenn Waldron / Pelican Mapping
jeladi jeladi
Reply | Threaded
Open this post in threaded view
|

Re: ModelNode question

Unfortunately I cannot share models since this is for proprietary work so I will have to debug it from my end. I did notice a difference when I turned the lighting for the sky layer on/off.  If the sky lighting is on I can see the features of the model a little better.  As an experiment I ran osgviewer and hit 'l' to turn off the lighting and got the same result that I see in my application.  So lighting is definitely a factor.

I thought even without the sky layer there was some degree of ambient light that would illuminate the models.  If I query the main view for some of its light parameters I get a lighting mode of HEADLIGHT and an ambient light of (0.0, 0.0, 0.0, 1.0).  That's completely off, right?  In earlier versions of my 2.8-based app I didn't have a sky layer and things still showed up.  Maybe the defaults changed?
jeladi jeladi
Reply | Threaded
Open this post in threaded view
|

Re: ModelNode question

I figured out the issue so I will post the solution here in case anyone else runs into this problem.  Previously in v2.8 I used LocalGeometryNode which inherits from GeoPositionNode.  In the constructor for GeoPositionNode the init() function gets called.  Inside GeoPositionNode::init() there is this line:

this->getOrCreateStateSet()->setMode( GL_LIGHTING, 0 );

In v3.0 I used ModelNode which also inherits from GeoPositionNode.  When the constructor for GeoPositionNode is invoked GeoPositionNode::construct() gets called since there is no longer a GeoPositionNode::init() in v3.0. GeoPositionNode::construct() is very similar to the older GeoPositionNode::init() but it does not have that setMode() call for GL_LIGHTING.

So instead I tried this:

m_modelNode = new osgEarth::ModelNode(mapNode, m_style);
m_modelNode->getOrCreateStateSet()->setMode(GL_LIGHTING, 0);

Now the models look correct whether the lighting for the sky layer is on or off.
jeladi jeladi
Reply | Threaded
Open this post in threaded view
|

Re: ModelNode question

I am running into one issue with this solution.  It worked yesterday evening but when I tried this morning it still exhibited the same behavior as before.  As an experiment I tried adding an hours variable to the sky layer in the earth file instead of using the system clock.  I set it to 20 since the object was in Japan.  Once I did that the model appeared correctly.

If I have turned off the lighting for the sky node via:

m_skyNode->setLighting(osg::StateAttribute::OFF);

why does changing the hour variable have an impact on whether or not I can see the model correctly?  What is controlling the ambient light of the scene?
jeladi jeladi
Reply | Threaded
Open this post in threaded view
|

Re: ModelNode question

In both the 2.8 and 3.0 versions I have taken the sky layer out of the earth file.  Is it true that in this case the only light that should be present is the light associated with the primary view?  There are no osg::Light objects in the scene graph if I use a FindNodeVisitor from the root.

In the 2.8 version the model is illuminated but in the 3.0 version it is not.  I am no longer turning off the GL_LIGHTING in the state set in the 3.0 version so that is not the issue.  The ambient, diffuse, and specular components for the single light in the view are the same for both versions.  The position and direction are also the same.  In both versions the ShaderGenerator gets invoked when the model is loaded.

So is there another light I am unaware of that is acting on my model in the 2.8 version?  Has there been a change to the shaders used that could potentially cause this?

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

Re: ModelNode question

If you don't use a sky, there are no lighting shaders at all. So any lighting parameters you use will have no effect.

I honestly don't remember back to version 2.8; perhaps there was some default lighting shader or perhaps it fell back on an FFP lighting model.
Glenn Waldron / Pelican Mapping
jeladi jeladi
Reply | Threaded
Open this post in threaded view
|

Re: ModelNode question

I played around with the ModelNode constructor for a bit and this block in ModelNode.cpp is what makes the difference:

if (_shaderPolicy == SHADERPOLICY_GENERATE)
 {
      // generate shader code for the loaded model:                  
      Registry::shaderGenerator().run(
                        node.get(),
                        "osgEarth.ModelNode",
                        Registry::stateSetCache());
 }
else if (_shaderPolicy == SHADERPOLICY_DISABLE)
{
   node->getOrCreateStateSet()->setAttributeAndModes(
                        new osg::Program(),
                        osg::StateAttribute::OFF | osg::StateAttribute::OVERRIDE);
}

If the block for the 'generate' option is executed then my models do not appear correct unless the sky layer is on and my models happen to be in or near the sunlight portion of the globe.

If the block for the 'disable' block is executed then my model appears correct regardless of whether the sky layer is present or not.  The only downside of this is that my RTTPicker no longer works because I guess the object ids don't get applied if you don't generate the shader.

How can I modify the shader such that the RTTPicker will still work but the appearance of my model will not change?