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 [email protected].
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
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org

Reply via email to