Posted: 23rd Jun 2007 1:23
By default, both PrepareForNewFileGen() and EndGeneration() call Clear(), which in turn will delete all of your 'building block' data - meaning that you have to specify your blocks again with the AddMeshBlock functions.

I chose to do it this way to ensure that all dynamic memory is released during normal use of the library - even if the user forgets to explicitly call Clear() when the user finishes doing their thing.

In hindsight, this is a bit limiting. I'll change this behaviour for the next update (and I'll catch that array exception too - whoops!)

I'm not back at home again 'til Sunday, so in the mean time your options are either a) re-specify the building block data for each new mesh or b) comment out and the calls to Clear() in the aforementioned two functions (just remember to call it yourself when you're finished). Let me know if this fixes your problem.

I haven't looked at the image combining yet, but when I do I'll keep compatibility with DarkLIGHTS in mind!

On a related note, my first attempt at boosting the generation speed of the library was thwarted by a bug with the 'write string' command (see the bug board for details). I'll keep you updated on my progress in this area.
Posted: 23rd Jun 2007 13:09
Commenting out the call to Clear() solved the problem. Thanks very much.

I really appreciate your help with this, thank you.
Posted: 24th Jun 2007 2:36
@Scraggle Also when using limbs a great deal of slow down comes from using the limb position/ angle commands. My culling code runs 8 times faster by storing this in an array for all static limbs, instead of calling them each loop. The hide and show limb commands are also a big slow down themselves, even if they are already hidden/ shown. Use flags to not hide a limb that is already hidden and not show one that is already shown.

When using the meshs instead of limbs, keep it under 65536 verts (21845 polys) per mesh if you want the save mesh command to work and save your results.

You should be able to use memblocks to pretty easily combine the meshs and images into 1. You should be able to write a code to auto combine them for any situation even. Just assign each image number to a tile of the master image. You can then use a simple decimal multiplication and an add to adjust the UV data automatically. If your new image is 2 tiles (0 and 1) wide and 1 long the v data will stay the same. You will have to muliply the u data by 0.5 (or 1/num tiles wide) and then add the tile offset back to it (tile num [0 based] * the value multiplied earlier [0.5 in this case].

We just got through adding a new building to our plant, so I have a little free time to start back on the culling and 3dw importer. I can write a simple code to combine limbs and textures if you want. I may already even have something laying around when I get home.

@Cash Not trying to hijack the thread or anything, but it may be usefull to others too. Check out my culling thread, there was an error with the placement of the projection matrix capture in the version I had up. This caused the camera range to not work properly. I have fixed the code, but am not sure if the versin you ported to a plugin contained the error. Just mentioning as I'm not sure when the error was introduced (I know it was while optimising code). Hopefully I'll have a basic terrain loader code back in tonight when I get off work for the 3dw importer.
Posted: 24th Jun 2007 5:43
Incorporating culling in Scraggles' application remains a pointless exercise. Even if you culled 700 tiles in a frame, the remaining 300 tiles will still make his FPS crash (not un-playably so, but he'll still be in the same situation that prompted this thread).

Even if you dropped the dated six-planes culling method for something more modern and then replaced your brute-force approach with a spatial partitioning solution (a quad-tree would be perfect here) - you would still be plagued by performance issues due to those numerous, sub optimal draw calls (been there, done that, learnt the hard way).

Put simply - frustum culling is designed for programs that are vertex limited. This application is a long way from being vertex limited on any recent (and not so recent) computer hardware and hence frustum culling is not an appropriate solution here.


Now, regarding your suggestions for combining images. Since at least two edges of each sub-image won't be straddling the image edges, you will also need to apply a border around each image to prevent texture bleeding from adjoining sub-images due to texture filtering.

The size of this border will need to take into account how many mip-map levels will be used (if any) to avoid texture bleeding at lower texture resolutions. The UV values will of course require adjusting to take the borders into account.

To do this properly, the borders will have to consist of the same edge pixel data as the bordered image so that texture sampling will yield acceptable results. You couldn't just fill the border with a solid colour - say black - as you would obviously just end up bleeding that colour.

Additionally, the success of doing this all via memblocks relies on being able to cram every texture into a single image (which may or may not be possible, depending on how many textures will be required - and whether or not Scraggles is willing to suffer loss of quality if textures need to be shrunk to fit). This is because the 'make object' command only lets you assign a single texture to each object.

Ofcourse, you could always bodge it using multiple textures and multiple texture layers/units - but that's kind of a waste of fill rate. Another alternative would be to split the level over two or more objects/limbs (a couple of limbs is obviously still faster than 1000) and then just combine the textures over multiple images as required for each limb.

Yet another alternative would be to drop the image-combining idea altogether and simply combine multiple limbs into single limbs based on type. You won't have a single mesh object, so you're still losing speed, but it won't be as bad as having 1000 limbs either and it's very simple to implement.
Posted: 24th Jun 2007 10:48
Easy there LOL. Didn't mean to offend anyone. All your suggestions are great and may very well be the way to go

I myself would try every combination possible and use what works best. This means I would want any and all information on what might be done. I would have to run a test application or see some screens to tell what I really would try first.

The frustum culling would not be totally useless since it only takes from 0.0005ms (sphere testing) to 0.003ms (box testing) per limb in DBP code and testing against all 6 planes of the frustum. Since he is effectively working in 2D mode he can get by with only checking 4 planes and change the order of the tests to the likely hood of the failing ones first. He could get by with most checks only doing 1 or 2 planes. If he got the dll from Cash, it would be even faster. 1024 limbs with all limbs on screen takes 1.4ms here to cull. With just 300 limbs on screen it takes 0.8ms. The speeds are more proportional on other test machines since my processor won't load over 50% with DBP applications. You won't even see a hit at those times. That being said you won't really see a substancial performance increase unless you have 100 polys + per limb or so, but every little bit helps when dealing with DBP.

As for the borders for the mipmaps on the images, they won't be needed really. Since he is working in 2D and the distances will be relatively the same except the edges of the screen, I would just turn them off and see how it runs. Just figure out what the pixel size is apprx for each tile on screen when in the center and make the texture that size (the size of mipmap that it would have used appx anyway). No need to use a 256 by 256 image if it's never gonna get closer than 64 by 64 on screen and so on when dealing with 2D. If it runs too slow and you need the mipmaps, then you can figure our the border problem

I think a combination of everything (including running a search for welding verts in this very forum) will be the final answer.
Posted: 24th Jun 2007 17:05
Easy there LOL. Didn't mean to offend anyone.


Heh, no one here is offended .

I speak from extensive experience with this type of problem and my only intent here is to relay my knowledge. Please don't take my analysis as a personal attack.


The frustum culling would not be totally useless since it only takes from 0.0005ms (sphere testing) to 0.003ms (box testing) per limb in DBP code and testing against all 6 planes of the frustum. Since he is effectively working in 2D mode he can get by with only checking 4 planes and change the order of the tests to the likely hood of the failing ones first. He could get by with most checks only doing 1 or 2 planes. If he got the dll from Cash, it would be even faster. 1024 limbs with all limbs on screen takes 1.4ms here to cull. With just 300 limbs on screen it takes 0.8ms. The speeds are more proportional on other test machines since my processor won't load over 50% with DBP applications. You won't even see a hit at those times.


That's all well and good, but it doesn't matter if your code could cull everything in zero seconds - it's the sheer number of draw calls that are causing the loss of FPS.


That being said you won't really see a substancial performance increase unless you have 100 polys + per limb or so


And this is the crux of the situation. Frustum culling will never provide the same speed increase as simply optimising the draw calls when the application is neither vertex or fill rate limited.

A hybrid situation wouldn't work here because the two techniques are mutually exclusive - one requires the world to be split into many pieces whilst the other requires that it is combined into as few as possible.

Of course, significantly increase the poly count and then a hybrid solution becomes very useful (you could combine small, sub-optimal polygon batches into larger GPU friendly batches and then cull what you don't see).

As you can see, optimisations like this are a delicate balancing act - it's all about picking the right tool for the job.

Don't take my word for it though, try it out and see for yourself!
Posted: 24th Jun 2007 17:37
it's the sheer number of draw calls that are causing the loss of FPS.


I can vouch for that. As I said in my 1st post, there are 280 (20x14) 'blocks' on screen at any time. I didn't bother to create the offscreen ones just as a speed test to see what the optimal culling routine would produce, but even then it was way too slow. So, I appreciate the help Lit but as you can see, even the most supremely perfect culling machine wouldn't produce fast enough results.

Danny's solution works beautifully, the only issue remaining now is the ability (or lack of) to light map the generated object.

Since he is working in 2D

I'm not really. I am working with 3D objects but the gameplay is in 2D.

Here's an early screenie:
Posted: 27th Jun 2007 19:48
Scraggle,

Just making a quick post to let you know what's going on. I've got time to work on this again this weekend, so look out for an update then.
Posted: 27th Jun 2007 21:10
Thanks Danny, I'll look forward to it
Posted: 28th Jun 2007 1:51
Just had time to glance over the code. It will take longer to save to file, but would the level run any faster if you remove all the duplicate vert positions and normals. I'm betting since he is using plains and cubes that alot of the UV values will be the same as well. And use quads instead of tris? It may even load faster since the file size would be alot smaller. Just wondering if you have already tried this as I am about to do something similar in my 3dw terrain loader.
Posted: 28th Jun 2007 2:13
I'm sure it probably would run quicker and would be very welcome but just for the record, I am only using plains and cubes as temporary placeholders.
Posted: 25th Jul 2007 18:09
Well, I'm back from my honeymoon and now I want to get this out of the way.
DSG's solution for combining all of the objects into a single .x file is beautiful! Now I need to combine all of the textures into a single image. As far as I can tell, there are thre things that I would need to do.

1) Combine all of the textures into a single image
2) Alter the .X file to inform it that there is only one image.
3) UV map the .X file

The first part is easy. The problem I have is with parts 2 & 3.
Anyone have any suggestions as to how to go about one or both of them?

Thanks
Posted: 25th Jul 2007 18:25
Welcome back! Just so you know, your wife is just pretending she doesn't care about you being on the computer

You know, the first time I read through this I guess I didn't pay enough attention. I completely understand what you're doing and the problem you're having.

You already know about limb counts vs. draw calls. Now you've combined everything into one giant obese limb. Programmatically I'd emulate what 3DWS does - it combines brushes that share a texture into a single limb. So, if your floor tiles all use the same texture they'd all be combined into a single limb. They'd be a separate limb from the wall, from the windows, from the doors, etc. You'd end up with a minimum number of limbs, each with it's own tileable texture.

Now, if I had one big object and I wanted to UV map it with one texture, I'd first import it into Milkshape and group each set of textured faces into limbs. The floor would be a limb, the walls would be a limb, etc. I'd save it and import it into Ultimate Unwrap 3D. I'd rearrange the limb maps into a nice square, then export the UV map. I probably wouldn't huge higher than a 1024x1024 texture. In Paint Shop Pro I'd apply the correct textures to the correct areas. No problem with that, pretty simple.

The problem you'll run into is that the texture, mapped across the entire, will probably look fuzzy. It's great for small objects, like characters and other similarly sized objects. For anything bigger it probably isn't desirable. Take the detail map off of the terrain and you'll see what I mean - a big stretched texture looks like complete garbage.

If you want, I'll UV map your level for you. Show me what it's supposed to look like then send me the level + textures. I'll give you a completely awesome 1024x1024 UV map. I warn you though, it probably won't please you.

Ultimately, I'd group limbs by textures. Then you can tile them as you see fit and retain the detail that you likely want.
Posted: 25th Jul 2007 19:42
Thanks for the input Cash, unfortunately what you're suggesting is not an option. The idea is for the user to be able to create his/her own map. So, exporting to another package is a no-go.
I was hoping to be able to UV map with code. DSG suggested it may be possible but I can't figure out how.

As for texture size ... each 'block' uses a 64x64 texture so 1024x1024 for the entire map is easily achievable if textures are re-used.
Posted: 25th Jul 2007 21:54
Hey Scraggle, I've read the whole thread but pardon if this has been suggested before...

In my project I am doing something very similar to yours. I have a fully 3D level which is built from a 2D array. This is a good way to go as it simplifies any sort of level editor that might be made which is important to me.

I am using a single texture for the entire level right from the get-go.

Here's what I do:

- Make a tiny dot parent triangle object
- Attach primitives (plane floors and walls) to the parent object as limbs, positioning them as they should be on the level
....... each primitive limb has its UV data changed dynamically with the UV texture commands, working off the large texture
....... using a single texture for the entire level, sectioned off into a grid (this has the added benefit of just doing texture object with a different texture and whallah... new theme for your level)
- use make mesh from object which combines all limbs into a single mesh
- save the mesh to a ".x" file, or do a make object and save as a ".dbo" file.
- when I load the file I just do load object and texture object, and it's all set!


Downfall of using a single texture is you're stuck with however many tiles you can fit on the texture, and you can't cross texture bounds (that I know of). So frugal use of texture space and re-use of textures is good. Also if the level is seen from far away sometimes the mipmaps will blend the grid of images together and you get "bleeding" of one grid image into another. For my situation (and possibly yours?) the benefits outweigh the constraints.

I can send you an example of what I've been doing if you want.
Posted: 26th Jul 2007 0:02
@Scraggle -

I see. Then I'd do what I suggested above, grouping limbs by textures. I want to write a demo of it, but I can't because I'm moving right now Maybe in a couple of days I'll be able to.
Posted: 26th Jul 2007 0:58
I've just tried tiresius' suggestion. I was reluctant to at first because I was almost certain that it wouldn't work. But I am very happy to report that I was wrong, it does work!

It isn't an ideal solution because there is a lot of texture bleeding but in the absence of any better solution I will be giving it a go.

Thanks tiresius

@Cash
I appreciate the ideas but because of the initial problems I incurred by using limbs I would prefer to stick with a single root limb if at all possible and it seems tiresius has found a way.
Thanks
Posted: 26th Jul 2007 5:29
Hi Scraggle.

I'm glad I could help. I've been a big fan of your games since those early competitions. But I knew it would work, because it is what I'm currently doing (I wouldn't suggest otherwise!)

Here's a pic of my 3D level object generated from a 2D UDT array (height, tile slope, material, etc.) using the single tiled texture method.



It's just whether or not the problems of this method affect you or are fine to live with.

Depending on how much mipmapping is done, a way to help prevent (or at least reduce) bleeding is for each tile in the texture to have a border of the edge color, and use UV coordinates not at the edge of the tiled portion but inside it a little bit. It makes the texture potentially less detailed, but if you don't have a ton of tiles it shouldn't be too bad.

Like this (yellow box shows UV bounds):


In any case, good luck with your new project!