# Curve to Mesh with UVs in Blender 3.x?

How can I use geometry nodes to turn curves into a mesh and create UVs at the same time?

When I use the Curve to Mesh node with a base curve and a profile curve, no UVs are created at all, which means that I subsequently have no way to build a corresponding shader.

In Blender 3.1+ this is apparently not feasible without additional nodes, since the Curve to Mesh only generates a mesh, but no mapping coordinates.

The common method that is discussed in many places creates the UV values on the basis of the points of the curves even before the node Curve to Mesh is applied:

However, this leads to the problem that e.g. cyclic splines are not processed correctly and the mapping is not flexible enough:

The problem becomes even bigger when multiple curves are to be processed simultaneously.

How can I solve this problem and create a constant UV mapping?

The main problem with the common technique of capturing the values per point and then using them as coordinates is that with cyclic splines the end point is the same as the start point, and thus the same value is always used for both face corners at the start and end of the spline.

## Is there a solution?

Yes, you can use a trick that gets around this problem:

By first capturing two values for each point, and after creating the mesh, selecting these values according to the Face Corners.

As an example:

If you have a rectangle (cyclic spline), it has four points. Now you capture the following values:

Value 1 Value 2
Index 0 4 0
Index 1 1 1
Index 2 2 2
Index 3 3 3

The first value corresponds to the face corners that connect to the point, the second value corresponds to the face corners that start from the point.

If you now select the face corners by their orientation after creating the mesh with Curve to Mesh, you can now decide which of the two values should be assigned to the UV Map.

This process is relatively simple, because face corners are always created according to the following pattern:

• Left lower face corner has the index $$0$$
• Right lower face corner has the index $$1$$
• Right upper face corner has the index $$2$$
• Left upper face corner has index $$3$$

If you create a selection using this pattern across the whole mesh, it will look something like this:

(Selection along the base curve)

(Selection along the profile curve)

Both together now generate the selection for the base curve and the profile curve respectively, which either uses the first value of the two previously captured values, or the second.

And the result is then a UV mapping where the last face corners of a cyclic spline are correctly mapped:

## What does the solution look like in detail?

In detail, this solution looks like this:

1. First I capture the values that are interesting for your UV mapping. In this example I do this simply with the index of the splines. But you can use basically any value that should be the basis for your mapping.

Here I first check if it is a cyclic spline and if the first index of the curve point corresponds to the value $$0$$.

Then I capture the previously mentioned values in the point domain with Capture Attribute.

If the index is $$0$$ and it is a cyclic spline, however, I assign the number of points of the spline to this point as the first value. Since an index always starts at $$0$$, the value Point Count can therefore be used directly, which in this case represents the fictitious additional point at the end of the spline.

To store these values conveniently, I use Combine XYZ, because this node lets me capture three values at once (even though we only need two in this example).

I capture these two values per curve, i.e. base curve and profile curve, because both can be cyclic:

2. Then comes the crucial part:

After applying the node Curve to Mesh, a mesh has been created, and thus Faces and Face Corners are available. Starting from the attribute domain Face Corners, a selection is now created in the following image, which, depending on the curve (base curve or profile curve), marks the face corners to which either one or the other value should be assigned (Shown here in the group "U" and "V", U for the base curve, and V for the profile curve):

3. At the end, just apply Curve to Mesh, and pass the generated UV map to a Group Output (Or save it to the geometry with Store Named Attribute):

However, it should be noted that this is done in the attribute domain Face Corner!

So far so good, the result is a node that allows correct texturing in the UV space.

Also, this way, multiple curves can be processed at the same time, allowing you to turn your profiles into a mesh along multiple curves.

I welcome feedback and suggestions for improvement, preferably on Github, where the project can also be found.

This solution works with a few small adjustments from version 3.1, but the blend file provided here is created with 3.4. In addition, the file available here contains a few more interesting functions that additionally allow the generated caps to be recognized and also provided with correct UVs.

On a personal note:

The solution presented here is an excerpt from an even more extensive project available in the Blender Market, which can also handle overlapping profile curves, as well as correct the normals of the generated faces (interesting for letters or other complex shapes):

Open source may be all well and good, but development costs time and money. With your contribution you support new features and further updates. Thank you!

Get the full version here: Curve to Mesh UV - Perfect UVs with Geometry Nodes

A hack, (nothing like as thorough, or general, as @quellenform's answer) for getting over the Geometry Nodes cyclic UV problem is to split your cyclic profile-curves by a tiny amount before conversion to mesh, using Trim Curve. Here, illustrated with a rope:

(Edit: Nowadays, you can trim fully, 0-1, and the split is achieved. I'm fairly sure, when this was written,that didn't work. So now you can trim acyclic and cyclic curves together, without harm.)

Above, the 0-1 Curve Parameter > Factor is stored on the freshly acyclic single-strand profile, and will be the strand V.

The single-strand profile is made into a cluster by instancing on the points of a Mesh Circle:

The whole cluster is scaled by the user to the desired rope-thickness. The strand index in the cluster is stored, for possible use by the shader.

The V from the profile curves, and the U from the incoming path-curve, are combined and output on the mesh face-corners before the seam in the profiles is welded back up:

Welding only end-points of the split profiles means the same operations can be executed whether or not the profiles are cyclic, no need for branching in possible variations of the group.

Passing out the strand index means each strand can be treated separately:

Which could, if you wanted, allow you to give each strand its own portion of the U dimension, to keep them all different, in the shader.

• I want to let you know that this solution gives a better result in my expert opinion, than quellenform's answer. he did write it up extremely well, however it has a major flaw, which is that it can get stretched according to the point density since it relies on the indices. I've come up with and found numerous answers and I wouldn't consider quellenform's answer a proper answer. (I've consider it, but seen it's flaws). still I've got to say idk if I've seen many answers written as well as his. Commented Apr 18, 2023 at 20:18
• Hi, @sumel.. thanks.. very glad this method works for you! I'm still going to call it a hack, though :). I haven't put it through the mill to anything like the extent quellenform has had to, to produce a logically provable, general foundation for a bullet-proof asset. (I've tried quite hard to break his version, no luck yet) I've got a feeling that if this one had to be adjusted for edge-cases, the adjustments would themselves be hacks, and the hole would get gradually deeper :) Commented Apr 19, 2023 at 7:53
• @Robert Betts, to clarify, I don't use this method myself. I've got 2 methods that both work perfectly and are field based (one of them I came up with, and the other was by a friend who when I pointed out a similar issue to what quellenform's has, came up with a solution which is now my favorite and go to.) I was just saying out of the 2 answer on this question, I think (know) yours gives a better result, and is very easy to do (so beginner friendly). Commented Apr 19, 2023 at 8:06
• I'll see if I have time. I was thinking about it. Commented Apr 19, 2023 at 8:25
• @shmuel You can use the spline length instead without any problems if you do not want to align the mapping with the indices. Small change, big effect. Commented Apr 18 at 8:14