<p>UV or barycentric coordinates represent a point on a triangle as a weighted average of the three vertexes. You can use those coordinates to smoothly interpolate any value over the triangle, like texture coordinates or the normal vector. So think of it like a two-step process. We map the world coordinates of the intersection point to uv coordinates in "triangle space", and then use those to map to another space, in this case "texture space". Your ray hits triangle ABC and you determine the uv coordinates of the intersection point, let's say (0.3, 0.5, 0.2). Intuitively, we're sort of saying the intersection point is 30% A, 50% B, and 20% C. Each vertex would have a texture coordinate, i.e. a pixel in the texture image, associated with it (that's part of modeling / setting up your scene, not something calculated at runtime). Mix the texture coordinates at A, B and C in that ratio and you'll get the point on the texture image associated with that point on the triangle.</p>

<p><a href="https://www.scratchapixel.com/lessons/3d-basic-rendering/ray-tracing-rendering-a-triangle/barycentric-coordinates" rel="nofollow noreferrer">This scratchapixel page</a> has some good diagrams and clear explanation.</p>

<p>edit: I'm sorry, I missed the part about how to calculate the coordinates in the first place. The page I linked explains it better than I could anyway.</p>

CC BY-SA 4.0
2018-06-27T20:35:02.033Z
2018-06-27T20:45:02.697Z
2018-06-27T20:45:02.697Z
Phil McLaughlin
<p>Below is a triangle with its vertices and uv coordinates. These are read from
the input model file. </p>

<p>I don't understand why the texture comes in different orientation than the image.</p>

<p><a href="https://i.sstatic.net/GRZtO.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/GRZtO.png" alt="enter image description here"></a> <a href="https://i.sstatic.net/XBtzs.jpg" rel="nofollow noreferrer"><img src="https://i.sstatic.net/XBtzs.jpg" alt="enter image description here"></a></p>

<p>here is the method to calculate uv coordinate for the hit point(ray-triangle code from Moller, Trumbore):</p>

<pre><code>     public bool GetIntersection(Vector rayOrigin, Vector rayDirection, ref 
              float hitDistance, out Vector uv)
    {
        uv = null;

        // begin calculating determinant - also used to calculate U parameter
        Vector pvec = rayDirection.Cross(edge2);

        // if determinant is near zero, ray lies in plane of triangle
        float det = edge1.Dot(pvec);

        const float EPSILON = 0.000001f;
        if ((det &gt; -EPSILON) &amp;&amp; (det &lt; EPSILON))
            return false;

        float inv_det = 1.0f / det;

        // calculate distance from vertex 0 to ray origin
        Vector tvec = rayOrigin - verts[0];

        // calculate U parameter and test bounds
        float u = tvec.Dot(pvec) * inv_det;
        if ((u &lt; 0.0f) || (u &gt; 1.0f))
            return false;

        // prepare to test V parameter
        Vector qvec = tvec.Cross(edge1);

        // calculate V parameter and test bounds
        float v = rayDirection.Dot(qvec) * inv_det;
        if ((v &lt; 0.0f) || (u + v &gt; 1.0f))
            return false;

        Vector uvHit = uvVectors[0] * u + uvVectors[1] * v + uvVectors[2] * (1 - u - v);
        uv = new Vector(uvHit[0], uvHit[1], 0);

        // calculate t, ray intersects triangle
        hitDistance = edge2.Dot(qvec) * inv_det;

        // only allow intersections in the forward ray direction
        return hitDistance &gt;= 0.0f;
    }
</code></pre>

<p>And here is the method in ImageTexture class to convert the hit point uv coordinate:</p>

<pre><code>    public Vector Interpolate(Vector uv)
    {
        float u = uv[0] - (float)Math.Floor(uv[0]);
        float v = uv[1] - (float)Math.Floor(uv[1]);
        u *= bmp.Width - 1;
        v *= bmp.Height - 1;

        Color cuv = bmp.GetPixel((int)u, (int)v);

        return new Vector(cuv.R, cuv.G, cuv.B);
    }
</code></pre>

<p>Also how are the uv coordinates that come from the input model are supposed to be calculated? If this is a big mesh(a terrain) with many triangles how is the uv coordinates for each triangle vertex is calculated?</p>

<p>Thanks.</p>

<raytracing><texture>
How to assign/calculate triangle texture coordinates
ali
# How to assign/calculate triangle texture coordinates

(Asked by: username_0 on 2018-06-22)

Below is a triangle with its vertices and uv coordinates. These are read from
the input model file.

I don't understand why the texture comes in different orientation than the image.

[![enter image description here](https://i.sstatic.net/GRZtO.png)](https://i.sstatic.net/GRZtO.png) [![enter image description here](https://i.sstatic.net/XBtzs.jpg)](https://i.sstatic.net/XBtzs.jpg)

here is the method to calculate uv coordinate for the hit point(ray-triangle code from Moller, Trumbore):

```
     public bool GetIntersection(Vector rayOrigin, Vector rayDirection, ref 
              float hitDistance, out Vector uv)
    {
        uv = null;

        // begin calculating determinant - also used to calculate U parameter
        Vector pvec = rayDirection.Cross(edge2);

        // if determinant is near zero, ray lies in plane of triangle
        float det = edge1.Dot(pvec);

        const float EPSILON = 0.000001f;
        if ((det > -EPSILON) && (det < EPSILON))
            return false;

        float inv_det = 1.0f / det;

        // calculate distance from vertex 0 to ray origin
        Vector tvec = rayOrigin - verts[0];

        // calculate U parameter and test bounds
        float u = tvec.Dot(pvec) * inv_det;
        if ((u < 0.0f) || (u > 1.0f))
            return false;

        // prepare to test V parameter
        Vector qvec = tvec.Cross(edge1);

        // calculate V parameter and test bounds
        float v = rayDirection.Dot(qvec) * inv_det;
        if ((v < 0.0f) || (u + v > 1.0f))
            return false;

        Vector uvHit = uvVectors[0] * u + uvVectors[1] * v + uvVectors[2] * (1 - u - v);
        uv = new Vector(uvHit[0], uvHit[1], 0);

        // calculate t, ray intersects triangle
        hitDistance = edge2.Dot(qvec) * inv_det;

        // only allow intersections in the forward ray direction
        return hitDistance >= 0.0f;
    }

```

And here is the method in ImageTexture class to convert the hit point uv coordinate:

```
    public Vector Interpolate(Vector uv)
    {
        float u = uv[0] - (float)Math.Floor(uv[0]);
        float v = uv[1] - (float)Math.Floor(uv[1]);
        u *= bmp.Width - 1;
        v *= bmp.Height - 1;

        Color cuv = bmp.GetPixel((int)u, (int)v);

        return new Vector(cuv.R, cuv.G, cuv.B);
    }

```

Also how are the uv coordinates that come from the input model are supposed to be calculated? If this is a big mesh(a terrain) with many triangles how is the uv coordinates for each triangle vertex is calculated?

Thanks.

**Tags:** raytracing, texture


---

## 1 answers

### Answer by username_1 on 2018-06-27. Score: 2 | Accepted answer

UV or barycentric coordinates represent a point on a triangle as a weighted average of the three vertexes. You can use those coordinates to smoothly interpolate any value over the triangle, like texture coordinates or the normal vector. So think of it like a two-step process. We map the world coordinates of the intersection point to uv coordinates in "triangle space", and then use those to map to another space, in this case "texture space". Your ray hits triangle ABC and you determine the uv coordinates of the intersection point, let's say (0.3, 0.5, 0.2). Intuitively, we're sort of saying the intersection point is 30% A, 50% B, and 20% C. Each vertex would have a texture coordinate, i.e. a pixel in the texture image, associated with it (that's part of modeling / setting up your scene, not something calculated at runtime). Mix the texture coordinates at A, B and C in that ratio and you'll get the point on the texture image associated with that point on the triangle.

[This scratchapixel page](https://www.scratchapixel.com/lessons/3d-basic-rendering/ray-tracing-rendering-a-triangle/barycentric-coordinates) has some good diagrams and clear explanation.

edit: I'm sorry, I missed the part about how to calculate the coordinates in the first place. The page I linked explains it better than I could anyway.


---

