THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED
On 19/05/2012 at 12:51, xxxxxxxx wrote:
This first routine is the one that computes the 3 weights (for vertices a,b,c of the triangle, but stored in my own structure as w0,w1,w2)...
//------------------------------------------------------------------------------------------------------
//******************************************************************************************************
// ComputeTriWeights()
//******************************************************************************************************
//------------------------------------------------------------------------------------------------------
void ComputeTriWeights(triWeightNdx *pWeights, Vector ixPoint, Vector polyNorm, Vector v0, Vector v1, Vector v2)
{
//=================================================================================
// Args:
// pWeights - a structure for holding the computed weights for 3 verts of a triangle
// ixPoint - intersection point of ray-cast with triangle (point on surface of triangle)
// polyNorm - polygon (triangle) Normal
// v0, v1, v2 - 3 verts that make up the triangle
//
// For each vertex of the triangle, it's weighting value is computed as:
//
// weight = 1.0 - (ISectDist divided by EdgeDist)
//
// [...if interested, see additional notes and diagrams here:
// http://www.renderosity.com/mod/forumpro/showthread.php?thread_id=2677445&page=2 ]
//
// So far, we have an ISectDist for each vertex-->intersection (idv0..idv2).
// What we don't have yet is the distance from each vertex to the opposing edge,
// along the vector described by the line from the vertex to the intersection.
//
// Optimization: The nature of these weights is that the sum of them add up to 1.0,
// so we really only need to calculate the first 2 weights and then we can deduce
// the 3rd based on those results.
//=================================================================================
Real idist, edist;
// compute weight for v0, using v1..v2 edge
edist = Ray2EdgeDist(v0,v1,v2,polyNorm,ixPoint);
if( edist >= flt_max - 0.0000001 ) // FLT_MAX is the signal that the intersection was _at_ this vertex
{ // (or at least so close that the error-correcting code let it through)
pWeights->w0 = 1.0; pWeights->w1 = 0.0; pWeights->w2 = 0.0;
return;
}
else if( edist <= 0.0 ) // don't divide by zero (this would be a degenerate triangle)
pWeights->w0 = 0.0;
else
{
idist = point_distance(v0, ixPoint); // distance from vert of the tripoly to the intersection point
pWeights->w0 = 1.0 - (idist / edist); // solve for weight = 1.0 - (ISectDist divided by EdgeDist)
}
if( pWeights->w0 < 0.0 ) pWeights->w0 = 0.0;
// repeat the above for v1, using v2..v0 edge
edist = Ray2EdgeDist(v1,v2,v0,polyNorm,ixPoint);
if( edist >= flt_max - 0.0000001 ) // FLT_MAX is the signal that the intersection was _at_ this vertex
{ // (or at least so close that the error-correcting code let it through)
pWeights->w0 = 0.0; pWeights->w1 = 1.0; pWeights->w2 = 0.0;
return;
}
else if( edist <= 0.0 ) // don't divide by zero (this would be a degenerate triangle)
pWeights->w1 = 0.0;
else
{
idist = point_distance(v1, ixPoint); // distance from vert of the tripoly to the intersection point
pWeights->w1 = 1.0 - (idist / edist); // solve for weight = 1.0 - (ISectDist divided by EdgeDist)
}
if( pWeights->w1 < 0.0 ) pWeights->w1 = 0.0;
// wgt2 gets whatever is left over...
pWeights->w2 = 1.0 - (pWeights->w0 + pWeights->w1);
if( pWeights->w2 < 0.0 ) pWeights->w2 = 0.0;
}
...the next sample routine computes the distances...
//======================================================================================================
// Ray2EdgeDist()
//
// Note: this routine is fairly specific to the task at hand, so the name of it shouldn't be taken
// as a general problem solver.
//
// vert - one vertex of a triangle
// e1,e2 - the vertices that make up the opposing edge
// pnorm - the normal of the triangle
// isect - the point of intersection (some point within the triangle)
//
// What this routine does is compute the distance from a vertex to the opposing edge of a triangle,
// along the vector described by the line from the vertex to the intersection point that was
// calculated in the linecast_loop() code.
//
// The methodology I'll use to come up with this is as follows:
//
// 1. create a 'plane' from the edge being tested, perpendicular to the plane described
// by the intersection point and the two points of the edge .
//
// 2. calculate the intersection between a ray cast from the vertex in question (along
// the vertex-->intersection vector), with the plane created in step one, above.
//
// ...note that once we have the new plane from step #1, this is basically the same methodology
// we used back in linecast_loop() to compute the original intersection point, just twisted
// around in space to deal with the new ray direction.
//======================================================================================================
Real Ray2EdgeDist(Vector vert, Vector e1, Vector e2, Vector pnorm, Vector isect)
{
// create plane for e1..e2 edge, perpendicular to triangle
Vector evec = e2 - e1; // get edge vector
Vector perp = !(evec % pnorm); // get vector perpendicular to polygon (normalized cross product)
Real plane = perp * e1; // convert to plane (dot product)
Vector rvec = !(isect - vert); // get ray vector from vert-->intersect
Real ndota = perp * rvec;
Real ndotv = perp * vert;
if( ndota <= 0.0 ) // divide-by-zero sanity check - due to some math rounding error that
return flt_max; // was adjusted for the initial point_in_triangle test, it's possible
// that the point is at the vertex being tested, which could cause the
// ray vector to be wacky, so just return a 'maximum' distance.
return (plane - ndotv) / ndota; // compute intersection distance from vert to edge, along vector from vert-->intersect
}
...finally, that point_distance() routine is actually just a simple macro:
#define point_distance(a,b) Len((b) - (a))