diff options
Diffstat (limited to 'source/blender/draw/intern/draw_cache_impl_mesh.c')
-rw-r--r-- | source/blender/draw/intern/draw_cache_impl_mesh.c | 164 |
1 files changed, 100 insertions, 64 deletions
diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.c b/source/blender/draw/intern/draw_cache_impl_mesh.c index a9d54da9d08..fabb0a3f3a0 100644 --- a/source/blender/draw/intern/draw_cache_impl_mesh.c +++ b/source/blender/draw/intern/draw_cache_impl_mesh.c @@ -43,6 +43,7 @@ #include "BKE_deform.h" #include "BKE_DerivedMesh.h" #include "BKE_editmesh.h" +#include "BKE_editmesh_tangent.h" #include "BKE_mesh.h" #include "BKE_texture.h" @@ -153,9 +154,16 @@ typedef struct MeshRenderData { int bweight; int *uv; int *vcol; - int *tangent; +// int *tangent; } cd_offset; + /* for certain cases we need an output loop-data storage (bmesh tangents) */ + struct { + CustomData ldata; + /* grr, special case variable (use in place of 'dm->tangent_mask') */ + char tangent_mask; + } cd_output; + char (*auto_names)[32]; char (*uv_names)[32]; char (*vcol_names)[32]; @@ -223,6 +231,8 @@ static MeshRenderData *mesh_render_data_create(Mesh *me, const int types) rdata->types = types; rdata->mat_len = mesh_render_mat_len_get(me); + CustomData_reset(&rdata->cd_output.ldata); + if (me->edit_btmesh) { BMEditMesh *embm = me->edit_btmesh; BMesh *bm = embm->bm; @@ -334,8 +344,46 @@ static MeshRenderData *mesh_render_data_create(Mesh *me, const int types) } if (types & MR_DATATYPE_SHADING) { - rdata->uv_len = CustomData_number_of_layers(&me->ldata, CD_MLOOPUV); - rdata->vcol_len = CustomData_number_of_layers(&me->ldata, CD_MLOOPCOL); + CustomData *cd_vdata, *cd_ldata; + + if (me->edit_btmesh) { + BMesh *bm = me->edit_btmesh->bm; + cd_vdata = &bm->vdata; + cd_ldata = &bm->ldata; + } + else { + cd_vdata = &me->vdata; + cd_ldata = &me->ldata; + } + + rdata->orco = CustomData_get_layer(cd_vdata, CD_ORCO); + /* If orco is not available compute it ourselves */ + if (!rdata->orco) { + if (me->edit_btmesh) { + BMesh *bm = me->edit_btmesh->bm; + rdata->orco = MEM_mallocN(sizeof(*rdata->orco) * rdata->vert_len, "orco mesh"); + BLI_assert((bm->elem_table_dirty & BM_VERT) == 0); + BMVert **vtable = bm->vtable; + for (int i = 0; i < bm->totvert; i++) { + copy_v3_v3(rdata->orco[i], vtable[i]->co); + } + BKE_mesh_orco_verts_transform(me, rdata->orco, rdata->vert_len, 0); + } + else { + rdata->orco = MEM_mallocN(sizeof(*rdata->orco) * rdata->vert_len, "orco mesh"); + MVert *mvert = rdata->mvert; + for (int a = 0; a < rdata->vert_len; a++, mvert++) { + copy_v3_v3(rdata->orco[a], mvert->co); + } + BKE_mesh_orco_verts_transform(me, rdata->orco, rdata->vert_len, 0); + } + } + + /* don't access mesh directly, instead use vars taken from BMesh or Mesh */ +#define me DONT_USE_THIS + + rdata->uv_len = CustomData_number_of_layers(cd_ldata, CD_MLOOPUV); + rdata->vcol_len = CustomData_number_of_layers(cd_ldata, CD_MLOOPCOL); rdata->mloopuv = MEM_mallocN(sizeof(*rdata->mloopuv) * rdata->uv_len, "rdata->mloopuv"); rdata->mloopcol = MEM_mallocN(sizeof(*rdata->mloopcol) * rdata->vcol_len, "rdata->mloopcol"); @@ -347,7 +395,6 @@ static MeshRenderData *mesh_render_data_create(Mesh *me, const int types) rdata->cd_offset.uv = MEM_mallocN(sizeof(*rdata->cd_offset.uv) * rdata->uv_len, "rdata->uv_ofs"); rdata->cd_offset.vcol = MEM_mallocN(sizeof(*rdata->cd_offset.vcol) * rdata->vcol_len, "rdata->vcol_ofs"); - rdata->cd_offset.tangent = MEM_mallocN(sizeof(*rdata->cd_offset.tangent) * rdata->uv_len, "rdata->tangent_ofs"); /* Allocate max */ rdata->auto_vcol = MEM_callocN( @@ -363,32 +410,32 @@ static MeshRenderData *mesh_render_data_create(Mesh *me, const int types) * to a safe glsl var name, but without name clash. * NOTE 2 : Replicate changes to code_generate_vertex_new() in gpu_codegen.c */ for (int i = 0; i < rdata->vcol_len; ++i) { - const char *name = CustomData_get_layer_name(&me->ldata, CD_MLOOPCOL, i); + const char *name = CustomData_get_layer_name(cd_ldata, CD_MLOOPCOL, i); unsigned int hash = BLI_ghashutil_strhash_p(name); BLI_snprintf(rdata->vcol_names[i], sizeof(*rdata->vcol_names), "c%u", hash); - rdata->mloopcol[i] = CustomData_get_layer_n(&me->ldata, CD_MLOOPCOL, i); + rdata->mloopcol[i] = CustomData_get_layer_n(cd_ldata, CD_MLOOPCOL, i); if (rdata->edit_bmesh) { rdata->cd_offset.vcol[i] = CustomData_get_n_offset(&rdata->edit_bmesh->bm->ldata, CD_MLOOPCOL, i); } /* Gather number of auto layers. */ /* We only do vcols that are not overridden by uvs */ - if (CustomData_get_named_layer_index(&me->ldata, CD_MLOOPUV, name) == -1) { + if (CustomData_get_named_layer_index(cd_ldata, CD_MLOOPUV, name) == -1) { BLI_snprintf(rdata->auto_names[rdata->uv_len + i], sizeof(*rdata->auto_names), "a%u", hash); rdata->auto_vcol[i] = true; } } /* Start Fresh */ - CustomData_free_layers(&me->ldata, CD_MLOOPTANGENT, me->totloop); + CustomData_free_layers(cd_ldata, CD_MLOOPTANGENT, rdata->loop_len); for (int i = 0; i < rdata->uv_len; ++i) { - const char *name = CustomData_get_layer_name(&me->ldata, CD_MLOOPUV, i); + const char *name = CustomData_get_layer_name(cd_ldata, CD_MLOOPUV, i); unsigned int hash = BLI_ghashutil_strhash_p(name); { /* UVs */ BLI_snprintf(rdata->uv_names[i], sizeof(*rdata->uv_names), "u%u", hash); - rdata->mloopuv[i] = CustomData_get_layer_n(&me->ldata, CD_MLOOPUV, i); + rdata->mloopuv[i] = CustomData_get_layer_n(cd_ldata, CD_MLOOPUV, i); if (rdata->edit_bmesh) { rdata->cd_offset.uv[i] = CustomData_get_n_offset(&rdata->edit_bmesh->bm->ldata, CD_MLOOPUV, i); } @@ -400,70 +447,64 @@ static MeshRenderData *mesh_render_data_create(Mesh *me, const int types) BLI_snprintf(rdata->tangent_names[i], sizeof(*rdata->tangent_names), "t%u", hash); if (rdata->edit_bmesh) { -#if 0 /* TODO Waiting for the port of emDM_calc_loop_tangents */ - BMesh *bm = rdata->edit_bmesh->bm; - - float (*loopnors)[3] = CustomData_get_layer(&bm->ldata, CD_NORMAL); + BMEditMesh *em = rdata->edit_bmesh; + BMesh *bm = em->bm; + + if (!CustomData_has_layer(&rdata->cd_output.ldata, CD_MLOOPTANGENT)) { + bool calc_active_tangent = false; + float (*poly_normals)[3] = rdata->poly_normals; + float (*loop_normals)[3] = CustomData_get_layer(cd_ldata, CD_NORMAL); + char tangent_names[MAX_MTFACE][MAX_NAME]; + int tangent_names_len = 0; + for (tangent_names_len = 0; tangent_names_len < rdata->uv_len; tangent_names_len++) { + BLI_strncpy( + tangent_names[tangent_names_len], + CustomData_get_layer_name(cd_ldata, CD_MLOOPUV, tangent_names_len), MAX_NAME); + } - rdata->mtangent[i] = CustomData_add_layer( - &bm->ldata, CD_MLOOPTANGENT, CD_CALLOC, NULL, bm->totloop); - CustomData_set_layer_flag(&bm->ldata, CD_MLOOPTANGENT, CD_FLAG_TEMPORARY); + BKE_editmesh_loop_tangent_calc( + em, calc_active_tangent, + tangent_names, tangent_names_len, + poly_normals, loop_normals, + rdata->orco, + &rdata->cd_output.ldata, bm->totloop, + &rdata->cd_output.tangent_mask); + } - BKE_mesh_loop_tangents_ex(bm->mvert, bm->totvert, bm->mloop, rdata->mtangent[i], - loopnors, rdata->mloopuv[i], bm->totloop, bm->mpoly, bm->totpoly, NULL); + /* note: BKE_editmesh_loop_tangent_calc calculates 'CD_TANGENT', + * not 'CD_MLOOPTANGENT' (as done below). It's OK, they're compatible. */ + rdata->mtangent[i] = CustomData_get_layer_n(&rdata->cd_output.ldata, CD_TANGENT, i); + BLI_assert(rdata->mtangent[i] != NULL); - rdata->tangent_ofs[i] = CustomData_get_n_offset(&bm->ldata, CD_MLOOPTANGENT, i); -#else - rdata->cd_offset.tangent[i] = -1; -#endif + /* special case, we don't use offsets here */ } else { - if (!CustomData_has_layer(&me->ldata, CD_NORMAL)) { +#undef me + if (!CustomData_has_layer(cd_ldata, CD_NORMAL)) { BKE_mesh_calc_normals_split(me); } - float (*loopnors)[3] = CustomData_get_layer(&me->ldata, CD_NORMAL); + float (*loopnors)[3] = CustomData_get_layer(cd_ldata, CD_NORMAL); rdata->mtangent[i] = CustomData_add_layer( - &me->ldata, CD_MLOOPTANGENT, CD_CALLOC, NULL, me->totloop); - CustomData_set_layer_flag(&me->ldata, CD_MLOOPTANGENT, CD_FLAG_TEMPORARY); + cd_ldata, CD_MLOOPTANGENT, CD_CALLOC, NULL, me->totloop); + CustomData_set_layer_flag(cd_ldata, CD_MLOOPTANGENT, CD_FLAG_TEMPORARY); BKE_mesh_loop_tangents_ex(me->mvert, me->totvert, me->mloop, rdata->mtangent[i], loopnors, rdata->mloopuv[i], me->totloop, me->mpoly, me->totpoly, NULL); +#define me DONT_USE_THIS } } } rdata->uv_active = CustomData_get_active_layer_index( - &me->ldata, CD_MLOOPUV) - CustomData_get_layer_index(&me->ldata, CD_MLOOPUV); + cd_ldata, CD_MLOOPUV) - CustomData_get_layer_index(cd_ldata, CD_MLOOPUV); rdata->vcol_active = CustomData_get_active_layer_index( - &me->ldata, CD_MLOOPCOL) - CustomData_get_layer_index(&me->ldata, CD_MLOOPCOL); + cd_ldata, CD_MLOOPCOL) - CustomData_get_layer_index(cd_ldata, CD_MLOOPCOL); rdata->tangent_active = CustomData_get_active_layer_index( - &me->ldata, CD_MLOOPTANGENT) - CustomData_get_layer_index(&me->ldata, CD_MLOOPTANGENT); - - rdata->orco = CustomData_get_layer(&me->vdata, CD_ORCO); + cd_ldata, CD_MLOOPTANGENT) - CustomData_get_layer_index(cd_ldata, CD_MLOOPTANGENT); - /* If orco is not available compute it ourselves */ - if (!rdata->orco) { - if (me->edit_btmesh) { - BMesh *bm = me->edit_btmesh->bm; - rdata->orco = MEM_mallocN(sizeof(*rdata->orco) * rdata->vert_len, "orco mesh"); - BLI_assert((bm->elem_table_dirty & BM_VERT) == 0); - BMVert **vtable = bm->vtable; - for (int i = 0; i < bm->totvert; i++) { - copy_v3_v3(rdata->orco[i], vtable[i]->co); - } - BKE_mesh_orco_verts_transform(me, rdata->orco, rdata->vert_len, 0); - } - else { - rdata->orco = MEM_mallocN(sizeof(*rdata->orco) * rdata->vert_len, "orco mesh"); - MVert *mvert = rdata->mvert; - for (int a = 0; a < rdata->vert_len; a++, mvert++) { - copy_v3_v3(rdata->orco[a], mvert->co); - } - BKE_mesh_orco_verts_transform(me, rdata->orco, rdata->vert_len, 0); - } - } +#undef me } return rdata; @@ -475,7 +516,6 @@ static void mesh_render_data_free(MeshRenderData *rdata) MEM_SAFE_FREE(rdata->auto_names); MEM_SAFE_FREE(rdata->cd_offset.uv); MEM_SAFE_FREE(rdata->cd_offset.vcol); - MEM_SAFE_FREE(rdata->cd_offset.tangent); MEM_SAFE_FREE(rdata->orco); MEM_SAFE_FREE(rdata->mloopuv); MEM_SAFE_FREE(rdata->mloopcol); @@ -493,6 +533,9 @@ static void mesh_render_data_free(MeshRenderData *rdata) MEM_SAFE_FREE(rdata->vert_weight_color); MEM_SAFE_FREE(rdata->edge_selection); MEM_SAFE_FREE(rdata->vert_color); + + CustomData_free(&rdata->cd_output.ldata, rdata->loop_len); + MEM_freeN(rdata); } @@ -1108,17 +1151,10 @@ static void mesh_render_data_looptri_tans_get( float *(*r_vert_tans)[3]) { if (rdata->edit_bmesh) { -#if 0 /* waiting for edit mesh tangent calculation */ const BMLoop **bm_looptri = (const BMLoop **)rdata->edit_bmesh->looptris[tri_idx]; - (*r_vert_tans)[0] = ((float *)BM_ELEM_CD_GET_VOID_P(bm_looptri[0], rdata->cd_offset.tangent[tangent_layer])); - (*r_vert_tans)[1] = ((float *)BM_ELEM_CD_GET_VOID_P(bm_looptri[1], rdata->cd_offset.tangent[tangent_layer])); - (*r_vert_tans)[2] = ((float *)BM_ELEM_CD_GET_VOID_P(bm_looptri[2], rdata->cd_offset.tangent[tangent_layer])); -#else - static float tan[4] = {0.0f}; - (*r_vert_tans)[0] = tan; - (*r_vert_tans)[1] = tan; - (*r_vert_tans)[2] = tan; -#endif + (*r_vert_tans)[0] = rdata->mtangent[tangent_layer][BM_elem_index_get(bm_looptri[0])]; + (*r_vert_tans)[1] = rdata->mtangent[tangent_layer][BM_elem_index_get(bm_looptri[1])]; + (*r_vert_tans)[2] = rdata->mtangent[tangent_layer][BM_elem_index_get(bm_looptri[2])]; } else { const MLoopTri *mlt = &rdata->mlooptri[tri_idx]; |