Posted: 15th Jun 2007 20:39
I have a problem that I can't find a solution for.

My current project is essentially 2D but made of 3D objects. Each map is held in an ASCII file, read in and then created. There are many different 'blocks' that make up the map but for testing purposes I have restricted it to floors (2D plain) and walls (3D cube). Each map is made up of 20x50 blocks and each block can have either a plain or a cube in it. Although all 20 horizontal blocks are shown on screen, only 14 of the vertical ones can be seen at any time.

My problem is working out the most efficient way of displaying the map.

Initially each block was a separate object and I would exclude any that went off screen as the map scrolled. Using that method I was getting about 150FPS. Which sounds good but that was just with the player character and map collision on. There were no enemies or animations taking place. So really, 150fps is quite low. Also I was faking the shadows by looking at each floor tiles surroundings and generating a shadow texture to bake onto it. It looked OK but was a little too faked.

So, I thought I would try using a single object for the map so that I could light-map it. I created a single triangle and then attached each block to it as a limb. That worked but the fps dropped to about 40. Odd because the level is only ~6000 poly's and there are only two 64x64 pixel textures on it (one for the floor and one for the walls). If there was an EXCLUDE OBJECT LIMB command I think this would definitely be the way to go but there isn't.

So, now I am at a loss. I don't know what to do. A 60,000 poly terrain object runs at around 500fps for me so I don't know what the problem is with my 6000 poly map. If I can't figure out the reason why the limbed map is running so slowly then I will have two options.

1) Stick with my original method and fake the shadows.
2) Create the maps in an external application. Something that I don't want to do because I want the user to be able to create their own maps and storing them as ASCII files makes it much easier.

So, can anyone explain why the limbed map runs so slowly? Or perhaps offer a viable alternative method?

Thanks
Posted: 15th Jun 2007 21:03
Hmm, this sounds like the thread "not render an object beyond a certain point"

Anyway have you tried using .dbo instead of .x, i don't know if it will make a difference but you never know it might

How did you bake you shadows? I'm placing objects on an advanced terrain and I'd like to bake shadows to it but don't know how in DBP to do it
Posted: 15th Jun 2007 21:18
Yes, I am using dbo's.

My shadow baking method wouldn't be any use to you because it wouldn't work on advanced terrain ... sorry

My method is quite simple. Because my map is a grid I can simply look at each floor tiles surrounding tiles and calculate which of the 6 shadows should be on it. Then on an off-screen bitmap I paste the floor texture then paste the shadow texture on top of it before grabbing the resulting image and using that to texture the floor tile.

Because of the layout of my map, there can only be one of six shadows on it:


However, I was hoping to add flames and light sources that would make it look better. That's why I want to light map it.

[EDIT]
Just looked at the other thread you mentioned and LiT's limb culling could have potential. I will try that and see what I get. Thanks
Posted: 15th Jun 2007 22:16
My current shadow solution is to give the model a black skirt and then cast the shadow on that in the modeling package. Then sit the models skirt just above the ground level.

Only works if the ground is level though so not ideal, id prefere it cast to the terrain
Posted: 16th Jun 2007 0:33
GatorHex: As I understand it, DarkLights should be able to lightmap an advanced terrain - although I don't know for sure. Or ... you could also write your own terrain lightmapper - I wrote a basic terrain lightmapper some time ago and it wasn't actually that hard (although it was pretty slow - you'd need to preprocess it).
Posted: 16th Jun 2007 5:19
If your level is only 6000 polys in size, then the most optimal thing you can do is render the entire object in a single draw call. This means combining it into a single mesh (no limbs!).

Combining it into a single object using limbs won't work because each limb requires its own draw call. Draw calls are expensive to set up and more often than not are much slower than the actual rendering itself. Further more, modern GPUs are notoriously bad at submitting and rendering small batches of polygons.

Rendering your current level object requires 1000 draw calls with very low and suboptimal polygon batches - yeeouch!! That's where your bad performance is coming from

Additionaly, trying to cull such a tiny number of polygons is far more likely to slow rendering down on recent-gen graphics hardware and probably will not be worth the effort at the current stage of your project.
Posted: 16th Jun 2007 10:54
This means combining it into a single mesh (no limbs!).


Is that possible from within DBP?

Keeping in mind that I would like to have the map stored as an ASCII file and that each of the 1000 blocks could potentially be a different object with a unique texture. How would I go about combining all of my objects into a single mesh?
Posted: 16th Jun 2007 12:01
How would I go about combining all of my objects into a single mesh?


Never tried it myself, but I would guess at making the object by adding limbs, then MAKE MESH FROM OBJECT
Posted: 16th Jun 2007 13:30
BatVink has the right idea! But if that doesn't work out, here are some other options:

- Build the mesh using the vertexdata commands ( 'add mesh to vertexdata' will come in handy here).

- Build the mesh using the mesh memblock commands

- Generate an ascii .x file of your level (don't baulk, this is easier than you might think)
Posted: 16th Jun 2007 13:48
MAKE MESH FROM OBJECT does what I asked but I think I asked the wrong question. I should have asked ... "How can I combine all my limbs into a single object?" If there were I corresponding MAKE OBJECT FROM MESH command then that would be great, but there isn't.

Which leaves me with DSG's suggestion.
However, I have never played with the Vertex Commands. So, that is something new to learn
I have never played with the memblock mesh commands, only image memblocks. So, that is something new to learn.
I have no idea about the ascii.x format. So, that is a huge thing to learn.

This started out as a relatively simply idea but now it has become a mammoth learning process.

Thanks for your help and if you can offer anything further I would certainly appreciate it.
Posted: 16th Jun 2007 13:59
If there were I corresponding MAKE OBJECT FROM MESH command then that would be great, but there isn't.


Such a command exists, although you probably missed it as they didn't stick with their existing naming convention ( MAKE OBJECT object_num, mesh_num, image_num). However, the single image limit probably reduces its worth.

Actually, I think generating a mesh file might be your only option here as I'm not sure if the vertexdata commands will allow you to preserve different textures from individual objects. I'd be happy to put together a sample of this method if you would like to take this route.
Posted: 16th Jun 2007 14:07
Thanks, I just tried the MAKE OBJECT command. However, as you point out, only being able to have a single image does make it pretty useless. It did work though.

I am really not sure how to proceed, so if you are willing to put together a sample, that would be great!

Thanks

[Edit] Would it help to have my map generating code and ascii map file?
Posted: 16th Jun 2007 14:18
That won't be necessary, I'll write something generic that will be painless to incorporate into your own code.

I'm out and about this afternoon so I'll put something together for you a little later in the day!
Posted: 16th Jun 2007 14:22
That would be great!

Thank you
Posted: 16th Jun 2007 15:26
@Scraggle -

LiT's code should do what you need. However, since it is DBP code, it's kind of slow. His implementation is perfect, DBP just has some issues with it.

I'll send you an e-mail. I converted it to a plugin a little while back. I haven't released it because I was hoping to incorporate his 3DW importer, but he's been really busy.

It has my animation controller + limb culling + some math functions. I'm not sure if my CC_absInt command is the correct one or not, but it's still infinitely faster than DBPs.
Posted: 16th Jun 2007 16:06
Thanks Cash

I have to go out shortly, so I will take a look at it later. Unfortunately though, I think the limb option (culled or not) won't work because I used HIDE LIMB to hide all the limbs that were off screen and it was still way too slow. Unless your code does something more to the limbs than just hide them, the way 'exclude object on' does.

Thanks
Posted: 16th Jun 2007 16:22
No, but it's way faster. It's almost as fast as the Update Terrain command, except that the culling is more powerful. It might not do it as quickly as you need, but it's waaaay faster than using DBP code to do it.

LiT asked for Exclude Limb before, but I believe Lee said that it wasn't going to happen any time soon because it would require changes to DBP's core rendering system. Sad, but understandable.

You might like the animation control system. It allows you to set up timer based animations for objects, and every animation can have a different framerate. It also blends between animations, and gives you animation marker feedback. It's what I use for Geisha House.
Posted: 17th Jun 2007 14:16
I've attached the promised sample to this post. I'm not finished with it yet, but it does everything that you require.

I haven't had a chance to annotate the source file properly yet, so I'll give a quick rundown of how to use it here:


- Call the PrepareForNewFileGen() function prior to generating any meshes

- Use the AddMeshBlockFromFile/Object/Mesh() functions to register your 'building blocks' with the system. These functions require that you specify a unique id string for each building block that the system will use to identify it later on. For your project, the unique id can be the ASCII character you use to represent different blocks in your map file.

Example:

make object box 1, 10, 10, 10
AddMeshBlockFromObject( 1, "texture.png", "a_box" )

` No longer need this
delete object 1


- When you have defined all of your blocks, call BeginGeneration() to switch into object generation mode.

- Once in this mode, use the AddToOutput( id as string, x_pos as float, y_pos as float, z_pos as float ) function to add instances of your building blocks to the generated mesh.

- Call EndGeneration() to exit this mode and generate the x file. The name of the generated file is stored in the TEMP_FILE_NAME constant.

Example:

BeginGeneration()

AddToOutput( "a_box", 0, 0, 0 )
AddToOutput( "a_box", 10, 0, 0 )

EndGeneration()

load object TEMP_FILE_NAME, 1

- If nothing seems to be happening, check the return values of the functions that you call and use the GetErrorDescription() function to get a string containing a description of any errors that are going on (NB. not all of the functions return an error value)



The attached example takes a couple of seconds to generate the file. There's lots that I can do to speed up the file generation and I'll work on that when I next get some spare time.

There's still some work to be done on it (mostly just speeding up the generation of the X file). I also want to add the ability to combine multiple textures into a single image to further improve performance (less textures = less render state changes = faster rendering!)

I'm going away for few days now so you may not see any replies from me until a little later next week!
Posted: 18th Jun 2007 12:50
That is absolutely fantastic!
It doesn't seem enough to just say thank you but what else can I do ... thank you
Posted: 22nd Jun 2007 15:35
Hi Danny,

I'm loving the code you have written, thank you. It speeds things up fantastically to have the map as a single object.
It worked perfectly for generating a single .X file but I have a problem generating more than one. I get an array does not exist or subscript out of bounds error when I try to generate the second file.

Between generations I am calling PrepareForNewFileGen() which seems to clear the arrays and (as far as I can tell) set everything up for the next object but it is quite a complex peice of code you have written and there is obviously a problem somewhere that I can't figure out.

Any suggestions?

Thanks.

[Edit]
I also want to add the ability to combine multiple textures into a single image

Have you had chance to look at that yet?
I've just tried using Dark Lights to lightmap the generated object but all of the textures disappear. I presume because they are all seperate and not a single image.

Thanks