[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [14572] branches/soc-2008-jaguarandi/ source/blender: Implemented shrink modes are now:

André Pinto andresusanopinto at gmail.com
Sun Apr 27 21:29:40 CEST 2008


Revision: 14572
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=14572
Author:   jaguarandi
Date:     2008-04-27 21:29:40 +0200 (Sun, 27 Apr 2008)

Log Message:
-----------
Implemented shrink modes are now:
+ Nearest surface point
+ Normal projection
+ Nearest vertex (gives similar results to nearest surface if the target mesh has many vertexs and is a lot faster to calculate)
^^ all bruteforce calculation for now

+ fixed matrix order multiplication
+ request for CD_MDEDEFORMVERT

Modified Paths:
--------------
    branches/soc-2008-jaguarandi/source/blender/blenkernel/intern/modifier.c
    branches/soc-2008-jaguarandi/source/blender/blenkernel/intern/shrinkwrap.c
    branches/soc-2008-jaguarandi/source/blender/makesdna/DNA_modifier_types.h
    branches/soc-2008-jaguarandi/source/blender/src/buttons_editing.c

Modified: branches/soc-2008-jaguarandi/source/blender/blenkernel/intern/modifier.c
===================================================================
--- branches/soc-2008-jaguarandi/source/blender/blenkernel/intern/modifier.c	2008-04-27 19:20:35 UTC (rev 14571)
+++ branches/soc-2008-jaguarandi/source/blender/blenkernel/intern/modifier.c	2008-04-27 19:29:40 UTC (rev 14572)
@@ -6977,7 +6977,7 @@
 static void shrinkwrapModifier_initData(ModifierData *md)
 {
 	ShrinkwrapModifierData *smd = (ShrinkwrapModifierData*) md;
-	smd->shrinkType = MOD_SHRINKWRAP_NEAREST;
+	smd->shrinkType = MOD_SHRINKWRAP_NEAREST_SURFACE;
 }
 
 static void shrinkwrapModifier_copyData(ModifierData *md, ModifierData *target)
@@ -6985,6 +6985,17 @@
 	memcpy(target, md, sizeof(MeshDeformModifierData));
 }
 
+CustomDataMask shrinkwrapModifier_requiredDataMask(ModifierData *md)
+{
+	ShrinkwrapModifierData *smd = (ShrinkwrapModifierData *)md;
+	CustomDataMask dataMask = 0;
+
+	/* ask for vertexgroups if we need them */
+	if(smd->vgroup_name[0]) dataMask |= (1 << CD_MDEFORMVERT);
+
+	return dataMask;
+}
+
 static void shrinkwrapModifier_foreachObjectLink(ModifierData *md, Object *ob, ObjectWalkFunc walk, void *userData)
 {
 	ShrinkwrapModifierData *smd = (ShrinkwrapModifierData*) md;
@@ -7333,9 +7344,9 @@
 		mti = INIT_TYPE(Shrinkwrap);
 		mti->type = eModifierTypeType_Nonconstructive;
 		mti->flags = eModifierTypeFlag_AcceptsMesh;
-		/*| eModifierTypeFlag_SupportsMapping; Not yet X'D */
 		mti->initData = shrinkwrapModifier_initData;
 		mti->copyData = shrinkwrapModifier_copyData;
+		mti->requiredDataMask = shrinkwrapModifier_requiredDataMask;
 		mti->foreachObjectLink = shrinkwrapModifier_foreachObjectLink;
 		mti->applyModifier = shrinkwrapModifier_applyModifier;
 		mti->updateDepgraph = shrinkwrapModifier_updateDepgraph;

Modified: branches/soc-2008-jaguarandi/source/blender/blenkernel/intern/shrinkwrap.c
===================================================================
--- branches/soc-2008-jaguarandi/source/blender/blenkernel/intern/shrinkwrap.c	2008-04-27 19:20:35 UTC (rev 14571)
+++ branches/soc-2008-jaguarandi/source/blender/blenkernel/intern/shrinkwrap.c	2008-04-27 19:29:40 UTC (rev 14572)
@@ -28,6 +28,8 @@
  */
 #include <string.h>
 #include <float.h>
+#include <math.h>
+#include <stdio.h>
 #include <assert.h>
 //TODO: its late and I don't fill like adding ifs() printfs (I'll remove them on end)
 
@@ -40,22 +42,200 @@
 #include "BKE_utildefines.h"
 #include "BKE_deform.h"
 #include "BKE_cdderivedmesh.h"
+#include "BKE_global.h"
 
 #include "BLI_arithb.h"
 
-/* Projects the vertex on the normal direction over the target mesh */
-static void shrinkwrap_calc_normal_projection(DerivedMesh *target, float *co, short *no)
+#define CONST
+
+static void normal_short2float(CONST short *ns, float *nf)
 {
+	nf[0] = ns[0] / 32767.0f;
+	nf[1] = ns[1] / 32767.0f;
+	nf[2] = ns[2] / 32767.0f;
 }
 
-/* Nearest surface point on target mesh */
-static void shrinkwrap_calc_nearest_point(DerivedMesh *target, float *co, short *no)
+/*
+ * This calculates the distance (in dir units) that the ray must travel to intersect plane
+ * It can return negative values
+ *
+ * TODO theres probably something like this on blender code
+ *
+ * Returns FLT_MIN in parallel case
+ */
+static float ray_intersect_plane(CONST float *point, CONST float *dir, CONST float *plane_point, CONST float *plane_normal)
 {
-	//TODO: For now its only doing a nearest vertex on target mesh (just for testing other things)
+		float pp[3];
+		float a, pp_dist;
+
+		a = INPR(dir, plane_normal);
+
+		if(fabs(a) < 1e-5f) return FLT_MIN;
+
+		VecSubf(pp, point, plane_point);
+		pp_dist = INPR(pp, plane_normal);
+
+		return -pp_dist/a;
+}
+
+/*
+ * Returns the minimum distance between the point and a triangle surface
+ * Writes the nearest surface point in the given nearest
+ */
+static float nearest_point_in_tri_surface(CONST float *co, CONST float *v0, CONST float *v1, CONST float *v2, float *nearest)
+{
+	//TODO: make this efficient (probably this can be made with something like 3 point_in_slice())
+	if(point_in_tri_prism(co, v0, v1, v2))
+	{
+		float normal[3];
+		float dist;
+
+		CalcNormFloat(v0, v1, v2, normal);
+		dist = ray_intersect_plane(co, normal, v0, normal);
+
+		VECADDFAC(nearest, co, normal, dist);
+		return fabs(dist);
+	}
+	else
+	{
+		float dist = FLT_MAX, tdist;
+		float closest[3];
+
+		PclosestVL3Dfl(closest, co, v0, v1);
+		tdist = VecLenf(co, closest);
+		if(tdist < dist)
+		{
+			dist = tdist;
+			VECCOPY(nearest, closest);
+		}
+
+		PclosestVL3Dfl(closest, co, v1, v2);
+		tdist = VecLenf(co, closest);
+		if(tdist < dist)
+		{
+			dist = tdist;
+			VECCOPY(nearest, closest);
+		}
+
+		PclosestVL3Dfl(closest, co, v2, v0);
+		tdist = VecLenf(co, closest);
+		if(tdist < dist)
+		{
+			dist = tdist;
+			VECCOPY(nearest, closest);
+		}
+
+		return dist;
+	}
+}
+
+
+
+/*
+ * Shrink to nearest surface point on target mesh
+ */
+static void shrinkwrap_calc_nearest_surface_point(DerivedMesh *target, float *co, float *unused)
+{
+	//TODO: this should use raycast code probably existent in blender
 	float minDist = FLT_MAX;
 	float orig_co[3];
 
 	int i;
+	int	numFaces = target->getNumFaces(target);
+	MVert *vert = target->getVertDataArray(target, CD_MVERT);
+	MFace *face = target->getFaceDataArray(target, CD_MFACE);
+
+	VECCOPY(orig_co, co);
+
+	for (i = 0; i < numFaces; i++)
+	{
+		float *v0, *v1, *v2, *v3;
+
+		v0 = vert[ face[i].v1 ].co;
+		v1 = vert[ face[i].v2 ].co;
+		v2 = vert[ face[i].v3 ].co;
+		v3 = face[i].v4 ? vert[ face[i].v4 ].co : 0;
+
+		while(v2)
+		{
+			float dist;
+			float tmp[3];
+
+			dist = nearest_point_in_tri_surface(orig_co, v0, v1, v2, tmp);
+
+			if(dist < minDist)
+			{
+				minDist = dist;
+				VECCOPY(co, tmp);
+			}
+
+			v1 = v2;
+			v2 = v3;
+			v3 = 0;
+		}
+	}
+}
+
+/*
+ * Projects the vertex on the normal direction over the target mesh
+ */
+static void shrinkwrap_calc_normal_projection(DerivedMesh *target, float *co, float *vnormal)
+{
+	//TODO: this should use raycast code probably existent in blender
+	float minDist = FLT_MAX;
+	float orig_co[3];
+
+	int i;
+	int	numFaces = target->getNumFaces(target);
+	MVert *vert = target->getVertDataArray(target, CD_MVERT);
+	MFace *face = target->getFaceDataArray(target, CD_MFACE);
+
+	VECCOPY(orig_co, co);
+
+	for (i = 0; i < numFaces; i++)
+	{
+		float *v0, *v1, *v2, *v3;
+
+		v0 = vert[ face[i].v1 ].co;
+		v1 = vert[ face[i].v2 ].co;
+		v2 = vert[ face[i].v3 ].co;
+		v3 = face[i].v4 ? vert[ face[i].v4 ].co : 0;
+
+		while(v2)
+		{
+			float dist;
+			float pnormal[3];
+
+			CalcNormFloat(v0, v1, v2, pnormal);
+			dist =  ray_intersect_plane(orig_co, vnormal, v0, pnormal);
+
+			if(fabs(dist) < minDist)
+			{
+				float tmp[3], nearest[3];
+				VECADDFAC(tmp, orig_co, vnormal, dist);
+
+				if( fabs(nearest_point_in_tri_surface(tmp, v0, v1, v2, nearest)) < 0.0001)
+				{
+					minDist = fabs(dist);
+					VECCOPY(co, nearest);
+				}
+			}
+			v1 = v2;
+			v2 = v3;
+			v3 = 0;
+		}
+	}
+}
+
+/*
+ * Shrink to nearest vertex on target mesh
+ */
+static void shrinkwrap_calc_nearest_vertex(DerivedMesh *target, float *co, float *unused)
+{
+	float minDist = FLT_MAX;
+	float orig_co[3];
+
+	int i;
 	int	numVerts = target->getNumVerts(target);
 	MVert *vert = target->getVertDataArray(target, CD_MVERT);
 
@@ -65,7 +245,7 @@
 	{
 		float diff[3], sdist;
 		VECSUB(diff, orig_co, vert[i].co);
-		sdist = Inpf(diff, diff);
+		sdist = INPR(diff, diff);
 		
 		if(sdist < minDist)
 		{
@@ -75,6 +255,7 @@
 	}
 }
 
+/* Main shrinkwrap function */
 DerivedMesh *shrinkwrapModifier_do(ShrinkwrapModifierData *smd, Object *ob, DerivedMesh *dm, int useRenderParams, int isFinalCalc)
 {
 
@@ -90,38 +271,36 @@
 
 		MDeformVert *dvert = NULL;
 		MVert		*vert  = NULL;
+		DerivedMesh *target_dm = NULL;
 
 		float local2target[4][4], target2local[4][4];
 
-		DerivedMesh *target_dm = (DerivedMesh *)smd->target->derivedFinal;
-
 		numVerts = result->getNumVerts(result);
-		dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT);	//TODO: cddm doens't supports vertex groups :S
+		dvert = result->getVertDataArray(result, CD_MDEFORMVERT);
 		vert  = result->getVertDataArray(result, CD_MVERT);
 
-		/* TODO: Check about editMesh stuff :S */
-		/*
-		if(G.obedit && G.editMesh)
-			target_dm = CDDM_from_editmesh(G.editMesh, smd->target->data); // Needs release before returning
-		else
-		*/
+		target_dm = (DerivedMesh *)smd->target->derivedFinal;
+		if(!target_dm)
+		{
+			printf("Target derived mesh is null! :S\n");
+		}
 
 
+		//TODO should we reduce the number of matrix mults? by choosing applying matrixs to target or to derived mesh?
 		//Calculate matrixs for local <-> target
+		Mat4Invert (smd->target->imat, smd->target->obmat);	//inverse is outdated
 
-		//Update inverse matrixs
-		Mat4Invert (ob->imat, ob->obmat);
-		Mat4Invert (smd->target->imat, smd->target->obmat);
+		Mat4MulSerie(local2target, smd->target->imat, ob->obmat, 0, 0, 0, 0, 0, 0);
+		Mat4Invert(target2local, local2target);
 
-		Mat4MulSerie(local2target, ob->obmat, smd->target->imat, 0, 0, 0, 0, 0, 0);
-		Mat4MulSerie(target2local, smd->target->obmat, ob->imat, 0, 0, 0, 0, 0, 0);
 
-
 		//Shrink (calculate each vertex final position)
 		for(i = 0; i<numVerts; i++)
 		{
 			float weight;
+
 			float orig[3], final[3]; //Coords relative to target_dm
+			float normal[3];
 
 			if(dvert && vgroup >= 0)
 			{
@@ -135,23 +314,45 @@
 			}
 			else weight = 1.0f;
 
+			if(weight == 0.0f) continue;	//Skip vertexs where we have no influence
+
 			VecMat4MulVecfl(orig, local2target, vert[i].co);
-			
 			VECCOPY(final, orig);
-			shrinkwrap_calc_nearest_point(target_dm, final, vert[i].no);
 
-			//TODO linear interpolation: theres probably somewhere a function for this
-			final[0] = orig[0] + weight * (final[0] - orig[0]);
-			final[1] = orig[1] + weight * (final[1] - orig[1]);
-			final[2] = orig[2] + weight * (final[2] - orig[2]);
+			//We also need to apply the rotation to normal
+			if(smd->shrinkType == MOD_SHRINKWRAP_NORMAL)
+			{
+				normal_short2float(vert[i].no, normal);
+				Mat4Mul3Vecfl(local2target, normal);
+				Normalize(normal);	//Watch out for scaling (TODO: do we really needed a unit-len normal?)
+			}
 
+
+			switch(smd->shrinkType)
+			{
+				case MOD_SHRINKWRAP_NEAREST_SURFACE:
+					shrinkwrap_calc_nearest_surface_point(target_dm, final, normal);
+				break;
+
+				case MOD_SHRINKWRAP_NORMAL:
+					shrinkwrap_calc_normal_projection(target_dm, final, normal);
+				break;
+
+				case MOD_SHRINKWRAP_NEAREST_VERTEX:

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list