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

Revision 13041, 27.9 kB (checked in by robert, 2 years ago)

Ran script to remove trailing spaces and tabs

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