Fix #108880: Skin and Miffor modifiers cause mesh collapse
Before 4369627e71, the Mirror modifier merge did not interpolate
customdata.
Previously, the customdata was simply copied from the original vertex
during the merge, resulting in the retention of flags such as
`MVERT_SKIN_ROOT`.
This fix could just repeat that behavior for mirror. But these flags
can be useful in other cases, so this commit re-adds them to the
resulting merged vertex.
Although this can generate geometries with multiple roots on the same
island, there are different scenarios in which this can happen.
Therefore, multiple roots on the same island is not necessarily
considered a bug.
This commit is contained in:
@@ -1455,6 +1455,8 @@ static void customdata_weld(
|
||||
int src_i, dest_i;
|
||||
int j;
|
||||
|
||||
int vs_flag = 0;
|
||||
|
||||
/* interpolates a layer at a time */
|
||||
dest_i = 0;
|
||||
for (src_i = 0; src_i < source->totlayer; src_i++) {
|
||||
@@ -1475,7 +1477,21 @@ static void customdata_weld(
|
||||
/* if we found a matching layer, add the data */
|
||||
if (dest->layers[dest_i].type == type) {
|
||||
void *src_data = source->layers[src_i].data;
|
||||
if (CustomData_layer_has_interp(dest, dest_i)) {
|
||||
if (type == CD_MVERT_SKIN) {
|
||||
/* The `typeInfo->interp` of #CD_MVERT_SKIN does not include the flags, so #MVERT_SKIN_ROOT
|
||||
* and #MVERT_SKIN_LOOSE are lost after the interpolation.
|
||||
*
|
||||
* This behavior is not incorrect. Ideally, islands should be checked to avoid repeated
|
||||
* roots.
|
||||
*
|
||||
* However, for now, to prevent the loss of flags, they are simply re-added if any of the
|
||||
* merged vertices have them. */
|
||||
for (j = 0; j < count; j++) {
|
||||
MVertSkin *vs = &((MVertSkin *)src_data)[src_indices[j]];
|
||||
vs_flag |= vs->flag;
|
||||
}
|
||||
}
|
||||
else if (CustomData_layer_has_interp(dest, dest_i)) {
|
||||
/* Already calculated.
|
||||
* TODO: Optimize by exposing `typeInfo->interp`. */
|
||||
}
|
||||
@@ -1505,7 +1521,11 @@ static void customdata_weld(
|
||||
for (dest_i = 0; dest_i < dest->totlayer; dest_i++) {
|
||||
CustomDataLayer *layer_dst = &dest->layers[dest_i];
|
||||
const eCustomDataType type = eCustomDataType(layer_dst->type);
|
||||
if (CustomData_layer_has_interp(dest, dest_i)) {
|
||||
if (type == CD_MVERT_SKIN) {
|
||||
MVertSkin *vs = &((MVertSkin *)layer_dst->data)[dest_index];
|
||||
vs->flag = vs_flag;
|
||||
}
|
||||
else if (CustomData_layer_has_interp(dest, dest_i)) {
|
||||
/* Already calculated. */
|
||||
}
|
||||
else if (CustomData_layer_has_math(dest, dest_i)) {
|
||||
|
||||
Reference in New Issue
Block a user