View Full Version : Barycentric coordinates?
Rivendale 09082005, 11:09 PM 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
09082005, 11:37 PM
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
09092005, 12: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
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
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 subtriangle
area2 = (length (cross vector1 vector3))/2 this is the area of the second subtriangle
area3 = (length (cross vector1 vector2))/2 this is the area of the third subtriangle
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! Handmade Barycentric coordinates!!!
baryfrommesh = meshop.getBaryCoords theMesh 1 p compare to the MAXScript result...
Rivendale
09092005, 11:00 PM
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
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...
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 (v2v1) (v3v1))
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 subtriangle
area2 = (length theCross2 )/2 this is the area of the second subtriangle
area3 = (length theCross3 )/2 this is the area of the third subtriangle
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! Handmade Barycentric coordinates!!!
baryfrommesh = meshop.getBaryCoords theMesh 1 p compare to the MAXScript result...
Rivendale
09102005, 01: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
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
09102005, 02: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.