Blender  V3.3
mesh_tangent.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2001-2002 NaN Holding BV. All rights reserved. */
3 
10 #include <limits.h>
11 
12 #include "MEM_guardedalloc.h"
13 
14 #include "DNA_mesh_types.h"
15 #include "DNA_meshdata_types.h"
16 
17 #include "BLI_math.h"
18 #include "BLI_task.h"
19 #include "BLI_utildefines.h"
20 
21 #include "BKE_customdata.h"
22 #include "BKE_mesh.h"
23 #include "BKE_mesh_runtime.h"
24 #include "BKE_mesh_tangent.h"
25 #include "BKE_report.h"
26 
27 #include "BLI_strict_flags.h"
28 
29 #include "atomic_ops.h"
30 #include "mikktspace.h"
31 
32 /* -------------------------------------------------------------------- */
36 /* Tangent space utils. */
37 
38 /* User data. */
39 typedef struct {
40  const MPoly *mpolys; /* faces */
41  const MLoop *mloops; /* faces's vertices */
42  const MVert *mverts; /* vertices */
43  const MLoopUV *luvs; /* texture coordinates */
44  const float (*lnors)[3]; /* loops' normals */
45  float (*tangents)[4]; /* output tangents */
46  int num_polys; /* number of polygons */
48 
49 /* Mikktspace's API */
50 static int get_num_faces(const SMikkTSpaceContext *pContext)
51 {
52  BKEMeshToTangent *p_mesh = (BKEMeshToTangent *)pContext->m_pUserData;
53  return p_mesh->num_polys;
54 }
55 
56 static int get_num_verts_of_face(const SMikkTSpaceContext *pContext, const int face_idx)
57 {
58  BKEMeshToTangent *p_mesh = (BKEMeshToTangent *)pContext->m_pUserData;
59  return p_mesh->mpolys[face_idx].totloop;
60 }
61 
62 static void get_position(const SMikkTSpaceContext *pContext,
63  float r_co[3],
64  const int face_idx,
65  const int vert_idx)
66 {
67  BKEMeshToTangent *p_mesh = (BKEMeshToTangent *)pContext->m_pUserData;
68  const int loop_idx = p_mesh->mpolys[face_idx].loopstart + vert_idx;
69  copy_v3_v3(r_co, p_mesh->mverts[p_mesh->mloops[loop_idx].v].co);
70 }
71 
72 static void get_texture_coordinate(const SMikkTSpaceContext *pContext,
73  float r_uv[2],
74  const int face_idx,
75  const int vert_idx)
76 {
77  BKEMeshToTangent *p_mesh = (BKEMeshToTangent *)pContext->m_pUserData;
78  copy_v2_v2(r_uv, p_mesh->luvs[p_mesh->mpolys[face_idx].loopstart + vert_idx].uv);
79 }
80 
81 static void get_normal(const SMikkTSpaceContext *pContext,
82  float r_no[3],
83  const int face_idx,
84  const int vert_idx)
85 {
86  BKEMeshToTangent *p_mesh = (BKEMeshToTangent *)pContext->m_pUserData;
87  copy_v3_v3(r_no, p_mesh->lnors[p_mesh->mpolys[face_idx].loopstart + vert_idx]);
88 }
89 
90 static void set_tspace(const SMikkTSpaceContext *pContext,
91  const float fv_tangent[3],
92  const float face_sign,
93  const int face_idx,
94  const int vert_idx)
95 {
96  BKEMeshToTangent *p_mesh = (BKEMeshToTangent *)pContext->m_pUserData;
97  float *p_res = p_mesh->tangents[p_mesh->mpolys[face_idx].loopstart + vert_idx];
98  copy_v3_v3(p_res, fv_tangent);
99  p_res[3] = face_sign;
100 }
101 
103  const int UNUSED(numVerts),
104  const MLoop *mloops,
105  float (*r_looptangent)[4],
106  const float (*loopnors)[3],
107  const MLoopUV *loopuvs,
108  const int UNUSED(numLoops),
109  const MPoly *mpolys,
110  const int numPolys,
111  ReportList *reports)
112 {
113  BKEMeshToTangent mesh_to_tangent = {NULL};
114  SMikkTSpaceContext s_context = {NULL};
115  SMikkTSpaceInterface s_interface = {NULL};
116 
117  const MPoly *mp;
118  int mp_index;
119 
120  /* First check we do have a tris/quads only mesh. */
121  for (mp = mpolys, mp_index = 0; mp_index < numPolys; mp++, mp_index++) {
122  if (mp->totloop > 4) {
123  BKE_report(
124  reports, RPT_ERROR, "Tangent space can only be computed for tris/quads, aborting");
125  return;
126  }
127  }
128 
129  /* Compute Mikktspace's tangent normals. */
130  mesh_to_tangent.mpolys = mpolys;
131  mesh_to_tangent.mloops = mloops;
132  mesh_to_tangent.mverts = mverts;
133  mesh_to_tangent.luvs = loopuvs;
134  mesh_to_tangent.lnors = loopnors;
135  mesh_to_tangent.tangents = r_looptangent;
136  mesh_to_tangent.num_polys = numPolys;
137 
138  s_context.m_pUserData = &mesh_to_tangent;
139  s_context.m_pInterface = &s_interface;
140  s_interface.m_getNumFaces = get_num_faces;
142  s_interface.m_getPosition = get_position;
144  s_interface.m_getNormal = get_normal;
145  s_interface.m_setTSpaceBasic = set_tspace;
146 
147  /* 0 if failed */
148  if (genTangSpaceDefault(&s_context) == false) {
149  BKE_report(reports, RPT_ERROR, "Mikktspace failed to generate tangents for this mesh!");
150  }
151 }
152 
154  const char *uvmap,
155  float (*r_looptangents)[4],
156  ReportList *reports)
157 {
158  const MLoopUV *loopuvs;
159 
160  /* Check we have valid texture coordinates first! */
161  if (uvmap) {
162  loopuvs = CustomData_get_layer_named(&mesh->ldata, CD_MLOOPUV, uvmap);
163  }
164  else {
166  }
167  if (!loopuvs) {
168  BKE_reportf(reports,
169  RPT_ERROR,
170  "Tangent space computation needs a UV Map, \"%s\" not found, aborting",
171  uvmap);
172  return;
173  }
174 
175  const float(*loopnors)[3] = CustomData_get_layer(&mesh->ldata, CD_NORMAL);
176  if (!loopnors) {
177  BKE_report(
178  reports, RPT_ERROR, "Tangent space computation needs loop normals, none found, aborting");
179  return;
180  }
181 
183  mesh->totvert,
184  mesh->mloop,
185  r_looptangents,
186  loopnors,
187  loopuvs,
188  mesh->totloop,
189  mesh->mpoly,
190  mesh->totpoly,
191  reports);
192 }
193 
196 /* -------------------------------------------------------------------- */
200 /* Necessary complexity to handle looptri's as quads for correct tangents */
201 #define USE_LOOPTRI_DETECT_QUADS
202 
203 typedef struct {
204  const float (*precomputedFaceNormals)[3];
205  const float (*precomputedLoopNormals)[3];
207  const MLoopUV *mloopuv; /* texture coordinates */
208  const MPoly *mpoly; /* indices */
209  const MLoop *mloop; /* indices */
210  const MVert *mvert; /* vertex coordinates */
211  const float (*vert_normals)[3];
212  const float (*orco)[3];
213  float (*tangent)[4]; /* destination */
215 
216 #ifdef USE_LOOPTRI_DETECT_QUADS
217  /* map from 'fake' face index to looptri,
218  * quads will point to the first looptri of the quad */
219  const int *face_as_quad_map;
221 #endif
222 
224 
225 /* interface */
226 static int dm_ts_GetNumFaces(const SMikkTSpaceContext *pContext)
227 {
228  SGLSLMeshToTangent *pMesh = pContext->m_pUserData;
229 
230 #ifdef USE_LOOPTRI_DETECT_QUADS
231  return pMesh->num_face_as_quad_map;
232 #else
233  return pMesh->numTessFaces;
234 #endif
235 }
236 
237 static int dm_ts_GetNumVertsOfFace(const SMikkTSpaceContext *pContext, const int face_num)
238 {
239 #ifdef USE_LOOPTRI_DETECT_QUADS
240  SGLSLMeshToTangent *pMesh = pContext->m_pUserData;
241  if (pMesh->face_as_quad_map) {
242  const MLoopTri *lt = &pMesh->looptri[pMesh->face_as_quad_map[face_num]];
243  const MPoly *mp = &pMesh->mpoly[lt->poly];
244  if (mp->totloop == 4) {
245  return 4;
246  }
247  }
248  return 3;
249 #else
250  UNUSED_VARS(pContext, face_num);
251  return 3;
252 #endif
253 }
254 
255 static void dm_ts_GetPosition(const SMikkTSpaceContext *pContext,
256  float r_co[3],
257  const int face_num,
258  const int vert_index)
259 {
260  // assert(vert_index >= 0 && vert_index < 4);
261  SGLSLMeshToTangent *pMesh = pContext->m_pUserData;
262  const MLoopTri *lt;
263  uint loop_index;
264  const float *co;
265 
266 #ifdef USE_LOOPTRI_DETECT_QUADS
267  if (pMesh->face_as_quad_map) {
268  lt = &pMesh->looptri[pMesh->face_as_quad_map[face_num]];
269  const MPoly *mp = &pMesh->mpoly[lt->poly];
270  if (mp->totloop == 4) {
271  loop_index = (uint)(mp->loopstart + vert_index);
272  goto finally;
273  }
274  /* fall through to regular triangle */
275  }
276  else {
277  lt = &pMesh->looptri[face_num];
278  }
279 #else
280  lt = &pMesh->looptri[face_num];
281 #endif
282  loop_index = lt->tri[vert_index];
283 
284 finally:
285  co = pMesh->mvert[pMesh->mloop[loop_index].v].co;
286  copy_v3_v3(r_co, co);
287 }
288 
289 static void dm_ts_GetTextureCoordinate(const SMikkTSpaceContext *pContext,
290  float r_uv[2],
291  const int face_num,
292  const int vert_index)
293 {
294  // assert(vert_index >= 0 && vert_index < 4);
295  SGLSLMeshToTangent *pMesh = pContext->m_pUserData;
296  const MLoopTri *lt;
297  uint loop_index;
298 
299 #ifdef USE_LOOPTRI_DETECT_QUADS
300  if (pMesh->face_as_quad_map) {
301  lt = &pMesh->looptri[pMesh->face_as_quad_map[face_num]];
302  const MPoly *mp = &pMesh->mpoly[lt->poly];
303  if (mp->totloop == 4) {
304  loop_index = (uint)(mp->loopstart + vert_index);
305  goto finally;
306  }
307  /* fall through to regular triangle */
308  }
309  else {
310  lt = &pMesh->looptri[face_num];
311  }
312 #else
313  lt = &pMesh->looptri[face_num];
314 #endif
315  loop_index = lt->tri[vert_index];
316 
317 finally:
318  if (pMesh->mloopuv != NULL) {
319  const float *uv = pMesh->mloopuv[loop_index].uv;
320  copy_v2_v2(r_uv, uv);
321  }
322  else {
323  const float *orco = pMesh->orco[pMesh->mloop[loop_index].v];
324  map_to_sphere(&r_uv[0], &r_uv[1], orco[0], orco[1], orco[2]);
325  }
326 }
327 
328 static void dm_ts_GetNormal(const SMikkTSpaceContext *pContext,
329  float r_no[3],
330  const int face_num,
331  const int vert_index)
332 {
333  // assert(vert_index >= 0 && vert_index < 4);
334  SGLSLMeshToTangent *pMesh = (SGLSLMeshToTangent *)pContext->m_pUserData;
335  const MLoopTri *lt;
336  uint loop_index;
337 
339  if (pMesh->face_as_quad_map) {
340  lt = &pMesh->looptri[pMesh->face_as_quad_map[face_num]];
341  const MPoly *mp = &pMesh->mpoly[lt->poly];
342  if (mp->totloop == 4) {
343  loop_index = (uint)(mp->loopstart + vert_index);
344  goto finally;
345  }
346  /* fall through to regular triangle */
347  }
348  else {
349  lt = &pMesh->looptri[face_num];
350  }
351 #else
352  lt = &pMesh->looptri[face_num];
353 #endif
354  loop_index = lt->tri[vert_index];
355 
356 finally:
357  if (pMesh->precomputedLoopNormals) {
358  copy_v3_v3(r_no, pMesh->precomputedLoopNormals[loop_index]);
359  }
360  else if ((pMesh->mpoly[lt->poly].flag & ME_SMOOTH) == 0) { /* flat */
361  if (pMesh->precomputedFaceNormals) {
362  copy_v3_v3(r_no, pMesh->precomputedFaceNormals[lt->poly]);
363  }
364  else {
365 #ifdef USE_LOOPTRI_DETECT_QUADS
366  const MPoly *mp = &pMesh->mpoly[lt->poly];
367  if (mp->totloop == 4) {
368  normal_quad_v3(r_no,
369  pMesh->mvert[pMesh->mloop[mp->loopstart + 0].v].co,
370  pMesh->mvert[pMesh->mloop[mp->loopstart + 1].v].co,
371  pMesh->mvert[pMesh->mloop[mp->loopstart + 2].v].co,
372  pMesh->mvert[pMesh->mloop[mp->loopstart + 3].v].co);
373  }
374  else
375 #endif
376  {
377  normal_tri_v3(r_no,
378  pMesh->mvert[pMesh->mloop[lt->tri[0]].v].co,
379  pMesh->mvert[pMesh->mloop[lt->tri[1]].v].co,
380  pMesh->mvert[pMesh->mloop[lt->tri[2]].v].co);
381  }
382  }
383  }
384  else {
385  copy_v3_v3(r_no, pMesh->vert_normals[pMesh->mloop[loop_index].v]);
386  }
387 }
388 
389 static void dm_ts_SetTSpace(const SMikkTSpaceContext *pContext,
390  const float fvTangent[3],
391  const float fSign,
392  const int face_num,
393  const int vert_index)
394 {
395  // assert(vert_index >= 0 && vert_index < 4);
396  SGLSLMeshToTangent *pMesh = (SGLSLMeshToTangent *)pContext->m_pUserData;
397  const MLoopTri *lt;
398  uint loop_index;
399 
401  if (pMesh->face_as_quad_map) {
402  lt = &pMesh->looptri[pMesh->face_as_quad_map[face_num]];
403  const MPoly *mp = &pMesh->mpoly[lt->poly];
404  if (mp->totloop == 4) {
405  loop_index = (uint)(mp->loopstart + vert_index);
406  goto finally;
407  }
408  /* fall through to regular triangle */
409  }
410  else {
411  lt = &pMesh->looptri[face_num];
412  }
413 #else
414  lt = &pMesh->looptri[face_num];
415 #endif
416  loop_index = lt->tri[vert_index];
417 
418  float *pRes;
419 
420 finally:
421  pRes = pMesh->tangent[loop_index];
422  copy_v3_v3(pRes, fvTangent);
423  pRes[3] = fSign;
424 }
425 
426 static void DM_calc_loop_tangents_thread(TaskPool *__restrict UNUSED(pool), void *taskdata)
427 {
428  struct SGLSLMeshToTangent *mesh2tangent = taskdata;
429  /* new computation method */
430  {
431  SMikkTSpaceContext sContext = {NULL};
432  SMikkTSpaceInterface sInterface = {NULL};
433 
434  sContext.m_pUserData = mesh2tangent;
435  sContext.m_pInterface = &sInterface;
436  sInterface.m_getNumFaces = dm_ts_GetNumFaces;
438  sInterface.m_getPosition = dm_ts_GetPosition;
440  sInterface.m_getNormal = dm_ts_GetNormal;
441  sInterface.m_setTSpaceBasic = dm_ts_SetTSpace;
442 
443  /* 0 if failed */
444  genTangSpaceDefault(&sContext);
445  }
446 }
447 
449  CustomData *tan_data,
450  int numLoopData,
451  const char *layer_name)
452 {
453  if (CustomData_get_named_layer_index(tan_data, CD_TANGENT, layer_name) == -1 &&
454  CustomData_get_named_layer_index(uv_data, CD_MLOOPUV, layer_name) != -1) {
455  CustomData_add_layer_named(tan_data, CD_TANGENT, CD_CALLOC, NULL, numLoopData, layer_name);
456  }
457 }
458 
460  bool calc_active_tangent,
461  const char (*tangent_names)[MAX_NAME],
462  int tangent_names_count,
463  bool *rcalc_act,
464  bool *rcalc_ren,
465  int *ract_uv_n,
466  int *rren_uv_n,
467  char *ract_uv_name,
468  char *rren_uv_name,
469  short *rtangent_mask)
470 {
471  /* Active uv in viewport */
472  int layer_index = CustomData_get_layer_index(loopData, CD_MLOOPUV);
473  *ract_uv_n = CustomData_get_active_layer(loopData, CD_MLOOPUV);
474  ract_uv_name[0] = 0;
475  if (*ract_uv_n != -1) {
476  strcpy(ract_uv_name, loopData->layers[*ract_uv_n + layer_index].name);
477  }
478 
479  /* Active tangent in render */
480  *rren_uv_n = CustomData_get_render_layer(loopData, CD_MLOOPUV);
481  rren_uv_name[0] = 0;
482  if (*rren_uv_n != -1) {
483  strcpy(rren_uv_name, loopData->layers[*rren_uv_n + layer_index].name);
484  }
485 
486  /* If active tangent not in tangent_names we take it into account */
487  *rcalc_act = false;
488  *rcalc_ren = false;
489  for (int i = 0; i < tangent_names_count; i++) {
490  if (tangent_names[i][0] == 0) {
491  calc_active_tangent = true;
492  }
493  }
494  if (calc_active_tangent) {
495  *rcalc_act = true;
496  *rcalc_ren = true;
497  for (int i = 0; i < tangent_names_count; i++) {
498  if (STREQ(ract_uv_name, tangent_names[i])) {
499  *rcalc_act = false;
500  }
501  if (STREQ(rren_uv_name, tangent_names[i])) {
502  *rcalc_ren = false;
503  }
504  }
505  }
506  *rtangent_mask = 0;
507 
508  const int uv_layer_num = CustomData_number_of_layers(loopData, CD_MLOOPUV);
509  for (int n = 0; n < uv_layer_num; n++) {
510  const char *name = CustomData_get_layer_name(loopData, CD_MLOOPUV, n);
511  bool add = false;
512  for (int i = 0; i < tangent_names_count; i++) {
513  if (tangent_names[i][0] && STREQ(tangent_names[i], name)) {
514  add = true;
515  break;
516  }
517  }
518  if (!add && ((*rcalc_act && ract_uv_name[0] && STREQ(ract_uv_name, name)) ||
519  (*rcalc_ren && rren_uv_name[0] && STREQ(rren_uv_name, name)))) {
520  add = true;
521  }
522  if (add) {
523  *rtangent_mask |= (short)(1 << n);
524  }
525  }
526 
527  if (uv_layer_num == 0) {
528  *rtangent_mask |= DM_TANGENT_MASK_ORCO;
529  }
530 }
531 
533  const MPoly *mpoly,
534  const uint mpoly_len,
535  const MLoop *mloop,
536  const MLoopTri *looptri,
537  const uint looptri_len,
538 
539  CustomData *loopdata,
540  bool calc_active_tangent,
541  const char (*tangent_names)[MAX_NAME],
542  int tangent_names_len,
543  const float (*vert_normals)[3],
544  const float (*poly_normals)[3],
545  const float (*loop_normals)[3],
546  const float (*vert_orco)[3],
547  /* result */
548  CustomData *loopdata_out,
549  const uint loopdata_out_len,
550  short *tangent_mask_curr_p)
551 {
552  int act_uv_n = -1;
553  int ren_uv_n = -1;
554  bool calc_act = false;
555  bool calc_ren = false;
556  char act_uv_name[MAX_NAME];
557  char ren_uv_name[MAX_NAME];
558  short tangent_mask = 0;
559  short tangent_mask_curr = *tangent_mask_curr_p;
560 
562  calc_active_tangent,
563  tangent_names,
564  tangent_names_len,
565  &calc_act,
566  &calc_ren,
567  &act_uv_n,
568  &ren_uv_n,
569  act_uv_name,
570  ren_uv_name,
571  &tangent_mask);
572  if ((tangent_mask_curr | tangent_mask) != tangent_mask_curr) {
573  /* Check we have all the needed layers */
574  /* Allocate needed tangent layers */
575  for (int i = 0; i < tangent_names_len; i++) {
576  if (tangent_names[i][0]) {
578  loopdata, loopdata_out, (int)loopdata_out_len, tangent_names[i]);
579  }
580  }
581  if ((tangent_mask & DM_TANGENT_MASK_ORCO) &&
582  CustomData_get_named_layer_index(loopdata, CD_TANGENT, "") == -1) {
584  loopdata_out, CD_TANGENT, CD_CALLOC, NULL, (int)loopdata_out_len, "");
585  }
586  if (calc_act && act_uv_name[0]) {
588  loopdata, loopdata_out, (int)loopdata_out_len, act_uv_name);
589  }
590  if (calc_ren && ren_uv_name[0]) {
592  loopdata, loopdata_out, (int)loopdata_out_len, ren_uv_name);
593  }
594 
595 #ifdef USE_LOOPTRI_DETECT_QUADS
597  int *face_as_quad_map = NULL;
598 
599  /* map faces to quads */
600  if (looptri_len != mpoly_len) {
601  /* Over allocate, since we don't know how many ngon or quads we have. */
602 
603  /* map fake face index to looptri */
604  face_as_quad_map = MEM_mallocN(sizeof(int) * looptri_len, __func__);
605  int k, j;
606  for (k = 0, j = 0; j < (int)looptri_len; k++, j++) {
607  face_as_quad_map[k] = j;
608  /* step over all quads */
609  if (mpoly[looptri[j].poly].totloop == 4) {
610  j++; /* skips the nest looptri */
611  }
612  }
614  }
615  else {
616  num_face_as_quad_map = (int)looptri_len;
617  }
618 #endif
619 
620  /* Calculation */
621  if (looptri_len != 0) {
623 
624  tangent_mask_curr = 0;
625  /* Calculate tangent layers */
626  SGLSLMeshToTangent data_array[MAX_MTFACE];
627  const int tangent_layer_num = CustomData_number_of_layers(loopdata_out, CD_TANGENT);
628  for (int n = 0; n < tangent_layer_num; n++) {
629  int index = CustomData_get_layer_index_n(loopdata_out, CD_TANGENT, n);
630  BLI_assert(n < MAX_MTFACE);
631  SGLSLMeshToTangent *mesh2tangent = &data_array[n];
632  mesh2tangent->numTessFaces = (int)looptri_len;
633 #ifdef USE_LOOPTRI_DETECT_QUADS
634  mesh2tangent->face_as_quad_map = face_as_quad_map;
636 #endif
637  mesh2tangent->mvert = mvert;
638  mesh2tangent->vert_normals = vert_normals;
639  mesh2tangent->mpoly = mpoly;
640  mesh2tangent->mloop = mloop;
641  mesh2tangent->looptri = looptri;
642  /* NOTE: we assume we do have tessellated loop normals at this point
643  * (in case it is object-enabled), have to check this is valid. */
644  mesh2tangent->precomputedLoopNormals = loop_normals;
645  mesh2tangent->precomputedFaceNormals = poly_normals;
646 
647  mesh2tangent->orco = NULL;
648  mesh2tangent->mloopuv = CustomData_get_layer_named(
649  loopdata, CD_MLOOPUV, loopdata_out->layers[index].name);
650 
651  /* Fill the resulting tangent_mask */
652  if (!mesh2tangent->mloopuv) {
653  mesh2tangent->orco = vert_orco;
654  if (!mesh2tangent->orco) {
655  continue;
656  }
657 
658  tangent_mask_curr |= DM_TANGENT_MASK_ORCO;
659  }
660  else {
662  loopdata, CD_MLOOPUV, loopdata_out->layers[index].name);
663  int uv_start = CustomData_get_layer_index(loopdata, CD_MLOOPUV);
664  BLI_assert(uv_ind != -1 && uv_start != -1);
665  BLI_assert(uv_ind - uv_start < MAX_MTFACE);
666  tangent_mask_curr |= (short)(1 << (uv_ind - uv_start));
667  }
668 
669  mesh2tangent->tangent = loopdata_out->layers[index].data;
671  }
672 
673  BLI_assert(tangent_mask_curr == tangent_mask);
676  }
677  else {
678  tangent_mask_curr = tangent_mask;
679  }
680 #ifdef USE_LOOPTRI_DETECT_QUADS
681  if (face_as_quad_map) {
683  }
684 # undef USE_LOOPTRI_DETECT_QUADS
685 
686 #endif
687 
688  *tangent_mask_curr_p = tangent_mask_curr;
689 
690  /* Update active layer index */
691  int act_uv_index = (act_uv_n != -1) ?
692  CustomData_get_layer_index_n(loopdata, CD_MLOOPUV, act_uv_n) :
693  -1;
694  if (act_uv_index != -1) {
695  int tan_index = CustomData_get_named_layer_index(
696  loopdata, CD_TANGENT, loopdata->layers[act_uv_index].name);
697  CustomData_set_layer_active_index(loopdata, CD_TANGENT, tan_index);
698  } /* else tangent has been built from orco */
699 
700  /* Update render layer index */
701  int ren_uv_index = (ren_uv_n != -1) ?
702  CustomData_get_layer_index_n(loopdata, CD_MLOOPUV, ren_uv_n) :
703  -1;
704  if (ren_uv_index != -1) {
705  int tan_index = CustomData_get_named_layer_index(
706  loopdata, CD_TANGENT, loopdata->layers[ren_uv_index].name);
707  CustomData_set_layer_render_index(loopdata, CD_TANGENT, tan_index);
708  } /* else tangent has been built from orco */
709  }
710 }
711 
713  bool calc_active_tangent,
714  const char (*tangent_names)[MAX_NAME],
715  int tangent_names_len)
716 {
718 
719  /* TODO(campbell): store in Mesh.runtime to avoid recalculation. */
720  short tangent_mask = 0;
722  me_eval->mpoly,
723  (uint)me_eval->totpoly,
724  me_eval->mloop,
725  me_eval->runtime.looptris.array,
726  (uint)me_eval->runtime.looptris.len,
727  &me_eval->ldata,
728  calc_active_tangent,
729  tangent_names,
730  tangent_names_len,
734  CustomData_get_layer(&me_eval->vdata, CD_ORCO), /* may be NULL */
735  /* result */
736  &me_eval->ldata,
737  (uint)me_eval->totloop,
738  &tangent_mask);
739 }
740 
typedef float(TangentPoint)[2]
CustomData interface, see also DNA_customdata_types.h.
const char * CustomData_get_layer_name(const struct CustomData *data, int type, int n)
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.cc:2590
int CustomData_get_layer_index_n(const struct CustomData *data, int type, int n)
void * CustomData_add_layer_named(struct CustomData *data, int type, eCDAllocType alloctype, void *layer, int totelem, const char *name)
Definition: customdata.cc:2792
int CustomData_get_active_layer(const struct CustomData *data, int type)
void * CustomData_get_layer_named(const struct CustomData *data, int type, const char *name)
int CustomData_get_layer_index(const struct CustomData *data, int type)
void * CustomData_get_layer(const struct CustomData *data, int type)
void CustomData_set_layer_active_index(struct CustomData *data, int type, int n)
Definition: customdata.cc:2578
int CustomData_get_render_layer(const struct CustomData *data, int type)
const float(* BKE_mesh_poly_normals_ensure(const struct Mesh *mesh))[3]
const float(* BKE_mesh_vertex_normals_ensure(const struct Mesh *mesh))[3]
const struct MLoopTri * BKE_mesh_runtime_looptri_ensure(const struct Mesh *mesh)
#define DM_TANGENT_MASK_ORCO
void BKE_reportf(ReportList *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition: report.c:83
#define BLI_assert(a)
Definition: BLI_assert.h:46
float normal_quad_v3(float n[3], const float v1[3], const float v2[3], const float v3[3], const float v4[3])
Definition: math_geom.c:50
void map_to_sphere(float *r_u, float *r_v, float x, float y, float z)
Definition: math_geom.c:4932
float normal_tri_v3(float n[3], const float v1[3], const float v2[3], const float v3[3])
Definition: math_geom.c:33
MINLINE void copy_v2_v2(float r[2], const float a[2])
MINLINE void copy_v3_v3(float r[3], const float a[3])
Strict compiler flags for areas of code we want to ensure don't do conversions without us knowing abo...
unsigned int uint
Definition: BLI_sys_types.h:67
@ TASK_PRIORITY_HIGH
Definition: BLI_task.h:57
void BLI_task_pool_work_and_wait(TaskPool *pool)
Definition: task_pool.cc:480
TaskPool * BLI_task_pool_create(void *userdata, eTaskPriority priority)
Definition: task_pool.cc:390
void BLI_task_pool_free(TaskPool *pool)
Definition: task_pool.cc:440
void BLI_task_pool_push(TaskPool *pool, TaskRunFunction run, void *taskdata, bool free_taskdata, TaskFreeFunction freedata)
Definition: task_pool.cc:459
#define UNUSED_VARS(...)
#define UNUSED(x)
#define STREQ(a, b)
@ CD_MLOOPUV
@ CD_TANGENT
#define MAX_MTFACE
#define MAX_NAME
Definition: DNA_defs.h:48
@ ME_SMOOTH
Read Guarded memory(de)allocation.
Provides wrapper around system-specific atomic primitives, and some extensions (faked-atomic operatio...
TaskPool * task_pool
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:33
static int dm_ts_GetNumFaces(const SMikkTSpaceContext *pContext)
Definition: mesh_tangent.c:226
static int get_num_faces(const SMikkTSpaceContext *pContext)
Definition: mesh_tangent.c:50
void BKE_mesh_calc_loop_tangent_single_ex(const MVert *mverts, const int UNUSED(numVerts), const MLoop *mloops, float(*r_looptangent)[4], const float(*loopnors)[3], const MLoopUV *loopuvs, const int UNUSED(numLoops), const MPoly *mpolys, const int numPolys, ReportList *reports)
Definition: mesh_tangent.c:102
static void dm_ts_GetTextureCoordinate(const SMikkTSpaceContext *pContext, float r_uv[2], const int face_num, const int vert_index)
Definition: mesh_tangent.c:289
static void get_position(const SMikkTSpaceContext *pContext, float r_co[3], const int face_idx, const int vert_idx)
Definition: mesh_tangent.c:62
#define USE_LOOPTRI_DETECT_QUADS
Definition: mesh_tangent.c:201
void BKE_mesh_calc_loop_tangent_ex(const MVert *mvert, const MPoly *mpoly, const uint mpoly_len, const MLoop *mloop, const MLoopTri *looptri, const uint looptri_len, CustomData *loopdata, bool calc_active_tangent, const char(*tangent_names)[MAX_NAME], int tangent_names_len, const float(*vert_normals)[3], 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)
Definition: mesh_tangent.c:532
static int dm_ts_GetNumVertsOfFace(const SMikkTSpaceContext *pContext, const int face_num)
Definition: mesh_tangent.c:237
static void dm_ts_SetTSpace(const SMikkTSpaceContext *pContext, const float fvTangent[3], const float fSign, const int face_num, const int vert_index)
Definition: mesh_tangent.c:389
static void dm_ts_GetPosition(const SMikkTSpaceContext *pContext, float r_co[3], const int face_num, const int vert_index)
Definition: mesh_tangent.c:255
static void set_tspace(const SMikkTSpaceContext *pContext, const float fv_tangent[3], const float face_sign, const int face_idx, const int vert_idx)
Definition: mesh_tangent.c:90
void BKE_mesh_add_loop_tangent_named_layer_for_uv(CustomData *uv_data, CustomData *tan_data, int numLoopData, const char *layer_name)
Definition: mesh_tangent.c:448
static void get_normal(const SMikkTSpaceContext *pContext, float r_no[3], const int face_idx, const int vert_idx)
Definition: mesh_tangent.c:81
void BKE_mesh_calc_loop_tangent_step_0(const CustomData *loopData, bool calc_active_tangent, const char(*tangent_names)[MAX_NAME], 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)
Definition: mesh_tangent.c:459
void BKE_mesh_calc_loop_tangents(Mesh *me_eval, bool calc_active_tangent, const char(*tangent_names)[MAX_NAME], int tangent_names_len)
Definition: mesh_tangent.c:712
static void DM_calc_loop_tangents_thread(TaskPool *__restrict UNUSED(pool), void *taskdata)
Definition: mesh_tangent.c:426
static int get_num_verts_of_face(const SMikkTSpaceContext *pContext, const int face_idx)
Definition: mesh_tangent.c:56
static void dm_ts_GetNormal(const SMikkTSpaceContext *pContext, float r_no[3], const int face_num, const int vert_index)
Definition: mesh_tangent.c:328
static void get_texture_coordinate(const SMikkTSpaceContext *pContext, float r_uv[2], const int face_idx, const int vert_idx)
Definition: mesh_tangent.c:72
void BKE_mesh_calc_loop_tangent_single(Mesh *mesh, const char *uvmap, float(*r_looptangents)[4], ReportList *reports)
Definition: mesh_tangent.c:153
tbool genTangSpaceDefault(const SMikkTSpaceContext *pContext)
Definition: mikktspace.c:253
bool add(void *owner, const AttributeIDRef &attribute_id, eAttrDomain domain, eCustomDataType data_type, const AttributeInit &initializer)
MutableSpan< float3 > tangents
const float(* lnors)[3]
Definition: mesh_tangent.c:44
float(* tangents)[4]
Definition: mesh_tangent.c:45
const MLoop * mloops
Definition: mesh_tangent.c:41
const MPoly * mpolys
Definition: mesh_tangent.c:40
const MLoopUV * luvs
Definition: mesh_tangent.c:43
const MVert * mverts
Definition: mesh_tangent.c:42
CustomDataLayer * layers
struct MLoopTri * array
unsigned int poly
unsigned int tri[3]
unsigned int v
float co[3]
struct MLoopTri_Store looptris
CustomData vdata
struct MVert * mvert
int totvert
struct MLoop * mloop
Mesh_Runtime runtime
int totpoly
int totloop
struct MPoly * mpoly
CustomData ldata
const MLoop * mloop
Definition: mesh_tangent.c:209
float(* tangent)[4]
Definition: mesh_tangent.c:213
const MVert * mvert
Definition: mesh_tangent.c:210
const float(* orco)[3]
Definition: mesh_tangent.c:212
const MLoopUV * mloopuv
Definition: mesh_tangent.c:207
const float(* precomputedLoopNormals)[3]
Definition: mesh_tangent.c:205
const MPoly * mpoly
Definition: mesh_tangent.c:208
const int * face_as_quad_map
Definition: mesh_tangent.c:219
const MLoopTri * looptri
Definition: mesh_tangent.c:206
const float(* vert_normals)[3]
Definition: mesh_tangent.c:211
const float(* precomputedFaceNormals)[3]
Definition: mesh_tangent.c:204
SMikkTSpaceInterface * m_pInterface
Definition: mikktspace.h:112
void(* m_getNormal)(const SMikkTSpaceContext *pContext, float fvNormOut[], const int iFace, const int iVert)
Definition: mikktspace.h:61
void(* m_getPosition)(const SMikkTSpaceContext *pContext, float fvPosOut[], const int iFace, const int iVert)
Definition: mikktspace.h:57
void(* m_getTexCoord)(const SMikkTSpaceContext *pContext, float fvTexcOut[], const int iFace, const int iVert)
Definition: mikktspace.h:65
void(* m_setTSpaceBasic)(const SMikkTSpaceContext *pContext, const float fvTangent[], const float fSign, const int iFace, const int iVert)
Definition: mikktspace.h:82
int(* m_getNumFaces)(const SMikkTSpaceContext *pContext)
Definition: mikktspace.h:49
int(* m_getNumVerticesOfFace)(const SMikkTSpaceContext *pContext, const int iFace)
Definition: mikktspace.h:53