root/OpenSceneGraph/trunk/include/osgText/Text @ 13041

Revision 13041, 18.3 kB (checked in by robert, 3 years ago)

Ran script to remove trailing spaces and tabs

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
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#ifndef OSGTEXT_TEXT
15#define OSGTEXT_TEXT 1
16
17
18#include <osg/Drawable>
19#include <osg/Quat>
20
21#include <osgText/TextBase>
22#include <osgText/Font>
23
24namespace osgText {
25
26
27class OSGTEXT_EXPORT Text : public osgText::TextBase
28{
29public:
30
31    Text();
32    Text(const Text& text,const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY);
33
34    virtual osg::Object* cloneType() const { return new Text(); }
35    virtual osg::Object* clone(const osg::CopyOp& copyop) const { return new Text(*this,copyop); }
36    virtual bool isSameKindAs(const osg::Object* obj) const { return dynamic_cast<const Text*>(obj)!=NULL; }
37    virtual const char* className() const { return "Text"; }
38    virtual const char* libraryName() const { return "osgText"; }
39
40    virtual void setFont(Font* font=0) { setFont(osg::ref_ptr<Font>(font)); };
41
42    /** Set the Font to use to render the text.*/
43    virtual void setFont(osg::ref_ptr<Font> font);
44
45    /** Set the font, loaded from the specified front file, to use to render the text,
46      * setFont("") sets the use of the default font.
47      * See the osgText::readFontFile function for how the font file will be located. */
48    virtual void setFont(const std::string& fontfile) { TextBase::setFont(fontfile); }
49
50    /**
51     * Turns off writing to the depth buffer when rendering text. This only affects text
52     * with no backdrop or text using the DELAYED_DEPTH_WRITES implementation, since
53     * the other backdrop implementations are really only useful for backwards
54     * compatibility and are not worth updating to utilize this flag.
55     */
56    void setEnableDepthWrites(bool enable) { _enableDepthWrites = enable; }
57    bool getEnableDepthWrites() const { return _enableDepthWrites; }
58
59
60    enum BackdropType
61    {
62        DROP_SHADOW_BOTTOM_RIGHT = 0,  // usually the type of shadow you see
63        DROP_SHADOW_CENTER_RIGHT,
64        DROP_SHADOW_TOP_RIGHT,
65        DROP_SHADOW_BOTTOM_CENTER,
66        DROP_SHADOW_TOP_CENTER,
67        DROP_SHADOW_BOTTOM_LEFT,
68        DROP_SHADOW_CENTER_LEFT,
69        DROP_SHADOW_TOP_LEFT,
70        OUTLINE,
71        NONE
72    };
73
74    enum BackdropImplementation
75    {
76        /* POLYGON_OFFSET:
77         * This uses glPolygonOffset to draw the text multiple times to
78         * create the drop-shadow and outline effects. glPolygonOffset
79         * is used to prevent z-fighting of the overlapping text.
80         * This probably should have been the best option, but all the ATI
81         * cards we have encountered so far have serious problems with this.
82         * We see little white holes/artifacts in the rendered glyph textures
83         * which move around depending on the viewing angle. For moving text,
84         * the moving holes give an extremely unpleasant flickering effect.
85         * Pumping up the "units" parameter in glPolygonOffset can minimize
86         * this problem, but two other bad side-effects occur if you do this.
87         * First, high values will cause problems with clipping, particularly
88         * when there are objects behind the text. The drop-shadows or outline
89         * may be culled because their computed offset is behind the object or
90         * z-far plane. Second, there is an additional problem associated with
91         * the Z-slope. High values can make large chunks of the backdrop
92         * suddenly disappear. This can be reduced by the "factor" parameter.
93         * Making the "factor" value small, can help, but experimentally, we've
94         * found that it creates a new, different kind of z-fighting problem.
95         * So there is no perfect solution. With units, you trade off the 'holes'
96         * for the large-section clipping.
97         * Experimentally, we have found units values from 150-512 to be tolerable
98         * to acceptable with respect to the 'holes'. A factor of .1 seems to
99         * bring down the large clipping problem without creating a new z-fighting
100         * problem.
101         * (You can experiment with these numbers by playing with the
102         * osg:PolygonOffset multipliers which this backend tries to respect.)
103         *
104         * If ATI ever fixes their cards/drivers, then this might become the
105         * best option.*/
106        POLYGON_OFFSET = 0,
107
108        /* NO_DEPTH_BUFFER
109         * Instead of using glPolygonOffset to prevent z-fighting, this mode
110         * just disables the depth buffer when rendering the text. This allows
111         * the text to be rendered without any z-fighting. The downside to this
112         * mode is that render order begins to matter and the text will not
113         * necessarily correctly appear above or behind other objects in the
114         * scene based on depth values.
115         * This mode is best for text that only needs to be ontop and
116         * not obscured by any objects.*/
117        NO_DEPTH_BUFFER,
118
119        /* DEPTH_RANGE
120         * This mode is inspired by Paul Martz's OpenGL FAQ, item 13.050.
121         * This uses glDepthRange as a substitute for glPolygonOffset.
122         * Strangely, experiments on ATI cards seem to produce cleaner results
123         * than when using glPolygonOffset. The trade-off for this is that the
124         * backdrop still may be placed too far back and might be culled by objects
125         * directly behind the object or by the far z-plane. If ATI ever fixes
126         * the glPolygonOffset problem, polygon offset is probably a slightly
127         * better solution because you can use smaller offsets. But with the
128         * current ATI problem, this option may be preferable.*/
129        DEPTH_RANGE,
130        /* STENCIL_BUFFER
131         * (Assuming the backend is written correctly,) the Stencil Buffer is
132         * the most "correct" and reliable way of producing backdrop text.
133         * The stencil buffer is a multipass system that allows writing to the
134         * same z-values without needing to resort to offsets. This implementation
135         * should not have any of the problems associated with the 3 previous
136         * implementations. But the trade-off for this mode is that without
137         * hardware acceleration for the stencil buffer, rendering will be
138         * extremely slow. (There is also potentially more overhead for this
139         * algorithm so it could be slower than the other implementations.
140         * Benchmarking would be required to determine if the speed differences
141         * are significant on your particular hardware.) This mode is best for
142         * when quality is important and stencil buffer hardware acceleration
143         * is available.*/
144        STENCIL_BUFFER,
145
146        /* DELAYED_DEPTH_WRITES
147         * This mode renders all text with depth writes turned off, then
148         * again with depth writes on, but with the color buffer disabled.
149         * This should render text accurately for all graphics cards. The
150         * only downside is the additional pass to render to the depth
151         * buffer. But if you don't need the depth buffer updated for
152         * your, this extra pass can be disabled by calling
153         * enableDepthWrites(false).*/
154        DELAYED_DEPTH_WRITES
155    };
156
157    /**
158     * BackdropType gives you a background shadow text behind your regular
159     * text. This helps give text extra contrast which can be useful when
160     * placing text against noisy backgrounds.
161     * The color of the background shadow text is specified by setBackdropColor().
162     * DROP_SHADOW_BOTTOM_RIGHT will draw backdrop text to the right and down of
163     * the normal text. Other DROW_SHADOW_* modes do the same for their repective directions.
164     * OUTLINE will draw backdrop text so that it appears the text has an outline
165     * or border around the normal text. This mode is particularly useful against
166     * really noisy backgrounds that may put text on top of things that have
167     * all types of colors which you don't have control over.
168     * Some real world examples of this general technique in use that I know of
169     * are Google Earth, Sid Meier's Pirates (2004 Remake), and Star Control 2 (PC 1993).
170     * The default is NONE.
171     */
172    void setBackdropType(BackdropType type);
173
174    BackdropType getBackdropType() const { return _backdropType; }
175
176    /**
177     * Sets the amount text is offset to create the backdrop/shadow effect.
178     * Set the value too high and for example, in OUTLINE mode you will get a "Brady Bunch"
179     * effect where you see duplicates of the text in a 3x3 grid.
180     * Set the value too small and you won't see anything.
181     * The values represent percentages. 1.0 means 100% so a value of 1.0
182     * in DROW_SHADOW_LEFT_CENTER mode would cause each glyph to be echoed
183     * next to it self. So the letter 'e' might look like 'ee'.
184     * Good values tend to be in the 0.03 to 0.10 range (but will be subject
185     * to your specific font and display characteristics).
186     * Note that the text bounding boxes are updated to include backdrop offsets.
187     * However, other metric information such as getCharacterHeight() are unaffected
188     * by this. This means that individual glyph spacing (kerning?) are unchanged
189     * even when this mode is used.
190     * The default is 0.07 (7% offset).
191     */
192    void setBackdropOffset(float offset = 0.07f);
193    /**
194     * This overloaded version lets you specify the offset for the horizontal
195     * and vertical components separately.
196     */
197    void setBackdropOffset(float horizontal, float vertical);
198
199    float getBackdropHorizontalOffset() const { return _backdropHorizontalOffset; }
200
201    float getBackdropVerticalOffset() const { return _backdropVerticalOffset; }
202
203    /**
204     * This specifies the color of the backdrop text.
205     * The default is black.
206     */
207    void setBackdropColor(const osg::Vec4& color);
208
209    const osg::Vec4& getBackdropColor() const { return _backdropColor; }
210
211    /**
212     * This specifies the underlying backdrop rendering implementation.
213     * Unfortunately, at this time, there is no "perfect" rendering solution
214     * so this function is provided to let you 'pick your poison'. Each
215     * implementation has trade-offs. See BackdropImplementation enum
216     * docs for details.*/
217     void setBackdropImplementation(BackdropImplementation implementation);
218
219     BackdropImplementation getBackdropImplementation() const { return _backdropImplementation; }
220
221
222
223    enum ColorGradientMode
224    {
225        SOLID = 0, // a.k.a. ColorGradients off
226        PER_CHARACTER,
227        OVERALL
228    };
229
230    /**
231     * This sets different types of text coloring modes.
232     * When the coloring mode is not set to SOLID, the
233     * colors specified in setColorGradientCorners() determine
234     * the colors for the text.
235     * When the gradient mode is OVERALL, the coloring scheme
236     * attempts to approximate the effect as if the entire text box/region
237     * were a single polygon and you had applied colors to each of the four
238     * corners with GL_SMOOTH enabled. In this mode, OpenGL interpolates
239     * the colors across the polygon, and this is what OVERALL tries to
240     * emulate. This can be used to give nice embellishments on things
241     * like logos and names.
242     * PER_CHARACTER is similar to OVERALL except that it applies the
243     * color interpolation to the four corners of each character instead
244     * of across the overall text box.
245     * The default is SOLID (a.k.a. off).
246     */
247    void setColorGradientMode(ColorGradientMode mode);
248
249    ColorGradientMode getColorGradientMode() const { return _colorGradientMode; }
250
251    /**
252     * Used only for gradient mode, let's you specify the colors of the 4 corners.
253     * If ColorGradients are off, these values are ignored (and the value from setColor()
254     * is the only one that is relevant.
255     */
256    void setColorGradientCorners(const osg::Vec4& topLeft, const osg::Vec4& bottomLeft, const osg::Vec4& bottomRight, const osg::Vec4& topRight);
257
258    const osg::Vec4& getColorGradientTopLeft() const { return _colorGradientTopLeft; }
259    const osg::Vec4& getColorGradientBottomLeft() const { return _colorGradientBottomLeft; }
260    const osg::Vec4& getColorGradientBottomRight() const { return _colorGradientBottomRight; }
261    const osg::Vec4& getColorGradientTopRight() const { return _colorGradientTopRight; }
262
263
264
265    /** Draw the text.*/
266    virtual void drawImplementation(osg::RenderInfo& renderInfo) const;
267
268    /** return false, osgText::Text does not support accept(AttributeFunctor&).*/
269    virtual bool supports(const osg::Drawable::AttributeFunctor&) const { return false; }
270
271    /** return true, osgText::Text does support accept(ConstAttributeFunctor&).*/
272    virtual bool supports(const osg::Drawable::ConstAttributeFunctor&) const { return true; }
273
274    /** accept an ConstAttributeFunctor and call its methods to tell it about the internal attributes that this Drawable has.*/
275    virtual void accept(osg::Drawable::ConstAttributeFunctor& af) const;
276
277    /** return true, osgText::Text does support accept(PrimitiveFunctor&) .*/
278    virtual bool supports(const osg::PrimitiveFunctor&) const { return true; }
279
280    /** accept a PrimtiveFunctor and call its methods to tell it about the internal primitives that this Drawable has.*/
281    virtual void accept(osg::PrimitiveFunctor& pf) const;
282
283
284    /** Set whether to use a mutex to ensure ref() and unref() are thread safe.*/
285    virtual void setThreadSafeRefUnref(bool threadSafe);
286
287    /** Resize any per context GLObject buffers to specified size. */
288    virtual void resizeGLObjectBuffers(unsigned int maxSize);
289
290    /** If State is non-zero, this function releases OpenGL objects for
291      * the specified graphics context. Otherwise, releases OpenGL objexts
292      * for all graphics contexts. */
293    virtual void releaseGLObjects(osg::State* state=0) const;
294
295public:
296
297    // internal structures, variable and methods used for rendering of characters.
298    struct OSGTEXT_EXPORT GlyphQuads
299    {
300        typedef std::vector<Glyph*> Glyphs;
301        typedef std::vector<unsigned int> LineNumbers;
302        typedef std::vector<osg::Vec2> Coords2;
303        typedef std::vector<osg::Vec3> Coords3;
304        typedef std::vector<osg::Vec2> TexCoords;
305        typedef std::vector<osg::Vec4> ColorCoords;
306
307        Glyphs                          _glyphs;
308        Coords2                         _coords;
309        osg::buffered_object<Coords3>   _transformedCoords;
310        TexCoords                       _texcoords;
311        LineNumbers                     _lineNumbers;
312
313        osg::buffered_object<Coords3>   _transformedBackdropCoords[8];
314        ColorCoords    _colorCoords;
315
316        Glyphs getGlyphs() { return _glyphs; }
317        const Glyphs getGlyphs() const { return _glyphs; }
318
319        Coords2& getCoords() { return _coords; }
320        const Coords2& getCoords() const { return _coords; }
321
322        Coords3& getTransformedCoords(unsigned int contexID) { return _transformedCoords[contexID]; }
323        const Coords3& getTransformedCoords(unsigned int contexID) const { return _transformedCoords[contexID]; }
324
325        TexCoords& getTexCoords() { return _texcoords; }
326        const TexCoords& getTexCoords() const { return _texcoords; }
327
328        LineNumbers& getLineNumbers() { return _lineNumbers; }
329        const LineNumbers& getLineNumbers() const { return _lineNumbers; }
330    };
331
332    typedef std::map<osg::ref_ptr<GlyphTexture>,GlyphQuads> TextureGlyphQuadMap;
333
334    /** Direct Access to GlyphQuads */
335    const GlyphQuads* getGlyphQuads(GlyphTexture* texture) const
336    {
337        TextureGlyphQuadMap::iterator itGlyphQuad = _textureGlyphQuadMap.find(texture);
338        if (itGlyphQuad == _textureGlyphQuadMap.end()) return NULL;
339
340        return &itGlyphQuad->second;
341    }
342
343    const TextureGlyphQuadMap& getTextureGlyphQuadMap() const
344    {
345        return _textureGlyphQuadMap;
346    }
347
348
349protected:
350
351    virtual ~Text();
352
353    Font* getActiveFont();
354    const Font* getActiveFont() const;
355
356    String::iterator computeLastCharacterOnLine(osg::Vec2& cursor, String::iterator first,String::iterator last);
357
358    // members which have public access.
359
360    // iternal map used for rendering. Set up by the computeGlyphRepresentation() method.
361    mutable TextureGlyphQuadMap            _textureGlyphQuadMap;
362
363    void computeGlyphRepresentation();
364
365    // internal caches of the positioning of the text.
366
367    bool computeAverageGlyphWidthAndHeight(float& avg_width, float& avg_height) const;
368
369    virtual void computePositions(unsigned int contextID) const;
370
371    void computeBackdropPositions(unsigned int contextID) const;
372    void computeBackdropBoundingBox() const;
373    void computeBoundingBoxMargin() const;
374
375    void computeColorGradients() const;
376    void computeColorGradientsOverall() const;
377    void computeColorGradientsPerCharacter() const;
378
379    void drawImplementation(osg::State& state, const osg::Vec4& colorMultiplier) const;
380    void drawForegroundText(osg::State& state, const GlyphQuads& glyphquad, const osg::Vec4& colorMultiplier) const;
381    void drawTextWithBackdrop(osg::State& state, const osg::Vec4& colorMultiplier) const;
382    void renderOnlyForegroundText(osg::State& state, const osg::Vec4& colorMultiplier) const;
383    void renderWithPolygonOffset(osg::State& state, const osg::Vec4& colorMultiplier) const;
384    void renderWithNoDepthBuffer(osg::State& state, const osg::Vec4& colorMultiplier) const;
385    void renderWithDepthRange(osg::State& state, const osg::Vec4& colorMultiplier) const;
386    void renderWithStencilBuffer(osg::State& state, const osg::Vec4& colorMultiplier) const;
387    void renderWithDelayedDepthWrites(osg::State& state, const osg::Vec4& colorMultiplier) const;
388
389    bool _enableDepthWrites;
390
391    BackdropType _backdropType;
392    BackdropImplementation _backdropImplementation;
393
394    float _backdropHorizontalOffset;
395    float _backdropVerticalOffset;
396    osg::Vec4 _backdropColor;
397
398    ColorGradientMode _colorGradientMode;
399    osg::Vec4 _colorGradientTopLeft;
400    osg::Vec4 _colorGradientBottomLeft;
401    osg::Vec4 _colorGradientBottomRight;
402    osg::Vec4 _colorGradientTopRight;
403
404    // Helper function for color interpolation
405    float bilinearInterpolate(float x1, float x2, float y1, float y2, float x, float y, float q11, float q12, float q21, float q22) const;
406};
407
408}
409
410
411#endif
Note: See TracBrowser for help on using the browser.