Thursday, June 23, 2022

Attics for Houses

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.

5 comments:

  1. This turned out really nicely! I love how you're spending loads of effort and time to implement things like this -- that's a process near and dear to my heart :-)

    ReplyDelete
  2. The woodwork is called trusses.
    My SketchFab has some kid toys and a rocking chair you can download for free as obj files. Attics are pretty tricky, impressive that you got it to work!

    ReplyDelete
    Replies
    1. I've never heard the term trusses for those parts. What's the difference between trusses and rafters, or are they the same thing?

      I'll check your object models. Thanks!

      Delete
    2. The rafters are the angled parts that support the roof.
      https://www.google.com/search?q=parts+of+roof+trusses&tbm=isch

      Here's the glider rocking chair: https://sketchfab.com/3d-models/glider-rocking-chair-8fdfc3c29a93459784a4ef5facec4b69
      And a baby toy: https://sketchfab.com/3d-models/baby-stacking-toy-1baa4c07e1e64798bbe7925cbbdd6a74

      Also, here's a pretty cool city generator tool that just came out for Blender. Might give you some ideas: https://paveloliva.gumroad.com/l/buildify

      Delete
    3. Oh, that's a nice figure showing all the parts of the interior roof. I didn't think to look for something like that. So the truss is the entire structure? I never realized there were so many parts! I don't have to label these in the code, but it makes it easier to discuss it with other people who are familiar with those terms.

      The glider rocking chair may be something I can use in certain house rooms and possibly the attic. Thanks. The ring tower toy may be more efficient to construct from a stack of tori and a cylinder so that LOD can work and the geometry can be merged across materials.

      The Blender city generator looks very nice! It definitely has more exterior detail that I've added to my buildings, though I'm not sure how well it will scale to drawing thousands of buildings on the screen. Also, is it limited to vertically extruded commercial buildings with flat roofs, or is that simply a limitation of the default assets it comes with?

      I've seen lots of different building generators, but most of them are for generating static exterior props. Very few include interiors (and lights), generate an infinite world full of buildings, have objects that can be moved, or can be navigated by game AI.

      Delete