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
5 #include "IrrCompileConfig.h"
\r
6 #ifdef _IRR_COMPILE_WITH_BILLBOARD_SCENENODE_
\r
7 #include "CBillboardSceneNode.h"
\r
8 #include "IVideoDriver.h"
\r
9 #include "ISceneManager.h"
\r
10 #include "ICameraSceneNode.h"
\r
19 CBillboardSceneNode::CBillboardSceneNode(ISceneNode* parent, ISceneManager* mgr, s32 id,
\r
20 const core::vector3df& position, const core::dimension2d<f32>& size,
\r
21 video::SColor colorTop, video::SColor colorBottom)
\r
22 : IBillboardSceneNode(parent, mgr, id, position)
\r
23 , Buffer(new SMeshBuffer())
\r
26 setDebugName("CBillboardSceneNode");
\r
31 Buffer->Vertices.set_used(4);
\r
32 Buffer->Indices.set_used(6);
\r
34 Buffer->Indices[0] = 0;
\r
35 Buffer->Indices[1] = 2;
\r
36 Buffer->Indices[2] = 1;
\r
37 Buffer->Indices[3] = 0;
\r
38 Buffer->Indices[4] = 3;
\r
39 Buffer->Indices[5] = 2;
\r
41 Buffer->Vertices[0].TCoords.set(1.0f, 1.0f);
\r
42 Buffer->Vertices[0].Color = colorBottom;
\r
44 Buffer->Vertices[1].TCoords.set(1.0f, 0.0f);
\r
45 Buffer->Vertices[1].Color = colorTop;
\r
47 Buffer->Vertices[2].TCoords.set(0.0f, 0.0f);
\r
48 Buffer->Vertices[2].Color = colorTop;
\r
50 Buffer->Vertices[3].TCoords.set(0.0f, 1.0f);
\r
51 Buffer->Vertices[3].Color = colorBottom;
\r
54 CBillboardSceneNode::~CBillboardSceneNode()
\r
59 //! pre render event
\r
60 void CBillboardSceneNode::OnRegisterSceneNode()
\r
63 SceneManager->registerNodeForRendering(this);
\r
65 ISceneNode::OnRegisterSceneNode();
\r
70 void CBillboardSceneNode::render()
\r
72 video::IVideoDriver* driver = SceneManager->getVideoDriver();
\r
73 ICameraSceneNode* camera = SceneManager->getActiveCamera();
\r
75 if (!camera || !driver)
\r
78 // make billboard look to camera
\r
81 driver->setTransform(video::ETS_WORLD, core::IdentityMatrix);
\r
82 driver->setMaterial(Buffer->Material);
\r
83 driver->drawMeshBuffer(Buffer);
\r
85 if (DebugDataVisible & scene::EDS_BBOX)
\r
87 driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
\r
90 driver->setMaterial(m);
\r
91 driver->draw3DBox(BBoxSafe, video::SColor(0,208,195,152));
\r
95 void CBillboardSceneNode::updateMesh(const irr::scene::ICameraSceneNode* camera)
\r
97 // billboard looks toward camera
\r
98 core::vector3df pos = getAbsolutePosition();
\r
100 core::vector3df campos = camera->getAbsolutePosition();
\r
101 core::vector3df target = camera->getTarget();
\r
102 core::vector3df up = camera->getUpVector();
\r
103 core::vector3df view = target - campos;
\r
106 core::vector3df horizontal = up.crossProduct(view);
\r
107 if ( horizontal.getLength() == 0 )
\r
109 horizontal.set(up.Y,up.X,up.Z);
\r
111 horizontal.normalize();
\r
112 core::vector3df topHorizontal = horizontal * 0.5f * TopEdgeWidth;
\r
113 horizontal *= 0.5f * Size.Width;
\r
116 core::vector3df vertical = horizontal.crossProduct(view);
\r
117 vertical.normalize();
\r
118 vertical *= 0.5f * Size.Height;
\r
122 core::array<video::S3DVertex>& vertices = Buffer->Vertices;
\r
124 for (s32 i=0; i<4; ++i)
\r
125 vertices[i].Normal = view;
\r
133 vertices[0].Pos = pos + horizontal + vertical;
\r
134 vertices[1].Pos = pos + topHorizontal - vertical;
\r
135 vertices[2].Pos = pos - topHorizontal - vertical;
\r
136 vertices[3].Pos = pos - horizontal + vertical;
\r
138 Buffer->setDirty(EBT_VERTEX);
\r
139 Buffer->recalculateBoundingBox();
\r
143 //! returns the axis aligned bounding box of this node
\r
144 const core::aabbox3d<f32>& CBillboardSceneNode::getBoundingBox() const
\r
146 // Really wrong when scaled.
\r
150 const core::aabbox3d<f32>& CBillboardSceneNode::getTransformedBillboardBoundingBox(const irr::scene::ICameraSceneNode* camera)
\r
152 updateMesh(camera);
\r
153 return Buffer->BoundingBox;
\r
156 void CBillboardSceneNode::setSize(const core::dimension2d<f32>& size)
\r
160 if (core::equals(Size.Width, 0.0f))
\r
162 TopEdgeWidth = Size.Width;
\r
164 if (core::equals(Size.Height, 0.0f))
\r
165 Size.Height = 1.0f;
\r
167 const f32 avg = (Size.Width + Size.Height)/6;
\r
168 BBoxSafe.MinEdge.set(-avg,-avg,-avg);
\r
169 BBoxSafe.MaxEdge.set(avg,avg,avg);
\r
173 void CBillboardSceneNode::setSize(f32 height, f32 bottomEdgeWidth, f32 topEdgeWidth)
\r
175 Size.set(bottomEdgeWidth, height);
\r
176 TopEdgeWidth = topEdgeWidth;
\r
178 if (core::equals(Size.Height, 0.0f))
\r
179 Size.Height = 1.0f;
\r
181 if (core::equals(Size.Width, 0.f) && core::equals(TopEdgeWidth, 0.f))
\r
184 TopEdgeWidth = 1.0f;
\r
187 const f32 avg = (core::max_(Size.Width,TopEdgeWidth) + Size.Height)/6;
\r
188 BBoxSafe.MinEdge.set(-avg,-avg,-avg);
\r
189 BBoxSafe.MaxEdge.set(avg,avg,avg);
\r
193 video::SMaterial& CBillboardSceneNode::getMaterial(u32 i)
\r
195 return Buffer->Material;
\r
199 //! returns amount of materials used by this scene node.
\r
200 u32 CBillboardSceneNode::getMaterialCount() const
\r
206 //! gets the size of the billboard
\r
207 const core::dimension2d<f32>& CBillboardSceneNode::getSize() const
\r
213 //! Gets the widths of the top and bottom edges of the billboard.
\r
214 void CBillboardSceneNode::getSize(f32& height, f32& bottomEdgeWidth,
\r
215 f32& topEdgeWidth) const
\r
217 height = Size.Height;
\r
218 bottomEdgeWidth = Size.Width;
\r
219 topEdgeWidth = TopEdgeWidth;
\r
223 //! Writes attributes of the scene node.
\r
224 void CBillboardSceneNode::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const
\r
226 IBillboardSceneNode::serializeAttributes(out, options);
\r
228 out->addFloat("Width", Size.Width);
\r
229 out->addFloat("TopEdgeWidth", TopEdgeWidth);
\r
230 out->addFloat("Height", Size.Height);
\r
231 out->addColor("Shade_Top", Buffer->Vertices[1].Color);
\r
232 out->addColor("Shade_Down", Buffer->Vertices[0].Color);
\r
236 //! Reads attributes of the scene node.
\r
237 void CBillboardSceneNode::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options)
\r
239 IBillboardSceneNode::deserializeAttributes(in, options);
\r
241 Size.Width = in->getAttributeAsFloat("Width");
\r
242 Size.Height = in->getAttributeAsFloat("Height");
\r
244 if (in->existsAttribute("TopEdgeWidth"))
\r
246 TopEdgeWidth = in->getAttributeAsFloat("TopEdgeWidth");
\r
247 if (Size.Width != TopEdgeWidth)
\r
248 setSize(Size.Height, Size.Width, TopEdgeWidth);
\r
252 Buffer->Vertices[1].Color = in->getAttributeAsColor("Shade_Top");
\r
253 Buffer->Vertices[0].Color = in->getAttributeAsColor("Shade_Down");
\r
254 Buffer->Vertices[2].Color = Buffer->Vertices[1].Color;
\r
255 Buffer->Vertices[3].Color = Buffer->Vertices[0].Color;
\r
259 //! Set the color of all vertices of the billboard
\r
260 //! \param overallColor: the color to set
\r
261 void CBillboardSceneNode::setColor(const video::SColor& overallColor)
\r
263 for(u32 vertex = 0; vertex < 4; ++vertex)
\r
264 Buffer->Vertices[vertex].Color = overallColor;
\r
268 //! Set the color of the top and bottom vertices of the billboard
\r
269 //! \param topColor: the color to set the top vertices
\r
270 //! \param bottomColor: the color to set the bottom vertices
\r
271 void CBillboardSceneNode::setColor(const video::SColor& topColor,
\r
272 const video::SColor& bottomColor)
\r
274 Buffer->Vertices[0].Color = bottomColor;
\r
275 Buffer->Vertices[1].Color = topColor;
\r
276 Buffer->Vertices[2].Color = topColor;
\r
277 Buffer->Vertices[3].Color = bottomColor;
\r
281 //! Gets the color of the top and bottom vertices of the billboard
\r
282 //! \param[out] topColor: stores the color of the top vertices
\r
283 //! \param[out] bottomColor: stores the color of the bottom vertices
\r
284 void CBillboardSceneNode::getColor(video::SColor& topColor,
\r
285 video::SColor& bottomColor) const
\r
287 bottomColor = Buffer->Vertices[0].Color;
\r
288 topColor = Buffer->Vertices[1].Color;
\r
292 //! Creates a clone of this scene node and its children.
\r
293 ISceneNode* CBillboardSceneNode::clone(ISceneNode* newParent, ISceneManager* newManager)
\r
296 newParent = Parent;
\r
298 newManager = SceneManager;
\r
300 CBillboardSceneNode* nb = new CBillboardSceneNode(newParent,
\r
301 newManager, ID, RelativeTranslation, Size);
\r
303 nb->cloneMembers(this, newManager);
\r
304 nb->Buffer->Material = Buffer->Material;
\r
306 nb->TopEdgeWidth = this->TopEdgeWidth;
\r
308 video::SColor topColor,bottomColor;
\r
309 getColor(topColor,bottomColor);
\r
310 nb->setColor(topColor,bottomColor);
\r
318 } // end namespace scene
\r
319 } // end namespace irr
\r
321 #endif // _IRR_COMPILE_WITH_BILLBOARD_SCENENODE_
\r