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