Blender  V2.59
crazyspace.c
Go to the documentation of this file.
00001 /*
00002  * $Id: crazyspace.c 36485 2011-05-04 13:15:42Z nazgul $
00003  *
00004  * ***** BEGIN GPL LICENSE BLOCK *****
00005  *
00006  * This program is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU General Public License
00008  * as published by the Free Software Foundation; either version 2
00009  * of the License, or (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software Foundation,
00018  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00019  *
00020  * The Original Code is Copyright (C) 2005 Blender Foundation.
00021  * All rights reserved.
00022  *
00023  *
00024  * Contributor(s): Blender Foundation,
00025  *                 Sergey Sharybin
00026  *
00027  * ***** END GPL LICENSE BLOCK *****
00028  */
00029 
00035 #include "MEM_guardedalloc.h"
00036 
00037 #include "DNA_scene_types.h"
00038 #include "DNA_object_types.h"
00039 #include "DNA_modifier_types.h"
00040 #include "DNA_meshdata_types.h"
00041 
00042 #include "BKE_DerivedMesh.h"
00043 #include "BKE_modifier.h"
00044 #include "BKE_multires.h"
00045 #include "BKE_mesh.h"
00046 
00047 #include "BLI_utildefines.h"
00048 #include "BLI_math.h"
00049 #include "BLI_editVert.h"
00050 
00051 #include "ED_util.h"
00052 
00053 typedef struct {
00054         float *vertexcos;
00055         short *flags;
00056 } MappedUserData;
00057 
00058 #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])
00059 static void set_crazy_vertex_quat(float *quat, float *v1, float *v2, float *v3, float *def1, float *def2, float *def3)
00060 {
00061         float vecu[3], vecv[3];
00062         float q1[4], q2[4];
00063 
00064         TAN_MAKE_VEC(vecu, v1, v2);
00065         TAN_MAKE_VEC(vecv, v1, v3);
00066         tri_to_quat( q1,v1, vecu, vecv);
00067 
00068         TAN_MAKE_VEC(vecu, def1, def2);
00069         TAN_MAKE_VEC(vecv, def1, def3);
00070         tri_to_quat( q2,def1, vecu, vecv);
00071 
00072         sub_qt_qtqt(quat, q2, q1);
00073 }
00074 #undef TAN_MAKE_VEC
00075 
00076 static void make_vertexcos__mapFunc(void *userData, int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s))
00077 {
00078         MappedUserData *mappedData= (MappedUserData*)userData;
00079         float *vec = mappedData->vertexcos;
00080 
00081         vec+= 3*index;
00082         if(!mappedData->flags[index]) {
00083                 /* we need coord from prototype vertex, not it clones or images,
00084                    suppose they stored in the beginning of vertex array stored in DM */
00085                 VECCOPY(vec, co);
00086                 mappedData->flags[index]= 1;
00087         }
00088 }
00089 
00090 static int modifiers_disable_subsurf_temporary(Object *ob)
00091 {
00092         ModifierData *md;
00093         int disabled = 0;
00094 
00095         for(md=ob->modifiers.first; md; md=md->next)
00096                 if(md->type==eModifierType_Subsurf)
00097                         if(md->mode & eModifierMode_OnCage) {
00098                                 md->mode ^= eModifierMode_DisableTemporary;
00099                                 disabled= 1;
00100                         }
00101 
00102         return disabled;
00103 }
00104 
00105 /* disable subsurf temporal, get mapped cos, and enable it */
00106 float *crazyspace_get_mapped_editverts(Scene *scene, Object *obedit)
00107 {
00108         Mesh *me= obedit->data;
00109         DerivedMesh *dm;
00110         float *vertexcos;
00111         int nverts= me->edit_mesh->totvert;
00112         short *flags;
00113         MappedUserData userData;
00114 
00115         /* disable subsurf temporal, get mapped cos, and enable it */
00116         if(modifiers_disable_subsurf_temporary(obedit)) {
00117                 /* need to make new derivemesh */
00118                 makeDerivedMesh(scene, obedit, me->edit_mesh, CD_MASK_BAREMESH);
00119         }
00120 
00121         /* now get the cage */
00122         dm= editmesh_get_derived_cage(scene, obedit, me->edit_mesh, CD_MASK_BAREMESH);
00123 
00124         vertexcos= MEM_callocN(3*sizeof(float)*nverts, "vertexcos map");
00125         flags= MEM_callocN(sizeof(short)*nverts, "vertexcos flags");
00126 
00127         userData.vertexcos= vertexcos;
00128         userData.flags= flags;
00129         dm->foreachMappedVert(dm, make_vertexcos__mapFunc, &userData);
00130 
00131         dm->release(dm);
00132 
00133         /* set back the flag, no new cage needs to be built, transform does it */
00134         modifiers_disable_subsurf_temporary(obedit);
00135 
00136         MEM_freeN(flags);
00137 
00138         return vertexcos;
00139 }
00140 
00141 void crazyspace_set_quats_editmesh(EditMesh *em, float *origcos, float *mappedcos, float *quats)
00142 {
00143         EditVert *eve, *prev;
00144         EditFace *efa;
00145         float *v1, *v2, *v3, *v4, *co1, *co2, *co3, *co4;
00146         intptr_t index= 0;
00147 
00148         /* two abused locations in vertices */
00149         for(eve= em->verts.first; eve; eve= eve->next, index++) {
00150                 eve->tmp.p = NULL;
00151                 eve->prev= (EditVert *)index;
00152         }
00153 
00154         /* first store two sets of tangent vectors in vertices, we derive it just from the face-edges */
00155         for(efa= em->faces.first; efa; efa= efa->next) {
00156 
00157                 /* retrieve mapped coordinates */
00158                 v1= mappedcos + 3*(intptr_t)(efa->v1->prev);
00159                 v2= mappedcos + 3*(intptr_t)(efa->v2->prev);
00160                 v3= mappedcos + 3*(intptr_t)(efa->v3->prev);
00161 
00162                 co1= (origcos)? origcos + 3*(intptr_t)(efa->v1->prev): efa->v1->co;
00163                 co2= (origcos)? origcos + 3*(intptr_t)(efa->v2->prev): efa->v2->co;
00164                 co3= (origcos)? origcos + 3*(intptr_t)(efa->v3->prev): efa->v3->co;
00165 
00166                 if(efa->v2->tmp.p==NULL && efa->v2->f1) {
00167                         set_crazy_vertex_quat(quats, co2, co3, co1, v2, v3, v1);
00168                         efa->v2->tmp.p= (void*)quats;
00169                         quats+= 4;
00170                 }
00171 
00172                 if(efa->v4) {
00173                         v4= mappedcos + 3*(intptr_t)(efa->v4->prev);
00174                         co4= (origcos)? origcos + 3*(intptr_t)(efa->v4->prev): efa->v4->co;
00175 
00176                         if(efa->v1->tmp.p==NULL && efa->v1->f1) {
00177                                 set_crazy_vertex_quat(quats, co1, co2, co4, v1, v2, v4);
00178                                 efa->v1->tmp.p= (void*)quats;
00179                                 quats+= 4;
00180                         }
00181                         if(efa->v3->tmp.p==NULL && efa->v3->f1) {
00182                                 set_crazy_vertex_quat(quats, co3, co4, co2, v3, v4, v2);
00183                                 efa->v3->tmp.p= (void*)quats;
00184                                 quats+= 4;
00185                         }
00186                         if(efa->v4->tmp.p==NULL && efa->v4->f1) {
00187                                 set_crazy_vertex_quat(quats, co4, co1, co3, v4, v1, v3);
00188                                 efa->v4->tmp.p= (void*)quats;
00189                                 quats+= 4;
00190                         }
00191                 }
00192                 else {
00193                         if(efa->v1->tmp.p==NULL && efa->v1->f1) {
00194                                 set_crazy_vertex_quat(quats, co1, co2, co3, v1, v2, v3);
00195                                 efa->v1->tmp.p= (void*)quats;
00196                                 quats+= 4;
00197                         }
00198                         if(efa->v3->tmp.p==NULL && efa->v3->f1) {
00199                                 set_crazy_vertex_quat(quats, co3, co1, co2, v3, v1, v2);
00200                                 efa->v3->tmp.p= (void*)quats;
00201                                 quats+= 4;
00202                         }
00203                 }
00204         }
00205 
00206         /* restore abused prev pointer */
00207         for(prev= NULL, eve= em->verts.first; eve; prev= eve, eve= eve->next)
00208                 eve->prev= prev;
00209 
00210 }
00211 
00212 void crazyspace_set_quats_mesh(Mesh *me, float *origcos, float *mappedcos, float *quats)
00213 {
00214         int i;
00215         MVert *mvert;
00216         MFace *mface;
00217         float *v1, *v2, *v3, *v4, *co1, *co2, *co3, *co4;
00218 
00219         mvert= me->mvert;
00220         for(i=0; i<me->totvert; i++, mvert++)
00221                 mvert->flag&= ~ME_VERT_TMP_TAG;
00222 
00223         /* first store two sets of tangent vectors in vertices, we derive it just from the face-edges */
00224         mvert= me->mvert;
00225         mface= me->mface;
00226         for(i=0; i<me->totface; i++, mface++) {
00227 
00228                 /* retrieve mapped coordinates */
00229                 v1= mappedcos + 3*mface->v1;
00230                 v2= mappedcos + 3*mface->v2;
00231                 v3= mappedcos + 3*mface->v3;
00232 
00233                 co1= (origcos)? origcos + 3*mface->v1: mvert[mface->v1].co;
00234                 co2= (origcos)? origcos + 3*mface->v2: mvert[mface->v2].co;
00235                 co3= (origcos)? origcos + 3*mface->v3: mvert[mface->v3].co;
00236 
00237                 if((mvert[mface->v2].flag&ME_VERT_TMP_TAG)==0) {
00238                         set_crazy_vertex_quat(&quats[mface->v2*4], co2, co3, co1, v2, v3, v1);
00239                         mvert[mface->v2].flag|= ME_VERT_TMP_TAG;
00240                 }
00241 
00242                 if(mface->v4) {
00243                         v4= mappedcos + 3*mface->v4;
00244                         co4= (origcos)? origcos + 3*mface->v4: mvert[mface->v4].co;
00245 
00246                         if((mvert[mface->v1].flag&ME_VERT_TMP_TAG)==0) {
00247                                 set_crazy_vertex_quat(&quats[mface->v1*4], co1, co2, co4, v1, v2, v4);
00248                                 mvert[mface->v1].flag|= ME_VERT_TMP_TAG;
00249                         }
00250                         if((mvert[mface->v3].flag&ME_VERT_TMP_TAG)==0) {
00251                                 set_crazy_vertex_quat(&quats[mface->v3*4], co3, co4, co2, v3, v4, v2);
00252                                 mvert[mface->v3].flag|= ME_VERT_TMP_TAG;
00253                         }
00254                         if((mvert[mface->v4].flag&ME_VERT_TMP_TAG)==0) {
00255                                 set_crazy_vertex_quat(&quats[mface->v4*4], co4, co1, co3, v4, v1, v3);
00256                                 mvert[mface->v4].flag|= ME_VERT_TMP_TAG;
00257                         }
00258                 }
00259                 else {
00260                         if((mvert[mface->v1].flag&ME_VERT_TMP_TAG)==0) {
00261                                 set_crazy_vertex_quat(&quats[mface->v1*4], co1, co2, co3, v1, v2, v3);
00262                                 mvert[mface->v1].flag|= ME_VERT_TMP_TAG;
00263                         }
00264                         if((mvert[mface->v3].flag&ME_VERT_TMP_TAG)==0) {
00265                                 set_crazy_vertex_quat(&quats[mface->v3*4], co3, co1, co2, v3, v1, v2);
00266                                 mvert[mface->v3].flag|= ME_VERT_TMP_TAG;
00267                         }
00268                 }
00269         }
00270 }
00271 
00272 int editmesh_get_first_deform_matrices(Scene *scene, Object *ob, EditMesh *em, float (**deformmats)[3][3], float (**deformcos)[3])
00273 {
00274         ModifierData *md;
00275         DerivedMesh *dm;
00276         int i, a, numleft = 0, numVerts = 0;
00277         int cageIndex = modifiers_getCageIndex(scene, ob, NULL, 1);
00278         float (*defmats)[3][3] = NULL, (*deformedVerts)[3] = NULL;
00279 
00280         modifiers_clearErrors(ob);
00281 
00282         dm = NULL;
00283         md = modifiers_getVirtualModifierList(ob);
00284 
00285         /* compute the deformation matrices and coordinates for the first
00286            modifiers with on cage editing that are enabled and support computing
00287            deform matrices */
00288         for(i = 0; md && i <= cageIndex; i++, md = md->next) {
00289                 ModifierTypeInfo *mti = modifierType_getInfo(md->type);
00290 
00291                 if(!editmesh_modifier_is_enabled(scene, md, dm))
00292                         continue;
00293 
00294                 if(mti->type==eModifierTypeType_OnlyDeform && mti->deformMatricesEM) {
00295                         if(!defmats) {
00296                                 dm= editmesh_get_derived(em, NULL);
00297                                 deformedVerts= editmesh_get_vertex_cos(em, &numVerts);
00298                                 defmats= MEM_callocN(sizeof(*defmats)*numVerts, "defmats");
00299 
00300                                 for(a=0; a<numVerts; a++)
00301                                         unit_m3(defmats[a]);
00302                         }
00303 
00304                         mti->deformMatricesEM(md, ob, em, dm, deformedVerts, defmats,
00305                                 numVerts);
00306                 }
00307                 else
00308                         break;
00309         }
00310 
00311         for(; md && i <= cageIndex; md = md->next, i++)
00312                 if(editmesh_modifier_is_enabled(scene, md, dm) && modifier_isCorrectableDeformed(md))
00313                         numleft++;
00314 
00315         if(dm)
00316                 dm->release(dm);
00317 
00318         *deformmats= defmats;
00319         *deformcos= deformedVerts;
00320 
00321         return numleft;
00322 }
00323 
00324 int sculpt_get_first_deform_matrices(Scene *scene, Object *ob, float (**deformmats)[3][3], float (**deformcos)[3])
00325 {
00326         ModifierData *md;
00327         DerivedMesh *dm;
00328         int a, numVerts= 0;
00329         float (*defmats)[3][3]= NULL, (*deformedVerts)[3]= NULL;
00330         MultiresModifierData *mmd= get_multires_modifier(scene, ob, 0);
00331         int has_multires = mmd != NULL && mmd->sculptlvl > 0;
00332         int numleft= 0;
00333 
00334         if(has_multires) {
00335                 *deformmats= NULL;
00336                 *deformcos= NULL;
00337                 return numleft;
00338         }
00339 
00340         dm= NULL;
00341         md= modifiers_getVirtualModifierList(ob);
00342 
00343         for(; md; md= md->next) {
00344                 ModifierTypeInfo *mti= modifierType_getInfo(md->type);
00345 
00346                 if(!modifier_isEnabled(scene, md, eModifierMode_Realtime)) continue;
00347 
00348                 if(mti->type==eModifierTypeType_OnlyDeform) {
00349                         if(!defmats) {
00350                                 Mesh *me= (Mesh*)ob->data;
00351                                 dm= mesh_create_derived(me, ob, NULL);
00352                                 deformedVerts= mesh_getVertexCos(me, &numVerts);
00353                                 defmats= MEM_callocN(sizeof(*defmats)*numVerts, "defmats");
00354 
00355                                 for(a=0; a<numVerts; a++)
00356                                         unit_m3(defmats[a]);
00357                         }
00358 
00359                         if(mti->deformMatrices) mti->deformMatrices(md, ob, dm, deformedVerts, defmats, numVerts);
00360                         else break;
00361                 }
00362         }
00363 
00364         for(; md; md= md->next) {
00365                 ModifierTypeInfo *mti= modifierType_getInfo(md->type);
00366 
00367                 if(!modifier_isEnabled(scene, md, eModifierMode_Realtime)) continue;
00368 
00369                 if(mti->type==eModifierTypeType_OnlyDeform)
00370                         numleft++;
00371         }
00372 
00373         if(dm)
00374                 dm->release(dm);
00375 
00376         *deformmats= defmats;
00377         *deformcos= deformedVerts;
00378 
00379         return numleft;
00380 }
00381 
00382 void crazyspace_build_sculpt(Scene *scene, Object *ob, float (**deformmats)[3][3], float (**deformcos)[3])
00383 {
00384         int totleft= sculpt_get_first_deform_matrices(scene, ob, deformmats, deformcos);
00385 
00386         if(totleft) {
00387                 /* there are deformation modifier which doesn't support deformation matricies
00388                    calculation. Need additional crazyspace correction */
00389 
00390                 float (*deformedVerts)[3]= *deformcos;
00391                 float (*origVerts)[3]= MEM_dupallocN(deformedVerts);
00392                 float *quats= NULL;
00393                 int i, deformed= 0;
00394                 ModifierData *md= modifiers_getVirtualModifierList(ob);
00395                 Mesh *me= (Mesh*)ob->data;
00396 
00397                 for(; md; md= md->next) {
00398                         ModifierTypeInfo *mti= modifierType_getInfo(md->type);
00399 
00400                         if(!modifier_isEnabled(scene, md, eModifierMode_Realtime)) continue;
00401 
00402                         if(mti->type==eModifierTypeType_OnlyDeform) {
00403                                 /* skip leading modifiers which have been already
00404                                    handled in sculpt_get_first_deform_matrices */
00405                                 if(mti->deformMatrices && !deformed)
00406                                         continue;
00407 
00408                                 mti->deformVerts(md, ob, NULL, deformedVerts, me->totvert, 0, 0);
00409                                 deformed= 1;
00410                         }
00411                 }
00412 
00413                 quats= MEM_mallocN(me->totvert*sizeof(float)*4, "crazy quats");
00414 
00415                 crazyspace_set_quats_mesh(me, (float*)origVerts, (float*)deformedVerts, quats);
00416 
00417                 for(i=0; i<me->totvert; i++) {
00418                         float qmat[3][3], tmat[3][3];
00419 
00420                         quat_to_mat3(qmat, &quats[i*4]);
00421                         mul_m3_m3m3(tmat, qmat, (*deformmats)[i]);
00422                         copy_m3_m3((*deformmats)[i], tmat);
00423                 }
00424 
00425                 MEM_freeN(origVerts);
00426                 MEM_freeN(quats);
00427         }
00428 
00429         if(!*deformmats) {
00430                 int a, numVerts;
00431                 Mesh *me= (Mesh*)ob->data;
00432 
00433                 *deformcos= mesh_getVertexCos(me, &numVerts);
00434                 *deformmats= MEM_callocN(sizeof(*(*deformmats))*numVerts, "defmats");
00435 
00436                 for(a=0; a<numVerts; a++)
00437                         unit_m3((*deformmats)[a]);
00438         }
00439 }