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.
This commit is contained in:
parent
0281bdac76
commit
8742899f5e
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 **************************** */
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 ****************** */
|
||||
|
|
Loading…
Reference in New Issue