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/bmesh/tools/bmesh_bevel.c')
-rw-r--r--source/blender/bmesh/tools/bmesh_bevel.c268
1 files changed, 142 insertions, 126 deletions
diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c
index 6c666183755..f263392bdd2 100644
--- a/source/blender/bmesh/tools/bmesh_bevel.c
+++ b/source/blender/bmesh/tools/bmesh_bevel.c
@@ -45,6 +45,11 @@
#include "./intern/bmesh_private.h"
+// #define BEVEL_DEBUG_TIME
+#ifdef BEVEL_DEBUG_TIME
+# include "PIL_time.h"
+#endif
+
#define BEVEL_EPSILON_D 1e-6
#define BEVEL_EPSILON 1e-6f
#define BEVEL_EPSILON_SQ 1e-12f
@@ -917,7 +922,7 @@ static void math_layer_info_init(BevelParams *bp, BMesh *bm)
* segment (and its continuation into vmesh) can usually arbitrarily be
* the previous face or the next face.
* Or, for the center polygon of a corner, all of the faces around
- * the vertex are possible choices.
+ * the vertex are possibleface_component choices.
* If we just choose randomly, the resulting UV maps or material
* assignment can look ugly/inconsistent.
* Allow for the case when arguments are null.
@@ -1891,6 +1896,57 @@ static void get_profile_point(BevelParams *bp, const Profile *pro, int i, int ns
}
/**
+ * Helper for #calculate_profile that builds the 3D locations for the segments
+ * and the higher power of 2 segments.
+ */
+static void calculate_profile_segments(const Profile *profile,
+ const float map[4][4],
+ const bool use_map,
+ const bool reversed,
+ const int ns,
+ const double *xvals,
+ const double *yvals,
+ float *r_prof_co)
+{
+ /* Iterate over the vertices along the boundary arc. */
+ for (int k = 0; k <= ns; k++) {
+ float co[3];
+ if (k == 0) {
+ copy_v3_v3(co, profile->start);
+ }
+ else if (k == ns) {
+ copy_v3_v3(co, profile->end);
+ }
+ else {
+ if (use_map) {
+ float p[3] = {reversed ? (float)yvals[ns - k] : (float)xvals[k],
+ reversed ? (float)xvals[ns - k] : (float)yvals[k],
+ 0.0f};
+ /* Do the 2D->3D transformation of the profile coordinates. */
+ mul_v3_m4v3(co, map, p);
+ }
+ else {
+ interp_v3_v3v3(co, profile->start, profile->end, (float)k / (float)ns);
+ }
+ }
+ /* Finish the 2D->3D transformation by projecting onto the final profile plane. */
+ float *prof_co_k = r_prof_co + 3 * k;
+ if (!is_zero_v3(profile->proj_dir)) {
+ float co2[3];
+ add_v3_v3v3(co2, co, profile->proj_dir);
+ /* pro->plane_co and pro->plane_no are filled in #set_profile_params. */
+ if (!isect_line_plane_v3(prof_co_k, co, co2, profile->plane_co, profile->plane_no)) {
+ /* Shouldn't happen. */
+ copy_v3_v3(prof_co_k, co);
+ }
+ }
+ else {
+ copy_v3_v3(prof_co_k, co);
+ }
+ }
+}
+
+/**
* Calculate the actual coordinate values for bndv's profile.
* This is only needed if bp->seg > 1.
* Allocate the space for them if that hasn't been done already.
@@ -1900,12 +1956,6 @@ static void get_profile_point(BevelParams *bp, const Profile *pro, int i, int ns
*/
static void calculate_profile(BevelParams *bp, BoundVert *bndv, bool reversed, bool miter)
{
- int i, k, ns;
- const double *xvals, *yvals;
- float co[3], co2[3], p[3], map[4][4], bottom_corner[3], top_corner[3];
- float *prof_co, *prof_co_k;
- float r;
- bool need_2, map_ok;
Profile *pro = &bndv->profile;
ProfileSpacing *pro_spacing = (miter) ? &bp->pro_spacing_miter : &bp->pro_spacing;
@@ -1913,89 +1963,51 @@ static void calculate_profile(BevelParams *bp, BoundVert *bndv, bool reversed, b
return;
}
- need_2 = bp->seg != bp->pro_spacing.seg_2;
- if (!pro->prof_co) {
- pro->prof_co = (float *)BLI_memarena_alloc(bp->mem_arena,
- ((size_t)bp->seg + 1) * 3 * sizeof(float));
+ bool need_2 = bp->seg != bp->pro_spacing.seg_2;
+ if (pro->prof_co == NULL) {
+ pro->prof_co = (float *)BLI_memarena_alloc(bp->mem_arena, sizeof(float) * 3 * (bp->seg + 1));
if (need_2) {
pro->prof_co_2 = (float *)BLI_memarena_alloc(
- bp->mem_arena, ((size_t)bp->pro_spacing.seg_2 + 1) * 3 * sizeof(float));
+ bp->mem_arena, sizeof(float) * 3 * (bp->pro_spacing.seg_2 + 1));
}
else {
pro->prof_co_2 = pro->prof_co;
}
}
- r = pro->super_r;
- if (bp->profile_type == BEVEL_PROFILE_SUPERELLIPSE && r == PRO_LINE_R) {
- map_ok = false;
+
+ bool use_map;
+ float map[4][4];
+ if (bp->profile_type == BEVEL_PROFILE_SUPERELLIPSE && pro->super_r == PRO_LINE_R) {
+ use_map = false;
}
else {
- map_ok = make_unit_square_map(pro->start, pro->middle, pro->end, map);
+ use_map = make_unit_square_map(pro->start, pro->middle, pro->end, map);
}
- if (bp->vmesh_method == BEVEL_VMESH_CUTOFF && map_ok) {
+ if (bp->vmesh_method == BEVEL_VMESH_CUTOFF && use_map) {
/* Calculate the "height" of the profile by putting the (0,0) and (1,1) corners of the
* un-transformed profile through the 2D->3D map and calculating the distance between them. */
- zero_v3(p);
- mul_v3_m4v3(bottom_corner, map, p);
- p[0] = 1.0f;
- p[1] = 1.0f;
- mul_v3_m4v3(top_corner, map, p);
+ float bottom_corner[3] = {0.0f, 0.0f, 0.0f};
+ mul_v3_m4v3(bottom_corner, map, bottom_corner);
+ float top_corner[3] = {1.0f, 1.0f, 0.0f};
+ mul_v3_m4v3(top_corner, map, top_corner);
+
pro->height = len_v3v3(bottom_corner, top_corner);
}
- /* The first iteration is the nseg case, the second is the seg_2 case (if it's needed) .*/
- for (i = 0; i < 2; i++) {
- if (i == 0) {
- ns = bp->seg;
- xvals = pro_spacing->xvals;
- yvals = pro_spacing->yvals;
- prof_co = pro->prof_co;
- }
- else {
- if (!need_2) {
- break; /* Shares coords with pro->prof_co. */
- }
- ns = bp->pro_spacing.seg_2;
- xvals = pro_spacing->xvals_2;
- yvals = pro_spacing->yvals_2;
- prof_co = pro->prof_co_2;
- }
-
- /* Iterate over the vertices along the boundary arc. */
- for (k = 0; k <= ns; k++) {
- if (k == 0) {
- copy_v3_v3(co, pro->start);
- }
- else if (k == ns) {
- copy_v3_v3(co, pro->end);
- }
- else {
- if (map_ok) {
- p[0] = reversed ? (float)yvals[ns - k] : (float)xvals[k];
- p[1] = reversed ? (float)xvals[ns - k] : (float)yvals[k];
- p[2] = 0.0f;
- /* Do the 2D->3D transformation of the profile coordinates. */
- mul_v3_m4v3(co, map, p);
- }
- else {
- interp_v3_v3v3(co, pro->start, pro->end, (float)k / (float)ns);
- }
- }
- /* Finish the 2D->3D transformation by projecting onto the final profile plane. */
- prof_co_k = prof_co + 3 * k; /* Each coord takes up 3 spaces. */
- if (!is_zero_v3(pro->proj_dir)) {
- add_v3_v3v3(co2, co, pro->proj_dir);
- /* pro->plane_co and pro->plane_no are filled in "set_profile_params". */
- if (!isect_line_plane_v3(prof_co_k, co, co2, pro->plane_co, pro->plane_no)) {
- /* Shouldn't happen. */
- copy_v3_v3(prof_co_k, co);
- }
- }
- else {
- copy_v3_v3(prof_co_k, co);
- }
- }
+ /* Calculate the 3D locations for the profile points */
+ calculate_profile_segments(
+ pro, map, use_map, reversed, bp->seg, pro_spacing->xvals, pro_spacing->yvals, pro->prof_co);
+ /* Also calcualte for the is the seg_2 case if it's needed .*/
+ if (need_2) {
+ calculate_profile_segments(pro,
+ map,
+ use_map,
+ reversed,
+ bp->pro_spacing.seg_2,
+ pro_spacing->xvals_2,
+ pro_spacing->yvals_2,
+ pro->prof_co_2);
}
}
@@ -7143,68 +7155,64 @@ static float find_profile_fullness(BevelParams *bp)
*/
static void set_profile_spacing(BevelParams *bp, ProfileSpacing *pro_spacing, bool custom)
{
- int seg, seg_2;
+ int seg = bp->seg;
- seg = bp->seg;
- seg_2 = power_of_2_max_i(bp->seg);
- if (seg > 1) {
- /* Sample the seg_2 segments used for subdividing the vertex meshes. */
- if (seg_2 == 2) {
- seg_2 = 4;
- }
- bp->pro_spacing.seg_2 = seg_2;
- if (seg_2 == seg) {
- pro_spacing->xvals_2 = pro_spacing->xvals;
- pro_spacing->yvals_2 = pro_spacing->yvals;
- }
- else {
- pro_spacing->xvals_2 = (double *)BLI_memarena_alloc(bp->mem_arena,
- (size_t)(seg_2 + 1) * sizeof(double));
- pro_spacing->yvals_2 = (double *)BLI_memarena_alloc(bp->mem_arena,
- (size_t)(seg_2 + 1) * sizeof(double));
- if (custom) {
- /* Make sure the curve profile widget's sample table is full of the seg_2 samples. */
- BKE_curveprofile_initialize((CurveProfile *)bp->custom_profile, (short)seg_2);
-
- /* Copy segment locations into the profile spacing struct. */
- for (int i = 0; i < seg_2 + 1; i++) {
- pro_spacing->xvals_2[i] = (double)bp->custom_profile->segments[i].y;
- pro_spacing->yvals_2[i] = (double)bp->custom_profile->segments[i].x;
- }
- }
- else {
- find_even_superellipse_chords(
- seg_2, bp->pro_super_r, pro_spacing->xvals_2, pro_spacing->yvals_2);
- }
- }
+ if (seg <= 1) {
+ /* Only 1 segment, we don't need any profile information. */
+ pro_spacing->xvals = NULL;
+ pro_spacing->yvals = NULL;
+ pro_spacing->xvals_2 = NULL;
+ pro_spacing->yvals_2 = NULL;
+ pro_spacing->seg_2 = 0;
+ return;
+ }
- /* Sample the input number of segments. */
- pro_spacing->xvals = (double *)BLI_memarena_alloc(bp->mem_arena,
- (size_t)(seg + 1) * sizeof(double));
- pro_spacing->yvals = (double *)BLI_memarena_alloc(bp->mem_arena,
- (size_t)(seg + 1) * sizeof(double));
+ int seg_2 = max_ii(power_of_2_max_i(bp->seg), 4);
+
+ /* Sample the seg_2 segments used during vertex mesh subdivision. */
+ bp->pro_spacing.seg_2 = seg_2;
+ if (seg_2 == seg) {
+ pro_spacing->xvals_2 = pro_spacing->xvals;
+ pro_spacing->yvals_2 = pro_spacing->yvals;
+ }
+ else {
+ pro_spacing->xvals_2 = (double *)BLI_memarena_alloc(bp->mem_arena,
+ sizeof(double) * (seg_2 + 1));
+ pro_spacing->yvals_2 = (double *)BLI_memarena_alloc(bp->mem_arena,
+ sizeof(double) * (seg_2 + 1));
if (custom) {
- /* Make sure the curve profile's sample table is full. */
- if (bp->custom_profile->segments_len != seg || !bp->custom_profile->segments) {
- BKE_curveprofile_initialize((CurveProfile *)bp->custom_profile, (short)seg);
- }
+ /* Make sure the curve profile widget's sample table is full of the seg_2 samples. */
+ BKE_curveprofile_init((CurveProfile *)bp->custom_profile, (short)seg_2);
/* Copy segment locations into the profile spacing struct. */
- for (int i = 0; i < seg + 1; i++) {
- pro_spacing->xvals[i] = (double)bp->custom_profile->segments[i].y;
- pro_spacing->yvals[i] = (double)bp->custom_profile->segments[i].x;
+ for (int i = 0; i < seg_2 + 1; i++) {
+ pro_spacing->xvals_2[i] = (double)bp->custom_profile->segments[i].y;
+ pro_spacing->yvals_2[i] = (double)bp->custom_profile->segments[i].x;
}
}
else {
- find_even_superellipse_chords(seg, bp->pro_super_r, pro_spacing->xvals, pro_spacing->yvals);
+ find_even_superellipse_chords(
+ seg_2, bp->pro_super_r, pro_spacing->xvals_2, pro_spacing->yvals_2);
}
}
- else { /* Only 1 segment, we don't need any profile information. */
- pro_spacing->xvals = NULL;
- pro_spacing->yvals = NULL;
- pro_spacing->xvals_2 = NULL;
- pro_spacing->yvals_2 = NULL;
- pro_spacing->seg_2 = 0;
+
+ /* Sample the input number of segments. */
+ pro_spacing->xvals = (double *)BLI_memarena_alloc(bp->mem_arena, sizeof(double) * (seg + 1));
+ pro_spacing->yvals = (double *)BLI_memarena_alloc(bp->mem_arena, sizeof(double) * (seg + 1));
+ if (custom) {
+ /* Make sure the curve profile's sample table is full. */
+ if (bp->custom_profile->segments_len != seg || !bp->custom_profile->segments) {
+ BKE_curveprofile_init((CurveProfile *)bp->custom_profile, (short)seg);
+ }
+
+ /* Copy segment locations into the profile spacing struct. */
+ for (int i = 0; i < seg + 1; i++) {
+ pro_spacing->xvals[i] = (double)bp->custom_profile->segments[i].y;
+ pro_spacing->yvals[i] = (double)bp->custom_profile->segments[i].x;
+ }
+ }
+ else {
+ find_even_superellipse_chords(seg, bp->pro_super_r, pro_spacing->xvals, pro_spacing->yvals);
}
}
@@ -7493,6 +7501,10 @@ void BM_mesh_bevel(BMesh *bm,
bp.custom_profile = custom_profile;
bp.vmesh_method = vmesh_method;
+#ifdef BEVEL_DEBUG_TIME
+ double start_time = PIL_check_seconds_timer();
+#endif
+
/* Disable the miters with the cutoff vertex mesh method, the combination isn't useful anyway. */
if (bp.vmesh_method == BEVEL_VMESH_CUTOFF) {
bp.miter_outer = BEVEL_MITER_SHARP;
@@ -7661,4 +7673,8 @@ void BM_mesh_bevel(BMesh *bm,
BLI_ghash_free(bp.face_hash, NULL, NULL);
BLI_memarena_free(bp.mem_arena);
}
+#ifdef BEVEL_DEBUG_TIME
+ double end_time = PIL_check_seconds_timer();
+ printf("BMESH BEVEL TIME = %.3f\n", end_time - start_time);
+#endif
}