diff options
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/blenkernel/intern/editmesh_tangent.cc | 288 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/mesh_tangent.cc | 447 |
2 files changed, 245 insertions, 490 deletions
diff --git a/source/blender/blenkernel/intern/editmesh_tangent.cc b/source/blender/blenkernel/intern/editmesh_tangent.cc index 5a01f64826d..a65532d083d 100644 --- a/source/blender/blenkernel/intern/editmesh_tangent.cc +++ b/source/blender/blenkernel/intern/editmesh_tangent.cc @@ -20,7 +20,7 @@ #include "MEM_guardedalloc.h" /* interface */ -#include "mikktspace.h" +#include "mikktspace.hh" /* -------------------------------------------------------------------- */ /** \name Tangent Space Calculation @@ -30,233 +30,129 @@ #define USE_LOOPTRI_DETECT_QUADS struct SGLSLEditMeshToTangent { - const float (*precomputedFaceNormals)[3]; - const float (*precomputedLoopNormals)[3]; - const BMLoop *(*looptris)[3]; - int cd_loop_uv_offset; /* texture coordinates */ - const float (*orco)[3]; - float (*tangent)[4]; /* destination */ - int numTessFaces; - -#ifdef USE_LOOPTRI_DETECT_QUADS - /* map from 'fake' face index to looptri, - * quads will point to the first looptri of the quad */ - const int *face_as_quad_map; - int num_face_as_quad_map; -#endif -}; - -#ifdef USE_LOOPTRI_DETECT_QUADS -/* seems weak but only used on quads */ -static const BMLoop *bm_loop_at_face_index(const BMFace *f, int vert_index) -{ - const BMLoop *l = BM_FACE_FIRST_LOOP(f); - while (vert_index--) { - l = l->next; - } - return l; -} -#endif - -static int emdm_ts_GetNumFaces(const SMikkTSpaceContext *pContext) -{ - SGLSLEditMeshToTangent *pMesh = static_cast<SGLSLEditMeshToTangent *>(pContext->m_pUserData); - + uint GetNumFaces() + { #ifdef USE_LOOPTRI_DETECT_QUADS - return pMesh->num_face_as_quad_map; + return (uint)num_face_as_quad_map; #else - return pMesh->numTessFaces; + return (uint)numTessFaces; #endif -} - -static int emdm_ts_GetNumVertsOfFace(const SMikkTSpaceContext *pContext, const int face_num) -{ -#ifdef USE_LOOPTRI_DETECT_QUADS - SGLSLEditMeshToTangent *pMesh = static_cast<SGLSLEditMeshToTangent *>(pContext->m_pUserData); - if (pMesh->face_as_quad_map) { - const BMLoop **lt = pMesh->looptris[pMesh->face_as_quad_map[face_num]]; - if (lt[0]->f->len == 4) { - return 4; - } } - return 3; -#else - UNUSED_VARS(pContext, face_num); - return 3; -#endif -} - -static void emdm_ts_GetPosition(const SMikkTSpaceContext *pContext, - float r_co[3], - const int face_num, - const int vert_index) -{ - // BLI_assert(vert_index >= 0 && vert_index < 4); - SGLSLEditMeshToTangent *pMesh = static_cast<SGLSLEditMeshToTangent *>(pContext->m_pUserData); - const BMLoop **lt; - const BMLoop *l; + uint GetNumVerticesOfFace(const uint face_num) + { #ifdef USE_LOOPTRI_DETECT_QUADS - if (pMesh->face_as_quad_map) { - lt = pMesh->looptris[pMesh->face_as_quad_map[face_num]]; - if (lt[0]->f->len == 4) { - l = bm_loop_at_face_index(lt[0]->f, vert_index); - goto finally; + if (face_as_quad_map) { + if (looptris[face_as_quad_map[face_num]][0]->f->len == 4) { + return 4; + } } - /* fall through to regular triangle */ - } - else { - lt = pMesh->looptris[face_num]; - } + return 3; #else - lt = pMesh->looptris[face_num]; + UNUSED_VARS(pContext, face_num); + return 3; #endif - l = lt[vert_index]; - - const float *co; - -finally: - co = l->v->co; - copy_v3_v3(r_co, co); -} + } -static void emdm_ts_GetTextureCoordinate(const SMikkTSpaceContext *pContext, - float r_uv[2], - const int face_num, - const int vert_index) -{ - // BLI_assert(vert_index >= 0 && vert_index < 4); - SGLSLEditMeshToTangent *pMesh = static_cast<SGLSLEditMeshToTangent *>(pContext->m_pUserData); - const BMLoop **lt; - const BMLoop *l; + const BMLoop *GetLoop(const uint face_num, uint vert_index) + { + // BLI_assert(vert_index >= 0 && vert_index < 4); + const BMLoop **lt; + const BMLoop *l; #ifdef USE_LOOPTRI_DETECT_QUADS - if (pMesh->face_as_quad_map) { - lt = pMesh->looptris[pMesh->face_as_quad_map[face_num]]; - if (lt[0]->f->len == 4) { - l = bm_loop_at_face_index(lt[0]->f, vert_index); - goto finally; + if (face_as_quad_map) { + lt = looptris[face_as_quad_map[face_num]]; + if (lt[0]->f->len == 4) { + l = BM_FACE_FIRST_LOOP(lt[0]->f); + while (vert_index--) { + l = l->next; + } + return l; + } + /* fall through to regular triangle */ + } + else { + lt = looptris[face_num]; } - /* fall through to regular triangle */ - } - else { - lt = pMesh->looptris[face_num]; - } #else - lt = pMesh->looptris[face_num]; + lt = looptris[face_num]; #endif - l = lt[vert_index]; - -finally: - if (pMesh->cd_loop_uv_offset != -1) { - const float *uv = BM_ELEM_CD_GET_FLOAT_P(l, pMesh->cd_loop_uv_offset); - copy_v2_v2(r_uv, uv); - } - else { - const float *orco = pMesh->orco[BM_elem_index_get(l->v)]; - map_to_sphere(&r_uv[0], &r_uv[1], orco[0], orco[1], orco[2]); + return lt[vert_index]; } -} -static void emdm_ts_GetNormal(const SMikkTSpaceContext *pContext, - float r_no[3], - const int face_num, - const int vert_index) -{ - // BLI_assert(vert_index >= 0 && vert_index < 4); - SGLSLEditMeshToTangent *pMesh = static_cast<SGLSLEditMeshToTangent *>(pContext->m_pUserData); - const BMLoop **lt; - const BMLoop *l; + mikk::float3 GetPosition(const uint face_num, const uint vert_index) + { + const BMLoop *l = GetLoop(face_num, vert_index); + return mikk::float3(l->v->co); + } -#ifdef USE_LOOPTRI_DETECT_QUADS - if (pMesh->face_as_quad_map) { - lt = pMesh->looptris[pMesh->face_as_quad_map[face_num]]; - if (lt[0]->f->len == 4) { - l = bm_loop_at_face_index(lt[0]->f, vert_index); - goto finally; + mikk::float3 GetTexCoord(const uint face_num, const uint vert_index) + { + const BMLoop *l = GetLoop(face_num, vert_index); + if (cd_loop_uv_offset != -1) { + const float *uv = (const float *)BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + return mikk::float3(uv[0], uv[1], 1.0f); + } + else { + const float *orco_p = orco[BM_elem_index_get(l->v)]; + float u, v; + map_to_sphere(&u, &v, orco_p[0], orco_p[1], orco_p[2]); + return mikk::float3(u, v, 1.0f); } - /* fall through to regular triangle */ - } - else { - lt = pMesh->looptris[face_num]; } -#else - lt = pMesh->looptris[face_num]; -#endif - l = lt[vert_index]; -finally: - if (pMesh->precomputedLoopNormals) { - copy_v3_v3(r_no, pMesh->precomputedLoopNormals[BM_elem_index_get(l)]); - } - else if (BM_elem_flag_test(l->f, BM_ELEM_SMOOTH) == 0) { /* flat */ - if (pMesh->precomputedFaceNormals) { - copy_v3_v3(r_no, pMesh->precomputedFaceNormals[BM_elem_index_get(l->f)]); + mikk::float3 GetNormal(const uint face_num, const uint vert_index) + { + const BMLoop *l = GetLoop(face_num, vert_index); + if (precomputedLoopNormals) { + return mikk::float3(precomputedLoopNormals[BM_elem_index_get(l)]); + } + else if (BM_elem_flag_test(l->f, BM_ELEM_SMOOTH) == 0) { /* flat */ + if (precomputedFaceNormals) { + return mikk::float3(precomputedFaceNormals[BM_elem_index_get(l->f)]); + } + else { + return mikk::float3(l->f->no); + } } else { - copy_v3_v3(r_no, l->f->no); + return mikk::float3(l->v->no); } } - else { - copy_v3_v3(r_no, l->v->no); + + void SetTangentSpace(const uint face_num, + const uint vert_index, + mikk::float3 T, + bool orientation) + { + const BMLoop *l = GetLoop(face_num, vert_index); + float *p_res = tangent[BM_elem_index_get(l)]; + copy_v4_fl4(p_res, T.x, T.y, T.z, orientation ? 1.0f : -1.0f); } -} -static void emdm_ts_SetTSpace(const SMikkTSpaceContext *pContext, - const float fvTangent[3], - const float fSign, - const int face_num, - const int vert_index) -{ - // BLI_assert(vert_index >= 0 && vert_index < 4); - SGLSLEditMeshToTangent *pMesh = static_cast<SGLSLEditMeshToTangent *>(pContext->m_pUserData); - const BMLoop **lt; - const BMLoop *l; + const float (*precomputedFaceNormals)[3]; + const float (*precomputedLoopNormals)[3]; + const BMLoop *(*looptris)[3]; + int cd_loop_uv_offset; /* texture coordinates */ + const float (*orco)[3]; + float (*tangent)[4]; /* destination */ + int numTessFaces; #ifdef USE_LOOPTRI_DETECT_QUADS - if (pMesh->face_as_quad_map) { - lt = pMesh->looptris[pMesh->face_as_quad_map[face_num]]; - if (lt[0]->f->len == 4) { - l = bm_loop_at_face_index(lt[0]->f, vert_index); - goto finally; - } - /* fall through to regular triangle */ - } - else { - lt = pMesh->looptris[face_num]; - } -#else - lt = pMesh->looptris[face_num]; + /* map from 'fake' face index to looptri, + * quads will point to the first looptri of the quad */ + const int *face_as_quad_map; + int num_face_as_quad_map; #endif - l = lt[vert_index]; - - float *pRes; - -finally: - pRes = pMesh->tangent[BM_elem_index_get(l)]; - copy_v3_v3(pRes, fvTangent); - pRes[3] = fSign; -} +}; static void emDM_calc_loop_tangents_thread(TaskPool *__restrict UNUSED(pool), void *taskdata) { - SGLSLEditMeshToTangent *mesh2tangent = static_cast<SGLSLEditMeshToTangent *>(taskdata); - /* new computation method */ - { - SMikkTSpaceContext sContext{}; - SMikkTSpaceInterface sInterface{}; - sContext.m_pUserData = mesh2tangent; - sContext.m_pInterface = &sInterface; - sInterface.m_getNumFaces = emdm_ts_GetNumFaces; - sInterface.m_getNumVerticesOfFace = emdm_ts_GetNumVertsOfFace; - sInterface.m_getPosition = emdm_ts_GetPosition; - sInterface.m_getTexCoord = emdm_ts_GetTextureCoordinate; - sInterface.m_getNormal = emdm_ts_GetNormal; - sInterface.m_setTSpaceBasic = emdm_ts_SetTSpace; - sInterface.m_setTSpace = nullptr; - /* 0 if failed */ - genTangSpaceDefault(&sContext); - } + SGLSLEditMeshToTangent *mesh_data = static_cast<SGLSLEditMeshToTangent *>(taskdata); + + mikk::Mikktspace<SGLSLEditMeshToTangent> mikk(*mesh_data); + mikk.genTangSpace(); } void BKE_editmesh_loop_tangent_calc(BMEditMesh *em, @@ -392,7 +288,7 @@ void BKE_editmesh_loop_tangent_calc(BMEditMesh *em, } BM_mesh_elem_index_ensure(bm, htype_index); - mesh2tangent->looptris = (const BMLoop *(*)[3])(em->looptris); + mesh2tangent->looptris = (const BMLoop *(*)[3])em->looptris; mesh2tangent->tangent = static_cast<float(*)[4]>(loopdata_out->layers[index].data); BLI_task_pool_push( diff --git a/source/blender/blenkernel/intern/mesh_tangent.cc b/source/blender/blenkernel/intern/mesh_tangent.cc index 4ebc6b74705..003b196107f 100644 --- a/source/blender/blenkernel/intern/mesh_tangent.cc +++ b/source/blender/blenkernel/intern/mesh_tangent.cc @@ -27,16 +27,46 @@ #include "BLI_strict_flags.h" #include "atomic_ops.h" -#include "mikktspace.h" +#include "mikktspace.hh" /* -------------------------------------------------------------------- */ /** \name Mesh Tangent Calculations (Single Layer) * \{ */ -/* Tangent space utils. */ - -/* User data. */ struct BKEMeshToTangent { + uint GetNumFaces() + { + return (uint)num_polys; + } + + uint GetNumVerticesOfFace(const uint face_num) + { + return (uint)mpolys[face_num].totloop; + } + + mikk::float3 GetPosition(const uint face_num, const uint vert_num) + { + const uint loop_idx = (uint)mpolys[face_num].loopstart + vert_num; + return mikk::float3(mverts[mloops[loop_idx].v].co); + } + + mikk::float3 GetTexCoord(const uint face_num, const uint vert_num) + { + const float *uv = luvs[(uint)mpolys[face_num].loopstart + vert_num].uv; + return mikk::float3(uv[0], uv[1], 1.0f); + } + + mikk::float3 GetNormal(const uint face_num, const uint vert_num) + { + return mikk::float3(lnors[(uint)mpolys[face_num].loopstart + vert_num]); + } + + void SetTangentSpace(const uint face_num, const uint vert_num, mikk::float3 T, bool orientation) + { + float *p_res = tangents[(uint)mpolys[face_num].loopstart + vert_num]; + copy_v4_fl4(p_res, T.x, T.y, T.z, orientation ? 1.0f : -1.0f); + } + const MPoly *mpolys; /* faces */ const MLoop *mloops; /* faces's vertices */ const MVert *mverts; /* vertices */ @@ -46,59 +76,6 @@ struct BKEMeshToTangent { int num_polys; /* number of polygons */ }; -/* Mikktspace's API */ -static int get_num_faces(const SMikkTSpaceContext *pContext) -{ - BKEMeshToTangent *p_mesh = static_cast<BKEMeshToTangent *>(pContext->m_pUserData); - return p_mesh->num_polys; -} - -static int get_num_verts_of_face(const SMikkTSpaceContext *pContext, const int face_idx) -{ - BKEMeshToTangent *p_mesh = static_cast<BKEMeshToTangent *>(pContext->m_pUserData); - return p_mesh->mpolys[face_idx].totloop; -} - -static void get_position(const SMikkTSpaceContext *pContext, - float r_co[3], - const int face_idx, - const int vert_idx) -{ - BKEMeshToTangent *p_mesh = static_cast<BKEMeshToTangent *>(pContext->m_pUserData); - const int loop_idx = p_mesh->mpolys[face_idx].loopstart + vert_idx; - copy_v3_v3(r_co, p_mesh->mverts[p_mesh->mloops[loop_idx].v].co); -} - -static void get_texture_coordinate(const SMikkTSpaceContext *pContext, - float r_uv[2], - const int face_idx, - const int vert_idx) -{ - BKEMeshToTangent *p_mesh = static_cast<BKEMeshToTangent *>(pContext->m_pUserData); - copy_v2_v2(r_uv, p_mesh->luvs[p_mesh->mpolys[face_idx].loopstart + vert_idx].uv); -} - -static void get_normal(const SMikkTSpaceContext *pContext, - float r_no[3], - const int face_idx, - const int vert_idx) -{ - BKEMeshToTangent *p_mesh = static_cast<BKEMeshToTangent *>(pContext->m_pUserData); - copy_v3_v3(r_no, p_mesh->lnors[p_mesh->mpolys[face_idx].loopstart + vert_idx]); -} - -static void set_tspace(const SMikkTSpaceContext *pContext, - const float fv_tangent[3], - const float face_sign, - const int face_idx, - const int vert_idx) -{ - BKEMeshToTangent *p_mesh = static_cast<BKEMeshToTangent *>(pContext->m_pUserData); - float *p_res = p_mesh->tangents[p_mesh->mpolys[face_idx].loopstart + vert_idx]; - copy_v3_v3(p_res, fv_tangent); - p_res[3] = face_sign; -} - void BKE_mesh_calc_loop_tangent_single_ex(const MVert *mverts, const int UNUSED(numVerts), const MLoop *mloops, @@ -110,23 +87,8 @@ void BKE_mesh_calc_loop_tangent_single_ex(const MVert *mverts, const int numPolys, ReportList *reports) { - BKEMeshToTangent mesh_to_tangent; - SMikkTSpaceContext s_context{}; - SMikkTSpaceInterface s_interface{}; - - const MPoly *mp; - int mp_index; - - /* First check we do have a tris/quads only mesh. */ - for (mp = mpolys, mp_index = 0; mp_index < numPolys; mp++, mp_index++) { - if (mp->totloop > 4) { - BKE_report( - reports, RPT_ERROR, "Tangent space can only be computed for tris/quads, aborting"); - return; - } - } - /* Compute Mikktspace's tangent normals. */ + BKEMeshToTangent mesh_to_tangent; mesh_to_tangent.mpolys = mpolys; mesh_to_tangent.mloops = mloops; mesh_to_tangent.mverts = mverts; @@ -135,20 +97,18 @@ void BKE_mesh_calc_loop_tangent_single_ex(const MVert *mverts, mesh_to_tangent.tangents = r_looptangent; mesh_to_tangent.num_polys = numPolys; - s_context.m_pUserData = &mesh_to_tangent; - s_context.m_pInterface = &s_interface; - s_interface.m_getNumFaces = get_num_faces; - s_interface.m_getNumVerticesOfFace = get_num_verts_of_face; - s_interface.m_getPosition = get_position; - s_interface.m_getTexCoord = get_texture_coordinate; - s_interface.m_getNormal = get_normal; - s_interface.m_setTSpaceBasic = set_tspace; - s_interface.m_setTSpace = nullptr; - - /* 0 if failed */ - if (genTangSpaceDefault(&s_context) == false) { - BKE_report(reports, RPT_ERROR, "Mikktspace failed to generate tangents for this mesh!"); + mikk::Mikktspace<BKEMeshToTangent> mikk(mesh_to_tangent); + + /* First check we do have a tris/quads only mesh. */ + for (int i = 0; i < numPolys; i++) { + if (mpolys[i].totloop > 4) { + BKE_report( + reports, RPT_ERROR, "Tangent space can only be computed for tris/quads, aborting"); + return; + } } + + mikk.genTangSpace(); } void BKE_mesh_calc_loop_tangent_single(Mesh *mesh, @@ -203,248 +163,147 @@ void BKE_mesh_calc_loop_tangent_single(Mesh *mesh, #define USE_LOOPTRI_DETECT_QUADS struct SGLSLMeshToTangent { - const float (*precomputedFaceNormals)[3]; - const float (*precomputedLoopNormals)[3]; - const MLoopTri *looptri; - const MLoopUV *mloopuv; /* texture coordinates */ - const MPoly *mpoly; /* indices */ - const MLoop *mloop; /* indices */ - const MVert *mvert; /* vertex coordinates */ - const float (*vert_normals)[3]; - const float (*orco)[3]; - float (*tangent)[4]; /* destination */ - int numTessFaces; - -#ifdef USE_LOOPTRI_DETECT_QUADS - /* map from 'fake' face index to looptri, - * quads will point to the first looptri of the quad */ - const int *face_as_quad_map; - int num_face_as_quad_map; -#endif -}; - -/* interface */ -static int dm_ts_GetNumFaces(const SMikkTSpaceContext *pContext) -{ - SGLSLMeshToTangent *pMesh = static_cast<SGLSLMeshToTangent *>(pContext->m_pUserData); - + uint GetNumFaces() + { #ifdef USE_LOOPTRI_DETECT_QUADS - return pMesh->num_face_as_quad_map; + return (uint)num_face_as_quad_map; #else - return pMesh->numTessFaces; + return (uint)numTessFaces; #endif -} - -static int dm_ts_GetNumVertsOfFace(const SMikkTSpaceContext *pContext, const int face_num) -{ -#ifdef USE_LOOPTRI_DETECT_QUADS - SGLSLMeshToTangent *pMesh = static_cast<SGLSLMeshToTangent *>(pContext->m_pUserData); - if (pMesh->face_as_quad_map) { - const MLoopTri *lt = &pMesh->looptri[pMesh->face_as_quad_map[face_num]]; - const MPoly *mp = &pMesh->mpoly[lt->poly]; - if (mp->totloop == 4) { - return 4; - } } - return 3; -#else - UNUSED_VARS(pContext, face_num); - return 3; -#endif -} - -static void dm_ts_GetPosition(const SMikkTSpaceContext *pContext, - float r_co[3], - const int face_num, - const int vert_index) -{ - // assert(vert_index >= 0 && vert_index < 4); - SGLSLMeshToTangent *pMesh = static_cast<SGLSLMeshToTangent *>(pContext->m_pUserData); - const MLoopTri *lt; - uint loop_index; - const float *co; + uint GetNumVerticesOfFace(const uint face_num) + { #ifdef USE_LOOPTRI_DETECT_QUADS - if (pMesh->face_as_quad_map) { - lt = &pMesh->looptri[pMesh->face_as_quad_map[face_num]]; - const MPoly *mp = &pMesh->mpoly[lt->poly]; - if (mp->totloop == 4) { - loop_index = (uint)(mp->loopstart + vert_index); - goto finally; + if (face_as_quad_map) { + const MLoopTri *lt = &looptri[face_as_quad_map[face_num]]; + const MPoly *mp = &mpoly[lt->poly]; + if (mp->totloop == 4) { + return 4; + } } - /* fall through to regular triangle */ - } - else { - lt = &pMesh->looptri[face_num]; - } + return 3; #else - lt = &pMesh->looptri[face_num]; + UNUSED_VARS(pContext, face_num); + return 3; #endif - loop_index = lt->tri[vert_index]; - -finally: - co = pMesh->mvert[pMesh->mloop[loop_index].v].co; - copy_v3_v3(r_co, co); -} - -static void dm_ts_GetTextureCoordinate(const SMikkTSpaceContext *pContext, - float r_uv[2], - const int face_num, - const int vert_index) -{ - // assert(vert_index >= 0 && vert_index < 4); - SGLSLMeshToTangent *pMesh = static_cast<SGLSLMeshToTangent *>(pContext->m_pUserData); - const MLoopTri *lt; - uint loop_index; + } + uint GetLoop(const uint face_num, const uint vert_num, const MLoopTri *<) + { #ifdef USE_LOOPTRI_DETECT_QUADS - if (pMesh->face_as_quad_map) { - lt = &pMesh->looptri[pMesh->face_as_quad_map[face_num]]; - const MPoly *mp = &pMesh->mpoly[lt->poly]; - if (mp->totloop == 4) { - loop_index = (uint)(mp->loopstart + vert_index); - goto finally; + if (face_as_quad_map) { + lt = &looptri[face_as_quad_map[face_num]]; + const MPoly *mp = &mpoly[lt->poly]; + if (mp->totloop == 4) { + return ((uint)mp->loopstart + vert_num); + } + /* fall through to regular triangle */ + } + else { + lt = &looptri[face_num]; } - /* fall through to regular triangle */ - } - else { - lt = &pMesh->looptri[face_num]; - } #else - lt = &pMesh->looptri[face_num]; + lt = &looptri[face_num]; #endif - loop_index = lt->tri[vert_index]; - -finally: - if (pMesh->mloopuv != nullptr) { - const float *uv = pMesh->mloopuv[loop_index].uv; - copy_v2_v2(r_uv, uv); + return lt->tri[vert_num]; } - else { - const float *orco = pMesh->orco[pMesh->mloop[loop_index].v]; - map_to_sphere(&r_uv[0], &r_uv[1], orco[0], orco[1], orco[2]); - } -} -static void dm_ts_GetNormal(const SMikkTSpaceContext *pContext, - float r_no[3], - const int face_num, - const int vert_index) -{ - // assert(vert_index >= 0 && vert_index < 4); - SGLSLMeshToTangent *pMesh = static_cast<SGLSLMeshToTangent *>(pContext->m_pUserData); - const MLoopTri *lt; - uint loop_index; + mikk::float3 GetPosition(const uint face_num, const uint vert_num) + { + const MLoopTri *lt; + uint loop_index = GetLoop(face_num, vert_num, lt); + return mikk::float3(mvert[mloop[loop_index].v].co); + } -#ifdef USE_LOOPTRI_DETECT_QUADS - if (pMesh->face_as_quad_map) { - lt = &pMesh->looptri[pMesh->face_as_quad_map[face_num]]; - const MPoly *mp = &pMesh->mpoly[lt->poly]; - if (mp->totloop == 4) { - loop_index = (uint)(mp->loopstart + vert_index); - goto finally; + mikk::float3 GetTexCoord(const uint face_num, const uint vert_num) + { + const MLoopTri *lt; + uint loop_index = GetLoop(face_num, vert_num, lt); + if (mloopuv != nullptr) { + const float *uv = mloopuv[loop_index].uv; + return mikk::float3(uv[0], uv[1], 1.0f); + } + else { + const float *l_orco = orco[mloop[loop_index].v]; + float u, v; + map_to_sphere(&u, &v, l_orco[0], l_orco[1], l_orco[2]); + return mikk::float3(u, v, 1.0f); } - /* fall through to regular triangle */ - } - else { - lt = &pMesh->looptri[face_num]; } -#else - lt = &pMesh->looptri[face_num]; -#endif - loop_index = lt->tri[vert_index]; -finally: - if (pMesh->precomputedLoopNormals) { - copy_v3_v3(r_no, pMesh->precomputedLoopNormals[loop_index]); - } - else if ((pMesh->mpoly[lt->poly].flag & ME_SMOOTH) == 0) { /* flat */ - if (pMesh->precomputedFaceNormals) { - copy_v3_v3(r_no, pMesh->precomputedFaceNormals[lt->poly]); + mikk::float3 GetNormal(const uint face_num, const uint vert_num) + { + const MLoopTri *lt; + uint loop_index = GetLoop(face_num, vert_num, lt); + if (precomputedLoopNormals) { + return mikk::float3(precomputedLoopNormals[loop_index]); } - else { -#ifdef USE_LOOPTRI_DETECT_QUADS - const MPoly *mp = &pMesh->mpoly[lt->poly]; - if (mp->totloop == 4) { - normal_quad_v3(r_no, - pMesh->mvert[pMesh->mloop[mp->loopstart + 0].v].co, - pMesh->mvert[pMesh->mloop[mp->loopstart + 1].v].co, - pMesh->mvert[pMesh->mloop[mp->loopstart + 2].v].co, - pMesh->mvert[pMesh->mloop[mp->loopstart + 3].v].co); + else if ((mpoly[lt->poly].flag & ME_SMOOTH) == 0) { /* flat */ + if (precomputedFaceNormals) { + return mikk::float3(precomputedFaceNormals[lt->poly]); } - else + else { +#ifdef USE_LOOPTRI_DETECT_QUADS + const MPoly *mp = &mpoly[lt->poly]; + float normal[3]; + if (mp->totloop == 4) { + normal_quad_v3(normal, + mvert[mloop[mp->loopstart + 0].v].co, + mvert[mloop[mp->loopstart + 1].v].co, + mvert[mloop[mp->loopstart + 2].v].co, + mvert[mloop[mp->loopstart + 3].v].co); + } + else #endif - { - normal_tri_v3(r_no, - pMesh->mvert[pMesh->mloop[lt->tri[0]].v].co, - pMesh->mvert[pMesh->mloop[lt->tri[1]].v].co, - pMesh->mvert[pMesh->mloop[lt->tri[2]].v].co); + { + normal_tri_v3(normal, + mvert[mloop[lt->tri[0]].v].co, + mvert[mloop[lt->tri[1]].v].co, + mvert[mloop[lt->tri[2]].v].co); + } + return mikk::float3(normal); } } + else { + return mikk::float3(vert_normals[mloop[loop_index].v]); + } } - else { - copy_v3_v3(r_no, pMesh->vert_normals[pMesh->mloop[loop_index].v]); - } -} -static void dm_ts_SetTSpace(const SMikkTSpaceContext *pContext, - const float fvTangent[3], - const float fSign, - const int face_num, - const int vert_index) -{ - // assert(vert_index >= 0 && vert_index < 4); - SGLSLMeshToTangent *pMesh = static_cast<SGLSLMeshToTangent *>(pContext->m_pUserData); - const MLoopTri *lt; - uint loop_index; + void SetTangentSpace(const uint face_num, const uint vert_num, mikk::float3 T, bool orientation) + { + const MLoopTri *lt; + uint loop_index = GetLoop(face_num, vert_num, lt); -#ifdef USE_LOOPTRI_DETECT_QUADS - if (pMesh->face_as_quad_map) { - lt = &pMesh->looptri[pMesh->face_as_quad_map[face_num]]; - const MPoly *mp = &pMesh->mpoly[lt->poly]; - if (mp->totloop == 4) { - loop_index = (uint)(mp->loopstart + vert_index); - goto finally; - } - /* fall through to regular triangle */ - } - else { - lt = &pMesh->looptri[face_num]; + copy_v4_fl4(tangent[loop_index], T.x, T.y, T.z, orientation ? 1.0f : -1.0f); } -#else - lt = &pMesh->looptri[face_num]; -#endif - loop_index = lt->tri[vert_index]; - float *pRes; + const float (*precomputedFaceNormals)[3]; + const float (*precomputedLoopNormals)[3]; + const MLoopTri *looptri; + const MLoopUV *mloopuv; /* texture coordinates */ + const MPoly *mpoly; /* indices */ + const MLoop *mloop; /* indices */ + const MVert *mvert; /* vertex coordinates */ + const float (*vert_normals)[3]; + const float (*orco)[3]; + float (*tangent)[4]; /* destination */ + int numTessFaces; -finally: - pRes = pMesh->tangent[loop_index]; - copy_v3_v3(pRes, fvTangent); - pRes[3] = fSign; -} +#ifdef USE_LOOPTRI_DETECT_QUADS + /* map from 'fake' face index to looptri, + * quads will point to the first looptri of the quad */ + const int *face_as_quad_map; + int num_face_as_quad_map; +#endif +}; static void DM_calc_loop_tangents_thread(TaskPool *__restrict UNUSED(pool), void *taskdata) { - SGLSLMeshToTangent *mesh2tangent = static_cast<SGLSLMeshToTangent *>(taskdata); - /* new computation method */ - { - SMikkTSpaceContext sContext{}; - SMikkTSpaceInterface sInterface{}; - - sContext.m_pUserData = mesh2tangent; - sContext.m_pInterface = &sInterface; - sInterface.m_getNumFaces = dm_ts_GetNumFaces; - sInterface.m_getNumVerticesOfFace = dm_ts_GetNumVertsOfFace; - sInterface.m_getPosition = dm_ts_GetPosition; - sInterface.m_getTexCoord = dm_ts_GetTextureCoordinate; - sInterface.m_getNormal = dm_ts_GetNormal; - sInterface.m_setTSpaceBasic = dm_ts_SetTSpace; - sInterface.m_setTSpace = nullptr; - - /* 0 if failed */ - genTangSpaceDefault(&sContext); - } + SGLSLMeshToTangent *mesh_data = static_cast<SGLSLMeshToTangent *>(taskdata); + + mikk::Mikktspace<SGLSLMeshToTangent> mikk(*mesh_data); + mikk.genTangSpace(); } void BKE_mesh_add_loop_tangent_named_layer_for_uv(CustomData *uv_data, |