[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [11118] branches/soc-2007-red_fox/source/ blender: Added a basic bevel modifier.

Levi Schooley redfox at hhofministries.org
Fri Jun 29 04:17:39 CEST 2007


Revision: 11118
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=11118
Author:   red_fox
Date:     2007-06-29 04:16:56 +0200 (Fri, 29 Jun 2007)

Log Message:
-----------
Added a basic bevel modifier.

BME_Tools.c contains the core bevel code as it stands.
It does not always produce correct geometry, it only bevels the entire mesh, and loose verts or edges crash Blender when the modifier is applied.
Also, two conversion functions were added to modifier.c in order to convert to and from DerivedMesh and BMesh.
Custom data is not transferred during conversion yet.

Levi

Modified Paths:
--------------
    branches/soc-2007-red_fox/source/blender/blenkernel/intern/modifier.c
    branches/soc-2007-red_fox/source/blender/makesdna/DNA_modifier_types.h
    branches/soc-2007-red_fox/source/blender/src/buttons_editing.c

Added Paths:
-----------
    branches/soc-2007-red_fox/source/blender/blenkernel/intern/BME_tools.c

Added: branches/soc-2007-red_fox/source/blender/blenkernel/intern/BME_tools.c
===================================================================
--- branches/soc-2007-red_fox/source/blender/blenkernel/intern/BME_tools.c	                        (rev 0)
+++ branches/soc-2007-red_fox/source/blender/blenkernel/intern/BME_tools.c	2007-06-29 02:16:56 UTC (rev 11118)
@@ -0,0 +1,397 @@
+/**
+ * BME_tools.c    jan 2007
+ *
+ *	Functions for changing the topology of a mesh.
+ *
+ * $Id: BME_eulers.c,v 1.00 2007/01/17 17:42:01 Briggs Exp $
+ *
+ * ***** BEGIN GPL/BL DUAL 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. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License.  See http://www.blender.org/BL/ for information
+ * about this.	
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2004 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Geoffrey Bantle.
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#include <math.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_listBase.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_mesh_types.h"
+
+#include "BKE_utildefines.h"
+#include "BKE_bmesh.h"
+#include "BLI_arithb.h"
+#include "BLI_blenlib.h"
+
+/**
+ *			BME_dissolve_edge
+ *
+ *	Edge Dissolve Function:
+ *	
+ *	Dissolves a 2-manifold edge by joining it's two faces. if 
+ *	they have opposite windings it first makes them consistent 
+ *	by calling BME_loop_reverse()
+ *
+ *	Returns -
+*/
+
+/**
+ *			BME_inset_edge
+ *
+ *	Edge Inset Function:
+ *	
+ *	Splits a face in two along an edge and returns the next loop 
+ *
+ *	Returns -
+ *	A BME_Poly pointer.
+ */
+
+BME_Loop *BME_inset_edge(BME_Mesh *bm, BME_Loop *l, BME_Poly *f){
+	BME_Loop *nloop;
+	BME_SFME(bm, f, l->v, l->next->v, &nloop);
+	return nloop->next; 
+}
+
+/**
+ *			BME_inset_poly
+ *
+ *	Face Inset Tool:
+ *	
+ *	Insets a single face and returns a pointer to the face at the 
+ *	center of the newly created region
+ *
+ *	Returns -
+ *	A BME_Poly pointer.
+ */
+
+#define MIN(a,b) (((a)<(b))?(a):(b))
+#define MAX(a,b) (((a)>(b))?(a):(b))
+
+BME_Poly *BME_inset_poly(BME_Mesh *bm,BME_Poly *f){
+	
+	BME_Vert *v;
+	BME_Loop *l,*nextloop, *killoop, *sloop;
+	
+	int len,i;
+	float max[3],min[3],cent[3]; //center of original face
+	
+	/*get bounding box for face*/
+	VECCOPY(max,f->loopbase->v->co);
+	VECCOPY(min,f->loopbase->v->co);
+	len = f->len;
+	for(i=0,l=f->loopbase;i<len;i++,l=l->next){
+		max[0] = MAX(max[0],l->v->co[0]);
+		max[1] = MAX(max[1],l->v->co[1]);
+		max[2] = MAX(max[2],l->v->co[2]);
+		
+		min[0] = MIN(min[0],l->v->co[0]);
+		min[1] = MIN(min[1],l->v->co[1]);
+		min[2] = MIN(min[2],l->v->co[2]);
+	}
+	
+	cent[0] = (min[0] + max[0]) / 2.0;
+	cent[1] = (min[1] + max[1]) / 2.0;
+	cent[2] = (min[2] + max[2]) / 2.0;
+	
+	
+	
+	/*inset each edge in the polygon.*/
+	len = f->len;
+	for(i=0,l=f->loopbase; i < len; i++){
+		nextloop = l->next;
+		f = BME_SFME(bm,l->f,l->v,l->next->v,NULL);
+		l=nextloop;
+	}
+	
+	/*for each new edge, call SEMV on it*/
+	for(i=0,l=f->loopbase; i < len; i++, l=l->next){ 
+		l->tflag1 = 1; //going to store info that this loops edge still needs split
+		f = BME_SFME(bm,l->f,l->v,l->next->v,NULL);
+		l->tflag2 = l->v->tflag1 = l->v->tflag2 = 0; 
+	}
+	
+	len = f->len;
+	for(i=0,l=f->loopbase; i < len; i++){
+		if(l->tflag1){
+			l->tflag1 = 0;
+			v= BME_SEMV(bm,l->next->v,l->e,NULL);
+			VECCOPY(v->co,l->v->co);
+			v->tflag1 = 1;
+			l = l->next->next;
+		}
+	}
+	
+	len = f->len;
+	sloop = NULL;
+	for(i=0,l=f->loopbase; i < len; i++,l=l->next){
+		if(l->v->tflag1 && l->next->next->v->tflag1){
+			sloop = l;
+			break;
+		}
+	}
+	if(sloop){
+		for(i=0,l=sloop; i < len; i++){
+			nextloop = l->next->next;
+			f = BME_SFME(bm,f,l->v,l->next->next->v,&killoop);
+			i+=1; //i+=2;
+			BME_JFKE(bm,l->f,((BME_Loop*)l->radial.next->data)->f,l->e);
+			l=nextloop;
+		}
+	}
+	
+	len = f->len;
+	for(i=0,l=f->loopbase; i < len; i++,l=l->next){
+		l->v->co[0] = (l->v->co[0] + cent[0]) / 2.0;
+		l->v->co[1] = (l->v->co[1] + cent[1]) / 2.0;
+		l->v->co[2] = (l->v->co[2] + cent[2]) / 2.0;
+	}
+	return NULL;
+}
+
+/******* Bevel code starts here ********/
+#define BME_BEVEL_ORIG 1
+#define BME_BEVEL_BEVEL 2
+
+/* copied this function from the old bevel tool temporarily */
+void bevel_displace_vec(float *midvec, float *v1, float *v2, float *v3, float d, float no[3])
+{
+	float a[3], c[3], n_a[3], n_c[3], mid[3], ac, ac2, fac;
+
+	VecSubf(a, v1, v2);
+	VecSubf(c, v3, v2);
+
+	Crossf(n_a, a, no);
+	Normalize(n_a);
+	Crossf(n_c, no, c);
+	Normalize(n_c);
+
+	Normalize(a);
+	Normalize(c);
+	ac = Inpf(a, c);
+
+	if (ac == 1 || ac == -1) {
+		midvec[0] = midvec[1] = midvec[2] = 0;
+		return;
+	}
+	ac2 = ac * ac;
+	fac = (float)sqrt((ac2 + 2*ac + 1)/(1 - ac2) + 1);
+	VecAddf(mid, n_c, n_a);
+	Normalize(mid);
+	VecMulf(mid, d * fac);
+	VecAddf(mid, mid, v2);
+	VecCopyf(midvec, mid);
+}
+
+
+/**
+ *			BME_bevel_poly
+ *
+ *	Polygon inset tool:
+ *	
+ *	Insets a polygon/face based on the tflag1's of its vertices
+ *	and edges. Used by the bevel tool only, for now.
+ *  The parameter "value" is the distance to inset (should be negative).
+ *  The parameter "options" is not currently used.
+ *
+ *	Returns -
+ *  A BME_Poly pointer to the resulting inner face.
+*/
+
+BME_Poly *BME_bevel_poly(BME_Mesh *bm, BME_Poly *f, float value, int options) {
+	BME_Vert *v;
+	BME_Edge *e1, *e2;
+	BME_Loop *l, *nextloop, *nl;
+	
+	int len, i;	
+	float vec[3],v1[3],v2[3],v3[3],no[3];
+
+	len = f->len;
+	for(i=0,l=f->loopbase; i < len; i++) {
+		nextloop = l->next;
+		v = l->v;
+		e1 = l->prev->e;
+		e2 = l->e;
+		
+		if (v->tflag1 & BME_BEVEL_BEVEL) {
+			if (e2->tflag1 & BME_BEVEL_BEVEL) {
+				if (e1->tflag1 & BME_BEVEL_BEVEL) {
+					/* if this edge is an original, we'll need a new one to inset */
+					if (e1->tflag1 & BME_BEVEL_ORIG) {
+						f = BME_SFME(bm,l->f,l->prev->v,l->v,&nl); /* 2-eged face for an extra edge */
+						/* mark this as being a beveled edge, but not an original! */
+						nl->e->tflag1 = BME_BEVEL_BEVEL;
+						/* may need to mark the opposing face for destruction here */
+					}
+					/* note, if the edge was not original, it has already been created,
+					 * so we don't need to do anything in an "else" clause
+					 */
+					
+					/* breaking my design rules here...this is only to show topology!
+					 * will need to separate geometrical transformations and the actual
+					 * topology later, right now it gives incorrect vertex locations.
+					 */
+					VECSUB(v1,l->prev->v->co,l->v->co);
+					VECSUB(v2,l->next->v->co,l->v->co);
+					Crossf(no, v1, v2);
+					VECCOPY(v1,l->prev->v->co);
+					VECCOPY(v2,l->v->co);
+					VECCOPY(v3,l->next->v->co);
+					/* split the previous edge, this is topology
+					 * (i.e. keep it even after the surrounding math is removed)
+					 * this vert will be inset
+					 */
+					v = BME_SEMV(bm,l->v,l->prev->e,NULL);
+					v->tflag1 = 0;
+					bevel_displace_vec(vec, v1, v2, v3, value, no);
+					VECCOPY(v->co, vec);
+					/* end broken design rule */
+					
+					l = l->prev; /* go back a loop (we might be destroying the one we were sitting on!) */
+					if (e2->tflag1 & BME_BEVEL_ORIG) {
+						f = BME_SFME(bm,l->f,l->v,l->next->next->v,&nl); /* 3-edged face this time */
+						/* mark this as being a beveled edge, but not an original! */
+						nl->e->tflag1 = BME_BEVEL_BEVEL;
+						/* may need to mark the opposing face for destruction here */
+					}
+					else {
+						f = BME_JFKE(bm,l->f,((BME_Loop*)l->next->radial.next->data)->f,l->next->e);
+						/* assumes we are forming a quad (we should be), keep an eye on this! */
+						f = BME_SFME(bm,l->f,l->v,l->next->next->next->v,NULL);
+						/* may need to mark the opposing face for destruction here */
+					}
+				}
+				else {
+					/* Split e1 */
+				}
+			}
+			else if (e1->tflag1 & BME_BEVEL_BEVEL) {
+				/* split e2 */
+				/* look for previously beveled vert to connect with */
+			}
+			else {
+				/* split both edges */
+				/* join the two new verts and tesselate (tesselation may be done later) */
+			}
+		}
+		
+		l=nextloop;
+	}
+
+	return f;
+}
+
+
+/**
+ *			BME_bevel_mesh
+ *
+ *	Mesh beveling tool:
+ *	
+ *	Bevels an entire mesh. It currently uses the tflag1's of
+ *	its vertices and edges to track topological changes.
+ *  The parameter "value" is the distance to inset (should be negative).
+ *  The parameter "options" is not currently used.
+ *
+ *	Returns -
+ *  A BME_Mesh pointer to the BMesh passed as a parameter.
+*/
+
+BME_Mesh *BME_bevel_mesh(BME_Mesh *bm, float value, int options) {
+	BME_Vert *v;
+	BME_Edge *e, *nexte;
+	BME_Loop *l;
+	BME_Poly *f, *f2;
+	BME_CycleNode *diskbase;
+	int i, len, lenf;
+
+	for (v=bm->verts.first; v; v=v->next) v->tflag1 = BME_BEVEL_ORIG | BME_BEVEL_BEVEL;
+	for (e=bm->edges.first; e; e=e->next) e->tflag1 = BME_BEVEL_ORIG | BME_BEVEL_BEVEL;
+	for (f=bm->polys.first; f; f=f->next) f->tflag1 = BME_BEVEL_ORIG;
+
+	f = bm->polys.first;
+	while (f) {
+		f2 = f->next; /* f->next shouldn't change, but just in case... */
+		if(f->tflag1 & BME_BEVEL_ORIG) {
+			BME_bevel_poly(bm,f,value,options);
+		}
+		f = f2;
+	}
+	
+	/* here we will loop through all the verts to clean up the left over geometry, it
+	 * currently assumes that the entire mesh has been beveled, and that there are no
+	 * loose verts or edges; it also has very little flexibility for multi-resolution
+	 * THIS IS BAD CODE! SCRAP IT FOR A NEW SOLUTION!
+	 */
+	for (v = bm->verts.first; v; v=v->next) {
+		if (v->tflag1 & (BME_BEVEL_ORIG | BME_BEVEL_BEVEL)) {
+			/* look for original edges (to be removed) */
+			while (e = BME_disk_next_edgeflag(v->edge, v, 0, BME_BEVEL_ORIG | BME_BEVEL_BEVEL)) {
+				len = BME_cycle_length(&(e->loop->radial));

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list