1 // Copyright (C) 2002-2012 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 "CBillboardSceneNode.h"
6 #include "IVideoDriver.h"
7 #include "ISceneManager.h"
8 #include "ICameraSceneNode.h"
9 #include "os.h"
10
11 namespace irr
12 {
13 namespace scene
14 {
15
16 //! constructor
CBillboardSceneNode(ISceneNode * parent,ISceneManager * mgr,s32 id,const core::vector3df & position,const core::dimension2d<f32> & size,video::SColor colorTop,video::SColor colorBottom)17 CBillboardSceneNode::CBillboardSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id,
18 const core::vector3df& position, const core::dimension2d<f32>& size,
19 video::SColor colorTop, video::SColor colorBottom)
20 : IBillboardSceneNode(parent, mgr, id, position)
21 {
22 #ifdef _DEBUG
23 setDebugName("CBillboardSceneNode");
24 #endif
25
26 setSize(size);
27
28 indices[0] = 0;
29 indices[1] = 2;
30 indices[2] = 1;
31 indices[3] = 0;
32 indices[4] = 3;
33 indices[5] = 2;
34
35 vertices[0].TCoords.set(1.0f, 1.0f);
36 vertices[0].Color = colorBottom;
37
38 vertices[1].TCoords.set(1.0f, 0.0f);
39 vertices[1].Color = colorTop;
40
41 vertices[2].TCoords.set(0.0f, 0.0f);
42 vertices[2].Color = colorTop;
43
44 vertices[3].TCoords.set(0.0f, 1.0f);
45 vertices[3].Color = colorBottom;
46 }
47
48
49 //! pre render event
OnRegisterSceneNode()50 void CBillboardSceneNode::OnRegisterSceneNode()
51 {
52 if (IsVisible)
53 SceneManager->registerNodeForRendering(this);
54
55 ISceneNode::OnRegisterSceneNode();
56 }
57
58
59 //! render
render()60 void CBillboardSceneNode::render()
61 {
62 video::IVideoDriver* driver = SceneManager->getVideoDriver();
63 ICameraSceneNode* camera = SceneManager->getActiveCamera();
64
65 if (!camera || !driver)
66 return;
67
68 // make billboard look to camera
69
70 core::vector3df pos = getAbsolutePosition();
71
72 core::vector3df campos = camera->getAbsolutePosition();
73 core::vector3df target = camera->getTarget();
74 core::vector3df up = camera->getUpVector();
75 core::vector3df view = target - campos;
76 view.normalize();
77
78 core::vector3df horizontal = up.crossProduct(view);
79 if ( horizontal.getLength() == 0 )
80 {
81 horizontal.set(up.Y,up.X,up.Z);
82 }
83 horizontal.normalize();
84 core::vector3df topHorizontal = horizontal * 0.5f * TopEdgeWidth;
85 horizontal *= 0.5f * Size.Width;
86
87 // pointing down!
88 core::vector3df vertical = horizontal.crossProduct(view);
89 vertical.normalize();
90 vertical *= 0.5f * Size.Height;
91
92 view *= -1.0f;
93
94 for (s32 i=0; i<4; ++i)
95 vertices[i].Normal = view;
96
97 /* Vertices are:
98 2--1
99 |\ |
100 | \|
101 3--0
102 */
103 vertices[0].Pos = pos + horizontal + vertical;
104 vertices[1].Pos = pos + topHorizontal - vertical;
105 vertices[2].Pos = pos - topHorizontal - vertical;
106 vertices[3].Pos = pos - horizontal + vertical;
107
108 // draw
109
110 if (DebugDataVisible & scene::EDS_BBOX)
111 {
112 driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
113 video::SMaterial m;
114 m.Lighting = false;
115 driver->setMaterial(m);
116 driver->draw3DBox(BBox, video::SColor(0,208,195,152));
117 }
118
119 driver->setTransform(video::ETS_WORLD, core::IdentityMatrix);
120
121 driver->setMaterial(Material);
122
123 driver->drawIndexedTriangleList(vertices, 4, indices, 2);
124 }
125
126
127 //! returns the axis aligned bounding box of this node
getBoundingBox() const128 const core::aabbox3d<f32>& CBillboardSceneNode::getBoundingBox() const
129 {
130 return BBox;
131 }
132
133
134 //! sets the size of the billboard
setSize(const core::dimension2d<f32> & size)135 void CBillboardSceneNode::setSize(const core::dimension2d<f32>& size)
136 {
137 Size = size;
138
139 if (core::equals(Size.Width, 0.0f))
140 Size.Width = 1.0f;
141 TopEdgeWidth = Size.Width;
142
143 if (core::equals(Size.Height, 0.0f))
144 Size.Height = 1.0f;
145
146 const f32 avg = (Size.Width + Size.Height)/6;
147 BBox.MinEdge.set(-avg,-avg,-avg);
148 BBox.MaxEdge.set(avg,avg,avg);
149 }
150
151
setSize(f32 height,f32 bottomEdgeWidth,f32 topEdgeWidth)152 void CBillboardSceneNode::setSize(f32 height, f32 bottomEdgeWidth, f32 topEdgeWidth)
153 {
154 Size.set(bottomEdgeWidth, height);
155 TopEdgeWidth = topEdgeWidth;
156
157 if (core::equals(Size.Height, 0.0f))
158 Size.Height = 1.0f;
159
160 if (core::equals(Size.Width, 0.f) && core::equals(TopEdgeWidth, 0.f))
161 {
162 Size.Width = 1.0f;
163 TopEdgeWidth = 1.0f;
164 }
165
166 const f32 avg = (core::max_(Size.Width,TopEdgeWidth) + Size.Height)/6;
167 BBox.MinEdge.set(-avg,-avg,-avg);
168 BBox.MaxEdge.set(avg,avg,avg);
169 }
170
171
getMaterial(u32 i)172 video::SMaterial& CBillboardSceneNode::getMaterial(u32 i)
173 {
174 return Material;
175 }
176
177
178 //! returns amount of materials used by this scene node.
getMaterialCount() const179 u32 CBillboardSceneNode::getMaterialCount() const
180 {
181 return 1;
182 }
183
184
185 //! gets the size of the billboard
getSize() const186 const core::dimension2d<f32>& CBillboardSceneNode::getSize() const
187 {
188 return Size;
189 }
190
191
192 //! Gets the widths of the top and bottom edges of the billboard.
getSize(f32 & height,f32 & bottomEdgeWidth,f32 & topEdgeWidth) const193 void CBillboardSceneNode::getSize(f32& height, f32& bottomEdgeWidth,
194 f32& topEdgeWidth) const
195 {
196 height = Size.Height;
197 bottomEdgeWidth = Size.Width;
198 topEdgeWidth = TopEdgeWidth;
199 }
200
201
202 //! Writes attributes of the scene node.
serializeAttributes(io::IAttributes * out,io::SAttributeReadWriteOptions * options) const203 void CBillboardSceneNode::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const
204 {
205 IBillboardSceneNode::serializeAttributes(out, options);
206
207 out->addFloat("Width", Size.Width);
208 out->addFloat("TopEdgeWidth", TopEdgeWidth);
209 out->addFloat("Height", Size.Height);
210 out->addColor("Shade_Top", vertices[1].Color);
211 out->addColor("Shade_Down", vertices[0].Color);
212 }
213
214
215 //! Reads attributes of the scene node.
deserializeAttributes(io::IAttributes * in,io::SAttributeReadWriteOptions * options)216 void CBillboardSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options)
217 {
218 IBillboardSceneNode::deserializeAttributes(in, options);
219
220 Size.Width = in->getAttributeAsFloat("Width");
221 Size.Height = in->getAttributeAsFloat("Height");
222
223 if (in->existsAttribute("TopEdgeWidth"))
224 {
225 TopEdgeWidth = in->getAttributeAsFloat("TopEdgeWidth");
226 if (Size.Width != TopEdgeWidth)
227 setSize(Size.Height, Size.Width, TopEdgeWidth);
228 }
229 else
230 setSize(Size);
231 vertices[1].Color = in->getAttributeAsColor("Shade_Top");
232 vertices[0].Color = in->getAttributeAsColor("Shade_Down");
233 vertices[2].Color = vertices[1].Color;
234 vertices[3].Color = vertices[0].Color;
235 }
236
237
238 //! Set the color of all vertices of the billboard
239 //! \param overallColor: the color to set
setColor(const video::SColor & overallColor)240 void CBillboardSceneNode::setColor(const video::SColor& overallColor)
241 {
242 for(u32 vertex = 0; vertex < 4; ++vertex)
243 vertices[vertex].Color = overallColor;
244 }
245
246
247 //! Set the color of the top and bottom vertices of the billboard
248 //! \param topColor: the color to set the top vertices
249 //! \param bottomColor: the color to set the bottom vertices
setColor(const video::SColor & topColor,const video::SColor & bottomColor)250 void CBillboardSceneNode::setColor(const video::SColor& topColor,
251 const video::SColor& bottomColor)
252 {
253 vertices[0].Color = bottomColor;
254 vertices[1].Color = topColor;
255 vertices[2].Color = topColor;
256 vertices[3].Color = bottomColor;
257 }
258
259
260 //! Gets the color of the top and bottom vertices of the billboard
261 //! \param[out] topColor: stores the color of the top vertices
262 //! \param[out] bottomColor: stores the color of the bottom vertices
getColor(video::SColor & topColor,video::SColor & bottomColor) const263 void CBillboardSceneNode::getColor(video::SColor& topColor,
264 video::SColor& bottomColor) const
265 {
266 bottomColor = vertices[0].Color;
267 topColor = vertices[1].Color;
268 }
269
270
271 //! Creates a clone of this scene node and its children.
clone(ISceneNode * newParent,ISceneManager * newManager)272 ISceneNode* CBillboardSceneNode::clone(ISceneNode* newParent, ISceneManager* newManager)
273 {
274 if (!newParent)
275 newParent = Parent;
276 if (!newManager)
277 newManager = SceneManager;
278
279 CBillboardSceneNode* nb = new CBillboardSceneNode(newParent,
280 newManager, ID, RelativeTranslation, Size);
281
282 nb->cloneMembers(this, newManager);
283 nb->Material = Material;
284 nb->TopEdgeWidth = this->TopEdgeWidth;
285
286 if ( newParent )
287 nb->drop();
288 return nb;
289 }
290
291
292 } // end namespace scene
293 } // end namespace irr
294
295