I edit the 23.SMeshHandling example to create my own terrainMesh (i don't want to use ITerrianSceneNode)
When i create this with CMeshBuffer it work exelent but need to create terrain bigger than 255x255 vertices.
Code: Select all
class TMesh
{
private:
u16 Width;
u16 Height;
f32 Scale;
core::array<f32> data;
public:
SMesh* Mesh;
TMesh() : Mesh(0), Width(0), Height(0), Scale(1.f)
{
Mesh = new SMesh();
}
~TMesh()
{
Mesh->drop();
}
void init(const IImage * hm, f32 scale, SColor cf, IVideoDriver *driver)
{
Scale = scale;
const u32 mp = driver -> getMaximalPrimitiveCount();
Width = hm->getDimension().Width;
Height = hm->getDimension().Height;
const u32 sw = mp / (6 * Height); // the width of each piece
u32 i=0;
for(u32 y0 = 0; y0 < Height; y0 += sw)
{
u16 y1 = y0 + sw;
if (y1 >= Height)
y1 = Height - 1; // the last one might be narrower
addstrip(hm, cf, y0, y1, i);
++i;
}
if (i<Mesh->getMeshBufferCount())
{
// clear the rest
for (u32 j=i; j<Mesh->getMeshBufferCount(); ++j)
{
Mesh->getMeshBuffer(j)->drop();
}
Mesh->MeshBuffers.erase(i,Mesh->getMeshBufferCount()-i);
}
Mesh->setDirty();
Mesh->recalculateBoundingBox();
}
// Generate a SMeshBuffer which represents all the vertices and
// indices for values of y between y0 and y1, and add it to the
// mesh.
f32 get(u16 x, u16 y) const { return data[y * Width + x]; }
vector3df getnormal(u16 x, u16 y, f32 s) const
{
const f32 zc = x+ y*Width;
f32 zl, zr, zu, zd;
if (x == 0)
{
zr = (x + 1)+ y * Width;
zl = zc + zc - zr;
}
else if (x == Width - 1)
{
zl = (x - 1)+ y * Width;
zr = zc + zc - zl;
}
else
{
zr = (x + 1)+ y * Width;
zl = (x - 1)+ y * Width;
}
if (y == 0)
{
zd = x + (y+ 1) * Width;
zu = zc + zc - zd;
}
else if (y == Height - 1)
{
zu = x+ (y- 1) * Width;
zd = zc + zc - zu;
}
else
{
zd = x+ (y+ 1) * Width;
zu = x+ (y- 1) * Width;
}
return vector3df(s * 2 * (zl - zr), 4, s * 2 * (zd - zu)).normalize();
}
void addstrip(const IImage* hm, SColor cf, u16 y0, u16 y1, u32 bufNum)
{
CDynamicMeshBuffer *buf = 0;
if (bufNum<Mesh->getMeshBufferCount())
{
buf = (CDynamicMeshBuffer*)Mesh->getMeshBuffer(bufNum);
}
else
{
// create new buffer
buf = new CDynamicMeshBuffer( EVT_STANDARD,EIT_32BIT);
Mesh->addMeshBuffer(buf);
// to simplify things we drop here but continue using buf
buf->drop();
}
int numberOfVertices=Height*Width;
buf->getVertexBuffer().set_used(numberOfVertices+1);
u32 i=0;
for (u16 y = y0; y <= y1; ++y)
{ cout<<"\nA"<<y<<" ";
for (u16 x = 0; x < Width; ++x)
{
const f32 z = SColor(hm->getPixel(x, y)).getLightness()/255;
const f32 xx = (f32)x/(f32)Width;
const f32 yy = (f32)y/(f32)Height;
cout<<x<<" ";
//video::S3DVertex2TCoords& v= static_cast<video::S3DVertex2TCoords*>(buf->getVertexBuffer().pointer())[i++];
S3DVertex& v = (buf->getVertexBuffer().pointer())[i++];
v.Pos.set(x, Scale * z, y);
v.Normal.set(getnormal(x, y, Scale));
v.Color.set(255,255,255,255);
v.TCoords.set(xx, yy);
}
}
buf->getIndexBuffer().set_used(6 * (Width - 1) * (y1 - y0));
i=0;
for(u16 y = y0; y < y1; ++y)
{
for(u16 x = 0; x < Width - 1; ++x)
{
const u16 n = (y-y0) * Width + x;
buf->getIndexBuffer().push_back(n);
buf->getIndexBuffer().push_back(n + Width);
buf->getIndexBuffer().push_back(n + Width + 1);
buf->getIndexBuffer().push_back(n + Width + 1);
buf->getIndexBuffer().push_back(n + 1);
buf->getIndexBuffer().push_back(n);
i+=6;
}
}
buf->recalculateBoundingBox();
}
};
PS: sorry for my English