0
$\begingroup$

I'm looking for the following operation in Blender:

Input: a mesh, with intersecting faces

Output: a (manifold) mesh that is the upper envelope of the input.

(To get manifold, it'd need to attach a bottom. This could, for instance, be the lower envelope. In my application, ideally, the lower envelope would be flat.)

Another way to think about this is world-space Visible Surface Determination (a.k.a. Hidden Surface Removal, if you're a dinosaur like me) from an orthogonal projection with eyepoint at z=infinity looking at the origin. And I'd like the resulting polygons woven into a mesh.

I've tried various approaches, including booleans, shrinkwrap, and 3D Print Toolbox's "Make Manifold," all without success. Solutions cannot rely on hand-cleanup afterwards, as I have many instances of the problem to solve and each has several thousand intersecting and/or completely hidden faces.

The application is 3D Printing and I can provide more detail about what I'm doing if necessary. For now, I'm attaching a screenshot of one of my models, showing the typical problem areas.enter image description here

Thanks for any info,

Tom


I'm adding more detail about the overall modelling operation I'm trying to do, in case this helps folks understand what I'm trying to do.

We can think of the models all starting as 0/1 black-and-white (not greyscale) images in Photoshop. They are derived from a variety of sources--drawing/handwriting/calligraphy directly in Photoshop or Painter, done directly on paper (or found in printed materials) then scanned, or as web clippings. They are conditioned in Photoshop and exported as a PNG file.

The PNG file is opened in Inkscape, where the only operation is to convert it to a SVG file. [I'd do this in Photoshop, but I have Photoshop CS6 because it is the last version I was able to purchase, and I don't like renting software. I've tried without success to export SVG from PS CS6.]

The SVG file is imported into Blender. It comes in as a curve, some kind of cubic. I don't know SVG's or Blender's particulars, but it appears to be a collection of cubic splines with interpolated control points each having two control vectors (one for the incoming curve and one for the outgoing). The exact name escapes me--maybe they're Hermite curves? Edit mode shows this.SVG imported into Blender

The example is a handwritten "LR"--someone's initials.

At this point, I'll describe exactly the object I want to produce. Let us consider the imported curves as defining a function g(x, y) where g(x, y) is 1 if the point (x,y) is on or inside the curves, and 0 otherwise. I also have an expansion distance e. I want the solid object h(x, y, z) that is between z = 0 and z = -1, inclusive, where h(x, y, z) = 1 [meaning the point (x,y,z) is in or on the boundary of the solid object] when (x, y) is within Euclidean distance -z*e of another point (x', y') where g(x',y')=1. This is like an extrusion in Z, but with sloped walls (the slope is 1/e) having growing cross-section as the z-coordinate is lowered.

Note that because the given curves can grow near one another or create loops, this is not a simple matter of computing the z=-1 curves and connecting them up to the z=0 curves. Consider the example of g(x,y) being a ring (annulus), like the letter 'O', with the inner radius being e/2. The walls coming from the inner circle of the annulus all meet at z=-1/2, but the walls from the outer circle go all the way to z=-1. In the illustration below, the annulus is at the origin, and below it is the y=0 cross-section of the solid object. On the right is a view of the desired solid object.Annulus example

If I merely computed the z=-1 curves, I'd miss the cone-shaped dimple in the middle of solid.

So to approximate the object I want, I first convert the imported (SVG) curve object to a mesh. This step is a little finicky--I've gotten some buggy results sometimes--but I've found that it seems to behave if the curve is at a decent scale factor, which indicates that "convert to mesh" is sensitive to numerical problems. I keep my Scene's Unit Scale at Metric/0.001, with length in Millimeters, as suggested by some other folks who work with 3D printing.

Next, I scale the mesh to size, which could be anywhere from 15 to 120 millimeters, with a reflection in the X-coordinate. (I'm printing stamps, which need the reverse image.)

This is followed by an extrusion in Z. (If the mesh that "convert to mesh" creates isn't well-formed, it generally makes itself obvious after this step.) In the illustration here, I created the extrusion before the reflection in X. extruded mesh

Next, in edit mode, I select all the bottom vertices and perform a Shrink/Fatten on them, fattening by the desired amount to give my expansion factor (e in the above discussion). Shrink/Fatten supposedly moves vertices an amount along their normal vector. How Blender computes the normal vector of a vertex is a mystery to me. Ideally, I'd like to recompute these vertex normals to have a z-component of 0, and to be a (normalized) average of the normals to the two edges of the z=-1 profile attached to that vertex--in other words, I don't want 3D to play into it at all. Let me know if you know how to accomplish that. A wireframe side view of the fattened object shows that most vertices end up at the same z-coordinate, but some are mysteriously above or below that.side view after shrink/fatten

Now the object is at the point seen in the first image I posted. From here I take the Boolean union of this object with a [truncated] cylinder, roughly as shown below. union with cylinder

I export this from blender as an STL file, open it in Cura, then slice and print. The printed object is used as a stamp for wet clay. The physical properties of wet clay, glaze, and plastic dictate the need for the sloped walls of the stamp.

Cura has been complaining about the STL files I've been giving it and refusing to slice them. The objects it is being given (result of the boolean union) are not well-formed. I've tried all combinations of the Self Intersection and Hole Tolerant options to no avail. So I'm presuming that the Boolean operation needs a well-formed 3D manifold to perform well (GIGO, after all). It seems to me the easiest way to get a manifold version of the object I get from Shrink/Fatten is to take the upper envelope and somehow seal the bottom, which is why I'm asking. Upper envelope/visible surface determination is a straightforward geometric operation that can be robustly performed on any collection of planar polygons (i.e. on triangles) in 3D with a bit of attention to numerical issues, so I thought it might be available somewhere I haven't looked yet.

I've omitted details not related to the extruded object I want, such as bevelling the cylinder and making a handle for the stamp. I hope this extra detail helps.


Update 2, 2025-07-24: I've decided to bite the bullet and code up my own solution. I'll update and answer my question when I get this done; it may not be for another couple of months (summer vacation is about to happen). I already have the "extrude+expand" operation written and now have only the upper envelope computation remaining.

$\endgroup$
12
  • $\begingroup$ In practice, completely avoiding manual cleanup for intersecting or messy meshes is extremely difficult, and mostly impossible. $\endgroup$ Commented Jul 17 at 0:15
  • $\begingroup$ I don't know what upper envelope is. If there's a pipe, above it empty space, then a perpendicular pipe, the upper envelope would be tops of both pipes, or just what is visible from the top? $\endgroup$ Commented Jul 17 at 6:24
  • $\begingroup$ How this mesh is created? Could it be possible to avoid issues in first place ? For me it looks like the wider bottom is extruted from the narrower top, and that causes the overlap in tighter corners. If it was done other way, the narrower to would be inset of the wider bottom, then the overlapping issues could be solved. $\endgroup$ Commented Jul 17 at 11:46
  • $\begingroup$ Would a voxel remesh operation be an option here? Or is the original mesh too complex for that to work? $\endgroup$ Commented Jul 18 at 20:46
  • $\begingroup$ @HarryMcKenzie Thanks, and I somewhat agree. This is why I proposed a particular way (upper envelope) of dealing with the mess. I've worked with a lot of geometric software, some robust and some not, and I'm looking for the former rather than the latter. $\endgroup$ Commented Jul 19 at 0:01

1 Answer 1

0
$\begingroup$

this is not a full answer, but a proof of a concept that might work: enter image description here

This Geometry Nodes Setup creates a mesh from the input curves. It does it by offsetting the curves along their normal, and moving them downward. Then filling the curves and sides (with a cylinder). enter image description here

The overlapping is avoided by Sampling down the curve we use for offsetting. As a result, the lower shape varies from the upper shape. But based on your description, I believe this shouldn't be an issue.

enter image description here

The "raw" results form the Geometry Nodes are not perfect, but I think it is quite easy to fix them manually. One option would be to separate GN setup to 2 steps, and manually tweak the offset curve, and only after that mesh it. ( I mean that the curve seen in above image, with fewer points would be modified manually) enter image description here

$\endgroup$
1
  • $\begingroup$ Thanks for the detailed approach. I am actually worried about the imprecision in the bottom curve (maybe I'm a bit OCD), and how this approach would handle large reflex angles (like 320+ degrees). I've decided that the pain of learning blender internals and remembering python is probably worth it, and plan to write my own solution. But thanks for your approach--I wasn't aware of the dataflow programming (geometry nodes) facility in blender before. $\endgroup$ Commented Jul 24 at 21:42

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.