diff options
author | Sergey Sharybin <sergey.vfx@gmail.com> | 2020-03-13 18:13:32 +0300 |
---|---|---|
committer | Sergey Sharybin <sergey.vfx@gmail.com> | 2020-03-13 18:15:31 +0300 |
commit | de30fda04e8d84a173e929a0f3d9d8c71bcc4bbf (patch) | |
tree | 1de36aed8d03074b2066fc1c0486bc3324d93611 /source/blender/blenkernel/intern/multires.c | |
parent | 67704cb8aaf70457692eb31328b4ed2bc6c41b62 (diff) |
Fix T74686: Loading btx file in multires modifier is not working
Was happening when object does not have CD_MDISPS allocated yet.
Need to make sure totdisp and level is specified on CD_MDISPS data
prior to loading (as the load expects them to be properly set).
Diffstat (limited to 'source/blender/blenkernel/intern/multires.c')
-rw-r--r-- | source/blender/blenkernel/intern/multires.c | 48 |
1 files changed, 43 insertions, 5 deletions
diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c index 70061c155d3..4e97d0fc05c 100644 --- a/source/blender/blenkernel/intern/multires.c +++ b/source/blender/blenkernel/intern/multires.c @@ -647,7 +647,7 @@ static void multires_del_higher(MultiresModifierData *mmd, Object *ob, int lvl) GridPaintMask *gpm; multires_set_tot_mdisps(me, mmd->totlvl); - CustomData_external_read(&me->ldata, &me->id, CD_MASK_MDISPS, me->totloop); + multiresModifier_ensure_external_read(me, mmd); mdisps = CustomData_get_layer(&me->ldata, CD_MDISPS); gpm = CustomData_get_layer(&me->ldata, CD_GRID_PAINT_MASK); @@ -713,7 +713,7 @@ void multiresModifier_del_levels(MultiresModifierData *mmd, MDisps *mdisps; multires_set_tot_mdisps(me, mmd->totlvl); - CustomData_external_read(&me->ldata, &me->id, CD_MASK_MDISPS, me->totloop); + multiresModifier_ensure_external_read(me, mmd); mdisps = CustomData_get_layer(&me->ldata, CD_MDISPS); multires_force_sculpt_rebuild(ob); @@ -1144,7 +1144,7 @@ void multires_modifier_update_mdisps(struct DerivedMesh *dm, Scene *scene) me = ccgdm->multires.ob->data; mmd = ccgdm->multires.mmd; multires_set_tot_mdisps(me, mmd->totlvl); - CustomData_external_read(&me->ldata, &me->id, CD_MASK_MDISPS, me->totloop); + multiresModifier_ensure_external_read(me, mmd); mdisps = CustomData_get_layer(&me->ldata, CD_MDISPS); if (mdisps) { @@ -1372,7 +1372,7 @@ DerivedMesh *multires_make_derived_from_derived( } multires_set_tot_mdisps(me, mmd->totlvl); - CustomData_external_read(&me->ldata, &me->id, CD_MASK_MDISPS, me->totloop); + multiresModifier_ensure_external_read(me, mmd); /*run displacement*/ multiresModifier_disp_run(result, ob->data, dm, APPLY_DISPLACEMENTS, subGridData, mmd->totlvl); @@ -2224,7 +2224,7 @@ static void multires_apply_smat(struct Depsgraph *UNUSED(depsgraph), } /* Make sure layer present. */ Mesh *mesh = (Mesh *)object->data; - CustomData_external_read(&mesh->ldata, &mesh->id, CD_MASK_MDISPS, mesh->totloop); + multiresModifier_ensure_external_read(mesh, mmd); if (!CustomData_get_layer(&mesh->ldata, CD_MDISPS)) { return; } @@ -2318,6 +2318,44 @@ void multires_topology_changed(Mesh *me) } } +/* Makes sure data from an external file is fully read. + * + * Since the multires data files only contain displacement vectors without knowledge about + * subdivision level some extra work is needed. Namely make is to all displacement grids have + * proper level and number of displacement vectors set. */ +void multires_ensure_external_read(struct Mesh *mesh, int top_level) +{ + if (!CustomData_external_test(&mesh->ldata, CD_MDISPS)) { + return; + } + + MDisps *mdisps = CustomData_get_layer(&mesh->ldata, CD_MDISPS); + if (mdisps == NULL) { + mdisps = CustomData_add_layer(&mesh->ldata, CD_MDISPS, CD_DEFAULT, NULL, mesh->totloop); + } + + const int totloop = mesh->totloop; + + for (int i = 0; i < totloop; ++i) { + if (mdisps[i].level != top_level) { + MEM_SAFE_FREE(mdisps[i].disps); + } + + /* NOTE: CustomData_external_read will take care of allocation of displacement vectors if + * they are missing. */ + + const int totdisp = multires_grid_tot[top_level]; + mdisps[i].totdisp = totdisp; + mdisps[i].level = top_level; + } + + CustomData_external_read(&mesh->ldata, &mesh->id, CD_MASK_MDISPS, mesh->totloop); +} +void multiresModifier_ensure_external_read(struct Mesh *mesh, const MultiresModifierData *mmd) +{ + multires_ensure_external_read(mesh, mmd->totlvl); +} + /***************** Multires interpolation stuff *****************/ /* Find per-corner coordinate with given per-face UV coord */ |