diff options
author | Joseph Eagar <joeedh@gmail.com> | 2011-02-27 09:19:40 +0300 |
---|---|---|
committer | Joseph Eagar <joeedh@gmail.com> | 2011-02-27 09:19:40 +0300 |
commit | f01261d040be27337db9f9996d648a279c89b7c4 (patch) | |
tree | c448230939b3c90d53ce8852dd00925d6052e3a4 /source/blender/editors/util/crazyspace.c | |
parent | dcaeda5c4e3a0687251b8511de4f2e8b85ef75c0 (diff) | |
parent | 2198cfdb2deec8b2e85e242c74a032f43d0b26ca (diff) |
merge with/from trunk at r35190
Diffstat (limited to 'source/blender/editors/util/crazyspace.c')
-rw-r--r-- | source/blender/editors/util/crazyspace.c | 407 |
1 files changed, 407 insertions, 0 deletions
diff --git a/source/blender/editors/util/crazyspace.c b/source/blender/editors/util/crazyspace.c new file mode 100644 index 00000000000..6b7292fe6c7 --- /dev/null +++ b/source/blender/editors/util/crazyspace.c @@ -0,0 +1,407 @@ +/* + * $Id$ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2005 Blender Foundation. + * All rights reserved. + * + * + * Contributor(s): Blender Foundation, + * Sergey Sharybin + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "MEM_guardedalloc.h" + +#include "DNA_scene_types.h" +#include "DNA_object_types.h" +#include "DNA_modifier_types.h" +#include "DNA_meshdata_types.h" + +#include "BKE_DerivedMesh.h" +#include "BKE_modifier.h" +#include "BKE_multires.h" +#include "BKE_mesh.h" +#include "BKE_tessmesh.h" + +#include "BLI_utildefines.h" +#include "BLI_math.h" +#include "BLI_editVert.h" + +#include "ED_util.h" + +#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) +{ + float vecu[3], vecv[3]; + float q1[4], q2[4]; + + TAN_MAKE_VEC(vecu, v1, v2); + TAN_MAKE_VEC(vecv, v1, v3); + tri_to_quat( q1,v1, vecu, vecv); + + TAN_MAKE_VEC(vecu, def1, def2); + TAN_MAKE_VEC(vecv, def1, def3); + tri_to_quat( q2,def1, vecu, vecv); + + sub_qt_qtqt(quat, q2, q1); +} +#undef TAN_MAKE_VEC + +static void make_vertexcos__mapFunc(void *userData, int index, float *co, float *UNUSED(no_f), short *UNUSED(no_s)) +{ + float *vec = userData; + + vec+= 3*index; + VECCOPY(vec, co); +} + +static int modifiers_disable_subsurf_temporary(Object *ob) +{ + ModifierData *md; + int disabled = 0; + + 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; + } + + return disabled; +} + +/* disable subsurf temporal, get mapped cos, and enable it */ +float *crazyspace_get_mapped_editverts(Scene *scene, Object *obedit) +{ + Mesh *me= obedit->data; + DerivedMesh *dm; + float *vertexcos; + + /* disable subsurf temporal, get mapped cos, and enable it */ + if(modifiers_disable_subsurf_temporary(obedit)) { + /* need to make new derivemesh */ + makeDerivedMesh(scene, obedit, me->edit_btmesh, CD_MASK_BAREMESH); + } + + /* now get the cage */ + dm= editbmesh_get_derived_cage(scene, obedit, me->edit_btmesh, CD_MASK_BAREMESH); + + vertexcos= MEM_mallocN(3*sizeof(float)*me->edit_btmesh->bm->totvert, "vertexcos map"); + dm->foreachMappedVert(dm, make_vertexcos__mapFunc, vertexcos); + + dm->release(dm); + + /* set back the flag, no new cage needs to be built, transform does it */ + modifiers_disable_subsurf_temporary(obedit); + + return vertexcos; +} + +void crazyspace_set_quats_editmesh(BMEditMesh *em, float *origcos, float *mappedcos, float *quats) +{ +#if 0 + BMEditVert *eve, *prev; + BMEditFace *efa; + BMIter iter; + float *v1, *v2, *v3, *v4, *co1, *co2, *co3, *co4; + intptr_t index= 0; + + /* two abused locations in vertices */ + for(eve= em->verts.first; eve; eve= eve->next, index++) { + eve->tmp.p = NULL; + eve->prev= (EditVert *)index; + } + + /* 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) { + + /* retrieve mapped coordinates */ + v1= mappedcos + 3*(intptr_t)(efa->v1->prev); + v2= mappedcos + 3*(intptr_t)(efa->v2->prev); + v3= mappedcos + 3*(intptr_t)(efa->v3->prev); + + co1= (origcos)? origcos + 3*(intptr_t)(efa->v1->prev): efa->v1->co; + co2= (origcos)? origcos + 3*(intptr_t)(efa->v2->prev): efa->v2->co; + co3= (origcos)? origcos + 3*(intptr_t)(efa->v3->prev): efa->v3->co; + + if(efa->v2->tmp.p==NULL && efa->v2->f1) { + set_crazy_vertex_quat(quats, co2, co3, co1, v2, v3, v1); + efa->v2->tmp.p= (void*)quats; + quats+= 4; + } + + if(efa->v4) { + v4= mappedcos + 3*(intptr_t)(efa->v4->prev); + co4= (origcos)? origcos + 3*(intptr_t)(efa->v4->prev): efa->v4->co; + + if(efa->v1->tmp.p==NULL && efa->v1->f1) { + set_crazy_vertex_quat(quats, co1, co2, co4, v1, v2, v4); + efa->v1->tmp.p= (void*)quats; + quats+= 4; + } + if(efa->v3->tmp.p==NULL && efa->v3->f1) { + set_crazy_vertex_quat(quats, co3, co4, co2, v3, v4, v2); + efa->v3->tmp.p= (void*)quats; + quats+= 4; + } + if(efa->v4->tmp.p==NULL && efa->v4->f1) { + set_crazy_vertex_quat(quats, co4, co1, co3, v4, v1, v3); + efa->v4->tmp.p= (void*)quats; + quats+= 4; + } + } + else { + if(efa->v1->tmp.p==NULL && efa->v1->f1) { + set_crazy_vertex_quat(quats, co1, co2, co3, v1, v2, v3); + efa->v1->tmp.p= (void*)quats; + quats+= 4; + } + if(efa->v3->tmp.p==NULL && efa->v3->f1) { + set_crazy_vertex_quat(quats, co3, co1, co2, v3, v1, v2); + efa->v3->tmp.p= (void*)quats; + quats+= 4; + } + } + } + + /* restore abused prev pointer */ + for(prev= NULL, eve= em->verts.first; eve; prev= eve, eve= eve->next) + eve->prev= prev; +#endif +} + +void crazyspace_set_quats_mesh(Mesh *me, float *origcos, float *mappedcos, float *quats) +{ + int i; + MVert *mvert; + MFace *mface; + float *v1, *v2, *v3, *v4, *co1, *co2, *co3, *co4; + + mvert= me->mvert; + for(i=0; i<me->totvert; i++, mvert++) + mvert->flag&= ~ME_VERT_TMP_TAG; + + /* first store two sets of tangent vectors in vertices, we derive it just from the face-edges */ + mvert= me->mvert; + mface= me->mface; + for(i=0; i<me->totface; i++, mface++) { + + /* retrieve mapped coordinates */ + v1= mappedcos + 3*mface->v1; + v2= mappedcos + 3*mface->v2; + v3= mappedcos + 3*mface->v3; + + co1= (origcos)? origcos + 3*mface->v1: mvert[mface->v1].co; + co2= (origcos)? origcos + 3*mface->v2: mvert[mface->v2].co; + co3= (origcos)? origcos + 3*mface->v3: mvert[mface->v3].co; + + if((mvert[mface->v2].flag&ME_VERT_TMP_TAG)==0) { + set_crazy_vertex_quat(&quats[mface->v2*4], co2, co3, co1, v2, v3, v1); + mvert[mface->v2].flag|= ME_VERT_TMP_TAG; + } + + if(mface->v4) { + v4= mappedcos + 3*mface->v4; + co4= (origcos)? origcos + 3*mface->v4: mvert[mface->v4].co; + + if((mvert[mface->v1].flag&ME_VERT_TMP_TAG)==0) { + set_crazy_vertex_quat(&quats[mface->v1*4], co1, co2, co4, v1, v2, v4); + mvert[mface->v1].flag|= ME_VERT_TMP_TAG; + } + if((mvert[mface->v3].flag&ME_VERT_TMP_TAG)==0) { + set_crazy_vertex_quat(&quats[mface->v3*4], co3, co4, co2, v3, v4, v2); + mvert[mface->v3].flag|= ME_VERT_TMP_TAG; + } + if((mvert[mface->v4].flag&ME_VERT_TMP_TAG)==0) { + set_crazy_vertex_quat(&quats[mface->v4*4], co4, co1, co3, v4, v1, v3); + mvert[mface->v4].flag|= ME_VERT_TMP_TAG; + } + } + else { + if((mvert[mface->v1].flag&ME_VERT_TMP_TAG)==0) { + set_crazy_vertex_quat(&quats[mface->v1*4], co1, co2, co3, v1, v2, v3); + mvert[mface->v1].flag|= ME_VERT_TMP_TAG; + } + if((mvert[mface->v3].flag&ME_VERT_TMP_TAG)==0) { + set_crazy_vertex_quat(&quats[mface->v3*4], co3, co1, co2, v3, v1, v2); + mvert[mface->v3].flag|= ME_VERT_TMP_TAG; + } + } + } +} + +int editbmesh_get_first_deform_matrices(Scene *scene, Object *ob, BMEditMesh *em, + float (**deformmats)[3][3], float (**deformcos)[3]) +{ + ModifierData *md; + DerivedMesh *dm; + int i, a, numleft = 0, numVerts = 0; + int cageIndex = modifiers_getCageIndex(scene, ob, NULL, 1); + float (*defmats)[3][3] = NULL, (*deformedVerts)[3] = NULL; + + modifiers_clearErrors(ob); + + dm = NULL; + md = modifiers_getVirtualModifierList(ob); + + /* 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(!editbmesh_modifier_is_enabled(scene, md, dm)) + continue; + + if(mti->type==eModifierTypeType_OnlyDeform && mti->deformMatricesEM) { + if(!defmats) { + dm= getEditDerivedBMesh(em, ob, NULL); + deformedVerts= editbmesh_get_vertex_cos(em, &numVerts); + defmats= MEM_callocN(sizeof(*defmats)*numVerts, "defmats"); + + for(a=0; a<numVerts; a++) + unit_m3(defmats[a]); + } + + mti->deformMatricesEM(md, ob, em, dm, deformedVerts, defmats, + numVerts); + } + else + break; + } + + for(; md && i <= cageIndex; md = md->next, i++) + if(editbmesh_modifier_is_enabled(scene, md, dm) && modifier_isCorrectableDeformed(md)) + numleft++; + + if(dm) + dm->release(dm); + + *deformmats= defmats; + *deformcos= deformedVerts; + + return numleft; +} + +int sculpt_get_first_deform_matrices(Scene *scene, Object *ob, float (**deformmats)[3][3], float (**deformcos)[3]) +{ + ModifierData *md; + DerivedMesh *dm; + int a, numVerts= 0; + float (*defmats)[3][3]= NULL, (*deformedVerts)[3]= NULL; + MultiresModifierData *mmd= get_multires_modifier(scene, ob, 0); + int has_multires = mmd != NULL && mmd->sculptlvl > 0; + int numleft= 0; + + if(has_multires) { + *deformmats= NULL; + *deformcos= NULL; + return numleft; + } + + dm= NULL; + md= modifiers_getVirtualModifierList(ob); + + for(; md; md= md->next) { + ModifierTypeInfo *mti= modifierType_getInfo(md->type); + + if(!modifier_isEnabled(scene, md, eModifierMode_Realtime)) continue; + + if(mti->type==eModifierTypeType_OnlyDeform) { + if(!defmats) { + Mesh *me= (Mesh*)ob->data; + dm= mesh_create_derived(me, ob, NULL); + deformedVerts= mesh_getVertexCos(me, &numVerts); + defmats= MEM_callocN(sizeof(*defmats)*numVerts, "defmats"); + + for(a=0; a<numVerts; a++) + unit_m3(defmats[a]); + } + + if(mti->deformMatrices) mti->deformMatrices(md, ob, dm, deformedVerts, defmats, numVerts); + else break; + } + } + + for(; md; md= md->next) { + ModifierTypeInfo *mti= modifierType_getInfo(md->type); + + if(!modifier_isEnabled(scene, md, eModifierMode_Realtime)) continue; + + if(mti->type==eModifierTypeType_OnlyDeform) + numleft++; + } + + if(dm) + dm->release(dm); + + *deformmats= defmats; + *deformcos= deformedVerts; + + return numleft; +} + +void crazyspace_build_sculpt(Scene *scene, Object *ob, float (**deformmats)[3][3], float (**deformcos)[3]) +{ + int totleft= sculpt_get_first_deform_matrices(scene, ob, deformmats, deformcos); + + if(totleft) { + /* there are deformation modifier which doesn't support deformation matricies + calculation. Need additional crazyspace correction */ + + float (*deformedVerts)[3]= *deformcos; + float (*origVerts)[3]= MEM_dupallocN(deformedVerts); + float *quats= NULL; + int i, deformed= 0; + ModifierData *md= modifiers_getVirtualModifierList(ob); + Mesh *me= (Mesh*)ob->data; + + for(; md; md= md->next) { + ModifierTypeInfo *mti= modifierType_getInfo(md->type); + + if(!modifier_isEnabled(scene, md, eModifierMode_Realtime)) continue; + + if(mti->type==eModifierTypeType_OnlyDeform) { + /* skip leading modifiers which have been alredy + handled in sculpt_get_first_deform_matrices */ + if(mti->deformMatrices && !deformed) + continue; + + mti->deformVerts(md, ob, NULL, deformedVerts, me->totvert, 0, 0); + deformed= 1; + } + } + + quats= MEM_mallocN(me->totvert*sizeof(float)*4, "crazy quats"); + + crazyspace_set_quats_mesh(me, (float*)origVerts, (float*)deformedVerts, quats); + + for(i=0; i<me->totvert; i++) { + float qmat[3][3], tmat[3][3]; + + quat_to_mat3(qmat, &quats[i*4]); + mul_m3_m3m3(tmat, qmat, (*deformmats)[i]); + copy_m3_m3((*deformmats)[i], tmat); + } + + MEM_freeN(origVerts); + MEM_freeN(quats); + } +} |