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!