[Bf-blender-cvs] [bcacf47cbcf] blender-v2.82-release: Displist: Add mikktspace tangent space generation for DL_SURF

Clément Foucault noreply at git.blender.org
Fri Jan 31 04:24:37 CET 2020


Commit: bcacf47cbcf72d13773577543835aaada7c8a522
Author: Clément Foucault
Date:   Fri Jan 31 02:49:35 2020 +0100
Branches: blender-v2.82-release
https://developer.blender.org/rBbcacf47cbcf72d13773577543835aaada7c8a522

Displist: Add mikktspace tangent space generation for DL_SURF

This should match mesh tangents form surfaces converted to mesh.

===================================================================

M	source/blender/blenkernel/intern/displist_tangent.c
M	source/blender/draw/intern/draw_cache_impl_displist.c

===================================================================

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. */
diff --git a/source/blender/draw/intern/draw_cache_impl_displist.c b/source/blender/draw/intern/draw_cache_impl_displist.c
index 10f4b7ddbb6..50979d72189 100644
--- a/source/blender/draw/intern/draw_cache_impl_displist.c
+++ b/source/blender/draw/intern/draw_cache_impl_displist.c
@@ -362,32 +362,6 @@ static void surf_uv_quad(const DispList *dl, const uint quad[4], float r_uv[4][2
   }
 }
 
-static GPUPackedNormal surf_tan_quad(const DispList *dl,
-                                     const float (*verts)[3],
-                                     const float nor[3],
-                                     uint index)
-{
-  float tan[3], tmp[3];
-
-  int v = index / dl->nr;
-  /* Note: For some reason the shading U and V are swapped compared to the
-   * one described in the surface format. So tangent is along V. */
-  if (v == 0) {
-    sub_v3_v3v3(tan, verts[index + dl->nr], verts[index]);
-  }
-  else {
-    sub_v3_v3v3(tan, verts[index], verts[index - dl->nr]);
-  }
-  /* Orthonormalize around the normal. */
-  cross_v3_v3v3(tmp, nor, tan);
-  cross_v3_v3v3(tan, tmp, nor);
-  normalize_v3(tan);
-
-  GPUPackedNormal ptan = GPU_normal_convert_i10_v3(tan);
-  ptan.w = 1; /* Pretty sure surfaces cannot have inverted normals. */
-  return ptan;
-}
-
 static void displist_vertbuf_attr_set_tri_pos_nor_uv(GPUVertBufRaw *pos_step,
                                                      GPUVertBufRaw *nor_step,
                                                      GPUVertBufRaw *uv_step,
@@ -428,6 +402,54 @@ static void displist_vertbuf_attr_set_tri_pos_nor_uv(GPUVertBufRaw *pos_step,
   }
 }
 
+#define SURFACE_QUAD_ITER_START(dl) \
+  { \
+    uint quad[4]; \
+    int quad_index = 0; \
+    int max_v = (dl->flag & DL_CYCL_V) ? dl->parts : (dl->parts - 1); \
+    int max_u = (dl->flag & DL_CYCL_U) ? dl->nr : (dl->nr - 1); \
+    for (int v = 0; v < max_v; v++) { \
+      quad[3] = dl->nr * v; \
+      quad[0] = quad[3] + 1; \
+      quad[2] = quad[3] + dl->nr; \
+      quad[1] = quad[0] + dl->nr; \
+      /* Cyclic wrap */ \
+      if (v == dl->parts - 1) { \
+        quad[1] -= dl->parts * dl->nr; \
+        quad[2] -= dl->parts * dl->nr; \
+      } \
+      for (int u = 0; u < max_u; u++, quad_index++) { \
+        /* Cyclic wrap */ \
+        if (u == dl->nr - 1) { \
+          quad[0] -= dl->nr; \
+          quad[1] -= dl->nr; \
+        }
+
+#define SURFACE_QUAD_ITER_END \
+  quad[2] = quad[1]; \
+  quad[1]++; \
+  quad[3] = quad[0]; \
+  quad[0]++; \
+  } \
+  } \
+  }
+
+static void displist_surf_fnors_ensure(const DispList *dl, float (**fnors)[3])
+{
+  int u_len = dl->nr - ((dl->flag & DL_CYCL_U) ? 0 : 1);
+  int v_len = dl->parts - ((dl->flag & DL_CYCL_V) ? 0 : 1);
+  const float(*verts)[3] = (float(*)[3])dl->verts;
+  float(*nor_flat)[3] = MEM_mallocN(sizeof(float) * 3 * u_len * v_len, __func__);
+  *fnors = nor_flat;
+
+  SURFACE_QUAD_ITER_START(dl)
+  {
+    normal_quad_v3(*nor_flat, verts[quad[0]], verts[quad[1]], verts[quad[2]], verts[quad[3]]);
+    nor_flat++;
+  }
+  SURFACE_QUAD_ITER_END
+}
+
 void DRW_displist_vertbuf_create_loop_pos_and_nor_and_uv_and_tan(ListBase *lb,
                                                                  GPUVertBuf *vbo_pos_nor,
                                                                  GPUVertBuf *vbo_uv,
@@ -495,7 +517,7 @@ void DRW_displist_vertbuf_create_loop_pos_and_nor_and_uv_and_tan(ListBase *lb,
         const GPUPackedNormal pnor = GPU_normal_convert_i10_v3(dl->nors);
 
         GPUPackedNormal ptan = {0, 0, 0, 1};
-        if (tan_step.size != 0) {
+        if (vbo_tan) {
           float tan[4];
           float(*tan_ptr)[4] = &tan;
           BKE_displist_tangent_calc(dl, NULL, &tan_ptr);
@@ -533,102 +555,81 @@ void DRW_displist_vertbuf_create_loop_pos_and_nor_and_uv_and_tan(ListBase *lb,
         }
       }
       else if (dl->type == DL_SURF) {
-        uint quad[4];
-        for (int a = 0; a < dl->parts; a++) {
-          if 

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list