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/blenkernel/intern/mesh_evaluate.c')
-rw-r--r--source/blender/blenkernel/intern/mesh_evaluate.c150
1 files changed, 113 insertions, 37 deletions
diff --git a/source/blender/blenkernel/intern/mesh_evaluate.c b/source/blender/blenkernel/intern/mesh_evaluate.c
index a334951c772..a65ac5151a8 100644
--- a/source/blender/blenkernel/intern/mesh_evaluate.c
+++ b/source/blender/blenkernel/intern/mesh_evaluate.c
@@ -51,6 +51,7 @@
#include "BLI_task.h"
#include "BKE_customdata.h"
+#include "BKE_global.h"
#include "BKE_mesh.h"
#include "BKE_multires.h"
#include "BKE_report.h"
@@ -132,7 +133,7 @@ void BKE_mesh_calc_normals_mapping_ex(
if (only_face_normals == false) {
/* vertex normals are optional, they require some extra calculations,
* so make them optional */
- BKE_mesh_calc_normals_poly(mverts, numVerts, mloop, mpolys, numLoops, numPolys, pnors, false);
+ BKE_mesh_calc_normals_poly(mverts, NULL, numVerts, mloop, mpolys, numLoops, numPolys, pnors, false);
}
else {
/* only calc poly normals */
@@ -221,18 +222,20 @@ static void mesh_calc_normals_poly_accum(
}
void BKE_mesh_calc_normals_poly(
- MVert *mverts, int numVerts,
+ MVert *mverts, float (*r_vertnors)[3], int numVerts,
const MLoop *mloop, const MPoly *mpolys,
int UNUSED(numLoops), int numPolys, float (*r_polynors)[3],
const bool only_face_normals)
{
float (*pnors)[3] = r_polynors;
- float (*tnorms)[3];
+ float (*vnors)[3] = r_vertnors;
+ bool free_vnors = false;
int i;
const MPoly *mp;
if (only_face_normals) {
BLI_assert((pnors != NULL) || (numPolys == 0));
+ BLI_assert(r_vertnors == NULL);
#pragma omp parallel for if (numPolys > BKE_MESH_OMP_LIMIT)
for (i = 0; i < numPolys; i++) {
@@ -242,25 +245,30 @@ void BKE_mesh_calc_normals_poly(
}
/* first go through and calculate normals for all the polys */
- tnorms = MEM_callocN(sizeof(*tnorms) * (size_t)numVerts, __func__);
+ if (vnors == NULL) {
+ vnors = MEM_callocN(sizeof(*vnors) * (size_t)numVerts, __func__);
+ free_vnors = true;
+ }
+ else {
+ memset(vnors, 0, sizeof(*vnors) * (size_t)numVerts);
+ }
+ mp = mpolys;
if (pnors) {
- mp = mpolys;
for (i = 0; i < numPolys; i++, mp++) {
- mesh_calc_normals_poly_accum(mp, mloop + mp->loopstart, mverts, pnors[i], tnorms);
+ mesh_calc_normals_poly_accum(mp, mloop + mp->loopstart, mverts, pnors[i], vnors);
}
}
else {
float tpnor[3]; /* temp poly normal */
- mp = mpolys;
for (i = 0; i < numPolys; i++, mp++) {
- mesh_calc_normals_poly_accum(mp, mloop + mp->loopstart, mverts, tpnor, tnorms);
+ mesh_calc_normals_poly_accum(mp, mloop + mp->loopstart, mverts, tpnor, vnors);
}
}
for (i = 0; i < numVerts; i++) {
MVert *mv = &mverts[i];
- float *no = tnorms[i];
+ float *no = vnors[i];
if (UNLIKELY(normalize_v3(no) == 0.0f)) {
/* following Mesh convention; we use vertex coordinate itself for normal in this case */
@@ -270,7 +278,9 @@ void BKE_mesh_calc_normals_poly(
normal_float_to_short_v3(mv->no, no);
}
- MEM_freeN(tnorms);
+ if (free_vnors) {
+ MEM_freeN(vnors);
+ }
}
void BKE_mesh_calc_normals(Mesh *mesh)
@@ -278,7 +288,7 @@ void BKE_mesh_calc_normals(Mesh *mesh)
#ifdef DEBUG_TIME
TIMEIT_START(BKE_mesh_calc_normals);
#endif
- BKE_mesh_calc_normals_poly(mesh->mvert, mesh->totvert,
+ BKE_mesh_calc_normals_poly(mesh->mvert, NULL, mesh->totvert,
mesh->mloop, mesh->mpoly, mesh->totloop, mesh->totpoly,
NULL, false);
#ifdef DEBUG_TIME
@@ -883,7 +893,9 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data, LoopSpli
clnors_avg[0] /= clnors_nbr;
clnors_avg[1] /= clnors_nbr;
/* Fix/update all clnors of this fan with computed average value. */
- printf("Invalid clnors in this fan!\n");
+ if (G.debug & G_DEBUG) {
+ printf("Invalid clnors in this fan!\n");
+ }
while ((clnor = BLI_SMALLSTACK_POP(clnors))) {
//print_v2("org clnor", clnor);
clnor[0] = (short)clnors_avg[0];
@@ -1338,12 +1350,14 @@ void BKE_mesh_normals_loop_split(
* Compute internal representation of given custom normals (as an array of float[2]).
* It also makes sure the mesh matches those custom normals, by setting sharp edges flag as needed to get a
* same custom lnor for all loops sharing a same smooth fan.
- * If use_vertices if true, custom_loopnors is assumed to be per-vertex, not per-loop
+ * If use_vertices if true, r_custom_loopnors is assumed to be per-vertex, not per-loop
* (this allows to set whole vert's normals at once, useful in some cases).
+ * r_custom_loopnors is expected to have normalized normals, or zero ones, in which case they will be replaced
+ * by default loop/vertex normal.
*/
static void mesh_normals_loop_custom_set(
const MVert *mverts, const int numVerts, MEdge *medges, const int numEdges,
- MLoop *mloops, float (*custom_loopnors)[3], const int numLoops,
+ MLoop *mloops, float (*r_custom_loopnors)[3], const int numLoops,
MPoly *mpolys, const float (*polynors)[3], const int numPolys,
short (*r_clnors_data)[2], const bool use_vertices)
{
@@ -1369,6 +1383,22 @@ static void mesh_normals_loop_custom_set(
mpolys, polynors, numPolys, use_split_normals, split_angle,
&lnors_spacearr, NULL, loop_to_poly);
+ /* Set all given zero vectors to their default value. */
+ if (use_vertices) {
+ for (i = 0; i < numVerts; i++) {
+ if (is_zero_v3(r_custom_loopnors[i])) {
+ normal_short_to_float_v3(r_custom_loopnors[i], mverts[i].no);
+ }
+ }
+ }
+ else {
+ for (i = 0; i < numLoops; i++) {
+ if (is_zero_v3(r_custom_loopnors[i])) {
+ copy_v3_v3(r_custom_loopnors[i], lnors[i]);
+ }
+ }
+ }
+
/* Now, check each current smooth fan (one lnor space per smooth fan!), and if all its matching custom lnors
* are not (enough) equal, add sharp edges as needed.
* This way, next time we run BKE_mesh_normals_loop_split(), we'll get lnor spacearr/smooth fans matching
@@ -1384,7 +1414,9 @@ static void mesh_normals_loop_custom_set(
* Maybe we should set those loops' edges as sharp?
*/
BLI_BITMAP_ENABLE(done_loops, i);
- printf("WARNING! Getting invalid NULL loop space for loop %d!\n", i);
+ if (G.debug & G_DEBUG) {
+ printf("WARNING! Getting invalid NULL loop space for loop %d!\n", i);
+ }
continue;
}
@@ -1406,11 +1438,7 @@ static void mesh_normals_loop_custom_set(
const int lidx = GET_INT_FROM_POINTER(loops->link);
MLoop *ml = &mloops[lidx];
const int nidx = lidx;
- float *nor = custom_loopnors[nidx];
-
- if (is_zero_v3(nor)) {
- nor = lnors[nidx];
- }
+ float *nor = r_custom_loopnors[nidx];
if (!org_nor) {
org_nor = nor;
@@ -1432,7 +1460,26 @@ static void mesh_normals_loop_custom_set(
loops = loops->next;
BLI_BITMAP_ENABLE(done_loops, lidx);
}
- BLI_BITMAP_ENABLE(done_loops, i); /* For single loops, where lnors_spacearr.lspacearr[i]->loops is NULL. */
+
+ /* We also have to check between last and first loops, otherwise we may miss some sharp edges here!
+ * This is just a simplified version of above while loop.
+ * See T45984. */
+ loops = lnors_spacearr.lspacearr[i]->loops;
+ if (loops && org_nor) {
+ const int lidx = GET_INT_FROM_POINTER(loops->link);
+ MLoop *ml = &mloops[lidx];
+ const int nidx = lidx;
+ float *nor = r_custom_loopnors[nidx];
+
+ if (dot_v3v3(org_nor, nor) < LNOR_SPACE_TRIGO_THRESHOLD) {
+ const MPoly *mp = &mpolys[loop_to_poly[lidx]];
+ const MLoop *mlp = &mloops[(lidx == mp->loopstart) ? mp->loopstart + mp->totloop - 1 : lidx - 1];
+ medges[(prev_ml->e == mlp->e) ? prev_ml->e : ml->e].flag |= ME_SHARP;
+ }
+ }
+
+ /* For single loops, where lnors_spacearr.lspacearr[i]->loops is NULL. */
+ BLI_BITMAP_ENABLE(done_loops, i);
}
}
@@ -1450,7 +1497,9 @@ static void mesh_normals_loop_custom_set(
for (i = 0; i < numLoops; i++) {
if (!lnors_spacearr.lspacearr[i]) {
BLI_BITMAP_DISABLE(done_loops, i);
- printf("WARNING! Still getting invalid NULL loop space in second loop for loop %d!\n", i);
+ if (G.debug & G_DEBUG) {
+ printf("WARNING! Still getting invalid NULL loop space in second loop for loop %d!\n", i);
+ }
continue;
}
@@ -1469,11 +1518,7 @@ static void mesh_normals_loop_custom_set(
while (loops) {
const int lidx = GET_INT_FROM_POINTER(loops->link);
const int nidx = use_vertices ? (int)mloops[lidx].v : lidx;
- float *nor = custom_loopnors[nidx];
-
- if (is_zero_v3(nor)) {
- nor = lnors[nidx];
- }
+ float *nor = r_custom_loopnors[nidx];
nbr_nors++;
add_v3_v3(avg_nor, nor);
@@ -1493,7 +1538,7 @@ static void mesh_normals_loop_custom_set(
}
else {
const int nidx = use_vertices ? (int)mloops[i].v : i;
- float *nor = custom_loopnors[nidx];
+ float *nor = r_custom_loopnors[nidx];
BKE_lnor_space_custom_normal_to_data(lnors_spacearr.lspacearr[i], nor, r_clnors_data[i]);
BLI_BITMAP_DISABLE(done_loops, i);
@@ -1509,24 +1554,56 @@ static void mesh_normals_loop_custom_set(
void BKE_mesh_normals_loop_custom_set(
const MVert *mverts, const int numVerts, MEdge *medges, const int numEdges,
- MLoop *mloops, float (*custom_loopnors)[3], const int numLoops,
+ MLoop *mloops, float (*r_custom_loopnors)[3], const int numLoops,
MPoly *mpolys, const float (*polynors)[3], const int numPolys,
short (*r_clnors_data)[2])
{
- mesh_normals_loop_custom_set(mverts, numVerts, medges, numEdges, mloops, custom_loopnors, numLoops,
+ mesh_normals_loop_custom_set(mverts, numVerts, medges, numEdges, mloops, r_custom_loopnors, numLoops,
mpolys, polynors, numPolys, r_clnors_data, false);
}
void BKE_mesh_normals_loop_custom_from_vertices_set(
- const MVert *mverts, float (*custom_vertnors)[3], const int numVerts,
+ const MVert *mverts, float (*r_custom_vertnors)[3], const int numVerts,
MEdge *medges, const int numEdges, MLoop *mloops, const int numLoops,
MPoly *mpolys, const float (*polynors)[3], const int numPolys,
short (*r_clnors_data)[2])
{
- mesh_normals_loop_custom_set(mverts, numVerts, medges, numEdges, mloops, custom_vertnors, numLoops,
+ mesh_normals_loop_custom_set(mverts, numVerts, medges, numEdges, mloops, r_custom_vertnors, numLoops,
mpolys, polynors, numPolys, r_clnors_data, true);
}
+/**
+ * Computes average per-vertex normals from given custom loop normals.
+ *
+ * @param clnors The computed custom loop normals.
+ * @param r_vert_clnors The (already allocated) array where to store averaged per-vertex normals.
+ */
+void BKE_mesh_normals_loop_to_vertex(
+ const int numVerts, const MLoop *mloops, const int numLoops,
+ const float (*clnors)[3], float (*r_vert_clnors)[3])
+{
+ const MLoop *ml;
+ int i;
+
+ int *vert_loops_nbr = MEM_callocN(sizeof(*vert_loops_nbr) * (size_t)numVerts, __func__);
+
+ copy_vn_fl((float *)r_vert_clnors, 3 * numVerts, 0.0f);
+
+ for (i = 0, ml = mloops; i < numLoops; i++, ml++) {
+ const unsigned int v = ml->v;
+
+ add_v3_v3(r_vert_clnors[v], clnors[i]);
+ vert_loops_nbr[v]++;
+ }
+
+ for (i = 0; i < numVerts; i++) {
+ mul_v3_fl(r_vert_clnors[i], 1.0f / (float)vert_loops_nbr[i]);
+ }
+
+ MEM_freeN(vert_loops_nbr);
+}
+
+
#undef LNOR_SPACE_TRIGO_THRESHOLD
/** \} */
@@ -2121,8 +2198,7 @@ void BKE_mesh_calc_volume(
totvol += vol;
}
if (r_center) {
- /* averaging factor 1/4 is applied in the end */
- madd_v3_v3fl(r_center, center, vol); /* XXX could extract this */
+ /* averaging factor 1/3 is applied in the end */
madd_v3_v3fl(r_center, v1->co, vol);
madd_v3_v3fl(r_center, v2->co, vol);
madd_v3_v3fl(r_center, v3->co, vol);
@@ -2137,11 +2213,11 @@ void BKE_mesh_calc_volume(
*r_volume = fabsf(totvol);
}
if (r_center) {
- /* Note: Factor 1/4 is applied once for all vertices here.
+ /* Note: Factor 1/3 is applied once for all vertices here.
* This also automatically negates the vector if totvol is negative.
*/
if (totvol != 0.0f)
- mul_v3_fl(r_center, 0.25f / totvol);
+ mul_v3_fl(r_center, (1.0f / 3.0f) / totvol);
}
}
@@ -3180,7 +3256,7 @@ void BKE_mesh_flush_hidden_from_polys_ex(MVert *mvert,
j = mp->totloop;
for (ml = &mloop[mp->loopstart]; j--; ml++) {
mvert[ml->v].flag &= (char)~ME_HIDE;
- medge[ml->e].flag &= (char)~ME_HIDE;
+ medge[ml->e].flag &= (short)~ME_HIDE;
}
}
}