Sunday, June 6, 2021

Procedural Buildings: Making Everything Interactive

My new goal for procedural buildings gameplay mode is to make nearly every object interactive. This includes all of the various smaller objects, appliances, room fixtures, etc. Basically anything that can be picked up or has moving parts. When I say "interactive," I mean the player can either pick them up and somehow use them, or use the interact key on them in-place for some effect (animation, sound, state change, etc.) Any object a person would expect to be able to pick up or change in a real building should be interactive here. At this point I've handled the majority of smaller objects, as explained in the sections below.

New Interactive Objects

I've added lots more object types that the player can be picked up and use. In addition, I made the mouse wheel switch between usable items so that the player can freely select among the inventory items. This allows for more flexibility and improved player "artwork." For example, if you have multiple colors of spray paint or whiteboard markers, it's much easier to change colors to create more complex designs.

The player can now either pull the toilet paper down from the hanging roll, or remove rolls of toilet paper from the holder. These removed rolls can then be carried around and dropped one square at a time on the floor or on top of other objects. I originally intended to stretch the paper out in a continuous band so that it could be wrapped around objects. Unfortunately, I was never able to make that look visually correct, or behave properly when the player or AI walked through it. Instead, I had to go with simpler individual squares. A single roll has 200 squares, and the roll will gradually decrease in radius until they're all used up and the inner tube is all that remains.

Check out my toilet paper artwork, made with individual TP squares dropped on the floor.

Kitchen cabinet doors can be opened, similar to desk/dresser/nightstand drawers. They don't yet contain items. I haven't modeled or drawn the cabinet interiors, so for now they simply show as black quads drawn over the opening. I also tried adding transparent holes, but those only show the interior of the wall behind the cabinets. It's not great, but it's better than drawing the cabinet faces and making the doors look fake. I'll have to get back to this and improve it later, then hide additional items in cabinets.

All of the kitchen cabinets have been opened. There's no interior yet, just a black hole sucking up all the light.

Kitchen sinks, bathroom sinks, and bathtubs can now be turned on and off. Sinks have simple animated water drawn when turned on, using a single partially transparent textured cylinder. The nearest sink generates a looping sound of running water that fades with volume based on the distance to the player.

Both bathroom sinks have been turned on, showing running water. It even shows in the mirror reflection.

Players can now enter and hide from zombies in bathroom stalls and showers, as long as the doors are closed. This will display a "[Hiding]" message near the bottom of the screen so that the player is aware that they're safe. I'm not sure how much sense it makes for someone to hide from a zombie in an all glass shower, but it was fun to add. It's not like my zombie gameplay makes much sense anyway!

I'm hiding in this shower stall with the door closed, and the zombies in this room are too dumb to notice me.

The player can interact with various appliances. Microwaves beep, TV channels can be changed, and computer monitors can be turned on and off. I plan to eventually make the rest of the appliances interactive in some way. Maybe I can figure out how to open the doors on some of the 3D models.

Players can open and close the blinds on house bedroom windows. This works with both the vertical and horizontal styles of blinds. I haven't implemented the logic to change the ambient lighting in the room because it's unclear how to do that efficiently without re-processing the lighting for the entire building. If I ever find a better way of doing indirect lighting, I'll make this work somehow.

Basketballs and soccer balls can now be throw at other objects to interact with them as well. For example, you can throw a ball at an elevator button or light switch to press it. (Since balls aren't normally found in office buildings, I allowed the player to carry items between buildings in some cases in order to test this.) Balls can be thrown at TVs and computer monitors to turn them on and off. I plan to model damage to these types of items and maybe also windows by adding crack decals in the future. Another example is that balls can be thrown at pictures hanging on walls, which will tilt them.


I explained how items can be nested inside other items in my previous blog post. What better way to increase the level of object nesting than allowing players to open boxes, revealing another level of hidden items inside. Unlike drawers that can only contain a single object, boxes can contain as many objects as will fit. I've written a placement algorithm that will attempt to stack them up or place a X by Y array of objects inside. These objects include books, toilet paper, paint cans, spray paint, bottles of water/coke/beer/wine, soccer balls, and basketballs. The contained items are less interactive and can't be used as consumables (power-ups) to make the game a bit more fair for the zombies.

When open, the 3D model of a box changes to expose the four open flaps. I check for collision of each flap with the room walls to avoid incorrect geometry intersections. These colliding flaps are bent further upward to avoid the wall. This can be seen in the bottom box in the stack to the right of the image below. Note that box flaps are not yet checked for collisions with other adjacent or stacked boxes.

All of the boxes in this storage room have been opened, revealing wine, spray paint, books, etc.

This change significantly increases the total number of items found in buildings, especially those with many boxes. However, these nested items aren't generated or drawn until the player opens the box. So I don't think it's going to affect performance too much unless the player spends hours opening thousands of boxes across many buildings in a local area. Note that once a box is opened, the state will be saved even if the player moves far away from the building and comes back.


I had previously only allowed the player to open and enter smaller closets with standard hinged doors. Now I've extended this to all closet shapes and sizes. Medium sized closets have doors that fold to each side, and larger/wider closets have doors that slide to each side. Since these closets have more interior space, they can contain a wider variety of items. This includes the usual boxes, and also lamps, computers, keyboards, and paint cans.

Here's an example of a closet with folding doors, followed by a closet with sliding doors, followed by a different closet with folding doors. I turned the closet lights on to make the items on the floor easier to see.

A medium sized closet with folding doors containing a lamp, box with a soccer ball, and box of colored spray paint cans.

A large closet with sliding doors containing a computer, box of toilet paper, basketball, etc.

A closet with folding doors containing a lamp, can of paint, computer, and some boxes.

Each closet has its own hanger rod and ceiling light that can be turned on and off by the player, or stolen for money. The player can close the closet doors and hide from zombies. When the doors are closed and the light is off, the interior of the closet is very dark. At some point in the future I may add clothes hanging in the closets.

Light Switches

The player has been able to turn room lights on and off with the 'S' key for a while now. However, I thought it would be better to add light switches to each room. These are generally placed next to a door in a way that the open door doesn't block them, and they're not obstructed by furniture and other objects. Rooms with exterior doors have multiple light switches, one at an interior door and another at an exterior door.

Every room now has at least one light switch on a wall next to a door.

I used white wall plates with rocker switches that change position when the player uses the interact key. This is the style of light switches used in my actual house. Each switch will toggle all lights in a room, unless the player has stolen the lights from the ceiling.

Book Stacking

Up to this point, soccer balls and basketballs were the only type of item the player could pick up and throw/drop. That's no fun, we need more drop-able items. I decided to allow the player to place books on the floor or any other flat horizontal surface, including stacking them on top of boxes and other books. The stack can be made as tall as the player can reach, or up to the ceiling when collision is disabled (flying mode). Books can be picked up again from the stack if they have nothing resting on top of them - in other words, only from the top of the stack. Stacking books on furniture such as nightstands and tables prevents the player from taking those items unless the books are removed.

Books stacked by the player on a table. Each stack has proper collision detection within the stack.

Books can now be removed from bookcases. Between individually placed books and those found in bookcases, drawers, and boxes, there are plenty to work with in most buildings. Some of the larger buildings contain thousands of books. There's no hard limit on the number of books that can be brought to one place.

I haven't added any true gameplay purpose for books yet. Maybe I'll allow players to throw them at zombies. Maybe I'll enable collision detection so that they can be stacked up to block the path through a doorway. Or maybe I'll hide something of value in some of them. I'll have to think about that later.


  1. The project is on GitHub:
    You can either clone and build from source, or download a release from May of this year. The textures and models are too large for the git repo and are stored on my Google Drive. If you have the project set up and want these, let me know and I can share it with you. It doesn't come with an installer like a game and will require a bit of setup work before you can run it.

  2. Do the dropped TP squares persist between building loads? Or do they reset when you enter another building like with paint?

    Please tell me you can display the real OS desktop on in-game computers so you can do real world stuff on the in-game computers?

    I can't shake the feeling that you need some sort of irradiance volume light probe system for indirect lighting. You've already got reflection planes! Usually, though, this kind of lighting is pre-baked, so I'm not sure how well it would work with various dynamic light sources. Maybe you could bake the irradiance for the nearest few rooms per light source and then scale the influence with the intensity of the source illumination.

    I love the idea of converting room types. Like, convert a room into a book room, which then grabs all the books in the building and puts them in that room. If there isn't room on the shelves, it just starts stacking them around the edges of the room. Kind of like a treasure room, but for literature.

    1. I changed toilet paper, spray paint, and markers so that their part of the building room geometry. Now I can have these in multiple buildings at the same time. Buildings with these items are flagged so that their interior geometry isn't cleared when the player moves far away from them to guarantee everything is still there if the player comes back.

      The exception is paint on exterior walls with windows. This is visible from outside the building and uses a different shader, so I can't easily draw this as part of the building interior. I'm worried about the cost of switching shaders for ever building that has paint on exterior walls, so I left this as it was before where it can only be shown on one building at a time.

  3. TP squares work like paint. They're not part of the building itself, which is why they remain even if you walk far away and come back. But they do disappear when you start dropping TP in another building - though not when you enter the other building. I wanted to framerate slowdowns when the player uses these items many times across buildings because this data is sent to the GPU every frame. I don't use VBOs for this due to the dynamic nature of the data. If there was some reason for these to persist across buildings then I'm sure I can find a way to do that. Actually maybe I never need to clear TP, since it can't be dropped as quickly as spray paint spots.

    Those desktop images are screenshots. I have no idea how to get the actual player's desktop with OpenGL, let along how to interact with Windows from inside 3DWorld.

    I have precomputed lighting that doesn't look too bad. However, it can't keep up with how quickly the player can walk around outside and inside buildings. Trying to make this work in realtime with an office building containing over a thousand lights, where the player can walk in any room at any time? I have no idea how to do that. The best I was able to do was to have some background threads running on the highest priority lights for the player's current position. It slows the framerate down a lot though, not only the computation but also re-sending parts of the lighting data to the GPU each frame as the player moves around. The second problem is how to handle the player or AI turning room lights on and off, or opening and closing doors, blinds, etc. All of these thing affect indirect lighting. It seems better to not have indirect lighting than have broken indirect lighting. (I managed to make this work in my other office building scene with a dozen light sources, but it doesn't scale to a full building. My largest buildings are likely larger than the entire levels of many games.)

    Right now the player can move books between rooms, but that doesn't change the room type.

    1. Yeah, good indirect lighting is a real trick.

      I was thinking of something like magic to change room types, summon all the objects of a certain type to a certain room, etc.