Blender  V3.3
multires_reshape_util.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2020 Blender Foundation. All rights reserved. */
3 
8 #include "multires_reshape.h"
9 
10 #include "MEM_guardedalloc.h"
11 
12 #include "DNA_mesh_types.h"
13 #include "DNA_meshdata_types.h"
14 #include "DNA_modifier_types.h"
15 #include "DNA_object_types.h"
16 #include "DNA_scene_types.h"
17 
18 #include "BLI_task.h"
19 
20 #include "BKE_customdata.h"
21 #include "BKE_mesh.h"
22 #include "BKE_mesh_runtime.h"
23 #include "BKE_multires.h"
24 #include "BKE_subdiv.h"
25 #include "BKE_subdiv_ccg.h"
26 #include "BKE_subdiv_eval.h"
27 #include "BKE_subdiv_foreach.h"
28 #include "BKE_subdiv_mesh.h"
29 
30 #include "DEG_depsgraph_query.h"
31 
32 /* -------------------------------------------------------------------- */
37  /*const*/ Object *object,
38  const MultiresModifierData *mmd)
39 {
40  Mesh *base_mesh;
41 
42  if (depsgraph != NULL) {
44  Object *object_eval = DEG_get_evaluated_object(depsgraph, object);
45  base_mesh = mesh_get_eval_deform(depsgraph, scene_eval, object_eval, &CD_MASK_BAREMESH);
46  }
47  else {
48  base_mesh = (Mesh *)object->data;
49  }
50 
51  SubdivSettings subdiv_settings;
52  BKE_multires_subdiv_settings_init(&subdiv_settings, mmd);
53  Subdiv *subdiv = BKE_subdiv_new_from_mesh(&subdiv_settings, base_mesh);
55  BKE_subdiv_free(subdiv);
56  return NULL;
57  }
58  return subdiv;
59 }
60 
61 static void context_zero(MultiresReshapeContext *reshape_context)
62 {
63  memset(reshape_context, 0, sizeof(*reshape_context));
64 }
65 
66 static void context_init_lookup(MultiresReshapeContext *reshape_context)
67 {
68  const Mesh *base_mesh = reshape_context->base_mesh;
69  const MPoly *mpoly = base_mesh->mpoly;
70  const int num_faces = base_mesh->totpoly;
71 
72  reshape_context->face_start_grid_index = MEM_malloc_arrayN(
73  num_faces, sizeof(int), "face_start_grid_index");
74  int num_grids = 0;
75  int num_ptex_faces = 0;
76  for (int face_index = 0; face_index < num_faces; ++face_index) {
77  const int num_corners = mpoly[face_index].totloop;
78  reshape_context->face_start_grid_index[face_index] = num_grids;
79  num_grids += num_corners;
80  num_ptex_faces += (num_corners == 4) ? 1 : num_corners;
81  }
82 
83  reshape_context->grid_to_face_index = MEM_malloc_arrayN(
84  num_grids, sizeof(int), "grid_to_face_index");
85  reshape_context->ptex_start_grid_index = MEM_malloc_arrayN(
86  num_ptex_faces, sizeof(int), "ptex_start_grid_index");
87  for (int face_index = 0, grid_index = 0, ptex_index = 0; face_index < num_faces; ++face_index) {
88  const int num_corners = mpoly[face_index].totloop;
89  const int num_face_ptex_faces = (num_corners == 4) ? 1 : num_corners;
90  for (int i = 0; i < num_face_ptex_faces; ++i) {
91  reshape_context->ptex_start_grid_index[ptex_index + i] = grid_index + i;
92  }
93  for (int corner = 0; corner < num_corners; ++corner, ++grid_index) {
94  reshape_context->grid_to_face_index[grid_index] = face_index;
95  }
96  ptex_index += num_face_ptex_faces;
97  }
98 
99  /* Store number of grids, which will be used for sanity checks. */
100  reshape_context->num_grids = num_grids;
101 }
102 
104 {
105  Mesh *base_mesh = reshape_context->base_mesh;
106  reshape_context->mdisps = CustomData_get_layer(&base_mesh->ldata, CD_MDISPS);
107  reshape_context->grid_paint_masks = CustomData_get_layer(&base_mesh->ldata, CD_GRID_PAINT_MASK);
108 }
109 
110 static void context_init_commoon(MultiresReshapeContext *reshape_context)
111 {
112  BLI_assert(reshape_context->subdiv != NULL);
113  BLI_assert(reshape_context->base_mesh != NULL);
114 
115  reshape_context->face_ptex_offset = BKE_subdiv_face_ptex_offset_get(reshape_context->subdiv);
116 
117  context_init_lookup(reshape_context);
118  context_init_grid_pointers(reshape_context);
119 }
120 
121 static bool context_is_valid(MultiresReshapeContext *reshape_context)
122 {
123  if (reshape_context->mdisps == NULL) {
124  /* Multi-resolution displacement has been removed before current changes were applies. */
125  return false;
126  }
127  return true;
128 }
129 
130 static bool context_verify_or_free(MultiresReshapeContext *reshape_context)
131 {
132  const bool is_valid = context_is_valid(reshape_context);
133  if (!is_valid) {
134  multires_reshape_context_free(reshape_context);
135  }
136  return is_valid;
137 }
138 
141  Object *object,
143 {
144  context_zero(reshape_context);
145 
146  const bool use_render_params = false;
147  Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
148  Mesh *base_mesh = (Mesh *)object->data;
149 
150  reshape_context->depsgraph = depsgraph;
151  reshape_context->object = object;
152  reshape_context->mmd = mmd;
153 
154  reshape_context->base_mesh = base_mesh;
155 
156  reshape_context->subdiv = multires_reshape_create_subdiv(NULL, object, mmd);
157  reshape_context->need_free_subdiv = true;
158 
159  reshape_context->reshape.level = multires_get_level(
160  scene_eval, object, mmd, use_render_params, true);
162  reshape_context->reshape.level);
163 
164  reshape_context->top.level = mmd->totlvl;
165  reshape_context->top.grid_size = BKE_subdiv_grid_size_from_level(reshape_context->top.level);
166 
167  context_init_commoon(reshape_context);
168 
169  return context_verify_or_free(reshape_context);
170 }
171 
174  Object *object,
176 {
177  context_zero(reshape_context);
178 
179  const bool use_render_params = false;
180  Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
181  Mesh *base_mesh = (Mesh *)object->data;
182 
183  reshape_context->depsgraph = depsgraph;
184  reshape_context->object = object;
185  reshape_context->mmd = mmd;
186 
187  reshape_context->base_mesh = base_mesh;
188 
189  reshape_context->subdiv = multires_reshape_create_subdiv(depsgraph, object, mmd);
190  reshape_context->need_free_subdiv = true;
191 
192  reshape_context->reshape.level = multires_get_level(
193  scene_eval, object, mmd, use_render_params, true);
195  reshape_context->reshape.level);
196 
197  reshape_context->top.level = mmd->totlvl;
198  reshape_context->top.grid_size = BKE_subdiv_grid_size_from_level(reshape_context->top.level);
199 
200  reshape_context->cd_vertex_crease = CustomData_get_layer(&base_mesh->vdata, CD_CREASE);
201 
202  context_init_commoon(reshape_context);
203 
204  return context_verify_or_free(reshape_context);
205 }
206 
208  SubdivCCG *subdiv_ccg,
209  Mesh *base_mesh,
210  int top_level)
211 {
212  context_zero(reshape_context);
213 
214  reshape_context->base_mesh = base_mesh;
215 
216  reshape_context->subdiv = subdiv_ccg->subdiv;
217  reshape_context->need_free_subdiv = false;
218 
219  reshape_context->reshape.level = subdiv_ccg->level;
221  reshape_context->reshape.level);
222 
223  reshape_context->top.level = top_level;
224  reshape_context->top.grid_size = BKE_subdiv_grid_size_from_level(reshape_context->top.level);
225 
226  context_init_commoon(reshape_context);
227 
228  return context_verify_or_free(reshape_context);
229 }
230 
232  struct Object *object,
233  struct MultiresModifierData *mmd,
234  int top_level)
235 {
236  Subdiv *subdiv = multires_reshape_create_subdiv(NULL, object, mmd);
237 
239  reshape_context, object, mmd, subdiv, top_level);
240 
241  reshape_context->need_free_subdiv = true;
242 
243  return result;
244 }
245 
247  struct Object *object,
248  struct MultiresModifierData *mmd,
249  struct Subdiv *subdiv,
250  int top_level)
251 {
252  context_zero(reshape_context);
253 
254  Mesh *base_mesh = (Mesh *)object->data;
255 
256  reshape_context->mmd = mmd;
257  reshape_context->base_mesh = base_mesh;
258 
259  reshape_context->subdiv = subdiv;
260  reshape_context->need_free_subdiv = false;
261 
262  reshape_context->reshape.level = mmd->totlvl;
264  reshape_context->reshape.level);
265 
266  reshape_context->top.level = top_level;
267  reshape_context->top.grid_size = BKE_subdiv_grid_size_from_level(reshape_context->top.level);
268 
269  context_init_commoon(reshape_context);
270 
271  return context_verify_or_free(reshape_context);
272 }
273 
275 {
276  MDisps *orig_mdisps = reshape_context->orig.mdisps;
277  GridPaintMask *orig_grid_paint_masks = reshape_context->orig.grid_paint_masks;
278 
279  if (orig_mdisps == NULL && orig_grid_paint_masks == NULL) {
280  return;
281  }
282 
283  const int num_grids = reshape_context->num_grids;
284  for (int grid_index = 0; grid_index < num_grids; grid_index++) {
285  if (orig_mdisps != NULL) {
286  MDisps *orig_grid = &orig_mdisps[grid_index];
287  MEM_SAFE_FREE(orig_grid->disps);
288  }
289  if (orig_grid_paint_masks != NULL) {
290  GridPaintMask *orig_paint_mask_grid = &orig_grid_paint_masks[grid_index];
291  MEM_SAFE_FREE(orig_paint_mask_grid->data);
292  }
293  }
294 
295  MEM_SAFE_FREE(orig_mdisps);
296  MEM_SAFE_FREE(orig_grid_paint_masks);
297 
298  reshape_context->orig.mdisps = NULL;
299  reshape_context->orig.grid_paint_masks = NULL;
300 }
301 
303 {
304  if (reshape_context->need_free_subdiv) {
305  BKE_subdiv_free(reshape_context->subdiv);
306  }
307 
308  multires_reshape_free_original_grids(reshape_context);
309 
310  MEM_SAFE_FREE(reshape_context->face_start_grid_index);
311  MEM_SAFE_FREE(reshape_context->ptex_start_grid_index);
312  MEM_SAFE_FREE(reshape_context->grid_to_face_index);
313 }
314 
317 /* -------------------------------------------------------------------- */
322  int grid_index)
323 {
324  BLI_assert(grid_index >= 0);
325  BLI_assert(grid_index < reshape_context->num_grids);
326 
327  /* TODO(sergey): Optimization: when SubdivCCG is known we can calculate face index using
328  * SubdivCCG::grid_faces and SubdivCCG::faces, saving memory used by grid_to_face_index. */
329 
330  return reshape_context->grid_to_face_index[grid_index];
331 }
332 
333 int multires_reshape_grid_to_corner(const MultiresReshapeContext *reshape_context, int grid_index)
334 {
335  BLI_assert(grid_index >= 0);
336  BLI_assert(grid_index < reshape_context->num_grids);
337 
338  /* TODO(sergey): Optimization: when SubdivCCG is known we can calculate face index using
339  * SubdivCCG::grid_faces and SubdivCCG::faces, saving memory used by grid_to_face_index. */
340 
341  const int face_index = multires_reshape_grid_to_face_index(reshape_context, grid_index);
342  return grid_index - reshape_context->face_start_grid_index[face_index];
343 }
344 
345 bool multires_reshape_is_quad_face(const MultiresReshapeContext *reshape_context, int face_index)
346 {
347  const MPoly *base_poly = &reshape_context->base_mesh->mpoly[face_index];
348  return (base_poly->totloop == 4);
349 }
350 
352  int grid_index)
353 {
354  const int face_index = multires_reshape_grid_to_face_index(reshape_context, grid_index);
355  const int corner = multires_reshape_grid_to_corner(reshape_context, grid_index);
356  const bool is_quad = multires_reshape_is_quad_face(reshape_context, face_index);
357  return reshape_context->face_ptex_offset[face_index] + (is_quad ? 0 : corner);
358 }
359 
361  const GridCoord *grid_coord)
362 {
363  PTexCoord ptex_coord;
364 
365  ptex_coord.ptex_face_index = multires_reshape_grid_to_ptex_index(reshape_context,
366  grid_coord->grid_index);
367 
368  float corner_u, corner_v;
369  BKE_subdiv_grid_uv_to_ptex_face_uv(grid_coord->u, grid_coord->v, &corner_u, &corner_v);
370 
371  const int face_index = multires_reshape_grid_to_face_index(reshape_context,
372  grid_coord->grid_index);
373  const int corner = multires_reshape_grid_to_corner(reshape_context, grid_coord->grid_index);
374  if (multires_reshape_is_quad_face(reshape_context, face_index)) {
375  float grid_u, grid_v;
376  BKE_subdiv_ptex_face_uv_to_grid_uv(corner_u, corner_v, &grid_u, &grid_v);
377  BKE_subdiv_rotate_grid_to_quad(corner, grid_u, grid_v, &ptex_coord.u, &ptex_coord.v);
378  }
379  else {
380  ptex_coord.u = corner_u;
381  ptex_coord.v = corner_v;
382  }
383 
384  return ptex_coord;
385 }
386 
388  const PTexCoord *ptex_coord)
389 {
390  GridCoord grid_coord;
391 
392  const int start_grid_index = reshape_context->ptex_start_grid_index[ptex_coord->ptex_face_index];
393  const int face_index = reshape_context->grid_to_face_index[start_grid_index];
394 
395  int corner_delta;
396  if (multires_reshape_is_quad_face(reshape_context, face_index)) {
397  corner_delta = BKE_subdiv_rotate_quad_to_corner(
398  ptex_coord->u, ptex_coord->v, &grid_coord.u, &grid_coord.v);
399  }
400  else {
401  corner_delta = 0;
402  grid_coord.u = ptex_coord->u;
403  grid_coord.v = ptex_coord->v;
404  }
405  grid_coord.grid_index = start_grid_index + corner_delta;
406 
407  BKE_subdiv_ptex_face_uv_to_grid_uv(grid_coord.u, grid_coord.v, &grid_coord.u, &grid_coord.v);
408 
409  return grid_coord;
410 }
411 
413  const int face_index,
414  const int corner,
415  const float dPdu[3],
416  const float dPdv[3],
417  float r_tangent_matrix[3][3])
418 {
419  /* For a quad faces we would need to flip the tangent, since they will use
420  * use different coordinates within displacement grid compared to the ptex face. */
421  const bool is_quad = multires_reshape_is_quad_face(reshape_context, face_index);
422  const int tangent_corner = is_quad ? corner : 0;
423  BKE_multires_construct_tangent_matrix(r_tangent_matrix, dPdu, dPdv, tangent_corner);
424 }
425 
427  const MultiresReshapeContext *reshape_context, const GridCoord *grid_coord)
428 {
429  ReshapeGridElement grid_element = {NULL, NULL};
430 
431  const int grid_size = reshape_context->top.grid_size;
432  const int grid_x = lround(grid_coord->u * (grid_size - 1));
433  const int grid_y = lround(grid_coord->v * (grid_size - 1));
434  const int grid_element_index = grid_y * grid_size + grid_x;
435 
436  if (reshape_context->mdisps != NULL) {
437  MDisps *displacement_grid = &reshape_context->mdisps[grid_coord->grid_index];
438  grid_element.displacement = displacement_grid->disps[grid_element_index];
439  }
440 
441  if (reshape_context->grid_paint_masks != NULL) {
442  GridPaintMask *grid_paint_mask = &reshape_context->grid_paint_masks[grid_coord->grid_index];
443  grid_element.mask = &grid_paint_mask->data[grid_element_index];
444  }
445 
446  return grid_element;
447 }
448 
450  const MultiresReshapeContext *reshape_context, const PTexCoord *ptex_coord)
451 {
452  GridCoord grid_coord = multires_reshape_ptex_coord_to_grid(reshape_context, ptex_coord);
453  return multires_reshape_grid_element_for_grid_coord(reshape_context, &grid_coord);
454 }
455 
457  const MultiresReshapeContext *reshape_context, const GridCoord *grid_coord)
458 {
459  ReshapeConstGridElement grid_element = {{0.0f, 0.0f, 0.0f}, 0.0f};
460 
461  const MDisps *mdisps = reshape_context->orig.mdisps;
462  if (mdisps != NULL) {
463  const MDisps *displacement_grid = &mdisps[grid_coord->grid_index];
464  if (displacement_grid->disps != NULL) {
465  const int grid_size = BKE_subdiv_grid_size_from_level(displacement_grid->level);
466  const int grid_x = lround(grid_coord->u * (grid_size - 1));
467  const int grid_y = lround(grid_coord->v * (grid_size - 1));
468  const int grid_element_index = grid_y * grid_size + grid_x;
469  copy_v3_v3(grid_element.displacement, displacement_grid->disps[grid_element_index]);
470  }
471  }
472 
473  const GridPaintMask *grid_paint_masks = reshape_context->orig.grid_paint_masks;
474  if (grid_paint_masks != NULL) {
475  const GridPaintMask *paint_mask_grid = &grid_paint_masks[grid_coord->grid_index];
476  if (paint_mask_grid->data != NULL) {
477  const int grid_size = BKE_subdiv_grid_size_from_level(paint_mask_grid->level);
478  const int grid_x = lround(grid_coord->u * (grid_size - 1));
479  const int grid_y = lround(grid_coord->v * (grid_size - 1));
480  const int grid_element_index = grid_y * grid_size + grid_x;
481  grid_element.mask = paint_mask_grid->data[grid_element_index];
482  }
483  }
484 
485  return grid_element;
486 }
487 
490 /* -------------------------------------------------------------------- */
495  const GridCoord *grid_coord,
496  float r_P[3],
497  float r_tangent_matrix[3][3])
498 {
499  float dPdu[3], dPdv[3];
500  const PTexCoord ptex_coord = multires_reshape_grid_coord_to_ptex(reshape_context, grid_coord);
501  Subdiv *subdiv = reshape_context->subdiv;
503  subdiv, ptex_coord.ptex_face_index, ptex_coord.u, ptex_coord.v, r_P, dPdu, dPdv);
504 
505  const int face_index = multires_reshape_grid_to_face_index(reshape_context,
506  grid_coord->grid_index);
507  const int corner = multires_reshape_grid_to_corner(reshape_context, grid_coord->grid_index);
509  reshape_context, face_index, corner, dPdu, dPdv, r_tangent_matrix);
510 }
511 
514 /* -------------------------------------------------------------------- */
518 static void allocate_displacement_grid(MDisps *displacement_grid, const int level)
519 {
520  const int grid_size = BKE_subdiv_grid_size_from_level(level);
521  const int grid_area = grid_size * grid_size;
522  float(*disps)[3] = MEM_calloc_arrayN(grid_area, sizeof(float[3]), "multires disps");
523  if (displacement_grid->disps != NULL) {
524  MEM_freeN(displacement_grid->disps);
525  }
526  /* TODO(sergey): Preserve data on the old level. */
527  displacement_grid->disps = disps;
528  displacement_grid->totdisp = grid_area;
529  displacement_grid->level = level;
530 }
531 
532 static void ensure_displacement_grid(MDisps *displacement_grid, const int level)
533 {
534  if (displacement_grid->disps != NULL && displacement_grid->level >= level) {
535  return;
536  }
537  allocate_displacement_grid(displacement_grid, level);
538 }
539 
540 static void ensure_displacement_grids(Mesh *mesh, const int grid_level)
541 {
542  const int num_grids = mesh->totloop;
544  for (int grid_index = 0; grid_index < num_grids; grid_index++) {
545  ensure_displacement_grid(&mdisps[grid_index], grid_level);
546  }
547 }
548 
549 static void ensure_mask_grids(Mesh *mesh, const int level)
550 {
552  if (grid_paint_masks == NULL) {
553  return;
554  }
555  const int num_grids = mesh->totloop;
556  const int grid_size = BKE_subdiv_grid_size_from_level(level);
557  const int grid_area = grid_size * grid_size;
558  for (int grid_index = 0; grid_index < num_grids; grid_index++) {
559  GridPaintMask *grid_paint_mask = &grid_paint_masks[grid_index];
560  if (grid_paint_mask->level >= level) {
561  continue;
562  }
563  grid_paint_mask->level = level;
564  if (grid_paint_mask->data) {
565  MEM_freeN(grid_paint_mask->data);
566  }
567  /* TODO(sergey): Preserve data on the old level. */
568  grid_paint_mask->data = MEM_calloc_arrayN(grid_area, sizeof(float), "gpm.data");
569  }
570 }
571 
572 void multires_reshape_ensure_grids(Mesh *mesh, const int level)
573 {
575  ensure_mask_grids(mesh, level);
576 }
577 
580 /* -------------------------------------------------------------------- */
585 {
586  const MDisps *mdisps = reshape_context->mdisps;
587  const GridPaintMask *grid_paint_masks = reshape_context->grid_paint_masks;
588 
589  MDisps *orig_mdisps = MEM_dupallocN(mdisps);
590  GridPaintMask *orig_grid_paint_masks = NULL;
591  if (grid_paint_masks != NULL) {
592  orig_grid_paint_masks = MEM_dupallocN(grid_paint_masks);
593  }
594 
595  const int num_grids = reshape_context->num_grids;
596  for (int grid_index = 0; grid_index < num_grids; grid_index++) {
597  MDisps *orig_grid = &orig_mdisps[grid_index];
598  /* Ignore possibly invalid/non-allocated original grids. They will be replaced with 0 original
599  * data when accessed during reshape process.
600  * Reshape process will ensure all grids are on top level, but that happens on separate set of
601  * grids which eventually replaces original one. */
602  if (orig_grid->disps != NULL) {
603  orig_grid->disps = MEM_dupallocN(orig_grid->disps);
604  }
605  if (orig_grid_paint_masks != NULL) {
606  GridPaintMask *orig_paint_mask_grid = &orig_grid_paint_masks[grid_index];
607  if (orig_paint_mask_grid->data != NULL) {
608  orig_paint_mask_grid->data = MEM_dupallocN(orig_paint_mask_grid->data);
609  }
610  }
611  }
612 
613  reshape_context->orig.mdisps = orig_mdisps;
614  reshape_context->orig.grid_paint_masks = orig_grid_paint_masks;
615 }
616 
618  const GridCoord *grid_coord,
619  void *userdata_v);
620 
623 
626 
630 
631 static void foreach_grid_face_coordinate_task(void *__restrict userdata_v,
632  const int face_index,
633  const TaskParallelTLS *__restrict UNUSED(tls))
634 {
635  ForeachGridCoordinateTaskData *data = userdata_v;
636 
637  const MultiresReshapeContext *reshape_context = data->reshape_context;
638 
639  const Mesh *base_mesh = data->reshape_context->base_mesh;
640  const MPoly *mpoly = base_mesh->mpoly;
641  const int grid_size = data->grid_size;
642  const float grid_size_1_inv = 1.0f / (((float)grid_size) - 1.0f);
643 
644  const int num_corners = mpoly[face_index].totloop;
645  int grid_index = reshape_context->face_start_grid_index[face_index];
646  for (int corner = 0; corner < num_corners; ++corner, ++grid_index) {
647  for (int y = 0; y < grid_size; ++y) {
648  const float v = (float)y * grid_size_1_inv;
649  for (int x = 0; x < grid_size; ++x) {
650  const float u = (float)x * grid_size_1_inv;
651 
652  GridCoord grid_coord;
653  grid_coord.grid_index = grid_index;
654  grid_coord.u = u;
655  grid_coord.v = v;
656 
657  data->callback(data->reshape_context, &grid_coord, data->callback_userdata_v);
658  }
659  }
660  }
661 }
662 
663 /* Run given callback for every grid coordinate at a given level. */
664 static void foreach_grid_coordinate(const MultiresReshapeContext *reshape_context,
665  const int level,
667  void *userdata_v)
668 {
670  data.reshape_context = reshape_context;
671  data.grid_size = BKE_subdiv_grid_size_from_level(level);
672  data.grid_size_1_inv = 1.0f / (((float)data.grid_size) - 1.0f);
673  data.callback = callback;
674  data.callback_userdata_v = userdata_v;
675 
676  TaskParallelSettings parallel_range_settings;
677  BLI_parallel_range_settings_defaults(&parallel_range_settings);
678  parallel_range_settings.min_iter_per_thread = 1;
679 
680  const Mesh *base_mesh = reshape_context->base_mesh;
681  const int num_faces = base_mesh->totpoly;
683  0, num_faces, &data, foreach_grid_face_coordinate_task, &parallel_range_settings);
684 }
685 
687  const MultiresReshapeContext *reshape_context,
688  const GridCoord *grid_coord,
689  void *UNUSED(userdata_v))
690 {
691  float P[3];
692  float tangent_matrix[3][3];
693  multires_reshape_evaluate_limit_at_grid(reshape_context, grid_coord, P, tangent_matrix);
694 
695  float inv_tangent_matrix[3][3];
696  invert_m3_m3(inv_tangent_matrix, tangent_matrix);
697 
699  grid_coord);
700 
701  float D[3];
702  sub_v3_v3v3(D, grid_element.displacement, P);
703 
704  float tangent_D[3];
705  mul_v3_m3v3(tangent_D, inv_tangent_matrix, D);
706 
707  copy_v3_v3(grid_element.displacement, tangent_D);
708 }
709 
711  const MultiresReshapeContext *reshape_context)
712 {
713  foreach_grid_coordinate(reshape_context,
714  reshape_context->top.level,
716  NULL);
717 }
718 
721 /* -------------------------------------------------------------------- */
725 /* TODO(sergey): Make foreach_grid_coordinate more accessible and move this functionality to
726  * own file. */
727 
728 static void assign_final_coords_from_mdisps(const MultiresReshapeContext *reshape_context,
729  const GridCoord *grid_coord,
730  void *UNUSED(userdata_v))
731 {
732  float P[3];
733  float tangent_matrix[3][3];
734  multires_reshape_evaluate_limit_at_grid(reshape_context, grid_coord, P, tangent_matrix);
735 
737  grid_coord);
738  float D[3];
739  mul_v3_m3v3(D, tangent_matrix, grid_element.displacement);
740 
741  add_v3_v3v3(grid_element.displacement, P, D);
742 }
743 
745  const MultiresReshapeContext *reshape_context)
746 {
748  reshape_context, reshape_context->top.level, assign_final_coords_from_mdisps, NULL);
749 }
750 
752  const GridCoord *grid_coord,
753  void *UNUSED(userdata_v))
754 {
755  float P[3];
756  float tangent_matrix[3][3];
757  multires_reshape_evaluate_limit_at_grid(reshape_context, grid_coord, P, tangent_matrix);
758 
759  const ReshapeConstGridElement orig_grid_element =
760  multires_reshape_orig_grid_element_for_grid_coord(reshape_context, grid_coord);
761 
762  float D[3];
763  mul_v3_m3v3(D, tangent_matrix, orig_grid_element.displacement);
764 
766  grid_coord);
767  add_v3_v3v3(grid_element.displacement, P, D);
768 
769  if (grid_element.mask != NULL) {
770  *grid_element.mask = orig_grid_element.mask;
771  }
772 }
773 
775  const MultiresReshapeContext *reshape_context)
776 {
778  reshape_context, reshape_context->top.level, assign_final_elements_from_orig_mdisps, NULL);
779 }
780 
typedef float(TangentPoint)[2]
CustomData interface, see also DNA_customdata_types.h.
const CustomData_MeshMasks CD_MASK_BAREMESH
Definition: customdata.cc:2051
void * CustomData_get_layer(const struct CustomData *data, int type)
struct Mesh * mesh_get_eval_deform(struct Depsgraph *depsgraph, const struct Scene *scene, struct Object *ob, const struct CustomData_MeshMasks *dataMask)
BLI_INLINE void BKE_multires_construct_tangent_matrix(float tangent_matrix[3][3], const float dPdu[3], const float dPdv[3], int corner)
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_subdiv_ptex_face_uv_to_grid_uv(float ptex_u, float ptex_v, float *r_grid_u, float *r_grid_v)
Definition: subdiv_inline.h:15
BLI_INLINE int BKE_subdiv_grid_size_from_level(int level)
Definition: subdiv_inline.h:33
BLI_INLINE void BKE_subdiv_rotate_grid_to_quad(int corner, float grid_u, float grid_v, float *r_quad_u, float *r_quad_v)
Definition: subdiv_inline.h:68
void BKE_subdiv_free(Subdiv *subdiv)
Definition: subdiv.c:184
BLI_INLINE void BKE_subdiv_grid_uv_to_ptex_face_uv(float grid_u, float grid_v, float *r_ptex_u, float *r_ptex_v)
Definition: subdiv_inline.h:24
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:209
BLI_INLINE int BKE_subdiv_rotate_quad_to_corner(float quad_u, float quad_v, float *r_corner_u, float *r_corner_v)
Definition: subdiv_inline.h:38
@ SUBDIV_EVALUATOR_TYPE_CPU
bool BKE_subdiv_eval_begin_from_mesh(struct Subdiv *subdiv, const struct Mesh *mesh, const float(*coarse_vertex_cos)[3], eSubdivEvaluatorType evaluator_type, struct OpenSubdiv_EvaluatorCache *evaluator_cache)
void BKE_subdiv_eval_limit_point_and_derivatives(struct Subdiv *subdiv, int ptex_face_index, float u, float v, float r_P[3], float r_dPdu[3], float r_dPdv[3])
Definition: subdiv_eval.c:286
#define BLI_assert(a)
Definition: BLI_assert.h:46
bool invert_m3_m3(float R[3][3], const float A[3][3])
Definition: math_matrix.c:1180
void mul_v3_m3v3(float r[3], const float M[3][3], const float a[3])
Definition: math_matrix.c:897
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(int start, int stop, void *userdata, TaskParallelRangeFunc func, const TaskParallelSettings *settings)
Definition: task_range.cc:94
BLI_INLINE void BLI_parallel_range_settings_defaults(TaskParallelSettings *settings)
Definition: BLI_task.h:293
#define UNUSED(x)
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:35
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
SyclQueue void void size_t num_bytes void
void *(* MEM_malloc_arrayN)(size_t len, size_t size, const char *str)
Definition: mallocn.c:34
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_dupallocN)(const void *vmemh)
Definition: mallocn.c:28
void *(* MEM_calloc_arrayN)(size_t len, size_t size, const char *str)
Definition: mallocn.c:32
static float P(float k)
Definition: math_interp.c:25
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]
CustomData vdata
int totpoly
int totloop
struct MPoly * mpoly
CustomData ldata
struct MultiresReshapeContext::@101 orig
struct GridPaintMask * grid_paint_masks
struct MultiresModifierData * mmd
struct MultiresReshapeContext::@99 reshape
struct MDisps * mdisps
struct Object * object
const float * cd_vertex_crease
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:13