( This was written as it poured out of my head, please excuse the grammar)
The goal I concentrated on for this prototype was to get a screen fill similar to the PC version but in full 3D with buildings that can be seen from all around and also zoomed into and out from smoothly.
A secondary goal was to to find out what minimal amount of resources (verts, textures and meshes) would be needed to capture the same detail and variety used in the original SimCity4 pre-rendered 3DS Max files.
That being said, I needed to some limits for the PS2. After checking with Gordon and using information from other resources (people) the limits I had were 50,000 verts and 100 meshes on screen for a 60 frame per second game and any extra meshes would decrease the performance considerably stepping down the frame rate to 30 fps, there are no in betweens. These are our engine limits which are different from the hardware limits. I recall Gordon saying that the PS2 stops drawing things after 600 meshes are on screen, but I’d verify that with him. Gordon did incorporate “Tri Stripping” which is an efficient way of handling geometry so there was a little grey area there and the only way to find out true performance was to throw some buildings at the consoles in different states to see what kind of fills (how many buildings on screen) we could get before things bogged down and crashed.
First a little definition for the people who are unclear. 1 mesh = 1 piece of geometry that has 1 texture assigned to the whole thing, all polygons. For example, if you have a scene that consists of 2 boxes, each assigned the same texture, then your scene consists of 2 meshes because each box is an independent entity. If you select both boxes and “combine” them (in Max it’s “attach” but the same principal) so they function as 1 entity with one texture assigned to them, even though the verts aren’t welded, it still counts as 1 mesh. In our engine. Instances are free vert loads after the first copy because verts are only loaded once from the original instance but not free on screen render because the renderer still needs the geometry to render. They also count as a mesh per instance.
Given the limits in the above paragraph, I could theoretically bog down or crash a PS 2 with a scene that consisted of a 1000 separate triangles. Even though the scene only has 3000 verts I’d be blowing out the mesh count. To test this, I built 2 versions of DirtyAnchor, one with a vert count under 1000 and a mesh count around 130 to 150, and another with a vert count at 1750 with a mesh count of 8. Gordon could fill the PS2 with around 20 of the 1st version with a vert count under 1000 before it crashed and could fill with over a 100 of the latter version with 1750 vert count. These results confirm the first sentence of this paragraph. In conclusion, the less mesh counts in your buildings the more buildings you can fill the screen with. Our LOD 1 buildings changed from shooting for under a 1000 verts and ramping up the mesh count to being very low on the mesh count and higher (1000 to 3500) on the verts. In conjunction with other LOD’s, the buildings closer to the camera can be displayed in more detail while the buildings farther away drop in mesh count and vert count with the lowest LOD 4 being a box and one mesh. Around LOD 3 the mesh count drops to 1 and the vert count around 200 to 300 . This should extend the buildings a good distance out to the horizon. LOD1 should fill 50 to 60 percent of the screen and you should be able to see road and parts of other buildings clipping in the sides of the screen (wich will probably be at LOD 1 as well). In some instances there could be several lod 1’s on screen but for the most part there should be only one building in main focus. As the camera pulls back and more buildings can be fully displayed on camera than one or two, the lod’s should switch LOD 2, then to LOD3 as a block is displayed etc…The smoothness of the transitions depend on how mant lod’s are used, the more lods the smother the transition. Camera distance settings will be different for the amount of LOD’s used.
Trying to get all the buildings down to 1 mesh at LOD 1 is extremly difficult as the real issue is the amount of textures. Using various techniques we are able to keep the textures to at minimum 128 x 256 (higth/width) per building with some buildings requiring a UV tiling 32×32, or 64×64, etc… Usually 1 to 3 of these depending on the building (like the skyscraper) are needed to complete the building. We kept the textures as low as possible because the of the very low memory available for textures on the PS2. The texure limit can be easly exceeded by filling a scene with a variety of buildings not to mention tree, cars, benches, etc… Since we only had 10, we couldn’t test to see how many different buildings with different textures we could fill in a scene.
In the following example I use 1 UV tiling brick texture, and one 128×256 for everything else.:
The LOD grouping in our game changed. At first, things like the lamps in DirtyAnchor that were instanced in were lod’d at the object level. For example, I made 3 lod’s of the lamp, grouped them into an lod node, and instanced that around DirtyAnchor. In the main DirtyAnchor file, the Brick mesh was lod’d, and everything else like the roof and tower vents were combined into one object and lod’d. Then the instances (lamps) were brought in and placed around the building. This set some parts of the building (like the lamps farther away and off to the side) to lod sooner than others and proved to be not as efficient in our engine. In the new method, with all the lod’s in one file except LOD 4,we now select lod 1 of the brick mesh, lod 1 of everything else that’s combined, all the lod1 instances (instances and their respective lod’s are now saved out as separate files) and group them into a group named whatever is approproiate with an lod1 designation. Next we select lod 2 of the brick mesh, lod 2 of everything else that’s been combined, and all the lod 2 instances and group them into a group named whatever is approproiate with an lod2 designation. The same process is done for LOD 3 and so on for as many lod’s are needed. These top level group nodes with the lod designation are then selected (in Maya they need to be selected in ordered starting with LOD 1) and are the ones that are put into an LOD group node. This creates groups of objects that function together as one lod with the top level node , the group node, being the one that the lod node is controling and switching. This is more efficient for our engine. CLOD (continous level of detail) meshes tended not to work on multimesh objects and would breakdown at the seams. Also the CPU overhead is much more than manual LOD’s so we followed the latter. The lod groups that aren’t being displayed are unloaded from the scene and do not count towards the vert, mesh, and texture limits at any particular frame.
Mesh were made with the mind set of filling the volume with minimum verts so things like bevels, door handles, trim, etc… have not been modeled but painted into the texture. A separate mesh was used for double sided geometry to limit overdraw to just the poly’s that need it. These were usually fence rails, ladder steps, and beams between the water tower legs.
Since we had the Max models and textures, my first order of business was to render all the buildings from all sides and whatever extra renders I needed, so we could have plenty of original reference images and that we could also compare the lower vert count buildings to. It made life easier for us in the short span of this demo to import the Max buildings into Maya and build off of them rather than to be constantly checking for scale. Only using the Max models as templates and creating all completely new geometry in Maya enabled us to cut out any anomalies that could arise from file translation and, more importantly, the amount of time it would have taken reducing the original geometry down to the vert counts they are currently at, would have taken way to long. It was faster to build it all new from scratch. My suspicions were confirmed when I tried to adjust one of the verts in one of the converted meshes in Maya, it wouldn’t let me translate it but I could rotate and scale the object as a whole. I used Habware’s .obj exporter at first to get DirtyAnchor exported from Max to Maya but it crashed on larger files like the skyscraper (officeBldg7). I ended up using “Deep Exploration” from Right Hemisphere to translate larger files like the skyscraper from Max to Maya. Deep Exploration needs Max and Maya installed as it doesn’t install any plugins into either Max or Maya but rather launches an instance of either to open a file, as least this was the case for opening Max files. Once opend in Deep Exploration you can save the file out as a .ma (Maya ASCII) file wich is what our game compiler uses. Deep exploration does screw up the camera so once you open the just newly saved .ma file in Maya it will appear in the wrong orientation even though both Max and Maya are set to Z up and 1 meter units. To fix this just create a new view panel in Maya and look through that, it will be in the correct orientation, or import that newly saved .ma file into a new Maya scene. Once in the correct orientation, I combine all meshes into one mesh even though they are pointing to different textures. I’m only using the mesh as template so I won’t be using any part og the geometry, and fewer meshes equals faster viewport redraws in Maya, even faster than Max considerably. Once the mesh is one mesh I delete history on the mesh so I only have the one mesh node in the hypergraph. Since the building’s foot print is imbedded in the name of the file, I create a box (this is assuming all settings, Z up, 1 unit equals 1 meter, are the same in Maya as they are in the original Max files) in the size of that foot print and scale the imported geometry, looking from the top viewport, to fit the box representing the footing size. Once it’s really close I assign it to a layer so I can template it easy. I then start building the new geometry, building by volume, and am able to snap to the imported geometry.
Restrictions on geometry were to “be stingy”. Use 4 to 5 sided cylinders with the edge normals smoothed and no mid-point verts in the caps for piping or round tube like objects. These should be like large pipes running along side the building. Things like ladder steps and antenna framing are made of double sided textured quads that are combined into one mesh separate from the rest of the geometry (even though it’s pointing to the same texture as in the case of a texture sheet) to restrict overdraw to just those objects. Use high contrast bevels in buildings where trim is concerned, almost as large as steps and paint anything else that’s smaller. Try to build the volume not the detail, paint the detail. The wide variety in the buildings made it hard to come up with a hard limit vert count wise and the LOD’s help increase LOD 1’s vert count. I think special cases need to be addressed as they come because of this variety in buildings. Also, we didn’t sew all the geometry to each other all the time but rather just let things poke in and through each other. Sewing or cutting objects up so verts are created at edge intersections to enable separate objects to be welded together sometimes creates extra verts, so we didn’t sew if we didn’t need to. This must be payed attention to as it might result in unexpected shading on geometry in certain situations.
Restrictions on texture started from what I was able to pull off with DirtyAnchor which was one (width/heighth) 128×256 and one UV tiling 32×32. Count an extra UV tiling 64×64 for a shiny map if you want glossy windows. In the end we were able to cram a considerable amount onto one 128×256. One end was used for tiling, for example, a buildings trim texture tiles horizontally left to right so I paint one normally from left to right 128 wide by 64 tall and make sure it tiles. I rotate the canvas 90 degrees so I have a tall thin texture, 64 wide by 128 tall, and copy that into my 128×256 master texture sheet and move it to the right all the way. I can now tile one end of my master texture sheet in one direction, vertically and get more resolution out of that part of the sheet. That is the only way to tile a texture sheet that also conatins non-tiling textures (at the other end). In the end, all the buildings needed at least one 128×256 and some needed UV tiling 32×32’s or 64×64’s, etc… The skyscraper ended up needing the 128×256 and 3 64×64’s. There are instances where you must tile (like brick on a building) because even a 256×256 wouldn’t give you the appropriate resolution to cover a large surface area. One thing to consider when creating texture sheets is that neighboring high contrast colors will need an extra 2 to 3 pixels for texel bleeding ( the line you get from non-tiling textures that are repeated is a form of texel bleeding) so colors for one object don’t show on soemthing else. The only other trick for sheets is that sometimes you can collapse uv’s into one row and squeeze out a 4 pixel wide texture. Please see image for an example of this.