45. 3D Town walkthrough
This post continues my adventures with 3D. Having created a simple 3D racing track in an earlier post, I wondered how difficult it would be to build a small town with buildings you could walk around – and maybe into as well.
http://instagram.com/p/YqzglfBHZo/
Creating the surface
This is hard if you haven’t done it before, but I borrowed the code straight from my racer program to create a 3D surface that stuck out into my screen, ready to put stuff onto.
3D modelling
Creating buildings isn’t too hard by 3D standards, once you get the hang of it. I had done this with my dice example in an earlier post, so I borrowed that code to create a function that would make walls and boxes and floors out of triangle vectors.
Textures
If you’re going to make a realistic 3D scene, you need textures. I found hundreds of free textures on many different sites, by simply googling for textures of different kinds – and many of them were designed so that you could tile them and they lined up exactly (ie no visible join between tiles). So that was much easier than I expected. (I added all the free texture sites to my sprites magazine in Flipboard – see post 42 for details on how to access this).
However, you soon realise you need quite a lot of textures if your scene is going to look at all realistic, and Codea isn’t really set up to handle that (eg it doesn’t have subfolders, so all your images from all projects have to live together). But it was OK for this limited experiment.
Scaling the textures
One thing I didn’t think about when collecting textures is that they need to be scaled. If you have this image
http://instagram.com/p/YqyzuqBHYa/
and you want to use it on a building that is 200 pixels high, you are going to get enormous bricks if you stretch this image over each side of the building.
What you have to do is specify how many pixels the image covers, and then tile the image over the wall many times – so if the image covers (say) 50 pixels, then a 220 pixel building will need 4.5 copies of the image (drawing the fractional part gets a little tricky,too).
You need to do this for all your textures so they are all scaled to the same size.
Superimposing textures
Of course, a blank building wall is pretty dull, so I wanted to add windows, doors, maybe posters. You can do this by using the same code that draws walls, but the problem I had was that when two drawings occupied exactly the same space (eg the wall and a window on that wall), the screen flicked erratically between them as though it couldn’t make up its mind what to show.
The answer is to draw the windows, doors, etc very slightly in front of the wall. So if you have a wall that runs from Y=100 to Y=200, with X=150, then you draw the windows and doors using X=150.1 (Codea handles fractional pixels fine). The top picture above shows the effect.
You can also draw interiors this way, by drawing a second box very slightly inside the first one. I drew a plaster texture inside one building this way, as seen below, and gave it a carpeted floor.
http://instagram.com/p/Yq0sF1BHbP/
The plaster looks very nice, and is an example of a texture designed to tile seamlessly.
There is one problem with interiors, which is that you need the doors and windows on the outside to also appear on the inside in the same place, in reverse. However, a simple trick is to make the doors and windows into boxes (ie give them four sides, like the buildings) and make them just deep enough to stick out from the building by 0.1 pixels on each side of the wall. This means one drawing does the inside and outside at the same time – and puts them in the right place on the inside, in reverse, too.
The things I didn’t do
I didn’t manage roofs. I have textures, but roofs are angled, and need to slope in all four directions. This required special code, which I haven’t written, so my town inhabitants might get wet. (Luckily I haven’t drawn any rain yet!).
I also wanted to be able to have open windows and/or doors, so you could see into buildings, or, if you were inside, you could see out. However, this is extremely difficult, because when you are making vector buildings, you can’t cut holes in them afterwards – you have to leave the holes to start with. And this means figuring out what rectangles are required to produce walls with holes cut in certain places, which apparently can be done as long as you use totally incomprehensible maths techniques. So I kept my doors and windows closed.
FPS
In any animation like this, you have to watch the frame rate (frames drawn per second), trying to keep it as close as possible to the normal 60 per second. Codea managed 60 FPS most of the time, except when there was a complex pattern on the screen – eg when looking across the tiled courtyard into the distance, or when inside the building with textured plaster and a fancy carpet. Then the FPS dropped to about 30.
This is OK, but I didn’t have many buildings, and I knew that if I added much more stuff, I was going to have to start managing the drawing, by figuring out which things didn’t need to be drawn (eg insides of buildings, unless you are inside them).
Where to from here?
I’ve stopped, for the moment at least, because this is getting big, and it requires a lot of planning and organisation. I’ve learned that 3D gets big and messy very fast. It’s exciting to create a 3D environment that you can walk through, but hard work, too. And I’m only working with rectangular and square objects – I haven’t even considered the difficulties involved with curved objects.
Where I got to
Below is a video of where I got to, showing a few buildings, the inside of one of them, with plaster walls and carpet, and the courtyard, complete with graffiti on one wall.
I’m happy to share the code, but to make it run, you will need to save a number of texture images into your Dropbox account.
Update:
Code is here
Zipped images are here, put them in your Dropbox Codea folder
I’d like to take you up on the code and assets. Great job!
ok, I’ve added links at the bottom of the post
Congragulations. Good job.