[Bf-blender-cvs] [e4b24e6e0cd] newboolean: All tri-tri non-coplanar tests work.
Howard Trickey
noreply at git.blender.org
Mon Dec 2 15:05:22 CET 2019
Commit: e4b24e6e0cd20a30b0cc3722be1b7628072f4f8d
Author: Howard Trickey
Date: Mon Oct 7 06:51:17 2019 -0400
Branches: newboolean
https://developer.blender.org/rBe4b24e6e0cd20a30b0cc3722be1b7628072f4f8d
All tri-tri non-coplanar tests work.
===================================================================
A source/blender/bmesh/tools/bmesh_boolean.c
A source/blender/bmesh/tools/bmesh_boolean.h
===================================================================
diff --git a/source/blender/bmesh/tools/bmesh_boolean.c b/source/blender/bmesh/tools/bmesh_boolean.c
new file mode 100644
index 00000000000..151626f8bcd
--- /dev/null
+++ b/source/blender/bmesh/tools/bmesh_boolean.c
@@ -0,0 +1,3345 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/** \file
+ * \ingroup bmesh
+ *
+ * Cut meshes along intersections and boolean operations on the intersections.
+ *
+ * Supported:
+ * - Concave faces.
+ * - Non-planar faces.
+ * - Coplanar intersections
+ * - Custom-data (UV's etc).
+ *
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_alloca.h"
+#include "BLI_bitmap.h"
+#include "BLI_delaunay_2d.h"
+#include "BLI_linklist.h"
+#include "BLI_math.h"
+#include "BLI_memarena.h"
+#include "BLI_utildefines.h"
+
+#include "bmesh.h"
+#include "intern/bmesh_private.h"
+
+#include "bmesh_boolean.h" /* own include */
+
+#include "BLI_strict_flags.h"
+
+#define BOOLDEBUG
+
+/* NOTE: Work in progress. Initial implementation using slow data structures and algorithms
+ * just to get the correct calculations down. After that, will replace data structures with
+ * faster-lookup versions (hash tables, kd-trees, bvh structures) and will parallelize.
+ */
+
+/* A set of integers, where each member gets an index
+ * that can be used to access the member.
+ * TODO: faster structure for lookup.
+ */
+typedef struct IndexedIntSet {
+ LinkNodePair listhead; /* links are ints */
+ int size;
+} IndexedIntSet;
+
+/* A map from int -> int.
+ * TODO: faster structure for lookup.
+ */
+typedef struct IntIntMap {
+ LinkNodePair listhead; /* Links are pointers to IntPair, allocated from arena. */
+} IntIntMap;
+
+typedef struct IntPair {
+ int first;
+ int second;
+} IntPair;
+
+typedef struct IntIntMapIterator {
+ const IntIntMap *map;
+ LinkNode *curlink;
+ IntPair *keyvalue;
+} IntIntMapIterator;
+
+/* A Mesh Interface.
+ * This would be an abstract interface in C++,
+ * but similate that effect in C.
+ * Idea is to write the rest of the code so that
+ * it will work with either Mesh or BMesh as the
+ * concrete representation.
+ * Thus, editmesh and modifier can use the same
+ * code but without need to convert to BMesh (or Mesh).
+ *
+ * Exactly one of bm and me should be non-null.
+ */
+typedef struct IMesh {
+ BMesh *bm;
+ struct Mesh *me;
+} IMesh;
+
+/* MeshAdd holds an incremental addition to an IMesh.
+ * New verts, edges, and faces are given indices starting
+ * beyond those of the underlying IMesh, and that new
+ * geometry is stored here. For edges and faces, the
+ * indices used can be either from the IMesh or from the
+ * new geometry stored here.
+ * Sometimes the new geometric elements are based on
+ * an example element in the underlying IMesh (the example
+ * will be used to copy attributes).
+ * So we store examples here too.
+ */
+typedef struct MeshAdd {
+ LinkNodePair verts; /* Links are NewVerts. */
+ LinkNodePair edges; /* Links are NewEdges. */
+ LinkNodePair faces; /* Links are NewFaces. */
+ int vindex_start; /* Add this to position in verts to get index of new vert. */
+ int eindex_start; /* Add this to position in edges to get index of new edge. */
+ int findex_start; /* Add this to position in faces to get index of new face. */
+ IMesh *im; /* Underlying IMesh. */
+} MeshAdd;
+
+typedef struct NewVert {
+ float co[3];
+ int example; /* If not -1, example vert in IMesh. */
+} NewVert;
+
+typedef struct NewEdge {
+ int v1;
+ int v2;
+ int example; /* If not -1, example edge in IMesh. */
+} NewEdge;
+
+typedef struct NewFace {
+ IntPair *vert_edge_pairs; /* Array of len (vert, edge) pairs. */
+ int len;
+ int example; /* If not -1, example face in IMesh. */
+} NewFace;
+
+/* MeshDelete holds an incremental deletion to an IMesh.
+ * It records the indices of the edges and faces that need
+ * to be deleted. (As of now, we don't have to delete verts
+ * except those that recorded separately as merges.)
+ */
+typedef struct MeshDelete {
+ BLI_bitmap *vert_bmap;
+ BLI_bitmap *edge_bmap;
+ BLI_bitmap *face_bmap;
+ int totvert;
+ int totedge;
+ int totface;
+} MeshDelete;
+
+/* A MeshPart is a subset of the geometry of an IndexMesh,
+ * with some possible additional geometry.
+ * The indices refer to vertex, edges, and faces in the IndexMesh
+ * that this part is based on,
+ * or, if the indices are larger than the total in the IndexMesh,
+ * then it is in extra geometry incrementally added.
+ * Unlike for IndexMesh, the edges implied by faces need not be explicitly
+ * represented here.
+ * Commonly a MeshPart will contain geometry that shares a plane,
+ * and when that is so, the plane member says which plane,
+ * TODO: faster structure for looking up verts, edges, faces.
+ */
+typedef struct MeshPart {
+ double plane[4]; /* First 3 are normal, 4th is signed distance to plane. */
+ double bbmin[3]; /* Bounding box min, with eps padding. */
+ double bbmax[3]; /* Bounding box max, with eps padding. */
+ LinkNode *verts; /* Links are ints (vert indices). */
+ LinkNode *edges; /* Links are ints (edge indices). */
+ LinkNode *faces; /* Links are ints (face indices). */
+} MeshPart;
+
+/* A MeshPartSet set is a set of MeshParts.
+ * For any two distinct elements of the set, either they are not
+ * coplanar or if they are, they are known not to intersect.
+ * TODO: faster structure for looking up by plane.
+ */
+typedef struct MeshPartSet {
+ double bbmin[3];
+ double bbmax[3];
+ LinkNode *meshparts; /* links are MeshParts* */
+ int tot_part;
+ const char *label; /* for debugging */
+} MeshPartSet;
+
+/* An IMeshPlus is an IMesh plus a MeshAdd.
+ * If the element indices are in range for the IMesh, then functions
+ * access those, else they access the MeshAdd.
+ */
+typedef struct IMeshPlus {
+ IMesh *im;
+ MeshAdd *meshadd;
+} IMeshPlus;
+
+/* Result of intersecting two MeshParts.
+ * This only need identify the thngs that probably intersect,
+ * as the actual intersections will be done later, when
+ * parts are self-intersected. Dedup will handle any problems.
+ * It is not necessary to include verts that are part of included
+ * edges, nor edges that are part of included faces.
+ */
+typedef struct PartPartIntersect {
+ LinkNodePair verts; /* Links are vert indices. */
+ LinkNodePair edges; /* Links are edge indices. */
+ LinkNodePair faces; /* Links are face indices. */
+ int a_index;
+ int b_index;
+} PartPartIntersect;
+
+typedef struct BoolState {
+ MemArena *mem_arena;
+ IMesh im;
+ int boolean_mode;
+ double eps;
+ int (*test_fn)(void *elem, void *user_data);
+ void *test_fn_user_data;
+} BoolState;
+
+/* test_fn results used to distinguish parts of mesh. */
+enum { TEST_NONE = -1, TEST_B = 0, TEST_A = 1, TEST_ALL = 2 };
+
+/* Decoration to shut up gnu 'unused function' warning. */
+#ifdef __GNUC__
+# define ATTU __attribute__((unused))
+#else
+# define ATTU
+#endif
+
+#ifdef BOOLDEBUG
+/* For Debugging. */
+# define CO3(v) (v)->co[0], (v)->co[1], (v)->co[2]
+# define F2(v) (v)[0], (v)[1]
+# define F3(v) (v)[0], (v)[1], (v)[2]
+# define F4(v) (v)[0], (v)[1], (v)[2], (v)[3]
+# define BMI(e) BM_elem_index_get(e)
+
+ATTU static void dump_part(const MeshPart *part, const char *label);
+ATTU static void dump_partset(const MeshPartSet *pset);
+ATTU static void dump_partpartintersect(const PartPartIntersect *ppi, const char *label);
+ATTU static void dump_meshadd(const MeshAdd *ma, const char *label);
+ATTU static void dump_meshdelete(const MeshDelete *meshdelete, const char *label);
+ATTU static void dump_intintmap(const IntIntMap *map, const char *label, const char *prefix);
+ATTU static void dump_cdt_input(const CDT_input *cdt, const char *label);
+ATTU static void dump_cdt_result(const CDT_result *cdt, const char *label, const char *prefix);
+#endif
+
+/* Forward declarations of some static functions. */
+static int min_int_in_array(int *array, int len);
+static LinkNode *linklist_shallow_copy_arena(LinkNode *list, struct MemArena *arena);
+static void calc_part_bb_eps(BoolState *bs, MeshPart *part, double eps);
+static bool find_in_intintmap(const IntIntMap *map, int key, int *r_val);
+static int meshadd_totvert(const MeshAdd *meshadd);
+static int meshadd_totedge(const MeshAdd *meshadd);
+static int meshadd_totface(const MeshAdd *meshadd);
+static NewVert *meshadd_get_newvert(const MeshAdd *meshadd, int v);
+static NewEdge *meshadd_get_newedge(const MeshAdd *meshadd, int e);
+static NewFace *meshadd_get_newface(const MeshAdd *meshadd, int f);
+static int meshadd_facelen(const MeshAdd *meshadd, int f);
+static int meshadd_face_vert(const MeshAdd *meshadd, int f, int index);
+static void meshadd_get_vert_co(const MeshAdd *meshadd, int v, float *r_coords);
+static void meshadd_get_edge_verts(const MeshAdd *meshadd, int e, int *r_v1, int *r_v2);
+static bool meshdelete_find_vert(MeshDelete *meshdelete, int v);
+static bool meshdelete_find_edge(MeshDelete *meshdelete, int e);
+static bool meshdelete_find_face(MeshDelete *meshdelete, int f);
+static int find_edge_by_verts_in_meshadd(const MeshAdd *meshadd, int v1, int v2);
+
+/** IndexedIntSet functions. */
+
+static void init_intset(IndexedIntSet *intset)
+{
+ intset->listhead.list = NULL;
+ intset->listhead.last_node = NULL;
+ intset->size = 0;
+}
+
+static int add_int_to_intset(BoolState *bs, IndexedIntSet *intset, int value)
+{
+ int index;
+
+ index = BLI_linklist_index(intset->listhead.list, POINTER_FROM_INT(value));
+ if (index == -1) {
+ BLI_linklist_append_arena(&intset->listhead, POINTER_FROM_INT
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list