Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/modifiers/intern')
-rw-r--r--source/blender/modifiers/intern/MOD_array.c4
-rw-r--r--source/blender/modifiers/intern/MOD_curve.c2
-rw-r--r--source/blender/modifiers/intern/MOD_displace.c3
-rw-r--r--source/blender/modifiers/intern/MOD_nodes.cc6
-rw-r--r--source/blender/modifiers/intern/MOD_normal_edit.c4
-rw-r--r--source/blender/modifiers/intern/MOD_solidify_extrude.c6
-rw-r--r--source/blender/modifiers/intern/MOD_solidify_nonmanifold.c307
-rw-r--r--source/blender/modifiers/intern/MOD_subsurf.c14
-rw-r--r--source/blender/modifiers/intern/MOD_ui_common.c2
-rw-r--r--source/blender/modifiers/intern/MOD_util.c2
-rw-r--r--source/blender/modifiers/intern/MOD_uvproject.c3
-rw-r--r--source/blender/modifiers/intern/MOD_volume_displace.cc6
-rw-r--r--source/blender/modifiers/intern/MOD_weightvgmix.c6
13 files changed, 215 insertions, 150 deletions
diff --git a/source/blender/modifiers/intern/MOD_array.c b/source/blender/modifiers/intern/MOD_array.c
index 2cc3bb8c916..ea42ac761ea 100644
--- a/source/blender/modifiers/intern/MOD_array.c
+++ b/source/blender/modifiers/intern/MOD_array.c
@@ -371,7 +371,7 @@ static Mesh *arrayModifier_doArray(ArrayModifierData *amd,
int tot_doubles;
const bool use_merge = (amd->flags & MOD_ARR_MERGE) != 0;
- const bool use_recalc_normals = (mesh->runtime.cd_dirty_vert & CD_MASK_NORMAL) || use_merge;
+ const bool use_recalc_normals = BKE_mesh_vertex_normals_are_dirty(mesh) || use_merge;
const bool use_offset_ob = ((amd->offset_type & MOD_ARR_OFF_OBJ) && amd->offset_ob != NULL);
int start_cap_nverts = 0, start_cap_nedges = 0, start_cap_npolys = 0, start_cap_nloops = 0;
@@ -819,7 +819,7 @@ static bool isDisabled(const struct Scene *UNUSED(scene),
* In other cases it should be impossible to have a type mismatch.
*/
- if (amd->curve_ob && amd->curve_ob->type != OB_CURVE) {
+ if (amd->curve_ob && amd->curve_ob->type != OB_CURVES_LEGACY) {
return true;
}
if (amd->start_cap && amd->start_cap->type != OB_MESH) {
diff --git a/source/blender/modifiers/intern/MOD_curve.c b/source/blender/modifiers/intern/MOD_curve.c
index ca5d59433f0..d1c7dd43f15 100644
--- a/source/blender/modifiers/intern/MOD_curve.c
+++ b/source/blender/modifiers/intern/MOD_curve.c
@@ -71,7 +71,7 @@ static bool isDisabled(const Scene *UNUSED(scene), ModifierData *md, bool UNUSED
*
* In other cases it should be impossible to have a type mismatch.
*/
- return !cmd->object || cmd->object->type != OB_CURVE;
+ return !cmd->object || cmd->object->type != OB_CURVES_LEGACY;
}
static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData)
diff --git a/source/blender/modifiers/intern/MOD_displace.c b/source/blender/modifiers/intern/MOD_displace.c
index 0411bcd7c34..ddbed4f498e 100644
--- a/source/blender/modifiers/intern/MOD_displace.c
+++ b/source/blender/modifiers/intern/MOD_displace.c
@@ -313,8 +313,7 @@ static void displaceModifier_do(DisplaceModifierData *dmd,
if (CustomData_has_layer(ldata, CD_CUSTOMLOOPNORMAL)) {
float(*clnors)[3] = NULL;
- if ((mesh->runtime.cd_dirty_vert & CD_MASK_NORMAL) ||
- !CustomData_has_layer(ldata, CD_NORMAL)) {
+ if (!CustomData_has_layer(ldata, CD_NORMAL)) {
BKE_mesh_calc_normals_split(mesh);
}
diff --git a/source/blender/modifiers/intern/MOD_nodes.cc b/source/blender/modifiers/intern/MOD_nodes.cc
index f54ed8f5a25..210a7edac54 100644
--- a/source/blender/modifiers/intern/MOD_nodes.cc
+++ b/source/blender/modifiers/intern/MOD_nodes.cc
@@ -454,6 +454,10 @@ static IDProperty *id_property_create_from_socket(const bNodeSocket &socket)
ui_data->base.rna_subtype = PROP_COLOR;
ui_data->default_array = (double *)MEM_mallocN(sizeof(double[4]), __func__);
ui_data->default_array_len = 4;
+ ui_data->min = 0.0;
+ ui_data->max = FLT_MAX;
+ ui_data->soft_min = 0.0;
+ ui_data->soft_max = 1.0;
for (const int i : IndexRange(4)) {
ui_data->default_array[i] = double(value->value[i]);
}
@@ -1381,7 +1385,7 @@ static void add_attribute_search_button(const bContext &C,
0.0f,
0.0f,
0.0f,
- "");
+ socket.description);
const Object *object = ED_object_context(&C);
BLI_assert(object != nullptr);
diff --git a/source/blender/modifiers/intern/MOD_normal_edit.c b/source/blender/modifiers/intern/MOD_normal_edit.c
index e6aebbfeb56..3649808f4f0 100644
--- a/source/blender/modifiers/intern/MOD_normal_edit.c
+++ b/source/blender/modifiers/intern/MOD_normal_edit.c
@@ -535,8 +535,8 @@ static Mesh *normalEditModifier_do(NormalEditModifierData *enmd,
CustomData *ldata = &result->ldata;
- const float(*vert_normals)[3] = BKE_mesh_vertex_normals_ensure(mesh);
- const float(*poly_normals)[3] = BKE_mesh_poly_normals_ensure(mesh);
+ const float(*vert_normals)[3] = BKE_mesh_vertex_normals_ensure(result);
+ const float(*poly_normals)[3] = BKE_mesh_poly_normals_ensure(result);
clnors = CustomData_get_layer(ldata, CD_CUSTOMLOOPNORMAL);
if (use_current_clnors) {
diff --git a/source/blender/modifiers/intern/MOD_solidify_extrude.c b/source/blender/modifiers/intern/MOD_solidify_extrude.c
index 0313c37283a..fdaf7bd41d1 100644
--- a/source/blender/modifiers/intern/MOD_solidify_extrude.c
+++ b/source/blender/modifiers/intern/MOD_solidify_extrude.c
@@ -953,7 +953,7 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex
}
/* must recalculate normals with vgroups since they can displace unevenly T26888. */
- if ((mesh->runtime.cd_dirty_vert & CD_MASK_NORMAL) || do_rim || dvert) {
+ if (BKE_mesh_vertex_normals_are_dirty(mesh) || do_rim || dvert) {
BKE_mesh_normals_tag_dirty(result);
}
else if (do_shell) {
@@ -1009,9 +1009,9 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex
#define SOLIDIFY_SIDE_NORMALS
#ifdef SOLIDIFY_SIDE_NORMALS
- /* NOTE(@sybren): due to the code setting cd_dirty_vert a few lines above,
+ /* NOTE(@sybren): due to the code setting normals dirty a few lines above,
* do_side_normals is always false. */
- const bool do_side_normals = !(result->runtime.cd_dirty_vert & CD_MASK_NORMAL);
+ const bool do_side_normals = !BKE_mesh_vertex_normals_are_dirty(result);
/* annoying to allocate these since we only need the edge verts, */
float(*edge_vert_nos)[3] = do_side_normals ?
MEM_calloc_arrayN(numVerts, sizeof(float[3]), __func__) :
diff --git a/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c b/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c
index ed7acef4cdc..ff25c1afd49 100644
--- a/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c
+++ b/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c
@@ -1405,21 +1405,26 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
for (uint j = 0; g->valid; j++, g++) {
if (!g->is_singularity) {
float *nor = g->no;
+ /* During vertex position calculation, the algorithm decides if it wants to disable the
+ * boundary fix to maintain correct thickness. If the used algorithm does not produce a
+ * free move direction (move_nor), it can use approximate_free_direction to decide on
+ * a movement direction based on the connected edges. */
float move_nor[3] = {0, 0, 0};
bool disable_boundary_fix = (smd->nonmanifold_boundary_mode ==
MOD_SOLIDIFY_NONMANIFOLD_BOUNDARY_MODE_NONE ||
(g->is_orig_closed || g->split));
+ bool approximate_free_direction = false;
/* Constraints Method. */
if (smd->nonmanifold_offset_mode == MOD_SOLIDIFY_NONMANIFOLD_OFFSET_MODE_CONSTRAINTS) {
NewEdgeRef *first_edge = NULL;
NewEdgeRef **edge_ptr = g->edges;
/* Contains normal and offset [nx, ny, nz, ofs]. */
- float(*normals_queue)[4] = MEM_malloc_arrayN(
- g->edges_len + 1, sizeof(*normals_queue), "normals_queue in solidify");
+ float(*planes_queue)[4] = MEM_malloc_arrayN(
+ g->edges_len + 1, sizeof(*planes_queue), "planes_queue in solidify");
uint queue_index = 0;
- float face_nors[3][3];
- float nor_ofs[3];
+ float fallback_nor[3];
+ float fallback_ofs = 0.0f;
const bool cycle = (g->is_orig_closed && !g->split) || g->is_even_split;
for (uint k = 0; k < g->edges_len; k++, edge_ptr++) {
@@ -1436,17 +1441,17 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
}
if (!null_faces[face->index]) {
- /* And normal to the queue. */
- mul_v3_v3fl(normals_queue[queue_index],
+ /* And plane to the queue. */
+ mul_v3_v3fl(planes_queue[queue_index],
poly_nors[face->index],
face->reversed ? -1 : 1);
- normals_queue[queue_index++][3] = ofs;
+ planes_queue[queue_index++][3] = ofs;
}
else {
/* Just use this approximate normal of the null face if there is no other
* normal to use. */
- mul_v3_v3fl(face_nors[0], poly_nors[face->index], face->reversed ? -1 : 1);
- nor_ofs[0] = ofs;
+ mul_v3_v3fl(fallback_nor, poly_nors[face->index], face->reversed ? -1 : 1);
+ fallback_ofs = ofs;
}
}
}
@@ -1455,131 +1460,173 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
}
}
}
- uint face_nors_len = 0;
- const float stop_explosion = 0.999f - fabsf(smd->offset_fac) * 0.05f;
- while (queue_index > 0) {
- if (face_nors_len == 0) {
- if (queue_index <= 2) {
- for (uint k = 0; k < queue_index; k++) {
- copy_v3_v3(face_nors[k], normals_queue[k]);
- nor_ofs[k] = normals_queue[k][3];
+ if (queue_index > 2) {
+ /* Find the two most different normals. */
+ float min_p = 2.0f;
+ uint min_n0 = 0;
+ uint min_n1 = 0;
+ for (uint k = 0; k < queue_index; k++) {
+ for (uint m = k + 1; m < queue_index; m++) {
+ float p = dot_v3v3(planes_queue[k], planes_queue[m]);
+ if (p < min_p) {
+ min_p = p;
+ min_n0 = k;
+ min_n1 = m;
}
- face_nors_len = queue_index;
- queue_index = 0;
}
- else {
- /* Find most different two normals. */
- float min_p = 2;
- uint min_n0 = 0;
- uint min_n1 = 0;
- for (uint k = 0; k < queue_index; k++) {
- for (uint m = k + 1; m < queue_index; m++) {
- float p = dot_v3v3(normals_queue[k], normals_queue[m]);
- if (p <= min_p + FLT_EPSILON) {
- min_p = p;
- min_n0 = m;
- min_n1 = k;
- }
- }
- }
- copy_v3_v3(face_nors[0], normals_queue[min_n0]);
- copy_v3_v3(face_nors[1], normals_queue[min_n1]);
- nor_ofs[0] = normals_queue[min_n0][3];
- nor_ofs[1] = normals_queue[min_n1][3];
- face_nors_len = 2;
- queue_index--;
- memmove(normals_queue + min_n0,
- normals_queue + min_n0 + 1,
- (queue_index - min_n0) * sizeof(*normals_queue));
- queue_index--;
- memmove(normals_queue + min_n1,
- normals_queue + min_n1 + 1,
- (queue_index - min_n1) * sizeof(*normals_queue));
- min_p = 1;
- min_n1 = 0;
- float max_p = -1;
- for (uint k = 0; k < queue_index; k++) {
- max_p = -1;
- for (uint m = 0; m < face_nors_len; m++) {
- float p = dot_v3v3(face_nors[m], normals_queue[k]);
- if (p > max_p + FLT_EPSILON) {
- max_p = p;
- }
- }
- if (max_p <= min_p + FLT_EPSILON) {
- min_p = max_p;
- min_n1 = k;
- }
- }
- if (min_p < 0.8) {
- copy_v3_v3(face_nors[2], normals_queue[min_n1]);
- nor_ofs[2] = normals_queue[min_n1][3];
- face_nors_len++;
- queue_index--;
- memmove(normals_queue + min_n1,
- normals_queue + min_n1 + 1,
- (queue_index - min_n1) * sizeof(*normals_queue));
+ }
+ /* Put the two found normals, first in the array queue. */
+ if (min_n1 != 0) {
+ swap_v4_v4(planes_queue[min_n0], planes_queue[0]);
+ swap_v4_v4(planes_queue[min_n1], planes_queue[1]);
+ }
+ else {
+ swap_v4_v4(planes_queue[min_n0], planes_queue[1]);
+ }
+ /* Find the third most important/different normal. */
+ min_p = 1.0f;
+ min_n1 = 2;
+ float max_p = -1.0f;
+ for (uint k = 2; k < queue_index; k++) {
+ max_p = max_ff(dot_v3v3(planes_queue[0], planes_queue[k]),
+ dot_v3v3(planes_queue[1], planes_queue[k]));
+ if (max_p <= min_p) {
+ min_p = max_p;
+ min_n1 = k;
+ }
+ }
+ swap_v4_v4(planes_queue[min_n1], planes_queue[2]);
+ }
+ /* Remove/average duplicate normals in planes_queue. */
+ while (queue_index > 2) {
+ uint best_n0 = 0;
+ uint best_n1 = 0;
+ float best_p = -1.0f;
+ float best_ofs_diff = 0.0f;
+ for (uint k = 0; k < queue_index; k++) {
+ for (uint m = k + 1; m < queue_index; m++) {
+ float p = dot_v3v3(planes_queue[m], planes_queue[k]);
+ float ofs_diff = fabsf(planes_queue[m][3] - planes_queue[k][3]);
+ if (p > best_p + FLT_EPSILON || (p >= best_p && ofs_diff < best_ofs_diff)) {
+ best_p = p;
+ best_ofs_diff = ofs_diff;
+ best_n0 = k;
+ best_n1 = m;
}
}
}
- else {
- uint best = 0;
- uint best_group = 0;
- float best_p = -1.0f;
- for (uint k = 0; k < queue_index; k++) {
- for (uint m = 0; m < face_nors_len; m++) {
- float p = dot_v3v3(face_nors[m], normals_queue[k]);
- if (p > best_p + FLT_EPSILON) {
- best_p = p;
- best = m;
- best_group = k;
+ /* Make sure there are no equal planes. This threshold is crucial for the
+ * methods below to work without numerical issues. */
+ if (best_p < 0.98f) {
+ break;
+ }
+ add_v3_v3(planes_queue[best_n0], planes_queue[best_n1]);
+ normalize_v3(planes_queue[best_n0]);
+ planes_queue[best_n0][3] = (planes_queue[best_n0][3] + planes_queue[best_n1][3]) *
+ 0.5f;
+ queue_index--;
+ memmove(planes_queue + best_n1,
+ planes_queue + best_n1 + 1,
+ (queue_index - best_n1) * sizeof(*planes_queue));
+ }
+ const uint size = queue_index;
+ /* If there is more than 2 planes at this vertex, the boundary fix should be disabled
+ * to stay at the correct thickness for all the faces. This is not very good in
+ * practice though, since that will almost always disable the boundary fix. Instead
+ * introduce a threshold which decides whether the boundary fix can be used without
+ * major thickness changes. If the following constant is 1.0, it would always
+ * prioritize correct thickness. At 0.7 the thickness is allowed to change a bit if
+ * necessary for the fix (~10%). Note this only applies if a boundary fix is used. */
+ const float boundary_fix_threshold = 0.7f;
+ if (size > 3) {
+ /* Use the most general least squares method to find the best position. */
+ float mat[3][3];
+ zero_m3(mat);
+ for (int k = 0; k < 3; k++) {
+ for (int m = 0; m < size; m++) {
+ madd_v3_v3fl(mat[k], planes_queue[m], planes_queue[m][k]);
+ }
+ /* Add a small epsilon to ensure the invert is going to work.
+ * This addition makes the inverse more stable and the results
+ * seem to get more precise. */
+ mat[k][k] += 5e-5f;
+ }
+ /* NOTE: this matrix invert fails if there is less than 3 different normals. */
+ invert_m3(mat);
+ zero_v3(nor);
+ for (int k = 0; k < size; k++) {
+ madd_v3_v3fl(nor, planes_queue[k], planes_queue[k][3]);
+ }
+ mul_v3_m3v3(nor, mat, nor);
+
+ if (!disable_boundary_fix) {
+ /* Figure out if the approximate boundary fix can get use here. */
+ float greatest_angle_cos = 1.0f;
+ for (uint k = 0; k < 2; k++) {
+ for (uint m = 2; m < size; m++) {
+ float p = dot_v3v3(planes_queue[m], planes_queue[k]);
+ if (p < greatest_angle_cos) {
+ greatest_angle_cos = p;
}
}
}
- add_v3_v3(face_nors[best], normals_queue[best_group]);
- normalize_v3(face_nors[best]);
- nor_ofs[best] = (nor_ofs[best] + normals_queue[best_group][3]) * 0.5f;
- queue_index--;
- memmove(normals_queue + best_group,
- normals_queue + best_group + 1,
- (queue_index - best_group) * sizeof(*normals_queue));
+ if (greatest_angle_cos > boundary_fix_threshold) {
+ approximate_free_direction = true;
+ }
+ else {
+ disable_boundary_fix = true;
+ }
}
}
- MEM_freeN(normals_queue);
-
- /* When up to 3 constraint normals are found. */
- if (ELEM(face_nors_len, 2, 3)) {
- const float q = dot_v3v3(face_nors[0], face_nors[1]);
+ else if (size > 1) {
+ /* When up to 3 constraint normals are found, there is a simple solution. */
+ const float stop_explosion = 0.999f - fabsf(smd->offset_fac) * 0.05f;
+ const float q = dot_v3v3(planes_queue[0], planes_queue[1]);
float d = 1.0f - q * q;
- cross_v3_v3v3(move_nor, face_nors[0], face_nors[1]);
+ cross_v3_v3v3(move_nor, planes_queue[0], planes_queue[1]);
+ normalize_v3(move_nor);
if (d > FLT_EPSILON * 10 && q < stop_explosion) {
d = 1.0f / d;
- mul_v3_fl(face_nors[0], (nor_ofs[0] - nor_ofs[1] * q) * d);
- mul_v3_fl(face_nors[1], (nor_ofs[1] - nor_ofs[0] * q) * d);
+ mul_v3_fl(planes_queue[0], (planes_queue[0][3] - planes_queue[1][3] * q) * d);
+ mul_v3_fl(planes_queue[1], (planes_queue[1][3] - planes_queue[0][3] * q) * d);
}
else {
d = 1.0f / (fabsf(q) + 1.0f);
- mul_v3_fl(face_nors[0], nor_ofs[0] * d);
- mul_v3_fl(face_nors[1], nor_ofs[1] * d);
+ mul_v3_fl(planes_queue[0], planes_queue[0][3] * d);
+ mul_v3_fl(planes_queue[1], planes_queue[1][3] * d);
}
- add_v3_v3v3(nor, face_nors[0], face_nors[1]);
- if (face_nors_len == 3) {
- float *free_nor = move_nor;
- mul_v3_fl(face_nors[2], nor_ofs[2]);
- d = dot_v3v3(face_nors[2], free_nor);
- if (LIKELY(fabsf(d) > FLT_EPSILON)) {
- sub_v3_v3v3(face_nors[0], nor, face_nors[2]); /* Override face_nor[0]. */
- mul_v3_fl(free_nor, dot_v3v3(face_nors[2], face_nors[0]) / d);
- sub_v3_v3(nor, free_nor);
+ add_v3_v3v3(nor, planes_queue[0], planes_queue[1]);
+ if (size == 3) {
+ d = dot_v3v3(planes_queue[2], move_nor);
+ /* The following threshold ignores the third plane if it is almost orthogonal to
+ * the still free direction. */
+ if (fabsf(d) > 0.02f) {
+ float tmp[3];
+ madd_v3_v3v3fl(tmp, nor, planes_queue[2], -planes_queue[2][3]);
+ mul_v3_v3fl(tmp, move_nor, dot_v3v3(planes_queue[2], tmp) / d);
+ sub_v3_v3(nor, tmp);
+ /* Disable boundary fix if the constraints would be majorly unsatisfied. */
+ if (fabsf(d) > 1.0f - boundary_fix_threshold) {
+ disable_boundary_fix = true;
+ }
}
+ }
+ approximate_free_direction = false;
+ }
+ else if (size == 1) {
+ /* Face corner case. */
+ mul_v3_v3fl(nor, planes_queue[0], planes_queue[0][3]);
+ if (g->edges_len > 2) {
disable_boundary_fix = true;
+ approximate_free_direction = true;
}
}
else {
- BLI_assert(face_nors_len < 2);
- mul_v3_v3fl(nor, face_nors[0], nor_ofs[0]);
+ /* Fallback case for null faces. */
+ mul_v3_v3fl(nor, fallback_nor, fallback_ofs);
disable_boundary_fix = true;
}
+ MEM_freeN(planes_queue);
}
/* Fixed/Even Method. */
else {
@@ -1707,26 +1754,29 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
}
/* Set move_nor for boundary fix. */
if (!disable_boundary_fix && g->edges_len > 2) {
- edge_ptr = g->edges + 1;
- float tmp[3];
- uint k;
- for (k = 1; k + 1 < g->edges_len; k++, edge_ptr++) {
- MEdge *e = orig_medge + (*edge_ptr)->old_edge;
- sub_v3_v3v3(
- tmp, orig_mvert_co[vm[e->v1] == i ? e->v2 : e->v1], orig_mvert_co[i]);
- add_v3_v3(move_nor, tmp);
- }
- if (k == 1) {
- disable_boundary_fix = true;
- }
- else {
- disable_boundary_fix = normalize_v3(move_nor) == 0.0f;
- }
+ approximate_free_direction = true;
}
else {
disable_boundary_fix = true;
}
}
+ if (approximate_free_direction) {
+ /* Set move_nor for boundary fix. */
+ NewEdgeRef **edge_ptr = g->edges + 1;
+ float tmp[3];
+ int k;
+ for (k = 1; k + 1 < g->edges_len; k++, edge_ptr++) {
+ MEdge *e = orig_medge + (*edge_ptr)->old_edge;
+ sub_v3_v3v3(tmp, orig_mvert_co[vm[e->v1] == i ? e->v2 : e->v1], orig_mvert_co[i]);
+ add_v3_v3(move_nor, tmp);
+ }
+ if (k == 1) {
+ disable_boundary_fix = true;
+ }
+ else {
+ disable_boundary_fix = normalize_v3(move_nor) == 0.0f;
+ }
+ }
/* Fix boundary verts. */
if (!disable_boundary_fix) {
/* Constraint normal, nor * constr_nor == 0 after this fix. */
@@ -1743,8 +1793,11 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
orig_mvert_co[i]);
if (smd->nonmanifold_boundary_mode == MOD_SOLIDIFY_NONMANIFOLD_BOUNDARY_MODE_FLAT) {
cross_v3_v3v3(constr_nor, e0, e1);
+ normalize_v3(constr_nor);
}
else {
+ BLI_assert(smd->nonmanifold_boundary_mode ==
+ MOD_SOLIDIFY_NONMANIFOLD_BOUNDARY_MODE_ROUND);
float f0[3];
float f1[3];
if (g->edges[0]->faces[0]->reversed) {
@@ -1766,9 +1819,11 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md,
normalize_v3(n0);
normalize_v3(n1);
add_v3_v3v3(constr_nor, n0, n1);
+ normalize_v3(constr_nor);
}
float d = dot_v3v3(constr_nor, move_nor);
- if (LIKELY(fabsf(d) > FLT_EPSILON)) {
+ /* Only allow the thickness to increase about 10 times. */
+ if (fabsf(d) > 0.1f) {
mul_v3_fl(move_nor, dot_v3v3(constr_nor, nor) / d);
sub_v3_v3(nor, move_nor);
}
diff --git a/source/blender/modifiers/intern/MOD_subsurf.c b/source/blender/modifiers/intern/MOD_subsurf.c
index cad36959f2b..b791e28d15b 100644
--- a/source/blender/modifiers/intern/MOD_subsurf.c
+++ b/source/blender/modifiers/intern/MOD_subsurf.c
@@ -234,7 +234,8 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
* assigned at this stage of modifier stack evaluation. */
const bool is_editmode = (mesh->edit_mesh != NULL);
const int required_mode = BKE_subsurf_modifier_eval_required_mode(is_render_mode, is_editmode);
- if (BKE_subsurf_modifier_can_do_gpu_subdiv_ex(scene, ctx->object, smd, required_mode, false)) {
+ if (BKE_subsurf_modifier_can_do_gpu_subdiv_ex(
+ scene, ctx->object, mesh, smd, required_mode, false)) {
subdiv_cache_cpu_evaluation_settings(ctx, mesh, smd);
return result;
}
@@ -246,9 +247,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *
/* Happens on bad topology, but also on empty input mesh. */
return result;
}
- const bool use_clnors = (smd->flags & eSubsurfModifierFlag_UseCustomNormals) &&
- (mesh->flag & ME_AUTOSMOOTH) &&
- CustomData_has_layer(&mesh->ldata, CD_CUSTOMLOOPNORMAL);
+ const bool use_clnors = BKE_subsurf_modifier_use_custom_loop_normals(smd, mesh);
if (use_clnors) {
/* If custom normals are present and the option is turned on calculate the split
* normals and clear flag so the normals get interpolated to the result mesh. */
@@ -412,6 +411,13 @@ static void panel_draw(const bContext *C, Panel *panel)
uiItemR(layout, ptr, "show_only_control_edges", 0, NULL, ICON_NONE);
+ SubsurfModifierData *smd = ptr->data;
+ Object *ob = ob_ptr.data;
+ Mesh *mesh = ob->data;
+ if (BKE_subsurf_modifier_force_disable_gpu_evaluation_for_mesh(smd, mesh)) {
+ uiItemL(layout, "Autosmooth or custom normals detected, disabling GPU subdivision", ICON_INFO);
+ }
+
modifier_panel_end(layout, ptr);
}
diff --git a/source/blender/modifiers/intern/MOD_ui_common.c b/source/blender/modifiers/intern/MOD_ui_common.c
index 94482742831..90652c180c6 100644
--- a/source/blender/modifiers/intern/MOD_ui_common.c
+++ b/source/blender/modifiers/intern/MOD_ui_common.c
@@ -324,7 +324,7 @@ static void modifier_panel_header(const bContext *C, Panel *panel)
buttons_number++;
}
} /* Tessellation point for curve-typed objects. */
- else if (ELEM(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
+ else if (ELEM(ob->type, OB_CURVES_LEGACY, OB_SURF, OB_FONT)) {
/* Some modifiers can work with pre-tessellated curves only. */
if (ELEM(md->type, eModifierType_Hook, eModifierType_Softbody, eModifierType_MeshDeform)) {
/* Add button (appearing to be ON) and add tip why this can't be changed. */
diff --git a/source/blender/modifiers/intern/MOD_util.c b/source/blender/modifiers/intern/MOD_util.c
index 41b600e386b..a8c52108cc0 100644
--- a/source/blender/modifiers/intern/MOD_util.c
+++ b/source/blender/modifiers/intern/MOD_util.c
@@ -204,7 +204,7 @@ Mesh *MOD_deform_mesh_eval_get(Object *ob,
BKE_mesh_orco_ensure(ob, mesh);
}
}
- else if (ELEM(ob->type, OB_FONT, OB_CURVE, OB_SURF)) {
+ else if (ELEM(ob->type, OB_FONT, OB_CURVES_LEGACY, OB_SURF)) {
/* TODO(sybren): get evaluated mesh from depsgraph once
* that's properly generated for curves. */
mesh = BKE_mesh_new_nomain_from_curve(ob);
diff --git a/source/blender/modifiers/intern/MOD_uvproject.c b/source/blender/modifiers/intern/MOD_uvproject.c
index 51ec0a46d32..d6f493267f8 100644
--- a/source/blender/modifiers/intern/MOD_uvproject.c
+++ b/source/blender/modifiers/intern/MOD_uvproject.c
@@ -285,9 +285,6 @@ static Mesh *uvprojectModifier_do(UVProjectModifierData *umd,
mesh->runtime.is_original = false;
- /* Mark tessellated CD layers as dirty. */
- mesh->runtime.cd_dirty_vert |= CD_MASK_TESSLOOPNORMAL;
-
return mesh;
}
diff --git a/source/blender/modifiers/intern/MOD_volume_displace.cc b/source/blender/modifiers/intern/MOD_volume_displace.cc
index 3e71d1fb106..5ce76046294 100644
--- a/source/blender/modifiers/intern/MOD_volume_displace.cc
+++ b/source/blender/modifiers/intern/MOD_volume_displace.cc
@@ -189,10 +189,8 @@ struct DisplaceGridOp {
template<typename GridType> void operator()()
{
- if constexpr (blender::is_same_any_v<GridType,
- openvdb::points::PointDataGrid,
- openvdb::StringGrid,
- openvdb::MaskGrid>) {
+ if constexpr (blender::
+ is_same_any_v<GridType, openvdb::points::PointDataGrid, openvdb::MaskGrid>) {
/* We don't support displacing these grid types yet. */
return;
}
diff --git a/source/blender/modifiers/intern/MOD_weightvgmix.c b/source/blender/modifiers/intern/MOD_weightvgmix.c
index 1078ebfaeb2..1b6472e2d42 100644
--- a/source/blender/modifiers/intern/MOD_weightvgmix.c
+++ b/source/blender/modifiers/intern/MOD_weightvgmix.c
@@ -105,6 +105,12 @@ static float mix_weight(float weight, float weight2, char mix_mode)
if (mix_mode == MOD_WVG_MIX_AVG) {
return (weight + weight2) * 0.5f;
}
+ if (mix_mode == MOD_WVG_MIX_MIN) {
+ return (weight < weight2 ? weight : weight2);
+ }
+ if (mix_mode == MOD_WVG_MIX_MAX) {
+ return (weight > weight2 ? weight : weight2);
+ }
return weight2;
}