48 float tangent_matrix[3][3];
62 GridCoord *grid_coords;
65 bool is_infinite_sharp;
74 int start_corner_index;
87struct LinearGridElement {
92 LinearGridElement *elements;
106 LinearGridElement *elements_storage;
111struct MultiresReshapeSmoothContext {
112 const MultiresReshapeContext *reshape_context;
138 LinearGrids linear_delta_grids;
141 blender::BitSpan loose_base_edges;
144 blender::bke::subdiv::Subdiv *reshape_subdiv;
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);
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));
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);
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);
426 callback(&ptex_coord, &grid_coord);
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);
578 Vertex *vertex = &reshape_smooth_context->geometry.vertices[subdiv_vertex_index];
580 vertex->grid_coords =
static_cast<GridCoord *
>(
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);
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);
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,
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);
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);
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);
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);
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);
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);
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,
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)
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Gabor Generate Gabor noise Gradient Generate interpolated color and intensity values based on the input vector Magic Generate a psychedelic color texture Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a point
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
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)
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::@200156053054134230066312172364357207125266140353 top
blender::bke::subdiv::Subdiv * subdiv
int * face_start_grid_index
blender::VArraySpan< float > cd_vertex_crease
blender::OffsetIndices< int > base_faces
struct MultiresReshapeContext::@354360336041134252127126015345003241176221362327 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