+struct GlyphGeometry
+{
+ osg::DrawArrays* quads;
+ osg::Vec2Array* uvs;
+ osg::Vec3Array* vertices;
+ osg::Vec3Array* normals;
+
+ void addGlyph(SGMaterialGlyph* glyph, double x, double y, double width, double height, const osg::Matrix& xform)
+ {
+
+ vertices->push_back(xform.preMult(osg::Vec3(thick, x, y)));
+ vertices->push_back(xform.preMult(osg::Vec3(thick, x + width, y)));
+ vertices->push_back(xform.preMult(osg::Vec3(thick, x + width, y + height)));
+ vertices->push_back(xform.preMult(osg::Vec3(thick, x, y + height)));
+
+ // texture coordinates
+ double xoffset = glyph->get_left();
+ double texWidth = glyph->get_width();
+
+ uvs->push_back(osg::Vec2(xoffset, 0));
+ uvs->push_back(osg::Vec2(xoffset + texWidth, 0));
+ uvs->push_back(osg::Vec2(xoffset + texWidth, 1));
+ uvs->push_back(osg::Vec2(xoffset, 1));
+
+ // normals
+ for (int i=0; i<4; ++i)
+ normals->push_back(xform.preMult(osg::Vec3(0, -1, 0)));
+
+ quads->setCount(vertices->size());
+ }
+
+ void addSignCase(double caseWidth, double caseHeight, const osg::Matrix& xform)
+ {
+ vertices->push_back(osg::Vec3(-thick, -caseWidth, grounddist));
+ vertices->push_back(osg::Vec3(thick, -caseWidth, grounddist));
+ vertices->push_back(osg::Vec3(thick, -caseWidth, grounddist + caseHeight));
+ vertices->push_back(osg::Vec3(-thick, -caseWidth, grounddist + caseHeight));
+
+
+ for (int i=0; i<4; ++i)
+ normals->push_back(xform.preMult(osg::Vec3(-1, 0.0, 0)));
+
+ vertices->push_back(osg::Vec3(-thick, -caseWidth, grounddist + caseHeight));
+ vertices->push_back(osg::Vec3(thick, -caseWidth, grounddist + caseHeight));
+ vertices->push_back(osg::Vec3(thick, caseWidth, grounddist + caseHeight));
+ vertices->push_back(osg::Vec3(-thick, caseWidth, grounddist + caseHeight));
+
+ for (int i=0; i<4; ++i)
+ normals->push_back(xform.preMult(osg::Vec3(0, 0, 1)));
+
+ vertices->push_back(osg::Vec3(-thick, caseWidth, grounddist + caseHeight));
+ vertices->push_back(osg::Vec3(thick, caseWidth, grounddist + caseHeight));
+ vertices->push_back(osg::Vec3(thick, caseWidth, grounddist));
+ vertices->push_back(osg::Vec3(-thick, caseWidth, grounddist));
+
+ for (int i=0; i<4; ++i)
+ normals->push_back(xform.preMult(osg::Vec3(1, 0.0, 0)));
+
+ for (int i = 0; i < 3; ++i) {
+ uvs->push_back(osg::Vec2(1, 1));
+ uvs->push_back(osg::Vec2(0.75, 1));
+ uvs->push_back(osg::Vec2(0.75, 0));
+ uvs->push_back(osg::Vec2(1, 0));
+ }
+
+ quads->setCount(vertices->size());
+ }
+};
+
+typedef std::map<Effect*, GlyphGeometry*> EffectGeometryMap;
+
+void SGMakeSignFace(EffectGeometryMap& glyphs, const ElementVec& elements, double hpos, const osg::Matrix& xform)
+{
+ BOOST_FOREACH(element_info* element, elements) {
+ GlyphGeometry* gg = glyphs[element->state];
+ gg->addGlyph(element->glyph, hpos, grounddist, element->abswidth, element->height, xform);
+ hpos += element->abswidth;
+ delete element;
+ }
+}
+
+GlyphGeometry* makeGeometry(Effect* eff, osg::Group* group)
+{
+ GlyphGeometry* gg = new GlyphGeometry;
+
+ EffectGeode* geode = new EffectGeode;
+ geode->setEffect(eff);
+
+ gg->vertices = new osg::Vec3Array;
+ gg->normals = new osg::Vec3Array;
+ gg->uvs = new osg::Vec2Array;
+
+ osg::Vec4Array* cl = new osg::Vec4Array;
+ cl->push_back(osg::Vec4(1, 1, 1, 1));
+
+ osg::Geometry* geometry = new osg::Geometry;
+ geometry->setVertexArray(gg->vertices);
+ geometry->setNormalArray(gg->normals);
+ geometry->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);
+ geometry->setColorArray(cl);
+ geometry->setColorBinding(osg::Geometry::BIND_OVERALL);
+ geometry->setTexCoordArray(0, gg->uvs);
+
+ gg->quads = new osg::DrawArrays(GL_QUADS, 0, gg->vertices->size());
+ geometry->addPrimitiveSet(gg->quads);
+ geode->addDrawable(geometry);
+ group->addChild(geode);
+ return gg;
+}