Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
UV mapping improvements (code included!)
#1
N-gon SPMBs in Curvy use very simple approach to UV mapping in their Absolute mode (it's hard to see any use for Stretch V modes we we'll ignore them here):
  • U coordinate of every vertex is simply StartMeshInfo.EdgeUV[E.vertexIndex[ev]].x, which basically gives you planar mapping projected from above 
  • V coordinates (UV tile height) depend on arbitrary world space length from UVParameter (dubbed "Step width" in the inspector)
There are few issues arising from that:
  • You can't really use maps with detail because detail will never be uniformly applied across extruded N-gon loops (being projected from above)
  • Artists have to do non-obvious manual adjustment of "Step width" (UV tile height) parameter for every given N-gon radius if they want to avoid stretching of texels
  • You can't reuse textures if you want to get uniform texel densities across multiple extrusions of different radius, because any radius always receives whole 0-1 U space
Here is an illustration of the first issue (all static images from here on are clickable for high-res original):

[Image: Xg5WuvYl.jpg]

It's actually quite easy to solve all those issues with a few simple changes to SPMB code.

1. Making planar mapping proportional. It's reasonable to assume that people usually want their texels to be uniform. Even if we're using planar projection, topmost and bottommost areas of the extrusion, where planar distortion is the least apparent, should ideally have neat square texels. Well, that should be easy to achieve: with planar mapping from above, all you have to do is take the extrusion radius into account. First, calculate the new multiplier in the Extrude method of SplinePathMeshBuilder (let's call it uvParameterWidth for consistency with tile height multiplier).

Code:
float uvParameterWidth = (CapWidth * 2f) / UVParameter;

And then apply it when UVs are assigned:

Code:
mUV[vIndex + ev] = new Vector2(StartMeshInfo.EdgeUV[E.vertexIndex[ev]].x * UVParameterWidth, vcoord);

Voila, texels on topmost and bottommost areas of extrusion are always proportionally scaled. And by modifying the "Step Width" (it should really be renamed to UV tile height or something to avoid confusion, though) we can now achieve consistent texel density across multiple extrusions of different radius, thanks to U coordinate not being invariably stretched from 0 to 1 across any radius. Just input the same "Step Width" to any number of splines, and no matter their radius, they will look consistent with no need for additional input.

[Image: 7dgY3TL.gif]


2. Ditching planar mapping. Ideally, though, there should be an option for wrap-around mapping where U coordinate is determined by the loop vertex index divided by the loop vertex count. There are two ways to implement it. To avoid removing planar mapping (maybe it's useful to someone) I simply added another entry to the MeshUV enum called AbsoluteWrapped. Then I check for it in the aforementioned Extrude method and do this:

Code:
mUV[vIndex + ev] = new Vector2 (((float) ev / (float) E.vertexCount), vcoord);

Of course, we still want the texels to be uniform, so we have to find a way to scale U (vcoord) proportionately. Obviously, that can be done by calculating circumference of the extrusion. Assuming our N-gon is closer to a circle, it's 6.28f * CapWidth. Just as vcoord, there is no point in calculating circumeference at each ev index, so do that outside of ev for loop, right under vcoord, and then apply it:

Code:
mUV[vIndex + ev] = new Vector2 (((float) ev / (float) E.vertexCount), vcoord / circumference);

And voila, we no longer have awful stretching on the sides:

[Image: KAHnokPl.jpg]

There is only one problem, though: Curvy is not generating two vertices at the edge loop end, which makes it impossible to use a UV seam and forces a texture to wrap backward to 0 on the very last face:

[Image: iJZloltl.jpg]

I'm not familiar enough with the Curvy code to jam an additional vertex into the loops - I don't know how to do it and I'm fairly sure you are using the size of the vertex array as a stand-in for expected side count, so that change might break something. So, that would be my feature request - add a duplicate last vertex to the end of N-gon loops (and rectangles, I guess). That's how all pipes and wires in the world are usually textured, they have a duplicate edge running across all length, allowing you to start and end your UV island at any U coordinate without any inconvenient stretching.

And while that's not in place, there is a workaround. Instead of using whole tile horizontally over the circumference, use half the tile and start traversing U backwards as you cross half the indexes in a loop:

Code:
if ((float) ev < (float) E.vertexCount / 2f) 
    mUV[vIndex + ev] = new Vector2 (((float) ev / (float) E.vertexCount), vcoord / circumference);
else 
    mUV[vIndex + ev] = new Vector2 (((float)(E.vertexCount - ev) / (float) E.vertexCount), vcoord / circumference);

That will give you two mirror seams on the topmost and bottommost edges of the extrusion, but it will look tolerable:

[Image: 0CZucMnl.jpg]

_____________________________

Feel free to use those changes anywhere and pretty please, change the implementation of extrusion loops by adding an aforementioned additional vertex that can enable UV seams. Smile

P.S.: Here is the UV grid texture if anyone needs it: http://i.imgur.com/mMXpWQj.png
Reply
#2
As already said by mail, those additions will find their way into Curvy 2.

Nice grid texture you have there, I must say! It's quite useful and even better than the ones I've included in Curvy 2, so I'd like to use it instead of mine if possible. Is this your personal texture? Is it from any other package or 3D modeller? Or, in other words, what license applies to that picture?

Thanks,
Jake
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Permission to publish custom CGModule source code? Apelsin 6 9,422 09-15-2022, 08:53 PM
Last Post: Josaf Tom
  Import/Export, Spline from code Mos Def 4 783 02-14-2022, 11:42 AM
Last Post: _Aka_
  Code snippet to automatically set UV Edge to true _Aka_ 0 13 12-20-2021, 04:29 PM
Last Post: _Aka_
  Updating old movement code Maltakreuz 3 2,343 08-18-2020, 04:49 PM
Last Post: _Aka_

Forum Jump: