Changeset View
Changeset View
Standalone View
Standalone View
source/blender/blenkernel/intern/subdiv_ccg.c
| Show First 20 Lines • Show All 1,736 Lines • ▼ Show 20 Lines | static void neighbor_coords_boundary_get(const SubdivCCG *subdiv_ccg, | ||||
| else { | else { | ||||
| neighbor_coords_boundary_outer_get(subdiv_ccg, coord, include_duplicates, r_neighbors); | neighbor_coords_boundary_outer_get(subdiv_ccg, coord, include_duplicates, r_neighbors); | ||||
| } | } | ||||
| } | } | ||||
| /* Input coordinate is inside of its grid, all the neighbors belong to the same grid. */ | /* Input coordinate is inside of its grid, all the neighbors belong to the same grid. */ | ||||
| static void neighbor_coords_inner_get(const SubdivCCG *subdiv_ccg, | static void neighbor_coords_inner_get(const SubdivCCG *subdiv_ccg, | ||||
| const SubdivCCGCoord *coord, | const SubdivCCGCoord *coord, | ||||
| const bool include_duplicates, | |||||
| SubdivCCGNeighbors *r_neighbors) | SubdivCCGNeighbors *r_neighbors) | ||||
| { | { | ||||
| subdiv_ccg_neighbors_init(r_neighbors, 4, 0); | subdiv_ccg_neighbors_init(r_neighbors, 4, 0); | ||||
| r_neighbors->coords[0] = coord_at_prev_row(subdiv_ccg, coord); | r_neighbors->coords[0] = coord_at_prev_row(subdiv_ccg, coord); | ||||
| r_neighbors->coords[1] = coord_at_next_row(subdiv_ccg, coord); | r_neighbors->coords[1] = coord_at_next_row(subdiv_ccg, coord); | ||||
| r_neighbors->coords[2] = coord_at_prev_col(subdiv_ccg, coord); | r_neighbors->coords[2] = coord_at_prev_col(subdiv_ccg, coord); | ||||
| r_neighbors->coords[3] = coord_at_next_col(subdiv_ccg, coord); | r_neighbors->coords[3] = coord_at_next_col(subdiv_ccg, coord); | ||||
| if (include_duplicates) { | |||||
| for (int i = 0; i < 4; i++) { | |||||
| if (is_boundary_grid_coord(subdiv_ccg, &r_neighbors->coords[i])) { | |||||
| } | |||||
| } | |||||
| } | |||||
| } | } | ||||
| void BKE_subdiv_ccg_neighbor_coords_get(const SubdivCCG *subdiv_ccg, | void BKE_subdiv_ccg_neighbor_coords_get(const SubdivCCG *subdiv_ccg, | ||||
| const SubdivCCGCoord *coord, | const SubdivCCGCoord *coord, | ||||
| const bool include_duplicates, | const bool include_duplicates, | ||||
| SubdivCCGNeighbors *r_neighbors) | SubdivCCGNeighbors *r_neighbors) | ||||
| { | { | ||||
| BLI_assert(coord->grid_index >= 0); | BLI_assert(coord->grid_index >= 0); | ||||
| BLI_assert(coord->grid_index < subdiv_ccg->num_grids); | BLI_assert(coord->grid_index < subdiv_ccg->num_grids); | ||||
| BLI_assert(coord->x >= 0); | BLI_assert(coord->x >= 0); | ||||
| BLI_assert(coord->x < subdiv_ccg->grid_size); | BLI_assert(coord->x < subdiv_ccg->grid_size); | ||||
| BLI_assert(coord->y >= 0); | BLI_assert(coord->y >= 0); | ||||
| BLI_assert(coord->y < subdiv_ccg->grid_size); | BLI_assert(coord->y < subdiv_ccg->grid_size); | ||||
| if (is_corner_grid_coord(subdiv_ccg, coord)) { | if (is_corner_grid_coord(subdiv_ccg, coord)) { | ||||
| neighbor_coords_corner_get(subdiv_ccg, coord, include_duplicates, r_neighbors); | neighbor_coords_corner_get(subdiv_ccg, coord, include_duplicates, r_neighbors); | ||||
| } | } | ||||
| else if (is_boundary_grid_coord(subdiv_ccg, coord)) { | else if (is_boundary_grid_coord(subdiv_ccg, coord)) { | ||||
| neighbor_coords_boundary_get(subdiv_ccg, coord, include_duplicates, r_neighbors); | neighbor_coords_boundary_get(subdiv_ccg, coord, include_duplicates, r_neighbors); | ||||
| } | } | ||||
| else { | else { | ||||
| neighbor_coords_inner_get(subdiv_ccg, coord, r_neighbors); | neighbor_coords_inner_get(subdiv_ccg, coord, include_duplicates, r_neighbors); | ||||
| } | } | ||||
| #ifndef NDEBUG | #ifndef NDEBUG | ||||
| for (int i = 0; i < r_neighbors->size; i++) { | for (int i = 0; i < r_neighbors->size; i++) { | ||||
| BLI_assert(BKE_subdiv_ccg_check_coord_valid(subdiv_ccg, &r_neighbors->coords[i])); | BLI_assert(BKE_subdiv_ccg_check_coord_valid(subdiv_ccg, &r_neighbors->coords[i])); | ||||
| } | } | ||||
| #endif | #endif | ||||
| } | } | ||||
| static bool is_duplicate_in_coarse_mesh_vertex(const SubdivCCG *subdiv_ccg, | |||||
| const SubdivCCGCoord *coord) | |||||
| { | |||||
| Subdiv *subdiv = subdiv_ccg->subdiv; | |||||
| OpenSubdiv_TopologyRefiner *topology_refiner = subdiv->topology_refiner; | |||||
| const int adjacent_vertex_index = adjacent_vertex_index_from_coord(subdiv_ccg, coord); | |||||
| BLI_assert(adjacent_vertex_index >= 0); | |||||
| BLI_assert(adjacent_vertex_index < subdiv_ccg->num_adjacent_vertices); | |||||
| const int num_vertex_edges = topology_refiner->getNumVertexEdges(topology_refiner, | |||||
| adjacent_vertex_index); | |||||
| SubdivCCGAdjacentVertex *adjacent_vertex = &subdiv_ccg->adjacent_vertices[adjacent_vertex_index]; | |||||
| const int num_adjacent_faces = adjacent_vertex->num_adjacent_faces; | |||||
| StaticOrHeapIntStorage vertex_edges_storage; | |||||
| static_or_heap_storage_init(&vertex_edges_storage); | |||||
| int *vertex_edges = static_or_heap_storage_get(&vertex_edges_storage, num_vertex_edges); | |||||
| topology_refiner->getVertexEdges(topology_refiner, adjacent_vertex_index, vertex_edges); | |||||
| for (int i = 0; i < num_vertex_edges; ++i) { | |||||
| const int edge_index = vertex_edges[i]; | |||||
| /* Use very first grid of every edge. */ | |||||
| const int edge_face_index = 0; | |||||
| /* Depending edge orientation we use first (zero-based) or previous-to-last point. */ | |||||
| int edge_vertices_indices[2]; | |||||
| topology_refiner->getEdgeVertices(topology_refiner, edge_index, edge_vertices_indices); | |||||
| int edge_point_index, duplicate_edge_point_index; | |||||
| if (edge_vertices_indices[0] == adjacent_vertex_index) { | |||||
| duplicate_edge_point_index = 0; | |||||
| edge_point_index = duplicate_edge_point_index + 1; | |||||
| } | |||||
| else { | |||||
| /* Edge "consists" of 2 grids, which makes it 2 * grid_size elements per edge. | |||||
| * The index of last edge element is 2 * grid_size - 1 (due to zero-based indices), | |||||
| * and we are interested in previous to last element. */ | |||||
| duplicate_edge_point_index = subdiv_ccg->grid_size * 2 - 1; | |||||
| edge_point_index = duplicate_edge_point_index - 1; | |||||
| } | |||||
| SubdivCCGAdjacentEdge *adjacent_edge = &subdiv_ccg->adjacent_edges[edge_index]; | |||||
| SubdivCCGCoord *grid_coord = | |||||
| &adjacent_edge->boundary_coords[edge_face_index][edge_point_index]; | |||||
| if (subdiv_ccg->grid_faces[grid_coord->grid_index] > | |||||
| subdiv_ccg->grid_faces[coord->grid_index]) { | |||||
| return true; | |||||
| } | |||||
| } | |||||
| for (int i = 0; i < num_adjacent_faces; i++) { | |||||
| SubdivCCGCoord neighbor_coord = adjacent_vertex->corner_coords[i]; | |||||
| if (subdiv_ccg->grid_faces[neighbor_coord.grid_index] > | |||||
| subdiv_ccg->grid_faces[coord->grid_index]) { | |||||
| return true; | |||||
| } | |||||
| } | |||||
| static_or_heap_storage_free(&vertex_edges_storage); | |||||
| return false; | |||||
| } | |||||
| static bool is_duplicate_in_coarse_mesh_edge(const SubdivCCG *subdiv_ccg, | |||||
| const SubdivCCGCoord *coord) | |||||
| { | |||||
| const int adjacent_edge_index = adjacent_edge_index_from_coord(subdiv_ccg, coord); | |||||
| const SubdivCCGAdjacentEdge *adjacent_edge = &subdiv_ccg->adjacent_edges[adjacent_edge_index]; | |||||
| const int num_adjacent_faces = adjacent_edge->num_adjacent_faces; | |||||
| const int point_index = adjacent_edge_point_index_from_coord( | |||||
| subdiv_ccg, coord, adjacent_edge_index); | |||||
| const int next_point_index = next_adjacent_edge_point_index(subdiv_ccg, point_index); | |||||
| const int prev_point_index = prev_adjacent_edge_point_index(subdiv_ccg, point_index); | |||||
| for (int i = 0; i < num_adjacent_faces; i++) { | |||||
| SubdivCCGCoord *boundary_coords = adjacent_edge->boundary_coords[i]; | |||||
| SubdivCCGCoord grid_coord = boundary_coords[point_index]; | |||||
| if (coord_step_inside_from_boundary(subdiv_ccg, &grid_coord).grid_index > coord->grid_index) { | |||||
| return true; | |||||
| } | |||||
| if (boundary_coords[next_point_index].grid_index > coord->grid_index) { | |||||
| return true; | |||||
| } | |||||
| if (boundary_coords[prev_point_index].grid_index > coord->grid_index) { | |||||
| return true; | |||||
| } | |||||
| } | |||||
| return false; | |||||
| } | |||||
| bool BKE_subdiv_ccg_is_duplicate(const SubdivCCG *subdiv_ccg, const SubdivCCGCoord *coord) | |||||
| { | |||||
| BLI_assert(coord->grid_index >= 0); | |||||
| BLI_assert(coord->grid_index < subdiv_ccg->num_grids); | |||||
| BLI_assert(coord->x >= 0); | |||||
| BLI_assert(coord->x < subdiv_ccg->grid_size); | |||||
| BLI_assert(coord->y >= 0); | |||||
| BLI_assert(coord->y < subdiv_ccg->grid_size); | |||||
| if (is_corner_grid_coord(subdiv_ccg, coord)) { | |||||
| if (coord->x == 0 && coord->y == 0) { | |||||
| SubdivCCGFace *face = subdiv_ccg->grid_faces[coord->grid_index]; | |||||
| return coord->grid_index > face->start_grid_index; | |||||
| } | |||||
| else { | |||||
| const int grid_size_1 = subdiv_ccg->grid_size - 1; | |||||
| if (coord->x == grid_size_1 && coord->y == grid_size_1) { | |||||
| return is_duplicate_in_coarse_mesh_vertex(subdiv_ccg, coord); | |||||
| } | |||||
| else { | |||||
| return is_duplicate_in_coarse_mesh_edge(subdiv_ccg, coord); | |||||
| } | |||||
| } | |||||
| } | |||||
| if (is_boundary_grid_coord(subdiv_ccg, coord)) { | |||||
| if (is_inner_edge_grid_coordinate(subdiv_ccg, coord)) { | |||||
| if (coord->x == 0) { | |||||
| int grid_index = prev_grid_index_from_coord(subdiv_ccg, coord); | |||||
| return coord->grid_index < grid_index; | |||||
| } | |||||
| if (coord->y == 0) { | |||||
| int grid_index = next_grid_index_from_coord(subdiv_ccg, coord); | |||||
| return coord->grid_index < grid_index; | |||||
| } | |||||
| } | |||||
| else { | |||||
| return is_duplicate_in_coarse_mesh_edge(subdiv_ccg, coord); | |||||
| } | |||||
| } | |||||
| return false; | |||||
| } | |||||
| int BKE_subdiv_ccg_grid_to_face_index(const SubdivCCG *subdiv_ccg, const int grid_index) | int BKE_subdiv_ccg_grid_to_face_index(const SubdivCCG *subdiv_ccg, const int grid_index) | ||||
| { | { | ||||
| // Subdiv *subdiv = subdiv_ccg->subdiv; /* UNUSED */ | // Subdiv *subdiv = subdiv_ccg->subdiv; /* UNUSED */ | ||||
| // OpenSubdiv_TopologyRefiner *topology_refiner = subdiv->topology_refiner; /* UNUSED */ | // OpenSubdiv_TopologyRefiner *topology_refiner = subdiv->topology_refiner; /* UNUSED */ | ||||
| SubdivCCGFace *face = subdiv_ccg->grid_faces[grid_index]; | SubdivCCGFace *face = subdiv_ccg->grid_faces[grid_index]; | ||||
| // const int face_grid_index = grid_index - face->start_grid_index; /* UNUSED */ | // const int face_grid_index = grid_index - face->start_grid_index; /* UNUSED */ | ||||
| const int face_index = face - subdiv_ccg->faces; | const int face_index = face - subdiv_ccg->faces; | ||||
| return face_index; | return face_index; | ||||
| } | } | ||||