Hi Community,

I am struggling with the Tessellator to make it work. I tried to consult
the OpenGL spec for the winding types and I tried all of them without
success :/. It is simple case where I have polygon with two wholes. The
contour generation seams to be ok, like in the attached picture, just the
tesselation is make it wrong, or I am using the Tessellator wrong. I am
attaching the source too - it requires boost 69 or later - used for the
union of the triangles.

Any hint is highly appreciated as always!
And thanks a bunch!

-- 
trajce nikolov nick

-- 
You received this message because you are subscribed to the Google Groups 
"OpenSceneGraph Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to osg-users+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/osg-users/CAO-%2Bzi%3DbFEYKMhyLVO%2BkqKhMLZa8Yg33ohiW02p0MQf8Kqt3iw%40mail.gmail.com.
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2010 Robert Osfield
 *
 * This application is open source and may be redistributed and/or modified
 * freely and without restriction, both in commercial and non commercial 
applications,
 * as long as this copyright notice is maintained.
 *
 * This application is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/

#include <osgDB/ReadFile>
#include <osgDB/WriteFile>
#include <osgUtil/Optimizer>
#include <osg/CoordinateSystemNode>
#include <osg/CullFace>
#include <osg/LineWidth>

#include <osgUtil/DelaunayTriangulator>
#include <osg/Switch>
#include <osg/Types>
#include <osgText/Text>

#include <osgViewer/Viewer>
#include <osgViewer/ViewerEventHandlers>

#include <osgGA/TrackballManipulator>
#include <osgGA/FlightManipulator>
#include <osgGA/DriveManipulator>
#include <osgGA/KeySwitchMatrixManipulator>
#include <osgGA/StateSetManipulator>
#include <osgGA/AnimationPathManipulator>
#include <osgGA/TerrainManipulator>
#include <osgGA/SphericalManipulator>
#include <osgUtil/Tessellator>
#include <deque>
#include <osg/io_utils>

#if 1
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
#include <boost/geometry/geometries/polygon.hpp>

#include <boost/foreach.hpp>

typedef boost::geometry::model::d2::point_xy<double> point;
typedef boost::geometry::model::polygon<point> polygon;
#endif

#include <osgGA/Device>

#include <iostream>



void createPerfectConstraint(osg::Geometry* dc)
{
        typedef boost::geometry::model::multi_polygon<polygon> mpolygon;
        mpolygon mp;
        polygon p;

        std::vector< polygon > polygons;

        osg::ref_ptr<osg::Vec3Array> vertices = 
dynamic_cast<osg::Vec3Array*>(dc->getVertexArray());

        for (size_t i = 0; i < dc->getNumPrimitiveSets(); ++i)
        {
                osg::ref_ptr<osg::DrawArrays> da = 
dynamic_cast<osg::DrawArrays*>(dc->getPrimitiveSet(i));
                if (!da.valid()) continue;

                size_t start = da->getFirst();
                size_t count = da->getCount();

                size_t cnt = 0;
                while (cnt < count)
                {
                        p.clear();

                        const osg::Vec3& v1 = vertices->at(start + cnt++);
                        const osg::Vec3& v3 = vertices->at(start + cnt++);
                        const osg::Vec3& v2 = vertices->at(start + cnt++);

                        boost::geometry::append(p, point(v1.x(), v1.y()));
                        boost::geometry::append(p, point(v2.x(), v2.y()));
                        boost::geometry::append(p, point(v3.x(), v3.y()));
                        boost::geometry::append(p, point(v1.x(), v1.y()));

                        std::string reason;
                        if (!boost::geometry::is_valid(p, reason))
                        {
                                std::cout << "Correcting data: " << reason << 
"\n";
                                boost::geometry::correct(p);

                                std::cout << v1 << v2 << v3 << std::endl;
                        }

                        polygons.push_back(p);
                }
        }
        mpolygon border;   // the unioned polygons

        for (polygon p : polygons)
        {
                // add another polygon each iteration
                mpolygon tmp_poly;
                boost::geometry::union_(border, p, tmp_poly);
                border = tmp_poly;
        }

        mp = border;

        if (mp.size() < 1) return;
        
        p = mp.at(mp.size() - 1);

        std::string reason;
        if (!boost::geometry::is_valid(p, reason))
        {
                std::cout << "Correcting data: " << reason << "\n";
                boost::geometry::correct(p);
        }

        std::vector< osg::ref_ptr<osg::Vec3Array> > contours;

        osg::Vec3Array* out = new osg::Vec3Array;
        contours.push_back(out);

        for (int i = 0; i < p.outer().size(); ++i) 
        {
                double x = boost::geometry::get<0>(p.outer()[i]);
                double y = boost::geometry::get<1>(p.outer()[i]);
                std::cout << " " << x;
                std::cout << " " << y;

                out->push_back(osg::Vec3(x, y, 0));
        }

#if 1
        dc->removePrimitiveSet(0, dc->getNumPrimitiveSets());
        dc->setVertexArray(out);
        dc->addPrimitiveSet(new osg::DrawArrays(GL_LINE_LOOP, 0, out->size()));
#endif
        for (unsigned i = 0; i < p.inners().size(); ++i)
        {
                const boost::geometry::model::ring<point>& inner = 
p.inners()[i];

                size_t start = out->size();
                osg::Vec3Array* contour = new osg::Vec3Array;
                for (int j = 0; j < inner.size(); ++j)
                {
                        double x = boost::geometry::get<0>(inner[j]);
                        double y = boost::geometry::get<1>(inner[j]);
                        std::cout << " " << x;
                        std::cout << " " << y;

                        out->push_back(osg::Vec3(x, y, 0));
                        contour->push_back(osg::Vec3(x, y, 0));
                }
                contours.push_back(contour);
                dc->addPrimitiveSet(new osg::DrawArrays(GL_LINE_LOOP, start, 
out->size()-start));
        }
        return;

        osgUtil::Tessellator t;
#if 1
        
        
        t.beginTessellation();
        
        for (size_t i = 0; i < contours.size(); ++i)
        {
                t.beginContour();
                osg::Vec3Array* vxs = contours.at(i);
                
                for (size_t j = 0; j < vxs->size(); ++j)
                {
                        osg::Vec3* v = &vxs->at(j);
                        t.addVertex(v);
                }
                t.endContour();
        }
        
        t.endTessellation();
#else
        t.retessellatePolygons(*dc);
#endif

#if 1
        dc->removePrimitiveSet(0, dc->getNumPrimitiveSets());

        osg::ref_ptr<osg::Vec3Array> resultVertices = new osg::Vec3Array;
        dc->setVertexArray(resultVertices);

        osgUtil::Tessellator::PrimList& primitives = t.getPrimList();
        for (size_t i = 0; i < primitives.size(); ++i)
        {
                osg::ref_ptr<osgUtil::Tessellator::Prim>& primitive = 
primitives.at(i);

                size_t start = resultVertices->size();
                for (size_t k = 0; k < primitive->_vertices.size(); ++k)
                {
                        osg::Vec3* v = primitive->_vertices.at(k);
                        resultVertices->push_back(*v);
                }

                dc->addPrimitiveSet(new osg::DrawArrays(primitive->_mode, 
start, resultVertices->size() - start));
        }
#endif

#if 0
        osg::ref_ptr<osg::Geode> tempGeode = new osg::Geode;
        tempGeode->addDrawable(dc);

        UnrollGeometryVisitor nv;
        tempGeode->accept(nv);
        nv.finalize();

        osg::ref_ptr<osg::Vec3Array> finalVertices = 
dynamic_cast<osg::Vec3Array*>(nv.geometryAsTriangles->getVertexArray());
        dc->setVertexArray(finalVertices);
        
        dc->removePrimitiveSet(0, dc->getNumPrimitiveSets());

        size_t cnt = 0;
        while (cnt < finalVertices->size())
        {
                polygon p;

                const osg::Vec3& v1 = finalVertices->at(cnt++);
                const osg::Vec3& v2 = finalVertices->at(cnt++);
                const osg::Vec3& v3 = finalVertices->at(cnt++);

                dc->addPrimitiveSet(new osg::DrawArrays(GL_LINE_LOOP,cnt-3, 3));
        }
#endif
}
        

osg::Node* createScene()
{
        osg::ref_ptr<osg::Geode> geode = new osg::Geode;

        osg::ref_ptr<osg::Vec3Array> points = new osg::Vec3Array;

        
        osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry;
        geometry->setVertexArray(points);
        geode->addDrawable(geometry);

        size_t start = 0;
        points->push_back(osg::Vec3(3, -10, 0));
        points->push_back(osg::Vec3(10, -10, 0));
        points->push_back(osg::Vec3(10, 30, 0));
        points->push_back(osg::Vec3(10, 30, 0));
        points->push_back(osg::Vec3(3, 30, 0));
        points->push_back(osg::Vec3(3, -10, 0));

        //geometry->addPrimitiveSet(new osg::DrawArrays(GL_TRIANGLES, start, 
points->size()-start));

        start = points->size();
        points->push_back(osg::Vec3(-10, -10, 0));
        points->push_back(osg::Vec3(-3, -10, 0));
        points->push_back(osg::Vec3(-3, 30, 0));
        points->push_back(osg::Vec3(-3, 30, 0));
        points->push_back(osg::Vec3(-10,30, 0));
        points->push_back(osg::Vec3(-10, -10, 0));

        //geometry->addPrimitiveSet(new osg::DrawArrays(GL_TRIANGLES, start, 
points->size()-start));

        start = points->size();
        points->push_back(osg::Vec3(-15, 25, 0));
        points->push_back(osg::Vec3(15, 25, 0));
        points->push_back(osg::Vec3(15, 45, 0));
        points->push_back(osg::Vec3(15, 45, 0));
        points->push_back(osg::Vec3(-15, 45, 0));
        points->push_back(osg::Vec3(-15, 25, 0));

        points->push_back(osg::Vec3(-15, -5, 0));
        points->push_back(osg::Vec3(15, -5, 0));
        points->push_back(osg::Vec3(15, 15, 0));
        points->push_back(osg::Vec3(15, 15, 0));
        points->push_back(osg::Vec3(-15, 15, 0));
        points->push_back(osg::Vec3(-15, -5, 0));

        //geometry->addPrimitiveSet(new osg::DrawArrays(GL_TRIANGLES, start, 
points->size() - start));

        start = points->size();
        points->push_back(osg::Vec3(-15, -7, 0));
        points->push_back(osg::Vec3(15, -7, 0));
        points->push_back(osg::Vec3(15, -15, 0));
        points->push_back(osg::Vec3(15, -15, 0));
        points->push_back(osg::Vec3(-15, -15, 0));
        points->push_back(osg::Vec3(-15, -7, 0));

        geometry->addPrimitiveSet(new osg::DrawArrays(GL_TRIANGLES, 0, 
points->size()));

        createPerfectConstraint(geometry);

        return geode.release();
}

int main(int argc, char** argv)
{
    // use an ArgumentParser object to manage the program arguments.
    osg::ArgumentParser arguments(&argc,argv);

    
arguments.getApplicationUsage()->setApplicationName(arguments.getApplicationName());
    
arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+"
 is the standard OpenSceneGraph example which loads and visualises 3d models.");
    
arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+"
 [options] filename ...");
    arguments.getApplicationUsage()->addCommandLineOption("--image 
<filename>","Load an image and render it on a quad");
    arguments.getApplicationUsage()->addCommandLineOption("--dem 
<filename>","Load an image/DEM and render it on a HeightField");
    arguments.getApplicationUsage()->addCommandLineOption("--login <url> 
<username> <password>","Provide authentication information for http file 
access.");
    arguments.getApplicationUsage()->addCommandLineOption("-p <filename>","Play 
specified camera path animation file, previously saved with 'z' key.");
    arguments.getApplicationUsage()->addCommandLineOption("--speed 
<factor>","Speed factor for animation playing (1 == normal speed).");
    arguments.getApplicationUsage()->addCommandLineOption("--device 
<device-name>","add named device to the viewer");
    arguments.getApplicationUsage()->addCommandLineOption("--stats","print out 
load and compile timing stats");

    osgViewer::Viewer viewer(arguments);

    unsigned int helpType = 0;
    if ((helpType = arguments.readHelpType()))
    {
        arguments.getApplicationUsage()->write(std::cout, helpType);
        //return 1;
    }

    // report any errors if they have occurred when parsing the program 
arguments.
    if (arguments.errors())
    {
        arguments.writeErrorMessages(std::cout);
        //return 1;
    }

    if (arguments.argc()<=1)
    {
        
arguments.getApplicationUsage()->write(std::cout,osg::ApplicationUsage::COMMAND_LINE_OPTION);
        //return 1;
    }

    bool printStats = arguments.read("--stats");

    std::string url, username, password;
    while(arguments.read("--login",url, username, password))
    {
        
osgDB::Registry::instance()->getOrCreateAuthenticationMap()->addAuthenticationDetails(
            url,
            new osgDB::AuthenticationDetails(username, password)
        );
    }

    std::string device;
    while(arguments.read("--device", device))
    {
        osg::ref_ptr<osgGA::Device> dev = 
osgDB::readRefFile<osgGA::Device>(device);
        if (dev.valid())
        {
            viewer.addDevice(dev);
        }
    }

    // set up the camera manipulators.
    {
        osg::ref_ptr<osgGA::KeySwitchMatrixManipulator> keyswitchManipulator = 
new osgGA::KeySwitchMatrixManipulator;

        keyswitchManipulator->addMatrixManipulator( '1', "Trackball", new 
osgGA::TrackballManipulator() );
        keyswitchManipulator->addMatrixManipulator( '2', "Flight", new 
osgGA::FlightManipulator() );
        keyswitchManipulator->addMatrixManipulator( '3', "Drive", new 
osgGA::DriveManipulator() );
        keyswitchManipulator->addMatrixManipulator( '4', "Terrain", new 
osgGA::TerrainManipulator() );
        keyswitchManipulator->addMatrixManipulator( '5', "Orbit", new 
osgGA::OrbitManipulator() );
        keyswitchManipulator->addMatrixManipulator( '6', "FirstPerson", new 
osgGA::FirstPersonManipulator() );
        keyswitchManipulator->addMatrixManipulator( '7', "Spherical", new 
osgGA::SphericalManipulator() );

        std::string pathfile;
        double animationSpeed = 1.0;
        while(arguments.read("--speed",animationSpeed) ) {}
        char keyForAnimationPath = '8';
        while (arguments.read("-p",pathfile))
        {
            osgGA::AnimationPathManipulator* apm = new 
osgGA::AnimationPathManipulator(pathfile);
            if (apm && !apm->getAnimationPath()->empty())
            {
                apm->setTimeScale(animationSpeed);

                unsigned int num = 
keyswitchManipulator->getNumMatrixManipulators();
                keyswitchManipulator->addMatrixManipulator( 
keyForAnimationPath, "Path", apm );
                keyswitchManipulator->selectMatrixManipulator(num);
                ++keyForAnimationPath;
            }
        }

        viewer.setCameraManipulator( keyswitchManipulator.get() );
    }

    // add the state manipulator
    viewer.addEventHandler( new 
osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()) );

    // add the thread model handler
    viewer.addEventHandler(new osgViewer::ThreadingHandler);

    // add the window size toggle handler
    viewer.addEventHandler(new osgViewer::WindowSizeHandler);

    // add the stats handler
    viewer.addEventHandler(new osgViewer::StatsHandler);

    // add the help handler
    viewer.addEventHandler(new 
osgViewer::HelpHandler(arguments.getApplicationUsage()));

    // add the record camera path handler
    viewer.addEventHandler(new osgViewer::RecordCameraPathHandler);

    // add the LOD Scale handler
        osgViewer::LODScaleHandler* lsh;
    viewer.addEventHandler(lsh = new osgViewer::LODScaleHandler);

        lsh->setKeyEventIncreaseLODScale('+');
        lsh->setKeyEventDecreaseLODScale('-');


    // add the screen capture handler
    viewer.addEventHandler(new osgViewer::ScreenCaptureHandler);


    osg::ElapsedTime elapsedTime;

    // load the data
    osg::ref_ptr<osg::Node> loadedModel = osgDB::readRefNodeFiles(arguments);
    if (!loadedModel)
    {
        std::cout << arguments.getApplicationName() <<": No data loaded" << 
std::endl;
        //return 1;
    }

    if (printStats)
    {
        double loadTime = elapsedTime.elapsedTime_m();
        std::cout<<"Load time "<<loadTime<<"ms"<<std::endl;

        viewer.getStats()->collectStats("compile", true);
    }


    // any option left unread are converted into errors to write out later.
    arguments.reportRemainingOptionsAsUnrecognized();

    // report any errors if they have occurred when parsing the program 
arguments.
    if (arguments.errors())
    {
        //arguments.writeErrorMessages(std::cout);
        return 1;
    }


    // optimize the scene graph, remove redundant nodes and state etc.
    osgUtil::Optimizer optimizer;
    //optimizer.optimize(loadedModel);

        size_t numBlades = 2;

        osg::ref_ptr<osg::Group> scene = new osg::Group;
        scene->addChild(loadedModel);

#if 1
        scene->addChild(createScene());
#endif

        viewer.setSceneData(scene);

        scene->getOrCreateStateSet()->setAttributeAndModes(new 
osg::CullFace(osg::CullFace::FRONT_AND_BACK), osg::StateAttribute::OFF);

        std::cout << "Model radius: " << scene->getBound().radius() << 
std::endl;

    viewer.realize();

    return viewer.run();

}
_______________________________________________
osg-users mailing list
osg-users@lists.openscenegraph.org
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org

Reply via email to