gwaldron / osgearth

3D Maps for OpenSceneGraph / C++14
https://www.pelicanmapping.com/home-1/opensource
Other
1.48k stars 774 forks source link

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

Open sebalaig opened 1 year ago

sebalaig commented 1 year ago

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(); auto* tmp= osgDB::readFile("arrow.osg"); modelSymbol->setModel(tmp); modelSymbol->heading() = 50; modelSymbol->scale() = 2; modelSymbol->placement() = InstanceSymbol::PLACEMENT_VERTEX; modelSymbol->autoScale() = true; osg::ref_ptr point = new osgEarth::PointSet(1); point->push_back(2.35, 48.85, 50); osg::ref_ptr feature = new Feature(point, geoSRS, style); osg::ref_ptr 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 commented 1 year ago

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

sebalaig commented 1 year ago

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 commented 1 year ago

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

gwaldron commented 11 months ago

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?

sebalaig commented 10 months ago

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 commented 9 months ago

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

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

jasonbeverage commented 9 months ago

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.

sebalaig commented 9 months ago

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 commented 6 months ago

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.