[Bf-blender-cvs] [76051848362] soc-2019-bevel-profiles: Working towards using the profile information in simple bevel cases, and started some faster (O(n) vs O(n^2)) sampling code for the profile paths. Adding lots of questions and TODOs...

Hans Goudey noreply at git.blender.org
Sat Jun 1 07:39:10 CEST 2019


Commit: 76051848362847ffabb5bddf858ad9c69f5481fc
Author: Hans Goudey
Date:   Fri May 31 21:39:21 2019 -0400
Branches: soc-2019-bevel-profiles
https://developer.blender.org/rB76051848362847ffabb5bddf858ad9c69f5481fc

Working towards using the profile information in simple bevel cases, and started some faster (O(n) vs O(n^2)) sampling code for the profile paths. Adding lots of questions and TODOs...

===================================================================

M	source/blender/blenkernel/intern/colortools.c
M	source/blender/bmesh/tools/bmesh_bevel.c
M	source/blender/makesdna/DNA_color_types.h

===================================================================

diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c
index 6889612e65d..5585bbdf3a2 100644
--- a/source/blender/blenkernel/intern/colortools.c
+++ b/source/blender/blenkernel/intern/colortools.c
@@ -904,7 +904,8 @@ void curvemapping_changed(CurveMapping *cumap, const bool rem_doubles)
     }
   }
 
-//  qsort(cmp, cuma->totpoint, sizeof(CurveMapPoint), sort_curvepoints);
+  /* HANS-TODO: Reenable this for other curves! */
+  /* qsort(cmp, cuma->totpoint, sizeof(CurveMapPoint), sort_curvepoints); */
 
   /* remove doubles, threshold set on 1% of default range */
   if (rem_doubles && cuma->totpoint > 2) {
@@ -1291,8 +1292,46 @@ void curvemap_path_evaluate(const struct CurveMap *cuma, float length_portion, f
   *y_out = lerp(cuma->curve[i].y, cuma->curve[i+1].y, lerp_factor);
 }
 
-static void curvemap_path_make_table(const struct CurveMap *cuma) {
+
+/* HANS-TODO: Fix this, it can't be the right method, because it doesn't generalize well to
+ * small distances between points. There could be a lot of points inside one segment length,
+ * but this code assumes that there's only 1. I need to think harder about what method to use here.
+ * But really it might not be worth pursuing this much because there might be a more general solution
+ * that includes curves and the small speedup it would give isn't a high priority right now */
+static void curvemap_path_make_table(struct CurveMap *cuma) {
   /* Fill table with values for the position of the graph at each of the segments */
+  float segment_length = cuma->total_length / cuma->nsegments;
+  float length_travelled = 0.0f;
+  float distance_to_next_point = curvemap_path_linear_distance_to_next_point(cuma, 0);
+  float distance_to_previous_point = 0.0f;
+  float f;
+  int i_point = 0;
+
+  cuma->x_segment_vals = MEM_callocN((size_t)cuma->nsegments * sizeof(float), "segment table x");
+  cuma->y_segment_vals = MEM_callocN((size_t)cuma->nsegments * sizeof(float), "segment table y"); /* HANS-TODO: Free these!! Where?? */
+
+  /* Travel along the path, recording locations of segments as we pass where they should be */
+  for (int i = 0; i < cuma->nsegments; i++) {
+    if (segment_length < distance_to_next_point) {
+      /* There is room for the next segment before the next point */
+      f = (distance_to_previous_point + segment_length) / (distance_to_previous_point + distance_to_next_point);
+      cuma->x_segment_vals[i] = lerp(cuma->curve[i_point].x, cuma->curve[i_point+1].x, f);
+      cuma->y_segment_vals[i] = lerp(cuma->curve[i_point].x, cuma->curve[i_point+1].x, f);
+      distance_to_next_point -= segment_length;
+      distance_to_previous_point += segment_length;
+    }
+    else {
+      /* We have to pass over a CurveMapPoint to get to the next segment */
+      float left_after_pass = segment_length - distance_to_next_point;
+      i_point++;
+      distance_to_previous_point = segment_length - distance_to_next_point;
+      distance_to_next_point = curvemap_path_linear_distance_to_next_point(cuma, i_point);
+      f = left_after_pass / (distance_to_previous_point + distance_to_next_point);
+      cuma->x_segment_vals[i] = lerp(cuma->curve[i_point].x, cuma->curve[i_point+1].x, f);
+      cuma->y_segment_vals[i] = lerp(cuma->curve[i_point].x, cuma->curve[i_point+1].x, f);
+    }
+    length_travelled += segment_length;
+  }
 
 }
 
diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c
index 150732e088c..cc35bf6e31f 100644
--- a/source/blender/bmesh/tools/bmesh_bevel.c
+++ b/source/blender/bmesh/tools/bmesh_bevel.c
@@ -56,10 +56,9 @@
 #define BEVEL_MAX_AUTO_ADJUST_PCT 300.0f
 #define BEVEL_MATCH_SPEC_WEIGHT 0.2
 
-
+#define DEBUG_CUSTOM_PROFILE_SAMPLE 0
 #define DEBUG_CUSTOM_PROFILE 1
 
-
 /* happens far too often, uncomment for development */
 // #define BEVEL_ASSERT_PROJECT
 
@@ -1648,11 +1647,104 @@ static void get_profile_point(BevelParams *bp, const Profile *pro, int i, int n,
 }
 
 
-static void calculate_custom_profile(BevelParams *bp, BoundVert *bndv)
-{
+/* This does the same thing as the regular calculate profile function, but it uses the
+ * custom profile points instead of the normal ones. Eventually, when the custom and normal
+ * profile spacings are merged, this function will be redundant, but for now, I will call this
+ * function in certain cases where I am working on the custom profile
+ * HANS-TODO: Get rid of this function when all custom profile cases are completed */
+static void calculate_profile_custom(BevelParams *bp, BoundVert *bndv) {
+  int i, k, ns;
+  const double *xvals, *yvals;
+  float co[3], co2[3], p[3], m[4][4];
+  float *prof_co, *prof_co_k;
+  float r;
+  bool need_2, map_ok;
+  Profile *pro = &bndv->profile;
 
-}
+  /* HANS-TODO: If the goal of this function is to translate the 2D coords of the profile spacing
+   * into 3D for the actual placement of the profile verts, I'm not sure that this function will
+   * actually have to be changed, because that process should be the same for different vert locations.
+   * So figure out if that's what this function does. */
 
+  /* This function should do the exact same thing for the custom profiles, so it shouldn't need to be changed */
+
+  if (bp->seg == 1) {
+    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));
+    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));
+    }
+    else {
+      pro->prof_co_2 = pro->prof_co;
+    }
+  }
+  r = pro->super_r;
+  if (r == PRO_LINE_R) {
+    map_ok = false;
+  }
+  else {
+    map_ok = make_unit_square_map(pro->coa, pro->midco, pro->cob, m);
+  }
+  /* 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 = bp->pro_spacing.xvals_custom;
+      yvals = bp->pro_spacing.yvals_custom;
+      prof_co = pro->prof_co;
+    }
+    else {
+      if (!need_2) {
+        break; /* shares coords with pro->prof_co */
+      }
+      ns = bp->pro_spacing.seg_2;
+      xvals = bp->pro_spacing.xvals_2_custom;
+      yvals = bp->pro_spacing.yvals_2_custom;
+      prof_co = pro->prof_co_2;
+    }
+    /* HANS-TODO: Why this assert? */
+    BLI_assert((r == PRO_LINE_R || (xvals != NULL && yvals != NULL)) && prof_co != NULL);
+
+    /* Iterate over the vertices along the boundary arc */
+    for (k = 0; k <= ns; k++) {
+      if (k == 0) {
+        copy_v3_v3(co, pro->coa);
+      }
+      else if (k == ns) {
+        copy_v3_v3(co, pro->cob);
+      }
+      else {
+        if (map_ok) {
+          p[0] = (float)xvals[k];
+          p[1] = (float)yvals[k];
+          p[2] = 0.0f;
+          mul_v3_m4v3(co, m, p); /* HANS-QUESTION: What's the reason to have this and the final projection? */
+        }
+        else {
+          interp_v3_v3v3(co, pro->coa, pro->cob, (float)k / (float)ns);
+        }
+      }
+      /* project co onto final profile plane */
+      prof_co_k = prof_co + 3 * k; /* 3 times deeper because 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 build 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 actual coordinate values for bndv's profile.
  * This is only needed if bp->seg > 1.
@@ -1675,12 +1767,8 @@ static void calculate_profile(BevelParams *bp, BoundVert *bndv)
    * into 3D for the actual placement of the profile verts, I'm not sure that this function will
    * actually have to be changed, because that process should be the same for different vert locations.
    * So figure out if that's what this function does. */
-  /*
-  if (bp->use_custom_profile) {
-    calculate_custom_profile(bp, bndv);
-    return;
-  }
-  */
+
+  /* This function should do the exact same thing for the custom profiles, so it shouldn't need to be changed */
 
   if (bp->seg == 1) {
     return;
@@ -1688,10 +1776,10 @@ static void calculate_profile(BevelParams *bp, BoundVert *bndv)
 
   need_2 = bp->seg != bp->pro_spacing.seg_2;
   if (!pro->prof_co) {
-    pro->prof_co = (float *)BLI_memarena_alloc(bp->mem_arena, (bp->seg + 1) * 3 * sizeof(float));
+    pro->prof_co = (float *)BLI_memarena_alloc(bp->mem_arena, ((size_t)bp->seg + 1) * 3 * sizeof(float));
     if (need_2) {
       pro->prof_co_2 = (float *)BLI_memarena_alloc(
-          bp->mem_arena, (bp->pro_spacing.seg_2 + 1) * 3 * sizeof(float));
+          bp->mem_arena, ((size_t)bp->pro_spacing.seg_2 + 1) * 3 * sizeof(float));
     }
     else {
       pro->prof_co_2 = pro->prof_co;
@@ -1704,6 +1792,7 @@ static void calculate_profile(BevelParams *bp, BoundVert *bndv)
   else {
     map_ok = make_unit_square_map(pro->coa, pro->midco, pro->cob, m);
   }
+  /* 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;
@@ -1720,7 +1809,10 @@ static void calculate_profile(BevelParams *bp, BoundVert *bndv)
       yvals = bp->pro_spacing.yvals_2;
       prof_co = pro->prof_co_2;
     }
+    /* HANS-TODO: Why this assert? */
     BLI_assert((r == PRO_LINE_R || (xvals != NULL && yvals != NULL)) && prof_co != NULL);
+
+    /* Iterate over the vertices along the boundary arc */
     for (k = 0; k <= ns; k++) {
       if (k == 0) {
         copy_v3_v3(co, pro->coa);
@@ -1730,19 +1822,20 @@ static void calculate_profile(BevelParams *bp, BoundVert *bndv)
       }
       else {
         if (map_ok) {
-          p[0] = xvals[k];
-          p[1] = yvals[k];
+          p[0] = (float)xvals[k];
+          p[1] = (float)yvals[k];
           p[2] = 0.0f;
-          mul_v3_m4v3(co, m, p);
+          mul_v3_m4v3(co, m, p); /* HANS-QUESTION: What's the 

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list