root/OpenSceneGraph/trunk/src/osgText/Text3D.cpp @ 8868

Revision 8868, 24.5 kB (checked in by robert, 6 years ago)

From Mathias Froehlich, "This is a generic optimization that does not depend on any cpu or instruction
set.

The optimization is based on the observation that matrix matrix multiplication
with a dense matrix 4x4 is 43 Operations whereas multiplication with a
transform, or scale matrix is only 4
2 operations. Which is a gain of a
*FACTOR*4* for these special cases.
The change implements these special cases, provides a unit test for these
implementation and converts uses of the expensiver dense matrix matrix
routine with the specialized versions.

Depending on the transform nodes in the scenegraph this change gives a
noticable improovement.
For example the osgforest code using the MatrixTransform? is about 20% slower
than the same codepath using the PositionAttitudeTransform? instead of the
MatrixTransform? with this patch applied.

If I remember right, the sse type optimizations did *not* provide a factor 4
improovement. Also these changes are totally independent of any cpu or
instruction set architecture. So I would prefer to have this current kind of
change instead of some hand coded and cpu dependent assembly stuff. If we
need that hand tuned stuff, these can go on top of this changes which must
provide than hand optimized additional variants for the specialized versions
to give a even better result in the end.

An other change included here is a change to rotation matrix from quaterion
code. There is a sqrt call which couold be optimized away. Since we divide in
effect by sqrt(length)*sqrt(length) which is just length ...
"

Line 
1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
2 *
3 * This library is open source and may be redistributed and/or modified under 
4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5 * (at your option) any later version.  The full license is in LICENSE file
6 * included with this distribution, and on the openscenegraph.org website.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 * OpenSceneGraph Public License for more details.
12*/
13
14#include <osgText/Text3D>
15#include <osg/io_utils>
16namespace osgText
17{
18
19Text3D::Text3D():
20    _font(0),
21    _characterDepth(1),
22    _renderMode(PER_GLYPH)
23{
24}
25
26Text3D::Text3D(const Text3D & text3D, const osg::CopyOp & copyop):
27    osgText::TextBase(text3D, copyop),
28    _font(text3D._font),
29    _characterDepth(text3D._characterDepth),
30    _renderMode(text3D._renderMode)
31{
32    computeGlyphRepresentation();
33}
34
35//void Text3D::accept(osg::Drawable::ConstAttributeFunctor& af) const
36//{
37//    TODO
38//}
39
40//void Text3D::accept(osg::PrimitiveFunctor& /*pf*/) const
41//{
42//    TODO
43//}
44
45void Text3D::setFont(osg::ref_ptr<Font3D> font)
46{
47    _font = font;
48   
49    computeGlyphRepresentation();
50}
51
52void Text3D::setFont(const std::string & fontfile)
53{
54    setFont(readRefFont3DFile(fontfile));
55}
56
57String::iterator Text3D::computeLastCharacterOnLine(osg::Vec2& cursor, String::iterator first,String::iterator last)
58{
59    if (_font.valid() == false) return last;
60
61    bool kerning = true;
62    unsigned int previous_charcode = 0;
63
64    String::iterator lastChar = first;
65
66    std::set<unsigned int> deliminatorSet;
67    deliminatorSet.insert(' ');
68    deliminatorSet.insert('\n');
69    deliminatorSet.insert(':');
70    deliminatorSet.insert('/');
71    deliminatorSet.insert(',');
72    deliminatorSet.insert(';');
73    deliminatorSet.insert(':');
74    deliminatorSet.insert('.');
75
76    float maximumHeight = _maximumHeight / _font->getScale();
77    float maximumWidth = _maximumWidth / _font->getScale();
78   
79    for(bool outOfSpace=false;lastChar!=last;++lastChar)
80    {
81        unsigned int charcode = *lastChar;
82       
83        if (charcode=='\n')
84        {
85            return lastChar;
86        }
87
88        Font3D::Glyph3D* glyph = _font->getGlyph(charcode);
89        if (glyph)
90        {
91            const osg::BoundingBox & bb = glyph->getBoundingBox();
92           
93            // adjust cursor position w.r.t any kerning.
94            if (previous_charcode)
95            {
96               
97                if (_layout == RIGHT_TO_LEFT)
98                {
99                    cursor.x() -= glyph->getHorizontalAdvance();
100                }
101               
102                if (kerning)
103                {
104                    switch (_layout)
105                    {
106                        case LEFT_TO_RIGHT:
107                        {
108                            cursor += _font->getKerning(previous_charcode, charcode, _kerningType);
109                            break;
110                        }
111                        case RIGHT_TO_LEFT:
112                        {
113                            cursor -= _font->getKerning(charcode, previous_charcode, _kerningType);
114                            break;
115                        }
116                        case VERTICAL:
117                            break; // no kerning when vertical.
118                    }
119                }
120            }
121            else
122            {
123                switch (_layout)
124                {
125                    case LEFT_TO_RIGHT:
126                    {
127                        cursor.x() -= glyph->getHorizontalBearing().x();
128                        break;
129                    }
130                    case RIGHT_TO_LEFT:
131                    {
132                        cursor.x() -= bb.xMax();
133                        break;
134                    }
135                    case VERTICAL:
136                        break;
137                }
138               
139            }
140           
141           
142
143            switch(_layout)
144            {
145              case LEFT_TO_RIGHT:
146              {
147                if (maximumWidth>0.0f && cursor.x()+bb.xMax()>maximumWidth) outOfSpace=true;
148                if(maximumHeight>0.0f && cursor.y()<-maximumHeight) outOfSpace=true;
149                break;
150              }
151              case RIGHT_TO_LEFT:
152              {
153                if (maximumWidth>0.0f && cursor.x()+bb.xMin()<-maximumWidth) outOfSpace=true;
154                if(maximumHeight>0.0f && cursor.y()<-maximumHeight) outOfSpace=true;
155                break;
156              }
157              case VERTICAL:
158                if (maximumHeight>0.0f && cursor.y()<-maximumHeight) outOfSpace=true;
159                break;
160            }
161           
162            // => word boundary detection & wrapping
163            if (outOfSpace) break;
164
165            // move the cursor onto the next character.
166            switch(_layout)
167            {
168              case LEFT_TO_RIGHT: cursor.x() += glyph->getHorizontalAdvance(); break;
169              case RIGHT_TO_LEFT: break;
170              case VERTICAL:      cursor.y() -= glyph->getVerticalAdvance(); break;
171            }
172
173            previous_charcode = charcode;
174
175        }
176
177    }
178   
179    // word boundary detection & wrapping
180    if (lastChar!=last)
181    {
182        if (deliminatorSet.count(*lastChar)==0)
183        {
184            String::iterator lastValidChar = lastChar;
185            while (lastValidChar!=first && deliminatorSet.count(*lastValidChar)==0)
186            {
187                --lastValidChar;
188               
189                //Substract off glyphs from the cursor position (to correctly center text)
190                Font3D::Glyph3D* glyph = _font->getGlyph(*lastValidChar);
191                if (glyph)
192                {
193                    switch(_layout)
194                    {
195                    case LEFT_TO_RIGHT: cursor.x() -= glyph->getHorizontalAdvance(); break;
196                    case RIGHT_TO_LEFT: cursor.x() += glyph->getHorizontalAdvance(); break;
197                    case VERTICAL:      cursor.y() += glyph->getVerticalAdvance(); break;
198                    }
199                }
200            }
201           
202            if (first!=lastValidChar)
203            {
204                ++lastValidChar;
205                lastChar = lastValidChar;
206            }
207        }
208    }
209
210    return lastChar;
211}
212
213void Text3D::computeGlyphRepresentation()
214{
215    if (_font.valid() == false) return;
216   
217    _textRenderInfo.clear();
218    _lineCount = 0;
219   
220    if (_text.empty())
221    {
222        _textBB.set(0,0,0, 0,0,0);//no size text
223        TextBase::computePositions(); //to reset the origin
224        return;
225    }
226   
227    // initialize bounding box, it will be expanded during glyph position calculation
228    _textBB.init();
229
230    osg::Vec2 startOfLine_coords(0.0f,0.0f);
231    osg::Vec2 cursor(startOfLine_coords);
232    osg::Vec2 local(0.0f,0.0f);
233    osg::Vec2 startOffset(0.0f,0.0f);
234   
235    unsigned int previous_charcode = 0;
236    unsigned int linelength = 0;
237    bool kerning = true;
238   
239    unsigned int lineNumber = 0;
240
241 
242
243    for(String::iterator itr=_text.begin(); itr!=_text.end(); )
244    {
245        _textRenderInfo.resize(lineNumber + 1);
246        LineRenderInfo & currentLineRenderInfo = _textRenderInfo.back();
247       
248        // record the start of the current line
249        String::iterator startOfLine_itr = itr;
250
251        // find the end of the current line.
252        osg::Vec2 endOfLine_coords(cursor);
253        String::iterator endOfLine_itr = computeLastCharacterOnLine(endOfLine_coords, itr,_text.end());
254       
255        // ** position the cursor function to the Layout and the alignement
256        TextBase::positionCursor(endOfLine_coords, cursor, (unsigned int) (endOfLine_itr - startOfLine_itr));
257
258       
259        if (itr!=endOfLine_itr)
260        {
261            for(;itr!=endOfLine_itr;++itr)
262            {
263                unsigned int charcode = *itr;
264
265                Font3D::Glyph3D* glyph = _font->getGlyph(charcode);
266                if (glyph)
267                {
268                    const osg::BoundingBox & bb = glyph->getBoundingBox();
269                   
270                    // adjust cursor position w.r.t any kerning.
271                    if (previous_charcode)
272                    {
273                        if (_layout == RIGHT_TO_LEFT)
274                        {
275                            cursor.x() -= glyph->getHorizontalAdvance();
276                        }
277                       
278                        if (kerning)
279                        {
280                            switch (_layout)
281                            {
282                                case LEFT_TO_RIGHT:
283                                {
284                                    cursor += _font->getKerning(previous_charcode, charcode, _kerningType);
285                                    break;
286                                }
287                                case RIGHT_TO_LEFT:
288                                {
289                                    cursor -= _font->getKerning(charcode, previous_charcode, _kerningType);
290                                    break;
291                                }
292                                case VERTICAL:
293                                    break; // no kerning when vertical.
294                            }
295                        }
296                    }
297                    else
298                    {
299                        switch (_layout)
300                        {
301                            case LEFT_TO_RIGHT:
302                            {
303                                cursor.x() -= glyph->getHorizontalBearing().x();
304                                break;
305                            }
306                            case RIGHT_TO_LEFT:
307                            {
308                                cursor.x() -= bb.xMax();
309                                break;
310                            }
311                            case VERTICAL:
312                            {
313//                                cursor.y() += glyph->getVerticalBearing().y();
314                                break;
315                            }
316                        }
317                       
318                    }
319
320                    local = cursor;
321                   
322                    if (_layout==VERTICAL)
323                    {
324                        local.x() += -glyph->getVerticalBearing().x();
325                        local.y() += -glyph->getVerticalBearing().y();
326                    }
327                     
328                   
329                   
330                    // move the cursor onto the next character.
331                    // also expand bounding box
332                    switch (_layout)
333                    {
334                        case LEFT_TO_RIGHT:
335                            _textBB.expandBy(osg::Vec3(cursor.x() + bb.xMin(), cursor.y() + bb.yMin(), 0.0f)); //lower left corner
336                            _textBB.expandBy(osg::Vec3(cursor.x() + bb.xMax(), cursor.y() + bb.yMax(), 0.0f)); //upper right corner
337                            cursor.x() += glyph->getHorizontalAdvance();
338                            break;
339                        case VERTICAL:
340                            _textBB.expandBy(osg::Vec3(cursor.x(), cursor.y(), 0.0f)); //upper left corner
341                            _textBB.expandBy(osg::Vec3(cursor.x() + glyph->getWidth(), cursor.y() - glyph->getHeight(), 0.0f)); //lower right corner
342                            cursor.y() -= glyph->getVerticalAdvance();
343                            break;
344                        case RIGHT_TO_LEFT:
345                            _textBB.expandBy(osg::Vec3(cursor.x()+bb.xMax(), cursor.y() + bb.yMax(), 0.0f)); //upper right corner
346                            _textBB.expandBy(osg::Vec3(cursor.x()+bb.xMin(), cursor.y()+bb.yMin(), 0.0f)); //lower left corner
347                           
348                            break;
349                    }
350                   
351                    osg::Vec3 pos = osg::Vec3(local.x(), local.y(), 0.0f);
352                    currentLineRenderInfo.push_back(Text3D::GlyphRenderInfo(glyph, pos));
353
354                   
355                    previous_charcode = charcode;
356                }
357            }
358        }
359        else
360        {
361            ++itr;
362        }
363                               
364        if (itr!=_text.end())
365        {
366            // skip over return.
367            if (*itr=='\n') ++itr;
368        }
369               
370        // move to new line.
371        switch(_layout)
372        {
373            case LEFT_TO_RIGHT:
374            case RIGHT_TO_LEFT:
375            {
376                startOfLine_coords.y() -= (1.0 + _lineSpacing) / _font->getScale();
377                ++_lineCount;
378                break;
379            }
380            case VERTICAL:
381            {
382                startOfLine_coords.x() += _characterHeight / _font->getScale() / _characterAspectRatio * (1.0 + _lineSpacing);
383                // because _lineCount is the max vertical no. of characters....
384                _lineCount = (_lineCount >linelength)?_lineCount:linelength;
385                break;
386            }
387            default:
388                break;
389        }
390
391        cursor = startOfLine_coords;
392        previous_charcode = 0;
393
394        ++lineNumber;
395    }
396    _textBB.expandBy(0.0f,0.0f,-1);
397   
398    TextBase::computePositions();
399}
400
401
402
403osg::BoundingBox Text3D::computeBound() const
404{
405    osg::BoundingBox  bbox;
406
407    if (_textBB.valid())
408    {
409        for(unsigned int i=0;i<_autoTransformCache.size();++i)
410        {
411            osg::Matrix& matrix = _autoTransformCache[i]._matrix;
412            bbox.expandBy(osg::Vec3(_textBB.xMin(),_textBB.yMin(),_textBB.zMin())*matrix);
413//          bbox.expandBy(osg::Vec3(_textBB.xMax(),_textBB.yMin(),_textBB.zMin())*matrix);
414            bbox.expandBy(osg::Vec3(_textBB.xMax(),_textBB.yMax(),_textBB.zMax())*matrix);
415//          bbox.expandBy(osg::Vec3(_textBB.xMin(),_textBB.yMax(),_textBB.zMin())*matrix);
416        }
417    }
418   
419    return bbox;
420}
421
422
423
424
425
426
427
428void Text3D::computePositions(unsigned int contextID) const
429{
430    if (_font.valid() == false) return;
431   
432    switch(_alignment)
433    {
434    case LEFT_TOP:      _offset.set(_textBB.xMin(),_textBB.yMax(),_textBB.zMin()); break;
435    case LEFT_CENTER:   _offset.set(_textBB.xMin(),(_textBB.yMax()+_textBB.yMin())*0.5f,_textBB.zMin()); break;
436    case LEFT_BOTTOM:   _offset.set(_textBB.xMin(),_textBB.yMin(),_textBB.zMin()); break;
437
438    case CENTER_TOP:    _offset.set((_textBB.xMax()+_textBB.xMin())*0.5f,_textBB.yMax(),_textBB.zMin()); break;
439    case CENTER_CENTER: _offset.set((_textBB.xMax()+_textBB.xMin())*0.5f,(_textBB.yMax()+_textBB.yMin())*0.5f,_textBB.zMin()); break;
440    case CENTER_BOTTOM: _offset.set((_textBB.xMax()+_textBB.xMin())*0.5f,_textBB.yMin(),_textBB.zMin()); break;
441
442    case RIGHT_TOP:     _offset.set(_textBB.xMax(),_textBB.yMax(),_textBB.zMin()); break;
443    case RIGHT_CENTER:  _offset.set(_textBB.xMax(),(_textBB.yMax()+_textBB.yMin())*0.5f,_textBB.zMin()); break;
444    case RIGHT_BOTTOM:  _offset.set(_textBB.xMax(),_textBB.yMin(),_textBB.zMin()); break;
445
446    case LEFT_BASE_LINE:  _offset.set(0.0f,0.0f,0.0f); break;
447    case CENTER_BASE_LINE:  _offset.set((_textBB.xMax()+_textBB.xMin())*0.5f,0.0f,0.0f); break;
448    case RIGHT_BASE_LINE:  _offset.set(_textBB.xMax(),0.0f,0.0f); break;
449   
450    case LEFT_BOTTOM_BASE_LINE:  _offset.set(0.0f,-_characterHeight*(_lineCount-1),0.0f); break;
451    case CENTER_BOTTOM_BASE_LINE:  _offset.set((_textBB.xMax()+_textBB.xMin())*0.5f,-_characterHeight*(_lineCount-1),0.0f); break;
452    case RIGHT_BOTTOM_BASE_LINE:  _offset.set(_textBB.xMax(),-_characterHeight*(_lineCount-1),0.0f); break;
453    }
454   
455    AutoTransformCache& atc = _autoTransformCache[contextID];
456    osg::Matrix& matrix = atc._matrix;
457
458   
459    float scale = _font->getScale();
460    osg::Vec3 scaleVec(scale * _characterHeight, scale * _characterHeight / _characterAspectRatio, _characterDepth);
461    matrix.makeTranslate(-_offset);
462    matrix.postMultScale(scaleVec);
463    matrix.postMultRotate(_rotation);
464    matrix.postMultTranslate(_position);
465
466   
467    _normal = osg::Matrix::transform3x3(osg::Vec3(0.0f,0.0f,1.0f),matrix);
468    _normal.normalize();
469
470    const_cast<Text3D*>(this)->dirtyBound();   
471}
472
473void Text3D::drawImplementation(osg::RenderInfo& renderInfo) const
474{
475    osg::State & state = *renderInfo.getState();
476    unsigned int contextID = state.getContextID();
477   
478   
479    // ** save the previous modelview matrix
480    osg::ref_ptr<osg::RefMatrix> previous(new osg::RefMatrix(state.getModelViewMatrix()));
481
482    // ** get the modelview for this context
483    osg::ref_ptr<osg::RefMatrix> modelview(new osg::RefMatrix(_autoTransformCache[contextID]._matrix));
484
485    // ** mult previous by the modelview for this context
486    modelview->postMult(*previous.get());
487   
488    // ** apply this new modelview matrix
489    state.applyModelViewMatrix(modelview.get());
490   
491   
492    if (_drawMode & TEXT)
493    {
494        renderInfo.getState()->disableAllVertexArrays();
495       
496        glPushAttrib(GL_TRANSFORM_BIT);
497        glEnable(GL_RESCALE_NORMAL);
498       
499        switch(_renderMode)
500        {
501            case PER_FACE:  renderPerFace(*renderInfo.getState());   break;
502            case PER_GLYPH:
503            default:        renderPerGlyph(*renderInfo.getState());  break;
504        }
505       
506        glPopAttrib();
507    }
508
509    if (_drawMode & BOUNDINGBOX)
510    {
511        if (_textBB.valid())
512        {
513            osg::Vec3 c000(osg::Vec3(_textBB.xMin(),_textBB.yMin(),_textBB.zMax()));
514            osg::Vec3 c100(osg::Vec3(_textBB.xMax(),_textBB.yMin(),_textBB.zMax()));
515            osg::Vec3 c110(osg::Vec3(_textBB.xMax(),_textBB.yMax(),_textBB.zMax()));
516            osg::Vec3 c010(osg::Vec3(_textBB.xMin(),_textBB.yMax(),_textBB.zMax()));
517       
518            osg::Vec3 c001(osg::Vec3(_textBB.xMin(),_textBB.yMin(),_textBB.zMin()));
519            osg::Vec3 c101(osg::Vec3(_textBB.xMax(),_textBB.yMin(),_textBB.zMin()));
520            osg::Vec3 c111(osg::Vec3(_textBB.xMax(),_textBB.yMax(),_textBB.zMin()));
521            osg::Vec3 c011(osg::Vec3(_textBB.xMin(),_textBB.yMax(),_textBB.zMin()));
522       
523            glBegin(GL_LINE_LOOP);
524                glVertex3fv(c000.ptr());
525                glVertex3fv(c100.ptr());
526                glVertex3fv(c110.ptr());
527                glVertex3fv(c010.ptr());
528            glEnd();
529           
530            glBegin(GL_LINE_LOOP);
531                glVertex3fv(c001.ptr());
532                glVertex3fv(c011.ptr());
533                glVertex3fv(c111.ptr());
534                glVertex3fv(c101.ptr());
535            glEnd();
536           
537            glBegin(GL_LINES);
538                glVertex3fv(c000.ptr());
539                glVertex3fv(c001.ptr());
540               
541                glVertex3fv(c100.ptr());
542                glVertex3fv(c101.ptr());
543               
544                glVertex3fv(c110.ptr());
545                glVertex3fv(c111.ptr());
546               
547                glVertex3fv(c010.ptr());
548                glVertex3fv(c011.ptr());
549            glEnd();
550        }
551    }   
552
553    if (_drawMode & ALIGNMENT)
554    {
555        float cursorsize = _characterHeight*0.5f;
556
557        osg::Vec3 hl(osg::Vec3(_offset.x()-cursorsize,_offset.y(),_offset.z()));
558        osg::Vec3 hr(osg::Vec3(_offset.x()+cursorsize,_offset.y(),_offset.z()));
559        osg::Vec3 vt(osg::Vec3(_offset.x(),_offset.y()-cursorsize,_offset.z()));
560        osg::Vec3 vb(osg::Vec3(_offset.x(),_offset.y()+cursorsize,_offset.z()));
561
562        glBegin(GL_LINES);
563            glVertex3fv(hl.ptr());
564            glVertex3fv(hr.ptr());
565            glVertex3fv(vt.ptr());
566            glVertex3fv(vb.ptr());
567        glEnd();
568       
569    }
570
571    // restore the previous modelview matrix
572    state.applyModelViewMatrix(previous.get());
573}
574
575
576
577void Text3D::renderPerGlyph(osg::State & state) const
578{   
579    // ** for each line, do ...
580    TextRenderInfo::const_iterator itLine, endLine = _textRenderInfo.end();
581    for (itLine = _textRenderInfo.begin(); itLine!=endLine; ++itLine)
582    {
583        // ** for each glyph in the line, do ...
584        LineRenderInfo::const_iterator it, end = itLine->end();
585        for (it = itLine->begin(); it!=end; ++it)
586        {
587           
588            glPushMatrix();
589
590            glTranslatef(it->_position.x(), it->_position.y(), it->_position.z());
591           
592            // ** apply the vertex array
593            state.setVertexPointer(it->_glyph->getVertexArray());
594           
595            // ** render the front face of the glyph
596            glNormal3f(0.0f,0.0f,1.0f);
597           
598            osg::Geometry::PrimitiveSetList & pslFront = it->_glyph->getFrontPrimitiveSetList();
599            for(osg::Geometry::PrimitiveSetList::const_iterator itr=pslFront.begin(), end = pslFront.end(); itr!=end; ++itr)
600            {
601               
602                (*itr)->draw(state, false);
603            }
604           
605            // ** render the wall face of the glyph
606            state.setNormalPointer(it->_glyph->getNormalArray());
607            osg::Geometry::PrimitiveSetList & pslWall = it->_glyph->getWallPrimitiveSetList();
608            for(osg::Geometry::PrimitiveSetList::const_iterator itr=pslWall.begin(), end=pslWall.end(); itr!=end; ++itr)
609            {
610                (*itr)->draw(state, false);
611            }
612           
613            // ** render the back face of the glyph
614            glNormal3f(0.0f,0.0f,-1.0f);
615                       
616            osg::Geometry::PrimitiveSetList & pslBack = it->_glyph->getBackPrimitiveSetList();
617            for(osg::Geometry::PrimitiveSetList::const_iterator itr=pslBack.begin(), end=pslBack.end(); itr!=end; ++itr)
618            {
619                (*itr)->draw(state, false);
620            }
621           
622            glPopMatrix();
623        }
624    }
625}
626
627void Text3D::renderPerFace(osg::State & state) const
628{
629    // ** render all front faces
630    glNormal3f(0.0f,0.0f,1.0f);
631   
632    TextRenderInfo::const_iterator itLine, endLine = _textRenderInfo.end();
633    for (itLine = _textRenderInfo.begin(); itLine!=endLine; ++itLine)
634    {
635        // ** for each glyph in the line, do ...
636        LineRenderInfo::const_iterator it, end = itLine->end();
637        for (it = itLine->begin(); it!=end; ++it)   
638        {
639            glPushMatrix();
640            glTranslatef(it->_position.x(), it->_position.y(), it->_position.z());
641            state.setVertexPointer(it->_glyph->getVertexArray());
642           
643            // ** render the front face of the glyph
644            osg::Geometry::PrimitiveSetList & psl = it->_glyph->getFrontPrimitiveSetList();
645            for(osg::Geometry::PrimitiveSetList::const_iterator itr=psl.begin(), end=psl.end(); itr!=end; ++itr)
646            {
647                (*itr)->draw(state, false);
648            }
649            glPopMatrix();
650        }
651    }
652   
653
654    // ** render all wall face of the text
655    for (itLine = _textRenderInfo.begin(); itLine!=endLine; ++itLine)
656    {
657        // ** for each glyph in the line, do ...
658        LineRenderInfo::const_iterator it, end = itLine->end();
659        for (it = itLine->begin(); it!=end; ++it)
660        {
661            glPushMatrix();
662            glTranslatef(it->_position.x(), it->_position.y(), it->_position.z());
663            state.setVertexPointer(it->_glyph->getVertexArray());
664            state.setNormalPointer(it->_glyph->getNormalArray());
665           
666            osg::Geometry::PrimitiveSetList & psl = it->_glyph->getWallPrimitiveSetList();
667            for(osg::Geometry::PrimitiveSetList::const_iterator itr=psl.begin(), end=psl.end(); itr!=end; ++itr)
668            {
669                (*itr)->draw(state, false);
670            }
671            glPopMatrix();
672        }
673    }
674
675   
676    // ** render all back face of the text
677    glNormal3f(0.0f,0.0f,-1.0f);
678               
679    for (itLine = _textRenderInfo.begin(); itLine!=endLine; ++itLine)
680    {
681        // ** for each glyph in the line, do ...
682        LineRenderInfo::const_iterator it, end = itLine->end();
683        for (it = itLine->begin(); it!=end; ++it)
684        {
685            glPushMatrix();
686            glTranslatef(it->_position.x(), it->_position.y(), it->_position.z());
687            state.setVertexPointer(it->_glyph->getVertexArray());
688           
689            // ** render the back face of the glyph
690            osg::Geometry::PrimitiveSetList & psl = it->_glyph->getBackPrimitiveSetList();
691            for(osg::Geometry::PrimitiveSetList::const_iterator itr=psl.begin(), end=psl.end(); itr!=end; ++itr)
692            {
693                (*itr)->draw(state, false);
694            }
695            glPopMatrix();
696        }
697    }
698}
699
700
701
702void Text3D::setThreadSafeRefUnref(bool threadSafe)
703{
704    TextBase::setThreadSafeRefUnref(threadSafe);
705
706    if (_font.valid()) _font->setThreadSafeRefUnref(threadSafe);
707}
708
709void Text3D::resizeGLObjectBuffers(unsigned int maxSize)
710{
711    TextBase::resizeGLObjectBuffers(maxSize);
712   
713    if (_font.valid()) _font->resizeGLObjectBuffers(maxSize);
714}
715
716void Text3D::releaseGLObjects(osg::State* state) const
717{
718    TextBase::releaseGLObjects(state);
719   
720    if (_font.valid()) _font->releaseGLObjects(state);
721}
722
723}
Note: See TracBrowser for help on using the browser.