PDA

View Full Version : Barycentric coordinates?


Rivendale
09-09-2005, 12:09 AM
Hey, I would appreciate some help with this one:

How do I calculate the barycentric coordinates for a points position relative to a triangle with known vertex positions? (The point lies on the same plane as the triangle)

CML

magicm
09-09-2005, 12:37 AM
In case you're working with an Editable Mesh, this should do it:


meshop.getBaryCoords <Mesh mesh> <int faceIndex> <point3 pos>
node:<node=unsupplied>

The barycentric coordinates of the specified point in the plane of the
specified face, relative to the face. If <mesh> is a node,
or if <mesh> is an Editable Mesh or a Mesh value and node
is specified, the position is in the current coordinate system context.
If <mesh> is an Editable Mesh or a Mesh value and node
is not specified, the position is in the mesh's local coordinate system.

Cheers,
Martijn

Rivendale
09-09-2005, 01:19 AM
Hey Martijn, thanks. I have already read up on that one but the thing is that the triangle is not a meshface so I need the mathematical solution for calclating it. I tried searching on the web too but I can't fully understand the solutions I've found. I need a simple example explaining how it's done.

cheers,
CML

Bobo
09-09-2005, 10:35 PM
Hey Martijn, thanks. I have already read up on that one but the thing is that the triangle is not a meshface so I need the mathematical solution for calclating it. I tried searching on the web too but I can't fully understand the solutions I've found. I need a simple example explaining how it's done.

cheers,
CML

Always the place to go for mathematical solutions ;)
http://mathworld.wolfram.com/BarycentricCoordinates.html

Bobo
09-09-2005, 11:01 PM
Always the place to go for mathematical solutions ;)
http://mathworld.wolfram.com/BarycentricCoordinates.html


Here is an example in MAXScript:

1. Create a Line shape in the form of triangle in the top viewport
2. Convert to Editable Mesh
3. Create a Dummy at the position of interest in the top viewport inside the triangle (it is in the same plane!)

theMesh = $Line01 --this is the mesh triangle with just one face
v1 = getVert theMesh 1 --get the 3 vertices in world space
v2 = getVert theMesh 2
v3 = getVert theMesh 3
p = $Dummy01.pos --get the position of the dummy as the point to get the bary coords from

vector1 = p - v1 --this is the vector from vertex 1 to the dummy
vector2 = p - v2 --this is the vector from vertex 2 to the dummy
vector3 = p - v3 --this is the vector from vertex 3 to the dummy


--because the length of the cross product vector is equal to the area of the parallelogram
--defined by the two operands, half of it is the area of the triangle!
area1 = (length (cross vector2 vector3))/2 --this is the area of the first sub-triangle
area2 = (length (cross vector1 vector3))/2 --this is the area of the second sub-triangle
area3 = (length (cross vector1 vector2))/2 --this is the area of the third sub-triangle

fullArea = area1 + area2 + area3 --this is the full area of the triangle

b1 = area1 / fullArea --this is the proportion of the first triangle vs. the full triangle
b2 = area2 / fullArea --this is the proportion of the second triangle vs. the full triangle
b3 = area3 / fullArea --this is the proportion of the third triangle vs. the full triangle

baryCoords = [b1, b2, b3] --Behold! Hand-made Barycentric coordinates!!!
baryfrommesh = meshop.getBaryCoords theMesh 1 p --compare to the MAXScript result...

Rivendale
09-10-2005, 12:00 AM
Oh man I can't thank you enough for this, I've banged my head at this for some time now. There is something more though...if the point lies outside the triangle you can still get the coordinates with meshop.getBaryCoords, but with the example it doesn't work in that case. What can I do?

Thanks!
CML

Bobo
09-10-2005, 12:24 AM
Oh man I can't thank you enough for this, I've banged my head at this for some time now. There is something more though...if the point lies outside the triangle you can still get the coordinates with meshop.getBaryCoords, but with the example it doesn't work in that case. What can I do?

Thanks!
CML

Ah, yes, you need a way to detect that one of the triangles has "negative" area. Then you would add the two bigger ones (whose area would be bigger than the original face) and subtract the negative one to get the total area. As you can see, the meshop's result still has .x + .y + .z = 1.0, but one of them is negative when the point is outside, and the sum of the other two is > 1.0.
I am looking into a MAXScript solution...

Bobo
09-10-2005, 05:20 AM
Ah, yes, you need a way to detect that one of the triangles has "negative" area. Then you would add the two bigger ones (whose area would be bigger than the original face) and subtract the negative one to get the total area. As you can see, the meshop's result still has .x + .y + .z = 1.0, but one of them is negative when the point is outside, and the sum of the other two is > 1.0.
I am looking into a MAXScript solution...


theMesh = $Line01 --this is the mesh triangle with just one face
v1 = getVert theMesh 1 --get the 3 vertices in world space
v2 = getVert theMesh 2
v3 = getVert theMesh 3
p = $Dummy01.pos --get the position of the dummy as the point to get the bary coords from

vector1 = p - v1 --this is the vector from vertex 1 to the dummy
vector2 = p - v2 --this is the vector from vertex 2 to the dummy
vector3 = p - v3 --this is the vector from vertex 3 to the dummy

--Calculate the cross product of the 3 vectors
theCross1 = (cross vector2 vector3)
theCross2 = (cross vector3 vector1)
theCross3 = (cross vector1 vector2)

--calculate the face normal using the cross product of two edges
theNormal = normalize (cross (v2-v1) (v3-v1))

--because the length of the cross product vector is equal to the area of the parallelogram
--defined by the two operands, half of it is the area of the triangle!
area1 = (length theCross1 )/2 --this is the area of the first sub-triangle
area2 = (length theCross2 )/2 --this is the area of the second sub-triangle
area3 = (length theCross3 )/2 --this is the area of the third sub-triangle

--calculate the angle of each cross product with the face normal
angle1 = acos ( dot ( normalize theCross1) theNormal )
angle2 = acos ( dot ( normalize theCross2) theNormal )
angle3 = acos ( dot ( normalize theCross3) theNormal )

--if the angle is different from the other two, take its area as negative
if angle1 != angle2 and angle1 != angle3 then area1 = -area1
if angle2 != angle1 and angle2 != angle3 then area2 = -area2
if angle3 != angle1 and angle3 != angle2 then area3 = -area3

fullArea = area1 + area2 + area3 --this is the full area of the triangle

b1 = area1 / fullArea --this is the proportion of the first triangle vs. the full triangle
b2 = area2 / fullArea --this is the proportion of the second triangle vs. the full triangle
b3 = area3 / fullArea --this is the proportion of the third triangle vs. the full triangle

baryCoords = [b1, b2, b3] --Behold! Hand-made Barycentric coordinates!!!
baryfrommesh = meshop.getBaryCoords theMesh 1 p --compare to the MAXScript result...

Rivendale
09-10-2005, 02:12 PM
Sweet! Now it's working great. Thanks a lot for taking the time Bobo.

edit: one small optimization would be to loose the acos part since it should be enough to dot the vectors, right?

CML

Bobo
09-10-2005, 03:31 PM
Sweet! Now it's working great. Thanks a lot for taking the time Bobo.

edit: one small optimization would be to loose the acos part since it should be enough to dot the vectors, right?

CML


Lots of optimizations possible. Yes, the dot would be enough. The vectors are always either parallel or pointing in opposite directions.

CGTalk Moderation
09-10-2005, 03:31 PM
This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.