When a triangle gets split when it's added, retriangulate in an
effort to reduce the number of pieces. [git-p4: depot-paths = "//depot/solvespace/": change = 1743]
This commit is contained in:
parent
05b50e0af8
commit
c58dbf1676
126
mesh.cpp
126
mesh.cpp
@ -49,6 +49,110 @@ void SMesh::GetBounding(Vector *vmax, Vector *vmin) {
|
||||
}
|
||||
}
|
||||
|
||||
void SMesh::Simplify(int start) {
|
||||
#define MAX_TRIANGLES 500
|
||||
if(l.n - start > MAX_TRIANGLES) return;
|
||||
|
||||
STriangle tout[MAX_TRIANGLES];
|
||||
int toutc = 0;
|
||||
|
||||
Vector n, conv[MAX_TRIANGLES*3];
|
||||
int convc = 0;
|
||||
|
||||
int start0 = start;
|
||||
|
||||
int i, j;
|
||||
for(i = start; i < l.n; i++) {
|
||||
l.elem[i].tag = 0;
|
||||
}
|
||||
|
||||
for(;;) {
|
||||
convc = 0;
|
||||
for(i = start; i < l.n; i++) {
|
||||
STriangle *tr = &(l.elem[i]);
|
||||
if(tr->tag) continue;
|
||||
|
||||
tr->tag = 1;
|
||||
n = (tr->Normal()).WithMagnitude(1);
|
||||
conv[convc++] = tr->a;
|
||||
conv[convc++] = tr->b;
|
||||
conv[convc++] = tr->c;
|
||||
|
||||
start = i+1;
|
||||
break;
|
||||
}
|
||||
if(i >= l.n) break;
|
||||
|
||||
bool didAdd;
|
||||
do {
|
||||
didAdd = false;
|
||||
|
||||
for(j = 0; j < convc; j++) {
|
||||
Vector a = conv[WRAP((j-1), convc)],
|
||||
b = conv[j],
|
||||
d = conv[WRAP((j+1), convc)],
|
||||
e = conv[WRAP((j+2), convc)];
|
||||
|
||||
Vector c;
|
||||
for(i = start; i < l.n; i++) {
|
||||
STriangle *tr = &(l.elem[i]);
|
||||
if(tr->tag) continue;
|
||||
|
||||
if((tr->a).Equals(d) && (tr->b).Equals(b)) {
|
||||
c = tr->c;
|
||||
} else if((tr->b).Equals(d) && (tr->c).Equals(b)) {
|
||||
c = tr->a;
|
||||
} else if((tr->c).Equals(d) && (tr->a).Equals(b)) {
|
||||
c = tr->b;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
// The vertex at C must be convex; but the others must
|
||||
// be tested
|
||||
Vector ab = b.Minus(a);
|
||||
Vector bc = c.Minus(b);
|
||||
Vector cd = d.Minus(c);
|
||||
Vector de = e.Minus(d);
|
||||
|
||||
double bDot = (ab.Cross(bc)).Dot(n);
|
||||
double dDot = (cd.Cross(de)).Dot(n);
|
||||
|
||||
bDot /= min(ab.Magnitude(), bc.Magnitude());
|
||||
dDot /= min(cd.Magnitude(), de.Magnitude());
|
||||
|
||||
if(fabs(bDot) < LENGTH_EPS) {
|
||||
conv[j] = c;
|
||||
} else if(fabs(dDot) < LENGTH_EPS) {
|
||||
conv[WRAP((j+1), convc)] = c;
|
||||
} else if(bDot > 0 && dDot > 0) {
|
||||
// conv[j] is unchanged, conv[j+1] goes to [j+2]
|
||||
memmove(conv+j+2, conv+j+1,
|
||||
(convc - j - 1)*sizeof(conv[0]));
|
||||
conv[j+1] = c;
|
||||
convc++;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
didAdd = true;
|
||||
tr->tag = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while(didAdd);
|
||||
|
||||
for(i = 0; i < convc - 2; i++) {
|
||||
STriangle tr = { 0, conv[0], conv[i+1], conv[i+2] };
|
||||
tout[toutc++] = tr;
|
||||
}
|
||||
}
|
||||
|
||||
l.n = start0;
|
||||
for(i = 0; i < toutc; i++) {
|
||||
AddTriangle(&(tout[i]));
|
||||
}
|
||||
}
|
||||
|
||||
void SMesh::AddAgainstBsp(SMesh *srcm, SBsp3 *bsp3) {
|
||||
int i;
|
||||
|
||||
@ -64,7 +168,9 @@ void SMesh::AddAgainstBsp(SMesh *srcm, SBsp3 *bsp3) {
|
||||
} else {
|
||||
AddTriangle(st->a, st->b, st->c);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if(l.n - pn > 4) {
|
||||
Simplify(pn);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -83,6 +189,7 @@ void SMesh::MakeFromUnion(SMesh *a, SMesh *b) {
|
||||
}
|
||||
|
||||
void SMesh::MakeFromDifference(SMesh *a, SMesh *b) {
|
||||
SDWORD in = GetMilliseconds();
|
||||
SBsp3 *bspa = SBsp3::FromMesh(a);
|
||||
SBsp3 *bspb = SBsp3::FromMesh(b);
|
||||
|
||||
@ -93,6 +200,8 @@ void SMesh::MakeFromDifference(SMesh *a, SMesh *b) {
|
||||
flipNormal = false;
|
||||
keepCoplanar = false;
|
||||
AddAgainstBsp(a, bspb);
|
||||
dbp("dt = %d", GetMilliseconds() - in);
|
||||
dbp("tris = %d", l.n);
|
||||
}
|
||||
|
||||
SBsp2 *SBsp2::Alloc(void) { return (SBsp2 *)AllocTemporary(sizeof(SBsp2)); }
|
||||
@ -217,11 +326,14 @@ SBsp3 *SBsp3::InsertConvex(Vector *vertex, int cnt, SMesh *instead) {
|
||||
Vector e12 = (vertex[2]).Minus(vertex[1]);
|
||||
Vector out = e01.Cross(e12);
|
||||
|
||||
#define MAX_VERTICES 50
|
||||
if(cnt+1 >= MAX_VERTICES) goto triangulate;
|
||||
|
||||
int i;
|
||||
Vector on[2];
|
||||
bool *isPos = (bool *)AllocTemporary(cnt*sizeof(bool));
|
||||
bool *isNeg = (bool *)AllocTemporary(cnt*sizeof(bool));
|
||||
bool *isOn = (bool *)AllocTemporary(cnt*sizeof(bool));
|
||||
bool isPos[MAX_VERTICES];
|
||||
bool isNeg[MAX_VERTICES];
|
||||
bool isOn[MAX_VERTICES];
|
||||
int posc = 0, negc = 0, onc = 0;
|
||||
for(i = 0; i < cnt; i++) {
|
||||
double dt = n.Dot(vertex[i]);
|
||||
@ -258,15 +370,15 @@ SBsp3 *SBsp3::InsertConvex(Vector *vertex, int cnt, SMesh *instead) {
|
||||
return this;
|
||||
}
|
||||
|
||||
Vector *vpos = (Vector *)AllocTemporary((cnt+1)*sizeof(Vector));
|
||||
Vector *vneg = (Vector *)AllocTemporary((cnt+1)*sizeof(Vector));
|
||||
Vector vpos[MAX_VERTICES];
|
||||
Vector vneg[MAX_VERTICES];
|
||||
int npos = 0, nneg = 0;
|
||||
|
||||
Vector inter[2];
|
||||
int inters = 0;
|
||||
|
||||
for(i = 0; i < cnt; i++) {
|
||||
int ip = (i + 1) % cnt;
|
||||
int ip = WRAP((i + 1), cnt);
|
||||
|
||||
if(isPos[i]) {
|
||||
vpos[npos++] = vertex[i];
|
||||
|
@ -177,6 +177,8 @@ public:
|
||||
void DoBounding(Vector v, Vector *vmax, Vector *vmin);
|
||||
void GetBounding(Vector *vmax, Vector *vmin);
|
||||
|
||||
void Simplify(int start);
|
||||
|
||||
void AddAgainstBsp(SMesh *srcm, SBsp3 *bsp3);
|
||||
void MakeFromUnion(SMesh *a, SMesh *b);
|
||||
void MakeFromDifference(SMesh *a, SMesh *b);
|
||||
|
@ -505,7 +505,7 @@ void Group::Draw(void) {
|
||||
GLfloat mpf[] = { 0.1f, 0.1f, 0.1f, 1.0 };
|
||||
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, mpf);
|
||||
} else {
|
||||
GLfloat mpf[] = { 0.3f, 0.3f, 0.3f, 1.0 };
|
||||
GLfloat mpf[] = { 0.4f, 0.4f, 0.4f, 1.0 };
|
||||
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, mpf);
|
||||
}
|
||||
// The back faces are drawn in red; should never seem them, since we
|
||||
|
@ -15,6 +15,7 @@ void SolveSpace::Init(char *cmdLine) {
|
||||
GW.Init();
|
||||
|
||||
TW.Show();
|
||||
GenerateAll(false, 0, INT_MAX);
|
||||
}
|
||||
|
||||
bool SolveSpace::PruneOrphans(void) {
|
||||
|
@ -12,11 +12,17 @@
|
||||
#define max(x, y) ((x) > (y) ? (x) : (y))
|
||||
#endif
|
||||
|
||||
inline int WRAP(int v, int n) {
|
||||
while(v >= n) v -= n;
|
||||
while(v < 0) v += n;
|
||||
return v;
|
||||
}
|
||||
|
||||
#define SWAP(T, a, b) do { T temp = (a); (a) = (b); (b) = temp; } while(0)
|
||||
#define ZERO(v) memset((v), 0, sizeof(*(v)))
|
||||
#define CO(v) (v).x, (v).y, (v).z
|
||||
|
||||
#define LENGTH_EPS (0.0001)
|
||||
#define LENGTH_EPS (0.0000001)
|
||||
|
||||
#define isforname(c) (isalnum(c) || (c) == '_' || (c) == '-' || (c) == '#')
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user