Saturday, June 13, 2020

Procedural City: Furniture for Building Interiors

I'm continuing to work on object placement within the rooms of 3DWorld's procedural buildings. First I need to show some updates to the furniture I added in the previous post. Then I'll get into the fun topic of toilets.


The books in my bookcases looked pretty plain because they were nothing more than colored cubes. I've changed them into several cubes representing the front and back covers, pages, and spine. Pages are white and the rest of the book is colored. Now they look more like books and less like colorful boxes.

Bookcase containing colorful books with covers and pages.

Next, I added pictures to the front covers of some books. This applies to books in bookcases and individual books placed on desks and tables. These are the same set of pictures/images that are hanging on the walls of rooms. Maybe at some point I can find more book-like pictures online. Not all books have cover images.

Bookcase containing books with images on some of their covers.

A book on a table with an image on its cover.

The final step was to add titles to the spines of books. I should be able to use the existing text drawing system in 3DWorld to add titles. This is the same system I use for drawing text message overlays, the framerate counter, game stats, debug visuals, etc. Text is drawn one character at a time using a font texture atlas and and array of adjacent textured quads, one per character. That leads to a ton of geometry, but I only need to generate text for books in the nearest building.

The only question is where to get the book titles from. I did a lot of online research into text generation, but it doesn't look easy to create reasonable sounding book titles. The best I could come up with was a website listing 1000 (actually 997) must-read books. I used this list of book titles as a pool of available text labels for adding to the spines of books placed on bookcases, desks, and tables. Extra long titles are wrapped onto two lines of text. Titles use colors opposite on the spectrum from the book cover's color.

Books on a bookcase with titles randomly selected from 1000 real book titles found online.


I added beds to building interiors a few weeks ago. The first version of beds used textured cubes for everything, including the pillows. As someone pointed out, these made beds look like they were made out of Legos. I went back and replaced these 5 sided (bottom not visible) shapes with something rounder with more triangles. I used a 2D, fifth root power falloff for the edges with 25 square root (nonlinear) spaced samples in each dimension. This is more expensive to draw, but looks much better. Pillows now have a smooth curve that blends into the bed sheets below rather than having hard edges.

The pillows on beds are now rounded shapes rather than cubes.


I finally got around to adding true instanced 3D models to 3DWorld's procedural building interiors. Up until now, all of the building interior models were procedurally generated on-the-fly when needed. (I don't count people and cars in this category because they're dynamic and not part of building interiors.) The main difference between room models and dynamic models is that the room models are generated as needed when the player is near a building, compared to people and cars which are all placed at scene load time.

I've been working on adding specific rooms to houses, starting with bedrooms in the previous post. Next on my list was bathrooms, which at the very least need a toilet. That's not something I can easily generate with code because toilets have too many complex curves. I downloaded a 3D toilet model online and got to work. I tried various experiments with this toilet model, some of which were interesting. I suppose the remainder of this post is going to be mostly about silly things I did with toilets.

First up, what happens if I use a toilet model for cars and pedestrians, and have 3DWorld attempt to animate the toilet as a person? Since the animation is procedural, it should in theory apply to any 3D model. Well, it did pretty much exactly what I expected, with hilarious results!

Are toilets furniture? I'm not sure, but it's time to add them to my procedural buildings. For now they're only added to houses. Maybe sometime later I can add office bathrooms. I'm categorizing them as "room objects" in the code, along with tables, chairs, bookcases, desks, beds, and lights. Toilets are placed in rooms categorized as bathrooms. Once again there are a large number of constraints on which rooms can be used as bathrooms. In fact, there may be more constraints for bathrooms than for bedrooms. Some of them are demonstrated below for amusement.

1. A room can't be both a bathroom and a bedroom:

The bedside toilet, for those who prefer not to leave the bedroom to use the bathroom. (The toilet is also probably too large and has been reduced in size after the screenshot was taken.)

2. A bathroom can only have one door, and it can't have stairs or an elevator in it:

All the privacy of having the bathroom at the center of the house and containing the stairs. At least the opaque windows give some privacy, right? (More on them below.)

3. Bookcases shouldn't be placed in bathrooms:

A bookcase strategically placed to allow for some light bathroom reading. Well, maybe it could be in reaching distance from the toilet.

4. Bathrooms shouldn't have an exterior door. We don't want visitors entering the house through the bathroom. (Sorry, I don't have an image for this one.)

There are also constraints on room sizes, number of bathrooms in a house, etc. I won't list everything because I don't have nice pictures of the other items.

Once all of these conditions are checked, it's time to place a toilet in a corner of the bathroom away from the door. This exposes another problem though. The toilet is often placed near a window, and can be easily seen through the window from outside the building. That certainly doesn't look right!

A properly placed toilet, except for the fact that it's next to a big transparent window.

Something must be done to address the lack of privacy when the toilet is placed near a window. So, what can we do about this? Real bathrooms use windows with frosted glass, swirly patterns, or glass blocks to prevent people from looking in but still allow the light to enter from outside. These windows have glass that refracts light in a complex way, distorting the light pattern to prevent people from seeing through them. They're often smaller than regular house windows as well.

I can't easily vary the size of windows per-room, and it's too expensive to create a proper refractive material. I'm not sure exactly how to do this in a way that looks right for all indoor and outdoor lighting conditions either. For example, the window should be bright in the day time when the sun is out and dark at night. I don't really want to have to regenerate the window when the room lights are turned on or the time of day is changed. I also can't make it partially transparent because then people can still see though the window. The best I came up with was adding a generic texture of an array of glass blocks.

I replaced the window with some frosted glass blocks to give the bathroom more privacy.

There are some minor issues here. The lighting/color is fixed, independent of time of day. It's that sort-of-light-but-not-bright color in between what you would get at night and what you would get during the day. The window is probably larger than it should be. Also, the blocks don't align with the corners of the window. Fixing the alignment is very difficult. The glass block texture is actually slightly behind the wall and covers the entire wall, which avoids having to figure out how many windows there actually are in this room and where they're located. It's also more efficient to draw one quad per wall rather than one per window, though there is often only one window in a bathroom. This is good enough for now.

I suppose I'll have to add sinks next. Maybe I can also add mirrors that have real reflections. I'm not sure what to do about the player's reflection since there's no player model, but I should be able to reflect everything else in the room.