Cleanup: avoid converting from CCGElem to SubdivCCGCoord

The other direction is faster.
This commit is contained in:
Brecht Van Lommel
2019-10-08 16:08:16 +02:00
parent 333293cad7
commit 899b7ff1de
2 changed files with 66 additions and 79 deletions

View File

@@ -92,6 +92,14 @@ typedef struct SubdivToCCGSettings {
bool need_mask;
} SubdivToCCGSettings;
typedef struct SubdivCCGCoord {
/* Index of the grid within SubdivCCG::grids array. */
int grid_index;
/* Coordinate within the grid. */
short x, y;
} SubdivCCGCoord;
/* This is actually a coarse face, which consists of multiple CCG grids. */
typedef struct SubdivCCGFace {
/* Total number of grids in this face.
@@ -107,15 +115,15 @@ typedef struct SubdivCCGFace {
typedef struct SubdivCCGAdjacentEdge {
int num_adjacent_faces;
/* Indexed by adjacent face index, then by point index on the edge.
* points to a grid element. */
struct CCGElem ***boundary_elements;
* points to a coordinate into the grids. */
struct SubdivCCGCoord **boundary_coords;
} SubdivCCGAdjacentEdge;
/* Definition of a vertex which is adjacent to at least one of the faces. */
typedef struct SubdivCCGAdjacentVertex {
int num_adjacent_faces;
/* Indexed by adjacent face index, points to a grid element. */
struct CCGElem **corner_elements;
/* Indexed by adjacent face index, points to a coordinate in the grids. */
struct SubdivCCGCoord *corner_coords;
} SubdivCCGAdjacentVertex;
/* Representation of subdivision surface which uses CCG grids. */
@@ -254,14 +262,6 @@ void BKE_subdiv_ccg_topology_counters(const SubdivCCG *subdiv_ccg,
int *r_num_faces,
int *r_num_loops);
typedef struct SubdivCCGCoord {
/* Index of the grid within SubdivCCG::grids array. */
int grid_index;
/* Coordinate within the grid. */
int x, y;
} SubdivCCGCoord;
typedef struct SubdivCCGNeighbors {
SubdivCCGCoord *coords;
int size;

View File

@@ -386,20 +386,33 @@ static void subdiv_ccg_allocate_adjacent_edges(SubdivCCG *subdiv_ccg, const int
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. */
static CCGElem **subdiv_ccg_adjacent_edge_add_face(SubdivCCG *subdiv_ccg,
SubdivCCGAdjacentEdge *adjacent_edge)
static SubdivCCGCoord *subdiv_ccg_adjacent_edge_add_face(SubdivCCG *subdiv_ccg,
SubdivCCGAdjacentEdge *adjacent_edge)
{
const int grid_size = subdiv_ccg->grid_size * 2;
const int adjacent_face_index = adjacent_edge->num_adjacent_faces;
++adjacent_edge->num_adjacent_faces;
/* Allocate memory for the boundary elements. */
adjacent_edge->boundary_elements = MEM_reallocN(adjacent_edge->boundary_elements,
adjacent_edge->num_adjacent_faces *
sizeof(*adjacent_edge->boundary_elements));
adjacent_edge->boundary_elements[adjacent_face_index] = MEM_malloc_arrayN(
grid_size * 2, sizeof(CCGElem *), "ccg adjacent boundary");
return adjacent_edge->boundary_elements[adjacent_face_index];
adjacent_edge->boundary_coords = MEM_reallocN(adjacent_edge->boundary_coords,
adjacent_edge->num_adjacent_faces *
sizeof(*adjacent_edge->boundary_coords));
adjacent_edge->boundary_coords[adjacent_face_index] = MEM_malloc_arrayN(
grid_size * 2, sizeof(SubdivCCGCoord), "ccg adjacent boundary");
return adjacent_edge->boundary_coords[adjacent_face_index];
}
static void subdiv_ccg_init_faces_edge_neighborhood(SubdivCCG *subdiv_ccg)
@@ -419,9 +432,6 @@ static void subdiv_ccg_init_faces_edge_neighborhood(SubdivCCG *subdiv_ccg)
StaticOrHeapIntStorage face_edges_storage;
static_or_heap_storage_init(&face_vertices_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. */
const int num_faces = subdiv_ccg->num_faces;
for (int face_index = 0; face_index < num_faces; face_index++) {
@@ -443,33 +453,32 @@ static void subdiv_ccg_init_faces_edge_neighborhood(SubdivCCG *subdiv_ccg)
const bool is_edge_flipped = (edge_vertices[0] != vertex_index);
/* Grid which is adjacent to the current 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. */
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. */
SubdivCCGAdjacentEdge *adjacent_edge = &subdiv_ccg->adjacent_edges[edge_index];
CCGElem **boundary_elements = subdiv_ccg_adjacent_edge_add_face(subdiv_ccg, adjacent_edge);
SubdivCCGCoord *boundary_coords = subdiv_ccg_adjacent_edge_add_face(subdiv_ccg,
adjacent_edge);
/* Fill CCG elements along the edge. */
int boundary_element_index = 0;
if (is_edge_flipped) {
for (int i = 0; i < grid_size; i++) {
boundary_elements[boundary_element_index++] = CCG_grid_elem(
&key, next_grid, grid_size - i - 1, grid_size - 1);
boundary_coords[boundary_element_index++] = subdiv_ccg_coord(
next_grid_index, grid_size - i - 1, grid_size - 1);
}
for (int i = 0; i < grid_size; i++) {
boundary_elements[boundary_element_index++] = CCG_grid_elem(
&key, current_grid, grid_size - 1, i);
boundary_coords[boundary_element_index++] = subdiv_ccg_coord(
current_grid_index, grid_size - 1, i);
}
}
else {
for (int i = 0; i < grid_size; i++) {
boundary_elements[boundary_element_index++] = CCG_grid_elem(
&key, current_grid, grid_size - 1, grid_size - i - 1);
boundary_coords[boundary_element_index++] = subdiv_ccg_coord(
current_grid_index, grid_size - 1, grid_size - i - 1);
}
for (int i = 0; i < grid_size; i++) {
boundary_elements[boundary_element_index++] = CCG_grid_elem(
&key, next_grid, i, grid_size - 1);
boundary_coords[boundary_element_index++] = subdiv_ccg_coord(
next_grid_index, i, grid_size - 1);
}
}
}
@@ -489,15 +498,16 @@ static void subdiv_ccg_allocate_adjacent_vertices(SubdivCCG *subdiv_ccg, const i
/* Returns storage where corner elements are to be stored. This is a pointer
* to the actual storage. */
static CCGElem **subdiv_ccg_adjacent_vertex_add_face(SubdivCCGAdjacentVertex *adjacent_vertex)
static SubdivCCGCoord *subdiv_ccg_adjacent_vertex_add_face(
SubdivCCGAdjacentVertex *adjacent_vertex)
{
const int adjacent_face_index = adjacent_vertex->num_adjacent_faces;
++adjacent_vertex->num_adjacent_faces;
/* Allocate memory for the boundary elements. */
adjacent_vertex->corner_elements = MEM_reallocN(adjacent_vertex->corner_elements,
adjacent_vertex->num_adjacent_faces *
sizeof(*adjacent_vertex->corner_elements));
return &adjacent_vertex->corner_elements[adjacent_face_index];
adjacent_vertex->corner_coords = MEM_reallocN(adjacent_vertex->corner_coords,
adjacent_vertex->num_adjacent_faces *
sizeof(*adjacent_vertex->corner_coords));
return &adjacent_vertex->corner_coords[adjacent_face_index];
}
static void subdiv_ccg_init_faces_vertex_neighborhood(SubdivCCG *subdiv_ccg)
@@ -530,11 +540,10 @@ static void subdiv_ccg_init_faces_vertex_neighborhood(SubdivCCG *subdiv_ccg)
const int vertex_index = face_vertices[corner];
/* Grid which is adjacent to the current corner. */
const int grid_index = face->start_grid_index + corner;
CCGElem *grid = subdiv_ccg->grids[grid_index];
/* Add new face to the adjacent edge. */
SubdivCCGAdjacentVertex *adjacent_vertex = &subdiv_ccg->adjacent_vertices[vertex_index];
CCGElem **corner_element = subdiv_ccg_adjacent_vertex_add_face(adjacent_vertex);
*corner_element = CCG_grid_elem(&key, grid, grid_size - 1, grid_size - 1);
SubdivCCGCoord *corner_coord = subdiv_ccg_adjacent_vertex_add_face(adjacent_vertex);
*corner_coord = subdiv_ccg_coord(grid_index, grid_size - 1, grid_size - 1);
}
}
/* Free possibly heap-allocated storage. */
@@ -627,15 +636,15 @@ void BKE_subdiv_ccg_destroy(SubdivCCG *subdiv_ccg)
for (int i = 0; i < subdiv_ccg->num_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++) {
MEM_SAFE_FREE(adjacent_edge->boundary_elements[face_index]);
MEM_SAFE_FREE(adjacent_edge->boundary_coords[face_index]);
}
MEM_SAFE_FREE(adjacent_edge->boundary_elements);
MEM_SAFE_FREE(adjacent_edge->boundary_coords);
}
MEM_SAFE_FREE(subdiv_ccg->adjacent_edges);
/* Free map of adjacent vertices. */
for (int i = 0; i < subdiv_ccg->num_adjacent_vertices; i++) {
SubdivCCGAdjacentVertex *adjacent_vertex = &subdiv_ccg->adjacent_vertices[i];
MEM_SAFE_FREE(adjacent_vertex->corner_elements);
MEM_SAFE_FREE(adjacent_vertex->corner_coords);
}
MEM_SAFE_FREE(subdiv_ccg->adjacent_vertices);
MEM_freeN(subdiv_ccg);
@@ -1038,7 +1047,8 @@ static void subdiv_ccg_average_grids_boundary(SubdivCCG *subdiv_ccg,
}
for (int face_index = 0; face_index < num_adjacent_faces; face_index++) {
for (int i = 1; i < grid_size2 - 1; i++) {
CCGElem *grid_element = adjacent_edge->boundary_elements[face_index][i];
CCGElem *grid_element = subdiv_ccg_coord_to_elem(
key, subdiv_ccg, &adjacent_edge->boundary_coords[face_index][i]);
element_accumulator_add(&tls->accumulators[i], subdiv_ccg, key, grid_element);
}
}
@@ -1048,7 +1058,8 @@ static void subdiv_ccg_average_grids_boundary(SubdivCCG *subdiv_ccg,
/* Copy averaged value to all the other faces. */
for (int face_index = 0; face_index < num_adjacent_faces; face_index++) {
for (int i = 1; i < grid_size2 - 1; i++) {
CCGElem *grid_element = adjacent_edge->boundary_elements[face_index][i];
CCGElem *grid_element = subdiv_ccg_coord_to_elem(
key, subdiv_ccg, &adjacent_edge->boundary_coords[face_index][i]);
element_accumulator_copy(subdiv_ccg, key, grid_element, &tls->accumulators[i]);
}
}
@@ -1090,13 +1101,15 @@ static void subdiv_ccg_average_grids_corners(SubdivCCG *subdiv_ccg,
GridElementAccumulator accumulator;
element_accumulator_init(&accumulator);
for (int face_index = 0; face_index < num_adjacent_faces; face_index++) {
CCGElem *grid_element = adjacent_vertex->corner_elements[face_index];
CCGElem *grid_element = subdiv_ccg_coord_to_elem(
key, subdiv_ccg, &adjacent_vertex->corner_coords[face_index]);
element_accumulator_add(&accumulator, subdiv_ccg, key, grid_element);
}
element_accumulator_mul_fl(&accumulator, 1.0f / (float)num_adjacent_faces);
/* Copy averaged value to all the other faces. */
for (int face_index = 0; face_index < num_adjacent_faces; face_index++) {
CCGElem *grid_element = adjacent_vertex->corner_elements[face_index];
CCGElem *grid_element = subdiv_ccg_coord_to_elem(
key, subdiv_ccg, &adjacent_vertex->corner_coords[face_index]);
element_accumulator_copy(subdiv_ccg, key, grid_element, &accumulator);
}
}
@@ -1333,26 +1346,6 @@ BLI_INLINE SubdivCCGCoord coord_at_next_col(const SubdivCCG *subdiv_ccg,
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. */
static SubdivCCGCoord coord_step_inside_from_boundary(const SubdivCCG *subdiv_ccg,
const SubdivCCGCoord *coord)
@@ -1486,10 +1479,7 @@ static void neighbor_coords_corner_vertex_get(const SubdivCCG *subdiv_ccg,
}
SubdivCCGAdjacentEdge *adjacent_edge = &subdiv_ccg->adjacent_edges[edge_index];
CCGElem *boundary_element =
adjacent_edge->boundary_elements[edge_face_index][edge_point_index];
r_neighbors->coords[i] = coord_from_ccg_element(subdiv_ccg, boundary_element);
r_neighbors->coords[i] = adjacent_edge->boundary_coords[edge_face_index][edge_point_index];
}
static_or_heap_storage_free(&vertex_edges_storage);
@@ -1604,14 +1594,11 @@ static void neighbor_coords_edge_get(const SubdivCCG *subdiv_ccg,
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);
r_neighbors->coords[0] = coord_from_ccg_element(
subdiv_ccg, adjacent_edge->boundary_elements[0][prev_point_index]);
r_neighbors->coords[1] = coord_from_ccg_element(
subdiv_ccg, adjacent_edge->boundary_elements[0][next_point_index]);
r_neighbors->coords[0] = adjacent_edge->boundary_coords[0][prev_point_index];
r_neighbors->coords[1] = adjacent_edge->boundary_coords[0][next_point_index];
for (int i = 0; i < adjacent_edge->num_adjacent_faces; ++i) {
SubdivCCGCoord grid_coord = coord_from_ccg_element(
subdiv_ccg, adjacent_edge->boundary_elements[i][point_index]);
SubdivCCGCoord grid_coord = adjacent_edge->boundary_coords[i][point_index];
r_neighbors->coords[i + 2] = coord_step_inside_from_boundary(subdiv_ccg, &grid_coord);
}
}