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

Revision 8441, 24.9 kB (checked in by robert, 7 years ago)

From David Callu, "fixed bounding box bug"

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::Matrix scaleMatrix = osg::Matrix::scale(scale * _characterHeight,
461                                                 scale * _characterHeight / _characterAspectRatio,
462                                                 _characterDepth);
463    if (!_rotation.zeroRotation())
464    {
465        matrix.makeTranslate(-_offset);
466        matrix.postMult(scaleMatrix);
467        matrix.postMult(osg::Matrix::rotate(_rotation));
468        matrix.postMult(osg::Matrix::translate(_position));
469    }
470    else
471    {
472        matrix.makeTranslate(-_offset);
473        matrix.postMult(scaleMatrix);
474        matrix.postMult(osg::Matrix::translate(_position));
475    }
476
477   
478    _normal = osg::Matrix::transform3x3(osg::Vec3(0.0f,0.0f,1.0f),matrix);
479    _normal.normalize();
480
481    const_cast<Text3D*>(this)->dirtyBound();   
482}
483
484void Text3D::drawImplementation(osg::RenderInfo& renderInfo) const
485{
486    osg::State & state = *renderInfo.getState();
487    unsigned int contextID = state.getContextID();
488   
489   
490    // ** save the previous modelview matrix
491    osg::ref_ptr<osg::RefMatrix> previous(new osg::RefMatrix(state.getModelViewMatrix()));
492
493    // ** get the modelview for this context
494    osg::ref_ptr<osg::RefMatrix> modelview(new osg::RefMatrix(_autoTransformCache[contextID]._matrix));
495
496    // ** mult previous by the modelview for this context
497    modelview->postMult(*previous.get());
498   
499    // ** apply this new modelview matrix
500    state.applyModelViewMatrix(modelview.get());
501   
502   
503    if (_drawMode & TEXT)
504    {
505        renderInfo.getState()->disableAllVertexArrays();
506       
507        glPushAttrib(GL_TRANSFORM_BIT);
508        glEnable(GL_RESCALE_NORMAL);
509       
510        switch(_renderMode)
511        {
512            case PER_FACE:  renderPerFace(*renderInfo.getState());   break;
513            case PER_GLYPH:
514            default:        renderPerGlyph(*renderInfo.getState());  break;
515        }
516       
517        glPopAttrib();
518    }
519
520    if (_drawMode & BOUNDINGBOX)
521    {
522        if (_textBB.valid())
523        {
524            osg::Vec3 c000(osg::Vec3(_textBB.xMin(),_textBB.yMin(),_textBB.zMax()));
525            osg::Vec3 c100(osg::Vec3(_textBB.xMax(),_textBB.yMin(),_textBB.zMax()));
526            osg::Vec3 c110(osg::Vec3(_textBB.xMax(),_textBB.yMax(),_textBB.zMax()));
527            osg::Vec3 c010(osg::Vec3(_textBB.xMin(),_textBB.yMax(),_textBB.zMax()));
528       
529            osg::Vec3 c001(osg::Vec3(_textBB.xMin(),_textBB.yMin(),_textBB.zMin()));
530            osg::Vec3 c101(osg::Vec3(_textBB.xMax(),_textBB.yMin(),_textBB.zMin()));
531            osg::Vec3 c111(osg::Vec3(_textBB.xMax(),_textBB.yMax(),_textBB.zMin()));
532            osg::Vec3 c011(osg::Vec3(_textBB.xMin(),_textBB.yMax(),_textBB.zMin()));
533       
534            glBegin(GL_LINE_LOOP);
535                glVertex3fv(c000.ptr());
536                glVertex3fv(c100.ptr());
537                glVertex3fv(c110.ptr());
538                glVertex3fv(c010.ptr());
539            glEnd();
540           
541            glBegin(GL_LINE_LOOP);
542                glVertex3fv(c001.ptr());
543                glVertex3fv(c011.ptr());
544                glVertex3fv(c111.ptr());
545                glVertex3fv(c101.ptr());
546            glEnd();
547           
548            glBegin(GL_LINES);
549                glVertex3fv(c000.ptr());
550                glVertex3fv(c001.ptr());
551               
552                glVertex3fv(c100.ptr());
553                glVertex3fv(c101.ptr());
554               
555                glVertex3fv(c110.ptr());
556                glVertex3fv(c111.ptr());
557               
558                glVertex3fv(c010.ptr());
559                glVertex3fv(c011.ptr());
560            glEnd();
561        }
562    }   
563
564    if (_drawMode & ALIGNMENT)
565    {
566        float cursorsize = _characterHeight*0.5f;
567
568        osg::Vec3 hl(osg::Vec3(_offset.x()-cursorsize,_offset.y(),_offset.z()));
569        osg::Vec3 hr(osg::Vec3(_offset.x()+cursorsize,_offset.y(),_offset.z()));
570        osg::Vec3 vt(osg::Vec3(_offset.x(),_offset.y()-cursorsize,_offset.z()));
571        osg::Vec3 vb(osg::Vec3(_offset.x(),_offset.y()+cursorsize,_offset.z()));
572
573        glBegin(GL_LINES);
574            glVertex3fv(hl.ptr());
575            glVertex3fv(hr.ptr());
576            glVertex3fv(vt.ptr());
577            glVertex3fv(vb.ptr());
578        glEnd();
579       
580    }
581
582    // restore the previous modelview matrix
583    state.applyModelViewMatrix(previous.get());
584}
585
586
587
588void Text3D::renderPerGlyph(osg::State & state) const
589{   
590    // ** for each line, do ...
591    TextRenderInfo::const_iterator itLine, endLine = _textRenderInfo.end();
592    for (itLine = _textRenderInfo.begin(); itLine!=endLine; ++itLine)
593    {
594        // ** for each glyph in the line, do ...
595        LineRenderInfo::const_iterator it, end = itLine->end();
596        for (it = itLine->begin(); it!=end; ++it)
597        {
598           
599            glPushMatrix();
600
601            glTranslatef(it->_position.x(), it->_position.y(), it->_position.z());
602           
603            // ** apply the vertex array
604            state.setVertexPointer(it->_glyph->getVertexArray());
605           
606            // ** render the front face of the glyph
607            glNormal3f(0.0f,0.0f,1.0f);
608           
609            osg::Geometry::PrimitiveSetList & pslFront = it->_glyph->getFrontPrimitiveSetList();
610            for(osg::Geometry::PrimitiveSetList::const_iterator itr=pslFront.begin(), end = pslFront.end(); itr!=end; ++itr)
611            {
612               
613                (*itr)->draw(state, false);
614            }
615           
616            // ** render the wall face of the glyph
617            state.setNormalPointer(it->_glyph->getNormalArray());
618            osg::Geometry::PrimitiveSetList & pslWall = it->_glyph->getWallPrimitiveSetList();
619            for(osg::Geometry::PrimitiveSetList::const_iterator itr=pslWall.begin(), end=pslWall.end(); itr!=end; ++itr)
620            {
621                (*itr)->draw(state, false);
622            }
623           
624            // ** render the back face of the glyph
625            glNormal3f(0.0f,0.0f,-1.0f);
626                       
627            osg::Geometry::PrimitiveSetList & pslBack = it->_glyph->getBackPrimitiveSetList();
628            for(osg::Geometry::PrimitiveSetList::const_iterator itr=pslBack.begin(), end=pslBack.end(); itr!=end; ++itr)
629            {
630                (*itr)->draw(state, false);
631            }
632           
633            glPopMatrix();
634        }
635    }
636}
637
638void Text3D::renderPerFace(osg::State & state) const
639{
640    // ** render all front faces
641    glNormal3f(0.0f,0.0f,1.0f);
642   
643    TextRenderInfo::const_iterator itLine, endLine = _textRenderInfo.end();
644    for (itLine = _textRenderInfo.begin(); itLine!=endLine; ++itLine)
645    {
646        // ** for each glyph in the line, do ...
647        LineRenderInfo::const_iterator it, end = itLine->end();
648        for (it = itLine->begin(); it!=end; ++it)   
649        {
650            glPushMatrix();
651            glTranslatef(it->_position.x(), it->_position.y(), it->_position.z());
652            state.setVertexPointer(it->_glyph->getVertexArray());
653           
654            // ** render the front face of the glyph
655            osg::Geometry::PrimitiveSetList & psl = it->_glyph->getFrontPrimitiveSetList();
656            for(osg::Geometry::PrimitiveSetList::const_iterator itr=psl.begin(), end=psl.end(); itr!=end; ++itr)
657            {
658                (*itr)->draw(state, false);
659            }
660            glPopMatrix();
661        }
662    }
663   
664
665    // ** render all wall face of the text
666    for (itLine = _textRenderInfo.begin(); itLine!=endLine; ++itLine)
667    {
668        // ** for each glyph in the line, do ...
669        LineRenderInfo::const_iterator it, end = itLine->end();
670        for (it = itLine->begin(); it!=end; ++it)
671        {
672            glPushMatrix();
673            glTranslatef(it->_position.x(), it->_position.y(), it->_position.z());
674            state.setVertexPointer(it->_glyph->getVertexArray());
675            state.setNormalPointer(it->_glyph->getNormalArray());
676           
677            osg::Geometry::PrimitiveSetList & psl = it->_glyph->getWallPrimitiveSetList();
678            for(osg::Geometry::PrimitiveSetList::const_iterator itr=psl.begin(), end=psl.end(); itr!=end; ++itr)
679            {
680                (*itr)->draw(state, false);
681            }
682            glPopMatrix();
683        }
684    }
685
686   
687    // ** render all back face of the text
688    glNormal3f(0.0f,0.0f,-1.0f);
689               
690    for (itLine = _textRenderInfo.begin(); itLine!=endLine; ++itLine)
691    {
692        // ** for each glyph in the line, do ...
693        LineRenderInfo::const_iterator it, end = itLine->end();
694        for (it = itLine->begin(); it!=end; ++it)
695        {
696            glPushMatrix();
697            glTranslatef(it->_position.x(), it->_position.y(), it->_position.z());
698            state.setVertexPointer(it->_glyph->getVertexArray());
699           
700            // ** render the back face of the glyph
701            osg::Geometry::PrimitiveSetList & psl = it->_glyph->getBackPrimitiveSetList();
702            for(osg::Geometry::PrimitiveSetList::const_iterator itr=psl.begin(), end=psl.end(); itr!=end; ++itr)
703            {
704                (*itr)->draw(state, false);
705            }
706            glPopMatrix();
707        }
708    }
709}
710
711
712
713void Text3D::setThreadSafeRefUnref(bool threadSafe)
714{
715    TextBase::setThreadSafeRefUnref(threadSafe);
716
717    if (_font.valid()) _font->setThreadSafeRefUnref(threadSafe);
718}
719
720void Text3D::resizeGLObjectBuffers(unsigned int maxSize)
721{
722    TextBase::resizeGLObjectBuffers(maxSize);
723   
724    if (_font.valid()) _font->resizeGLObjectBuffers(maxSize);
725}
726
727void Text3D::releaseGLObjects(osg::State* state) const
728{
729    TextBase::releaseGLObjects(state);
730   
731    if (_font.valid()) _font->releaseGLObjects(state);
732}
733
734}
Note: See TracBrowser for help on using the browser.