fix [#30771] Shapekeys: Basis shapekey is not kept in sync with "RealMesh"

behave the same as in 2.4x.

- merge BMesh / Pre-BMesh code shape key conversion code, old code was called as a fallback but merge instead.
- fix possible crash - new bmesh code was clamping the vertex index for the oldverts array by the new total number of verts.
This commit is contained in:
Campbell Barton 2012-04-11 15:59:50 +00:00
parent 1f6369fd41
commit c8b19b7b7f

@ -763,104 +763,63 @@ void BM_mesh_bm_to_me(BMesh *bm, Mesh *me, int dotess)
ofs = bm_to_mesh_shape_basis_offset(me, bm); /* may be NULL */ ofs = bm_to_mesh_shape_basis_offset(me, bm); /* may be NULL */
} }
for (currkey = me->key->block.first; currkey; currkey = currkey->next) { for (currkey = me->key->block.first; currkey; currkey = currkey->next) {
int apply_offset = (ofs && (currkey != actkey) && (bm->shapenr - 1 == currkey->relative)); int apply_offset = (ofs && (currkey != actkey) && (bm->shapenr - 1 == currkey->relative));
int *keyi; int *keyi;
float (*ofs_pt)[3] = ofs; float (*ofs_pt)[3] = ofs;
float *fp; float *newkey, *oldkey, *fp;
j = bm_to_mesh_shape_layer_index_from_kb(bm, currkey); j = bm_to_mesh_shape_layer_index_from_kb(bm, currkey);
if (j != -1) { /* new bmesh conversion method */
/* new bmesh conversion method */
float *co;
if (currkey->data) fp = newkey = MEM_callocN(me->key->elemsize * bm->totvert, "currkey->data");
MEM_freeN(currkey->data); oldkey = currkey->data;
currkey->data = fp = MEM_mallocN(sizeof(float) * 3 * bm->totvert, "shape key data");
currkey->totelem = bm->totvert;
mvert = me->mvert; mvert = me->mvert;
BM_ITER(eve, &iter, bm, BM_VERTS_OF_MESH, NULL) { BM_ITER(eve, &iter, bm, BM_VERTS_OF_MESH, NULL) {
co = (currkey == actkey) ?
eve->co :
CustomData_bmesh_get_n(&bm->vdata, eve->head.data, CD_SHAPEKEY, j);
copy_v3_v3(fp, co); if (currkey == actkey) {
copy_v3_v3(fp, eve->co);
/* propagate edited basis offsets to other shapes */ if (actkey != me->key->refkey) {
if (apply_offset) { if (oldverts) {
add_v3_v3(fp, *ofs_pt++); keyi = CustomData_bmesh_get(&bm->vdata, eve->head.data, CD_SHAPE_KEYINDEX);
} if (*keyi != ORIGINDEX_NONE && *keyi < currkey->totelem) { // valid old vertex
copy_v3_v3(mvert->co, oldverts[*keyi].co);
if (currkey == actkey && oldverts) {
keyi = CustomData_bmesh_get(&bm->vdata, eve->head.data, CD_SHAPE_KEYINDEX);
if (*keyi >= 0 && *keyi < currkey->totelem) // valid old vertex
copy_v3_v3(mvert->co, oldverts[*keyi].co);
mvert++;
}
fp += 3;
}
}
else {
/* if we didn't find a shapekey, tag the block to be reconstructed
* via the old method below */
/* old method of reconstructing keys via vertice's original key indices,
* currently used if the new method above fails (which is theoretically
* possible in certain cases of undo) */
float *newkey, *oldkey;
printf("warning: had to hackishly reconstruct shape key \"%s\","
" it may not be correct anymore.\n", currkey->name);
fp = newkey = MEM_callocN(me->key->elemsize * bm->totvert, "currkey->data");
oldkey = currkey->data;
mvert = me->mvert;
BM_ITER(eve, &iter, bm, BM_VERTS_OF_MESH, NULL) {
keyi = CustomData_bmesh_get(&bm->vdata, eve->head.data, CD_SHAPE_KEYINDEX);
if (keyi && *keyi != ORIGINDEX_NONE && *keyi < currkey->totelem) { /* valid old vertex */
if (currkey == actkey) {
if (actkey == me->key->refkey) {
copy_v3_v3(fp, mvert->co);
}
else {
copy_v3_v3(fp, mvert->co);
if (oldverts) {
copy_v3_v3(mvert->co, oldverts[*keyi].co);
}
}
}
else {
if (oldkey) {
copy_v3_v3(fp, oldkey + 3 * *keyi);
} }
} }
} }
else {
copy_v3_v3(fp, mvert->co);
}
/* propagate edited basis offsets to other shapes */
if (apply_offset) {
add_v3_v3(fp, *ofs_pt++);
}
fp += 3;
mvert++;
} }
currkey->totelem = bm->totvert; else if (j != -1) {
if (currkey->data) MEM_freeN(currkey->data); /* in most cases this runs */
currkey->data = newkey; copy_v3_v3(fp, CustomData_bmesh_get_n(&bm->vdata, eve->head.data, CD_SHAPEKEY, j));
/* end old compad code */ }
else if (oldkey) {
/* old method of reconstructing keys via vertice's original key indices,
* currently used if the new method above fails (which is theoretically
* possible in certain cases of undo) */
copy_v3_v3(fp, oldkey + 3 * *keyi);
}
else {
/* fail! fill in with dummy value */
copy_v3_v3(fp, mvert->co);
}
/* propagate edited basis offsets to other shapes */
if (apply_offset) {
add_v3_v3(fp, *ofs_pt++);
}
fp += 3;
mvert++;
} }
currkey->totelem = bm->totvert;
if (currkey->data) {
MEM_freeN(currkey->data);
}
currkey->data = newkey;
} }
if (ofs) MEM_freeN(ofs); if (ofs) MEM_freeN(ofs);