Tutorial - how to watertighten almost anything (loses detail)

Discussion in 'Design and Modeling' started by EricFinley, Dec 8, 2009.

  1. EricFinley
    EricFinley Member
    Now that I've got your attention... this will be a step-by-step description of a process I use to generate watertight shells conforming to the exterior of, thus far, pretty much any mesh.

    For example, I'm using this on figures imported from DAZ Studio, which uses a whole lot of totally nonmanifold single-sheet meshes for stuff like clothing. And eyelashes, and eyes, and irises, and pupils. Separately.

    This will produce an approximation of your mesh. Topologically speaking, it will not be a pretty result; it will contain faces varying from the full dimension of a cube of [X size], to tiny triangles much much smaller than that. Visually, it will lose fine details, especially concave ones. Concave sharp corners will suffer the most, and narrow passages may come out bridged by material which you will have to remove by hand. But it appears that the result is always watertight, so that's a heck of a lot better as a starting point than most.

    Here's the procedure. This all uses MeshLab, so load up your existing non-watertight model in there. (The version of MeshLab I'm using is version 1.2.2b, though the same procedure will essentially work on 1.2.1b. For me, the currently available 1.2.3b seems bugged. I do this work on a two-year-old laptop or a three-year-old desktop, but in general you can expect these steps to take less than fifteen minutes apiece if you pick the parameters right... which is the same criteria as are necessary to get under Shapeways' 500K poly limit. Much faster on a better machine, of course.)

    I'll be working with this charming hoodlum, built in DAZ Studio by my friend Davyd Atwood. At just under 300K polys, he's not overcomplicated to be a Shapeways print; however, he's also made up of 240 separate pieces, each of them non-manifold.

    1) Form a "bubble shell".
    Go to Filters > Remeshing, simplification and reconstruction > Uniform Mesh Resampling. Check the boxes for Clean Vertices, Multisample, and Absolute Distance; leave Discretize unchecked.

    The numeric parameters here are a little trickier to simply prescribe. What you want is a shell which will be complex enough to capture the figure, yet not so complex that it puts your polygon count and time through the roof. Which can easily happen. For meshes that are roughly humanoid, or have a similar surface area to volume ratio, a Precision of about 0.350 (percent - this is in the second box on the first row) will yield a decent final result with around 150,000 faces, and won't take forever to calculate. Note the absolute value you get corresponding to this number - the first box on the Precision row. Write this down.

    As for the Offset value, in theory you could just pick a very small number (or zero) and come up with a close-fitting sheath in one step. This doesn't work, because it's smaller than the size of the grid you're slicing it into. You'll end up with disconnected "stripes" of mesh instead of a single sheath; that, or MeshLab will crash. An absolute Offset value on the order of twice the absolute Precision we noted above should generally work, though it can go noticeably higher than that and still get remarkably decent final results. Write down the absolute Offset value you used in this step.

    Tommy has put on a bit of weight in the result, but he's still basically recognizable.

    2) Remove the inner shell(s).
    The above operation actually created both an outer and an inner shell, at equal distances away from the outer edge. The inner shell is often somewhat fractured. We'll clean this up with repeated applications of Filter > Cleaning and repairing > Remove isolated pieces (by face num).

    Start by running it once with the default value (25) and observing the log window at the bottom. You'll see that it has removed some number of pieces, out of another number of total pieces. What we're watching is actually the difference between the two - the number of pieces kept. You want to end up with just one shell - the outer one (which, luckily, will also generally have the most faces).

    Assuming you didn't get there in one shot, re-run the filter with a value equal to approximately one-fifth of the total faces shown in the info pane - the number before the parentheses is the one you want. (The other includes the faces in your original model, which is still present on another layer. If you want to see the original, you can open the Layers pane, and toggle the visibility of your new layer "Offset Mesh." ) This will usually get rid of all but the largest inner shell (often ~30-40% of the total faces) and the outer shell (usually ~50-60% of the original total); if not, repeat the filter with an increasing face count until you're down to at most two connected pieces left.

    If you're down to only one connected piece, you're done this step. If not, run the filter one last time with about 50% of the current face count as the threshold; this will cut off the smaller of the two pieces and keep the bigger one, which is what you want. At the end of this step you should have only one connected piece remaining; you can always double-check this from within MeshLab simply by re-running this same filter with a very low value (like 1) for the number of faces required.

    You likely want to do a Save As now. You will only be saving the new layer created (currently named "Offset Mesh"), not the whole contents of your viewscreen. I generally immortalize the values I used in Step 1 as part of the file name, like "Tommy offset 0.35 0.0064.stl"). File type is irrelevant; I use STL by habit.

    Tommy still looks the same; we've just deleted his internal (quasi-)organs.

    3) Form a second bubble shell. Now we're going to run the Uniform Mesh Resample filter a second time - this time applying it to the bubble mesh. The same three checkboxes should be ticked. You'll want the same absolute Precision as before - this is the first number you jotted down in Step 1. MeshLab will adjust these values very slightly; that's okay. For the Offset, you want this second Offset to be smaller than the value from Step 1, but still roughly comparable to the absolute Precision. For example, if you used 2x Precision in Step 1, try ~1.5x Precision here.

    (For Tommy, who is ~1cm tall at present, my absolute Precision is 0.003247, my Step 1 absolute Offset was 0.0064, and my Step 2 absolute Offset is 0.005. If the autocomplete isn't letting you enter a particular value, tweak the decimals in the percentage space alongside it until you get roughly what you want for an absolute.)

    Tommy's kilt is a single-sheet mesh - the bottom edge of the kilt is one big nonmanifold edge, and the skirt's thickness is zero. This is why it is imperative that the secondary Offset be smaller than that in step one. If you don't have this problem, then you can often use identical first and second absolute Offsets, to avoid distorting the proportions of your piece.

    The result is even more bloated than last time.

    4) Remove the outer shell and invert the inner shell. Now go to Edit > Select Connected Components in a Region. Hold down Alt (for "select visible only"), and draw a box which includes any part of the figure. It'll look like you've selected all of it, but you've only selected the outermost shell. Delete it.

    What you'll see now is the original bubble shell. That's because it's bigger than the result you just created. Open the layer dialog (View > Show layer dialog) and click on the green eye next to the first Offset Mesh (or whatever you Save As'd it as) layer. That'll hide it. While you're at it, hide the original layer too, the one at the top. Make sure to click the name of the newest layer (Offset Mesh_copy or just Offset Mesh) so that it's the active one, especially if you prefer to get the Layer dialog out of the way again.

    In theory, we would want to do another pass with deleting isolated pieces other than the primary inner shell. But because of the way we've set things up with the size of the two offsets, it's virtually guaranteed that you won't have any, and if you do, they'll be obvious.

    Now, not to put too fine a point on it, Tommy the hoodlum is black. That's because the normals on the inner shell are set up to point inward. Use Filter > Normals, Curvature and Orientation > Invert Face Orientation.

    Tommy is now a somewhat less detailed, but completely 2-manifold and watertight, version of his original self.

    4) Save-As the result. The process is done. At first, and with particularly poor meshes (such as ones with a single-sheet mesh which extends well away from the body), you may need to tinker with the Offset sizes in the two resampling steps until you get a pleasing result. Another option is to use a different program to "fill" the nuisance parts of the mesh, such as by closing off the bottom edge of a skirt into a solid, before running this routine.

    As I said before, with Precision = 0.35%, the result gives around 150,000 polys for a humanoid mesh. Lowering this value will increase the poly count, and the time. Because we only keep the surface polys, you can expect it to scale roughly as the square of the Precision change you make... that is, if you halve the Precision to 0.175%, and are willing to wait for it to run, you should see somewhere between 450,000 and 750,000 polys - it depends a lot on the precise geometry at this point. In my experience it's simpler to start out low and then run a Subdivide (in Blender) on only the areas where I need to recreate or modify details.

    Some further tricks:

    To preserve detail in an area, you chop it off of the original mesh and use this same technique on it separately. Remember that this technique will work on any mesh, even a disembodied face. Some care will be needed with the merging of the pieces back together - but you may get some use out of NetFabb's Stitch Triangles script, or out of the recently-previewed MeshMixer, for this. (I often just do it by hand so as to be sure it's right.)

    The resulting mesh is an excellent candidate for refinement in ZBrush or (for those of us who can't afford $400 in software) Blender's Sculpt Mode. In particular, concave areas which lost detail during the bubble-shelling process can be attacked with a level 2-3 Multires plus some Draw (subtract, low strength) and Pinch (set to 100% strength), to very good effect.

    In addition, the mesh is smooth enough that either a global Shrink/Fatten Along Normals (or equivalent operation), or some use of the Inflate (subtract, low strength) sculpt tool, can help restore the correct dimensions where needed.
  2. pete
    pete Shapeways Employee CEO
    Hi Eric,

    you are doing cool stuff! Would you mind if we turn your post into a tutorial for our tutorial section?

    thanks in advance,
  3. EricFinley
    EricFinley Member
    Not a bit; that was basically the intent. Given the distortions it introduces, though, I'm not sure whether it's actually useful to most folks. The lack of responses here makes me think it may not be; I dunno. Useful to me, certainly, and you're welcome to tutorialize it if you like.

    I'm just thinking it might be worth first actively soliciting commentary on whether anyone else has used this, sees themselves using it, or is otherwise interested in tweaking it first.
  4. 18435_deleted
    18435_deleted Member
    Especially with human figures the amount of distortion is too high. But maybe it is a starting ponit for building a shell. A way to carve out the figure.
  5. EricFinley
    EricFinley Member
    Depending on the desired scale, yeah - for 25mm tall miniatures, the amount of detail preserved is almost at the printable limit anyway. But yes, for larger ones it would definitely only work as a starting point.

    I'm working on more sophisticated watertightening tricks using Python scripts, but they're not ready for prime-time yet.
  6. Spacetime
    Spacetime Member
    Hey there! This is great stuff but I'm having trouble making the inner shell?

    I went through the steps you gave but I'm not seeing any inside shell being created?

    Basically I'm trying to take my solid models from C4D and shell them in an efficient way. I'm sure MeshLab can do this but I'm not sure how to get there.