Fix T51604: Support Auto-Smooth in Edit-Mesh

and allocate loop_normals in MeshRenderData instead of CustomData

Differential Revision: D2907
This commit is contained in:
Germano Cavalcante 2017-11-06 14:14:07 -02:00
parent 7082bd1f4c
commit 5d70e847dd
Notes: blender-bot 2023-02-14 10:11:49 +01:00
Referenced by issue #51604, Mesh/Edit-Mesh Auto-Smooth Split Normal Support
1 changed files with 66 additions and 27 deletions

View File

@ -339,6 +339,33 @@ static void mesh_cd_calc_used_gpu_layers(
}
}
static void mesh_render_calc_normals_loop_and_poly(const Mesh *me, const float split_angle, MeshRenderData *rdata)
{
BLI_assert((me->flag & ME_AUTOSMOOTH) != 0);
int totloop = me->totloop;
int totpoly = me->totpoly;
float (*loop_normals)[3] = MEM_mallocN(sizeof(*loop_normals) * totloop, __func__);
float (*poly_normals)[3] = MEM_mallocN(sizeof(*poly_normals) * totpoly, __func__);
short (*clnors)[2] = CustomData_get_layer(&me->ldata, CD_CUSTOMLOOPNORMAL);
BKE_mesh_calc_normals_poly(
me->mvert, NULL, me->totvert,
me->mloop, me->mpoly, totloop, totpoly, poly_normals, false);
BKE_mesh_normals_loop_split(
me->mvert, me->totvert, me->medge, me->totedge,
me->mloop, loop_normals, totloop, me->mpoly, poly_normals, totpoly,
true, split_angle, NULL, clnors, NULL);
rdata->loop_len = totloop;
rdata->poly_len = totpoly;
rdata->loop_normals = loop_normals;
rdata->poly_normals = poly_normals;
}
/**
* TODO(campbell): 'gpumat_array' may include materials linked to the object.
* While not default, object materials should be supported.
@ -354,6 +381,9 @@ static MeshRenderData *mesh_render_data_create_ex(
CustomData_reset(&rdata->cd.output.ldata);
const bool is_auto_smooth = (me->flag & ME_AUTOSMOOTH) != 0;
const float split_angle = is_auto_smooth ? me->smoothresh : (float)M_PI;
if (me->edit_btmesh) {
BMEditMesh *embm = me->edit_btmesh;
BMesh *bm = embm->bm;
@ -374,7 +404,12 @@ static MeshRenderData *mesh_render_data_create_ex(
rdata->tri_len = embm->tottri;
}
if (types & MR_DATATYPE_LOOP) {
rdata->loop_len = bm->totloop;
int totloop = bm->totloop;
if (is_auto_smooth) {
rdata->loop_normals = MEM_mallocN(sizeof(*rdata->loop_normals) * totloop, __func__);
BM_loops_calc_normal_vcos(bm, NULL, NULL, NULL, true, split_angle, rdata->loop_normals, NULL, NULL, -1);
}
rdata->loop_len = totloop;
bm_ensure_types |= BM_LOOP;
}
if (types & MR_DATATYPE_POLY) {
@ -447,12 +482,12 @@ static MeshRenderData *mesh_render_data_create_ex(
BKE_mesh_recalc_looptri(me->mloop, me->mpoly, me->mvert, me->totloop, me->totpoly, rdata->mlooptri);
}
if (types & MR_DATATYPE_LOOP) {
if (me->flag & ME_AUTOSMOOTH) {
BKE_mesh_calc_normals_split(me);
rdata->loop_normals = CustomData_get_layer(&me->ldata, CD_NORMAL);
}
rdata->loop_len = me->totloop;
rdata->mloop = CustomData_get_layer(&me->ldata, CD_MLOOP);
if (is_auto_smooth) {
mesh_render_calc_normals_loop_and_poly(me, split_angle, rdata);
}
}
if (types & MR_DATATYPE_POLY) {
rdata->poly_len = me->totpoly;
@ -538,8 +573,6 @@ static MeshRenderData *mesh_render_data_create_ex(
rdata->orco = NULL;
}
const bool is_auto_smooth = (me->flag & ME_AUTOSMOOTH) != 0;
/* don't access mesh directly, instead use vars taken from BMesh or Mesh */
#define me DONT_USE_THIS
#ifdef me /* quiet warning */
@ -665,8 +698,10 @@ static MeshRenderData *mesh_render_data_create_ex(
BMesh *bm = em->bm;
if (is_auto_smooth && rdata->loop_normals == NULL) {
/* TODO: split normals, see below */
rdata->loop_normals = CustomData_get_layer(cd_ldata, CD_NORMAL);
/* Should we store the previous array of `loop_normals` in somewhere? */
rdata->loop_len = bm->totloop;
rdata->loop_normals = MEM_mallocN(sizeof(*rdata->loop_normals) * rdata->loop_len, __func__);
BM_loops_calc_normal_vcos(bm, NULL, NULL, NULL, true, split_angle, rdata->loop_normals, NULL, NULL, -1);
}
bool calc_active_tangent = false;
@ -683,10 +718,8 @@ static MeshRenderData *mesh_render_data_create_ex(
#undef me
if (is_auto_smooth && rdata->loop_normals == NULL) {
if (!CustomData_has_layer(cd_ldata, CD_NORMAL)) {
BKE_mesh_calc_normals_split(me);
}
rdata->loop_normals = CustomData_get_layer(cd_ldata, CD_NORMAL);
/* Should we store the previous array of `loop_normals` in CustomData? */
mesh_render_calc_normals_loop_and_poly(me, split_angle, rdata);
}
bool calc_active_tangent = false;
@ -777,6 +810,7 @@ static void mesh_render_data_free(MeshRenderData *rdata)
MEM_SAFE_FREE(rdata->loose_edges);
MEM_SAFE_FREE(rdata->edges_adjacent_polys);
MEM_SAFE_FREE(rdata->mlooptri);
MEM_SAFE_FREE(rdata->loop_normals);
MEM_SAFE_FREE(rdata->poly_normals);
MEM_SAFE_FREE(rdata->poly_normals_pack);
MEM_SAFE_FREE(rdata->vert_normals_pack);
@ -1981,12 +2015,18 @@ static Gwn_VertBuf *mesh_batch_cache_get_tri_pos_and_normals_ex(
GWN_vertbuf_attr_get_raw_data(vbo, attr_id.pos, &pos_step);
GWN_vertbuf_attr_get_raw_data(vbo, attr_id.nor, &nor_step);
if (rdata->edit_bmesh) {
mesh_render_data_ensure_poly_normals_pack(rdata);
mesh_render_data_ensure_vert_normals_pack(rdata);
float (*lnors)[3] = rdata->loop_normals;
Gwn_PackedNormal *pnors_pack = rdata->poly_normals_pack;
Gwn_PackedNormal *vnors_pack = rdata->vert_normals_pack;
if (rdata->edit_bmesh) {
Gwn_PackedNormal *pnors_pack, *vnors_pack;
if (lnors == NULL) {
mesh_render_data_ensure_poly_normals_pack(rdata);
mesh_render_data_ensure_vert_normals_pack(rdata);
pnors_pack = rdata->poly_normals_pack;
vnors_pack = rdata->vert_normals_pack;
}
for (int i = 0; i < tri_len; i++) {
const BMLoop **bm_looptri = (const BMLoop **)rdata->edit_bmesh->looptris[i];
@ -1997,15 +2037,15 @@ static Gwn_VertBuf *mesh_batch_cache_get_tri_pos_and_normals_ex(
continue;
}
const uint vtri[3] = {
BM_elem_index_get(bm_looptri[0]->v),
BM_elem_index_get(bm_looptri[1]->v),
BM_elem_index_get(bm_looptri[2]->v),
};
if (BM_elem_flag_test(bm_face, BM_ELEM_SMOOTH)) {
if (lnors) {
for (uint t = 0; t < 3; t++) {
*((Gwn_PackedNormal *)GWN_vertbuf_raw_step(&nor_step)) = vnors_pack[vtri[t]];
const float *nor = lnors[BM_elem_index_get(bm_looptri[t])];
*((Gwn_PackedNormal *)GWN_vertbuf_raw_step(&nor_step)) = GWN_normal_convert_i10_v3(nor);
}
}
else if (BM_elem_flag_test(bm_face, BM_ELEM_SMOOTH)) {
for (uint t = 0; t < 3; t++) {
*((Gwn_PackedNormal *)GWN_vertbuf_raw_step(&nor_step)) = vnors_pack[BM_elem_index_get(bm_looptri[t]->v)];
}
}
else {
@ -2021,7 +2061,6 @@ static Gwn_VertBuf *mesh_batch_cache_get_tri_pos_and_normals_ex(
}
}
else {
float (*lnors)[3] = rdata->loop_normals;
if (lnors == NULL) {
/* Use normals from vertex. */
mesh_render_data_ensure_poly_normals_pack(rdata);