[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [16082] branches/apricot/source: Apricot Branch

Brecht Van Lommel brechtvanlommel at pandora.be
Wed Aug 13 19:42:58 CEST 2008


Revision: 16082
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=16082
Author:   blendix
Date:     2008-08-13 19:42:58 +0200 (Wed, 13 Aug 2008)

Log Message:
-----------
Apricot Branch
==============

svn merge -r16064:HEAD https://svn.blender.org/svnroot/bf-blender/trunk/blender

Modified Paths:
--------------
    branches/apricot/source/blender/blenkernel/intern/bvhutils.c
    branches/apricot/source/blender/src/header_view3d.c
    branches/apricot/source/gameengine/GameLogic/SCA_PythonController.cpp

Modified: branches/apricot/source/blender/blenkernel/intern/bvhutils.c
===================================================================
--- branches/apricot/source/blender/blenkernel/intern/bvhutils.c	2008-08-13 17:38:38 UTC (rev 16081)
+++ branches/apricot/source/blender/blenkernel/intern/bvhutils.c	2008-08-13 17:42:58 UTC (rev 16082)
@@ -48,9 +48,6 @@
 
 /* Math stuff for ray casting on mesh faces and for nearest surface */
 
-static float nearest_point_in_tri_surface(const float *point, const float *v0, const float *v1, const float *v2, float *nearest);
-
-#define ISECT_EPSILON 1e-6
 static float ray_tri_intersection(const BVHTreeRay *ray, const float m_dist, const float *v0, const float *v1, const float *v2)
 {
 	float dist;
@@ -79,170 +76,324 @@
 	return FLT_MAX;
 }
 
+
 /*
- * This calculates the distance from point to the plane
- * Distance is negative if point is on the back side of plane
+ * Function adapted from David Eberly's distance tools (LGPL)
+ * http://www.geometrictools.com/LibFoundation/Distance/Distance.html
  */
-static float point_plane_distance(const float *point, const float *plane_point, const float *plane_normal)
+static float nearest_point_in_tri_surface(const float *v0,const float *v1,const float *v2,const float *p, int *v, int *e, float *d, float *nearest )
 {
-	float pp[3];
-	VECSUB(pp, point, plane_point);
-	return INPR(pp, plane_normal);
-}
-static float choose_nearest(const float v0[2], const float v1[2], const float point[2], float closest[2])
-{
-	float d[2][2], sdist[2];
-	VECSUB2D(d[0], v0, point);
-	VECSUB2D(d[1], v1, point);
+	float diff[3];
+	float e0[3];
+	float e1[3];
+	float A00;
+	float A01;
+	float A11;
+	float B0;
+	float B1;
+	float C;
+	float Det;
+	float S;
+	float T;
+	float sqrDist;
+	int lv = -1, le = -1;
+	
+	VECSUB(diff, v0, p);
+	VECSUB(e0, v1, v0);
+	VECSUB(e1, v2, v0);
+	
+	A00 = INPR ( e0, e0 );
+	A01 = INPR( e0, e1 );
+	A11 = INPR ( e1, e1 );
+	B0 = INPR( diff, e0 );
+	B1 = INPR( diff, e1 );
+	C = INPR( diff, diff );
+	Det = fabs( A00 * A11 - A01 * A01 );
+	S = A01 * B1 - A11 * B0;
+	T = A01 * B0 - A00 * B1;
 
-	sdist[0] = d[0][0]*d[0][0] + d[0][1]*d[0][1];
-	sdist[1] = d[1][0]*d[1][0] + d[1][1]*d[1][1];
-
-	if(sdist[0] < sdist[1])
+	if ( S + T <= Det )
 	{
-		if(closest)
-			VECCOPY2D(closest, v0);
-		return sdist[0];
+		if ( S < 0.0f )
+		{
+			if ( T < 0.0f )  // Region 4
+			{
+				if ( B0 < 0.0f )
+				{
+					T = 0.0f;
+					if ( -B0 >= A00 )
+					{
+						S = (float)1.0;
+						sqrDist = A00 + 2.0f * B0 + C;
+						lv = 1;
+					}
+					else
+					{
+						if(fabs(A00) > FLT_EPSILON)
+							S = -B0/A00;
+						else
+							S = 0.0f;
+						sqrDist = B0 * S + C;
+						le = 0;
+					}
+				}
+				else
+				{
+					S = 0.0f;
+					if ( B1 >= 0.0f )
+					{
+						T = 0.0f;
+						sqrDist = C;
+						lv = 0;
+					}
+					else if ( -B1 >= A11 )
+					{
+						T = 1.0f;
+						sqrDist = A11 + 2.0f * B1 + C;
+						lv = 2;
+					}
+					else
+					{
+						if(fabs(A11) > FLT_EPSILON)
+							T = -B1 / A11;
+						else
+							T = 0.0f;
+						sqrDist = B1 * T + C;
+						le = 1;
+					}
+				}
+			}
+			else  // Region 3
+			{
+				S = 0.0f;
+				if ( B1 >= 0.0f )
+				{
+					T = 0.0f;
+					sqrDist = C;
+					lv = 0;
+				}
+				else if ( -B1 >= A11 )
+				{
+					T = 1.0f;
+					sqrDist = A11 + 2.0f * B1 + C;
+					lv = 2;
+				}
+				else
+				{
+					if(fabs(A11) > FLT_EPSILON)
+						T = -B1 / A11;
+					else
+						T = 0.0;
+					sqrDist = B1 * T + C;
+					le = 1;
+				}
+			}
+		}
+		else if ( T < 0.0f )  // Region 5
+		{
+			T = 0.0f;
+			if ( B0 >= 0.0f )
+			{
+				S = 0.0f;
+				sqrDist = C;
+				lv = 0;
+			}
+			else if ( -B0 >= A00 )
+			{
+				S = 1.0f;
+				sqrDist = A00 + 2.0f * B0 + C;
+				lv = 1;
+			}
+			else
+			{
+				if(fabs(A00) > FLT_EPSILON)
+					S = -B0 / A00;
+				else
+					S = 0.0f;
+				sqrDist = B0 * S + C;
+				le = 0;
+			}
+		}
+		else  // Region 0
+		{
+            // Minimum at interior lv
+			float invDet;
+			if(fabs(Det) > FLT_EPSILON)
+				invDet = 1.0f / Det;
+			else
+				invDet = 0.0f;
+			S *= invDet;
+			T *= invDet;
+			sqrDist = S * ( A00 * S + A01 * T + 2.0f * B0) +
+					T * ( A01 * S + A11 * T + 2.0f * B1 ) + C;
+		}
 	}
 	else
 	{
-		if(closest)
-			VECCOPY2D(closest, v1);
-		return sdist[1];
-	}
-}
-/*
- * calculates the closest point between point-tri (2D)
- * returns that tri must be right-handed
- * Returns square distance
- */
-static float closest_point_in_tri2D(const float point[2], /*const*/ float tri[3][2], float closest[2])
-{
-	float edge_di[2];
-	float v_point[2];
-	float proj[2];					//point projected over edge-dir, edge-normal (witouth normalized edge)
-	const float *v0 = tri[2], *v1;
-	float edge_slen, d;				//edge squared length
-	int i;
-	const float *nearest_vertex = NULL;
+		float tmp0, tmp1, numer, denom;
 
-
-	//for each edge
-	for(i=0, v0=tri[2], v1=tri[0]; i < 3; v0=tri[i++], v1=tri[i])
-	{
-		VECSUB2D(edge_di,    v1, v0);
-		VECSUB2D(v_point, point, v0);
-
-		proj[1] =  v_point[0]*edge_di[1] - v_point[1]*edge_di[0];	//dot product with edge normal
-
-		//point inside this edge
-		if(proj[1] < 0)
-			continue;
-
-		proj[0] = v_point[0]*edge_di[0] + v_point[1]*edge_di[1];
-
-		//closest to this edge is v0
-		if(proj[0] < 0)
+		if ( S < 0.0f )  // Region 2
 		{
-			if(nearest_vertex == NULL || nearest_vertex == v0)
-				nearest_vertex = v0;
+			tmp0 = A01 + B0;
+			tmp1 = A11 + B1;
+			if ( tmp1 > tmp0 )
+			{
+				numer = tmp1 - tmp0;
+				denom = A00 - 2.0f * A01 + A11;
+				if ( numer >= denom )
+				{
+					S = 1.0f;
+					T = 0.0f;
+					sqrDist = A00 + 2.0f * B0 + C;
+					lv = 1;
+				}
+				else
+				{
+					if(fabs(denom) > FLT_EPSILON)
+						S = numer / denom;
+					else
+						S = 0.0f;
+					T = 1.0f - S;
+					sqrDist = S * ( A00 * S + A01 * T + 2.0f * B0 ) +
+							T * ( A01 * S + A11 * T + 2.0f * B1 ) + C;
+					le = 2;
+				}
+			}
 			else
 			{
-				//choose nearest
-				return choose_nearest(nearest_vertex, v0, point, closest);
+				S = 0.0f;
+				if ( tmp1 <= 0.0f )
+				{
+					T = 1.0f;
+					sqrDist = A11 + 2.0f * B1 + C;
+					lv = 2;
+				}
+				else if ( B1 >= 0.0f )
+				{
+					T = 0.0f;
+					sqrDist = C;
+					lv = 0;
+				}
+				else
+				{
+					if(fabs(A11) > FLT_EPSILON)
+						T = -B1 / A11;
+					else
+						T = 0.0f;
+					sqrDist = B1 * T + C;
+					le = 1;
+				}
 			}
-			i++;	//We can skip next edge
-			continue;
 		}
-
-		edge_slen = edge_di[0]*edge_di[0] + edge_di[1]*edge_di[1];	//squared edge len
-		//closest to this edge is v1
-		if(proj[0] > edge_slen)
+		else if ( T < 0.0f )  // Region 6
 		{
-			if(nearest_vertex == NULL || nearest_vertex == v1)
-				nearest_vertex = v1;
+			tmp0 = A01 + B1;
+			tmp1 = A00 + B0;
+			if ( tmp1 > tmp0 )
+			{
+				numer = tmp1 - tmp0;
+				denom = A00 - 2.0f * A01 + A11;
+				if ( numer >= denom )
+				{
+					T = 1.0f;
+					S = 0.0f;
+					sqrDist = A11 + 2.0f * B1 + C;
+					lv = 2;
+				}
+				else
+				{
+					if(fabs(denom) > FLT_EPSILON)
+						T = numer / denom;
+					else
+						T = 0.0f;
+					S = 1.0f - T;
+					sqrDist = S * ( A00 * S + A01 * T + 2.0f * B0 ) +
+							T * ( A01 * S + A11 * T + 2.0f * B1 ) + C;
+					le = 2;
+				}
+			}
 			else
 			{
-				return choose_nearest(nearest_vertex, v1, point, closest);
+				T = 0.0f;
+				if ( tmp1 <= 0.0f )
+				{
+					S = 1.0f;
+					sqrDist = A00 + 2.0f * B0 + C;
+					lv = 1;
+				}
+				else if ( B0 >= 0.0f )
+				{
+					S = 0.0f;
+					sqrDist = C;
+					lv = 0;
+				}
+				else
+				{
+					if(fabs(A00) > FLT_EPSILON)
+						S = -B0 / A00;
+					else
+						S = 0.0f;
+					sqrDist = B0 * S + C;
+					le = 0;
+				}
 			}
-			continue;
 		}
-
-		//nearest is on this edge
-		d= proj[1] / edge_slen;
-		closest[0] = point[0] - edge_di[1] * d;
-		closest[1] = point[1] + edge_di[0] * d;
-
-		return proj[1]*proj[1]/edge_slen;
+		else  // Region 1
+		{
+			numer = A11 + B1 - A01 - B0;
+			if ( numer <= 0.0f )
+			{
+				S = 0.0f;
+				T = 1.0f;
+				sqrDist = A11 + 2.0f * B1 + C;
+				lv = 2;
+			}
+			else
+			{
+				denom = A00 - 2.0f * A01 + A11;
+				if ( numer >= denom )
+				{
+					S = 1.0f;
+					T = 0.0f;
+					sqrDist = A00 + 2.0f * B0 + C;
+					lv = 1;
+				}
+				else
+				{
+					if(fabs(denom) > FLT_EPSILON)
+						S = numer / denom;
+					else
+						S = 0.0f;
+					T = 1.0f - S;
+					sqrDist = S * ( A00 * S + A01 * T + 2.0f * B0 ) +
+							T * ( A01 * S + A11 * T + 2.0f * B1 ) + C;
+					le = 2;
+				}
+			}
+		}
 	}
 
-	if(nearest_vertex)
+	// Account for numerical round-off error
+	if ( sqrDist < FLT_EPSILON )
+		sqrDist = 0.0f;
+	
 	{
-		VECSUB2D(v_point, nearest_vertex, point);
-		VECCOPY2D(closest, nearest_vertex);
-		return v_point[0]*v_point[0] + v_point[1]*v_point[1];
+		float w[3], x[3], y[3], z[3];
+		VECCOPY(w, v0);
+		VECCOPY(x, e0);
+		VecMulf(x, S);
+		VECCOPY(y, e1);
+		VecMulf(y, T);
+		VECADD(z, w, x);
+		VECADD(z, z, y);
+		VECSUB(d, p, z);
+		VECCOPY(nearest, z);
+		// d = p - ( v0 + S * e0 + T * e1 );
 	}
-	else
-	{
-		VECCOPY(closest, point);	//point is already inside
-		return 0.0f;
-	}
-}
+	*v = lv;
+	*e = le;
 
-/*
- * Returns the square of the minimum distance between the point and a triangle surface
- * If nearest is not NULL the nearest surface point is written on it
- */
-static float nearest_point_in_tri_surface(const float *point, const float *v0, const float *v1, const float *v2, float *nearest)
-{
-	//Lets solve the 2D problem (closest point-tri)
-	float normal_dist, plane_sdist, plane_offset;
-	float du[3], dv[3], dw[3];	//orthogonal axis (du=(v0->v1), dw=plane normal)
-
-	float p_2d[2], tri_2d[3][2], nearest_2d[2];
-
-	CalcNormFloat((float*)v0, (float*)v1, (float*)v2, dw);
-
-	//point-plane distance and calculate axis
-	normal_dist = point_plane_distance(point, v0, dw);
-
-	// OPTIMIZATION
-	//	if we are only interested in nearest distance if its closer than some distance already found
-	//  we can:
-	//		if(normal_dist*normal_dist >= best_dist_so_far) return FLOAT_MAX;
-	//
-
-	VECSUB(du, v1, v0);
-	Normalize(du);
-	Crossf(dv, dw, du);
-	plane_offset = INPR(v0, dw);
-
-	//project stuff to 2d
-	tri_2d[0][0] = INPR(du, v0);
-	tri_2d[0][1] = INPR(dv, v0);
-
-	tri_2d[1][0] = INPR(du, v1);
-	tri_2d[1][1] = INPR(dv, v1);
-
-	tri_2d[2][0] = INPR(du, v2);
-	tri_2d[2][1] = INPR(dv, v2);
-
-	p_2d[0] = INPR(du, point);
-	p_2d[1] = INPR(dv, point);
-
-	//we always have a right-handed tri
-	//this should always happen because of the way normal is calculated
-	plane_sdist = closest_point_in_tri2D(p_2d, tri_2d, nearest_2d);
-
-	//project back to 3d
-	if(nearest)
-	{
-		nearest[0] = du[0]*nearest_2d[0] + dv[0] * nearest_2d[1] + dw[0] * plane_offset;

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list