Fix #24388: multires base mesh
- MDisp should be re-allocated if face changed amount of vertices - Allocate disps array in layerSwap_mdisps to prevent loosing all highres data
This commit is contained in:
@@ -37,6 +37,8 @@ struct Multires;
|
||||
struct MultiresModifierData;
|
||||
struct ModifierData;
|
||||
struct Object;
|
||||
struct Scene;
|
||||
struct MDisps;
|
||||
|
||||
void multires_mark_as_modified(struct Object *ob);
|
||||
|
||||
@@ -74,5 +76,10 @@ void multires_load_old_250(struct Mesh *);
|
||||
void multiresModifier_scale_disp(struct Scene *scene, struct Object *ob);
|
||||
void multiresModifier_prepare_join(struct Scene *scene, struct Object *ob, struct Object *to_ob);
|
||||
|
||||
int multires_mdisp_corners(struct MDisps *s);
|
||||
|
||||
/* update multires data after topology changing */
|
||||
void multires_topology_changed(struct Object *ob);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_main.h"
|
||||
#include "BKE_utildefines.h"
|
||||
#include "BKE_multires.h"
|
||||
|
||||
/* number of layers to add when growing a CustomData object */
|
||||
#define CUSTOMDATA_GROW 5
|
||||
@@ -441,19 +442,6 @@ static void mdisps_bilinear(float out[3], float (*disps)[3], int st, float u, fl
|
||||
}
|
||||
#endif
|
||||
|
||||
static int mdisp_corners(MDisps *s)
|
||||
{
|
||||
int lvl= 13;
|
||||
|
||||
while(lvl > 0) {
|
||||
int side = (1 << (lvl-1)) + 1;
|
||||
if ((s->totdisp % (side*side)) == 0) return s->totdisp / (side*side);
|
||||
lvl--;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void layerSwap_mdisps(void *data, const int *ci)
|
||||
{
|
||||
MDisps *s = data;
|
||||
@@ -462,7 +450,7 @@ static void layerSwap_mdisps(void *data, const int *ci)
|
||||
|
||||
if(s->disps) {
|
||||
int nverts= (ci[1] == 3) ? 4 : 3; /* silly way to know vertex count of face */
|
||||
corners= mdisp_corners(s);
|
||||
corners= multires_mdisp_corners(s);
|
||||
cornersize= s->totdisp/corners;
|
||||
|
||||
if(corners!=nverts) {
|
||||
@@ -470,8 +458,8 @@ static void layerSwap_mdisps(void *data, const int *ci)
|
||||
if it happened, just forgot displacement */
|
||||
|
||||
MEM_freeN(s->disps);
|
||||
s->disps= NULL;
|
||||
s->totdisp= 0; /* flag to update totdisp */
|
||||
s->totdisp= (s->totdisp/corners)*nverts;
|
||||
s->disps= MEM_callocN(s->totdisp*sizeof(float)*3, "mdisp swap");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -304,34 +304,46 @@ int multiresModifier_reshapeFromDeformMod(Scene *scene, MultiresModifierData *mm
|
||||
return result;
|
||||
}
|
||||
|
||||
/* reset the multires levels to match the number of mdisps */
|
||||
static int get_levels_from_disps(Object *ob)
|
||||
{
|
||||
Mesh *me = ob->data;
|
||||
MDisps *mdisp;
|
||||
int i, totlvl= 0;
|
||||
|
||||
mdisp = CustomData_get_layer(&me->fdata, CD_MDISPS);
|
||||
|
||||
for(i = 0; i < me->totface; ++i, ++mdisp) {
|
||||
int S = me->mface[i].v4 ? 4 : 3;
|
||||
|
||||
if(mdisp->totdisp == 0) continue;
|
||||
|
||||
while(1) {
|
||||
int side = (1 << (totlvl-1)) + 1;
|
||||
int lvl_totdisp = side*side*S;
|
||||
if(mdisp->totdisp == lvl_totdisp)
|
||||
break;
|
||||
else if(mdisp->totdisp < lvl_totdisp)
|
||||
--totlvl;
|
||||
else
|
||||
++totlvl;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return totlvl;
|
||||
}
|
||||
|
||||
/* reset the multires levels to match the number of mdisps */
|
||||
void multiresModifier_set_levels_from_disps(MultiresModifierData *mmd, Object *ob)
|
||||
{
|
||||
Mesh *me = ob->data;
|
||||
MDisps *mdisp;
|
||||
int i;
|
||||
|
||||
mdisp = CustomData_get_layer(&me->fdata, CD_MDISPS);
|
||||
|
||||
if(mdisp) {
|
||||
for(i = 0; i < me->totface; ++i, ++mdisp) {
|
||||
int S = me->mface[i].v4 ? 4 : 3;
|
||||
|
||||
if(mdisp->totdisp == 0) continue;
|
||||
|
||||
while(1) {
|
||||
int side = (1 << (mmd->totlvl-1)) + 1;
|
||||
int lvl_totdisp = side*side*S;
|
||||
if(mdisp->totdisp == lvl_totdisp)
|
||||
break;
|
||||
else if(mdisp->totdisp < lvl_totdisp)
|
||||
--mmd->totlvl;
|
||||
else
|
||||
++mmd->totlvl;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
mmd->totlvl = get_levels_from_disps(ob);
|
||||
mmd->lvl = MIN2(mmd->sculptlvl, mmd->totlvl);
|
||||
mmd->sculptlvl = MIN2(mmd->sculptlvl, mmd->totlvl);
|
||||
mmd->renderlvl = MIN2(mmd->renderlvl, mmd->totlvl);
|
||||
@@ -1555,6 +1567,19 @@ void multires_apply_smat(Scene *scene, Object *ob, float smat[3][3])
|
||||
subdm->release(subdm);
|
||||
}
|
||||
|
||||
int multires_mdisp_corners(MDisps *s)
|
||||
{
|
||||
int lvl= 13;
|
||||
|
||||
while(lvl > 0) {
|
||||
int side = (1 << (lvl-1)) + 1;
|
||||
if ((s->totdisp % (side*side)) == 0) return s->totdisp / (side*side);
|
||||
lvl--;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void multiresModifier_scale_disp(Scene *scene, Object *ob)
|
||||
{
|
||||
float smat[3][3];
|
||||
@@ -1578,3 +1603,27 @@ void multiresModifier_prepare_join(Scene *scene, Object *ob, Object *to_ob)
|
||||
|
||||
multires_apply_smat(scene, ob, mat);
|
||||
}
|
||||
|
||||
/* update multires data after topology changing */
|
||||
void multires_topology_changed(Object *ob)
|
||||
{
|
||||
Mesh *me= (Mesh*)ob->data;
|
||||
MDisps *mdisp= CustomData_get_layer(&me->fdata, CD_MDISPS);
|
||||
int i;
|
||||
|
||||
if(!mdisp) return;
|
||||
|
||||
for(i = 0; i < me->totface; i++, mdisp++) {
|
||||
int corners= multires_mdisp_corners(mdisp);
|
||||
int nvert= me->mface[i].v4 ? 4 : 3;
|
||||
|
||||
if(corners!=nvert) {
|
||||
mdisp->totdisp= (mdisp->totdisp/corners)*nvert;
|
||||
|
||||
if(mdisp->disps)
|
||||
MEM_freeN(mdisp->disps);
|
||||
|
||||
mdisp->disps= MEM_callocN(mdisp->totdisp*sizeof(float)*3, "mdisp topology");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,6 +54,7 @@
|
||||
#include "BKE_mesh.h"
|
||||
#include "BKE_paint.h"
|
||||
#include "BKE_report.h"
|
||||
#include "BKE_multires.h"
|
||||
|
||||
#include "ED_mesh.h"
|
||||
#include "ED_object.h"
|
||||
@@ -1306,6 +1307,9 @@ void load_editMesh(Scene *scene, Object *ob)
|
||||
}
|
||||
|
||||
mesh_calc_normals(me->mvert, me->totvert, me->mface, me->totface, NULL);
|
||||
|
||||
/* topology could be changed, ensure mdisps are ok */
|
||||
multires_topology_changed(ob);
|
||||
}
|
||||
|
||||
void remake_editMesh(Scene *scene, Object *ob)
|
||||
|
||||
Reference in New Issue
Block a user