Cleanup: style, use braces for blenkernel
[blender.git] / source / blender / blenkernel / intern / editmesh_tangent.c
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
17 /** \file
18  * \ingroup bke
19  */
20
21 #include "BLI_math.h"
22 #include "BLI_task.h"
23
24 #include "DNA_defs.h"
25 #include "DNA_customdata_types.h"
26 #include "DNA_meshdata_types.h"
27
28 #include "BKE_mesh.h"
29 #include "BKE_mesh_tangent.h" /* for utility functions */
30 #include "BKE_editmesh.h"
31 #include "BKE_editmesh_tangent.h"
32
33 #include "MEM_guardedalloc.h"
34
35 /* interface */
36 #include "mikktspace.h"
37
38 /** \name Tangent Space Calculation
39  * \{ */
40
41 /* Necessary complexity to handle looptri's as quads for correct tangents */
42 #define USE_LOOPTRI_DETECT_QUADS
43
44 typedef struct {
45   const float (*precomputedFaceNormals)[3];
46   const float (*precomputedLoopNormals)[3];
47   const BMLoop *(*looptris)[3];
48   int cd_loop_uv_offset; /* texture coordinates */
49   const float (*orco)[3];
50   float (*tangent)[4]; /* destination */
51   int numTessFaces;
52
53 #ifdef USE_LOOPTRI_DETECT_QUADS
54   /* map from 'fake' face index to looptri,
55    * quads will point to the first looptri of the quad */
56   const int *face_as_quad_map;
57   int num_face_as_quad_map;
58 #endif
59
60 } SGLSLEditMeshToTangent;
61
62 #ifdef USE_LOOPTRI_DETECT_QUADS
63 /* seems weak but only used on quads */
64 static const BMLoop *bm_loop_at_face_index(const BMFace *f, int vert_index)
65 {
66   const BMLoop *l = BM_FACE_FIRST_LOOP(f);
67   while (vert_index--) {
68     l = l->next;
69   }
70   return l;
71 }
72 #endif
73
74 static int emdm_ts_GetNumFaces(const SMikkTSpaceContext *pContext)
75 {
76   SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData;
77
78 #ifdef USE_LOOPTRI_DETECT_QUADS
79   return pMesh->num_face_as_quad_map;
80 #else
81   return pMesh->numTessFaces;
82 #endif
83 }
84
85 static int emdm_ts_GetNumVertsOfFace(const SMikkTSpaceContext *pContext, const int face_num)
86 {
87 #ifdef USE_LOOPTRI_DETECT_QUADS
88   SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData;
89   if (pMesh->face_as_quad_map) {
90     const BMLoop **lt = pMesh->looptris[pMesh->face_as_quad_map[face_num]];
91     if (lt[0]->f->len == 4) {
92       return 4;
93     }
94   }
95   return 3;
96 #else
97   UNUSED_VARS(pContext, face_num);
98   return 3;
99 #endif
100 }
101
102 static void emdm_ts_GetPosition(const SMikkTSpaceContext *pContext,
103                                 float r_co[3],
104                                 const int face_num,
105                                 const int vert_index)
106 {
107   //assert(vert_index >= 0 && vert_index < 4);
108   SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData;
109   const BMLoop **lt;
110   const BMLoop *l;
111
112 #ifdef USE_LOOPTRI_DETECT_QUADS
113   if (pMesh->face_as_quad_map) {
114     lt = pMesh->looptris[pMesh->face_as_quad_map[face_num]];
115     if (lt[0]->f->len == 4) {
116       l = bm_loop_at_face_index(lt[0]->f, vert_index);
117       goto finally;
118     }
119     /* fall through to regular triangle */
120   }
121   else {
122     lt = pMesh->looptris[face_num];
123   }
124 #else
125   lt = pMesh->looptris[face_num];
126 #endif
127   l = lt[vert_index];
128
129   const float *co;
130
131 finally:
132   co = l->v->co;
133   copy_v3_v3(r_co, co);
134 }
135
136 static void emdm_ts_GetTextureCoordinate(const SMikkTSpaceContext *pContext,
137                                          float r_uv[2],
138                                          const int face_num,
139                                          const int vert_index)
140 {
141   //assert(vert_index >= 0 && vert_index < 4);
142   SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData;
143   const BMLoop **lt;
144   const BMLoop *l;
145
146 #ifdef USE_LOOPTRI_DETECT_QUADS
147   if (pMesh->face_as_quad_map) {
148     lt = pMesh->looptris[pMesh->face_as_quad_map[face_num]];
149     if (lt[0]->f->len == 4) {
150       l = bm_loop_at_face_index(lt[0]->f, vert_index);
151       goto finally;
152     }
153     /* fall through to regular triangle */
154   }
155   else {
156     lt = pMesh->looptris[face_num];
157   }
158 #else
159   lt = pMesh->looptris[face_num];
160 #endif
161   l = lt[vert_index];
162
163 finally:
164   if (pMesh->cd_loop_uv_offset != -1) {
165     const float *uv = BM_ELEM_CD_GET_VOID_P(l, pMesh->cd_loop_uv_offset);
166     copy_v2_v2(r_uv, uv);
167   }
168   else {
169     const float *orco = pMesh->orco[BM_elem_index_get(l->v)];
170     map_to_sphere(&r_uv[0], &r_uv[1], orco[0], orco[1], orco[2]);
171   }
172 }
173
174 static void emdm_ts_GetNormal(const SMikkTSpaceContext *pContext,
175                               float r_no[3],
176                               const int face_num,
177                               const int vert_index)
178 {
179   //assert(vert_index >= 0 && vert_index < 4);
180   SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData;
181   const BMLoop **lt;
182   const BMLoop *l;
183
184 #ifdef USE_LOOPTRI_DETECT_QUADS
185   if (pMesh->face_as_quad_map) {
186     lt = pMesh->looptris[pMesh->face_as_quad_map[face_num]];
187     if (lt[0]->f->len == 4) {
188       l = bm_loop_at_face_index(lt[0]->f, vert_index);
189       goto finally;
190     }
191     /* fall through to regular triangle */
192   }
193   else {
194     lt = pMesh->looptris[face_num];
195   }
196 #else
197   lt = pMesh->looptris[face_num];
198 #endif
199   l = lt[vert_index];
200
201 finally:
202   if (pMesh->precomputedLoopNormals) {
203     copy_v3_v3(r_no, pMesh->precomputedLoopNormals[BM_elem_index_get(l)]);
204   }
205   else if (BM_elem_flag_test(l->f, BM_ELEM_SMOOTH) == 0) { /* flat */
206     if (pMesh->precomputedFaceNormals) {
207       copy_v3_v3(r_no, pMesh->precomputedFaceNormals[BM_elem_index_get(l->f)]);
208     }
209     else {
210       copy_v3_v3(r_no, l->f->no);
211     }
212   }
213   else {
214     copy_v3_v3(r_no, l->v->no);
215   }
216 }
217
218 static void emdm_ts_SetTSpace(const SMikkTSpaceContext *pContext,
219                               const float fvTangent[3],
220                               const float fSign,
221                               const int face_num,
222                               const int vert_index)
223 {
224   //assert(vert_index >= 0 && vert_index < 4);
225   SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData;
226   const BMLoop **lt;
227   const BMLoop *l;
228
229 #ifdef USE_LOOPTRI_DETECT_QUADS
230   if (pMesh->face_as_quad_map) {
231     lt = pMesh->looptris[pMesh->face_as_quad_map[face_num]];
232     if (lt[0]->f->len == 4) {
233       l = bm_loop_at_face_index(lt[0]->f, vert_index);
234       goto finally;
235     }
236     /* fall through to regular triangle */
237   }
238   else {
239     lt = pMesh->looptris[face_num];
240   }
241 #else
242   lt = pMesh->looptris[face_num];
243 #endif
244   l = lt[vert_index];
245
246   float *pRes;
247
248 finally:
249   pRes = pMesh->tangent[BM_elem_index_get(l)];
250   copy_v3_v3(pRes, fvTangent);
251   pRes[3] = fSign;
252 }
253
254 static void emDM_calc_loop_tangents_thread(TaskPool *__restrict UNUSED(pool),
255                                            void *taskdata,
256                                            int UNUSED(threadid))
257 {
258   struct SGLSLEditMeshToTangent *mesh2tangent = taskdata;
259   /* new computation method */
260   {
261     SMikkTSpaceContext sContext = {NULL};
262     SMikkTSpaceInterface sInterface = {NULL};
263     sContext.m_pUserData = mesh2tangent;
264     sContext.m_pInterface = &sInterface;
265     sInterface.m_getNumFaces = emdm_ts_GetNumFaces;
266     sInterface.m_getNumVerticesOfFace = emdm_ts_GetNumVertsOfFace;
267     sInterface.m_getPosition = emdm_ts_GetPosition;
268     sInterface.m_getTexCoord = emdm_ts_GetTextureCoordinate;
269     sInterface.m_getNormal = emdm_ts_GetNormal;
270     sInterface.m_setTSpaceBasic = emdm_ts_SetTSpace;
271     /* 0 if failed */
272     genTangSpaceDefault(&sContext);
273   }
274 }
275
276 /**
277  * \see #BKE_mesh_calc_loop_tangent, same logic but used arrays instead of #BMesh data.
278  *
279  * \note This function is not so normal, its using `bm->ldata` as input, but output's to `dm->loopData`.
280  * This is done because #CD_TANGENT is cache data used only for drawing.
281  */
282 void BKE_editmesh_loop_tangent_calc(BMEditMesh *em,
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
305   BKE_mesh_calc_loop_tangent_step_0(&bm->ldata,
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]) {
320         BKE_mesh_add_loop_tangent_named_layer_for_uv(
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) {
326       CustomData_add_layer_named(
327           loopdata_out, CD_TANGENT, CD_CALLOC, NULL, (int)loopdata_out_len, "");
328     }
329     if (calc_act && act_uv_name[0]) {
330       BKE_mesh_add_loop_tangent_named_layer_for_uv(
331           &bm->ldata, loopdata_out, (int)loopdata_out_len, act_uv_name);
332     }
333     if (calc_ren && ren_uv_name[0]) {
334       BKE_mesh_add_loop_tangent_named_layer_for_uv(
335           &bm->ldata, loopdata_out, (int)loopdata_out_len, ren_uv_name);
336     }
337     int totface = em->tottri;
338 #ifdef USE_LOOPTRI_DETECT_QUADS
339     int num_face_as_quad_map;
340     int *face_as_quad_map = NULL;
341
342     /* map faces to quads */
343     if (em->tottri != bm->totface) {
344       /* over alloc, since we dont 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       }
356       num_face_as_quad_map = i;
357     }
358     else {
359       num_face_as_quad_map = totface;
360     }
361 #endif
362     /* Calculation */
363     if (em->tottri != 0) {
364       TaskScheduler *scheduler = BLI_task_scheduler_get();
365       TaskPool *task_pool;
366       task_pool = BLI_task_pool_create(scheduler, NULL);
367
368       tangent_mask_curr = 0;
369       /* Calculate tangent layers */
370       SGLSLEditMeshToTangent data_array[MAX_MTFACE];
371       int index = 0;
372       int n = 0;
373       CustomData_update_typemap(loopdata_out);
374       const int tangent_layer_num = CustomData_number_of_layers(loopdata_out, CD_TANGENT);
375       for (n = 0; n < tangent_layer_num; n++) {
376         index = CustomData_get_layer_index_n(loopdata_out, CD_TANGENT, n);
377         BLI_assert(n < MAX_MTFACE);
378         SGLSLEditMeshToTangent *mesh2tangent = &data_array[n];
379         mesh2tangent->numTessFaces = em->tottri;
380 #ifdef USE_LOOPTRI_DETECT_QUADS
381         mesh2tangent->face_as_quad_map = face_as_quad_map;
382         mesh2tangent->num_face_as_quad_map = num_face_as_quad_map;
383 #endif
384         mesh2tangent->precomputedFaceNormals = poly_normals;
385         /* Note, we assume we do have tessellated loop normals at this point (in case it is object-enabled),
386          * have to check this is valid...
387          */
388         mesh2tangent->precomputedLoopNormals = loop_normals;
389         mesh2tangent->cd_loop_uv_offset = CustomData_get_n_offset(&bm->ldata, CD_MLOOPUV, n);
390
391         /* needed for indexing loop-tangents */
392         int htype_index = BM_LOOP;
393         if (mesh2tangent->cd_loop_uv_offset == -1) {
394           mesh2tangent->orco = vert_orco;
395           if (!mesh2tangent->orco) {
396             continue;
397           }
398           /* needed for orco lookups */
399           htype_index |= BM_VERT;
400           tangent_mask_curr |= DM_TANGENT_MASK_ORCO;
401         }
402         else {
403           /* Fill the resulting tangent_mask */
404           int uv_ind = CustomData_get_named_layer_index(
405               &bm->ldata, CD_MLOOPUV, loopdata_out->layers[index].name);
406           int uv_start = CustomData_get_layer_index(&bm->ldata, CD_MLOOPUV);
407           BLI_assert(uv_ind != -1 && uv_start != -1);
408           BLI_assert(uv_ind - uv_start < MAX_MTFACE);
409           tangent_mask_curr |= 1 << (uv_ind - uv_start);
410         }
411         if (mesh2tangent->precomputedFaceNormals) {
412           /* needed for face normal lookups */
413           htype_index |= BM_FACE;
414         }
415         BM_mesh_elem_index_ensure(bm, htype_index);
416
417         mesh2tangent->looptris = (const BMLoop *(*)[3])em->looptris;
418         mesh2tangent->tangent = loopdata_out->layers[index].data;
419
420         BLI_task_pool_push(
421             task_pool, emDM_calc_loop_tangents_thread, mesh2tangent, false, TASK_PRIORITY_LOW);
422       }
423
424       BLI_assert(tangent_mask_curr == tangent_mask);
425       BLI_task_pool_work_and_wait(task_pool);
426       BLI_task_pool_free(task_pool);
427     }
428     else {
429       tangent_mask_curr = tangent_mask;
430     }
431 #ifdef USE_LOOPTRI_DETECT_QUADS
432     if (face_as_quad_map) {
433       MEM_freeN(face_as_quad_map);
434     }
435 #  undef USE_LOOPTRI_DETECT_QUADS
436 #endif
437   }
438
439   *tangent_mask_curr_p = tangent_mask_curr;
440
441   int act_uv_index = CustomData_get_layer_index_n(&bm->ldata, CD_MLOOPUV, act_uv_n);
442   if (act_uv_index >= 0) {
443     int tan_index = CustomData_get_named_layer_index(
444         loopdata_out, CD_TANGENT, bm->ldata.layers[act_uv_index].name);
445     CustomData_set_layer_active_index(loopdata_out, CD_TANGENT, tan_index);
446   } /* else tangent has been built from orco */
447
448   /* Update render layer index */
449   int ren_uv_index = CustomData_get_layer_index_n(&bm->ldata, CD_MLOOPUV, ren_uv_n);
450   if (ren_uv_index >= 0) {
451     int tan_index = CustomData_get_named_layer_index(
452         loopdata_out, CD_TANGENT, bm->ldata.layers[ren_uv_index].name);
453     CustomData_set_layer_render_index(loopdata_out, CD_TANGENT, tan_index);
454   } /* else tangent has been built from orco */
455 }
456
457 /** \} */