51static void subdiv_ccg_average_inner_face_grids(
SubdivCCG &subdiv_ccg,
55void subdiv_ccg_average_faces_boundaries_and_corners(
SubdivCCG &subdiv_ccg,
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);
90 subdiv_ccg.
normals.reinitialize(num_grids * grid_area);
104static void subdiv_ccg_eval_grid_element_limit(
Subdiv &
subdiv,
106 const int ptex_face_index,
111 if (
subdiv.displacement_evaluator !=
nullptr) {
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) {
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);
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);
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();
221 for (
const int face_index : range) {
222 if (subdiv_ccg.
faces[face_index].size() == 4) {
223 subdiv_ccg_eval_regular_grid(
224 subdiv, subdiv_ccg, face_ptex_offset, mask_evaluator, face_index);
227 subdiv_ccg_eval_special_grid(
228 subdiv, subdiv_ccg, face_ptex_offset, mask_evaluator, face_index);
234 if (
subdiv.displacement_evaluator !=
nullptr) {
240static void subdiv_ccg_allocate_adjacent_edges(
SubdivCCG &subdiv_ccg,
const int num_edges)
263static void subdiv_ccg_init_faces_edge_neighborhood(
SubdivCCG &subdiv_ccg)
267 const OpenSubdiv::Far::TopologyLevel &base_level =
subdiv->topology_refiner->base_level();
268 const int num_edges = base_level.GetNumEdges();
269 const int grid_size = subdiv_ccg.
grid_size;
270 if (num_edges == 0) {
274 subdiv_ccg_allocate_adjacent_edges(subdiv_ccg, num_edges);
277 for (
const int face_index :
faces.index_range()) {
279 const int num_face_grids = face.
size();
280 const OpenSubdiv::Far::ConstIndexArray face_vertices = base_level.GetFaceVertices(face_index);
283 const OpenSubdiv::Far::ConstIndexArray face_edges = base_level.GetFaceEdges(face_index);
285 for (
int corner = 0; corner < num_face_grids; corner++) {
286 const int vertex_index = face_vertices[corner];
287 const int edge_index = face_edges[corner];
288 const OpenSubdiv::Far::ConstIndexArray edge_vertices = base_level.GetEdgeVertices(
290 const bool is_edge_flipped = (edge_vertices[0] != vertex_index);
292 const int current_grid_index = face.
start() + corner;
294 const int next_grid_index = face.
start() + (corner + 1) % num_face_grids;
298 grid_size * 2, adjacent_edge);
300 int boundary_element_index = 0;
301 if (is_edge_flipped) {
302 for (
int i = 0;
i < grid_size;
i++) {
303 boundary_coords[boundary_element_index++] = subdiv_ccg_coord(
304 next_grid_index, grid_size -
i - 1, grid_size - 1);
306 for (
int i = 0;
i < grid_size;
i++) {
307 boundary_coords[boundary_element_index++] = subdiv_ccg_coord(
308 current_grid_index, grid_size - 1,
i);
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, grid_size -
i - 1);
316 for (
int i = 0;
i < grid_size;
i++) {
317 boundary_coords[boundary_element_index++] = subdiv_ccg_coord(
318 next_grid_index,
i, grid_size - 1);
325static void subdiv_ccg_allocate_adjacent_vertices(
SubdivCCG &subdiv_ccg,
const int num_vertices)
334 const int grid_index,
341static void subdiv_ccg_init_faces_vertex_neighborhood(
SubdivCCG &subdiv_ccg)
346 const int num_vertices = topology_refiner->
base_level().GetNumVertices();
347 const int grid_size = subdiv_ccg.
grid_size;
348 if (num_vertices == 0) {
352 subdiv_ccg_allocate_adjacent_vertices(subdiv_ccg, num_vertices);
354 for (
const int face_index :
faces.index_range()) {
356 const int num_face_grids = face.
size();
357 const OpenSubdiv::Far::ConstIndexArray face_vertices =
358 topology_refiner->
base_level().GetFaceVertices(face_index);
359 for (
int corner = 0; corner < num_face_grids; corner++) {
360 const int vertex_index = face_vertices[corner];
362 const int grid_index = face.
start() + corner;
365 subdiv_ccg_adjacent_vertex_add_face(
366 adjacent_vertex, grid_index, grid_size - 1, grid_size - 1);
371static void subdiv_ccg_init_faces_neighborhood(
SubdivCCG &subdiv_ccg)
373 subdiv_ccg_init_faces_edge_neighborhood(subdiv_ccg);
374 subdiv_ccg_init_faces_vertex_neighborhood(subdiv_ccg);
387 const Mesh &coarse_mesh,
390#ifdef WITH_OPENSUBDIV
392 std::unique_ptr<SubdivCCG> subdiv_ccg = std::make_unique<SubdivCCG>();
393 subdiv_ccg->subdiv = &
subdiv;
396 subdiv_ccg->grid_area = subdiv_ccg->grid_size * subdiv_ccg->grid_size;
397 subdiv_ccg->faces = coarse_mesh.faces();
398 subdiv_ccg->grids_num = subdiv_ccg->faces.total_size();
399 subdiv_ccg->grid_to_face_map = coarse_mesh.corner_to_face_map();
402 subdiv_ccg_alloc_elements(*subdiv_ccg,
subdiv, settings);
403 subdiv_ccg_init_faces_neighborhood(*subdiv_ccg);
404 if (!subdiv_ccg_evaluate_grids(*subdiv_ccg,
subdiv, mask_evaluator)) {
419 const Mesh &coarse_mesh)
432 subdiv, settings, coarse_mesh, has_mask ? &mask_evaluator :
nullptr);
434 mask_evaluator.
free(&mask_evaluator);
440 result->runtime->subdiv_ccg = std::move(subdiv_ccg);
446 if (this->subdiv !=
nullptr) {
453#ifdef WITH_OPENSUBDIV
486#ifdef WITH_OPENSUBDIV
493static void subdiv_ccg_recalc_inner_face_normals(
const SubdivCCG &subdiv_ccg,
497 const int grid_size = subdiv_ccg.
grid_size;
498 const int grid_area = subdiv_ccg.
grid_area;
499 const int grid_size_1 = grid_size - 1;
501 for (
int y = 0;
y < grid_size - 1;
y++) {
502 for (
int x = 0;
x < grid_size - 1;
x++) {
503 const int face_index =
y * grid_size_1 +
x;
504 float *face_normal = face_normals[face_index];
515static void subdiv_ccg_average_inner_face_normals(
SubdivCCG &subdiv_ccg,
519 const int grid_size = subdiv_ccg.
grid_size;
520 const int grid_area = subdiv_ccg.
grid_area;
521 const int grid_size_1 = grid_size - 1;
524 for (
int y = 0;
y < grid_size;
y++) {
525 for (
int x = 0;
x < grid_size;
x++) {
526 float normal_acc[3] = {0.0f, 0.0f, 0.0f};
529 if (
x < grid_size_1 &&
y < grid_size_1) {
530 add_v3_v3(normal_acc, face_normals[
y * grid_size_1 +
x]);
534 if (
y < grid_size_1) {
535 add_v3_v3(normal_acc, face_normals[
y * grid_size_1 + (
x - 1)]);
539 add_v3_v3(normal_acc, face_normals[(
y - 1) * grid_size_1 + (
x - 1)]);
543 if (
y >= 1 &&
x < grid_size_1) {
544 add_v3_v3(normal_acc, face_normals[(
y - 1) * grid_size_1 +
x]);
554static void subdiv_ccg_recalc_inner_grid_normals(
SubdivCCG &subdiv_ccg,
const IndexMask &face_mask)
559 const int grid_size_1 = subdiv_ccg.
grid_size - 1;
566 for (
const int face_index : segment) {
568 for (
const int grid_index : face) {
569 subdiv_ccg_recalc_inner_face_normals(subdiv_ccg, face_normals, grid_index);
570 subdiv_ccg_average_inner_face_normals(subdiv_ccg, face_normals, grid_index);
572 subdiv_ccg_average_inner_face_grids(subdiv_ccg, key, face);
581#ifdef WITH_OPENSUBDIV
582 if (subdiv_ccg.
normals.is_empty()) {
586 subdiv_ccg_recalc_inner_grid_normals(subdiv_ccg, subdiv_ccg.
faces.index_range());
595#ifdef WITH_OPENSUBDIV
596 if (subdiv_ccg.
normals.is_empty()) {
604 subdiv_ccg_recalc_inner_grid_normals(subdiv_ccg, face_mask);
607 subdiv_ccg_average_faces_boundaries_and_corners(subdiv_ccg, key, face_mask);
619#ifdef WITH_OPENSUBDIV
621static void average_grid_element_value_v3(
float a[3],
float b[3])
628static void average_grid_element(
SubdivCCG &subdiv_ccg,
629 const int grid_element_a,
630 const int grid_element_b)
632 average_grid_element_value_v3(subdiv_ccg.
positions[grid_element_a],
634 if (!subdiv_ccg.
normals.is_empty()) {
635 average_grid_element_value_v3(subdiv_ccg.
normals[grid_element_a],
636 subdiv_ccg.
normals[grid_element_b]);
639 float mask = (subdiv_ccg.
masks[grid_element_a] + subdiv_ccg.
masks[grid_element_b]) * 0.5f;
646struct GridElementAccumulator {
652static void element_accumulator_init(GridElementAccumulator &accumulator)
656 accumulator.mask = 0.0f;
659static void element_accumulator_add(GridElementAccumulator &accumulator,
663 accumulator.co += subdiv_ccg.
positions[elem];
664 if (!subdiv_ccg.
normals.is_empty()) {
665 accumulator.no += subdiv_ccg.
normals[elem];
668 accumulator.mask += subdiv_ccg.
masks[elem];
672static void element_accumulator_mul_fl(GridElementAccumulator &accumulator,
const float f)
676 accumulator.mask *= f;
679static void element_accumulator_copy(
SubdivCCG &subdiv_ccg,
680 const int destination,
681 const GridElementAccumulator &accumulator)
683 subdiv_ccg.
positions[destination] = accumulator.co;
684 if (!subdiv_ccg.
normals.is_empty()) {
685 subdiv_ccg.
normals[destination] = accumulator.no;
688 subdiv_ccg.
masks[destination] = accumulator.mask;
692static void subdiv_ccg_average_inner_face_grids(
SubdivCCG &subdiv_ccg,
696 const int num_face_grids = face.
size();
697 const int grid_size = subdiv_ccg.
grid_size;
698 int prev_grid = face.
start() + num_face_grids - 1;
700 for (
const int grid : face) {
701 for (
int i = 1;
i < grid_size;
i++) {
704 average_grid_element(subdiv_ccg, prev_grid_element, grid_element);
710 GridElementAccumulator center_accumulator;
711 element_accumulator_init(center_accumulator);
712 for (
const int grid : face) {
714 element_accumulator_add(center_accumulator, subdiv_ccg, grid_center_element);
716 element_accumulator_mul_fl(center_accumulator, 1.0f / num_face_grids);
717 for (
const int grid : face) {
719 element_accumulator_copy(subdiv_ccg, grid_center_element, center_accumulator);
723static void subdiv_ccg_average_grids_boundary(
SubdivCCG &subdiv_ccg,
729 const int grid_size2 = subdiv_ccg.
grid_size * 2;
730 if (num_adjacent_faces == 1) {
734 for (
int i = 1;
i < grid_size2 - 1;
i++) {
735 element_accumulator_init(accumulators[
i]);
737 for (
int face_index = 0; face_index < num_adjacent_faces; face_index++) {
738 for (
int i = 1;
i < grid_size2 - 1;
i++) {
739 const int grid_element = adjacent_edge.
boundary_coords[face_index][
i].to_index(key);
740 element_accumulator_add(accumulators[
i], subdiv_ccg, grid_element);
743 for (
int i = 1;
i < grid_size2 - 1;
i++) {
744 element_accumulator_mul_fl(accumulators[
i], 1.0f / num_adjacent_faces);
747 for (
int face_index = 0; face_index < num_adjacent_faces; face_index++) {
748 for (
int i = 1;
i < grid_size2 - 1;
i++) {
749 const int grid_element = adjacent_edge.
boundary_coords[face_index][
i].to_index(key);
750 element_accumulator_copy(subdiv_ccg, grid_element, accumulators[
i]);
755static void subdiv_ccg_average_grids_corners(
SubdivCCG &subdiv_ccg,
760 if (num_adjacent_faces == 1) {
764 GridElementAccumulator accumulator;
765 element_accumulator_init(accumulator);
766 for (
int face_index = 0; face_index < num_adjacent_faces; face_index++) {
767 const int grid_element = adjacent_vertex.
corner_coords[face_index].to_index(key);
768 element_accumulator_add(accumulator, subdiv_ccg, grid_element);
770 element_accumulator_mul_fl(accumulator, 1.0f / num_adjacent_faces);
772 for (
int face_index = 0; face_index < num_adjacent_faces; face_index++) {
773 const int grid_element = adjacent_vertex.
corner_coords[face_index].to_index(key);
774 element_accumulator_copy(subdiv_ccg, grid_element, accumulator);
778static void subdiv_ccg_average_boundaries(
SubdivCCG &subdiv_ccg,
788 for (
const int i : segment) {
790 subdiv_ccg_average_grids_boundary(subdiv_ccg, key, adjacent_edge, accumulators);
795static void subdiv_ccg_average_corners(
SubdivCCG &subdiv_ccg,
802 subdiv_ccg_average_grids_corners(subdiv_ccg, key, adjacent_vert);
810#ifdef WITH_OPENSUBDIV
823#ifdef WITH_OPENSUBDIV
825static void subdiv_ccg_affected_face_adjacency(
SubdivCCG &subdiv_ccg,
834 const OpenSubdiv::Far::ConstIndexArray face_vertices =
835 topology_refiner->
base_level().GetFaceVertices(face_index);
836 adjacent_verts.
add_multiple({face_vertices.begin(), face_vertices.size()});
838 const OpenSubdiv::Far::ConstIndexArray face_edges =
839 topology_refiner->
base_level().GetFaceEdges(face_index);
840 adjacent_edges.
add_multiple({face_edges.begin(), face_edges.size()});
844void subdiv_ccg_average_faces_boundaries_and_corners(
SubdivCCG &subdiv_ccg,
850 subdiv_ccg_affected_face_adjacency(subdiv_ccg, face_mask, adjacent_vert_set, adjacent_edge_set);
855 std::sort(adjacent_verts.
begin(), adjacent_verts.
end());
856 std::sort(adjacent_edges.
begin(), adjacent_edges.
end());
859 subdiv_ccg_average_boundaries(
862 subdiv_ccg_average_corners(
870#ifdef WITH_OPENSUBDIV
874 subdiv_ccg_average_inner_face_grids(subdiv_ccg, key, subdiv_ccg.
faces[face_index]);
891 const int num_grids = subdiv_ccg.
grids_num;
892 const int grid_size = subdiv_ccg.
grid_size;
893 const int grid_area = grid_size * grid_size;
894 const int num_edges_per_grid = 2 * (grid_size * (grid_size - 1));
895 r_num_vertices = num_grids * grid_area;
896 r_num_edges = num_grids * num_edges_per_grid;
897 r_num_faces = num_grids * (grid_size - 1) * (grid_size - 1);
898 r_num_loops = r_num_faces * 4;
909 printf(
"%s: grid index: %d, coord: (%d, %d)\n", message, coord.
grid_index, coord.
x, coord.
y);
917 const int grid_size = subdiv_ccg.
grid_size;
918 if (coord.
x < 0 || coord.
x >= grid_size) {
921 if (coord.
y < 0 || coord.
y >= grid_size) {
928 const int num_unique,
929 const int num_duplicates)
931 const int size = num_unique + num_duplicates;
939 const int grid_size_1 = subdiv_ccg.
grid_size - 1;
940 return (coord.
x == 0 && coord.
y == 0) || (coord.
x == 0 && coord.
y == grid_size_1) ||
941 (coord.
x == grid_size_1 && coord.
y == grid_size_1) ||
942 (coord.
x == grid_size_1 && coord.
y == 0);
948 const int grid_size_1 = subdiv_ccg.
grid_size - 1;
949 return coord.
x == 0 || coord.
y == 0 || coord.
x == grid_size_1 || coord.
y == grid_size_1;
956 const int grid_size_1 = subdiv_ccg.
grid_size - 1;
958 return coord.
y > 0 && coord.
y < grid_size_1;
961 return coord.
x > 0 && coord.
x < grid_size_1;
1002#ifdef WITH_OPENSUBDIV
1010 const int grid_size_1 = subdiv_ccg.
grid_size - 1;
1011 if (
result.x == grid_size_1) {
1014 else if (
result.y == grid_size_1) {
1017 else if (
result.x == 0) {
1020 else if (
result.y == 0) {
1033 const int face_grid_index = coord.
grid_index;
1034 int next_face_grid_index = face_grid_index + 1 - face.
start();
1035 if (next_face_grid_index == face.
size()) {
1036 next_face_grid_index = 0;
1038 return face.
start() + next_face_grid_index;
1043 const int face_grid_index = coord.
grid_index;
1044 int prev_face_grid_index = face_grid_index - 1 - face.
start();
1045 if (prev_face_grid_index < 0) {
1046 prev_face_grid_index = face.
size() - 1;
1048 return face.
start() + prev_face_grid_index;
1053static void neighbor_coords_corner_center_get(
const SubdivCCG &subdiv_ccg,
1055 const bool include_duplicates,
1059 const int num_adjacent_grids = face.
size();
1062 r_neighbors, num_adjacent_grids, (include_duplicates) ? num_adjacent_grids - 1 : 0);
1064 int duplicate_face_grid_index = num_adjacent_grids;
1065 for (
int face_grid_index = 0; face_grid_index < num_adjacent_grids; ++face_grid_index) {
1068 neighbor_coord.
x = 1;
1069 neighbor_coord.
y = 0;
1070 r_neighbors.
coords[face_grid_index] = neighbor_coord;
1073 neighbor_coord.
x = 0;
1074 r_neighbors.
coords[duplicate_face_grid_index++] = neighbor_coord;
1080static int adjacent_vertex_index_from_coord(
const SubdivCCG &subdiv_ccg,
1090 const OpenSubdiv::Far::ConstIndexArray face_vertices =
1091 topology_refiner->
base_level().GetFaceVertices(face_index);
1093 const int adjacent_vertex_index = face_vertices[face_grid_index];
1094 return adjacent_vertex_index;
1098static void neighbor_coords_corner_vertex_get(
const SubdivCCG &subdiv_ccg,
1100 const bool include_duplicates,
1106 const int adjacent_vertex_index = adjacent_vertex_index_from_coord(subdiv_ccg, coord);
1107 const OpenSubdiv::Far::ConstIndexArray vertex_edges =
1108 topology_refiner->
base_level().GetVertexEdges(adjacent_vertex_index);
1114 r_neighbors, vertex_edges.size(), (include_duplicates) ? num_adjacent_faces - 1 : 0);
1116 for (
int i = 0;
i < vertex_edges.size(); ++
i) {
1117 const int edge_index = vertex_edges[
i];
1120 const int edge_face_index = 0;
1123 const OpenSubdiv::Far::ConstIndexArray edge_vertices_indices =
1124 topology_refiner->
base_level().GetEdgeVertices(edge_index);
1125 int edge_point_index, duplicate_edge_point_index;
1126 if (edge_vertices_indices[0] == adjacent_vertex_index) {
1127 duplicate_edge_point_index = 0;
1128 edge_point_index = duplicate_edge_point_index + 1;
1134 duplicate_edge_point_index = subdiv_ccg.
grid_size * 2 - 1;
1135 edge_point_index = duplicate_edge_point_index - 1;
1142 if (include_duplicates) {
1144 for (
int i = 0, duplicate_i = vertex_edges.size();
i < num_adjacent_faces;
i++) {
1147 r_neighbors.
coords[duplicate_i++] = neighbor_coord;
1162 const OpenSubdiv::Far::ConstIndexArray face_edges = topology_refiner->
base_level().GetFaceEdges(
1165 const int grid_size_1 = subdiv_ccg.
grid_size - 1;
1166 int adjacent_edge_index = -1;
1167 if (coord.
x == grid_size_1) {
1168 adjacent_edge_index = face_edges[face_grid_index];
1172 adjacent_edge_index = face_edges[face_grid_index == 0 ? face.
size() - 1 : face_grid_index - 1];
1175 return adjacent_edge_index;
1178static int adjacent_edge_point_index_from_coord(
const SubdivCCG &subdiv_ccg,
1180 const int adjacent_edge_index)
1185 const int adjacent_vertex_index = adjacent_vertex_index_from_coord(subdiv_ccg, coord);
1186 const OpenSubdiv::Far::ConstIndexArray edge_vertices_indices =
1187 topology_refiner->
base_level().GetEdgeVertices(adjacent_edge_index);
1193 int directional_edge_vertex_index = -1;
1195 const int grid_size_1 = subdiv_ccg.
grid_size - 1;
1196 int adjacent_edge_point_index = -1;
1197 if (coord.
x == grid_size_1) {
1198 adjacent_edge_point_index = subdiv_ccg.
grid_size - coord.
y - 1;
1199 directional_edge_vertex_index = edge_vertices_indices[0];
1203 adjacent_edge_point_index = subdiv_ccg.
grid_size + coord.
x;
1204 directional_edge_vertex_index = edge_vertices_indices[1];
1208 if (adjacent_vertex_index != directional_edge_vertex_index) {
1209 const int num_edge_points = subdiv_ccg.
grid_size * 2;
1210 adjacent_edge_point_index = num_edge_points - adjacent_edge_point_index - 1;
1213 return adjacent_edge_point_index;
1220static int next_adjacent_edge_point_index(
const SubdivCCG &subdiv_ccg,
const int point_index)
1222 if (point_index == subdiv_ccg.
grid_size - 1) {
1223 return point_index + 2;
1225 return point_index + 1;
1227static int prev_adjacent_edge_point_index(
const SubdivCCG &subdiv_ccg,
const int point_index)
1229 if (point_index == subdiv_ccg.
grid_size) {
1230 return point_index - 2;
1232 return point_index - 1;
1238static int adjacent_grid_corner_point_index_on_edge(
const SubdivCCG &subdiv_ccg,
1239 const int point_index)
1241 if (point_index == subdiv_ccg.
grid_size) {
1242 return point_index - 1;
1244 return point_index + 1;
1249static void neighbor_coords_edge_get(
const SubdivCCG &subdiv_ccg,
1251 const bool include_duplicates,
1256 const int adjacent_edge_index = adjacent_edge_index_from_coord(subdiv_ccg, coord);
1261 int num_duplicates = 0;
1262 if (include_duplicates) {
1263 num_duplicates += num_adjacent_faces - 1;
1267 num_duplicates += num_adjacent_faces;
1272 const int point_index = adjacent_edge_point_index_from_coord(
1273 subdiv_ccg, coord, adjacent_edge_index);
1274 const int point_index_duplicate = adjacent_grid_corner_point_index_on_edge(subdiv_ccg,
1277 const int next_point_index = next_adjacent_edge_point_index(subdiv_ccg, point_index);
1278 const int prev_point_index = prev_adjacent_edge_point_index(subdiv_ccg, point_index);
1280 int duplicate_i = num_adjacent_faces;
1281 for (
int i = 0;
i < num_adjacent_faces; ++
i) {
1285 r_neighbors.
coords[
i + 2] = coord_step_inside_from_boundary(subdiv_ccg, grid_coord);
1289 r_neighbors.
coords[0] = boundary_coords[prev_point_index];
1290 r_neighbors.
coords[1] = boundary_coords[next_point_index];
1292 else if (include_duplicates) {
1294 r_neighbors.
coords[duplicate_i + 2] = grid_coord;
1299 if (include_duplicates && is_corner) {
1300 SubdivCCGCoord duplicate_corner_grid_coord = boundary_coords[point_index_duplicate];
1301 r_neighbors.
coords[duplicate_i + 2] = duplicate_corner_grid_coord;
1305 BLI_assert(duplicate_i - num_adjacent_faces == num_duplicates);
1309static void neighbor_coords_corner_edge_get(
const SubdivCCG &subdiv_ccg,
1311 const bool include_duplicates,
1314 neighbor_coords_edge_get(subdiv_ccg, coord, include_duplicates, r_neighbors);
1318static void neighbor_coords_corner_get(
const SubdivCCG &subdiv_ccg,
1320 const bool include_duplicates,
1323 if (coord.
x == 0 && coord.
y == 0) {
1324 neighbor_coords_corner_center_get(subdiv_ccg, coord, include_duplicates, r_neighbors);
1327 const int grid_size_1 = subdiv_ccg.
grid_size - 1;
1328 if (coord.
x == grid_size_1 && coord.
y == grid_size_1) {
1329 neighbor_coords_corner_vertex_get(subdiv_ccg, coord, include_duplicates, r_neighbors);
1332 neighbor_coords_corner_edge_get(subdiv_ccg, coord, include_duplicates, r_neighbors);
1340static void neighbor_coords_boundary_inner_get(
const SubdivCCG &subdiv_ccg,
1342 const bool include_duplicates,
1352 r_neighbors.
coords[3].grid_index = prev_grid_index_from_coord(subdiv_ccg, coord);
1353 r_neighbors.
coords[3].x = coord.
y;
1354 r_neighbors.
coords[3].y = 1;
1356 if (include_duplicates) {
1358 r_neighbors.
coords[4].y = 0;
1361 else if (coord.
y == 0) {
1366 r_neighbors.
coords[3].grid_index = next_grid_index_from_coord(subdiv_ccg, coord);
1367 r_neighbors.
coords[3].x = 1;
1368 r_neighbors.
coords[3].y = coord.
x;
1370 if (include_duplicates) {
1372 r_neighbors.
coords[4].x = 0;
1378static void neighbor_coords_boundary_outer_get(
const SubdivCCG &subdiv_ccg,
1380 const bool include_duplicates,
1383 neighbor_coords_edge_get(subdiv_ccg, coord, include_duplicates, r_neighbors);
1389static void neighbor_coords_boundary_get(
const SubdivCCG &subdiv_ccg,
1391 const bool include_duplicates,
1395 neighbor_coords_boundary_inner_get(subdiv_ccg, coord, include_duplicates, r_neighbors);
1398 neighbor_coords_boundary_outer_get(subdiv_ccg, coord, include_duplicates, r_neighbors);
1403static void neighbor_coords_inner_get(
const SubdivCCG &subdiv_ccg,
1419 const bool include_duplicates,
1422#ifdef WITH_OPENSUBDIV
1431 neighbor_coords_corner_get(subdiv_ccg, coord, include_duplicates, r_neighbors);
1434 neighbor_coords_boundary_get(subdiv_ccg, coord, include_duplicates, r_neighbors);
1437 neighbor_coords_inner_get(subdiv_ccg, coord, r_neighbors);
1446 UNUSED_VARS(subdiv_ccg, coord, include_duplicates, r_neighbors);
1457 const int grid_size_1 = subdiv_ccg.
grid_size - 1;
1463 if (coord.
x == grid_size_1) {
1465 r_v2 = corner_verts[
next];
1467 if (coord.
y == grid_size_1) {
1469 r_v2 = corner_verts[prev];
1482 const int grid_size_1 = subdiv_ccg.
grid_size - 1;
1484 if (coord.
x == 0 && coord.
y == 0) {
1488 if (coord.
x == grid_size_1 && coord.
y == grid_size_1) {
1490 r_v1 = r_v2 = corner_verts[coord.
grid_index];
1502 subdiv_ccg, coord, corner_verts,
faces, r_v1, r_v2);
1517 subdiv_ccg, coord, corner_verts,
faces, v1,
v2);
1518 switch (adjacency) {
1520 return boundary_verts[v1];
1522 return boundary_verts[v1] && boundary_verts[
v2];
1533 const int grid_area = subdiv_ccg.
grid_area;
1546 int &r_ptex_face_index,
1552 const float grid_size = subdiv_ccg.
grid_size;
1553 const float grid_size_1_inv = 1.0f / (grid_size - 1);
1555 const float grid_u = coord.
x * grid_size_1_inv;
1556 const float grid_v = coord.
y * grid_size_1_inv;
1562 r_ptex_face_index = face_ptex_offset[face_index];
1566 if (face.
size() == 4) {
1570 r_ptex_face_index += corner;
1571 r_u = 1.0f - grid_v;
1572 r_v = 1.0f - grid_u;
1578 const int grid_index,
1589 int ptex_face_index;
int CCG_grid_xy_to_index(const int grid_size, const int x, const int y)
Mesh * BKE_mesh_copy_for_eval(const Mesh &source)
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)
#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.
ATTR_WARN_UNUSED_RESULT const void * element
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMVert * v
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
IndexRange index_range() const
void reinitialize(const int64_t new_size)
static IndexMask from_indices(Span< T > indices, IndexMaskMemory &memory)
void foreach_index(Fn &&fn) const
void foreach_segment(Fn &&fn) const
void append(const T &value)
constexpr int64_t size() const
constexpr int64_t start() const
void add_multiple(Span< Key > keys)
constexpr int64_t size() const
IndexRange index_range() const
void reinitialize(const int64_t new_size)
const OpenSubdiv::Far::TopologyLevel & base_level() const
ccl_device_inline float2 mask(const MaskType mask, const float2 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)
float3 eval_final_point(Subdiv *subdiv, int ptex_face_index, float u, float v)
bool eval_begin_from_mesh(Subdiv *subdiv, const Mesh *mesh, eSubdivEvaluatorType evaluator_type, Span< float3 > coarse_vert_positions={}, OpenSubdiv_EvaluatorCache *evaluator_cache=nullptr)
float3 eval_limit_point(Subdiv *subdiv, int ptex_face_index, float u, float v)
BLI_INLINE void rotate_grid_to_quad(int corner, float grid_u, float grid_v, float *r_quad_u, float *r_quad_v)
void eval_limit_point_and_normal(Subdiv *subdiv, int ptex_face_index, float u, float v, float3 &r_P, float3 &r_N)
BLI_INLINE int grid_size_from_level(int level)
@ SUBDIV_EVALUATOR_TYPE_CPU
void stats_begin(SubdivStats *stats, StatsValue value)
void stats_end(SubdivStats *stats, StatsValue value)
@ SUBDIV_STATS_SUBDIV_TO_CCG
Span< int > face_ptex_offset_get(Subdiv *subdiv)
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
VecBase< float, 3 > float3
blender::Vector< blender::Array< SubdivCCGCoord > > boundary_coords
blender::Vector< SubdivCCGCoord > corner_coords
float(* eval_mask)(SubdivCCGMaskEvaluator *mask_evaluator, int ptex_face_index, float u, float v)
void(* free)(SubdivCCGMaskEvaluator *mask_evaluator)
SubdivCCGNeighborCoords coords
blender::Array< blender::float3 > normals
blender::BitGroupVector grid_hidden
blender::Array< float > masks
blender::Array< SubdivCCGAdjacentVertex > adjacent_verts
blender::bke::subdiv::Subdiv * subdiv
blender::OffsetIndices< int > faces
blender::Array< SubdivCCGAdjacentEdge > adjacent_edges
blender::Span< int > grid_to_face_map
blender::Array< blender::float3 > positions
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)
void BKE_subdiv_ccg_recalc_normals(SubdivCCG &subdiv_ccg)
CCGKey BKE_subdiv_ccg_key_top_level(const SubdivCCG &subdiv_ccg)
Mesh * BKE_subdiv_to_ccg_mesh(Subdiv &subdiv, const SubdivToCCGSettings &settings, const Mesh &coarse_mesh)
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)
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)
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)