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

This commit is contained in:
2009-03-06 06:06:14 +00:00
parent e91a478dab
commit f2371cbbae
6 changed files with 150 additions and 398 deletions

View File

@@ -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);

View File

@@ -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;

View File

@@ -1,4 +1,6 @@
#include <string.h>
#include <math.h>
#include <stdlib.h>
#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; i<nverts; i++) {
// verts[i][iaxis] = 0.0f;
//}
compute_poly_normal(normal, verts, nverts);
Crossf(axis, up, normal);
angle = VecAngle2(normal, up);
axis[0] *= -1;
axis[1] *= -1;
axis[2] *= -1;
if (angle == 0.0) return;
AxisAngleToQuat(q, axis, angle);
angle = saacos(normal[0]*up[0]+normal[1]*up[1] + normal[2]*up[2]);
if (angle == 0.0f) return;
AxisAngleToQuatd(q, axis, angle);
QuatToMat3(q, mat);
for(i = 0; i < nverts; i++)
@@ -361,357 +396,28 @@ int linecrosses(float *v1, float *v2, float *v3, float *v4)
return w1 == w2 && w2 == w3 && w3 == w4 && w4==w5;
}
static int goodline_notworking(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2, BMVert *v3,
float (*p)[3], float *outv, int nvert)
{
BMIter iter;
BMLoop *l;
int i, ret = 1;
float r = 0.00001f;
/*cases of a vector being too close to
an axis can cause problems, so this is to
prevent that.*/
for (i=0; i<3; i++) {
p[v1->head.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; i<nvert; i++) {
if (i!=v1->head.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; i<nvert; i++) {
//if (i == v1i or i == v3i) continue
pv1 = projectverts[i];
pv2 = projectverts[(i+1)%nvert];
if (linecrosses(pv1, pv2, v1, v3)) return 0l;
}
return 1;
}
static int goodline_old(float (*projectverts)[3], int v1i, int v2i, int nvert, float *outv)
{
/*the hardcoded stuff here, 0.999 and 1.0001, may be problems
in the future, not sure. - joeedh*/
float v1[3], v2[3], p[3], vv1[3], vv2[3], mid[3], a[3], b[3];
int i = 0, lcount=0;
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);
VecAddf(v1, p, a);
VecAddf(v2, p, b);
while (i < nvert) {
VECCOPY(vv1, projectverts[i]);
VECCOPY(vv2, projectverts[(i+1)%nvert]);
if (linecrosses(vv1, vv2, v1, v2)) return 0;
VecAddf(mid, vv1, vv2);
VecMulf(mid, 0.5f);
VecSubf(a, vv1, mid);
VecSubf(b, vv2, mid);
VecMulf(a, 1.0001f);
VecMulf(b, 1.0001f);
VecAddf(vv1, mid, a);
VecAddf(vv2, mid, b);
if (linecrosses(vv1, vv2, p, outv)) lcount += 1;
i += 1;
}
if ((lcount % 2) == 0) return 0;
return 1;
}
/*
* FIND EAR
*
@@ -721,8 +427,13 @@ static int goodline_old(float (*projectverts)[3], int v1i, int v2i, int nvert, f
*
*/
static BMLoop *find_ear(BMesh *bm, BMFace *f, quadtree *tree,
float (*verts)[3], int nvert, float *outv)
typedef struct quadtree {
int *dsdf;
int *dsfds;
} quadtree;
static BMLoop *find_ear(BMesh *bm, BMFace *f, float (*verts)[3],
int nvert)
{
BMVert *v1, *v2, *v3;
BMLoop *bestear = NULL, *l;
@@ -739,8 +450,8 @@ static BMLoop *find_ear(BMesh *bm, BMFace *f, quadtree *tree,
if (BM_Edge_Exist(v1, v3)) isear = 0;
if (isear && !goodline(tree->root, 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; i<nvert; i++) {
outv[0] = MAX2(outv[0], projectverts[i][0]+0.01f);
outv[1] = MAX2(outv[1], projectverts[i][1]+0.01f);
outv[2] = MAX2(outv[2], projectverts[i][2]+0.01f);
min[0] = MIN2(min[0], projectverts[i][0]-0.01f);
min[1] = MIN2(min[1], projectverts[i][1]-0.01f);
min[2] = MIN2(min[2], projectverts[i][2]-0.01f);
projectverts[i][2] = 0.0f;
}
outv[2] = 0.0f;
min[2] = 0.0f;
tree = quadree_new(min, outv);
outv[0] += 1.0f;
outv[1] += 1.0f;
for (i=0; i<nvert; i++) {
quadtree_insert(tree, projectverts[i], projectverts[(i+1)%nvert]);
}
done = 0;
while(!done && f->len > 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);
}

View File

@@ -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 */

View File

@@ -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);

View File

@@ -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);
}
}
}