2012-02-19 19:31:04 +01:00
|
|
|
/*
|
|
|
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*
|
|
|
|
* Contributor(s): Geoffrey Bantle, Levi Schooley.
|
|
|
|
*
|
|
|
|
* ***** END GPL LICENSE BLOCK *****
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef __BMESH_H__
|
|
|
|
#define __BMESH_H__
|
|
|
|
|
|
|
|
/** \file blender/bmesh/bmesh.h
|
|
|
|
* \ingroup bmesh
|
2012-02-27 21:27:19 +01:00
|
|
|
*
|
|
|
|
* \addtogroup bmesh BMesh
|
|
|
|
*
|
|
|
|
* \brief BMesh is a non-manifold boundary representation designed to replace the current, limited EditMesh structure,
|
|
|
|
* solving many of the design limitations and maintenance issues of EditMesh.
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* \section bm_structure The Structure
|
|
|
|
*
|
|
|
|
* BMesh stores topology in four main element structures:
|
|
|
|
*
|
|
|
|
* - Faces - BMFace
|
|
|
|
* - Loops - BMLoop, (stores per-face-vertex data, UV's, vertex-colors, etc)
|
|
|
|
* - Edges - BMEdge
|
|
|
|
* - Verts - BMVert
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* \subsection bm_header_flags Header Flags
|
|
|
|
* Each element (vertex/edge/face/loop) in a mesh has an associated bit-field called "header flags".
|
|
|
|
*
|
|
|
|
* BMHeader flags should <b>never</b> be read or written to by bmesh operators (see Operators below).
|
|
|
|
*
|
|
|
|
* Access to header flags is done with BM_elem_flag_*() functions.
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* \subsection bm_faces Faces
|
|
|
|
*
|
|
|
|
* Faces in BMesh are stored as a circular linked list of loops. Loops store per-face-vertex data
|
|
|
|
* (amongst other things outlined later in this document), and define the face boundary.
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* \subsection bm_loop The Loop
|
|
|
|
*
|
|
|
|
* Loops define the boundary loop of a face. Each loop logically corresponds to an edge,
|
|
|
|
* which is defined by the loop and next loop's vertices.
|
|
|
|
*
|
|
|
|
* Loops store several handy pointers:
|
|
|
|
*
|
|
|
|
* - BMLoop#v - pointer to the vertex associated with this loop.
|
|
|
|
* - BMLoop#e - pointer to the edge associated with this loop.
|
|
|
|
* - BMLoop#f - pointer to the face associated with this loop.
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* \subsection bm_two_side_face 2-Sided Faces
|
|
|
|
*
|
|
|
|
* There are some situations where you need 2-sided faces (e.g. a face of two vertices).
|
|
|
|
* This is supported by BMesh, but note that such faces should only be used as intermediary steps,
|
|
|
|
* and should not end up in the final mesh.
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* \subsection bm_edges_and_verts Edges and Vertices
|
|
|
|
*
|
|
|
|
* Edges and Vertices in BMesh are much like their counterparts in EditMesh,
|
|
|
|
* except for some members private to the BMesh api.
|
|
|
|
*
|
|
|
|
* \note There can be more then one edge between two vertices in bmesh,
|
|
|
|
* though the rest of blender (e.g. DerivedMesh, CDDM, CCGSubSurf, etc) does not support this.
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* \subsection bm_queries Queries
|
|
|
|
*
|
|
|
|
* The following topological queries are available:
|
|
|
|
*
|
|
|
|
* - Edges/Faces/Loops around a vertex.
|
|
|
|
* - Faces around an edge.
|
|
|
|
* - Loops around an edge.
|
|
|
|
*
|
|
|
|
* These are accessible through the iterator api, which is covered later in this document
|
|
|
|
*
|
|
|
|
* See source/blender/bmesh/bmesh_queries.h for more misc. queries.
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* \section bm_api The BMesh API
|
|
|
|
*
|
|
|
|
* One of the goals of the BMesh API is to make it easy and natural to produce highly maintainable code.
|
|
|
|
* Code duplication, etc are avoided where possible.
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* \subsection bm_iter_api Iterator API
|
|
|
|
*
|
|
|
|
* Most topological queries in BMesh go through an iterator API (see Queries above).
|
|
|
|
* These are defined in bmesh_iterators.h. If you can, please use the #BM_ITER macro in bmesh_iterators.h
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* \subsection bm_walker_api Walker API
|
|
|
|
*
|
|
|
|
* Topological queries that require a stack (e.g. recursive queries) go through the Walker API,
|
|
|
|
* which is defined in bmesh_walkers.h. Currently the "walkers" are hard-coded into the API,
|
|
|
|
* though a mechanism for plugging in new walkers needs to be added at some point.
|
|
|
|
*
|
|
|
|
* Most topological queries should go through these two APIs;
|
|
|
|
* there are additional functions you can use for topological iteration, but their meant for internal bmesh code.
|
|
|
|
*
|
|
|
|
* Note that the walker API supports delimiter flags, to allow the caller to flag elements not to walk past.
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* \subsection bm_ops Operators
|
|
|
|
*
|
|
|
|
* Operators are an integral part of BMesh. Unlike regular blender operators,
|
|
|
|
* BMesh operators <b>bmo's</b> are designed to be nested (e.g. call other operators).
|
|
|
|
*
|
|
|
|
* Each operator has a number of input/output "slots" which are used to pass settings & data into/out of the operator
|
|
|
|
* (and allows for chaining operators together).
|
|
|
|
*
|
|
|
|
* These slots are identified by name, using strings.
|
|
|
|
*
|
|
|
|
* Access to slots is done with BMO_slot_*() functions.
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* \subsection bm_tool_flags Tool Flags
|
|
|
|
*
|
|
|
|
* The BMesh API provides a set of flags for faces, edges and vertices, which are private to an operator.
|
|
|
|
* These flags may be used by the client operator code as needed
|
|
|
|
* (a common example is flagging elements for use in another operator).
|
|
|
|
* Each call to an operator allocates it's own set of tool flags when it's executed,
|
|
|
|
* avoiding flag conflicts between operators.
|
|
|
|
*
|
|
|
|
* These flags should not be confused with header flags, which are used to store persistent flags
|
|
|
|
* (e.g. selection, hide status, etc).
|
|
|
|
*
|
|
|
|
* Access to tool flags is done with BMO_elem_flag_*() functions.
|
|
|
|
*
|
|
|
|
* \warning Operators are never allowed to read or write to header flags.
|
|
|
|
* They act entirely on the data inside their input slots.
|
|
|
|
* For example an operator should not check the selected state of an element,
|
|
|
|
* there are some exceptions to this - some operators check of a face is smooth.
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* \subsection bm_slot_types Slot Types
|
|
|
|
*
|
|
|
|
* The following slot types are available:
|
|
|
|
*
|
|
|
|
* - integer - #BMO_OP_SLOT_INT
|
|
|
|
* - boolean - #BMO_OP_SLOT_BOOL
|
|
|
|
* - float - #BMO_OP_SLOT_FLT
|
|
|
|
* - pointer - #BMO_OP_SLOT_PNT
|
|
|
|
* - element buffer - #BMO_OP_SLOT_ELEMENT_BUF - a list of verts/edges/faces
|
|
|
|
* - map - BMO_OP_SLOT_MAPPING - simple hash map
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* \subsection bm_slot_iter Slot Iterators
|
|
|
|
*
|
|
|
|
* Access to element buffers or maps must go through the slot iterator api, defined in bmesh_operators.h.
|
|
|
|
* Use #BMO_ITER where ever possible.
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* \subsection bm_elem_buf Element Buffers
|
|
|
|
*
|
|
|
|
* The element buffer slot type is used to feed elements (verts/edges/faces) to operators.
|
|
|
|
* Internally they are stored as pointer arrays (which happily has not caused any problems so far).
|
|
|
|
* Many operators take in a buffer of elements, process it,
|
|
|
|
* then spit out a new one; this allows operators to be chained together.
|
|
|
|
*
|
|
|
|
* \note Element buffers may have elements of different types within the same buffer (this is supported by the API.
|
2012-02-19 19:31:04 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
extern "C" {
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "DNA_listBase.h"
|
|
|
|
#include "DNA_customdata_types.h"
|
|
|
|
|
|
|
|
#include "BLI_utildefines.h"
|
|
|
|
|
|
|
|
#include "bmesh_class.h"
|
|
|
|
|
|
|
|
/*forward declarations*/
|
|
|
|
struct Mesh;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* BMHeader
|
|
|
|
*
|
|
|
|
* All mesh elements begin with a BMHeader. This structure
|
|
|
|
* hold several types of data
|
|
|
|
*
|
|
|
|
* 1: The type of the element (vert, edge, loop or face)
|
|
|
|
* 2: Persistant "header" flags/markings (sharp, seam, select, hidden, ect)
|
|
|
|
note that this is different from the "tool" flags.
|
|
|
|
* 3: Unique ID in the bmesh.
|
|
|
|
* 4: some elements for internal record keeping.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* BMHeader->htype (char) */
|
2012-02-27 21:27:19 +01:00
|
|
|
enum {
|
|
|
|
BM_VERT = 1,
|
|
|
|
BM_EDGE = 2,
|
|
|
|
BM_LOOP = 4,
|
|
|
|
BM_FACE = 8
|
|
|
|
};
|
|
|
|
|
|
|
|
#define BM_ALL (BM_VERT | BM_EDGE | BM_LOOP | BM_FACE)
|
2012-02-19 19:31:04 +01:00
|
|
|
|
|
|
|
/* BMHeader->hflag (char) */
|
2012-02-27 21:27:19 +01:00
|
|
|
enum {
|
|
|
|
BM_ELEM_SELECT = (1 << 0),
|
|
|
|
BM_ELEM_HIDDEN = (1 << 1),
|
|
|
|
BM_ELEM_SEAM = (1 << 2),
|
|
|
|
BM_ELEM_SMOOTH = (1 << 3), /* used for faces and edges, note from the user POV,
|
2012-02-19 19:31:04 +01:00
|
|
|
* this is a sharp edge when disabled */
|
|
|
|
|
2012-02-27 21:27:19 +01:00
|
|
|
BM_ELEM_TAG = (1 << 4), /* internal flag, used for ensuring correct normals
|
|
|
|
* during multires interpolation, and any other time
|
|
|
|
* when temp tagging is handy.
|
|
|
|
* always assume dirty & clear before use. */
|
2012-02-19 19:31:04 +01:00
|
|
|
|
2012-02-27 21:27:19 +01:00
|
|
|
/* we have 2 spare flags which is awesome but since we're limited to 8
|
|
|
|
* only add new flags with care! - campbell */
|
|
|
|
/* BM_ELEM_SPARE = (1 << 5), */
|
|
|
|
/* BM_ELEM_SPARE = (1 << 6), */
|
2012-02-26 22:32:20 +01:00
|
|
|
|
2012-02-27 21:27:19 +01:00
|
|
|
BM_ELEM_INTERNAL_TAG = (1 << 7) /* for low level internal API tagging,
|
|
|
|
* since tools may want to tag verts and
|
|
|
|
* not have functions clobber them */
|
|
|
|
};
|
2012-02-19 19:31:04 +01:00
|
|
|
|
|
|
|
/* Mesh Level Ops */
|
|
|
|
extern int bm_mesh_allocsize_default[4];
|
|
|
|
|
|
|
|
/* ob is needed by multires */
|
|
|
|
BMesh *BM_mesh_create(struct Object *ob, const int allocsize[4]);
|
|
|
|
BMesh *BM_mesh_copy(BMesh *bmold);
|
|
|
|
void BM_mesh_free(BMesh *bm);
|
|
|
|
|
|
|
|
/* frees mesh, but not actual BMesh struct */
|
|
|
|
void BM_mesh_data_free(BMesh *bm);
|
2012-02-24 06:56:06 +01:00
|
|
|
void BM_mesh_normals_update(BMesh *bm, const short skip_hidden);
|
2012-02-19 19:31:04 +01:00
|
|
|
|
|
|
|
/* Construction */
|
|
|
|
BMVert *BM_vert_create(BMesh *bm, const float co[3], const BMVert *example);
|
|
|
|
BMEdge *BM_edge_create(BMesh *bm, BMVert *v1, BMVert *v2, const BMEdge *example, int nodouble);
|
|
|
|
BMFace *BM_face_create(BMesh *bm, BMVert **verts, BMEdge **edges, const int len, int nodouble);
|
|
|
|
|
|
|
|
BMFace *BM_face_create_quad_tri_v(BMesh *bm,
|
|
|
|
BMVert **verts, int len,
|
|
|
|
const BMFace *example, const int nodouble);
|
|
|
|
|
|
|
|
/* easier to use version of BM_face_create_quad_tri_v.
|
|
|
|
* creates edges if necassary. */
|
|
|
|
BMFace *BM_face_create_quad_tri(BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4,
|
|
|
|
const BMFace *example, const int nodouble);
|
|
|
|
|
|
|
|
/* makes an ngon from an unordered list of edges. v1 and v2 must be the verts
|
|
|
|
* defining edges[0], and define the winding of the new face. */
|
|
|
|
BMFace *BM_face_create_ngon(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, int len, int nodouble);
|
|
|
|
|
|
|
|
/* stuff for dealing with header flags */
|
2012-02-26 00:41:31 +01:00
|
|
|
#define BM_elem_flag_test( ele, hflag) _bm_elem_flag_test (&(ele)->head, hflag)
|
|
|
|
#define BM_elem_flag_enable( ele, hflag) _bm_elem_flag_enable (&(ele)->head, hflag)
|
|
|
|
#define BM_elem_flag_disable(ele, hflag) _bm_elem_flag_disable (&(ele)->head, hflag)
|
|
|
|
#define BM_elem_flag_set( ele, hflag, val) _bm_elem_flag_set (&(ele)->head, hflag, val)
|
|
|
|
#define BM_elem_flag_toggle( ele, hflag) _bm_elem_flag_toggle (&(ele)->head, hflag)
|
|
|
|
#define BM_elem_flag_merge( ele_a, ele_b) _bm_elem_flag_merge (&(ele_a)->head, &(ele_b)->head)
|
2012-02-25 23:23:40 +01:00
|
|
|
|
2012-02-27 15:57:09 +01:00
|
|
|
BM_INLINE char _bm_elem_flag_test(const BMHeader *head, const char hflag);
|
|
|
|
BM_INLINE void _bm_elem_flag_enable(BMHeader *head, const char hflag);
|
|
|
|
BM_INLINE void _bm_elem_flag_disable(BMHeader *head, const char hflag);
|
|
|
|
BM_INLINE void _bm_elem_flag_set(BMHeader *head, const char hflag, const int val);
|
|
|
|
BM_INLINE void _bm_elem_flag_toggle(BMHeader *head, const char hflag);
|
|
|
|
BM_INLINE void _bm_elem_flag_merge(BMHeader *head_a, BMHeader *head_b);
|
2012-02-19 19:31:04 +01:00
|
|
|
|
|
|
|
/* notes on BM_elem_index_set(...) usage,
|
|
|
|
* Set index is sometimes abused as temp storage, other times we cant be
|
|
|
|
* sure if the index values are valid because certain operations have modified
|
|
|
|
* the mesh structure.
|
|
|
|
*
|
|
|
|
* To set the elements to valid indicies 'BM_mesh_elem_index_ensure' should be used
|
|
|
|
* rather then adding inline loops, however there are cases where we still
|
|
|
|
* set the index directly
|
|
|
|
*
|
|
|
|
* In an attempt to manage this, here are 3 tags Im adding to uses of
|
|
|
|
* 'BM_elem_index_set'
|
|
|
|
*
|
|
|
|
* - 'set_inline' -- since the data is already being looped over set to a
|
|
|
|
* valid value inline.
|
|
|
|
*
|
|
|
|
* - 'set_dirty!' -- intentionally sets the index to an invalid value,
|
|
|
|
* flagging 'bm->elem_index_dirty' so we dont use it.
|
|
|
|
*
|
|
|
|
* - 'set_ok' -- this is valid use since the part of the code is low level.
|
|
|
|
*
|
|
|
|
* - 'set_ok_invalid' -- set to -1 on purpose since this should not be
|
|
|
|
* used without a full array re-index, do this on
|
|
|
|
* adding new vert/edge/faces since they may be added at
|
|
|
|
* the end of the array.
|
|
|
|
*
|
|
|
|
* - 'set_loop' -- currently loop index values are not used used much so
|
|
|
|
* assume each case they are dirty.
|
|
|
|
* - campbell */
|
|
|
|
|
2012-02-25 23:23:40 +01:00
|
|
|
#define BM_elem_index_get(ele) _bm_elem_index_get(&(ele)->head)
|
|
|
|
#define BM_elem_index_set(ele, index) _bm_elem_index_set(&(ele)->head, index)
|
|
|
|
BM_INLINE int _bm_elem_index_get(const BMHeader *ele);
|
|
|
|
BM_INLINE void _bm_elem_index_set(BMHeader *ele, const int index);
|
2012-02-19 19:31:04 +01:00
|
|
|
|
|
|
|
/* todo */
|
2012-02-23 05:26:24 +01:00
|
|
|
BMFace *BM_face_copy(BMesh *bm, BMFace *f, const short copyverts, const short copyedges);
|
2012-02-19 19:31:04 +01:00
|
|
|
|
|
|
|
/* copies loop data from adjacent faces */
|
|
|
|
void BM_face_copy_shared(BMesh *bm, BMFace *f);
|
|
|
|
|
|
|
|
/* copies attributes, e.g. customdata, header flags, etc, from one element
|
|
|
|
* to another of the same type.*/
|
|
|
|
void BM_elem_attrs_copy(BMesh *source_mesh, BMesh *target_mesh, const void *source, void *target);
|
|
|
|
|
|
|
|
/* Modification */
|
|
|
|
/* join two adjacent faces together along an edge. note that
|
|
|
|
* the faces must only be joined by on edge. e is the edge you
|
|
|
|
* wish to dissolve.*/
|
|
|
|
BMFace *BM_faces_join_pair(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e);
|
|
|
|
|
|
|
|
/* generic, flexible join faces function; note that most everything uses
|
|
|
|
* this, including BM_faces_join_pair */
|
|
|
|
BMFace *BM_faces_join(BMesh *bm, BMFace **faces, int totface);
|
|
|
|
|
|
|
|
/* split a face along two vertices. returns the newly made face, and sets
|
|
|
|
* the nl member to a loop in the newly created edge.*/
|
|
|
|
BMFace *BM_face_split(BMesh *bm, BMFace *f,
|
|
|
|
BMVert *v1, BMVert *v2,
|
2012-02-28 08:42:48 +01:00
|
|
|
BMLoop **r_l, BMEdge *example);
|
2012-02-19 19:31:04 +01:00
|
|
|
|
|
|
|
/* these 2 functions are very similar */
|
2012-02-26 06:48:12 +01:00
|
|
|
BMEdge* BM_vert_collapse_faces(BMesh *bm, BMEdge *ke, BMVert *kv, float fac,
|
|
|
|
const short join_faces, const short kill_degenerate_faces);
|
|
|
|
BMEdge* BM_vert_collapse_edge(BMesh *bm, BMEdge *ke, BMVert *kv,
|
|
|
|
const short kill_degenerate_faces);
|
2012-02-19 19:31:04 +01:00
|
|
|
|
|
|
|
|
|
|
|
/* splits an edge. ne is set to the new edge created. */
|
2012-02-28 08:42:48 +01:00
|
|
|
BMVert *BM_edge_split(BMesh *bm, BMEdge *e, BMVert *v, BMEdge **r_e, float percent);
|
2012-02-19 19:31:04 +01:00
|
|
|
|
|
|
|
/* split an edge multiple times evenly */
|
|
|
|
BMVert *BM_edge_split_n(BMesh *bm, BMEdge *e, int numcuts);
|
|
|
|
|
|
|
|
/* connect two verts together, through a face they share. this function may
|
|
|
|
* be removed in the future. */
|
2012-02-28 08:42:48 +01:00
|
|
|
BMEdge *BM_verts_connect(BMesh *bm, BMVert *v1, BMVert *v2, BMFace **r_f);
|
2012-02-19 19:31:04 +01:00
|
|
|
|
|
|
|
/* rotates an edge topologically, either clockwise (if ccw=0) or counterclockwise
|
|
|
|
* (if ccw is 1). */
|
|
|
|
BMEdge *BM_edge_rotate(BMesh *bm, BMEdge *e, int ccw);
|
|
|
|
|
|
|
|
/* Rip a single face from a vertex fan */
|
|
|
|
BMVert *BM_vert_rip(BMesh *bm, BMFace *sf, BMVert *sv);
|
|
|
|
|
|
|
|
/*updates a face normal*/
|
|
|
|
void BM_face_normal_update(BMesh *bm, BMFace *f);
|
|
|
|
void BM_face_normal_update_vcos(BMesh *bm, BMFace *f, float no[3], float (*vertexCos)[3]);
|
|
|
|
|
|
|
|
/*updates face and vertex normals incident on an edge*/
|
|
|
|
void BM_edge_normals_update(BMesh *bm, BMEdge *e);
|
|
|
|
|
|
|
|
/*update a vert normal (but not the faces incident on it)*/
|
|
|
|
void BM_vert_normal_update(BMesh *bm, BMVert *v);
|
|
|
|
void BM_vert_normal_update_all(BMesh *bm, BMVert *v);
|
|
|
|
|
|
|
|
void BM_face_normal_flip(BMesh *bm, BMFace *f);
|
|
|
|
|
|
|
|
/*dissolves all faces around a vert, and removes it.*/
|
|
|
|
int BM_disk_dissolve(BMesh *bm, BMVert *v);
|
|
|
|
|
|
|
|
/* dissolves vert, in more situations then BM_disk_dissolve
|
|
|
|
* (e.g. if the vert is part of a wire edge, etc).*/
|
|
|
|
int BM_vert_dissolve(BMesh *bm, BMVert *v);
|
|
|
|
|
|
|
|
/* Projects co onto face f, and returns true if it is inside
|
|
|
|
* the face bounds. Note that this uses a best-axis projection
|
|
|
|
* test, instead of projecting co directly into f's orientation
|
|
|
|
* space, so there might be accuracy issues.*/
|
|
|
|
int BM_face_point_inside_test(BMesh *bm, BMFace *f, const float co[3]);
|
|
|
|
|
|
|
|
/* get the area of the face */
|
|
|
|
float BM_face_area_calc(BMesh *bm, BMFace *f);
|
|
|
|
/* computes the centroid of a face, using the center of the bounding box */
|
|
|
|
void BM_face_center_bounds_calc(BMesh *bm, BMFace *f, float center[3]);
|
|
|
|
/* computes the centroid of a face, using the mean average */
|
|
|
|
void BM_face_center_mean_calc(BMesh *bm, BMFace *f, float center[3]);
|
|
|
|
|
|
|
|
/* flag conversion funcs */
|
|
|
|
char BM_face_flag_from_mflag(const char mflag);
|
|
|
|
char BM_edge_flag_from_mflag(const short mflag);
|
|
|
|
char BM_vert_flag_from_mflag(const char mflag);
|
|
|
|
/* reverse */
|
|
|
|
char BM_face_flag_to_mflag(BMFace *f);
|
|
|
|
short BM_edge_flag_to_mflag(BMEdge *e);
|
|
|
|
char BM_vert_flag_to_mflag(BMVert *v);
|
|
|
|
|
|
|
|
void BM_loop_kill(BMesh *bm, BMLoop *l);
|
|
|
|
void BM_face_kill(BMesh *bm, BMFace *f);
|
|
|
|
void BM_edge_kill(BMesh *bm, BMEdge *e);
|
|
|
|
void BM_vert_kill(BMesh *bm, BMVert *v);
|
|
|
|
|
|
|
|
/* kills all edges associated with f, along with any other faces containing
|
|
|
|
* those edges*/
|
|
|
|
void BM_face_edges_kill(BMesh *bm, BMFace *f);
|
|
|
|
|
|
|
|
/* kills all verts associated with f, along with any other faces containing
|
|
|
|
* those vertices*/
|
|
|
|
void BM_face_verts_kill(BMesh *bm, BMFace *f);
|
|
|
|
|
|
|
|
/*clear all data in bm*/
|
|
|
|
void BM_mesh_clear(BMesh *bm);
|
|
|
|
|
|
|
|
void BM_mesh_elem_index_ensure(BMesh *bm, const char hflag);
|
|
|
|
|
|
|
|
void BM_mesh_elem_index_validate(BMesh *bm, const char *location, const char *func,
|
|
|
|
const char *msg_a, const char *msg_b);
|
|
|
|
|
|
|
|
BMVert *BM_vert_at_index(BMesh *bm, const int index);
|
|
|
|
BMEdge *BM_edge_at_index(BMesh *bm, const int index);
|
|
|
|
BMFace *BM_face_at_index(BMesh *bm, const int index);
|
|
|
|
|
|
|
|
/*start/stop edit*/
|
2012-02-27 15:07:19 +01:00
|
|
|
void bmesh_edit_begin(BMesh *bm, int flag);
|
|
|
|
void bmesh_edit_end(BMesh *bm, int flag);
|
2012-02-19 19:31:04 +01:00
|
|
|
|
|
|
|
|
|
|
|
#ifdef USE_BMESH_HOLES
|
|
|
|
# define BM_FACE_FIRST_LOOP(p) (((BMLoopList *)((p)->loops.first))->first)
|
|
|
|
#else
|
|
|
|
# define BM_FACE_FIRST_LOOP(p) ((p)->l_first)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* size to use for static arrays when dealing with NGons,
|
|
|
|
* alloc after this limit is reached.
|
|
|
|
* this value is rather arbitrary */
|
|
|
|
#define BM_NGON_STACK_SIZE 32
|
|
|
|
|
|
|
|
/* avoid inf loop, this value is arbtrary
|
|
|
|
* but should not error on valid cases */
|
|
|
|
#define BM_LOOP_RADIAL_MAX 10000
|
|
|
|
#define BM_NGON_MAX 100000
|
|
|
|
|
|
|
|
/* include the rest of the API */
|
|
|
|
#include "bmesh_marking.h"
|
|
|
|
#include "bmesh_operator_api.h"
|
|
|
|
#include "bmesh_operators.h"
|
|
|
|
#include "bmesh_error.h"
|
|
|
|
#include "bmesh_queries.h"
|
2012-02-28 17:29:48 +01:00
|
|
|
#include "bmesh_interp.h"
|
2012-02-19 19:31:04 +01:00
|
|
|
#include "bmesh_iterators.h"
|
|
|
|
#include "bmesh_walkers.h"
|
|
|
|
#include "intern/bmesh_inline.c"
|
2012-02-25 20:43:51 +01:00
|
|
|
#include "intern/bmesh_operator_api_inline.c"
|
2012-02-19 19:31:04 +01:00
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#endif /* __BMESH_H__ */
|