root/OpenSceneGraph/trunk/examples/osgtext3D/osgtext3D.cpp @ 11681

Revision 11681, 21.3 kB (checked in by robert, 4 years ago)

Implemented boundary polygon creation based on the refined boundary segments

Line 
1/* OpenSceneGraph example, osgtext.
2*
3*  Permission is hereby granted, free of charge, to any person obtaining a copy
4*  of this software and associated documentation files (the "Software"), to deal
5*  in the Software without restriction, including without limitation the rights
6*  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7*  copies of the Software, and to permit persons to whom the Software is
8*  furnished to do so, subject to the following conditions:
9*
10*  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
11*  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
12*  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
13*  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
14*  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
15*  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
16*  THE SOFTWARE.
17*/
18
19#include <osg/ArgumentParser>
20#include <osg/Geode>
21#include <osg/Geometry>
22#include <osg/PositionAttitudeTransform>
23#include <osgText/Font3D>
24#include <osgDB/WriteFile>
25#include <osgGA/StateSetManipulator>
26#include <osgUtil/Tessellator>
27#include <osgViewer/Viewer>
28#include <osgViewer/ViewerEventHandlers>
29#include <osg/io_utils>
30
31extern int main_orig(int, char**);
32extern int main_test(int, char**);
33
34
35osg::Vec3 computeRayIntersectionPoint(const osg::Vec3& a, const osg::Vec3& an, const osg::Vec3& c, const osg::Vec3& cn)
36{
37    float denominator = ( cn.x() * an.y() - cn.y() * an.x());
38    if (denominator==0.0)
39    {
40        //OSG_NOTICE<<"computeRayIntersectionPoint()<<denominator==0.0"<<std::endl;
41        // line segments must be parallel.
42        return (a+c)*0.5;
43    }
44
45    float t = ((a.x()-c.x())*an.y() - (a.y()-c.y())*an.x()) / denominator;
46    return c + cn*t;
47}
48
49osg::Vec3 computeIntersectionPoint(const osg::Vec3& a, const osg::Vec3& b, const osg::Vec3& c, const osg::Vec3& d)
50{
51#if 0
52    float ba_x = b.x()-a.x();
53    float ba_y = b.y()-a.y();
54
55    float dc_x = d.x()-c.x();
56    float dc_y = d.y()-c.y();
57
58    float denominator = (dc_x * ba_y - dc_y * ba_x);
59    if (denominator==0.0)
60    {
61        // line segments must be parallel.
62        return (b+c)*0.5;
63    }
64
65    float t = ((a.x()-c.x())*ba_y + (a.y()-c.y())*ba_x) / denominator;
66
67    return c + (d-c)*t;
68#endif
69    return computeRayIntersectionPoint(a, b-a, c, d-c);
70
71}
72
73osg::Vec3 computeBisectorNormal(const osg::Vec3& a, const osg::Vec3& b, const osg::Vec3& c, const osg::Vec3& d)
74{
75    osg::Vec2 ab(a.x()-b.x(), a.y()-b.y());
76    osg::Vec2 dc(d.x()-c.x(), d.y()-c.y());
77    /*float length_ab =*/ ab.normalize();
78    /*float length_dc =*/ dc.normalize();
79
80    float e = dc.y() - ab.y();
81    float f = ab.x() - dc.x();
82    float denominator = sqrtf(e*e + f*f);
83    float nx = e / denominator;
84    float ny = f / denominator;
85    if (( ab.x()*ny - ab.y()*nx) > 0.0f)
86    {
87        // OSG_NOTICE<<"   computeBisectorNormal(a=["<<a<<"], b=["<<b<<"], c=["<<c<<"], d=["<<d<<"]), nx="<<nx<<", ny="<<ny<<", denominator="<<denominator<<" no need to swap"<<std::endl;
88        return osg::Vec3(nx,ny,0.0f);
89    }
90    else
91    {
92        OSG_NOTICE<<"   computeBisectorNormal(a=["<<a<<"], b=["<<b<<"], c=["<<c<<"], d=["<<d<<"]), nx="<<nx<<", ny="<<ny<<", denominator="<<denominator<<" need to swap!!!"<<std::endl;
93        return osg::Vec3(-nx,-ny,0.0f);
94    }
95}
96
97float computeBisectorIntersectorThickness(const osg::Vec3& a, const osg::Vec3& b, const osg::Vec3& c, const osg::Vec3& d, const osg::Vec3& e, const osg::Vec3& f)
98{
99    osg::Vec3 intersection_abcd = computeIntersectionPoint(a,b,c,d);
100    osg::Vec3 bisector_abcd = computeBisectorNormal(a,b,c,d);
101    osg::Vec3 intersection_cdef = computeIntersectionPoint(c,d,e,f);
102    osg::Vec3 bisector_cdef = computeBisectorNormal(c,d,e,f);
103    if (bisector_abcd==bisector_cdef)
104    {
105        //OSG_NOTICE<<"computeBisectorIntersector(["<<a<<"], ["<<b<<"], ["<<c<<"], ["<<d<<"], ["<<e<<"], ["<<f<<"[)"<<std::endl;
106        //OSG_NOTICE<<"   bisectors parallel, thickness = "<<FLT_MAX<<std::endl;
107        return FLT_MAX;
108    }
109
110    osg::Vec3 bisector_intersection = computeRayIntersectionPoint(intersection_abcd,bisector_abcd, intersection_cdef, bisector_cdef);
111    osg::Vec3 normal(d.y()-c.y(), c.x()-d.x(), 0.0);
112    float cd_length = normal.normalize();
113    if (cd_length==0)
114    {
115        //OSG_NOTICE<<"computeBisectorIntersector(["<<a<<"], ["<<b<<"], ["<<c<<"], ["<<d<<"], ["<<e<<"], ["<<f<<"[)"<<std::endl;
116        //OSG_NOTICE<<"   segment length==0, thickness = "<<FLT_MAX<<std::endl;
117        return FLT_MAX;
118    }
119
120    float thickness = (bisector_intersection - c) * normal;
121#if 0
122    OSG_NOTICE<<"computeBisectorIntersector(["<<a<<"], ["<<b<<"], ["<<c<<"], ["<<d<<"], ["<<e<<"], ["<<f<<"[)"<<std::endl;
123    OSG_NOTICE<<"   bisector_abcd = "<<bisector_abcd<<", bisector_cdef="<<bisector_cdef<<std::endl;
124    OSG_NOTICE<<"   bisector_intersection = "<<bisector_intersection<<", thickness = "<<thickness<<std::endl;
125#endif
126    return thickness;
127}
128
129class Boundary
130{
131public:
132
133    typedef std::pair<unsigned int, unsigned int> Segment;
134    typedef std::vector<Segment>  Segments;
135    osg::ref_ptr<osg::Vec3Array> _vertices;
136    Segments _segments;
137
138    Boundary(osg::Vec3Array* vertices, unsigned int start, unsigned int count)
139    {
140        _vertices = vertices;
141
142        if ((*_vertices)[start]==(*_vertices)[start+count-1])
143        {
144            // OSG_NOTICE<<"Boundary is a line loop"<<std::endl;
145        }
146        else
147        {
148            OSG_NOTICE<<"Boundary is not a line loop"<<std::endl;
149        }
150
151        _segments.reserve(count-1);
152        for(unsigned int i=start; i<start+count-1; ++i)
153        {
154            _segments.push_back(Segment(i,i+1));
155        }
156
157    }
158
159    float computeThickness(unsigned int i)
160    {
161        Segment& seg_before = _segments[ (i+_segments.size()-1) % _segments.size() ];
162        Segment& seg_target = _segments[ (i) % _segments.size() ];
163        Segment& seg_after =  _segments[ (i+1) % _segments.size() ];
164        return computeBisectorIntersectorThickness(
165            (*_vertices)[seg_before.first], (*_vertices)[seg_before.second],
166            (*_vertices)[seg_target.first], (*_vertices)[seg_target.second],
167            (*_vertices)[seg_after.first], (*_vertices)[seg_after.second]);
168    }
169
170    void computeAllThickness()
171    {
172        for(unsigned int i=0; i<_segments.size(); ++i)
173        {
174            computeThickness(i);
175        }
176    }
177
178
179    bool findMinThickness(unsigned int& minThickness_i, float& minThickness)
180    {
181        minThickness_i = _segments.size();
182        for(unsigned int i=0; i<_segments.size(); ++i)
183        {
184            float thickness = computeThickness(i);
185            if (thickness>0.0 && thickness <  minThickness)
186            {
187                minThickness = thickness;
188                minThickness_i = i;
189            }
190        }
191
192        return minThickness_i != _segments.size();
193    }
194
195    void removeAllSegmentsBelowThickness(float targetThickness)
196    {
197        // OSG_NOTICE<<"removeAllSegmentsBelowThickness("<<targetThickness<<")"<<std::endl;
198        for(;;)
199        {
200            unsigned int minThickness_i = _segments.size();
201            float minThickness = targetThickness;
202            if (!findMinThickness(minThickness_i,minThickness)) break;
203
204            // OSG_NOTICE<<"  removing segment _segments["<<minThickness_i<<"] ("<<_segments[minThickness_i].first<<", "<<_segments[minThickness_i].second<<" with thickness="<<minThickness<<" "<<std::endl;
205            _segments.erase(_segments.begin()+minThickness_i);
206        }
207    }
208
209    osg::Vec3 computeBisectorPoint(unsigned int i, float targetThickness)
210    {
211        Segment& seg_before = _segments[ (i+_segments.size()-1) % _segments.size() ];
212        Segment& seg_target = _segments[ (i) % _segments.size() ];
213        osg::Vec3& a = (*_vertices)[seg_before.first];
214        osg::Vec3& b = (*_vertices)[seg_before.second];
215        osg::Vec3& c = (*_vertices)[seg_target.first];
216        osg::Vec3& d = (*_vertices)[seg_target.second];
217        osg::Vec3 intersection_abcd = computeIntersectionPoint(a,b,c,d);
218        osg::Vec3 bisector_abcd = computeBisectorNormal(a,b,c,d);
219        osg::Vec3 ab_sidevector(b.y()-a.y(), a.x()-b.x(), 0.0);
220        ab_sidevector.normalize();
221        float scale_factor = 1.0/ (bisector_abcd*ab_sidevector);
222        osg::Vec3 new_vertex = intersection_abcd + bisector_abcd*(scale_factor*targetThickness);
223
224        // OSG_NOTICE<<"bisector_abcd = "<<bisector_abcd<<", ab_sidevector="<<ab_sidevector<<", b-a="<<b-a<<", scale_factor="<<scale_factor<<std::endl;
225
226        new_vertex.z() += 0.5f;
227        return new_vertex;
228    }
229
230    void addBoundaryToGeometry(osg::Geometry* geometry, float targetThickness)
231    {
232        if (_segments.empty()) return;
233
234        if (geometry->getVertexArray()==0) geometry->setVertexArray(new osg::Vec3Array);
235        osg::Vec3Array* new_vertices = dynamic_cast<osg::Vec3Array*>(geometry->getVertexArray());
236
237        unsigned int first = new_vertices->size();
238        unsigned int count = 0;
239
240        // reserve enough space in the vertex array to accomodate the vertices associated with the segments
241        // new_vertices->reserve(new_vertices->size()+_segments.size()+1);
242
243        // create vertices
244        unsigned int previous_second = _segments[0].second;
245        osg::Vec3 newPoint = computeBisectorPoint(0, targetThickness);
246        new_vertices->push_back(newPoint);
247        ++count;
248
249        for(unsigned int i=1; i<_segments.size(); ++i)
250        {
251            previous_second = _segments[i].second;
252            newPoint = computeBisectorPoint(i, targetThickness);
253            new_vertices->push_back(newPoint);
254            ++count;
255        }
256
257        // repeat the first point to make it a full closed loop
258        new_vertices->push_back((*new_vertices)[first]);
259        ++count;
260
261        // add DrawArrays primitive set for polygon
262        if (count!=0) geometry->addPrimitiveSet(new osg::DrawArrays(GL_POLYGON, first, count));
263    }
264
265};
266
267
268float computeAngle(osg::Vec3& v1, osg::Vec3& v2, osg::Vec3& v3)
269{
270    osg::Vec3 v12(v1-v2);
271    osg::Vec3 v32(v3-v2);
272    v12.normalize();
273    v32.normalize();
274    float dot = v12*v32;
275    float angle = acosf(dot);
276    return angle;
277}
278
279void computeBoundaryAngles(osg::Vec3Array& vertices, unsigned int start, unsigned int count)
280{
281    //OSG_NOTICE<<"computeBoundaryAngles("<<vertices.size()<<", "<<start<<", "<<count<<")"<<std::endl;
282    if (vertices[start+count-1]==vertices[start])
283    {
284        // OSG_NOTICE<<"is a line loop"<<std::endl;
285    }
286    else
287    {
288        OSG_NOTICE<<"is not line loop, ("<<vertices[start+count-1]<<"), ("<<vertices[start]<<")"<<std::endl;
289        return;
290    }
291
292    computeAngle(vertices[start+count-2],vertices[start],vertices[start+1]);
293    for(unsigned int i=start+1; i<start+count-1; ++i)
294    {
295        computeAngle(vertices[i-1],vertices[i],vertices[i+1]);
296    }
297    computeAngle(vertices[start+count-2],vertices[start],vertices[start+1]);
298}
299
300void computeBoundaryAngles(osg::Geometry* geometry)
301{
302    OSG_NOTICE<<"computeBoundaryAngles("<<geometry<<")"<<std::endl;
303    osg::Vec3Array* vertices = dynamic_cast<osg::Vec3Array*>(geometry->getVertexArray());
304    osg::Geometry::PrimitiveSetList& primitives = geometry->getPrimitiveSetList();
305    for(osg::Geometry::PrimitiveSetList::iterator itr = primitives.begin();
306        itr != primitives.end();
307        ++itr)
308    {
309        osg::DrawArrays* drawArray = dynamic_cast<osg::DrawArrays*>(itr->get());
310        if (drawArray && drawArray->getMode()==GL_POLYGON)
311        {
312            computeBoundaryAngles(*vertices, drawArray->getFirst(), drawArray->getCount());
313        }
314    }
315}
316
317osg::Vec3 computeNewVertexPosition(osg::Vec3& v1, osg::Vec3& v2, osg::Vec3& v3)
318{
319    double angle = computeAngle(v1,v2,v3);
320    osg::Vec3 v21(v2-v1);
321    osg::Vec3 v32(v3-v2);
322    float length_21 = v21.normalize();
323    float length_32 = v32.normalize();
324
325    float t = 5.0;
326    if (length_21==0.0)
327    {
328        OSG_NOTICE<<"length_21=="<<length_21<<", length_32="<<length_32<<std::endl;
329        osg::Vec3 bisector = v32 ^ osg::Vec3(0.0f,0.0f,1.0f);
330        bisector.normalize();
331        osg::Vec3 new_vertex = v2 + bisector * t;
332        return new_vertex;
333    }
334    else if (length_32==0.0)
335    {
336        OSG_NOTICE<<"length_21=="<<length_21<<", length_32="<<length_32<<std::endl;
337        osg::Vec3 bisector = v21 ^ osg::Vec3(0.0f,0.0f,1.0f);
338        bisector.normalize();
339        osg::Vec3 new_vertex = v2 + bisector * t;
340        return new_vertex;
341    }
342
343    osg::Vec3 cross = v21^v32;
344    osg::Vec3 bisector(v32-v21);
345
346#if 0
347    OSG_NOTICE<<"v1=["<<v1<<"], v2=["<<v2<<"], v3=["<<v3<<"], dot_angle="<<osg::RadiansToDegrees(angle)<<std::endl;
348    OSG_NOTICE<<"     computeIntersectionPoint() point "<<computeIntersectionPoint(v1,v2,v2,v3)<<std::endl;
349#endif
350    // OSG_NOTICE<<"     computeBisectorNormal() normal "<<computeBisectorNormal(v1,v2,v2,v3)<<std::endl;
351   
352    if (bisector.length()<0.5)
353    {
354        // angle wider than 90 degrees so use side vectors as guide for angle to project along.
355        osg::Vec3 s21 = v21 ^ osg::Vec3(0.0f,0.0f,1.0f);
356        s21.normalize();
357
358        osg::Vec3 s32 = v32 ^ osg::Vec3(0.0f,0.0f,1.0f);
359        s32.normalize();
360
361        osg::Vec3 bisector(s21+s32);
362        bisector.normalize();
363
364       
365        if ((computeBisectorNormal(v1,v2,v2,v3)-bisector).length2()>0.001)
366        {
367            OSG_NOTICE<<"     WARNING 1 bisector disagree "<<bisector<<", s21=["<<s21<<"], s32=["<<s32<<"]"<<std::endl;
368        }
369        else
370        {
371#if 0
372            OSG_NOTICE<<"     bisector normal "<<bisector<<std::endl;
373#endif
374        }
375
376        float l = t / sin(angle*0.5);
377
378        osg::Vec3 new_vertex = v2 + bisector * l;
379        new_vertex.z() += 0.5f;
380
381        return new_vertex;
382    }
383    else
384    {
385        float l = t / sin(angle*0.5);
386
387        bisector.normalize();
388        if (cross.z()>0.0) bisector = -bisector;
389
390        if ((computeBisectorNormal(v1,v2,v2,v3)-bisector).length2()>0.001)
391        {
392            OSG_NOTICE<<"     WARNING 2 bisector disagree "<<bisector<<std::endl;
393        }
394        else
395        {
396#if 0
397            OSG_NOTICE<<"     bisector normal "<<bisector<<std::endl;
398#endif
399        }
400
401        osg::Vec3 new_vertex = v2 + bisector * l;
402        new_vertex.z() += 0.5f;
403        return new_vertex;
404    }
405}
406
407osg::DrawArrays* computeBevelEdge(osg::Vec3Array& orig_vertices, unsigned int start, unsigned int count, osg::Vec3Array& new_vertices)
408{
409
410    // OSG_NOTICE<<"computeBevelEdge("<<orig_vertices.size()<<", "<<start<<", "<<count<<")"<<std::endl;
411    if (orig_vertices[start+count-1]==orig_vertices[start])
412    {
413        // OSG_NOTICE<<"is a line loop"<<std::endl;
414    }
415    else
416    {
417        OSG_NOTICE<<"is not line loop, ("<<orig_vertices[start+count-1]<<"), ("<<orig_vertices[start]<<")"<<std::endl;
418        return new osg::DrawArrays(GL_POLYGON, start, count);
419    }
420
421    new_vertices[start] = computeNewVertexPosition(orig_vertices[start+count-2],orig_vertices[start],orig_vertices[start+1]);
422    for(unsigned int i=start+1; i<start+count-1; ++i)
423    {
424        new_vertices[i] = computeNewVertexPosition(orig_vertices[i-1],orig_vertices[i],orig_vertices[i+1]);
425    }
426    new_vertices[start+count-1] = computeNewVertexPosition(orig_vertices[start+count-2],orig_vertices[start],orig_vertices[start+1]);
427
428    return new osg::DrawArrays(GL_POLYGON, start, count);
429}
430
431void removeLoops(osg::Vec3Array& orig_vertices, unsigned int start, unsigned int count)
432{
433}
434
435osg::Geometry* computeBevelEdge(osg::Geometry* orig_geometry)
436{
437    // OSG_NOTICE<<"computeBoundaryAngles("<<orig_geometry<<")"<<std::endl;
438    osg::Vec3Array* orig_vertices = dynamic_cast<osg::Vec3Array*>(orig_geometry->getVertexArray());
439    osg::Geometry::PrimitiveSetList& orig_primitives = orig_geometry->getPrimitiveSetList();
440
441    osg::Geometry* new_geometry = new osg::Geometry;
442    osg::Vec3Array* new_vertices = new osg::Vec3Array(*orig_vertices);
443    osg::Geometry::PrimitiveSetList& new_primitives = new_geometry->getPrimitiveSetList();
444    new_geometry->setVertexArray(new_vertices);
445    osg::Vec4Array* new_colours = new osg::Vec4Array;
446    new_colours->push_back(osg::Vec4(1.0,0.0,0.0,1.0));
447    new_geometry->setColorArray(new_colours);
448    new_geometry->setColorBinding(osg::Geometry::BIND_OVERALL);
449
450    for(osg::Geometry::PrimitiveSetList::iterator itr = orig_primitives.begin();
451        itr != orig_primitives.end();
452        ++itr)
453    {
454        osg::DrawArrays* drawArray = dynamic_cast<osg::DrawArrays*>(itr->get());
455        if (drawArray && drawArray->getMode()==GL_POLYGON)
456        {
457            osg::DrawArrays* new_drawArray = computeBevelEdge(*orig_vertices, drawArray->getFirst(), drawArray->getCount(), *new_vertices);
458            removeLoops(*new_vertices, new_drawArray->getFirst(), new_drawArray->getCount());
459            new_primitives.push_back(new_drawArray);
460        }
461    }
462    return new_geometry;
463}
464
465osg::Geometry* computeThickness(osg::Geometry* orig_geometry, float thickness)
466{
467    // OSG_NOTICE<<"computeThickness("<<orig_geometry<<")"<<std::endl;
468    osg::Vec3Array* orig_vertices = dynamic_cast<osg::Vec3Array*>(orig_geometry->getVertexArray());
469    osg::Geometry::PrimitiveSetList& orig_primitives = orig_geometry->getPrimitiveSetList();
470
471    osg::Geometry* new_geometry = new osg::Geometry;
472
473    osg::Vec4Array* new_colours = new osg::Vec4Array;
474    new_colours->push_back(osg::Vec4(1.0,1.0,0.0,1.0));
475    new_geometry->setColorArray(new_colours);
476    new_geometry->setColorBinding(osg::Geometry::BIND_OVERALL);
477
478    for(osg::Geometry::PrimitiveSetList::iterator itr = orig_primitives.begin();
479        itr != orig_primitives.end();
480        ++itr)
481    {
482        osg::DrawArrays* drawArray = dynamic_cast<osg::DrawArrays*>(itr->get());
483        if (drawArray && drawArray->getMode()==GL_POLYGON)
484        {
485            Boundary boundary(orig_vertices, drawArray->getFirst(), drawArray->getCount());
486            boundary.computeAllThickness();
487
488            boundary.removeAllSegmentsBelowThickness(thickness);
489            boundary.addBoundaryToGeometry(new_geometry, thickness);
490        }
491    }
492    return new_geometry;
493}
494
495int main(int argc, char** argv)
496{
497    osg::ArgumentParser arguments(&argc, argv);
498
499    if (arguments.read("--test"))
500    {
501        return main_test(argc,argv);
502    }
503    else if (arguments.read("--original") || arguments.read("--orig"))
504    {
505        return main_orig(argc,argv);
506    }
507
508    std::string fontFile("arial.ttf");
509    while(arguments.read("-f",fontFile)) {}
510
511    std::string word("This is a simple test");
512
513    while(arguments.read("--ascii"))
514    {
515        word.clear();
516        for(unsigned int c=' '; c<=127;++c)
517        {
518            word.push_back(c);
519        }
520    }
521
522    while(arguments.read("-w",word)) {}
523
524    osg::ref_ptr<osgText::Font3D> font = osgText::readFont3DFile(fontFile);
525    if (!font) return 1;
526    OSG_NOTICE<<"Read font "<<fontFile<<" font="<<font.get()<<std::endl;
527
528    bool useOldBoundaryCalc = false;
529    while(arguments.read("--old")) useOldBoundaryCalc = true;
530
531    bool useTessellator = false;
532    while(arguments.read("-t") || arguments.read("--tessellate")) { useTessellator = true; }
533
534    float thickness = 5.0;
535    while(arguments.read("--thickness",thickness)) {}
536
537    osg::ref_ptr<osg::Group> group = new osg::Group;
538    osg::Vec3 position;
539
540    for(unsigned int i=0; i<word.size(); ++i)
541    {
542        osg::ref_ptr<osgText::Font3D::Glyph3D> glyph = font->getGlyph(word[i]);
543        if (!glyph) return 1;
544
545        osg::ref_ptr<osg::PositionAttitudeTransform> transform = new osg::PositionAttitudeTransform;
546        transform->setPosition(position);
547        transform->setAttitude(osg::Quat(osg::inDegrees(90.0),osg::Vec3d(1.0,0.0,0.0)));
548
549        position.x() += glyph->getHorizontalWidth();
550
551        osg::ref_ptr<osg::Geode> geode = new osg::Geode;
552
553        osg::Vec3Array* vertices = glyph->getRawVertexArray();
554        osg::Geometry::PrimitiveSetList& primitives = glyph->getRawFacePrimitiveSetList();
555
556        osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry;
557        geometry->setVertexArray(vertices);
558        geometry->setPrimitiveSetList(primitives);
559        osg::Vec4Array* colours = new osg::Vec4Array;
560        colours->push_back(osg::Vec4(1.0,1.0,1.0,1.0));
561        geometry->setColorArray(colours);
562        geometry->setColorBinding(osg::Geometry::BIND_OVERALL);
563
564        osg::Geometry* bevel = 0;
565        if (useOldBoundaryCalc)
566        {
567            bevel = computeBevelEdge(geometry);
568       }
569        else
570        {
571            bevel = computeThickness(geometry, thickness);
572        }
573
574        if (bevel) geode->addDrawable(bevel);
575
576        if (useTessellator)
577        {
578            if (geometry)
579            {
580                osgUtil::Tessellator ts;
581                ts.setWindingType(osgUtil::Tessellator::TESS_WINDING_POSITIVE);
582                ts.setTessellationType(osgUtil::Tessellator::TESS_TYPE_GEOMETRY);
583                ts.retessellatePolygons(*geometry);
584            }
585
586            if (bevel)
587            {
588                osgUtil::Tessellator ts;
589                ts.setWindingType(osgUtil::Tessellator::TESS_WINDING_POSITIVE);
590                ts.setTessellationType(osgUtil::Tessellator::TESS_TYPE_GEOMETRY);
591                ts.retessellatePolygons(*bevel);
592            }
593
594        }
595
596        geode->addDrawable(geometry.get());
597
598        transform->addChild(geode.get());
599
600        group->addChild(transform.get());
601    }
602
603    std::string filename;
604    if (arguments.read("-o", filename)) osgDB::writeNodeFile(*group, filename);
605
606    osgViewer::Viewer viewer(arguments);
607    viewer.setSceneData(group.get());
608    viewer.addEventHandler( new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()) );
609    return viewer.run();
610}
Note: See TracBrowser for help on using the browser.