Vegetation Maps || Just a thought
Heh, I thought I'd give it a shot:
The code:
Note that this doesn't care about scales etc. I tried this with a 1024x1024 vegetation map, a 1024x1024 terrain texture and 64x64 heightmap. I used addTerrainMesh instead of addTerrainSceneNode, and then made a IAnimatedMeshSceneNode. That's because the class needs access to the mesh, which the terrain scene node doesn't support. A little note: the class assumes that the terrain node is placed at (0,0,0) and that maxHeight = 200 (oh yeah, I haven't made the destructor function either. Well, consider this as a prototype then... ).
The code:
Code: Select all
class CVegetation
{
public:
CVegetation(IAnimatedMeshSceneNode* terrainNode, IAnimatedMesh* terrainMesh, IImage* vegetationMap);
~CVegetation() {}
protected:
IAnimatedMeshSceneNode* m_terrainNode;
IAnimatedMesh* m_terrainMesh;
ITriangleSelector* m_triselector;
IImage* m_vegetationMap;
void createVegetation();
void checkPoint(int x, int y);
void placeObject(vector3df location);
};
CVegetation::CVegetation(IAnimatedMeshSceneNode* terrainNode, IAnimatedMesh* terrainMesh, IImage* vegetationMap)
{
m_terrainNode = terrainNode;
m_terrainMesh = terrainMesh;
m_vegetationMap = vegetationMap;
m_vegetationMap->grab();
m_triselector = g_pSceneManager->createOctTreeTriangleSelector(m_terrainMesh->getMesh(0), m_terrainNode);
m_terrainNode->setTriangleSelector(m_triselector);
this->createVegetation();
}
void CVegetation::createVegetation()
{
dimension2d<s32> dimension = m_vegetationMap->getDimension();
SColor pixel;
for (int i = dimension.Height; i; i--)
{
for (int j = dimension.Width; j; j--)
{
pixel = m_vegetationMap->getPixel(i, j);
if (pixel.color == 0) // Entirely black
this->checkPoint(i, j);
}
}
}
void CVegetation::checkPoint(int x, int y)
{
vector3df position;
line3d<f32> traceline(x, 200, y, x, 0, y);
triangle3df triangle;
if (g_pSceneManager->getSceneCollisionManager()->getCollisionPoint(traceline, m_triselector, position, triangle))
this->placeObject(position);
}
void CVegetation::placeObject(vector3df location)
{
// Only place grass in 6 of 10 cases, for the sake of randomness
if (RAND10() > 6) return;
// Move the billboard up a bit
location.Y += 24;
ISceneNode* grassNode;
ITexture* grassTexture;
if (RAND10() > 5)
{
grassNode = g_pSceneManager->addBillboardSceneNode(0, dimension2d<f32>(24, 64), location);
grassTexture = g_pDriver->getTexture("grass2.bmp");
}
else
{
grassNode = g_pSceneManager->addBillboardSceneNode(0, dimension2d<f32>(64, 48), location);
grassTexture = g_pDriver->getTexture("grass.bmp");
}
grassNode->setMaterialTexture(0, grassTexture);
grassNode->setMaterialFlag(EMF_LIGHTING, false);
grassNode->setMaterialType(EMT_TRANSPARENT_ADD_COLOR);
}
I think computing the positions for vegetation is overkill... placing them randomly may be ok, but that TriangleSelector will only work with very small areas.
This approach could be used in an editor which stores the generated data to a file that is later on used for terrain/veg.-loading
This approach could be used in an editor which stores the generated data to a file that is later on used for terrain/veg.-loading
Hardwarespecs in signatures suck !