5
\$\begingroup\$

enter image description here

I'll let this picture do the talking. I'm trying to create a mesh from a bezier curve and then add a texture to it. The problem here is that the interpolation points along the curve do not increase linearly, so points farther from the control point (near the endpoints) stretch and those in the bend contract, causing the texture to be uneven across the curve, which can be problematic when using a pattern like stripes on a road. How can I determine how far along the curve the vertices actually are so I can give a proper UV coordinate?

EDIT: Allow me to clarify that I'm not talking about the trapezoidal distortion of the roads. That I know is normal and I'm not concerned about. I've updated the image to show more clearly where my concerns are.

Interpolating over the curve I get 10 segments, but each of these 10 segments is not spaced at an equal point along the curve, so I have to account for this in assigning UV data to vertices or else the road texture will stretch/shrink depending on how far apart vertices are at that particular part of the curve.

\$\endgroup\$
5
  • \$\begingroup\$ The problem I'm having is that with, for example, a road texture, the markings on the road are farther apart when they're near the endpoints and closer together when they're near the control point. \$\endgroup\$
    – ssb
    Commented Jun 3, 2014 at 12:32
  • 2
    \$\begingroup\$ It seems the root problem here is sampling the Bezier at equal arc length intervals. \$\endgroup\$
    – Anko
    Commented Jun 3, 2014 at 14:36
  • \$\begingroup\$ I don't know why @KromStern deleted its post, which was the most valuable, not to say it was just the right answer. I deleted my post since, after some small experiments, i proved it completely wrong : approximating one of the trapezoid by a rectangle is impossible when the difference in upper/lower width can be >40% even for a moderate slope with a good amount of polygons. Opsenas and API-Beast 's answers are, for the same reason, not valid either. \$\endgroup\$ Commented Jun 3, 2014 at 19:05
  • \$\begingroup\$ @GameAlchemist Since I use some very similar code for line rendering in my library and it works™ I can say that my answer is pretty valid. \$\endgroup\$
    – API-Beast
    Commented Jun 3, 2014 at 19:37
  • \$\begingroup\$ By 'not valid' i mean that the texture will be stretched in the outer part of the curve if using only one quad per segment. -that will be case also when using one equal lenght segment like Anko suggests- Now if you use enough segments (more than in the O.P.'s image) the artifact might be negligible and the solution perfectly OK. \$\endgroup\$ Commented Jun 4, 2014 at 7:43

2 Answers 2

4
\$\begingroup\$

A line is a list of connected points. For each point you'll need to calculate the X-Texture coordinate of that point, the Y coordinate will always be 0 for the upper point and 1 for the lower point.

After you have defined how long one texture segment is you can do so by stepping through all the segments you have generated and noting how much distance you have covered:

float pos = 0;
float textureLength = 200;
Points[0].TexCoord = 0;
for(int i = 1; i < Points.size(); ++i)
{
    pos += DistanceBetween(Points[i].Position, Points[i-1].Position);
    Points[i].TexCoord = pos / textureLength;
}
\$\endgroup\$
1
\$\begingroup\$

I'd suggest calculating UV according to section size (i guess U value would be constant), you know the size of the section, now calculate how many times road's texture should repeat along each edge (different V for each side according to size) and when you start drawing next section just set minimum values of V coordinate to the result of calculations of previous section.

Vector2 SetupSection(Vertex[6] aVertexes, Vector2 vPrevVValues)
{
    //lets consider that polygons are 0,1,2 and 3,4,5
    //where vertexes 0, 4 and 5 are bottom vertexes and 1, 2 and 3 are top vertexes (or min/max)
    //now lets calculate distance
    float fLeftDistance = (aVertexes[0].Position - aVertexes[1].position).Length();
    float vValue = fLeftDistance / fSizeModifier; //some constant decided by you
    aVertexes[0].v = aVertexes[4].v = vPrevValues.x; //Set left bottom to previous values
    aVertexes[5].v = vPrevValues.y; //set right bot to previous values
    vPrevValues.x += fLeftDistance;
    aVertexes[1].v = vPrevValues.x;

    float fRightDistance = (aVertexes[5].Position - aVertexes[3].position).Length();
    float vValue = fLeftDistance / fSizeModifier;
    vPrevValues.y += vValue;
    aVertexes[2].v = aVertexes[3].v = vPrevValues.y;
    return vPrevValue;//return new V values
}
\$\endgroup\$

You must log in to answer this question.

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