Performance improvement for terrainmesh generation.

git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@1356 dfc29bdd-3216-0410-991c-e03cc46cb475
master
hybrid 2008-05-30 12:10:24 +00:00
parent 8ee7c89b14
commit 464c714f39
1 changed files with 34 additions and 28 deletions

View File

@ -31,7 +31,7 @@ IMesh* CGeometryCreator::createHillPlaneMesh(
countHills.Height = 1.f; countHills.Height = 1.f;
// center // center
const core::position2d<f32> center((tileSize.Width * tileCount.Width) / 2.0f, (tileSize.Height * tileCount.Height) / 2.0f); const core::position2d<f32> center((tileSize.Width * tileCount.Width) * 0.5f, (tileSize.Height * tileCount.Height) * 0.5f);
// texture coord step // texture coord step
const core::dimension2d<f32> tx( const core::dimension2d<f32> tx(
@ -59,9 +59,9 @@ IMesh* CGeometryCreator::createHillPlaneMesh(
vtx.TCoords.set(tsx, 1.0f - tsy); vtx.TCoords.set(tsx, 1.0f - tsy);
if (hillHeight != 0.0f) if (hillHeight != 0.0f)
vtx.Pos.Y = (f32)(sin(vtx.Pos.X * countHills.Width * core::PI / center.X) * vtx.Pos.Y = sinf(vtx.Pos.X * countHills.Width * core::PI / center.X) *
cos(vtx.Pos.Z * countHills.Height * core::PI / center.Y)) cosf(vtx.Pos.Z * countHills.Height * core::PI / center.Y) *
*hillHeight; hillHeight;
buffer->Vertices.push_back(vtx); buffer->Vertices.push_back(vtx);
sy += tileSize.Height; sy += tileSize.Height;
@ -136,9 +136,8 @@ IMesh* CGeometryCreator::createTerrainMesh(video::IImage* texture,
const u32 tm = os::Timer::getRealTime()/1000; const u32 tm = os::Timer::getRealTime()/1000;
const core::dimension2d<s32> hMapSize= heightmap->getDimension(); const core::dimension2d<s32> hMapSize= heightmap->getDimension();
const core::dimension2d<s32> tMapSize= texture->getDimension(); const core::dimension2d<s32> tMapSize= texture->getDimension();
const core::position2d<f32> thRel((f32)tMapSize.Width / hMapSize.Width, (f32)tMapSize.Height / hMapSize.Height); const core::position2d<f32> thRel(static_cast<f32>(tMapSize.Width) / hMapSize.Width, static_cast<f32>(tMapSize.Height) / hMapSize.Height);
maxHeight /= 255.0f; // height step per color value
video::SMaterial material;
core::position2d<s32> processed(0,0); core::position2d<s32> processed(0,0);
while (processed.Y<hMapSize.Height) while (processed.Y<hMapSize.Height)
@ -152,32 +151,39 @@ IMesh* CGeometryCreator::createTerrainMesh(video::IImage* texture,
blockSize.Height = hMapSize.Height - processed.Y; blockSize.Height = hMapSize.Height - processed.Y;
SMeshBuffer* buffer = new SMeshBuffer(); SMeshBuffer* buffer = new SMeshBuffer();
buffer->setHardwareMappingHint(scene::EHM_STATIC);
buffer->Vertices.reallocate(blockSize.getArea());
// add vertices of vertex block // add vertices of vertex block
s32 y; s32 y;
core::vector2df pos(0.f, processed.Y*stretchSize.Height);
const core::vector2df bs(1.f/blockSize.Width, 1.f/blockSize.Height);
core::vector2df tc(0.f, 0.5f*bs.Y);
for (y=0; y<blockSize.Height; ++y) for (y=0; y<blockSize.Height; ++y)
{ {
pos.X=processed.X*stretchSize.Width;
tc.X=0.5f*bs.X;
for (s32 x=0; x<blockSize.Width; ++x) for (s32 x=0; x<blockSize.Width; ++x)
{ {
video::SColor clr = heightmap->getPixel(x+processed.X, y+processed.Y); const f32 height = heightmap->getPixel(x+processed.X, y+processed.Y).getAverage() * maxHeight;
const f32 height = ((clr.getRed() + clr.getGreen() + clr.getBlue()) / 3.0f)/255.0f * maxHeight;
vtx.Pos.set((f32)(x+processed.X) * stretchSize.Width, vtx.Pos.set(pos.X, height, pos.Y);
height, (f32)(y+processed.Y) * stretchSize.Height); vtx.TCoords.set(tc);
vtx.TCoords.set((x+0.5f) / blockSize.Width,
(y+0.5f) / blockSize.Height);
buffer->Vertices.push_back(vtx); buffer->Vertices.push_back(vtx);
pos.X += stretchSize.Width;
tc.X += bs.X;
} }
pos.Y += stretchSize.Height;
tc.Y += bs.Y;
} }
buffer->Indices.reallocate((blockSize.Height-1)*(blockSize.Width-1)*6);
// add indices of vertex block // add indices of vertex block
for (y=0; y<blockSize.Height-1; ++y) for (y=0; y<blockSize.Height-1; ++y)
{ {
s32 c1 = 0;
for (s32 x=0; x<blockSize.Width-1; ++x) for (s32 x=0; x<blockSize.Width-1; ++x)
{ {
s32 c = (y*blockSize.Width) + x; const s32 c = c1 + x;
buffer->Indices.push_back(c); buffer->Indices.push_back(c);
buffer->Indices.push_back(c + blockSize.Width); buffer->Indices.push_back(c + blockSize.Width);
@ -187,10 +193,11 @@ IMesh* CGeometryCreator::createTerrainMesh(video::IImage* texture,
buffer->Indices.push_back(c + blockSize.Width); buffer->Indices.push_back(c + blockSize.Width);
buffer->Indices.push_back(c + 1 + blockSize.Width); buffer->Indices.push_back(c + 1 + blockSize.Width);
} }
c1 += blockSize.Width;
} }
// recalculate normals // recalculate normals
for (s32 i=0; i<(s32)buffer->Indices.size(); i+=3) for (u32 i=0; i<buffer->Indices.size(); i+=3)
{ {
core::plane3d<f32> p( core::plane3d<f32> p(
buffer->Vertices[buffer->Indices[i+0]].Pos, buffer->Vertices[buffer->Indices[i+0]].Pos,
@ -213,21 +220,20 @@ IMesh* CGeometryCreator::createTerrainMesh(video::IImage* texture,
sprintf(textureName, "terrain%u_%u", tm, mesh->getMeshBufferCount()); sprintf(textureName, "terrain%u_%u", tm, mesh->getMeshBufferCount());
material.setTexture(0, driver->addTexture(textureName, img)); buffer->Material.setTexture(0, driver->addTexture(textureName, img));
if (material.getTexture(0)) if (buffer->Material.getTexture(0))
{ {
c8 tmp[255]; c8 tmp[255];
sprintf(tmp, "Generated terrain texture (%dx%d): %s", sprintf(tmp, "Generated terrain texture (%dx%d): %s",
material.getTexture(0)->getSize().Width, buffer->Material.getTexture(0)->getSize().Width,
material.getTexture(0)->getSize().Height, buffer->Material.getTexture(0)->getSize().Height,
textureName); textureName);
os::Printer::log(tmp); os::Printer::log(tmp);
} }
else else
os::Printer::log("Could not create terrain texture.", textureName, ELL_ERROR); os::Printer::log("Could not create terrain texture.", textureName, ELL_ERROR);
buffer->Material = material;
img->drop(); img->drop();
} }
@ -581,9 +587,9 @@ IMesh* CGeometryCreator::createSphereMesh(f32 radius, u32 polyCountX, u32 polyCo
{ {
// calculate points position // calculate points position
const core::vector3df pos((f32)(radius * cos(axz) * sinay), const core::vector3df pos(static_cast<f32>(radius * cos(axz) * sinay),
(f32)(radius * cos(ay)), static_cast<f32>(radius * cos(ay)),
(f32)(radius * sin(axz) * sinay)); static_cast<f32>(radius * sin(axz) * sinay));
// for spheres the normal is the position // for spheres the normal is the position
core::vector3df normal(pos); core::vector3df normal(pos);
normal.normalize(); normal.normalize();
@ -594,7 +600,7 @@ IMesh* CGeometryCreator::createSphereMesh(f32 radius, u32 polyCountX, u32 polyCo
if (y==0) if (y==0)
{ {
if (normal.Y != -1.0f && normal.Y != 1.0f) if (normal.Y != -1.0f && normal.Y != 1.0f)
tu = (f32)(acos(core::clamp(normal.X/sinay, -1.0, 1.0)) * 0.5 *core::RECIPROCAL_PI64); tu = static_cast<f32>(acos(core::clamp(normal.X/sinay, -1.0, 1.0)) * 0.5 *core::RECIPROCAL_PI64);
if (normal.Z < 0.0f) if (normal.Z < 0.0f)
tu=1-tu; tu=1-tu;
} }
@ -603,7 +609,7 @@ IMesh* CGeometryCreator::createSphereMesh(f32 radius, u32 polyCountX, u32 polyCo
buffer->Vertices[i] = video::S3DVertex(pos.X, pos.Y, pos.Z, buffer->Vertices[i] = video::S3DVertex(pos.X, pos.Y, pos.Z,
normal.X, normal.Y, normal.Z, normal.X, normal.Y, normal.Z,
clr, tu, clr, tu,
(f32)(ay*core::RECIPROCAL_PI64)); static_cast<f32>(ay*core::RECIPROCAL_PI64));
++i; ++i;
axz += AngleX; axz += AngleX;
} }