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

Revision 9881, 25.5 kB (checked in by robert, 6 years ago)

From David Callu, "Problem:

osgText::Text and osgText::Text3D use the same font file.
The first really load the file and obtain an osgText::Font object,
the second use the cache created during the first load of the
font file, and so obtain an osgText::Font object instead of
osgText::Font3D object. To obtain an osgText::Font3D object,
osgText::Text3D call osgDB::readObjectFile(...) with an option
to specify the plugin we want an osgText::Font3D instead of
osgText::Font.

Generalised Problem:

In osgDB::Registry, loaded file cache is referenced by the name
of this file, so if I load a file with some options, and the cache
already contain object for this filename, I obtain an object
potentially not loaded with my options.

Behaviours:

Cache management is delegate to osgDB::Registry, but cache
coherence (load a file with option then reuse it, deactivate the
cache when load a specific file or don't cached the loaded file)
is user's responsibility.

Text3D solution:

Postfix the font file name by .text3d or something similar and then have the freetype plugin return
osgText::Font3D when it detects this.
This operation is done by osgText::readFont3DFile() which unsure the filename have .text3d as extension.
This is totaly transparent for user, and backward compatible.

BTW, I fix the bug about the Normal of 3D text. Currently, the front and wall face have
the same normal (0,0,1) in the Text3D object coordinate. Now the wall face have its own
normal array computed by the plugin.

BTW 2, I implement
- void Text3D::accept(osg::Drawable::ConstAttributeFunctor?& af) const
- void Text3D::accept(osg::PrimitiveFunctor?& pf) const
so now statistics are well reported.
"

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