11
$\begingroup$

I want the quads in my mesh to be planar, or flat, that is, the 4 points of the quad could all be on the same plane. Or in other words, they need only x and y values to describe their "local" position.

Difficult part is if you do it to one face, the vertices shared by neighbouring faces get transformed which makes them non-planar...

Doing Mesh-> Cleanup-> Make Planar Faces on all faces doesn't work right. Every time you apply it the mesh visibly changes. If it worked the first time it wouldn't change more than once. Besides, the non-planar quads are visible to the eye.

Reason: modelling a low polygon mesh to be converted to individual flat faces in a program called Pepakura and make into a real life sculpture from flat MDF pieces.

Each quad has to be planar ("flat") so I can build this from flat MDF pieces.

Obviously the overall shape of the mesh will change, but not much.

$\endgroup$
  • 1
    $\begingroup$ related: blender.stackexchange.com/questions/2351/… $\endgroup$ – cegaton Feb 1 '16 at 16:09
  • 3
    $\begingroup$ I think the term you are looking for is Planar. $\endgroup$ – PGmath Feb 1 '16 at 16:24
  • $\begingroup$ The script in the linked topic might be useful for papercraft, not wood or similar material, because you can fold paper, but for wood each face has to be separate. Also, with a program like Pepakura you can move around those separated faces to use your sheet of whatever material you use more economically. $\endgroup$ – Leo Ervin Feb 1 '16 at 16:57
  • 2
    $\begingroup$ Share the model to encourage us to look at automated approaches. $\endgroup$ – zeffii Feb 3 '16 at 16:57
  • 2
    $\begingroup$ I just wanted to comment that all answers are great ones and recommend anyone interested in this to read all of them as each has something unique to teach. That said please give me some time to decide which one to accept and which one to give the bounty. Again, all contain valuable information. $\endgroup$ – Leo Ervin Feb 5 '16 at 21:39
4
$\begingroup$

This is a completely different method. It is more manual work but will give you 100% planar ngons.

In short: split all your faces. Scale each of them along their normal to 0. This will make them planar. Join them back again using booleans.

Split your mesh: Go into edit mode. Go to mesh select mode faces. Select all faces, press spacebar and type "edge split". Now you should be able to move one face without it dragging the others with it.

separated faces

Set your Transform orientation to "Normal". Scale it along it's normal to 0: hit Szz0Enter. Scale it up five times or so: hit S5Enter.

planar face

Extrude it some: hit e5Enter. Recalculate normals: hit Ctrl+N. Split this box into a new object: hit P and select "Selection".

building box

Do the same for another face but extrude it the other way.

subtractive face

Subtract the second from the first:

boolean subtraction

You can also use intersection:

boolean intersection

Continue with more faces:

more faces

By now, the central crossing of these four faces have produced two vertices. If you don't want this. Slide one of them into the other.

You probably want to use the mirror modifier to reduce the work by half.

$\endgroup$
  • $\begingroup$ Genius. I think Blender devs could make this into an automated script/part of Blender if they found this. $\endgroup$ – Leo Ervin Feb 4 '16 at 10:03
  • $\begingroup$ Thanks. :-) You can experiment with scaling them along normal Z all at once if you use Pivot center around "Individual origins". It could make reduce the workload. $\endgroup$ – Gunslinger Feb 4 '16 at 10:12
  • $\begingroup$ Come to think of it I think this is what Jerryno meant when he said he could write a script for making faces planar. I'll wait and see if he replies to my comment or does that. $\endgroup$ – Leo Ervin Feb 4 '16 at 10:33
  • 1
    $\begingroup$ @LeoErvin Yes this is it but just manual method. It's the chiseling from solid by planes from face normals. Didn't had much time last 2 days but it will be weekend so I'll look into it again. $\endgroup$ – Jaroslav Jerryno Novotny Feb 5 '16 at 12:33
12
+100
$\begingroup$

First thing first: How to check for non planar faces and amount of their distortion:

enter image description here

Second thing: How to make them planar?

There is no way to make them all planar without changing overall shape of the mesh a lot or the topology. Here is why:

To make faces planar, we need to move the vertices. So for each vertex we will see all the faces around it, get their normals, from each of these normals construct a plane and where those planes intersect store a new vertex. From all these new vertices then make a new mesh with the same topology and switch it for the old one. Very simple, but it has one catch: when a vertex has more than 3 surrounding faces, their planar intersection does not necessarily exist - it would be actually very rate if it did:

enter image description here

To meet them at single point, some plane translation is inevitable and depending on the angles this translation can be huge and ruin the shape of object.

So to create mesh from these intersecting planes (made from normals of faces) one would have to create a different mesh with a totally new topology, different vertex count (depending on the mesh shape) by basically chiseling a solid with these planes (would you accept this solution?).

The other solution is not exact and is an iterative approach to a solution. This solution Blender offers under Mesh > Cleanup > Make Planar Faces. We call these iterative methods to a solution Numerical methods. Each numeric method (which is an algorithm) has it's stability. Making faces planar is in general a very unstable algorithm. You may find your mesh oscillating between different shapes never closing on a solution or vertices getting very far from their original location sliding away to infinity - also never closing on a solution. What will happen depends on the mesh shape and you may actually find meshes that this approach solves and converges to a single solution.

But usually it's best to apply this operator not on the entire mesh, but only to selected parts that you know will solve. That's also why the operator has limited iterations to 200 - if it does not converge in that many steps it's very unlikely it will converge in more.

So to make a mesh from planar faces one must start from the beginning:

$\endgroup$
  • $\begingroup$ I appreciate the explanation of how to create a mesh planar and the explanation of why its best to do so from the beginning, but would you please add to the answer how to make all faces of a mesh planar, even if it will change the shape "a lot"? Because the latter is subjective as well as depends on the individual model. $\endgroup$ – Leo Ervin Feb 3 '16 at 20:57
  • 1
    $\begingroup$ @LeoErvin "A lot" means the model is not guaranteed to look the same after the process. The only process that would work is that chiseling from a solid. Is this something you want? If yes I can make a script to do that. $\endgroup$ – Jaroslav Jerryno Novotny Feb 3 '16 at 22:34
  • $\begingroup$ It's not a problem if it looks different for me, and I believe for most papercraft models. Papercraft models are already very lowpoly and not very accurate/precise by nature. But I don't think I undertsand what you mean by "chiseling from a solid", sorry. I've uploaded my model if that helps explain what you mean by that differently. Thank you for offering to write a script. $\endgroup$ – Leo Ervin Feb 3 '16 at 22:53
  • $\begingroup$ Jerryno, please make the script when you get the time. $\endgroup$ – Leo Ervin Feb 8 '16 at 17:35
  • $\begingroup$ @LeoErvin I did code for couple hours through weekend but it's not finished yet. There are couple difficulties yet to overcome: solving edges that have only one face (= open ends of mesh) and solving cavities in the mesh. I am not sure it will give better results than manual method of Leon Chung on open mesh, but for closed meshes it should be the best solution. $\endgroup$ – Jaroslav Jerryno Novotny Feb 8 '16 at 17:50
5
$\begingroup$

"Make planar faces" works with iterations. Each iteration only affects the non-planar faces a tiny amount.

This is with 1 iteration:

iteration-1

And this is with 200 iterations:

iteration-200

Quite a difference huh? But the cube was very distorted in the first place. I hade to apply the "Make planar faces" like 6 times before it was done.

What I think you should try is crank the iteration setting up to max. If your faces are almost planar already, it will flatten out after a while. It does for me when used on a real case (the cube was not).

$\endgroup$
  • $\begingroup$ Thanks for the answer, but there's one issue here: there's no way as far as I can tell to know when the faces are planar and when you can stop applying that operator. Visually you can make a guess but you can't know if you guessed correctly. $\endgroup$ – Leo Ervin Feb 3 '16 at 21:00
  • $\begingroup$ @LeoErvin You can check that with distortion visualization, but the main problem is that vertices slide away from their original location a lot (which is also what happened here) $\endgroup$ – Jaroslav Jerryno Novotny Feb 4 '16 at 8:23
  • $\begingroup$ Isn't the distortion visualization also depending on visual representation (darkest blue being less and red being the most?) which is enough to make a guess but not know? $\endgroup$ – Leo Ervin Feb 4 '16 at 8:25
  • $\begingroup$ @LeoErvin You can set the threshold to for instance 0.001 degrees. Is that good enough? $\endgroup$ – Gunslinger Feb 4 '16 at 8:57
  • $\begingroup$ Sorry, what I mean is here you have to rely on visual preception too. I mean first you have to assume the faces are indeed the same shade of dark blue as it seems to your eyes. I guess you could do a screencap and open in your 2d editor and use a color picker on each face, but even then if there are 0-255 shades and 0.001-x degrees doesn't Blender make an approximation when drawing the angle as a color already? $\endgroup$ – Leo Ervin Feb 4 '16 at 9:03
3
$\begingroup$

Here is a a demo video to show how I did it.

First, you have to admit that nothing is perfect. It totally depends on how accurate you want.

As Gunslinger mentioned, there is already a build-in operation called Make Planar Faces in Mesh > Clean up menu. However, if the result is not as good as expected by taking more iterations, there is a spin-off from this post.

Here is a way to make it happen in a few minutes by using it (combined with other operations of course), not so effective, but seems to be the only affordable way to get the most accurate result:

Download the attached addon, which is the same as the one in the post above. Install. Then follow steps below:

  1. Delete one side of the model, luckily this is a symetrical mesh, it is enough to edit half of it, then mirror it for the other side.
  2. Select all vertices on a quad IN TURN (you have to do this right clicking on each verts instead of using tools like border select or cicle select). This first quad should be around the center of the topology structure (eye in this case, you'll realize why I recommend to do so later). Then click Coplanar by 3 Verts button in Mesh Tools panel in Tool tab. In the option below, set Reference Plane to First, which mean taking the first three selected vertices to define the reference plane.
  3. Then select two vertices on either edge first, then select one adjacent quad which shares the same edge with this quad, then repeat step 2.
  4. Repeat it until you finish this operation on every quad. Now, all quads should be "perfectly" planar. (Note that you have to avoid re-touching all polygons that have been tweaked, otherwise the distortion will be distributed back!)
  5. To check it, there are generally three ways in Edit Mode:

    • Select all polygons then use Mesh > Clean up > Split Non-Planar Faces (or find it in Spacebar searcher), set Max Angle to 0.001 in the option panel, which is the smallest accepted value (0 means to split all quads or ngons no matter what). If no quads splitted, then congratulations.

    • In Properties sidebar (N panel), toggle Mesh Analysis panel, then set Type to Distortion. set the min angle to 0°, and the second angle to a very small degree like 0.1° (values smaller than that will not that helpful here anyway). If all quads appear as dark blue identically, then congratulations.

    • Go to File > User Preferences... > Add-ons, enable 3D Print Toolbox addon. Find 3D Printing tab in tool sidebar (T panel), click Distorted under Checks section, while keepting the degree value 0 as default. If any non-flat polygons found, You'll see the check result in Output Section Below, click that button will select all non-flat faces so you can see where further tweaks needed. If it shows 0, then congratulations. This is the most recommended way for final check.

However, not all cases can be done by this solution. Your case got some luck because:

  1. it is an open mesh (not solid);
  2. it is symetrical (make it more affordable for manual tweaking);
  3. it has a relatively simple topology;
  4. there are a few triangles, which can be used to make adjacent quads happy if you have to.

However, more tweaks have to be taken for fine tuning (mainly for avoiding distortion happening again while mirroring).

Example file:

Script used (run it in Text Editor, or save as .py file then install as addon):

bl_info = {
    "name": "Coplanar by 3 Verts",
    "author": "NirenYang[BlenderCN]",
    "version": (0, 1),
    "blender": (2, 75, 5),
    "location": "3d view - toolbar",
    "description": "Make vertices coplanar using a plane defined by the first/last three selected verts.",
    "warning": "",
    "wiki_url": "",
    "tracker_url": "",
    "category": "mesh",
}

import bpy import bmesh from mathutils.geometry import intersect_line_plane, distance_point_to_plane, normal

enum_ref = [( 'first', 'First', 'Defined by the first three selected verts' ), ( 'last', 'Last', 'Defined by the last three selected verts' )] class MESH_OT_3points_flat_trim(bpy.types.Operator): """ Manually pick three vertices to define the reference plane """ bl_idname = 'mesh.3points_flat_trim' bl_label = 'Coplanar by 3 Verts' bl_options = {'REGISTER', 'UNDO'}

ref_order = bpy.props.EnumProperty(name='Refferece Plane', description='Use the first/last three selected vertices to define the reference plane', items=enum_ref, default="last") filter_distance = bpy.props.FloatProperty(name='Filter Distance', description='Only affects vertices further than this distance', default=0.0, precision=3, min=0.0) @classmethod def poll(cls, context): obj = context.active_object return (obj and obj.type == 'MESH') def execute(self, context): C = context D = bpy.data ob = C.active_object #if bpy.app.debug != True: # bpy.app.debug = True # if C.active_object.show_extra_indices != True: # C.active_object.show_extra_indices = True if ob.mode == 'OBJECT': me = C.object.data bm = bmesh.new() bm.from_mesh(me) else: obj = C.edit_object me = obj.data bm = bmesh.from_edit_mesh(me) bm.select_history.validate() if len(bm.select_history) < 3: self.report({'INFO'}, 'Pick three vertices first') return {'CANCELLED'} points3Index = [] points3 = [] _ordering = bm.select_history if self.ref_order=="first" else list(bm.select_history)[::-1] for i in _ordering: if len(points3) >= 3: break elif isinstance(i, bmesh.types.BMVert): points3.append(i.co) points3Index.append(i.index) print(points3Index) if len(points3) < 3: self.report({'INFO'}, 'at least three vertices are needed to be selected') return {'CANCELLED'} points3Normal = normal(*points3) for v in bm.verts: if v.select and v.index not in points3Index: _move = True if self.filter_distance > 0.0: _move = abs(distance_point_to_plane(v.co, points3[0], points3Normal)) < self.filter_distance if _move == True: v.co = intersect_line_plane(v.co, v.co+points3Normal, points3[0], points3Normal) if ob.mode == 'OBJECT': bm.to_mesh(me) bm.free() else: bmesh.update_edit_mesh(me, True) return {'FINISHED'} def menu_func_MESH_OT_3points_flat_trim(self, context): self.layout.operator(MESH_OT_3points_flat_trim.bl_idname, text=MESH_OT_3points_flat_trim.bl_label) def register(): bpy.utils.register_class(MESH_OT_3points_flat_trim) bpy.types.VIEW3D_PT_tools_meshedit.append(menu_func_MESH_OT_3points_flat_trim) def unregister(): bpy.types.VIEW3D_PT_tools_meshedit.remove(menu_func_MESH_OT_3points_flat_trim) bpy.utils.unregister_class(MESH_OT_3points_flat_trim) if __name__ == "__main__": register()
$\endgroup$
  • $\begingroup$ Thank you, I've upvoted the answer, but to be honest I'm confused what it does. From what I understood and correct me if I'm wrong it makes almost ("perfectly") planar faces? So does it do the same as Clenup->Make Planaer Faces if you run the latter dozens of times, or does it do anything more than that? Because if there's some manual selections need to be done I don't see the advantage. $\endgroup$ – Leo Ervin Feb 5 '16 at 10:46
  • $\begingroup$ I know, it can be hard to understand literally, I'll try make a video to show what I did it. "Almost perfectly" means that although I believe there is no absolutely perfect thing existing even in digital 3D world, it can be much much more accrurate than using the built-in operation. You can test it by either of the three ways I suggested above. $\endgroup$ – Leon Cheung Feb 5 '16 at 10:56
  • $\begingroup$ I've uploaded a demo video link, to show the details. Hope it helps. $\endgroup$ – Leon Cheung Feb 5 '16 at 12:23
  • $\begingroup$ To step 4: This is not guaranteed as usually closed meshes cannot be solved to have all faces planar. What you are doing is only distributing the distortion to some place else. $\endgroup$ – Jaroslav Jerryno Novotny Feb 5 '16 at 13:13
  • $\begingroup$ @Jerryno I've stressed in the answer that this mesh got some luck partially because it is open. Second, actually it is possible to avoid distributing distortions to the polygons that have been tweaked, please check the video link to see what I did. (probably I should complement a bit to that part) $\endgroup$ – Leon Cheung Feb 5 '16 at 13:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.