doxygen: add newline after \file
[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(
103         const SMikkTSpaceContext *pContext, float r_co[3],
104         const int face_num, const int vert_index)
105 {
106         //assert(vert_index >= 0 && vert_index < 4);
107         SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData;
108         const BMLoop **lt;
109         const BMLoop *l;
110
111 #ifdef USE_LOOPTRI_DETECT_QUADS
112         if (pMesh->face_as_quad_map) {
113                 lt = pMesh->looptris[pMesh->face_as_quad_map[face_num]];
114                 if (lt[0]->f->len == 4) {
115                         l = bm_loop_at_face_index(lt[0]->f, vert_index);
116                         goto finally;
117                 }
118                 /* fall through to regular triangle */
119         }
120         else {
121                 lt = pMesh->looptris[face_num];
122         }
123 #else
124         lt = pMesh->looptris[face_num];
125 #endif
126         l = lt[vert_index];
127
128         const float *co;
129
130 finally:
131         co = l->v->co;
132         copy_v3_v3(r_co, co);
133 }
134
135 static void emdm_ts_GetTextureCoordinate(
136         const SMikkTSpaceContext *pContext, float r_uv[2],
137         const int face_num, const int vert_index)
138 {
139         //assert(vert_index >= 0 && vert_index < 4);
140         SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData;
141         const BMLoop **lt;
142         const BMLoop *l;
143
144 #ifdef USE_LOOPTRI_DETECT_QUADS
145         if (pMesh->face_as_quad_map) {
146                 lt = pMesh->looptris[pMesh->face_as_quad_map[face_num]];
147                 if (lt[0]->f->len == 4) {
148                         l = bm_loop_at_face_index(lt[0]->f, vert_index);
149                         goto finally;
150                 }
151                 /* fall through to regular triangle */
152         }
153         else {
154                 lt = pMesh->looptris[face_num];
155         }
156 #else
157         lt = pMesh->looptris[face_num];
158 #endif
159         l = lt[vert_index];
160
161 finally:
162         if (pMesh->cd_loop_uv_offset != -1) {
163                 const float *uv = BM_ELEM_CD_GET_VOID_P(l, pMesh->cd_loop_uv_offset);
164                 copy_v2_v2(r_uv, uv);
165         }
166         else {
167                 const float *orco = pMesh->orco[BM_elem_index_get(l->v)];
168                 map_to_sphere(&r_uv[0], &r_uv[1], orco[0], orco[1], orco[2]);
169         }
170 }
171
172 static void emdm_ts_GetNormal(
173         const SMikkTSpaceContext *pContext, float r_no[3],
174         const int face_num, const int vert_index)
175 {
176         //assert(vert_index >= 0 && vert_index < 4);
177         SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData;
178         const BMLoop **lt;
179         const BMLoop *l;
180
181 #ifdef USE_LOOPTRI_DETECT_QUADS
182         if (pMesh->face_as_quad_map) {
183                 lt = pMesh->looptris[pMesh->face_as_quad_map[face_num]];
184                 if (lt[0]->f->len == 4) {
185                         l = bm_loop_at_face_index(lt[0]->f, vert_index);
186                         goto finally;
187                 }
188                 /* fall through to regular triangle */
189         }
190         else {
191                 lt = pMesh->looptris[face_num];
192         }
193 #else
194         lt = pMesh->looptris[face_num];
195 #endif
196         l = lt[vert_index];
197
198 finally:
199         if (pMesh->precomputedLoopNormals) {
200                 copy_v3_v3(r_no, pMesh->precomputedLoopNormals[BM_elem_index_get(l)]);
201         }
202         else if (BM_elem_flag_test(l->f, BM_ELEM_SMOOTH) == 0) {  /* flat */
203                 if (pMesh->precomputedFaceNormals) {
204                         copy_v3_v3(r_no, pMesh->precomputedFaceNormals[BM_elem_index_get(l->f)]);
205                 }
206                 else {
207                         copy_v3_v3(r_no, l->f->no);
208                 }
209         }
210         else {
211                 copy_v3_v3(r_no, l->v->no);
212         }
213 }
214
215 static void emdm_ts_SetTSpace(
216         const SMikkTSpaceContext *pContext, const float fvTangent[3], const float fSign,
217         const int face_num, const int vert_index)
218 {
219         //assert(vert_index >= 0 && vert_index < 4);
220         SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData;
221         const BMLoop **lt;
222         const BMLoop *l;
223
224 #ifdef USE_LOOPTRI_DETECT_QUADS
225         if (pMesh->face_as_quad_map) {
226                 lt = pMesh->looptris[pMesh->face_as_quad_map[face_num]];
227                 if (lt[0]->f->len == 4) {
228                         l = bm_loop_at_face_index(lt[0]->f, vert_index);
229                         goto finally;
230                 }
231                 /* fall through to regular triangle */
232         }
233         else {
234                 lt = pMesh->looptris[face_num];
235         }
236 #else
237         lt = pMesh->looptris[face_num];
238 #endif
239         l = lt[vert_index];
240
241         float *pRes;
242
243 finally:
244         pRes = pMesh->tangent[BM_elem_index_get(l)];
245         copy_v3_v3(pRes, fvTangent);
246         pRes[3] = fSign;
247 }
248
249 static void emDM_calc_loop_tangents_thread(TaskPool * __restrict UNUSED(pool), void *taskdata, int UNUSED(threadid))
250 {
251         struct SGLSLEditMeshToTangent *mesh2tangent = taskdata;
252         /* new computation method */
253         {
254                 SMikkTSpaceContext sContext = {NULL};
255                 SMikkTSpaceInterface sInterface = {NULL};
256                 sContext.m_pUserData = mesh2tangent;
257                 sContext.m_pInterface = &sInterface;
258                 sInterface.m_getNumFaces = emdm_ts_GetNumFaces;
259                 sInterface.m_getNumVerticesOfFace = emdm_ts_GetNumVertsOfFace;
260                 sInterface.m_getPosition = emdm_ts_GetPosition;
261                 sInterface.m_getTexCoord = emdm_ts_GetTextureCoordinate;
262                 sInterface.m_getNormal = emdm_ts_GetNormal;
263                 sInterface.m_setTSpaceBasic = emdm_ts_SetTSpace;
264                 /* 0 if failed */
265                 genTangSpaceDefault(&sContext);
266         }
267 }
268
269 /**
270  * \see #BKE_mesh_calc_loop_tangent, same logic but used arrays instead of #BMesh data.
271  *
272  * \note This function is not so normal, its using `bm->ldata` as input, but output's to `dm->loopData`.
273  * This is done because #CD_TANGENT is cache data used only for drawing.
274  */
275 void BKE_editmesh_loop_tangent_calc(
276         BMEditMesh *em, bool calc_active_tangent,
277         const char (*tangent_names)[MAX_NAME], int tangent_names_len,
278         const float (*poly_normals)[3],
279         const float (*loop_normals)[3],
280         const float (*vert_orco)[3],
281         /* result */
282         CustomData *loopdata_out,
283         const uint  loopdata_out_len,
284         short *tangent_mask_curr_p)
285 {
286         BMesh *bm = em->bm;
287
288         int act_uv_n = -1;
289         int ren_uv_n = -1;
290         bool calc_act = false;
291         bool calc_ren = false;
292         char act_uv_name[MAX_NAME];
293         char ren_uv_name[MAX_NAME];
294         short tangent_mask = 0;
295         short tangent_mask_curr = *tangent_mask_curr_p;
296
297         BKE_mesh_calc_loop_tangent_step_0(
298                 &bm->ldata, calc_active_tangent, tangent_names, tangent_names_len,
299                 &calc_act, &calc_ren, &act_uv_n, &ren_uv_n, act_uv_name, ren_uv_name, &tangent_mask);
300
301         if ((tangent_mask_curr | tangent_mask) != tangent_mask_curr) {
302                 for (int i = 0; i < tangent_names_len; i++) {
303                         if (tangent_names[i][0]) {
304                                 BKE_mesh_add_loop_tangent_named_layer_for_uv(
305                                         &bm->ldata, loopdata_out, (int)loopdata_out_len, tangent_names[i]);
306                         }
307                 }
308                 if ((tangent_mask & DM_TANGENT_MASK_ORCO) && CustomData_get_named_layer_index(loopdata_out, CD_TANGENT, "") == -1)
309                         CustomData_add_layer_named(loopdata_out, CD_TANGENT, CD_CALLOC, NULL, (int)loopdata_out_len, "");
310                 if (calc_act && act_uv_name[0])
311                         BKE_mesh_add_loop_tangent_named_layer_for_uv(&bm->ldata, loopdata_out, (int)loopdata_out_len, act_uv_name);
312                 if (calc_ren && ren_uv_name[0])
313                         BKE_mesh_add_loop_tangent_named_layer_for_uv(&bm->ldata, loopdata_out, (int)loopdata_out_len, ren_uv_name);
314                 int totface = em->tottri;
315 #ifdef USE_LOOPTRI_DETECT_QUADS
316                 int num_face_as_quad_map;
317                 int *face_as_quad_map = NULL;
318
319                 /* map faces to quads */
320                 if (em->tottri != bm->totface) {
321                         /* over alloc, since we dont know how many ngon or quads we have */
322
323                         /* map fake face index to looptri */
324                         face_as_quad_map = MEM_mallocN(sizeof(int) * totface, __func__);
325                         int i, j;
326                         for (i = 0, j = 0; j < totface; i++, j++) {
327                                 face_as_quad_map[i] = j;
328                                 /* step over all quads */
329                                 if (em->looptris[j][0]->f->len == 4) {
330                                         j++;  /* skips the nest looptri */
331                                 }
332                         }
333                         num_face_as_quad_map = i;
334                 }
335                 else {
336                         num_face_as_quad_map = totface;
337                 }
338 #endif
339                 /* Calculation */
340                 if (em->tottri != 0) {
341                         TaskScheduler *scheduler = BLI_task_scheduler_get();
342                         TaskPool *task_pool;
343                         task_pool = BLI_task_pool_create(scheduler, NULL);
344
345                         tangent_mask_curr = 0;
346                         /* Calculate tangent layers */
347                         SGLSLEditMeshToTangent data_array[MAX_MTFACE];
348                         int index = 0;
349                         int n = 0;
350                         CustomData_update_typemap(loopdata_out);
351                         const int tangent_layer_num = CustomData_number_of_layers(loopdata_out, CD_TANGENT);
352                         for (n = 0; n < tangent_layer_num; n++) {
353                                 index = CustomData_get_layer_index_n(loopdata_out, CD_TANGENT, n);
354                                 BLI_assert(n < MAX_MTFACE);
355                                 SGLSLEditMeshToTangent *mesh2tangent = &data_array[n];
356                                 mesh2tangent->numTessFaces = em->tottri;
357 #ifdef USE_LOOPTRI_DETECT_QUADS
358                                 mesh2tangent->face_as_quad_map = face_as_quad_map;
359                                 mesh2tangent->num_face_as_quad_map = num_face_as_quad_map;
360 #endif
361                                 mesh2tangent->precomputedFaceNormals = poly_normals;
362                                 /* Note, we assume we do have tessellated loop normals at this point (in case it is object-enabled),
363                                  * have to check this is valid...
364                                  */
365                                 mesh2tangent->precomputedLoopNormals = loop_normals;
366                                 mesh2tangent->cd_loop_uv_offset = CustomData_get_n_offset(&bm->ldata, CD_MLOOPUV, n);
367
368                                 /* needed for indexing loop-tangents */
369                                 int htype_index = BM_LOOP;
370                                 if (mesh2tangent->cd_loop_uv_offset == -1) {
371                                         mesh2tangent->orco = vert_orco;
372                                         if (!mesh2tangent->orco)
373                                                 continue;
374                                         /* needed for orco lookups */
375                                         htype_index |= BM_VERT;
376                                         tangent_mask_curr |= DM_TANGENT_MASK_ORCO;
377                                 }
378                                 else {
379                                         /* Fill the resulting tangent_mask */
380                                         int uv_ind = CustomData_get_named_layer_index(&bm->ldata, CD_MLOOPUV, loopdata_out->layers[index].name);
381                                         int uv_start = CustomData_get_layer_index(&bm->ldata, CD_MLOOPUV);
382                                         BLI_assert(uv_ind != -1 && uv_start != -1);
383                                         BLI_assert(uv_ind - uv_start < MAX_MTFACE);
384                                         tangent_mask_curr |= 1 << (uv_ind - uv_start);
385                                 }
386                                 if (mesh2tangent->precomputedFaceNormals) {
387                                         /* needed for face normal lookups */
388                                         htype_index |= BM_FACE;
389                                 }
390                                 BM_mesh_elem_index_ensure(bm, htype_index);
391
392                                 mesh2tangent->looptris = (const BMLoop *(*)[3])em->looptris;
393                                 mesh2tangent->tangent = loopdata_out->layers[index].data;
394
395                                 BLI_task_pool_push(task_pool, emDM_calc_loop_tangents_thread, mesh2tangent, false, TASK_PRIORITY_LOW);
396                         }
397
398                         BLI_assert(tangent_mask_curr == tangent_mask);
399                         BLI_task_pool_work_and_wait(task_pool);
400                         BLI_task_pool_free(task_pool);
401                 }
402                 else {
403                         tangent_mask_curr = tangent_mask;
404                 }
405 #ifdef USE_LOOPTRI_DETECT_QUADS
406                 if (face_as_quad_map) {
407                         MEM_freeN(face_as_quad_map);
408                 }
409 #undef USE_LOOPTRI_DETECT_QUADS
410 #endif
411         }
412
413         *tangent_mask_curr_p = tangent_mask_curr;
414
415         int act_uv_index = CustomData_get_layer_index_n(&bm->ldata, CD_MLOOPUV, act_uv_n);
416         if (act_uv_index >= 0) {
417                 int tan_index = CustomData_get_named_layer_index(loopdata_out, CD_TANGENT, bm->ldata.layers[act_uv_index].name);
418                 CustomData_set_layer_active_index(loopdata_out, CD_TANGENT, tan_index);
419         } /* else tangent has been built from orco */
420
421         /* Update render layer index */
422         int ren_uv_index = CustomData_get_layer_index_n(&bm->ldata, CD_MLOOPUV, ren_uv_n);
423         if (ren_uv_index >= 0) {
424                 int tan_index = CustomData_get_named_layer_index(loopdata_out, CD_TANGENT, bm->ldata.layers[ren_uv_index].name);
425                 CustomData_set_layer_render_index(loopdata_out, CD_TANGENT, tan_index);
426         } /* else tangent has been built from orco */
427 }
428
429 /** \} */