TextNode.hh 12 KB
Newer Older
Jan Möbius's avatar
Jan Möbius committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
/*===========================================================================*\
 *                                                                           *
 *                              OpenFlipper                                  *
 *           Copyright (c) 2001-2015, RWTH-Aachen University                 *
 *           Department of Computer Graphics and Multimedia                  *
 *                          All rights reserved.                             *
 *                            www.openflipper.org                            *
 *                                                                           *
 *---------------------------------------------------------------------------*
 * This file is part of OpenFlipper.                                         *
 *---------------------------------------------------------------------------*
 *                                                                           *
 * Redistribution and use in source and binary forms, with or without        *
 * modification, are permitted provided that the following conditions        *
 * are met:                                                                  *
 *                                                                           *
 * 1. Redistributions of source code must retain the above copyright notice, *
 *    this list of conditions and the following disclaimer.                  *
 *                                                                           *
 * 2. Redistributions in binary form must reproduce the above copyright      *
 *    notice, this list of conditions and the following disclaimer in the    *
 *    documentation and/or other materials provided with the distribution.   *
 *                                                                           *
 * 3. Neither the name of the copyright holder nor the names of its          *
 *    contributors may be used to endorse or promote products derived from   *
 *    this software without specific prior written permission.               *
 *                                                                           *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS       *
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A           *
 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,  *
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,       *
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR        *
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF    *
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING      *
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS        *
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.              *
 *                                                                           *
\*===========================================================================*/

/*===========================================================================*\
 *                                                                           *
 *   $Revision$                                                      *
 *   $Author$                                                          *
 *   $Date$                   *
 *                                                                           *
\*===========================================================================*/




//=============================================================================
//
//  CLASS PointNode
//
//=============================================================================

#ifndef ACG_TEXTNODE_HH
#define ACG_TEXTNODE_HH


//== INCLUDES =================================================================

#include "BaseNode.hh"
#include "TransformNode.hh"
#include "DrawModes.hh"
#include <ACG/GL/IRenderer.hh>
#include <ACG/GL/VertexDeclaration.hh>
#include <vector>
#include <QFont>
#include <QFontMetrics>
#include <QImage>
#include <QPainter>
#include <QGLWidget>

//== NAMESPACES ===============================================================

namespace ACG {
namespace SceneGraph {

//== CLASS DEFINITION =========================================================



/** \class TextNode TextNode.hh <ACG/Scenegraph/TextNode.hh>
 *  TextNode can be used to display a string on quads in OpenGL. This string can be set with
 * 	setText(std::string _text). A TextNode can be attached to a parent node by using the function
 * 	BaseObjectData::addAdditionalNode. The quads can then be set to align to the parent (OBJECT_ALIGNED)
 *	via the setRenderingMode(TextMode _textMode) function. Alternatively the quads can be aligned
 *	to the screen (SCREEN_ALIGNED). The font that is used to display text on the screen
 *  can be set with the setFont(const QFont& _font) function. Finally the quads can be scaled
 * 	via the setSize(double _size) function.
**/

class ACGDLLEXPORT TextNode : public BaseNode
{
public:

  enum TextMode {
    SCREEN_ALIGNED, /// Text will always stay parallel to screen
    SCREEN_ALIGNED_STATIC_SIZE, /// Text will always stay parallel to screen (like SCREEN_ALIGNED) and text has static size, independent of the camera position
    OBJECT_ALIGNED  /// Text will be transformed and projected by Modelview and projection matrix
  };

  /** default constructor
   * @param _parent Define the parent Node this node gets attached to
   * @param _name Name of this Node
   * @param _textMode Define the text rendering style ( see TextNode::TextMode )
   * @param _alwaysOnTop Draw text on top of everything else?
   */
  TextNode( BaseNode*     _parent=0,
113
            const std::string&  _name="<TextNode>",
Jan Möbius's avatar
Jan Möbius committed
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
            TextMode     _textMode = SCREEN_ALIGNED,
            bool         _alwaysOnTop = false);

  /// destructor
  ~TextNode();

  /// static name of this class
  ACG_CLASSNAME(TextNode);

  /// return available draw modes
  DrawModes::DrawMode  availableDrawModes() const;

  /// update bounding box
  void boundingBox(Vec3d& _bbMin, Vec3d& _bbMax);

  /// draw Text
  void draw(GLState& _state, const DrawModes::DrawMode& _drawMode);

  /// set texture and drawing states
  void enter(GLState& _state, const DrawModes::DrawMode& _drawmode);
134
  void enterCompat(GLState& _state, const DrawModes::DrawMode& _drawmode);
Jan Möbius's avatar
Jan Möbius committed
135
136
137

  /// restore texture and drawing states
  void leave(GLState& _state, const DrawModes::DrawMode& _drawmode);
138
  void leaveCompat(GLState& _state, const DrawModes::DrawMode& _drawmode);
Jan Möbius's avatar
Jan Möbius committed
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307

  /// set RenderObject for Shader pipeline renderer
  void getRenderObjects(ACG::IRenderer* _renderer, ACG::GLState&  _state , const ACG::SceneGraph::DrawModes::DrawMode&  _drawMode , const ACG::SceneGraph::Material* _mat);

  /** Set the rendering mode ( see TextNode::TextMode )
   */
  void setRenderingMode(TextMode _textMode);

  /// draw the text always on top
  void setAlwaysOnTop(bool _alwaysOnTop);

  /// returns wheter always on top is setted or not
  bool alwaysOnTop();

  /// returns the rendering mode (SCREEN_ALIGNED or OBJECT_ALIGNED)
  TextMode renderingMode();

  /// sets the string that will be rendered
  void setText(std::string _text);

  /// sets the size by which the quads displaying the text will be scaled
  void setSize(const double _size);

  /// sets the pixelsize of the text (only available for the SCREEN_ALIGNED_STATIC_SIZE mode and only works, if scaling is 1)
  void setPixelSize(const unsigned int _size);

  /// sets the font to be used for generating a texture with most characters of the chosen font
  void setFont(const QFont& _font);

  /** \brief returns the scaling factor for screen aligned text the text. returns 0, if textmode is not SCREEN_ALIGNED_STATIC_SIZE
   *
   * screen aligned static size text will be scaled up/down in 3d space to achieve the static size in screen space
   * lastScale returns the last scaling factor where the text was multiplied, to compute e.g. a distance
   * which is also static in screen space
   */
  float lastScale() {return lastScale_;};

protected:
  /**
   * Generates a texture by drawing most characters into one texture.
   * This texture is then used to draw single characters onto quads
   */
  static void updateFont();

private:
  /// returns the nearest greater power of 2 to num
  static quint32 nearestPowerOfTwo(quint32 num);

  /**
   * generates a quad for each character in #text_ and also
   * calculates the texture coordinates for each quad's character
   */
  void updateVBO();

  /// binds #vbo_ and sets the necessary OpenGL states
  void bindVBO();

  /// unbinds #vbo_
  void unbindVBO();

  /// modifies _state so that the modelviewmatrix will be screenaligned. remember to call "_state.pop_modelview_matrix();" twice
  void applyScreenAligned(GLState &_state);

  /**
   * Creates a map #charToIndex_ from most characters to an incrementing set of indices.
   * These indices are used to create the texture coordinates in updateVBO().
   */
  static std::map< char, std::pair<unsigned int, unsigned int> > createMap();

private:

  /// scaling factor by which the quads in #vbo_ are scaled
  double size_;

  /// pixelSize of the text for the SCREEN_ALIGNED_STATIC_SIZE mode
  unsigned pixelSize_;

  /// text to be displayed on quads in #vbo_
  std::string text_;

  /// current display mode of #text_ (SCREEN_ALIGNED, SCREEN_ALIGNED_STATIC_SIZE or OBJECT_ALIGNED)
  TextMode textMode_;

  /**
   * handle to the vertex buffer object, containing the quads on which the characters in
   * #text_ are rendered
   */
  GLuint vbo_;

  /// buffer of vertex coordinates and texture coordinates of the quads
  std::vector<GLfloat> vertexBuffer_;
  size_t oldVboSize_;

  /// stores if GL_BLEND was enabled on entering TextNode
  bool blendEnabled_;

  /// stores if GL_TEXTURE_2D was enabled on entering TextNode
  bool texture2dEnabled_;

  /// stores if GL_CULL_FACE was enabled on entering TextNode
  bool cullFaceEnabled_;

  /// stores if GL_DEPTH_TEST was enabled on entering TextNode
  bool depthEnabled_;

  /// stores if text should be drawn always on top
  bool alwaysOnTop_;

  /// stores if the alpha test was enabled
  bool alphaTest_;

  /// stores the alpha value used for alpha test
  float alphaTestValue_;

  /// stores alpha test comparison function
  GLenum alphaTestFunc_;

  /// stores the sfactor parameter of glBlendFunc on entering TextNode
  GLint blendSrc_;

  /// stores the dfactor parameter of glBlendFunc on entering TextNode
  GLint blendDest_;

  /// stores the vertex declaration
  ACG::VertexDeclaration vertexDecl_;

  /// stores the last scaling factor the text computed to SCREEN_ALIGNED_STATIC_SIZE
  float lastScale_;

  /// maps most readable characters to indices for texture coordinate calculation in updateVBO()
  static std::map< char, std::pair<unsigned int, unsigned int> > charToIndex_;

  /// font that is used to generate the texture in updateFont()
  static QFont qfont_;

  /// handle for the texture into which characters from #qfont_ are painted in updateFont()
  static GLuint texture_;

  /// width of the generated texture
  static int imageWidth_;

  /// height of the generated texture
  static int imageHeight_;

  /// max width of qfont
  static qreal maxFontWidth_;

  /// number of characters that are drawn into the texture
  static const int numberOfChars_ = 94;

  /// number of rows of characters in the texture
  static const unsigned int rows_ = 10;

  /// number of columns of characters in the texture
  static const unsigned int columns_ = 10;

  /// this is used to ensure that the texture is only generated once when necessary
  static bool initialised_;

  /// color that is used to draw the characters into the texture in updateFont()
  static QColor color_;
};

//=============================================================================
} // namespace SceneGraph
} // namespace ACG
//=============================================================================
#endif // ACG_TEXTNODE_HH defined
//=============================================================================