Sculpting on deformed mesh

==========================

Removed limitation of armatured-only objects for sculpting -- now all
deformation modifiers are allowed in sculpt mode. Use crazyspace corrections
like from transformation modules was used to support all deformation modifiers.

Internal change: all crazyspace-related functions were noved to crazyspace.c

P.S. Brush could make quite unexpected deformation for meshes which are
     deformed in specified way. Got patch for this and discussing with Brecht
	 if it's really needed or maybe it could be done in better way.
This commit is contained in:
Sergey Sharybin 2011-02-12 17:51:02 +00:00
parent 673ac43f2e
commit d909e61d99
7 changed files with 417 additions and 253 deletions

View file

@ -512,8 +512,9 @@ void makeDerivedMesh(struct Scene *scene, struct Object *ob, struct EditMesh *em
int editmesh_get_first_deform_matrices(struct Scene *, struct Object *, struct EditMesh *em,
float (**deformmats)[3][3], float (**deformcos)[3]);
/* returns an array of deform matrices for crazyspace correction when sculpting */
void sculpt_get_deform_matrices(struct Scene *scene, struct Object *ob,
/* returns an array of deform matrices for crazyspace correction when sculpting,
and the number of modifiers left */
int sculpt_get_deform_matrices(struct Scene *scene, struct Object *ob,
float (**deformmats)[3][3], float (**deformcos)[3]);
void weight_to_rgb(float input, float *fr, float *fg, float *fb);

View file

@ -1721,12 +1721,6 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
if(useDeform < 0 && mti->dependsOnTime && mti->dependsOnTime(md)) continue;
if(mti->type == eModifierTypeType_OnlyDeform) {
if(sculpt_mode && !has_multires)
if(!ELEM(md->type, eModifierType_Armature, eModifierType_ShapeKey)) {
modifier_setError(md, "Not supported in sculpt mode.");
continue;
}
if(!deformedVerts)
deformedVerts = mesh_getVertexCos(me, &numVerts);
@ -1780,7 +1774,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos
continue;
}
if(sculpt_mode && (!has_multires || multires_applied))
if(md->type != eModifierType_Armature || multires_applied) {
if(mti->type != eModifierTypeType_OnlyDeform || multires_applied) {
modifier_setError(md, "Not supported in sculpt mode.");
continue;
}
@ -2485,105 +2479,6 @@ float *mesh_get_mapped_verts_nors(Scene *scene, Object *ob)
return vertexcosnos;
}
/* ********* crazyspace *************** */
int editmesh_get_first_deform_matrices(Scene *scene, Object *ob, EditMesh *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(!editmesh_modifier_is_enabled(scene, md, dm))
continue;
if(mti->type==eModifierTypeType_OnlyDeform && mti->deformMatricesEM) {
if(!defmats) {
dm= editmesh_get_derived(em, NULL);
deformedVerts= editmesh_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(editmesh_modifier_is_enabled(scene, md, dm) && modifier_isCorrectableDeformed(md))
numleft++;
if(dm)
dm->release(dm);
*deformmats= defmats;
*deformcos= deformedVerts;
return numleft;
}
void sculpt_get_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;
if(has_multires) {
*deformmats= NULL;
*deformcos= NULL;
return;
}
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 && mti->deformMatrices) {
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]);
}
mti->deformMatrices(md, ob, dm, deformedVerts, defmats, numVerts);
}
}
if(dm)
dm->release(dm);
*deformmats= defmats;
*deformcos= deformedVerts;
}
/* ******************* GLSL ******************** */
void DM_add_tangent_layer(DerivedMesh *dm)

View file

@ -28,12 +28,15 @@
#ifndef ED_UTIL_H
#define ED_UTIL_H
struct Scene;
struct Object;
struct bContext;
struct ARegion;
struct uiBlock;
struct wmOperator;
struct wmOperatorType;
struct EditMesh;
struct Mesh;
/* ed_util.c */
@ -73,6 +76,15 @@ void undo_editmode_menu (struct bContext *C);
void undo_editmode_clear (void);
void undo_editmode_step (struct bContext *C, int step);
/* crazyspace.c */
float *crazyspace_get_mapped_editverts(struct Scene *scene, struct Object *obedit);
void crazyspace_set_quats_editmesh(struct EditMesh *em, float *origcos, float *mappedcos, float *quats);
void crazyspace_set_quats_mesh(struct Mesh *me, float *origcos, float *mappedcos, float *quats);
int editmesh_get_first_deform_matrices(struct Scene *scene, struct Object *ob, struct EditMesh *em, float (**deformmats)[3][3], float (**deformcos)[3]);
int sculpt_get_first_deform_matrices(struct Scene *scene, struct Object *ob, float (**deformmats)[3][3], float (**deformcos)[3]);
void crazyspace_build_sculpt(struct Scene *scene, struct Object *ob, float (**deformmats)[3][3], float (**deformcos)[3]);
/* ************** XXX OLD CRUFT WARNING ************* */
void apply_keyb_grid(int shift, int ctrl, float *val, float fac1, float fac2, float fac3, int invert);

View file

@ -66,6 +66,7 @@
#include "WM_types.h"
#include "ED_screen.h"
#include "ED_view3d.h"
#include "ED_util.h" /* for crazyspace correction */
#include "paint_intern.h"
#include "sculpt_intern.h"
@ -169,7 +170,7 @@ int sculpt_modifiers_active(Scene *scene, Object *ob)
if(!modifier_isEnabled(scene, md, eModifierMode_Realtime)) continue;
if(md->type==eModifierType_ShapeKey) continue;
if(mti->type==eModifierTypeType_OnlyDeform && mti->deformMatrices)
if(mti->type==eModifierTypeType_OnlyDeform)
return 1;
}
@ -2642,7 +2643,7 @@ void sculpt_update_mesh_elements(Scene *scene, Object *ob, int need_fmap)
if(ss->kb) ss->orig_cos = key_to_vertcos(ob, ss->kb);
else ss->orig_cos = mesh_getVertexCos(ob->data, NULL);
sculpt_get_deform_matrices(scene, ob, &ss->deform_imats, &ss->deform_cos);
crazyspace_build_sculpt(scene, ob, &ss->deform_imats, &ss->deform_cos);
BLI_pbvh_apply_vertCos(ss->pbvh, ss->deform_cos);
for(a = 0; a < ((Mesh*)ob->data)->totvert; ++a)

View file

@ -85,6 +85,7 @@
#include "ED_types.h"
#include "ED_uvedit.h"
#include "ED_curve.h" /* for ED_curve_editnurbs */
#include "ED_util.h" /* for crazyspace correction */
#include "UI_view2d.h"
@ -1940,147 +1941,6 @@ static void VertsToTransData(TransInfo *t, TransData *td, EditMesh *em, EditVert
}
}
/* *********************** CrazySpace correction. Now without doing subsurf optimal ****************** */
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 */
static float *get_crazy_mapped_editverts(TransInfo *t)
{
Mesh *me= t->obedit->data;
DerivedMesh *dm;
float *vertexcos;
/* disable subsurf temporal, get mapped cos, and enable it */
if(modifiers_disable_subsurf_temporary(t->obedit)) {
/* need to make new derivemesh */
makeDerivedMesh(t->scene, t->obedit, me->edit_mesh, CD_MASK_BAREMESH);
}
/* now get the cage */
dm= editmesh_get_derived_cage(t->scene, t->obedit, me->edit_mesh, CD_MASK_BAREMESH);
vertexcos= MEM_mallocN(3*sizeof(float)*me->edit_mesh->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(t->obedit);
return vertexcos;
}
#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 set_crazyspace_quats(EditMesh *em, float *origcos, float *mappedcos, float *quats)
{
EditVert *eve, *prev;
EditFace *efa;
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;
}
void createTransBMeshVerts(TransInfo *t, BME_Mesh *bm, BME_TransData_Head *td) {
BME_Vert *v;
BME_TransData *vtd;
@ -2200,9 +2060,9 @@ static void createTransEditVerts(bContext *C, TransInfo *t)
correction with quats, relative to the coordinates after
the modifiers that support deform matrices (defcos) */
if(totleft > 0) {
mappedcos= get_crazy_mapped_editverts(t);
mappedcos= crazyspace_get_mapped_editverts(t->scene, t->obedit);
quats= MEM_mallocN( (t->total)*sizeof(float)*4, "crazy quats");
set_crazyspace_quats(em, (float*)defcos, mappedcos, quats);
crazyspace_set_quats_editmesh(em, (float*)defcos, mappedcos, quats);
if(mappedcos)
MEM_freeN(mappedcos);
}

View file

@ -34,6 +34,7 @@ set(SRC
editmode_undo.c
numinput.c
undo.c
crazyspace.c
util_intern.h
# general includes

View file

@ -0,0 +1,394 @@
/**
* $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 "BLI_utildefines.h"
#include "BLI_math.h"
#include "BLI_editVert.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_mesh, CD_MASK_BAREMESH);
}
/* now get the cage */
dm= editmesh_get_derived_cage(scene, obedit, me->edit_mesh, CD_MASK_BAREMESH);
vertexcos= MEM_mallocN(3*sizeof(float)*me->edit_mesh->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(EditMesh *em, float *origcos, float *mappedcos, float *quats)
{
EditVert *eve, *prev;
EditFace *efa;
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;
}
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 editmesh_get_first_deform_matrices(Scene *scene, Object *ob, EditMesh *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(!editmesh_modifier_is_enabled(scene, md, dm))
continue;
if(mti->type==eModifierTypeType_OnlyDeform && mti->deformMatricesEM) {
if(!defmats) {
dm= editmesh_get_derived(em, NULL);
deformedVerts= editmesh_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(editmesh_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;
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)
mti->deformVerts(md, ob, NULL, deformedVerts, me->totvert, 0, 0);
}
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);
}
}