CBillboardSceneNode.cpp 7.4 KB

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