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