Thursday, March 22, 2012

Building Rooms

There are many papers and demos about creating building volumes and their facades. There is not much about how to build their interiors. Today I want to share a simple technique I found. It allows to break a space into multiple rooms. This alone is not enough to build interesting interiors, but it can be successfully combined with halls, staircases and more dramatic spaces.

This is what we are going for:

The idea is to divide a space into rooms of random sizes. The rooms should be connected by doors. The outer walls should have windows.

As you will see, the real challenge is to make sure the doors and windows will appear in the right places. A door should not appear in the middle of a wall intersection. Windows must properly align with room sizes.

To show this technique I will use the L-System langue I have developed for Voxel Studio. I hope the code is simple enough to convey the idea behind it.

We will start by breaking the space into even rooms:

You can see the output of the "testrooms" module here:

It is a simple, neat idea. The "room" module will divide recursively while the room size remains bigger than 5 (meters). Once the room cannot be subdivided anymore, the third definition for "room" kicks in and instances some walls.

Let's add some variety. Instead of splitting rooms in half we can choose a more interesting ratio. We can also make the subdivision random. Rooms could stop dividing even if they were bigger than 5 meters, which will lead to bigger rooms:

Not much changed since the previous version. The key addition was a third constraint in the "room" rules, selecting the rule only if (rnd < 0.8). This means 20% of the time a room, no matter how big, could stop subdividing.

The results are already more interesting. Also, multiple runs of the "testrooms" module produce different layouts. Here is one example:

This looks close to what we wanted, it should be just adding doors to the inner walls and windows to the outer ones. Well, not so fast. While the rooms are properly identified, there is something going on with the walls. If we contract each room a little bit the problem becomes apparent:

As you can see, each room has its own set of four walls. When a large room appears besides a series of smaller rooms, we get a large wall running over the smaller walls. If we had doors there, they would be hidden behind the large wall.

The simplest solution would be just to hide the large wall when we detect it has been occluded by a smaller wall. This can be done by adding an "occlusion" conditional to the walls. 

Occlusion tests work by intersecting volumes. Even the slightest intersection will result in a positive occlusion. For this reason, we will shrink our wall occluders a little bit. This way wall intersections in the corners will not result in positive occlusion. We will not worry about the little gaps this will create for now.

Here is the modified code:

There are now two rules for the walls. One for a wall that is occluded, and a second for a wall that does not intersect any other wall. To spot which walls were occluded, I chose to render them as shorter, wider walls. They appear in red below:
As you can see, we could start punching door holes in the remaining walls and they would not be hidden by a parallel wall coming from a neighbor cell. Still, finding the proper location for these holes would be tricky. The hole must not appear in the intersection of two perpendicular walls.

Instead finding a solution for this, let's look closely at the walls marked in red. These were the walls  removed by the occlusion test. You will see they never intersect each other. We could open a hole anywhere in the wall and it would never be in front of another wall. What if we reverse our logic, that is, we hide the non occluded walls and use the occluded ones for our rooms?

The following code does that, it also adds a door opening in the middle of the walls:

Here is a render of the new rules:

You will notice the outer walls are gone. This is because they are not occluded. This actually helps, since we are adding windows there anyway. 

There is another advantage. Remember the gaps we had to create in the walls so they would not occlude by the corners? Only occluding walls need to leave gaps, and since now they are not even visible, the gaps are no longer a problem.

Let's add outer walls with some window openings:

The previous code adds a call to the "outerwalls" module, which will target the sides of the scope box and repeat a series of windows at constant intervals. You can see the results here:

The red arrow points to a new problem. Since the windows repeat regularly, they often appear in the middle of walls. The solution is to use "snap" planes. Snap planes, just like occlusion rules, are recurrent techniques in procedural architecture. A snap plane is an imaginary line that influences the subdivision and repetition of modules. 

We can make the repeating windows snap to the walls. This way they will still repeat, but the repetition intervals will be constrained by the snap lines.

This is how you would specify them:

The lines that matter are highlighted in red. Starting at the bottom, the "snap" statement declares a new snap plane and names it "wall". Then the repeat statement includes the "wall" snap plane. It means it will repeat every 5 meters or a "wall" snap plane is found, whichever comes first. And last, the "module" statement to call the "outerwalls" module was replaced by "defer". Defer makes sure all the other rules have run before the module is executed. This is necessary because all the walls need to be in place before adding any windows.

As a result, the repetition now is now properly constrained within the rooms:

Thursday, March 15, 2012

What would you like to come out of this?

Until today I had this running poll at the top of the site asking the same question. The options were:
  1. Content creation application (like WorldMachine)
  2. 3ds max plugins
  3. Fully dynamic sandbox game (nextgen Minecraft)
  4. Dwarf Fortress universe with rich graphics

It ran for several months and collected more than 5000 votes. I cannot tell exactly how many votes. For some reason Blogger's poll widget went crazy around 4000 and started counting backwards for a while, then forwards, then backwards again, then forward, and so on. Blogger is so buggy it makes you feel safe: at least you know these same engineers are not working on life support systems.

Since I am removing the poll, I thought I should comment on the results. The most popular option was "Fully dynamic sandbox game (nextgen Minecraft)", with 2445 votes. This is hardly a surprise since the poll ran along Minecraft's explosive raise. So am I making a nextgen Minecraft? No, I'm sorry. I think Minecraft should be left to Notch. Also there are too many Minecraft clones. I see little point in making yet another one. I would also wait a few years until physics simulations can be done at sub-pixel levels.

The second most popular option was "Dwarf Fortress universe with rich graphics", with 2069 votes. It was surprising that it got so many votes. It was very close to Minecraft, which I assumed was far more popular than Dwarf Fortress. Maybe it tells something about the readers of this site. Am I making a visually rich Dwarf Fortress? No, it is not that either. Dwarf Fortress is too rich, I think I would barely scratch the surface or would take me forever. I want to release something sooner than that.

And then there were other two options about content creation: 3ds max plugins and a world building application like World Machine. 3ds max plugins got almost no votes, only 319. The world building application got 833. This is higher than what I expected, I assumed most of the participants were mostly interested in games. If you have been following my lasts posts, you would know I have been developing this world building application for a long time now. Hopefully I will get it into a state it can be released so you can play with it and create your own worlds, and export them to game engines or content tools like 3ds max. As to what the poll is concerned, this is the option I have chosen.

I am also starting a game. As I said before, it is not a Minecraft or Dwarf Fortress clone. It is more about the survival and exploration of a very large world. I will reveal more information in the near future. I want to thank all the poll participants and apologize for going into a different direction.

Monday, March 5, 2012

Procedural Pixel Art

Most of us use procedural techniques to produce realistic results. It is very refreshing to see them applied to achieve a more abstract look. To pull this off is very difficult, you need to combine a very developed artistic sensibility with programming skills.

I have been following this project for a while now: Voyager3. I like very much the feel of the environments. It reminds me of beautiful game art like the one in Sword and Sworcery and Journey.

This is concept art, but it you check the site you will see they are getting close to achieving this look. The project is fairly new, but I think it has great potential.