2 * bmesh_construct.c August 2008
4 * BM construction functions.
6 * ***** BEGIN GPL LICENSE BLOCK *****
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software Foundation,
21 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 * The Original Code is Copyright (C) 2007 Blender Foundation.
24 * All rights reserved.
26 * The Original Code is: all of this file.
28 * Contributor(s): Geoffrey Bantle.
30 * ***** END GPL LICENSE BLOCK *****
33 #include "MEM_guardedalloc.h"
34 #include "BKE_customdata.h"
37 #include "bmesh_private.h"
40 static void bm_copy_loop_attributes(BMesh *source_mesh, BMesh *target_mesh,
41 BMLoop *source_loop, BMLoop *target_loop);
46 * This file contains functions for making and destroying
47 * individual elements like verts, edges and faces.
54 * Creates a new vertex and returns a pointer
55 * to it. If a pointer to an example vertex is
56 * passed in, it's custom data and properties
57 * will be copied to the new vertex.
61 BMVert *BM_Make_Vert(BMesh *bm, float co[3], BMVert *example)
66 CustomData_bmesh_copy_data(&bm->vdata, &bm->vdata, example->data, &v->data);
73 * Creates a new edge betweeen two vertices and returns a
74 * pointer to it. If 'nodouble' equals 1, then a check is
75 * is done to make sure that an edge between those two vertices
76 * does not already exist. If it does, that edge is returned instead
77 * of creating a new one.
79 * If a new edge is created, and a pointer to an example edge is
80 * provided, it's custom data and properties will be copied to the
85 BMEdge *BM_Make_Edge(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge *example, int nodouble)
89 if(nodouble) /*test if edge already exists.*/
90 e = bmesh_disk_existedge(v1, v2);
93 e = bmesh_me(bm, v1, v2);
96 CustomData_bmesh_copy_data(&bm->edata, &bm->edata, example->data, &e->data);
104 * BMESH MAKE QUADTRIANGLE
106 * Creates a new quad or triangle from
107 * a list of 3 or 4 vertices. If nodouble
108 * equals 1, then a check is done to see
109 * if a face with these vertices already
110 * exists and returns it instead. If a pointer
111 * to an example face is provided, it's custom
112 * data and properties will be copied to the new
115 * Note that the winding of the face is determined
116 * by the order of the vertices in the vertex array
120 /*remove the edge array bits from this. Its not really needed?*/
121 BMFace *BM_Make_Quadtriangle(BMesh *bm, BMVert **verts, BMEdge **edges, int len, BMFace *example, int nodouble)
127 edar[0] = edar[1] = edar[2] = edar[3] = NULL;
133 if(len == 4) edar[3] = edges[3];
135 edar[0] = bmesh_disk_existedge(verts[0],verts[1]);
136 edar[1] = bmesh_disk_existedge(verts[1],verts[2]);
138 edar[2] = bmesh_disk_existedge(verts[2],verts[3]);
139 edar[3] = bmesh_disk_existedge(verts[3],verts[0]);
142 edar[2] = bmesh_disk_existedge(verts[2],verts[0]);
147 /*check if face exists or overlaps*/
149 overlap = BM_Exist_Face_Overlaps(bm, verts, len, &f);
151 overlap = BM_Exist_Face_Overlaps(bm, verts, len, &f);
156 if((!f) && (!overlap)){
157 if(!edar[0]) edar[0] = bmesh_me(bm, verts[0], verts[1]);
158 if(!edar[1]) edar[1] = bmesh_me(bm, verts[1], verts[2]);
160 if(!edar[2]) edar[2] = bmesh_me(bm, verts[2], verts[3]);
161 if(!edar[3]) edar[3] = bmesh_me(bm, verts[3], verts[0]);
163 if(!edar[2]) edar[2] = bmesh_me(bm, verts[2], verts[0]);
166 if(len == 4) f = bmesh_mf(bm, verts[0], verts[1], edar, 4);
167 else f = bmesh_mf(bm, verts[0], verts[1], edar, 3);
170 CustomData_bmesh_copy_data(&bm->pdata, &bm->pdata, example->data, &f->data);
178 /*copies face data from shared adjacent faces*/
179 void BM_Face_CopyShared(BMesh *bm, BMFace *f) {
185 l=BMIter_New(&iter, bm, BM_LOOPS_OF_FACE, f);
186 for (; l; l=BMIter_Step(&iter)) {
187 l2 = l->radial.next->data;
191 bm_copy_loop_attributes(bm, bm, l2, l);
193 l2 = (BMLoop*) l2->head.next;
194 bm_copy_loop_attributes(bm, bm, l2, l);
203 * Attempts to make a new Ngon from a list of edges.
204 * If nodouble equals one, a check for overlaps or existing
209 #define VERT_BUF_SIZE 100
210 BMFace *BM_Make_Ngon(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, int len, int nodouble)
212 BMVert *vert_buf[VERT_BUF_SIZE];
213 BMVert **verts = vert_buf, *lastv;
215 int overlap = 0, i, j;
218 if(len > VERT_BUF_SIZE)
219 verts = MEM_callocN(sizeof(BMVert *) * len, "bmesh make ngon vertex array");
221 /*if ((edges[i]->v1 == edges[i]->v1) ||
222 (edges[i]->v1 == edges[i]->v2))
224 lastv = edges[i]->v2;
225 } else lastv = edges[i]->v1;
228 for (i=1; i<len; i++) {
232 for(i = 0, j=0; i < len; i++){
233 if(!BMO_TestFlag(bm, edges[i]->v1, BM_EDGEVERT)){
234 BMO_SetFlag(bm, edges[i]->v1, BM_EDGEVERT);
235 verts[j++] = edges[i]->v1;
237 if(!BMO_TestFlag(bm, edges[i]->v2, BM_EDGEVERT)) {
238 BMO_SetFlag(bm, edges[i]->v2, BM_EDGEVERT);
239 verts[j++] = edges[i]->v2;
243 overlap = BM_Exist_Face_Overlaps(bm, verts, len, &f);
246 for(i = 0; i < len; i++){
247 BMO_ClearFlag(bm, edges[i]->v1, BM_EDGEVERT);
248 BMO_ClearFlag(bm, edges[i]->v2, BM_EDGEVERT);
251 if(len > VERT_BUF_SIZE)
255 if((!f) && (!overlap)) {
256 f = bmesh_mf(bm, v1, v2, edges, len);
263 /*bmesh_make_face_from_face(BMesh *bm, BMFace *source, BMFace *target) */
269 * Called by operators to remove elements that they have marked for
274 void BM_remove_tagged_faces(BMesh *bm, int flag)
276 BMHeader *current, *next;
278 current = bm->polys.first;
280 next = current->next;
281 if(BMO_TestFlag(bm, current, flag)) bmesh_kf(bm, (BMFace*)current);
285 void BM_remove_tagged_edges(BMesh *bm, int flag)
287 BMHeader *current, *next;
289 current = bm->edges.first;
292 next = current->next;
293 if(BMO_TestFlag(bm, current, flag)) bmesh_ke(bm, (BMEdge*)current);
298 void BM_remove_tagged_verts(BMesh *bm, int flag)
300 BMHeader *current, *next;
302 current = bm->verts.first;
305 next = current->next;
306 if(BMO_TestFlag(bm, current, flag)) bmesh_kv(bm,(BMVert*)current);
311 static void bm_copy_vert_attributes(BMesh *source_mesh, BMesh *target_mesh, BMVert *source_vertex, BMVert *target_vertex)
313 CustomData_bmesh_copy_data(&source_mesh->vdata, &target_mesh->vdata, source_vertex->data, &target_vertex->data);
314 target_vertex->bweight = source_vertex->bweight;
317 static void bm_copy_edge_attributes(BMesh *source_mesh, BMesh *target_mesh, BMEdge *source_edge, BMEdge *target_edge)
319 CustomData_bmesh_copy_data(&source_mesh->edata, &target_mesh->edata, source_edge->data, &target_edge->data);
320 target_edge->crease = source_edge->crease;
321 target_edge->bweight = source_edge->bweight;
324 static void bm_copy_loop_attributes(BMesh *source_mesh, BMesh *target_mesh, BMLoop *source_loop, BMLoop *target_loop)
326 CustomData_bmesh_copy_data(&source_mesh->ldata, &target_mesh->ldata, source_loop->data, &target_loop->data);
329 static void bm_copy_face_attributes(BMesh *source_mesh, BMesh *target_mesh, BMFace *source_face, BMFace *target_face)
331 CustomData_bmesh_copy_data(&source_mesh->pdata, &target_mesh->pdata, source_face->data, &target_face->data);
332 target_face->mat_nr = source_face->mat_nr;
335 /*Todo: Special handling for hide flags?*/
337 void BM_Copy_Attributes(BMesh *source_mesh, BMesh *target_mesh, void *source, void *target)
339 BMHeader *sheader = source, *theader = target;
341 if(sheader->type != theader->type)
344 /*First we copy select*/
345 if(BM_Is_Selected(source_mesh, source)) BM_Select(target_mesh, target, 1);
347 /*Now we copy flags*/
348 theader->flag = sheader->flag;
350 /*Copy specific attributes*/
351 if(theader->type == BM_VERT)
352 bm_copy_vert_attributes(source_mesh, target_mesh, (BMVert*)source, (BMVert*)target);
353 else if(theader->type == BM_EDGE)
354 bm_copy_edge_attributes(source_mesh, target_mesh, (BMEdge*)source, (BMEdge*)target);
355 else if(theader->type == BM_LOOP)
356 bm_copy_loop_attributes(source_mesh, target_mesh, (BMLoop*)source, (BMLoop*)target);
357 else if(theader->type == BM_FACE)
358 bm_copy_face_attributes(source_mesh, target_mesh, (BMFace*)source, (BMFace*)target);