root/OpenSceneGraph/trunk/examples/osgtext3D/TextNode.cpp @ 12292

Revision 12292, 8.3 kB (checked in by robert, 3 years ago)

Ran svn propset -R svn:eol-style native . on the OpenSceneGraph

  • Property svn:eol-style set to native
Line 
1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2010 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 "TextNode.h"
15#include "../../src/osgText/GlyphGeometry.h"
16
17#include <osg/PositionAttitudeTransform>
18#include <osg/Geode>
19#include <osgUtil/SmoothingVisitor>
20
21#include <osg/io_utils>
22
23using namespace osgText;
24
25/////////////////////////////////////////////////////////////////////////////////////////
26//
27// Layout
28//
29Layout::Layout()
30{
31}
32
33Layout::Layout(const Layout& layout, const osg::CopyOp& copyop):
34    osg::Object(layout,copyop)
35{
36}
37
38osg::ref_ptr<Layout>& Layout::getDefaultLayout()
39{
40    static OpenThreads::Mutex s_DefaultLayoutMutex;
41    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_DefaultLayoutMutex);
42
43    static osg::ref_ptr<Layout> s_defaultLayout = new Layout;
44    return s_defaultLayout;
45}
46
47void Layout::layout(TextNode& text) const
48{
49    OSG_NOTICE<<"Layout::layout"<<std::endl;
50
51    Font* font = text.getActiveFont();
52    Style* style = text.getActiveStyle();
53    TextTechnique* technique = text.getTextTechnique();
54    const String& str = text.getText();
55
56    if (!text.getTextTechnique())
57    {
58        OSG_NOTICE<<"Warning: no TextTechnique assigned to Layout"<<std::endl;
59        return;
60    }
61
62    osg::Vec3 pos(0.0f,0.0f,0.0f);
63    float characterSize = text.getCharacterSize();
64    osg::Vec3 size(characterSize, characterSize, 0.0);
65    if (style)
66    {
67        size.y() = characterSize;
68        size.z() = characterSize;
69    }
70
71
72    osgText::FontResolution resolution(32,32);
73    if (style)
74    {
75        resolution.first = static_cast<unsigned int>(static_cast<float>(resolution.first)*style->getSampleDensity());
76        resolution.second = static_cast<unsigned int>(static_cast<float>(resolution.second)*style->getSampleDensity());
77    }
78
79    float characterWidthScale = 1.0f;
80    float characterHeightScale = 1.0f;
81
82    bool textIs3D = (style && style->getThicknessRatio()!=0.0);
83    if (!textIs3D)
84    {
85        characterWidthScale = 1.0f/static_cast<float>(resolution.first);
86        characterHeightScale = 1.0f/static_cast<float>(resolution.second);
87    }
88
89    osgText::KerningType kerningType = osgText::KERNING_DEFAULT;
90
91    technique->start();
92
93    unsigned int previousCharcode = 0;
94    for(unsigned int i=0; i<str.size(); ++i)
95    {
96        unsigned int charcode = str[i];
97
98        if (size.z()==0.0f)
99        {
100            osgText::Glyph* glyph = font->getGlyph(resolution, charcode);
101            if (glyph)
102            {
103                technique->addCharacter(pos, size, glyph, style);
104                pos += osg::Vec3(size.x()*(glyph->getHorizontalAdvance()*characterWidthScale), 0.0f ,0.0f);
105            }
106        }
107        else
108        {
109            osgText::Glyph3D* glyph = font->getGlyph3D(charcode);
110            OSG_NOTICE<<"pos = "<<pos<<", charcode="<<charcode<<", glyph="<<glyph<< std::endl;
111            if (glyph)
112            {
113                osg::Vec3 local_scale( size );
114                technique->addCharacter(pos, local_scale, glyph, style);
115                pos += osg::Vec3(size.x()*glyph->getWidth(), 0.0f ,0.0f);
116            }
117        }
118
119        if (previousCharcode!=0 && charcode!=0)
120        {
121            osg::Vec2 offset = font->getKerning(previousCharcode, charcode, kerningType);
122            OSG_NOTICE<<"  offset = "<<offset<< std::endl;
123            pos.x() += offset.x();
124            pos.y() += offset.y();
125        }
126
127        previousCharcode = charcode;
128    }
129
130    technique->finish();
131}
132
133
134/////////////////////////////////////////////////////////////////////////////////////////
135//
136// TextTechnique
137//
138TextTechnique::TextTechnique():
139    _textNode(0)
140{
141}
142
143
144TextTechnique::TextTechnique(const TextTechnique& technique, const osg::CopyOp& copyop):
145    osg::Object(technique, copyop),
146    _textNode(0)
147{
148}
149
150osg::ref_ptr<TextTechnique>& TextTechnique::getDefaultTextTechinque()
151{
152    static OpenThreads::Mutex s_DefaultTextTechniqueMutex;
153    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_DefaultTextTechniqueMutex);
154
155    static osg::ref_ptr<TextTechnique> s_defaultTextTechnique = new TextTechnique;
156    return s_defaultTextTechnique;
157}
158
159void TextTechnique::start()
160{
161    OSG_NOTICE<<"TextTechnique::start()"<<std::endl;
162}
163
164void TextTechnique::addCharacter(const osg::Vec3& position, const osg::Vec3& size, Glyph* glyph, Style* style)
165{
166    OSG_NOTICE<<"TextTechnique::addCharacter 2D("<<position<<", "<<size<<", "<<glyph<<", "<<style<<")"<<std::endl;
167}
168
169void TextTechnique::addCharacter(const osg::Vec3& position, const osg::Vec3& size, Glyph3D* glyph, Style* style)
170{
171    OSG_NOTICE<<"TextTechnique::addCharacter 3D("<<position<<", "<<size<<", "<<glyph<<", "<<style<<")"<<std::endl;
172
173    osg::ref_ptr<osg::PositionAttitudeTransform> transform = new osg::PositionAttitudeTransform;
174    transform->setPosition(position);
175    transform->setAttitude(osg::Quat(osg::inDegrees(90.0),osg::Vec3d(1.0,0.0,0.0)));
176    transform->setScale(size);
177
178    osg::ref_ptr<osg::Geode> geode = new osg::Geode;
179
180    const Bevel* bevel = style ? style->getBevel() : 0;
181    bool outline = style ? style->getOutlineRatio()>0.0f : false;
182    float width = style->getThicknessRatio();
183    float creaseAngle = 30.0f;
184    bool smooth = true;
185
186    if (bevel)
187    {
188        float thickness = bevel->getBevelThickness();
189
190        osg::ref_ptr<osg::Geometry> glyphGeometry = osgText::computeGlyphGeometry(glyph, thickness, width);
191        osg::ref_ptr<osg::Geometry> textGeometry = osgText::computeTextGeometry(glyphGeometry.get(), *bevel, width);
192        osg::ref_ptr<osg::Geometry> shellGeometry = outline ? osgText::computeShellGeometry(glyphGeometry.get(), *bevel, width) : 0;
193        if (textGeometry.valid()) geode->addDrawable(textGeometry.get());
194        if (shellGeometry.valid()) geode->addDrawable(shellGeometry.get());
195
196        // create the normals
197        if (smooth && textGeometry.valid())
198        {
199            osgUtil::SmoothingVisitor::smooth(*textGeometry, osg::DegreesToRadians(creaseAngle));
200        }
201    }
202    else
203    {
204        osg::ref_ptr<osg::Geometry> textGeometry = osgText::computeTextGeometry(glyph, width);
205        if (textGeometry.valid()) geode->addDrawable(textGeometry.get());
206
207        // create the normals
208        if (smooth && textGeometry.valid())
209        {
210            osgUtil::SmoothingVisitor::smooth(*textGeometry, osg::DegreesToRadians(creaseAngle));
211        }
212    }
213
214    transform->addChild(geode.get());
215
216    _textNode->addChild(transform.get());
217
218    transform->getOrCreateStateSet()->setMode(GL_NORMALIZE, osg::StateAttribute::ON);
219
220}
221
222void TextTechnique::finish()
223{
224    OSG_NOTICE<<"TextTechnique::finish()"<<std::endl;
225}
226
227void TextTechnique::traverse(osg::NodeVisitor& nv)
228{
229    // OSG_NOTICE<<"TextTechnique::traverse()"<<std::endl;
230    if (_textNode) _textNode->osg::Group::traverse(nv);
231}
232
233/////////////////////////////////////////////////////////////////////////////////////////
234//
235// TextNode
236//
237TextNode::TextNode():
238        _characterSize(1.0f)
239{
240}
241
242
243TextNode::TextNode(const TextNode& text, const osg::CopyOp& copyop):
244    osg::Group(text, copyop)
245{
246}
247
248TextNode::~TextNode()
249{
250    setTextTechnique(0);
251}
252
253void TextNode::traverse(osg::NodeVisitor& nv)
254{
255    if (_technique.valid())
256    {
257        _technique->traverse(nv);
258    }
259    else
260    {
261        Group::traverse(nv);
262    }
263}
264
265void TextNode::setTextTechnique(TextTechnique* technique)
266{
267    if (_technique==technique) return;
268
269    if (_technique.valid()) _technique->setTextNode(0);
270
271    if (TextTechnique::getDefaultTextTechinque()==technique)
272    {
273        OSG_NOTICE<<"Warning: Attempt to assign DefaultTextTechnique() prototype to TextNode::setTextTechnique(..), assigning a clone() of it instead."<<std::endl;
274        technique = new TextTechnique(*TextTechnique::getDefaultTextTechinque());
275    }
276
277    _technique = technique;
278
279    if (_technique.valid()) _technique->setTextNode(this);
280}
281
282
283void TextNode::update()
284{
285    getActiveLayout()->layout(*this);
286}
287
288void TextNode::setText(const std::string& str)
289{
290    _string.set(str);
291}
Note: See TracBrowser for help on using the browser.