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>2015-05-07 16:16:10 +0300
committerBastien Montagne <montagne29@wanadoo.fr>2015-05-07 16:19:32 +0300
commitaa3fc89257f839260e7577881f399011a709badf (patch)
tree2f804ffb355dc2c5659697a841c68f9da5d60fa4
parent15fd37fab23ad906942726162a677d9254a94be4 (diff)
Fix T44611: 'make_links_data' modifiers would fail and crash with multires modifier.
Since it was not ensuring dest has valid mdisp data matching new multires modifier subdiv level... Also, fixed a bug in `multires_subdivide()`, which would crash when trying to increase from level 0 (aka no subdiv) to > 1 (wrong check, trying to interpolate when it should not). And added a few sanity checks.
-rw-r--r--source/blender/blenkernel/BKE_multires.h5
-rw-r--r--source/blender/blenkernel/intern/multires.c44
-rw-r--r--source/blender/blenkernel/intern/object.c7
3 files changed, 39 insertions, 17 deletions
diff --git a/source/blender/blenkernel/BKE_multires.h b/source/blender/blenkernel/BKE_multires.h
index 627b8d6fdbd..a8242a529f3 100644
--- a/source/blender/blenkernel/BKE_multires.h
+++ b/source/blender/blenkernel/BKE_multires.h
@@ -79,8 +79,9 @@ struct DerivedMesh *get_multires_dm(struct Scene *scene, struct MultiresModifier
struct Object *ob);
void multiresModifier_del_levels(struct MultiresModifierData *, struct Object *, int direction);
void multiresModifier_base_apply(struct MultiresModifierData *mmd, struct Object *ob);
-void multiresModifier_subdivide(struct MultiresModifierData *mmd, struct Object *ob,
- int updateblock, int simple);
+void multiresModifier_subdivide(struct MultiresModifierData *mmd, struct Object *ob, int updateblock, int simple);
+void multiresModifier_sync_levels_ex(
+ struct Object *ob_dst, struct MultiresModifierData *mmd_src, struct MultiresModifierData *mmd_dst);
int multiresModifier_reshape(struct Scene *scene, struct MultiresModifierData *mmd,
struct Object *dst, struct Object *src);
int multiresModifier_reshapeFromDM(struct Scene *scene, struct MultiresModifierData *mmd,
diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c
index e4bf05c2b5b..0c984c38b8e 100644
--- a/source/blender/blenkernel/intern/multires.c
+++ b/source/blender/blenkernel/intern/multires.c
@@ -882,18 +882,20 @@ static void multires_subdivide(MultiresModifierData *mmd, Object *ob, int totlvl
{
Mesh *me = ob->data;
MDisps *mdisps;
- int lvl = mmd->totlvl;
+ const int lvl = mmd->totlvl;
if ((totlvl > multires_max_levels) || (me->totpoly == 0))
return;
+ BLI_assert(totlvl > lvl);
+
multires_force_update(ob);
mdisps = CustomData_get_layer(&me->ldata, CD_MDISPS);
if (!mdisps)
mdisps = multires_mdisps_initialize_hidden(me, totlvl);
- if (mdisps->disps && !updateblock && totlvl > 1) {
+ if (mdisps->disps && !updateblock && lvl != 0) {
/* upsample */
DerivedMesh *lowdm, *cddm, *highdm;
CCGElem **highGridData, **lowGridData, **subGridData;
@@ -910,6 +912,7 @@ static void multires_subdivide(MultiresModifierData *mmd, Object *ob, int totlvl
/* create multires DM from original mesh at low level */
lowdm = multires_dm_create_local(ob, cddm, lvl, lvl, simple, has_mask);
+ BLI_assert(lowdm != cddm);
cddm->release(cddm);
/* copy subsurf grids and replace them with low displaced grids */
@@ -2137,27 +2140,38 @@ void multires_load_old(Object *ob, Mesh *me)
me->mr = NULL;
}
-/* If 'ob' and 'to_ob' both have multires modifiers, synchronize them
- * such that 'ob' has the same total number of levels as 'to_ob'. */
-static void multires_sync_levels(Scene *scene, Object *ob, Object *to_ob)
+/* If 'ob_src' and 'ob_dst' both have multires modifiers, synchronize them
+ * such that 'ob_dst' has the same total number of levels as 'ob_src'. */
+void multiresModifier_sync_levels_ex(Object *ob_dst, MultiresModifierData *mmd_src, MultiresModifierData *mmd_dst)
{
- MultiresModifierData *mmd = get_multires_modifier(scene, ob, 1);
- MultiresModifierData *to_mmd = get_multires_modifier(scene, to_ob, 1);
+ if (mmd_src->totlvl == mmd_dst->totlvl) {
+ return;
+ }
+
+ if (mmd_src->totlvl > mmd_dst->totlvl) {
+ multires_subdivide(mmd_dst, ob_dst, mmd_src->totlvl, false, mmd_dst->simple);
+ }
+ else {
+ multires_del_higher(mmd_dst, ob_dst, mmd_src->totlvl);
+ }
+}
- if (!mmd) {
+static void multires_sync_levels(Scene *scene, Object *ob_src, Object *ob_dst)
+{
+ MultiresModifierData *mmd_src = get_multires_modifier(scene, ob_src, true);
+ MultiresModifierData *mmd_dst = get_multires_modifier(scene, ob_dst, true);
+
+ if (!mmd_src) {
/* object could have MDISP even when there is no multires modifier
* this could lead to troubles due to i've got no idea how mdisp could be
* upsampled correct without modifier data.
* just remove mdisps if no multires present (nazgul) */
- multires_customdata_delete(ob->data);
+ multires_customdata_delete(ob_src->data);
}
- if (mmd && to_mmd) {
- if (mmd->totlvl > to_mmd->totlvl)
- multires_del_higher(mmd, ob, to_mmd->totlvl);
- else
- multires_subdivide(mmd, ob, to_mmd->totlvl, 0, mmd->simple);
+ if (mmd_src && mmd_dst) {
+ multiresModifier_sync_levels_ex(ob_dst, mmd_src, mmd_dst);
}
}
@@ -2276,7 +2290,7 @@ void multiresModifier_scale_disp(Scene *scene, Object *ob)
void multiresModifier_prepare_join(Scene *scene, Object *ob, Object *to_ob)
{
float smat[3][3], tmat[3][3], mat[3][3];
- multires_sync_levels(scene, ob, to_ob);
+ multires_sync_levels(scene, to_ob, ob);
/* construct scale matrix for displacement */
BKE_object_scale_to_mat3(to_ob, tmat);
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index bd0b7275174..5b29187e7cd 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -96,6 +96,7 @@
#include "BKE_editmesh.h"
#include "BKE_mball.h"
#include "BKE_modifier.h"
+#include "BKE_multires.h"
#include "BKE_node.h"
#include "BKE_object.h"
#include "BKE_paint.h"
@@ -280,6 +281,12 @@ void BKE_object_link_modifiers(struct Object *ob_dst, struct Object *ob_src)
nmd = modifier_new(md->type);
BLI_strncpy(nmd->name, md->name, sizeof(nmd->name));
+
+ if (md->type == eModifierType_Multires) {
+ /* Has to be done after mod creation, but *before* we actually copy its settings! */
+ multiresModifier_sync_levels_ex(ob_dst, (MultiresModifierData *)md, (MultiresModifierData *)nmd);
+ }
+
modifier_copyData(md, nmd);
BLI_addtail(&ob_dst->modifiers, nmd);
modifier_unique_name(&ob_dst->modifiers, nmd);