Page MenuHome
Paste P1328

Experemental moving split-normal calculation out of draw manager mesh extraction.
ActivePublic

Authored by Campbell Barton (campbellbarton) on Apr 6 2020, 4:00 AM.
diff --git a/source/blender/blenkernel/BKE_editmesh_cache.h b/source/blender/blenkernel/BKE_editmesh_cache.h
index 6c812098b2e..5f80fb8bb09 100644
--- a/source/blender/blenkernel/BKE_editmesh_cache.h
+++ b/source/blender/blenkernel/BKE_editmesh_cache.h
@@ -29,6 +29,10 @@ struct BMEditMesh;
struct EditMeshData;
void BKE_editmesh_cache_ensure_poly_normals(struct BMEditMesh *em, struct EditMeshData *emd);
+void BKE_editmesh_cache_ensure_loop_normals(struct BMEditMesh *em,
+ struct EditMeshData *emd,
+ const bool is_autosmooth,
+ const float split_angle);
void BKE_editmesh_cache_ensure_vert_normals(struct BMEditMesh *em, struct EditMeshData *emd);
void BKE_editmesh_cache_ensure_poly_centers(struct BMEditMesh *em, struct EditMeshData *emd);
diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c
index 1293a33b1dc..e0024bd99dc 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.c
+++ b/source/blender/blenkernel/intern/DerivedMesh.c
@@ -48,6 +48,7 @@
#include "BKE_colorband.h"
#include "BKE_deform.h"
#include "BKE_editmesh.h"
+#include "BKE_editmesh_cache.h"
#include "BKE_key.h"
#include "BKE_layer.h"
#include "BKE_lib_id.h"
@@ -1390,21 +1391,14 @@ bool editbmesh_modifier_is_enabled(Scene *scene, ModifierData *md, bool has_prev
return true;
}
-
-static void editbmesh_calc_modifier_final_normals(const Mesh *mesh_input,
- const CustomData_MeshMasks *final_datamask,
- Mesh *mesh_final)
+static void editbmesh_calc_modifier_final_normals__mdata(
+ const Mesh *UNUSED(mesh_input),
+ const CustomData_MeshMasks *final_datamask,
+ Mesh *mesh_final,
+ const bool do_loop_normals,
+ const bool do_poly_normals)
{
- if (mesh_final->runtime.geom_type != ME_GEOMTYPE_MDATA) {
- /* Generated at draw time. */
- return;
- }
-
- const bool do_loop_normals = ((mesh_input->flag & ME_AUTOSMOOTH) != 0 ||
- (final_datamask->lmask & CD_MASK_NORMAL) != 0);
- /* Some modifiers may need this info from their target (other) object,
- * simpler to generate it here as well. */
- const bool do_poly_normals = ((final_datamask->pmask & CD_MASK_NORMAL) != 0);
+ BLI_assert(mesh_final->runtime.geom_type == ME_GEOMTYPE_MDATA);
/* In case we also need poly normals, add the layer and compute them here
* (BKE_mesh_calc_normals_split() assumes that if that data exists, it is always valid). */
@@ -1452,6 +1446,58 @@ static void editbmesh_calc_modifier_final_normals(const Mesh *mesh_input,
}
}
+static void editbmesh_calc_modifier_final_normals__bmesh(
+ const Mesh *mesh_input,
+ const CustomData_MeshMasks *UNUSED(final_datamask),
+ Mesh *mesh_final,
+ const bool do_loop_normals,
+ const bool UNUSED(do_poly_normals))
+{
+ BLI_assert(mesh_final->runtime.geom_type == ME_GEOMTYPE_BMESH);
+ BMEditMesh *em = mesh_final->edit_mesh;
+ EditMeshData *emd = mesh_final->runtime.edit_data;
+
+ /* The draw manager always uses these, don't check any flags. */
+ if (emd->vertexCos != NULL) {
+ BKE_editmesh_cache_ensure_vert_normals(em, emd);
+ BKE_editmesh_cache_ensure_poly_normals(em, emd);
+ }
+
+ if (do_loop_normals) {
+ const bool is_auto_smooth = (mesh_input->flag & ME_AUTOSMOOTH) != 0;
+ const float split_angle = is_auto_smooth ? mesh_input->smoothresh : (float)M_PI;
+ BKE_editmesh_cache_ensure_loop_normals(em, emd, is_auto_smooth, split_angle);
+ }
+
+ /* same as mesh_calc_modifiers (if using loop normals, poly nors have already been computed). */
+ if (!do_loop_normals) {
+ BKE_mesh_ensure_normals_for_display(mesh_final);
+ }
+}
+
+static void editbmesh_calc_modifier_final_normals(const Mesh *mesh_input,
+ const CustomData_MeshMasks *final_datamask,
+ Mesh *mesh_final)
+{
+ const bool do_loop_normals = ((mesh_input->flag & ME_AUTOSMOOTH) != 0 ||
+ (final_datamask->lmask & CD_MASK_NORMAL) != 0);
+ /* Some modifiers may need this info from their target (other) object,
+ * simpler to generate it here as well. */
+ const bool do_poly_normals = ((final_datamask->pmask & CD_MASK_NORMAL) != 0);
+
+ switch ((eMeshGeomType)mesh_final->runtime.geom_type) {
+ case ME_GEOMTYPE_MDATA:
+ editbmesh_calc_modifier_final_normals__mdata(
+ mesh_input, final_datamask, mesh_final, do_loop_normals, do_poly_normals);
+ return;
+ case ME_GEOMTYPE_BMESH:
+ editbmesh_calc_modifier_final_normals__bmesh(
+ mesh_input, final_datamask, mesh_final, do_loop_normals, do_poly_normals);
+ return;
+ }
+ BLI_assert(0);
+}
+
static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph,
Scene *scene,
Object *ob,
diff --git a/source/blender/blenkernel/intern/editmesh_cache.c b/source/blender/blenkernel/intern/editmesh_cache.c
index bee31d4990a..cdf99abcfed 100644
--- a/source/blender/blenkernel/intern/editmesh_cache.c
+++ b/source/blender/blenkernel/intern/editmesh_cache.c
@@ -62,6 +62,45 @@ void BKE_editmesh_cache_ensure_poly_normals(BMEditMesh *em, EditMeshData *emd)
emd->polyNos = (const float(*)[3])polyNos;
}
+void BKE_editmesh_cache_ensure_loop_normals(BMEditMesh *em,
+ EditMeshData *emd,
+ bool is_auto_smooth,
+ float split_angle)
+{
+ printf("Running\n");
+ if (emd->loopNos != NULL) {
+ return;
+ }
+
+ const float(*vertexCos)[3] = NULL;
+ const float(*vertexNos)[3] = NULL;
+ const float(*polyNos)[3] = NULL;
+
+ if (emd->vertexCos != NULL) {
+ BKE_editmesh_cache_ensure_poly_normals(em, emd);
+ BKE_editmesh_cache_ensure_vert_normals(em, emd);
+
+ vertexCos = emd->vertexCos;
+ vertexNos = emd->vertexNos;
+ polyNos = emd->polyNos;
+ }
+
+ float(*loopNos)[3] = MEM_mallocN(sizeof(*loopNos) * em->bm->totloop, __func__);
+ int clnors_offset = CustomData_get_offset(&em->bm->ldata, CD_CUSTOMLOOPNORMAL);
+ BM_loops_calc_normal_vcos(em->bm,
+ vertexCos,
+ vertexNos,
+ polyNos,
+ is_auto_smooth,
+ split_angle,
+ loopNos,
+ NULL,
+ NULL,
+ clnors_offset,
+ false);
+ emd->loopNos = loopNos;
+}
+
void BKE_editmesh_cache_ensure_vert_normals(BMEditMesh *em, EditMeshData *emd)
{
if (!(emd->vertexCos && (emd->vertexNos == NULL))) {
diff --git a/source/blender/blenkernel/intern/mesh_runtime.c b/source/blender/blenkernel/intern/mesh_runtime.c
index aa3586d1e3d..1ae3a21b042 100644
--- a/source/blender/blenkernel/intern/mesh_runtime.c
+++ b/source/blender/blenkernel/intern/mesh_runtime.c
@@ -220,6 +220,9 @@ bool BKE_mesh_runtime_clear_edit_data(Mesh *mesh)
if (mesh->runtime.edit_data->vertexNos != NULL) {
MEM_freeN((void *)mesh->runtime.edit_data->vertexNos);
}
+ if (mesh->runtime.edit_data->loopNos != NULL) {
+ MEM_freeN((void *)mesh->runtime.edit_data->loopNos);
+ }
MEM_SAFE_FREE(mesh->runtime.edit_data);
return true;
diff --git a/source/blender/draw/intern/draw_cache_extract_mesh.c b/source/blender/draw/intern/draw_cache_extract_mesh.c
index 28cf15400d4..5f18aaf1a34 100644
--- a/source/blender/draw/intern/draw_cache_extract_mesh.c
+++ b/source/blender/draw/intern/draw_cache_extract_mesh.c
@@ -112,6 +112,7 @@ typedef struct MeshRenderData {
const float (*bm_vert_normals)[3];
const float (*bm_poly_normals)[3];
const float (*bm_poly_centers)[3];
+ const float (*bm_loop_normals)[3];
int *v_origindex, *e_origindex, *p_origindex;
int crease_ofs;
@@ -172,6 +173,7 @@ static MeshRenderData *mesh_render_data_create(Mesh *me,
mr->bm_vert_normals = mr->edit_data->vertexNos;
mr->bm_poly_normals = mr->edit_data->polyNos;
mr->bm_poly_centers = mr->edit_data->polyCos;
+ mr->bm_loop_normals = mr->edit_data->loopNos;
}
bool has_mdata = (mr->me->runtime.geom_type == ME_GEOMTYPE_MDATA);
@@ -333,19 +335,20 @@ static MeshRenderData *mesh_render_data_create(Mesh *me,
/* Use bmface->no instead. */
}
if (((data_flag & MR_DATA_LOOP_NOR) && is_auto_smooth) || (data_flag & MR_DATA_TAN_LOOP_NOR)) {
- mr->loop_normals = MEM_mallocN(sizeof(*mr->loop_normals) * mr->loop_len, __func__);
- int clnors_offset = CustomData_get_offset(&mr->bm->ldata, CD_CUSTOMLOOPNORMAL);
- BM_loops_calc_normal_vcos(mr->bm,
- NULL,
- NULL,
- NULL,
- is_auto_smooth,
- split_angle,
- mr->loop_normals,
- NULL,
- NULL,
- clnors_offset,
- false);
+ /* This isn't const, but it's never modified. */
+ printf("Using ");
+ mr->loop_normals = (void *)mr->bm_loop_normals;
+#ifdef DEBUG
+ if (mr->loop_normals == NULL) {
+ printf(
+ "%s: error, 'editbmesh_calc_modifier_final_normals' "
+ "should have calculated loop normals.\n",
+ __func__);
+ }
+ else {
+ printf("OK");
+ }
+#endif
}
if ((iter_type & MR_ITER_LOOPTRI) || (data_flag & MR_DATA_LOOPTRI)) {
/* Edit mode ensures this is valid, no need to calculate. */
@@ -389,8 +392,9 @@ static void mesh_render_data_free(MeshRenderData *mr)
{
MEM_SAFE_FREE(mr->mlooptri);
MEM_SAFE_FREE(mr->poly_normals);
- MEM_SAFE_FREE(mr->loop_normals);
-
+ if (mr->loop_normals != mr->bm_loop_normals) {
+ MEM_SAFE_FREE(mr->loop_normals);
+ }
MEM_SAFE_FREE(mr->lverts);
MEM_SAFE_FREE(mr->ledges);
diff --git a/source/blender/makesdna/DNA_mesh_types.h b/source/blender/makesdna/DNA_mesh_types.h
index 5ca84f87722..6da9969d52d 100644
--- a/source/blender/makesdna/DNA_mesh_types.h
+++ b/source/blender/makesdna/DNA_mesh_types.h
@@ -59,6 +59,7 @@ typedef struct EditMeshData {
/** lazy initialize (when \a vertexCos is set) */
float const (*vertexNos)[3];
float const (*polyNos)[3];
+ float const (*loopNos)[3];
/** also lazy init but dont depend on \a vertexCos */
const float (*polyCos)[3];