2009-10-07 21:19:58 +00:00
|
|
|
/**
|
|
|
|
|
* $Id:
|
|
|
|
|
*
|
|
|
|
|
* ***** 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. 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.
|
|
|
|
|
*
|
|
|
|
|
* Contributor(s): Joseph Eagar.
|
|
|
|
|
*
|
|
|
|
|
* ***** END GPL LICENSE BLOCK *****
|
|
|
|
|
*/
|
|
|
|
|
|
2009-01-07 15:17:58 +00:00
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
|
|
|
|
|
|
#include "BKE_utildefines.h"
|
2010-03-11 18:27:45 +00:00
|
|
|
#include "BKE_tessmesh.h"
|
2009-01-07 15:17:58 +00:00
|
|
|
|
2009-11-23 14:41:22 +00:00
|
|
|
#include "BLI_math.h"
|
2009-02-02 03:25:23 +00:00
|
|
|
#include "BLI_rand.h"
|
2009-02-08 14:25:04 +00:00
|
|
|
#include "BLI_ghash.h"
|
2009-09-17 23:05:33 +00:00
|
|
|
#include "BLI_array.h"
|
2011-02-27 06:19:40 +00:00
|
|
|
#include "BLI_utildefines.h"
|
2009-01-07 15:17:58 +00:00
|
|
|
|
2009-02-02 03:25:23 +00:00
|
|
|
#include "DNA_object_types.h"
|
2010-03-11 18:27:45 +00:00
|
|
|
#include "DNA_windowmanager_types.h"
|
2009-01-07 15:17:58 +00:00
|
|
|
|
2009-02-02 03:25:23 +00:00
|
|
|
#include "ED_mesh.h"
|
2009-01-07 15:17:58 +00:00
|
|
|
|
2009-02-02 03:25:23 +00:00
|
|
|
#include "bmesh.h"
|
2010-07-14 22:06:10 +00:00
|
|
|
#include "bmesh_private.h"
|
|
|
|
|
|
2009-02-02 03:25:23 +00:00
|
|
|
#include "mesh_intern.h"
|
2009-02-08 14:25:04 +00:00
|
|
|
#include "subdivideop.h"
|
2009-01-07 15:17:58 +00:00
|
|
|
|
2009-02-02 03:25:23 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <math.h>
|
2009-01-07 15:17:58 +00:00
|
|
|
|
2009-02-09 07:08:35 +00:00
|
|
|
/*flags for all elements share a common bitfield space*/
|
2009-02-02 03:25:23 +00:00
|
|
|
#define SUBD_SPLIT 1
|
2009-02-08 14:25:04 +00:00
|
|
|
|
2009-02-08 17:01:28 +00:00
|
|
|
#define EDGE_PERCENT 2
|
|
|
|
|
|
2009-02-08 14:25:04 +00:00
|
|
|
/*I don't think new faces are flagged, currently, but
|
|
|
|
|
better safe than sorry.*/
|
2009-02-09 07:08:35 +00:00
|
|
|
#define FACE_NEW 4
|
|
|
|
|
#define FACE_CUSTOMFILL 8
|
|
|
|
|
#define ELE_INNER 16
|
|
|
|
|
#define ELE_SPLIT 32
|
|
|
|
|
#define ELE_CONNECT 64
|
2009-01-07 15:17:58 +00:00
|
|
|
|
2009-02-08 11:53:14 +00:00
|
|
|
/*stuff for the flag paramter. note that
|
|
|
|
|
what used to live in "beauty" and
|
|
|
|
|
in "seltype" live here. still have to
|
|
|
|
|
convert the beauty flags over, which
|
|
|
|
|
is why it starts at 128 (to avoid
|
|
|
|
|
collision).*/
|
|
|
|
|
#define SELTYPE_INNER 128
|
|
|
|
|
|
2009-02-03 06:22:30 +00:00
|
|
|
/*
|
|
|
|
|
NOTE: beauty has been renamed to flag!
|
|
|
|
|
*/
|
|
|
|
|
|
2009-01-07 15:17:58 +00:00
|
|
|
/*generic subdivision rules:
|
|
|
|
|
|
|
|
|
|
* two selected edges in a face should make a link
|
|
|
|
|
between them.
|
|
|
|
|
|
|
|
|
|
* one edge should do, what? make pretty topology, or just
|
|
|
|
|
split the edge only?
|
|
|
|
|
*/
|
|
|
|
|
|
2011-03-28 00:29:45 +00:00
|
|
|
#if 0 //misc. code, maps a parametric coordinate to a fractal line
|
|
|
|
|
float lastrnd[3], vec2[3] = {0.0f, 0.0f, 0.0f};
|
|
|
|
|
int seed = BLI_rand();
|
|
|
|
|
int d, i, j, dp, lvl, wid;
|
|
|
|
|
float df;
|
|
|
|
|
|
|
|
|
|
BLI_srandom(seed);
|
|
|
|
|
|
|
|
|
|
wid = (params->numcuts+2);
|
|
|
|
|
dp = perc*wid;
|
|
|
|
|
wid /= 2;
|
|
|
|
|
d = lvl = 0;
|
|
|
|
|
while (1) {
|
|
|
|
|
if (d > dp) {
|
|
|
|
|
d -= wid;
|
|
|
|
|
} else if (d < dp) {
|
|
|
|
|
d += wid;
|
|
|
|
|
} else {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
wid = MAX2((wid/2), 1);
|
|
|
|
|
lvl++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
zero_v3(vec1);
|
|
|
|
|
df = 1.0f;
|
|
|
|
|
for (i=0; i<lvl; i++, df /= 4.0f) {
|
|
|
|
|
int tot = (1<<i);
|
|
|
|
|
|
|
|
|
|
lastrnd[0] = BLI_drand()-0.5f;
|
|
|
|
|
lastrnd[1] = BLI_drand()-0.5f;
|
|
|
|
|
lastrnd[2] = BLI_drand()-0.5f;
|
|
|
|
|
for (j=0; j<tot; j++) {
|
|
|
|
|
float a, b, rnd[3], rnd2[3];
|
|
|
|
|
|
|
|
|
|
rnd[0] = BLI_drand()-0.5f;
|
|
|
|
|
rnd[1] = BLI_drand()-0.5f;
|
|
|
|
|
rnd[2] = BLI_drand()-0.5f;
|
|
|
|
|
|
|
|
|
|
a = (float)j*(float)((float)params->numcuts/(float)tot);
|
|
|
|
|
b = (float)(j+1)*(float)((float)params->numcuts/(float)tot);
|
|
|
|
|
if (d >= a && d <= b) {
|
|
|
|
|
interp_v3_v3v3(rnd2, lastrnd, rnd, (((float)d)-a)/(b-a));
|
|
|
|
|
mul_v3_fl(rnd2, df);
|
|
|
|
|
add_v3_v3(vec1, rnd2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
copy_v3_v3(lastrnd, rnd);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
2009-03-13 13:11:50 +00:00
|
|
|
/*connects face with smallest len, which I think should always be correct for
|
|
|
|
|
edge subdivision*/
|
|
|
|
|
BMEdge *connect_smallest_face(BMesh *bm, BMVert *v1, BMVert *v2, BMFace **nf) {
|
|
|
|
|
BMIter iter, iter2;
|
|
|
|
|
BMVert *v;
|
|
|
|
|
BMLoop *nl;
|
|
|
|
|
BMFace *face, *curf = NULL;
|
|
|
|
|
|
|
|
|
|
/*this isn't the best thing in the world. it doesn't handle cases where there's
|
|
|
|
|
multiple faces yet. that might require a convexity test to figure out which
|
|
|
|
|
face is "best," and who knows what for non-manifold conditions.*/
|
2009-05-16 16:18:08 +00:00
|
|
|
for (face = BMIter_New(&iter, bm, BM_FACES_OF_VERT, v1); face; face=BMIter_Step(&iter)) {
|
|
|
|
|
for (v=BMIter_New(&iter2, bm, BM_VERTS_OF_FACE, face); v; v=BMIter_Step(&iter2)) {
|
2009-03-13 13:11:50 +00:00
|
|
|
if (v == v2) {
|
|
|
|
|
if (!curf || face->len < curf->len) curf = face;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (curf) {
|
|
|
|
|
face = BM_Split_Face(bm, curf, v1, v2, &nl, NULL);
|
|
|
|
|
|
|
|
|
|
if (nf) *nf = face;
|
|
|
|
|
return nl ? nl->e : NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
2009-02-02 03:25:23 +00:00
|
|
|
/* calculates offset for co, based on fractal, sphere or smooth settings */
|
2011-05-09 14:32:55 +00:00
|
|
|
static void alter_co(BMesh *bm, BMVert *v, BMEdge *UNUSED(origed), subdparams *params, float perc,
|
2009-02-03 06:22:30 +00:00
|
|
|
BMVert *vsta, BMVert *vend)
|
2009-02-02 03:25:23 +00:00
|
|
|
{
|
|
|
|
|
float vec1[3], fac;
|
2011-03-28 00:29:45 +00:00
|
|
|
float *co=NULL, *origco=NULL;
|
|
|
|
|
int i, totlayer = CustomData_number_of_layers(&bm->vdata, CD_SHAPEKEY);
|
|
|
|
|
|
|
|
|
|
BM_Vert_UpdateAllNormals(bm, v);
|
2009-07-16 06:27:37 +00:00
|
|
|
|
2011-03-28 00:29:45 +00:00
|
|
|
origco = CustomData_bmesh_get_n(&bm->vdata, v->head.data, CD_SHAPEKEY, params->origkey);
|
|
|
|
|
sub_v3_v3v3(vec1, origco, v->co);
|
|
|
|
|
|
|
|
|
|
for (i=0; i<totlayer; i++) {
|
|
|
|
|
co = CustomData_bmesh_get_n(&bm->vdata, v->head.data, CD_SHAPEKEY, i);
|
|
|
|
|
sub_v3_v3(co, vec1);
|
2009-07-16 06:27:37 +00:00
|
|
|
}
|
2009-01-07 15:17:58 +00:00
|
|
|
|
2011-03-28 00:29:45 +00:00
|
|
|
for (i=0; i<totlayer; i++) {
|
|
|
|
|
co = CustomData_bmesh_get_n(&bm->vdata, v->head.data, CD_SHAPEKEY, i);
|
|
|
|
|
|
|
|
|
|
if(params->beauty & B_SMOOTH) {
|
|
|
|
|
/* we calculate an offset vector vec1[], to be added to *co */
|
|
|
|
|
float len, fac, nor[3], nor1[3], nor2[3], smooth=params->smooth;
|
|
|
|
|
|
|
|
|
|
sub_v3_v3v3(nor, vsta->co, vend->co);
|
|
|
|
|
len= 0.5f*normalize_v3(nor);
|
|
|
|
|
|
|
|
|
|
copy_v3_v3(nor1, vsta->no);
|
|
|
|
|
copy_v3_v3(nor2, vend->no);
|
|
|
|
|
|
|
|
|
|
/* cosine angle */
|
|
|
|
|
fac= nor[0]*nor1[0] + nor[1]*nor1[1] + nor[2]*nor1[2] ;
|
|
|
|
|
|
|
|
|
|
vec1[0]= fac*nor1[0];
|
|
|
|
|
vec1[1]= fac*nor1[1];
|
|
|
|
|
vec1[2]= fac*nor1[2];
|
|
|
|
|
|
|
|
|
|
/* cosine angle */
|
|
|
|
|
fac= -nor[0]*nor2[0] - nor[1]*nor2[1] - nor[2]*nor2[2] ;
|
|
|
|
|
|
|
|
|
|
vec1[0]+= fac*nor2[0];
|
|
|
|
|
vec1[1]+= fac*nor2[1];
|
|
|
|
|
vec1[2]+= fac*nor2[2];
|
|
|
|
|
|
|
|
|
|
/* falloff for multi subdivide */
|
|
|
|
|
smooth *= sqrt(fabs(1.0f - 2.0f*fabs(perc)));
|
|
|
|
|
|
|
|
|
|
vec1[0]*= smooth*len;
|
|
|
|
|
vec1[1]*= smooth*len;
|
|
|
|
|
vec1[2]*= smooth*len;
|
|
|
|
|
|
|
|
|
|
co[0] += vec1[0];
|
|
|
|
|
co[1] += vec1[1];
|
|
|
|
|
co[2] += vec1[2];
|
|
|
|
|
}
|
|
|
|
|
else if(params->beauty & B_SPHERE) { /* subdivide sphere */
|
|
|
|
|
normalize_v3(co);
|
|
|
|
|
co[0]*= params->smooth;
|
|
|
|
|
co[1]*= params->smooth;
|
|
|
|
|
co[2]*= params->smooth;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(params->beauty & B_FRACTAL) {
|
|
|
|
|
float len = len_v3v3(vsta->co, vend->co);
|
|
|
|
|
float vec2[3] = {0.0f, 0.0f, 0.0f}, co2[3];
|
|
|
|
|
|
|
|
|
|
fac= params->fractal*len;
|
|
|
|
|
|
|
|
|
|
add_v3_v3(vec2, vsta->no);
|
|
|
|
|
add_v3_v3(vec2, vend->no);
|
|
|
|
|
mul_v3_fl(vec2, 0.5f);
|
|
|
|
|
|
|
|
|
|
add_v3_v3v3(co2, v->co, params->off);
|
|
|
|
|
vec1[0] = fac*(BLI_gTurbulence(1.0, co2[0], co2[1], co2[2], 15, 0, 1)-0.5f);
|
|
|
|
|
vec1[1] = fac*(BLI_gTurbulence(1.0, co2[0], co2[1], co2[2], 15, 0, 1)-0.5f);
|
|
|
|
|
vec1[2] = fac*(BLI_gTurbulence(1.0, co2[0], co2[1], co2[2], 15, 0, 1)-0.5f);
|
|
|
|
|
|
|
|
|
|
mul_v3_v3(vec2, vec1);
|
|
|
|
|
|
|
|
|
|
/*add displacement*/
|
|
|
|
|
add_v3_v3v3(co, co, vec2);
|
|
|
|
|
}
|
2009-02-02 03:25:23 +00:00
|
|
|
}
|
|
|
|
|
}
|
2009-01-07 15:17:58 +00:00
|
|
|
|
2009-02-02 03:25:23 +00:00
|
|
|
/* assumes in the edge is the correct interpolated vertices already */
|
2009-02-03 06:22:30 +00:00
|
|
|
/* percent defines the interpolation, rad and flag are for special options */
|
2009-02-02 03:25:23 +00:00
|
|
|
/* results in new vertex with correct coordinate, vertex normal and weight group info */
|
2009-03-16 14:15:18 +00:00
|
|
|
static BMVert *bm_subdivide_edge_addvert(BMesh *bm, BMEdge *edge,BMEdge *oedge,
|
|
|
|
|
subdparams *params, float percent,
|
|
|
|
|
float percent2,
|
2009-02-08 17:01:28 +00:00
|
|
|
BMEdge **out,BMVert *vsta,BMVert *vend)
|
2009-02-02 03:25:23 +00:00
|
|
|
{
|
|
|
|
|
BMVert *ev;
|
|
|
|
|
|
2009-03-13 13:11:50 +00:00
|
|
|
ev = BM_Split_Edge(bm, edge->v1, edge, out, percent);
|
2009-03-16 14:15:18 +00:00
|
|
|
|
2009-02-09 07:08:35 +00:00
|
|
|
BMO_SetFlag(bm, ev, ELE_INNER);
|
2009-01-07 15:17:58 +00:00
|
|
|
|
2009-02-02 03:25:23 +00:00
|
|
|
/* offset for smooth or sphere or fractal */
|
2011-03-28 00:29:45 +00:00
|
|
|
alter_co(bm, ev, oedge, params, percent2, vsta, vend);
|
2009-01-07 15:17:58 +00:00
|
|
|
|
2009-02-02 03:25:23 +00:00
|
|
|
#if 0 //TODO
|
|
|
|
|
/* clip if needed by mirror modifier */
|
|
|
|
|
if (edge->v1->f2) {
|
|
|
|
|
if ( edge->v1->f2 & edge->v2->f2 & 1) {
|
|
|
|
|
co[0]= 0.0f;
|
|
|
|
|
}
|
|
|
|
|
if ( edge->v1->f2 & edge->v2->f2 & 2) {
|
|
|
|
|
co[1]= 0.0f;
|
|
|
|
|
}
|
|
|
|
|
if ( edge->v1->f2 & edge->v2->f2 & 4) {
|
|
|
|
|
co[2]= 0.0f;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
return ev;
|
|
|
|
|
}
|
2009-01-07 15:17:58 +00:00
|
|
|
|
2009-03-16 14:15:18 +00:00
|
|
|
static BMVert *subdivideedgenum(BMesh *bm, BMEdge *edge, BMEdge *oedge,
|
2009-02-08 17:01:28 +00:00
|
|
|
int curpoint, int totpoint, subdparams *params,
|
|
|
|
|
BMEdge **newe, BMVert *vsta, BMVert *vend)
|
2009-02-02 03:25:23 +00:00
|
|
|
{
|
|
|
|
|
BMVert *ev;
|
2009-03-16 14:15:18 +00:00
|
|
|
float percent, percent2 = 0.0f;
|
2009-02-02 03:25:23 +00:00
|
|
|
|
2009-02-08 17:01:28 +00:00
|
|
|
if (BMO_TestFlag(bm, edge, EDGE_PERCENT) && totpoint == 1)
|
2009-02-09 06:36:59 +00:00
|
|
|
percent = BMO_Get_MapFloat(bm, params->op,
|
2009-03-22 23:16:43 +00:00
|
|
|
"edgepercents", edge);
|
2009-02-02 03:25:23 +00:00
|
|
|
else {
|
|
|
|
|
percent= 1.0f/(float)(totpoint+1-curpoint);
|
2011-03-28 00:29:45 +00:00
|
|
|
percent2 = (float)(curpoint+1) / (float)(totpoint+1);
|
2009-01-07 15:17:58 +00:00
|
|
|
|
2009-02-02 03:25:23 +00:00
|
|
|
}
|
|
|
|
|
|
2009-03-16 14:15:18 +00:00
|
|
|
ev= bm_subdivide_edge_addvert(bm, edge, oedge, params, percent,
|
|
|
|
|
percent2, newe, vsta, vend);
|
2009-02-02 03:25:23 +00:00
|
|
|
return ev;
|
|
|
|
|
}
|
|
|
|
|
|
2009-02-08 17:01:28 +00:00
|
|
|
static void bm_subdivide_multicut(BMesh *bm, BMEdge *edge, subdparams *params,
|
2009-02-03 06:22:30 +00:00
|
|
|
BMVert *vsta, BMVert *vend) {
|
2009-03-16 14:15:18 +00:00
|
|
|
BMEdge *eed = edge, *newe, temp = *edge;
|
2011-03-28 00:29:45 +00:00
|
|
|
BMVert *v, ov1=*edge->v1, ov2=*edge->v2, *v1=edge->v1, *v2=edge->v2;
|
2009-02-08 17:01:28 +00:00
|
|
|
int i, numcuts = params->numcuts;
|
2009-02-02 03:25:23 +00:00
|
|
|
|
2011-03-28 00:29:45 +00:00
|
|
|
temp.v1 = &ov1;
|
|
|
|
|
temp.v2 = &ov2;
|
|
|
|
|
|
2009-02-02 03:25:23 +00:00
|
|
|
for(i=0;i<numcuts;i++) {
|
2009-03-16 14:15:18 +00:00
|
|
|
v = subdivideedgenum(bm, eed, &temp, i, params->numcuts, params,
|
2009-02-08 17:01:28 +00:00
|
|
|
&newe, vsta, vend);
|
2011-03-28 00:29:45 +00:00
|
|
|
|
2009-02-02 03:25:23 +00:00
|
|
|
BMO_SetFlag(bm, v, SUBD_SPLIT);
|
|
|
|
|
BMO_SetFlag(bm, eed, SUBD_SPLIT);
|
2010-02-18 10:09:52 +00:00
|
|
|
BMO_SetFlag(bm, newe, SUBD_SPLIT);
|
2009-02-09 07:08:35 +00:00
|
|
|
|
|
|
|
|
BMO_SetFlag(bm, v, ELE_SPLIT);
|
|
|
|
|
BMO_SetFlag(bm, eed, ELE_SPLIT);
|
2010-02-18 10:09:52 +00:00
|
|
|
BMO_SetFlag(bm, newe, SUBD_SPLIT);
|
2010-07-14 22:06:10 +00:00
|
|
|
|
|
|
|
|
CHECK_ELEMENT(bm, v);
|
|
|
|
|
if (v->e) CHECK_ELEMENT(bm, v->e);
|
|
|
|
|
if (v->e && v->e->l) CHECK_ELEMENT(bm, v->e->l->f);
|
2009-02-02 03:25:23 +00:00
|
|
|
}
|
2011-03-28 00:29:45 +00:00
|
|
|
|
|
|
|
|
alter_co(bm, v1, &temp, params, 0, &ov1, &ov2);
|
|
|
|
|
alter_co(bm, v2, &temp, params, 1.0, &ov1, &ov2);
|
2009-02-02 03:25:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*note: the patterns are rotated as necassary to
|
|
|
|
|
match the input geometry. they're based on the
|
|
|
|
|
pre-split state of the face*/
|
2009-01-07 15:17:58 +00:00
|
|
|
|
|
|
|
|
/*
|
2009-02-02 03:25:23 +00:00
|
|
|
|
|
|
|
|
v3---------v2
|
2009-01-07 15:17:58 +00:00
|
|
|
| |
|
|
|
|
|
| |
|
2009-02-02 03:25:23 +00:00
|
|
|
| |
|
|
|
|
|
| |
|
|
|
|
|
v4---v0---v1
|
2009-01-07 15:17:58 +00:00
|
|
|
|
|
|
|
|
*/
|
2011-02-27 06:19:40 +00:00
|
|
|
static void quad_1edge_split(BMesh *bm, BMFace *UNUSED(face),
|
2009-02-08 17:01:28 +00:00
|
|
|
BMVert **verts, subdparams *params) {
|
2009-02-02 03:25:23 +00:00
|
|
|
BMFace *nf;
|
2009-02-08 17:01:28 +00:00
|
|
|
int i, add, numcuts = params->numcuts;
|
2009-02-02 03:25:23 +00:00
|
|
|
|
|
|
|
|
/*if it's odd, the middle face is a quad, otherwise it's a triangle*/
|
|
|
|
|
if (numcuts % 2==0) {
|
|
|
|
|
add = 2;
|
|
|
|
|
for (i=0; i<numcuts; i++) {
|
|
|
|
|
if (i == numcuts/2) add -= 1;
|
2009-03-13 13:11:50 +00:00
|
|
|
connect_smallest_face(bm, verts[i], verts[numcuts+add],
|
2009-02-08 11:53:14 +00:00
|
|
|
&nf);
|
2009-02-02 03:25:23 +00:00
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
add = 2;
|
|
|
|
|
for (i=0; i<numcuts; i++) {
|
2009-03-13 13:11:50 +00:00
|
|
|
connect_smallest_face(bm, verts[i], verts[numcuts+add],
|
2009-02-08 11:53:14 +00:00
|
|
|
&nf);
|
2009-02-02 03:25:23 +00:00
|
|
|
if (i == numcuts/2) {
|
|
|
|
|
add -= 1;
|
2009-03-13 13:11:50 +00:00
|
|
|
connect_smallest_face(bm, verts[i],
|
2009-02-08 17:01:28 +00:00
|
|
|
verts[numcuts+add],
|
2009-02-08 11:53:14 +00:00
|
|
|
&nf);
|
2009-02-02 03:25:23 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2009-09-17 23:05:33 +00:00
|
|
|
subdpattern quad_1edge = {
|
2009-02-02 03:25:23 +00:00
|
|
|
{1, 0, 0, 0},
|
2009-09-17 23:05:33 +00:00
|
|
|
quad_1edge_split,
|
2009-02-02 03:25:23 +00:00
|
|
|
4,
|
2009-01-07 15:17:58 +00:00
|
|
|
};
|
|
|
|
|
|
2009-02-02 03:25:23 +00:00
|
|
|
|
2009-01-07 15:17:58 +00:00
|
|
|
/*
|
2009-08-11 11:33:23 +00:00
|
|
|
v6--------v5
|
2009-02-02 03:25:23 +00:00
|
|
|
| |
|
2009-08-11 11:33:23 +00:00
|
|
|
| |v4s
|
|
|
|
|
| |v3s
|
|
|
|
|
| s s |
|
|
|
|
|
v7-v0--v1-v2
|
2009-01-07 15:17:58 +00:00
|
|
|
|
|
|
|
|
*/
|
2011-02-27 06:19:40 +00:00
|
|
|
static void quad_2edge_split_path(BMesh *bm, BMFace *UNUSED(face), BMVert **verts,
|
2009-08-11 11:33:23 +00:00
|
|
|
subdparams *params)
|
2009-02-08 17:01:28 +00:00
|
|
|
{
|
2009-02-02 03:25:23 +00:00
|
|
|
BMFace *nf;
|
2009-02-08 17:01:28 +00:00
|
|
|
int i, numcuts = params->numcuts;
|
2009-02-02 03:25:23 +00:00
|
|
|
|
|
|
|
|
for (i=0; i<numcuts; i++) {
|
2009-08-11 11:33:23 +00:00
|
|
|
connect_smallest_face(bm, verts[i], verts[numcuts+(numcuts-i)],
|
2009-02-08 11:53:14 +00:00
|
|
|
&nf);
|
2009-02-02 03:25:23 +00:00
|
|
|
}
|
2009-08-11 11:33:23 +00:00
|
|
|
connect_smallest_face(bm, verts[numcuts*2+3], verts[numcuts*2+1], &nf);
|
2009-02-02 03:25:23 +00:00
|
|
|
}
|
2009-01-07 15:17:58 +00:00
|
|
|
|
2009-09-17 23:05:33 +00:00
|
|
|
subdpattern quad_2edge_path = {
|
2009-08-11 11:33:23 +00:00
|
|
|
{1, 1, 0, 0},
|
2009-09-17 23:05:33 +00:00
|
|
|
quad_2edge_split_path,
|
2009-02-02 03:25:23 +00:00
|
|
|
4,
|
|
|
|
|
};
|
2009-01-07 15:17:58 +00:00
|
|
|
|
|
|
|
|
/*
|
2009-02-02 03:25:23 +00:00
|
|
|
v6--------v5
|
2009-01-07 15:17:58 +00:00
|
|
|
| |
|
2009-02-02 03:25:23 +00:00
|
|
|
| |v4s
|
|
|
|
|
| |v3s
|
|
|
|
|
| s s |
|
|
|
|
|
v7-v0--v1-v2
|
2009-01-07 15:17:58 +00:00
|
|
|
|
|
|
|
|
*/
|
2011-02-27 06:19:40 +00:00
|
|
|
static void quad_2edge_split_innervert(BMesh *bm, BMFace *UNUSED(face), BMVert **verts,
|
2009-02-08 17:01:28 +00:00
|
|
|
subdparams *params)
|
|
|
|
|
{
|
2009-02-02 03:25:23 +00:00
|
|
|
BMFace *nf;
|
2009-08-11 11:33:23 +00:00
|
|
|
BMVert *v, *lastv;
|
2011-03-28 00:29:45 +00:00
|
|
|
BMEdge *e, *ne, olde;
|
2009-02-08 17:01:28 +00:00
|
|
|
int i, numcuts = params->numcuts;
|
2009-02-02 03:25:23 +00:00
|
|
|
|
2009-08-11 11:33:23 +00:00
|
|
|
lastv = verts[numcuts];
|
|
|
|
|
|
|
|
|
|
for (i=numcuts-1; i>=0; i--) {
|
|
|
|
|
e = connect_smallest_face(bm, verts[i], verts[numcuts+(numcuts-i)],
|
2009-02-08 11:53:14 +00:00
|
|
|
&nf);
|
2009-08-11 11:33:23 +00:00
|
|
|
|
2011-03-28 00:29:45 +00:00
|
|
|
olde = *e;
|
|
|
|
|
v = bm_subdivide_edge_addvert(bm, e, &olde, params, 0.5f, 0.5f, &ne, e->v1, e->v2);
|
|
|
|
|
|
|
|
|
|
if (i != numcuts-1)
|
|
|
|
|
connect_smallest_face(bm, lastv, v, &nf);
|
|
|
|
|
|
2009-08-11 11:33:23 +00:00
|
|
|
lastv = v;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
connect_smallest_face(bm, lastv, verts[numcuts*2+2], &nf);
|
|
|
|
|
}
|
|
|
|
|
|
2009-09-17 23:05:33 +00:00
|
|
|
subdpattern quad_2edge_innervert = {
|
2009-08-11 11:33:23 +00:00
|
|
|
{1, 1, 0, 0},
|
2009-09-17 23:05:33 +00:00
|
|
|
quad_2edge_split_innervert,
|
2009-08-11 11:33:23 +00:00
|
|
|
4,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
v6--------v5
|
|
|
|
|
| |
|
|
|
|
|
| |v4s
|
|
|
|
|
| |v3s
|
|
|
|
|
| s s |
|
|
|
|
|
v7-v0--v1-v2
|
|
|
|
|
|
|
|
|
|
*/
|
2011-03-20 16:30:39 +00:00
|
|
|
static void quad_2edge_split_fan(BMesh *bm, BMFace *UNUSED(face), BMVert **verts,
|
2009-08-11 11:33:23 +00:00
|
|
|
subdparams *params)
|
|
|
|
|
{
|
|
|
|
|
BMFace *nf;
|
2011-03-20 16:30:39 +00:00
|
|
|
// BMVert *v;
|
|
|
|
|
BMVert *lastv;
|
|
|
|
|
// BMEdge *e, *ne;
|
2009-08-11 11:33:23 +00:00
|
|
|
int i, numcuts = params->numcuts;
|
|
|
|
|
|
|
|
|
|
lastv = verts[2];
|
|
|
|
|
|
|
|
|
|
for (i=0; i<numcuts; i++) {
|
|
|
|
|
connect_smallest_face(bm, verts[i], verts[numcuts*2+2], &nf);
|
|
|
|
|
connect_smallest_face(bm, verts[numcuts+(numcuts-i)],
|
|
|
|
|
verts[numcuts*2+2], &nf);
|
2009-02-02 03:25:23 +00:00
|
|
|
}
|
|
|
|
|
}
|
2009-01-07 15:17:58 +00:00
|
|
|
|
2009-09-17 23:05:33 +00:00
|
|
|
subdpattern quad_2edge_fan = {
|
2009-02-02 03:25:23 +00:00
|
|
|
{1, 1, 0, 0},
|
2009-09-17 23:05:33 +00:00
|
|
|
quad_2edge_split_fan,
|
2009-02-02 03:25:23 +00:00
|
|
|
4,
|
|
|
|
|
};
|
2009-01-07 15:17:58 +00:00
|
|
|
|
2009-02-02 03:25:23 +00:00
|
|
|
/* s s
|
|
|
|
|
v8--v7--v6-v5
|
|
|
|
|
| |
|
|
|
|
|
| v4 s
|
|
|
|
|
| |
|
|
|
|
|
| v3 s
|
|
|
|
|
| s s |
|
|
|
|
|
v9-v0--v1-v2
|
2009-01-07 15:17:58 +00:00
|
|
|
|
|
|
|
|
*/
|
2011-03-20 16:30:39 +00:00
|
|
|
static void quad_3edge_split(BMesh *bm, BMFace *UNUSED(face), BMVert **verts,
|
2009-02-08 17:01:28 +00:00
|
|
|
subdparams *params)
|
|
|
|
|
{
|
2009-02-02 03:25:23 +00:00
|
|
|
BMFace *nf;
|
2009-02-08 17:01:28 +00:00
|
|
|
int i, add=0, numcuts = params->numcuts;
|
2009-02-02 03:25:23 +00:00
|
|
|
|
|
|
|
|
for (i=0; i<numcuts; i++) {
|
|
|
|
|
if (i == numcuts/2) {
|
|
|
|
|
if (numcuts % 2 != 0) {
|
2009-03-13 13:11:50 +00:00
|
|
|
connect_smallest_face(bm, verts[numcuts-i-1+add],
|
2009-02-08 17:01:28 +00:00
|
|
|
verts[i+numcuts+1], &nf);
|
2009-02-02 03:25:23 +00:00
|
|
|
}
|
|
|
|
|
add = numcuts*2+2;
|
|
|
|
|
}
|
2009-03-13 13:11:50 +00:00
|
|
|
connect_smallest_face(bm, verts[numcuts-i-1+add],
|
2009-02-08 17:01:28 +00:00
|
|
|
verts[i+numcuts+1], &nf);
|
2009-02-02 03:25:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (i=0; i<numcuts/2+1; i++) {
|
2009-03-13 13:11:50 +00:00
|
|
|
connect_smallest_face(bm, verts[i],verts[(numcuts-i)+numcuts*2+1],
|
2009-02-08 11:53:14 +00:00
|
|
|
&nf);
|
2009-02-02 03:25:23 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2009-09-17 23:05:33 +00:00
|
|
|
subdpattern quad_3edge = {
|
2009-02-02 03:25:23 +00:00
|
|
|
{1, 1, 1, 0},
|
2009-09-17 23:05:33 +00:00
|
|
|
quad_3edge_split,
|
2009-02-02 03:25:23 +00:00
|
|
|
4,
|
2009-01-07 15:17:58 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
2009-02-02 03:25:23 +00:00
|
|
|
|
|
|
|
|
v8--v7-v6--v5
|
|
|
|
|
| s |
|
|
|
|
|
|v9 s s|v4
|
|
|
|
|
first line | | last line
|
|
|
|
|
|v10s s s|v3
|
|
|
|
|
v11-v0--v1-v2
|
|
|
|
|
|
|
|
|
|
it goes from bottom up
|
|
|
|
|
*/
|
2011-03-20 16:30:39 +00:00
|
|
|
static void quad_4edge_subdivide(BMesh *bm, BMFace *UNUSED(face), BMVert **verts,
|
2009-02-08 17:01:28 +00:00
|
|
|
subdparams *params)
|
|
|
|
|
{
|
2009-02-02 03:25:23 +00:00
|
|
|
BMFace *nf;
|
2009-02-03 06:22:30 +00:00
|
|
|
BMVert *v, *v1, *v2;
|
2009-03-16 14:15:18 +00:00
|
|
|
BMEdge *e, *ne, temp;
|
2009-02-08 17:01:28 +00:00
|
|
|
BMVert **lines;
|
|
|
|
|
int numcuts = params->numcuts;
|
2011-03-20 16:30:39 +00:00
|
|
|
int i, j, a, b, s=numcuts+2 /* , totv=numcuts*4+4 */;
|
2009-02-02 03:25:23 +00:00
|
|
|
|
2009-02-08 17:01:28 +00:00
|
|
|
lines = MEM_callocN(sizeof(BMVert*)*(numcuts+2)*(numcuts+2),
|
|
|
|
|
"q_4edge_split");
|
2009-02-02 03:25:23 +00:00
|
|
|
/*build a 2-dimensional array of verts,
|
|
|
|
|
containing every vert (and all new ones)
|
|
|
|
|
in the face.*/
|
|
|
|
|
|
|
|
|
|
/*first line*/
|
|
|
|
|
for (i=0; i<numcuts+2; i++) {
|
2009-02-08 17:01:28 +00:00
|
|
|
lines[i] = verts[numcuts*3+2+(numcuts-i+1)];
|
2009-02-02 03:25:23 +00:00
|
|
|
}
|
2009-01-07 15:17:58 +00:00
|
|
|
|
2009-02-02 03:25:23 +00:00
|
|
|
/*last line*/
|
|
|
|
|
for (i=0; i<numcuts+2; i++) {
|
2009-02-08 17:01:28 +00:00
|
|
|
lines[(s-1)*s+i] = verts[numcuts+i];
|
2009-02-02 03:25:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*first and last members of middle lines*/
|
|
|
|
|
for (i=0; i<numcuts; i++) {
|
|
|
|
|
a = i;
|
|
|
|
|
b = numcuts + 1 + numcuts + 1 + (numcuts - i - 1);
|
|
|
|
|
|
2009-03-13 13:11:50 +00:00
|
|
|
e = connect_smallest_face(bm, verts[a], verts[b], &nf);
|
2010-07-14 22:06:10 +00:00
|
|
|
if (!e)
|
|
|
|
|
continue;
|
2009-03-13 13:11:50 +00:00
|
|
|
|
2009-02-09 07:08:35 +00:00
|
|
|
BMO_SetFlag(bm, e, ELE_INNER);
|
|
|
|
|
BMO_SetFlag(bm, nf, ELE_INNER);
|
|
|
|
|
|
2009-02-02 03:25:23 +00:00
|
|
|
|
2009-02-08 17:01:28 +00:00
|
|
|
v1 = lines[(i+1)*s] = verts[a];
|
|
|
|
|
v2 = lines[(i+1)*s + s-1] = verts[b];
|
2009-03-16 14:15:18 +00:00
|
|
|
|
|
|
|
|
temp = *e;
|
2009-02-02 03:25:23 +00:00
|
|
|
for (a=0; a<numcuts; a++) {
|
2009-03-16 14:15:18 +00:00
|
|
|
v = subdivideedgenum(bm, e, &temp, a, numcuts, params, &ne,
|
2011-03-28 00:29:45 +00:00
|
|
|
v1, v2);
|
2010-07-14 22:06:10 +00:00
|
|
|
if (!v)
|
|
|
|
|
bmesh_error();
|
|
|
|
|
|
2009-02-09 07:08:35 +00:00
|
|
|
BMO_SetFlag(bm, ne, ELE_INNER);
|
2009-02-02 03:25:23 +00:00
|
|
|
lines[(i+1)*s+a+1] = v;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (i=1; i<numcuts+2; i++) {
|
|
|
|
|
for (j=1; j<numcuts+1; j++) {
|
|
|
|
|
a = i*s + j;
|
|
|
|
|
b = (i-1)*s + j;
|
2009-03-13 13:11:50 +00:00
|
|
|
e = connect_smallest_face(bm, lines[a], lines[b], &nf);
|
2010-07-14 22:06:10 +00:00
|
|
|
if (!e)
|
|
|
|
|
continue;
|
2009-03-13 13:11:50 +00:00
|
|
|
|
2009-02-09 07:08:35 +00:00
|
|
|
BMO_SetFlag(bm, e, ELE_INNER);
|
|
|
|
|
BMO_SetFlag(bm, nf, ELE_INNER);
|
2009-02-02 03:25:23 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MEM_freeN(lines);
|
|
|
|
|
}
|
2009-01-07 15:17:58 +00:00
|
|
|
|
2009-02-08 08:52:25 +00:00
|
|
|
/* v3
|
|
|
|
|
/ \
|
|
|
|
|
/ \
|
|
|
|
|
/ \
|
|
|
|
|
/ \
|
|
|
|
|
/ \
|
|
|
|
|
v4--v0--v1--v2
|
|
|
|
|
s s
|
|
|
|
|
*/
|
2011-03-20 16:30:39 +00:00
|
|
|
static void tri_1edge_split(BMesh *bm, BMFace *UNUSED(face), BMVert **verts,
|
2009-02-08 17:01:28 +00:00
|
|
|
subdparams *params)
|
|
|
|
|
{
|
2009-02-08 08:52:25 +00:00
|
|
|
BMFace *nf;
|
2009-02-08 17:01:28 +00:00
|
|
|
int i, numcuts = params->numcuts;
|
2009-02-08 08:52:25 +00:00
|
|
|
|
|
|
|
|
for (i=0; i<numcuts; i++) {
|
2009-03-13 13:11:50 +00:00
|
|
|
connect_smallest_face(bm, verts[i], verts[numcuts+1], &nf);
|
2009-02-08 08:52:25 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2009-09-17 23:05:33 +00:00
|
|
|
subdpattern tri_1edge = {
|
2009-02-08 08:52:25 +00:00
|
|
|
{1, 0, 0},
|
2009-09-17 23:05:33 +00:00
|
|
|
tri_1edge_split,
|
2009-02-08 08:52:25 +00:00
|
|
|
3,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/* v5
|
|
|
|
|
/ \
|
|
|
|
|
s v6/---\ v4 s
|
|
|
|
|
/ \ / \
|
|
|
|
|
sv7/---v---\ v3 s
|
|
|
|
|
/ \/ \/ \
|
|
|
|
|
v8--v0--v1--v2
|
|
|
|
|
s s
|
|
|
|
|
*/
|
2011-03-20 16:30:39 +00:00
|
|
|
static void tri_3edge_subdivide(BMesh *bm, BMFace *UNUSED(face), BMVert **verts,
|
2009-02-08 17:01:28 +00:00
|
|
|
subdparams *params)
|
|
|
|
|
{
|
2009-02-08 08:52:25 +00:00
|
|
|
BMFace *nf;
|
2009-03-16 14:15:18 +00:00
|
|
|
BMEdge *e, *ne, temp;
|
2011-03-28 00:29:45 +00:00
|
|
|
BMVert ***lines, *v, ov1, ov2;
|
2009-02-08 08:52:25 +00:00
|
|
|
void *stackarr[1];
|
2009-02-08 17:01:28 +00:00
|
|
|
int i, j, a, b, numcuts = params->numcuts;
|
2009-02-08 08:52:25 +00:00
|
|
|
|
|
|
|
|
/*number of verts in each line*/
|
|
|
|
|
lines = MEM_callocN(sizeof(void*)*(numcuts+2), "triangle vert table");
|
|
|
|
|
|
2009-02-08 11:53:14 +00:00
|
|
|
lines[0] = (BMVert**) stackarr;
|
2009-02-08 17:01:28 +00:00
|
|
|
lines[0][0] = verts[numcuts*2+1];
|
2009-02-08 08:52:25 +00:00
|
|
|
|
|
|
|
|
lines[1+numcuts] = MEM_callocN(sizeof(void*)*(numcuts+2),
|
|
|
|
|
"triangle vert table 2");
|
|
|
|
|
for (i=0; i<numcuts; i++) {
|
2009-02-08 17:01:28 +00:00
|
|
|
lines[1+numcuts][1+i] = verts[i];
|
2009-02-08 08:52:25 +00:00
|
|
|
}
|
2009-02-08 17:01:28 +00:00
|
|
|
lines[1+numcuts][0] = verts[numcuts*3+2];
|
|
|
|
|
lines[1+numcuts][1+numcuts] = verts[numcuts];
|
2009-02-08 08:52:25 +00:00
|
|
|
|
|
|
|
|
for (i=0; i<numcuts; i++) {
|
|
|
|
|
lines[i+1] = MEM_callocN(sizeof(void*)*(2+i),
|
|
|
|
|
"triangle vert table row");
|
|
|
|
|
a = numcuts*2 + 2 + i;
|
|
|
|
|
b = numcuts + numcuts - i;
|
2009-03-13 13:11:50 +00:00
|
|
|
e = connect_smallest_face(bm, verts[a], verts[b], &nf);
|
2009-03-09 15:15:17 +00:00
|
|
|
if (!e) goto cleanup;
|
|
|
|
|
|
2009-02-09 07:08:35 +00:00
|
|
|
BMO_SetFlag(bm, e, ELE_INNER);
|
|
|
|
|
BMO_SetFlag(bm, nf, ELE_INNER);
|
2009-02-08 08:52:25 +00:00
|
|
|
|
2009-02-08 17:01:28 +00:00
|
|
|
lines[i+1][0] = verts[a];
|
|
|
|
|
lines[i+1][1+i] = verts[b];
|
2009-03-16 14:15:18 +00:00
|
|
|
|
|
|
|
|
temp = *e;
|
2011-03-28 00:29:45 +00:00
|
|
|
ov1 = *verts[a];
|
|
|
|
|
ov2 = *verts[b];
|
|
|
|
|
temp.v1 = &ov1;
|
|
|
|
|
temp.v2 = &ov2;
|
2009-02-08 08:52:25 +00:00
|
|
|
for (j=0; j<i; j++) {
|
2009-03-16 14:15:18 +00:00
|
|
|
v = subdivideedgenum(bm, e, &temp, j, i, params, &ne,
|
2009-02-08 17:01:28 +00:00
|
|
|
verts[a], verts[b]);
|
2009-02-08 08:52:25 +00:00
|
|
|
lines[i+1][j+1] = v;
|
2009-02-08 11:53:14 +00:00
|
|
|
|
2009-02-09 07:08:35 +00:00
|
|
|
BMO_SetFlag(bm, ne, ELE_INNER);
|
2009-02-08 08:52:25 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* v5
|
|
|
|
|
/ \
|
|
|
|
|
s v6/---\ v4 s
|
|
|
|
|
/ \ / \
|
|
|
|
|
sv7/---v---\ v3 s
|
|
|
|
|
/ \/ \/ \
|
|
|
|
|
v8--v0--v1--v2
|
|
|
|
|
s s
|
|
|
|
|
*/
|
|
|
|
|
for (i=1; i<numcuts+1; i++) {
|
|
|
|
|
for (j=0; j<i; j++) {
|
2009-03-13 13:11:50 +00:00
|
|
|
e= connect_smallest_face(bm, lines[i][j], lines[i+1][j+1],
|
2009-02-08 11:53:14 +00:00
|
|
|
&nf);
|
2009-02-09 07:08:35 +00:00
|
|
|
|
|
|
|
|
BMO_SetFlag(bm, e, ELE_INNER);
|
|
|
|
|
BMO_SetFlag(bm, nf, ELE_INNER);
|
2009-02-08 11:53:14 +00:00
|
|
|
|
2009-03-13 13:11:50 +00:00
|
|
|
e= connect_smallest_face(bm,lines[i][j+1],lines[i+1][j+1],
|
2009-02-08 11:53:14 +00:00
|
|
|
&nf);
|
2009-02-09 07:08:35 +00:00
|
|
|
|
|
|
|
|
BMO_SetFlag(bm, e, ELE_INNER);
|
|
|
|
|
BMO_SetFlag(bm, nf, ELE_INNER);
|
2009-02-08 08:52:25 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2009-03-09 15:15:17 +00:00
|
|
|
cleanup:
|
2009-02-08 11:53:14 +00:00
|
|
|
for (i=1; i<numcuts+2; i++) {
|
2009-03-09 15:15:17 +00:00
|
|
|
if (lines[i]) MEM_freeN(lines[i]);
|
2009-02-08 08:52:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MEM_freeN(lines);
|
|
|
|
|
}
|
|
|
|
|
|
2009-09-17 23:05:33 +00:00
|
|
|
subdpattern tri_3edge = {
|
2009-02-08 08:52:25 +00:00
|
|
|
{1, 1, 1},
|
2009-09-17 23:05:33 +00:00
|
|
|
tri_3edge_subdivide,
|
2009-02-08 08:52:25 +00:00
|
|
|
3,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
2009-09-17 23:05:33 +00:00
|
|
|
subdpattern quad_4edge = {
|
2009-02-02 03:25:23 +00:00
|
|
|
{1, 1, 1, 1},
|
2009-09-17 23:05:33 +00:00
|
|
|
quad_4edge_subdivide,
|
2009-02-02 03:25:23 +00:00
|
|
|
4,
|
2009-01-07 15:17:58 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
subdpattern *patterns[] = {
|
2009-08-11 11:33:23 +00:00
|
|
|
NULL, //quad single edge pattern is inserted here
|
|
|
|
|
NULL, //quad corner vert pattern is inserted here
|
|
|
|
|
NULL, //tri single edge pattern is inserted here
|
|
|
|
|
NULL,
|
2009-09-17 23:05:33 +00:00
|
|
|
&quad_3edge,
|
2009-08-11 11:33:23 +00:00
|
|
|
NULL,
|
2009-01-07 15:17:58 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
#define PLEN (sizeof(patterns) / sizeof(void*))
|
|
|
|
|
|
2009-02-02 03:25:23 +00:00
|
|
|
typedef struct subd_facedata {
|
|
|
|
|
BMVert *start; subdpattern *pat;
|
2009-07-17 10:54:00 +00:00
|
|
|
int totedgesel; //only used if pat was NULL, e.g. no pattern was found
|
2010-07-14 22:06:10 +00:00
|
|
|
BMFace *face;
|
2009-02-02 03:25:23 +00:00
|
|
|
} subd_facedata;
|
2009-01-07 15:17:58 +00:00
|
|
|
|
|
|
|
|
void esubdivide_exec(BMesh *bmesh, BMOperator *op)
|
|
|
|
|
{
|
2009-02-09 06:36:59 +00:00
|
|
|
BMOpSlot *einput;
|
2009-01-07 15:17:58 +00:00
|
|
|
subdpattern *pat;
|
2009-02-08 17:01:28 +00:00
|
|
|
subdparams params;
|
2009-02-02 03:25:23 +00:00
|
|
|
subd_facedata *facedata = NULL;
|
2011-03-28 00:29:45 +00:00
|
|
|
BMIter viter, fiter, liter;
|
|
|
|
|
BMVert *v, **verts = NULL;
|
|
|
|
|
BMEdge *edge, **edges = NULL;
|
|
|
|
|
BMLoop *nl, *l, **splits = NULL, **loops = NULL;
|
|
|
|
|
BMFace *face;
|
2009-09-17 23:05:33 +00:00
|
|
|
BLI_array_declare(splits);
|
|
|
|
|
BLI_array_declare(loops);
|
2011-03-28 00:29:45 +00:00
|
|
|
BLI_array_declare(facedata);
|
|
|
|
|
BLI_array_declare(edges);
|
|
|
|
|
BLI_array_declare(verts);
|
2009-07-16 06:27:37 +00:00
|
|
|
float smooth, fractal;
|
2009-08-11 11:33:23 +00:00
|
|
|
int beauty, cornertype, singleedge, gridfill;
|
2011-03-28 00:29:45 +00:00
|
|
|
int skey, seed, i, j, matched, a, b, numcuts, totesel;
|
2009-01-07 15:17:58 +00:00
|
|
|
|
Brought Extrude all the way back. The contextual menu works,
as does only edges and individual faces extrude (individual vert
extrude already did).
Note that I need to port this, after we all figure out how to handle
operators with variable transform follow-ons.
I also implemented the merge->collapse function, which is currently
accessable under ctrl->v, Bmesh Test Operator. I still need to
implement the other merge modes, and properly hook everything into
the merge menu tool, which I plan on doing soon (tomorrow hopefully).
The cool thing about the collapse tool, is not only does it handle (all)
UV layers, it handles vcols as well. To do this, I had to add a few math
functions to the customdata API, which seem to be working well.
2009-08-11 07:49:35 +00:00
|
|
|
BMO_Flag_Buffer(bmesh, op, "edges", SUBD_SPLIT, BM_EDGE);
|
2009-02-02 03:25:23 +00:00
|
|
|
|
2009-08-11 11:33:23 +00:00
|
|
|
numcuts = BMO_Get_Int(op, "numcuts");
|
2011-03-28 00:29:45 +00:00
|
|
|
seed = BMO_Get_Int(op, "seed");
|
2009-08-11 11:33:23 +00:00
|
|
|
smooth = BMO_Get_Float(op, "smooth");
|
|
|
|
|
fractal = BMO_Get_Float(op, "fractal");
|
|
|
|
|
beauty = BMO_Get_Int(op, "beauty");
|
|
|
|
|
cornertype = BMO_Get_Int(op, "quadcornertype");
|
|
|
|
|
singleedge = BMO_Get_Int(op, "singleedge");
|
|
|
|
|
gridfill = BMO_Get_Int(op, "gridfill");
|
|
|
|
|
|
2011-03-28 00:29:45 +00:00
|
|
|
BLI_srandom(seed);
|
|
|
|
|
|
2009-08-11 11:33:23 +00:00
|
|
|
patterns[1] = NULL;
|
|
|
|
|
//straight cut is patterns[1] == NULL
|
|
|
|
|
switch (cornertype) {
|
|
|
|
|
case SUBD_PATH:
|
2009-09-17 23:05:33 +00:00
|
|
|
patterns[1] = &quad_2edge_path;
|
2009-08-11 11:33:23 +00:00
|
|
|
break;
|
|
|
|
|
case SUBD_INNERVERT:
|
2009-09-17 23:05:33 +00:00
|
|
|
patterns[1] = &quad_2edge_innervert;
|
2009-08-11 11:33:23 +00:00
|
|
|
break;
|
|
|
|
|
case SUBD_FAN:
|
2009-09-17 23:05:33 +00:00
|
|
|
patterns[1] = &quad_2edge_fan;
|
2009-08-11 11:33:23 +00:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (singleedge) {
|
2009-09-17 23:05:33 +00:00
|
|
|
patterns[0] = &quad_1edge;
|
|
|
|
|
patterns[2] = &tri_1edge;
|
2009-08-11 11:33:23 +00:00
|
|
|
} else {
|
|
|
|
|
patterns[0] = NULL;
|
|
|
|
|
patterns[2] = NULL;
|
|
|
|
|
}
|
2009-02-08 11:53:14 +00:00
|
|
|
|
2009-08-11 11:33:23 +00:00
|
|
|
if (gridfill) {
|
2009-09-17 23:05:33 +00:00
|
|
|
patterns[3] = &quad_4edge;
|
|
|
|
|
patterns[5] = &tri_3edge;
|
2009-08-11 11:33:23 +00:00
|
|
|
} else {
|
|
|
|
|
patterns[3] = NULL;
|
|
|
|
|
patterns[5] = NULL;
|
|
|
|
|
}
|
2009-02-02 03:25:23 +00:00
|
|
|
|
2011-03-28 00:29:45 +00:00
|
|
|
/*add a temporary shapekey layer to store displacements on current geometry*/
|
|
|
|
|
BM_add_data_layer(bmesh, &bmesh->vdata, CD_SHAPEKEY);
|
|
|
|
|
skey = CustomData_number_of_layers(&bmesh->vdata, CD_SHAPEKEY)-1;
|
|
|
|
|
|
|
|
|
|
BM_ITER(v, &viter, bmesh, BM_VERTS_OF_MESH, NULL) {
|
|
|
|
|
float *co = CustomData_bmesh_get_n(&bmesh->vdata, v->head.data, CD_SHAPEKEY, skey);
|
|
|
|
|
copy_v3_v3(co, v->co);
|
|
|
|
|
}
|
|
|
|
|
|
2009-02-11 12:32:29 +00:00
|
|
|
/*first go through and tag edges*/
|
2009-03-22 23:16:43 +00:00
|
|
|
BMO_Flag_To_Slot(bmesh, op, "edges",
|
2009-02-11 12:32:29 +00:00
|
|
|
SUBD_SPLIT, BM_EDGE);
|
|
|
|
|
|
2009-02-08 17:01:28 +00:00
|
|
|
params.numcuts = numcuts;
|
2009-02-09 06:36:59 +00:00
|
|
|
params.op = op;
|
2009-07-16 06:27:37 +00:00
|
|
|
params.smooth = smooth;
|
2011-03-28 00:29:45 +00:00
|
|
|
params.seed = seed;
|
2009-07-16 06:27:37 +00:00
|
|
|
params.fractal = fractal;
|
|
|
|
|
params.beauty = beauty;
|
2011-03-28 00:29:45 +00:00
|
|
|
params.origkey = skey;
|
|
|
|
|
params.off[0] = BLI_drand()*200.0f;
|
|
|
|
|
params.off[1] = BLI_drand()*200.0f;
|
|
|
|
|
params.off[2] = BLI_drand()*200.0f;
|
|
|
|
|
|
2009-03-22 23:16:43 +00:00
|
|
|
BMO_Mapping_To_Flag(bmesh, op, "custompatterns",
|
2009-02-09 06:36:59 +00:00
|
|
|
FACE_CUSTOMFILL);
|
|
|
|
|
|
2009-03-22 23:16:43 +00:00
|
|
|
BMO_Mapping_To_Flag(bmesh, op, "edgepercents",
|
2009-02-09 06:36:59 +00:00
|
|
|
EDGE_PERCENT);
|
|
|
|
|
|
2009-03-22 23:16:43 +00:00
|
|
|
for (face=BMIter_New(&fiter, bmesh, BM_FACES_OF_MESH, NULL);
|
2009-02-02 03:25:23 +00:00
|
|
|
face; face=BMIter_Step(&fiter)) {
|
2009-07-17 11:15:06 +00:00
|
|
|
BMEdge *e1 = NULL, *e2 = NULL;
|
|
|
|
|
float vec1[3], vec2[3];
|
|
|
|
|
|
2009-02-02 03:25:23 +00:00
|
|
|
/*figure out which pattern to use*/
|
2009-02-08 14:25:04 +00:00
|
|
|
|
2009-09-17 23:05:33 +00:00
|
|
|
BLI_array_empty(edges);
|
|
|
|
|
BLI_array_empty(verts);
|
2009-07-17 10:54:00 +00:00
|
|
|
matched = 0;
|
|
|
|
|
|
2009-02-08 14:25:04 +00:00
|
|
|
i = 0;
|
2009-07-17 10:54:00 +00:00
|
|
|
totesel = 0;
|
2009-02-02 03:25:23 +00:00
|
|
|
for (nl=BMIter_New(&liter, bmesh, BM_LOOPS_OF_FACE, face);
|
|
|
|
|
nl; nl=BMIter_Step(&liter)) {
|
2009-09-17 23:05:33 +00:00
|
|
|
BLI_array_growone(edges);
|
|
|
|
|
BLI_array_growone(verts);
|
2009-02-02 03:25:23 +00:00
|
|
|
edges[i] = nl->e;
|
|
|
|
|
verts[i] = nl->v;
|
2009-07-17 10:54:00 +00:00
|
|
|
|
2009-07-17 11:15:06 +00:00
|
|
|
if (BMO_TestFlag(bmesh, edges[i], SUBD_SPLIT)) {
|
|
|
|
|
if (!e1) e1 = edges[i];
|
|
|
|
|
else e2 = edges[i];
|
|
|
|
|
|
2009-07-17 10:54:00 +00:00
|
|
|
totesel++;
|
2009-07-17 11:15:06 +00:00
|
|
|
}
|
2009-07-17 10:54:00 +00:00
|
|
|
|
2009-02-02 03:25:23 +00:00
|
|
|
i++;
|
|
|
|
|
}
|
2009-01-07 15:17:58 +00:00
|
|
|
|
2009-07-17 11:15:06 +00:00
|
|
|
/*make sure the two edges have a valid angle to each other*/
|
2009-07-17 11:28:44 +00:00
|
|
|
if (totesel == 2 && (e1->v1 == e2->v1 || e1->v1 == e2->v2
|
|
|
|
|
|| e1->v2 == e2->v1 || e1->v2 == e2->v1)) {
|
2009-07-17 11:15:06 +00:00
|
|
|
float angle;
|
|
|
|
|
|
2009-11-23 14:41:22 +00:00
|
|
|
sub_v3_v3v3(vec1, e1->v2->co, e1->v1->co);
|
|
|
|
|
sub_v3_v3v3(vec2, e2->v2->co, e2->v1->co);
|
|
|
|
|
normalize_v3(vec1);
|
|
|
|
|
normalize_v3(vec2);
|
2009-07-17 11:15:06 +00:00
|
|
|
|
|
|
|
|
angle = INPR(vec1, vec2);
|
|
|
|
|
angle = ABS(angle);
|
|
|
|
|
if (ABS(angle-1.0) < 0.01)
|
|
|
|
|
totesel = 0;
|
|
|
|
|
}
|
|
|
|
|
|
2009-02-08 14:25:04 +00:00
|
|
|
if (BMO_TestFlag(bmesh, face, FACE_CUSTOMFILL)) {
|
2009-02-09 06:36:59 +00:00
|
|
|
pat = BMO_Get_MapData(bmesh, op,
|
2009-03-22 23:16:43 +00:00
|
|
|
"custompatterns", face);
|
2009-02-08 14:25:04 +00:00
|
|
|
for (i=0; i<pat->len; i++) {
|
|
|
|
|
matched = 1;
|
|
|
|
|
for (j=0; j<pat->len; j++) {
|
|
|
|
|
a = (j + i) % pat->len;
|
|
|
|
|
if ((!!BMO_TestFlag(bmesh, edges[a], SUBD_SPLIT))
|
|
|
|
|
!= (!!pat->seledges[j])) {
|
|
|
|
|
matched = 0;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (matched) {
|
2009-09-17 23:05:33 +00:00
|
|
|
BLI_array_growone(facedata);
|
|
|
|
|
b = BLI_array_count(facedata)-1;
|
2009-02-08 14:25:04 +00:00
|
|
|
facedata[b].pat = pat;
|
|
|
|
|
facedata[b].start = verts[i];
|
2010-07-14 22:06:10 +00:00
|
|
|
facedata[b].face = face;
|
|
|
|
|
facedata[b].totedgesel = totesel;
|
Printf-style method of calling operations now take a modified format string,
like so:
[opname] [slotname]=%[format code]
Before it was relying on the input format codes being in the same proper
order as the slots, which seemed like a potential maintainance nightmare to
me. Also the flags for creating buffers from bmop flags or header flags,
now support additional modifiers for combining vert/edge/face inputs.
E.g. %hfvef would accept all geometry with a header flag, and
%fef would accept edges and faces with a certain bmop flag set.
Example from the UI code:
if (!EDBM_CallOpf(em, op, "del geom=%hf context=%d", BM_SELECT, DEL_ONLYFACES))
return OPERATOR_CANCELLED;
(remember EDBM_CallOpf is the UI wrapper for this that does conversion,
error reporting, etc).
On todo is cleaning up/splitting bmesh_operators.h,
since it's kindof a mesh right now. I'm thinking of adding the slot
names in comments next to the slot ids, but I definitely would have to
clean up bmesh_operators.h first, or it'd just be too chaotic for me.
BTW, the operator API should now have enough meta info to wrap with
a scripting language, not that it matters since that's not happening till
much much later.
Also hopefully corrected some SConscripts, fix mostly provided by Elia Sarti,
though I also copied some SConscripts from 2.5 (not sure if doing
so was especially helpful).
Finally, I refactored a few places to use the new operator calling api,
as an example of how this is beneficial.
2009-03-04 08:21:10 +00:00
|
|
|
BMO_SetFlag(bmesh, face, SUBD_SPLIT);
|
2009-02-08 14:25:04 +00:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*obvously don't test for other patterns matching*/
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2009-02-02 03:25:23 +00:00
|
|
|
for (i=0; i<PLEN; i++) {
|
|
|
|
|
pat = patterns[i];
|
2009-08-11 11:33:23 +00:00
|
|
|
if (!pat) continue;
|
|
|
|
|
|
2009-02-02 03:25:23 +00:00
|
|
|
if (pat->len == face->len) {
|
|
|
|
|
for (a=0; a<pat->len; a++) {
|
2009-07-17 10:54:00 +00:00
|
|
|
matched = 1;
|
|
|
|
|
for (b=0; b<pat->len; b++) {
|
|
|
|
|
j = (b + a) % pat->len;
|
|
|
|
|
if ((!!BMO_TestFlag(bmesh, edges[j], SUBD_SPLIT))
|
|
|
|
|
!= (!!pat->seledges[b])) {
|
|
|
|
|
matched = 0;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2009-01-07 15:17:58 +00:00
|
|
|
}
|
2009-07-17 10:54:00 +00:00
|
|
|
if (matched) break;
|
2009-02-02 03:25:23 +00:00
|
|
|
}
|
|
|
|
|
if (matched) {
|
2009-09-17 23:05:33 +00:00
|
|
|
BLI_array_growone(facedata);
|
|
|
|
|
j = BLI_array_count(facedata) - 1;
|
2009-07-17 10:54:00 +00:00
|
|
|
|
|
|
|
|
BMO_SetFlag(bmesh, face, SUBD_SPLIT);
|
|
|
|
|
|
2009-02-02 03:25:23 +00:00
|
|
|
facedata[j].pat = pat;
|
|
|
|
|
facedata[j].start = verts[a];
|
2010-07-14 22:06:10 +00:00
|
|
|
facedata[j].face = face;
|
|
|
|
|
facedata[j].totedgesel = totesel;
|
2009-02-02 03:25:23 +00:00
|
|
|
break;
|
|
|
|
|
}
|
2009-01-07 15:17:58 +00:00
|
|
|
}
|
2009-07-17 10:54:00 +00:00
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!matched && totesel) {
|
2009-09-17 23:05:33 +00:00
|
|
|
BLI_array_growone(facedata);
|
|
|
|
|
j = BLI_array_count(facedata) - 1;
|
2009-07-17 10:54:00 +00:00
|
|
|
|
|
|
|
|
BMO_SetFlag(bmesh, face, SUBD_SPLIT);
|
|
|
|
|
facedata[j].totedgesel = totesel;
|
2010-07-14 22:06:10 +00:00
|
|
|
facedata[j].face = face;
|
2009-01-07 15:17:58 +00:00
|
|
|
}
|
2009-02-02 03:25:23 +00:00
|
|
|
}
|
2009-01-07 15:17:58 +00:00
|
|
|
|
2009-03-22 23:16:43 +00:00
|
|
|
einput = BMO_GetSlot(op, "edges");
|
2009-02-08 17:01:28 +00:00
|
|
|
|
2009-02-02 03:25:23 +00:00
|
|
|
/*go through and split edges*/
|
|
|
|
|
for (i=0; i<einput->len; i++) {
|
|
|
|
|
edge = ((BMEdge**)einput->data.p)[i];
|
2010-02-18 10:09:52 +00:00
|
|
|
bm_subdivide_multicut(bmesh, edge, ¶ms, edge->v1, edge->v2);
|
2009-02-02 03:25:23 +00:00
|
|
|
}
|
2009-01-07 15:17:58 +00:00
|
|
|
|
2009-02-02 03:25:23 +00:00
|
|
|
i = 0;
|
2010-07-14 22:06:10 +00:00
|
|
|
for (i=0; i<BLI_array_count(facedata); i++) {
|
|
|
|
|
face = facedata[i].face;
|
|
|
|
|
|
2009-02-02 03:25:23 +00:00
|
|
|
/*figure out which pattern to use*/
|
2009-09-17 23:05:33 +00:00
|
|
|
BLI_array_empty(verts);
|
2009-02-08 14:25:04 +00:00
|
|
|
|
2009-02-02 03:25:23 +00:00
|
|
|
pat = facedata[i].pat;
|
2010-07-19 04:44:37 +00:00
|
|
|
|
|
|
|
|
if (!pat && facedata[i].totedgesel == 2) {
|
2009-07-17 10:54:00 +00:00
|
|
|
int vlen;
|
|
|
|
|
|
2010-07-19 04:44:37 +00:00
|
|
|
/*ok, no pattern. we still may be able to do something.*/
|
2009-09-17 23:05:33 +00:00
|
|
|
BLI_array_empty(loops);
|
|
|
|
|
BLI_array_empty(splits);
|
2009-07-17 10:54:00 +00:00
|
|
|
|
|
|
|
|
/*for case of two edges, connecting them shouldn't be too hard*/
|
|
|
|
|
BM_ITER(l, &liter, bmesh, BM_LOOPS_OF_FACE, face) {
|
2009-09-17 23:05:33 +00:00
|
|
|
BLI_array_growone(loops);
|
|
|
|
|
loops[BLI_array_count(loops)-1] = l;
|
2009-07-17 10:54:00 +00:00
|
|
|
}
|
|
|
|
|
|
2009-09-17 23:05:33 +00:00
|
|
|
vlen = BLI_array_count(loops);
|
2009-07-17 10:54:00 +00:00
|
|
|
|
|
|
|
|
/*find the boundary of one of the split edges*/
|
|
|
|
|
for (a=1; a<vlen; a++) {
|
|
|
|
|
if (!BMO_TestFlag(bmesh, loops[a-1]->v, ELE_INNER)
|
|
|
|
|
&& BMO_TestFlag(bmesh, loops[a]->v, ELE_INNER))
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (BMO_TestFlag(bmesh, loops[(a+numcuts+1)%vlen]->v, ELE_INNER)) {
|
|
|
|
|
b = (a+numcuts+1)%vlen;
|
|
|
|
|
} else {
|
|
|
|
|
/*find the boundary of the other edge.*/
|
|
|
|
|
for (j=0; j<vlen; j++) {
|
|
|
|
|
b = (j + a + numcuts + 1) % vlen;
|
|
|
|
|
if (!BMO_TestFlag(bmesh, loops[b==0 ? vlen-1 : b-1]->v, ELE_INNER)
|
|
|
|
|
&& BMO_TestFlag(bmesh, loops[b]->v, ELE_INNER))
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
b += numcuts - 1;
|
|
|
|
|
|
|
|
|
|
for (j=0; j<numcuts; j++) {
|
2009-09-17 23:05:33 +00:00
|
|
|
BLI_array_growone(splits);
|
|
|
|
|
splits[BLI_array_count(splits)-1] = loops[a];
|
2009-07-17 10:54:00 +00:00
|
|
|
|
2009-09-17 23:05:33 +00:00
|
|
|
BLI_array_growone(splits);
|
|
|
|
|
splits[BLI_array_count(splits)-1] = loops[b];
|
2009-07-17 10:54:00 +00:00
|
|
|
|
|
|
|
|
b = (b-1) % vlen;
|
|
|
|
|
a = (a+1) % vlen;
|
|
|
|
|
}
|
|
|
|
|
|
2009-09-17 23:05:33 +00:00
|
|
|
//BM_LegalSplits(bmesh, face, splits, BLI_array_count(splits)/2);
|
2009-07-17 10:54:00 +00:00
|
|
|
|
2009-09-17 23:05:33 +00:00
|
|
|
for (j=0; j<BLI_array_count(splits)/2; j++) {
|
2009-07-17 10:54:00 +00:00
|
|
|
if (splits[j*2]) {
|
|
|
|
|
BMFace *nf;
|
|
|
|
|
|
2009-07-25 04:52:44 +00:00
|
|
|
nf = BM_Split_Face(bmesh, face, splits[j*2]->v, splits[j*2+1]->v, &nl, NULL);
|
2009-07-17 10:54:00 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
} else if (!pat) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2009-02-02 03:25:23 +00:00
|
|
|
|
|
|
|
|
j = a = 0;
|
|
|
|
|
for (nl=BMIter_New(&liter, bmesh, BM_LOOPS_OF_FACE, face);
|
|
|
|
|
nl; nl=BMIter_Step(&liter)) {
|
|
|
|
|
if (nl->v == facedata[i].start) {
|
|
|
|
|
a = j+1;
|
|
|
|
|
break;
|
2009-01-07 15:17:58 +00:00
|
|
|
}
|
2009-02-02 03:25:23 +00:00
|
|
|
j++;
|
|
|
|
|
}
|
2009-01-07 15:17:58 +00:00
|
|
|
|
2009-02-08 12:41:13 +00:00
|
|
|
for (j=0; j<face->len; j++) {
|
2009-09-17 23:05:33 +00:00
|
|
|
BLI_array_growone(verts);
|
2009-02-08 12:41:13 +00:00
|
|
|
}
|
|
|
|
|
|
2009-02-02 03:25:23 +00:00
|
|
|
j = 0;
|
|
|
|
|
for (nl=BMIter_New(&liter, bmesh, BM_LOOPS_OF_FACE, face);
|
|
|
|
|
nl; nl=BMIter_Step(&liter)) {
|
|
|
|
|
b = (j-a+face->len) % face->len;
|
|
|
|
|
verts[b] = nl->v;
|
|
|
|
|
j += 1;
|
2009-01-07 15:17:58 +00:00
|
|
|
}
|
2010-07-14 22:06:10 +00:00
|
|
|
|
|
|
|
|
CHECK_ELEMENT(bmesh, face);
|
2009-02-08 17:01:28 +00:00
|
|
|
pat->connectexec(bmesh, face, verts, ¶ms);
|
2009-01-07 15:17:58 +00:00
|
|
|
}
|
2009-02-02 03:25:23 +00:00
|
|
|
|
2011-03-28 00:29:45 +00:00
|
|
|
/*copy original-geometry displacements to current coordinates*/
|
|
|
|
|
BM_ITER(v, &viter, bmesh, BM_VERTS_OF_MESH, NULL) {
|
|
|
|
|
float *co = CustomData_bmesh_get_n(&bmesh->vdata, v->head.data, CD_SHAPEKEY, skey);
|
|
|
|
|
copy_v3_v3(v->co, co);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BM_free_data_layer_n(bmesh, &bmesh->vdata, CD_SHAPEKEY, skey);
|
|
|
|
|
|
2009-09-17 23:05:33 +00:00
|
|
|
if (facedata) BLI_array_free(facedata);
|
|
|
|
|
if (edges) BLI_array_free(edges);
|
|
|
|
|
if (verts) BLI_array_free(verts);
|
|
|
|
|
BLI_array_free(splits);
|
|
|
|
|
BLI_array_free(loops);
|
2009-02-09 07:08:35 +00:00
|
|
|
|
2009-03-22 23:16:43 +00:00
|
|
|
BMO_Flag_To_Slot(bmesh, op, "outinner",
|
2010-07-22 00:18:35 +00:00
|
|
|
ELE_INNER, BM_ALL);
|
2009-03-22 23:16:43 +00:00
|
|
|
BMO_Flag_To_Slot(bmesh, op, "outsplit",
|
2009-02-09 07:08:35 +00:00
|
|
|
ELE_SPLIT, BM_ALL);
|
2010-01-28 00:45:30 +00:00
|
|
|
|
|
|
|
|
BMO_Flag_To_Slot(bmesh, op, "geomout",
|
2010-02-18 10:09:52 +00:00
|
|
|
ELE_INNER|ELE_SPLIT|SUBD_SPLIT, BM_ALL);
|
2009-02-02 03:25:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*editmesh-emulating function*/
|
2011-03-20 16:30:39 +00:00
|
|
|
void BM_esubdivideflag(Object *UNUSED(obedit), BMesh *bm, int flag, float smooth,
|
2011-04-13 22:30:25 +00:00
|
|
|
float fractal, int beauty, int numcuts,
|
|
|
|
|
int seltype, int cornertype, int singleedge,
|
|
|
|
|
int gridfill, int seed)
|
2009-08-11 11:33:23 +00:00
|
|
|
{
|
2009-02-02 03:25:23 +00:00
|
|
|
BMOperator op;
|
|
|
|
|
|
2009-07-16 06:27:37 +00:00
|
|
|
BMO_InitOpf(bm, &op, "esubd edges=%he smooth=%f fractal=%f "
|
2009-08-11 11:33:23 +00:00
|
|
|
"beauty=%d numcuts=%d quadcornertype=%d singleedge=%d "
|
2011-03-28 00:29:45 +00:00
|
|
|
"gridfill=%d seed=%d",
|
2009-08-11 11:33:23 +00:00
|
|
|
flag, smooth, fractal, beauty, numcuts,
|
2011-03-28 00:29:45 +00:00
|
|
|
cornertype, singleedge, gridfill, seed);
|
2009-07-16 06:27:37 +00:00
|
|
|
|
2009-02-02 03:25:23 +00:00
|
|
|
BMO_Exec_Op(bm, &op);
|
2009-07-16 06:27:37 +00:00
|
|
|
|
2009-02-09 07:08:35 +00:00
|
|
|
if (seltype == SUBDIV_SELECT_INNER) {
|
Printf-style method of calling operations now take a modified format string,
like so:
[opname] [slotname]=%[format code]
Before it was relying on the input format codes being in the same proper
order as the slots, which seemed like a potential maintainance nightmare to
me. Also the flags for creating buffers from bmop flags or header flags,
now support additional modifiers for combining vert/edge/face inputs.
E.g. %hfvef would accept all geometry with a header flag, and
%fef would accept edges and faces with a certain bmop flag set.
Example from the UI code:
if (!EDBM_CallOpf(em, op, "del geom=%hf context=%d", BM_SELECT, DEL_ONLYFACES))
return OPERATOR_CANCELLED;
(remember EDBM_CallOpf is the UI wrapper for this that does conversion,
error reporting, etc).
On todo is cleaning up/splitting bmesh_operators.h,
since it's kindof a mesh right now. I'm thinking of adding the slot
names in comments next to the slot ids, but I definitely would have to
clean up bmesh_operators.h first, or it'd just be too chaotic for me.
BTW, the operator API should now have enough meta info to wrap with
a scripting language, not that it matters since that's not happening till
much much later.
Also hopefully corrected some SConscripts, fix mostly provided by Elia Sarti,
though I also copied some SConscripts from 2.5 (not sure if doing
so was especially helpful).
Finally, I refactored a few places to use the new operator calling api,
as an example of how this is beneficial.
2009-03-04 08:21:10 +00:00
|
|
|
BMOIter iter;
|
2009-02-09 07:08:35 +00:00
|
|
|
BMHeader *ele;
|
2011-03-20 16:30:39 +00:00
|
|
|
// int i;
|
2009-02-09 07:08:35 +00:00
|
|
|
|
2009-09-16 17:43:09 +00:00
|
|
|
ele = BMO_IterNew(&iter, bm, &op, "outinner", BM_EDGE|BM_VERT);
|
|
|
|
|
for (; ele; ele=BMO_IterStep(&iter)) {
|
|
|
|
|
BM_Select(bm, ele, 1);
|
|
|
|
|
}
|
|
|
|
|
} else if (seltype == SUBDIV_SELECT_LOOPCUT) {
|
|
|
|
|
BMOIter iter;
|
|
|
|
|
BMHeader *ele;
|
2011-03-20 16:30:39 +00:00
|
|
|
// int i;
|
2009-09-16 17:43:09 +00:00
|
|
|
|
|
|
|
|
/*deselect input*/
|
|
|
|
|
BM_clear_flag_all(bm, BM_SELECT);
|
|
|
|
|
|
|
|
|
|
ele = BMO_IterNew(&iter, bm, &op, "outinner", BM_EDGE|BM_VERT);
|
Printf-style method of calling operations now take a modified format string,
like so:
[opname] [slotname]=%[format code]
Before it was relying on the input format codes being in the same proper
order as the slots, which seemed like a potential maintainance nightmare to
me. Also the flags for creating buffers from bmop flags or header flags,
now support additional modifiers for combining vert/edge/face inputs.
E.g. %hfvef would accept all geometry with a header flag, and
%fef would accept edges and faces with a certain bmop flag set.
Example from the UI code:
if (!EDBM_CallOpf(em, op, "del geom=%hf context=%d", BM_SELECT, DEL_ONLYFACES))
return OPERATOR_CANCELLED;
(remember EDBM_CallOpf is the UI wrapper for this that does conversion,
error reporting, etc).
On todo is cleaning up/splitting bmesh_operators.h,
since it's kindof a mesh right now. I'm thinking of adding the slot
names in comments next to the slot ids, but I definitely would have to
clean up bmesh_operators.h first, or it'd just be too chaotic for me.
BTW, the operator API should now have enough meta info to wrap with
a scripting language, not that it matters since that's not happening till
much much later.
Also hopefully corrected some SConscripts, fix mostly provided by Elia Sarti,
though I also copied some SConscripts from 2.5 (not sure if doing
so was especially helpful).
Finally, I refactored a few places to use the new operator calling api,
as an example of how this is beneficial.
2009-03-04 08:21:10 +00:00
|
|
|
for (; ele; ele=BMO_IterStep(&iter)) {
|
2009-02-09 07:08:35 +00:00
|
|
|
BM_Select(bm, ele, 1);
|
2010-03-10 11:16:26 +00:00
|
|
|
|
|
|
|
|
if (ele->type == BM_VERT) {
|
|
|
|
|
BMEdge *e;
|
|
|
|
|
BMIter eiter;
|
|
|
|
|
|
|
|
|
|
BM_ITER(e, &eiter, bm, BM_EDGES_OF_VERT, ele) {
|
|
|
|
|
if (!BM_TestHFlag(e, BM_SELECT) && BM_TestHFlag(e->v1, BM_SELECT)
|
|
|
|
|
&& BM_TestHFlag(e->v2, BM_SELECT)) {
|
|
|
|
|
BM_SetHFlag(e, BM_SELECT);
|
|
|
|
|
bm->totedgesel += 1;
|
|
|
|
|
} else if (BM_TestHFlag(e, BM_SELECT) && (!BM_TestHFlag(e->v1, BM_SELECT)
|
|
|
|
|
|| !BM_TestHFlag(e->v2, BM_SELECT))) {
|
|
|
|
|
BM_ClearHFlag(e, BM_SELECT);
|
|
|
|
|
bm->totedgesel -= 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2009-02-09 07:08:35 +00:00
|
|
|
}
|
|
|
|
|
}
|
2009-09-16 17:43:09 +00:00
|
|
|
|
2009-02-02 03:25:23 +00:00
|
|
|
BMO_Finish_Op(bm, &op);
|
|
|
|
|
}
|
2009-02-03 06:22:30 +00:00
|
|
|
|
2009-07-17 06:05:09 +00:00
|
|
|
void esplit_exec(BMesh *bm, BMOperator *op)
|
|
|
|
|
{
|
|
|
|
|
BMOIter siter;
|
|
|
|
|
BMEdge *e;
|
|
|
|
|
subdparams params;
|
2011-03-28 00:29:45 +00:00
|
|
|
int skey;
|
|
|
|
|
|
2009-07-17 06:05:09 +00:00
|
|
|
params.numcuts = BMO_GetSlot(op, "numcuts")->data.i;
|
|
|
|
|
params.op = op;
|
|
|
|
|
|
2011-03-28 00:29:45 +00:00
|
|
|
BM_add_data_layer(bm, &bm->vdata, CD_SHAPEKEY);
|
|
|
|
|
skey = CustomData_number_of_layers(&bm->vdata, CD_SHAPEKEY)-1;
|
|
|
|
|
|
|
|
|
|
params.origkey = skey;
|
|
|
|
|
|
2009-07-17 06:05:09 +00:00
|
|
|
/*go through and split edges*/
|
|
|
|
|
BMO_ITER(e, &siter, bm, op, "edges", BM_EDGE) {
|
|
|
|
|
bm_subdivide_multicut(bm, e, ¶ms, e->v1, e->v2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BMO_Flag_To_Slot(bm, op, "outsplit",
|
|
|
|
|
ELE_SPLIT, BM_ALL);
|
2011-03-28 00:29:45 +00:00
|
|
|
|
|
|
|
|
BM_free_data_layer_n(bm, &bm->vdata, CD_SHAPEKEY, skey);
|
2009-07-17 06:05:09 +00:00
|
|
|
}
|