51 float tangent_matrix[3][3];
65 GridCoord *grid_coords;
68 bool is_infinite_sharp;
85struct LinearGridElement {
90 LinearGridElement *elements;
104 LinearGridElement *elements_storage;
109struct MultiresReshapeSmoothContext {
110 const MultiresReshapeContext *reshape_context;
132 blender::Array<int> face_offsets;
134 blender::OffsetIndices<int>
faces()
const
136 return blender::OffsetIndices<int>(face_offsets, blender::offset_indices::NoSortCheck());
142 LinearGrids linear_delta_grids;
145 blender::BitSpan loose_base_edges;
148 blender::bke::subdiv::Subdiv *reshape_subdiv;
158 SurfaceGrid *base_surface_grids;
175static void linear_grids_init(LinearGrids *linear_grids)
177 linear_grids->num_grids = 0;
178 linear_grids->level = 0;
180 linear_grids->grids =
nullptr;
181 linear_grids->elements_storage =
nullptr;
184static void linear_grids_allocate(LinearGrids *linear_grids,
int num_grids,
int level)
187 const size_t grid_area = grid_size * grid_size;
188 const size_t num_grid_elements = num_grids * grid_area;
190 linear_grids->num_grids = num_grids;
191 linear_grids->level = level;
192 linear_grids->grid_size = grid_size;
198 for (
int i = 0;
i < num_grids; ++
i) {
199 const size_t element_offset = grid_area *
i;
200 linear_grids->grids[
i].elements = &linear_grids->elements_storage[element_offset];
204static LinearGridElement *linear_grid_element_get(
const LinearGrids *linear_grids,
210 const int grid_size = linear_grids->grid_size;
212 const int grid_x = lround(grid_coord->
u * (grid_size - 1));
213 const int grid_y = lround(grid_coord->
v * (grid_size - 1));
214 const int grid_element_index = grid_y * grid_size + grid_x;
216 LinearGrid *grid = &linear_grids->grids[grid_coord->
grid_index];
217 return &grid->elements[grid_element_index];
220static void linear_grids_free(LinearGrids *linear_grids)
226static void linear_grid_element_init(LinearGridElement *linear_grid_element)
228 linear_grid_element->mask = 0.0f;
232static void linear_grid_element_sub(LinearGridElement *
result,
233 const LinearGridElement *a,
234 const LinearGridElement *
b)
236 result->mask = a->mask -
b->mask;
239static void linear_grid_element_interpolate(LinearGridElement *
result,
240 const LinearGridElement elements[4],
241 const float weights[4])
243 result->mask = elements[0].mask * weights[0] + elements[1].mask * weights[1] +
244 elements[2].mask * weights[2] + elements[3].mask * weights[3];
253static void base_surface_grids_allocate(MultiresReshapeSmoothContext *reshape_smooth_context)
257 const int num_grids = reshape_context->
num_grids;
259 const int grid_area = grid_size * grid_size;
263 for (
int grid_index = 0; grid_index < num_grids; ++grid_index) {
267 reshape_smooth_context->base_surface_grids = surface_grid;
270static void base_surface_grids_free(MultiresReshapeSmoothContext *reshape_smooth_context)
272 if (reshape_smooth_context->base_surface_grids ==
nullptr) {
278 const int num_grids = reshape_context->
num_grids;
279 for (
int grid_index = 0; grid_index < num_grids; ++grid_index) {
280 MEM_freeN(reshape_smooth_context->base_surface_grids[grid_index].points);
282 MEM_freeN(reshape_smooth_context->base_surface_grids);
285static SurfacePoint *base_surface_grids_read(
286 const MultiresReshapeSmoothContext *reshape_smooth_context,
const GridCoord *grid_coord)
290 const int grid_index = grid_coord->
grid_index;
292 const int grid_x = lround(grid_coord->
u * (grid_size - 1));
293 const int grid_y = lround(grid_coord->
v * (grid_size - 1));
294 const int grid_element_index = grid_y * grid_size + grid_x;
296 SurfaceGrid *surface_grid = &reshape_smooth_context->base_surface_grids[grid_index];
297 return &surface_grid->points[grid_element_index];
300static void base_surface_grids_write(
const MultiresReshapeSmoothContext *reshape_smooth_context,
303 float tangent_matrix[3][3])
305 SurfacePoint *point = base_surface_grids_read(reshape_smooth_context, grid_coord);
307 copy_m3_m3(point->tangent_matrix, tangent_matrix);
317static int get_face_grid_index(
const MultiresReshapeSmoothContext *reshape_smooth_context,
320 const Corner *first_corner = &reshape_smooth_context->geometry.corners[face.
start()];
321 const int grid_index = first_corner->grid_index;
324 for (
const int corner_index : face) {
325 const Corner *corner = &reshape_smooth_context->geometry.corners[corner_index];
333static GridCoord *vertex_grid_coord_with_grid_index(
const Vertex *vertex,
const int grid_index)
335 for (
int i = 0;
i < vertex->num_grid_coords; ++
i) {
336 if (vertex->grid_coords[
i].grid_index == grid_index) {
337 return &vertex->grid_coords[
i];
345static void grid_coords_from_face_verts(
const MultiresReshapeSmoothContext *reshape_smooth_context,
351 const int grid_index = get_face_grid_index(reshape_smooth_context, face);
355 const int corner_index = face[
i];
356 const Corner *corner = &reshape_smooth_context->geometry.corners[corner_index];
357 grid_coords[
i] = vertex_grid_coord_with_grid_index(corner->vertex, grid_index);
366static float lerp_f(
float t,
float a,
float b)
368 return (a + t * (
b - a));
388 const float u01 = lerp_f(u, face_grid_coords[0]->u, face_grid_coords[1]->u);
389 const float u32 = lerp_f(u, face_grid_coords[3]->u, face_grid_coords[2]->u);
391 const float v03 = lerp_f(
v, face_grid_coords[0]->
v, face_grid_coords[3]->
v);
392 const float v12 = lerp_f(
v, face_grid_coords[1]->
v, face_grid_coords[2]->
v);
395 result->u = lerp_f(
v, u01, u32);
396 result->v = lerp_f(u, v03, v12);
399static void foreach_toplevel_grid_coord(
400 const MultiresReshapeSmoothContext *reshape_smooth_context,
407 const int inner_grid_size = (1 << level_difference) + 1;
408 const float inner_grid_size_1_inv = 1.0f / float(inner_grid_size - 1);
412 for (const int face_index : range) {
413 const blender::IndexRange face = faces[face_index];
414 const GridCoord *face_grid_coords[4];
415 grid_coords_from_face_verts(reshape_smooth_context, face, face_grid_coords);
417 for (int y = 0; y < inner_grid_size; ++y) {
418 const float ptex_v = float(y) * inner_grid_size_1_inv;
419 for (int x = 0; x < inner_grid_size; ++x) {
420 const float ptex_u = float(x) * inner_grid_size_1_inv;
422 PTexCoord ptex_coord;
423 ptex_coord.ptex_face_index = face_index;
424 ptex_coord.u = ptex_u;
425 ptex_coord.v = ptex_v;
427 GridCoord grid_coord;
428 interpolate_grid_coord(&grid_coord, face_grid_coords, ptex_u, ptex_v);
430 callback(&ptex_coord, &grid_coord);
451static bool is_crease_supported(
const MultiresReshapeSmoothContext *reshape_smooth_context)
453 return !
ELEM(reshape_smooth_context->smoothing_type,
460static float get_effective_crease(
const MultiresReshapeSmoothContext *reshape_smooth_context,
461 const int base_edge_index)
463 if (!is_crease_supported(reshape_smooth_context)) {
466 if (reshape_smooth_context->reshape_context->cd_edge_crease.is_empty()) {
469 return reshape_smooth_context->reshape_context->cd_edge_crease[base_edge_index];
472static float get_effective_crease_float(
const MultiresReshapeSmoothContext *reshape_smooth_context,
475 if (!is_crease_supported(reshape_smooth_context)) {
481static void context_init(MultiresReshapeSmoothContext *reshape_smooth_context,
485 reshape_smooth_context->reshape_context = reshape_context;
487 reshape_smooth_context->geometry.num_vertices = 0;
488 reshape_smooth_context->geometry.vertices =
nullptr;
490 reshape_smooth_context->geometry.max_edges = 0;
491 reshape_smooth_context->geometry.num_edges = 0;
492 reshape_smooth_context->geometry.edges =
nullptr;
494 reshape_smooth_context->geometry.num_corners = 0;
495 reshape_smooth_context->geometry.corners =
nullptr;
497 reshape_smooth_context->geometry.num_faces = 0;
499 linear_grids_init(&reshape_smooth_context->linear_delta_grids);
501 reshape_smooth_context->loose_base_edges = {};
502 reshape_smooth_context->reshape_subdiv =
nullptr;
503 reshape_smooth_context->base_surface_grids =
nullptr;
505 reshape_smooth_context->smoothing_type = mode;
508static void context_free_geometry(MultiresReshapeSmoothContext *reshape_smooth_context)
510 if (reshape_smooth_context->geometry.vertices !=
nullptr) {
511 for (
int i = 0;
i < reshape_smooth_context->geometry.num_vertices; ++
i) {
512 MEM_SAFE_FREE(reshape_smooth_context->geometry.vertices[
i].grid_coords);
517 reshape_smooth_context->geometry.face_offsets = {};
520 linear_grids_free(&reshape_smooth_context->linear_delta_grids);
523static void context_free_subdiv(MultiresReshapeSmoothContext *reshape_smooth_context)
525 if (reshape_smooth_context->reshape_subdiv ==
nullptr) {
531static void context_free(MultiresReshapeSmoothContext *reshape_smooth_context)
533 context_free_geometry(reshape_smooth_context);
534 context_free_subdiv(reshape_smooth_context);
535 base_surface_grids_free(reshape_smooth_context);
539 const int num_vertices,
545 MultiresReshapeSmoothContext *reshape_smooth_context =
546 static_cast<MultiresReshapeSmoothContext *
>(foreach_context->
user_data);
547 const int max_edges = reshape_smooth_context->smoothing_type ==
550 reshape_smooth_context->geometry.max_edges;
553 reshape_smooth_context->geometry.num_vertices = num_vertices;
557 reshape_smooth_context->geometry.max_edges = max_edges;
561 reshape_smooth_context->geometry.num_corners = num_loops;
565 reshape_smooth_context->geometry.num_faces = num_faces;
566 reshape_smooth_context->geometry.face_offsets.reinitialize(num_faces + 1);
567 reshape_smooth_context->geometry.face_offsets.last() = num_loops;
574 const int coarse_vertex_index,
575 const int subdiv_vertex_index)
577 const MultiresReshapeSmoothContext *reshape_smooth_context =
578 static_cast<MultiresReshapeSmoothContext *
>(foreach_context->
user_data);
582 Vertex *vertex = &reshape_smooth_context->geometry.vertices[subdiv_vertex_index];
584 vertex->grid_coords =
static_cast<GridCoord *
>(
586 vertex->grid_coords[vertex->num_grid_coords] = *grid_coord;
587 ++vertex->num_grid_coords;
589 if (coarse_vertex_index == -1) {
599 if (crease == 0.0f) {
603 crease = get_effective_crease_float(reshape_smooth_context, crease);
610 const int coarse_vertex_index,
611 const int subdiv_vertex_index)
613 const MultiresReshapeSmoothContext *reshape_smooth_context =
614 static_cast<const MultiresReshapeSmoothContext *
>(foreach_context->
user_data);
621 const int num_corners = reshape_context->
base_faces[face_index].size();
623 const int corner = grid_coord.
grid_index - start_grid_index;
625 if (grid_coord.
u == 0.0f && grid_coord.
v == 0.0f) {
626 for (
int current_corner = 0; current_corner < num_corners; ++current_corner) {
627 GridCoord corner_grid_coord = grid_coord;
628 corner_grid_coord.
grid_index = start_grid_index + current_corner;
629 foreach_single_vertex(
630 foreach_context, &corner_grid_coord, coarse_vertex_index, subdiv_vertex_index);
635 foreach_single_vertex(foreach_context, &grid_coord, coarse_vertex_index, subdiv_vertex_index);
637 if (grid_coord.
u == 0.0f) {
639 prev_grid_coord.
grid_index = start_grid_index + ((corner + num_corners - 1) % num_corners);
640 prev_grid_coord.
u = grid_coord.
v;
641 prev_grid_coord.
v = 0.0f;
643 foreach_single_vertex(
644 foreach_context, &prev_grid_coord, coarse_vertex_index, subdiv_vertex_index);
647 if (grid_coord.
v == 0.0f) {
649 next_grid_coord.
grid_index = start_grid_index + ((corner + 1) % num_corners);
650 next_grid_coord.
u = 0.0f;
651 next_grid_coord.
v = grid_coord.
u;
653 foreach_single_vertex(
654 foreach_context, &next_grid_coord, coarse_vertex_index, subdiv_vertex_index);
660 const int ptex_face_index,
661 const float ptex_face_u,
662 const float ptex_face_v,
665 const int subdiv_vertex_index)
669 ptex_coord.
u = ptex_face_u;
670 ptex_coord.
v = ptex_face_v;
671 foreach_vertex(foreach_context, &ptex_coord, -1, subdiv_vertex_index);
674static void foreach_vertex_every_corner(
677 const int ptex_face_index,
678 const float ptex_face_u,
679 const float ptex_face_v,
680 const int coarse_vertex_index,
683 const int subdiv_vertex_index)
687 ptex_coord.
u = ptex_face_u;
688 ptex_coord.
v = ptex_face_v;
689 foreach_vertex(foreach_context, &ptex_coord, coarse_vertex_index, subdiv_vertex_index);
694 const int ptex_face_index,
695 const float ptex_face_u,
696 const float ptex_face_v,
700 const int subdiv_vertex_index)
704 ptex_coord.
u = ptex_face_u;
705 ptex_coord.
v = ptex_face_v;
706 foreach_vertex(foreach_context, &ptex_coord, -1, subdiv_vertex_index);
715 const int coarse_face_index,
716 const int coarse_corner,
717 const int subdiv_loop_index,
718 const int subdiv_vertex_index,
721 const MultiresReshapeSmoothContext *reshape_smooth_context =
722 static_cast<const MultiresReshapeSmoothContext *
>(foreach_context->
user_data);
727 Corner *corner = &reshape_smooth_context->geometry.corners[subdiv_loop_index];
728 corner->vertex = &reshape_smooth_context->geometry.vertices[subdiv_vertex_index];
731 corner->grid_index = first_grid_index + coarse_corner;
737 const int subdiv_face_index,
738 const int start_loop_index,
741 MultiresReshapeSmoothContext *reshape_smooth_context =
742 static_cast<MultiresReshapeSmoothContext *
>(foreach_context->
user_data);
746 reshape_smooth_context->geometry.face_offsets[subdiv_face_index] = start_loop_index;
749static void foreach_vertex_of_loose_edge(
754 const int vertex_index)
756 const MultiresReshapeSmoothContext *reshape_smooth_context =
757 static_cast<const MultiresReshapeSmoothContext *
>(foreach_context->
user_data);
758 Vertex *vertex = &reshape_smooth_context->geometry.vertices[vertex_index];
760 if (vertex->num_grid_coords != 0) {
761 vertex->is_infinite_sharp =
true;
765static void store_edge(MultiresReshapeSmoothContext *reshape_smooth_context,
775 Edge *edge = &reshape_smooth_context->geometry.edges[edge_index];
776 edge->v1 = subdiv_v1;
777 edge->v2 = subdiv_v2;
783 const int coarse_edge_index,
789 MultiresReshapeSmoothContext *reshape_smooth_context =
790 static_cast<MultiresReshapeSmoothContext *
>(foreach_context->
user_data);
794 store_edge(reshape_smooth_context, subdiv_v1, subdiv_v2, 1.0f);
804 if (!reshape_smooth_context->loose_base_edges.is_empty()) {
805 if (reshape_smooth_context->loose_base_edges[coarse_edge_index]) {
810 const float crease = get_effective_crease(reshape_smooth_context, coarse_edge_index);
811 if (crease == 0.0f) {
814 store_edge(reshape_smooth_context, subdiv_v1, subdiv_v2, crease);
817static void geometry_init_loose_information(MultiresReshapeSmoothContext *reshape_smooth_context)
823 reshape_smooth_context->loose_base_edges = loose_edges.
is_loose_bits;
825 int num_used_edges = 0;
830 const float crease = get_effective_crease(reshape_smooth_context, edge);
831 if (crease == 0.0f) {
837 const int resolution = get_reshape_level_resolution(reshape_context);
838 const int num_subdiv_vertices_per_base_edge = resolution - 2;
839 reshape_smooth_context->geometry.max_edges = num_used_edges *
840 (num_subdiv_vertices_per_base_edge + 1);
843static void geometry_create(MultiresReshapeSmoothContext *reshape_smooth_context)
852 foreach_context.
loop = foreach_loop;
853 foreach_context.
poly = foreach_poly;
855 foreach_context.
edge = foreach_edge;
856 foreach_context.
user_data = reshape_smooth_context;
858 geometry_init_loose_information(reshape_smooth_context);
861 mesh_settings.
resolution = get_reshape_level_resolution(reshape_context);
866 reshape_context->
subdiv, &foreach_context, &mesh_settings, reshape_context->
base_mesh);
883 const MultiresReshapeSmoothContext *reshape_smooth_context =
884 static_cast<const MultiresReshapeSmoothContext *
>(converter->
user_data);
895 const MultiresReshapeSmoothContext *reshape_smooth_context =
896 static_cast<const MultiresReshapeSmoothContext *
>(converter->
user_data);
911 const MultiresReshapeSmoothContext *reshape_smooth_context =
912 static_cast<const MultiresReshapeSmoothContext *
>(converter->
user_data);
914 return reshape_smooth_context->geometry.num_vertices;
921 const MultiresReshapeSmoothContext *reshape_smooth_context =
922 static_cast<const MultiresReshapeSmoothContext *
>(converter->
user_data);
928 const int corner_index = face[
i];
929 const Corner *corner = &reshape_smooth_context->geometry.corners[corner_index];
930 face_vertices[
i] = corner->vertex - reshape_smooth_context->geometry.vertices;
936 const MultiresReshapeSmoothContext *reshape_smooth_context =
937 static_cast<const MultiresReshapeSmoothContext *
>(converter->
user_data);
938 return reshape_smooth_context->geometry.num_edges;
942 const int edge_index,
943 int edge_vertices[2])
945 const MultiresReshapeSmoothContext *reshape_smooth_context =
946 static_cast<const MultiresReshapeSmoothContext *
>(converter->
user_data);
949 const Edge *edge = &reshape_smooth_context->geometry.edges[edge_index];
950 edge_vertices[0] = edge->v1;
951 edge_vertices[1] = edge->v2;
956 const MultiresReshapeSmoothContext *reshape_smooth_context =
957 static_cast<const MultiresReshapeSmoothContext *
>(converter->
user_data);
960 const Edge *edge = &reshape_smooth_context->geometry.edges[edge_index];
961 return edge->sharpness;
966 const MultiresReshapeSmoothContext *reshape_smooth_context =
967 static_cast<const MultiresReshapeSmoothContext *
>(converter->
user_data);
970 const Vertex *vertex = &reshape_smooth_context->geometry.vertices[vertex_index];
971 return vertex->sharpness;
976 const MultiresReshapeSmoothContext *reshape_smooth_context =
977 static_cast<const MultiresReshapeSmoothContext *
>(converter->
user_data);
981 const Vertex *vertex = &reshape_smooth_context->geometry.vertices[vertex_index];
982 return vertex->is_infinite_sharp;
985static void converter_init(
const MultiresReshapeSmoothContext *reshape_smooth_context,
993 converter->
faces = reshape_smooth_context->geometry.faces();
1021 converter->
user_data = (
void *)reshape_smooth_context;
1025static void reshape_subdiv_create(MultiresReshapeSmoothContext *reshape_smooth_context)
1031 converter_init(reshape_smooth_context, &converter);
1034 settings, &converter);
1040 &evaluator_settings);
1042 reshape_smooth_context->reshape_subdiv = reshape_subdiv;
1048using ReshapeSubdivCoarsePositionCb =
1049 void(
const MultiresReshapeSmoothContext *reshape_smooth_context,
1054static void reshape_subdiv_refine(
const MultiresReshapeSmoothContext *reshape_smooth_context,
1055 ReshapeSubdivCoarsePositionCb coarse_position_cb)
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];
1065 coarse_position_cb(reshape_smooth_context, vertex,
P);
1073 if (vertex->num_grid_coords == 0) {
1081 return &vertex->grid_coords[0];
1085static void reshape_subdiv_refine_orig_P(
1086 const MultiresReshapeSmoothContext *reshape_smooth_context,
const Vertex *vertex,
float r_P[3])
1089 const GridCoord *grid_coord = reshape_subdiv_refine_vertex_grid_coord(vertex);
1092 if (grid_coord ==
nullptr) {
1098 float tangent_matrix[3][3];
1109static void reshape_subdiv_refine_orig(
const MultiresReshapeSmoothContext *reshape_smooth_context)
1111 reshape_subdiv_refine(reshape_smooth_context, reshape_subdiv_refine_orig_P);
1115static void reshape_subdiv_refine_final_P(
1116 const MultiresReshapeSmoothContext *reshape_smooth_context,
const Vertex *vertex,
float r_P[3])
1119 const GridCoord *grid_coord = reshape_subdiv_refine_vertex_grid_coord(vertex);
1122 if (grid_coord ==
nullptr) {
1128 reshape_context, grid_coord);
1134static void reshape_subdiv_refine_final(
const MultiresReshapeSmoothContext *reshape_smooth_context)
1136 reshape_subdiv_refine(reshape_smooth_context, reshape_subdiv_refine_final_P);
1139static void reshape_subdiv_evaluate_limit_at_grid(
1140 const MultiresReshapeSmoothContext *reshape_smooth_context,
1144 float r_tangent_matrix[3][3])
1148 float dPdu[3], dPdv[3];
1161 reshape_context, face_index, corner, dPdu, dPdv, r_tangent_matrix);
1170static LinearGridElement linear_grid_element_orig_get(
1171 const MultiresReshapeSmoothContext *reshape_smooth_context,
const GridCoord *grid_coord)
1177 LinearGridElement linear_grid_element;
1178 linear_grid_element_init(&linear_grid_element);
1180 linear_grid_element.mask = orig_grid_element.
mask;
1182 return linear_grid_element;
1185static LinearGridElement linear_grid_element_final_get(
1186 const MultiresReshapeSmoothContext *reshape_smooth_context,
const GridCoord *grid_coord)
1190 reshape_context, grid_coord);
1192 LinearGridElement linear_grid_element;
1193 linear_grid_element_init(&linear_grid_element);
1195 if (final_grid_element.
mask !=
nullptr) {
1196 linear_grid_element.mask = *final_grid_element.
mask;
1199 return linear_grid_element;
1207static void linear_grid_element_delta_interpolate(
1208 const MultiresReshapeSmoothContext *reshape_smooth_context,
1210 LinearGridElement *
result)
1214 const int reshape_level = reshape_context->
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);
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;
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);
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}};
1229 LinearGridElement corner_elements[4];
1230 for (
int i = 0;
i < 4; ++
i) {
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;
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);
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};
1247 linear_grid_element_interpolate(
result, corner_elements, weights);
1250static void evaluate_linear_delta_grids(MultiresReshapeSmoothContext *reshape_smooth_context)
1253 const int num_grids = reshape_context->
num_grids;
1254 const int top_level = reshape_context->
top.
level;
1256 linear_grids_allocate(&reshape_smooth_context->linear_delta_grids, num_grids, top_level);
1258 foreach_toplevel_grid_coord(reshape_smooth_context,
1260 LinearGridElement *linear_delta_element = linear_grid_element_get(
1261 &reshape_smooth_context->linear_delta_grids, grid_coord);
1263 linear_grid_element_delta_interpolate(
1264 reshape_smooth_context, grid_coord, linear_delta_element);
1268static void propagate_linear_data_delta(
const MultiresReshapeSmoothContext *reshape_smooth_context,
1274 LinearGridElement *linear_delta_element = linear_grid_element_get(
1275 &reshape_smooth_context->linear_delta_grids, grid_coord);
1280 if (final_grid_element->
mask !=
nullptr) {
1282 orig_grid_element.
mask + linear_delta_element->mask, 0.0f, 1.0f);
1292static void evaluate_base_surface_grids(
const MultiresReshapeSmoothContext *reshape_smooth_context)
1294 foreach_toplevel_grid_coord(
1295 reshape_smooth_context, [&](
const PTexCoord *ptex_coord,
const GridCoord *grid_coord) {
1297 float tangent_matrix[3][3];
1298 reshape_subdiv_evaluate_limit_at_grid(
1299 reshape_smooth_context, ptex_coord, grid_coord, limit_P, tangent_matrix);
1301 base_surface_grids_write(reshape_smooth_context, grid_coord, limit_P, tangent_matrix);
1313static void evaluate_final_original_point(
1314 const MultiresReshapeSmoothContext *reshape_smooth_context,
1316 float r_orig_final_P[3])
1325 float base_mesh_limit_P[3];
1326 float base_mesh_tangent_matrix[3][3];
1328 reshape_context, grid_coord, base_mesh_limit_P, base_mesh_tangent_matrix);
1331 float orig_displacement[3];
1335 add_v3_v3v3(r_orig_final_P, base_mesh_limit_P, orig_displacement);
1338static void evaluate_higher_grid_positions_with_details(
1339 const MultiresReshapeSmoothContext *reshape_smooth_context)
1342 foreach_toplevel_grid_coord(
1343 reshape_smooth_context, [&](
const PTexCoord *ptex_coord,
const GridCoord *grid_coord) {
1345 float orig_final_P[3];
1346 evaluate_final_original_point(reshape_smooth_context, grid_coord, orig_final_P);
1349 const SurfacePoint *orig_sculpt_point = base_surface_grids_read(reshape_smooth_context,
1353 float original_detail_delta[3];
1354 sub_v3_v3v3(original_detail_delta, orig_final_P, orig_sculpt_point->P);
1358 float original_detail_delta_tangent[3];
1359 float original_sculpt_tangent_matrix_inv[3][3];
1360 invert_m3_m3(original_sculpt_tangent_matrix_inv, orig_sculpt_point->tangent_matrix);
1362 original_sculpt_tangent_matrix_inv,
1363 original_detail_delta);
1366 float smooth_limit_P[3];
1367 float smooth_tangent_matrix[3][3];
1368 reshape_subdiv_evaluate_limit_at_grid(
1369 reshape_smooth_context, ptex_coord, grid_coord, smooth_limit_P, smooth_tangent_matrix);
1372 float smooth_delta[3];
1373 mul_v3_m3v3(smooth_delta, smooth_tangent_matrix, original_detail_delta_tangent);
1379 reshape_context, grid_coord);
1384 propagate_linear_data_delta(reshape_smooth_context, &grid_element, grid_coord);
1388static void evaluate_higher_grid_positions(
1389 const MultiresReshapeSmoothContext *reshape_smooth_context)
1392 foreach_toplevel_grid_coord(
1393 reshape_smooth_context, [&](
const PTexCoord *ptex_coord,
const GridCoord *grid_coord) {
1397 reshape_context, grid_coord);
1407 propagate_linear_data_delta(reshape_smooth_context, &grid_element, grid_coord);
1422#ifdef WITH_OPENSUBDIV
1424 if (level_difference == 0) {
1429 MultiresReshapeSmoothContext reshape_smooth_context;
1438 geometry_create(&reshape_smooth_context);
1439 evaluate_linear_delta_grids(&reshape_smooth_context);
1441 reshape_subdiv_create(&reshape_smooth_context);
1443 base_surface_grids_allocate(&reshape_smooth_context);
1444 reshape_subdiv_refine_orig(&reshape_smooth_context);
1445 evaluate_base_surface_grids(&reshape_smooth_context);
1447 reshape_subdiv_refine_final(&reshape_smooth_context);
1448 evaluate_higher_grid_positions_with_details(&reshape_smooth_context);
1450 context_free(&reshape_smooth_context);
1459#ifdef WITH_OPENSUBDIV
1461 if (level_difference == 0) {
1466 MultiresReshapeSmoothContext reshape_smooth_context;
1467 context_init(&reshape_smooth_context, reshape_context, mode);
1469 geometry_create(&reshape_smooth_context);
1470 evaluate_linear_delta_grids(&reshape_smooth_context);
1472 reshape_subdiv_create(&reshape_smooth_context);
1474 reshape_subdiv_refine_final(&reshape_smooth_context);
1475 evaluate_higher_grid_positions(&reshape_smooth_context);
1477 context_free(&reshape_smooth_context);
CustomData interface, see also DNA_customdata_types.h.
MultiresSubdivideModeType
MINLINE float clamp_f(float value, float min, float max)
void copy_m3_m3(float m1[3][3], const float m2[3][3])
bool invert_m3_m3(float inverse[3][3], const float mat[3][3])
void mul_v3_m3v3(float r[3], const float M[3][3], const float a[3])
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])
Read Guarded memory(de)allocation.
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 * v2
ATTR_WARN_UNUSED_RESULT const BMVert * v
constexpr bool is_empty() const
constexpr int64_t size() const
constexpr int64_t start() const
constexpr IndexRange index_range() const
void setCoarsePositions(const float *positions, const int start_vertex_index, const int num_vertices)
#define MEM_reallocN(vmemh, len)
void * MEM_calloc_arrayN(size_t len, size_t size, const char *str)
void * MEM_malloc_arrayN(size_t len, size_t size, const char *str)
void MEM_freeN(void *vmemh)
ccl_device_inline float2 mask(const MaskType mask, const float2 a)
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)
void multires_reshape_tangent_matrix_for_corner(const MultiresReshapeContext *reshape_context, int face_index, int corner, const float dPdu[3], const float dPdv[3], float r_tangent_matrix[3][3])
int multires_reshape_grid_to_corner(const MultiresReshapeContext *reshape_context, int grid_index)
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_with_details(const MultiresReshapeContext *reshape_context)
void multires_reshape_smooth_object_grids(const MultiresReshapeContext *reshape_context, const MultiresSubdivideModeType mode)
void free(Subdiv *subdiv)
BLI_INLINE float crease_to_sharpness(float crease)
int converter_fvar_linear_from_settings(const Settings *settings)
bool foreach_subdiv_geometry(Subdiv *subdiv, const ForeachContext *context, const ToMeshSettings *mesh_settings, const Mesh *coarse_mesh)
void eval_limit_point(Subdiv *subdiv, int ptex_face_index, float u, float v, float r_P[3])
void eval_limit_point_and_derivatives(Subdiv *subdiv, int ptex_face_index, float u, float v, float r_P[3], float r_dPdu[3], float r_dPdv[3])
int converter_vtx_boundary_interpolation_from_settings(const Settings *settings)
bool eval_begin(Subdiv *subdiv, eSubdivEvaluatorType evaluator_type, OpenSubdiv_EvaluatorCache *evaluator_cache, const OpenSubdiv_EvaluatorSettings *settings)
BLI_INLINE int grid_size_from_level(int level)
Subdiv * new_from_converter(const Settings *settings, OpenSubdiv_Converter *converter)
@ SUBDIV_EVALUATOR_TYPE_CPU
void converter_free(OpenSubdiv_Converter *converter)
std::array< VecBase< T, 3 >, 8 > corners(const Bounds< VecBase< T, 3 > > &bounds)
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
OpenSubdiv_FVarLinearInterpolation
OpenSubdiv_VtxBoundaryInterpolation
struct MultiresReshapeContext::@217025040031013155267033302301341011136345264200 reshape
blender::bke::subdiv::Subdiv * subdiv
int * face_start_grid_index
blender::VArraySpan< float > cd_vertex_crease
blender::OffsetIndices< int > base_faces
struct MultiresReshapeContext::@020251072072313275303356043045365232052345353114 top
int(* getFaceCornerUVIndex)(const OpenSubdiv_Converter *converter, const int face_index, const int corner_index)
void(* freeUserData)(const OpenSubdiv_Converter *converter)
int(* getNumEdges)(const OpenSubdiv_Converter *converter)
void(* precalcUVLayer)(const OpenSubdiv_Converter *converter, const int layer_index)
float(* getEdgeSharpness)(const OpenSubdiv_Converter *converter, const int edge_index)
int(* getNumVertexFaces)(const OpenSubdiv_Converter *converter, const int vertex_index)
void(* getVertexFaces)(const OpenSubdiv_Converter *converter, const int vertex_index, int *vertex_faces)
void(* getVertexEdges)(const OpenSubdiv_Converter *converter, const int vertex_index, int *vertex_edges)
OpenSubdiv_FVarLinearInterpolation(* getFVarLinearInterpolation)(const OpenSubdiv_Converter *converter)
bool(* specifiesFullTopology)(const OpenSubdiv_Converter *converter)
int(* getNumUVCoordinates)(const OpenSubdiv_Converter *converter)
void(* getFaceVertices)(const OpenSubdiv_Converter *converter, const int face_index, int *face_vertices)
OpenSubdiv_VtxBoundaryInterpolation(* getVtxBoundaryInterpolation)(const OpenSubdiv_Converter *converter)
int(* getNumUVLayers)(const OpenSubdiv_Converter *converter)
int(* getNumEdgeFaces)(const OpenSubdiv_Converter *converter, const int edge_index)
blender::OffsetIndices< int > faces
bool(* isInfiniteSharpVertex)(const OpenSubdiv_Converter *converter, const int vertex_index)
float(* getVertexSharpness)(const OpenSubdiv_Converter *converter, const int vertex_index)
OpenSubdiv_SchemeType(* getSchemeType)(const OpenSubdiv_Converter *converter)
void(* getEdgeVertices)(const OpenSubdiv_Converter *converter, const int edge_index, int edge_vertices[2])
int(* getNumVertexEdges)(const OpenSubdiv_Converter *converter, const int vertex_index)
int(* getNumVertices)(const OpenSubdiv_Converter *converter)
void(* getFaceEdges)(const OpenSubdiv_Converter *converter, const int face_index, int *face_edges)
void(* finishUVLayer)(const OpenSubdiv_Converter *converter)
void(* getEdgeFaces)(const OpenSubdiv_Converter *converter, const int edge, int *edge_faces)
blender::opensubdiv::EvalOutputAPI * eval_output
blender::BitVector is_loose_bits
ForeachVertexFromEdgeCb vertex_every_edge
ForeachTopologyInformationCb topology_info
ForeachVertexOfLooseEdgeCb vertex_of_loose_edge
ForeachVertexFromCornerCb vertex_every_corner
ForeachVertexInnerCb vertex_inner
OpenSubdiv_Evaluator * evaluator