Barycentric Coordinates

https://www.scratchapixel.com/lessons/3d-basic-rendering/ray-tracing-rendering-a-triangle/barycentric-coordinates

barycentric coordinates are particularly important in CG. they have a few functions and are the key to the next ray-triangle intersection algorithm proposed by Moller 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 loation 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 uu, vv, and ww (the barycentric coordinates), three real numbers (scalars) such that u+v+w=1u+v+w=1 (barycentric coordinates are normalized). Note that from two of the coordinates we can find the third one: w=1−u−vw=1−u−v from which we can establish that u+v≤1u+v≤1 (we will use this simple but important property later on). Equation 1 defines the position of a point P on the plane of the triangle formed by the vertices A, B and C. The point is within the triangle (A, B, C) if 0≤u,v,w≤10≤u,v,w≤1. If any one of the coordinates is less than zero or greater than one, the point is outside the triangle. If any of them is zero, P is on one of the lines joining the vertices of the triangle.

You can also simply use two coordinates (let’s 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 P=A+u∗AB+v∗ACP=A+u∗AB+v∗AC (where u≥0u≥0 and v≥0v≥0 and u+v≤1u+v≤1). This equation can read as, “starts from A, move a little bit in the direction of AB, then a little bit in the direction of AC and you will find P”. Now if you develop this equation you can write:

P=A+u(B−A)+v(C−A)=A+uB−uA+vC−vA=(1−u−v)∗A+u∗B+v∗C

This equation is similar to equation 1 except that if w=1−u−v you have the following formula:
P=w∗A+u∗B+v∗C
instead of
P=u∗A+v∗B+w∗C.
These two equations are perfectly similar but it’s hard to understand why we usually write (1−u−v)∗A+u∗B+v∗C instead of u∗A+v∗B+(1−u−v)∗C without the above explanation.
两种写法都是可以的,但是通常使用第一种写法。

barycentric coordinnates 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).

在这里插入图片描述
Figure 1: barycentric coordinates can be seen as the area of sub-triangles CAP (for u), ABP (for v) and BCP (for w) over the area of the triangle ABC which is why the are also called areal coordinates.

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(θθ), where θθ is the angle subtended by the vectors AB and AC (figure 2). To create the parallelogram we used two triangles, therefore the area of one triangle is half the area of the parallelogram.

With this in hands, it becomes easy to compute u and v (w is computed out of u and v as explained before).
在这里插入图片描述
Figure 2: to compute the area of a triangle we start from the formula used to compute a parallelogram (its base multiplied by its height H). To compute H, we multiply sin(θθ) by the length of the vector AC.

在这里插入图片描述

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(θ). We can simply use instead:

在这里插入图片描述

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:

bool rayTriangleIntersect( 
    const Vec3f &orig, const Vec3f &dir, 
    const Vec3f &v0, const Vec3f &v1, const Vec3f &v2, 
    float &t, float &u, float &v) 
{ 
    // compute plane's normal
    Vec3f v0v1 = v1 - v0; 
    Vec3f v0v2 = v2 - v0; 
    // no need to normalize
    Vec3f N = v0v1.crossProduct(v0v2); // N 
    float area = N.length() / 2; // area of the triangle 
 
    ... 
 
    // Step 2: inside-outside test
    Vec3f C; // vector perpendicular to triangle's plane 
 
    // edge 0
    ... 
 
    // edge 1
    Vec3f edge1 = v2 - v1; 
    Vec3f vp1 = P - v1; 
    C = edge1.crossProduct(vp1); 
    u = (C.length() / 2) / area; 
    if (N.dotProduct(C) < 0)  return false; // P is on the right side 
 
    // edge 2
    Vec3f edge2 = v0 - v2; 
    Vec3f vp2 = P - v2; 
    C = edge2.crossProduct(vp2); 
    v = (C.length() / 2) / area; 
    if (N.dotProduct(C) < 0) return false; // P is on the right side; 
 
    return true; // this ray hits the triangle 
} 

The plane normal should not be normalized because we use the length of the vector to compute the triangle area.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值