Changeset View
Changeset View
Standalone View
Standalone View
source/blender/blenkernel/intern/subdiv_ccg.c
| Context not available. | |||||
| subdiv_ccg->num_adjacent_edges, sizeof(*subdiv_ccg->adjacent_edges), "ccg adjacent edges"); | subdiv_ccg->num_adjacent_edges, sizeof(*subdiv_ccg->adjacent_edges), "ccg adjacent edges"); | ||||
| } | } | ||||
| static SubdivCCGCoord subdiv_ccg_coord(int grid_index, int x, int y) | |||||
| { | |||||
| SubdivCCGCoord coord = {.grid_index = grid_index, .x = x, .y = y}; | |||||
| return coord; | |||||
| } | |||||
| static CCGElem *subdiv_ccg_coord_to_elem(const CCGKey *key, | |||||
| const SubdivCCG *subdiv_ccg, | |||||
| const SubdivCCGCoord *coord) | |||||
| { | |||||
| return CCG_grid_elem(key, subdiv_ccg->grids[coord->grid_index], coord->x, coord->y); | |||||
| } | |||||
| /* Returns storage where boundary elements are to be stored. */ | /* Returns storage where boundary elements are to be stored. */ | ||||
| static SubdivCCGCoord *subdiv_ccg_adjacent_edge_add_face(SubdivCCG *subdiv_ccg, | static CCGElem **subdiv_ccg_adjacent_edge_add_face(SubdivCCG *subdiv_ccg, | ||||
| SubdivCCGAdjacentEdge *adjacent_edge) | SubdivCCGAdjacentEdge *adjacent_edge) | ||||
| { | { | ||||
| const int grid_size = subdiv_ccg->grid_size * 2; | const int grid_size = subdiv_ccg->grid_size * 2; | ||||
| const int adjacent_face_index = adjacent_edge->num_adjacent_faces; | const int adjacent_face_index = adjacent_edge->num_adjacent_faces; | ||||
| ++adjacent_edge->num_adjacent_faces; | ++adjacent_edge->num_adjacent_faces; | ||||
| /* Allocate memory for the boundary elements. */ | /* Allocate memory for the boundary elements. */ | ||||
| adjacent_edge->boundary_coords = MEM_reallocN(adjacent_edge->boundary_coords, | adjacent_edge->boundary_elements = MEM_reallocN(adjacent_edge->boundary_elements, | ||||
| adjacent_edge->num_adjacent_faces * | adjacent_edge->num_adjacent_faces * | ||||
| sizeof(*adjacent_edge->boundary_coords)); | sizeof(*adjacent_edge->boundary_elements)); | ||||
| adjacent_edge->boundary_coords[adjacent_face_index] = MEM_malloc_arrayN( | adjacent_edge->boundary_elements[adjacent_face_index] = MEM_malloc_arrayN( | ||||
| grid_size * 2, sizeof(SubdivCCGCoord), "ccg adjacent boundary"); | grid_size * 2, sizeof(CCGElem *), "ccg adjacent boundary"); | ||||
| return adjacent_edge->boundary_coords[adjacent_face_index]; | return adjacent_edge->boundary_elements[adjacent_face_index]; | ||||
| } | } | ||||
| static void subdiv_ccg_init_faces_edge_neighborhood(SubdivCCG *subdiv_ccg) | static void subdiv_ccg_init_faces_edge_neighborhood(SubdivCCG *subdiv_ccg) | ||||
| Context not available. | |||||
| StaticOrHeapIntStorage face_edges_storage; | StaticOrHeapIntStorage face_edges_storage; | ||||
| static_or_heap_storage_init(&face_vertices_storage); | static_or_heap_storage_init(&face_vertices_storage); | ||||
| static_or_heap_storage_init(&face_edges_storage); | static_or_heap_storage_init(&face_edges_storage); | ||||
| /* Key to access elements. */ | |||||
| CCGKey key; | |||||
| BKE_subdiv_ccg_key_top_level(&key, subdiv_ccg); | |||||
| /* Store adjacency for all faces. */ | /* Store adjacency for all faces. */ | ||||
| const int num_faces = subdiv_ccg->num_faces; | const int num_faces = subdiv_ccg->num_faces; | ||||
| for (int face_index = 0; face_index < num_faces; face_index++) { | for (int face_index = 0; face_index < num_faces; face_index++) { | ||||
| Context not available. | |||||
| const bool is_edge_flipped = (edge_vertices[0] != vertex_index); | const bool is_edge_flipped = (edge_vertices[0] != vertex_index); | ||||
| /* Grid which is adjacent to the current corner. */ | /* Grid which is adjacent to the current corner. */ | ||||
| const int current_grid_index = face->start_grid_index + corner; | const int current_grid_index = face->start_grid_index + corner; | ||||
| CCGElem *current_grid = subdiv_ccg->grids[current_grid_index]; | |||||
| /* Grid which is adjacent to the next corner. */ | /* Grid which is adjacent to the next corner. */ | ||||
| const int next_grid_index = face->start_grid_index + (corner + 1) % num_face_grids; | const int next_grid_index = face->start_grid_index + (corner + 1) % num_face_grids; | ||||
| CCGElem *next_grid = subdiv_ccg->grids[next_grid_index]; | |||||
| /* Add new face to the adjacent edge. */ | /* Add new face to the adjacent edge. */ | ||||
| SubdivCCGAdjacentEdge *adjacent_edge = &subdiv_ccg->adjacent_edges[edge_index]; | SubdivCCGAdjacentEdge *adjacent_edge = &subdiv_ccg->adjacent_edges[edge_index]; | ||||
| SubdivCCGCoord *boundary_coords = subdiv_ccg_adjacent_edge_add_face(subdiv_ccg, | CCGElem **boundary_elements = subdiv_ccg_adjacent_edge_add_face(subdiv_ccg, adjacent_edge); | ||||
| adjacent_edge); | |||||
| /* Fill CCG elements along the edge. */ | /* Fill CCG elements along the edge. */ | ||||
| int boundary_element_index = 0; | int boundary_element_index = 0; | ||||
| if (is_edge_flipped) { | if (is_edge_flipped) { | ||||
| for (int i = 0; i < grid_size; i++) { | for (int i = 0; i < grid_size; i++) { | ||||
| boundary_coords[boundary_element_index++] = subdiv_ccg_coord( | boundary_elements[boundary_element_index++] = CCG_grid_elem( | ||||
| next_grid_index, grid_size - i - 1, grid_size - 1); | &key, next_grid, grid_size - i - 1, grid_size - 1); | ||||
| } | } | ||||
| for (int i = 0; i < grid_size; i++) { | for (int i = 0; i < grid_size; i++) { | ||||
| boundary_coords[boundary_element_index++] = subdiv_ccg_coord( | boundary_elements[boundary_element_index++] = CCG_grid_elem( | ||||
| current_grid_index, grid_size - 1, i); | &key, current_grid, grid_size - 1, i); | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| for (int i = 0; i < grid_size; i++) { | for (int i = 0; i < grid_size; i++) { | ||||
| boundary_coords[boundary_element_index++] = subdiv_ccg_coord( | boundary_elements[boundary_element_index++] = CCG_grid_elem( | ||||
| current_grid_index, grid_size - 1, grid_size - i - 1); | &key, current_grid, grid_size - 1, grid_size - i - 1); | ||||
| } | } | ||||
| for (int i = 0; i < grid_size; i++) { | for (int i = 0; i < grid_size; i++) { | ||||
| boundary_coords[boundary_element_index++] = subdiv_ccg_coord( | boundary_elements[boundary_element_index++] = CCG_grid_elem( | ||||
| next_grid_index, i, grid_size - 1); | &key, next_grid, i, grid_size - 1); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| Context not available. | |||||
| /* Returns storage where corner elements are to be stored. This is a pointer | /* Returns storage where corner elements are to be stored. This is a pointer | ||||
| * to the actual storage. */ | * to the actual storage. */ | ||||
| static SubdivCCGCoord *subdiv_ccg_adjacent_vertex_add_face( | static CCGElem **subdiv_ccg_adjacent_vertex_add_face(SubdivCCGAdjacentVertex *adjacent_vertex) | ||||
| SubdivCCGAdjacentVertex *adjacent_vertex) | |||||
| { | { | ||||
| const int adjacent_face_index = adjacent_vertex->num_adjacent_faces; | const int adjacent_face_index = adjacent_vertex->num_adjacent_faces; | ||||
| ++adjacent_vertex->num_adjacent_faces; | ++adjacent_vertex->num_adjacent_faces; | ||||
| /* Allocate memory for the boundary elements. */ | /* Allocate memory for the boundary elements. */ | ||||
| adjacent_vertex->corner_coords = MEM_reallocN(adjacent_vertex->corner_coords, | adjacent_vertex->corner_elements = MEM_reallocN(adjacent_vertex->corner_elements, | ||||
| adjacent_vertex->num_adjacent_faces * | adjacent_vertex->num_adjacent_faces * | ||||
| sizeof(*adjacent_vertex->corner_coords)); | sizeof(*adjacent_vertex->corner_elements)); | ||||
| return &adjacent_vertex->corner_coords[adjacent_face_index]; | return &adjacent_vertex->corner_elements[adjacent_face_index]; | ||||
| } | } | ||||
| static void subdiv_ccg_init_faces_vertex_neighborhood(SubdivCCG *subdiv_ccg) | static void subdiv_ccg_init_faces_vertex_neighborhood(SubdivCCG *subdiv_ccg) | ||||
| Context not available. | |||||
| const int vertex_index = face_vertices[corner]; | const int vertex_index = face_vertices[corner]; | ||||
| /* Grid which is adjacent to the current corner. */ | /* Grid which is adjacent to the current corner. */ | ||||
| const int grid_index = face->start_grid_index + corner; | const int grid_index = face->start_grid_index + corner; | ||||
| CCGElem *grid = subdiv_ccg->grids[grid_index]; | |||||
| /* Add new face to the adjacent edge. */ | /* Add new face to the adjacent edge. */ | ||||
| SubdivCCGAdjacentVertex *adjacent_vertex = &subdiv_ccg->adjacent_vertices[vertex_index]; | SubdivCCGAdjacentVertex *adjacent_vertex = &subdiv_ccg->adjacent_vertices[vertex_index]; | ||||
| SubdivCCGCoord *corner_coord = subdiv_ccg_adjacent_vertex_add_face(adjacent_vertex); | CCGElem **corner_element = subdiv_ccg_adjacent_vertex_add_face(adjacent_vertex); | ||||
| *corner_coord = subdiv_ccg_coord(grid_index, grid_size - 1, grid_size - 1); | *corner_element = CCG_grid_elem(&key, grid, grid_size - 1, grid_size - 1); | ||||
| } | } | ||||
| } | } | ||||
| /* Free possibly heap-allocated storage. */ | /* Free possibly heap-allocated storage. */ | ||||
| Context not available. | |||||
| for (int i = 0; i < subdiv_ccg->num_adjacent_edges; i++) { | for (int i = 0; i < subdiv_ccg->num_adjacent_edges; i++) { | ||||
| SubdivCCGAdjacentEdge *adjacent_edge = &subdiv_ccg->adjacent_edges[i]; | SubdivCCGAdjacentEdge *adjacent_edge = &subdiv_ccg->adjacent_edges[i]; | ||||
| for (int face_index = 0; face_index < adjacent_edge->num_adjacent_faces; face_index++) { | for (int face_index = 0; face_index < adjacent_edge->num_adjacent_faces; face_index++) { | ||||
| MEM_SAFE_FREE(adjacent_edge->boundary_coords[face_index]); | MEM_SAFE_FREE(adjacent_edge->boundary_elements[face_index]); | ||||
| } | } | ||||
| MEM_SAFE_FREE(adjacent_edge->boundary_coords); | MEM_SAFE_FREE(adjacent_edge->boundary_elements); | ||||
| } | } | ||||
| MEM_SAFE_FREE(subdiv_ccg->adjacent_edges); | MEM_SAFE_FREE(subdiv_ccg->adjacent_edges); | ||||
| /* Free map of adjacent vertices. */ | /* Free map of adjacent vertices. */ | ||||
| for (int i = 0; i < subdiv_ccg->num_adjacent_vertices; i++) { | for (int i = 0; i < subdiv_ccg->num_adjacent_vertices; i++) { | ||||
| SubdivCCGAdjacentVertex *adjacent_vertex = &subdiv_ccg->adjacent_vertices[i]; | SubdivCCGAdjacentVertex *adjacent_vertex = &subdiv_ccg->adjacent_vertices[i]; | ||||
| MEM_SAFE_FREE(adjacent_vertex->corner_coords); | MEM_SAFE_FREE(adjacent_vertex->corner_elements); | ||||
| } | } | ||||
| MEM_SAFE_FREE(subdiv_ccg->adjacent_vertices); | MEM_SAFE_FREE(subdiv_ccg->adjacent_vertices); | ||||
| MEM_freeN(subdiv_ccg); | MEM_freeN(subdiv_ccg); | ||||
| Context not available. | |||||
| } | } | ||||
| for (int face_index = 0; face_index < num_adjacent_faces; face_index++) { | for (int face_index = 0; face_index < num_adjacent_faces; face_index++) { | ||||
| for (int i = 1; i < grid_size2 - 1; i++) { | for (int i = 1; i < grid_size2 - 1; i++) { | ||||
| CCGElem *grid_element = subdiv_ccg_coord_to_elem( | CCGElem *grid_element = adjacent_edge->boundary_elements[face_index][i]; | ||||
| key, subdiv_ccg, &adjacent_edge->boundary_coords[face_index][i]); | |||||
| element_accumulator_add(&tls->accumulators[i], subdiv_ccg, key, grid_element); | element_accumulator_add(&tls->accumulators[i], subdiv_ccg, key, grid_element); | ||||
| } | } | ||||
| } | } | ||||
| Context not available. | |||||
| /* Copy averaged value to all the other faces. */ | /* Copy averaged value to all the other faces. */ | ||||
| for (int face_index = 0; face_index < num_adjacent_faces; face_index++) { | for (int face_index = 0; face_index < num_adjacent_faces; face_index++) { | ||||
| for (int i = 1; i < grid_size2 - 1; i++) { | for (int i = 1; i < grid_size2 - 1; i++) { | ||||
| CCGElem *grid_element = subdiv_ccg_coord_to_elem( | CCGElem *grid_element = adjacent_edge->boundary_elements[face_index][i]; | ||||
| key, subdiv_ccg, &adjacent_edge->boundary_coords[face_index][i]); | |||||
| element_accumulator_copy(subdiv_ccg, key, grid_element, &tls->accumulators[i]); | element_accumulator_copy(subdiv_ccg, key, grid_element, &tls->accumulators[i]); | ||||
| } | } | ||||
| } | } | ||||
| Context not available. | |||||
| GridElementAccumulator accumulator; | GridElementAccumulator accumulator; | ||||
| element_accumulator_init(&accumulator); | element_accumulator_init(&accumulator); | ||||
| for (int face_index = 0; face_index < num_adjacent_faces; face_index++) { | for (int face_index = 0; face_index < num_adjacent_faces; face_index++) { | ||||
| CCGElem *grid_element = subdiv_ccg_coord_to_elem( | CCGElem *grid_element = adjacent_vertex->corner_elements[face_index]; | ||||
| key, subdiv_ccg, &adjacent_vertex->corner_coords[face_index]); | |||||
| element_accumulator_add(&accumulator, subdiv_ccg, key, grid_element); | element_accumulator_add(&accumulator, subdiv_ccg, key, grid_element); | ||||
| } | } | ||||
| element_accumulator_mul_fl(&accumulator, 1.0f / (float)num_adjacent_faces); | element_accumulator_mul_fl(&accumulator, 1.0f / (float)num_adjacent_faces); | ||||
| /* Copy averaged value to all the other faces. */ | /* Copy averaged value to all the other faces. */ | ||||
| for (int face_index = 0; face_index < num_adjacent_faces; face_index++) { | for (int face_index = 0; face_index < num_adjacent_faces; face_index++) { | ||||
| CCGElem *grid_element = subdiv_ccg_coord_to_elem( | CCGElem *grid_element = adjacent_vertex->corner_elements[face_index]; | ||||
| key, subdiv_ccg, &adjacent_vertex->corner_coords[face_index]); | |||||
| element_accumulator_copy(subdiv_ccg, key, grid_element, &accumulator); | element_accumulator_copy(subdiv_ccg, key, grid_element, &accumulator); | ||||
| } | } | ||||
| } | } | ||||
| Context not available. | |||||
| return true; | return true; | ||||
| } | } | ||||
| BLI_INLINE void subdiv_ccg_neighbors_init(SubdivCCGNeighbors *neighbors, | BLI_INLINE void subdiv_ccg_neighbors_init(SubdivCCGNeighbors *neighbors, int size) | ||||
| const int num_unique, | |||||
| const int num_duplicates) | |||||
| { | { | ||||
| const int size = num_unique + num_duplicates; | |||||
| neighbors->size = size; | neighbors->size = size; | ||||
| neighbors->num_duplicates = num_duplicates; | |||||
| if (size < ARRAY_SIZE(neighbors->coords_fixed)) { | if (size < ARRAY_SIZE(neighbors->coords_fixed)) { | ||||
| neighbors->coords = neighbors->coords_fixed; | neighbors->coords = neighbors->coords_fixed; | ||||
| } | } | ||||
| Context not available. | |||||
| return result; | return result; | ||||
| } | } | ||||
| BLI_INLINE SubdivCCGCoord coord_from_ccg_element(const SubdivCCG *subdiv_ccg, CCGElem *element) | |||||
| { | |||||
| const size_t element_data_offset = (unsigned char *)element - subdiv_ccg->grids_storage; | |||||
| const size_t element_global_index = element_data_offset / subdiv_ccg->grid_element_size; | |||||
| const int grid_area = subdiv_ccg->grid_size * subdiv_ccg->grid_size; | |||||
| const int grid_index = element_global_index / grid_area; | |||||
| const size_t grid_start_element_index = grid_index * grid_area; | |||||
| const int element_grid_index = element_global_index - grid_start_element_index; | |||||
| const int y = element_grid_index / subdiv_ccg->grid_size; | |||||
| const int x = element_grid_index - y * subdiv_ccg->grid_size; | |||||
| SubdivCCGCoord result; | |||||
| result.grid_index = grid_index; | |||||
| result.x = x; | |||||
| result.y = y; | |||||
| return result; | |||||
| } | |||||
| /* For the input coordinate which is at the boundary of the grid do one step inside. */ | /* For the input coordinate which is at the boundary of the grid do one step inside. */ | ||||
| static SubdivCCGCoord coord_step_inside_from_boundary(const SubdivCCG *subdiv_ccg, | static SubdivCCGCoord coord_step_inside_from_boundary(const SubdivCCG *subdiv_ccg, | ||||
| const SubdivCCGCoord *coord) | const SubdivCCGCoord *coord) | ||||
| Context not available. | |||||
| * can only iterate over grid of a single face, without looking into adjacency. */ | * can only iterate over grid of a single face, without looking into adjacency. */ | ||||
| static void neighbor_coords_corner_center_get(const SubdivCCG *subdiv_ccg, | static void neighbor_coords_corner_center_get(const SubdivCCG *subdiv_ccg, | ||||
| const SubdivCCGCoord *coord, | const SubdivCCGCoord *coord, | ||||
| const bool include_duplicates, | |||||
| SubdivCCGNeighbors *r_neighbors) | SubdivCCGNeighbors *r_neighbors) | ||||
| { | { | ||||
| SubdivCCGFace *face = subdiv_ccg->grid_faces[coord->grid_index]; | SubdivCCGFace *face = subdiv_ccg->grid_faces[coord->grid_index]; | ||||
| const int num_adjacent_grids = face->num_grids; | |||||
| subdiv_ccg_neighbors_init( | subdiv_ccg_neighbors_init(r_neighbors, face->num_grids); | ||||
| r_neighbors, num_adjacent_grids, (include_duplicates) ? num_adjacent_grids - 1 : 0); | |||||
| int duplicate_face_grid_index = num_adjacent_grids; | for (int face_grid_index = 0; face_grid_index < face->num_grids; ++face_grid_index) { | ||||
| for (int face_grid_index = 0; face_grid_index < num_adjacent_grids; ++face_grid_index) { | |||||
| SubdivCCGCoord neighbor_coord; | SubdivCCGCoord neighbor_coord; | ||||
| neighbor_coord.grid_index = face->start_grid_index + face_grid_index; | neighbor_coord.grid_index = face->start_grid_index + face_grid_index; | ||||
| neighbor_coord.x = 1; | neighbor_coord.x = 1; | ||||
| neighbor_coord.y = 0; | neighbor_coord.y = 0; | ||||
| r_neighbors->coords[face_grid_index] = neighbor_coord; | r_neighbors->coords[face_grid_index] = neighbor_coord; | ||||
| if (include_duplicates && neighbor_coord.grid_index != coord->grid_index) { | |||||
| neighbor_coord.x = 0; | |||||
| r_neighbors->coords[duplicate_face_grid_index++] = neighbor_coord; | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| Context not available. | |||||
| /* The corner is adjacent to a coarse vertex. */ | /* The corner is adjacent to a coarse vertex. */ | ||||
| static void neighbor_coords_corner_vertex_get(const SubdivCCG *subdiv_ccg, | static void neighbor_coords_corner_vertex_get(const SubdivCCG *subdiv_ccg, | ||||
| const SubdivCCGCoord *coord, | const SubdivCCGCoord *coord, | ||||
| const bool include_duplicates, | |||||
| SubdivCCGNeighbors *r_neighbors) | SubdivCCGNeighbors *r_neighbors) | ||||
| { | { | ||||
| Subdiv *subdiv = subdiv_ccg->subdiv; | Subdiv *subdiv = subdiv_ccg->subdiv; | ||||
| Context not available. | |||||
| const int num_vertex_edges = topology_refiner->getNumVertexEdges(topology_refiner, | const int num_vertex_edges = topology_refiner->getNumVertexEdges(topology_refiner, | ||||
| adjacent_vertex_index); | adjacent_vertex_index); | ||||
| SubdivCCGAdjacentVertex *adjacent_vertex = &subdiv_ccg->adjacent_vertices[adjacent_vertex_index]; | subdiv_ccg_neighbors_init(r_neighbors, num_vertex_edges); | ||||
| const int num_adjacent_faces = adjacent_vertex->num_adjacent_faces; | |||||
| subdiv_ccg_neighbors_init( | |||||
| r_neighbors, num_vertex_edges, (include_duplicates) ? num_adjacent_faces - 1 : 0); | |||||
| StaticOrHeapIntStorage vertex_edges_storage; | StaticOrHeapIntStorage vertex_edges_storage; | ||||
| static_or_heap_storage_init(&vertex_edges_storage); | static_or_heap_storage_init(&vertex_edges_storage); | ||||
| Context not available. | |||||
| /* Depending edge orientation we use first (zero-based) or previous-to-last point. */ | /* Depending edge orientation we use first (zero-based) or previous-to-last point. */ | ||||
| int edge_vertices_indices[2]; | int edge_vertices_indices[2]; | ||||
| topology_refiner->getEdgeVertices(topology_refiner, edge_index, edge_vertices_indices); | topology_refiner->getEdgeVertices(topology_refiner, edge_index, edge_vertices_indices); | ||||
| int edge_point_index, duplicate_edge_point_index; | int edge_point_index; | ||||
| if (edge_vertices_indices[0] == adjacent_vertex_index) { | if (edge_vertices_indices[0] == adjacent_vertex_index) { | ||||
| duplicate_edge_point_index = 0; | edge_point_index = 1; | ||||
| edge_point_index = duplicate_edge_point_index + 1; | |||||
| } | } | ||||
| else { | else { | ||||
| /* Edge "consists" of 2 grids, which makes it 2 * grid_size elements per edge. | /* 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), | * 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. */ | * and we are interested in previous to last element. */ | ||||
| duplicate_edge_point_index = subdiv_ccg->grid_size * 2 - 1; | edge_point_index = subdiv_ccg->grid_size * 2 - 2; | ||||
| edge_point_index = duplicate_edge_point_index - 1; | |||||
| } | } | ||||
| SubdivCCGAdjacentEdge *adjacent_edge = &subdiv_ccg->adjacent_edges[edge_index]; | SubdivCCGAdjacentEdge *adjacent_edge = &subdiv_ccg->adjacent_edges[edge_index]; | ||||
| r_neighbors->coords[i] = adjacent_edge->boundary_coords[edge_face_index][edge_point_index]; | CCGElem *boundary_element = | ||||
| } | adjacent_edge->boundary_elements[edge_face_index][edge_point_index]; | ||||
| if (include_duplicates) { | r_neighbors->coords[i] = coord_from_ccg_element(subdiv_ccg, boundary_element); | ||||
| /* Add duplicates of the current grid vertex in adjacent faces if requested. */ | |||||
| for (int i = 0, duplicate_i = num_vertex_edges; i < num_adjacent_faces; i++) { | |||||
| SubdivCCGCoord neighbor_coord = adjacent_vertex->corner_coords[i]; | |||||
| if (neighbor_coord.grid_index != coord->grid_index) { | |||||
| r_neighbors->coords[duplicate_i++] = neighbor_coord; | |||||
| } | |||||
| } | |||||
| } | } | ||||
| static_or_heap_storage_free(&vertex_edges_storage); | static_or_heap_storage_free(&vertex_edges_storage); | ||||
| Context not available. | |||||
| * coarse faces, but is not at the coarse vertex. */ | * coarse faces, but is not at the coarse vertex. */ | ||||
| static void neighbor_coords_edge_get(const SubdivCCG *subdiv_ccg, | static void neighbor_coords_edge_get(const SubdivCCG *subdiv_ccg, | ||||
| const SubdivCCGCoord *coord, | const SubdivCCGCoord *coord, | ||||
| const bool include_duplicates, | |||||
| SubdivCCGNeighbors *r_neighbors) | SubdivCCGNeighbors *r_neighbors) | ||||
| { | { | ||||
| Context not available. | |||||
| const SubdivCCGAdjacentEdge *adjacent_edge = &subdiv_ccg->adjacent_edges[adjacent_edge_index]; | const SubdivCCGAdjacentEdge *adjacent_edge = &subdiv_ccg->adjacent_edges[adjacent_edge_index]; | ||||
| /* 2 neighbor points along the edge, plus one inner point per every adjacent grid. */ | /* 2 neighbor points along the edge, plus one inner point per every adjacent grid. */ | ||||
| const int num_adjacent_faces = adjacent_edge->num_adjacent_faces; | const int num_neighbor_coord = adjacent_edge->num_adjacent_faces + 2; | ||||
| subdiv_ccg_neighbors_init( | subdiv_ccg_neighbors_init(r_neighbors, num_neighbor_coord); | ||||
| r_neighbors, num_adjacent_faces + 2, (include_duplicates) ? num_adjacent_faces - 1 : 0); | |||||
| const int point_index = adjacent_edge_point_index_from_coord( | const int point_index = adjacent_edge_point_index_from_coord( | ||||
| subdiv_ccg, coord, adjacent_edge_index); | subdiv_ccg, coord, adjacent_edge_index); | ||||
| const int next_point_index = next_adjacent_edge_point_index(subdiv_ccg, point_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); | const int prev_point_index = prev_adjacent_edge_point_index(subdiv_ccg, point_index); | ||||
| for (int i = 0, duplicate_i = num_adjacent_faces; i < num_adjacent_faces; ++i) { | r_neighbors->coords[0] = coord_from_ccg_element( | ||||
| SubdivCCGCoord *boundary_coords = adjacent_edge->boundary_coords[i]; | subdiv_ccg, adjacent_edge->boundary_elements[0][prev_point_index]); | ||||
| /* One step into the grid from the edge for each adjacent face. */ | r_neighbors->coords[1] = coord_from_ccg_element( | ||||
| SubdivCCGCoord grid_coord = boundary_coords[point_index]; | subdiv_ccg, adjacent_edge->boundary_elements[0][next_point_index]); | ||||
| r_neighbors->coords[i + 2] = coord_step_inside_from_boundary(subdiv_ccg, &grid_coord); | |||||
| if (grid_coord.grid_index == coord->grid_index) { | for (int i = 0; i < adjacent_edge->num_adjacent_faces; ++i) { | ||||
| /* Prev and next along the edge for the current grid. */ | SubdivCCGCoord grid_coord = coord_from_ccg_element( | ||||
| r_neighbors->coords[0] = boundary_coords[prev_point_index]; | subdiv_ccg, adjacent_edge->boundary_elements[i][point_index]); | ||||
| r_neighbors->coords[1] = boundary_coords[next_point_index]; | r_neighbors->coords[i + 2] = coord_step_inside_from_boundary(subdiv_ccg, &grid_coord); | ||||
| } | |||||
| else if (include_duplicates) { | |||||
| /* Same coordinate on neighboring grids if requested. */ | |||||
| r_neighbors->coords[duplicate_i + 2] = grid_coord; | |||||
| duplicate_i++; | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| /* The corner is at the middle of edge between faces. */ | /* The corner is at the middle of edge between faces. */ | ||||
| static void neighbor_coords_corner_edge_get(const SubdivCCG *subdiv_ccg, | static void neighbor_coords_corner_edge_get(const SubdivCCG *subdiv_ccg, | ||||
| const SubdivCCGCoord *coord, | const SubdivCCGCoord *coord, | ||||
| const bool include_duplicates, | |||||
| SubdivCCGNeighbors *r_neighbors) | SubdivCCGNeighbors *r_neighbors) | ||||
| { | { | ||||
| neighbor_coords_edge_get(subdiv_ccg, coord, include_duplicates, r_neighbors); | neighbor_coords_edge_get(subdiv_ccg, coord, r_neighbors); | ||||
| } | } | ||||
| /* Input coordinate is at one of 4 corners of its grid corners. */ | /* Input coordinate is at one of 4 corners of its grid corners. */ | ||||
| static void neighbor_coords_corner_get(const SubdivCCG *subdiv_ccg, | static void neighbor_coords_corner_get(const SubdivCCG *subdiv_ccg, | ||||
| const SubdivCCGCoord *coord, | const SubdivCCGCoord *coord, | ||||
| const bool include_duplicates, | |||||
| SubdivCCGNeighbors *r_neighbors) | SubdivCCGNeighbors *r_neighbors) | ||||
| { | { | ||||
| if (coord->x == 0 && coord->y == 0) { | if (coord->x == 0 && coord->y == 0) { | ||||
| neighbor_coords_corner_center_get(subdiv_ccg, coord, include_duplicates, r_neighbors); | neighbor_coords_corner_center_get(subdiv_ccg, coord, r_neighbors); | ||||
| } | } | ||||
| else { | else { | ||||
| const int grid_size_1 = subdiv_ccg->grid_size - 1; | const int grid_size_1 = subdiv_ccg->grid_size - 1; | ||||
| if (coord->x == grid_size_1 && coord->y == grid_size_1) { | if (coord->x == grid_size_1 && coord->y == grid_size_1) { | ||||
| neighbor_coords_corner_vertex_get(subdiv_ccg, coord, include_duplicates, r_neighbors); | neighbor_coords_corner_vertex_get(subdiv_ccg, coord, r_neighbors); | ||||
| } | } | ||||
| else { | else { | ||||
| neighbor_coords_corner_edge_get(subdiv_ccg, coord, include_duplicates, r_neighbors); | neighbor_coords_corner_edge_get(subdiv_ccg, coord, r_neighbors); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| Context not available. | |||||
| * other faces. */ | * other faces. */ | ||||
| static void neighbor_coords_boundary_inner_get(const SubdivCCG *subdiv_ccg, | static void neighbor_coords_boundary_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, (include_duplicates) ? 1 : 0); | subdiv_ccg_neighbors_init(r_neighbors, 4); | ||||
| if (coord->x == 0) { | if (coord->x == 0) { | ||||
| r_neighbors->coords[0] = coord_at_prev_row(subdiv_ccg, coord); | r_neighbors->coords[0] = coord_at_prev_row(subdiv_ccg, coord); | ||||
| Context not available. | |||||
| r_neighbors->coords[3].grid_index = prev_grid_index_from_coord(subdiv_ccg, coord); | r_neighbors->coords[3].grid_index = prev_grid_index_from_coord(subdiv_ccg, coord); | ||||
| r_neighbors->coords[3].x = coord->y; | r_neighbors->coords[3].x = coord->y; | ||||
| r_neighbors->coords[3].y = 1; | r_neighbors->coords[3].y = 1; | ||||
| if (include_duplicates) { | |||||
| r_neighbors->coords[4] = r_neighbors->coords[3]; | |||||
| r_neighbors->coords[4].y = 0; | |||||
| } | |||||
| } | } | ||||
| else if (coord->y == 0) { | else if (coord->y == 0) { | ||||
| r_neighbors->coords[0] = coord_at_prev_col(subdiv_ccg, coord); | r_neighbors->coords[0] = coord_at_prev_col(subdiv_ccg, coord); | ||||
| Context not available. | |||||
| r_neighbors->coords[3].grid_index = next_grid_index_from_coord(subdiv_ccg, coord); | r_neighbors->coords[3].grid_index = next_grid_index_from_coord(subdiv_ccg, coord); | ||||
| r_neighbors->coords[3].x = 1; | r_neighbors->coords[3].x = 1; | ||||
| r_neighbors->coords[3].y = coord->x; | r_neighbors->coords[3].y = coord->x; | ||||
| if (include_duplicates) { | |||||
| r_neighbors->coords[4] = r_neighbors->coords[3]; | |||||
| r_neighbors->coords[4].x = 0; | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| /* Input coordinate is on an edge between two faces. Need to check adjacency. */ | /* Input coordinate is on an edge between two faces. Need to check adjacency. */ | ||||
| static void neighbor_coords_boundary_outer_get(const SubdivCCG *subdiv_ccg, | static void neighbor_coords_boundary_outer_get(const SubdivCCG *subdiv_ccg, | ||||
| const SubdivCCGCoord *coord, | const SubdivCCGCoord *coord, | ||||
| const bool include_duplicates, | |||||
| SubdivCCGNeighbors *r_neighbors) | SubdivCCGNeighbors *r_neighbors) | ||||
| { | { | ||||
| neighbor_coords_edge_get(subdiv_ccg, coord, include_duplicates, r_neighbors); | neighbor_coords_edge_get(subdiv_ccg, coord, r_neighbors); | ||||
| } | } | ||||
| /* Input coordinate is at one of 4 boundaries of its grid. | /* Input coordinate is at one of 4 boundaries of its grid. | ||||
| Context not available. | |||||
| * a part of coarse face edge. */ | * a part of coarse face edge. */ | ||||
| static void neighbor_coords_boundary_get(const SubdivCCG *subdiv_ccg, | static void neighbor_coords_boundary_get(const SubdivCCG *subdiv_ccg, | ||||
| const SubdivCCGCoord *coord, | const SubdivCCGCoord *coord, | ||||
| const bool include_duplicates, | |||||
| SubdivCCGNeighbors *r_neighbors) | SubdivCCGNeighbors *r_neighbors) | ||||
| { | { | ||||
| if (is_inner_edge_grid_coordinate(subdiv_ccg, coord)) { | if (is_inner_edge_grid_coordinate(subdiv_ccg, coord)) { | ||||
| neighbor_coords_boundary_inner_get(subdiv_ccg, coord, include_duplicates, r_neighbors); | neighbor_coords_boundary_inner_get(subdiv_ccg, coord, r_neighbors); | ||||
| } | } | ||||
| else { | else { | ||||
| neighbor_coords_boundary_outer_get(subdiv_ccg, coord, include_duplicates, r_neighbors); | neighbor_coords_boundary_outer_get(subdiv_ccg, coord, r_neighbors); | ||||
| } | } | ||||
| } | } | ||||
| Context not available. | |||||
| const SubdivCCGCoord *coord, | const SubdivCCGCoord *coord, | ||||
| SubdivCCGNeighbors *r_neighbors) | SubdivCCGNeighbors *r_neighbors) | ||||
| { | { | ||||
| subdiv_ccg_neighbors_init(r_neighbors, 4, 0); | subdiv_ccg_neighbors_init(r_neighbors, 4); | ||||
| 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); | ||||
| Context not available. | |||||
| 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, | |||||
| SubdivCCGNeighbors *r_neighbors) | SubdivCCGNeighbors *r_neighbors) | ||||
| { | { | ||||
| BLI_assert(coord->grid_index >= 0); | BLI_assert(coord->grid_index >= 0); | ||||
| Context not available. | |||||
| 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, 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, r_neighbors); | ||||
| } | } | ||||
| else { | else { | ||||
| neighbor_coords_inner_get(subdiv_ccg, coord, r_neighbors); | neighbor_coords_inner_get(subdiv_ccg, coord, r_neighbors); | ||||
| Context not available. | |||||