Advice needed about a custom tiled zone system

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
Post Reply
Linaxys
Posts: 47
Joined: Tue Feb 24, 2009 10:46 pm

Advice needed about a custom tiled zone system

Post by Linaxys »

(EXE to see : http://www.mediafire.com/download.php?mjzumjkm0r3)

Hello,
I have a big lack of optimizations in my tiled zone system.
I would like to make a really infinite ground that we can edit with the mouse.

Here is how I build the mesh to be tiled :

Image

Code: Select all

	SMesh *newMesh = new SMesh();
	video::SColor color(0xFFFFFFFF);
	SMeshBuffer* mb;

	for (f32 e = 0.0f; e < 10; e += 2.0f) {
		for (f32 i = 0.0f; i < 10; i += 2.0f) {
			mb = new SMeshBuffer();

			mb->Vertices.push_back(video::S3DVertex( -50+50*e, 0 ,  50+50*i, 1, 1, 1, color ,0 ,0));
			mb->Vertices.push_back(video::S3DVertex(  50+50*e, 0 ,  50+50*i, 1, 1, 1, color ,1 ,0));
			mb->Vertices.push_back(video::S3DVertex(  50+50*e, 0 , -50+50*i, 1, 1, 1, color ,1 ,1));
			mb->Vertices.push_back(video::S3DVertex( -50+50*e, 0 , -50+50*i, 1, 1, 1, color ,0 ,1));
			mb->Indices.push_back(0);
			mb->Indices.push_back(1);
			mb->Indices.push_back(2);
			mb->Indices.push_back(0);
			mb->Indices.push_back(2);
			mb->Indices.push_back(3);

			//mb->getMaterial().setTexture(0,grassTexture);

			mb->recalculateBoundingBox();
			newMesh->addMeshBuffer(mb);
		}
		for (f32 i = 0.0f; i < 10; i += 2.0f) {
			mb = new SMeshBuffer();

			mb->Vertices.push_back(video::S3DVertex( -50-50*e, 0 ,  50+50*i, 1, 1, 1, color ,0 ,0));
			mb->Vertices.push_back(video::S3DVertex(  50-50*e, 0 ,  50+50*i, 1, 1, 1, color ,1 ,0));
			mb->Vertices.push_back(video::S3DVertex(  50-50*e, 0 , -50+50*i, 1, 1, 1, color ,1 ,1));
			mb->Vertices.push_back(video::S3DVertex( -50-50*e, 0 , -50+50*i, 1, 1, 1, color ,0 ,1));
			mb->Indices.push_back(0);
			mb->Indices.push_back(1);
			mb->Indices.push_back(2);
			mb->Indices.push_back(0);
			mb->Indices.push_back(2);
			mb->Indices.push_back(3);

			//mb->getMaterial().setTexture(0,grassTexture);

			mb->recalculateBoundingBox();
			newMesh->addMeshBuffer(mb);
		}
		for (f32 i = 0.0f; i < 10; i += 2.0f) {
			mb = new SMeshBuffer();

			mb->Vertices.push_back(video::S3DVertex( -50+50*e, 0 ,  50-50*i, 1, 1, 1, color ,0 ,0));
			mb->Vertices.push_back(video::S3DVertex(  50+50*e, 0 ,  50-50*i, 1, 1, 1, color ,1 ,0));
			mb->Vertices.push_back(video::S3DVertex(  50+50*e, 0 , -50-50*i, 1, 1, 1, color ,1 ,1));
			mb->Vertices.push_back(video::S3DVertex( -50+50*e, 0 , -50-50*i, 1, 1, 1, color ,0 ,1));
			mb->Indices.push_back(0);
			mb->Indices.push_back(1);
			mb->Indices.push_back(2);
			mb->Indices.push_back(0);
			mb->Indices.push_back(2);
			mb->Indices.push_back(3);

			//mb->getMaterial().setTexture(0,grassTexture);

			mb->recalculateBoundingBox();
			newMesh->addMeshBuffer(mb);
		}
		for (f32 i = 0.0f; i < 10; i += 2.0f) {
			mb = new SMeshBuffer();

			mb->Vertices.push_back(video::S3DVertex( -50-50*e, 0 ,  50-50*i, 1, 1, 1, color ,0 ,0));
			mb->Vertices.push_back(video::S3DVertex(  50-50*e, 0 ,  50-50*i, 1, 1, 1, color ,1 ,0));
			mb->Vertices.push_back(video::S3DVertex(  50-50*e, 0 , -50-50*i, 1, 1, 1, color ,1 ,1));
			mb->Vertices.push_back(video::S3DVertex( -50-50*e, 0 , -50-50*i, 1, 1, 1, color ,0 ,1));
			mb->Indices.push_back(0);
			mb->Indices.push_back(1);
			mb->Indices.push_back(2);
			mb->Indices.push_back(0);
			mb->Indices.push_back(2);
			mb->Indices.push_back(3);

			//mb->getMaterial().setTexture(0,grassTexture);

			mb->recalculateBoundingBox();
			newMesh->addMeshBuffer(mb);
		}
	}

	newMesh->recalculateBoundingBox();
	return (IMesh*)newMesh;
Then I get a 1000*1000 mesh.
I never knew why when I place it, I have to do like it's a 900*900 mesh...

I need to make a lot of meshBuffers so that we can change the texture of any square we want.

And here is how I tile it :

Code: Select all

void zoneMemoryUpdate() {
	// Get the player's position.
	vector3df pPos = CedCamera->getNode()->getPosition();

	// And we find a zone to unload.
	for (size_t i = 0; i < CedZones.size(); i++) {
		f32 dist = CedZones[i]->getPosition().getDistanceFrom(pPos);
		if (dist > 2500) {
			// We are too far from this zone, remove it !
			for (u32 n = 0; n < CedZones[i]->getNodesCount(); n++) {
				IMeshSceneNode *sn = (IMeshSceneNode*)CedZones[i]->getNode(n);
				// Get it's meshBuffer.
				for (u32 a = 0; a < sn->getMesh()->getMeshBufferCount(); a++) {
					// Now, remove the meshBuffer stucked in the memory !
					CedDriver->removeHardwareBuffer(sn->getMesh()->getMeshBuffer(a));
					sn->getMesh()->getMeshBuffer(a)->drop();
				}

				// Remove the zone's mesh.
				CedScene->getMeshCache()->removeMesh(sn->getMesh());
				sn->getMesh()->drop();

				// Remove node
				sn->remove();
				CedZones[i]->removeNode(sn);
			}
		}
	}

	// Find a zone to load.
	// Get the nearest multiple of 900.
	f32 nearestX = pPos.X;
	f32 nearestZ = pPos.Z;

	nearestX = nearestX/900;
	nearestX = floor(nearestX);
	nearestX = nearestX * 900;

	nearestZ = nearestZ/900;
	nearestZ = floor(nearestZ);
	nearestZ = nearestZ * 900;

	// Make the positions to look at.
	array<vector3df> checkLocations;
	checkLocations.push_back(vector3df(nearestX, 0, nearestZ));
	checkLocations.push_back(vector3df(nearestX, 0, nearestZ + 900));
	checkLocations.push_back(vector3df(nearestX, 0, nearestZ - 900));
	checkLocations.push_back(vector3df(nearestX + 900, 0, nearestZ));
	checkLocations.push_back(vector3df(nearestX - 900, 0, nearestZ));
	checkLocations.push_back(vector3df(nearestX + 900, 0, nearestZ + 900));
	checkLocations.push_back(vector3df(nearestX + 900, 0, nearestZ - 900));
	checkLocations.push_back(vector3df(nearestX - 900, 0, nearestZ + 900));
	checkLocations.push_back(vector3df(nearestX - 900, 0, nearestZ - 900));

	// Now, find the zones having at least one of these coordinates.
	for (size_t i = 0; i < CedZones.size(); i++) {
		for (size_t z = 0; z < checkLocations.size(); z++) {
			//if (CedZones[i]->getPosition() == checkLocations[z])
			if (CedZones[i]->getPosition().getDistanceFrom(checkLocations[z]) < 900)
				checkLocations.erase(z);
		}
	}

	// Now, we load each zone from what we've found.
	if (CedZones.size() != 0) {
		for (size_t x = 0; x < checkLocations.size(); x++) {
			Ced_Zone *newZone = new Ced_Zone(checkLocations[x]);
			CedZones.push_back(newZone);
		}
	}
}
So, it really slowdowns when I get 6 zones in front of me...
Does anyone have an idea please ?

Thanks for your help.
arras
Posts: 1622
Joined: Mon Apr 05, 2004 8:35 am
Location: Slovakia
Contact:

Post by arras »

I was not reading through all your code and I am not sure what exactly you want to accomplish. But ...building "infinite" ground you can edit is impossible simply due to hardware limits. Building large ground (terrain is the better name) is possible. Even very large terrain.

What you need is to:

-ensure only part of terrain is rendered in any moment.

-any kind of LOD (level of detail) system will help.

-to make each tile in to its own meshbuffer so you can set its texture or other attributes is nono ...you will end up with very slow framerates, best way to accomplish this is using shaders, even some other ways are possible.

-each mesh buffer is rendered separately so rendering 1000 tiles in one mesh buffer is much faster than rendering them in 1000 meshbuffers (one tile per buffer). If you use several meshbuffers than use them to cull parts of your terrain.

-if you need really huge terrain, you can consider storing its data in file on disk instead of memory and loading its parts as needed (as position of rendering camera changes). You can even split terrain in to several scene nodes for this.
Linaxys
Posts: 47
Joined: Tue Feb 24, 2009 10:46 pm

Post by Linaxys »

Hey arras, thanks for your reply.

I've just found a solution, loading a terrain scene node and tiling it with my method instead of building a custom heavy mesh.

I just load a 64x64 heightmap, scale it to 200,200,200 and tile it as I done...

I don't know if it would be possible to be infinite, I don't really know but I think it is, here's my new part of the editor : http://www.mediafire.com/?tgjthxmcemk

EDIT : (Right-click and use ZQSD, sorry, I forgot to change the keyboard layout...)
arras wrote:best way to accomplish this is using shaders, even some other ways are possible.
Argh... Sorry but I'd like my program to be able to run on as much machines as possible...
If you are talking about CG or HLSL shaders, then I really can't.
But other shaders should be fine.

To save the data, I don't think it would be a problem, you helped me in another topic I made to know how to save the data, I just have to save the position of the zone having a modified vertice in the Y coordinates,...

I'm not really really sure, works fine under my 9800M GTX, and it's about 47 - 50 FPS under an Intel GMA 950...

Here is how it gives :

Image

I will share the code if it works as I want.
Post Reply