Blender  V2.93
multires_reshape_smooth.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_meshdata_types.h"
30 #include "DNA_modifier_types.h"
31 
32 #include "BLI_bitmap.h"
33 #include "BLI_math_vector.h"
34 #include "BLI_task.h"
35 #include "BLI_utildefines.h"
36 
37 #include "BKE_customdata.h"
38 #include "BKE_multires.h"
39 #include "BKE_subdiv.h"
40 #include "BKE_subdiv_eval.h"
41 #include "BKE_subdiv_foreach.h"
42 #include "BKE_subdiv_mesh.h"
43 
47 
48 #include "atomic_ops.h"
49 #include "subdiv_converter.h"
50 
51 /* -------------------------------------------------------------------- */
55 /* Surface refers to a simplified and lower-memory footprint representation of the limit surface.
56  *
57  * Used to store pre-calculated information which is expensive or impossible to evaluate when
58  * traversing the final limit surface. */
59 
60 typedef struct SurfacePoint {
61  float P[3];
62  float tangent_matrix[3][3];
64 
65 typedef struct SurfaceGrid {
68 
69 /* Geometry elements which are used to simplify creation of topology refiner at the sculpt level.
70  * Contains a limited subset of information needed to construct topology refiner. */
71 
72 typedef struct Vertex {
73  /* All grid coordinates which the vertex corresponding to.
74  * For a vertices which are created from inner points of grids there is always one coordinate. */
77 
80 
81 typedef struct Corner {
82  const Vertex *vertex;
85 
86 typedef struct Face {
89 } Face;
90 
91 typedef struct Edge {
92  int v1;
93  int v2;
94 
95  float sharpness;
96 } Edge;
97 
98 /* Storage of data which is linearly interpolated from the reshape level to the top level. */
99 
100 typedef struct LinearGridElement {
101  float mask;
103 
104 typedef struct LinearGrid {
107 
108 typedef struct LinearGrids {
110  int level;
111 
112  /* Cached size for the grid, for faster lookup. */
114 
115  /* Indexed by grid index. */
117 
118  /* Elements for all grids are allocated in a single array, for the allocation performance. */
121 
122 /* Context which holds all information eeded during propagation and smoothing. */
123 
126 
127  /* Geometry at a reshape multires level. */
128  struct {
131 
132  /* Maximum number of edges which might be stored in the edges array.
133  * Is calculated based on the number of edges in the base mesh and the subdivision level. */
135 
136  /* Sparse storage of edges. Will only include edges which have non-zero sharpness.
137  *
138  * NOTE: Different type from others to be able to easier use atomic ops. */
139  size_t num_edges;
141 
144 
148 
149  /* Grids of data which is linearly interpolated between grid elements at the reshape level.
150  * The data is actually stored as a delta, which is then to be added to the higher levels. */
152 
153  /* Index i of this map indicates that base edge i is adjacent to at least one face. */
155 
156  /* Subdivision surface created for geometry at a reshape level. */
158 
159  /* Limit surface of the base mesh with original sculpt level details on it, subdivided up to the
160  * top level.
161  * Is used as a base point to calculate how much displacement has been made in the sculpt mode.
162  *
163  * NOTE: Referring to sculpt as it is the main user of this functionality and it is clear to
164  * understand what it actually means in a concrete example. This is a generic code which is also
165  * used by Subdivide operation, but the idea is exactly the same as propagation in the sculpt
166  * mode. */
168 
169  /* Defines how displacement is interpolated on the higher levels (for example, whether
170  * displacement is smoothed in Catmull-Clark mode or interpolated linearly preserving sharp edges
171  * of the current sculpt level).
172  *
173  * NOTE: Uses same enumerator type as Subdivide operator, since the values are the same and
174  * decoupling type just adds extra headache to convert one enumerator to another. */
177 
180 /* -------------------------------------------------------------------- */
184 static void linear_grids_init(LinearGrids *linear_grids)
185 {
186  linear_grids->num_grids = 0;
187  linear_grids->level = 0;
188 
189  linear_grids->grids = NULL;
190  linear_grids->elements_storage = NULL;
191 }
192 
193 static void linear_grids_allocate(LinearGrids *linear_grids, int num_grids, int level)
194 {
195  const size_t grid_size = BKE_subdiv_grid_size_from_level(level);
196  const size_t grid_area = grid_size * grid_size;
197  const size_t num_grid_elements = num_grids * grid_area;
198 
199  linear_grids->num_grids = num_grids;
200  linear_grids->level = level;
201  linear_grids->grid_size = grid_size;
202 
203  linear_grids->grids = MEM_malloc_arrayN(num_grids, sizeof(LinearGrid), "linear grids");
204  linear_grids->elements_storage = MEM_calloc_arrayN(
205  num_grid_elements, sizeof(LinearGridElement), "linear elements storage");
206 
207  for (int i = 0; i < num_grids; ++i) {
208  const size_t element_offset = grid_area * i;
209  linear_grids->grids[i].elements = &linear_grids->elements_storage[element_offset];
210  }
211 }
212 
214  const GridCoord *grid_coord)
215 {
216  BLI_assert(grid_coord->grid_index >= 0);
217  BLI_assert(grid_coord->grid_index < linear_grids->num_grids);
218 
219  const int grid_size = linear_grids->grid_size;
220 
221  const int grid_x = lround(grid_coord->u * (grid_size - 1));
222  const int grid_y = lround(grid_coord->v * (grid_size - 1));
223  const int grid_element_index = grid_y * grid_size + grid_x;
224 
225  LinearGrid *grid = &linear_grids->grids[grid_coord->grid_index];
226  return &grid->elements[grid_element_index];
227 }
228 
229 static void linear_grids_free(LinearGrids *linear_grids)
230 {
231  MEM_SAFE_FREE(linear_grids->grids);
232  MEM_SAFE_FREE(linear_grids->elements_storage);
233 }
234 
235 static void linear_grid_element_init(LinearGridElement *linear_grid_element)
236 {
237  linear_grid_element->mask = 0.0f;
238 }
239 
240 /* result = a - b. */
242  const LinearGridElement *a,
243  const LinearGridElement *b)
244 {
245  result->mask = a->mask - b->mask;
246 }
247 
249  const LinearGridElement elements[4],
250  const float weights[4])
251 {
252  result->mask = elements[0].mask * weights[0] + elements[1].mask * weights[1] +
253  elements[2].mask * weights[2] + elements[3].mask * weights[3];
254 }
255 
258 /* -------------------------------------------------------------------- */
262 static void base_surface_grids_allocate(MultiresReshapeSmoothContext *reshape_smooth_context)
263 {
264  const MultiresReshapeContext *reshape_context = reshape_smooth_context->reshape_context;
265 
266  const int num_grids = reshape_context->num_grids;
267  const int grid_size = reshape_context->top.grid_size;
268  const int grid_area = grid_size * grid_size;
269 
270  SurfaceGrid *surface_grid = MEM_malloc_arrayN(num_grids, sizeof(SurfaceGrid), "delta grids");
271 
272  for (int grid_index = 0; grid_index < num_grids; ++grid_index) {
273  surface_grid[grid_index].points = MEM_calloc_arrayN(
274  sizeof(SurfacePoint), grid_area, "delta grid displacement");
275  }
276 
277  reshape_smooth_context->base_surface_grids = surface_grid;
278 }
279 
280 static void base_surface_grids_free(MultiresReshapeSmoothContext *reshape_smooth_context)
281 {
282  if (reshape_smooth_context->base_surface_grids == NULL) {
283  return;
284  }
285 
286  const MultiresReshapeContext *reshape_context = reshape_smooth_context->reshape_context;
287 
288  const int num_grids = reshape_context->num_grids;
289  for (int grid_index = 0; grid_index < num_grids; ++grid_index) {
290  MEM_freeN(reshape_smooth_context->base_surface_grids[grid_index].points);
291  }
292  MEM_freeN(reshape_smooth_context->base_surface_grids);
293 }
294 
296  const MultiresReshapeSmoothContext *reshape_smooth_context, const GridCoord *grid_coord)
297 {
298  const MultiresReshapeContext *reshape_context = reshape_smooth_context->reshape_context;
299 
300  const int grid_index = grid_coord->grid_index;
301  const int grid_size = reshape_context->top.grid_size;
302  const int grid_x = lround(grid_coord->u * (grid_size - 1));
303  const int grid_y = lround(grid_coord->v * (grid_size - 1));
304  const int grid_element_index = grid_y * grid_size + grid_x;
305 
306  SurfaceGrid *surface_grid = &reshape_smooth_context->base_surface_grids[grid_index];
307  return &surface_grid->points[grid_element_index];
308 }
309 
310 static void base_surface_grids_write(const MultiresReshapeSmoothContext *reshape_smooth_context,
311  const GridCoord *grid_coord,
312  float P[3],
313  float tangent_matrix[3][3])
314 {
315  SurfacePoint *point = base_surface_grids_read(reshape_smooth_context, grid_coord);
316  copy_v3_v3(point->P, P);
317  copy_m3_m3(point->tangent_matrix, tangent_matrix);
318 }
319 
322 /* -------------------------------------------------------------------- */
327  const MultiresReshapeSmoothContext *reshape_smooth_context,
328  const PTexCoord *ptex_coord,
329  const GridCoord *grid_coord,
330  void *userdata_v);
331 
334 
337 
341 
342 /* Find grid index which given face was created for. */
343 static int get_face_grid_index(const MultiresReshapeSmoothContext *reshape_smooth_context,
344  const Face *face)
345 {
346  const Corner *first_corner = &reshape_smooth_context->geometry.corners[face->start_corner_index];
347  const int grid_index = first_corner->grid_index;
348 
349 #ifndef NDEBUG
350  for (int face_corner = 0; face_corner < face->num_corners; ++face_corner) {
351  const int corner_index = face->start_corner_index + face_corner;
352  const Corner *corner = &reshape_smooth_context->geometry.corners[corner_index];
353  BLI_assert(corner->grid_index == grid_index);
354  }
355 #endif
356 
357  return grid_index;
358 }
359 
360 static GridCoord *vertex_grid_coord_with_grid_index(const Vertex *vertex, const int grid_index)
361 {
362  for (int i = 0; i < vertex->num_grid_coords; ++i) {
363  if (vertex->grid_coords[i].grid_index == grid_index) {
364  return &vertex->grid_coords[i];
365  }
366  }
367  return NULL;
368 }
369 
370 /* Get grid coordinates which correspond to corners of the given face.
371  * All the grid coordinates will be from the same grid index. */
373  const MultiresReshapeSmoothContext *reshape_smooth_context,
374  const Face *face,
375  const GridCoord *grid_coords[])
376 {
377  BLI_assert(face->num_corners == 4);
378 
379  const int grid_index = get_face_grid_index(reshape_smooth_context, face);
380  BLI_assert(grid_index != -1);
381 
382  for (int i = 0; i < face->num_corners; ++i) {
383  const int corner_index = face->start_corner_index + i;
384  const Corner *corner = &reshape_smooth_context->geometry.corners[corner_index];
385  grid_coords[i] = vertex_grid_coord_with_grid_index(corner->vertex, grid_index);
386  BLI_assert(grid_coords[i] != NULL);
387  }
388 }
389 
390 static float lerp(float t, float a, float b)
391 {
392  return (a + t * (b - a));
393 }
394 
396  const GridCoord *face_grid_coords[4],
397  const float u,
398  const float v)
399 {
400  /*
401  * v
402  * ^
403  * | (3) -------- (2)
404  * | | |
405  * | | |
406  * | | |
407  * | | |
408  * | (0) -------- (1)
409  * *--------------------------> u
410  */
411 
412  const float u01 = lerp(u, face_grid_coords[0]->u, face_grid_coords[1]->u);
413  const float u32 = lerp(u, face_grid_coords[3]->u, face_grid_coords[2]->u);
414 
415  const float v03 = lerp(v, face_grid_coords[0]->v, face_grid_coords[3]->v);
416  const float v12 = lerp(v, face_grid_coords[1]->v, face_grid_coords[2]->v);
417 
418  result->grid_index = face_grid_coords[0]->grid_index;
419  result->u = lerp(v, u01, u32);
420  result->v = lerp(u, v03, v12);
421 }
422 
423 static void foreach_toplevel_grid_coord_task(void *__restrict userdata_v,
424  const int face_index,
425  const TaskParallelTLS *__restrict UNUSED(tls))
426 {
427  ForeachHighLevelCoordTaskData *data = userdata_v;
428 
429  const MultiresReshapeSmoothContext *reshape_smooth_context = data->reshape_smooth_context;
430  const int inner_grid_size = data->inner_grid_size;
431  const float inner_grid_size_1_inv = data->inner_grid_size_1_inv;
432 
433  const Face *face = &reshape_smooth_context->geometry.faces[face_index];
434  const GridCoord *face_grid_coords[4];
435  grid_coords_from_face_vertices(reshape_smooth_context, face, face_grid_coords);
436 
437  for (int y = 0; y < inner_grid_size; ++y) {
438  const float ptex_v = (float)y * inner_grid_size_1_inv;
439  for (int x = 0; x < inner_grid_size; ++x) {
440  const float ptex_u = (float)x * inner_grid_size_1_inv;
441 
442  PTexCoord ptex_coord;
443  ptex_coord.ptex_face_index = face_index;
444  ptex_coord.u = ptex_u;
445  ptex_coord.v = ptex_v;
446 
447  GridCoord grid_coord;
448  interpolate_grid_coord(&grid_coord, face_grid_coords, ptex_u, ptex_v);
449 
450  data->callback(reshape_smooth_context, &ptex_coord, &grid_coord, data->callback_userdata_v);
451  }
452  }
453 }
454 
455 static void foreach_toplevel_grid_coord(const MultiresReshapeSmoothContext *reshape_smooth_context,
457  void *callback_userdata_v)
458 {
459  const MultiresReshapeContext *reshape_context = reshape_smooth_context->reshape_context;
460  const int level_difference = (reshape_context->top.level - reshape_context->reshape.level);
461 
463  data.reshape_smooth_context = reshape_smooth_context;
464  data.inner_grid_size = (1 << level_difference) + 1;
465  data.inner_grid_size_1_inv = 1.0f / (float)(data.inner_grid_size - 1);
466  data.callback = callback;
467  data.callback_userdata_v = callback_userdata_v;
468 
469  TaskParallelSettings parallel_range_settings;
470  BLI_parallel_range_settings_defaults(&parallel_range_settings);
471  parallel_range_settings.min_iter_per_thread = 1;
472 
473  const int num_faces = reshape_smooth_context->geometry.num_faces;
475  0, num_faces, &data, foreach_toplevel_grid_coord_task, &parallel_range_settings);
476 }
477 
480 /* -------------------------------------------------------------------- */
487 static int get_reshape_level_resolution(const MultiresReshapeContext *reshape_context)
488 {
489  return (1 << reshape_context->reshape.level) + 1;
490 }
491 
492 /* Get crease which will be used for communication to OpenSubdiv topology.
493  * Note that simple subdivision treats all base edges as infinitely sharp. */
495  const MultiresReshapeSmoothContext *reshape_smooth_context, const MEdge *base_edge)
496 {
497  if (ELEM(reshape_smooth_context->smoothing_type,
500  return 255;
501  }
502  return base_edge->crease;
503 }
504 
505 static void context_init(MultiresReshapeSmoothContext *reshape_smooth_context,
506  const MultiresReshapeContext *reshape_context,
507  const eMultiresSubdivideModeType mode)
508 {
509  reshape_smooth_context->reshape_context = reshape_context;
510 
511  reshape_smooth_context->geometry.num_vertices = 0;
512  reshape_smooth_context->geometry.vertices = NULL;
513 
514  reshape_smooth_context->geometry.max_edges = 0;
515  reshape_smooth_context->geometry.num_edges = 0;
516  reshape_smooth_context->geometry.edges = NULL;
517 
518  reshape_smooth_context->geometry.num_corners = 0;
519  reshape_smooth_context->geometry.corners = NULL;
520 
521  reshape_smooth_context->geometry.num_faces = 0;
522  reshape_smooth_context->geometry.faces = NULL;
523 
524  linear_grids_init(&reshape_smooth_context->linear_delta_grids);
525 
526  reshape_smooth_context->non_loose_base_edge_map = NULL;
527  reshape_smooth_context->reshape_subdiv = NULL;
528  reshape_smooth_context->base_surface_grids = NULL;
529 
530  reshape_smooth_context->smoothing_type = mode;
531 }
532 
533 static void context_free_geometry(MultiresReshapeSmoothContext *reshape_smooth_context)
534 {
535  if (reshape_smooth_context->geometry.vertices != NULL) {
536  for (int i = 0; i < reshape_smooth_context->geometry.num_vertices; ++i) {
537  MEM_SAFE_FREE(reshape_smooth_context->geometry.vertices[i].grid_coords);
538  }
539  }
540  MEM_SAFE_FREE(reshape_smooth_context->geometry.vertices);
541  MEM_SAFE_FREE(reshape_smooth_context->geometry.corners);
542  MEM_SAFE_FREE(reshape_smooth_context->geometry.faces);
543  MEM_SAFE_FREE(reshape_smooth_context->geometry.edges);
544 
545  linear_grids_free(&reshape_smooth_context->linear_delta_grids);
546 }
547 
548 static void context_free_subdiv(MultiresReshapeSmoothContext *reshape_smooth_context)
549 {
550  if (reshape_smooth_context->reshape_subdiv == NULL) {
551  return;
552  }
553  BKE_subdiv_free(reshape_smooth_context->reshape_subdiv);
554 }
555 
556 static void context_free(MultiresReshapeSmoothContext *reshape_smooth_context)
557 {
558  MEM_freeN(reshape_smooth_context->non_loose_base_edge_map);
559 
560  context_free_geometry(reshape_smooth_context);
561  context_free_subdiv(reshape_smooth_context);
562  base_surface_grids_free(reshape_smooth_context);
563 }
564 
565 static bool foreach_topology_info(const SubdivForeachContext *foreach_context,
566  const int num_vertices,
567  const int num_edges,
568  const int num_loops,
569  const int num_polygons)
570 {
571  MultiresReshapeSmoothContext *reshape_smooth_context = foreach_context->user_data;
572  const int max_edges = reshape_smooth_context->smoothing_type == MULTIRES_SUBDIVIDE_LINEAR ?
573  num_edges :
574  reshape_smooth_context->geometry.max_edges;
575 
576  /* NOTE: Calloc so the counters are re-set to 0 "for free". */
577  reshape_smooth_context->geometry.num_vertices = num_vertices;
578  reshape_smooth_context->geometry.vertices = MEM_calloc_arrayN(
579  sizeof(Vertex), num_vertices, "smooth vertices");
580 
581  reshape_smooth_context->geometry.max_edges = max_edges;
582  reshape_smooth_context->geometry.edges = MEM_malloc_arrayN(
583  sizeof(Edge), max_edges, "smooth edges");
584 
585  reshape_smooth_context->geometry.num_corners = num_loops;
586  reshape_smooth_context->geometry.corners = MEM_malloc_arrayN(
587  sizeof(Corner), num_loops, "smooth corners");
588 
589  reshape_smooth_context->geometry.num_faces = num_polygons;
590  reshape_smooth_context->geometry.faces = MEM_malloc_arrayN(
591  sizeof(Face), num_polygons, "smooth faces");
592 
593  return true;
594 }
595 
596 static void foreach_single_vertex(const SubdivForeachContext *foreach_context,
597  const GridCoord *grid_coord,
598  const int subdiv_vertex_index)
599 {
600  const MultiresReshapeSmoothContext *reshape_smooth_context = foreach_context->user_data;
601 
602  BLI_assert(subdiv_vertex_index < reshape_smooth_context->geometry.num_vertices);
603 
604  Vertex *vertex = &reshape_smooth_context->geometry.vertices[subdiv_vertex_index];
605 
606  vertex->grid_coords = MEM_reallocN(vertex->grid_coords,
607  sizeof(Vertex) * (vertex->num_grid_coords + 1));
608  vertex->grid_coords[vertex->num_grid_coords] = *grid_coord;
609  ++vertex->num_grid_coords;
610 }
611 
612 /* TODO(sergey): De-duplicate with similar function in multires_reshape_vertcos.c */
613 static void foreach_vertex(const SubdivForeachContext *foreach_context,
614  const PTexCoord *ptex_coord,
615  const int subdiv_vertex_index)
616 {
617  const MultiresReshapeSmoothContext *reshape_smooth_context = foreach_context->user_data;
618  const MultiresReshapeContext *reshape_context = reshape_smooth_context->reshape_context;
619 
620  const GridCoord grid_coord = multires_reshape_ptex_coord_to_grid(reshape_context, ptex_coord);
621  const int face_index = multires_reshape_grid_to_face_index(reshape_context,
622  grid_coord.grid_index);
623 
624  const Mesh *base_mesh = reshape_context->base_mesh;
625  const MPoly *base_poly = &base_mesh->mpoly[face_index];
626  const int num_corners = base_poly->totloop;
627  const int start_grid_index = reshape_context->face_start_grid_index[face_index];
628  const int corner = grid_coord.grid_index - start_grid_index;
629 
630  if (grid_coord.u == 0.0f && grid_coord.v == 0.0f) {
631  for (int current_corner = 0; current_corner < num_corners; ++current_corner) {
632  GridCoord corner_grid_coord = grid_coord;
633  corner_grid_coord.grid_index = start_grid_index + current_corner;
634  foreach_single_vertex(foreach_context, &corner_grid_coord, subdiv_vertex_index);
635  }
636  return;
637  }
638 
639  foreach_single_vertex(foreach_context, &grid_coord, subdiv_vertex_index);
640 
641  if (grid_coord.u == 0.0f) {
642  GridCoord prev_grid_coord;
643  prev_grid_coord.grid_index = start_grid_index + ((corner + num_corners - 1) % num_corners);
644  prev_grid_coord.u = grid_coord.v;
645  prev_grid_coord.v = 0.0f;
646 
647  foreach_single_vertex(foreach_context, &prev_grid_coord, subdiv_vertex_index);
648  }
649 
650  if (grid_coord.v == 0.0f) {
651  GridCoord next_grid_coord;
652  next_grid_coord.grid_index = start_grid_index + ((corner + 1) % num_corners);
653  next_grid_coord.u = 0.0f;
654  next_grid_coord.v = grid_coord.u;
655 
656  foreach_single_vertex(foreach_context, &next_grid_coord, subdiv_vertex_index);
657  }
658 }
659 
660 static void foreach_vertex_inner(const struct SubdivForeachContext *foreach_context,
661  void *UNUSED(tls),
662  const int ptex_face_index,
663  const float ptex_face_u,
664  const float ptex_face_v,
665  const int UNUSED(coarse_poly_index),
666  const int UNUSED(coarse_corner),
667  const int subdiv_vertex_index)
668 {
669  const PTexCoord ptex_coord = {
670  .ptex_face_index = ptex_face_index,
671  .u = ptex_face_u,
672  .v = ptex_face_v,
673  };
674  foreach_vertex(foreach_context, &ptex_coord, subdiv_vertex_index);
675 }
676 
677 static void foreach_vertex_every_corner(const struct SubdivForeachContext *foreach_context,
678  void *UNUSED(tls_v),
679  const int ptex_face_index,
680  const float ptex_face_u,
681  const float ptex_face_v,
682  const int UNUSED(coarse_vertex_index),
683  const int UNUSED(coarse_face_index),
684  const int UNUSED(coarse_face_corner),
685  const int subdiv_vertex_index)
686 {
687  const PTexCoord ptex_coord = {
688  .ptex_face_index = ptex_face_index,
689  .u = ptex_face_u,
690  .v = ptex_face_v,
691  };
692  foreach_vertex(foreach_context, &ptex_coord, subdiv_vertex_index);
693 }
694 
695 static void foreach_vertex_every_edge(const struct SubdivForeachContext *foreach_context,
696  void *UNUSED(tls_v),
697  const int ptex_face_index,
698  const float ptex_face_u,
699  const float ptex_face_v,
700  const int UNUSED(coarse_edge_index),
701  const int UNUSED(coarse_face_index),
702  const int UNUSED(coarse_face_corner),
703  const int subdiv_vertex_index)
704 {
705  const PTexCoord ptex_coord = {
706  .ptex_face_index = ptex_face_index,
707  .u = ptex_face_u,
708  .v = ptex_face_v,
709  };
710  foreach_vertex(foreach_context, &ptex_coord, subdiv_vertex_index);
711 }
712 
713 static void foreach_loop(const struct SubdivForeachContext *foreach_context,
714  void *UNUSED(tls),
715  const int UNUSED(ptex_face_index),
716  const float UNUSED(ptex_face_u),
717  const float UNUSED(ptex_face_v),
718  const int UNUSED(coarse_loop_index),
719  const int coarse_poly_index,
720  const int coarse_corner,
721  const int subdiv_loop_index,
722  const int subdiv_vertex_index,
723  const int UNUSED(subdiv_edge_index))
724 {
725  MultiresReshapeSmoothContext *reshape_smooth_context = foreach_context->user_data;
726  const MultiresReshapeContext *reshape_context = reshape_smooth_context->reshape_context;
727 
728  BLI_assert(subdiv_loop_index < reshape_smooth_context->geometry.num_corners);
729 
730  Corner *corner = &reshape_smooth_context->geometry.corners[subdiv_loop_index];
731  corner->vertex = &reshape_smooth_context->geometry.vertices[subdiv_vertex_index];
732 
733  const int first_grid_index = reshape_context->face_start_grid_index[coarse_poly_index];
734  corner->grid_index = first_grid_index + coarse_corner;
735 }
736 
737 static void foreach_poly(const SubdivForeachContext *foreach_context,
738  void *UNUSED(tls),
739  const int UNUSED(coarse_poly_index),
740  const int subdiv_poly_index,
741  const int start_loop_index,
742  const int num_loops)
743 {
744  MultiresReshapeSmoothContext *reshape_smooth_context = foreach_context->user_data;
745 
746  BLI_assert(subdiv_poly_index < reshape_smooth_context->geometry.num_faces);
747 
748  Face *face = &reshape_smooth_context->geometry.faces[subdiv_poly_index];
749  face->start_corner_index = start_loop_index;
750  face->num_corners = num_loops;
751 }
752 
753 static void foreach_vertex_of_loose_edge(const struct SubdivForeachContext *foreach_context,
754  void *UNUSED(tls),
755  const int UNUSED(coarse_edge_index),
756  const float UNUSED(u),
757  const int vertex_index)
758 {
759  const MultiresReshapeSmoothContext *reshape_smooth_context = foreach_context->user_data;
760  Vertex *vertex = &reshape_smooth_context->geometry.vertices[vertex_index];
761 
762  if (vertex->num_grid_coords != 0) {
763  vertex->is_infinite_sharp = true;
764  }
765 }
766 
767 static void store_edge(MultiresReshapeSmoothContext *reshape_smooth_context,
768  const int subdiv_v1,
769  const int subdiv_v2,
770  const char crease)
771 {
772  /* This is a bit overhead to use atomics in such a simple function called from many threads,
773  * but this allows to save quite measurable amount of memory. */
774  const int edge_index = atomic_fetch_and_add_z(&reshape_smooth_context->geometry.num_edges, 1);
775  BLI_assert(edge_index < reshape_smooth_context->geometry.max_edges);
776 
777  Edge *edge = &reshape_smooth_context->geometry.edges[edge_index];
778  edge->v1 = subdiv_v1;
779  edge->v2 = subdiv_v2;
781 }
782 
783 static void foreach_edge(const struct SubdivForeachContext *foreach_context,
784  void *UNUSED(tls),
785  const int coarse_edge_index,
786  const int UNUSED(subdiv_edge_index),
787  const int subdiv_v1,
788  const int subdiv_v2)
789 {
790  MultiresReshapeSmoothContext *reshape_smooth_context = foreach_context->user_data;
791  const MultiresReshapeContext *reshape_context = reshape_smooth_context->reshape_context;
792 
793  if (reshape_smooth_context->smoothing_type == MULTIRES_SUBDIVIDE_LINEAR) {
794  store_edge(reshape_smooth_context, subdiv_v1, subdiv_v2, (char)255);
795  return;
796  }
797 
798  /* Ignore all inner face edges as they have sharpness of zero when using Catmull-Clark mode. In
799  * simple mode, all edges have maximum sharpness, so they can't be skipped. */
800  if (coarse_edge_index == ORIGINDEX_NONE &&
801  reshape_smooth_context->smoothing_type != MULTIRES_SUBDIVIDE_SIMPLE) {
802  return;
803  }
804  /* Ignore all loose edges as well, as they are not communicated to the OpenSubdiv. */
805  if (!BLI_BITMAP_TEST_BOOL(reshape_smooth_context->non_loose_base_edge_map, coarse_edge_index)) {
806  return;
807  }
808  /* Edges without crease are to be ignored as well. */
809  const Mesh *base_mesh = reshape_context->base_mesh;
810  const MEdge *base_edge = &base_mesh->medge[coarse_edge_index];
811  const char crease = get_effective_edge_crease_char(reshape_smooth_context, base_edge);
812  if (crease == 0) {
813  return;
814  }
815  store_edge(reshape_smooth_context, subdiv_v1, subdiv_v2, crease);
816 }
817 
819 {
820  const MultiresReshapeContext *reshape_context = reshape_smooth_context->reshape_context;
821  const Mesh *base_mesh = reshape_context->base_mesh;
822  const MPoly *base_mpoly = base_mesh->mpoly;
823  const MLoop *base_mloop = base_mesh->mloop;
824  const MEdge *base_edge = base_mesh->medge;
825 
826  reshape_smooth_context->non_loose_base_edge_map = BLI_BITMAP_NEW(base_mesh->totedge,
827  "non_loose_base_edge_map");
828 
829  int num_used_edges = 0;
830  for (int poly_index = 0; poly_index < base_mesh->totpoly; ++poly_index) {
831  const MPoly *base_poly = &base_mpoly[poly_index];
832  for (int corner = 0; corner < base_poly->totloop; corner++) {
833  const MLoop *loop = &base_mloop[base_poly->loopstart + corner];
834  if (!BLI_BITMAP_TEST_BOOL(reshape_smooth_context->non_loose_base_edge_map, loop->e)) {
835  BLI_BITMAP_ENABLE(reshape_smooth_context->non_loose_base_edge_map, loop->e);
836 
837  const char crease = get_effective_edge_crease_char(reshape_smooth_context,
838  &base_edge[loop->e]);
839  if (crease != 0) {
840  ++num_used_edges;
841  }
842  }
843  }
844  }
845 
846  const int resolution = get_reshape_level_resolution(reshape_context);
847  const int num_subdiv_vertices_per_base_edge = resolution - 2;
848  reshape_smooth_context->geometry.max_edges = num_used_edges *
849  (num_subdiv_vertices_per_base_edge + 1);
850 }
851 
852 static void geometry_create(MultiresReshapeSmoothContext *reshape_smooth_context)
853 {
854  const MultiresReshapeContext *reshape_context = reshape_smooth_context->reshape_context;
855 
856  SubdivForeachContext foreach_context = {
858  .vertex_inner = foreach_vertex_inner,
859  .vertex_every_corner = foreach_vertex_every_corner,
860  .vertex_every_edge = foreach_vertex_every_edge,
861  .loop = foreach_loop,
862  .poly = foreach_poly,
863  .vertex_of_loose_edge = foreach_vertex_of_loose_edge,
864  .edge = foreach_edge,
865  .user_data = reshape_smooth_context,
866  };
867 
868  geometry_init_loose_information(reshape_smooth_context);
869 
870  SubdivToMeshSettings mesh_settings;
871  mesh_settings.resolution = get_reshape_level_resolution(reshape_context);
872  mesh_settings.use_optimal_display = false;
873 
874  /* TODO(sergey): Tell the foreach() to ignore loose vertices. */
876  reshape_context->subdiv, &foreach_context, &mesh_settings, reshape_context->base_mesh);
877 }
878 
881 /* -------------------------------------------------------------------- */
886 {
887  return OSD_SCHEME_CATMARK;
888 }
889 
891  const struct OpenSubdiv_Converter *converter)
892 {
893  const MultiresReshapeSmoothContext *reshape_smooth_context = converter->user_data;
894  const MultiresReshapeContext *reshape_context = reshape_smooth_context->reshape_context;
895  const SubdivSettings *settings = &reshape_context->subdiv->settings;
896 
898 }
899 
901  const OpenSubdiv_Converter *converter)
902 {
903  const MultiresReshapeSmoothContext *reshape_smooth_context = converter->user_data;
904  const MultiresReshapeContext *reshape_context = reshape_smooth_context->reshape_context;
905  const SubdivSettings *settings = &reshape_context->subdiv->settings;
906 
908 }
909 
911 {
912  return false;
913 }
914 
915 static int get_num_faces(const OpenSubdiv_Converter *converter)
916 {
917  const MultiresReshapeSmoothContext *reshape_smooth_context = converter->user_data;
918 
919  return reshape_smooth_context->geometry.num_faces;
920 }
921 
922 static int get_num_vertices(const OpenSubdiv_Converter *converter)
923 {
924  const MultiresReshapeSmoothContext *reshape_smooth_context = converter->user_data;
925 
926  return reshape_smooth_context->geometry.num_vertices;
927 }
928 
929 static int get_num_face_vertices(const OpenSubdiv_Converter *converter, int face_index)
930 {
931  const MultiresReshapeSmoothContext *reshape_smooth_context = converter->user_data;
932  BLI_assert(face_index < reshape_smooth_context->geometry.num_faces);
933 
934  const Face *face = &reshape_smooth_context->geometry.faces[face_index];
935  return face->num_corners;
936 }
937 
938 static void get_face_vertices(const OpenSubdiv_Converter *converter,
939  int face_index,
940  int *face_vertices)
941 {
942  const MultiresReshapeSmoothContext *reshape_smooth_context = converter->user_data;
943  BLI_assert(face_index < reshape_smooth_context->geometry.num_faces);
944 
945  const Face *face = &reshape_smooth_context->geometry.faces[face_index];
946 
947  for (int i = 0; i < face->num_corners; ++i) {
948  const int corner_index = face->start_corner_index + i;
949  const Corner *corner = &reshape_smooth_context->geometry.corners[corner_index];
950  face_vertices[i] = corner->vertex - reshape_smooth_context->geometry.vertices;
951  }
952 }
953 
954 static int get_num_edges(const struct OpenSubdiv_Converter *converter)
955 {
956  const MultiresReshapeSmoothContext *reshape_smooth_context = converter->user_data;
957  return reshape_smooth_context->geometry.num_edges;
958 }
959 
960 static void get_edge_vertices(const OpenSubdiv_Converter *converter,
961  const int edge_index,
962  int edge_vertices[2])
963 {
964  const MultiresReshapeSmoothContext *reshape_smooth_context = converter->user_data;
965  BLI_assert(edge_index < reshape_smooth_context->geometry.num_edges);
966 
967  const Edge *edge = &reshape_smooth_context->geometry.edges[edge_index];
968  edge_vertices[0] = edge->v1;
969  edge_vertices[1] = edge->v2;
970 }
971 
972 static float get_edge_sharpness(const OpenSubdiv_Converter *converter, const int edge_index)
973 {
974  const MultiresReshapeSmoothContext *reshape_smooth_context = converter->user_data;
975  BLI_assert(edge_index < reshape_smooth_context->geometry.num_edges);
976 
977  const Edge *edge = &reshape_smooth_context->geometry.edges[edge_index];
978  return edge->sharpness;
979 }
980 
981 static bool is_infinite_sharp_vertex(const OpenSubdiv_Converter *converter, int vertex_index)
982 {
983  const MultiresReshapeSmoothContext *reshape_smooth_context = converter->user_data;
984 
985  BLI_assert(vertex_index < reshape_smooth_context->geometry.num_vertices);
986 
987  const Vertex *vertex = &reshape_smooth_context->geometry.vertices[vertex_index];
988  return vertex->is_infinite_sharp;
989 }
990 
991 static void converter_init(const MultiresReshapeSmoothContext *reshape_smooth_context,
992  OpenSubdiv_Converter *converter)
993 {
994  converter->getSchemeType = get_scheme_type;
998 
999  converter->getNumFaces = get_num_faces;
1000  converter->getNumEdges = get_num_edges;
1001  converter->getNumVertices = get_num_vertices;
1002 
1004  converter->getFaceVertices = get_face_vertices;
1005  converter->getFaceEdges = NULL;
1006 
1007  converter->getEdgeVertices = get_edge_vertices;
1008  converter->getNumEdgeFaces = NULL;
1009  converter->getEdgeFaces = NULL;
1010  converter->getEdgeSharpness = get_edge_sharpness;
1011 
1012  converter->getNumVertexEdges = NULL;
1013  converter->getVertexEdges = NULL;
1014  converter->getNumVertexFaces = NULL;
1015  converter->getVertexFaces = NULL;
1017  converter->getVertexSharpness = NULL;
1018 
1019  converter->getNumUVLayers = NULL;
1020  converter->precalcUVLayer = NULL;
1021  converter->finishUVLayer = NULL;
1022  converter->getNumUVCoordinates = NULL;
1023  converter->getFaceCornerUVIndex = NULL;
1024 
1025  converter->freeUserData = NULL;
1026 
1027  converter->user_data = (void *)reshape_smooth_context;
1028 }
1029 
1030 /* Create subdiv descriptor created for topology at a reshape level, */
1031 static void reshape_subdiv_create(MultiresReshapeSmoothContext *reshape_smooth_context)
1032 {
1033  const MultiresReshapeContext *reshape_context = reshape_smooth_context->reshape_context;
1034  const SubdivSettings *settings = &reshape_context->subdiv->settings;
1035 
1036  OpenSubdiv_Converter converter;
1037  converter_init(reshape_smooth_context, &converter);
1038 
1039  Subdiv *reshape_subdiv = BKE_subdiv_new_from_converter(settings, &converter);
1040  BKE_subdiv_eval_begin(reshape_subdiv);
1041 
1042  reshape_smooth_context->reshape_subdiv = reshape_subdiv;
1043 
1044  BKE_subdiv_converter_free(&converter);
1045 }
1046 
1047 /* Callback to provide coarse position for subdivision surface topology at a reshape level. */
1049  const MultiresReshapeSmoothContext *reshape_smooth_context,
1050  const Vertex *vertex,
1051  float r_P[3]);
1052 
1053 /* Refine subdivision surface topology at a reshape level for new coarse vertices positions. */
1054 static void reshape_subdiv_refine(const MultiresReshapeSmoothContext *reshape_smooth_context,
1055  ReshapeSubdivCoarsePositionCb coarse_position_cb)
1056 {
1057  Subdiv *reshape_subdiv = reshape_smooth_context->reshape_subdiv;
1058 
1059  /* TODO(sergey): For non-trivial coarse_position_cb we should multi-thread this loop. */
1060 
1061  const int num_vertices = reshape_smooth_context->geometry.num_vertices;
1062  for (int i = 0; i < num_vertices; ++i) {
1063  const Vertex *vertex = &reshape_smooth_context->geometry.vertices[i];
1064  float P[3];
1065  coarse_position_cb(reshape_smooth_context, vertex, P);
1066  reshape_subdiv->evaluator->setCoarsePositions(reshape_subdiv->evaluator, P, i, 1);
1067  }
1068  reshape_subdiv->evaluator->refine(reshape_subdiv->evaluator);
1069 }
1070 
1072 {
1073  if (vertex->num_grid_coords == 0) {
1074  /* This is a loose vertex, the coordinate is not important. */
1075  /* TODO(sergey): Once the subdiv_foreach() supports properly ignoring loose elements this
1076  * should become an assert instead. */
1077  return NULL;
1078  }
1079  /* NOTE: All grid coordinates will point to the same object position, so can be simple and use
1080  * first grid coordinate. */
1081  return &vertex->grid_coords[0];
1082 }
1083 
1084 /* Version of reshape_subdiv_refine() which uses coarse position from original grids. */
1086  const MultiresReshapeSmoothContext *reshape_smooth_context, const Vertex *vertex, float r_P[3])
1087 {
1088  const MultiresReshapeContext *reshape_context = reshape_smooth_context->reshape_context;
1089  const GridCoord *grid_coord = reshape_subdiv_refine_vertex_grid_coord(vertex);
1090 
1091  /* Check whether this is a loose vertex. */
1092  if (grid_coord == NULL) {
1093  zero_v3(r_P);
1094  return;
1095  }
1096 
1097  float limit_P[3];
1098  float tangent_matrix[3][3];
1099  multires_reshape_evaluate_limit_at_grid(reshape_context, grid_coord, limit_P, tangent_matrix);
1100 
1101  const ReshapeConstGridElement orig_grid_element =
1102  multires_reshape_orig_grid_element_for_grid_coord(reshape_context, grid_coord);
1103 
1104  float D[3];
1105  mul_v3_m3v3(D, tangent_matrix, orig_grid_element.displacement);
1106 
1107  add_v3_v3v3(r_P, limit_P, D);
1108 }
1109 static void reshape_subdiv_refine_orig(const MultiresReshapeSmoothContext *reshape_smooth_context)
1110 {
1111  reshape_subdiv_refine(reshape_smooth_context, reshape_subdiv_refine_orig_P);
1112 }
1113 
1114 /* Version of reshape_subdiv_refine() which uses coarse position from final grids. */
1116  const MultiresReshapeSmoothContext *reshape_smooth_context, const Vertex *vertex, float r_P[3])
1117 {
1118  const MultiresReshapeContext *reshape_context = reshape_smooth_context->reshape_context;
1119  const GridCoord *grid_coord = reshape_subdiv_refine_vertex_grid_coord(vertex);
1120 
1121  /* Check whether this is a loose vertex. */
1122  if (grid_coord == NULL) {
1123  zero_v3(r_P);
1124  return;
1125  }
1126 
1128  reshape_context, grid_coord);
1129 
1130  /* NOTE: At this point in reshape/propagate pipeline grid displacement is actually storing object
1131  * vertices coordinates. */
1132  copy_v3_v3(r_P, grid_element.displacement);
1133 }
1134 static void reshape_subdiv_refine_final(const MultiresReshapeSmoothContext *reshape_smooth_context)
1135 {
1136  reshape_subdiv_refine(reshape_smooth_context, reshape_subdiv_refine_final_P);
1137 }
1138 
1140  const MultiresReshapeSmoothContext *reshape_smooth_context,
1141  const PTexCoord *ptex_coord,
1142  const GridCoord *grid_coord,
1143  float limit_P[3],
1144  float r_tangent_matrix[3][3])
1145 {
1146  const MultiresReshapeContext *reshape_context = reshape_smooth_context->reshape_context;
1147 
1148  float dPdu[3], dPdv[3];
1150  ptex_coord->ptex_face_index,
1151  ptex_coord->u,
1152  ptex_coord->v,
1153  limit_P,
1154  dPdu,
1155  dPdv);
1156 
1157  const int face_index = multires_reshape_grid_to_face_index(reshape_context,
1158  grid_coord->grid_index);
1159  const int corner = multires_reshape_grid_to_corner(reshape_context, grid_coord->grid_index);
1161  reshape_context, face_index, corner, dPdu, dPdv, r_tangent_matrix);
1162 }
1163 
1166 /* -------------------------------------------------------------------- */
1171  const MultiresReshapeSmoothContext *reshape_smooth_context, const GridCoord *grid_coord)
1172 {
1173  const MultiresReshapeContext *reshape_context = reshape_smooth_context->reshape_context;
1174  const ReshapeConstGridElement orig_grid_element =
1175  multires_reshape_orig_grid_element_for_grid_coord(reshape_context, grid_coord);
1176 
1177  LinearGridElement linear_grid_element;
1178  linear_grid_element_init(&linear_grid_element);
1179 
1180  linear_grid_element.mask = orig_grid_element.mask;
1181 
1182  return linear_grid_element;
1183 }
1184 
1186  const MultiresReshapeSmoothContext *reshape_smooth_context, const GridCoord *grid_coord)
1187 {
1188  const MultiresReshapeContext *reshape_context = reshape_smooth_context->reshape_context;
1190  reshape_context, grid_coord);
1191 
1192  LinearGridElement linear_grid_element;
1193  linear_grid_element_init(&linear_grid_element);
1194 
1195  if (final_grid_element.mask != NULL) {
1196  linear_grid_element.mask = *final_grid_element.mask;
1197  }
1198 
1199  return linear_grid_element;
1200 }
1201 
1202 /* Interpolate difference of the linear data.
1203  *
1204  * Will access final data and original data at the grid elements at the reshape level,
1205  * calculate difference between final and original, and linearly interpolate to get value at the
1206  * top level. */
1208  const MultiresReshapeSmoothContext *reshape_smooth_context,
1209  const GridCoord *grid_coord,
1211 {
1212  const MultiresReshapeContext *reshape_context = reshape_smooth_context->reshape_context;
1213 
1214  const int reshape_level = reshape_context->reshape.level;
1215  const int reshape_level_grid_size = BKE_subdiv_grid_size_from_level(reshape_level);
1216  const int reshape_level_grid_size_1 = reshape_level_grid_size - 1;
1217  const float reshape_level_grid_size_1_inv = 1.0f / (float)(reshape_level_grid_size_1);
1218 
1219  const float x_f = grid_coord->u * reshape_level_grid_size_1;
1220  const float y_f = grid_coord->v * reshape_level_grid_size_1;
1221 
1222  const int x_i = x_f;
1223  const int y_i = y_f;
1224  const int x_n_i = (x_i == reshape_level_grid_size - 1) ? (x_i) : (x_i + 1);
1225  const int y_n_i = (y_i == reshape_level_grid_size - 1) ? (y_i) : (y_i + 1);
1226 
1227  const int corners_int_coords[4][2] = {{x_i, y_i}, {x_n_i, y_i}, {x_n_i, y_n_i}, {x_i, y_n_i}};
1228 
1229  LinearGridElement corner_elements[4];
1230  for (int i = 0; i < 4; ++i) {
1231  GridCoord corner_grid_coord;
1232  corner_grid_coord.grid_index = grid_coord->grid_index;
1233  corner_grid_coord.u = corners_int_coords[i][0] * reshape_level_grid_size_1_inv;
1234  corner_grid_coord.v = corners_int_coords[i][1] * reshape_level_grid_size_1_inv;
1235 
1236  const LinearGridElement orig_element = linear_grid_element_orig_get(reshape_smooth_context,
1237  &corner_grid_coord);
1238  const LinearGridElement final_element = linear_grid_element_final_get(reshape_smooth_context,
1239  &corner_grid_coord);
1240  linear_grid_element_sub(&corner_elements[i], &final_element, &orig_element);
1241  }
1242 
1243  const float u = x_f - x_i;
1244  const float v = y_f - y_i;
1245  const float weights[4] = {(1.0f - u) * (1.0f - v), u * (1.0f - v), u * v, (1.0f - u) * v};
1246 
1247  linear_grid_element_interpolate(result, corner_elements, weights);
1248 }
1249 
1251  const MultiresReshapeSmoothContext *reshape_smooth_context,
1252  const PTexCoord *UNUSED(ptex_coord),
1253  const GridCoord *grid_coord,
1254  void *UNUSED(userdata_v))
1255 {
1256  LinearGridElement *linear_delta_element = linear_grid_element_get(
1257  &reshape_smooth_context->linear_delta_grids, grid_coord);
1258 
1259  linear_grid_element_delta_interpolate(reshape_smooth_context, grid_coord, linear_delta_element);
1260 }
1261 
1262 static void evaluate_linear_delta_grids(MultiresReshapeSmoothContext *reshape_smooth_context)
1263 {
1264  const MultiresReshapeContext *reshape_context = reshape_smooth_context->reshape_context;
1265  const int num_grids = reshape_context->num_grids;
1266  const int top_level = reshape_context->top.level;
1267 
1268  linear_grids_allocate(&reshape_smooth_context->linear_delta_grids, num_grids, top_level);
1269 
1271 }
1272 
1273 static void propagate_linear_data_delta(const MultiresReshapeSmoothContext *reshape_smooth_context,
1274  ReshapeGridElement *final_grid_element,
1275  const GridCoord *grid_coord)
1276 {
1277  const MultiresReshapeContext *reshape_context = reshape_smooth_context->reshape_context;
1278 
1279  LinearGridElement *linear_delta_element = linear_grid_element_get(
1280  &reshape_smooth_context->linear_delta_grids, grid_coord);
1281 
1282  const ReshapeConstGridElement orig_grid_element =
1283  multires_reshape_orig_grid_element_for_grid_coord(reshape_context, grid_coord);
1284 
1285  if (final_grid_element->mask != NULL) {
1286  *final_grid_element->mask = clamp_f(
1287  orig_grid_element.mask + linear_delta_element->mask, 0.0f, 1.0f);
1288  }
1289 }
1290 
1293 /* -------------------------------------------------------------------- */
1298  const MultiresReshapeSmoothContext *reshape_smooth_context,
1299  const PTexCoord *ptex_coord,
1300  const GridCoord *grid_coord,
1301  void *UNUSED(userdata_v))
1302 {
1303  float limit_P[3];
1304  float tangent_matrix[3][3];
1306  reshape_smooth_context, ptex_coord, grid_coord, limit_P, tangent_matrix);
1307 
1308  base_surface_grids_write(reshape_smooth_context, grid_coord, limit_P, tangent_matrix);
1309 }
1310 
1311 static void evaluate_base_surface_grids(const MultiresReshapeSmoothContext *reshape_smooth_context)
1312 {
1314 }
1315 
1318 /* -------------------------------------------------------------------- */
1322 /* Evaluate final position of the original (pre-sculpt-edit) point position at a given grid
1323  * coordinate. */
1325  const MultiresReshapeSmoothContext *reshape_smooth_context,
1326  const GridCoord *grid_coord,
1327  float r_orig_final_P[3])
1328 {
1329  const MultiresReshapeContext *reshape_context = reshape_smooth_context->reshape_context;
1330 
1331  /* Element of an original MDISPS grid) */
1332  const ReshapeConstGridElement orig_grid_element =
1333  multires_reshape_orig_grid_element_for_grid_coord(reshape_context, grid_coord);
1334 
1335  /* Limit surface of the base mesh. */
1336  float base_mesh_limit_P[3];
1337  float base_mesh_tangent_matrix[3][3];
1339  reshape_context, grid_coord, base_mesh_limit_P, base_mesh_tangent_matrix);
1340 
1341  /* Convert original displacement from tangent space to object space. */
1342  float orig_displacement[3];
1343  mul_v3_m3v3(orig_displacement, base_mesh_tangent_matrix, orig_grid_element.displacement);
1344 
1345  /* Final point = limit surface + displacement. */
1346  add_v3_v3v3(r_orig_final_P, base_mesh_limit_P, orig_displacement);
1347 }
1348 
1350  const MultiresReshapeSmoothContext *reshape_smooth_context,
1351  const PTexCoord *ptex_coord,
1352  const GridCoord *grid_coord,
1353  void *UNUSED(userdata_v))
1354 {
1355  const MultiresReshapeContext *reshape_context = reshape_smooth_context->reshape_context;
1356 
1357  /* Position of the original veretx at top level. */
1358  float orig_final_P[3];
1359  evaluate_final_original_point(reshape_smooth_context, grid_coord, orig_final_P);
1360 
1361  /* Original surface point on sculpt level (sculpt level before edits in sculpt mode). */
1362  const SurfacePoint *orig_sculpt_point = base_surface_grids_read(reshape_smooth_context,
1363  grid_coord);
1364 
1365  /* Difference between original top level and original sculpt level in object space. */
1366  float original_detail_delta[3];
1367  sub_v3_v3v3(original_detail_delta, orig_final_P, orig_sculpt_point->P);
1368 
1369  /* Difference between original top level and original sculpt level in tangent space of original
1370  * sculpt level. */
1371  float original_detail_delta_tangent[3];
1372  float original_sculpt_tangent_matrix_inv[3][3];
1373  invert_m3_m3(original_sculpt_tangent_matrix_inv, orig_sculpt_point->tangent_matrix);
1374  mul_v3_m3v3(
1375  original_detail_delta_tangent, original_sculpt_tangent_matrix_inv, original_detail_delta);
1376 
1377  /* Limit surface of smoothed (subdivided) edited sculpt level. */
1378  float smooth_limit_P[3];
1379  float smooth_tangent_matrix[3][3];
1381  reshape_smooth_context, ptex_coord, grid_coord, smooth_limit_P, smooth_tangent_matrix);
1382 
1383  /* Add original detail to the smoothed surface. */
1384  float smooth_delta[3];
1385  mul_v3_m3v3(smooth_delta, smooth_tangent_matrix, original_detail_delta_tangent);
1386 
1387  /* Grid element of the result.
1388  *
1389  * NOTE: Displacement is storing object space coordinate. */
1391  grid_coord);
1392 
1393  add_v3_v3v3(grid_element.displacement, smooth_limit_P, smooth_delta);
1394 
1395  /* Propagate non-coordinate data. */
1396  propagate_linear_data_delta(reshape_smooth_context, &grid_element, grid_coord);
1397 }
1398 
1400  const MultiresReshapeSmoothContext *reshape_smooth_context)
1401 {
1404 }
1405 
1407  const MultiresReshapeSmoothContext *reshape_smooth_context,
1408  const PTexCoord *ptex_coord,
1409  const GridCoord *grid_coord,
1410  void *UNUSED(userdata_v))
1411 {
1412  const MultiresReshapeContext *reshape_context = reshape_smooth_context->reshape_context;
1413  Subdiv *reshape_subdiv = reshape_smooth_context->reshape_subdiv;
1414 
1416  grid_coord);
1417 
1418  /* Surface. */
1419  float P[3];
1421  reshape_subdiv, ptex_coord->ptex_face_index, ptex_coord->u, ptex_coord->v, P);
1422 
1423  copy_v3_v3(grid_element.displacement, P);
1424 
1425  /* Propagate non-coordinate data. */
1426  propagate_linear_data_delta(reshape_smooth_context, &grid_element, grid_coord);
1427 }
1428 
1430  const MultiresReshapeSmoothContext *reshape_smooth_context)
1431 {
1433  reshape_smooth_context, evaluate_higher_grid_positions_callback, NULL);
1434 }
1435 
1438 /* -------------------------------------------------------------------- */
1443  const MultiresReshapeContext *reshape_context)
1444 {
1445  const int level_difference = (reshape_context->top.level - reshape_context->reshape.level);
1446  if (level_difference == 0) {
1447  /* Early output. */
1448  return;
1449  }
1450 
1451  MultiresReshapeSmoothContext reshape_smooth_context;
1452  if (reshape_context->subdiv->settings.is_simple) {
1453  context_init(&reshape_smooth_context, reshape_context, MULTIRES_SUBDIVIDE_SIMPLE);
1454  }
1455  else {
1456  context_init(&reshape_smooth_context, reshape_context, MULTIRES_SUBDIVIDE_CATMULL_CLARK);
1457  }
1458 
1459  geometry_create(&reshape_smooth_context);
1460  evaluate_linear_delta_grids(&reshape_smooth_context);
1461 
1462  reshape_subdiv_create(&reshape_smooth_context);
1463 
1464  base_surface_grids_allocate(&reshape_smooth_context);
1465  reshape_subdiv_refine_orig(&reshape_smooth_context);
1466  evaluate_base_surface_grids(&reshape_smooth_context);
1467 
1468  reshape_subdiv_refine_final(&reshape_smooth_context);
1469  evaluate_higher_grid_positions_with_details(&reshape_smooth_context);
1470 
1471  context_free(&reshape_smooth_context);
1472 }
1473 
1475  const eMultiresSubdivideModeType mode)
1476 {
1477  const int level_difference = (reshape_context->top.level - reshape_context->reshape.level);
1478  if (level_difference == 0) {
1479  /* Early output. */
1480  return;
1481  }
1482 
1483  MultiresReshapeSmoothContext reshape_smooth_context;
1484  context_init(&reshape_smooth_context, reshape_context, mode);
1485 
1486  geometry_create(&reshape_smooth_context);
1487  evaluate_linear_delta_grids(&reshape_smooth_context);
1488 
1489  reshape_subdiv_create(&reshape_smooth_context);
1490 
1491  reshape_subdiv_refine_final(&reshape_smooth_context);
1492  evaluate_higher_grid_positions(&reshape_smooth_context);
1493 
1494  context_free(&reshape_smooth_context);
1495 }
1496 
typedef float(TangentPoint)[2]
CustomData interface, see also DNA_customdata_types.h.
#define ORIGINDEX_NONE
eMultiresSubdivideModeType
Definition: BKE_multires.h:171
@ MULTIRES_SUBDIVIDE_LINEAR
Definition: BKE_multires.h:174
@ MULTIRES_SUBDIVIDE_CATMULL_CLARK
Definition: BKE_multires.h:172
@ MULTIRES_SUBDIVIDE_SIMPLE
Definition: BKE_multires.h:173
BLI_INLINE float BKE_subdiv_edge_crease_to_sharpness_char(char edge_crease)
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
Subdiv * BKE_subdiv_new_from_converter(const SubdivSettings *settings, struct OpenSubdiv_Converter *converter)
Definition: subdiv.c:103
void BKE_subdiv_eval_limit_point(struct Subdiv *subdiv, const int ptex_face_index, const float u, const float v, float r_P[3])
Definition: subdiv_eval.c:171
bool BKE_subdiv_eval_begin(struct Subdiv *subdiv)
Definition: subdiv_eval.c:41
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
bool BKE_subdiv_foreach_subdiv_geometry(struct Subdiv *subdiv, const struct SubdivForeachContext *context, const struct SubdivToMeshSettings *mesh_settings, const struct Mesh *coarse_mesh)
#define BLI_assert(a)
Definition: BLI_assert.h:58
#define BLI_BITMAP_ENABLE(_bitmap, _index)
Definition: BLI_bitmap.h:78
#define BLI_BITMAP_TEST_BOOL(_bitmap, _index)
Definition: BLI_bitmap.h:73
#define BLI_BITMAP_NEW(_tot, _alloc_string)
Definition: BLI_bitmap.h:50
unsigned int BLI_bitmap
Definition: BLI_bitmap.h:32
#define BLI_INLINE
MINLINE float clamp_f(float value, float min, float max)
void copy_m3_m3(float m1[3][3], const float m2[3][3])
Definition: math_matrix.c:89
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])
MINLINE void zero_v3(float r[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)
#define ELEM(...)
_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
_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 GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble t
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
#define MEM_reallocN(vmemh, len)
Provides wrapper around system-specific atomic primitives, and some extensions (faked-atomic operatio...
ATOMIC_INLINE size_t atomic_fetch_and_add_z(size_t *p, size_t x)
ATTR_WARN_UNUSED_RESULT const BMVert * v
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_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)
ReshapeGridElement multires_reshape_grid_element_for_grid_coord(const MultiresReshapeContext *reshape_context, const GridCoord *grid_coord)
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])
ReshapeConstGridElement multires_reshape_orig_grid_element_for_grid_coord(const MultiresReshapeContext *reshape_context, const GridCoord *grid_coord)
GridCoord multires_reshape_ptex_coord_to_grid(const MultiresReshapeContext *reshape_context, const PTexCoord *ptex_coord)
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])
void multires_reshape_smooth_object_grids(const MultiresReshapeContext *reshape_context, const eMultiresSubdivideModeType mode)
static LinearGridElement linear_grid_element_final_get(const MultiresReshapeSmoothContext *reshape_smooth_context, const GridCoord *grid_coord)
static void reshape_subdiv_evaluate_limit_at_grid(const MultiresReshapeSmoothContext *reshape_smooth_context, const PTexCoord *ptex_coord, const GridCoord *grid_coord, float limit_P[3], float r_tangent_matrix[3][3])
static int get_num_edges(const struct OpenSubdiv_Converter *converter)
void(* ForeachTopLevelGridCoordCallback)(const MultiresReshapeSmoothContext *reshape_smooth_context, const PTexCoord *ptex_coord, const GridCoord *grid_coord, void *userdata_v)
static void foreach_edge(const struct SubdivForeachContext *foreach_context, void *UNUSED(tls), const int coarse_edge_index, const int UNUSED(subdiv_edge_index), const int subdiv_v1, const int subdiv_v2)
static void reshape_subdiv_refine_final_P(const MultiresReshapeSmoothContext *reshape_smooth_context, const Vertex *vertex, float r_P[3])
static void foreach_vertex_every_edge(const struct SubdivForeachContext *foreach_context, void *UNUSED(tls_v), const int ptex_face_index, const float ptex_face_u, const float ptex_face_v, const int UNUSED(coarse_edge_index), const int UNUSED(coarse_face_index), const int UNUSED(coarse_face_corner), const int subdiv_vertex_index)
static void foreach_toplevel_grid_coord_task(void *__restrict userdata_v, const int face_index, const TaskParallelTLS *__restrict UNUSED(tls))
void multires_reshape_smooth_object_grids_with_details(const MultiresReshapeContext *reshape_context)
static void propagate_linear_data_delta(const MultiresReshapeSmoothContext *reshape_smooth_context, ReshapeGridElement *final_grid_element, const GridCoord *grid_coord)
static void reshape_subdiv_refine(const MultiresReshapeSmoothContext *reshape_smooth_context, ReshapeSubdivCoarsePositionCb coarse_position_cb)
static bool specifies_full_topology(const OpenSubdiv_Converter *UNUSED(converter))
static LinearGridElement * linear_grid_element_get(const LinearGrids *linear_grids, const GridCoord *grid_coord)
struct LinearGrid LinearGrid
struct SurfacePoint SurfacePoint
struct Vertex Vertex
static float get_edge_sharpness(const OpenSubdiv_Converter *converter, const int edge_index)
struct MultiresReshapeSmoothContext MultiresReshapeSmoothContext
static OpenSubdiv_SchemeType get_scheme_type(const OpenSubdiv_Converter *UNUSED(converter))
static void evaluate_higher_grid_positions_callback(const MultiresReshapeSmoothContext *reshape_smooth_context, const PTexCoord *ptex_coord, const GridCoord *grid_coord, void *UNUSED(userdata_v))
static void foreach_poly(const SubdivForeachContext *foreach_context, void *UNUSED(tls), const int UNUSED(coarse_poly_index), const int subdiv_poly_index, const int start_loop_index, const int num_loops)
static void linear_grids_free(LinearGrids *linear_grids)
static void reshape_subdiv_create(MultiresReshapeSmoothContext *reshape_smooth_context)
static void linear_grid_element_sub(LinearGridElement *result, const LinearGridElement *a, const LinearGridElement *b)
static void evaluate_higher_grid_positions(const MultiresReshapeSmoothContext *reshape_smooth_context)
static LinearGridElement linear_grid_element_orig_get(const MultiresReshapeSmoothContext *reshape_smooth_context, const GridCoord *grid_coord)
static void foreach_single_vertex(const SubdivForeachContext *foreach_context, const GridCoord *grid_coord, const int subdiv_vertex_index)
struct Corner Corner
static OpenSubdiv_VtxBoundaryInterpolation get_vtx_boundary_interpolation(const struct OpenSubdiv_Converter *converter)
static void foreach_toplevel_grid_coord(const MultiresReshapeSmoothContext *reshape_smooth_context, ForeachTopLevelGridCoordCallback callback, void *callback_userdata_v)
static void linear_grid_element_delta_interpolate(const MultiresReshapeSmoothContext *reshape_smooth_context, const GridCoord *grid_coord, LinearGridElement *result)
static int get_num_faces(const OpenSubdiv_Converter *converter)
static void evaluate_base_surface_grids(const MultiresReshapeSmoothContext *reshape_smooth_context)
static void evaluate_higher_grid_positions_with_details(const MultiresReshapeSmoothContext *reshape_smooth_context)
BLI_INLINE const GridCoord * reshape_subdiv_refine_vertex_grid_coord(const Vertex *vertex)
static void linear_grid_element_interpolate(LinearGridElement *result, const LinearGridElement elements[4], const float weights[4])
static void context_free(MultiresReshapeSmoothContext *reshape_smooth_context)
static void linear_grid_element_init(LinearGridElement *linear_grid_element)
static SurfacePoint * base_surface_grids_read(const MultiresReshapeSmoothContext *reshape_smooth_context, const GridCoord *grid_coord)
struct ForeachTopLevelGridCoordTaskData ForeachHighLevelCoordTaskData
static void grid_coords_from_face_vertices(const MultiresReshapeSmoothContext *reshape_smooth_context, const Face *face, const GridCoord *grid_coords[])
static char get_effective_edge_crease_char(const MultiresReshapeSmoothContext *reshape_smooth_context, const MEdge *base_edge)
static void context_init(MultiresReshapeSmoothContext *reshape_smooth_context, const MultiresReshapeContext *reshape_context, const eMultiresSubdivideModeType mode)
struct SurfaceGrid SurfaceGrid
static GridCoord * vertex_grid_coord_with_grid_index(const Vertex *vertex, const int grid_index)
static void foreach_vertex(const SubdivForeachContext *foreach_context, const PTexCoord *ptex_coord, const int subdiv_vertex_index)
static int get_num_vertices(const OpenSubdiv_Converter *converter)
static void foreach_vertex_of_loose_edge(const struct SubdivForeachContext *foreach_context, void *UNUSED(tls), const int UNUSED(coarse_edge_index), const float UNUSED(u), const int vertex_index)
static void linear_grids_allocate(LinearGrids *linear_grids, int num_grids, int level)
static void base_surface_grids_write(const MultiresReshapeSmoothContext *reshape_smooth_context, const GridCoord *grid_coord, float P[3], float tangent_matrix[3][3])
static void evaluate_base_surface_grids_callback(const MultiresReshapeSmoothContext *reshape_smooth_context, const PTexCoord *ptex_coord, const GridCoord *grid_coord, void *UNUSED(userdata_v))
struct Edge Edge
static void base_surface_grids_free(MultiresReshapeSmoothContext *reshape_smooth_context)
static void reshape_subdiv_refine_final(const MultiresReshapeSmoothContext *reshape_smooth_context)
static bool foreach_topology_info(const SubdivForeachContext *foreach_context, const int num_vertices, const int num_edges, const int num_loops, const int num_polygons)
struct LinearGridElement LinearGridElement
static float lerp(float t, float a, float b)
static void evaluate_linear_delta_grids(MultiresReshapeSmoothContext *reshape_smooth_context)
struct LinearGrids LinearGrids
static void geometry_init_loose_information(MultiresReshapeSmoothContext *reshape_smooth_context)
void() ReshapeSubdivCoarsePositionCb(const MultiresReshapeSmoothContext *reshape_smooth_context, const Vertex *vertex, float r_P[3])
static void get_edge_vertices(const OpenSubdiv_Converter *converter, const int edge_index, int edge_vertices[2])
static void foreach_vertex_every_corner(const struct SubdivForeachContext *foreach_context, void *UNUSED(tls_v), const int ptex_face_index, const float ptex_face_u, const float ptex_face_v, const int UNUSED(coarse_vertex_index), const int UNUSED(coarse_face_index), const int UNUSED(coarse_face_corner), const int subdiv_vertex_index)
static void reshape_subdiv_refine_orig(const MultiresReshapeSmoothContext *reshape_smooth_context)
static int get_num_face_vertices(const OpenSubdiv_Converter *converter, int face_index)
static void base_surface_grids_allocate(MultiresReshapeSmoothContext *reshape_smooth_context)
static void store_edge(MultiresReshapeSmoothContext *reshape_smooth_context, const int subdiv_v1, const int subdiv_v2, const char crease)
static void converter_init(const MultiresReshapeSmoothContext *reshape_smooth_context, OpenSubdiv_Converter *converter)
static void foreach_vertex_inner(const struct SubdivForeachContext *foreach_context, void *UNUSED(tls), const int ptex_face_index, const float ptex_face_u, const float ptex_face_v, const int UNUSED(coarse_poly_index), const int UNUSED(coarse_corner), const int subdiv_vertex_index)
static void evaluate_linear_delta_grids_callback(const MultiresReshapeSmoothContext *reshape_smooth_context, const PTexCoord *UNUSED(ptex_coord), const GridCoord *grid_coord, void *UNUSED(userdata_v))
static void linear_grids_init(LinearGrids *linear_grids)
static int get_reshape_level_resolution(const MultiresReshapeContext *reshape_context)
static void foreach_loop(const struct SubdivForeachContext *foreach_context, void *UNUSED(tls), const int UNUSED(ptex_face_index), const float UNUSED(ptex_face_u), const float UNUSED(ptex_face_v), const int UNUSED(coarse_loop_index), const int coarse_poly_index, const int coarse_corner, const int subdiv_loop_index, const int subdiv_vertex_index, const int UNUSED(subdiv_edge_index))
static bool is_infinite_sharp_vertex(const OpenSubdiv_Converter *converter, int vertex_index)
static void reshape_subdiv_refine_orig_P(const MultiresReshapeSmoothContext *reshape_smooth_context, const Vertex *vertex, float r_P[3])
static OpenSubdiv_FVarLinearInterpolation get_fvar_linear_interpolation(const OpenSubdiv_Converter *converter)
static void evaluate_higher_grid_positions_with_details_callback(const MultiresReshapeSmoothContext *reshape_smooth_context, const PTexCoord *ptex_coord, const GridCoord *grid_coord, void *UNUSED(userdata_v))
struct Face Face
static void evaluate_final_original_point(const MultiresReshapeSmoothContext *reshape_smooth_context, const GridCoord *grid_coord, float r_orig_final_P[3])
static int get_face_grid_index(const MultiresReshapeSmoothContext *reshape_smooth_context, const Face *face)
static void geometry_create(MultiresReshapeSmoothContext *reshape_smooth_context)
static void context_free_geometry(MultiresReshapeSmoothContext *reshape_smooth_context)
static void context_free_subdiv(MultiresReshapeSmoothContext *reshape_smooth_context)
static void interpolate_grid_coord(GridCoord *result, const GridCoord *face_grid_coords[4], const float u, const float v)
static void get_face_vertices(const OpenSubdiv_Converter *converter, int face_index, int *face_vertices)
static unsigned a[3]
Definition: RandGen.cpp:92
OpenSubdiv_FVarLinearInterpolation
OpenSubdiv_VtxBoundaryInterpolation
OpenSubdiv_SchemeType
@ OSD_SCHEME_CATMARK
const Vertex * vertex
const MultiresReshapeSmoothContext * reshape_smooth_context
ForeachTopLevelGridCoordCallback callback
LinearGridElement * elements
LinearGridElement * elements_storage
unsigned int e
struct MEdge * medge
int totedge
struct MLoop * mloop
int totpoly
struct MPoly * mpoly
struct MultiresReshapeContext::@99 reshape
struct MultiresReshapeContext::@100 top
struct Subdiv * subdiv
const MultiresReshapeContext * reshape_context
eMultiresSubdivideModeType smoothing_type
struct MultiresReshapeSmoothContext::@102 geometry
int(* getNumVertexFaces)(const struct OpenSubdiv_Converter *converter, const int vertex_index)
bool(* specifiesFullTopology)(const struct OpenSubdiv_Converter *converter)
void(* freeUserData)(const struct OpenSubdiv_Converter *converter)
void(* getFaceVertices)(const struct OpenSubdiv_Converter *converter, const int face_index, int *face_vertices)
float(* getVertexSharpness)(const struct OpenSubdiv_Converter *converter, const int vertex_index)
void(* getFaceEdges)(const struct OpenSubdiv_Converter *converter, const int face_index, int *face_edges)
int(* getNumUVLayers)(const struct OpenSubdiv_Converter *converter)
int(* getNumVertexEdges)(const struct OpenSubdiv_Converter *converter, const int vertex_index)
OpenSubdiv_FVarLinearInterpolation(* getFVarLinearInterpolation)(const struct OpenSubdiv_Converter *converter)
void(* getEdgeVertices)(const struct OpenSubdiv_Converter *converter, const int edge_index, int edge_vertices[2])
OpenSubdiv_SchemeType(* getSchemeType)(const struct OpenSubdiv_Converter *converter)
bool(* isInfiniteSharpVertex)(const struct OpenSubdiv_Converter *converter, const int vertex_index)
void(* getVertexFaces)(const struct OpenSubdiv_Converter *converter, const int vertex_index, int *vertex_faces)
int(* getNumVertices)(const struct OpenSubdiv_Converter *converter)
float(* getEdgeSharpness)(const struct OpenSubdiv_Converter *converter, const int edge_index)
int(* getNumEdges)(const struct OpenSubdiv_Converter *converter)
int(* getNumFaces)(const struct OpenSubdiv_Converter *converter)
int(* getNumEdgeFaces)(const struct OpenSubdiv_Converter *converter, const int edge_index)
int(* getNumUVCoordinates)(const struct OpenSubdiv_Converter *converter)
void(* getVertexEdges)(const struct OpenSubdiv_Converter *converter, const int vertex_index, int *vertex_edges)
void(* finishUVLayer)(const struct OpenSubdiv_Converter *converter)
void(* getEdgeFaces)(const struct OpenSubdiv_Converter *converter, const int edge, int *edge_faces)
OpenSubdiv_VtxBoundaryInterpolation(* getVtxBoundaryInterpolation)(const struct OpenSubdiv_Converter *converter)
void(* precalcUVLayer)(const struct OpenSubdiv_Converter *converter, const int layer_index)
int(* getFaceCornerUVIndex)(const struct OpenSubdiv_Converter *converter, const int face_index, const int corner_index)
int(* getNumFaceVertices)(const struct OpenSubdiv_Converter *converter, const int face_index)
void(* setCoarsePositions)(struct OpenSubdiv_Evaluator *evaluator, const float *positions, const int start_vertex_index, const int num_vertices)
void(* refine)(struct OpenSubdiv_Evaluator *evaluator)
SubdivForeachTopologyInformationCb topology_info
SubdivSettings settings
Definition: BKE_subdiv.h:176
struct OpenSubdiv_Evaluator * evaluator
Definition: BKE_subdiv.h:182
SurfacePoint * points
float tangent_matrix[3][3]
GridCoord * grid_coords
int BKE_subdiv_converter_fvar_linear_from_settings(const SubdivSettings *settings)
void BKE_subdiv_converter_free(struct OpenSubdiv_Converter *converter)
int BKE_subdiv_converter_vtx_boundary_interpolation_from_settings(const SubdivSettings *settings)
BLI_INLINE float D(const float *data, const int res[3], int x, int y, int z)
Definition: voxel.c:29