4
$\begingroup$

I would very much like to show the normals on a model (vertex, face, split). I am aware how to make them visible in editing mode, where they can be shown as blue, cyan and purple lines (overlay menu).

For educational purposes, I would like to show those normals as fancy arrows, like in the figure below. Is there a simple solution for this?

enter image description here

$\endgroup$
1

3 Answers 3

4
$\begingroup$

Face Normals can be displayed by a Geometry Nodes modifier. Note that the origin of the arrow object should be at the bottom (3D Cursor) so the arrows stick out correctly.

screenshot

The Custom Split Normals and Vertex Normals are not accessible yet in GN in Blender 3.4. There are plans to add them (at least the Custom Split Normals) as you can read here: https://devtalk.blender.org/t/custom-split-normals/24642

$\endgroup$
2
  • $\begingroup$ Thank you for your reply! This looks like advanced level usage of blender, which is beyond my skills. $\endgroup$ Nov 13, 2022 at 17:14
  • $\begingroup$ Unfortunately, this method will not work in general. The arrows point into "some" normal direction defined at the vertex of the dual mesh. For less regular shapes, this direction does not necessarily coincide with the normal of the face. This problem dose not occur in the solution given by Nathan. $\endgroup$
    – p6majo
    Apr 1 at 13:50
4
$\begingroup$

We can do this with geometry nodes, with a few tricks involved. We'll start with an no-subdiv icosphere like you have. We have no custom normals on this (we'll get to those in a bit.) We'll start with face normals.

enter image description here

There's actually more than one kind of face normal in Blender. Because quads and ngons can be non-planar, they can have their own face normals that are different than their triangulated normals. Here, I'm assuming you want the triangulated face normals, and we're starting by triangulating the mesh (even though in the case of our icosphere, it's already triangulated.) The nodes are pretty simple; we just turn our faces to points, align with the nearest normal, and instance our arrow mesh. Testing it out, the domain of "face" normals seems to be set by choosing "faces" in the mesh-to-points node.

We'll group that and move on to vertex normals. It wouldn't make any sense to show vertex normals in the middle of our faces; the interpolated vertex normal there is (right now) the same as the face normal. So instead, we'll instance these onto the vertices:

enter image description here

You can see this is roughly the same structure, except we're instancing on our vertices, making it point domain data.

Custom normals are where we have to get tricky. First, of course, we're going to need an arrow for every face-corner; additionally, there's little GN support for direct use of custom normals, so we'll have to hack it.

Rather than instancing on our previous object, I'm going to make a linked duplicate, autosmooth it, and then start from scratch with modifiers:

enter image description here

So what are we doing here?

  1. Edge splitting all edges creates a unique vertex for every face-corner, which can receive its own custom normal and can spawn a new instance;

  2. Our data transfer modifier creates the face-corner custom normals (it can target a hidden copy of the mesh if you'd like). Here, I'm copying normals from the wireframe Suzanne;

  3. We make an attribute to back up our current position;

  4. We do a constant displacement in the direction of custom normals.

At this point, we can find the custom normal of the vertex very easily, by simply subtracting its position from its old position (it's a unit-length displacement). We can also restore our original position very easily.

enter image description here

Shown with other object at the same time. We're figuring out our custom normal by subtract posBack from position rather than using a Normal node. Note that we're transforming our instances by -1 in their Z axis to counteract our displacement. Otherwise, this is the same thing as our vertex normals. We're not joining to our original geometry, just outputting the arrows, because we intend to use this object in conjunction with our other object, and because our original geometry is no longer much like the icosphere with which we started :)

Finally, we can enable cage display on all modifiers, parent both the source of our custom normals and our custom normal display to our object that displays face and vertex normals, and we can make any edits to the original object (or, to our source of normals) to see them displayed, in real time:

enter image description here

In your question's image, you're using 3 arrows for each normal. We could easily use a set of 3 arrows instead of a single one for each instance. However, what we can't do, is align those with a UV tangent vector. So we can't use this to, for example, demonstrate tangent space. It would be nice if there was some way to get UV tangents into geometry nodes, but that's life.

$\endgroup$
1
$\begingroup$

Instancing

Blunder's answer is quite fine and really not that difficult, you should try it. This can't be said for Nathan's answer, which is amazing but definitely advanced.

Here's my attempt to make it as easy as possible:

Create your gizmo, make sure it's aligned to axes:

Now select this gizmo, then select another object. The order is important, because the last selected object becomes active. Press ✲ CtrlP to parent the gizmo to that (active) object.

Then in Object Properties enable instancing:

💡 Keep in mind a normal is a single vector - represented by the blue bar; the direction of green and red bars is arbitrary (there is a logic behind where they point, but it's not of much value, and could be changed in future versions of Blender).

$\endgroup$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .