Sunday, August 24, 2025

Procedural Prisons

This post continues my work on special purpose procedural buildings. I added basement jail cells in the previous post. This time I'm expanding on that topic and generating entire prisons, where the jail cells form one of the basic building blocks.

Prisons have been more work than I originally expected, and I can tell from the start that this will be a long post. This also partially explains why I haven't posted anything else in the past two months. The other reason is that I'm typically busier with non-programming work in the summer. I need to get off the computer and outside for at least part of the year, and the best weather is in summer. My daughter is starting high school as well, so that's one more distraction from this project.

Prisons required quite a few new features:

  • A new building type (prison, obviously)
  • A new floorplan class (cell block - open area with cells cut out of it)
  • A new window type (barred)
  • A new interior door type (metal door with window)
  • A new flooring type (rubber gym mat) 
  • Three new room types (visitation, gym, shower)
  • Four new object types (gym weight, exercise machine, cafeteria tray, bar of soap)
  • Five new 3D models (dumbbell rack, Roman chair, exercise bike, horizontal bar, leg press)

I can tell just by looking at the line counts of the source files that prisons were more work than retail stores, factories, warehouses, hospitals, and schools. So far there's 1391 lines of code. Prisons weren't as much work as malls, but malls have multiple blog posts. If you want to take a look, the code can be found in my GitHub project page.

I'll cover all of these additions below. I think it makes the most sense to explain the details of these categories and then show interior screenshots of everything together near the end of the post.

Interior Floorplan

Most of the existing above ground special building types were assigned to the single rectangle building shape. This includes retail stores, factories, warehouses, hospitals, schools, and parking structures. These buildings have a simple rectangular floorplan that makes it easy to assign as open space or add hallways with rooms to the sides in regular patterns. The problem is that most of these buildings are already assigned to one of the previous functions/types and there aren't many unassigned buildings left to make into prisons.

So instead I'm going to select multi-rectangle building footprints for prisons. These are the ones shaped like the letters L, T, H, U, O, or +. (Well, I guess '+' isn't a letter.) I'm limiting this to non-stacked floorplans where all vertical floors have the same footprint. Even with that limitation, things get complex as I need to handle adjacency between these rectangles and ensure that everything is connected and all rooms are reachable. Note that this also includes those 'O' shaped buildings with interior courtyards, which of course caused me trouble.

The basic idea is to convert each rectangle into a separate cell block. I decided to place prison cells along windows such that each cell has exactly one full exterior window at the back, and possibly a window on the side for corner cells. Window spacing tends to be around 6-8 feet, which makes for a reasonable cell size that can fit a bed, sink, and toilet. Regularly spaced windows leads to uniform cell sizes. Aligning cells to windows also avoids the need to check for and avoid walls that intersect windows.

The cell block floorplan has cells along the windows on two opposite sides and a central hallway down the center. I chose the hallway direction (north-south vs. east-west) as the one that allows the largest number of cells to be placed. This is usually the longer side that has more windows, except for a few cases where cells can't be placed near interior corners. Large rectangular areas will have a very wide hallway that can be further partitioned into a cluster of central rooms, effectively breaking the area up into two separate cell blocks. I divided this central area into a row of adjacent rooms and a hallway connecting the opposite cell blocks if there's space. That way I can make some of these rooms private types such as bathrooms without requiring people to walk through them to get from one cell block to the other. The combination of two cell blocks and connecting hallway typically forms a H or S shape of public hallway space in each building part.

Adjacent rectangular parts are connected together with a wall and a metal door to provide access to all areas of the prison. Doors are required at each adjacency, except for the case of O-shaped ring buildings where one door can be omitted while still having a fully connected floorplan. The placer can remove cells or re-generate the floorplan so that required doors can be added. The most effective fix for missing doors is to remove cells from one side of the hallway (preferred on the interior side) to make more space for a door.

The next task was to add stairs and elevators to connect floors vertically. The existing placement logic for stairs and elevators doesn't work for this custom floorplan. There is no single central hallway, and most rooms are too small or too private to place stairs in the center. The best solution I could come up with was to place both the stairs and the elevator in a corner of a room if there's no other valid placement. This will sometimes create elevators adjacent to exterior walls that partially overlap windows. It doesn't look great, but it's more important to ensure buildings are connected for gameplay purposes.

Sometimes the stairs placement will still fail. This happens often in H and O shaped buildings with thin rectangles. The problem is that the placement areas have just enough room for cells on both sides and a hallway in the center, but the hallway isn't wide enough to fit stairs at any point along it. I decided on an iterative approach where I throw out and regenerate the floorplan if stairs placement fails. Each iteration I increase the minimum hallway width, and eventually the placer can only fit cells on one side of the hallway. This works for all buildings I've seen.

The second part of the problem is connecting basements with stairs. Prisons can have basements with either parking garages or more cells (dungeons). My solution to this problem was to extend the above ground stairs to the basement when possible. I blocked off the space below these stairs in the basement to make sure no cells or parking spaces are placed there. These stairs will also continue down to lower basement levels, connecting the entire building together vertically with a single set of stairs. This is the first time I've written code to create stairs that span the entire height like this. I went back and changed the stairs placement so that the other building types such as office buildings can use this approach as well.

The default flooring in prisons is concrete, and the default ceiling is acoustic tiles. Maybe the ceiling should be concrete? Or is that too much concrete? Some of the special room types have other flooring and ceilings. For example, offices and classrooms have carpeting, gyms have rubber or wood, and cafeterias, showers, and bathrooms have some type of tile. The various flooring types show up as different shades of gray in the floorplan image below. 

Prison L-shaped floorplan in top-down map view. A total of 20 Cells are along the top and bottom rows. Walls and ceiling lights are white while desks and tables are brown. Tile is light gray, concrete is mid gray, and carpet is dark gray.

Windows in rooms assigned as cells or cell blocks have thicker frames and bars installed on the inside of the glass. Doors connecting cell blocks to other rooms use a new type of heavy metal plate door with a barred window. This type of door required extra work so that the player and building AI/zombies can see through the window, rather than treating closed doors as sight occluders. Metal doors have a different opening and closing sound that's metallic.

Exterior doors posed a new challenge. If I have prison cells at all available windows, where can I find space for the entrance door? In some cases it can be placed on the side of the building part that doesn't have cells. But that isn't always possible with those thin rectangles of H and O shaped buildings as the cell doors may block the entrance door when they're both open. My solution was to choose a ground floor cell and change it to a small entrance room, with a door to the outside and a metal door leading to the cell block on the inside. I had to make a similar change to add a courtyard door to the O-shaped buildings. (I would like to make the courtyard into an exercise area or basketball court, but I haven't gotten to that yet.)

H-shaped prison exterior showing entrance door and bars in the windows. Ah, Mink Prison.

Prison entrance doorway area with its own metal security door. This is really a repurposed cell.

Path Finding 

This new floorplan broke building AI navigation. The problem was that the cell block "hallway" areas weren't simple rectangular hallways because they had missing cells where building rectangle parts abutted and there were no windows. This formed open areas with L, U, and T shapes. The existing AI path finding system only works on rectangular rooms. Now this isn't exactly new, I do have some odd room shapes in other buildings. For example, the factory floor has an office and bathroom cut into the corners, and hospital patient rooms have corner bathrooms. I had written special case code to handle these, but it was too difficult to extend that to work with arbitrary cell block shapes with any number of nested rooms.

The new system I wrote orders rooms inner to outer based on nesting: cells first, then the cell block/hallway. The room an object is assigned to is the first room that contains the center point of the object. This works with the player, building AI, and placed objects. Doors between sub-rooms work in a similar way: The first connection is to the parent room containing the door, and the second connection is to the child room adjacent to the door. Building AI navigation must also consider walls between nested rooms as blockers/colliders for the parent room.

This took quite a bit of experimenting to get correct. It involved some head scratching trying to figure out why people were stuck in place or walking through walls. I think I have it working correctly now. (Update: No, it's still broken, but I'll fix it.)

Room Assignment 

Okay, back to that cluster of rooms between the cell blocks. I decided on a list of eight possible room assignments for these, some of which are new room types:

  • Visitation Room (new)
  • Laundry Room (commercial type like the ones in hotels)
  • Office (generic room type that can always be added)
  • Cafeteria (same as school)
  • Gym (new)
  • Shower (new)
  • Classroom (same as school and hospital)
  • Bathroom (office style with stalls)

Some of these are reused, with minor changes to adjust for prisons. For example, there are no alcohol cans or bottles, and most of the clothing is orange. Larger bathrooms have one wall of cells replaced with enclosed/private showers. These are basically bathroom stalls with the toilet replaced by a shower and small bench.

Prison bathroom with shower stalls along one wall. These use the toilet stall geometry but have a shower instead. Out of order signs apply here as well.

I decided to create a new system for prison room assignment rather than writing a mess of special cases like I did for other building types. This system assigns weights to the various room types based on their constraints and preferences, and chooses the room type for each available "slot" as the one with the highest weight. I added a bit of randomness as well so that the same types aren't chosen for rooms stacked above each other.

This system has a number of scored categories and constraints:

  • Preferred min/max room size
  • Desired room count (per prison): one, multiple, etc.
  • Are stairs and elevators allowed in this room?
  • Are exterior doors allowed in this room?
  • Is room private? If so, it can't be on the only path between two other rooms. 
  • Preference for ground floor vs. upper floors vs. basement
  • Desire for windows vs. no windows vs. don't care

Each candidate room is scored across the categories and the room type with the highest score is chosen. This system isn't perfect as it tends to place most of the special (count=1) rooms on the ground floor as rooms are assigned bottom up. However, this does work out better for the player since they can see these rooms without taking the stairs or elevator to upper floors. There are also situations where the more constrained room types such as bathrooms and shower rooms are missing from the building entirely. I don't have a good fix for this, other than setting a max size for buildings selected for prisons to ensure there's space for more interior (non-cell block) rooms.

Laundry room visible through the barred window on a cell block metal door.

 

Rounded Rectangles

I wanted to add metal trays to prison cafeterias rather than the ceramic plates I had in malls. This is good for school cafeterias as well. I originally created rectangular shapes, but they didn't look very good. I wanted rounded corners. I discovered that I could create a rectangle with rounded corners by taking a cylinder, splitting it into four quadrants, and translating those quadrants away from each other in a way that stretches the edges connecting them. In addition, I can apply this to a truncated cone to get a rectangular shape with sloped sides.

Now "round rectangle" is an official object shape that can be used. This is the shape I used for cafeteria trays and bars of soap. I also changed the existing drawing of mattresses, trashcans, cell phones, and mall store theft sensors to have rounded corners. I attempted this with conference tables, but I was never able to get texturing to work with this shape. So I only apply this to solid color, untextured objects.

Prison cafeteria with rounded corner metal food trays. I should probably remove the plates.

Cell Blocks

Cell blocks are the areas that include rows of cells and the connecting hallway. They may have cells on one side, both sides, or a mix of the two for some of their length. Cells are separated from adjacent cells by plaster walls and separated from the hallway by metal bars and a barred door. This is similar to the basement "dungeon" prison rooms in the previous blog post.

I added guard desks with chairs and phones to hallways wide enough for them to fit. I also added flashing red warning lights between some of the cells by reusing those objects from factories. I was thinking of placing keys on either the guard desk or the wall somewhere, but I haven't gotten to that yet.

Cell block with cells, stairs, and open metal door.

 
Cell block with U-shaped hallway/open area (opens up behind the room on the back left) and guard desk. 

 

Visitation Rooms

Prison visitation rooms are divided into two halves for the inmates vs. visitors. There is a glass window separating the sides, with rows of small tables and chairs between them. I placed telephones on both sides of the desks. I think it would make sense to have only the receiver part of the phone, but I only have that one office phone 3D model with an included keypad. Separators are added between visit stations for privacy. The visitor side of the room has a row of additional chairs along the wall to serve as a waiting area.

The dividing line must be chosen so that both halves of the room have an exit door. Then the prisoner vs. visitor side is determined based on factors such as connected room types, location relative to building entrance, presence of windows, etc. If no valid dividing line is found, the room is reassigned to another type.

Prison visitation room with glass wall, tables, chairs, phones, and dividers. This is the visitor side with some waiting room chairs on the right. I'm not sure what's causing the light banding on the dividers; I'll fix this later.

This split room does cause problems with zombie path finding. They sometimes enter the side opposite the player and will wait there rather than going around to the player's side. I believe this is the first room type that can't be crossed. I'm sure I could fix it with enough special cases, but I don't know if it's worth the trouble.

Gyms

Prison gyms have custom flooring that's either rubber gym mat or hardwood boards. I think the rubber mat is more appropriate for weight lifting areas, so that type is more common. Gyms can either be assigned to interior rooms or exterior rooms that have windows.

Gyms are full of exercise equipment and multiple types of weights. I've added five different 3D models of equipment, plus multiple styles of procedurally generated lifting and hand weights, as well as individual metal weight rings. Gyms also have a row of lockers along one wall, assuming there's space. Benches are placed along walls in random places. Sometimes an orange shirt is added on the floor, and orange shirts are in the lockers. I didn't have a proper prison jumpsuit 3D model, so I reused the tee-shirt model. Some gyms have water fountains and others have wall mirrors. I didn't want to add too many objects and risk making these rooms too cluttered for the AI people to cross through, so there's quite a bit of open space.

I allowed stairs to be placed in gyms. This looks somewhat out of place, though it's not nearly as bad as stairs in bathrooms or shower rooms. Stairs don't fit in cafeterias, classrooms, or visitation rooms either. I had to allow them in gyms to avoid being too restrictive and seeing buildings with no stairs.

Prison gym with rubber floor mat. This one has exercise machines, weights, lockers on the back left, and a water fountain in the back right.

 
Prison gym with the less common wood flooring (using a fence texture!) This one has metal benches on the sides and a mirror in the back. Lockers are on the back right.

Shower Rooms

And last we have prison shower rooms. We can't forget to add shower rooms! Thankfully I've never been in one of these, so I had to use reference images. The walls, floor, and ceiling use the same tile textures as underground swimming pool rooms. (That green tile wall texture looks exactly like the room I remember taking swimming lessons in when I was a kid.)

I decided on having an open area with shower stations along the walls everywhere that's not blocked by a door. Wider rooms have an additional central wall with more showers that creates a ring-like space. Each shower has single or dual handles, a shower head, and a drain. The player can turn these showers on, but this only plays a water sound. I placed some metal benches between the showers were there was space. And of course, you can also find bars of soap on the floor that can be picked up. I reused the rounded rectangle shape for soap.

Large prison shower room with a central wall and multiple benches. Look, a rat on the floor! There are also bars of soap on the floor if you look carefully. They blend in with the white tile.


Smaller and dirtier prison shower room with water damage, trash on the floor, and a rusty metal door.
 

Final Thoughts

Wow, this post was a lot of work to write! I hope people find all of this interesting. There are some minor fixes and improvements left to do for prisons. For example, I'm still not entirely happy with the room assignment. I would prefer that each prison has at least one room of each special type.

What's next? I finally have a plan for drawing those reflective metal objects in building interiors. I'm going to see if I can generate a cube map texture for the room the player is in to use for reflections in the fragment shader. I'm not sure how this will work for non-rectangular rooms like prison cell blocks. I guess we'll have to wait and see.

Sunday, June 22, 2025

Underground Jails

It's getting close to the 4th of July and summer time in general when I'll be busy with other things and won't have as much time to work on 3DWorld. I may not get a chance to write a blog post in July. I didn't want to start on a big project such as a new building type right now, so instead I added a new room type. I'm not exactly sure what made me think of this, but I decided to add basement jails. I was particularly interested to see how the lighting and shadow code performed on a room full of narrow horizontal and vertical bars. I suppose these fit with the interrogation rooms I added last October.

It's always easiest to place special room types underground as I don't need to worry about windows and other exterior elements. The existing code for extended basements creates a huge network of underground rooms that I can work with. The first step is to choose one that's both long enough and wide enough to create a hallway with rows of jail cells on either side. This isn't as common as you may think since the existing code tends to create rooms on the smaller side or rooms that are long and narrow. (Usually the long narrow rooms are the result of failed hallways that don't have a room to connect to and are converted to "leaf" rooms.) The second test is for a doorway near the center of either one or both of the long ends of the room, and no side doorways. Most rooms meet the door requirements.

Once the jail rooms are selected, they're divided in the short dimension into a central hallway with rows of cells to either side. Bars separating the cells and hallway use a mixture of rusted metal or scratched metal textures. The room doorway connects to this hallway. Cell size is uniform for each room and chosen to be deep enough to fit a bed's length and long enough to fit the bed width, cell door, and sink side-by-side. The cell door is in the center and has a set of bars to either side of it spanning the width of the cell. In addition, I added a toilet to the back wall opposite the door with a toilet paper holder next to it. It's not much privacy, but I suppose it's not much worse than the toilet placement in some of my generated houses.

Each cell is created in a similar way to bedroom closets in houses. I didn't make them sub-rooms because the sub-room logic really only works well for a single nested room, and it wasn't needed in this case. I added a small round light to the ceiling in each cell, in addition to the larger hallway light(s). At first I had the two groups independently controlled, but later added a single light switch next to the door that controls both sets of lights. I reduced the amount of indirect lighting for jails because there are so many lights, few occluders, and I feel it looks better when the jail area is somewhat darker than other rooms.

Jail bars are handled like interior windows used with conference rooms. They're not occluders since the player can see through them, but they do block object interactions. This means you can't take objects through the bars or interact with objects on the other side of the bars such as flushing the toilet. Zombies also can't attack through jail cell bars.

All cell doors swing outward into the hallway. In fact I reused the same logic as interior doors and only changed the graphics to replace white wood with rusty metal bars. I also replaced the wood door open/close sound with a metal door sound. Jail cell doors are narrower than standard building interior doors so that they don't block the narrow central hallway as much. I initially had problems with zombies passing through the openings because their collision bounds were expanded to include their animations and were wider than the doorway. After some experimenting, I went with shrinking the length of the bars to either side of the door when used with AI collisions. This effectively widens the opening slightly for the AI to pass through while following the player.

The first style of jail cell has walls separating adjacent cells. These use a plaster material in houses and a concrete material in office buildings to match the extended basement room walls of these two building types. I replaced the carpet on the floor with concrete in these rooms. The walls, ceilings, and floors pick up the cracks and water damage properties of the building's basement. Here is an example of this style of jail with indirect lighting enabled.

Jail with walls between cells. Some doors have been opened and some others are locked with brown padlocks.

Some of the cell doors are locked with a padlock, with a key to all cell locks hanging on the wall opposite the door. The screenshot above has brown padlocks and a brown key that can be seen in the very back if you click on the image to zoom in. In theory it should be possible to lock a zombie in a cell if I set the doors to be re-lockable, but I don't think this works in practice. They only enter the cell if the player is in there, and they tend to block the exit and corner the player in the cell. The only way I've been able to get by them without being killed is by pausing the AI logic or disabling collision checks. So instead I changed the padlocks to be permanently removed when the cells are unlocked so that it's not possible for the player to lock themself inside. The key remains in the player's inventory after use and can be used from either side of the door just in case. Maybe I'll eventually add a way for the player to place zombie bait in jail cells, and then allow the door to be re-locked.

The second style of jail cell uses another set of bars in the opposite direction to separate cells rather than adding walls. It forms cells surrounded by bars on up to three sides. It didn't look correct to place a sink next to these bars, so I moved the sink to the back wall between the bed and toilet. Only cells that are long enough to fit all three of {bed, sink, toilet} along the back wall can use this style. This produces a more open floorplan and more complex shadows.

Another jail with bars between cells rather than walls.

Jail beds are different from house beds. They have black metal rather than wood frames, and always have white sheets. The theme here is grayscale colors. Some of the cells have a single bed, while others have bunk beds. These are really just two beds stacked vertically with a short ladder added to the side.

Closeup of a jail cell bunk bed. A sink and toilet are also visible.

I actually added bunk beds to house bedrooms earlier, I just haven't shown that in my blog yet. I also added a small random chance of a person sleeping in the bed. This somewhat unintentionally applies to jail cell beds as well, but only for jails in house basements. Let me find someone sleeping ... there she is. That's not a very relaxed position, and her head is a bit too much sunk into the pillow. I didn't have a sleeping animation, so I used the first frame of the idle animation instead.

A jail cell bunk bed with a woman sleeping in it.

She's not wearing an orange or black and white jumpsuit though. And high heels in jail? I guess there's not much I can do about it because I can't find a 3D model of a person with a prison uniform on Mixamo, other than one of the zombie models I already have. Wait, I can make all zombies prisoners. That's appropriate for this post! They're not lying in beds though because I don't have any animation for this zombie model that looks correct when lying in a bed. Both the idle and walking animations have him hunched over with his arms out.

Zombie prisoners have cornered me at the end of the jail hallway. At least he only has one arm to hit me with.

I still feel like these jails are a bit too bright. I can turn off indirect lighting and it looks like the screenshot below. There are more shadows and light vs. dark color contrast. I kind of like this look. It reminds me of a black and white photograph. What do you think?

A jail with concrete rather than plaster walls and many cracks. This screenshot has indirect lighting disabled and has harsher lighting with more shadows.

That was a fun post to write, especially the part at the end with the woman in bed and the zombies. What's next? Now that I have jail cells, it should be possible to add full prisons. I would need to work out the window placement so that cells can be added to above ground rooms. It's likely significant effort to customize the interior enough for a prison, so I'm not sure if and when I'll attempt this.

The project with source code is available on GitHub. Some people have been asking me how they can view these buildings themselves. This requires changing default.txt to enable config_heightmap.txt, which is the base scene I've added cities and buildings to. It helps to download the extra 3D models and textures from my Google Drive link. You can find the instructions in my README file.

Thursday, June 12, 2025

Parking Structures

I'm continuing to work on my series of special procedural building types. Previously I added malls, factories, warehouses, hospitals, and schools. I did go back and add a number of features to those other types. For example, I added locker rooms to schools, hospitals, and industrial buildings. I created coffee machines that dispense coffee and hot chocolate for break rooms. I placed shoes on the floor next to front doors. I added hard hats to factories and warehouses. Computers and mice on desks. Test tubes of blood, valves, and gauges in hospitals. Apples on school desks. Shader-based abstract art pictures in houses. (I might write a separate short blog post on these later.) Those additions aren't the subject of this post though. Maybe I'll show some screenshots of these changes in the next summary/progress post.

This time I'm working on something a bit different that has a new style of building compared to the other types. I've added parking structures, which are above ground variants of my underground parking garages. The biggest difference is that these buildings have open gaps between walls rather than individual windows. This may seem like a minor difference, but making the generation and drawing work in this case was quite difficult. Previous buildings always had the interior window surfaces drawn as opaque when the player looked in from outside. This was due to a technical limitation of how windows were cut out of exterior walls using textures and stencil masks rather than actual geometry. While this did make drawing more complex, it also meant that buildings functioned as occluders for objects behind them. This is not the case for parking structures. The player can see completely through them and out the other side. They're more open air than concrete walls, which means that some of my earlier optimizations are no longer valid.

I did have some trouble with lighting due to the way interior room lights and exterior sun/moon light is handled in two separate draw passes. All building objects are labeled as interior vs. exterior and drawn in exactly one of those passes. The problem with parking structures is that they have walls and pillars along the exterior edges that are visible from both inside and outside the building. I can't use trickery with the depth and stencil masks to draw walls with window cutouts here. What I ended up doing was drawing some of these objects in both interior and exterior passes, with different faces enabled for each pass depending on which way they were oriented. Those vertical pillars along the outside edges are effectively half inside and half outside the building. 

While the exterior is different, the interior is mostly a combination of existing components. I reused most of the existing underground parking garage code to create the above ground variants. This includes all of the logic to insert pillars, walls, ramps, parking spaces, cars, and sprinkler pipes in the ceiling. The only differences were related to anything placed on walls, and the logic to avoid obstacles. I did have to make some changes to object drawing to increase the draw distance of pillars and walls so that they wouldn't disappear when the player walks away from the building like the underground versions of these objects do.

Those exterior pillars I mentioned above are special cases. They're not added to underground parking garages because the outside walls provide support. However, parking structures don't have full height walls, so they need more structural support. I wrote code that attempts to move pillars to the sides in multiple iterative steps if they intersect another object or block the stairs, elevator, or ramp. I also added a type of narrower non-square pillar that is easier to fit into tight spaces. The placement algorithm should ensure there's enough clearance for cars to move around and between fixed structural objects like this. 

I reused the code that attached fire extinguishers to mall pillars to add them to pillars in both underground and above ground parking areas. I also repurposed the code that adds stains to walls and floors so that it places oil stains in some parking spaces.

Below are some screenshots of the new parking structures with indirect lighting enabled.

Parking structure interior with cars, a person, handicap spots, stairs, elevator, red sprinkler pipes, oil stains, and a fire extinguisher in the back center.

Parking structure with walls between rows of parking spaces.

All parking levels are connected by a set of vertically stacked ramps that extend from the basement up to the roof. These ramps run along one side of the building, are wide enough for two cars to fit side-by-side, and have enough clearance at the ends for cars to turn. I added railings on the inside edges and at the end of the upper (roof) level. These are wider versions of the original underground parking garage "ramps to nowhere". The player and building people/zombies can walk up parking ramps, and objects such as balls will roll down them.

Close view of a ramp connecting multiple parking levels.

 

A large and open parking area full of cars, with stains on the ground. The ramp is to the right.

I added the elevator and stairs next to each other on one of the building's sides. Handicap spaces are placed next to these and limited to 5% of total spaces. In my opinion, the U-shaped stairs work better than straight stairs for parking structures. They're more compact and leave more room for parking spaces, though they do look somewhat odd next to elevators due the the large difference in depth. Maybe elevators should be larger? I mixed the stairs up so that they face the same direction as the elevator 50% of the time and are perpendicular and facing away from the elevator the other 50%. Stairs extend from the basement all the way to the roof and are numbered on each floor. Elevators extend from the basement to the top floor. They don't reach the roof because I haven't implemented elevator entrances above building interiors. Technically, city malls have elevator levels above ground, but that's somewhat of a different case to handle.

A closeup of the stairs and elevator. Maybe the stairs need a light like I added to retail buildings?

Each parking structure has a small bathroom in a corner on the ground floor with a toilet and a sink. This uses the same room-inside-a-room logic as hospital patient rooms and industrial buildings. The entire remainder of the above ground building is a single room of type "parking" that covers all floors. Once again, it's much faster to reuse existing code. It's not entirely reused though because I had to add the side walls, as there are no full height exterior walls on the building itself that form the outside walls of the bathroom.

A parking structure bathroom. It's similar to bathrooms found in hospital rooms and smaller office buildings.

That's all for interiors. It's time to discuss the exterior design. Parking structures have a number of exterior doors with a bit of concrete wall to the left and right of them to give them a proper frame. There's also a cutout for the area where cars enter and exit. I added "enter" and "exit" signs, in addition to signs marking the clearance. A driveway extends from the entrance outward, but doesn't yet connect to a road.

Inside the entrance is a pair of ticket machines with gates/bars that can either be raised or lowered. The machines themselves use a texture I found online for the front panel and a yellow and black striped gate arm texture. The arm blocks the player but can easily be walked around. I haven't made these machines interactive yet. 

Now I'll show a few screenshots of parking structure exteriors. Note that the lighting looks different here. This is because 3DWorld has separate lighting environments for building exterior vs. interior light sources. The interior lights from the above screenshots have precomputed indirect volumetric lighting enabled. This only works for the building the player is currently inside (for performance reasons), so there is no indirect lighting visible in this outdoor screenshot. In addition, the custom ambient lighting for parking structures that I used to offset the lack of windows is disabled when the player is outside.

Parking structure entrance/exit viewed from the outside, with enter, exit, and clearance signs visible. Here the ramp is near the entrance.

Parking ticket machines with gates on both the entrance and exit sides. Some gates are open while others are closed.

 

The parking structure roof has a small enclosed area at the top of the stairs as well as the uppermost ramp segment. I haven't yet found a good way to add cars or parking spaces to the upper levels. This is technically the roof rather than an interior part of the building. The normal object placement system doesn't support objects added outside the interior bounds of the building. I have limited support for adding rooftop items, but this doesn't include 3D models. I also can't reuse the code to add cars to parking lots as that only works inside city bounds.

Since the rooftop is otherwise empty, I decided to add something similar to streetlights. This way there will at least be light sources if I do find a way to add cars. This doesn't actually use the same system as city streetlights because it wouldn't be efficient in this case, and again, this isn't inside a city. Instead I used the system I created to add porch lights to houses that collects together all light sources during the building generation step. The performance is acceptable because only around 50 out of 18,000 buildings are parking structures. It seems to work reasonably well, though it doesn't support shadows. I think that's okay because there aren't many shadow casting object on the roof yet anyway, other than the light poles themselves. These lights turn on at night time as the sun sets. They're not all that bright, which I suppose is to be expected for parking areas.

Parking structure viewed from the side and above. There are lights on the roof, but no cars. The big "Parking" sign is also visible.


Night time view of the roof with lights on. It's pretty empty up here.

Update:

Okay, now that I've written about it, I feel like I need to add rooftop cars. My hacky solution is to assign each parking structure a successive "city" index after all of the cities are added. Then I can add some special case logic to treat these roofs like a city with a single parking lot in a single block. It's messy and probably not very efficient, but it works. The existing lighting code happens to be correct as well, including the sun and moon shadows.

Parking structure, now with cars on the roof.

If you compare the images you can see that the lights have changed as well. They now have extra cubes at the bases. They're also now aligned to the rows of parking spaces, which means there are somewhat fewer lights than there used to be. I had to remove lights that were too close to the ramp to avoid blocking the paths of cars. I even modified the rooftop lights so that shadows are enabled and the cars now cast shadows. Of course it does hurt framerate somewhat to do this. At least they're static shadows.

Night time scene with shadow casting rooftop lights.

As usual, I'll probably improve and add to these building types after publishing this blog post. This happens with every new building type. There have been so many small additions that I'll never have the time to write about. Many of these changes are based on user feedback that I get from comments and emails.

Next on the list is factory conveyor belts. These are similar to escalators and moving walkways and should be a fun addition. It shouldn't take me very long to add them!

Sunday, May 11, 2025

Procedural Schools

I've been working on adding schools to 3DWorld's procedural cities on and off for a few months now. I started schools shortly after hospitals, and switched back and forth between working on the two building types. Hospitals got to a semi-finished state first, so I wrote a blog post on them last month. This post will be on the topic of procedural schools. I'm not quite done with schools at this point, but I'm starting to work on other unrelated topics. Maybe reader comments/feedback will give me some ideas on how to finish schools. I definitely got a lot of good feedback on hospitals last month.

As with the hospitals post, I'll describe each new type of room and show at least one screenshot for each of them. Technically, none of the room types is really new, but they're all at least somewhat customized for schools.

School buildings are of the taller and blocky "city" form rather than the strip mall-like one or two floor schools that seem to be more common in areas with more land. I tried my best to fit them into my standard office building templates with a central hallway and optional secondary hallways, with possible vertical stacked parts of progressively smaller footprints. This leads to most of the rooms having similar sizes, which isn't ideal, but I'll try to work with that. I ran into that same limitation with hospitals. Maybe sometime I'll find a better system to create buildings with larger and more complex footprints. I could use that for malls and factories as well.

Classrooms

I actually added classrooms to both schools and hospitals, though they're much more common in schools. In fact most of the rooms in schools are assigned as classrooms. I feel like the classroom discussion belongs in the schools post rather than the hospitals post, so I held off on writing about them until now.

Classrooms have a few requirements. First, there is a minimum room size required to fit at least 3x3 student desks. In order to guarantee most rooms are large enough to be classrooms, I modified the hallway and room generation logic in the office building floor planning step to create fewer larger rooms. One component of this was to increase the threshold or building size needed for adding secondary hallways. Classrooms must also have at least one exterior wall with a window, and no stairs, elevators, or exterior doors.

Most of the space in classrooms is filled with a 2D grid of smaller student desks with chairs, placed in multiple rows and columns as space allows. I copied and customized the code that I used to place rows of shelves in retail rooms. Any desks that are too close to a door or other object are omitted. The placement logic is relatively simple compared to some other room types because I don't need to worry about things like exterior doors, stairs, and elevators. A random assortment of books, papers, pens, and pencils is placed on top of these desks.

A teacher desk is placed against a wall, with preference for the long side of the room and interior walls with no windows. This desk has drawers and the top surface can have papers and an optional cup, which contains coffee 50% of the time. If the wall is windowless, a chalkboard/blackboard is added behind the teacher's desk and covers most of the wall. I'm going to refer to it as a blackboard because I've made them all black rather than dark green. Plus it seems to fit better with "whiteboard" used in offices. I then added an American flag to one side of the blackboard and an analog clock to the other. To finish the room off, I placed a few other objects such as plants, paper and trash on the floor, and room number signs outside the door.

A school classroom with student desks and a teacher's desk and chalkboard in front.

Here's a larger classroom with darker chair colors. The screenshot was taken from inside the doorway to the room, which is why there are no desks or chairs in the foreground.


A second classroom with darker chairs.

Oh! I also changed the titles of most of the books found in schools to match a selection of real school subjects. The list I came up with is: Math, Mathematics, Algebra, Geometry, Trigonometry, Calculus, Science, Biology, Chemistry, Physics, Economics, Computer Science, English, Literature, Language Arts, Social Studies, History, Geography, Government, Sociology, and Visual Arts. Some of these have "I" or "II" suffixes. Unfortunately, I haven't yet found a way to make the subjects match the images placed on the book covers. The textbook subjects found in each classroom are random as well, rather than matching the subject taught in the room.

A student desk with a calculus book ... that has a picture of a museum dinosaur exhibit on it? What does that have to do with calculus?
 

Blackboards come with chalk and erasers that the player can use to draw on them. I was thinking of adding some existing text and drawings on the boards, but I don't know where to get the images from. Drawing text with normal font doesn't look correct; I need something handwritten. Most of the images I saw in Google image search are artistic drawings rather than something you would find in schools. I was only able to find one image of some math that was high resolution, free, not watermarked, and the correct color and aspect ratio. It's clipped at the edges, but otherwise looks okay. This image is added to the blackboards of 25% of classrooms. If I find more useful images I'll add them later. Sadly, erasers held by the player don't work on these images.

Blackboard with some math writing that's somewhat stretched and clipped.

Hallway Lockers

Most larger building types have hallways, but only schools have lockers placed in these hallways. I added rows of lockers to each side of the primary hallway on each floor, wherever there was space. There are gaps in the rows where doors or other objects such as water fountains and fire extinguishers block their placement. Each school building part chooses a random locker color from a selection of light/bright colors. Some lockers have padlocks added to them.

School hallways also have a random chance of papers and trash on the floor. Otherwise, they're similar to office buildings with restrooms, water fountains, fire extinguishers, and trashcans on each floor.

A shorter school hallway with blue lockers and stairs. There is some paper trash visible in the bottom center.

Some of the larger schools have hundreds of lockers lining the hallway. This is probably too many given the number of desks in the classrooms, but it's fine for now. I'm sure some schools have too few lockers as well.

A longer school hallway with red lockers, elevators, and intersecting hallways. There are a few papers on the floor in the back.

The player can open the lockers without padlocks, and of course they contain items. All locker interiors have a larger bottom section and a smaller top section. Both shelves can have stacks of textbooks. Smaller objects such as cell phones, paper balls, bottles, and cans are placed on these books or on the empty shelf. Some lockers have papers attached to the inside of their doors. The larger bottom shelf also has a chance of a hanging colored tee shirt (which is a bit undersized, so I had to add it at an angle).

A school building with light brown lockers. I've opened the ones that aren't locked with a padlock.

Cafeterias

I added a cafeteria to some schools, though it's generally not large enough to fit many students. The minimum size is set so that there are at least three rows of tables. Each row has either a single long table or two shorter tables with an aisle in between. Most building floorplans contain similar sized rooms, which is a limitation. Maybe I should remove walls and merge two or more adjacent rooms into a single larger room? That way it could be used for cafeterias, auditoriums, gyms, etc. Of course I would probably need to increase the ceiling height of these rooms as well. None of this is particularly easy given the way the floor planning code is written and the fact that room assignment is run at a later time when it's too late to change walls or doors.

Cafeterias are similar to mall food courts and use the same table and chair geometry. The main difference is that cafeteria tables tend to be longer than mall tables. Various food, drink, and school items are placed on these tables. This includes cans, bottles, cups, pizza boxes, bananas, plates, silverware, vases, books, and laptops. There's also a clock on the wall. Now that I'm writing this, I think I'll add larger cylindrical trashcans to the corners of the cafeteria.

Cafeterias always have some type of tile floor texture that's easier to clean than carpeting. The rest of the school has randomly either carpeted or tile floor.

A school cafeteria with tables and orange chairs. Yes, that's a can of beer on the left table. You shouldn't be surprised, considering I had beer in hospital rooms as well (see the previous blog post).

Teacher Lounges

Teacher lounges are basically the same as the lounges found in some office buildings. They have a central table with chairs, one or more couches, and optionally a refrigerator, a vending machine, and a wall mounted TV. Here we have the opposite problem to cafeterias: The rooms are too large. I should probably add more items to make use of the extra space. Or maybe place teacher lounges next to cafeterias and move the wall so that half the lounge size is added to the cafeteria? This won't work in general though because there are multiple teacher lounges and only one cafeteria.

Teacher lounge with couch, tables, chairs, bookcase, vending machine, refrigerator, and wall TV.

Libraries

The final room type I've added to schools is libraries. Well, that's not really true. Schools have restrooms, offices, utility rooms, and server rooms as well. What I really meant to say is the final school-specific room type is libraries. Except that some office buildings have libraries as well. Anyway, this is the final type I'm going to discuss in the current post.

Libraries have the expected stacks of books in the form of bookcases against the walls. They also have  normal office furniture such as desks, tables, chairs, and filing cabinets. Sometimes they're small, such as the library in the screenshot below. I'm adding libraries last since they're optional, so they only get assigned to rooms that haven't been set to some other purpose. This means that they don't have much selection based on room size, and some smaller schools have no libraries.

A small school library with bookcases, desks, a computer, and a filing cabinet.

That's as far as I've gotten with schools. There are still some room types that I want to add later, especially if I can get more control over room size and height. It would be nice if I could find a way to add procedural writing on blackboards as well.

The code can be found in my GitHub repo here.

Friday, April 18, 2025

Procedural Hospitals

The next types of procedural buildings on my list after malls, factories, and warehouses are hospitals and schools. I've been working on both of these together, but hospitals were started first and are further along than schools. I'll discuss hospitals in this post and probably get to schools in the next one.

Hospital Exteriors 

My very first addition to hospitals for this round was to add illuminated red crosses to either side of the lit signs on top of city hospital buildings. These use the existing text rendering system with a single "+" character. This is a good start, though it's a minor change that only works in cities and is only really visible at night time.

Night time hospital with emissive green name sign and red crosses to the sides.

Hospital Interiors

The next step was to add ambulances to hospital parking garages. Technically, this isn't the next task I worked on, but it was one of the earlier additions that was completed by the time I started writing this post. Ambulances don't normally fit inside parking garages because they're too tall and may intersect the pipes that run along the ceiling. I had to cheat and shrink them by 20% (compared to ambulances found above ground) so that they fit. It's not too obvious that this shrink was applied. I wonder if I can get away with using this same approach to squeeze a school bus into a school parking garage? Probably not!

Hospital underground parking garage with some slightly smaller than normal ambulances.

With those two minor changes out of the way, it was time to work on hospital interiors. Non-city hospitals are only assigned to larger cube-based buildings where the ground floor part is large enough to add primary and secondary hallways. This allows the existing secondary and ring hallway floorplan templates to be used, with various rooms placed along the hallways. The resulting rooms have relatively consistent sizes that work well for hospital room types.

The only major difference to the hallways themselves is the addition of a reception desk at one end of the primary hallway on each floor, rather than at both ends of the hallway on the ground floor only. These can serve as nurse desks or similar. All of the normal hallway items still apply: water fountains, fire extinguishers, clocks, and US flags.

The major difference between hospitals and office buildings is the assignment of room types. While hospitals can have some office rooms, the majority of rooms are related to hospital services. So far I've added recovery rooms for one or multiple patients, exam rooms, waiting rooms, operating rooms, and classrooms. Each of these contains a different set of placed object types with some amount of overlap.

Patient Rooms

Most rooms along the building exterior that have windows and a single door are reserved for patients. These have one or more hospital beds selected from one of three new 3D models, which are randomly selected per hospital part. The number of beds is a function of room size to best utilize the available space. Rooms that have multiple beds along a single wall have curtains separating the beds. TVs are placed on the walls opposite beds where there's space, and if their line of sight isn't blocked. I also added a variety of other items to hospital rooms including tables with flowers and telephones on them, chairs, couches, potted plants, and the new wheelchair 3D model. Chairs come in several existing varieties: wooden house chairs, plastic office chairs, and occasional rocking chairs. At this time the beds are all empty because I don't have any models of people with a lying down animation.

Here are some example hospital rooms. I've enabled indirect lighting in all screenshots, so they're quite bright inside.

Hospital patient room with three beds separated by curtains, a table, couch, chairs, and wheelchair.
 

Another hospital room with beds, curtains, table with plant, and rocking chair.

Hospital room with a different style of bed, couch, and TVs on the wall.

Very bright hospital room that's long and thin with a third bed type.

Just for fun, I made hospital beds slightly under the max player carry limit. This means that you can pick one up if your inventory is otherwise empty, but you'll be at max carry capacity and extra slow. It makes more sense to move the beds around by pushing and pulling if they get in the way. Their wheels make them movable by the player.

If the room is large enough, it also includes a private bathroom in the corner to one side of the entrance door. Once again I've reused the nested sub-room system from factories and warehouses. The bathroom has a separate light, toilet, sink, and mirror. The placement system ensures both the main room door and the bathroom door are not blocked by anything. Bathrooms are added at the floorplanning step since they require adding walls, which means that patient rooms are selected before the main room assignment pass. This complicates later placement steps as it requires shuffling room types around if stairs are added later or a bed can't be fit in the room.

Hospital patient room private bathroom, added as a nested sub-room in the corner by the door.

Waiting Rooms 

Waiting rooms were the next to be added, since they contain mostly existing objects. The interior walls of the room are lined with rows of chairs and one or two couches. If the room is large enough, an additional one or two rows of chairs are placed against a short wall in the center. I also put a TV on the wall, and either a bookcase with reading books or a vending machine in a corner of the room. Finally, I added either a digital or analog clock on the wall that dynamically updates to show the true time.

Vending machines are a new type of interactive object. These have been placed in office building and hotel lounges and lobbies as well. There are two types of vending machines with different exterior textures, one serving bottled drinks and the other serving snacks such as chips and candy bars. I got the textures, stats, and item lists for both of these from online vending machine ads. I was surprised at the typical cost: $8000 for refrigerated vending machines and $6000 for non-refrigerated ones! Of course the player could steal these for that value, if only they weren't several times over the player carrying capacity.

Vending machines are interactive. They have a fixed number of random items (0-9) that can be purchased for $2 each. Where does the player get $2 from? You have to steal it from somewhere else in the building. Drink vending machines give random drink consumables that have various effects on the player: water, Coke, beer, and wine. Yes, $2 alcohol from vending machines! In hospitals! The first two drinks heal the player and the second two make the player drunk. And if the player doesn't need a heal, that's $2 wasted. Being slightly drunk is a good thing because it increases damage resistance, but being too drunk causes visual artifacts and can eventually kill the player. Snack machines produce a variety of items that heal a small amount of health. I don't know how practical these vending machines are, but they were a lot of fun to add.

I also changed the set of random items the player can loot by breaking into parked cars so that some of them have effects such as healing. Maybe it's too easy to get healed now? Most of my time playing I'm either at full health or dead though, so it may not matter all that much.

Waiting rooms are more commonly placed on ground floors, but can appear at any floor. Rooms that would normally be assigned to patient rooms are re-assigned to waiting rooms if stairs or elevators are added to them later during the "connect" step. However, these rooms may already have nested bathrooms. That works out fine though because these can be repurposed as waiting room bathrooms. Or maybe they're intended for sample collection for lab work? I do need to check for bathroom intersections when placing other room objects.

Here are some waiting rooms that I've come across in the hospital closest to the starting area. 

Hospital waiting room with gray chairs and couch, a TV on the wall, and a bookcase in the corner by the elevator cutout. (The elevator opens to the hallway outside the room.)

Another waiting room with a drink vending machine and stairs going up on the right side. This one has a private bathroom as well.

A very small waiting room with a single couch, at the top of the stairs shown in the previous screenshot. This one has a snack vending machine and an analog clock.

Exam Rooms 

Exam rooms were next. I felt like I already had enough hospital bed 3D models, so I used a random existing bed model rather than adding yet another exam bed model. I placed a doctor's desk with computer, monitor, and phone in the room. Then I added an optional computer monitor on the wall, an optional first aid kit, an optional wheelchair, a filing cabinet, a chair, and a stool. I added either a simple sink or full bathroom vanity with doors/drawers full of items.

Hospital exam room that's probably too large, with bed, desk, sink (behind the bed), wall monitor, first aid kit, and filing cabinet.
 

Ah, that's right, vanities are new as well. I started by adding these to house bathrooms. They're basically the same as kitchen cabinets + sinks, except they're white rather than brown wood and contain a different set of items. They also have mirrors that open, similar to bathroom medicine cabinets. At the moment exam room vanities have the same items found in house bathroom vanities. That will likely change later.

Vanity model used as a hospital exam room sink and cabinet. Those are definitely not cans of beer inside the open door.

All right, I changed them to contain bottles of medicine rather than other types of cans and bottles. But I'm not going to capture a new screenshot for this post.

Hospitals sure contain a lot of medicine bottles. Right now medicine fully heals the player, including the effects of snake and spider venom. Maybe I should add different types of medicines that have different effects? Some of them can be bad for the player, just to make things interesting. Or I can add a time limit to prevent players from using medicine too frequently. Maybe there's a message "can't take more than one dose of medicine in the same minute" or a negative effect on the player.

I feel like I should add some other equipment such as a blood pressure cuff. The problem is that I don't want to fill hospitals with a large number of unique models as that hurts both load time and framerate. A second problem is that these rooms are too large for exam rooms. This particular hospital with secondary hallways has a main floorplan where all the rooms are the same relatively large size, so I can't do much about the wasted space. Ring hallways have a greater variety of room sizes that produce more interesting room layouts.

Operating Rooms 

Operating rooms were added last, mostly because I had a hard time deciding what to add to them. I started with a hospital bed 3D model (again), but eventually replaced it with an operating table. I changed the ceiling lights to be round, larger, and brighter. I added the 3D model of what is apparently called a "trolley" - the metal wheeled cart that holds the operating instruments. I added one or two machines along the walls or in the corner of the room. These are the same machines I previously added to extended basements and factories. They seem to fit with the strange equipment likely to be seen in operating rooms. I also attempted to place a metal chemical/gas tank along the wall, using the same tank object as factories. I placed a clock on one of the walls. Finally, I added another optional wheelchair. It's a nice looking model, so it may as well go into every hospital room type.

Operating room with large and very bright lights, an operating table, some machines, a trolley, and a wheelchair.
 

Another operating room. This one is larger and has a chemical tank along the far wall.
 

There's a good chance that I'll go back to improve operating rooms in the future. I think there's a lot of potential, especially if I can work them into the gameplay somehow. Maybe the player can strap zombies onto operating tables? Maybe the player can use a scalpel as a weapon?

Classrooms 

Finally, there are classrooms. I actually copied these from schools, so I won't show classrooms until the procedural schools post. I suppose these are for training of student doctors, health related classes for the public, and that sort of thing.

Hospitals occasionally contain conference rooms that are assigned during the floorplan stage. These are left over from the office building logic and seem okay to allow. And of course there are standard bathrooms with stalls. Whatever rooms remain that are too small to fit beds, etc. can be made into offices, storage, or utility rooms.