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