Thursday, July 21, 2022

Building Furnaces, Vents, and Ducts

This is a follow-up post to my previous one on house attics. After I had written the initial code to populate attics with random items, I decided that I was missing air ducts. I already had furnaces in some attics, and I already wrote a system for placing a network of pipes. Surely it won't be too difficult to add ducts next, right?

I started by adding vents to the ceilings of most of the rooms in houses using code modified from what I wrote to add vents to the walls of office buildings. It's actually easier because I only have to avoid ceiling lights, stairwells, and attic doors, which are the only objects currently placed on ceilings. This means it's almost always possible to place a valid ceiling vent. For now I'm only attempting to connect vents on the topmost floor (below the attic) with ducts, and only when there's a furnace in the attic. The ground floor could probably have vents in the floors instead and air ducts in the basement or crawlspace. I'm not sure how to handle middle floors since I haven't lived in a house like this that I could use as a reference. I suppose the ducts are in the walls or between the ceilings and floors in that case. Sadly, my walls and ceiling-floor gaps are currently too narrow to fit ducts. For now I left these vents unconnected.

I added an extra duct on top of the furnace for the air return, and routed that down around the back to a larger intake vent on the ceiling under the furnace. Sometimes the furnace is too close to the attic roof and it won't fit. In this situation I omit the air return in the hope that the player doesn't notice. The intake vent wasn't always landing in a convenient location, so I changed the furnace placement to position it above a hallway or larger room with stairs and not above the ceiling light. This worked well because the furnace has no other placement constraints and can be put almost anywhere, as long as it's not too close to the edge of the attic and not blocking the attic access door.

I started with ducts that have rectangular cross sections as that seemed like it would be easier. Each section of duct is divided into an integer number of metal cubes with one tile of a texture applied to each face. This gives it the look of a modular air system. Here's an example attic.

Attic with wood panels and furnace next to open attic access door. This one has many air ducts but not many other objects.

It took me many attempts at placing ducts correctly and realistically. I settled on sorting vents from furthest to closest to the furnace to form the main routes first. Vents that happened to line up with the furnace were connected with straight segments. Otherwise, they were connected with an L-shaped connection consisting of a segment in X and a segment in Y that met at a right angle. There are two such possible segments, one starting in X and the other starting in Y. I chose a random one of these and selected the other orientation when the first one was invalid. Since attics are always rectangular, I don't have to worry about their routing going outside the attic. Therefore, the only constraint is that they don't intersect the wood vertical roof support pillars and don't block the attic access door/stairs. If the path of the duct intersects a previously placed duct, it's shortened and connected to that duct with a straight or T-joint. Then I also generate a straight segment to the nearest existing duct and use that instead if it's valid and the distance is less than the length of the original path to the furnace. Any vent that happens to intersect a previous duct when extended upward into the attic is directly joined to it.

That set of rules was able to successfully route about 90% of vents to the furnace. The remaining failures were cases where the vent was on the opposite side of the attic access door from the furnace and a single jog wouldn't work. I made many attempts to solve this. What I ended up doing was splitting up ducts that had been placed earlier into short segments and attempting to route the unconnected vent to the center of the closest segment with a pair of straight runs with a single jog. This is the same logic used to connect vents to the furnace. If the closest segment can't be connected to, then we look at the next closest segment, until the vent is connected or no segments are left. In theory this can still fail, in particular if all of the vents are across the attic access door from the furnace. However, I haven't been able to find a case like this after visiting dozens of attics. So I consider it solved. In the rare event I miss a vent it's not obvious anyway, unless the player clips through the floor to see that the vent is unconnected.

Boxes and other attic objects are placed after the ducts so that there are no intersections. I had to increase the number of objects in attics with furnaces and ducts to offset the loss of floor space for placing them.

I've also added different floor and ceiling surfaces for attics. Maybe that's a bit off topic for this post, but I may as well mention it since it's obvious from my screenshots. Floors can now be either wood planks or plywood. Ceilings can be wood planks, plywood, fiberglass insulation, or finished plaster. Here's an example of a cluttered attic with ducts and plywood on both the ceiling and floor.

Cluttered attic with plywood, furnace, and air ducts. Yes, the furnace is missing the air return duct on top because it's too close to the wall.

Here's another attic with that pink fluffy fiberglass insulation in the roof between the rafters. I couldn't find a seamless texture for fiberglass insulation. I even tried looking for cotton candy textures, but came up empty handed on that as well. None of the free textures I could find were seamless/tileable. In the end I generated a cloud texture in Gimp and tinted it pink. I suppose it looks good enough.

Attic with pink fiberglass insulation, furnace, and air ducts. Sigh, no air return again.

You can see in this screenshot that the main duct is wider than the smaller ducts connecting to it. This is in fact the result of multiple ducts routing to the same side of the furnace being merged and the max width used for the connection. It often happens to work out this way. It's also pretty common to have ducts coming from each side of the furnace and extending toward different sides of the attic.

When I was finished with rectangular ducts, I moved on to cylindrical ducts. These turned out to be much more difficult to join together. I was able to place rectangular metal boxes over the ceiling vents to make it easier to connect the ducts, but joining ducts together caused a lot of trouble. For example, two ducts running next to each other can't simply be merged the same way as cubes to form a wider duct. Instead, they must be shifted around so that either their ends meet exactly or they form a T-junction. Texture alignment generated additional complexity.

This attic has cylindrical ducts. I like the look of the rectangular ducts better.

I suppose this looks acceptable. I would have liked to use wider ducts for main branches with many vents along them, but I ran into problems with player collision detection when using cylinders of larger radius. I want to keep them small enough so that the player can step over them to make the attic open for exploration. I prefer the look of rectangular ducts, so I made cylindrical ducts appear in only 25% of attics even though I feel they're more common in real houses (including mine).

That looks good for houses. Now what about office buildings? It makes sense that the furnace(s) should go in the same utility rooms as the water heater(s) I added a few months ago. I don't think office buildings generally use the same small furnaces as houses, but I can still add some as temporary placeholders until I figure out how to include commercial HVAC systems. It's easy to add them, so why not?

Office building utility room with water heaters, sink, and now furnaces.

Of course now I need to find a way to connect these to wall vents in offices. Until I do so, the player will have to imagine there are ducts somewhere in the thin walls. This particular utility room annoys me though because there's a wall vent right next to the furnace, yet it's not connected! At the very least I should go back and connect that one, or possibly relocate it to the side of one of the ducts above a furnace.

I'm pretty happy with the current state of furnaces, vents, and ducts. I might go back and add floor vents with basement ducts sometime later.