[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [11636] trunk/blender/source/blender: == Constraints - Geometry Targets ==

Joshua Leung aligorith at gmail.com
Fri Aug 17 13:23:49 CEST 2007


Revision: 11636
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=11636
Author:   aligorith
Date:     2007-08-17 13:23:48 +0200 (Fri, 17 Aug 2007)

Log Message:
-----------
== Constraints - Geometry Targets ==

It is now possible to use the geometry of Meshes and/or Lattices as the target of a constraint. All you need to do, is to create a new Vertex-Group and assign all the points that you wish to use as the target, then type that name into the VG: field for the relevant constraints.

One of the cases where this is beneficial is when you need to copy the location of a vertex. Now you don't need to make extra vertex-parents for that.

Additional Notes:
* The code takes the average of the locations of the nominated vertices, and puts that in world-space for constraint solving (and regular space-conversion stuff).
* Currently, rotation and scaling of points is not taken into account. The rotation/scaling used is from the object's matrix. Hopefully, this will only be a temporary problem (will be fixed soon)

Modified Paths:
--------------
    trunk/blender/source/blender/blenkernel/BKE_deform.h
    trunk/blender/source/blender/blenkernel/intern/constraint.c
    trunk/blender/source/blender/blenkernel/intern/deform.c
    trunk/blender/source/blender/src/buttons_object.c

Modified: trunk/blender/source/blender/blenkernel/BKE_deform.h
===================================================================
--- trunk/blender/source/blender/blenkernel/BKE_deform.h	2007-08-17 09:16:59 UTC (rev 11635)
+++ trunk/blender/source/blender/blenkernel/BKE_deform.h	2007-08-17 11:23:48 UTC (rev 11636)
@@ -46,6 +46,7 @@
 struct bDeformGroup *copy_defgroup (struct bDeformGroup *ingroup);
 struct bDeformGroup *get_named_vertexgroup (Object *ob, char *name);
 int get_defgroup_num (struct Object *ob, struct bDeformGroup *dg);
+int get_named_vertexgroup_num (Object *ob, char *name);
 void unique_vertexgroup_name (struct bDeformGroup *dg, struct Object *ob);
 
 #endif

Modified: trunk/blender/source/blender/blenkernel/intern/constraint.c
===================================================================
--- trunk/blender/source/blender/blenkernel/intern/constraint.c	2007-08-17 09:16:59 UTC (rev 11635)
+++ trunk/blender/source/blender/blenkernel/intern/constraint.c	2007-08-17 11:23:48 UTC (rev 11636)
@@ -45,6 +45,8 @@
 #include "DNA_object_types.h"
 #include "DNA_action_types.h"
 #include "DNA_curve_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_lattice_types.h"
 #include "DNA_scene_types.h"
 
 #include "BKE_utildefines.h"
@@ -54,12 +56,15 @@
 #include "BKE_blender.h"
 #include "BKE_constraint.h"
 #include "BKE_displist.h"
+#include "BKE_deform.h"
+#include "BKE_DerivedMesh.h"
 #include "BKE_object.h"
 #include "BKE_ipo.h"
 #include "BKE_global.h"
 #include "BKE_library.h"
 #include "BKE_idprop.h"
 
+
 #include "BPY_extern.h"
 
 #include "blendef.h"
@@ -1106,9 +1111,111 @@
 
 /* ------------------------------- Target ---------------------------- */
 
+/* function that sets the given matrix based on given vertex group in mesh */
+static void contarget_get_mesh_mat (Object *ob, char *substring, float mat[][4])
+{
+	DerivedMesh *dm = (DerivedMesh *)ob->derivedFinal;
+	float vec[3] = {0.0f, 0.0f, 0.0f}, tvec[3];
+	int dgroup;
+	
+	/* initialize target matrix using target matrix */
+	Mat4CpyMat4(mat, ob->obmat);
+	
+	/* get index of vertex group */
+	dgroup = get_named_vertexgroup_num(ob, substring);
+	if (dgroup < 0) return;
+	
+	/* only continue if there's a valid DerivedMesh */
+	if (dm) {
+		MDeformVert *dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT);
+		int *index = (int *)dm->getVertDataArray(dm, CD_ORIGINDEX);
+		int numVerts = dm->getNumVerts(dm);
+		int i, j, count = 0;
+		float co[3];
+		
+		/* get the average of all verts with that are in the vertex-group */
+		for (i = 0; i < numVerts; i++, index++) {	
+			for (j = 0; j < dvert[i].totweight; j++) {
+				/* does this vertex belong to nominated vertex group? */
+				if (dvert[i].dw[j].def_nr == dgroup) {
+					dm->getVertCo(dm, i, co);
+					VecAddf(vec, vec, co);
+					count++;
+					break;
+				}
+				
+			}
+		}
+		
+		/* calculate average, and apply as new location for matrix */
+		if (count > 0)
+			VecMulf(vec, 1.0f / count);
+		VecMat4MulVecfl(tvec, ob->obmat, vec);
+		
+		/* copy new location to matrix */
+		VECCOPY(mat[3], tvec);
+	}
+}
+
+/* function that sets the given matrix based on given vertex group in lattice */
+static void contarget_get_lattice_mat (Object *ob, char *substring, float mat[][4])
+{
+	Lattice *lt= (Lattice *)ob->data;
+	
+	DispList *dl = find_displist(&ob->disp, DL_VERTS);
+	float *co = dl?dl->verts:NULL;
+	BPoint *bp = lt->def;
+	
+	MDeformVert *dvert = lt->dvert;
+	int tot_verts= lt->pntsu*lt->pntsv*lt->pntsw;
+	float vec[3]= {0.0f, 0.0f, 0.0f}, tvec[3];
+	int dgroup=0, grouped=0;
+	int i, n;
+	
+	/* initialize target matrix using target matrix */
+	Mat4CpyMat4(mat, ob->obmat);
+	
+	/* get index of vertex group */
+	dgroup = get_named_vertexgroup_num(ob, substring);
+	if (dgroup < 0) return;
+	
+	/* 1. Loop through control-points checking if in nominated vertex-group.
+	 * 2. If it is, add it to vec to find the average point.
+	 */
+	for (i=0; i < tot_verts; i++, dvert++) {
+		for (n= 0; n < dvert->totweight; n++) {
+			/* found match - vert is in vgroup */
+			if (dvert->dw[n].def_nr == dgroup) {
+				/* copy coordinates of point to temporary vector, then add to find average */
+				if (co)
+					memcpy(tvec, co, 3*sizeof(float));
+				else
+					memcpy(tvec, bp->vec, 3*sizeof(float));
+					
+				VecAddf(vec, vec, tvec);
+				grouped++;
+				
+				break;
+			}
+		}
+		
+		/* advance pointer to coordinate data */
+		if (co) co+= 3;
+		else bp++;
+	}
+	
+	/* find average location, then multiply by ob->obmat to find world-space location */
+	if (grouped)
+		VecMulf(vec, 1.0f / grouped);
+	VecMat4MulVecfl(tvec, ob->obmat, vec);
+	
+	/* copy new location to matrix */
+	VECCOPY(mat[3], tvec);
+}
+
 /* generic function to get the appropriate matrix for most target cases */
 /* The cases where the target can be object data have not been implemented */
-static void constraint_target_to_mat4 (Object *ob, const char *substring, float mat[][4], short from, short to)
+static void constraint_target_to_mat4 (Object *ob, char *substring, float mat[][4], short from, short to)
 {
 	/*	Case OBJECT */
 	if (!strlen(substring)) {
@@ -1116,10 +1223,28 @@
 		constraint_mat_convertspace(ob, NULL, mat, from, to);
 	}
 	/* 	Case VERTEXGROUP */
-	else if (ELEM(ob->type, OB_MESH, OB_LATTICE)) {
-		/* devise a matrix from the data in the vertexgroup */
-		/* TODO: will be handled in other files */
+	/* Current method just takes the average location of all the points in the
+	 * VertexGroup, and uses that as the location value of the target's matrix 
+	 * instead. 
+	 *
+	 * TODO: figure out a way to find 3-points to define a rotation plane based
+	 *		on the normal of the triangle formed by those three points.
+	 * NOTE: editmode is not currently taken into consideration when doing this
+	 */
+	else if (ob->type == OB_MESH) {
+		/* devise a matrix from the vertices in the vertexgroup */
+		contarget_get_mesh_mat(ob, substring, mat);
+		
+		/* make sure it's in the right space for evaluation */
+		constraint_mat_convertspace(ob, NULL, mat, from, to);
 	}
+	else if (ob->type == OB_LATTICE) {
+		/* devise a matrix from the vertices in the vertexgroup */
+		contarget_get_lattice_mat(ob, substring, mat);
+		
+		/* make sure it's in the right space for evaluation */
+		constraint_mat_convertspace(ob, NULL, mat, from, to);
+	}
 	/*	Case BONE */
 	else {
 		bPoseChannel *pchan;
@@ -1313,7 +1438,10 @@
 			Object *ob= data->tar;
 			
 			if (data->tar) {
-				if (strlen(data->subtarget)) {
+				if (data->tar->type==OB_ARMATURE && strlen(data->subtarget)) {
+					/* Pose-Channels for the CopyLoc target are handled specially, so that
+					 * we can support using the bone-tip as an option.
+					 */
 					bPoseChannel *pchan;
 					float tmat[4][4];
 					
@@ -1334,10 +1462,8 @@
 					constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_WORLD, con->tarspace);
 				}
 				else {
-					Mat4CpyMat4(mat, ob->obmat);
-					
-					/* convert matrix space as required */
-					constraint_mat_convertspace(ob, NULL, mat, CONSTRAINT_SPACE_WORLD, con->tarspace);
+					/* get target matrix as is done normally for other constraints */
+					constraint_target_to_mat4(data->tar, data->subtarget, mat, CONSTRAINT_SPACE_WORLD, con->tarspace);
 				}
 				valid=1;
 			}
@@ -2664,10 +2790,10 @@
 		/* value should have been set from IPO's/Constraint Channels already */
 		enf = con->enforce;
 		
-		/* move target/owner into right spaces */
+		/* move owner into right space */
 		constraint_mat_convertspace(cob->ob, cob->pchan, cob->matrix, CONSTRAINT_SPACE_WORLD, con->ownspace);
 		
-		/* Get the target matrix */
+		/* Get the target matrix - in right space to be used */
 		ownerdata= ((cob->pchan)? (void *)cob->pchan : (void *)cob->ob);
 		get_constraint_target_matrix(con, cob->type, ownerdata, tarmat, ctime);
 		

Modified: trunk/blender/source/blender/blenkernel/intern/deform.c
===================================================================
--- trunk/blender/source/blender/blenkernel/intern/deform.c	2007-08-17 09:16:59 UTC (rev 11635)
+++ trunk/blender/source/blender/blenkernel/intern/deform.c	2007-08-17 11:23:48 UTC (rev 11636)
@@ -113,14 +113,31 @@
 	return NULL;
 }
 
-int get_defgroup_num (Object *ob, bDeformGroup	*dg)
+int get_named_vertexgroup_num (Object *ob, char *name)
 {
+	/* Return the location of the named deform group within the list of
+	 * deform groups. This function is a combination of get_defgroup_num and
+	 * get_named_vertexgroup. The other two could be called instead, but that
+	 * require looping over the vertexgroups twice.
+	 */
+	bDeformGroup *curdef;
+	int def_nr;
+	
+	for (curdef=ob->defbase.first, def_nr=0; curdef; curdef=curdef->next, def_nr++) {
+		if (!strcmp(curdef->name, name))
+			return def_nr;
+	}
+	
+	return -1;
+}
+
+int get_defgroup_num (Object *ob, bDeformGroup *dg)
+{
 	/* Fetch the location of this deform group
 	 * within the linked list of deform groups.
 	 * (this number is stored in the deform
 	 * weights of the deform verts to link them
-	 * to this deform group) deform deform
-	 * deform blah blah deform
+	 * to this deform group).
 	 */
 
 	bDeformGroup *eg;
@@ -129,8 +146,7 @@
 	eg = ob->defbase.first;
 	def_nr = 0;
 
-	/* loop through all deform groups
-	 */
+	/* loop through all deform groups */
 	while (eg != NULL) {
 
 		/* if the current deform group is

Modified: trunk/blender/source/blender/src/buttons_object.c
===================================================================
--- trunk/blender/source/blender/src/buttons_object.c	2007-08-17 09:16:59 UTC (rev 11635)
+++ trunk/blender/source/blender/src/buttons_object.c	2007-08-17 11:23:48 UTC (rev 11636)
@@ -540,12 +540,13 @@
 	uiBut *but;
 	char typestr[64], *subtarget;
 	short height, width = 265;
-	short is_armature_target, is_armature_owner;
+	short is_armature_target, is_geom_target, is_armature_owner;
 	int rb_col;
 
 	target= get_constraint_target(con, &subtarget);
 	is_armature_target= (target && target->type==OB_ARMATURE);
 	is_armature_owner= ((ob->type == OB_ARMATURE) && (ob->flag & OB_POSEMODE));
+	is_geom_target= (target && (ELEM(target->type, OB_MESH, OB_LATTICE)) );
 	
 	/* unless button has own callback, it adds this callback to button */
 	uiBlockSetFunc(block, constraint_active_func, ob, con);
@@ -639,6 +640,10 @@
 						but= uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "BO:", *xco+120, *yco-66,150,18, &data->subtarget, 0, 24, 0, 0, "Subtarget Bone");
 						uiButSetCompleteFunc(but, autocomplete_bone, (void *)data->tar);
 					}

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list