#include "CGridSceneNode.h"
using namespace irr;
CGridSceneNode::CGridSceneNode(ISceneNode* parent, scene::ISceneManager* smgr, s32 id,
u32 spacing, u32 size, video::SColor gridcolor, u32 accentlineoffset,
video::SColor accentgridcolor, bool axislinestate) : ISceneNode(parent, smgr, id),
m_spacing(spacing), m_size(size),
m_gridcolor(gridcolor), m_accentgridcolor(accentgridcolor),
m_accentlineoffset(accentlineoffset), m_AxisLineState(axislinestate),
m_XLineColor(video::SColor(255,255,0,0)), m_ZLineColor(video::SColor(255,0,0,255)), m_YLineColor(video::SColor(255,0,255,0)),
m_buffer(0)
{
// Set the material
m_buffer = new irr::scene::CDynamicMeshBuffer(irr::video::EVT_STANDARD, irr::video::EIT_16BIT);
m_buffer->getMaterial().Wireframe = false;
m_buffer->getMaterial().Lighting = false;
m_buffer->getMaterial().Thickness = 1;
m_buffer->getMaterial().FogEnable = false;
m_buffer->getMaterial().ZWriteEnable = false;
m_buffer->getMaterial().BackfaceCulling = true;
m_buffer->getMaterial().AntiAliasing = true;
// Set the default culling state to Frustum Box
AutomaticCullingState = scene::EAC_FRUSTUM_BOX;
RegenerateGrid();
}
CGridSceneNode::~CGridSceneNode()
{
if ( m_buffer )
m_buffer->drop();
}
CGridSceneNode* CGridSceneNode::clone(scene::ISceneNode *newParent, scene::ISceneManager *newSceneManager)
{
if (!newParent) newParent = Parent;
if (!newSceneManager) newSceneManager = SceneManager;
CGridSceneNode* clone = new CGridSceneNode(
Parent,
SceneManager,
ID,
m_spacing,
m_size*2,
m_gridcolor,
m_accentlineoffset,
m_accentgridcolor,
m_AxisLineState);
if (!clone)
return 0x0;
clone->SetAxisLineXColor(m_XLineColor);
clone->SetAxisLineZColor(m_ZLineColor);
clone->SetMaterial(m_buffer->getMaterial());
clone->drop();
return clone;
}
void CGridSceneNode::OnRegisterSceneNode()
{
if (IsVisible)
SceneManager->registerNodeForRendering(this);
ISceneNode::OnRegisterSceneNode();
}
void CGridSceneNode::RegenerateGrid()
{
//Clean up memory
m_buffer->getIndexBuffer().set_used(0);
m_buffer->getVertexBuffer().set_used(0);
u32 m_numVertices = ((m_size / m_spacing) + 1) * 2 * 2;
if (m_accentlineoffset) m_numVertices += ((m_size / (m_spacing * m_accentlineoffset)) + 1) * 2 * 2;
if ( m_numVertices > 65535)
{
//Too many vertices on 16 bit for for 16bit indices of SMeshBuffer
//Returning with a blank buffer to avoid segfaulting the entire application
return;
}
//Set our left corner
core::vector3df leftMost = core::vector3df(0,0,0);
leftMost.X -= m_size/2;
leftMost.Z -= m_size/2;
//Set our right corner
core::vector3df rightMost = core::vector3df(0,0,0);
rightMost.X += m_size/2;
rightMost.Z += m_size/2;
u32 indexIndex = 0;
//X-axis lines
for (u32 x = 0; x <= m_size; x+= m_spacing)
{
core::vector3df start = leftMost;
start.X += x ;
core::vector3df end = rightMost;
end.X = start.X;
m_buffer->getVertexBuffer().push_back(video::S3DVertex(start, core::vector3df(0,1,0), m_gridcolor, core::vector2df(0.0f, 0.0f)));
m_buffer->getVertexBuffer().push_back(video::S3DVertex(end, core::vector3df(0,1,0), m_gridcolor, core::vector2df(0.0f, 0.0f)));
m_buffer->getIndexBuffer().push_back(indexIndex++);
m_buffer->getIndexBuffer().push_back(indexIndex++);
}
//Z-axis lines
for (u32 z = 0; z <= m_size; z+= m_spacing)
{
core::vector3df start = leftMost;
start.Z += z ;
core::vector3df end = rightMost;
end.Z = start.Z;
m_buffer->getVertexBuffer().push_back(video::S3DVertex(start, core::vector3df(0,1,0), m_gridcolor, core::vector2df(0.0f, 0.0f)));
m_buffer->getVertexBuffer().push_back(video::S3DVertex(end, core::vector3df(0,1,0), m_gridcolor, core::vector2df(0.0f, 0.0f)));
m_buffer->getIndexBuffer().push_back(indexIndex++);
m_buffer->getIndexBuffer().push_back(indexIndex++);
}
//Accent lines are only drawn if the offset is greater than 0
if (m_accentlineoffset > 0)
{
//X-axis
for (u32 x = 0; x <= m_size; x+= m_spacing*m_accentlineoffset)
{
core::vector3df start = leftMost;
start.X += x ;
core::vector3df end = rightMost;
end.X = start.X;
m_buffer->getVertexBuffer().push_back(video::S3DVertex(start, core::vector3df(0,1,0), m_accentgridcolor, core::vector2df(0.0f, 0.0f)));
m_buffer->getVertexBuffer().push_back(video::S3DVertex(end, core::vector3df(0,1,0), m_accentgridcolor, core::vector2df(0.0f, 0.0f)));
m_buffer->getIndexBuffer().push_back(indexIndex++);
m_buffer->getIndexBuffer().push_back(indexIndex++);
}
//Z-axis
for (u32 z = 0; z <= m_size; z+= m_spacing*m_accentlineoffset)
{
core::vector3df start = leftMost;
start.Z += z ;
core::vector3df end = rightMost;
end.Z = start.Z;
m_buffer->getVertexBuffer().push_back(video::S3DVertex(start, core::vector3df(0,1,0), m_accentgridcolor, core::vector2df(0.0f, 0.0f)));
m_buffer->getVertexBuffer().push_back(video::S3DVertex(end, core::vector3df(0,1,0), m_accentgridcolor, core::vector2df(0.0f, 0.0f)));
m_buffer->getIndexBuffer().push_back(indexIndex++);
m_buffer->getIndexBuffer().push_back(indexIndex++);
}
}
// Create our box, it is the size of the grid exactly, plus 1 in the Y axis
m_buffer->setBoundingBox( core::aabbox3df(-(f32)m_size/2,-0.5f,-(f32)m_size/2,(f32)m_size/2,0.5f,(f32)m_size/2) );
}
void CGridSceneNode::render()
{
video::IVideoDriver* driver = SceneManager->getVideoDriver();
//Prep to render
if (driver)
{
driver->setMaterial(m_buffer->getMaterial());
driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
driver->drawVertexPrimitiveList(m_buffer->getVertexBuffer().getData(), // const void* vertices
m_buffer->getVertexBuffer().size(), //u32 vertexCount
m_buffer->getIndexBuffer().getData(), // const void* indexList
m_buffer->getVertexBuffer().size()/2, // u32 primCount
m_buffer->getVertexType(), // E_VERTEX_TYPE vType
scene::EPT_LINES, // scene::E_PRIMITIVE_TYPE pType
m_buffer->getIndexType() ); // E_INDEX_TYPE iType
// Axis Lines are only drawn if the State is true
if (m_AxisLineState)
{
m_buffer->getMaterial().Thickness = 3;
driver->setMaterial(m_buffer->getMaterial());
driver->draw3DLine(core::vector3df(0,0,0),core::vector3df(0.5f,0,0), m_XLineColor);
driver->draw3DLine(core::vector3df(0,0,0),core::vector3df(0,0.5f,0), m_YLineColor);
driver->draw3DLine(core::vector3df(0,0,0),core::vector3df(0,0,0.5f), m_ZLineColor);
m_buffer->getMaterial().Thickness = 1;
driver->setMaterial(m_buffer->getMaterial());
}
}
}
const core::aabbox3d<f32>& CGridSceneNode::getBoundingBox() const
{
return m_buffer->getBoundingBox();
}
u32 CGridSceneNode::getMaterialCount() const
{
return 1;
}
video::SMaterial& CGridSceneNode::getMaterial(u32 i)
{
return m_buffer->getMaterial();
}
u32 CGridSceneNode::GetSpacing()
{
return m_spacing;
}
u32 CGridSceneNode::GetSize()
{
return m_size;
}
u32 CGridSceneNode::GetAccentlineOffset()
{
return m_accentlineoffset;
}
video::SColor CGridSceneNode::GetAccentlineColor()
{
return m_accentgridcolor;
}
video::SColor CGridSceneNode::GetGridColor()
{
return m_gridcolor;
}
bool CGridSceneNode::AreAxisLineActive()
{
return m_AxisLineState;
}
video::SColor CGridSceneNode::GetAxisLineXColor()
{
return m_XLineColor;
}
video::SColor CGridSceneNode::GetAxisLineZColor()
{
return m_ZLineColor;
}
void CGridSceneNode::SetSpacing(u32 newspacing)
{
m_spacing = newspacing;
RegenerateGrid();
}
void CGridSceneNode::SetSize(u32 newsize)
{
m_size = newsize;
RegenerateGrid();
}
void CGridSceneNode::SetAccentlineColor(video::SColor newcolor)
{
m_accentgridcolor = newcolor;
RegenerateGrid();
}
void CGridSceneNode::SetAccentlineOffset(u32 newoffset)
{
m_accentlineoffset = newoffset;
RegenerateGrid();
}
void CGridSceneNode::SetGridColor(video::SColor newcolor)
{
m_gridcolor = newcolor;
RegenerateGrid();
}
void CGridSceneNode::SetAxisLineActive(bool active)
{
m_AxisLineState = active;
}
void CGridSceneNode::SetAxisLineXColor(video::SColor XLine)
{
m_XLineColor = XLine;
}
void CGridSceneNode::SetAxisLineZColor(video::SColor ZLine)
{
m_ZLineColor = ZLine;
}
void CGridSceneNode::SetMaterial(video::SMaterial newMaterial)
{
m_buffer->getMaterial() = newMaterial;
}