From 4cb838d54f6a84e2717fce580a65d205f3980b03 Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Wed, 4 Jan 2006 15:37:48 +0000 Subject: [PATCH] Fix for CrazySpace correction. (Special request of our Argentinan bird movie friends :) There were two issues with it, which both have been tackled as follows: - the correction transformations (quaternions) were calculated per face, and then averaged over the vertices. This gave annoying inaccuracies, especially when the geometry is irregular. The new code first calculates two tangent vectors in a vertex, based on the associated edges it has in a face. These tangents then are used to define the transform. Tangents are 20% of the length of an edge now. - When a SubSurf modifier was in the chain, the deformation caused by the subsurf was also included in CrazySpace correction, giving even larger errors. New code temporally disables Subsurf, recalculates vertices, and then does the crazy tricks. :) All in all, quite well working! --- source/blender/src/transform_conversions.c | 145 +++++++++++++++------ 1 file changed, 106 insertions(+), 39 deletions(-) diff --git a/source/blender/src/transform_conversions.c b/source/blender/src/transform_conversions.c index ccbf8fd8aed..65bf0a597ba 100755 --- a/source/blender/src/transform_conversions.c +++ b/source/blender/src/transform_conversions.c @@ -1411,6 +1411,8 @@ static void VertsToTransData(TransData *td, EditVert *eve) td->val = NULL; } +/* *********************** CrazySpace correction. Now without doing subsurf optimal ****************** */ + static void make_vertexcos__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s) { float *vec = userData; @@ -1419,71 +1421,136 @@ static void make_vertexcos__mapFunc(void *userData, int index, float *co, float VECCOPY(vec, co); } -static float *get_mapped_editverts(void) +/* 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) { - int needsFree; - DerivedMesh *dm= editmesh_get_derived_cage(&needsFree); + Object *ob = ob_v; + ModifierData *md; + + int i, cageIndex = modifiers_getCageIndex(ob, NULL ); + + for( i = 0, md=ob->modifiers.first; md; ++i, md=md->next ) + if( md == md_v ) { + if( i >= cageIndex ) + md->mode ^= eModifierMode_OnCage; + break; + } +} + + +/* disable subsurf temporal, get mapped cos, and enable it */ +static float *get_crazy_mapped_editverts(void) +{ + DerivedMesh *dm; + ModifierData *md; float *vertexcos; + int needsFree; + 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 */ + makeDispListMesh(G.obedit); + } + + /* now get the cage */ + dm= editmesh_get_derived_cage(&needsFree); + vertexcos= MEM_mallocN(3*sizeof(float)*G.totvert, "vertexcos map"); - dm->foreachMappedVert(dm, make_vertexcos__mapFunc, vertexcos); if (needsFree) dm->release(dm); + + if(md) { + /* set back the flag, no new cage needs to be built, transform does it */ + modifiers_setOnCage(G.obedit, md); + } + return vertexcos; } -/* helper for below, interpolates or assigns and increments */ -static float *crazy_quat_blend(EditVert *eve, float *quat) +#define TAN_MAKE_VEC(a, b, c) a[0]= b[0] + 0.2f*(b[0]-c[0]); a[1]= b[1] + 0.2f*(b[1]-c[1]); a[2]= b[2] + 0.2f*(b[2]-c[2]) +static void set_crazy_vertex_quat(float *quat, float *v1, float *v2, float *v3, float *def1, float *def2, float *def3) { - if(eve->vn==NULL) { - eve->vn= (EditVert *)quat; - QUATCOPY(quat+4, quat); - return quat+4; - } - else { - float *q1= (float *)eve->vn; - QuatInterpol(q1, q1, quat, 0.5f); - return quat; - } + float vecu[3], vecv[3]; + float q1[4], q2[4]; + + TAN_MAKE_VEC(vecu, v1, v2); + TAN_MAKE_VEC(vecv, v1, v3); + triatoquat(v1, vecu, vecv, q1); + + TAN_MAKE_VEC(vecu, def1, def2); + TAN_MAKE_VEC(vecv, def1, def3); + triatoquat(def1, vecu, vecv, q2); + + QuatSub(quat, q2, q1); } +#undef TAN_MAKE_VEC static void set_crazyspace_quats(float *mappedcos, float *quats) { EditMesh *em = G.editMesh; EditVert *eve, *prev; EditFace *efa; - float q1[4], q2[4]; - float *v1, *v2, *v3, *quatp; + float *v1, *v2, *v3, *v4; int index= 0; - /* 2 abused locations in vertices */ + /* two abused locations in vertices */ for(eve= em->verts.first; eve; eve= eve->next, index++) { eve->vn= NULL; eve->prev= (EditVert *)index; } - quatp= quats; + /* first store two sets of tangent vectors in vertices, we derive it just from the face-edges */ for(efa= em->faces.first; efa; efa= efa->next) { - /* vertex f1 flags were set for transform */ - if( (efa->v1->f1 && efa->v1->vn==NULL) || (efa->v2->f1 && efa->v2->vn==NULL) - || (efa->v3->f1 && efa->v3->vn==NULL) || (efa->v4 && efa->v4->f1 && efa->v4->vn==NULL) ) { + /* retrieve mapped coordinates */ + v1= mappedcos + 3*( (int)(efa->v1->prev) ); + v2= mappedcos + 3*( (int)(efa->v2->prev) ); + v3= mappedcos + 3*( (int)(efa->v3->prev) ); - triatoquat(efa->v1->co, efa->v2->co, efa->v3->co, q1); + if(efa->v2->vn==NULL && efa->v2->f1) { + set_crazy_vertex_quat(quats, efa->v2->co, efa->v3->co, efa->v1->co, v2, v3, v1); + efa->v2->vn= (EditVert *)(quats); + quats+= 4; + } + + if(efa->v4) { + v4= mappedcos + 3*( (int)(efa->v4->prev) ); - /* retrieve mapped coordinates */ - v1= mappedcos + 3*( (int)(efa->v1->prev) ); - v2= mappedcos + 3*( (int)(efa->v2->prev) ); - v3= mappedcos + 3*( (int)(efa->v3->prev) ); - triatoquat(v1, v2, v3, q2); - - QuatSub(quatp, q2, q1); - - if(efa->v1->f1) quatp= crazy_quat_blend(efa->v1, quatp); - if(efa->v2->f1) quatp= crazy_quat_blend(efa->v2, quatp); - if(efa->v3->f1) quatp= crazy_quat_blend(efa->v3, quatp); - if(efa->v4 && efa->v4->f1) quatp= crazy_quat_blend(efa->v4, quatp); + if(efa->v1->vn==NULL && efa->v1->f1) { + set_crazy_vertex_quat(quats, efa->v1->co, efa->v2->co, efa->v4->co, v1, v2, v4); + efa->v1->vn= (EditVert *)(quats); + quats+= 4; + } + if(efa->v3->vn==NULL && efa->v3->f1) { + set_crazy_vertex_quat(quats, efa->v3->co, efa->v4->co, efa->v2->co, v3, v4, v2); + efa->v3->vn= (EditVert *)(quats); + quats+= 4; + } + if(efa->v4->vn==NULL && efa->v4->f1) { + set_crazy_vertex_quat(quats, efa->v4->co, efa->v1->co, efa->v3->co, v4, v1, v3); + efa->v4->vn= (EditVert *)(quats); + quats+= 4; + } + } + else { + if(efa->v1->vn==NULL && efa->v1->f1) { + set_crazy_vertex_quat(quats, efa->v1->co, efa->v2->co, efa->v3->co, v1, v2, v3); + efa->v1->vn= (EditVert *)(quats); + quats+= 4; + } + if(efa->v3->vn==NULL && efa->v3->f1) { + set_crazy_vertex_quat(quats, efa->v3->co, efa->v1->co, efa->v2->co, v3, v1, v2); + efa->v3->vn= (EditVert *)(quats); + quats+= 4; + } } } @@ -1562,9 +1629,9 @@ static void createTransEditVerts(TransInfo *t) if(propmode==0) { if(modifiers_getCageIndex(G.obedit, NULL)>=0) { if(modifiers_isDeformed(G.obedit)) { - mappedcos= get_mapped_editverts(); - /* add one more quaternion, because of crazy_quat_blend */ - quats= MEM_mallocN( (t->total+1)*sizeof(float)*4, "crazy quats"); + /* 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); } }