Blender  V2.93
displist_tangent.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16 
21 #include "BLI_math.h"
22 #include "BLI_task.h"
23 
24 #include "BKE_displist.h"
25 #include "BKE_displist_tangent.h"
26 
27 #include "MEM_guardedalloc.h"
28 
29 /* interface */
30 #include "mikktspace.h"
31 
32 typedef struct {
33  const DispList *dl;
34  float (*tangent)[4]; /* destination */
36  float (*fnormals)[3];
38  int u_len, v_len;
40 
43 /* ---------------------------------------------------------------------- */
47 static int dl3_ts_GetNumFaces(const SMikkTSpaceContext *pContext)
48 {
49  SGLSLDisplistToTangent *dlt = pContext->m_pUserData;
50 
51  return dlt->dl->parts;
52 }
53 
54 static int dl3_ts_GetNumVertsOfFace(const SMikkTSpaceContext *pContext, const int face_num)
55 {
56  UNUSED_VARS(pContext, face_num);
57 
58  return 3;
59 }
60 
61 static void dl3_ts_GetPosition(const SMikkTSpaceContext *pContext,
62  float r_co[3],
63  const int face_num,
64  const int vert_index)
65 {
66  SGLSLDisplistToTangent *dlt = pContext->m_pUserData;
67  const float(*verts)[3] = (float(*)[3])dlt->dl->verts;
68  const int(*idx)[3] = (int(*)[3])dlt->dl->index;
69 
70  copy_v3_v3(r_co, verts[idx[face_num][vert_index]]);
71 }
72 
73 static void dl3_ts_GetTextureCoordinate(const SMikkTSpaceContext *pContext,
74  float r_uv[2],
75  const int face_num,
76  const int vert_index)
77 {
78  SGLSLDisplistToTangent *dlt = pContext->m_pUserData;
79  const int(*idx)[3] = (int(*)[3])dlt->dl->index;
80 
81  r_uv[0] = idx[face_num][vert_index] / (float)(dlt->dl->nr - 1);
82  r_uv[1] = 0.0f;
83 }
84 
85 static void dl3_ts_GetNormal(const SMikkTSpaceContext *pContext,
86  float r_no[3],
87  const int face_num,
88  const int vert_index)
89 {
90  SGLSLDisplistToTangent *dlt = pContext->m_pUserData;
91  UNUSED_VARS(face_num, vert_index);
92 
93  copy_v3_v3(r_no, dlt->dl->nors);
94 }
95 
96 static void dl3_ts_SetTSpace(const SMikkTSpaceContext *pContext,
97  const float fvTangent[3],
98  const float fSign,
99  const int face_num,
100  const int vert_index)
101 {
102  SGLSLDisplistToTangent *dlt = pContext->m_pUserData;
103  UNUSED_VARS(face_num, vert_index);
104 
105  copy_v3_v3(dlt->tangent[0], fvTangent);
106  dlt->tangent[0][3] = fSign;
107 }
108 
111 /* ---------------------------------------------------------------------- */
115 static int dlsurf_ts_GetNumFaces(const SMikkTSpaceContext *pContext)
116 {
117  SGLSLDisplistToTangent *dlt = pContext->m_pUserData;
118 
119  return dlt->v_len * dlt->u_len;
120 }
121 
122 static int dlsurf_ts_GetNumVertsOfFace(const SMikkTSpaceContext *pContext, const int face_num)
123 {
124  UNUSED_VARS(pContext, face_num);
125 
126  return 4;
127 }
128 
130  const int face_num,
131  const int vert_index)
132 {
133  int u = face_num % dlt->u_len;
134  int v = face_num / dlt->u_len;
135 
136  if (vert_index == 0) {
137  u += 1;
138  }
139  else if (vert_index == 1) {
140  u += 1;
141  v += 1;
142  }
143  else if (vert_index == 2) {
144  v += 1;
145  }
146 
147  /* Cyclic correction. */
148  u = u % dlt->dl->nr;
149  v = v % dlt->dl->parts;
150 
151  return v * dlt->dl->nr + u;
152 }
153 
154 static void dlsurf_ts_GetPosition(const SMikkTSpaceContext *pContext,
155  float r_co[3],
156  const int face_num,
157  const int vert_index)
158 {
159  SGLSLDisplistToTangent *dlt = pContext->m_pUserData;
160  const float(*verts)[3] = (float(*)[3])dlt->dl->verts;
161 
162  copy_v3_v3(r_co, verts[face_to_vert_index(dlt, face_num, vert_index)]);
163 }
164 
166  float r_uv[2],
167  const int face_num,
168  const int vert_index)
169 {
170  SGLSLDisplistToTangent *dlt = pContext->m_pUserData;
171 
172  int idx = face_to_vert_index(dlt, face_num, vert_index);
173 
174  /* Note: For some reason the shading U and V are swapped compared to the
175  * one described in the surface format. */
176  r_uv[0] = (idx / dlt->dl->nr) / (float)(dlt->v_len);
177  r_uv[1] = (idx % dlt->dl->nr) / (float)(dlt->u_len);
178 
179  if (r_uv[0] == 0.0f && ELEM(vert_index, 1, 2)) {
180  r_uv[0] = 1.0f;
181  }
182  if (r_uv[1] == 0.0f && ELEM(vert_index, 0, 1)) {
183  r_uv[1] = 1.0f;
184  }
185 }
186 
187 static void dlsurf_ts_GetNormal(const SMikkTSpaceContext *pContext,
188  float r_no[3],
189  const int face_num,
190  const int vert_index)
191 {
192  SGLSLDisplistToTangent *dlt = pContext->m_pUserData;
193  const float(*nors)[3] = (float(*)[3])dlt->dl->nors;
194 
195  if (dlt->fnormals) {
196  copy_v3_v3(r_no, dlt->fnormals[face_num]);
197  }
198  else {
199  copy_v3_v3(r_no, nors[face_to_vert_index(dlt, face_num, vert_index)]);
200  }
201 }
202 
203 static void dlsurf_ts_SetTSpace(const SMikkTSpaceContext *pContext,
204  const float fvTangent[3],
205  const float fSign,
206  const int face_num,
207  const int vert_index)
208 {
209  SGLSLDisplistToTangent *dlt = pContext->m_pUserData;
210  UNUSED_VARS(face_num, vert_index);
211 
212  float *r_tan = dlt->tangent[face_num * 4 + vert_index];
213  copy_v3_v3(r_tan, fvTangent);
214  r_tan[3] = fSign;
215 }
216 
219 /* ---------------------------------------------------------------------- */
223 void BKE_displist_tangent_calc(const DispList *dl, float (*fnormals)[3], float (**r_tangent)[4])
224 {
225  if (dl->type == DL_INDEX3) {
226  /* INDEX3 have only one tangent so we don't need actual allocation. */
227  BLI_assert(*r_tangent != NULL);
228 
229  SGLSLDisplistToTangent mesh2tangent = {
230  .tangent = *r_tangent,
231  .dl = dl,
232  };
233  SMikkTSpaceContext sContext = {NULL};
234  SMikkTSpaceInterface sInterface = {NULL};
235  sContext.m_pUserData = &mesh2tangent;
236  sContext.m_pInterface = &sInterface;
237  sInterface.m_getNumFaces = dl3_ts_GetNumFaces;
239  sInterface.m_getPosition = dl3_ts_GetPosition;
241  sInterface.m_getNormal = dl3_ts_GetNormal;
242  sInterface.m_setTSpaceBasic = dl3_ts_SetTSpace;
243  /* 0 if failed */
244  genTangSpaceDefault(&sContext);
245  }
246  else if (dl->type == DL_SURF) {
247  SGLSLDisplistToTangent mesh2tangent = {
248  .dl = dl,
249  .u_len = dl->nr - ((dl->flag & DL_CYCL_U) ? 0 : 1),
250  .v_len = dl->parts - ((dl->flag & DL_CYCL_V) ? 0 : 1),
251  .fnormals = fnormals,
252  };
253 
254  int loop_len = mesh2tangent.u_len * mesh2tangent.v_len * 4;
255 
256  if (*r_tangent == NULL) {
257  *r_tangent = MEM_mallocN(sizeof(float[4]) * loop_len, "displist tangents");
258  }
259  mesh2tangent.tangent = *r_tangent;
260  SMikkTSpaceContext sContext = {NULL};
261  SMikkTSpaceInterface sInterface = {NULL};
262  sContext.m_pUserData = &mesh2tangent;
263  sContext.m_pInterface = &sInterface;
268  sInterface.m_getNormal = dlsurf_ts_GetNormal;
270  /* 0 if failed */
271  genTangSpaceDefault(&sContext);
272  }
273  else {
274  /* Unsupported. */
275  BLI_assert(0);
276  }
277 }
278 
typedef float(TangentPoint)[2]
display list (or rather multi purpose list) stuff.
@ DL_CYCL_V
Definition: BKE_displist.h:54
@ DL_CYCL_U
Definition: BKE_displist.h:53
@ DL_SURF
Definition: BKE_displist.h:40
@ DL_INDEX3
Definition: BKE_displist.h:42
#define BLI_assert(a)
Definition: BLI_assert.h:58
MINLINE void copy_v3_v3(float r[3], const float a[3])
#define UNUSED_VARS(...)
#define ELEM(...)
Read Guarded memory(de)allocation.
ATTR_WARN_UNUSED_RESULT const BMVert * v
static int face_to_vert_index(SGLSLDisplistToTangent *dlt, const int face_num, const int vert_index)
static void dlsurf_ts_GetNormal(const SMikkTSpaceContext *pContext, float r_no[3], const int face_num, const int 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)
void BKE_displist_tangent_calc(const DispList *dl, float(*fnormals)[3], float(**r_tangent)[4])
static int dl3_ts_GetNumVertsOfFace(const SMikkTSpaceContext *pContext, const int face_num)
static int dl3_ts_GetNumFaces(const SMikkTSpaceContext *pContext)
static void dl3_ts_GetNormal(const SMikkTSpaceContext *pContext, float r_no[3], const int face_num, const int vert_index)
static void dl3_ts_GetPosition(const SMikkTSpaceContext *pContext, float r_co[3], const int face_num, const int vert_index)
static void dl3_ts_GetTextureCoordinate(const SMikkTSpaceContext *pContext, float r_uv[2], const int face_num, const int vert_index)
static void dlsurf_ts_GetTextureCoordinate(const SMikkTSpaceContext *pContext, float r_uv[2], const int face_num, const int vert_index)
static int dlsurf_ts_GetNumFaces(const SMikkTSpaceContext *pContext)
static void dl3_ts_SetTSpace(const SMikkTSpaceContext *pContext, const float fvTangent[3], const float fSign, const int face_num, const int vert_index)
static void dlsurf_ts_GetPosition(const SMikkTSpaceContext *pContext, float r_co[3], const int face_num, const int vert_index)
static int dlsurf_ts_GetNumVertsOfFace(const SMikkTSpaceContext *pContext, const int face_num)
static float verts[][3]
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:47
tbool genTangSpaceDefault(const SMikkTSpaceContext *pContext)
Definition: mikktspace.c:269
short type
Definition: BKE_displist.h:71
float * verts
Definition: BKE_displist.h:74
int * index
Definition: BKE_displist.h:75
float * nors
Definition: BKE_displist.h:74
short flag
Definition: BKE_displist.h:71
SMikkTSpaceInterface * m_pInterface
Definition: mikktspace.h:128
void(* m_getNormal)(const SMikkTSpaceContext *pContext, float fvNormOut[], const int iFace, const int iVert)
Definition: mikktspace.h:77
void(* m_getPosition)(const SMikkTSpaceContext *pContext, float fvPosOut[], const int iFace, const int iVert)
Definition: mikktspace.h:73
void(* m_getTexCoord)(const SMikkTSpaceContext *pContext, float fvTexcOut[], const int iFace, const int iVert)
Definition: mikktspace.h:81
void(* m_setTSpaceBasic)(const SMikkTSpaceContext *pContext, const float fvTangent[], const float fSign, const int iFace, const int iVert)
Definition: mikktspace.h:98
int(* m_getNumFaces)(const SMikkTSpaceContext *pContext)
Definition: mikktspace.h:65
int(* m_getNumVerticesOfFace)(const SMikkTSpaceContext *pContext, const int iFace)
Definition: mikktspace.h:69