Archived

This topic is now archived and is closed to further replies.

Aeroum

Converting Point to UV (or barycentric)

Recommended Posts

For a triangle it was said that to convert from the UV coords to xyz, this works... given: v0, v1, v2, u, v find: x, y, z x = v0.x + u*(v1.x-v0.x) + v*(v2.x-v0.x); y = v0.y + u*(v1.y-v0.y) + v*(v2.y-v0.y); z = v0.z + u*(v1.z-v0.z) + v*(v2.z-v0.z); Now what about getting the U and V from 3 triangle vertices and 1 point... given: v0, v1, v2, x, y, z find: u, v Aeroum

Share this post


Link to post
Share on other sites
Let''s denote the (x,y,z) vector as v3. Now we get a more compact equation. Also, let vij denote vi-vj. Let''s denote (u,v) with (a,b) (I at least don''t like mixing the scalar v with the vectors v0, v1 etc.)

v3 = v0+v10*a+v20*b

If we form a linear system (three equation) out of this, we can''t solve it just like that. This is because if the point v3 is not on the plane (v0,v1,v2), there is no solution! Although WE know that v3 is guaranteed to be on the plane, the computer doesn''t know it - small floating point rounding errors make the problem impossible to solve.

That''s why we reformulate the problem: don''t try to solve v0+v10*a+v20*b which is equal to v3, but try to solve for v0+v10*a+v20*b which is CLOSEST to v3. If you look at this on a sheet of paper, you''ll see that the answers (a,b) are equal in both cases. This method is generally referred to as "the method least-squares".

Now, the formulas. Let''s denote the square of the distance d as:

d = [(v0+v10*a+v20*b)-v3]*[(v0+v10*a+v20*b)-v3]
<=>
d = (v03+v10*a+v20*b)^2

Here ^2 means a dot product of a vector by itself.

Our problem now is to minimize the square of the distance. We know that the distance is minimized exactly when the derivatives of d wrt. to a and b are zero. Mathematically expressed:

{ @d/@a = 0
{ @d/@b = 0

The computation of the derivative can exploit the formula for computing the derivative of a multiplication (^2).

@d/@a = 2*(v03+v10*a+v20*b)*v10
@d/@b = 2*(v03+v10*a+v20*b)*v20

For these to be zeroes it boils down to:

{ (v03*v10)+(v10*v10)*a+(v20*v10)*b = 0
{ (v03*v20)+(v10*v20)*a+(v20*v20)*b = 0

And finally:

{ (v10*v10)*a + (v20*v10)*b = (v30*v10)
{ (v10*v20)*a + (v20*v20)*b = (v30*v20)

This is an equation pair which, except in degenerate cases (ie. the triangle is not a true triangle, but a point or a line instead), is guaranteed to have a solution.

If you have any questions, don''t hesitate to ask.

- Mikko Kauppila

Share this post


Link to post
Share on other sites
Well, alright, I''m following you...a bit...but I don''t see how this...

{ (v10*v10)*a + (v20*v10)*b = (v30*v10)
{ (v10*v20)*a + (v20*v20)*b = (v30*v20)

solves for a or b...

And before doing the calculation I''m testing if the point is on the plane of the triangle first. And if it''s not, I don''t solve u and v (or a and b).

And on that last part...I don''t see vertex 0 in there anywhere. And did you mean v1, v2, v3 instead of v10, v20, v30?

~Aeroum

Share this post


Link to post
Share on other sites
v0,v1 and v2 are the points of the triangle.
v3 is the point (x,y,z)

The vectors v10, v20 and v30 are:

v10 = v1-v0
v20 = v2-v0
v30 = v3-v0

So everything is "centered" about v0. This is what the notation vij = vi-vj meant.

"I don''t see how this solves for a and b".

Well, that''s why I included the complete derivation for you to study. The (a,b) returned are the correct ones. If you don''t know how to solve an equation pair, here''s a source snippet:

This code solves the equation pair:

{ ax + by = u
{ cx + dy = v


int GJESolve2x2( real a, real b, real c, real d, real & x, real & y,
real u, real v )
{
if( a*d == b*c ) return -1;

if( RealAbs(a) > RealAbs(c) )
{
real ra = 1.0/a;
d -= b*c*ra;
v -= u*c*ra;
y = v/d;
x = (u-b*y)*ra;
}
else
{
real rc = 1.0/c;
b -= d*a*rc;
u -= v*a*rc;
y = u/b;
x = (v-d*y)*rc;
}
return 0;
}


- Mikko Kauppila

Share this post


Link to post
Share on other sites