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. if ( !otherGrid.isVisible() )
  82. continue;
  83.  
  84. irr::core::vector2df otherLeftTop, otherRightBottom;
  85. otherGrid.calcGridInside(otherLeftTop, otherRightBottom);
  86. irr::f32 dist = axisX ? irr::core::abs_(pos - otherLeftTop.X) : irr::core::abs_(pos - otherLeftTop.Y);
  87. irr::f32 mod = fmodf(dist+epsilonHalf, otherGrid.getSpacing());
  88. if ( irr::core::equals( mod, 0.f, 2*epsilonHalf ) )
  89. return false;
  90. }
  91. return true;
  92. }
  93.  
  94.  
  95. void CGridSceneNode::SGrid::calcGridInside(irr::core::vector2df& leftTop, irr::core::vector2df& rightBottom) const
  96. {
  97. leftTop = irr::core::vector2df(0,0);
  98. rightBottom = leftTop;
  99.  
  100. //Set our corners
  101. if ( Alignment == CENTER )
  102. {
  103. rightBottom.X = Spacing * (int)(0.5f*Size.Width/Spacing);
  104. rightBottom.Y = Spacing * (int)(0.5f*Size.Height/Spacing);
  105. leftTop.X = -rightBottom.X;
  106. leftTop.Y = -rightBottom.Y;
  107. }
  108. else
  109. {
  110. leftTop.X = -Size.Width/2.f;
  111. leftTop.Y = -Size.Height/2.f;
  112. rightBottom.X = leftTop.X + Spacing * (int)(Size.Width/Spacing);
  113. rightBottom.Y = leftTop.Y + Spacing * (int)(Size.Height/Spacing);
  114. }
  115. leftTop.X += Offset.X;
  116. leftTop.Y += Offset.Z;
  117. rightBottom.X += Offset.X;
  118. rightBottom.Y += Offset.Z;
  119. }
  120.  
  121. void CGridSceneNode::SGrid::regenerateMesh(const CGridSceneNode* const gridNode)
  122. {
  123. GridDirty = false;
  124.  
  125. //Clean up memory
  126. MeshBuffer->getIndexBuffer().set_used(0);
  127. MeshBuffer->getVertexBuffer().set_used(0);
  128.  
  129. u32 numVertices = ((u32)(Size.Width / Spacing) + 1) * 2 + ((u32)(Size.Height / Spacing) + 1) * 2;
  130. if ( numVertices > 65535)
  131. {
  132. //Too many vertices on 16 bit for for 16bit indices of SMeshBuffer
  133. //Returning with a blank buffer to avoid segfaulting the entire application
  134. return;
  135. }
  136.  
  137. if ( Spacing <= 0 )
  138. return;
  139.  
  140. // inner has the last outside borders, while outer has the full size
  141. core::vector2df innerLeftTop, innerRightBottom;
  142. calcGridInside(innerLeftTop, innerRightBottom);
  143. core::vector3df outerLeftTop(-Size.Width/2.f,0,-Size.Height/2.f);
  144. core::vector3df outerRightBottom(Size.Width/2.f,0,Size.Height/2.f);
  145. outerLeftTop += Offset;
  146. outerRightBottom += Offset;
  147.  
  148. u32 indexIndex = 0;
  149.  
  150. //lines parallel to X-axis
  151. core::vector3df start = outerLeftTop;
  152. core::vector3df end = outerRightBottom;
  153. for (f32 x = 0.f; x <= (innerRightBottom.X - innerLeftTop.X); x+= Spacing)
  154. {
  155. start.X = x + innerLeftTop.X;
  156.  
  157. if ( !canUseGridLine(start.X, true, gridNode) )
  158. continue;
  159.  
  160. end.X = start.X;
  161.  
  162. MeshBuffer->getVertexBuffer().push_back(video::S3DVertex(start, core::vector3df(0,1,0), GridColor, core::vector2df(0.0f, 0.0f)));
  163. MeshBuffer->getVertexBuffer().push_back(video::S3DVertex(end, core::vector3df(0,1,0), GridColor, core::vector2df(0.0f, 0.0f)));
  164.  
  165. MeshBuffer->getIndexBuffer().push_back(indexIndex++);
  166. MeshBuffer->getIndexBuffer().push_back(indexIndex++);
  167. }
  168.  
  169. //lines parallel to Z-axis
  170. start = outerLeftTop;
  171. end = outerRightBottom;
  172. for (f32 z = 0.f; z <= (innerRightBottom.Y - innerLeftTop.Y); z+= Spacing)
  173. {
  174. start.Z = z + innerLeftTop.Y;
  175.  
  176. if ( !canUseGridLine(start.Z, false, gridNode) )
  177. continue;
  178.  
  179. end.Z = start.Z;
  180.  
  181. MeshBuffer->getVertexBuffer().push_back(video::S3DVertex(start, core::vector3df(0,1,0), GridColor, core::vector2df(0.0f, 0.0f)));
  182. MeshBuffer->getVertexBuffer().push_back(video::S3DVertex(end, core::vector3df(0,1,0), GridColor, core::vector2df(0.0f, 0.0f)));
  183.  
  184. MeshBuffer->getIndexBuffer().push_back(indexIndex++);
  185. MeshBuffer->getIndexBuffer().push_back(indexIndex++);
  186. }
  187.  
  188. // Create our box, it is the size of the grid exactly, plus 1 in the Y axis
  189. 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);
  190. bbox.MinEdge += Offset;
  191. bbox.MaxEdge += Offset;
  192. MeshBuffer->setBoundingBox(bbox);
  193.  
  194. BoundingBoxDirty = true;
  195. }
  196.  
  197. void CGridSceneNode::SGrid::setVisible(bool visible)
  198. {
  199. IsVisible = visible;
  200. GridDirty = true; // grids must be recalculated because they don't have lines used by another visible grid
  201. }
  202.  
  203. bool CGridSceneNode::SGrid::isVisible() const
  204. {
  205. return IsVisible;
  206. }
  207.  
  208. void CGridSceneNode::SGrid::setAlignment(CGridSceneNode::EAlign align)
  209. {
  210. Alignment = align;
  211. GridDirty = true;
  212. }
  213.  
  214. CGridSceneNode::EAlign CGridSceneNode::SGrid::getAlignment() const
  215. {
  216. return Alignment;
  217. }
  218.  
  219. void CGridSceneNode::SGrid::setSpacing(f32 newspacing)
  220. {
  221. Spacing = newspacing;
  222. GridDirty = true;
  223. }
  224.  
  225. f32 CGridSceneNode::SGrid::getSpacing() const
  226. {
  227. return Spacing;
  228. }
  229.  
  230. void CGridSceneNode::SGrid::setSize(const irr::core::dimension2df& newsize)
  231. {
  232. Size = newsize;
  233. GridDirty = true;
  234. }
  235.  
  236. const irr::core::dimension2df& CGridSceneNode::SGrid::getSize() const
  237. {
  238. return Size;
  239. }
  240.  
  241. void CGridSceneNode::SGrid::setOffset(const irr::core::vector3df& offset)
  242. {
  243. Offset = offset;
  244. GridDirty = true;
  245. }
  246.  
  247. const irr::core::vector3df& CGridSceneNode::SGrid::getOffset() const
  248. {
  249. return Offset;
  250. }
  251.  
  252. void CGridSceneNode::SGrid::setGridColor(video::SColor newcolor)
  253. {
  254. GridColor = newcolor;
  255. GridDirty = true;
  256. }
  257.  
  258. video::SColor CGridSceneNode::SGrid::getGridColor() const
  259. {
  260. return GridColor;
  261. }
  262.  
  263. void CGridSceneNode::SGrid::setMaxRenderDistance(irr::f32 dist)
  264. {
  265. MaxRenderDist = dist;
  266. }
  267.  
  268. irr::f32 CGridSceneNode::SGrid::getMaxRenderDistance() const
  269. {
  270. return MaxRenderDist;
  271. }
  272.  
  273. void CGridSceneNode::SGrid::setMaterial(const video::SMaterial& newMaterial)
  274. {
  275. MeshBuffer->getMaterial() = newMaterial;
  276. }
  277.  
  278. const irr::video::SMaterial& CGridSceneNode::SGrid::getMaterial() const
  279. {
  280. return MeshBuffer->getMaterial();
  281. }
  282.  
  283. irr::video::SMaterial& CGridSceneNode::SGrid::getMaterial()
  284. {
  285. return MeshBuffer->getMaterial();
  286. }
  287.  
  288. void CGridSceneNode::SGrid::getGridLines(irr::core::array<irr::core::line2df> &lines, const irr::core::matrix4* transformation) const
  289. {
  290. video::S3DVertex* vertices = MeshBuffer->getVertexBuffer().pointer();
  291. for ( u32 i=0; i < MeshBuffer->getVertexBuffer().size() / 2; ++i )
  292. {
  293. core::vector3df vs = vertices[i*2].Pos;
  294. core::vector3df ve = vertices[i*2+1].Pos;
  295.  
  296. if ( transformation )
  297. {
  298. transformation->transformVect(vs);
  299. transformation->transformVect(ve);
  300. }
  301.  
  302. lines.push_back( core::line2df( vs.X, vs.Z, ve.X, ve.Z) );
  303. }
  304. }
  305.  
  306. const irr::core::aabbox3d<irr::f32>& CGridSceneNode::SGrid::getBoundingBox() const
  307. {
  308. return MeshBuffer->getBoundingBox();
  309. }
  310.  
  311. void CGridSceneNode::SGrid::render(irr::video::IVideoDriver * driver )
  312. {
  313. if ( !isVisible() )
  314. return;
  315.  
  316. driver->setMaterial(MeshBuffer->getMaterial());
  317.  
  318. driver->drawVertexPrimitiveList(MeshBuffer->getVertexBuffer().getData(), // const void* vertices
  319. MeshBuffer->getVertexBuffer().size(), // u32 vertexCount
  320. MeshBuffer->getIndexBuffer().getData(), // const void* indexList
  321. MeshBuffer->getVertexBuffer().size()/2, // u32 primCount
  322. MeshBuffer->getVertexType(), // E_VERTEX_TYPE vType
  323. scene::EPT_LINES, // scene::E_PRIMITIVE_TYPE pType
  324. MeshBuffer->getIndexType() ); // E_INDEX_TYPE iType
  325. }
  326.  
  327.  
  328.  
  329. // ----------------------------------------------------------------------------
  330. CGridSceneNode::CGridSceneNode(ISceneNode* parent, scene::ISceneManager* smgr, s32 id, irr::u32 numGrids)
  331. : ISceneNode(parent, smgr, id), SelectionMesh(0), SelectionMeshBuffer(0), ShowSelectionOnce(false)
  332. {
  333. // Set the default culling state to Frustum Box
  334. AutomaticCullingState = scene::EAC_FRUSTUM_BOX;
  335.  
  336. for ( irr::u32 i=0; i<numGrids;++i )
  337. {
  338. Grids.push_back(SGrid());
  339. }
  340.  
  341. SelectionMeshBuffer = new irr::scene::CDynamicMeshBuffer(irr::video::EVT_STANDARD, irr::video::EIT_16BIT);
  342. SelectionMesh = new irr::scene::SMesh();
  343. SelectionMesh->addMeshBuffer( SelectionMeshBuffer );
  344. SelectionMeshBuffer->getMaterial().Wireframe = false;
  345. SelectionMeshBuffer->getMaterial().Lighting = false;
  346. SelectionMeshBuffer->getMaterial().FogEnable = false;
  347. SelectionMeshBuffer->getMaterial().BackfaceCulling = false;
  348. }
  349.  
  350. CGridSceneNode::~CGridSceneNode()
  351. {
  352. if ( SelectionMesh )
  353. SelectionMesh->drop();
  354. if ( SelectionMeshBuffer )
  355. SelectionMeshBuffer->drop();
  356. }
  357.  
  358. CGridSceneNode* CGridSceneNode::clone(scene::ISceneNode *newParent, scene::ISceneManager *newSceneManager)
  359. {
  360. if (!newParent) newParent = Parent;
  361. if (!newSceneManager) newSceneManager = SceneManager;
  362.  
  363. CGridSceneNode* clone = new CGridSceneNode(
  364. Parent,
  365. SceneManager,
  366. ID,
  367. Grids.size() );
  368. if (!clone)
  369. return 0;
  370.  
  371. for ( irr::u32 i=0; i< Grids.size(); ++i )
  372. {
  373. SGrid & grid = clone->getGrid(i);
  374. grid = getGrid(i);
  375. }
  376.  
  377. clone->drop();
  378. return clone;
  379. }
  380.  
  381. void CGridSceneNode::OnRegisterSceneNode()
  382. {
  383. if ( hasDirtyGrid() )
  384. regenerateMeshes();
  385. if( hasDirtyBoundingBox() )
  386. {
  387. rebuildBoundingBox();
  388. rebuildSelectionMesh();
  389. }
  390.  
  391. if (IsVisible)
  392. SceneManager->registerNodeForRendering(this);
  393.  
  394. ISceneNode::OnRegisterSceneNode();
  395. }
  396.  
  397. void CGridSceneNode::setGridVisibilityByDistToCamera()
  398. {
  399. for ( irr::u32 i=0; i<Grids.size(); ++i )
  400. {
  401. Grids[i].setVisible(true);
  402.  
  403. if ( !SceneManager->getActiveCamera()->isOrthogonal() )
  404. {
  405. irr::core::plane3df gridPlane(0,Grids[i].getOffset().Y,0,0,1,0);
  406. AbsoluteTransformation.transformPlane(gridPlane);
  407. irr::f32 distToCam = gridPlane.getDistanceTo( SceneManager->getActiveCamera()->getAbsolutePosition() );
  408. if ( !SceneManager->getActiveCamera()->isOrthogonal() && distToCam > Grids[i].getMaxRenderDistance() )
  409. {
  410. Grids[i].setVisible(false);
  411. }
  412. }
  413. }
  414. }
  415.  
  416. void CGridSceneNode::render()
  417. {
  418. video::IVideoDriver* driver = SceneManager->getVideoDriver();
  419.  
  420. if ( !driver )
  421. return;
  422.  
  423. // setGridVisibilityByDistToCamera();
  424.  
  425. driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
  426. for ( irr::u32 i=0; i<Grids.size(); ++i )
  427. {
  428. Grids[i].render(driver);
  429. }
  430.  
  431. if ( ShowSelectionOnce )
  432. {
  433. ShowSelectionOnce = false;
  434. driver->setMaterial(SelectionMeshBuffer->getMaterial());
  435.  
  436. driver->drawVertexPrimitiveList(SelectionMeshBuffer->getVertexBuffer().getData(), // const void* vertices
  437. SelectionMeshBuffer->getVertexBuffer().size(), // u32 vertexCount
  438. SelectionMeshBuffer->getIndexBuffer().getData(), // const void* indexList
  439. SelectionMeshBuffer->getIndexBuffer().size()/3, // u32 primCount
  440. SelectionMeshBuffer->getVertexType(), // E_VERTEX_TYPE vType
  441. scene::EPT_TRIANGLES, // scene::E_PRIMITIVE_TYPE pType
  442. SelectionMeshBuffer->getIndexType() ); // E_INDEX_TYPE iType
  443. }
  444. }
  445.  
  446. bool CGridSceneNode::hasDirtyBoundingBox() const
  447. {
  448. bool hasDirty = false;
  449. for ( irr::u32 i=0; i<Grids.size(); ++i )
  450. {
  451. if ( Grids[i].BoundingBoxDirty )
  452. {
  453. hasDirty = true;
  454. break;
  455. }
  456. }
  457. return hasDirty;
  458. }
  459.  
  460. bool CGridSceneNode::hasDirtyGrid() const
  461. {
  462. bool hasDirty = false;
  463. for ( irr::u32 i=0; i<Grids.size(); ++i )
  464. {
  465. if ( Grids[i].GridDirty )
  466. {
  467. hasDirty = true;
  468. break;
  469. }
  470. }
  471. return hasDirty;
  472. }
  473.  
  474. void CGridSceneNode::regenerateMeshes()
  475. {
  476. for ( irr::u32 i=0; i<Grids.size(); ++i )
  477. {
  478. Grids[i].regenerateMesh(this);
  479. }
  480. }
  481.  
  482. void CGridSceneNode::rebuildBoundingBox()
  483. {
  484. if ( Grids.empty() )
  485. BoundingBox.reset( irr::core::vector3df(FLT_MAX,FLT_MAX,FLT_MAX) );
  486. else
  487. {
  488. // recalculate when one boundingbox has changed
  489. bool hasDirty = false;
  490. for ( irr::u32 i=0; i<Grids.size(); ++i )
  491. {
  492. if ( Grids[i].BoundingBoxDirty )
  493. {
  494. hasDirty = true;
  495. break;
  496. }
  497. }
  498.  
  499. if ( hasDirty )
  500. {
  501. BoundingBox = Grids[0].getBoundingBox();
  502. Grids[0].BoundingBoxDirty = false;
  503. for ( irr::u32 i=1; i<Grids.size(); ++i )
  504. {
  505. BoundingBox.addInternalBox( Grids[i].getBoundingBox() );
  506. Grids[i].BoundingBoxDirty = false;
  507. }
  508. }
  509. }
  510. }
  511.  
  512. void CGridSceneNode::rebuildSelectionMesh()
  513. {
  514. SelectionMeshBuffer->getVertexBuffer().reallocate(4);
  515. SelectionMeshBuffer->getVertexBuffer().set_used(0);
  516.  
  517. irr::video::SColor col(128, 0, 0, 255);
  518. irr::core::vector3df edges[8];
  519. BoundingBox.getEdges(edges);
  520. irr::video::S3DVertex* vertices = SelectionMeshBuffer->getVertexBuffer().pointer();
  521. for ( int i=0; i<4; ++i )
  522. SelectionMeshBuffer->getVertexBuffer().push_back ( video::S3DVertex((edges[i*2]+edges[i*2+1])/2, core::vector3df(0,1,0), col, core::vector2df(0.0f, 0.0f)) );
  523.  
  524. if ( SelectionMeshBuffer->getIndexBuffer().size() < 6 )
  525. {
  526. SelectionMeshBuffer->getIndexBuffer().reallocate(6);
  527. SelectionMeshBuffer->getIndexBuffer().set_used(0);
  528. SelectionMeshBuffer->getIndexBuffer().push_back(0);
  529. SelectionMeshBuffer->getIndexBuffer().push_back(1);
  530. SelectionMeshBuffer->getIndexBuffer().push_back(2);
  531. SelectionMeshBuffer->getIndexBuffer().push_back(2);
  532. SelectionMeshBuffer->getIndexBuffer().push_back(1);
  533. SelectionMeshBuffer->getIndexBuffer().push_back(3);
  534. }
  535.  
  536. SelectionMeshBuffer->setDirty();
  537.  
  538. irr::scene::ITriangleSelector * s = SceneManager->createTriangleSelector(SelectionMesh, this);
  539. setTriangleSelector(s);
  540. s->drop();
  541. }
  542.  
  543. const core::aabbox3d<f32>& CGridSceneNode::getBoundingBox() const
  544. {
  545. return BoundingBox;
  546. }
  547.  
  548. u32 CGridSceneNode::getMaterialCount() const
  549. {
  550. return Grids.size();
  551. }
  552.  
  553. video::SMaterial& CGridSceneNode::getMaterial(u32 i)
  554. {
  555. return Grids[i].getMaterial();
  556. }
  557.  
  558. irr::u32 CGridSceneNode::getNumberOfGrids() const
  559. {
  560. return Grids.size();
  561. }
  562.  
  563. irr::u32 CGridSceneNode::addGrid()
  564. {
  565. Grids.push_back(SGrid());
  566. return Grids.size()-1;
  567. }
  568.  
  569. void CGridSceneNode::removeGrid(irr::u32 index)
  570. {
  571. Grids.erase(index, 1);
  572. }
  573.  
  574. CGridSceneNode::SGrid& CGridSceneNode::getGrid(irr::u32 index)
  575. {
  576. return Grids[index];
  577. }
  578.  
  579. const CGridSceneNode::SGrid& CGridSceneNode::getGrid(irr::u32 index) const
  580. {
  581. return Grids[index];
  582. }
  583.  
  584. void CGridSceneNode::setGridsSize(const irr::core::dimension2df& newsize)
  585. {
  586. GridsSize = newsize;
  587. for ( irr::u32 i=0; i < Grids.size(); ++i )
  588. {
  589. Grids[i].setSize(newsize);
  590. }
  591. }
  592.  
  593. const irr::core::dimension2df& CGridSceneNode::getGridsSize() const
  594. {
  595. return GridsSize;
  596. }
  597.  
Not running #stdin #stdout 0s 0KB
stdin
Standard input is empty
stdout
Standard output is empty