Jump to content
  • Advertisement
Sign in to follow this  
Alessandro

barycentric coordinates C++ code check

This topic is 2469 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm using the following code to calculate barycentric coordinates for a point on triangle t1/t2/t3 and use those to gather the related point position on a second triangle T1/T2/T3.
It seems to work but sometimes I'm not totally sure about it, and I'd be more confident if you guys could check on that.
Do you see any possible trouble or issue with it? Do you perhaps have other C++ code to share?
Thanks for any help.


// compute the area of a triangle using Heron's formula
double triarea(double a, double b, double c)
{
double s = (a + b + c)/2.0;
double area=sqrt(fabs(s*(s-a)*(s-b)*(s-c)));
return area;
}

// compute the distance between two 2d points
double dist(double x0, double y0, double z0, double x1, double y1, double z1)
{
double a = x1 - x0;
double b = y1 - y0;
double c = z1 - z0;
return sqrt(a*a + b*b + c*c);
}

// calculate barycentric coordinates
// triangle 1st vertex: x0,y0,z0
// triangle 2nd vertex: x1,y1,z1
// triangle 3rd vertex: x2,y2,z2
// point inside triangle: vx, vy,vz
// *u,*v,*w are the coordinates returned
void barycent(double x0, double y0, double z0, double x1, double y1, double z1, double x2, double y2, double z2,
double vx, double vy, double vz,
double *u, double *v, double *w)
{
// compute the area of the big triangle
double a = dist(x0, y0, z0, x1, y1, z1);
double b = dist(x1, y1, z1, x2, y2, z2);
double c = dist(x2, y2, z2, x0, y0, z0);
double totalarea = triarea(a, b, c);

// compute the distances from the outer vertices to the inner vertex
double length0 = dist(x0, y0, z0, vx, vy, vz);
double length1 = dist(x1, y1, z1, vx, vy, vz);
double length2 = dist(x2, y2, z2, vx, vy, vz);

// divide the area of each small triangle by the area of the big triangle
*u = triarea(b, length1, length2)/totalarea;
*v = triarea(c, length0, length2)/totalarea;
*w = triarea(a, length0, length1)/totalarea;
}

void main()
{
double r1,r2,r3; // barycentric coordinates
barycent(t1.x, t1.y, t1.z, t2.x, t2.y, t2.z, t3.x, t3.y, t3.z, firstPoint.x, firstPoint.y, firstPoint.z, &r1, &r2, &r3);
Point3d newPoint(T1.x*r1 + T2.x*r2 + T3.x*r3, T1.y*r1 + T2.y*r2 + T3.y*r3, T1.z*r1 + T2.z*r2 + T3.z*r3); // T1,T2,T3 are the coordinates of another triangle
}

Share this post


Link to post
Share on other sites
Advertisement
I've done fairly intensive stuff with this sort of thing in the past... was drawing/defining tendon insertion points into polygonal bones. I just felt my way through it and did not ever encounter any trouble.

I don't think the area of the triangle is a factor you should be concerned with. Probably you just want to be doing some simple projections. If you are working with an object oriented language such as C++ you should find a vector library you are happy with. It will make things much more presentable and easier to proof for yourself.

PS: I was probably not using literal "barycentric" coordinates. It depends on what your application is I suppose. But if you need to fix a point onto a triangle, two coordinates does the trick. Also just trying to be helpful (your post has been languishing for a while)

EDITED: I could've sworn I explained that you can get away with one ratio for the distance between the first two corners, and then a second ratio for the distance between that point and the last corner. Don't know what happened to that. Anyway, again, depends on the application.

Share this post


Link to post
Share on other sites
I've never seen barycentric coordinates calculated like that... that's a fairly expensive way to calculate them, using square roots and all. I'm writing a software renderer using barycentric coordinates for school. Here's the part where I calculate the coordinates:


// This function is a member of my Triangle class, which holds 3 3D vectors,
// a, b, and c which denote the 3 points making up the triangle. The 3
// values for the barycentric coordinates get stored in lambda
Vector<3, T> baryCoords(Vector<2, T> vec) const
{
Vector<3, T> lambda;
T den = 1 / ((b.y - c.y) * (a.x - c.x) + (c.x - b.x) * (a.y - c.y));

lambda.x = ((b.y - c.y) * (vec.x - c.x) + (c.x - b.x) * (vec.y - c.y)) * den;
lambda.y = ((c.y - a.y) * (vec.x - c.x) + (a.x - c.x) * (vec.y - c.y)) * den;
lambda.z = 1 - lambda.x - lambda.y;

return lambda;
}

// I use it kinda like this:
Triangle<float> t; // assign it's ABC points
Vector<2, float> p; // Give it some position
Vector<3, float> lambda = t.baryCoords(p);
Vector<3, float> final = lambda.x * t.getA() + lambda.y * t.getB() + lambda.z * t.getC();


I'm following the equations from Wikipedia.

[edit]

Ah, I see why you're doing it like that now. You have to be sure the point lies in the same plane as the triangle, and if it does, you can simplify it to be calculated like my function.

Share this post


Link to post
Share on other sites
Thank you very much for all the suggestions, and the code example as well. I implemented that in my barycentric routine and everything now works as expected! laugh.png

Share this post


Link to post
Share on other sites
Also, getting rid of those square roots now allows to do the calculations much faster: I'm using that barycentric routine to calculate UV coordinates (I need to find the UV point that correspond to a point on a 3D model), and that runs for a large set of data. Now, without sqrt's, the routine does it in about 1/12th than earlier.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!