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.
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.
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.
Welcome back! Have you seen the Vuntra City procedural project? It looks like it is taking some inspiration from 3D World, though that may be coincidental. https://www.youtube.com/@VuntraCity
ReplyDeleteShe is working more on NPCs right now (as one would expect from a woman) and doesn't seem to have as much infrastructure and utility spaces (again, in keeping with gender norms). You should reach out and help develop the game!
Yes,
DeleteI've been following Vuntra City for several months now. I was a dev tester for one of the builds awhile back. I don't think Lara was aware of my project or has any interest in it. The two were developed independently, though I did borrow a few of her ideas such as the ambient occlusion shadows of furniture.
Our two projects have very different goals. She's more interested in making a game with gameplay that everyone can run. I'm more interested in the technical details and getting everything right, as you would expect from a "pure engineer". I've played Vuntra city and it's about as buggy as 3DWorld. It's playable but you can get stuck and it has some "interesting" physics. Hers definitely looks nicer than mine, though the floorplans are less realistic.
I feel like playing (or at least watching some playthroughs) of Prison Architect would be helpful for this post. Have you played it? The idea of "corner cells" isn't really a thing, for example, as it is not very extendable, in case the prison is built out more. That's one interesting aspect of your system, that all of the buildings are designed complete, instead of being built in pieces, starting small and adding additions over time.
ReplyDeleteThe other thing is the amount of support areas, mainly commercial kitchens. There are also commonly some work areas, which you might be able to pull in from the industrial building types?
I've never played Prison Architect, though I'm familiar with the game and have watched videos of others playing. All of 3DWorld's buildings are generated from the outside in with a fixed set of steps: exteriors by joining together rectangles horizontally and vertically, adding walls to divide into rooms, dividing those rooms into sub-rooms, assigning room types, placing objects and furniture. It wasn't meant to be extendable.
DeleteI'm sure my prisons have too many cells compared to other rooms. The main goal was to add different room types rather than buildings that have a lot of room overlap with other types of buildings. I'm missing commercial kitchens in other building types as well such as schools, hospitals, and mall food courts. The difficulty with kitchens is that they have a large number of unique item types that aren't found in other rooms and are difficult to create. It's a lot of work for one room type. It's the same problem as something like operating rooms, which I'm not too happy with.
I wonder if we could procgen a bunch of those unique items in kitchens and operating rooms from primitives, instead of a bunch of unique meshes. Maybe after your new reflective metallic shader is working, and just make everything stainless steel.
DeleteI already generate and then draw instanced copies of some objects such as spiders and trees. The downside is that this is more draw calls because it can't be batched into the group of objects that share the material across the entire building. I don't think this is a problem with kitchens though since they're rare compared to other room types. It's just a lot of work to create (or find) all of those objects.
DeleteWhen the stair placement fails, what about swapping out one of the cells for stairs instead? That way you don't need the hallway to change, and you could even have multiple staircases for fire exiting. I know in a lot of long narrow buildings the stairs are at the ends of halls and corners of buildings, right next to the exterior doors, so you can get to other floors without walking through the interior hallways.
ReplyDeleteI did try that. The problem is that some of the cell bounds are too small to add stairs with entrances on each end. The walls between cells are actually placed first, so I would have to remove them. I do have a system for this. It just seemed simpler to widen the hallways. The exterior door, however, does fit in a cell.
DeleteIf I placed stairs first then I would have to consider then in the floorplanning step, which would make a lot of non-rectangular areas with corners cut out of the building parts. The old system didn't support this, it only worked on rectangles.
Some buildings have multiple stairs when they can fit. Stairs are added to at least one part, but as many as every part (up to 4).
I like the entrance room. Seems like it could use a desk and water cooler for the guard on duty? The cell next to this entrance room could be the stairwell.
ReplyDeleteI'm not sure if there's room for a desk. I'll have to look into that. There should at least be something in this room. Thanks for the suggestion.
DeleteNeat new Rounded Rectangle object type! You could probably use this to make procedural cars as well! Maybe whole buildings? Machines? Swimming pools?
ReplyDeleteRounded rectangles are only drawn shapes. Larger items such as cars and pools would probably need at least proper round rectangle collision detection, which would be more work. I'll have to see if I can make this work with pools. If the radius is small I can probably use a bounding box. Machines are mostly textured, and I haven't yet figured out how to texture these shapes.
DeleteYour corded phone model looks fairly similar to this one:
ReplyDeletehttps://sketchfab.com/3d-models/nortel-vista-200-corded-landline-telephone-aa47a7474cdd4e1cbf21b2ceceeabf47
though that's a 3D scan, and doesn't have very clean topology.
I found this one, but the cord has so many polygons!
https://sketchfab.com/3d-models/corded-public-phone-low-poly-63ef9397e3b9418e8abfba9cc4c470a8
So I stripped it down and made a version with buttons:
https://skfb.ly/pAxYn
And a version with no buttons, which is probably the one you want:
https://skfb.ly/pAxY7
You might be able to strip out the mesh info for the buttons at runtime, but the extra 500 polygon model might be worth it. You decide. Enjoy!
Ooh, You could just load the no-buttons version, and then procgen the buttons where you want them! Good use for the new rounded-rectangle primitive, assuming you can get the number texture to render on it properly.
DeleteIt's this model: https://sketchfab.com/3d-models/landline-phone-85d3fe01f51642d6b3130e602d6633fa
DeleteThe locations of most of the recent models can be found here: https://github.com/fegennari/3DWorld/blob/master/image_and_model_credits.txt
So you made a corded phone without the cord?! I'll take a look later. Thanks. If I had a model where the buttons were a separate material I could conditionally draw it.
I would probably just make the buttons squares to improve performance. If I generate them they won't be instanced. It's much less work to just use a 3D model someone else created for details like this.
Yes, this one has separate materials for the buttons, handset, base, and hook. So you could split the model up at runtime and controll all the parts parametrically:
Deletehttps://skfb.ly/pAxYn
Maybe even add a procedurally animated cord!
It seems like the correct solution for the visitation room pathfinding is to split it into two rooms.
ReplyDeleteThat's a good idea. The only problem is that the rooms are added first and then assigned later. I can't easily go back and add a new room after assigning an existing room to visitation. I mean I can, but I would have to go back and update all of the other variables referencing rooms by index such as the doors. Really it's only the path finding that needs to treat the room as two separate graph nodes. That's probably easier to change.
DeleteNo jumpsuit model on a hanger? Got you covered!
ReplyDeletehttps://skfb.ly/pAynE
Thanks!
DeleteShower rooms look nice. We had communal showers in college, and I've done plumbing design on some group showers in other schools. Usually there's a seperate toweling area for drying off, but that might not exist in prisons.
ReplyDeleteDo the rats climb in and out of the floor drains?
Maybe I can add another area with benches and lockers.
DeleteNo, rats only walk around on the floors. They can go though the cell bars though. I'm sure I could make them come out of the drains if I worked on that.
Looking forward to seeing the metallic reflection cube map!
ReplyDeleteIt's going to be difficult. I already have the cube map code from other experiments that I can reuse. The problem is where to create the cube map from. If I put it in the center of the room it may clip through something like the visitation room window. If I make it follow the player then I have to regenerate it each frame the player moves, which would be slow.
Delete