ssloy / tinyrenderer

A brief computer graphics / rendering course
https://github.com/ssloy/tinyrenderer/wiki
Other
20.68k stars 1.98k forks source link

Math question about lesson 2 #104

Closed XiaofanLinUS closed 2 years ago

XiaofanLinUS commented 2 years ago

When calculating the b-coordinates of point P, I understand we need to find the cross product between vectors [AB.x, AC.x, PA.x] and [AB.y, AC.y, PA.y]. Because their dot products are zeros meaning the cross product represents the vector we need to find, for [u,v,1] [AB.x, AC.x, PA.x] = 0 and [u,v,1] [AB.y, AC.y, PA.y] = 0, the solution of [u, v, 1]. But I don't know how this is related to the intersection of lines and the equation of the line passing through two points. All I can see is this is related to a "plane defined by two vectors". Can you help me understand the following statement made by you in lesson 2. Thanks a lot for this great material. Best.

"That is a small hint: to find an intersection of two straight lines in a plane (that is exactly what we did here), it is sufficient to compute one cross product. By the way, test yourself: how do we find an equation of a line passing through two given points?"

ssloy commented 2 years ago

I think that it would be simpler to go another way.

Given a 2D triangle with points A, B, C and a 2D point P, we want to find a vector u, v, w such that P = u A + v B + w C. In other words, (u,v,w) are the barycentric coordinates of P wrt ABC.

You can find it using triangle areas: u = area of the triangle PBC v = area of the triangle PCA w = area of the traingle PAB

If you want the constraint u+v+w = 1, then divide those numbers by the total area of the triangle ABC itself. Long story short, here is the code:

double triangle_area_2d(const vec2 &a, const vec2 &b, const vec2 &c) {
    return .5*((b.y-a.y)*(b.x+a.x) + (c.y-b.y)*(c.x+b.x) + (a.y-c.y)*(a.x+c.x));
}

vec3 barycentric(vec2 A, vec2 B, vec2 C, vec2 P) {
    double total_area = triangle_area_2d(A, B, C);
    double u = triangle_area_2d(P, B, C);
    double v = triangle_area_2d(P, C, A);
    double w = triangle_area_2d(P, A, B);
    return {u/total_area, v/total_area, w/total_area};
}
XiaofanLinUS commented 2 years ago

I just found out there is some typo in my first comment. Anyway, the second explanation seems more natural. Thanks.