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.
This commit is contained in:
@@ -168,6 +168,7 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
|
||||
|
||||
layout.label(text="Evaluation:")
|
||||
layout.prop(md, "factor", slider=True)
|
||||
layout.prop(md, "deform_mode")
|
||||
layout.prop(md, "interpolation")
|
||||
|
||||
layout.label(text="Time Mapping:")
|
||||
|
@@ -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,
|
||||
|
@@ -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,
|
||||
|
@@ -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,
|
||||
|
@@ -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");
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
|
@@ -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,
|
||||
|
@@ -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);
|
||||
|
Reference in New Issue
Block a user