~ubuntu-branches/ubuntu/trusty/blender/trusty-proposed

« back to all changes in this revision

Viewing changes to source/blender/editors/mesh/editmesh_knife.c

  • Committer: Package Import Robot
  • Author(s): Matteo F. Vescovi
  • Date: 2013-08-14 10:43:49 UTC
  • mfrom: (14.2.19 sid)
  • Revision ID: package-import@ubuntu.com-20130814104349-t1d5mtwkphp12dyj
Tags: 2.68a-3
* Upload to unstable
* debian/: python3.3 Depends simplified
  - debian/control: python3.3 Depends dropped
    for blender-data package
  - 0001-blender_thumbnailer.patch refreshed
* debian/control: libavcodec b-dep versioning dropped

Show diffs side-by-side

added added

removed removed

Lines of Context:
35
35
 
36
36
#include "MEM_guardedalloc.h"
37
37
 
38
 
#include "BLI_blenlib.h"
 
38
#include "BLI_listbase.h"
 
39
#include "BLI_string.h"
39
40
#include "BLI_array.h"
 
41
#include "BLI_linklist.h"
40
42
#include "BLI_math.h"
41
43
#include "BLI_smallhash.h"
42
44
#include "BLI_memarena.h"
45
47
 
46
48
#include "BKE_DerivedMesh.h"
47
49
#include "BKE_context.h"
 
50
#include "BKE_editmesh.h"
 
51
#include "BKE_editmesh_bvh.h"
48
52
 
49
53
#include "BIF_gl.h"
50
54
#include "BIF_glutil.h" /* for paint cursor */
57
61
#include "WM_api.h"
58
62
#include "WM_types.h"
59
63
 
60
 
#include "DNA_scene_types.h"
61
64
#include "DNA_object_types.h"
62
 
#include "BKE_tessmesh.h"
63
65
#include "UI_resources.h"
64
66
 
65
67
#include "RNA_access.h"
66
68
#include "RNA_define.h"
67
69
 
68
 
#include "mesh_intern.h"
 
70
#include "mesh_intern.h"  /* own include */
69
71
 
70
72
/* this code here is kindof messy. . .I might need to eventually rework it - joeedh */
71
73
 
89
91
        ListBase edges;
90
92
        ListBase faces;
91
93
 
92
 
        float co[3], cageco[3], sco[3]; /* sco is screen coordinates for cageco */
93
 
        short flag, draw, isface, inspace;
 
94
        float co[3], cageco[3], sco[2]; /* sco is screen coordinates for cageco */
 
95
        bool is_face, in_space;
 
96
        bool draw;
94
97
} KnifeVert;
95
98
 
96
99
typedef struct Ref {
102
105
        KnifeVert *v1, *v2;
103
106
        BMFace *basef; /* face to restrict face fill to */
104
107
        ListBase faces;
105
 
        int draw;
106
108
 
107
 
        BMEdge *e, *oe; /* non-NULL if this is an original edge */
 
109
        BMEdge *e /* , *e_old */; /* non-NULL if this is an original edge */
 
110
        bool draw;
108
111
} KnifeEdge;
109
112
 
110
113
typedef struct BMEdgeHit {
111
114
        KnifeEdge *kfe;
112
115
        float hit[3], cagehit[3];
113
116
        float realhit[3]; /* used in midpoint mode */
114
 
        float schit[3];
 
117
        float schit[2];
115
118
        float l; /* lambda along cut line */
116
119
        float perc; /* lambda along hit line */
117
120
        KnifeVert *v; /* set if snapped to a vert */
128
131
        KnifeVert *vert;
129
132
        KnifeEdge *edge;
130
133
        BMFace *bmface;
131
 
        int is_space;
 
134
        bool is_space;
132
135
 
133
136
        float mval[2]; /* mouse screen position (may be non-integral if snapped to something) */
134
137
} KnifePosData;
137
140
typedef struct KnifeTool_OpData {
138
141
        ARegion *ar;        /* region that knifetool was activated in */
139
142
        void *draw_handle;  /* for drawing preview loop */
140
 
        ViewContext vc;
 
143
        ViewContext vc;     /* note: _don't_ use 'mval', instead use the one we define below */
 
144
        float mval[2];      /* mouse value with snapping applied */
141
145
        //bContext *C;
142
146
 
143
147
        Object *ob;
173
177
 
174
178
        KnifeColors colors;
175
179
 
 
180
        /* run by the UI or not */
 
181
        bool is_interactive;
 
182
 
176
183
        /* operatpr options */
177
 
        char cut_through;    /* preference, can be modified at runtime (that feature may go) */
178
 
        char only_select;    /* set on initialization */
179
 
        char select_result;  /* set on initialization */
 
184
        bool cut_through;    /* preference, can be modified at runtime (that feature may go) */
 
185
        bool only_select;    /* set on initialization */
 
186
        bool select_result;  /* set on initialization */
180
187
 
181
 
        short is_ortho;
 
188
        bool is_ortho;
182
189
        float ortho_extent;
183
190
        float clipsta, clipend;
184
191
 
189
196
                MODE_PANNING
190
197
        } mode;
191
198
 
192
 
        int snap_midpoints, prevmode, extend;
193
 
        int ignore_edge_snapping, ignore_vert_snapping;
 
199
        int prevmode;
 
200
        bool snap_midpoints, extend;
 
201
        bool ignore_edge_snapping;
 
202
        bool ignore_vert_snapping;
194
203
 
195
204
        enum {
196
205
                ANGLE_FREE,
200
209
                ANGLE_135
201
210
        } angle_snapping;
202
211
 
203
 
        float (*cagecos)[3];
 
212
        const float (*cagecos)[3];
204
213
} KnifeTool_OpData;
205
214
 
206
215
static ListBase *knife_get_face_kedges(KnifeTool_OpData *kcd, BMFace *f);
228
237
        ED_area_headerprint(CTX_wm_area(C), header);
229
238
}
230
239
 
 
240
#if 0
231
241
BLI_INLINE int round_ftoi(float x)
232
242
{
233
243
        return x > 0.0f ?  (int)(x + 0.5f) : (int)(x - 0.5f);
234
244
}
 
245
#endif
235
246
 
236
 
static void knife_project_v3(KnifeTool_OpData *kcd, const float co[3], float sco[3])
 
247
static void knife_project_v2(const KnifeTool_OpData *kcd, const float co[3], float sco[2])
237
248
{
238
 
        ED_view3d_project_float_v3_m4(kcd->ar, co, sco, kcd->projmat);
 
249
        ED_view3d_project_float_v2_m4(kcd->ar, co, sco, (float (*)[4])kcd->projmat);
239
250
}
240
251
 
241
252
static void knife_pos_data_clear(KnifePosData *kpd)
245
256
        kpd->vert = NULL;
246
257
        kpd->edge = NULL;
247
258
        kpd->bmface = NULL;
248
 
        kpd->mval[0] = 0.0f;
249
 
        kpd->mval[1] = 0.0f;
 
259
        zero_v2(kpd->mval);
250
260
}
251
261
 
252
262
static ListBase *knife_empty_list(KnifeTool_OpData *kcd)
317
327
        return NULL;
318
328
}
319
329
 
320
 
static KnifeVert *new_knife_vert(KnifeTool_OpData *kcd, const float co[3], float *cageco)
 
330
static KnifeVert *new_knife_vert(KnifeTool_OpData *kcd, const float co[3], const float cageco[3])
321
331
{
322
332
        KnifeVert *kfv = BLI_mempool_calloc(kcd->kverts);
323
333
 
325
335
 
326
336
        copy_v3_v3(kfv->co, co);
327
337
        copy_v3_v3(kfv->cageco, cageco);
328
 
        copy_v3_v3(kfv->sco, co);
329
338
 
330
 
        knife_project_v3(kcd, kfv->co, kfv->sco);
 
339
        knife_project_v2(kcd, kfv->co, kfv->sco);
331
340
 
332
341
        return kfv;
333
342
}
494
503
        if (kcd->prev.edge && kcd->prev.edge == kcd->curr.edge)
495
504
                return;
496
505
 
497
 
        kfe->draw = 1;
 
506
        kfe->draw = true;
498
507
 
499
508
        if (kcd->prev.vert) {
500
509
                kfe->v1 = kcd->prev.vert;
505
514
        else {
506
515
                kfe->v1 = new_knife_vert(kcd, kcd->prev.co, kcd->prev.co);
507
516
                kfe->v1->draw = kfe->draw = !kcd->prev.is_space;
508
 
                kfe->v1->inspace = kcd->prev.is_space;
 
517
                kfe->v1->in_space = kcd->prev.is_space;
509
518
                kfe->draw = !kcd->prev.is_space;
510
 
                kfe->v1->isface = 1;
 
519
                kfe->v1->is_face = true;
511
520
                if (kfe->v1->draw && kcd->prev.bmface)
512
521
                        knife_append_list(kcd, &kfe->v1->faces, kcd->prev.bmface);
513
522
        }
522
531
        else {
523
532
                kfe->v2 = new_knife_vert(kcd, kcd->curr.co, kcd->curr.co);
524
533
                kfe->v2->draw = !kcd->curr.is_space;
525
 
                kfe->v2->isface = 1;
526
 
                kfe->v2->inspace = kcd->curr.is_space;
 
534
                kfe->v2->is_face = true;
 
535
                kfe->v2->in_space = kcd->curr.is_space;
527
536
                if (kfe->v2->draw && kcd->curr.bmface)
528
537
                        knife_append_list(kcd, &kfe->v2->faces, kcd->curr.bmface);
529
538
 
530
539
                if (kcd->curr.is_space)
531
 
                        kfe->draw = 0;
 
540
                        kfe->draw = false;
532
541
 
533
542
                kcd->curr.vert = kfe->v2;
534
543
        }
632
641
        KnifeEdge *kfenew;
633
642
 
634
643
        kfenew = new_knife_edge(kcd);
635
 
        kfenew->draw = 1;
636
644
        kfenew->basef = f;
637
645
        kfenew->v1 = v1;
638
646
        kfenew->v2 = v2;
639
 
        kfenew->draw = 1;
 
647
        kfenew->draw = true;
640
648
 
641
649
        knife_add_to_vert_edges(kcd, kfenew);
642
650
 
650
658
        BMFace *f;
651
659
        Ref *r;
652
660
 
653
 
        if (kfv->isface && facef) {
 
661
        if (kfv->is_face && facef) {
654
662
                knife_append_list(kcd, lst, facef);
655
663
        }
656
664
        else if (kfv->v) {
689
697
        ListBase firstfaces = {NULL, NULL}, lastfaces = {NULL, NULL};
690
698
        Ref *r, *r2;
691
699
        KnifeEdge **splitkfe;
692
 
        int i, j, found;
 
700
        int i, j;
693
701
 
694
702
        if (!kcd->totlinehit) {
695
703
                /* if no linehits then no interesting back face stuff to do */
727
735
                /* For each face incident to firstv,
728
736
                 * find the first following linehit (if any) sharing that face and connect */
729
737
                for (r = firstfaces.first; r; r = r->next) {
 
738
                        bool found = false;
730
739
                        f = r->ref;
731
 
                        found = 0;
732
740
                        for (j = 0, lh2 = kcd->linehits; j < kcd->totlinehit && !found; j++, lh2++) {
733
741
                                kfe2 = lh2->kfe;
734
742
                                for (r2 = kfe2->faces.first; r2; r2 = r2->next) {
735
743
                                        if (r2->ref == f) {
736
744
                                                v2 = splitkfe[j] ? kfe2->v1 : knife_split_edge(kcd, kfe2, lh2->hit, &splitkfe[j]);
737
745
                                                knife_add_single_cut_through(kcd, firstv, v2, f);
738
 
                                                found = 1;
 
746
                                                found = true;
739
747
                                                break;
740
748
                                        }
741
749
                                }
757
765
                /* For each face attached to edge for this linehit,
758
766
                 * find the first following linehit (if any) sharing that face and connect */
759
767
                for (r = kfe->faces.first; r; r = r->next) {
 
768
                        bool found = false;
760
769
                        f = r->ref;
761
 
                        found = 0;
762
770
                        for (j = i + 1, lh2 = lh + 1; j < kcd->totlinehit && !found; j++, lh2++) {
763
771
                                kfe2 = lh2->kfe;
764
772
                                for (r2 = kfe2->faces.first; r2; r2 = r2->next) {
766
774
                                                v1 = splitkfe[i] ? kfe->v1 : knife_split_edge(kcd, kfe, lh->hit, &splitkfe[i]);
767
775
                                                v2 = splitkfe[j] ? kfe2->v1 : knife_split_edge(kcd, kfe2, lh2->hit, &splitkfe[j]);
768
776
                                                knife_add_single_cut_through(kcd, v1, v2, f);
769
 
                                                found = 1;
 
777
                                                found = true;
770
778
                                                break;
771
779
                                        }
772
780
                                }
890
898
 
891
899
}
892
900
 
893
 
static void knifetool_draw_angle_snapping(KnifeTool_OpData *kcd)
 
901
static void knifetool_draw_angle_snapping(const KnifeTool_OpData *kcd)
894
902
{
895
903
        bglMats mats;
896
904
        double u[3], u1[2], u2[2], v1[3], v2[3], dx, dy;
1006
1014
static void knifetool_draw(const bContext *C, ARegion *UNUSED(ar), void *arg)
1007
1015
{
1008
1016
        View3D *v3d = CTX_wm_view3d(C);
1009
 
        KnifeTool_OpData *kcd = arg;
 
1017
        const KnifeTool_OpData *kcd = arg;
1010
1018
 
1011
1019
        if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
1012
1020
 
1062
1070
 
1063
1071
        if (kcd->totlinehit > 0) {
1064
1072
                const float vthresh4 = kcd->vthresh / 4.0f;
1065
 
                const float vthresh4_squared = vthresh4 * vthresh4;
 
1073
                const float vthresh4_sq = vthresh4 * vthresh4;
1066
1074
 
1067
1075
                BMEdgeHit *lh;
1068
1076
                int i;
1076
1084
                glBegin(GL_POINTS);
1077
1085
                lh = kcd->linehits;
1078
1086
                for (i = 0; i < kcd->totlinehit; i++, lh++) {
1079
 
                        float sv1[3], sv2[3];
1080
 
 
1081
 
                        knife_project_v3(kcd, lh->kfe->v1->cageco, sv1);
1082
 
                        knife_project_v3(kcd, lh->kfe->v2->cageco, sv2);
1083
 
                        knife_project_v3(kcd, lh->cagehit, lh->schit);
1084
 
 
1085
 
                        if (len_squared_v2v2(lh->schit, sv1) < vthresh4_squared) {
 
1087
                        float sv1[2], sv2[2];
 
1088
 
 
1089
                        knife_project_v2(kcd, lh->kfe->v1->cageco, sv1);
 
1090
                        knife_project_v2(kcd, lh->kfe->v2->cageco, sv2);
 
1091
                        knife_project_v2(kcd, lh->cagehit, lh->schit);
 
1092
 
 
1093
                        if (len_squared_v2v2(lh->schit, sv1) < vthresh4_sq) {
1086
1094
                                copy_v3_v3(lh->cagehit, lh->kfe->v1->cageco);
1087
1095
                                glVertex3fv(lh->cagehit);
1088
1096
                                lh->v = lh->kfe->v1;
1089
1097
                        }
1090
 
                        else if (len_squared_v2v2(lh->schit, sv2) < vthresh4_squared) {
 
1098
                        else if (len_squared_v2v2(lh->schit, sv2) < vthresh4_sq) {
1091
1099
                                copy_v3_v3(lh->cagehit, lh->kfe->v2->cageco);
1092
1100
                                glVertex3fv(lh->cagehit);
1093
1101
                                lh->v = lh->kfe->v2;
1167
1175
                                       const float v1[3],  const float v2[3], const float v3[3],
1168
1176
                                       SmallHash *ehash, bglMats *mats, int *count)
1169
1177
{
1170
 
        BVHTree *tree2 = BLI_bvhtree_new(3, FLT_EPSILON * 4, 8, 8), *tree = BMBVH_BVHTree(bmtree);
 
1178
        BVHTree *tree2 = BLI_bvhtree_new(3, FLT_EPSILON * 4, 8, 8), *tree = BKE_bmbvh_tree_get(bmtree);
1171
1179
        BMEdgeHit *edges = NULL;
1172
1180
        BLI_array_declare(edges);
1173
1181
        BVHTreeOverlap *results, *result;
1179
1187
        /* for comparing distances, error of intersection depends on triangle scale.
1180
1188
         * need to scale down before squaring for accurate comparison */
1181
1189
        const float depsilon = (FLT_EPSILON / 2.0f) * len_v3_tri_side_max(v1, v2, v3);
1182
 
        const float depsilon_squared = depsilon * depsilon;
 
1190
        const float depsilon_sq = depsilon * depsilon;
1183
1191
 
1184
1192
        copy_v3_v3(cos + 0, v1);
1185
1193
        copy_v3_v3(cos + 3, v2);
1192
1200
 
1193
1201
        for (i = 0; i < tot; i++, result++) {
1194
1202
                BMLoop *l1;
1195
 
                BMFace *hitf;
 
1203
                BMFace *f_hit;
1196
1204
                ListBase *lst;
1197
1205
                Ref *ref;
1198
1206
 
1204
1212
                for (ref = lst->first; ref; ref = ref->next) {
1205
1213
                        KnifeEdge *kfe = ref->ref;
1206
1214
 
1207
 
                        if (BLI_smallhash_haskey(ehash, (intptr_t)kfe)) {
 
1215
                        if (BLI_smallhash_haskey(ehash, (uintptr_t)kfe)) {
1208
1216
                                continue;  /* We already found a hit on this knife edge */
1209
1217
                        }
1210
1218
 
1211
1219
                        if (isect_line_tri_v3(kfe->v1->cageco, kfe->v2->cageco, v1, v2, v3, &lambda, NULL)) {
1212
 
                                float p[3], no[3], view[3], sp[3];
 
1220
                                float p[3], no[3], view[3], sp[2];
1213
1221
 
1214
1222
                                interp_v3_v3v3(p, kfe->v1->cageco, kfe->v2->cageco, lambda);
1215
1223
 
1216
 
                                if (kcd->curr.vert && len_squared_v3v3(kcd->curr.vert->cageco, p) < depsilon_squared) {
1217
 
                                        continue;
1218
 
                                }
1219
 
                                if (kcd->prev.vert && len_squared_v3v3(kcd->prev.vert->cageco, p) < depsilon_squared) {
1220
 
                                        continue;
1221
 
                                }
1222
 
                                if (len_squared_v3v3(kcd->prev.cage, p) < depsilon_squared ||
1223
 
                                    len_squared_v3v3(kcd->curr.cage, p) < depsilon_squared)
 
1224
                                if (kcd->curr.vert && len_squared_v3v3(kcd->curr.vert->cageco, p) < depsilon_sq) {
 
1225
                                        continue;
 
1226
                                }
 
1227
                                if (kcd->prev.vert && len_squared_v3v3(kcd->prev.vert->cageco, p) < depsilon_sq) {
 
1228
                                        continue;
 
1229
                                }
 
1230
                                if (len_squared_v3v3(kcd->prev.cage, p) < depsilon_sq ||
 
1231
                                    len_squared_v3v3(kcd->curr.cage, p) < depsilon_sq)
1224
1232
                                {
1225
1233
                                        continue;
1226
1234
                                }
1227
1235
                                if ((kcd->vc.rv3d->rflag & RV3D_CLIPPING) &&
1228
 
                                    ED_view3d_clipping_test(kcd->vc.rv3d, p, TRUE))
 
1236
                                    ED_view3d_clipping_test(kcd->vc.rv3d, p, true))
1229
1237
                                {
1230
1238
                                        continue;
1231
1239
                                }
1232
1240
 
1233
 
                                knife_project_v3(kcd, p, sp);
 
1241
                                knife_project_v2(kcd, p, sp);
1234
1242
                                ED_view3d_unproject(mats, view, sp[0], sp[1], 0.0f);
1235
1243
                                mul_m4_v3(kcd->ob->imat, view);
1236
1244
 
1237
1245
                                if (kcd->cut_through) {
1238
 
                                        hitf = FALSE;
 
1246
                                        f_hit = NULL;
1239
1247
                                }
1240
1248
                                else {
1241
1249
                                        /* check if this point is visible in the viewport */
1259
1267
                                        add_v3_v3(p1, no);
1260
1268
                                                
1261
1269
                                        /* ray cast */
1262
 
                                        hitf = BMBVH_RayCast(bmtree, p1, no, NULL, NULL);
 
1270
                                        f_hit = BKE_bmbvh_ray_cast(bmtree, p1, no, NULL, NULL, NULL);
1263
1271
                                }
1264
1272
 
1265
1273
                                /* ok, if visible add the new point */
1266
 
                                if (!hitf && !BLI_smallhash_haskey(ehash, (intptr_t)kfe)) {
 
1274
                                if (!f_hit && !BLI_smallhash_haskey(ehash, (uintptr_t)kfe)) {
1267
1275
                                        BMEdgeHit hit;
1268
1276
        
1269
 
                                        if (len_squared_v3v3(p, kcd->curr.co) < depsilon_squared ||
1270
 
                                            len_squared_v3v3(p, kcd->prev.co) < depsilon_squared)
 
1277
                                        if (len_squared_v3v3(p, kcd->curr.co) < depsilon_sq ||
 
1278
                                            len_squared_v3v3(p, kcd->prev.co) < depsilon_sq)
1271
1279
                                        {
1272
1280
                                                continue;
1273
1281
                                        }
1304
1312
                                        else {
1305
1313
                                                copy_v3_v3(hit.hit, p);
1306
1314
                                        }
1307
 
                                        knife_project_v3(kcd, hit.cagehit, hit.schit);
 
1315
                                        knife_project_v2(kcd, hit.cagehit, hit.schit);
1308
1316
 
1309
1317
                                        BLI_array_append(edges, hit);
1310
 
                                        BLI_smallhash_insert(ehash, (intptr_t)kfe, NULL);
 
1318
                                        BLI_smallhash_insert(ehash, (uintptr_t)kfe, NULL);
1311
1319
                                }
1312
1320
                        }
1313
1321
                }
1363
1371
        bglMats mats;
1364
1372
        BMEdgeHit *e1, *e2;
1365
1373
        SmallHash hash, *ehash = &hash;
1366
 
        float v1[3], v2[3], v3[3], v4[4], s1[3], s2[3];
 
1374
        float v1[3], v2[3], v3[3], v4[4], s1[2], s2[2];
1367
1375
        int i, c1, c2;
1368
1376
 
1369
1377
        knife_bgl_get_mats(kcd, &mats);
1378
1386
        copy_v3_v3(v2, kcd->curr.cage);
1379
1387
 
1380
1388
        /* project screen line's 3d coordinates back into 2d */
1381
 
        knife_project_v3(kcd, v1, s1);
1382
 
        knife_project_v3(kcd, v2, s2);
 
1389
        knife_project_v2(kcd, v1, s1);
 
1390
        knife_project_v2(kcd, v2, s2);
1383
1391
 
1384
 
        if (len_v2v2(s1, s2) < 1)
 
1392
        if (len_squared_v2v2(s1, s2) < 1)
1385
1393
                return;
1386
1394
 
1387
1395
        /* unproject screen line */
1388
 
        ED_view3d_win_to_segment_clip(kcd->ar, kcd->vc.v3d, s1, v1, v3);
1389
 
        ED_view3d_win_to_segment_clip(kcd->ar, kcd->vc.v3d, s2, v2, v4);
 
1396
        ED_view3d_win_to_segment(kcd->ar, kcd->vc.v3d, s1, v1, v3, true);
 
1397
        ED_view3d_win_to_segment(kcd->ar, kcd->vc.v3d, s2, v2, v4, true);
1390
1398
 
1391
1399
        mul_m4_v3(kcd->ob->imat, v1);
1392
1400
        mul_m4_v3(kcd->ob->imat, v2);
1481
1489
        mul_m4_v3(kcd->ob->imat, r_origin_ofs);
1482
1490
}
1483
1491
 
1484
 
static BMFace *knife_find_closest_face(KnifeTool_OpData *kcd, float co[3], float cageco[3], int *is_space)
 
1492
static BMFace *knife_find_closest_face(KnifeTool_OpData *kcd, float co[3], float cageco[3], bool *is_space)
1485
1493
{
1486
1494
        BMFace *f;
1487
1495
        float dist = KMAXDIST;
1493
1501
        knife_input_ray_segment(kcd, kcd->curr.mval, 1.0f, origin, origin_ofs);
1494
1502
        sub_v3_v3v3(ray, origin_ofs, origin);
1495
1503
 
1496
 
        f = BMBVH_RayCast(kcd->bmbvh, origin, ray, co, cageco);
 
1504
        f = BKE_bmbvh_ray_cast(kcd->bmbvh, origin, ray, NULL, co, cageco);
1497
1505
 
1498
1506
        if (is_space)
1499
1507
                *is_space = !f;
1500
1508
 
1501
1509
        if (!f) {
1502
 
                /* try to use backbuffer selection method if ray casting failed */
1503
 
                f = EDBM_face_find_nearest(&kcd->vc, &dist);
 
1510
                if (kcd->is_interactive) {
 
1511
                        /* try to use backbuffer selection method if ray casting failed */
 
1512
                        f = EDBM_face_find_nearest(&kcd->vc, &dist);
1504
1513
 
1505
 
                /* cheat for now; just put in the origin instead
1506
 
                 * of a true coordinate on the face.
1507
 
                 * This just puts a point 1.0f infront of the view. */
1508
 
                add_v3_v3v3(co, origin, ray);
 
1514
                        /* cheat for now; just put in the origin instead
 
1515
                         * of a true coordinate on the face.
 
1516
                         * This just puts a point 1.0f infront of the view. */
 
1517
                        add_v3_v3v3(co, origin, ray);
 
1518
                }
1509
1519
        }
1510
1520
 
1511
1521
        return f;
1513
1523
 
1514
1524
/* find the 2d screen space density of vertices within a radius.  used to scale snapping
1515
1525
 * distance for picking edges/verts.*/
1516
 
static int knife_sample_screen_density(KnifeTool_OpData *kcd, float radius)
 
1526
static int knife_sample_screen_density(KnifeTool_OpData *kcd, const float radius)
1517
1527
{
1518
1528
        BMFace *f;
1519
 
        int is_space;
1520
 
        float co[3], cageco[3], sco[3];
 
1529
        bool is_space;
 
1530
        float co[3], cageco[3], sco[2];
 
1531
 
 
1532
        BLI_assert(kcd->is_interactive == true);
1521
1533
 
1522
1534
        f = knife_find_closest_face(kcd, co, cageco, &is_space);
1523
1535
 
1524
1536
        if (f && !is_space) {
 
1537
                const float radius_sq = radius * radius;
1525
1538
                ListBase *lst;
1526
1539
                Ref *ref;
1527
 
                float dis;
 
1540
                float dis_sq;
1528
1541
                int c = 0;
1529
1542
 
1530
 
                knife_project_v3(kcd, cageco, sco);
 
1543
                knife_project_v2(kcd, cageco, sco);
1531
1544
 
1532
1545
                lst = knife_get_face_kedges(kcd, f);
1533
1546
                for (ref = lst->first; ref; ref = ref->next) {
1537
1550
                        for (i = 0; i < 2; i++) {
1538
1551
                                KnifeVert *kfv = i ? kfe->v2 : kfe->v1;
1539
1552
 
1540
 
                                knife_project_v3(kcd, kfv->cageco, kfv->sco);
 
1553
                                knife_project_v2(kcd, kfv->cageco, kfv->sco);
1541
1554
 
1542
 
                                dis = len_v2v2(kfv->sco, sco);
1543
 
                                if (dis < radius) {
 
1555
                                dis_sq = len_squared_v2v2(kfv->sco, sco);
 
1556
                                if (dis_sq < radius_sq) {
1544
1557
                                        if (kcd->vc.rv3d->rflag & RV3D_CLIPPING) {
1545
 
                                                if (ED_view3d_clipping_test(kcd->vc.rv3d, kfv->cageco, TRUE) == 0) {
 
1558
                                                if (ED_view3d_clipping_test(kcd->vc.rv3d, kfv->cageco, true) == 0) {
1546
1559
                                                        c++;
1547
1560
                                                }
1548
1561
                                        }
1563
1576
 * surrounding mesh (in screen space)*/
1564
1577
static float knife_snap_size(KnifeTool_OpData *kcd, float maxsize)
1565
1578
{
1566
 
        float density = (float)knife_sample_screen_density(kcd, maxsize * 2.0f);
 
1579
        float density;
 
1580
 
 
1581
        if (kcd->is_interactive) {
 
1582
                density = (float)knife_sample_screen_density(kcd, maxsize * 2.0f);
 
1583
        }
 
1584
        else {
 
1585
                density = 1.0f;
 
1586
        }
1567
1587
 
1568
1588
        if (density < 1.0f)
1569
1589
                density = 1.0f;
1572
1592
}
1573
1593
 
1574
1594
/* p is closest point on edge to the mouse cursor */
1575
 
static KnifeEdge *knife_find_closest_edge(KnifeTool_OpData *kcd, float p[3], float cagep[3], BMFace **fptr, int *is_space)
 
1595
static KnifeEdge *knife_find_closest_edge(KnifeTool_OpData *kcd, float p[3], float cagep[3], BMFace **fptr, bool *is_space)
1576
1596
{
1577
1597
        BMFace *f;
1578
 
        float co[3], cageco[3], sco[3], maxdist = knife_snap_size(kcd, kcd->ethresh);
 
1598
        float co[3], cageco[3], sco[2];
 
1599
        float maxdist = knife_snap_size(kcd, kcd->ethresh);
1579
1600
 
1580
1601
        if (kcd->ignore_vert_snapping)
1581
1602
                maxdist *= 0.5f;
1590
1611
        kcd->curr.bmface = f;
1591
1612
 
1592
1613
        if (f) {
 
1614
                const float maxdist_sq = maxdist * maxdist;
1593
1615
                KnifeEdge *cure = NULL;
1594
1616
                ListBase *lst;
1595
1617
                Ref *ref;
1596
 
                float dis, curdis = FLT_MAX;
 
1618
                float dis_sq, curdis_sq = FLT_MAX;
1597
1619
 
1598
 
                knife_project_v3(kcd, cageco, sco);
 
1620
                knife_project_v2(kcd, cageco, sco);
1599
1621
 
1600
1622
                /* look through all edges associated with this face */
1601
1623
                lst = knife_get_face_kedges(kcd, f);
1603
1625
                        KnifeEdge *kfe = ref->ref;
1604
1626
 
1605
1627
                        /* project edge vertices into screen space */
1606
 
                        knife_project_v3(kcd, kfe->v1->cageco, kfe->v1->sco);
1607
 
                        knife_project_v3(kcd, kfe->v2->cageco, kfe->v2->sco);
 
1628
                        knife_project_v2(kcd, kfe->v1->cageco, kfe->v1->sco);
 
1629
                        knife_project_v2(kcd, kfe->v2->cageco, kfe->v2->sco);
1608
1630
 
1609
 
                        dis = dist_to_line_segment_v2(sco, kfe->v1->sco, kfe->v2->sco);
1610
 
                        if (dis < curdis && dis < maxdist) {
 
1631
                        dis_sq = dist_squared_to_line_segment_v2(sco, kfe->v1->sco, kfe->v2->sco);
 
1632
                        if (dis_sq < curdis_sq && dis_sq < maxdist_sq) {
1611
1633
                                if (kcd->vc.rv3d->rflag & RV3D_CLIPPING) {
1612
1634
                                        float lambda = line_point_factor_v2(sco, kfe->v1->sco, kfe->v2->sco);
1613
1635
                                        float vec[3];
1614
1636
 
1615
1637
                                        interp_v3_v3v3(vec, kfe->v1->cageco, kfe->v2->cageco, lambda);
1616
1638
 
1617
 
                                        if (ED_view3d_clipping_test(kcd->vc.rv3d, vec, TRUE) == 0) {
 
1639
                                        if (ED_view3d_clipping_test(kcd->vc.rv3d, vec, true) == 0) {
1618
1640
                                                cure = kfe;
1619
 
                                                curdis = dis;
 
1641
                                                curdis_sq = dis_sq;
1620
1642
                                        }
1621
1643
                                }
1622
1644
                                else {
1623
1645
                                        cure = kfe;
1624
 
                                        curdis = dis;
 
1646
                                        curdis_sq = dis_sq;
1625
1647
                                }
1626
1648
                        }
1627
1649
                }
1668
1690
 
1669
1691
/* find a vertex near the mouse cursor, if it exists */
1670
1692
static KnifeVert *knife_find_closest_vert(KnifeTool_OpData *kcd, float p[3], float cagep[3], BMFace **fptr,
1671
 
                                          int *is_space)
 
1693
                                          bool *is_space)
1672
1694
{
1673
1695
        BMFace *f;
1674
 
        float co[3], cageco[3], sco[3], maxdist = knife_snap_size(kcd, kcd->vthresh);
 
1696
        float co[3], cageco[3], sco[2], maxdist = knife_snap_size(kcd, kcd->vthresh);
1675
1697
 
1676
1698
        if (kcd->ignore_vert_snapping)
1677
1699
                maxdist *= 0.5f;
1684
1706
        kcd->curr.bmface = f;
1685
1707
 
1686
1708
        if (f) {
 
1709
                const float maxdist_sq = maxdist * maxdist;
1687
1710
                ListBase *lst;
1688
1711
                Ref *ref;
1689
1712
                KnifeVert *curv = NULL;
1690
 
                float dis, curdis = FLT_MAX;
 
1713
                float dis_sq, curdis_sq = FLT_MAX;
1691
1714
 
1692
 
                knife_project_v3(kcd, cageco, sco);
 
1715
                knife_project_v2(kcd, cageco, sco);
1693
1716
 
1694
1717
                lst = knife_get_face_kedges(kcd, f);
1695
1718
                for (ref = lst->first; ref; ref = ref->next) {
1699
1722
                        for (i = 0; i < 2; i++) {
1700
1723
                                KnifeVert *kfv = i ? kfe->v2 : kfe->v1;
1701
1724
 
1702
 
                                knife_project_v3(kcd, kfv->cageco, kfv->sco);
 
1725
                                knife_project_v2(kcd, kfv->cageco, kfv->sco);
1703
1726
 
1704
 
                                dis = len_v2v2(kfv->sco, sco);
1705
 
                                if (dis < curdis && dis < maxdist) {
 
1727
                                dis_sq = len_squared_v2v2(kfv->sco, sco);
 
1728
                                if (dis_sq < curdis_sq && dis_sq < maxdist_sq) {
1706
1729
                                        if (kcd->vc.rv3d->rflag & RV3D_CLIPPING) {
1707
 
                                                if (ED_view3d_clipping_test(kcd->vc.rv3d, kfv->cageco, TRUE) == 0) {
 
1730
                                                if (ED_view3d_clipping_test(kcd->vc.rv3d, kfv->cageco, true) == 0) {
1708
1731
                                                        curv = kfv;
1709
 
                                                        curdis = dis;
 
1732
                                                        curdis_sq = dis_sq;
1710
1733
                                                }
1711
1734
                                        }
1712
1735
                                        else {
1713
1736
                                                curv = kfv;
1714
 
                                                curdis = dis;
 
1737
                                                curdis_sq = dis_sq;
1715
1738
                                        }
1716
1739
                                }
1717
1740
                        }
1747
1770
        return NULL;
1748
1771
}
1749
1772
 
1750
 
/* update both kcd->curr.mval and kcd->vc.mval to snap to required angle */
 
1773
/* update both kcd->curr.mval and kcd->mval to snap to required angle */
1751
1774
static void knife_snap_angle(KnifeTool_OpData *kcd)
1752
1775
{
1753
1776
        float dx, dy;
1784
1807
                kcd->curr.mval[0] = kcd->prev.mval[0];
1785
1808
        }
1786
1809
 
1787
 
        kcd->vc.mval[0] = round_ftoi(kcd->curr.mval[0]);
1788
 
        kcd->vc.mval[1] = round_ftoi(kcd->curr.mval[1]);
 
1810
        copy_v2_v2(kcd->mval, kcd->curr.mval);
1789
1811
}
1790
1812
 
1791
1813
/* update active knife edge/vert pointers */
1792
1814
static int knife_update_active(KnifeTool_OpData *kcd)
1793
1815
{
1794
1816
        knife_pos_data_clear(&kcd->curr);
1795
 
        kcd->curr.mval[0] = (float)kcd->vc.mval[0];
1796
 
        kcd->curr.mval[1] = (float)kcd->vc.mval[1];
 
1817
        copy_v2_v2(kcd->curr.mval, kcd->mval);
1797
1818
        if (kcd->angle_snapping != ANGLE_FREE && kcd->mode == MODE_DRAGGING)
1798
1819
                knife_snap_angle(kcd);
1799
1820
 
1841
1862
        KnifeEdge *kfe;
1842
1863
} facenet_entry;
1843
1864
 
1844
 
static void rnd_offset_co(float co[3], float scale)
 
1865
static void rnd_offset_co(RNG *rng, float co[3], float scale)
1845
1866
{
1846
1867
        int i;
1847
1868
 
1848
1869
        for (i = 0; i < 3; i++) {
1849
 
                co[i] += (BLI_frand() - 0.5) * scale;
 
1870
                co[i] += (BLI_rng_get_float(rng) - 0.5) * scale;
1850
1871
        }
1851
1872
}
1852
1873
 
1879
1900
                if (!BMO_elem_flag_test(bm, f, FACE_NEW))
1880
1901
                        continue;
1881
1902
 
1882
 
                if (BLI_smallhash_haskey(visit, (intptr_t)f))
 
1903
                if (BLI_smallhash_haskey(visit, (uintptr_t)f))
1883
1904
                        continue;
1884
1905
 
1885
1906
                BLI_array_empty(stack);
1886
1907
                BLI_array_empty(faces);
1887
1908
                BLI_array_append(stack, f);
1888
 
                BLI_smallhash_insert(visit, (intptr_t)f, NULL);
 
1909
                BLI_smallhash_insert(visit, (uintptr_t)f, NULL);
1889
1910
 
1890
1911
                do {
1891
1912
                        f2 = BLI_array_pop(stack);
1902
1923
                                BM_ITER_ELEM (f3, &fiter, e, BM_FACES_OF_EDGE) {
1903
1924
                                        if (!BMO_elem_flag_test(bm, f3, FACE_NEW))
1904
1925
                                                continue;
1905
 
                                        if (BLI_smallhash_haskey(visit, (intptr_t)f3))
 
1926
                                        if (BLI_smallhash_haskey(visit, (uintptr_t)f3))
1906
1927
                                                continue;
1907
1928
 
1908
 
                                        BLI_smallhash_insert(visit, (intptr_t)f3, NULL);
 
1929
                                        BLI_smallhash_insert(visit, (uintptr_t)f3, NULL);
1909
1930
                                        BLI_array_append(stack, f3);
1910
1931
                                }
1911
1932
                        }
1914
1935
                if (BLI_array_count(faces) > 0) {
1915
1936
                        idx = BM_elem_index_get(faces[0]);
1916
1937
 
1917
 
                        f2 = BM_faces_join(bm, faces, BLI_array_count(faces), TRUE);
 
1938
                        f2 = BM_faces_join(bm, faces, BLI_array_count(faces), true);
1918
1939
                        if (f2) {
1919
1940
                                BMO_elem_flag_enable(bm, f2, FACE_NEW);
1920
1941
                                BM_elem_index_set(f2, idx); /* set_dirty! *//* BMESH_TODO, check if this is valid or not */
1947
1968
        BMFace **faces = MEM_callocN(sizeof(BMFace *) * bm->totface, "faces knife");
1948
1969
        MemArena *arena = BLI_memarena_new(1 << 16, "knifenet_fill_faces");
1949
1970
        SmallHash shash;
 
1971
        RNG *rng;
1950
1972
        int i, j, k = 0, totface = bm->totface;
1951
1973
 
1952
1974
        BMO_push(bm, NULL);
1953
 
        bmesh_edit_begin(bm, BMO_OP_FLAG_UNTAN_MULTIRES);
 
1975
        bmesh_edit_begin(bm, BMO_OPTYPE_FLAG_UNTAN_MULTIRES | BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH);
1954
1976
 
1955
1977
        /* BMESH_TODO this should be valid now, leaving here until we can ensure this - campbell */
1956
1978
        i = 0;
1994
2016
                i++;
1995
2017
 
1996
2018
                if (kfe->e && kfe->v1->v == kfe->e->v1 && kfe->v2->v == kfe->e->v2) {
1997
 
                        kfe->oe = kfe->e;
 
2019
                        kfe->e_old = kfe->e;
1998
2020
                        continue;
1999
2021
                }
2000
2022
 
2001
2023
                j++;
2002
2024
 
2003
2025
                if (kfe->e) {
2004
 
                        kfe->oe = kfe->e;
 
2026
                        kfe->e_old = kfe->e;
2005
2027
 
2006
2028
                        BMO_elem_flag_enable(bm, kfe->e, DEL);
2007
2029
                        BMO_elem_flag_disable(bm, kfe->e, BOUNDARY);
2027
2049
 
2028
2050
                if (!kfe->v1 || !kfe->v2 || kfe->v1->inspace || kfe->v2->inspace)
2029
2051
                        continue;
2030
 
                if (!(kfe->oe && kfe->v1->v == kfe->oe->v1 && kfe->v2->v == kfe->oe->v2))
 
2052
                if (!(kfe->e_old && kfe->v1->v == kfe->e_old->v1 && kfe->v2->v == kfe->e_old->v2))
2031
2053
                        continue;
2032
2054
 
2033
2055
                k++;
2034
2056
 
2035
2057
                BMO_elem_flag_enable(bm, kfe->e, BOUNDARY);
2036
 
                kfe->oe = kfe->e;
 
2058
                kfe->e_old = kfe->e;
2037
2059
 
2038
2060
                for (ref = kfe->faces.first; ref; ref = ref->next) {
2039
2061
                        f = ref->ref;
2046
2068
                }
2047
2069
        }
2048
2070
 
2049
 
        BLI_srand(0);
 
2071
        rng = BLI_rng_new(0);
2050
2072
 
2051
2073
        for (i = 0; i < totface; i++) {
2052
2074
                SmallHash *hash = &shash;
2064
2086
                BLI_scanfill_begin(&sf_ctx);
2065
2087
 
2066
2088
                for (entry = face_nets[i].first; entry; entry = entry->next) {
2067
 
                        if (!BLI_smallhash_haskey(hash, (intptr_t)entry->kfe->v1)) {
 
2089
                        if (!BLI_smallhash_haskey(hash, (uintptr_t)entry->kfe->v1)) {
2068
2090
                                sf_vert = BLI_scanfill_vert_add(&sf_ctx, entry->kfe->v1->v->co);
2069
2091
                                sf_vert->poly_nr = 0;
2070
 
                                rnd_offset_co(sf_vert->co, rndscale);
 
2092
                                rnd_offset_co(rng, sf_vert->co, rndscale);
2071
2093
                                sf_vert->tmp.p = entry->kfe->v1->v;
2072
 
                                BLI_smallhash_insert(hash, (intptr_t)entry->kfe->v1, sf_vert);
 
2094
                                BLI_smallhash_insert(hash, (uintptr_t)entry->kfe->v1, sf_vert);
2073
2095
                        }
2074
2096
 
2075
 
                        if (!BLI_smallhash_haskey(hash, (intptr_t)entry->kfe->v2)) {
 
2097
                        if (!BLI_smallhash_haskey(hash, (uintptr_t)entry->kfe->v2)) {
2076
2098
                                sf_vert = BLI_scanfill_vert_add(&sf_ctx, entry->kfe->v2->v->co);
2077
2099
                                sf_vert->poly_nr = 0;
2078
 
                                rnd_offset_co(sf_vert->co, rndscale);
 
2100
                                rnd_offset_co(rng, sf_vert->co, rndscale);
2079
2101
                                sf_vert->tmp.p = entry->kfe->v2->v;
2080
 
                                BLI_smallhash_insert(hash, (intptr_t)entry->kfe->v2, sf_vert);
 
2102
                                BLI_smallhash_insert(hash, (uintptr_t)entry->kfe->v2, sf_vert);
2081
2103
                        }
2082
2104
                }
2083
2105
 
2084
2106
                for (j = 0, entry = face_nets[i].first; entry; entry = entry->next, j++) {
2085
 
                        sf_vert_last = BLI_smallhash_lookup(hash, (intptr_t)entry->kfe->v1);
2086
 
                        sf_vert = BLI_smallhash_lookup(hash, (intptr_t)entry->kfe->v2);
 
2107
                        sf_vert_last = BLI_smallhash_lookup(hash, (uintptr_t)entry->kfe->v1);
 
2108
                        sf_vert = BLI_smallhash_lookup(hash, (uintptr_t)entry->kfe->v2);
2087
2109
 
2088
2110
                        sf_vert->poly_nr++;
2089
2111
                        sf_vert_last->poly_nr++;
2090
2112
                }
2091
2113
 
2092
2114
                for (j = 0, entry = face_nets[i].first; entry; entry = entry->next, j++) {
2093
 
                        sf_vert_last = BLI_smallhash_lookup(hash, (intptr_t)entry->kfe->v1);
2094
 
                        sf_vert = BLI_smallhash_lookup(hash, (intptr_t)entry->kfe->v2);
 
2115
                        sf_vert_last = BLI_smallhash_lookup(hash, (uintptr_t)entry->kfe->v1);
 
2116
                        sf_vert = BLI_smallhash_lookup(hash, (uintptr_t)entry->kfe->v2);
2095
2117
 
2096
2118
                        if (sf_vert->poly_nr > 1 && sf_vert_last->poly_nr > 1) {
2097
2119
                                ScanFillEdge *sf_edge;
2098
2120
                                sf_edge = BLI_scanfill_edge_add(&sf_ctx, sf_vert_last, sf_vert);
2099
 
                                if (entry->kfe->oe)
 
2121
                                if (entry->kfe->e_old)
2100
2122
                                        sf_edge->f = SF_EDGE_BOUNDARY;  /* mark as original boundary edge */
2101
2123
 
2102
2124
                                BMO_elem_flag_disable(bm, entry->kfe->e->v1, DEL);
2125
2147
 
2126
2148
                        f2 = BM_face_create_quad_tri(bm,
2127
2149
                                                     v1, v2, v3, NULL,
2128
 
                                                     NULL, FALSE);
 
2150
                                                     NULL, false);
2129
2151
 
2130
2152
                        BMO_elem_flag_enable(bm, f2, FACE_NEW);
2131
2153
 
2165
2187
                BM_elem_attrs_copy(bm, bm, f2, f);
2166
2188
 
2167
2189
                BM_ITER_ELEM (l1, &liter1, f, BM_LOOPS_OF_FACE) {
2168
 
                        BM_loop_interp_from_face(bm, l1, f2, TRUE, TRUE);
 
2190
                        BM_loop_interp_from_face(bm, l1, f2, true, true);
2169
2191
                }
2170
2192
        }
2171
2193
 
2182
2204
        if (faces)
2183
2205
                MEM_freeN(faces);
2184
2206
        BLI_memarena_free(arena);
 
2207
        BLI_rng_free(rng);
2185
2208
 
2186
2209
        BMO_error_clear(bm); /* remerge_faces sometimes raises errors, so make sure to clear them */
2187
2210
 
2188
 
        bmesh_edit_end(bm, BMO_OP_FLAG_UNTAN_MULTIRES);
 
2211
        bmesh_edit_end(bm, BMO_OPTYPE_FLAG_UNTAN_MULTIRES | BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH);
2189
2212
        BMO_pop(bm);
2190
2213
}
2191
2214
 
2192
2215
#else  /* use direct (non-scanfill) method for cuts */
2193
2216
 
2194
 
/* assuming v is on line ab, what fraction of the way is v from a to b? */
2195
 
static float frac_along(const float a[3], const float b[3], const float v[3])
2196
 
{
2197
 
        float lab;
2198
 
 
2199
 
        lab = len_v3v3(a, b);
2200
 
        if (lab == 0.0f) {
2201
 
                return 0.0f;
2202
 
        }
2203
 
        else {
2204
 
                return len_v3v3(a, v) / lab;
2205
 
        }
2206
 
}
2207
 
 
2208
2217
/* sort list of kverts by fraction along edge e */
2209
2218
static void sort_by_frac_along(ListBase *lst, BMEdge *e)
2210
2219
{
2211
 
        KnifeVert *vcur, *vprev;
2212
 
        float *v1co, *v2co;
 
2220
        /* note, since we know the point is along the edge, sort from distance to v1co */
 
2221
        const float *v1co = e->v1->co;
 
2222
//      const float *v2co = e->v2->co;
2213
2223
        Ref *cur = NULL, *prev = NULL, *next = NULL;
2214
2224
 
2215
2225
        if (lst->first == lst->last)
2216
2226
                return;
2217
2227
 
2218
 
        v1co = e->v1->co;
2219
 
        v2co = e->v2->co;
2220
 
 
2221
2228
        for (cur = ((Ref *)lst->first)->next; cur; cur = next) {
 
2229
                KnifeVert *vcur = cur->ref;
 
2230
#if 0
 
2231
                const float vcur_fac = line_point_factor_v3(vcur->co, v1co, v2co);
 
2232
#else
 
2233
                const float vcur_fac = len_squared_v3v3(v1co, vcur->co);
 
2234
#endif
 
2235
 
2222
2236
                next = cur->next;
2223
2237
                prev = cur->prev;
2224
2238
 
2225
2239
                BLI_remlink(lst, cur);
2226
2240
 
2227
 
                vcur = cur->ref;
2228
2241
                while (prev) {
2229
 
                        vprev = prev->ref;
2230
 
                        if (frac_along(v1co, v2co, vprev->co) <= frac_along(v1co, v2co, vcur->co))
2231
 
                                break;
 
2242
                        KnifeVert *vprev = prev->ref;
 
2243
#if 0
 
2244
                        if (line_point_factor_v3(vprev->co, v1co, v2co) <= vcur_fac)
 
2245
                                break;
 
2246
#else
 
2247
                        if (len_squared_v3v3(v1co, vprev->co) <= vcur_fac)
 
2248
                                break;
 
2249
#endif
2232
2250
                        prev = prev->prev;
2233
2251
                }
2234
2252
 
2239
2257
/* The chain so far goes from an instantiated vertex to kfv (some may be reversed).
2240
2258
 * If possible, complete the chain to another instantiated vertex and return 1, else return 0.
2241
2259
 * The visited hash says which KnifeVert's have already been tried, not including kfv. */
2242
 
static int find_chain_search(KnifeTool_OpData *kcd, KnifeVert *kfv, ListBase *fedges, SmallHash *visited,
2243
 
                             ListBase *chain)
 
2260
static bool find_chain_search(KnifeTool_OpData *kcd, KnifeVert *kfv, ListBase *fedges, SmallHash *visited,
 
2261
                              ListBase *chain)
2244
2262
{
2245
2263
        Ref *r;
2246
2264
        KnifeEdge *kfe;
2247
2265
        KnifeVert *kfv_other;
2248
2266
 
2249
2267
        if (kfv->v)
2250
 
                return TRUE;
 
2268
                return true;
2251
2269
 
2252
2270
        BLI_smallhash_insert(visited, (uintptr_t)kfv, NULL);
2253
2271
        /* Try all possible next edges. Could either go through fedges
2264
2282
                if (kfv_other && !BLI_smallhash_haskey(visited, (uintptr_t)kfv_other)) {
2265
2283
                        knife_append_list(kcd, chain, kfe);
2266
2284
                        if (find_chain_search(kcd, kfv_other, fedges, visited, chain))
2267
 
                                return TRUE;
 
2285
                                return true;
2268
2286
                        BLI_remlink(chain, chain->last);
2269
2287
                }
2270
2288
        }
2271
 
        return FALSE;
 
2289
        return false;
2272
2290
}
2273
2291
 
2274
2292
static ListBase *find_chain_from_vertex(KnifeTool_OpData *kcd, KnifeEdge *kfe, BMVert *v, ListBase *fedges)
2275
2293
{
2276
2294
        SmallHash visited_, *visited = &visited_;
2277
2295
        ListBase *ans;
2278
 
        int found;
 
2296
        bool found;
2279
2297
 
2280
2298
        ans = knife_empty_list(kcd);
2281
2299
        knife_append_list(kcd, ans, kfe);
2282
 
        found = 0;
 
2300
        found = false;
2283
2301
        BLI_smallhash_init(visited);
2284
2302
        if (kfe->v1->v == v) {
2285
2303
                BLI_smallhash_insert(visited, (uintptr_t)(kfe->v1), NULL);
2340
2358
/* The hole so far goes from kfvfirst to kfv (some may be reversed).
2341
2359
 * If possible, complete the hole back to kfvfirst and return 1, else return 0.
2342
2360
 * The visited hash says which KnifeVert's have already been tried, not including kfv or kfvfirst. */
2343
 
static int find_hole_search(KnifeTool_OpData *kcd, KnifeVert *kfvfirst, KnifeVert *kfv, ListBase *fedges,
2344
 
                            SmallHash *visited, ListBase *hole)
 
2361
static bool find_hole_search(KnifeTool_OpData *kcd, KnifeVert *kfvfirst, KnifeVert *kfv, ListBase *fedges,
 
2362
                             SmallHash *visited, ListBase *hole)
2345
2363
{
2346
2364
        Ref *r;
2347
2365
        KnifeEdge *kfe, *kfelast;
2348
2366
        KnifeVert *kfv_other;
2349
2367
 
2350
2368
        if (kfv == kfvfirst)
2351
 
                return TRUE;
 
2369
                return true;
2352
2370
 
2353
2371
        BLI_smallhash_insert(visited, (uintptr_t)kfv, NULL);
2354
2372
        kfelast = ((Ref *)hole->last)->ref;
2366
2384
                if (kfv_other && !BLI_smallhash_haskey(visited, (uintptr_t)kfv_other)) {
2367
2385
                        knife_append_list(kcd, hole, kfe);
2368
2386
                        if (find_hole_search(kcd, kfvfirst, kfv_other, fedges, visited, hole))
2369
 
                                return TRUE;
 
2387
                                return true;
2370
2388
                        BLI_remlink(hole, hole->last);
2371
2389
                }
2372
2390
        }
2373
 
        return FALSE;
 
2391
        return false;
2374
2392
}
2375
2393
 
2376
2394
/* Find a hole (simple cycle with no instantiated vertices).
2381
2399
        Ref *r, *ref;
2382
2400
        KnifeEdge *kfe;
2383
2401
        SmallHash visited_, *visited = &visited_;
2384
 
        int found;
 
2402
        bool found;
2385
2403
 
2386
2404
        ans = NULL;
2387
 
        found = FALSE;
 
2405
        found = false;
2388
2406
 
2389
2407
        for (r = fedges->first; r && !found; r = r->next) {
2390
2408
                kfe = r->ref;
2415
2433
}
2416
2434
 
2417
2435
/* Try to find "nice" diagonals - short, and far apart from each other.
2418
 
 * If found, return TRUE and make a 'main chain' going across f which uses
 
2436
 * If found, return true and make a 'main chain' going across f which uses
2419
2437
 * the two diagonals and one part of the hole, and a 'side chain' that
2420
2438
 * completes the hole. */
2421
 
static int find_hole_chains(KnifeTool_OpData *kcd, ListBase *hole, BMFace *f, ListBase **mainchain,
2422
 
                            ListBase **sidechain)
 
2439
static bool find_hole_chains(KnifeTool_OpData *kcd, ListBase *hole, BMFace *f, ListBase **mainchain,
 
2440
                             ListBase **sidechain)
2423
2441
{
2424
2442
        float **fco, **hco;
2425
2443
        BMVert **fv;
2431
2449
        ListBase *chain;
2432
2450
        BMVert *v;
2433
2451
        BMIter iter;
2434
 
        int nh, nf, i, j, k, m, ax, ay, ok, sep = 0 /* Quite warnings */, bestsep;
 
2452
        int nh, nf, i, j, k, m, ax, ay, sep = 0 /* Quite warnings */, bestsep;
2435
2453
        int besti[2], bestj[2];
2436
2454
        float d, bestd;
2437
2455
 
2438
2456
        nh = BLI_countlist(hole);
2439
2457
        nf = f->len;
2440
2458
        if (nh < 2 || nf < 3)
2441
 
                return 0;
 
2459
                return false;
2442
2460
 
2443
2461
        /* Gather 2d projections of hole and face vertex coordinates.
2444
2462
         * Use best-axis projection - not completely accurate, maybe revisit */
2499
2517
                                bestd = FLT_MAX;
2500
2518
                        }
2501
2519
                        for (j = 0; j < nf; j++) {
 
2520
                                bool ok;
 
2521
 
2502
2522
                                if (m == 1 && j == bestj[0])
2503
2523
                                        continue;
2504
2524
                                d = len_squared_v2v2(hco[i], fco[j]);
2505
2525
                                if (d > bestd)
2506
2526
                                        continue;
2507
2527
 
2508
 
                                ok = TRUE;
 
2528
                                ok = true;
2509
2529
                                for (k = 0; k < nh && ok; k++) {
2510
2530
                                        if (k == i || (k + 1) % nh == i)
2511
2531
                                                continue;
2512
2532
                                        if (isect_line_line_v2(hco[i], fco[j], hco[k], hco[(k + 1) % nh]))
2513
 
                                                ok = FALSE;
 
2533
                                                ok = false;
2514
2534
                                }
2515
2535
                                if (!ok)
2516
2536
                                        continue;
2518
2538
                                        if (k == j || (k + 1) % nf == j)
2519
2539
                                                continue;
2520
2540
                                        if (isect_line_line_v2(hco[i], fco[j], fco[k], fco[(k + 1) % nf]))
2521
 
                                                ok = FALSE;
 
2541
                                                ok = false;
2522
2542
                                }
2523
2543
                                if (ok) {
2524
2544
                                        besti[m] = i;
2553
2573
                }
2554
2574
                *sidechain = chain;
2555
2575
 
2556
 
                return TRUE;
 
2576
                return true;
2557
2577
        }
2558
2578
        else {
2559
 
                return FALSE;
 
2579
                return false;
2560
2580
        }
2561
2581
}
2562
2582
 
2563
 
static int knife_edge_in_face(KnifeTool_OpData *UNUSED(kcd), KnifeEdge *kfe, BMFace *f)
 
2583
static bool knife_edge_in_face(KnifeTool_OpData *UNUSED(kcd), KnifeEdge *kfe, BMFace *f)
2564
2584
{
2565
2585
        /* BMesh *bm = kcd->em->bm; */ /* UNUSED */
2566
2586
        BMVert *v1, *v2;
2570
2590
        int v1inside, v2inside;
2571
2591
 
2572
2592
        if (!f)
2573
 
                return FALSE;
 
2593
                return false;
2574
2594
 
2575
2595
        v1 = kfe->v1->v;
2576
2596
        v2 = kfe->v2->v;
2589
2609
        v1inside = l1 ? 0 : BM_face_point_inside_test(f, kfe->v1->co);
2590
2610
        v2inside = l2 ? 0 : BM_face_point_inside_test(f, kfe->v2->co);
2591
2611
        if ((l1 && v2inside) || (l2 && v1inside) || (v1inside && v2inside))
2592
 
                return TRUE;
 
2612
                return true;
2593
2613
        if (l1 && l2) {
2594
2614
                /* Can have case where v1 and v2 are on shared chain between two faces.
2595
2615
                 * BM_face_legal_splits does visibility and self-intersection tests,
2598
2618
                mid_v3_v3v3(mid, kfe->v1->co, kfe->v2->co);
2599
2619
                return BM_face_point_inside_test(f, mid);
2600
2620
        }
2601
 
        return FALSE;
 
2621
        return false;
2602
2622
}
2603
2623
 
2604
2624
/* Split face f with KnifeEdges on chain.  f remains as one side, the face formed is put in *newface.
2639
2659
                        *newface = NULL;
2640
2660
                }
2641
2661
                else {
2642
 
                        *newface = BM_face_split(bm, f, v1, v2, &lnew, NULL, TRUE);
 
2662
                        *newface = BM_face_split(bm, f, v1, v2, &lnew, NULL, true);
2643
2663
                }
2644
2664
        }
2645
2665
        else {
2651
2671
                        for (l_iter = lnew->next, i = 0; i < nco; l_iter = l_iter->next, i++) {
2652
2672
                                BLI_assert(equals_v3v3(cos[i], l_iter->v->co));
2653
2673
                                if (kcd->select_result) {
2654
 
                                        BM_edge_select_set(bm, l_iter->e, TRUE);
 
2674
                                        BM_edge_select_set(bm, l_iter->e, true);
2655
2675
                                }
2656
2676
                                kverts[i]->v = l_iter->v;
2657
2677
                        }
2661
2681
        /* the select chain above doesnt account for the first loop */
2662
2682
        if (kcd->select_result) {
2663
2683
                if (lnew) {
2664
 
                        BM_edge_select_set(bm, lnew->e, TRUE);
 
2684
                        BM_edge_select_set(bm, lnew->e, true);
2665
2685
                }
2666
2686
        }
2667
2687
}
2698
2718
                if (fnew_kfedges->first)
2699
2719
                        knife_make_face_cuts(kcd, fnew, fnew_kfedges);
2700
2720
 
2701
 
                /* find_chain should always remove edges if it returns TRUE,
 
2721
                /* find_chain should always remove edges if it returns true,
2702
2722
                 * but guard against infinite loop anyway */
2703
2723
                count = BLI_countlist(kfedges);
2704
2724
                if (count >= oldcount) {
2721
2741
                        kfe = ((Ref *)sidechain->first)->ref;
2722
2742
                        if (knife_edge_in_face(kcd, kfe, f)) {
2723
2743
                                knife_make_chain_cut(kcd, f, sidechain, &fnew2);
 
2744
                                if (fnew2 == NULL) {
 
2745
                                        return;
 
2746
                                }
2724
2747
                                fhole = f;
2725
2748
                        }
2726
2749
                        else if (knife_edge_in_face(kcd, kfe, fnew)) {
2727
2750
                                knife_make_chain_cut(kcd, fnew, sidechain, &fnew2);
 
2751
                                if (fnew2 == NULL) {
 
2752
                                        return;
 
2753
                                }
2728
2754
                                fhole = fnew2;
2729
2755
                        }
2730
2756
                        else {
2758
2784
                                knife_make_face_cuts(kcd, fnew2, fnew2_kfedges);
2759
2785
                        if (f == fhole)
2760
2786
                                break;
2761
 
                        /* find_hole should always remove edges if it returns TRUE,
 
2787
                        /* find_hole should always remove edges if it returns true,
2762
2788
                         * but guard against infinite loop anyway */
2763
2789
                        count = BLI_countlist(kfedges);
2764
2790
                        if (count >= oldcount) {
2831
2857
                sort_by_frac_along(lst, e);
2832
2858
                for (ref = lst->first; ref; ref = ref->next) {
2833
2859
                        kfv = ref->ref;
2834
 
                        pct = frac_along(e->v1->co, e->v2->co, kfv->co);
 
2860
                        pct = line_point_factor_v3(kfv->co, e->v1->co, e->v2->co);
2835
2861
                        kfv->v = BM_edge_split(bm, e, e->v1, &enew, pct);
2836
2862
                }
2837
2863
        }
2853
2879
#endif
2854
2880
 
2855
2881
/* called on tool confirmation */
2856
 
static void knifetool_finish(wmOperator *op)
 
2882
static void knifetool_finish_ex(KnifeTool_OpData *kcd)
2857
2883
{
2858
 
        KnifeTool_OpData *kcd = op->customdata;
2859
 
 
2860
2884
#if SCANFILL_CUTS
2861
2885
        knifenet_fill_faces(kcd);
2862
2886
#else
2864
2888
#endif
2865
2889
 
2866
2890
        EDBM_mesh_normals_update(kcd->em);
2867
 
        EDBM_update_generic(kcd->em, TRUE, TRUE);
 
2891
        EDBM_update_generic(kcd->em, true, true);
2868
2892
}
2869
 
 
2870
 
/* copied from paint_image.c */
2871
 
static int project_knife_view_clip(View3D *v3d, RegionView3D *rv3d, float *clipsta, float *clipend)
 
2893
static void knifetool_finish(wmOperator *op)
2872
2894
{
2873
 
        int orth = ED_view3d_clip_range_get(v3d, rv3d, clipsta, clipend);
2874
 
 
2875
 
        if (orth) { /* only needed for ortho */
2876
 
                float fac = 2.0f / ((*clipend) - (*clipsta));
2877
 
                *clipsta *= fac;
2878
 
                *clipend *= fac;
2879
 
        }
2880
 
 
2881
 
        return orth;
 
2895
        KnifeTool_OpData *kcd = op->customdata;
 
2896
        knifetool_finish_ex(kcd);
2882
2897
}
2883
2898
 
2884
2899
static void knife_recalc_projmat(KnifeTool_OpData *kcd)
2885
2900
{
2886
2901
        invert_m4_m4(kcd->ob->imat, kcd->ob->obmat);
2887
2902
        ED_view3d_ob_project_mat_get(kcd->ar->regiondata, kcd->ob, kcd->projmat);
2888
 
        //mult_m4_m4m4(kcd->projmat, kcd->vc.rv3d->winmat, kcd->vc.rv3d->viewmat);
 
2903
        //mul_m4_m4m4(kcd->projmat, kcd->vc.rv3d->winmat, kcd->vc.rv3d->viewmat);
2889
2904
 
2890
 
        kcd->is_ortho = project_knife_view_clip(kcd->vc.v3d, kcd->vc.rv3d, 
2891
 
                                                &kcd->clipsta, &kcd->clipend);
 
2905
        kcd->is_ortho = ED_view3d_clip_range_get(kcd->vc.v3d, kcd->vc.rv3d,
 
2906
                                                 &kcd->clipsta, &kcd->clipend, true);
2892
2907
}
2893
2908
 
2894
2909
/* called when modal loop selection is done... */
2895
 
static void knifetool_exit(bContext *C, wmOperator *op)
 
2910
static void knifetool_exit_ex(bContext *C, KnifeTool_OpData *kcd)
2896
2911
{
2897
 
        KnifeTool_OpData *kcd = op->customdata;
2898
 
 
2899
2912
        if (!kcd)
2900
2913
                return;
2901
2914
 
2902
 
        WM_cursor_restore(CTX_wm_window(C));
 
2915
        if (kcd->is_interactive) {
 
2916
                WM_cursor_restore(CTX_wm_window(C));
2903
2917
 
2904
 
        /* deactivate the extra drawing stuff in 3D-View */
2905
 
        ED_region_draw_cb_exit(kcd->ar->type, kcd->draw_handle);
 
2918
                /* deactivate the extra drawing stuff in 3D-View */
 
2919
                ED_region_draw_cb_exit(kcd->ar->type, kcd->draw_handle);
 
2920
        }
2906
2921
 
2907
2922
        /* free the custom data */
2908
2923
        BLI_mempool_destroy(kcd->refs);
2913
2928
        BLI_ghash_free(kcd->origvertmap, NULL, NULL);
2914
2929
        BLI_ghash_free(kcd->kedgefacemap, NULL, NULL);
2915
2930
 
2916
 
        BMBVH_FreeBVH(kcd->bmbvh);
 
2931
        BKE_bmbvh_free(kcd->bmbvh);
2917
2932
        BLI_memarena_free(kcd->arena);
2918
2933
 
2919
2934
        /* tag for redraw */
2920
2935
        ED_region_tag_redraw(kcd->ar);
2921
2936
 
2922
2937
        if (kcd->cagecos)
2923
 
                MEM_freeN(kcd->cagecos);
 
2938
                MEM_freeN((void *)kcd->cagecos);
2924
2939
 
2925
2940
        if (kcd->linehits)
2926
2941
                MEM_freeN(kcd->linehits);
2927
2942
 
2928
2943
        /* destroy kcd itself */
2929
2944
        MEM_freeN(kcd);
 
2945
}
 
2946
static void knifetool_exit(bContext *C, wmOperator *op)
 
2947
{
 
2948
        KnifeTool_OpData *kcd = op->customdata;
 
2949
        knifetool_exit_ex(C, kcd);
2930
2950
        op->customdata = NULL;
2931
2951
}
2932
2952
 
2933
 
static void cage_mapped_verts_callback(void *userData, int index, const float co[3],
2934
 
                                       const float UNUSED(no_f[3]), const short UNUSED(no_s[3]))
2935
 
{
2936
 
        void **data = userData;
2937
 
        BMEditMesh *em = data[0];
2938
 
        float (*cagecos)[3] = data[1];
2939
 
        SmallHash *hash = data[2];
2940
 
 
2941
 
        if (index >= 0 && index < em->bm->totvert && !BLI_smallhash_haskey(hash, index)) {
2942
 
                BLI_smallhash_insert(hash, index, NULL);
2943
 
                copy_v3_v3(cagecos[index], co);
2944
 
        }
2945
 
}
2946
 
 
2947
 
static void knifetool_update_mval(KnifeTool_OpData *kcd, int mval_i[2])
 
2953
static void knifetool_update_mval(KnifeTool_OpData *kcd, const float mval[2])
2948
2954
{
2949
2955
        knife_recalc_projmat(kcd);
2950
 
        kcd->vc.mval[0] = mval_i[0];
2951
 
        kcd->vc.mval[1] = mval_i[1];
 
2956
        copy_v2_v2(kcd->mval, mval);
2952
2957
 
2953
2958
        if (knife_update_active(kcd)) {
2954
2959
                ED_region_tag_redraw(kcd->ar);
2955
2960
        }
2956
2961
}
2957
2962
 
 
2963
static void knifetool_update_mval_i(KnifeTool_OpData *kcd, const int mval_i[2])
 
2964
{
 
2965
        float mval[2] = {UNPACK2(mval_i)};
 
2966
        knifetool_update_mval(kcd, mval);
 
2967
}
 
2968
 
2958
2969
/* called when modal loop selection gets set up... */
2959
 
static int knifetool_init(bContext *C, wmOperator *op, int UNUSED(do_cut))
 
2970
static void knifetool_init(bContext *C, KnifeTool_OpData *kcd,
 
2971
                           const bool only_select, const bool cut_through, const bool is_interactive)
2960
2972
{
2961
 
        KnifeTool_OpData *kcd;
2962
2973
        Scene *scene = CTX_data_scene(C);
2963
2974
        Object *obedit = CTX_data_edit_object(C);
2964
 
        DerivedMesh *cage, *final;
2965
 
        SmallHash shash;
2966
 
        void *data[3];
2967
 
        const short only_select = RNA_boolean_get(op->ptr, "only_selected");
2968
 
 
2969
 
        /* alloc new customdata */
2970
 
        kcd = op->customdata = MEM_callocN(sizeof(KnifeTool_OpData), "knifetool Modal Op Data");
2971
2975
 
2972
2976
        /* assign the drawing handle for drawing preview line... */
2973
2977
        kcd->ob = obedit;
2974
2978
        kcd->ar = CTX_wm_region(C);
2975
 
        kcd->draw_handle = ED_region_draw_cb_activate(kcd->ar->type, knifetool_draw, kcd, REGION_DRAW_POST_VIEW);
 
2979
 
2976
2980
        em_setup_viewcontext(C, &kcd->vc);
2977
2981
 
2978
 
        kcd->em = BMEdit_FromObject(kcd->ob);
 
2982
        kcd->em = BKE_editmesh_from_object(kcd->ob);
2979
2983
 
2980
2984
        BM_mesh_elem_index_ensure(kcd->em->bm, BM_VERT);
2981
2985
 
2982
 
        cage = editbmesh_get_derived_cage_and_final(scene, obedit, kcd->em, &final, CD_MASK_DERIVEDMESH);
2983
 
        kcd->cagecos = MEM_callocN(sizeof(float) * 3 * kcd->em->bm->totvert, "knife cagecos");
2984
 
        data[0] = kcd->em;
2985
 
        data[1] = kcd->cagecos;
2986
 
        data[2] = &shash;
2987
 
 
2988
 
        BLI_smallhash_init(&shash);
2989
 
        cage->foreachMappedVert(cage, cage_mapped_verts_callback, data);
2990
 
        BLI_smallhash_release(&shash);
2991
 
 
2992
 
        kcd->bmbvh = BMBVH_NewBVH(kcd->em,
2993
 
                                  (BMBVH_USE_CAGE | BMBVH_RETURN_ORIG) |
 
2986
        kcd->cagecos = (const float (*)[3])BKE_editmesh_vertexCos_get(kcd->em, scene, NULL);
 
2987
 
 
2988
        kcd->bmbvh = BKE_bmbvh_new(kcd->em,
 
2989
                                  BMBVH_RETURN_ORIG |
2994
2990
                                  (only_select ? BMBVH_RESPECT_SELECT : BMBVH_RESPECT_HIDDEN),
2995
 
                                  scene, obedit);
 
2991
                                  kcd->cagecos, false);
2996
2992
 
2997
2993
        kcd->arena = BLI_memarena_new(1 << 15, "knife");
2998
2994
        kcd->vthresh = KMAXDIST - 1;
2999
2995
        kcd->ethresh = KMAXDIST;
3000
2996
 
3001
 
        kcd->extend = 1;
 
2997
        kcd->extend = true;
3002
2998
 
3003
2999
        knife_recalc_projmat(kcd);
3004
3000
 
3013
3009
        kcd->kedgefacemap = BLI_ghash_ptr_new("knife origvertmap");
3014
3010
 
3015
3011
        /* cut all the way through the mesh if use_occlude_geometry button not pushed */
3016
 
        kcd->cut_through = !RNA_boolean_get(op->ptr, "use_occlude_geometry");
 
3012
        kcd->is_interactive = is_interactive;
 
3013
        kcd->cut_through = cut_through;
3017
3014
        kcd->only_select = only_select;
3018
3015
 
3019
3016
        /* can't usefully select resulting edges in face mode */
3022
3019
        knife_pos_data_clear(&kcd->curr);
3023
3020
        knife_pos_data_clear(&kcd->prev);
3024
3021
 
3025
 
        knife_init_colors(&kcd->colors);
 
3022
        if (is_interactive) {
 
3023
                kcd->draw_handle = ED_region_draw_cb_activate(kcd->ar->type, knifetool_draw, kcd, REGION_DRAW_POST_VIEW);
3026
3024
 
3027
 
        return 1;
 
3025
                knife_init_colors(&kcd->colors);
 
3026
        }
3028
3027
}
3029
3028
 
3030
3029
static int knifetool_cancel(bContext *C, wmOperator *op)
3034
3033
        return OPERATOR_CANCELLED;
3035
3034
}
3036
3035
 
3037
 
static int knifetool_invoke(bContext *C, wmOperator *op, wmEvent *evt)
 
3036
static int knifetool_invoke(bContext *C, wmOperator *op, const wmEvent *event)
3038
3037
{
 
3038
        const bool only_select = RNA_boolean_get(op->ptr, "only_selected");
 
3039
        const bool cut_through = !RNA_boolean_get(op->ptr, "use_occlude_geometry");
 
3040
 
3039
3041
        KnifeTool_OpData *kcd;
3040
3042
 
3041
3043
        view3d_operator_needs_opengl(C);
3042
3044
 
3043
 
        if (!knifetool_init(C, op, 0))
3044
 
                return OPERATOR_CANCELLED;
 
3045
        /* alloc new customdata */
 
3046
        kcd = op->customdata = MEM_callocN(sizeof(KnifeTool_OpData), __func__);
 
3047
 
 
3048
        knifetool_init(C, kcd, only_select, cut_through, true);
3045
3049
 
3046
3050
        /* add a modal handler for this operator - handles loop selection */
3047
3051
        WM_cursor_modal(CTX_wm_window(C), BC_KNIFECURSOR);
3048
3052
        WM_event_add_modal_handler(C, op);
3049
3053
 
3050
 
        kcd = op->customdata;
3051
 
        knifetool_update_mval(kcd, evt->mval);
 
3054
        knifetool_update_mval_i(kcd, event->mval);
3052
3055
 
3053
3056
        knife_update_header(C, kcd);
3054
3057
 
3119
3122
        return keymap;
3120
3123
}
3121
3124
 
3122
 
static int knifetool_modal(bContext *C, wmOperator *op, wmEvent *event)
 
3125
static int knifetool_modal(bContext *C, wmOperator *op, const wmEvent *event)
3123
3126
{
3124
3127
        Object *obedit = CTX_data_edit_object(C);
3125
3128
        KnifeTool_OpData *kcd = op->customdata;
3126
 
        int do_refresh = FALSE;
 
3129
        bool do_refresh = false;
3127
3130
 
3128
 
        if (!obedit || obedit->type != OB_MESH || BMEdit_FromObject(obedit) != kcd->em) {
 
3131
        if (!obedit || obedit->type != OB_MESH || BKE_editmesh_from_object(obedit) != kcd->em) {
3129
3132
                knifetool_exit(C, op);
3130
3133
                ED_area_headerprint(CTX_wm_area(C), NULL);
3131
3134
                return OPERATOR_FINISHED;
3158
3161
 
3159
3162
                                return OPERATOR_FINISHED;
3160
3163
                        case KNF_MODAL_MIDPOINT_ON:
3161
 
                                kcd->snap_midpoints = 1;
 
3164
                                kcd->snap_midpoints = true;
3162
3165
 
3163
3166
                                knife_recalc_projmat(kcd);
3164
3167
                                knife_update_active(kcd);
3165
3168
                                knife_update_header(C, kcd);
3166
3169
                                ED_region_tag_redraw(kcd->ar);
3167
 
                                do_refresh = TRUE;
 
3170
                                do_refresh = true;
3168
3171
                                break;
3169
3172
                        case KNF_MODAL_MIDPOINT_OFF:
3170
 
                                kcd->snap_midpoints = 0;
 
3173
                                kcd->snap_midpoints = false;
3171
3174
 
3172
3175
                                knife_recalc_projmat(kcd);
3173
3176
                                knife_update_active(kcd);
3174
3177
                                knife_update_header(C, kcd);
3175
3178
                                ED_region_tag_redraw(kcd->ar);
3176
 
                                do_refresh = TRUE;
 
3179
                                do_refresh = true;
3177
3180
                                break;
3178
3181
                        case KNF_MODEL_IGNORE_SNAP_ON:
3179
3182
                                ED_region_tag_redraw(kcd->ar);
3180
 
                                kcd->ignore_vert_snapping = kcd->ignore_edge_snapping = 1;
 
3183
                                kcd->ignore_vert_snapping = kcd->ignore_edge_snapping = true;
3181
3184
                                knife_update_header(C, kcd);
3182
 
                                do_refresh = TRUE;
 
3185
                                do_refresh = true;
3183
3186
                                break;
3184
3187
                        case KNF_MODEL_IGNORE_SNAP_OFF:
3185
3188
                                ED_region_tag_redraw(kcd->ar);
3186
 
                                kcd->ignore_vert_snapping = kcd->ignore_edge_snapping = 0;
 
3189
                                kcd->ignore_vert_snapping = kcd->ignore_edge_snapping = false;
3187
3190
                                knife_update_header(C, kcd);
3188
 
                                do_refresh = TRUE;
 
3191
                                do_refresh = true;
3189
3192
                                break;
3190
3193
                        case KNF_MODAL_ANGLE_SNAP_TOGGLE:
3191
3194
                                kcd->angle_snapping = !kcd->angle_snapping;
3192
3195
                                knife_update_header(C, kcd);
3193
 
                                do_refresh = TRUE;
 
3196
                                do_refresh = true;
3194
3197
                                break;
3195
3198
                        case KNF_MODAL_CUT_THROUGH_TOGGLE:
3196
3199
                                kcd->cut_through = !kcd->cut_through;
3197
3200
                                knife_update_header(C, kcd);
3198
 
                                do_refresh = TRUE;
 
3201
                                do_refresh = true;
3199
3202
                                break;
3200
3203
                        case KNF_MODAL_NEW_CUT:
3201
3204
                                ED_region_tag_redraw(kcd->ar);
3241
3244
 
3242
3245
                        case MOUSEMOVE: /* mouse moved somewhere to select another loop */
3243
3246
                                if (kcd->mode != MODE_PANNING) {
3244
 
                                        knifetool_update_mval(kcd, event->mval);
 
3247
                                        knifetool_update_mval_i(kcd, event->mval);
3245
3248
                                }
3246
3249
 
3247
3250
                                break;
3251
3254
        if (do_refresh) {
3252
3255
                /* we don't really need to update mval,
3253
3256
                 * but this happens to be the best way to refresh at the moment */
3254
 
                knifetool_update_mval(kcd, event->mval);
 
3257
                knifetool_update_mval_i(kcd, event->mval);
3255
3258
        }
3256
3259
 
3257
3260
        /* keep going until the user confirms */
3274
3277
        /* flags */
3275
3278
        ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING;
3276
3279
 
3277
 
        RNA_def_boolean(ot->srna, "use_occlude_geometry", TRUE, "Occlude Geometry", "Only cut the front most geometry");
3278
 
        RNA_def_boolean(ot->srna, "only_selected", FALSE, "Only Selected", "Only cut selected geometry");
 
3280
        RNA_def_boolean(ot->srna, "use_occlude_geometry", true, "Occlude Geometry", "Only cut the front most geometry");
 
3281
        RNA_def_boolean(ot->srna, "only_selected", false, "Only Selected", "Only cut selected geometry");
 
3282
}
 
3283
 
 
3284
 
 
3285
/* -------------------------------------------------------------------- */
 
3286
/* Knife tool as a utility function
 
3287
 * that can be used for internal slicing operations */
 
3288
 
 
3289
/**
 
3290
 * Return a point inside the face.
 
3291
 *
 
3292
 * tessellation here seems way overkill,
 
3293
 * but without this its very hard to know of a point is inside the face
 
3294
 */
 
3295
static void edvm_mesh_knife_face_point(BMFace *f, float r_cent[3])
 
3296
{
 
3297
        int tottri = f->len - 2;
 
3298
        BMLoop **loops     = BLI_array_alloca(loops, f->len);
 
3299
        int    (*index)[3] = BLI_array_alloca(index, tottri);
 
3300
        int j;
 
3301
 
 
3302
        float const *best_co[3] = {NULL};
 
3303
        float  best_area  = -1.0f;
 
3304
        bool ok = false;
 
3305
 
 
3306
        tottri = BM_face_calc_tessellation(f, loops, index);
 
3307
        BLI_assert(tottri <= f->len - 2);
 
3308
 
 
3309
        for (j = 0; j < tottri; j++) {
 
3310
                const float *p1 = loops[index[j][0]]->v->co;
 
3311
                const float *p2 = loops[index[j][1]]->v->co;
 
3312
                const float *p3 = loops[index[j][2]]->v->co;
 
3313
                float area;
 
3314
 
 
3315
                float cross[3];
 
3316
                cross_v3_v3v3(cross, p2, p3);
 
3317
                area = fabsf(dot_v3v3(p1, cross));
 
3318
                if (area > best_area) {
 
3319
                        best_co[0] = p1;
 
3320
                        best_co[1] = p2;
 
3321
                        best_co[2] = p3;
 
3322
                        best_area = area;
 
3323
                        ok = true;
 
3324
                }
 
3325
        }
 
3326
 
 
3327
        if (ok) {
 
3328
                mid_v3_v3v3v3(r_cent, best_co[0], best_co[1], best_co[2]);
 
3329
        }
 
3330
        else {
 
3331
                mid_v3_v3v3v3(r_cent, loops[0]->v->co, loops[1]->v->co, loops[2]->v->co);
 
3332
        }
 
3333
}
 
3334
 
 
3335
static bool edbm_mesh_knife_face_isect(ARegion *ar, LinkNode *polys, BMFace *f, float projmat[4][4])
 
3336
{
 
3337
        float cent_ss[2];
 
3338
        float cent[3];
 
3339
 
 
3340
        edvm_mesh_knife_face_point(f, cent);
 
3341
 
 
3342
        ED_view3d_project_float_v2_m4(ar, cent, cent_ss, projmat);
 
3343
 
 
3344
        /* check */
 
3345
        {
 
3346
                LinkNode *p = polys;
 
3347
                int isect = 0;
 
3348
 
 
3349
                while (p) {
 
3350
                        const float (*mval_fl)[2] = p->link;
 
3351
                        const int mval_tot = MEM_allocN_len(mval_fl) / sizeof(*mval_fl);
 
3352
                        isect += (int)isect_point_poly_v2(cent_ss, mval_fl, mval_tot - 1);
 
3353
                        p = p->next;
 
3354
                }
 
3355
 
 
3356
                if (isect % 2) {
 
3357
                        return true;
 
3358
                }
 
3359
        }
 
3360
 
 
3361
        return false;
 
3362
}
 
3363
 
 
3364
/**
 
3365
 * \param use_tag  When set, tag all faces inside the polylines.
 
3366
 */
 
3367
void EDBM_mesh_knife(bContext *C, LinkNode *polys, bool use_tag)
 
3368
{
 
3369
        KnifeTool_OpData *kcd;
 
3370
 
 
3371
        view3d_operator_needs_opengl(C);
 
3372
 
 
3373
        /* init */
 
3374
        {
 
3375
                const bool only_select = false;
 
3376
                const bool cut_through = false;
 
3377
                const bool is_interactive = false;  /* can enable for testing */
 
3378
 
 
3379
                kcd = MEM_callocN(sizeof(KnifeTool_OpData), __func__);
 
3380
 
 
3381
                knifetool_init(C, kcd, only_select, cut_through, is_interactive);
 
3382
 
 
3383
                kcd->ignore_edge_snapping = true;
 
3384
                kcd->ignore_vert_snapping = true;
 
3385
 
 
3386
                if (use_tag) {
 
3387
                        BM_mesh_elem_hflag_enable_all(kcd->em->bm, BM_EDGE, BM_ELEM_TAG, false);
 
3388
                }
 
3389
        }
 
3390
 
 
3391
        /* execute */
 
3392
        {
 
3393
                LinkNode *p = polys;
 
3394
 
 
3395
                knife_recalc_projmat(kcd);
 
3396
 
 
3397
                while (p) {
 
3398
                        const float (*mval_fl)[2] = p->link;
 
3399
                        const int mval_tot = MEM_allocN_len(mval_fl) / sizeof(*mval_fl);
 
3400
                        int i;
 
3401
 
 
3402
                        for (i = 0; i < mval_tot; i++) {
 
3403
                                knifetool_update_mval(kcd, mval_fl[i]);
 
3404
                                if (i == 0) {
 
3405
                                        knife_start_cut(kcd);
 
3406
                                        kcd->mode = MODE_DRAGGING;
 
3407
                                }
 
3408
                                else {
 
3409
                                        knife_add_cut(kcd);
 
3410
                                }
 
3411
                        }
 
3412
                        knife_finish_cut(kcd);
 
3413
                        kcd->mode = MODE_IDLE;
 
3414
                        p = p->next;
 
3415
                }
 
3416
        }
 
3417
 
 
3418
        /* finish */
 
3419
        {
 
3420
                knifetool_finish_ex(kcd);
 
3421
 
 
3422
                /* tag faces inside! */
 
3423
                if (use_tag) {
 
3424
                        BMesh *bm = kcd->em->bm;
 
3425
                        float projmat[4][4];
 
3426
 
 
3427
                        BMEdge *e;
 
3428
                        BMIter iter;
 
3429
 
 
3430
                        bool keep_search;
 
3431
 
 
3432
                        ED_view3d_ob_project_mat_get(kcd->ar->regiondata, kcd->ob, projmat);
 
3433
 
 
3434
                        /* use face-loop tag to store if we have intersected */
 
3435
#define F_ISECT_IS_UNKNOWN(f)  BM_elem_flag_test(BM_FACE_FIRST_LOOP(f), BM_ELEM_TAG)
 
3436
#define F_ISECT_SET_UNKNOWN(f) BM_elem_flag_enable(BM_FACE_FIRST_LOOP(f), BM_ELEM_TAG)
 
3437
#define F_ISECT_SET_OUTSIDE(f) BM_elem_flag_disable(BM_FACE_FIRST_LOOP(f), BM_ELEM_TAG)
 
3438
                        {
 
3439
                                BMFace *f;
 
3440
                                BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
 
3441
                                        F_ISECT_SET_UNKNOWN(f);
 
3442
                                        BM_elem_flag_disable(f, BM_ELEM_TAG);
 
3443
                                }
 
3444
                        }
 
3445
 
 
3446
                        /* tag all faces linked to cut edges */
 
3447
                        BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
 
3448
                                /* check are we tagged?, then we are an original face */
 
3449
                                if (BM_elem_flag_test(e, BM_ELEM_TAG) == false) {
 
3450
                                        BMFace *f;
 
3451
                                        BMIter fiter;
 
3452
                                        BM_ITER_ELEM (f, &fiter, e, BM_FACES_OF_EDGE) {
 
3453
                                                if (edbm_mesh_knife_face_isect(kcd->ar, polys, f, projmat)) {
 
3454
                                                        BM_elem_flag_enable(f, BM_ELEM_TAG);
 
3455
                                                }
 
3456
                                        }
 
3457
                                }
 
3458
                        }
 
3459
 
 
3460
                        /* expand tags for faces which are not cut, but are inside the polys */
 
3461
                        do {
 
3462
                                BMFace *f;
 
3463
                                keep_search = false;
 
3464
                                BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
 
3465
                                        if (BM_elem_flag_test(f, BM_ELEM_TAG) == false && (F_ISECT_IS_UNKNOWN(f))) {
 
3466
                                                /* am I connected to a tagged face via an un-tagged edge (ie, not across a cut) */
 
3467
                                                BMLoop *l_first = BM_FACE_FIRST_LOOP(f);
 
3468
                                                BMLoop *l_iter = l_first;
 
3469
                                                bool found = false;
 
3470
 
 
3471
                                                do {
 
3472
                                                        if (BM_elem_flag_test(l_iter->e, BM_ELEM_TAG) != false) {
 
3473
                                                                /* now check if the adjacent faces is tagged */
 
3474
                                                                BMLoop *l_radial_iter = l_iter->radial_next;
 
3475
                                                                if (l_radial_iter != l_iter) {
 
3476
                                                                        do {
 
3477
                                                                                if (BM_elem_flag_test(l_radial_iter->f, BM_ELEM_TAG)) {
 
3478
                                                                                        found = true;
 
3479
                                                                                }
 
3480
                                                                        } while ((l_radial_iter = l_radial_iter->radial_next) != l_iter && (found == false));
 
3481
                                                                }
 
3482
                                                        }
 
3483
                                                } while ((l_iter = l_iter->next) != l_first && (found == false));
 
3484
 
 
3485
                                                if (found) {
 
3486
                                                        if (edbm_mesh_knife_face_isect(kcd->ar, polys, f, projmat)) {
 
3487
                                                                BM_elem_flag_enable(f, BM_ELEM_TAG);
 
3488
                                                                keep_search = true;
 
3489
                                                        }
 
3490
                                                        else {
 
3491
                                                                /* don't loose time on this face again, set it as outside */
 
3492
                                                                F_ISECT_SET_OUTSIDE(f);
 
3493
                                                        }
 
3494
                                                }
 
3495
                                        }
 
3496
                                }
 
3497
                        } while (keep_search);
 
3498
 
 
3499
#undef F_ISECT_IS_UNKNOWN
 
3500
#undef F_ISECT_SET_UNKNOWN
 
3501
#undef F_ISECT_SET_OUTSIDE
 
3502
 
 
3503
                }
 
3504
 
 
3505
                knifetool_exit_ex(C, kcd);
 
3506
                kcd = NULL;
 
3507
        }
3279
3508
}