svn merge ^/trunk/blender -r41226:41227 .
[blender.git] / source / blender / modifiers / intern / MOD_weightvgmix.c
index 29e00040bf6c773f81cf3dae81231e7daf4d8fa3..43f503a7624a4042828d5453e748fce6f9b48464 100644 (file)
@@ -1,36 +1,31 @@
 /*
-* $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) 2011 by Bastien Montagne.
-* All rights reserved.
-*
-* Contributor(s): None yet.
-*
-* ***** END GPL LICENSE BLOCK *****
-*
-*/
+ * ***** 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) 2011 by Bastien Montagne.
+ * All rights reserved.
+ *
+ * Contributor(s): None yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ */
 
-/*
- * XXX I’d like to make modified weights visible in WeightPaint mode,
- *     but couldn’t figure a way to do this…
- *     Maybe this will need changes in mesh_calc_modifiers (DerivedMesh.c)?
- *     Or the WeightPaint mode code itself?
+/** \file blender/modifiers/intern/MOD_weightvgmix.c
+ *  \ingroup modifiers
  */
 
 #include "BLI_utildefines.h"
@@ -61,8 +56,8 @@ static float mix_weight(float weight, float weight2, char mix_mode)
 {
 #if 0
        /*
-        * XXX Dont know why, but the switch version takes many CPU time,
-        *     and produces lag in realtime playback
+        * XXX Don't know why, but the switch version takes many CPU time,
+        *     and produces lag in realtime playback...
         */
        switch (mix_mode)
        {
@@ -98,16 +93,16 @@ static float mix_weight(float weight, float weight2, char mix_mode)
                return (weight * weight2);
        else if (mix_mode == MOD_WVG_MIX_DIV) {
                /* Avoid dividing by zero (or really small values). */
-               if (weight2 < 0.0 && weight2 > -MOD_WVG_ZEROFLOOR)
+               if (weight2 < 0.0f && weight2 > -MOD_WVG_ZEROFLOOR)
                        weight2 = -MOD_WVG_ZEROFLOOR;
-               else if (weight2 >= 0.0 && weight2 < MOD_WVG_ZEROFLOOR)
+               else if (weight2 >= 0.0f && weight2 < MOD_WVG_ZEROFLOOR)
                        weight2 = MOD_WVG_ZEROFLOOR;
                return (weight / weight2);
        }
        else if (mix_mode == MOD_WVG_MIX_DIF)
                return (weight < weight2 ? weight2 - weight : weight - weight2);
        else if (mix_mode == MOD_WVG_MIX_AVG)
-               return (weight + weight2) / 2.0;
+               return (weight + weight2) * 0.5f;
        else return weight2;
 }
 
@@ -118,10 +113,10 @@ static void initData(ModifierData *md)
 {
        WeightVGMixModifierData *wmd = (WeightVGMixModifierData*) md;
 
-       wmd->default_weight         = 0.0;
-       wmd->default_weight2        = 0.0;
+       wmd->default_weight_a       = 0.0f;
+       wmd->default_weight_b       = 0.0f;
        wmd->mix_mode               = MOD_WVG_MIX_SET;
-       wmd->mix_set                = MOD_WVG_SET_INTER;
+       wmd->mix_set                = MOD_WVG_SET_AND;
 
        wmd->mask_constant          = 1.0f;
        wmd->mask_tex_use_channel   = MOD_WVG_MASK_TEX_USE_INT; /* Use intensity by default. */
@@ -133,10 +128,10 @@ static void copyData(ModifierData *md, ModifierData *target)
        WeightVGMixModifierData *wmd  = (WeightVGMixModifierData*) md;
        WeightVGMixModifierData *twmd = (WeightVGMixModifierData*) target;
 
-       BLI_strncpy(twmd->defgrp_name, wmd->defgrp_name, sizeof(twmd->defgrp_name));
-       BLI_strncpy(twmd->defgrp_name2, wmd->defgrp_name2, sizeof(twmd->defgrp_name2));
-       twmd->default_weight         = wmd->default_weight;
-       twmd->default_weight2        = wmd->default_weight2;
+       BLI_strncpy(twmd->defgrp_name_a, wmd->defgrp_name_a, sizeof(twmd->defgrp_name_a));
+       BLI_strncpy(twmd->defgrp_name_b, wmd->defgrp_name_b, sizeof(twmd->defgrp_name_b));
+       twmd->default_weight_a       = wmd->default_weight_a;
+       twmd->default_weight_b       = wmd->default_weight_b;
        twmd->mix_mode               = wmd->mix_mode;
        twmd->mix_set                = wmd->mix_set;
 
@@ -146,8 +141,7 @@ static void copyData(ModifierData *md, ModifierData *target)
        twmd->mask_tex_use_channel   = wmd->mask_tex_use_channel;
        twmd->mask_tex_mapping       = wmd->mask_tex_mapping;
        twmd->mask_tex_map_obj       = wmd->mask_tex_map_obj;
-       BLI_strncpy(twmd->mask_tex_uvlayer_name, wmd->mask_tex_uvlayer_name,
-                   sizeof(twmd->mask_tex_uvlayer_name));
+       BLI_strncpy(twmd->mask_tex_uvlayer_name, wmd->mask_tex_uvlayer_name, sizeof(twmd->mask_tex_uvlayer_name));
 }
 
 static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
@@ -191,6 +185,11 @@ static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *u
        foreachObjectLink(md, ob, (ObjectWalkFunc)walk, userData);
 }
 
+static void foreachTexLink(ModifierData *md, Object *ob, TexWalkFunc walk, void *userData)
+{
+       walk(userData, ob, md, "mask_texture");
+}
+
 static void updateDepgraph(ModifierData *md, DagForest *forest, struct Scene *UNUSED(scene),
                            Object *UNUSED(ob), DagNode *obNode)
 {
@@ -213,7 +212,7 @@ static int isDisabled(ModifierData *md, int UNUSED(useRenderParams))
 {
        WeightVGMixModifierData *wmd = (WeightVGMixModifierData*) md;
        /* If no vertex group, bypass. */
-       return (wmd->defgrp_name == NULL);
+       return (wmd->defgrp_name_a[0] == '\0');
 }
 
 static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *derivedData,
@@ -225,13 +224,14 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *der
        Mesh *ob_m = NULL;
 #endif
        MDeformVert *dvert = NULL;
+       MDeformWeight **dw1, **tdw1, **dw2, **tdw2;
        int numVerts;
        int defgrp_idx, defgrp_idx2 = -1;
-       float *org_w = NULL;
-       float *new_w = NULL;
+       float *org_w;
+       float *new_w;
        int *tidx, *indices = NULL;
        int numIdx = 0;
-       int i, j;
+       int i;
        char rel_ret = 0; /* Boolean, whether we have to release ret dm or not, when not using it! */
 
        /* Get number of verts. */
@@ -244,23 +244,23 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *der
                return dm;
 
        /* Get vgroup idx from its name. */
-       defgrp_idx = defgroup_name_index(ob, wmd->defgrp_name);
+       defgrp_idx = defgroup_name_index(ob, wmd->defgrp_name_a);
        if (defgrp_idx < 0)
                return dm;
        /* Get seconf vgroup idx from its name, if given. */
-       if (wmd->defgrp_name2[0] != (char)0) {
-               defgrp_idx2 = defgroup_name_index(ob, wmd->defgrp_name2);
+       if (wmd->defgrp_name_b[0] != (char)0) {
+               defgrp_idx2 = defgroup_name_index(ob, wmd->defgrp_name_b);
                if (defgrp_idx2 < 0)
                        return dm;
        }
 
-       /* XXX All this to avoid copying dm when not needed However, it nearly doubles compute
-        *     time! See scene 5 of the WeighVG test file
+       /* XXX All this to avoid copying dm when not needed... However, it nearly doubles compute
+        *     time! See scene 5 of the WeighVG test file...
         */
 #if 0
        /* Get actual dverts (ie vertex group data). */
        dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT);
-       /* If no dverts, return unmodified data */
+       /* If no dverts, return unmodified data... */
        if (dvert == NULL)
                return dm;
 
@@ -274,7 +274,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *der
        /* Create a copy of our dmesh, only if our affected cdata layer is the same as org mesh. */
        if (dvert == CustomData_get_layer(&ob_m->vdata, CD_MDEFORMVERT)) {
                /* XXX Seems to create problems with weightpaint mode???
-                *     I’m missing something here, I guess…
+                *     I'm missing something here, I guess...
                 */
 //             DM_set_only_copy(dm, CD_MASK_MDEFORMVERT); /* Only copy defgroup layer. */
                ret = CDDM_copy(dm);
@@ -288,7 +288,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *der
        else
                ret = dm;
 #else
-       ret = CDDM_copy(dm);
+       ret = CDDM_copy(dm, 0);
        rel_ret = 1;
        dvert = ret->getVertDataArray(ret, CD_MDEFORMVERT);
        if (dvert == NULL) {
@@ -300,76 +300,91 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *der
 
        /* Find out which vertices to work on. */
        tidx = MEM_mallocN(sizeof(int) * numVerts, "WeightVGMix Modifier, tidx");
+       tdw1 = MEM_mallocN(sizeof(MDeformWeight*) * numVerts, "WeightVGMix Modifier, tdw1");
+       tdw2 = MEM_mallocN(sizeof(MDeformWeight*) * numVerts, "WeightVGMix Modifier, tdw2");
        switch (wmd->mix_set) {
-       case MOD_WVG_SET_ORG:
+       case MOD_WVG_SET_A:
                /* All vertices in first vgroup. */
                for (i = 0; i < numVerts; i++) {
-                       for (j = 0; j < dvert[i].totweight; j++) {
-                               if(dvert[i].dw[j].def_nr == defgrp_idx) {
-                                       tidx[numIdx++] = i;
-                                       break;
-                               }
+                       MDeformWeight *dw = defvert_find_index(&dvert[i], defgrp_idx);
+                       if(dw) {
+                               tdw1[numIdx] = dw;
+                               tdw2[numIdx] = defvert_find_index(&dvert[i], defgrp_idx2);
+                               tidx[numIdx++] = i;
                        }
                }
                break;
-       case MOD_WVG_SET_NEW:
+       case MOD_WVG_SET_B:
                /* All vertices in second vgroup. */
                for (i = 0; i < numVerts; i++) {
-                       for (j = 0; j < dvert[i].totweight; j++) {
-                               if(dvert[i].dw[j].def_nr == defgrp_idx2) {
-                                       tidx[numIdx++] = i;
-                                       break;
-                               }
+                       MDeformWeight *dw = defvert_find_index(&dvert[i], defgrp_idx2);
+                       if(dw) {
+                               tdw1[numIdx] = defvert_find_index(&dvert[i], defgrp_idx);
+                               tdw2[numIdx] = dw;
+                               tidx[numIdx++] = i;
                        }
                }
                break;
-       case MOD_WVG_SET_UNION:
+       case MOD_WVG_SET_OR:
                /* All vertices in one vgroup or the other. */
                for (i = 0; i < numVerts; i++) {
-                       for (j = 0; j < dvert[i].totweight; j++) {
-                               if(dvert[i].dw[j].def_nr == defgrp_idx || dvert[i].dw[j].def_nr == defgrp_idx2) {
-                                       tidx[numIdx++] = i;
-                                       break;
-                               }
+                       MDeformWeight *adw = defvert_find_index(&dvert[i], defgrp_idx);
+                       MDeformWeight *bdw = defvert_find_index(&dvert[i], defgrp_idx2);
+                       if(adw || bdw) {
+                               tdw1[numIdx] = adw;
+                               tdw2[numIdx] = bdw;
+                               tidx[numIdx++] = i;
                        }
                }
                break;
-       case MOD_WVG_SET_INTER:
+       case MOD_WVG_SET_AND:
                /* All vertices in both vgroups. */
                for (i = 0; i < numVerts; i++) {
-                       char idx1 = 0;
-                       char idx2 = 0;
-                       for (j = 0; j < dvert[i].totweight; j++) {
-                               if(dvert[i].dw[j].def_nr == defgrp_idx) {
-                                       if (idx2) {
-                                               tidx[numIdx++] = i;
-                                               break;
-                                       }
-                                       else
-                                               idx1 = 1;
-                               }
-                               else if(dvert[i].dw[j].def_nr == defgrp_idx2) {
-                                       if (idx1) {
-                                               tidx[numIdx++] = i;
-                                               break;
-                                       }
-                                       else
-                                               idx2 = 1;
-                               }
+                       MDeformWeight *adw = defvert_find_index(&dvert[i], defgrp_idx);
+                       MDeformWeight *bdw = defvert_find_index(&dvert[i], defgrp_idx2);
+                       if(adw && bdw) {
+                               tdw1[numIdx] = adw;
+                               tdw2[numIdx] = bdw;
+                               tidx[numIdx++] = i;
                        }
                }
                break;
        case MOD_WVG_SET_ALL:
        default:
-               /* Use all vertices, no need to do anything here. */
+               /* Use all vertices. */
+               for (i = 0; i < numVerts; i++) {
+                       tdw1[i] = defvert_find_index(&dvert[i], defgrp_idx);
+                       tdw2[i] = defvert_find_index(&dvert[i], defgrp_idx2);
+               }
+               numIdx = -1;
                break;
        }
-       if (numIdx) {
+       if(numIdx == 0) {
+               /* Use no vertices! Hence, return org data. */
+               MEM_freeN(tdw1);
+               MEM_freeN(tdw2);
+               MEM_freeN(tidx);
+               if (rel_ret)
+                       ret->release(ret);
+               return dm;
+       }
+       if (numIdx != -1) {
                indices = MEM_mallocN(sizeof(int) * numIdx, "WeightVGMix Modifier, indices");
                memcpy(indices, tidx, sizeof(int) * numIdx);
+               dw1 = MEM_mallocN(sizeof(MDeformWeight*) * numIdx, "WeightVGMix Modifier, dw1");
+               memcpy(dw1, tdw1, sizeof(MDeformWeight*) * numIdx);
+               MEM_freeN(tdw1);
+               dw2 = MEM_mallocN(sizeof(MDeformWeight*) * numIdx, "WeightVGMix Modifier, dw2");
+               memcpy(dw2, tdw2, sizeof(MDeformWeight*) * numIdx);
+               MEM_freeN(tdw2);
        }
-       else
+       else {
+               /* Use all vertices. */
                numIdx = numVerts;
+               /* Just copy MDeformWeight pointers arrays, they will be freed at the end. */
+               dw1 = tdw1;
+               dw2 = tdw2;
+       }
        MEM_freeN(tidx);
 
        org_w = MEM_mallocN(sizeof(float) * numIdx, "WeightVGMix Modifier, org_w");
@@ -378,27 +393,9 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *der
        /* Mix weights. */
        for (i = 0; i < numIdx; i++) {
                float weight2 = 0.0;
-               char w1 = 0;
-               char w2 = 0;
-               int idx = indices ? indices[i] : i;
-               for (j = 0; j < dvert[idx].totweight; j++) {
-                       if(dvert[idx].dw[j].def_nr == defgrp_idx) {
-                               org_w[i] = dvert[idx].dw[j].weight;
-                               w1 = 1;
-                               if (w2)
-                                       break;
-                       }
-                       else if(dvert[idx].dw[j].def_nr == defgrp_idx2) {
-                               weight2 = dvert[idx].dw[j].weight;
-                               w2 = 1;
-                               if (w1)
-                                       break;
-                       }
-               }
-               if (w1 == 0)
-                       org_w[i] = wmd->default_weight;
-               if (w2 == 0)
-                       weight2 = wmd->default_weight2;
+               org_w[i] = dw1[i] ? dw1[i]->weight : wmd->default_weight_a;
+               weight2  = dw2[i] ? dw2[i]->weight : wmd->default_weight_b;
+
                new_w[i] = mix_weight(org_w[i], weight2, wmd->mix_mode);
        }
 
@@ -410,13 +407,14 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *der
        /* Update (add to) vgroup.
         * XXX Depending on the MOD_WVG_SET_xxx option chosen, we might have to add vertices to vgroup.
         */
-       weightvg_update_vg(dvert, defgrp_idx, numIdx, indices, org_w, 1, -FLT_MAX, 0, 0.0f);
+       weightvg_update_vg(dvert, defgrp_idx, dw1, numIdx, indices, org_w, TRUE, -FLT_MAX, FALSE, 0.0f);
 
        /* Freeing stuff. */
-       if (org_w)
-               MEM_freeN(org_w);
-       if (new_w)
-               MEM_freeN(new_w);
+       MEM_freeN(org_w);
+       MEM_freeN(new_w);
+       MEM_freeN(dw1);
+       MEM_freeN(dw2);
+
        if (indices)
                MEM_freeN(indices);
 
@@ -425,7 +423,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *der
 }
 
 static DerivedMesh *applyModifierEM(ModifierData *md, Object *ob,
-                                    struct EditMesh *UNUSED(editData),
+                                    struct BMEditMesh *UNUSED(editData),
                                     DerivedMesh *derivedData)
 {
        return applyModifier(md, ob, derivedData, 0, 1);
@@ -433,7 +431,7 @@ static DerivedMesh *applyModifierEM(ModifierData *md, Object *ob,
 
 
 ModifierTypeInfo modifierType_WeightVGMix = {
-       /* name */              "WeightVGMix",
+       /* name */              "VertexWeightMix",
        /* structName */        "WeightVGMixModifierData",
        /* structSize */        sizeof(WeightVGMixModifierData),
        /* type */              eModifierTypeType_Nonconstructive,
@@ -457,5 +455,5 @@ ModifierTypeInfo modifierType_WeightVGMix = {
        /* dependsOnNormals */  NULL,
        /* foreachObjectLink */ foreachObjectLink,
        /* foreachIDLink */     foreachIDLink,
+       /* foreachTexLink */    foreachTexLink,
 };
-