osgearth icon indicating copy to clipboard operation
osgearth copied to clipboard

Feature with ModelSymbol with model node created from a FeatureSource not displayed

Open sebalaig opened this issue 11 months ago • 9 comments

Discussed in https://github.com/gwaldron/osgearth/discussions/2311

Originally posted by sebalaig July 18, 2023 Hello,

I'm trying to display an OSG geode (in an osg file "arrow.osg") in my map using the Feature and ModelSymbol tools, but this is not working: nothing is visible. I'm missing something but I cannot figure out what's wrong..

Here is my code:

        osgEarth::Style style;
        ModelSymbol* modelSymbol = style.getOrCreate<ModelSymbol>();
        auto* tmp= osgDB::readFile<osg::Geode>("arrow.osg");
        modelSymbol->setModel(tmp);
        modelSymbol->heading() = 50;
        modelSymbol->scale()   = 2;
        modelSymbol->placement() = InstanceSymbol::PLACEMENT_VERTEX;
        modelSymbol->autoScale() = true;

        osg::ref_ptr<osgEarth::PointSet> point = new osgEarth::PointSet(1);
        point->push_back(2.35, 48.85, 50);

        osg::ref_ptr<Feature> feature = new Feature(point, geoSRS, style);
        osg::ref_ptr<FeatureNode> featureNode = new FeatureNode(feature);
        featureNode->setMapNode(mapNode);
        
        mapNode->addChild(featureNode);

That code was ok using previous osgearth version (2.7) but fails with v3.3.

I tested by using osg::Transform to rotate/scale and GeoTransform to set the model position => it ok.

But in my context, I'm in an overload of FeatureSource::createFeatureCursorImplementation, so I have to build features, and it would be easier/cleaner to use osgearth API instead of OSG one's IMHO.

Thank you in advance for your help.

sebalaig avatar Jul 20 '23 13:07 sebalaig

It looks like a bug fixed in osgearth 3.4, a duplicate of #2299. I will update my osgearth version and confirm that.

sebalaig avatar Jul 20 '23 15:07 sebalaig

It looks like a bug fixed in osgearth 3.4, a duplicate of #2299. I will update my osgearth version and confirm that.

I tested with the master branch @ ed410ee952a9ec9f32a414d8179c3a75f62b0a6c, I confirm that creating a FeatureNode is ok by setting the model of the ModelSymbol.

However, my problem still occurs while creating Features from a FeatureSource::createFeatureCursorImplementation implementation.

sebalaig avatar Jul 21 '23 07:07 sebalaig

Hi, can anybody help me about this problem please ? I cannot find any workaround (@gwaldron ?). Thank you in advance for your help 🙏 .

sebalaig avatar Aug 01 '23 10:08 sebalaig

Sorry for the delay. Can you try this is the master branch and let us know if it works? If not, can you pls provide a simple cpp to reproduce?

gwaldron avatar Oct 23 '23 20:10 gwaldron

Sorry for the delay. Can you try this is the master branch and let us know if it works? If not, can you pls provide a simple cpp to reproduce?

Hi, I still reproduce in main branch. Here is a main trying to display a pointset with a ModelSymbol (red_flag.osg) in Paris :

#include <osgEarth/MapNode>

#include <osgEarth/EarthManipulator>
#include <osgEarth/ExampleResources>

#include <osgEarth/ImageOverlay>
#include <osgEarth/CircleNode>
#include <osgEarth/RectangleNode>
#include <osgEarth/EllipseNode>
#include <osgEarth/PlaceNode>
#include <osgEarth/LabelNode>
#include <osgEarth/LocalGeometryNode>
#include <osgEarth/FeatureNode>
#include <osgEarth/ModelNode>
#include <osgEarth/FeatureSource>
#include <osgEarth/ImageOverlayEditor>
#include <osgEarth/GeometryFactory>
#include <osgEarth/Registry>
#include <osgEarth/TiledFeatureModelLayer>

#include <osgViewer/Viewer>
#include <osgDB/ReadFile>
#include <osgGA/CameraManipulator>

using namespace osgEarth;
using namespace osgEarth::Util;
using namespace osgEarth::Contrib;
using namespace osgEarth::Util;




class TestFeatureSource : public osgEarth::FeatureSource
{
public:
    TestFeatureSource(osgEarth::MapNode *mapNode, const osgEarth::FeatureSource::Options& options = osgEarth::FeatureSource::Options());
    virtual ~TestFeatureSource();

    const osgEarth::FeatureProfile* createFeatureProfile();

    //! Implements the feature cursor creation
    virtual osgEarth::FeatureCursor* createFeatureCursorImplementation(const osgEarth::Query& query, osgEarth::ProgressCallback* progress) override;

    virtual osgEarth::Geometry::Type getGeometryType() const;

private:

    osgEarth::MapNode *_p_mapNode;

    const osgEarth::FeatureSource::Options      _options;
    osgEarth::FeatureSchema        _schema;
    osg::ref_ptr<osgDB::Options>    _dbOptions;
};

TestFeatureSource::TestFeatureSource(MapNode *mapNode, const FeatureSource::Options& options )
    : FeatureSource(new osgEarth::FeatureSource::Options(options), nullptr), _p_mapNode(mapNode), _options( options )
{
    setFeatureProfile(createFeatureProfile());
}

TestFeatureSource::~TestFeatureSource()
{
}

const FeatureProfile* TestFeatureSource::createFeatureProfile()
{
    const Profile* wgs84 = Registry::instance()->getGlobalGeodeticProfile();
    
    GeoExtent extent(wgs84->getSRS(), 2, 48, 3, 49);
    FeatureProfile* profile = new FeatureProfile( extent );
    profile->setTilingProfile( Profile::create("wgs84", extent.xMin(), extent.yMin(), extent.xMax(), extent.yMax()) );
    return profile;
}

FeatureCursor* TestFeatureSource::createFeatureCursorImplementation(const Query& query, ProgressCallback* progress)
{
    FeatureListCursor *listCursor = NULL;

    /* -- Get extent -- */
    if( query.tileKey().isSet() )
    {
        osgEarth::FeatureList features;

        const SpatialReference* geoSRS = _p_mapNode->getMapSRS()->getGeographicSRS();

        osgEarth::Style style;
        ModelSymbol* modelSymbol = style.getOrCreate<ModelSymbol>();
        osg::Node* node = osgDB::readNodeFile("red_flag.osg");
        //osg::Node* node = osgDB::readNodeFile("arrow.osg");

        osgEarth::Registry::shaderGenerator().run(node, "pipo");

        modelSymbol->setModel(node);

        osgEarth::AltitudeSymbol* alt = style.getOrCreate<osgEarth::AltitudeSymbol>();
        alt->clamping() = alt->CLAMP_TO_TERRAIN;
        alt->technique() = alt->TECHNIQUE_DRAPE;
        alt->binding() = alt->BINDING_VERTEX;

        osg::ref_ptr<osgEarth::PointSet> point = new osgEarth::PointSet(1);
        point->push_back(2.35, 48.85);

        osg::ref_ptr<Feature> feature = new Feature(point, geoSRS, style);
        features.push_back( feature );

        listCursor = new FeatureListCursor(features);
    }
    return listCursor;
}

osgEarth::Geometry::Type TestFeatureSource::getGeometryType() const
{
    return osgEarth::Geometry::TYPE_POINTSET;
}

class WindArrowFeatureLayer : public osgEarth::TiledFeatureModelLayer
{
public:
    WindArrowFeatureLayer(osgEarth::TiledFeatureModelLayer::Options* optr, const osgEarth::TiledFeatureModelLayer::Options* optr0);
};

WindArrowFeatureLayer::WindArrowFeatureLayer(Options* optr, const Options* optr0) :
    TiledFeatureModelLayer(optr, optr0)
{
    TiledFeatureModelLayer::init();

    setStyleSheet(new StyleSheet);
}

//------------------------------------------------------------------

int
usage(char** argv)
{
    OE_WARN << "Usage: " << argv[0] << " <earthfile>" << std::endl;
    return -1;
}

//------------------------------------------------------------------

int
main(int argc, char** argv)
{
    osgEarth::initialize();

    osg::Group* root = new osg::Group();

    // try to load an earth file.
    osg::ArgumentParser arguments(&argc, argv);

    osgViewer::Viewer viewer(arguments);
    osg::ref_ptr<EarthManipulator> manipulator = new EarthManipulator();
    viewer.setCameraManipulator(manipulator);
    viewer.setUpViewOnSingleScreen(1);

    // load an earth file and parse demo arguments
    auto node = MapNodeHelper().load(arguments, &viewer);
    if (!node)
        return usage(argv);

    root->addChild(node);

    // find the map node that we loaded.
    MapNode* mapNode = MapNode::get(node);
    if (!mapNode)
        return usage(argv);

    osgEarth::FeatureSource::Options options;
    osg::ref_ptr<TestFeatureSource> source = new TestFeatureSource(mapNode, options);

    osgEarth::TiledFeatureModelLayer::Options layerOpt;
    osg::ref_ptr<WindArrowFeatureLayer> modelLayer = new WindArrowFeatureLayer(new TiledFeatureModelLayer::Options(layerOpt), nullptr);
    modelLayer->setFeatureSource(source);
    modelLayer->setVisible(true);
    modelLayer->setOpacity(1.0);

    /* -- Add to scene -- */
    mapNode->getMap()->addLayer(modelLayer);

    // initialize the viewer:
    viewer.setSceneData(root);

    osgEarth::Viewpoint viewpoint("position",
        2.35,
        48.85,
        0,
        0.0,     // heading_deg
        -90.0,   // pitch_deg
        2000); // range

    manipulator->setViewpoint(viewpoint, 2);

    return viewer.run();
}

It displays a single white point, which look at the middle of the earth (visible in wired mode). image

I'm not sur wether if I'm missing something or if this is an osgearth issue. I don't know if I'm using osgEarth::FeatureSource API correctly or not... Thank you in advance for you help !

Best regards

sebalaig avatar Nov 06 '23 14:11 sebalaig

Hello, Could you reproduce the issue I describe from the code sample ?

Thank you in advance for your help/feedback. Best regards.

sebalaig avatar Nov 30 '23 11:11 sebalaig

I've pushed a fix for this to the master, it was an issue with an internal cache attempting to use the URI (which doesn't exist) as a key. Thanks for the example code, it was helpful to track the issue down.

jasonbeverage avatar Dec 08 '23 20:12 jasonbeverage

Hi @jasonbeverage, You're welcome, thanks for the fix ! However, I updated to get your fix, but I have the same behaviour with my example. Furthermore, if I set a breakpoint in the code you updated (i.e SubstituteModelFilter::process) it is never reached. Am I doing something wrong ? Thank you in advance for your help.

sebalaig avatar Dec 14 '23 23:12 sebalaig

Hi to both of you @jasonbeverage & @gwaldron, Do you have any idea of when this issue would be fixed if so ? Thank you in advance for your reply.

Best regards.

sebalaig avatar Feb 27 '24 16:02 sebalaig