48 float tangent_matrix[3][3];
65 bool is_infinite_sharp;
74 int start_corner_index;
87struct LinearGridElement {
92 LinearGridElement *elements;
106 LinearGridElement *elements_storage;
111struct MultiresReshapeSmoothContext {
138 LinearGrids linear_delta_grids;
154 SurfaceGrid *base_surface_grids;
171static void linear_grids_init(LinearGrids *linear_grids)
173 linear_grids->num_grids = 0;
174 linear_grids->level = 0;
176 linear_grids->grids =
nullptr;
177 linear_grids->elements_storage =
nullptr;
180static void linear_grids_allocate(LinearGrids *linear_grids,
int num_grids,
int level)
183 const size_t grid_area = grid_size * grid_size;
184 const size_t num_grid_elements = num_grids * grid_area;
186 linear_grids->num_grids = num_grids;
187 linear_grids->level = level;
188 linear_grids->grid_size = grid_size;
190 linear_grids->grids =
static_cast<LinearGrid *
>(
192 linear_grids->elements_storage =
static_cast<LinearGridElement *
>(
195 for (
int i = 0; i < num_grids; ++i) {
196 const size_t element_offset = grid_area * i;
197 linear_grids->grids[i].elements = &linear_grids->elements_storage[element_offset];
201static LinearGridElement *linear_grid_element_get(
const LinearGrids *linear_grids,
207 const int grid_size = linear_grids->grid_size;
209 const int grid_x = lround(grid_coord->
u * (grid_size - 1));
210 const int grid_y = lround(grid_coord->
v * (grid_size - 1));
211 const int grid_element_index = grid_y * grid_size + grid_x;
213 LinearGrid *grid = &linear_grids->grids[grid_coord->
grid_index];
214 return &grid->elements[grid_element_index];
217static void linear_grids_free(LinearGrids *linear_grids)
223static void linear_grid_element_init(LinearGridElement *linear_grid_element)
225 linear_grid_element->mask = 0.0f;
229static void linear_grid_element_sub(LinearGridElement *result,
230 const LinearGridElement *a,
231 const LinearGridElement *
b)
233 result->mask = a->mask -
b->mask;
236static void linear_grid_element_interpolate(LinearGridElement *result,
237 const LinearGridElement elements[4],
238 const float weights[4])
240 result->mask = elements[0].mask * weights[0] + elements[1].mask * weights[1] +
241 elements[2].mask * weights[2] + elements[3].mask * weights[3];
250static void base_surface_grids_allocate(MultiresReshapeSmoothContext *reshape_smooth_context)
254 const int num_grids = reshape_context->
num_grids;
256 const int grid_area = grid_size * grid_size;
258 SurfaceGrid *surface_grid =
static_cast<SurfaceGrid *
>(
261 for (
int grid_index = 0; grid_index < num_grids; ++grid_index) {
262 surface_grid[grid_index].points =
static_cast<SurfacePoint *
>(
266 reshape_smooth_context->base_surface_grids = surface_grid;
269static void base_surface_grids_free(MultiresReshapeSmoothContext *reshape_smooth_context)
271 if (reshape_smooth_context->base_surface_grids ==
nullptr) {
277 const int num_grids = reshape_context->
num_grids;
278 for (
int grid_index = 0; grid_index < num_grids; ++grid_index) {
279 MEM_freeN(reshape_smooth_context->base_surface_grids[grid_index].points);
281 MEM_freeN(reshape_smooth_context->base_surface_grids);
284static SurfacePoint *base_surface_grids_read(
285 const MultiresReshapeSmoothContext *reshape_smooth_context,
const GridCoord *grid_coord)
289 const int grid_index = grid_coord->
grid_index;
291 const int grid_x = lround(grid_coord->
u * (grid_size - 1));
292 const int grid_y = lround(grid_coord->
v * (grid_size - 1));
293 const int grid_element_index = grid_y * grid_size + grid_x;
295 SurfaceGrid *surface_grid = &reshape_smooth_context->base_surface_grids[grid_index];
296 return &surface_grid->points[grid_element_index];
299static void base_surface_grids_write(
const MultiresReshapeSmoothContext *reshape_smooth_context,
302 float tangent_matrix[3][3])
304 SurfacePoint *point = base_surface_grids_read(reshape_smooth_context, grid_coord);
306 copy_m3_m3(point->tangent_matrix, tangent_matrix);
316static int get_face_grid_index(
const MultiresReshapeSmoothContext *reshape_smooth_context,
319 const Corner *first_corner = &reshape_smooth_context->geometry.corners[face->start_corner_index];
320 const int grid_index = first_corner->grid_index;
323 for (
int face_corner = 0; face_corner < face->num_corners; ++face_corner) {
324 const int corner_index = face->start_corner_index + face_corner;
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);
354 for (
int i = 0; i < face->num_corners; ++i) {
355 const int corner_index = face->start_corner_index + 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);
362static float lerp(
float t,
float a,
float b)
364 return (a + t * (
b - a));
367static void interpolate_grid_coord(
GridCoord *result,
384 const float u01 =
lerp(u, face_grid_coords[0]->u, face_grid_coords[1]->u);
385 const float u32 =
lerp(u, face_grid_coords[3]->u, face_grid_coords[2]->u);
387 const float v03 =
lerp(
v, face_grid_coords[0]->
v, face_grid_coords[3]->
v);
388 const float v12 =
lerp(
v, face_grid_coords[1]->
v, face_grid_coords[2]->
v);
390 result->grid_index = face_grid_coords[0]->
grid_index;
391 result->u =
lerp(
v, u01, u32);
392 result->v =
lerp(u, v03, v12);
395static void foreach_toplevel_grid_coord(
396 const MultiresReshapeSmoothContext *reshape_smooth_context,
403 const int inner_grid_size = (1 << level_difference) + 1;
404 const float inner_grid_size_1_inv = 1.0f /
float(inner_grid_size - 1);
406 const int num_faces = reshape_smooth_context->geometry.num_faces;
408 for (
const int face_index : range) {
409 const Face *face = &reshape_smooth_context->geometry.faces[face_index];
411 grid_coords_from_face_verts(reshape_smooth_context, face, face_grid_coords);
413 for (
int y = 0; y < inner_grid_size; ++
y) {
414 const float ptex_v =
float(y) * inner_grid_size_1_inv;
415 for (
int x = 0; x < inner_grid_size; ++
x) {
416 const float ptex_u =
float(x) * inner_grid_size_1_inv;
420 ptex_coord.
u = ptex_u;
421 ptex_coord.
v = ptex_v;
424 interpolate_grid_coord(&grid_coord, face_grid_coords, ptex_u, ptex_v);
447static bool is_crease_supported(
const MultiresReshapeSmoothContext *reshape_smooth_context)
449 return !
ELEM(reshape_smooth_context->smoothing_type,
456static float get_effective_crease(
const MultiresReshapeSmoothContext *reshape_smooth_context,
457 const int base_edge_index)
459 if (!is_crease_supported(reshape_smooth_context)) {
462 if (reshape_smooth_context->reshape_context->cd_edge_crease.is_empty()) {
465 return reshape_smooth_context->reshape_context->cd_edge_crease[base_edge_index];
468static float get_effective_crease_float(
const MultiresReshapeSmoothContext *reshape_smooth_context,
471 if (!is_crease_supported(reshape_smooth_context)) {
477static void context_init(MultiresReshapeSmoothContext *reshape_smooth_context,
481 reshape_smooth_context->reshape_context = reshape_context;
483 reshape_smooth_context->geometry.num_vertices = 0;
484 reshape_smooth_context->geometry.vertices =
nullptr;
486 reshape_smooth_context->geometry.max_edges = 0;
487 reshape_smooth_context->geometry.num_edges = 0;
488 reshape_smooth_context->geometry.edges =
nullptr;
490 reshape_smooth_context->geometry.num_corners = 0;
491 reshape_smooth_context->geometry.corners =
nullptr;
493 reshape_smooth_context->geometry.num_faces = 0;
494 reshape_smooth_context->geometry.faces =
nullptr;
496 linear_grids_init(&reshape_smooth_context->linear_delta_grids);
498 reshape_smooth_context->loose_base_edges = {};
499 reshape_smooth_context->reshape_subdiv =
nullptr;
500 reshape_smooth_context->base_surface_grids =
nullptr;
502 reshape_smooth_context->smoothing_type = mode;
505static void context_free_geometry(MultiresReshapeSmoothContext *reshape_smooth_context)
507 if (reshape_smooth_context->geometry.vertices !=
nullptr) {
508 for (
int i = 0; i < reshape_smooth_context->geometry.num_vertices; ++i) {
509 MEM_SAFE_FREE(reshape_smooth_context->geometry.vertices[i].grid_coords);
517 linear_grids_free(&reshape_smooth_context->linear_delta_grids);
520static void context_free_subdiv(MultiresReshapeSmoothContext *reshape_smooth_context)
522 if (reshape_smooth_context->reshape_subdiv ==
nullptr) {
528static void context_free(MultiresReshapeSmoothContext *reshape_smooth_context)
530 context_free_geometry(reshape_smooth_context);
531 context_free_subdiv(reshape_smooth_context);
532 base_surface_grids_free(reshape_smooth_context);
536 const int num_vertices,
542 MultiresReshapeSmoothContext *reshape_smooth_context =
543 static_cast<MultiresReshapeSmoothContext *
>(foreach_context->
user_data);
546 reshape_smooth_context->geometry.max_edges;
549 reshape_smooth_context->geometry.num_vertices = num_vertices;
550 reshape_smooth_context->geometry.vertices =
static_cast<Vertex *
>(
553 reshape_smooth_context->geometry.max_edges = max_edges;
554 reshape_smooth_context->geometry.edges =
static_cast<Edge *
>(
557 reshape_smooth_context->geometry.num_corners = num_loops;
558 reshape_smooth_context->geometry.corners =
static_cast<Corner *
>(
561 reshape_smooth_context->geometry.num_faces = num_faces;
562 reshape_smooth_context->geometry.faces =
static_cast<Face *
>(
570 const int coarse_vertex_index,
571 const int subdiv_vertex_index)
573 const MultiresReshapeSmoothContext *reshape_smooth_context =
574 static_cast<MultiresReshapeSmoothContext *
>(foreach_context->
user_data);
576 BLI_assert(subdiv_vertex_index < reshape_smooth_context->geometry.num_vertices);
578 Vertex *vertex = &reshape_smooth_context->geometry.vertices[subdiv_vertex_index];
580 vertex->grid_coords =
static_cast<GridCoord *
>(
581 MEM_reallocN(vertex->grid_coords,
sizeof(Vertex) * (vertex->num_grid_coords + 1)));
582 vertex->grid_coords[vertex->num_grid_coords] = *grid_coord;
583 ++vertex->num_grid_coords;
585 if (coarse_vertex_index == -1) {
595 if (crease == 0.0f) {
599 crease = get_effective_crease_float(reshape_smooth_context, crease);
606 const int coarse_vertex_index,
607 const int subdiv_vertex_index)
609 const MultiresReshapeSmoothContext *reshape_smooth_context =
610 static_cast<const MultiresReshapeSmoothContext *
>(foreach_context->
user_data);
617 const int num_corners = reshape_context->
base_faces[face_index].size();
619 const int corner = grid_coord.
grid_index - start_grid_index;
621 if (grid_coord.
u == 0.0f && grid_coord.
v == 0.0f) {
622 for (
int current_corner = 0; current_corner < num_corners; ++current_corner) {
623 GridCoord corner_grid_coord = grid_coord;
624 corner_grid_coord.
grid_index = start_grid_index + current_corner;
625 foreach_single_vertex(
626 foreach_context, &corner_grid_coord, coarse_vertex_index, subdiv_vertex_index);
631 foreach_single_vertex(foreach_context, &grid_coord, coarse_vertex_index, subdiv_vertex_index);
633 if (grid_coord.
u == 0.0f) {
635 prev_grid_coord.
grid_index = start_grid_index + ((corner + num_corners - 1) % num_corners);
636 prev_grid_coord.u = grid_coord.
v;
637 prev_grid_coord.v = 0.0f;
639 foreach_single_vertex(
640 foreach_context, &prev_grid_coord, coarse_vertex_index, subdiv_vertex_index);
643 if (grid_coord.
v == 0.0f) {
645 next_grid_coord.
grid_index = start_grid_index + ((corner + 1) % num_corners);
646 next_grid_coord.u = 0.0f;
647 next_grid_coord.v = grid_coord.
u;
649 foreach_single_vertex(
650 foreach_context, &next_grid_coord, coarse_vertex_index, subdiv_vertex_index);
656 const int ptex_face_index,
657 const float ptex_face_u,
658 const float ptex_face_v,
661 const int subdiv_vertex_index)
665 ptex_coord.
u = ptex_face_u;
666 ptex_coord.
v = ptex_face_v;
667 foreach_vertex(foreach_context, &ptex_coord, -1, subdiv_vertex_index);
670static void foreach_vertex_every_corner(
673 const int ptex_face_index,
674 const float ptex_face_u,
675 const float ptex_face_v,
676 const int coarse_vertex_index,
679 const int subdiv_vertex_index)
683 ptex_coord.
u = ptex_face_u;
684 ptex_coord.
v = ptex_face_v;
685 foreach_vertex(foreach_context, &ptex_coord, coarse_vertex_index, subdiv_vertex_index);
690 const int ptex_face_index,
691 const float ptex_face_u,
692 const float ptex_face_v,
696 const int subdiv_vertex_index)
700 ptex_coord.
u = ptex_face_u;
701 ptex_coord.
v = ptex_face_v;
702 foreach_vertex(foreach_context, &ptex_coord, -1, subdiv_vertex_index);
711 const int coarse_face_index,
712 const int coarse_corner,
713 const int subdiv_loop_index,
714 const int subdiv_vertex_index,
717 const MultiresReshapeSmoothContext *reshape_smooth_context =
718 static_cast<const MultiresReshapeSmoothContext *
>(foreach_context->
user_data);
721 BLI_assert(subdiv_loop_index < reshape_smooth_context->geometry.num_corners);
723 Corner *corner = &reshape_smooth_context->geometry.corners[subdiv_loop_index];
724 corner->vertex = &reshape_smooth_context->geometry.vertices[subdiv_vertex_index];
727 corner->grid_index = first_grid_index + coarse_corner;
733 const int subdiv_face_index,
734 const int start_loop_index,
737 const MultiresReshapeSmoothContext *reshape_smooth_context =
738 static_cast<const MultiresReshapeSmoothContext *
>(foreach_context->
user_data);
740 BLI_assert(subdiv_face_index < reshape_smooth_context->geometry.num_faces);
742 Face *face = &reshape_smooth_context->geometry.faces[subdiv_face_index];
743 face->start_corner_index = start_loop_index;
744 face->num_corners = num_loops;
747static void foreach_vertex_of_loose_edge(
752 const int vertex_index)
754 const MultiresReshapeSmoothContext *reshape_smooth_context =
755 static_cast<const MultiresReshapeSmoothContext *
>(foreach_context->
user_data);
756 Vertex *vertex = &reshape_smooth_context->geometry.vertices[vertex_index];
758 if (vertex->num_grid_coords != 0) {
759 vertex->is_infinite_sharp =
true;
763static void store_edge(MultiresReshapeSmoothContext *reshape_smooth_context,
771 BLI_assert(edge_index < reshape_smooth_context->geometry.max_edges);
773 Edge *edge = &reshape_smooth_context->geometry.edges[edge_index];
774 edge->v1 = subdiv_v1;
775 edge->v2 = subdiv_v2;
781 const int coarse_edge_index,
787 MultiresReshapeSmoothContext *reshape_smooth_context =
788 static_cast<MultiresReshapeSmoothContext *
>(foreach_context->
user_data);
792 store_edge(reshape_smooth_context, subdiv_v1, subdiv_v2, 1.0f);
802 if (!reshape_smooth_context->loose_base_edges.is_empty()) {
803 if (reshape_smooth_context->loose_base_edges[coarse_edge_index]) {
808 const float crease = get_effective_crease(reshape_smooth_context, coarse_edge_index);
809 if (crease == 0.0f) {
812 store_edge(reshape_smooth_context, subdiv_v1, subdiv_v2, crease);
815static void geometry_init_loose_information(MultiresReshapeSmoothContext *reshape_smooth_context)
821 reshape_smooth_context->loose_base_edges = loose_edges.
is_loose_bits;
823 int num_used_edges = 0;
828 const float crease = get_effective_crease(reshape_smooth_context, edge);
829 if (crease == 0.0f) {
835 const int resolution = get_reshape_level_resolution(reshape_context);
836 const int num_subdiv_vertices_per_base_edge = resolution - 2;
837 reshape_smooth_context->geometry.max_edges = num_used_edges *
838 (num_subdiv_vertices_per_base_edge + 1);
841static void geometry_create(MultiresReshapeSmoothContext *reshape_smooth_context)
850 foreach_context.
loop = foreach_loop;
851 foreach_context.
poly = foreach_poly;
853 foreach_context.
edge = foreach_edge;
854 foreach_context.
user_data = reshape_smooth_context;
856 geometry_init_loose_information(reshape_smooth_context);
859 mesh_settings.
resolution = get_reshape_level_resolution(reshape_context);
864 reshape_context->
subdiv, &foreach_context, &mesh_settings, reshape_context->
base_mesh);
881 const MultiresReshapeSmoothContext *reshape_smooth_context =
882 static_cast<const MultiresReshapeSmoothContext *
>(converter->
user_data);
893 const MultiresReshapeSmoothContext *reshape_smooth_context =
894 static_cast<const MultiresReshapeSmoothContext *
>(converter->
user_data);
909 const MultiresReshapeSmoothContext *reshape_smooth_context =
910 static_cast<const MultiresReshapeSmoothContext *
>(converter->
user_data);
912 return reshape_smooth_context->geometry.num_faces;
917 const MultiresReshapeSmoothContext *reshape_smooth_context =
918 static_cast<const MultiresReshapeSmoothContext *
>(converter->
user_data);
920 return reshape_smooth_context->geometry.num_vertices;
925 const MultiresReshapeSmoothContext *reshape_smooth_context =
926 static_cast<const MultiresReshapeSmoothContext *
>(converter->
user_data);
927 BLI_assert(face_index < reshape_smooth_context->geometry.num_faces);
929 const Face *face = &reshape_smooth_context->geometry.faces[face_index];
930 return face->num_corners;
937 const MultiresReshapeSmoothContext *reshape_smooth_context =
938 static_cast<const MultiresReshapeSmoothContext *
>(converter->
user_data);
939 BLI_assert(face_index < reshape_smooth_context->geometry.num_faces);
941 const Face *face = &reshape_smooth_context->geometry.faces[face_index];
943 for (
int i = 0; i < face->num_corners; ++i) {
944 const int corner_index = face->start_corner_index + i;
945 const Corner *corner = &reshape_smooth_context->geometry.corners[corner_index];
946 face_vertices[i] = corner->vertex - reshape_smooth_context->geometry.vertices;
952 const MultiresReshapeSmoothContext *reshape_smooth_context =
953 static_cast<const MultiresReshapeSmoothContext *
>(converter->
user_data);
954 return reshape_smooth_context->geometry.num_edges;
958 const int edge_index,
959 int edge_vertices[2])
961 const MultiresReshapeSmoothContext *reshape_smooth_context =
962 static_cast<const MultiresReshapeSmoothContext *
>(converter->
user_data);
963 BLI_assert(edge_index < reshape_smooth_context->geometry.num_edges);
965 const Edge *edge = &reshape_smooth_context->geometry.edges[edge_index];
966 edge_vertices[0] = edge->v1;
967 edge_vertices[1] = edge->v2;
972 const MultiresReshapeSmoothContext *reshape_smooth_context =
973 static_cast<const MultiresReshapeSmoothContext *
>(converter->
user_data);
974 BLI_assert(edge_index < reshape_smooth_context->geometry.num_edges);
976 const Edge *edge = &reshape_smooth_context->geometry.edges[edge_index];
977 return edge->sharpness;
982 const MultiresReshapeSmoothContext *reshape_smooth_context =
983 static_cast<const MultiresReshapeSmoothContext *
>(converter->
user_data);
984 BLI_assert(vertex_index < reshape_smooth_context->geometry.num_vertices);
986 const Vertex *vertex = &reshape_smooth_context->geometry.vertices[vertex_index];
987 return vertex->sharpness;
992 const MultiresReshapeSmoothContext *reshape_smooth_context =
993 static_cast<const MultiresReshapeSmoothContext *
>(converter->
user_data);
995 BLI_assert(vertex_index < reshape_smooth_context->geometry.num_vertices);
997 const Vertex *vertex = &reshape_smooth_context->geometry.vertices[vertex_index];
998 return vertex->is_infinite_sharp;
1001static void converter_init(
const MultiresReshapeSmoothContext *reshape_smooth_context,
1037 converter->
user_data = (
void *)reshape_smooth_context;
1041static void reshape_subdiv_create(MultiresReshapeSmoothContext *reshape_smooth_context)
1047 converter_init(reshape_smooth_context, &converter);
1050 settings, &converter);
1056 &evaluator_settings);
1058 reshape_smooth_context->reshape_subdiv = reshape_subdiv;
1064using ReshapeSubdivCoarsePositionCb =
1065 void(
const MultiresReshapeSmoothContext *reshape_smooth_context,
1066 const Vertex *vertex,
1070static void reshape_subdiv_refine(
const MultiresReshapeSmoothContext *reshape_smooth_context,
1071 ReshapeSubdivCoarsePositionCb coarse_position_cb)
1077 const int num_vertices = reshape_smooth_context->geometry.num_vertices;
1078 for (
int i = 0; i < num_vertices; ++i) {
1079 const Vertex *vertex = &reshape_smooth_context->geometry.vertices[i];
1081 coarse_position_cb(reshape_smooth_context, vertex,
P);
1089 if (vertex->num_grid_coords == 0) {
1097 return &vertex->grid_coords[0];
1101static void reshape_subdiv_refine_orig_P(
1102 const MultiresReshapeSmoothContext *reshape_smooth_context,
const Vertex *vertex,
float r_P[3])
1105 const GridCoord *grid_coord = reshape_subdiv_refine_vertex_grid_coord(vertex);
1108 if (grid_coord ==
nullptr) {
1114 float tangent_matrix[3][3];
1125static void reshape_subdiv_refine_orig(
const MultiresReshapeSmoothContext *reshape_smooth_context)
1127 reshape_subdiv_refine(reshape_smooth_context, reshape_subdiv_refine_orig_P);
1131static void reshape_subdiv_refine_final_P(
1132 const MultiresReshapeSmoothContext *reshape_smooth_context,
const Vertex *vertex,
float r_P[3])
1135 const GridCoord *grid_coord = reshape_subdiv_refine_vertex_grid_coord(vertex);
1138 if (grid_coord ==
nullptr) {
1144 reshape_context, grid_coord);
1150static void reshape_subdiv_refine_final(
const MultiresReshapeSmoothContext *reshape_smooth_context)
1152 reshape_subdiv_refine(reshape_smooth_context, reshape_subdiv_refine_final_P);
1155static void reshape_subdiv_evaluate_limit_at_grid(
1156 const MultiresReshapeSmoothContext *reshape_smooth_context,
1160 float r_tangent_matrix[3][3])
1164 float dPdu[3], dPdv[3];
1177 reshape_context, face_index, corner, dPdu, dPdv, r_tangent_matrix);
1186static LinearGridElement linear_grid_element_orig_get(
1187 const MultiresReshapeSmoothContext *reshape_smooth_context,
const GridCoord *grid_coord)
1193 LinearGridElement linear_grid_element;
1194 linear_grid_element_init(&linear_grid_element);
1196 linear_grid_element.mask = orig_grid_element.
mask;
1198 return linear_grid_element;
1201static LinearGridElement linear_grid_element_final_get(
1202 const MultiresReshapeSmoothContext *reshape_smooth_context,
const GridCoord *grid_coord)
1206 reshape_context, grid_coord);
1208 LinearGridElement linear_grid_element;
1209 linear_grid_element_init(&linear_grid_element);
1211 if (final_grid_element.
mask !=
nullptr) {
1212 linear_grid_element.mask = *final_grid_element.
mask;
1215 return linear_grid_element;
1223static void linear_grid_element_delta_interpolate(
1224 const MultiresReshapeSmoothContext *reshape_smooth_context,
1226 LinearGridElement *result)
1230 const int reshape_level = reshape_context->
reshape.
level;
1232 const int reshape_level_grid_size_1 = reshape_level_grid_size - 1;
1233 const float reshape_level_grid_size_1_inv = 1.0f /
float(reshape_level_grid_size_1);
1235 const float x_f = grid_coord->
u * reshape_level_grid_size_1;
1236 const float y_f = grid_coord->
v * reshape_level_grid_size_1;
1238 const int x_i = x_f;
1239 const int y_i = y_f;
1240 const int x_n_i = (x_i == reshape_level_grid_size - 1) ? (x_i) : (x_i + 1);
1241 const int y_n_i = (y_i == reshape_level_grid_size - 1) ? (y_i) : (y_i + 1);
1243 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}};
1245 LinearGridElement corner_elements[4];
1246 for (
int i = 0; i < 4; ++i) {
1249 corner_grid_coord.
u = corners_int_coords[i][0] * reshape_level_grid_size_1_inv;
1250 corner_grid_coord.
v = corners_int_coords[i][1] * reshape_level_grid_size_1_inv;
1252 const LinearGridElement orig_element = linear_grid_element_orig_get(reshape_smooth_context,
1253 &corner_grid_coord);
1254 const LinearGridElement final_element = linear_grid_element_final_get(reshape_smooth_context,
1255 &corner_grid_coord);
1256 linear_grid_element_sub(&corner_elements[i], &final_element, &orig_element);
1259 const float u = x_f - x_i;
1260 const float v = y_f - y_i;
1261 const float weights[4] = {(1.0f - u) * (1.0f -
v), u * (1.0f -
v), u *
v, (1.0f - u) *
v};
1263 linear_grid_element_interpolate(result, corner_elements, weights);
1266static void evaluate_linear_delta_grids(MultiresReshapeSmoothContext *reshape_smooth_context)
1269 const int num_grids = reshape_context->
num_grids;
1270 const int top_level = reshape_context->
top.
level;
1272 linear_grids_allocate(&reshape_smooth_context->linear_delta_grids, num_grids, top_level);
1274 foreach_toplevel_grid_coord(reshape_smooth_context,
1276 LinearGridElement *linear_delta_element = linear_grid_element_get(
1277 &reshape_smooth_context->linear_delta_grids, grid_coord);
1279 linear_grid_element_delta_interpolate(
1280 reshape_smooth_context, grid_coord, linear_delta_element);
1284static void propagate_linear_data_delta(
const MultiresReshapeSmoothContext *reshape_smooth_context,
1290 LinearGridElement *linear_delta_element = linear_grid_element_get(
1291 &reshape_smooth_context->linear_delta_grids, grid_coord);
1296 if (final_grid_element->
mask !=
nullptr) {
1298 orig_grid_element.
mask + linear_delta_element->mask, 0.0f, 1.0f);
1308static void evaluate_base_surface_grids(
const MultiresReshapeSmoothContext *reshape_smooth_context)
1310 foreach_toplevel_grid_coord(
1311 reshape_smooth_context, [&](
const PTexCoord *ptex_coord,
const GridCoord *grid_coord) {
1313 float tangent_matrix[3][3];
1314 reshape_subdiv_evaluate_limit_at_grid(
1315 reshape_smooth_context, ptex_coord, grid_coord, limit_P, tangent_matrix);
1317 base_surface_grids_write(reshape_smooth_context, grid_coord, limit_P, tangent_matrix);
1329static void evaluate_final_original_point(
1330 const MultiresReshapeSmoothContext *reshape_smooth_context,
1332 float r_orig_final_P[3])
1341 float base_mesh_limit_P[3];
1342 float base_mesh_tangent_matrix[3][3];
1344 reshape_context, grid_coord, base_mesh_limit_P, base_mesh_tangent_matrix);
1347 float orig_displacement[3];
1351 add_v3_v3v3(r_orig_final_P, base_mesh_limit_P, orig_displacement);
1354static void evaluate_higher_grid_positions_with_details(
1355 const MultiresReshapeSmoothContext *reshape_smooth_context)
1358 foreach_toplevel_grid_coord(
1359 reshape_smooth_context, [&](
const PTexCoord *ptex_coord,
const GridCoord *grid_coord) {
1361 float orig_final_P[3];
1362 evaluate_final_original_point(reshape_smooth_context, grid_coord, orig_final_P);
1365 const SurfacePoint *orig_sculpt_point = base_surface_grids_read(reshape_smooth_context,
1369 float original_detail_delta[3];
1370 sub_v3_v3v3(original_detail_delta, orig_final_P, orig_sculpt_point->P);
1374 float original_detail_delta_tangent[3];
1375 float original_sculpt_tangent_matrix_inv[3][3];
1376 invert_m3_m3(original_sculpt_tangent_matrix_inv, orig_sculpt_point->tangent_matrix);
1378 original_sculpt_tangent_matrix_inv,
1379 original_detail_delta);
1382 float smooth_limit_P[3];
1383 float smooth_tangent_matrix[3][3];
1384 reshape_subdiv_evaluate_limit_at_grid(
1385 reshape_smooth_context, ptex_coord, grid_coord, smooth_limit_P, smooth_tangent_matrix);
1388 float smooth_delta[3];
1389 mul_v3_m3v3(smooth_delta, smooth_tangent_matrix, original_detail_delta_tangent);
1395 reshape_context, grid_coord);
1400 propagate_linear_data_delta(reshape_smooth_context, &grid_element, grid_coord);
1404static void evaluate_higher_grid_positions(
1405 const MultiresReshapeSmoothContext *reshape_smooth_context)
1408 foreach_toplevel_grid_coord(
1409 reshape_smooth_context, [&](
const PTexCoord *ptex_coord,
const GridCoord *grid_coord) {
1413 reshape_context, grid_coord);
1423 propagate_linear_data_delta(reshape_smooth_context, &grid_element, grid_coord);
1438#ifdef WITH_OPENSUBDIV
1440 if (level_difference == 0) {
1445 MultiresReshapeSmoothContext reshape_smooth_context;
1453 geometry_create(&reshape_smooth_context);
1454 evaluate_linear_delta_grids(&reshape_smooth_context);
1456 reshape_subdiv_create(&reshape_smooth_context);
1458 base_surface_grids_allocate(&reshape_smooth_context);
1459 reshape_subdiv_refine_orig(&reshape_smooth_context);
1460 evaluate_base_surface_grids(&reshape_smooth_context);
1462 reshape_subdiv_refine_final(&reshape_smooth_context);
1463 evaluate_higher_grid_positions_with_details(&reshape_smooth_context);
1465 context_free(&reshape_smooth_context);
1474#ifdef WITH_OPENSUBDIV
1476 if (level_difference == 0) {
1481 MultiresReshapeSmoothContext reshape_smooth_context;
1482 context_init(&reshape_smooth_context, reshape_context, mode);
1484 geometry_create(&reshape_smooth_context);
1485 evaluate_linear_delta_grids(&reshape_smooth_context);
1487 reshape_subdiv_create(&reshape_smooth_context);
1489 reshape_subdiv_refine_final(&reshape_smooth_context);
1490 evaluate_higher_grid_positions(&reshape_smooth_context);
1492 context_free(&reshape_smooth_context);
CustomData interface, see also DNA_customdata_types.h.
eMultiresSubdivideModeType
@ MULTIRES_SUBDIVIDE_LINEAR
@ MULTIRES_SUBDIVIDE_CATMULL_CLARK
@ MULTIRES_SUBDIVIDE_SIMPLE
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.
#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 * v2
ATTR_WARN_UNUSED_RESULT const BMVert * v
constexpr bool is_empty() const
local_group_size(16, 16) .push_constant(Type b
DEGForeachIDComponentCallback callback
draw_view in_light_buf[] float
void *(* MEM_malloc_arrayN)(size_t len, size_t size, const char *str)
void *(* MEM_calloc_arrayN)(size_t len, size_t size, const char *str)
void MEM_freeN(void *vmemh)
ccl_device_inline float4 mask(const int4 mask, const float4 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(const MultiresReshapeContext *reshape_context, const eMultiresSubdivideModeType mode)
void multires_reshape_smooth_object_grids_with_details(const MultiresReshapeContext *reshape_context)
void free(Subdiv *subdiv)
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)
BLI_INLINE float crease_to_sharpness(float edge_crease)
Subdiv * new_from_converter(const Settings *settings, OpenSubdiv_Converter *converter)
@ SUBDIV_EVALUATOR_TYPE_CPU
void converter_free(OpenSubdiv_Converter *converter)
OpenSubdiv_FVarLinearInterpolation
OpenSubdiv_VtxBoundaryInterpolation
blender::bke::subdiv::Subdiv * subdiv
int * face_start_grid_index
blender::VArraySpan< float > cd_vertex_crease
blender::OffsetIndices< int > base_faces
struct MultiresReshapeContext::@92 top
struct MultiresReshapeContext::@91 reshape
int(* getFaceCornerUVIndex)(const OpenSubdiv_Converter *converter, const int face_index, const int corner_index)
int(* getNumFaceVertices)(const OpenSubdiv_Converter *converter, const int face_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)
int(* getNumFaces)(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)
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)
void(* setCoarsePositions)(OpenSubdiv_Evaluator *evaluator, const float *positions, const int start_vertex_index, const int num_vertices)
void(* refine)(OpenSubdiv_Evaluator *evaluator)
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