Add code to extrude a triangle mesh, and to perform Boolean ops on
a triangle mesh in a BSP. That works, although it splits too often, the initial triangulations are not good quality, and coplanar faces are not yet handled. I'll do the coplanar thing tomorrow. [git-p4: depot-paths = "//depot/solvespace/": change = 1735]solver
parent
c079497762
commit
de46118324
32
glhelper.cpp
32
glhelper.cpp
|
@ -111,6 +111,22 @@ void glxColor4d(double r, double g, double b, double a)
|
||||||
if(!ColorLocked) glColor4d(r, g, b, a);
|
if(!ColorLocked) glColor4d(r, g, b, a);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void glxFillMesh(SMesh *m)
|
||||||
|
{
|
||||||
|
glEnable(GL_NORMALIZE);
|
||||||
|
glBegin(GL_TRIANGLES);
|
||||||
|
for(int i = 0; i < m->l.n; i++) {
|
||||||
|
STriangle *tr = &(m->l.elem[i]);
|
||||||
|
Vector n = tr->Normal();
|
||||||
|
glNormal3d(n.x, n.y, n.z);
|
||||||
|
|
||||||
|
glxVertex3v(tr->a);
|
||||||
|
glxVertex3v(tr->b);
|
||||||
|
glxVertex3v(tr->c);
|
||||||
|
}
|
||||||
|
glEnd();
|
||||||
|
}
|
||||||
|
|
||||||
static void GLX_CALLBACK Vertex(Vector *p) {
|
static void GLX_CALLBACK Vertex(Vector *p) {
|
||||||
glxVertex3v(*p);
|
glxVertex3v(*p);
|
||||||
}
|
}
|
||||||
|
@ -220,26 +236,22 @@ void glxDebugEdgeList(SEdgeList *el)
|
||||||
void glxDebugMesh(SMesh *m)
|
void glxDebugMesh(SMesh *m)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
glLineWidth(2);
|
glLineWidth(1);
|
||||||
glPointSize(7);
|
glPointSize(7);
|
||||||
glDisable(GL_DEPTH_TEST);
|
|
||||||
glxUnlockColor();
|
glxUnlockColor();
|
||||||
for(i = 0; i < m->l.n; i++) {
|
for(i = 0; i < m->l.n; i++) {
|
||||||
STriangle *t = &(m->l.elem[i]);
|
STriangle *t = &(m->l.elem[i]);
|
||||||
if(t->tag) continue;
|
if(t->tag) continue;
|
||||||
|
|
||||||
glxColor4d(0, 1, 0, 0.3);
|
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||||
glBegin(GL_LINE_LOOP);
|
glxColor4d(0, 1, 0, 1.0);
|
||||||
glxVertex3v(t->a);
|
glBegin(GL_TRIANGLES);
|
||||||
glxVertex3v(t->b);
|
|
||||||
glxVertex3v(t->c);
|
|
||||||
glEnd();
|
|
||||||
glxColor4d(0, 0, 1, 0.4);
|
|
||||||
glBegin(GL_POINTS);
|
|
||||||
glxVertex3v(t->a);
|
glxVertex3v(t->a);
|
||||||
glxVertex3v(t->b);
|
glxVertex3v(t->b);
|
||||||
glxVertex3v(t->c);
|
glxVertex3v(t->c);
|
||||||
glEnd();
|
glEnd();
|
||||||
|
glPolygonOffset(0, 0);
|
||||||
|
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -113,7 +113,7 @@ void GraphicsWindow::Init(void) {
|
||||||
showPoints = true;
|
showPoints = true;
|
||||||
showConstraints = true;
|
showConstraints = true;
|
||||||
showHdnLines = false;
|
showHdnLines = false;
|
||||||
showSolids = false;
|
showSolids = true;
|
||||||
|
|
||||||
solving = SOLVE_ALWAYS;
|
solving = SOLVE_ALWAYS;
|
||||||
|
|
||||||
|
@ -1181,11 +1181,31 @@ void GraphicsWindow::Paint(int w, int h) {
|
||||||
selection[i].Draw();
|
selection[i].Draw();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(SS.group.n >= 2) {
|
if(SS.group.n >= 5) {
|
||||||
SMesh m; ZERO(&m);
|
SMesh *ma = &(SS.group.elem[2].mesh);
|
||||||
(SS.group.elem[1].poly).TriangulateInto(&m);
|
SMesh *mb = &(SS.group.elem[4].mesh);
|
||||||
glxDebugMesh(&m);
|
|
||||||
m.Clear();
|
SBsp3 *pa = SBsp3::FromMesh(ma);
|
||||||
|
SBsp3 *pb = SBsp3::FromMesh(mb);
|
||||||
|
|
||||||
|
SMesh br; ZERO(&br);
|
||||||
|
for(i = 0; i < mb->l.n; i++) {
|
||||||
|
pa->Insert(&(mb->l.elem[i]), &br, true, false);
|
||||||
|
}
|
||||||
|
for(i = 0; i < ma->l.n; i++) {
|
||||||
|
pb->Insert(&(ma->l.elem[i]), &br, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
glEnable(GL_LIGHTING);
|
||||||
|
glxFillMesh(&br);
|
||||||
|
glDisable(GL_LIGHTING);
|
||||||
|
glxLockColorTo(0, 1, 0);
|
||||||
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
glxDebugMesh(&br);
|
||||||
|
|
||||||
|
br.Clear();
|
||||||
|
FreeAllTemporary();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
222
mesh.cpp
222
mesh.cpp
|
@ -4,6 +4,16 @@ void SMesh::Clear(void) {
|
||||||
l.Clear();
|
l.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SMesh::AddTriangle(Vector n, Vector a, Vector b, Vector c) {
|
||||||
|
Vector ab = b.Minus(a), bc = c.Minus(b);
|
||||||
|
Vector np = ab.Cross(bc);
|
||||||
|
if(np.Dot(n) > 0) {
|
||||||
|
AddTriangle(a, b, c);
|
||||||
|
} else {
|
||||||
|
AddTriangle(c, b, a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void SMesh::AddTriangle(Vector a, Vector b, Vector c) {
|
void SMesh::AddTriangle(Vector a, Vector b, Vector c) {
|
||||||
STriangle t; ZERO(&t);
|
STriangle t; ZERO(&t);
|
||||||
t.a = a;
|
t.a = a;
|
||||||
|
@ -12,3 +22,215 @@ void SMesh::AddTriangle(Vector a, Vector b, Vector c) {
|
||||||
l.Add(&t);
|
l.Add(&t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SBsp2 *SBsp2::Alloc(void) { return (SBsp2 *)AllocTemporary(sizeof(SBsp2)); }
|
||||||
|
SBsp3 *SBsp3::Alloc(void) { return (SBsp3 *)AllocTemporary(sizeof(SBsp3)); }
|
||||||
|
|
||||||
|
SBsp3 *SBsp3::FromMesh(SMesh *m) {
|
||||||
|
int i;
|
||||||
|
SBsp3 *ret = NULL;
|
||||||
|
for(i = 0; i < m->l.n; i++) {
|
||||||
|
ret = ret->Insert(&(m->l.elem[i]), NULL, false, false);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector SBsp3::IntersectionWith(Vector a, Vector b) {
|
||||||
|
double da = a.Dot(n) - d;
|
||||||
|
double db = b.Dot(n) - d;
|
||||||
|
if(da*db > 0) oops();
|
||||||
|
|
||||||
|
double dab = (db - da);
|
||||||
|
Vector r = (a.ScaledBy(db/dab)).Plus(b.ScaledBy(-da/dab));
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SBsp3::InsertHow(int how, STriangle *tr,
|
||||||
|
SMesh *instead, bool flip, bool cpl)
|
||||||
|
{
|
||||||
|
switch(how) {
|
||||||
|
case POS:
|
||||||
|
if(instead && !pos) goto alt;
|
||||||
|
pos = pos->Insert(tr, instead, flip, cpl);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NEG:
|
||||||
|
if(instead && !neg) goto alt;
|
||||||
|
neg = neg->Insert(tr, instead, flip, cpl);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case COPLANAR: {
|
||||||
|
if(instead) goto alt;
|
||||||
|
SBsp3 *m = Alloc();
|
||||||
|
m->n = n;
|
||||||
|
m->d = d;
|
||||||
|
m->tri = *tr;
|
||||||
|
m->more = more;
|
||||||
|
more = m;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: oops();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
|
||||||
|
alt:
|
||||||
|
if(how == POS && !flip) {
|
||||||
|
instead->AddTriangle(tr->a, tr->b, tr->c);
|
||||||
|
}
|
||||||
|
if(how == NEG && flip) {
|
||||||
|
instead->AddTriangle(tr->c, tr->b, tr->a);
|
||||||
|
}
|
||||||
|
if(how == COPLANAR) {
|
||||||
|
// Arbitrarily pick a side. This fails if two faces are coplanar.
|
||||||
|
InsertHow(POS, tr, instead, flip, cpl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SBsp3 *SBsp3::Insert(STriangle *tr, SMesh *instead, bool flip, bool cpl) {
|
||||||
|
if(!this) {
|
||||||
|
// Brand new node; so allocate for it, and fill us in.
|
||||||
|
SBsp3 *r = Alloc();
|
||||||
|
r->n = tr->Normal();
|
||||||
|
r->d = (tr->a).Dot(r->n);
|
||||||
|
r->tri = *tr;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
double dt[3] = { (tr->a).Dot(n), (tr->b).Dot(n), (tr->c).Dot(n) };
|
||||||
|
|
||||||
|
int inc = 0, posc = 0, negc = 0;
|
||||||
|
bool ispos[3], isneg[3], ison[3];
|
||||||
|
ZERO(&ispos); ZERO(&isneg); ZERO(&ison);
|
||||||
|
// Count vertices in the plane
|
||||||
|
for(int i = 0; i < 3; i++) {
|
||||||
|
if(fabs(dt[i] - d) < LENGTH_EPS) {
|
||||||
|
inc++;
|
||||||
|
ison[i] = true;
|
||||||
|
} else if(dt[i] > d) {
|
||||||
|
posc++;
|
||||||
|
ispos[i] = true;
|
||||||
|
} else {
|
||||||
|
negc++;
|
||||||
|
isneg[i] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// All vertices in-plane
|
||||||
|
if(inc == 3) {
|
||||||
|
InsertHow(COPLANAR, tr, instead, flip, cpl);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// No split required
|
||||||
|
if(posc == 0 || negc == 0) {
|
||||||
|
if(inc == 2) {
|
||||||
|
// Two vertices in-plane, other above or below
|
||||||
|
// XXX do edge bsp
|
||||||
|
}
|
||||||
|
|
||||||
|
if(posc > 0) {
|
||||||
|
InsertHow(POS, tr, instead, flip, cpl);
|
||||||
|
} else {
|
||||||
|
InsertHow(NEG, tr, instead, flip, cpl);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The polygon must be split into two pieces, one above, one below.
|
||||||
|
Vector a, b, c;
|
||||||
|
|
||||||
|
// Standardize so that a is on the plane
|
||||||
|
if(posc == 1 && negc == 1 && inc == 1) {
|
||||||
|
bool bpos;
|
||||||
|
if (ison[0]) { a = tr->a; b = tr->b; c = tr->c; bpos = ispos[1];
|
||||||
|
} else if(ison[1]) { a = tr->b; b = tr->c; c = tr->a; bpos = ispos[2];
|
||||||
|
} else if(ison[2]) { a = tr->c; b = tr->a; c = tr->b; bpos = ispos[0];
|
||||||
|
} else oops();
|
||||||
|
|
||||||
|
Vector bPc = IntersectionWith(b, c);
|
||||||
|
STriangle btri = { 0, a, b, bPc };
|
||||||
|
STriangle ctri = { 0, c, a, bPc };
|
||||||
|
|
||||||
|
if(bpos) {
|
||||||
|
InsertHow(POS, &btri, instead, flip, cpl);
|
||||||
|
InsertHow(NEG, &ctri, instead, flip, cpl);
|
||||||
|
} else {
|
||||||
|
InsertHow(POS, &ctri, instead, flip, cpl);
|
||||||
|
InsertHow(NEG, &btri, instead, flip, cpl);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Standardize so that a is on one side, and b and c are on the other.
|
||||||
|
if(posc == 2 && negc == 1) {
|
||||||
|
if (isneg[0]) { a = tr->a; b = tr->b; c = tr->c;
|
||||||
|
} else if(isneg[1]) { a = tr->b; b = tr->c; c = tr->a;
|
||||||
|
} else if(isneg[2]) { a = tr->c; b = tr->a; c = tr->b;
|
||||||
|
} else oops();
|
||||||
|
|
||||||
|
} else if(posc == 1 && negc == 2) {
|
||||||
|
if (ispos[0]) { a = tr->a; b = tr->b; c = tr->c;
|
||||||
|
} else if(ispos[1]) { a = tr->b; b = tr->c; c = tr->a;
|
||||||
|
} else if(ispos[2]) { a = tr->c; b = tr->a; c = tr->b;
|
||||||
|
} else oops();
|
||||||
|
} else oops();
|
||||||
|
|
||||||
|
Vector aPb = IntersectionWith(a, b);
|
||||||
|
Vector cPa = IntersectionWith(c, a);
|
||||||
|
|
||||||
|
STriangle alone = { 0, a, aPb, cPa };
|
||||||
|
STriangle quad1 = { 0, aPb, b, c };
|
||||||
|
STriangle quad2 = { 0, aPb, c, cPa };
|
||||||
|
|
||||||
|
if(posc == 2 && negc == 1) {
|
||||||
|
InsertHow(POS, &quad1, instead, flip, cpl);
|
||||||
|
InsertHow(POS, &quad2, instead, flip, cpl);
|
||||||
|
InsertHow(NEG, &alone, instead, flip, cpl);
|
||||||
|
} else {
|
||||||
|
InsertHow(NEG, &quad1, instead, flip, cpl);
|
||||||
|
InsertHow(NEG, &quad2, instead, flip, cpl);
|
||||||
|
InsertHow(POS, &alone, instead, flip, cpl);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SBsp3::DebugDraw(void) {
|
||||||
|
if(!this) return;
|
||||||
|
|
||||||
|
pos->DebugDraw();
|
||||||
|
Vector norm = tri.Normal();
|
||||||
|
glNormal3d(norm.x, norm.y, norm.z);
|
||||||
|
|
||||||
|
glEnable(GL_LIGHTING);
|
||||||
|
glBegin(GL_TRIANGLES);
|
||||||
|
glxVertex3v(tri.a);
|
||||||
|
glxVertex3v(tri.b);
|
||||||
|
glxVertex3v(tri.c);
|
||||||
|
glEnd();
|
||||||
|
|
||||||
|
glDisable(GL_LIGHTING);
|
||||||
|
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||||
|
glPolygonOffset(-1, 0);
|
||||||
|
glBegin(GL_TRIANGLES);
|
||||||
|
glxVertex3v(tri.a);
|
||||||
|
glxVertex3v(tri.b);
|
||||||
|
glxVertex3v(tri.c);
|
||||||
|
glEnd();
|
||||||
|
|
||||||
|
glDisable(GL_LIGHTING);
|
||||||
|
glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
|
||||||
|
glPointSize(10);
|
||||||
|
glPolygonOffset(-1, 0);
|
||||||
|
glBegin(GL_TRIANGLES);
|
||||||
|
glxVertex3v(tri.a);
|
||||||
|
glxVertex3v(tri.b);
|
||||||
|
glxVertex3v(tri.c);
|
||||||
|
glEnd();
|
||||||
|
|
||||||
|
glPolygonOffset(0, 0);
|
||||||
|
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||||
|
|
||||||
|
more->DebugDraw();
|
||||||
|
neg->DebugDraw();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
13
polygon.cpp
13
polygon.cpp
|
@ -1,5 +1,10 @@
|
||||||
#include "solvespace.h"
|
#include "solvespace.h"
|
||||||
|
|
||||||
|
Vector STriangle::Normal(void) {
|
||||||
|
Vector ab = b.Minus(a), bc = c.Minus(b);
|
||||||
|
return ab.Cross(bc);
|
||||||
|
}
|
||||||
|
|
||||||
void SEdgeList::Clear(void) {
|
void SEdgeList::Clear(void) {
|
||||||
l.Clear();
|
l.Clear();
|
||||||
}
|
}
|
||||||
|
@ -222,6 +227,7 @@ void SPolygon::FixContourDirections(void) {
|
||||||
|
|
||||||
static int TriMode, TriVertexCount;
|
static int TriMode, TriVertexCount;
|
||||||
static Vector Tri1, TriNMinus1, TriNMinus2;
|
static Vector Tri1, TriNMinus1, TriNMinus2;
|
||||||
|
static Vector TriNormal;
|
||||||
static SMesh *TriMesh;
|
static SMesh *TriMesh;
|
||||||
static void GLX_CALLBACK TriBegin(int mode)
|
static void GLX_CALLBACK TriBegin(int mode)
|
||||||
{
|
{
|
||||||
|
@ -238,15 +244,15 @@ static void GLX_CALLBACK TriVertex(Vector *triN)
|
||||||
}
|
}
|
||||||
if(TriMode == GL_TRIANGLES) {
|
if(TriMode == GL_TRIANGLES) {
|
||||||
if((TriVertexCount % 3) == 2) {
|
if((TriVertexCount % 3) == 2) {
|
||||||
TriMesh->AddTriangle(TriNMinus2, TriNMinus1, *triN);
|
TriMesh->AddTriangle(TriNormal, TriNMinus2, TriNMinus1, *triN);
|
||||||
}
|
}
|
||||||
} else if(TriMode == GL_TRIANGLE_FAN) {
|
} else if(TriMode == GL_TRIANGLE_FAN) {
|
||||||
if(TriVertexCount >= 2) {
|
if(TriVertexCount >= 2) {
|
||||||
TriMesh->AddTriangle(Tri1, TriNMinus1, *triN);
|
TriMesh->AddTriangle(TriNormal, Tri1, TriNMinus1, *triN);
|
||||||
}
|
}
|
||||||
} else if(TriMode == GL_TRIANGLE_STRIP) {
|
} else if(TriMode == GL_TRIANGLE_STRIP) {
|
||||||
if(TriVertexCount >= 2) {
|
if(TriVertexCount >= 2) {
|
||||||
TriMesh->AddTriangle(TriNMinus2, TriNMinus1, *triN);
|
TriMesh->AddTriangle(TriNormal, TriNMinus2, TriNMinus1, *triN);
|
||||||
}
|
}
|
||||||
} else oops();
|
} else oops();
|
||||||
|
|
||||||
|
@ -256,6 +262,7 @@ static void GLX_CALLBACK TriVertex(Vector *triN)
|
||||||
}
|
}
|
||||||
void SPolygon::TriangulateInto(SMesh *m) {
|
void SPolygon::TriangulateInto(SMesh *m) {
|
||||||
TriMesh = m;
|
TriMesh = m;
|
||||||
|
TriNormal = normal;
|
||||||
|
|
||||||
GLUtesselator *gt = gluNewTess();
|
GLUtesselator *gt = gluNewTess();
|
||||||
gluTessCallback(gt, GLU_TESS_BEGIN, (glxCallbackFptr *)TriBegin);
|
gluTessCallback(gt, GLU_TESS_BEGIN, (glxCallbackFptr *)TriBegin);
|
||||||
|
|
21
polygon.h
21
polygon.h
|
@ -85,6 +85,8 @@ class STriangle {
|
||||||
public:
|
public:
|
||||||
int tag;
|
int tag;
|
||||||
Vector a, b, c;
|
Vector a, b, c;
|
||||||
|
|
||||||
|
Vector Normal(void);
|
||||||
};
|
};
|
||||||
|
|
||||||
class SBsp2 {
|
class SBsp2 {
|
||||||
|
@ -95,10 +97,16 @@ public:
|
||||||
SBsp2 *neg;
|
SBsp2 *neg;
|
||||||
|
|
||||||
SBsp2 *more;
|
SBsp2 *more;
|
||||||
|
|
||||||
|
void Insert(SEdge *se);
|
||||||
|
static SBsp2 *Alloc(void);
|
||||||
};
|
};
|
||||||
|
|
||||||
class SBsp3 {
|
class SBsp3 {
|
||||||
public:
|
public:
|
||||||
|
Vector n;
|
||||||
|
double d;
|
||||||
|
|
||||||
STriangle tri;
|
STriangle tri;
|
||||||
SBsp3 *pos;
|
SBsp3 *pos;
|
||||||
SBsp3 *neg;
|
SBsp3 *neg;
|
||||||
|
@ -106,6 +114,18 @@ public:
|
||||||
SBsp3 *more;
|
SBsp3 *more;
|
||||||
|
|
||||||
SBsp2 *edges;
|
SBsp2 *edges;
|
||||||
|
|
||||||
|
static SBsp3 *Alloc(void);
|
||||||
|
static SBsp3 *FromMesh(SMesh *m);
|
||||||
|
|
||||||
|
Vector IntersectionWith(Vector a, Vector b);
|
||||||
|
|
||||||
|
static const int POS = 100, NEG = 101, COPLANAR = 200;
|
||||||
|
void InsertHow(int how, STriangle *str, SMesh *instead, bool flip,bool cpl);
|
||||||
|
|
||||||
|
SBsp3 *Insert(STriangle *str, SMesh *instead, bool flip, bool cpl);
|
||||||
|
|
||||||
|
void DebugDraw(void);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -115,6 +135,7 @@ public:
|
||||||
|
|
||||||
void Clear(void);
|
void Clear(void);
|
||||||
void AddTriangle(Vector a, Vector b, Vector c);
|
void AddTriangle(Vector a, Vector b, Vector c);
|
||||||
|
void AddTriangle(Vector n, Vector a, Vector b, Vector c);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
123
sketch.cpp
123
sketch.cpp
|
@ -384,6 +384,7 @@ void Group::CopyEntity(hEntity in, int a, hParam dx, hParam dy, hParam dz,
|
||||||
void Group::MakePolygons(void) {
|
void Group::MakePolygons(void) {
|
||||||
int i;
|
int i;
|
||||||
poly.Clear();
|
poly.Clear();
|
||||||
|
mesh.Clear();
|
||||||
|
|
||||||
SEdgeList edges;
|
SEdgeList edges;
|
||||||
ZERO(&edges);
|
ZERO(&edges);
|
||||||
|
@ -400,70 +401,75 @@ void Group::MakePolygons(void) {
|
||||||
if(edges.AssemblePolygon(&poly, &error)) {
|
if(edges.AssemblePolygon(&poly, &error)) {
|
||||||
polyError.yes = false;
|
polyError.yes = false;
|
||||||
poly.normal = poly.ComputeNormal();
|
poly.normal = poly.ComputeNormal();
|
||||||
|
poly.FixContourDirections();
|
||||||
} else {
|
} else {
|
||||||
polyError.yes = true;
|
polyError.yes = true;
|
||||||
polyError.notClosedAt = error;
|
polyError.notClosedAt = error;
|
||||||
poly.Clear();
|
poly.Clear();
|
||||||
}
|
}
|
||||||
} else if(type == EXTRUDE) {
|
} else if(type == EXTRUDE) {
|
||||||
Vector translate;
|
int i;
|
||||||
translate.x = SS.GetParam(h.param(0))->val;
|
Group *src = SS.GetGroup(opA);
|
||||||
translate.y = SS.GetParam(h.param(1))->val;
|
Vector translate = Vector::MakeFrom(
|
||||||
translate.z = SS.GetParam(h.param(2))->val;
|
SS.GetParam(h.param(0))->val,
|
||||||
Vector t0, dt;
|
SS.GetParam(h.param(1))->val,
|
||||||
|
SS.GetParam(h.param(2))->val
|
||||||
|
);
|
||||||
|
Vector tbot, ttop;
|
||||||
if(subtype == EXTRUDE_ONE_SIDED) {
|
if(subtype == EXTRUDE_ONE_SIDED) {
|
||||||
t0 = Vector::MakeFrom(0, 0, 0); dt = translate;
|
tbot = Vector::MakeFrom(0, 0, 0); ttop = translate;
|
||||||
} else {
|
} else {
|
||||||
t0 = translate.ScaledBy(-1); dt = translate.ScaledBy(2);
|
tbot = translate.ScaledBy(-1); ttop = translate.ScaledBy(1);
|
||||||
}
|
}
|
||||||
|
bool flipBottom = translate.Dot(src->poly.normal) > 0;
|
||||||
|
|
||||||
|
// Get a triangulation of the source poly; this is not a closed mesh.
|
||||||
|
SMesh srcm; ZERO(&srcm);
|
||||||
|
(src->poly).TriangulateInto(&srcm);
|
||||||
|
|
||||||
|
SMesh outm; ZERO(&outm);
|
||||||
|
// Do the bottom; that has normal pointing opposite from translate
|
||||||
|
for(i = 0; i < srcm.l.n; i++) {
|
||||||
|
STriangle *st = &(srcm.l.elem[i]);
|
||||||
|
Vector at = (st->a).Plus(tbot),
|
||||||
|
bt = (st->b).Plus(tbot),
|
||||||
|
ct = (st->c).Plus(tbot);
|
||||||
|
if(flipBottom) {
|
||||||
|
mesh.AddTriangle(ct, bt, at);
|
||||||
|
} else {
|
||||||
|
mesh.AddTriangle(at, bt, ct);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// And the top; that has the normal pointing the same dir as translate
|
||||||
|
for(i = 0; i < srcm.l.n; i++) {
|
||||||
|
STriangle *st = &(srcm.l.elem[i]);
|
||||||
|
Vector at = (st->a).Plus(ttop),
|
||||||
|
bt = (st->b).Plus(ttop),
|
||||||
|
ct = (st->c).Plus(ttop);
|
||||||
|
if(flipBottom) {
|
||||||
|
mesh.AddTriangle(at, bt, ct);
|
||||||
|
} else {
|
||||||
|
mesh.AddTriangle(ct, bt, at);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
srcm.Clear();
|
||||||
// Get the source polygon to extrude, and break it down to edges
|
// Get the source polygon to extrude, and break it down to edges
|
||||||
edges.Clear();
|
edges.Clear();
|
||||||
Group *src = SS.GetGroup(opA);
|
|
||||||
|
|
||||||
(src->poly).MakeEdgesInto(&edges);
|
(src->poly).MakeEdgesInto(&edges);
|
||||||
|
|
||||||
|
// The sides; these are quads, represented as two triangles.
|
||||||
for(i = 0; i < edges.l.n; i++) {
|
for(i = 0; i < edges.l.n; i++) {
|
||||||
SEdge *edge = &(edges.l.elem[i]);
|
SEdge *edge = &(edges.l.elem[i]);
|
||||||
edge->a = (edge->a).Plus(t0);
|
Vector abot = (edge->a).Plus(tbot), bbot = (edge->b).Plus(tbot);
|
||||||
edge->b = (edge->b).Plus(t0);
|
Vector atop = (edge->a).Plus(ttop), btop = (edge->b).Plus(ttop);
|
||||||
|
if(flipBottom) {
|
||||||
|
mesh.AddTriangle(bbot, abot, atop);
|
||||||
|
mesh.AddTriangle(bbot, atop, btop);
|
||||||
|
} else {
|
||||||
|
mesh.AddTriangle(abot, bbot, atop);
|
||||||
|
mesh.AddTriangle(bbot, btop, atop);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SPolygon np;
|
|
||||||
memset(&np, 0, sizeof(np));
|
|
||||||
// The bottom
|
|
||||||
if(!edges.AssemblePolygon(&np, NULL)) oops();
|
|
||||||
Vector n = np.ComputeNormal();
|
|
||||||
if(translate.Dot(n) > 0) {
|
|
||||||
n = n.ScaledBy(-1);
|
|
||||||
}
|
|
||||||
np.normal = n;
|
|
||||||
np.FixContourDirections();
|
|
||||||
|
|
||||||
// Regenerate the edges, with the contour directions fixed up.
|
|
||||||
edges.Clear();
|
|
||||||
np.MakeEdgesInto(&edges);
|
|
||||||
|
|
||||||
// The sides
|
|
||||||
int i;
|
|
||||||
for(i = 0; i < edges.l.n; i++) {
|
|
||||||
SEdge *edge = &(edges.l.elem[i]);
|
|
||||||
memset(&np, 0, sizeof(np));
|
|
||||||
np.AddEmptyContour();
|
|
||||||
np.AddPoint(edge->a);
|
|
||||||
np.AddPoint(edge->b);
|
|
||||||
np.AddPoint((edge->b).Plus(dt));
|
|
||||||
np.AddPoint((edge->a).Plus(dt));
|
|
||||||
np.AddPoint(edge->a);
|
|
||||||
np.normal = ((edge->a).Minus(edge->b).Cross(n)).WithMagnitude(1);
|
|
||||||
|
|
||||||
edge->a = (edge->a).Plus(dt);
|
|
||||||
edge->b = (edge->b).Plus(dt);
|
|
||||||
}
|
|
||||||
|
|
||||||
// The top
|
|
||||||
memset(&np, 0, sizeof(np));
|
|
||||||
if(!edges.AssemblePolygon(&np, NULL)) oops();
|
|
||||||
np.normal = n.ScaledBy(-1);
|
|
||||||
}
|
}
|
||||||
edges.Clear();
|
edges.Clear();
|
||||||
}
|
}
|
||||||
|
@ -471,6 +477,12 @@ void Group::MakePolygons(void) {
|
||||||
void Group::Draw(void) {
|
void Group::Draw(void) {
|
||||||
if(!visible) return;
|
if(!visible) return;
|
||||||
|
|
||||||
|
|
||||||
|
GLfloat mpf[] = { 0.4f, 0.4f, 0.4f, 1.0 };
|
||||||
|
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, mpf);
|
||||||
|
GLfloat mpb[] = { 1.0f, 0.1f, 0.1f, 1.0 };
|
||||||
|
glMaterialfv(GL_BACK, GL_AMBIENT_AND_DIFFUSE, mpb);
|
||||||
|
|
||||||
if(polyError.yes) {
|
if(polyError.yes) {
|
||||||
glxColor4d(1, 0, 0, 0.2);
|
glxColor4d(1, 0, 0, 0.2);
|
||||||
glLineWidth(10);
|
glLineWidth(10);
|
||||||
|
@ -486,16 +498,13 @@ void Group::Draw(void) {
|
||||||
glxWriteText("not closed contour!");
|
glxWriteText("not closed contour!");
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
} else {
|
} else {
|
||||||
int i;
|
// glxFillPolygon(&poly);
|
||||||
glEnable(GL_LIGHTING);
|
|
||||||
GLfloat mpf[] = { 0.3f, 1.0f, 0.3f, 0.5 };
|
|
||||||
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, mpf);
|
|
||||||
GLfloat mpb[] = { 1.0f, 0.3f, 0.3f, 0.5 };
|
|
||||||
glMaterialfv(GL_BACK, GL_AMBIENT_AND_DIFFUSE, mpb);
|
|
||||||
glxFillPolygon(&poly);
|
|
||||||
|
|
||||||
glDisable(GL_LIGHTING);
|
|
||||||
}
|
}
|
||||||
|
glEnable(GL_LIGHTING);
|
||||||
|
// glxFillMesh(&mesh);
|
||||||
|
glDisable(GL_LIGHTING);
|
||||||
|
|
||||||
|
// glxDebugMesh(&mesh);
|
||||||
}
|
}
|
||||||
|
|
||||||
hParam Request::AddParam(IdList<Param,hParam> *param, hParam hp) {
|
hParam Request::AddParam(IdList<Param,hParam> *param, hParam hp) {
|
||||||
|
|
|
@ -77,6 +77,7 @@ void glxVertex3v(Vector u);
|
||||||
typedef void GLX_CALLBACK glxCallbackFptr(void);
|
typedef void GLX_CALLBACK glxCallbackFptr(void);
|
||||||
void glxTesselatePolygon(GLUtesselator *gt, SPolygon *p);
|
void glxTesselatePolygon(GLUtesselator *gt, SPolygon *p);
|
||||||
void glxFillPolygon(SPolygon *p);
|
void glxFillPolygon(SPolygon *p);
|
||||||
|
void glxFillMesh(SMesh *m);
|
||||||
void glxDebugPolygon(SPolygon *p);
|
void glxDebugPolygon(SPolygon *p);
|
||||||
void glxDebugEdgeList(SEdgeList *l);
|
void glxDebugEdgeList(SEdgeList *l);
|
||||||
void glxDebugMesh(SMesh *m);
|
void glxDebugMesh(SMesh *m);
|
||||||
|
|
Loading…
Reference in New Issue