diff options
author | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2007-07-29 01:04:30 +0400 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2007-07-29 01:04:30 +0400 |
commit | 8742899f5e3ef3b76c5fa2227ab3df3bdc0e1ef9 (patch) | |
tree | 872416258cce5ee4eea00f6f0efc91ba862634c7 /source | |
parent | 0281bdac765ce750df349b82abf8ced970ca65fd (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')
-rw-r--r-- | source/blender/blenkernel/BKE_DerivedMesh.h | 5 | ||||
-rw-r--r-- | source/blender/blenkernel/BKE_lattice.h | 4 | ||||
-rw-r--r-- | source/blender/blenkernel/BKE_modifier.h | 6 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/DerivedMesh.c | 82 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/armature.c | 144 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/modifier.c | 46 | ||||
-rw-r--r-- | source/blender/blenlib/BLI_arithb.h | 2 | ||||
-rw-r--r-- | source/blender/blenlib/intern/arithb.c | 18 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_modifier_types.h | 1 | ||||
-rwxr-xr-x | source/blender/src/transform_conversions.c | 125 |
10 files changed, 313 insertions, 120 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; } diff --git a/source/blender/blenlib/BLI_arithb.h b/source/blender/blenlib/BLI_arithb.h index a732f09ca58..7a1bedf5c14 100644 --- a/source/blender/blenlib/BLI_arithb.h +++ b/source/blender/blenlib/BLI_arithb.h @@ -217,6 +217,8 @@ void Mat3MulVecfl(float mat[][3], float *vec); void Mat3MulVecd(float mat[][3], double *vec); void Mat3TransMulVecfl(float mat[][3], float *vec); +void Mat3AddMat3(float m1[][3], float m2[][3], float m3[][3]); +void Mat4AddMat4(float m1[][4], float m2[][4], float m3[][4]); void VecUpMat3old(float *vec, float mat[][3], short axis); void VecUpMat3(float *vec, float mat[][3], short axis); diff --git a/source/blender/blenlib/intern/arithb.c b/source/blender/blenlib/intern/arithb.c index e98ce92787f..f403be6cd92 100644 --- a/source/blender/blenlib/intern/arithb.c +++ b/source/blender/blenlib/intern/arithb.c @@ -952,6 +952,24 @@ void Mat4MulFloat3(float *m, float f) /* only scale component */ } } +void Mat3AddMat3(float m1[][3], float m2[][3], float m3[][3]) +{ + int i, j; + + for(i=0;i<3;i++) + for(j=0;j<3;j++) + m1[i][j]= m2[i][j] + m3[i][j]; +} + +void Mat4AddMat4(float m1[][4], float m2[][4], float m3[][4]) +{ + int i, j; + + for(i=0;i<4;i++) + for(j=0;j<4;j++) + m1[i][j]= m2[i][j] + m3[i][j]; +} + void VecStar(float mat[][3], float *vec) { diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index 2d296ad10fa..71e850e4368 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -38,6 +38,7 @@ typedef enum ModifierMode { eModifierMode_OnCage = (1<<3), eModifierMode_Expanded = (1<<4), eModifierMode_Virtual = (1<<5), + eModifierMode_DisableTemporary = (1 << 31) } ModifierMode; typedef struct ModifierData { diff --git a/source/blender/src/transform_conversions.c b/source/blender/src/transform_conversions.c index 0db4eaaf94f..65fd4067276 100755 --- a/source/blender/src/transform_conversions.c +++ b/source/blender/src/transform_conversions.c @@ -1506,43 +1506,33 @@ static void make_vertexcos__mapFunc(void *userData, int index, float *co, float VECCOPY(vec, co); } -/* hurmf, copy from buttons_editing.c, i have to sort this out what it means... */ -static void modifiers_setOnCage(void *ob_v, void *md_v) +static int modifiers_disable_subsurf_temporary(Object *ob) { - Object *ob = ob_v; ModifierData *md; + int disabled = 0; - int i, cageIndex = modifiers_getCageIndex(ob, NULL ); + for(md=ob->modifiers.first; md; md=md->next) + if(md->type==eModifierType_Subsurf) + if(md->mode & eModifierMode_OnCage) { + md->mode ^= eModifierMode_DisableTemporary; + disabled= 1; + } - for( i = 0, md=ob->modifiers.first; md; ++i, md=md->next ) - if( md == md_v ) { - if( i >= cageIndex ) - md->mode ^= eModifierMode_OnCage; - break; - } + return disabled; } - /* disable subsurf temporal, get mapped cos, and enable it */ static float *get_crazy_mapped_editverts(void) { DerivedMesh *dm; - ModifierData *md; float *vertexcos; - int i; - - for( i = 0, md=G.obedit->modifiers.first; md; ++i, md=md->next ) { - if(md->type==eModifierType_Subsurf) - if(md->mode & eModifierMode_OnCage) - break; - } - if(md) { - /* this call disables subsurf and enables the underlying modifier to deform, apparently */ - modifiers_setOnCage(G.obedit, md); - /* make it all over */ + + /* disable subsurf temporal, get mapped cos, and enable it */ + if(modifiers_disable_subsurf_temporary(G.obedit)) { + /* need to make new derivemesh */ makeDerivedMesh(G.obedit, CD_MASK_BAREMESH); } - + /* now get the cage */ dm= editmesh_get_derived_cage(CD_MASK_BAREMESH); @@ -1551,10 +1541,8 @@ static float *get_crazy_mapped_editverts(void) dm->release(dm); - if(md) { - /* set back the flag, no new cage needs to be built, transform does it */ - modifiers_setOnCage(G.obedit, md); - } + /* set back the flag, no new cage needs to be built, transform does it */ + modifiers_disable_subsurf_temporary(G.obedit); return vertexcos; } @@ -1577,12 +1565,12 @@ static void set_crazy_vertex_quat(float *quat, float *v1, float *v2, float *v3, } #undef TAN_MAKE_VEC -static void set_crazyspace_quats(float *mappedcos, float *quats) +static void set_crazyspace_quats(float *origcos, float *mappedcos, float *quats) { EditMesh *em = G.editMesh; EditVert *eve, *prev; EditFace *efa; - float *v1, *v2, *v3, *v4; + float *v1, *v2, *v3, *v4, *co1, *co2, *co3, *co4; long index= 0; /* two abused locations in vertices */ @@ -1595,43 +1583,48 @@ static void set_crazyspace_quats(float *mappedcos, float *quats) for(efa= em->faces.first; efa; efa= efa->next) { /* retrieve mapped coordinates */ - v1= mappedcos + 3*( (long)(efa->v1->prev) ); - v2= mappedcos + 3*( (long)(efa->v2->prev) ); - v3= mappedcos + 3*( (long)(efa->v3->prev) ); - + v1= mappedcos + 3*(long)(efa->v1->prev); + v2= mappedcos + 3*(long)(efa->v2->prev); + v3= mappedcos + 3*(long)(efa->v3->prev); + + co1= (origcos)? origcos + 3*(long)(efa->v1->prev): efa->v1->co; + co2= (origcos)? origcos + 3*(long)(efa->v2->prev): efa->v2->co; + co3= (origcos)? origcos + 3*(long)(efa->v3->prev): efa->v3->co; + if(efa->v2->tmp.fp==NULL && efa->v2->f1) { - set_crazy_vertex_quat(quats, efa->v2->co, efa->v3->co, efa->v1->co, v2, v3, v1); + set_crazy_vertex_quat(quats, co2, co3, co1, v2, v3, v1); efa->v2->tmp.fp= quats; quats+= 4; } if(efa->v4) { - v4= mappedcos + 3*( (long)(efa->v4->prev) ); - + v4= mappedcos + 3*(long)(efa->v4->prev); + co4= (origcos)? origcos + 3*(long)(efa->v4->prev): efa->v4->co; + if(efa->v1->tmp.fp==NULL && efa->v1->f1) { - set_crazy_vertex_quat(quats, efa->v1->co, efa->v2->co, efa->v4->co, v1, v2, v4); + set_crazy_vertex_quat(quats, co1, co2, co4, v1, v2, v4); efa->v1->tmp.fp= quats; quats+= 4; } if(efa->v3->tmp.fp==NULL && efa->v3->f1) { - set_crazy_vertex_quat(quats, efa->v3->co, efa->v4->co, efa->v2->co, v3, v4, v2); + set_crazy_vertex_quat(quats, co3, co4, co2, v3, v4, v2); efa->v3->tmp.fp= quats; quats+= 4; } if(efa->v4->tmp.fp==NULL && efa->v4->f1) { - set_crazy_vertex_quat(quats, efa->v4->co, efa->v1->co, efa->v3->co, v4, v1, v3); + set_crazy_vertex_quat(quats, co4, co1, co3, v4, v1, v3); efa->v4->tmp.fp= quats; quats+= 4; } } else { if(efa->v1->tmp.fp==NULL && efa->v1->f1) { - set_crazy_vertex_quat(quats, efa->v1->co, efa->v2->co, efa->v3->co, v1, v2, v3); + set_crazy_vertex_quat(quats, co1, co2, co3, v1, v2, v3); efa->v1->tmp.fp= quats; quats+= 4; } if(efa->v3->tmp.fp==NULL && efa->v3->f1) { - set_crazy_vertex_quat(quats, efa->v3->co, efa->v1->co, efa->v2->co, v3, v1, v2); + set_crazy_vertex_quat(quats, co3, co1, co2, v3, v1, v2); efa->v3->tmp.fp= quats; quats+= 4; } @@ -1651,8 +1644,8 @@ static void createTransEditVerts(TransInfo *t) EditVert *eve; EditVert **nears = NULL; float *vectors = NULL, *mappedcos = NULL, *quats= NULL; - float mtx[3][3], smtx[3][3]; - int count=0, countsel=0; + float mtx[3][3], smtx[3][3], (*defmats)[3][3] = NULL, (*defcos)[3] = NULL; + int count=0, countsel=0, a, totleft; int propmode = t->flag & T_PROP_EDIT; int mirror= (G.scene->toolsettings->editbutflag & B_MESH_X_MIRROR); @@ -1714,10 +1707,23 @@ static void createTransEditVerts(TransInfo *t) if(propmode==0) { if(modifiers_getCageIndex(G.obedit, NULL)>=0) { if(modifiers_isDeformed(G.obedit)) { - /* disable subsurf temporal, get mapped cos, and enable it */ - mappedcos= get_crazy_mapped_editverts(); - quats= MEM_mallocN( (t->total)*sizeof(float)*4, "crazy quats"); - set_crazyspace_quats(mappedcos, quats); + /* check if we can use deform matrices for modifier from the + start up to stack, they are more accurate than quats */ + totleft= editmesh_get_first_deform_matrices(&defmats, &defcos); + + /* if we still have more modifiers, also do crazyspace + correction with quats, relative to the coordinates after + the modifiers that support deform matrices (defcos) */ + if(totleft > 0) { + mappedcos= get_crazy_mapped_editverts(); + quats= MEM_mallocN( (t->total)*sizeof(float)*4, "crazy quats"); + set_crazyspace_quats((float*)defcos, mappedcos, quats); + if(mappedcos) + MEM_freeN(mappedcos); + } + + if(defcos) + MEM_freeN(defcos); } } } @@ -1733,7 +1739,7 @@ static void createTransEditVerts(TransInfo *t) } } - for (eve=em->verts.first; eve; eve=eve->next) { + for (a=0, eve=em->verts.first; eve; eve=eve->next, a++) { if(eve->h==0) { if(propmode || eve->f1) { VertsToTransData(tob, eve); @@ -1753,11 +1759,22 @@ static void createTransEditVerts(TransInfo *t) } /* CrazySpace */ - if(quats && eve->tmp.fp) { + if(defmats || (quats && eve->tmp.fp)) { float mat[3][3], imat[3][3], qmat[3][3]; - QuatToMat3(eve->tmp.fp, qmat); - Mat3MulMat3(mat, mtx, qmat); + /* use both or either quat and defmat correction */ + if(quats && eve->tmp.f) { + QuatToMat3(eve->tmp.fp, qmat); + + if(defmats) + Mat3MulSerie(mat, mtx, qmat, defmats[a], + NULL, NULL, NULL, NULL, NULL); + else + Mat3MulMat3(mat, mtx, qmat); + } + else + Mat3MulMat3(mat, mtx, defmats[a]); + Mat3Inv(imat, mat); Mat3CpyMat3(tob->smtx, imat); @@ -1782,10 +1799,10 @@ static void createTransEditVerts(TransInfo *t) MEM_freeN(nears); } /* crazy space free */ - if(mappedcos) - MEM_freeN(mappedcos); if(quats) MEM_freeN(quats); + if(defmats) + MEM_freeN(defmats); } /* ********************* UV ****************** */ |