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
20 /** \file
21 * \ingroup bke
22 *
23 * Functions to evaluate mesh tangents.
24 */
25
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 /* -------------------------------------------------------------------- */
49 /** \name Mesh Tangent Calculations (Single Layer)
50 * \{ */
51
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 */
63 } BKEMeshToTangent;
64
65 /* Mikktspace's API */
get_num_faces(const SMikkTSpaceContext * pContext)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
get_num_verts_of_face(const SMikkTSpaceContext * pContext,const int face_idx)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
get_position(const SMikkTSpaceContext * pContext,float r_co[3],const int face_idx,const int vert_idx)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
get_texture_coordinate(const SMikkTSpaceContext * pContext,float r_uv[2],const int face_idx,const int vert_idx)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
get_normal(const SMikkTSpaceContext * pContext,float r_no[3],const int face_idx,const int vert_idx)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
set_tspace(const SMikkTSpaceContext * pContext,const float fv_tangent[3],const float face_sign,const int face_idx,const int vert_idx)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
118 /**
119 * Compute simplified tangent space normals, i.e.
120 * tangent vector + sign of bi-tangent one, which combined with
121 * split normals can be used to recreate the full tangent space.
122 * Note: * The mesh should be made of only tris and quads!
123 */
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)124 void BKE_mesh_calc_loop_tangent_single_ex(const MVert *mverts,
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;
163 s_interface.m_getNumVerticesOfFace = get_num_verts_of_face;
164 s_interface.m_getPosition = get_position;
165 s_interface.m_getTexCoord = get_texture_coordinate;
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
175 /**
176 * Wrapper around BKE_mesh_calc_loop_tangent_single_ex, which takes care of most boiling code.
177 * \note
178 * - There must be a valid loop's CD_NORMALS available.
179 * - The mesh should be made of only tris and quads!
180 */
BKE_mesh_calc_loop_tangent_single(Mesh * mesh,const char * uvmap,float (* r_looptangents)[4],ReportList * reports)181 void BKE_mesh_calc_loop_tangent_single(Mesh *mesh,
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 {
194 loopuvs = CustomData_get_layer(&mesh->ldata, CD_MLOOPUV);
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
211 BKE_mesh_calc_loop_tangent_single_ex(mesh->mvert,
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
223 /** \} */
224
225 /* -------------------------------------------------------------------- */
226 /** \name Mesh Tangent Calculations (All Layers)
227 * \{ */
228
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];
235 const MLoopTri *looptri;
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 */
242 int numTessFaces;
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;
248 int num_face_as_quad_map;
249 #endif
250
251 } SGLSLMeshToTangent;
252
253 /* interface */
dm_ts_GetNumFaces(const SMikkTSpaceContext * pContext)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
dm_ts_GetNumVertsOfFace(const SMikkTSpaceContext * pContext,const int face_num)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
dm_ts_GetPosition(const SMikkTSpaceContext * pContext,float r_co[3],const int face_num,const int vert_index)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
dm_ts_GetTextureCoordinate(const SMikkTSpaceContext * pContext,float r_uv[2],const int face_num,const int vert_index)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
dm_ts_GetNormal(const SMikkTSpaceContext * pContext,float r_no[3],const int face_num,const int vert_index)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
366 #ifdef USE_LOOPTRI_DETECT_QUADS
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
dm_ts_SetTSpace(const SMikkTSpaceContext * pContext,const float fvTangent[3],const float fSign,const int face_num,const int vert_index)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
429 #ifdef USE_LOOPTRI_DETECT_QUADS
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
DM_calc_loop_tangents_thread(TaskPool * __restrict UNUSED (pool),void * taskdata)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;
466 sInterface.m_getNumVerticesOfFace = dm_ts_GetNumVertsOfFace;
467 sInterface.m_getPosition = dm_ts_GetPosition;
468 sInterface.m_getTexCoord = dm_ts_GetTextureCoordinate;
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
BKE_mesh_add_loop_tangent_named_layer_for_uv(CustomData * uv_data,CustomData * tan_data,int numLoopData,const char * layer_name)477 void BKE_mesh_add_loop_tangent_named_layer_for_uv(CustomData *uv_data,
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
488 /**
489 * Here we get some useful information such as active uv layer name and
490 * search if it is already in tangent_names.
491 * Also, we calculate tangent_mask that works as a descriptor of tangents state.
492 * If tangent_mask has changed, then recalculate tangents.
493 */
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)494 void BKE_mesh_calc_loop_tangent_step_0(const CustomData *loopData,
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
567 /**
568 * See: #BKE_editmesh_loop_tangent_calc (matching logic).
569 */
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)570 void BKE_mesh_calc_loop_tangent_ex(const MVert *mvert,
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
598 BKE_mesh_calc_loop_tangent_step_0(loopdata,
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]) {
614 BKE_mesh_add_loop_tangent_named_layer_for_uv(
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) {
620 CustomData_add_layer_named(
621 loopdata_out, CD_TANGENT, CD_CALLOC, NULL, (int)loopdata_out_len, "");
622 }
623 if (calc_act && act_uv_name[0]) {
624 BKE_mesh_add_loop_tangent_named_layer_for_uv(
625 loopdata, loopdata_out, (int)loopdata_out_len, act_uv_name);
626 }
627 if (calc_ren && ren_uv_name[0]) {
628 BKE_mesh_add_loop_tangent_named_layer_for_uv(
629 loopdata, loopdata_out, (int)loopdata_out_len, ren_uv_name);
630 }
631
632 #ifdef USE_LOOPTRI_DETECT_QUADS
633 int num_face_as_quad_map;
634 int *face_as_quad_map = NULL;
635
636 /* map faces to quads */
637 if (looptri_len != mpoly_len) {
638 /* over alloc, since we dont 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 }
650 num_face_as_quad_map = k;
651 }
652 else {
653 num_face_as_quad_map = (int)looptri_len;
654 }
655 #endif
656
657 /* Calculation */
658 if (looptri_len != 0) {
659 TaskPool *task_pool = BLI_task_pool_create(NULL, TASK_PRIORITY_LOW);
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;
672 mesh2tangent->num_face_as_quad_map = num_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 {
697 int uv_ind = CustomData_get_named_layer_index(
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;
706 BLI_task_pool_push(task_pool, DM_calc_loop_tangents_thread, mesh2tangent, false, NULL);
707 }
708
709 BLI_assert(tangent_mask_curr == tangent_mask);
710 BLI_task_pool_work_and_wait(task_pool);
711 BLI_task_pool_free(task_pool);
712 }
713 else {
714 tangent_mask_curr = tangent_mask;
715 }
716 #ifdef USE_LOOPTRI_DETECT_QUADS
717 if (face_as_quad_map) {
718 MEM_freeN(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
BKE_mesh_calc_loop_tangents(Mesh * me_eval,bool calc_active_tangent,const char (* tangent_names)[MAX_NAME],int tangent_names_len)748 void BKE_mesh_calc_loop_tangents(Mesh *me_eval,
749 bool calc_active_tangent,
750 const char (*tangent_names)[MAX_NAME],
751 int tangent_names_len)
752 {
753 BKE_mesh_runtime_looptri_ensure(me_eval);
754
755 /* TODO(campbell): store in Mesh.runtime to avoid recalculation. */
756 short tangent_mask = 0;
757 BKE_mesh_calc_loop_tangent_ex(me_eval->mvert,
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),
768 CustomData_get_layer(&me_eval->ldata, 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
776 /** \} */
777