28 #pragma warning(disable: 4127) // do not warn about constant conditional expression
30 #include <osg/Version>
31 #include <osgViewer/ViewerEventHandlers>
32 #include <osgGA/TrackballManipulator>
33 #include <osgDB/ReadFile>
34 #include <osgDB/WriteFile>
35 #include <osg/ShapeDrawable>
39 #include <osg/Geometry>
40 #include <osg/Sequence>
41 #include <osg/Texture2D>
42 #include <osgViewer/Viewer>
43 #include <osgUtil/Tessellator>
44 #include <osg/PositionAttitudeTransform>
45 #include <osg/ShadeModel>
47 #include <osg/LightSource>
48 #include <osg/ComputeBoundsVisitor>
77 std::map<std::string, osg::ref_ptr<osg::Node> > GUIOSGBuilder::myCars;
84 GUIOSGBuilder::buildOSGScene(osg::Node*
const tlg, osg::Node*
const tly, osg::Node*
const tlr, osg::Node*
const tlu) {
85 osgUtil::Tessellator tesselator;
86 osg::Group* root =
new osg::Group();
90 if (!e->isInternal()) {
91 buildOSGEdgeGeometry(*e, *root, tesselator);
101 for (std::vector<std::string>::const_iterator i = tlids.begin(); i != tlids.end(); ++i) {
104 const MSLane* lastLane = 0;
106 for (MSTrafficLightLogic::LaneVectorVector::const_iterator j = lanes.begin(); j != lanes.end(); ++j, ++idx) {
107 if ((*j).size() == 0) {
110 const MSLane*
const lane = (*j)[0];
114 if (lane == lastLane) {
118 d.
centerX = pos.
x() - 1.5 * sin(angle);
119 d.
centerY = pos.
y() - 1.5 * cos(angle);
121 osg::Switch* switchNode =
new osg::Switch();
122 switchNode->addChild(getTrafficLight(d, tlg, osg::Vec4d(0.1, 0.5, 0.1, 1.0), .25),
false);
123 switchNode->addChild(getTrafficLight(d, tly, osg::Vec4d(0.5, 0.5, 0.1, 1.0), .25),
false);
124 switchNode->addChild(getTrafficLight(d, tlr, osg::Vec4d(0.5, 0.1, 0.1, 1.0), .25),
false);
125 switchNode->addChild(getTrafficLight(d, tlu, osg::Vec4d(0.8, 0.4, 0.0, 1.0), .25),
false);
126 root->addChild(switchNode);
139 osg::Light* light =
new osg::Light(d.
filename[5] -
'0');
141 light->setPosition(osg::Vec4(0.0, 0.0, 0.0, 1.0));
142 light->setDiffuse(osg::Vec4(1.0, 1.0, 1.0, 1.0));
143 light->setSpecular(osg::Vec4(1.0, 1.0, 1.0, 1.0));
144 light->setAmbient(osg::Vec4(1.0, 1.0, 1.0, 1.0));
146 osg::LightSource* lightSource =
new osg::LightSource();
147 lightSource->setLight(light);
148 lightSource->setLocalStateSetModes(osg::StateAttribute::ON);
149 lightSource->setStateSetModes(*addTo.getOrCreateStateSet(), osg::StateAttribute::ON);
151 osg::PositionAttitudeTransform* lightTransform =
new osg::PositionAttitudeTransform();
152 lightTransform->addChild(lightSource);
154 lightTransform->setScale(osg::Vec3d(0.1, 0.1, 0.1));
155 addTo.addChild(lightTransform);
160 GUIOSGBuilder::buildOSGEdgeGeometry(
const MSEdge& edge,
162 osgUtil::Tessellator& tessellator) {
163 const std::vector<MSLane*>& lanes = edge.
getLanes();
164 for (std::vector<MSLane*>::const_iterator j = lanes.begin(); j != lanes.end(); ++j) {
167 osg::Geode* geode =
new osg::Geode();
168 osg::Geometry* geom =
new osg::Geometry();
169 geode->addDrawable(geom);
170 addTo.addChild(geode);
171 const int shapeSize = (int)(edge.
isWalkingArea() ? shape.size() : shape.size() * 2);
173 osg::Vec3Array* osg_coords =
new osg::Vec3Array(shapeSize);
174 geom->setVertexArray(osg_coords);
177 for (
int k = 0; k < (int)shape.size(); ++k, ++index) {
178 (*osg_coords)[index].set((
float)shape[k].x(), (float)shape[k].y(), (float)shape[k].z() + zOffset);
184 for (
int k = 0; k < (int)rshape.size(); ++k, ++index) {
185 (*osg_coords)[index].set((
float)rshape[k].x(), (float)rshape[k].y(), (float)rshape[k].z() + zOffset);
189 for (
int k = (
int) lshape.size() - 1; k >= 0; --k, ++index) {
190 (*osg_coords)[index].set((
float)lshape[k].x(), (float)lshape[k].y(), (float)lshape[k].z() + zOffset);
193 osg::Vec3Array* osg_normals =
new osg::Vec3Array(1);
194 (*osg_normals)[0] = osg::Vec3(0, 0, 1);
195 #if OSG_MIN_VERSION_REQUIRED(3,2,0)
196 geom->setNormalArray(osg_normals, osg::Array::BIND_PER_PRIMITIVE_SET);
198 geom->setNormalArray(osg_normals);
199 geom->setNormalBinding(osg::Geometry::BIND_PER_PRIMITIVE);
201 osg::Vec4ubArray* osg_colors =
new osg::Vec4ubArray(1);
202 (*osg_colors)[0].set(128, 128, 128, 255);
203 #if OSG_MIN_VERSION_REQUIRED(3,2,0)
204 geom->setColorArray(osg_colors, osg::Array::BIND_OVERALL);
206 geom->setColorArray(osg_colors);
207 geom->setColorBinding(osg::Geometry::BIND_OVERALL);
209 geom->addPrimitiveSet(
new osg::DrawArrays(osg::PrimitiveSet::POLYGON, 0, shapeSize));
211 osg::ref_ptr<osg::StateSet> ss = geode->getOrCreateStateSet();
212 ss->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
213 ss->setMode(GL_BLEND, osg::StateAttribute::OVERRIDE | osg::StateAttribute::PROTECTED | osg::StateAttribute::ON);
215 if (shape.size() > 2) {
216 tessellator.retessellatePolygons(*geom);
218 std::cout <<
"l=" << l->
getID() <<
" origPoints=" << shape.size() <<
" geomSize=" << geom->getVertexArray()->getNumElements() <<
" points=";
219 for (
int i = 0; i < (int)geom->getVertexArray()->getNumElements(); i++) {
220 const osg::Vec3& p = (*((osg::Vec3Array*)geom->getVertexArray()))[i];
221 std::cout << p.x() <<
"," << p.y() <<
"," << p.z() <<
" ";
226 static_cast<GUILane*
>(l)->setGeometry(geom);
234 osgUtil::Tessellator& tessellator) {
236 osg::Geode* geode =
new osg::Geode();
237 osg::Geometry* geom =
new osg::Geometry();
238 geode->addDrawable(geom);
239 addTo.addChild(geode);
240 osg::Vec3Array* osg_coords =
new osg::Vec3Array((
int)shape.size());
241 geom->setVertexArray(osg_coords);
242 for (
int k = 0; k < (int)shape.size(); ++k) {
243 (*osg_coords)[k].set((
float)shape[k].x(), (float)shape[k].y(), (float)shape[k].z());
245 osg::Vec3Array* osg_normals =
new osg::Vec3Array(1);
246 (*osg_normals)[0] = osg::Vec3(0, 0, 1);
247 #if OSG_MIN_VERSION_REQUIRED(3,2,0)
248 geom->setNormalArray(osg_normals, osg::Array::BIND_PER_PRIMITIVE_SET);
250 geom->setNormalArray(osg_normals);
251 geom->setNormalBinding(osg::Geometry::BIND_PER_PRIMITIVE);
253 osg::Vec4ubArray* osg_colors =
new osg::Vec4ubArray(1);
254 (*osg_colors)[0].set(128, 128, 128, 255);
255 #if OSG_MIN_VERSION_REQUIRED(3,2,0)
256 geom->setColorArray(osg_colors, osg::Array::BIND_OVERALL);
258 geom->setColorArray(osg_colors);
259 geom->setColorBinding(osg::Geometry::BIND_OVERALL);
261 geom->addPrimitiveSet(
new osg::DrawArrays(osg::PrimitiveSet::POLYGON, 0, (
int)shape.size()));
263 osg::ref_ptr<osg::StateSet> ss = geode->getOrCreateStateSet();
264 ss->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
265 ss->setMode(GL_BLEND, osg::StateAttribute::OVERRIDE | osg::StateAttribute::PROTECTED | osg::StateAttribute::ON);
267 if (shape.size() > 4) {
268 tessellator.retessellatePolygons(*geom);
270 junction.setGeometry(geom);
276 osg::Node* pLoadedModel = osgDB::readNodeFile(d.
filename);
277 if (pLoadedModel ==
nullptr) {
281 osg::ShadeModel* sm =
new osg::ShadeModel();
282 sm->setMode(osg::ShadeModel::FLAT);
283 pLoadedModel->getOrCreateStateSet()->setAttribute(sm);
284 osg::PositionAttitudeTransform* base =
new osg::PositionAttitudeTransform();
285 base->addChild(pLoadedModel);
286 osg::ComputeBoundsVisitor bboxCalc;
287 pLoadedModel->accept(bboxCalc);
288 const osg::BoundingBox& bbox = bboxCalc.getBoundingBox();
290 double xScale = d.
width > 0 ? d.
width / (bbox.xMax() - bbox.xMin()) : 1.;
291 double yScale = d.
height > 0 ? d.
height / (bbox.yMax() - bbox.yMin()) : 1.;
292 const double zScale = d.
altitude > 0 ? d.
altitude / (bbox.zMax() - bbox.zMin()) : 1.;
294 xScale = yScale = zScale;
296 base->setScale(osg::Vec3d(xScale, yScale, zScale));
298 base->setAttitude(osg::Quat(osg::DegreesToRadians(d.
roll), osg::Vec3d(1, 0, 0),
299 osg::DegreesToRadians(d.
tilt), osg::Vec3d(0, 1, 0),
300 osg::DegreesToRadians(d.
rot), osg::Vec3d(0, 0, 1)));
301 addTo.addChild(base);
305 osg::PositionAttitudeTransform*
306 GUIOSGBuilder::getTrafficLight(
const GUISUMOAbstractView::Decal& d, osg::Node* tl,
const osg::Vec4& color,
const double size) {
307 osg::PositionAttitudeTransform* ret =
new osg::PositionAttitudeTransform();
309 osg::PositionAttitudeTransform* base =
new osg::PositionAttitudeTransform();
311 osg::ComputeBoundsVisitor bboxCalc;
312 tl->accept(bboxCalc);
313 const osg::BoundingBox& bbox = bboxCalc.getBoundingBox();
314 double xScale = d.
width > 0 ? d.
width / (bbox.xMax() - bbox.xMin()) : 1.;
315 double yScale = d.
height > 0 ? d.
height / (bbox.yMax() - bbox.yMin()) : 1.;
316 const double zScale = d.
altitude > 0 ? d.
altitude / (bbox.zMax() - bbox.zMin()) : 1.;
318 xScale = yScale = zScale;
320 base->setScale(osg::Vec3d(xScale, yScale, zScale));
322 base->setAttitude(osg::Quat(osg::DegreesToRadians(d.
roll), osg::Vec3(1, 0, 0),
323 osg::DegreesToRadians(d.
tilt), osg::Vec3(0, 1, 0),
324 osg::DegreesToRadians(d.
rot), osg::Vec3(0, 0, 1)));
327 osg::Geode* geode =
new osg::Geode();
329 osg::ShapeDrawable* shape =
new osg::ShapeDrawable(
new osg::Sphere(center, (
float)size));
330 geode->addDrawable(shape);
331 osg::ref_ptr<osg::StateSet> ss = shape->getOrCreateStateSet();
332 ss->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
333 ss->setMode(GL_BLEND, osg::StateAttribute::OVERRIDE | osg::StateAttribute::PROTECTED | osg::StateAttribute::ON);
334 osg::PositionAttitudeTransform* ellipse =
new osg::PositionAttitudeTransform();
335 ellipse->addChild(geode);
336 ellipse->setPivotPoint(center);
337 ellipse->setPosition(center);
338 ellipse->setScale(osg::Vec3d(4., 4., 2.5 * d.
altitude + 1.1));
339 shape->setColor(color);
340 ret->addChild(ellipse);
346 GUIOSGBuilder::setShapeState(osg::ref_ptr<osg::ShapeDrawable> shape) {
347 osg::ref_ptr<osg::StateSet> ss = shape->getOrCreateStateSet();
348 ss->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
349 ss->setMode(GL_BLEND, osg::StateAttribute::OVERRIDE | osg::StateAttribute::PROTECTED | osg::StateAttribute::ON);
353 GUIOSGView::OSGMovable
355 GUIOSGView::OSGMovable m;
356 m.pos =
new osg::PositionAttitudeTransform();
358 const std::string& osgFile = type.
getOSGFile();
359 if (myCars.find(osgFile) == myCars.end()) {
360 myCars[osgFile] = osgDB::readNodeFile(osgFile);
361 if (myCars[osgFile] == 0) {
365 osg::Node* carNode = myCars[osgFile];
366 if (carNode !=
nullptr) {
367 osg::ComputeBoundsVisitor bboxCalc;
368 carNode->accept(bboxCalc);
369 const osg::BoundingBox& bbox = bboxCalc.getBoundingBox();
370 osg::PositionAttitudeTransform* base =
new osg::PositionAttitudeTransform();
371 base->addChild(carNode);
372 base->setPivotPoint(osg::Vec3d((bbox.xMin() + bbox.xMax()) / 2., bbox.yMin(), bbox.zMin()));
373 base->setScale(osg::Vec3d(type.
getWidth() / (bbox.xMax() - bbox.xMin()),
374 type.
getLength() / (bbox.yMax() - bbox.yMin()),
375 type.
getHeight() / (bbox.zMax() - bbox.zMin())));
376 m.pos->addChild(base);
379 m.lights =
new osg::Switch();
380 for (
double offset = -0.3; offset < 0.5; offset += 0.6) {
381 osg::Geode* geode =
new osg::Geode();
382 osg::ShapeDrawable* right =
new osg::ShapeDrawable(
new osg::Sphere(osg::Vec3d(offset, (type.
getLength() - .9) / 2., (type.
getHeight() - .5) / 2.), .1f));
383 geode->addDrawable(right);
384 setShapeState(right);
385 right->setColor(osg::Vec4(1.f, .5f, 0.f, .8f));
386 osg::Sequence* seq =
new osg::Sequence();
388 seq->addChild(geode, .33);
389 seq->addChild(
new osg::Geode(), .33);
391 seq->setInterval(osg::Sequence::LOOP, 0, -1);
393 seq->setDuration(1.0f, -1);
395 seq->setMode(osg::Sequence::START);
396 m.lights->addChild(seq);
399 osg::Geode* geode =
new osg::Geode();
400 osg::CompositeShape* comp =
new osg::CompositeShape();
401 comp->addChild(
new osg::Sphere(osg::Vec3d(-0.3, (type.
getLength() + .8) / 2., (type.
getHeight() - .5) / 2.), .1f));
402 comp->addChild(
new osg::Sphere(osg::Vec3d(0.3, (type.
getLength() + .8) / 2., (type.
getHeight() - .5) / 2.), .1f));
403 osg::ShapeDrawable* brake =
new osg::ShapeDrawable(comp);
404 brake->setColor(osg::Vec4(1.f, 0.f, 0.f, .8f));
405 geode->addDrawable(brake);
406 setShapeState(brake);
407 m.lights->addChild(geode);
409 geode =
new osg::Geode();
411 m.geom =
new osg::ShapeDrawable(
new osg::Sphere(center, .5f));
412 geode->addDrawable(m.geom);
413 setShapeState(m.geom);
414 osg::PositionAttitudeTransform* ellipse =
new osg::PositionAttitudeTransform();
415 ellipse->addChild(geode);
416 ellipse->addChild(m.lights);
417 ellipse->setPivotPoint(center);
418 ellipse->setPosition(center);
420 m.pos->addChild(ellipse);