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