aboutsummaryrefslogtreecommitdiff
path: root/dep/src/g3dlite/Box.cpp
diff options
context:
space:
mode:
authorclick <none@none>2010-06-05 00:59:25 +0200
committerclick <none@none>2010-06-05 00:59:25 +0200
commite77716188861d4aa83b227a90e04a66b63baeb1f (patch)
treece72764181a760314ec851f7535052dcf75649db /dep/src/g3dlite/Box.cpp
parent1426c2970f42a2d065198806f750bf5dd28d580b (diff)
HIGHLY EXPERIMENTAL - USE AT YOUR OWN RISK
Implement the use of the new vmap3-format by Lynx3d (mad props to you for this, and thanks for the talks earlier) + reduced Vmap size to less than one third, and improve precision + indoor/outdoor check which allows automatic unmounting of players + additional area information from WMOAreaTable.dbc, removed existing "hacks" + WMO liquid information for swimming and fishing correctly in buildings/cities/caves/instances (lava and slime WILL hurt from now on!) - buildfiles for windows are not properly done, and will need to be sorted out NOTE: Do NOT annoy Lynx3d about this, any issues with this "port" is entirely our fault ! THIS REVISION IS CONSIDERED UNSTABLE AND CONTAINS WORK IN PROGRESS - USE AT YOUR OWN RISK! --HG-- branch : trunk
Diffstat (limited to 'dep/src/g3dlite/Box.cpp')
-rw-r--r--dep/src/g3dlite/Box.cpp213
1 files changed, 136 insertions, 77 deletions
diff --git a/dep/src/g3dlite/Box.cpp b/dep/src/g3dlite/Box.cpp
index 725a7e95c3a..f7c112ae3a5 100644
--- a/dep/src/g3dlite/Box.cpp
+++ b/dep/src/g3dlite/Box.cpp
@@ -2,7 +2,7 @@
@file Box.cpp
Box class
- @maintainer Morgan McGuire, matrix@graphics3d.com
+ @maintainer Morgan McGuire, http://graphics.cs.williams.edu
@created 2001-06-02
@edited 2006-02-05
@@ -27,10 +27,56 @@ namespace G3D {
Box::Box() {
}
+
Box::Box(const AABox& b) {
init(b.low(), b.high());
}
+Box::Box(class BinaryInput& b) {
+ deserialize(b);
+}
+
+
+void Box::serialize(class BinaryOutput& b) const {
+ int i;
+ for (i = 0; i < 8; ++i) {
+ _corner[i].serialize(b);
+ }
+
+ // Other state can be reconstructed
+}
+
+
+void Box::deserialize(class BinaryInput& b) {
+ int i;
+
+ _center = Vector3::zero();
+ for (i = 0; i < 8; ++i) {
+ _corner[i].deserialize(b);
+ _center += _corner[i];
+ }
+
+ _center = _center / 8;
+
+ // Reconstruct other state from the corners
+ _axis[0] = _corner[5] - _corner[4];
+ _axis[1] = _corner[7] - _corner[4];
+ _axis[2] = _corner[0] - _corner[4];
+
+ for (i = 0; i < 3; ++i) {
+ _extent[i] = _axis[i].magnitude();
+ _axis[i] /= _extent[i];
+ }
+
+ _volume = _extent.x * _extent.y * _extent.z;
+
+ _area = 2 *
+ (_extent.x * _extent.y +
+ _extent.y * _extent.z +
+ _extent.z * _extent.x);
+}
+
+
Box::Box(
const Vector3& min,
const Vector3& max) {
@@ -43,6 +89,11 @@ void Box::init(
const Vector3& min,
const Vector3& max) {
+ debugAssert(
+ (min.x <= max.x) &&
+ (min.y <= max.y) &&
+ (min.z <= max.z));
+
setMany(0, 1, 2, 3, z, max);
setMany(4, 5, 6, 7, z, min);
@@ -58,23 +109,40 @@ void Box::init(
_axis[1] = Vector3::unitY();
_axis[2] = Vector3::unitZ();
- _volume = _extent.x * _extent.y * _extent.z;
- _area = 2 *
+ if (_extent.isFinite()) {
+ _volume = _extent.x * _extent.y * _extent.z;
+ } else {
+ _volume = G3D::finf();
+ }
+
+ debugAssert(! isNaN(_extent.x));
+
+ _area = 2 *
(_extent.x * _extent.y +
_extent.y * _extent.z +
_extent.z * _extent.x);
- _center = (max + min) / 2;
+ _center = (max + min) * 0.5f;
+
+ // If the extent is infinite along an axis, make the center zero to avoid NaNs
+ for (int i = 0; i < 3; ++i) {
+ if (! G3D::isFinite(_extent[i])) {
+ _center[i] = 0.0f;
+ }
+ }
}
+
float Box::volume() const {
return _volume;
}
-float Box::surfaceArea() const {
+
+float Box::area() const {
return _area;
}
+
void Box::getLocalFrame(CoordinateFrame& frame) const {
frame.rotation = Matrix3(
@@ -85,12 +153,14 @@ void Box::getLocalFrame(CoordinateFrame& frame) const {
frame.translation = _center;
}
+
CoordinateFrame Box::localFrame() const {
CoordinateFrame out;
getLocalFrame(out);
return out;
}
+
void Box::getFaceCorners(int f, Vector3& v0, Vector3& v1, Vector3& v2, Vector3& v3) const {
switch (f) {
case 0:
@@ -122,45 +192,29 @@ void Box::getFaceCorners(int f, Vector3& v0, Vector3& v1, Vector3& v2, Vector3&
}
}
-bool Box::culledBy(
- const Array<Plane>& plane,
- int& cullingPlaneIndex,
- const uint32 inMask,
- uint32& outMask) const {
-
- return culledBy(plane.getCArray(), plane.size(), cullingPlaneIndex, inMask, outMask);
-}
-
-bool Box::culledBy(
- const Array<Plane>& plane,
- int& cullingPlaneIndex,
- const uint32 inMask) const {
- return culledBy(plane.getCArray(), plane.size(), cullingPlaneIndex, inMask);
-}
-int32 Box::dummy = 0;
+int Box::dummy = 0;
bool Box::culledBy(
- const class Plane* plane,
- int numPlanes,
+ const Array<Plane>& plane,
int& cullingPlane,
const uint32 _inMask,
uint32& childMask) const {
uint32 inMask = _inMask;
- assert(numPlanes < 31);
+ assert(plane.size() < 31);
childMask = 0;
// See if there is one plane for which all of the
- // vertices are in the negative half space.
- for (int p = 0; p < numPlanes; p++) {
-
- // Only test planes that are not masked
- if ((inMask & 1) != 0) {
+ // vertices are in the negative half space.
+ for (int p = 0; p < plane.size(); ++p) {
- Vector3 corner;
+ // Only test planes that are not masked
+ if ((inMask & 1) != 0) {
+
+ Vector3 corner;
int numContained = 0;
int v = 0;
@@ -168,83 +222,84 @@ bool Box::culledBy(
// We can early-out only if we have found one point on each
// side of the plane (i.e. if we are straddling). That
// occurs when (numContained < v) && (numContained > 0)
- for (v = 0; (v < 8) && ((numContained == v) || (numContained == 0)); ++v) {
- if (plane[p].halfSpaceContains(getCorner(v))) {
+ for (v = 0; (v < 8) && ((numContained == v) || (numContained == 0)); ++v) {
+ if (plane[p].halfSpaceContains(_corner[v])) {
++numContained;
}
- }
+ }
- if (numContained == 0) {
- // Plane p culled the box
- cullingPlane = p;
+ if (numContained == 0) {
+ // Plane p culled the box
+ cullingPlane = p;
// The caller should not recurse into the children,
// since the parent is culled. If they do recurse,
// make them only test against this one plane, which
// will immediately cull the volume.
childMask = 1 << p;
- return true;
+ return true;
} else if (numContained < v) {
// The bounding volume straddled the plane; we have
// to keep testing against this plane
childMask |= (1 << p);
}
- }
+ }
// Move on to the next bit.
- inMask = inMask >> 1;
+ inMask = inMask >> 1;
}
// None of the planes could cull this box
- cullingPlane = -1;
+ cullingPlane = -1;
return false;
}
+
bool Box::culledBy(
- const class Plane* plane,
- int numPlanes,
- int& cullingPlane,
- const uint32 _inMask) const {
+ const Array<Plane>& plane,
+ int& cullingPlane,
+ const uint32 _inMask) const {
- uint32 inMask = _inMask;
- assert(numPlanes < 31);
+ uint32 inMask = _inMask;
+ assert(plane.size() < 31);
// See if there is one plane for which all of the
- // vertices are in the negative half space.
- for (int p = 0; p < numPlanes; p++) {
+ // vertices are in the negative half space.
+ for (int p = 0; p < plane.size(); ++p) {
- // Only test planes that are not masked
- if ((inMask & 1) != 0) {
-
- bool culled = true;
+ // Only test planes that are not masked
+ if ((inMask & 1) != 0) {
+
+ bool culled = true;
int v;
- // Assume this plane culls all points. See if there is a point
- // not culled by the plane... early out when at least one point
+ // Assume this plane culls all points. See if there is a point
+ // not culled by the plane... early out when at least one point
// is in the positive half space.
- for (v = 0; (v < 8) && culled; ++v) {
- culled = ! plane[p].halfSpaceContains(getCorner(v));
- }
+ for (v = 0; (v < 8) && culled; ++v) {
+ culled = ! plane[p].halfSpaceContains(corner(v));
+ }
- if (culled) {
- // Plane p culled the box
- cullingPlane = p;
+ if (culled) {
+ // Plane p culled the box
+ cullingPlane = p;
- return true;
+ return true;
}
- }
+ }
// Move on to the next bit.
- inMask = inMask >> 1;
+ inMask = inMask >> 1;
}
// None of the planes could cull this box
- cullingPlane = -1;
+ cullingPlane = -1;
return false;
}
+
bool Box::contains(
const Vector3& point) const {
@@ -264,7 +319,7 @@ bool Box::contains(
Vector3 osPoint = M.inverse() * (point - _corner[0]);
return
- (osPoint.x >= 0) &&
+ (osPoint.x >= 0) &&
(osPoint.y >= 0) &&
(osPoint.z >= 0) &&
(osPoint.x <= 1) &&
@@ -274,47 +329,51 @@ bool Box::contains(
#undef setMany
-#if 0
+
void Box::getRandomSurfacePoint(Vector3& P, Vector3& N) const {
float aXY = _extent.x * _extent.y;
float aYZ = _extent.y * _extent.z;
float aZX = _extent.z * _extent.x;
- float r = (float)random(0, aXY + aYZ + aZX);
+ float r = (float)uniformRandom(0, aXY + aYZ + aZX);
// Choose evenly between positive and negative face planes
- float d = (random(0, 1) < 0.5f) ? -1.0f : 1.0f;
+ float d = (uniformRandom(0, 1) < 0.5f) ? -1.0f : 1.0f;
// The probability of choosing a given face is proportional to
// its area.
if (r < aXY) {
- P = _axis[0] * (float)random(-0.5, 0.5) * _extent.x +
- _axis[1] * (float)random(-0.5, 0.5) * _extent.y +
+ P = _axis[0] * (float)uniformRandom(-0.5, 0.5) * _extent.x +
+ _axis[1] * (float)uniformRandom(-0.5, 0.5) * _extent.y +
_center + _axis[2] * d * _extent.z * 0.5f;
N = _axis[2] * d;
} else if (r < aYZ) {
- P = _axis[1] * (float)random(-0.5, 0.5) * _extent.y +
- _axis[2] * (float)random(-0.5, 0.5) * _extent.z +
+ P = _axis[1] * (float)uniformRandom(-0.5, 0.5) * _extent.y +
+ _axis[2] * (float)uniformRandom(-0.5, 0.5) * _extent.z +
_center + _axis[0] * d * _extent.x * 0.5f;
N = _axis[0] * d;
} else {
- P = _axis[2] * (float)random(-0.5, 0.5) * _extent.z +
- _axis[0] *(float) random(-0.5, 0.5) * _extent.x +
+ P = _axis[2] * (float)uniformRandom(-0.5, 0.5) * _extent.z +
+ _axis[0] *(float) uniformRandom(-0.5, 0.5) * _extent.x +
_center + _axis[1] * d * _extent.y * 0.5f;
N = _axis[1] * d;
}
}
+
Vector3 Box::randomInteriorPoint() const {
Vector3 sum = _center;
for (int a = 0; a < 3; ++a) {
- sum += _axis[a] * (float)random(-0.5, 0.5) * _extent[a];
+ sum += _axis[a] * (float)uniformRandom(-0.5, 0.5) * _extent[a];
}
return sum;
}
-#endif
+
+Box Box::inf() {
+ return Box(-Vector3::inf(), Vector3::inf());
+}
void Box::getBounds(class AABox& aabb) const {
@@ -330,5 +389,5 @@ void Box::getBounds(class AABox& aabb) const {
aabb = AABox(lo, hi);
}
-} // namespace
+} // namespace