Cleanup: spelling, comments

This commit is contained in:
Campbell Barton 2020-05-01 12:36:11 +10:00
parent 0cb53d4740
commit 5ee1c7f695
2 changed files with 163 additions and 108 deletions

View File

@ -19,6 +19,9 @@
/** \file
* \ingroup bke
*
* This implements the un-subdivide algorithm, which generates a lower resolution base mesh and
* its corresponding grids to match a given original mesh.
*/
#include "MEM_guardedalloc.h"
@ -47,33 +50,36 @@
#include "multires_reshape.h"
#include "multires_unsubdivide.h"
/* This implements the unsubdivide algorithm, which generates a lower resolution base mesh and its
* corresponding grids to match a given original mesh. */
/* This is done in the following steps:
* - If there are already grids in the original mesh, convert them from tangent displacement to
object space coordinates.
* - Assign datalayers to the original mesh to map vertices to a new base mesh. These datalayes
store the indicies of the elements in the original mesh. This way the original inidices are
preserved when doing mesh modifications (removing and disolving vertices) when building the new
base mesh.
*
* - If there are already grids in the original mesh,
* convert them from tangent displacement to object space coordinates.
* - Assign data-layers to the original mesh to map vertices to a new base mesh.
* These data-layers store the indices of the elements in the original mesh.
* This way the original indices are
* preserved when doing mesh modifications (removing and dissolving vertices)
* when building the new base mesh.
* - Try to find a lower resolution base mesh. This is done by flood fill operation that tags the
center vertices of the lower level grid. If the algorithm can tag all vertices correctly, the lower
level base mesh is generated by dissolving the tagged vertices.
* - Use the datalayers to map vertices from the base mesh to the original mesh and original to
base mesh.
* center vertices of the lower level grid.
* If the algorithm can tag all vertices correctly,
* the lower level base mesh is generated by dissolving the tagged vertices.
* - Use the data-layers to map vertices from the base mesh to the original mesh and original to
* base mesh.
* - Find two adjacent vertices on the base mesh to a given vertex to map that loop from base mesh
to original mesh
* to original mesh
* - Extract the grid from the original mesh from that loop. If there are no grids in the original
mesh, build the new grid directly from the vertex coordinates by iterating in a grid pattern over
them. If there are grids in the original mesh, iterate in a grid pattern over the polys, reorder
all the coordinates of the grid in that poly and copy those coordinates to the new base mesh grid.
* - Copy the new grid data over to a new allocated MDISP layer with the appropiate size to store
the new levels.
* mesh, build the new grid directly from the vertex coordinates by iterating in a grid pattern
* over them. If there are grids in the original mesh, iterate in a grid pattern over the polys,
* reorder all the coordinates of the grid in that poly and copy those coordinates to the new
* base mesh grid.
* - Copy the new grid data over to a new allocated MDISP layer with the appropriate size to store
* the new levels.
* - Convert the grid data from object space to tangent displacement.
*/
/* Used to check if a vertex is in a disconnected element ID. */
/**
* Used to check if a vertex is in a disconnected element ID.
*/
static bool is_vertex_in_id(BMVert *v, int *elem_id, int elem)
{
const int v_index = BM_elem_index_get(v);
@ -90,9 +96,12 @@ static bool is_vertex_pole(BMVert *v)
return !BM_vert_is_boundary(v) && (BM_vert_edge_count(v) == 3 || BM_vert_edge_count(v) >= 5);
}
/* Returns the first pole that is found in an element ID. */
/* Tries to give priority to 3 vert poles as they generally generate better results in cases were
* the unsubdivide solution is ambiguous. */
/**
* Returns the first pole that is found in an element ID.
*
* Tries to give priority to 3 vert poles as they generally generate better results in cases were
* the un-subdivide solution is ambiguous.
*/
static BMVert *unsubdivide_find_any_pole(BMesh *bm, int *elem_id, int elem)
{
BMIter iter;
@ -109,9 +118,12 @@ static BMVert *unsubdivide_find_any_pole(BMesh *bm, int *elem_id, int elem)
return pole;
}
/* Checks if the mesh is all quads. */
/* TODO(pablodp606). This can perform additional checks if they are faster than trying to search
* for an unsubidivide solution. This way it is possible to cancel the operation faster. */
/**
* Checks if the mesh is all quads.
*
* TODO(pablodp606): This can perform additional checks if they are faster than trying to search
* for an un-subdivide solution. This way it is possible to cancel the operation faster.
*/
static bool unsubdivide_is_all_quads(BMesh *bm)
{
BMIter iter;
@ -146,17 +158,23 @@ static bool unsubdivide_is_all_quads(BMesh *bm)
return true;
}
/* Returns true if from_v and to_v, which should be part of the same quad face, are diagonals. */
/**
* Returns true if from_v and to_v, which should be part of the same quad face, are diagonals.
*/
static bool is_vertex_diagonal(BMVert *from_v, BMVert *to_v)
{
return !BM_edge_exists(from_v, to_v);
}
/* Generates a possible solution for unsubdivision by tagging the (0,0) vertices of the possible
* grids. */
/* This works using a flood fill operation using the quads diagonals to jump to the next vertex. */
/* If initial_vertex is part of the base mesh solution, the flood fill should tag only the (0.0)
* vertices of the grids that need to be dissolved, and nothing else. */
/**
* Generates a possible solution for un-subdivision by tagging the (0,0)
* vertices of the possible grids.
*
* This works using a flood fill operation using the quads diagonals to jump to the next vertex.
*
* If initial_vertex is part of the base mesh solution, the flood fill should tag only the (0.0)
* vertices of the grids that need to be dissolved, and nothing else.
*/
static void unsubdivide_face_center_vertex_tag(BMesh *bm, BMVert *initial_vertex)
{
bool *visited_vertices = MEM_calloc_arrayN(sizeof(bool), bm->totvert, "visited vertices");
@ -225,10 +243,13 @@ static void unsubdivide_face_center_vertex_tag(BMesh *bm, BMVert *initial_vertex
MEM_freeN(visited_vertices);
}
/* This function checks if the current status of the BMVert tags corresponds to a valid unsubdivide
* solution. */
/* This means that all vertices corresponding to the (0,0) grid coordinate should be tagged. */
/* On a valid solution, the following things should happen:
/**
* This function checks if the current status of the #BMVert tags
* corresponds to a valid un-subdivide solution.
*
* This means that all vertices corresponding to the (0,0) grid coordinate should be tagged.
*
* On a valid solution, the following things should happen:
* - No boundary vertices should be tagged
* - No vertices connected by an edge or a quad diagonal to a tagged vertex should be tagged
* - All boundary vertices should have one vertex connected by an edge or a diagonal tagged
@ -256,7 +277,7 @@ static bool unsubdivide_is_center_vertex_tag_valid(BMesh *bm, int *elem_id, int
}
}
if (BM_vert_is_boundary(v)) {
/* Untagged vertex in boundary without connected tagged vertices. */
/* Un-tagged vertex in boundary without connected tagged vertices. */
bool any_tagged = false;
BM_ITER_ELEM (f, &iter_a, v, BM_FACES_OF_VERT) {
BM_ITER_ELEM (neighbor_v, &iter_b, f, BM_VERTS_OF_FACE) {
@ -275,12 +296,14 @@ static bool unsubdivide_is_center_vertex_tag_valid(BMesh *bm, int *elem_id, int
return true;
}
/* Searchs and validates an unsubdivide solution for a given element ID. */
/**
* Search and validates an un-subdivide solution for a given element ID.
*/
static bool unsubdivide_tag_disconnected_mesh_element(BMesh *bm, int *elem_id, int elem)
{
/* First, get vertex candidates to try to generate possible unsubdivide solution. */
/* First, get vertex candidates to try to generate possible un-subdivide solution. */
/* Find a vertex pole. If there is a solution on an all quad base mesh, this vertex should be
* part of the base mesh. If it isnt, then there is no solution. */
* part of the base mesh. If it isn't, then there is no solution. */
GSQueue *initial_vertex = BLI_gsqueue_new(sizeof(BMVert *));
BMVert *initial_vertex_pole = unsubdivide_find_any_pole(bm, elem_id, elem);
if (initial_vertex_pole != NULL) {
@ -340,7 +363,9 @@ static bool unsubdivide_tag_disconnected_mesh_element(BMesh *bm, int *elem_id, i
return valid_tag_found;
}
/* Uses a flood fill operation to generate a different ID for each disconnected mesh element. */
/**
* Uses a flood fill operation to generate a different ID for each disconnected mesh element.
*/
static int unsubdivide_init_elem_ids(BMesh *bm, int *elem_id)
{
bool *visited_vertices = MEM_calloc_arrayN(sizeof(bool), bm->totvert, "visited vertices");
@ -378,8 +403,10 @@ static int unsubdivide_init_elem_ids(BMesh *bm, int *elem_id)
return current_id;
}
/* Builds a base mesh one subdiv level down from the current original mesh if the original mesh has
* a valid solution stored in the BMVert tags. */
/**
* Builds a base mesh one subdivision level down from the current original mesh if the original
* mesh has a valid solution stored in the #BMVert tags.
*/
static void unsubdivide_build_base_mesh_from_tags(BMesh *bm)
{
BMVert *v;
@ -425,37 +452,42 @@ static void unsubdivide_build_base_mesh_from_tags(BMesh *bm)
true);
}
/* Main function to get a base mesh one level down from the current original mesh if it exists. */
/* This searchs for different unsubdivide solutions and stores them as a combination of BMVert
* flags for each disconnected mesh element. */
/* If the solution for all elements are valid, it builds a new base mesh based on those tags by
* dissolving and merging vertices. */
/**
* Main function to get a base mesh one level down from the current original mesh if it exists.
*
* This searches for different un-subdivide solutions and stores them as a combination of #BMVert
* flags for each disconnected mesh element.
*
* If the solution for all elements are valid, it builds a new base mesh based on those tags by
* dissolving and merging vertices.
*/
static bool multires_unsubdivide_single_level(BMesh *bm)
{
/* Do a first check to make sure that it makes sense to search for unsubdivision in this mesh. */
/* Do a first check to make sure that it makes sense to search for un-subdivision in this mesh.
*/
if (!unsubdivide_is_all_quads(bm)) {
return false;
};
/* Init the vertex table. */
/* Initialize the vertex table. */
BM_mesh_elem_table_init(bm, BM_VERT);
BM_mesh_elem_table_ensure(bm, BM_VERT);
/* Build disconnected elements IDs. Each dissconnected mesh element is evaluated separatedly. */
/* Build disconnected elements IDs. Each disconnected mesh element is evaluated separately. */
int *elem_id = MEM_calloc_arrayN(sizeof(int), bm->totvert, " ELEM ID");
const int tot_ids = unsubdivide_init_elem_ids(bm, elem_id);
bool valid_tag_found = true;
/* Reset the BMesh flags as they are used to store data during the unsudivide process. */
/* Reset the #BMesh flags as they are used to store data during the un-subdivide process. */
BM_mesh_elem_hflag_disable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_TAG, false);
BM_mesh_elem_hflag_disable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, false);
/* For each disconnected mesh element ID, search if an unsubdividie solution is possible. The
* whole unsubdivide process fails if a single disconnected mesh element fails. */
/* For each disconnected mesh element ID, search if an un-subdivide solution is possible. The
* whole un-subdivide process fails if a single disconnected mesh element fails. */
for (int id = 0; id < tot_ids; id++) {
/* Try to the BMesh vertex flag tags corresponding to an unsubdivide solution. */
/* Try to the #BMesh vertex flag tags corresponding to an un-subdivide solution. */
if (!unsubdivide_tag_disconnected_mesh_element(bm, elem_id, id)) {
valid_tag_found = false;
break;
@ -472,7 +504,9 @@ static bool multires_unsubdivide_single_level(BMesh *bm)
return valid_tag_found;
}
/* Returns the next edge and vertex in the direction of a given edge. */
/**
* Returns the next edge and vertex in the direction of a given edge.
*/
static BMEdge *edge_step(BMVert *v, BMEdge *edge, BMVert **r_next_vertex)
{
BMIter iter;
@ -503,8 +537,10 @@ static BMFace *face_step(BMEdge *edge, BMFace *f)
return f;
}
/* Returns the other edge which belongs to the face f which is different from edge_x and shares
* initial_vertex. */
/**
* Returns the other edge which belongs to the face f which is different from edge_x and shares
* initial_vertex.
*/
static BMEdge *get_initial_edge_y(BMFace *f, BMEdge *edge_x, BMVert *initial_vertex)
{
BMIter iter;
@ -522,7 +558,8 @@ static BMEdge *get_initial_edge_y(BMFace *f, BMEdge *edge_x, BMVert *initial_ver
return NULL;
}
/* Writes the current mdisp data into the corresponding area of quad poly giving its corner's loop.
/**
* Writes the current mdisp data into the corresponding area of quad poly giving its corner's loop.
*/
static void write_loop_in_face_grid(
float (*face_grid)[3], MDisps *mdisp, int face_grid_size, int orig_grid_size, int loop)
@ -581,8 +618,10 @@ static void write_loop_in_face_grid(
}
}
/* Writes a buffer containing the 4 grids in the correct orientation of the 4 loops of a face into
* the main MultiresUnsubdivideGrid that is being extracted. */
/**
* Writes a buffer containing the 4 grids in the correct orientation of the 4 loops of a face into
* the main #MultiresUnsubdivideGrid that is being extracted.
*/
static void write_face_grid_in_unsubdivide_grid(MultiresUnsubdivideGrid *grid,
float (*face_grid)[3],
int face_grid_size,
@ -603,9 +642,12 @@ static void write_face_grid_in_unsubdivide_grid(MultiresUnsubdivideGrid *grid,
}
}
/* Stores the data from the mdisps grids of the loops of the face f into the new grid for the new
* base mesh. */
/* Used when there are already grids in the original mesh. */
/**
* Stores the data from the mdisps grids of the loops of the face f
* into the new grid for the new base mesh.
*
* Used when there are already grids in the original mesh.
*/
static void store_grid_data(MultiresUnsubdivideContext *context,
MultiresUnsubdivideGrid *grid,
BMVert *v,
@ -620,7 +662,7 @@ static void store_grid_data(MultiresUnsubdivideContext *context,
const int corner_vertex_index = BM_elem_index_get(v);
/* Calculates an offset to write the grids correctly oriented in the main
* MultiresUnsubdivideGrid. */
* #MultiresUnsubdivideGrid. */
int loop_offset = 0;
for (int i = 0; i < poly->totloop; i++) {
const int loop_index = poly->loopstart + i;
@ -650,15 +692,17 @@ static void store_grid_data(MultiresUnsubdivideContext *context,
write_loop_in_face_grid(face_grid, mdisp, face_grid_size, grid_size, quad_loop);
}
/* Write the face_grid buffer in the correct position in the MultiresUnsubdivideGrids that is
/* Write the face_grid buffer in the correct position in the #MultiresUnsubdivideGrids that is
* being extracted. */
write_face_grid_in_unsubdivide_grid(grid, face_grid, face_grid_size, grid_x, grid_y);
MEM_freeN(face_grid);
}
/* Stores the data into the new grid from a bmesh vertex. Used when there are no grids in the
* original mesh. */
/**
* Stores the data into the new grid from a #BMVert.
* Used when there are no grids in the original mesh.
*/
static void store_vertex_data(MultiresUnsubdivideGrid *grid, BMVert *v, int grid_x, int grid_y)
{
const int remap_index_y = grid->grid_size - 1 - grid_x;
@ -669,7 +713,8 @@ static void store_vertex_data(MultiresUnsubdivideGrid *grid, BMVert *v, int grid
copy_v3_v3(grid->grid_co[grid_index], v->co);
}
/* Main function to extract data from the original bmesh and MDISPS as grids for the new base mesh.
/**
* Main function to extract data from the original bmesh and MDISPS as grids for the new base mesh.
*/
static void multires_unsubdivide_extract_single_grid_from_face_edge(
MultiresUnsubdivideContext *context,
@ -743,7 +788,7 @@ static void multires_unsubdivide_extract_single_grid_from_face_edge(
edge_x = edge_step(current_vertex_x, edge_x, &current_vertex_x);
}
else {
/* If there were grids in the original mesh, extrat the data from the grids and iterate
/* If there were grids in the original mesh, extract the data from the grids and iterate
* over the faces. */
store_grid_data(context, grid, current_vertex_x, grid_face, grid_x, grid_y);
edge_x = edge_step(current_vertex_x, edge_x, &current_vertex_x);
@ -780,9 +825,12 @@ static void multires_unsubdivide_extract_single_grid_from_face_edge(
}
}
/* Returns the l+1 and l-1 vertices of the base mesh poly were the grid from the face f1 and edge
* e1 is going to be extracted. */
/* These vertes should always have an corresponding existing vertex on the base mesh. */
/**
* Returns the l+1 and l-1 vertices of the base mesh poly were the grid from the face f1 and edge
* e1 is going to be extracted.
*
* These vertices should always have an corresponding existing vertex on the base mesh.
*/
static void multires_unsubdivide_get_grid_corners_on_base_mesh(BMFace *f1,
BMEdge *e1,
BMVert **r_corner_x,
@ -842,7 +890,7 @@ static BMesh *get_bmesh_from_mesh(Mesh *mesh)
return bm;
}
/* Datalayer names to store the original indices of the elements before modifying the mesh. */
/* Data-layer names to store the original indices of the elements before modifying the mesh. */
static const char lname[] = "l_remap_index";
static const char vname[] = "v_remap_index";
@ -859,8 +907,10 @@ static void multires_unsubdivide_free_original_datalayers(Mesh *mesh)
}
}
/* Generates two datalayers to map loops and vertices from base mesh to original mesh after
* dissolving the vertices. */
/**
* Generates two data-layers to map loops and vertices from base mesh to original mesh after
* dissolving the vertices.
*/
static void multires_unsubdivide_add_original_index_datalayers(Mesh *mesh)
{
multires_unsubdivide_free_original_datalayers(mesh);
@ -871,7 +921,7 @@ static void multires_unsubdivide_add_original_index_datalayers(Mesh *mesh)
int *v_index = CustomData_add_layer_named(
&mesh->vdata, CD_PROP_INT, CD_CALLOC, NULL, mesh->totvert, vname);
/* Init these datalayer with the indicies in the current mesh. */
/* Initialize these data-layer with the indices in the current mesh. */
for (int i = 0; i < mesh->totloop; i++) {
l_index[i] = i;
}
@ -889,7 +939,7 @@ static void multires_unsubdivide_prepare_original_bmesh_for_extract(
BMesh *bm_original_mesh = context->bm_original_mesh = get_bmesh_from_mesh(original_mesh);
/* Init the elem tables. */
/* Initialize the elem tables. */
BM_mesh_elem_table_ensure(bm_original_mesh, BM_EDGE);
BM_mesh_elem_table_ensure(bm_original_mesh, BM_FACE);
BM_mesh_elem_table_ensure(bm_original_mesh, BM_VERT);
@ -900,7 +950,7 @@ static void multires_unsubdivide_prepare_original_bmesh_for_extract(
BM_mesh_elem_hflag_disable_all(
bm_original_mesh, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, false);
/* Get the mapping datalayer. */
/* Get the mapping data-layer. */
context->base_to_orig_vmap = CustomData_get_layer_named(&base_mesh->vdata, CD_PROP_INT, vname);
/* Tag the base mesh vertices in the original mesh. */
@ -922,8 +972,10 @@ static void multires_unsubdivide_prepare_original_bmesh_for_extract(
}
}
/* Checks the orientation of the loops to flip the x and y axis when extracting the grid if
* necessary. */
/**
* Checks the orientation of the loops to flip the x and y axis when extracting the grid if
* necessary.
*/
static bool multires_unsubdivide_flip_grid_x_axis(Mesh *mesh, int poly, int loop, int v_x)
{
MPoly *p = &mesh->mpoly[poly];
@ -955,7 +1007,7 @@ static void multires_unsubdivide_extract_grids(MultiresUnsubdivideContext *conte
context->base_mesh_grids = MEM_calloc_arrayN(
sizeof(MultiresUnsubdivideGrid), base_mesh->totloop, "grids");
/* Based on the exising indicies in the datalayers, generate two vertex indices maps. */
/* Based on the existing indices in the data-layers, generate two vertex indices maps. */
/* From vertex index in original to vertex index in base and from vertex index in base to vertex
* index in original. */
int *orig_to_base_vmap = MEM_calloc_arrayN(sizeof(int), bm_original_mesh->totvert, "orig vmap");
@ -977,8 +1029,8 @@ static void multires_unsubdivide_extract_grids(MultiresUnsubdivideContext *conte
orig_to_base_vmap[orig_vertex_index] = i;
}
/* Add the original datalayers to the base mesh to have the loop indicies stored in a datalayer,
* so they can be used from BMesh. */
/* Add the original data-layers to the base mesh to have the loop indices stored in a data-layer,
* so they can be used from #BMesh. */
multires_unsubdivide_add_original_index_datalayers(base_mesh);
const int base_l_layer_index = CustomData_get_named_layer_index(
@ -991,14 +1043,14 @@ static void multires_unsubdivide_extract_grids(MultiresUnsubdivideContext *conte
BM_mesh_elem_table_ensure(bm_base_mesh, BM_VERT);
BM_mesh_elem_table_ensure(bm_base_mesh, BM_FACE);
/* Get the datalayer that contains the loops indicies. */
/* Get the data-layer that contains the loops indices. */
const int base_l_offset = CustomData_get_n_offset(
&bm_base_mesh->ldata, CD_PROP_INT, base_l_layer_index);
/* Main loop for extracting the grids. Iterates over the base mesh vertices. */
BM_ITER_MESH (v, &iter, bm_base_mesh, BM_VERTS_OF_MESH) {
/* For each base mesh vertex, get the corresponding BMVert of the original mesh using the
/* For each base mesh vertex, get the corresponding #BMVert of the original mesh using the
* vertex map. */
const int orig_vertex_index = base_to_orig_vmap[BM_elem_index_get(v)];
BMVert *vert_original = BM_vert_at_index(bm_original_mesh, orig_vertex_index);
@ -1074,11 +1126,11 @@ bool multires_unsubdivide_to_basemesh(MultiresUnsubdivideContext *context)
{
Mesh *original_mesh = context->original_mesh;
/* Prepare the datalayers to map base to original. */
/* Prepare the data-layers to map base to original. */
multires_unsubdivide_add_original_index_datalayers(original_mesh);
BMesh *bm_base_mesh = get_bmesh_from_mesh(original_mesh);
/* Unsubdivide as many iterations as possible. */
/* Un-subdivide as many iterations as possible. */
context->num_new_levels = 0;
int num_levels_left = context->max_new_levels;
while (num_levels_left > 0 && multires_unsubdivide_single_level(bm_base_mesh)) {
@ -1086,7 +1138,7 @@ bool multires_unsubdivide_to_basemesh(MultiresUnsubdivideContext *context)
num_levels_left--;
}
/* If no unsubdivide steps were possible, free the bmesh, the map datalayers and stop. */
/* If no un-subdivide steps were possible, free the bmesh, the map data-layers and stop. */
if (context->num_new_levels == 0) {
multires_unsubdivide_free_original_datalayers(original_mesh);
BM_mesh_free(bm_base_mesh);
@ -1096,7 +1148,7 @@ bool multires_unsubdivide_to_basemesh(MultiresUnsubdivideContext *context)
/* Calculate the final levels for the new grids over base mesh. */
context->num_total_levels = context->num_new_levels + context->num_original_levels;
/* Store the new basemesh as a mesh in context, free bmesh. */
/* Store the new base-mesh as a mesh in context, free bmesh. */
context->base_mesh = BKE_mesh_new_nomain(0, 0, 0, 0, 0);
BM_mesh_bm_to_me(NULL,
bm_base_mesh,
@ -1106,7 +1158,7 @@ bool multires_unsubdivide_to_basemesh(MultiresUnsubdivideContext *context)
}));
BM_mesh_free(bm_base_mesh);
/* Init bmesh and maps for the original mesh and extract the grids. */
/* Initialize bmesh and maps for the original mesh and extract the grids. */
multires_unsubdivide_prepare_original_bmesh_for_extract(context);
multires_unsubdivide_extract_grids(context);
@ -1125,8 +1177,10 @@ void multires_unsubdivide_context_free(MultiresUnsubdivideContext *context)
MEM_SAFE_FREE(context->base_mesh_grids);
}
/* This functiona allocates new mdisps with the right size to fit the new extracted grids from the
* base mesh and copies the data to them. */
/**
* This function allocates new mdisps with the right size to fit the new extracted grids from the
* base mesh and copies the data to them.
*/
static void multires_create_grids_in_unsubdivided_base_mesh(MultiresUnsubdivideContext *context,
Mesh *base_mesh)
{
@ -1191,7 +1245,7 @@ int multiresModifier_rebuild_subdiv(struct Depsgraph *depsgraph,
/* Set the limit for the levels that should be rebuild. */
unsubdiv_context.max_new_levels = rebuild_limit;
/* Unsubdivide and create the data for the new grids. */
/* Un-subdivide and create the data for the new grids. */
if (multires_unsubdivide_to_basemesh(&unsubdiv_context) == 0) {
/* If there was no possible to rebuild any level, free the data and return. */
if (mmd->totlvl != 0) {
@ -1227,15 +1281,15 @@ int multiresModifier_rebuild_subdiv(struct Depsgraph *depsgraph,
mmd->renderlvl = (char)(mmd->renderlvl + unsubdiv_context.num_new_levels);
/* Create a resape context to convert the MDISPS data to tangent displacement. It can be the same
* as the previous one as a new Subdiv needs to be created for the new base mesh. */
/* Create a reshape context to convert the MDISPS data to tangent displacement. It can be the
* same as the previous one as a new Subdivision needs to be created for the new base mesh. */
if (!multires_reshape_context_create_from_base_mesh(&reshape_context, depsgraph, object, mmd)) {
return 0;
}
multires_reshape_object_grids_to_tangent_displacement(&reshape_context);
multires_reshape_context_free(&reshape_context);
/* Free the unsubdivide context and return the total number of levels that were rebuild. */
/* Free the un-subdivide context and return the total number of levels that were rebuild. */
const int rebuild_subdvis = unsubdiv_context.num_new_levels;
multires_unsubdivide_context_free(&unsubdiv_context);

View File

@ -37,34 +37,35 @@ typedef struct MultiresUnsubdivideGrid {
int grid_index;
int grid_size;
/* Grid coordinates in object space. */
/** Grid coordinates in object space. */
float (*grid_co)[3];
} MultiresUnsubdivideGrid;
typedef struct MultiresUnsubdivideContext {
/* Input Mesh to unsubdivide. */
/* Input Mesh to un-subdivide. */
struct Mesh *original_mesh;
struct MDisps *original_mdisp;
/* Number of subdivision in the grids of the input mesh. */
/** Number of subdivision in the grids of the input mesh. */
int num_original_levels;
/* Level 0 base mesh after applying the maximum amount of unsubdivisions. */
/** Level 0 base mesh after applying the maximum amount of unsubdivisions. */
struct Mesh *base_mesh;
/* Limit on how many levels down the unsubdivide operation should create, if possible. */
/** Limit on how many levels down the unsubdivide operation should create, if possible. */
int max_new_levels;
/* New levels that were created after unsubdividing. */
/** New levels that were created after unsubdividing. */
int num_new_levels;
/* Number of subdivisions that should be applied to the base mesh. (num_new_levels +
* num_original_levels)
/**
* Number of subdivisions that should be applied to the base mesh.
* (num_new_levels + num_original_levels).
*/
int num_total_levels;
/* Data for the new grids, indexed by base mesh loop index. */
/** Data for the new grids, indexed by base mesh loop index. */
int num_grids;
struct MultiresUnsubdivideGrid *base_mesh_grids;
@ -74,7 +75,7 @@ typedef struct MultiresUnsubdivideContext {
int *base_to_orig_vmap;
} MultiresUnsubdivideContext;
/* ================================================================================================
/* --------------------------------------------------------------------
* Construct/destruct reshape context.
*/
@ -83,7 +84,7 @@ void multires_unsubdivide_context_init(MultiresUnsubdivideContext *context,
struct MultiresModifierData *mmd);
void multires_unsubdivide_context_free(MultiresUnsubdivideContext *context);
/* ================================================================================================
/* --------------------------------------------------------------------
* Rebuild Lower Subdivisions.
*/