Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/blender/blenkernel/intern/DerivedMesh.c201
-rw-r--r--source/blender/blenkernel/intern/editderivedmesh.c185
2 files changed, 351 insertions, 35 deletions
diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c
index 85fa7a39df3..fa529208101 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.c
+++ b/source/blender/blenkernel/intern/DerivedMesh.c
@@ -2990,6 +2990,9 @@ void mesh_get_mapped_verts_coords(DerivedMesh *dm, float (*r_cos)[3], const int
/** \name Tangent Space Calculation
* \{ */
+/* Necessary complexity to handle looptri's as quads for correct tangents */
+#define USE_LOOPTRI_DETECT_QUADS
+
typedef struct {
float (*precomputedFaceNormals)[3];
float (*precomputedLoopNormals)[3];
@@ -3002,6 +3005,13 @@ typedef struct {
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
+
} SGLSLMeshToTangent;
/* interface */
@@ -3010,14 +3020,30 @@ typedef struct {
static int dm_ts_GetNumFaces(const SMikkTSpaceContext *pContext)
{
SGLSLMeshToTangent *pMesh = pContext->m_pUserData;
+
+#ifdef USE_LOOPTRI_DETECT_QUADS
+ return pMesh->num_face_as_quad_map;
+#else
return pMesh->numTessFaces;
+#endif
}
static int dm_ts_GetNumVertsOfFace(const SMikkTSpaceContext *pContext, const int face_num)
{
- //SGLSLMeshToTangent *pMesh = pContext->m_pUserData;
+#ifdef USE_LOOPTRI_DETECT_QUADS
+ SGLSLMeshToTangent *pMesh = 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(
@@ -3026,8 +3052,30 @@ static void dm_ts_GetPosition(
{
//assert(vert_index >= 0 && vert_index < 4);
SGLSLMeshToTangent *pMesh = pContext->m_pUserData;
- const MLoopTri *lt = &pMesh->looptri[face_num];
- const float *co = pMesh->mvert[pMesh->mloop[lt->tri[vert_index]].v].co;
+ const MLoopTri *lt;
+ int loop_index;
+ const float *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 = mp->loopstart + vert_index;
+ goto finally;
+ }
+ /* 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:
+ co = pMesh->mvert[pMesh->mloop[loop_index].v].co;
copy_v3_v3(r_co, co);
}
@@ -3037,14 +3085,34 @@ static void dm_ts_GetTextureCoordinate(
{
//assert(vert_index >= 0 && vert_index < 4);
SGLSLMeshToTangent *pMesh = pContext->m_pUserData;
- const MLoopTri *lt = &pMesh->looptri[face_num];
+ const MLoopTri *lt;
+ int loop_index;
+
+#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 = mp->loopstart + vert_index;
+ goto finally;
+ }
+ /* 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->mloopuv != NULL) {
- const float *uv = pMesh->mloopuv[lt->tri[vert_index]].uv;
+ const float *uv = pMesh->mloopuv[loop_index].uv;
copy_v2_v2(r_uv, uv);
}
else {
- const float *orco = pMesh->orco[pMesh->mloop[lt->tri[vert_index]].v];
+ 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]);
}
}
@@ -3054,27 +3122,60 @@ static void dm_ts_GetNormal(
const int face_num, const int vert_index)
{
//assert(vert_index >= 0 && vert_index < 4);
- SGLSLMeshToTangent *pMesh = pContext->m_pUserData;
- const MLoopTri *lt = &pMesh->looptri[face_num];
- const bool smoothnormal = (pMesh->mpoly[lt->poly].flag & ME_SMOOTH) != 0;
+ SGLSLMeshToTangent *pMesh = (SGLSLMeshToTangent *) pContext->m_pUserData;
+ const MLoopTri *lt;
+ int loop_index;
+
+#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 = mp->loopstart + vert_index;
+ goto finally;
+ }
+ /* 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[lt->tri[vert_index]]);
+ copy_v3_v3(r_no, pMesh->precomputedLoopNormals[loop_index]);
}
- else if (!smoothnormal) { // flat
+ else if ((pMesh->mpoly[lt->poly].flag & ME_SMOOTH) == 0) { /* flat */
if (pMesh->precomputedFaceNormals) {
copy_v3_v3(r_no, pMesh->precomputedFaceNormals[lt->poly]);
}
else {
- const float *p0 = pMesh->mvert[pMesh->mloop[lt->tri[0]].v].co;
- const float *p1 = pMesh->mvert[pMesh->mloop[lt->tri[1]].v].co;
- const float *p2 = pMesh->mvert[pMesh->mloop[lt->tri[2]].v].co;
-
- normal_tri_v3(r_no, p0, p1, p2);
+#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
+#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);
+ }
}
}
else {
- const short *no = pMesh->mvert[pMesh->mloop[lt->tri[vert_index]].v].no;
+ const short *no = pMesh->mvert[pMesh->mloop[loop_index].v].no;
normal_short_to_float_v3(r_no, no);
}
}
@@ -3084,9 +3185,32 @@ static void dm_ts_SetTSpace(
const int face_num, const int vert_index)
{
//assert(vert_index >= 0 && vert_index < 4);
- SGLSLMeshToTangent *pMesh = pContext->m_pUserData;
- const MLoopTri *lt = &pMesh->looptri[face_num];
- float *pRes = pMesh->tangent[lt->tri[vert_index]];
+ SGLSLMeshToTangent *pMesh = (SGLSLMeshToTangent *) pContext->m_pUserData;
+ const MLoopTri *lt;
+ int loop_index;
+
+#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 = mp->loopstart + vert_index;
+ goto finally;
+ }
+ /* fall through to regular triangle */
+ }
+ else {
+ lt = &pMesh->looptri[face_num];
+ }
+#else
+ lt = &pMesh->looptri[face_num];
+#endif
+ loop_index = lt->tri[vert_index];
+
+ float *pRes;
+
+finally:
+ pRes = pMesh->tangent[loop_index];
copy_v3_v3(pRes, fvTangent);
pRes[3] = fSign;
}
@@ -3133,6 +3257,31 @@ void DM_calc_loop_tangents(DerivedMesh *dm)
DM_add_loop_layer(dm, CD_TANGENT, CD_CALLOC, NULL);
tangent = DM_get_loop_data_layer(dm, CD_TANGENT);
+#ifdef USE_LOOPTRI_DETECT_QUADS
+ int num_face_as_quad_map;
+ int *face_as_quad_map = NULL;
+
+ /* map faces to quads */
+ if (totface != dm->getNumPolys(dm)) {
+ /* over alloc, since we dont know how many ngon or quads we have */
+
+ /* map fake face index to looptri */
+ face_as_quad_map = MEM_mallocN(sizeof(int) * totface, __func__);
+ int i, j;
+ for (i = 0, j = 0; j < totface; i++, j++) {
+ face_as_quad_map[i] = j;
+ /* step over all quads */
+ if (mpoly[looptri[j].poly].totloop == 4) {
+ j++; /* skips the nest looptri */
+ }
+ }
+ num_face_as_quad_map = i;
+ }
+ else {
+ num_face_as_quad_map = totface;
+ }
+#endif
+
/* new computation method */
{
SGLSLMeshToTangent mesh2tangent = {NULL};
@@ -3150,6 +3299,11 @@ void DM_calc_loop_tangents(DerivedMesh *dm)
mesh2tangent.tangent = tangent;
mesh2tangent.numTessFaces = totface;
+#ifdef USE_LOOPTRI_DETECT_QUADS
+ mesh2tangent.face_as_quad_map = face_as_quad_map;
+ mesh2tangent.num_face_as_quad_map = num_face_as_quad_map;
+#endif
+
sContext.m_pUserData = &mesh2tangent;
sContext.m_pInterface = &sInterface;
sInterface.m_getNumFaces = dm_ts_GetNumFaces;
@@ -3161,6 +3315,13 @@ void DM_calc_loop_tangents(DerivedMesh *dm)
/* 0 if failed */
genTangSpaceDefault(&sContext);
+
+#ifdef USE_LOOPTRI_DETECT_QUADS
+ if (face_as_quad_map) {
+ MEM_freeN(face_as_quad_map);
+ }
+#undef USE_LOOPTRI_DETECT_QUADS
+#endif
}
}
diff --git a/source/blender/blenkernel/intern/editderivedmesh.c b/source/blender/blenkernel/intern/editderivedmesh.c
index 34da175e64b..bf6669c39a6 100644
--- a/source/blender/blenkernel/intern/editderivedmesh.c
+++ b/source/blender/blenkernel/intern/editderivedmesh.c
@@ -240,6 +240,9 @@ static void emDM_calcLoopNormalsSpaceArray(
/** \name Tangent Space Calculation
* \{ */
+/* Necessary complexity to handle looptri's as quads for correct tangents */
+#define USE_LOOPTRI_DETECT_QUADS
+
typedef struct {
const float (*precomputedFaceNormals)[3];
const float (*precomputedLoopNormals)[3];
@@ -249,22 +252,56 @@ typedef struct {
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
+
} SGLSLEditMeshToTangent;
+#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
+
/* interface */
#include "mikktspace.h"
static int emdm_ts_GetNumFaces(const SMikkTSpaceContext *pContext)
{
SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData;
+
+#ifdef USE_LOOPTRI_DETECT_QUADS
+ return pMesh->num_face_as_quad_map;
+#else
return pMesh->numTessFaces;
+#endif
}
static int emdm_ts_GetNumVertsOfFace(const SMikkTSpaceContext *pContext, const int face_num)
{
- //SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData;
+#ifdef USE_LOOPTRI_DETECT_QUADS
+ SGLSLEditMeshToTangent *pMesh = 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(
@@ -273,8 +310,30 @@ static void emdm_ts_GetPosition(
{
//assert(vert_index >= 0 && vert_index < 4);
SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData;
- const BMLoop **lt = pMesh->looptris[face_num];
- const float *co = lt[vert_index]->v->co;
+ 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;
+ }
+ /* fall through to regular triangle */
+ }
+ else {
+ lt = pMesh->looptris[face_num];
+ }
+#else
+ lt = pMesh->looptris[face_num];
+#endif
+ l = lt[vert_index];
+
+ const float *co;
+
+finally:
+ co = l->v->co;
copy_v3_v3(r_co, co);
}
@@ -284,14 +343,33 @@ static void emdm_ts_GetTextureCoordinate(
{
//assert(vert_index >= 0 && vert_index < 4);
SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData;
- const BMLoop **lt = pMesh->looptris[face_num];
+ 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;
+ }
+ /* 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->cd_loop_uv_offset != -1) {
- const float *uv = BM_ELEM_CD_GET_VOID_P(lt[vert_index], pMesh->cd_loop_uv_offset);
+ const float *uv = BM_ELEM_CD_GET_VOID_P(l, pMesh->cd_loop_uv_offset);
copy_v2_v2(r_uv, uv);
}
else {
- const float *orco = pMesh->orco[BM_elem_index_get(lt[vert_index]->v)];
+ 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]);
}
}
@@ -302,22 +380,40 @@ static void emdm_ts_GetNormal(
{
//assert(vert_index >= 0 && vert_index < 4);
SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData;
- const BMLoop **lt = pMesh->looptris[face_num];
- const bool smoothnormal = BM_elem_flag_test_bool(lt[0]->f, BM_ELEM_SMOOTH);
+ 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;
+ }
+ /* 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(lt[vert_index])]);
+ copy_v3_v3(r_no, pMesh->precomputedLoopNormals[BM_elem_index_get(l)]);
}
- else if (!smoothnormal) {
+ 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(lt[0]->f)]);
+ copy_v3_v3(r_no, pMesh->precomputedFaceNormals[BM_elem_index_get(l->f)]);
}
else {
- copy_v3_v3(r_no, lt[0]->f->no);
+ copy_v3_v3(r_no, l->f->no);
}
}
else {
- copy_v3_v3(r_no, lt[vert_index]->v->no);
+ copy_v3_v3(r_no, l->v->no);
}
}
@@ -327,8 +423,30 @@ static void emdm_ts_SetTSpace(
{
//assert(vert_index >= 0 && vert_index < 4);
SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData;
- const BMLoop **lt = pMesh->looptris[face_num];
- float *pRes = pMesh->tangent[BM_elem_index_get(lt[vert_index])];
+ 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;
+ }
+ /* fall through to regular triangle */
+ }
+ else {
+ lt = pMesh->looptris[face_num];
+ }
+#else
+ lt = pMesh->looptris[face_num];
+#endif
+ l = lt[vert_index];
+
+ float *pRes;
+
+finally:
+ pRes = pMesh->tangent[BM_elem_index_get(l)];
copy_v3_v3(pRes, fvTangent);
pRes[3] = fSign;
}
@@ -389,6 +507,31 @@ static void emDM_calcLoopTangents(DerivedMesh *dm)
DM_add_loop_layer(dm, CD_TANGENT, CD_CALLOC, NULL);
tangent = DM_get_loop_data_layer(dm, CD_TANGENT);
+#ifdef USE_LOOPTRI_DETECT_QUADS
+ int num_face_as_quad_map;
+ int *face_as_quad_map = NULL;
+
+ /* map faces to quads */
+ if (bmdm->em->tottri != bm->totface) {
+ /* over alloc, since we dont know how many ngon or quads we have */
+
+ /* map fake face index to looptri */
+ face_as_quad_map = MEM_mallocN(sizeof(int) * totface, __func__);
+ int i, j;
+ for (i = 0, j = 0; j < totface; i++, j++) {
+ face_as_quad_map[i] = j;
+ /* step over all quads */
+ if (em->looptris[j][0]->f->len == 4) {
+ j++; /* skips the nest looptri */
+ }
+ }
+ num_face_as_quad_map = i;
+ }
+ else {
+ num_face_as_quad_map = totface;
+ }
+#endif
+
/* new computation method */
{
SGLSLEditMeshToTangent mesh2tangent = {NULL};
@@ -403,6 +546,11 @@ static void emDM_calcLoopTangents(DerivedMesh *dm)
mesh2tangent.tangent = tangent;
mesh2tangent.numTessFaces = totface;
+#ifdef USE_LOOPTRI_DETECT_QUADS
+ mesh2tangent.face_as_quad_map = face_as_quad_map;
+ mesh2tangent.num_face_as_quad_map = num_face_as_quad_map;
+#endif
+
sContext.m_pUserData = &mesh2tangent;
sContext.m_pInterface = &sInterface;
sInterface.m_getNumFaces = emdm_ts_GetNumFaces;
@@ -414,6 +562,13 @@ static void emDM_calcLoopTangents(DerivedMesh *dm)
/* 0 if failed */
genTangSpaceDefault(&sContext);
+
+#ifdef USE_LOOPTRI_DETECT_QUADS
+ if (face_as_quad_map) {
+ MEM_freeN(face_as_quad_map);
+ }
+#undef USE_LOOPTRI_DETECT_QUADS
+#endif
}
}