2013-07-29 06:08:34 +08:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Binary space partitioning tree, used to represent a volume in 3-space
|
|
|
|
// bounded by a triangle mesh. These are used to compute Boolean operations
|
|
|
|
// on meshes. These aren't used for anything relating to an SShell of
|
|
|
|
// ratpoly surfaces.
|
|
|
|
//
|
|
|
|
// Copyright 2008-2013 Jonathan Westhues.
|
|
|
|
//-----------------------------------------------------------------------------
|
2008-06-23 16:37:12 +08:00
|
|
|
#include "solvespace.h"
|
|
|
|
|
2016-05-05 13:54:05 +08:00
|
|
|
SBsp2 *SBsp2::Alloc() { return (SBsp2 *)AllocTemporary(sizeof(SBsp2)); }
|
|
|
|
SBsp3 *SBsp3::Alloc() { return (SBsp3 *)AllocTemporary(sizeof(SBsp3)); }
|
2008-06-23 16:37:12 +08:00
|
|
|
|
|
|
|
SBsp3 *SBsp3::FromMesh(SMesh *m) {
|
|
|
|
SBsp3 *bsp3 = NULL;
|
|
|
|
int i;
|
|
|
|
|
2015-03-27 23:31:23 +08:00
|
|
|
SMesh mc = {};
|
2008-06-23 16:37:12 +08:00
|
|
|
for(i = 0; i < m->l.n; i++) {
|
|
|
|
mc.AddTriangle(&(m->l.elem[i]));
|
|
|
|
}
|
|
|
|
|
2008-02-07 17:57:59 +08:00
|
|
|
srand(0); // Let's be deterministic, at least!
|
|
|
|
int n = mc.l.n;
|
|
|
|
while(n > 1) {
|
|
|
|
int k = rand() % n;
|
|
|
|
n--;
|
2015-03-27 23:43:28 +08:00
|
|
|
swap(mc.l.elem[k], mc.l.elem[n]);
|
2008-02-07 17:57:59 +08:00
|
|
|
}
|
2008-06-23 16:37:12 +08:00
|
|
|
|
|
|
|
for(i = 0; i < mc.l.n; i++) {
|
2016-03-25 22:16:58 +08:00
|
|
|
bsp3 = InsertOrCreate(bsp3, &(mc.l.elem[i]), NULL);
|
2008-06-23 16:37:12 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
mc.Clear();
|
|
|
|
return bsp3;
|
|
|
|
}
|
|
|
|
|
2016-05-21 13:18:00 +08:00
|
|
|
Vector SBsp3::IntersectionWith(Vector a, Vector b) const {
|
2008-06-23 16:37:12 +08:00
|
|
|
double da = a.Dot(n) - d;
|
|
|
|
double db = b.Dot(n) - d;
|
2016-05-19 06:51:36 +08:00
|
|
|
ssassert(da*db < 0, "Expected segment to intersect BSP node");
|
2008-06-23 16:37:12 +08:00
|
|
|
|
|
|
|
double dab = (db - da);
|
|
|
|
return (a.ScaledBy(db/dab)).Plus(b.ScaledBy(-da/dab));
|
|
|
|
}
|
|
|
|
|
|
|
|
void SBsp3::InsertInPlane(bool pos2, STriangle *tr, SMesh *m) {
|
|
|
|
Vector tc = ((tr->a).Plus(tr->b).Plus(tr->c)).ScaledBy(1.0/3);
|
|
|
|
|
|
|
|
bool onFace = false;
|
2013-08-27 03:36:00 +08:00
|
|
|
bool sameNormal = false;
|
2008-06-23 16:37:12 +08:00
|
|
|
double maxNormalMag = -1;
|
|
|
|
|
|
|
|
Vector lln, trn = tr->Normal();
|
|
|
|
|
|
|
|
SBsp3 *ll = this;
|
|
|
|
while(ll) {
|
|
|
|
if((ll->tri).ContainsPoint(tc)) {
|
|
|
|
onFace = true;
|
|
|
|
// If the mesh contains almost-zero-area triangles, and we're
|
|
|
|
// just on the edge of one of those, then don't trust its normal.
|
|
|
|
lln = (ll->tri).Normal();
|
|
|
|
if(lln.Magnitude() > maxNormalMag) {
|
|
|
|
sameNormal = trn.Dot(lln) > 0;
|
|
|
|
maxNormalMag = lln.Magnitude();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ll = ll->more;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(m->flipNormal && ((!pos2 && !onFace) ||
|
|
|
|
(onFace && !sameNormal && m->keepCoplanar)))
|
|
|
|
{
|
|
|
|
m->AddTriangle(tr->meta, tr->c, tr->b, tr->a);
|
2015-03-29 08:30:52 +08:00
|
|
|
} else if(!(m->flipNormal) && ((pos2 && !onFace) ||
|
2008-06-23 16:37:12 +08:00
|
|
|
(onFace && sameNormal && m->keepCoplanar)))
|
|
|
|
{
|
|
|
|
m->AddTriangle(tr->meta, tr->a, tr->b, tr->c);
|
|
|
|
} else {
|
|
|
|
m->atLeastOneDiscarded = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 16:31:20 +08:00
|
|
|
void SBsp3::InsertHow(BspClass how, STriangle *tr, SMesh *instead) {
|
2008-06-23 16:37:12 +08:00
|
|
|
switch(how) {
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 16:31:20 +08:00
|
|
|
case BspClass::POS:
|
2008-06-23 16:37:12 +08:00
|
|
|
if(instead && !pos) goto alt;
|
2016-03-25 22:16:58 +08:00
|
|
|
pos = InsertOrCreate(pos, tr, instead);
|
2008-06-23 16:37:12 +08:00
|
|
|
break;
|
|
|
|
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 16:31:20 +08:00
|
|
|
case BspClass::NEG:
|
2008-06-23 16:37:12 +08:00
|
|
|
if(instead && !neg) goto alt;
|
2016-03-25 22:16:58 +08:00
|
|
|
neg = InsertOrCreate(neg, tr, instead);
|
2008-06-23 16:37:12 +08:00
|
|
|
break;
|
|
|
|
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 16:31:20 +08:00
|
|
|
case BspClass::COPLANAR: {
|
2008-06-23 16:37:12 +08:00
|
|
|
if(instead) goto alt;
|
|
|
|
SBsp3 *m = Alloc();
|
|
|
|
m->n = n;
|
|
|
|
m->d = d;
|
|
|
|
m->tri = *tr;
|
|
|
|
m->more = more;
|
|
|
|
more = m;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
|
|
|
|
alt:
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 16:31:20 +08:00
|
|
|
if(how == BspClass::POS && !(instead->flipNormal)) {
|
2008-06-23 16:37:12 +08:00
|
|
|
instead->AddTriangle(tr->meta, tr->a, tr->b, tr->c);
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 16:31:20 +08:00
|
|
|
} else if(how == BspClass::NEG && instead->flipNormal) {
|
2008-06-23 16:37:12 +08:00
|
|
|
instead->AddTriangle(tr->meta, tr->c, tr->b, tr->a);
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 16:31:20 +08:00
|
|
|
} else if(how == BspClass::COPLANAR) {
|
2008-06-23 16:37:12 +08:00
|
|
|
if(edges) {
|
|
|
|
edges->InsertTriangle(tr, instead, this);
|
|
|
|
} else {
|
|
|
|
// I suppose this actually is allowed to happen, if the coplanar
|
|
|
|
// face is the leaf, and all of its neighbors are earlier in tree?
|
|
|
|
InsertInPlane(false, tr, instead);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
instead->atLeastOneDiscarded = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 16:31:20 +08:00
|
|
|
void SBsp3::InsertConvexHow(BspClass how, STriMeta meta, Vector *vertex, int n,
|
2008-06-23 16:37:12 +08:00
|
|
|
SMesh *instead)
|
|
|
|
{
|
|
|
|
switch(how) {
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 16:31:20 +08:00
|
|
|
case BspClass::POS:
|
2008-06-23 16:37:12 +08:00
|
|
|
if(pos) {
|
|
|
|
pos = pos->InsertConvex(meta, vertex, n, instead);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 16:31:20 +08:00
|
|
|
case BspClass::NEG:
|
2008-06-23 16:37:12 +08:00
|
|
|
if(neg) {
|
|
|
|
neg = neg->InsertConvex(meta, vertex, n, instead);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2016-05-19 06:51:36 +08:00
|
|
|
default: ssassert(false, "Unexpected BSP insert type");
|
2008-06-23 16:37:12 +08:00
|
|
|
}
|
|
|
|
int i;
|
|
|
|
for(i = 0; i < n - 2; i++) {
|
|
|
|
STriangle tr = STriangle::From(meta,
|
|
|
|
vertex[0], vertex[i+1], vertex[i+2]);
|
|
|
|
InsertHow(how, &tr, instead);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SBsp3 *SBsp3::InsertConvex(STriMeta meta, Vector *vertex, int cnt,
|
|
|
|
SMesh *instead)
|
|
|
|
{
|
|
|
|
Vector e01 = (vertex[1]).Minus(vertex[0]);
|
|
|
|
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[MAX_VERTICES];
|
|
|
|
bool isNeg[MAX_VERTICES];
|
|
|
|
bool isOn[MAX_VERTICES];
|
2013-08-27 03:08:16 +08:00
|
|
|
int posc, negc, onc; posc = negc = onc = 0;
|
2008-06-23 16:37:12 +08:00
|
|
|
for(i = 0; i < cnt; i++) {
|
|
|
|
double dt = n.Dot(vertex[i]);
|
|
|
|
isPos[i] = isNeg[i] = isOn[i] = false;
|
|
|
|
if(fabs(dt - d) < LENGTH_EPS) {
|
|
|
|
isOn[i] = true;
|
|
|
|
if(onc < 2) {
|
|
|
|
on[onc] = vertex[i];
|
|
|
|
}
|
|
|
|
onc++;
|
|
|
|
} else if(dt > d) {
|
2015-03-29 08:30:52 +08:00
|
|
|
isPos[i] = true;
|
2008-06-23 16:37:12 +08:00
|
|
|
posc++;
|
|
|
|
} else {
|
|
|
|
isNeg[i] = true;
|
|
|
|
negc++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(onc != 2 && onc != 1 && onc != 0) goto triangulate;
|
|
|
|
|
|
|
|
if(onc == 2) {
|
|
|
|
if(!instead) {
|
|
|
|
SEdge se = SEdge::From(on[0], on[1]);
|
2016-03-25 22:16:58 +08:00
|
|
|
edges = SBsp2::InsertOrCreateEdge(edges, &se, n, out);
|
2008-06-23 16:37:12 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(posc == 0) {
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 16:31:20 +08:00
|
|
|
InsertConvexHow(BspClass::NEG, meta, vertex, cnt, instead);
|
2008-06-23 16:37:12 +08:00
|
|
|
return this;
|
|
|
|
}
|
|
|
|
if(negc == 0) {
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 16:31:20 +08:00
|
|
|
InsertConvexHow(BspClass::POS, meta, vertex, cnt, instead);
|
2008-06-23 16:37:12 +08:00
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
Vector vpos[MAX_VERTICES];
|
|
|
|
Vector vneg[MAX_VERTICES];
|
2013-08-27 03:08:16 +08:00
|
|
|
int npos, nneg; npos = nneg = 0;
|
2008-06-23 16:37:12 +08:00
|
|
|
|
|
|
|
Vector inter[2];
|
2013-08-27 03:08:16 +08:00
|
|
|
int inters; inters = 0;
|
2008-06-23 16:37:12 +08:00
|
|
|
|
|
|
|
for(i = 0; i < cnt; i++) {
|
|
|
|
int ip = WRAP((i + 1), cnt);
|
|
|
|
|
|
|
|
if(isPos[i]) {
|
|
|
|
vpos[npos++] = vertex[i];
|
|
|
|
}
|
|
|
|
if(isNeg[i]) {
|
|
|
|
vneg[nneg++] = vertex[i];
|
|
|
|
}
|
|
|
|
if(isOn[i]) {
|
|
|
|
vneg[nneg++] = vertex[i];
|
|
|
|
vpos[npos++] = vertex[i];
|
|
|
|
}
|
|
|
|
if((isPos[i] && isNeg[ip]) || (isNeg[i] && isPos[ip])) {
|
|
|
|
Vector vi = IntersectionWith(vertex[i], vertex[ip]);
|
|
|
|
vpos[npos++] = vi;
|
|
|
|
vneg[nneg++] = vi;
|
|
|
|
|
2008-02-10 21:34:32 +08:00
|
|
|
if(inters >= 2) goto triangulate; // XXX shouldn't happen but does
|
2008-06-23 16:37:12 +08:00
|
|
|
inter[inters++] = vi;
|
|
|
|
}
|
|
|
|
}
|
2016-05-19 06:51:36 +08:00
|
|
|
if(npos > cnt + 1 || nneg > cnt + 1) ssassert(false, "Impossible");
|
2008-06-23 16:37:12 +08:00
|
|
|
|
|
|
|
if(!instead) {
|
|
|
|
if(inters == 2) {
|
|
|
|
SEdge se = SEdge::From(inter[0], inter[1]);
|
2016-03-25 22:16:58 +08:00
|
|
|
edges = SBsp2::InsertOrCreateEdge(edges, &se, n, out);
|
2008-06-23 16:37:12 +08:00
|
|
|
} else if(inters == 1 && onc == 1) {
|
|
|
|
SEdge se = SEdge::From(inter[0], on[0]);
|
2016-03-25 22:16:58 +08:00
|
|
|
edges = SBsp2::InsertOrCreateEdge(edges, &se, n, out);
|
2008-06-23 16:37:12 +08:00
|
|
|
} else if(inters == 0 && onc == 2) {
|
|
|
|
// We already handled this on-plane existing edge
|
2008-02-10 21:34:32 +08:00
|
|
|
} else {
|
|
|
|
goto triangulate;
|
|
|
|
}
|
2008-06-23 16:37:12 +08:00
|
|
|
}
|
2008-02-10 21:34:32 +08:00
|
|
|
if(nneg < 3 || npos < 3) goto triangulate; // XXX
|
2008-06-23 16:37:12 +08:00
|
|
|
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 16:31:20 +08:00
|
|
|
InsertConvexHow(BspClass::NEG, meta, vneg, nneg, instead);
|
|
|
|
InsertConvexHow(BspClass::POS, meta, vpos, npos, instead);
|
2008-06-23 16:37:12 +08:00
|
|
|
return this;
|
|
|
|
|
|
|
|
triangulate:
|
|
|
|
// We don't handle the special case for this; do it as triangles
|
|
|
|
SBsp3 *r = this;
|
|
|
|
for(i = 0; i < cnt - 2; i++) {
|
|
|
|
STriangle tr = STriangle::From(meta,
|
|
|
|
vertex[0], vertex[i+1], vertex[i+2]);
|
2016-03-25 22:16:58 +08:00
|
|
|
r = InsertOrCreate(r, &tr, instead);
|
2008-06-23 16:37:12 +08:00
|
|
|
}
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2016-03-25 22:16:58 +08:00
|
|
|
SBsp3 *SBsp3::InsertOrCreate(SBsp3 *where, STriangle *tr, SMesh *instead) {
|
|
|
|
if(where == NULL) {
|
2008-06-23 16:37:12 +08:00
|
|
|
if(instead) {
|
|
|
|
if(instead->flipNormal) {
|
|
|
|
instead->atLeastOneDiscarded = true;
|
|
|
|
} else {
|
|
|
|
instead->AddTriangle(tr->meta, tr->a, tr->b, tr->c);
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Brand new node; so allocate for it, and fill us in.
|
|
|
|
SBsp3 *r = Alloc();
|
|
|
|
r->n = (tr->Normal()).WithMagnitude(1);
|
|
|
|
r->d = (tr->a).Dot(r->n);
|
|
|
|
r->tri = *tr;
|
|
|
|
return r;
|
|
|
|
}
|
2016-03-25 22:16:58 +08:00
|
|
|
where->Insert(tr, instead);
|
|
|
|
return where;
|
|
|
|
}
|
2008-06-23 16:37:12 +08:00
|
|
|
|
2016-03-25 22:16:58 +08:00
|
|
|
void SBsp3::Insert(STriangle *tr, SMesh *instead) {
|
2008-06-23 16:37:12 +08:00
|
|
|
double dt[3] = { (tr->a).Dot(n), (tr->b).Dot(n), (tr->c).Dot(n) };
|
|
|
|
|
|
|
|
int inc = 0, posc = 0, negc = 0;
|
2015-03-27 23:31:23 +08:00
|
|
|
bool isPos[3] = {}, isNeg[3] = {}, isOn[3] = {};
|
2008-06-23 16:37:12 +08:00
|
|
|
// 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) {
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 16:31:20 +08:00
|
|
|
InsertHow(BspClass::COPLANAR, tr, instead);
|
2016-03-25 22:16:58 +08:00
|
|
|
return;
|
2008-06-23 16:37:12 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// No split required
|
|
|
|
if(posc == 0 || negc == 0) {
|
|
|
|
if(inc == 2) {
|
|
|
|
Vector a, b;
|
|
|
|
if (!isOn[0]) { a = tr->b; b = tr->c; }
|
|
|
|
else if(!isOn[1]) { a = tr->c; b = tr->a; }
|
|
|
|
else if(!isOn[2]) { a = tr->a; b = tr->b; }
|
2016-05-19 06:51:36 +08:00
|
|
|
else ssassert(false, "Impossible");
|
2008-06-23 16:37:12 +08:00
|
|
|
if(!instead) {
|
|
|
|
SEdge se = SEdge::From(a, b);
|
2016-03-25 22:16:58 +08:00
|
|
|
edges = SBsp2::InsertOrCreateEdge(edges, &se, n, tr->Normal());
|
2008-06-23 16:37:12 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(posc > 0) {
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 16:31:20 +08:00
|
|
|
InsertHow(BspClass::POS, tr, instead);
|
2008-06-23 16:37:12 +08:00
|
|
|
} else {
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 16:31:20 +08:00
|
|
|
InsertHow(BspClass::NEG, tr, instead);
|
2008-06-23 16:37:12 +08:00
|
|
|
}
|
2016-03-25 22:16:58 +08:00
|
|
|
return;
|
2008-06-23 16:37:12 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// The polygon must be split into two pieces, one above, one below.
|
|
|
|
Vector a, b, c;
|
|
|
|
|
|
|
|
if(posc == 1 && negc == 1 && inc == 1) {
|
|
|
|
bool bpos;
|
|
|
|
// Standardize so that a is on the plane
|
|
|
|
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];
|
2016-05-19 06:51:36 +08:00
|
|
|
} else ssassert(false, "Impossible");
|
2008-06-23 16:37:12 +08:00
|
|
|
|
|
|
|
Vector bPc = IntersectionWith(b, c);
|
|
|
|
STriangle btri = STriangle::From(tr->meta, a, b, bPc);
|
|
|
|
STriangle ctri = STriangle::From(tr->meta, c, a, bPc);
|
|
|
|
|
|
|
|
if(bpos) {
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 16:31:20 +08:00
|
|
|
InsertHow(BspClass::POS, &btri, instead);
|
|
|
|
InsertHow(BspClass::NEG, &ctri, instead);
|
2008-06-23 16:37:12 +08:00
|
|
|
} else {
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 16:31:20 +08:00
|
|
|
InsertHow(BspClass::POS, &ctri, instead);
|
|
|
|
InsertHow(BspClass::NEG, &btri, instead);
|
2008-06-23 16:37:12 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if(!instead) {
|
|
|
|
SEdge se = SEdge::From(a, bPc);
|
2016-03-25 22:16:58 +08:00
|
|
|
edges = SBsp2::InsertOrCreateEdge(edges, &se, n, tr->Normal());
|
2008-06-23 16:37:12 +08:00
|
|
|
}
|
|
|
|
|
2016-03-25 22:16:58 +08:00
|
|
|
return;
|
2008-06-23 16:37:12 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if(posc == 2 && negc == 1) {
|
|
|
|
// Standardize so that a is on one side, and b and c are on the other.
|
|
|
|
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;
|
2016-05-19 06:51:36 +08:00
|
|
|
} else ssassert(false, "Impossible");
|
2008-06-23 16:37:12 +08:00
|
|
|
|
|
|
|
} 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;
|
2016-05-19 06:51:36 +08:00
|
|
|
} else ssassert(false, "Impossible");
|
|
|
|
} else ssassert(false, "Impossible");
|
2008-06-23 16:37:12 +08:00
|
|
|
|
|
|
|
Vector aPb = IntersectionWith(a, b);
|
|
|
|
Vector cPa = IntersectionWith(c, a);
|
|
|
|
|
|
|
|
STriangle alone = STriangle::From(tr->meta, a, aPb, cPa);
|
|
|
|
Vector quad[4] = { aPb, b, c, cPa };
|
|
|
|
|
|
|
|
if(posc == 2 && negc == 1) {
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 16:31:20 +08:00
|
|
|
InsertConvexHow(BspClass::POS, tr->meta, quad, 4, instead);
|
|
|
|
InsertHow(BspClass::NEG, &alone, instead);
|
2008-06-23 16:37:12 +08:00
|
|
|
} else {
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 16:31:20 +08:00
|
|
|
InsertConvexHow(BspClass::NEG, tr->meta, quad, 4, instead);
|
|
|
|
InsertHow(BspClass::POS, &alone, instead);
|
2008-06-23 16:37:12 +08:00
|
|
|
}
|
|
|
|
if(!instead) {
|
|
|
|
SEdge se = SEdge::From(aPb, cPa);
|
2016-03-25 22:16:58 +08:00
|
|
|
edges = SBsp2::InsertOrCreateEdge(edges, &se, n, alone.Normal());
|
2008-06-23 16:37:12 +08:00
|
|
|
}
|
|
|
|
|
2016-03-25 22:16:58 +08:00
|
|
|
return;
|
2008-06-23 16:37:12 +08:00
|
|
|
}
|
|
|
|
|
2016-05-21 13:18:00 +08:00
|
|
|
void SBsp3::GenerateInPaintOrder(SMesh *m) const {
|
2009-03-18 00:33:46 +08:00
|
|
|
|
|
|
|
// Doesn't matter which branch we take if the normal has zero z
|
|
|
|
// component, so don't need a separate case for that.
|
|
|
|
if(n.z < 0) {
|
2016-03-25 22:16:58 +08:00
|
|
|
if(pos) pos->GenerateInPaintOrder(m);
|
2009-03-18 00:33:46 +08:00
|
|
|
} else {
|
2016-03-25 22:16:58 +08:00
|
|
|
if(neg) neg->GenerateInPaintOrder(m);
|
2009-03-18 00:33:46 +08:00
|
|
|
}
|
|
|
|
|
2016-05-21 13:18:00 +08:00
|
|
|
const SBsp3 *flip = this;
|
2009-03-18 00:33:46 +08:00
|
|
|
while(flip) {
|
|
|
|
m->AddTriangle(&(flip->tri));
|
|
|
|
flip = flip->more;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(n.z < 0) {
|
2016-03-25 22:16:58 +08:00
|
|
|
if(neg) neg->GenerateInPaintOrder(m);
|
2009-03-18 00:33:46 +08:00
|
|
|
} else {
|
2016-03-25 22:16:58 +08:00
|
|
|
if(pos) pos->GenerateInPaintOrder(m);
|
2009-03-18 00:33:46 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-21 13:18:00 +08:00
|
|
|
void SBsp3::DebugDraw() const {
|
2008-06-23 16:37:12 +08:00
|
|
|
|
2016-03-25 22:16:58 +08:00
|
|
|
if(pos) pos->DebugDraw();
|
2008-06-23 16:37:12 +08:00
|
|
|
Vector norm = tri.Normal();
|
|
|
|
glNormal3d(norm.x, norm.y, norm.z);
|
|
|
|
|
|
|
|
glEnable(GL_DEPTH_TEST);
|
|
|
|
glEnable(GL_LIGHTING);
|
|
|
|
glBegin(GL_TRIANGLES);
|
2013-10-22 12:45:06 +08:00
|
|
|
ssglVertex3v(tri.a);
|
|
|
|
ssglVertex3v(tri.b);
|
|
|
|
ssglVertex3v(tri.c);
|
2008-06-23 16:37:12 +08:00
|
|
|
glEnd();
|
|
|
|
|
|
|
|
glDisable(GL_LIGHTING);
|
|
|
|
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
2013-10-22 12:45:06 +08:00
|
|
|
ssglDepthRangeOffset(2);
|
2008-06-23 16:37:12 +08:00
|
|
|
glBegin(GL_TRIANGLES);
|
2013-10-22 12:45:06 +08:00
|
|
|
ssglVertex3v(tri.a);
|
|
|
|
ssglVertex3v(tri.b);
|
|
|
|
ssglVertex3v(tri.c);
|
2008-06-23 16:37:12 +08:00
|
|
|
glEnd();
|
|
|
|
|
|
|
|
glDisable(GL_LIGHTING);
|
|
|
|
glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
|
|
|
|
glPointSize(10);
|
2013-10-22 12:45:06 +08:00
|
|
|
ssglDepthRangeOffset(2);
|
2008-06-23 16:37:12 +08:00
|
|
|
glBegin(GL_TRIANGLES);
|
2013-10-22 12:45:06 +08:00
|
|
|
ssglVertex3v(tri.a);
|
|
|
|
ssglVertex3v(tri.b);
|
|
|
|
ssglVertex3v(tri.c);
|
2015-03-29 08:30:52 +08:00
|
|
|
glEnd();
|
2008-06-23 16:37:12 +08:00
|
|
|
|
2013-10-22 12:45:06 +08:00
|
|
|
ssglDepthRangeOffset(0);
|
2008-06-23 16:37:12 +08:00
|
|
|
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
|
|
|
|
2016-03-25 22:16:58 +08:00
|
|
|
if(more) more->DebugDraw();
|
|
|
|
if(neg) neg->DebugDraw();
|
2008-06-23 16:37:12 +08:00
|
|
|
|
2016-03-25 22:16:58 +08:00
|
|
|
if(edges) edges->DebugDraw(n, d);
|
2008-06-23 16:37:12 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////
|
|
|
|
|
2016-05-21 13:18:00 +08:00
|
|
|
Vector SBsp2::IntersectionWith(Vector a, Vector b) const {
|
2008-06-23 16:37:12 +08:00
|
|
|
double da = a.Dot(no) - d;
|
|
|
|
double db = b.Dot(no) - d;
|
2016-05-19 06:51:36 +08:00
|
|
|
ssassert(da*db < 0, "Expected segment to intersect BSP node");
|
2008-06-23 16:37:12 +08:00
|
|
|
|
|
|
|
double dab = (db - da);
|
|
|
|
return (a.ScaledBy(db/dab)).Plus(b.ScaledBy(-da/dab));
|
|
|
|
}
|
|
|
|
|
2016-03-25 22:16:58 +08:00
|
|
|
SBsp2 *SBsp2::InsertOrCreateEdge(SBsp2 *where, SEdge *nedge, Vector nnp, Vector out) {
|
|
|
|
if(where == NULL) {
|
2008-06-23 16:37:12 +08:00
|
|
|
// Brand new node; so allocate for it, and fill us in.
|
|
|
|
SBsp2 *r = Alloc();
|
|
|
|
r->np = nnp;
|
|
|
|
r->no = ((r->np).Cross((nedge->b).Minus(nedge->a))).WithMagnitude(1);
|
|
|
|
if(out.Dot(r->no) < 0) {
|
|
|
|
r->no = (r->no).ScaledBy(-1);
|
|
|
|
}
|
|
|
|
r->d = (nedge->a).Dot(r->no);
|
|
|
|
r->edge = *nedge;
|
|
|
|
return r;
|
|
|
|
}
|
2016-03-25 22:16:58 +08:00
|
|
|
where->InsertEdge(nedge, nnp, out);
|
|
|
|
return where;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SBsp2::InsertEdge(SEdge *nedge, Vector nnp, Vector out) {
|
2008-06-23 16:37:12 +08:00
|
|
|
|
|
|
|
double dt[2] = { (nedge->a).Dot(no), (nedge->b).Dot(no) };
|
|
|
|
|
2015-03-27 23:31:23 +08:00
|
|
|
bool isPos[2] = {}, isNeg[2] = {}, isOn[2] = {};
|
2008-06-23 16:37:12 +08:00
|
|
|
for(int i = 0; i < 2; i++) {
|
|
|
|
if(fabs(dt[i] - d) < LENGTH_EPS) {
|
|
|
|
isOn[i] = true;
|
|
|
|
} else if(dt[i] > d) {
|
|
|
|
isPos[i] = true;
|
|
|
|
} else {
|
|
|
|
isNeg[i] = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if((isPos[0] && isPos[1])||(isPos[0] && isOn[1])||(isOn[0] && isPos[1])) {
|
2016-03-25 22:16:58 +08:00
|
|
|
pos = InsertOrCreateEdge(pos, nedge, nnp, out);
|
|
|
|
return;
|
2008-06-23 16:37:12 +08:00
|
|
|
}
|
|
|
|
if((isNeg[0] && isNeg[1])||(isNeg[0] && isOn[1])||(isOn[0] && isNeg[1])) {
|
2016-03-25 22:16:58 +08:00
|
|
|
neg = InsertOrCreateEdge(neg, nedge, nnp, out);
|
|
|
|
return;
|
2008-06-23 16:37:12 +08:00
|
|
|
}
|
|
|
|
if(isOn[0] && isOn[1]) {
|
|
|
|
SBsp2 *m = Alloc();
|
|
|
|
|
|
|
|
m->np = nnp;
|
|
|
|
m->no = ((m->np).Cross((nedge->b).Minus(nedge->a))).WithMagnitude(1);
|
|
|
|
if(out.Dot(m->no) < 0) {
|
|
|
|
m->no = (m->no).ScaledBy(-1);
|
|
|
|
}
|
|
|
|
m->d = (nedge->a).Dot(m->no);
|
|
|
|
m->edge = *nedge;
|
|
|
|
|
|
|
|
m->more = more;
|
|
|
|
more = m;
|
2016-03-25 22:16:58 +08:00
|
|
|
return;
|
2008-06-23 16:37:12 +08:00
|
|
|
}
|
|
|
|
if((isPos[0] && isNeg[1]) || (isNeg[0] && isPos[1])) {
|
|
|
|
Vector aPb = IntersectionWith(nedge->a, nedge->b);
|
|
|
|
|
|
|
|
SEdge ea = SEdge::From(nedge->a, aPb);
|
|
|
|
SEdge eb = SEdge::From(aPb, nedge->b);
|
|
|
|
|
|
|
|
if(isPos[0]) {
|
2016-03-25 22:16:58 +08:00
|
|
|
pos = InsertOrCreateEdge(pos, &ea, nnp, out);
|
|
|
|
neg = InsertOrCreateEdge(neg, &eb, nnp, out);
|
2008-06-23 16:37:12 +08:00
|
|
|
} else {
|
2016-03-25 22:16:58 +08:00
|
|
|
neg = InsertOrCreateEdge(neg, &ea, nnp, out);
|
|
|
|
pos = InsertOrCreateEdge(pos, &eb, nnp, out);
|
2008-06-23 16:37:12 +08:00
|
|
|
}
|
2016-03-25 22:16:58 +08:00
|
|
|
return;
|
2008-06-23 16:37:12 +08:00
|
|
|
}
|
2016-05-19 06:51:36 +08:00
|
|
|
ssassert(false, "Impossible");
|
2008-06-23 16:37:12 +08:00
|
|
|
}
|
|
|
|
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 16:31:20 +08:00
|
|
|
void SBsp2::InsertTriangleHow(BspClass how, STriangle *tr, SMesh *m, SBsp3 *bsp3) {
|
2008-06-23 16:37:12 +08:00
|
|
|
switch(how) {
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 16:31:20 +08:00
|
|
|
case BspClass::POS:
|
2008-06-23 16:37:12 +08:00
|
|
|
if(pos) {
|
|
|
|
pos->InsertTriangle(tr, m, bsp3);
|
|
|
|
} else {
|
|
|
|
bsp3->InsertInPlane(true, tr, m);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 16:31:20 +08:00
|
|
|
case BspClass::NEG:
|
2008-06-23 16:37:12 +08:00
|
|
|
if(neg) {
|
|
|
|
neg->InsertTriangle(tr, m, bsp3);
|
|
|
|
} else {
|
|
|
|
bsp3->InsertInPlane(false, tr, m);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2016-05-19 06:51:36 +08:00
|
|
|
default: ssassert(false, "Unexpected BSP insert type");
|
2008-06-23 16:37:12 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void SBsp2::InsertTriangle(STriangle *tr, SMesh *m, SBsp3 *bsp3) {
|
|
|
|
double dt[3] = { (tr->a).Dot(no), (tr->b).Dot(no), (tr->c).Dot(no) };
|
|
|
|
|
2015-03-27 23:31:23 +08:00
|
|
|
bool isPos[3] = {}, isNeg[3] = {}, isOn[3] = {};
|
2008-06-23 16:37:12 +08:00
|
|
|
int inc = 0, posc = 0, negc = 0;
|
|
|
|
for(int i = 0; i < 3; i++) {
|
|
|
|
if(fabs(dt[i] - d) < LENGTH_EPS) {
|
|
|
|
isOn[i] = true;
|
|
|
|
inc++;
|
|
|
|
} else if(dt[i] > d) {
|
|
|
|
isPos[i] = true;
|
|
|
|
posc++;
|
|
|
|
} else {
|
|
|
|
isNeg[i] = true;
|
|
|
|
negc++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(inc == 3) {
|
|
|
|
// All vertices on-line; so it's a degenerate triangle, to ignore.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// No split required
|
|
|
|
if(posc == 0 || negc == 0) {
|
|
|
|
if(posc > 0) {
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 16:31:20 +08:00
|
|
|
InsertTriangleHow(BspClass::POS, tr, m, bsp3);
|
2008-06-23 16:37:12 +08:00
|
|
|
} else {
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 16:31:20 +08:00
|
|
|
InsertTriangleHow(BspClass::NEG, tr, m, bsp3);
|
2008-06-23 16:37:12 +08:00
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// The polygon must be split into two pieces, one above, one below.
|
|
|
|
Vector a, b, c;
|
|
|
|
|
|
|
|
if(posc == 1 && negc == 1 && inc == 1) {
|
|
|
|
bool bpos;
|
|
|
|
// Standardize so that a is on the plane
|
|
|
|
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];
|
2016-05-19 06:51:36 +08:00
|
|
|
} else ssassert(false, "Impossible");
|
2008-06-23 16:37:12 +08:00
|
|
|
|
|
|
|
Vector bPc = IntersectionWith(b, c);
|
|
|
|
STriangle btri = STriangle::From(tr->meta, a, b, bPc);
|
|
|
|
STriangle ctri = STriangle::From(tr->meta, c, a, bPc);
|
|
|
|
|
|
|
|
if(bpos) {
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 16:31:20 +08:00
|
|
|
InsertTriangleHow(BspClass::POS, &btri, m, bsp3);
|
|
|
|
InsertTriangleHow(BspClass::NEG, &ctri, m, bsp3);
|
2008-06-23 16:37:12 +08:00
|
|
|
} else {
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 16:31:20 +08:00
|
|
|
InsertTriangleHow(BspClass::POS, &ctri, m, bsp3);
|
|
|
|
InsertTriangleHow(BspClass::NEG, &btri, m, bsp3);
|
2008-06-23 16:37:12 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(posc == 2 && negc == 1) {
|
|
|
|
// Standardize so that a is on one side, and b and c are on the other.
|
|
|
|
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;
|
2016-05-19 06:51:36 +08:00
|
|
|
} else ssassert(false, "Impossible");
|
2008-06-23 16:37:12 +08:00
|
|
|
|
|
|
|
} 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;
|
2016-05-19 06:51:36 +08:00
|
|
|
} else ssassert(false, "Impossible");
|
|
|
|
} else ssassert(false, "Impossible");
|
2008-06-23 16:37:12 +08:00
|
|
|
|
|
|
|
Vector aPb = IntersectionWith(a, b);
|
|
|
|
Vector cPa = IntersectionWith(c, a);
|
|
|
|
|
|
|
|
STriangle alone = STriangle::From(tr->meta, a, aPb, cPa);
|
|
|
|
STriangle quad1 = STriangle::From(tr->meta, aPb, b, c );
|
|
|
|
STriangle quad2 = STriangle::From(tr->meta, aPb, c, cPa);
|
|
|
|
|
|
|
|
if(posc == 2 && negc == 1) {
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 16:31:20 +08:00
|
|
|
InsertTriangleHow(BspClass::POS, &quad1, m, bsp3);
|
|
|
|
InsertTriangleHow(BspClass::POS, &quad2, m, bsp3);
|
|
|
|
InsertTriangleHow(BspClass::NEG, &alone, m, bsp3);
|
2008-06-23 16:37:12 +08:00
|
|
|
} else {
|
Convert all enumerations to use `enum class`.
Specifically, take the old code that looks like this:
class Foo {
enum { X = 1, Y = 2 };
int kind;
}
... foo.kind = Foo::X; ...
and convert it to this:
class Foo {
enum class Kind : uint32_t { X = 1, Y = 2 };
Kind kind;
}
... foo.kind = Foo::Kind::X;
(In some cases the enumeration would not be in the class namespace,
such as when it is generally useful.)
The benefits are as follows:
* The type of the field gives a clear indication of intent, both
to humans and tools (such as binding generators).
* The compiler is able to automatically warn when a switch is not
exhaustive; but this is currently suppressed by the
default: ssassert(false, ...)
idiom.
* Integers and plain enums are weakly type checked: they implicitly
convert into each other. This can hide bugs where type conversion
is performed but not intended. Enum classes are strongly type
checked.
* Plain enums pollute parent namespaces; enum classes do not.
Almost every defined enum we have already has a kind of ad-hoc
namespacing via `NAMESPACE_`, which is now explicit.
* Plain enums do not have a well-defined ABI size, which is
important for bindings. Enum classes can have it, if specified.
We specify the base type for all enums as uint32_t, which is
a safe choice and allows us to not change the numeric values
of any variants.
This commit introduces absolutely no functional change to the code,
just renaming and change of types. It handles almost all cases,
except GraphicsWindow::pending.operation, which needs minor
functional change.
2016-05-20 16:31:20 +08:00
|
|
|
InsertTriangleHow(BspClass::NEG, &quad1, m, bsp3);
|
|
|
|
InsertTriangleHow(BspClass::NEG, &quad2, m, bsp3);
|
|
|
|
InsertTriangleHow(BspClass::POS, &alone, m, bsp3);
|
2008-06-23 16:37:12 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-05-21 13:18:00 +08:00
|
|
|
void SBsp2::DebugDraw(Vector n, double d) const {
|
2016-05-19 06:51:36 +08:00
|
|
|
ssassert(fabs((edge.a).Dot(n) - d) < LENGTH_EPS, "Endpoint too close to BSP node plane");
|
|
|
|
ssassert(fabs((edge.b).Dot(n) - d) < LENGTH_EPS, "Endpoint too close to BSP node plane");
|
2008-06-23 16:37:12 +08:00
|
|
|
|
2015-03-22 21:39:12 +08:00
|
|
|
ssglLineWidth(10);
|
2008-06-23 16:37:12 +08:00
|
|
|
glBegin(GL_LINES);
|
2013-10-22 12:45:06 +08:00
|
|
|
ssglVertex3v(edge.a);
|
|
|
|
ssglVertex3v(edge.b);
|
2008-06-23 16:37:12 +08:00
|
|
|
glEnd();
|
2016-03-25 22:16:58 +08:00
|
|
|
if(pos) pos->DebugDraw(n, d);
|
|
|
|
if(neg) neg->DebugDraw(n, d);
|
|
|
|
if(more) more->DebugDraw(n, d);
|
2015-03-22 21:39:12 +08:00
|
|
|
ssglLineWidth(1);
|
2008-06-23 16:37:12 +08:00
|
|
|
}
|
|
|
|
|