Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/blenkernel/intern/subdiv_mesh.c')
-rw-r--r--source/blender/blenkernel/intern/subdiv_mesh.c1895
1 files changed, 897 insertions, 998 deletions
diff --git a/source/blender/blenkernel/intern/subdiv_mesh.c b/source/blender/blenkernel/intern/subdiv_mesh.c
index 8ac120ec79d..d461394bc02 100644
--- a/source/blender/blenkernel/intern/subdiv_mesh.c
+++ b/source/blender/blenkernel/intern/subdiv_mesh.c
@@ -46,87 +46,77 @@
*/
typedef struct SubdivMeshContext {
- const SubdivToMeshSettings *settings;
- const Mesh *coarse_mesh;
- Subdiv *subdiv;
- Mesh *subdiv_mesh;
- /* Cached custom data arrays for fastter access. */
- int *vert_origindex;
- int *edge_origindex;
- int *loop_origindex;
- int *poly_origindex;
- /* UV layers interpolation. */
- int num_uv_layers;
- MLoopUV *uv_layers[MAX_MTFACE];
- /* Accumulated values.
- *
- * Averaging is happening for vertices along the coarse edges and corners.
- * This is needed for both displacement and normals.
- *
- * Displacement is being accumulated to a verticies coordinates, since those
- * are not needed during traversal of edge/corner vertices.
- *
- * For normals we are using dedicated array, since we can not use same
- * vertices (normals are `short`, which will cause a lot of precision
- * issues). */
- float (*accumulated_normals)[3];
- /* Per-subdivided vertex counter of averaged values. */
- int *accumulated_counters;
- /* Denotes whether normals can be evaluated from a limit surface. One case
- * when it's not possible is when displacement is used. */
- bool can_evaluate_normals;
- bool have_displacement;
+ const SubdivToMeshSettings *settings;
+ const Mesh *coarse_mesh;
+ Subdiv *subdiv;
+ Mesh *subdiv_mesh;
+ /* Cached custom data arrays for fastter access. */
+ int *vert_origindex;
+ int *edge_origindex;
+ int *loop_origindex;
+ int *poly_origindex;
+ /* UV layers interpolation. */
+ int num_uv_layers;
+ MLoopUV *uv_layers[MAX_MTFACE];
+ /* Accumulated values.
+ *
+ * Averaging is happening for vertices along the coarse edges and corners.
+ * This is needed for both displacement and normals.
+ *
+ * Displacement is being accumulated to a verticies coordinates, since those
+ * are not needed during traversal of edge/corner vertices.
+ *
+ * For normals we are using dedicated array, since we can not use same
+ * vertices (normals are `short`, which will cause a lot of precision
+ * issues). */
+ float (*accumulated_normals)[3];
+ /* Per-subdivided vertex counter of averaged values. */
+ int *accumulated_counters;
+ /* Denotes whether normals can be evaluated from a limit surface. One case
+ * when it's not possible is when displacement is used. */
+ bool can_evaluate_normals;
+ bool have_displacement;
} SubdivMeshContext;
static void subdiv_mesh_ctx_cache_uv_layers(SubdivMeshContext *ctx)
{
- Mesh *subdiv_mesh = ctx->subdiv_mesh;
- ctx->num_uv_layers =
- CustomData_number_of_layers(&subdiv_mesh->ldata, CD_MLOOPUV);
- for (int layer_index = 0; layer_index < ctx->num_uv_layers; ++layer_index) {
- ctx->uv_layers[layer_index] = CustomData_get_layer_n(
- &subdiv_mesh->ldata, CD_MLOOPUV, layer_index);
- }
+ Mesh *subdiv_mesh = ctx->subdiv_mesh;
+ ctx->num_uv_layers = CustomData_number_of_layers(&subdiv_mesh->ldata, CD_MLOOPUV);
+ for (int layer_index = 0; layer_index < ctx->num_uv_layers; ++layer_index) {
+ ctx->uv_layers[layer_index] = CustomData_get_layer_n(
+ &subdiv_mesh->ldata, CD_MLOOPUV, layer_index);
+ }
}
static void subdiv_mesh_ctx_cache_custom_data_layers(SubdivMeshContext *ctx)
{
- Mesh *subdiv_mesh = ctx->subdiv_mesh;
- /* Pointers to original indices layers. */
- ctx->vert_origindex = CustomData_get_layer(
- &subdiv_mesh->vdata, CD_ORIGINDEX);
- ctx->edge_origindex = CustomData_get_layer(
- &subdiv_mesh->edata, CD_ORIGINDEX);
- ctx->loop_origindex = CustomData_get_layer(
- &subdiv_mesh->ldata, CD_ORIGINDEX);
- ctx->poly_origindex = CustomData_get_layer(
- &subdiv_mesh->pdata, CD_ORIGINDEX);
- /* UV layers interpolation. */
- subdiv_mesh_ctx_cache_uv_layers(ctx);
+ Mesh *subdiv_mesh = ctx->subdiv_mesh;
+ /* Pointers to original indices layers. */
+ ctx->vert_origindex = CustomData_get_layer(&subdiv_mesh->vdata, CD_ORIGINDEX);
+ ctx->edge_origindex = CustomData_get_layer(&subdiv_mesh->edata, CD_ORIGINDEX);
+ ctx->loop_origindex = CustomData_get_layer(&subdiv_mesh->ldata, CD_ORIGINDEX);
+ ctx->poly_origindex = CustomData_get_layer(&subdiv_mesh->pdata, CD_ORIGINDEX);
+ /* UV layers interpolation. */
+ subdiv_mesh_ctx_cache_uv_layers(ctx);
}
-static void subdiv_mesh_prepare_accumulator(
- SubdivMeshContext *ctx, int num_vertices)
+static void subdiv_mesh_prepare_accumulator(SubdivMeshContext *ctx, int num_vertices)
{
- if (!ctx->can_evaluate_normals && !ctx->have_displacement) {
- return;
- }
- /* TODO(sergey): Technically, this is overallocating, we don't need memory
- * for an inner subdivision vertices. */
- ctx->accumulated_normals = MEM_calloc_arrayN(
- sizeof(*ctx->accumulated_normals),
- num_vertices,
- "subdiv accumulated normals");
- ctx->accumulated_counters = MEM_calloc_arrayN(
- sizeof(*ctx->accumulated_counters),
- num_vertices,
- "subdiv accumulated counters");
+ if (!ctx->can_evaluate_normals && !ctx->have_displacement) {
+ return;
+ }
+ /* TODO(sergey): Technically, this is overallocating, we don't need memory
+ * for an inner subdivision vertices. */
+ ctx->accumulated_normals = MEM_calloc_arrayN(
+ sizeof(*ctx->accumulated_normals), num_vertices, "subdiv accumulated normals");
+ ctx->accumulated_counters = MEM_calloc_arrayN(
+ sizeof(*ctx->accumulated_counters), num_vertices, "subdiv accumulated counters");
}
static void subdiv_mesh_context_free(SubdivMeshContext *ctx)
{
- MEM_SAFE_FREE(ctx->accumulated_normals);
- MEM_SAFE_FREE(ctx->accumulated_counters);
+ MEM_SAFE_FREE(ctx->accumulated_normals);
+ MEM_SAFE_FREE(ctx->accumulated_counters);
}
/* =============================================================================
@@ -134,42 +124,39 @@ static void subdiv_mesh_context_free(SubdivMeshContext *ctx)
*/
typedef struct LoopsOfPtex {
- /* First loop of the ptex, starts at ptex (0, 0) and goes in u direction. */
- const MLoop *first_loop;
- /* Last loop of the ptex, starts at ptex (0, 0) and goes in v direction. */
- const MLoop *last_loop;
- /* For quad coarse faces only. */
- const MLoop *second_loop;
- const MLoop *third_loop;
+ /* First loop of the ptex, starts at ptex (0, 0) and goes in u direction. */
+ const MLoop *first_loop;
+ /* Last loop of the ptex, starts at ptex (0, 0) and goes in v direction. */
+ const MLoop *last_loop;
+ /* For quad coarse faces only. */
+ const MLoop *second_loop;
+ const MLoop *third_loop;
} LoopsOfPtex;
-static void loops_of_ptex_get(
- const SubdivMeshContext *ctx,
- LoopsOfPtex *loops_of_ptex,
- const MPoly *coarse_poly,
- const int ptex_of_poly_index)
+static void loops_of_ptex_get(const SubdivMeshContext *ctx,
+ LoopsOfPtex *loops_of_ptex,
+ const MPoly *coarse_poly,
+ const int ptex_of_poly_index)
{
- const MLoop *coarse_mloop = ctx->coarse_mesh->mloop;
- const int first_ptex_loop_index =
- coarse_poly->loopstart + ptex_of_poly_index;
- /* Loop which look in the (opposite) V direction of the current
- * ptex face.
- *
- * TODO(sergey): Get rid of using module on every iteration. */
- const int last_ptex_loop_index =
- coarse_poly->loopstart +
- (ptex_of_poly_index + coarse_poly->totloop - 1) %
- coarse_poly->totloop;
- loops_of_ptex->first_loop = &coarse_mloop[first_ptex_loop_index];
- loops_of_ptex->last_loop = &coarse_mloop[last_ptex_loop_index];
- if (coarse_poly->totloop == 4) {
- loops_of_ptex->second_loop = loops_of_ptex->first_loop + 1;
- loops_of_ptex->third_loop = loops_of_ptex->first_loop + 2;
- }
- else {
- loops_of_ptex->second_loop = NULL;
- loops_of_ptex->third_loop = NULL;
- }
+ const MLoop *coarse_mloop = ctx->coarse_mesh->mloop;
+ const int first_ptex_loop_index = coarse_poly->loopstart + ptex_of_poly_index;
+ /* Loop which look in the (opposite) V direction of the current
+ * ptex face.
+ *
+ * TODO(sergey): Get rid of using module on every iteration. */
+ const int last_ptex_loop_index = coarse_poly->loopstart +
+ (ptex_of_poly_index + coarse_poly->totloop - 1) %
+ coarse_poly->totloop;
+ loops_of_ptex->first_loop = &coarse_mloop[first_ptex_loop_index];
+ loops_of_ptex->last_loop = &coarse_mloop[last_ptex_loop_index];
+ if (coarse_poly->totloop == 4) {
+ loops_of_ptex->second_loop = loops_of_ptex->first_loop + 1;
+ loops_of_ptex->third_loop = loops_of_ptex->first_loop + 2;
+ }
+ else {
+ loops_of_ptex->second_loop = NULL;
+ loops_of_ptex->third_loop = NULL;
+ }
}
/* =============================================================================
@@ -180,136 +167,130 @@ static void loops_of_ptex_get(
* exception cases all over the code. */
typedef struct VerticesForInterpolation {
- /* This field points to a vertex data which is to be used for interpolation.
- * The idea is to avoid unnecessary allocations for regular faces, where
- * we can simply use corner verticies. */
- const CustomData *vertex_data;
- /* Vertices data calculated for ptex corners. There are always 4 elements
- * in this custom data, aligned the following way:
- *
- * index 0 -> uv (0, 0)
- * index 1 -> uv (0, 1)
- * index 2 -> uv (1, 1)
- * index 3 -> uv (1, 0)
- *
- * Is allocated for non-regular faces (triangles and n-gons). */
- CustomData vertex_data_storage;
- bool vertex_data_storage_allocated;
- /* Infices within vertex_data to interpolate for. The indices are aligned
- * with uv coordinates in a similar way as indices in loop_data_storage. */
- int vertex_indices[4];
+ /* This field points to a vertex data which is to be used for interpolation.
+ * The idea is to avoid unnecessary allocations for regular faces, where
+ * we can simply use corner verticies. */
+ const CustomData *vertex_data;
+ /* Vertices data calculated for ptex corners. There are always 4 elements
+ * in this custom data, aligned the following way:
+ *
+ * index 0 -> uv (0, 0)
+ * index 1 -> uv (0, 1)
+ * index 2 -> uv (1, 1)
+ * index 3 -> uv (1, 0)
+ *
+ * Is allocated for non-regular faces (triangles and n-gons). */
+ CustomData vertex_data_storage;
+ bool vertex_data_storage_allocated;
+ /* Infices within vertex_data to interpolate for. The indices are aligned
+ * with uv coordinates in a similar way as indices in loop_data_storage. */
+ int vertex_indices[4];
} VerticesForInterpolation;
-static void vertex_interpolation_init(
- const SubdivMeshContext *ctx,
- VerticesForInterpolation *vertex_interpolation,
- const MPoly *coarse_poly)
+static void vertex_interpolation_init(const SubdivMeshContext *ctx,
+ VerticesForInterpolation *vertex_interpolation,
+ const MPoly *coarse_poly)
{
- const Mesh *coarse_mesh = ctx->coarse_mesh;
- const MLoop *coarse_mloop = coarse_mesh->mloop;
- if (coarse_poly->totloop == 4) {
- vertex_interpolation->vertex_data = &coarse_mesh->vdata;
- vertex_interpolation->vertex_indices[0] =
- coarse_mloop[coarse_poly->loopstart + 0].v;
- vertex_interpolation->vertex_indices[1] =
- coarse_mloop[coarse_poly->loopstart + 1].v;
- vertex_interpolation->vertex_indices[2] =
- coarse_mloop[coarse_poly->loopstart + 2].v;
- vertex_interpolation->vertex_indices[3] =
- coarse_mloop[coarse_poly->loopstart + 3].v;
- vertex_interpolation->vertex_data_storage_allocated = false;
- }
- else {
- vertex_interpolation->vertex_data =
- &vertex_interpolation->vertex_data_storage;
- /* Allocate storage for loops corresponding to ptex corners. */
- CustomData_copy(&ctx->coarse_mesh->vdata,
- &vertex_interpolation->vertex_data_storage,
- CD_MASK_EVERYTHING.vmask,
- CD_CALLOC,
- 4);
- /* Initialize indices. */
- vertex_interpolation->vertex_indices[0] = 0;
- vertex_interpolation->vertex_indices[1] = 1;
- vertex_interpolation->vertex_indices[2] = 2;
- vertex_interpolation->vertex_indices[3] = 3;
- vertex_interpolation->vertex_data_storage_allocated = true;
- /* Interpolate center of poly right away, it stays unchanged for all
- * ptex faces. */
- const float weight = 1.0f / (float)coarse_poly->totloop;
- float *weights = BLI_array_alloca(weights, coarse_poly->totloop);
- int *indices = BLI_array_alloca(indices, coarse_poly->totloop);
- for (int i = 0; i < coarse_poly->totloop; ++i) {
- weights[i] = weight;
- indices[i] = coarse_mloop[coarse_poly->loopstart + i].v;
- }
- CustomData_interp(&coarse_mesh->vdata,
- &vertex_interpolation->vertex_data_storage,
- indices,
- weights, NULL,
- coarse_poly->totloop,
- 2);
- }
+ const Mesh *coarse_mesh = ctx->coarse_mesh;
+ const MLoop *coarse_mloop = coarse_mesh->mloop;
+ if (coarse_poly->totloop == 4) {
+ vertex_interpolation->vertex_data = &coarse_mesh->vdata;
+ vertex_interpolation->vertex_indices[0] = coarse_mloop[coarse_poly->loopstart + 0].v;
+ vertex_interpolation->vertex_indices[1] = coarse_mloop[coarse_poly->loopstart + 1].v;
+ vertex_interpolation->vertex_indices[2] = coarse_mloop[coarse_poly->loopstart + 2].v;
+ vertex_interpolation->vertex_indices[3] = coarse_mloop[coarse_poly->loopstart + 3].v;
+ vertex_interpolation->vertex_data_storage_allocated = false;
+ }
+ else {
+ vertex_interpolation->vertex_data = &vertex_interpolation->vertex_data_storage;
+ /* Allocate storage for loops corresponding to ptex corners. */
+ CustomData_copy(&ctx->coarse_mesh->vdata,
+ &vertex_interpolation->vertex_data_storage,
+ CD_MASK_EVERYTHING.vmask,
+ CD_CALLOC,
+ 4);
+ /* Initialize indices. */
+ vertex_interpolation->vertex_indices[0] = 0;
+ vertex_interpolation->vertex_indices[1] = 1;
+ vertex_interpolation->vertex_indices[2] = 2;
+ vertex_interpolation->vertex_indices[3] = 3;
+ vertex_interpolation->vertex_data_storage_allocated = true;
+ /* Interpolate center of poly right away, it stays unchanged for all
+ * ptex faces. */
+ const float weight = 1.0f / (float)coarse_poly->totloop;
+ float *weights = BLI_array_alloca(weights, coarse_poly->totloop);
+ int *indices = BLI_array_alloca(indices, coarse_poly->totloop);
+ for (int i = 0; i < coarse_poly->totloop; ++i) {
+ weights[i] = weight;
+ indices[i] = coarse_mloop[coarse_poly->loopstart + i].v;
+ }
+ CustomData_interp(&coarse_mesh->vdata,
+ &vertex_interpolation->vertex_data_storage,
+ indices,
+ weights,
+ NULL,
+ coarse_poly->totloop,
+ 2);
+ }
}
-static void vertex_interpolation_from_corner(
- const SubdivMeshContext *ctx,
- VerticesForInterpolation *vertex_interpolation,
- const MPoly *coarse_poly,
- const int corner)
+static void vertex_interpolation_from_corner(const SubdivMeshContext *ctx,
+ VerticesForInterpolation *vertex_interpolation,
+ const MPoly *coarse_poly,
+ const int corner)
{
- if (coarse_poly->totloop == 4) {
- /* Nothing to do, all indices and data is already assigned. */
- }
- else {
- const CustomData *vertex_data = &ctx->coarse_mesh->vdata;
- const Mesh *coarse_mesh = ctx->coarse_mesh;
- const MLoop *coarse_mloop = coarse_mesh->mloop;
- LoopsOfPtex loops_of_ptex;
- loops_of_ptex_get(ctx, &loops_of_ptex, coarse_poly, corner);
- /* Ptex face corner corresponds to a poly loop with same index. */
- CustomData_copy_data(
- vertex_data,
- &vertex_interpolation->vertex_data_storage,
- coarse_mloop[coarse_poly->loopstart + corner].v,
- 0,
- 1);
- /* Interpolate remaining ptex face corners, which hits loops
- * middle points.
- *
- * TODO(sergey): Re-use one of interpolation results from previous
- * iteration. */
- const float weights[2] = {0.5f, 0.5f};
- const int first_loop_index = loops_of_ptex.first_loop - coarse_mloop;
- const int last_loop_index = loops_of_ptex.last_loop - coarse_mloop;
- const int first_indices[2] = {
- coarse_mloop[first_loop_index].v,
- coarse_mloop[coarse_poly->loopstart +
- (first_loop_index - coarse_poly->loopstart + 1) %
- coarse_poly->totloop].v};
- const int last_indices[2] = {coarse_mloop[first_loop_index].v,
- coarse_mloop[last_loop_index].v};
- CustomData_interp(vertex_data,
- &vertex_interpolation->vertex_data_storage,
- first_indices,
- weights, NULL,
- 2,
- 1);
- CustomData_interp(vertex_data,
- &vertex_interpolation->vertex_data_storage,
- last_indices,
- weights, NULL,
- 2,
- 3);
- }
+ if (coarse_poly->totloop == 4) {
+ /* Nothing to do, all indices and data is already assigned. */
+ }
+ else {
+ const CustomData *vertex_data = &ctx->coarse_mesh->vdata;
+ const Mesh *coarse_mesh = ctx->coarse_mesh;
+ const MLoop *coarse_mloop = coarse_mesh->mloop;
+ LoopsOfPtex loops_of_ptex;
+ loops_of_ptex_get(ctx, &loops_of_ptex, coarse_poly, corner);
+ /* Ptex face corner corresponds to a poly loop with same index. */
+ CustomData_copy_data(vertex_data,
+ &vertex_interpolation->vertex_data_storage,
+ coarse_mloop[coarse_poly->loopstart + corner].v,
+ 0,
+ 1);
+ /* Interpolate remaining ptex face corners, which hits loops
+ * middle points.
+ *
+ * TODO(sergey): Re-use one of interpolation results from previous
+ * iteration. */
+ const float weights[2] = {0.5f, 0.5f};
+ const int first_loop_index = loops_of_ptex.first_loop - coarse_mloop;
+ const int last_loop_index = loops_of_ptex.last_loop - coarse_mloop;
+ const int first_indices[2] = {
+ coarse_mloop[first_loop_index].v,
+ coarse_mloop[coarse_poly->loopstart +
+ (first_loop_index - coarse_poly->loopstart + 1) % coarse_poly->totloop]
+ .v};
+ const int last_indices[2] = {coarse_mloop[first_loop_index].v,
+ coarse_mloop[last_loop_index].v};
+ CustomData_interp(vertex_data,
+ &vertex_interpolation->vertex_data_storage,
+ first_indices,
+ weights,
+ NULL,
+ 2,
+ 1);
+ CustomData_interp(vertex_data,
+ &vertex_interpolation->vertex_data_storage,
+ last_indices,
+ weights,
+ NULL,
+ 2,
+ 3);
+ }
}
-static void vertex_interpolation_end(
- VerticesForInterpolation *vertex_interpolation)
+static void vertex_interpolation_end(VerticesForInterpolation *vertex_interpolation)
{
- if (vertex_interpolation->vertex_data_storage_allocated) {
- CustomData_free(&vertex_interpolation->vertex_data_storage, 4);
- }
+ if (vertex_interpolation->vertex_data_storage_allocated) {
+ CustomData_free(&vertex_interpolation->vertex_data_storage, 4);
+ }
}
/* =============================================================================
@@ -317,129 +298,115 @@ static void vertex_interpolation_end(
*/
typedef struct LoopsForInterpolation {
- /* This field points to a loop data which is to be used for interpolation.
- * The idea is to avoid unnecessary allocations for regular faces, where
- * we can simply interpolate corner verticies. */
- const CustomData *loop_data;
- /* Loops data calculated for ptex corners. There are always 4 elements
- * in this custom data, aligned the following way:
- *
- * index 0 -> uv (0, 0)
- * index 1 -> uv (0, 1)
- * index 2 -> uv (1, 1)
- * index 3 -> uv (1, 0)
- *
- * Is allocated for non-regular faces (triangles and n-gons). */
- CustomData loop_data_storage;
- bool loop_data_storage_allocated;
- /* Infices within loop_data to interpolate for. The indices are aligned with
- * uv coordinates in a similar way as indices in loop_data_storage. */
- int loop_indices[4];
+ /* This field points to a loop data which is to be used for interpolation.
+ * The idea is to avoid unnecessary allocations for regular faces, where
+ * we can simply interpolate corner verticies. */
+ const CustomData *loop_data;
+ /* Loops data calculated for ptex corners. There are always 4 elements
+ * in this custom data, aligned the following way:
+ *
+ * index 0 -> uv (0, 0)
+ * index 1 -> uv (0, 1)
+ * index 2 -> uv (1, 1)
+ * index 3 -> uv (1, 0)
+ *
+ * Is allocated for non-regular faces (triangles and n-gons). */
+ CustomData loop_data_storage;
+ bool loop_data_storage_allocated;
+ /* Infices within loop_data to interpolate for. The indices are aligned with
+ * uv coordinates in a similar way as indices in loop_data_storage. */
+ int loop_indices[4];
} LoopsForInterpolation;
-static void loop_interpolation_init(
- const SubdivMeshContext *ctx,
- LoopsForInterpolation *loop_interpolation,
- const MPoly *coarse_poly)
+static void loop_interpolation_init(const SubdivMeshContext *ctx,
+ LoopsForInterpolation *loop_interpolation,
+ const MPoly *coarse_poly)
{
- const Mesh *coarse_mesh = ctx->coarse_mesh;
- if (coarse_poly->totloop == 4) {
- loop_interpolation->loop_data = &coarse_mesh->ldata;
- loop_interpolation->loop_indices[0] = coarse_poly->loopstart + 0;
- loop_interpolation->loop_indices[1] = coarse_poly->loopstart + 1;
- loop_interpolation->loop_indices[2] = coarse_poly->loopstart + 2;
- loop_interpolation->loop_indices[3] = coarse_poly->loopstart + 3;
- loop_interpolation->loop_data_storage_allocated = false;
- }
- else {
- loop_interpolation->loop_data = &loop_interpolation->loop_data_storage;
- /* Allocate storage for loops corresponding to ptex corners. */
- CustomData_copy(&ctx->coarse_mesh->ldata,
- &loop_interpolation->loop_data_storage,
- CD_MASK_EVERYTHING.lmask,
- CD_CALLOC,
- 4);
- /* Initialize indices. */
- loop_interpolation->loop_indices[0] = 0;
- loop_interpolation->loop_indices[1] = 1;
- loop_interpolation->loop_indices[2] = 2;
- loop_interpolation->loop_indices[3] = 3;
- loop_interpolation->loop_data_storage_allocated = true;
- /* Interpolate center of poly right away, it stays unchanged for all
- * ptex faces. */
- const float weight = 1.0f / (float)coarse_poly->totloop;
- float *weights = BLI_array_alloca(weights, coarse_poly->totloop);
- int *indices = BLI_array_alloca(indices, coarse_poly->totloop);
- for (int i = 0; i < coarse_poly->totloop; ++i) {
- weights[i] = weight;
- indices[i] = coarse_poly->loopstart + i;
- }
- CustomData_interp(&coarse_mesh->ldata,
- &loop_interpolation->loop_data_storage,
- indices,
- weights, NULL,
- coarse_poly->totloop,
- 2);
- }
+ const Mesh *coarse_mesh = ctx->coarse_mesh;
+ if (coarse_poly->totloop == 4) {
+ loop_interpolation->loop_data = &coarse_mesh->ldata;
+ loop_interpolation->loop_indices[0] = coarse_poly->loopstart + 0;
+ loop_interpolation->loop_indices[1] = coarse_poly->loopstart + 1;
+ loop_interpolation->loop_indices[2] = coarse_poly->loopstart + 2;
+ loop_interpolation->loop_indices[3] = coarse_poly->loopstart + 3;
+ loop_interpolation->loop_data_storage_allocated = false;
+ }
+ else {
+ loop_interpolation->loop_data = &loop_interpolation->loop_data_storage;
+ /* Allocate storage for loops corresponding to ptex corners. */
+ CustomData_copy(&ctx->coarse_mesh->ldata,
+ &loop_interpolation->loop_data_storage,
+ CD_MASK_EVERYTHING.lmask,
+ CD_CALLOC,
+ 4);
+ /* Initialize indices. */
+ loop_interpolation->loop_indices[0] = 0;
+ loop_interpolation->loop_indices[1] = 1;
+ loop_interpolation->loop_indices[2] = 2;
+ loop_interpolation->loop_indices[3] = 3;
+ loop_interpolation->loop_data_storage_allocated = true;
+ /* Interpolate center of poly right away, it stays unchanged for all
+ * ptex faces. */
+ const float weight = 1.0f / (float)coarse_poly->totloop;
+ float *weights = BLI_array_alloca(weights, coarse_poly->totloop);
+ int *indices = BLI_array_alloca(indices, coarse_poly->totloop);
+ for (int i = 0; i < coarse_poly->totloop; ++i) {
+ weights[i] = weight;
+ indices[i] = coarse_poly->loopstart + i;
+ }
+ CustomData_interp(&coarse_mesh->ldata,
+ &loop_interpolation->loop_data_storage,
+ indices,
+ weights,
+ NULL,
+ coarse_poly->totloop,
+ 2);
+ }
}
-static void loop_interpolation_from_corner(
- const SubdivMeshContext *ctx,
- LoopsForInterpolation *loop_interpolation,
- const MPoly *coarse_poly,
- const int corner)
+static void loop_interpolation_from_corner(const SubdivMeshContext *ctx,
+ LoopsForInterpolation *loop_interpolation,
+ const MPoly *coarse_poly,
+ const int corner)
{
- if (coarse_poly->totloop == 4) {
- /* Nothing to do, all indices and data is already assigned. */
- }
- else {
- const CustomData *loop_data = &ctx->coarse_mesh->ldata;
- const Mesh *coarse_mesh = ctx->coarse_mesh;
- const MLoop *coarse_mloop = coarse_mesh->mloop;
- LoopsOfPtex loops_of_ptex;
- loops_of_ptex_get(ctx, &loops_of_ptex, coarse_poly, corner);
- /* Ptex face corner corresponds to a poly loop with same index. */
- CustomData_free_elem(&loop_interpolation->loop_data_storage, 0, 1);
- CustomData_copy_data(loop_data,
- &loop_interpolation->loop_data_storage,
- coarse_poly->loopstart + corner,
- 0,
- 1);
- /* Interpolate remaining ptex face corners, which hits loops
- * middle points.
- *
- * TODO(sergey): Re-use one of interpolation results from previous
- * iteration. */
- const float weights[2] = {0.5f, 0.5f};
- const int base_loop_index = coarse_poly->loopstart;
- const int first_loop_index = loops_of_ptex.first_loop - coarse_mloop;
- const int second_loop_index =
- base_loop_index +
- (first_loop_index - base_loop_index + 1) % coarse_poly->totloop;
- const int first_indices[2] = {first_loop_index, second_loop_index};
- const int last_indices[2] = {
- loops_of_ptex.last_loop - coarse_mloop,
- loops_of_ptex.first_loop - coarse_mloop};
- CustomData_interp(loop_data,
- &loop_interpolation->loop_data_storage,
- first_indices,
- weights, NULL,
- 2,
- 1);
- CustomData_interp(loop_data,
- &loop_interpolation->loop_data_storage,
- last_indices,
- weights, NULL,
- 2,
- 3);
- }
+ if (coarse_poly->totloop == 4) {
+ /* Nothing to do, all indices and data is already assigned. */
+ }
+ else {
+ const CustomData *loop_data = &ctx->coarse_mesh->ldata;
+ const Mesh *coarse_mesh = ctx->coarse_mesh;
+ const MLoop *coarse_mloop = coarse_mesh->mloop;
+ LoopsOfPtex loops_of_ptex;
+ loops_of_ptex_get(ctx, &loops_of_ptex, coarse_poly, corner);
+ /* Ptex face corner corresponds to a poly loop with same index. */
+ CustomData_free_elem(&loop_interpolation->loop_data_storage, 0, 1);
+ CustomData_copy_data(
+ loop_data, &loop_interpolation->loop_data_storage, coarse_poly->loopstart + corner, 0, 1);
+ /* Interpolate remaining ptex face corners, which hits loops
+ * middle points.
+ *
+ * TODO(sergey): Re-use one of interpolation results from previous
+ * iteration. */
+ const float weights[2] = {0.5f, 0.5f};
+ const int base_loop_index = coarse_poly->loopstart;
+ const int first_loop_index = loops_of_ptex.first_loop - coarse_mloop;
+ const int second_loop_index = base_loop_index +
+ (first_loop_index - base_loop_index + 1) % coarse_poly->totloop;
+ const int first_indices[2] = {first_loop_index, second_loop_index};
+ const int last_indices[2] = {loops_of_ptex.last_loop - coarse_mloop,
+ loops_of_ptex.first_loop - coarse_mloop};
+ CustomData_interp(
+ loop_data, &loop_interpolation->loop_data_storage, first_indices, weights, NULL, 2, 1);
+ CustomData_interp(
+ loop_data, &loop_interpolation->loop_data_storage, last_indices, weights, NULL, 2, 3);
+ }
}
static void loop_interpolation_end(LoopsForInterpolation *loop_interpolation)
{
- if (loop_interpolation->loop_data_storage_allocated) {
- CustomData_free(&loop_interpolation->loop_data_storage, 4);
- }
+ if (loop_interpolation->loop_data_storage_allocated) {
+ CustomData_free(&loop_interpolation->loop_data_storage, 4);
+ }
}
/* =============================================================================
@@ -447,516 +414,472 @@ static void loop_interpolation_end(LoopsForInterpolation *loop_interpolation)
*/
typedef struct SubdivMeshTLS {
- bool vertex_interpolation_initialized;
- VerticesForInterpolation vertex_interpolation;
- const MPoly *vertex_interpolation_coarse_poly;
- int vertex_interpolation_coarse_corner;
-
- bool loop_interpolation_initialized;
- LoopsForInterpolation loop_interpolation;
- const MPoly *loop_interpolation_coarse_poly;
- int loop_interpolation_coarse_corner;
+ bool vertex_interpolation_initialized;
+ VerticesForInterpolation vertex_interpolation;
+ const MPoly *vertex_interpolation_coarse_poly;
+ int vertex_interpolation_coarse_corner;
+
+ bool loop_interpolation_initialized;
+ LoopsForInterpolation loop_interpolation;
+ const MPoly *loop_interpolation_coarse_poly;
+ int loop_interpolation_coarse_corner;
} SubdivMeshTLS;
static void subdiv_mesh_tls_free(void *tls_v)
{
- SubdivMeshTLS *tls = tls_v;
- if (tls->vertex_interpolation_initialized) {
- vertex_interpolation_end(&tls->vertex_interpolation);
- }
- if (tls->loop_interpolation_initialized) {
- loop_interpolation_end(&tls->loop_interpolation);
- }
+ SubdivMeshTLS *tls = tls_v;
+ if (tls->vertex_interpolation_initialized) {
+ vertex_interpolation_end(&tls->vertex_interpolation);
+ }
+ if (tls->loop_interpolation_initialized) {
+ loop_interpolation_end(&tls->loop_interpolation);
+ }
}
/* =============================================================================
* Evaluation helper functions.
*/
-static void eval_final_point_and_vertex_normal(
- Subdiv *subdiv,
- const int ptex_face_index,
- const float u, const float v,
- float r_P[3], short r_N[3])
+static void eval_final_point_and_vertex_normal(Subdiv *subdiv,
+ const int ptex_face_index,
+ const float u,
+ const float v,
+ float r_P[3],
+ short r_N[3])
{
- if (subdiv->displacement_evaluator == NULL) {
- BKE_subdiv_eval_limit_point_and_short_normal(
- subdiv, ptex_face_index, u, v, r_P, r_N);
- }
- else {
- BKE_subdiv_eval_final_point(
- subdiv, ptex_face_index, u, v, r_P);
- }
+ if (subdiv->displacement_evaluator == NULL) {
+ BKE_subdiv_eval_limit_point_and_short_normal(subdiv, ptex_face_index, u, v, r_P, r_N);
+ }
+ else {
+ BKE_subdiv_eval_final_point(subdiv, ptex_face_index, u, v, r_P);
+ }
}
/* =============================================================================
* Accumulation helpers.
*/
-static void subdiv_accumulate_vertex_normal_and_displacement(
- SubdivMeshContext *ctx,
- const int ptex_face_index,
- const float u, const float v,
- MVert *subdiv_vert)
+static void subdiv_accumulate_vertex_normal_and_displacement(SubdivMeshContext *ctx,
+ const int ptex_face_index,
+ const float u,
+ const float v,
+ MVert *subdiv_vert)
{
- Subdiv *subdiv = ctx->subdiv;
- const int subdiv_vertex_index = subdiv_vert - ctx->subdiv_mesh->mvert;
- float dummy_P[3], dPdu[3], dPdv[3], D[3];
- BKE_subdiv_eval_limit_point_and_derivatives(
- subdiv, ptex_face_index, u, v, dummy_P, dPdu, dPdv);
- /* Accumulate normal. */
- if (ctx->can_evaluate_normals) {
- float N[3];
- cross_v3_v3v3(N, dPdu, dPdv);
- normalize_v3(N);
- add_v3_v3(ctx->accumulated_normals[subdiv_vertex_index], N);
- }
- /* Accumulate displacement if needed. */
- if (ctx->have_displacement) {
- BKE_subdiv_eval_displacement(
- subdiv, ptex_face_index, u, v, dPdu, dPdv, D);
- add_v3_v3(subdiv_vert->co, D);
- }
- ++ctx->accumulated_counters[subdiv_vertex_index];
+ Subdiv *subdiv = ctx->subdiv;
+ const int subdiv_vertex_index = subdiv_vert - ctx->subdiv_mesh->mvert;
+ float dummy_P[3], dPdu[3], dPdv[3], D[3];
+ BKE_subdiv_eval_limit_point_and_derivatives(subdiv, ptex_face_index, u, v, dummy_P, dPdu, dPdv);
+ /* Accumulate normal. */
+ if (ctx->can_evaluate_normals) {
+ float N[3];
+ cross_v3_v3v3(N, dPdu, dPdv);
+ normalize_v3(N);
+ add_v3_v3(ctx->accumulated_normals[subdiv_vertex_index], N);
+ }
+ /* Accumulate displacement if needed. */
+ if (ctx->have_displacement) {
+ BKE_subdiv_eval_displacement(subdiv, ptex_face_index, u, v, dPdu, dPdv, D);
+ add_v3_v3(subdiv_vert->co, D);
+ }
+ ++ctx->accumulated_counters[subdiv_vertex_index];
}
/* =============================================================================
* Callbacks.
*/
-static bool subdiv_mesh_topology_info(
- const SubdivForeachContext *foreach_context,
- const int num_vertices,
- const int num_edges,
- const int num_loops,
- const int num_polygons)
+static bool subdiv_mesh_topology_info(const SubdivForeachContext *foreach_context,
+ const int num_vertices,
+ const int num_edges,
+ const int num_loops,
+ const int num_polygons)
{
- SubdivMeshContext *subdiv_context = foreach_context->user_data;
- subdiv_context->subdiv_mesh = BKE_mesh_new_nomain_from_template(
- subdiv_context->coarse_mesh,
- num_vertices,
- num_edges,
- 0,
- num_loops,
- num_polygons);
- subdiv_mesh_ctx_cache_custom_data_layers(subdiv_context);
- subdiv_mesh_prepare_accumulator(subdiv_context, num_vertices);
- return true;
+ SubdivMeshContext *subdiv_context = foreach_context->user_data;
+ subdiv_context->subdiv_mesh = BKE_mesh_new_nomain_from_template(
+ subdiv_context->coarse_mesh, num_vertices, num_edges, 0, num_loops, num_polygons);
+ subdiv_mesh_ctx_cache_custom_data_layers(subdiv_context);
+ subdiv_mesh_prepare_accumulator(subdiv_context, num_vertices);
+ return true;
}
/* =============================================================================
* Vertex subdivision process.
*/
-static void subdiv_vertex_data_copy(
- const SubdivMeshContext *ctx,
- const MVert *coarse_vertex,
- MVert *subdiv_vertex)
+static void subdiv_vertex_data_copy(const SubdivMeshContext *ctx,
+ const MVert *coarse_vertex,
+ MVert *subdiv_vertex)
{
- const Mesh *coarse_mesh = ctx->coarse_mesh;
- Mesh *subdiv_mesh = ctx->subdiv_mesh;
- const int coarse_vertex_index = coarse_vertex - coarse_mesh->mvert;
- const int subdiv_vertex_index = subdiv_vertex - subdiv_mesh->mvert;
- CustomData_copy_data(&coarse_mesh->vdata,
- &ctx->subdiv_mesh->vdata,
- coarse_vertex_index,
- subdiv_vertex_index,
- 1);
+ const Mesh *coarse_mesh = ctx->coarse_mesh;
+ Mesh *subdiv_mesh = ctx->subdiv_mesh;
+ const int coarse_vertex_index = coarse_vertex - coarse_mesh->mvert;
+ const int subdiv_vertex_index = subdiv_vertex - subdiv_mesh->mvert;
+ CustomData_copy_data(
+ &coarse_mesh->vdata, &ctx->subdiv_mesh->vdata, coarse_vertex_index, subdiv_vertex_index, 1);
}
-static void subdiv_vertex_data_interpolate(
- const SubdivMeshContext *ctx,
- MVert *subdiv_vertex,
- const VerticesForInterpolation *vertex_interpolation,
- const float u, const float v)
+static void subdiv_vertex_data_interpolate(const SubdivMeshContext *ctx,
+ MVert *subdiv_vertex,
+ const VerticesForInterpolation *vertex_interpolation,
+ const float u,
+ const float v)
{
- const int subdiv_vertex_index = subdiv_vertex - ctx->subdiv_mesh->mvert;
- const float weights[4] = {(1.0f - u) * (1.0f - v),
- u * (1.0f - v),
- u * v,
- (1.0f - u) * v};
- CustomData_interp(vertex_interpolation->vertex_data,
- &ctx->subdiv_mesh->vdata,
- vertex_interpolation->vertex_indices,
- weights, NULL,
- 4,
- subdiv_vertex_index);
- if (ctx->vert_origindex != NULL) {
- ctx->vert_origindex[subdiv_vertex_index] = ORIGINDEX_NONE;
- }
+ const int subdiv_vertex_index = subdiv_vertex - ctx->subdiv_mesh->mvert;
+ const float weights[4] = {(1.0f - u) * (1.0f - v), u * (1.0f - v), u * v, (1.0f - u) * v};
+ CustomData_interp(vertex_interpolation->vertex_data,
+ &ctx->subdiv_mesh->vdata,
+ vertex_interpolation->vertex_indices,
+ weights,
+ NULL,
+ 4,
+ subdiv_vertex_index);
+ if (ctx->vert_origindex != NULL) {
+ ctx->vert_origindex[subdiv_vertex_index] = ORIGINDEX_NONE;
+ }
}
-static void evaluate_vertex_and_apply_displacement_copy(
- const SubdivMeshContext *ctx,
- const int ptex_face_index,
- const float u, const float v,
- const MVert *coarse_vert,
- MVert *subdiv_vert)
+static void evaluate_vertex_and_apply_displacement_copy(const SubdivMeshContext *ctx,
+ const int ptex_face_index,
+ const float u,
+ const float v,
+ const MVert *coarse_vert,
+ MVert *subdiv_vert)
{
- const int subdiv_vertex_index = subdiv_vert - ctx->subdiv_mesh->mvert;
- const float inv_num_accumulated =
- 1.0f / ctx->accumulated_counters[subdiv_vertex_index];
- /* Displacement is accumulated in subdiv vertex position.
- * Needs to be backed up before copying data from original vertex. */
- float D[3] = {0.0f, 0.0f, 0.0f};
- if (ctx->have_displacement) {
- copy_v3_v3(D, subdiv_vert->co);
- mul_v3_fl(D, inv_num_accumulated);
- }
- /* Copy custom data and evaluate position. */
- subdiv_vertex_data_copy(ctx, coarse_vert, subdiv_vert);
- BKE_subdiv_eval_limit_point(
- ctx->subdiv, ptex_face_index, u, v, subdiv_vert->co);
- /* Apply displacement. */
- add_v3_v3(subdiv_vert->co, D);
- /* Copy normal from accumulated storage. */
- if (ctx->can_evaluate_normals) {
- float N[3];
- copy_v3_v3(N, ctx->accumulated_normals[subdiv_vertex_index]);
- normalize_v3(N);
- normal_float_to_short_v3(subdiv_vert->no, N);
- }
+ const int subdiv_vertex_index = subdiv_vert - ctx->subdiv_mesh->mvert;
+ const float inv_num_accumulated = 1.0f / ctx->accumulated_counters[subdiv_vertex_index];
+ /* Displacement is accumulated in subdiv vertex position.
+ * Needs to be backed up before copying data from original vertex. */
+ float D[3] = {0.0f, 0.0f, 0.0f};
+ if (ctx->have_displacement) {
+ copy_v3_v3(D, subdiv_vert->co);
+ mul_v3_fl(D, inv_num_accumulated);
+ }
+ /* Copy custom data and evaluate position. */
+ subdiv_vertex_data_copy(ctx, coarse_vert, subdiv_vert);
+ BKE_subdiv_eval_limit_point(ctx->subdiv, ptex_face_index, u, v, subdiv_vert->co);
+ /* Apply displacement. */
+ add_v3_v3(subdiv_vert->co, D);
+ /* Copy normal from accumulated storage. */
+ if (ctx->can_evaluate_normals) {
+ float N[3];
+ copy_v3_v3(N, ctx->accumulated_normals[subdiv_vertex_index]);
+ normalize_v3(N);
+ normal_float_to_short_v3(subdiv_vert->no, N);
+ }
}
static void evaluate_vertex_and_apply_displacement_interpolate(
- const SubdivMeshContext *ctx,
- const int ptex_face_index,
- const float u, const float v,
- VerticesForInterpolation *vertex_interpolation,
- MVert *subdiv_vert)
+ const SubdivMeshContext *ctx,
+ const int ptex_face_index,
+ const float u,
+ const float v,
+ VerticesForInterpolation *vertex_interpolation,
+ MVert *subdiv_vert)
{
- const int subdiv_vertex_index = subdiv_vert - ctx->subdiv_mesh->mvert;
- const float inv_num_accumulated =
- 1.0f / ctx->accumulated_counters[subdiv_vertex_index];
- /* Displacement is accumulated in subdiv vertex position.
- * Needs to be backed up before copying data from original vertex. */
- float D[3] = {0.0f, 0.0f, 0.0f};
- if (ctx->have_displacement) {
- copy_v3_v3(D, subdiv_vert->co);
- mul_v3_fl(D, inv_num_accumulated);
- }
- /* Interpolate custom data and evaluate position. */
- subdiv_vertex_data_interpolate(
- ctx, subdiv_vert, vertex_interpolation, u, v);
- BKE_subdiv_eval_limit_point(
- ctx->subdiv, ptex_face_index, u, v, subdiv_vert->co);
- /* Apply displacement. */
- add_v3_v3(subdiv_vert->co, D);
- /* Copy normal from accumulated storage. */
- if (ctx->can_evaluate_normals) {
- float N[3];
- copy_v3_v3(N, ctx->accumulated_normals[subdiv_vertex_index]);
- mul_v3_fl(N, inv_num_accumulated);
- normalize_v3(N);
- normal_float_to_short_v3(subdiv_vert->no, N);
- }
+ const int subdiv_vertex_index = subdiv_vert - ctx->subdiv_mesh->mvert;
+ const float inv_num_accumulated = 1.0f / ctx->accumulated_counters[subdiv_vertex_index];
+ /* Displacement is accumulated in subdiv vertex position.
+ * Needs to be backed up before copying data from original vertex. */
+ float D[3] = {0.0f, 0.0f, 0.0f};
+ if (ctx->have_displacement) {
+ copy_v3_v3(D, subdiv_vert->co);
+ mul_v3_fl(D, inv_num_accumulated);
+ }
+ /* Interpolate custom data and evaluate position. */
+ subdiv_vertex_data_interpolate(ctx, subdiv_vert, vertex_interpolation, u, v);
+ BKE_subdiv_eval_limit_point(ctx->subdiv, ptex_face_index, u, v, subdiv_vert->co);
+ /* Apply displacement. */
+ add_v3_v3(subdiv_vert->co, D);
+ /* Copy normal from accumulated storage. */
+ if (ctx->can_evaluate_normals) {
+ float N[3];
+ copy_v3_v3(N, ctx->accumulated_normals[subdiv_vertex_index]);
+ mul_v3_fl(N, inv_num_accumulated);
+ normalize_v3(N);
+ normal_float_to_short_v3(subdiv_vert->no, N);
+ }
}
-static void subdiv_mesh_vertex_every_corner_or_edge(
- const SubdivForeachContext *foreach_context,
- void *UNUSED(tls),
- const int ptex_face_index,
- const float u, const float v,
- const int subdiv_vertex_index)
+static void subdiv_mesh_vertex_every_corner_or_edge(const SubdivForeachContext *foreach_context,
+ void *UNUSED(tls),
+ const int ptex_face_index,
+ const float u,
+ const float v,
+ const int subdiv_vertex_index)
{
- SubdivMeshContext *ctx = foreach_context->user_data;
- Mesh *subdiv_mesh = ctx->subdiv_mesh;
- MVert *subdiv_mvert = subdiv_mesh->mvert;
- MVert *subdiv_vert = &subdiv_mvert[subdiv_vertex_index];
- subdiv_accumulate_vertex_normal_and_displacement(
- ctx, ptex_face_index, u, v, subdiv_vert);
+ SubdivMeshContext *ctx = foreach_context->user_data;
+ Mesh *subdiv_mesh = ctx->subdiv_mesh;
+ MVert *subdiv_mvert = subdiv_mesh->mvert;
+ MVert *subdiv_vert = &subdiv_mvert[subdiv_vertex_index];
+ subdiv_accumulate_vertex_normal_and_displacement(ctx, ptex_face_index, u, v, subdiv_vert);
}
-static void subdiv_mesh_vertex_every_corner(
- const SubdivForeachContext *foreach_context,
- void *tls,
- const int ptex_face_index,
- const float u, const float v,
- const int UNUSED(coarse_vertex_index),
- const int UNUSED(coarse_poly_index),
- const int UNUSED(coarse_corner),
- const int subdiv_vertex_index)
+static void subdiv_mesh_vertex_every_corner(const SubdivForeachContext *foreach_context,
+ void *tls,
+ const int ptex_face_index,
+ const float u,
+ const float v,
+ const int UNUSED(coarse_vertex_index),
+ const int UNUSED(coarse_poly_index),
+ const int UNUSED(coarse_corner),
+ const int subdiv_vertex_index)
{
- subdiv_mesh_vertex_every_corner_or_edge(
- foreach_context, tls, ptex_face_index, u, v, subdiv_vertex_index);
+ subdiv_mesh_vertex_every_corner_or_edge(
+ foreach_context, tls, ptex_face_index, u, v, subdiv_vertex_index);
}
-static void subdiv_mesh_vertex_every_edge(
- const SubdivForeachContext *foreach_context,
- void *tls,
- const int ptex_face_index,
- const float u, const float v,
- const int UNUSED(coarse_edge_index),
- const int UNUSED(coarse_poly_index),
- const int UNUSED(coarse_corner),
- const int subdiv_vertex_index)
+static void subdiv_mesh_vertex_every_edge(const SubdivForeachContext *foreach_context,
+ void *tls,
+ const int ptex_face_index,
+ const float u,
+ const float v,
+ const int UNUSED(coarse_edge_index),
+ const int UNUSED(coarse_poly_index),
+ const int UNUSED(coarse_corner),
+ const int subdiv_vertex_index)
{
- subdiv_mesh_vertex_every_corner_or_edge(
- foreach_context, tls, ptex_face_index, u, v, subdiv_vertex_index);
+ subdiv_mesh_vertex_every_corner_or_edge(
+ foreach_context, tls, ptex_face_index, u, v, subdiv_vertex_index);
}
-static void subdiv_mesh_vertex_corner(
- const SubdivForeachContext *foreach_context,
- void *UNUSED(tls),
- const int ptex_face_index,
- const float u, const float v,
- const int coarse_vertex_index,
- const int UNUSED(coarse_poly_index),
- const int UNUSED(coarse_corner),
- const int subdiv_vertex_index)
+static void subdiv_mesh_vertex_corner(const SubdivForeachContext *foreach_context,
+ void *UNUSED(tls),
+ const int ptex_face_index,
+ const float u,
+ const float v,
+ const int coarse_vertex_index,
+ const int UNUSED(coarse_poly_index),
+ const int UNUSED(coarse_corner),
+ const int subdiv_vertex_index)
{
- BLI_assert(coarse_vertex_index != ORIGINDEX_NONE);
- SubdivMeshContext *ctx = foreach_context->user_data;
- const Mesh *coarse_mesh = ctx->coarse_mesh;
- const MVert *coarse_mvert = coarse_mesh->mvert;
- Mesh *subdiv_mesh = ctx->subdiv_mesh;
- MVert *subdiv_mvert = subdiv_mesh->mvert;
- const MVert *coarse_vert = &coarse_mvert[coarse_vertex_index];
- MVert *subdiv_vert = &subdiv_mvert[subdiv_vertex_index];
- evaluate_vertex_and_apply_displacement_copy(
- ctx, ptex_face_index, u, v, coarse_vert, subdiv_vert);
+ BLI_assert(coarse_vertex_index != ORIGINDEX_NONE);
+ SubdivMeshContext *ctx = foreach_context->user_data;
+ const Mesh *coarse_mesh = ctx->coarse_mesh;
+ const MVert *coarse_mvert = coarse_mesh->mvert;
+ Mesh *subdiv_mesh = ctx->subdiv_mesh;
+ MVert *subdiv_mvert = subdiv_mesh->mvert;
+ const MVert *coarse_vert = &coarse_mvert[coarse_vertex_index];
+ MVert *subdiv_vert = &subdiv_mvert[subdiv_vertex_index];
+ evaluate_vertex_and_apply_displacement_copy(
+ ctx, ptex_face_index, u, v, coarse_vert, subdiv_vert);
}
-static void subdiv_mesh_ensure_vertex_interpolation(
- SubdivMeshContext *ctx,
- SubdivMeshTLS *tls,
- const MPoly *coarse_poly,
- const int coarse_corner)
+static void subdiv_mesh_ensure_vertex_interpolation(SubdivMeshContext *ctx,
+ SubdivMeshTLS *tls,
+ const MPoly *coarse_poly,
+ const int coarse_corner)
{
- /* Check whether we've moved to another corner or polygon. */
- if (tls->vertex_interpolation_initialized) {
- if (tls->vertex_interpolation_coarse_poly != coarse_poly ||
- tls->vertex_interpolation_coarse_corner != coarse_corner)
- {
- vertex_interpolation_end(&tls->vertex_interpolation);
- tls->vertex_interpolation_initialized = false;
- }
- }
- /* Initialize the interpolation. */
- if (!tls->vertex_interpolation_initialized) {
- vertex_interpolation_init(ctx, &tls->vertex_interpolation, coarse_poly);
- }
- /* Update it for a new corner if needed. */
- if (!tls->vertex_interpolation_initialized ||
- tls->vertex_interpolation_coarse_corner != coarse_corner)
- {
- vertex_interpolation_from_corner(
- ctx, &tls->vertex_interpolation, coarse_poly, coarse_corner);
- }
- /* Store settings used for the current state of interpolator. */
- tls->vertex_interpolation_initialized = true;
- tls->vertex_interpolation_coarse_poly = coarse_poly;
- tls->vertex_interpolation_coarse_corner = coarse_corner;
+ /* Check whether we've moved to another corner or polygon. */
+ if (tls->vertex_interpolation_initialized) {
+ if (tls->vertex_interpolation_coarse_poly != coarse_poly ||
+ tls->vertex_interpolation_coarse_corner != coarse_corner) {
+ vertex_interpolation_end(&tls->vertex_interpolation);
+ tls->vertex_interpolation_initialized = false;
+ }
+ }
+ /* Initialize the interpolation. */
+ if (!tls->vertex_interpolation_initialized) {
+ vertex_interpolation_init(ctx, &tls->vertex_interpolation, coarse_poly);
+ }
+ /* Update it for a new corner if needed. */
+ if (!tls->vertex_interpolation_initialized ||
+ tls->vertex_interpolation_coarse_corner != coarse_corner) {
+ vertex_interpolation_from_corner(ctx, &tls->vertex_interpolation, coarse_poly, coarse_corner);
+ }
+ /* Store settings used for the current state of interpolator. */
+ tls->vertex_interpolation_initialized = true;
+ tls->vertex_interpolation_coarse_poly = coarse_poly;
+ tls->vertex_interpolation_coarse_corner = coarse_corner;
}
-static void subdiv_mesh_vertex_edge(
- const SubdivForeachContext *foreach_context,
- void *tls_v,
- const int ptex_face_index,
- const float u, const float v,
- const int UNUSED(coarse_edge_index),
- const int coarse_poly_index,
- const int coarse_corner,
- const int subdiv_vertex_index)
+static void subdiv_mesh_vertex_edge(const SubdivForeachContext *foreach_context,
+ void *tls_v,
+ const int ptex_face_index,
+ const float u,
+ const float v,
+ const int UNUSED(coarse_edge_index),
+ const int coarse_poly_index,
+ const int coarse_corner,
+ const int subdiv_vertex_index)
{
- SubdivMeshContext *ctx = foreach_context->user_data;
- SubdivMeshTLS *tls = tls_v;
- const Mesh *coarse_mesh = ctx->coarse_mesh;
- const MPoly *coarse_mpoly = coarse_mesh->mpoly;
- const MPoly *coarse_poly = &coarse_mpoly[coarse_poly_index];
- Mesh *subdiv_mesh = ctx->subdiv_mesh;
- MVert *subdiv_mvert = subdiv_mesh->mvert;
- MVert *subdiv_vert = &subdiv_mvert[subdiv_vertex_index];
- subdiv_mesh_ensure_vertex_interpolation(
- ctx, tls, coarse_poly, coarse_corner);
- evaluate_vertex_and_apply_displacement_interpolate(
- ctx,
- ptex_face_index, u, v,
- &tls->vertex_interpolation,
- subdiv_vert);
+ SubdivMeshContext *ctx = foreach_context->user_data;
+ SubdivMeshTLS *tls = tls_v;
+ const Mesh *coarse_mesh = ctx->coarse_mesh;
+ const MPoly *coarse_mpoly = coarse_mesh->mpoly;
+ const MPoly *coarse_poly = &coarse_mpoly[coarse_poly_index];
+ Mesh *subdiv_mesh = ctx->subdiv_mesh;
+ MVert *subdiv_mvert = subdiv_mesh->mvert;
+ MVert *subdiv_vert = &subdiv_mvert[subdiv_vertex_index];
+ subdiv_mesh_ensure_vertex_interpolation(ctx, tls, coarse_poly, coarse_corner);
+ evaluate_vertex_and_apply_displacement_interpolate(
+ ctx, ptex_face_index, u, v, &tls->vertex_interpolation, subdiv_vert);
}
-static void subdiv_mesh_vertex_inner(
- const SubdivForeachContext *foreach_context,
- void *tls_v,
- const int ptex_face_index,
- const float u, const float v,
- const int coarse_poly_index,
- const int coarse_corner,
- const int subdiv_vertex_index)
+static void subdiv_mesh_vertex_inner(const SubdivForeachContext *foreach_context,
+ void *tls_v,
+ const int ptex_face_index,
+ const float u,
+ const float v,
+ const int coarse_poly_index,
+ const int coarse_corner,
+ const int subdiv_vertex_index)
{
- SubdivMeshContext *ctx = foreach_context->user_data;
- SubdivMeshTLS *tls = tls_v;
- Subdiv *subdiv = ctx->subdiv;
- const Mesh *coarse_mesh = ctx->coarse_mesh;
- const MPoly *coarse_mpoly = coarse_mesh->mpoly;
- const MPoly *coarse_poly = &coarse_mpoly[coarse_poly_index];
- Mesh *subdiv_mesh = ctx->subdiv_mesh;
- MVert *subdiv_mvert = subdiv_mesh->mvert;
- MVert *subdiv_vert = &subdiv_mvert[subdiv_vertex_index];
- subdiv_mesh_ensure_vertex_interpolation(
- ctx, tls, coarse_poly, coarse_corner);
- subdiv_vertex_data_interpolate(
- ctx, subdiv_vert, &tls->vertex_interpolation, u, v);
- eval_final_point_and_vertex_normal(
- subdiv, ptex_face_index, u, v, subdiv_vert->co, subdiv_vert->no);
+ SubdivMeshContext *ctx = foreach_context->user_data;
+ SubdivMeshTLS *tls = tls_v;
+ Subdiv *subdiv = ctx->subdiv;
+ const Mesh *coarse_mesh = ctx->coarse_mesh;
+ const MPoly *coarse_mpoly = coarse_mesh->mpoly;
+ const MPoly *coarse_poly = &coarse_mpoly[coarse_poly_index];
+ Mesh *subdiv_mesh = ctx->subdiv_mesh;
+ MVert *subdiv_mvert = subdiv_mesh->mvert;
+ MVert *subdiv_vert = &subdiv_mvert[subdiv_vertex_index];
+ subdiv_mesh_ensure_vertex_interpolation(ctx, tls, coarse_poly, coarse_corner);
+ subdiv_vertex_data_interpolate(ctx, subdiv_vert, &tls->vertex_interpolation, u, v);
+ eval_final_point_and_vertex_normal(
+ subdiv, ptex_face_index, u, v, subdiv_vert->co, subdiv_vert->no);
}
/* =============================================================================
* Edge subdivision process.
*/
-static void subdiv_copy_edge_data(
- SubdivMeshContext *ctx,
- MEdge *subdiv_edge,
- const MEdge *coarse_edge)
+static void subdiv_copy_edge_data(SubdivMeshContext *ctx,
+ MEdge *subdiv_edge,
+ const MEdge *coarse_edge)
{
- const int subdiv_edge_index = subdiv_edge - ctx->subdiv_mesh->medge;
- if (coarse_edge == NULL) {
- subdiv_edge->crease = 0;
- subdiv_edge->bweight = 0;
- subdiv_edge->flag = 0;
- if (!ctx->settings->use_optimal_display) {
- subdiv_edge->flag |= ME_EDGERENDER;
- }
- if (ctx->edge_origindex != NULL) {
- ctx->edge_origindex[subdiv_edge_index] = ORIGINDEX_NONE;
- }
- return;
- }
- const int coarse_edge_index = coarse_edge - ctx->coarse_mesh->medge;
- CustomData_copy_data(&ctx->coarse_mesh->edata,
- &ctx->subdiv_mesh->edata,
- coarse_edge_index,
- subdiv_edge_index,
- 1);
- subdiv_edge->flag |= ME_EDGERENDER;
+ const int subdiv_edge_index = subdiv_edge - ctx->subdiv_mesh->medge;
+ if (coarse_edge == NULL) {
+ subdiv_edge->crease = 0;
+ subdiv_edge->bweight = 0;
+ subdiv_edge->flag = 0;
+ if (!ctx->settings->use_optimal_display) {
+ subdiv_edge->flag |= ME_EDGERENDER;
+ }
+ if (ctx->edge_origindex != NULL) {
+ ctx->edge_origindex[subdiv_edge_index] = ORIGINDEX_NONE;
+ }
+ return;
+ }
+ const int coarse_edge_index = coarse_edge - ctx->coarse_mesh->medge;
+ CustomData_copy_data(
+ &ctx->coarse_mesh->edata, &ctx->subdiv_mesh->edata, coarse_edge_index, subdiv_edge_index, 1);
+ subdiv_edge->flag |= ME_EDGERENDER;
}
-static void subdiv_mesh_edge(
- const SubdivForeachContext *foreach_context,
- void *UNUSED(tls),
- const int coarse_edge_index,
- const int subdiv_edge_index,
- const int subdiv_v1, const int subdiv_v2)
+static void subdiv_mesh_edge(const SubdivForeachContext *foreach_context,
+ void *UNUSED(tls),
+ const int coarse_edge_index,
+ const int subdiv_edge_index,
+ const int subdiv_v1,
+ const int subdiv_v2)
{
- SubdivMeshContext *ctx = foreach_context->user_data;
- Mesh *subdiv_mesh = ctx->subdiv_mesh;
- MEdge *subdiv_medge = subdiv_mesh->medge;
- MEdge *subdiv_edge = &subdiv_medge[subdiv_edge_index];
- const MEdge *coarse_edge = NULL;
- if (coarse_edge_index != ORIGINDEX_NONE) {
- const Mesh *coarse_mesh = ctx->coarse_mesh;
- const MEdge *coarse_medge = coarse_mesh->medge;
- coarse_edge = &coarse_medge[coarse_edge_index];
- }
- subdiv_copy_edge_data(ctx, subdiv_edge, coarse_edge);
- subdiv_edge->v1 = subdiv_v1;
- subdiv_edge->v2 = subdiv_v2;
+ SubdivMeshContext *ctx = foreach_context->user_data;
+ Mesh *subdiv_mesh = ctx->subdiv_mesh;
+ MEdge *subdiv_medge = subdiv_mesh->medge;
+ MEdge *subdiv_edge = &subdiv_medge[subdiv_edge_index];
+ const MEdge *coarse_edge = NULL;
+ if (coarse_edge_index != ORIGINDEX_NONE) {
+ const Mesh *coarse_mesh = ctx->coarse_mesh;
+ const MEdge *coarse_medge = coarse_mesh->medge;
+ coarse_edge = &coarse_medge[coarse_edge_index];
+ }
+ subdiv_copy_edge_data(ctx, subdiv_edge, coarse_edge);
+ subdiv_edge->v1 = subdiv_v1;
+ subdiv_edge->v2 = subdiv_v2;
}
/* =============================================================================
* Loops creation/interpolation.
*/
-static void subdiv_interpolate_loop_data(
- const SubdivMeshContext *ctx,
- MLoop *subdiv_loop,
- const LoopsForInterpolation *loop_interpolation,
- const float u, const float v)
+static void subdiv_interpolate_loop_data(const SubdivMeshContext *ctx,
+ MLoop *subdiv_loop,
+ const LoopsForInterpolation *loop_interpolation,
+ const float u,
+ const float v)
{
- const int subdiv_loop_index = subdiv_loop - ctx->subdiv_mesh->mloop;
- const float weights[4] = {(1.0f - u) * (1.0f - v),
- u * (1.0f - v),
- u * v,
- (1.0f - u) * v};
- CustomData_interp(loop_interpolation->loop_data,
- &ctx->subdiv_mesh->ldata,
- loop_interpolation->loop_indices,
- weights, NULL,
- 4,
- subdiv_loop_index);
- /* TODO(sergey): Set ORIGINDEX. */
+ const int subdiv_loop_index = subdiv_loop - ctx->subdiv_mesh->mloop;
+ const float weights[4] = {(1.0f - u) * (1.0f - v), u * (1.0f - v), u * v, (1.0f - u) * v};
+ CustomData_interp(loop_interpolation->loop_data,
+ &ctx->subdiv_mesh->ldata,
+ loop_interpolation->loop_indices,
+ weights,
+ NULL,
+ 4,
+ subdiv_loop_index);
+ /* TODO(sergey): Set ORIGINDEX. */
}
static void subdiv_eval_uv_layer(SubdivMeshContext *ctx,
MLoop *subdiv_loop,
const int ptex_face_index,
- const float u, const float v)
+ const float u,
+ const float v)
{
- if (ctx->num_uv_layers == 0) {
- return;
- }
- Subdiv *subdiv = ctx->subdiv;
- const int mloop_index = subdiv_loop - ctx->subdiv_mesh->mloop;
- for (int layer_index = 0; layer_index < ctx->num_uv_layers; layer_index++) {
- MLoopUV *subdiv_loopuv = &ctx->uv_layers[layer_index][mloop_index];
- BKE_subdiv_eval_face_varying(subdiv,
- layer_index,
- ptex_face_index,
- u, v,
- subdiv_loopuv->uv);
- }
+ if (ctx->num_uv_layers == 0) {
+ return;
+ }
+ Subdiv *subdiv = ctx->subdiv;
+ const int mloop_index = subdiv_loop - ctx->subdiv_mesh->mloop;
+ for (int layer_index = 0; layer_index < ctx->num_uv_layers; layer_index++) {
+ MLoopUV *subdiv_loopuv = &ctx->uv_layers[layer_index][mloop_index];
+ BKE_subdiv_eval_face_varying(subdiv, layer_index, ptex_face_index, u, v, subdiv_loopuv->uv);
+ }
}
-static void subdiv_mesh_ensure_loop_interpolation(
- SubdivMeshContext *ctx,
- SubdivMeshTLS *tls,
- const MPoly *coarse_poly,
- const int coarse_corner)
+static void subdiv_mesh_ensure_loop_interpolation(SubdivMeshContext *ctx,
+ SubdivMeshTLS *tls,
+ const MPoly *coarse_poly,
+ const int coarse_corner)
{
- /* Check whether we've moved to another corner or polygon. */
- if (tls->loop_interpolation_initialized) {
- if (tls->loop_interpolation_coarse_poly != coarse_poly ||
- tls->loop_interpolation_coarse_corner != coarse_corner)
- {
- loop_interpolation_end(&tls->loop_interpolation);
- tls->loop_interpolation_initialized = false;
- }
- }
- /* Initialize the interpolation. */
- if (!tls->loop_interpolation_initialized) {
- loop_interpolation_init(ctx, &tls->loop_interpolation, coarse_poly);
- }
- /* Update it for a new corner if needed. */
- if (!tls->loop_interpolation_initialized ||
- tls->loop_interpolation_coarse_corner != coarse_corner)
- {
- loop_interpolation_from_corner(
- ctx, &tls->loop_interpolation, coarse_poly, coarse_corner);
- }
- /* Store settings used for the current state of interpolator. */
- tls->loop_interpolation_initialized = true;
- tls->loop_interpolation_coarse_poly = coarse_poly;
- tls->loop_interpolation_coarse_corner = coarse_corner;
+ /* Check whether we've moved to another corner or polygon. */
+ if (tls->loop_interpolation_initialized) {
+ if (tls->loop_interpolation_coarse_poly != coarse_poly ||
+ tls->loop_interpolation_coarse_corner != coarse_corner) {
+ loop_interpolation_end(&tls->loop_interpolation);
+ tls->loop_interpolation_initialized = false;
+ }
+ }
+ /* Initialize the interpolation. */
+ if (!tls->loop_interpolation_initialized) {
+ loop_interpolation_init(ctx, &tls->loop_interpolation, coarse_poly);
+ }
+ /* Update it for a new corner if needed. */
+ if (!tls->loop_interpolation_initialized ||
+ tls->loop_interpolation_coarse_corner != coarse_corner) {
+ loop_interpolation_from_corner(ctx, &tls->loop_interpolation, coarse_poly, coarse_corner);
+ }
+ /* Store settings used for the current state of interpolator. */
+ tls->loop_interpolation_initialized = true;
+ tls->loop_interpolation_coarse_poly = coarse_poly;
+ tls->loop_interpolation_coarse_corner = coarse_corner;
}
-static void subdiv_mesh_loop(
- const SubdivForeachContext *foreach_context,
- void *tls_v,
- const int ptex_face_index,
- const float u, const float v,
- const int UNUSED(coarse_loop_index),
- const int coarse_poly_index,
- const int coarse_corner,
- const int subdiv_loop_index,
- const int subdiv_vertex_index, const int subdiv_edge_index)
+static void subdiv_mesh_loop(const SubdivForeachContext *foreach_context,
+ void *tls_v,
+ const int ptex_face_index,
+ const float u,
+ const float v,
+ const int UNUSED(coarse_loop_index),
+ const int coarse_poly_index,
+ const int coarse_corner,
+ const int subdiv_loop_index,
+ const int subdiv_vertex_index,
+ const int subdiv_edge_index)
{
- SubdivMeshContext *ctx = foreach_context->user_data;
- SubdivMeshTLS *tls = tls_v;
- const Mesh *coarse_mesh = ctx->coarse_mesh;
- const MPoly *coarse_mpoly = coarse_mesh->mpoly;
- const MPoly *coarse_poly = &coarse_mpoly[coarse_poly_index];
- Mesh *subdiv_mesh = ctx->subdiv_mesh;
- MLoop *subdiv_mloop = subdiv_mesh->mloop;
- MLoop *subdiv_loop = &subdiv_mloop[subdiv_loop_index];
- subdiv_mesh_ensure_loop_interpolation(
- ctx, tls, coarse_poly, coarse_corner);
- subdiv_interpolate_loop_data(
- ctx, subdiv_loop, &tls->loop_interpolation, u, v);
- subdiv_eval_uv_layer(ctx, subdiv_loop, ptex_face_index, u, v);
- subdiv_loop->v = subdiv_vertex_index;
- subdiv_loop->e = subdiv_edge_index;
+ SubdivMeshContext *ctx = foreach_context->user_data;
+ SubdivMeshTLS *tls = tls_v;
+ const Mesh *coarse_mesh = ctx->coarse_mesh;
+ const MPoly *coarse_mpoly = coarse_mesh->mpoly;
+ const MPoly *coarse_poly = &coarse_mpoly[coarse_poly_index];
+ Mesh *subdiv_mesh = ctx->subdiv_mesh;
+ MLoop *subdiv_mloop = subdiv_mesh->mloop;
+ MLoop *subdiv_loop = &subdiv_mloop[subdiv_loop_index];
+ subdiv_mesh_ensure_loop_interpolation(ctx, tls, coarse_poly, coarse_corner);
+ subdiv_interpolate_loop_data(ctx, subdiv_loop, &tls->loop_interpolation, u, v);
+ subdiv_eval_uv_layer(ctx, subdiv_loop, ptex_face_index, u, v);
+ subdiv_loop->v = subdiv_vertex_index;
+ subdiv_loop->e = subdiv_edge_index;
}
/* =============================================================================
@@ -967,53 +890,49 @@ static void subdiv_copy_poly_data(const SubdivMeshContext *ctx,
MPoly *subdiv_poly,
const MPoly *coarse_poly)
{
- const int coarse_poly_index = coarse_poly - ctx->coarse_mesh->mpoly;
- const int subdiv_poly_index = subdiv_poly - ctx->subdiv_mesh->mpoly;
- CustomData_copy_data(&ctx->coarse_mesh->pdata,
- &ctx->subdiv_mesh->pdata,
- coarse_poly_index,
- subdiv_poly_index,
- 1);
+ const int coarse_poly_index = coarse_poly - ctx->coarse_mesh->mpoly;
+ const int subdiv_poly_index = subdiv_poly - ctx->subdiv_mesh->mpoly;
+ CustomData_copy_data(
+ &ctx->coarse_mesh->pdata, &ctx->subdiv_mesh->pdata, coarse_poly_index, subdiv_poly_index, 1);
}
-static void subdiv_mesh_poly(
- const SubdivForeachContext *foreach_context,
- void *UNUSED(tls),
- const int coarse_poly_index,
- const int subdiv_poly_index,
- const int start_loop_index, const int num_loops)
+static void subdiv_mesh_poly(const SubdivForeachContext *foreach_context,
+ void *UNUSED(tls),
+ const int coarse_poly_index,
+ const int subdiv_poly_index,
+ const int start_loop_index,
+ const int num_loops)
{
- BLI_assert(coarse_poly_index != ORIGINDEX_NONE);
- SubdivMeshContext *ctx = foreach_context->user_data;
- const Mesh *coarse_mesh = ctx->coarse_mesh;
- const MPoly *coarse_mpoly = coarse_mesh->mpoly;
- const MPoly *coarse_poly = &coarse_mpoly[coarse_poly_index];
- Mesh *subdiv_mesh = ctx->subdiv_mesh;
- MPoly *subdiv_mpoly = subdiv_mesh->mpoly;
- MPoly *subdiv_poly = &subdiv_mpoly[subdiv_poly_index];
- subdiv_copy_poly_data(ctx, subdiv_poly, coarse_poly);
- subdiv_poly->loopstart = start_loop_index;
- subdiv_poly->totloop = num_loops;
+ BLI_assert(coarse_poly_index != ORIGINDEX_NONE);
+ SubdivMeshContext *ctx = foreach_context->user_data;
+ const Mesh *coarse_mesh = ctx->coarse_mesh;
+ const MPoly *coarse_mpoly = coarse_mesh->mpoly;
+ const MPoly *coarse_poly = &coarse_mpoly[coarse_poly_index];
+ Mesh *subdiv_mesh = ctx->subdiv_mesh;
+ MPoly *subdiv_mpoly = subdiv_mesh->mpoly;
+ MPoly *subdiv_poly = &subdiv_mpoly[subdiv_poly_index];
+ subdiv_copy_poly_data(ctx, subdiv_poly, coarse_poly);
+ subdiv_poly->loopstart = start_loop_index;
+ subdiv_poly->totloop = num_loops;
}
/* =============================================================================
* Loose elements subdivision process.
*/
-static void subdiv_mesh_vertex_loose(
- const SubdivForeachContext *foreach_context,
- void *UNUSED(tls),
- const int coarse_vertex_index,
- const int subdiv_vertex_index)
+static void subdiv_mesh_vertex_loose(const SubdivForeachContext *foreach_context,
+ void *UNUSED(tls),
+ const int coarse_vertex_index,
+ const int subdiv_vertex_index)
{
- SubdivMeshContext *ctx = foreach_context->user_data;
- const Mesh *coarse_mesh = ctx->coarse_mesh;
- const MVert *coarse_mvert = coarse_mesh->mvert;
- const MVert *coarse_vertex = &coarse_mvert[coarse_vertex_index];
- Mesh *subdiv_mesh = ctx->subdiv_mesh;
- MVert *subdiv_mvert = subdiv_mesh->mvert;
- MVert *subdiv_vertex = &subdiv_mvert[subdiv_vertex_index];
- subdiv_vertex_data_copy(ctx, coarse_vertex, subdiv_vertex);
+ SubdivMeshContext *ctx = foreach_context->user_data;
+ const Mesh *coarse_mesh = ctx->coarse_mesh;
+ const MVert *coarse_mvert = coarse_mesh->mvert;
+ const MVert *coarse_vertex = &coarse_mvert[coarse_vertex_index];
+ Mesh *subdiv_mesh = ctx->subdiv_mesh;
+ MVert *subdiv_mvert = subdiv_mesh->mvert;
+ MVert *subdiv_vertex = &subdiv_mvert[subdiv_vertex_index];
+ subdiv_vertex_data_copy(ctx, coarse_vertex, subdiv_vertex);
}
/* Get neighbor edges of the given one.
@@ -1023,154 +942,140 @@ static void find_edge_neighbors(const SubdivMeshContext *ctx,
const MEdge *edge,
const MEdge *neighbors[2])
{
- const Mesh *coarse_mesh = ctx->coarse_mesh;
- const MEdge *coarse_medge = coarse_mesh->medge;
- neighbors[0] = NULL;
- neighbors[1] = NULL;
- int neighbor_counters[2] = {0, 0};
- for (int edge_index = 0; edge_index < coarse_mesh->totedge; edge_index++) {
- const MEdge *current_edge = &coarse_medge[edge_index];
- if (current_edge == edge) {
- continue;
- }
- if (ELEM(edge->v1, current_edge->v1, current_edge->v2)) {
- neighbors[0] = current_edge;
- ++neighbor_counters[0];
- }
- if (ELEM(edge->v2, current_edge->v1, current_edge->v2)) {
- neighbors[1] = current_edge;
- ++neighbor_counters[1];
- }
- }
- /* Vertices which has more than one neighbor are considered infinitely
- * sharp. This is also how topology factory treats vertices of a surface
- * which are adjacent to a loose edge. */
- if (neighbor_counters[0] > 1) {
- neighbors[0] = NULL;
- }
- if (neighbor_counters[1] > 1) {
- neighbors[1] = NULL;
- }
+ const Mesh *coarse_mesh = ctx->coarse_mesh;
+ const MEdge *coarse_medge = coarse_mesh->medge;
+ neighbors[0] = NULL;
+ neighbors[1] = NULL;
+ int neighbor_counters[2] = {0, 0};
+ for (int edge_index = 0; edge_index < coarse_mesh->totedge; edge_index++) {
+ const MEdge *current_edge = &coarse_medge[edge_index];
+ if (current_edge == edge) {
+ continue;
+ }
+ if (ELEM(edge->v1, current_edge->v1, current_edge->v2)) {
+ neighbors[0] = current_edge;
+ ++neighbor_counters[0];
+ }
+ if (ELEM(edge->v2, current_edge->v1, current_edge->v2)) {
+ neighbors[1] = current_edge;
+ ++neighbor_counters[1];
+ }
+ }
+ /* Vertices which has more than one neighbor are considered infinitely
+ * sharp. This is also how topology factory treats vertices of a surface
+ * which are adjacent to a loose edge. */
+ if (neighbor_counters[0] > 1) {
+ neighbors[0] = NULL;
+ }
+ if (neighbor_counters[1] > 1) {
+ neighbors[1] = NULL;
+ }
}
-static void points_for_loose_edges_interpolation_get(
- SubdivMeshContext *ctx,
- const MEdge *coarse_edge,
- const MEdge *neighbors[2],
- float points_r[4][3])
+static void points_for_loose_edges_interpolation_get(SubdivMeshContext *ctx,
+ const MEdge *coarse_edge,
+ const MEdge *neighbors[2],
+ float points_r[4][3])
{
- const Mesh *coarse_mesh = ctx->coarse_mesh;
- const MVert *coarse_mvert = coarse_mesh->mvert;
- /* Middle points corresponds to the edge. */
- copy_v3_v3(points_r[1], coarse_mvert[coarse_edge->v1].co);
- copy_v3_v3(points_r[2], coarse_mvert[coarse_edge->v2].co);
- /* Start point, duplicate from edge start if no neighbor. */
- if (neighbors[0] != NULL) {
- if (neighbors[0]->v1 == coarse_edge->v1) {
- copy_v3_v3(points_r[0], coarse_mvert[neighbors[0]->v2].co);
- }
- else {
- copy_v3_v3(points_r[0], coarse_mvert[neighbors[0]->v1].co);
- }
- }
- else {
- sub_v3_v3v3(points_r[0], points_r[1], points_r[2]);
- add_v3_v3(points_r[0], points_r[1]);
- }
- /* End point, duplicate from edge end if no neighbor. */
- if (neighbors[1] != NULL) {
- if (neighbors[1]->v1 == coarse_edge->v2) {
- copy_v3_v3(points_r[3], coarse_mvert[neighbors[1]->v2].co);
- }
- else {
- copy_v3_v3(points_r[3], coarse_mvert[neighbors[1]->v1].co);
- }
- }
- else {
- sub_v3_v3v3(points_r[3], points_r[2], points_r[1]);
- add_v3_v3(points_r[3], points_r[2]);
- }
+ const Mesh *coarse_mesh = ctx->coarse_mesh;
+ const MVert *coarse_mvert = coarse_mesh->mvert;
+ /* Middle points corresponds to the edge. */
+ copy_v3_v3(points_r[1], coarse_mvert[coarse_edge->v1].co);
+ copy_v3_v3(points_r[2], coarse_mvert[coarse_edge->v2].co);
+ /* Start point, duplicate from edge start if no neighbor. */
+ if (neighbors[0] != NULL) {
+ if (neighbors[0]->v1 == coarse_edge->v1) {
+ copy_v3_v3(points_r[0], coarse_mvert[neighbors[0]->v2].co);
+ }
+ else {
+ copy_v3_v3(points_r[0], coarse_mvert[neighbors[0]->v1].co);
+ }
+ }
+ else {
+ sub_v3_v3v3(points_r[0], points_r[1], points_r[2]);
+ add_v3_v3(points_r[0], points_r[1]);
+ }
+ /* End point, duplicate from edge end if no neighbor. */
+ if (neighbors[1] != NULL) {
+ if (neighbors[1]->v1 == coarse_edge->v2) {
+ copy_v3_v3(points_r[3], coarse_mvert[neighbors[1]->v2].co);
+ }
+ else {
+ copy_v3_v3(points_r[3], coarse_mvert[neighbors[1]->v1].co);
+ }
+ }
+ else {
+ sub_v3_v3v3(points_r[3], points_r[2], points_r[1]);
+ add_v3_v3(points_r[3], points_r[2]);
+ }
}
-static void subdiv_mesh_vertex_of_loose_edge_interpolate(
- SubdivMeshContext *ctx,
- const MEdge *coarse_edge,
- const float u,
- const int subdiv_vertex_index)
+static void subdiv_mesh_vertex_of_loose_edge_interpolate(SubdivMeshContext *ctx,
+ const MEdge *coarse_edge,
+ const float u,
+ const int subdiv_vertex_index)
{
- const Mesh *coarse_mesh = ctx->coarse_mesh;
- Mesh *subdiv_mesh = ctx->subdiv_mesh;
- if (u == 0.0f) {
- CustomData_copy_data(&coarse_mesh->vdata,
- &subdiv_mesh->vdata,
- coarse_edge->v1,
- subdiv_vertex_index,
- 1);
- }
- else if (u == 1.0f) {
- CustomData_copy_data(&coarse_mesh->vdata,
- &subdiv_mesh->vdata,
- coarse_edge->v2,
- subdiv_vertex_index,
- 1);
- }
- else {
- BLI_assert(u > 0.0f);
- BLI_assert(u < 1.0f);
- const float interpolation_weights[2] = {1.0f - u, u};
- const int coarse_vertex_indices[2] = {coarse_edge->v1, coarse_edge->v2};
- CustomData_interp(&coarse_mesh->vdata,
- &subdiv_mesh->vdata,
- coarse_vertex_indices,
- interpolation_weights, NULL,
- 2, subdiv_vertex_index);
- if (ctx->vert_origindex != NULL) {
- ctx->vert_origindex[subdiv_vertex_index] = ORIGINDEX_NONE;
- }
- }
+ const Mesh *coarse_mesh = ctx->coarse_mesh;
+ Mesh *subdiv_mesh = ctx->subdiv_mesh;
+ if (u == 0.0f) {
+ CustomData_copy_data(
+ &coarse_mesh->vdata, &subdiv_mesh->vdata, coarse_edge->v1, subdiv_vertex_index, 1);
+ }
+ else if (u == 1.0f) {
+ CustomData_copy_data(
+ &coarse_mesh->vdata, &subdiv_mesh->vdata, coarse_edge->v2, subdiv_vertex_index, 1);
+ }
+ else {
+ BLI_assert(u > 0.0f);
+ BLI_assert(u < 1.0f);
+ const float interpolation_weights[2] = {1.0f - u, u};
+ const int coarse_vertex_indices[2] = {coarse_edge->v1, coarse_edge->v2};
+ CustomData_interp(&coarse_mesh->vdata,
+ &subdiv_mesh->vdata,
+ coarse_vertex_indices,
+ interpolation_weights,
+ NULL,
+ 2,
+ subdiv_vertex_index);
+ if (ctx->vert_origindex != NULL) {
+ ctx->vert_origindex[subdiv_vertex_index] = ORIGINDEX_NONE;
+ }
+ }
}
-static void subdiv_mesh_vertex_of_loose_edge(
- const struct SubdivForeachContext *foreach_context,
- void *UNUSED(tls),
- const int coarse_edge_index,
- const float u,
- const int subdiv_vertex_index)
+static void subdiv_mesh_vertex_of_loose_edge(const struct SubdivForeachContext *foreach_context,
+ void *UNUSED(tls),
+ const int coarse_edge_index,
+ const float u,
+ const int subdiv_vertex_index)
{
- SubdivMeshContext *ctx = foreach_context->user_data;
- const Mesh *coarse_mesh = ctx->coarse_mesh;
- const MEdge *coarse_edge = &coarse_mesh->medge[coarse_edge_index];
- Mesh *subdiv_mesh = ctx->subdiv_mesh;
- MVert *subdiv_mvert = subdiv_mesh->mvert;
- /* Find neighbors of the current loose edge. */
- const MEdge *neighbors[2];
- find_edge_neighbors(ctx, coarse_edge, neighbors);
- /* Get points for b-spline interpolation. */
- float points[4][3];
- points_for_loose_edges_interpolation_get(
- ctx, coarse_edge, neighbors, points);
- /* Perform interpolation. */
- float weights[4];
- key_curve_position_weights(u, weights, KEY_BSPLINE);
- /* Interpolate custom data. */
- subdiv_mesh_vertex_of_loose_edge_interpolate(
- ctx, coarse_edge, u, subdiv_vertex_index);
- /* Initialize */
- MVert *subdiv_vertex = &subdiv_mvert[subdiv_vertex_index];
- interp_v3_v3v3v3v3(subdiv_vertex->co,
- points[0],
- points[1],
- points[2],
- points[3],
- weights);
- /* Reset flags and such. */
- subdiv_vertex->flag = 0;
- /* TODO(sergey): This matches old behavior, but we can as well interpolate
- * it. Maybe even using vertex varying attributes. */
- subdiv_vertex->bweight = 0.0f;
- /* Reset normal, initialize it in a similar way as edit mode does for a
- * vertices adjacent to a loose edges. */
- normal_float_to_short_v3(subdiv_vertex->no, subdiv_vertex->co);
+ SubdivMeshContext *ctx = foreach_context->user_data;
+ const Mesh *coarse_mesh = ctx->coarse_mesh;
+ const MEdge *coarse_edge = &coarse_mesh->medge[coarse_edge_index];
+ Mesh *subdiv_mesh = ctx->subdiv_mesh;
+ MVert *subdiv_mvert = subdiv_mesh->mvert;
+ /* Find neighbors of the current loose edge. */
+ const MEdge *neighbors[2];
+ find_edge_neighbors(ctx, coarse_edge, neighbors);
+ /* Get points for b-spline interpolation. */
+ float points[4][3];
+ points_for_loose_edges_interpolation_get(ctx, coarse_edge, neighbors, points);
+ /* Perform interpolation. */
+ float weights[4];
+ key_curve_position_weights(u, weights, KEY_BSPLINE);
+ /* Interpolate custom data. */
+ subdiv_mesh_vertex_of_loose_edge_interpolate(ctx, coarse_edge, u, subdiv_vertex_index);
+ /* Initialize */
+ MVert *subdiv_vertex = &subdiv_mvert[subdiv_vertex_index];
+ interp_v3_v3v3v3v3(subdiv_vertex->co, points[0], points[1], points[2], points[3], weights);
+ /* Reset flags and such. */
+ subdiv_vertex->flag = 0;
+ /* TODO(sergey): This matches old behavior, but we can as well interpolate
+ * it. Maybe even using vertex varying attributes. */
+ subdiv_vertex->bweight = 0.0f;
+ /* Reset normal, initialize it in a similar way as edit mode does for a
+ * vertices adjacent to a loose edges. */
+ normal_float_to_short_v3(subdiv_vertex->no, subdiv_vertex->co);
}
/* =============================================================================
@@ -1180,82 +1085,76 @@ static void subdiv_mesh_vertex_of_loose_edge(
static void setup_foreach_callbacks(const SubdivMeshContext *subdiv_context,
SubdivForeachContext *foreach_context)
{
- memset(foreach_context, 0, sizeof(*foreach_context));
- /* General information. */
- foreach_context->topology_info = subdiv_mesh_topology_info;
- /* Every boundary geometry. Used for dispalcement and normals averaging. */
- if (subdiv_context->can_evaluate_normals ||
- subdiv_context->have_displacement)
- {
- foreach_context->vertex_every_corner = subdiv_mesh_vertex_every_corner;
- foreach_context->vertex_every_edge = subdiv_mesh_vertex_every_edge;
- }
- else {
- foreach_context->vertex_every_corner = NULL;
- foreach_context->vertex_every_edge = NULL;
- }
- foreach_context->vertex_corner = subdiv_mesh_vertex_corner;
- foreach_context->vertex_edge = subdiv_mesh_vertex_edge;
- foreach_context->vertex_inner = subdiv_mesh_vertex_inner;
- foreach_context->edge = subdiv_mesh_edge;
- foreach_context->loop = subdiv_mesh_loop;
- foreach_context->poly = subdiv_mesh_poly;
- foreach_context->vertex_loose = subdiv_mesh_vertex_loose;
- foreach_context->vertex_of_loose_edge = subdiv_mesh_vertex_of_loose_edge;
- foreach_context->user_data_tls_free = subdiv_mesh_tls_free;
+ memset(foreach_context, 0, sizeof(*foreach_context));
+ /* General information. */
+ foreach_context->topology_info = subdiv_mesh_topology_info;
+ /* Every boundary geometry. Used for dispalcement and normals averaging. */
+ if (subdiv_context->can_evaluate_normals || subdiv_context->have_displacement) {
+ foreach_context->vertex_every_corner = subdiv_mesh_vertex_every_corner;
+ foreach_context->vertex_every_edge = subdiv_mesh_vertex_every_edge;
+ }
+ else {
+ foreach_context->vertex_every_corner = NULL;
+ foreach_context->vertex_every_edge = NULL;
+ }
+ foreach_context->vertex_corner = subdiv_mesh_vertex_corner;
+ foreach_context->vertex_edge = subdiv_mesh_vertex_edge;
+ foreach_context->vertex_inner = subdiv_mesh_vertex_inner;
+ foreach_context->edge = subdiv_mesh_edge;
+ foreach_context->loop = subdiv_mesh_loop;
+ foreach_context->poly = subdiv_mesh_poly;
+ foreach_context->vertex_loose = subdiv_mesh_vertex_loose;
+ foreach_context->vertex_of_loose_edge = subdiv_mesh_vertex_of_loose_edge;
+ foreach_context->user_data_tls_free = subdiv_mesh_tls_free;
}
/* =============================================================================
* Public entry point.
*/
-Mesh *BKE_subdiv_to_mesh(
- Subdiv *subdiv,
- const SubdivToMeshSettings *settings,
- const Mesh *coarse_mesh)
+Mesh *BKE_subdiv_to_mesh(Subdiv *subdiv,
+ const SubdivToMeshSettings *settings,
+ const Mesh *coarse_mesh)
{
- BKE_subdiv_stats_begin(&subdiv->stats, SUBDIV_STATS_SUBDIV_TO_MESH);
- /* Make sure evaluator is up to date with possible new topology, and that
- * is is refined for the new positions of coarse vertices.
- */
- if (!BKE_subdiv_eval_update_from_mesh(subdiv, coarse_mesh)) {
- /* This could happen in two situations:
- * - OpenSubdiv is disabled.
- * - Something totally bad happened, and OpenSubdiv rejected our
- * topology.
- * In either way, we can't safely continue. */
- if (coarse_mesh->totpoly) {
- BKE_subdiv_stats_end(&subdiv->stats, SUBDIV_STATS_SUBDIV_TO_MESH);
- return NULL;
- }
- }
- /* Initialize subdivion mesh creation context/ */
- SubdivMeshContext subdiv_context = {0};
- subdiv_context.settings = settings;
- subdiv_context.coarse_mesh = coarse_mesh;
- subdiv_context.subdiv = subdiv;
- subdiv_context.have_displacement =
- (subdiv->displacement_evaluator != NULL);
- subdiv_context.can_evaluate_normals = !subdiv_context.have_displacement;
- /* Multi-threaded traversal/evaluation. */
- BKE_subdiv_stats_begin(&subdiv->stats,
- SUBDIV_STATS_SUBDIV_TO_MESH_GEOMETRY);
- SubdivForeachContext foreach_context;
- setup_foreach_callbacks(&subdiv_context, &foreach_context);
- SubdivMeshTLS tls = {0};
- foreach_context.user_data = &subdiv_context;
- foreach_context.user_data_tls_size = sizeof(SubdivMeshTLS);
- foreach_context.user_data_tls = &tls;
- BKE_subdiv_foreach_subdiv_geometry(
- subdiv, &foreach_context, settings, coarse_mesh);
- BKE_subdiv_stats_end(&subdiv->stats, SUBDIV_STATS_SUBDIV_TO_MESH_GEOMETRY);
- Mesh *result = subdiv_context.subdiv_mesh;
- // BKE_mesh_validate(result, true, true);
- BKE_subdiv_stats_end(&subdiv->stats, SUBDIV_STATS_SUBDIV_TO_MESH);
- if (!subdiv_context.can_evaluate_normals) {
- result->runtime.cd_dirty_vert |= CD_MASK_NORMAL;
- }
- /* Free used memoty. */
- subdiv_mesh_context_free(&subdiv_context);
- return result;
+ BKE_subdiv_stats_begin(&subdiv->stats, SUBDIV_STATS_SUBDIV_TO_MESH);
+ /* Make sure evaluator is up to date with possible new topology, and that
+ * is is refined for the new positions of coarse vertices.
+ */
+ if (!BKE_subdiv_eval_update_from_mesh(subdiv, coarse_mesh)) {
+ /* This could happen in two situations:
+ * - OpenSubdiv is disabled.
+ * - Something totally bad happened, and OpenSubdiv rejected our
+ * topology.
+ * In either way, we can't safely continue. */
+ if (coarse_mesh->totpoly) {
+ BKE_subdiv_stats_end(&subdiv->stats, SUBDIV_STATS_SUBDIV_TO_MESH);
+ return NULL;
+ }
+ }
+ /* Initialize subdivion mesh creation context/ */
+ SubdivMeshContext subdiv_context = {0};
+ subdiv_context.settings = settings;
+ subdiv_context.coarse_mesh = coarse_mesh;
+ subdiv_context.subdiv = subdiv;
+ subdiv_context.have_displacement = (subdiv->displacement_evaluator != NULL);
+ subdiv_context.can_evaluate_normals = !subdiv_context.have_displacement;
+ /* Multi-threaded traversal/evaluation. */
+ BKE_subdiv_stats_begin(&subdiv->stats, SUBDIV_STATS_SUBDIV_TO_MESH_GEOMETRY);
+ SubdivForeachContext foreach_context;
+ setup_foreach_callbacks(&subdiv_context, &foreach_context);
+ SubdivMeshTLS tls = {0};
+ foreach_context.user_data = &subdiv_context;
+ foreach_context.user_data_tls_size = sizeof(SubdivMeshTLS);
+ foreach_context.user_data_tls = &tls;
+ BKE_subdiv_foreach_subdiv_geometry(subdiv, &foreach_context, settings, coarse_mesh);
+ BKE_subdiv_stats_end(&subdiv->stats, SUBDIV_STATS_SUBDIV_TO_MESH_GEOMETRY);
+ Mesh *result = subdiv_context.subdiv_mesh;
+ // BKE_mesh_validate(result, true, true);
+ BKE_subdiv_stats_end(&subdiv->stats, SUBDIV_STATS_SUBDIV_TO_MESH);
+ if (!subdiv_context.can_evaluate_normals) {
+ result->runtime.cd_dirty_vert |= CD_MASK_NORMAL;
+ }
+ /* Free used memoty. */
+ subdiv_mesh_context_free(&subdiv_context);
+ return result;
}