The barycentric coordinate presents a point in a triangle with the weighted sum of the triangle's vertice positions. Assume triangle vertices \(A(x_{A},y_{A})\), \(B(x_{B},y_{B})\), and \(C(x_{C},y_{C})\), position of any point \(P(x_{P},y_{P})\) inside the triangle can be calculated as:
\[
P = \alpha A + \beta B + \gamma C
\]
where \(\alpha + \beta + \gamma = 1\). In other words, \(\alpha\), \(\beta\) and \(\gamma\) are the weights showing how much each vertex contributes or is close to the point \(P\).
Calculation
One way to represent how close a point is to a vertex is to calculate its proportional distance to the edge opposite to the vertex, as is shown in the following figure:
Assume \(D_{BC}\) to be the distance to edge \(BC\), the \(\alpha\) weight can be calculated as:
The Barycentric coordinates' distinctive feature makes it suitable for geometric calculations in computer graphics. This includes but is not limited to:
Interpolation: Barycentric coordinates can be used to interpolate values smoothly varying across a triangle. This is useful in texture mapping, color blending, and shading.
Invariance to affine transformations: Regardless of the affine transformation applied to the triangle, the relative position of the vertices remains the same. As Barycentric coordinates are based on the relative position of the vertices, it could simplify calculation when affine transformations are involved.
Implementation
To determine whether a point is inside a triangle with Barycentric coordinates, whether the three weights are all positive is the only thing needed to check. For the points inside the triangle, its color is the weighted sum of the triangle's vertices' color, where the weights are exactly the Barycentric coordinates' weights. Other parts of the rasterization process are the same as Task 2.
The following code shows the rasterization process with Barycentric coordinates, highlighted are the parts where Barycentric coordinates are involved:
// Step 1: Convert the triangle vertices to the supersample buffer's coordinate systemintzoom_coefficient=sqrt(sample_rate);floatx0_ss=x0*zoom_coefficient;floaty0_ss=y0*zoom_coefficient;floatx1_ss=x1*zoom_coefficient;floaty1_ss=y1*zoom_coefficient;floatx2_ss=x2*zoom_coefficient;floaty2_ss=y2*zoom_coefficient;// Step 2: Find the bounding box of the triangle in the supersample bufferintbounding_box_x_min=(int)floor(min(x0_ss,min(x1_ss,x2_ss)));intbounding_box_x_max=(int)ceil(max(x0_ss,max(x1_ss,x2_ss)));intbounding_box_y_min=(int)floor(min(y0_ss,min(y1_ss,y2_ss)));intbounding_box_y_max=(int)ceil(max(y0_ss,max(y1_ss,y2_ss)));// Step 3: Iterate through all the pixels in the bounding box//cout << "iterating through pixels in the bounding box" << endl;intcurrent_x_position,current_y_position;floatline01_delta_x=x1_ss-x0_ss;floatline01_delta_y=y1_ss-y0_ss;floatline12_delta_x=x2_ss-x1_ss;floatline12_delta_y=y2_ss-y1_ss;floatline20_delta_x=x0_ss-x2_ss;floatline20_delta_y=y0_ss-y2_ss;floatweight_0,weight_1,weight_2;Colorcurrent_color;for(current_y_position=bounding_box_y_min;current_y_position<=bounding_box_y_max;current_y_position++){for(current_x_position=bounding_box_x_min;current_x_position<=bounding_box_x_max;current_x_position++){// calcuate the weights of the barycentric coordinatesweight_0=(-(current_x_position+0.5-x1_ss)*line12_delta_y+(current_y_position+0.5-y1_ss)*line12_delta_x)/(-(x0_ss-x1_ss)*line12_delta_y+(y0_ss-y1_ss)*line12_delta_x);weight_1=(-(current_x_position+0.5-x2_ss)*line20_delta_y+(current_y_position+0.5-y2_ss)*line20_delta_x)/(-(x1_ss-x2_ss)*line20_delta_y+(y1_ss-y2_ss)*line20_delta_x);weight_2=(-(current_x_position+0.5-x0_ss)*line01_delta_y+(current_y_position+0.5-y0_ss)*line01_delta_x)/(-(x2_ss-x0_ss)*line01_delta_y+(y2_ss-y0_ss)*line01_delta_x);// check if the pixel is inside the triangleif(weight_0>=0.&&weight_1>=0.&&weight_2>=0.){// if so, calculate the color of the pixelcurrent_color=c0*weight_0+c1*weight_1+c2*weight_2;// fill the corresponding buffersample_buffer[current_y_position*width*zoom_coefficient+current_x_position]=current_color;}}}
Results
The screenshot of svg/basic/test7.svg is shown below.