Procedurally Generating Floorplans

Debug Drawing all the Door/Window Overlaps as well as all the free corners of the room.

This information will be used by each room to place Furniture Inside

3 Likes

This is just amazing!! The one-reason that I’ve purchased this Apparance…
Too bad it wasn’t included in the DEMO projects :frowning:

Hope I’ll be able to get something going like you have. Especially the categories for specific furniture placement is really cool!! Great job

1 Like

as EduardoHulshof hasn’t been online for alost a year, I won’t be expecting any more comments on how he achieved this roomgenerator…

Do you have an example project that reflects this funcionality @sam ?

1 Like

Sorry, there aren’t any available yet, and it’s unfortunate the Twitch doesn’t keep videos for longer. I’ll ask Eduardo if he can share any insight for you on here.

If you can do that. I’ve found his page in Instagram but last post was almost a year ago… Guess he’s not on that account anymore :pensive: I bought this plugin for this feature only, but to be honest, my skills ain’t allow me to create it myself… So really hope you can get in touch with him :pray:t2:

It is quite ambitous to make ‘realistic’ room/floorplans for a house. There are lots of complications as you work through it. Both Ed and I have built logic like this in Apparance so can advise.

My first steps would be to sub-divide the space into portions, recursively, until some end condition is met (e.g. room not too small). Second phase is working out where outside doors/windows are, and having that information used whenever you divide the space up (so walls don’t intersect openings). Each split should add at least one door (to maintain connectivity). Next step might be to bias and adjust the sizing and door counts to create ‘types’ of rooms with differing characteristics (also, ‘hallway’ can be considered a type of room). These types of process require working with the List type and building procedures that iterate through these lists to derive/calculate information. Unfortunately lists and iteration can be considered ‘moderate difficulty’ topics (and not helped by iteration always having to be implemented via recursion).

This would certainly make a good set of streams/videos, and I’d like to find time to produce some in the future.

1 Like

Hello! I’ve been quite busy lately with my job but I can probably offer some insight in here on how did I get to it.

It was quite a journey. I more or less streamed the whole process but didn’t keep the videos. I still have the procedures tucked into a project. I’ll need to resurrect the project and refamiliarize myself with it.

I’ll post some stuff in the coming days. (I actually look forward to go back and scratch that procedural itch)

1 Like

That’ll be amazing! It’s all hocus pocus to me, to be honest… I’m good in modeling, but putting the parts together, procedurally is a whole new level :sweat_smile:

I went looking for your streams, but too bad twitch doesn’t save them forever…

Good news. I managed to resurrect the project, and bring it to UE5.1

I’ll start a step-by-step of how I got to that result.

GifMaker_20230118083448007

Here’s a sneak peek of the top level Procedure

This is what’s going on in there:

  1. I split the original frame between the building portion, and floor portion, and place all the floor bits
  2. I then split again into building and roof. (At the bottom I place the roof)
  3. I feed the remaining frame into the Logic that builds the Outer Walls, and spits out where the doors and windows are (so I can guarantee I don’t place walls across them when I split the interior of the house into further rooms.
  4. The main logic of splitting the room, is where the bulk of the magic happens, as it recursively iterates (The key process you need to wrap your head around in Apparance), until it can’t divide the rooms anymore.
    5 . It spits out the objects and then I merge everything back together.

EDIT 1: That work was done over the course of a couple of months. I was away for about 15 days during that (holiday) period, so this was more or less a month of work, working a couple of hours a day, I think total it would have been about between 30~50 hours, a lot of which went into trying to figure out the logic to not place walls through doors.

1 Like

The whole floorplan builder uses a series of procedures for the
I think this is the whole list. However, there may be some other procedures in other categories that are not there. I’ll include them later. if needed
image

First I’m going to continue with the high-level look into the process.

In the previous post, I talked about building the Outer walls, of the House.NewBaseRoom procedure (it’s called new because it’s the second iteration and I likely deleted the original one).

It does this:

The procedure itself is this:
(UPDATED: Rejigged positioning, and added some comments for clarity)

1 - It Extends the Frame in X and in Y by the Wall thickness then again, in the opposite directions, to place the corners. (The House.SimpleWall procedures place the corners)

2 - The remaining bits are fed into the House.ExteriorWall Procedure, which builds the Walls with doors and windows.

NOTE: Each window receives a different Twist of the random seed, so they are guaranteed to generate, different arrangements. If I want to make a “shotgun house” (where the front and back doors are lined up, I could feed the same seed to opposing walls. Like so.

This is what it looks like without the House.ExteriorWall objects connected

And this is what it looks like with only one House.ExeriorWall Connected

Tomorrow I’ll post the logic of that procedure.

Ok, let’s take a look at how walls are built.

House.SimpleWalls are, well, simple. I have an asset that is a simple cube mesh, and I place it in the entire frame.

There could be some polygonal optimizations to this, as a lot of the sides of these cubes are never going to be visible.

Apparance lets you build your own mesh if you turn on Experimental Features and there you could specify which sides of the Cubes to draw based on where they are placed, but that’s something for another day.

Now the House.ExteriorWall is a little bit more fun, we’ll see some recursion happening there already.

First let’s look at the node itself and its inputs.
image

Frame: We have a frame (that’s the size of the wall)
Select: Used by Stacker.Splitter and Stacker.Merger operators. I think these nodes need their own tutorial https://apparance.uk/manual-operators.htm#Construction
Door Width and Height: these parameters get exposed all the way out so you can configure at the instance level in Unreal
Seed: What random seed this wall will be using
Axis: Which way (X or Y) this Wall is facing.
Frame Width: How thick the door frames are supposed to be (passed into the House.DoorBuilder procedure:
Window Sill: the height from the floor the window starts
Window Height: the height of the window, I don’t do any clever invariant checks here such as capping the window height to the ceiling height, although it would be fairly easy to implement. so you can actually push the windows out of the frame :stuck_out_tongue:
image
Original Frame: Since we do many frame operations during recursion I keep a reference of the full original frame.
Side: This is some sort of ID I added for the future (I’m not using it in any way right now).

This is the House.ExteriorWall procedure.

This procedure relies on the Stacker.Splitter set or operators

1 - It places simple walls in Upper and Lower Caps.
2 - It sets the Openings to have DoorWidth (as Spacers, which are fixed-size things in a frame split by the stacker splitter). So in my Case, Doors and windows have the same size. it would be possible to have them be different, but it would complicate the procedure a bit. so same it is for now.
3 - So for the spacer frame, it has a chance of placing a door (10%), if it fails, it sees if it should instead place a window (30% chance), if it fails that check, just places a regular wall.
4 - Places Simple Wall in the Object slots, which are fillers of whatever frame size is left after you placed the spacers, so they are, for the lack of a better term, “stretchy”

I think there is a probability here to have a house with NO DOORS :scream: if my high-school math is right that probability is 0.01% (since I’m choosing to have a door at each side 10% of the time). in the grand scheme of things, it’s actually quite high. One in every 10.000 houses will have no doors. gotta do something about it.

NOTE: I collect Door and Window Segment Pairs on these Stacker.MergerL these are information on where the doors and windows are, so in the future, when dividing the house I don’t place a wall across it.

Calculating those House.OpeningOffsets and House.CreateDoorPair was very hard, and I needed @sam to help me figure it out and point me in the right direction as this is a problem that he had encountered/solved before. (earlier in this thread).

Starting to get through the core of it. the Room.Splitter logic. I posted about this on my mastodon account.

Just going to copy-paste it in here because I’m lazy.

Let’s start with a small house. The whole thing started with me trying to split the house into sensibly sized you would find in a house.

The procedure takes a frame (In Apparance a Frame is the equivalent of a 3D volume) and checks the size of a room and decides if a split SHOULD happen and if a split MUST happen. Additionally, it checks which one is the longest side and only splits there, the reason here is we don’t want to end up with a lot of corridors. (I added a screenshot to illustrate that situation).

Once those checks are made, we pick a random location between a Min and a Max Room size.

It does this splitting operation recursively until a room can’t split. If a room does not pass that check a wall goes down on the last valid split.

That part was easy. I worked that out really early in the process (you can see it earlier in this thread).

Things got dicey we I got to doors and windows.

When a wall between rooms finally goes down, it places what I called a “Connecting Wall”.

All my splits are Connecting Walls, which is not really natural, but it does prevent creating dead ends, and rooms with no doors or access.

A connecting takes a frame and the door design parameters. and an Axis (we need to know if the wall is aligned with X or Y.

It outputs the wall objects, as well as the frames (where the door is, and where the “wall parts are” we use that later to decide the safe corners of the room.

We also output the Door segment (which is a pair of float values that tell where, alongside that door, the door starts, and ends.

this gets added to the list of Doors in the room for further split checks.

I actually went back to this and stated to try to push this a bit further.

When I paused this work, I had just started thinking about how I would:
1 - Choose how rooms are assigned (e.g. How do I decide what should be a bedroom, what should be a bathroom)
2 - How I would populate the rooms once I had chosen what it would be.

For the first problem, I started with a Random selection, then for the Bathroom I ended up with a very simple rule.

The room is small enough + it has only one door.

NOTE: I’d rather not place a Bathroom inside a Kitchen like the picture below :grimacing: (Not that I haven’t seen this before when looking for places to rent :nauseated_face:

But this did give me something to work with as a proxy for actually solving the first problem, so I jumped into the second problem (mostly as an exploration of what were the things I’d need to consider when I knew what kind of room I was starting to build.

Since I have a “solid” rule for the bathroom that’s what I chose to tackle.

I already knew that I needed to know what the “free corners” were. which I was already collecting, so that was easy.

then I thought, I just need to know their size, which is very simple, then place things that can fit in that area.

However, this breaks down quickly as you could end up with 2 Baths and no toilet in a bathroom, which doesn’t make sense.

So I landed on a logic more or less like this, and I think this will apply to the majority of the rooms.

Rooms will have a Zone, that is dependent on its size, and each of these zones will be populated with a “diorama” of things that would go on that zone, plus the center of the room in some cases.

So a bathroom would have:
LargestArea: Bath or Showerbox
LargeArea: Toilet bowl
Small Area: Vanity / Medicine Cabinet
Smallest Area: A Towel Rack

So some crucial information I needed to collect was the Area of the Corner, and which one were the Corner Walls (so I don’t place Mirrors flying in the middle of the bathroom)

The image below show the corners color coded to indicate which one is corner each room is in

e.g. (FrontRight Red, Front-Left Green, BackRigh Blue, BackLeft Yellow)

And then again by size
Largest Red, Large Green, Small Blue, Smallest Yellow

So I can confidently place things like below, as I know both they will fit, and how I should orient it because I know where the walls are.

1 Like