Multires: Remove legacy compatibility code
It was rather a huge chunk of code, which started to become more harder to maintain with the transition to OpenSubdiv based implementation. Because of this transition, the compatibility was also rather on a poor side. Remove compatibility support for pre-2.50.9 multires. Ref T77107 Reviewed By: brecht, mont29 Differential Revision: https://developer.blender.org/D9238
This commit is contained in:
parent
f68c3d557a
commit
d11e357824
Notes:
blender-bot
2024-05-08 11:36:44 +02:00
Referenced by issue #77107, Multires: Remove pre-2.5 compatibility code
|
@ -36,7 +36,6 @@ struct DerivedMesh;
|
|||
struct MDisps;
|
||||
struct Mesh;
|
||||
struct ModifierData;
|
||||
struct Multires;
|
||||
struct MultiresModifierData;
|
||||
struct Object;
|
||||
struct Scene;
|
||||
|
@ -125,11 +124,6 @@ void multiresModifier_sync_levels_ex(struct Object *ob_dst,
|
|||
|
||||
void multires_stitch_grids(struct Object *);
|
||||
|
||||
/* Related to the old multires */
|
||||
void multires_free(struct Multires *mr);
|
||||
void multires_load_old(struct Object *ob, struct Mesh *me);
|
||||
void multires_load_old_250(struct Mesh *);
|
||||
|
||||
void multiresModifier_scale_disp(struct Depsgraph *depsgraph,
|
||||
struct Scene *scene,
|
||||
struct Object *ob);
|
||||
|
|
|
@ -275,50 +275,6 @@ static void mesh_blend_read_data(BlendDataReader *reader, ID *id)
|
|||
mesh->totselect = 0;
|
||||
}
|
||||
|
||||
/* Multires data */
|
||||
BLO_read_data_address(reader, &mesh->mr);
|
||||
if (mesh->mr) {
|
||||
BLO_read_list(reader, &mesh->mr->levels);
|
||||
MultiresLevel *lvl = mesh->mr->levels.first;
|
||||
|
||||
CustomData_blend_read(reader, &mesh->mr->vdata, lvl->totvert);
|
||||
BKE_defvert_blend_read(
|
||||
reader, lvl->totvert, CustomData_get(&mesh->mr->vdata, 0, CD_MDEFORMVERT));
|
||||
CustomData_blend_read(reader, &mesh->mr->fdata, lvl->totface);
|
||||
|
||||
BLO_read_data_address(reader, &mesh->mr->edge_flags);
|
||||
BLO_read_data_address(reader, &mesh->mr->edge_creases);
|
||||
|
||||
BLO_read_data_address(reader, &mesh->mr->verts);
|
||||
|
||||
/* If mesh has the same number of vertices as the
|
||||
* highest multires level, load the current mesh verts
|
||||
* into multires and discard the old data. Needed
|
||||
* because some saved files either do not have a verts
|
||||
* array, or the verts array contains out-of-date
|
||||
* data. */
|
||||
if (mesh->totvert == ((MultiresLevel *)mesh->mr->levels.last)->totvert) {
|
||||
if (mesh->mr->verts) {
|
||||
MEM_freeN(mesh->mr->verts);
|
||||
}
|
||||
mesh->mr->verts = MEM_dupallocN(mesh->mvert);
|
||||
}
|
||||
|
||||
for (; lvl; lvl = lvl->next) {
|
||||
BLO_read_data_address(reader, &lvl->verts);
|
||||
BLO_read_data_address(reader, &lvl->faces);
|
||||
BLO_read_data_address(reader, &lvl->edges);
|
||||
BLO_read_data_address(reader, &lvl->colfaces);
|
||||
}
|
||||
}
|
||||
|
||||
/* if multires is present but has no valid vertex data,
|
||||
* there's no way to recover it; silently remove multires */
|
||||
if (mesh->mr && !mesh->mr->verts) {
|
||||
multires_free(mesh->mr);
|
||||
mesh->mr = NULL;
|
||||
}
|
||||
|
||||
if ((BLO_read_requires_endian_switch(reader)) && mesh->tface) {
|
||||
TFace *tf = mesh->tface;
|
||||
for (int i = 0; i < mesh->totface; i++, tf++) {
|
||||
|
|
|
@ -1449,9 +1449,6 @@ DerivedMesh *multires_make_derived_from_derived(
|
|||
return result;
|
||||
}
|
||||
|
||||
/**** Old Multires code ****
|
||||
***************************/
|
||||
|
||||
/* Adapted from sculptmode.c */
|
||||
void old_mdisps_bilinear(float out[3], float (*disps)[3], const int st, float u, float v)
|
||||
{
|
||||
|
@ -1506,723 +1503,6 @@ void old_mdisps_bilinear(float out[3], float (*disps)[3], const int st, float u,
|
|||
add_v3_v3v3(out, d2[0], d2[1]);
|
||||
}
|
||||
|
||||
static void old_mdisps_rotate(
|
||||
int S, int UNUSED(newside), int oldside, int x, int y, float *u, float *v)
|
||||
{
|
||||
float offset = oldside * 0.5f - 0.5f;
|
||||
|
||||
if (S == 1) {
|
||||
*u = offset + x;
|
||||
*v = offset - y;
|
||||
}
|
||||
if (S == 2) {
|
||||
*u = offset + y;
|
||||
*v = offset + x;
|
||||
}
|
||||
if (S == 3) {
|
||||
*u = offset - x;
|
||||
*v = offset + y;
|
||||
}
|
||||
if (S == 0) {
|
||||
*u = offset - y;
|
||||
*v = offset - x;
|
||||
}
|
||||
}
|
||||
|
||||
static void old_mdisps_convert(MFace *mface, MDisps *mdisp)
|
||||
{
|
||||
int newlvl = log(sqrt(mdisp->totdisp) - 1) / M_LN2;
|
||||
int oldlvl = newlvl + 1;
|
||||
int oldside = multires_side_tot[oldlvl];
|
||||
int newside = multires_side_tot[newlvl];
|
||||
int nvert = (mface->v4) ? 4 : 3;
|
||||
int newtotdisp = multires_grid_tot[newlvl] * nvert;
|
||||
int x, y, S;
|
||||
float(*disps)[3], (*out)[3], u = 0.0f, v = 0.0f; /* Quite gcc barking. */
|
||||
|
||||
disps = MEM_calloc_arrayN(newtotdisp, sizeof(float[3]), "multires disps");
|
||||
|
||||
out = disps;
|
||||
for (S = 0; S < nvert; S++) {
|
||||
for (y = 0; y < newside; y++) {
|
||||
for (x = 0; x < newside; x++, out++) {
|
||||
old_mdisps_rotate(S, newside, oldside, x, y, &u, &v);
|
||||
old_mdisps_bilinear(*out, mdisp->disps, oldside, u, v);
|
||||
|
||||
if (S == 1) {
|
||||
(*out)[1] = -(*out)[1];
|
||||
}
|
||||
else if (S == 2) {
|
||||
SWAP(float, (*out)[0], (*out)[1]);
|
||||
}
|
||||
else if (S == 3) {
|
||||
(*out)[0] = -(*out)[0];
|
||||
}
|
||||
else if (S == 0) {
|
||||
SWAP(float, (*out)[0], (*out)[1]);
|
||||
(*out)[0] = -(*out)[0];
|
||||
(*out)[1] = -(*out)[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MEM_freeN(mdisp->disps);
|
||||
|
||||
mdisp->totdisp = newtotdisp;
|
||||
mdisp->level = newlvl;
|
||||
mdisp->disps = disps;
|
||||
}
|
||||
|
||||
void multires_load_old_250(Mesh *me)
|
||||
{
|
||||
MDisps *mdisps, *mdisps2;
|
||||
MFace *mf;
|
||||
int i, j, k;
|
||||
|
||||
mdisps = CustomData_get_layer(&me->fdata, CD_MDISPS);
|
||||
|
||||
if (mdisps) {
|
||||
for (i = 0; i < me->totface; i++) {
|
||||
if (mdisps[i].totdisp) {
|
||||
old_mdisps_convert(&me->mface[i], &mdisps[i]);
|
||||
}
|
||||
}
|
||||
|
||||
CustomData_add_layer(&me->ldata, CD_MDISPS, CD_CALLOC, NULL, me->totloop);
|
||||
mdisps2 = CustomData_get_layer(&me->ldata, CD_MDISPS);
|
||||
|
||||
k = 0;
|
||||
mf = me->mface;
|
||||
for (i = 0; i < me->totface; i++, mf++) {
|
||||
int nvert = mf->v4 ? 4 : 3;
|
||||
int totdisp = mdisps[i].totdisp / nvert;
|
||||
|
||||
for (j = 0; j < nvert; j++, k++) {
|
||||
mdisps2[k].disps = MEM_calloc_arrayN(
|
||||
totdisp, sizeof(float[3]), "multires disp in conversion");
|
||||
mdisps2[k].totdisp = totdisp;
|
||||
mdisps2[k].level = mdisps[i].level;
|
||||
memcpy(mdisps2[k].disps, mdisps[i].disps + totdisp * j, totdisp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Does not actually free lvl itself */
|
||||
static void multires_free_level(MultiresLevel *lvl)
|
||||
{
|
||||
if (lvl) {
|
||||
if (lvl->faces) {
|
||||
MEM_freeN(lvl->faces);
|
||||
}
|
||||
if (lvl->edges) {
|
||||
MEM_freeN(lvl->edges);
|
||||
}
|
||||
if (lvl->colfaces) {
|
||||
MEM_freeN(lvl->colfaces);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void multires_free(Multires *mr)
|
||||
{
|
||||
if (mr) {
|
||||
MultiresLevel *lvl = mr->levels.first;
|
||||
|
||||
/* Free the first-level data */
|
||||
if (lvl) {
|
||||
CustomData_free(&mr->vdata, lvl->totvert);
|
||||
CustomData_free(&mr->fdata, lvl->totface);
|
||||
if (mr->edge_flags) {
|
||||
MEM_freeN(mr->edge_flags);
|
||||
}
|
||||
if (mr->edge_creases) {
|
||||
MEM_freeN(mr->edge_creases);
|
||||
}
|
||||
}
|
||||
|
||||
while (lvl) {
|
||||
multires_free_level(lvl);
|
||||
lvl = lvl->next;
|
||||
}
|
||||
|
||||
/* mr->verts may be NULL when loading old files,
|
||||
* see direct_link_mesh() in readfile.c, and T43560. */
|
||||
MEM_SAFE_FREE(mr->verts);
|
||||
|
||||
BLI_freelistN(&mr->levels);
|
||||
|
||||
MEM_freeN(mr);
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct IndexNode {
|
||||
struct IndexNode *next, *prev;
|
||||
int index;
|
||||
} IndexNode;
|
||||
|
||||
static void create_old_vert_face_map(ListBase **map,
|
||||
IndexNode **mem,
|
||||
const MultiresFace *mface,
|
||||
const int totvert,
|
||||
const int totface)
|
||||
{
|
||||
int i, j;
|
||||
IndexNode *node = NULL;
|
||||
|
||||
(*map) = MEM_calloc_arrayN(totvert, sizeof(ListBase), "vert face map");
|
||||
(*mem) = MEM_calloc_arrayN(totface, sizeof(IndexNode[4]), "vert face map mem");
|
||||
node = *mem;
|
||||
|
||||
/* Find the users */
|
||||
for (i = 0; i < totface; i++) {
|
||||
for (j = 0; j < (mface[i].v[3] ? 4 : 3); j++, node++) {
|
||||
node->index = i;
|
||||
BLI_addtail(&(*map)[mface[i].v[j]], node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void create_old_vert_edge_map(ListBase **map,
|
||||
IndexNode **mem,
|
||||
const MultiresEdge *medge,
|
||||
const int totvert,
|
||||
const int totedge)
|
||||
{
|
||||
int i, j;
|
||||
IndexNode *node = NULL;
|
||||
|
||||
(*map) = MEM_calloc_arrayN(totvert, sizeof(ListBase), "vert edge map");
|
||||
(*mem) = MEM_calloc_arrayN(totedge, sizeof(IndexNode[2]), "vert edge map mem");
|
||||
node = *mem;
|
||||
|
||||
/* Find the users */
|
||||
for (i = 0; i < totedge; i++) {
|
||||
for (j = 0; j < 2; j++, node++) {
|
||||
node->index = i;
|
||||
BLI_addtail(&(*map)[medge[i].v[j]], node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static MultiresFace *find_old_face(
|
||||
ListBase *map, MultiresFace *faces, int v1, int v2, int v3, int v4)
|
||||
{
|
||||
IndexNode *n1;
|
||||
int v[4], i, j;
|
||||
|
||||
v[0] = v1;
|
||||
v[1] = v2;
|
||||
v[2] = v3;
|
||||
v[3] = v4;
|
||||
|
||||
for (n1 = map[v1].first; n1; n1 = n1->next) {
|
||||
int fnd[4] = {0, 0, 0, 0};
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
for (j = 0; j < 4; j++) {
|
||||
if (v[i] == faces[n1->index].v[j]) {
|
||||
fnd[i] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fnd[0] && fnd[1] && fnd[2] && fnd[3]) {
|
||||
return &faces[n1->index];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static MultiresEdge *find_old_edge(ListBase *map, MultiresEdge *edges, int v1, int v2)
|
||||
{
|
||||
IndexNode *n1, *n2;
|
||||
|
||||
for (n1 = map[v1].first; n1; n1 = n1->next) {
|
||||
for (n2 = map[v2].first; n2; n2 = n2->next) {
|
||||
if (n1->index == n2->index) {
|
||||
return &edges[n1->index];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void multires_load_old_edges(
|
||||
ListBase **emap, MultiresLevel *lvl, int *vvmap, int dst, int v1, int v2, int mov)
|
||||
{
|
||||
int emid = find_old_edge(emap[2], lvl->edges, v1, v2)->mid;
|
||||
vvmap[dst + mov] = emid;
|
||||
|
||||
if (lvl->next->next) {
|
||||
multires_load_old_edges(emap + 1, lvl->next, vvmap, dst + mov, v1, emid, mov / 2);
|
||||
multires_load_old_edges(emap + 1, lvl->next, vvmap, dst + mov, v2, emid, -mov / 2);
|
||||
}
|
||||
}
|
||||
|
||||
static void multires_load_old_faces(ListBase **fmap,
|
||||
ListBase **emap,
|
||||
MultiresLevel *lvl,
|
||||
int *vvmap,
|
||||
int dst,
|
||||
int v1,
|
||||
int v2,
|
||||
int v3,
|
||||
int v4,
|
||||
int st2,
|
||||
int st3)
|
||||
{
|
||||
int fmid;
|
||||
int emid13, emid14, emid23, emid24;
|
||||
|
||||
if (lvl && lvl->next) {
|
||||
fmid = find_old_face(fmap[1], lvl->faces, v1, v2, v3, v4)->mid;
|
||||
vvmap[dst] = fmid;
|
||||
|
||||
emid13 = find_old_edge(emap[1], lvl->edges, v1, v3)->mid;
|
||||
emid14 = find_old_edge(emap[1], lvl->edges, v1, v4)->mid;
|
||||
emid23 = find_old_edge(emap[1], lvl->edges, v2, v3)->mid;
|
||||
emid24 = find_old_edge(emap[1], lvl->edges, v2, v4)->mid;
|
||||
|
||||
multires_load_old_faces(fmap + 1,
|
||||
emap + 1,
|
||||
lvl->next,
|
||||
vvmap,
|
||||
dst + st2 * st3 + st3,
|
||||
fmid,
|
||||
v2,
|
||||
emid23,
|
||||
emid24,
|
||||
st2,
|
||||
st3 / 2);
|
||||
|
||||
multires_load_old_faces(fmap + 1,
|
||||
emap + 1,
|
||||
lvl->next,
|
||||
vvmap,
|
||||
dst - st2 * st3 + st3,
|
||||
emid14,
|
||||
emid24,
|
||||
fmid,
|
||||
v4,
|
||||
st2,
|
||||
st3 / 2);
|
||||
|
||||
multires_load_old_faces(fmap + 1,
|
||||
emap + 1,
|
||||
lvl->next,
|
||||
vvmap,
|
||||
dst + st2 * st3 - st3,
|
||||
emid13,
|
||||
emid23,
|
||||
v3,
|
||||
fmid,
|
||||
st2,
|
||||
st3 / 2);
|
||||
|
||||
multires_load_old_faces(fmap + 1,
|
||||
emap + 1,
|
||||
lvl->next,
|
||||
vvmap,
|
||||
dst - st2 * st3 - st3,
|
||||
v1,
|
||||
fmid,
|
||||
emid13,
|
||||
emid14,
|
||||
st2,
|
||||
st3 / 2);
|
||||
|
||||
if (lvl->next->next) {
|
||||
multires_load_old_edges(emap, lvl->next, vvmap, dst, emid24, fmid, st3);
|
||||
multires_load_old_edges(emap, lvl->next, vvmap, dst, emid13, fmid, -st3);
|
||||
multires_load_old_edges(emap, lvl->next, vvmap, dst, emid14, fmid, -st2 * st3);
|
||||
multires_load_old_edges(emap, lvl->next, vvmap, dst, emid23, fmid, st2 * st3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void multires_mvert_to_ss(DerivedMesh *dm, MVert *mvert)
|
||||
{
|
||||
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
|
||||
CCGSubSurf *ss = ccgdm->ss;
|
||||
CCGElem *vd;
|
||||
CCGKey key;
|
||||
int index;
|
||||
int totvert, totedge, totface;
|
||||
int gridSize = ccgSubSurf_getGridSize(ss);
|
||||
int edgeSize = ccgSubSurf_getEdgeSize(ss);
|
||||
int i = 0;
|
||||
|
||||
dm->getGridKey(dm, &key);
|
||||
|
||||
totface = ccgSubSurf_getNumFaces(ss);
|
||||
for (index = 0; index < totface; index++) {
|
||||
CCGFace *f = ccgdm->faceMap[index].face;
|
||||
int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f);
|
||||
|
||||
vd = ccgSubSurf_getFaceCenterData(f);
|
||||
copy_v3_v3(CCG_elem_co(&key, vd), mvert[i].co);
|
||||
i++;
|
||||
|
||||
for (S = 0; S < numVerts; S++) {
|
||||
for (x = 1; x < gridSize - 1; x++, i++) {
|
||||
vd = ccgSubSurf_getFaceGridEdgeData(ss, f, S, x);
|
||||
copy_v3_v3(CCG_elem_co(&key, vd), mvert[i].co);
|
||||
}
|
||||
}
|
||||
|
||||
for (S = 0; S < numVerts; S++) {
|
||||
for (y = 1; y < gridSize - 1; y++) {
|
||||
for (x = 1; x < gridSize - 1; x++, i++) {
|
||||
vd = ccgSubSurf_getFaceGridData(ss, f, S, x, y);
|
||||
copy_v3_v3(CCG_elem_co(&key, vd), mvert[i].co);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
totedge = ccgSubSurf_getNumEdges(ss);
|
||||
for (index = 0; index < totedge; index++) {
|
||||
CCGEdge *e = ccgdm->edgeMap[index].edge;
|
||||
int x;
|
||||
|
||||
for (x = 1; x < edgeSize - 1; x++, i++) {
|
||||
vd = ccgSubSurf_getEdgeData(ss, e, x);
|
||||
copy_v3_v3(CCG_elem_co(&key, vd), mvert[i].co);
|
||||
}
|
||||
}
|
||||
|
||||
totvert = ccgSubSurf_getNumVerts(ss);
|
||||
for (index = 0; index < totvert; index++) {
|
||||
CCGVert *v = ccgdm->vertMap[index].vert;
|
||||
|
||||
vd = ccgSubSurf_getVertData(ss, v);
|
||||
copy_v3_v3(CCG_elem_co(&key, vd), mvert[i].co);
|
||||
i++;
|
||||
}
|
||||
|
||||
ccgSubSurf_updateToFaces(ss, 0, NULL, 0);
|
||||
}
|
||||
|
||||
/* Loads a multires object stored in the old Multires struct into the new format */
|
||||
static void multires_load_old_dm(DerivedMesh *dm, Mesh *me, int totlvl)
|
||||
{
|
||||
MultiresLevel *lvl, *lvl1;
|
||||
Multires *mr = me->mr;
|
||||
MVert *vsrc, *vdst;
|
||||
unsigned int src, dst;
|
||||
int st_last = multires_side_tot[totlvl - 1] - 1;
|
||||
int extedgelen = multires_side_tot[totlvl] - 2;
|
||||
int *vvmap; // inorder for dst, map to src
|
||||
int crossedgelen;
|
||||
int s, x, tottri, totquad;
|
||||
unsigned int i, j, totvert;
|
||||
|
||||
src = 0;
|
||||
vsrc = mr->verts;
|
||||
vdst = dm->getVertArray(dm);
|
||||
totvert = (unsigned int)dm->getNumVerts(dm);
|
||||
vvmap = MEM_calloc_arrayN(totvert, sizeof(int), "multires vvmap");
|
||||
|
||||
if (!vvmap) {
|
||||
return;
|
||||
}
|
||||
|
||||
lvl1 = mr->levels.first;
|
||||
/* Load base verts */
|
||||
for (i = 0; i < lvl1->totvert; i++) {
|
||||
vvmap[totvert - lvl1->totvert + i] = src;
|
||||
src++;
|
||||
}
|
||||
|
||||
/* Original edges */
|
||||
dst = totvert - lvl1->totvert - extedgelen * lvl1->totedge;
|
||||
for (i = 0; i < lvl1->totedge; i++) {
|
||||
int ldst = dst + extedgelen * i;
|
||||
int lsrc = src;
|
||||
lvl = lvl1->next;
|
||||
|
||||
for (j = 2; j <= mr->level_count; j++) {
|
||||
int base = multires_side_tot[totlvl - j + 1] - 2;
|
||||
int skip = multires_side_tot[totlvl - j + 2] - 1;
|
||||
int st = multires_side_tot[j - 1] - 1;
|
||||
|
||||
for (x = 0; x < st; x++) {
|
||||
vvmap[ldst + base + x * skip] = lsrc + st * i + x;
|
||||
}
|
||||
|
||||
lsrc += lvl->totvert - lvl->prev->totvert;
|
||||
lvl = lvl->next;
|
||||
}
|
||||
}
|
||||
|
||||
/* Center points */
|
||||
dst = 0;
|
||||
for (i = 0; i < lvl1->totface; i++) {
|
||||
int sides = lvl1->faces[i].v[3] ? 4 : 3;
|
||||
|
||||
vvmap[dst] = src + lvl1->totedge + i;
|
||||
dst += 1 + sides * (st_last - 1) * st_last;
|
||||
}
|
||||
|
||||
/* The rest is only for level 3 and up */
|
||||
if (lvl1->next && lvl1->next->next) {
|
||||
ListBase **fmap, **emap;
|
||||
IndexNode **fmem, **emem;
|
||||
|
||||
/* Face edge cross */
|
||||
tottri = totquad = 0;
|
||||
crossedgelen = multires_side_tot[totlvl - 1] - 2;
|
||||
dst = 0;
|
||||
for (i = 0; i < lvl1->totface; i++) {
|
||||
int sides = lvl1->faces[i].v[3] ? 4 : 3;
|
||||
|
||||
lvl = lvl1->next->next;
|
||||
dst++;
|
||||
|
||||
for (j = 3; j <= mr->level_count; j++) {
|
||||
int base = multires_side_tot[totlvl - j + 1] - 2;
|
||||
int skip = multires_side_tot[totlvl - j + 2] - 1;
|
||||
int st = pow(2, j - 2);
|
||||
int st2 = pow(2, j - 3);
|
||||
int lsrc = lvl->prev->totvert;
|
||||
|
||||
/* Skip exterior edge verts */
|
||||
lsrc += lvl1->totedge * st;
|
||||
|
||||
/* Skip earlier face edge crosses */
|
||||
lsrc += st2 * (tottri * 3 + totquad * 4);
|
||||
|
||||
for (s = 0; s < sides; s++) {
|
||||
for (x = 0; x < st2; x++) {
|
||||
vvmap[dst + crossedgelen * (s + 1) - base - x * skip - 1] = lsrc;
|
||||
lsrc++;
|
||||
}
|
||||
}
|
||||
|
||||
lvl = lvl->next;
|
||||
}
|
||||
|
||||
dst += sides * (st_last - 1) * st_last;
|
||||
|
||||
if (sides == 4) {
|
||||
totquad++;
|
||||
}
|
||||
else {
|
||||
tottri++;
|
||||
}
|
||||
}
|
||||
|
||||
/* calculate vert to edge/face maps for each level (except the last) */
|
||||
fmap = MEM_calloc_arrayN((mr->level_count - 1), sizeof(ListBase *), "multires fmap");
|
||||
emap = MEM_calloc_arrayN((mr->level_count - 1), sizeof(ListBase *), "multires emap");
|
||||
fmem = MEM_calloc_arrayN((mr->level_count - 1), sizeof(IndexNode *), "multires fmem");
|
||||
emem = MEM_calloc_arrayN((mr->level_count - 1), sizeof(IndexNode *), "multires emem");
|
||||
lvl = lvl1;
|
||||
for (i = 0; i < (unsigned int)mr->level_count - 1; i++) {
|
||||
create_old_vert_face_map(fmap + i, fmem + i, lvl->faces, lvl->totvert, lvl->totface);
|
||||
create_old_vert_edge_map(emap + i, emem + i, lvl->edges, lvl->totvert, lvl->totedge);
|
||||
lvl = lvl->next;
|
||||
}
|
||||
|
||||
/* Interior face verts */
|
||||
/* lvl = lvl1->next->next; */ /* UNUSED */
|
||||
dst = 0;
|
||||
for (j = 0; j < lvl1->totface; j++) {
|
||||
int sides = lvl1->faces[j].v[3] ? 4 : 3;
|
||||
int ldst = dst + 1 + sides * (st_last - 1);
|
||||
|
||||
for (s = 0; s < sides; s++) {
|
||||
int st2 = multires_side_tot[totlvl - 1] - 2;
|
||||
int st3 = multires_side_tot[totlvl - 2] - 2;
|
||||
int st4 = st3 == 0 ? 1 : (st3 + 1) / 2;
|
||||
int mid = ldst + st2 * st3 + st3;
|
||||
int cv = lvl1->faces[j].v[s];
|
||||
int nv = lvl1->faces[j].v[s == sides - 1 ? 0 : s + 1];
|
||||
int pv = lvl1->faces[j].v[s == 0 ? sides - 1 : s - 1];
|
||||
|
||||
multires_load_old_faces(fmap,
|
||||
emap,
|
||||
lvl1->next,
|
||||
vvmap,
|
||||
mid,
|
||||
vvmap[dst],
|
||||
cv,
|
||||
find_old_edge(emap[0], lvl1->edges, pv, cv)->mid,
|
||||
find_old_edge(emap[0], lvl1->edges, cv, nv)->mid,
|
||||
st2,
|
||||
st4);
|
||||
|
||||
ldst += (st_last - 1) * (st_last - 1);
|
||||
}
|
||||
|
||||
dst = ldst;
|
||||
}
|
||||
|
||||
/*lvl = lvl->next;*/ /*UNUSED*/
|
||||
|
||||
for (i = 0; i < (unsigned int)(mr->level_count - 1); i++) {
|
||||
MEM_freeN(fmap[i]);
|
||||
MEM_freeN(fmem[i]);
|
||||
MEM_freeN(emap[i]);
|
||||
MEM_freeN(emem[i]);
|
||||
}
|
||||
|
||||
MEM_freeN(fmap);
|
||||
MEM_freeN(emap);
|
||||
MEM_freeN(fmem);
|
||||
MEM_freeN(emem);
|
||||
}
|
||||
|
||||
/* Transfer verts */
|
||||
for (i = 0; i < totvert; i++) {
|
||||
copy_v3_v3(vdst[i].co, vsrc[vvmap[i]].co);
|
||||
}
|
||||
|
||||
MEM_freeN(vvmap);
|
||||
|
||||
multires_mvert_to_ss(dm, vdst);
|
||||
}
|
||||
|
||||
/* Copy the first-level vcol data to the mesh, if it exists */
|
||||
/* Warning: higher-level vcol data will be lost */
|
||||
static void multires_load_old_vcols(Mesh *me)
|
||||
{
|
||||
MultiresLevel *lvl;
|
||||
MultiresColFace *colface;
|
||||
MCol *mcol;
|
||||
int i, j;
|
||||
|
||||
if (!(lvl = me->mr->levels.first)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(colface = lvl->colfaces)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* older multires format never supported multiple vcol layers,
|
||||
* so we can assume the active vcol layer is the correct one */
|
||||
if (!(mcol = CustomData_get_layer(&me->fdata, CD_MCOL))) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < me->totface; i++) {
|
||||
for (j = 0; j < 4; j++) {
|
||||
mcol[i * 4 + j].a = colface[i].col[j].a;
|
||||
mcol[i * 4 + j].r = colface[i].col[j].r;
|
||||
mcol[i * 4 + j].g = colface[i].col[j].g;
|
||||
mcol[i * 4 + j].b = colface[i].col[j].b;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Copy the first-level face-flag data to the mesh */
|
||||
static void multires_load_old_face_flags(Mesh *me)
|
||||
{
|
||||
MultiresLevel *lvl;
|
||||
MultiresFace *faces;
|
||||
int i;
|
||||
|
||||
if (!(lvl = me->mr->levels.first)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(faces = lvl->faces)) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < me->totface; i++) {
|
||||
me->mface[i].flag = faces[i].flag;
|
||||
}
|
||||
}
|
||||
|
||||
void multires_load_old(Object *ob, Mesh *me)
|
||||
{
|
||||
MultiresLevel *lvl;
|
||||
ModifierData *md;
|
||||
MultiresModifierData *mmd;
|
||||
DerivedMesh *dm, *orig;
|
||||
CustomDataLayer *l;
|
||||
int i;
|
||||
|
||||
/* Load original level into the mesh */
|
||||
lvl = me->mr->levels.first;
|
||||
CustomData_free_layers(&me->vdata, CD_MVERT, lvl->totvert);
|
||||
CustomData_free_layers(&me->edata, CD_MEDGE, lvl->totedge);
|
||||
CustomData_free_layers(&me->fdata, CD_MFACE, lvl->totface);
|
||||
me->totvert = lvl->totvert;
|
||||
me->totedge = lvl->totedge;
|
||||
me->totface = lvl->totface;
|
||||
me->mvert = CustomData_add_layer(&me->vdata, CD_MVERT, CD_CALLOC, NULL, me->totvert);
|
||||
me->medge = CustomData_add_layer(&me->edata, CD_MEDGE, CD_CALLOC, NULL, me->totedge);
|
||||
me->mface = CustomData_add_layer(&me->fdata, CD_MFACE, CD_CALLOC, NULL, me->totface);
|
||||
memcpy(me->mvert, me->mr->verts, sizeof(MVert) * me->totvert);
|
||||
for (i = 0; i < me->totedge; i++) {
|
||||
me->medge[i].v1 = lvl->edges[i].v[0];
|
||||
me->medge[i].v2 = lvl->edges[i].v[1];
|
||||
}
|
||||
for (i = 0; i < me->totface; i++) {
|
||||
me->mface[i].v1 = lvl->faces[i].v[0];
|
||||
me->mface[i].v2 = lvl->faces[i].v[1];
|
||||
me->mface[i].v3 = lvl->faces[i].v[2];
|
||||
me->mface[i].v4 = lvl->faces[i].v[3];
|
||||
me->mface[i].mat_nr = lvl->faces[i].mat_nr;
|
||||
}
|
||||
|
||||
/* Copy the first-level data to the mesh */
|
||||
/* XXX We must do this before converting tessfaces to polys/lopps! */
|
||||
for (i = 0, l = me->mr->vdata.layers; i < me->mr->vdata.totlayer; i++, l++) {
|
||||
CustomData_add_layer(&me->vdata, l->type, CD_REFERENCE, l->data, me->totvert);
|
||||
}
|
||||
for (i = 0, l = me->mr->fdata.layers; i < me->mr->fdata.totlayer; i++, l++) {
|
||||
CustomData_add_layer(&me->fdata, l->type, CD_REFERENCE, l->data, me->totface);
|
||||
}
|
||||
CustomData_reset(&me->mr->vdata);
|
||||
CustomData_reset(&me->mr->fdata);
|
||||
|
||||
multires_load_old_vcols(me);
|
||||
multires_load_old_face_flags(me);
|
||||
|
||||
/* multiresModifier_subdivide_legacy (actually, multires_subdivide_legacy) expects polys, not
|
||||
* tessfaces! */
|
||||
BKE_mesh_convert_mfaces_to_mpolys(me);
|
||||
|
||||
/* Add a multires modifier to the object */
|
||||
md = ob->modifiers.first;
|
||||
while (md && BKE_modifier_get_info(md->type)->type == eModifierTypeType_OnlyDeform) {
|
||||
md = md->next;
|
||||
}
|
||||
mmd = (MultiresModifierData *)BKE_modifier_new(eModifierType_Multires);
|
||||
BLI_insertlinkbefore(&ob->modifiers, md, mmd);
|
||||
|
||||
for (i = 0; i < me->mr->level_count - 1; i++) {
|
||||
multiresModifier_subdivide_legacy(mmd, NULL, ob, 1, 0);
|
||||
}
|
||||
|
||||
mmd->lvl = mmd->totlvl;
|
||||
orig = CDDM_from_mesh(me);
|
||||
/* XXX We *must* alloc paint mask here, else we have some kind of mismatch in
|
||||
* multires_modifier_update_mdisps() (called by dm->release(dm)), which always creates the
|
||||
* reference subsurfed dm with this option, before calling multiresModifier_disp_run(),
|
||||
* which implicitly expects both subsurfs from its first dm and oldGridData parameters to
|
||||
* be of the same "format"! */
|
||||
dm = multires_make_derived_from_derived(orig, mmd, NULL, ob, 0);
|
||||
|
||||
multires_load_old_dm(dm, me, mmd->totlvl + 1);
|
||||
|
||||
multires_dm_mark_as_modified(dm, MULTIRES_COORDS_MODIFIED);
|
||||
dm->release(dm);
|
||||
orig->release(orig);
|
||||
|
||||
/* Remove the old multires */
|
||||
multires_free(me->mr);
|
||||
me->mr = NULL;
|
||||
}
|
||||
|
||||
/* 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,
|
||||
|
|
|
@ -799,20 +799,6 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *bmain)
|
|||
|
||||
// BLI_freelistN(&pidlist);
|
||||
|
||||
if (ob->type == OB_MESH) {
|
||||
Mesh *me = blo_do_versions_newlibadr(fd, lib, ob->data);
|
||||
void *olddata = ob->data;
|
||||
ob->data = me;
|
||||
|
||||
/* XXX - library meshes crash on loading most yoFrankie levels,
|
||||
* the multires pointer gets invalid - Campbell */
|
||||
if (me && me->id.lib == NULL && me->mr && me->mr->level_count > 1) {
|
||||
multires_load_old(ob, me);
|
||||
}
|
||||
|
||||
ob->data = olddata;
|
||||
}
|
||||
|
||||
if (ob->totcol && ob->matbits == NULL) {
|
||||
int a;
|
||||
|
||||
|
@ -1152,7 +1138,7 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *bmain)
|
|||
|
||||
if (bmain->versionfile == 250 && bmain->subversionfile > 1) {
|
||||
for (me = bmain->meshes.first; me; me = me->id.next) {
|
||||
multires_load_old_250(me);
|
||||
CustomData_free_layer_active(&me->fdata, CD_MDISPS, me->totface);
|
||||
}
|
||||
|
||||
for (ob = bmain->objects.first; ob; ob = ob->id.next) {
|
||||
|
|
|
@ -1959,7 +1959,6 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *bmain)
|
|||
Light *la;
|
||||
Material *ma;
|
||||
ParticleSettings *part;
|
||||
Mesh *me;
|
||||
bNodeTree *ntree;
|
||||
Tex *tex;
|
||||
ModifierData *md;
|
||||
|
@ -2074,23 +2073,6 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *bmain)
|
|||
}
|
||||
}
|
||||
|
||||
/* Copy over old per-level multires vertex data
|
||||
* into a single vertex array in struct Multires */
|
||||
for (me = bmain->meshes.first; me; me = me->id.next) {
|
||||
if (me->mr && !me->mr->verts) {
|
||||
MultiresLevel *lvl = me->mr->levels.last;
|
||||
if (lvl) {
|
||||
me->mr->verts = lvl->verts;
|
||||
lvl->verts = NULL;
|
||||
/* Don't need the other vert arrays */
|
||||
for (lvl = lvl->prev; lvl; lvl = lvl->prev) {
|
||||
MEM_freeN(lvl->verts);
|
||||
lvl->verts = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bmain->versionfile != 245 || bmain->subversionfile < 1) {
|
||||
for (la = bmain->lights.first; la; la = la->id.next) {
|
||||
la->falloff_type = LA_FALLOFF_INVLINEAR;
|
||||
|
|
|
@ -48,7 +48,6 @@ struct MPropCol;
|
|||
struct MVert;
|
||||
struct Material;
|
||||
struct Mesh;
|
||||
struct Multires;
|
||||
struct SubdivCCG;
|
||||
|
||||
#
|
||||
|
@ -230,9 +229,6 @@ typedef struct Mesh {
|
|||
* default and Face Sets can be used without affecting the color of the mesh. */
|
||||
int face_sets_color_default;
|
||||
|
||||
/** Deprecated multiresolution modeling data, only keep for loading old files. */
|
||||
struct Multires *mr DNA_DEPRECATED;
|
||||
|
||||
Mesh_Runtime runtime;
|
||||
} Mesh;
|
||||
|
||||
|
|
|
@ -518,54 +518,4 @@ typedef struct MRecast {
|
|||
int i;
|
||||
} MRecast;
|
||||
|
||||
/** Multires structs kept for compatibility with old files. */
|
||||
typedef struct MultiresCol {
|
||||
float a, r, g, b;
|
||||
} MultiresCol;
|
||||
|
||||
typedef struct MultiresColFace {
|
||||
/* vertex colors */
|
||||
MultiresCol col[4];
|
||||
} MultiresColFace;
|
||||
|
||||
typedef struct MultiresFace {
|
||||
unsigned int v[4];
|
||||
unsigned int mid;
|
||||
char flag, mat_nr, _pad[2];
|
||||
} MultiresFace;
|
||||
|
||||
typedef struct MultiresEdge {
|
||||
unsigned int v[2];
|
||||
unsigned int mid;
|
||||
} MultiresEdge;
|
||||
|
||||
typedef struct MultiresLevel {
|
||||
struct MultiresLevel *next, *prev;
|
||||
|
||||
MultiresFace *faces;
|
||||
MultiresColFace *colfaces;
|
||||
MultiresEdge *edges;
|
||||
|
||||
unsigned int totvert, totface, totedge;
|
||||
char _pad[4];
|
||||
|
||||
/* Kept for compatibility with even older files */
|
||||
MVert *verts;
|
||||
} MultiresLevel;
|
||||
|
||||
typedef struct Multires {
|
||||
ListBase levels;
|
||||
MVert *verts;
|
||||
|
||||
unsigned char level_count, current, newlvl, edgelvl, pinlvl, renderlvl;
|
||||
unsigned char use_col, flag;
|
||||
|
||||
/* Special level 1 data that cannot be modified from other levels */
|
||||
CustomData vdata;
|
||||
CustomData fdata;
|
||||
short *edge_flags;
|
||||
char *edge_creases;
|
||||
} Multires;
|
||||
/* End multi-res structs. */
|
||||
|
||||
/** \} */
|
||||
|
|
Loading…
Reference in New Issue