Note: After a little bit of tinkering I got a new geometry node in Blender that makes this very easy to implement: https://docs.blender.org/manual/en/dev/modeling/geometry_nodes/mesh/topology/corners_of_edge.html

It will be in 4.0 an combined with a face of corner is equal to a Faces of Edge node.


I am wondering if it is possible to retrieve the Faces of an Edge in Geometry nodes. The topology nodes sadly don't have a fitting node. In this example image I want to get the indexes (later normals) from the edge.

enter image description here

I thought combining some topology nodes together and comparing would work, but things would get complicated very fast. Maybe someone has an idea for a simpler solution.

EDIT: I should have make the question more clear. I dont wont the faces of an specific edge. I want a general node, to receice the indexes, like the answeres from @Markus von Broady @Robin Betts. Though i think my question was to vague of what I wanted to achieve, so the other answeres are perfectly solutions.

Also I just wanted it for Quads and Triangles.

  • 1
    $\begingroup$ This is an annoying and interesting limitation of geonodes (alongside lack of loops): in a normal programming language, using the existing functions (nodes), you would take index of the edge, and then use first vertex index of "Edge Vertices", then use "corners of vertex" by giving corners weight based on the next or previous corner ("Offset corner") belonging to an edge (skipping some logic here) of the same index as the one taken at the beginning of this explanation. But here, you can't control from which context you're sampling data, and so you can't compare data across contexts… $\endgroup$ Apr 24, 2023 at 16:58
  • 1
    $\begingroup$ I think it's a design flaw of geometry nodes, that context changes aren't denoted by frames encompassing different contexts… $\endgroup$ Apr 24, 2023 at 16:58
  • 1
    $\begingroup$ @MarkusvonBroady, Scooby Doo would have preferred Animation Nodes $\endgroup$
    – lemon
    Apr 24, 2023 at 17:04

4 Answers 4


Blender 4.0+

As already mentioned in the comments, the solution for current Blender versions is as follows:

The Corners of Edge node returns (in the case that the edge is connected to two faces) the index of the face corner of the adjacent faces selected with Sort Index:

(Image from the official documentation)

The Face of Corner node uses this index to select the respective face.

In this example, I save the index of both adjacent faces in X and Y of a vector for convenient further processing.

Blender 3.6 or below

As I see it, this is only a question of the correct interpolation between the attribute domains.

If you want to select the two faces connected with an edge, then you can solve this as follows:

  1. Select the desired edge and capture this selection with Capture Attribute as a float value in the domain Edge.
  2. Then interpolate from the domain Face Corner to Faces (the previously stored selection in Edge is transferred to Face Corner, and then to the domain Face) and store this value also in the domain Face.

Finally, you can use this selection (only two faces are selected) to fetch the corresponding values from these faces.

You can do this, for example, by separating the faces with this selection and Separate Geometry, and then fetching them from there with Sample Index (index $0$ and $1$):


The solutions shown above are funny when it comes to finding out only one edge and its adjacent faces.

But what if you want to get the adjacent faces for all edges of a mesh, i.e. do exactly what you would expect from a non-existing node Faces of Edge?

Then the task becomes a lot more fun and the solution might look something like this:

The trick here is that the node Edge Angle fortunately gives you back the signed angle of an edge. This value is somewhere between $-180°$ and $180°$.

An angle of $0°$ means that the two adjacent faces are planar, an angle greater than $0°$ means that the two faces are convex, and an angle less than $0°$ means that the faces are concave.

Now by mapping this angle into a range of $90° - 180°$ (without Clamp), I get the bisected angle between the two faces.

If I now rotate the normal of an edge (which already represents the interpolated direction of the normals of both faces) with the direction vector of the edge as the Axis with this angle, this resulting vector is always exactly perpendicular to the normals of one of the two faces.

And now I simply sample the closest face and use exactly this vector scaled with a very small value like $0.000001$ and added to the position of the respective edge as Sample Position. Since an edge has at least one face (hopefully), I repeat this with the inverted angle as well.

In this way I can relatively reliably determine per edge the indices of both adjacent faces (and consequently also the normals of these faces).

Finally, I save these two indices into a 2D Vector called "faces_of_edge" to make them easily reusable.

...of course this solution works only for meshes whose edges have a maximum of two faces.

Ah, and by the way: This solution can theoretically be adapted from version 3.1 (not tested), which is also cool.

  • $\begingroup$ Simplicity itself: I think I may have answered a question that wasn't asked... again :) $\endgroup$
    – Robin Betts
    Apr 25, 2023 at 9:44
  • 1
    $\begingroup$ @RobinBetts Even if the question was not asked: I think you have answered it wonderfully. ;-) $\endgroup$
    – quellenform
    Apr 25, 2023 at 9:48
  • $\begingroup$ Oh damn, I'm joining R.B. If this question wasn't accepted, I would be sure this is not what the OP wanted. He actually wanted faces for a single edge. I wonder how many times I have made a similar mistake in the past. In general I think I'm quite bad at understanding questions. $\endgroup$ Apr 25, 2023 at 13:42

This approach assumes that there are 1 or 2 faces per edge, and stores the 1 or 2 adjacent-face indices as attributes on edges.

The strategy:

  • Capture face and edge indices, then split edges.
  • Accumulate face indices, grouped by captured edge index.
  • The 'Leading' output of Accumulate Field is the index of the first face of the edge.
  • If 'Leading' and 'Total' are equal, there is no second face.
  • Else the second face index is 'Total' minus 'Leading'.
  • The group captures the 'Face 1' and 'Face 2' indices on edges, with non-existent second-face indices represented as -1.

Edit: Although the sorting by Accumulate Field has worked without error in tests, the red +1 and -1 nodes have been added to shift and unshift face-indices, to avoid any possible ambiguity between 'face-index 0' and 'absence-of-face'.

enter image description here

  • $\begingroup$ Hmmm, have you tested it? It's late so I'm allowed to be blind, but it seems you're sampling by index of the original edge, the split edges - but the indices can't possibly match. $\endgroup$ Apr 24, 2023 at 22:29
  • $\begingroup$ @MarkusvonBroady Your apprentice has let loose his inner sadist and tortured many monkeys in the service of this node group, and is yet to find an example in which the captured edge-index is not preserved, or duplicated to both edges resulting from its split. But I guess proof would require a consultation of The Source. $\endgroup$
    – Robin Betts
    Apr 25, 2023 at 8:09
  • $\begingroup$ But you're right, for safety I should be using the captured index to transfer. This group relies on the dupe edges being piled up after the original, intact, ordered list, by the split operation. Saving spaghetti was a bad motive. EDITED, $\endgroup$
    – Robin Betts
    Apr 25, 2023 at 8:22
  • 2
    $\begingroup$ I'm happy my lack of understanding improved your understanding… Apparently I misread your node setup as i.imgur.com/17aU53R.png but it was the other way around. What confused me was perceiving your setup through a prism of mine, but your clever strategy is to sample the first split edge and see which face it ended up with, and use subtraction to get the other face index otherwise. Alright, so now I understand, time to investigate what quellenform came up with... And to future visitors, check out the first version as well. $\endgroup$ Apr 25, 2023 at 13:31
  • 1
    $\begingroup$ @RobinBetts After further investigation, it wasnt something wrong with your tree. I had problems with the Viewer node. But when using the calculation for example in a delete geometry node everything was fine. I think the viewer node has problems, displaying on some domains. $\endgroup$
    – soerensc_
    Apr 25, 2023 at 15:07

In the ancient times there were no topology nodes, and so we were creating mappings, where elements were repositioned based on their attributes, and then they could be sampled based on those attributes, because sampling by position is an option.

So let's say you want to randomize face colors to clearly show different faces, but since some neighboring faces may end up with a similar color, you want to put a wireframe on the edges - but in order to be performant, you want the wireframe to be present ONLY between similar colors:

  1. Capture Edge index
  2. Split edges.
  3. Convert edges to points. These points will keep the properties of edges like the col attribute, even though it was captured in face domain.
  4. Position those points on x = original edge index (the one captured) and y = index of the face of this edge. This way you can sample not just by the edge index, but by a combination of original edge index and which face this edge was assigned to during splitting.
  5. To get the face index of an edge, just count using Accumulate Field node, whenever you hit an edge that you already processed, increase the counter of that edge.
  6. Now create the wireframe by removing all edges from the original geometry, for which the neighboring colors are too different. So sample the split edges using edge index as X, and either 0 or 1 as Y (either first or 2nd face of the edge). Then delete the faces (I don't know why you have to delete faces, it bugs out otherwise), to curves, bevel curves, join with original geo.

Just to be clear: it works for more than 2 faces as well. For example, if you find it pointless to separate two faces of similar color with a wireframe, when it's already separated by a third face, you can just check for the existence of that 3rd face:

  • $\begingroup$ Jeeez ... what wizardry is this? $\endgroup$
    – Robin Betts
    Apr 24, 2023 at 22:14
  • $\begingroup$ @RobinBetts nothing you wouldn't do plenty of times 😜 $\endgroup$ Apr 24, 2023 at 22:32
  • $\begingroup$ Thanks this worked (: $\endgroup$
    – soerensc_
    Apr 25, 2023 at 11:58

My approach was to scan the corners of all the faces and use edges of corners to match the edge index. Adjacent Edge node group

The flaw is that it only works on quad faces so I understand I probably don't qualify for the bounty. I may have time to look at my selection method more closely tomorrow.

  • $\begingroup$ A clarification: it works well on faces with 3 or 4 edges but will fail when selecting an edge between faces that have an edge count > 4. $\endgroup$ Apr 24, 2023 at 16:25
  • $\begingroup$ thanks for the answer, sadly not directly what i looked for. $\endgroup$
    – soerensc_
    Apr 25, 2023 at 15:11

You must log in to answer this question.

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