Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoshua Leung <aligorith@gmail.com>2007-08-17 15:23:48 +0400
committerJoshua Leung <aligorith@gmail.com>2007-08-17 15:23:48 +0400
commit400d77bbe29ddecaaa4530146f07435877f9a6aa (patch)
treedfb746811c78f111784679e2b1895669939f0a6b /source/blender/blenkernel/intern
parent4d884c0fbfd8c7588f6e082adc8925a8df44be24 (diff)
== 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)
Diffstat (limited to 'source/blender/blenkernel/intern')
-rw-r--r--source/blender/blenkernel/intern/constraint.c148
-rw-r--r--source/blender/blenkernel/intern/deform.c26
2 files changed, 158 insertions, 16 deletions
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
index 205feb15ab3..651b8a102e9 100644
--- a/source/blender/blenkernel/intern/constraint.c
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -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 @@ void constraint_mat_convertspace (Object *ob, bPoseChannel *pchan, float mat[][4
/* ------------------------------- 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,9 +1223,27 @@ static void constraint_target_to_mat4 (Object *ob, const char *substring, float
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 {
@@ -1313,7 +1438,10 @@ short get_constraint_target_matrix (bConstraint *con, short ownertype, void *own
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 @@ short get_constraint_target_matrix (bConstraint *con, short ownertype, void *own
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 @@ void solve_constraints (ListBase *conlist, bConstraintOb *cob, float ctime)
/* 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);
diff --git a/source/blender/blenkernel/intern/deform.c b/source/blender/blenkernel/intern/deform.c
index aa6220e88bc..9356ba14071 100644
--- a/source/blender/blenkernel/intern/deform.c
+++ b/source/blender/blenkernel/intern/deform.c
@@ -113,14 +113,31 @@ bDeformGroup *get_named_vertexgroup (Object *ob, char *name)
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 @@ int get_defgroup_num (Object *ob, bDeformGroup *dg)
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