Blender  V2.93
editmesh_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 "DNA_customdata_types.h"
25 #include "DNA_defs.h"
26 #include "DNA_meshdata_types.h"
27 
28 #include "BKE_editmesh.h"
29 #include "BKE_editmesh_tangent.h"
30 #include "BKE_mesh.h"
31 #include "BKE_mesh_tangent.h" /* for utility functions */
32 
33 #include "MEM_guardedalloc.h"
34 
35 /* interface */
36 #include "mikktspace.h"
37 
38 /* -------------------------------------------------------------------- */
42 /* Necessary complexity to handle looptri's as quads for correct tangents */
43 #define USE_LOOPTRI_DETECT_QUADS
44 
45 typedef struct {
46  const float (*precomputedFaceNormals)[3];
47  const float (*precomputedLoopNormals)[3];
48  const BMLoop *(*looptris)[3];
49  int cd_loop_uv_offset; /* texture coordinates */
50  const float (*orco)[3];
51  float (*tangent)[4]; /* destination */
53 
54 #ifdef USE_LOOPTRI_DETECT_QUADS
55  /* map from 'fake' face index to looptri,
56  * quads will point to the first looptri of the quad */
57  const int *face_as_quad_map;
59 #endif
60 
62 
63 #ifdef USE_LOOPTRI_DETECT_QUADS
64 /* seems weak but only used on quads */
65 static const BMLoop *bm_loop_at_face_index(const BMFace *f, int vert_index)
66 {
67  const BMLoop *l = BM_FACE_FIRST_LOOP(f);
68  while (vert_index--) {
69  l = l->next;
70  }
71  return l;
72 }
73 #endif
74 
75 static int emdm_ts_GetNumFaces(const SMikkTSpaceContext *pContext)
76 {
77  SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData;
78 
79 #ifdef USE_LOOPTRI_DETECT_QUADS
80  return pMesh->num_face_as_quad_map;
81 #else
82  return pMesh->numTessFaces;
83 #endif
84 }
85 
86 static int emdm_ts_GetNumVertsOfFace(const SMikkTSpaceContext *pContext, const int face_num)
87 {
88 #ifdef USE_LOOPTRI_DETECT_QUADS
89  SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData;
90  if (pMesh->face_as_quad_map) {
91  const BMLoop **lt = pMesh->looptris[pMesh->face_as_quad_map[face_num]];
92  if (lt[0]->f->len == 4) {
93  return 4;
94  }
95  }
96  return 3;
97 #else
98  UNUSED_VARS(pContext, face_num);
99  return 3;
100 #endif
101 }
102 
103 static void emdm_ts_GetPosition(const SMikkTSpaceContext *pContext,
104  float r_co[3],
105  const int face_num,
106  const int vert_index)
107 {
108  // BLI_assert(vert_index >= 0 && vert_index < 4);
109  SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData;
110  const BMLoop **lt;
111  const BMLoop *l;
112 
113 #ifdef USE_LOOPTRI_DETECT_QUADS
114  if (pMesh->face_as_quad_map) {
115  lt = pMesh->looptris[pMesh->face_as_quad_map[face_num]];
116  if (lt[0]->f->len == 4) {
117  l = bm_loop_at_face_index(lt[0]->f, vert_index);
118  goto finally;
119  }
120  /* fall through to regular triangle */
121  }
122  else {
123  lt = pMesh->looptris[face_num];
124  }
125 #else
126  lt = pMesh->looptris[face_num];
127 #endif
128  l = lt[vert_index];
129 
130  const float *co;
131 
132 finally:
133  co = l->v->co;
134  copy_v3_v3(r_co, co);
135 }
136 
138  float r_uv[2],
139  const int face_num,
140  const int vert_index)
141 {
142  // BLI_assert(vert_index >= 0 && vert_index < 4);
143  SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData;
144  const BMLoop **lt;
145  const BMLoop *l;
146 
147 #ifdef USE_LOOPTRI_DETECT_QUADS
148  if (pMesh->face_as_quad_map) {
149  lt = pMesh->looptris[pMesh->face_as_quad_map[face_num]];
150  if (lt[0]->f->len == 4) {
151  l = bm_loop_at_face_index(lt[0]->f, vert_index);
152  goto finally;
153  }
154  /* fall through to regular triangle */
155  }
156  else {
157  lt = pMesh->looptris[face_num];
158  }
159 #else
160  lt = pMesh->looptris[face_num];
161 #endif
162  l = lt[vert_index];
163 
164 finally:
165  if (pMesh->cd_loop_uv_offset != -1) {
166  const float *uv = BM_ELEM_CD_GET_VOID_P(l, pMesh->cd_loop_uv_offset);
167  copy_v2_v2(r_uv, uv);
168  }
169  else {
170  const float *orco = pMesh->orco[BM_elem_index_get(l->v)];
171  map_to_sphere(&r_uv[0], &r_uv[1], orco[0], orco[1], orco[2]);
172  }
173 }
174 
175 static void emdm_ts_GetNormal(const SMikkTSpaceContext *pContext,
176  float r_no[3],
177  const int face_num,
178  const int vert_index)
179 {
180  // BLI_assert(vert_index >= 0 && vert_index < 4);
181  SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData;
182  const BMLoop **lt;
183  const BMLoop *l;
184 
185 #ifdef USE_LOOPTRI_DETECT_QUADS
186  if (pMesh->face_as_quad_map) {
187  lt = pMesh->looptris[pMesh->face_as_quad_map[face_num]];
188  if (lt[0]->f->len == 4) {
189  l = bm_loop_at_face_index(lt[0]->f, vert_index);
190  goto finally;
191  }
192  /* fall through to regular triangle */
193  }
194  else {
195  lt = pMesh->looptris[face_num];
196  }
197 #else
198  lt = pMesh->looptris[face_num];
199 #endif
200  l = lt[vert_index];
201 
202 finally:
203  if (pMesh->precomputedLoopNormals) {
205  }
206  else if (BM_elem_flag_test(l->f, BM_ELEM_SMOOTH) == 0) { /* flat */
207  if (pMesh->precomputedFaceNormals) {
209  }
210  else {
211  copy_v3_v3(r_no, l->f->no);
212  }
213  }
214  else {
215  copy_v3_v3(r_no, l->v->no);
216  }
217 }
218 
219 static void emdm_ts_SetTSpace(const SMikkTSpaceContext *pContext,
220  const float fvTangent[3],
221  const float fSign,
222  const int face_num,
223  const int vert_index)
224 {
225  // BLI_assert(vert_index >= 0 && vert_index < 4);
226  SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData;
227  const BMLoop **lt;
228  const BMLoop *l;
229 
230 #ifdef USE_LOOPTRI_DETECT_QUADS
231  if (pMesh->face_as_quad_map) {
232  lt = pMesh->looptris[pMesh->face_as_quad_map[face_num]];
233  if (lt[0]->f->len == 4) {
234  l = bm_loop_at_face_index(lt[0]->f, vert_index);
235  goto finally;
236  }
237  /* fall through to regular triangle */
238  }
239  else {
240  lt = pMesh->looptris[face_num];
241  }
242 #else
243  lt = pMesh->looptris[face_num];
244 #endif
245  l = lt[vert_index];
246 
247  float *pRes;
248 
249 finally:
250  pRes = pMesh->tangent[BM_elem_index_get(l)];
251  copy_v3_v3(pRes, fvTangent);
252  pRes[3] = fSign;
253 }
254 
255 static void emDM_calc_loop_tangents_thread(TaskPool *__restrict UNUSED(pool), void *taskdata)
256 {
257  struct SGLSLEditMeshToTangent *mesh2tangent = taskdata;
258  /* new computation method */
259  {
260  SMikkTSpaceContext sContext = {NULL};
261  SMikkTSpaceInterface sInterface = {NULL};
262  sContext.m_pUserData = mesh2tangent;
263  sContext.m_pInterface = &sInterface;
264  sInterface.m_getNumFaces = emdm_ts_GetNumFaces;
266  sInterface.m_getPosition = emdm_ts_GetPosition;
268  sInterface.m_getNormal = emdm_ts_GetNormal;
269  sInterface.m_setTSpaceBasic = emdm_ts_SetTSpace;
270  /* 0 if failed */
271  genTangSpaceDefault(&sContext);
272  }
273 }
274 
283  bool calc_active_tangent,
284  const char (*tangent_names)[MAX_NAME],
285  int tangent_names_len,
286  const float (*poly_normals)[3],
287  const float (*loop_normals)[3],
288  const float (*vert_orco)[3],
289  /* result */
290  CustomData *loopdata_out,
291  const uint loopdata_out_len,
292  short *tangent_mask_curr_p)
293 {
294  BMesh *bm = em->bm;
295 
296  int act_uv_n = -1;
297  int ren_uv_n = -1;
298  bool calc_act = false;
299  bool calc_ren = false;
300  char act_uv_name[MAX_NAME];
301  char ren_uv_name[MAX_NAME];
302  short tangent_mask = 0;
303  short tangent_mask_curr = *tangent_mask_curr_p;
304 
306  calc_active_tangent,
307  tangent_names,
308  tangent_names_len,
309  &calc_act,
310  &calc_ren,
311  &act_uv_n,
312  &ren_uv_n,
313  act_uv_name,
314  ren_uv_name,
315  &tangent_mask);
316 
317  if ((tangent_mask_curr | tangent_mask) != tangent_mask_curr) {
318  for (int i = 0; i < tangent_names_len; i++) {
319  if (tangent_names[i][0]) {
321  &bm->ldata, loopdata_out, (int)loopdata_out_len, tangent_names[i]);
322  }
323  }
324  if ((tangent_mask & DM_TANGENT_MASK_ORCO) &&
325  CustomData_get_named_layer_index(loopdata_out, CD_TANGENT, "") == -1) {
327  loopdata_out, CD_TANGENT, CD_CALLOC, NULL, (int)loopdata_out_len, "");
328  }
329  if (calc_act && act_uv_name[0]) {
331  &bm->ldata, loopdata_out, (int)loopdata_out_len, act_uv_name);
332  }
333  if (calc_ren && ren_uv_name[0]) {
335  &bm->ldata, loopdata_out, (int)loopdata_out_len, ren_uv_name);
336  }
337  int totface = em->tottri;
338 #ifdef USE_LOOPTRI_DETECT_QUADS
340  int *face_as_quad_map = NULL;
341 
342  /* map faces to quads */
343  if (em->tottri != bm->totface) {
344  /* Over allocate, since we don't know how many ngon or quads we have. */
345 
346  /* map fake face index to looptri */
347  face_as_quad_map = MEM_mallocN(sizeof(int) * totface, __func__);
348  int i, j;
349  for (i = 0, j = 0; j < totface; i++, j++) {
350  face_as_quad_map[i] = j;
351  /* step over all quads */
352  if (em->looptris[j][0]->f->len == 4) {
353  j++; /* skips the nest looptri */
354  }
355  }
357  }
358  else {
359  num_face_as_quad_map = totface;
360  }
361 #endif
362  /* Calculation */
363  if (em->tottri != 0) {
366 
367  tangent_mask_curr = 0;
368  /* Calculate tangent layers */
370  int index = 0;
371  int n = 0;
372  CustomData_update_typemap(loopdata_out);
373  const int tangent_layer_num = CustomData_number_of_layers(loopdata_out, CD_TANGENT);
374  for (n = 0; n < tangent_layer_num; n++) {
375  index = CustomData_get_layer_index_n(loopdata_out, CD_TANGENT, n);
376  BLI_assert(n < MAX_MTFACE);
377  SGLSLEditMeshToTangent *mesh2tangent = &data_array[n];
378  mesh2tangent->numTessFaces = em->tottri;
379 #ifdef USE_LOOPTRI_DETECT_QUADS
380  mesh2tangent->face_as_quad_map = face_as_quad_map;
382 #endif
383  mesh2tangent->precomputedFaceNormals = poly_normals;
384  /* Note, we assume we do have tessellated loop normals at this point
385  * (in case it is object-enabled), have to check this is valid. */
386  mesh2tangent->precomputedLoopNormals = loop_normals;
388 
389  /* needed for indexing loop-tangents */
390  int htype_index = BM_LOOP;
391  if (mesh2tangent->cd_loop_uv_offset == -1) {
392  mesh2tangent->orco = vert_orco;
393  if (!mesh2tangent->orco) {
394  continue;
395  }
396  /* needed for orco lookups */
397  htype_index |= BM_VERT;
398  tangent_mask_curr |= DM_TANGENT_MASK_ORCO;
399  }
400  else {
401  /* Fill the resulting tangent_mask */
403  &bm->ldata, CD_MLOOPUV, loopdata_out->layers[index].name);
404  int uv_start = CustomData_get_layer_index(&bm->ldata, CD_MLOOPUV);
405  BLI_assert(uv_ind != -1 && uv_start != -1);
406  BLI_assert(uv_ind - uv_start < MAX_MTFACE);
407  tangent_mask_curr |= 1 << (uv_ind - uv_start);
408  }
409  if (mesh2tangent->precomputedFaceNormals) {
410  /* needed for face normal lookups */
411  htype_index |= BM_FACE;
412  }
413  BM_mesh_elem_index_ensure(bm, htype_index);
414 
415  mesh2tangent->looptris = (const BMLoop *(*)[3])em->looptris;
416  mesh2tangent->tangent = loopdata_out->layers[index].data;
417 
419  }
420 
421  BLI_assert(tangent_mask_curr == tangent_mask);
424  }
425  else {
426  tangent_mask_curr = tangent_mask;
427  }
428 #ifdef USE_LOOPTRI_DETECT_QUADS
429  if (face_as_quad_map) {
431  }
432 # undef USE_LOOPTRI_DETECT_QUADS
433 #endif
434  }
435 
436  *tangent_mask_curr_p = tangent_mask_curr;
437 
438  int act_uv_index = CustomData_get_layer_index_n(&bm->ldata, CD_MLOOPUV, act_uv_n);
439  if (act_uv_index >= 0) {
440  int tan_index = CustomData_get_named_layer_index(
441  loopdata_out, CD_TANGENT, bm->ldata.layers[act_uv_index].name);
442  CustomData_set_layer_active_index(loopdata_out, CD_TANGENT, tan_index);
443  } /* else tangent has been built from orco */
444 
445  /* Update render layer index */
446  int ren_uv_index = CustomData_get_layer_index_n(&bm->ldata, CD_MLOOPUV, ren_uv_n);
447  if (ren_uv_index >= 0) {
448  int tan_index = CustomData_get_named_layer_index(
449  loopdata_out, CD_TANGENT, bm->ldata.layers[ren_uv_index].name);
450  CustomData_set_layer_render_index(loopdata_out, CD_TANGENT, tan_index);
451  } /* else tangent has been built from orco */
452 }
453 
typedef float(TangentPoint)[2]
int CustomData_number_of_layers(const struct CustomData *data, int type)
@ CD_CALLOC
int CustomData_get_named_layer_index(const struct CustomData *data, int type, const char *name)
void CustomData_set_layer_render_index(struct CustomData *data, int type, int n)
Definition: customdata.c:2448
int CustomData_get_layer_index_n(const struct CustomData *data, int type, int n)
Definition: customdata.c:2308
void * CustomData_add_layer_named(struct CustomData *data, int type, eCDAllocType alloctype, void *layer, int totelem, const char *name)
Definition: customdata.c:2637
int CustomData_get_layer_index(const struct CustomData *data, int type)
void CustomData_set_layer_active_index(struct CustomData *data, int type, int n)
Definition: customdata.c:2439
int CustomData_get_n_offset(const struct CustomData *data, int type, int n)
void CustomData_update_typemap(struct CustomData *data)
Definition: customdata.c:2071
#define DM_TANGENT_MASK_ORCO
void BKE_mesh_add_loop_tangent_named_layer_for_uv(struct CustomData *uv_data, struct CustomData *tan_data, int numLoopData, const char *layer_name)
Definition: mesh_tangent.c:477
void BKE_mesh_calc_loop_tangent_step_0(const struct CustomData *loopData, bool calc_active_tangent, const char(*tangent_names)[64], int tangent_names_count, bool *rcalc_act, bool *rcalc_ren, int *ract_uv_n, int *rren_uv_n, char *ract_uv_name, char *rren_uv_name, short *rtangent_mask)
#define BLI_assert(a)
Definition: BLI_assert.h:58
void map_to_sphere(float *r_u, float *r_v, const float x, const float y, const float z)
Definition: math_geom.c:5236
MINLINE void copy_v2_v2(float r[2], const float a[2])
MINLINE void copy_v3_v3(float r[3], const float a[3])
unsigned int uint
Definition: BLI_sys_types.h:83
void BLI_task_pool_work_and_wait(TaskPool *pool)
Definition: task_pool.cc:496
TaskPool * BLI_task_pool_create(void *userdata, TaskPriority priority)
Definition: task_pool.cc:406
void BLI_task_pool_free(TaskPool *pool)
Definition: task_pool.cc:456
@ TASK_PRIORITY_LOW
Definition: BLI_task.h:66
void BLI_task_pool_push(TaskPool *pool, TaskRunFunction run, void *taskdata, bool free_taskdata, TaskFreeFunction freedata)
Definition: task_pool.cc:475
#define UNUSED_VARS(...)
#define UNUSED(x)
@ CD_MLOOPUV
@ CD_TANGENT
#define MAX_MTFACE
#define MAX_NAME
Definition: DNA_defs.h:62
Read Guarded memory(de)allocation.
@ BM_LOOP
Definition: bmesh_class.h:385
@ BM_FACE
Definition: bmesh_class.h:386
@ BM_VERT
Definition: bmesh_class.h:383
@ BM_ELEM_SMOOTH
Definition: bmesh_class.h:477
#define BM_FACE_FIRST_LOOP(p)
Definition: bmesh_class.h:553
#define BM_ELEM_CD_GET_VOID_P(ele, offset)
Definition: bmesh_class.h:530
#define BM_elem_index_get(ele)
Definition: bmesh_inline.h:124
#define BM_elem_flag_test(ele, hflag)
Definition: bmesh_inline.h:26
ATTR_WARN_UNUSED_RESULT BMesh * bm
void BM_mesh_elem_index_ensure(BMesh *bm, const char htype)
Definition: bmesh_mesh.c:2152
ATTR_WARN_UNUSED_RESULT const BMLoop * l
static int emdm_ts_GetNumFaces(const SMikkTSpaceContext *pContext)
static void emDM_calc_loop_tangents_thread(TaskPool *__restrict UNUSED(pool), void *taskdata)
void BKE_editmesh_loop_tangent_calc(BMEditMesh *em, bool calc_active_tangent, const char(*tangent_names)[MAX_NAME], int tangent_names_len, const float(*poly_normals)[3], const float(*loop_normals)[3], const float(*vert_orco)[3], CustomData *loopdata_out, const uint loopdata_out_len, short *tangent_mask_curr_p)
static void emdm_ts_GetNormal(const SMikkTSpaceContext *pContext, float r_no[3], const int face_num, const int vert_index)
static int emdm_ts_GetNumVertsOfFace(const SMikkTSpaceContext *pContext, const int face_num)
static const BMLoop * bm_loop_at_face_index(const BMFace *f, int vert_index)
static void emdm_ts_GetTextureCoordinate(const SMikkTSpaceContext *pContext, float r_uv[2], const int face_num, const int vert_index)
static void emdm_ts_SetTSpace(const SMikkTSpaceContext *pContext, const float fvTangent[3], const float fSign, const int face_num, const int vert_index)
static void emdm_ts_GetPosition(const SMikkTSpaceContext *pContext, float r_co[3], const int face_num, const int vert_index)
TaskPool * task_pool
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:47
tbool genTangSpaceDefault(const SMikkTSpaceContext *pContext)
Definition: mikktspace.c:269
struct BMLoop *(* looptris)[3]
Definition: BKE_editmesh.h:60
struct BMesh * bm
Definition: BKE_editmesh.h:52
int len
Definition: bmesh_class.h:279
float no[3]
Definition: bmesh_class.h:280
struct BMVert * v
Definition: bmesh_class.h:165
struct BMFace * f
Definition: bmesh_class.h:183
struct BMLoop * next
Definition: bmesh_class.h:245
float co[3]
Definition: bmesh_class.h:99
float no[3]
Definition: bmesh_class.h:100
CustomData ldata
Definition: bmesh_class.h:337
int totface
Definition: bmesh_class.h:297
CustomDataLayer * layers
const float(* precomputedFaceNormals)[3]
const BMLoop *(* looptris)[3]
const float(* orco)[3]
const float(* precomputedLoopNormals)[3]
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