|Zombie simulator: a small step forwards|
|Friday, 15 January 2010 20:00|
In my original plans for the Zombie Simulator, I stated that I wanted to have all buildings in the world destructible.
I've kept that in mind as I've built the engine, designing the wall models as cubes that can be assembled to form the buildings.
Early on I found the best way to do this was to create each building as a separate Mesh, and have each floor (ground, first, etc.) as a separate Mesh Buffer. Floors are then constructed by simply adding the vertices required to describe a wall piece to the floor's Mesh Buffer at a certain location.
The next stage for my plans involved modifying the code that assembles the buildings to be able to call it at-will when a wall piece needs to be swapped out for a destroyed version. To test this process I added functionality to work out which wall piece was under the mouse when the left mouse button was clicked, then use the delete key to remove it, triggering the wall, floor and building to be marked dirty. After the next screen refresh, the affected floor is reconstructed, sans the destroyed wall.
And there you have it, the next step in the process was to poke holes in what I've already done.
It seems easy on the face of it, but I had a fair bit of learning to do. For instance, Irrlicht has no documentation on how to remove vertices from a IMeshBuffer, which is what an SMeshBuffer is converted into when it is added to a Mesh. Removing vertices from an SMeshBuffer is easy, but an IMeshBuffer has no methods to achieve the same.
After trawling through the Irrlicht forums for a while (quite a while), I stumbled upon what I needed. It turns out that an IMeshBuffer can be cast as a CMeshBuffer, which provides equivalent access to the vertices and indices as an SMeshBuffer.
CMeshBuffer* buffer = (CMeshBuffer*) mesh->getMeshBuffer(0);
In the process of upgrading the engine, I found that I needed to store the chain of parent objects for each wall piece, so that changes to the "health" of a wall piece could be propagated up the chain, to the floor it's on and finally to the building the floor is a part of. Unfortunately, I forgot that C++ has a hard time dealing with object pointers when you add them to a vector.
Vectors are a type of array. When you add a new one, the array gets reallocated, possibly in a new location. Once I'd begun keeping pointers to the objects I created, passing them down to the child objects, I started to notice random glitches and crashes. The reason was that these classes, the walls, floors and buildings, were moving around in memory as they were being assembled, leading to the pointers pointing at junk memory where the class had originally been located.
Some refactoring was needed, so rather than just switch to C++ lists (which I believe stay in place), I decided to do it properly and incorporated boost into the project, specifically to get access to the shared_ptr class which provides the engine a method of storing the permanent location of where a class exists in memory.
After about an hour and a half fixing compilation errors and modifying the code, the engine is now nice and stable.
That $&&#$ glitch in the b3d exporter is back again
While altering the rusty factory roof object in Blender, I added a couple of new vertices to a few of the roof pieces. Upon exporting the mesh to b3d, and loading it into the engine, I found that all my wall pieces were screwed up like they had been before.
Swearing to myself, I decided to investigate what was causing it, and yes, I have the answer, and it turns out it's a feature, not a bug.
Within the engine, I was able to narrow down the problem to a particular roof piece, so I went back to Blender to examine it in more detail. I eventually noticed that piece had gained a triangle without any texture assigned to it. I hadn't spotted it because it was hidden between two other wall pieces.
It turns out that exporting this untextured triangle to b3d format, then reading it with Irrlicht's Mesh reader was the cause of the problem. Normally, each object I create in Blender has a single texture, which results in a single MeshBuffer being created and assigned that texture. When the Mesh reader stumbled upon the solitary untextured triangle, it simply created a new MeshBuffer for it and inserted it into the list.
Since I identify wall pieces by their Mesh Buffer index, every piece following the solitary triangle was out of place by one, which meant the nice tidy buildings turning into an apparently random inside-out mess.blog comments powered by Disqus