diff options
author | Germano <germano.costa@ig.com.br> | 2017-11-06 19:14:07 +0300 |
---|---|---|
committer | Germano <germano.costa@ig.com.br> | 2017-11-06 19:14:07 +0300 |
commit | 5d70e847dd6f5182fa67c3b08260fbb5366009b5 (patch) | |
tree | 1456cfbc4cb11214f5ecff1e65a1719c08b44bd0 /source/blender/draw | |
parent | 7082bd1f4ca4516109dba72506d33d1c65bc2e35 (diff) |
Fix T51604: Support Auto-Smooth in Edit-Mesh
and allocate loop_normals in MeshRenderData instead of CustomData
Differential Revision: D2907
Diffstat (limited to 'source/blender/draw')
-rw-r--r-- | source/blender/draw/intern/draw_cache_impl_mesh.c | 91 |
1 files changed, 65 insertions, 26 deletions
diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.c b/source/blender/draw/intern/draw_cache_impl_mesh.c index 615b79328b6..8cd0c13faec 100644 --- a/source/blender/draw/intern/draw_cache_impl_mesh.c +++ b/source/blender/draw/intern/draw_cache_impl_mesh.c @@ -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); + float (*lnors)[3] = rdata->loop_normals; + if (rdata->edit_bmesh) { - mesh_render_data_ensure_poly_normals_pack(rdata); - mesh_render_data_ensure_vert_normals_pack(rdata); + Gwn_PackedNormal *pnors_pack, *vnors_pack; - Gwn_PackedNormal *pnors_pack = rdata->poly_normals_pack; - Gwn_PackedNormal *vnors_pack = rdata->vert_normals_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++) { + 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[vtri[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); |