# Scaling 3D furniture while keeping the thickness constant

I am creating a program in WindowsForms and Xna that allows users to create a 3D room. By dragging and customizing different .fbx models, they can "build" a room or whatever and then look at it in 3D. Everything worked nicely so far, until I got to a point that involves scaling a model. A model is usually made up of multiple meshes, and each mesh has a class that contains information about that mesh such as, position, rotation, name, mesh, scaleFactor, etc. This class also contains a list called ScalableAxes which contains strings of the axes name, in which this mesh can be scaled.

I have also included a parent-child relationship, when a user imports a .fbx model, there is also a custom .pdn file which contains information about parenting. Usually every mesh in the .fbx model becomes a child of an "empty mesh" (just a class, with no mesh or bone assigned to it).

Now let's say this "empty mesh" name is Body and it contains few child meshes such as left side, right side, top side, bottom side, top door, bottom door. Let's say I scale Body on the Y axis by a factor of 2. Since Body has no Mesh in his class assigned, it would skip this and loop through his children. If a child has a mesh, then it would look to ScalableAxes list and if it contains Y (in this case) it would go on to the scaling part.

The problem starts here. Let's say I come to Left side, left side can be scaled on the Y axis, but the top and bottom sides CAN'T be scaled on the Y axis. So scaling it this way would lead to gaps between left side and top and *bottom side**. Also there can be a whole variety of different models, and meshes. For example: one has only one door, other has sides between top and bottom, and so on...

EDIT: For example: left side is 964 on Y axis, top and bottom side are each 18 on Y axis, so the combined length is 1000 on Y axis. I scale the whole Body by 2 on the Y axis (meaning the new Y size should be 1000 * 2 = 2000). If I were to use scaling by 2 on the Y axis on all meshes (that can be scaled on the Y axis), then left side would be 1928, top and bottom would stay the same so, 18 each on Y axis. This would lead to 1928+18+18, 1964 size on the Y axis instead of 2000.

EDIT2: This program is all about arranging / making furniture in 3D. So let's say you got this night stand in your project made with this program.

And you find the size of it to small, and you want to scale it vertically. When you would scale it the "thickness" of all of the elements (meshes that made up this model) should stay the same since you want to make it bigger not "thicker". Only the length and width should change. So the left and right side would get scaled vertically, but top and bottom side wouldn't since that vertical direction is their "thickness". And if you would want to scale the model horizontally (make it wider), the top and bottom sides would get scaled, but left and right would stay the same since that direction is their "thickness" (they would only have to get moved to the right positions).

Thats why in my previous picture I said that top and bottom side cant be scaled on the Y axis, since that was their "thickness".

EDIT 3: bummzack, your method works great and all, but what if I have a furniture that has, 3 or more doors. How would I be able to scale all of the doors equally?

Any help is greatly appreciated!

• bumping, comeon, theres gotta be someone that knows how to do this. – user1806687 Jan 21 '13 at 16:28
• It seems like you're going about this the wrong way. And why can't the top and bottom sides not scale in the Y axis? Is that an arbitrary restriction that you imposed or is it because scaling it wouldn't change anything? – Tetrad Jan 21 '13 at 20:48

I wrote an application in Flash that does something similar to what you want to do (it's a tool where you can build and order your custom furniture in the browser).

I'm afraid your approach with scaling is never going to work, unless you provide some meta-data or structural information with your furniture. The bedside table you posted is a good example for this. How would your application know that the feet/base of the table is actually the base and should not be scaled vertically?

As soon as you're dealing with textures, things also get more complicated. Optimally, you would also scale UV coordinates, so that textures repeat along the model and don't get stretched. But this requires tileable textures without baked shadows or anything...

In the application I wrote, the "walls" of the furniture are being created dynamically (these are simple cuboids). By dynamically creating/altering the mesh, it's easily possible to also change UV coordinates etc. Different layouts (think GUI layouts, but 3D) ensure the furniture layout/structure.

There is also more complex geometry (such as drawers or clothing hangers) which can be added to the furniture (here's an example configuration). That's probably really close to what you want to do, because in this case, we load the geometry dynamically from file but it still has to adjust its size when the furniture measurements change. To achieve this, we created different bones (or vertex-groups).

Here's the screenshot of a simple drawer model:

There are two "bones" (or vertex groups) called "LEFT" and "RIGHT". We simply established a naming convention for these bones (eg. LEFT, RIGHT, TOP, BOTTOM, CENTER, etc.) and moved these bones to different positions in code when the model needed scaling.

If you need to scale in all 3 axes, you might be better off with vertex groups for all the corners of the model, but even then you won't get perfect results with every type of furniture.

In case of your nightstand you could have a bone in every corner (8 corners) of the model. Then you would have to move 4 corners to adjust one side. This requires careful preparation of the model though and you can still run into issues, especially if the center of the model needs special scaling/treatment and with texture scaling.

If your app allows the user to upload his own models, then I guess you'll be better off with uniform scaling of the model (as your approach with individual scaling just won't work).

• Yes, this is exactlly what I need. I will let you know how it goes. :D – user1806687 Jan 22 '13 at 16:43

I think what you're looking for is the 3d equivalent of a 9-patch image. 9-patch images are often used in 2d graphics to draw UI elements, like buttons, which need to be rescaled to different heights and widths. Scaling the button image uniformly will look dreadful, so different scaling is applied to different parts of the image so as to retain the corner and edge details without stretching.

So basically you want to leave the corners unscaled, scale the edges in only one axis, and the middle can be scaled in both axis. For 3d graphics, it'd be the same except you'd limit scaling in the edges along a plane rather than axis.

http://developer.android.com/guide/topics/graphics/2d-graphics.html#nine-patch

It seems like you need to practice equations, especially finding out what your knowns and unknowns are.

left_side = 964
top_side = 18
bottom_side = 18
total = left_side + top_side + bottom_side
= 964 + 18 + 18
= 1000


Now you want to scale total by 2. The only value that is allowed to change is left_side, it's your unknown. The others are knowns. Hence the equation:

left_side + top_side + bottom_side = 2000
left_side = 2000 - top_side - bottom_side
= 2000 - 18 - 18
= 1964


Giving a scaling factor of:

scale = 1964 / 964 = 2.03734439834

• Actually, the 1964 is an unknown variable, I just wrote it, to tell you how much it should've been. – user1806687 Jan 22 '13 at 16:33
• @user1806687 It's not an unknown variable. It's a value that needs to be replaced in the expression when you compute the value of scale. – sam hocevar Jan 22 '13 at 16:56