From f2371cbbaeaf4844f58c2a62fbb36380ace7c4d0 Mon Sep 17 00:00:00 2001 From: Joseph Eagar Date: Fri, 6 Mar 2009 06:06:14 +0000 Subject: [PATCH] tesselator works. . .FINALLYscons/scons.py BF_QUICK=bf_editors_mesh,bf_bmesh,bf_blenlib,bf_transform,bf_editors_transform also made transform code execute it after transform end. tesselator uses original algorithm, yay --- source/blender/blenlib/BLI_arithb.h | 1 + source/blender/blenlib/intern/arithb.c | 22 + source/blender/bmesh/intern/bmesh_polygon.c | 490 ++++-------------- source/blender/editors/include/ED_mesh.h | 4 + source/blender/editors/mesh/bmeshutils.c | 26 + .../editors/transform/transform_generics.c | 5 + 6 files changed, 150 insertions(+), 398 deletions(-) diff --git a/source/blender/blenlib/BLI_arithb.h b/source/blender/blenlib/BLI_arithb.h index 5acee360872..3c0a41e1591 100644 --- a/source/blender/blenlib/BLI_arithb.h +++ b/source/blender/blenlib/BLI_arithb.h @@ -267,6 +267,7 @@ void Vec2Subf(float *v, float *v1, float *v2); void Vec2Copyf(float *v1, float *v2); void Vec2Lerpf(float *target, float *a, float *b, float t); +void AxisAngleToQuatd(float *q, float *axis, double angle); void AxisAngleToQuat(float *q, float *axis, float angle); void RotationBetweenVectorsToQuat(float *q, float v1[3], float v2[3]); void vectoquat(float *vec, short axis, short upflag, float *q); diff --git a/source/blender/blenlib/intern/arithb.c b/source/blender/blenlib/intern/arithb.c index 0df4792cd3d..7d8bcbe2e7e 100644 --- a/source/blender/blenlib/intern/arithb.c +++ b/source/blender/blenlib/intern/arithb.c @@ -1404,6 +1404,28 @@ void AxisAngleToQuat(float *q, float *axis, float angle) q[3] = nor[2] * si; } +void AxisAngleToQuatd(float *q, float *axis, double angle) +{ + double nor[3]; + double si, l; + + nor[0] = axis[0]; + nor[1] = axis[1]; + nor[2] = axis[2]; + + l = sqrt(nor[0]*nor[0] + nor[1]*nor[1] + nor[2]*nor[2]); + nor[0] /= l; + nor[1] /= l; + nor[2] /= l; + + angle /= 2; + si = sin(angle); + q[0] = cos(angle); + q[1] = nor[0] * si; + q[2] = nor[1] * si; + q[3] = nor[2] * si; +} + void vectoquat(float *vec, short axis, short upflag, float *q) { float q2[4], nor[3], *fp, mat[3][3], angle, si, co, x2, y2, z2, len1; diff --git a/source/blender/bmesh/intern/bmesh_polygon.c b/source/blender/bmesh/intern/bmesh_polygon.c index dcd108f7edf..fc8a67df5ae 100644 --- a/source/blender/bmesh/intern/bmesh_polygon.c +++ b/source/blender/bmesh/intern/bmesh_polygon.c @@ -1,4 +1,6 @@ #include +#include +#include #include "BKE_utildefines.h" @@ -93,16 +95,21 @@ static int convexangle(float *v1t, float *v2t, float *v3t) static void compute_poly_normal(float normal[3], float (*verts)[3], int nverts) { - float *u, *v; + float *u, *v;/*, *w, v1[3], v2[3];*/ + double n[3] = {0.0, 0.0, 0.0}, l; int i; - normal[0] = 0.0; - normal[1] = 0.0; - normal[2] = 0.0; - for(i = 0; i < nverts; i++){ u = verts[i]; v = verts[(i+1) % nverts]; + /*w = verts[(i+2) % nverts]; + + VecSubf(v1, u, v); + VecSubf(v2, w, v); + Crossf(normal, v1, v2); + Normalize(normal); + + return;*/ /* newell's method @@ -112,15 +119,23 @@ static void compute_poly_normal(float normal[3], float (*verts)[3], int nverts) odd. half of that is the cross product. . .what's the other half? + + also could be like a[1]*(b[2] + a[2]) - b[1]*(a[2] - b[2]) */ - normal[0] += (u[1] - v[1]) * (u[2] + v[2]); - normal[1] += (u[2] - v[2]) * (u[0] + v[0]); - normal[2] += (u[0] - v[0]) * (u[1] + v[1]); - i++; + n[0] += (u[1] - v[1]) * (u[2] + v[2]); + n[1] += (u[2] - v[2]) * (u[0] + v[0]); + n[2] += (u[0] - v[0]) * (u[1] + v[1]); } - - Normalize(normal); + + l = sqrt(n[0]*n[0]+n[1]*n[1]+n[2]*n[2]); + n[0] /= l; + n[1] /= l; + n[2] /= l; + + normal[0] = n[0]; + normal[1] = n[1]; + normal[2] = n[2]; } /* @@ -238,16 +253,36 @@ void compute_poly_plane(float (*verts)[3], int nverts) void poly_rotate_plane(float normal[3], float (*verts)[3], int nverts) { - float up[3] = {0.0,0.0,1.0}, axis[3], angle, q[4]; - float mat[3][3]; - int i; + float up[3] = {0.0f,0.0f,1.0f}, axis[3], q[4]; + float mat[3][3], axes[3][3] = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}; + double angle; + int i, iaxis=0, bestangle=180.0f; + + for (i=0; i<3; i++) { + angle = saacos(normal[0]*axes[i][0]+normal[1]*axes[i][1] + + normal[2]*axes[i][2]); + if (angle < bestangle) { + iaxis = i; + bestangle = angle; + } + } + + //for (i=0; ihead.eflag2][i] += r; - p[v2->head.eflag2][i] -= r; - p[v3->head.eflag2][i] += r; - } - - //l = BMIter_New(&iter, bm, BM_LOOPS_OF_FACE, f); - //for (; l; l=BMIter_Step(&iter)) { - if (convexangle(p[v1->head.eflag2], p[v2->head.eflag2], - p[v3->head.eflag2])) { - ret = 0; - goto cleanup; - } - - for (i=0; ihead.eflag2 && i!=v2->head.eflag2 && - i!=v3->head.eflag2) - { - if (point_in_triangle(p[v3->head.eflag2], - p[v2->head.eflag2], p[v1->head.eflag2], - p[i])) - { - ret = 0; - goto cleanup; - } - } - } - -cleanup: - for (i=0; i<3; i++) { - p[v1->head.eflag2][i] -= r; - p[v2->head.eflag2][i] += r; - p[v3->head.eflag2][i] -= r; - } - - return ret; -} - -typedef struct qline { - struct qline *next, *prev; - - float *a; - float *b; -} qline; - -typedef struct quadnode { - float min[3], max[3]; - struct quadnode *children[2][2]; - ListBase lines; - int len; - int leaf; - int depth; -} quadnode; - -typedef struct quadtree { - BLI_mempool *linepool, *nodepool; - quadnode *root; -} quadtree; - -#define MAX_CHILD 5 -#define MAX_DEPTH 1 - -#define D 0.0001f -#define AABB(min, max, p) (p[0] >= min[0]-D && p[0] <= max[0]+D && p[1] >= min[1]-D && p[1] <= max[1]+D) - -static int quadnode_intersect_line(quadnode *node, qline *line) { - if (AABB(node->min, node->max, line->a)) return 1; - if (AABB(node->min, node->max, line->b)) return 1; - else { - float v1[3], v2[3], v3[3], v4[3]; - - VECCOPY(v1, node->min); - v2[0] = node->min[0]; - v2[1] = node->max[1]; - v2[2] = 0.0f; - VECCOPY(v3, node->max); - v4[0] = node->max[0]; - v4[1] = node->min[1]; - v4[2] = 0.0f; - - if (linecrosses(v1, v2, line->a, line->b)) return 1; - if (linecrosses(v2, v3, line->a, line->b)) return 1; - if (linecrosses(v3, v4, line->a, line->b)) return 1; - if (linecrosses(v4, v1, line->a, line->b)) return 1; - } - - return 0; -} - -static void quadnode_insert(quadtree *tree, quadnode *node, qline *line) { - if (!node->leaf) { - int x, y; - for (x=0; x<2; x++) { - for (y=0; y<2; y++) { - if (quadnode_intersect_line(node->children[x][y], line)) { - quadnode_insert(tree, node->children[x][y], line); - } - } - } - } else { - if (node->len > MAX_CHILD && node->depth != MAX_DEPTH) { - qline *cline, *cnext; - quadnode *c; - int x, y; - float cell[2] = {(node->max[0]-node->min[0])/2, (node->max[1] - node->min[1])/2}; - - node->leaf = 0; - for (x=0; x<2; x++) { - for (y=0; y<2; y++) { - c = BLI_mempool_calloc(tree->nodepool); - node->children[x][y] = c; - c->min[0] = node->min[0] + cell[0]*x - 0.001f; - c->min[1] = node->min[1] + cell[1]*y - 0.001f; - c->min[2] = 0.0f; - c->max[0] = c->min[0] + cell[0] + 0.001f; - c->max[1] = c->min[1] + cell[1] + 0.001f; - c->max[2] = 0.0f; - c->leaf = 1; - c->depth = node->depth + 1; - c->lines.first = c->lines.last = NULL; - } - } - - for (cline=node->lines.first; cline; cline=cnext) { - cnext = cline->next; - - quadnode_insert(tree, node, cline); - BLI_mempool_free(tree->linepool, cline); - } - node->lines.first = node->lines.last = NULL; - - quadnode_insert(tree, node, line); - } else { - qline *cpy = BLI_mempool_calloc(tree->linepool); - *cpy = *line; - BLI_addtail(&node->lines, cpy); - node->len++; - } - } -} - -void quadtree_insert(quadtree *tree, float *a, float *b) { - qline line; - - line.a = a; - line.b = b; - - quadnode_insert(tree, tree->root, &line); -} - -quadtree *quadree_new(float *min, float *max) { - quadtree *tree = MEM_callocN(sizeof(*tree), "quadtree"); - tree->linepool = BLI_mempool_create(sizeof(qline), 10, 32); - tree->nodepool = BLI_mempool_create(sizeof(quadnode), 10, 32); - - tree->root = BLI_mempool_calloc(tree->nodepool); - tree->root->leaf = 1; - VECCOPY(tree->root->min, min); - VECCOPY(tree->root->max, max); - - return tree; -} - -void quadtree_free(quadtree *tree) { - BLI_mempool_destroy(tree->linepool); - BLI_mempool_destroy(tree->nodepool); - MEM_freeN(tree); -} - - -static int goodline_one(quadnode *node, float *p, float *outv) -{ - if (!node->leaf) { - int x, y, ret=0; - qline line = {NULL, NULL, p, outv}; - - for (x=0; x<2; x++) { - for (y=0; y<2; y++) { - if (quadnode_intersect_line(node->children[x][y], &line)) { - ret += goodline_one(node->children[x][y], - p, outv); - } - } - } - - return ret; - } else { - float vv1[3], vv2[3], mid[3], a[3], b[3]; - float v1[3], v2[3]; - int lcount=0; - qline *line; - - for (line=node->lines.first; line; line=line->next) { - VECCOPY(vv1, line->a); - VECCOPY(vv2, line->b); - - VecAddf(mid, vv1, vv2); - VecMulf(mid, 0.5f); - - VecSubf(a, vv1, mid); - VecSubf(b, vv2, mid); - - VecMulf(a, 1.00001f); - VecMulf(b, 1.00001f); - - VecAddf(vv1, mid, a); - VecAddf(vv2, mid, b); - - if (linecrosses(vv1, vv2, p, outv)) lcount += 1; - } - - return lcount; - } - - return 0; -} - -static int goodline_two(quadnode *node, float *v1, float *v2) -{ - /*the hardcoded stuff here, 0.999 and 1.0001, may be problems - in the future, not sure. - joeedh*/ - - if (!node->leaf) { - int x, y, ret; - qline line = {NULL, NULL, v1, v2}; - - for (x=0; x<2; x++) { - for (y=0; y<2; y++) { - if (quadnode_intersect_line(node->children[x][y], &line)) { - ret = goodline_two(node->children[x][y], - v1, v2); - if (!ret) return 0; - } - } - } - - return 1; - } else { - float vv1[3], vv2[3], mid[3], a[3], b[3]; - qline *line; - - for (line=node->lines.first; line; line=line->next) { - VECCOPY(vv1, line->a); - VECCOPY(vv2, line->b); - - /*VecAddf(mid, vv1, vv2); - VecMulf(mid, 0.5f); - - VecSubf(a, vv1, mid); - VecSubf(b, vv2, mid); - - VecMulf(a, 0.999f); - VecMulf(b, 0.999f); - - VecAddf(vv1, mid, a); - VecAddf(vv2, mid, b);*/ - - if (linecrosses(vv1, vv2, v1, v2)) return 0; - - } - - return 1; - } - - return 1; -} - -static int goodline(quadnode *node, float (*projectverts)[3], int v1i, - int v2i, int nvert, float *outv) -{ - float v1[3], v2[3], p[3], a[3], b[3]; +int goodline(float (*projectverts)[3], int v1i, + int v2i, int v3i, int nvert) { + float v1[3], v2[3], v3[3], *pv1, *pv2; + int i; VECCOPY(v1, projectverts[v1i]); VECCOPY(v2, projectverts[v2i]); - VecAddf(p, v1, v2); - VecMulf(p, 0.5f); - - VecSubf(a, v1, p); - VecSubf(b, v2, p); - VecMulf(a, 0.999f); - VecMulf(b, 0.999f); + VECCOPY(v3, projectverts[v3i]); - VecAddf(v1, a, p); - VecAddf(v2, b, p); - - if (goodline_one(node, p, outv) % 2 == 0) return 0; - //if (!goodline_two(node, v1, v2)) return 0; + if (winding(v1, v2, v3)) return 0; + + for (i=0; iroot, verts, v1->head.eflag2, - v3->head.eflag2, nvert, outv)) + if (isear && !goodline(verts, v1->head.eflag2, v2->head.eflag2, + v3->head.eflag2, nvert)) isear = 0; if(isear){ @@ -776,14 +487,13 @@ static BMLoop *find_ear(BMesh *bm, BMFace *f, quadtree *tree, * -Modify this to try and find ears that will not create a non-manifold face after conversion back to editmesh * */ -void BM_Triangulate_Face(BMesh *bm, BMFace *f, float (*projectverts)[3], int newedgeflag, int newfaceflag) +void BM_Triangulate_Face(BMesh *bm, BMFace *f, float (*projectverts)[3], + int newedgeflag, int newfaceflag) { int i, done, nvert; + float no[3]; BMLoop *l, *newl, *nextloop; BMVert *v; - quadtree *tree; - float outv[3] = {-1.0e30f, -1.0e30f, -1.0e30f}; - float min[3] = {1.0e30f, 1.0e30f, 1.0e30f};; /*copy vertex coordinates to vertspace array*/ i = 0; @@ -795,46 +505,33 @@ void BM_Triangulate_Face(BMesh *bm, BMFace *f, float (*projectverts)[3], int new l = (BMLoop*)(l->head.next); }while(l != f->loopbase); - //bmesh_update_face_normal(bm, f, projectverts); + ///bmesh_update_face_normal(bm, f, projectverts); - compute_poly_normal(f->no, projectverts, f->len); - compute_poly_plane(projectverts, i); + compute_poly_normal(f->no, projectverts, f->len); poly_rotate_plane(f->no, projectverts, i); - + /*check if we rotated the wrong way*/ + compute_poly_normal(no, projectverts, f->len); + if (no[2] < 0) { + poly_rotate_plane(no, projectverts, i); + } + nvert = f->len; + //compute_poly_plane(projectverts, i); for (i=0; ilen > 3){ done = 1; - l = find_ear(bm, f, tree, projectverts, nvert, outv); + l = find_ear(bm, f, projectverts, nvert); if(l) { done = 0; v = l->v; f = bmesh_sfme(bm, f, ((BMLoop*)(l->head.prev))->v, ((BMLoop*)(l->head.next))->v, &newl); if (!f) { printf("yeek! triangulator failed to split face!\n"); - quadtree_free(tree); break; } @@ -859,7 +556,6 @@ void BM_Triangulate_Face(BMesh *bm, BMFace *f, float (*projectverts)[3], int new f = bmesh_sfme(bm, l->f, l->v,nextloop->v, &newl); if (!f) { printf("triangle fan step of triangulator failed.\n"); - quadtree_free(tree); return; } @@ -868,6 +564,4 @@ void BM_Triangulate_Face(BMesh *bm, BMFace *f, float (*projectverts)[3], int new l = nextloop; } } - - quadtree_free(tree); } diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h index 0353fb8c28d..b289994c1ee 100644 --- a/source/blender/editors/include/ED_mesh.h +++ b/source/blender/editors/include/ED_mesh.h @@ -68,6 +68,10 @@ struct CustomData; #define B_JOINTRIA_SHARP 0X800 #define B_JOINTRIA_MAT 0X1000 +/* bmeshutils.c */ + +/*recalculate tesselations for ngons*/ +void EDBM_Tesselate(struct EditMesh *em); /* meshtools.c */ diff --git a/source/blender/editors/mesh/bmeshutils.c b/source/blender/editors/mesh/bmeshutils.c index c2f79c835c8..9e3d0379ba3 100644 --- a/source/blender/editors/mesh/bmeshutils.c +++ b/source/blender/editors/mesh/bmeshutils.c @@ -89,6 +89,32 @@ #include "mesh_intern.h" #include "bmesh.h" +void EDBM_Tesselate(EditMesh *em) +{ + EditMesh *em2; + EditFace *efa; + BMesh *bm; + int found=0; + + for (efa=em->faces.first; efa; efa=efa->next) { + if ((efa->e1->h & EM_FGON) || (efa->e2->h & EM_FGON) || + (efa->e3->h & EM_FGON) || (efa->e4&&(efa->e4->h&EM_FGON))) + { + found = 1; + break; + } + } + + if (found) { + bm = editmesh_to_bmesh(em); + em2 = bmesh_to_editmesh(bm); + set_editMesh(em, em2); + + MEM_freeN(em2); + BM_Free_Mesh(bm); + } +} + int EDBM_CallOpf(EditMesh *em, wmOperator *op, char *fmt, ...) { BMesh *bm = editmesh_to_bmesh(em); diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index 276b09563a7..861681423e9 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -797,6 +797,11 @@ void postTrans (TransInfo *t) else if(t->spacetype==SPACE_ACTION) { if (t->customData) MEM_freeN(t->customData); + } else if (t->spacetype==SPACE_VIEW3D) { + if (t->obedit) { + /*retesselate*/ + EDBM_Tesselate(((Mesh*)t->obedit->data)->edit_mesh); + } } }