Barycentric Coordinates
Barycentric coordinates are very useful in many field and are particularly important in CG. They have a few functions and are the key to the next ray-triangle intersection algorithm proposed by Möller-Trumbore that will be studied in the next chapter. How barycentric coordinates can be used in CG will be discussed at the end of this chapter.
Barycentric coordinates can be used to express the position of any point located on the triangle with three scalars. The location of this point includes any position inside the triangle, any position on any of the three edges of the triangles, or any one of the three triangle's vertices themselves. To compute the position of this point using barycentric coordinates we use the following equation (1):
where A B and C are the vertices of a triangle and u, v, and w (the barycentric coordinates), three real numbers (scalars) such that
You can also simply use two coordinates (lets say u and v) to express the coordinates of P in a two dimensional coordinate system defined by its origin (A) and the edge AB and AC (pretty much like expressing 2D points in the orthogonal two-dimensional coordinate system defined by an x- and y-axis. The only difference in our case is that AB and AC are not necessarily orthogonal and that the origin of this coordinate system is A). Anyway, just to say that you can define a position inside the triangle with the equation
This equation is similar to equation 1 excepted that if
These two equations are perfectly similar but it's hard to understand why we usually write
Barycentric coordinates are also known as areal coordinates. Although not very commonly used, this term indicates that the coordinates u, v and w are proportional to the area of the three sub-triangles defined by P, the point located on the triangle, and the triangle's vertices (A, B, C). These three sub-triangles are denoted ABP, BCP, CAP (see figure 1).
Which leads us to the formulas used to compute the barycentric coordinates:
In the rest of the lesson we will assume that u makes us move along the edge AB (if u=1 then P=B) and v along the edge AC (if v=1 then P=C). Which is the reason why we will use the area of the sub-triangle CAP to compute u and the area of the sub-triangle ABP to compute v. This is a convention that most people follow in the CG programming community (when we will learn how to use barycentric coordinates to interpolate vertex data you will have a visual example (figure 3) to better understand this).
Now computing the area of a triangle is trivial. If you duplicate the triangle and mirror it along its longest edge, you get a parallelogram. To compute the area of a parallelogram, simply compute its base, its side and multiply these two numbers together scaled by sin(
With this in hands, it becomes easy to compute u and v (w is computed out of u and v as explained before).
To make things easier, we can take advantage of the fact that the area of the sub-triangles ABP, BCP and CAP are proportional to the lengths of the cross product that we computed in the previous chapter to find P, the intersection point. This is one of the cross product properties: the magnitude of the cross product can be interpreted as the area of the parallelogram. Therefore we don't need to explicitly compute the previous formula (which includes an "expansive" sin(
Note than in mathematical terms, the double bars notation (|| ||) means "length of" (lesson 4). In other words we need to compute the length of the vector resulting of the cross product (C-B)x(P-B). We know how to compute the cross product of two vectors and the length of a vector so we have now all we need to compute the barycentric coordinates of the intersection point:
The plane normal should not be normalized because we use the length of the vector to compute the triangle area.
Using Barycentric Coordinates
Barycentric coordinates are most useful in shading. A triangle is a flat surface and we can associate any additional information or data (points, color, vectors, etc.) to each one of its vertices. This information is usually called vertex data. Let's imaging for example that you want vertex A to be red, vertex B to be green and vertex C to be blue.
If the intersection point coincides with one of the triangle's vertices, then the color of the object at the intersection point is simply the color associated with that vertex. Simple enough. The question is what happens when the ray intersects the triangle anywhere else (either on an edge or inside the triangle)? If the barycentric coordinates are used to compute the position of a point located on the triangle using the triangle vertices, we can interpolate any other data defined at the triangle's vertices (like for example the color) in the exact same way. In other words, barycentric coordinates are used to interpolate vertex data across the triangle's surface (the technique can be applied to any data type, float, color, etc.). This technique is very useful for shading for example to interpolate the normal at the intersection point. Normals of an object can be defined on per face or per vertex basis (we speak of face normal or vertex normal). If they are defined per vertex, we can use this interpolation technique to simulate a smooth shading across the triangle's surface even though, the triangle is "mathematically" flat (the normal at the hit point is a combination of the vertex normals therefore if the vertex normals are different from each other, the result of this interpolation is not constant across the surface of the triangle).
Barycentric coordinates are also used to compute texture coordinates (we will study this in the lesson on texturing).
Optimizing The Computation Of Barycentric Coordinates
You will notice that in the version of the algorithm we have been describing so far, we use the cross product of AB and AP, and the cross product of CA and CP to compute u and v. But if you look at the code again you will also notice that we have already computed these cross products for the inside-outside test. They have been used to compute the result of whether P is on the right or left side of edge0 (ABxAP) and edge2 (CAxCP). Naturally the first optimisation consists of reusing the result of these values. Also notice that (equation 2):
There is not need to compute the triangle area since the ratio between the triangle ABP and the triangle ABC is the same as the ratio between the parallelogram ABP (which is twice the area of the triangle ABP) and the paralleogram ABC (which is twice the area of the triangle ABC). Therefore we can also avoid the division by 2. The pseudocode becomes:
Finally we can prove that (equation 3):
First remember that
We now need to prove that this equation is true. Remember from lesson 4 that the cross product of two vectors can be seen as:
where the angle
If we assume that
A and B are also colinear in that case because they are constructed from vectors which are coplanar. Finally we can replace our results for the numerator and the denominator in equations 3 and rewrite:
We can eliminate one of the ||B||'s which leaves us with:
If we replace A back with
which is indeed the formula we used in the first place to compute v (equation 2). Therefore equation 3 is a valid formula to compute v. We already compute the numerator
In mathematics the formula
Here is the final version of our intersection routine which includes the optimized method to compute the barycentric coordinates:
Source Code
In this version of the ray-triangle intersection method we have implemented the technique described in chapter 2 to compute the hit point coordinates and the method described in this chapter to compute barycentric coordinates. When a ray hits the triangle, the pixel's color is set with the barycentric coordinates (to help you visualize them).
This code could be optimised even further. We know that the intersection point is not contained by the triangle if u < 0 or u > 1 or v < 0 or v > 1 or (u + v) > 1. Therefore we could first compute u and v and return false as soon as either one of them is lower than 0 or greater than 1 or if (u + v) is greater than 1. Lines 39 to 42 could therefore be entirely skipped. This optimisation is used in the ray-triangle intersection method we present in the next chapter. The IsectData structure was extended to support barycentric coordinates. When an intersection occurs, we set its u and v values (lines 52-53).
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
Figure 4 shows the result of the program.
'Graphics' 카테고리의 다른 글
[Cuda] Cuda 구조 (1) | 2017.03.31 |
---|