[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [29620] trunk/blender/source/blender/ editors/armature/meshlaplacian.c: Armature weighting / mesh deform no longer use render raytracing

Brecht Van Lommel brecht at blender.org
Tue Jun 22 17:10:57 CEST 2010


Revision: 29620
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=29620
Author:   blendix
Date:     2010-06-22 17:10:57 +0200 (Tue, 22 Jun 2010)

Log Message:
-----------
Armature weighting / mesh deform no longer use render raytracing
acceleration structure but BVH instead.

(merge from render25 branch)

Modified Paths:
--------------
    trunk/blender/source/blender/editors/armature/meshlaplacian.c

Modified: trunk/blender/source/blender/editors/armature/meshlaplacian.c
===================================================================
--- trunk/blender/source/blender/editors/armature/meshlaplacian.c	2010-06-22 15:09:41 UTC (rev 29619)
+++ trunk/blender/source/blender/editors/armature/meshlaplacian.c	2010-06-22 15:10:57 UTC (rev 29620)
@@ -52,8 +52,6 @@
 #include "BLI_polardecomp.h"
 #endif
 
-#include "RE_raytrace.h"
-
 #include "ONL_opennl.h"
 
 #include "BLO_sys_types.h" // for intptr_t support
@@ -107,8 +105,7 @@
 		float *p;			/* values from all p vectors */
 		float *mindist;		/* minimum distance to a bone for all vertices */
 		
-		RayObject *raytree;	/* ray tracing acceleration structure */
-		RayFace   *faces;	/* faces to add to the ray tracing struture */
+		BVHTree   *bvhtree;	/* ray tracing acceleration structure */
 		MFace     **vface;	/* a face that the vertex belongs to */
 	} heat;
 
@@ -396,29 +393,65 @@
 #define WEIGHT_LIMIT_END	0.025f
 #define DISTANCE_EPSILON	1e-4f
 
+typedef struct BVHCallbackUserData {
+	float start[3];
+	float vec[3];
+	LaplacianSystem *sys;
+} BVHCallbackUserData;
+
+static void bvh_callback(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit)
+{
+	BVHCallbackUserData *data = (struct BVHCallbackUserData*)userdata;
+	MFace *mf = data->sys->heat.mface + index;
+	float (*verts)[3] = data->sys->heat.verts;
+	float lambda, uv[2], n[3], dir[3];
+
+	mul_v3_v3fl(dir, data->vec, hit->dist);
+
+	if(isect_ray_tri_v3(data->start, dir, verts[mf->v1], verts[mf->v2], verts[mf->v3], &lambda, uv)) {
+		normal_tri_v3(n, verts[mf->v1], verts[mf->v2], verts[mf->v3]);
+		if(lambda < 1.0f && dot_v3v3(n, data->vec) < -1e-5f) {
+			hit->index = index;
+			hit->dist *= lambda;
+		}
+	}
+
+	mul_v3_v3fl(dir, data->vec, hit->dist);
+
+	if(isect_ray_tri_v3(data->start, dir, verts[mf->v1], verts[mf->v3], verts[mf->v4], &lambda, uv)) {
+		normal_tri_v3(n, verts[mf->v1], verts[mf->v3], verts[mf->v4]);
+		if(lambda < 1.0f && dot_v3v3(n, data->vec) < -1e-5f) {
+			hit->index = index;
+			hit->dist *= lambda;
+		}
+	}
+}
+
 /* Raytracing for vertex to bone/vertex visibility */
 static void heat_ray_tree_create(LaplacianSystem *sys)
 {
 	MFace *mface = sys->heat.mface;
+	float (*verts)[3] = sys->heat.verts;
 	int totface = sys->heat.totface;
 	int totvert = sys->heat.totvert;
 	int a;
 
-	sys->heat.raytree = RE_rayobject_vbvh_create(totface);
-	sys->heat.faces = MEM_callocN(sizeof(RayFace)*totface, "Heat RayFaces");
+	sys->heat.bvhtree = BLI_bvhtree_new(totface, 0.0f, 4, 6);
 	sys->heat.vface = MEM_callocN(sizeof(MFace*)*totvert, "HeatVFaces");
 
 	for(a=0; a<totface; a++) {
-	
 		MFace *mf = mface+a;
-		RayFace *rayface = sys->heat.faces+a;
+		float bb[6];
 
-		RayObject *obj = RE_rayface_from_coords(
-							rayface, &sys->heat, mf,
-							sys->heat.verts[mf->v1], sys->heat.verts[mf->v2],
-							sys->heat.verts[mf->v3], mf->v4 ? sys->heat.verts[mf->v4] : 0
-						);
-		RE_rayobject_add(sys->heat.raytree, obj); 
+		INIT_MINMAX(bb, bb+3);
+		DO_MINMAX(verts[mf->v1], bb, bb+3);
+		DO_MINMAX(verts[mf->v2], bb, bb+3);
+		DO_MINMAX(verts[mf->v3], bb, bb+3);
+		if(mf->v4) {
+			DO_MINMAX(verts[mf->v4], bb, bb+3);
+		}
+
+		BLI_bvhtree_insert(sys->heat.bvhtree, a, bb, 2);
 		
 		//Setup inverse pointers to use on isect.orig
 		sys->heat.vface[mf->v1]= mf;
@@ -426,12 +459,14 @@
 		sys->heat.vface[mf->v3]= mf;
 		if(mf->v4) sys->heat.vface[mf->v4]= mf;
 	}
-	RE_rayobject_done(sys->heat.raytree); 
+
+	BLI_bvhtree_balance(sys->heat.bvhtree); 
 }
 
 static int heat_ray_source_visible(LaplacianSystem *sys, int vertex, int source)
 {
-	Isect isec;
+    BVHTreeRayHit hit;
+	BVHCallbackUserData data;
 	MFace *mface;
 	float end[3];
 	int visible;
@@ -440,28 +475,25 @@
 	if(!mface)
 		return 1;
 
-	/* setup isec */
-	memset(&isec, 0, sizeof(isec));
-	isec.mode= RE_RAY_SHADOW;
-	isec.lay= -1;
-	isec.orig.ob = &sys->heat;
-	isec.orig.face = mface;
-	isec.skip = RE_SKIP_CULLFACE;
-	
-	copy_v3_v3(isec.start, sys->heat.verts[vertex]);
+	data.sys= sys;
+	copy_v3_v3(data.start, sys->heat.verts[vertex]);
 
 	if(sys->heat.root) /* bone */
-		closest_to_line_segment_v3(end, isec.start,
+		closest_to_line_segment_v3(end, data.start,
 			sys->heat.root[source], sys->heat.tip[source]);
 	else /* vertex */
 		copy_v3_v3(end, sys->heat.source[source]);
 
-	sub_v3_v3v3(isec.vec, end, isec.start);
-	isec.labda = 1.0f - 1e-5;
-	madd_v3_v3v3fl(isec.start, isec.start, isec.vec, 1e-5);
+	sub_v3_v3v3(data.vec, end, data.start);
+	madd_v3_v3v3fl(data.start, data.start, data.vec, 1e-5);
+	mul_v3_fl(data.vec, 1.0f - 2e-5);
 
-	visible= !RE_rayobject_raycast(sys->heat.raytree, &isec);
+	/* pass normalized vec + distance to bvh */
+	hit.index = -1;
+	hit.dist = normalize_v3(data.vec);
 
+	visible= BLI_bvhtree_ray_cast(sys->heat.bvhtree, data.start, data.vec, 0.0f, &hit, bvh_callback, (void*)&data) == -1;
+
 	return visible;
 }
 
@@ -587,9 +619,8 @@
 
 static void heat_system_free(LaplacianSystem *sys)
 {
-	RE_rayobject_free(sys->heat.raytree);
+	BLI_bvhtree_free(sys->heat.bvhtree);
 	MEM_freeN(sys->heat.vface);
-	MEM_freeN(sys->heat.faces);
 
 	MEM_freeN(sys->heat.mindist);
 	MEM_freeN(sys->heat.H);
@@ -1050,11 +1081,19 @@
 
 	/* direct solver */
 	int *varidx;
-
-	/* raytrace */
-	RayObject *raytree;
 } MeshDeformBind;
 
+typedef struct MeshDeformIsect {
+	float start[3];
+	float vec[3];
+	float labda;
+
+	void *face;
+	int isect;
+	float u, v;
+	
+} MeshDeformIsect;
+
 /* ray intersection */
 
 /* our own triangle intersection, so we can fully control the epsilons and
@@ -1117,65 +1156,9 @@
 	return 1;
 }
 
-/* blender's raytracer is not use now, even though it is much faster. it can
- * give problems with rays falling through, so we use our own intersection 
- * function above with tweaked epsilons */
-
-#if 0
-static MeshDeformBind *MESHDEFORM_BIND = NULL;
-
-static void meshdeform_ray_coords_func(RayFace *face, float **v1, float **v2, float **v3, float **v4)
+static int meshdeform_intersect(MeshDeformBind *mdb, MeshDeformIsect *isec)
 {
-	MFace *mface= (MFace*)face;
-	float (*cagecos)[3]= MESHDEFORM_BIND->cagecos;
-
-	*v1= cagecos[mface->v1];
-	*v2= cagecos[mface->v2];
-	*v3= cagecos[mface->v3];
-	*v4= (mface->v4)? cagecos[mface->v4]: NULL;
-}
-
-static int meshdeform_ray_check_func(Isect *is, RayFace *face)
-{
-	return 1;
-}
-
-static void meshdeform_ray_tree_create(MeshDeformBind *mdb)
-{
 	MFace *mface;
-	float min[3], max[3];
-	int a, totface;
-
-	/* create a raytrace tree from the mesh */
-	INIT_MINMAX(min, max);
-
-	for(a=0; a<mdb->totcagevert; a++)
-		DO_MINMAX(mdb->cagecos[a], min, max)
-
-	MESHDEFORM_BIND= mdb;
-
-	mface= mdb->cagedm->getFaceArray(mdb->cagedm);
-	totface= mdb->cagedm->getNumFaces(mdb->cagedm);
-
-	mdb->raytree= RE_ray_tree_create(64, totface, min, max,
-		meshdeform_ray_coords_func, meshdeform_ray_check_func);
-
-	for(a=0; a<totface; a++, mface++)
-		RE_ray_tree_add_face(mdb->raytree, mface);
-
-	RE_ray_tree_done(mdb->raytree);
-}
-
-static void meshdeform_ray_tree_free(MeshDeformBind *mdb)
-{
-	MESHDEFORM_BIND= NULL;
-	RE_ray_tree_free(mdb->raytree);
-}
-#endif
-
-static int meshdeform_intersect(MeshDeformBind *mdb, Isect *isec)
-{
-	MFace *mface;
 	float face[4][3], co[3], uvw[3], len, nor[3], end[3];
 	int f, hit, is= 0, totface;
 
@@ -1212,7 +1195,7 @@
 			len= len_v3v3(isec->start, co)/len_v3v3(isec->start, end);
 			if(len < isec->labda) {
 				isec->labda= len;
-				isec->hit.face = mface;
+				isec->face = mface;
 				isec->isect= (INPR(isec->vec, nor) <= 0.0f);
 				is= 1;
 			}
@@ -1225,7 +1208,7 @@
 static MDefBoundIsect *meshdeform_ray_tree_intersect(MeshDeformBind *mdb, float *co1, float *co2)
 {
 	MDefBoundIsect *isect;
-	Isect isec;
+	MeshDeformIsect isec;
 	float (*cagecos)[3];
 	MFace *mface;
 	float vert[4][3], len, end[3];
@@ -1233,21 +1216,15 @@
 
 	/* setup isec */
 	memset(&isec, 0, sizeof(isec));
-	isec.mode= RE_RAY_MIRROR; /* we want the closest intersection */
-	isec.lay= -1;
 	isec.labda= 1e10f;
 
 	VECADD(isec.start, co1, epsilon);
 	VECADD(end, co2, epsilon);
 	sub_v3_v3v3(isec.vec, end, isec.start);
 
-#if 0
-	/*if(RE_ray_tree_intersect(mdb->raytree, &isec)) {*/
-#endif
-
 	if(meshdeform_intersect(mdb, &isec)) {
 		len= isec.labda;
-		mface=(MFace*)isec.hit.face;
+		mface=(MFace*)isec.face;
 
 		/* create MDefBoundIsect */
 		isect= BLI_memarena_alloc(mdb->memarena, sizeof(*isect));
@@ -1790,11 +1767,6 @@
 
 	progress_bar(0, "Setting up mesh deform system");
 
-#if 0
-	/* create ray tree */
-	meshdeform_ray_tree_create(mdb);
-#endif
-
 	totinside= 0;
 	for(a=0; a<mdb->totvert; a++) {
 		copy_v3_v3(vec, mdb->vertexcos[a]);
@@ -1817,11 +1789,6 @@
 			for(x=0; x<mdb->size; x++)
 				meshdeform_add_intersections(mdb, x, y, z);
 
-#if 0
-	/* free ray tree */
-	meshdeform_ray_tree_free(mdb);
-#endif
-
 	/* compute exterior and interior tags */
 	meshdeform_bind_floodfill(mdb);
 





More information about the Bf-blender-cvs mailing list