~baltix/+junk/irrlicht-test

« back to all changes in this revision

Viewing changes to source/Irrlicht/CTextSceneNode.cpp

  • Committer: Mantas Kriaučiūnas
  • Date: 2011-07-18 13:06:25 UTC
  • Revision ID: mantas@akl.lt-20110718130625-c5pvifp61e7kj1ol
Included whole irrlicht SVN libraries to work around launchpad recipe issue with quilt, see https://answers.launchpad.net/launchpad/+question/165193

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright (C) 2002-2011 Nikolaus Gebhardt
 
2
// This file is part of the "Irrlicht Engine".
 
3
// For conditions of distribution and use, see copyright notice in irrlicht.h
 
4
 
 
5
#include "CTextSceneNode.h"
 
6
#include "ISceneManager.h"
 
7
#include "IVideoDriver.h"
 
8
#include "ICameraSceneNode.h"
 
9
#include "IGUISpriteBank.h"
 
10
#include "SMeshBuffer.h"
 
11
#include "os.h"
 
12
 
 
13
 
 
14
namespace irr
 
15
{
 
16
namespace scene
 
17
{
 
18
 
 
19
 
 
20
//! constructor
 
21
CTextSceneNode::CTextSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id,
 
22
                        gui::IGUIFont* font, scene::ISceneCollisionManager* coll,
 
23
                        const core::vector3df& position, const wchar_t* text,
 
24
                        video::SColor color)
 
25
        : ITextSceneNode(parent, mgr, id, position), Text(text), Color(color),
 
26
                Font(font), Coll(coll)
 
27
 
 
28
{
 
29
        #ifdef _DEBUG
 
30
        setDebugName("CTextSceneNode");
 
31
        #endif
 
32
 
 
33
        if (Font)
 
34
                Font->grab();
 
35
 
 
36
        setAutomaticCulling(scene::EAC_OFF);
 
37
}
 
38
 
 
39
//! destructor
 
40
CTextSceneNode::~CTextSceneNode()
 
41
{
 
42
        if (Font)
 
43
                Font->drop();
 
44
}
 
45
 
 
46
void CTextSceneNode::OnRegisterSceneNode()
 
47
{
 
48
        if (IsVisible)
 
49
                SceneManager->registerNodeForRendering(this, ESNRP_TRANSPARENT);
 
50
 
 
51
        ISceneNode::OnRegisterSceneNode();
 
52
}
 
53
 
 
54
//! renders the node.
 
55
void CTextSceneNode::render()
 
56
{
 
57
        if (!Font || !Coll)
 
58
                return;
 
59
 
 
60
        core::position2d<s32> pos = Coll->getScreenCoordinatesFrom3DPosition(getAbsolutePosition(),
 
61
                SceneManager->getActiveCamera());
 
62
 
 
63
        core::rect<s32> r(pos, core::dimension2d<s32>(1,1));
 
64
        Font->draw(Text.c_str(), r, Color, true, true);
 
65
}
 
66
 
 
67
 
 
68
//! returns the axis aligned bounding box of this node
 
69
const core::aabbox3d<f32>& CTextSceneNode::getBoundingBox() const
 
70
{
 
71
        return Box;
 
72
}
 
73
 
 
74
//! sets the text string
 
75
void CTextSceneNode::setText(const wchar_t* text)
 
76
{
 
77
        Text = text;
 
78
}
 
79
 
 
80
 
 
81
//! sets the color of the text
 
82
void CTextSceneNode::setTextColor(video::SColor color)
 
83
{
 
84
        Color = color;
 
85
}
 
86
 
 
87
 
 
88
//!--------------------------------- CBillboardTextSceneNode ----------------------------------------------
 
89
 
 
90
 
 
91
//! constructor
 
92
CBillboardTextSceneNode::CBillboardTextSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id,
 
93
        gui::IGUIFont* font,const wchar_t* text,
 
94
        const core::vector3df& position, const core::dimension2d<f32>& size,
 
95
        video::SColor colorTop,video::SColor shade_bottom )
 
96
: IBillboardTextSceneNode(parent, mgr, id, position),
 
97
        Font(0), ColorTop(colorTop), ColorBottom(shade_bottom), Mesh(0)
 
98
{
 
99
        #ifdef _DEBUG
 
100
        setDebugName("CBillboardTextSceneNode");
 
101
        #endif
 
102
 
 
103
        Material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
 
104
        Material.MaterialTypeParam = 1.f / 255.f;
 
105
        Material.BackfaceCulling = false;
 
106
        Material.Lighting = false;
 
107
        Material.ZBuffer = video::ECFN_LESSEQUAL;
 
108
        Material.ZWriteEnable = false;
 
109
 
 
110
        if (font)
 
111
        {
 
112
                // doesn't support other font types
 
113
                if (font->getType() == gui::EGFT_BITMAP)
 
114
                {
 
115
                        Font = (gui::IGUIFontBitmap*)font;
 
116
                        Font->grab();
 
117
 
 
118
                        // mesh with one buffer per texture
 
119
                        Mesh = new SMesh();
 
120
                        for (u32 i=0; i<Font->getSpriteBank()->getTextureCount(); ++i)
 
121
                        {
 
122
                                SMeshBuffer *mb = new SMeshBuffer();
 
123
                                mb->Material = Material;
 
124
                                mb->Material.setTexture(0, Font->getSpriteBank()->getTexture(i));
 
125
                                Mesh->addMeshBuffer(mb);
 
126
                                mb->drop();
 
127
                        }
 
128
                }
 
129
                else
 
130
                {
 
131
                        os::Printer::log("Sorry, CBillboardTextSceneNode does not support this font type", ELL_INFORMATION);
 
132
                }
 
133
        }
 
134
 
 
135
        setText(text);
 
136
        setSize(size);
 
137
 
 
138
        setAutomaticCulling ( scene::EAC_BOX );
 
139
}
 
140
 
 
141
 
 
142
 
 
143
CBillboardTextSceneNode::~CBillboardTextSceneNode()
 
144
{
 
145
        if (Font)
 
146
                Font->drop();
 
147
 
 
148
        if (Mesh)
 
149
                Mesh->drop();
 
150
 
 
151
}
 
152
 
 
153
 
 
154
//! sets the text string
 
155
void CBillboardTextSceneNode::setText(const wchar_t* text)
 
156
{
 
157
        if ( !Mesh )
 
158
                return;
 
159
 
 
160
        Text = text;
 
161
 
 
162
        Symbol.clear();
 
163
 
 
164
        // clear mesh
 
165
        for (u32 j=0; j < Mesh->getMeshBufferCount(); ++j)
 
166
        {
 
167
                ((SMeshBuffer*)Mesh->getMeshBuffer(j))->Indices.clear();
 
168
                ((SMeshBuffer*)Mesh->getMeshBuffer(j))->Vertices.clear();
 
169
        }
 
170
 
 
171
        if (!Font)
 
172
                return;
 
173
 
 
174
        const core::array< core::rect<s32> > &sourceRects = Font->getSpriteBank()->getPositions();
 
175
        const core::array< gui::SGUISprite > &sprites = Font->getSpriteBank()->getSprites();
 
176
 
 
177
        f32 dim[2];
 
178
        f32 tex[4];
 
179
 
 
180
        u32 i;
 
181
        for ( i = 0; i != Text.size (); ++i )
 
182
        {
 
183
                SSymbolInfo info;
 
184
 
 
185
                u32 spriteno = Font->getSpriteNoFromChar( &text[i] );
 
186
                u32 rectno = sprites[spriteno].Frames[0].rectNumber;
 
187
                u32 texno = sprites[spriteno].Frames[0].textureNumber;
 
188
 
 
189
                dim[0] = core::reciprocal ( (f32) Font->getSpriteBank()->getTexture(texno)->getSize().Width );
 
190
                dim[1] = core::reciprocal ( (f32) Font->getSpriteBank()->getTexture(texno)->getSize().Height );
 
191
 
 
192
                const core::rect<s32>& s = sourceRects[rectno];
 
193
 
 
194
                // add space for letter to buffer
 
195
                SMeshBuffer* buf = (SMeshBuffer*)Mesh->getMeshBuffer(texno);
 
196
                u32 firstInd = buf->Indices.size();
 
197
                u32 firstVert = buf->Vertices.size();
 
198
                buf->Indices.set_used(firstInd + 6);
 
199
                buf->Vertices.set_used(firstVert + 4);
 
200
 
 
201
                tex[0] = (s.LowerRightCorner.X * dim[0]) + 0.5f*dim[0]; // half pixel
 
202
                tex[1] = (s.LowerRightCorner.Y * dim[1]) + 0.5f*dim[1];
 
203
                tex[2] = (s.UpperLeftCorner.Y  * dim[1]) - 0.5f*dim[1];
 
204
                tex[3] = (s.UpperLeftCorner.X  * dim[0]) - 0.5f*dim[0];
 
205
 
 
206
                buf->Vertices[firstVert+0].TCoords.set(tex[0], tex[1]);
 
207
                buf->Vertices[firstVert+1].TCoords.set(tex[0], tex[2]);
 
208
                buf->Vertices[firstVert+2].TCoords.set(tex[3], tex[2]);
 
209
                buf->Vertices[firstVert+3].TCoords.set(tex[3], tex[1]);
 
210
 
 
211
                buf->Vertices[firstVert+0].Color = ColorBottom;
 
212
                buf->Vertices[firstVert+3].Color = ColorBottom;
 
213
                buf->Vertices[firstVert+1].Color = ColorTop;
 
214
                buf->Vertices[firstVert+2].Color = ColorTop;
 
215
 
 
216
                buf->Indices[firstInd+0] = (u16)firstVert+0;
 
217
                buf->Indices[firstInd+1] = (u16)firstVert+2;
 
218
                buf->Indices[firstInd+2] = (u16)firstVert+1;
 
219
                buf->Indices[firstInd+3] = (u16)firstVert+0;
 
220
                buf->Indices[firstInd+4] = (u16)firstVert+3;
 
221
                buf->Indices[firstInd+5] = (u16)firstVert+2;
 
222
 
 
223
                wchar_t *tp = 0;
 
224
                if (i>0)
 
225
                        tp = &Text[i-1];
 
226
 
 
227
                info.Width = (f32)s.getWidth();
 
228
                info.bufNo = texno;
 
229
                info.Kerning = (f32)Font->getKerningWidth(&Text[i], tp);
 
230
                info.firstInd = firstInd;
 
231
                info.firstVert = firstVert;
 
232
 
 
233
                Symbol.push_back(info);
 
234
        }
 
235
}
 
236
 
 
237
 
 
238
//! pre render event
 
239
void CBillboardTextSceneNode::OnAnimate(u32 timeMs)
 
240
{
 
241
        if (!IsVisible || !Font || !Mesh)
 
242
                return;
 
243
 
 
244
        ICameraSceneNode* camera = SceneManager->getActiveCamera();
 
245
        if (!camera)
 
246
                return;
 
247
 
 
248
        // get text width
 
249
        f32 textLength = 0.f;
 
250
        u32 i;
 
251
        for(i=0; i!=Symbol.size(); ++i)
 
252
        {
 
253
                SSymbolInfo &info = Symbol[i];
 
254
                textLength += info.Kerning + info.Width;
 
255
        }
 
256
        if (textLength<0.0f)
 
257
                textLength=1.0f;
 
258
 
 
259
        //const core::matrix4 &m = camera->getViewFrustum()->Matrices[ video::ETS_VIEW ];
 
260
 
 
261
        // make billboard look to camera
 
262
        core::vector3df pos = getAbsolutePosition();
 
263
 
 
264
        core::vector3df campos = camera->getAbsolutePosition();
 
265
        core::vector3df target = camera->getTarget();
 
266
        core::vector3df up = camera->getUpVector();
 
267
        core::vector3df view = target - campos;
 
268
        view.normalize();
 
269
 
 
270
        core::vector3df horizontal = up.crossProduct(view);
 
271
        if ( horizontal.getLength() == 0 )
 
272
        {
 
273
                horizontal.set(up.Y,up.X,up.Z);
 
274
        }
 
275
 
 
276
        horizontal.normalize();
 
277
        core::vector3df space = horizontal;
 
278
 
 
279
        horizontal *= 0.5f * Size.Width;
 
280
 
 
281
        core::vector3df vertical = horizontal.crossProduct(view);
 
282
        vertical.normalize();
 
283
        vertical *= 0.5f * Size.Height;
 
284
 
 
285
        view *= -1.0f;
 
286
 
 
287
        // center text
 
288
        pos += space * (Size.Width * -0.5f);
 
289
 
 
290
        for ( i = 0; i!= Symbol.size(); ++i )
 
291
        {
 
292
                SSymbolInfo &info = Symbol[i];
 
293
                f32 infw = info.Width / textLength;
 
294
                f32 infk = info.Kerning / textLength;
 
295
                f32 w = (Size.Width * infw * 0.5f);
 
296
                pos += space * w;
 
297
 
 
298
                SMeshBuffer* buf = (SMeshBuffer*)Mesh->getMeshBuffer(info.bufNo);
 
299
 
 
300
                buf->Vertices[info.firstVert+0].Normal = view;
 
301
                buf->Vertices[info.firstVert+1].Normal = view;
 
302
                buf->Vertices[info.firstVert+2].Normal = view;
 
303
                buf->Vertices[info.firstVert+3].Normal = view;
 
304
 
 
305
                buf->Vertices[info.firstVert+0].Pos = pos + (space * w) + vertical;
 
306
                buf->Vertices[info.firstVert+1].Pos = pos + (space * w) - vertical;
 
307
                buf->Vertices[info.firstVert+2].Pos = pos - (space * w) - vertical;
 
308
                buf->Vertices[info.firstVert+3].Pos = pos - (space * w) + vertical;
 
309
 
 
310
                pos += space * (Size.Width*infk + w);
 
311
        }
 
312
 
 
313
        // make bounding box
 
314
 
 
315
        for (i=0; i< Mesh->getMeshBufferCount() ; ++i)
 
316
                Mesh->getMeshBuffer(i)->recalculateBoundingBox();
 
317
        Mesh->recalculateBoundingBox();
 
318
 
 
319
        BBox = Mesh->getBoundingBox();
 
320
        core::matrix4 mat( getAbsoluteTransformation(), core::matrix4::EM4CONST_INVERSE );
 
321
        mat.transformBoxEx(BBox);
 
322
}
 
323
 
 
324
void CBillboardTextSceneNode::OnRegisterSceneNode()
 
325
{
 
326
        SceneManager->registerNodeForRendering(this, ESNRP_TRANSPARENT);
 
327
        ISceneNode::OnRegisterSceneNode();
 
328
}
 
329
 
 
330
 
 
331
//! render
 
332
void CBillboardTextSceneNode::render()
 
333
{
 
334
        if ( !Mesh )
 
335
                return;
 
336
 
 
337
        video::IVideoDriver* driver = SceneManager->getVideoDriver();
 
338
 
 
339
        // draw
 
340
        core::matrix4 mat;
 
341
        driver->setTransform(video::ETS_WORLD, mat);
 
342
 
 
343
        for (u32 i = 0; i < Mesh->getMeshBufferCount(); ++i)
 
344
        {
 
345
                driver->setMaterial(Mesh->getMeshBuffer(i)->getMaterial());
 
346
                driver->drawMeshBuffer(Mesh->getMeshBuffer(i));
 
347
        }
 
348
 
 
349
        if ( DebugDataVisible & scene::EDS_BBOX )
 
350
        {
 
351
                driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
 
352
                video::SMaterial m;
 
353
                m.Lighting = false;
 
354
                driver->setMaterial(m);
 
355
                driver->draw3DBox(BBox, video::SColor(0,208,195,152));
 
356
        }
 
357
}
 
358
 
 
359
 
 
360
//! returns the axis aligned bounding box of this node
 
361
const core::aabbox3d<f32>& CBillboardTextSceneNode::getBoundingBox() const
 
362
{
 
363
        return BBox;
 
364
}
 
365
 
 
366
 
 
367
//! sets the size of the billboard
 
368
void CBillboardTextSceneNode::setSize(const core::dimension2d<f32>& size)
 
369
{
 
370
        Size = size;
 
371
 
 
372
        if (Size.Width == 0.0f)
 
373
                Size.Width = 1.0f;
 
374
 
 
375
        if (Size.Height == 0.0f )
 
376
                Size.Height = 1.0f;
 
377
 
 
378
        //f32 avg = (size.Width + size.Height)/6;
 
379
        //BBox.MinEdge.set(-avg,-avg,-avg);
 
380
        //BBox.MaxEdge.set(avg,avg,avg);
 
381
}
 
382
 
 
383
 
 
384
video::SMaterial& CBillboardTextSceneNode::getMaterial(u32 i)
 
385
{
 
386
        if (Mesh && Mesh->getMeshBufferCount() > i )
 
387
                return Mesh->getMeshBuffer(i)->getMaterial();
 
388
        else
 
389
                return Material;
 
390
}
 
391
 
 
392
 
 
393
//! returns amount of materials used by this scene node.
 
394
u32 CBillboardTextSceneNode::getMaterialCount() const
 
395
{
 
396
        if (Mesh)
 
397
                return Mesh->getMeshBufferCount();
 
398
        else
 
399
                return 0;
 
400
}
 
401
 
 
402
 
 
403
//! gets the size of the billboard
 
404
const core::dimension2d<f32>& CBillboardTextSceneNode::getSize() const
 
405
{
 
406
        return Size;
 
407
}
 
408
 
 
409
 
 
410
//! sets the color of the text
 
411
void CBillboardTextSceneNode::setTextColor(video::SColor color)
 
412
{
 
413
        Color = color;
 
414
}
 
415
 
 
416
//! Set the color of all vertices of the billboard
 
417
//! \param overallColor: the color to set
 
418
void CBillboardTextSceneNode::setColor(const video::SColor & overallColor)
 
419
{
 
420
        if ( !Mesh )
 
421
                return;
 
422
 
 
423
        for ( u32 i = 0; i != Text.size (); ++i )
 
424
        {
 
425
                const SSymbolInfo &info = Symbol[i];
 
426
                SMeshBuffer* buf = (SMeshBuffer*)Mesh->getMeshBuffer(info.bufNo);
 
427
                buf->Vertices[info.firstVert+0].Color = overallColor;
 
428
                buf->Vertices[info.firstVert+1].Color = overallColor;
 
429
                buf->Vertices[info.firstVert+2].Color = overallColor;
 
430
                buf->Vertices[info.firstVert+3].Color = overallColor;
 
431
        }
 
432
}
 
433
 
 
434
 
 
435
//! Set the color of the top and bottom vertices of the billboard
 
436
//! \param topColor: the color to set the top vertices
 
437
//! \param bottomColor: the color to set the bottom vertices
 
438
void CBillboardTextSceneNode::setColor(const video::SColor & topColor, const video::SColor & bottomColor)
 
439
{
 
440
        if ( !Mesh )
 
441
                return;
 
442
 
 
443
        ColorBottom = bottomColor;
 
444
        ColorTop = topColor;
 
445
        for ( u32 i = 0; i != Text.size (); ++i )
 
446
        {
 
447
                const SSymbolInfo &info = Symbol[i];
 
448
                SMeshBuffer* buf = (SMeshBuffer*)Mesh->getMeshBuffer(info.bufNo);
 
449
                buf->Vertices[info.firstVert+0].Color = ColorBottom;
 
450
                buf->Vertices[info.firstVert+3].Color = ColorBottom;
 
451
                buf->Vertices[info.firstVert+1].Color = ColorTop;
 
452
                buf->Vertices[info.firstVert+2].Color = ColorTop;
 
453
        }
 
454
}
 
455
 
 
456
 
 
457
//! Gets the color of the top and bottom vertices of the billboard
 
458
//! \param topColor: stores the color of the top vertices
 
459
//! \param bottomColor: stores the color of the bottom vertices
 
460
void CBillboardTextSceneNode::getColor(video::SColor & topColor, video::SColor & bottomColor) const
 
461
{
 
462
        topColor = ColorTop;
 
463
        bottomColor = ColorBottom;
 
464
}
 
465
 
 
466
 
 
467
} // end namespace scene
 
468
} // end namespace irr
 
469