ClangFormat: apply to source, most of intern
[blender.git] / source / blender / blenkernel / intern / subdiv_displacement_multires.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  * The Original Code is Copyright (C) 2018 by Blender Foundation.
17  * All rights reserved.
18  */
19
20 /** \file
21  * \ingroup bke
22  */
23
24 #include "BKE_subdiv.h"
25
26 #include "DNA_mesh_types.h"
27 #include "DNA_meshdata_types.h"
28 #include "DNA_modifier_types.h"
29 #include "DNA_object_types.h"
30
31 #include "BLI_utildefines.h"
32 #include "BLI_math_vector.h"
33
34 #include "BKE_customdata.h"
35 #include "BKE_multires.h"
36 #include "BKE_subdiv_eval.h"
37
38 #include "MEM_guardedalloc.h"
39
40 typedef struct PolyCornerIndex {
41   int poly_index;
42   int corner;
43 } PolyCornerIndex;
44
45 typedef struct MultiresDisplacementData {
46   Subdiv *subdiv;
47   int grid_size;
48   /* Mesh is used to read external displacement. */
49   Mesh *mesh;
50   const MPoly *mpoly;
51   const MDisps *mdisps;
52   /* Indexed by ptex face index, contains polygon/corner which corresponds
53    * to it.
54    *
55    * NOTE: For quad polygon this is an index of first corner only, since
56    * there we only have one ptex. */
57   PolyCornerIndex *ptex_poly_corner;
58   /* Indexed by coarse face index, returns first ptex face index corresponding
59    * to that coarse face. */
60   int *face_ptex_offset;
61   /* Sanity check, is used in debug builds.
62    * Controls that initialize() was called prior to eval_displacement(). */
63   bool is_initialized;
64 } MultiresDisplacementData;
65
66 /* Denotes which grid to use to average value of the displacement read from the
67  * grid which corresponds to the ptex face. */
68 typedef enum eAverageWith {
69   AVERAGE_WITH_NONE,
70   AVERAGE_WITH_ALL,
71   AVERAGE_WITH_PREV,
72   AVERAGE_WITH_NEXT,
73 } eAverageWith;
74
75 static int displacement_get_grid_and_coord(SubdivDisplacement *displacement,
76                                            const int ptex_face_index,
77                                            const float u,
78                                            const float v,
79                                            const MDisps **r_displacement_grid,
80                                            float *grid_u,
81                                            float *grid_v)
82 {
83   MultiresDisplacementData *data = displacement->user_data;
84   const PolyCornerIndex *poly_corner = &data->ptex_poly_corner[ptex_face_index];
85   const MPoly *poly = &data->mpoly[poly_corner->poly_index];
86   const int start_grid_index = poly->loopstart + poly_corner->corner;
87   int corner = 0;
88   if (poly->totloop == 4) {
89     float corner_u, corner_v;
90     corner = BKE_subdiv_rotate_quad_to_corner(u, v, &corner_u, &corner_v);
91     *r_displacement_grid = &data->mdisps[start_grid_index + corner];
92     BKE_subdiv_ptex_face_uv_to_grid_uv(corner_u, corner_v, grid_u, grid_v);
93   }
94   else {
95     *r_displacement_grid = &data->mdisps[start_grid_index];
96     BKE_subdiv_ptex_face_uv_to_grid_uv(u, v, grid_u, grid_v);
97   }
98   return corner;
99 }
100
101 static const MDisps *displacement_get_other_grid(SubdivDisplacement *displacement,
102                                                  const int ptex_face_index,
103                                                  const int corner,
104                                                  const int corner_delta)
105 {
106   MultiresDisplacementData *data = displacement->user_data;
107   const PolyCornerIndex *poly_corner = &data->ptex_poly_corner[ptex_face_index];
108   const MPoly *poly = &data->mpoly[poly_corner->poly_index];
109   const int effective_corner = (poly->totloop == 4) ? corner : poly_corner->corner;
110   const int next_corner = (effective_corner + corner_delta + poly->totloop) % poly->totloop;
111   return &data->mdisps[poly->loopstart + next_corner];
112 }
113
114 BLI_INLINE eAverageWith read_displacement_grid(const MDisps *displacement_grid,
115                                                const int grid_size,
116                                                const float grid_u,
117                                                const float grid_v,
118                                                float r_tangent_D[3])
119 {
120   if (displacement_grid->disps == NULL) {
121     zero_v3(r_tangent_D);
122     return AVERAGE_WITH_NONE;
123   }
124   const int x = (grid_u * (grid_size - 1) + 0.5f);
125   const int y = (grid_v * (grid_size - 1) + 0.5f);
126   copy_v3_v3(r_tangent_D, displacement_grid->disps[y * grid_size + x]);
127   if (x == 0 && y == 0) {
128     return AVERAGE_WITH_ALL;
129   }
130   else if (x == 0) {
131     return AVERAGE_WITH_PREV;
132   }
133   else if (y == 0) {
134     return AVERAGE_WITH_NEXT;
135   }
136   return AVERAGE_WITH_NONE;
137 }
138
139 static void average_convert_grid_coord_to_ptex(const MPoly *poly,
140                                                const int corner,
141                                                const float grid_u,
142                                                const float grid_v,
143                                                float *r_ptex_face_u,
144                                                float *r_ptex_face_v)
145 {
146   if (poly->totloop == 4) {
147     BKE_subdiv_rotate_grid_to_quad(corner, grid_u, grid_v, r_ptex_face_u, r_ptex_face_v);
148   }
149   else {
150     BKE_subdiv_grid_uv_to_ptex_face_uv(grid_u, grid_v, r_ptex_face_u, r_ptex_face_v);
151   }
152 }
153
154 static void average_construct_tangent_matrix(Subdiv *subdiv,
155                                              const MPoly *poly,
156                                              const int ptex_face_index,
157                                              const int corner,
158                                              const float u,
159                                              const float v,
160                                              float r_tangent_matrix[3][3])
161 {
162   const bool is_quad = (poly->totloop == 4);
163   const int quad_corner = is_quad ? corner : 0;
164   float dummy_P[3], dPdu[3], dPdv[3];
165   BKE_subdiv_eval_limit_point_and_derivatives(subdiv, ptex_face_index, u, v, dummy_P, dPdu, dPdv);
166   BKE_multires_construct_tangent_matrix(r_tangent_matrix, dPdu, dPdv, quad_corner);
167 }
168
169 static void average_read_displacement_tangent(MultiresDisplacementData *data,
170                                               const MDisps *other_displacement_grid,
171                                               const float grid_u,
172                                               const float grid_v,
173                                               float r_tangent_D[3])
174 {
175   read_displacement_grid(other_displacement_grid, data->grid_size, grid_u, grid_v, r_tangent_D);
176 }
177
178 static void average_read_displacement_object(MultiresDisplacementData *data,
179                                              const MDisps *displacement_grid,
180                                              const float grid_u,
181                                              const float grid_v,
182                                              const int ptex_face_index,
183                                              const int corner_index,
184                                              float r_D[3])
185 {
186   const PolyCornerIndex *poly_corner = &data->ptex_poly_corner[ptex_face_index];
187   const MPoly *poly = &data->mpoly[poly_corner->poly_index];
188   /* Get (u, v) coordinate within the other ptex face which corresponds to
189    * the grid coordinates. */
190   float u, v;
191   average_convert_grid_coord_to_ptex(poly, corner_index, grid_u, grid_v, &u, &v);
192   /* Construct tangent matrix which corresponds to partial derivatives
193    * calculated for the other ptex face. */
194   float tangent_matrix[3][3];
195   average_construct_tangent_matrix(
196       data->subdiv, poly, ptex_face_index, corner_index, u, v, tangent_matrix);
197   /* Read displacement from other grid in a tangent space. */
198   float tangent_D[3];
199   average_read_displacement_tangent(data, displacement_grid, grid_u, grid_v, tangent_D);
200   /* Convert displacement to object space. */
201   mul_v3_m3v3(r_D, tangent_matrix, tangent_D);
202 }
203
204 static void average_get_other_ptex_and_corner(MultiresDisplacementData *data,
205                                               const int ptex_face_index,
206                                               const int corner,
207                                               const int corner_delta,
208                                               int *r_other_ptex_face_index,
209                                               int *r_other_corner_index)
210 {
211   const PolyCornerIndex *poly_corner = &data->ptex_poly_corner[ptex_face_index];
212   const MPoly *poly = &data->mpoly[poly_corner->poly_index];
213   const int num_corners = poly->totloop;
214   const bool is_quad = (num_corners == 4);
215   const int poly_index = poly - data->mpoly;
216   const int start_ptex_face_index = data->face_ptex_offset[poly_index];
217   *r_other_corner_index = (corner + corner_delta + num_corners) % num_corners;
218   *r_other_ptex_face_index = is_quad ? start_ptex_face_index :
219                                        start_ptex_face_index + *r_other_corner_index;
220 }
221
222 /* NOTE: Grid coordinates are relatiev to the other grid already. */
223 static void average_with_other(SubdivDisplacement *displacement,
224                                const int ptex_face_index,
225                                const int corner,
226                                const float grid_u,
227                                const float grid_v,
228                                const int corner_delta,
229                                float r_D[3])
230 {
231   MultiresDisplacementData *data = displacement->user_data;
232   const MDisps *other_displacement_grid = displacement_get_other_grid(
233       displacement, ptex_face_index, corner, corner_delta);
234   int other_ptex_face_index, other_corner_index;
235   average_get_other_ptex_and_corner(
236       data, ptex_face_index, corner, corner_delta, &other_ptex_face_index, &other_corner_index);
237   /* Get displacement in object space. */
238   float other_D[3];
239   average_read_displacement_object(data,
240                                    other_displacement_grid,
241                                    grid_u,
242                                    grid_v,
243                                    other_ptex_face_index,
244                                    other_corner_index,
245                                    other_D);
246   /* Average result with the other displacement vector. */
247   add_v3_v3(r_D, other_D);
248   mul_v3_fl(r_D, 0.5f);
249 }
250
251 static void average_with_all(SubdivDisplacement *displacement,
252                              const int ptex_face_index,
253                              const int corner,
254                              const float UNUSED(grid_u),
255                              const float UNUSED(grid_v),
256                              float r_D[3])
257 {
258   MultiresDisplacementData *data = displacement->user_data;
259   const PolyCornerIndex *poly_corner = &data->ptex_poly_corner[ptex_face_index];
260   const MPoly *poly = &data->mpoly[poly_corner->poly_index];
261   const int num_corners = poly->totloop;
262   for (int corner_delta = 1; corner_delta < num_corners; corner_delta++) {
263     average_with_other(displacement, ptex_face_index, corner, 0.0f, 0.0f, corner_delta, r_D);
264   }
265 }
266
267 static void average_with_next(SubdivDisplacement *displacement,
268                               const int ptex_face_index,
269                               const int corner,
270                               const float grid_u,
271                               const float UNUSED(grid_v),
272                               float r_D[3])
273 {
274   average_with_other(displacement, ptex_face_index, corner, 0.0f, grid_u, 1, r_D);
275 }
276
277 static void average_with_prev(SubdivDisplacement *displacement,
278                               const int ptex_face_index,
279                               const int corner,
280                               const float UNUSED(grid_u),
281                               const float grid_v,
282                               float r_D[3])
283 {
284   average_with_other(displacement, ptex_face_index, corner, grid_v, 0.0f, -1, r_D);
285 }
286
287 static void average_displacement(SubdivDisplacement *displacement,
288                                  eAverageWith average_with,
289                                  const int ptex_face_index,
290                                  const int corner,
291                                  const float grid_u,
292                                  const float grid_v,
293                                  float r_D[3])
294 {
295   switch (average_with) {
296     case AVERAGE_WITH_ALL:
297       average_with_all(displacement, ptex_face_index, corner, grid_u, grid_v, r_D);
298       break;
299     case AVERAGE_WITH_PREV:
300       average_with_prev(displacement, ptex_face_index, corner, grid_u, grid_v, r_D);
301       break;
302     case AVERAGE_WITH_NEXT:
303       average_with_next(displacement, ptex_face_index, corner, grid_u, grid_v, r_D);
304       break;
305     case AVERAGE_WITH_NONE:
306       break;
307   }
308 }
309
310 static int displacement_get_face_corner(MultiresDisplacementData *data,
311                                         const int ptex_face_index,
312                                         const float u,
313                                         const float v)
314 {
315   const PolyCornerIndex *poly_corner = &data->ptex_poly_corner[ptex_face_index];
316   const MPoly *poly = &data->mpoly[poly_corner->poly_index];
317   const int num_corners = poly->totloop;
318   const bool is_quad = (num_corners == 4);
319   if (is_quad) {
320     float dummy_corner_u, dummy_corner_v;
321     return BKE_subdiv_rotate_quad_to_corner(u, v, &dummy_corner_u, &dummy_corner_v);
322   }
323   else {
324     return poly_corner->corner;
325   }
326 }
327
328 static void initialize(SubdivDisplacement *displacement)
329 {
330   MultiresDisplacementData *data = displacement->user_data;
331   Mesh *mesh = data->mesh;
332   /* Make sure external displacement is read. */
333   CustomData_external_read(&mesh->ldata, &mesh->id, CD_MASK_MDISPS, mesh->totloop);
334   data->is_initialized = true;
335 }
336
337 static void eval_displacement(SubdivDisplacement *displacement,
338                               const int ptex_face_index,
339                               const float u,
340                               const float v,
341                               const float dPdu[3],
342                               const float dPdv[3],
343                               float r_D[3])
344 {
345   MultiresDisplacementData *data = displacement->user_data;
346   BLI_assert(data->is_initialized);
347   const int grid_size = data->grid_size;
348   /* Get displacement in tangent space. */
349   const MDisps *displacement_grid;
350   float grid_u, grid_v;
351   const int corner_of_quad = displacement_get_grid_and_coord(
352       displacement, ptex_face_index, u, v, &displacement_grid, &grid_u, &grid_v);
353   /* Read displacement from the current displacement grid and see if any
354    * averaging is needed. */
355   float tangent_D[3];
356   eAverageWith average_with = read_displacement_grid(
357       displacement_grid, grid_size, grid_u, grid_v, tangent_D);
358   /* Convert it to the object space. */
359   float tangent_matrix[3][3];
360   BKE_multires_construct_tangent_matrix(tangent_matrix, dPdu, dPdv, corner_of_quad);
361   mul_v3_m3v3(r_D, tangent_matrix, tangent_D);
362   /* For the boundary points of grid average two (or all) neighbor grids. */
363   const int corner = displacement_get_face_corner(data, ptex_face_index, u, v);
364   average_displacement(displacement, average_with, ptex_face_index, corner, grid_u, grid_v, r_D);
365 }
366
367 static void free_displacement(SubdivDisplacement *displacement)
368 {
369   MultiresDisplacementData *data = displacement->user_data;
370   MEM_freeN(data->ptex_poly_corner);
371   MEM_freeN(data);
372 }
373
374 /* TODO(sergey): This seems to be generally used information, which almost
375  * worth adding to a subdiv itself, with possible cache of the value. */
376 static int count_num_ptex_faces(const Mesh *mesh)
377 {
378   int num_ptex_faces = 0;
379   const MPoly *mpoly = mesh->mpoly;
380   for (int poly_index = 0; poly_index < mesh->totpoly; poly_index++) {
381     const MPoly *poly = &mpoly[poly_index];
382     num_ptex_faces += (poly->totloop == 4) ? 1 : poly->totloop;
383   }
384   return num_ptex_faces;
385 }
386
387 static void displacement_data_init_mapping(SubdivDisplacement *displacement, const Mesh *mesh)
388 {
389   MultiresDisplacementData *data = displacement->user_data;
390   const MPoly *mpoly = mesh->mpoly;
391   const int num_ptex_faces = count_num_ptex_faces(mesh);
392   /* Allocate memory. */
393   data->ptex_poly_corner = MEM_malloc_arrayN(
394       num_ptex_faces, sizeof(*data->ptex_poly_corner), "ptex poly corner");
395   /* Fill in offsets. */
396   int ptex_face_index = 0;
397   PolyCornerIndex *ptex_poly_corner = data->ptex_poly_corner;
398   for (int poly_index = 0; poly_index < mesh->totpoly; poly_index++) {
399     const MPoly *poly = &mpoly[poly_index];
400     if (poly->totloop == 4) {
401       ptex_poly_corner[ptex_face_index].poly_index = poly_index;
402       ptex_poly_corner[ptex_face_index].corner = 0;
403       ptex_face_index++;
404     }
405     else {
406       for (int corner = 0; corner < poly->totloop; corner++) {
407         ptex_poly_corner[ptex_face_index].poly_index = poly_index;
408         ptex_poly_corner[ptex_face_index].corner = corner;
409         ptex_face_index++;
410       }
411     }
412   }
413 }
414
415 static void displacement_init_data(SubdivDisplacement *displacement,
416                                    Subdiv *subdiv,
417                                    Mesh *mesh,
418                                    const MultiresModifierData *mmd)
419 {
420   MultiresDisplacementData *data = displacement->user_data;
421   data->subdiv = subdiv;
422   data->grid_size = BKE_subdiv_grid_size_from_level(mmd->totlvl);
423   data->mesh = mesh;
424   data->mpoly = mesh->mpoly;
425   data->mdisps = CustomData_get_layer(&mesh->ldata, CD_MDISPS);
426   data->face_ptex_offset = BKE_subdiv_face_ptex_offset_get(subdiv);
427   data->is_initialized = false;
428   displacement_data_init_mapping(displacement, mesh);
429 }
430
431 static void displacement_init_functions(SubdivDisplacement *displacement)
432 {
433   displacement->initialize = initialize;
434   displacement->eval_displacement = eval_displacement;
435   displacement->free = free_displacement;
436 }
437
438 void BKE_subdiv_displacement_attach_from_multires(Subdiv *subdiv,
439                                                   Mesh *mesh,
440                                                   const MultiresModifierData *mmd)
441 {
442   /* Make sure we don't have previously assigned displacement. */
443   BKE_subdiv_displacement_detach(subdiv);
444   /* It is possible to have mesh without MDISPS layer. Happens when using
445    * dynamic topology. */
446   if (!CustomData_has_layer(&mesh->ldata, CD_MDISPS)) {
447     return;
448   }
449   /* Allocate all required memory. */
450   SubdivDisplacement *displacement = MEM_callocN(sizeof(SubdivDisplacement),
451                                                  "multires displacement");
452   displacement->user_data = MEM_callocN(sizeof(MultiresDisplacementData),
453                                         "multires displacement data");
454   displacement_init_data(displacement, subdiv, mesh, mmd);
455   displacement_init_functions(displacement);
456   /* Finish. */
457   subdiv->displacement_evaluator = displacement;
458 }