Notifications
Clear all

[Closed] Barycentric coordinates?

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

9 Replies

In case you’re working with an Editable Mesh, this should do it:


meshop.[b]getBaryCoords[/b] <Mesh mesh> <int faceIndex> <point3 pos>
[b]node[/b]:<node=unsupplied>

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

Cheers,
Martijn

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

1 Reply
(@bobo)
Joined: 11 months ago

Posts: 0

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...

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

2 Replies
(@bobo)
Joined: 11 months ago

Posts: 0

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)
Joined: 11 months ago

Posts: 0

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...

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

1 Reply
(@bobo)
Joined: 11 months ago

Posts: 0

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