Blender  V2.93
multires_reshape_util.c
Go to the documentation of this file.
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) 2020 Blender Foundation.
17  * All rights reserved.
18  */
19 
24 #include "multires_reshape.h"
25 
26 #include "MEM_guardedalloc.h"
27 
28 #include "DNA_mesh_types.h"
29 #include "DNA_modifier_types.h"
30 #include "DNA_object_types.h"
31 #include "DNA_scene_types.h"
32 
33 #include "BLI_task.h"
34 
35 #include "BKE_mesh.h"
36 #include "BKE_mesh_runtime.h"
37 #include "BKE_multires.h"
38 #include "BKE_subdiv.h"
39 #include "BKE_subdiv_ccg.h"
40 #include "BKE_subdiv_eval.h"
41 #include "BKE_subdiv_foreach.h"
42 #include "BKE_subdiv_mesh.h"
43 
44 #include "DEG_depsgraph_query.h"
45 
46 /* -------------------------------------------------------------------- */
50 /* Create subdivision surface descriptor which is configured for surface evaluation at a given
51  * multires modifier. */
53  /*const*/ Object *object,
54  const MultiresModifierData *mmd)
55 {
56  Mesh *base_mesh;
57 
58  if (depsgraph != NULL) {
60  Object *object_eval = DEG_get_evaluated_object(depsgraph, object);
61  base_mesh = mesh_get_eval_deform(depsgraph, scene_eval, object_eval, &CD_MASK_BAREMESH);
62  }
63  else {
64  base_mesh = (Mesh *)object->data;
65  }
66 
67  SubdivSettings subdiv_settings;
68  BKE_multires_subdiv_settings_init(&subdiv_settings, mmd);
69  Subdiv *subdiv = BKE_subdiv_new_from_mesh(&subdiv_settings, base_mesh);
70  if (!BKE_subdiv_eval_begin_from_mesh(subdiv, base_mesh, NULL)) {
71  BKE_subdiv_free(subdiv);
72  return NULL;
73  }
74  return subdiv;
75 }
76 
77 static void context_zero(MultiresReshapeContext *reshape_context)
78 {
79  memset(reshape_context, 0, sizeof(*reshape_context));
80 }
81 
82 static void context_init_lookup(MultiresReshapeContext *reshape_context)
83 {
84  const Mesh *base_mesh = reshape_context->base_mesh;
85  const MPoly *mpoly = base_mesh->mpoly;
86  const int num_faces = base_mesh->totpoly;
87 
88  reshape_context->face_start_grid_index = MEM_malloc_arrayN(
89  sizeof(int), num_faces, "face_start_grid_index");
90  int num_grids = 0;
91  int num_ptex_faces = 0;
92  for (int face_index = 0; face_index < num_faces; ++face_index) {
93  const int num_corners = mpoly[face_index].totloop;
94  reshape_context->face_start_grid_index[face_index] = num_grids;
95  num_grids += num_corners;
96  num_ptex_faces += (num_corners == 4) ? 1 : num_corners;
97  }
98 
99  reshape_context->grid_to_face_index = MEM_malloc_arrayN(
100  sizeof(int), num_grids, "grid_to_face_index");
101  reshape_context->ptex_start_grid_index = MEM_malloc_arrayN(
102  sizeof(int), num_ptex_faces, "ptex_start_grid_index");
103  for (int face_index = 0, grid_index = 0, ptex_index = 0; face_index < num_faces; ++face_index) {
104  const int num_corners = mpoly[face_index].totloop;
105  const int num_face_ptex_faces = (num_corners == 4) ? 1 : num_corners;
106  for (int i = 0; i < num_face_ptex_faces; ++i) {
107  reshape_context->ptex_start_grid_index[ptex_index + i] = grid_index + i;
108  }
109  for (int corner = 0; corner < num_corners; ++corner, ++grid_index) {
110  reshape_context->grid_to_face_index[grid_index] = face_index;
111  }
112  ptex_index += num_face_ptex_faces;
113  }
114 
115  /* Store number of grids, which will be used for sanity checks. */
116  reshape_context->num_grids = num_grids;
117 }
118 
120 {
121  Mesh *base_mesh = reshape_context->base_mesh;
122  reshape_context->mdisps = CustomData_get_layer(&base_mesh->ldata, CD_MDISPS);
123  reshape_context->grid_paint_masks = CustomData_get_layer(&base_mesh->ldata, CD_GRID_PAINT_MASK);
124 }
125 
126 static void context_init_commoon(MultiresReshapeContext *reshape_context)
127 {
128  BLI_assert(reshape_context->subdiv != NULL);
129  BLI_assert(reshape_context->base_mesh != NULL);
130 
131  reshape_context->face_ptex_offset = BKE_subdiv_face_ptex_offset_get(reshape_context->subdiv);
132 
133  context_init_lookup(reshape_context);
134  context_init_grid_pointers(reshape_context);
135 }
136 
137 static bool context_is_valid(MultiresReshapeContext *reshape_context)
138 {
139  if (reshape_context->mdisps == NULL) {
140  /* Multires displacement has been removed before current changes were applies. */
141  return false;
142  }
143  return true;
144 }
145 
146 static bool context_verify_or_free(MultiresReshapeContext *reshape_context)
147 {
148  const bool is_valid = context_is_valid(reshape_context);
149  if (!is_valid) {
150  multires_reshape_context_free(reshape_context);
151  }
152  return is_valid;
153 }
154 
157  Object *object,
159 {
160  context_zero(reshape_context);
161 
162  const bool use_render_params = false;
163  Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
164  Mesh *base_mesh = (Mesh *)object->data;
165 
166  reshape_context->depsgraph = depsgraph;
167  reshape_context->object = object;
168  reshape_context->mmd = mmd;
169 
170  reshape_context->base_mesh = base_mesh;
171 
172  reshape_context->subdiv = multires_reshape_create_subdiv(NULL, object, mmd);
173  reshape_context->need_free_subdiv = true;
174 
175  reshape_context->reshape.level = multires_get_level(
176  scene_eval, object, mmd, use_render_params, true);
178  reshape_context->reshape.level);
179 
180  reshape_context->top.level = mmd->totlvl;
181  reshape_context->top.grid_size = BKE_subdiv_grid_size_from_level(reshape_context->top.level);
182 
183  context_init_commoon(reshape_context);
184 
185  return context_verify_or_free(reshape_context);
186 }
187 
190  Object *object,
192 {
193  context_zero(reshape_context);
194 
195  const bool use_render_params = false;
196  Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
197  Mesh *base_mesh = (Mesh *)object->data;
198 
199  reshape_context->depsgraph = depsgraph;
200  reshape_context->object = object;
201  reshape_context->mmd = mmd;
202 
203  reshape_context->base_mesh = base_mesh;
204 
205  reshape_context->subdiv = multires_reshape_create_subdiv(depsgraph, object, mmd);
206  reshape_context->need_free_subdiv = true;
207 
208  reshape_context->reshape.level = multires_get_level(
209  scene_eval, object, mmd, use_render_params, true);
211  reshape_context->reshape.level);
212 
213  reshape_context->top.level = mmd->totlvl;
214  reshape_context->top.grid_size = BKE_subdiv_grid_size_from_level(reshape_context->top.level);
215 
216  context_init_commoon(reshape_context);
217 
218  return context_verify_or_free(reshape_context);
219 }
220 
222  SubdivCCG *subdiv_ccg,
223  Mesh *base_mesh,
224  int top_level)
225 {
226  context_zero(reshape_context);
227 
228  reshape_context->base_mesh = base_mesh;
229 
230  reshape_context->subdiv = subdiv_ccg->subdiv;
231  reshape_context->need_free_subdiv = false;
232 
233  reshape_context->reshape.level = subdiv_ccg->level;
235  reshape_context->reshape.level);
236 
237  reshape_context->top.level = top_level;
238  reshape_context->top.grid_size = BKE_subdiv_grid_size_from_level(reshape_context->top.level);
239 
240  context_init_commoon(reshape_context);
241 
242  return context_verify_or_free(reshape_context);
243 }
244 
246  struct Object *object,
247  struct MultiresModifierData *mmd,
248  int top_level)
249 {
250  Subdiv *subdiv = multires_reshape_create_subdiv(NULL, object, mmd);
251 
253  reshape_context, object, mmd, subdiv, top_level);
254 
255  reshape_context->need_free_subdiv = true;
256 
257  return result;
258 }
259 
261  struct Object *object,
262  struct MultiresModifierData *mmd,
263  struct Subdiv *subdiv,
264  int top_level)
265 {
266  context_zero(reshape_context);
267 
268  Mesh *base_mesh = (Mesh *)object->data;
269 
270  reshape_context->mmd = mmd;
271  reshape_context->base_mesh = base_mesh;
272 
273  reshape_context->subdiv = subdiv;
274  reshape_context->need_free_subdiv = false;
275 
276  reshape_context->reshape.level = mmd->totlvl;
278  reshape_context->reshape.level);
279 
280  reshape_context->top.level = top_level;
281  reshape_context->top.grid_size = BKE_subdiv_grid_size_from_level(reshape_context->top.level);
282 
283  context_init_commoon(reshape_context);
284 
285  return context_verify_or_free(reshape_context);
286 }
287 
289 {
290  MDisps *orig_mdisps = reshape_context->orig.mdisps;
291  GridPaintMask *orig_grid_paint_masks = reshape_context->orig.grid_paint_masks;
292 
293  if (orig_mdisps == NULL && orig_grid_paint_masks == NULL) {
294  return;
295  }
296 
297  const int num_grids = reshape_context->num_grids;
298  for (int grid_index = 0; grid_index < num_grids; grid_index++) {
299  if (orig_mdisps != NULL) {
300  MDisps *orig_grid = &orig_mdisps[grid_index];
301  MEM_SAFE_FREE(orig_grid->disps);
302  }
303  if (orig_grid_paint_masks != NULL) {
304  GridPaintMask *orig_paint_mask_grid = &orig_grid_paint_masks[grid_index];
305  MEM_SAFE_FREE(orig_paint_mask_grid->data);
306  }
307  }
308 
309  MEM_SAFE_FREE(orig_mdisps);
310  MEM_SAFE_FREE(orig_grid_paint_masks);
311 
312  reshape_context->orig.mdisps = NULL;
313  reshape_context->orig.grid_paint_masks = NULL;
314 }
315 
317 {
318  if (reshape_context->need_free_subdiv) {
319  BKE_subdiv_free(reshape_context->subdiv);
320  }
321 
322  multires_reshape_free_original_grids(reshape_context);
323 
324  MEM_SAFE_FREE(reshape_context->face_start_grid_index);
325  MEM_SAFE_FREE(reshape_context->ptex_start_grid_index);
326  MEM_SAFE_FREE(reshape_context->grid_to_face_index);
327 }
328 
331 /* -------------------------------------------------------------------- */
335 /* For the given grid index get index of face it was created for. */
337  int grid_index)
338 {
339  BLI_assert(grid_index >= 0);
340  BLI_assert(grid_index < reshape_context->num_grids);
341 
342  /* TODO(sergey): Optimization: when SubdivCCG is known we can calculate face index using
343  * SubdivCCG::grid_faces and SubdivCCG::faces, saving memory used by grid_to_face_index. */
344 
345  return reshape_context->grid_to_face_index[grid_index];
346 }
347 
348 /* For the given grid index get corner of a face it was created for. */
349 int multires_reshape_grid_to_corner(const MultiresReshapeContext *reshape_context, int grid_index)
350 {
351  BLI_assert(grid_index >= 0);
352  BLI_assert(grid_index < reshape_context->num_grids);
353 
354  /* TODO(sergey): Optimization: when SubdivCCG is known we can calculate face index using
355  * SubdivCCG::grid_faces and SubdivCCG::faces, saving memory used by grid_to_face_index. */
356 
357  const int face_index = multires_reshape_grid_to_face_index(reshape_context, grid_index);
358  return grid_index - reshape_context->face_start_grid_index[face_index];
359 }
360 
361 bool multires_reshape_is_quad_face(const MultiresReshapeContext *reshape_context, int face_index)
362 {
363  const MPoly *base_poly = &reshape_context->base_mesh->mpoly[face_index];
364  return (base_poly->totloop == 4);
365 }
366 
367 /* For the given grid index get index of corresponding ptex face. */
369  int grid_index)
370 {
371  const int face_index = multires_reshape_grid_to_face_index(reshape_context, grid_index);
372  const int corner = multires_reshape_grid_to_corner(reshape_context, grid_index);
373  const bool is_quad = multires_reshape_is_quad_face(reshape_context, face_index);
374  return reshape_context->face_ptex_offset[face_index] + (is_quad ? 0 : corner);
375 }
376 
377 /* Convert normalized coordinate within a grid to a normalized coordinate within a ptex face. */
379  const GridCoord *grid_coord)
380 {
381  PTexCoord ptex_coord;
382 
383  ptex_coord.ptex_face_index = multires_reshape_grid_to_ptex_index(reshape_context,
384  grid_coord->grid_index);
385 
386  float corner_u, corner_v;
387  BKE_subdiv_grid_uv_to_ptex_face_uv(grid_coord->u, grid_coord->v, &corner_u, &corner_v);
388 
389  const int face_index = multires_reshape_grid_to_face_index(reshape_context,
390  grid_coord->grid_index);
391  const int corner = multires_reshape_grid_to_corner(reshape_context, grid_coord->grid_index);
392  if (multires_reshape_is_quad_face(reshape_context, face_index)) {
393  float grid_u, grid_v;
394  BKE_subdiv_ptex_face_uv_to_grid_uv(corner_u, corner_v, &grid_u, &grid_v);
395  BKE_subdiv_rotate_grid_to_quad(corner, grid_u, grid_v, &ptex_coord.u, &ptex_coord.v);
396  }
397  else {
398  ptex_coord.u = corner_u;
399  ptex_coord.v = corner_v;
400  }
401 
402  return ptex_coord;
403 }
404 
405 /* Convert a normalized coordinate within a ptex face to a normalized coordinate within a grid. */
407  const PTexCoord *ptex_coord)
408 {
409  GridCoord grid_coord;
410 
411  const int start_grid_index = reshape_context->ptex_start_grid_index[ptex_coord->ptex_face_index];
412  const int face_index = reshape_context->grid_to_face_index[start_grid_index];
413 
414  int corner_delta;
415  if (multires_reshape_is_quad_face(reshape_context, face_index)) {
416  corner_delta = BKE_subdiv_rotate_quad_to_corner(
417  ptex_coord->u, ptex_coord->v, &grid_coord.u, &grid_coord.v);
418  }
419  else {
420  corner_delta = 0;
421  grid_coord.u = ptex_coord->u;
422  grid_coord.v = ptex_coord->v;
423  }
424  grid_coord.grid_index = start_grid_index + corner_delta;
425 
426  BKE_subdiv_ptex_face_uv_to_grid_uv(grid_coord.u, grid_coord.v, &grid_coord.u, &grid_coord.v);
427 
428  return grid_coord;
429 }
430 
432  const int face_index,
433  const int corner,
434  const float dPdu[3],
435  const float dPdv[3],
436  float r_tangent_matrix[3][3])
437 {
438  /* For a quad faces we would need to flip the tangent, since they will use
439  * use different coordinates within displacement grid compared to the ptex face. */
440  const bool is_quad = multires_reshape_is_quad_face(reshape_context, face_index);
441  const int tangent_corner = is_quad ? corner : 0;
442  BKE_multires_construct_tangent_matrix(r_tangent_matrix, dPdu, dPdv, tangent_corner);
443 }
444 
446  const MultiresReshapeContext *reshape_context, const GridCoord *grid_coord)
447 {
448  ReshapeGridElement grid_element = {NULL, NULL};
449 
450  const int grid_size = reshape_context->top.grid_size;
451  const int grid_x = lround(grid_coord->u * (grid_size - 1));
452  const int grid_y = lround(grid_coord->v * (grid_size - 1));
453  const int grid_element_index = grid_y * grid_size + grid_x;
454 
455  if (reshape_context->mdisps != NULL) {
456  MDisps *displacement_grid = &reshape_context->mdisps[grid_coord->grid_index];
457  grid_element.displacement = displacement_grid->disps[grid_element_index];
458  }
459 
460  if (reshape_context->grid_paint_masks != NULL) {
461  GridPaintMask *grid_paint_mask = &reshape_context->grid_paint_masks[grid_coord->grid_index];
462  grid_element.mask = &grid_paint_mask->data[grid_element_index];
463  }
464 
465  return grid_element;
466 }
467 
469  const MultiresReshapeContext *reshape_context, const PTexCoord *ptex_coord)
470 {
471  GridCoord grid_coord = multires_reshape_ptex_coord_to_grid(reshape_context, ptex_coord);
472  return multires_reshape_grid_element_for_grid_coord(reshape_context, &grid_coord);
473 }
474 
476  const MultiresReshapeContext *reshape_context, const GridCoord *grid_coord)
477 {
478  ReshapeConstGridElement grid_element = {{0.0f, 0.0f, 0.0f}, 0.0f};
479 
480  const MDisps *mdisps = reshape_context->orig.mdisps;
481  if (mdisps != NULL) {
482  const MDisps *displacement_grid = &mdisps[grid_coord->grid_index];
483  if (displacement_grid->disps != NULL) {
484  const int grid_size = BKE_subdiv_grid_size_from_level(displacement_grid->level);
485  const int grid_x = lround(grid_coord->u * (grid_size - 1));
486  const int grid_y = lround(grid_coord->v * (grid_size - 1));
487  const int grid_element_index = grid_y * grid_size + grid_x;
488  copy_v3_v3(grid_element.displacement, displacement_grid->disps[grid_element_index]);
489  }
490  }
491 
492  const GridPaintMask *grid_paint_masks = reshape_context->orig.grid_paint_masks;
493  if (grid_paint_masks != NULL) {
494  const GridPaintMask *paint_mask_grid = &grid_paint_masks[grid_coord->grid_index];
495  if (paint_mask_grid->data != NULL) {
496  const int grid_size = BKE_subdiv_grid_size_from_level(paint_mask_grid->level);
497  const int grid_x = lround(grid_coord->u * (grid_size - 1));
498  const int grid_y = lround(grid_coord->v * (grid_size - 1));
499  const int grid_element_index = grid_y * grid_size + grid_x;
500  grid_element.mask = paint_mask_grid->data[grid_element_index];
501  }
502  }
503 
504  return grid_element;
505 }
506 
509 /* -------------------------------------------------------------------- */
514  const GridCoord *grid_coord,
515  float r_P[3],
516  float r_tangent_matrix[3][3])
517 {
518  float dPdu[3], dPdv[3];
519  const PTexCoord ptex_coord = multires_reshape_grid_coord_to_ptex(reshape_context, grid_coord);
520  Subdiv *subdiv = reshape_context->subdiv;
522  subdiv, ptex_coord.ptex_face_index, ptex_coord.u, ptex_coord.v, r_P, dPdu, dPdv);
523 
524  const int face_index = multires_reshape_grid_to_face_index(reshape_context,
525  grid_coord->grid_index);
526  const int corner = multires_reshape_grid_to_corner(reshape_context, grid_coord->grid_index);
528  reshape_context, face_index, corner, dPdu, dPdv, r_tangent_matrix);
529 }
530 
533 /* -------------------------------------------------------------------- */
537 static void allocate_displacement_grid(MDisps *displacement_grid, const int level)
538 {
539  const int grid_size = BKE_subdiv_grid_size_from_level(level);
540  const int grid_area = grid_size * grid_size;
541  float(*disps)[3] = MEM_calloc_arrayN(grid_area, sizeof(float[3]), "multires disps");
542  if (displacement_grid->disps != NULL) {
543  MEM_freeN(displacement_grid->disps);
544  }
545  /* TODO(sergey): Preserve data on the old level. */
546  displacement_grid->disps = disps;
547  displacement_grid->totdisp = grid_area;
548  displacement_grid->level = level;
549 }
550 
551 static void ensure_displacement_grid(MDisps *displacement_grid, const int level)
552 {
553  if (displacement_grid->disps != NULL && displacement_grid->level >= level) {
554  return;
555  }
556  allocate_displacement_grid(displacement_grid, level);
557 }
558 
559 static void ensure_displacement_grids(Mesh *mesh, const int grid_level)
560 {
561  const int num_grids = mesh->totloop;
563  for (int grid_index = 0; grid_index < num_grids; grid_index++) {
564  ensure_displacement_grid(&mdisps[grid_index], grid_level);
565  }
566 }
567 
568 static void ensure_mask_grids(Mesh *mesh, const int level)
569 {
571  if (grid_paint_masks == NULL) {
572  return;
573  }
574  const int num_grids = mesh->totloop;
575  const int grid_size = BKE_subdiv_grid_size_from_level(level);
576  const int grid_area = grid_size * grid_size;
577  for (int grid_index = 0; grid_index < num_grids; grid_index++) {
578  GridPaintMask *grid_paint_mask = &grid_paint_masks[grid_index];
579  if (grid_paint_mask->level >= level) {
580  continue;
581  }
582  grid_paint_mask->level = level;
583  if (grid_paint_mask->data) {
584  MEM_freeN(grid_paint_mask->data);
585  }
586  /* TODO(sergey): Preserve data on the old level. */
587  grid_paint_mask->data = MEM_calloc_arrayN(grid_area, sizeof(float), "gpm.data");
588  }
589 }
590 
591 void multires_reshape_ensure_grids(Mesh *mesh, const int level)
592 {
594  ensure_mask_grids(mesh, level);
595 }
596 
599 /* -------------------------------------------------------------------- */
604 {
605  const MDisps *mdisps = reshape_context->mdisps;
606  const GridPaintMask *grid_paint_masks = reshape_context->grid_paint_masks;
607 
608  MDisps *orig_mdisps = MEM_dupallocN(mdisps);
609  GridPaintMask *orig_grid_paint_masks = NULL;
610  if (grid_paint_masks != NULL) {
611  orig_grid_paint_masks = MEM_dupallocN(grid_paint_masks);
612  }
613 
614  const int num_grids = reshape_context->num_grids;
615  for (int grid_index = 0; grid_index < num_grids; grid_index++) {
616  MDisps *orig_grid = &orig_mdisps[grid_index];
617  /* Ignore possibly invalid/non-allocated original grids. They will be replaced with 0 original
618  * data when accessed during reshape process.
619  * Reshape process will ensure all grids are on top level, but that happens on separate set of
620  * grids which eventually replaces original one. */
621  if (orig_grid->disps != NULL) {
622  orig_grid->disps = MEM_dupallocN(orig_grid->disps);
623  }
624  if (orig_grid_paint_masks != NULL) {
625  GridPaintMask *orig_paint_mask_grid = &orig_grid_paint_masks[grid_index];
626  if (orig_paint_mask_grid->data != NULL) {
627  orig_paint_mask_grid->data = MEM_dupallocN(orig_paint_mask_grid->data);
628  }
629  }
630  }
631 
632  reshape_context->orig.mdisps = orig_mdisps;
633  reshape_context->orig.grid_paint_masks = orig_grid_paint_masks;
634 }
635 
636 typedef void (*ForeachGridCoordinateCallback)(const MultiresReshapeContext *reshape_context,
637  const GridCoord *grid_coord,
638  void *userdata_v);
639 
642 
645 
649 
650 static void foreach_grid_face_coordinate_task(void *__restrict userdata_v,
651  const int face_index,
652  const TaskParallelTLS *__restrict UNUSED(tls))
653 {
654  ForeachGridCoordinateTaskData *data = userdata_v;
655 
656  const MultiresReshapeContext *reshape_context = data->reshape_context;
657 
658  const Mesh *base_mesh = data->reshape_context->base_mesh;
659  const MPoly *mpoly = base_mesh->mpoly;
660  const int grid_size = data->grid_size;
661  const float grid_size_1_inv = 1.0f / (((float)grid_size) - 1.0f);
662 
663  const int num_corners = mpoly[face_index].totloop;
664  int grid_index = reshape_context->face_start_grid_index[face_index];
665  for (int corner = 0; corner < num_corners; ++corner, ++grid_index) {
666  for (int y = 0; y < grid_size; ++y) {
667  const float v = (float)y * grid_size_1_inv;
668  for (int x = 0; x < grid_size; ++x) {
669  const float u = (float)x * grid_size_1_inv;
670 
671  GridCoord grid_coord;
672  grid_coord.grid_index = grid_index;
673  grid_coord.u = u;
674  grid_coord.v = v;
675 
676  data->callback(data->reshape_context, &grid_coord, data->callback_userdata_v);
677  }
678  }
679  }
680 }
681 
682 /* Run given callback for every grid coordinate at a given level. */
683 static void foreach_grid_coordinate(const MultiresReshapeContext *reshape_context,
684  const int level,
686  void *userdata_v)
687 {
689  data.reshape_context = reshape_context;
690  data.grid_size = BKE_subdiv_grid_size_from_level(level);
691  data.grid_size_1_inv = 1.0f / (((float)data.grid_size) - 1.0f);
692  data.callback = callback;
693  data.callback_userdata_v = userdata_v;
694 
695  TaskParallelSettings parallel_range_settings;
696  BLI_parallel_range_settings_defaults(&parallel_range_settings);
697  parallel_range_settings.min_iter_per_thread = 1;
698 
699  const Mesh *base_mesh = reshape_context->base_mesh;
700  const int num_faces = base_mesh->totpoly;
702  0, num_faces, &data, foreach_grid_face_coordinate_task, &parallel_range_settings);
703 }
704 
706  const MultiresReshapeContext *reshape_context,
707  const GridCoord *grid_coord,
708  void *UNUSED(userdata_v))
709 {
710  float P[3];
711  float tangent_matrix[3][3];
712  multires_reshape_evaluate_limit_at_grid(reshape_context, grid_coord, P, tangent_matrix);
713 
714  float inv_tangent_matrix[3][3];
715  invert_m3_m3(inv_tangent_matrix, tangent_matrix);
716 
718  grid_coord);
719 
720  float D[3];
721  sub_v3_v3v3(D, grid_element.displacement, P);
722 
723  float tangent_D[3];
724  mul_v3_m3v3(tangent_D, inv_tangent_matrix, D);
725 
726  copy_v3_v3(grid_element.displacement, tangent_D);
727 }
728 
730  const MultiresReshapeContext *reshape_context)
731 {
732  foreach_grid_coordinate(reshape_context,
733  reshape_context->top.level,
735  NULL);
736 }
737 
740 /* -------------------------------------------------------------------- */
744 /* TODO(sergey): Make foreach_grid_coordinate more accessible and move this functionality to
745  * own file. */
746 
747 static void assign_final_coords_from_mdisps(const MultiresReshapeContext *reshape_context,
748  const GridCoord *grid_coord,
749  void *UNUSED(userdata_v))
750 {
751  float P[3];
752  float tangent_matrix[3][3];
753  multires_reshape_evaluate_limit_at_grid(reshape_context, grid_coord, P, tangent_matrix);
754 
756  grid_coord);
757  float D[3];
758  mul_v3_m3v3(D, tangent_matrix, grid_element.displacement);
759 
760  add_v3_v3v3(grid_element.displacement, P, D);
761 }
762 
764  const MultiresReshapeContext *reshape_context)
765 {
767  reshape_context, reshape_context->top.level, assign_final_coords_from_mdisps, NULL);
768 }
769 
771  const GridCoord *grid_coord,
772  void *UNUSED(userdata_v))
773 {
774  float P[3];
775  float tangent_matrix[3][3];
776  multires_reshape_evaluate_limit_at_grid(reshape_context, grid_coord, P, tangent_matrix);
777 
778  const ReshapeConstGridElement orig_grid_element =
779  multires_reshape_orig_grid_element_for_grid_coord(reshape_context, grid_coord);
780 
781  float D[3];
782  mul_v3_m3v3(D, tangent_matrix, orig_grid_element.displacement);
783 
785  grid_coord);
786  add_v3_v3v3(grid_element.displacement, P, D);
787 
788  if (grid_element.mask != NULL) {
789  *grid_element.mask = orig_grid_element.mask;
790  }
791 }
792 
794  const MultiresReshapeContext *reshape_context)
795 {
797  reshape_context, reshape_context->top.level, assign_final_elements_from_orig_mdisps, NULL);
798 }
799 
typedef float(TangentPoint)[2]
const CustomData_MeshMasks CD_MASK_BAREMESH
Definition: customdata.c:1919
void * CustomData_get_layer(const struct CustomData *data, int type)
struct Mesh * mesh_get_eval_deform(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob, const struct CustomData_MeshMasks *dataMask)
void BKE_multires_subdiv_settings_init(struct SubdivSettings *settings, const struct MultiresModifierData *mmd)
int multires_get_level(const struct Scene *scene, const struct Object *ob, const struct MultiresModifierData *mmd, bool render, bool ignore_simplify)
BLI_INLINE void BKE_multires_construct_tangent_matrix(float tangent_matrix[3][3], const float dPdu[3], const float dPdv[3], const int corner)
BLI_INLINE void BKE_subdiv_rotate_grid_to_quad(const int corner, const float grid_u, const float grid_v, float *r_quad_u, float *r_quad_v)
Definition: subdiv_inline.h:84
BLI_INLINE int BKE_subdiv_grid_size_from_level(const int level)
Definition: subdiv_inline.h:49
void BKE_subdiv_free(Subdiv *subdiv)
Definition: subdiv.c:189
BLI_INLINE int BKE_subdiv_rotate_quad_to_corner(const float quad_u, const float quad_v, float *r_corner_u, float *r_corner_v)
Definition: subdiv_inline.h:54
Subdiv * BKE_subdiv_new_from_mesh(const SubdivSettings *settings, const struct Mesh *mesh)
int * BKE_subdiv_face_ptex_offset_get(Subdiv *subdiv)
Definition: subdiv.c:206
BLI_INLINE void BKE_subdiv_grid_uv_to_ptex_face_uv(const float grid_u, const float grid_v, float *r_ptex_u, float *r_ptex_v)
Definition: subdiv_inline.h:40
BLI_INLINE void BKE_subdiv_ptex_face_uv_to_grid_uv(const float ptex_u, const float ptex_v, float *r_grid_u, float *r_grid_v)
Definition: subdiv_inline.h:31
bool BKE_subdiv_eval_begin_from_mesh(struct Subdiv *subdiv, const struct Mesh *mesh, const float(*coarse_vertex_cos)[3])
void BKE_subdiv_eval_limit_point_and_derivatives(struct Subdiv *subdiv, const int ptex_face_index, const float u, const float v, float r_P[3], float r_dPdu[3], float r_dPdv[3])
Definition: subdiv_eval.c:177
#define BLI_assert(a)
Definition: BLI_assert.h:58
bool invert_m3_m3(float R[3][3], const float A[3][3])
Definition: math_matrix.c:1161
void mul_v3_m3v3(float r[3], const float M[3][3], const float a[3])
Definition: math_matrix.c:901
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void add_v3_v3v3(float r[3], const float a[3], const float b[3])
void BLI_task_parallel_range(const int start, const int stop, void *userdata, TaskParallelRangeFunc func, const TaskParallelSettings *settings)
Definition: task_range.cc:110
BLI_INLINE void BLI_parallel_range_settings_defaults(TaskParallelSettings *settings)
Definition: BLI_task.h:231
#define UNUSED(x)
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:51
struct Object * DEG_get_evaluated_object(const struct Depsgraph *depsgraph, struct Object *object)
struct Scene * DEG_get_evaluated_scene(const struct Depsgraph *graph)
@ CD_GRID_PAINT_MASK
Object is a sort of wrapper for general info.
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
ATTR_WARN_UNUSED_RESULT const BMVert * v
bool is_valid
const Depsgraph * depsgraph
DEGForeachIDComponentCallback callback
void *(* MEM_malloc_arrayN)(size_t len, size_t size, const char *str)
Definition: mallocn.c:48
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
void *(* MEM_dupallocN)(const void *vmemh)
Definition: mallocn.c:42
void *(* MEM_calloc_arrayN)(size_t len, size_t size, const char *str)
Definition: mallocn.c:46
static float P(float k)
Definition: math_interp.c:41
int multires_reshape_grid_to_face_index(const MultiresReshapeContext *reshape_context, int grid_index)
void multires_reshape_assign_final_elements_from_orig_mdisps(const MultiresReshapeContext *reshape_context)
static void ensure_displacement_grids(Mesh *mesh, const int grid_level)
bool multires_reshape_is_quad_face(const MultiresReshapeContext *reshape_context, int face_index)
static void foreach_grid_face_coordinate_task(void *__restrict userdata_v, const int face_index, const TaskParallelTLS *__restrict UNUSED(tls))
void multires_reshape_assign_final_coords_from_mdisps(const MultiresReshapeContext *reshape_context)
static void context_init_grid_pointers(MultiresReshapeContext *reshape_context)
bool multires_reshape_context_create_from_object(MultiresReshapeContext *reshape_context, Depsgraph *depsgraph, Object *object, MultiresModifierData *mmd)
static bool context_verify_or_free(MultiresReshapeContext *reshape_context)
static void object_grid_element_to_tangent_displacement(const MultiresReshapeContext *reshape_context, const GridCoord *grid_coord, void *UNUSED(userdata_v))
struct ForeachGridCoordinateTaskData ForeachGridCoordinateTaskData
ReshapeGridElement multires_reshape_grid_element_for_grid_coord(const MultiresReshapeContext *reshape_context, const GridCoord *grid_coord)
int multires_reshape_grid_to_ptex_index(const MultiresReshapeContext *reshape_context, int grid_index)
static void context_init_lookup(MultiresReshapeContext *reshape_context)
PTexCoord multires_reshape_grid_coord_to_ptex(const MultiresReshapeContext *reshape_context, const GridCoord *grid_coord)
void multires_reshape_context_free(MultiresReshapeContext *reshape_context)
void multires_reshape_store_original_grids(MultiresReshapeContext *reshape_context)
static void allocate_displacement_grid(MDisps *displacement_grid, const int level)
int multires_reshape_grid_to_corner(const MultiresReshapeContext *reshape_context, int grid_index)
void multires_reshape_tangent_matrix_for_corner(const MultiresReshapeContext *reshape_context, const int face_index, const int corner, const float dPdu[3], const float dPdv[3], float r_tangent_matrix[3][3])
bool multires_reshape_context_create_from_modifier(MultiresReshapeContext *reshape_context, struct Object *object, struct MultiresModifierData *mmd, int top_level)
void multires_reshape_ensure_grids(Mesh *mesh, const int level)
void multires_reshape_free_original_grids(MultiresReshapeContext *reshape_context)
void(* ForeachGridCoordinateCallback)(const MultiresReshapeContext *reshape_context, const GridCoord *grid_coord, void *userdata_v)
static void foreach_grid_coordinate(const MultiresReshapeContext *reshape_context, const int level, ForeachGridCoordinateCallback callback, void *userdata_v)
bool multires_reshape_context_create_from_subdiv(MultiresReshapeContext *reshape_context, struct Object *object, struct MultiresModifierData *mmd, struct Subdiv *subdiv, int top_level)
static void context_zero(MultiresReshapeContext *reshape_context)
Subdiv * multires_reshape_create_subdiv(Depsgraph *depsgraph, Object *object, const MultiresModifierData *mmd)
void multires_reshape_object_grids_to_tangent_displacement(const MultiresReshapeContext *reshape_context)
bool multires_reshape_context_create_from_base_mesh(MultiresReshapeContext *reshape_context, Depsgraph *depsgraph, Object *object, MultiresModifierData *mmd)
ReshapeConstGridElement multires_reshape_orig_grid_element_for_grid_coord(const MultiresReshapeContext *reshape_context, const GridCoord *grid_coord)
ReshapeGridElement multires_reshape_grid_element_for_ptex_coord(const MultiresReshapeContext *reshape_context, const PTexCoord *ptex_coord)
static void ensure_displacement_grid(MDisps *displacement_grid, const int level)
static bool context_is_valid(MultiresReshapeContext *reshape_context)
GridCoord multires_reshape_ptex_coord_to_grid(const MultiresReshapeContext *reshape_context, const PTexCoord *ptex_coord)
static void assign_final_elements_from_orig_mdisps(const MultiresReshapeContext *reshape_context, const GridCoord *grid_coord, void *UNUSED(userdata_v))
static void context_init_commoon(MultiresReshapeContext *reshape_context)
static void ensure_mask_grids(Mesh *mesh, const int level)
void multires_reshape_evaluate_limit_at_grid(const MultiresReshapeContext *reshape_context, const GridCoord *grid_coord, float r_P[3], float r_tangent_matrix[3][3])
bool multires_reshape_context_create_from_ccg(MultiresReshapeContext *reshape_context, SubdivCCG *subdiv_ccg, Mesh *base_mesh, int top_level)
static void assign_final_coords_from_mdisps(const MultiresReshapeContext *reshape_context, const GridCoord *grid_coord, void *UNUSED(userdata_v))
ForeachGridCoordinateCallback callback
const MultiresReshapeContext * reshape_context
unsigned int level
float(* disps)[3]
struct CustomData pdata ldata
int totpoly
int totloop
struct MPoly * mpoly
struct MultiresReshapeContext::@101 orig
struct GridPaintMask * grid_paint_masks
struct MultiresModifierData * mmd
struct MultiresReshapeContext::@99 reshape
struct MDisps * mdisps
struct Object * object
struct Depsgraph * depsgraph
struct MultiresReshapeContext::@100 top
struct Subdiv * subdiv
void * data
struct Subdiv * subdiv
BLI_INLINE float D(const float *data, const int res[3], int x, int y, int z)
Definition: voxel.c:29