51static void subdiv_ccg_average_inner_face_grids(
SubdivCCG &subdiv_ccg,
55void subdiv_ccg_average_faces_boundaries_and_corners(
SubdivCCG &subdiv_ccg,
57 const IndexMask &face_mask);
66static int topology_refiner_count_face_corners(
69 const int num_faces = topology_refiner->
base_level().GetNumFaces();
71 for (
int face_index = 0; face_index < num_faces; face_index++) {
72 num_corners += topology_refiner->
base_level().GetFaceVertices(face_index).size();
79static void subdiv_ccg_alloc_elements(
SubdivCCG &subdiv_ccg,
85 const int64_t num_grids = topology_refiner_count_face_corners(topology_refiner);
87 const int64_t grid_area = grid_size * grid_size;
88 subdiv_ccg.
positions.reinitialize(num_grids * grid_area);
89 if (settings.need_normal) {
90 subdiv_ccg.
normals.reinitialize(num_grids * grid_area);
92 if (settings.need_mask) {
104static void subdiv_ccg_eval_grid_element_limit(
Subdiv &subdiv,
106 const int ptex_face_index,
114 else if (!subdiv_ccg.
normals.is_empty()) {
127static void subdiv_ccg_eval_grid_element_mask(
SubdivCCG &subdiv_ccg,
129 const int ptex_face_index,
137 if (mask_evaluator !=
nullptr) {
145static void subdiv_ccg_eval_grid_element(
Subdiv &subdiv,
148 const int ptex_face_index,
153 subdiv_ccg_eval_grid_element_limit(subdiv, subdiv_ccg, ptex_face_index, u,
v, element);
154 subdiv_ccg_eval_grid_element_mask(subdiv_ccg, mask_evaluator, ptex_face_index, u,
v, element);
157static void subdiv_ccg_eval_regular_grid(
Subdiv &subdiv,
161 const int face_index)
163 const int ptex_face_index = face_ptex_offset[face_index];
164 const int grid_size = subdiv_ccg.
grid_size;
165 const int grid_area = subdiv_ccg.
grid_area;
166 const float grid_size_1_inv = 1.0f / (grid_size - 1);
168 for (
int corner = 0; corner < face.size(); corner++) {
169 const int grid_index = face.start() + corner;
171 for (
int y = 0; y < grid_size; y++) {
172 const float grid_v = y * grid_size_1_inv;
173 for (
int x = 0; x < grid_size; x++) {
174 const float grid_u = x * grid_size_1_inv;
178 subdiv_ccg_eval_grid_element(
179 subdiv, subdiv_ccg, mask_evaluator, ptex_face_index, u,
v, element);
185static void subdiv_ccg_eval_special_grid(
Subdiv &subdiv,
189 const int face_index)
191 const int grid_size = subdiv_ccg.
grid_size;
192 const int grid_area = subdiv_ccg.
grid_area;
193 const float grid_size_1_inv = 1.0f / (grid_size - 1);
195 for (
int corner = 0; corner < face.size(); corner++) {
196 const int grid_index = face.start() + corner;
197 const int ptex_face_index = face_ptex_offset[face_index] + corner;
199 for (
int y = 0; y < grid_size; y++) {
200 const float u = 1.0f - (y * grid_size_1_inv);
201 for (
int x = 0; x < grid_size; x++) {
202 const float v = 1.0f - (x * grid_size_1_inv);
204 subdiv_ccg_eval_grid_element(
205 subdiv, subdiv_ccg, mask_evaluator, ptex_face_index, u,
v, element);
211static bool subdiv_ccg_evaluate_grids(
SubdivCCG &subdiv_ccg,
217 const int num_faces = topology_refiner->
base_level().GetNumFaces();
220 for (
const int face_index : range) {
221 if (subdiv_ccg.
faces[face_index].size() == 4) {
222 subdiv_ccg_eval_regular_grid(
223 subdiv, subdiv_ccg, face_ptex_offset, mask_evaluator, face_index);
226 subdiv_ccg_eval_special_grid(
227 subdiv, subdiv_ccg, face_ptex_offset, mask_evaluator, face_index);
239static void subdiv_ccg_allocate_adjacent_edges(
SubdivCCG &subdiv_ccg,
const int num_edges)
244static SubdivCCGCoord subdiv_ccg_coord(
int grid_index,
int x,
int y)
257 const int grid_size = subdiv_ccg.
grid_size * 2;
269static void subdiv_ccg_init_faces_edge_neighborhood(
SubdivCCG &subdiv_ccg)
272 const OffsetIndices<int> faces = subdiv_ccg.
faces;
274 const int num_edges = base_level.GetNumEdges();
275 const int grid_size = subdiv_ccg.
grid_size;
276 if (num_edges == 0) {
280 subdiv_ccg_allocate_adjacent_edges(subdiv_ccg, num_edges);
283 for (
const int face_index : faces.index_range()) {
285 const int num_face_grids = face.
size();
286 const OpenSubdiv::Far::ConstIndexArray face_vertices = base_level.GetFaceVertices(face_index);
289 const OpenSubdiv::Far::ConstIndexArray face_edges = base_level.GetFaceEdges(face_index);
291 for (
int corner = 0; corner < num_face_grids; corner++) {
292 const int vertex_index = face_vertices[corner];
293 const int edge_index = face_edges[corner];
294 const OpenSubdiv::Far::ConstIndexArray edge_vertices = base_level.GetEdgeVertices(
296 const bool is_edge_flipped = (edge_vertices[0] != vertex_index);
298 const int current_grid_index = face.start() + corner;
300 const int next_grid_index = face.start() + (corner + 1) % num_face_grids;
303 SubdivCCGCoord *boundary_coords = subdiv_ccg_adjacent_edge_add_face(subdiv_ccg,
306 int boundary_element_index = 0;
307 if (is_edge_flipped) {
308 for (
int i = 0; i < grid_size; i++) {
309 boundary_coords[boundary_element_index++] = subdiv_ccg_coord(
310 next_grid_index, grid_size - i - 1, grid_size - 1);
312 for (
int i = 0; i < grid_size; i++) {
313 boundary_coords[boundary_element_index++] = subdiv_ccg_coord(
314 current_grid_index, grid_size - 1, i);
318 for (
int i = 0; i < grid_size; i++) {
319 boundary_coords[boundary_element_index++] = subdiv_ccg_coord(
320 current_grid_index, grid_size - 1, grid_size - i - 1);
322 for (
int i = 0; i < grid_size; i++) {
323 boundary_coords[boundary_element_index++] = subdiv_ccg_coord(
324 next_grid_index, i, grid_size - 1);
331static void subdiv_ccg_allocate_adjacent_vertices(
SubdivCCG &subdiv_ccg,
const int num_vertices)
351static void subdiv_ccg_init_faces_vertex_neighborhood(
SubdivCCG &subdiv_ccg)
354 const OffsetIndices<int> faces = subdiv_ccg.
faces;
356 const int num_vertices = topology_refiner->
base_level().GetNumVertices();
357 const int grid_size = subdiv_ccg.
grid_size;
358 if (num_vertices == 0) {
362 subdiv_ccg_allocate_adjacent_vertices(subdiv_ccg, num_vertices);
364 for (
const int face_index : faces.index_range()) {
366 const int num_face_grids = face.size();
367 const OpenSubdiv::Far::ConstIndexArray face_vertices =
368 topology_refiner->
base_level().GetFaceVertices(face_index);
369 for (
int corner = 0; corner < num_face_grids; corner++) {
370 const int vertex_index = face_vertices[corner];
372 const int grid_index = face.start() + corner;
375 SubdivCCGCoord *corner_coord = subdiv_ccg_adjacent_vertex_add_face(adjacent_vertex);
376 *corner_coord = subdiv_ccg_coord(grid_index, grid_size - 1, grid_size - 1);
381static void subdiv_ccg_init_faces_neighborhood(
SubdivCCG &subdiv_ccg)
383 subdiv_ccg_init_faces_edge_neighborhood(subdiv_ccg);
384 subdiv_ccg_init_faces_vertex_neighborhood(subdiv_ccg);
397 const Mesh &coarse_mesh,
400#ifdef WITH_OPENSUBDIV
402 std::unique_ptr<SubdivCCG> subdiv_ccg = std::make_unique<SubdivCCG>();
403 subdiv_ccg->subdiv = &subdiv;
406 subdiv_ccg->grid_area = subdiv_ccg->grid_size * subdiv_ccg->grid_size;
407 subdiv_ccg->faces = coarse_mesh.faces();
408 subdiv_ccg->grids_num = subdiv_ccg->faces.total_size();
409 subdiv_ccg->grid_to_face_map = coarse_mesh.corner_to_face_map();
410 subdiv_ccg_alloc_elements(*subdiv_ccg, subdiv, settings);
411 subdiv_ccg_init_faces_neighborhood(*subdiv_ccg);
412 if (!subdiv_ccg_evaluate_grids(*subdiv_ccg, subdiv, mask_evaluator)) {
419 UNUSED_VARS(subdiv, settings, coarse_mesh, mask_evaluator);
426 const Mesh &coarse_mesh)
439 subdiv, settings, coarse_mesh, has_mask ? &mask_evaluator :
nullptr);
441 mask_evaluator.
free(&mask_evaluator);
447 result->runtime->subdiv_ccg = std::move(subdiv_ccg);
453 if (this->subdiv !=
nullptr) {
459 for (
int face_index = 0; face_index < adjacent_edge->
num_adjacent_faces; face_index++) {
473#ifdef WITH_OPENSUBDIV
506#ifdef WITH_OPENSUBDIV
513static void subdiv_ccg_recalc_inner_face_normals(
const SubdivCCG &subdiv_ccg,
517 const int grid_size = subdiv_ccg.
grid_size;
518 const int grid_area = subdiv_ccg.
grid_area;
519 const int grid_size_1 = grid_size - 1;
521 for (
int y = 0; y < grid_size - 1; y++) {
522 for (
int x = 0; x < grid_size - 1; x++) {
523 const int face_index = y * grid_size_1 +
x;
524 float *face_normal = face_normals[face_index];
535static void subdiv_ccg_average_inner_face_normals(
SubdivCCG &subdiv_ccg,
539 const int grid_size = subdiv_ccg.
grid_size;
540 const int grid_area = subdiv_ccg.
grid_area;
541 const int grid_size_1 = grid_size - 1;
544 for (
int y = 0; y < grid_size; y++) {
545 for (
int x = 0; x < grid_size; x++) {
546 float normal_acc[3] = {0.0f, 0.0f, 0.0f};
549 if (x < grid_size_1 && y < grid_size_1) {
550 add_v3_v3(normal_acc, face_normals[y * grid_size_1 + x]);
554 if (y < grid_size_1) {
555 add_v3_v3(normal_acc, face_normals[y * grid_size_1 + (x - 1)]);
559 add_v3_v3(normal_acc, face_normals[(y - 1) * grid_size_1 + (x - 1)]);
563 if (y >= 1 && x < grid_size_1) {
564 add_v3_v3(normal_acc, face_normals[(y - 1) * grid_size_1 + x]);
574static void subdiv_ccg_recalc_inner_grid_normals(
SubdivCCG &subdiv_ccg,
const IndexMask &face_mask)
579 const int grid_size_1 = subdiv_ccg.
grid_size - 1;
583 const OffsetIndices<int> faces = subdiv_ccg.
faces;
586 for (
const int face_index : segment) {
588 for (
const int grid_index : face) {
589 subdiv_ccg_recalc_inner_face_normals(subdiv_ccg, face_normals, grid_index);
590 subdiv_ccg_average_inner_face_normals(subdiv_ccg, face_normals, grid_index);
592 subdiv_ccg_average_inner_face_grids(subdiv_ccg, key, face);
601#ifdef WITH_OPENSUBDIV
602 if (subdiv_ccg.
normals.is_empty()) {
606 subdiv_ccg_recalc_inner_grid_normals(subdiv_ccg, subdiv_ccg.
faces.index_range());
615#ifdef WITH_OPENSUBDIV
616 if (subdiv_ccg.
normals.is_empty()) {
620 if (face_mask.is_empty()) {
624 subdiv_ccg_recalc_inner_grid_normals(subdiv_ccg, face_mask);
627 subdiv_ccg_average_faces_boundaries_and_corners(subdiv_ccg, key, face_mask);
639#ifdef WITH_OPENSUBDIV
641static void average_grid_element_value_v3(
float a[3],
float b[3])
648static void average_grid_element(
SubdivCCG &subdiv_ccg,
649 const int grid_element_a,
650 const int grid_element_b)
652 average_grid_element_value_v3(subdiv_ccg.
positions[grid_element_a],
654 if (!subdiv_ccg.
normals.is_empty()) {
655 average_grid_element_value_v3(subdiv_ccg.
normals[grid_element_a],
656 subdiv_ccg.
normals[grid_element_b]);
659 float mask = (subdiv_ccg.
masks[grid_element_a] + subdiv_ccg.
masks[grid_element_b]) * 0.5f;
666struct GridElementAccumulator {
672static void element_accumulator_init(GridElementAccumulator &accumulator)
676 accumulator.mask = 0.0f;
679static void element_accumulator_add(GridElementAccumulator &accumulator,
683 accumulator.co += subdiv_ccg.
positions[elem];
684 if (!subdiv_ccg.
normals.is_empty()) {
685 accumulator.no += subdiv_ccg.
normals[elem];
688 accumulator.mask += subdiv_ccg.
masks[elem];
692static void element_accumulator_mul_fl(GridElementAccumulator &accumulator,
const float f)
696 accumulator.mask *= f;
699static void element_accumulator_copy(
SubdivCCG &subdiv_ccg,
700 const int destination,
701 const GridElementAccumulator &accumulator)
703 subdiv_ccg.
positions[destination] = accumulator.co;
704 if (!subdiv_ccg.
normals.is_empty()) {
705 subdiv_ccg.
normals[destination] = accumulator.no;
708 subdiv_ccg.
masks[destination] = accumulator.mask;
712static void subdiv_ccg_average_inner_face_grids(
SubdivCCG &subdiv_ccg,
716 const int num_face_grids = face.size();
717 const int grid_size = subdiv_ccg.
grid_size;
718 int prev_grid = face.start() + num_face_grids - 1;
720 for (
const int grid : face) {
721 for (
int i = 1; i < grid_size; i++) {
724 average_grid_element(subdiv_ccg, prev_grid_element, grid_element);
730 GridElementAccumulator center_accumulator;
731 element_accumulator_init(center_accumulator);
732 for (
const int grid : face) {
734 element_accumulator_add(center_accumulator, subdiv_ccg, grid_center_element);
736 element_accumulator_mul_fl(center_accumulator, 1.0f / num_face_grids);
737 for (
const int grid : face) {
739 element_accumulator_copy(subdiv_ccg, grid_center_element, center_accumulator);
743static void subdiv_ccg_average_grids_boundary(
SubdivCCG &subdiv_ccg,
749 const int grid_size2 = subdiv_ccg.
grid_size * 2;
750 if (num_adjacent_faces == 1) {
754 for (
int i = 1; i < grid_size2 - 1; i++) {
755 element_accumulator_init(accumulators[i]);
757 for (
int face_index = 0; face_index < num_adjacent_faces; face_index++) {
758 for (
int i = 1; i < grid_size2 - 1; i++) {
760 element_accumulator_add(accumulators[i], subdiv_ccg, grid_element);
763 for (
int i = 1; i < grid_size2 - 1; i++) {
764 element_accumulator_mul_fl(accumulators[i], 1.0f / num_adjacent_faces);
767 for (
int face_index = 0; face_index < num_adjacent_faces; face_index++) {
768 for (
int i = 1; i < grid_size2 - 1; i++) {
770 element_accumulator_copy(subdiv_ccg, grid_element, accumulators[i]);
775struct AverageGridsCornerData {
780 const int *adjacent_vert_index_map;
783static void subdiv_ccg_average_grids_corners(
SubdivCCG &subdiv_ccg,
788 if (num_adjacent_faces == 1) {
792 GridElementAccumulator accumulator;
793 element_accumulator_init(accumulator);
794 for (
int face_index = 0; face_index < num_adjacent_faces; face_index++) {
796 element_accumulator_add(accumulator, subdiv_ccg, grid_element);
798 element_accumulator_mul_fl(accumulator, 1.0f / num_adjacent_faces);
800 for (
int face_index = 0; face_index < num_adjacent_faces; face_index++) {
802 element_accumulator_copy(subdiv_ccg, grid_element, accumulator);
806static void subdiv_ccg_average_boundaries(
SubdivCCG &subdiv_ccg,
808 const IndexMask &adjacent_edge_mask)
816 for (
const int i : segment) {
818 subdiv_ccg_average_grids_boundary(subdiv_ccg, key, adjacent_edge, accumulators);
823static void subdiv_ccg_average_corners(
SubdivCCG &subdiv_ccg,
825 const IndexMask &adjacent_vert_mask)
828 adjacent_vert_mask.foreach_index(
GrainSize(1024), [&](
const int i) {
830 subdiv_ccg_average_grids_corners(subdiv_ccg, key, adjacent_vert);
838#ifdef WITH_OPENSUBDIV
851#ifdef WITH_OPENSUBDIV
853static void subdiv_ccg_affected_face_adjacency(
SubdivCCG &subdiv_ccg,
854 const IndexMask &face_mask,
861 face_mask.foreach_index([&](
const int face_index) {
862 const OpenSubdiv::Far::ConstIndexArray face_vertices =
863 topology_refiner->
base_level().GetFaceVertices(face_index);
864 adjacent_verts.
add_multiple({face_vertices.begin(), face_vertices.size()});
866 const OpenSubdiv::Far::ConstIndexArray face_edges =
867 topology_refiner->
base_level().GetFaceEdges(face_index);
868 adjacent_edges.
add_multiple({face_edges.begin(), face_edges.size()});
872void subdiv_ccg_average_faces_boundaries_and_corners(
SubdivCCG &subdiv_ccg,
874 const IndexMask &face_mask)
878 subdiv_ccg_affected_face_adjacency(subdiv_ccg, face_mask, adjacent_vert_set, adjacent_edge_set);
883 std::sort(adjacent_verts.
begin(), adjacent_verts.
end());
884 std::sort(adjacent_edges.
begin(), adjacent_edges.
end());
886 IndexMaskMemory memory;
887 subdiv_ccg_average_boundaries(
888 subdiv_ccg, key, IndexMask::from_indices(adjacent_edges.as_span(), memory));
890 subdiv_ccg_average_corners(
891 subdiv_ccg, key, IndexMask::from_indices(adjacent_verts.as_span(), memory));
898#ifdef WITH_OPENSUBDIV
901 face_mask.foreach_index(
GrainSize(512), [&](
const int face_index) {
902 subdiv_ccg_average_inner_face_grids(subdiv_ccg, key, subdiv_ccg.
faces[face_index]);
919 const int num_grids = subdiv_ccg.
grids_num;
920 const int grid_size = subdiv_ccg.
grid_size;
921 const int grid_area = grid_size * grid_size;
922 const int num_edges_per_grid = 2 * (grid_size * (grid_size - 1));
923 r_num_vertices = num_grids * grid_area;
924 r_num_edges = num_grids * num_edges_per_grid;
925 r_num_faces = num_grids * (grid_size - 1) * (grid_size - 1);
926 r_num_loops = r_num_faces * 4;
937 printf(
"%s: grid index: %d, coord: (%d, %d)\n", message, coord.
grid_index, coord.
x, coord.
y);
945 const int grid_size = subdiv_ccg.
grid_size;
946 if (coord.
x < 0 || coord.
x >= grid_size) {
949 if (coord.
y < 0 || coord.
y >= grid_size) {
956 const int num_unique,
957 const int num_duplicates)
959 const int size = num_unique + num_duplicates;
967 const int grid_size_1 = subdiv_ccg.
grid_size - 1;
968 return (coord.
x == 0 && coord.
y == 0) || (coord.
x == 0 && coord.
y == grid_size_1) ||
969 (coord.
x == grid_size_1 && coord.
y == grid_size_1) ||
970 (coord.
x == grid_size_1 && coord.
y == 0);
976 const int grid_size_1 = subdiv_ccg.
grid_size - 1;
977 return coord.
x == 0 || coord.
y == 0 || coord.
x == grid_size_1 || coord.
y == grid_size_1;
984 const int grid_size_1 = subdiv_ccg.
grid_size - 1;
986 return coord.
y > 0 && coord.
y < grid_size_1;
989 return coord.
x > 0 && coord.
x < grid_size_1;
1030#ifdef WITH_OPENSUBDIV
1038 const int grid_size_1 = subdiv_ccg.
grid_size - 1;
1039 if (result.x == grid_size_1) {
1042 else if (result.y == grid_size_1) {
1045 else if (result.x == 0) {
1048 else if (result.y == 0) {
1061 const int face_grid_index = coord.
grid_index;
1062 int next_face_grid_index = face_grid_index + 1 - face.start();
1063 if (next_face_grid_index == face.size()) {
1064 next_face_grid_index = 0;
1066 return face.start() + next_face_grid_index;
1071 const int face_grid_index = coord.
grid_index;
1072 int prev_face_grid_index = face_grid_index - 1 - face.start();
1073 if (prev_face_grid_index < 0) {
1074 prev_face_grid_index = face.size() - 1;
1076 return face.start() + prev_face_grid_index;
1081static void neighbor_coords_corner_center_get(
const SubdivCCG &subdiv_ccg,
1083 const bool include_duplicates,
1087 const int num_adjacent_grids = face.size();
1090 r_neighbors, num_adjacent_grids, (include_duplicates) ? num_adjacent_grids - 1 : 0);
1092 int duplicate_face_grid_index = num_adjacent_grids;
1093 for (
int face_grid_index = 0; face_grid_index < num_adjacent_grids; ++face_grid_index) {
1095 neighbor_coord.
grid_index = face.start() + face_grid_index;
1096 neighbor_coord.
x = 1;
1097 neighbor_coord.
y = 0;
1098 r_neighbors.
coords[face_grid_index] = neighbor_coord;
1101 neighbor_coord.
x = 0;
1102 r_neighbors.
coords[duplicate_face_grid_index++] = neighbor_coord;
1108static int adjacent_vertex_index_from_coord(
const SubdivCCG &subdiv_ccg,
1116 const int face_grid_index = coord.
grid_index - face.start();
1118 const OpenSubdiv::Far::ConstIndexArray face_vertices =
1119 topology_refiner->
base_level().GetFaceVertices(face_index);
1121 const int adjacent_vertex_index = face_vertices[face_grid_index];
1122 return adjacent_vertex_index;
1126static void neighbor_coords_corner_vertex_get(
const SubdivCCG &subdiv_ccg,
1128 const bool include_duplicates,
1134 const int adjacent_vertex_index = adjacent_vertex_index_from_coord(subdiv_ccg, coord);
1135 const OpenSubdiv::Far::ConstIndexArray vertex_edges =
1136 topology_refiner->
base_level().GetVertexEdges(adjacent_vertex_index);
1142 r_neighbors, vertex_edges.size(), (include_duplicates) ? num_adjacent_faces - 1 : 0);
1144 for (
int i = 0; i < vertex_edges.size(); ++i) {
1145 const int edge_index = vertex_edges[i];
1148 const int edge_face_index = 0;
1151 const OpenSubdiv::Far::ConstIndexArray edge_vertices_indices =
1152 topology_refiner->
base_level().GetEdgeVertices(edge_index);
1153 int edge_point_index, duplicate_edge_point_index;
1154 if (edge_vertices_indices[0] == adjacent_vertex_index) {
1155 duplicate_edge_point_index = 0;
1156 edge_point_index = duplicate_edge_point_index + 1;
1162 duplicate_edge_point_index = subdiv_ccg.
grid_size * 2 - 1;
1163 edge_point_index = duplicate_edge_point_index - 1;
1170 if (include_duplicates) {
1172 for (
int i = 0, duplicate_i = vertex_edges.size(); i < num_adjacent_faces; i++) {
1175 r_neighbors.
coords[duplicate_i++] = neighbor_coord;
1188 const int face_grid_index = coord.
grid_index - face.start();
1190 const OpenSubdiv::Far::ConstIndexArray face_edges = topology_refiner->
base_level().GetFaceEdges(
1193 const int grid_size_1 = subdiv_ccg.
grid_size - 1;
1194 int adjacent_edge_index = -1;
1195 if (coord.
x == grid_size_1) {
1196 adjacent_edge_index = face_edges[face_grid_index];
1200 adjacent_edge_index = face_edges[face_grid_index == 0 ? face.size() - 1 : face_grid_index - 1];
1203 return adjacent_edge_index;
1206static int adjacent_edge_point_index_from_coord(
const SubdivCCG &subdiv_ccg,
1208 const int adjacent_edge_index)
1213 const int adjacent_vertex_index = adjacent_vertex_index_from_coord(subdiv_ccg, coord);
1214 const OpenSubdiv::Far::ConstIndexArray edge_vertices_indices =
1215 topology_refiner->
base_level().GetEdgeVertices(adjacent_edge_index);
1221 int directional_edge_vertex_index = -1;
1223 const int grid_size_1 = subdiv_ccg.
grid_size - 1;
1224 int adjacent_edge_point_index = -1;
1225 if (coord.
x == grid_size_1) {
1226 adjacent_edge_point_index = subdiv_ccg.
grid_size - coord.
y - 1;
1227 directional_edge_vertex_index = edge_vertices_indices[0];
1231 adjacent_edge_point_index = subdiv_ccg.
grid_size + coord.
x;
1232 directional_edge_vertex_index = edge_vertices_indices[1];
1236 if (adjacent_vertex_index != directional_edge_vertex_index) {
1237 const int num_edge_points = subdiv_ccg.
grid_size * 2;
1238 adjacent_edge_point_index = num_edge_points - adjacent_edge_point_index - 1;
1241 return adjacent_edge_point_index;
1248static int next_adjacent_edge_point_index(
const SubdivCCG &subdiv_ccg,
const int point_index)
1250 if (point_index == subdiv_ccg.
grid_size - 1) {
1251 return point_index + 2;
1253 return point_index + 1;
1255static int prev_adjacent_edge_point_index(
const SubdivCCG &subdiv_ccg,
const int point_index)
1257 if (point_index == subdiv_ccg.
grid_size) {
1258 return point_index - 2;
1260 return point_index - 1;
1266static int adjacent_grid_corner_point_index_on_edge(
const SubdivCCG &subdiv_ccg,
1267 const int point_index)
1269 if (point_index == subdiv_ccg.
grid_size) {
1270 return point_index - 1;
1272 return point_index + 1;
1277static void neighbor_coords_edge_get(
const SubdivCCG &subdiv_ccg,
1279 const bool include_duplicates,
1284 const int adjacent_edge_index = adjacent_edge_index_from_coord(subdiv_ccg, coord);
1289 int num_duplicates = 0;
1290 if (include_duplicates) {
1291 num_duplicates += num_adjacent_faces - 1;
1295 num_duplicates += num_adjacent_faces;
1300 const int point_index = adjacent_edge_point_index_from_coord(
1301 subdiv_ccg, coord, adjacent_edge_index);
1302 const int point_index_duplicate = adjacent_grid_corner_point_index_on_edge(subdiv_ccg,
1305 const int next_point_index = next_adjacent_edge_point_index(subdiv_ccg, point_index);
1306 const int prev_point_index = prev_adjacent_edge_point_index(subdiv_ccg, point_index);
1308 int duplicate_i = num_adjacent_faces;
1309 for (
int i = 0; i < num_adjacent_faces; ++i) {
1313 r_neighbors.
coords[i + 2] = coord_step_inside_from_boundary(subdiv_ccg, grid_coord);
1317 r_neighbors.
coords[0] = boundary_coords[prev_point_index];
1318 r_neighbors.
coords[1] = boundary_coords[next_point_index];
1320 else if (include_duplicates) {
1322 r_neighbors.
coords[duplicate_i + 2] = grid_coord;
1327 if (include_duplicates && is_corner) {
1328 SubdivCCGCoord duplicate_corner_grid_coord = boundary_coords[point_index_duplicate];
1329 r_neighbors.
coords[duplicate_i + 2] = duplicate_corner_grid_coord;
1333 BLI_assert(duplicate_i - num_adjacent_faces == num_duplicates);
1337static void neighbor_coords_corner_edge_get(
const SubdivCCG &subdiv_ccg,
1339 const bool include_duplicates,
1342 neighbor_coords_edge_get(subdiv_ccg, coord, include_duplicates, r_neighbors);
1346static void neighbor_coords_corner_get(
const SubdivCCG &subdiv_ccg,
1348 const bool include_duplicates,
1351 if (coord.
x == 0 && coord.
y == 0) {
1352 neighbor_coords_corner_center_get(subdiv_ccg, coord, include_duplicates, r_neighbors);
1355 const int grid_size_1 = subdiv_ccg.
grid_size - 1;
1356 if (coord.
x == grid_size_1 && coord.
y == grid_size_1) {
1357 neighbor_coords_corner_vertex_get(subdiv_ccg, coord, include_duplicates, r_neighbors);
1360 neighbor_coords_corner_edge_get(subdiv_ccg, coord, include_duplicates, r_neighbors);
1368static void neighbor_coords_boundary_inner_get(
const SubdivCCG &subdiv_ccg,
1370 const bool include_duplicates,
1380 r_neighbors.
coords[3].grid_index = prev_grid_index_from_coord(subdiv_ccg, coord);
1381 r_neighbors.
coords[3].x = coord.
y;
1382 r_neighbors.
coords[3].y = 1;
1384 if (include_duplicates) {
1386 r_neighbors.
coords[4].y = 0;
1389 else if (coord.
y == 0) {
1394 r_neighbors.
coords[3].grid_index = next_grid_index_from_coord(subdiv_ccg, coord);
1395 r_neighbors.
coords[3].x = 1;
1396 r_neighbors.
coords[3].y = coord.
x;
1398 if (include_duplicates) {
1400 r_neighbors.
coords[4].x = 0;
1406static void neighbor_coords_boundary_outer_get(
const SubdivCCG &subdiv_ccg,
1408 const bool include_duplicates,
1411 neighbor_coords_edge_get(subdiv_ccg, coord, include_duplicates, r_neighbors);
1417static void neighbor_coords_boundary_get(
const SubdivCCG &subdiv_ccg,
1419 const bool include_duplicates,
1423 neighbor_coords_boundary_inner_get(subdiv_ccg, coord, include_duplicates, r_neighbors);
1426 neighbor_coords_boundary_outer_get(subdiv_ccg, coord, include_duplicates, r_neighbors);
1431static void neighbor_coords_inner_get(
const SubdivCCG &subdiv_ccg,
1447 const bool include_duplicates,
1450#ifdef WITH_OPENSUBDIV
1459 neighbor_coords_corner_get(subdiv_ccg, coord, include_duplicates, r_neighbors);
1462 neighbor_coords_boundary_get(subdiv_ccg, coord, include_duplicates, r_neighbors);
1465 neighbor_coords_inner_get(subdiv_ccg, coord, r_neighbors);
1474 UNUSED_VARS(subdiv_ccg, coord, include_duplicates, r_neighbors);
1480#ifdef WITH_OPENSUBDIV
1484 if (topology_refiner ==
nullptr) {
1488 const int num_coarse_faces = topology_refiner->
base_level().GetNumFaces();
1492 int start_grid_index = 0;
1493 for (
int face_index = 0; face_index < num_coarse_faces; face_index++) {
1494 const int num_face_grids = topology_refiner->
base_level().GetFaceVertices(face_index).size();
1496 start_grid_index += num_face_grids;
1516 const int grid_size_1 = subdiv_ccg.
grid_size - 1;
1522 if (coord.
x == grid_size_1) {
1524 r_v2 = corner_verts[
next];
1526 if (coord.
y == grid_size_1) {
1528 r_v2 = corner_verts[prev];
1541 const int grid_size_1 = subdiv_ccg.
grid_size - 1;
1543 if (coord.
x == 0 && coord.
y == 0) {
1547 if (coord.
x == grid_size_1 && coord.
y == grid_size_1) {
1549 r_v1 = r_v2 = corner_verts[coord.
grid_index];
1561 subdiv_ccg, coord, corner_verts, faces, r_v1, r_v2);
1576 subdiv_ccg, coord, corner_verts, faces, v1,
v2);
1577 switch (adjacency) {
1579 return boundary_verts[v1];
1581 return boundary_verts[v1] && boundary_verts[
v2];
1592 const int grid_area = subdiv_ccg.
grid_area;
1605 int *r_ptex_face_index,
1611 const float grid_size = subdiv_ccg.
grid_size;
1612 const float grid_size_1_inv = 1.0f / (grid_size - 1);
1614 const float grid_u = coord.
x * grid_size_1_inv;
1615 const float grid_v = coord.
y * grid_size_1_inv;
1618 const OffsetIndices<int> faces = subdiv_ccg.
faces;
1621 *r_ptex_face_index = face_ptex_offset[face_index];
1623 const float corner = coord.
grid_index - face.start();
1625 if (face.size() == 4) {
1629 *r_ptex_face_index += corner;
1630 *r_u = 1.0f - grid_v;
1631 *r_v = 1.0f - grid_u;
1640 int ptex_face_index;
1648 const int grid_index,
int CCG_grid_xy_to_index(const int grid_size, const int x, const int y)
Mesh * BKE_mesh_new_nomain_from_template(const Mesh *me_src, int verts_num, int edges_num, int faces_num, int corners_num)
int BKE_subdiv_ccg_grid_to_face_index(const SubdivCCG &subdiv_ccg, const int grid_index)
bool BKE_subdiv_ccg_mask_init_from_paint(SubdivCCGMaskEvaluator *mask_evaluator, const Mesh *mesh)
@ SUBDIV_CCG_ADJACENT_EDGE
@ SUBDIV_CCG_ADJACENT_VERTEX
@ SUBDIV_CCG_ADJACENT_NONE
#define BLI_assert_unreachable()
#define BLI_assert_msg(a, msg)
MINLINE int bitscan_forward_i(int a)
float normal_quad_v3(float n[3], const float v1[3], const float v2[3], const float v3[3], const float v4[3])
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void zero_v3(float r[3])
MINLINE void mul_v3_v3fl(float r[3], const float a[3], float f)
MINLINE void add_v3_v3(float r[3], const float a[3])
#define UNUSED_VARS_NDEBUG(...)
Read Guarded memory(de)allocation.
#define MEM_reallocN(vmemh, len)
ATTR_WARN_UNUSED_RESULT const void * element
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMVert * v
IndexRange index_range() const
void reinitialize(const int64_t new_size)
constexpr int64_t size() const
void add_multiple(Span< Key > keys)
IndexRange index_range() const
void reinitialize(const int64_t new_size)
const OpenSubdiv::Far::TopologyLevel & base_level() const
local_group_size(16, 16) .push_constant(Type b
void *(* MEM_malloc_arrayN)(size_t len, size_t size, const char *str)
ccl_device_inline float4 mask(const int4 mask, const float4 a)
IndexRange grid_range(const int grid_area, const int grid)
int grid_xy_to_vert(const CCGKey &key, const int grid, const int x, const int y)
int face_corner_prev(const IndexRange face, const int corner)
int face_find_corner_from_vert(const IndexRange face, const Span< int > corner_verts, const int vert)
int face_corner_next(const IndexRange face, const int corner)
void free(Subdiv *subdiv)
BLI_INLINE void rotate_grid_to_quad(int corner, float grid_u, float grid_v, float *r_quad_u, float *r_quad_v)
bool eval_begin_from_mesh(Subdiv *subdiv, const Mesh *mesh, Span< float3 > coarse_vert_positions, eSubdivEvaluatorType evaluator_type, OpenSubdiv_EvaluatorCache *evaluator_cache)
void eval_limit_point(Subdiv *subdiv, int ptex_face_index, float u, float v, float r_P[3])
void eval_limit_point_and_normal(Subdiv *subdiv, int ptex_face_index, float u, float v, float r_P[3], float r_N[3])
BLI_INLINE int grid_size_from_level(int level)
@ SUBDIV_EVALUATOR_TYPE_CPU
void stats_begin(SubdivStats *stats, StatsValue value)
int * face_ptex_offset_get(Subdiv *subdiv)
void stats_end(SubdivStats *stats, StatsValue value)
@ SUBDIV_STATS_SUBDIV_TO_CCG
void eval_final_point(Subdiv *subdiv, int ptex_face_index, float u, float v, float r_P[3])
SubdivCCGCoord ** boundary_coords
SubdivCCGCoord * corner_coords
int to_index(const CCGKey &key) const
float(* eval_mask)(SubdivCCGMaskEvaluator *mask_evaluator, int ptex_face_index, float u, float v)
void(* free)(SubdivCCGMaskEvaluator *mask_evaluator)
blender::Vector< SubdivCCGCoord, 256 > coords
blender::Array< blender::float3 > normals
blender::BitGroupVector grid_hidden
blender::Array< float > masks
struct SubdivCCG::@65 cache_
blender::Array< SubdivCCGAdjacentVertex > adjacent_verts
blender::bke::subdiv::Subdiv * subdiv
blender::Array< int > start_face_grid_index
blender::OffsetIndices< int > faces
blender::Array< SubdivCCGAdjacentEdge > adjacent_edges
blender::Span< int > grid_to_face_map
blender::Array< blender::float3 > positions
Displacement * displacement_evaluator
blender::opensubdiv::TopologyRefinerImpl * topology_refiner
void BKE_subdiv_ccg_update_normals(SubdivCCG &subdiv_ccg, const IndexMask &face_mask)
BLI_INLINE SubdivCCGCoord coord_at_prev_col(const SubdivCCG &, const SubdivCCGCoord &coord)
BLI_INLINE void subdiv_ccg_neighbors_init(SubdivCCGNeighbors &neighbors, const int num_unique, const int num_duplicates)
const int * BKE_subdiv_ccg_start_face_grid_index_get(const SubdivCCG &subdiv_ccg)
const int * BKE_subdiv_ccg_start_face_grid_index_ensure(SubdivCCG &subdiv_ccg)
void BKE_subdiv_ccg_recalc_normals(SubdivCCG &subdiv_ccg)
CCGKey BKE_subdiv_ccg_key_top_level(const SubdivCCG &subdiv_ccg)
void BKE_subdiv_ccg_eval_limit_point(const SubdivCCG &subdiv_ccg, const SubdivCCGCoord &coord, float r_point[3])
Mesh * BKE_subdiv_to_ccg_mesh(Subdiv &subdiv, const SubdivToCCGSettings &settings, const Mesh &coarse_mesh)
bool BKE_subdiv_ccg_coord_is_mesh_boundary(const OffsetIndices< int > faces, const Span< int > corner_verts, const blender::BitSpan boundary_verts, const SubdivCCG &subdiv_ccg, const SubdivCCGCoord coord)
blender::BitGroupVector & BKE_subdiv_ccg_grid_hidden_ensure(SubdivCCG &subdiv_ccg)
BLI_INLINE bool is_inner_edge_grid_coordinate(const SubdivCCG &subdiv_ccg, const SubdivCCGCoord &coord)
static void adjacent_vertices_index_from_adjacent_edge(const SubdivCCG &subdiv_ccg, const SubdivCCGCoord &coord, const blender::Span< int > corner_verts, const blender::OffsetIndices< int > faces, int &r_v1, int &r_v2)
void BKE_subdiv_ccg_print_coord(const char *message, const SubdivCCGCoord &coord)
void BKE_subdiv_ccg_eval_limit_positions(const SubdivCCG &subdiv_ccg, const CCGKey &key, const int grid_index, const MutableSpan< float3 > r_limit_positions)
BLI_INLINE bool is_corner_grid_coord(const SubdivCCG &subdiv_ccg, const SubdivCCGCoord &coord)
void BKE_subdiv_ccg_average_stitch_faces(SubdivCCG &subdiv_ccg, const IndexMask &face_mask)
CCGKey BKE_subdiv_ccg_key(const SubdivCCG &, int level)
static void subdiv_ccg_coord_to_ptex_coord(const SubdivCCG &subdiv_ccg, const SubdivCCGCoord &coord, int *r_ptex_face_index, float *r_u, float *r_v)
SubdivCCGAdjacencyType BKE_subdiv_ccg_coarse_mesh_adjacency_info_get(const SubdivCCG &subdiv_ccg, const SubdivCCGCoord &coord, const blender::Span< int > corner_verts, const blender::OffsetIndices< int > faces, int &r_v1, int &r_v2)
bool BKE_subdiv_ccg_check_coord_valid(const SubdivCCG &subdiv_ccg, const SubdivCCGCoord &coord)
void BKE_subdiv_ccg_topology_counters(const SubdivCCG &subdiv_ccg, int &r_num_vertices, int &r_num_edges, int &r_num_faces, int &r_num_loops)
void BKE_subdiv_ccg_average_grids(SubdivCCG &subdiv_ccg)
BLI_INLINE bool is_boundary_grid_coord(const SubdivCCG &subdiv_ccg, const SubdivCCGCoord &coord)
BLI_INLINE SubdivCCGCoord coord_at_next_col(const SubdivCCG &subdiv_ccg, const SubdivCCGCoord &coord)
void BKE_subdiv_ccg_neighbor_coords_get(const SubdivCCG &subdiv_ccg, const SubdivCCGCoord &coord, const bool include_duplicates, SubdivCCGNeighbors &r_neighbors)
BLI_INLINE SubdivCCGCoord coord_at_next_row(const SubdivCCG &subdiv_ccg, const SubdivCCGCoord &coord)
std::unique_ptr< SubdivCCG > BKE_subdiv_to_ccg(Subdiv &subdiv, const SubdivToCCGSettings &settings, const Mesh &coarse_mesh, SubdivCCGMaskEvaluator *mask_evaluator)
BLI_INLINE SubdivCCGCoord coord_at_prev_row(const SubdivCCG &, const SubdivCCGCoord &coord)
void BKE_subdiv_ccg_grid_hidden_free(SubdivCCG &subdiv_ccg)