add 'deform - integrate' option to mesh-cache,
authorCampbell Barton <ideasman42@gmail.com>
Thu, 24 Jan 2013 04:02:30 +0000 (04:02 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Thu, 24 Jan 2013 04:02:30 +0000 (04:02 +0000)
This means the deformation on the input to the modifier can be re-applied ontop of the mesh cache.

In practice this is most useful for using corrective shape-keys with mesh-cache.

release/scripts/startup/bl_ui/properties_data_modifier.py
source/blender/blenkernel/BKE_mesh.h
source/blender/blenkernel/intern/mesh.c
source/blender/makesdna/DNA_modifier_types.h
source/blender/makesrna/intern/rna_modifier.c
source/blender/modifiers/intern/MOD_meshcache.c
source/blender/modifiers/intern/MOD_meshcache_util.c
source/blender/modifiers/intern/MOD_meshcache_util.h

index 79846df14aef27404e8a6858b08e94548dbdb018..99f82b1e8a359b43d7339fea9bbb263fe1d6eda1 100644 (file)
@@ -168,6 +168,7 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
 
         layout.label(text="Evaluation:")
         layout.prop(md, "factor", slider=True)
 
         layout.label(text="Evaluation:")
         layout.prop(md, "factor", slider=True)
+        layout.prop(md, "deform_mode")
         layout.prop(md, "interpolation")
 
         layout.label(text="Time Mapping:")
         layout.prop(md, "interpolation")
 
         layout.label(text="Time Mapping:")
index 3466a914bce8605752ac93a122e54a4fc410278a..cfe562e231c1ec0dd01e553626fac763c6eb9751 100644 (file)
@@ -100,6 +100,16 @@ void BKE_mesh_calc_poly_center(struct MPoly *mpoly, struct MLoop *loopstart,
 float BKE_mesh_calc_poly_area(struct MPoly *mpoly, struct MLoop *loopstart,
                               struct MVert *mvarray, const float polynormal[3]);
 
 float BKE_mesh_calc_poly_area(struct MPoly *mpoly, struct MLoop *loopstart,
                               struct MVert *mvarray, const float polynormal[3]);
 
+void BKE_mesh_calc_relative_deform(
+        const struct MPoly *mpoly, const int totpoly,
+        const struct MLoop *mloop, const int totvert,
+
+        const float (*vert_cos_src)[3],
+        const float (*vert_cos_dst)[3],
+
+        const float (*vert_cos_org)[3],
+              float (*vert_cos_new)[3]);
+
 /* Find the index of the loop in 'poly' which references vertex,
  * returns -1 if not found */
 int poly_find_loop_from_vert(const struct MPoly *poly,
 /* Find the index of the loop in 'poly' which references vertex,
  * returns -1 if not found */
 int poly_find_loop_from_vert(const struct MPoly *poly,
index 79cbd2ef886e202229d5582db5cad1899a941ff6..03df0c289446b2e1e1eb672c931a98908868c071 100644 (file)
@@ -2993,6 +2993,68 @@ float BKE_mesh_calc_poly_area(MPoly *mpoly, MLoop *loopstart,
        }
 }
 
        }
 }
 
+/**
+ * This function takes the difference between 2 vertex-coord-arrays
+ * (\a vert_cos_src, \a vert_cos_dst),
+ * and applies the difference to \a vert_cos_new relative to \a vert_cos_org.
+ *
+ * \param vert_cos_src reference deform source.
+ * \param vert_cos_dst reference deform destination.
+ *
+ * \param vert_cos_org reference for the output location.
+ * \param vert_cos_new resulting coords.
+ */
+void BKE_mesh_calc_relative_deform(
+        const MPoly *mpoly, const int totpoly,
+        const MLoop *mloop, const int totvert,
+
+        const float (*vert_cos_src)[3],
+        const float (*vert_cos_dst)[3],
+
+        const float (*vert_cos_org)[3],
+              float (*vert_cos_new)[3])
+{
+       const MPoly *mp;
+       int i;
+
+       int *vert_accum = MEM_callocN(sizeof(*vert_accum) * totvert, __func__);
+
+       memset(vert_cos_new, '\0', sizeof(*vert_cos_new) * totvert);
+
+       for (i = 0, mp = mpoly; i < totpoly; i++, mp++) {
+               const MLoop *loopstart = mloop + mp->loopstart;
+               int j;
+
+               for (j = 0; j < mp->totloop; j++) {
+                       int v_prev = (loopstart + ((mp->totloop + (j - 1)) % mp->totloop))->v;
+                       int v_curr = (loopstart + j)->v;
+                       int v_next = (loopstart + ((j + 1) % mp->totloop))->v;
+
+                       float tvec[3];
+
+                       barycentric_transform(
+                                   tvec, vert_cos_dst[v_curr],
+                                   vert_cos_org[v_prev], vert_cos_org[v_curr], vert_cos_org[v_next],
+                                   vert_cos_src[v_prev], vert_cos_src[v_curr], vert_cos_src[v_next]
+                                   );
+
+                       add_v3_v3(vert_cos_new[v_curr], tvec);
+                       vert_accum[v_curr] += 1;
+               }
+       }
+
+       for (i = 0; i < totvert; i++) {
+               if (vert_accum[i]) {
+                       mul_v3_fl(vert_cos_new[i], 1.0f / (float)vert_accum[i]);
+               }
+               else {
+                       copy_v3_v3(vert_cos_new[i], vert_cos_org[i]);
+               }
+       }
+
+       MEM_freeN(vert_accum);
+}
+
 /* Find the index of the loop in 'poly' which references vertex,
  * returns -1 if not found */
 int poly_find_loop_from_vert(const MPoly *poly, const MLoop *loopstart,
 /* Find the index of the loop in 'poly' which references vertex,
  * returns -1 if not found */
 int poly_find_loop_from_vert(const MPoly *poly, const MLoop *loopstart,
index 42ddbd8436854f968ae4c522e0cd228429fc517d..117eac0e42b036ddad86928f3ef5b4fb275d45c3 100644 (file)
@@ -1175,6 +1175,8 @@ typedef struct MeshCacheModifierData {
        char interp;
 
        float factor;
        char interp;
 
        float factor;
+       char deform_mode;
+       char pad[7];
 
        /* play_mode == MOD_MESHCACHE_PLAY_CFEA */
        float frame_start;
 
        /* play_mode == MOD_MESHCACHE_PLAY_CFEA */
        float frame_start;
@@ -1194,6 +1196,11 @@ enum {
        MOD_MESHCACHE_TYPE_PC2  = 2
 };
 
        MOD_MESHCACHE_TYPE_PC2  = 2
 };
 
+enum {
+       MOD_MESHCACHE_DEFORM_OVERWRITE  = 0,
+       MOD_MESHCACHE_DEFORM_INTEGRATE  = 1
+};
+
 enum {
        MOD_MESHCACHE_INTERP_NONE  = 0,
        MOD_MESHCACHE_INTERP_LINEAR = 1,
 enum {
        MOD_MESHCACHE_INTERP_NONE  = 0,
        MOD_MESHCACHE_INTERP_LINEAR = 1,
index c427b9860e39b64746cad0ed5c0a2ac28dec3800..21ab11271c43f6559c305e043cd085cecc800f8d 100644 (file)
@@ -3489,6 +3489,14 @@ static void rna_def_modifier_meshcache(BlenderRNA *brna)
                {0, NULL, 0, NULL, NULL}
        };
 
                {0, NULL, 0, NULL, NULL}
        };
 
+       static EnumPropertyItem prop_deform_mode_items[] = {
+               {MOD_MESHCACHE_DEFORM_OVERWRITE, "OVERWRITE", 0, "Overwrite",
+                "Replace vertex coords with cached values"},
+               {MOD_MESHCACHE_DEFORM_INTEGRATE, "INTEGRATE", 0, "Integrate",
+                "Integrate deformation from this modifiers input with the mesh-cache coords (useful for shape keys)"},
+               {0, NULL, 0, NULL, NULL}
+       };
+
        static EnumPropertyItem prop_interpolation_type_items[] = {
                {MOD_MESHCACHE_INTERP_NONE, "NONE", 0, "None ", ""},
                {MOD_MESHCACHE_INTERP_LINEAR, "LINEAR", 0, "Linear", ""},
        static EnumPropertyItem prop_interpolation_type_items[] = {
                {MOD_MESHCACHE_INTERP_NONE, "NONE", 0, "None ", ""},
                {MOD_MESHCACHE_INTERP_LINEAR, "LINEAR", 0, "Linear", ""},
@@ -3553,6 +3561,11 @@ static void rna_def_modifier_meshcache(BlenderRNA *brna)
        RNA_def_property_ui_text(prop, "Time Mode", "");
        RNA_def_property_update(prop, 0, "rna_Modifier_update");
 
        RNA_def_property_ui_text(prop, "Time Mode", "");
        RNA_def_property_update(prop, 0, "rna_Modifier_update");
 
+       prop = RNA_def_property(srna, "deform_mode", PROP_ENUM, PROP_NONE);
+       RNA_def_property_enum_sdna(prop, NULL, "deform_mode");
+       RNA_def_property_enum_items(prop, prop_deform_mode_items);
+       RNA_def_property_ui_text(prop, "Deform Mode", "");
+       RNA_def_property_update(prop, 0, "rna_Modifier_update");
 
        prop = RNA_def_property(srna, "filepath", PROP_STRING, PROP_FILEPATH);
        RNA_def_property_ui_text(prop, "File Path", "Path to external displacements file");
 
        prop = RNA_def_property(srna, "filepath", PROP_STRING, PROP_FILEPATH);
        RNA_def_property_ui_text(prop, "File Path", "Path to external displacements file");
index e74da2c5d2be9969b024d29311102c869218dd24..1dd41c349d920e440b26233eee1407d5756bcce6 100644 (file)
@@ -28,6 +28,8 @@
 
 #include "DNA_scene_types.h"
 #include "DNA_object_types.h"
 
 #include "DNA_scene_types.h"
 #include "DNA_object_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
 
 #include "BLI_utildefines.h"
 #include "BLI_string.h"
 
 #include "BLI_utildefines.h"
 #include "BLI_string.h"
@@ -37,6 +39,7 @@
 #include "BKE_DerivedMesh.h"
 #include "BKE_scene.h"
 #include "BKE_global.h"
 #include "BKE_DerivedMesh.h"
 #include "BKE_scene.h"
 #include "BKE_global.h"
+#include "BKE_mesh.h"
 #include "BKE_main.h"
 
 #include "MEM_guardedalloc.h"
 #include "BKE_main.h"
 
 #include "MEM_guardedalloc.h"
@@ -84,6 +87,7 @@ static void copyData(ModifierData *md, ModifierData *target)
        tmcmd->frame_scale = mcmd->frame_scale;
 
        tmcmd->factor = mcmd->factor;
        tmcmd->frame_scale = mcmd->frame_scale;
 
        tmcmd->factor = mcmd->factor;
+       tmcmd->deform_mode = mcmd->deform_mode;
 
        tmcmd->eval_frame  = mcmd->eval_frame;
        tmcmd->eval_time   = mcmd->eval_time;
 
        tmcmd->eval_frame  = mcmd->eval_frame;
        tmcmd->eval_time   = mcmd->eval_time;
@@ -111,7 +115,8 @@ static void meshcache_do(
         MeshCacheModifierData *mcmd, Object *ob, DerivedMesh *UNUSED(dm),
         float (*vertexCos_Real)[3], int numVerts)
 {
         MeshCacheModifierData *mcmd, Object *ob, DerivedMesh *UNUSED(dm),
         float (*vertexCos_Real)[3], int numVerts)
 {
-       float (*vertexCos_Store)[3] = (mcmd->factor < 1.0f) ?
+       const bool use_factor = mcmd->factor < 1.0f;
+       float (*vertexCos_Store)[3] = (use_factor || (mcmd->deform_mode == MOD_MESHCACHE_DEFORM_INTEGRATE)) ?
                                      MEM_mallocN(sizeof(*vertexCos_Store) * numVerts, __func__) : NULL;
        float (*vertexCos)[3] = vertexCos_Store ? vertexCos_Store : vertexCos_Real;
 
                                      MEM_mallocN(sizeof(*vertexCos_Store) * numVerts, __func__) : NULL;
        float (*vertexCos)[3] = vertexCos_Store ? vertexCos_Store : vertexCos_Real;
 
@@ -229,8 +234,57 @@ static void meshcache_do(
                }
        }
 
                }
        }
 
+       /* tricky shape key integration (slow!) */
+       if (mcmd->deform_mode == MOD_MESHCACHE_DEFORM_INTEGRATE) {
+               /* we could support any object type */
+               if (ob->type != OB_MESH) {
+                       modifier_setError(&mcmd->modifier, "'Integrate' only valid for Mesh objects");
+               }
+               else {
+                       Mesh *me = ob->data;
+                       if (me->totvert != numVerts) {
+                               modifier_setError(&mcmd->modifier, "'Integrate' original mesh vertex mismatch");
+                       }
+                       else {
+                               if (me->totpoly == 0) {
+                                       modifier_setError(&mcmd->modifier, "'Integrate' requires faces");
+                               }
+                               else {
+                                       /* the moons align! */
+                                       int i;
+
+                                       float (*vertexCos_Source)[3] = MEM_mallocN(sizeof(*vertexCos_Source) * numVerts, __func__);
+                                       float (*vertexCos_New)[3]    = MEM_mallocN(sizeof(*vertexCos_New) * numVerts, __func__);
+                                       MVert *mv = me->mvert;
+
+                                       for (i = 0; i < numVerts; i++, mv++) {
+                                               copy_v3_v3(vertexCos_Source[i], mv->co);
+                                       }
+
+                                       BKE_mesh_calc_relative_deform(
+                                               me->mpoly, me->totpoly,
+                                               me->mloop, me->totvert,
+
+                                               (const float (*)[3])vertexCos_Source,   /* from the original Mesh*/
+                                               (const float (*)[3])vertexCos_Real,     /* the input we've been given (shape keys!) */
+
+                                               (const float (*)[3])vertexCos,          /* the result of this modifier */
+                                               vertexCos_New       /* the result of this function */
+                                               );
+
+                                       /* write the corrected locations back into the result */
+                                       memcpy(use_factor ? vertexCos : vertexCos_Real, vertexCos_New, sizeof(*vertexCos) * numVerts);
+
+                                       MEM_freeN(vertexCos_Source);
+                                       MEM_freeN(vertexCos_New);
+                               }
+                       }
+               }
+       }
+
        if (vertexCos_Store) {
        if (vertexCos_Store) {
-               if (ok) {
+
+               if (ok && use_factor) {
                        interp_vn_vn(*vertexCos_Real, *vertexCos_Store, mcmd->factor, numVerts * 3);
                }
 
                        interp_vn_vn(*vertexCos_Real, *vertexCos_Store, mcmd->factor, numVerts * 3);
                }
 
index 9068eb87581b6791b00835c4bcd565bea4b82b5a..679a79322c33c85115a383167554efd0cbf329bd 100644 (file)
 #include "BLI_utildefines.h"
 #include "BLI_math.h"
 
 #include "BLI_utildefines.h"
 #include "BLI_math.h"
 
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
 #include "DNA_modifier_types.h"
 
 #include "DNA_modifier_types.h"
 
+#include "MEM_guardedalloc.h"
+
 #include "MOD_meshcache_util.h"
 
 void MOD_meshcache_calc_range(const float frame, const char interp,
 #include "MOD_meshcache_util.h"
 
 void MOD_meshcache_calc_range(const float frame, const char interp,
index 4cbae43d05184ee3ca3dad28bb2f7a4c4854960b..d7e71518f77d3093bd460d6198e23ab6994454fb 100644 (file)
@@ -26,6 +26,9 @@
 
 #ifndef __MOD_MESHCACHE_UTIL_H__
 
 
 #ifndef __MOD_MESHCACHE_UTIL_H__
 
+struct MPoly;
+struct MLoop;
+
 /* MOD_meshcache_mdd.c */
 bool MOD_meshcache_read_mdd_index(FILE *fp,
                                   float (*vertexCos)[3], const int vertex_tot,
 /* MOD_meshcache_mdd.c */
 bool MOD_meshcache_read_mdd_index(FILE *fp,
                                   float (*vertexCos)[3], const int vertex_tot,
@@ -54,6 +57,7 @@ bool MOD_meshcache_read_pc2_times(const char *filepath,
                                   const float time, const float fps, const char time_mode,
                                   const char **err_str);
 
                                   const float time, const float fps, const char time_mode,
                                   const char **err_str);
 
+/* MOD_meshcache_util.c */
 void MOD_meshcache_calc_range(const float frame, const char interp,
                               const int frame_tot,
                               int r_index_range[2], float *r_factor);
 void MOD_meshcache_calc_range(const float frame, const char interp,
                               const int frame_tot,
                               int r_index_range[2], float *r_factor);