Cage Mesh Deformer - Studio Beta

Hello fellow developers,

We have just released a public Studio Beta for Cage Mesh Deformer! Yay!

This is our first step towards the next big milestone for Avatars - 3D Layered Clothing. With the cage mesh deformer enabled, you’ll be able to “reshape” existing MeshParts to make them look different.

Here is a quick example of what the cage mesh deformer is capable of:

What is the Cage Mesh Deformer?

The Cage Mesh Deformer is a key part of the upcoming Layered Clothing tech, and it is responsible for “static” mesh deformation. I.e., deformation runs only once, and then a deformed mesh can be animated/deformed using more traditional tools (like animation/skinning and physics simulation). The Cage Mesh can be thought of as an invisible mesh that drives the deformation of a “driven” mesh.

Key features:

  • Fully agnostic to driven mesh topology (as long as a mesh is properly “caged”, it can have arbitrary topology)
  • 100% compatible with smooth skinning and animatable
  • Multi-layered (with layer ordering support)
  • Super flexible and supports arbitrary nonlinear deformations
  • Bi-directional (a layer can be driven by other layers below or can drive/compress them)

How do I use it?

You’ll need to enable the Beta Feature first.

To enable the beta feature:

  • Go to File → Beta Features in Studio
  • Check the box to the left of “Cage Mesh Deformer”
  • Restart Studio

image6

New data-model instances and how to rig meshes for deformation

We added two new data-model instances. They are responsible for different deformation needs.
Let’s have a quick look at them.

WrapTarget

The WrapTarget instance lets us define the desired target shape (think about an avatar body that determines the shape of clothing). A MeshPart can have only one WrapTarget associated with it. However, a Model Instance with multiple MeshParts as children could have as many WrapTargets as there are MeshParts. The Deformer will merge all WrapTargets into a single monolithic cage mesh, based on the connectivity (welds/motors/ballsocket constraints etc.) of the underlying MeshParts, using the same logic as for physical assemblies. The spanning-tree defines connectivity for WrapTargets using the same logic as for physics assemblies.

Important properties:

  • CageMeshId - a mesh that defines the external surface (target) for the deformation

  • CageOrigin - relative offset from parent MeshPart

  • ImportOrigin - relative offset from CageMesh to Import origin (i.e., where world zero was when cage mesh imported, not used by the deformer directly but useful to align multiple cage meshes together)

How to Rig WrapTarget

To make the FBX importer automatically create a WrapTarget object, you need to have two meshes (one renderable and one cage).

The first mesh is renderable - it may have arbitrary topology/UVs, and in fact, it could be anything, and it’s only limited by your imagination.

For demonstration purposes, I made a twisted cube:


Renderable Mesh

The second mesh (outer cage) is required for proper deformation fitting and never used for rendering.

There are few technical details you need to know:

  • Outer Cage mesh is used to approximate the renderable mesh surface (i.e. it should be fitted to follow the renderable mesh surface)
  • Outer Cage mesh should use the following naming scheme <RENDER_MESH_NAME>_OuterCage where <RENDER_MESH_NAME> is the name of the corresponding renderable mesh
  • Cage mesh should have UV coordinates associated with it

UV coordinates are the most important part. Cage deformer uses UV coordinates for “indexing” cages, i.e., when it needs to match different cage meshes (from different deformation WrapLayers or multiple WrapTargets), it will use UV coordinates to find corresponding vertices on the other cages.

Thus UV coordinates define a “DNA” of the resulting cage. Different cage meshes may be arbitrarily shaped, but as long as they share a UV layout, they are compatible and can be used for deformation.


Outer Cage mesh (pay attention to UV layout)

Note: There is no need for smooth skinning for cage mesh; it’s a simple rigid mesh.

Now it’s time to import the WrapTarget mesh into Studio and see how it works.

  1. Use Avatar Importer to import deformable meshes
    image1

  2. Use the “Custom” option for custom meshes or “Rthro/R15” if you are importing avatar bodies. Note: This could change in the future as we provide a special path to import caged meshes.

  3. Select “twist.fbx” from the folder contained provided test files (find the download link at the end of this post)

After import, the resulting scene should look something like this:

Please double check that the WrapTarget object was created correctly by the FBX Importer:
image4

And that’s it!

Congratulations, you have successfully imported your first deformer target!

If something looks incorrect, please double-check all the steps and check the Studio output log for errors. Let’s leave this scene for now and try to create a deformable object a.k.a WrapLayer.

WrapLayer

WrapLayer instance lets us define the “deformation layer,” i.e., a MeshPart that will be deformed and drive the deformation of the layer above (you can think about it as clothing that follows a body shape but have its own thickness and will affect all clothes above it). Unlike the WrapTarget, for the WrapLayer we need two cage meshes; let me show you why we need two cages and how to rig them properly.

The first cage mesh (CageMeshId property) performs the same function as WrapTarget cage mesh, i.e., approximates the renderable mesh’s outer surface. It does not directly affect renderable mesh deformation, but it is crucial for proper layering (we’ll discuss layering in more detail later). We call such a cage an “Outer Cage”.

The second cage mesh (ReferenceMeshId property) directly affects the deformation of the renderable mesh and determines the inner surface of the renderable mesh. Think about it as a mesh that should be fully covered by renderable mesh. The difference between the two cages determines the “thickness” of the renderable mesh and is used by the deformer to determine how exactly the renderable mesh shape should be changed. We call such a cage an “Inner Cage”.

It may sound a little tricky so let’s have a look at the following picture to make it more clear:


Green shirt = Renderable mesh
Red outline = Inner Cage
Blue outline = Outer Cage

On the right, you can see the difference between Inner and Outer cages. This difference is used to determine the renderable mesh’s thickness. I.e., when the shirt layer is added to the deformer, the deformer will only process areas where thickness is not zero

Important properties:

  • CageMeshId - a mesh that defines the external surface (target) for the deformation

  • CageOrigin - relative offset from parent MeshPart

  • ReferenceMeshId - a mesh that defines the internal surface (reference) for the deformation

  • ReferenceOrigin - relative offset from parent MeshPart

  • ImportOrigin - relative offset from CageMesh to Import origin (i.e., where world zero was when cage mesh imported, not used by the deformer directly but useful to align multiple cage meshes together)

  • Order - Layer order (layers are processed from lowest to highest)

How to rig Wrap Layer

To make the FBX importer automatically create a WrapLayer object, you need to have three meshes (one renderable, one inner cage, and one outer cage).

The first mesh is renderable; it may have arbitrary topology/UVs for texture mapping, and in fact, it could be anything, and it’s only limited by imagination.

For demonstration purposes, I made a Roblox themed cube:


Renderable mesh

The second mesh (outer cage) is never used for rendering and used to approximate the renderable mesh surface.

Technical requirements are the same as for the WrapTarget cage

  • Outer Cage mesh is used to approximate renderable mesh surface (i.e. it should be fitted to follow renderable mesh surface)
  • Outer Cage mesh should use the following naming scheme <RENDER_MESH_NAME>_OuterCage where <RENDER_MESH_NAME> is the name of the corresponding renderable mesh
  • Cage mesh should have UV coordinates associated with it that match.


Outer Cage mesh (pay attention to UV layout)

The third mesh (inner cage) is also never used for rendering and used to define the renderable mesh frame-of-reference.


Inner Cage mesh (pay attention to UV layout)

There are few technical details you need to know:

  • Inner Cage mesh is used to approximate the renderable mesh’s frame of reference (i.e. the renderable mesh is related to the cage)
  • Inner Cage mesh should use the following naming scheme <RENDER_MESH_NAME>_InnerCage where <RENDER_MESH_NAME> is the name of the corresponding renderable mesh
  • Cage mesh should have UV coordinates associated with it

Note: All my cage meshes have different shapes, but they share the same UV layout, which makes them compatible.

Now it’s time to import the WrapLayer mesh into the Studio and finally see the deformer in action.

  1. Use Avatar Importer to import the deformable meshes
    image1

  2. Use “Custom” option for custom meshes or “Rthro/R15” if you are importing avatar bodies

  3. Select “roblox_cube_caged.fbx” from the folder that contains the provided test files

Note: During the import process (for your custom cages) you may get the following warning “Number of cage vertices doesn’t match.” This warning should not affect the deformer algorithm, but if it bothers you, then please make all edges “sharp/hard” for both cages.

After the import, the resulting scene should look something like this:

Please double check that WrapLayer object was created correctly by the FBX Importer
image5

Congratulations, you have successfully imported your first deformable layer!

If something looks incorrect, please double-check if you followed all the steps, and check the Studio output log for errors. Now when we have both the WrapTarget and WrapLayer instances in the scene, let’s deform our Roblox-themed cube.

Apply Deformation

Since we are not using Humanoids/Accessories for this tutorial, please install the following Studio plugin before moving forward:

This plugin is created to simplify the layering and alignment process for deformable meshes.

You can find the already (pre)imported WrapTarget and WrapLayer as long as the plugin source code is in the following (open-sourced) place:

  1. Open the place in Studio using the link above

  2. Select two models - first “Target” and then “Layer”
    Note: The selection order is important!

  3. Click the “CopyTo” button from the Cage Deformer plugin panel.

    image11

  4. Now you have a cube that follows the WrapTarget cage!

  5. You can repeat this operation as many times as you want.
    Each time, it will add another “layer” to the deformer, and each new layer will automatically follow the layer below.
    Here I made three layers, and I also made them transparent for convenience.

Here you can find another place with many different WrapTargets to the same Roblox-themed cube.

Note: In the example above, we used a plugin to set up layers, in the case of the Humanoid all accessories align/layer automatically when you put them onto an avatar. It is as simple as a workspace drag-and-drop.

Advanced layering / deformation

Here you can find another uncopylocked place with a bit more complex rigging using accessories and multiple layers.

Rigged FBX files to download!

We uploaded all the source FBX files used in this article to our public GitHub repo for your convenience

https://github.com/Roblox/avatar/tree/main/cage_deformer

We want your feedback!

We have only scratched the surface in terms of soft body mesh-to-mesh deformations; there are many more deformer-related topics to cover - Layer order, Underlying layers compression, Fine-tuning and fitting adjustments, Splitting into parts, Animation support, Bind-pose adjustments, etc.

We don’t yet have public documentation covering advanced deformer features, and we may change something based on your feedback. So don’t hesitate to ask any questions.
Play with the new tech and let us know what you think!

Please note that most of the deformer properties are available only for plugins for safety and performance reasons. Let us know which properties you would find valuable to be made editable in-game. Pay attention to skinning behavior with the Cage Mesh Deformer beta enabled. When the beta is enabled, we use a new (and less tested) skinning code path (even without the deformer enabled).

We’ll keep working on the FBX importer (and the current plugin is most likely a temporary solution); please share your ideas on improving the existing art pipeline.

Here are a few deformer usage ideas (other than clothing), which can be interesting to explore. Feel free to add more in the comments.

  • Car crash deformation (cage that responds to collision)
  • Soft body (physically simulated cage mesh)
  • Kitbashing / Adding visual variety to the scene
  • Muscles / Body customization

Performance

Here are a few notes about the deformer’s performance to get you a better understanding of its performance constraints:

  • Deformation is supposed to run once (when a deformer instance is parented to Workspace) or when the deformation properties change. If you noticed an unexpected deformer invalidation, please let us know.

  • Deformed meshes cost extra memory. Since the deformer only runs once, we need to store deformed vertices in memory.

Next steps

Hidden Surface Removal

  • A system to automatically eliminate invisible triangles that are fully covered by overlying mesh layers. The fewer triangles to render, the better performance!

More performance optimizations

  • The beta version of the deformer is fast (and asynchronous) but we only recently started the massive performance testing and will focus on the deformer performance for the next few months.

Studio Tools for real-time cage editing and deformer rigging

  • Yes! Eventually, cages will be editable directly in Studio using our built-in Studio tools, and the API for cage editors will be exposed for plugin writers.

Known issues

  • Sometimes the deformer doesn’t kick off after welding. Save the place file and reopen the scene to work around this issue.
  • Sometimes shadows don’t get updated after deformer target changes.
  • Cage Deformer (WrapTarget and WrapLayer) will work ONLY with MeshParts, and 3D Layered Clothing will be considered an “Accessory”. So, if your game hasn’t enabled MeshPart Heads and Accessories (Action Required: MeshPart Heads & Accessories (May 24th)), please enable it in time for the upcoming Layered Clothing feature.
392 Likes

This topic was automatically opened after 13 minutes.

This is an amazing update. However, my only issue with the shown picture is that this character layered clothing looks a bit streched. Can you make it so that mesh (resizes) with the cage? This looks inhuman imo, and this layered clothing clearly does not fit the character.

Screen Shot 2021-04-30 at 10.48.05 AM

77 Likes

Beta features only work in studio and if enabled.

11 Likes

So why would they demo the place without even any option to edit it in Studio?

6 Likes

Good question. I assume they forgot to uncopylock it.

You could also re-create it yourself trivially:

4 Likes

This changes so much for me. I have been using a lot of mesh deformation lately. (and have been in great, great need of this)

How much of an impact?

1 Like

I assume they forgot to uncopylock it.

Oh sorry, fixed

14 Likes

Ok, they uncopylocked it now.
image

5 Likes

Been waiting for this since it was shown at RDC 2019, I’m so excited to see mesh clothes that fit on any body and to be able to release my own mesh clothes, and I’m glad progress had been made so far that we get a studio beta.

5 Likes

AHAH this is gonna take meme games to another level. cant wait to make squashed characters and weird morphs.

10 Likes

Oh good, I can make the environment work against the player now, as well as make them question reality.

5 Likes

It appears the GitHub repository is still private at this time.
https://github.com/Roblox/avatar/tree/main/cage_deformer

9 Likes

The cage mesh deformer has the same memory impact as using FastClusters (FC). I.e., it doesn’t introduce any extra memory waste for Humanoids (since they are using FC anyway), and it doesn’t introduce any waste for low-end platforms (since they are always using FastClusters)

9 Likes

Give us a few minutes; we are working on publishing it.

8 Likes

what is THIS?
image

12 Likes

This new feature seems like it’s going to be really useful for more advanced visual effects, for example moving plants or such

5 Likes

Setting up wrap layer and applying mesh deformation seems a bit too complicated currently, are there going to be updates to make it a bit more simple?

3 Likes

Looks like it’s the RenderingTest class.
They use it to do regression testing on the rendering pipeline.

13 Likes

Super cool! I can’t wait to see all the creative ways people are going to use this. Thanks for all of the hard work that went into this.

Really interested to see if I can use this for creature markings on custom characters.

5 Likes