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