Changeset View
Changeset View
Standalone View
Standalone View
source/blender/draw/intern/draw_cache_impl_mesh.c
| Show First 20 Lines • Show All 333 Lines • ▼ Show 20 Lines | #endif | ||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| 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. | * TODO(campbell): 'gpumat_array' may include materials linked to the object. | ||||
| * While not default, object materials should be supported. | * While not default, object materials should be supported. | ||||
| * Although this only impacts the data thats generated, not the materials that display. | * Although this only impacts the data thats generated, not the materials that display. | ||||
| */ | */ | ||||
| static MeshRenderData *mesh_render_data_create_ex( | static MeshRenderData *mesh_render_data_create_ex( | ||||
| Mesh *me, const int types, | Mesh *me, const int types, | ||||
| struct GPUMaterial **gpumat_array, uint gpumat_array_len) | struct GPUMaterial **gpumat_array, uint gpumat_array_len) | ||||
| { | { | ||||
| MeshRenderData *rdata = MEM_callocN(sizeof(*rdata), __func__); | MeshRenderData *rdata = MEM_callocN(sizeof(*rdata), __func__); | ||||
| rdata->types = types; | rdata->types = types; | ||||
| rdata->mat_len = mesh_render_mat_len_get(me); | rdata->mat_len = mesh_render_mat_len_get(me); | ||||
| CustomData_reset(&rdata->cd.output.ldata); | 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) { | if (me->edit_btmesh) { | ||||
| BMEditMesh *embm = me->edit_btmesh; | BMEditMesh *embm = me->edit_btmesh; | ||||
| BMesh *bm = embm->bm; | BMesh *bm = embm->bm; | ||||
| rdata->edit_bmesh = embm; | rdata->edit_bmesh = embm; | ||||
| int bm_ensure_types = 0; | int bm_ensure_types = 0; | ||||
| if (types & (MR_DATATYPE_VERT)) { | if (types & (MR_DATATYPE_VERT)) { | ||||
| rdata->vert_len = bm->totvert; | rdata->vert_len = bm->totvert; | ||||
| bm_ensure_types |= BM_VERT; | bm_ensure_types |= BM_VERT; | ||||
| } | } | ||||
| if (types & (MR_DATATYPE_EDGE)) { | if (types & (MR_DATATYPE_EDGE)) { | ||||
| rdata->edge_len = bm->totedge; | rdata->edge_len = bm->totedge; | ||||
| bm_ensure_types |= BM_EDGE; | bm_ensure_types |= BM_EDGE; | ||||
| } | } | ||||
| if (types & MR_DATATYPE_LOOPTRI) { | if (types & MR_DATATYPE_LOOPTRI) { | ||||
| BKE_editmesh_tessface_calc(embm); | BKE_editmesh_tessface_calc(embm); | ||||
| rdata->tri_len = embm->tottri; | rdata->tri_len = embm->tottri; | ||||
| } | } | ||||
| if (types & MR_DATATYPE_LOOP) { | 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; | bm_ensure_types |= BM_LOOP; | ||||
| } | } | ||||
| if (types & MR_DATATYPE_POLY) { | if (types & MR_DATATYPE_POLY) { | ||||
| rdata->poly_len = bm->totface; | rdata->poly_len = bm->totface; | ||||
| bm_ensure_types |= BM_FACE; | bm_ensure_types |= BM_FACE; | ||||
| } | } | ||||
| if (types & MR_DATATYPE_OVERLAY) { | if (types & MR_DATATYPE_OVERLAY) { | ||||
| rdata->efa_act = BM_mesh_active_face_get(bm, false, true); | rdata->efa_act = BM_mesh_active_face_get(bm, false, true); | ||||
| ▲ Show 20 Lines • Show All 56 Lines • ▼ Show 20 Lines | if (types & (MR_DATATYPE_EDGE)) { | ||||
| rdata->medge = CustomData_get_layer(&me->edata, CD_MEDGE); | rdata->medge = CustomData_get_layer(&me->edata, CD_MEDGE); | ||||
| } | } | ||||
| if (types & MR_DATATYPE_LOOPTRI) { | if (types & MR_DATATYPE_LOOPTRI) { | ||||
| const int tri_len = rdata->tri_len = poly_to_tri_count(me->totpoly, me->totloop); | const int tri_len = rdata->tri_len = poly_to_tri_count(me->totpoly, me->totloop); | ||||
| rdata->mlooptri = MEM_mallocN(sizeof(*rdata->mlooptri) * tri_len, __func__); | rdata->mlooptri = MEM_mallocN(sizeof(*rdata->mlooptri) * tri_len, __func__); | ||||
| BKE_mesh_recalc_looptri(me->mloop, me->mpoly, me->mvert, me->totloop, me->totpoly, rdata->mlooptri); | BKE_mesh_recalc_looptri(me->mloop, me->mpoly, me->mvert, me->totloop, me->totpoly, rdata->mlooptri); | ||||
| } | } | ||||
| if (types & MR_DATATYPE_LOOP) { | 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->loop_len = me->totloop; | ||||
| rdata->mloop = CustomData_get_layer(&me->ldata, CD_MLOOP); | 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) { | if (types & MR_DATATYPE_POLY) { | ||||
| rdata->poly_len = me->totpoly; | rdata->poly_len = me->totpoly; | ||||
| rdata->mpoly = CustomData_get_layer(&me->pdata, CD_MPOLY); | rdata->mpoly = CustomData_get_layer(&me->pdata, CD_MPOLY); | ||||
| } | } | ||||
| if (types & MR_DATATYPE_DVERT) { | if (types & MR_DATATYPE_DVERT) { | ||||
| rdata->vert_len = me->totvert; | rdata->vert_len = me->totvert; | ||||
| rdata->dvert = CustomData_get_layer(&me->vdata, CD_MDEFORMVERT); | rdata->dvert = CustomData_get_layer(&me->vdata, CD_MDEFORMVERT); | ||||
| ▲ Show 20 Lines • Show All 69 Lines • ▼ Show 20 Lines | if (cd_vused[CD_ORCO] & 1) { | ||||
| BKE_mesh_orco_verts_transform(me, rdata->orco, rdata->vert_len, 0); | BKE_mesh_orco_verts_transform(me, rdata->orco, rdata->vert_len, 0); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| rdata->orco = NULL; | 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 */ | /* don't access mesh directly, instead use vars taken from BMesh or Mesh */ | ||||
| #define me DONT_USE_THIS | #define me DONT_USE_THIS | ||||
| #ifdef me /* quiet warning */ | #ifdef me /* quiet warning */ | ||||
| #endif | #endif | ||||
| struct { | struct { | ||||
| uint uv_len; | uint uv_len; | ||||
| uint vcol_len; | uint vcol_len; | ||||
| } cd_layers_src = { | } cd_layers_src = { | ||||
| ▲ Show 20 Lines • Show All 109 Lines • ▼ Show 20 Lines | if (rdata->cd.layers.tangent_len != 0) { | ||||
| /* If tangent from orco is requested, decrement tangent_len */ | /* If tangent from orco is requested, decrement tangent_len */ | ||||
| int actual_tangent_len = (cd_lused[CD_TANGENT] & DM_TANGENT_MASK_ORCO) ? | int actual_tangent_len = (cd_lused[CD_TANGENT] & DM_TANGENT_MASK_ORCO) ? | ||||
| rdata->cd.layers.tangent_len - 1 : rdata->cd.layers.tangent_len; | rdata->cd.layers.tangent_len - 1 : rdata->cd.layers.tangent_len; | ||||
| if (rdata->edit_bmesh) { | if (rdata->edit_bmesh) { | ||||
| BMEditMesh *em = rdata->edit_bmesh; | BMEditMesh *em = rdata->edit_bmesh; | ||||
| BMesh *bm = em->bm; | BMesh *bm = em->bm; | ||||
| if (is_auto_smooth && rdata->loop_normals == NULL) { | if (is_auto_smooth && rdata->loop_normals == NULL) { | ||||
| /* TODO: split normals, see below */ | /* Should we store the previous array of `loop_normals` in somewhere? */ | ||||
| rdata->loop_normals = CustomData_get_layer(cd_ldata, CD_NORMAL); | 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; | bool calc_active_tangent = false; | ||||
| BKE_editmesh_loop_tangent_calc( | BKE_editmesh_loop_tangent_calc( | ||||
| em, calc_active_tangent, | em, calc_active_tangent, | ||||
| tangent_names, actual_tangent_len, | tangent_names, actual_tangent_len, | ||||
| rdata->poly_normals, rdata->loop_normals, | rdata->poly_normals, rdata->loop_normals, | ||||
| rdata->orco, | rdata->orco, | ||||
| &rdata->cd.output.ldata, bm->totloop, | &rdata->cd.output.ldata, bm->totloop, | ||||
| &rdata->cd.output.tangent_mask); | &rdata->cd.output.tangent_mask); | ||||
| } | } | ||||
| else { | else { | ||||
| #undef me | #undef me | ||||
| if (is_auto_smooth && rdata->loop_normals == NULL) { | if (is_auto_smooth && rdata->loop_normals == NULL) { | ||||
| if (!CustomData_has_layer(cd_ldata, CD_NORMAL)) { | /* Should we store the previous array of `loop_normals` in CustomData? */ | ||||
| BKE_mesh_calc_normals_split(me); | mesh_render_calc_normals_loop_and_poly(me, split_angle, rdata); | ||||
| } | |||||
| rdata->loop_normals = CustomData_get_layer(cd_ldata, CD_NORMAL); | |||||
| } | } | ||||
| bool calc_active_tangent = false; | bool calc_active_tangent = false; | ||||
| BKE_mesh_calc_loop_tangent_ex( | BKE_mesh_calc_loop_tangent_ex( | ||||
| me->mvert, | me->mvert, | ||||
| me->mpoly, me->totpoly, | me->mpoly, me->totpoly, | ||||
| me->mloop, | me->mloop, | ||||
| ▲ Show 20 Lines • Show All 74 Lines • ▼ Show 20 Lines | static void mesh_render_data_free(MeshRenderData *rdata) | ||||
| MEM_SAFE_FREE(rdata->cd.layers.uv); | MEM_SAFE_FREE(rdata->cd.layers.uv); | ||||
| MEM_SAFE_FREE(rdata->cd.layers.vcol); | MEM_SAFE_FREE(rdata->cd.layers.vcol); | ||||
| MEM_SAFE_FREE(rdata->cd.layers.tangent); | MEM_SAFE_FREE(rdata->cd.layers.tangent); | ||||
| MEM_SAFE_FREE(rdata->cd.layers.auto_vcol); | MEM_SAFE_FREE(rdata->cd.layers.auto_vcol); | ||||
| MEM_SAFE_FREE(rdata->loose_verts); | MEM_SAFE_FREE(rdata->loose_verts); | ||||
| MEM_SAFE_FREE(rdata->loose_edges); | MEM_SAFE_FREE(rdata->loose_edges); | ||||
| MEM_SAFE_FREE(rdata->edges_adjacent_polys); | MEM_SAFE_FREE(rdata->edges_adjacent_polys); | ||||
| MEM_SAFE_FREE(rdata->mlooptri); | MEM_SAFE_FREE(rdata->mlooptri); | ||||
| MEM_SAFE_FREE(rdata->loop_normals); | |||||
| MEM_SAFE_FREE(rdata->poly_normals); | MEM_SAFE_FREE(rdata->poly_normals); | ||||
| MEM_SAFE_FREE(rdata->poly_normals_pack); | MEM_SAFE_FREE(rdata->poly_normals_pack); | ||||
| MEM_SAFE_FREE(rdata->vert_normals_pack); | MEM_SAFE_FREE(rdata->vert_normals_pack); | ||||
| MEM_SAFE_FREE(rdata->vert_weight_color); | MEM_SAFE_FREE(rdata->vert_weight_color); | ||||
| MEM_SAFE_FREE(rdata->edge_select_bool); | MEM_SAFE_FREE(rdata->edge_select_bool); | ||||
| MEM_SAFE_FREE(rdata->vert_color); | MEM_SAFE_FREE(rdata->vert_color); | ||||
| CustomData_free(&rdata->cd.output.ldata, rdata->loop_len); | CustomData_free(&rdata->cd.output.ldata, rdata->loop_len); | ||||
| ▲ Show 20 Lines • Show All 1,188 Lines • ▼ Show 20 Lines | if (*r_vbo == NULL) { | ||||
| const int vbo_len_capacity = tri_len * 3; | const int vbo_len_capacity = tri_len * 3; | ||||
| int vbo_len_used = 0; | int vbo_len_used = 0; | ||||
| GWN_vertbuf_data_alloc(vbo, vbo_len_capacity); | GWN_vertbuf_data_alloc(vbo, vbo_len_capacity); | ||||
| Gwn_VertBufRaw pos_step, nor_step; | Gwn_VertBufRaw pos_step, nor_step; | ||||
| GWN_vertbuf_attr_get_raw_data(vbo, attr_id.pos, &pos_step); | GWN_vertbuf_attr_get_raw_data(vbo, attr_id.pos, &pos_step); | ||||
| GWN_vertbuf_attr_get_raw_data(vbo, attr_id.nor, &nor_step); | GWN_vertbuf_attr_get_raw_data(vbo, attr_id.nor, &nor_step); | ||||
| float (*lnors)[3] = rdata->loop_normals; | |||||
| if (rdata->edit_bmesh) { | 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_poly_normals_pack(rdata); | ||||
| mesh_render_data_ensure_vert_normals_pack(rdata); | mesh_render_data_ensure_vert_normals_pack(rdata); | ||||
| Gwn_PackedNormal *pnors_pack = rdata->poly_normals_pack; | pnors_pack = rdata->poly_normals_pack; | ||||
| Gwn_PackedNormal *vnors_pack = rdata->vert_normals_pack; | vnors_pack = rdata->vert_normals_pack; | ||||
| } | |||||
| for (int i = 0; i < tri_len; i++) { | for (int i = 0; i < tri_len; i++) { | ||||
| const BMLoop **bm_looptri = (const BMLoop **)rdata->edit_bmesh->looptris[i]; | const BMLoop **bm_looptri = (const BMLoop **)rdata->edit_bmesh->looptris[i]; | ||||
| const BMFace *bm_face = bm_looptri[0]->f; | const BMFace *bm_face = bm_looptri[0]->f; | ||||
| /* use_hide always for edit-mode */ | /* use_hide always for edit-mode */ | ||||
| if (BM_elem_flag_test(bm_face, BM_ELEM_HIDDEN)) { | if (BM_elem_flag_test(bm_face, BM_ELEM_HIDDEN)) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| const uint vtri[3] = { | if (lnors) { | ||||
| 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)) { | |||||
| for (uint t = 0; t < 3; t++) { | 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 { | else { | ||||
| const Gwn_PackedNormal *snor_pack = &pnors_pack[BM_elem_index_get(bm_face)]; | const Gwn_PackedNormal *snor_pack = &pnors_pack[BM_elem_index_get(bm_face)]; | ||||
| for (uint t = 0; t < 3; t++) { | for (uint t = 0; t < 3; t++) { | ||||
| *((Gwn_PackedNormal *)GWN_vertbuf_raw_step(&nor_step)) = *snor_pack; | *((Gwn_PackedNormal *)GWN_vertbuf_raw_step(&nor_step)) = *snor_pack; | ||||
| } | } | ||||
| } | } | ||||
| for (uint t = 0; t < 3; t++) { | for (uint t = 0; t < 3; t++) { | ||||
| copy_v3_v3(GWN_vertbuf_raw_step(&pos_step), bm_looptri[t]->v->co); | copy_v3_v3(GWN_vertbuf_raw_step(&pos_step), bm_looptri[t]->v->co); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| float (*lnors)[3] = rdata->loop_normals; | |||||
| if (lnors == NULL) { | if (lnors == NULL) { | ||||
| /* Use normals from vertex. */ | /* Use normals from vertex. */ | ||||
| mesh_render_data_ensure_poly_normals_pack(rdata); | mesh_render_data_ensure_poly_normals_pack(rdata); | ||||
| } | } | ||||
| for (int i = 0; i < tri_len; i++) { | for (int i = 0; i < tri_len; i++) { | ||||
| const MLoopTri *mlt = &rdata->mlooptri[i]; | const MLoopTri *mlt = &rdata->mlooptri[i]; | ||||
| const MPoly *mp = &rdata->mpoly[mlt->poly]; | const MPoly *mp = &rdata->mpoly[mlt->poly]; | ||||
| ▲ Show 20 Lines • Show All 1,833 Lines • Show Last 20 Lines | |||||