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:
authorClément Foucault <foucault.clem@gmail.com>2020-01-31 04:49:35 +0300
committerClément Foucault <foucault.clem@gmail.com>2020-01-31 04:55:19 +0300
commitbcacf47cbcf72d13773577543835aaada7c8a522 (patch)
tree88621362a1801c4e4b54ea5467872ded8259ff04 /source/blender/blenkernel/intern/displist_tangent.c
parent2de704da6883dc89766d6b766b215596d38f8839 (diff)
Displist: Add mikktspace tangent space generation for DL_SURF
This should match mesh tangents form surfaces converted to mesh.
Diffstat (limited to 'source/blender/blenkernel/intern/displist_tangent.c')
-rw-r--r--source/blender/blenkernel/intern/displist_tangent.c161
1 files changed, 147 insertions, 14 deletions
diff --git a/source/blender/blenkernel/intern/displist_tangent.c b/source/blender/blenkernel/intern/displist_tangent.c
index 754aa78c0ac..4ac8d47feba 100644
--- a/source/blender/blenkernel/intern/displist_tangent.c
+++ b/source/blender/blenkernel/intern/displist_tangent.c
@@ -29,17 +29,21 @@
/* interface */
#include "mikktspace.h"
-/** \name Tangent Space Calculation
- * \{ */
-
-/* Necessary complexity to handle looptri's as quads for correct tangents */
-#define USE_LOOPTRI_DETECT_QUADS
-
typedef struct {
const DispList *dl;
float (*tangent)[4]; /* destination */
+ /** Face normal for flat shading. */
+ float (*fnormals)[3];
+ /** Use by surfaces. Size of the surface in faces. */
+ int u_len, v_len;
} SGLSLDisplistToTangent;
+/** \} */
+
+/* ---------------------------------------------------------------------- */
+/** \name DL_INDEX3 tangents
+ * \{ */
+
static int dl3_ts_GetNumFaces(const SMikkTSpaceContext *pContext)
{
SGLSLDisplistToTangent *dlt = pContext->m_pUserData;
@@ -102,10 +106,122 @@ static void dl3_ts_SetTSpace(const SMikkTSpaceContext *pContext,
dlt->tangent[0][3] = fSign;
}
-void BKE_displist_tangent_calc(const DispList *dl, float (*fnormals)[3], float (**r_tangent)[4])
+/** \} */
+
+/* ---------------------------------------------------------------------- */
+/** \name DL_SURF tangents
+ * \{ */
+
+static int dlsurf_ts_GetNumFaces(const SMikkTSpaceContext *pContext)
+{
+ SGLSLDisplistToTangent *dlt = pContext->m_pUserData;
+
+ return dlt->v_len * dlt->u_len;
+}
+
+static int dlsurf_ts_GetNumVertsOfFace(const SMikkTSpaceContext *pContext, const int face_num)
+{
+ UNUSED_VARS(pContext, face_num);
+
+ return 4;
+}
+
+static int face_to_vert_index(SGLSLDisplistToTangent *dlt,
+ const int face_num,
+ const int vert_index)
+{
+ int u = face_num % dlt->u_len;
+ int v = face_num / dlt->u_len;
+
+ if (vert_index == 0) {
+ u += 1;
+ }
+ else if (vert_index == 1) {
+ u += 1;
+ v += 1;
+ }
+ else if (vert_index == 2) {
+ v += 1;
+ }
+
+ /* Cyclic correction. */
+ u = u % dlt->dl->nr;
+ v = v % dlt->dl->parts;
+
+ return v * dlt->dl->nr + u;
+}
+
+static void dlsurf_ts_GetPosition(const SMikkTSpaceContext *pContext,
+ float r_co[3],
+ const int face_num,
+ const int vert_index)
+{
+ SGLSLDisplistToTangent *dlt = pContext->m_pUserData;
+ const float(*verts)[3] = (float(*)[3])dlt->dl->verts;
+
+ copy_v3_v3(r_co, verts[face_to_vert_index(dlt, face_num, vert_index)]);
+}
+
+static void dlsurf_ts_GetTextureCoordinate(const SMikkTSpaceContext *pContext,
+ float r_uv[2],
+ const int face_num,
+ const int vert_index)
+{
+ SGLSLDisplistToTangent *dlt = pContext->m_pUserData;
+
+ int idx = face_to_vert_index(dlt, face_num, vert_index);
+
+ /* Note: For some reason the shading U and V are swapped compared to the
+ * one described in the surface format. */
+ r_uv[0] = (idx / dlt->dl->nr) / (float)(dlt->v_len);
+ r_uv[1] = (idx % dlt->dl->nr) / (float)(dlt->u_len);
+
+ if (r_uv[0] == 0.0f && ELEM(vert_index, 1, 2)) {
+ r_uv[0] = 1.0f;
+ }
+ if (r_uv[1] == 0.0f && ELEM(vert_index, 0, 1)) {
+ r_uv[1] = 1.0f;
+ }
+}
+
+static void dlsurf_ts_GetNormal(const SMikkTSpaceContext *pContext,
+ float r_no[3],
+ const int face_num,
+ const int vert_index)
{
- UNUSED_VARS(fnormals);
+ SGLSLDisplistToTangent *dlt = pContext->m_pUserData;
+ const float(*nors)[3] = (float(*)[3])dlt->dl->nors;
+
+ if (dlt->fnormals) {
+ copy_v3_v3(r_no, dlt->fnormals[face_num]);
+ }
+ else {
+ copy_v3_v3(r_no, nors[face_to_vert_index(dlt, face_num, vert_index)]);
+ }
+}
+
+static void dlsurf_ts_SetTSpace(const SMikkTSpaceContext *pContext,
+ const float fvTangent[3],
+ const float fSign,
+ const int face_num,
+ const int vert_index)
+{
+ SGLSLDisplistToTangent *dlt = pContext->m_pUserData;
+ UNUSED_VARS(face_num, vert_index);
+
+ float *r_tan = dlt->tangent[face_num * 4 + vert_index];
+ copy_v3_v3(r_tan, fvTangent);
+ r_tan[3] = fSign;
+}
+
+/** \} */
+
+/* ---------------------------------------------------------------------- */
+/** \name Entry point
+ * \{ */
+void BKE_displist_tangent_calc(const DispList *dl, float (*fnormals)[3], float (**r_tangent)[4])
+{
if (dl->type == DL_INDEX3) {
/* INDEX3 have only one tangent so we don't need actual allocation. */
BLI_assert(*r_tangent != NULL);
@@ -128,14 +244,31 @@ void BKE_displist_tangent_calc(const DispList *dl, float (*fnormals)[3], float (
genTangSpaceDefault(&sContext);
}
else if (dl->type == DL_SURF) {
-#if 0
- int vert_len = dl->parts * dl->nr;
+ SGLSLDisplistToTangent mesh2tangent = {
+ .dl = dl,
+ .u_len = dl->nr - ((dl->flag & DL_CYCL_U) ? 0 : 1),
+ .v_len = dl->parts - ((dl->flag & DL_CYCL_V) ? 0 : 1),
+ .fnormals = fnormals,
+ };
+
+ int loop_len = mesh2tangent.u_len * mesh2tangent.v_len * 4;
+
if (*r_tangent == NULL) {
- *r_tangent = MEM_mallocN(sizeof(float[4]) * vert_len, "displist tangents");
+ *r_tangent = MEM_mallocN(sizeof(float[4]) * loop_len, "displist tangents");
}
-#endif
- /* TODO */
- BLI_assert(0);
+ mesh2tangent.tangent = *r_tangent;
+ SMikkTSpaceContext sContext = {NULL};
+ SMikkTSpaceInterface sInterface = {NULL};
+ sContext.m_pUserData = &mesh2tangent;
+ sContext.m_pInterface = &sInterface;
+ sInterface.m_getNumFaces = dlsurf_ts_GetNumFaces;
+ sInterface.m_getNumVerticesOfFace = dlsurf_ts_GetNumVertsOfFace;
+ sInterface.m_getPosition = dlsurf_ts_GetPosition;
+ sInterface.m_getTexCoord = dlsurf_ts_GetTextureCoordinate;
+ sInterface.m_getNormal = dlsurf_ts_GetNormal;
+ sInterface.m_setTSpaceBasic = dlsurf_ts_SetTSpace;
+ /* 0 if failed */
+ genTangSpaceDefault(&sContext);
}
else {
/* Unsupported. */