Merge branch 'master' into blender2.8
[blender.git] / source / blender / blenkernel / intern / editmesh_tangent.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * ***** END GPL LICENSE BLOCK *****
19  */
20
21 /** \file blender/blenkernel/intern/editmesh_tangent.c
22  *  \ingroup bke
23  */
24
25 #include "BLI_math.h"
26 #include "BLI_task.h"
27
28 #include "DNA_defs.h"
29 #include "DNA_customdata_types.h"
30 #include "DNA_meshdata_types.h"
31
32 #include "BKE_mesh.h"
33 #include "BKE_mesh_tangent.h"  /* for utility functions */
34 #include "BKE_editmesh.h"
35 #include "BKE_editmesh_tangent.h"
36
37 #include "MEM_guardedalloc.h"
38
39 /* interface */
40 #include "mikktspace.h"
41
42 /** \name Tangent Space Calculation
43  * \{ */
44
45 /* Necessary complexity to handle looptri's as quads for correct tangents */
46 #define USE_LOOPTRI_DETECT_QUADS
47
48 typedef struct {
49         const float (*precomputedFaceNormals)[3];
50         const float (*precomputedLoopNormals)[3];
51         const BMLoop *(*looptris)[3];
52         int cd_loop_uv_offset;   /* texture coordinates */
53         const float (*orco)[3];
54         float (*tangent)[4];    /* destination */
55         int numTessFaces;
56
57 #ifdef USE_LOOPTRI_DETECT_QUADS
58         /* map from 'fake' face index to looptri,
59          * quads will point to the first looptri of the quad */
60         const int    *face_as_quad_map;
61         int       num_face_as_quad_map;
62 #endif
63
64 } SGLSLEditMeshToTangent;
65
66 #ifdef USE_LOOPTRI_DETECT_QUADS
67 /* seems weak but only used on quads */
68 static const BMLoop *bm_loop_at_face_index(const BMFace *f, int vert_index)
69 {
70         const BMLoop *l = BM_FACE_FIRST_LOOP(f);
71         while (vert_index--) {
72                 l = l->next;
73         }
74         return l;
75 }
76 #endif
77
78 static int emdm_ts_GetNumFaces(const SMikkTSpaceContext *pContext)
79 {
80         SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData;
81
82 #ifdef USE_LOOPTRI_DETECT_QUADS
83         return pMesh->num_face_as_quad_map;
84 #else
85         return pMesh->numTessFaces;
86 #endif
87 }
88
89 static int emdm_ts_GetNumVertsOfFace(const SMikkTSpaceContext *pContext, const int face_num)
90 {
91 #ifdef USE_LOOPTRI_DETECT_QUADS
92         SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData;
93         if (pMesh->face_as_quad_map) {
94                 const BMLoop **lt = pMesh->looptris[pMesh->face_as_quad_map[face_num]];
95                 if (lt[0]->f->len == 4) {
96                         return 4;
97                 }
98         }
99         return 3;
100 #else
101         UNUSED_VARS(pContext, face_num);
102         return 3;
103 #endif
104 }
105
106 static void emdm_ts_GetPosition(
107         const SMikkTSpaceContext *pContext, float r_co[3],
108         const int face_num, const int vert_index)
109 {
110         //assert(vert_index >= 0 && vert_index < 4);
111         SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData;
112         const BMLoop **lt;
113         const BMLoop *l;
114
115 #ifdef USE_LOOPTRI_DETECT_QUADS
116         if (pMesh->face_as_quad_map) {
117                 lt = pMesh->looptris[pMesh->face_as_quad_map[face_num]];
118                 if (lt[0]->f->len == 4) {
119                         l = bm_loop_at_face_index(lt[0]->f, vert_index);
120                         goto finally;
121                 }
122                 /* fall through to regular triangle */
123         }
124         else {
125                 lt = pMesh->looptris[face_num];
126         }
127 #else
128         lt = pMesh->looptris[face_num];
129 #endif
130         l = lt[vert_index];
131
132         const float *co;
133
134 finally:
135         co = l->v->co;
136         copy_v3_v3(r_co, co);
137 }
138
139 static void emdm_ts_GetTextureCoordinate(
140         const SMikkTSpaceContext *pContext, float r_uv[2],
141         const int face_num, const int vert_index)
142 {
143         //assert(vert_index >= 0 && vert_index < 4);
144         SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData;
145         const BMLoop **lt;
146         const BMLoop *l;
147
148 #ifdef USE_LOOPTRI_DETECT_QUADS
149         if (pMesh->face_as_quad_map) {
150                 lt = pMesh->looptris[pMesh->face_as_quad_map[face_num]];
151                 if (lt[0]->f->len == 4) {
152                         l = bm_loop_at_face_index(lt[0]->f, vert_index);
153                         goto finally;
154                 }
155                 /* fall through to regular triangle */
156         }
157         else {
158                 lt = pMesh->looptris[face_num];
159         }
160 #else
161         lt = pMesh->looptris[face_num];
162 #endif
163         l = lt[vert_index];
164
165 finally:
166         if (pMesh->cd_loop_uv_offset != -1) {
167                 const float *uv = BM_ELEM_CD_GET_VOID_P(l, pMesh->cd_loop_uv_offset);
168                 copy_v2_v2(r_uv, uv);
169         }
170         else {
171                 const float *orco = pMesh->orco[BM_elem_index_get(l->v)];
172                 map_to_sphere(&r_uv[0], &r_uv[1], orco[0], orco[1], orco[2]);
173         }
174 }
175
176 static void emdm_ts_GetNormal(
177         const SMikkTSpaceContext *pContext, float r_no[3],
178         const int face_num, const int vert_index)
179 {
180         //assert(vert_index >= 0 && vert_index < 4);
181         SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData;
182         const BMLoop **lt;
183         const BMLoop *l;
184
185 #ifdef USE_LOOPTRI_DETECT_QUADS
186         if (pMesh->face_as_quad_map) {
187                 lt = pMesh->looptris[pMesh->face_as_quad_map[face_num]];
188                 if (lt[0]->f->len == 4) {
189                         l = bm_loop_at_face_index(lt[0]->f, vert_index);
190                         goto finally;
191                 }
192                 /* fall through to regular triangle */
193         }
194         else {
195                 lt = pMesh->looptris[face_num];
196         }
197 #else
198         lt = pMesh->looptris[face_num];
199 #endif
200         l = lt[vert_index];
201
202 finally:
203         if (pMesh->precomputedLoopNormals) {
204                 copy_v3_v3(r_no, pMesh->precomputedLoopNormals[BM_elem_index_get(l)]);
205         }
206         else if (BM_elem_flag_test(l->f, BM_ELEM_SMOOTH) == 0) {  /* flat */
207                 if (pMesh->precomputedFaceNormals) {
208                         copy_v3_v3(r_no, pMesh->precomputedFaceNormals[BM_elem_index_get(l->f)]);
209                 }
210                 else {
211                         copy_v3_v3(r_no, l->f->no);
212                 }
213         }
214         else {
215                 copy_v3_v3(r_no, l->v->no);
216         }
217 }
218
219 static void emdm_ts_SetTSpace(
220         const SMikkTSpaceContext *pContext, const float fvTangent[3], const float fSign,
221         const int face_num, const int vert_index)
222 {
223         //assert(vert_index >= 0 && vert_index < 4);
224         SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData;
225         const BMLoop **lt;
226         const BMLoop *l;
227
228 #ifdef USE_LOOPTRI_DETECT_QUADS
229         if (pMesh->face_as_quad_map) {
230                 lt = pMesh->looptris[pMesh->face_as_quad_map[face_num]];
231                 if (lt[0]->f->len == 4) {
232                         l = bm_loop_at_face_index(lt[0]->f, vert_index);
233                         goto finally;
234                 }
235                 /* fall through to regular triangle */
236         }
237         else {
238                 lt = pMesh->looptris[face_num];
239         }
240 #else
241         lt = pMesh->looptris[face_num];
242 #endif
243         l = lt[vert_index];
244
245         float *pRes;
246
247 finally:
248         pRes = pMesh->tangent[BM_elem_index_get(l)];
249         copy_v3_v3(pRes, fvTangent);
250         pRes[3] = fSign;
251 }
252
253 static void emDM_calc_loop_tangents_thread(TaskPool * __restrict UNUSED(pool), void *taskdata, int UNUSED(threadid))
254 {
255         struct SGLSLEditMeshToTangent *mesh2tangent = taskdata;
256         /* new computation method */
257         {
258                 SMikkTSpaceContext sContext = {NULL};
259                 SMikkTSpaceInterface sInterface = {NULL};
260                 sContext.m_pUserData = mesh2tangent;
261                 sContext.m_pInterface = &sInterface;
262                 sInterface.m_getNumFaces = emdm_ts_GetNumFaces;
263                 sInterface.m_getNumVerticesOfFace = emdm_ts_GetNumVertsOfFace;
264                 sInterface.m_getPosition = emdm_ts_GetPosition;
265                 sInterface.m_getTexCoord = emdm_ts_GetTextureCoordinate;
266                 sInterface.m_getNormal = emdm_ts_GetNormal;
267                 sInterface.m_setTSpaceBasic = emdm_ts_SetTSpace;
268                 /* 0 if failed */
269                 genTangSpaceDefault(&sContext);
270         }
271 }
272
273 /**
274  * \see #BKE_mesh_calc_loop_tangent, same logic but used arrays instead of #BMesh data.
275  *
276  * \note This function is not so normal, its using `bm->ldata` as input, but output's to `dm->loopData`.
277  * This is done because #CD_TANGENT is cache data used only for drawing.
278  */
279 void BKE_editmesh_loop_tangent_calc(
280         BMEditMesh *em, bool calc_active_tangent,
281         const char (*tangent_names)[MAX_NAME], int tangent_names_len,
282         const float (*poly_normals)[3],
283         const float (*loop_normals)[3],
284         const float (*vert_orco)[3],
285         /* result */
286         CustomData *loopdata_out,
287         const uint  loopdata_out_len,
288         short *tangent_mask_curr_p)
289 {
290         BMesh *bm = em->bm;
291
292         int act_uv_n = -1;
293         int ren_uv_n = -1;
294         bool calc_act = false;
295         bool calc_ren = false;
296         char act_uv_name[MAX_NAME];
297         char ren_uv_name[MAX_NAME];
298         short tangent_mask = 0;
299         short tangent_mask_curr = *tangent_mask_curr_p;
300
301         BKE_mesh_calc_loop_tangent_step_0(
302                 &bm->ldata, calc_active_tangent, tangent_names, tangent_names_len,
303                 &calc_act, &calc_ren, &act_uv_n, &ren_uv_n, act_uv_name, ren_uv_name, &tangent_mask);
304
305         if ((tangent_mask_curr | tangent_mask) != tangent_mask_curr) {
306                 for (int i = 0; i < tangent_names_len; i++) {
307                         if (tangent_names[i][0]) {
308                                 BKE_mesh_add_loop_tangent_named_layer_for_uv(
309                                         &bm->ldata, loopdata_out, (int)loopdata_out_len, tangent_names[i]);
310                         }
311                 }
312                 if ((tangent_mask & DM_TANGENT_MASK_ORCO) && CustomData_get_named_layer_index(loopdata_out, CD_TANGENT, "") == -1)
313                         CustomData_add_layer_named(loopdata_out, CD_TANGENT, CD_CALLOC, NULL, (int)loopdata_out_len, "");
314                 if (calc_act && act_uv_name[0])
315                         BKE_mesh_add_loop_tangent_named_layer_for_uv(&bm->ldata, loopdata_out, (int)loopdata_out_len, act_uv_name);
316                 if (calc_ren && ren_uv_name[0])
317                         BKE_mesh_add_loop_tangent_named_layer_for_uv(&bm->ldata, loopdata_out, (int)loopdata_out_len, ren_uv_name);
318                 int totface = em->tottri;
319 #ifdef USE_LOOPTRI_DETECT_QUADS
320                 int num_face_as_quad_map;
321                 int *face_as_quad_map = NULL;
322
323                 /* map faces to quads */
324                 if (em->tottri != bm->totface) {
325                         /* over alloc, since we dont know how many ngon or quads we have */
326
327                         /* map fake face index to looptri */
328                         face_as_quad_map = MEM_mallocN(sizeof(int) * totface, __func__);
329                         int i, j;
330                         for (i = 0, j = 0; j < totface; i++, j++) {
331                                 face_as_quad_map[i] = j;
332                                 /* step over all quads */
333                                 if (em->looptris[j][0]->f->len == 4) {
334                                         j++;  /* skips the nest looptri */
335                                 }
336                         }
337                         num_face_as_quad_map = i;
338                 }
339                 else {
340                         num_face_as_quad_map = totface;
341                 }
342 #endif
343                 /* Calculation */
344                 if (em->tottri != 0) {
345                         TaskScheduler *scheduler = BLI_task_scheduler_get();
346                         TaskPool *task_pool;
347                         task_pool = BLI_task_pool_create(scheduler, NULL);
348
349                         tangent_mask_curr = 0;
350                         /* Calculate tangent layers */
351                         SGLSLEditMeshToTangent data_array[MAX_MTFACE];
352                         int index = 0;
353                         int n = 0;
354                         CustomData_update_typemap(loopdata_out);
355                         const int tangent_layer_num = CustomData_number_of_layers(loopdata_out, CD_TANGENT);
356                         for (n = 0; n < tangent_layer_num; n++) {
357                                 index = CustomData_get_layer_index_n(loopdata_out, CD_TANGENT, n);
358                                 BLI_assert(n < MAX_MTFACE);
359                                 SGLSLEditMeshToTangent *mesh2tangent = &data_array[n];
360                                 mesh2tangent->numTessFaces = em->tottri;
361 #ifdef USE_LOOPTRI_DETECT_QUADS
362                                 mesh2tangent->face_as_quad_map = face_as_quad_map;
363                                 mesh2tangent->num_face_as_quad_map = num_face_as_quad_map;
364 #endif
365                                 mesh2tangent->precomputedFaceNormals = poly_normals;
366                                 /* Note, we assume we do have tessellated loop normals at this point (in case it is object-enabled),
367                                  * have to check this is valid...
368                                  */
369                                 mesh2tangent->precomputedLoopNormals = loop_normals;
370                                 mesh2tangent->cd_loop_uv_offset = CustomData_get_n_offset(&bm->ldata, CD_MLOOPUV, n);
371
372                                 /* needed for indexing loop-tangents */
373                                 int htype_index = BM_LOOP;
374                                 if (mesh2tangent->cd_loop_uv_offset == -1) {
375                                         mesh2tangent->orco = vert_orco;
376                                         if (!mesh2tangent->orco)
377                                                 continue;
378                                         /* needed for orco lookups */
379                                         htype_index |= BM_VERT;
380                                         tangent_mask_curr |= DM_TANGENT_MASK_ORCO;
381                                 }
382                                 else {
383                                         /* Fill the resulting tangent_mask */
384                                         int uv_ind = CustomData_get_named_layer_index(&bm->ldata, CD_MLOOPUV, loopdata_out->layers[index].name);
385                                         int uv_start = CustomData_get_layer_index(&bm->ldata, CD_MLOOPUV);
386                                         BLI_assert(uv_ind != -1 && uv_start != -1);
387                                         BLI_assert(uv_ind - uv_start < MAX_MTFACE);
388                                         tangent_mask_curr |= 1 << (uv_ind - uv_start);
389                                 }
390                                 if (mesh2tangent->precomputedFaceNormals) {
391                                         /* needed for face normal lookups */
392                                         htype_index |= BM_FACE;
393                                 }
394                                 BM_mesh_elem_index_ensure(bm, htype_index);
395
396                                 mesh2tangent->looptris = (const BMLoop *(*)[3])em->looptris;
397                                 mesh2tangent->tangent = loopdata_out->layers[index].data;
398
399                                 BLI_task_pool_push(task_pool, emDM_calc_loop_tangents_thread, mesh2tangent, false, TASK_PRIORITY_LOW);
400                         }
401
402                         BLI_assert(tangent_mask_curr == tangent_mask);
403                         BLI_task_pool_work_and_wait(task_pool);
404                         BLI_task_pool_free(task_pool);
405                 }
406                 else {
407                         tangent_mask_curr = tangent_mask;
408                 }
409 #ifdef USE_LOOPTRI_DETECT_QUADS
410                 if (face_as_quad_map) {
411                         MEM_freeN(face_as_quad_map);
412                 }
413 #undef USE_LOOPTRI_DETECT_QUADS
414 #endif
415         }
416
417         *tangent_mask_curr_p = tangent_mask_curr;
418
419         int act_uv_index = CustomData_get_layer_index_n(&bm->ldata, CD_MLOOPUV, act_uv_n);
420         if (act_uv_index >= 0) {
421                 int tan_index = CustomData_get_named_layer_index(loopdata_out, CD_TANGENT, bm->ldata.layers[act_uv_index].name);
422                 CustomData_set_layer_active_index(loopdata_out, CD_TANGENT, tan_index);
423         } /* else tangent has been built from orco */
424
425         /* Update render layer index */
426         int ren_uv_index = CustomData_get_layer_index_n(&bm->ldata, CD_MLOOPUV, ren_uv_n);
427         if (ren_uv_index >= 0) {
428                 int tan_index = CustomData_get_named_layer_index(loopdata_out, CD_TANGENT, bm->ldata.layers[ren_uv_index].name);
429                 CustomData_set_layer_render_index(loopdata_out, CD_TANGENT, tan_index);
430         } /* else tangent has been built from orco */
431 }
432
433 /** \} */