I was originally planning to work on indirect lighting for building interiors next. This turned out to be a very difficult and time consuming project, and I don't have too much to show for this yet because it's still incomplete. My next post will likely be on the topic of indirect lighting. Somewhere in the middle of that my development was interrupted by someone suggesting I add attics to houses. That's a great idea!
Problem Statement
Of course attics were also quite complex and time consuming to add. I would say about as much work as house basements or office building parking garages. This was primarily due to two reasons: First, attics aren't cube-shaped rooms, they have sloped roof polygons rather than vertical walls and horizontal/parallel ceilings. None of my existing code worked in this case, including object placement, wall decorations, lighting, player collision, and people/rat/spider AI updates. I basically had to special case all of this code to handle attics. Then I had to write custom sphere/ray/cube intersection code to handle roof polygons, which required many debug iterations.
Second, I wanted to add attics without modifying any of the existing interior or exterior geometry. I can't be going back and reworking every system each time I add a new building feature. This means that attics must connect to existing rooms without moving walls and light fixtures. They must handle things like chimneys crossing through them. They can't break the existing people, rat, or spider movement systems. And, by far the most difficult, they must work with multiple sections of roof intersecting at odd angles.
Adding attics introduced a lot of new complexity, but at least I didn't have to deal with windows and doors. I'm sure it's possible to go back and add skylights and ventilation to attics later if I'm up for the challenge.
Attic Roofs
This last case can come up in L-shaped houses that have both cube sections at the same height, such that the roofs of the two parts intersect each other. According to this diagram, these would be the "crossed gable" and "cross hipped" roof types. Up until now the player was not allowed inside the roof area, so all of the polygons clipping through each other weren't visible. But now that I want to make this part of the attic interior, this has to be dealt with somehow. At first I added special cases to skip adding attics to this type of house. Later I got back to working on this and wrote the code to clip roof polygons (triangles and convex quads) to the other existing roof polygons. It wasn't as bad as I thought, and worked pretty well. I still wasn't sure what to do with an L-shaped area and how exactly to add objects such as wood beams in the roof. In the end I added vertical walls to split the area into two separate cubes, and made the larger one the attic.
Now that I think of it, I can probably go back and simplify all of the rooftop solar panel placement logic. The existing system goes through a lot of trouble to detect if a roof polygon clips through another polygon to avoid placing a solar panel on it that intersects other geometry. Maybe this code is no longer needed since polygons no longer intersect? I may be able to simplify roof power line connection logic as well.
Another issue that came up was attics where the ceiling was too low for the player to stand. Depending on how I implemented the collision detection, either the player's head would stick out of the roof, or they couldn't enter the attic. Neither of these is acceptable. My initial thought was to skip adding an attic in this case, but this didn't work because attics were added before the roof. I didn't want to reorder the steps because this would break that "without modifying existing geometry" rule above. So instead I set a min roof height for the part containing the attic to ensure the player could stand inside it. This mostly worked, but generated comically tall and narrow roofs for some thin house sections. I had to go back and skip adding attics to house parts that were too narrow. I don't like this complex chain of logic that was needed, but I'm not sure how else it could have been done.
Small attic with two lights and an open door with a ladder extending down into a dark room below. |
Attic Access Doors and Ladders
Attics are accessed by a door that pulls down from the ceiling with a folding wooden ladder. This is how the attic is accessed in most of the houses I've lived in. I placed the door in one of the larger rooms near the center of the house, in the ceiling of the topmost floor. If the house contained a hallway in the correct location then I used that as the access room. I put it off to the side of the center of the room to avoid blocking the room light and the path through the room (in the case of hallways), but not so far to the side that it blocks doors. There's an extra check for clearance in front of the door in both the floor below and the attic above to make sure the player has enough space to enter and leave at both ends.
The folding ladder activated with the player's interact key and only draw when extended down to the floor. It's very steep, near vertical, and doesn't work well as stairs. I made it function as a ramp instead, using the same code as parking garage ramps. I wanted to make the player climb the ladder slowly, so I decreased player movement speed to only 20% when on the ladder. This partially accounts for the fact that zombies can't yet climb attic ladders. This slow movement makes ladders more risky, because zombies can get you when you're climbing and will sometimes wait for you at the bottom of the ladder. The attic isn't supposed to be a safe hiding spot. Of course it's also possible to jump down from the attic on the opposite of the opening from the ladder and land in the room below quickly.
Attic access door and extended ladder in the hallway of a house shown with indirect lighting. |
Attic Lighting
Lighting works differently in attics. I don't have a flat ceiling to add a standard rectangular or flat cylindrical light to, so instead I hung spherical lights from the center ceiling beam. Shorter/square attics have a single large light, while longer attics have two lights, one near each end. Attics will be full of random large objects, which creates many shadows. In addition, the light radius and field of view aren't large enough to reach into the corners. I increased the indirect lighting contribution in attics to make objects further from the lights actually visible. I still get nice dark areas in the occluded corners behind larger objects and brighter spots in front of objects, which can be seen in the various screenshots in this post. While this high level of indirect lighting is better for taking screenshots, I may reduce the indirect lighting later because I rather like the creepy dark corners of the attics.
I said earlier that I still haven't completed indirect lighting. At this point it's mostly a problem with performance vs. noise. I can't get low noise with good CPU compute time for volumetric indirect lighting. However, attics are a bit easier since they're one room with only 1-2 lights. I can increase the number of simulated rays and get results in reasonable runtime with acceptable noise. So I've enabled indirect lighting for attics, since I feel it improves the look quite a bit compared to using a constant ambient lighting term. I'll likely get into more detail on this topic in a future post.
Long attic under a gabled roof with a rug in the distance and many objects scattered about. A rat can be seen on the attic floor. |
Object Placement
Next I'll discuss object placement. Most attics that I've seen are full of complex wood beams that hold up the roof. I'm not sure what the correct term for these different parts are, so I'll just refer to them as "woodwork". I suppose the beams that run along the bottom of the roof are rafters, but what are the beams that run along the roof line and the vertical posts called? And what about those horizontal support beams that form a sort of A-frame shape? Whatever these are called, I looked at some reference images of attic interiors and tried to add all of the woodwork. There are two code templates I used, one for peaked/gable roofs and the other for hipped roofs due to the difference in the way the roof polygons are placed. In some cases one or more sides has part of a vertical wall, which I also treat as a "roof polygon". All of these beams start as a cube that's rotated into the proper orientation using lots of complex math involving cross products and trigonometry. It took me many hours to get this right. Since the ends of the beams aren't properly mitered, they don't quite meet exactly and have small gaps and intersections. I did my best to try and hide this with small translates and other geometry. I'm not sure how practical it is to calculate the correct faces/angles for every beam, and if I'll ever have the time and patience for that. It works well enough for now. A lot of that will be hidden in shadow in the final attic anyway.
I would love to have spiders crawling around on the rafters and other beams. So far I haven't figured out quite how to make this happen, given how complex all of the surfaces are. My existing solution based on object building cubes won't work here. In fact the rafters aren't even real collision objects, they're drawn as part of the roof when the player is in the building. Only the vertical posts that the player can run into are real objects. At least I can put spiders and rats on the floor and have them run around among the boxes and other objects.
Attics work as storage rooms, but I can't quite reuse the existing storage room placement logic because of the various differences in the shape of the room and the types of objects to be placed. For sure there are tons of boxes and crates to add. Small furniture and appliances such as lamps, nightstands, and chairs will work for attics. In addition, I can scatter balls, paint cans, books, and various other smaller objects across the floor and on top of larger placed objects. (I was thinking of adding something larger such as a dresser, but that currently can't fit through the opening for the attic door. I'm not sure how someone would get it up the narrow attic ladder either.) The more cluttered the better, as long as the player is able to pick up and/or move these objects to clear a path to walk. It might be nice to add some unique items that are only found in attics such as kid's toys. It would be neat to have a rocking chair or horse that the player can push to make it rock back and forth.I'll have to see what free 3D models I can find online.
Attic with an open access door, a chimney passing through it in the back right, and indirect lighting casting soft shadows. |
Furnaces
I've also added furnaces to some attics. Furnaces were another side project for me. I've had them on my to-do list for a while, ever since I added vents to office buildings. I started with adding furnaces to houses because at least I know what they should look like from experience. The houses I've lived in have mostly had their furnaces in the basements or attics. The house I currently live in has the furnace in a small room off the central hallway, but I don't think that's as common. For 3DWorld, I added the furnace in the same room as the water heater if the house has a basement. Otherwise, I add it in the attic if there is one. I couldn't find a good 3D model, so I took a picture of my furnace, did a poor job of editing it and trying to fix the slight rotation, and slapped that on as a texture. I couldn't get a picture from the optimal angle and the lighting wasn't great. The various pipes that come out the front aren't properly 3D, but it works well enough. It's obviously a furnace. I'll need to add all of the duct-work and actual pipe geometry later. That should add a lot of more clutter to the attic, though I need to be careful that it doesn't block the player's path too much since these objects won't be movable by the player.
House basements now have gas lines that connect to the stove, water heater, and fireplace. I've made gas lines connect to furnaces above the basement as well. However, the only case where a furnace is above the basement is when it's in the attic, and that only happens when there's no basement to put it in, so the pipes won't be visible anyway. I'm sure I'll get back to this at some point. One possibility is to make the furnace placement random when the house has both a basement and an attic.
Attic under a hipped roof with a furnace in the back left. |