And to give an idea of the size of the map, here is a montage:
Using a 1024px texture, the map is an almighty 1024 bu square. The ship is 2bu high. How on earth does a 1px-per-bu map work? Using another texture to add detail and interpolation:
Because each pixel has 256 possibly alpha values, that 256px/bu gives approximately control on a scale of 1/256th of a bu - which is more than enough. Couple that with a detail texture to add interest, and you’re all set.
The detail textures are 1024px as well, and each spans 20bu (more than a screenwidth), so surely you’d see those pixels as well? Well, because of the clipping value, interpolation and the 256-possible-values, you really can’t. But if you zoom in to the grass, you can see the effect of the interpolation. Bear in mind this is several hundred times closer than you’ll see in game - it normally reaches about to the top of the landing legs:
The shader node that handles the details looks like:
There are four input channels (RGBA of the terrain map). Each get’s multiplied against a channel in the associated texture. This means you have 9 different detail textures, of which three can be displayed simultaneously (and you can display mixes between them). Each detail texture is mapped to 1/3 of the alpha values, which allows the full range of the detail textures channel values to come from the texture. This also allows you to put grass on the rocks without either texture “clipping.”
The multiply and power values on each image are fudge factors to solve an off-by-half issue I couldn’t identify the proper source of. I think it may be to do with conversion from RGB into B/W.
For the physics mesh, the terrain (with detail shader, but without grass) is rendered out at 16x resolution (ie 16px/bu, 16384x16384). It takes about 1/30th of a second for the GPU to generate, and then about 30 seconds to transfer it to the CPU and save it as a 1Gb bmp file. This is then converted into a SVG by a tool called “potrace”. The SVG is imported into blender and then:
- Converted into a mesh
- Doubles are removed at a distance of 0.01bu (because the SVG curves are quite detailed, but we only have 16px/bu of actual information)
- A limited-dissolve is run at 5 degrees to prevent excessive vertices on flat areas.
- extruded to give the physics engine something to work with.
This whole process takes about 1 minute.
You can see here the detail on the generated physics mesh:
For the map shown in the top image of this post, the polycount is 3000 polygons for the lower cave structure, and is both far more detailed and far more efficient than anything I could do by hand. As the level grows, the polycount will increase, and I hope bullet will be able to cope. I suspect it will end up being ~100,000 polygons. If needs be, I may end up separating it into multiple smaller meshes in a grid pattern to better use the physics engines broadphase.
The physics mesh is also used for casting the shadows, as it can be “seen” in 3D by the render engine.