Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBastien Montagne <montagne29@wanadoo.fr>2018-12-03 18:19:08 +0300
committerBastien Montagne <montagne29@wanadoo.fr>2018-12-03 18:22:27 +0300
commit3235a3081c12e99d4bec350eff04b3073c07cdf8 (patch)
treec75a7e0edd39f81ca879de8cc2d27c595c6c35fd /source/blender/blenkernel/intern/customdata.c
parent957435785cd04dd68307c390a5063026917e836e (diff)
Fix T57858: Add validation callback to CustomData layers.
Our mesh validation was only checking cd layout so far, not their actual data. While this might only be needed for a few types, this is a required addition for things like imported UVs, else we have no way to avoid nasty things like NANs & co. Note that more layer types may need that callback, time will say. For now added it to some obvious missing cases...
Diffstat (limited to 'source/blender/blenkernel/intern/customdata.c')
-rw-r--r--source/blender/blenkernel/intern/customdata.c98
1 files changed, 88 insertions, 10 deletions
diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c
index e841832f51c..b938dbb1d04 100644
--- a/source/blender/blenkernel/intern/customdata.c
+++ b/source/blender/blenkernel/intern/customdata.c
@@ -126,6 +126,9 @@ typedef struct LayerTypeInfo {
* default is assumed to be all zeros */
void (*set_default)(void *data, int count);
+ /** A function used by mesh validating code, must ensures passed item has valid data. */
+ cd_validate validate;
+
/** functions necessary for geometry collapse */
bool (*equal)(const void *data1, const void *data2);
void (*multiply)(void *data, float fac);
@@ -313,6 +316,30 @@ static void layerInterp_normal(
normalize_v3_v3((float *)dest, no);
}
+static bool layerValidate_normal(void *data, const uint totitems, const bool do_fixes)
+{
+ static const float no_default[3] = {0.0f, 0.0f, 1.0f}; /* Z-up default normal... */
+ float (*no)[3] = data;
+ bool has_errors = false;
+
+ for (int i = 0; i < totitems; i++, no++) {
+ if (!is_finite_v3((float *)no)) {
+ has_errors = true;
+ if (do_fixes) {
+ copy_v3_v3((float *)no, no_default);
+ }
+ }
+ else if (!compare_ff(len_squared_v3((float *)no), 1.0f, 1e-6f)) {
+ has_errors = true;
+ if (do_fixes) {
+ normalize_v3((float *)no);
+ }
+ }
+ }
+
+ return has_errors;
+}
+
static void layerCopyValue_normal(const void *source, void *dest, const int mixmode, const float mixfactor)
{
const float *no_src = source;
@@ -422,6 +449,23 @@ static void layerCopy_propFloat(const void *source, void *dest,
memcpy(dest, source, sizeof(MFloatProperty) * count);
}
+static bool layerValidate_propFloat(void *data, const uint totitems, const bool do_fixes)
+{
+ MFloatProperty *fp = data;
+ bool has_errors = false;
+
+ for (int i = 0; i < totitems; i++, fp++) {
+ if (!isfinite(fp->f)) {
+ if (do_fixes) {
+ fp->f = 0.0f;
+ }
+ has_errors = true;
+ }
+ }
+
+ return has_errors;
+}
+
static void layerCopy_propInt(const void *source, void *dest,
int count)
{
@@ -908,6 +952,23 @@ static void layerInterp_mloopuv(
((MLoopUV *)dest)->flag = flag;
}
+static bool layerValidate_mloopuv(void *data, const uint totitems, const bool do_fixes)
+{
+ MLoopUV *uv = data;
+ bool has_errors = false;
+
+ for (int i = 0; i < totitems; i++, uv++) {
+ if (!is_finite_v2(uv->uv)) {
+ if (do_fixes) {
+ zero_v2(uv->uv);
+ }
+ has_errors = true;
+ }
+ }
+
+ return has_errors;
+}
+
/* origspace is almost exact copy of mloopuv's, keep in sync */
static void layerCopyValue_mloop_origspace(const void *source, void *dest,
const int UNUSED(mixmode), const float UNUSED(mixfactor))
@@ -1192,21 +1253,22 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
{sizeof(MFace), "MFace", 1, NULL, NULL, NULL, NULL, NULL, NULL},
/* 5: CD_MTFACE */
{sizeof(MTFace), "MTFace", 1, N_("UVMap"), layerCopy_tface, NULL, layerInterp_tface, layerSwap_tface,
- layerDefault_tface, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, layerMaxNum_tface},
+ layerDefault_tface, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, layerMaxNum_tface},
/* 6: CD_MCOL */
/* 4 MCol structs per face */
- {sizeof(MCol) * 4, "MCol", 4, N_("Col"), NULL, NULL, layerInterp_mcol,
- layerSwap_mcol, layerDefault_mcol, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, layerMaxNum_mloopcol},
+ {sizeof(MCol) * 4, "MCol", 4, N_("Col"), NULL, NULL, layerInterp_mcol, layerSwap_mcol,
+ layerDefault_mcol, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, layerMaxNum_mloopcol},
/* 7: CD_ORIGINDEX */
{sizeof(int), "", 0, NULL, NULL, NULL, NULL, NULL, layerDefault_origindex},
/* 8: CD_NORMAL */
/* 3 floats per normal vector */
{sizeof(float) * 3, "vec3f", 1, NULL, NULL, NULL, layerInterp_normal, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, layerCopyValue_normal},
+ layerValidate_normal, NULL, NULL, NULL, NULL, NULL, layerCopyValue_normal},
/* 9: CD_FACEMAP */
{sizeof(int), "", 0, NULL, NULL, NULL, NULL, NULL, layerDefault_fmap, NULL},
/* 10: CD_PROP_FLT */
- {sizeof(MFloatProperty), "MFloatProperty", 1, N_("Float"), layerCopy_propFloat, NULL, NULL, NULL},
+ {sizeof(MFloatProperty), "MFloatProperty", 1, N_("Float"), layerCopy_propFloat, NULL, NULL, NULL, NULL,
+ layerValidate_propFloat},
/* 11: CD_PROP_INT */
{sizeof(MIntProperty), "MIntProperty", 1, N_("Int"), layerCopy_propInt, NULL, NULL, NULL},
/* 12: CD_PROP_STR */
@@ -1221,18 +1283,18 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
{sizeof(int), "", 0, NULL, NULL, NULL, NULL, NULL, NULL},
/* 16: CD_MLOOPUV */
{sizeof(MLoopUV), "MLoopUV", 1, N_("UVMap"), NULL, NULL, layerInterp_mloopuv, NULL, NULL,
- layerEqual_mloopuv, layerMultiply_mloopuv, layerInitMinMax_mloopuv,
+ layerValidate_mloopuv, layerEqual_mloopuv, layerMultiply_mloopuv, layerInitMinMax_mloopuv,
layerAdd_mloopuv, layerDoMinMax_mloopuv, layerCopyValue_mloopuv, NULL, NULL, NULL, layerMaxNum_tface},
/* 17: CD_MLOOPCOL */
{sizeof(MLoopCol), "MLoopCol", 1, N_("Col"), NULL, NULL, layerInterp_mloopcol, NULL,
- layerDefault_mloopcol, layerEqual_mloopcol, layerMultiply_mloopcol, layerInitMinMax_mloopcol,
+ layerDefault_mloopcol, NULL, layerEqual_mloopcol, layerMultiply_mloopcol, layerInitMinMax_mloopcol,
layerAdd_mloopcol, layerDoMinMax_mloopcol, layerCopyValue_mloopcol, NULL, NULL, NULL, layerMaxNum_mloopcol},
/* 18: CD_TANGENT */
{sizeof(float) * 4 * 4, "", 0, N_("Tangent"), NULL, NULL, NULL, NULL, NULL},
/* 19: CD_MDISPS */
{sizeof(MDisps), "MDisps", 1, NULL, layerCopy_mdisps,
layerFree_mdisps, NULL, layerSwap_mdisps, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL,
layerRead_mdisps, layerWrite_mdisps, layerFilesize_mdisps},
/* 20: CD_PREVIEW_MCOL */
{sizeof(MCol) * 4, "MCol", 4, N_("PreviewCol"), NULL, NULL, layerInterp_mcol,
@@ -1261,12 +1323,12 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
/* 30: CD_CREASE */
{sizeof(float), "", 0, N_("SubSurfCrease"), NULL, NULL, layerInterp_bweight},
/* 31: CD_ORIGSPACE_MLOOP */
- {sizeof(OrigSpaceLoop), "OrigSpaceLoop", 1, N_("OS Loop"), NULL, NULL, layerInterp_mloop_origspace, NULL, NULL,
+ {sizeof(OrigSpaceLoop), "OrigSpaceLoop", 1, N_("OS Loop"), NULL, NULL, layerInterp_mloop_origspace, NULL, NULL, NULL,
layerEqual_mloop_origspace, layerMultiply_mloop_origspace, layerInitMinMax_mloop_origspace,
layerAdd_mloop_origspace, layerDoMinMax_mloop_origspace, layerCopyValue_mloop_origspace},
/* 32: CD_PREVIEW_MLOOPCOL */
{sizeof(MLoopCol), "MLoopCol", 1, N_("PreviewLoopCol"), NULL, NULL, layerInterp_mloopcol, NULL,
- layerDefault_mloopcol, layerEqual_mloopcol, layerMultiply_mloopcol, layerInitMinMax_mloopcol,
+ layerDefault_mloopcol, NULL, layerEqual_mloopcol, layerMultiply_mloopcol, layerInitMinMax_mloopcol,
layerAdd_mloopcol, layerDoMinMax_mloopcol, layerCopyValue_mloopcol},
/* 33: CD_BM_ELEM_PYPTR */
{sizeof(void *), "", 1, NULL, layerCopy_bmesh_elem_py_ptr,
@@ -3509,6 +3571,22 @@ bool CustomData_verify_versions(struct CustomData *data, int index)
return keeplayer;
}
+/**
+ * Validate and fix data of \a layer, if possible (needs relevant callback in layer's type to be defined).
+ *
+ * \return True if some errors were found.
+ */
+bool CustomData_layer_validate(CustomDataLayer *layer, const uint totitems, const bool do_fixes)
+{
+ const LayerTypeInfo *typeInfo = layerType_getInfo(layer->type);
+
+ if (typeInfo->validate != NULL) {
+ return typeInfo->validate(layer->data, totitems, do_fixes);
+ }
+
+ return false;
+}
+
/****************************** External Files *******************************/
static void customdata_external_filename(char filename[FILE_MAX], ID *id, CustomDataExternal *external)