Fix T41890: Regression in new array modifier code, vnors were no more offset-corrected.

This is not needed when we tag normals as dirty, but in simple cases, if offset has some
rotation (or non-uniform scaling) component, vertex normals has to be corrected.
This commit is contained in:
Bastien Montagne 2014-09-21 10:12:26 +02:00
parent b96a3607dd
commit 398ca952ab
Notes: blender-bot 2023-02-14 10:21:15 +01:00
Referenced by issue #41890, Mirror subserf and array modifiers cause arrayed objects to have inverted normals
1 changed files with 19 additions and 10 deletions

View File

@ -404,6 +404,9 @@ static DerivedMesh *arrayModifier_doArray(
int *full_doubles_map = NULL;
int tot_doubles;
const bool use_merge = amd->flags & MOD_ARR_MERGE;
const bool use_recalc_normals = (dm->dirty & DM_DIRTY_NORMALS) || use_merge;
int start_cap_nverts = 0, start_cap_nedges = 0, start_cap_npolys = 0, start_cap_nloops = 0;
int end_cap_nverts = 0, end_cap_nedges = 0, end_cap_npolys = 0, end_cap_nloops = 0;
int result_nverts = 0, result_nedges = 0, result_npolys = 0, result_nloops = 0;
@ -514,7 +517,7 @@ static DerivedMesh *arrayModifier_doArray(
result = CDDM_from_template(dm, result_nverts, result_nedges, 0, result_nloops, result_npolys);
result_dm_verts = CDDM_get_verts(result);
if (amd->flags & MOD_ARR_MERGE) {
if (use_merge) {
/* Will need full_doubles_map for handling merge */
full_doubles_map = MEM_mallocN(sizeof(int) * result_nverts, "mod array doubles map");
fill_vn_i(full_doubles_map, result_nverts, -1);
@ -561,6 +564,15 @@ static DerivedMesh *arrayModifier_doArray(
/* apply offset to all new verts */
for (i = 0; i < chunk_nverts; i++, mv++, mv_prev++) {
mul_m4_v3(current_offset, mv->co);
/* We have to correct normals too, if we do not tag them as dirty! */
if (!use_recalc_normals) {
float no[3];
normal_short_to_float_v3(no, mv->no);
mul_mat3_m4_v3(current_offset, no);
normalize_v3(no);
normal_float_to_short_v3(mv->no, no);
}
}
/* adjust edge vertex indices */
@ -583,7 +595,7 @@ static DerivedMesh *arrayModifier_doArray(
}
/* Handle merge between chunk n and n-1 */
if ((amd->flags & MOD_ARR_MERGE) && (c >= 1)) {
if (use_merge && (c >= 1)) {
if (!offset_has_scale && (c >= 2)) {
/* Mapping chunk 3 to chunk 2 is a translation of mapping 2 to 1
* ... that is except if scaling makes the distance grow */
@ -622,10 +634,7 @@ static DerivedMesh *arrayModifier_doArray(
copy_m4_m4(final_offset, current_offset);
if ((amd->flags & MOD_ARR_MERGE) &&
(amd->flags & MOD_ARR_MERGEFINAL) &&
(count > 1))
{
if (use_merge && (amd->flags & MOD_ARR_MERGEFINAL) && (count > 1)) {
/* Merge first and last copies */
dm_mvert_map_doubles(
full_doubles_map,
@ -651,7 +660,7 @@ static DerivedMesh *arrayModifier_doArray(
result_npolys - start_cap_npolys - end_cap_npolys,
start_cap_nverts, start_cap_nedges, start_cap_nloops, start_cap_npolys);
/* Identify doubles with first chunk */
if (amd->flags & MOD_ARR_MERGE) {
if (use_merge) {
dm_mvert_map_doubles(
full_doubles_map,
result_dm_verts,
@ -676,7 +685,7 @@ static DerivedMesh *arrayModifier_doArray(
result_npolys - end_cap_npolys,
end_cap_nverts, end_cap_nedges, end_cap_nloops, end_cap_npolys);
/* Identify doubles with last chunk */
if (amd->flags & MOD_ARR_MERGE) {
if (use_merge) {
dm_mvert_map_doubles(
full_doubles_map,
result_dm_verts,
@ -693,13 +702,13 @@ static DerivedMesh *arrayModifier_doArray(
/* In case org dm has dirty normals, or we made some merging, mark normals as dirty in new dm!
* TODO: we may need to set other dirty flags as well?
*/
if ((dm->dirty & DM_DIRTY_NORMALS) || full_doubles_map) {
if (use_recalc_normals) {
result->dirty |= DM_DIRTY_NORMALS;
}
/* Handle merging */
tot_doubles = 0;
if (full_doubles_map) {
if (use_merge) {
for (i = 0; i < result_nverts; i++) {
if (full_doubles_map[i] != -1) {
tot_doubles++;