From 296f91c4cc02a5822bf8c74031be1ec35db86d3c Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 24 Jan 2013 04:02:30 +0000 Subject: add 'deform - integrate' option to mesh-cache, 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. --- source/blender/blenkernel/BKE_mesh.h | 10 ++++ source/blender/blenkernel/intern/mesh.c | 62 ++++++++++++++++++++++ source/blender/makesdna/DNA_modifier_types.h | 7 +++ source/blender/makesrna/intern/rna_modifier.c | 13 +++++ source/blender/modifiers/intern/MOD_meshcache.c | 58 +++++++++++++++++++- .../blender/modifiers/intern/MOD_meshcache_util.c | 4 ++ .../blender/modifiers/intern/MOD_meshcache_util.h | 4 ++ 7 files changed, 156 insertions(+), 2 deletions(-) (limited to 'source') diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index 3466a914bce..cfe562e231c 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -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]); +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, diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index 79cbd2ef886..03df0c28944 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -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, diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index 42ddbd84368..117eac0e42b 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -1175,6 +1175,8 @@ typedef struct MeshCacheModifierData { char interp; float factor; + char deform_mode; + char pad[7]; /* play_mode == MOD_MESHCACHE_PLAY_CFEA */ float frame_start; @@ -1194,6 +1196,11 @@ enum { 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, diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c index c427b9860e3..21ab11271c4 100644 --- a/source/blender/makesrna/intern/rna_modifier.c +++ b/source/blender/makesrna/intern/rna_modifier.c @@ -3489,6 +3489,14 @@ static void rna_def_modifier_meshcache(BlenderRNA *brna) {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", ""}, @@ -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"); + 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"); diff --git a/source/blender/modifiers/intern/MOD_meshcache.c b/source/blender/modifiers/intern/MOD_meshcache.c index e74da2c5d2b..1dd41c349d9 100644 --- a/source/blender/modifiers/intern/MOD_meshcache.c +++ b/source/blender/modifiers/intern/MOD_meshcache.c @@ -28,6 +28,8 @@ #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" @@ -37,6 +39,7 @@ #include "BKE_DerivedMesh.h" #include "BKE_scene.h" #include "BKE_global.h" +#include "BKE_mesh.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->deform_mode = mcmd->deform_mode; 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) { - 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; @@ -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 (ok) { + + if (ok && use_factor) { interp_vn_vn(*vertexCos_Real, *vertexCos_Store, mcmd->factor, numVerts * 3); } diff --git a/source/blender/modifiers/intern/MOD_meshcache_util.c b/source/blender/modifiers/intern/MOD_meshcache_util.c index 9068eb87581..679a79322c3 100644 --- a/source/blender/modifiers/intern/MOD_meshcache_util.c +++ b/source/blender/modifiers/intern/MOD_meshcache_util.c @@ -23,8 +23,12 @@ #include "BLI_utildefines.h" #include "BLI_math.h" +#include "DNA_mesh_types.h" +#include "DNA_meshdata_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, diff --git a/source/blender/modifiers/intern/MOD_meshcache_util.h b/source/blender/modifiers/intern/MOD_meshcache_util.h index 4cbae43d051..d7e71518f77 100644 --- a/source/blender/modifiers/intern/MOD_meshcache_util.h +++ b/source/blender/modifiers/intern/MOD_meshcache_util.h @@ -26,6 +26,9 @@ #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, @@ -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); +/* 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); -- cgit v1.2.3