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:
authorBrecht Van Lommel <brechtvanlommel@pandora.be>2007-07-29 01:04:30 +0400
committerBrecht Van Lommel <brechtvanlommel@pandora.be>2007-07-29 01:04:30 +0400
commit8742899f5e3ef3b76c5fa2227ab3df3bdc0e1ef9 (patch)
tree872416258cce5ee4eea00f6f0efc91ba862634c7 /source/blender/blenkernel
parent0281bdac765ce750df349b82abf8ced970ca65fd (diff)
Armature CrazySpace Improvement
=============================== An improved CrazySpace correction is now used for Armature modifiers that use vertex groups, and that are the first enabled modifiers in the stack. This is a a specific case, but also a common one. http://www.blender.org/development/current-projects/changes-since-244/skinning/ Implementation Notes: - The quaternion crazyspace correction is still used for modifiers other than the armature modifier. - Modifiers can now provide a deform matrix per vertex to be used for crazyspace correction, only the armature modifier implements this now.
Diffstat (limited to 'source/blender/blenkernel')
-rw-r--r--source/blender/blenkernel/BKE_DerivedMesh.h5
-rw-r--r--source/blender/blenkernel/BKE_lattice.h4
-rw-r--r--source/blender/blenkernel/BKE_modifier.h6
-rw-r--r--source/blender/blenkernel/intern/DerivedMesh.c82
-rw-r--r--source/blender/blenkernel/intern/armature.c144
-rw-r--r--source/blender/blenkernel/intern/modifier.c46
6 files changed, 221 insertions, 66 deletions
diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h
index 872717fdb9b..4a19bfb9249 100644
--- a/source/blender/blenkernel/BKE_DerivedMesh.h
+++ b/source/blender/blenkernel/BKE_DerivedMesh.h
@@ -425,6 +425,11 @@ DerivedMesh *editmesh_get_derived_cage(CustomDataMask dataMask);
DerivedMesh *editmesh_get_derived_cage_and_final(DerivedMesh **final_r,
CustomDataMask dataMask);
+/* returns an array of deform matrices for crazyspace correction, and the
+ number of modifiers left */
+int editmesh_get_first_deform_matrices(float (**deformmats)[3][3],
+ float (**deformcos)[3]);
+
void weight_to_rgb(float input, float *fr, float *fg, float *fb);
/* determines required DerivedMesh data according to view and edit modes */
diff --git a/source/blender/blenkernel/BKE_lattice.h b/source/blender/blenkernel/BKE_lattice.h
index 55eb1d27cc0..3dc4b49b52b 100644
--- a/source/blender/blenkernel/BKE_lattice.h
+++ b/source/blender/blenkernel/BKE_lattice.h
@@ -64,8 +64,8 @@ void lattice_deform_verts(struct Object *laOb, struct Object *target,
int numVerts, char *vgroup);
void armature_deform_verts(struct Object *armOb, struct Object *target,
struct DerivedMesh *dm, float (*vertexCos)[3],
- int numVerts, int deformflag,
- const char *defgrp_name);
+ float (*defMats)[3][3], int numVerts,
+ int deformflag, const char *defgrp_name);
float (*lattice_getVertexCos(struct Object *ob, int *numVerts_r))[3];
void lattice_applyVertexCos(struct Object *ob, float (*vertexCos)[3]);
void lattice_calc_modifiers(struct Object *ob);
diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h
index ce3f33bd35c..297443b883d 100644
--- a/source/blender/blenkernel/BKE_modifier.h
+++ b/source/blender/blenkernel/BKE_modifier.h
@@ -125,6 +125,11 @@ typedef struct ModifierTypeInfo {
struct EditMesh *editData, struct DerivedMesh *derivedData,
float (*vertexCos)[3], int numVerts);
+ /* Set deform matrix per vertex for crazyspace correction */
+ void (*deformMatricesEM)(
+ struct ModifierData *md, struct Object *ob,
+ struct EditMesh *editData, struct DerivedMesh *derivedData,
+ float (*vertexCos)[3], float (*defMats)[3][3], int numVerts);
/********************* Non-deform modifier functions *********************/
@@ -257,6 +262,7 @@ void modifier_copyData(struct ModifierData *md, struct ModifierData *ta
int modifier_dependsOnTime(struct ModifierData *md);
int modifier_supportsMapping(struct ModifierData *md);
int modifier_couldBeCage(struct ModifierData *md);
+int modifier_isDeformer(struct ModifierData *md);
void modifier_setError(struct ModifierData *md, char *format, ...);
void modifiers_foreachObjectLink(struct Object *ob,
diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c
index 5f8e9c7b207..be1d39d6c8c 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.c
+++ b/source/blender/blenkernel/intern/DerivedMesh.c
@@ -1887,6 +1887,24 @@ static float (*editmesh_getVertexCos(EditMesh *em, int *numVerts_r))[3]
return cos;
}
+static int editmesh_modifier_is_enabled(ModifierData *md, DerivedMesh *dm)
+{
+ ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+ int required_mode = eModifierMode_Realtime | eModifierMode_Editmode;
+
+ if((md->mode & required_mode) != required_mode) return 0;
+ if((mti->flags & eModifierTypeFlag_RequiresOriginalData) && dm) {
+ modifier_setError(md, "Internal error, modifier requires"
+ "original data (bad stack position).");
+ return 0;
+ }
+ if(mti->isDisabled && mti->isDisabled(md)) return 0;
+ if(!(mti->flags & eModifierTypeFlag_SupportsEditmode)) return 0;
+ if(md->mode & eModifierMode_DisableTemporary) return 0;
+
+ return 1;
+}
+
static void editmesh_calc_modifiers(DerivedMesh **cage_r,
DerivedMesh **final_r,
CustomDataMask dataMask)
@@ -1897,7 +1915,6 @@ static void editmesh_calc_modifiers(DerivedMesh **cage_r,
float (*deformedVerts)[3] = NULL;
DerivedMesh *dm;
int i, numVerts = 0, cageIndex = modifiers_getCageIndex(ob, NULL);
- int required_mode = eModifierMode_Realtime | eModifierMode_Editmode;
LinkNode *datamasks, *curr;
modifiers_clearErrors(ob);
@@ -1918,14 +1935,8 @@ static void editmesh_calc_modifiers(DerivedMesh **cage_r,
for(i = 0; md; i++, md = md->next, curr = curr->next) {
ModifierTypeInfo *mti = modifierType_getInfo(md->type);
- if((md->mode & required_mode) != required_mode) continue;
- if((mti->flags & eModifierTypeFlag_RequiresOriginalData) && dm) {
- modifier_setError(md, "Internal error, modifier requires"
- "original data (bad stack position).");
+ if(!editmesh_modifier_is_enabled(md, dm))
continue;
- }
- if(mti->isDisabled && mti->isDisabled(md)) continue;
- if(!(mti->flags & eModifierTypeFlag_SupportsEditmode)) continue;
/* How to apply modifier depends on (a) what we already have as
* a result of previous modifiers (could be a DerivedMesh or just
@@ -2461,6 +2472,61 @@ float *mesh_get_mapped_verts_nors(Object *ob)
return vertexcosnos;
}
+/* ********* crazyspace *************** */
+
+int editmesh_get_first_deform_matrices(float (**deformmats)[3][3], float (**deformcos)[3])
+{
+ Object *ob = G.obedit;
+ EditMesh *em = G.editMesh;
+ ModifierData *md;
+ DerivedMesh *dm;
+ int i, a, numleft = 0, numVerts = 0;
+ int cageIndex = modifiers_getCageIndex(ob, NULL);
+ float (*defmats)[3][3] = NULL, (*deformedVerts)[3] = NULL;
+
+ modifiers_clearErrors(ob);
+
+ dm = NULL;
+ md = ob->modifiers.first;
+
+ /* compute the deformation matrices and coordinates for the first
+ modifiers with on cage editing that are enabled and support computing
+ deform matrices */
+ for(i = 0; md && i <= cageIndex; i++, md = md->next) {
+ ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+
+ if(!editmesh_modifier_is_enabled(md, dm))
+ continue;
+
+ if(mti->type==eModifierTypeType_OnlyDeform && mti->deformMatricesEM) {
+ if(!defmats) {
+ dm= getEditMeshDerivedMesh(em, ob, NULL);
+ deformedVerts= editmesh_getVertexCos(em, &numVerts);
+ defmats= MEM_callocN(sizeof(*defmats)*numVerts, "defmats");
+
+ for(a=0; a<numVerts; a++)
+ Mat3One(defmats[a]);
+ }
+
+ mti->deformMatricesEM(md, ob, em, dm, deformedVerts, defmats,
+ numVerts);
+ }
+ else
+ break;
+ }
+
+ for(; md && i <= cageIndex; md = md->next, i++)
+ if(editmesh_modifier_is_enabled(md, dm) && modifier_isDeformer(md))
+ numleft++;
+
+ if(dm)
+ dm->release(dm);
+
+ *deformmats= defmats;
+ *deformcos= deformedVerts;
+
+ return numleft;
+}
/* ************************* fluidsim bobj file handling **************************** */
diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c
index b320a7e0106..db384181982 100644
--- a/source/blender/blenkernel/intern/armature.c
+++ b/source/blender/blenkernel/intern/armature.c
@@ -504,39 +504,54 @@ static void pchan_b_bone_defmats(bPoseChannel *pchan)
Bone *bone= pchan->bone;
Mat4 *b_bone= b_bone_spline_setup(pchan);
Mat4 *b_bone_mats;
+ float tmat[4][4];
int a;
- pchan->b_bone_mats=b_bone_mats= MEM_mallocN((1+bone->segments)*sizeof(Mat4), "BBone defmats");
-
- /* first matrix is the inverse arm_mat, to bring points in local bone space */
+ /* allocate b_bone matrices and dual quats */
+ b_bone_mats= MEM_mallocN((1+bone->segments)*sizeof(Mat4), "BBone defmats");
+ pchan->b_bone_mats= b_bone_mats;
+
+ /* first matrix is the inverse arm_mat, to bring points in local bone space
+ for finding out which segment it belongs to */
Mat4Invert(b_bone_mats[0].mat, bone->arm_mat);
-
- /* then we multiply the bbone_mats with arm_mat */
+
+ /* then we make the b_bone_mats:
+ - first transform to local bone space
+ - translate over the curve to the bbone mat space
+ - transform with b_bone matrix
+ - transform back into global space */
+ Mat4One(tmat);
+
for(a=0; a<bone->segments; a++) {
- Mat4MulMat4(b_bone_mats[a+1].mat, b_bone[a].mat, bone->arm_mat);
+ tmat[3][1] = -a*(bone->length/(float)bone->segments);
+
+ Mat4MulSerie(b_bone_mats[a+1].mat, pchan->chan_mat, bone->arm_mat,
+ b_bone[a].mat, tmat, b_bone_mats[0].mat, NULL, NULL, NULL);
}
}
-static void b_bone_deform(bPoseChannel *pchan, Bone *bone, float *defpos)
+static void b_bone_deform(bPoseChannel *pchan, Bone *bone, float *co, float defmat[][3])
{
Mat4 *b_bone= pchan->b_bone_mats;
- float segment;
+ float (*mat)[4]= b_bone[0].mat;
+ float segment, y;
int a;
- /* need to transform defpos back to bonespace */
- Mat4MulVecfl(b_bone[0].mat, defpos);
+ /* need to transform co back to bonespace, only need y */
+ y= mat[0][1]*co[0] + mat[1][1]*co[1] + mat[2][1]*co[2] + mat[3][1];
/* now calculate which of the b_bones are deforming this */
segment= bone->length/((float)bone->segments);
- a= (int) (defpos[1]/segment);
+ a= (int)(y/segment);
- /* note; by clamping it extends deform at endpoints, goes best with straight joints in restpos. */
+ /* note; by clamping it extends deform at endpoints, goes best with
+ straight joints in restpos. */
CLAMP(a, 0, bone->segments-1);
- /* since the bbone mats translate from (0.0.0) on the curve, we subtract */
- defpos[1] -= ((float)a)*segment;
-
- Mat4MulVecfl(b_bone[a+1].mat, defpos);
+ Mat4MulVecfl(b_bone[a+1].mat, co);
+
+ if(defmat)
+ Mat3CpyMat4(defmat, b_bone[a+1].mat);
}
/* using vec with dist to bone b1 - b2 */
@@ -590,12 +605,24 @@ float distfactor_to_bone (float vec[3], float b1[3], float b2[3], float rad1, fl
}
}
-static float dist_bone_deform(bPoseChannel *pchan, float *vec, float *co)
+static void pchan_deform_mat_add(bPoseChannel *pchan, float weight, float bbonemat[][3], float mat[][3])
+{
+ float wmat[3][3];
+
+ if(pchan->bone->segments>1)
+ Mat3CpyMat3(wmat, bbonemat);
+ else
+ Mat3CpyMat4(wmat, pchan->chan_mat);
+
+ Mat3MulFloat((float*)wmat, weight);
+ Mat3AddMat3(mat, mat, wmat);
+}
+
+static float dist_bone_deform(bPoseChannel *pchan, float *vec, float mat[][3], float *co)
{
Bone *bone= pchan->bone;
- float fac;
- float cop[3];
- float contrib=0.0;
+ float fac, contrib=0.0;
+ float cop[3], bbonemat[3][3];
if(bone==NULL) return 0.0f;
@@ -603,52 +630,58 @@ static float dist_bone_deform(bPoseChannel *pchan, float *vec, float *co)
fac= distfactor_to_bone(cop, bone->arm_head, bone->arm_tail, bone->rad_head, bone->rad_tail, bone->dist);
- if (fac>0.0){
+ if (fac>0.0) {
fac*=bone->weight;
contrib= fac;
if(contrib>0.0) {
-
- VECCOPY (cop, co);
-
if(bone->segments>1)
- b_bone_deform(pchan, bone, cop); // applies on cop
-
- Mat4MulVecfl(pchan->chan_mat, cop);
-
- VecSubf (cop, cop, co); // Make this a delta from the base position
+ // applies on cop and bbonemat
+ b_bone_deform(pchan, bone, cop, (mat)?bbonemat:NULL);
+ else
+ Mat4MulVecfl(pchan->chan_mat, cop);
+
+ // Make this a delta from the base position
+ VecSubf (cop, cop, co);
cop[0]*=fac; cop[1]*=fac; cop[2]*=fac;
VecAddf (vec, vec, cop);
+
+ if(mat)
+ pchan_deform_mat_add(pchan, fac, bbonemat, mat);
}
}
return contrib;
}
-static void pchan_bone_deform(bPoseChannel *pchan, float weight, float *vec, float *co, float *contrib)
+static void pchan_bone_deform(bPoseChannel *pchan, float weight, float *vec, float mat[][3], float *co, float *contrib)
{
- float cop[3];
+ float cop[3], bbonemat[3][3];
if (!weight)
return;
- VECCOPY (cop, co);
-
+ VECCOPY(cop, co);
+
if(pchan->bone->segments>1)
- b_bone_deform(pchan, pchan->bone, cop); // applies on cop
-
- Mat4MulVecfl(pchan->chan_mat, cop);
+ // applies on cop and bbonemat
+ b_bone_deform(pchan, pchan->bone, cop, (mat)?bbonemat:NULL);
+ else
+ Mat4MulVecfl(pchan->chan_mat, cop);
vec[0]+=(cop[0]-co[0])*weight;
vec[1]+=(cop[1]-co[1])*weight;
vec[2]+=(cop[2]-co[2])*weight;
+ if(mat)
+ pchan_deform_mat_add(pchan, weight, bbonemat, mat);
+
(*contrib)+=weight;
}
void armature_deform_verts(Object *armOb, Object *target, DerivedMesh *dm,
- float (*vertexCos)[3], int numVerts, int deformflag,
- const char *defgrp_name)
+ float (*vertexCos)[3], float (*defMats)[3][3],
+ int numVerts, int deformflag, const char *defgrp_name)
{
bPoseChannel *pchan, **defnrToPC = NULL;
MDeformVert *dverts = NULL;
@@ -669,12 +702,11 @@ void armature_deform_verts(Object *armOb, Object *target, DerivedMesh *dm,
/* bone defmats are already in the channels, chan_mat */
- /* initialize B_bone matrices */
- for(pchan = armOb->pose->chanbase.first; pchan; pchan = pchan->next) {
+ /* initialize B_bone matrices and dual quaternions */
+ for(pchan = armOb->pose->chanbase.first; pchan; pchan = pchan->next)
if(!(pchan->bone->flag & BONE_NO_DEFORM))
if(pchan->bone->segments > 1)
pchan_b_bone_defmats(pchan);
- }
/* get the def_nr for the overall armature vertex group if present */
for(i = 0, dg = target->defbase.first; dg; i++, dg = dg->next)
@@ -723,6 +755,7 @@ void armature_deform_verts(Object *armOb, Object *target, DerivedMesh *dm,
for(i = 0; i < numVerts; i++) {
MDeformVert *dvert;
float *co = vertexCos[i];
+ float summat[3][3], (*smat)[3] = NULL;
float vec[3];
float contrib = 0.0f;
float armature_weight = 1.0f; /* default to 1 if no overall def group */
@@ -730,6 +763,11 @@ void armature_deform_verts(Object *armOb, Object *target, DerivedMesh *dm,
vec[0] = vec[1] = vec[2] = 0.0f;
+ if(defMats) {
+ Mat3Clr((float*)summat);
+ smat = summat;
+ }
+
if(use_dverts || armature_def_nr >= 0) {
if(dm) dvert = dm->getVertData(dm, i, CD_MDEFORMVERT);
else if(dverts && i < target_totvert) dvert = dverts + i;
@@ -772,7 +810,7 @@ void armature_deform_verts(Object *armOb, Object *target, DerivedMesh *dm,
bone->rad_tail,
bone->dist);
}
- pchan_bone_deform(pchan, weight, vec, co, &contrib);
+ pchan_bone_deform(pchan, weight, vec, smat, co, &contrib);
}
}
/* if there are vertexgroups but not groups with bones
@@ -782,7 +820,7 @@ void armature_deform_verts(Object *armOb, Object *target, DerivedMesh *dm,
for(pchan = armOb->pose->chanbase.first; pchan;
pchan = pchan->next) {
if(!(pchan->bone->flag & BONE_NO_DEFORM))
- contrib += dist_bone_deform(pchan, vec, co);
+ contrib += dist_bone_deform(pchan, vec, smat, co);
}
}
}
@@ -790,15 +828,31 @@ void armature_deform_verts(Object *armOb, Object *target, DerivedMesh *dm,
for(pchan = armOb->pose->chanbase.first; pchan;
pchan = pchan->next) {
if(!(pchan->bone->flag & BONE_NO_DEFORM))
- contrib += dist_bone_deform(pchan, vec, co);
+ contrib += dist_bone_deform(pchan, vec, smat, co);
}
}
/* actually should be EPSILON? weight values and contrib can be like 10e-39 small */
if(contrib > 0.0001f) {
- VecMulf(vec, armature_weight / contrib);
+ float scale = armature_weight/contrib;
+
+ VecMulf(vec, scale);
VecAddf(co, vec, co);
+
+ if(defMats) {
+ float pre[3][3], post[3][3], tmpmat[3][3];
+
+ Mat3CpyMat4(pre, premat);
+ Mat3CpyMat4(post, postmat);
+ Mat3CpyMat3(tmpmat, defMats[i]);
+
+ Mat3MulFloat((float*)smat, scale);
+ Mat3MulSerie(defMats[i], tmpmat, pre, smat, post,
+ NULL, NULL, NULL, NULL);
+ }
+
}
+
/* always, check above code */
Mat4MulVecfl(postmat, co);
}
diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c
index dd65eba0df9..d6fa8d1d3d6 100644
--- a/source/blender/blenkernel/intern/modifier.c
+++ b/source/blender/blenkernel/intern/modifier.c
@@ -4577,8 +4577,8 @@ static void armatureModifier_deformVerts(
{
ArmatureModifierData *amd = (ArmatureModifierData*) md;
- armature_deform_verts(amd->object, ob, derivedData, vertexCos, numVerts,
- amd->deformflag, amd->defgrp_name);
+ armature_deform_verts(amd->object, ob, derivedData, vertexCos, NULL,
+ numVerts, amd->deformflag, amd->defgrp_name);
}
static void armatureModifier_deformVertsEM(
@@ -4590,7 +4590,23 @@ static void armatureModifier_deformVertsEM(
if(!derivedData) dm = CDDM_from_editmesh(editData, ob->data);
- armature_deform_verts(amd->object, ob, dm, vertexCos, numVerts,
+ armature_deform_verts(amd->object, ob, dm, vertexCos, NULL, numVerts,
+ amd->deformflag, amd->defgrp_name);
+
+ if(!derivedData) dm->release(dm);
+}
+
+static void armatureModifier_deformMatricesEM(
+ ModifierData *md, Object *ob, EditMesh *editData,
+ DerivedMesh *derivedData, float (*vertexCos)[3],
+ float (*defMats)[3][3], int numVerts)
+{
+ ArmatureModifierData *amd = (ArmatureModifierData*) md;
+ DerivedMesh *dm = derivedData;
+
+ if(!derivedData) dm = CDDM_from_editmesh(editData, ob->data);
+
+ armature_deform_verts(amd->object, ob, dm, vertexCos, defMats, numVerts,
amd->deformflag, amd->defgrp_name);
if(!derivedData) dm->release(dm);
@@ -5067,6 +5083,7 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type)
mti->updateDepgraph = armatureModifier_updateDepgraph;
mti->deformVerts = armatureModifier_deformVerts;
mti->deformVertsEM = armatureModifier_deformVertsEM;
+ mti->deformMatricesEM = armatureModifier_deformMatricesEM;
mti = INIT_TYPE(Hook);
mti->type = eModifierTypeType_OnlyDeform;
@@ -5268,6 +5285,7 @@ int modifiers_getCageIndex(Object *ob, int *lastPossibleCageIndex_r)
if (!(md->mode & eModifierMode_Editmode)) continue;
if (mti->isDisabled && mti->isDisabled(md)) continue;
if (!(mti->flags & eModifierTypeFlag_SupportsEditmode)) continue;
+ if (md->mode & eModifierMode_DisableTemporary) continue;
if (!modifier_supportsMapping(md))
break;
@@ -5447,20 +5465,26 @@ int modifiers_usesArmature(Object *ob, bArmature *arm)
return 0;
}
+int modifier_isDeformer(ModifierData *md)
+{
+ if (md->type==eModifierType_Armature)
+ return 1;
+ if (md->type==eModifierType_Curve)
+ return 1;
+ if (md->type==eModifierType_Lattice)
+ return 1;
+
+ return 0;
+}
+
int modifiers_isDeformed(Object *ob)
{
ModifierData *md = modifiers_getVirtualModifierList(ob);
for (; md; md=md->next) {
if(ob==G.obedit && (md->mode & eModifierMode_Editmode)==0);
- else {
- if (md->type==eModifierType_Armature)
- return 1;
- if (md->type==eModifierType_Curve)
- return 1;
- if (md->type==eModifierType_Lattice)
- return 1;
- }
+ else if(modifier_isDeformer(md))
+ return 1;
}
return 0;
}