fork download
  1. #include "CGridSceneNode.h"
  2.  
  3. using namespace irr;
  4.  
  5. CGridSceneNode::SGrid::SGrid()
  6. : IsVisible(true)
  7. , Alignment(CENTER)
  8. , Spacing(8.f)
  9. , Size(2048.f, 2048.f)
  10. , Offset(0.f, 0.f, 0.f)
  11. , GridColor( irr::video::SColor(255,128,128,128))
  12. , MaxRenderDist(FLT_MAX)
  13. , GridDirty(true)
  14. , BoundingBoxDirty(true)
  15. , MeshBuffer(0)
  16. {
  17. // Set the material
  18. MeshBuffer = new irr::scene::CDynamicMeshBuffer(irr::video::EVT_STANDARD, irr::video::EIT_16BIT);
  19. setDefaultMaterial();
  20. }
  21.  
  22. CGridSceneNode::SGrid::~SGrid()
  23. {
  24. if ( MeshBuffer )
  25. MeshBuffer->drop();
  26. }
  27.  
  28. CGridSceneNode::SGrid::SGrid(const SGrid& other)
  29. : MeshBuffer(0)
  30. {
  31. MeshBuffer = new irr::scene::CDynamicMeshBuffer(irr::video::EVT_STANDARD, irr::video::EIT_16BIT);
  32. *this = other;
  33. }
  34.  
  35. CGridSceneNode::SGrid& CGridSceneNode::SGrid::operator=(const CGridSceneNode::SGrid& other)
  36. {
  37. if (&other == this )
  38. return *this;
  39.  
  40. IsVisible = other.IsVisible;
  41. Alignment = other.Alignment;
  42. Spacing = other.Spacing;
  43. Size = other.Size;
  44. Offset = other.Offset;
  45. GridColor = other.GridColor;
  46. MaxRenderDist = other.MaxRenderDist;
  47. setMaterial(other.getMaterial());
  48. // note, each object keeps it's own MeshBuffer for the lifetime and just changes the content
  49. GridDirty = true;
  50.  
  51. return *this;
  52. }
  53.  
  54. void CGridSceneNode::SGrid::setDefaultMaterial()
  55. {
  56. if( !MeshBuffer )
  57. return;
  58. MeshBuffer->getMaterial().Wireframe = false;
  59. MeshBuffer->getMaterial().Lighting = false;
  60. MeshBuffer->getMaterial().Thickness = 1;
  61. MeshBuffer->getMaterial().FogEnable = false;
  62. MeshBuffer->getMaterial().ZWriteEnable = true;
  63. MeshBuffer->getMaterial().ZBuffer = true;
  64. MeshBuffer->getMaterial().BackfaceCulling = true;
  65. MeshBuffer->getMaterial().AntiAliasing = false;
  66. }
  67.  
  68. bool CGridSceneNode::SGrid::canUseGridLine(irr::f32 pos, bool axisX, const CGridSceneNode* const gridNode)
  69. {
  70. if ( !gridNode )
  71. return true;
  72.  
  73. const irr::f32 epsilonHalf = 0.1f;
  74. for ( irr::u32 i=0; i<gridNode->getNumberOfGrids(); ++i )
  75. {
  76. const SGrid & otherGrid = gridNode->getGrid(i);
  77. if ( &otherGrid == this )
  78. continue;
  79. if ( otherGrid.getSpacing() <= getSpacing() )
  80. continue; // we want the biggest spacing to show up most
  81. irr::core::vector3df otherStart = otherGrid.calcGridStart();
  82. irr::f32 dist = axisX ? irr::core::abs_(pos - otherStart.X) : irr::core::abs_(pos - otherStart.Z);
  83. irr::f32 mod = fmodf(dist+epsilonHalf, otherGrid.getSpacing());
  84. if ( irr::core::equals( mod, 0.f, 2*epsilonHalf ) )
  85. return false;
  86. }
  87. return true;
  88. }
  89.  
  90. irr::core::vector3df CGridSceneNode::SGrid::calcGridStart() const
  91. {
  92. core::vector3df start(0,0,0);
  93.  
  94. //Set our corners
  95. if ( Alignment == CENTER )
  96. {
  97. irr::u32 tilesX = (irr::u32)(0.5f*Size.Width/Spacing);
  98. irr::u32 tilesY = (irr::u32)(0.5f*Size.Height/Spacing);
  99. start.X -= tilesX*Spacing;
  100. start.Z -= tilesY*Spacing;
  101. }
  102. else
  103. {
  104. start.X -= Size.Width/2.f;
  105. start.Z -= Size.Height/2.f;
  106. }
  107. start += Offset;
  108. return start;
  109. }
  110.  
  111. void CGridSceneNode::SGrid::regenerateMesh(const CGridSceneNode* const gridNode)
  112. {
  113. GridDirty = false;
  114.  
  115. //Clean up memory
  116. MeshBuffer->getIndexBuffer().set_used(0);
  117. MeshBuffer->getVertexBuffer().set_used(0);
  118.  
  119. u32 numVertices = ((u32)(Size.Width / Spacing) + 1) * 2 + ((u32)(Size.Height / Spacing) + 1) * 2;
  120. if ( numVertices > 65535)
  121. {
  122. //Too many vertices on 16 bit for for 16bit indices of SMeshBuffer
  123. //Returning with a blank buffer to avoid segfaulting the entire application
  124. return;
  125. }
  126.  
  127. core::vector3df leftMost( calcGridStart() );
  128. core::vector3df rightMost(Size.Width/2.f,0,Size.Height/2.f);
  129. rightMost += Offset;
  130.  
  131. u32 indexIndex = 0;
  132.  
  133. //X-axis lines
  134. for (f32 x = 0.f; x <= Size.Width; x+= Spacing)
  135. {
  136. core::vector3df start = leftMost;
  137. start.X += x ;
  138.  
  139. if ( !canUseGridLine(start.X, true, gridNode) )
  140. continue;
  141.  
  142. core::vector3df end = rightMost;
  143. end.X = start.X;
  144.  
  145. MeshBuffer->getVertexBuffer().push_back(video::S3DVertex(start, core::vector3df(0,1,0), GridColor, core::vector2df(0.0f, 0.0f)));
  146. MeshBuffer->getVertexBuffer().push_back(video::S3DVertex(end, core::vector3df(0,1,0), GridColor, core::vector2df(0.0f, 0.0f)));
  147.  
  148. MeshBuffer->getIndexBuffer().push_back(indexIndex++);
  149. MeshBuffer->getIndexBuffer().push_back(indexIndex++);
  150. }
  151.  
  152. //Z-axis lines
  153. for (f32 z = 0.f; z <= Size.Height; z+= Spacing)
  154. {
  155. core::vector3df start = leftMost;
  156. start.Z += z ;
  157.  
  158. if ( !canUseGridLine(start.Z, false, gridNode) )
  159. continue;
  160.  
  161. core::vector3df end = rightMost;
  162. end.Z = start.Z;
  163.  
  164. MeshBuffer->getVertexBuffer().push_back(video::S3DVertex(start, core::vector3df(0,1,0), GridColor, core::vector2df(0.0f, 0.0f)));
  165. MeshBuffer->getVertexBuffer().push_back(video::S3DVertex(end, core::vector3df(0,1,0), GridColor, core::vector2df(0.0f, 0.0f)));
  166.  
  167. MeshBuffer->getIndexBuffer().push_back(indexIndex++);
  168. MeshBuffer->getIndexBuffer().push_back(indexIndex++);
  169. }
  170.  
  171. // Create our box, it is the size of the grid exactly, plus 1 in the Y axis
  172. irr::core::aabbox3df bbox(-(f32)Size.Width/2.f,-0.5f,-(f32)Size.Height/2.f,(f32)Size.Width/2.f,0.5f,(f32)Size.Height/2.f);
  173. bbox.MinEdge += Offset;
  174. bbox.MaxEdge += Offset;
  175. MeshBuffer->setBoundingBox(bbox);
  176.  
  177. BoundingBoxDirty = true;
  178. }
  179.  
  180. void CGridSceneNode::SGrid::setAlignment(CGridSceneNode::EAlign align)
  181. {
  182. Alignment = align;
  183. GridDirty = true;
  184. }
  185.  
  186. CGridSceneNode::EAlign CGridSceneNode::SGrid::getAlignment() const
  187. {
  188. return Alignment;
  189. }
  190.  
  191. void CGridSceneNode::SGrid::setSpacing(f32 newspacing)
  192. {
  193. Spacing = newspacing;
  194. GridDirty = true;
  195. }
  196.  
  197. f32 CGridSceneNode::SGrid::getSpacing() const
  198. {
  199. return Spacing;
  200. }
  201.  
  202. void CGridSceneNode::SGrid::setSize(const irr::core::dimension2df& newsize)
  203. {
  204. Size = newsize;
  205. GridDirty = true;
  206. }
  207.  
  208. const irr::core::dimension2df& CGridSceneNode::SGrid::getSize() const
  209. {
  210. return Size;
  211. }
  212.  
  213. void CGridSceneNode::SGrid::setOffset(const irr::core::vector3df& offset)
  214. {
  215. Offset = offset;
  216. GridDirty = true;
  217. }
  218.  
  219. const irr::core::vector3df& CGridSceneNode::SGrid::getOffset() const
  220. {
  221. return Offset;
  222. }
  223.  
  224. void CGridSceneNode::SGrid::setGridColor(video::SColor newcolor)
  225. {
  226. GridColor = newcolor;
  227. GridDirty = true;
  228. }
  229.  
  230. video::SColor CGridSceneNode::SGrid::getGridColor() const
  231. {
  232. return GridColor;
  233. }
  234.  
  235. void CGridSceneNode::SGrid::setMaxRenderDistance(irr::f32 dist)
  236. {
  237. MaxRenderDist = dist;
  238. }
  239.  
  240. irr::f32 CGridSceneNode::SGrid::getMaxRenderDistance() const
  241. {
  242. return MaxRenderDist;
  243. }
  244.  
  245. void CGridSceneNode::SGrid::setMaterial(const video::SMaterial& newMaterial)
  246. {
  247. MeshBuffer->getMaterial() = newMaterial;
  248. }
  249.  
  250. const irr::video::SMaterial& CGridSceneNode::SGrid::getMaterial() const
  251. {
  252. return MeshBuffer->getMaterial();
  253. }
  254.  
  255. irr::video::SMaterial& CGridSceneNode::SGrid::getMaterial()
  256. {
  257. return MeshBuffer->getMaterial();
  258. }
  259.  
  260. const irr::core::aabbox3d<irr::f32>& CGridSceneNode::SGrid::getBoundingBox() const
  261. {
  262. return MeshBuffer->getBoundingBox();
  263. }
  264.  
  265.  
  266. void CGridSceneNode::SGrid::render(irr::video::IVideoDriver * driver )
  267. {
  268. if ( !isVisible() )
  269. return;
  270.  
  271. driver->setMaterial(MeshBuffer->getMaterial());
  272.  
  273. driver->drawVertexPrimitiveList(MeshBuffer->getVertexBuffer().getData(), // const void* vertices
  274. MeshBuffer->getVertexBuffer().size(), // u32 vertexCount
  275. MeshBuffer->getIndexBuffer().getData(), // const void* indexList
  276. MeshBuffer->getVertexBuffer().size()/2, // u32 primCount
  277. MeshBuffer->getVertexType(), // E_VERTEX_TYPE vType
  278. scene::EPT_LINES, // scene::E_PRIMITIVE_TYPE pType
  279. MeshBuffer->getIndexType() ); // E_INDEX_TYPE iType
  280. }
  281.  
  282.  
  283.  
  284.  
  285. CGridSceneNode::CGridSceneNode(ISceneNode* parent, scene::ISceneManager* smgr, s32 id, irr::u32 numGrids)
  286. : ISceneNode(parent, smgr, id)
  287. {
  288. // Set the default culling state to Frustum Box
  289. AutomaticCullingState = scene::EAC_FRUSTUM_BOX;
  290.  
  291. for ( irr::u32 i=0; i<numGrids;++i )
  292. {
  293. Grids.push_back(SGrid());
  294. }
  295. }
  296.  
  297. CGridSceneNode* CGridSceneNode::clone(scene::ISceneNode *newParent, scene::ISceneManager *newSceneManager)
  298. {
  299. if (!newParent) newParent = Parent;
  300. if (!newSceneManager) newSceneManager = SceneManager;
  301.  
  302. CGridSceneNode* clone = new CGridSceneNode(
  303. Parent,
  304. SceneManager,
  305. ID,
  306. Grids.size() );
  307. if (!clone)
  308. return 0;
  309.  
  310. for ( irr::u32 i=0; i< Grids.size(); ++i )
  311. {
  312. SGrid & grid = clone->getGrid(i);
  313. grid = getGrid(i);
  314. }
  315.  
  316. clone->drop();
  317. return clone;
  318. }
  319.  
  320. void CGridSceneNode::OnRegisterSceneNode()
  321. {
  322. if ( hasDirtyGrid() )
  323. regenerateMeshes();
  324. if( hasDirtyBoundingBox() )
  325. rebuildBoundingBox();
  326.  
  327. if (IsVisible)
  328. SceneManager->registerNodeForRendering(this);
  329.  
  330. ISceneNode::OnRegisterSceneNode();
  331. }
  332.  
  333.  
  334. void CGridSceneNode::render()
  335. {
  336. video::IVideoDriver* driver = SceneManager->getVideoDriver();
  337.  
  338. if ( !driver )
  339. return;
  340.  
  341. driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
  342. for ( irr::u32 i=0; i<Grids.size(); ++i )
  343. {
  344. if ( !SceneManager->getActiveCamera()->isOrthogonal() )
  345. {
  346. irr::core::plane3df gridPlane(0,Grids[i].getOffset().Y,0,0,1,0);
  347. AbsoluteTransformation.transformPlane(gridPlane);
  348. irr::f32 distToCam = gridPlane.getDistanceTo( SceneManager->getActiveCamera()->getAbsolutePosition() );
  349. if ( !SceneManager->getActiveCamera()->isOrthogonal() && distToCam > Grids[i].getMaxRenderDistance() )
  350. continue;
  351. }
  352.  
  353. Grids[i].render(driver);
  354. }
  355. }
  356.  
  357. bool CGridSceneNode::hasDirtyBoundingBox() const
  358. {
  359. bool hasDirty = false;
  360. for ( irr::u32 i=0; i<Grids.size(); ++i )
  361. {
  362. if ( Grids[i].BoundingBoxDirty )
  363. {
  364. hasDirty = true;
  365. break;
  366. }
  367. }
  368. return hasDirty;
  369. }
  370.  
  371. bool CGridSceneNode::hasDirtyGrid() const
  372. {
  373. bool hasDirty = false;
  374. for ( irr::u32 i=0; i<Grids.size(); ++i )
  375. {
  376. if ( Grids[i].GridDirty )
  377. {
  378. hasDirty = true;
  379. break;
  380. }
  381. }
  382. return hasDirty;
  383. }
  384.  
  385. void CGridSceneNode::regenerateMeshes()
  386. {
  387. for ( irr::u32 i=0; i<Grids.size(); ++i )
  388. {
  389. Grids[i].regenerateMesh(this);
  390. }
  391. }
  392.  
  393. void CGridSceneNode::rebuildBoundingBox()
  394. {
  395. if ( Grids.empty() )
  396. BoundingBox.reset( irr::core::vector3df(FLT_MAX,FLT_MAX,FLT_MAX) );
  397. else
  398. {
  399. // recalculate when one boundingbox has changed
  400. bool hasDirty = false;
  401. for ( irr::u32 i=0; i<Grids.size(); ++i )
  402. {
  403. if ( Grids[i].BoundingBoxDirty )
  404. {
  405. hasDirty = true;
  406. break;
  407. }
  408. }
  409.  
  410. if ( hasDirty )
  411. {
  412. BoundingBox = Grids[0].getBoundingBox();
  413. Grids[0].BoundingBoxDirty = false;
  414. for ( irr::u32 i=1; i<Grids.size(); ++i )
  415. {
  416. BoundingBox.addInternalBox( Grids[i].getBoundingBox() );
  417. Grids[i].BoundingBoxDirty = false;
  418. }
  419. }
  420. }
  421. }
  422.  
  423. const core::aabbox3d<f32>& CGridSceneNode::getBoundingBox() const
  424. {
  425. return BoundingBox;
  426. }
  427.  
  428. u32 CGridSceneNode::getMaterialCount() const
  429. {
  430. return Grids.size();
  431. }
  432.  
  433. video::SMaterial& CGridSceneNode::getMaterial(u32 i)
  434. {
  435. return Grids[i].getMaterial();
  436. }
  437.  
  438. irr::u32 CGridSceneNode::getNumberOfGrids() const
  439. {
  440. return Grids.size();
  441. }
  442.  
  443. irr::u32 CGridSceneNode::addGrid()
  444. {
  445. Grids.push_back(SGrid());
  446. return Grids.size()-1;
  447. }
  448.  
  449. void CGridSceneNode::removeGrid(irr::u32 index)
  450. {
  451. Grids.erase(index, 1);
  452. }
  453.  
  454. CGridSceneNode::SGrid& CGridSceneNode::getGrid(irr::u32 index)
  455. {
  456. return Grids[index];
  457. }
  458.  
  459. const CGridSceneNode::SGrid& CGridSceneNode::getGrid(irr::u32 index) const
  460. {
  461. return Grids[index];
  462. }
  463.  
  464. void CGridSceneNode::setGridsSize(const irr::core::dimension2df& newsize)
  465. {
  466. for ( irr::u32 i=0; i < Grids.size(); ++i )
  467. {
  468. Grids[i].setSize(newsize);
  469. }
  470. }
  471.  
Not running #stdin #stdout 0s 0KB
stdin
Standard input is empty
stdout
Standard output is empty