[Bf-blender-cvs] [704d49ebd74] soc-2021-knife-tools: Knife: Better multi-object edit mode

Cian Jinks noreply at git.blender.org
Mon Sep 20 22:53:42 CEST 2021


Commit: 704d49ebd74bb0ae8f94827e8a4b939954e90ca1
Author: Cian Jinks
Date:   Mon Sep 20 21:40:47 2021 +0100
Branches: soc-2021-knife-tools
https://developer.blender.org/rB704d49ebd74bb0ae8f94827e8a4b939954e90ca1

Knife: Better multi-object edit mode

The knife tool can now make cuts in multi-object edit mode which cross over multiple objects and go from the geometry of one object to multiple others.

Previously, object switching functionality was implemented but this proved insufficient to achieve the functionality contained within this patch. Instead, the dependence on a singular Object and BMEditMesh stored in the KnifeTool_OpData struct needed to be entirely removed.

This has resulted in a lot of passing around of Object pointers which could potentially be simplified using a map of some kind in the future. For now it works well.

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

M	source/blender/editors/mesh/editmesh_knife.c

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

diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c
index 7081346de06..093d0d19ffa 100644
--- a/source/blender/editors/mesh/editmesh_knife.c
+++ b/source/blender/editors/mesh/editmesh_knife.c
@@ -116,6 +116,7 @@ typedef struct KnifeColors {
 /* Knifetool Operator. */
 typedef struct KnifeVert {
   Object *ob;
+  uint base_index;
   BMVert *v; /* Non-NULL if this is an original vert. */
   ListBase edges;
   ListBase faces;
@@ -133,7 +134,6 @@ typedef struct Ref {
 } Ref;
 
 typedef struct KnifeEdge {
-  Object *ob;
   KnifeVert *v1, *v2;
   BMFace *basef; /* Face to restrict face fill to. */
   ListBase faces;
@@ -157,6 +157,8 @@ typedef struct KnifeLineHit {
   KnifeEdge *kfe;
   KnifeVert *v;
   BMFace *f;
+  Object *ob;
+  uint base_index;
 } KnifeLineHit;
 
 typedef struct KnifePosData {
@@ -169,6 +171,8 @@ typedef struct KnifePosData {
   KnifeVert *vert;
   KnifeEdge *edge;
   BMFace *bmface;
+  Object *ob; /* Object of the vert, edge or bmface. */
+  uint base_index;
 
   /* When true, the cursor isn't over a face. */
   bool is_space;
@@ -213,13 +217,9 @@ typedef struct KnifeTool_OpData {
 
   Scene *scene;
 
-  Object *ob;
-  BMEditMesh *em;
-
   /* Used for swapping current object when in multi-object edit mode. */
   Base **bases;
   uint bases_len;
-  int base_index;
 
   MemArena *arena;
 
@@ -265,17 +265,6 @@ typedef struct KnifeTool_OpData {
 
   BLI_mempool *refs;
 
-  /**
-   * Use this instead of #Object.imat since it's calculated using #invert_m4_m4_safe_ortho
-   * to support objects with zero scale on a single axis.
-   */
-  float ob_imat[4][4];
-
-  float projmat[4][4];
-  float projmat_inv[4][4];
-  /* Vector along view z axis (object space, normalized). */
-  float proj_zaxis[3];
-
   KnifeColors colors;
 
   /* Run by the UI or not. */
@@ -377,45 +366,40 @@ enum {
 /** \name Drawing
  * \{ */
 
+#if 1
 static void knifetool_raycast_planes(const KnifeTool_OpData *kcd, float r_v1[3], float r_v2[3])
 {
   float planes[4][4];
-  planes_from_projmat(kcd->projmat, planes[2], planes[0], planes[1], planes[3], NULL, NULL);
-
-  float curr_os[3];
-  float prev_os[3];
-  mul_v3_m4v3(curr_os, kcd->ob_imat, kcd->curr.cage);
-  mul_v3_m4v3(prev_os, kcd->ob_imat, kcd->prev.cage);
+  planes_from_projmat(
+      kcd->vc.rv3d->persmat, planes[2], planes[0], planes[1], planes[3], NULL, NULL);
 
   /* Ray-cast all planes. */
   {
     float ray_dir[3];
-    float ray_hit_best[2][3] = {{UNPACK3(prev_os)}, {UNPACK3(curr_os)}};
+    float ray_hit_best[2][3] = {{UNPACK3(kcd->prev.cage)}, {UNPACK3(kcd->curr.cage)}};
     float lambda_best[2] = {-FLT_MAX, FLT_MAX};
     int i;
 
     /* We (sometimes) need the lines to be at the same depth before projecting. */
-#if 0
+#  if 0
     sub_v3_v3v3(ray_dir, kcd->curr.cage, kcd->prev.cage);
-#else
+#  else
     {
       float curr_cage_adjust[3];
       float co_depth[3];
 
-      copy_v3_v3(co_depth, prev_os);
-      mul_m4_v3(kcd->ob->obmat, co_depth);
+      copy_v3_v3(co_depth, kcd->prev.cage);
       ED_view3d_win_to_3d(kcd->vc.v3d, kcd->region, co_depth, kcd->curr.mval, curr_cage_adjust);
-      mul_m4_v3(kcd->ob_imat, curr_cage_adjust);
 
-      sub_v3_v3v3(ray_dir, curr_cage_adjust, prev_os);
+      sub_v3_v3v3(ray_dir, curr_cage_adjust, kcd->prev.cage);
     }
-#endif
+#  endif
 
     for (i = 0; i < 4; i++) {
       float ray_hit[3];
       float lambda_test;
-      if (isect_ray_plane_v3(prev_os, ray_dir, planes[i], &lambda_test, false)) {
-        madd_v3_v3v3fl(ray_hit, prev_os, ray_dir, lambda_test);
+      if (isect_ray_plane_v3(kcd->prev.cage, ray_dir, planes[i], &lambda_test, false)) {
+        madd_v3_v3v3fl(ray_hit, kcd->prev.cage, ray_dir, lambda_test);
         if (lambda_test < 0.0f) {
           if (lambda_test > lambda_best[0]) {
             copy_v3_v3(ray_hit_best[0], ray_hit);
@@ -433,8 +417,6 @@ static void knifetool_raycast_planes(const KnifeTool_OpData *kcd, float r_v1[3],
 
     copy_v3_v3(r_v1, ray_hit_best[0]);
     copy_v3_v3(r_v2, ray_hit_best[1]);
-    mul_m4_v3(kcd->ob->obmat, r_v1);
-    mul_m4_v3(kcd->ob->obmat, r_v2);
   }
 }
 
@@ -498,6 +480,7 @@ static void knifetool_draw_orientation_locking(const KnifeTool_OpData *kcd)
     immUnbindProgram();
   }
 }
+#endif
 
 static void knifetool_draw_visible_distances(const KnifeTool_OpData *kcd)
 {
@@ -603,8 +586,10 @@ static void knifetool_draw_angle(const KnifeTool_OpData *kcd,
     float axis[3];
     float arc_angle;
 
-    const float inverse_average_scale = 1 / (kcd->ob->obmat[0][0] + kcd->ob->obmat[1][1] +
-                                             kcd->ob->obmat[2][2]);
+    const float inverse_average_scale = 1 /
+                                        (kcd->curr.ob->obmat[0][0] + kcd->curr.ob->obmat[1][1] +
+                                         kcd->curr.ob->obmat[2][2]);
+
     const float px_scale =
         3.0f * inverse_average_scale *
         (ED_view3d_pixel_size_no_ui_scale(rv3d, mid) *
@@ -1210,7 +1195,7 @@ static void knife_bvh_init(KnifeTool_OpData *kcd)
   bool test_fn_ret = false;
 
   /* Calculate tottri. */
-  for (int b = 0; b < kcd->bases_len; b++) {
+  for (uint b = 0; b < kcd->bases_len; b++) {
     ob_tottri = 0;
     ob = kcd->bases[b]->object;
     em = BKE_editmesh_from_object(ob);
@@ -1242,7 +1227,7 @@ static void knife_bvh_init(KnifeTool_OpData *kcd)
    * Don't forget to update #knife_bvh_intersect_plane!
    */
   tottri = 0;
-  for (int b = 0; b < kcd->bases_len; b++) {
+  for (uint b = 0; b < kcd->bases_len; b++) {
     ob = kcd->bases[b]->object;
     em = BKE_editmesh_from_object(ob);
     looptris = em->looptris;
@@ -1300,11 +1285,10 @@ static void knife_bvh_raycast_cb(void *userdata,
   bool isect;
   int tottri;
   float tri_cos[3][3];
-  float ob_imat[4][4];
 
   if (index != -1) {
     tottri = 0;
-    int b = 0;
+    uint b = 0;
     for (; b < kcd->bases_len; b++) {
       index -= tottri;
       ob = kcd->bases[b]->object;
@@ -1370,7 +1354,6 @@ static BMFace *knife_bvh_raycast(KnifeTool_OpData *kcd,
                                  float *r_dist,
                                  float r_hitout[3],
                                  float r_cagehit[3],
-                                 bool same_object, /* Fail intersection if object != kcd->ob. */
                                  uint *r_base_index)
 {
   BMFace *face;
@@ -1384,12 +1367,6 @@ static BMFace *knife_bvh_raycast(KnifeTool_OpData *kcd,
 
   /* Handle Hit */
   if (hit.index != -1 && hit.dist != dist) {
-    if (same_object) {
-      if (kcd->base_index != kcd->bvh.base_index) {
-        return NULL;
-      }
-    }
-
     face = kcd->bvh.looptris[hit.index][0]->f;
 
     /* Hits returned in world space. */
@@ -1416,18 +1393,16 @@ static BMFace *knife_bvh_raycast(KnifeTool_OpData *kcd,
 }
 
 /* `co` is expected to be in world space. */
-static BMFace *knife_bvh_raycast_filter(
-    KnifeTool_OpData *kcd,
-    const float co[3],
-    const float dir[3],
-    const float radius,
-    float *r_dist,
-    float r_hitout[3],
-    float r_cagehit[3],
-    bool same_object, /* Fail intersection if object != kcd->ob. */
-    uint *r_base_index,
-    bool (*filter_cb)(BMFace *f, void *userdata),
-    void *filter_userdata)
+static BMFace *knife_bvh_raycast_filter(KnifeTool_OpData *kcd,
+                                        const float co[3],
+                                        const float dir[3],
+                                        const float radius,
+                                        float *r_dist,
+                                        float r_hitout[3],
+                                        float r_cagehit[3],
+                                        uint *r_base_index,
+                                        bool (*filter_cb)(BMFace *f, void *userdata),
+                                        void *filter_userdata)
 {
   kcd->bvh.filter_cb = filter_cb;
   kcd->bvh.filter_data = filter_userdata;
@@ -1446,12 +1421,6 @@ static BMFace *knife_bvh_raycast_filter(
 
   /* Handle Hit */
   if (hit.index != -1 && hit.dist != dist) {
-    if (same_object) {
-      if (kcd->base_index != kcd->bvh.base_index) {
-        return NULL;
-      }
-    }
-
     face = kcd->bvh.looptris[hit.index][0]->f;
 
     /* Hits returned in world space. */
@@ -1477,34 +1446,6 @@ static BMFace *knife_bvh_raycast_filter(
   return NULL;
 }
 
-/* TODO: Currently filters to only intersections with kcd->ob.
- * Change when adding functionality to cut across multiple objects. */
-static int *knife_bvh_intersect_plane(KnifeTool_OpData *kcd, float *plane, uint *r_intersect_tot)
-{
-  Object *ob;
-  BMEditMesh *em;
-  int tottri = 0;
-  int b = 0;
-  for (; b < kcd->bases_len; b++) {
-    ob = kcd->bases[b]->object;
-    em = BKE_editmesh_from_object(ob);
-    if (kcd->ob == ob) {
-      break;
-    }
-    tottri += em->tottri;
-  }
-
-  int *results = NULL;
-  results = BLI_bvhtree_intersect_plane(kcd->bvh.tree, plane, r_intersect_tot);
-  for (int i = 0; i < *r_intersect_tot; i++) {
-    results[i] -= tottri;
-    if (results[i] < 0 || results[i] >= em->tottri) {
-      results[i] = -1;
-    }
-  }
-  return results;
-}
-
 /** \} */
 
 /* -------------------------------------------------------------------- */
@@ -1540,7 +1481,7 @@ static void knifetool_recast_cageco(KnifeTool_OpData *kcd, float mval[3], float
   sub_v3_v3v3(ray, origin_ofs, origin);
   normalize_v3_v3(ray_normal, ray);
 
-  knife_bvh_raycast(kcd, origin, ray_normal, 0.0f, NULL, co, r_cage, true, NULL);
+  knife_bvh_raycast(kcd, origin, ray_normal, 0.0f, NULL, co, r_cage, NULL);
 }
 
 static bool knife_verts_edge_in_face(KnifeVert *v1, KnifeVert *v2, BMFace *f)
@@ -1584,15 +1525,8 @@ static bool knife_verts_edge_in_face(KnifeVert *v1, KnifeVert *v2, BMFace *f)
   return false;
 }
 
-static void knife_recalc_projmat(KnifeTool_OpData *kcd)
+static void knife_recalc_ortho(KnifeTool_OpData *kcd)
 {
-  ED_view3d_ob_project_mat_get(kcd->region->regiondata, kcd->ob, kcd->projmat);
-  invert_m4_m4(kcd->projmat_inv, kcd->projmat);
-
-  invert_m4_m4_safe_ortho(kcd->ob_imat, kcd->ob->obmat);
-  mul_v3_mat3_m4v3(kcd->proj_zaxis, kcd->ob_imat, kcd->vc.rv3d->viewinv[2]);
-  normalize_v3(kcd->proj_zaxis);
-
   

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list