namespace irr
{
namespace scene
{
struct SGrassElement
{
core::dimension2d<s32> sprite;
video::S3DVertex points[4];
};
class IGrassSceneNode : public ISceneNode
{
public :
IGrassSceneNode(ITerrainSceneNode* terrain, ISceneManager* mgr, s32 id, core::vector3d<s32> gridpos, char *filepath, video::IImage* heightMap, video::IImage* treeMap, video::IImage* grassMap, core::IWind *windgen);
virtual ~IGrassSceneNode();
virtual video::SMaterial& getMaterial(u32 i);
virtual u32 getMaterialCount() const;
virtual void OnRegisterSceneNode();
virtual void OnAnimate(u32 timeMs);
virtual void render();
virtual const irr::core::aabbox3d<irr::f32>& getBoundingBox() const;
void setImageCount(core::dimension2d<s32> ic);
core::dimension2d<s32> getImageCount();
void setDrawDistance(f32 draw);
f32 getDrawDistance();
void setMaxDensity(u32 max);
u32 getMaxDensity();
void setRefreshDelay(u32 ms);
u32 getRefreshDelay();
void setWindRes(u32 newres);
u32 getWindRes();
private :
video::IVideoDriver* m_driver;
core::array<SGrassElement> grassElement;
irr::u16 m_indices[6];
u32 m_windRes;
f32 m_drawDistance;
core::dimension2d<s32> imagecount;
core::dimension2d<f32> imagesize;
core::IWind *m_windGen;
s32 m_maxDensity;
irr::video::SMaterial m_material;
irr::core::aabbox3d<irr::f32> m_box;
u32 m_timeMs;
core::array<f32> v1;
core::array<f32> v2;
core::array<f32> v3;
core::array<f32> v4;
};
IGrassSceneNode::IGrassSceneNode(ITerrainSceneNode* terrain, ISceneManager* mgr, s32 id, core::vector3d<s32> gridpos, char *filepath, video::IImage* heightMap, video::IImage* treeMap, video::IImage* grassMap, core::IWind *windgen) :
ISceneNode((ITerrainSceneNode*)terrain, mgr, -1),
m_drawDistance(2),
m_maxDensity(800),
m_box(terrain->getBoundingBox()),
m_windGen(windgen)
{
m_driver = SceneManager->getVideoDriver();
m_material.Wireframe = false;
m_material.Lighting = false;
m_material.BackfaceCulling = false;
m_indices[0] = 3;
m_indices[1] = 2;
m_indices[2] = 0;
m_indices[3] = 0;
m_indices[4] = 2;
m_indices[5] = 1;
//setPosition(core::vector3df((f32)(gridpos.X*(terrain->getBoundingBox().MaxEdge - terrain->getBoundingBox().MinEdge).X),0 , (f32)(gridpos.Z*(terrain->getBoundingBox().MaxEdge - terrain->getBoundingBox().MinEdge).Z)));
setPosition(terrain->getPosition());
setWindRes(5);
setImageCount(core::dimension2d<s32>(4,2));
u32 m_timeMs = 0;
core::matrix4 m;
m.setRotationDegrees(terrain->getRotation());
m.setTranslation(terrain->getAbsolutePosition());
//------------------------------------------------------GRASS------------------------------------------------------
s32 count = 15000/*((terrain->getBoundingBox().MaxEdge - terrain->getBoundingBox().MinEdge).X * (terrain->getBoundingBox().MaxEdge - terrain->getBoundingBox().MinEdge).Z) / 100*/;
grassElement.set_used(count);
for(s32 i = 0; i < count; i++)
{
//initialisation
//texture
grassElement[i].sprite.Width = rand() % imagecount.Width;
if (i<30)
grassElement[i].sprite.Height = 1 *(rand() % imagecount.Height);
else
grassElement[i].sprite.Height = 0;
//position
f32 x = (rand() % (u32)(terrain->getTransformedBoundingBox().MaxEdge - terrain->getTransformedBoundingBox().MinEdge).X / 2);
f32 z = (rand() % (u32)(terrain->getTransformedBoundingBox().MaxEdge - terrain->getTransformedBoundingBox().MinEdge).Z / 2);
/*x -= (terrain->getBoundingBox().MaxEdge - terrain->getBoundingBox().MinEdge).X / 2;
z -= (terrain->getBoundingBox().MaxEdge - terrain->getBoundingBox().MinEdge).Z / 2;*/
f32 y = terrain->getHeight(x, z);
//rotation
f32 rotation = (rand() % 3600) / 10.0f;
//verification
irr::core::vector3df posElement(x, y, z);
m.transformVect(posElement);
core::vector3df p = getPosition() + posElement - terrain->getPosition();
core::vector3df xz(p.X/terrain->getScale().X,0.0f,p.Z/terrain->getScale().Z);
s32 x1 = (s32)floorf(xz.X);
s32 z1 = (s32)floorf(xz.Z);
//destruction si les herbes sont en dehors du terrain
if(terrain->getTransformedBoundingBox().isPointInside(p))
{
--count; --i;
grassElement.set_used(count);
continue;
}
//destruction si les herbes sont trop petites
video::SColor cDensity = grassMap->getPixel(x1,z1);
core::dimension2d<f32> size((f32)(rand() % 2 + 2), (f32)cDensity.getBlue()/5.0f);
if ((u32)(rand() % 255) > cDensity.getAlpha() || cDensity.getAlpha() < 1 )
{
--count; --i;
grassElement.set_used(count);
continue;
}
//definition
//calcul de la position des points
core::vector3df points[4];
points[0] = core::vector3df(x, y, z);
points[1] = core::vector3df(x + size.Width, y, z);
points[2] = core::vector3df(x + size.Width, y + size.Height, z);
points[3] = core::vector3df(x, y + size.Height, z);
//calcul de la rotation des points
s32 distance = sqrt(pow(size.Width, 2) + pow(size.Height, 2));
irr::core::vector3df rotToPos[2];
rotToPos[0].X = distance * cos(rotation);
rotToPos[0].Z = distance * sin(rotation);
rotToPos[0].Y = 0;
rotToPos[1].X = distance * cos(rotation + 180);
rotToPos[1].Z = distance * sin(rotation + 180);
rotToPos[1].Y = 0;
points[0] += rotToPos[0];
points[1] += rotToPos[0];
points[2] += rotToPos[0];
points[3] += rotToPos[0];
s32 indiceTxt1 = i % (imagecount.Width - 1);
s32 indiceTxt2 = i % (imagecount.Height - 1);
s32 arrpos = (imagecount.Width * grassElement[i].sprite.Height) + grassElement[i].sprite.Width;
grassElement[i].points[0] = video::S3DVertex(points[0].X, points[0].Y, points[0].Z, 0, 0, 0, irr::video::SColor(255,0,255,255), v1[arrpos], v2[arrpos]);
grassElement[i].points[1] = video::S3DVertex(points[1].X, points[1].Y, points[1].Z, 0, 0, 0, irr::video::SColor(255,0,255,255), v4[arrpos], v2[arrpos]);
grassElement[i].points[2] = video::S3DVertex(points[2].X, points[2].Y, points[2].Z, 0, 0, 0, irr::video::SColor(255,0,255,255), v4[arrpos], v3[arrpos]);
grassElement[i].points[3] = video::S3DVertex(points[3].X, points[3].Y, points[3].Z, 0, 0, 0, irr::video::SColor(255,0,255,255), v1[arrpos], v3[arrpos]);
}
//------------------------------------------------------TREE-------------------------------------------------------
//on verra ça après, il a suffisamment de problème avec les herbes
}
IGrassSceneNode::~IGrassSceneNode()
{
}
video::SMaterial& IGrassSceneNode::getMaterial(u32 i)
{
return m_material;
}
u32 IGrassSceneNode::getMaterialCount() const
{
return 1;
}
void IGrassSceneNode::OnRegisterSceneNode()
{
if(IsVisible)
SceneManager->registerNodeForRendering(this, irr::scene::ESNRP_SOLID);
ISceneNode::OnRegisterSceneNode();
}
void IGrassSceneNode::OnAnimate(u32 timeMs)
{
m_timeMs = timeMs;
ISceneNode::OnAnimate(timeMs);
}
void IGrassSceneNode::render()
{
m_driver->setMaterial(m_material);
m_driver->setTransform(irr::video::ETS_WORLD, AbsoluteTransformation);
irr::scene::ICameraSceneNode *camera = SceneManager->getActiveCamera();
for(u32 i = 0; i < grassElement.size(); i += (m_maxDensity) / 10)
{
std::cout<<i<<std::endl;
if((grassElement[i].points[0].Pos - camera->getPosition()).X < m_drawDistance && (grassElement[i].points[0].Pos - camera->getPosition()).Z < m_drawDistance)
{
std::cout<<i<<std::endl;
core::vector2df add = m_windGen->getWind(core::vector3df(0, 0, 0), m_timeMs);
add *= 0.75;
grassElement[i].points[2].Pos.Z += add.X;
grassElement[i].points[2].Pos.Y += add.Y;
grassElement[i].points[3].Pos.Z += add.X;
grassElement[i].points[3].Pos.Y += add.Y;
m_driver->drawIndexedTriangleList(&grassElement[i].points[0], 4, m_indices, 2);
grassElement[i].points[2].Pos.Z -= add.X;
grassElement[i].points[2].Pos.Y -= add.Y;
grassElement[i].points[3].Pos.Z -= add.X;
grassElement[i].points[3].Pos.Y -= add.Y;
}
}
}
void IGrassSceneNode::setWindRes(u32 newres)
{
m_windRes = newres;
}
u32 IGrassSceneNode::getWindRes()
{
return m_windRes;
}
core::dimension2d<s32> IGrassSceneNode::getImageCount()
{
return imagecount;
}
void IGrassSceneNode::setImageCount(core::dimension2d<s32> ic)
{
imagecount = ic;
imagesize.Width= 1.0f / f32(imagecount.Width);
imagesize.Height=1.0f / f32(imagecount.Height);
v1.set_used(imagecount.Width * imagecount.Height);
v2.set_used(imagecount.Width * imagecount.Height);
v3.set_used(imagecount.Width * imagecount.Height);
v4.set_used(imagecount.Width * imagecount.Height);
for (int x=0;x<imagecount.Width; ++x)
for (int y=0;y<imagecount.Height; ++y)
{
v1[ (imagecount.Width*y)+x ] = imagesize.Width * x;
v2[ (imagecount.Width*y)+x ] = imagesize.Height * (y+1);
v3[ (imagecount.Width*y)+x ] = imagesize.Height * y;
v4[ (imagecount.Width*y)+x ] = imagesize.Width * (x+1);
}
}
void IGrassSceneNode::setDrawDistance(f32 draw)
{
m_drawDistance = draw*draw;
}
f32 IGrassSceneNode::getDrawDistance()
{
return (f32)sqrt(m_drawDistance);
}
void IGrassSceneNode::setMaxDensity(u32 max)
{
m_maxDensity = max;
}
u32 IGrassSceneNode::getMaxDensity()
{
return m_maxDensity;
}
const irr::core::aabbox3d<irr::f32>& IGrassSceneNode::getBoundingBox() const
{
return m_box;
}
} // end namespace scene
} // end namespace irr
namespace map
{
Grass::Grass(GameEngine* scene, irr::scene::ITerrainSceneNode* terrain)
{
heightMap = scene->getDevice()->getVideoDriver()->createImageFromFile("heightmap.bmp");
textureMap = scene->getDevice()->getVideoDriver()->createImageFromFile("treemap.bmp");
grassMap = scene->getDevice()->getVideoDriver()->createImageFromFile("grassmap.png");
irr::video::ITexture* texture = scene->getDevice()->getVideoDriver()->getTexture("grass.png");
int height = 10;
int width = 10;
for (int x = 0; x < width; x++)
{
for (int z = 0; z < height; z++)
{
m_listeGrassNode.push_back(new irr::scene::IGrassSceneNode(terrain, scene->getDevice()->getSceneManager(), -1, irr::core::vector3d<irr::s32>(x,0,z), "grass", heightMap, textureMap, grassMap, scene->getWind()));
m_listeGrassNode[x*width + z]->setMaterialFlag(irr::video::EMF_LIGHTING, false);
m_listeGrassNode[x*width + z]->setMaterialType(irr::video::EMT_TRANSPARENT_ALPHA_CHANNEL);
m_listeGrassNode[x*width + z]->setMaterialTexture(0, texture);
m_listeGrassNode[x*width + z]->drop();
}
}
}
}