aboutsummaryrefslogtreecommitdiff
path: root/externals/g3dlite
diff options
context:
space:
mode:
Diffstat (limited to 'externals/g3dlite')
-rw-r--r--externals/g3dlite/AABox.cpp366
-rw-r--r--externals/g3dlite/Any.cpp1237
-rw-r--r--externals/g3dlite/BinaryFormat.cpp81
-rw-r--r--externals/g3dlite/BinaryInput.cpp568
-rw-r--r--externals/g3dlite/BinaryOutput.cpp522
-rw-r--r--externals/g3dlite/Box.cpp393
-rw-r--r--externals/g3dlite/CMakeLists.txt37
-rw-r--r--externals/g3dlite/Capsule.cpp179
-rw-r--r--externals/g3dlite/CollisionDetection.cpp2455
-rw-r--r--externals/g3dlite/CoordinateFrame.cpp436
-rw-r--r--externals/g3dlite/Crypto.cpp70
-rw-r--r--externals/g3dlite/Cylinder.cpp176
-rw-r--r--externals/g3dlite/G3D/AABox.h272
-rw-r--r--externals/g3dlite/G3D/Any.h570
-rw-r--r--externals/g3dlite/G3D/AnyVal.h512
-rw-r--r--externals/g3dlite/G3D/AreaMemoryManager.h93
-rw-r--r--externals/g3dlite/G3D/Array.h1274
-rw-r--r--externals/g3dlite/G3D/AtomicInt32.h164
-rw-r--r--externals/g3dlite/G3D/BinaryFormat.h140
-rw-r--r--externals/g3dlite/G3D/BinaryInput.h441
-rw-r--r--externals/g3dlite/G3D/BinaryOutput.h421
-rw-r--r--externals/g3dlite/G3D/BoundsTrait.h20
-rw-r--r--externals/g3dlite/G3D/Box.h195
-rw-r--r--externals/g3dlite/G3D/Box2D.h121
-rw-r--r--externals/g3dlite/G3D/BumpMapPreprocess.h61
-rw-r--r--externals/g3dlite/G3D/Capsule.h90
-rw-r--r--externals/g3dlite/G3D/CollisionDetection.h1205
-rw-r--r--externals/g3dlite/G3D/Color1.h144
-rw-r--r--externals/g3dlite/G3D/Color1uint8.h91
-rw-r--r--externals/g3dlite/G3D/Color3.h432
-rw-r--r--externals/g3dlite/G3D/Color3uint8.h110
-rw-r--r--externals/g3dlite/G3D/Color4.h338
-rw-r--r--externals/g3dlite/G3D/Color4uint8.h115
-rw-r--r--externals/g3dlite/G3D/Cone.h68
-rw-r--r--externals/g3dlite/G3D/ConvexPolyhedron.h180
-rw-r--r--externals/g3dlite/G3D/CoordinateFrame.h331
-rw-r--r--externals/g3dlite/G3D/Crypto.h96
-rw-r--r--externals/g3dlite/G3D/Cylinder.h92
-rw-r--r--externals/g3dlite/G3D/EqualsTrait.h26
-rw-r--r--externals/g3dlite/G3D/G3D.h162
-rw-r--r--externals/g3dlite/G3D/G3DAll.h26
-rw-r--r--externals/g3dlite/G3D/G3DGameUnits.h42
-rw-r--r--externals/g3dlite/G3D/GCamera.h337
-rw-r--r--externals/g3dlite/G3D/GImage.h607
-rw-r--r--externals/g3dlite/G3D/GLight.h106
-rw-r--r--externals/g3dlite/G3D/GMutex.h123
-rw-r--r--externals/g3dlite/G3D/GThread.h121
-rw-r--r--externals/g3dlite/G3D/GUniqueID.h69
-rw-r--r--externals/g3dlite/G3D/HashTrait.h92
-rw-r--r--externals/g3dlite/G3D/Image1.h81
-rw-r--r--externals/g3dlite/G3D/Image1uint8.h80
-rw-r--r--externals/g3dlite/G3D/Image3.h81
-rw-r--r--externals/g3dlite/G3D/Image3uint8.h85
-rw-r--r--externals/g3dlite/G3D/Image4.h86
-rw-r--r--externals/g3dlite/G3D/Image4uint8.h85
-rw-r--r--externals/g3dlite/G3D/ImageFormat.h419
-rw-r--r--externals/g3dlite/G3D/Intersect.h55
-rw-r--r--externals/g3dlite/G3D/KDTree.h1667
-rw-r--r--externals/g3dlite/G3D/Line.h105
-rw-r--r--externals/g3dlite/G3D/LineSegment.h115
-rw-r--r--externals/g3dlite/G3D/Log.h109
-rw-r--r--externals/g3dlite/G3D/Map2D.h667
-rw-r--r--externals/g3dlite/G3D/Matrix.h634
-rw-r--r--externals/g3dlite/G3D/Matrix2.h69
-rw-r--r--externals/g3dlite/G3D/Matrix3.h366
-rw-r--r--externals/g3dlite/G3D/Matrix4.h249
-rw-r--r--externals/g3dlite/G3D/MemoryManager.h93
-rw-r--r--externals/g3dlite/G3D/MeshAlg.h683
-rw-r--r--externals/g3dlite/G3D/MeshBuilder.h82
-rw-r--r--externals/g3dlite/G3D/NetAddress.h132
-rw-r--r--externals/g3dlite/G3D/NetworkDevice.h738
-rw-r--r--externals/g3dlite/G3D/ParseError.h59
-rw-r--r--externals/g3dlite/G3D/PhysicsFrame.h74
-rw-r--r--externals/g3dlite/G3D/Plane.h161
-rw-r--r--externals/g3dlite/G3D/PointHashGrid.h917
-rw-r--r--externals/g3dlite/G3D/PointKDTree.h1185
-rw-r--r--externals/g3dlite/G3D/Pointer.h292
-rw-r--r--externals/g3dlite/G3D/PositionTrait.h7
-rw-r--r--externals/g3dlite/G3D/PrecomputedRandom.h110
-rw-r--r--externals/g3dlite/G3D/Quat.h725
-rw-r--r--externals/g3dlite/G3D/Quat.inl36
-rw-r--r--externals/g3dlite/G3D/Queue.h364
-rw-r--r--externals/g3dlite/G3D/Random.h139
-rw-r--r--externals/g3dlite/G3D/Ray.h371
-rw-r--r--externals/g3dlite/G3D/Rect2D.h417
-rw-r--r--externals/g3dlite/G3D/ReferenceCount.h570
-rw-r--r--externals/g3dlite/G3D/RegistryUtil.h97
-rw-r--r--externals/g3dlite/G3D/Set.h186
-rw-r--r--externals/g3dlite/G3D/SmallArray.h155
-rw-r--r--externals/g3dlite/G3D/Sphere.h148
-rw-r--r--externals/g3dlite/G3D/Spline.h367
-rw-r--r--externals/g3dlite/G3D/Stopwatch.h144
-rw-r--r--externals/g3dlite/G3D/System.h507
-rw-r--r--externals/g3dlite/G3D/Table.h924
-rw-r--r--externals/g3dlite/G3D/TextInput.h801
-rw-r--r--externals/g3dlite/G3D/TextOutput.h249
-rw-r--r--externals/g3dlite/G3D/ThreadSet.h87
-rw-r--r--externals/g3dlite/G3D/Triangle.h160
-rw-r--r--externals/g3dlite/G3D/UprightFrame.h83
-rw-r--r--externals/g3dlite/G3D/Vector2.h454
-rw-r--r--externals/g3dlite/G3D/Vector2.inl18
-rw-r--r--externals/g3dlite/G3D/Vector2int16.h127
-rw-r--r--externals/g3dlite/G3D/Vector3.h798
-rw-r--r--externals/g3dlite/G3D/Vector3.inl249
-rw-r--r--externals/g3dlite/G3D/Vector3int16.h127
-rw-r--r--externals/g3dlite/G3D/Vector3int32.h128
-rw-r--r--externals/g3dlite/G3D/Vector4.h716
-rw-r--r--externals/g3dlite/G3D/Vector4.inl191
-rw-r--r--externals/g3dlite/G3D/Vector4int8.h113
-rw-r--r--externals/g3dlite/G3D/WeakCache.h122
-rw-r--r--externals/g3dlite/G3D/Welder.h82
-rw-r--r--externals/g3dlite/G3D/WrapMode.h93
-rw-r--r--externals/g3dlite/G3D/constants.h129
-rw-r--r--externals/g3dlite/G3D/debug.h66
-rw-r--r--externals/g3dlite/G3D/debugAssert.h233
-rw-r--r--externals/g3dlite/G3D/debugPrintf.h62
-rw-r--r--externals/g3dlite/G3D/enumclass.h147
-rw-r--r--externals/g3dlite/G3D/fileutils.h254
-rw-r--r--externals/g3dlite/G3D/filter.h29
-rw-r--r--externals/g3dlite/G3D/format.h44
-rw-r--r--externals/g3dlite/G3D/g3dfnmatch.h83
-rw-r--r--externals/g3dlite/G3D/g3dmath.h845
-rw-r--r--externals/g3dlite/G3D/g3dmath.inl288
-rw-r--r--externals/g3dlite/G3D/platform.h331
-rw-r--r--externals/g3dlite/G3D/prompt.h67
-rw-r--r--externals/g3dlite/G3D/serialize.h30
-rw-r--r--externals/g3dlite/G3D/splinefunc.h118
-rw-r--r--externals/g3dlite/G3D/stringutils.h140
-rw-r--r--externals/g3dlite/G3D/uint128.h51
-rw-r--r--externals/g3dlite/G3D/units.h126
-rw-r--r--externals/g3dlite/G3D/vectorMath.h235
-rw-r--r--externals/g3dlite/Line.cpp89
-rw-r--r--externals/g3dlite/LineSegment.cpp236
-rw-r--r--externals/g3dlite/Log.cpp146
-rw-r--r--externals/g3dlite/Matrix3.cpp1927
-rw-r--r--externals/g3dlite/Matrix4.cpp523
-rw-r--r--externals/g3dlite/MemoryManager.cpp91
-rw-r--r--externals/g3dlite/Plane.cpp149
-rw-r--r--externals/g3dlite/Quat.cpp583
-rw-r--r--externals/g3dlite/Random.cpp212
-rw-r--r--externals/g3dlite/Ray.cpp218
-rw-r--r--externals/g3dlite/ReferenceCount.cpp61
-rw-r--r--externals/g3dlite/RegistryUtil.cpp290
-rw-r--r--externals/g3dlite/Sphere.cpp223
-rw-r--r--externals/g3dlite/System.cpp1746
-rw-r--r--externals/g3dlite/TextInput.cpp1136
-rw-r--r--externals/g3dlite/TextOutput.cpp452
-rw-r--r--externals/g3dlite/Triangle.cpp186
-rw-r--r--externals/g3dlite/UprightFrame.cpp132
-rw-r--r--externals/g3dlite/Vector2.cpp224
-rw-r--r--externals/g3dlite/Vector3.cpp507
-rw-r--r--externals/g3dlite/Vector4.cpp520
-rw-r--r--externals/g3dlite/debugAssert.cpp389
-rw-r--r--externals/g3dlite/fileutils.cpp1165
-rw-r--r--externals/g3dlite/format.cpp164
-rw-r--r--externals/g3dlite/g3dfnmatch.cpp204
-rw-r--r--externals/g3dlite/g3dmath.cpp108
-rw-r--r--externals/g3dlite/prompt.cpp729
-rw-r--r--externals/g3dlite/stringutils.cpp275
159 files changed, 0 insertions, 51004 deletions
diff --git a/externals/g3dlite/AABox.cpp b/externals/g3dlite/AABox.cpp
deleted file mode 100644
index 035497aa3c4..00000000000
--- a/externals/g3dlite/AABox.cpp
+++ /dev/null
@@ -1,366 +0,0 @@
-/**
- @file AABox.cpp
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2004-01-10
- @edited 2006-01-11
-*/
-
-#include "G3D/platform.h"
-#include "G3D/AABox.h"
-#include "G3D/Box.h"
-#include "G3D/Plane.h"
-#include "G3D/Sphere.h"
-#include "G3D/BinaryInput.h"
-#include "G3D/BinaryOutput.h"
-
-
-namespace G3D {
-
-const AABox& AABox::maxFinite() {
- static const AABox b = AABox(Vector3::minFinite(),
- Vector3::maxFinite());
- return b;
-}
-
-
-const AABox& AABox::large() {
- static const AABox b = AABox(Vector3::minFinite() * 0.5f,
- Vector3::maxFinite() * 0.5f);
- return b;
-}
-
-
-const AABox& AABox::inf() {
- static const AABox b = AABox(-Vector3::inf(), Vector3::inf());
- return b;
-}
-
-
-const AABox& AABox::zero() {
- static const AABox b = AABox(Vector3::zero(), Vector3::zero());
- return b;
-}
-
-
-void AABox::serialize(class BinaryOutput& b) const {
- b.writeVector3(lo);
- b.writeVector3(hi);
-}
-
-
-void AABox::deserialize(class BinaryInput& b) {
- lo = b.readVector3();
- hi = b.readVector3();
-}
-
-
-void AABox::split(const Vector3::Axis& axis, float location, AABox& low, AABox& high) const {
- // Low, medium, and high along the chosen axis
- float L = G3D::min(location, lo[axis]);
- float M = G3D::min(G3D::max(location, lo[axis]), hi[axis]);
- float H = G3D::max(location, hi[axis]);
-
- // Copy over this box.
- high = low = *this;
-
- // Now move the split points along the special axis
- low.lo[axis] = L;
- low.hi[axis] = M;
- high.lo[axis] = M;
- high.hi[axis] = H;
-}
-
-
-Vector3 AABox::randomSurfacePoint() const {
- Vector3 extent = hi - lo;
- float aXY = extent.x * extent.y;
- float aYZ = extent.y * extent.z;
- float aZX = extent.z * extent.x;
-
- float r = (float)uniformRandom(0.0f, aXY + aYZ + aZX);
-
- // Choose evenly between positive and negative face planes
- float d = ((float)uniformRandom(0, 1) < 0.5f) ? 0.0f : 1.0f;
-
- // The probability of choosing a given face is proportional to
- // its area.
- if (r < aXY) {
- return
- lo +
- Vector3(
- (float)uniformRandom(0.0f, extent.x),
- (float)uniformRandom(0.0f, extent.y),
- d * extent.z);
- } else if (r < aYZ) {
- return
- lo +
- Vector3(
- d * extent.x,
- (float)uniformRandom(0, extent.y),
- (float)uniformRandom(0, extent.z));
- } else {
- return
- lo +
- Vector3(
- (float)uniformRandom(0, extent.x),
- d * extent.y,
- (float)uniformRandom(0, extent.z));
- }
-}
-
-
-Vector3 AABox::randomInteriorPoint() const {
- return Vector3(
- (float)uniformRandom(lo.x, hi.x),
- (float)uniformRandom(lo.y, hi.y),
- (float)uniformRandom(lo.z, hi.z));
-}
-
-
-bool AABox::intersects(const AABox& other) const {
- // Must be overlap along all three axes.
- // Try to find a separating axis.
-
- for (int a = 0; a < 3; ++a) {
-
- // |--------|
- // |------|
-
- if ((lo[a] > other.hi[a]) ||
- (hi[a] < other.lo[a])) {
- return false;
- }
- }
-
- return true;
-}
-
-int AABox::dummy = 0;
-
-bool AABox::culledBy(
- const Array<Plane>& plane,
- int& cullingPlane,
- const uint32 _inMask,
- uint32& childMask) const {
-
- uint32 inMask = _inMask;
- assert(plane.size() < 31);
-
- childMask = 0;
-
- const bool finite =
- (abs(lo.x) < G3D::finf()) &&
- (abs(hi.x) < G3D::finf()) &&
- (abs(lo.y) < G3D::finf()) &&
- (abs(hi.y) < G3D::finf()) &&
- (abs(lo.z) < G3D::finf()) &&
- (abs(hi.z) < G3D::finf());
-
- // See if there is one plane for which all of the
- // 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) {
-
- Vector3 corner;
-
- int numContained = 0;
- int v = 0;
-
- // 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) {
- // Unrolling these 3 if's into a switch decreases performance
- // by about 2x
- corner.x = (v & 1) ? hi.x : lo.x;
- corner.y = (v & 2) ? hi.y : lo.y;
- corner.z = (v & 4) ? hi.z : lo.z;
-
- if (finite) { // this branch is highly predictable
- if (plane[p].halfSpaceContainsFinite(corner)) {
- ++numContained;
- }
- } else {
- if (plane[p].halfSpaceContains(corner)) {
- ++numContained;
- }
- }
- }
-
- 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;
-
- } 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;
- }
-
- // None of the planes could cull this box
- cullingPlane = -1;
- return false;
-}
-
-
-bool AABox::culledBy(
- const Array<Plane>& plane,
- int& cullingPlane,
- const uint32 _inMask) const {
-
- uint32 inMask = _inMask;
- assert(plane.size() < 31);
-
- const bool finite =
- (abs(lo.x) < G3D::finf()) &&
- (abs(hi.x) < G3D::finf()) &&
- (abs(lo.y) < G3D::finf()) &&
- (abs(hi.y) < G3D::finf()) &&
- (abs(lo.z) < G3D::finf()) &&
- (abs(hi.z) < G3D::finf());
-
- // See if there is one plane for which all of the
- // 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;
- Vector3 corner;
-
- 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
- // is in the positive half space.
- for (v = 0; (v < 8) && culled; ++v) {
-
- // Unrolling these 3 if's into a switch decreases performance
- // by about 2x
- corner.x = (v & 1) ? hi.x : lo.x;
- corner.y = (v & 2) ? hi.y : lo.y;
- corner.z = (v & 4) ? hi.z : lo.z;
-
- if (finite) { // this branch is highly predictable
- culled = ! plane[p].halfSpaceContainsFinite(corner);
- } else {
- culled = ! plane[p].halfSpaceContains(corner);
- }
- }
-
- if (culled) {
- // Plane p culled the box
- cullingPlane = p;
-
- return true;
- }
- }
-
- // Move on to the next bit.
- inMask = inMask >> 1;
- }
-
- // None of the planes could cull this box
- cullingPlane = -1;
- return false;
-}
-
-
-bool AABox::intersects(const class Sphere& sphere) const {
- double d = 0;
-
- //find the square of the distance
- //from the sphere to the box
- for (int i = 0; i < 3; ++i) {
- if (sphere.center[i] < lo[i]) {
- d += square(sphere.center[i] - lo[i]);
- } else if (sphere.center[i] > hi[i]) {
- d += square(sphere.center[i] - hi[i]);
- }
- }
-
- return d <= square(sphere.radius);
-}
-
-Vector3 AABox::corner(int index) const {
-
- // default constructor inits all components to 0
- Vector3 v;
-
- switch (index)
- {
- case 0:
- v.x = lo.x;
- v.y = lo.y;
- v.z = hi.z;
- break;
-
- case 1:
- v.x = hi.x;
- v.y = lo.y;
- v.z = hi.z;
- break;
-
- case 2:
- v.x = hi.x;
- v.y = hi.y;
- v.z = hi.z;
- break;
-
- case 3:
- v.x = lo.x;
- v.y = hi.y;
- v.z = hi.z;
- break;
-
- case 4:
- v.x = lo.x;
- v.y = lo.y;
- v.z = lo.z;
- break;
-
- case 5:
- v.x = hi.x;
- v.y = lo.y;
- v.z = lo.z;
- break;
-
- case 6:
- v.x = hi.x;
- v.y = hi.y;
- v.z = lo.z;
- break;
-
- case 7:
- v.x = lo.x;
- v.y = hi.y;
- v.z = lo.z;
- break;
-
- default:
- debugAssertM(false, "Invalid corner index");
- break;
- }
-
- return v;
-}
-
-
-}
diff --git a/externals/g3dlite/Any.cpp b/externals/g3dlite/Any.cpp
deleted file mode 100644
index de4d32e83ea..00000000000
--- a/externals/g3dlite/Any.cpp
+++ /dev/null
@@ -1,1237 +0,0 @@
-/**
- @file Any.cpp
-
- @author Morgan McGuire
- @author Shawn Yarbrough
-
- @created 2006-06-11
- @edited 2009-11-15
-
- Copyright 2000-2009, Morgan McGuire.
- All rights reserved.
- */
-
-#include "G3D/Any.h"
-#include "G3D/TextOutput.h"
-#include "G3D/TextInput.h"
-#include "G3D/stringutils.h"
-#include <deque>
-#include <iostream>
-
-namespace G3D {
-
-void Any::beforeRead() const {
- if (isPlaceholder()) {
- // Tried to read from a placeholder--throw an exception as if
- // the original operator[] had failed.
- KeyNotFound e;
- alwaysAssertM(m_data, "Corrupt placeholder");
-
- e.filename = m_data->source.filename;
- e.line = m_data->source.line;
- e.character = m_data->source.character;
- e.key = m_placeholderName;
- e.message =
- "This exception may have been thrown later than "
- "the actual operator[] invocation.";
-
- throw e;
- }
-}
-
-
-Any::Data* Any::Data::create(const Data* d) {
- Data* p = create(d->type);
-
- p->comment = d->comment;
- p->name = d->name;
-
- switch (d->type) {
- case NONE:
- case BOOLEAN:
- case NUMBER:
- // No clone needed
- break;
-
- case STRING:
- *(p->value.s) = *(d->value.s);
- break;
-
- case ARRAY:
- *(p->value.a) = *(d->value.a);
- break;
-
- case TABLE:
- *(p->value.t) = *(d->value.t);
- // Note that placeholders may be copied; that is ok--they are still
- // just placeholders.
- break;
- }
-
- return p;
-}
-
-
-Any::Data* Any::Data::create(Any::Type t) {
- size_t s = sizeof(Data);
-
- switch (t) {
- case NONE:
- case BOOLEAN:
- case NUMBER:
- // No extra space needed
- break;
-
- case STRING:
- s += sizeof(std::string);
- break;
-
- case ARRAY:
- s += sizeof(AnyArray);
- break;
-
- case TABLE:
- s += sizeof(AnyTable);
- break;
- }
-
- // Allocate the data object
- Data* p = new (MemoryManager::create()->alloc(s)) Data(t);
-
- // Create the (empyt) value object at the end of the Data object
- switch (t) {
- case NONE:
- case BOOLEAN:
- case NUMBER:
- // No value
- break;
-
- case STRING:
- p->value.s = new (p + 1) std::string();
- break;
-
- case ARRAY:
- p->value.a = new (p + 1) AnyArray();
- break;
-
- case TABLE:
- p->value.t = new (p + 1) AnyTable();
- break;
- }
-
- return p;
-}
-
-
-void Any::Data::destroy(Data* d) {
- if (d != NULL) {
- d->~Data();
- MemoryManager::create()->free(d);
- }
-}
-
-
-Any::Data::~Data() {
- debugAssertM(referenceCount.value() <= 0, "Deleted while still referenced.");
-
- // Destruct but do not deallocate children
- switch (type) {
- case STRING:
- debugAssert(value.s != NULL);
- value.s->~basic_string();
- break;
-
- case ARRAY:
- debugAssert(value.a != NULL);
- value.a->~Array();
- break;
-
- case TABLE:
- debugAssert(value.t != NULL);
- value.t->~Table();
- break;
-
- default:
- // All other types should have a NULL value pointer (i.e., they were used just for name and comment fields)
- debugAssertM(value.s == NULL, "Corrupt Any::Data::Value");
- }
-
- value.s = NULL;
-}
-
-
-//////////////////////////////////////////////////////////////
-
-bool Any::containsKey(const std::string& x) const {
- beforeRead();
- verifyType(TABLE);
-
- Any* a = m_data->value.t->getPointer(x);
-
- // Don't return true for placeholder objects
- return (a != NULL) && (! a->isPlaceholder());
-}
-
-
-void Any::dropReference() {
- if (m_data && m_data->referenceCount.decrement() <= 0) {
- // This was the last reference to the shared data
- Data::destroy(m_data);
- }
- m_data = NULL;
-}
-
-
-void Any::ensureMutable() {
- if (m_data && (m_data->referenceCount.value() >= 1)) {
- // Copy the data. We must do this before dropping the reference
- // to avoid a race condition
- Data* d = Data::create(m_data);
- dropReference();
- m_data = d;
- }
-}
-
-
-Any::Any() : m_type(NONE), m_data(NULL) {
-}
-
-
-Any::Any(TextInput& t) : m_type(NONE), m_data(NULL) {
- deserialize(t);
-}
-
-
-Any::Any(const Any& x) : m_type(NONE), m_data(NULL) {
- x.beforeRead();
- *this = x;
-}
-
-
-Any::Any(double x) : m_type(NUMBER), m_simpleValue(x), m_data(NULL) {
-}
-
-
-#ifdef G3D_32BIT
-Any::Any(int64 x) : m_type(NUMBER), m_simpleValue((double)x), m_data(NULL) {
-}
-#endif // G3D_32BIT
-
-
-Any::Any(long x) : m_type(NUMBER), m_simpleValue((double)x), m_data(NULL) {
-}
-
-
-Any::Any(int x) : m_type(NUMBER), m_simpleValue((double)x), m_data(NULL) {
-}
-
-
-Any::Any(short x) : m_type(NUMBER), m_simpleValue((double)x), m_data(NULL) {
-}
-
-
-Any::Any(bool x) : m_type(BOOLEAN), m_simpleValue(x), m_data(NULL) {
-}
-
-
-Any::Any(const std::string& s) : m_type(STRING), m_data(Data::create(STRING)) {
- *(m_data->value.s) = s;
-}
-
-
-Any::Any(const char* s) : m_type(STRING), m_data(NULL) {
- if (s == NULL) {
- m_type = NONE;
- } else {
- ensureData();
- *(m_data->value.s) = s;
- }
-}
-
-
-Any::Any(Type t, const std::string& name) : m_type(t), m_data(NULL) {
- alwaysAssertM(t == ARRAY || t == TABLE, "Can only create ARRAY or TABLE from Type enum.");
-
- ensureData();
- if (name != "") {
- m_data->name = name;
- }
-}
-
-
-Any::~Any() {
- dropReference();
-}
-
-
-void Any::beforeWrite() {
- if (isPlaceholder()) {
- // This is no longer a placeholder
- m_placeholderName = "";
- }
-}
-
-Any& Any::operator=(const Any& x) {
- x.beforeRead();
-
- if (this == &x) {
- return *this;
- }
-
- beforeWrite();
-
- dropReference();
-
- m_type = x.m_type;
- m_simpleValue = x.m_simpleValue;
-
- if (x.m_data != NULL) {
- x.m_data->referenceCount.increment();
- m_data = x.m_data;
- }
-
- return *this;
-}
-
-
-Any& Any::operator=(double x) {
- *this = Any(x);
- return *this;
-}
-
-
-Any& Any::operator=(int x) {
- return (*this = Any(x));
-}
-
-
-Any& Any::operator=(bool x) {
- *this = Any(x);
- return *this;
-}
-
-
-Any& Any::operator=(const std::string& x) {
- *this = Any(x);
- return *this;
-}
-
-
-Any& Any::operator=(const char* x) {
- *this = Any(x);
- return *this;
-}
-
-
-Any& Any::operator=(Type t) {
- switch (t) {
- case NONE:
- *this = Any();
- break;
-
- case TABLE:
- case ARRAY:
- *this = Any(t);
- break;
-
- default:
- alwaysAssertM(false, "Can only assign NONE, TABLE, or ARRAY Type enum.");
- }
-
- return *this;
-}
-
-
-Any::Type Any::type() const {
- beforeRead();
- return m_type;
-}
-
-
-const std::string& Any::comment() const {
- beforeRead();
-
- static const std::string blank;
- if (m_data != NULL) {
- return m_data->comment;
- } else {
- return blank;
- }
-}
-
-
-void Any::setComment(const std::string& c) {
- beforeRead();
- ensureData();
- m_data->comment = c;
-}
-
-
-bool Any::isNone() const {
- beforeRead();
- return (m_type == NONE);
-}
-
-
-double Any::number() const {
- beforeRead();
- verifyType(NUMBER);
- return m_simpleValue.n;
-}
-
-
-const std::string& Any::string() const {
- beforeRead();
- verifyType(STRING);
- return *(m_data->value.s);
-}
-
-
-bool Any::boolean() const {
- beforeRead();
- verifyType(BOOLEAN);
- return m_simpleValue.b;
-}
-
-
-const std::string& Any::name() const {
- beforeRead();
- static const std::string blank;
- if (m_data != NULL) {
- return m_data->name;
- } else {
- return blank;
- }
-}
-
-
-void Any::setName(const std::string& n) {
- beforeRead();
- ensureData();
- m_data->name = n;
-}
-
-
-int Any::size() const {
- beforeRead();
- verifyType(ARRAY, TABLE);
- switch (m_type) {
- case TABLE:
- return m_data->value.t->size();
-
- case ARRAY:
- return m_data->value.a->size();
-
- default:;
- return 0;
- } // switch (m_type)
-}
-
-
-int Any::length() const {
- beforeRead();
- return size();
-}
-
-
-void Any::resize(int n) {
- beforeRead();
- alwaysAssertM(n >= 0, "Cannot resize less than 0.");
- verifyType(ARRAY);
- m_data->value.a->resize(n);
-}
-
-
-void Any::clear() {
- beforeRead();
- verifyType(ARRAY, TABLE);
- switch (m_type) {
- case ARRAY:
- m_data->value.a->clear();
- break;
-
- case TABLE:
- m_data->value.t->clear();
- break;
-
- default:;
- }
-}
-
-
-const Any& Any::operator[](int i) const {
- beforeRead();
- verifyType(ARRAY);
- debugAssert(m_data != NULL);
- Array<Any>& array = *(m_data->value.a);
- return array[i];
-}
-
-
-Any& Any::next() {
- beforeRead();
- verifyType(ARRAY);
- int n = size();
- resize(n + 1);
- return (*this)[n];
-}
-
-
-Any& Any::operator[](int i) {
- beforeRead();
- verifyType(ARRAY);
- debugAssert(m_data != NULL);
- Array<Any>& array = *(m_data->value.a);
- return array[i];
-}
-
-
-const Array<Any>& Any::array() const {
- beforeRead();
- verifyType(ARRAY);
- debugAssert(m_data != NULL);
- return *(m_data->value.a);
-}
-
-
-void Any::append(const Any& x0) {
- beforeRead();
- verifyType(ARRAY);
- debugAssert(m_data != NULL);
- m_data->value.a->append(x0);
-}
-
-
-void Any::append(const Any& x0, const Any& x1) {
- beforeRead();
- append(x0);
- append(x1);
-}
-
-
-void Any::append(const Any& x0, const Any& x1, const Any& x2) {
- beforeRead();
- append(x0);
- append(x1);
- append(x2);
-}
-
-
-void Any::append(const Any& x0, const Any& x1, const Any& x2, const Any& x3) {
- beforeRead();
- append(x0);
- append(x1);
- append(x2);
- append(x3);
-}
-
-
-const Table<std::string, Any>& Any::table() const {
- beforeRead();
- verifyType(TABLE);
- debugAssert(m_data != NULL);
- return *(m_data->value.t);
-}
-
-
-const Any& Any::operator[](const std::string& x) const {
- beforeRead();
- verifyType(TABLE);
- debugAssert(m_data != NULL);
- const Table<std::string, Any>& table = *(m_data->value.t);
- Any* value = table.getPointer(x);
- if (value == NULL) {
- KeyNotFound e;
- if (m_data) {
- e.filename = m_data->source.filename;
- e.line = m_data->source.line;
- e.character = m_data->source.character;
- }
- e.key = x;
- throw e;
- }
- return *value;
-}
-
-
-Any& Any::operator[](const std::string& key) {
- beforeRead();
- verifyType(TABLE);
-
- bool created = false;
- Any& value = m_data->value.t->getCreate(key, created);
-
- if (created) {
- // The entry was created by this method; do not allow it to be
- // read before it is written.
- value.m_placeholderName = key;
-
- // Write source data for the value
- value.ensureData();
- value.m_data->source = source();
- }
-
- return value;
-}
-
-
-void Any::set(const std::string& k, const Any& v) {
- beforeRead();
- v.beforeRead();
- verifyType(TABLE);
- debugAssert(m_data != NULL);
- Table<std::string, Any>& table = *(m_data->value.t);
- table.set(k, v);
-}
-
-
-const Any& Any::get(const std::string& x, const Any& defaultVal) const {
- beforeRead();
- defaultVal.beforeRead();
- try {
- return operator[](x);
- } catch(KeyNotFound) {
- return defaultVal;
- }
-}
-
-
-bool Any::operator==(const Any& x) const {
- beforeRead();
- x.beforeRead();
- if (m_type != x.m_type) {
- return false;
- }
-
- switch (m_type) {
- case NONE:
- return true;
-
- case BOOLEAN:
- return (m_simpleValue.b == x.m_simpleValue.b);
-
- case NUMBER:
- return (m_simpleValue.n == x.m_simpleValue.n);
-
- case STRING:
- debugAssert(m_data != NULL);
- return (*(m_data->value.s) == *(x.m_data->value.s));
-
- case TABLE: {
- if (size() != x.size()) {
- return false;
- }
- debugAssert(m_data != NULL);
- if (m_data->name != x.m_data->name) {
- return false;
- }
- Table<std::string, Any>& cmptable = *( m_data->value.t);
- Table<std::string, Any>& xcmptable = *(x.m_data->value.t);
- for (Table<std::string,Any>::Iterator it1 = cmptable.begin(), it2 = xcmptable.begin();
- it1 != cmptable.end() && it2 != xcmptable.end();
- ++it1, ++it2) {
- if (*it1 != *it2) {
- return false;
- }
- }
- return true;
- }
-
- case ARRAY: {
- if (size() != x.size()) {
- return false;
- }
- debugAssert(m_data != NULL);
- if (m_data->name != x.m_data->name) {
- return false;
- }
-
- Array<Any>& cmparray = *( m_data->value.a);
- Array<Any>& xcmparray = *(x.m_data->value.a);
-
- for (int ii = 0; ii < size(); ++ii) {
- if (cmparray[ii] != xcmparray[ii]) {
- return false;
- }
- }
- return true;
- }
-
- default:
- alwaysAssertM(false, "Unknown type.");
- return false;
- } // switch (m_type)
-
-}
-
-
-bool Any::operator!=(const Any& x) const {
- beforeRead();
- x.beforeRead();
- return !operator==(x);
-}
-
-
-static void getDeserializeSettings(TextInput::Settings& settings) {
- settings.cppBlockComments = true;
- settings.cppLineComments = true;
- settings.otherLineComments = true;
- settings.otherCommentCharacter = '#';
- settings.generateCommentTokens = true;
- settings.singleQuotedStrings = false;
- settings.msvcSpecials = false;
- settings.caseSensitive = false;
-}
-
-
-std::string Any::unparse() const {
- beforeRead();
- TextOutput::Settings settings;
- TextOutput to(settings);
- serialize(to);
- return to.commitString();
-}
-
-
-void Any::parse(const std::string& src) {
- beforeRead();
- TextInput::Settings settings;
- getDeserializeSettings(settings);
-
- TextInput ti(TextInput::FROM_STRING, src, settings);
- deserialize(ti);
-}
-
-
-void Any::load(const std::string& filename) {
- beforeRead();
- TextInput::Settings settings;
- getDeserializeSettings(settings);
-
- TextInput ti(filename, settings);
- deserialize(ti);
-}
-
-
-void Any::save(const std::string& filename) const {
- beforeRead();
- TextOutput::Settings settings;
- settings.wordWrap = TextOutput::Settings::WRAP_NONE;
-
- TextOutput to(filename,settings);
- serialize(to);
- to.commit();
-}
-
-
-static bool needsQuotes(const std::string& s) {
- if (! isLetter(s[0]) && (s[0] != '_')) {
- return true;
- }
-
- for (int i = 0; i < (int)s.length(); ++i) {
- char c = s[i];
-
- // peek character
- char p = (i == (int)s.length() - 1) ? '_' : s[i + 1];
-
- // Identify separators
- if ((c == '-' && p == '>') ||
- (c == ':' && p == ':')) {
- // Skip over this symbol
- ++i;
- continue;
- }
-
- if (! isDigit(c) && ! isLetter(c) & (c != '.')) {
- // This is an illegal character for an identifier, so we need quotes
- return true;
- }
- }
-
- return false;
-}
-
-
-// TODO: if the output will fit on one line, compress tables and arrays into a single line
-void Any::serialize(TextOutput& to) const {
- beforeRead();
- if (m_data && ! m_data->comment.empty()) {
- to.printf("\n/* %s */\n", m_data->comment.c_str());
- }
-
- switch (m_type) {
- case NONE:
- to.writeSymbol("NONE");
- break;
-
- case BOOLEAN:
- to.writeBoolean(m_simpleValue.b);
- break;
-
- case NUMBER:
- to.writeNumber(m_simpleValue.n);
- break;
-
- case STRING:
- debugAssert(m_data != NULL);
- to.writeString(*(m_data->value.s));
- break;
-
- case TABLE: {
- debugAssert(m_data != NULL);
- if (! m_data->name.empty()) {
- if (needsQuotes(m_data->name)) {
- to.writeString(m_data->name);
- } else {
- to.writeSymbol(m_data->name);
- }
- }
- to.writeSymbol("{");
- to.writeNewline();
- to.pushIndent();
- AnyTable& table = *(m_data->value.t);
- Array<std::string> keys;
- table.getKeys(keys);
- keys.sort();
-
- for (int i = 0; i < keys.size(); ++i) {
-
- to.writeSymbol(keys[i]);
- to.writeSymbol("=");
- table[keys[i]].serialize(to);
-
- if (i < keys.size() - 1) {
- to.writeSymbol(",");
- }
- to.writeNewline();
-
- // Skip a line between table entries
- to.writeNewline();
- }
-
- to.popIndent();
- to.writeSymbol("}");
- break;
- }
-
- case ARRAY: {
- debugAssert(m_data != NULL);
- if (! m_data->name.empty()) {
- // For arrays, leave no trailing space between the name and the paren
- to.writeSymbol(format("%s(", m_data->name.c_str()));
- } else {
- to.writeSymbol("(");
- }
- to.writeNewline();
- to.pushIndent();
- Array<Any>& array = *(m_data->value.a);
- for (int ii = 0; ii < size(); ++ii) {
- array[ii].serialize(to);
- if (ii < size() - 1) {
- to.writeSymbol(",");
- to.writeNewline();
- }
-
- // Put the close paren on an array right behind the last element
- }
- to.popIndent();
- to.writeSymbol(")");
- break;
- }
- }
-}
-
-
-void Any::deserializeComment(TextInput& ti, Token& token, std::string& comment) {
- // Parse comments
- while (token.type() == Token::COMMENT) {
- comment += trimWhitespace(token.string()) + "\n";
-
- // Allow comments to contain newlines.
- do {
- token = ti.read();
- comment += "\n";
- } while (token.type() == Token::NEWLINE);
- }
-
- comment = trimWhitespace(comment);
-}
-
-/** True if \a c is an open paren of some form */
-static bool isOpen(const char c) {
- return c == '(' || c == '[' || c == '{';
-}
-
-
-/** True if \a c is an open paren of some form */
-static bool isClose(const char c) {
- return c == ')' || c == ']' || c == '}';
-}
-
-
-/** True if \a s is a C++ name operator */
-static bool isNameOperator(const std::string& s) {
- return s == "." || s == "::" || s == "->";
-}
-
-
-void Any::deserializeName(TextInput& ti, Token& token, std::string& name) {
- debugAssert(token.type() == Token::SYMBOL);
- std::string s = token.string();
- while (! isOpen(s[0])) {
- name += s;
-
- // Skip newlines and comments
- token = ti.readSignificant();
-
- if (token.type() != Token::SYMBOL) {
- throw ParseError(ti.filename(), token.line(), token.character(),
- "Expected symbol while parsing Any");
- }
- s = token.string();
- }
-}
-
-
-void Any::deserialize(TextInput& ti) {
- beforeRead();
- Token token = ti.read();
- deserialize(ti, token);
- // Restore the last token
- ti.push(token);
-}
-
-
-void Any::deserialize(TextInput& ti, Token& token) {
- // Deallocate old data
- dropReference();
- m_type = NONE;
- m_simpleValue.b = false;
-
- // Skip leading newlines
- while (token.type() == Token::NEWLINE) {
- token = ti.read();
- }
-
- std::string comment;
- if (token.type() == Token::COMMENT) {
- deserializeComment(ti, token, comment);
- }
-
- if (token.type() == Token::END) {
- // There should never be a comment without an Any following it; even
- // if the file ends with some commented out stuff,
- // that should not happen after a comma, so we'd never read that
- // far in a proper file.
- throw ParseError(ti.filename(), token.line(), token.character(),
- "File ended without a properly formed Any");
- }
-
- switch (token.type()) {
- case Token::STRING:
- m_type = STRING;
- ensureData();
- *(m_data->value.s) = token.string();
- m_data->source.set(ti, token);
- break;
-
- case Token::NUMBER:
- m_type = NUMBER;
- m_simpleValue.n = token.number();
- ensureData();
- m_data->source.set(ti, token);
- break;
-
- case Token::BOOLEAN:
- m_type = BOOLEAN;
- m_simpleValue.b = token.boolean();
- ensureData();
- m_data->source.set(ti, token);
- break;
-
- case Token::SYMBOL:
- // Named Array, Named Table, Array, Table, or NONE
- if (toUpper(token.string()) == "NONE") {
- // Nothing left to do; we initialized to NONE originally
- ensureData();
- m_data->source.set(ti, token);
- } else {
- // Array or Table
-
- // Parse the name
-
- // s must have at least one element or this would not have
- // been parsed as a symbol
- std::string name;
- deserializeName(ti, token, name);
- if (token.type() != Token::SYMBOL) {
- throw ParseError(ti.filename(), token.line(), token.character(),
- "Malformed Any TABLE or ARRAY; must start with [, (, or {");
- }
-
- if (isOpen(token.string()[0])) {
- // Array or table
- deserializeBody(ti, token);
- } else {
- throw ParseError(ti.filename(), token.line(), token.character(),
- "Malformed Any TABLE or ARRAY; must start with [, (, or {");
- }
-
- if (! name.empty()) {
- ensureData();
- m_data->name = name;
- }
- } // if NONE
- break;
-
- default:
- throw ParseError(ti.filename(), token.line(), token.character(),
- "Unexpected token");
-
- } // switch
-
- if (! comment.empty()) {
- ensureData();
- m_data->comment = comment;
- }
-
- if (m_type != ARRAY && m_type != TABLE) {
- // Array and table already consumed their last token
- token = ti.read();
- }
-}
-
-
-void Any::ensureData() {
- if (m_data == NULL) {
- m_data = Data::create(m_type);
- }
-}
-
-
-static bool isSeparator(char c) {
- return c == ',' || c == ';';
-}
-
-
-void Any::readUntilCommaOrClose(TextInput& ti, Token& token) {
- while (! ((token.type() == Token::SYMBOL) &&
- (isClose(token.string()[0])) ||
- isSeparator(token.string()[0]))) {
- switch (token.type()) {
- case Token::NEWLINE:
- case Token::COMMENT:
- // Consume
- token = ti.read();
- break;
-
- default:
- throw ParseError(ti.filename(), token.line(), token.character(),
- "Expected a comma or close paren");
- }
- }
-}
-
-
-void Any::deserializeBody(TextInput& ti, Token& token) {
- char closeSymbol = '}';
- m_type = TABLE;
-
- const char c = token.string()[0];
-
- if (c != '{') {
- m_type = ARRAY;
- // Chose the appropriate close symbol
- closeSymbol = (c == '(') ? ')' : ']';
- }
-
- // Allocate the underlying data structure
- ensureData();
- m_data->source.set(ti, token);
-
- // Consume the open token
- token = ti.read();
-
- while (! ((token.type() == Token::SYMBOL) && (token.string()[0] == closeSymbol))) {
-
- // Read any leading comment. This must be done here (and not in the recursive deserialize
- // call) in case the body contains only a comment.
- std::string comment;
- deserializeComment(ti, token, comment);
-
- if ((token.type() == Token::SYMBOL) && (token.string()[0] == closeSymbol)) {
- // We're done; this catches the case where the array is empty
- break;
- }
-
- // Pointer the value being read
- Any a = NULL;
- std::string key;
-
- if (m_type == TABLE) {
- // Read the key
- if (token.type() != Token::SYMBOL && token.type() != Token::STRING) {
- throw ParseError(ti.filename(), token.line(), token.character(), "Expected a name");
- }
-
- key = token.string();
- // Consume everything up to the = sign
- token = ti.readSignificant();
-
- if ((token.type() != Token::SYMBOL) || (token.string() != "=")) {
- throw ParseError(ti.filename(), token.line(), token.character(), "Expected =");
- } else {
- // Consume (don't consume comments--we want the value pointed to by a to get those).
- token = ti.read();
- }
- }
- a.deserialize(ti, token);
-
- if (! comment.empty()) {
- // Prepend the comment we read earlier
- a.ensureData();
- a.m_data->comment = trimWhitespace(comment + "\n" + a.m_data->comment);
- }
-
- if (m_type == TABLE) {
- set(key, a);
- } else {
- append(a);
- }
-
- // Read until the comma or close paren, discarding trailing comments and newlines
- readUntilCommaOrClose(ti, token);
-
- // Consume the comma
- if (isSeparator(token.string()[0])) {
- token = ti.read();
- }
- }
-
- // Consume the close paren (to match other deserialize methods)
- token = ti.read();
-}
-
-
-Any::operator int() const {
- beforeRead();
- return iRound(number());
-}
-
-
-Any::operator float() const {
- beforeRead();
- return float(number());
-}
-
-
-Any::operator double() const {
- beforeRead();
- return number();
-}
-
-
-Any::operator bool() const {
- beforeRead();
- return boolean();
-}
-
-
-Any::operator std::string() const {
- beforeRead();
- return string();
-}
-
-
-const Any::Source& Any::source() const {
- static Source s;
- if (m_data) {
- return m_data->source;
- } else {
- return s;
- }
-}
-
-
-void Any::verify(bool value, const std::string& message) const {
- beforeRead();
- if (! value) {
- ParseError p;
- if (m_data) {
- p.filename = m_data->source.filename;
- p.line = m_data->source.line;
- p.character = m_data->source.character;
- }
-
- if (name().empty()) {
- p.message = "Parse error";
- } else {
- p.message = "Parse error while reading the contents of " + name();
- }
-
- if (! message.empty()) {
- p.message = p.message + ": " + message;
- }
-
- throw p;
- }
-}
-
-
-void Any::verifyName(const std::string& n) const {
- beforeRead();
- verify(beginsWith(toUpper(name()), toUpper(n)), "Name must begin with " + n);
-}
-
-
-void Any::verifyType(Type t) const {
- beforeRead();
- if (type() != t) {
- verify(false, "Must have type " + toString(t));
- }
-}
-
-
-void Any::verifyType(Type t0, Type t1) const {
- beforeRead();
- if (type() != t0 && type() != t1) {
- verify(false, "Must have type " + toString(t0) + " or " + toString(t1));
- }
-}
-
-
-void Any::verifySize(int low, int high) const {
- beforeRead();
- verifyType(ARRAY, TABLE);
- if (size() < low || size() > high) {
- verify(false, format("Size must be between %d and %d", low, high));
- }
-}
-
-
-void Any::verifySize(int s) const {
- beforeRead();
- verifyType(ARRAY, TABLE);
- if (size() != s) {
- verify(false, format("Size must be %d", s));
- }
-}
-
-
-std::string Any::toString(Type t) {
- switch(t) {
- case NONE: return "NONE";
- case BOOLEAN: return "BOOLEAN";
- case NUMBER: return "NUMBER";
- case STRING: return "STRING";
- case ARRAY: return "ARRAY";
- case TABLE: return "TABLE";
- default:
- alwaysAssertM(false, "Illegal Any::Type");
- return "";
- }
-}
-
-} // namespace G3D
-
diff --git a/externals/g3dlite/BinaryFormat.cpp b/externals/g3dlite/BinaryFormat.cpp
deleted file mode 100644
index d3991378f45..00000000000
--- a/externals/g3dlite/BinaryFormat.cpp
+++ /dev/null
@@ -1,81 +0,0 @@
-/**
- @file BinaryFormat.cpp
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2005-06-10
- @edited 2005-06-10
- */
-
-#include "G3D/BinaryFormat.h"
-
-namespace G3D {
-
-int32 byteSize(BinaryFormat f) {
- switch (f) {
- case BOOL8_BINFMT:
- case UINT8_BINFMT:
- case INT8_BINFMT:
- return 1;
-
- case UINT16_BINFMT:
- case INT16_BINFMT:
- return 2;
-
- case FLOAT16_BINFMT:
- return 2;
-
- case UINT32_BINFMT:
- case INT32_BINFMT:
- case FLOAT32_BINFMT:
- return 4;
-
- case FLOAT64_BINFMT:
- case UINT64_BINFMT:
- case INT64_BINFMT:
- return 8;
-
- case INT128_BINFMT:
- case UINT128_BINFMT:
- return 16;
-
- case VECTOR2_BINFMT:
- return 2 * 4;
-
- case VECTOR2INT16_BINFMT:
- return 2 * 2;
-
- case VECTOR3_BINFMT:
- return 3 * 4;
-
- case VECTOR3INT16_BINFMT:
- return 3 * 2;
-
- case VECTOR4_BINFMT:
- return 4 * 4;
-
- case VECTOR4INT16_BINFMT:
- return 4 * 4;
-
- case COLOR3_BINFMT:
- return 3 * 4;
-
- case COLOR3UINT8_BINFMT:
- return 3 * 1;
-
- case COLOR3INT16_BINFMT:
- return 3 * 2;
-
- case COLOR4_BINFMT:
- return 4 * 4;
-
- case COLOR4UINT8_BINFMT:
- return 4 * 1;
-
- case COLOR4INT16_BINFMT:
- return 4 * 2;
-
- default:
- return -1;
- }
-}
-}
diff --git a/externals/g3dlite/BinaryInput.cpp b/externals/g3dlite/BinaryInput.cpp
deleted file mode 100644
index 65a9976fe04..00000000000
--- a/externals/g3dlite/BinaryInput.cpp
+++ /dev/null
@@ -1,568 +0,0 @@
-/**
- @file BinaryInput.cpp
-
- @author Morgan McGuire, graphics3d.com
- Copyright 2001-2007, Morgan McGuire. All rights reserved.
-
- @created 2001-08-09
- @edited 2005-02-24
-
-
- <PRE>
- {
- BinaryOutput b("c:/tmp/test.b", BinaryOutput::LITTLE_ENDIAN);
-
- float f = 3.1415926;
- int i = 1027221;
- std::string s = "Hello World!";
-
- b.writeFloat32(f);
- b.writeInt32(i);
- b.writeString(s);
- b.commit();
-
-
- BinaryInput in("c:/tmp/test.b", BinaryInput::LITTLE_ENDIAN);
-
- debugAssert(f == in.readFloat32());
- int ii = in.readInt32();
- debugAssert(i == ii);
- debugAssert(s == in.readString());
- }
- </PRE>
- */
-
-#include "G3D/platform.h"
-#include "G3D/BinaryInput.h"
-#include "G3D/Array.h"
-#include "G3D/fileutils.h"
-#include "G3D/Log.h"
-#include <zlib.h>
-
-#include <cstring>
-
-namespace G3D {
-
-void BinaryInput::readBool8(std::vector<bool>& out, int64 n) {
- out.resize((int)n);
- // std::vector optimizes bool in a way that prevents fast reading
- for (int64 i = 0; i < n ; ++i) {
- out[i] = readBool8();
- }
-}
-
-
-void BinaryInput::readBool8(Array<bool>& out, int64 n) {
- out.resize(n);
- readBool8(out.begin(), n);
-}
-
-
-#define IMPLEMENT_READER(ucase, lcase)\
-void BinaryInput::read##ucase(std::vector<lcase>& out, int64 n) {\
- out.resize(n);\
- read##ucase(&out[0], n);\
-}\
-\
-\
-void BinaryInput::read##ucase(Array<lcase>& out, int64 n) {\
- out.resize(n);\
- read##ucase(out.begin(), n);\
-}
-
-
-IMPLEMENT_READER(UInt8, uint8)
-IMPLEMENT_READER(Int8, int8)
-IMPLEMENT_READER(UInt16, uint16)
-IMPLEMENT_READER(Int16, int16)
-IMPLEMENT_READER(UInt32, uint32)
-IMPLEMENT_READER(Int32, int32)
-IMPLEMENT_READER(UInt64, uint64)
-IMPLEMENT_READER(Int64, int64)
-IMPLEMENT_READER(Float32, float32)
-IMPLEMENT_READER(Float64, float64)
-
-#undef IMPLEMENT_READER
-
-// Data structures that are one byte per element can be
-// directly copied, regardles of endian-ness.
-#define IMPLEMENT_READER(ucase, lcase)\
-void BinaryInput::read##ucase(lcase* out, int64 n) {\
- if (sizeof(lcase) == 1) {\
- readBytes(out, n);\
- } else {\
- for (int64 i = 0; i < n ; ++i) {\
- out[i] = read##ucase();\
- }\
- }\
-}
-
-IMPLEMENT_READER(Bool8, bool)
-IMPLEMENT_READER(UInt8, uint8)
-IMPLEMENT_READER(Int8, int8)
-
-#undef IMPLEMENT_READER
-
-
-#define IMPLEMENT_READER(ucase, lcase)\
-void BinaryInput::read##ucase(lcase* out, int64 n) {\
- if (m_swapBytes) {\
- for (int64 i = 0; i < n; ++i) {\
- out[i] = read##ucase();\
- }\
- } else {\
- readBytes(out, sizeof(lcase) * n);\
- }\
-}
-
-
-IMPLEMENT_READER(UInt16, uint16)
-IMPLEMENT_READER(Int16, int16)
-IMPLEMENT_READER(UInt32, uint32)
-IMPLEMENT_READER(Int32, int32)
-IMPLEMENT_READER(UInt64, uint64)
-IMPLEMENT_READER(Int64, int64)
-IMPLEMENT_READER(Float32, float32)
-IMPLEMENT_READER(Float64, float64)
-
-#undef IMPLEMENT_READER
-
-void BinaryInput::loadIntoMemory(int64 startPosition, int64 minLength) {
- // Load the next section of the file
- debugAssertM(m_filename != "<memory>", "Read past end of file.");
-
- int64 absPos = m_alreadyRead + m_pos;
-
- if (m_bufferLength < minLength) {
- // The current buffer isn't big enough to hold the chunk we want to read.
- // This happens if there was little memory available during the initial constructor
- // read but more memory has since been freed.
- m_bufferLength = minLength;
- debugAssert(m_freeBuffer);
- m_buffer = (uint8*)System::realloc(m_buffer, m_bufferLength);
- if (m_buffer == NULL) {
- throw "Tried to read a larger memory chunk than could fit in memory. (2)";
- }
- }
-
- m_alreadyRead = startPosition;
-
-# ifdef G3D_WIN32
- FILE* file = fopen(m_filename.c_str(), "rb");
- debugAssert(file);
- int ret = fseek(file, (off_t)m_alreadyRead, SEEK_SET);
- debugAssert(ret == 0);
- size_t toRead = (size_t)G3D::min(m_bufferLength, m_length - m_alreadyRead);
- ret = fread(m_buffer, 1, toRead, file);
- debugAssert(ret == toRead);
- fclose(file);
- file = NULL;
-
-# else
- FILE* file = fopen(m_filename.c_str(), "rb");
- debugAssert(file);
- int ret = fseeko(file, (off_t)m_alreadyRead, SEEK_SET);
- debugAssert(ret == 0);
- size_t toRead = (size_t)G3D::min<int64>(m_bufferLength, m_length - m_alreadyRead);
- ret = fread(m_buffer, 1, toRead, file);
- debugAssert((size_t)ret == (size_t)toRead);
- fclose(file);
- file = NULL;
-# endif
-
- m_pos = absPos - m_alreadyRead;
- debugAssert(m_pos >= 0);
-}
-
-
-
-const bool BinaryInput::NO_COPY = false;
-
-static bool needSwapBytes(G3DEndian fileEndian) {
- return (fileEndian != System::machineEndian());
-}
-
-
-/** Helper used by the constructors for decompression */
-static uint32 readUInt32(const uint8* data, bool swapBytes) {
- if (swapBytes) {
- uint8 out[4];
- out[0] = data[3];
- out[1] = data[2];
- out[2] = data[1];
- out[3] = data[0];
- return *((uint32*)out);
- } else {
- return *((uint32*)data);
- }
-}
-
-
-void BinaryInput::setEndian(G3DEndian e) {
- m_fileEndian = e;
- m_swapBytes = needSwapBytes(m_fileEndian);
-}
-
-
-BinaryInput::BinaryInput(
- const uint8* data,
- int64 dataLen,
- G3DEndian dataEndian,
- bool compressed,
- bool copyMemory) :
- m_filename("<memory>"),
- m_bitPos(0),
- m_bitString(0),
- m_beginEndBits(0),
- m_alreadyRead(0),
- m_bufferLength(0),
- m_pos(0) {
-
- m_freeBuffer = copyMemory || compressed;
-
- setEndian(dataEndian);
-
- if (compressed) {
- // Read the decompressed size from the first 4 bytes
- m_length = G3D::readUInt32(data, m_swapBytes);
-
- debugAssert(m_freeBuffer);
- m_buffer = (uint8*)System::alignedMalloc(m_length, 16);
-
- unsigned long L = m_length;
- // Decompress with zlib
- int64 result = uncompress(m_buffer, (unsigned long*)&L, data + 4, dataLen - 4);
- m_length = L;
- m_bufferLength = L;
- debugAssert(result == Z_OK); (void)result;
-
- } else {
- m_length = dataLen;
- m_bufferLength = m_length;
- if (! copyMemory) {
- debugAssert(!m_freeBuffer);
- m_buffer = const_cast<uint8*>(data);
- } else {
- debugAssert(m_freeBuffer);
- m_buffer = (uint8*)System::alignedMalloc(m_length, 16);
- System::memcpy(m_buffer, data, dataLen);
- }
- }
-}
-
-
-BinaryInput::BinaryInput(
- const std::string& filename,
- G3DEndian fileEndian,
- bool compressed) :
- m_filename(filename),
- m_bitPos(0),
- m_bitString(0),
- m_beginEndBits(0),
- m_alreadyRead(0),
- m_length(0),
- m_bufferLength(0),
- m_buffer(NULL),
- m_pos(0),
- m_freeBuffer(true) {
-
- setEndian(fileEndian);
-
- // Update global file tracker
- _internal::currentFilesUsed.insert(m_filename);
-
-
- if (! fileExists(m_filename, false)) {
- std::string zipfile;
- std::string internalfile;
- if (zipfileExists(m_filename, zipfile, internalfile)) {
- // Load from zipfile
- void* v;
- size_t s;
- zipRead(filename, v, s);
- m_buffer = reinterpret_cast<uint8*>(v);
- m_bufferLength = m_length = s;
- if (compressed) {
- decompress();
- }
- m_freeBuffer = true;
- } else {
- Log::common()->printf("Warning: File not found: %s\n", m_filename.c_str());
- }
- return;
- }
-
- // Figure out how big the file is and verify that it exists.
- m_length = fileLength(m_filename);
-
- // Read the file into memory
- FILE* file = fopen(m_filename.c_str(), "rb");
-
- if (! file || (m_length == -1)) {
- throw format("File not found: \"%s\"", m_filename.c_str());
- return;
- }
-
- if (! compressed && (m_length > INITIAL_BUFFER_LENGTH)) {
- // Read only a subset of the file so we don't consume
- // all available memory.
- m_bufferLength = INITIAL_BUFFER_LENGTH;
- } else {
- // Either the length is fine or the file is compressed
- // and requires us to read the whole thing for zlib.
- m_bufferLength = m_length;
- }
-
- debugAssert(m_freeBuffer);
- m_buffer = (uint8*)System::alignedMalloc(m_bufferLength, 16);
- if (m_buffer == NULL) {
- if (compressed) {
- throw "Not enough memory to load compressed file. (1)";
- }
-
- // Try to allocate a small array; not much memory is available.
- // Give up if we can't allocate even 1k.
- while ((m_buffer == NULL) && (m_bufferLength > 1024)) {
- m_bufferLength /= 2;
- m_buffer = (uint8*)System::alignedMalloc(m_bufferLength, 16);
- }
- }
- debugAssert(m_buffer);
-
- fread(m_buffer, m_bufferLength, sizeof(int8), file);
- fclose(file);
- file = NULL;
-
- if (compressed) {
- if (m_bufferLength != m_length) {
- throw "Not enough memory to load compressed file. (2)";
- }
-
- decompress();
- }
-}
-
-void BinaryInput::decompress() {
- // Decompress
- // Use the existing buffer as the source, allocate
- // a new buffer to use as the destination.
-
- int64 tempLength = m_length;
- m_length = G3D::readUInt32(m_buffer, m_swapBytes);
-
- // The file couldn't have better than 500:1 compression
- alwaysAssertM(m_length < m_bufferLength * 500, "Compressed file header is corrupted");
-
- uint8* tempBuffer = m_buffer;
- m_buffer = (uint8*)System::alignedMalloc(m_length, 16);
-
- debugAssert(m_buffer);
- debugAssert(isValidHeapPointer(tempBuffer));
- debugAssert(isValidHeapPointer(m_buffer));
-
- unsigned long L = m_length;
- int64 result = uncompress(m_buffer, &L, tempBuffer + 4, tempLength - 4);
- m_length = L;
- m_bufferLength = m_length;
-
- debugAssertM(result == Z_OK, "BinaryInput/zlib detected corruption in " + m_filename);
- (void)result;
-
- System::alignedFree(tempBuffer);
-}
-
-
-void BinaryInput::readBytes(void* bytes, int64 n) {
- prepareToRead(n);
- debugAssert(isValidPointer(bytes));
-
- memcpy(bytes, m_buffer + m_pos, n);
- m_pos += n;
-}
-
-
-BinaryInput::~BinaryInput() {
-
- if (m_freeBuffer) {
- System::alignedFree(m_buffer);
- }
- m_buffer = NULL;
-}
-
-
-uint64 BinaryInput::readUInt64() {
- prepareToRead(8);
- uint8 out[8];
-
- if (m_swapBytes) {
- out[0] = m_buffer[m_pos + 7];
- out[1] = m_buffer[m_pos + 6];
- out[2] = m_buffer[m_pos + 5];
- out[3] = m_buffer[m_pos + 4];
- out[4] = m_buffer[m_pos + 3];
- out[5] = m_buffer[m_pos + 2];
- out[6] = m_buffer[m_pos + 1];
- out[7] = m_buffer[m_pos + 0];
- } else {
- *(uint64*)out = *(uint64*)(m_buffer + m_pos);
- }
-
- m_pos += 8;
- return *(uint64*)out;
-}
-
-
-std::string BinaryInput::readString(int64 n) {
- prepareToRead(n);
- debugAssertM((m_pos + n) <= m_length, "Read past end of file");
-
- char *s = (char*)System::alignedMalloc(n + 1, 16);
- assert(s != NULL);
-
- memcpy(s, m_buffer + m_pos, n);
- // There may not be a null, so make sure
- // we add one.
- s[n] = '\0';
-
- std::string out = s;
- System::alignedFree(s);
- s = NULL;
-
- m_pos += n;
-
- return out;
-
-}
-
-
-std::string BinaryInput::readString() {
- int64 n = 0;
-
- if ((m_pos + m_alreadyRead + n) < (m_length - 1)) {
- prepareToRead(1);
- }
-
- if ( ((m_pos + m_alreadyRead + n) < (m_length - 1)) &&
- (m_buffer[m_pos + n] != '\0')) {
-
- ++n;
- while ( ((m_pos + m_alreadyRead + n) < (m_length - 1)) &&
- (m_buffer[m_pos + n] != '\0')) {
-
- prepareToRead(1);
- ++n;
- }
- }
-
- // Consume NULL
- ++n;
-
- return readString(n);
-}
-
-
-std::string BinaryInput::readStringEven() {
- std::string x = readString();
- if (hasMore() && (G3D::isOdd(x.length() + 1))) {
- skip(1);
- }
- return x;
-}
-
-
-std::string BinaryInput::readString32() {
- int len = readUInt32();
- return readString(len);
-}
-
-
-Vector4 BinaryInput::readVector4() {
- float x = readFloat32();
- float y = readFloat32();
- float z = readFloat32();
- float w = readFloat32();
- return Vector4(x, y, z, w);
-}
-
-
-Vector3 BinaryInput::readVector3() {
- float x = readFloat32();
- float y = readFloat32();
- float z = readFloat32();
- return Vector3(x, y, z);
-}
-
-
-Vector2 BinaryInput::readVector2() {
- float x = readFloat32();
- float y = readFloat32();
- return Vector2(x, y);
-}
-
-
-Color4 BinaryInput::readColor4() {
- float r = readFloat32();
- float g = readFloat32();
- float b = readFloat32();
- float a = readFloat32();
- return Color4(r, g, b, a);
-}
-
-
-Color3 BinaryInput::readColor3() {
- float r = readFloat32();
- float g = readFloat32();
- float b = readFloat32();
- return Color3(r, g, b);
-}
-
-
-void BinaryInput::beginBits() {
- debugAssert(m_beginEndBits == 0);
- m_beginEndBits = 1;
- m_bitPos = 0;
-
- debugAssertM(hasMore(), "Can't call beginBits when at the end of a file");
- m_bitString = readUInt8();
-}
-
-
-uint32 BinaryInput::readBits(int numBits) {
- debugAssert(m_beginEndBits == 1);
-
- uint32 out = 0;
-
- const int total = numBits;
- while (numBits > 0) {
- if (m_bitPos > 7) {
- // Consume a new byte for reading. We do this at the beginning
- // of the loop so that we don't try to read past the end of the file.
- m_bitPos = 0;
- m_bitString = readUInt8();
- }
-
- // Slide the lowest bit of the bitString into
- // the correct position.
- out |= (m_bitString & 1) << (total - numBits);
-
- // Shift over to the next bit
- m_bitString = m_bitString >> 1;
- ++m_bitPos;
- --numBits;
- }
-
- return out;
-}
-
-
-void BinaryInput::endBits() {
- debugAssert(m_beginEndBits == 1);
- if (m_bitPos == 0) {
- // Put back the last byte we read
- --m_pos;
- }
- m_beginEndBits = 0;
- m_bitPos = 0;
-}
-
-}
diff --git a/externals/g3dlite/BinaryOutput.cpp b/externals/g3dlite/BinaryOutput.cpp
deleted file mode 100644
index 2de46c6d4bb..00000000000
--- a/externals/g3dlite/BinaryOutput.cpp
+++ /dev/null
@@ -1,522 +0,0 @@
-/**
- @file BinaryOutput.cpp
-
- @author Morgan McGuire, graphics3d.com
- Copyright 2002-2007, Morgan McGuire, All rights reserved.
-
- @created 2002-02-20
- @edited 2008-01-07
- */
-
-#include "G3D/platform.h"
-#include "G3D/BinaryOutput.h"
-#include "G3D/fileutils.h"
-#include "G3D/stringutils.h"
-#include "G3D/Array.h"
-#include <zlib.h>
-
-#include <cstring>
-
-// Largest memory buffer that the system will use for writing to
-// disk. After this (or if the system runs out of memory)
-// chunks of the file will be dumped to disk.
-//
-// Currently 400 MB
-#define MAX_BINARYOUTPUT_BUFFER_SIZE 400000000
-
-namespace G3D {
-
-void BinaryOutput::writeBool8(const std::vector<bool>& out, int n) {
- for (int i = 0; i < n; ++i) {
- writeBool8(out[i]);
- }
-}
-
-
-void BinaryOutput::writeBool8(const Array<bool>& out, int n) {
- writeBool8(out.getCArray(), n);
-}
-
-#define IMPLEMENT_WRITER(ucase, lcase)\
-void BinaryOutput::write##ucase(const std::vector<lcase>& out, int n) {\
- write##ucase(&out[0], n);\
-}\
-\
-\
-void BinaryOutput::write##ucase(const Array<lcase>& out, int n) {\
- write##ucase(out.getCArray(), n);\
-}
-
-
-IMPLEMENT_WRITER(UInt8, uint8)
-IMPLEMENT_WRITER(Int8, int8)
-IMPLEMENT_WRITER(UInt16, uint16)
-IMPLEMENT_WRITER(Int16, int16)
-IMPLEMENT_WRITER(UInt32, uint32)
-IMPLEMENT_WRITER(Int32, int32)
-IMPLEMENT_WRITER(UInt64, uint64)
-IMPLEMENT_WRITER(Int64, int64)
-IMPLEMENT_WRITER(Float32, float32)
-IMPLEMENT_WRITER(Float64, float64)
-
-#undef IMPLEMENT_WRITER
-
-// Data structures that are one byte per element can be
-// directly copied, regardles of endian-ness.
-#define IMPLEMENT_WRITER(ucase, lcase)\
-void BinaryOutput::write##ucase(const lcase* out, int n) {\
- if (sizeof(lcase) == 1) {\
- writeBytes((void*)out, n);\
- } else {\
- for (int i = 0; i < n ; ++i) {\
- write##ucase(out[i]);\
- }\
- }\
-}
-
-IMPLEMENT_WRITER(Bool8, bool)
-IMPLEMENT_WRITER(UInt8, uint8)
-IMPLEMENT_WRITER(Int8, int8)
-
-#undef IMPLEMENT_WRITER
-
-
-#define IMPLEMENT_WRITER(ucase, lcase)\
-void BinaryOutput::write##ucase(const lcase* out, int n) {\
- if (m_swapBytes) {\
- for (int i = 0; i < n; ++i) {\
- write##ucase(out[i]);\
- }\
- } else {\
- writeBytes((const void*)out, sizeof(lcase) * n);\
- }\
-}
-
-
-IMPLEMENT_WRITER(UInt16, uint16)
-IMPLEMENT_WRITER(Int16, int16)
-IMPLEMENT_WRITER(UInt32, uint32)
-IMPLEMENT_WRITER(Int32, int32)
-IMPLEMENT_WRITER(UInt64, uint64)
-IMPLEMENT_WRITER(Int64, int64)
-IMPLEMENT_WRITER(Float32, float32)
-IMPLEMENT_WRITER(Float64, float64)
-
-#undef IMPLEMENT_WRITER
-
-
-void BinaryOutput::reallocBuffer(size_t bytes, size_t oldBufferLen) {
- //debugPrintf("reallocBuffer(%d, %d)\n", bytes, oldBufferLen);
-
- size_t newBufferLen = (int)(m_bufferLen * 1.5) + 100;
- uint8* newBuffer = NULL;
-
- if ((m_filename == "<memory>") || (newBufferLen < MAX_BINARYOUTPUT_BUFFER_SIZE)) {
- // We're either writing to memory (in which case we *have* to try and allocate)
- // or we've been asked to allocate a reasonable size buffer.
-
- //debugPrintf(" realloc(%d)\n", newBufferLen);
- newBuffer = (uint8*)System::realloc(m_buffer, newBufferLen);
- if (newBuffer != NULL) {
- m_maxBufferLen = newBufferLen;
- }
- }
-
- if ((newBuffer == NULL) && (bytes > 0)) {
- // Realloc failed; we're probably out of memory. Back out
- // the entire call and try to dump some data to disk.
- m_bufferLen = oldBufferLen;
- reserveBytesWhenOutOfMemory(bytes);
- } else {
- m_buffer = newBuffer;
- debugAssert(isValidHeapPointer(m_buffer));
- }
-}
-
-
-void BinaryOutput::reserveBytesWhenOutOfMemory(size_t bytes) {
- if (m_filename == "<memory>") {
- throw "Out of memory while writing to memory in BinaryOutput (no RAM left).";
- } else if ((int)bytes > (int)m_maxBufferLen) {
- throw "Out of memory while writing to disk in BinaryOutput (could not create a large enough buffer).";
- } else {
-
- // Dump the contents to disk. In order to enable seeking backwards,
- // we keep the last 10 MB in memory.
- int writeBytes = m_bufferLen - 10 * 1024 * 1024;
-
- if (writeBytes < m_bufferLen / 3) {
- // We're going to write less than 1/3 of the file;
- // give up and just write the whole thing.
- writeBytes = m_bufferLen;
- }
- debugAssert(writeBytes > 0);
-
- //debugPrintf("Writing %d bytes to disk\n", writeBytes);
-
- const char* mode = (m_alreadyWritten > 0) ? "ab" : "wb";
- FILE* file = fopen(m_filename.c_str(), mode);
- debugAssert(file);
-
- size_t count = fwrite(m_buffer, 1, writeBytes, file);
- debugAssert((int)count == writeBytes); (void)count;
-
- fclose(file);
- file = NULL;
-
- // Record that we saved this data.
- m_alreadyWritten += writeBytes;
- m_bufferLen -= writeBytes;
- m_pos -= writeBytes;
-
- debugAssert(m_bufferLen < m_maxBufferLen);
- debugAssert(m_bufferLen >= 0);
- debugAssert(m_pos >= 0);
- debugAssert(m_pos <= m_bufferLen);
-
- // Shift the unwritten data back appropriately in the buffer.
- debugAssert(isValidHeapPointer(m_buffer));
- System::memcpy(m_buffer, m_buffer + writeBytes, m_bufferLen);
- debugAssert(isValidHeapPointer(m_buffer));
-
- // *now* we allocate bytes (there should presumably be enough
- // space in the buffer; if not, we'll come back through this
- // code and dump the last 10MB to disk as well. Note that the
- // bytes > maxBufferLen case above would already have triggered
- // if this call couldn't succeed.
- reserveBytes(bytes);
- }
-}
-
-
-BinaryOutput::BinaryOutput() {
- m_alreadyWritten = 0;
- m_swapBytes = false;
- m_pos = 0;
- m_filename = "<memory>";
- m_buffer = NULL;
- m_bufferLen = 0;
- m_maxBufferLen = 0;
- m_beginEndBits = 0;
- m_bitString = 0;
- m_bitPos = 0;
- m_ok = true;
- m_committed = false;
-}
-
-
-BinaryOutput::BinaryOutput(
- const std::string& filename,
- G3DEndian fileEndian) {
-
- m_pos = 0;
- m_alreadyWritten = 0;
- setEndian(fileEndian);
- m_filename = filename;
- m_buffer = NULL;
- m_bufferLen = 0;
- m_maxBufferLen = 0;
- m_beginEndBits = 0;
- m_bitString = 0;
- m_bitPos = 0;
- m_committed = false;
-
- m_ok = true;
- /** Verify ability to write to disk */
- commit(false);
- m_committed = false;
-}
-
-
-void BinaryOutput::reset() {
- debugAssert(m_beginEndBits == 0);
- alwaysAssertM(m_filename == "<memory>",
- "Can only reset a BinaryOutput that writes to memory.");
-
- // Do not reallocate, just clear the size of the buffer.
- m_pos = 0;
- m_alreadyWritten = 0;
- m_bufferLen = 0;
- m_beginEndBits = 0;
- m_bitString = 0;
- m_bitPos = 0;
- m_committed = false;
-}
-
-
-BinaryOutput::~BinaryOutput() {
- debugAssert((m_buffer == NULL) || isValidHeapPointer(m_buffer));
- System::free(m_buffer);
- m_buffer = NULL;
- m_bufferLen = 0;
- m_maxBufferLen = 0;
-}
-
-
-void BinaryOutput::setEndian(G3DEndian fileEndian) {
- m_fileEndian = fileEndian;
- m_swapBytes = (fileEndian != System::machineEndian());
-}
-
-
-bool BinaryOutput::ok() const {
- return m_ok;
-}
-
-
-void BinaryOutput::compress() {
- if (m_alreadyWritten > 0) {
- throw "Cannot compress huge files (part of this file has already been written to disk).";
- }
-
- // Old buffer size
- int L = m_bufferLen;
- uint8* convert = (uint8*)&L;
-
- // Zlib requires the output buffer to be this big
- unsigned long newSize = iCeil(m_bufferLen * 1.01) + 12;
- uint8* temp = (uint8*)System::malloc(newSize);
- int result = compress2(temp, &newSize, m_buffer, m_bufferLen, 9);
-
- debugAssert(result == Z_OK); (void)result;
-
- // Write the header
- if (m_swapBytes) {
- m_buffer[0] = convert[3];
- m_buffer[1] = convert[2];
- m_buffer[2] = convert[1];
- m_buffer[3] = convert[0];
- } else {
- m_buffer[0] = convert[0];
- m_buffer[1] = convert[1];
- m_buffer[2] = convert[2];
- m_buffer[3] = convert[3];
- }
-
- // Write the data
- if ((int64)newSize + 4 > (int64)m_maxBufferLen) {
- m_maxBufferLen = newSize + 4;
- m_buffer = (uint8*)System::realloc(m_buffer, m_maxBufferLen);
- }
- m_bufferLen = newSize + 4;
- System::memcpy(m_buffer + 4, temp, newSize);
- m_pos = m_bufferLen;
-
- System::free(temp);
-}
-
-
-void BinaryOutput::commit(bool flush) {
- debugAssertM(! m_committed, "Cannot commit twice");
- m_committed = true;
- debugAssertM(m_beginEndBits == 0, "Missing endBits before commit");
-
- // Make sure the directory exists.
- std::string root, base, ext, path;
- Array<std::string> pathArray;
- parseFilename(m_filename, root, pathArray, base, ext);
-
- path = root + stringJoin(pathArray, '/');
- if (! fileExists(path, false)) {
- createDirectory(path);
- }
-
- const char* mode = (m_alreadyWritten > 0) ? "ab" : "wb";
-
- FILE* file = fopen(m_filename.c_str(), mode);
-
- m_ok = (file != NULL) && m_ok;
-
- if (m_ok) {
- debugAssertM(file, std::string("Could not open '") + m_filename + "'");
-
- if (m_buffer != NULL) {
- m_alreadyWritten += m_bufferLen;
-
- int success = fwrite(m_buffer, m_bufferLen, 1, file);
- (void)success;
- debugAssertM(success == 1, std::string("Could not write to '") + m_filename + "'");
- }
- if (flush) {
- fflush(file);
- }
- fclose(file);
- file = NULL;
- }
-}
-
-
-void BinaryOutput::commit(
- uint8* out) {
- debugAssertM(! m_committed, "Cannot commit twice");
- m_committed = true;
-
- System::memcpy(out, m_buffer, m_bufferLen);
-}
-
-
-void BinaryOutput::writeUInt16(uint16 u) {
- reserveBytes(2);
-
- uint8* convert = (uint8*)&u;
-
- if (m_swapBytes) {
- m_buffer[m_pos] = convert[1];
- m_buffer[m_pos + 1] = convert[0];
- } else {
- *(uint16*)(m_buffer + m_pos) = u;
- }
-
- m_pos += 2;
-}
-
-
-void BinaryOutput::writeUInt32(uint32 u) {
- reserveBytes(4);
-
- uint8* convert = (uint8*)&u;
-
- debugAssert(m_beginEndBits == 0);
-
- if (m_swapBytes) {
- m_buffer[m_pos] = convert[3];
- m_buffer[m_pos + 1] = convert[2];
- m_buffer[m_pos + 2] = convert[1];
- m_buffer[m_pos + 3] = convert[0];
- } else {
- *(uint32*)(m_buffer + m_pos) = u;
- }
-
- m_pos += 4;
-}
-
-
-void BinaryOutput::writeUInt64(uint64 u) {
- reserveBytes(8);
-
- uint8* convert = (uint8*)&u;
-
- if (m_swapBytes) {
- m_buffer[m_pos] = convert[7];
- m_buffer[m_pos + 1] = convert[6];
- m_buffer[m_pos + 2] = convert[5];
- m_buffer[m_pos + 3] = convert[4];
- m_buffer[m_pos + 4] = convert[3];
- m_buffer[m_pos + 5] = convert[2];
- m_buffer[m_pos + 6] = convert[1];
- m_buffer[m_pos + 7] = convert[0];
- } else {
- *(uint64*)(m_buffer + m_pos) = u;
- }
-
- m_pos += 8;
-}
-
-
-void BinaryOutput::writeString(const char* s) {
- // +1 is because strlen doesn't count the null
- int len = strlen(s) + 1;
-
- debugAssert(m_beginEndBits == 0);
- reserveBytes(len);
- System::memcpy(m_buffer + m_pos, s, len);
- m_pos += len;
-}
-
-
-void BinaryOutput::writeStringEven(const char* s) {
- // +1 is because strlen doesn't count the null
- int len = strlen(s) + 1;
-
- reserveBytes(len);
- System::memcpy(m_buffer + m_pos, s, len);
- m_pos += len;
-
- // Pad with another NULL
- if ((len % 2) == 1) {
- writeUInt8(0);
- }
-}
-
-
-void BinaryOutput::writeString32(const char* s) {
- writeUInt32(strlen(s) + 1);
- writeString(s);
-}
-
-
-void BinaryOutput::writeVector4(const Vector4& v) {
- writeFloat32(v.x);
- writeFloat32(v.y);
- writeFloat32(v.z);
- writeFloat32(v.w);
-}
-
-
-void BinaryOutput::writeVector3(const Vector3& v) {
- writeFloat32(v.x);
- writeFloat32(v.y);
- writeFloat32(v.z);
-}
-
-
-void BinaryOutput::writeVector2(const Vector2& v) {
- writeFloat32(v.x);
- writeFloat32(v.y);
-}
-
-
-void BinaryOutput::writeColor4(const Color4& v) {
- writeFloat32(v.r);
- writeFloat32(v.g);
- writeFloat32(v.b);
- writeFloat32(v.a);
-}
-
-
-void BinaryOutput::writeColor3(const Color3& v) {
- writeFloat32(v.r);
- writeFloat32(v.g);
- writeFloat32(v.b);
-}
-
-
-void BinaryOutput::beginBits() {
- debugAssertM(m_beginEndBits == 0, "Already in beginBits...endBits");
- m_bitString = 0x00;
- m_bitPos = 0;
- m_beginEndBits = 1;
-}
-
-
-void BinaryOutput::writeBits(uint32 value, int numBits) {
-
- while (numBits > 0) {
- // Extract the current bit of value and
- // insert it into the current byte
- m_bitString |= (value & 1) << m_bitPos;
- ++m_bitPos;
- value = value >> 1;
- --numBits;
-
- if (m_bitPos > 7) {
- // We've reached the end of this byte
- writeUInt8(m_bitString);
- m_bitString = 0x00;
- m_bitPos = 0;
- }
- }
-}
-
-
-void BinaryOutput::endBits() {
- debugAssertM(m_beginEndBits == 1, "Not in beginBits...endBits");
- if (m_bitPos > 0) {
- writeUInt8(m_bitString);
- }
- m_bitString = 0;
- m_bitPos = 0;
- m_beginEndBits = 0;
-}
-
-}
diff --git a/externals/g3dlite/Box.cpp b/externals/g3dlite/Box.cpp
deleted file mode 100644
index f7c112ae3a5..00000000000
--- a/externals/g3dlite/Box.cpp
+++ /dev/null
@@ -1,393 +0,0 @@
-/**
- @file Box.cpp
- Box class
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2001-06-02
- @edited 2006-02-05
-*/
-
-#include "G3D/Box.h"
-#include "G3D/debug.h"
-#include "G3D/Plane.h"
-#include "G3D/AABox.h"
-#include "G3D/CoordinateFrame.h"
-
-namespace G3D {
-
-/**
- Sets a field on four vertices. Used by the constructor.
- */
-#define setMany(i0, i1, i2, i3, field, extreme) \
- _corner[i0].field = _corner[i1].field = \
- _corner[i2].field = _corner[i3].field = \
- (extreme).field
-
-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) {
-
- init(min.min(max), min.max(max));
-
-}
-
-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);
-
- setMany(1, 2, 5, 6, x, max);
- setMany(0, 3, 4, 7, x, min);
-
- setMany(3, 2, 6, 7, y, max);
- setMany(0, 1, 5, 4, y, min);
-
- _extent = max - min;
-
- _axis[0] = Vector3::unitX();
- _axis[1] = Vector3::unitY();
- _axis[2] = Vector3::unitZ();
-
- 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) * 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::area() const {
- return _area;
-}
-
-
-void Box::getLocalFrame(CoordinateFrame& frame) const {
-
- frame.rotation = Matrix3(
- _axis[0][0], _axis[1][0], _axis[2][0],
- _axis[0][1], _axis[1][1], _axis[2][1],
- _axis[0][2], _axis[1][2], _axis[2][2]);
-
- 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:
- v0 = _corner[0]; v1 = _corner[1]; v2 = _corner[2]; v3 = _corner[3];
- break;
-
- case 1:
- v0 = _corner[1]; v1 = _corner[5]; v2 = _corner[6]; v3 = _corner[2];
- break;
-
- case 2:
- v0 = _corner[7]; v1 = _corner[6]; v2 = _corner[5]; v3 = _corner[4];
- break;
-
- case 3:
- v0 = _corner[2]; v1 = _corner[6]; v2 = _corner[7]; v3 = _corner[3];
- break;
-
- case 4:
- v0 = _corner[3]; v1 = _corner[7]; v2 = _corner[4]; v3 = _corner[0];
- break;
-
- case 5:
- v0 = _corner[1]; v1 = _corner[0]; v2 = _corner[4]; v3 = _corner[5];
- break;
-
- default:
- debugAssert((f >= 0) && (f < 6));
- }
-}
-
-
-
-int Box::dummy = 0;
-
-bool Box::culledBy(
- const Array<Plane>& plane,
- int& cullingPlane,
- const uint32 _inMask,
- uint32& childMask) const {
-
- uint32 inMask = _inMask;
- 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 < plane.size(); ++p) {
-
- // Only test planes that are not masked
- if ((inMask & 1) != 0) {
-
- Vector3 corner;
-
- int numContained = 0;
- int v = 0;
-
- // 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(_corner[v])) {
- ++numContained;
- }
- }
-
- 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;
-
- } 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;
- }
-
- // None of the planes could cull this box
- cullingPlane = -1;
- return false;
-}
-
-
-bool Box::culledBy(
- const Array<Plane>& plane,
- int& cullingPlane,
- const uint32 _inMask) const {
-
- 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 < plane.size(); ++p) {
-
- // 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
- // is in the positive half space.
- for (v = 0; (v < 8) && culled; ++v) {
- culled = ! plane[p].halfSpaceContains(corner(v));
- }
-
- if (culled) {
- // Plane p culled the box
- cullingPlane = p;
-
- return true;
- }
- }
-
- // Move on to the next bit.
- inMask = inMask >> 1;
- }
-
- // None of the planes could cull this box
- cullingPlane = -1;
- return false;
-}
-
-
-bool Box::contains(
- const Vector3& point) const {
-
- // Form axes from three edges, transform the point into that
- // space, and perform 3 interval tests
-
- Vector3 u = _corner[4] - _corner[0];
- Vector3 v = _corner[3] - _corner[0];
- Vector3 w = _corner[1] - _corner[0];
-
- Matrix3 M = Matrix3(u.x, v.x, w.x,
- u.y, v.y, w.y,
- u.z, v.z, w.z);
-
- // M^-1 * (point - _corner[0]) = point in unit cube's object space
- // compute the inverse of M
- Vector3 osPoint = M.inverse() * (point - _corner[0]);
-
- return
- (osPoint.x >= 0) &&
- (osPoint.y >= 0) &&
- (osPoint.z >= 0) &&
- (osPoint.x <= 1) &&
- (osPoint.y <= 1) &&
- (osPoint.z <= 1);
-}
-
-#undef setMany
-
-
-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)uniformRandom(0, aXY + aYZ + aZX);
-
- // Choose evenly between positive and negative face planes
- 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)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)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)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)uniformRandom(-0.5, 0.5) * _extent[a];
- }
-
- return sum;
-}
-
-Box Box::inf() {
- return Box(-Vector3::inf(), Vector3::inf());
-}
-
-void Box::getBounds(class AABox& aabb) const {
-
- Vector3 lo = _corner[0];
- Vector3 hi = lo;
-
- for (int v = 1; v < 8; ++v) {
- const Vector3& C = _corner[v];
- lo = lo.min(C);
- hi = hi.max(C);
- }
-
- aabb = AABox(lo, hi);
-}
-
-
-} // namespace
diff --git a/externals/g3dlite/CMakeLists.txt b/externals/g3dlite/CMakeLists.txt
deleted file mode 100644
index da5c89ec143..00000000000
--- a/externals/g3dlite/CMakeLists.txt
+++ /dev/null
@@ -1,37 +0,0 @@
-# Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
-#
-# This file is free software; as a special exception the author gives
-# unlimited permission to copy and/or distribute it, with or without
-# modifications, as long as this notice is preserved.
-#
-# This program is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
-# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-
-file(GLOB sources *.cpp)
-
-set(g3dlib_STAT_SRCS
- ${sources}
-)
-if(WIN32)
- include_directories(
- ${CMAKE_CURRENT_SOURCE_DIR}
- ${CMAKE_SOURCE_DIR}/externals/zlib
- )
-else()
- include_directories(
- ${CMAKE_CURRENT_SOURCE_DIR}
- )
-endif()
-
-add_library(g3dlib STATIC ${g3dlib_STAT_SRCS})
-
-if(WIN32)
- target_link_libraries(g3dlib
- zlib
- )
-else()
- target_link_libraries(g3dlib
- ${ZLIB_LIBRARIES}
- )
-endif()
diff --git a/externals/g3dlite/Capsule.cpp b/externals/g3dlite/Capsule.cpp
deleted file mode 100644
index 2ad3891c960..00000000000
--- a/externals/g3dlite/Capsule.cpp
+++ /dev/null
@@ -1,179 +0,0 @@
-/**
- @file Capsule.cpp
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2003-02-07
- @edited 2005-08-18
-
- Copyright 2000-2009, Morgan McGuire.
- All rights reserved.
- */
-
-#include "G3D/Capsule.h"
-#include "G3D/BinaryInput.h"
-#include "G3D/BinaryOutput.h"
-#include "G3D/LineSegment.h"
-#include "G3D/Sphere.h"
-#include "G3D/CoordinateFrame.h"
-#include "G3D/Line.h"
-#include "G3D/AABox.h"
-
-namespace G3D {
-
-Capsule::Capsule(class BinaryInput& b) {
- deserialize(b);
-}
-
-
-Capsule::Capsule() {
-}
-
-
-Capsule::Capsule(const Vector3& _p1, const Vector3& _p2, float _r)
- : p1(_p1), p2(_p2), _radius(_r) {
-}
-
-
-void Capsule::serialize(class BinaryOutput& b) const {
- p1.serialize(b);
- p2.serialize(b);
- b.writeFloat64(_radius);
-}
-
-
-void Capsule::deserialize(class BinaryInput& b) {
- p1.deserialize(b);
- p2.deserialize(b);
- _radius = b.readFloat64();
-}
-
-
-Line Capsule::axis() const {
- return Line::fromTwoPoints(p1, p2);
-}
-
-
-float Capsule::volume() const {
- return
- // Sphere volume
- pow(_radius, 3) * pi() * 4 / 3 +
-
- // Cylinder volume
- pow(_radius, 2) * (p1 - p2).magnitude();
-}
-
-
-float Capsule::area() const {
-
- return
- // Sphere area
- pow(_radius, 2) * 4 * pi() +
-
- // Cylinder area
- twoPi() * _radius * (p1 - p2).magnitude();
-}
-
-
-void Capsule::getBounds(AABox& out) const {
- Vector3 min = p1.min(p2) - (Vector3(1, 1, 1) * _radius);
- Vector3 max = p1.max(p2) + (Vector3(1, 1, 1) * _radius);
-
- out = AABox(min, max);
-}
-
-
-bool Capsule::contains(const Vector3& p) const {
- return LineSegment::fromTwoPoints(p1, p2).distanceSquared(p) <= square(radius());
-}
-
-
-void Capsule::getRandomSurfacePoint(Vector3& p, Vector3& N) const {
- float h = height();
- float r = radius();
-
- // Create a random point on a standard capsule and then rotate to the global frame.
-
- // Relative areas
- float capRelArea = sqrt(r) / 2.0f;
- float sideRelArea = r * h;
-
- float r1 = uniformRandom(0, capRelArea * 2 + sideRelArea);
-
- if (r1 < capRelArea * 2) {
-
- // Select a point uniformly at random on a sphere
- N = Sphere(Vector3::zero(), 1).randomSurfacePoint();
- p = N * r;
- p.y += sign(p.y) * h / 2.0f;
- } else {
- // Side
- float a = uniformRandom(0, (float)twoPi());
- N.x = cos(a);
- N.y = 0;
- N.z = sin(a);
- p.x = N.x * r;
- p.z = N.y * r;
- p.y = uniformRandom(-h / 2.0f, h / 2.0f);
- }
-
- // Transform to world space
- CoordinateFrame cframe;
- getReferenceFrame(cframe);
-
- p = cframe.pointToWorldSpace(p);
- N = cframe.normalToWorldSpace(N);
-}
-
-
-void Capsule::getReferenceFrame(CoordinateFrame& cframe) const {
- cframe.translation = center();
-
- Vector3 Y = (p1 - p2).direction();
- Vector3 X = (abs(Y.dot(Vector3::unitX())) > 0.9) ? Vector3::unitY() : Vector3::unitX();
- Vector3 Z = X.cross(Y).direction();
- X = Y.cross(Z);
- cframe.rotation.setColumn(0, X);
- cframe.rotation.setColumn(1, Y);
- cframe.rotation.setColumn(2, Z);
-}
-
-
-Vector3 Capsule::randomInteriorPoint() const {
- float h = height();
- float r = radius();
-
- // Create a random point in a standard capsule and then rotate to the global frame.
-
- Vector3 p;
-
- float hemiVolume = pi() * (r*r*r) * 4 / 6.0;
- float cylVolume = pi() * square(r) * h;
-
- float r1 = uniformRandom(0, 2.0 * hemiVolume + cylVolume);
-
- if (r1 < 2.0 * hemiVolume) {
-
- p = Sphere(Vector3::zero(), r).randomInteriorPoint();
-
- p.y += sign(p.y) * h / 2.0f;
-
- } else {
-
- // Select a point uniformly at random on a disk
- float a = uniformRandom(0, (float)twoPi());
- float r2 = sqrt(uniformRandom(0, 1)) * r;
-
- p = Vector3(cos(a) * r2,
- uniformRandom(-h / 2.0f, h / 2.0f),
- sin(a) * r2);
- }
-
- // Transform to world space
- CoordinateFrame cframe;
- getReferenceFrame(cframe);
-
- return cframe.pointToWorldSpace(p);
-}
-
-} // namespace
diff --git a/externals/g3dlite/CollisionDetection.cpp b/externals/g3dlite/CollisionDetection.cpp
deleted file mode 100644
index 77eef0a5500..00000000000
--- a/externals/g3dlite/CollisionDetection.cpp
+++ /dev/null
@@ -1,2455 +0,0 @@
-/**
- @file CollisionDetection.cpp
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @cite Bounce direction based on Paul Nettle's ftp://ftp.3dmaileffects.com/pub/FluidStudios/CollisionDetection/Fluid_Studios_Generic_Collision_Detection_for_Games_Using_Ellipsoids.pdf and comments by Max McGuire. Ray-sphere code by Eric Haines.
-
- @created 2001-11-24
- @edited 2008-12-29
- */
-
-#include "G3D/CoordinateFrame.h"
-#include "G3D/platform.h"
-#include "G3D/CollisionDetection.h"
-#include "G3D/debugAssert.h"
-#include "G3D/vectorMath.h"
-#include "G3D/Capsule.h"
-#include "G3D/Plane.h"
-#include "G3D/Line.h"
-#include "G3D/LineSegment.h"
-#include "G3D/Sphere.h"
-#include "G3D/Box.h"
-#include "G3D/Triangle.h"
-#include "G3D/Vector3.h"
-#include "G3D/AABox.h"
-
-#ifdef _MSC_VER
-// Turn on fast floating-point optimizations
-#pragma float_control( push )
-#pragma fp_contract( on )
-#pragma fenv_access( off )
-#pragma float_control( except, off )
-#pragma float_control( precise, off )
-#endif
-
-
-namespace G3D {
-
-bool CollisionDetection::ignoreBool;
-Vector3 CollisionDetection::ignore;
-Array<Vector3> CollisionDetection::ignoreArray;
-
-
-
-Vector3 CollisionDetection::separatingAxisForSolidBoxSolidBox(
- const int separatingAxisIndex,
- const Box & box1,
- const Box & box2) {
- debugAssert(separatingAxisIndex >= 0);
- debugAssert(separatingAxisIndex < 15);
- Vector3 axis;
- if (separatingAxisIndex < 3) {
- axis = box1.axis(separatingAxisIndex);
- } else if (separatingAxisIndex < 6) {
- axis = box2.axis(separatingAxisIndex - 3);
- } else {
- int box1Index = (separatingAxisIndex - 6) / 3;
- int box2Index = (separatingAxisIndex - 6) % 3;
- axis = cross(box1.axis(box1Index), box2.axis(box2Index));
- }
- return axis;
-}
-
-#ifdef _MSC_VER
-# pragma warning (push)
-# pragma warning (disable : 4244)
-#endif
-
-float CollisionDetection::projectedDistanceForSolidBoxSolidBox(
- const int separatingAxisIndex,
- const Vector3 & a,
- const Vector3 & b,
- const Vector3 & D,
- const double* c,
- const double* ca,
- const double* ad,
- const double* bd)
-{
- (void)D;
-
- float R0 = 0.0f;
- float R1 = 0.0f;
- float R = 0.0f;
- switch (separatingAxisIndex) {
- case 0:
- // A0
- R0 = a[0];
- R1 = b[0] * ca[0] + b[1] * ca[1] + b[2] * ca[2];
- R = fabs(ad[0]);
- break;
- case 1:
- // A1
- R0 = a[1];
- R1 = b[0] * ca[3] + b[1] * ca[4] + b[2] * ca[5];
- R = fabs(ad[1]);
- break;
- case 2:
- // A2
- R0 = a[2];
- R1 = b[0] * ca[6] + b[1] * ca[7] + b[2] * ca[8];
- R = fabs(ad[2]);
- break;
- case 3:
- // B0
- R0 = a[0] * ca[0] + a[1] * ca[3] + a[2] * ca[6];
- R1 = b[0];
- R = fabs(bd[0]);
- break;
- case 4:
- // B1
- R0 = a[0] * ca[1] + a[1] * ca[4] + a[2] * ca[7];
- R1 = b[1];
- R = fabs(bd[1]);
- break;
- case 5:
- // B2
- R0 = a[0] * ca[2] + a[1] * ca[5] + a[2] * ca[8];
- R1 = b[2];
- R = fabs(bd[2]);
- break;
- case 6:
- // A0 x B0
- R0 = a[1] * ca[6] + a[2] * ca[3];
- R1 = b[1] * ca[2] + b[2] * ca[1];
- R = fabs(c[3] * ad[2] - c[6] * ad[1]);
- break;
- case 7:
- // A0 x B1
- R0 = a[1] * ca[7] + a[2] * ca[4];
- R1 = b[0] * ca[2] + b[2] * ca[0];
- R = fabs(c[4] * ad[2] - c[7] * ad[1]);
- break;
- case 8:
- // A0 x B2
- R0 = a[1] * ca[8] + a[2] * ca[5];
- R1 = b[0] * ca[1] + b[1] * ca[0];
- R = fabs(c[5] * ad[2] - c[8] * ad[1]);
- break;
- case 9:
- // A1 x B0
- R0 = a[0] * ca[6] + a[2] * ca[0];
- R1 = b[1] * ca[5] + b[2] * ca[4];
- R = fabs(c[6] * ad[0] - c[0] * ad[2]);
- break;
- case 10:
- // A1 x B1
- R0 = a[0] * ca[7] + a[2] * ca[1];
- R1 = b[0] * ca[5] + b[2] * ca[3];
- R = fabs(c[7] * ad[0] - c[1] * ad[2]);
- break;
- case 11:
- // A1 x B2
- R0 = a[0] * ca[8] + a[2] * ca[2];
- R1 = b[0] * ca[4] + b[1] * ca[3];
- R = fabs(c[8] * ad[0] - c[2] * ad[2]);
- break;
- case 12:
- // A2 x B0
- R0 = a[0] * ca[3] + a[1] * ca[0];
- R1 = b[1] * ca[8] + b[2] * ca[7];
- R = fabs(c[0] * ad[1] - c[3] * ad[0]);
- break;
- case 13:
- // A2 x B1
- R0 = a[0] * ca[4] + a[1] * ca[1];
- R1 = b[0] * ca[8] + b[2] * ca[6];
- R = fabs(c[1] * ad[1] - c[4] * ad[0]);
- break;
- case 14:
- // A2 x B2
- R0 = a[0] * ca[5] + a[1] * ca[2];
- R1 = b[0] * ca[7] + b[1] * ca[6];
- R = fabs(c[2] * ad[1] - c[5] * ad[0]);
- break;
- default:
- debugAssertM(false, "fell through switch statement");
- }
-
- return (R - (R0 + R1));
-}
-
-
-bool CollisionDetection::parallelAxisForSolidBoxSolidBox(
- const double* ca,
- const double epsilon,
- int & axis1,
- int & axis2) {
- const double parallelDot = 1.0 - epsilon;
- for (int i = 0; i < 9; i++) {
- if (ca[i] >= parallelDot) {
- axis1 = i / 3;
- axis2 = i % 3;
- return true;
- }
- }
- return false;
-}
-
-
-
-
-void CollisionDetection::fillSolidBoxSolidBoxInfo(
- const Box & box1,
- const Box & box2,
- Vector3 & a,
- Vector3 & b,
- Vector3 & D,
- double* c,
- double* ca,
- double* ad,
- double* bd) {
- // length between center and each side of box1 and box2
- a = box1.extent() * 0.5;
- b = box2.extent() * 0.5;
-
- // difference between centers of box1 and box2
- D = box2.center() - box1.center();
-
- // store the value of all possible dot products between the
- // axes of box1 and box2, c_{row, col} in the Eberly paper
- // corresponds to c[row * 3 + col] for this 9 element array.
- //
- // c[] holds signed values, ca[] hold absolute values
- for (int i = 0; i < 9; i++) {
- c[i] = dot(box1.axis(i / 3), box2.axis(i % 3));
- ca[i] = fabs(c[i]);
- }
-
- // store all possible dot products between the axes of box1 and D,
- // as well as the axes of box2 and D
- for (int i = 0; i < 3; i++) {
- ad[i] = dot(box1.axis(i), D);
- bd[i] = dot(box2.axis(i), D);
- }
-}
-
-
-
-bool CollisionDetection::conservativeBoxBoxTest(
- const Vector3 & a, const Vector3 & b, const Vector3 & D) {
- // do a quick bounding sphere test because it is relatively
- // cheap, (three dot products, two sqrts, and a few others)
- double boxRadius1 = a.magnitude();
- double boxRadius2 = b.magnitude();
- return (D.squaredMagnitude() < square(boxRadius1 + boxRadius2));
-}
-
-
-
-
-bool CollisionDetection::fixedSolidBoxIntersectsFixedSolidBox(
- const Box& box1,
- const Box& box2,
- const int lastSeparatingAxis) {
- // for explanations of the variable please refer to the
- // paper and fillSolidBoxSolidBoxInfo()
- Vector3 a;
- Vector3 b;
- Vector3 D;
- double c[9];
- double ca[9];
- double ad[3];
- double bd[3];
-
- fillSolidBoxSolidBoxInfo(box1, box2, a, b, D, c, ca, ad, bd);
-
- int dummy1, dummy2;
- bool parallelAxes = parallelAxisForSolidBoxSolidBox(ca, 0.00001,
- dummy1, dummy2);
-
- // check the separating axis from the last time step
- if (lastSeparatingAxis != -1 &&
- (lastSeparatingAxis < 6 || !parallelAxes)) {
- double projectedDistance = projectedDistanceForSolidBoxSolidBox(
- lastSeparatingAxis, a, b, D, c, ca, ad, bd);
-
- // the separating axis from the last time step is still
- // valid, the boxes do not intersect
- if (projectedDistance > 0.0) {
- return false;
- }
- }
-
- // test if the boxes can be separated by a plane normal to
- // any of the three axes of box1, any of the three axes of box2,
- // or any of the 9 possible cross products of axes from box1
- // and box2
- for (int i = 0; i < 15; i++) {
- // do not need to check edge-edge cases if any two of
- // the axes are parallel
- if (parallelAxes && i == 6) {
- return true;
- }
-
- double projectedDistance =
- projectedDistanceForSolidBoxSolidBox(i, a, b, D, c, ca, ad, bd);
-
- // found a separating axis, the boxes do not intersect
- if (projectedDistance > 0.0) {
- return false;
- }
- }
-
- return true;
-}
-
-
-
-void CollisionDetection::closestPointsBetweenLineAndLine(
- const Line & line1,
- const Line & line2,
- Vector3 & closest1,
- Vector3 & closest2) {
- // TODO make accessors for Line that don't make a copy of data
- Vector3 P0 = line1.point();
- Vector3 u = line1.direction();
- Vector3 Q0 = line2.point();
- Vector3 v = line2.direction();
- Vector3 w0 = P0 - Q0;
-
- // a = 1.0, c = 1.0
- double b = dot(u, v);
- double d = dot(u, w0);
- double e = dot(v, w0);
- double D = 1.0 - b * b;
- double sc, tc;
-
- static const double epsilon = 0.00001;
-
- if (D < epsilon) {
- // lines are parallel, choose P0 as one point, find the point
- // on line2 that is closest to P0
- sc = 0.0;
- tc = (b > 1.0) ? (d / b) : (e / 1.0);
- } else {
- // lines are not parallel
- sc = (b * e - 1.0 * d) / D;
- tc = (1.0 * e - b * d) / D;
- }
-
- closest1 = P0 + (sc * u);
- closest2 = Q0 + (tc * v);
-}
-
-
-
-float CollisionDetection::penetrationDepthForFixedBoxFixedBox(
- const Box& box1,
- const Box& box2,
- Array<Vector3>& contactPoints,
- Array<Vector3>& contactNormals,
- const int lastSeparatingAxis) {
-
- contactPoints.resize(0, DONT_SHRINK_UNDERLYING_ARRAY);
- contactNormals.resize(0, DONT_SHRINK_UNDERLYING_ARRAY);
-
- Vector3 a;
- Vector3 b;
- Vector3 D;
- double c[9];
- double ca[9];
- double ad[3];
- double bd[3];
-
- debugAssert(lastSeparatingAxis >= -1);
- debugAssert(lastSeparatingAxis < 15);
-
- fillSolidBoxSolidBoxInfo(box1, box2, a, b, D, c, ca, ad, bd);
-
- int axis1, axis2;
- bool parallelAxes = parallelAxisForSolidBoxSolidBox(ca, 0.00001,
- axis1, axis2);
-
-
- // check the separating axis from the last time step
- if (lastSeparatingAxis != -1 &&
- (lastSeparatingAxis < 6 || !parallelAxes)) {
- float projectedDistance = projectedDistanceForSolidBoxSolidBox(
- lastSeparatingAxis, a, b, D, c, ca, ad, bd);
-
- // the separating axis from the last time step is still
- // valid, the boxes do not intersect
- if (projectedDistance > 0.0) {
- return -projectedDistance;
- }
- }
-
- // test if the boxes can be separated by a plane normal to
- // any of the three axes of box1, any of the three axes of box2,
- // (test 9 possible cross products later)
- float penetration = -finf();
- int penetrationAxisIndex = -1;
-
- for (int i = 0; i < 6; i++) {
- float projectedDistance =
- projectedDistanceForSolidBoxSolidBox(i, a, b, D, c, ca, ad, bd);
-
- // found a separating axis, the boxes do not intersect
- if (projectedDistance > 0.0) {
- return -projectedDistance;
- }
-
- // keep track of the axis that is least violated
- if (projectedDistance > penetration) {
- penetration = projectedDistance;
- penetrationAxisIndex = i;
- }
- }
-
-
- // for each edge-edge case we have to adjust the magnitude of
- // penetration since we did not include the dot(L, L) denominator
- // that can be smaller than 1.0 for the edge-edge cases.
- if (!parallelAxes) {
- double edgeDistances[9];
-
- // run through edge-edge cases to see if we can find a separating axis
- for (int i = 6; i < 15; i++) {
- float projectedDistance =
- projectedDistanceForSolidBoxSolidBox(i, a, b, D, c, ca, ad, bd);
-
- // found a separating axis, the boxes do not intersect,
- // correct magnitude and return projected distance
- if (projectedDistance > 0.0) {
- Vector3 L = separatingAxisForSolidBoxSolidBox(i, box1, box2);
- projectedDistance /= dot(L, L);
- return -projectedDistance;
- }
-
- edgeDistances[i - 6] = projectedDistance;
- }
-
- // no separating axis found, the boxes do intersect,
- // correct the magnitudes of the projectedDistance values
- for (int i = 6; i < 15; i++) {
- // find the negative penetration value with the smallest magnitude,
- // the adjustment done for the edge-edge cases only increases
- // magnitude by dividing by a number smaller than 1 and greater than 0
- float projectedDistance = (float)edgeDistances[i - 6];
- if (projectedDistance > penetration) {
- Vector3 L = separatingAxisForSolidBoxSolidBox(i, box1, box2);
- projectedDistance /= dot(L, L);
- if (projectedDistance > penetration) {
- penetration = projectedDistance;
- penetrationAxisIndex = i;
- }
- }
- }
- }
-
- // get final separating axis vector
- Vector3 L = separatingAxisForSolidBoxSolidBox(penetrationAxisIndex,
- box1, box2);
-
- // set L to be the normal that faces away from box1
- if (dot(L, D) < 0) {
- L = -L;
- }
-
- Vector3 contactPoint;
-
- if (penetrationAxisIndex < 6) {
- // vertex to face collision, find deepest colliding vertex
- const Box* vertexBox;
- const Box* faceBox;
- Vector3 faceNormal = L;
-
- // L will be the outward facing normal for the faceBox
- if (penetrationAxisIndex < 3) {
- faceBox = & box1;
- vertexBox = & box2;
- if (dot(L, D) < 0) {
- faceNormal = -L;
- }
- } else {
- faceBox = & box2;
- vertexBox = & box1;
- if (dot(L, D) > 0) {
- faceNormal = -L;
- }
- }
-
- // find the vertex that is farthest away in the direction
- // face normal direction
- int deepestPointIndex = 0;
- float deepestPointDot = dot(faceNormal, vertexBox->corner(0));
- for (int i = 1; i < 8; i++) {
- float dotProduct = dot(faceNormal, vertexBox->corner(i));
- if (dotProduct < deepestPointDot) {
- deepestPointDot = dotProduct;
- deepestPointIndex = i;
- }
- }
-
- // return the point half way between the deepest point and the
- // contacting face
- contactPoint = vertexBox->corner(deepestPointIndex) +
- (-penetration * 0.5 * faceNormal);
- } else {
- // edge-edge case, find the two ege lines
- int edge1 = (penetrationAxisIndex - 6) / 3;
- int edge2 = (penetrationAxisIndex - 6) % 3;
- Vector3 linePoint1 = box1.center();
- Vector3 linePoint2 = box2.center();
- Vector3 lineDir1;
- Vector3 lineDir2;
-
- // find edge line by finding the edge axis, and the
- // other two axes that are closest to the other box
- for (int i = 0; i < 3; i++ ) {
- if (i == edge1) {
- lineDir1 = box1.axis(i);
- } else {
- Vector3 axis = box1.axis(i);
- if (dot(axis, L) < 0) {
- axis = -axis;
- }
- linePoint1 += axis * a[i];
- }
-
- if (i == edge2) {
- lineDir2 = box2.axis(i);
- } else {
- Vector3 axis = box2.axis(i);
- if (dot(axis, L) > 0) {
- axis = -axis;
- }
- linePoint2 += axis * b[i];
- }
- }
-
- // make lines from the two closest edges, and find
- // the points that on each line that are closest to the other
- Line line1 = Line::fromPointAndDirection(linePoint1, lineDir1);
- Line line2 = Line::fromPointAndDirection(linePoint2, lineDir2);
- Vector3 closest1;
- Vector3 closest2;
-
- closestPointsBetweenLineAndLine(line1, line2, closest1, closest2);
-
- // take the average of the two closest edge points for the final
- // contact point
- contactPoint = (closest1 + closest2) * 0.5;
- }
-
- contactPoints.push(contactPoint);
- contactNormals.push(L);
-
- return -penetration;
-
-}
-
-
-
-
-float CollisionDetection::penetrationDepthForFixedSphereFixedBox(
- const Sphere& sphere,
- const Box& box,
- Array<Vector3>& contactPoints,
- Array<Vector3>& contactNormals) {
-
- contactPoints.resize(0, DONT_SHRINK_UNDERLYING_ARRAY);
- contactNormals.resize(0, DONT_SHRINK_UNDERLYING_ARRAY);
-
- // In its local coordinate frame, the box measures
- // 2 * halfExtent[a] along dimesion a.
- Vector3 halfExtent(box.extent(0), box.extent(1), box.extent(2));
- halfExtent *= 0.5f;
-
- CoordinateFrame boxFrame;
- box.getLocalFrame(boxFrame);
-
- // Transform the sphere to the box's coordinate frame.
- Vector3 center = boxFrame.pointToObjectSpace(sphere.center);
-
- // Find the square of the distance from the sphere to the box
-
-
- // Distance along each axis from the closest side of the box
- // to the sphere center. Negative values are *inside* the box.
- Vector3 distOutsideBox;
-
- // Divide space up into the 27 regions corresponding
- // to {+|-|0}X, {+|-|0}Y, {+|-|0}Z and classify the
- // sphere center into one of them.
- Vector3 centerRegion;
-
- // In the edge collision case, the edge is between vertices
- // (constant + variable) and (constant - variable).
- Vector3 constant, variable;
-
- int numNonZero = 0;
-
- // Iterate over axes
- for (int a = 0; a < 3; ++a) {
- // For each (box side), see which direction the sphere
- // is outside the box (positive or negative). Add the
- // square of that distance to the total distance from
- // the box.
-
- float distanceFromLow = -halfExtent[a] - center[a];
- float distanceFromHigh = center[a] - halfExtent[a];
-
- if (fabsf(distanceFromLow) < fabsf(distanceFromHigh)) {
- distOutsideBox[a] = distanceFromLow;
- } else {
- distOutsideBox[a] = distanceFromHigh;
- }
-
- if (distanceFromLow < 0.0) {
- if (distanceFromHigh < 0.0) {
- // Inside the box
- centerRegion[a] = 0.0;
- variable[a] = 1.0;
- } else {
- // Off the high side
- centerRegion[a] = 1.0;
- constant[a] = halfExtent[a];
- ++numNonZero;
- }
- } else if (distanceFromHigh < 0.0) {
- // Off the low side
- centerRegion[a] = -1.0;
- constant[a] = -halfExtent[a];
- ++numNonZero;
- } else {
- debugAssertM(false,
- "distanceFromLow and distanceFromHigh cannot both be positive");
- }
- }
-
- // Squared distance between the outside of the box and the
- // sphere center.
- float d2 = Vector3::zero().max(distOutsideBox).squaredMagnitude();
-
- if (d2 > square(sphere.radius)) {
- // There is no penetration because the distance is greater
- // than the radius of the sphere. This is the common case
- // and we quickly exit.
- return -1;
- }
-
- // We know there is some penetration but need to classify it.
- //
- // Examine the region that contains the center of the sphere. If
- // there is exactly one non-zero axis, the collision is with a
- // plane. If there are exactly two non-zero axes, the collision
- // is with an edge. If all three axes are non-zero, the collision is
- // with a vertex. If there are no non-zero axes, the center is inside
- // the box.
-
- double depth = -1;
- switch (numNonZero) {
- case 3: // Vertex collision
- // The collision point is the vertex at constant, the normal
- // is the vector from there to the sphere center.
- contactNormals.append(boxFrame.normalToWorldSpace(constant - center));
- contactPoints.append(boxFrame.pointToWorldSpace(constant));
- depth = sphere.radius - sqrt(d2);
- break;
-
- case 2: // Edge collision
- {
- // TODO: unwrapping the edge constructor and closest point
- // code will probably make it faster.
-
- // Determine the edge
- Line line = Line::fromPointAndDirection(constant, variable);
-
- // Penetration depth:
- depth = sphere.radius - sqrt(d2);
-
- // The contact point is the closes point to the sphere on the line
- Vector3 X = line.closestPoint(center);
- contactNormals.append(boxFrame.normalToWorldSpace(X - center).direction());
- contactPoints.append(boxFrame.pointToWorldSpace(X));
- }
- break;
-
- case 1: // Plane collision
- {
- // The plane normal is the centerRegion vector,
- // so the sphere normal is the negative. Take
- // it to world space from box-space.
-
- // Center region doesn't need to be normalized because
- // it is known to contain only one non-zero value
- // and that value is +/- 1.
- Vector3 N = boxFrame.normalToWorldSpace(-centerRegion);
- contactNormals.append(N);
-
- // Penetration depth:
- depth = sphere.radius - sqrtf(d2);
-
- // Compute the contact point from the penetration depth
- contactPoints.append(sphere.center + N * (sphere.radius - depth));
- }
- break;
-
- case 0: // Volume collision
-
- // The sphere center is inside the box. This is an easy case
- // to handle. Note that all axes of distOutsideBox must
- // be negative.
-
- // Arbitratily choose the sphere center as a contact point
- contactPoints.append(sphere.center);
-
- // Find the least-negative penetration axis.
- //
- // We could have computed this during the loop over the axes,
- // but since volume collisions are rare (they only occur with
- // large time steps), this case will seldom be executed and
- // should not be optimized at the expense of the others.
- if (distOutsideBox.x > distOutsideBox.y) {
- if (distOutsideBox.x > distOutsideBox.z) {
- // Smallest penetration on x-axis
- // Chose normal based on which side we're closest to.
- // Keep in mind that this is a normal to the sphere,
- // so it is the inverse of the box normal.
- if (center.x > 0) {
- contactNormals.append(boxFrame.normalToWorldSpace(-Vector3::unitX()));
- } else {
- contactNormals.append(boxFrame.normalToWorldSpace(Vector3::unitX()));
- }
- depth = -distOutsideBox.x;
- } else {
- // Smallest penetration on z-axis
- goto ZAXIS;
- }
- } else if (distOutsideBox.y > distOutsideBox.z) {
- // Smallest penetration on y-axis
- // Chose normal based on which side we're closest to.
- // Keep in mind that this is a normal to the sphere,
- // so it is the inverse of the box normal.
- if (center.y > 0) {
- contactNormals.append(boxFrame.normalToWorldSpace(-Vector3::unitY()));
- } else {
- contactNormals.append(boxFrame.normalToWorldSpace(Vector3::unitY()));
- }
- depth = -distOutsideBox.y;
- } else {
- // Smallest on z-axis
-ZAXIS:
- // Chose normal based on which side we're closest to.
- // Keep in mind that this is a normal to the sphere,
- // so it is the inverse of the box normal.
- if (center.z > 0) {
- contactNormals.append(boxFrame.normalToWorldSpace(-Vector3::unitZ()));
- } else {
- contactNormals.append(boxFrame.normalToWorldSpace(Vector3::unitZ()));
- }
- depth = -distOutsideBox.z;
- }
- break;
-
- default:
- debugAssertM(false, "Fell through switch");
- break;
- }
-
- return depth;
-}
-
-
-float CollisionDetection::penetrationDepthForFixedSphereFixedSphere(
- const Sphere& sphereA,
- const Sphere& sphereB,
- Array<Vector3>& contactPoints,
- Array<Vector3>& contactNormals) {
-
- Vector3 axis = sphereB.center - sphereA.center;
- double radius = sphereA.radius + sphereB.radius;
- double mag = axis.magnitude();
- axis /= mag;
- double depth = -(mag - radius);
-
- contactPoints.resize(0, DONT_SHRINK_UNDERLYING_ARRAY);
- contactNormals.resize(0, DONT_SHRINK_UNDERLYING_ARRAY);
-
- if (depth >= 0) {
- contactPoints.append(sphereA.center + axis * (sphereA.radius - depth / 2));
- contactNormals.append(axis);
- }
-
- return depth;
-}
-
-
-float CollisionDetection::penetrationDepthForFixedSphereFixedPlane(
- const Sphere& sphereA,
- const Plane& planeB,
- Array<Vector3>& contactPoints,
- Array<Vector3>& contactNormals) {
-
- Vector3 N;
- double d;
-
- planeB.getEquation(N, d);
-
- double depth = -(sphereA.center.dot(N) + d - sphereA.radius);
-
- contactPoints.resize(0, DONT_SHRINK_UNDERLYING_ARRAY);
- contactNormals.resize(0, DONT_SHRINK_UNDERLYING_ARRAY);
-
- if (depth >= 0) {
- contactPoints.append(N * (depth - sphereA.radius) + sphereA.center);
- contactNormals.append(N);
- }
-
- return depth;
-}
-
-
-float CollisionDetection::penetrationDepthForFixedBoxFixedPlane(
- const Box& box,
- const Plane& plane,
- Array<Vector3>& contactPoints,
- Array<Vector3>& contactNormals) {
-
- Vector3 N;
- double d;
-
- plane.getEquation(N, d);
-
- contactPoints.resize(0, DONT_SHRINK_UNDERLYING_ARRAY);
- contactNormals.resize(0, DONT_SHRINK_UNDERLYING_ARRAY);
-
- float lowest = finf();
- for (int i = 0; i < 8; ++i) {
- const Vector3 vertex = box.corner(i);
-
- float x = vertex.dot(N) + (float)d;
-
- if (x <= 0) {
- // All vertices below the plane should be contact points.
- contactPoints.append(vertex);
- contactNormals.append(-N);
- }
-
- lowest = min(lowest, x);
- }
-
- // Depth should be a positive number
- return -lowest;
-}
-
-
-float CollisionDetection::collisionTimeForMovingPointFixedPlane(
- const Vector3& point,
- const Vector3& velocity,
- const Plane& plane,
- Vector3& location,
- Vector3& outNormal) {
-
- // Solve for the time at which normal.dot(point + velocity) + d == 0.
- double d;
- Vector3 normal;
- plane.getEquation(normal, d);
-
- float vdotN = velocity.dot(normal);
- float pdotN = point.dot(normal);
-
- if (fuzzyEq(pdotN + d, 0)) {
- // The point is *in* the plane.
- location = point;
- outNormal = normal;
- return 0;
- }
-
- if (vdotN >= 0) {
- // no collision will occur
- location = Vector3::inf();
- return finf();
- }
-
- float t = -(pdotN + d) / vdotN;
- if (t < 0) {
- location = Vector3::inf();
- return finf();
- } else {
- location = point + velocity * t;
- outNormal = normal;
- return t;
- }
-}
-
-bool __fastcall CollisionDetection::rayAABox(
- const Ray& ray,
- const Vector3& invDir,
- const AABox& box,
- const Vector3& boxCenter,
- float boundingRadiusSquared,
- Vector3& location,
- bool& inside) {
-
- debugAssertM(fabs(ray.direction().squaredLength() - 1.0f) < 0.01f, format("Length = %f", ray.direction().length()));
- {
- // Pre-emptive partial bounding sphere test
- const Vector3 L(boxCenter - ray.origin());
- float d = L.dot(ray.direction());
-
- float L2 = L.dot(L);
- float D2 = square(d);
- float M2 = L2 - D2;
-
- if (((d < 0) && (L2 > boundingRadiusSquared)) || (M2 > boundingRadiusSquared)) {
- inside = false;
- return false;
- }
- // Passing here does not mean that the ray hits the bounding sphere;
- // we would still have to perform more expensive tests to determine
- // that.
- }
-
- inside = true;
- const Vector3& MinB = box.low();
- const Vector3& MaxB = box.high();
- Vector3 MaxT(-1.0f, -1.0f, -1.0f);
-
- // Find candidate planes.
- for (int i = 0; i < 3; ++i) {
- if (ray.origin()[i] < MinB[i]) {
- location[i] = MinB[i];
- inside = false;
-
- // Calculate T distances to candidate planes
- if (ray.direction()[i] != 0) {
- MaxT[i] = (MinB[i] - ray.origin()[i]) * invDir[i];
- }
- } else if (ray.origin()[i] > MaxB[i]) {
- location[i] = MaxB[i];
- inside = false;
-
- // Calculate T distances to candidate planes
- if (ray.direction()[i] != 0) {
- MaxT[i] = (MaxB[i] - ray.origin()[i]) * invDir[i];
- }
- }
- }
-
- if (inside) {
- // Ray origin inside bounding box
- location = ray.origin();
- return true;
- }
-
- // Get largest of the maxT's for final choice of intersection
- int WhichPlane = 0;
- if (MaxT[1] > MaxT[WhichPlane]) {
- WhichPlane = 1;
- }
-
- if (MaxT[2] > MaxT[WhichPlane]) {
- WhichPlane = 2;
- }
-
- // Check final candidate actually inside box
- if (MaxT[WhichPlane] < 0.0f) {
- // Miss the box
- return false;
- }
-
- for (int i = 0; i < 3; ++i) {
- if (i != WhichPlane) {
- location[i] = ray.origin()[i] + MaxT[WhichPlane] * ray.direction()[i];
- if ((location[i] < MinB[i]) ||
- (location[i] > MaxB[i])) {
- // On this plane we're outside the box extents, so
- // we miss the box
- return false;
- }
- }
- }
-
- return true;
-}
-
-float CollisionDetection::collisionTimeForMovingPointFixedSphere(
- const Vector3& point,
- const Vector3& velocity,
- const Sphere& sphere,
- Vector3& location,
- Vector3& outNormal,
- bool solid) {
-
- if (solid && sphere.contains(point)) {
- location = point;
- outNormal = (point - sphere.center).direction();
- return 0.0f;
- }
-
- float speed = velocity.magnitude();
- const Vector3& direction = velocity / speed;
-
- // length of the axis between the start and the sphere
- const Vector3& L = sphere.center - point;
- float d = L.dot(direction);
-
- float L2 = L.dot(L);
- float R2 = square(sphere.radius);
- float D2 = square(d);
-
- if ((d < 0.0f) && (L2 > R2)) {
- location = Vector3::inf();
- return finf();
- }
-
- const float M2 = L2 - D2;
-
- if (M2 > R2) {
- location = Vector3::inf();
- return finf();
- }
-
- float q = sqrt(R2 - M2);
- float time;
-
- if (L2 > R2) {
- time = d - q;
- } else {
- time = d + q;
- }
-
- time /= speed;
-
- location = point + velocity * time;
- outNormal = (location - sphere.center).direction();
-
- return time;
-}
-
-
-float CollisionDetection::collisionTimeForMovingSphereFixedSphere(
- const Sphere& movingSphere,
- const Vector3& velocity,
- const Sphere& fixedSphere,
- Vector3& location,
- Vector3& outNormal) {
-
- const Vector3& sep = (fixedSphere.center - movingSphere.center);
- float sepLen = sep.squaredLength();
- if (sepLen < square(movingSphere.radius + fixedSphere.radius)) {
- // Interpenetrating
- outNormal = sep.directionOrZero();
- location = fixedSphere.center - outNormal * fixedSphere.radius;
- return 0;
- }
-
- float time = collisionTimeForMovingPointFixedSphere
- (movingSphere.center, velocity,
- Sphere(fixedSphere.center, fixedSphere.radius + movingSphere.radius),
- location, outNormal);
-
- if (time < finf()) {
- // Location is now the center of the moving sphere at the collision time.
- // Adjust for the size of the moving sphere. Two spheres always collide
- // along a line between their centers.
- location += (location - fixedSphere.center) * movingSphere.radius / fixedSphere.radius;
- }
-
- return time;
-}
-
-
-/*
-float CollisionDetection::collisionTimeForMovingPointFixedTriangle(
- const Vector3& point,
- const Vector3& velocity,
- const Triangle& triangle,
- Vector3& outLocation,
- Vector3& outNormal) {
-
- double time = collisionTimeForMovingPointFixedPlane(point, velocity, triangle.plane(), outLocation, outNormal);
-
- if (time == finf()) {
- // No collision with the plane of the triangle.
- return finf();
- }
-
- if (isPointInsideTriangle(triangle.vertex(0), triangle.vertex(1), triangle.vertex(2), triangle.normal(), outLocation, triangle.primaryAxis())) {
- // Collision occured inside the triangle
- return time;
- } else {
- // Missed the triangle
- outLocation = Vector3::inf();
- return finf();
- }
-}*/
-
-/*
-float CollisionDetection::collisionTimeForMovingPointFixedTriangle(
- const Vector3& orig,
- const Vector3& dir,
- const Vector3& vert0,
- const Vector3& vert1,
- const Vector3& vert2) {
-
- // Barycenteric coords
- double u, v;
- #define EPSILON 0.000001
- #define CROSS(dest,v1,v2) \
- dest[0]=v1[1]*v2[2]-v1[2]*v2[1]; \
- dest[1]=v1[2]*v2[0]-v1[0]*v2[2]; \
- dest[2]=v1[0]*v2[1]-v1[1]*v2[0];
-
- #define DOT(v1,v2) (v1[0]*v2[0]+v1[1]*v2[1]+v1[2]*v2[2])
-
- #define SUB(dest,v1,v2) \
- dest[0]=v1[0]-v2[0]; \
- dest[1]=v1[1]-v2[1]; \
- dest[2]=v1[2]-v2[2];
-
- double edge1[3], edge2[3], tvec[3], pvec[3], qvec[3];
-
- // find vectors for two edges sharing vert0
- SUB(edge1, vert1, vert0);
- SUB(edge2, vert2, vert0);
-
- // begin calculating determinant - also used to calculate U parameter
- CROSS(pvec, dir, edge2);
-
- // if determinant is near zero, ray lies in plane of triangle
- const double det = DOT(edge1, pvec);
-
- if (det < EPSILON) {
- return finf();
- }
-
- // calculate distance from vert0 to ray origin
- SUB(tvec, orig, vert0);
-
- // calculate U parameter and test bounds
- u = DOT(tvec, pvec);
- if ((u < 0.0) || (u > det)) {
- // Hit the plane outside the triangle
- return finf();
- }
-
- // prepare to test V parameter
- CROSS(qvec, tvec, edge1);
-
- // calculate V parameter and test bounds
- v = DOT(dir, qvec);
- if ((v < 0.0) || (u + v > det)) {
- // Hit the plane outside the triangle
- return finf();
- }
-
- // calculate t, scale parameters, ray intersects triangle
- // If we want u,v, we can compute this
- // double t = DOT(edge2, qvec);
- //const double inv_det = 1.0 / det;
- //t *= inv_det;
- //u *= inv_det;
- //v *= inv_det;
- // return t;
-
- // Case where we don't need correct (u, v):
-
- const double t = DOT(edge2, qvec);
-
- if (t >= 0) {
- // Note that det must be positive
- return t / det;
- } else {
- // We had to travel backwards in time to intersect
- return finf();
- }
-
- #undef EPSILON
- #undef CROSS
- #undef DOT
- #undef SUB
-}
-*/
-
-float CollisionDetection::collisionTimeForMovingPointFixedBox(
- const Vector3& point,
- const Vector3& velocity,
- const Box& box,
- Vector3& location,
- Vector3& outNormal) {
-
- double bestTime;
-
- Vector3 normal;
- Vector3 v[4];
-
- // Prime the loop
- int f = 0;
- box.getFaceCorners(f, v[0], v[1], v[2], v[3]);
- bestTime = collisionTimeForMovingPointFixedRectangle(point, velocity, v[0], v[1], v[2], v[3], location, normal);
- outNormal = normal;
-
- // Check other faces
- for (f = 1; f < 6; ++f) {
- Vector3 pos;
- box.getFaceCorners(f, v[0], v[1], v[2], v[3]);
- float time = collisionTimeForMovingPointFixedRectangle(point, velocity, v[0], v[1], v[2], v[3], pos, normal);
- if (time < bestTime) {
- bestTime = time;
- outNormal = normal;
- location = pos;
- }
- }
-
- return bestTime;
-}
-
-
-float CollisionDetection::collisionTimeForMovingPointFixedAABox(
- const Vector3& origin,
- const Vector3& dir,
- const AABox& box,
- Vector3& location,
- bool& Inside,
- Vector3& normal) {
-
- if (collisionLocationForMovingPointFixedAABox(origin, dir, box, location, Inside, normal)) {
- return (location - origin).magnitude();
- } else {
- return (float)finf();
- }
-}
-
-
-bool CollisionDetection::collisionLocationForMovingPointFixedAABox(
- const Vector3& origin,
- const Vector3& dir,
- const AABox& box,
- Vector3& location,
- bool& Inside,
- Vector3& normal) {
-
- // Integer representation of a floating-point value.
- #define IR(x) ((uint32&)x)
-
- Inside = true;
- const Vector3& MinB = box.low();
- const Vector3& MaxB = box.high();
- Vector3 MaxT(-1.0f, -1.0f, -1.0f);
-
- // Find candidate planes.
- for (int i = 0; i < 3; ++i) {
- if (origin[i] < MinB[i]) {
- location[i] = MinB[i];
- Inside = false;
-
- // Calculate T distances to candidate planes
- if (IR(dir[i])) {
- MaxT[i] = (MinB[i] - origin[i]) / dir[i];
- }
- } else if (origin[i] > MaxB[i]) {
- location[i] = MaxB[i];
- Inside = false;
-
- // Calculate T distances to candidate planes
- if (IR(dir[i])) {
- MaxT[i] = (MaxB[i] - origin[i]) / dir[i];
- }
- }
- }
-
- if (Inside) {
- // Ray origin inside bounding box
- location = origin;
- return false;
- }
-
- // Get largest of the maxT's for final choice of intersection
- int WhichPlane = 0;
- if (MaxT[1] > MaxT[WhichPlane]) {
- WhichPlane = 1;
- }
-
- if (MaxT[2] > MaxT[WhichPlane]) {
- WhichPlane = 2;
- }
-
- // Check final candidate actually inside box
- if (IR(MaxT[WhichPlane]) & 0x80000000) {
- // Miss the box
- return false;
- }
-
- for (int i = 0; i < 3; ++i) {
- if (i != WhichPlane) {
- location[i] = origin[i] + MaxT[WhichPlane] * dir[i];
- if ((location[i] < MinB[i]) ||
- (location[i] > MaxB[i])) {
- // On this plane we're outside the box extents, so
- // we miss the box
- return false;
- }
- }
- }
-
- // Choose the normal to be the plane normal facing into the ray
- normal = Vector3::zero();
- normal[WhichPlane] = (dir[WhichPlane] > 0) ? -1.0 : 1.0;
-
- return true;
-
- #undef IR
-}
-
-
-
-float CollisionDetection::collisionTimeForMovingPointFixedRectangle(
- const Vector3& point,
- const Vector3& velocity,
- const Vector3& v0,
- const Vector3& v1,
- const Vector3& v2,
- const Vector3& v3,
- Vector3& location,
- Vector3& outNormal) {
-
- Plane plane = Plane(v0, v1, v2);
-
- float time = collisionTimeForMovingPointFixedPlane(point, velocity, plane, location, outNormal);
-
- if (time == finf()) {
- // No collision is ever going to happen
- return time;
- }
-
- if (isPointInsideRectangle(v0, v1, v2, v3, plane.normal(), location)) {
- // The intersection point is inside the rectangle; that is the location where
- // the point hits the rectangle.
- return time;
- } else {
- return finf();
- }
-}
-
-/** Used by findRayCapsuleIntersection.
- @cite From magic software http://www.magic-software.com/Source/Intersection3D/MgcIntr3DLinCap.cpp */
-static int findRayCapsuleIntersectionAux(
- const Vector3& rkOrigin,
- const Vector3& rkDirection,
- const Capsule& rkCapsule,
- double afT[2]) {
-
- Vector3 capsuleDirection = rkCapsule.point(1) - rkCapsule.point(0);
-
- // set up quadratic Q(t) = a*t^2 + 2*b*t + c
- Vector3 kU, kV, kW = capsuleDirection;
- float fWLength = kW.unitize();
- Vector3::generateOrthonormalBasis(kU, kV, kW);
- Vector3 kD(kU.dot(rkDirection), kV.dot(rkDirection), kW.dot(rkDirection));
- float fDLength = kD.unitize();
-
- float fEpsilon = 1e-6f;
-
- float fInvDLength = 1.0f/fDLength;
- Vector3 kDiff = rkOrigin - rkCapsule.point(0);
- Vector3 kP(kU.dot(kDiff),kV.dot(kDiff),kW.dot(kDiff));
- float fRadiusSqr = square(rkCapsule.radius());
-
- float fInv, fA, fB, fC, fDiscr, fRoot, fT, fTmp;
-
- // Is the velocity parallel to the capsule direction? (or zero)
- if ((abs(kD.z) >= 1.0f - fEpsilon) || (fDLength < fEpsilon)) {
-
- float fAxisDir = rkDirection.dot(capsuleDirection);
-
- fDiscr = fRadiusSqr - kP.x*kP.x - kP.y*kP.y;
- if ((fAxisDir < 0) && (fDiscr >= 0.0f)) {
- // Velocity anti-parallel to the capsule direction
- fRoot = sqrt(fDiscr);
- afT[0] = (kP.z + fRoot)*fInvDLength;
- afT[1] = -(fWLength - kP.z + fRoot)*fInvDLength;
- return 2;
- } else if ((fAxisDir > 0) && (fDiscr >= 0.0f)) {
- // Velocity parallel to the capsule direction
- fRoot = sqrt(fDiscr);
- afT[0] = -(kP.z + fRoot)*fInvDLength;
- afT[1] = (fWLength - kP.z + fRoot)*fInvDLength;
- return 2;
- } else {
- // sphere heading wrong direction, or no velocity at all
- return 0;
- }
- }
-
- // test intersection with infinite cylinder
- fA = kD.x*kD.x + kD.y*kD.y;
- fB = kP.x*kD.x + kP.y*kD.y;
- fC = kP.x*kP.x + kP.y*kP.y - fRadiusSqr;
- fDiscr = fB*fB - fA*fC;
- if (fDiscr < 0.0f) {
- // line does not intersect infinite cylinder
- return 0;
- }
-
- int iQuantity = 0;
-
- if (fDiscr > 0.0f) {
- // line intersects infinite cylinder in two places
- fRoot = sqrt(fDiscr);
- fInv = 1.0f/fA;
- fT = (-fB - fRoot)*fInv;
- fTmp = kP.z + fT*kD.z;
- if ((0.0f <= fTmp) && (fTmp <= fWLength)) {
- afT[iQuantity] = fT * fInvDLength;
- iQuantity++;
- }
-
- fT = (-fB + fRoot)*fInv;
- fTmp = kP.z + fT*kD.z;
-
- if ((0.0f <= fTmp) && (fTmp <= fWLength)) {
- afT[iQuantity++] = fT*fInvDLength;
- }
-
- if (iQuantity == 2) {
- // line intersects capsule wall in two places
- return 2;
- }
- } else {
- // line is tangent to infinite cylinder
- fT = -fB/fA;
- fTmp = kP.z + fT*kD.z;
- if ((0.0f <= fTmp) && (fTmp <= fWLength)) {
- afT[0] = fT*fInvDLength;
- return 1;
- }
- }
-
- // test intersection with bottom hemisphere
- // fA = 1
- fB += kP.z*kD.z;
- fC += kP.z*kP.z;
- fDiscr = fB*fB - fC;
- if (fDiscr > 0.0f) {
- fRoot = sqrt(fDiscr);
- fT = -fB - fRoot;
- fTmp = kP.z + fT*kD.z;
- if (fTmp <= 0.0f) {
- afT[iQuantity++] = fT*fInvDLength;
- if (iQuantity == 2) {
- return 2;
- }
- }
-
- fT = -fB + fRoot;
- fTmp = kP.z + fT*kD.z;
- if (fTmp <= 0.0f) {
- afT[iQuantity++] = fT*fInvDLength;
- if (iQuantity == 2) {
- return 2;
- }
- }
- } else if (fDiscr == 0.0f) {
- fT = -fB;
- fTmp = kP.z + fT*kD.z;
- if (fTmp <= 0.0f) {
- afT[iQuantity++] = fT*fInvDLength;
- if (iQuantity == 2) {
- return 2;
- }
- }
- }
-
- // test intersection with top hemisphere
- // fA = 1
- fB -= kD.z*fWLength;
- fC += fWLength*(fWLength - 2.0f*kP.z);
-
- fDiscr = fB*fB - fC;
- if (fDiscr > 0.0f) {
- fRoot = sqrt(fDiscr);
- fT = -fB - fRoot;
- fTmp = kP.z + fT*kD.z;
- if (fTmp >= fWLength) {
- afT[iQuantity++] = fT*fInvDLength;
- if (iQuantity == 2) {
- return 2;
- }
- }
-
- fT = -fB + fRoot;
- fTmp = kP.z + fT*kD.z;
- if (fTmp >= fWLength) {
- afT[iQuantity++] = fT*fInvDLength;
- if (iQuantity == 2) {
- return 2;
- }
- }
- } else if (fDiscr == 0.0f) {
- fT = -fB;
- fTmp = kP.z + fT*kD.z;
- if (fTmp >= fWLength) {
- afT[iQuantity++] = fT*fInvDLength;
- if (iQuantity == 2) {
- return 2;
- }
- }
- }
-
- return iQuantity;
-}
-
-
-/** Used by collisionTimeForMovingPointFixedCapsule.
- @cite From magic software http://www.magic-software.com/Source/Intersection3D/MgcIntr3DLinCap.cpp
-
- @param rkRay The ray
- @param rkCapsule The capsule
- @param riQuantity The number of intersections found
- @param akPoint The intersections found
- @return True if there is at least one intersection
- */
-static bool findRayCapsuleIntersection(
- const Ray& rkRay,
- const Capsule& rkCapsule,
- int& riQuantity,
- Vector3 akPoint[2]) {
-
- double afT[2];
- riQuantity = findRayCapsuleIntersectionAux(rkRay.origin(), rkRay.direction(), rkCapsule, afT);
-
- // Only return intersections that occur in the future
- int iClipQuantity = 0;
- int i;
- for (i = 0; i < riQuantity; ++i) {
- if (afT[i] >= 0.0f) {
- akPoint[iClipQuantity] = rkRay.origin() + afT[i] * rkRay.direction();
- ++iClipQuantity;
- }
- }
-
- riQuantity = iClipQuantity;
- return (riQuantity > 0);
-}
-
-float CollisionDetection::collisionTimeForMovingPointFixedCapsule(
- const Vector3& _point,
- const Vector3& velocity,
- const Capsule& capsule,
- Vector3& location,
- Vector3& outNormal) {
-
- float timeScale = velocity.magnitude();
-
- if (timeScale == 0.0f) {
- timeScale = 1;
- }
-
- Vector3 direction = velocity / timeScale;
- int numIntersections;
- Vector3 intersection[2];
- findRayCapsuleIntersection(Ray::fromOriginAndDirection(_point, direction), capsule, numIntersections, intersection);
-
- if (numIntersections == 2) {
- // A collision can only occur if there are two intersections. If there is one
- // intersection, that one is exiting the capsule.
-
- // Find the entering intersection (the first one that occurs).
- float d0 = (intersection[0] - _point).squaredMagnitude();
- float d1 = (intersection[1] - _point).squaredMagnitude();
-
- // Compute the surface normal (if we aren't ignoring the result)
- if (&outNormal != &ignore) {
- Vector3 p2 = LineSegment::fromTwoPoints(capsule.point(0), capsule.point(1)).closestPoint(_point);
- outNormal = (_point - p2).direction();
- }
-
- if (d0 > d1) {
- location = intersection[1];
- return sqrt(d1) / timeScale;
- } else {
- location = intersection[0];
- return sqrt(d0) / timeScale;
- }
- } else {
- // No entering intersection discovered; return no intersection.
- location = Vector3::inf();
- return finf();
- }
-}
-
-
-float CollisionDetection::collisionTimeForMovingSphereFixedPlane(
- const Sphere& sphere,
- const Vector3& velocity,
- const Plane& plane,
- Vector3& location,
- Vector3& outNormal) {
-
- if (sphere.radius == 0) {
- // Optimization for zero radius sphere
- return collisionTimeForMovingPointFixedPlane(sphere.center, velocity, plane, location, outNormal);
- }
-
- // The collision point on the sphere will be the point at
- // center - (radius * normal). Collisions only occur when
- // the sphere is travelling into the plane.
-
- double d;
- plane.getEquation(outNormal, d);
-
- double vdotN = velocity.dot(outNormal);
-
- if (fuzzyGt(vdotN, 0)) {
- // No collision when the sphere is moving towards a backface.
- location = Vector3::inf();
- return (float)finf();
- }
-
- float cdotN = sphere.center.dot(outNormal);
-
- // Distance from the center to the plane
- float distance = cdotN + (float)d;
-
- // Where is the collision on the sphere?
- Vector3 point = sphere.center - (sphere.radius * outNormal);
-
- if (fuzzyLe(G3D::abs(distance), sphere.radius)) {
- // Already interpenetrating
- location = sphere.center - distance * outNormal;
- return 0;
- } else {
- return collisionTimeForMovingPointFixedPlane(point, velocity, plane, location, outNormal);
- }
-
-}
-
-
-float CollisionDetection::collisionTimeForMovingSphereFixedTriangle(
- const class Sphere& sphere,
- const Vector3& velocity,
- const Triangle& triangle,
- Vector3& outLocation,
- float b[3]) {
-
- Vector3 dummy;
- float time = collisionTimeForMovingSphereFixedPlane(sphere, velocity, triangle.plane(),
- outLocation, dummy);
-
- if (time == finf()) {
- // No collision is ever going to happen
- return time;
- }
-
- // We will hit the plane of the triangle at *time*. See if
- // the intersection point actually is within the triangle.
-
- if (isPointInsideTriangle(triangle.vertex(0), triangle.vertex(1), triangle.vertex(2), triangle.normal(),
- outLocation, b, triangle.primaryAxis())) {
-
- // The intersection point is inside the triangle; that is the location where
- // the sphere hits the triangle.
-
-# ifdef G3D_DEBUG
- {
- // Internal consistency checks
- debugAssertM(b[0] >= 0.0 && b[0] <= 1.0f, "Intersection is outside triangle.");
- debugAssertM(b[1] >= 0.0 && b[1] <= 1.0f, "Intersection is outside triangle.");
- debugAssertM(b[2] >= 0.0 && b[2] <= 1.0f, "Intersection is outside triangle.");
- Vector3 blend =
- b[0] * triangle.vertex(0) +
- b[1] * triangle.vertex(1) +
- b[2] * triangle.vertex(2);
- debugAssertM(blend.fuzzyEq(outLocation), "Barycentric coords don't match intersection.");
- // Call again so that we can debug the problem
- // isPointInsideTriangle(triangle.vertex(0), triangle.vertex(1), triangle.vertex(2), triangle.normal(),
- // outLocation, b, triangle.primaryAxis());
- }
-# endif
-
- return time;
- }
-
- // The collision (if it exists) is with a point on the triangle perimeter.
- // Switch over to moving the triangle towards a fixed sphere and see at what time
- // they will hit.
-
- // Closest point on the triangle to the sphere intersection with the plane.
- int edgeIndex;
- const Vector3& point = closestPointOnTrianglePerimeter(triangle._vertex, triangle.edgeDirection,
- triangle.edgeMagnitude, outLocation, edgeIndex);
-
- float t = 0;
- if (! sphere.contains(point)) {
- // The point is outside the sphere--see when it will hit
- t = collisionTimeForMovingPointFixedSphere(point, -velocity, sphere, dummy, dummy);
- }
-
- if (t < finf()) {
- outLocation = point;
- // Compute Barycentric coords
-
- // Index of the next vertex
- static const int next[] = {1, 2, 0};
-
- // Project along the edge in question.
- // Avoid sqrt by taking advantage of the existing edgeDirection unit vector.
- b[next[edgeIndex]] = (outLocation - triangle._vertex[edgeIndex]).dot
- (triangle.edgeDirection[edgeIndex]) / triangle.edgeMagnitude[edgeIndex];
-
- b[edgeIndex] = 1.0f - b[next[edgeIndex]];
-
- b[next[next[edgeIndex]]] = 0.0f;
-
-# ifdef G3D_DEBUG
- {
- // Internal consistency checks
- for (int i = 0; i < 3; ++i) {
- debugAssertM(fuzzyGe(b[i], 0.0f) && fuzzyLe(b[i], 1.0f), "Intersection is outside triangle.");
- }
- Vector3 blend =
- b[0] * triangle.vertex(0) +
- b[1] * triangle.vertex(1) +
- b[2] * triangle.vertex(2);
- debugAssertM(blend.fuzzyEq(outLocation),
- format("Barycentric coords don't match intersection. %s != %s",
- blend.toString().c_str(),
- outLocation.toString().c_str()));
-
- // Call again so that we can debug the problem
- collisionTimeForMovingPointFixedSphere(point, -velocity, sphere, dummy, dummy);
- }
-# endif
-
- // Due to tiny roundoffs, these values might be slightly out of bounds.
- // Ensure that they are legal. Note that the above debugging code
- // verifies that we are not clamping truly illegal values.
- for (int i = 0; i < 3; ++i) {
- b[i] = clamp(b[i], 0.0f, 1.0f);
- }
- }
-
- // The collision occured at the point, if it occured. The normal
- // was the plane normal, computed above.
-
- return t;
-}
-
-
-float CollisionDetection::collisionTimeForMovingSphereFixedRectangle(
- const Sphere& sphere,
- const Vector3& velocity,
- const Vector3& v0,
- const Vector3& v1,
- const Vector3& v2,
- const Vector3& v3,
- Vector3& location,
- Vector3& outNormal) {
-
- Plane plane(v0, v1, v2);
-
- float time = collisionTimeForMovingSphereFixedPlane(sphere, velocity, plane, location, outNormal);
-
- if (time == finf()) {
- // No collision is ever going to happen
- return time;
- }
-
- if (isPointInsideRectangle(v0, v1, v2, v3, plane.normal(), location)) {
- // The intersection point is inside the rectangle; that is the location where
- // the sphere hits the rectangle.
- return time;
- }
-
- // Switch over to moving the rectangle towards a fixed sphere and see at what time
- // they will hit.
-
- Vector3 point = closestPointToRectanglePerimeter(v0, v1, v2, v3, sphere.center);
-
- Vector3 dummy;
- double t = collisionTimeForMovingPointFixedSphere(point, -velocity, sphere, location, dummy);
-
- // Normal is the plane normal, location is the original location of the point.
- location = point;
-
- return t;
-}
-
-
-float CollisionDetection::collisionTimeForMovingSphereFixedBox(
- const Sphere& sphere,
- const Vector3& velocity,
- const Box& box,
- Vector3& location,
- Vector3& outNormal) {
-
- if (fixedSolidSphereIntersectsFixedSolidBox(sphere, box)) {
- // TODO: Compute more useful location and normal?
- location = sphere.center;
- outNormal = Vector3::zero();
- return 0;
- }
-
- float bestTime;
-
- Vector3 v[4];
- int f = 0;
- box.getFaceCorners(f, v[0], v[1], v[2], v[3]);
- bestTime = collisionTimeForMovingSphereFixedRectangle(sphere, velocity, v[0], v[1], v[2], v[3], location, outNormal);
-
- for (f = 1; f < 6; ++f) {
- Vector3 pos, normal;
- box.getFaceCorners(f, v[0], v[1], v[2], v[3]);
- float time = collisionTimeForMovingSphereFixedRectangle(sphere, velocity, v[0], v[1], v[2], v[3], pos, normal);
- if (time < bestTime) {
- bestTime = time;
- location = pos;
- outNormal = normal;
- }
- }
-
- return bestTime;
-}
-
-
-float CollisionDetection::collisionTimeForMovingSphereFixedCapsule(
- const Sphere& sphere,
- const Vector3& velocity,
- const Capsule& capsule,
- Vector3& location,
- Vector3& outNormal) {
-
- (void)outNormal;
-
- Capsule _capsule(capsule.point(0), capsule.point(1), capsule.radius() + sphere.radius);
-
- Vector3 normal;
- double time = collisionTimeForMovingPointFixedCapsule(sphere.center, velocity, _capsule, location, normal);
-
- if (time < finf()) {
- // Location is now the position of the center of the sphere at the time of collision.
- // We have to adjust the collision location for the size of the sphere.
- location -= sphere.radius * normal;
- }
-
- return time;
-}
-
-
-Vector3 CollisionDetection::bounceDirection(
- const Sphere& sphere,
- const Vector3& velocity,
- const float collisionTime,
- const Vector3& collisionLocation,
- const Vector3& collisionNormal) {
-
- // Location when the collision occurs
- Vector3 sphereLocation = sphere.center + velocity * collisionTime;
-
- Vector3 normal = (sphereLocation - collisionLocation);
- if (fuzzyEq(normal.squaredMagnitude(), 0)) {
- normal = collisionNormal;
- } else {
- normal.unitize();
- }
-
- Vector3 direction = velocity.direction();
-
- // Reflect direction about the normal
- return direction - 2.0 * normal * normal.dot(direction);
-}
-
-
-Vector3 CollisionDetection::slideDirection(
- const Sphere& sphere,
- const Vector3& velocity,
- const float collisionTime,
- const Vector3& collisionLocation) {
-
- Vector3 sphereLocation = sphere.center + velocity * collisionTime;
- Vector3 normal = (sphereLocation - collisionLocation).direction();
- Vector3 direction = velocity.direction();
-
- // subtract off the part in the direction away from the normal.
- return direction - normal * normal.dot(direction);
-}
-
-
-Vector3 CollisionDetection::closestPointOnLineSegment(
- const Vector3& v0,
- const Vector3& v1,
- const Vector3& point) {
-
- const Vector3& edge = (v1 - v0);
- float edgeLength = edge.magnitude();
-
- if (edgeLength == 0) {
- // The line segment is a point
- return v0;
- }
-
- return closestPointOnLineSegment(v0, v1, edge / edgeLength, edgeLength, point);
-}
-
-
-Vector3 CollisionDetection::closestPointOnLineSegment(
- const Vector3& v0,
- const Vector3& v1,
- const Vector3& edgeDirection,
- const float edgeLength,
- const Vector3& point) {
-
- debugAssert((v1 - v0).direction().fuzzyEq(edgeDirection));
- debugAssert(fuzzyEq((v1 - v0).magnitude(), edgeLength));
-
- // Vector towards the point
- const Vector3& c = point - v0;
-
- // Projected onto the edge itself
- float t = edgeDirection.dot(c);
-
- if (t <= 0) {
- // Before the start
- return v0;
- } else if (t >= edgeLength) {
- // After the end
- return v1;
- } else {
- // At distance t along the edge
- return v0 + edgeDirection * t;
- }
-}
-
-
-Vector3 CollisionDetection::closestPointOnTrianglePerimeter(
- const Vector3& v0,
- const Vector3& v1,
- const Vector3& v2,
- const Vector3& point) {
-
- Vector3 v[3] = {v0, v1, v2};
- Vector3 edgeDirection[3] = {(v1 - v0), (v2 - v1), (v0 - v2)};
- float edgeLength[3];
-
- for (int i = 0; i < 3; ++i) {
- edgeLength[i] = edgeDirection[i].magnitude();
- edgeDirection[i] /= edgeLength[i];
- }
-
- int edgeIndex;
- return closestPointOnTrianglePerimeter(v, edgeDirection, edgeLength, point, edgeIndex);
-}
-
-
-Vector3 CollisionDetection::closestPointOnTrianglePerimeter(
- const Vector3 v[3],
- const Vector3 edgeDirection[3],
- const float edgeLength[3],
- const Vector3& point,
- int& edgeIndex) {
-
- // Closest point on segment from v[i] to v[i + 1]
- Vector3 r[3];
-
- // Distance squared from r[i] to point
- float d[3];
-
- // Index of the next point
- static const int next[] = {1, 2, 0};
-
- for (int i = 0; i < 3; ++i) {
- r[i] = closestPointOnLineSegment(v[i], v[next[i]], edgeDirection[i], edgeLength[i], point);
- d[i] = (r[i] - point).squaredMagnitude();
- }
-
- if (d[0] < d[1]) {
- if (d[0] < d[2]) {
- // Between v0 and v1
- edgeIndex = 0;
- } else {
- // Between v2 and v0
- edgeIndex = 2;
- }
- } else {
- if (d[1] < d[2]) {
- // Between v1 and v2
- edgeIndex = 1;
- } else {
- // Between v2 and v0
- edgeIndex = 2;
- }
- }
-
-# ifdef G3D_DEBUG
- {
- Vector3 diff = r[edgeIndex] - v[edgeIndex];
- debugAssertM(fuzzyEq(diff.direction().dot(edgeDirection[edgeIndex]), 1.0f) ||
- diff.fuzzyEq(Vector3::zero()), "Point not on correct triangle edge");
- float frac = diff.dot(edgeDirection[edgeIndex])/edgeLength[edgeIndex];
- debugAssertM(frac >= -0.000001, "Point off low side of edge.");
- debugAssertM(frac <= 1.000001, "Point off high side of edge.");
- }
-# endif
-
- return r[edgeIndex];
-}
-
-
-bool CollisionDetection::isPointInsideTriangle(
- const Vector3& v0,
- const Vector3& v1,
- const Vector3& v2,
- const Vector3& normal,
- const Vector3& point,
- float b[3],
- Vector3::Axis primaryAxis) {
-
- if (primaryAxis == Vector3::DETECT_AXIS) {
- primaryAxis = normal.primaryAxis();
- }
-
- // Check that the point is within the triangle using a Barycentric
- // coordinate test on a two dimensional plane.
- int i, j;
-
- switch (primaryAxis) {
- case Vector3::X_AXIS:
- i = Vector3::Y_AXIS;
- j = Vector3::Z_AXIS;
- break;
-
- case Vector3::Y_AXIS:
- i = Vector3::Z_AXIS;
- j = Vector3::X_AXIS;
- break;
-
- case Vector3::Z_AXIS:
- i = Vector3::X_AXIS;
- j = Vector3::Y_AXIS;
- break;
-
- default:
- // This case is here to supress a warning on Linux
- i = j = 0;
- debugAssertM(false, "Should not get here.");
- break;
- }
-
- // See if all barycentric coordinates are non-negative
-
- // 2D area via cross product
-# define AREA2(d, e, f) (((e)[i] - (d)[i]) * ((f)[j] - (d)[j]) - ((f)[i] - (d)[i]) * ((e)[j] - (d)[j]))
-
- // Area of the polygon
- float area = AREA2(v0, v1, v2);
- if (area == 0) {
- // This triangle has zero area, so the point must not
- // be in it unless the triangle point is the test point.
- return (v0 == point);
- }
-
- debugAssert(area != 0);
-
- float invArea = 1.0f / area;
-
- // (avoid normalization until absolutely necessary)
- b[0] = AREA2(point, v1, v2) * invArea;
-
- if ((b[0] < 0.0f) || (b[0] > 1.0f)) {
- return false;
- }
-
- b[1] = AREA2(v0, point, v2) * invArea;
- if ((b[1] < 0.0f) || (b[1] > 1.0f)) {
- return false;
- }
-
- b[2] = 1.0f - b[0] - b[1];
-
-# undef AREA2
-
- return (b[2] >= 0.0f) && (b[2] <= 1.0f);
-}
-
-
-bool CollisionDetection::isPointInsideRectangle(
- const Vector3& v0,
- const Vector3& v1,
- const Vector3& v2,
- const Vector3& v3,
- const Vector3& normal,
- const Vector3& point) {
-
- return isPointInsideTriangle(v0, v1, v2, normal, point) ||
- isPointInsideTriangle(v2, v3, v0, normal, point);
-}
-
-
-Vector3 CollisionDetection::closestPointToRectanglePerimeter(
- const Vector3& v0,
- const Vector3& v1,
- const Vector3& v2,
- const Vector3& v3,
- const Vector3& point) {
-
- Vector3 r0 = closestPointOnLineSegment(v0, v1, point);
- Vector3 r1 = closestPointOnLineSegment(v1, v2, point);
- Vector3 r2 = closestPointOnLineSegment(v2, v3, point);
- Vector3 r3 = closestPointOnLineSegment(v3, v0, point);
-
- double d0 = (r0 - point).squaredMagnitude();
- double d1 = (r1 - point).squaredMagnitude();
- double d2 = (r2 - point).squaredMagnitude();
- double d3 = (r3 - point).squaredMagnitude();
-
- if (d0 < d1) {
- if (d0 < d2) {
- if (d0 < d3) {
- return r0;
- } else {
- return r3;
- }
- } else {
- if (d2 < d3) {
- return r2;
- } else {
- return r3;
- }
- }
- } else {
- if (d1 < d2) {
- if (d1 < d3) {
- return r1;
- } else {
- return r3;
- }
- } else {
- if (d2 < d3) {
- return r2;
- } else {
- return r3;
- }
- }
- }
-}
-
-
-Vector3 CollisionDetection::closestPointToRectangle(
- const Vector3& v0,
- const Vector3& v1,
- const Vector3& v2,
- const Vector3& v3,
- const Vector3& point) {
-
- Plane plane(v0, v1, v2);
-
- // Project the point into the plane
- double a, b, c, d;
- plane.getEquation(a, b, c, d);
-
- double distance = a*point.x + b*point.y + c*point.z + d;
- Vector3 planePoint = point - distance * plane.normal();
-
- if (isPointInsideRectangle(v0, v1, v2, v3, plane.normal(), planePoint)) {
- return planePoint;
- } else {
- return closestPointToRectanglePerimeter(v0, v1, v2, v3, planePoint);
- }
-}
-
-
-bool CollisionDetection::fixedSolidSphereIntersectsFixedSolidSphere(
- const Sphere& sphere1,
- const Sphere& sphere2) {
-
- return (sphere1.center - sphere2.center).squaredMagnitude() < square(sphere1.radius + sphere2.radius);
-}
-
-
-bool CollisionDetection::fixedSolidSphereIntersectsFixedSolidBox(
- const Sphere& sphere,
- const Box& box) {
-
- // If the center of the sphere is within the box, the whole
- // sphere is within the box.
- if (box.contains(sphere.center)) {
- return true;
- }
-
- float r2 = square(sphere.radius);
-
- // Find the closest point on the surface of the box to the sphere. If
- // this point is within the sphere's radius, they intersect.
- int f;
- for (f = 0; f < 6; ++f) {
- Vector3 v0, v1, v2, v3;
- box.getFaceCorners(f, v0, v1, v2, v3);
- if ((closestPointToRectangle(v0, v1, v2, v3, sphere.center) - sphere.center).squaredMagnitude() <= r2) {
- return true;
- }
- }
-
- return false;
-}
-
-
-bool CollisionDetection::movingSpherePassesThroughFixedBox(
- const Sphere& sphere,
- const Vector3& velocity,
- const Box& box,
- double timeLimit) {
-
- // If they intersect originally, they definitely pass through each other.
- if (fixedSolidSphereIntersectsFixedSolidBox(sphere, box)) {
- return true;
- }
-
- // See if the sphere hits the box during the time period.
- Vector3 dummy1, dummy2;
-
- return (collisionTimeForMovingSphereFixedBox(sphere, velocity, box, dummy1, dummy2) < timeLimit);
-}
-
-
-bool CollisionDetection::movingSpherePassesThroughFixedSphere(
- const Sphere& sphere,
- const Vector3& velocity,
- const Sphere& fixedSphere,
- double timeLimit) {
-
- if (fixedSolidSphereIntersectsFixedSolidSphere(sphere, fixedSphere)) {
- return true;
- }
-
- // Extend the fixed sphere by the radius of the moving sphere
- Sphere bigFixed(fixedSphere.center, fixedSphere.radius + sphere.radius);
- Vector3 dummy1, dummy2;
-
- // If the sphere collides with the other sphere during the time limit, it passes through
- return (collisionTimeForMovingPointFixedSphere(sphere.center, velocity, bigFixed, dummy1, dummy2) < timeLimit);
-}
-
-
-
-bool CollisionDetection::fixedSolidSphereIntersectsFixedTriangle(
- const Sphere& sphere,
- const Triangle& triangle) {
-
- // How far is the sphere from the plane of the triangle
- const Plane& plane = triangle.plane();
-
- // Does the closest point to the sphere center lie within the triangle?
- Vector3 v = plane.closestPoint(sphere.center);
-
- // Is the closest point to the plane within the sphere?
- if ((v - sphere.center).squaredLength() <= square(sphere.radius)) {
- // Is it also within the triangle?
- float b[3];
- if (isPointInsideTriangle(triangle.vertex(0), triangle.vertex(1), triangle.vertex(2), triangle.normal(),
- v, b, triangle.primaryAxis())){
- // The closest point is inside the triangle
- return true;
- }
- }
-
- // ignored
- int edgeIndex;
-
- v = closestPointOnTrianglePerimeter(triangle._vertex, triangle.edgeDirection, triangle.edgeMagnitude, sphere.center, edgeIndex);
-
- // Is the closest point within the sphere?
- return ((v - sphere.center).squaredLength() <= square(sphere.radius));
-}
-
-
-////////////////////////////////////////////////////////////////////////////////
-// AABB-triangle overlap test code based on Tomas Akenine-Möller's
-// http://www.cs.lth.se/home/Tomas_Akenine_Moller/code/tribox3.txt
-// Ported 2008-12-28
-
-#define X 0
-#define Y 1
-#define Z 2
-
-#define FINDMINMAX(x0, x1, x2, min, max) \
- min = max = x0; \
- if(x1<min) min=x1;\
- if(x1>max) max=x1;\
- if(x2<min) min=x2;\
- if(x2>max) max=x2;
-
-static bool planeBoxOverlap(const Vector3& normal, const Vector3& vert, const Vector3& maxbox) {
- Vector3 vmin, vmax;
- float v;
-
- // for each axis
- for(int a = 0; a < 3; ++a) {
- v = vert[a];
-
- if (normal[a] > 0.0f) {
- vmin[a] = -maxbox[a] - v;
- vmax[a] = maxbox[a] - v;
- } else {
- vmin[a] = maxbox[a] - v;
- vmax[a] = -maxbox[a] - v;
- }
- }
-
- if (normal.dot(vmin) > 0.0f) {
- return false;
- } else if (normal.dot(vmax) >= 0.0f) {
- return true;
- } else {
- return false;
- }
-}
-
-/*======================== X-tests ========================*/
-
-#define AXISTEST_X01(a, b, fa, fb) \
- p0 = a*v0[Y] - b*v0[Z]; \
- p2 = a*v2[Y] - b*v2[Z]; \
- if(p0<p2) {min=p0; max=p2;} else {min=p2; max=p0;} \
- rad = fa * boxhalfsize[Y] + fb * boxhalfsize[Z]; \
- if(min>rad || max<-rad) return false;
-
-
-#define AXISTEST_X2(a, b, fa, fb) \
- p0 = a*v0[Y] - b*v0[Z]; \
- p1 = a*v1[Y] - b*v1[Z]; \
- if(p0<p1) {min=p0; max=p1;} else {min=p1; max=p0;} \
- rad = fa * boxhalfsize[Y] + fb * boxhalfsize[Z]; \
- if(min>rad || max<-rad) return false;
-
-/*======================== Y-tests ========================*/
-
-#define AXISTEST_Y02(a, b, fa, fb) \
- p0 = -a*v0[X] + b*v0[Z]; \
- p2 = -a*v2[X] + b*v2[Z]; \
- if(p0<p2) {min=p0; max=p2;} else {min=p2; max=p0;} \
- rad = fa * boxhalfsize[X] + fb * boxhalfsize[Z]; \
- if(min>rad || max<-rad) return false;
-
-#define AXISTEST_Y1(a, b, fa, fb) \
- p0 = -a*v0[X] + b*v0[Z]; \
- p1 = -a*v1[X] + b*v1[Z]; \
- if(p0<p1) {min=p0; max=p1;} else {min=p1; max=p0;} \
- rad = fa * boxhalfsize[X] + fb * boxhalfsize[Z]; \
- if(min>rad || max<-rad) return false;
-
-/*======================== Z-tests ========================*/
-
-#define AXISTEST_Z12(a, b, fa, fb) \
- p1 = a*v1[X] - b*v1[Y]; \
- p2 = a*v2[X] - b*v2[Y]; \
- if(p2<p1) {min=p2; max=p1;} else {min=p1; max=p2;} \
- rad = fa * boxhalfsize[X] + fb * boxhalfsize[Y]; \
- if(min>rad || max<-rad) return false;
-
-#define AXISTEST_Z0(a, b, fa, fb) \
- p0 = a*v0[X] - b*v0[Y]; \
- p1 = a*v1[X] - b*v1[Y]; \
- if(p0<p1) {min=p0; max=p1;} else {min=p1; max=p0;} \
- rad = fa * boxhalfsize[X] + fb * boxhalfsize[Y]; \
- if(min>rad || max<-rad) return false;
-
-bool CollisionDetection::fixedSolidBoxIntersectsFixedTriangle(
- const AABox& box, const Triangle& tri) {
-
- // use separating axis theorem to test overlap between triangle and box
- // need to test for overlap in these directions:
- // 1) the {x,y,z}-directions (actually, since we use the AABB of the triangle
- // we do not even need to test these)
- // 2) normal of the triangle
- // 3) crossproduct(edge from tri, {x,y,z}-direction)
- // this gives 3x3=9 more tests
-
- // This is the fastest branch (on Sun).
- // Move the triangle to the object space of the box
- // Triangle vertices in box object space
-
- const Vector3& boxcenter = box.center();
- const Vector3& boxhalfsize = box.extent() * 0.5f;
-
- const Vector3& v0 = tri.vertex(0) - boxcenter;
- const Vector3& v1 = tri.vertex(1) - boxcenter;
- const Vector3& v2 = tri.vertex(2) - boxcenter;
-
- // Compute triangle edges in object space
- const Vector3& e0 = v1 - v0;
- const Vector3& e1 = v2 - v1;
- const Vector3& e2 = v0 - v2;
-
- // Bullet 3:
- // test the 9 tests first (this was faster)
- float min,max,p0,p1,p2,rad;
- Vector3 fe;
-
- fe = abs(e0);
- AXISTEST_X01(e0[Z], e0[Y], fe[Z], fe[Y]);
- AXISTEST_Y02(e0[Z], e0[X], fe[Z], fe[X]);
- AXISTEST_Z12(e0[Y], e0[X], fe[Y], fe[X]);
-
- fe = abs(e1);
- AXISTEST_X01(e1[Z], e1[Y], fe[Z], fe[Y]);
- AXISTEST_Y02(e1[Z], e1[X], fe[Z], fe[X]);
- AXISTEST_Z0 (e1[Y], e1[X], fe[Y], fe[X]);
-
- fe = abs(e2);
- AXISTEST_X2 (e2[Z], e2[Y], fe[Z], fe[Y]);
- AXISTEST_Y1 (e2[Z], e2[X], fe[Z], fe[X]);
- AXISTEST_Z12(e2[Y], e2[X], fe[Y], fe[X]);
-
- // Bullet 1:
- // first test overlap in the {x,y,z}-directions
- // find min, max of the triangle each direction, and test for overlap in
- // that direction -- this is equivalent to testing a minimal AABB around
- // the triangle against the AABB
-
- // test in X-direction
- FINDMINMAX(v0[X],v1[X],v2[X],min,max);
- if (min > boxhalfsize[X] || max < -boxhalfsize[X]) {
- return false;
- }
-
- // test in Y-direction
- FINDMINMAX(v0[Y],v1[Y],v2[Y],min,max);
- if (min > boxhalfsize[Y] || max < -boxhalfsize[Y]) {
- return false;
- }
-
- // test in Z-direction
- FINDMINMAX(v0[Z],v1[Z],v2[Z],min,max);
- if (min > boxhalfsize[Z] || max < -boxhalfsize[Z]) {
- return false;
- }
-
- // Bullet 2:
- // test if the box intersects the plane of the triangle
- // compute plane equation of triangle: normal*x+d=0
-
- if (! planeBoxOverlap(tri.normal(), v0, boxhalfsize)) {
- return false;
- }
-
- // box and triangle overlap
- return true;
-}
-#undef X
-#undef Y
-#undef Z
-
-////////////////////////////////////////////////////////////////////////////////
-
-
-} // namespace
-
-#ifdef _MSC_VER
-// Turn off fast floating-point optimizations
-#pragma float_control( pop )
-#pragma warning (pop)
-#endif
diff --git a/externals/g3dlite/CoordinateFrame.cpp b/externals/g3dlite/CoordinateFrame.cpp
deleted file mode 100644
index 9b639b62082..00000000000
--- a/externals/g3dlite/CoordinateFrame.cpp
+++ /dev/null
@@ -1,436 +0,0 @@
-/**
- @file CoordinateFrame.cpp
-
- Coordinate frame class
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2001-06-02
- @edited 2009-11-13
-
- Copyright 2000-2010, Morgan McGuire.
- All rights reserved.
-*/
-
-#include "G3D/platform.h"
-#include "G3D/CoordinateFrame.h"
-#include "G3D/Quat.h"
-#include "G3D/Matrix4.h"
-#include "G3D/Box.h"
-#include "G3D/AABox.h"
-#include "G3D/Sphere.h"
-#include "G3D/Triangle.h"
-#include "G3D/Ray.h"
-#include "G3D/Capsule.h"
-#include "G3D/Cylinder.h"
-#include "G3D/UprightFrame.h"
-#include "G3D/Any.h"
-#include "G3D/stringutils.h"
-
-namespace G3D {
-
-CoordinateFrame::CoordinateFrame(const Any& any) {
- any.verifyName("CFrame");
- if (toUpper(any.name()) == "CFRAME") {
- any.verifyType(Any::TABLE, Any::ARRAY);
- if (any.type() == Any::TABLE) {
- rotation = any["rotation"];
- translation = any["translation"];
- } else {
- any.verifySize(2);
- rotation = any[0];
- translation = any[1];
- }
- } else {
- any.verifyName("CFrame::fromXYZYPRDegrees");
- any.verifyType(Any::ARRAY);
- any.verifySize(3, 6);
-
- int s = any.size();
-
- *this = fromXYZYPRDegrees(any[0], any[1], any[2],
- (s > 3) ? any[3].number() : 0.0f,
- (s > 4) ? any[4].number() : 0.0f,
- (s > 5) ? any[5].number() : 0.0f);
- }
-}
-
-
-CoordinateFrame::operator Any() const {
- float x, y, z, yaw, pitch, roll;
- getXYZYPRDegrees(x, y, z, yaw, pitch, roll);
- Any a(Any::ARRAY, "CFrame::fromXYZYPRDegrees");
- a.append(x, y, z, yaw);
- if ( ! G3D::fuzzyEq(yaw, 0.0f) || ! G3D::fuzzyEq(pitch, 0.0f) || ! G3D::fuzzyEq(roll, 0.0f)) {
- a.append(yaw);
- if (! G3D::fuzzyEq(pitch, 0.0f) || ! G3D::fuzzyEq(roll, 0.0f)) {
- a.append(pitch);
- if (! G3D::fuzzyEq(roll, 0.0f)) {
- a.append(roll);
- }
- }
- }
- return a;
-}
-
-
-CoordinateFrame::CoordinateFrame(const class UprightFrame& f) {
- *this = f.toCoordinateFrame();
-}
-
-
-CoordinateFrame::CoordinateFrame() :
- rotation(Matrix3::identity()), translation(Vector3::zero()) {
-}
-
-CoordinateFrame CoordinateFrame::fromXYZYPRRadians(float x, float y, float z, float yaw,
- float pitch, float roll) {
- Matrix3 rotation = Matrix3::fromAxisAngle(Vector3::unitY(), yaw);
-
- rotation = Matrix3::fromAxisAngle(rotation.column(0), pitch) * rotation;
- rotation = Matrix3::fromAxisAngle(rotation.column(2), roll) * rotation;
-
- const Vector3 translation(x, y, z);
-
- return CoordinateFrame(rotation, translation);
-}
-
-
-void CoordinateFrame::getXYZYPRRadians(float& x, float& y, float& z,
- float& yaw, float& pitch, float& roll) const {
- x = translation.x;
- y = translation.y;
- z = translation.z;
-
- const Vector3& look = lookVector();
-
- if (abs(look.y) > 0.99f) {
- // Looking nearly straight up or down
-
- yaw = G3D::pi() + atan2(look.x, look.z);
- pitch = asin(look.y);
- roll = 0.0f;
-
- } else {
-
- // Yaw cannot be affected by others, so pull it first
- yaw = G3D::pi() + atan2(look.x, look.z);
-
- // Pitch is the elevation of the yaw vector
- pitch = asin(look.y);
-
- Vector3 actualRight = rightVector();
- Vector3 expectedRight = look.cross(Vector3::unitY());
-
- roll = 0;//acos(actualRight.dot(expectedRight)); TODO
- }
-}
-
-
-void CoordinateFrame::getXYZYPRDegrees(float& x, float& y, float& z,
- float& yaw, float& pitch, float& roll) const {
- getXYZYPRRadians(x, y, z, yaw, pitch, roll);
- yaw = toDegrees(yaw);
- pitch = toDegrees(pitch);
- roll = toDegrees(roll);
-}
-
-
-CoordinateFrame CoordinateFrame::fromXYZYPRDegrees(float x, float y, float z,
- float yaw, float pitch, float roll) {
- return fromXYZYPRRadians(x, y, z, toRadians(yaw), toRadians(pitch), toRadians(roll));
-}
-
-
-Ray CoordinateFrame::lookRay() const {
- return Ray::fromOriginAndDirection(translation, lookVector());
-}
-
-
-bool CoordinateFrame::fuzzyEq(const CoordinateFrame& other) const {
-
- for (int c = 0; c < 3; ++c) {
- for (int r = 0; r < 3; ++r) {
- if (! G3D::fuzzyEq(other.rotation[r][c], rotation[r][c])) {
- return false;
- }
- }
- if (! G3D::fuzzyEq(translation[c], other.translation[c])) {
- return false;
- }
- }
-
- return true;
-}
-
-
-bool CoordinateFrame::fuzzyIsIdentity() const {
- const Matrix3& I = Matrix3::identity();
-
- for (int c = 0; c < 3; ++c) {
- for (int r = 0; r < 3; ++r) {
- if (fuzzyNe(I[r][c], rotation[r][c])) {
- return false;
- }
- }
- if (fuzzyNe(translation[c], 0)) {
- return false;
- }
- }
-
- return true;
-}
-
-
-bool CoordinateFrame::isIdentity() const {
- return
- (translation == Vector3::zero()) &&
- (rotation == Matrix3::identity());
-}
-
-
-Matrix4 CoordinateFrame::toMatrix4() const {
- return Matrix4(*this);
-}
-
-
-std::string CoordinateFrame::toXML() const {
- return G3D::format(
- "<COORDINATEFRAME>\n %lf,%lf,%lf,%lf,\n %lf,%lf,%lf,%lf,\n %lf,%lf,%lf,%lf,\n %lf,%lf,%lf,%lf\n</COORDINATEFRAME>\n",
- rotation[0][0], rotation[0][1], rotation[0][2], translation.x,
- rotation[1][0], rotation[1][1], rotation[1][2], translation.y,
- rotation[2][0], rotation[2][1], rotation[2][2], translation.z,
- 0.0, 0.0, 0.0, 1.0);
-}
-
-
-Plane CoordinateFrame::toObjectSpace(const Plane& p) const {
- Vector3 N, P;
- double d;
- p.getEquation(N, d);
- P = N * (float)d;
- P = pointToObjectSpace(P);
- N = normalToObjectSpace(N);
- return Plane(N, P);
-}
-
-
-Plane CoordinateFrame::toWorldSpace(const Plane& p) const {
- Vector3 N, P;
- double d;
- p.getEquation(N, d);
- P = N * (float)d;
- P = pointToWorldSpace(P);
- N = normalToWorldSpace(N);
- return Plane(N, P);
-}
-
-
-Triangle CoordinateFrame::toObjectSpace(const Triangle& t) const {
- return Triangle(pointToObjectSpace(t.vertex(0)),
- pointToObjectSpace(t.vertex(1)),
- pointToObjectSpace(t.vertex(2)));
-}
-
-
-Triangle CoordinateFrame::toWorldSpace(const Triangle& t) const {
- return Triangle(pointToWorldSpace(t.vertex(0)),
- pointToWorldSpace(t.vertex(1)),
- pointToWorldSpace(t.vertex(2)));
-}
-
-
-Cylinder CoordinateFrame::toWorldSpace(const Cylinder& c) const {
- return Cylinder(
- pointToWorldSpace(c.point(0)),
- pointToWorldSpace(c.point(1)),
- c.radius());
-}
-
-
-Capsule CoordinateFrame::toWorldSpace(const Capsule& c) const {
- return Capsule(
- pointToWorldSpace(c.point(0)),
- pointToWorldSpace(c.point(1)),
- c.radius());
-}
-
-
-Box CoordinateFrame::toWorldSpace(const AABox& b) const {
- Box b2(b);
- return toWorldSpace(b2);
-}
-
-
-Box CoordinateFrame::toWorldSpace(const Box& b) const {
- Box out(b);
-
- for (int i = 0; i < 8; ++i) {
- out._corner[i] = pointToWorldSpace(b._corner[i]);
- debugAssert(! isNaN(out._corner[i].x));
- }
-
- for (int i = 0; i < 3; ++i) {
- out._axis[i] = vectorToWorldSpace(b._axis[i]);
- }
-
- out._center = pointToWorldSpace(b._center);
-
- return out;
-}
-
-
-Box CoordinateFrame::toObjectSpace(const Box &b) const {
- return inverse().toWorldSpace(b);
-}
-
-
-Box CoordinateFrame::toObjectSpace(const AABox& b) const {
- return toObjectSpace(Box(b));
-}
-
-
-CoordinateFrame::CoordinateFrame(class BinaryInput& b) : rotation(Matrix3::zero()) {
- deserialize(b);
-}
-
-
-void CoordinateFrame::deserialize(class BinaryInput& b) {
- rotation.deserialize(b);
- translation.deserialize(b);
-}
-
-
-void CoordinateFrame::serialize(class BinaryOutput& b) const {
- rotation.serialize(b);
- translation.serialize(b);
-}
-
-
-Sphere CoordinateFrame::toWorldSpace(const Sphere &b) const {
- return Sphere(pointToWorldSpace(b.center), b.radius);
-}
-
-
-Sphere CoordinateFrame::toObjectSpace(const Sphere &b) const {
- return Sphere(pointToObjectSpace(b.center), b.radius);
-}
-
-
-Ray CoordinateFrame::toWorldSpace(const Ray& r) const {
- return Ray::fromOriginAndDirection(pointToWorldSpace(r.origin()), vectorToWorldSpace(r.direction()));
-}
-
-
-Ray CoordinateFrame::toObjectSpace(const Ray& r) const {
- return Ray::fromOriginAndDirection(pointToObjectSpace(r.origin()), vectorToObjectSpace(r.direction()));
-}
-
-
-void CoordinateFrame::lookAt(const Vector3 &target) {
- lookAt(target, Vector3::unitY());
-}
-
-
-void CoordinateFrame::lookAt(
- const Vector3& target,
- Vector3 up) {
-
- up = up.direction();
-
- Vector3 look = (target - translation).direction();
- if (fabs(look.dot(up)) > .99f) {
- up = Vector3::unitX();
- if (fabs(look.dot(up)) > .99f) {
- up = Vector3::unitY();
- }
- }
-
- up -= look * look.dot(up);
- up.unitize();
-
- Vector3 z = -look;
- Vector3 x = -z.cross(up);
- x.unitize();
-
- Vector3 y = z.cross(x);
-
- rotation.setColumn(0, x);
- rotation.setColumn(1, y);
- rotation.setColumn(2, z);
-}
-
-
-CoordinateFrame CoordinateFrame::lerp(
- const CoordinateFrame& other,
- float alpha) const {
-
- if (alpha == 1.0f) {
- return other;
- } else if (alpha == 0.0f) {
- return *this;
- } else {
- Quat q1 = Quat(this->rotation);
- Quat q2 = Quat(other.rotation);
-
- return CoordinateFrame(
- q1.slerp(q2, alpha).toRotationMatrix(),
- this->translation * (1 - alpha) + other.translation * alpha);
- }
-}
-
-
-void CoordinateFrame::pointToWorldSpace(const Array<Vector3>& v, Array<Vector3>& vout) const {
- vout.resize(v.size());
-
- for (int i = v.size() - 1; i >= 0; --i) {
- vout[i] = pointToWorldSpace(v[i]);
- }
-}
-
-
-void CoordinateFrame::normalToWorldSpace(const Array<Vector3>& v, Array<Vector3>& vout) const {
- vout.resize(v.size());
-
- for (int i = v.size() - 1; i >= 0; --i) {
- vout[i] = normalToWorldSpace(v[i]);
- }
-}
-
-
-void CoordinateFrame::vectorToWorldSpace(const Array<Vector3>& v, Array<Vector3>& vout) const {
- vout.resize(v.size());
-
- for (int i = v.size() - 1; i >= 0; --i) {
- vout[i] = vectorToWorldSpace(v[i]);
- }
-}
-
-
-void CoordinateFrame::pointToObjectSpace(const Array<Vector3>& v, Array<Vector3>& vout) const {
- vout.resize(v.size());
-
- for (int i = v.size() - 1; i >= 0; --i) {
- vout[i] = pointToObjectSpace(v[i]);
- }
-}
-
-
-void CoordinateFrame::normalToObjectSpace(const Array<Vector3>& v, Array<Vector3>& vout) const {
- vout.resize(v.size());
-
- for (int i = v.size() - 1; i >= 0; --i) {
- vout[i] = normalToObjectSpace(v[i]);
- }
-}
-
-
-void CoordinateFrame::vectorToObjectSpace(const Array<Vector3>& v, Array<Vector3>& vout) const {
- vout.resize(v.size());
-
- for (int i = v.size() - 1; i >= 0; --i) {
- vout[i] = vectorToObjectSpace(v[i]);
- }
-}
-
-} // namespace
diff --git a/externals/g3dlite/Crypto.cpp b/externals/g3dlite/Crypto.cpp
deleted file mode 100644
index c69b23375ce..00000000000
--- a/externals/g3dlite/Crypto.cpp
+++ /dev/null
@@ -1,70 +0,0 @@
-/**
- @file Crypto.cpp
-
- @author Morgan McGuire, http://graphics.cs.williams.edu
-
-
- @created 2006-03-28
- @edited 2006-04-06
- */
-
-#include "G3D/platform.h"
-#include "G3D/Crypto.h"
-#include "G3D/g3dmath.h"
-#include <zlib.h>
-
-namespace G3D {
-
-
-int Crypto::smallPrime(int n) {
- debugAssert(n < numSmallPrimes() && n >= 0);
-
- // From:
- // http://primes.utm.edu/lists/small/1000.txt
-
- static const int table[] = {
- 2, 3, 5, 7, 11, 13, 17, 19, 23, 29,
- 31, 37, 41, 43, 47, 53, 59, 61, 67, 71,
- 73, 79, 83, 89, 97, 101, 103, 107, 109, 113,
- 127, 131, 137, 139, 149, 151, 157, 163, 167, 173,
- 179, 181, 191, 193, 197, 199, 211, 223, 227, 229,
- 233, 239, 241, 251, 257, 263, 269, 271, 277, 281,
- 283, 293, 307, 311, 313, 317, 331, 337, 347, 349,
- 353, 359, 367, 373, 379, 383, 389, 397, 401, 409,
- 419, 421, 431, 433, 439, 443, 449, 457, 461, 463,
- 467, 479, 487, 491, 499, 503, 509, 521, 523, 541,
- 547, 557, 563, 569, 571, 577, 587, 593, 599, 601,
- 607, 613, 617, 619, 631, 641, 643, 647, 653, 659,
- 661, 673, 677, 683, 691, 701, 709, 719, 727, 733,
- 739, 743, 751, 757, 761, 769, 773, 787, 797, 809,
- 811, 821, 823, 827, 829, 839, 853, 857, 859, 863,
- 877, 881, 883, 887, 907, 911, 919, 929, 937, 941,
- 947, 953, 967, 971, 977, 983, 991, 997, 1009, 1013,
- 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069,
- 1087, 1091, 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151,
- 1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223,
- 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291,
- 1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373,
- 1381, 1399, 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451,
- 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, 1499, 1511,
- 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583,
- 1597, 1601, 1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657,
- 1663, 1667, 1669, 1693, 1697, 1699, 1709, 1721, 1723, 1733,
- 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811,
- 1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877, 1879, 1889,
- 1901, 1907, 1913, 1931, 1933, 1949, 1951, 1973, 1979, 1987,
- 1993, 1997, 1999};
-
- return table[n];
-}
-
-
-int Crypto::numSmallPrimes() {
- return 303;
-}
-
-uint32 Crypto::crc32(const void* byte, size_t numBytes) {
- return ::crc32(::crc32(0, Z_NULL, 0), static_cast<const Bytef *>(byte), numBytes);
-}
-
-} // G3D
diff --git a/externals/g3dlite/Cylinder.cpp b/externals/g3dlite/Cylinder.cpp
deleted file mode 100644
index 7a7b9f9440d..00000000000
--- a/externals/g3dlite/Cylinder.cpp
+++ /dev/null
@@ -1,176 +0,0 @@
-/**
- @file Cylinder.cpp
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2003-02-07
- @edited 2006-02-18
-
- Copyright 2000-2006, Morgan McGuire.
- All rights reserved.
- */
-
-#include "G3D/platform.h"
-#include "G3D/Cylinder.h"
-#include "G3D/BinaryInput.h"
-#include "G3D/BinaryOutput.h"
-#include "G3D/LineSegment.h"
-#include "G3D/CoordinateFrame.h"
-#include "G3D/Line.h"
-#include "G3D/AABox.h"
-
-namespace G3D {
-
-Cylinder::Cylinder(class BinaryInput& b) {
- deserialize(b);
-}
-
-
-Cylinder::Cylinder() {
-}
-
-
-Cylinder::Cylinder(const Vector3& _p1, const Vector3& _p2, float _r)
- : p1(_p1), p2(_p2), mRadius(_r) {
-}
-
-
-void Cylinder::serialize(class BinaryOutput& b) const {
- p1.serialize(b);
- p2.serialize(b);
- b.writeFloat64(mRadius);
-}
-
-
-void Cylinder::deserialize(class BinaryInput& b) {
- p1.deserialize(b);
- p2.deserialize(b);
- mRadius = b.readFloat64();
-}
-
-
-Line Cylinder::axis() const {
- return Line::fromTwoPoints(p1, p2);
-}
-
-
-
-float Cylinder::radius() const {
- return mRadius;
-}
-
-
-float Cylinder::volume() const {
- return
- (float)pi() * square(mRadius) * (p1 - p2).magnitude();
-}
-
-
-float Cylinder::area() const {
- return
- // Sides
- (twoPi() * mRadius) * height() +
-
- // Caps
- twoPi() * square(mRadius);
-}
-
-void Cylinder::getBounds(AABox& out) const {
- Vector3 min = p1.min(p2) - (Vector3(1, 1, 1) * mRadius);
- Vector3 max = p1.max(p2) + (Vector3(1, 1, 1) * mRadius);
- out = AABox(min, max);
-}
-
-bool Cylinder::contains(const Vector3& p) const {
- return LineSegment::fromTwoPoints(p1, p2).distanceSquared(p) <= square(mRadius);
-}
-
-
-void Cylinder::getReferenceFrame(CoordinateFrame& cframe) const {
- cframe.translation = center();
-
- Vector3 Y = (p1 - p2).direction();
- Vector3 X = (abs(Y.dot(Vector3::unitX())) > 0.9) ? Vector3::unitY() : Vector3::unitX();
- Vector3 Z = X.cross(Y).direction();
- X = Y.cross(Z);
- cframe.rotation.setColumn(0, X);
- cframe.rotation.setColumn(1, Y);
- cframe.rotation.setColumn(2, Z);
-}
-
-
-void Cylinder::getRandomSurfacePoint(Vector3& p, Vector3& N) const {
- float h = height();
- float r = radius();
-
- // Create a random point on a standard cylinder and then rotate to the global frame.
-
- // Relative areas (factor of 2PI already taken out)
- float capRelArea = square(r) / 2.0f;
- float sideRelArea = r * h;
-
- float r1 = uniformRandom(0, capRelArea * 2 + sideRelArea);
-
- if (r1 < capRelArea * 2) {
-
- // Select a point uniformly at random on a disk
- // @cite http://mathworld.wolfram.com/DiskPointPicking.html
- float a = uniformRandom(0, (float)twoPi());
- float r2 = sqrt(uniformRandom(0, 1)) * r;
- p.x = cos(a) * r2;
- p.z = sin(a) * r2;
-
- N.x = 0;
- N.z = 0;
- if (r1 < capRelArea) {
- // Top
- p.y = h / 2.0f;
- N.y = 1;
- } else {
- // Bottom
- p.y = -h / 2.0f;
- N.y = -1;
- }
- } else {
- // Side
- float a = uniformRandom(0, (float)twoPi());
- N.x = cos(a);
- N.y = 0;
- N.z = sin(a);
- p.x = N.x * r;
- p.z = N.y * r;
- p.y = uniformRandom(-h / 2.0f, h / 2.0f);
- }
-
- // Transform to world space
- CoordinateFrame cframe;
- getReferenceFrame(cframe);
-
- p = cframe.pointToWorldSpace(p);
- N = cframe.normalToWorldSpace(N);
-}
-
-
-Vector3 Cylinder::randomInteriorPoint() const {
- float h = height();
- float r = radius();
-
- // Create a random point in a standard cylinder and then rotate to the global frame.
-
- // Select a point uniformly at random on a disk
- // @cite http://mathworld.wolfram.com/DiskPointPicking.html
- float a = uniformRandom(0, (float)twoPi());
- float r2 = sqrt(uniformRandom(0, 1)) * r;
-
- Vector3 p( cos(a) * r2,
- uniformRandom(-h / 2.0f, h / 2.0f),
- sin(a) * r2);
-
- // Transform to world space
- CoordinateFrame cframe;
- getReferenceFrame(cframe);
-
- return cframe.pointToWorldSpace(p);
-}
-
-} // namespace
diff --git a/externals/g3dlite/G3D/AABox.h b/externals/g3dlite/G3D/AABox.h
deleted file mode 100644
index 2e8da1f6098..00000000000
--- a/externals/g3dlite/G3D/AABox.h
+++ /dev/null
@@ -1,272 +0,0 @@
-/**
- @file AABox.h
-
- Axis-aligned box class
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2004-01-10
- @edited 2009-02-10
-
- Copyright 2000-2009, Morgan McGuire.
- All rights reserved.
- */
-
-#ifndef G3D_AABOX_H
-#define G3D_AABOX_H
-
-#include "G3D/platform.h"
-#include "G3D/Vector3.h"
-#include "G3D/debug.h"
-#include "G3D/Array.h"
-#include "G3D/Plane.h"
-
-namespace G3D {
-
-/**
- An axis-aligned box.
- */
-class AABox {
-private:
- friend class Intersect;
-
- /** Optional argument placeholder */
- static int dummy;
-
- Vector3 lo;
- Vector3 hi;
-
-public:
-
- /** Does not initialize the fields */
- inline AABox() {}
-
- /**
- Constructs a zero-area AABox at v.
- */
- inline explicit AABox(const Vector3& v) {
- lo = hi = v;
- }
-
- /** Assumes that low is less than or equal to high along each dimension.
- To have this automatically enforced, use
- <code>AABox(low.min(high), low.max(high));</code>
- */
- inline AABox(const Vector3& low, const Vector3& high) {
- set(low, high);
- }
-
- /** Assumes that low is less than or equal to high along each dimension.
- */
- inline void set(const Vector3& low, const Vector3& high) {
- debugAssert(
- (low.x <= high.x) &&
- (low.y <= high.y) &&
- (low.z <= high.z));
- lo = low;
- hi = high;
- }
-
- /**
- Grows to include the bounds of a
- */
- inline void merge(const AABox& a) {
- lo = lo.min(a.lo);
- hi = hi.max(a.hi);
- }
-
- inline void merge(const Vector3& a) {
- lo = lo.min(a);
- hi = hi.max(a);
- }
-
- void serialize(class BinaryOutput& b) const;
-
- void deserialize(class BinaryInput& b);
-
- inline bool isFinite() const {
- return lo.isFinite() && hi.isFinite();
- }
-
- inline const Vector3& low() const {
- return lo;
- }
-
- inline const Vector3& high() const {
- return hi;
- }
-
- /**
- The largest possible finite box.
- */
- static const AABox& maxFinite();
-
- /** A large finite box. This is smaller than FLT_MAX
- because it leaves room to add boxes together. */
- static const AABox& large();
-
- static const AABox& inf();
-
- static const AABox& zero();
-
- /**
- Returns the centroid of the box.
- */
- inline Vector3 center() const {
- return (lo + hi) * 0.5;
- }
-
- Vector3 corner(int index) const;
-
- /**
- Distance from corner(0) to the next corner along axis a.
- */
- inline float extent(int a) const {
- debugAssert(a < 3);
- return hi[a] - lo[a];
- }
-
-
- inline Vector3 extent() const {
- return hi - lo;
- }
-
-
- /**
- Splits the box into two AABoxes along the specified axis. low contains
- the part that was closer to negative infinity along axis, high contains
- the other part. Either may have zero volume.
- */
- void split(const Vector3::Axis& axis, float location, AABox& low, AABox& high) const;
-
- /**
- Conservative culling test for up to 32 planes.
- Returns true if there exists a <CODE>plane[p]</CODE> for
- which the entire object is in the negative half space
- (opposite the plane normal).
-
- <CODE>testMask</CODE> and <CODE>childMask</CODE>
- are used for optimizing bounding volume hierarchies.
- The version of this method that produces childMask
- is slower than the version without; it should only
- be used for parent nodes.
-
- @param cullingPlaneIndex The index of the first plane for which
- the entire object is in the negative half-space. The function
- exits early when one plane is found. -1 when the function
- returns false (i.e. when no plane culls the whole object).
-
- @param testMask If bit <I>p</I> is 0, the
- bounding volume automatically passes the culling test for
- <CODE>plane[p]</CODE> (i.e. it is known that the volume
- is entirely within the positive half space). The function
- must return false if testMask is 0 and test all planes
- when testMask is -1 (0xFFFFFFFF).
-
- @param childMask Test mask for the children of this volume.
-
- */
- bool culledBy(
- const Array<Plane>& plane,
- int32& cullingPlaneIndex,
- const uint32 testMask,
- uint32& childMask) const;
-
- /**
- Conservative culling test that does not produce a mask for children.
- */
- bool culledBy(
- const Array<Plane>& plane,
- int32& cullingPlaneIndex = dummy,
- const uint32 testMask = 0xFFFFFFFF) const;
-
- /** less than or equal to containment */
- inline bool contains(const AABox& other) const {
- return
- (other.hi.x <= hi.x) &&
- (other.hi.y <= hi.y) &&
- (other.hi.z <= hi.z) &&
- (other.lo.x >= lo.x) &&
- (other.lo.y >= lo.y) &&
- (other.lo.z >= lo.z);
- }
-
- inline bool contains(
- const Vector3& point) const {
- return
- (point.x >= lo.x) &&
- (point.y >= lo.y) &&
- (point.z >= lo.z) &&
- (point.x <= hi.x) &&
- (point.y <= hi.y) &&
- (point.z <= hi.z);
- }
-
- inline float area() const {
- Vector3 diag = hi - lo;
- return 2.0f * (diag.x * diag.y + diag.y * diag.z + diag.x * diag.z);
- }
-
- inline float volume() const {
- Vector3 diag = hi - lo;
- return diag.x * diag.y * diag.z;
- }
-
- Vector3 randomInteriorPoint() const;
-
- Vector3 randomSurfacePoint() const;
-
- /** Returns true if there is any overlap */
- bool intersects(const AABox& other) const;
-
- /** Returns true if there is any overlap.
- @cite Jim Arvo's algorithm from Graphics Gems II*/
- bool intersects(const class Sphere& other) const;
-
- /** Return the intersection of the two boxes */
- AABox intersect(const AABox& other) const {
- Vector3 H = hi.min(other.hi);
- Vector3 L = lo.max(other.lo).min(H);
- return AABox(L, H);
- }
-
- inline size_t hashCode() const {
- return lo.hashCode() + hi.hashCode();
- }
-
- inline bool operator==(const AABox& b) const {
- return (lo == b.lo) && (hi == b.hi);
- }
-
- inline bool operator!=(const AABox& b) const {
- return !((lo == b.lo) && (hi == b.hi));
- }
-
- inline AABox operator+(const Vector3& v) const {
- AABox out;
- out.lo = lo + v;
- out.hi = hi + v;
- return out;
- }
-
- inline AABox operator-(const Vector3& v) const {
- AABox out;
- out.lo = lo - v;
- out.hi = hi - v;
- return out;
- }
-
- void getBounds(AABox& out) const {
- out = *this;
- }
-};
-
-}
-
-template <> struct HashTrait<G3D::AABox> {
- static size_t hashCode(const G3D::AABox& key) { return key.hashCode(); }
-};
-
-
-
-#endif
diff --git a/externals/g3dlite/G3D/Any.h b/externals/g3dlite/G3D/Any.h
deleted file mode 100644
index 49701202ca9..00000000000
--- a/externals/g3dlite/G3D/Any.h
+++ /dev/null
@@ -1,570 +0,0 @@
-/**
- @file Any.h
-
- @author Morgan McGuire, Shawn Yarbrough, and Corey Taylor
- @maintainer Morgan McGuire
-
- @created 2006-06-11
- @edited 2009-12-16
-
- Copyright 2000-2010, Morgan McGuire.
- All rights reserved.
- */
-
-#ifndef G3D_Any_h
-#define G3D_Any_h
-
-#include "G3D/platform.h"
-#include "G3D/Table.h"
-#include "G3D/Array.h"
-#include "G3D/AtomicInt32.h"
-#include <string>
-
-// needed for Token
-#include "G3D/TextInput.h"
-
-#ifdef verify
-#undef verify
-#endif
-
-namespace G3D {
-
-class TextOutput;
-
-/**
-\brief Easy loading and saving of human-readable configuration files.
-
-Encodes typed, structured data and can serialize it to a human
-readable format that is very similar to the Python language's data
-syntax. Well-suited for quickly creating human-readable file formats,
-especially since deserialization and serialization preserve comments and
-an Any can tell you what file and line it came from.
-
-The class is designed so that copying Anys generally is fast, even if
-it is a large array or table. This is because data is shared between
-copies until it is mutated, at which point an actual copy occurs.
-
-\section Example
-Sample File:
-<pre>
-{
- shape = "round",
-
- # in meters
- radius = 3.7,
-
- position = Vector3(1.0, -1.0, 0.0),
- texture = { format = "RGB8", size = (320, 200)}
-}
-</pre>
-
-Sample code using:
-<pre>
-Any x;
-x.load("ball.txt");
-if (x["shape"].string() == "round") {
- x["density"] = 3;
-}
-x.save("ball.txt");
-</pre>
-
-The custom serialization format was chosen to be terse, easy for
-humans to read, and easy for machines to parse. It was specifically
-chosen over formats like XML, YAML, JSON, S-expressions, and Protocol
-Buffers, although there is no reason you could not write readers and
-writers for G3D::Any that support those.
-
-G3D::Any assumes that structures do not contain cycles; it is an
-error to create a structure like:
-
-<pre>
-Any x(Any::ARRAY);
-x.array().append(x); // don't do this!
-</pre>
-
-although no exception will be thrown at runtime during that append.
-
-
-\section Parsing
-
-The primary use of Any is to create your own text file formats.
-The Vector3 constructor is a good example of how to use the Any::verify
-methods to provide good error checking while parsing such formats:
-
-<pre>
-Vector3::Vector3(const Any& any) {
- any.verifyName("Vector3");
- any.verifyType(Any::TABLE, Any::ARRAY);
- any.verifySize(3);
-
- if (any.type() == Any::ARRAY) {
- x = any[0];
- y = any[1];
- z = any[2];
- } else {
- // Table
- x = any["x"];
- y = any["y"];
- z = any["z"];
- }
-}
-</pre>
-
-\section BNF
-Serialized format BNF:
-
-<pre>
-identifier ::= (letter | "_") (letter | digit | "_")*
-identifier-op ::= "::" | "->" | "."
-
-identifier-exp ::= [identifier-op] identifier (identifier-op identifier)*
-
-comment ::= "#" <any characters> "\n"
-separator ::= "," | ";"
-
-number ::= <legal C printf number format>
-string ::= <legal C double-quoted string; backslashes must be escaped>
-boolean ::= "True" | "False"
-none ::= "None"
-array ::= "(" [value ("," value)*] ")"
-pair ::= (identifier | string) "=" value
-table ::= "{" [pair (separator pair)*] "}"
-named-array ::= identifier-exp tuple
-named-table ::= identifier-exp dict
-
-value ::= [comment] (none | number | boolean | string | array | table | named-array | named-table)
-</pre>
-
-Except for single-line comments, whitespace is not significant.
-All parsing is case-insensitive.
-
-The deserializer allows the substitution of [] for () when writing
-tuples and ";" for ",".
-
-The serializer indents four spaces for each level of nesting.
-Tables are written with the keys in alphabetic order.
-*/
-class Any {
-public:
-
- enum Type {NONE, BOOLEAN, NUMBER, STRING, ARRAY, TABLE};
-
- static std::string toString(Type t);
-
- /** Where an Any came from in a file. Useful for throwing parsing errors */
- class Source {
- public:
- std::string filename;
- int line;
- int character;
-
- Source() : line(0), character(0) {}
-
- void set(const TextInput& ti, const Token& t) {
- filename = ti.filename();
- line = t.line();
- character = t.character();
- }
- };
-
- typedef Array<Any> AnyArray;
- typedef Table<std::string, Any> AnyTable;
-
-private:
-
- /** Called from deserialize() */
- static void deserializeComment(TextInput& ti, Token& token, std::string& comment);
-
- /** NONE, BOOLEAN, and NUMBER are stored directly in the Any */
- union SimpleValue {
- bool b;
- double n;
-
- inline SimpleValue() : n(0.0) {}
- inline SimpleValue(bool x) : b(x) {}
- inline SimpleValue(double x) : n(x) {}
- };
-
- class Data {
- public:
- /** ARRAY, TABLE, or STRING value only. NULL otherwise. */
- union Value {
- std::string* s;
- Array<Any>* a;
- AnyTable* t;
- inline Value() : s(NULL) {}
- };
-
- // Needed so that the destructor knows what is in Value
- // and can call its destructor.
- Type type;
-
- /** Always points to memory that is allocated with the Data, so
- the destructor does not delete this. */
- Value value;
-
- std::string comment;
-
- std::string name;
-
- /** For STRING, ARRAY and TABLE types, m_value is shared between
- multiple instances. Mutation is allowed only if the reference
- count is exactly 1, otherwise the mutating instance must copy
- the value. This is not used for other types.
- */
- AtomicInt32 referenceCount;
-
- Source source;
-
- private:
-
- /** Called by create() */
- inline Data(Type t) : type(t), referenceCount(1) {}
-
- /** Called by destroy */
- ~Data();
-
- public:
-
- /** Clones the argument */
- static Data* create(const Data* d);
- static Data* create(Type t);
-
- /** Free d, invoking its destructor and freeing the memory for
- the value. */
- static void destroy(Data* d);
-
- };
-
- /** If not empty, this Any was created from operator[] on a table
- and perhaps was not intended to exist. The name is needed to
- format the error message if it is read from before it is
- written to.
-
- The source of a placeholder object is that of the parent
- object until it is written.
- */
- std::string m_placeholderName;
-
- Type m_type;
- SimpleValue m_simpleValue;
- mutable Data* m_data;
-
- /** Called before every read operation to ensure that this object
- is not a placeholder. */
- void beforeRead() const;
-
- /** Called before every write operation to wipe the placeholder
- status. */
- void beforeWrite();
-
- /** Decrements the reference count (if there is one). If the
- reference count is zero after decrement, calls delete on @a m_data
- and sets it to NULL.
- */
- void dropReference();
-
- /** Allocate the Data object if it does not exist */
- void ensureData();
-
- /** If m_data is not NULL, ensure that it has a unique reference
- and contains a valid m_data. This has a race condition if two
- threads are both trying to modify the same Any
- simultaneously.*/
- void ensureMutable();
-
- /** Read an unnamed a TABLE or ARRAY. Token should be the open
- paren token; it is the next token after the close on
- return. Called from deserialize().*/
- void deserializeBody(TextInput& ti, Token& token);
-
- void deserialize(TextInput& ti, Token& token);
-
- /** Read the name of a named Array or Table. */
- static void deserializeName(TextInput& ti, Token& token, std::string& name);
-
- /** Read until a comma is consumed or a close paren is hit, and
- return that token. Considers the passed in token to be the first
- value read. */
- static void readUntilCommaOrClose(TextInput& ti, Token& token);
-
- /** Construct an Any that is a proxy for a table fetch from \a data.
- This proxy can be copied exactly once on return from operator[].*/
- Any(const std::string& key, Data* data);
-
- inline bool isPlaceholder() const {
- return ! m_placeholderName.empty();
- }
-
-public:
-
- /** Base class for all Any exceptions.*/
- class Exception {
- public:
- virtual ~Exception() {}
- };
-
- /** Thrown by operator[] when a key is not present in a const table. */
- class KeyNotFound : public ParseError {
- public:
- std::string key;
- };
-
- /** Thrown by operator[] when an array index is not present. */
- class IndexOutOfBounds : public Exception {
- public:
- int index;
- int size;
- inline IndexOutOfBounds() : index(0), size(0) {}
- inline IndexOutOfBounds(int i, int s) : index(i), size(s) {}
- };
-
- /** NONE constructor */
- Any();
-
- /** Deserialize */
- explicit Any(TextInput& t);
-
- Any(const Any& x);
-
- /** NUMBER constructor */
- Any(double x);
-
-#ifdef G3D_32BIT
- /** NUMBER constructor */
- Any(int64 x);
-#endif // G3D_32BIT
-
-#if 0
- /** NUMBER constructor */
- Any(int32 x);
-#endif // 0
-
- /** NUMBER constructor */
- Any(long x);
-
- /** NUMBER constructor */
- Any(int x);
-
- /** NUMBER constructor */
- Any(short x);
-
- /** BOOLEAN constructor */
- Any(bool x);
-
- /** STRING constructor */
- Any(const std::string& x);
-
- /** STRING constructor */
- Any(const char* x);
-
- /** \a t must be ARRAY or TABLE */
- Any(Type t, const std::string& name = "");
-
- ~Any();
-
- /** Removes the comment and name */
- Any& operator=(const Any& x);
-
- /** Removes the comment and name */
- Any& operator=(double x);
-
- /** Removes the comment and name */
- Any& operator=(int x);
-
- /** Removes the comment and name */
- Any& operator=(bool x);
-
- /** Removes the comment and name */
- Any& operator=(const std::string& x);
-
- /** Removes the comment and name */
- Any& operator=(const char* x);
-
- /** \a t must be ARRAY, TABLE, or NONE. Removes the comment and name */
- Any& operator=(Type t);
-
- Type type() const;
-
- /** Same as deserialize or load, but operates on a string instead
- of a stream or file.
-
- \sa deserialize, load
- */
- void parse(const std::string& src);
-
- std::string unparse() const;
-
- /** Comments appear before values when they are in serialized form.*/
- const std::string& comment() const;
- void setComment(const std::string& c);
-
- /** True if this is the NONE value */
- bool isNone() const;
-
- /** Throws a ParseError exception if this is not a number */
- double number() const;
- const std::string& string() const;
- bool boolean() const;
-
- /** If this is named ARRAY or TABLE, returns the name. */
- const std::string& name() const;
-
- /** \brief Set the name used when serializing an ARRAY or TABLE.
-
- Only legal for ARRAY or TABLE. The \a name must begin with a letter
- and contain only letters, numbers, underscores and scope operators.
-
- <pre>
- a2z
- hello
- Foo::bar
- color.red
- this->that
- __x
- </pre>
-
-
- The scope operators "::", "->", and
- ".", may have spaces around them. The name may not
- contain parentheses.
- */
- void setName(const std::string& name);
-
- /** Number of elements if this is an ARRAY or TABLE */
- int size() const;
- int length() const;
-
- /** For an array, returns the ith element */
- const Any& operator[](int i) const;
- Any& operator[](int i);
-
- /** Directly exposes the underlying data structure for an ARRAY. */
- const Array<Any>& array() const;
- void append(const Any& v0);
- void append(const Any& v0, const Any& v1);
- void append(const Any& v0, const Any& v1, const Any& v2);
- void append(const Any& v0, const Any& v1, const Any& v2, const Any& v3);
-
- /** Directly exposes the underlying data structure for table.*/
- const Table<std::string, Any>& table() const;
-
- /** For a table, returns the element for \a key. Throws KeyNotFound
- exception if the element does not exist.
- */
- const Any& operator[](const std::string& key) const;
-
- // Needed to prevent the operator[](int) overload from catching
- // string literals
- inline const Any& operator[](const char* key) const {
- return operator[](std::string(key));
- }
-
- /**
- Fetch an element from a table. This can be used as:
-
- <pre>
- a["key"] = value; (create the key if it did not exist)
- </pre>
-
- or
-
- <pre>
- value = a["key"]; (throw an error if the key did not exist)
- </pre>
-
- <b>Note:</b>
- In order to cause elements to be correctly created in the
- first case while still providing "key not found" errors in the
- second case, the Any returned is a special object that delays
- the actual fetch until the following assignment or method
- call. This means that in the event of an error, the exception
- may be thrown from a line other than the actual fetch. Use
- the Any::get() or the const Any::operator[]() methods to avoid
- this behavior and ensure error-checking at fetch time.
- */
- Any& operator[](const std::string& key);
-
- /** \copydoc Any::operator[](const std::string&) */
- inline Any& operator[](const char* key) {
- return operator[](std::string(key));
- }
-
- /** For a table, returns the element for key \a x and \a
- defaultVal if it does not exist. */
- const Any& get(const std::string& key, const Any& defaultVal) const;
-
- /** Returns true if this key is in the TABLE. Illegal to call on an object that is not a TABLE. */
- bool containsKey(const std::string& key) const;
-
- /** For a table, assigns the element for key k. */
- void set(const std::string& key, const Any& val);
-
- /** for an ARRAY, resizes and returns the last element */
- Any& next();
-
-
- /** True if the Anys are exactly equal, ignoring comments. Applies deeply on arrays and tables. */
- bool operator==(const Any& x) const;
- bool operator!=(const Any& x) const;
-
- operator int() const;
- operator float() const;
- operator double() const;
- operator bool() const;
- operator std::string() const;
-
- /** Resize to \a n elements, where new elements are NIL
- It is an error to call this method if this is not an Any::ARRAY */
- void resize(int n);
-
- /**
- Clears all entries.
- This must be a TABLE or ARRAY */
- void clear();
-
- /** Parse from a file.
- \sa deserialize, parse */
- void load(const std::string& filename);
-
- /** Uses the serialize method. */
- void save(const std::string& filename) const;
-
- void serialize(TextOutput& to) const;
- /** Parse from a stream.
- \sa load, parse */
- void deserialize(TextInput& ti);
-
- const Source& source() const;
-
- /** Throws a ParseError if \a value is false. Useful for quickly
- creating parse rules in classes that deserialize from Any.
- */
- void verify(bool value, const std::string& message = "") const;
-
- /** Verifies that the name begins with identifier \a n. It may contain
- identifier operators after this */
- void verifyName(const std::string& n) const;
-
- /** Verifies that the type is \a t. */
- void verifyType(Type t) const;
-
- /** Throws an exception if the type is not \a t0 or \a t1. */
- void verifyType(Type t0, Type t1) const;
-
- /** Verifies that the size is between \a low and \a high, inclusive */
- void verifySize(int low, int high) const;
-
- /** Verifies that the size is exactly \a s */
- void verifySize(int s) const;
-
-private:
-
- void deserializeTable(TextInput& ti);
- void deserializeArray(TextInput& ti,const std::string& term);
-
-}; // class Any
-
-} // namespace G3D
-
-#endif
diff --git a/externals/g3dlite/G3D/AnyVal.h b/externals/g3dlite/G3D/AnyVal.h
deleted file mode 100644
index 8c1bc72f206..00000000000
--- a/externals/g3dlite/G3D/AnyVal.h
+++ /dev/null
@@ -1,512 +0,0 @@
-/**
- @file AnyVal.h
- @author Morgan McGuire
- @created 2006-06-11
- @edited 2008-07-14
- */
-
-#ifndef G3D_ANYVAL_H
-#define G3D_ANYVAL_H
-
-#include "G3D/platform.h"
-#include <string>
-#include "G3D/Array.h"
-#include "G3D/TextInput.h"
-
-namespace G3D {
-// Forward declarations for G3D types
-class Vector2;
-class Vector3;
-class Vector4;
-class Color1;
-class Color3;
-class Color4;
-class Quat;
-class Matrix2;
-class Matrix3;
-class Matrix4;
-class CoordinateFrame;
-class TextInput;
-class TextOutput;
-class BinaryInput;
-class BinaryOutput;
-class Rect2D;
-class AABox;
-
-/**
- \deprecated
- <b>Use the G3D::Any class instead. This is only provided for
- backwards compatibility to G3D 7.xx.</b>
-
- A generic value, useful for defining property trees that can
- be loaded from and saved to disk. The values are intentionally
- restricted to a small set.
-
- When written to files, the syntax is as follows. Note that you can
- nest arrays and tables in order to create full tree (i.e., XML-like)
- structures as configuration files:
-
- <table>
- <tr><td>NULL</td><td><code>Nil</code></td></tr>
- <tr><td>double</td><td><i>The number in printf double format</i></td></tr>
- <tr><td>bool</td><td><code>true</code> <i>or</i> <code>false</code></td></tr>
- <tr><td>std::string</td><td><i>The string in double-quotes (</i><code>"</code><i>)</i></td></tr>
- <tr><td>Rect2D</td><td><code>R(</code><i>x<sub>0</sub></i><code>,</code><i>y<sub>0</sub></i><code>,</code><i>x<sub>1</sub></i><code>,</code><i>y<sub>1</sub></i><code>)</code></td></tr>
- <tr><td>Color1</td><td><code>C1(</code><i>value</i><code>)</code></td></tr>
- <tr><td>Color3</td><td><code>C3(</code><i>r</i><code>,</code><i>g</i><code>,</code><i>b</i><code>)</code></td></tr>
- <tr><td>Color4</td><td><code>C4(</code><i>r</i><code>,</code><i>g</i><code>,</code><i>b</i><code>,</code><i>a</i><code>)</code></td></tr>
- <tr><td>Vector2</td><td><code>V2(</code><i>x</i><code>,</code><i>y</i><code>)</code></td></tr>
- <tr><td>Vector3</td><td><code>V3(</code><i>x</i><code>,</code><i>y</i><code>,</code><i>z</i><code>)</code></td></tr>
- <tr><td>Vector4</td><td><code>V4(</code><i>x</i><code>,</code><i>y</i><code>,</code><i>z</i><code>,</code><i>w</i><code>)</code></td></tr>
- <tr><td>Quat</td><td><code>V(</code>x<code>,</code>y<code>,</code>z<code>,</code>w<code>)</code></td></tr>
- <tr><td>AABox</td><td><code>AAB(</code>low Vector3<code>, </code>high Vector3<code>)</code></td></tr>
- <tr><td>Matrix2</td><td><code>M2(</code>r0c0<code>, </code>r0c1<code>,
- <br>&nbsp;&nbsp;&nbsp;</code>r1c0<code>, </code>r1c1<code>)</code></td></tr>
- <tr><td>Matrix3</td><td><code>M3(</code>r0c0<code>, </code>r0c1<code>, </code>r0c2<code>,
- <br>&nbsp;&nbsp;&nbsp;</code>r1c0<code>, </code>r1c1<code>, </code>r1c2<code>,
- <br>&nbsp;&nbsp;&nbsp;</code>r2c0<code>, </code>r2c1<code>, </code>r2c2<code>)</code></td></tr>
- <tr><td>Matrix4</td><td><code>M4(</code>r0c0<code>, </code>r0c1<code>, </code>r0c2<code>, </code>r0c3<code>,
- <br>&nbsp;&nbsp;&nbsp;</code>r1c0<code>, </code>r1c1<code>, </code>r1c2<code>, </code>r1c3<code>,
- <br>&nbsp;&nbsp;&nbsp;</code>r2c0<code>, </code>r2c1<code>, </code>r2c2<code>, </code>r2c3<code>,
- <br>&nbsp;&nbsp;&nbsp;</code>r3c0<code>, </code>r3c1<code>, </code>r3c2<code>, </code>r3c3<code>)</code></td></tr>
- <tr><td>CoordinateFrame</td><td><code>CF(</code>r0c0<code>, </code>r0c1<code>, </code>r0c2<code>, </code>r0c3<code>,
- <br>&nbsp;&nbsp;&nbsp;</code>r1c0<code>, </code>r1c1<code>, </code>r1c2<code>, </code>r1c3<code>,
- <br>&nbsp;&nbsp;&nbsp;</code>r2c0<code>, </code>r2c1<code>, </code>r2c2<code>, </code>r2c3<code>)</code></td></tr>
- <tr><td>CoordinateFrame</td><td><code>CF(V3(</code><i>x</i><code>, </code><i>y</i><code>, </code><i>z</i><code>), </code><i>yaw deg</i><code>, </code><i>pitch deg</i><code>, </code><i>optional roll deg</i><code>)</code></td></tr>
-
- <tr><td>Array</td><td><code>[</code><i>element<sub>0</sub></i><code>, </code><i>element<sub>1</sub></i><code>, </code> ... <code>, </code><i>element<sub>n-1</sub></i><code>]</code></td></tr>
- <tr><td>Table</td><td><code>{</code><i>symbol<sub>0</sub></i><code> = </code><i>value<sub>0</sub></i>
- <br><code>&nbsp;</code><i>symbol<sub>1</sub></i><code> = </code><i>value<sub>1</sub></i>
- <br><code>&nbsp;</code>...
- <br><code>&nbsp;</code><i>symbol<sub>n-1</sub></i><code> = </code><i>value<sub>n-1</sub></i><code>}</code></td></tr>
- </table>
-
- See also boost::any for a more general purpose but slightly harder to use
- "any" for C++.
-
- The semantics of operator[] and the get() methods are slightly different;
- operator[] acts more like a scripting language that automatically extends
- arrays and tables instead of generating errors. get() has more strict semantics,
- like a C++ class.
-
- AnyVal uses copy-on-mutate, so that <code>AnyVal a = b</code> semantically copies <code>b</code> (like <code>int a = b</code> would), although in practice
- it delays the copy until one is mutated so that it is still fast to "copy" large arrays and tables.
-
- Reading example:
- <pre>
- AnyVal property = AnyVal::fromFile("c:/tmp/test.txt"));
-
- Vector3 vel = property["angular velocity"]
-
- <i>Using defaults to handle errors:
- If there was no "enabled" value, this will return the default instead of failing</i>
- bool enabled = property["enabled"].boolean(true);
-
- </pre>
-
- Writing to a file:
- <pre>
- AnyVal dict(AnyVal::TABLE);
-
- dict["enabled"] = AnyVal(true);
- dict["weight"] = 100;
- dict["angular velocity"] = Vector3(1, -3, 4.5);
-
- TextOutput t("c:/tmp/test.txt");
- dict.serialize(t);
- t.commit();
- </pre>
-
- Example of a data file:
- <pre>
- {
- heights = [1, 17, 32]
- model =
- {
- color = C3(1, 1, 1)
- filename = "foo.md2"
- }
- position = V3(23, 14, 0)
- name = "Elmer"
- }
- </pre>
-
- <p>
- <b>What's the difference from boost::any?</b>
- <br>I think that AnyVal will be easier for novice C++ users. It addresses the problem that
- even though G3D::TextInput makes reading configuration files extremely simple, many people
- still don't use it. So AnyVal makes it ridiculously simple to read and write a tree of G3D
- types to a file.
-
- <i>AnyVal:</i>
-<pre>
-{
-AnyVal tree(TextInput("config.txt"));
-
-bool enabled = tree.get("enabled", false);
-Vector3 direction = tree.get("direction", Vector3::zero());
-...
-}
-</pre>
-
-<i>boost:</i>
-<pre>
-{
-bool enabled = false;
-Vector3 direction;
-Table<boost::any> tree;
-
- ...write lots of file parsing code...
-
- if (tree.containsKey("enabled")) {
- const boost::any& val = tree["enabled"];
- try {
- enabled = any_cast<bool>(val);
- } catch(const boost::bad_any_cast &) {
- }
- }
-
- if (tree.containsKey("direction")) {
- const boost::any& val = tree["direction"];
- try {
- direction = any_cast<Vector3>(val);
- } catch(const boost::bad_any_cast &) {
- }
- }
- ...
-}
-</pre>
-
-\deprecated
- */
-class AnyVal {
-public:
-
- /** Array and table values are all Any.*/
- enum Type {
- NIL,
- NUMBER,
- BOOLEAN,
- STRING,
- VECTOR2,
- VECTOR3,
- VECTOR4,
- MATRIX2,
- MATRIX3,
- MATRIX4,
- QUAT,
- COORDINATEFRAME,
- COORDINATEFRAME2D,
- CFRAME = COORDINATEFRAME,
- CFRAME2D = COORDINATEFRAME2D,
- COLOR1,
- COLOR3,
- COLOR4,
- RECT2D,
- AABOX2D = RECT2D,
- AABOX,
- ARRAY,
- TABLE};
-
- /** Base class for all AnyVal exceptions.*/
- class Exception {
- public:
- virtual ~Exception() {}
- };
-
- /** Thrown when an inappropriate operation is performed (e.g., operator[] on a number) */
- class WrongType : public Exception {
- public:
- Type expected;
- Type actual;
- WrongType() : expected(NIL), actual(NIL) {}
- WrongType(Type e, Type a) : expected(e), actual(a) {}
- };
-
- /** Thrown by operator[] when a key is not present. */
- class KeyNotFound : public Exception {
- public:
- std::string key;
- KeyNotFound() {}
- KeyNotFound(const std::string& k) : key(k) {}
- };
-
- class IndexOutOfBounds : public Exception {
- public:
- int index;
- int size;
- IndexOutOfBounds() : index(0), size(0) {}
- IndexOutOfBounds(int i, int s) : index(i), size(s) {}
- };
-
- /** Thrown when deserialize() when the input is incorrectly formatted. */
- class CorruptText : public Exception {
- public:
- std::string message;
-
- /** Token where the problem occurred.*/
- G3D::Token token;
-
- CorruptText() {}
- CorruptText(const std::string& s, const G3D::Token& t) : message(s), token(t) {}
- };
-
-private:
-
- Type m_type;
- void* m_value;
-
- /** For table and array types, *m_value is shared between multiple
- instances. Mutation is allowed only if the reference count is
- exactly 1, otherwise the mutating instance must copy the
- value. This is not used for other types.
- */
- int* m_referenceCount;
-
- /** Decrements the reference count (if there is one). If the
- reference count is zero or does not exist. Calls delete on @a
- m_value and sets it to NULL.
- */
- void deleteValue();
-
- /** Returns a copy of the value. */
- void* copyValue() const;
-
- /** Assumes isSharedType. Ensures that this has a unique reference */
- void makeMutable();
-
- /** True if this is a shared value between multiple instances. */
- inline bool isShared() const {
- return m_referenceCount && (*m_referenceCount > 1);
- }
-
- /** True when m_value is a double pointer */
- inline bool isSharedType() const {
- return (m_type == TABLE) || (m_type == ARRAY);
- }
-
-public:
-
- AnyVal();
-
- /** Deserialize */
- explicit AnyVal(G3D::TextInput& t);
-
- static AnyVal fromFile(const std::string& filename);
-
- void load(const std::string& filename);
-
- void save(const std::string& filename) const;
-
- ///** Deserialize */
- //explicit AnyVal(G3D::BinaryInput& t);
-
- /** Construct a number */
- AnyVal(double);
- AnyVal(int);
-
- // Explicit to avoid ambiguity with the 'double' constructor
- // when an integer type is constructed
- AnyVal(bool);
- AnyVal(const G3D::Vector2&);
- AnyVal(const G3D::Vector3&);
- AnyVal(const G3D::Vector4&);
-
- AnyVal(const G3D::Color1&);
- AnyVal(const G3D::Color3&);
- AnyVal(const G3D::Color4&);
-
- AnyVal(const std::string&);
- AnyVal(const char*);
-
- AnyVal(const G3D::Quat&);
-
- AnyVal(const G3D::Rect2D&);
- AnyVal(const G3D::AABox&);
-
- AnyVal(const G3D::CoordinateFrame&);
- AnyVal(const G3D::Matrix2&);
- AnyVal(const G3D::Matrix3&);
- AnyVal(const G3D::Matrix4&);
-
- AnyVal(const AnyVal&);
-
- AnyVal(Type arrayOrTable);
-
- AnyVal& operator=(const AnyVal&);
-
- /** Frees the underlying storage */
- ~AnyVal();
-
- Type type() const;
-
- bool isNil() const {
- return type() == NIL;
- }
-
- void serialize(G3D::TextOutput& t) const;
- //void serialize(G3D::BinaryOutput& t) const;
- void deserialize(G3D::TextInput& t);
- //void deserialize(G3D::BinaryInput& t);
-
- /** Array dereference. If the index is out of bounds, IndexOutOfBounds is thrown */
- const AnyVal& operator[](int) const;
-
- /** Extend this array by one element. */
- void append(const AnyVal&);
-
- /** If the index is out of bounds, the array is resized. If the index is negative,
- IndexOutOfBounds is thrown.*/
- AnyVal& operator[](int);
-
- /** If @a i is out of bounds or this is not an ARRAY, defaultVal is returned.*/
- const AnyVal& get(int i, const AnyVal& defaultVal) const;
-
- /** If out of bounds, IndexOutOfBounds is thrown. */
- const AnyVal& get(int i) const;
-
- /** Returns defaultVal if this is not a TABLE or the key is not found. */
- const AnyVal& get(const std::string& key, const AnyVal& defaultVal) const;
-
- /** Throws KeyNotFound exception if the key is not present.*/
- const AnyVal& get(const std::string& key) const;
-
- /** Table reference */
- const AnyVal& operator[](const std::string&) const;
-
- /** Table reference. If the element does not exist, it is created. */
- AnyVal& operator[](const std::string&);
-
- /** Table reference */
- const AnyVal& operator[](const char*) const;
-
- /** Table reference. If the element does not exist, it is created. */
- AnyVal& operator[](const char*);
-
- /** If this value is not a number throws a WrongType exception. */
- double number() const;
-
- /** If this value is not a number, returns defaultVal. */
- double number(double defaultVal) const;
-
- operator double () const {
- return number();
- }
-
- operator float () const {
- return (float)number();
- }
-
- bool boolean() const;
- bool boolean(bool b) const;
-
- operator bool() const {
- return boolean();
- }
-
- const std::string& string() const;
- const std::string& string(const std::string& defaultVal) const;
-
- operator const std::string& () const {
- return string();
- }
-
- const G3D::Rect2D& rect2D() const;
- const G3D::Rect2D& rect2D(const G3D::Rect2D& defaultVal) const;
-
- operator const Rect2D& () const {
- return rect2D();
- }
-
- const G3D::AABox& aabox() const;
- const G3D::AABox& aabox(const G3D::AABox& defaultVal) const;
-
- operator const AABox& () const {
- return aabox();
- }
-
- const G3D::Vector2& vector2() const;
- const G3D::Vector2& vector2(const G3D::Vector2& defaultVal) const;
-
- operator const Vector2& () const {
- return vector2();
- }
-
- const G3D::Vector3& vector3() const;
- const G3D::Vector3& vector3(const G3D::Vector3& defaultVal) const;
-
- operator const Vector3& () {
- return vector3();
- }
-
- const G3D::Vector4& vector4() const;
- const G3D::Vector4& vector4(const G3D::Vector4& defaultVal) const;
-
- operator const Vector4& () const {
- return vector4();
- }
-
- const G3D::Color1& color1() const;
- const G3D::Color1& color1(const G3D::Color1& defaultVal) const;
-
- const G3D::Color3& color3() const;
- const G3D::Color3& color3(const G3D::Color3& defaultVal) const;
-
- operator const Color3& () const {
- return color3();
- }
-
- const G3D::Color4& color4() const;
- const G3D::Color4& color4(const G3D::Color4& defaultVal) const;
-
- operator const Color4& () const {
- return color4();
- }
-
- const G3D::CoordinateFrame& coordinateFrame() const;
- const G3D::CoordinateFrame& coordinateFrame(const G3D::CoordinateFrame& defaultVal) const;
-
- operator const CoordinateFrame& () const {
- return coordinateFrame();
- }
-
- const G3D::Matrix2& matrix2() const;
- const G3D::Matrix2& matrix2(const G3D::Matrix2& defaultVal) const;
-
- operator const Matrix2& () const {
- return matrix2();
- }
-
- const G3D::Matrix3& matrix3() const;
- const G3D::Matrix3& matrix3(const G3D::Matrix3& defaultVal) const;
-
- operator const Matrix3& () const {
- return matrix3();
- }
-
- const G3D::Matrix4& matrix4() const;
- const G3D::Matrix4& matrix4(const G3D::Matrix4& defaultVal) const;
-
- operator const Matrix4& () const {
- return matrix4();
- }
-
- const G3D::Quat& quat() const;
- const G3D::Quat& quat(const G3D::Quat& defaultVal) const;
-
- operator const Quat& () const {
- return quat();
- }
-
- std::string toString() const;
-
- /** Number of elements for an array or table.*/
- int size() const;
-
- /** For a table, returns the keys. */
- void getKeys(G3D::Array<std::string>&) const;
-};
-
-}
-
-#endif
diff --git a/externals/g3dlite/G3D/AreaMemoryManager.h b/externals/g3dlite/G3D/AreaMemoryManager.h
deleted file mode 100644
index d8d8f710359..00000000000
--- a/externals/g3dlite/G3D/AreaMemoryManager.h
+++ /dev/null
@@ -1,93 +0,0 @@
-/**
- @file AreaMemoryManager.h
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2009-01-20
- @edited 2009-05-29
-
- Copyright 2000-2009, Morgan McGuire.
- All rights reserved.
- */
-
-
-#ifndef G3D_AreaMemoryManager_h
-#define G3D_AreaMemoryManager_h
-
-#include "G3D/platform.h"
-#include "G3D/g3dmath.h"
-#include "G3D/Array.h"
-#include "G3D/MemoryManager.h"
-
-namespace G3D {
-
-/**
- \brief Allocates memory in large blocks and then frees it as an area.
-
- Useful for ensuring cache coherence and for reducing the time cost of
- multiple allocations and deallocations.
-
- <b>Not threadsafe</b>
- */
-class AreaMemoryManager : public MemoryManager {
-private:
-
- class Buffer {
- private:
- uint8* m_first;
- size_t m_size;
- size_t m_used;
-
- public:
-
- Buffer(size_t size);
-
- ~Buffer();
-
- /** Returns NULL if out of space */
- void* alloc(size_t s);
- };
-
- size_t m_sizeHint;
-
- /** The underlying array is stored in regular MemoryManager heap memory */
- Array<Buffer*> m_bufferArray;
-
- AreaMemoryManager(size_t sizeHint);
-
-public:
-
- typedef ReferenceCountedPointer<AreaMemoryManager> Ref;
-
- /**
- \param sizeHint Total amount of memory expected to be allocated.
- The allocator will allocate memory from the system in increments
- of this size.
- */
- static AreaMemoryManager::Ref create(size_t sizeHint = 10 * 1024 * 1024);
-
- /** Invokes deallocateAll. */
- ~AreaMemoryManager();
-
- size_t bytesAllocated() const;
-
- /** Allocates memory out of the buffer pool.
- @param s must be no larger than sizeHint */
- virtual void* alloc(size_t s);
-
- /** Ignored. */
- virtual void free(void* x);
-
- virtual bool isThreadsafe() const;
-
- /** Deletes all previously allocated memory. Because delete is not
- invoked on objects in this memory, it is not safe to simply
- free memory containing C++ objects that expect their destructors
- to be called. */
- void deallocateAll();
-};
-
-typedef AreaMemoryManager CoherentAllocator;
-}
-
-#endif
diff --git a/externals/g3dlite/G3D/Array.h b/externals/g3dlite/G3D/Array.h
deleted file mode 100644
index cc9e1d9dd01..00000000000
--- a/externals/g3dlite/G3D/Array.h
+++ /dev/null
@@ -1,1274 +0,0 @@
-/**
- @file Array.h
-
- @maintainer Morgan McGuire, graphics3d.com
- @cite Portions written by Aaron Orenstein, a@orenstein.name
-
- @created 2001-03-11
- @edited 2009-05-29
-
- Copyright 2000-2009, Morgan McGuire, http://graphics.cs.williams.edu
- All rights reserved.
- */
-
-#ifndef G3D_Array_h
-#define G3D_Array_h
-
-#include "G3D/platform.h"
-#include "G3D/debug.h"
-#include "G3D/System.h"
-#include "G3D/MemoryManager.h"
-#ifdef G3D_DEBUG
-// For formatting error messages
-# include "G3D/format.h"
-#endif
-#include <vector>
-#include <algorithm>
-
-#ifdef _MSC_VER
-# include <new>
-
-# pragma warning (push)
- // debug information too long
-# pragma warning( disable : 4312)
-# pragma warning( disable : 4786)
-#endif
-
-
-namespace G3D {
-
-/**
- Constant for passing to Array::resize
- */
-const bool DONT_SHRINK_UNDERLYING_ARRAY = false;
-
-/** Constant for Array::sort */
-const int SORT_INCREASING = 1;
-/** Constant for Array::sort */
-const int SORT_DECREASING = -1;
-
-/**
- \brief Dynamic 1D array tuned for performance.
-
- Objects must have a default constructor (constructor that
- takes no arguments) in order to be used with this template.
- You will get the error "no appropriate default constructor found"
- if they do not.
-
- Do not use with objects that overload placement <code>operator new</code>,
- since the speed of Array is partly due to pooled allocation.
-
- Array is highly optimized compared to std::vector.
- Array operations are less expensive than on std::vector and for large
- amounts of data, Array consumes only 1.5x the total size of the
- data, while std::vector consumes 2.0x. The default
- array takes up zero heap space. The first resize (or append)
- operation grows it to a reasonable internal size so it is efficient
- to append to small arrays.
-
- Then Array needs to copy
- data internally on a resize operation it correctly invokes copy
- constructors of the elements (the MSVC6 implementation of
- std::vector uses realloc, which can create memory leaks for classes
- containing references and pointers). Array provides a guaranteed
- safe way to access the underlying data as a flat C array --
- Array::getCArray. Although (T*)std::vector::begin() can be used for
- this purpose, it is not guaranteed to succeed on all platforms.
-
- To serialize an array, see G3D::serialize.
-
- The template parameter MIN_ELEMENTS indicates the smallest number of
- elements that will be allocated. The default of 10 is designed to avoid
- the overhead of repeatedly allocating the array as it grows from 1, to 2, and so on.
- If you are creating a lot of small Arrays, however, you may want to set this smaller
- to reduce the memory cost. Once the array has been allocated, it will never
- deallocate the underlying array unless MIN_ELEMENTS is set to 0, MIN_BYTES is 0, and the array
- is empty.
-
- Do not subclass an Array.
-
- \sa G3D::SmallArray
- */
-template <class T, int MIN_ELEMENTS = 10, size_t MIN_BYTES = 32>
-class Array {
-private:
- /** 0...num-1 are initialized elements, num...numAllocated-1 are not */
- T* data;
-
- int num;
- int numAllocated;
-
- MemoryManager::Ref m_memoryManager;
-
- /** \param n Number of elements
- */
- void init(int n, const MemoryManager::Ref& m) {
- m_memoryManager = m;
- debugAssert(n >= 0);
- this->num = 0;
- this->numAllocated = 0;
- data = NULL;
- if (n > 0) {
- resize(n);
- } else {
- data = NULL;
- }
- }
-
- void _copy(const Array &other) {
- init(other.num, MemoryManager::create());
- for (int i = 0; i < num; i++) {
- data[i] = other.data[i];
- }
- }
-
- /**
- Returns true iff address points to an element of this array.
- Used by append.
- */
- inline bool inArray(const T* address) {
- return (address >= data) && (address < data + num);
- }
-
-
- /** Only compiled if you use the sort procedure. */
- static bool __cdecl compareGT(const T& a, const T& b) {
- return a > b;
- }
-
-
- /**
- Allocates a new array of size numAllocated (not a parameter to the method)
- and then copies at most oldNum elements from the old array to it. Destructors are
- called for oldNum elements of the old array.
- */
- void realloc(int oldNum) {
- T* oldData = data;
-
- // The allocation is separate from the constructor invocation because we don't want
- // to pay for the cost of constructors until the newly allocated
- // elements are actually revealed to the application. They
- // will be constructed in the resize() method.
-
- data = (T*)m_memoryManager->alloc(sizeof(T) * numAllocated);
- alwaysAssertM(data, "Memory manager returned NULL: out of memory?");
-
- // Call the copy constructors
- {const int N = G3D::min(oldNum, numAllocated);
- const T* end = data + N;
- T* oldPtr = oldData;
- for (T* ptr = data; ptr < end; ++ptr, ++oldPtr) {
-
- // Use placement new to invoke the constructor at the location
- // that we determined. Use the copy constructor to make the assignment.
- const T* constructed = new (ptr) T(*oldPtr);
-
- (void)constructed;
- debugAssertM(constructed == ptr,
- "new returned a different address than the one provided by Array.");
- }}
-
- // Call destructors on the old array (if there is no destructor, this will compile away)
- {const T* end = oldData + oldNum;
- for (T* ptr = oldData; ptr < end; ++ptr) {
- ptr->~T();
- }}
-
- m_memoryManager->free(oldData);
- }
-
-public:
-
- /**
- G3D C++ STL style iterator variable. Call begin() to get
- the first iterator, pre-increment (++i) the iterator to get to
- the next value. Use dereference (*i) to access the element.
- */
- typedef T* Iterator;
- /** G3D C++ STL style const iterator in same style as Iterator. */
- typedef const T* ConstIterator;
-
- /** stl porting compatibility helper */
- typedef Iterator iterator;
- /** stl porting compatibility helper */
- typedef ConstIterator const_iterator;
- /** stl porting compatibility helper */
- typedef T value_type;
- /** stl porting compatibility helper */
- typedef int size_type;
- /** stl porting compatibility helper */
- typedef int difference_type;
-
- /**
- C++ STL style iterator method. Returns the first iterator element.
- Do not change the size of the array while iterating.
- */
- Iterator begin() {
- return data;
- }
-
- ConstIterator begin() const {
- return data;
- }
- /**
- C++ STL style iterator method. Returns one after the last iterator
- element.
- */
- ConstIterator end() const {
- return data + num;
- }
-
- Iterator end() {
- return data + num;
- }
-
- /**
- The array returned is only valid until the next append() or resize call, or
- the Array is deallocated.
- */
- T* getCArray() {
- return data;
- }
-
- /**
- The array returned is only valid until the next append() or resize call, or
- the Array is deallocated.
- */
- const T* getCArray() const {
- return data;
- }
-
- /** Creates a zero length array (no heap allocation occurs until resize). */
- Array() : num(0) {
- init(0, MemoryManager::create());
- debugAssert(num >= 0);
- }
-
-
- /** Creates an array containing v0. */
- Array(const T& v0) {
- init(1, MemoryManager::create());
- (*this)[0] = v0;
- }
-
- /** Creates an array containing v0 and v1. */
- Array(const T& v0, const T& v1) {
- init(2, MemoryManager::create());
- (*this)[0] = v0;
- (*this)[1] = v1;
- }
-
- /** Creates an array containing v0...v2. */
- Array(const T& v0, const T& v1, const T& v2) {
- init(3, MemoryManager::create());
- (*this)[0] = v0;
- (*this)[1] = v1;
- (*this)[2] = v2;
- }
-
- /** Creates an array containing v0...v3. */
- Array(const T& v0, const T& v1, const T& v2, const T& v3) {
- init(4, MemoryManager::create());
- (*this)[0] = v0;
- (*this)[1] = v1;
- (*this)[2] = v2;
- (*this)[3] = v3;
- }
-
- /** Creates an array containing v0...v4. */
- Array(const T& v0, const T& v1, const T& v2, const T& v3, const T& v4) {
- init(5, MemoryManager::create());
- (*this)[0] = v0;
- (*this)[1] = v1;
- (*this)[2] = v2;
- (*this)[3] = v3;
- (*this)[4] = v4;
- }
-
-
- /**
- Copy constructor
- */
- Array(const Array& other) : num(0) {
- _copy(other);
- debugAssert(num >= 0);
- }
-
- /**
- Destructor does not delete() the objects if T is a pointer type
- (e.g. T = int*) instead, it deletes the <B>pointers themselves</B> and
- leaves the objects. Call deleteAll if you want to dealocate
- the objects referenced. Do not call deleteAll if <CODE>T</CODE> is not a pointer
- type (e.g. do call Array<Foo*>::deleteAll, do <B>not</B> call Array<Foo>::deleteAll).
- */
- ~Array() {
- // Invoke the destructors on the elements
- for (int i = 0; i < num; i++) {
- (data + i)->~T();
- }
-
- m_memoryManager->free(data);
- // Set to 0 in case this Array is global and gets referenced during app exit
- data = NULL;
- num = 0;
- numAllocated = 0;
- }
-
- /**
- Removes all elements. Use resize(0, false) or fastClear if you want to
- remove all elements without deallocating the underlying array
- so that future append() calls will be faster.
- */
- void clear(bool shrink = true) {
- resize(0, shrink);
- }
-
- void clearAndSetMemoryManager(const MemoryManager::Ref& m) {
- clear();
- debugAssert(data == NULL);
- m_memoryManager = m;
- }
-
- /** resize(0, false)
- @deprecated*/
- void fastClear() {
- clear(false);
- }
-
- /**
- Assignment operator.
- */
- Array& operator=(const Array& other) {
- debugAssert(num >= 0);
- resize(other.num); for (int i = 0; i < num; ++i) {
- data[i] = other[i];
- }
- debugAssert(num >= 0);
- return *this;
- }
-
- Array& operator=(const std::vector<T>& other) {
- resize((int)other.size());
- for (int i = 0; i < num; ++i) {
- data[i] = other[i];
- }
- return *this;
- }
-
- inline MemoryManager::Ref memoryManager() const {
- return m_memoryManager;
- }
-
- /**
- Number of elements in the array.
- */
- inline int size() const {
- return num;
- }
-
- /**
- Number of elements in the array. (Same as size; this is just
- here for convenience).
- */
- inline int length() const {
- return size();
- }
-
- /**
- Swaps element index with the last element in the array then
- shrinks the array by one.
- */
- void fastRemove(int index, bool shrinkIfNecessary = false) {
- debugAssert(index >= 0);
- debugAssert(index < num);
- data[index] = data[num - 1];
- resize(size() - 1, shrinkIfNecessary);
- }
-
-
- /**
- Inserts at the specified index and shifts all other elements up by one.
- */
- void insert(int n, const T& value) {
- // Add space for the extra element
- resize(num + 1, false);
-
- for (int i = num - 1; i > n; --i) {
- data[i] = data[i - 1];
- }
- data[n] = value;
- }
-
- /** @param shrinkIfNecessary if false, memory will never be
- reallocated when the array shrinks. This makes resizing much
- faster but can waste memory.
- */
- void resize(int n, bool shrinkIfNecessary = true) {
- debugAssert(n >= 0);
- if (num == n) {
- return;
- }
-
- int oldNum = num;
- num = n;
-
- // Call the destructors on newly hidden elements if there are any
- for (int i = num; i < oldNum; ++i) {
- (data + i)->~T();
- }
-
- // Once allocated, always maintain MIN_ELEMENTS elements or 32 bytes, whichever is higher.
- const int minSize = std::max(MIN_ELEMENTS, (int)(MIN_BYTES / sizeof(T)));
-
- if ((MIN_ELEMENTS == 0) && (MIN_BYTES == 0) && (n == 0) && shrinkIfNecessary) {
- // Deallocate the array completely
- numAllocated = 0;
- m_memoryManager->free(data);
- data = NULL;
- return;
- }
-
- if (num > numAllocated) {
- // Grow the underlying array
-
- if (numAllocated == 0) {
- // First allocation; grow to exactly the size requested to avoid wasting space.
- numAllocated = n;
- debugAssert(oldNum == 0);
- realloc(oldNum);
- } else {
-
- if (num < minSize) {
- // Grow to at least the minimum size
- numAllocated = minSize;
-
- } else {
-
- // Increase the underlying size of the array. Grow aggressively
- // up to 64k, less aggressively up to 400k, and then grow relatively
- // slowly (1.5x per resize) to avoid excessive space consumption.
- //
- // These numbers are tweaked according to performance tests.
-
- float growFactor = 3.0;
-
- int oldSizeBytes = numAllocated * sizeof(T);
- if (oldSizeBytes > 400000) {
- // Avoid bloat
- growFactor = 1.5;
- } else if (oldSizeBytes > 64000) {
- // This is what std:: uses at all times
- growFactor = 2.0;
- }
-
- numAllocated = (num - numAllocated) + (int)(numAllocated * growFactor);
-
- if (numAllocated < minSize) {
- numAllocated = minSize;
- }
- }
-
- realloc(oldNum);
- }
-
- } else if ((num <= numAllocated / 3) && shrinkIfNecessary && (num > minSize)) {
- // Shrink the underlying array
-
- // Only copy over old elements that still remain after resizing
- // (destructors were called for others if we're shrinking)
- realloc(iMin(num, oldNum));
-
- }
-
- // Call the constructors on newly revealed elements.
- // Do not use parens because we don't want the intializer
- // invoked for POD types.
- for (int i = oldNum; i < num; ++i) {
- new (data + i) T;
- }
- }
-
- /**
- Add an element to the end of the array. Will not shrink the underlying array
- under any circumstances. It is safe to append an element that is already
- in the array.
- */
- inline void append(const T& value) {
-
- if (num < numAllocated) {
- // This is a simple situation; just stick it in the next free slot using
- // the copy constructor.
- new (data + num) T(value);
- ++num;
- } else if (inArray(&value)) {
- // The value was in the original array; resizing
- // is dangerous because it may move the value
- // we have a reference to.
- T tmp = value;
- append(tmp);
- } else {
- // Here we run the empty initializer where we don't have to, but
- // this simplifies the computation.
- resize(num + 1, DONT_SHRINK_UNDERLYING_ARRAY);
- data[num - 1] = value;
- }
- }
-
-
- inline void append(const T& v1, const T& v2) {
- if (inArray(&v1) || inArray(&v2)) {
- // Copy into temporaries so that the references won't break when
- // the array resizes.
- T t1 = v1;
- T t2 = v2;
- append(t1, t2);
- } else if (num + 1 < numAllocated) {
- // This is a simple situation; just stick it in the next free slot using
- // the copy constructor.
- new (data + num) T(v1);
- new (data + num + 1) T(v2);
- num += 2;
- } else {
- // Resize the array. Note that neither value is already in the array.
- resize(num + 2, DONT_SHRINK_UNDERLYING_ARRAY);
- data[num - 2] = v1;
- data[num - 1] = v2;
- }
- }
-
-
- inline void append(const T& v1, const T& v2, const T& v3) {
- if (inArray(&v1) || inArray(&v2) || inArray(&v3)) {
- T t1 = v1;
- T t2 = v2;
- T t3 = v3;
- append(t1, t2, t3);
- } else if (num + 2 < numAllocated) {
- // This is a simple situation; just stick it in the next free slot using
- // the copy constructor.
- new (data + num) T(v1);
- new (data + num + 1) T(v2);
- new (data + num + 2) T(v3);
- num += 3;
- } else {
- resize(num + 3, DONT_SHRINK_UNDERLYING_ARRAY);
- data[num - 3] = v1;
- data[num - 2] = v2;
- data[num - 1] = v3;
- }
- }
-
-
- inline void append(const T& v1, const T& v2, const T& v3, const T& v4) {
- if (inArray(&v1) || inArray(&v2) || inArray(&v3) || inArray(&v4)) {
- T t1 = v1;
- T t2 = v2;
- T t3 = v3;
- T t4 = v4;
- append(t1, t2, t3, t4);
- } else if (num + 3 < numAllocated) {
- // This is a simple situation; just stick it in the next free slot using
- // the copy constructor.
- new (data + num) T(v1);
- new (data + num + 1) T(v2);
- new (data + num + 2) T(v3);
- new (data + num + 3) T(v4);
- num += 4;
- } else {
- resize(num + 4, DONT_SHRINK_UNDERLYING_ARRAY);
- data[num - 4] = v1;
- data[num - 3] = v2;
- data[num - 2] = v3;
- data[num - 1] = v4;
- }
- }
-
- /**
- Returns true if the given element is in the array.
- */
- bool contains(const T& e) const {
- for (int i = 0; i < size(); ++i) {
- if ((*this)[i] == e) {
- return true;
- }
- }
-
- return false;
- }
-
- /**
- Append the elements of array. Cannot be called with this array
- as an argument.
- */
- void append(const Array<T>& array) {
- debugAssert(this != &array);
- int oldNum = num;
- int arrayLength = array.length();
-
- resize(num + arrayLength, false);
-
- for (int i = 0; i < arrayLength; i++) {
- data[oldNum + i] = array.data[i];
- }
- }
-
- /**
- Pushes a new element onto the end and returns its address.
- This is the same as A.resize(A.size() + 1, false); A.last()
- */
- inline T& next() {
- resize(num + 1, false);
- return last();
- }
-
- /**
- Pushes an element onto the end (appends)
- */
- inline void push(const T& value) {
- append(value);
- }
-
- inline void push(const Array<T>& array) {
- append(array);
- }
-
- /** Alias to provide std::vector compatibility */
- inline void push_back(const T& v) {
- push(v);
- }
-
- /** "The member function removes the last element of the controlled sequence, which must be non-empty."
- For compatibility with std::vector. */
- inline void pop_back() {
- pop();
- }
-
- /**
- "The member function returns the storage currently allocated to hold the controlled
- sequence, a value at least as large as size()"
- For compatibility with std::vector.
- */
- int capacity() const {
- return numAllocated;
- }
-
- /**
- "The member function returns a reference to the first element of the controlled sequence,
- which must be non-empty."
- For compatibility with std::vector.
- */
- T& front() {
- return (*this)[0];
- }
-
- /**
- "The member function returns a reference to the first element of the controlled sequence,
- which must be non-empty."
- For compatibility with std::vector.
- */
- const T& front() const {
- return (*this)[0];
- }
-
- /**
- "The member function returns a reference to the last element of the controlled sequence,
- which must be non-empty."
- For compatibility with std::vector.
- */
- T& back() {
- return (*this)[size()-1];
- }
-
- /**
- "The member function returns a reference to the last element of the controlled sequence,
- which must be non-empty."
- For compatibility with std::vector.
- */
- const T& back() const {
- return (*this)[size()-1];
- }
-
- /**
- Removes the last element and returns it. By default, shrinks the underlying array.
- */
- inline T pop(bool shrinkUnderlyingArrayIfNecessary = true) {
- debugAssert(num > 0);
- T temp = data[num - 1];
- resize(num - 1, shrinkUnderlyingArrayIfNecessary);
- return temp;
- }
-
- /** Pops the last element and discards it without returning anything. Faster than pop.
- By default, does not shrink the underlying array.*/
- inline void popDiscard(bool shrinkUnderlyingArrayIfNecessary = false) {
- debugAssert(num > 0);
- resize(num - 1, shrinkUnderlyingArrayIfNecessary);
- }
-
-
- /**
- "The member function swaps the controlled sequences between *this and str."
- Note that this is slower than the optimal std implementation.
-
- For compatibility with std::vector.
- */
- void swap(Array<T>& str) {
- Array<T> temp = str;
- str = *this;
- *this = temp;
- }
-
-
- /**
- Performs bounds checks in debug mode
- */
- inline T& operator[](int n) {
- debugAssertM((n >= 0) && (n < num), format("Array index out of bounds. n = %d, size() = %d", n, num));
- debugAssert(data!=NULL);
- return data[n];
- }
-
- inline T& operator[](unsigned int n) {
- debugAssertM(n < (unsigned int)num, format("Array index out of bounds. n = %d, size() = %d", n, num));
- return data[n];
- }
-
- /**
- Performs bounds checks in debug mode
- */
- inline const T& operator[](int n) const {
- debugAssert((n >= 0) && (n < num));
- debugAssert(data!=NULL);
- return data[n];
- }
-
- inline const T& operator[](unsigned int n) const {
- debugAssert((n < (unsigned int)num));
- debugAssert(data!=NULL);
- return data[n];
- }
-
- inline T& randomElement() {
- debugAssert(num > 0);
- debugAssert(data!=NULL);
- return data[iRandom(0, num - 1)];
- }
-
- inline const T& randomElement() const {
- debugAssert(num > 0);
- debugAssert(data!=NULL);
- return data[iRandom(0, num - 1)];
- }
-
- /**
- Returns the last element, performing a check in
- debug mode that there is at least one element.
- */
- inline const T& last() const {
- debugAssert(num > 0);
- debugAssert(data!=NULL);
- return data[num - 1];
- }
-
- /** Returns element lastIndex() */
- inline T& last() {
- debugAssert(num > 0);
- debugAssert(data!=NULL);
- return data[num - 1];
- }
-
- /** Returns <i>size() - 1</i> */
- inline int lastIndex() const {
- debugAssertM(num > 0, "Array is empty");
- return num - 1;
- }
-
- inline int firstIndex() const {
- debugAssertM(num > 0, "Array is empty");
- return 0;
- }
-
- /** Returns element firstIndex(), performing a check in debug mode to ensure that there is at least one */
- inline T& first() {
- debugAssertM(num > 0, "Array is empty");
- return data[0];
- }
-
- inline const T& first() const {
- debugAssertM(num > 0, "Array is empty");
- return data[0];
- }
-
- /** Returns iFloor(size() / 2), throws an assertion in debug mode if the array is empty */
- inline int middleIndex() const {
- debugAssertM(num > 0, "Array is empty");
- return num >> 1;
- }
-
- /** Returns element middleIndex() */
- inline const T& middle() const {
- debugAssertM(num > 0, "Array is empty");
- return data[num >> 1];
- }
-
- /** Returns element middleIndex() */
- inline T& middle() {
- debugAssertM(num > 0, "Array is empty");
- return data[num >> 1];
- }
-
- /**
- Calls delete on all objects[0...size-1]
- and sets the size to zero.
- */
- void deleteAll() {
- for (int i = 0; i < num; i++) {
- delete data[i];
- }
- resize(0);
- }
-
- /**
- Returns the index of (the first occurance of) an index or -1 if
- not found. Searches from the right.
- */
- int rfindIndex(const T& value) const {
- for (int i = num -1 ; i >= 0; --i) {
- if (data[i] == value) {
- return i;
- }
- }
- return -1;
- }
-
- /**
- Returns the index of (the first occurance of) an index or -1 if
- not found.
- */
- int findIndex(const T& value) const {
- for (int i = 0; i < num; ++i) {
- if (data[i] == value) {
- return i;
- }
- }
- return -1;
- }
-
- /**
- Finds an element and returns the iterator to it. If the element
- isn't found then returns end().
- */
- Iterator find(const T& value) {
- for (int i = 0; i < num; ++i) {
- if (data[i] == value) {
- return data + i;
- }
- }
- return end();
- }
-
- ConstIterator find(const T& value) const {
- for (int i = 0; i < num; ++i) {
- if (data[i] == value) {
- return data + i;
- }
- }
- return end();
- }
-
- /**
- Removes count elements from the array
- referenced either by index or Iterator.
- */
- void remove(Iterator element, int count = 1) {
- debugAssert((element >= begin()) && (element < end()));
- debugAssert((count > 0) && (element + count) <= end());
- Iterator last = end() - count;
-
- while(element < last) {
- element[0] = element[count];
- ++element;
- }
-
- resize(num - count);
- }
-
- void remove(int index, int count = 1) {
- debugAssert((index >= 0) && (index < num));
- debugAssert((count > 0) && (index + count <= num));
-
- remove(begin() + index, count);
- }
-
- /**
- Reverse the elements of the array in place.
- */
- void reverse() {
- T temp;
-
- int n2 = num / 2;
- for (int i = 0; i < n2; ++i) {
- temp = data[num - 1 - i];
- data[num - 1 - i] = data[i];
- data[i] = temp;
- }
- }
-
- /**
- Sort using a specific less-than function, e.g.:
-
- <PRE>
- bool __cdecl myLT(const MyClass& elem1, const MyClass& elem2) {
- return elem1.x < elem2.x;
- }
- </PRE>
-
- Note that for pointer arrays, the <CODE>const</CODE> must come
- <I>after</I> the class name, e.g., <CODE>Array<MyClass*></CODE> uses:
-
- <PRE>
- bool __cdecl myLT(MyClass*const& elem1, MyClass*const& elem2) {
- return elem1->x < elem2->x;
- }
- </PRE>
-
- or a functor, e.g.,
- <pre>
-bool
-less_than_functor::operator()( const double& lhs, const double& rhs ) const
-{
-return( lhs < rhs? true : false );
-}
-</pre>
- */
- // void sort(bool (__cdecl *lessThan)(const T& elem1, const T& elem2)) {
- // std::sort(data, data + num, lessThan);
- //}
- template<class LessThan>
- void sort(const LessThan& lessThan) {
- // Using std::sort, which according to http://www.open-std.org/JTC1/SC22/WG21/docs/D_4.cpp
- // was 2x faster than qsort for arrays around size 2000 on intel core2 with gcc
- std::sort(data, data + num, lessThan);
- }
-
- /**
- Sorts the array in increasing order using the > or < operator. To
- invoke this method on Array<T>, T must override those operator.
- You can overide these operators as follows:
- <code>
- bool T::operator>(const T& other) const {
- return ...;
- }
- bool T::operator<(const T& other) const {
- return ...;
- }
- </code>
- */
- void sort(int direction = SORT_INCREASING) {
- if (direction == SORT_INCREASING) {
- std::sort(data, data + num);
- } else {
- std::sort(data, data + num, compareGT);
- }
- }
-
- /**
- Sorts elements beginIndex through and including endIndex.
- */
- void sortSubArray(int beginIndex, int endIndex, int direction = SORT_INCREASING) {
- if (direction == SORT_INCREASING) {
- std::sort(data + beginIndex, data + endIndex + 1);
- } else {
- std::sort(data + beginIndex, data + endIndex + 1, compareGT);
- }
- }
-
- void sortSubArray(int beginIndex, int endIndex, bool (__cdecl *lessThan)(const T& elem1, const T& elem2)) {
- std::sort(data + beginIndex, data + endIndex + 1, lessThan);
- }
-
- /**
- The StrictWeakOrdering can be either a class that overloads the function call operator() or
- a function pointer of the form <code>bool (__cdecl *lessThan)(const T& elem1, const T& elem2)</code>
- */
- template<typename StrictWeakOrdering>
- void sortSubArray(int beginIndex, int endIndex, StrictWeakOrdering& lessThan) {
- std::sort(data + beginIndex, data + endIndex + 1, lessThan);
- }
-
- /** Uses < and == to evaluate operator(); this is the default comparator for Array::partition. */
- class DefaultComparator {
- public:
- inline int operator()(const T& A, const T& B) const {
- if (A < B) {
- return 1;
- } else if (A == B) {
- return 0;
- } else {
- return -1;
- }
- }
- };
-
- /** The output arrays are resized with fastClear() so that if they are already of the same size
- as this array no memory is allocated during partitioning.
-
- @param comparator A function, or class instance with an overloaded operator() that compares
- two elements of type <code>T</code> and returns 0 if they are equal, -1 if the second is smaller,
- and 1 if the first is smaller (i.e., following the conventions of std::string::compare). For example:
-
- <pre>
- int compare(int A, int B) {
- if (A < B) {
- return 1;
- } else if (A == B) {
- return 0;
- } else {
- return -1;
- }
- }
- </pre>
- */
- template<typename Comparator>
- void partition(
- const T& partitionElement,
- Array<T>& ltArray,
- Array<T>& eqArray,
- Array<T>& gtArray,
- const Comparator& comparator) const {
-
- // Make sure all arrays are independent
- debugAssert(&ltArray != this);
- debugAssert(&eqArray != this);
- debugAssert(&gtArray != this);
- debugAssert(&ltArray != &eqArray);
- debugAssert(&ltArray != &gtArray);
- debugAssert(&eqArray != &gtArray);
-
- // Clear the arrays
- ltArray.fastClear();
- eqArray.fastClear();
- gtArray.fastClear();
-
- // Form a table of buckets for lt, eq, and gt
- Array<T>* bucket[3] = {&ltArray, &eqArray, &gtArray};
-
- for (int i = 0; i < num; ++i) {
- int c = comparator(partitionElement, data[i]);
- debugAssertM(c >= -1 && c <= 1, "Comparator returned an illegal value.");
-
- // Insert into the correct bucket, 0, 1, or 2
- bucket[c + 1]->append(data[i]);
- }
- }
-
- /**
- Uses < and == on elements to perform a partition. See partition().
- */
- void partition(
- const T& partitionElement,
- Array<T>& ltArray,
- Array<T>& eqArray,
- Array<T>& gtArray) const {
-
- partition(partitionElement, ltArray, eqArray, gtArray, typename Array<T>::DefaultComparator());
- }
-
- /**
- Paritions the array into those below the median, those above the median, and those elements
- equal to the median in expected O(n) time using quickselect. If the array has an even
- number of different elements, the median for partition purposes is the largest value
- less than the median.
-
- @param tempArray used for working scratch space
- @param comparator see parition() for a discussion.*/
- template<typename Comparator>
- void medianPartition(
- Array<T>& ltMedian,
- Array<T>& eqMedian,
- Array<T>& gtMedian,
- Array<T>& tempArray,
- const Comparator& comparator) const {
-
- ltMedian.fastClear();
- eqMedian.fastClear();
- gtMedian.fastClear();
-
- // Handle trivial cases first
- switch (size()) {
- case 0:
- // Array is empty; no parition is possible
- return;
-
- case 1:
- // One element
- eqMedian.append(first());
- return;
-
- case 2:
- {
- // Two element array; median is the smaller
- int c = comparator(first(), last());
-
- switch (c) {
- case -1:
- // first was bigger
- eqMedian.append(last());
- gtMedian.append(first());
- break;
-
- case 0:
- // Both equal to the median
- eqMedian.append(first(), last());
- break;
-
- case 1:
- // Last was bigger
- eqMedian.append(first());
- gtMedian.append(last());
- break;
- }
- }
- return;
- }
-
- // All other cases use a recursive randomized median
-
- // Number of values less than all in the current arrays
- int ltBoost = 0;
-
- // Number of values greater than all in the current arrays
- int gtBoost = 0;
-
- // For even length arrays, force the gt array to be one larger than the
- // lt array:
- // [1 2 3] size = 3, choose half = (s + 1) /2
- //
- int lowerHalfSize, upperHalfSize;
- if (isEven(size())) {
- lowerHalfSize = size() / 2;
- upperHalfSize = lowerHalfSize + 1;
- } else {
- lowerHalfSize = upperHalfSize = (size() + 1) / 2;
- }
- const T* xPtr = NULL;
-
- // Maintain pointers to the arrays; we'll switch these around during sorting
- // to avoid copies.
- const Array<T>* source = this;
- Array<T>* lt = &ltMedian;
- Array<T>* eq = &eqMedian;
- Array<T>* gt = &gtMedian;
- Array<T>* extra = &tempArray;
-
- while (true) {
- // Choose a random element -- choose the middle element; this is theoretically
- // suboptimal, but for loosly sorted array is actually the best strategy
-
- xPtr = &(source->middle());
- if (source->size() == 1) {
- // Done; there's only one element left
- break;
- }
- const T& x = *xPtr;
-
- // Note: partition (fast) clears the arrays for us
- source->partition(x, *lt, *eq, *gt, comparator);
-
- int L = lt->size() + ltBoost + eq->size();
- int U = gt->size() + gtBoost + eq->size();
- if ((L >= lowerHalfSize) &&
- (U >= upperHalfSize)) {
-
- // x must be the partition median
- break;
-
- } else if (L < lowerHalfSize) {
-
- // x must be smaller than the median. Recurse into the 'gt' array.
- ltBoost += lt->size() + eq->size();
-
- // The new gt array will be the old source array, unless
- // that was the this pointer (i.e., unless we are on the
- // first iteration)
- Array<T>* newGt = (source == this) ? extra : const_cast<Array<T>*>(source);
-
- // Now set up the gt array as the new source
- source = gt;
- gt = newGt;
-
- } else {
-
- // x must be bigger than the median. Recurse into the 'lt' array.
- gtBoost += gt->size() + eq->size();
-
- // The new lt array will be the old source array, unless
- // that was the this pointer (i.e., unless we are on the
- // first iteration)
- Array<T>* newLt = (source == this) ? extra : const_cast<Array<T>*>(source);
-
- // Now set up the lt array as the new source
- source = lt;
- lt = newLt;
- }
- }
-
- // Now that we know the median, make a copy of it (since we're about to destroy the array that it
- // points into).
- T median = *xPtr;
- xPtr = NULL;
-
- // Partition the original array (note that this fast clears for us)
- partition(median, ltMedian, eqMedian, gtMedian, comparator);
- }
-
- /**
- Computes a median partition using the default comparator and a dynamically allocated temporary
- working array. If the median is not in the array, it is chosen to be the largest value smaller
- than the true median.
- */
- void medianPartition(
- Array<T>& ltMedian,
- Array<T>& eqMedian,
- Array<T>& gtMedian) const {
-
- Array<T> temp;
- medianPartition(ltMedian, eqMedian, gtMedian, temp, DefaultComparator());
- }
-
-
- /** Redistributes the elements so that the new order is statistically independent
- of the original order. O(n) time.*/
- void randomize() {
- T temp;
-
- for (int i = size() - 1; i >= 0; --i) {
- int x = iRandom(0, i);
-
- temp = data[i];
- data[i] = data[x];
- data[x] = temp;
- }
- }
-
-
-};
-
-
-/** Array::contains for C-arrays */
-template<class T> bool contains(const T* array, int len, const T& e) {
- for (int i = len - 1; i >= 0; --i) {
- if (array[i] == e) {
- return true;
- }
- }
- return false;
-}
-
-} // namespace
-
-#ifdef _MSC_VER
-# pragma warning (pop)
-#endif
-
-#endif
diff --git a/externals/g3dlite/G3D/AtomicInt32.h b/externals/g3dlite/G3D/AtomicInt32.h
deleted file mode 100644
index 2d63f998355..00000000000
--- a/externals/g3dlite/G3D/AtomicInt32.h
+++ /dev/null
@@ -1,164 +0,0 @@
-/**
- @file AtomicInt32.h
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2005-09-01
- @edited 2006-06-21
- */
-#ifndef G3D_ATOMICINT32_H
-#define G3D_ATOMICINT32_H
-
-#include "G3D/platform.h"
-#include "G3D/g3dmath.h"
-
-#if defined(G3D_OSX)
-# include <libkern/OSAtomic.h>
-#endif
-
-namespace G3D {
-
-/**
- An integer that may safely be used on different threads without
- external locking.
-
- On Win32, Linux, FreeBSD, and Mac OS X this is implemented without locks.
-
- <B>BETA API</B> This is unsupported and may change
- */
-class AtomicInt32 {
-private:
-# if defined(G3D_WIN32)
- volatile long m_value;
-# elif defined(G3D_OSX)
- int32_t m_value;
-# else
- volatile int32 m_value;
-# endif
-
-
-public:
-
- /** Initial value is undefined. */
- AtomicInt32() {}
-
- /** Atomic set */
- explicit AtomicInt32(const int32 x) {
- m_value = x;
- }
-
- /** Atomic set */
- AtomicInt32(const AtomicInt32& x) {
- m_value = x.m_value;
- }
-
- /** Atomic set */
- const AtomicInt32& operator=(const int32 x) {
- m_value = x;
- return *this;
- }
-
- /** Atomic set */
- void operator=(const AtomicInt32& x) {
- m_value = x.m_value;
- }
-
- /** Returns the current value */
- int32 value() const {
- return m_value;
- }
-
- /** Returns the old value, before the add. */
- int32 add(const int32 x) {
-# if defined(G3D_WIN32)
-
- return InterlockedExchangeAdd(&m_value, x);
-
-# elif defined(G3D_LINUX) || defined(G3D_FREEBSD)
-
- int32 old;
- asm volatile ("lock; xaddl %0,%1"
- : "=r"(old), "=m"(m_value) /* outputs */
- : "0"(x), "m"(m_value) /* inputs */
- : "memory", "cc");
- return old;
-
-# elif defined(G3D_OSX)
-
- int32 old = m_value;
- OSAtomicAdd32(x, &m_value);
- return old;
-
-# endif
- }
-
- /** Returns old value. */
- int32 sub(const int32 x) {
- return add(-x);
- }
-
- void increment() {
-# if defined(G3D_WIN32)
- // Note: returns the newly incremented value
- InterlockedIncrement(&m_value);
-# elif defined(G3D_LINUX) || defined(G3D_FREEBSD)
- add(1);
-# elif defined(G3D_OSX)
- // Note: returns the newly incremented value
- OSAtomicIncrement32(&m_value);
-# endif
- }
-
- /** Returns zero if the result is zero after decrement, non-zero otherwise.*/
- int32 decrement() {
-# if defined(G3D_WIN32)
- // Note: returns the newly decremented value
- return InterlockedDecrement(&m_value);
-# elif defined(G3D_LINUX) || defined(G3D_FREEBSD)
- unsigned char nz;
-
- asm volatile ("lock; decl %1;\n\t"
- "setnz %%al"
- : "=a" (nz)
- : "m" (m_value)
- : "memory", "cc");
- return nz;
-# elif defined(G3D_OSX)
- // Note: returns the newly decremented value
- return OSAtomicDecrement32(&m_value);
-# endif
- }
-
-
- /** Atomic test-and-set: if <code>*this == comperand</code> then <code>*this := exchange</code> else do nothing.
- In both cases, returns the old value of <code>*this</code>.
-
- Performs an atomic comparison of this with the Comperand value.
- If this is equal to the Comperand value, the Exchange value is stored in this.
- Otherwise, no operation is performed.
-
- Under VC6 the sign bit may be lost.
- */
- int32 compareAndSet(const int32 comperand, const int32 exchange) {
-# if defined(G3D_WIN32)
- return InterlockedCompareExchange(&m_value, exchange, comperand);
-# elif defined(G3D_LINUX) || defined(G3D_FREEBSD) || defined(G3D_OSX)
- // Based on Apache Portable Runtime
- // http://koders.com/c/fid3B6631EE94542CDBAA03E822CA780CBA1B024822.aspx
- int32 ret;
- asm volatile ("lock; cmpxchgl %1, %2"
- : "=a" (ret)
- : "r" (exchange), "m" (m_value), "0"(comperand)
- : "memory", "cc");
- return ret;
-
- // Note that OSAtomicCompareAndSwap32 does not return a useful value for us
- // so it can't satisfy the cmpxchgl contract.
-# endif
- }
-
-};
-
-} // namespace
-
-#endif
diff --git a/externals/g3dlite/G3D/BinaryFormat.h b/externals/g3dlite/G3D/BinaryFormat.h
deleted file mode 100644
index f6719a1c540..00000000000
--- a/externals/g3dlite/G3D/BinaryFormat.h
+++ /dev/null
@@ -1,140 +0,0 @@
-/**
- @file BinaryFormat.h
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @author 2005-06-03
- @edited 2005-06-03
-
- Copyright 2000-2005, Morgan McGuire.
- All rights reserved.
- */
-
-#ifndef G3D_BINARYFORMAT_H
-#define G3D_BINARYFORMAT_H
-
-#include "G3D/platform.h"
-#include "G3D/g3dmath.h"
-
-namespace G3D {
-
-class Vector2;
-class Vector2int16;
-class Vector3;
-class Vector3int16;
-class Vector4;
-class Vector4int16;
-class Color3;
-class Color3uint8;
-class Color4;
-class Color4uint8;
-
-/**
- Some values like float16 and int128 have no current CPU data structure that implements them but are useful
- for file formats and for GPUs.
-
- CHUNK_BINFMT data follows the protocol.
- */
-// Must be packed int 16 bits for the chunk reader
-// We can't name these just "INT8" etc. because some libraries #define names like that
-enum BinaryFormat {
- FIRST_BINFMT = 1000,
-
- BOOL8_BINFMT,
- UINT8_BINFMT, INT8_BINFMT, UINT16_BINFMT, INT16_BINFMT, UINT32_BINFMT, INT32_BINFMT, UINT64_BINFMT, INT64_BINFMT, UINT128_BINFMT, INT128_BINFMT,
- FLOAT16_BINFMT, FLOAT32_BINFMT, FLOAT64_BINFMT,
- VECTOR2_BINFMT, VECTOR2INT16_BINFMT,
- VECTOR3_BINFMT, VECTOR3INT16_BINFMT,
- VECTOR4_BINFMT, VECTOR4INT16_BINFMT,
- COLOR3_BINFMT, COLOR3UINT8_BINFMT, COLOR3INT16_BINFMT,
- COLOR4_BINFMT, COLOR4UINT8_BINFMT, COLOR4INT16_BINFMT,
- STRING_BINFMT, STRINGEVEN_BINFMT, STRING8_BINFMT, STRING16_BINFMT, STRING32_BINFMT,
-
- CHUNK_BINFMT,
-
- CUSTOM_BINFMT,
-
- LAST_BINFMT
-};
-
-}
-
-/** A macro that maps G3D types to format constants.
- (e.g. binaryFormatOf(Vector3) == VECTOR3_BINFMT).
-*/
-// This implementation is designed to meet the following constraints:
-// 1. Work around the many MSVC++ partial template bugs
-// 2. Work for primitive types (e.g. int)
-#define binaryFormatOf(T) (G3D::_internal::_BinaryFormat<T>::x())
-
-namespace G3D {
-namespace _internal {
-
-
-template<class T> class _BinaryFormat {
-public:
- static BinaryFormat x() {
- return CUSTOM_BINFMT;
- }
-};
-}}
-
-
-/**
- Macro to declare the underlying format (as will be returned by glFormatOf)
- of a type. For example,
-
- <PRE>
- DECLARE_BINARYFORMATOF(Vector4, VECTOR4_BINFMT)
- </PRE>
-
- Use this so you can make vertex arrays of your own classes and not just
- the standard ones.
- */
-#define DECLARE_BINARYFORMATOF(CType, EnumType) \
-namespace G3D { \
- namespace _internal { \
- template<> class _BinaryFormat<CType> { \
- public: \
- static BinaryFormat x() { \
- return EnumType; \
- } \
- }; \
- } \
-}
-
-DECLARE_BINARYFORMATOF( bool, BOOL8_BINFMT )
-
-DECLARE_BINARYFORMATOF( uint8, UINT8_BINFMT )
-DECLARE_BINARYFORMATOF( int8, INT8_BINFMT )
-DECLARE_BINARYFORMATOF( uint16, UINT16_BINFMT )
-DECLARE_BINARYFORMATOF( int16, INT16_BINFMT )
-DECLARE_BINARYFORMATOF( uint32, UINT32_BINFMT )
-DECLARE_BINARYFORMATOF( int32, INT32_BINFMT )
-DECLARE_BINARYFORMATOF( uint64, UINT64_BINFMT )
-DECLARE_BINARYFORMATOF( int64, INT64_BINFMT )
-
-DECLARE_BINARYFORMATOF( float32, FLOAT32_BINFMT )
-DECLARE_BINARYFORMATOF( float64, FLOAT64_BINFMT )
-
-DECLARE_BINARYFORMATOF( Vector2, VECTOR2_BINFMT )
-DECLARE_BINARYFORMATOF( Vector2int16, VECTOR2INT16_BINFMT )
-DECLARE_BINARYFORMATOF( Vector3, VECTOR3_BINFMT )
-DECLARE_BINARYFORMATOF( Vector3int16, VECTOR3INT16_BINFMT )
-DECLARE_BINARYFORMATOF( Vector4, VECTOR4_BINFMT )
-DECLARE_BINARYFORMATOF( Vector4int16, VECTOR4INT16_BINFMT )
-
-DECLARE_BINARYFORMATOF( Color3, COLOR3_BINFMT )
-DECLARE_BINARYFORMATOF( Color3uint8, COLOR3UINT8_BINFMT )
-DECLARE_BINARYFORMATOF( Color4, COLOR4_BINFMT )
-DECLARE_BINARYFORMATOF( Color4uint8, COLOR4UINT8_BINFMT )
-
-namespace G3D {
-
-/** Returns -1 if the format is custom, otherwise the byte size
- of a single element in this format.*/
-int32 byteSize(BinaryFormat f);
-
-
-} //G3D
-
-#endif
diff --git a/externals/g3dlite/G3D/BinaryInput.h b/externals/g3dlite/G3D/BinaryInput.h
deleted file mode 100644
index 1dac93ea55e..00000000000
--- a/externals/g3dlite/G3D/BinaryInput.h
+++ /dev/null
@@ -1,441 +0,0 @@
-/**
- @file BinaryInput.h
-
- @maintainer Morgan McGuire, graphics3d.com
-
- @created 2001-08-09
- @edited 2006-07-19
-
- Copyright 2000-2009, Morgan McGuire.
- All rights reserved.
- */
-
-#ifndef G3D_BinaryInput_h
-#define G3D_BinaryInput_h
-
-#ifdef _MSC_VER
-// Disable conditional expression is constant, which occurs incorrectly on inlined functions
-# pragma warning(push)
-# pragma warning( disable : 4127 )
-#endif
-
-#include <assert.h>
-#include <string>
-#include <vector>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <stdio.h>
-#include "G3D/platform.h"
-#include "G3D/Array.h"
-#include "G3D/Color4.h"
-#include "G3D/Color3.h"
-#include "G3D/Vector4.h"
-#include "G3D/Vector3.h"
-#include "G3D/Vector2.h"
-#include "G3D/g3dmath.h"
-#include "G3D/debug.h"
-#include "G3D/System.h"
-
-
-namespace G3D {
-
-#if defined(G3D_WIN32) || defined(G3D_LINUX)
- // Allow writing of integers to non-word aligned locations.
- // This is legal on x86, but not on other platforms.
- #define G3D_ALLOW_UNALIGNED_WRITES
-#endif
-
-/**
- Sequential or random access byte-order independent binary file access.
- Files compressed with zlib and beginning with an unsigned 32-bit int
- size are transparently decompressed when the compressed = true flag is
- specified to the constructor.
-
- For every readX method there are also versions that operate on a whole
- Array, std::vector, or C-array. e.g. readFloat32(Array<float32>& array, n)
- These methods resize the array or std::vector to the appropriate size
- before reading. For a C-array, they require the pointer to reference
- a memory block at least large enough to hold <I>n</I> elements.
-
- Most classes define serialize/deserialize methods that use BinaryInput,
- BinaryOutput, TextInput, and TextOutput. There are text serializer
- functions for primitive types (e.g. int, std::string, float, double) but not
- binary serializers-- you <B>must</b> call the BinaryInput::readInt32 or
- other appropriate function. This is because it would be very hard to
- debug the error sequence: <CODE>serialize(1.0, bo); ... float f; deserialize(f, bi);</CODE>
- in which a double is serialized and then deserialized as a float.
- */
-class BinaryInput {
-private:
-
- // The initial buffer will be no larger than this, but
- // may grow if a large memory read occurs. 50 MB
- enum {INITIAL_BUFFER_LENGTH = 50000000};
-
- /**
- is the file big or little endian
- */
- G3DEndian m_fileEndian;
- std::string m_filename;
-
- bool m_swapBytes;
-
- /** Next position to read from in bitString during readBits. */
- int m_bitPos;
-
- /** Bits currently being read by readBits.
- Contains at most 8 (low) bits. Note that
- beginBits/readBits actually consumes one extra byte, which
- will be restored by writeBits.*/
- uint32 m_bitString;
-
- /** 1 when between beginBits and endBits, 0 otherwise. */
- int m_beginEndBits;
-
- /** When operating on huge files, we cannot load the whole file into memory.
- This is the file position to which buffer[0] corresponds.
- */
- int64 m_alreadyRead;
-
- /**
- Length of the entire file, in bytes.
- For the length of the buffer, see bufferLength
- */
- int64 m_length;
-
- /** Length of the array referenced by buffer. May go past the end of the file!*/
- int64 m_bufferLength;
- uint8* m_buffer;
-
- /**
- Next byte in file, relative to buffer.
- */
- int64 m_pos;
-
- /**
- When true, the buffer is freed in the destructor.
- */
- bool m_freeBuffer;
-
- /** Ensures that we are able to read at least minLength from startPosition (relative
- to start of file). */
- void loadIntoMemory(int64 startPosition, int64 minLength = 0);
-
- /** Verifies that at least this number of bytes can be read.*/
- inline void prepareToRead(int64 nbytes) {
- debugAssertM(m_length > 0, m_filename + " not found or corrupt.");
- debugAssertM(m_pos + nbytes + m_alreadyRead <= m_length, "Read past end of file.");
-
- if (m_pos + nbytes > m_bufferLength) {
- loadIntoMemory(m_pos + m_alreadyRead, nbytes);
- }
- }
-
- // Not implemented on purpose, don't use
- BinaryInput(const BinaryInput&);
- BinaryInput& operator=(const BinaryInput&);
- bool operator==(const BinaryInput&);
-
- /** Buffer is compressed; replace it with a decompressed version */
- void decompress();
-public:
-
- /** false, constant to use with the copyMemory option */
- static const bool NO_COPY;
-
- /**
- If the file cannot be opened, a zero length buffer is presented.
- Automatically opens files that are inside zipfiles.
-
- @param compressed Set to true if and only if the file was
- compressed using BinaryOutput's zlib compression. This has
- nothing to do with whether the input is in a zipfile.
- */
- BinaryInput(
- const std::string& filename,
- G3DEndian fileEndian,
- bool compressed = false);
-
- /**
- Creates input stream from an in memory source.
- Unless you specify copyMemory = false, the data is copied
- from the pointer, so you may deallocate it as soon as the
- object is constructed. It is an error to specify copyMemory = false
- and compressed = true.
-
- To decompress part of a file, you can follow the following paradigm:
-
- <PRE>
- BinaryInput master(...);
-
- // read from master to point where compressed data exists.
-
- BinaryInput subset(master.getCArray() + master.getPosition(),
- master.length() - master.getPosition(),
- master.endian(), true, true);
-
- // Now read from subset (it is ok for master to go out of scope)
- </PRE>
- */
- BinaryInput(
- const uint8* data,
- int64 dataLen,
- G3DEndian dataEndian,
- bool compressed = false,
- bool copyMemory = true);
-
- virtual ~BinaryInput();
-
- /** Change the endian-ness of the file. This only changes the
- interpretation of the file for future read calls; the
- underlying data is unmodified.*/
- void setEndian(G3DEndian endian);
-
- G3DEndian endian() const {
- return m_fileEndian;
- }
-
- std::string getFilename() const {
- return m_filename;
- }
-
- /**
- Returns a pointer to the internal memory buffer.
- May throw an exception for huge files.
- */
- const uint8* getCArray() const {
- if (m_alreadyRead > 0) {
- throw "Cannot getCArray for a huge file";
- }
- return m_buffer;
- }
-
- /**
- Performs bounds checks in debug mode. [] are relative to
- the start of the file, not the current position.
- Seeks to the new position before reading (and leaves
- that as the current position)
- */
- inline uint8 operator[](int64 n) {
- setPosition(n);
- return readUInt8();
- }
-
- /**
- Returns the length of the file in bytes.
- */
- inline int64 getLength() const {
- return m_length;
- }
-
- inline int64 size() const {
- return getLength();
- }
-
- /**
- Returns the current byte position in the file,
- where 0 is the beginning and getLength() - 1 is the end.
- */
- inline int64 getPosition() const {
- return m_pos + m_alreadyRead;
- }
-
- /**
- Sets the position. Cannot set past length.
- May throw a char* when seeking backwards more than 10 MB on a huge file.
- */
- inline void setPosition(int64 p) {
- debugAssertM(p <= m_length, "Read past end of file");
- m_pos = p - m_alreadyRead;
- if ((m_pos < 0) || (m_pos > m_bufferLength)) {
- loadIntoMemory(m_pos + m_alreadyRead);
- }
- }
-
- /**
- Goes back to the beginning of the file.
- */
- inline void reset() {
- setPosition(0);
- }
-
- inline int8 readInt8() {
- prepareToRead(1);
- return m_buffer[m_pos++];
- }
-
- inline bool readBool8() {
- return (readInt8() != 0);
- }
-
- inline uint8 readUInt8() {
- prepareToRead(1);
- return ((uint8*)m_buffer)[m_pos++];
- }
-
- uint16 inline readUInt16() {
- prepareToRead(2);
-
- m_pos += 2;
- if (m_swapBytes) {
- uint8 out[2];
- out[0] = m_buffer[m_pos - 1];
- out[1] = m_buffer[m_pos - 2];
- return *(uint16*)out;
- } else {
- #ifdef G3D_ALLOW_UNALIGNED_WRITES
- return *(uint16*)(&m_buffer[m_pos - 2]);
- #else
- uint8 out[2];
- out[0] = m_buffer[m_pos - 2];
- out[1] = m_buffer[m_pos - 1];
- return *(uint16*)out;
- #endif
- }
-
- }
-
- inline int16 readInt16() {
- uint16 a = readUInt16();
- return *(int16*)&a;
- }
-
- inline uint32 readUInt32() {
- prepareToRead(4);
-
- m_pos += 4;
- if (m_swapBytes) {
- uint8 out[4];
- out[0] = m_buffer[m_pos - 1];
- out[1] = m_buffer[m_pos - 2];
- out[2] = m_buffer[m_pos - 3];
- out[3] = m_buffer[m_pos - 4];
- return *(uint32*)out;
- } else {
- #ifdef G3D_ALLOW_UNALIGNED_WRITES
- return *(uint32*)(&m_buffer[m_pos - 4]);
- #else
- uint8 out[4];
- out[0] = m_buffer[m_pos - 4];
- out[1] = m_buffer[m_pos - 3];
- out[2] = m_buffer[m_pos - 2];
- out[3] = m_buffer[m_pos - 1];
- return *(uint32*)out;
- #endif
- }
- }
-
-
- inline int32 readInt32() {
- uint32 a = readUInt32();
- return *(int32*)&a;
- }
-
- uint64 readUInt64();
-
- inline int64 readInt64() {
- uint64 a = readUInt64();
- return *(int64*)&a;
- }
-
- inline float32 readFloat32() {
- union {
- uint32 a;
- float32 b;
- };
- a = readUInt32();
- return b;
- }
-
- inline float64 readFloat64() {
- union {
- uint64 a;
- float64 b;
- };
- a = readUInt64();
- return b;
- }
-
- void readBytes(void* bytes, int64 n);
-
- /**
- Reads an n character string. The string is not
- required to end in NULL in the file but will
- always be a proper std::string when returned.
- */
- std::string readString(int64 n);
-
- /**
- Reads until NULL or the end of the file is encountered.
- */
- std::string readString();
-
- /**
- Reads until NULL or the end of the file is encountered.
- If the string has odd length (including NULL), reads
- another byte.
- */
- std::string readStringEven();
-
-
- std::string readString32();
-
- Vector4 readVector4();
- Vector3 readVector3();
- Vector2 readVector2();
-
- Color4 readColor4();
- Color3 readColor3();
-
- /**
- Skips ahead n bytes.
- */
- inline void skip(int64 n) {
- setPosition(m_pos + m_alreadyRead + n);
- }
-
- /**
- Returns true if the position is not at the end of the file
- */
- inline bool hasMore() const {
- return m_pos + m_alreadyRead < m_length;
- }
-
- /** Prepares for bit reading via readBits. Only readBits can be
- called between beginBits and endBits without corrupting the
- data stream. */
- void beginBits();
-
- /** Can only be called between beginBits and endBits */
- uint32 readBits(int numBits);
-
- /** Ends bit-reading. */
- void endBits();
-
-# define DECLARE_READER(ucase, lcase)\
- void read##ucase(lcase* out, int64 n);\
- void read##ucase(std::vector<lcase>& out, int64 n);\
- void read##ucase(Array<lcase>& out, int64 n);
-
- DECLARE_READER(Bool8, bool)
- DECLARE_READER(UInt8, uint8)
- DECLARE_READER(Int8, int8)
- DECLARE_READER(UInt16, uint16)
- DECLARE_READER(Int16, int16)
- DECLARE_READER(UInt32, uint32)
- DECLARE_READER(Int32, int32)
- DECLARE_READER(UInt64, uint64)
- DECLARE_READER(Int64, int64)
- DECLARE_READER(Float32, float32)
- DECLARE_READER(Float64, float64)
-# undef DECLARE_READER
-};
-
-
-}
-
-#ifdef _MSC_VER
-# pragma warning(pop)
-#endif
-
-#endif
diff --git a/externals/g3dlite/G3D/BinaryOutput.h b/externals/g3dlite/G3D/BinaryOutput.h
deleted file mode 100644
index d81ec56a67b..00000000000
--- a/externals/g3dlite/G3D/BinaryOutput.h
+++ /dev/null
@@ -1,421 +0,0 @@
-/**
- @file BinaryOutput.h
-
- @maintainer Morgan McGuire, graphics3d.com
-
- @created 2001-08-09
- @edited 2008-01-24
-
- Copyright 2000-2006, Morgan McGuire.
- All rights reserved.
- */
-
-#ifndef G3D_BINARYOUTPUT_H
-#define G3D_BINARYOUTPUT_H
-
-#include "G3D/platform.h"
-#include <assert.h>
-#include <string>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <stdio.h>
-#include "G3D/Color4.h"
-#include "G3D/Color3.h"
-#include "G3D/Vector4.h"
-#include "G3D/Vector3.h"
-#include "G3D/Vector2.h"
-#include "G3D/g3dmath.h"
-#include "G3D/debug.h"
-#include "G3D/BinaryInput.h"
-#include "G3D/System.h"
-
-#ifdef _MSC_VER
-# pragma warning (push)
-// Conditional is constant (wrong in inline)
-# pragma warning (disable : 4127)
-#endif
-namespace G3D {
-
-/**
- Sequential or random access byte-order independent binary file access.
-
- The compress() call can be used to compress with zlib.
-
- Any method call can trigger an out of memory error (thrown as char*)
- when writing to "<memory>" instead of a file.
-
- Compressed writing and seeking backwards is not supported for huge files
- (i.e., BinaryOutput may have to dump the contents to disk if they
- exceed available RAM).
- */
-class BinaryOutput {
-private:
- std::string m_filename;
-
- bool m_committed;
-
- /** 0 outside of beginBits...endBits, 1 inside */
- int m_beginEndBits;
-
- /** The current string of bits being built up by beginBits...endBits.
- This string is treated semantically, as if the lowest bit was
- on the left and the highest was on the right.*/
- int8 m_bitString;
-
- /** Position (from the lowest bit) currently used in bitString.*/
- int m_bitPos;
-
- // True if the file endianess does not match the machine endian
- bool m_swapBytes;
-
- G3DEndian m_fileEndian;
-
- uint8* m_buffer;
-
- /** Size of the elements used */
- int m_bufferLen;
-
- /** Underlying size of memory allocaded */
- int m_maxBufferLen;
-
- /** Next byte in file */
- int m_pos;
-
- /** is this initialized? */
- bool m_init;
-
- /** Number of bytes already written to the file.*/
- size_t m_alreadyWritten;
-
- bool m_ok;
-
- void reserveBytesWhenOutOfMemory(size_t bytes);
-
- void reallocBuffer(size_t bytes, size_t oldBufferLen);
-
- /**
- Make sure at least bytes can be written, resizing if
- necessary.
- */
- inline void reserveBytes(int bytes) {
- debugAssert(bytes > 0);
- size_t oldBufferLen = (size_t)m_bufferLen;
-
- m_bufferLen = iMax(m_bufferLen, (m_pos + bytes));
- if (m_bufferLen > m_maxBufferLen) {
- reallocBuffer(bytes, oldBufferLen);
- }
- }
-
- // Not implemented on purpose, don't use
- BinaryOutput(const BinaryOutput&);
- BinaryOutput& operator=(const BinaryOutput&);
- bool operator==(const BinaryOutput&);
-
-public:
-
- /**
- You must call setEndian() if you use this (memory) constructor.
- */
- BinaryOutput();
-
- /**
- Doesn't actually open the file; commit() does that.
- Use "<memory>" as the filename if you're going to commit
- to memory.
- */
- BinaryOutput(
- const std::string& filename,
- G3DEndian fileEndian);
-
- ~BinaryOutput();
-
- /** Compresses the data in the buffer in place,
- preceeding it with a little-endian uint32 indicating
- the uncompressed size.
-
- Call immediately before commit().
-
- Cannot be used for huge files (ones where the data
- was already written to disk)-- will throw char*.
- */
- void compress();
-
- /** True if no errors have been encountered.*/
- bool ok() const;
-
- /**
- Returns a pointer to the internal memory buffer.
- */
- inline const uint8* getCArray() const {
- return m_buffer;
- }
-
- void setEndian(G3DEndian fileEndian);
-
- G3DEndian endian() const {
- return m_fileEndian;
- }
-
- std::string getFilename() const {
- return m_filename;
- }
-
- /**
- Write the bytes to disk. It is ok to call this
- multiple times; it will just overwrite the previous file.
-
- Parent directories are created as needed if they do
- not exist.
-
- <B>Not</B> called from the destructor; you must call
- it yourself.
-
- @param flush If true (default) the file is ready for reading when the method returns, otherwise
- the method returns immediately and writes the file in the background.
- */
- void commit(bool flush = true);
-
- /**
- Write the bytes to memory (which must be of
- at least size() bytes).
- */
- void commit(uint8*);
-
- /**
- A memory BinaryOutput may be reset so that it can be written to again
- without allocating new memory. The underlying array will not be deallocated,
- but the reset structure will act like a newly intialized one.
- */
- void reset();
-
-
- inline int length() const {
- return (int)m_bufferLen + (int)m_alreadyWritten;
- }
-
- inline int size() const {
- return length();
- }
-
- /**
- Sets the length of the file to n, padding
- with 0's past the current end. Does not
- change the position of the next byte to be
- written unless n < size().
-
- Throws char* when resetting a huge file to be shorter
- than its current length.
- */
- inline void setLength(int n) {
- n = n - (int)m_alreadyWritten;
-
- if (n < 0) {
- throw "Cannot resize huge files to be shorter.";
- }
-
- if (n < m_bufferLen) {
- m_pos = n;
- }
- if (n > m_bufferLen) {
- reserveBytes(n - m_bufferLen);
- }
- }
-
- /**
- Returns the current byte position in the file,
- where 0 is the beginning and getLength() - 1 is the end.
- */
- inline int64 position() const {
- return (int64)m_pos + (int64)m_alreadyWritten;
- }
-
-
- /**
- Sets the position. Can set past length, in which case
- the file is padded with zeros up to one byte before the
- next to be written.
-
- May throw a char* exception when seeking backwards on a huge file.
- */
- inline void setPosition(int64 p) {
- p = p - (int64)m_alreadyWritten;
-
- if (p > m_bufferLen) {
- setLength((int)(p + (int64)m_alreadyWritten));
- }
-
- if (p < 0) {
- throw "Cannot seek more than 10 MB backwards on huge files.";
- }
-
- m_pos = (int)p;
- }
-
-
- void writeBytes(
- const void* b,
- int count) {
-
- reserveBytes(count);
- debugAssert(m_pos >= 0);
- debugAssert(m_bufferLen >= count);
- System::memcpy(m_buffer + m_pos, b, count);
- m_pos += count;
- }
-
- /**
- Writes a signed 8-bit integer to the current position.
- */
- inline void writeInt8(int8 i) {
- reserveBytes(1);
- m_buffer[m_pos] = *(uint8*)&i;
- m_pos++;
- }
-
- inline void writeBool8(bool b) {
- writeInt8(b ? 1 : 0);
- }
-
- inline void writeUInt8(uint8 i) {
- reserveBytes(1);
- m_buffer[m_pos] = i;
- m_pos++;
- }
-
- void writeUInt16(uint16 u);
-
- inline void writeInt16(int16 i) {
- writeUInt16(*(uint16*)&i);
- }
-
- void writeUInt32(uint32 u);
-
- inline void writeInt32(int32 i) {
- debugAssert(m_beginEndBits == 0);
- writeUInt32(*(uint32*)&i);
- }
-
- void writeUInt64(uint64 u);
-
- inline void writeInt64(int64 i) {
- writeUInt64(*(uint64*)&i);
- }
-
- inline void writeFloat32(float32 f) {
- debugAssert(m_beginEndBits == 0);
- union {
- float32 a;
- uint32 b;
- };
- a = f;
- writeUInt32(b);
- }
-
- inline void writeFloat64(float64 f) {
- union {
- float64 a;
- uint64 b;
- };
- a = f;
- writeUInt64(b);
- }
-
- /**
- Write a string with NULL termination.
- */
- inline void writeString(const std::string& s) {
- writeString(s.c_str());
- }
-
- void writeString(const char* s);
-
- /**
- Write a string, ensuring that the total length
- including NULL is even.
- */
- void writeStringEven(const std::string& s) {
- writeStringEven(s.c_str());
- }
-
- void writeStringEven(const char* s);
-
-
- void writeString32(const char* s);
-
- /**
- Write a string with a 32-bit length field in front
- of it.
- */
- void writeString32(const std::string& s) {
- writeString32(s.c_str());
- }
-
- void writeVector4(const Vector4& v);
-
- void writeVector3(const Vector3& v);
-
- void writeVector2(const Vector2& v);
-
- void writeColor4(const Color4& v);
-
- void writeColor3(const Color3& v);
-
- /**
- Skips ahead n bytes.
- */
- inline void skip(int n) {
- if (m_pos + n > m_bufferLen) {
- setLength((int)m_pos + (int)m_alreadyWritten + n);
- }
- m_pos += n;
- }
-
- /** Call before a series of BinaryOutput::writeBits calls. Only writeBits
- can be called between beginBits and endBits without corrupting the stream.*/
- void beginBits();
-
- /** Write numBits from bitString to the output stream. Bits are numbered from
- low to high.
-
- Can only be
- called between beginBits and endBits. Bits written are semantically
- little-endian, regardless of the actual endian-ness of the system. That is,
- <CODE>writeBits(0xABCD, 16)</CODE> writes 0xCD to the first byte and
- 0xAB to the second byte. However, if used with BinaryInput::readBits, the ordering
- is transparent to the caller.
- */
- void writeBits(uint32 bitString, int numBits);
-
- /** Call after a series of BinaryOutput::writeBits calls. This will
- finish out with zeros the last byte into which bits were written.*/
- void endBits();
-
-
-# define DECLARE_WRITER(ucase, lcase)\
- void write##ucase(const lcase* out, int n);\
- void write##ucase(const std::vector<lcase>& out, int n);\
- void write##ucase(const Array<lcase>& out, int n);
-
- DECLARE_WRITER(Bool8, bool)
- DECLARE_WRITER(UInt8, uint8)
- DECLARE_WRITER(Int8, int8)
- DECLARE_WRITER(UInt16, uint16)
- DECLARE_WRITER(Int16, int16)
- DECLARE_WRITER(UInt32, uint32)
- DECLARE_WRITER(Int32, int32)
- DECLARE_WRITER(UInt64, uint64)
- DECLARE_WRITER(Int64, int64)
- DECLARE_WRITER(Float32, float32)
- DECLARE_WRITER(Float64, float64)
-# undef DECLARE_WRITER
-
-};
-
-}
-
-#ifdef _MSC_VER
-# pragma warning (pop)
-#endif
-
-#endif
diff --git a/externals/g3dlite/G3D/BoundsTrait.h b/externals/g3dlite/G3D/BoundsTrait.h
deleted file mode 100644
index 15e1418010c..00000000000
--- a/externals/g3dlite/G3D/BoundsTrait.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/**
- @file BoundsTrait.h
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @created 2008-10-01
- @edited 2008-10-01
- Copyright 2000-2009, Morgan McGuire.
- All rights reserved.
- */
-
-#ifndef G3D_BOUNDSTRAIT_H
-#define G3D_BOUNDSTRAIT_H
-
-#include "G3D/platform.h"
-
-template<typename Value>
-struct BoundsTrait{};
-
-#endif
-
diff --git a/externals/g3dlite/G3D/Box.h b/externals/g3dlite/G3D/Box.h
deleted file mode 100644
index 82af9125b05..00000000000
--- a/externals/g3dlite/G3D/Box.h
+++ /dev/null
@@ -1,195 +0,0 @@
-/**
- @file Box.h
-
- Box class
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @cite Portions based on Dave Eberly's Magic Software Library at <A HREF="http://www.magic-software.com">http://www.magic-software.com</A>
- @created 2001-06-02
- @edited 2007-06-05
-
- Copyright 2000-2006, Morgan McGuire.
- All rights reserved.
- */
-
-#ifndef G3D_BOX_H
-#define G3D_BOX_H
-
-#include "G3D/platform.h"
-#include "G3D/Vector3.h"
-#include "G3D/Array.h"
-#include "G3D/Plane.h"
-
-namespace G3D {
-
-class CoordinateFrame;
-
-/**
- An arbitrary 3D box, useful as a bounding box.
-
-
- To construct a box from a coordinate frame, center and extent, use the idiom:
-
- <CODE>Box box = cframe.toObjectSpace(Box(center - extent/2, center + extent/2));</CODE>
- */
-class Box {
-private:
-
- static int32 dummy;
-
- friend class CoordinateFrame;
-
- /**
- <PRE>
- 3 2 7 6
-
- 0 1 4 5
-
- front back (seen through front)
- </PRE>
- */
- Vector3 _corner[8];
-
- /**
- Unit axes.
- */
- Vector3 _axis[3];
-
- Vector3 _center;
-
- /**
- Extent along each axis.
- */
- Vector3 _extent;
-
- float _area;
- float _volume;
-
- void init(
- const Vector3& min,
- const Vector3& max);
-
-public:
-
- /**
- Does not initialize the fields.
- */
- Box();
-
- /**
- Constructs a box from two opposite corners.
- */
- Box(
- const Vector3& min,
- const Vector3& max);
-
- static Box inf();
-
- Box(class BinaryInput& b);
-
- Box(const class AABox& b);
-
- void serialize(class BinaryOutput& b) const;
- void deserialize(class BinaryInput& b);
-
- /**
- Returns the object to world transformation for
- this box. localFrame().worldToObject(...) takes
- objects into the space where the box axes are
- (1,0,0), (0,1,0), (0,0,1). Note that there
- is no scaling in this transformation.
- */
- CoordinateFrame localFrame() const;
-
- void getLocalFrame(CoordinateFrame& frame) const;
-
- /**
- Returns the centroid of the box.
- */
- inline Vector3 center() const {
- return _center;
- }
-
-
- inline Vector3 corner(int i) const {
- debugAssert(i < 8);
- return _corner[i];
- }
-
- /**
- Unit length.
- */
- inline Vector3 axis(int a) const {
- debugAssert(a < 3);
- return _axis[a];
- }
-
- /**
- Distance from corner(0) to the next corner
- along the box's local axis a.
- */
- inline float extent(int a) const {
- debugAssert(a < 3);
- return (float)_extent[a];
- }
-
- inline Vector3 extent() const {
- return _extent;
- }
-
- /**
- Returns the four corners of a face (0 <= f < 6).
- The corners are returned to form a counter clockwise quad facing outwards.
- */
- void getFaceCorners(
- int f,
- Vector3& v0,
- Vector3& v1,
- Vector3& v2,
- Vector3& v3) const;
-
-
- /**
- See AABox::culledBy
- */
- bool culledBy
- (
- const Array<Plane>& plane,
- int32& cullingPlaneIndex,
- const uint32 testMask,
- uint32& childMask) const;
-
- /**
- Conservative culling test that does not produce a mask for children.
- */
- bool culledBy
- (
- const Array<Plane>& plane,
- int32& cullingPlaneIndex = dummy,
- const uint32 testMask = -1) const;
-
- bool contains(
- const Vector3& point) const;
-
- float area() const;
-
- float volume() const;
-
- void getRandomSurfacePoint(Vector3& P, Vector3& N = Vector3::ignore()) const;
-
- /**
- Uniformly distributed on the interior (includes surface)
- */
- Vector3 randomInteriorPoint() const;
-
- void getBounds(class AABox&) const;
-
- bool isFinite() const {
- return G3D::isFinite(_volume);
- }
-};
-
-}
-
-#endif
diff --git a/externals/g3dlite/G3D/Box2D.h b/externals/g3dlite/G3D/Box2D.h
deleted file mode 100644
index 80accad89dd..00000000000
--- a/externals/g3dlite/G3D/Box2D.h
+++ /dev/null
@@ -1,121 +0,0 @@
-/**
- @file Box2D.h
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2001-06-02
- @edited 2008-12-27
-
- Copyright 2000-2009, Morgan McGuire.
- All rights reserved.
- */
-
-#ifndef G3D_Box2D_h
-#define G3D_Box2D_h
-
-#include "G3D/platform.h"
-#include "G3D/Vector2.h"
-
-namespace G3D {
-
-class CoordinateFrame;
-typedef class CoordinateFrame CFrame;
-class Rect2D;
-typedef class Rect2D AABox2D;
-
-/**
- 2D oriented box
- @cite http://www.flipcode.com/archives/2D_OBB_Intersection.shtml
- */
-class Box2D {
-private:
- /** Corners of the box, where 0 is the lower left. */
- Vector2 m_corner[4];
-
- /** Two edges of the box extended away from corner[0], with length
- = 1 / extentSquared */
- Vector2 m_axisin[2];
-
- /** Two edges of the box extended away from corner[0], with unit length */
- Vector2 m_axis[2];
-
- /** Centroid of the box */
- Vector2 m_center;
-
- /** origin[a] = m_corner[0].dot(m_axisin[a]); */
- float origin[2];
-
- /** Surface area */
- float m_area;
-
- Vector2 m_extent;
-
- /** Returns true if other overlaps one dimension of this. */
- bool overlaps1Way(const Box2D& other) const;
-
-
- /** Updates the axes after the m_corners move. Assumes the
- m_corners actually form a rectangle. */
- void computeAxes();
-
-public:
-
- /**
- @param center World-space center
- @param w Width along object-space x-axis
- @param h Height along object-space y-axis
- @param angle Counter-clockwise angle from object-space x-axis in radians
- */
- Box2D(const Vector2& center = Vector2(0, 0), float w = 0, float h = 0, float angle = 0);
-
- Box2D(const AABox2D& b);
-
- Box2D(const Vector2& min, const Vector2& max);
-
- /** Transform @a b by @a frame, discarding the Z components, and
- compute the new box.*/
- Box2D(const CFrame& frame, Box2D& b);
-
- inline bool contains(const Vector2& v) const {
- // Take to object space:
- const Vector2& p = v - m_center;
- float x = p.dot(m_axisin[0]);
- float y = p.dot(m_axisin[1]);
-
- // Must be within extent/2 on both axes in object space
- return (abs(x) <= 0.5f) && (abs(y) <= 0.5f);
- }
-
- /** @brief Distance from corner(0) to the next corner along the box's local axis a. */
- inline const Vector2& extent() const {
- return m_extent;
- }
-
- /** @brief Unit length vector along axis @a a */
- inline const Vector2& axis(int a) const {
- debugAssert(a == 0 || a == 1);
- return m_axis[a];
- }
-
- /** @brief Surface area */
- inline float area() const {
- return m_area;
- }
-
- inline const Vector2& corner(int i) const {
- debugAssert(i >=0 && i <= 3);
- return m_corner[i];
- }
-
- inline const Vector2& center() const {
- return m_center;
- }
-
- /** Returns true if the intersection of the boxes is non-empty. */
- inline bool overlaps(const Box2D& other) const {
- return overlaps1Way(other) && other.overlaps1Way(*this);
- }
-};
-
-} // G3D
-#endif
diff --git a/externals/g3dlite/G3D/BumpMapPreprocess.h b/externals/g3dlite/G3D/BumpMapPreprocess.h
deleted file mode 100644
index 955f99e61b2..00000000000
--- a/externals/g3dlite/G3D/BumpMapPreprocess.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/**
- \file BumpMapPreprocess.h
-
- \maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- \created 2010-01-28
- \edited 2010-01-28
-
- Copyright 2000-2010, Morgan McGuire.
- All rights reserved.
- */
-
-#ifndef G3D_BumpMapPreprocess_h
-#define G3D_BumpMapPreprocess_h
-
-#include "G3D/platform.h"
-
-namespace G3D {
-class Any;
-
-/**
-Not in the BumpMap class to avoid a circular dependency between Texture and BumpMap.
-G3D::GImage::computeNormalMap().
-*/
-class BumpMapPreprocess {
-public:
-
- /** If true, the elevations are box filtered after computing normals
- and before uploading, which produces better results for parallax offset mapping
- Defaults to false. */
- bool lowPassFilter;
-
- /** Height of the maximum ("white") value, in pixels, for the purpose of computing normals.
- A value of 255 means that a 255 x 255 bump image with a full black-to-white gradient
- will produce a 45-degree ramp (this also results in "cubic" voxels).
- A negative value means to set zExtentPixels to -zExtentPixels * max(width, height).
- The default is -0.02.
- */
- float zExtentPixels;
-
- /** After computing normals, scale the height by |N.z|, a trick that reduces texture swim in steep areas for parallax offset
- mapping. Defaults to false.*/
- bool scaleZByNz;
-
- BumpMapPreprocess() : lowPassFilter(false), zExtentPixels(-0.02f), scaleZByNz(false) {}
-
- BumpMapPreprocess(const Any& any);
-
- operator Any() const;
-
- bool operator==(const BumpMapPreprocess& other) const {
- return
- (lowPassFilter == other.lowPassFilter) &&
- (zExtentPixels == other.zExtentPixels) &&
- (scaleZByNz == other.scaleZByNz);
- }
-};
-
-}
-
-#endif
diff --git a/externals/g3dlite/G3D/Capsule.h b/externals/g3dlite/G3D/Capsule.h
deleted file mode 100644
index baeea3aa82b..00000000000
--- a/externals/g3dlite/G3D/Capsule.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/**
- @file Capsule.h
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2003-02-07
- @edited 2005-08-20
-
- Copyright 2000-2006, Morgan McGuire.
- All rights reserved.
- */
-
-#ifndef G3D_CAPSULE_H
-#define G3D_CAPSULE_H
-
-#include "G3D/platform.h"
-#include "G3D/g3dmath.h"
-#include "G3D/Vector3.h"
-
-namespace G3D {
-
-class Line;
-class AABox;
-/**
- A shape formed by extruding a sphere along a line segment.
- */
-class Capsule {
-private:
- Vector3 p1;
- Vector3 p2;
-
- float _radius;
-public:
-
-
- /** Uninitialized */
- Capsule();
- Capsule(class BinaryInput& b);
- Capsule(const Vector3& _p1, const Vector3& _p2, float _r);
- void serialize(class BinaryOutput& b) const;
- void deserialize(class BinaryInput& b);
-
- /** The line down the center of the capsule */
- Line axis() const;
-
- inline float radius() const {
- return _radius;
- }
-
- /** Argument may be 0 or 1 */
- inline Vector3 point(int i) const {
- debugAssert(i == 0 || i == 1);
- return (i == 0) ? p1 : p2;
- }
-
- /** Distance between the sphere centers. The total extent of the cylinder is
- 2r + h. */
- inline float height() const {
- return (p1 - p2).magnitude();
- }
-
- inline Vector3 center() const {
- return (p1 + p2) / 2.0;
- }
-
- /** Get a reference frame in which the center of mass is the origin and Y is the axis of the capsule.*/
- void getReferenceFrame(class CoordinateFrame& cframe) const;
-
- /**
- Returns true if the point is inside the capsule or on its surface.
- */
- bool contains(const Vector3& p) const;
-
- float volume() const;
-
- float area() const;
-
- /** Get axis aligned bounding box */
- void getBounds(AABox& out) const;
-
- /** Random world space point with outward facing normal. */
- void getRandomSurfacePoint(Vector3& P, Vector3& N) const;
-
- /** Point selected uniformly at random over the volume. */
- Vector3 randomInteriorPoint() const;
-};
-
-} // namespace
-
-#endif
diff --git a/externals/g3dlite/G3D/CollisionDetection.h b/externals/g3dlite/G3D/CollisionDetection.h
deleted file mode 100644
index c8fcf5534c2..00000000000
--- a/externals/g3dlite/G3D/CollisionDetection.h
+++ /dev/null
@@ -1,1205 +0,0 @@
-/**
- @file CollisionDetection.h
-
-
- Moving collision detection for simple primitives.
-
- @author Morgan McGuire, http://graphics.cs.williams.edu
- @cite Spherical collision based on Paul Nettle's
- ftp://ftp.3dmaileffects.com/pub/FluidStudios/CollisionDetection/Fluid_Studios_Generic_Collision_Detection_for_Games_Using_Ellipsoids.pdf
- and comments by Max McGuire. Ray-sphere intersection by Eric Haines.
- Box-Box intersection written by Kevin Egan.
- Thanks to Max McGuire of Iron Lore for various bug fixes.
- Box-Triangle by Tomas Akenine-Moller
-
- @created 2001-11-19
- @edited 2008-12-19
-
- Copyright 2000-2009, Morgan McGuire.
- All rights reserved.
- */
-
-#ifndef G3D_COLLISIONDETECTION_H
-#define G3D_COLLISIONDETECTION_H
-
-#include "G3D/platform.h"
-#include "G3D/Vector3.h"
-#include "G3D/Plane.h"
-#include "G3D/Box.h"
-#include "G3D/Triangle.h"
-#include "G3D/Array.h"
-#include "G3D/Ray.h"
-#include "G3D/Line.h"
-
-namespace G3D {
-
-
-/**
- Collision detection primitives and tools for building
- higher order collision detection schemes.
-
- These routines provide <I>moving</I> and static collision detection.
- Moving collision detection allows the calculation of collisions that
- occur during a period of time -- as opposed to the intersection of
- two static bodies.
-
- Moving collision detection routines detect collisions between
- <I>only</I> static primitives and moving spheres or points. Since the
- reference frame can be user defined, these functions can be used to
- detect the collision between two moving bodies by subtracting
- the velocity vector of one object from the velocity vector of the
- sphere or point the detection is to occur with. This unified
- velocity vector will act as if both objects are moving simultaneously.
-
- Collisions are detected for single-sided objects only. That is,
- no collision is detected when <I>leaving</I> a primitive or passing
- through a plane or triangle opposite the normal... except for the
- point-sphere calculation or when otherwise noted.
-
- For a sphere, the collision location returned is the point in world
- space where the surface of the sphere and the fixed object meet.
- It is <B>not</B> the position of the center of the sphere at
- the time of the collision.
-
- The collision normal returned is the surface normal to the fixed
- object at the collision location.
-
- <p>
- <b>Static Collision Detection:</b> (Neither object is moving)
-
- <table>
- <tr><td></td><td><b>Vector3</b></td><td><b>LineSegment</b></td><td><b>Ray *</b></td><td><b>Line</b></td><td><b>Plane</b></td><td><b>Triangle</b></td><td><b>Sphere</b></td><td><b>Cylinder</b></td><td><b>Capsule</b></td><td><b>AABox</b></td><td><b>Box</b></td></tr>
- <tr><td><b>Vector3</b></td><td>\link Vector3::operator== V3::==\endlink \link Vector3::fuzzyEq V3::fuzzy \endlink \link G3D::distance distance \endlink</td><td bgcolor=#C0C0C0 colspan=10 ></td></tr>
- <tr><td><b>LineSegment</b></td><td>\link LineSegment::closestPoint LS::closestPoint\endlink \link LineSegment::distance LS::distance\endlink \link CollisionDetection::closestPointOnLineSegment CD\endlink</td><td></td><td bgcolor=#C0C0C0 colspan=9 ></td></tr>
- <tr><td><b>Ray *</b></td><td>Ray::closestPoint Ray::distance</td><td></td><td></td><td bgcolor=#C0C0C0 colspan=8 ></td></tr>
- <tr><td><b>Line</b></td><td>Line::closestPoint Line::distance</td><td></td><td>\link CollisionDetection::closestPointsBetweenLineAndLine CD\endlink</td><td></td><td bgcolor=#C0C0C0 colspan=7 ></td></tr>
- <tr><td><b>Plane</b></td><td></td><td></td><td></td><td></td><td></td><td bgcolor=#C0C0C0 colspan=6 ></td></tr>
- <tr><td><b>Triangle</b></td><td></td><td></td><td></td><td></td><td></td><td></td><td bgcolor=#C0C0C0 colspan=5 ></td></tr>
- <tr><td><b>Sphere</b></td><td>Sphere::contains</td><td></td><td>\link CollisionDetection::collisionTimeForMovingPointFixedSphere CD \endlink, \link Ray::intersectionTime R::time\endlink</td><td></td><td></td><td></td><td></td><td bgcolor=#C0C0C0 colspan=4 ></td></tr>
- <tr><td><b>Cylinder</b></td><td>Cylinder::contains</td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td bgcolor=#C0C0C0 colspan=3 ></td></tr>
- <tr><td><b>Capsule</b></td><td>Capsule::contains</td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td bgcolor=#C0C0C0 colspan=2 ></td></tr>
- <tr><td><b>AABox</b></td><td>AABox::contains</td><td></td><td></td><td></td><td></td><td>\link CollisionDetection::fixedSolidBoxIntersectsFixedTriangle CD\endlink</td><td></td><td></td><td></td><td></td><td bgcolor=#C0C0C0 colspan=1 ></td></tr>
- <tr><td><b>Box</b></td><td>Box::contains</td><td>(treat as Ray)</td><td>\link CollisionDetection::collisionTimeForMovingPointFixedBox CD\endlink</td><td>(treat as Ray)</td><td>\link CollisionDetection::penetrationDepthForFixedBoxFixedPlane CD \endlink</td><td>\link CollisionDetection::penetrationDepthForFixedBoxFixedPlane CD\endlink</td><td>\link CollisionDetection::penetrationDepthForFixedSphereFixedBox CD\endlink</td><td>None (use OPCODE)</td><td>\link CollisionDetection::movingSpherePassesThroughFixedBox CD \endlink</td><td>\link CollisionDetection::penetrationDepthForFixedBoxFixedBox CD\endlink</td><td>\link CollisionDetection::penetrationDepthForFixedBoxFixedBox CD\endlink</td></tr>
- </table>
-
- <p>
- <b>Moving Collision Detection:</b>
-
- <i>* Note: Moving collision detection against certain primitives is equivalent to static collision
- detection against a bigger primitive. Ray, Line Segment == ``moving Point''; Capsule ==``moving Sphere''; Plane == ``moving Line''</i>
-
- @deprecated Routines moving to the G3D::Intersect class in G3D 8.0
- */
-class CollisionDetection {
-private:
-
- /**
- Default parameter if value passed to a function as reference is
- not to be calculated. Must be explicitly supported by function.
- */
- static Vector3 ignore;
-
- /**
- Default parameter if value passed to a function as reference is
- not to be calculated. Must be explicitly supported by function.
- */
- static bool ignoreBool;
-
- /**
- Default parameter if value passed to a function as reference is
- not to be calculated. Must be explicitly supported by function.
- */
- static Array<Vector3> ignoreArray;
-
-
- // Static class!
- CollisionDetection() {}
- virtual ~CollisionDetection() {}
-
-public:
-
- /**
- Converts an index [0, 15] to the corresponding separating axis.
- Does not return normalized vector in the edge-edge case
- (indices 6 through 15).
-
- @param separatingAxisIndex Separating axis.
- @param box1 Box 1.
- @param box2 Box 2.
-
- @return Axis that separates the two boxes.
- */
- static Vector3 separatingAxisForSolidBoxSolidBox(
- const int separatingAxisIndex,
- const Box & box1,
- const Box & box2);
-
- /**
- Tests whether two boxes have axes that are parallel to
- each other. If they are, axis1 and axis2 are set to be
- the parallel axes for both box1 and box2 respectively.
-
- @param ca Dot products of each of the boxes axes
- @param epsilon Fudge factor (small unit by which the dot
- products may vary and still be considered
- zero).
- @param axis1 Parallel Axis 1. [Post Condition]
- @param axis2 Parallel Axis 2. [Post Condition]
-
- @return true - If boxes have a parallel axis
- @return false - otherwise.
- */
- static bool parallelAxisForSolidBoxSolidBox(
- const double* ca,
- const double epsilon,
- int & axis1,
- int & axis2);
-
- /**
- Calculates the projected distance between the two boxes along
- the specified separating axis, negative distances correspond
- to an overlap along that separating axis. The distance is not
- divided by denominator dot(L, L), see
- penetrationDepthForFixedSphereFixedBox() for more details
-
- @param separatingAxisIndex
- @param a Box 1's bounding sphere vector
- @param b Box 2's bounding sphere vector
- @param D Vector between Box 1 and Box 2's center points
- @param c Pointer to array of dot products of the axes of Box 1
- and Box 2.
- @param ca Pointer to array of unsigned dot products of the axes
- of Box 1 and Box 2.
- @param ad Pointer to array of dot products of Box 1 axes and D.
- @param bd Pointer to array of dot products of Box 2 axes and D.
-
- @return Projected distance between the two boxes along the
- specified separating axis.
- */
- static float projectedDistanceForSolidBoxSolidBox(
- const int separatingAxisIndex,
- const Vector3 & a,
- const Vector3 & b,
- const Vector3 & D,
- const double* c,
- const double* ca,
- const double* ad,
- const double* bd);
-
-
- /**
- Creates a set of standard information about two boxes in order to
- solve for their collision. This information includes a vector to
- the radius of the bounding sphere for each box, the vector between
- each boxes' center and a series of dot products between differing
- important vectors. These dot products include those between the axes
- of both boxes (signed and unsigned values), and the dot products
- between all the axes of box1 and the boxes' center vector and box2
- and the boxes' center vector.
-
- @pre The following space requirements must be met:
- - c[] 9 elements
- - ca[] 9 elements
- - ad[] 3 elements
- - bd[] 3 elements
-
- @cite dobted from David Eberly's papers, variables used in this function
- correspond to variables used in pages 6 and 7 in the pdf
- http://www.magic-software.com/Intersection.html
- http://www.magic-software.com/Documentation/DynamicCollisionDetection.pdf
-
- @note Links are out-dated. (Kept to preserve origin and authorship)
-
- @param box1 Box 1
- @param box2 Box 2
- @param a Box 1's bounding sphere vector
- @param b Box 2's bounding sphere vector
- @param D Vector between Box 1 and Box 2's center points
- @param c Pointer to array of dot products of the axes of Box 1
- and Box 2.
- @param ca Pointer to array of unsigned dot products of the axes
- of Box 1 and Box 2.
- @param ad Pointer to array of dot products of Box 1 axes and D.
- @param bd Pointer to array of dot products of Box 2 axes and D.
- */
- static void fillSolidBoxSolidBoxInfo(
- const Box & box1,
- const Box & box2,
- Vector3 & a,
- Vector3 & b,
- Vector3 & D,
- double* c,
- double* ca,
- double* ad,
- double* bd);
-
- /**
- Performs a simple bounding sphere check between two boxes to determine
- whether these boxes could <i>possibly</i> intersect. This is a very
- cheap operation (three dot products, two sqrts and a few others). If
- it returns true, an intersection is possible, but not necessarily
- guaranteed.
-
- @param a Vector from box A's center to an outer vertex
- @param b Vector from box B's center to an outer vertex
- @param D Distance between the centers of the two boxes
-
- @return true - if possible intersection
- @return false - otherwise (This does not guarantee an intersection)
- */
- static bool conservativeBoxBoxTest(
- const Vector3 & a,
- const Vector3 & b,
- const Vector3 & D);
-
- /**
- Determines whether two fixed solid boxes intersect.
-
- @note To speed up collision detection, the lastSeparatingAxis from
- the previous time step can be passed in and that plane can be
- checked first. If the separating axis was not saved, or if the
- two boxes intersected then lastSeparatingAxis should equal -1.
-
- @cite Adobted from David Eberly's papers, variables used in this function
- correspond to variables used in pages 6 and 7 in the pdf
- http://www.magic-software.com/Intersection.html
- http://www.magic-software.com/Documentation/DynamicCollisionDetection.pdf
-
- @param box1 Box 1.
- @param box2 Box 2.
- @param lastSeparatingAxis Last separating axis.
- (optimization - see note)
-
- @return true - Intersection.
- @return false - otherwise.
- */
- static bool fixedSolidBoxIntersectsFixedSolidBox(
- const Box& box1,
- const Box& box2,
- const int lastSeparatingAxis = -1);
-
- /**
- Calculates the closest points on two lines with each other. If the
- lines are parallel then using the starting point, else calculate the
- closest point on each line to the other.
-
- @note This is very similiar to calculating the intersection of two lines.
- Logically then, the two points calculated would be identical if calculated
- with inifinite precision, but with the finite precision of floating point
- calculations, these values could (will) differ as the line slope approaches
- zero or inifinity.
-
- @cite variables and algorithm based on derivation at the following website:
- http://softsurfer.com/Archive/algorithm_0106/algorithm_0106.htm
-
- @param line1 Line 1.
- @param line2 Line 2.
- @param closest1 Closest point on line 1.
- @param closest2 Closest point on line 2.
- */
- static void closestPointsBetweenLineAndLine(
- const Line & line1,
- const Line & line2,
- Vector3 & closest1,
- Vector3 & closest2);
-
- /**
- Calculates the depth of penetration between two fixed boxes.
- Contact normal faces away from box1 and into box2. If there is
- contact, only one contact point is returned. The minimally
- violated separating plane is computed
- - if the separating axis corresponds to a face
- the contact point is half way between the deepest vertex
- and the face
- - if the separating axis corresponds to two edges
- the contact point is the midpoint of the smallest line
- segment between the two edge lines
-
- @note This is very similiar to calculating the intersection of two lines.
- Logically then, the two points calculated would be identical if calculated
- with inifinite precision, but with the finite precision of floating point
- calculations, these values could (will) differ as the line slope approaches
- zero or inifinity.
-
- @cite adobted from David Eberly's papers, variables used in this function
- correspond to variables used in pages 6 and 7 in the pdf
- http://www.magic-software.com/Intersection.html
- http://www.magic-software.com/Documentation/DynamicCollisionDetection.pdf
-
- @param box1 Box 1
- @param box2 Box 2
- @param contactPoints Contact point between boxes. [Post Condition]
- @param contactNormals Surface normal at contact point. [Post Condition]
- @param lastSeparatingAxis Last separating axis. (Used for optimization)
-
- @return Depth of penetration between the two boxes. If there is no
- intersection between the boxes, then a negative value is returned.
- */
- static float penetrationDepthForFixedBoxFixedBox(
- const Box& box1,
- const Box& box2,
- Array<Vector3>& contactPoints,
- Array<Vector3>& contactNormals,
- const int lastSeparatingAxis = -1);
-
- /**
- Calculates the depth of penetration between two fixed spheres as well
- as the deepest point of Sphere A that penetrates Sphere B. The normal
- returned points <B>away</B> from the object A, although it may
- represent a perpendicular to either the faces of object B or object A
- depending on their relative orientations.
-
- @param sphereA Fixed Sphere A.
- @param sphereB Fixed Sphere B.
- @param contactPoints Sphere A's deepest point that penetrates Sphere B.
- [Post Condition]
- @param contactNormals Normal at penetration point. [Post Condition]
-
- @return Depth of penetration. If there is no intersection between the
- objects then the depth will be a negative value.
- */
- static float penetrationDepthForFixedSphereFixedSphere(
- const class Sphere& sphereA,
- const Sphere& sphereB,
- Array<Vector3>& contactPoints,
- Array<Vector3>& contactNormals = ignoreArray);
-
- /**
- Calculates the depth of penetration between a fixed sphere and a fixed
- box as well as the deepest point of the sphere that penetrates the box
- and the normal at that intersection.
-
- @note There are three possible intersections between a sphere and box.
- - Sphere completely contained in the box
- - Sphere intersects one edge
- - Sphere intersects one vertex
-
- The contact point and contact normal vary for each of these situations.
- - Sphere contained in Box:
- - Normal is based on side of least penetration (as is the depth calculation).
- - Point is based on center of sphere
- - Sphere intersects one edge
- - Normal is based on vector from the box center to the point of depth.
- - Point is closest point to the sphere on the line
- - Sphere intersects one vertex
- - Normal is based on vector from the box center to the vertex of penetration.
- - Point is vertex of penetration.
-
- @cite Adapted from Jim Arvo's method in Graphics Gems
- See also http://www.win.tue.nl/~gino/solid/gdc2001depth.pdf
-
- @param sphere Fixed Sphere.
- @param box Fixed Box.
- @param contactPoints Sphere point that penetrates the box. [Post Condition]
- @param contactNormals Normal at the penetration point. [Post Condition]
-
- @return Depth of penetration. If there is no intersection between the
- objects then the depth will be a negative value.
- */
- static float penetrationDepthForFixedSphereFixedBox(
- const Sphere& sphere,
- const Box& box,
- Array<Vector3>& contactPoints,
- Array<Vector3>& contactNormals = ignoreArray);
-
- /**
- Calculates the depth of penetration between a Fixed Sphere and a Fixed
- Plane as well as the deepest point of the sphere that penetrates the plane
- and the plane normal at that intersection.
-
- @param sphereA Fixed Sphere.
- @param planeB Fixed Plane.
- @param contactPoints Sphere point that penetrates the plane.
- [Post Condition]
- @param contactNormals Normal at penetration point. [Post Condition]
-
- @return Depth of penetration. If there is no intersection between the
- objects then the depth will be a negative value.
- */
- static float penetrationDepthForFixedSphereFixedPlane(
- const Sphere& sphereA,
- const class Plane& planeB,
- Array<Vector3>& contactPoints,
- Array<Vector3>& contactNormals = ignoreArray);
-
- /**
- Calculates the depth of penetration between a fixed box and a fixed
- plane as well as the vertexes of the box that penetrate the plane
- and the plane normals at those intersections.
-
- @param box Fixed Box.
- @param plane Fixed Plane.
- @param contactPoints Box points that penetrate the plane.
- [Post Condition]
- @param contactNormals Normals at penetration points [Post Condition]
-
- @return Depth of penetration. If there is no intersection between the
- objects then the depth will be a negative value.
- */
- static float penetrationDepthForFixedBoxFixedPlane(
- const Box& box,
- const Plane& plane,
- Array<Vector3>& contactPoints,
- Array<Vector3>& contactNormals = ignoreArray);
-
- /**
- Calculates time between the intersection of a moving point and a fixed
- plane.
-
- @note This is only a one sided collision test. The side defined by
- the plane's surface normal is the only one tested. For a two sided
- collision, call the function once for each side's surface normal.
-
- @param point Moving point.
- @param velocity Point's velocity.
- @param plane Fixed plane.
- @param location Location of collision. [Post Condition]
- (Infinite vector on no collision)
- @param outNormal Plane's surface normal. [Post Condition]
-
- @return Time til collision. If there is no collision then the return
- value will be inf().
- */
- static float collisionTimeForMovingPointFixedPlane(
- const Vector3& point,
- const Vector3& velocity,
- const class Plane& plane,
- Vector3& outLocation,
- Vector3& outNormal = ignore);
-
- /**
- Calculates time between the intersection of a moving point and a fixed
- triangle.
-
- @note This is only a one sided collision test. The side defined by
- the triangle's surface normal is the only one tested. For a two sided
- collision, call the function once for each side's surface normal.
-
- @param orig Moving point.
- @param dir Point's velocity.
- @param v0 Triangle vertex 1.
- @param v1 Triangle vertex 2.
- @param v2 Triangle vertex 3
-
- @return Time til collision. If there is no collision then the return
- value will be inf().
- */
- inline static float collisionTimeForMovingPointFixedTriangle(
- const Vector3& orig,
- const Vector3& dir,
- const Vector3& v0,
- const Vector3& v1,
- const Vector3& v2) {
- return Ray::fromOriginAndDirection(orig, dir).intersectionTime(v0, v1, v2);
- }
-
- /**
- Calculates time between the intersection of a moving point and a fixed
- triangle.
-
- @note This is only a one sided collision test. The side defined by
- the triangle's surface normal is the only one tested. For a two sided
- collision, call the function once for each side's surface normal.
-
- @param orig Moving point.
- @param dir Point's velocity.
- @param v0 Triangle vertex 1.
- @param v1 Triangle vertex 2.
- @param v2 Triangle vertex 3
- @param location Location of collision. [Post Condition]
- (Infinite vector on no collision)
-
- @return Time til collision. If there is no collision then the return
- value will be inf().
- */
- inline static float collisionTimeForMovingPointFixedTriangle(
- const Vector3& orig,
- const Vector3& dir,
- const Vector3& v0,
- const Vector3& v1,
- const Vector3& v2,
- Vector3& location) {
- float t = collisionTimeForMovingPointFixedTriangle(orig, dir, v0, v1, v2);
- if (t < finf()) {
- location = orig + dir * t;
- }
- return t;
- }
-
- /**
- Calculates time between the intersection of a moving point and a fixed
- triangle.
-
- @note This is only a one sided collision test. The side defined by
- the triangle's surface normal is the only one tested. For a two sided
- collision, call the function once for each side's surface normal.
-
- @param orig Moving point.
- @param dir Point's velocity.
- @param tri Fixed triangle.
- @param location Location of collision. [Post Condition]
- (Infinite vector on no collision)
- @param normal Triangle's surface normal. [Post Condition]
-
- @return Time til collision. If there is no collision then the return
- value will be inf().
- */
- inline static float collisionTimeForMovingPointFixedTriangle(
- const Vector3& orig,
- const Vector3& dir,
- const Triangle& tri,
- Vector3& location = ignore,
- Vector3& normal = ignore) {
-
- float t = collisionTimeForMovingPointFixedTriangle(
- orig, dir, tri.vertex(0), tri.vertex(1), tri.vertex(2));
-
- if ((t < finf()) && (&location != &ignore)) {
- location = orig + dir * t;
- normal = tri.normal();
- }
- return t;
- }
-
- /**
- Calculates time between the intersection of a moving point and a fixed
- triangle.
-
- @note This is only a one sided collision test. The side defined by
- the triangle's surface normal is the only one tested. For a two sided
- collision, call the function once for each side's surface normal.
-
- @param orig Moving point.
- @param dir Point's velocity.
- @param v0 Triangle vertex 1.
- @param v1 Triangle vertex 2.
- @param v2 Triangle vertex 3
- @param location Location of collision. [Post Condition]
- (Infinite vector on no collision)
- @param normal Triangle's surface normal. [Post Condition]
-
- @return Time til collision. If there is no collision then the return
- value will be inf().
- */
- inline static float collisionTimeForMovingPointFixedTriangle(
- const Vector3& orig,
- const Vector3& dir,
- const Vector3& v0,
- const Vector3& v1,
- const Vector3& v2,
- Vector3& location,
- Vector3& normal) {
- float t = collisionTimeForMovingPointFixedTriangle(orig, dir, v0, v1, v2);
- if (t < finf()) {
- location = orig + dir * t;
- normal = (v1 - v0).cross(v2 - v0).direction();
- }
- return t;
- }
-
- /**
- If the ray origin is inside the box, returns inf() but inside
- is set to true.
- <B>Beta API</B>
-
- @cite Andrew Woo, from "Graphics Gems", Academic Press, 1990
- @cite Optimized code by Pierre Terdiman, 2000 (~20-30% faster on Celeron 500)
- @cite Epsilon value added by Klaus Hartmann
- @cite http://www.codercorner.com/RayAABB.cpp
- */
- static float collisionTimeForMovingPointFixedAABox(
- const Vector3& point,
- const Vector3& velocity,
- const class AABox& box,
- Vector3& outLocation,
- bool& inside = ignoreBool,
- Vector3& outNormal = ignore);
-
- /**
- Calculates time between the intersection of a moving point and a fixed
- Axis-Aligned Box (AABox).
-
- @note Avoids the sqrt from collisionTimeForMovingPointFixedAABox.
-
- @param point Moving point.
- @param velocity Sphere's velocity.
- @param box Fixed AAbox.
- @param location Location of collision. [Post Condition]
- @param Inside Does the ray originate inside the box? [Post Condition]
- @param normal Box's surface normal to collision [Post Condition]
-
- @return Time til collision. If there is no collision then the return
- value will be inf().
- */
- static bool collisionLocationForMovingPointFixedAABox(
- const Vector3& point,
- const Vector3& velocity,
- const class AABox& box,
- Vector3& outLocation,
- bool& inside = ignoreBool,
- Vector3& normal = ignore);
-
-
- /**
- @brief Calculates intersection of a ray and a static
- Axis-Aligned Box (AABox).
-
- @note Avoids the sqrt from collisionTimeForMovingPointFixedAABox;
- early-out branches and operations optimized for Intel Core2 architecture.
-
- @param invDir 1/dir
- @param location Location of collision. [Post Condition]
- @param inside Does the ray originate inside the box? [Post Condition]
-
- @return True if the ray hits the box
- */
- static bool __fastcall rayAABox(
- const Ray& ray,
- const Vector3& invDir,
- const AABox& box,
- const Vector3& boxCenter,
- float boundingRadiusSquared,
- Vector3& location,
- bool& inside);
-
- /**
- Calculates time between the intersection of a moving point and a fixed
- sphere.
-
- @note When ray is starts inside the rectangle, the exiting intersection
- is detected.
-
- @param point Moving point.
- @param velocity Point's velocity.
- @param sphere Fixed Sphere.
- @param outLocation Location of collision. [Post Condition]
- @param outNormal Sphere's surface normal to collision [Post Condition]
- \param solid If true, rays inside the sphere immediately intersect (good for collision detection). If false, they hit the opposite side of the sphere (good for ray tracing).
-
- @return Time until collision. If there is no collision then the return
- value will be inf().
- */
- static float collisionTimeForMovingPointFixedSphere(
- const Vector3& point,
- const Vector3& velocity,
- const class Sphere& sphere,
- Vector3& outLocation,
- Vector3& outNormal = ignore,
- bool solid = false);
-
- /**
- Calculates time between the intersection of a moving point and a fixed
- box.
-
- @note If the point is already inside the box, no collision: inf is returned.
-
- @param point Moving point.
- @param velocity Sphere's velocity.
- @param box Fixed box.
- @param location Position of collision. [Post Condition]
- @param outNormal Box's surface normal to collision [Post Condition]
-
- @return Time til collision. If there is no collision then the return
- value will be inf().
- */
- static float collisionTimeForMovingPointFixedBox(
- const Vector3& point,
- const Vector3& velocity,
- const class Box& box,
- Vector3& outLocation,
- Vector3& outNormal = ignore);
-
- /**
- Calculates time between the intersection of a moving point and a fixed
- rectangle defined by the points v0, v1, v2, & v3.
-
- @note This is only a one sided collision test. The side defined by
- the rectangle's surface normal is the only one tested. For a two sided
- collision, call the function once for each side's surface normal.
-
- @param point Moving point.
- @param velocity Sphere's velocity.
- @param v0 Rectangle vertex 1.
- @param v1 Rectangle vertex 2.
- @param v2 Rectangle vertex 3
- @param v3 Rectangle vertex 4.
- @param location Location of collision [Post Condition]
- @param outNormal Rectangle's surface normal. [Post Condition]
-
- @return Time til collision. If there is no collision then the return
- value will be inf().
- */
- static float collisionTimeForMovingPointFixedRectangle(
- const Vector3& point,
- const Vector3& velocity,
- const Vector3& v0,
- const Vector3& v1,
- const Vector3& v2,
- const Vector3& v3,
- Vector3& outLocation,
- Vector3& outNormal = ignore);
-
- /**
- Calculates time between the intersection of a moving point and a fixed
- capsule.
-
- @param point Moving point.
- @param velocity Point's velocity.
- @param capsule Fixed capsule.
- @param outLocation Location of collision. [Post Condition]
- @param outNormal Capsule's surface normal to collision [Post Condition]
-
- @return Time til collision. If there is no collision then the return
- value will be inf().
- */
- static float collisionTimeForMovingPointFixedCapsule(
- const Vector3& point,
- const Vector3& velocity,
- const class Capsule& capsule,
- Vector3& outLocation,
- Vector3& outNormal = ignore);
-
- /**
- Calculates time between the intersection of a moving sphere and a fixed
- triangle.
-
- @param sphere Moving sphere.
- @param velocity Sphere's velocity.
- @param plane Fixed Plane.
- @param outLocation Location of collision -- not center position of sphere
- at the collision time. [Post Condition]
- @param outNormal Box's surface normal to collision [Post Condition]
-
- @return Time til collision. If there is no collision then the return
- value will be inf().
- */
- static float collisionTimeForMovingSphereFixedPlane(
- const class Sphere& sphere,
- const Vector3& velocity,
- const class Plane& plane,
- Vector3& outLocation,
- Vector3& outNormal = ignore);
-
- /**
- Calculates time between the intersection of a moving sphere and a fixed
- triangle.
-
- @param sphere Moving sphere.
- @param velocity Sphere's velocity.
- @param triangle Fixed Triangle. (collisions can happen on the back side of the triangle)
- @param outLocation Location of collision, if collision occurs -- not center position of sphere
- at the collision time. If there is interpenetration at the start, this point may be inside
- the sphere.
- @param b Barycentric coordinates. These are not valid unless collision occurs.
-
- @return Time til collision. If there is no collision then the return
- value will be inf().
- */
- static float collisionTimeForMovingSphereFixedTriangle(
- const class Sphere& sphere,
- const Vector3& velocity,
- const Triangle& triangle,
- Vector3& outLocation,
- float b[3] = (float*)&ignore);
-
- /**
- Calculates time between the intersection of a moving sphere and a fixed
- rectangle defined by the points v0, v1, v2, & v3.
-
- @param sphere Moving sphere.
- @param velocity Sphere's velocity.
- @param v0 Rectangle vertex 1.
- @param v1 Rectangle vertex 2.
- @param v2 Rectangle vertex 3
- @param v3 Rectangle vertex 4.
- @param outLocation Location of collision -- not center position of sphere
- at the collision time. [Post Condition]
- @param outNormal Box's surface normal to collision [Post Condition]
-
- @return Time til collision. If there is no collision then the return
- value will be inf().
- */
- static float collisionTimeForMovingSphereFixedRectangle(
- const class Sphere& sphere,
- const Vector3& velocity,
- const Vector3& v0,
- const Vector3& v1,
- const Vector3& v2,
- const Vector3& v3,
- Vector3& outLocation,
- Vector3& outNormal = ignore);
-
- /**
- Calculates time between the intersection of a moving sphere and a fixed
- box.
-
- @note This function will not detect an intersection between a moving object
- that is already interpenetrating the fixed object.
-
- @param sphere Moving sphere.
- @param velocity Sphere's velocity.
- @param box Fixed box.
- @param location Location of collision -- not center position of sphere
- at the collision time. [Post Condition]
- @param outNormal Box's surface normal to collision [Post Condition]
-
- @return Time til collision. If there is no collision then the return
- value will be inf().
- */
- static float collisionTimeForMovingSphereFixedBox(
- const class Sphere& sphere,
- const Vector3& velocity,
- const class Box& box,
- Vector3& outLocation,
- Vector3& outNormal = ignore);
-
- /** Calculates time between the intersection of a moving sphere
- and a fixed sphere.
-
- If they are already interpenetrating, returns 0 and @a
- location is the closest point on the surface of the fixed sphere
- to the center of the moving sphere.
-
- @param sphere Moving sphere.
- @param velocity Sphere's velocity.
- @param fixedSphere Fixed Sphere.
- @param outLocation Location of collision -- not center position of sphere
- at the collision time. [Post Condition]
- @param outNormal Moving sphere's surface normal to collision [Post Condition]
-
- @return Time until collision. If there is no collision then the return
- value will be inf().
- */
- static float collisionTimeForMovingSphereFixedSphere(
- const Sphere& sphere,
- const Vector3& velocity,
- const Sphere& fixedSphere,
- Vector3& outLocation,
- Vector3& outNormal = ignore);
-
- /**
- Calculates time between the intersection of a moving sphere and a fixed
- capsule.
-
- @note This won't detect a collision if the sphere is already
- interpenetrating the capsule.
-
- @param sphere Moving sphere.
- @param velocity Sphere's velocity.
- @param capsule Fixed capsule.
- @param location Location of collision -- not center position of sphere
- at the collision time. [Post Condition]
- @param outNormal Capsule's surface normal to the collision [Post Condition]
-
- @return Time til collision. If there is no collision then the return
- value will be inf().
- */
- static float collisionTimeForMovingSphereFixedCapsule(
- const class Sphere& sphere,
- const Vector3& velocity,
- const class Capsule& capsule,
- Vector3& outLocation,
- Vector3& outNormal = ignore);
-
- /**
- Finds the direction of bounce that a sphere would have when it
- intersects an object with the given time of collision, the
- collision location and the collision normal.
-
- @note This function works like a pong style ball bounce.
-
- @param sphere Moving sphere.
- @param velocity Sphere's velocity.
- @param collisionTime Time of collision.
- @param collisionLocation Collision location.
- @param collisionNormal Surface collision normal.
-
- @return Direction of bounce.
- */
- static Vector3 bounceDirection(
- const class Sphere& sphere,
- const Vector3& velocity,
- const float collisionTime,
- const Vector3& collisionLocation,
- const Vector3& collisionNormal);
-
- /**
- Finds the direction of slide given a moving sphere, its velocity, the
- time of collision and the collision location. This function works as
- if the sphere intersects the surface and continues to hug it.
-
- @note The result will work well for calculating the movement of a player
- who collides with an object and continues moving along the object instead
- of just bouncing off it.
-
- @param sphere Moving sphere.
- @param velocity Sphere's velocity.
- @param collisionTime Time of collision
- @param collisionLocation Collision location.
-
- @return Direction of slide.
- */
- static Vector3 slideDirection(
- const class Sphere& sphere,
- const Vector3& velocity,
- const float collisionTime,
- const Vector3& collisionLocation);
-
- /**
- Finds the closest point on a line segment to a given point.
-
- @param v0 line vertex 1.
- @param v1 line vertex 2.
- @param point External point.
-
- @return Closests point to <code>point</code> on the line segment.
- */
- static Vector3 closestPointOnLineSegment(
- const Vector3& v0,
- const Vector3& v1,
- const Vector3& point);
-
- /**
- Finds the closest point on a line segment to a given point.
-
- @note This is an optimization to closestPointOnLineSegment. Edge length
- and direction can be used in this function if already pre-calculated. This
- prevents doing the same work twice.
-
- @param v0 line vertex 0.
- @param v1 line vertex 1.
- @param edgeDirection The direction of the segment (unit length).
- @param edgeLength The length of the segment.
- @param point External point.
-
- @return Closests point to <code>point</code> on the line segment.
- */
- static Vector3 closestPointOnLineSegment(
- const Vector3& v0,
- const Vector3& v1,
- const Vector3& edgeDirection,
- float edgeLength,
- const Vector3& point);
-
- /**
- Finds the closest point on the perimeter of the triangle to an external point;
- given a triangle defined by three points v0, v1, & v2, and the external point.
-
- @param v0 Triangle vertex 0.
- @param v1 Triangle vertex 1.
- @param v2 Triangle vertex 2.
- @param point External point.
-
- @return Closests point to <code>point</code> on the perimeter of the
- triangle.
- */
- static Vector3 closestPointOnTrianglePerimeter(
- const Vector3& v0,
- const Vector3& v1,
- const Vector3& v2,
- const Vector3& point);
-
- /**
- Finds the closest point on the perimeter of the triangle to an external point;
- given a triangle defined by the array of points v, its edge directions and
- their lengths, as well as the external point.
-
- @note This is an optimization to closestPointToTrianglePerimeter. Edge length
- and direction can be used in this function if already pre-calculated. This
- prevents doing the same work twice.
-
- @param v Triangle vertices.
- @param point External point.
- @param edgeIndex The point lies on the edge between v[edgeIndex] and v[(edgeIndex + 1) % 3]
-
- @return Closest point to <code>point</code> on the perimeter of the
- triangle.
- */
- static Vector3 closestPointOnTrianglePerimeter(
- const Vector3 v[3],
- const Vector3 edgeDirection[3],
- const float edgeLength[3],
- const Vector3& point,
- int& edgeIndex);
-
- /**
- Tests whether a point is contained within the triangle defined by
- v0, v1, and v2 and its plane's normal.
-
- @param v0 Triangle vertex 0.
- @param v1 Triangle vertex 1.
- @param v2 Triangle vertex 2.
- @param normal Normal to triangle's plane.
- @param point The point in question.
- @param primaryAxis Primary axis of triangle. This will be detected
- if not given. This parameter is provided as an optimization.
- @param b Barycentric coordinates; b[i] is the weight on v[i]
-
- @return true - if point is inside the triangle.
- @return false - otherwise
- */
- static bool isPointInsideTriangle(
- const Vector3& v0,
- const Vector3& v1,
- const Vector3& v2,
- const Vector3& normal,
- const Vector3& point,
- float b[3],
- Vector3::Axis primaryAxis = Vector3::DETECT_AXIS);
-
- inline static bool isPointInsideTriangle(
- const Vector3& v0,
- const Vector3& v1,
- const Vector3& v2,
- const Vector3& normal,
- const Vector3& point,
- Vector3::Axis primaryAxis = Vector3::DETECT_AXIS) {
-
- float b[3];
- return isPointInsideTriangle(v0, v1, v2, normal, point, b, primaryAxis);
- }
-
- /**
- Tests for the intersection of a moving sphere and a fixed box in a
- given time limit.
-
- @note Returns true if any part of the sphere is inside the box
- during the time period (inf means "ever"). Useful for
- performing bounding-box collision detection.
-
- @param sphere Moving sphere.
- @param velocity Velocity of moving sphere.
- @param box Fixed box.
- @param timeLimit Time limit for intersection test.
-
- @return true - if the two objects will touch.
- @return false - if there is no intersection.
- */
- static bool movingSpherePassesThroughFixedBox(
- const Sphere& sphere,
- const Vector3& velocity,
- const Box& box,
- double timeLimit = inf());
-
- /**
- Tests for the intersection of a moving sphere and a fixed sphere in a
- given time limit.
-
- @note This function will not detect an intersection between a moving object
- that is already interpenetrating the fixed object.
-
- @param sphere Moving sphere.
- @param velocity Velocity of moving sphere.
- @param fixedSphere Fixed sphere.
- @param timeLimit Time limit for intersection test.
-
- @return true - if the two spheres will touch.
- @return false - if there is no intersection.
- */
- static bool movingSpherePassesThroughFixedSphere(
- const Sphere& sphere,
- const Vector3& velocity,
- const Sphere& fixedSphere,
- double timeLimit = inf());
-
- /**
- Tests for the intersection of two fixed spheres.
-
- @param sphere1 Fixed sphere 1.
- @param sphere2 Fixed sphere 2.
-
- @return true - if the two spheres touch.
- @return false - if there is no intersection.
- */
- static bool fixedSolidSphereIntersectsFixedSolidSphere(
- const Sphere& sphere1,
- const Sphere& sphere2);
-
- /**
- Tests for the intersection of a fixed sphere and a fixed box.
-
- @param sphere Fixed sphere.
- @param box Fixed box.
-
- @return true - if the two objects touch.
- @return false - if there is no intersection.
- */
- static bool fixedSolidSphereIntersectsFixedSolidBox(
- const Sphere& sphere,
- const Box& box);
-
- static bool fixedSolidSphereIntersectsFixedTriangle(
- const Sphere& sphere,
- const Triangle& triangle);
-
- static bool fixedSolidBoxIntersectsFixedTriangle(
- const AABox& box,
- const Triangle& triangle);
-
- /**
- Tests whether a point is inside a rectangle defined by the vertexes
- v0, v1, v2, & v3, and the rectangle's plane normal.
-
- @param v0 Rectangle vertex 1.
- @param v1 Rectangle vertex 2.
- @param v2 Rectangle vertex 3.
- @param v3 Rectangle vertex 4.
- @param normal Normal to rectangle's plane.
- @param point The point in question.
-
- @return true - if point is inside the rectangle.
- @return false - otherwise
- */
- static bool isPointInsideRectangle(
- const Vector3& v0,
- const Vector3& v1,
- const Vector3& v2,
- const Vector3& v3,
- const Vector3& normal,
- const Vector3& point);
-
- /**
- Finds the closest point on the perimeter of the rectangle to an
- external point; given a rectangle defined by four points v0, v1,
- v2, & v3, and the external point.
-
- @param v0 Rectangle vertex 1.
- @param v1 Rectangle vertex 2.
- @param v2 Rectangle vertex 3.
- @param v3 Rectangle vertex 4.
- @param point External point.
-
- @return Closests point to <code>point</code> on the perimeter of the
- rectangle.
- */
- static Vector3 closestPointToRectanglePerimeter(
- const Vector3& v0,
- const Vector3& v1,
- const Vector3& v2,
- const Vector3& v3,
- const Vector3& point);
-
- /**
- Finds the closest point in the rectangle to an external point; Given
- a rectangle defined by four points v0, v1, v2, & v3, and the external
- point.
-
- @param v0 Rectangle vertex 1.
- @param v1 Rectangle vertex 2.
- @param v2 Rectangle vertex 3
- @param v3 Rectangle vertex 4.
- @param point External point.
-
- @return Closet point in the rectangle to the external point.
- */
- static Vector3 closestPointToRectangle(
- const Vector3& v0,
- const Vector3& v1,
- const Vector3& v2,
- const Vector3& v3,
- const Vector3& point);
-};
-
-} // namespace
-
-#endif // G3D_COLLISIONDETECTION_H
diff --git a/externals/g3dlite/G3D/Color1.h b/externals/g3dlite/G3D/Color1.h
deleted file mode 100644
index 0f68c84b363..00000000000
--- a/externals/g3dlite/G3D/Color1.h
+++ /dev/null
@@ -1,144 +0,0 @@
-/**
- @file Color1.h
-
- Monochrome Color class
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @created 2007-01-31
- @edited 2009-03-20
-
- Copyright 2000-2009, Morgan McGuire.
- All rights reserved.
- */
-
-#ifndef G3D_COLOR1_H
-#define G3D_COLOR1_H
-
-#include "G3D/platform.h"
-#include "G3D/g3dmath.h"
-#include "G3D/HashTrait.h"
-#include <string>
-
-namespace G3D {
-
-/**
- Monochrome color. This is just a float, but it has nice semantics
- because a scaling by 255 automatically occurs when switching between
- fixed point (Color1uint8) and floating point (Color1) formats.
- */
-class Color1 {
-private:
- // Hidden operators
- bool operator<(const Color1&) const;
- bool operator>(const Color1&) const;
- bool operator<=(const Color1&) const;
- bool operator>=(const Color1&) const;
-
-public:
- float value;
-
- /**
- Initializes to 0
- */
- inline Color1() : value(0) {}
-
- Color1(class BinaryInput& bi);
-
- inline explicit Color1(float v) : value(v) {
- }
-
- inline bool isZero() const {
- return value == 0.0f;
- }
-
- inline bool isOne() const {
- return value == 1.0f;
- }
-
- static const Color1& one();
-
- static const Color1& zero();
-
- /** Returns the value three times */
- class Color3 rgb() const;
-
- Color1 (const class Color1uint8& other);
-
- void serialize(class BinaryOutput& bo) const;
- void deserialize(class BinaryInput& bi);
-
- Color1 operator+ (const Color1& other) const {
- return Color1(value + other.value);
- }
-
- Color1 operator+ (const float other) const {
- return Color1(value + other);
- }
-
- Color1& operator+= (const Color1 other) {
- value += other.value;
- return *this;
- }
-
- Color1& operator-= (const Color1 other) {
- value -= other.value;
- return *this;
- }
-
- Color1 operator- (const Color1& other) const {
- return Color1(value - other.value);
- }
-
- Color1 operator- (const float other) const {
- return Color1(value - other);
- }
-
- Color1 operator- () const {
- return Color1(-value);
- }
-
- Color1 operator* (const Color1& other) const {
- return Color1(value * other.value);
- }
-
- Color1 operator* (const float other) const {
- return Color1(value * other);
- }
-
- Color1 operator/ (const Color1& other) const {
- return Color1(value / other.value);
- }
-
- Color1 operator/ (const float other) const {
- return Color1(value / other);
- }
-
- inline Color1 max(const Color1& other) const {
- return Color1(G3D::max(value, other.value));
- }
-
- inline Color1 min(const Color1& other) const {
- return Color1(G3D::min(value, other.value));
- }
-
- inline Color1 lerp(const Color1& other, float a) const {
- return Color1(value + (other.value - value) * a);
-
- }
-
- inline size_t hashCode() const {
- return (size_t)(value * 0xFFFFFF);
- }
-};
-
-}
-
-template <>
-struct HashTrait<G3D::Color1> {
- static size_t hashCode(const G3D::Color1& key) {
- return key.hashCode();
- }
-};
-
-
-#endif
diff --git a/externals/g3dlite/G3D/Color1uint8.h b/externals/g3dlite/G3D/Color1uint8.h
deleted file mode 100644
index 092099d0d17..00000000000
--- a/externals/g3dlite/G3D/Color1uint8.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/**
- @file Color1uint8.h
-
- @maintainer Morgan McGuire, graphics3d.com
-
- @created 2007-01-30
- @edited 2007-01-30
-
- Copyright 2000-2007, Morgan McGuire.
- All rights reserved.
- */
-
-#ifndef G3D_COLOR1UINT8_H
-#define G3D_COLOR1UINT8_H
-
-#include "G3D/platform.h"
-#include "G3D/g3dmath.h"
-
-namespace G3D {
-
-/**
- Represents a Color1 as a packed integer. Convenient
- for creating unsigned int vertex arrays.
-
- <B>WARNING</B>: Integer color formats are different than
- integer vertex formats. The color channels are automatically
- scaled by 255 (because OpenGL automatically scales integer
- colors back by this factor). So Color3(1,1,1) == Color3uint8(255,255,255)
- but Vector3(1,1,1) == Vector3int16(1,1,1).
-
- <B>Note</B>:
- Conversion of a float32 to uint8 is accomplished by min(iFloor(f * 256)) and
- back to float32 by u / 255.0f. This gives equal size intervals.
-Consider a number line from 0 to 1 and a corresponding one from 0 to 255. If we use iRound(x * 255), then the mapping for three critical intervals are:
-
-<pre>
-let s = 0.5/255
- float int size
-[0, s) -> 0 s
-[s, s * 3) -> 1 2*s
-(1 - s, 1] -> 255 s
-</pre>
-
-If we use max(floor(x * 256), 255), then we get:
-
-<pre>
-let s = 1/256
- float int size
-[0, s) -> 0 s
-[s, 2 * s) -> 1 s
-(1 - s, 1] -> 255 s
-</PRE>
-and the intervals are all the same size, thus giving equal precision to all values.
- */
-G3D_BEGIN_PACKED_CLASS(1)
-class Color1uint8 {
-private:
- // Hidden operators
- bool operator<(const Color1uint8&) const;
- bool operator>(const Color1uint8&) const;
- bool operator<=(const Color1uint8&) const;
- bool operator>=(const Color1uint8&) const;
-
-public:
-
- uint8 value;
-
- Color1uint8() : value(0) {}
-
- explicit Color1uint8(const uint8 _v) : value(_v) {}
-
- Color1uint8(const class Color1& c);
-
- Color1uint8(class BinaryInput& bi);
-
- void serialize(class BinaryOutput& bo) const;
-
- void deserialize(class BinaryInput& bi);
-
- inline bool operator==(const Color1uint8& other) const {
- return value == other.value;
- }
-
- inline bool operator!=(const Color1uint8& other) const {
- return value != other.value;
- }
-
-}
-G3D_END_PACKED_CLASS(1)
-}
-#endif
diff --git a/externals/g3dlite/G3D/Color3.h b/externals/g3dlite/G3D/Color3.h
deleted file mode 100644
index bffe434fc27..00000000000
--- a/externals/g3dlite/G3D/Color3.h
+++ /dev/null
@@ -1,432 +0,0 @@
-/**
- @file Color3.h
-
- Color class
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @cite Portions based on Dave Eberly's Magic Software Library
- at <A HREF="http://www.magic-software.com">http://www.magic-software.com</A>
-
- @created 2001-06-02
- @edited 2009-04-28
-
- Copyright 2000-2009, Morgan McGuire.
- All rights reserved.
- */
-
-#ifndef G3D_Color3_h
-#define G3D_Color3_h
-
-#include "G3D/platform.h"
-#include "G3D/g3dmath.h"
-#include "G3D/HashTrait.h"
-#include "G3D/Color1.h"
-#include <string>
-
-namespace G3D {
-class Any;
-
-/**
- Do not subclass-- this implementation makes assumptions about the
- memory layout.
- */
-class Color3 {
-private:
- // Hidden operators
- bool operator<(const Color3&) const;
- bool operator>(const Color3&) const;
- bool operator<=(const Color3&) const;
- bool operator>=(const Color3&) const;
-
-public:
- /**
- Does not initialize fields.
- */
- Color3();
-
- /** \param any Must be in one of the following forms:
- - Color3(#, #, #)
- - Color3::fromARGB(#)
- - Color3{r = #, g = #, b = #)
- - Color3::one()
- - Color3::zero()
- */
- Color3(const Any& any);
-
- /** Converts the Color3 to an Any. */
- operator Any() const;
-
- explicit Color3(class BinaryInput& bi);
-
- Color3(float r, float g, float b);
- Color3(float v) : r(v), g(v), b(v) {}
-
- explicit Color3(const class Vector3& v);
-
- explicit Color3(const float value[3]);
-
- /** Returns this color */
- const Color3& rgb() const {
- return *this;
- }
-
- /**
- Initialize from another color.
- */
- Color3 (const Color3& other);
-
- Color3 (const class Color3uint8& other);
-
- inline bool isZero() const {
- return (r == 0.0f) && (g == 0.0f) && (b == 0.0f);
- }
-
- inline bool isOne() const {
- return (r == 1.0f) && (g == 1.0f) && (b == 1.0f);
- }
-
- bool isFinite() const;
-
- /**
- Initialize from an HTML-style color (e.g. 0xFF0000 == RED)
- */
- static Color3 fromARGB(uint32);
-
- /** Returns one of the color wheel colors (e.g. RED, GREEN, CYAN).
- Does not include white, black, or gray. */
- static const Color3& wheelRandom();
-
- /** Generate colors according to the ANSI color set, mod 16.
- \sa pastelMap */
- static Color3 ansiMap(uint32 i);
-
- /**
- Generate colors using a hash such that adjacent values
- are unlikely to have similar colors.
-
- Useful for rendering with
- stable but arbitrary colors, e.g., when debugging a mesh
- algorithm.
-
- \sa ansiMap
- */
- static Color3 pastelMap(uint32 i);
-
- /**
- * Channel value.
- */
- float r, g, b;
-
- void serialize(class BinaryOutput& bo) const;
- void deserialize(class BinaryInput& bi);
-
- // access vector V as V[0] = V.r, V[1] = V.g, V[2] = V.b
- //
- // WARNING. These member functions rely on
- // (1) Color3 not having virtual functions
- // (2) the data packed in a 3*sizeof(float) memory block
- const float& operator[] (int i) const;
- float& operator[] (int i);
-
- // assignment and comparison
- Color3& operator= (const Color3& rkVector);
- bool operator== (const Color3& rkVector) const;
- bool operator!= (const Color3& rkVector) const;
- size_t hashCode() const;
-
- // arithmetic operations
- Color3 operator+ (const Color3& rkVector) const;
- Color3 operator- (const Color3& rkVector) const;
- inline Color3 operator* (float s) const {
- return Color3(r * s, g * s, b * s);
- }
- Color3 operator* (const Color3& rkVector) const;
- inline Color3 operator/ (float fScalar) const {
- return (*this) * (1.0f / fScalar);
- }
- Color3 operator- () const;
-
- // arithmetic updates
- Color3& operator+= (const Color3& rkVector);
- Color3& operator-= (const Color3& rkVector);
- Color3& operator*= (const Color3& rkVector);
- Color3& operator*= (float fScalar);
- Color3& operator/= (float fScalar);
-
- bool fuzzyEq(const Color3& other) const;
- bool fuzzyNe(const Color3& other) const;
-
- // vector operations
- float length () const;
- Color3 direction() const;
- float squaredLength () const;
- float dot (const Color3& rkVector) const;
- float unitize (float fTolerance = 1e-06);
- Color3 cross (const Color3& rkVector) const;
- Color3 unitCross (const Color3& rkVector) const;
-
- inline Color3 pow(const Color3& other) const {
- return Color3(::pow(r, other.r), ::pow(g, other.g), ::pow(b, other.b));
- }
-
- inline Color3 pow(float other) const {
- return Color3(::pow(r, other), ::pow(g, other), ::pow(b, other));
- }
-
- inline Color3 max(const Color3& other) const {
- return Color3(G3D::max(r, other.r), G3D::max(g, other.g), G3D::max(b, other.b));
- }
-
- inline Color3 min(const Color3& other) const {
- return Color3(G3D::min(r, other.r), G3D::min(g, other.g), G3D::min(b, other.b));
- }
-
- /** Smallest element */
- inline float min() const {
- return G3D::min(G3D::min(r, g), b);
- }
-
- /** Largest element */
- inline float max() const {
- return G3D::max(G3D::max(r, g), b);
- }
-
- inline Color3 lerp(const Color3& other, float a) const {
- return (*this) + (other - *this) * a;
-
- }
-
- inline float sum() const {
- return r + g + b;
- }
-
- inline float average() const {
- return sum() / 3.0f;
- }
-
-
- /**
- * Converts from HSV to RGB , note: toHSV(fromHSV(_hsv)) may not be _hsv, if it is at a grey point or black point.
- * The components of _hsv should lie in the unit interval.
- * @cite Alvy Ray Smith SIGGRAPH 1978 "Color Gamut Transform Pairs"
- **/
- static Color3 fromHSV(const Vector3& _hsv);
- static Vector3 toHSV(const Color3& _rgb);
-
- /** Duplicates the matlab jet colormap maps [0,1] --> (r,g,b) where blue is close to 0 and red is close to 1. */
- static Color3 jetColorMap(const float& val);
-
- /** Returns colors with maximum saturation and value @param hue [0, 1]*/
- static Color3 rainbowColorMap(float hue);
-
- std::string toString() const;
-
- /** Random unit vector */
- static Color3 random();
-
- // Special values.
- // Intentionally not inlined: see Matrix3::identity() for details.
- static const Color3& red();
- static const Color3& green();
- static const Color3& blue();
- static const Color3& purple();
- static const Color3& cyan();
- static const Color3& yellow();
- static const Color3& brown();
- static const Color3& orange();
- static const Color3& black();
- static const Color3& gray();
- static const Color3& white();
-
- static const Color3& zero();
- static const Color3& one();
-
- inline Color3 bgr() const {
- return Color3(b, g, r);
- }
-};
-
-inline G3D::Color3 operator* (float s, const G3D::Color3& c) {
- return c * s;
-}
-
-inline G3D::Color3 operator* (G3D::Color1& s, const G3D::Color3& c) {
- return c * s.value;
-}
-
-inline G3D::Color3 operator* (const G3D::Color3& c, G3D::Color1& s) {
- return c * s.value;
-}
-
-
-//----------------------------------------------------------------------------
-inline Color3::Color3 () {
-}
-
-//----------------------------------------------------------------------------
-
-inline Color3::Color3(float fX, float fY, float fZ) {
- r = fX;
- g = fY;
- b = fZ;
-}
-
-//----------------------------------------------------------------------------
-inline Color3::Color3(const float afCoordinate[3]) {
- r = afCoordinate[0];
- g = afCoordinate[1];
- b = afCoordinate[2];
-}
-
-//----------------------------------------------------------------------------
-inline Color3::Color3 (const Color3& rkVector) {
- r = rkVector.r;
- g = rkVector.g;
- b = rkVector.b;
-}
-
-//----------------------------------------------------------------------------
-inline float& Color3::operator[] (int i) {
- return ((float*)this)[i];
-}
-
-//----------------------------------------------------------------------------
-
-inline const float& Color3::operator[] (int i) const {
- return ((float*)this)[i];
-}
-
-//----------------------------------------------------------------------------
-
-inline bool Color3::fuzzyEq(const Color3& other) const {
- return G3D::fuzzyEq((*this - other).squaredLength(), 0);
-}
-
-//----------------------------------------------------------------------------
-
-inline bool Color3::fuzzyNe(const Color3& other) const {
- return G3D::fuzzyNe((*this - other).squaredLength(), 0);
-}
-
-
-//----------------------------------------------------------------------------
-inline Color3& Color3::operator= (const Color3& rkVector) {
- r = rkVector.r;
- g = rkVector.g;
- b = rkVector.b;
- return *this;
-}
-
-//----------------------------------------------------------------------------
-inline bool Color3::operator== (const Color3& rkVector) const {
- return ( r == rkVector.r && g == rkVector.g && b == rkVector.b );
-}
-
-//----------------------------------------------------------------------------
-inline bool Color3::operator!= (const Color3& rkVector) const {
- return ( r != rkVector.r || g != rkVector.g || b != rkVector.b );
-}
-
-//----------------------------------------------------------------------------
-inline Color3 Color3::operator+ (const Color3& rkVector) const {
- return Color3(r + rkVector.r, g + rkVector.g, b + rkVector.b);
-}
-
-//----------------------------------------------------------------------------
-inline Color3 Color3::operator- (const Color3& rkVector) const {
- return Color3(r -rkVector.r, g - rkVector.g, b - rkVector.b);
-}
-
-//----------------------------------------------------------------------------
-inline Color3 Color3::operator* (const Color3& rkVector) const {
- return Color3(r * rkVector.r, g * rkVector.g, b * rkVector.b);
-}
-
-//----------------------------------------------------------------------------
-inline Color3 Color3::operator- () const {
- return Color3( -r, -g, -b);
-}
-
-//----------------------------------------------------------------------------
-inline Color3& Color3::operator+= (const Color3& rkVector) {
- r += rkVector.r;
- g += rkVector.g;
- b += rkVector.b;
- return *this;
-}
-
-//----------------------------------------------------------------------------
-inline Color3& Color3::operator-= (const Color3& rkVector) {
- r -= rkVector.r;
- g -= rkVector.g;
- b -= rkVector.b;
- return *this;
-}
-
-//----------------------------------------------------------------------------
-inline Color3& Color3::operator*= (float fScalar) {
- r *= fScalar;
- g *= fScalar;
- b *= fScalar;
- return *this;
-}
-
-//----------------------------------------------------------------------------
-inline Color3& Color3::operator*= (const Color3& rkVector) {
- r *= rkVector.r;
- g *= rkVector.g;
- b *= rkVector.b;
- return *this;
-}
-//----------------------------------------------------------------------------
-inline float Color3::squaredLength () const {
- return r*r + g*g + b*b;
-}
-
-//----------------------------------------------------------------------------
-inline float Color3::length () const {
- return sqrtf(r*r + g*g + b*b);
-}
-
-//----------------------------------------------------------------------------
-inline Color3 Color3::direction () const {
- float lenSquared = r * r + g * g + b * b;
-
- if (lenSquared != 1.0f) {
- return *this / sqrtf(lenSquared);
- } else {
- return *this;
- }
-}
-
-//----------------------------------------------------------------------------
-inline float Color3::dot (const Color3& rkVector) const {
- return r*rkVector.r + g*rkVector.g + b*rkVector.b;
-}
-
-//----------------------------------------------------------------------------
-inline Color3 Color3::cross (const Color3& rkVector) const {
- return Color3(g*rkVector.b - b*rkVector.g, b*rkVector.r - r*rkVector.b,
- r*rkVector.g - g*rkVector.r);
-}
-
-//----------------------------------------------------------------------------
-inline Color3 Color3::unitCross (const Color3& rkVector) const {
- Color3 kCross(g*rkVector.b - b*rkVector.g, b*rkVector.r - r*rkVector.b,
- r*rkVector.g - g*rkVector.r);
- kCross.unitize();
- return kCross;
-}
-
-
-} // namespace
-
-
-template <> struct HashTrait<G3D::Color3> {
- static size_t hashCode(const G3D::Color3& key) {
- return key.hashCode();
- }
-};
-
-
-#endif
diff --git a/externals/g3dlite/G3D/Color3uint8.h b/externals/g3dlite/G3D/Color3uint8.h
deleted file mode 100644
index bd4b00d7fd6..00000000000
--- a/externals/g3dlite/G3D/Color3uint8.h
+++ /dev/null
@@ -1,110 +0,0 @@
-/**
- @file Color3uint8.h
-
- @maintainer Morgan McGuire, graphics3d.com
-
- @created 2003-04-07
- @edited 2006-06-24
-
- Copyright 2000-2006, Morgan McGuire.
- All rights reserved.
- */
-
-#ifndef G3D_COLOR3UINT8_H
-#define G3D_COLOR3UINT8_H
-
-#include "G3D/platform.h"
-#include "G3D/g3dmath.h"
-
-namespace G3D {
-
-/**
- Represents a Color3 as a packed integer. Convenient
- for creating unsigned int vertex arrays. Used by
- G3D::GImage as the underlying format.
-
- <B>WARNING</B>: Integer color formats are different than
- integer vertex formats. The color channels are automatically
- scaled by 255 (because OpenGL automatically scales integer
- colors back by this factor). So Color3(1,1,1) == Color3uint8(255,255,255)
- but Vector3(1,1,1) == Vector3int16(1,1,1).
- */
-
-G3D_BEGIN_PACKED_CLASS(1)
-
-class Color3uint8 {
-private:
- // Hidden operators
- bool operator<(const Color3uint8&) const;
- bool operator>(const Color3uint8&) const;
- bool operator<=(const Color3uint8&) const;
- bool operator>=(const Color3uint8&) const;
-
-public:
- uint8 r;
- uint8 g;
- uint8 b;
-
- Color3uint8() : r(0), g(0), b(0) {}
-
- Color3uint8(const uint8 _r, const uint8 _g, const uint8 _b) : r(_r), g(_g), b(_b) {}
-
- Color3uint8(const class Color3& c);
-
- Color3uint8(class BinaryInput& bi);
-
- inline static Color3uint8 fromARGB(uint32 i) {
- Color3uint8 c;
- c.r = (i >> 16) & 0xFF;
- c.g = (i >> 8) & 0xFF;
- c.b = i & 0xFF;
- return c;
- }
-
- inline Color3uint8 bgr() const {
- return Color3uint8(b, g, r);
- }
-
- /**
- Returns the color packed into a uint32
- (the upper byte is 0xFF)
- */
- inline uint32 asUInt32() const {
- return (0xFF << 24) + ((uint32)r << 16) + ((uint32)g << 8) + b;
- }
-
- void serialize(class BinaryOutput& bo) const;
-
- void deserialize(class BinaryInput& bi);
-
- // access vector V as V[0] = V.r, V[1] = V.g, V[2] = V.b
- //
- // WARNING. These member functions rely on
- // (1) Color3 not having virtual functions
- // (2) the data packed in a 3*sizeof(uint8) memory block
- uint8& operator[] (int i) const {
- debugAssert((unsigned int)i < 3);
- return ((uint8*)this)[i];
- }
-
- operator uint8* () {
- return (G3D::uint8*)this;
- }
-
- operator const uint8* () const {
- return (uint8*)this;
- }
-
- bool operator==(const Color3uint8& other) const {
- return (other.r == r) && (other.g == g) && (other.b == b);
- }
-
- bool operator!=(const Color3uint8& other) const {
- return (other.r != r) && (other.g != g) && (other.b != b);
- }
-}
-G3D_END_PACKED_CLASS(1)
-
-} // namespace G3D
-
-#endif
diff --git a/externals/g3dlite/G3D/Color4.h b/externals/g3dlite/G3D/Color4.h
deleted file mode 100644
index d8858abbce2..00000000000
--- a/externals/g3dlite/G3D/Color4.h
+++ /dev/null
@@ -1,338 +0,0 @@
-/**
- @file Color4.h
-
- Color class
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @cite Portions based on Dave Eberly's Magic Software Library
- at <A HREF="http://www.magic-software.com">http://www.magic-software.com</A>
-
- @created 2002-06-25
- @edited 2009-11-15
-
- Copyright 2000-2009, Morgan McGuire.
- All rights reserved.
- */
-
-#ifndef G3D_Color4_h
-#define G3D_Color4_h
-
-#include "G3D/platform.h"
-#include "G3D/g3dmath.h"
-#include "G3D/Color3.h"
-#include <string>
-
-namespace G3D {
-
-class Any;
-
-/**
- Do not subclass-- this implementation makes assumptions about the
- memory layout.
- */
-class Color4 {
-private:
- // Hidden operators
- bool operator<(const Color4&) const;
- bool operator>(const Color4&) const;
- bool operator<=(const Color4&) const;
- bool operator>=(const Color4&) const;
-
-public:
-
- /** \param any Must be in one of the following forms:
- - Color4(#, #, #, #)
- - Color4::fromARGB(#)
- - Color4{r = #, g = #, b = #, a = #)
- */
- Color4(const Any& any);
-
- /** Converts the Color4 to an Any. */
- operator Any() const;
-
- /**
- * Does not initialize fields.
- */
- Color4 ();
-
- Color4(const Color3& c3, float a = 1.0);
-
- Color4(const class Color4uint8& c);
-
- Color4(class BinaryInput& bi);
-
- Color4(const class Vector4& v);
-
- Color4(float r, float g, float b, float a = 1.0);
-
- static const Color4& one();
-
- Color4(float value[4]);
-
- /**
- * Initialize from another color.
- */
- Color4(const Color4& other);
-
-
- inline bool isZero() const {
- return (r == 0.0f) && (g == 0.0f) && (b == 0.0f) && (a == 0.0f);
- }
-
- inline bool isOne() const {
- return (r == 1.0f) && (g == 1.0f) && (b == 1.0f) && (a == 1.0f);
- }
-
- void serialize(class BinaryOutput& bo) const;
- void deserialize(class BinaryInput& bi);
-
- /**
- Initialize from an HTML-style color (e.g. 0xFFFF0000 == RED)
- */
- static Color4 fromARGB(uint32);
-
- /**
- * Channel values.
- */
- float r, g, b, a;
-
- inline Color3 rgb() const {
- return Color3(r, g, b);
- }
-
- // access vector V as V[0] = V.r, V[1] = V.g, V[2] = V.b, v[3] = V.a
- //
- // WARNING. These member functions rely on
- // (1) Color4 not having virtual functions
- // (2) the data packed in a 3*sizeof(float) memory block
- float& operator[] (int i) const;
-
- // assignment and comparison
- Color4& operator= (const Color4& rkVector);
- bool operator== (const Color4& rkVector) const;
- bool operator!= (const Color4& rkVector) const;
- size_t hashCode() const;
-
- // arithmetic operations
- Color4 operator+ (const Color4& rkVector) const;
- Color4 operator- (const Color4& rkVector) const;
- Color4 operator* (float fScalar) const;
- inline Color4 operator* (const Color4& k) const {
- return Color4(r*k.r, g*k.g, b*k.b, a * k.a);
- }
- Color4 operator/ (float fScalar) const;
- Color4 operator- () const;
- friend Color4 operator* (double fScalar, const Color4& rkVector);
-
- // arithmetic updates
- Color4& operator+= (const Color4& rkVector);
- Color4& operator-= (const Color4& rkVector);
- Color4& operator*= (float fScalar);
- Color4& operator/= (float fScalar);
-
- bool fuzzyEq(const Color4& other) const;
- bool fuzzyNe(const Color4& other) const;
-
- std::string toString() const;
-
- inline Color4 max(const Color4& other) const {
- return Color4(G3D::max(r, other.r), G3D::max(g, other.g), G3D::max(b, other.b), G3D::max(a, other.a));
- }
-
- inline Color4 min(const Color4& other) const {
- return Color4(G3D::min(r, other.r), G3D::min(g, other.g), G3D::min(b, other.b), G3D::min(a, other.a));
- }
-
- /** r + g + b + a */
- inline float sum() const {
- return r + g + b + a;
- }
-
- inline Color4 lerp(const Color4& other, float a) const {
- return (*this) + (other - *this) * a;
-
- }
-
- // Special values.
- // Intentionally not inlined: see Matrix3::identity() for details.
- static const Color4& zero();
- static const Color4& clear();
-
- static const Color4& inf();
- static const Color4& nan();
-
- inline bool isFinite() const {
- return G3D::isFinite(r) && G3D::isFinite(g) && G3D::isFinite(b) && G3D::isFinite(a);
- }
-
- inline Color3 bgr() const {
- return Color3(b, g, r);
- }
-};
-
-/**
- Extends the c3 with alpha = 1.0
- */
-Color4 operator*(const Color3& c3, const Color4& c4);
-
-
-inline Color4 operator*(const Color3& c3, const Color4& c4) {
- return Color4(c3.r * c4.r, c3.g * c4.g, c3.b * c4.b, c4.a);
-}
-
-//----------------------------------------------------------------------------
-
-inline Color4::Color4 () {
- // For efficiency in construction of large arrays of vectors, the
- // default constructor does not initialize the vector.
-}
-
-//----------------------------------------------------------------------------
-
-inline Color4::Color4(const Color3& c3, float a) {
- r = c3.r;
- g = c3.g;
- b = c3.b;
- this->a = a;
-}
-
-//----------------------------------------------------------------------------
-
-inline Color4::Color4(
- float r,
- float g,
- float b,
- float a) :
- r(r), g(g), b(b), a(a) {
-}
-
-//----------------------------------------------------------------------------
-inline Color4::Color4 (float afCoordinate[4]) {
- r = afCoordinate[0];
- g = afCoordinate[1];
- b = afCoordinate[2];
- a = afCoordinate[3];
-}
-
-//----------------------------------------------------------------------------
-
-inline Color4::Color4(
- const Color4& other) {
-
- r = other.r;
- g = other.g;
- b = other.b;
- a = other.a;
-}
-
-//----------------------------------------------------------------------------
-
-inline float& Color4::operator[] (int i) const {
- return ((float*)this)[i];
-}
-
-//----------------------------------------------------------------------------
-
-inline bool Color4::fuzzyEq(const Color4& other) const {
- Color4 dif = (*this - other);
- return G3D::fuzzyEq(dif.r * dif.r + dif.g * dif.g + dif.b * dif.b + dif.a * dif.a, 0);
-}
-
-//----------------------------------------------------------------------------
-
-inline bool Color4::fuzzyNe(const Color4& other) const {
- Color4 dif = (*this - other);
- return G3D::fuzzyNe(dif.r * dif.r + dif.g * dif.g + dif.b * dif.b + dif.a * dif.a, 0);
-}
-
-
-//----------------------------------------------------------------------------
-inline Color4& Color4::operator= (const Color4& other) {
- r = other.r;
- g = other.g;
- b = other.b;
- a = other.a;
- return *this;
-}
-
-//----------------------------------------------------------------------------
-
-inline bool Color4::operator== (const Color4& other) const {
- return ( r == other.r && g == other.g && b == other.b && a == other.a);
-}
-
-//----------------------------------------------------------------------------
-
-inline bool Color4::operator!= (const Color4& other) const {
- return ( r != other.r || g != other.g || b != other.b || a != other.a);
-}
-
-//----------------------------------------------------------------------------
-inline Color4 Color4::operator+ (const Color4& other) const {
- return Color4(r + other.r, g + other.g, b + other.b, a + other.a);
-}
-
-//----------------------------------------------------------------------------
-inline Color4 Color4::operator- (const Color4& other) const {
- return Color4(r - other.r, g - other.g, b - other.b, a - other.a);
-}
-
-//----------------------------------------------------------------------------
-
-inline Color4 Color4::operator* (float fScalar) const {
- return Color4(fScalar * r, fScalar * g, fScalar * b, fScalar * a);
-}
-
-//----------------------------------------------------------------------------
-
-inline Color4 Color4::operator- () const {
- return Color4(-r, -g, -b, -a);
-}
-
-//----------------------------------------------------------------------------
-
-inline Color4 operator* (float fScalar, const Color4& other) {
- return Color4(fScalar * other.r, fScalar * other.g,
- fScalar * other.b, fScalar * other.a);
-}
-
-//----------------------------------------------------------------------------
-
-inline Color4& Color4::operator+= (const Color4& other) {
- r += other.r;
- g += other.g;
- b += other.b;
- a += other.a;
- return *this;
-}
-
-//----------------------------------------------------------------------------
-
-inline Color4& Color4::operator-= (const Color4& other) {
- r -= other.r;
- g -= other.g;
- b -= other.b;
- a -= other.a;
- return *this;
-}
-
-//----------------------------------------------------------------------------
-
-inline Color4& Color4::operator*= (float fScalar) {
- r *= fScalar;
- g *= fScalar;
- b *= fScalar;
- a *= fScalar;
- return *this;
-}
-
-} // namespace
-
-template <>
-struct HashTrait<G3D::Color4> {
- static size_t hashCode(const G3D::Color4& key) {
- return key.hashCode();
- }
-};
-
-#endif
diff --git a/externals/g3dlite/G3D/Color4uint8.h b/externals/g3dlite/G3D/Color4uint8.h
deleted file mode 100644
index ab8c0729276..00000000000
--- a/externals/g3dlite/G3D/Color4uint8.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/**
- @file Color4uint8.h
-
- @maintainer Morgan McGuire, graphics3d.com
-
- @created 2003-04-07
- @edited 2006-03-24
-
- Copyright 2000-2006, Morgan McGuire.
- All rights reserved.
- */
-
-#ifndef COLOR4UINT8_H
-#define COLOR4UINT8_H
-
-#include "G3D/g3dmath.h"
-#include "G3D/platform.h"
-#include "G3D/Color3uint8.h"
-
-namespace G3D {
-
-/**
- Represents a Color4 as a packed integer. Convenient
- for creating unsigned int vertex arrays. Used by
- G3D::GImage as the underlying format.
-
- <B>WARNING</B>: Integer color formats are different than
- integer vertex formats. The color channels are automatically
- scaled by 255 (because OpenGL automatically scales integer
- colors back by this factor). So Color4(1,1,1) == Color4uint8(255,255,255)
- but Vector3(1,1,1) == Vector3int16(1,1,1).
-
- */
-G3D_BEGIN_PACKED_CLASS(1)
-class Color4uint8 {
-private:
- // Hidden operators
- bool operator<(const Color4uint8&) const;
- bool operator>(const Color4uint8&) const;
- bool operator<=(const Color4uint8&) const;
- bool operator>=(const Color4uint8&) const;
-
-public:
- uint8 r;
- uint8 g;
- uint8 b;
- uint8 a;
-
- Color4uint8() : r(0), g(0), b(0), a(0) {}
-
- Color4uint8(const class Color4& c);
-
- Color4uint8(const uint8 _r, const uint8 _g, const uint8 _b, const uint8 _a) : r(_r), g(_g), b(_b), a(_a) {}
-
- Color4uint8(const Color3uint8& c, const uint8 _a) : r(c.r), g(c.g), b(c.b), a(_a) {}
-
- Color4uint8(class BinaryInput& bi);
-
- inline static Color4uint8 fromARGB(uint32 i) {
- Color4uint8 c;
- c.a = (i >> 24) & 0xFF;
- c.r = (i >> 16) & 0xFF;
- c.g = (i >> 8) & 0xFF;
- c.b = i & 0xFF;
- return c;
- }
-
- inline uint32 asUInt32() const {
- return ((uint32)a << 24) + ((uint32)r << 16) + ((uint32)g << 8) + b;
- }
-
- // access vector V as V[0] = V.r, V[1] = V.g, V[2] = V.b
- //
- // WARNING. These member functions rely on
- // (1) Color4uint8 not having virtual functions
- // (2) the data packed in a 3*sizeof(uint8) memory block
- uint8& operator[] (int i) const {
- return ((uint8*)this)[i];
- }
-
- operator uint8* () {
- return (uint8*)this;
- }
-
- operator const uint8* () const {
- return (uint8*)this;
- }
-
-
- inline Color3uint8 bgr() const {
- return Color3uint8(b, g, r);
- }
-
- void serialize(class BinaryOutput& bo) const;
-
- void deserialize(class BinaryInput& bi);
-
- inline Color3uint8 rgb() const {
- return Color3uint8(r, g, b);
- }
-
- bool operator==(const Color4uint8& other) const {
- return *reinterpret_cast<const uint32*>(this) == *reinterpret_cast<const uint32*>(&other);
- }
-
- bool operator!=(const Color4uint8& other) const {
- return *reinterpret_cast<const uint32*>(this) != *reinterpret_cast<const uint32*>(&other);
- }
-
-}
-G3D_END_PACKED_CLASS(1)
-
-} // namespace G3D
-
-#endif
diff --git a/externals/g3dlite/G3D/Cone.h b/externals/g3dlite/G3D/Cone.h
deleted file mode 100644
index d801a9b348f..00000000000
--- a/externals/g3dlite/G3D/Cone.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/**
- @file Cone.h
-
- Cone class
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @cite Portions based on Dave Eberly's Magic Software Library at <A HREF="http://www.magic-software.com">http://www.magic-software.com</A>
-
- @created 2001-06-02
- @edited 2006-02-23
-
- Copyright 2000-2006, Morgan McGuire.
- All rights reserved.
- */
-
-#ifndef G3D_CONE_H
-#define G3D_CONE_H
-
-#include "G3D/platform.h"
-#include "G3D/g3dmath.h"
-#include "G3D/Vector3.h"
-
-namespace G3D {
-
-/**
- An infinite cone.
- */
-class Cone {
-
-private:
- Vector3 tip;
- Vector3 direction;
-
- /** Angle from the center line to the edge. */
- float angle;
-
-public:
-
- /**
- @param angle Angle from the center line to the edge, in radians
- */
- Cone(const Vector3& tip, const Vector3& direction, float angle);
-
- /**
- Forms the smallest cone that contains the box. Undefined if
- the tip is inside or on the box.
- */
- Cone(const Vector3& tip, const class Box& box);
-
- virtual ~Cone() {}
-
- /**
- Returns true if the cone touches, intersects, or contains b.
-
- If c.intersects(s) and c.intersects(Sphere(s.center, s.radius * 2)
- then the sphere s is entirely within cone c.
- */
- bool intersects(const class Sphere& s) const;
-
- /**
- True if v is a point inside the cone.
- */
- bool contains(const class Vector3& v) const;
-};
-
-} // namespace
-
-#endif
diff --git a/externals/g3dlite/G3D/ConvexPolyhedron.h b/externals/g3dlite/G3D/ConvexPolyhedron.h
deleted file mode 100644
index a6fdd62cf90..00000000000
--- a/externals/g3dlite/G3D/ConvexPolyhedron.h
+++ /dev/null
@@ -1,180 +0,0 @@
-/**
- @file ConvexPolyhedron.h
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2001-11-11
- @edited 2006-04-10
-
- Copyright 2000-2006, Morgan McGuire.
- All rights reserved.
- */
-
-#ifndef G3D_CONVEXPOLYHEDRON_H
-#define G3D_CONVEXPOLYHEDRON_H
-
-#include "G3D/platform.h"
-#include "G3D/Vector3.h"
-#include "G3D/Vector2.h"
-#include "G3D/CoordinateFrame.h"
-#include "G3D/Plane.h"
-#include "G3D/Line.h"
-#include "G3D/Array.h"
-
-namespace G3D {
-
-class DirectedEdge {
-public:
- Vector3 start;
- Vector3 stop;
-};
-
-class ConvexPolygon {
-private:
-
- friend class ConvexPolyhedron;
-
- Array<Vector3> _vertex;
-
-public:
-
- ConvexPolygon() {}
- ConvexPolygon(const Vector3& v0, const Vector3& v1, const Vector3& v2);
- ConvexPolygon(const Array<Vector3>& __vertex);
- virtual ~ConvexPolygon() {}
-
- /**
- Counter clockwise winding order.
- */
- inline const Vector3& vertex(int i) const {
- return _vertex[i];
- }
-
- inline void setVertex(int i, const Vector3& v) {
- _vertex[i] = v;
- }
-
- /**
- Zero vertices indicates an empty polygon (zero area).
- */
- inline int numVertices() const {
- return _vertex.size();
- }
-
- inline void setNumVertices(int n) {
- _vertex.resize(n);
- }
-
- /**
- O(n) in the number of edges
- */
- bool isEmpty() const;
-
- /**
- Cuts the polygon at the plane. If the polygon is entirely above or below
- the plane, one of the returned polygons will be empty.
-
- @param above The part of the polygon above (on the side the
- normal points to or in the plane) the plane
- @param below The part of the polygon below the plane.
- @param newEdge If a new edge was introduced, this is that edge (on the above portion; the below portion is the opposite winding.
- */
- void cut(const Plane& plane, ConvexPolygon &above, ConvexPolygon &below, DirectedEdge& newEdge);
- void cut(const Plane& plane, ConvexPolygon &above, ConvexPolygon &below);
-
- /**
- When a cut plane grazes a vertex in the polygon, two near-identical vertices may be created.
- The closeness of these two points can cause a number of problems, such as ConvexPolygon::normal()
- returning an infinite vector. It should be noted, however, that not all applications are
- sensitive to near-identical vertices.
-
- removeDuplicateVertices() detects and eliminates redundant vertices.
- */
- void removeDuplicateVertices();
-
- /**
- O(n) in the number of edges
- */
- float getArea() const;
-
- inline Vector3 normal() const {
- debugAssert(_vertex.length() >= 3);
- return (_vertex[1] - _vertex[0]).cross(_vertex[2] - _vertex[0]).direction();
- }
-
- /**
- Returns the same polygon with inverse winding.
- */
- ConvexPolygon inverse() const;
-};
-
-
-
-class ConvexPolyhedron {
-public:
- /**
- Zero faces indicates an empty polyhedron
- */
- Array<ConvexPolygon> face;
-
- ConvexPolyhedron() {}
- ConvexPolyhedron(const Array<ConvexPolygon>& _face);
-
- /**
- O(n) in the number of edges
- */
- bool isEmpty() const;
-
- /**
- O(n) in the number of edges
- */
- float getVolume() const;
-
- /**
- Cuts the polyhedron at the plane. If the polyhedron is entirely above or below
- the plane, one of the returned polyhedra will be empty.
-
- @param above The part of the polyhedron above (on the side the
- normal points to or in the plane) the plane
- @param below The part of the polyhedron below the plane.
- */
- void cut(const Plane& plane, ConvexPolyhedron &above, ConvexPolyhedron &below);
-};
-
-/**
-
- */
-class ConvexPolygon2D {
-private:
-
- Array<Vector2> m_vertex;
-
-public:
-
- ConvexPolygon2D() {}
-
- /**
- Points are counter-clockwise in a Y = down, X = right coordinate
- system.
-
- @param reverse If true, the points are reversed (i.e. winding direction is changed)
- before the polygon is created.
- */
- ConvexPolygon2D(const Array<Vector2>& pts, bool reverse = false);
-
- inline int numVertices() const {
- return m_vertex.size();
- }
-
- inline const Vector2& vertex(int index) const {
- debugAssert((index >= 0) && (index <= m_vertex.size()));
- return m_vertex[index];
- }
-
- /** @param reverseWinding If true, the winding direction of the polygon is reversed for this test.*/
- bool contains(const Vector2& p, bool reverseWinding = false) const;
-};
-
-
-} // namespace
-#endif
diff --git a/externals/g3dlite/G3D/CoordinateFrame.h b/externals/g3dlite/G3D/CoordinateFrame.h
deleted file mode 100644
index 7ed4d0acc65..00000000000
--- a/externals/g3dlite/G3D/CoordinateFrame.h
+++ /dev/null
@@ -1,331 +0,0 @@
-/**
- @file CoordinateFrame.h
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2001-03-04
- @edited 2009-04-29
-
- Copyright 2000-2009, Morgan McGuire.
- All rights reserved.
-*/
-
-#ifndef G3D_CFrame_h
-#define G3D_CFrame_h
-
-#include "G3D/platform.h"
-#include "G3D/Vector3.h"
-#include "G3D/Vector4.h"
-#include "G3D/Matrix3.h"
-#include "G3D/Array.h"
-#include <math.h>
-#include <string>
-#include <stdio.h>
-#include <cstdarg>
-#include <assert.h>
-
-#ifdef _MSC_VER
-// Turn off "conditional expression is constant" warning; MSVC generates this
-// for debug assertions in inlined methods.
-# pragma warning (disable : 4127)
-#endif
-
-
-namespace G3D {
-class Any;
-
-/**
- A rigid body RT (rotation-translation) transformation.
-
-CoordinateFrame abstracts a 4x4 matrix that maps object space to world space:
-
- v_world = C * v_object
-
-CoordinateFrame::rotation is the upper 3x3 submatrix, CoordinateFrame::translation
-is the right 3x1 column. The 4th row is always [0 0 0 1], so it isn't stored.
-So you don't have to remember which way the multiplication and transformation work,
-it provides explicit toWorldSpace and toObjectSpace methods. Also, points, vectors
-(directions), and surface normals transform differently, so they have separate methods.
-
-Some helper functions transform whole primitives like boxes in and out of object space.
-
-Convert to Matrix4 using CoordinateFrame::toMatrix4. You <I>can</I> construct a CoordinateFrame
-from a Matrix4 using Matrix4::approxCoordinateFrame, however, because a Matrix4 is more
-general than a CoordinateFrame, some information may be lost.
-
-@sa G3D::UprightFrame, G3D::PhysicsFrame, G3D::Matrix4, G3D::Quat
-*/
-class CoordinateFrame {
-public:
-
- /** Takes object space points to world space. */
- Matrix3 rotation;
-
- /** Takes object space points to world space. */
- Vector3 translation;
-
- /** \param any Must be in one of the following forms:
- - CFrame((matrix3 expr), (vector3 expr))
- - CFrame::fromXYZYPRDegrees(#, #, #, #, #, #)
- - CFrame { rotation = (matrix3 expr), translation = (vector3 expr) }
- */
- CoordinateFrame(const Any& any);
-
- /** Converts the CFrame to an Any. */
- operator Any() const;
-
- inline bool operator==(const CoordinateFrame& other) const {
- return (translation == other.translation) && (rotation == other.rotation);
- }
-
- inline bool operator!=(const CoordinateFrame& other) const {
- return !(*this == other);
- }
-
- bool fuzzyEq(const CoordinateFrame& other) const;
-
- bool fuzzyIsIdentity() const;
-
- bool isIdentity() const;
-
- /**
- Initializes to the identity coordinate frame.
- */
- CoordinateFrame();
-
- CoordinateFrame(const Vector3& _translation) :
- rotation(Matrix3::identity()), translation(_translation) {
- }
-
- CoordinateFrame(const Matrix3 &rotation, const Vector3 &translation) :
- rotation(rotation), translation(translation) {
- }
-
- CoordinateFrame(const Matrix3 &rotation) :
- rotation(rotation), translation(Vector3::zero()) {
- }
-
- CoordinateFrame(const class UprightFrame& f);
-
- static CoordinateFrame fromXYZYPRRadians(float x, float y, float z, float yaw = 0.0f, float pitch = 0.0f, float roll = 0.0f);
-
- /** Construct a coordinate frame from translation = (x,y,z) and
- rotations (in that order) about Y, object space X, object space
- Z. Note that because object-space axes are used, these are not
- equivalent to Euler angles; they are known as Tait-Bryan
- rotations and are more convenient for intuitive positioning.*/
- static CoordinateFrame fromXYZYPRDegrees(float x, float y, float z, float yaw = 0.0f, float pitch = 0.0f, float roll = 0.0f);
-
- CoordinateFrame(class BinaryInput& b);
-
- void deserialize(class BinaryInput& b);
-
- void serialize(class BinaryOutput& b) const;
-
- CoordinateFrame(const CoordinateFrame &other) :
- rotation(other.rotation), translation(other.translation) {}
-
- /**
- Computes the inverse of this coordinate frame.
- */
- inline CoordinateFrame inverse() const {
- CoordinateFrame out;
- out.rotation = rotation.transpose();
- out.translation = -out.rotation * translation;
- return out;
- }
-
- inline ~CoordinateFrame() {}
-
- /** See also Matrix4::approxCoordinateFrame */
- class Matrix4 toMatrix4() const;
-
- void getXYZYPRRadians(float& x, float& y, float& z, float& yaw, float& pitch, float& roll) const;
- void getXYZYPRDegrees(float& x, float& y, float& z, float& yaw, float& pitch, float& roll) const;
-
-
- /**
- Produces an XML serialization of this coordinate frame.
- @deprecated
- */
- std::string toXML() const;
-
- /**
- Returns the heading of the lookVector as an angle in radians relative to
- the world -z axis. That is, a counter-clockwise heading where north (-z)
- is 0 and west (-x) is PI/2.
-
- Note that the heading ignores the Y axis, so an inverted
- object has an inverted heading.
- */
- inline float getHeading() const {
- Vector3 look = rotation.column(2);
- float angle = -(float) atan2(-look.x, look.z);
- return angle;
- }
-
- /**
- Takes the coordinate frame into object space.
- this->inverse() * c
- */
- inline CoordinateFrame toObjectSpace(const CoordinateFrame& c) const {
- return this->inverse() * c;
- }
-
- inline Vector4 toObjectSpace(const Vector4& v) const {
- return this->inverse().toWorldSpace(v);
- }
-
- inline Vector4 toWorldSpace(const Vector4& v) const {
- return Vector4(rotation * Vector3(v.x, v.y, v.z) + translation * v.w, v.w);
- }
-
- /**
- Transforms the point into world space.
- */
- inline Vector3 pointToWorldSpace(const Vector3& v) const {
- return Vector3(
- rotation[0][0] * v[0] + rotation[0][1] * v[1] + rotation[0][2] * v[2] + translation[0],
- rotation[1][0] * v[0] + rotation[1][1] * v[1] + rotation[1][2] * v[2] + translation[1],
- rotation[2][0] * v[0] + rotation[2][1] * v[1] + rotation[2][2] * v[2] + translation[2]);
- }
-
- /**
- Transforms the point into object space. Assumes that the rotation matrix is orthonormal.
- */
- inline Vector3 pointToObjectSpace(const Vector3& v) const {
- float p[3];
- p[0] = v[0] - translation[0];
- p[1] = v[1] - translation[1];
- p[2] = v[2] - translation[2];
- debugAssert(G3D::fuzzyEq(rotation.determinant(), 1.0f));
- return Vector3(
- rotation[0][0] * p[0] + rotation[1][0] * p[1] + rotation[2][0] * p[2],
- rotation[0][1] * p[0] + rotation[1][1] * p[1] + rotation[2][1] * p[2],
- rotation[0][2] * p[0] + rotation[1][2] * p[1] + rotation[2][2] * p[2]);
- }
-
- /**
- Transforms the vector into world space (no translation).
- */
- inline Vector3 vectorToWorldSpace(const Vector3& v) const {
- return rotation * v;
- }
-
- inline Vector3 normalToWorldSpace(const Vector3& v) const {
- return rotation * v;
- }
-
- class Ray toObjectSpace(const Ray& r) const;
-
- Ray toWorldSpace(const Ray& r) const;
-
- /**
- Transforms the vector into object space (no translation).
- */
- inline Vector3 vectorToObjectSpace(const Vector3 &v) const {
- // Multiply on the left (same as rotation.transpose() * v)
- return v * rotation;
- }
-
- inline Vector3 normalToObjectSpace(const Vector3 &v) const {
- // Multiply on the left (same as rotation.transpose() * v)
- return v * rotation;
- }
-
- void pointToWorldSpace(const Array<Vector3>& v, Array<Vector3>& vout) const;
-
- void normalToWorldSpace(const Array<Vector3>& v, Array<Vector3>& vout) const;
-
- void vectorToWorldSpace(const Array<Vector3>& v, Array<Vector3>& vout) const;
-
- void pointToObjectSpace(const Array<Vector3>& v, Array<Vector3>& vout) const;
-
- void normalToObjectSpace(const Array<Vector3>& v, Array<Vector3>& vout) const;
-
- void vectorToObjectSpace(const Array<Vector3>& v, Array<Vector3>& vout) const;
-
- class Box toWorldSpace(const class AABox& b) const;
-
- class Box toWorldSpace(const class Box& b) const;
-
- class Cylinder toWorldSpace(const class Cylinder& b) const;
-
- class Capsule toWorldSpace(const class Capsule& b) const;
-
- class Plane toWorldSpace(const class Plane& p) const;
-
- class Sphere toWorldSpace(const class Sphere& b) const;
-
- class Triangle toWorldSpace(const class Triangle& t) const;
-
- class Box toObjectSpace(const AABox& b) const;
-
- class Box toObjectSpace(const Box& b) const;
-
- class Plane toObjectSpace(const Plane& p) const;
-
- class Sphere toObjectSpace(const Sphere& b) const;
-
- Triangle toObjectSpace(const Triangle& t) const;
-
- /** Compose: create the transformation that is <I>other</I> followed by <I>this</I>.*/
- CoordinateFrame operator*(const CoordinateFrame &other) const {
- return CoordinateFrame(rotation * other.rotation,
- pointToWorldSpace(other.translation));
- }
-
- CoordinateFrame operator+(const Vector3& v) const {
- return CoordinateFrame(rotation, translation + v);
- }
-
- CoordinateFrame operator-(const Vector3& v) const {
- return CoordinateFrame(rotation, translation - v);
- }
-
- void lookAt(const Vector3& target);
-
- void lookAt(
- const Vector3& target,
- Vector3 up);
-
- /** The direction this camera is looking (its negative z axis)*/
- inline Vector3 lookVector() const {
- return -rotation.column(2);
- }
-
- /** Returns the ray starting at the camera origin travelling in direction CoordinateFrame::lookVector. */
- class Ray lookRay() const;
-
- /** Up direction for this camera (its y axis). */
- inline Vector3 upVector() const {
- return rotation.column(1);
- }
-
- inline Vector3 rightVector() const {
- return rotation.column(0);
- }
-
- /**
- If a viewer looks along the look vector, this is the viewer's "left".
- Useful for strafing motions and building alternative coordinate frames.
- */
- inline Vector3 leftVector() const {
- return -rotation.column(0);
- }
-
- /**
- Linearly interpolates between two coordinate frames, using
- Quat::slerp for the rotations.
- */
- CoordinateFrame lerp(
- const CoordinateFrame& other,
- float alpha) const;
-
-};
-
-typedef CoordinateFrame CFrame;
-
-} // namespace
-
-#endif
diff --git a/externals/g3dlite/G3D/Crypto.h b/externals/g3dlite/G3D/Crypto.h
deleted file mode 100644
index 56c816a4977..00000000000
--- a/externals/g3dlite/G3D/Crypto.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/**
- @file Crypto.h
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
-
- @created 2006-03-29
- @edited 2006-04-06
- */
-
-#ifndef G3D_CRYPTO_H
-#define G3D_CRYPTO_H
-
-#include "G3D/platform.h"
-#include "G3D/g3dmath.h"
-#include <string>
-
-namespace G3D {
-
-/** See G3D::Crypto::md5 */
-class MD5Hash {
-private:
-
- uint8 value[16];
-
-public:
-
- MD5Hash() {
- for (int i = 0; i < 16; ++i) {
- value[i] = 0;
- }
- }
-
- explicit MD5Hash(class BinaryInput& b);
-
- uint8& operator[](int i) {
- return value[i];
- }
-
- const uint8& operator[](int i) const {
- return value[i];
- }
-
- bool operator==(const MD5Hash& other) const {
- bool match = true;
- for (int i = 0; i < 16; ++i) {
- match = match && (other.value[i] == value[i]);
- }
- return match;
- }
-
- inline bool operator!=(const MD5Hash& other) const {
- return !(*this == other);
- }
-
- void deserialize(class BinaryInput& b);
-
- void serialize(class BinaryOutput& b) const;
-};
-
-
-/** Cryptography and hashing helper functions */
-class Crypto {
-public:
-
- /**
- Computes the CRC32 value of a byte array. CRC32 is designed to be a hash
- function that produces different values for similar strings.
-
- This implementation is compatible with PKZIP and GZIP.
-
- Based on http://www.gamedev.net/reference/programming/features/crc32/
- */
- static uint32 crc32(const void* bytes, size_t numBytes);
-
- /**
- Computes the MD5 hash (message digest) of a byte stream, as defined by
- http://www.ietf.org/rfc/rfc1321.txt.
-
- @cite Based on implementation by L. Peter Deutsch, ghost@aladdin.com
- */
- MD5Hash md5(const void* bytes, size_t numBytes);
-
- /**
- Returns the nth prime less than 2000 in constant time. The first prime has index
- 0 and is the number 2.
- */
- static int smallPrime(int n);
-
- /** Returns 1 + the largest value that can be passed to smallPrime. */
- static int numSmallPrimes();
-};
-
-}
-
-#endif
diff --git a/externals/g3dlite/G3D/Cylinder.h b/externals/g3dlite/G3D/Cylinder.h
deleted file mode 100644
index 85eba77b794..00000000000
--- a/externals/g3dlite/G3D/Cylinder.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/**
- @file Cylinder.h
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2003-02-07
- @edited 2005-09-26
-
- Copyright 2000-2005, Morgan McGuire.
- All rights reserved.
- */
-
-#ifndef G3D_Cylinder_H
-#define G3D_Cylinder_H
-
-#include "G3D/platform.h"
-#include "G3D/g3dmath.h"
-#include "G3D/Vector3.h"
-
-namespace G3D {
-
-class Line;
-class AABox;
-/**
- Right cylinder
- */
-class Cylinder {
-private:
- Vector3 p1;
- Vector3 p2;
-
- float mRadius;
-
-public:
-
- /** Uninitialized */
- Cylinder();
- Cylinder(class BinaryInput& b);
- Cylinder(const Vector3& _p1, const Vector3& _p2, float _r);
- void serialize(class BinaryOutput& b) const;
- void deserialize(class BinaryInput& b);
-
- /** The line down the center of the Cylinder */
- Line axis() const;
-
- /**
- A reference frame in which the center of mass is at the origin and
- the Y-axis is the cylinder's axis. If the cylinder is transformed, this reference frame
- may freely rotate around its axis.*/
- void getReferenceFrame(class CoordinateFrame& cframe) const;
-
- /** Returns point 0 or 1 */
- inline const Vector3& point(int i) const {
- debugAssert(i >= 0 && i <= 1);
- return (i == 0) ? p1 : p2;
- }
-
- /**
- Returns true if the point is inside the Cylinder or on its surface.
- */
- bool contains(const Vector3& p) const;
-
- float area() const;
-
- float volume() const;
-
- float radius() const;
-
- /** Center of mass */
- inline Vector3 center() const {
- return (p1 + p2) / 2.0f;
- }
-
- inline float height() const {
- return (p1 - p2).magnitude();
- }
-
- /**
- Get close axis aligned bounding box.
- With vertical world orientation, the top and bottom might not be very tight. */
- void getBounds(AABox& out) const;
-
- /** Random world space point with outward facing normal. */
- void getRandomSurfacePoint(Vector3& P, Vector3& N) const;
-
- /** Point selected uniformly at random over the volume. */
- Vector3 randomInteriorPoint() const;
-};
-
-} // namespace
-
-#endif
diff --git a/externals/g3dlite/G3D/EqualsTrait.h b/externals/g3dlite/G3D/EqualsTrait.h
deleted file mode 100644
index 349cb5088fb..00000000000
--- a/externals/g3dlite/G3D/EqualsTrait.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/**
- @file EqualsTrait.h
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @created 2008-10-01
- @edited 2008-10-01
- Copyright 2000-2009, Morgan McGuire.
- All rights reserved.
- */
-
-#ifndef G3D_EQUALSTRAIT_H
-#define G3D_EQUALSTRAIT_H
-
-#include "G3D/platform.h"
-
-/** Default implementation of EqualsTrait.
- @see G3D::Table for specialization requirements.
-*/
-template<typename Key> struct EqualsTrait {
- static bool equals(const Key& a, const Key& b) {
- return a == b;
- }
-};
-
-#endif
-
diff --git a/externals/g3dlite/G3D/G3D.h b/externals/g3dlite/G3D/G3D.h
deleted file mode 100644
index 5b56b9c71dc..00000000000
--- a/externals/g3dlite/G3D/G3D.h
+++ /dev/null
@@ -1,162 +0,0 @@
-/**
- @file G3D.h
-
- This header includes all of the G3D libraries in
- appropriate namespaces.
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2001-08-25
- @edited 2010-01-30
-
- Copyright 2000-2010, Morgan McGuire.
- All rights reserved.
-*/
-
-#ifndef G3D_G3D_h
-#define G3D_G3D_h
-
-#define NOMINMAX 1
-#ifdef min
- #undef min
-#endif
-#ifdef max
- #undef max
-#endif
-
-#include "G3D/platform.h"
-#include "G3D/units.h"
-#include "G3D/ParseError.h"
-#include "G3D/Random.h"
-#include "G3D/Array.h"
-#include "G3D/SmallArray.h"
-#include "G3D/Queue.h"
-#include "G3D/Crypto.h"
-#include "G3D/format.h"
-#include "G3D/Vector2.h"
-#include "G3D/Vector3.h"
-#include "G3D/Vector4.h"
-#include "G3D/Color1.h"
-#include "G3D/Color3.h"
-#include "G3D/Color4.h"
-#include "G3D/Matrix2.h"
-#include "G3D/Matrix3.h"
-#include "G3D/Matrix4.h"
-#include "G3D/CoordinateFrame.h"
-#include "G3D/PhysicsFrame.h"
-#include "G3D/Plane.h"
-#include "G3D/Line.h"
-#include "G3D/Ray.h"
-#include "G3D/Sphere.h"
-#include "G3D/Box.h"
-#include "G3D/Box2D.h"
-#include "G3D/AABox.h"
-#include "G3D/WrapMode.h"
-#include "G3D/Cone.h"
-#include "G3D/Quat.h"
-#include "G3D/stringutils.h"
-#include "G3D/prompt.h"
-#include "G3D/Table.h"
-#include "G3D/Set.h"
-#include "G3D/GUniqueID.h"
-#include "G3D/BinaryFormat.h"
-#include "G3D/BinaryInput.h"
-#include "G3D/BinaryOutput.h"
-#include "G3D/debug.h"
-#include "G3D/g3dfnmatch.h"
-#include "G3D/G3DGameUnits.h"
-#include "G3D/g3dmath.h"
-#include "G3D/uint128.h"
-#include "G3D/fileutils.h"
-#include "G3D/ReferenceCount.h"
-#include "G3D/Welder.h"
-#include "G3D/GMutex.h"
-#include "G3D/PrecomputedRandom.h"
-#include "G3D/MemoryManager.h"
-#include "G3D/AreaMemoryManager.h"
-#include "G3D/BumpMapPreprocess.h"
-
-template<class T> struct HashTrait< G3D::ReferenceCountedPointer<T> > {
- static size_t hashCode(G3D::ReferenceCountedPointer<T> key) { return reinterpret_cast<size_t>( key.pointer() ); }
-};
-
-#include "G3D/GImage.h"
-#include "G3D/CollisionDetection.h"
-#include "G3D/Intersect.h"
-#include "G3D/Log.h"
-#include "G3D/serialize.h"
-#include "G3D/TextInput.h"
-#include "G3D/NetAddress.h"
-#include "G3D/NetworkDevice.h"
-#include "G3D/System.h"
-#include "G3D/splinefunc.h"
-#include "G3D/Spline.h"
-#include "G3D/UprightFrame.h"
-#include "G3D/LineSegment.h"
-#include "G3D/Capsule.h"
-#include "G3D/Cylinder.h"
-#include "G3D/Triangle.h"
-#include "G3D/Color3uint8.h"
-#include "G3D/Color4uint8.h"
-#include "G3D/Vector2int16.h"
-#include "G3D/Vector3int16.h"
-#include "G3D/Vector3int32.h"
-#include "G3D/Vector4int8.h"
-#include "G3D/ConvexPolyhedron.h"
-#include "G3D/MeshAlg.h"
-#include "G3D/vectorMath.h"
-#include "G3D/Rect2D.h"
-#include "G3D/GCamera.h"
-#include "G3D/GLight.h"
-#include "G3D/KDTree.h"
-#include "G3D/PointKDTree.h"
-#include "G3D/TextOutput.h"
-#include "G3D/MeshBuilder.h"
-#include "G3D/Stopwatch.h"
-#include "G3D/AtomicInt32.h"
-#include "G3D/GThread.h"
-#include "G3D/ThreadSet.h"
-#include "G3D/RegistryUtil.h"
-#include "G3D/Any.h"
-#include "G3D/PointHashGrid.h"
-#include "G3D/Map2D.h"
-#include "G3D/Image1.h"
-#include "G3D/Image1uint8.h"
-#include "G3D/Image3.h"
-#include "G3D/Image3uint8.h"
-#include "G3D/Image4.h"
-#include "G3D/Image4uint8.h"
-#include "G3D/filter.h"
-#include "G3D/WeakCache.h"
-#include "G3D/Pointer.h"
-#include "G3D/Matrix.h"
-#include "G3D/ImageFormat.h"
-
-#ifdef _MSC_VER
-# pragma comment(lib, "zlib")
-# pragma comment(lib, "ws2_32")
-# pragma comment(lib, "winmm")
-# pragma comment(lib, "imagehlp")
-# pragma comment(lib, "gdi32")
-# pragma comment(lib, "user32")
-# pragma comment(lib, "kernel32")
-# pragma comment(lib, "version")
-# pragma comment(lib, "advapi32")
-# pragma comment(lib, "png")
-# pragma comment(lib, "jpeg")
-# pragma comment(lib, "zip")
-# ifdef _DEBUG
- // Don't link against G3D when building G3D itself.
-# ifndef G3D_BUILDING_LIBRARY_DLL
-# pragma comment(lib, "G3Dd.lib")
-# endif
-# else
- // Don't link against G3D when building G3D itself.
-# ifndef G3D_BUILDING_LIBRARY_DLL
-# pragma comment(lib, "G3D.lib")
-# endif
-# endif
-#endif
-
-#endif
-
diff --git a/externals/g3dlite/G3D/G3DAll.h b/externals/g3dlite/G3D/G3DAll.h
deleted file mode 100644
index 1176fe742e7..00000000000
--- a/externals/g3dlite/G3D/G3DAll.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/**
- @file G3DAll.h
-
- Includes all G3D and GLG3D files and uses the G3D namespace.
-
- This requires OpenGL and SDL headers. If you don't want all of this,
- \#include <G3D.h> separately.
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2002-01-01
- @edited 2006-08-13
-
- Copyright 2000-2006, Morgan McGuire.
- All rights reserved.
- */
-
-#ifndef G3D_G3DALL_H
-#define G3D_G3DALL_H
-
-#include "G3D/G3D.h"
-#include "GLG3D/GLG3D.h"
-
-using namespace G3D;
-
-#endif
diff --git a/externals/g3dlite/G3D/G3DGameUnits.h b/externals/g3dlite/G3D/G3DGameUnits.h
deleted file mode 100644
index e2bc2c811e8..00000000000
--- a/externals/g3dlite/G3D/G3DGameUnits.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/**
- @file G3DGameUnits.h
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @created 2002-10-05
- @edited 2006-11-10
- */
-
-#ifndef G3D_GAMEUNITS_H
-#define G3D_GAMEUNITS_H
-
-#include "G3D/platform.h"
-
-namespace G3D {
-/**
- Time, in seconds.
- */
-typedef double GameTime;
-typedef double SimTime;
-
-/**
- Actual wall clock time in seconds.
- */
-typedef double RealTime;
-
-enum AMPM {AM, PM};
-
-/** \deprecated */
-enum {SECOND=1, MINUTE=60, HOUR = 60*60, DAY=24*60*60, SUNRISE=24*60*60/4, SUNSET=24*60*60*3/4, MIDNIGHT=0, METER=1, KILOMETER=1000};
-
-/**
- Converts a 12 hour clock time into the number of seconds since
- midnight. Note that 12:00 PM is noon and 12:00 AM is midnight.
-
- Example: <CODE>toSeconds(10, 00, AM)</CODE>
- */
-SimTime toSeconds(int hour, int minute, double seconds, AMPM ap);
-SimTime toSeconds(int hour, int minute, AMPM ap);
-
-}
-
-#endif
diff --git a/externals/g3dlite/G3D/GCamera.h b/externals/g3dlite/G3D/GCamera.h
deleted file mode 100644
index 018fbc85d59..00000000000
--- a/externals/g3dlite/G3D/GCamera.h
+++ /dev/null
@@ -1,337 +0,0 @@
-/**
- @file GCamera.h
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2005-07-20
- @edited 2009-04-20
-*/
-
-#ifndef G3D_GCamera_H
-#define G3D_GCamera_H
-
-#include "G3D/platform.h"
-#include "G3D/CoordinateFrame.h"
-#include "G3D/Vector3.h"
-#include "G3D/Plane.h"
-#include "G3D/debugAssert.h"
-
-namespace G3D {
-
-class Matrix4;
-class Rect2D;
-class Any;
-
-/**
- Abstraction of a pinhole camera.
-
- The area a camera sees is called a frustum. It is bounded by the
- near plane, the far plane, and the sides of the view frame projected
- into the scene. It has the shape of a pyramid with the top cut off.
-
- Cameras can project points from 3D to 2D. The "unit" projection
- matches OpenGL. It maps the entire view frustum to a cube of unit
- radius (i.e., edges of length 2) centered at the origin. The
- non-unit projection then maps that cube to the specified pixel
- viewport in X and Y and the range [0, 1] in Z. The projection is
- reversable as long as the projected Z value is known.
-
- All viewport arguments are the pixel bounds of the viewport-- e.g.,
- RenderDevice::viewport().
- */
-class GCamera {
-
-public:
- /**
- Stores the direction of the field of view
- */
- enum FOVDirection {HORIZONTAL, VERTICAL};
-
-private:
-
- /** Full field of view (in radians) */
- float m_fieldOfView;
-
- /** Clipping plane, *not* imaging plane. Negative numbers. */
- float m_nearPlaneZ;
-
- /** Negative */
- float m_farPlaneZ;
-
- /** Stores the camera's location and orientation */
- CoordinateFrame m_cframe;
-
- /** Horizontal or Vertical */
- FOVDirection m_direction;
-
-public:
-
- /** Must be of the format produced by the Any cast, e.g.,
-
- <pre>
- GCamera {
- coordinateFrame = CFrame::fromXYZYPRDegrees(-13.3f, 8.0f, -1.9f, 246.6f, -3),
- nearPlaneZ = -0.5,
- farPlaneZ = -50,
- fovDirection = "HORIZONTAL",
- fovAngleDegrees = 90
- }</pre>
-
- Missing fields are filled from the default GCamera constructor.
- */
- GCamera(const Any& any);
-
- operator Any() const;
-
- class Frustum {
- public:
- class Face {
- public:
- /** Counter clockwise indices into vertexPos */
- int vertexIndex[4];
-
- /** The plane containing the face. */
- Plane plane;
- };
-
- /** The vertices, in homogeneous space. If w == 0,
- a vertex is at infinity. */
- Array<Vector4> vertexPos;
-
- /** The faces in the frustum. When the
- far plane is at infinity, there are 5 faces,
- otherwise there are 6. The faces are in the order
- N,R,L,B,T,[F].
- */
- Array<Face> faceArray;
- };
-
- GCamera();
-
- GCamera(const Matrix4& proj, const CFrame& frame);
-
- virtual ~GCamera();
-
- /** Returns the current coordinate frame */
- const CoordinateFrame& coordinateFrame() const {
- return m_cframe;
- }
-
- /** Sets c to the camera's coordinate frame */
- void getCoordinateFrame(CoordinateFrame& c) const;
-
- /** Sets a new coordinate frame for the camera */
- void setCoordinateFrame(const CoordinateFrame& c);
-
- /** Sets \a P equal to the camera's projection matrix. This is the
- matrix that maps points to the homogeneous clip cube that
- varies from -1 to 1 on all axes. The projection matrix does
- not include the camera transform.
-
- This is the matrix that a RenderDevice (or OpenGL) uses as the projection matrix.
- @sa RenderDevice::setProjectionAndCameraMatrix, RenderDevice::setProjectionMatrix, Matrix4::perspectiveProjection
- */
- void getProjectUnitMatrix(const Rect2D& viewport, Matrix4& P) const;
-
- /** Sets \a P equal to the matrix that transforms points to pixel
- coordinates on the given viewport. A point correspoinding to
- the top-left corner of the viewport in camera space will
- transform to viewport.x0y0() and the bottom-right to viewport.x1y1(). */
- void getProjectPixelMatrix(const Rect2D& viewport, Matrix4& P) const;
-
- /** Converts projected points from OpenGL standards
- (-1, 1) to normal 3D coordinate standards (0, 1)
-
- \deprecated
- */ // TODO: Remove
- Vector3 convertFromUnitToNormal(const Vector3& in, const Rect2D& viewport) const;
-
- /**
- Sets the field of view, in radians. The
- initial angle is toRadians(55). Must specify
- the direction of the angle.
-
- This is the full angle, i.e., from the left side of the
- viewport to the right side.
- */
- void setFieldOfView(float angle, FOVDirection direction);
-
- /** Returns the current full field of view angle (from the left side of the
- viewport to the right side) and direction */
- inline void getFieldOfView(float& angle, FOVDirection& direction) const {
- angle = m_fieldOfView;
- direction = m_direction;
- }
-
- /**
- Projects a world space point onto a width x height screen. The
- returned coordinate uses pixmap addressing: x = right and y =
- down. The resulting z value is 0 at the near plane, 1 at the far plane,
- and is a linear compression of unit cube projection.
-
- If the point is behind the camera, Vector3::inf() is returned.
- */
- Vector3 project(const G3D::Vector3& point,
- const class Rect2D& viewport) const;
-
- /**
- Projects a world space point onto a unit cube. The resulting
- x,y,z values range between -1 and 1, where z is -1
- at the near plane and 1 at the far plane and varies hyperbolically in between.
-
- If the point is behind the camera, Vector3::inf() is returned.
- */
- Vector3 projectUnit(const G3D::Vector3& point,
- const class Rect2D& viewport) const;
-
- /**
- Gives the world-space coordinates of screen space point v, where
- v.x is in pixels from the left, v.y is in pixels from
- the top, and v.z is on the range 0 (near plane) to 1 (far plane).
- */
- Vector3 unproject(const Vector3& v, const Rect2D& viewport) const;
-
- /**
- Gives the world-space coordinates of unit cube point v, where
- v varies from -1 to 1 on all axes. The unproject first
- transforms the point into a pixel location for the viewport, then calls unproject
- */
- Vector3 unprojectUnit(const Vector3& v, const Rect2D& viewport) const;
-
- /**
- Returns the pixel area covered by a shape of the given
- world space area at the given z value (z must be negative).
- */
- float worldToScreenSpaceArea(float area, float z, const class Rect2D& viewport) const;
-
- /**
- Returns the world space 3D viewport corners. These
- are at the near clipping plane. The corners are constructed
- from the nearPlaneZ, viewportWidth, and viewportHeight.
- "left" and "right" are from the GCamera's perspective.
- */
- void getNearViewportCorners(const class Rect2D& viewport,
- Vector3& outUR, Vector3& outUL,
- Vector3& outLL, Vector3& outLR) const;
-
- /**
- Returns the world space 3D viewport corners. These
- are at the Far clipping plane. The corners are constructed
- from the nearPlaneZ, farPlaneZ, viewportWidth, and viewportHeight.
- "left" and "right" are from the GCamera's perspective.
- */
- void getFarViewportCorners(const class Rect2D& viewport,
- Vector3& outUR, Vector3& outUL,
- Vector3& outLL, Vector3& outLR) const;
-
- /**
- Returns the image plane depth, assumes imagePlane
- is the same as the near clipping plane.
- returns a positive number.
- */
- float imagePlaneDepth() const;
-
- /**
- Returns the world space ray passing through the center of pixel
- (x, y) on the image plane. The pixel x and y axes are opposite
- the 3D object space axes: (0,0) is the upper left corner of the screen.
- They are in viewport coordinates, not screen coordinates.
-
- The ray origin is at the origin. To start it at the image plane,
- move it forward by imagePlaneDepth/ray.direction.z
-
- Integer (x, y) values correspond to
- the upper left corners of pixels. If you want to cast rays
- through pixel centers, add 0.5 to x and y.
- */
- Ray worldRay(
- float x,
- float y,
- const class Rect2D& viewport) const;
-
- /**
- Returns a negative z-value.
- */
- inline float nearPlaneZ() const {
- return m_nearPlaneZ;
- }
-
- /**
- Returns a negative z-value.
- */
- inline float farPlaneZ() const {
- return m_farPlaneZ;
- }
-
- /**
- Sets a new value for the far clipping plane
- Expects a negative value
- */
- inline void setFarPlaneZ(float z) {
- debugAssert(z < 0);
- m_farPlaneZ = z;
- }
-
- /**
- Sets a new value for the near clipping plane
- Expects a negative value
- */
- inline void setNearPlaneZ(float z) {
- debugAssert(z < 0);
- m_nearPlaneZ = z;
- }
-
- /**
- Returns the camera space width of the viewport at the near plane.
- */
- float viewportWidth(const class Rect2D& viewport) const;
-
- /**
- Returns the camera space height of the viewport at the near plane.
- */
- float viewportHeight(const class Rect2D& viewport) const;
-
- void setPosition(const Vector3& t);
-
- /** Rotate the camera in place to look at the target. Does not
- persistently look at that location when the camera moves;
- i.e., if you move the camera and still want it to look at the
- old target, you must call lookAt again after moving the
- camera.)*/
- void lookAt(const Vector3& position, const Vector3& up = Vector3::unitY());
-
- /**
- Returns the clipping planes of the frustum, in world space.
- The planes have normals facing <B>into</B> the view frustum.
-
- The plane order is guaranteed to be:
- Near, Right, Left, Top, Bottom, [Far]
-
- If the far plane is at infinity, the resulting array will have
- 5 planes, otherwise there will be 6.
-
- The viewport is used only to determine the aspect ratio of the screen; the
- absolute dimensions and xy values don't matter.
- */
- void getClipPlanes
- (
- const Rect2D& viewport,
- Array<Plane>& outClip) const;
-
- /**
- Returns the world space view frustum, which is a truncated pyramid describing
- the volume of space seen by this camera.
- */
- void frustum(const Rect2D& viewport, GCamera::Frustum& f) const;
-
- GCamera::Frustum frustum(const Rect2D& viewport) const;
-
- /** Read and Write camera parameters */
- void serialize(class BinaryOutput& bo) const;
- void deserialize(class BinaryInput& bi);
-
-};
-
-} // namespace G3D
-
-#endif
diff --git a/externals/g3dlite/G3D/GImage.h b/externals/g3dlite/G3D/GImage.h
deleted file mode 100644
index 8ae11134fc9..00000000000
--- a/externals/g3dlite/G3D/GImage.h
+++ /dev/null
@@ -1,607 +0,0 @@
-/**
- \file GImage.h
-
- See G3D::GImage for details.
-
- @cite JPEG compress/decompressor is the <A HREF="http://www.ijg.org/files/">IJG library</A>, used in accordance with their license.
- @cite JPG code by John Chisholm, using the IJG Library
- @cite TGA code by Morgan McGuire
- @cite BMP code by John Chisholm, based on code by Edward "CGameProgrammer" Resnick <A HREF="mailto:cgp@gdnmail.net">mailto:cgp@gdnmail.net</A> at <A HREF="ftp://ftp.flipcode.com/cotd/LoadPicture.txt">ftp://ftp.flipcode.com/cotd/LoadPicture.txt</A>
- @cite PCX format described in the ZSOFT PCX manual http://www.nist.fss.ru/hr/doc/spec/pcx.htm#2
- @cite PNG compress/decompressor is the <A HREF="http://www.libpng.org/pub/png/libpng.html">libpng library</A>, used in accordance with their license.
- @cite PPM code by Morgan McGuire based on http://netpbm.sourceforge.net/doc/ppm.html
-
- \maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- \created 2002-05-27
- \edited 2010-01-04
-
- Copyright 2000-2010, Morgan McGuire.
- All rights reserved.
- */
-
-#ifndef G3D_GImage_h
-#define G3D_GImage_h
-
-#include "G3D/platform.h"
-#include <string>
-#include "G3D/Array.h"
-#include "G3D/g3dmath.h"
-#include "G3D/stringutils.h"
-#include "G3D/Color1uint8.h"
-#include "G3D/Color3uint8.h"
-#include "G3D/Color4uint8.h"
-#include "G3D/MemoryManager.h"
-#include "G3D/BumpMapPreprocess.h"
-
-namespace G3D {
-class BinaryInput;
-class BinaryOutput;
-
-
-/**
- Interface to image compression & file formats.
-
- Supported formats (decode and encode): Color JPEG, PNG,
- (Uncompressed)TGA 24, (Uncompressed)TGA 32, BMP 1, BMP 4, BMP 8, BMP
- 24, PPM (P6), and PPM ASCII (P1, P2, P3), which includes PPM, PGM,
- and PBM. 8-bit paletted PCX, 24-bit PCX, and ICO are supported for
- decoding only.
-
- Sample usage:
-
- \verbatim
- // Loading from disk:
- G3D::GImage im1("test.jpg");
-
- // Loading from memory:
- G3D::GImage im2(data, length);
-
- // im.pixel is a pointer to RGB color data. If you want
- // an alpha channel, call RGBtoRGBA or RGBtoARGB for
- // conversion.
-
- // Saving to memory:
- G3D::GImage im3(width, height);
- // (Set the pixels of im3...)
- uint8* data2;
- int len2;
- im3.encode(G3D::GImage::JPEG, data2, len2);
-
- // Saving to disk
- im3.save("out.jpg");
- \endverbatim
-
- The free Image Magick Magick Wand API
- (http://www.imagemagick.org/www/api/magick_wand.html) provides a more powerful
- API for image manipulation and wider set of image load/save formats. It is
- recommended over GImage (we don't include it directly in G3D because their license
- is more restrictive than the BSD one).
-
- */
-class GImage {
-private:
-
- /** Used exclusively for allocating m_byte; this may be an
- implementation that allocates directly on a GPU.*/
- MemoryManager::Ref m_memMan;
- uint8* m_byte;
-
- int m_channels;
- int m_width;
- int m_height;
-
-public:
-
- class Error {
- public:
- Error(
- const std::string& reason,
- const std::string& filename = "") :
- reason(reason), filename(filename) {}
-
- std::string reason;
- std::string filename;
- };
-
- /** PGM, PPM, and PBM all come in two versions and are classified as PPM_* files */
- enum Format {JPEG, BMP, TGA, PCX, ICO, PNG,
- PPM_BINARY, PGM_BINARY = PPM_BINARY,
- PPM_ASCII, PGM_ASCII = PPM_ASCII,
- AUTODETECT, UNKNOWN};
-
-
- /**
- The number of channels; either 3 (RGB) or 4 (RGBA)
- */
- inline int channels() const {
- return m_channels;
- }
-
- inline int width() const {
- return m_width;
- }
-
- inline int height() const {
- return m_height;
- }
-
- inline const uint8* byte() const {
- return m_byte;
- }
-
- /** Returns a pointer to the underlying data, which is stored
- in row-major order without row padding.
- e.g., <code>uint8* ptr = image.rawData<uint8>();
- */
- template<typename Type>
- inline const Type* rawData() const {
- return (Type*)m_byte;
- }
-
- /** \copybrief GImage::rawData() const */
- template<typename Type>
- inline Type* rawData() {
- return (Type*)m_byte;
- }
-
- inline const Color1uint8* pixel1() const {
- debugAssertM(m_channels == 1, format("Tried to call GImage::pixel1 on an image with %d channels", m_channels));
- return (Color1uint8*)m_byte;
- }
-
- inline Color1uint8* pixel1() {
- debugAssertM(m_channels == 1, format("Tried to call GImage::pixel1 on an image with %d channels", m_channels));
- return (Color1uint8*)m_byte;
- }
-
- /** Returns a pointer to the upper left pixel
- as Color4uint8.
- */
- inline const Color4uint8* pixel4() const {
- debugAssertM(m_channels == 4, format("Tried to call GImage::pixel4 on an image with %d channels", m_channels));
- return (Color4uint8*)m_byte;
- }
-
- inline Color4uint8* pixel4() {
- debugAssert(m_channels == 4);
- return (Color4uint8*)m_byte;
- }
-
- /** Returns a pointer to the upper left pixel
- as Color3uint8.
- */
- inline const Color3uint8* pixel3() const {
- debugAssertM(m_channels == 3, format("Tried to call GImage::pixel3 on an image with %d channels", m_channels));
- return (Color3uint8*)m_byte;
- }
-
- inline Color3uint8* pixel3() {
- debugAssert(m_channels == 3);
- return (Color3uint8*)m_byte;
- }
-
- /** Returns the pixel at (x, y), where (0,0) is the upper left. */
- inline const Color1uint8& pixel1(int x, int y) const {
- debugAssert(x >= 0 && x < m_width);
- debugAssert(y >= 0 && y < m_height);
- return pixel1()[x + y * m_width];
- }
-
- /** Returns the pixel at (x, y), where (0,0) is the upper left. */
- inline Color1uint8& pixel1(int x, int y) {
- debugAssert(x >= 0 && x < m_width);
- debugAssert(y >= 0 && y < m_height);
- return pixel1()[x + y * m_width];
- }
-
- /** Returns the pixel at (x, y), where (0,0) is the upper left. */
- inline const Color3uint8& pixel3(int x, int y) const {
- debugAssert(x >= 0 && x < m_width);
- debugAssert(y >= 0 && y < m_height);
- return pixel3()[x + y * m_width];
- }
-
- inline Color3uint8& pixel3(int x, int y) {
- debugAssert(x >= 0 && x < m_width);
- debugAssert(y >= 0 && y < m_height);
- return pixel3()[x + y * m_width];
- }
-
- /** Returns the pixel at (x, y), where (0,0) is the upper left. */
- inline const Color4uint8& pixel4(int x, int y) const {
- debugAssert(x >= 0 && x < m_width);
- debugAssert(y >= 0 && y < m_height);
- return pixel4()[x + y * m_width];
- }
-
- inline Color4uint8& pixel4(int x, int y) {
- debugAssert(x >= 0 && x < m_width);
- debugAssert(y >= 0 && y < m_height);
- return pixel4()[x + y * m_width];
- }
-
- inline uint8* byte() {
- return m_byte;
- }
-
-private:
-
- void encodeBMP(
- BinaryOutput& out) const;
-
- /**
- The TGA file will be either 24- or 32-bit depending
- on the number of channels.
- */
- void encodeTGA(
- BinaryOutput& out) const;
-
- /**
- Converts this image into a JPEG
- */
- void encodeJPEG(
- BinaryOutput& out) const;
-
- /**
- Converts this image into a JPEG
- */
- void encodePNG(
- BinaryOutput& out) const;
-
- void encodePPM(
- BinaryOutput& out) const;
-
- void encodePPMASCII(
- BinaryOutput& out) const;
-
- void decodeTGA(
- BinaryInput& input);
-
- void decodeBMP(
- BinaryInput& input);
-
- void decodeJPEG(
- BinaryInput& input);
-
- void decodePCX(
- BinaryInput& input);
-
- void decodeICO(
- BinaryInput& input);
-
- void decodePNG(
- BinaryInput& input);
-
- void decodePPM(
- BinaryInput& input);
-
- void decodePPMASCII(
- BinaryInput& input);
-
- /**
- Given [maybe] a filename, memory buffer, and [maybe] a format,
- returns the most likely format of this file.
- */
- static Format resolveFormat(
- const std::string& filename,
- const uint8* data,
- int dataLen,
- Format maybeFormat);
-
- void _copy(
- const GImage& other);
-
-public:
-
- /** Predicts the image file format of \a filename */
- static Format resolveFormat(const std::string& filename);
-
- void flipHorizontal();
- void flipVertical();
- void rotate90CW(int numTimes = 1);
-
- /**
- Create an empty image of the given size.
- \sa load()
- */
- GImage(
- int width = 0,
- int height = 0,
- int channels = 3,
- const MemoryManager::Ref& m = MemoryManager::create());
-
- /**
- Load an encoded image from disk and decode it.
- Throws GImage::Error if something goes wrong.
- */
- GImage(
- const std::string& filename,
- Format format = AUTODETECT,
- const MemoryManager::Ref& m = MemoryManager::create());
-
- /**
- Decodes an image stored in a buffer.
- */
- GImage(
- const unsigned char*data,
- int length,
- Format format = AUTODETECT,
- const MemoryManager::Ref& m = MemoryManager::create());
-
- GImage(
- const GImage& other,
- const MemoryManager::Ref& m = MemoryManager::create());
-
- GImage& operator=(const GImage& other);
-
- /**
- Returns a new GImage that has 4 channels. RGB is
- taken from this GImage and the alpha from the red
- channel of the supplied image. The new GImage is passed
- as a reference parameter for speed.
- */
- void insertRedAsAlpha(const GImage& alpha, GImage& output) const;
-
- /**
- Returns a new GImage with 3 channels, removing
- the alpha channel if there is one. The new GImage
- is passed as a reference parameter for speed.
- */
- void stripAlpha(GImage& output) const;
-
- /**
- Loads an image from disk (clearing the old one first),
- using the existing memory manager.
- */
- void load(
- const std::string& filename,
- Format format = AUTODETECT);
-
- /**
- Frees memory and resets to a 0x0 image.
- */
- void clear();
-
- /**
- Deallocates the pixels.
- */
- virtual ~GImage();
-
- /**
- Resizes the internal buffer to (\a width x \a height) with the
- number of \a channels specified.
-
- \param zero If true, all data is set to 0 (black).
- */
- void resize(int width, int height, int channels, bool zero = true);
-
- /**
- Copies src sub-image data into dest at a certain offset.
- The dest variable must already contain an image that is large
- enough to contain the src sub-image at the specified offset.
- Returns true on success and false if the src sub-image cannot
- completely fit within dest at the specified offset. Both
- src and dest must have the same number of channels.
- */
- static bool pasteSubImage(
- GImage& dest,
- const GImage& src,
- int destX,
- int destY,
- int srcX,
- int srcY,
- int srcWidth,
- int srcHeight);
-
- /**
- creates dest from src sub-image data.
- Returns true on success and false if the src sub-image
- is not within src.
- */
- static bool copySubImage(GImage & dest, const GImage & src,
- int srcX, int srcY, int srcWidth, int srcHeight);
-
- void convertToRGBA();
-
- void convertToRGB();
-
- /** Averages color channels if they exist */
- void convertToL8();
-
- /**
- Returns true if format is supported. Format
- should be an extension string (e.g. "BMP").
- */
- static bool supportedFormat(
- const std::string& format);
-
- /**
- Converts a string to an enum, returns UNKNOWN if not recognized.
- */
- static Format stringToFormat(
- const std::string& format);
-
- /**
- Encode and save to disk.
- */
- void save(
- const std::string& filename,
- Format format = AUTODETECT) const;
-
- /**
- The caller must delete the returned buffer.
- TODO: provide a memory manager
- */
- void encode(
- Format format,
- uint8*& outData,
- int& outLength) const;
-
- /**
- Does not commit the BinaryOutput when done.
- */
- void encode(
- Format format,
- BinaryOutput& out) const;
-
- /**
- Decodes the buffer into this image.
- @param format Must be the correct format.
- */
- void decode(
- BinaryInput& input,
- Format format);
-
- /** Returns the size of this object in bytes */
- int sizeInMemory() const;
-
- /** Ok for in == out */
- static void R8G8B8_to_Y8U8V8(int width, int height, const uint8* in, uint8* out);
-
- /** Ok for in == out */
- static void Y8U8V8_to_R8G8B8(int width, int height, const uint8* in, uint8* out);
-
- /**
- @param in RGB buffer of numPixels * 3 bytes
- @param out Buffer of numPixels * 4 bytes
- @param numPixels Number of RGB pixels to convert
- */
- static void RGBtoRGBA(
- const uint8* in,
- uint8* out,
- int numPixels);
-
- static void RGBtoARGB(
- const uint8* in,
- uint8* out,
- int numPixels);
-
- static void LtoRGB
- (const uint8* in,
- uint8* out,
- int numPixels);
-
- static void LtoRGBA
- (const uint8* in,
- uint8* out,
- int numPixels);
-
- /** Safe for in == out */
- static void RGBtoBGR(
- const uint8* in,
- uint8* out,
- int numPixels);
-
- /**
- Win32 32-bit HDC format.
- */
- static void RGBtoBGRA(
- const uint8* in,
- uint8* out,
- int numPixels);
-
- static void RGBAtoRGB(
- const uint8* in,
- uint8* out,
- int numPixels);
- /**
- Uses the red channel of the second image as an alpha channel.
- */
- static void RGBxRGBtoRGBA(
- const uint8* colorRGB,
- const uint8* alphaRGB,
- uint8* out,
- int numPixels);
-
- /**
- Flips the image along the vertical axis.
- Safe for in == out.
- */
- static void flipRGBVertical(
- const uint8* in,
- uint8* out,
- int width,
- int height);
-
- static void flipRGBAVertical(
- const uint8* in,
- uint8* out,
- int width,
- int height);
-
- /**
- Given a tangent space bump map, computes a new image where the
- RGB channels are a tangent space normal map and the alpha channel
- is the original bump map. Assumes the input image is tileable.
-
- In the resulting image, x = red = tangent, y = green = binormal, and z = blue = normal.
-
- Particularly useful as part of the idiom:
- <PRE>
- GImage normal;
- computeNormalMap(GImage(filename), normal);
- return Texture::fromGImage(filename, normal);
- </PRE>
-
- */
- static void computeNormalMap(
- const class GImage& bump,
- class GImage& normal,
- const BumpMapPreprocess& preprocess = BumpMapPreprocess());
-
- static void computeNormalMap
- (int width,
- int height,
- int channels,
- const uint8* src,
- GImage& normal,
- const BumpMapPreprocess& preprocess = BumpMapPreprocess());
-
- /**
- Bayer demosaicing using the filter proposed in
-
- HIGH-QUALITY LINEAR INTERPOLATION FOR DEMOSAICING OF BAYER-PATTERNED COLOR IMAGES
- Henrique S. Malvar, Li-wei He, and Ross Cutler
-
- The filter wraps at the image boundaries.
-
- Assumes in != out.
- */
- static void BAYER_G8B8_R8G8_to_R8G8B8_MHC(int w, int h, const uint8* in, uint8* _out);
- static void BAYER_G8R8_B8G8_to_R8G8B8_MHC(int w, int h, const uint8* in, uint8* _out);
- static void BAYER_R8G8_G8B8_to_R8G8B8_MHC(int w, int h, const uint8* in, uint8* _out);
- static void BAYER_B8G8_G8R8_to_R8G8B8_MHC(int w, int h, const uint8* in, uint8* _out);
-
- /** Fast conversion; the output has 1/2 the size of the input in each direction. Assumes in != out.
- See G3D::BAYER_G8B8_R8G8_to_R8G8B8_MHC for a much better result. */
- static void BAYER_G8B8_R8G8_to_Quarter_R8G8B8
- (int inWidth,
- int inHeight,
- const uint8* in,
- uint8* out);
-
- /** Attempt to undo fast conversion of G3D::BAYER_G8B8_R8G8_to_Quarter_R8G8B8;
- the green channel will lose data. Assumes in != out
- The input should have size 3 * inWidth * inHeight. The output should have size
- 2 * inWidth * 2 * inHeight.
- */
- static void Quarter_R8G8B8_to_BAYER_G8B8_R8G8
- (int inWidth,
- int inHeight,
- const uint8* in,
- uint8* out);
-
- /** Overwrites every pixel with one of the two colors in a checkerboard pattern.
- The fields used from the two colors depend on the current number of channels in @a im.
- */
- static void makeCheckerboard
- (GImage& im,
- int checkerSize = 1,
- const Color4uint8& color1 = Color4uint8(255,255,255,255),
- const Color4uint8& color2 = Color4uint8(0,0,0,255));
-};
-
-}
-
-#endif
diff --git a/externals/g3dlite/G3D/GLight.h b/externals/g3dlite/G3D/GLight.h
deleted file mode 100644
index 3a95f1a8114..00000000000
--- a/externals/g3dlite/G3D/GLight.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/**
- @file GLight.h
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2003-11-12
- @edited 2009-11-08
-*/
-
-#ifndef G3D_GLight_h
-#define G3D_GLight_h
-
-#include "G3D/platform.h"
-#include "G3D/Vector4.h"
-#include "G3D/Vector3.h"
-#include "G3D/Color4.h"
-
-namespace G3D {
-class Any;
-
-/**
- A light representation that closely follows the OpenGL light format.
- */
-class GLight {
-public:
- /** World space position (for a directional light, w = 0 */
- Vector4 position;
-
- /** For a spot or directional light, this is the "right vector" that will be used when constructing
- a reference frame(). */
- Vector3 rightDirection;
-
- /** Direction in which the light faces, if a spot light. This is the "look vector" of the light source. */
- Vector3 spotDirection;
-
- /** In <B>degrees</B>. 180 = no cutoff (point/dir). Values less than 90 = spot light */
- float spotCutoff;
-
- /** If true, G3D::SuperShader will render a cone of light large
- enough to encompass the entire square that bounds the cutoff
- angle. This produces a square prism instead of a cone of light
- when used with a G3D::ShadowMap. for an unshadowed light this
- has no effect.*/
- bool spotSquare;
-
- /** Constant, linear, quadratic */
- float attenuation[3];
-
- /** May be outside the range [0, 1] */
- Color3 color;
-
- /** If false, this light is ignored */
- bool enabled;
-
- /** If false, this light does not create specular highlights
- (useful when using negative lights). */
- bool specular;
-
- /** If false, this light does not create diffuse illumination
- (useful when rendering a specular-only pass). */
- bool diffuse;
-
- GLight();
-
- /** Accepted forms:
- - GLight::directional( vector3, color3, [bool, [bool]])
- - GLight::spot(vector3, vector3, #, color3, [#, [#, [#, [#, [bool, [bool]]]])
- - GLight::point(vector3, color3, [#, [#, [#, [#, [bool, [bool]]]])
- - GLight { [all fields] }
- */
- GLight(const Any& any);
-
- /** Converts the Color3 to an Any. */
- operator Any() const;
-
- /** @param toLight will be normalized */
- static GLight directional(const Vector3& toLight, const Color3& color, bool specular = true, bool diffuse = true);
-
- static GLight point(const Vector3& pos, const Color3& color, float constAtt = 1, float linAtt = 0, float quadAtt = 0.5f, bool specular = true, bool diffuse = true);
-
- /** @param pointDirection Will be normalized. Points in the
- direction that light propagates.
-
- @param cutOffAngleDegrees Must be on the range [0, 90]. This
- is the angle from the point direction to the edge of the light
- cone. I.e., a value of 45 produces a light with a 90-degree
- cone of view.
- */
- static GLight spot(const Vector3& pos, const Vector3& pointDirection, float cutOffAngleDegrees,
- const Color3& color, float constAtt = 1, float linAtt = 0, float quadAtt = 0,
- bool specular = true, bool diffuse = true);
-
- /** Returns the sphere within which this light has some noticable effect. May be infinite.
- @param cutoff The value at which the light intensity is considered negligible. */
- class Sphere effectSphere(float cutoff = 30.0f / 255) const;
-
- /** Computes a reference frame (e.g., for use with G3D::ShadowMap */
- class CoordinateFrame frame() const;
-
- bool operator==(const GLight& other) const;
- bool operator!=(const GLight& other) const;
-};
-
-} // namespace
-#endif
-
diff --git a/externals/g3dlite/G3D/GMutex.h b/externals/g3dlite/G3D/GMutex.h
deleted file mode 100644
index 3469b812736..00000000000
--- a/externals/g3dlite/G3D/GMutex.h
+++ /dev/null
@@ -1,123 +0,0 @@
-/**
- @file GMutex.h
-
- @created 2005-09-22
- @edited 2009-03-25
- */
-
-#ifndef G3D_GMutex_h
-#define G3D_GMutex_h
-
-#include "G3D/platform.h"
-#include "G3D/AtomicInt32.h"
-#include "G3D/debugAssert.h"
-#include <string>
-
-#ifndef G3D_WIN32
-# include <pthread.h>
-# include <signal.h>
-#endif
-
-
-namespace G3D {
-
-/**
- \brief A mutual exclusion lock that busy-waits when locking.
-
- On a machine with one (significant) thread per processor core,
- a spinlock may be substantially faster than a mutex.
-
- \sa G3D::GThread, G3D::GMutex, G3D::AtomicInt32
- */
-class Spinlock {
-private:
-
- AtomicInt32 x;
-
-public:
-
- inline Spinlock() : x(0) {}
-
- /** Busy waits until the lock is unlocked, then locks it
- exclusively. Returns true if the lock succeeded on the first
- try (indicating no contention). */
- inline bool lock() {
- bool first = true;
- while (x.compareAndSet(0, 1) == 1) {
- first = false;
-# ifdef G3D_WIN32
- Sleep(0);
-# else
- usleep(0);
-# endif
- }
- return first;
- }
-
- inline void unlock() {
- x.compareAndSet(1, 0);
- }
-
-};
-
-/**
- \brief Mutual exclusion lock used for synchronization.
-
- @sa G3D::GThread, G3D::AtomicInt32, G3D::Spinlock
-*/
-class GMutex {
-private:
-# ifdef G3D_WIN32
- CRITICAL_SECTION m_handle;
-# else
- pthread_mutex_t m_handle;
- pthread_mutexattr_t m_attr;
-# endif
-
- // Not implemented on purpose, don't use
- GMutex(const GMutex &mlock);
- GMutex &operator=(const GMutex &);
- bool operator==(const GMutex&);
-
-public:
- GMutex();
- ~GMutex();
-
- /** Locks the mutex or blocks until available. */
- void lock();
-
- /** Locks the mutex if it not already locked.
- Returns true if lock successful, false otherwise. */
- bool tryLock();
-
- /** Unlocks the mutex. */
- void unlock();
-};
-
-
-/**
- Automatically locks while in scope.
-*/
-class GMutexLock {
-private:
- GMutex* m;
-
- // Not implemented on purpose, don't use
- GMutexLock(const GMutexLock &mlock);
- GMutexLock &operator=(const GMutexLock &);
- bool operator==(const GMutexLock&);
-
-public:
- GMutexLock(GMutex* mutex) {
- m = mutex;
- m->lock();
- }
-
- ~GMutexLock() {
- m->unlock();
- }
-};
-
-} // G3D
-
-#endif
diff --git a/externals/g3dlite/G3D/GThread.h b/externals/g3dlite/G3D/GThread.h
deleted file mode 100644
index 58437efc3fb..00000000000
--- a/externals/g3dlite/G3D/GThread.h
+++ /dev/null
@@ -1,121 +0,0 @@
-/**
- @file GThread.h
-
- @created 2005-09-22
- @edited 2007-01-31
-
- */
-
-#ifndef G3D_GTHREAD_H
-#define G3D_GTHREAD_H
-
-#include "G3D/platform.h"
-#include "G3D/ReferenceCount.h"
-#include <string>
-
-#ifndef G3D_WIN32
-# include <pthread.h>
-# include <signal.h>
-#endif
-
-
-namespace G3D {
-
-typedef ReferenceCountedPointer<class GThread> GThreadRef;
-
-/**
- Platform independent thread implementation. You can either subclass and
- override GThread::threadMain or call the create method with a method.
-
- Beware of reference counting and threads. If circular references exist between
- GThread subclasses then neither class will ever be deallocated. Also,
- dropping all pointers (and causing deallocation) of a GThread does NOT
- stop the underlying process.
-
- @sa G3D::GMutex, G3D::Spinlock, G3D::AtomicInt32
-*/
-class GThread : public ReferenceCountedObject {
-private:
- // "Status" is a reserved work on FreeBSD
- enum GStatus {STATUS_CREATED, STATUS_STARTED, STATUS_RUNNING, STATUS_COMPLETED};
-
- // Not implemented on purpose, don't use
- GThread(const GThread &);
- GThread& operator=(const GThread&);
- bool operator==(const GThread&);
-
-#ifdef G3D_WIN32
- static DWORD WINAPI internalThreadProc(LPVOID param);
-#else
- static void* internalThreadProc(void* param);
-#endif //G3D_WIN32
-
- volatile GStatus m_status;
-
- // Thread handle to hold HANDLE and pthread_t
-#ifdef G3D_WIN32
- HANDLE m_handle;
- HANDLE m_event;
-#else
- pthread_t m_handle;
-#endif //G3D_WIN32
-
- std::string m_name;
-
-protected:
-
- /** Overriden by the thread implementor */
- virtual void threadMain() = 0;
-
-public:
- typedef ReferenceCountedPointer<class GThread> Ref;
- enum SpawnBehavior {USE_NEW_THREAD, USE_CURRENT_THREAD};
-
- GThread(const std::string& name);
-
- virtual ~GThread();
-
- /** Constructs a basic GThread without requiring a subclass.
-
- @param proc The global or static function for the threadMain() */
- static GThreadRef create(const std::string& name, void (*proc)(void*), void* param = NULL);
-
- /** Starts the thread and executes threadMain(). Returns false if
- the thread failed to start (either because it was already started
- or because the OS refused).
-
- @param behavior If USE_CURRENT_THREAD, rather than spawning a new thread, this routine
- runs threadMain on the current thread.
- */
- bool start(SpawnBehavior behavior = USE_NEW_THREAD);
-
- /** Terminates the thread without notifying or
- waiting for a cancelation point. */
- void terminate();
-
- /**
- Returns true if threadMain is currently executing. This will
- only be set when the thread is actually running and might not
- be set when start() returns. */
- bool running() const;
-
- /** True after start() has been called, even through the thread
- may have already completed(), or be currently running().*/
- bool started() const;
-
- /** Returns true if the thread has exited. */
- bool completed() const;
-
- /** Waits for the thread to finish executing. */
- void waitForCompletion();
-
- /** Returns thread name */
- inline const std::string& name() {
- return m_name;
- }
-};
-
-
-} // namespace G3D
-
-#endif //G3D_GTHREAD_H
diff --git a/externals/g3dlite/G3D/GUniqueID.h b/externals/g3dlite/G3D/GUniqueID.h
deleted file mode 100644
index c8b775c2e66..00000000000
--- a/externals/g3dlite/G3D/GUniqueID.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/**
- @file GUniqueID.h
- @author Morgan McGuire, http://graphics.cs.williams.edu
- */
-#ifndef G3D_GUNIQUEID_H
-#define G3D_GUNIQUEID_H
-
-#include "G3D/platform.h"
-#include "G3D/g3dmath.h"
-#include "G3D/Table.h"
-
-namespace G3D {
-
-/** Globally unique identifiers. The probability of two different
- programs generating the same value from UniqueID::create is
- vanishingly small.
-
- UniqueIDs optionally contain a 10-bit application specific tag
- that distinguishes their type.
-*/
-class GUniqueID {
-private:
-
- uint64 id;
-
-public:
-
- GUniqueID() : id(0) {}
-
- bool uninitialized() const {
- return id == 0;
- }
-
- uint16 tag() const {
- return id >> 54;
- }
-
- operator uint64() const {
- return id;
- }
-
- bool operator==(const GUniqueID& other) const {
- return id == other.id;
- }
-
- bool operator!=(const GUniqueID& other) const {
- return id != other.id;
- }
-
- void serialize(class BinaryOutput& b) const;
-
- void deserialize(class BinaryInput& b);
-
- void serialize(class TextOutput& t) const;
-
- void deserialize(class TextInput& t);
-
- /** Create a new ID */
- static GUniqueID create(uint16 tag = 0);
-};
-
-} // G3D
-
-/** For Table and Set */
-template<> struct HashTrait<class G3D::GUniqueID> {
- static size_t hashCode(G3D::GUniqueID id) { return (size_t)(G3D::uint64)id; }
-};
-
-#endif
diff --git a/externals/g3dlite/G3D/HashTrait.h b/externals/g3dlite/G3D/HashTrait.h
deleted file mode 100644
index ca35da48643..00000000000
--- a/externals/g3dlite/G3D/HashTrait.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/**
- @file HashTrait.h
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @created 2008-10-01
- @edited 2009-11-01
-
- Copyright 2000-2009, Morgan McGuire.
- All rights reserved.
- */
-
-#ifndef G3D_HashTrait_h
-#define G3D_HashTrait_h
-
-#include "G3D/platform.h"
-#include "G3D/Crypto.h"
-#include "G3D/g3dmath.h"
-#include "G3D/uint128.h"
-
-/** Must be specialized for custom types.
- @see G3D::Table for specialization requirements.
-*/
-template <typename T> struct HashTrait{};
-
-template <typename T> struct HashTrait<T*> {
- static size_t hashCode(const void* k) { return reinterpret_cast<size_t>(k); }
-};
-
-#if 0
-template <> struct HashTrait <int> {
- static size_t hashCode(int k) { return static_cast<size_t>(k); }
-};
-#endif
-
-template <> struct HashTrait <G3D::int16> {
- static size_t hashCode(G3D::int16 k) { return static_cast<size_t>(k); }
-};
-
-template <> struct HashTrait <G3D::uint16> {
- static size_t hashCode(G3D::uint16 k) { return static_cast<size_t>(k); }
-};
-
-//template <> struct HashTrait <int> {
-// static size_t hashCode(int k) { return static_cast<size_t>(k); }
-//};
-
-template <> struct HashTrait <G3D::int32> {
- static size_t hashCode(G3D::int32 k) { return static_cast<size_t>(k); }
-};
-
-template <> struct HashTrait <G3D::uint32> {
- static size_t hashCode(G3D::uint32 k) { return static_cast<size_t>(k); }
-};
-
-#if 0
-template <> struct HashTrait <long unsigned int> {
- static size_t hashCode(G3D::uint32 k) { return static_cast<size_t>(k); }
-};
-#endif
-
-template <> struct HashTrait <G3D::int64> {
- static size_t hashCode(G3D::int64 k) { return static_cast<size_t>(k); }
-};
-
-template <> struct HashTrait <G3D::uint64> {
- static size_t hashCode(G3D::uint64 k) { return static_cast<size_t>(k); }
-};
-
-template <> struct HashTrait <std::string> {
- static size_t hashCode(const std::string& k) { return static_cast<size_t>(G3D::Crypto::crc32(k.c_str(), k.size())); }
-};
-
-template <> struct HashTrait<G3D::uint128> {
- // Use the FNV-1 hash (http://isthe.com/chongo/tech/comp/fnv/#FNV-1).
- static size_t hashCode(G3D::uint128 key) {
- static const G3D::uint128 FNV_PRIME_128(1 << 24, 0x159);
- static const G3D::uint128 FNV_OFFSET_128(0xCF470AAC6CB293D2ULL, 0xF52F88BF32307F8FULL);
-
- G3D::uint128 hash = FNV_OFFSET_128;
- G3D::uint128 mask(0, 0xFF);
- for (int i = 0; i < 16; ++i) {
- hash *= FNV_PRIME_128;
- hash ^= (mask & key);
- key >>= 8;
- }
-
- G3D::uint64 foldedHash = hash.hi ^ hash.lo;
- return static_cast<size_t>((foldedHash >> 32) ^ (foldedHash & 0xFFFFFFFF));
- }
-};
-
-#endif
diff --git a/externals/g3dlite/G3D/Image1.h b/externals/g3dlite/G3D/Image1.h
deleted file mode 100644
index 711e83f2079..00000000000
--- a/externals/g3dlite/G3D/Image1.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/**
- @file Image1.h
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2007-01-31
- @edited 2007-01-31
-*/
-
-
-#ifndef G3D_IMAGE1_H
-#define G3D_IMAGE1_H
-
-#include "G3D/platform.h"
-#include "G3D/Map2D.h"
-#include "G3D/Color1.h"
-#include "G3D/GImage.h"
-
-namespace G3D {
-
-typedef ReferenceCountedPointer<class Image1> Image1Ref;
-
-/**
- Luminance image with 32-bit floating point storage.
-
- See also G3D::Image1uint8, G3D::GImage.
- */
-class Image1 : public Map2D<Color1, Color1> {
-public:
-
- typedef Image1 Type;
- typedef ReferenceCountedPointer<class Image1> Ref;
- typedef Color1 Storage;
- typedef Color1 Compute;
-
-protected:
-
- Image1(int w, int h, WrapMode wrap);
-
- void copyGImage(const class GImage& im);
- void copyArray(const Color1* src, int w, int h);
- void copyArray(const Color3* src, int w, int h);
- void copyArray(const Color4* src, int w, int h);
- void copyArray(const Color1uint8* src, int w, int h);
- void copyArray(const Color3uint8* src, int w, int h);
- void copyArray(const Color4uint8* src, int w, int h);
-
-public:
-
- const class ImageFormat* format() const;
-
- /** Creates an all-zero width x height image. */
- static Ref createEmpty(int width, int height, WrapMode wrap = WrapMode::ERROR);
-
- /** Creates a 0 x 0 image. */
- static Ref createEmpty(WrapMode wrap = WrapMode::ERROR);
-
- static Ref fromFile(const std::string& filename, WrapMode wrap = WrapMode::ERROR, GImage::Format fmt = GImage::AUTODETECT);
-
- static Ref fromArray(const class Color1uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
- static Ref fromArray(const class Color3uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
- static Ref fromArray(const class Color4uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
- static Ref fromArray(const class Color1* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
- static Ref fromArray(const class Color3* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
- static Ref fromArray(const class Color4* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
-
- static Ref fromImage1uint8(const ReferenceCountedPointer<class Image1uint8>& im);
-
- static Ref fromGImage(const class GImage& im, WrapMode wrap = WrapMode::ERROR);
-
- /** Loads from any of the file formats supported by G3D::GImage. If there is an alpha channel on the input,
- it is stripped. */
- void load(const std::string& filename, GImage::Format fmt = GImage::AUTODETECT);
-
- /** Saves in any of the formats supported by G3D::GImage. */
- void save(const std::string& filename, GImage::Format fmt = GImage::AUTODETECT);
-};
-
-} // G3D
-
-#endif
diff --git a/externals/g3dlite/G3D/Image1uint8.h b/externals/g3dlite/G3D/Image1uint8.h
deleted file mode 100644
index f32e022e92a..00000000000
--- a/externals/g3dlite/G3D/Image1uint8.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/**
- @file Image1uint8.h
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2007-01-31
- @edited 2007-01-31
-*/
-
-#ifndef G3D_IMAGE1UINT8_H
-#define G3D_IMAGE1UINT8_H
-
-#include "G3D/platform.h"
-#include "G3D/Map2D.h"
-#include "G3D/Color1uint8.h"
-#include "G3D/Color1.h"
-#include "G3D/GImage.h"
-
-namespace G3D {
-
-typedef ReferenceCountedPointer<class Image1uint8> Image1uint8Ref;
-
-/**
- Compact storage for luminance 8-bit images.
-
- See also G3D::Image3, G3D::GImage
- */
-class Image1uint8 : public Map2D<Color1uint8, Color1> {
-public:
-
- typedef Image1uint8 Type;
- typedef Image1uint8Ref Ref;
-
-protected:
-
- Image1uint8(int w, int h, WrapMode wrap);
-
- void copyGImage(const class GImage& im);
- void copyArray(const Color1* src, int w, int h);
- void copyArray(const Color3* src, int w, int h);
- void copyArray(const Color4* src, int w, int h);
- void copyArray(const Color1uint8* src, int w, int h);
- void copyArray(const Color3uint8* src, int w, int h);
- void copyArray(const Color4uint8* src, int w, int h);
-
-public:
-
- const class ImageFormat* format() const;
-
- /** Creates an all-zero width x height image. */
- static Ref createEmpty(int width, int height, WrapMode wrap = WrapMode::ERROR);
-
- /** Creates a 0 x 0 image. */
- static Ref createEmpty(WrapMode wrap = WrapMode::ERROR);
-
- static Ref fromFile(const std::string& filename, WrapMode wrap = WrapMode::ERROR, GImage::Format fmt = GImage::AUTODETECT);
-
- static Ref fromGImage(const class GImage& im, WrapMode wrap = WrapMode::ERROR);
-
- static Ref fromArray(const class Color1uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
- static Ref fromArray(const class Color3uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
- static Ref fromArray(const class Color4uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
- static Ref fromArray(const class Color1* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
- static Ref fromArray(const class Color3* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
- static Ref fromArray(const class Color4* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
-
- static Ref fromImage1(const ReferenceCountedPointer<class Image1>& im);
- static Ref fromImage3uint8(const ReferenceCountedPointer<class Image3uint8>& im);
-
- /** Loads from any of the file formats supported by G3D::GImage. If there is an alpha channel on the input,
- it is stripped. */
- void load(const std::string& filename, GImage::Format fmt = GImage::AUTODETECT);
-
- /** Saves in any of the formats supported by G3D::GImage. */
- void save(const std::string& filename, GImage::Format fmt = GImage::AUTODETECT);
-};
-
-} // G3D
-
-#endif
diff --git a/externals/g3dlite/G3D/Image3.h b/externals/g3dlite/G3D/Image3.h
deleted file mode 100644
index 13cb8fa7faf..00000000000
--- a/externals/g3dlite/G3D/Image3.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/**
- @file Image3.h
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2007-01-31
- @edited 2007-01-31
-*/
-
-
-#ifndef G3D_IMAGE3_H
-#define G3D_IMAGE3_H
-
-#include "G3D/platform.h"
-#include "G3D/Map2D.h"
-#include "G3D/Color3.h"
-#include "G3D/GImage.h"
-
-namespace G3D {
-
-typedef ReferenceCountedPointer<class Image3> Image3Ref;
-
-/**
- RGB image with 32-bit floating point storage for each channel.
-
- See also G3D::Image3uint8, G3D::GImage.
- */
-class Image3 : public Map2D<Color3, Color3> {
-public:
-
- typedef Image3 Type;
- typedef ReferenceCountedPointer<class Image3> Ref;
- typedef Color3 Storage;
- typedef Color3 Compute;
-
-protected:
-
- Image3(int w, int h, WrapMode wrap);
-
- void copyGImage(const class GImage& im);
- void copyArray(const Color1* src, int w, int h);
- void copyArray(const Color3* src, int w, int h);
- void copyArray(const Color4* src, int w, int h);
- void copyArray(const Color1uint8* src, int w, int h);
- void copyArray(const Color3uint8* src, int w, int h);
- void copyArray(const Color4uint8* src, int w, int h);
-
-public:
-
- const class ImageFormat* format() const;
-
- /** Creates an all-zero width x height image. */
- static Ref createEmpty(int width, int height, WrapMode wrap = WrapMode::ERROR);
-
- /** Creates a 0 x 0 image. */
- static Ref createEmpty(WrapMode wrap = WrapMode::ERROR);
-
- static Ref fromFile(const std::string& filename, WrapMode wrap = WrapMode::ERROR, GImage::Format fmt = GImage::AUTODETECT);
-
- static Ref fromArray(const class Color1uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
- static Ref fromArray(const class Color3uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
- static Ref fromArray(const class Color4uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
- static Ref fromArray(const class Color1* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
- static Ref fromArray(const class Color3* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
- static Ref fromArray(const class Color4* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
-
- static Ref fromImage3uint8(const ReferenceCountedPointer<class Image3uint8>& im);
-
- static Ref fromGImage(const class GImage& im, WrapMode wrap = WrapMode::ERROR);
-
- /** Loads from any of the file formats supported by G3D::GImage. If there is an alpha channel on the input,
- it is stripped. */
- void load(const std::string& filename, GImage::Format fmt = GImage::AUTODETECT);
-
- /** Saves in any of the formats supported by G3D::GImage. */
- void save(const std::string& filename, GImage::Format fmt = GImage::AUTODETECT);
-};
-
-} // G3D
-
-#endif
diff --git a/externals/g3dlite/G3D/Image3uint8.h b/externals/g3dlite/G3D/Image3uint8.h
deleted file mode 100644
index d4fdbc169ca..00000000000
--- a/externals/g3dlite/G3D/Image3uint8.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/**
- @file Image3uint8.h
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2007-01-31
- @edited 2007-01-31
-*/
-
-#ifndef G3D_IMAGE3UINT8_H
-#define G3D_IMAGE3UINT8_H
-
-#include "G3D/platform.h"
-#include "G3D/Map2D.h"
-#include "G3D/Color3uint8.h"
-#include "G3D/Color3.h"
-#include "G3D/GImage.h"
-
-namespace G3D {
-
-typedef ReferenceCountedPointer<class Image3uint8> Image3uint8Ref;
-
-/**
- Compact storage for RGB 8-bit per channel images.
-
- See also G3D::Image3, G3D::GImage
- */
-class Image3uint8 : public Map2D<Color3uint8, Color3> {
-public:
-
- typedef Image3uint8 Type;
- typedef Image3uint8Ref Ref;
-
-protected:
-
- Image3uint8(int w, int h, WrapMode wrap);
-
- void copyGImage(const class GImage& im);
- void copyArray(const Color1* src, int w, int h);
- void copyArray(const Color3* src, int w, int h);
- void copyArray(const Color4* src, int w, int h);
- void copyArray(const Color1uint8* src, int w, int h);
- void copyArray(const Color3uint8* src, int w, int h);
- void copyArray(const Color4uint8* src, int w, int h);
-
-public:
-
- const class ImageFormat* format() const;
-
- /** Creates an all-zero width x height image. */
- static Ref createEmpty(int width, int height, WrapMode wrap = WrapMode::ERROR);
-
-
- /** Creates a 0 x 0 image. */
- static Ref createEmpty(WrapMode wrap = WrapMode::ERROR);
-
-
- static Ref fromFile(const std::string& filename, WrapMode wrap = WrapMode::ERROR, GImage::Format fmt = GImage::AUTODETECT);
-
- static Ref fromGImage(const class GImage& im, WrapMode wrap = WrapMode::ERROR);
-
- static Ref fromArray(const class Color1uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
- static Ref fromArray(const class Color3uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
- static Ref fromArray(const class Color4uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
- static Ref fromArray(const class Color1* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
- static Ref fromArray(const class Color3* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
- static Ref fromArray(const class Color4* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
-
- static Ref fromImage3(const ReferenceCountedPointer<class Image3>& im);
- static Ref fromImage1uint8(const ReferenceCountedPointer<class Image1uint8>& im);
-
- /** Loads from any of the file formats supported by G3D::GImage. If there is an alpha channel on the input,
- it is stripped. */
- void load(const std::string& filename, GImage::Format fmt = GImage::AUTODETECT);
-
- /** Saves in any of the formats supported by G3D::GImage. */
- void save(const std::string& filename, GImage::Format fmt = GImage::AUTODETECT);
-
- /** Extracts color channel 0 <= c <= 2 and returns it as a new monochrome image. */
- ReferenceCountedPointer<class Image1uint8> getChannel(int c) const;
-};
-
-} // G3D
-
-#endif
diff --git a/externals/g3dlite/G3D/Image4.h b/externals/g3dlite/G3D/Image4.h
deleted file mode 100644
index 21d7f1e79b1..00000000000
--- a/externals/g3dlite/G3D/Image4.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/**
- @file Image4.h
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2007-01-31
- @edited 2007-01-31
-*/
-
-
-#ifndef G3D_IMAGE4_H
-#define G3D_IMAGE4_H
-
-#include "G3D/platform.h"
-#include "G3D/Map2D.h"
-#include "G3D/Color4.h"
-#include "G3D/GImage.h"
-
-namespace G3D {
-
-typedef ReferenceCountedPointer<class Image4> Image4Ref;
-
-/**
- RGBA image with 32-bit floating point storage for each channel.
-
- Whenever a method needs to convert from RGB to RGBA, A=1 is assumed.
-
- Bilinear interpolation on Image4 is about 8x faster than on
- Image4uint8 due to the large cost of converting int->float on modern
- machines.
-
- @sa G3D::Image4uint8, G3D::GImage.
- */
-class Image4 : public Map2D<Color4, Color4> {
-public:
-
- typedef Image4 Type;
- typedef ReferenceCountedPointer<class Image4> Ref;
- typedef Color4 Storage;
- typedef Color4 Compute;
-
-protected:
-
- Image4(int w, int h, WrapMode wrap);
-
- void copyGImage(const class GImage& im);
- void copyArray(const Color1* src, int w, int h);
- void copyArray(const Color3* src, int w, int h);
- void copyArray(const Color4* src, int w, int h);
- void copyArray(const Color1uint8* src, int w, int h);
- void copyArray(const Color3uint8* src, int w, int h);
- void copyArray(const Color4uint8* src, int w, int h);
-
-public:
-
- const class ImageFormat* format() const;
-
- /** Creates an all-zero width x height image. */
- static Ref createEmpty(int width, int height, WrapMode wrap = WrapMode::ERROR);
-
- /** Creates a 0 x 0 image. */
- static Ref createEmpty(WrapMode wrap = WrapMode::ERROR);
-
- static Ref fromFile(const std::string& filename, WrapMode wrap = WrapMode::ERROR, GImage::Format fmt = GImage::AUTODETECT);
-
- static Ref fromArray(const class Color1uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
- static Ref fromArray(const class Color3uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
- static Ref fromArray(const class Color4uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
- static Ref fromArray(const class Color1* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
- static Ref fromArray(const class Color3* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
- static Ref fromArray(const class Color4* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
-
- static Ref fromImage4uint8(const ReferenceCountedPointer<class Image4uint8>& im);
-
- static Ref fromGImage(const class GImage& im, WrapMode wrap = WrapMode::ERROR);
-
- /** Loads from any of the file formats supported by G3D::GImage. */
- void load(const std::string& filename, GImage::Format fmt = GImage::AUTODETECT);
-
- /** Saves in any of the formats supported by G3D::GImage. */
- void save(const std::string& filename, GImage::Format fmt = GImage::AUTODETECT);
-};
-
-} // G3D
-
-#endif
diff --git a/externals/g3dlite/G3D/Image4uint8.h b/externals/g3dlite/G3D/Image4uint8.h
deleted file mode 100644
index 46df6b490b4..00000000000
--- a/externals/g3dlite/G3D/Image4uint8.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/**
- @file Image4uint8.h
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2007-01-31
- @edited 2007-01-31
-*/
-
-#ifndef G3D_IMAGE4UINT8_H
-#define G3D_IMAGE4UINT8_H
-
-#include "G3D/platform.h"
-#include "G3D/Map2D.h"
-#include "G3D/Color4uint8.h"
-#include "G3D/Color4.h"
-#include "G3D/GImage.h"
-#include "G3D/Image1uint8.h"
-
-namespace G3D {
-
-typedef ReferenceCountedPointer<class Image4uint8> Image4uint8Ref;
-
-/**
- Compact storage for RGBA 8-bit per channel images.
-
- See also G3D::Image4, G3D::GImage
- */
-class Image4uint8 : public Map2D<Color4uint8, Color4> {
-public:
-
- typedef Image4uint8 Type;
- typedef Image4uint8Ref Ref;
-
-protected:
-
- Image4uint8(int w, int h, WrapMode wrap);
-
- void copyGImage(const class GImage& im);
- void copyArray(const Color1* src, int w, int h);
- void copyArray(const Color3* src, int w, int h);
- void copyArray(const Color4* src, int w, int h);
- void copyArray(const Color1uint8* src, int w, int h);
- void copyArray(const Color3uint8* src, int w, int h);
- void copyArray(const Color4uint8* src, int w, int h);
-
-public:
-
- const class ImageFormat* format() const;
-
- /** Creates an all-zero width x height image. */
- static Ref createEmpty(int width, int height, WrapMode wrap = WrapMode::ERROR);
-
-
- /** Creates a 0 x 0 image. */
- static Ref createEmpty(WrapMode wrap = WrapMode::ERROR);
-
-
- static Ref fromFile(const std::string& filename, WrapMode wrap = WrapMode::ERROR, GImage::Format fmt = GImage::AUTODETECT);
-
- static Ref fromGImage(const class GImage& im, WrapMode wrap = WrapMode::ERROR);
-
- static Ref fromArray(const class Color1uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
- static Ref fromArray(const class Color3uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
- static Ref fromArray(const class Color4uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
- static Ref fromArray(const class Color1* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
- static Ref fromArray(const class Color3* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
- static Ref fromArray(const class Color4* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
-
- static Ref fromImage4(const ReferenceCountedPointer<class Image4>& im);
-
- /** Loads from any of the file formats supported by G3D::GImage. If there is an alpha channel on the input,
- it is stripped. */
- void load(const std::string& filename, GImage::Format fmt = GImage::AUTODETECT);
-
- /** Saves in any of the formats supported by G3D::GImage. */
- void save(const std::string& filename, GImage::Format fmt = GImage::AUTODETECT);
-
- /** Extracts color channel 0 <= c <= 3 and returns it as a new monochrome image. */
- ReferenceCountedPointer<class Image1uint8> getChannel(int c) const;
-};
-
-} // G3D
-
-#endif
diff --git a/externals/g3dlite/G3D/ImageFormat.h b/externals/g3dlite/G3D/ImageFormat.h
deleted file mode 100644
index 7f098322d26..00000000000
--- a/externals/g3dlite/G3D/ImageFormat.h
+++ /dev/null
@@ -1,419 +0,0 @@
-/**
- @file ImageFormat.h
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2003-05-23
- @edited 2010-01-01
-*/
-
-#ifndef GLG3D_ImageFormat_H
-#define GLG3D_ImageFormat_H
-
-#include "G3D/platform.h"
-#include "G3D/Table.h"
-#include "G3D/enumclass.h"
-
-namespace G3D {
-
-/** Information about common image formats.
- Don't construct these; use the methods provided.
-
- For most formats, the number indicates the number of bits per channel and a suffix of "F" indicates
- floating point. This does not hold for the YUV and DXT formats.*/
-class ImageFormat {
-public:
-
- // Must update ImageFormat::name() when this enum changes.
- enum Code {
- CODE_NONE = -1,
- CODE_L8,
- CODE_L16,
- CODE_L16F,
- CODE_L32F,
-
- CODE_A8,
- CODE_A16,
- CODE_A16F,
- CODE_A32F,
-
- CODE_LA4,
- CODE_LA8,
- CODE_LA16,
- CODE_LA16F,
- CODE_LA32F,
-
- CODE_RGB5,
- CODE_RGB5A1,
- CODE_RGB8,
- CODE_RGB10,
- CODE_RGB10A2,
- CODE_RGB16,
- CODE_RGB16F,
- CODE_RGB32F,
- CODE_R11G11B10F,
- CODE_RGB9E5F,
-
- CODE_RGB8I,
- CODE_RGB8UI,
-
- CODE_ARGB8,
- CODE_BGR8,
-
- CODE_RG8,
- CODE_RG8I,
- CODE_RG8UI,
-
- CODE_RGBA8,
- CODE_RGBA16,
- CODE_RGBA16F,
- CODE_RGBA32F,
-
- CODE_RGBA32UI,
-
- CODE_BAYER_RGGB8,
- CODE_BAYER_GRBG8,
- CODE_BAYER_GBRG8,
- CODE_BAYER_BGGR8,
- CODE_BAYER_RGGB32F,
- CODE_BAYER_GRBG32F,
- CODE_BAYER_GBRG32F,
- CODE_BAYER_BGGR32F,
-
- CODE_HSV8,
- CODE_HSV32F,
-
- CODE_YUV420_PLANAR,
- CODE_YUV422,
- CODE_YUV444,
-
- CODE_RGB_DXT1,
- CODE_RGBA_DXT1,
- CODE_RGBA_DXT3,
- CODE_RGBA_DXT5,
-
- CODE_SRGB8,
- CODE_SRGBA8,
-
- CODE_SL8,
- CODE_SLA8,
-
- CODE_SRGB_DXT1,
- CODE_SRGBA_DXT1,
- CODE_SRGBA_DXT3,
- CODE_SRGBA_DXT5,
-
- CODE_DEPTH16,
- CODE_DEPTH24,
- CODE_DEPTH32,
- CODE_DEPTH32F,
-
- CODE_STENCIL1,
- CODE_STENCIL4,
- CODE_STENCIL8,
- CODE_STENCIL16,
-
- CODE_DEPTH24_STENCIL8,
-
- CODE_NUM
- };
-
- enum ColorSpace {
- COLOR_SPACE_NONE,
- COLOR_SPACE_RGB,
- COLOR_SPACE_HSV,
- COLOR_SPACE_YUV,
- COLOR_SPACE_SRGB
- };
-
- enum BayerPattern {
- BAYER_PATTERN_NONE,
- BAYER_PATTERN_RGGB,
- BAYER_PATTERN_GRBG,
- BAYER_PATTERN_GBRG,
- BAYER_PATTERN_BGGR
- };
-
- /** Number of channels (1 for a depth texture). */
- int numComponents;
- bool compressed;
-
- /** Useful for serializing. */
- Code code;
-
- ColorSpace colorSpace;
-
- /** If this is a Bayer format, what is the pattern. */
- BayerPattern bayerPattern;
-
- /** The OpenGL format equivalent to this one, e.g, GL_RGB8 Zero if there is no equivalent. This is actually a GLenum */
- int openGLFormat;
-
- /** The OpenGL base format equivalent to this one (e.g., GL_RGB, GL_ALPHA). Zero if there is no equivalent. */
- int openGLBaseFormat;
-
- int luminanceBits;
-
- /** Number of bits per pixel storage for alpha values; Zero for compressed textures and non-RGB. */
- int alphaBits;
-
- /** Number of bits per pixel storage for red values; Zero for compressed textures and non-RGB. */
- int redBits;
-
- /** Number of bits per pixel storage for green values; Zero for compressed textures and non-RGB. */
- int greenBits;
-
- /** Number of bits per pixel storage for blue values; Zero for compressed textures and non-RGB. */
- int blueBits;
-
- /** Number of bits per pixel */
- int stencilBits;
-
- /** Number of depth bits (for depth textures; e.g. shadow maps) */
- int depthBits;
-
- /** Amount of CPU memory per pixel when packed into an array, discounting any end-of-row padding. */
- int cpuBitsPerPixel;
-
- /** Amount of CPU memory per pixel when packed into an array, discounting any end-of-row padding.
- @deprecated Use cpuBitsPerPixel*/
- int packedBitsPerTexel;
-
- /**
- Amount of GPU memory per pixel on most graphics cards, for formats supported by OpenGL. This is
- only an estimate--the actual amount of memory may be different on your actual card.
-
- This may be greater than the sum of the per-channel bits
- because graphics cards need to pad to the nearest 1, 2, or
- 4 bytes.
- */
- int openGLBitsPerPixel;
-
- /** @deprecated Use openGLBitsPerPixel */
- int hardwareBitsPerTexel;
-
- /** The OpenGL bytes (type) format of the data buffer used with this texture format, e.g., GL_UNSIGNED_BYTE */
- int openGLDataFormat;
-
- /** True if there is no alpha channel for this texture. */
- bool opaque;
-
- /** True if the bit depths specified are for float formats. */
- bool floatingPoint;
-
- /** Human readable name of this format.*/
- const std::string& name() const;
-
- /** Takes the same values that name() returns */
- static const ImageFormat* fromString(const std::string& s);
-
-private:
-
- ImageFormat
- (int numComponents,
- bool compressed,
- int glFormat,
- int glBaseFormat,
- int luminanceBits,
- int alphaBits,
- int redBits,
- int greenBits,
- int blueBits,
- int depthBits,
- int stencilBits,
- int hardwareBitsPerTexel,
- int packedBitsPerTexel,
- int glDataFormat,
- bool opaque,
- bool floatingPoint,
- Code code,
- ColorSpace colorSpace,
- BayerPattern bayerPattern = BAYER_PATTERN_NONE);
-
-public:
-
- static const ImageFormat* L8();
-
- static const ImageFormat* L16();
-
- static const ImageFormat* L16F();
-
- static const ImageFormat* L32F();
-
- static const ImageFormat* A8();
-
- static const ImageFormat* A16();
-
- static const ImageFormat* A16F();
-
- static const ImageFormat* A32F();
-
- static const ImageFormat* LA4();
-
- static const ImageFormat* LA8();
-
- static const ImageFormat* LA16();
-
- static const ImageFormat* LA16F();
-
- static const ImageFormat* LA32F();
-
- static const ImageFormat* BGR8();
-
- static const ImageFormat* RG8();
- static const ImageFormat* RG8I();
- static const ImageFormat* RG8UI();
-
- static const ImageFormat* RGB5();
-
- static const ImageFormat* RGB5A1();
-
- static const ImageFormat* RGB8();
-
- static const ImageFormat* RGB10();
-
- static const ImageFormat* RGB10A2();
-
- static const ImageFormat* RGB16();
-
- static const ImageFormat* RGB16F();
-
- static const ImageFormat* RGB32F();
-
- static const ImageFormat* RGBA8();
-
- static const ImageFormat* RGBA16();
-
- static const ImageFormat* RGBA16F();
-
- static const ImageFormat* RGBA32F();
-
- static const ImageFormat* RGBA32UI();
-
- static const ImageFormat* R11G11B10F();
-
- static const ImageFormat* RGB9E5F();
-
- static const ImageFormat* RGB8I();
-
- static const ImageFormat* RGB8UI();
-
- static const ImageFormat* RGB_DXT1();
-
- static const ImageFormat* RGBA_DXT1();
-
- static const ImageFormat* RGBA_DXT3();
-
- static const ImageFormat* RGBA_DXT5();
-
- static const ImageFormat* SRGB8();
-
- static const ImageFormat* SRGBA8();
-
- static const ImageFormat* SL8();
-
- static const ImageFormat* SLA8();
-
- static const ImageFormat* SRGB_DXT1();
-
- static const ImageFormat* SRGBA_DXT1();
-
- static const ImageFormat* SRGBA_DXT3();
-
- static const ImageFormat* SRGBA_DXT5();
-
- static const ImageFormat* DEPTH16();
-
- static const ImageFormat* DEPTH24();
-
- static const ImageFormat* DEPTH32();
-
- static const ImageFormat* DEPTH32F();
-
- static const ImageFormat* STENCIL1();
-
- static const ImageFormat* STENCIL4();
-
- static const ImageFormat* STENCIL8();
-
- static const ImageFormat* STENCIL16();
-
- static const ImageFormat* DEPTH24_STENCIL8();
-
- static const ImageFormat* YUV420_PLANAR();
-
- static const ImageFormat* YUV422();
-
- static const ImageFormat* YUV444();
-
- /**
- NULL pointer; indicates that the G3D::Texture class should choose
- either RGBA8 or RGB8 depending on the presence of an alpha channel
- in the input.
- */
- static const ImageFormat* AUTO() { return NULL; }
-
- /** Returns DEPTH16, DEPTH24, or DEPTH32 according to the bits
- specified. You can use "glGetInteger(GL_DEPTH_BITS)" to match
- the screen's format.*/
- static const ImageFormat* depth(int depthBits = 24);
-
- /** Returns STENCIL1, STENCIL4, STENCIL8 or STENCIL16 according to the bits
- specified. You can use "glGetInteger(GL_STENCIL_BITS)" to match
- the screen's format.*/
- static const ImageFormat* stencil(int bits = 8);
-
- /** Returns the matching ImageFormat* identified by the Code. May return NULL
- if this format's code is reserved but not yet implemented by G3D. */
- static const ImageFormat* fromCode(ImageFormat::Code code);
-
-
-
- /** For use with ImageFormat::convert. */
- class BayerAlgorithm {
- public:
- enum Value {
- NEAREST,
- BILINEAR,
- MHC,
- HIGH_QUALITY = MHC
- };
- private:
-
- Value value;
-
- public:
-
- G3D_DECLARE_ENUM_CLASS_METHODS(BayerAlgorithm);
- };
-
- /** Converts between arbitrary formats on the CPU. Not all format conversions are supported or directly supported.
- Formats without direct conversions will attempt to convert through RGBA first.
-
- A conversion routine might only support source or destination padding or y inversion or none.
- If support is needed and not available in any of the direct conversion routines, then no conversion is done.
-
- YUV422 expects data in YUY2 format (Y, U, Y2, v). Most YUV formats require width and heights that are multiples of 2.
-
- Returns true if a conversion was available, false if none occurred.
- */
- static bool convert(const Array<const void*>& srcBytes, int srcWidth, int srcHeight, const ImageFormat* srcFormat, int srcRowPadBits,
- const Array<void*>& dstBytes, const ImageFormat* dstFormat, int dstRowPadBits,
- bool invertY = false, BayerAlgorithm bayerAlg = BayerAlgorithm::HIGH_QUALITY);
-
- /* Checks if a conversion between two formats is available. */
- static bool conversionAvailable(const ImageFormat* srcFormat, int srcRowPadBits, const ImageFormat* dstFormat, int dstRowPadBits, bool invertY = false);
-};
-
-typedef ImageFormat TextureFormat;
-
-}
-
-template <>
-struct HashTrait<const G3D::ImageFormat*> {
- static size_t hashCode(const G3D::ImageFormat* key) { return reinterpret_cast<size_t>(key); }
-};
-
-
-
-#endif
diff --git a/externals/g3dlite/G3D/Intersect.h b/externals/g3dlite/G3D/Intersect.h
deleted file mode 100644
index 4a3c8fb4540..00000000000
--- a/externals/g3dlite/G3D/Intersect.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/**
- @file Intersect.h
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2009-06-29
- @edited 2009-06-29
-
- Copyright 2000-2009, Morgan McGuire.
- All rights reserved.
-
- From the G3D Innovation Engine
- http://g3d.sf.net
- */
-#ifndef G3D_Intersect
-#define G3D_Intersect
-
-#include "G3D/platform.h"
-#include "G3D/Ray.h"
-#include "G3D/AABox.h"
-
-namespace G3D {
-
-/**
- @beta
- */
-class Intersect {
-public:
-
- /** \brief Returns true if the intersection of the ray and the solid box is non-empty.
-
- \cite "Fast Ray / Axis-Aligned Bounding Box Overlap Tests using Ray Slopes"
- by Martin Eisemann, Thorsten Grosch, Stefan Müller and Marcus Magnor
- Computer Graphics Lab, TU Braunschweig, Germany and
- University of Koblenz-Landau, Germany
- */
- static bool __fastcall rayAABox(const Ray& ray, const AABox& box);
-
- /** \brief Returns true if the intersection of the ray and the solid box is non-empty.
-
- \param time If there is an intersection, set to the time to that intersection. If the ray origin is inside the box,
- this is a negative value indicating the distance backwards from the ray origin to the first intersection.
- \a time is not set if there is no intersection.
-
- \cite Slope-Mul method from "Fast Ray / Axis-Aligned Bounding Box Overlap Tests using Ray Slopes"
- by Martin Eisemann, Thorsten Grosch, Stefan Müller and Marcus Magnor
- Computer Graphics Lab, TU Braunschweig, Germany and
- University of Koblenz-Landau, Germany
- */
- static bool __fastcall rayAABox(const Ray& ray, const AABox& box, float& time);
-};
-
-}
-
-#endif
diff --git a/externals/g3dlite/G3D/KDTree.h b/externals/g3dlite/G3D/KDTree.h
deleted file mode 100644
index 4785ef2baea..00000000000
--- a/externals/g3dlite/G3D/KDTree.h
+++ /dev/null
@@ -1,1667 +0,0 @@
-/**
- @file KDTree.h
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2004-01-11
- @edited 2009-12-28
-
- Copyright 2000-2009, Morgan McGuire.
- All rights reserved.
- */
-
-#ifndef G3D_KDTREE_H
-#define G3D_KDTREE_H
-
-#include "G3D/platform.h"
-#include "G3D/Array.h"
-#include "G3D/Table.h"
-#include "G3D/Vector2.h"
-#include "G3D/Vector3.h"
-#include "G3D/Vector4.h"
-#include "G3D/AABox.h"
-#include "G3D/Sphere.h"
-#include "G3D/Box.h"
-#include "G3D/Triangle.h"
-#include "G3D/Ray.h"
-#include "G3D/GCamera.h"
-#include "G3D/BinaryInput.h"
-#include "G3D/BinaryOutput.h"
-#include "G3D/CollisionDetection.h"
-#include "G3D/GCamera.h"
-#include "G3D/BoundsTrait.h"
-#include <algorithm>
-
-// If defined, in debug mode the tree is checked for consistency
-// as a way of detecting corruption due to implementation bugs
-// #define VERIFY_TREE
-
-template<> struct BoundsTrait<class G3D::Vector2> {
- static void getBounds(const G3D::Vector2& v, G3D::AABox& out) { out = G3D::AABox(G3D::Vector3(v, 0)); }
-};
-
-template<> struct BoundsTrait<class G3D::Vector3> {
- static void getBounds(const G3D::Vector3& v, G3D::AABox& out) { out = G3D::AABox(v); }
-};
-
-template<> struct BoundsTrait<class G3D::Vector4> {
- static void getBounds(const G3D::Vector4& v, G3D::AABox& out) { out = G3D::AABox(v.xyz()); }
-};
-
-template<> struct BoundsTrait<class G3D::AABox> {
- static void getBounds(const G3D::AABox& v, G3D::AABox& out) { out = v; }
-};
-
-template<> struct BoundsTrait<class G3D::Sphere> {
- static void getBounds(const G3D::Sphere& s, G3D::AABox& out) { s.getBounds(out); }
-};
-
-template<> struct BoundsTrait<class G3D::Box> {
- static void getBounds(const G3D::Box& b, G3D::AABox& out) { b.getBounds(out); }
-};
-
-template<> struct BoundsTrait<class G3D::Vector2*> {
- static void getBounds(const G3D::Vector2*& v, G3D::AABox& out) { out = G3D::AABox(G3D::Vector3(*v, 0)); }
-};
-
-template<> struct BoundsTrait<class G3D::Vector3*> {
- static void getBounds(const G3D::Vector3*& v, G3D::AABox& out) { out = G3D::AABox(*v); }
-};
-
-template<> struct BoundsTrait<class G3D::Vector4*> {
- static void getBounds(const G3D::Vector4*& v, G3D::AABox& out) { out = G3D::AABox(v->xyz()); }
-};
-
-template<> struct BoundsTrait<class G3D::AABox*> {
- static void getBounds(const G3D::AABox*& v, G3D::AABox& out) { out = *v; }
-};
-
-template<> struct BoundsTrait<class G3D::Sphere*> {
- static void getBounds(const G3D::Sphere*& s, G3D::AABox& out) { s->getBounds(out); }
-};
-
-template<> struct BoundsTrait<class G3D::Box*> {
- static void getBounds(const G3D::Box*& b, G3D::AABox& out) { b->getBounds(out); }
-};
-
-
-template<> struct BoundsTrait<class G3D::Triangle*> {
- static void getBounds(const G3D::Triangle*& t, G3D::AABox& out) { t->getBounds(out); }
-};
-
-namespace G3D {
- namespace _internal {
-
- /**
- Wraps a pointer value so that it can be treated as the instance itself;
- convenient for inserting pointers into a Table but using the
- object equality instead of pointer equality.
- */
- template<class Type>
- class Indirector {
- public:
- Type* handle;
-
- inline Indirector(Type* h) : handle(h) {}
-
- inline Indirector() : handle(NULL) {}
-
- /** Returns true iff the values referenced by the handles are equivalent. */
- inline bool operator==(const Indirector& m) const {
- return *handle == *(m.handle);
- }
-
- inline bool operator==(const Type& m) const {
- return *handle == m;
- }
-
- inline size_t hashCode() const {
- return handle->hashCode();
- }
- };
- } // namespace internal
-} // namespace G3D
-
-template <class Handle> struct HashTrait<typename G3D::_internal::Indirector<Handle> > {
- static size_t hashCode(const G3D::_internal::Indirector<Handle>& key) { return key.hashCode(); }
-};
-
-namespace G3D {
-
-/**
- A set that supports spatial queries using a KD tree (axis-aligned
- BSP tree) for speed.
-
- KDTree allows you to quickly find objects in 3D that lie within
- a box or along a ray. For large sets of objects it is much faster
- than testing each object for a collision.
-
- KDTree is as powerful as but more general than a Quad Tree, Oct
- Tree, or regular KD tree that cycles through axes, but less general than an unconstrained BSP tree
- (which is much slower to create).
-
- Internally, objects
- are arranged into a tree according to their
- axis-aligned bounds. This increases the cost of insertion to
- O(log n) but allows fast overlap queries.
-
- <B>Template Parameters</B>
- <DT>The template parameter <I>T</I> must be one for which
- the following functions are all overloaded:
-
- <pre>
- T::T(); // public constructor of no arguments
- template <> struct HashTrait<T> { static size_t hashCode(int key); };
- template<> struct BoundsTrait<T> { static void getBounds(const T& obj, G3D::AABox& out); };
- </pre>
-
- G3D provides these for common classes like G3D::Vector3 and G3D::Sphere.
- If you use a custom class, or a pointer to a custom class, you will need
- to define those functions.
-
- <B>Moving %Set Members</B>
- <DT>It is important that objects do not move without updating the
- KDTree. If the axis-aligned bounds of an object are about
- to change, KDTree::remove it before they change and
- KDTree::insert it again afterward. For objects
- where the hashCode and == operator are invariant with respect
- to the 3D position,
- you can use the KDTree::update method as a shortcut to
- insert/remove an object in one step after it has moved.
-
-
- Note: Do not mutate any value once it has been inserted into KDTree. Values
- are copied interally. All KDTree iterators convert to pointers to constant
- values to reinforce this.
-
- If you want to mutate the objects you intend to store in a KDTree
- simply insert <I>pointers</I> to your objects instead of the objects
- themselves, and ensure that the above operations are defined. (And
- actually, because values are copied, if your values are large you may
- want to insert pointers anyway, to save space and make the balance
- operation faster.)
-
- <B>Dimensions</B>
- Although designed as a 3D-data structure, you can use the KDTree
- for data distributed along 2 or 1 axes by simply returning bounds
- that are always zero along one or more dimensions.
-
-*/
-template< class T,
- class BoundsFunc = BoundsTrait<T>,
- class HashFunc = HashTrait<T>,
- class EqualsFunc = EqualsTrait<T> >
-class KDTree {
-protected:
-#define TreeType KDTree<T, BoundsFunc, HashFunc, EqualsFunc>
-
- /** Wrapper for a value that includes a cache of its bounds.
- Except for the test value used in a set-query operation, there
- is only ever one instance of the handle associated with any
- value and the memberTable and Nodes maintain pointers to that
- heap-allocated value.
- */
- class Handle {
- public:
- /** The bounds of each object are constrained to AABox::large */
- AABox bounds;
-
- /** Center of bounds. We cache this value to avoid recomputing it
- during the median sort, and because MSVC 6 std::sort goes into
- an infinite loop if we compute the midpoint on the fly (possibly
- a floating point roundoff issue, where B<A and A<B both are true).*/
- Vector3 center;
-
- T value;
-
- Handle() {}
-
- inline Handle(const T& v) : value(v) {
- BoundsFunc::getBounds(v, bounds);
- bounds = bounds.intersect(AABox::large());
- center = bounds.center();
- }
-
- inline bool operator==(const Handle& other) const {
- return EqualsFunc::equals(value, other.value);
- }
-
- inline size_t hashCode() const {
- return HashFunc::hashCode(value);
- }
- };
-
- /** Returns the bounds of the sub array. Used by makeNode. */
- static AABox computeBounds(
- const Array<Handle*>& point,
- int beginIndex,
- int endIndex) {
-
- Vector3 lo = Vector3::inf();
- Vector3 hi = -lo;
-
- debugAssertM(beginIndex <= endIndex, "No points");
- for (int p = beginIndex; p <= endIndex; ++p) {
- // This code is written with the vector min and max expanded
- // because otherwise it compiles incorrectly with -O3 on
- // gcc 3.4
-
- const Vector3& pLo = point[p]->bounds.low();
- const Vector3& pHi = point[p]->bounds.high();
- for (int a = 0; a < 3; ++a) {
- lo[a] = G3D::min(lo[a], pLo[a]);
- hi[a] = G3D::max(hi[a], pHi[a]);
- }
- }
-
- return AABox(lo, hi);
- }
-
- /** Compares centers */
- class CenterComparator {
- public:
- Vector3::Axis sortAxis;
-
- CenterComparator(Vector3::Axis a) : sortAxis(a) {}
-
- inline int operator()(Handle* A, const Handle* B) const {
- float a = A->center[sortAxis];
- float b = B->center[sortAxis];
-
- if (a < b) {
- return 1;
- } else if (a > b) {
- return -1;
- } else {
- return 0;
- }
- }
- };
-
-
- /** Compares bounds for strict >, <, or overlap*/
- class BoundsComparator {
- public:
- Vector3::Axis sortAxis;
-
- BoundsComparator(Vector3::Axis a) : sortAxis(a) {}
-
- inline int operator()(Handle* A, const Handle* B) const {
- const AABox& a = A->bounds;
- const AABox& b = B->bounds;
-
- if (a.high()[sortAxis] < b.low()[sortAxis]) {
- return 1;
- } else if (a.low()[sortAxis] > b.high()[sortAxis]) {
- return -1;
- } else {
- return 0;
- }
- }
- };
-
-
- /** Compares bounds to the sort location */
- class Comparator {
- public:
- Vector3::Axis sortAxis;
- float sortLocation;
-
- Comparator(Vector3::Axis a, float l) : sortAxis(a), sortLocation(l) {}
-
- inline int operator()(Handle* ignore, const Handle* handle) const {
- (void)ignore;
- const AABox& box = handle->bounds;
- debugAssert(ignore == NULL);
-
- if (box.high()[sortAxis] < sortLocation) {
- // Box is strictly below the sort location
- return -1;
- } else if (box.low()[sortAxis] > sortLocation) {
- // Box is strictly above the sort location
- return 1;
- } else {
- // Box overlaps the sort location
- return 0;
- }
- }
- };
-
- // Using System::malloc with this class provided no speed improvement.
- class Node {
- public:
-
- /** Spatial bounds on all values at this node and its children, based purely on
- the parent's splitting planes. May be infinite. */
- AABox splitBounds;
-
- Vector3::Axis splitAxis;
-
- /** Location along the specified axis */
- float splitLocation;
-
- /** child[0] contains all values strictly
- smaller than splitLocation along splitAxis.
-
- child[1] contains all values strictly
- larger.
-
- Both may be NULL if there are not enough
- values to bother recursing.
- */
- Node* child[2];
-
- /** Array of values at this node (i.e., values
- straddling the split plane + all values if
- this is a leaf node).
-
- This is an array of pointers because that minimizes
- data movement during tree building, which accounts
- for about 15% of the time cost of tree building.
- */
- Array<Handle*> valueArray;
-
- /** For each object in the value array, a copy of its bounds.
- Packing these into an array at the node level
- instead putting them in the valueArray improves
- cache coherence, which is about a 3x performance
- increase when performing intersection computations.
- */
- Array<AABox> boundsArray;
-
- /** Creates node with NULL children */
- Node() {
- splitAxis = Vector3::X_AXIS;
- splitLocation = 0;
- splitBounds = AABox(-Vector3::inf(), Vector3::inf());
- for (int i = 0; i < 2; ++i) {
- child[i] = NULL;
- }
- }
-
- /**
- Doesn't clone children.
- */
- Node(const Node& other) : valueArray(other.valueArray), boundsArray(other.boundsArray) {
- splitAxis = other.splitAxis;
- splitLocation = other.splitLocation;
- splitBounds = other.splitBounds;
- for (int i = 0; i < 2; ++i) {
- child[i] = NULL;
- }
- }
-
- /** Copies the specified subarray of pt into point, NULLs the children.
- Assumes a second pass will set splitBounds. */
- Node(const Array<Handle*>& pt) : valueArray(pt) {
- splitAxis = Vector3::X_AXIS;
- splitLocation = 0;
- for (int i = 0; i < 2; ++i) {
- child[i] = NULL;
- }
-
- boundsArray.resize(valueArray.size());
- for (int i = 0; i < valueArray.size(); ++i) {
- boundsArray[i] = valueArray[i]->bounds;
- }
- }
-
- /** Deletes the children (but not the values) */
- ~Node() {
- for (int i = 0; i < 2; ++i) {
- delete child[i];
- }
- }
-
- /** Returns true if this node is a leaf (no children) */
- inline bool isLeaf() const {
- return (child[0] == NULL) && (child[1] == NULL);
- }
-
-
- /**
- Recursively appends all handles and children's handles
- to the array.
- */
- void getHandles(Array<Handle*>& handleArray) const {
- handleArray.append(valueArray);
- for (int i = 0; i < 2; ++i) {
- if (child[i] != NULL) {
- child[i]->getHandles(handleArray);
- }
- }
- }
-
- void verifyNode(const Vector3& lo, const Vector3& hi) {
- // debugPrintf("Verifying: split %d @ %f [%f, %f, %f], [%f, %f, %f]\n",
- // splitAxis, splitLocation, lo.x, lo.y, lo.z, hi.x, hi.y, hi.z);
-
- debugAssertM(lo == splitBounds.low(),
- format("lo = %s, splitBounds.lo = %s",
- lo.toString().c_str(), splitBounds.low().toString().c_str()));
- debugAssert(hi == splitBounds.high());
-
- for (int i = 0; i < valueArray.length(); ++i) {
- const AABox& b = valueArray[i]->bounds;
- debugAssert(b == boundsArray[i]);
-
- for(int axis = 0; axis < 3; ++axis) {
- debugAssert(b.low()[axis] <= b.high()[axis]);
- debugAssert(b.low()[axis] >= lo[axis]);
- debugAssert(b.high()[axis] <= hi[axis]);
- }
- }
-
- if (child[0] || child[1]) {
- debugAssert(lo[splitAxis] < splitLocation);
- debugAssert(hi[splitAxis] > splitLocation);
- }
-
- Vector3 newLo = lo;
- newLo[splitAxis] = splitLocation;
- Vector3 newHi = hi;
- newHi[splitAxis] = splitLocation;
-
- if (child[0] != NULL) {
- child[0]->verifyNode(lo, newHi);
- }
-
- if (child[1] != NULL) {
- child[1]->verifyNode(newLo, hi);
- }
- }
-
-
- /**
- Stores the locations of the splitting planes (the structure but not the content)
- so that the tree can be quickly rebuilt from a previous configuration without
- calling balance.
- */
- static void serializeStructure(const Node* n, BinaryOutput& bo) {
- if (n == NULL) {
- bo.writeUInt8(0);
- } else {
- bo.writeUInt8(1);
- n->splitBounds.serialize(bo);
- serialize(n->splitAxis, bo);
- bo.writeFloat32(n->splitLocation);
- for (int c = 0; c < 2; ++c) {
- serializeStructure(n->child[c], bo);
- }
- }
- }
-
- /** Clears the member table */
- static Node* deserializeStructure(BinaryInput& bi) {
- if (bi.readUInt8() == 0) {
- return NULL;
- } else {
- Node* n = new Node();
- n->splitBounds.deserialize(bi);
- deserialize(n->splitAxis, bi);
- n->splitLocation = bi.readFloat32();
- for (int c = 0; c < 2; ++c) {
- n->child[c] = deserializeStructure(bi);
- }
- return n;
- }
- }
-
- /** Returns the deepest node that completely contains bounds. */
- Node* findDeepestContainingNode(const AABox& bounds) {
-
- // See which side of the splitting plane the bounds are on
- if (bounds.high()[splitAxis] < splitLocation) {
- // Bounds are on the low side. Recurse into the child
- // if it exists.
- if (child[0] != NULL) {
- return child[0]->findDeepestContainingNode(bounds);
- }
- } else if (bounds.low()[splitAxis] > splitLocation) {
- // Bounds are on the high side, recurse into the child
- // if it exists.
- if (child[1] != NULL) {
- return child[1]->findDeepestContainingNode(bounds);
- }
- }
-
- // There was no containing child, so this node is the
- // deepest containing node.
- return this;
- }
-
-
- /** Appends all members that intersect the box.
- If useSphere is true, members that pass the box test
- face a second test against the sphere. */
- void getIntersectingMembers(
- const AABox& box,
- const Sphere& sphere,
- Array<T*>& members,
- bool useSphere) const {
-
- // Test all values at this node
- for (int v = 0; v < boundsArray.size(); ++v) {
- const AABox& bounds = boundsArray[v];
- if (bounds.intersects(box) &&
- (! useSphere || bounds.intersects(sphere))) {
- members.append(& (valueArray[v]->value));
- }
- }
-
- // If the left child overlaps the box, recurse into it
- if ((child[0] != NULL) && (box.low()[splitAxis] < splitLocation)) {
- child[0]->getIntersectingMembers(box, sphere, members, useSphere);
- }
-
- // If the right child overlaps the box, recurse into it
- if ((child[1] != NULL) && (box.high()[splitAxis] > splitLocation)) {
- child[1]->getIntersectingMembers(box, sphere, members, useSphere);
- }
- }
-
- /**
- Recurse through the tree, assigning splitBounds fields.
- */
- void assignSplitBounds(const AABox& myBounds) {
- splitBounds = myBounds;
-
- AABox childBounds[2];
- myBounds.split(splitAxis, splitLocation, childBounds[0], childBounds[1]);
-
-# if defined(G3D_DEBUG) && defined(VERIFY_TREE)
- // Verify the split
- for (int v = 0; v < boundsArray.size(); ++v) {
- const AABox& bounds = boundsArray[v];
- debugAssert(myBounds.contains(bounds));
- }
-# endif
-
- for (int c = 0; c < 2; ++c) {
- if (child[c]) {
- child[c]->assignSplitBounds(childBounds[c]);
- }
- }
- }
-
- /** Returns true if the ray intersects this node */
- bool intersects(const Ray& ray, float distance) const {
- // See if the ray will ever hit this node or its children
- Vector3 location;
- bool alreadyInsideBounds = false;
- bool rayWillHitBounds =
- CollisionDetection::collisionLocationForMovingPointFixedAABox(
- ray.origin(), ray.direction(), splitBounds, location, alreadyInsideBounds);
-
- bool canHitThisNode = (alreadyInsideBounds ||
- (rayWillHitBounds && ((location - ray.origin()).squaredLength() < square(distance))));
-
- return canHitThisNode;
- }
-
- template<typename RayCallback>
- void intersectRay(
- const Ray& ray,
- RayCallback& intersectCallback,
- float& distance,
- bool intersectCallbackIsFast) const {
-
- if (! intersects(ray, distance)) {
- // The ray doesn't hit this node, so it can't hit the children of the node.
- return;
- }
-
- // Test for intersection against every object at this node.
- for (int v = 0; v < valueArray.size(); ++v) {
- bool canHitThisObject = true;
-
- if (! intersectCallbackIsFast) {
- // See if
- Vector3 location;
- const AABox& bounds = boundsArray[v];
- bool alreadyInsideBounds = false;
- bool rayWillHitBounds =
- CollisionDetection::collisionLocationForMovingPointFixedAABox(
- ray.origin(), ray.direction(), bounds, location, alreadyInsideBounds);
-
- canHitThisObject = (alreadyInsideBounds ||
- (rayWillHitBounds && ((location - ray.origin()).squaredLength() < square(distance))));
- }
-
- if (canHitThisObject) {
- // It is possible that this ray hits this object. Look for the intersection using the
- // callback.
- const T& value = valueArray[v]->value;
- intersectCallback(ray, value, distance);
- }
- }
-
- // There are three cases to consider next:
- //
- // 1. the ray can start on one side of the splitting plane and never enter the other,
- // 2. the ray can start on one side and enter the other, and
- // 3. the ray can travel exactly down the splitting plane
-
- enum {NONE = -1};
- int firstChild = NONE;
- int secondChild = NONE;
-
- if (ray.origin()[splitAxis] < splitLocation) {
-
- // The ray starts on the small side
- firstChild = 0;
-
- if (ray.direction()[splitAxis] > 0) {
- // The ray will eventually reach the other side
- secondChild = 1;
- }
-
- } else if (ray.origin()[splitAxis] > splitLocation) {
-
- // The ray starts on the large side
- firstChild = 1;
-
- if (ray.direction()[splitAxis] < 0) {
- secondChild = 0;
- }
- } else {
- // The ray starts on the splitting plane
- if (ray.direction()[splitAxis] < 0) {
- // ...and goes to the small side
- firstChild = 0;
- } else if (ray.direction()[splitAxis] > 0) {
- // ...and goes to the large side
- firstChild = 1;
- }
- }
-
- // Test on the side closer to the ray origin.
- if ((firstChild != NONE) && child[firstChild]) {
- child[firstChild]->intersectRay(ray, intersectCallback, distance, intersectCallbackIsFast);
- }
-
- if (ray.direction()[splitAxis] != 0) {
- // See if there was an intersection before hitting the splitting plane.
- // If so, there is no need to look on the far side and recursion terminates.
- float distanceToSplittingPlane = (splitLocation - ray.origin()[splitAxis]) / ray.direction()[splitAxis];
- if (distanceToSplittingPlane > distance) {
- // We aren't going to hit anything else before hitting the splitting plane,
- // so don't bother looking on the far side of the splitting plane at the other
- // child.
- return;
- }
- }
-
- // Test on the side farther from the ray origin.
- if ((secondChild != NONE) && child[secondChild]) {
- child[secondChild]->intersectRay(ray, intersectCallback, distance, intersectCallbackIsFast);
- }
-
- }
- };
-
-
- /**
- Recursively subdivides the subarray.
-
- Clears the source array as soon as it is no longer needed.
-
- Call assignSplitBounds() on the root node after making a tree.
- */
- Node* makeNode(
- Array<Handle*>& source,
- int valuesPerNode,
- int numMeanSplits,
- Array<Handle*>& temp) {
-
- Node* node = NULL;
-
- if (source.size() <= valuesPerNode) {
- // Make a new leaf node
- node = new Node(source);
-
- // Set the pointers in the memberTable
- for (int i = 0; i < source.size(); ++i) {
- memberTable.set(Member(source[i]), node);
- }
- source.clear();
-
- } else {
- // Make a new internal node
- node = new Node();
-
- const AABox& bounds = computeBounds(source, 0, source.size() - 1);
- const Vector3& extent = bounds.high() - bounds.low();
-
- Vector3::Axis splitAxis = extent.primaryAxis();
-
- float splitLocation;
-
- // Arrays for holding the children
- Array<Handle*> lt, gt;
-
- if (numMeanSplits <= 0) {
-
- source.medianPartition(lt, node->valueArray, gt, temp, CenterComparator(splitAxis));
-
- // Choose the split location to be the center of whatever fell in the center
- splitLocation = node->valueArray[0]->center[splitAxis];
-
- // Some of the elements in the lt or gt array might really overlap the split location.
- // Move them as needed.
- for (int i = 0; i < lt.size(); ++i) {
- const AABox& bounds = lt[i]->bounds;
- if ((bounds.low()[splitAxis] <= splitLocation) && (bounds.high()[splitAxis] >= splitLocation)) {
- node->valueArray.append(lt[i]);
- // Remove this element and process the new one that
- // is swapped in in its place.
- lt.fastRemove(i); --i;
- }
- }
-
- for (int i = 0; i < gt.size(); ++i) {
- const AABox& bounds = gt[i]->bounds;
- if ((bounds.low()[splitAxis] <= splitLocation) && (bounds.high()[splitAxis] >= splitLocation)) {
- node->valueArray.append(gt[i]);
- // Remove this element and process the new one that
- // is swapped in in its place.
- gt.fastRemove(i); --i;
- }
- }
-
- if ((node->valueArray.size() > (source.size() / 2)) &&
- (source.size() > 6)) {
- // This was a bad partition; we ended up putting the splitting plane right in the middle of most of the
- // objects. We could try to split on a different axis, or use a different partition (e.g., the extents mean,
- // or geometric mean). This implementation falls back on the extents mean, since that case is already handled
- // below.
- numMeanSplits = 1;
- }
- }
-
- // Note: numMeanSplits may have been increased by the code in the previous case above in order to
- // force a re-partition.
-
- if (numMeanSplits > 0) {
- // Split along the mean
- splitLocation =
- bounds.high()[splitAxis] * 0.5f +
- bounds.low()[splitAxis] * 0.5f;
-
- debugAssertM(isFinite(splitLocation),
- "Internal error: split location must be finite.");
-
- source.partition(NULL, lt, node->valueArray, gt, Comparator(splitAxis, splitLocation));
-
- // The Comparator ensures that elements are strictly on the correct side of the split
- }
-
-
-# if defined(G3D_DEBUG) && defined(VERIFY_TREE)
- debugAssert(lt.size() + node->valueArray.size() + gt.size() == source.size());
- // Verify that all objects ended up on the correct side of the split.
- // (i.e., make sure that the Array partition was correct)
- for (int i = 0; i < lt.size(); ++i) {
- const AABox& bounds = lt[i]->bounds;
- debugAssert(bounds.high()[splitAxis] < splitLocation);
- }
-
- for (int i = 0; i < gt.size(); ++i) {
- const AABox& bounds = gt[i]->bounds;
- debugAssert(bounds.low()[splitAxis] > splitLocation);
- }
-
- for (int i = 0; i < node->valueArray.size(); ++i) {
- const AABox& bounds = node->valueArray[i]->bounds;
- debugAssert(bounds.high()[splitAxis] >= splitLocation);
- debugAssert(bounds.low()[splitAxis] <= splitLocation);
- }
-# endif
-
- // The source array is no longer needed
- source.clear();
-
- node->splitAxis = splitAxis;
- node->splitLocation = splitLocation;
-
- // Update the bounds array and member table
- node->boundsArray.resize(node->valueArray.size());
- for (int i = 0; i < node->valueArray.size(); ++i) {
- Handle* v = node->valueArray[i];
- node->boundsArray[i] = v->bounds;
- memberTable.set(Member(v), node);
- }
-
- if (lt.size() > 0) {
- node->child[0] = makeNode(lt, valuesPerNode, numMeanSplits - 1, temp);
- }
-
- if (gt.size() > 0) {
- node->child[1] = makeNode(gt, valuesPerNode, numMeanSplits - 1, temp);
- }
-
- }
-
- return node;
- }
-
- /**
- Recursively clone the passed in node tree, setting
- pointers for members in the memberTable as appropriate.
- called by the assignment operator.
- */
- Node* cloneTree(Node* src) {
- Node* dst = new Node(*src);
-
- // Make back pointers
- for (int i = 0; i < dst->valueArray.size(); ++i) {
- memberTable.set(Member(dst->valueArray[i]), dst);
- }
-
- // Clone children
- for (int i = 0; i < 2; ++i) {
- if (src->child[i] != NULL) {
- dst->child[i] = cloneTree(src->child[i]);
- }
- }
-
- return dst;
- }
-
- /**
- Wrapper for a Handle; used to create a memberTable that acts like Table<Handle, Node*> but
- stores only Handle* internally to avoid memory copies.
- */
- typedef _internal::Indirector<Handle> Member;
-
- typedef Table<Member, Node*> MemberTable;
-
- /** Maps members to the node containing them */
- MemberTable memberTable;
-
- Node* root;
-
-public:
-
- /** To construct a balanced tree, insert the elements and then call
- KDTree::balance(). */
- KDTree() : root(NULL) {}
-
-
- KDTree(const KDTree& src) : root(NULL) {
- *this = src;
- }
-
-
- KDTree& operator=(const KDTree& src) {
- delete root;
- // Clone tree takes care of filling out the memberTable.
- root = cloneTree(src.root);
- return *this;
- }
-
-
- ~KDTree() {
- clear();
- }
-
- /**
- Throws out all elements of the set.
- */
- void clear() {
- typedef typename Table<_internal::Indirector<Handle>, Node*>::Iterator It;
-
- // Delete all handles stored in the member table
- It cur = memberTable.begin();
- It end = memberTable.end();
- while (cur != end) {
- delete cur->key.handle;
- cur->key.handle = NULL;
- ++cur;
- }
- memberTable.clear();
-
- // Delete the tree structure itself
- delete root;
- root = NULL;
- }
-
- int size() const {
- return memberTable.size();
- }
-
- /**
- Inserts an object into the set if it is not
- already present. O(log n) time. Does not
- cause the tree to be balanced.
- */
- void insert(const T& value) {
- if (contains(value)) {
- // Already in the set
- return;
- }
-
- Handle* h = new Handle(value);
-
- if (root == NULL) {
- // This is the first node; create a root node
- root = new Node();
- }
-
- Node* node = root->findDeepestContainingNode(h->bounds);
-
- // Insert into the node
- node->valueArray.append(h);
- node->boundsArray.append(h->bounds);
-
- // Insert into the node table
- Member m(h);
- memberTable.set(m, node);
- }
-
- /** Inserts each elements in the array in turn. If the tree
- begins empty (no structure and no elements), this is faster
- than inserting each element in turn. You still need to balance
- the tree at the end.*/
- void insert(const Array<T>& valueArray) {
- if (root == NULL) {
- // Optimized case for an empty tree; don't bother
- // searching or reallocating the root node's valueArray
- // as we incrementally insert.
- root = new Node();
- root->valueArray.resize(valueArray.size());
- root->boundsArray.resize(root->valueArray.size());
- for (int i = 0; i < valueArray.size(); ++i) {
- // Insert in opposite order so that we have the exact same
- // data structure as if we inserted each (i.e., order is reversed
- // from array).
- Handle* h = new Handle(valueArray[i]);
- int j = valueArray.size() - i - 1;
- root->valueArray[j] = h;
- root->boundsArray[j] = h->bounds;
- memberTable.set(Member(h), root);
- }
-
- } else {
- // Insert at appropriate tree depth.
- for (int i = 0; i < valueArray.size(); ++i) {
- insert(valueArray[i]);
- }
- }
- }
-
-
- /**
- Returns true if this object is in the set, otherwise
- returns false. O(1) time.
- */
- bool contains(const T& value) {
- // Temporarily create a handle and member
- Handle h(value);
- return memberTable.containsKey(Member(&h));
- }
-
-
- /**
- Removes an object from the set in O(1) time.
- It is an error to remove members that are not already
- present. May unbalance the tree.
-
- Removing an element never causes a node (split plane) to be removed...
- nodes are only changed when the tree is rebalanced. This behavior
- is desirable because it allows the split planes to be serialized,
- and then deserialized into an empty tree which can be repopulated.
- */
- void remove(const T& value) {
- debugAssertM(contains(value),
- "Tried to remove an element from a "
- "KDTree that was not present");
-
- // Get the list of elements at the node
- Handle h(value);
- Member m(&h);
-
- Array<Handle*>& list = memberTable[m]->valueArray;
-
- Handle* ptr = NULL;
-
- // Find the element and remove it
- for (int i = list.length() - 1; i >= 0; --i) {
- if (list[i]->value == value) {
- // This was the element. Grab the pointer so that
- // we can delete it below
- ptr = list[i];
-
- // Remove the handle from the node
- list.fastRemove(i);
-
- // Remove the corresponding bounds
- memberTable[m]->boundsArray.fastRemove(i);
- break;
- }
- }
-
- // Remove the member
- memberTable.remove(m);
-
- // Delete the handle data structure
- delete ptr;
- ptr = NULL;
- }
-
-
- /**
- If the element is in the set, it is removed.
- The element is then inserted.
-
- This is useful when the == and hashCode methods
- on <I>T</I> are independent of the bounds. In
- that case, you may call update(v) to insert an
- element for the first time and call update(v)
- again every time it moves to keep the tree
- up to date.
- */
- void update(const T& value) {
- if (contains(value)) {
- remove(value);
- }
- insert(value);
- }
-
-
- /**
- Rebalances the tree (slow). Call when objects
- have moved substantially from their original positions
- (which unbalances the tree and causes the spatial
- queries to be slow).
-
- @param valuesPerNode Maximum number of elements to put at
- a node.
-
- @param numMeanSplits numMeanSplits = 0 gives a
- fully axis aligned BSP-tree, where the balance operation attempts to balance
- the tree so that every splitting plane has an equal number of left
- and right children (i.e. it is a <B>median</B> split along that axis).
- This tends to maximize average performance.
-
- You can override this behavior by
- setting a number of <B>mean</B> (average) splits. numMeanSplits = MAX_INT
- creates a full oct-tree, which tends to optimize peak performance at the expense of
- average performance. It tends to have better clustering behavior when
- members are not uniformly distributed.
- */
- void balance(int valuesPerNode = 5, int numMeanSplits = 3) {
- if (root == NULL) {
- // Tree is empty
- return;
- }
-
- // Get all handles and delete the old tree structure
- Node* oldRoot = root;
- for (int c = 0; c < 2; ++c) {
- if (root->child[c] != NULL) {
- root->child[c]->getHandles(root->valueArray);
-
- // Delete the child; this will delete all structure below it
- delete root->child[c];
- root->child[c] = NULL;
- }
- }
-
- Array<Handle*> temp;
- // Make a new root. Work with a copy of the value array because
- // makeNode clears the source array as it progresses
- Array<Handle*> copy(oldRoot->valueArray);
- root = makeNode(copy, valuesPerNode, numMeanSplits, temp);
-
- // Throw away the old root node
- delete oldRoot;
- oldRoot = NULL;
-
- // Walk the tree, assigning splitBounds. We start with unbounded
- // space. This will override the current member table.
- const AABox& LARGE = AABox::large();
- root->assignSplitBounds(LARGE);
-
-# ifdef _DEBUG
- {
- // Ensure that the balanced tree is still correct
- root->verifyNode(LARGE.low(), LARGE.high());
- }
-# endif
- }
-
-
- /** Clear, set the contents to the values in the array, and then balance */
- void setContents(const Array<T>& array, int valuesPerNode = 5, int numMeanSplits = 3) {
- clear();
- insert(array);
- balance(valuesPerNode, numMeanSplits);
- }
-
-
-protected:
-
- /**
- @param parentMask The mask that this node returned from culledBy.
- */
- static void getIntersectingMembers(
- const Array<Plane>& plane,
- Array<T*>& members,
- Node* node,
- uint32 parentMask) {
-
- int dummy;
-
- if (parentMask == 0) {
- // None of these planes can cull anything
- for (int v = node->valueArray.size() - 1; v >= 0; --v) {
- members.append(& (node->valueArray[v]->value));
- }
-
- // Iterate through child nodes
- for (int c = 0; c < 2; ++c) {
- if (node->child[c]) {
- getIntersectingMembers(plane, members, node->child[c], 0);
- }
- }
- } else {
-
- // Test values at this node against remaining planes
- for (int v = node->boundsArray.size() - 1; v >= 0; --v) {
- if (! node->boundsArray[v].culledBy(plane, dummy, parentMask)) {
- members.append(&(node->valueArray[v]->value));
- }
- }
-
- uint32 childMask = 0xFFFFFF;
-
- // Iterate through child nodes
- for (int c = 0; c < 2; ++c) {
- if (node->child[c] &&
- ! node->child[c]->splitBounds.culledBy(plane, dummy, parentMask, childMask)) {
- // This node was not culled
- getIntersectingMembers(plane, members, node->child[c], childMask);
- }
- }
- }
- }
-
-public:
-
- /**
- Returns all members inside the set of planes.
- @param members The results are appended to this array.
- */
- void getIntersectingMembers(const Array<Plane>& plane, Array<T*>& members) const {
- if (root == NULL) {
- return;
- }
-
- getIntersectingMembers(plane, members, root, 0xFFFFFF);
- }
-
- void getIntersectingMembers(const Array<Plane>& plane, Array<T>& members) const {
- Array<T*> temp;
- getIntersectingMembers(plane, temp, root, 0xFFFFFF);
- for (int i = 0; i < temp.size(); ++i) {
- members.append(*temp[i]);
- }
- }
-
- /**
- Typically used to find all visible
- objects inside the view frustum (see also GCamera::getClipPlanes)... i.e. all objects
- <B>not</B> culled by frustum.
-
- Example:
- <PRE>
- Array<Object*> visible;
- tree.getIntersectingMembers(camera.frustum(), visible);
- // ... Draw all objects in the visible array.
- </PRE>
- @param members The results are appended to this array.
- */
- void getIntersectingMembers(const GCamera::Frustum& frustum, Array<T*>& members) const {
- Array<Plane> plane;
-
- for (int i = 0; i < frustum.faceArray.size(); ++i) {
- plane.append(frustum.faceArray[i].plane);
- }
-
- getIntersectingMembers(plane, members);
- }
-
- void getIntersectingMembers(const GCamera::Frustum& frustum, Array<T>& members) const {
- Array<T*> temp;
- getIntersectingMembers(frustum, temp);
- for (int i = 0; i < temp.size(); ++i) {
- members.append(*temp[i]);
- }
- }
-
- /**
- C++ STL style iterator variable. See beginBoxIntersection().
- The iterator overloads the -> (dereference) operator, so this
- acts like a pointer to the current member.
- */
- // This iterator turns Node::getIntersectingMembers into a
- // coroutine. It first translates that method from recursive to
- // stack based, then captures the system state (analogous to a Scheme
- // continuation) after each element is appended to the member array,
- // and allowing the computation to be restarted.
- class BoxIntersectionIterator {
- private:
- friend class TreeType;
-
- /** True if this is the "end" iterator instance */
- bool isEnd;
-
- /** The box that we're testing against. */
- AABox box;
-
- /** Node that we're currently looking at. Undefined if isEnd
- is true. */
- Node* node;
-
- /** Nodes waiting to be processed */
- // We could use backpointers within the tree and careful
- // state management to avoid ever storing the stack-- but
- // it is much easier this way and only inefficient if the
- // caller uses post increment (which they shouldn't!).
- Array<Node*> stack;
-
- /** The next index of current->valueArray to return.
- Undefined when isEnd is true.*/
- int nextValueArrayIndex;
-
- BoxIntersectionIterator() : isEnd(true) {}
-
- BoxIntersectionIterator(const AABox& b, const Node* root) :
- isEnd(root == NULL), box(b),
- node(const_cast<Node*>(root)), nextValueArrayIndex(-1) {
-
- // We intentionally start at the "-1" index of the current
- // node so we can use the preincrement operator to move
- // ourselves to element 0 instead of repeating all of the
- // code from the preincrement method. Note that this might
- // cause us to become the "end" instance.
- ++(*this);
- }
-
- public:
-
- inline bool operator!=(const BoxIntersectionIterator& other) const {
- return ! (*this == other);
- }
-
- bool operator==(const BoxIntersectionIterator& other) const {
- if (isEnd) {
- return other.isEnd;
- } else if (other.isEnd) {
- return false;
- } else {
- // Two non-end iterators; see if they match. This is kind of
- // silly; users shouldn't call == on iterators in general unless
- // one of them is the end iterator.
- if ((box != other.box) || (node != other.node) ||
- (nextValueArrayIndex != other.nextValueArrayIndex) ||
- (stack.length() != other.stack.length())) {
- return false;
- }
-
- // See if the stacks are the same
- for (int i = 0; i < stack.length(); ++i) {
- if (stack[i] != other.stack[i]) {
- return false;
- }
- }
-
- // We failed to find a difference; they must be the same
- return true;
- }
- }
-
- /**
- Pre increment.
- */
- BoxIntersectionIterator& operator++() {
- ++nextValueArrayIndex;
-
- bool foundIntersection = false;
- while (! isEnd && ! foundIntersection) {
-
- // Search for the next node if we've exhausted this one
- while ((! isEnd) && (nextValueArrayIndex >= node->valueArray.length())) {
- // If we entered this loop, then the iterator has exhausted the elements at
- // node (possibly because it just switched to a child node with no members).
- // This loop continues until it finds a node with members or reaches
- // the end of the whole intersection search.
-
- // If the right child overlaps the box, push it onto the stack for
- // processing.
- if ((node->child[1] != NULL) &&
- (box.high()[node->splitAxis] > node->splitLocation)) {
- stack.push(node->child[1]);
- }
-
- // If the left child overlaps the box, push it onto the stack for
- // processing.
- if ((node->child[0] != NULL) &&
- (box.low()[node->splitAxis] < node->splitLocation)) {
- stack.push(node->child[0]);
- }
-
- if (stack.length() > 0) {
- // Go on to the next node (which may be either one of the ones we
- // just pushed, or one from farther back the tree).
- node = stack.pop();
- nextValueArrayIndex = 0;
- } else {
- // That was the last node; we're done iterating
- isEnd = true;
- }
- }
-
- // Search for the next intersection at this node until we run out of children
- while (! isEnd && ! foundIntersection && (nextValueArrayIndex < node->valueArray.length())) {
- if (box.intersects(node->boundsArray[nextValueArrayIndex])) {
- foundIntersection = true;
- } else {
- ++nextValueArrayIndex;
- // If we exhaust this node, we'll loop around the master loop
- // to find a new node.
- }
- }
- }
-
- return *this;
- }
-
- private:
- /**
- Post increment (much slower than preincrement!).
- Intentionally overloaded to preclude accidentally slow code.
- */
- BoxIntersectionIterator operator++(int);
- /*{
- BoxIntersectionIterator old = *this;
- ++this;
- return old;
- }*/
-
- public:
-
- /** Overloaded dereference operator so the iterator can masquerade as a pointer
- to a member */
- const T& operator*() const {
- alwaysAssertM(! isEnd, "Can't dereference the end element of an iterator");
- return node->valueArray[nextValueArrayIndex]->value;
- }
-
- /** Overloaded dereference operator so the iterator can masquerade as a pointer
- to a member */
- T const * operator->() const {
- alwaysAssertM(! isEnd, "Can't dereference the end element of an iterator");
- return &(stack.last()->valueArray[nextValueArrayIndex]->value);
- }
-
- /** Overloaded cast operator so the iterator can masquerade as a pointer
- to a member */
- operator T*() const {
- alwaysAssertM(! isEnd, "Can't dereference the end element of an iterator");
- return &(stack.last()->valueArray[nextValueArrayIndex]->value);
- }
- };
-
-
- /**
- Iterates through the members that intersect the box
- */
- BoxIntersectionIterator beginBoxIntersection(const AABox& box) const {
- return BoxIntersectionIterator(box, root);
- }
-
- BoxIntersectionIterator endBoxIntersection() const {
- // The "end" iterator instance
- return BoxIntersectionIterator();
- }
-
- /**
- Appends all members whose bounds intersect the box.
- See also KDTree::beginBoxIntersection.
- */
- void getIntersectingMembers(const AABox& box, Array<T*>& members) const {
- if (root == NULL) {
- return;
- }
- root->getIntersectingMembers(box, Sphere(Vector3::zero(), 0), members, false);
- }
-
- void getIntersectingMembers(const AABox& box, Array<T>& members) const {
- Array<T*> temp;
- getIntersectingMembers(box, temp);
- for (int i = 0; i < temp.size(); ++i) {
- members.append(*temp[i]);
- }
- }
-
-
- /**
- Invoke a callback for every member along a ray until the closest intersection is found.
-
- @param callback either a function or an instance of a class with an overloaded operator() of the form:
-
- <code>void callback(const Ray& ray, const T& object, float& distance)</code>. If the ray hits the object
- before travelling distance <code>distance</code>, updates <code>distance</code> with the new distance to
- the intersection, otherwise leaves it unmodified. A common example is:
-
- <pre>
- class Entity {
- public:
-
- void intersect(const Ray& ray, float& maxDist, Vector3& outLocation, Vector3& outNormal) {
- float d = maxDist;
-
- // ... search for intersection distance d
-
- if ((d > 0) && (d < maxDist)) {
- // Intersection occured
- maxDist = d;
- outLocation = ...;
- outNormal = ...;
- }
- }
- };
-
- // Finds the surface normal and location of the first intersection with the scene
- class Intersection {
- public:
- Entity* closestEntity;
- Vector3 hitLocation;
- Vector3 hitNormal;
-
- void operator()(const Ray& ray, const Entity* entity, float& distance) {
- entity->intersect(ray, distance, hitLocation, hitNormal);
- }
- };
-
- KDTree<Entity*> scene;
-
- Intersection intersection;
- float distance = finf();
- scene.intersectRay(camera.worldRay(x, y), intersection, distance);
- </pre>
-
-
- @param distance When the method is invoked, this is the maximum
- distance that the tree should search for an intersection. On
- return, this is set to the distance to the first intersection
- encountered.
-
- @param intersectCallbackIsFast If false, each object's bounds are
- tested before the intersectCallback is invoked. If the
- intersect callback runs at the same speed or faster than
- AABox-ray intersection, set this to true.
- */
- template<typename RayCallback>
- void intersectRay(
- const Ray& ray,
- RayCallback& intersectCallback,
- float& distance,
- bool intersectCallbackIsFast = false) const {
-
- root->intersectRay(ray, intersectCallback, distance, intersectCallbackIsFast);
- }
-
-
- /**
- @brief Finds all members whose bounding boxes intersect the sphere. The actual
- elements may not intersect the sphere.
-
- @param members The results are appended to this array.
- */
- void getIntersectingMembers(const Sphere& sphere, Array<T*>& members) const {
- if (root == NULL) {
- return;
- }
-
- AABox box;
- sphere.getBounds(box);
- root->getIntersectingMembers(box, sphere, members, true);
- }
-
- void getIntersectingMembers(const Sphere& sphere, Array<T>& members) const {
- Array<T*> temp;
- getIntersectingMembers(sphere, temp);
- for (int i = 0; i < temp.size(); ++i) {
- members.append(*temp[i]);
- }
- }
-
- /**
- Stores the locations of the splitting planes (the structure but not the content)
- so that the tree can be quickly rebuilt from a previous configuration without
- calling balance.
- */
- void serializeStructure(BinaryOutput& bo) const {
- Node::serializeStructure(root, bo);
- }
-
- /** Clears the member table */
- void deserializeStructure(BinaryInput& bi) {
- clear();
- root = Node::deserializeStructure(bi);
- }
-
- /**
- Returns an array of all members of the set. See also KDTree::begin.
- */
- void getMembers(Array<T>& members) const {
- Array<Member> temp;
- memberTable.getKeys(temp);
- for (int i = 0; i < temp.size(); ++i) {
- members.append(*(temp.handle));
- }
- }
-
-
- /** If a value that is EqualsFunc to @a value is present, returns a pointer to the
- version stored in the data structure, otherwise returns NULL.
- */
- const T* getPointer(const T& value) const {
- // Temporarily create a handle and member
- Handle h(value);
- const Member* member = memberTable.getKeyPointer(Member(&h));
- if (member == NULL) {
- // Not found
- return NULL;
- } else {
- return &(member->handle->value);
- }
- }
-
-
- /**
- C++ STL style iterator variable. See begin().
- Overloads the -> (dereference) operator, so this acts like a pointer
- to the current member.
- */
- class Iterator {
- private:
- friend class TreeType;
-
- // Note: this is a Table iterator, we are currently defining
- // Set iterator
- typename Table<Member, Node*>::Iterator it;
-
- Iterator(const typename Table<Member, Node*>::Iterator& it) : it(it) {}
-
- public:
-
- inline bool operator!=(const Iterator& other) const {
- return !(*this == other);
- }
-
- bool operator==(const Iterator& other) const {
- return it == other.it;
- }
-
- /**
- Pre increment.
- */
- Iterator& operator++() {
- ++it;
- return *this;
- }
-
- private:
- /**
- Post increment (slower than preincrement). Intentionally unimplemented to prevent slow code.
- */
- Iterator operator++(int);/* {
- Iterator old = *this;
- ++(*this);
- return old;
- }*/
- public:
-
- const T& operator*() const {
- return it->key.handle->value;
- }
-
- T* operator->() const {
- return &(it->key.handle->value);
- }
-
- operator T*() const {
- return &(it->key.handle->value);
- }
- };
-
-
- /**
- C++ STL style iterator method. Returns the first member.
- Use preincrement (++entry) to get to the next element (iteration
- order is arbitrary).
- Do not modify the set while iterating.
- */
- Iterator begin() const {
- return Iterator(memberTable.begin());
- }
-
-
- /**
- C++ STL style iterator method. Returns one after the last iterator
- element.
- */
- Iterator end() const {
- return Iterator(memberTable.end());
- }
-#undef TreeType
-};
-
-
-}
-
-#endif
diff --git a/externals/g3dlite/G3D/Line.h b/externals/g3dlite/G3D/Line.h
deleted file mode 100644
index 3579a6becec..00000000000
--- a/externals/g3dlite/G3D/Line.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/**
- @file Line.h
-
- Line class
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2001-06-02
- @edited 2006-02-28
- */
-
-#ifndef G3D_LINE_H
-#define G3D_LINE_H
-
-#include "G3D/platform.h"
-#include "G3D/Vector3.h"
-
-namespace G3D {
-
-class Plane;
-
-/**
- An infinite 3D line.
- */
-class Line {
-protected:
-
- Vector3 _point;
- Vector3 _direction;
-
- Line(const Vector3& point, const Vector3& direction) {
- _point = point;
- _direction = direction.direction();
- }
-
-public:
-
- /** Undefined (provided for creating Array<Line> only) */
- inline Line() {}
-
- Line(class BinaryInput& b);
-
- void serialize(class BinaryOutput& b) const;
-
- void deserialize(class BinaryInput& b);
-
- virtual ~Line() {}
-
- /**
- Constructs a line from two (not equal) points.
- */
- static Line fromTwoPoints(const Vector3 &point1, const Vector3 &point2) {
- return Line(point1, point2 - point1);
- }
-
- /**
- Creates a line from a point and a (nonzero) direction.
- */
- static Line fromPointAndDirection(const Vector3& point, const Vector3& direction) {
- return Line(point, direction);
- }
-
- /**
- Returns the closest point on the line to point.
- */
- Vector3 closestPoint(const Vector3& pt) const;
-
- /**
- Returns the distance between point and the line
- */
- double distance(const Vector3& point) const {
- return (closestPoint(point) - point).magnitude();
- }
-
- /** Returns a point on the line */
- Vector3 point() const;
-
- /** Returns the direction (or negative direction) of the line */
- Vector3 direction() const;
-
- /**
- Returns the point where the line and plane intersect. If there
- is no intersection, returns a point at infinity.
- */
- Vector3 intersection(const Plane &plane) const;
-
-
- /** Finds the closest point to the two lines.
-
- @param minDist Returns the minimum distance between the lines.
-
- @cite http://objectmix.com/graphics/133793-coordinates-closest-points-pair-skew-lines.html
- */
- Vector3 closestPoint(const Line& B, float& minDist) const;
-
- inline Vector3 closestPoint(const Line& B) const {
- float m;
- return closestPoint(B, m);
- }
-};
-
-};// namespace
-
-
-#endif
diff --git a/externals/g3dlite/G3D/LineSegment.h b/externals/g3dlite/G3D/LineSegment.h
deleted file mode 100644
index 70210ec7e00..00000000000
--- a/externals/g3dlite/G3D/LineSegment.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/**
- @file LineSegment.h
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2003-02-08
- @edited 2008-02-02
- */
-
-#ifndef G3D_LINESEGMENT_H
-#define G3D_LINESEGMENT_H
-
-#include "G3D/platform.h"
-#include "G3D/Vector3.h"
-
-namespace G3D {
-
-/**
- An finite segment of an infinite 3D line.
- */
-class LineSegment {
-protected:
-
- Vector3 _point;
-
- /** Not normalized */
- Vector3 direction;
-
- LineSegment(const Vector3& __point, const Vector3& _direction) : _point(__point), direction(_direction) {
- }
-
-public:
-
- inline LineSegment() : _point(Vector3::zero()), direction(Vector3::zero()) {}
-
- LineSegment(class BinaryInput& b);
-
- void serialize(class BinaryOutput& b) const;
-
- void deserialize(class BinaryInput& b);
-
- virtual ~LineSegment() {}
-
- /**
- * Constructs a line from two (not equal) points.
- */
- static LineSegment fromTwoPoints(const Vector3 &point1, const Vector3 &point2) {
- return LineSegment(point1, point2 - point1);
- }
-
- /** Call with 0 or 1 */
- Vector3 point(int i) const;
-
- inline float length() const {
- return direction.magnitude();
- }
-
- /**
- * Returns the closest point on the line segment to point.
- */
- Vector3 closestPoint(const Vector3 &point) const;
-
- /**
- Returns the distance between point and the line
- */
- double distance(const Vector3& p) const {
- return (closestPoint(p) - p).magnitude();
- }
-
- double distanceSquared(const Vector3& p) const {
- return (closestPoint(p) - p).squaredMagnitude();
- }
-
- /** Returns true if some part of this segment is inside the sphere */
- bool intersectsSolidSphere(const class Sphere& s) const;
-
- Vector3 randomPoint() const;
-
-};
-
-
-class LineSegment2D {
-private:
-
- Vector2 m_origin;
-
- /** Not normalized */
- Vector2 m_direction;
-
- /** Length of m_direction */
- float m_length;
-
-public:
-
- LineSegment2D() {}
-
- static LineSegment2D fromTwoPoints(const Vector2& p0, const Vector2& p1);
-
- /** Returns the intersection of these segements (including
- testing endpoints), or Vector2::inf() if they do not intersect. */
- Vector2 intersection(const LineSegment2D& other) const;
-
- Vector2 point(int i) const;
-
- Vector2 closestPoint(const Vector2& Q) const;
-
- float distance(const Vector2& p) const;
-
- float length() const;
-};
-
-} // namespace
-
-
-#endif
diff --git a/externals/g3dlite/G3D/Log.h b/externals/g3dlite/G3D/Log.h
deleted file mode 100644
index d252d0c1a17..00000000000
--- a/externals/g3dlite/G3D/Log.h
+++ /dev/null
@@ -1,109 +0,0 @@
-/**
- @file Log.h
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @cite Backtrace by Aaron Orenstein
- @created 2001-08-04
- @edited 2005-11-04
- */
-
-#ifndef G3D_LOG_H
-#define G3D_LOG_H
-
-#include <stdio.h>
-#include <string>
-#include "G3D/platform.h"
-
-#ifndef G3D_WIN32
- #include <stdarg.h>
-#endif
-
-namespace G3D {
-
-/** Prints to the common system log, log.txt, which is usually
- in the working directory of the program. If your disk is
- not writable or is slow, it will attempt to write to "c:/tmp/log.txt" or
- "c:/temp/log.txt" on Windows systems instead.
-
- Unlike printf or debugPrintf,
- this function guarantees that all output is committed before it returns.
- This is very useful for debugging a crash, which might hide the last few
- buffered print statements otherwise.
-
- Many G3D routines write useful warnings and debugging information to the
- system log, which makes it a good first place to go when tracking down
- a problem.
- */
-void logPrintf(const char* fmt, ...);
-
-/** Does not flush the buffer; follow up with a logPrintf to force the flush. */
-void logLazyPrintf(const char* fmt, ...);
-
-/**
- System log for debugging purposes. The first log opened
- is the "common log" and can be accessed with the static
- method common(). If you access common() and a common log
- does not yet exist, one is created for you.
- */
-class Log {
-private:
-
- /**
- Log messages go here.
- */
- FILE* logFile;
-
- std::string filename;
-
- static Log* commonLog;
-
- int stripFromStackBottom;
-
-public:
-
- /**
- @param stripFromStackBottom Number of call stacks to strip from the
- bottom of the stack when printing a trace. Useful for hiding
- routines like "main" and "WinMain". If the specified file cannot
- be opened for some reason, tries to open "c:/tmp/log.txt" or
- "c:/temp/log.txt" instead.
- */
- Log(const std::string& filename = "log.txt",
- int stripFromStackBottom = 0);
-
- virtual ~Log();
-
- /**
- Returns the handle to the file log.
- */
- FILE* getFile() const;
-
- /**
- Marks the beginning of a logfile section.
- */
- void section(const std::string& s);
-
- /**
- Given arguments like printf, writes characters to the debug text overlay.
- */
- // We want G3D_CHECK_PRINTF_ARGS here, but that conflicts with the
- // overload.
- void __cdecl printf(const char* fmt, ...) G3D_CHECK_PRINTF_METHOD_ARGS;
-
- void __cdecl vprintf(const char*, va_list argPtr) G3D_CHECK_VPRINTF_METHOD_ARGS;
- /** Does not flush */
- void __cdecl lazyvprintf(const char*, va_list argPtr) G3D_CHECK_VPRINTF_METHOD_ARGS;
-
- static Log* common();
-
- static std::string getCommonLogFilename();
-
- void print(const std::string& s);
-
-
- void println(const std::string& s);
-};
-
-}
-
-#endif
diff --git a/externals/g3dlite/G3D/Map2D.h b/externals/g3dlite/G3D/Map2D.h
deleted file mode 100644
index 9af9f7242c1..00000000000
--- a/externals/g3dlite/G3D/Map2D.h
+++ /dev/null
@@ -1,667 +0,0 @@
-/**
- @file Map2D.h
-
- More flexible support than provided by G3D::GImage.
-
- @maintainer Morgan McGuire, morgan@cs.brown.edu
- @created 2004-10-10
- @edited 2009-03-24
- */
-#ifndef G3D_Map2D_h
-#define G3D_Map2D_h
-
-#include "G3D/platform.h"
-#include "G3D/g3dmath.h"
-#include "G3D/Array.h"
-#include "G3D/vectorMath.h"
-#include "G3D/Vector2int16.h"
-#include "G3D/ReferenceCount.h"
-#include "G3D/AtomicInt32.h"
-#include "G3D/GThread.h"
-#include "G3D/Rect2D.h"
-#include "G3D/WrapMode.h"
-
-#include <string>
-
-namespace G3D {
-namespace _internal {
-
-/** The default compute type for a type is the type itself. */
-template<typename Storage> class _GetComputeType {
-public:
- typedef Storage Type;
-};
-
-} // _internal
-} // G3D
-
-// This weird syntax is needed to support VC6, which doesn't
-// properly implement template overloading.
-#define DECLARE_COMPUTE_TYPE(StorageType, ComputeType) \
-namespace G3D { \
- namespace _internal { \
- template<> class _GetComputeType < StorageType > { \
- public: \
- typedef ComputeType Type; \
- }; \
- } \
-}
-
-DECLARE_COMPUTE_TYPE( float32, float64)
-DECLARE_COMPUTE_TYPE( float64, float64)
-
-DECLARE_COMPUTE_TYPE( int8, float32)
-DECLARE_COMPUTE_TYPE( int16, float32)
-DECLARE_COMPUTE_TYPE( int32, float64)
-DECLARE_COMPUTE_TYPE( int64, float64)
-
-DECLARE_COMPUTE_TYPE( uint8, float32)
-DECLARE_COMPUTE_TYPE( uint16, float32)
-DECLARE_COMPUTE_TYPE( uint32, float64)
-DECLARE_COMPUTE_TYPE( uint64, float64)
-
-DECLARE_COMPUTE_TYPE( Vector2, Vector2)
-DECLARE_COMPUTE_TYPE( Vector2int16, Vector2)
-
-DECLARE_COMPUTE_TYPE( Vector3, Vector3)
-DECLARE_COMPUTE_TYPE( Vector3int16, Vector3)
-
-DECLARE_COMPUTE_TYPE( Vector4, Vector4)
-
-DECLARE_COMPUTE_TYPE( Color3, Color3)
-DECLARE_COMPUTE_TYPE( Color3uint8, Color3)
-
-DECLARE_COMPUTE_TYPE( Color4, Color4)
-DECLARE_COMPUTE_TYPE( Color4uint8, Color4)
-#undef DECLARE_COMPUTE_TYPE
-
-namespace G3D {
-
-/**
- Map of values across a discrete 2D plane. Can be thought of as a generic class for 2D images,
- allowing flexibility as to pixel format and convenient methods.
- In fact, the "pixels" can be any values
- on a grid that can be sensibly interpolated--RGB colors, scalars, 4D vectors, and so on.
-
- Other "image" classes in G3D:
-
- G3D::GImage - Supports file formats, fast, Color3uint8 and Color4uint8 formats. No interpolation.
-
- G3D::Texture::Ref - Represents image on the graphics card (not directly readable on the CPU). Supports 2D, 3D, and a variety of interpolation methods, loads file formats.
-
- G3D::Image3 - A subclass of Map2D<Color3> that supports image loading and saving and conversion to Texture.
-
- G3D::Image4 - A subclass of Map2D<Color4> that supports image loading and saving and conversion to Texture.
-
- G3D::Image3uint8 - A subclass of Map2D<Color3uint8> that supports image loading and saving and conversion to Texture.
-
- G3D::Image4uint8 - A subclass of Map2D<Color4uint8> that supports image loading and saving and conversion to Texture.
-
- There are two type parameters-- the first (@ Storage) is the type
- used to store the "pixel" values efficiently and
- the second (@a Compute) is
- the type operated on by computation. The Compute::Compute(Storage&) constructor
- is used to convert between storage and computation types.
- @a Storage is often an integer version of @a Compute, for example
- <code>Map2D<double, uint8></code>. By default, the computation type is:
-
- <pre>
- Storage Computation
-
- uint8 float32
- uint16 float32
- uint32 float64
- uint64 float64
-
- int8 float32
- int16 float32
- int32 float64
- int64 float64
-
- float32 float64
- float64 float64
-
- Vector2 Vector2
- Vector2int16 Vector2
-
- Vector3 Vector3
- Vector3int16 Vector3
-
- Vector4 Vector4
-
- Color3 Color3
- Color3uint8 Color3
-
- Color4 Color4
- Color4uint8 Color4
- </pre>
- Any other storage type defaults to itself as the computation type.
-
- The computation type can be any that
- supports lerp, +, -, *, /, and an empty constructor.
-
- Assign value:
-
- <code>im->set(x, y, 7);</code> or
- <code>im->get(x, y) = 7;</code>
-
- Read value:
-
- <code>int c = im(x, y);</code>
-
- Can also sample with nearest neighbor, bilinear, and bicubic
- interpolation.
-
- Sampling follows OpenGL conventions, where
- pixel values represent grid points and (0.5, 0.5) is half-way
- between two vertical and two horizontal grid points.
- To draw an image of dimensions w x h with nearest neighbor
- sampling, render pixels from [0, 0] to [w - 1, h - 1].
-
- Under the WrapMode::CLAMP wrap mode, the value of bilinear interpolation
- becomes constant outside [1, w - 2] horizontally. Nearest neighbor
- interpolation is constant outside [0, w - 1] and bicubic outside
- [3, w - 4]. The class does not offer quadratic interpolation because
- the interpolation filter could not center over a pixel.
-
- @author Morgan McGuire, http://graphics.cs.williams.edu
- */
-template< typename Storage,
-typename Compute = typename G3D::_internal::_GetComputeType<Storage>::Type>
-class Map2D : public ReferenceCountedObject {
-
-//
-// It doesn't make sense to automatically convert from Compute back to Storage
-// because the rounding rule (and scaling) is application dependent.
-// Thus the interpolation methods all return type Compute.
-//
-
-public:
-
- typedef Storage StorageType;
- typedef Compute ComputeType;
- typedef Map2D<Storage, Compute> Type;
- typedef ReferenceCountedPointer<Map2D> Ref;
-
-protected:
-
- Storage ZERO;
-
- /** Width, in pixels. */
- uint32 w;
-
- /** Height, in pixels. */
- uint32 h;
-
- WrapMode _wrapMode;
-
- /** 0 if no mutating method has been invoked
- since the last call to setChanged(); */
- AtomicInt32 m_changed;
-
- Array<Storage> data;
-
- /** Handles the exceptional cases from get */
- const Storage& slowGet(int x, int y, WrapMode wrap) {
- switch (wrap) {
- case WrapMode::CLAMP:
- return fastGet(iClamp(x, 0, w - 1), iClamp(y, 0, h - 1));
-
- case WrapMode::TILE:
- return fastGet(iWrap(x, w), iWrap(y, h));
-
- case WrapMode::ZERO:
- return ZERO;
-
- case WrapMode::ERROR:
- alwaysAssertM(((uint32)x < w) && ((uint32)y < h),
- format("Index out of bounds: (%d, %d), w = %d, h = %d",
- x, y, w, h));
-
- // intentionally fall through
- case WrapMode::IGNORE:
- // intentionally fall through
- default:
- {
- static Storage temp;
- return temp;
- }
- }
- }
-
-public:
-
- /** Unsafe access to the underlying data structure with no wrapping support; requires that (x, y) is in bounds. */
- inline const Storage& fastGet(int x, int y) const {
- debugAssert(((uint32)x < w) && ((uint32)y < h));
- return data[x + y * w];
- }
-
- /** Unsafe access to the underlying data structure with no wrapping support; requires that (x, y) is in bounds. */
- inline void fastSet(int x, int y, const Storage& v) {
- debugAssert(((uint32)x < w) && ((uint32)y < h));
- data[x + y * w] = v;
- }
-
-protected:
-
- /** Given four control points and a value on the range [0, 1)
- evaluates the Catmull-rom spline between the times of the
- middle two control points */
- Compute bicubic(const Compute* ctrl, double s) const {
-
- // f = B * S * ctrl'
-
- // B matrix: Catmull-Rom spline basis
- static const double B[4][4] = {
- { 0.0, -0.5, 1.0, -0.5},
- { 1.0, 0.0, -2.5, 1.5},
- { 0.0, 0.5, 2.0, -1.5},
- { 0.0, 0.0, -0.5, 0.5}};
-
- // S: Powers of the fraction
- double S[4];
- double s2 = s * s;
- S[0] = 1.0;
- S[1] = s;
- S[2] = s2;
- S[3] = s2 * s;
-
- Compute sum(ZERO);
-
- for (int c = 0; c < 4; ++c) {
- double coeff = 0.0;
- for (int power = 0; power < 4; ++power) {
- coeff += B[c][power] * S[power];
- }
- sum += ctrl[c] * coeff;
- }
-
- return sum;
- }
-
-
- Map2D(int w, int h, WrapMode wrap) : w(0), h(0), _wrapMode(wrap), m_changed(1) {
- ZERO = Storage(Compute(Storage()) * 0);
- resize(w, h);
- }
-
-public:
-
- /**
- Although Map2D is not threadsafe (except for the setChanged() method),
- you can use this mutex to create your own threadsafe access to a Map2D.
- Not used by the default implementation.
- */
- GMutex mutex;
-
- static Ref create(int w = 0, int h = 0, WrapMode wrap = WrapMode::ERROR) {
- return new Map2D(w, h, wrap);
- }
-
- /** Resizes without clearing, leaving garbage.
- */
- void resize(uint32 newW, uint32 newH) {
- if ((newW != w) || (newH != h)) {
- w = newW;
- h = newH;
- data.resize(w * h);
- setChanged(true);
- }
- }
-
- /**
- Returns true if this map has been written to since the last call to setChanged(false).
- This is useful if you are caching a texture map other value that must be recomputed
- whenever this changes.
- */
- bool changed() {
- return m_changed.value() != 0;
- }
-
- /** Set/unset the changed flag. */
- void setChanged(bool c) {
- m_changed = c ? 1 : 0;
- }
-
- /** Returns a pointer to the underlying row-major data. There is no padding at the end of the row.
- Be careful--this will be reallocated during a resize. You should call setChanged(true) if you mutate the array.*/
- Storage* getCArray() {
- return data.getCArray();
- }
-
-
- const Storage* getCArray() const {
- return data.getCArray();
- }
-
-
- /** Row-major array. You should call setChanged(true) if you mutate the array. */
- Array<Storage>& getArray() {
- return data;
- }
-
-
- const Array<Storage>& getArray() const {
- return data;
- }
-
- /** is (x, y) strictly within the image bounds, or will it trigger some kind of wrap mode */
- inline bool inBounds(int x, int y) const {
- return (((uint32)x < w) && ((uint32)y < h));
- }
-
- /** is (x, y) strictly within the image bounds, or will it trigger some kind of wrap mode */
- inline bool inBounds(const Vector2int16& v) const {
- return inBounds(v.x, v.y);
- }
-
- /** Get the value at (x, y).
-
- Note that the type of image->get(x, y) is
- the storage type, not the computation
- type. If the constructor promoting Storage to Compute rescales values
- (as, for example Color3(Color3uint8&) does), this will not match the value
- returned by Map2D::nearest.
- */
- inline const Storage& get(int x, int y, WrapMode wrap) const {
- if (((uint32)x < w) && ((uint32)y < h)) {
- return data[x + y * w];
- } else {
- // Remove the const to allow a slowGet on this object
- // (we're returning a const reference so this is ok)
- return const_cast<Type*>(this)->slowGet(x, y, wrap);
- }
-# ifndef G3D_WIN32
- // gcc gives a useless warning that the above code might reach the end of the function;
- // we use this line to supress the warning.
- return ZERO;
-# endif
- }
-
- inline const Storage& get(int x, int y) const {
- return get(x, y, _wrapMode);
- }
-
- inline const Storage& get(const Vector2int16& p) const {
- return get(p.x, p.y, _wrapMode);
- }
-
- inline const Storage& get(const Vector2int16& p, WrapMode wrap) const {
- return get(p.x, p.y, wrap);
- }
-
- inline Storage& get(int x, int y, WrapMode wrap) {
- return const_cast<Storage&>(const_cast<const Type*>(this)->get(x, y, wrap));
-# ifndef G3D_WIN32
- // gcc gives a useless warning that the above code might reach the end of the function;
- // we use this line to supress the warning.
- return ZERO;
-# endif
- }
-
- inline Storage& get(int x, int y) {
- return const_cast<Storage&>(const_cast<const Type*>(this)->get(x, y));
-# ifndef G3D_WIN32
- // gcc gives a useless warning that the above code might reach the end of the function;
- // we use this line to supress the warning.
- return ZERO;
-# endif
- }
-
- inline Storage& get(const Vector2int16& p) {
- return get(p.x, p.y);
- }
-
- /** Sets the changed flag to true */
- inline void set(const Vector2int16& p, const Storage& v) {
- set(p.x, p.y, v);
- }
-
- /** Sets the changed flag to true */
- void set(int x, int y, const Storage& v, WrapMode wrap) {
- setChanged(true);
- if (((uint32)x < w) && ((uint32)y < h)) {
- // In bounds, wrapping isn't an issue.
- data[x + y * w] = v;
- } else {
- const_cast<Storage&>(slowGet(x, y, wrap)) = v;
- }
- }
-
- void set(int x, int y, const Storage& v) {
- set(x, y, v, _wrapMode);
- }
-
-
- void setAll(const Storage& v) {
- for(int i = 0; i < data.size(); ++i) {
- data[i] = v;
- }
- setChanged(true);
- }
-
- /** flips if @a flip is true*/
- void maybeFlipVertical(bool flip) {
- if (flip) {
- flipVertical();
- }
- }
-
- virtual void flipVertical() {
- int halfHeight = h/2;
- Storage* d = data.getCArray();
- for (int y = 0; y < halfHeight; ++y) {
- int o1 = y * w;
- int o2 = (h - y - 1) * w;
- for (int x = 0; x < (int)w; ++x) {
- int i1 = o1 + x;
- int i2 = o2 + x;
- Storage temp = d[i1];
- d[i1] = d[i2];
- d[i2] = temp;
- }
- }
- setChanged(true);
- }
-
- virtual void flipHorizontal() {
- int halfWidth = w / 2;
- Storage* d = data.getCArray();
- for (int x = 0; x < halfWidth; ++x) {
- for (int y = 0; y < (int)h; ++y) {
- int i1 = y * w + x;
- int i2 = y * w + (w - x - 1);
- Storage temp = d[i1];
- d[i1] = d[i2];
- d[i2] = temp;
- }
- }
- setChanged(true);
- }
-
- /**
- Crops this map so that it only contains pixels between (x, y) and (x + w - 1, y + h - 1) inclusive.
- */
- virtual void crop(int newX, int newY, int newW, int newH) {
- alwaysAssertM(newX + newW <= (int)w, "Cannot grow when cropping");
- alwaysAssertM(newY + newH <= (int)h, "Cannot grow when cropping");
- alwaysAssertM(newX >= 0 && newY >= 0, "Origin out of bounds.");
-
- // Always safe to copy towards the upper left, provided
- // that we're iterating towards the lower right. This lets us avoid
- // reallocating the underlying array.
- for (int y = 0; y < newH; ++y) {
- for (int x = 0; x < newW; ++x) {
- data[x + y * newW] = data[(x + newX) + (y + newY) * w];
- }
- }
-
- resize(newW, newH);
- }
-
- /** iRounds to the nearest x0 and y0. */
- virtual void crop(const Rect2D& rect) {
- crop(iRound(rect.x0()), iRound(rect.y0()), iRound(rect.x1()) - iRound(rect.x0()), iRound(rect.y1()) - iRound(rect.y0()));
- }
-
- /** Returns the nearest neighbor. Pixel values are considered
- to be at the upper left corner, so <code>image->nearest(x, y) == image(x, y)</code>
- */
- inline Compute nearest(float x, float y, WrapMode wrap) const {
- int ix = iRound(x);
- int iy = iRound(y);
- return Compute(get(ix, iy, wrap));
- }
-
- inline Compute nearest(float x, float y) const {
- return nearest(x, y, _wrapMode);
- }
-
- inline Compute nearest(const Vector2& p) const {
- return nearest(p.x, p.y);
- }
-
- /** Returns the average value of all elements of the map */
- Compute average() const {
- if ((w == 0) || (h == 0)) {
- return ZERO;
- }
-
- // To avoid overflows, compute the average of row averages
-
- Compute rowSum = ZERO;
- for (unsigned int y = 0; y < h; ++y) {
- Compute sum = ZERO;
- int offset = y * w;
- for (unsigned int x = 0; x < w; ++x) {
- sum += Compute(data[offset + x]);
- }
- rowSum += sum * (1.0f / w);
- }
-
- return rowSum * (1.0f / h);
- }
-
- /**
- Needs to access elements from (floor(x), floor(y))
- to (floor(x) + 1, floor(y) + 1) and will use
- the wrap mode appropriately (possibly generating
- out of bounds errors).
-
- Guaranteed to match nearest(x, y) at integers. */
- Compute bilinear(float x, float y, WrapMode wrap) const {
- const int i = iFloor(x);
- const int j = iFloor(y);
-
- const float fX = x - i;
- const float fY = y - j;
-
- // Horizontal interpolation, first row
- const Compute& t0 = get(i, j, wrap);
- const Compute& t1 = get(i + 1, j, wrap);
-
- // Horizontal interpolation, second row
- const Compute& t2 = get(i, j + 1, wrap);
- const Compute& t3 = get(i + 1, j + 1, wrap);
-
- const Compute& A = lerp(t0, t1, fX);
- const Compute& B = lerp(t2, t3, fX);
-
- // Vertical interpolation
- return lerp(A, B, fY);
- }
-
- Compute bilinear(float x, float y) const {
- return bilinear(x, y, _wrapMode);
- }
-
- inline Compute bilinear(const Vector2& p) const {
- return bilinear(p.x, p.y, _wrapMode);
- }
-
- inline Compute bilinear(const Vector2& p, WrapMode wrap) const {
- return bilinear(p.x, p.y, wrap);
- }
-
- /**
- Uses Catmull-Rom splines to interpolate between grid
- values. Guaranteed to match nearest(x, y) at integers.
- */
- Compute bicubic(float x, float y, WrapMode wrap) const {
- int i = iFloor(x);
- int j = iFloor(y);
- float fX = x - i;
- float fY = y - j;
-
- Compute vsample[4];
- for (int v = 0; v < 4; ++v) {
-
- // Horizontal interpolation
- Compute hsample[4];
- for (int u = 0; u < 4; ++u) {
- hsample[u] = Compute(get(i + u - 1, j + v - 1, wrap));
- }
-
- vsample[v] = bicubic(hsample, fX);
- }
-
- // Vertical interpolation
- return bicubic(vsample, fY);
- }
-
- Compute bicubic(float x, float y) const {
- return bicubic(x, y, _wrapMode);
- }
-
- inline Compute bicubic(const Vector2& p, WrapMode wrap) const {
- return bicubic(p.x, p.y, wrap);
- }
-
- inline Compute bicubic(const Vector2& p) const {
- return bicubic(p.x, p.y, _wrapMode);
- }
-
- /** Pixel width */
- inline int32 width() const {
- return (int32)w;
- }
-
-
- /** Pixel height */
- inline int32 height() const {
- return (int32)h;
- }
-
-
- /** Dimensions in pixels */
- Vector2int16 size() const {
- return Vector2int16(w, h);
- }
-
- /** Rectangle from (0, 0) to (w, h) */
- Rect2D rect2DBounds() const {
- return Rect2D::xywh(0, 0, w, h);
- }
-
- /** Number of bytes occupied by the image data and this structure */
- size_t sizeInMemory() const {
- return data.size() * sizeof(Storage) + sizeof(*this);
- }
-
-
- WrapMode wrapMode() const {
- return _wrapMode;
- }
-
-
- void setWrapMode(WrapMode m) {
- _wrapMode = m;
- }
-};
-
-
-
-}
-
-#endif // G3D_IMAGE_H
diff --git a/externals/g3dlite/G3D/Matrix.h b/externals/g3dlite/G3D/Matrix.h
deleted file mode 100644
index 3c5394d9a76..00000000000
--- a/externals/g3dlite/G3D/Matrix.h
+++ /dev/null
@@ -1,634 +0,0 @@
-/**
- @file Matrix.h
- @author Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2005-10-23
- @edited 2007-07-18
- */
-
-#ifndef G3D_MATRIX_H
-#define G3D_MATRIX_H
-
-#include "G3D/g3dmath.h"
-#include "G3D/Vector3.h"
-#include "G3D/Vector4.h"
-#include "G3D/Matrix3.h"
-#include "G3D/Matrix4.h"
-#include "G3D/ReferenceCount.h"
-
-namespace G3D {
-
-/**
- N x M matrix.
-
- The actual data is tracked internally by a reference counted pointer;
- it is efficient to pass and assign Matrix objects because no data is actually copied.
- This avoids the headache of pointers and allows natural math notation:
-
- <PRE>
- Matrix A, B, C;
- // ...
-
- C = A * f(B);
- C = C.inverse();
-
- A = Matrix::identity(4);
- C = A;
- C.set(0, 0, 2.0); // Triggers a copy of the data so that A remains unchanged.
-
- // etc.
-
- </PRE>
-
- The Matrix::debugNumCopyOps and Matrix::debugNumAllocOps counters
- increment every time an operation forces the copy and allocation of matrices. You
- can use these to detect slow operations when efficiency is a major concern.
-
- Some methods accept an output argument instead of returning a value. For example,
- <CODE>A = B.transpose()</CODE> can also be invoked as <CODE>B.transpose(A)</CODE>.
- The latter may be more efficient, since Matrix may be able to re-use the storage of
- A (if it has approximatly the right size and isn't currently shared with another matrix).
-
- @sa G3D::Matrix3, G3D::Matrix4, G3D::Vector2, G3D::Vector3, G3D::Vector4, G3D::CoordinateFrame
-
- @beta
- */
-class Matrix {
-public:
- /**
- Internal precision. Currently float, but this may become a templated class in the future
- to allow operations like Matrix<double> and Matrix<ComplexFloat>.
-
- Not necessarily a plain-old-data type (e.g., could ComplexFloat), but must be something
- with no constructor, that can be safely memcpyd, and that has a bit pattern of all zeros
- when zero.*/
- typedef float T;
-
- /** Incremented every time the elements of a matrix are copied. Useful for profiling your
- own code that uses Matrix to determine when it is slow due to copying.*/
- static int debugNumCopyOps;
-
- /** Incremented every time a new matrix object is allocated. Useful for profiling your
- own code that uses Matrix to determine when it is slow due to allocation.*/
- static int debugNumAllocOps;
-
-private:
-public:
-
- /** Used internally by Matrix.
-
- Does not throw exceptions-- assumes the caller has taken care of
- argument checking. */
- class Impl : public ReferenceCountedObject {
- public:
-
- static void* operator new(size_t size) {
- return System::malloc(size);
- }
-
- static void operator delete(void* p) {
- System::free(p);
- }
-
- ~Impl();
-
- private:
- friend class Matrix;
-
- /** elt[r][c] = the element. Pointers into data.*/
- T** elt;
-
- /** Row major data for the entire matrix. */
- T* data;
-
- /** The number of rows */
- int R;
-
- /** The number of columns */
- int C;
-
- int dataSize;
-
- /** If R*C is much larger or smaller than the current, deletes all previous data
- and resets to random data. Otherwise re-uses existing memory and just resets
- R, C, and the row pointers. */
- void setSize(int newRows, int newCols);
-
- inline Impl() : elt(NULL), data(NULL), R(0), C(0), dataSize(0) {}
-
- Impl(const Matrix3& M);
-
- Impl(const Matrix4& M);
-
- inline Impl(int r, int c) : elt(NULL), data(NULL), R(0), C(0), dataSize(0) {
- setSize(r, c);
- }
-
- Impl& operator=(const Impl& m);
-
- inline Impl(const Impl& B) : elt(NULL), data(NULL), R(0), C(0), dataSize(0) {
- // Use the assignment operator
- *this = B;
- }
-
- void setZero();
-
- inline void set(int r, int c, T v) {
- debugAssert(r < R);
- debugAssert(c < C);
- elt[r][c] = v;
- }
-
- inline const T& get(int r, int c) const {
- debugAssert(r < R);
- debugAssert(c < C);
- return elt[r][c];
- }
-
- /** Multiplies this by B and puts the result in out. */
- void mul(const Impl& B, Impl& out) const;
-
- /** Ok if out == this or out == B */
- void add(const Impl& B, Impl& out) const;
-
- /** Ok if out == this or out == B */
- void add(T B, Impl& out) const;
-
- /** Ok if out == this or out == B */
- void sub(const Impl& B, Impl& out) const;
-
- /** Ok if out == this or out == B */
- void sub(T B, Impl& out) const;
-
- /** B - this */
- void lsub(T B, Impl& out) const;
-
- /** Ok if out == this or out == B */
- void arrayMul(const Impl& B, Impl& out) const;
-
- /** Ok if out == this or out == B */
- void mul(T B, Impl& out) const;
-
- /** Ok if out == this or out == B */
- void arrayDiv(const Impl& B, Impl& out) const;
-
- /** Ok if out == this or out == B */
- void div(T B, Impl& out) const;
-
- void negate(Impl& out) const;
-
- /** Slow way of computing an inverse; for reference */
- void inverseViaAdjoint(Impl& out) const;
-
- /** Use Gaussian elimination with pivots to solve for the inverse destructively in place. */
- void inverseInPlaceGaussJordan();
-
- void adjoint(Impl& out) const;
-
- /** Matrix of all cofactors */
- void cofactor(Impl& out) const;
-
- /**
- Cofactor [r][c] is defined as C[r][c] = -1 ^(r+c) * det(A[r][c]),
- where A[r][c] is the (R-1)x(C-1) matrix formed by removing row r and
- column c from the original matrix.
- */
- T cofactor(int r, int c) const;
-
- /** Ok if out == this or out == B */
- void transpose(Impl& out) const;
-
- T determinant() const;
-
- /** Determinant computed without the given row and column */
- T determinant(int r, int c) const;
-
- void arrayLog(Impl& out) const;
-
- void arrayExp(Impl& out) const;
-
- void arraySqrt(Impl& out) const;
-
- void arrayCos(Impl& out) const;
-
- void arraySin(Impl& out) const;
-
- void swapRows(int r0, int r1);
-
- void swapAndNegateCols(int c0, int c1);
-
- void mulRow(int r, const T& v);
-
- void abs(Impl& out) const;
-
- /** Makes a (R-1)x(C-1) copy of this matrix */
- void withoutRowAndCol(int excludeRow, int excludeCol, Impl& out) const;
-
- bool anyNonZero() const;
-
- bool allNonZero() const;
-
- void setRow(int r, const T* vals);
-
- void setCol(int c, const T* vals);
- };
-private:
-
- typedef ReferenceCountedPointer<Impl> ImplRef;
-
- ImplRef impl;
-
- inline Matrix(ImplRef i) : impl(i) {}
- inline Matrix(Impl* i) : impl(ImplRef(i)) {}
-
- /** Used by SVD */
- class SortRank {
- public:
- T value;
- int col;
-
- inline bool operator>(const SortRank& x) const {
- return x.value > value;
- }
-
- inline bool operator<(const SortRank& x) const {
- return x.value < value;
- }
-
- inline bool operator>=(const SortRank& x) const {
- return x.value >= value;
- }
-
- inline bool operator<=(const SortRank& x) const {
- return x.value <= value;
- }
-
- inline bool operator==(const SortRank& x) const {
- return x.value == value;
- }
-
- inline bool operator!=(const SortRank& x) const {
- return x.value != value;
- }
- };
-
- Matrix vectorPseudoInverse() const;
- Matrix partitionPseudoInverse() const;
- Matrix colPartPseudoInverse() const;
- Matrix rowPartPseudoInverse() const;
-
- Matrix col2PseudoInverse(const Matrix& B) const;
- Matrix col3PseudoInverse(const Matrix& B) const;
- Matrix col4PseudoInverse(const Matrix& B) const;
- Matrix row2PseudoInverse(const Matrix& B) const;
- Matrix row3PseudoInverse(const Matrix& B) const;
- Matrix row4PseudoInverse(const Matrix& B) const;
-
-public:
-
- Matrix() : impl(new Impl(0, 0)) {}
-
- Matrix(const Matrix3& M) : impl(new Impl(M)) {}
-
- Matrix(const Matrix4& M) : impl(new Impl(M)) {}
-
- template<class S>
- static Matrix fromDiagonal(const Array<S>& d) {
- Matrix D = zero(d.length(), d.length());
- for (int i = 0; i < d.length(); ++i) {
- D.set(i, i, d[i]);
- }
- return D;
- }
-
- static Matrix fromDiagonal(const Matrix& d);
-
- /** Returns a new matrix that is all zero. */
- Matrix(int R, int C) : impl(new Impl(R, C)) {
- impl->setZero();
- }
-
- /** Returns a new matrix that is all zero. */
- static Matrix zero(int R, int C);
-
- /** Returns a new matrix that is all one. */
- static Matrix one(int R, int C);
-
- /** Returns a new identity matrix */
- static Matrix identity(int N);
-
- /** Uniformly distributed values between zero and one. */
- static Matrix random(int R, int C);
-
- /** The number of rows */
- inline int rows() const {
- return impl->R;
- }
-
- /** Number of columns */
- inline int cols() const {
- return impl->C;
- }
-
- /** Generally more efficient than A * B */
- Matrix& operator*=(const T& B);
-
- /** Generally more efficient than A / B */
- Matrix& operator/=(const T& B);
-
- /** Generally more efficient than A + B */
- Matrix& operator+=(const T& B);
-
- /** Generally more efficient than A - B */
- Matrix& operator-=(const T& B);
-
- /** No performance advantage over A * B because
- matrix multiplication requires intermediate
- storage. */
- Matrix& operator*=(const Matrix& B);
-
- /** Generally more efficient than A + B */
- Matrix& operator+=(const Matrix& B);
-
- /** Generally more efficient than A - B */
- Matrix& operator-=(const Matrix& B);
-
- /** Returns a new matrix that is a subset of this one,
- from r1:r2 to c1:c2, inclusive.*/
- Matrix subMatrix(int r1, int r2, int c1, int c2) const;
-
- /** Matrix multiplication. To perform element-by-element multiplication,
- see arrayMul. */
- inline Matrix operator*(const Matrix& B) const {
- Matrix C(impl->R, B.impl->C);
- impl->mul(*B.impl, *C.impl);
- return C;
- }
-
- /** See also A *= B, which is more efficient in many cases */
- inline Matrix operator*(const T& B) const {
- Matrix C(impl->R, impl->C);
- impl->mul(B, *C.impl);
- return C;
- }
-
- /** See also A += B, which is more efficient in many cases */
- inline Matrix operator+(const Matrix& B) const {
- Matrix C(impl->R, impl->C);
- impl->add(*B.impl, *C.impl);
- return C;
- }
-
- /** See also A -= B, which is more efficient in many cases */
- inline Matrix operator-(const Matrix& B) const {
- Matrix C(impl->R, impl->C);
- impl->sub(*B.impl, *C.impl);
- return C;
- }
-
- /** See also A += B, which is more efficient in many cases */
- inline Matrix operator+(const T& v) const {
- Matrix C(impl->R, impl->C);
- impl->add(v, *C.impl);
- return C;
- }
-
- /** See also A -= B, which is more efficient in many cases */
- inline Matrix operator-(const T& v) const {
- Matrix C(impl->R, impl->C);
- impl->sub(v, *C.impl);
- return C;
- }
-
-
- Matrix operator>(const T& scalar) const;
-
- Matrix operator<(const T& scalar) const;
-
- Matrix operator>=(const T& scalar) const;
-
- Matrix operator<=(const T& scalar) const;
-
- Matrix operator==(const T& scalar) const;
-
- Matrix operator!=(const T& scalar) const;
-
- /** scalar B - this */
- inline Matrix lsub(const T& B) const {
- Matrix C(impl->R, impl->C);
- impl->lsub(B, *C.impl);
- return C;
- }
-
- inline Matrix arrayMul(const Matrix& B) const {
- Matrix C(impl->R, impl->C);
- impl->arrayMul(*B.impl, *C.impl);
- return C;
- }
-
- Matrix3 toMatrix3() const;
-
- Matrix4 toMatrix4() const;
-
- Vector2 toVector2() const;
-
- Vector3 toVector3() const;
-
- Vector4 toVector4() const;
-
- /** Mutates this */
- void arrayMulInPlace(const Matrix& B);
-
- /** Mutates this */
- void arrayDivInPlace(const Matrix& B);
-
- // Declares an array unary method and its explicit-argument counterpart
-# define DECLARE_METHODS_1(method)\
- inline Matrix method() const {\
- Matrix C(impl->R, impl->C);\
- impl->method(*C.impl);\
- return C;\
- }\
- void method(Matrix& out) const;
-
-
- DECLARE_METHODS_1(abs)
- DECLARE_METHODS_1(arrayLog)
- DECLARE_METHODS_1(arrayExp)
- DECLARE_METHODS_1(arraySqrt)
- DECLARE_METHODS_1(arrayCos)
- DECLARE_METHODS_1(arraySin)
- DECLARE_METHODS_1(negate)
-
-# undef DECLARE_METHODS_1
-
- inline Matrix operator-() const {
- return negate();
- }
-
- /**
- A<SUP>-1</SUP> computed using the Gauss-Jordan algorithm,
- for square matrices.
- Run time is <I>O(R<sup>3</sup>)</I>, where <I>R</i> is the
- number of rows.
- */
- inline Matrix inverse() const {
- Impl* A = new Impl(*impl);
- A->inverseInPlaceGaussJordan();
- return Matrix(A);
- }
-
- inline T determinant() const {
- return impl->determinant();
- }
-
- /**
- A<SUP>T</SUP>
- */
- inline Matrix transpose() const {
- Impl* A = new Impl(cols(), rows());
- impl->transpose(*A);
- return Matrix(A);
- }
-
- /** Transpose in place; more efficient than transpose */
- void transpose(Matrix& out) const;
-
- inline Matrix adjoint() const {
- Impl* A = new Impl(cols(), rows());
- impl->adjoint(*A);
- return Matrix(A);
- }
-
- /**
- (A<SUP>T</SUP>A)<SUP>-1</SUP>A<SUP>T</SUP>) computed
- using SVD.
-
- @param tolerance Use -1 for automatic tolerance.
- */
- Matrix pseudoInverse(float tolerance = -1) const;
-
- /** Called from pseudoInverse when the matrix has size > 4 along some dimension.*/
- Matrix svdPseudoInverse(float tolerance = -1) const;
-
- /**
- (A<SUP>T</SUP>A)<SUP>-1</SUP>A<SUP>T</SUP>) computed
- using Gauss-Jordan elimination.
- */
- inline Matrix gaussJordanPseudoInverse() const {
- Matrix trans = transpose();
- return (trans * (*this)).inverse() * trans;
- }
-
- /** Singular value decomposition. Factors into three matrices
- such that @a this = @a U * fromDiagonal(@a d) * @a V.transpose().
-
- The matrix must have at least as many rows as columns.
-
- Run time is <I>O(C<sup>2</sup>*R)</I>.
-
- @param sort If true (default), the singular values
- are arranged so that D is sorted from largest to smallest.
- */
- void svd(Matrix& U, Array<T>& d, Matrix& V, bool sort = true) const;
-
- void set(int r, int c, T v);
-
- void setCol(int c, const Matrix& vec);
-
- void setRow(int r, const Matrix& vec);
-
- Matrix col(int c) const;
-
- Matrix row(int r) const;
-
- T get(int r, int c) const;
-
- Vector2int16 size() const {
- return Vector2int16(rows(), cols());
- }
-
- int numElements() const {
- return rows() * cols();
- }
-
- void swapRows(int r0, int r1);
-
- /** Swaps columns c0 and c1 and negates both */
- void swapAndNegateCols(int c0, int c1);
-
- void mulRow(int r, const T& v);
-
- /** Returns true if any element is non-zero */
- bool anyNonZero() const;
-
- /** Returns true if all elements are non-zero */
- bool allNonZero() const;
-
- inline bool allZero() const {
- return !anyNonZero();
- }
-
- inline bool anyZero() const {
- return !allNonZero();
- }
-
- /** Serializes in Matlab source format */
- void serialize(TextOutput& t) const;
-
- std::string toString(const std::string& name) const;
-
- std::string toString() const {
- static const std::string name = "";
- return toString(name);
- }
-
- /** 2-norm squared: sum(squares). (i.e., dot product with itself) */
- double normSquared() const;
-
- /** 2-norm (sqrt(sum(squares)) */
- double norm() const;
-
- /**
- Low-level SVD functionality. Useful for applications that do not want
- to construct a Matrix but need to perform the SVD operation.
-
- this = U * D * V'
-
- Assumes that rows >= cols
-
- @return NULL on success, a string describing the error on failure.
- @param U rows x cols matrix to be decomposed, gets overwritten with U, a rows x cols matrix with orthogonal columns.
- @param D vector of singular values of a (diagonal of the D matrix). Length cols.
- @param V returns the right orthonormal transformation matrix, size cols x cols
-
- @cite Based on Dianne Cook's implementation, which is adapted from
- svdecomp.c in XLISP-STAT 2.1, which is code from Numerical Recipes
- adapted by Luke Tierney and David Betz. The Numerical Recipes code
- is adapted from Forsythe et al, who based their code on Golub and
- Reinsch's original implementation.
- */
- static const char* svdCore(float** U, int rows, int cols, float* D, float** V);
-
-};
-
-}
-
-inline G3D::Matrix operator-(const G3D::Matrix::T& v, const G3D::Matrix& M) {
- return M.lsub(v);
-}
-
-inline G3D::Matrix operator*(const G3D::Matrix::T& v, const G3D::Matrix& M) {
- return M * v;
-}
-
-inline G3D::Matrix operator+(const G3D::Matrix::T& v, const G3D::Matrix& M) {
- return M + v;
-}
-
-inline G3D::Matrix abs(const G3D::Matrix& M) {
- return M.abs();
-}
-
-#endif
-
diff --git a/externals/g3dlite/G3D/Matrix2.h b/externals/g3dlite/G3D/Matrix2.h
deleted file mode 100644
index eaf4aefa220..00000000000
--- a/externals/g3dlite/G3D/Matrix2.h
+++ /dev/null
@@ -1,69 +0,0 @@
-#ifndef G3D_MATRIX2_H
-#define G3D_MATRIX2_H
-
-#include "G3D/platform.h"
-#include "G3D/Vector2.h"
-
-namespace G3D {
-
-/** @beta */
-class Matrix2 {
-private:
-
- float data[2][2];
-
-public:
-
- inline Matrix2() {
- data[0][0] = 1.0f; data[0][1] = 0.0f;
- data[1][0] = 0.0f; data[1][1] = 1.0f;
- }
-
- inline Matrix2(float v00, float v01, float v10, float v11) {
- data[0][0] = v00; data[0][1] = v01;
- data[1][0] = v10; data[1][1] = v11;
- }
-
- inline Vector2 operator*(const Vector2& v) const {
- return Vector2(data[0][0] * v[0] + data[0][1] * v[1],
- data[1][0] * v[0] + data[1][1] * v[1]);
- }
-
- inline Matrix2 inverse() const {
- return Matrix2(data[0][0], data[1][0],
- data[0][1], data[1][1]) * (1.0f / determinant());
- }
-
- inline Matrix2 transpose() const {
- return Matrix2(data[0][0], data[1][0],
- data[0][1], data[1][1]);
- }
-
- inline float determinant() const {
- return data[0][0] * data[1][1] - data[0][1] * data[1][0];
- }
-
- inline Matrix2 operator*(float f) const {
- return Matrix2(data[0][0] * f, data[0][1] * f,
- data[1][0] * f, data[1][1] * f);
- }
-
- inline Matrix2 operator/(float f) const {
- return Matrix2(data[0][0] / f, data[0][1] / f,
- data[1][0] / f, data[1][1] / f);
- }
-
- inline float* operator[](int i) {
- debugAssert(i >= 0 && i <= 2);
- return data[i];
- }
-
- inline const float* operator[](int i) const {
- debugAssert(i >= 0 && i <= 1);
- return data[i];
- }
-};
-
-}
-
-#endif
diff --git a/externals/g3dlite/G3D/Matrix3.h b/externals/g3dlite/G3D/Matrix3.h
deleted file mode 100644
index 06ec7e67474..00000000000
--- a/externals/g3dlite/G3D/Matrix3.h
+++ /dev/null
@@ -1,366 +0,0 @@
-/**
- @file Matrix3.h
-
- 3x3 matrix class
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @cite Portions based on Dave Eberly's Magic Software Library at <A HREF="http://www.magic-software.com">http://www.magic-software.com</A>
-
- @created 2001-06-02
- @edited 2006-04-05
- */
-
-#ifndef G3D_Matrix3_h
-#define G3D_Matrix3_h
-
-#include "G3D/platform.h"
-#include "G3D/Vector3.h"
-#include "G3D/Vector4.h"
-#include "G3D/debugAssert.h"
-
-#include <cstring>
-
-namespace G3D {
-
-#ifdef _MSC_VER
-// Turn off "conditional expression is constant" warning; MSVC generates this
-// for debug assertions in inlined methods.
-# pragma warning (disable : 4127)
-#endif
-
-class Any;
-
-/**
- 3x3 matrix. Do not subclass.
- */
-class Matrix3 {
-private:
-
- float elt[3][3];
-
- // Hidden operators
- bool operator<(const Matrix3&) const;
- bool operator>(const Matrix3&) const;
- bool operator<=(const Matrix3&) const;
- bool operator>=(const Matrix3&) const;
-
-public:
-
- Matrix3(const Any& any);
-
- operator Any() const;
-
- /** Initial values are undefined for performance. See also
- Matrix3::zero(), Matrix3::identity(), Matrix3::fromAxisAngle, etc.*/
- inline Matrix3() {}
-
- Matrix3 (class BinaryInput& b);
- Matrix3 (const float aafEntry[3][3]);
- Matrix3 (const Matrix3& rkMatrix);
- Matrix3 (float fEntry00, float fEntry01, float fEntry02,
- float fEntry10, float fEntry11, float fEntry12,
- float fEntry20, float fEntry21, float fEntry22);
-
- bool fuzzyEq(const Matrix3& b) const;
-
- /** Constructs a matrix from a quaternion.
- @cite Graphics Gems II, p. 351--354
- @cite Implementation from Watt and Watt, pg 362*/
- Matrix3(const class Quat& q);
-
- void serialize(class BinaryOutput& b) const;
- void deserialize(class BinaryInput& b);
-
- /** Returns true if column(0).cross(column(1)).dot(column(2)) > 0. */
- bool isRightHanded() const;
-
- /**
- Sets all elements.
- */
- void set(float fEntry00, float fEntry01, float fEntry02,
- float fEntry10, float fEntry11, float fEntry12,
- float fEntry20, float fEntry21, float fEntry22);
-
- /**
- * member access, allows use of construct mat[r][c]
- */
- inline float* operator[] (int iRow) {
- debugAssert(iRow >= 0);
- debugAssert(iRow < 3);
- return (float*)&elt[iRow][0];
- }
-
- inline const float* operator[] (int iRow) const {
- debugAssert(iRow >= 0);
- debugAssert(iRow < 3);
- return (const float*)&elt[iRow][0];
- }
-
- inline operator float* () {
- return (float*)&elt[0][0];
- }
-
- inline operator const float* () const{
- return (const float*)&elt[0][0];
- }
-
- Vector3 column(int c) const;
- const Vector3& row(int r) const;
-
- void setColumn(int iCol, const Vector3 &vector);
- void setRow(int iRow, const Vector3 &vector);
-
- // assignment and comparison
- inline Matrix3& operator= (const Matrix3& rkMatrix) {
- memcpy(elt, rkMatrix.elt, 9 * sizeof(float));
- return *this;
- }
-
- bool operator== (const Matrix3& rkMatrix) const;
- bool operator!= (const Matrix3& rkMatrix) const;
-
- // arithmetic operations
- Matrix3 operator+ (const Matrix3& rkMatrix) const;
- Matrix3 operator- (const Matrix3& rkMatrix) const;
- /** Matrix-matrix multiply */
- Matrix3 operator* (const Matrix3& rkMatrix) const;
- Matrix3 operator- () const;
-
- Matrix3& operator+= (const Matrix3& rkMatrix);
- Matrix3& operator-= (const Matrix3& rkMatrix);
- Matrix3& operator*= (const Matrix3& rkMatrix);
-
- /**
- * matrix * vector [3x3 * 3x1 = 3x1]
- */
- inline Vector3 operator* (const Vector3& v) const {
- Vector3 kProd;
-
- for (int r = 0; r < 3; ++r) {
- kProd[r] =
- elt[r][0] * v[0] +
- elt[r][1] * v[1] +
- elt[r][2] * v[2];
- }
-
- return kProd;
- }
-
-
- /**
- * vector * matrix [1x3 * 3x3 = 1x3]
- */
- friend Vector3 operator* (const Vector3& rkVector,
- const Matrix3& rkMatrix);
-
- /**
- * matrix * scalar
- */
- Matrix3 operator* (float fScalar) const;
-
- /** scalar * matrix */
- friend Matrix3 operator* (double fScalar, const Matrix3& rkMatrix);
- friend Matrix3 operator* (float fScalar, const Matrix3& rkMatrix);
- friend Matrix3 operator* (int fScalar, const Matrix3& rkMatrix);
-
- Matrix3& operator*= (float k);
- Matrix3& operator/= (float k);
-
-
-private:
- /** Multiplication where out != A and out != B */
- static void _mul(const Matrix3& A, const Matrix3& B, Matrix3& out);
-public:
-
- /** Optimized implementation of out = A * B. It is safe (but slow) to call
- with A, B, and out possibly pointer equal to one another.*/
- // This is a static method so that it is not ambiguous whether "this"
- // is an input or output argument.
- inline static void mul(const Matrix3& A, const Matrix3& B, Matrix3& out) {
- if ((&out == &A) || (&out == &B)) {
- // We need a temporary anyway, so revert to the stack method.
- out = A * B;
- } else {
- // Optimized in-place multiplication.
- _mul(A, B, out);
- }
- }
-
-private:
- static void _transpose(const Matrix3& A, Matrix3& out);
-public:
-
- /** Optimized implementation of out = A.transpose(). It is safe (but slow) to call
- with A and out possibly pointer equal to one another.
-
- Note that <CODE>A.transpose() * v</CODE> can be computed
- more efficiently as <CODE>v * A</CODE>.
- */
- inline static void transpose(const Matrix3& A, Matrix3& out) {
- if (&A == &out) {
- out = A.transpose();
- } else {
- _transpose(A, out);
- }
- }
-
- /** Returns true if the rows and column L2 norms are 1.0 and the rows are orthogonal. */
- bool isOrthonormal() const;
-
- Matrix3 transpose () const;
- bool inverse (Matrix3& rkInverse, float fTolerance = 1e-06) const;
- Matrix3 inverse (float fTolerance = 1e-06) const;
- float determinant () const;
-
- /** singular value decomposition */
- void singularValueDecomposition (Matrix3& rkL, Vector3& rkS,
- Matrix3& rkR) const;
- /** singular value decomposition */
- void singularValueComposition (const Matrix3& rkL,
- const Vector3& rkS, const Matrix3& rkR);
-
- /** Gram-Schmidt orthonormalization (applied to columns of rotation matrix) */
- void orthonormalize();
-
- /** orthogonal Q, diagonal D, upper triangular U stored as (u01,u02,u12) */
- void qDUDecomposition (Matrix3& rkQ, Vector3& rkD,
- Vector3& rkU) const;
-
- /**
- Polar decomposition of a matrix. Based on pseudocode from Nicholas J
- Higham, "Computing the Polar Decomposition -- with Applications Siam
- Journal of Science and Statistical Computing, Vol 7, No. 4, October
- 1986.
-
- Decomposes A into R*S, where R is orthogonal and S is symmetric.
-
- Ken Shoemake's "Matrix animation and polar decomposition"
- in Proceedings of the conference on Graphics interface '92
- seems to be better known in the world of graphics, but Higham's version
- uses a scaling constant that can lead to faster convergence than
- Shoemake's when the initial matrix is far from orthogonal.
- */
- void polarDecomposition(Matrix3 &R, Matrix3 &S) const;
-
- /**
- * Matrix norms.
- */
- float spectralNorm () const;
-
- float squaredFrobeniusNorm() const;
-
- float frobeniusNorm() const;
-
- float l1Norm() const;
-
- float lInfNorm() const;
-
- float diffOneNorm(const Matrix3 &y) const;
-
- /** matrix must be orthonormal */
- void toAxisAngle(Vector3& rkAxis, float& rfRadians) const;
-
- static Matrix3 fromDiagonal(const Vector3& d) {
- return Matrix3(d.x, 0, 0,
- 0, d.y, 0,
- 0, 0, d.z);
- }
-
- static Matrix3 fromAxisAngle(const Vector3& rkAxis, float fRadians);
-
- /**
- * The matrix must be orthonormal. The decomposition is yaw*pitch*roll
- * where yaw is rotation about the Up vector, pitch is rotation about the
- * right axis, and roll is rotation about the Direction axis.
- */
- bool toEulerAnglesXYZ (float& rfYAngle, float& rfPAngle,
- float& rfRAngle) const;
- bool toEulerAnglesXZY (float& rfYAngle, float& rfPAngle,
- float& rfRAngle) const;
- bool toEulerAnglesYXZ (float& rfYAngle, float& rfPAngle,
- float& rfRAngle) const;
- bool toEulerAnglesYZX (float& rfYAngle, float& rfPAngle,
- float& rfRAngle) const;
- bool toEulerAnglesZXY (float& rfYAngle, float& rfPAngle,
- float& rfRAngle) const;
- bool toEulerAnglesZYX (float& rfYAngle, float& rfPAngle,
- float& rfRAngle) const;
- static Matrix3 fromEulerAnglesXYZ (float fYAngle, float fPAngle, float fRAngle);
- static Matrix3 fromEulerAnglesXZY (float fYAngle, float fPAngle, float fRAngle);
- static Matrix3 fromEulerAnglesYXZ (float fYAngle, float fPAngle, float fRAngle);
- static Matrix3 fromEulerAnglesYZX (float fYAngle, float fPAngle, float fRAngle);
- static Matrix3 fromEulerAnglesZXY (float fYAngle, float fPAngle, float fRAngle);
- static Matrix3 fromEulerAnglesZYX (float fYAngle, float fPAngle, float fRAngle);
-
- /** eigensolver, matrix must be symmetric */
- void eigenSolveSymmetric (float afEigenvalue[3],
- Vector3 akEigenvector[3]) const;
-
- static void tensorProduct (const Vector3& rkU, const Vector3& rkV,
- Matrix3& rkProduct);
- std::string toString() const;
-
- static const float EPSILON;
-
- // Special values.
- // The unguaranteed order of initialization of static variables across
- // translation units can be a source of annoying bugs, so now the static
- // special values (like Vector3::ZERO, Color3::WHITE, ...) are wrapped
- // inside static functions that return references to them.
- // These functions are intentionally not inlined, because:
- // "You might be tempted to write [...] them as inline functions
- // inside their respective header files, but this is something you
- // must definitely not do. An inline function can be duplicated
- // in every file in which it appears œóõ½ and this duplication
- // includes the static object definition. Because inline functions
- // automatically default to internal linkage, this would result in
- // having multiple static objects across the various translation
- // units, which would certainly cause problems. So you must
- // ensure that there is only one definition of each wrapping
- // function, and this means not making the wrapping functions inline",
- // according to Chapter 10 of "Thinking in C++, 2nd ed. Volume 1" by Bruce Eckel,
- // http://www.mindview.net/
- static const Matrix3& zero();
- static const Matrix3& identity();
-
-protected:
-
- // support for eigensolver
- void tridiagonal (float afDiag[3], float afSubDiag[3]);
- bool qLAlgorithm (float afDiag[3], float afSubDiag[3]);
-
- // support for singular value decomposition
- static const float ms_fSvdEpsilon;
- static const int ms_iSvdMaxIterations;
- static void bidiagonalize (Matrix3& kA, Matrix3& kL,
- Matrix3& kR);
- static void golubKahanStep (Matrix3& kA, Matrix3& kL,
- Matrix3& kR);
-
- // support for spectral norm
- static float maxCubicRoot (float afCoeff[3]);
-
-};
-
-
-//----------------------------------------------------------------------------
-/** <code>v * M == M.transpose() * v</code> */
-inline Vector3 operator* (const Vector3& rkPoint, const Matrix3& rkMatrix) {
- Vector3 kProd;
-
- for (int r = 0; r < 3; ++r) {
- kProd[r] =
- rkPoint[0] * rkMatrix.elt[0][r] +
- rkPoint[1] * rkMatrix.elt[1][r] +
- rkPoint[2] * rkMatrix.elt[2][r];
- }
-
- return kProd;
-}
-
-
-} // namespace
-
-#endif
-
diff --git a/externals/g3dlite/G3D/Matrix4.h b/externals/g3dlite/G3D/Matrix4.h
deleted file mode 100644
index 9ce87d875b8..00000000000
--- a/externals/g3dlite/G3D/Matrix4.h
+++ /dev/null
@@ -1,249 +0,0 @@
-/**
- @file Matrix4.h
-
- 4x4 matrix class
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2003-10-02
- @edited 2009-10-20
- */
-
-#ifndef G3D_Matrix4_h
-#define G3D_Matrix4_h
-
-#ifdef _MSC_VER
-// Disable conditional expression is constant, which occurs incorrectly on inlined functions
-# pragma warning (push)
-# pragma warning( disable : 4127 )
-#endif
-
-#include "G3D/platform.h"
-#include "G3D/debugAssert.h"
-#include "G3D/Matrix3.h"
-#include "G3D/Vector3.h"
-
-namespace G3D {
-
-class Any;
-
-/**
- A 4x4 matrix.
-
- See also G3D::CoordinateFrame, G3D::Matrix3, G3D::Quat
- */
-class Matrix4 {
-private:
-
- float elt[4][4];
-
- /**
- Computes the determinant of the 3x3 matrix that lacks excludeRow
- and excludeCol.
- */
- float subDeterminant(int excludeRow, int excludeCol) const;
-
- // Hidden operators
- bool operator<(const Matrix4&) const;
- bool operator>(const Matrix4&) const;
- bool operator<=(const Matrix4&) const;
- bool operator>=(const Matrix4&) const;
-
-public:
- /** Must be of the form: <code>Matrix4(#, #, # .... #)</code>*/
- Matrix4(const Any& any);
-
- operator Any() const;
-
- Matrix4(
- float r1c1, float r1c2, float r1c3, float r1c4,
- float r2c1, float r2c2, float r2c3, float r2c4,
- float r3c1, float r3c2, float r3c3, float r3c4,
- float r4c1, float r4c2, float r4c3, float r4c4);
-
- /**
- init should be <B>row major</B>.
- */
- Matrix4(const float* init);
-
- /**
- a is the upper left 3x3 submatrix and b is the upper right 3x1 submatrix. The last row of the created matrix is (0,0,0,1).
- */
- Matrix4(const class Matrix3& upper3x3, const class Vector3& lastCol = Vector3::zero());
-
- Matrix4(const class CoordinateFrame& c);
-
- Matrix4(const double* init);
-
- Matrix4();
-
- /** Produces an RT transformation that nearly matches this Matrix4.
- Because a Matrix4 may not be precisely a rotation and translation,
- this may introduce error. */
- class CoordinateFrame approxCoordinateFrame() const;
-
- // Special values.
- // Intentionally not inlined: see Matrix3::identity() for details.
- static const Matrix4& identity();
- static const Matrix4& zero();
-
- /** If this is a perspective projection matrix created by
- Matrix4::perspectiveProjection, extract its parameters. */
- void getPerspectiveProjectionParameters
- (float& left,
- float& right,
- float& bottom,
- float& top,
- float& nearval,
- float& farval,
- float updirection = -1.0f) const;
-
- inline float* operator[](int r) {
- debugAssert(r >= 0);
- debugAssert(r < 4);
- return (float*)&elt[r];
- }
-
- inline const float* operator[](int r) const {
- debugAssert(r >= 0);
- debugAssert(r < 4);
- return (const float*)&elt[r];
- }
-
- inline operator float* () {
- return (float*)&elt[0][0];
- }
-
- inline operator const float* () const {
- return (const float*)&elt[0][0];
- }
-
- Matrix4 operator*(const Matrix4& other) const;
-
- class Matrix3 upper3x3() const;
-
- /** Homogeneous multiplication. Let k = M * [v w]^T. result = k.xyz() / k.w */
- class Vector3 homoMul(const class Vector3& v, float w) const;
-
- /**
- Constructs an orthogonal projection matrix from the given parameters.
- Near and far are the <b>NEGATIVE</b> of the near and far plane Z values
- (to follow OpenGL conventions).
-
- \param upDirection Use -1.0 for 2D Y increasing downwards (the G3D 8.x default convention),
- 1.0 for 2D Y increasing upwards (the G3D 7.x default and OpenGL convention)
- */
- static Matrix4 orthogonalProjection(
- float left,
- float right,
- float bottom,
- float top,
- float nearval,
- float farval,
- float upDirection = -1.0f);
-
-
- /** \param upDirection Use -1.0 for 2D Y increasing downwards (the G3D 8.x default convention),
- 1.0 for 2D Y increasing upwards (the G3D 7.x default and OpenGL convention)
- */
- static Matrix4 orthogonalProjection(
- const class Rect2D& rect,
- float nearval,
- float farval,
- float upDirection = -1.0f);
-
- /** \param upDirection Use -1.0 for 2D Y increasing downwards (the G3D 8.x default convention),
- 1.0 for 2D Y increasing upwards (the G3D 7.x default and OpenGL convention)
- */
- static Matrix4 perspectiveProjection(
- float left,
- float right,
- float bottom,
- float top,
- float nearval,
- float farval,
- float upDirection = -1.0f);
-
- void setRow(int r, const class Vector4& v);
- void setColumn(int c, const Vector4& v);
-
- const Vector4& row(int r) const;
- Vector4 column(int c) const;
-
- Matrix4 operator*(const float s) const;
- Vector4 operator*(const Vector4& vector) const;
-
- Matrix4 transpose() const;
-
- bool operator!=(const Matrix4& other) const;
- bool operator==(const Matrix4& other) const;
-
- float determinant() const;
- Matrix4 inverse() const;
-
- /**
- Transpose of the cofactor matrix (used in computing the inverse).
- Note: This is in fact only one type of adjoint. More generally,
- an adjoint of a matrix is any mapping of a matrix which possesses
- certain properties. This returns the so-called adjugate
- or classical adjoint.
- */
- Matrix4 adjoint() const;
- Matrix4 cofactor() const;
-
- /** Serializes row-major */
- void serialize(class BinaryOutput& b) const;
- void deserialize(class BinaryInput& b);
-
- std::string toString() const;
-
- /** 3D scale matrix */
- inline static Matrix4 scale(const Vector3& v) {
- return Matrix4(v.x, 0, 0, 0,
- 0, v.y, 0, 0,
- 0, 0, v.z, 0,
- 0, 0, 0, 1);
- }
-
- /** 3D scale matrix */
- inline static Matrix4 scale(float x, float y, float z) {
- return scale(Vector3(x, y, z));
- }
-
- /** 3D scale matrix */
- inline static Matrix4 scale(float s) {
- return scale(s,s,s);
- }
-
- /** 3D translation matrix */
- inline static Matrix4 translation(const Vector3& v) {
- return Matrix4(Matrix3::identity(), v);
- }
-
- inline static Matrix4 translation(float x, float y, float z) {
- return Matrix4(Matrix3::identity(), Vector3(x, y, z));
- }
-
- /** Create a rotation matrix that rotates \a deg degrees around the Y axis */
- inline static Matrix4 yawDegrees(float deg) {
- return Matrix4(Matrix3::fromAxisAngle(Vector3::unitY(), toRadians(deg)));
- }
-
- inline static Matrix4 pitchDegrees(float deg) {
- return Matrix4(Matrix3::fromAxisAngle(Vector3::unitX(), toRadians(deg)));
- }
-
- inline static Matrix4 rollDegrees(float deg) {
- return Matrix4(Matrix3::fromAxisAngle(Vector3::unitZ(), toRadians(deg)));
- }
-};
-
-
-
-} // namespace
-
-#ifdef _MSC_VER
-# pragma warning (pop)
-#endif
-
-#endif
diff --git a/externals/g3dlite/G3D/MemoryManager.h b/externals/g3dlite/G3D/MemoryManager.h
deleted file mode 100644
index 15bf6d8be43..00000000000
--- a/externals/g3dlite/G3D/MemoryManager.h
+++ /dev/null
@@ -1,93 +0,0 @@
-/**
- @file MemoryManager.h
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @created 2009-04-20
- @edited 2009-04-20
-
- Copyright 2000-2009, Morgan McGuire.
- All rights reserved.
- */
-#ifndef G3D_MemoryManager_h
-#define G3D_MemoryManager_h
-
-#include "G3D/platform.h"
-#include "G3D/ReferenceCount.h"
-
-namespace G3D {
-
-/**
- Abstraction of memory management.
- Default implementation uses G3D::System::malloc and is threadsafe.
-
- \sa CRTMemoryManager, AlignedMemoryManager, AreaMemoryManager */
-class MemoryManager : public ReferenceCountedObject {
-protected:
-
- MemoryManager();
-
-public:
-
- typedef ReferenceCountedPointer<class MemoryManager> Ref;
-
- /** Return a pointer to \a s bytes of memory that are unused by
- the rest of the program. The contents of the memory are
- undefined */
- virtual void* alloc(size_t s);
-
- /** Invoke to declare that this memory will no longer be used by
- the program. The memory manager is not required to actually
- reuse or release this memory. */
- virtual void free(void* ptr);
-
- /** Returns true if this memory manager is threadsafe (i.e., alloc
- and free can be called asychronously) */
- virtual bool isThreadsafe() const;
-
- /** Return the instance. There's only one instance of the default
- MemoryManager; it is cached after the first creation. */
- static MemoryManager::Ref create();
-};
-
-/**
- Allocates memory on 16-byte boundaries.
- \sa MemoryManager, CRTMemoryManager, AreaMemoryManager */
-class AlignedMemoryManager : public MemoryManager {
-protected:
-
- AlignedMemoryManager();
-
-public:
-
- typedef ReferenceCountedPointer<class AlignedMemoryManager> Ref;
-
-
- virtual void* alloc(size_t s);
-
- virtual void free(void* ptr);
-
- virtual bool isThreadsafe() const;
-
- static AlignedMemoryManager::Ref create();
-};
-
-
-/** MemoryManager implemented using the C runtime. */
-class CRTMemoryManager : public MemoryManager {
-protected:
- CRTMemoryManager();
-
-public:
- typedef ReferenceCountedPointer<class MemoryManager> Ref;
- virtual void* alloc(size_t s);
- virtual void free(void* ptr);
- virtual bool isThreadsafe() const;
-
- /** There's only one instance of this memory manager; it is
- cached after the first creation. */
- static CRTMemoryManager::Ref create();
-};
-
-}
-
-#endif
diff --git a/externals/g3dlite/G3D/MeshAlg.h b/externals/g3dlite/G3D/MeshAlg.h
deleted file mode 100644
index 1decea10105..00000000000
--- a/externals/g3dlite/G3D/MeshAlg.h
+++ /dev/null
@@ -1,683 +0,0 @@
-/**
- @file MeshAlg.h
-
- Indexed Mesh algorithms.
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2003-09-14
- @edited 2010-01-18
-*/
-
-#ifndef G3D_MeshAlg_h
-#define G3D_MeshAlg_h
-
-#include "G3D/platform.h"
-#include "G3D/Array.h"
-#include "G3D/Vector3.h"
-#include "G3D/CoordinateFrame.h"
-#include "G3D/SmallArray.h"
-#include "G3D/constants.h"
-#include "G3D/Image1.h"
-
-#ifdef G3D_WIN32
-// Turn off "conditional expression is constant" warning; MSVC generates this
-// for debug assertions in inlined methods.
-#pragma warning (disable : 4127)
-#endif
-
-namespace G3D {
-
-/**
- Indexed <B>mesh alg</B>orithms. You have to build your own mesh class.
- <P>
- No mesh class is provided with G3D because there isn't an "ideal"
- mesh format-- one application needs keyframed animation, another
- skeletal animation, a third texture coordinates, a fourth
- cannot precompute information, etc. Instead of compromising, this
- class implements the hard parts of mesh computation and you can write
- your own ideal mesh class on top of it.
-
- \sa G3D::ArticulatedModel, G3D::IFSModel
- */
-class MeshAlg {
-public:
-
- /** \deprecated */
- typedef PrimitiveType Primitive;
-
- /** Adjacency information for a vertex.
- Does not contain the vertex position or normal,
- which are stored in the MeshAlg::Geometry object.
- <CODE>Vertex</CODE>s must be stored in an array
- parallel to (indexed in the same way as)
- MeshAlg::Geometry::vertexArray.
- */
- class Vertex {
- public:
- Vertex() {}
-
- /**
- Array of edges adjacent to this vertex.
- Let e = edgeIndex[i].
- edge[(e >= 0) ? e : ~e].vertexIndex[0] == this
- vertex index.
-
- Edges may be listed multiple times if they are
- degenerate.
- */
- SmallArray<int, 6> edgeIndex;
-
- /**
- Returns true if e or ~e is in the edgeIndex list.
- */
- inline bool inEdge(int e) const {
- return edgeIndex.contains(~e) || edgeIndex.contains(e);
- }
-
- /**
- Array of faces containing this vertex. Faces
- may be listed multiple times if they are degenerate.
- */
- SmallArray<int, 6> faceIndex;
-
- inline bool inFace(int f) const {
- debugAssert(f >= 0);
- return faceIndex.contains(f);
- }
- };
-
-
- /**
- Oriented, indexed triangle.
- */
- class Face {
- public:
- Face();
-
- /**
- Used by Edge::faceIndex to indicate a missing face.
- This is a large negative value.
- */
- static const int NONE;
-
-
- /**
- Vertices in the face in counter-clockwise order.
- Degenerate faces may include the same vertex multiple times.
- */
- int vertexIndex[3];
-
- inline bool containsVertex(int v) const {
- return contains(vertexIndex, 3, v);
- }
-
- /**
- Edge indices in counter-clockwise order. Edges are
- undirected, so it is important to know which way
- each edge is pointing in a face. This is encoded
- using negative indices.
-
- If <CODE>edgeIndex[i] >= 0</CODE> then this face
- contains the directed edge
- between vertex indices
- <CODE>edgeArray[face.edgeIndex[i]].vertexIndex[0]</CODE>
- and
- <CODE>edgeArray[face.edgeIndex[i]].vertexIndex[1]</CODE>.
-
- If <CODE>edgeIndex[i] < 0</CODE> then
- <CODE>~edgeIndex[i]</CODE> (i.e. the two's
- complement of) is used and this face contains the directed
- edge between vertex indices
- <CODE>edgeArray[~face.edgeIndex[i]].vertexIndex[0]</CODE>
- and
- <CODE>edgeArray[~face.edgeIndex[i]].vertexIndex[1]</CODE>.
-
- Degenerate faces may include the same edge multiple times.
- */
- // Temporarily takes on the value Face::NONE during adjacency
- // computation to indicate an edge that has not yet been assigned.
- int edgeIndex[3];
-
- inline bool containsEdge(int e) const {
- if (e < 0) {
- e = ~e;
- }
- return contains(edgeIndex, 3, e) || contains(edgeIndex, 3, ~e);
- }
-
- /** Contains the forward edge e if e >= 0 and the backward edge
- ~e otherwise. */
- inline bool containsDirectedEdge(int e) const {
- return contains(edgeIndex, 3, e);
- }
- };
-
-
- /** Oriented, indexed edge */
- class Edge {
- public:
- Edge();
-
- /** Degenerate edges may include the same vertex times. */
- int vertexIndex[2];
-
- inline bool containsVertex(int v) const {
- return contains(vertexIndex, 2, v);
- }
-
- /**
- The edge is directed <B>forward</B> in face 0
- <B>backward</B> in face 1. Face index of MeshAlg::Face::NONE
- indicates a boundary (a.k.a. crack, broken) edge.
- */
- int faceIndex[2];
-
- /** Returns true if f is contained in the faceIndex array in either slot.
- To see if it is forward in that face, just check edge.faceIndex[0] == f.*/
- inline bool inFace(int f) const {
- return contains(faceIndex, 2, f);
- }
-
- /**
- Returns true if either faceIndex is NONE.
- */
- inline bool boundary() const {
- return (faceIndex[0] == Face::NONE) ||
- (faceIndex[1] == Face::NONE);
- }
-
- /**
- Returns the reversed edge.
- */
- inline Edge reverse() const {
- Edge e;
- e.vertexIndex[0] = vertexIndex[1];
- e.vertexIndex[1] = vertexIndex[0];
- e.faceIndex[0] = faceIndex[1];
- e.faceIndex[1] = faceIndex[0];
- return e;
- }
- };
-
-
- /**
- Convenient for passing around the per-vertex data that changes under
- animation. The faces and edges are needed to interpret
- these values.
- */
- class Geometry {
- public:
- /** Vertex positions */
- Array<Vector3> vertexArray;
-
- /** Vertex normals */
- Array<Vector3> normalArray;
-
- /**
- Assignment is optimized using SSE.
- */
- Geometry& operator=(const Geometry& src);
-
- void clear() {
- vertexArray.clear();
- normalArray.clear();
- }
- };
-
- /**
- Given a set of vertices and a set of indices for traversing them
- to create triangles, computes other mesh properties.
-
- <B>Colocated vertices are treated as separate.</B> To have
- colocated vertices collapsed (necessary for many algorithms,
- like shadowing), weld the mesh before computing adjacency.
-
- <I>Recent change: In version 6.00, colocated vertices were automatically
- welded by this routine and degenerate faces and edges were removed. That
- is no longer the case.</I>
-
- Where two faces meet, there are two opposite directed edges. These
- are collapsed into a single bidirectional edge in the edgeArray.
- If four faces meet exactly at the same edge, that edge will appear
- twice in the array, and so on. If an edge is a boundary of the mesh
- (i.e. if the edge has only one adjacent face) it will appear in the
- array with one face index set to MeshAlg::Face::NONE.
-
- @param vertexGeometry %Vertex positions to use when deciding colocation.
- @param indexArray Order to traverse vertices to make triangles
- @param faceArray <I>Output</I>
- @param edgeArray <I>Output</I>. Sorted so that boundary edges are at the end of the array.
- @param vertexArray <I>Output</I>
- */
- static void computeAdjacency(
- const Array<Vector3>& vertexGeometry,
- const Array<int>& indexArray,
- Array<Face>& faceArray,
- Array<Edge>& edgeArray,
- Array<Vertex>& vertexArray);
-
- /**
- @deprecated Use the other version of computeAdjacency, which takes Array<Vertex>.
- @param facesAdjacentToVertex <I>Output</I> adjacentFaceArray[v] is an array of
- indices for faces touching vertex index v
- */
- static void computeAdjacency(
- const Array<Vector3>& vertexArray,
- const Array<int>& indexArray,
- Array<Face>& faceArray,
- Array<Edge>& edgeArray,
- Array< Array<int> >& facesAdjacentToVertex);
-
- /**
- Computes some basic mesh statistics including: min, max mean and median,
- edge lengths; and min, mean, median, and max face area.
-
- @param vertexArray %Vertex positions to use when deciding colocation.
- @param indexArray Order to traverse vertices to make triangles
- @param minEdgeLength Minimum edge length
- @param meanEdgeLength Mean edge length
- @param medianEdgeLength Median edge length
- @param maxEdgeLength Max edge length
- @param minFaceArea Minimum face area
- @param meanFaceArea Mean face area
- @param medianFaceArea Median face area
- @param maxFaceArea Max face area
- */
- static void computeAreaStatistics(
- const Array<Vector3>& vertexArray,
- const Array<int>& indexArray,
- double& minEdgeLength,
- double& meanEdgeLength,
- double& medianEdgeLength,
- double& maxEdgeLength,
- double& minFaceArea,
- double& meanFaceArea,
- double& medianFaceArea,
- double& maxFaceArea);
-
-private:
-
- /** Helper for weldAdjacency */
- static void weldBoundaryEdges(
- Array<Face>& faceArray,
- Array<Edge>& edgeArray,
- Array<Vertex>& vertexArray);
-
-public:
-
- /**
- Computes tangent and binormal vectors,
- which provide a (mostly) consistent
- parameterization over the surface for
- effects like bump mapping. In the resulting coordinate frame,
- T = x (varies with texture s coordinate), B = y (varies with negative texture t coordinate),
- and N = z for a right-handed coordinate frame. If a billboard is vertical on the screen
- in view of the camera, the tangent space matches the camera's coordinate frame.
-
- The vertex, texCoord, tangent, and binormal
- arrays are parallel arrays.
-
- The resulting tangent and binormal might not be exactly
- perpendicular to each other. They are guaranteed to
- be perpendicular to the normal.
-
- @cite Max McGuire
- */
- static void computeTangentSpaceBasis(
- const Array<Vector3>& vertexArray,
- const Array<Vector2>& texCoordArray,
- const Array<Vector3>& vertexNormalArray,
- const Array<Face>& faceArray,
- Array<Vector3>& tangent,
- Array<Vector3>& binormal);
-
- /** @deprecated */
- static void computeNormals(
- const Array<Vector3>& vertexArray,
- const Array<Face>& faceArray,
- const Array< Array<int> >& adjacentFaceArray,
- Array<Vector3>& vertexNormalArray,
- Array<Vector3>& faceNormalArray);
-
- /**
- Vertex normals are weighted by the area of adjacent faces.
- Nelson Max showed this is superior to uniform weighting for
- general meshes in jgt.
-
- @param vertexNormalArray Output. Unit length
- @param faceNormalArray Output. Degenerate faces produce zero magnitude normals. Unit length
- @see weld
- */
- static void computeNormals(
- const Array<Vector3>& vertexGeometry,
- const Array<Face>& faceArray,
- const Array<Vertex>& vertexArray,
- Array<Vector3>& vertexNormalArray,
- Array<Vector3>& faceNormalArray);
-
- /** Computes unit length normals in place using the other computeNormals methods.
- If you already have a face array use another method; it will be faster.
- @see weld*/
- static void computeNormals(
- Geometry& geometry,
- const Array<int>& indexArray);
-
- /**
- Computes face normals only. Significantly faster (especially if
- normalize is false) than computeNormals.
- @see weld
- */
- static void computeFaceNormals(
- const Array<Vector3>& vertexArray,
- const Array<Face>& faceArray,
- Array<Vector3>& faceNormals,
- bool normalize = true);
-
- /**
- Classifies each face as a backface or a front face relative
- to the observer point P (which is at infinity when P.w = 0).
- A face with normal exactly perpendicular to the observer vector
- may be classified as either a front or a back face arbitrarily.
- */
- static void identifyBackfaces(
- const Array<Vector3>& vertexArray,
- const Array<Face>& faceArray,
- const Vector4& P,
- Array<bool>& backface);
-
- /** A faster version of identifyBackfaces for the case where
- face normals have already been computed */
- static void identifyBackfaces(
- const Array<Vector3>& vertexArray,
- const Array<Face>& faceArray,
- const Vector4& P,
- Array<bool>& backface,
- const Array<Vector3>& faceNormals);
-
- /**
- Welds nearby and colocated elements of the <I>oldVertexArray</I> together so that
- <I>newVertexArray</I> contains no vertices within <I>radius</I> of one another.
- Every vertex in newVertexPositions also appears in oldVertexPositions.
- This is useful for downsampling meshes and welding cracks created by artist errors
- or numerical imprecision.
-
- The two integer arrays map indices back and forth between the arrays according to:
- <PRE>
- oldVertexArray[toOld[ni]] == newVertexArray[ni]
- oldVertexArray[oi] == newVertexArray[toNew[ni]]
- </PRE>
-
- Note that newVertexPositions is never longer than oldVertexPositions
- and is shorter when vertices are welded.
-
- Welding with a large radius will effectively compute a lower level of detail for
- the mesh.
-
- The welding method runs in roughly linear time in the length of oldVertexArray--
- a uniform spatial grid is used to achieve nearly constant time vertex collapses
- for uniformly distributed vertices.
-
- It is sometimes desirable to keep the original vertex ordering but
- identify the unique vertices. The following code computes
- array canonical s.t. canonical[v] = first occurance of
- a vertex near oldVertexPositions[v] in oldVertexPositions.
-
- <PRE>
- Array<int> canonical(oldVertexPositions.size()), toNew, toOld;
- computeWeld(oldVertexPositions, Array<Vector3>(), toNew, toOld, radius);
- for (int v = 0; v < canonical.size(); ++v) {
- canonical[v] = toOld[toNew[v]];
- }
- </PRE>
-
- See also G3D::MeshAlg::weldAdjacency.
-
- @cite The method is that described as the 'Grouper' in Baum, Mann, Smith, and Winget,
- Making Radiosity Usable: Automatic Preprocessing and Meshing Techniques for
- the Generation of Accurate Radiosity Solutions, Computer Graphics vol 25, no 4, July 1991.
-
- @deprecated Use weld.
- */
- static void computeWeld(
- const Array<Vector3>& oldVertexPositions,
- Array<Vector3>& newVertexPositions,
- Array<int>& toNew,
- Array<int>& toOld,
- double radius = fuzzyEpsilon);
-
- /**
- Modifies the face, edge, and vertex arrays in place so that
- colocated (within radius) vertices are treated as identical.
- Note that the vertexArray and corresponding geometry will
- contain elements that are no longer used. In the vertexArray,
- these elements are initialized to MeshAlg::Vertex() but not
- removed (because removal would change the indexing).
-
- This is a good preprocessing step for algorithms that are only
- concerned with the shape of a mesh (e.g. cartoon rendering, fur, shadows)
- and not the indexing of the vertices.
-
- Use this method when you have already computed adjacency information
- and want to collapse colocated vertices within that data without
- disturbing the actual mesh vertices or indexing scheme.
-
- If you have not computed adjacency already, use MeshAlg::computeWeld
- instead and compute adjacency information after welding.
-
- @deprecated Use weld.
-
- @param faceArray Mutated in place. Size is maintained (degenerate
- faces are <b>not</B> removed).
- @param edgeArray Mutated in place. May shrink if boundary edges
- are welded together.
- @param vertexArray Mutated in place. Size is maintained (duplicate
- vertices contain no adjacency info).
- */
- static void weldAdjacency(
- const Array<Vector3>& originalGeometry,
- Array<Face>& faceArray,
- Array<Edge>& edgeArray,
- Array<Vertex>& vertexArray,
- double radius = fuzzyEpsilon);
-
-
- /**
- Counts the number of edges (in an edge array returned from
- MeshAlg::computeAdjacency) that have only one adjacent face.
- */
- static int countBoundaryEdges(const Array<Edge>& edgeArray);
-
-
- /**
- Generates an array of integers from start to start + n - 1 that have run numbers
- in series then omit the next skip before the next run. Useful for turning
- a triangle list into an indexed face set.
-
- Example:
- <PRE>
- createIndexArray(10, x);
- // x = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
-
- createIndexArray(5, x, 2);
- // x = [2, 3, 4, 5, 6, 7]
-
- createIndexArray(6, x, 0, 2, 1);
- // x = [0, 1, 3, 4, 6, 7]
- </PRE>
- */
- static void createIndexArray(
- int n,
- Array<int>& array,
- int start = 0,
- int run = 1,
- int skip = 0);
-
- /**
- Computes a conservative, near-optimal axis aligned bounding box and sphere.
-
- @cite The bounding sphere uses the method from J. Ritter. An effcient bounding sphere. In Andrew S. Glassner, editor, Graphics Gems. Academic Press, Boston, MA, 1990.
-
- */
- static void computeBounds(const Array<Vector3>& vertex, class AABox& box, class Sphere& sphere);
-
- /** Computes bounds for a subset of the vertices. It is ok if vertices appear more than once in the index array. */
- static void computeBounds(const Array<Vector3>& vertex, const Array<int>& index, class AABox& box, class Sphere& sphere);
-
- /**
- In debug mode, asserts that the adjacency references between the
- face, edge, and vertex array are consistent.
- */
- static void debugCheckConsistency(
- const Array<Face>& faceArray,
- const Array<Edge>& edgeArray,
- const Array<Vertex>& vertexArray);
-
- /**
- Generates a unit square in the X-Z plane composed of a grid of wCells x hCells
- squares and then transforms it by xform.
-
- @param vertex Output vertices
- @param texCoord Output texture coordinates
- @param index Output triangle list indices
- @param textureScale Lower-right texture coordinate
- @param spaceCentered If true, the coordinates generated are centered at the origin before the transformation.
- @param twoSided If true, matching top and bottom planes are generated.
- \param elevation If non-NULL, values from this image are used as elevations. Apply an \a xform to adjust the scale
- */
- static void generateGrid(
- Array<Vector3>& vertex,
- Array<Vector2>& texCoord,
- Array<int>& index,
- int wCells = 10,
- int hCells = 10,
- const Vector2& textureScale = Vector2(1,1),
- bool spaceCentered = true,
- bool twoSided = true,
- const CoordinateFrame& xform = CoordinateFrame(),
- const Image1::Ref& elevation = NULL);
-
- /** Converts quadlist (QUADS),
- triangle fan (TRIANGLE_FAN),
- tristrip(TRIANGLE_STRIP), and quadstrip (QUAD_STRIP) indices into
- triangle list (TRIANGLES) indices and appends them to outIndices. */
- template<class IndexType>
- static void toIndexedTriList(
- const Array<IndexType>& inIndices,
- MeshAlg::Primitive inType,
- Array<IndexType>& outIndices) {
-
- debugAssert(
- inType == PrimitiveType::TRIANGLE_STRIP ||
- inType == PrimitiveType::TRIANGLE_FAN ||
- inType == PrimitiveType::QUADS ||
- inType == PrimitiveType::QUAD_STRIP);
-
- const int inSize = inIndices.size();
-
- switch(inType) {
- case PrimitiveType::TRIANGLE_FAN:
- {
- debugAssert(inSize >= 3);
-
- int N = outIndices.size();
- outIndices.resize(N + (inSize - 2) * 3);
-
- for (IndexType i = 1, outIndex = N; i <= (inSize - 2); ++i, outIndex += 3) {
- outIndices[outIndex] = inIndices[0];
- outIndices[outIndex + 1] = inIndices[i];
- outIndices[outIndex + 2] = inIndices[i + 1];
- }
-
- break;
- }
-
- case PrimitiveType::TRIANGLE_STRIP:
- {
- debugAssert(inSize >= 3);
-
- int N = outIndices.size();
- outIndices.resize(N + (inSize - 2) * 3);
-
- bool atEven = false;
- for (IndexType i = 0, outIndex = N; i <= (inSize - 2); ++i, outIndex += 3) {
- if (atEven) {
- outIndices[outIndex] = inIndices[i + 1];
- outIndices[outIndex + 1] = inIndices[i];
- outIndices[outIndex + 2] = inIndices[i + 2];
- atEven = false;
- } else {
- outIndices[outIndex] = inIndices[i];
- outIndices[outIndex + 1] = inIndices[i + 1];
- outIndices[outIndex + 2] = inIndices[i + 2];
- atEven = true;
- }
- }
-
- break;
- }
-
- case PrimitiveType::QUADS:
- {
- debugAssert(inIndices.size() >= 4);
-
- int N = outIndices.size();
- outIndices.resize(N + (inSize / 4) * 3);
-
- for (IndexType i = 0, outIndex = N; i <= (inSize - 4); i += 4, outIndex += 6) {
- outIndices[outIndex] = inIndices[i];
- outIndices[outIndex + 1] = inIndices[i + 1];
- outIndices[outIndex + 2] = inIndices[i + 3];
- outIndices[outIndex + 3] = inIndices[i + 1];
- outIndices[outIndex + 4] = inIndices[i + 2];
- outIndices[outIndex + 5] = inIndices[i + 3];
- }
-
- break;
- }
-
- case PrimitiveType::QUAD_STRIP:
- {
- debugAssert(inIndices.size() >= 4);
-
- int N = outIndices.size();
- outIndices.resize(N + (inSize - 2) * 3);
-
- for (IndexType i = 0, outIndex = N; i <= (inSize - 2); i += 2, outIndex += 6) {
- outIndices[outIndex] = inIndices[i];
- outIndices[outIndex + 1] = inIndices[i + 1];
- outIndices[outIndex + 2] = inIndices[i + 2];
- outIndices[outIndex + 3] = inIndices[i + 2];
- outIndices[outIndex + 4] = inIndices[i + 1];
- outIndices[outIndex + 5] = inIndices[i + 3];
- }
- break;
- }
- default:
- alwaysAssertM(false, "Illegal argument");
- }
- }
-
-protected:
-
- /**
- Helper for computeAdjacency. If a directed edge with index e already
- exists from i0 to i1 then e is returned. If a directed edge with index e
- already exists from i1 to i0, ~e is returned (the complement) and
- edgeArray[e] is set to f. Otherwise, a new edge is created from i0 to i1
- with first face index f and its index is returned.
-
- @param vertexArray Vertex positions to use when deciding colocation.
-
- @param area Area of face f. When multiple edges of the same direction
- are found between the same vertices (usually because of degenerate edges)
- the face with larger area is kept in the edge table.
- */
- static int findEdgeIndex(
- const Array<Vector3>& vertexArray,
- Array<Edge>& geometricEdgeArray,
- int i0, int i1, int f, double area);
-};
-}
-#endif
-
diff --git a/externals/g3dlite/G3D/MeshBuilder.h b/externals/g3dlite/G3D/MeshBuilder.h
deleted file mode 100644
index 9920d59d7d3..00000000000
--- a/externals/g3dlite/G3D/MeshBuilder.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/**
- @file MeshBuilder.h
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2002-02-27
- @edited 2004-10-04
- */
-#ifndef G3D_MESHBUILDER_H
-#define G3D_MESHBUILDER_H
-
-#include "G3D/platform.h"
-#include "G3D/Array.h"
-#include "G3D/Vector3.h"
-#include "G3D/Triangle.h"
-
-namespace G3D {
-
-/**
- Allows creation of optimized watertight meshes from unoptimized polygon soups.
- See also G3D::MeshAlg for algorithms that operate on the output.
- */
-class MeshBuilder {
-public:
-
- /**
- Set setWeldRadius to AUTO_WELD to weld vertices closer than 1/2
- the smallest edge length in a model.
- */
- enum {AUTO_WELD = -100};
-
-private:
- /** Indices of vertices in <B>or near</B> a grid cell. */
- typedef Array<int> List;
-
- std::string name;
-
- /**
- All of the triangles, as a long triangle list.
- */
- Array<Vector3> triList;
-
- void centerTriList();
- void computeBounds(Vector3& min, Vector3& max);
-
- bool _twoSided;
-
- /** Collapse radius */
- double close;
-
-public:
-
- inline MeshBuilder(bool twoSided = false) : _twoSided(twoSided), close(AUTO_WELD) {}
-
- /** Writes the model to the arrays, which can then be used with
- G3D::IFSModel::save and G3D::MeshAlg */
- void commit(std::string& name, Array<int>& indexArray, Array<Vector3>& vertexArray);
-
- /**
- Adds a new triangle to the model. (Counter clockwise)
- */
- void addTriangle(const Vector3& a, const Vector3& b, const Vector3& c);
-
- /**
- Adds two new triangles to the model. (Counter clockwise)
- */
- void addQuad(const Vector3& a, const Vector3& b, const Vector3& c, const Vector3& d);
-
- void addTriangle(const Triangle& t);
-
- void setName(const std::string& n);
-
- /** Vertices within this distance are considered identical.
- Use AUTO_WELD (the default) to have the distance be a function of the model size.*/
- void setWeldRadius(double r) {
- close = r;
- }
-};
-
-} // namespace
-
-#endif
diff --git a/externals/g3dlite/G3D/NetAddress.h b/externals/g3dlite/G3D/NetAddress.h
deleted file mode 100644
index 8ed20a06690..00000000000
--- a/externals/g3dlite/G3D/NetAddress.h
+++ /dev/null
@@ -1,132 +0,0 @@
-#ifndef G3D_NETADDRESS_H
-#define G3D_NETADDRESS_H
-
-#include "G3D/platform.h"
-#include "G3D/Table.h"
-
-/** These control the version of Winsock used by G3D.
- Version 2.0 is standard for G3D 6.09 and later.
- Version 1.1 is standard for G3D 6.08 and earlier.
- */
-#define G3D_WINSOCK_MAJOR_VERSION 2
-#define G3D_WINSOCK_MINOR_VERSION 0
-
-#ifdef G3D_WIN32
-# if (G3D_WINSOCK_MAJOR_VERSION == 2)
-# include <winsock2.h>
-# elif (G3D_WINSOCK_MAJOR_VERSION == 1)
-# include <winsock.h>
-# endif
-#else
-# include <sys/types.h>
-# include <sys/socket.h>
-# include <netinet/in.h>
-# ifndef SOCKADDR_IN
-# define SOCKADDR_IN struct sockaddr_in
-# endif
-# ifndef SOCKET
-# define SOCKET int
-# endif
-#endif
-
-#include "G3D/g3dmath.h"
-
-namespace G3D {
-
-class NetAddress {
-private:
- friend class NetworkDevice;
- friend class LightweightConduit;
- friend class ReliableConduit;
-
- /** Host byte order */
- void init(uint32 host, uint16 port);
- void init(const std::string& hostname, uint16 port);
- NetAddress(const SOCKADDR_IN& a);
- NetAddress(const struct in_addr& addr, uint16 port = 0);
-
- SOCKADDR_IN addr;
-
-public:
- /**
- In host byte order
- */
- NetAddress(uint32 host, uint16 port = 0);
-
- /**
- @param port Specified in host byte order (i.e., don't worry about endian issues)
- */
- NetAddress(const std::string& hostname, uint16 port);
-
- /**
- @param hostnameAndPort in the form "hostname:port" or "ip:port"
- */
- NetAddress(const std::string& hostnameAndPort);
-
- /**
- @deprecated Use G3D::NetworkDevice::broadcastAddressArray()
-
- @brief Creates a UDP broadcast address for use with a
- G3D::LightweightConduit.
-
- UDP broadcast allows one machine to send a packet to all machines
- on the same local network. The IP portion of the address is
- 0xFFFFFFFF, which indicates "broadcast" to the underlying socket
- API. This feature is not available with the connection-based TCP
- protocol abstracted by G3D::ReliableConduit; use multisend
- instead.
- */
- static NetAddress broadcastAddress(uint16 port);
-
- NetAddress();
-
- void serialize(class BinaryOutput& b) const;
- void deserialize(class BinaryInput& b);
-
- /** @brief Returns true if this is not an illegal address. */
- bool ok() const;
-
- /** @brief Returns a value in host format (i.e., don't worry about
- endian issues) */
- inline uint32 ip() const {
- return ntohl(addr.sin_addr.s_addr);
- //return ntohl(addr.sin_addr.S_un.S_addr);
- }
-
- inline uint16 port() const {
- return ntohs(addr.sin_port);
- }
-
- std::string ipString() const;
- std::string toString() const;
-
-};
-
-std::ostream& operator<<(std::ostream& os, const NetAddress&);
-
-} // namespace G3D
-
-template <> struct HashTrait<G3D::NetAddress> {
- static size_t hashCode(const G3D::NetAddress& key) {
- return static_cast<size_t>(key.ip() + (static_cast<G3D::uint32>(key.port()) << 16));
- }
-};
-
-namespace G3D {
-
-/**
- Two addresses may point to the same computer but be != because
- they have different IP's.
- */
-inline bool operator==(const NetAddress& a, const NetAddress& b) {
- return (a.ip() == b.ip()) && (a.port() == b.port());
-}
-
-
-inline bool operator!=(const NetAddress& a, const NetAddress& b) {
- return !(a == b);
-}
-
-} // namespace G3D
-
-#endif
diff --git a/externals/g3dlite/G3D/NetworkDevice.h b/externals/g3dlite/G3D/NetworkDevice.h
deleted file mode 100644
index ea3290cbc09..00000000000
--- a/externals/g3dlite/G3D/NetworkDevice.h
+++ /dev/null
@@ -1,738 +0,0 @@
-/**
- @file NetworkDevice.h
-
- These classes abstract networking from the socket level to a
- serialized messaging style that is more appropriate for games. The
- performance has been tuned for sending many small messages. The
- message protocol contains a header that prevents them from being used
- with raw UDP/TCP (e.g. connecting to an HTTP server).
-
- LightweightConduit and ReliableConduits have different interfaces
- because they have different semantics. You would never want to
- interchange them without rewriting the surrounding code.
-
- NetworkDevice creates conduits because they need access to a global
- log pointer and because I don't want non-reference counted conduits
- being created.
-
- Be careful with threads and reference counting. The reference
- counters are not threadsafe, and are also not updated correctly if a
- thread is explicitly killed. Since the conduits will be passed by
- const XConduitRef& most of the time this doesn't appear as a major
- problem. With non-blocking conduits, you should need few threads
- anyway.
-
- LightweightConduits preceed each message with a 4-byte host order
- unsigned integer that is the message type. This does not appear in
- the message serialization/deserialization.
-
- ReliableConduits preceed each message with two 4-byte host order
- unsigned integers. The first is the message type and the second
- indicates the length of the rest of the data. The size does not
- include the size of the header itself. The minimum message is 9
- bytes:a 4-byte type, a 4-byte header equal to "1", and one byte of data.
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @created 2002-11-22
- @edited 2006-11-25
- */
-
-#ifndef G3D_NETWORKDEVICE_H
-#define G3D_NETWORKDEVICE_H
-
-#include "G3D/platform.h"
-#include "G3D/NetAddress.h"
-
-#include <string>
-#include <iostream>
-#include "G3D/g3dmath.h"
-
-#include "G3D/ReferenceCount.h"
-#include "G3D/Array.h"
-#include "G3D/BinaryOutput.h"
-
-namespace G3D {
-
-class TextOutput;
-
-class Conduit : public ReferenceCountedObject {
-protected:
- friend class NetworkDevice;
- friend class NetListener;
-
- uint64 mSent;
- uint64 mReceived;
- uint64 bSent;
- uint64 bReceived;
-
- SOCKET sock;
-
- /**
- Used for serialization. One per socket
- to make this threadsafe.
- */
- BinaryOutput binaryOutput;
-
- Conduit();
-
-public:
-
- virtual ~Conduit();
- uint64 bytesSent() const;
- uint64 messagesSent() const;
- uint64 bytesReceived() const;
- uint64 messagesReceived() const;
-
- /**
- If true, receive will return true.
- */
- virtual bool messageWaiting();
-
- /**
- Returns the type of the waiting message (i.e. the type supplied
- with send). The return value is zero when there is no message
- waiting.
-
- One way to use this is to have a Table mapping message types to
- pre-allocated subclasses so receiving looks like:
-
- <PRE>
- // My base class for messages.
- class Message {
- virtual void serialize(BinaryOutput&) const;
- virtual void deserialize(BinaryInput&);
- virtual void process() = 0;
- };
-
- Message* m = table[conduit->waitingMessageType()];
- conduit->receive(m);
- m->process();
- </PRE>
-
- Another is to simply switch on the message type:
-
- <pre>
- switch (conduit->waitingMessageType()) {
- case 0:
- // No message
- break;
-
- case ENTITY_SPAWN_MSG:
- {
- EntitySpawnMsg m;
- condiut->receive(m);
- spawnEntity(m.id, m.position, m.modelID);
- }
- break;
- ...
- }
- </pre>
- */
- virtual uint32 waitingMessageType() = 0;
-
- /** Returns true if the connection is ok. */
- bool ok() const;
-};
-
-typedef ReferenceCountedPointer<class ReliableConduit> ReliableConduitRef;
-
-#ifdef __GNUC__
-// Workaround for a known bug in gcc 4.x where htonl produces
-// a spurrious warning.
-// http://gcc.gnu.org/ml/gcc-bugs/2005-10/msg03270.html
-uint32 gcchtonl(uint32);
-#endif
-
-// Messaging and stream APIs must be supported on a single class because
-// sometimes an application will switch modes on a single socket. For
-// example, when transferring 3D level geometry during handshaking with
-// a game server.
-/**
- A conduit that guarantees messages will arrive, intact and in order.
- Create on the client using NetworkDevice::createReliableConduit and
- on the server using NetListener::waitForConnection. Set the reference
- counted pointer to NULL to disconnect.
-
- To construct a ReliableConduit:
- <OL>
- <LI> Create a G3D::NetworkDevice (if you are using G3D::GApp, it creates
- one for you) on the client and on the server.
- <LI> On the server, create a G3D::NetListener using
- G3D::NetworkDevice::createListener
- <LI> On the server, invoke G3D::NetListener::waitForConnection.
- <LI> On the client, call G3D::NetworkDevice::createReliableConduit.
- You will need the server's G3D::NetAddress. Consider using
- G3D::Discovery::Client to find it via broadcasting.
- </OL>
-
- */
-class ReliableConduit : public Conduit {
-private:
- friend class NetworkDevice;
- friend class NetListener;
-
- enum State {RECEIVING, HOLDING, NO_MESSAGE} state;
-
- NetAddress addr;
-
- /**
- Type of the incoming message.
- */
- uint32 messageType;
-
- /**
- Total size of the incoming message (read from the header).
- */
- uint32 messageSize;
-
- /** Shared buffer for receiving messages. */
- void* receiveBuffer;
-
- /** Total size of the receiveBuffer. */
- size_t receiveBufferTotalSize;
-
- /** Size occupied by the current message... so far. This will be
- equal to messageSize when the whole message has arrived.
- */
- size_t receiveBufferUsedSize;
-
- ReliableConduit(const NetAddress& addr);
-
- ReliableConduit(const SOCKET& sock,
- const NetAddress& addr);
-
- template<typename T> static void serializeMessage
- (uint32 t, const T& m, BinaryOutput& b) {
-
- b.writeUInt32(t);
-
- // Reserve space for the 4 byte size header
- b.writeUInt32(0);
-
- size_t L = b.length();
- m.serialize(b);
- if ((size_t)b.length() == L) {
- // No data was created by serialization.
- // We need to send at least one byte because receive assumes that
- // a zero length message is an error.
- b.writeUInt8(0xFF);
- }
-
- uint32 len = b.size() - 8;
-
- // We send the length first to tell recv how much data to read.
- // Here we abuse BinaryOutput a bit and write directly into
- // its buffer, violating the abstraction.
- // Note that we write to the second set of 4 bytes, which is
- // the size field.
- uint32* lenPtr = ((uint32*)b.getCArray()) + 1;
- #if defined(__GNUC__)
- *lenPtr = gcchtonl(len);
- #else
- *lenPtr = htonl(len);
- #endif
- }
-
-
- void sendBuffer(const BinaryOutput& b);
-
- /** Accumulates whatever part of the message (not the header) is
- still waiting on the socket into the receiveBuffer during
- state = RECEIVING mode. Closes the socket if anything goes
- wrong. When receiveBufferUsedSize == messageSize, the entire
- message has arrived. */
- void receiveIntoBuffer();
-
- /** Receives the messageType and messageSize from the socket. */
- void receiveHeader();
-
-public:
-
- /**
- Client invokes this to connect to a server. The call blocks until the
- conduit is opened. The conduit will not be ok() if it fails.
- */
- static ReliableConduitRef create(const NetAddress& address);
-
- /** Closes the socket. */
- ~ReliableConduit();
-
-
- // The message is actually copied from the socket to an internal buffer during
- // this call. Receive only deserializes.
- virtual bool messageWaiting();
-
- /**
- Serializes the message and schedules it to be sent as soon as possible,
- and then returns immediately. The message can be any <B>class</B> with
- a serialize and deserialize method. On the receiving side,
- use G3D::ReliableConduit::waitingMessageType() to detect the incoming
- message and then invoke G3D::ReliableConduit::receive(msg) where msg
- is of the same class as the message that was sent.
-
- The actual data sent across the network is preceeded by the
- message type and the size of the serialized message as a 32-bit
- integer. The size is sent because TCP is a stream protocol and
- doesn't have a concept of discrete messages.
- */
- template<typename T> inline void send(uint32 type, const T& message) {
- binaryOutput.reset();
- serializeMessage(type, message, binaryOutput);
- sendBuffer(binaryOutput);
- }
-
- /** Sends an empty message with the given type. Useful for sending
- commands that have no parameters. */
- void send(uint32 type);
-
- /** Send the same message to a number of conduits. Useful for sending
- data from a server to many clients (only serializes once). */
- template<typename T>
- inline static void multisend(
- const Array<ReliableConduitRef>& array,
- uint32 type,
- const T& m) {
-
- if (array.size() > 0) {
- array[0]->binaryOutput.reset();
- serializeMessage(type, m, array[0]->binaryOutput);
-
- for (int i = 0; i < array.size(); ++i) {
- array[i]->sendBuffer(array[0]->binaryOutput);
- }
- }
- }
-
- virtual uint32 waitingMessageType();
-
- /**
- If a message is waiting, deserializes the waiting message into
- message and returns true, otherwise returns false. You can
- determine the type of the message (and therefore, the class
- of message) using G3D::ReliableConduit::waitingMessageType().
- */
- template<typename T> inline bool receive(T& message) {
- if (! messageWaiting()) {
- return false;
- }
-
- debugAssert(state == HOLDING);
- // Deserialize
- BinaryInput b((uint8*)receiveBuffer, receiveBufferUsedSize, G3D_LITTLE_ENDIAN, BinaryInput::NO_COPY);
- message.deserialize(b);
-
- // Don't let anyone read this message again. We leave the buffer
- // allocated for the next caller, however.
- receiveBufferUsedSize = 0;
- state = NO_MESSAGE;
- messageType = 0;
- messageSize = 0;
-
- // Potentially read the next message.
- messageWaiting();
-
- return true;
- }
-
- /** Removes the current message from the queue. */
- inline void receive() {
- if (! messageWaiting()) {
- return;
- }
- receiveBufferUsedSize = 0;
- state = NO_MESSAGE;
- messageType = 0;
- messageSize = 0;
-
- // Potentially read the next message.
- messageWaiting();
- }
-
- NetAddress address() const;
-};
-
-
-typedef ReferenceCountedPointer<class LightweightConduit> LightweightConduitRef;
-
-/**
- Provides fast but unreliable transfer of messages. On a LAN,
- LightweightConduit will probably never drop messages but you
- <I>might</I> get your messages out of order. On an internet
- connection it might drop messages altogether. Messages are never
- corrupted, however. LightweightConduit requires a little less setup
- and overhead than ReliableConduit. ReliableConduit guarantees
- message delivery and order but requires a persistent connection.
-
- To set up a LightweightConduit (assuming you have already made
- subclasses of G3D::NetMessage based on your application's
- pcommunication protocol):
-
-[Server Side]
-<OL>
-<LI> Call LightweightConduit::create(port, true, false),
-where port is the port on which you will receive messages.
-
-<LI> Poll LightweightConduit::messageWaiting from your main loop. When
-it is true (or, equivalently, when LightweightConduit::waitingMessageType
-is non-zero) there is an incoming message.
-
-<LI> To read the incoming message, call LightweightConduit::receive with
-the appropriate class type, which mist have a deserialize method.
-LightweightConduit::waitingMessageType tells you what class is
-needed (you make up your own message constants for your program; numbers
-under 1000 are reserved for G3D's internal use).
-
-<LI> When done, simply set the G3D::LightweightConduitRef to NULL or let
-it go out of scope and the conduit cleans itself up automatically.
-</OL>
-
-[Client Side]
-<OL>
-<LI> Call G3D::LightweightConduit::create(). If you will
-broadcast to all servers on a LAN, set the third optional argument to
-true (the default is false for no broadcast). You can also set up the
-receive port as if it was a server to send and receive from a single
-LightweightConduit.
-
-<LI> To send, call G3D::LightweightConduit::send with the target address
-and a pointer to an instance of the message you want to send.
-
-<LI> When done, simply set the G3D::LightweightConduitRef to NULL or let
-it go out of scope and the conduit cleans itself up automatically.
-
-</OL>
- */
-class LightweightConduit : public Conduit {
-private:
- friend class NetworkDevice;
-
- /**
- True when waitingForMessageType has read the message
- from the network into messageType/messageStream.
- */
- bool alreadyReadMessage;
-
- /**
- Origin of the received message.
- */
- NetAddress messageSender;
-
- /**
- The type of the last message received.
- */
- uint32 messageType;
-
- /**
- The message received (the type has already been read off).
- */
- Array<uint8> messageBuffer;
-
- LightweightConduit(uint16 receivePort, bool enableReceive, bool enableBroadcast);
-
- void sendBuffer(const NetAddress& a, BinaryOutput& b);
-
- /** Maximum transmission unit (packet size in bytes) for this socket.
- May vary between sockets. */
- int MTU;
-
-
- template<typename T>
- void serializeMessage(
- uint32 type,
- const T& m,
- BinaryOutput& b) const {
-
- debugAssert(type != 0);
- b.writeUInt32(type);
- m.serialize(b);
- b.writeUInt32(1);
-
- debugAssertM(b.size() < MTU,
- format("This LightweightConduit is limited to messages of "
- "%d bytes (Ethernet hardware limit; this is the "
- "'UDP MTU')", maxMessageSize()));
-
- if (b.size() >= MTU) {
- throw LightweightConduit::PacketSizeException(
- format("This LightweightConduit is limited to messages of "
- "%d bytes (Ethernet hardware limit; this is the "
- "'UDP MTU')", maxMessageSize()),
- b.size() - 4, // Don't count the type header
- maxMessageSize());
- }
- }
-
-public:
-
- static LightweightConduitRef create(uint16 receivePort, bool enableReceive, bool enableBroadcast);
-
- class PacketSizeException {
- public:
- std::string message;
- int serializedPacketSize;
- int maxMessageSize;
-
- inline PacketSizeException(const std::string& m, int s, int b) :
- message(m),
- serializedPacketSize(s),
- maxMessageSize(b) {}
- };
-
- /** Closes the socket. */
- ~LightweightConduit();
-
- /** The maximum length of a message that can be sent
- (G3D places a small header at the front of each UDP packet;
- this is already taken into account by the value returned).
- */
- inline int maxMessageSize() const {
- return MTU - 4;
- }
-
-
- template<typename T> inline void send(const NetAddress& a, uint32 type, const T& msg) {
- binaryOutput.reset();
- serializeMessage(type, msg, binaryOutput);
- sendBuffer(a, binaryOutput);
- }
-
- /** Send the same message to multiple addresses (only serializes once).
- Useful when server needs to send to a known list of addresses
- (unlike direct UDP broadcast to all addresses on the subnet) */
- template<typename T> inline void send(const Array<NetAddress>& a, uint32 type, const T& m) {
- binaryOutput.reset();
- serializeMessage(type, m, binaryOutput);
-
- for (int i = 0; i < a.size(); ++i) {
- sendBuffer(a[i], binaryOutput);
- }
- }
-
- bool receive(NetAddress& sender);
-
- template<typename T> inline bool receive(NetAddress& sender, T& message) {
- bool r = receive(sender);
- if (r) {
- BinaryInput b((messageBuffer.getCArray() + 4),
- messageBuffer.size() - 4,
- G3D_LITTLE_ENDIAN, BinaryInput::NO_COPY);
- message.deserialize(b);
- }
-
- return r;
- }
-
- inline bool receive() {
- static NetAddress ignore;
- return receive(ignore);
- }
-
- virtual uint32 waitingMessageType();
-
-
- virtual bool messageWaiting();
-};
-
-///////////////////////////////////////////////////////////////////////////////
-
-typedef ReferenceCountedPointer<class NetListener> NetListenerRef;
-
-/**
- Runs on the server listening for clients trying to make reliable connections.
- */
-class NetListener : public ReferenceCountedObject {
-private:
-
- friend class NetworkDevice;
-
- SOCKET sock;
-
- /** Port is in host byte order. */
- NetListener(uint16 port);
-
-public:
-
- static NetListenerRef create(const uint16 port);
-
- ~NetListener();
-
- /** Block until a connection is received. Returns NULL if
- something went wrong. */
- ReliableConduitRef waitForConnection();
-
- /** True if a client is waiting (i.e. waitForConnection will
- return immediately). */
- bool clientWaiting() const;
-
- bool ok() const;
-};
-
-
-///////////////////////////////////////////////////////////////////////////////
-
-/**
- @brief Abstraction of network (socket) functionality.
-
- An abstraction over sockets that provides a message-based network
- infrastructure optimized for sending many small (~500 bytes) messages.
- All functions always return immediately.
-
- Create only one NetworkDevice per process (a WinSock restriction).
-
- NetworkDevice is technically not thread safe. However, as long as
- you use different conduits on different threads (or lock conduits
- before sending), you will encounter no problems sharing the single
- NetworkDevice across multiple threads. That is, do not invoke the same
- Conduit's send or receive method on two threads at once.
-
- This assumes that the underlying WinSock/BSD sockets implementation
- is thread safe. That is not guaranteed, but in practice seems
- to always be true (see
- http://tangentsoft.net/wskfaq/intermediate.html#threadsafety)
-
- <hr>
-
- IP networks use "network byte order" (big-endian) for
- communicating integers. "Host byte order" is the endian-ness of
- the local machine (typically little-endian; see
- System::endian). The C functions htonl() and ntohl() convert 32-bit
- values between these formats. G3D only ever exposes host byte order,
- so programmers rarely need to be aware of the distinction.
-
- */
-class NetworkDevice {
-public:
-
- /** @brief Description of an ethernet or wireless ethernet adapter.*/
- class EthernetAdapter {
- public:
- /** Reverse-DNS of the ip address.*/
- std::string hostname;
-
- /** Name of the adapter */
- std::string name;
-
- /** IP address in host byte order.*/
- uint32 ip;
-
- /** Subnet mask in host byte order.*/
- uint32 subnet;
-
- /** UDP broadcast address in host byte order.*/
- uint32 broadcast;
-
- /** MAC (hardware) address, if known */
- uint8 mac[6];
-
- EthernetAdapter();
-
- /** Produces a text description of this adapter */
- void describe(TextOutput& t) const;
- };
-
-private:
-
- friend class Conduit;
- friend class LightweightConduit;
- friend class ReliableConduit;
- friend class NetListener;
-
- bool initialized;
-
- Array<EthernetAdapter> m_adapterArray;
-
- /** Broadcast addresses available on this machine,
- extracted from m_adapterArray.*/
- Array<uint32> m_broadcastAddresses;
-
- /** Utility method. */
- void closesocket(SOCKET& sock) const;
-
- /** Utility method. Returns true on success.*/
- bool bind(SOCKET sock, const NetAddress& addr) const;
-
- /** The global instance */
- static NetworkDevice* s_instance;
-
- NetworkDevice();
-
- bool init();
-
- void _cleanup();
-
- /** Called from init to update m_adapterArray and
- m_broadcastAddresses. */
- void addAdapter(const EthernetAdapter& a);
-
-public:
-
- /** Prints an IP address to a string.
- @param ip In host byte order.*/
- static std::string formatIP(uint32 ip);
-
- /** Prints a MAC address to a string. */
- static std::string formatMAC(const uint8 mac[6]);
-
- ~NetworkDevice();
-
- /** Returns the available ethernet adapters for the current
- machine that are online. Does not include the loopback adapter
- for localhost.*/
- inline const Array<EthernetAdapter>& adapterArray() const {
- return m_adapterArray;
- }
-
- /** Returns the (unique) IP addresses for UDP broadcasting
- extracted from adapterArray(). All are in host byte order. */
- inline const Array<uint32>& broadcastAddressArray() const {
- return m_broadcastAddresses;
- }
-
- /**
- Returns NULL if there was a problem initializing the network.
- */
- static NetworkDevice* instance();
-
- /**
- Shuts down the network device (destroying the global instance).
- */
- static void cleanup();
-
- /**
- Prints a human-readable description of this machine
- to the text output stream.
- */
- void describeSystem(
- TextOutput& t);
-
- void describeSystem(
- std::string& s);
-
- /** Returns the name (or one of the names) of this computer */
- std::string localHostName() const;
-
- /** There is often more than one address for the local host. This
- returns all of them.
- @deprecated Use adapterArray()
- */
- void localHostAddresses(Array<NetAddress>& array) const;
-};
-
-
-#ifdef __GNUC__
-inline uint32 gcchtonl(uint32 x) {
- // This pragma fools gcc into surpressing all error messages,
- // including the bogus one that it creates for htonl
-# pragma GCC system_header
- return htonl(x);
-}
-#endif
-
-} // G3D namespace
-
-#ifndef _WIN32
-#undef SOCKADDR_IN
-#undef SOCKET
-#endif
-
-#endif
diff --git a/externals/g3dlite/G3D/ParseError.h b/externals/g3dlite/G3D/ParseError.h
deleted file mode 100644
index f02948e3d29..00000000000
--- a/externals/g3dlite/G3D/ParseError.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/**
- @file ParseError.h
-
- @maintainer Morgan McGuire
-
- @created 2009-11-15
- @edited 2009-11-15
-
- Copyright 2000-2009, Morgan McGuire.
- All rights reserved.
- */
-#ifndef G3D_ParseError_h
-#define G3D_ParseError_h
-
-#include "G3D/platform.h"
-#include "G3D/g3dmath.h"
-#include <string>
-
-namespace G3D {
-
-/** Thrown by TextInput, Any, and other parsers on unexpected input. */
-class ParseError {
-public:
- enum {UNKNOWN = -1};
-
- /** Empty means unknown */
- std::string filename;
-
- /** For a binary file, the location of the parse error. -1 if unknown.*/
- int64 byte;
-
- /** For a text file, the line number is the line number of start of token which caused the exception. 1 is
- the first line of the file. -1 means unknown. Note that you can use
- TextInput::Settings::startingLineNumberOffset to shift the effective line
- number that is reported by that class.
- */
- int line;
-
- /** Character number (in the line) of the start of the token which caused the
- exception. 1 is the character in the line. May be -1 if unknown.
- */
- int character;
-
- std::string message;
-
- ParseError() : byte(UNKNOWN), line(UNKNOWN), character(UNKNOWN) {}
-
- virtual ~ParseError() {}
-
- ParseError(const std::string& f, int l, int c, const std::string& m) :
- filename (f), byte(UNKNOWN), line(l), character(c), message(m) {}
-
- ParseError(const std::string& f, int64 b, const std::string& m) :
- filename (f), byte(b), line(UNKNOWN), character(UNKNOWN), message(m) {}
-};
-
-}
-
-#endif
diff --git a/externals/g3dlite/G3D/PhysicsFrame.h b/externals/g3dlite/G3D/PhysicsFrame.h
deleted file mode 100644
index a5a9305b83e..00000000000
--- a/externals/g3dlite/G3D/PhysicsFrame.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/**
- @file PhysicsFrame.h
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2002-07-08
- @edited 2006-01-10
-*/
-
-#ifndef G3D_PHYSICSFRAME_H
-#define G3D_PHYSICSFRAME_H
-
-#include "G3D/platform.h"
-#include "G3D/Vector3.h"
-#include "G3D/Matrix3.h"
-#include "G3D/Quat.h"
-#include "G3D/CoordinateFrame.h"
-#include <math.h>
-#include <string>
-
-
-namespace G3D {
-
-/**
- An RT transformation using a quaternion; suitable for
- physics integration.
-
- This interface is in "Beta" and will change in the next release.
- */
-class PhysicsFrame {
-public:
-
- Quat rotation;
-
- /**
- Takes object space points to world space.
- */
- Vector3 translation;
-
- /**
- Initializes to the identity frame.
- */
- PhysicsFrame();
-
- /**
- Purely translational force
- */
- PhysicsFrame(const Vector3& translation) : translation(translation) {}
-
- PhysicsFrame(const CoordinateFrame& coordinateFrame);
-
- /** Compose: create the transformation that is <I>other</I> followed by <I>this</I>.*/
- PhysicsFrame operator*(const PhysicsFrame& other) const;
-
- virtual ~PhysicsFrame() {}
-
- CoordinateFrame toCoordinateFrame() const;
-
- /**
- Linear interpolation (spherical linear for the rotations).
- */
- PhysicsFrame lerp(
- const PhysicsFrame& other,
- float alpha) const;
-
- void deserialize(class BinaryInput& b);
-
- void serialize(class BinaryOutput& b) const;
-
-};
-
-} // namespace
-
-#endif
diff --git a/externals/g3dlite/G3D/Plane.h b/externals/g3dlite/G3D/Plane.h
deleted file mode 100644
index 360bcd2bc75..00000000000
--- a/externals/g3dlite/G3D/Plane.h
+++ /dev/null
@@ -1,161 +0,0 @@
-/**
- @file Plane.h
-
- Plane class
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2001-06-02
- @edited 2004-07-18
-*/
-
-#ifndef G3D_PLANE_H
-#define G3D_PLANE_H
-
-#include "G3D/platform.h"
-#include "G3D/Vector3.h"
-#include "G3D/Vector4.h"
-#include "G3D/debugAssert.h"
-
-namespace G3D {
-
-/**
- An infinite 2D plane in 3D space.
- */
-class Plane {
-private:
-
- /** normal.Dot(x,y,z) = distance */
- Vector3 _normal;
- float _distance;
-
- /**
- Assumes the normal has unit length.
- */
- Plane(const Vector3& n, float d) : _normal(n), _distance(d) {
- }
-
-public:
-
- Plane() : _normal(Vector3::unitY()), _distance(0) {
- }
-
- /**
- Constructs a plane from three points.
- */
- Plane(
- const Vector3& point0,
- const Vector3& point1,
- const Vector3& point2);
-
- /**
- Constructs a plane from three points, where at most two are
- at infinity (w = 0, not xyz = inf).
- */
- Plane(
- Vector4 point0,
- Vector4 point1,
- Vector4 point2);
-
- /**
- The normal will be unitized.
- */
- Plane(
- const Vector3& __normal,
- const Vector3& point);
-
- static Plane fromEquation(float a, float b, float c, float d);
-
- Plane(class BinaryInput& b);
- void serialize(class BinaryOutput& b) const;
- void deserialize(class BinaryInput& b);
-
- virtual ~Plane() {}
-
- /**
- Returns true if point is on the side the normal points to or
- is in the plane.
- */
- inline bool halfSpaceContains(Vector3 point) const {
- // Clamp to a finite range for testing
- point = point.clamp(Vector3::minFinite(), Vector3::maxFinite());
-
- // We can get away with putting values *at* the limits of the float32 range into
- // a dot product, since the dot product is carried out on float64.
- return _normal.dot(point) >= _distance;
- }
-
- /**
- Returns true if point is on the side the normal points to or
- is in the plane.
- */
- inline bool halfSpaceContains(const Vector4& point) const {
- if (point.w == 0) {
- return _normal.dot(point.xyz()) > 0;
- } else {
- return halfSpaceContains(point.xyz() / point.w);
- }
- }
-
- /**
- Returns true if point is on the side the normal points to or
- is in the plane. Only call on finite points. Faster than halfSpaceContains.
- */
- inline bool halfSpaceContainsFinite(const Vector3& point) const {
- debugAssert(point.isFinite());
- return _normal.dot(point) >= _distance;
- }
-
- /**
- Returns true if the point is nearly in the plane.
- */
- inline bool fuzzyContains(const Vector3 &point) const {
- return fuzzyEq(point.dot(_normal), _distance);
- }
-
- inline const Vector3& normal() const {
- return _normal;
- }
-
- /**
- Returns distance from point to plane. Distance is negative if point is behind (not in plane in direction opposite normal) the plane.
- */
- inline float distance(const Vector3& x) const {
- return (_normal.dot(x) - _distance);
- }
-
- inline Vector3 closestPoint(const Vector3& x) const {
- return x + (_normal * (-distance(x)));
- }
-
- /** Returns normal * distance from origin */
- Vector3 center() const {
- return _normal * _distance;
- }
-
- /**
- Inverts the facing direction of the plane so the new normal
- is the inverse of the old normal.
- */
- void flip();
-
- /**
- Returns the equation in the form:
-
- <CODE>normal.Dot(Vector3(<I>x</I>, <I>y</I>, <I>z</I>)) + d = 0</CODE>
- */
- void getEquation(Vector3 &normal, double& d) const;
- void getEquation(Vector3 &normal, float& d) const;
-
- /**
- ax + by + cz + d = 0
- */
- void getEquation(double& a, double& b, double& c, double& d) const;
- void getEquation(float& a, float& b, float& c, float& d) const;
-
- std::string toString() const;
-};
-
-} // namespace
-
-#endif
diff --git a/externals/g3dlite/G3D/PointHashGrid.h b/externals/g3dlite/G3D/PointHashGrid.h
deleted file mode 100644
index 0db9e677321..00000000000
--- a/externals/g3dlite/G3D/PointHashGrid.h
+++ /dev/null
@@ -1,917 +0,0 @@
-/**
- @file PointHashGrid.h
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @created 2008-07-01
- @edited 2009-05-28
-
- Copyright 2000-2009, Morgan McGuire.
- All rights reserved.
-*/
-#ifndef G3D_PointHashGrid_h
-#define G3D_PointHashGrid_h
-
-#include "G3D/platform.h"
-#include "G3D/EqualsTrait.h"
-#include "G3D/HashTrait.h"
-#include "G3D/Vector3.h"
-#include "G3D/Vector3int32.h"
-#include "G3D/Array.h"
-#include "G3D/Table.h"
-#include "G3D/AABox.h"
-#include "G3D/Sphere.h"
-#include "G3D/SmallArray.h"
-
-namespace G3D {
-
-/**
- Storage of data in a sparse 3D grid of point-based data. The
- space cost for <I>n</I> elements is O(<I>n</I>). For data with
- approximately uniform density (with respect to the radius hint),
- the time cost of searching for neighbors is O(1).
-
- <i>Value</i> must be supported by a G3D::PositionTrait,
- G3D::EqualsTrait, and G3D::HashFunc. overrides are provided for
- common G3D classes like G3D::Vector3.
-*/
-template<class Value,
- class PosFunc = PositionTrait<Value>,
- class EqualsFunc = EqualsTrait<Value>,
- class HashFunc = HashTrait<Vector3int32> >
-class PointHashGrid {
-private:
-
-#define ThisType PointHashGrid<Value, PosFunc, EqualsFunc, HashFunc>
-
- /** A value annotated with precomputed position and hash code.*/
- class Entry {
- public:
- Vector3 position;
- Value value;
- };
-
- /** One cell of the grid. */
- typedef Array<Entry> Cell;
- typedef Table<Vector3int32, Cell, HashFunc> CellTable;
-
- /** The cube of +/-1 along each dimension. Initialized by initOffsetArray.*/
- Vector3int32 m_offsetArray[3*3*3];
-
- /** Incremented every time the data structure is mutated.
- Used by the iterators to determine if the data structure
- has changed since iteration began. */
- int m_epoch;
-
- /** Extent of a cell along one dimension. */
- float m_cellWidth;
-
- /** 1.0 / cell width */
- float m_invCellWidth;
-
- /** Conservative bounds; the actual data may be smaller. */
- AABox m_bounds;
-
- /** Number of elements. */
- int m_size;
-
- /** Non-empty cells indexed by grid position. Actual 3D position is
- <code>position * m_cellWidth</code>*/
- CellTable m_data;
-
- MemoryManager::Ref m_memoryManager;
-
- /** Intentionally unimplemented: prevent copy construction. */
- PointHashGrid(const ThisType&);
-
-
- /** Intentionally unimplemented: prevent assignment. */
- PointHashGrid& operator=(const ThisType&);
-
-
- /** Locate the cell and index within that cell containing v. Called by
- remove() and contains(). */
- bool find(const Value& v,
- Vector3int32& foundCellCoord,
- Cell*& foundCell,
- int& index) {
-
- Vector3 pos;
- PosFunc::getPosition(v, pos);
-
- Vector3int32 cellCoord;
- getCellCoord(pos, cellCoord);
- for (int i = 0; i < 27; ++i) {
- Vector3int32 c = cellCoord + m_offsetArray[i];
- Cell* cell = m_data.getPointer(c);
- if (cell != NULL) {
- // The cell exists
- for (int j = 0; j < cell->size(); ++j) {
- if (EqualsFunc::equals((*cell)[j].value, v)) {
- foundCell = cell;
- index = j;
- foundCellCoord = c;
- return true;
- }
- }
- }
- }
-
- // Not found
- return false;
- }
-
- /** Given a real-space position, returns the cell coord
- containing it.*/
- inline void getCellCoord(const Vector3& pos, Vector3int32& cellCoord) const {
- for (int a = 0; a < 3; ++a) {
- cellCoord[a] = iFloor(pos[a] * m_invCellWidth);
- }
- }
-
- /** Initializes m_offsetArray. */
- void initOffsetArray() {
- int i = 0;
- Vector3int32 d;
- for (d.x = -1; d.x <= +1; ++d.x) {
- for (d.y = -1; d.y <= +1; ++d.y) {
- for (d.z = -1; d.z <= +1; ++d.z) {
- m_offsetArray[i] = d;
- ++i;
- }
- }
- }
-
- // Put (0, 0, 0) first, so that contains() is most likely to find
- // the value quickly.
- i = (1 * 3 + 1) * 3 + 1;
- debugAssert(m_offsetArray[i] == Vector3int32(0,0,0));
- Vector3int32 temp = m_offsetArray[0];
- m_offsetArray[0] = m_offsetArray[i];
- m_offsetArray[i] = temp;
- }
-
-public:
-
- /**
- @param radiusHint the radius that will typically be used with
- beginSphereIntersection and beginBoxIntersection. If two <i>Value</i>s are equal,
- their positions must be within this radius as well.
- */
- PointHashGrid(float radiusHint, const MemoryManager::Ref& m = MemoryManager::create()) : m_size(0), m_memoryManager(m) {
- initOffsetArray();
- m_data.clearAndSetMemoryManager(m_memoryManager);
-
- debugAssertM(radiusHint > 0, "Cell radius must be positive");
- m_cellWidth = radiusHint;
- m_invCellWidth = 1.0f / m_cellWidth;
- }
-
- /**
- If radiusHint is negative, it is automatically chosen to put
- about 5 values in each grid cell (which means about 27 * 5
- values for each beginIntersection call).
- */
- PointHashGrid(const Array<Value>& init, float radiusHint = -1.0f, const MemoryManager::Ref& m = MemoryManager::create()) : m_size(0), m_memoryManager(m) {
- initOffsetArray();
- m_data.clearAndSetMemoryManager(m_memoryManager);
-
- Vector3 lo(Vector3::inf());
- Vector3 hi(-lo);
-
- // Compute bounds
- Array<Entry> entry(init.size());
- for (int i = 0; i < entry.size(); ++i) {
- const Value& value = init[i];
- Vector3 pos = m_posFunc(value);
-
- entry[i].value = value;
- entry[i].hashCode = m_hashFunc(value);
- entry[i].position = pos;
-
- lo = lo.min(pos);
- hi = hi.max(pos);
- }
-
- m_bounds = AABox(lo, hi);
-
- if (radiusHint <= 0) {
- // Compute a good cell width based on the bounds.
- //
- // N numPerCell
- // ----- = ---------
- // volume r^3
-
- float numPerCell = 5;
- radiusHint =
- (float)pow(numPerCell * m_bounds.volume() / init.size(), 1.0 / 3.0);
-
- if (radiusHint == 0) {
- // Volume must have been zero because all points were colocated.
- radiusHint = 0.1f;
- }
- }
-
- insert(init);
- }
-
- /** Returns the number of elements. */
- inline int size() const {
- return m_size;
- }
-
- /** Returns a conservative bounding box around the contents. This is
- conservative because it is not updated when elements are removed. */
- const AABox& conservativeBoxBounds() const {
- return m_bounds;
- }
-
- /** Insert @a v at position @a p given by <code>getPosition(v, p)</code>.
- Multiple elements that are equal may be inserted; all copies will be
- in the data structure. */
- void insert(const Value& v) {
- Vector3 pos;
- PosFunc::getPosition(v, pos);
- Vector3int32 cellCoord;
- getCellCoord(pos, cellCoord);
-
- // See if the cell already exists
- Cell& cell = m_data.getCreate(cellCoord);
-
- if (cell.size() == 0) {
- // Use the same memory manager as for the whole class
- cell.clearAndSetMemoryManager(m_memoryManager);
- }
-
- Entry& entry = cell.next();
- entry.value = v;
- entry.position = pos;
-
- // Update the bounds
- if (size() == 0) {
- m_bounds = AABox(pos);
- } else {
- m_bounds.merge(pos);
- }
-
- ++m_size;
- ++m_epoch;
- }
-
-
- /** Inserts all elements of the array. */
- void insert(const Array<Value>& v) {
- for (int i = 0; i < v.size(); ++i) {
- insert(v[i]);
- }
- }
-
-
- /** If there are multiple copies of an element, you must
- delete them multiple times.
-
- @param shrinkIfNecessary If <b>true</b>, deallocate underlying data
- structures as they are emptied. False increases performace at
- the cost of memory overhead for dynamic structures.
-
- @return true if the element was found.
- */
- bool remove(const Value& v, bool shrinkIfNecessary = true) {
- Cell* cell = NULL;
- int index = 0;
- Vector3int32 cellCoord;
-
- if (find(v, cellCoord, cell, index)) {
- cell->fastRemove(index, shrinkIfNecessary);
- --m_size;
- ++m_epoch;
-
- if ((cell->size() == 0) && shrinkIfNecessary) {
- // Remove the cell itself
-
- // Drop our pointer, which is about to dangle
- cell = NULL;
- bool success = m_data.remove(cellCoord);
- debugAssertM(success, "Data structure corrupt: "
- "tried to remove a cell that doesn't exist.");
- }
-
- return true;
-
- } else {
- return false;
- }
- }
-
- /** Removes all elements of @v. */
- void remove(const Array<Value>& v, bool shrink = true) {
- for (int i = 0; i < v.size(); ++i) {
- remove(v[i], shrink);
- }
- }
-
- ///////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////
-
- class Iterator {
- private:
- friend class ThisType;
-
- bool m_isEnd;
-
- const ThisType* m_grid;
-
- typename CellTable::Iterator m_tableIterator;
-
- /** Index within m_tableIterator->value of the current value. */
- int m_arrayIndex;
-
- const int m_epoch;
-
- /** End iterator. Note that the m_tableIterator is initialized to the end iterator
- of a temporary value! This is ok because we'll never look at the value of the
- m_tableIterator, since we're initializing the "end" Iterator.*/
- Iterator() : m_isEnd(true), m_grid(NULL), m_tableIterator(CellTable().end()),
- m_arrayIndex(0), m_epoch(0) {}
-
- Iterator(const ThisType* grid) :
- m_isEnd(false),
- m_grid(grid),
- m_tableIterator( grid->m_data.begin() ),
- m_arrayIndex(0),
- m_epoch(grid->m_epoch) { }
-
- private:
-
- const Value& value() const {
- debugAssert(! m_isEnd);
- debugAssertM(m_tableIterator->value.size() > m_arrayIndex,
- "No more elements");
- return m_tableIterator->value[m_arrayIndex].value;
- }
-
- public:
-
- inline bool operator!=(const Iterator& other) const {
- if (other.m_isEnd && m_isEnd) {
- return false;
- } else {
- return (m_isEnd != other.m_isEnd) ||
- (m_tableIterator != other.m_tableIterator) ||
- (m_arrayIndex != other.m_arrayIndex);
- }
- }
-
- bool operator==(const Iterator& other) const {
- return !(*this != other);
- }
-
- /** Preincrement */
- Iterator& operator++() {
- debugAssert(! m_isEnd);
- debugAssertM(m_epoch == m_grid->m_epoch,
- "It is illegal to mutate the HashGrid "
- "while iterating through it.");
-
- ++m_arrayIndex;
-
- if (m_arrayIndex >= m_tableIterator->value.size()) {
- // Move on to the next cell
- ++m_tableIterator;
- m_arrayIndex = 0;
-
- // Check to see if we're at the end
- m_isEnd = (m_tableIterator == m_grid->m_data.end());
- }
-
- return *this;
- }
-
- /** Post increment (slower) */
- Iterator operator++(int) {
- debugAssert(! m_isEnd);
- Iterator old = *this;
- ++(*this);
- return old;
- }
-
- const Value& operator*() const { return value(); }
- const Value* operator->() const { return &value(); }
- operator Value*() const { return &value(); }
- }; // Iterator
-
-
- /** Iterate through all members. It is an error to mutate the HashGrid
- while iterating through it. Each member can be accessed by "dereferencing"
- the iterator:
-
- <pre>
- for (Grid::Iterator i = grid.begin(); i != grid.end(), ++i) {
- const Value& = *i;
- ...
- }
- </pre>
- */
- Iterator begin() const {
- return Iterator(this);
- }
-
- const Iterator& end() const {
- static const Iterator it;
- return it;
- }
-
- ///////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////
-
- // Forward declaration required by older gcc versions for friend declaration in BoxIterator
- class SphereIterator;
- class BoxIterator {
- private:
- friend class ThisType;
- friend class SphereIterator;
-
- bool m_isEnd;
-
- const ThisType* m_grid;
-
- /** Lower bound on the boxes covered, inclusive. */
- Vector3int32 m_lo;
-
- /** Upper bound on the boxes covered, inclusive.*/
- Vector3int32 m_hi;
-
- /** If true, test values against m_box before returning them.*/
- bool m_exact;
-
- /** The underlying box in 3D space */
- AABox m_box;
-
- /** The iterator winds through the 3D grid between m_lo and (m_lo + m_extent) in
- Z,Y,X-major order. This is the index keeping track of how
- far it has come */
- Vector3int32 m_current;
-
- /** The current cell. */
- Cell* m_cell;
-
- /** Index within m_cell of the current value */
- int m_arrayIndex;
-
- const int m_epoch;
-
-
- /** Called from advance() */
- void advanceCell() {
- do {
- ++m_current.x;
- if (m_current.x > m_hi.x) {
- m_current.x = m_lo.x;
- ++m_current.y;
- if (m_current.y > m_hi.y) {
- m_current.y = m_lo.y;
- ++m_current.z;
- if (m_current.z > m_hi.z) {
- m_isEnd = true;
- return;
- }
- }
- }
-
- // Pick up the new cell
- m_cell = m_grid->m_data.getPointer(m_current);
- // Keep advancing if the cell does not exist
- } while ((m_cell == NULL) || (m_cell->size() == 0));
- }
-
- /** Advance to the next value */
- void advance() {
- debugAssert(! m_isEnd);
-
- do {
- ++m_arrayIndex;
- bool inConstructor = (m_cell == NULL);
- if (inConstructor || m_arrayIndex >= m_cell->size()) {
- advanceCell();
- m_arrayIndex = 0;
-
- if (m_isEnd) {
- // Ran out of values
- return;
- }
- debugAssert(m_cell != NULL);
- }
-
- // Advance until we have a value that can be returned, either
- // because we don't care about exactness or because it is
- // guaranteed to be within the box.
- } while (m_exact && ! m_box.contains(position()));
- }
-
-
- /** End iterator */
- BoxIterator() : m_isEnd(true), m_grid(NULL), m_exact(true), m_current(0,0,0), m_cell(NULL), m_arrayIndex(0), m_epoch(0) {}
-
- /** Begin iterator */
- BoxIterator(const ThisType* grid, bool exact, const AABox& box) :
- m_isEnd(false),
- m_grid(grid),
- m_exact(exact),
- m_box(box),
- m_current(-1, 0 ,0),
- m_cell(NULL),
- m_arrayIndex(0),
- m_epoch(grid->m_epoch) {
-
- m_grid->getCellCoord(box.low(), m_lo);
- m_grid->getCellCoord(box.high(), m_hi);
-
- // Get to the first value
- m_current = m_lo;
- // Back up one so that advancing takes us to the first
- --m_current.x;
- advance();
- }
-
- const Value& value() const {
- debugAssert(! m_isEnd);
- return (*m_cell)[m_arrayIndex].value;
- }
-
- /** Used by SphereIterator::advance() */
- const Vector3& position() const {
- debugAssert(! m_isEnd);
- return (*m_cell)[m_arrayIndex].position;
- }
-
- // Intentionally unimplemented
- BoxIterator& operator=(const BoxIterator&);
-
- public:
-
- inline bool operator!=(const BoxIterator& other) const {
- if (other.m_isEnd && m_isEnd) {
- return false;
- } else {
- return (m_isEnd != other.m_isEnd) ||
- (m_cell != other.m_cell) ||
- (m_arrayIndex != other.m_arrayIndex);
- }
- }
-
- bool operator==(const BoxIterator& other) const {
- return !(*this != other);
- }
-
- /** Preincrement */
- BoxIterator& operator++() {
- debugAssert(! m_isEnd);
- debugAssertM(m_epoch == m_grid->m_epoch,
- "It is illegal to mutate the HashGrid "
- "while iterating through it.");
-
- advance();
-
- return *this;
- }
-
- /** Post increment (slower) */
- BoxIterator operator++(int) {
- Iterator old = *this;
- ++(*this);
- return old;
- }
-
- const Value& operator*() const { return value(); }
- const Value* operator->() const { return &value(); }
- operator Value*() const { return &value(); }
-
- bool hasMore() const {
- return ! m_isEnd;
- }
- }; // BoxIterator
-
- /**
- Finds all values whose positions are within @a box. It is an error to
- mutate the PointHashGrid while iterating through it.
-
- @param exact If false, the iterator will execute more quickly but will likely return some
- values that lie outside the box. Set exact = false if you are going to test the
- results against the yourself box anyway.
- */
- BoxIterator beginBoxIntersection(const AABox& box, bool exact = true) const {
- return BoxIterator(this, exact, box);
- }
-
- const BoxIterator& endBoxIntersection() const {
- static const BoxIterator it;
- return it;
- }
-
- ///////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////
-
- class SphereIterator {
- private:
-
- friend class ThisType;
-
- bool m_isEnd;
- Sphere m_sphere;
- BoxIterator m_boxIterator;
-
- SphereIterator() : m_isEnd(true) {}
-
- void advance() {
- if (! m_boxIterator.hasMore()) {
- m_isEnd = true;
- return;
- }
-
- while (! m_sphere.contains(m_boxIterator.position())) {
- ++m_boxIterator;
-
- if (! m_boxIterator.hasMore()) {
- m_isEnd = true;
- return;
- }
- }
- }
-
- static AABox getBoundingBox(const Sphere& s) {
- AABox box;
- s.getBounds(box);
- return box;
- }
-
- SphereIterator(const ThisType* grid, const Sphere& sphere) :
- m_isEnd(false),
- m_sphere(sphere),
- m_boxIterator(grid, false, getBoundingBox(sphere)) {
-
- // Find the first element that is actually in the sphere,
- // not just the box.
- advance();
- }
-
- const Value& value() const {
- return *m_boxIterator;
- }
-
- // TODO: if the sphere is very big compared to radius, check each
- // cell's box to see if the cell itself is actually inside the sphere
- // before iterating through it, since there may be many boxes outside the sphere.
-
- // Intentionally unimplemented
- SphereIterator& operator=(const SphereIterator&);
- public:
-
- inline bool operator!=(const SphereIterator& other) const {
- if (other.m_isEnd && m_isEnd) {
- return false;
- } else {
- return
- (m_isEnd != other.m_isEnd) ||
- (m_sphere != other.m_sphere) ||
- (m_boxIterator != other.m_boxIterator);
- }
- }
-
- bool operator==(const SphereIterator& other) const {
- return !(*this != other);
- }
-
-
-
- /** Preincrement */
- SphereIterator& operator++() {
- debugAssert(! m_isEnd);
-
- ++m_boxIterator;
- advance();
-
- return *this;
- }
-
- /** Post increment (slower) */
- SphereIterator operator++(int) {
- Iterator old = *this;
- ++(*this);
- return old;
- }
-
- const Value& operator*() const { return value(); }
- const Value* operator->() const { return &value(); }
- operator Value*() const { return &value(); }
-
- bool hasMore() const {
- return ! m_isEnd;
- }
- }; // SphereIterator
-
- /**
- Finds all values whose positions are within @a sphere. It is an error
- to mutate the HashGrid while iterating through it.
- */
- SphereIterator beginSphereIntersection(const Sphere& sphere) const {
- return SphereIterator(this, sphere);
- }
-
- const SphereIterator& endSphereIntersection() const {
- static const SphereIterator it;
- return it;
- }
-
- ///////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////
-
- /**
- Dereference to access the bounds() and size() [element count] of the underlying
- cell objet.
-
- Example:
- <pre>
- for(PointHashGrid<Vector3>::CellIterator iter = grid.beginCells(); iter != grid.endCells(); ++iter) {
- entriesFound += iter->size();
- }
- </pre>
- */
- class CellIterator {
- private:
- friend class ThisType;
-
- bool m_isEnd;
- const ThisType* m_grid;
- typename CellTable::Iterator m_tableIterator;
- const int m_epoch;
-
-
- Cell& cell() {
- return m_tableIterator->value;
- }
-
- public:
-
- class CellObject {
- friend class CellIterator;
- private:
- const CellIterator* m_parent;
-
- CellObject() : m_parent(NULL) {}
-
- public:
-
- /** Returns the bounds on this cell */
- AABox bounds() const {
- const Vector3int32& k = m_parent->m_tableIterator->key;
- return AABox(Vector3(k) * m_parent->m_cellWidth,
- Vector3(k + Vector3int32(1, 1, 1)) * m_parent->m_cellWidth);
- }
-
- /** Number of elements inside this cell */
- int size() const {
- debugAssert(! m_parent->m_isEnd);
- return m_parent->m_tableIterator->value.size();
- }
- };
-
- private:
- /** Used to make the indirection work.*/
- CellObject m_indirection;
-
- /** End iterator. Note that the m_tableIterator is initialized to the end iterator
- of a temporary value! This is ok because we'll never look at the value of the
- m_tableIterator, since we're initializing the "end" Iterator.*/
- CellIterator() :
- m_isEnd(true),
- m_grid(NULL),
- m_tableIterator( CellTable().end() ),
- m_epoch(0) {}
-
- CellIterator(const ThisType* grid) :
- m_isEnd(false),
- m_grid(grid),
- m_tableIterator( grid->m_data.begin()),
- m_epoch(grid->m_epoch) {
- m_indirection.m_parent = this;
- m_isEnd = ! m_tableIterator.hasMore();
- }
-
- // Intentionally unimplemented
- CellIterator& operator=(const CellIterator&);
-
- public:
-
- const CellObject& operator*() const { return m_indirection; }
- const CellObject* operator->() const { return &m_indirection; }
- operator CellObject*() const { return &m_indirection; }
-
- inline bool operator!=(const CellIterator& other) const {
- // != is called more often than == during iteration
- return !(
- (m_isEnd && other.m_isEnd) ||
- ((m_isEnd == other.m_isEnd) &&
- (m_tableIterator != other.m_tableIterator)));
- }
-
- bool operator==(const CellIterator& other) const {
- return !(*this != other);
- }
-
- /** Preincrement */
- CellIterator& operator++() {
- debugAssertM(m_epoch == m_grid->m_epoch,
- "It is illegal to mutate the HashGrid while "
- "iterating through it.");
- ++m_tableIterator;
- m_isEnd = ! m_tableIterator.hasMore();
- return *this;
- }
-
- /** Post increment (slower) */
- CellIterator operator++(int) {
- Iterator old = *this;
- ++(*this);
- return old;
- }
-
- bool hasMore() const {
- return ! m_isEnd;
- }
- }; // CellIterator
-
- /** Iterates through the non-empty cells. This is intended primarily for
- debugging and visualizing the data structure.*/
- CellIterator beginCells() const {
- return CellIterator(this);
- }
-
- const CellIterator& endCells() const {
- static const CellIterator it;
- return it;
- }
-
- ///////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////
-
- /** Returns true if there is a value that is exactly equal to @a v. This will
- check all neighboring cells to avoid roundoff error at cell boundaries.
- */
- bool contains(const Value& v) const {
- Cell* cell = NULL;
- int index = 0;
- Vector3int32 cellCoord;
- return const_cast<ThisType*>(this)->find(v, cellCoord, cell, index);
- }
-
- /** Calls delete on all of the values, which are assumed to be pointers.
- This is a helper to avoid requiring you to iterate through the data
- structure, removing and deleting each one. Clears the PointHashGrid at the
- end.
-
- Using objects (instead of pointers) or reference counted pointers is
- recommended over using pointers and this deleteAll method.*/
- void deleteAll() {
- for (Iterator it = begin(); it.hasMore(); ++it) {
- delete *it;
- }
- clear();
- }
-
- void clearAndSetMemoryManager(const MemoryManager::Ref& m) {
- ++m_epoch;
- m_size = 0;
- m_bounds = AABox();
-
- m_data.clearAndSetMemoryManager(m);
- m_memoryManager = m;
- }
-
- /** Removes all data.
- @param shrink If true, underlying structures are deallocated as
- they are freed.*/
- void clear(bool shrink = true) {
- m_size = 0;
- m_bounds = AABox();
- if (! shrink) {
- // Remove all data
- for (CellIterator it = beginCells(); it.hasMore(); ++it) {
- it.cell().clear(true);
- }
- } else {
- m_data.clear();
- }
- ++m_epoch;
- }
-
- int debugGetDeepestBucketSize() const {
- return m_data.debugGetDeepestBucketSize();
- }
-
- float debugGetAverageBucketSize() const {
- return m_data.debugGetAverageBucketSize();
- }
-#undef ThisType
-};
-
-} // G3D
-#endif
diff --git a/externals/g3dlite/G3D/PointKDTree.h b/externals/g3dlite/G3D/PointKDTree.h
deleted file mode 100644
index 151cbd5f2f3..00000000000
--- a/externals/g3dlite/G3D/PointKDTree.h
+++ /dev/null
@@ -1,1185 +0,0 @@
-/**
- @file PointKDTree.h
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2004-01-11
- @edited 2008-11-02
-
- Copyright 2000-2009, Morgan McGuire.
- All rights reserved.
-
- */
-
-#ifndef X_PointKDTree_H
-#define X_PointKDTree_H
-
-#include "G3D/platform.h"
-#include "G3D/Array.h"
-#include "G3D/Table.h"
-#include "G3D/Vector2.h"
-#include "G3D/Vector3.h"
-#include "G3D/Vector4.h"
-#include "G3D/AABox.h"
-#include "G3D/Sphere.h"
-#include "G3D/Box.h"
-#include "G3D/BinaryInput.h"
-#include "G3D/BinaryOutput.h"
-#include "G3D/CollisionDetection.h"
-#include "G3D/GCamera.h"
-#include "G3D/PositionTrait.h"
-#include <algorithm>
-
-namespace G3D {
-
-/**
- A set data structure that supports spatial queries using an axis-aligned
- BSP tree for speed.
-
- PointKDTree allows you to quickly find points in 3D that lie within
- a box or sphere. For large sets of objects it is much faster
- than testing each object for a collision. See also G3D::KDTree; this class
- is optimized for point sets, e.g.,for use in photon mapping and mesh processing.
-
- <B>Template Parameters</B>
-
- <br>
-
- <br>The template parameter <I>T</I> must be one for which
- the following functions are overloaded:
-
- <pre>
- T::T(); <I>(public constructor of no arguments)</I>
-
- template<> struct PositionTrait<class T> {
- static void getPosition(const T& v, G3D::Vector3& p);};
-
- template <> struct HashTrait<class T> {
- static size_t hashCode(const T& key);};
-
- template<> struct EqualsTrait<class T> {
- static bool equals(const T& a, const T& b); };
- </pre>
-
- <p>
-
- G3D provides these for the Vector2, Vector3, and Vector4 classes.
- If you use a custom class, or a pointer to a custom class, you will need
- to define those functions.
-
- <B>Moving %Set Members</B>
- <DT>It is important that objects do not move without updating the
- PointKDTree. If the position of an object is about
- to change, PointKDTree::remove it before they change and
- PointKDTree::insert it again afterward. For objects
- where the hashCode and == operator are invariant with respect
- to the 3D position,
- you can use the PointKDTree::update method as a shortcut to
- insert/remove an object in one step after it has moved.
-
-
- Note: Do not mutate any value once it has been inserted into PointKDTree. Values
- are copied interally. All PointKDTree iterators convert to pointers to constant
- values to reinforce this.
-
- If you want to mutate the objects you intend to store in a PointKDTree
- simply insert <I>pointers</I> to your objects instead of the objects
- themselves, and ensure that the above operations are defined. (And
- actually, because values are copied, if your values are large you may
- want to insert pointers anyway, to save space and make the balance
- operation faster.)
-
- <B>Dimensions</B>
- Although designed as a 3D-data structure, you can use the PointKDTree
- for data distributed along 2 or 1 axes by simply returning bounds
- that are always zero along one or more dimensions.
-
-*/
-template<class T,
- class PositionFunc = PositionTrait<T>,
- class HashFunc = HashTrait<T>,
- class EqualsFunc = EqualsTrait<T> >
-class PointKDTree {
-protected:
-#define TreeType PointKDTree<T, PositionFunc, HashFunc, EqualsFunc>
-
- // Unlike the KDTree, the PointKDTree assumes that T elements are
- // small and keeps the handle and cached position together instead of
- // placing them in separate bounds arrays. Also note that a copy of T
- // is kept in the member table and that there is no indirection.
- class Handle {
- private:
- Vector3 m_position;
-
- public:
- T value;
-
- inline Handle() {}
- inline Handle(const T& v) : value(v) {
- PositionFunc::getPosition(v, m_position);
- }
-
- /** Used by makeNode to create fake handles for partitioning. */
- void setPosition(const Vector3& v) {
- m_position = v;
- }
-
- inline const Vector3& position() const {
- return m_position;
- }
- };
-
- /** Returns the bounds of the sub array. Used by makeNode. */
- static AABox computeBounds(
- const Array<Handle>& point) {
-
- if (point.size() == 0) {
- return AABox(Vector3::inf(), Vector3::inf());
- }
-
- AABox bounds(point[0].position());
-
- for (int p = 0; p < point.size(); ++p) {
- bounds.merge(point[p].position());
- }
-
- return bounds;
- }
-
- class Node {
- public:
-
- /** Spatial bounds on all values at this node and its children, based purely on
- the parent's splitting planes. May be infinite */
- AABox splitBounds;
-
- Vector3::Axis splitAxis;
-
- /** Location along the specified axis */
- float splitLocation;
-
- /** child[0] contains all values strictly
- smaller than splitLocation along splitAxis.
-
- child[1] contains all values strictly
- larger.
-
- Both may be NULL if there are not enough
- values to bother recursing.
- */
- Node* child[2];
-
- /** Values if this is a leaf node). */
- Array<Handle> valueArray;
-
- /** Creates node with NULL children */
- Node() {
- splitAxis = Vector3::X_AXIS;
- splitLocation = 0;
- splitBounds = AABox(-Vector3::inf(), Vector3::inf());
- for (int i = 0; i < 2; ++i) {
- child[i] = NULL;
- }
- }
-
- /**
- Doesn't clone children.
- */
- Node(const Node& other) : valueArray(other.valueArray) {
- splitAxis = other.splitAxis;
- splitLocation = other.splitLocation;
- splitBounds = other.splitBounds;
- for (int i = 0; i < 2; ++i) {
- child[i] = NULL;
- }
- }
-
- /** Copies the specified subarray of pt into point, NULLs the children.
- Assumes a second pass will set splitBounds. */
- Node(const Array<Handle>& pt) {
- splitAxis = Vector3::X_AXIS;
- splitLocation = 0;
- for (int i = 0; i < 2; ++i) {
- child[i] = NULL;
- }
- valueArray = pt;
- }
-
-
- /** Deletes the children (but not the values) */
- ~Node() {
- for (int i = 0; i < 2; ++i) {
- delete child[i];
- }
- }
-
-
- /** Returns true if this node is a leaf (no children) */
- inline bool isLeaf() const {
- return (child[0] == NULL) && (child[1] == NULL);
- }
-
-
- /**
- Recursively appends all handles and children's handles
- to the array.
- */
- void getHandles(Array<Handle>& handleArray) const {
- handleArray.append(valueArray);
- for (int i = 0; i < 2; ++i) {
- if (child[i] != NULL) {
- child[i]->getHandles(handleArray);
- }
- }
- }
-
-
- void verifyNode(const Vector3& lo, const Vector3& hi) {
- // debugPrintf("Verifying: split %d @ %f [%f, %f, %f], [%f, %f, %f]\n",
- // splitAxis, splitLocation, lo.x, lo.y, lo.z, hi.x, hi.y, hi.z);
-
- debugAssert(lo == splitBounds.low());
- debugAssert(hi == splitBounds.high());
-
- for (int i = 0; i < valueArray.length(); ++i) {
- const Vector3& b = valueArray[i].position();
- debugAssert(splitBounds.contains(b));
- }
-
- if (child[0] || child[1]) {
- debugAssert(lo[splitAxis] < splitLocation);
- debugAssert(hi[splitAxis] > splitLocation);
- }
-
- Vector3 newLo = lo;
- newLo[splitAxis] = splitLocation;
- Vector3 newHi = hi;
- newHi[splitAxis] = splitLocation;
-
- if (child[0] != NULL) {
- child[0]->verifyNode(lo, newHi);
- }
-
- if (child[1] != NULL) {
- child[1]->verifyNode(newLo, hi);
- }
- }
-
-
- /**
- Stores the locations of the splitting planes (the structure but not the content)
- so that the tree can be quickly rebuilt from a previous configuration without
- calling balance.
- */
- static void serializeStructure(const Node* n, BinaryOutput& bo) {
- if (n == NULL) {
- bo.writeUInt8(0);
- } else {
- bo.writeUInt8(1);
- n->splitBounds.serialize(bo);
- serialize(n->splitAxis, bo);
- bo.writeFloat32(n->splitLocation);
- for (int c = 0; c < 2; ++c) {
- serializeStructure(n->child[c], bo);
- }
- }
- }
-
- /** Clears the member table */
- static Node* deserializeStructure(BinaryInput& bi) {
- if (bi.readUInt8() == 0) {
- return NULL;
- } else {
- Node* n = new Node();
- n->splitBounds.deserialize(bi);
- deserialize(n->splitAxis, bi);
- n->splitLocation = bi.readFloat32();
- for (int c = 0; c < 2; ++c) {
- n->child[c] = deserializeStructure(bi);
- }
- }
- }
-
- /** Returns the deepest node that completely contains bounds. */
- Node* findDeepestContainingNode(const Vector3& point) {
-
- // See which side of the splitting plane the bounds are on
- if (point[splitAxis] < splitLocation) {
- // Point is on the low side. Recurse into the child
- // if it exists.
- if (child[0] != NULL) {
- return child[0]->findDeepestContainingNode(point);
- }
- } else if (point[splitAxis] > splitLocation) {
- // Point is on the high side, recurse into the child
- // if it exists.
- if (child[1] != NULL) {
- return child[1]->findDeepestContainingNode(point);
- }
- }
-
- // There was no containing child, so this node is the
- // deepest containing node.
- return this;
- }
-
- /** Appends all members that intersect the box.
- If useSphere is true, members are tested against the sphere instead. */
- void getIntersectingMembers(
- const AABox& sphereBounds,
- const Sphere& sphere,
- Array<T>& members) const {
-
- // Test all values at this node. Extract the
- // underlying C array for speed
- const int N = valueArray.size();
- const Handle* handleArray = valueArray.getCArray();
-
- const float r2 = square(sphere.radius);
-
- // Copy the sphere center so that it is on the stack near the radius
- const Vector3 center = sphere.center;
- for (int v = 0; v < N; ++v) {
- if ((center - handleArray[v].position()).squaredLength() <= r2) {
- members.append(handleArray[v].value);
- }
- }
-
- // If the left child overlaps the box, recurse into it
- if (child[0] && (sphereBounds.low()[splitAxis] < splitLocation)) {
- child[0]->getIntersectingMembers(sphereBounds, sphere, members);
- }
-
- // If the right child overlaps the box, recurse into it
- if (child[1] && (sphereBounds.high()[splitAxis] > splitLocation)) {
- child[1]->getIntersectingMembers(sphereBounds, sphere, members);
- }
- }
-
- /** Appends all members that intersect the box.
- If useSphere is true, members are tested against the sphere instead.
-
- Implemented using both box and sphere tests to simplify the implementation
- of a future beginSphereInteresection iterator using the same underlying
- BoxIterator class.
- */
- void getIntersectingMembers(
- const AABox& box,
- const Sphere& sphere,
- Array<T>& members,
- bool useSphere) const {
-
- // Test all values at this node
- for (int v = 0; v < valueArray.size(); ++v) {
- if ((useSphere && sphere.contains(valueArray[v].position())) ||
- (! useSphere && box.contains(valueArray[v].position()))) {
- members.append(valueArray[v].value);
- }
- }
-
- // If the left child overlaps the box, recurse into it
- if ((child[0] != NULL) && (box.low()[splitAxis] < splitLocation)) {
- child[0]->getIntersectingMembers(box, sphere, members, useSphere);
- }
-
- // If the right child overlaps the box, recurse into it
- if ((child[1] != NULL) && (box.high()[splitAxis] > splitLocation)) {
- child[1]->getIntersectingMembers(box, sphere, members, useSphere);
- }
- }
-
- /**
- Recurse through the tree, assigning splitBounds fields.
- */
- void assignSplitBounds(const AABox& myBounds) {
- splitBounds = myBounds;
-
-# ifdef G3D_DEBUG
- if (child[0] || child[1]) {
- debugAssert(splitBounds.high()[splitAxis] > splitLocation);
- debugAssert(splitBounds.low()[splitAxis] < splitLocation);
- }
-# endif
-
- AABox childBounds[2];
- myBounds.split(splitAxis, splitLocation, childBounds[0], childBounds[1]);
-
- for (int c = 0; c < 2; ++c) {
- if (child[c]) {
- child[c]->assignSplitBounds(childBounds[c]);
- }
- }
- }
- };
-
- class AxisComparator {
- private:
- Vector3::Axis sortAxis;
-
- public:
-
- AxisComparator(Vector3::Axis s) : sortAxis(s) {}
-
- inline int operator()(const Handle& A, const Handle& B) const {
- if (A.position()[sortAxis] > B.position()[sortAxis]) {
- return -1;
- } else if (A.position()[sortAxis] < B.position()[sortAxis]) {
- return 1;
- } else {
- return 0;
- }
- }
- };
-
- /**
- Recursively subdivides the subarray.
-
- The source array will be cleared after it is used
-
- Call assignSplitBounds() on the root node after making a tree.
- */
- Node* makeNode(
- Array<Handle>& source,
- Array<Handle>& temp,
- int valuesPerNode,
- int numMeanSplits) {
-
- Node* node = NULL;
-
- if (source.size() <= valuesPerNode) {
- // Make a new leaf node
- node = new Node(source);
-
- // Set the pointers in the memberTable
- for (int i = 0; i < source.size(); ++i) {
- memberTable.set(source[i].value, node);
- }
-
- } else {
- // Make a new internal node
- node = new Node();
-
- const AABox bounds = computeBounds(source);
- const Vector3 extent = bounds.high() - bounds.low();
-
- Vector3::Axis splitAxis = extent.primaryAxis();
-
- float splitLocation;
-
- Array<Handle> lt, gt;
-
- if (numMeanSplits <= 0) {
- source.medianPartition(lt, node->valueArray, gt, temp, AxisComparator(splitAxis));
- splitLocation = node->valueArray[0].position()[splitAxis];
-
- if ((node->valueArray.size() > source.size() / 2) &&
- (source.size() > 10)) {
- // Our median split put an awful lot of points on the splitting plane. Try a mean
- // split instead
- numMeanSplits = 1;
- }
- }
-
- if (numMeanSplits > 0) {
- // Compute the mean along the axis
-
- splitLocation = (bounds.high()[splitAxis] +
- bounds.low()[splitAxis]) / 2.0;
-
- Handle splitHandle;
- Vector3 v;
- v[splitAxis] = splitLocation;
- splitHandle.setPosition(v);
-
- source.partition(splitHandle, lt, node->valueArray, gt, AxisComparator(splitAxis));
- }
-
-# if defined(G3D_DEBUG) && defined(VERIFY_TREE)
- for (int i = 0; i < lt.size(); ++i) {
- const Vector3& v = lt[i].position();
- debugAssert(v[splitAxis] < splitLocation);
- }
- for (int i = 0; i < gt.size(); ++i) {
- debugAssert(gt[i].position()[splitAxis] > splitLocation);
- }
- for (int i = 0; i < node->valueArray.size(); ++i) {
- debugAssert(node->valueArray[i].position()[splitAxis] == splitLocation);
- }
-# endif
-
- node->splitAxis = splitAxis;
- node->splitLocation = splitLocation;
-
- // Throw away the source array to save memory
- source.fastClear();
-
- if (lt.size() > 0) {
- node->child[0] = makeNode(lt, temp, valuesPerNode, numMeanSplits - 1);
- }
-
- if (gt.size() > 0) {
- node->child[1] = makeNode(gt, temp, valuesPerNode, numMeanSplits - 1);
- }
-
- // Add the values stored at this interior node to the member table
- for(int i = 0; i < node->valueArray.size(); ++i) {
- memberTable.set(node->valueArray[i].value, node);
- }
-
- }
-
- return node;
- }
-
- /**
- Recursively clone the passed in node tree, setting
- pointers for members in the memberTable as appropriate.
- called by the assignment operator.
- */
- Node* cloneTree(Node* src) {
- Node* dst = new Node(*src);
-
- // Make back pointers
- for (int i = 0; i < dst->valueArray.size(); ++i) {
- memberTable.set(dst->valueArray[i].value, dst);
- }
-
- // Clone children
- for (int i = 0; i < 2; ++i) {
- if (src->child[i] != NULL) {
- dst->child[i] = cloneTree(src->child[i]);
- }
- }
-
- return dst;
- }
-
- /** Maps members to the node containing them */
- typedef Table<T, Node*, HashFunc, EqualsFunc> MemberTable;
- MemberTable memberTable;
-
- Node* root;
-
-public:
-
- /** To construct a balanced tree, insert the elements and then call
- PointKDTree::balance(). */
- PointKDTree() : root(NULL) {}
-
-
- PointKDTree(const PointKDTree& src) : root(NULL) {
- *this = src;
- }
-
-
- PointKDTree& operator=(const PointKDTree& src) {
- delete root;
- // Clone tree takes care of filling out the memberTable.
- root = cloneTree(src.root);
- return *this;
- }
-
-
- ~PointKDTree() {
- clear();
- }
-
- /**
- Throws out all elements of the set and erases the structure of the tree.
- */
- void clear() {
- memberTable.clear();
- delete root;
- root = NULL;
- }
-
- /** Removes all elements of the set while maintaining the structure of the tree */
- void clearData() {
- memberTable.clear();
- Array<Node*> stack;
- stack.push(root);
- while (stack.size() > 0) {
- Node* node = stack.pop();
- node->valueArray.fastClear();
-
- for (int i = 0; i < 2; ++i) {
- if (node->child[i] != NULL) {
- stack.push(node->child[i]);
- }
- }
- }
- }
-
-
- int size() const {
- return memberTable.size();
- }
-
- /**
- Inserts an object into the set if it is not
- already present. O(log n) time. Does not
- cause the tree to be balanced.
- */
- void insert(const T& value) {
- if (contains(value)) {
- // Already in the set
- return;
- }
-
- Handle h(value);
-
- if (root == NULL) {
- // This is the first node; create a root node
- root = new Node();
- }
-
- Node* node = root->findDeepestContainingNode(h.position());
-
- // Insert into the node
- node->valueArray.append(h);
-
- // Insert into the node table
- memberTable.set(value, node);
- }
-
- /** Inserts each elements in the array in turn. If the tree
- begins empty (no structure and no elements), this is faster
- than inserting each element in turn. You still need to balance
- the tree at the end.*/
- void insert(const Array<T>& valueArray) {
- // Pre-size the member table to avoid multiple allocations
- memberTable.setSizeHint(valueArray.size() + size());
-
- if (root == NULL) {
- // Optimized case for an empty tree; don't bother
- // searching or reallocating the root node's valueArray
- // as we incrementally insert.
- root = new Node();
- root->valueArray.resize(valueArray.size());
- for (int i = 0; i < valueArray.size(); ++i) {
- // Insert in opposite order so that we have the exact same
- // data structure as if we inserted each (i.e., order is reversed
- // from array).
- root->valueArray[valueArray.size() - i - 1] = Handle(valueArray[i]);
- memberTable.set(valueArray[i], root);
- }
- } else {
- // Insert at appropriate tree depth.
- for (int i = 0; i < valueArray.size(); ++i) {
- insert(valueArray[i]);
- }
- }
- }
-
-
- /**
- Returns true if this object is in the set, otherwise
- returns false. O(1) time.
- */
- bool contains(const T& value) {
- return memberTable.containsKey(value);
- }
-
-
- /**
- Removes an object from the set in O(1) time.
- It is an error to remove members that are not already
- present. May unbalance the tree.
-
- Removing an element never causes a node (split plane) to be removed...
- nodes are only changed when the tree is rebalanced. This behavior
- is desirable because it allows the split planes to be serialized,
- and then deserialized into an empty tree which can be repopulated.
- */
- void remove(const T& value) {
- debugAssertM(contains(value),
- "Tried to remove an element from a "
- "PointKDTree that was not present");
-
- Array<Handle>& list = memberTable[value]->valueArray;
-
- // Find the element and remove it
- for (int i = list.length() - 1; i >= 0; --i) {
- if (list[i].value == value) {
- list.fastRemove(i);
- break;
- }
- }
- memberTable.remove(value);
- }
-
-
- /**
- If the element is in the set, it is removed.
- The element is then inserted.
-
- This is useful when the == and hashCode methods
- on <I>T</I> are independent of the bounds. In
- that case, you may call update(v) to insert an
- element for the first time and call update(v)
- again every time it moves to keep the tree
- up to date.
- */
- void update(const T& value) {
- if (contains(value)) {
- remove(value);
- }
- insert(value);
- }
-
-
- /**
- Rebalances the tree (slow). Call when objects
- have moved substantially from their original positions
- (which unbalances the tree and causes the spatial
- queries to be slow).
-
- @param valuesPerNode Maximum number of elements to put at
- a node.
-
- @param numMeanSplits numMeanSplits = 0 gives a
- fully axis aligned BSP-tree, where the balance operation attempts to balance
- the tree so that every splitting plane has an equal number of left
- and right children (i.e. it is a <B>median</B> split along that axis).
- This tends to maximize average performance; all querries will return in the same amount of time.
-
- You can override this behavior by
- setting a number of <B>mean</B> (average) splits. numMeanSplits = MAX_INT
- creates a full oct-tree, which tends to optimize peak performance (some areas of the scene will terminate after few recursive splits) at the expense of
- peak performance.
- */
- void balance(int valuesPerNode = 40, int numMeanSplits = 3) {
- if (root == NULL) {
- // Tree is empty
- return;
- }
-
- Array<Handle> handleArray;
- root->getHandles(handleArray);
-
- // Delete the old tree
- clear();
-
- Array<Handle> temp;
- root = makeNode(handleArray, temp, valuesPerNode, numMeanSplits);
- temp.fastClear();
-
- // Walk the tree, assigning splitBounds. We start with unbounded
- // space.
- root->assignSplitBounds(AABox::maxFinite());
-
-# ifdef _DEBUG
- root->verifyNode(Vector3::minFinite(), Vector3::maxFinite());
-# endif
- }
-
-private:
-
- /**
- Returns the elements
-
- @param parentMask The mask that this node returned from culledBy.
- */
- static void getIntersectingMembers(
- const Array<Plane>& plane,
- Array<T>& members,
- Node* node,
- uint32 parentMask) {
-
- int dummy;
-
- if (parentMask == 0) {
- // None of these planes can cull anything
- for (int v = node->valueArray.size() - 1; v >= 0; --v) {
- members.append(node->valueArray[v].value);
- }
-
- // Iterate through child nodes
- for (int c = 0; c < 2; ++c) {
- if (node->child[c]) {
- getIntersectingMembers(plane, members, node->child[c], 0);
- }
- }
- } else {
-
- if (node->valueArray.size() > 0) {
- // This is a leaf; check the points
- debugAssertM(node->child[0] == NULL, "Malformed Point tree");
- debugAssertM(node->child[1] == NULL, "Malformed Point tree");
-
- // Test values at this node against remaining planes
- for (int p = 0; p < plane.size(); ++p) {
- if ((parentMask >> p) & 1 != 0) {
- // Test against this plane
- const Plane& curPlane = plane[p];
- for (int v = node->valueArray.size() - 1; v >= 0; --v) {
- if (curPlane.halfSpaceContains(node->valueArray[v].position())) {
- members.append(node->valueArray[v].value);
- }
- }
- }
- }
- } else {
-
- uint32 childMask = 0xFFFFFF;
-
- // Iterate through child nodes
- for (int c = 0; c < 2; ++c) {
- if (node->child[c] &&
- ! node->child[c]->splitBounds.culledBy(plane, dummy, parentMask, childMask)) {
- // This node was not culled
- getIntersectingMembers(plane, members, node->child[c], childMask);
- }
- }
- }
- }
- }
-
-public:
-
- /**
- Returns all members inside the set of planes.
- @param members The results are appended to this array.
- */
- void getIntersectingMembers(const Array<Plane>& plane, Array<T>& members) const {
- if (root == NULL) {
- return;
- }
-
- getIntersectingMembers(plane, members, root, 0xFFFFFF);
- }
-
- /**
- Typically used to find all visible
- objects inside the view frustum (see also GCamera::getClipPlanes)... i.e. all objects
- <B>not</B> culled by frustum.
-
- Example:
- <PRE>
- Array<Object*> visible;
- tree.getIntersectingMembers(camera.frustum(), visible);
- // ... Draw all objects in the visible array.
- </PRE>
- @param members The results are appended to this array.
- */
- void getIntersectingMembers(const GCamera::Frustum& frustum, Array<T>& members) const {
- Array<Plane> plane;
-
- for (int i = 0; i < frustum.faceArray.size(); ++i) {
- plane.append(frustum.faceArray[i].plane);
- }
-
- getIntersectingMembers(plane, members);
- }
-
- /**
- C++ STL style iterator variable. See beginBoxIntersection().
- The iterator overloads the -> (dereference) operator, so this
- acts like a pointer to the current member.
- */
- // This iterator turns Node::getIntersectingMembers into a
- // coroutine. It first translates that method from recursive to
- // stack based, then captures the system state (analogous to a Scheme
- // continuation) after each element is appended to the member array,
- // and allowing the computation to be restarted.
- class BoxIntersectionIterator {
- private:
- friend class TreeType;
-
- /** True if this is the "end" iterator instance */
- bool isEnd;
-
- /** The box that we're testing against. */
- AABox box;
-
- /** Node that we're currently looking at. Undefined if isEnd
- is true. */
- Node* node;
-
- /** Nodes waiting to be processed */
- // We could use backpointers within the tree and careful
- // state management to avoid ever storing the stack-- but
- // it is much easier this way and only inefficient if the
- // caller uses post increment (which they shouldn't!).
- Array<Node*> stack;
-
- /** The next index of current->valueArray to return.
- Undefined when isEnd is true.*/
- int nextValueArrayIndex;
-
- BoxIntersectionIterator() : isEnd(true) {}
-
- BoxIntersectionIterator(const AABox& b, const Node* root) :
- isEnd(root == NULL), box(b),
- node(const_cast<Node*>(root)), nextValueArrayIndex(-1) {
-
- // We intentionally start at the "-1" index of the current
- // node so we can use the preincrement operator to move
- // ourselves to element 0 instead of repeating all of the
- // code from the preincrement method. Note that this might
- // cause us to become the "end" instance.
- ++(*this);
- }
-
- public:
-
- inline bool operator!=(const BoxIntersectionIterator& other) const {
- return ! (*this == other);
- }
-
- bool operator==(const BoxIntersectionIterator& other) const {
- if (isEnd) {
- return other.isEnd;
- } else if (other.isEnd) {
- return false;
- } else {
- // Two non-end iterators; see if they match. This is kind of
- // silly; users shouldn't call == on iterators in general unless
- // one of them is the end iterator.
- if ((box != other.box) || (node != other.node) ||
- (nextValueArrayIndex != other.nextValueArrayIndex) ||
- (stack.length() != other.stack.length())) {
- return false;
- }
-
- // See if the stacks are the same
- for (int i = 0; i < stack.length(); ++i) {
- if (stack[i] != other.stack[i]) {
- return false;
- }
- }
-
- // We failed to find a difference; they must be the same
- return true;
- }
- }
-
- /**
- Pre increment.
- */
- BoxIntersectionIterator& operator++() {
- ++nextValueArrayIndex;
-
- bool foundIntersection = false;
- while (! isEnd && ! foundIntersection) {
-
- // Search for the next node if we've exhausted this one
- while ((! isEnd) && (nextValueArrayIndex >= node->valueArray.length())) {
- // If we entered this loop, then the iterator has exhausted the elements at
- // node (possibly because it just switched to a child node with no members).
- // This loop continues until it finds a node with members or reaches
- // the end of the whole intersection search.
-
- // If the right child overlaps the box, push it onto the stack for
- // processing.
- if ((node->child[1] != NULL) &&
- (box.high()[node->splitAxis] > node->splitLocation)) {
- stack.push(node->child[1]);
- }
-
- // If the left child overlaps the box, push it onto the stack for
- // processing.
- if ((node->child[0] != NULL) &&
- (box.low()[node->splitAxis] < node->splitLocation)) {
- stack.push(node->child[0]);
- }
-
- if (stack.length() > 0) {
- // Go on to the next node (which may be either one of the ones we
- // just pushed, or one from farther back the tree).
- node = stack.pop();
- nextValueArrayIndex = 0;
- } else {
- // That was the last node; we're done iterating
- isEnd = true;
- }
- }
-
- // Search for the next intersection at this node until we run out of children
- while (! isEnd && ! foundIntersection && (nextValueArrayIndex < node->valueArray.length())) {
- if (box.intersects(node->valueArray[nextValueArrayIndex].bounds)) {
- foundIntersection = true;
- } else {
- ++nextValueArrayIndex;
- // If we exhaust this node, we'll loop around the master loop
- // to find a new node.
- }
- }
- }
-
- return *this;
- }
-
- /**
- Post increment (much slower than preincrement!).
- */
- BoxIntersectionIterator operator++(int) {
- BoxIntersectionIterator old = *this;
- ++this;
- return old;
- }
-
- /** Overloaded dereference operator so the iterator can masquerade as a pointer
- to a member */
- const T& operator*() const {
- alwaysAssertM(! isEnd, "Can't dereference the end element of an iterator");
- return node->valueArray[nextValueArrayIndex].value;
- }
-
- /** Overloaded dereference operator so the iterator can masquerade as a pointer
- to a member */
- T const * operator->() const {
- alwaysAssertM(! isEnd, "Can't dereference the end element of an iterator");
- return &(stack.last()->valueArray[nextValueArrayIndex].value);
- }
-
- /** Overloaded cast operator so the iterator can masquerade as a pointer
- to a member */
- operator T*() const {
- alwaysAssertM(! isEnd, "Can't dereference the end element of an iterator");
- return &(stack.last()->valueArray[nextValueArrayIndex].value);
- }
- };
-
-
- /**
- Iterates through the members that intersect the box
- */
- BoxIntersectionIterator beginBoxIntersection(const AABox& box) const {
- return BoxIntersectionIterator(box, root);
- }
-
- BoxIntersectionIterator endBoxIntersection() const {
- // The "end" iterator instance
- return BoxIntersectionIterator();
- }
-
- /**
- Appends all members whose bounds intersect the box.
- See also PointKDTree::beginBoxIntersection.
- */
- void getIntersectingMembers(const AABox& box, Array<T>& members) const {
- if (root == NULL) {
- return;
- }
- root->getIntersectingMembers(box, Sphere(Vector3::zero(), 0), members, false);
- }
-
-
- /**
- @param members The results are appended to this array.
- */
- void getIntersectingMembers(const Sphere& sphere, Array<T>& members) const {
- if (root == NULL) {
- return;
- }
-
- AABox box;
- sphere.getBounds(box);
- root->getIntersectingMembers(box, sphere, members);
-
- }
-
-
- /**
- Stores the locations of the splitting planes (the structure but not the content)
- so that the tree can be quickly rebuilt from a previous configuration without
- calling balance.
- */
- void serializeStructure(BinaryOutput& bo) const {
- Node::serializeStructure(root, bo);
- }
-
- /** Clears the member table */
- void deserializeStructure(BinaryInput& bi) {
- clear();
- root = Node::deserializeStructure(bi);
- }
-
- /**
- Returns an array of all members of the set. See also PointKDTree::begin.
- */
- void getMembers(Array<T>& members) const {
- memberTable.getKeys(members);
- }
-
-
- /**
- C++ STL style iterator variable. See begin().
- Overloads the -> (dereference) operator, so this acts like a pointer
- to the current member.
- */
- class Iterator {
- private:
- friend class TreeType;
-
- // Note: this is a Table iterator, we are currently defining
- // Set iterator
- typename MemberTable::Iterator it;
-
- Iterator(const typename MemberTable::Iterator& it) : it(it) {}
-
- public:
- inline bool operator!=(const Iterator& other) const {
- return !(*this == other);
- }
-
- bool operator==(const Iterator& other) const {
- return it == other.it;
- }
-
- /**
- Pre increment.
- */
- Iterator& operator++() {
- ++it;
- return *this;
- }
-
- /**
- Post increment (slower than preincrement).
- */
- Iterator operator++(int) {
- Iterator old = *this;
- ++(*this);
- return old;
- }
-
- const T& operator*() const {
- return it->key;
- }
-
- T* operator->() const {
- return &(it->key);
- }
-
- operator T*() const {
- return &(it->key);
- }
- };
-
-
- /**
- C++ STL style iterator method. Returns the first member.
- Use preincrement (++entry) to get to the next element (iteration
- order is arbitrary).
- Do not modify the set while iterating.
- */
- Iterator begin() const {
- return Iterator(memberTable.begin());
- }
-
-
- /**
- C++ STL style iterator method. Returns one after the last iterator
- element.
- */
- Iterator end() const {
- return Iterator(memberTable.end());
- }
-#undef TreeType
-};
-
-}
-
-#endif
diff --git a/externals/g3dlite/G3D/Pointer.h b/externals/g3dlite/G3D/Pointer.h
deleted file mode 100644
index 6e35062a746..00000000000
--- a/externals/g3dlite/G3D/Pointer.h
+++ /dev/null
@@ -1,292 +0,0 @@
-/**
- @file Pointer.h
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2007-05-16
- @edited 2009-03-26
-
- Copyright 2000-2009, Morgan McGuire.
- All rights reserved.
- */
-#ifndef G3D_Pointer_h
-#define G3D_Pointer_h
-
-#include "G3D/debugAssert.h"
-#include "G3D/ReferenceCount.h"
-
-namespace G3D {
-
-/**
- Acts like a pointer to a value of type ValueType (i.e.,
- ValueType*), but can operate through accessor methods as well as on
- a value in memory. This is useful for implementing scripting
- languages and other applications that need to connect existing APIs
- by reference.
-
- Because the accessors require values to be passed by value (instead of by reference)
- this is primarily useful for objects whose memory size is small.
-
- <pre>
- class Foo {
- public:
- void setEnabled(bool b);
- bool getEnabled() const;
- };
-
- Foo f;
- bool b;
-
- Pointer<bool> p1(&b);
- Pointer<bool> p2(&f, &Foo::getEnabled, &Foo::setEnabled);
-
- *p1 = true;
- *p2 = false;
- *p2 = *p1; \/\/ Value assignment
- p2 = p1; \/\/ Pointer aliasing
-
- \/\/ Or, equivalently:
- p1.setValue(true);
- p2.setValue(false);
-
- p2.setValue(p1.getValue());
- p2 = p1;
- </pre>
-
- <i>Note:</i> Because of the way that dereference is implemented, you cannot pass <code>*p</code> through a function
- that takes varargs (...), e.g., <code>printf("%d", *p)</code> will produce a compile-time error. Instead use
- <code>printf("%d",(bool)*p)</code> or <code>printf("%d", p.getValue())</code>.
-
- */
-template<class ValueType>
-class Pointer {
-private:
-
- class Interface {
- public:
- virtual ~Interface() {};
- virtual void set(ValueType b) = 0;
- virtual ValueType get() const = 0;
- virtual Interface* clone() const = 0;
- virtual bool isNull() const = 0;
- };
-
- class Memory : public Interface {
- private:
-
- ValueType* value;
-
- public:
-
- Memory(ValueType* value) : value(value) {
- //debugAssert(value != NULL);
- }
-
- virtual void set(ValueType v) {
- *value = v;
- }
-
- virtual ValueType get() const {
- return *value;
- }
-
- virtual Interface* clone() const {
- return new Memory(value);
- }
-
- virtual bool isNull() const {
- return value == NULL;
- }
- };
-
- template<class T, typename GetMethod, typename SetMethod>
- class Accessor : public Interface {
- private:
-
- T* object;
- GetMethod getMethod;
- SetMethod setMethod;
-
- public:
-
- Accessor(T* object,
- GetMethod getMethod,
- SetMethod setMethod) : object(object), getMethod(getMethod), setMethod(setMethod) {
- debugAssert(object != NULL);
- }
-
- virtual void set(ValueType v) {
- (object->*setMethod)(v);
- }
-
- virtual ValueType get() const {
- return (object->*getMethod)();
- }
-
- virtual Interface* clone() const {
- return new Accessor(object, getMethod, setMethod);
- }
-
- virtual bool isNull() const {
- return object == NULL;
- }
- };
-
-
- template<class T, typename GetMethod, typename SetMethod>
- class RefAccessor : public Interface {
- private:
-
- ReferenceCountedPointer<T> object;
- GetMethod getMethod;
- SetMethod setMethod;
-
- public:
-
- RefAccessor(
- const ReferenceCountedPointer<T>& object,
- GetMethod getMethod,
- SetMethod setMethod) : object(object), getMethod(getMethod), setMethod(setMethod) {
-
- debugAssert(object != NULL);
- }
-
- virtual void set(ValueType v) {
- (object.pointer()->*setMethod)(v);
- }
-
- virtual ValueType get() const {
- return (object.pointer()->*getMethod)();
- }
-
- virtual Interface* clone() const {
- return new RefAccessor(object, getMethod, setMethod);
- }
-
- virtual bool isNull() const {
- return object.isNull();
- }
- };
-
-
- Interface* m_interface;
-
-public:
-
- Pointer() : m_interface(NULL) {};
-
- /** Allows implicit cast from real pointer */
- Pointer(ValueType* v) : m_interface(new Memory(v)) {}
-
- inline bool isNull() const {
- return (m_interface == NULL) || m_interface->isNull();
- }
-
- // Assignment
- inline Pointer& operator=(const Pointer& r) {
- delete m_interface;
- if (r.m_interface != NULL) {
- m_interface = r.m_interface->clone();
- } else {
- m_interface = NULL;
- }
- return this[0];
- }
-
- Pointer(const Pointer& p) : m_interface(NULL) {
- this[0] = p;
- }
-
- template<class Class>
- Pointer(const ReferenceCountedPointer<Class>& object,
- ValueType (Class::*getMethod)() const,
- void (Class::*setMethod)(ValueType)) :
- m_interface(new RefAccessor<Class, ValueType (Class::*)() const, void (Class::*)(ValueType)>(object, getMethod, setMethod)) {}
-
- template<class Class>
- Pointer(const ReferenceCountedPointer<Class>& object,
- const ValueType& (Class::*getMethod)() const,
- void (Class::*setMethod)(ValueType)) :
- m_interface(new RefAccessor<Class, const ValueType& (Class::*)() const, void (Class::*)(ValueType)>(object, getMethod, setMethod)) {}
-
- template<class Class>
- Pointer(const ReferenceCountedPointer<Class>& object,
- ValueType (Class::*getMethod)() const,
- void (Class::*setMethod)(const ValueType&)) :
- m_interface(new RefAccessor<Class, ValueType (Class::*)() const, void (Class::*)(const ValueType&)>(object, getMethod, setMethod)) {}
-
- template<class Class>
- Pointer(const ReferenceCountedPointer<Class>& object,
- const ValueType& (Class::*getMethod)() const,
- void (Class::*setMethod)(const ValueType&)) :
- m_interface(new RefAccessor<Class, const ValueType& (Class::*)() const, void (Class::*)(const ValueType&)>(object, getMethod, setMethod)) {}
-
- template<class Class>
- Pointer(Class* object,
- const ValueType& (Class::*getMethod)() const,
- void (Class::*setMethod)(const ValueType&)) :
- m_interface(new Accessor<Class, const ValueType& (Class::*)() const, void (Class::*)(const ValueType&)>(object, getMethod, setMethod)) {}
-
- template<class Class>
- Pointer(Class* object,
- ValueType (Class::*getMethod)() const,
- void (Class::*setMethod)(const ValueType&)) :
- m_interface(new Accessor<Class, ValueType (Class::*)() const, void (Class::*)(const ValueType&)>(object, getMethod, setMethod)) {}
-
- template<class Class>
- Pointer(Class* object,
- const ValueType& (Class::*getMethod)() const,
- void (Class::*setMethod)(ValueType)) :
- m_interface(new Accessor<Class, const ValueType& (Class::*)() const, void (Class::*)(ValueType)>(object, getMethod, setMethod)) {}
-
- template<class Class>
- Pointer(Class* object,
- ValueType (Class::*getMethod)() const,
- void (Class::*setMethod)(ValueType)) :
- m_interface(new Accessor<Class, ValueType (Class::*)() const, void (Class::*)(ValueType)>(object, getMethod, setMethod)) {}
-
- ~Pointer() {
- delete m_interface;
- }
-
- inline const ValueType getValue() const {
- debugAssert(m_interface != NULL);
- return m_interface->get();
- }
-
- inline void setValue(const ValueType& v) {
- debugAssert(m_interface != NULL);
- m_interface->set(v);
- }
-
- class IndirectValue {
- private:
-
- friend class Pointer;
- Pointer* pointer;
- IndirectValue(Pointer* p) : pointer(p) {}
-
- public:
-
- void operator=(const ValueType& v) {
- pointer->setValue(v);
- }
-
- operator ValueType() const {
- return pointer->getValue();
- }
-
- };
-
- inline IndirectValue operator*() {
- return IndirectValue(this);
- }
-
- inline const ValueType operator*() const {
- return getValue();
- }
-};
-
-}
-
-#endif
diff --git a/externals/g3dlite/G3D/PositionTrait.h b/externals/g3dlite/G3D/PositionTrait.h
deleted file mode 100644
index 67a4f64138a..00000000000
--- a/externals/g3dlite/G3D/PositionTrait.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef G3D_POSITIONTRAIT_H
-#define G3D_POSITIONTRAIT_H
-
-template<typename Value>
-struct PositionTrait{};
-
-#endif
diff --git a/externals/g3dlite/G3D/PrecomputedRandom.h b/externals/g3dlite/G3D/PrecomputedRandom.h
deleted file mode 100644
index 411d128c582..00000000000
--- a/externals/g3dlite/G3D/PrecomputedRandom.h
+++ /dev/null
@@ -1,110 +0,0 @@
-/**
- @file PrecomputedRandom.h
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2009-03-31
- @edited 2009-03-31
-
- Copyright 2000-2009, Morgan McGuire.
- All rights reserved.
- */
-#ifndef G3D_PrecomputedRandom_h
-#define G3D_PrecomputedRandom_h
-
-#include "G3D/platform.h"
-#include "G3D/Random.h"
-
-namespace G3D {
-
-/** Fast random numbers using a precomputed data table.
-
- e.g., generates cosHemi about 13x faster than Random.
- This is useful for quickly generating seeded random
- numbers for reproducibility. G3D::Random takes a long
- time to seed; this is instantaneous (providing the
- precomputed data is already available.)
-
- Not threadsafe.*/
-class PrecomputedRandom : public Random {
-public:
- /** Put the cosHemi and the uniform together so that when
- alternating between them we stay in cache. This is also packed
- into a good size for SIMD and GPU operations.*/
- class HemiUniformData {
- public:
- float cosHemiX;
- float cosHemiY;
- float cosHemiZ;
- float uniform;
- };
-
- class SphereBitsData {
- public:
- float sphereX;
- float sphereY;
- float sphereZ;
- uint32 bits;
- };
-
-protected:
-
- /** Array of 2^n elements. */
- const HemiUniformData* m_hemiUniform;
- const SphereBitsData* m_sphereBits;
-
- /** 2^n - 1; the AND mask for computing a fast modulo */
- int m_modMask;
-
- int m_index;
-
- /** If true, free m_hemiUniform and m_sphereBits in destructor */
- bool m_freeData;
-
-public:
-
- /*
- \param dataSize Must be a power of 2
- \param data Will NOT be deleted by the destructor.
- */
- PrecomputedRandom(const HemiUniformData* data1, const SphereBitsData* data2, int dataSize, uint32 seed = 0xF018A4D2);
-
- /**
- \param dataSize Number of random numbers that can be requested before periodicity. Must be a power of 2.
- */
- PrecomputedRandom(int dataSize, uint32 seed = 0xF018A4D2);
-
- ~PrecomputedRandom();
-
- /** Each bit is random. Subclasses can choose to override just
- this method and the other methods will all work automatically. */
- virtual uint32 bits();
-
- // integer is inherited
-
- /** Uniform random float on the range [min, max] */
- virtual float uniform(float low, float high);
-
- /** Uniform random float on the range [0, 1] */
- virtual float uniform();
-
- // gaussian is inherited
-
- /** Returns 3D unit vectors distributed according to
- a cosine distribution about the z axis. */
- virtual void cosHemi(float& x, float& y, float& z);
-
- /** Returns 3D unit vectors distributed according to a cosine
- power distribution (\f$ \mbox{cos}^k \theta \f$) about
- the z-axis. */
- virtual void cosPowHemi(const float k, float& x, float& y, float& z);
-
- // hemi is inherited
-
- /** Returns 3D unit vectors uniformly distributed on the sphere */
- virtual void sphere(float& x, float& y, float& z);
-};
-
-}
-
-#endif
diff --git a/externals/g3dlite/G3D/Quat.h b/externals/g3dlite/G3D/Quat.h
deleted file mode 100644
index 9ef3d57b301..00000000000
--- a/externals/g3dlite/G3D/Quat.h
+++ /dev/null
@@ -1,725 +0,0 @@
-/**
- @file Quat.h
-
- Quaternion
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2002-01-23
- @edited 2009-05-10
- */
-
-#ifndef G3D_Quat_h
-#define G3D_Quat_h
-
-#include "G3D/platform.h"
-#include "G3D/g3dmath.h"
-#include "G3D/Vector3.h"
-#include "G3D/Matrix3.h"
-#include <string>
-
-namespace G3D {
-
-/**
- Unit quaternions are used in computer graphics to represent
- rotation about an axis. Any 3x3 rotation matrix can
- be stored as a quaternion.
-
- A quaternion represents the sum of a real scalar and
- an imaginary vector: ix + jy + kz + w. A unit quaternion
- representing a rotation by A about axis v has the form
- [sin(A/2)*v, cos(A/2)]. For a unit quaternion, q.conj() == q.inverse()
- is a rotation by -A about v. -q is the same rotation as q
- (negate both the axis and angle).
-
- A non-unit quaterion q represents the same rotation as
- q.unitize() (Dam98 pg 28).
-
- Although quaternion-vector operations (eg. Quat + Vector3) are
- well defined, they are not supported by this class because
- they typically are bugs when they appear in code.
-
- Do not subclass.
-
- <B>BETA API -- subject to change</B>
- @cite Erik B. Dam, Martin Koch, Martin Lillholm, Quaternions, Interpolation and Animation. Technical Report DIKU-TR-98/5, Department of Computer Science, University of Copenhagen, Denmark. 1998.
- */
-class Quat {
-private:
- // Hidden operators
- bool operator<(const Quat&) const;
- bool operator>(const Quat&) const;
- bool operator<=(const Quat&) const;
- bool operator>=(const Quat&) const;
-
-public:
-
- /**
- q = [sin(angle / 2) * axis, cos(angle / 2)]
-
- In Watt & Watt's notation, s = w, v = (x, y, z)
- In the Real-Time Rendering notation, u = (x, y, z), w = w
- */
- float x, y, z, w;
-
- /**
- Initializes to a zero degree rotation.
- */
- inline Quat() : x(0), y(0), z(0), w(1) {}
-
- Quat(
- const Matrix3& rot);
-
- inline Quat(float _x, float _y, float _z, float _w) :
- x(_x), y(_y), z(_z), w(_w) {}
-
- /** Defaults to a pure vector quaternion */
- inline Quat(const Vector3& v, float _w = 0) : x(v.x), y(v.y), z(v.z), w(_w) {
- }
-
- /**
- The real part of the quaternion.
- */
- inline const float& real() const {
- return w;
- }
-
- inline float& real() {
- return w;
- }
-
- /** Note: two quats can represent the Quat::sameRotation and not be equal. */
- bool fuzzyEq(const Quat& q) {
- return G3D::fuzzyEq(x, q.x) && G3D::fuzzyEq(y, q.y) && G3D::fuzzyEq(z, q.z) && G3D::fuzzyEq(w, q.w);
- }
-
- /** True if these quaternions represent the same rotation (note that every rotation is
- represented by two values; q and -q).
- */
- bool sameRotation(const Quat& q) {
- return fuzzyEq(q) || fuzzyEq(-q);
- }
-
- inline Quat operator-() const {
- return Quat(-x, -y, -z, -w);
- }
-
- /**
- Returns the imaginary part (x, y, z)
- */
- inline const Vector3& imag() const {
- return *(reinterpret_cast<const Vector3*>(this));
- }
-
- inline Vector3& imag() {
- return *(reinterpret_cast<Vector3*>(this));
- }
-
- /** q = [sin(angle/2)*axis, cos(angle/2)] */
- static Quat fromAxisAngleRotation(
- const Vector3& axis,
- float angle);
-
- /** Returns the axis and angle of rotation represented
- by this quaternion (i.e. q = [sin(angle/2)*axis, cos(angle/2)]) */
- void toAxisAngleRotation(
- Vector3& axis,
- double& angle) const;
-
- void toAxisAngleRotation(
- Vector3& axis,
- float& angle) const {
- double d;
- toAxisAngleRotation(axis, d);
- angle = (float)d;
- }
-
- Matrix3 toRotationMatrix() const;
-
- void toRotationMatrix(
- Matrix3& rot) const;
-
- /**
- Spherical linear interpolation: linear interpolation along the
- shortest (3D) great-circle route between two quaternions.
-
- Note: Correct rotations are expected between 0 and PI in the right order.
-
- @cite Based on Game Physics -- David Eberly pg 538-540
- @param threshold Critical angle between between rotations at which
- the algorithm switches to normalized lerp, which is more
- numerically stable in those situations. 0.0 will always slerp.
- */
- Quat slerp(
- const Quat& other,
- float alpha,
- float threshold = 0.05f) const;
-
- /** Normalized linear interpolation of quaternion components. */
- Quat nlerp(const Quat& other, float alpha) const;
-
- /**
- Negates the imaginary part.
- */
- inline Quat conj() const {
- return Quat(-x, -y, -z, w);
- }
-
- inline float sum() const {
- return x + y + z + w;
- }
-
- inline float average() const {
- return sum() / 4.0f;
- }
-
- inline Quat operator*(float s) const {
- return Quat(x * s, y * s, z * s, w * s);
- }
-
- inline Quat& operator*=(float s) {
- x *= s;
- y *= s;
- z *= s;
- w *= s;
- return *this;
- }
-
- /** @cite Based on Watt & Watt, page 360 */
- friend Quat operator* (float s, const Quat& q);
-
- inline Quat operator/(float s) const {
- return Quat(x / s, y / s, z / s, w / s);
- }
-
- inline float dot(const Quat& other) const {
- return (x * other.x) + (y * other.y) + (z * other.z) + (w * other.w);
- }
-
- /** Note that q<SUP>-1</SUP> = q.conj() for a unit quaternion.
- @cite Dam99 page 13 */
- inline Quat inverse() const {
- return conj() / dot(*this);
- }
-
- Quat operator-(const Quat& other) const;
-
- Quat operator+(const Quat& other) const;
-
- /**
- Quaternion multiplication (composition of rotations).
- Note that this does not commute.
- */
- Quat operator*(const Quat& other) const;
-
- /* (*this) * other.inverse() */
- Quat operator/(const Quat& other) const {
- return (*this) * other.inverse();
- }
-
-
- /** Is the magnitude nearly 1.0? */
- inline bool isUnit(float tolerance = 1e-5) const {
- return abs(dot(*this) - 1.0f) < tolerance;
- }
-
-
- inline float magnitude() const {
- return sqrtf(dot(*this));
- }
-
- inline Quat log() const {
- if ((x == 0) && (y == 0) && (z == 0)) {
- if (w > 0) {
- return Quat(0, 0, 0, ::logf(w));
- } else if (w < 0) {
- // Log of a negative number. Multivalued, any number of the form
- // (PI * v, ln(-q.w))
- return Quat((float)pi(), 0, 0, ::logf(-w));
- } else {
- // log of zero!
- return Quat((float)nan(), (float)nan(), (float)nan(), (float)nan());
- }
- } else {
- // Partly imaginary.
- float imagLen = sqrtf(x * x + y * y + z * z);
- float len = sqrtf(imagLen * imagLen + w * w);
- float theta = atan2f(imagLen, (float)w);
- float t = theta / imagLen;
- return Quat(t * x, t * y, t * z, ::logf(len));
- }
- }
- /** log q = [Av, 0] where q = [sin(A) * v, cos(A)].
- Only for unit quaternions
- debugAssertM(isUnit(), "Log only defined for unit quaternions");
- // Solve for A in q = [sin(A)*v, cos(A)]
- Vector3 u(x, y, z);
- double len = u.magnitude();
-
- if (len == 0.0) {
- return
- }
- double A = atan2((double)w, len);
- Vector3 v = u / len;
-
- return Quat(v * A, 0);
- }
- */
-
- /** exp q = [sin(A) * v, cos(A)] where q = [Av, 0].
- Only defined for pure-vector quaternions */
- inline Quat exp() const {
- debugAssertM(w == 0, "exp only defined for vector quaternions");
- Vector3 u(x, y, z);
- float A = u.magnitude();
- Vector3 v = u / A;
- return Quat(sinf(A) * v, cosf(A));
- }
-
-
- /**
- Raise this quaternion to a power. For a rotation, this is
- the effect of rotating x times as much as the original
- quaterion.
-
- Note that q.pow(a).pow(b) == q.pow(a + b)
- @cite Dam98 pg 21
- */
- inline Quat pow(float x) const {
- return (log() * x).exp();
- }
-
- inline void unitize() {
- float mag2 = dot(*this);
- if (! G3D::fuzzyEq(mag2, 1.0f)) {
- *this *= rsq(mag2);
- }
- }
-
- /**
- Returns a unit quaterion obtained by dividing through by
- the magnitude.
- */
- inline Quat toUnit() const {
- Quat x = *this;
- x.unitize();
- return x;
- }
-
- /**
- The linear algebra 2-norm, sqrt(q dot q). This matches
- the value used in Dam's 1998 tech report but differs from the
- n(q) value used in Eberly's 1999 paper, which is the square of the
- norm.
- */
- inline float norm() const {
- return magnitude();
- }
-
- // access quaternion as q[0] = q.x, q[1] = q.y, q[2] = q.z, q[3] = q.w
- //
- // WARNING. These member functions rely on
- // (1) Quat not having virtual functions
- // (2) the data packed in a 4*sizeof(float) memory block
- const float& operator[] (int i) const;
- float& operator[] (int i);
-
- /** Generate uniform random unit quaternion (i.e. random "direction")
- @cite From "Uniform Random Rotations", Ken Shoemake, Graphics Gems III.
- */
- static Quat unitRandom();
-
- void deserialize(class BinaryInput& b);
- void serialize(class BinaryOutput& b) const;
-
- // 2-char swizzles
-
- Vector2 xx() const;
- Vector2 yx() const;
- Vector2 zx() const;
- Vector2 wx() const;
- Vector2 xy() const;
- Vector2 yy() const;
- Vector2 zy() const;
- Vector2 wy() const;
- Vector2 xz() const;
- Vector2 yz() const;
- Vector2 zz() const;
- Vector2 wz() const;
- Vector2 xw() const;
- Vector2 yw() const;
- Vector2 zw() const;
- Vector2 ww() const;
-
- // 3-char swizzles
-
- Vector3 xxx() const;
- Vector3 yxx() const;
- Vector3 zxx() const;
- Vector3 wxx() const;
- Vector3 xyx() const;
- Vector3 yyx() const;
- Vector3 zyx() const;
- Vector3 wyx() const;
- Vector3 xzx() const;
- Vector3 yzx() const;
- Vector3 zzx() const;
- Vector3 wzx() const;
- Vector3 xwx() const;
- Vector3 ywx() const;
- Vector3 zwx() const;
- Vector3 wwx() const;
- Vector3 xxy() const;
- Vector3 yxy() const;
- Vector3 zxy() const;
- Vector3 wxy() const;
- Vector3 xyy() const;
- Vector3 yyy() const;
- Vector3 zyy() const;
- Vector3 wyy() const;
- Vector3 xzy() const;
- Vector3 yzy() const;
- Vector3 zzy() const;
- Vector3 wzy() const;
- Vector3 xwy() const;
- Vector3 ywy() const;
- Vector3 zwy() const;
- Vector3 wwy() const;
- Vector3 xxz() const;
- Vector3 yxz() const;
- Vector3 zxz() const;
- Vector3 wxz() const;
- Vector3 xyz() const;
- Vector3 yyz() const;
- Vector3 zyz() const;
- Vector3 wyz() const;
- Vector3 xzz() const;
- Vector3 yzz() const;
- Vector3 zzz() const;
- Vector3 wzz() const;
- Vector3 xwz() const;
- Vector3 ywz() const;
- Vector3 zwz() const;
- Vector3 wwz() const;
- Vector3 xxw() const;
- Vector3 yxw() const;
- Vector3 zxw() const;
- Vector3 wxw() const;
- Vector3 xyw() const;
- Vector3 yyw() const;
- Vector3 zyw() const;
- Vector3 wyw() const;
- Vector3 xzw() const;
- Vector3 yzw() const;
- Vector3 zzw() const;
- Vector3 wzw() const;
- Vector3 xww() const;
- Vector3 yww() const;
- Vector3 zww() const;
- Vector3 www() const;
-
- // 4-char swizzles
-
- Vector4 xxxx() const;
- Vector4 yxxx() const;
- Vector4 zxxx() const;
- Vector4 wxxx() const;
- Vector4 xyxx() const;
- Vector4 yyxx() const;
- Vector4 zyxx() const;
- Vector4 wyxx() const;
- Vector4 xzxx() const;
- Vector4 yzxx() const;
- Vector4 zzxx() const;
- Vector4 wzxx() const;
- Vector4 xwxx() const;
- Vector4 ywxx() const;
- Vector4 zwxx() const;
- Vector4 wwxx() const;
- Vector4 xxyx() const;
- Vector4 yxyx() const;
- Vector4 zxyx() const;
- Vector4 wxyx() const;
- Vector4 xyyx() const;
- Vector4 yyyx() const;
- Vector4 zyyx() const;
- Vector4 wyyx() const;
- Vector4 xzyx() const;
- Vector4 yzyx() const;
- Vector4 zzyx() const;
- Vector4 wzyx() const;
- Vector4 xwyx() const;
- Vector4 ywyx() const;
- Vector4 zwyx() const;
- Vector4 wwyx() const;
- Vector4 xxzx() const;
- Vector4 yxzx() const;
- Vector4 zxzx() const;
- Vector4 wxzx() const;
- Vector4 xyzx() const;
- Vector4 yyzx() const;
- Vector4 zyzx() const;
- Vector4 wyzx() const;
- Vector4 xzzx() const;
- Vector4 yzzx() const;
- Vector4 zzzx() const;
- Vector4 wzzx() const;
- Vector4 xwzx() const;
- Vector4 ywzx() const;
- Vector4 zwzx() const;
- Vector4 wwzx() const;
- Vector4 xxwx() const;
- Vector4 yxwx() const;
- Vector4 zxwx() const;
- Vector4 wxwx() const;
- Vector4 xywx() const;
- Vector4 yywx() const;
- Vector4 zywx() const;
- Vector4 wywx() const;
- Vector4 xzwx() const;
- Vector4 yzwx() const;
- Vector4 zzwx() const;
- Vector4 wzwx() const;
- Vector4 xwwx() const;
- Vector4 ywwx() const;
- Vector4 zwwx() const;
- Vector4 wwwx() const;
- Vector4 xxxy() const;
- Vector4 yxxy() const;
- Vector4 zxxy() const;
- Vector4 wxxy() const;
- Vector4 xyxy() const;
- Vector4 yyxy() const;
- Vector4 zyxy() const;
- Vector4 wyxy() const;
- Vector4 xzxy() const;
- Vector4 yzxy() const;
- Vector4 zzxy() const;
- Vector4 wzxy() const;
- Vector4 xwxy() const;
- Vector4 ywxy() const;
- Vector4 zwxy() const;
- Vector4 wwxy() const;
- Vector4 xxyy() const;
- Vector4 yxyy() const;
- Vector4 zxyy() const;
- Vector4 wxyy() const;
- Vector4 xyyy() const;
- Vector4 yyyy() const;
- Vector4 zyyy() const;
- Vector4 wyyy() const;
- Vector4 xzyy() const;
- Vector4 yzyy() const;
- Vector4 zzyy() const;
- Vector4 wzyy() const;
- Vector4 xwyy() const;
- Vector4 ywyy() const;
- Vector4 zwyy() const;
- Vector4 wwyy() const;
- Vector4 xxzy() const;
- Vector4 yxzy() const;
- Vector4 zxzy() const;
- Vector4 wxzy() const;
- Vector4 xyzy() const;
- Vector4 yyzy() const;
- Vector4 zyzy() const;
- Vector4 wyzy() const;
- Vector4 xzzy() const;
- Vector4 yzzy() const;
- Vector4 zzzy() const;
- Vector4 wzzy() const;
- Vector4 xwzy() const;
- Vector4 ywzy() const;
- Vector4 zwzy() const;
- Vector4 wwzy() const;
- Vector4 xxwy() const;
- Vector4 yxwy() const;
- Vector4 zxwy() const;
- Vector4 wxwy() const;
- Vector4 xywy() const;
- Vector4 yywy() const;
- Vector4 zywy() const;
- Vector4 wywy() const;
- Vector4 xzwy() const;
- Vector4 yzwy() const;
- Vector4 zzwy() const;
- Vector4 wzwy() const;
- Vector4 xwwy() const;
- Vector4 ywwy() const;
- Vector4 zwwy() const;
- Vector4 wwwy() const;
- Vector4 xxxz() const;
- Vector4 yxxz() const;
- Vector4 zxxz() const;
- Vector4 wxxz() const;
- Vector4 xyxz() const;
- Vector4 yyxz() const;
- Vector4 zyxz() const;
- Vector4 wyxz() const;
- Vector4 xzxz() const;
- Vector4 yzxz() const;
- Vector4 zzxz() const;
- Vector4 wzxz() const;
- Vector4 xwxz() const;
- Vector4 ywxz() const;
- Vector4 zwxz() const;
- Vector4 wwxz() const;
- Vector4 xxyz() const;
- Vector4 yxyz() const;
- Vector4 zxyz() const;
- Vector4 wxyz() const;
- Vector4 xyyz() const;
- Vector4 yyyz() const;
- Vector4 zyyz() const;
- Vector4 wyyz() const;
- Vector4 xzyz() const;
- Vector4 yzyz() const;
- Vector4 zzyz() const;
- Vector4 wzyz() const;
- Vector4 xwyz() const;
- Vector4 ywyz() const;
- Vector4 zwyz() const;
- Vector4 wwyz() const;
- Vector4 xxzz() const;
- Vector4 yxzz() const;
- Vector4 zxzz() const;
- Vector4 wxzz() const;
- Vector4 xyzz() const;
- Vector4 yyzz() const;
- Vector4 zyzz() const;
- Vector4 wyzz() const;
- Vector4 xzzz() const;
- Vector4 yzzz() const;
- Vector4 zzzz() const;
- Vector4 wzzz() const;
- Vector4 xwzz() const;
- Vector4 ywzz() const;
- Vector4 zwzz() const;
- Vector4 wwzz() const;
- Vector4 xxwz() const;
- Vector4 yxwz() const;
- Vector4 zxwz() const;
- Vector4 wxwz() const;
- Vector4 xywz() const;
- Vector4 yywz() const;
- Vector4 zywz() const;
- Vector4 wywz() const;
- Vector4 xzwz() const;
- Vector4 yzwz() const;
- Vector4 zzwz() const;
- Vector4 wzwz() const;
- Vector4 xwwz() const;
- Vector4 ywwz() const;
- Vector4 zwwz() const;
- Vector4 wwwz() const;
- Vector4 xxxw() const;
- Vector4 yxxw() const;
- Vector4 zxxw() const;
- Vector4 wxxw() const;
- Vector4 xyxw() const;
- Vector4 yyxw() const;
- Vector4 zyxw() const;
- Vector4 wyxw() const;
- Vector4 xzxw() const;
- Vector4 yzxw() const;
- Vector4 zzxw() const;
- Vector4 wzxw() const;
- Vector4 xwxw() const;
- Vector4 ywxw() const;
- Vector4 zwxw() const;
- Vector4 wwxw() const;
- Vector4 xxyw() const;
- Vector4 yxyw() const;
- Vector4 zxyw() const;
- Vector4 wxyw() const;
- Vector4 xyyw() const;
- Vector4 yyyw() const;
- Vector4 zyyw() const;
- Vector4 wyyw() const;
- Vector4 xzyw() const;
- Vector4 yzyw() const;
- Vector4 zzyw() const;
- Vector4 wzyw() const;
- Vector4 xwyw() const;
- Vector4 ywyw() const;
- Vector4 zwyw() const;
- Vector4 wwyw() const;
- Vector4 xxzw() const;
- Vector4 yxzw() const;
- Vector4 zxzw() const;
- Vector4 wxzw() const;
- Vector4 xyzw() const;
- Vector4 yyzw() const;
- Vector4 zyzw() const;
- Vector4 wyzw() const;
- Vector4 xzzw() const;
- Vector4 yzzw() const;
- Vector4 zzzw() const;
- Vector4 wzzw() const;
- Vector4 xwzw() const;
- Vector4 ywzw() const;
- Vector4 zwzw() const;
- Vector4 wwzw() const;
- Vector4 xxww() const;
- Vector4 yxww() const;
- Vector4 zxww() const;
- Vector4 wxww() const;
- Vector4 xyww() const;
- Vector4 yyww() const;
- Vector4 zyww() const;
- Vector4 wyww() const;
- Vector4 xzww() const;
- Vector4 yzww() const;
- Vector4 zzww() const;
- Vector4 wzww() const;
- Vector4 xwww() const;
- Vector4 ywww() const;
- Vector4 zwww() const;
- Vector4 wwww() const;
-};
-
-inline Quat exp(const Quat& q) {
- return q.exp();
-}
-
-inline Quat log(const Quat& q) {
- return q.log();
-}
-
-inline G3D::Quat operator*(double s, const G3D::Quat& q) {
- return q * (float)s;
-}
-
-inline G3D::Quat operator*(float s, const G3D::Quat& q) {
- return q * s;
-}
-
-inline float& Quat::operator[] (int i) {
- debugAssert(i >= 0);
- debugAssert(i < 4);
- return ((float*)this)[i];
-}
-
-inline const float& Quat::operator[] (int i) const {
- debugAssert(i >= 0);
- debugAssert(i < 4);
- return ((float*)this)[i];
-}
-
-inline Quat Quat::operator-(const Quat& other) const {
- return Quat(x - other.x, y - other.y, z - other.z, w - other.w);
-}
-
-inline Quat Quat::operator+(const Quat& other) const {
- return Quat(x + other.x, y + other.y, z + other.z, w + other.w);
-}
-
-} // Namespace G3D
-
-// Outside the namespace to avoid overloading confusion for C++
-inline G3D::Quat pow(const G3D::Quat& q, double x) {
- return q.pow((float)x);
-}
-
-
-#endif
diff --git a/externals/g3dlite/G3D/Quat.inl b/externals/g3dlite/G3D/Quat.inl
deleted file mode 100644
index 9e4c861d93b..00000000000
--- a/externals/g3dlite/G3D/Quat.inl
+++ /dev/null
@@ -1,36 +0,0 @@
-/**
- Quat.inl
-
- @cite Quaternion implementation based on Watt & Watt page 363.
- Thanks to Max McGuire for slerp optimizations.
-
- @maintainer Morgan McGuire, matrix@graphics3d.com
-
- @created 2002-01-23
- @edited 2004-03-04
- */
-
-namespace G3D {
-
-inline float& Quat::operator[] (int i) {
- debugAssert(i >= 0);
- debugAssert(i < 4);
- return ((float*)this)[i];
-}
-
-inline const float& Quat::operator[] (int i) const {
- debugAssert(i >= 0);
- debugAssert(i < 4);
- return ((float*)this)[i];
-}
-
-inline Quat Quat::operator-(const Quat& other) const {
- return Quat(x - other.x, y - other.y, z - other.z, w - other.w);
-}
-
-inline Quat Quat::operator+(const Quat& other) const {
- return Quat(x + other.x, y + other.y, z + other.z, w + other.w);
-}
-
-}
-
diff --git a/externals/g3dlite/G3D/Queue.h b/externals/g3dlite/G3D/Queue.h
deleted file mode 100644
index 36573265d1a..00000000000
--- a/externals/g3dlite/G3D/Queue.h
+++ /dev/null
@@ -1,364 +0,0 @@
-/**
- @file Queue.h
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2002-07-09
- @edited 2008-12-20
- */
-
-#ifndef G3D_QUEUE_H
-#define G3D_QUEUE_H
-
-#include "G3D/platform.h"
-#include "G3D/System.h"
-#include "G3D/debug.h"
-
-namespace G3D {
-
-/**
- Locate the indices of the break between of the two
- sections of the circular queue. These are used to
- construct two for loops that iterate over the whole
- sequence without using the modulo operator.
-
- [0 ... secondEnd) [head .... firstEnd)
- */
-#define FIND_ENDS \
- int firstEnd = head + num;\
- int secondEnd = 0;\
- if (firstEnd > numAllocated) {\
- secondEnd = firstEnd - numAllocated;\
- firstEnd = numAllocated;\
- }
-
-
-/**
- Dynamic queue that uses a circular buffer for performance.
-
- Faster than std::deque for objects with constructors.
- */
-template <class T>
-class Queue {
-private:
- //
- // |<---- num ---->|
- // [ | | | | | | | | | | | | | ]
- // ^
- // |
- // head
- //
- //
-
- /**
- Only num elements are initialized.
- */
- T* data;
-
- /**
- Index of the next element to be dequeue-d in data.
- */
- int head;
-
- /**
- Number of elements (including head) that are visible and initialized.
- */
- int num;
-
- /**
- Size of data array in elements.
- */
- int numAllocated;
-
- /** If a clear was needed, assumes it already occured */
- void _copy(const Queue& other) {
- debugAssert(data == NULL);
- data = (T*)System::malloc(sizeof(T) * other.numAllocated);
- debugAssert(data);
- head = other.head;
- num = other.num;
- numAllocated = other.numAllocated;
-
- FIND_ENDS;
-
- for (int i = head; i < firstEnd; ++i) {
- new (data + i)T(other.data[i]);
- }
-
- for (int i = 0; i < secondEnd; ++i) {
- new (data + i)T(other.data[i]);
- }
- }
-
-
- /**
- Computes a data array index from a queue position. The queue position
- may be negative.
- */
- inline int index(int i) const {
- return (head + i + numAllocated) % numAllocated;
- }
-
- /**
- Allocates newSize elements and repacks the array.
- */
- void repackAndRealloc(int newSize) {
- // TODO: shrink queue
- T* old = data;
- data = (T*)System::malloc(newSize * sizeof(T));
- debugAssert(data != NULL);
-
- FIND_ENDS;
-
- int j = 0;
- for (int i = head; i < firstEnd; ++i, ++j) {
- new (data + j)T(old[i]);
- (old + i)->~T();
- }
-
- for (int i = 0; i < secondEnd; ++i, ++j) {
- new (data + j)T(old[i]);
- (old + i)->~T();
- }
-
- head = 0;
- System::free(old);
- numAllocated = newSize;
- }
-
- /**
- Ensure that there is at least one element between
- the tail and head, wrapping around in the circular
- buffer.
- */
- inline void reserveSpace() {
- if (num == numAllocated) {
- repackAndRealloc(numAllocated * 3 + 20);
- }
- }
-
-public:
-
- Queue() :
- data(NULL),
- head(0),
- num(0),
- numAllocated(0) {
- }
-
-
- /**
- Copy constructor
- */
- Queue(const Queue& other) : data(NULL) {
- _copy(other);
- }
-
-
- /**
- Destructor does not delete() the objects if T is a pointer type
- (e.g. T = int*) instead, it deletes the pointers themselves and
- leaves the objects. Call deleteAll if you want to dealocate
- the objects referenced.
- */
- virtual ~Queue() {
- clear();
- }
-
- /**
- Insert a new element into the front of the queue
- (a traditional queue only uses pushBack).
- */
- inline void pushFront(const T& e) {
- reserveSpace();
-
- // Get the index of head-1
- int i = index(-1);
-
- // Call the constructor on the newly exposed element.
- new (data + i)T(e);
-
- // Reassign the head to point to this index
- head = i;
- ++num;
- }
-
- /**
- Insert a new element at the end of the queue.
- */
- inline void pushBack(const T& e) {
- reserveSpace();
-
- // Get the index of 1+tail
- int i = index(num);
-
- // Initialize that element
- new (data + i)T(e);
- ++num;
- }
-
- /**
- pushBack
- */
- inline void enqueue(const T& e) {
- pushBack(e);
- }
-
-
- /**
- Remove the last element from the queue. The queue will never
- shrink in size. (A typical queue only uses popFront).
- */
- inline T popBack() {
- int tail = index(num - 1);
- T result(data[tail]);
-
- // Call the destructor
- (data + tail)->~T();
- --num;
-
- return result;
- }
-
- /**
- Remove the next element from the head of the queue. The queue will never
- shrink in size. */
- inline T popFront() {
- T result(data[head]);
- // Call the destructor
- (data + head)->~T();
- head = (head + 1) % numAllocated;
- --num;
- return result;
- }
-
-
- /**
- popFront
- */
- inline T dequeue() {
- return popFront();
- }
-
- /**
- Removes all elements (invoking their destructors).
-
- @param freeStorage If false, the underlying array is not deallocated
- (allowing fast push in the future), however, the size of the Queue
- is reported as zero.
-
- */
- void clear(bool freeStorage = true) {
-
- FIND_ENDS;
-
- // Invoke the destructors on the elements
- int i;
- for (i = head; i < firstEnd; ++i) {
- (data + i)->~T();
- }
-
- for (i = 0; i < secondEnd; ++i) {
- (data + i)->~T();
- }
-
- num = 0;
- head = 0;
- if (freeStorage) {
- numAllocated = 0;
- System::free(data);
- data = NULL;
- }
- }
-
- /** Clear without freeing the underlying array. */
- void fastClear() {
- clear(false);
- }
-
- /**
- Assignment operator.
- */
- Queue& operator=(const Queue& other) {
- clear();
- _copy(other);
- return *this;
- }
-
- /**
- Number of elements in the queue.
- */
- inline int size() const {
- return num;
- }
-
- /**
- Number of elements in the queue.
- */
- inline int length() const {
- return size();
- }
-
- /**
- Performs bounds checks in debug mode
- */
- inline T& operator[](int n) {
- debugAssert((n >= 0) && (n < num));
- return data[index(n)];
- }
-
- /**
- Performs bounds checks in debug mode
- */
- inline const T& operator[](int n) const {
- debugAssert((n >= 0) && (n < num));
- return data[index(n)];
- }
-
-
- /** Returns the back element */
- inline const T& last() const {
- return (*this)[size() - 1];
- }
-
- inline T& last() {
- return (*this)[size() - 1];
- }
-
- /**
- Returns true if the given element is in the queue.
- */
- bool contains(const T& e) const {
- for (int i = 0; i < size(); ++i) {
- if ((*this)[i] == e) {
- return true;
- }
- }
-
- return false;
- }
-
- /**
- Calls delete on all objects[0...size-1]
- and sets the queue size to zero.
- */
- void deleteAll() {
- FIND_ENDS;
-
- int i;
- for (i = 0; i < secondEnd; ++i) {
- delete data[i];
- }
-
- for (i = head; i < firstEnd; ++i) {
- delete data[i];
- }
- clear();
- }
-};
-
-#undef FIND_ENDS
-
-}; // namespace
-
-#endif
diff --git a/externals/g3dlite/G3D/Random.h b/externals/g3dlite/G3D/Random.h
deleted file mode 100644
index 54491d06f1b..00000000000
--- a/externals/g3dlite/G3D/Random.h
+++ /dev/null
@@ -1,139 +0,0 @@
-/**
- @file Random.h
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2009-01-02
- @edited 2009-03-20
-
- Copyright 2000-2009, Morgan McGuire.
- All rights reserved.
- */
-#ifndef G3D_Random_h
-#define G3D_Random_h
-
-#include "G3D/platform.h"
-#include "G3D/g3dmath.h"
-#include "G3D/GMutex.h"
-
-namespace G3D {
-
-/** Random number generator.
-
- Threadsafe.
-
- Useful for generating consistent random numbers across platforms
- and when multiple threads are involved.
-
- Uses the Fast Mersenne Twister (FMT-19937) algorithm.
-
- On average, uniform() runs about 2x-3x faster than rand().
-
- @cite http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/index.html
-
- On OS X, Random is about 10x faster than drand48() (which is
- threadsafe) and 4x faster than rand() (which is not threadsafe).
- */
-class Random {
-protected:
-
- /** Constants (important for the algorithm; do not modify) */
- enum {
- N = 624,
- M = 397,
- R = 31,
- U = 11,
- S = 7,
- T = 15,
- L = 18,
- A = 0x9908B0DF,
- B = 0x9D2C5680,
- C = 0xEFC60000};
-
- /**
- Prevents multiple overlapping calls to generate().
- */
- Spinlock lock;
-
- /** State vector (these are the next N values that will be returned) */
- uint32* state;
-
- /** Index into state */
- int index;
-
- bool m_threadsafe;
-
- /** Generate the next N ints, and store them for readback later.
- Called from bits() */
- virtual void generate();
-
- /** For subclasses. The void* parameter is just to distinguish this from the
- public constructor.*/
- Random(void*);
-
-public:
-
- /** \param threadsafe Set to false if you know that this random
- will only be used on a single thread. This eliminates the
- lock and improves performance on some platforms.
- */
- Random(uint32 seed = 0xF018A4D2, bool threadsafe = true);
-
- virtual ~Random();
-
- /** Each bit is random. Subclasses can choose to override just
- this method and the other methods will all work automatically. */
- virtual uint32 bits();
-
- /** Uniform random integer on the range [min, max] */
- virtual int integer(int min, int max);
-
- /** Uniform random float on the range [min, max] */
- virtual inline float uniform(float low, float high) {
- // We could compute the ratio in double precision here for
- // about 1.5x slower performance and slightly better
- // precision.
- return low + (high - low) * ((float)bits() / (float)0xFFFFFFFFUL);
- }
-
- /** Uniform random float on the range [0, 1] */
- virtual inline float uniform() {
- // We could compute the ratio in double precision here for
- // about 1.5x slower performance and slightly better
- // precision.
- const float norm = 1.0f / (float)0xFFFFFFFFUL;
- return (float)bits() * norm;
- }
-
- /** Normally distributed reals. */
- virtual float gaussian(float mean, float stdev);
-
- /** Returns 3D unit vectors distributed according to
- a cosine distribution about the z-axis. */
- virtual void cosHemi(float& x, float& y, float& z);
-
- /** Returns 3D unit vectors distributed according to a cosine
- power distribution (\f$ \cos^k \theta \f$) about
- the z-axis. */
- virtual void cosPowHemi(const float k, float& x, float& y, float& z);
-
- /** Returns 3D unit vectors uniformly distributed on the
- hemisphere about the z-axis. */
- virtual void hemi(float& x, float& y, float& z);
-
- /** Returns 3D unit vectors uniformly distributed on the sphere */
- virtual void sphere(float& x, float& y, float& z);
-
- /**
- A shared instance for when the performance and features but not
- consistency of the class are desired. It is slightly (10%)
- faster to use a distinct instance than to use the common one.
-
- Threadsafe.
- */
- static Random& common();
-};
-
-}
-
-#endif
diff --git a/externals/g3dlite/G3D/Ray.h b/externals/g3dlite/G3D/Ray.h
deleted file mode 100644
index bfee9243343..00000000000
--- a/externals/g3dlite/G3D/Ray.h
+++ /dev/null
@@ -1,371 +0,0 @@
-/**
- @file Ray.h
-
- Ray class
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2002-07-12
- @edited 2009-06-29
- */
-
-#ifndef G3D_Ray_h
-#define G3D_Ray_h
-
-#include "G3D/platform.h"
-#include "G3D/Vector3.h"
-#include "G3D/Triangle.h"
-
-namespace G3D {
-
-/**
- A 3D Ray.
- */
-class Ray {
-private:
- friend class Intersect;
-
- Vector3 m_origin;
-
- /** Unit length */
- Vector3 m_direction;
-
- /** 1.0 / direction */
- Vector3 m_invDirection;
-
-
- // The following are for the "ray slope" optimization from
- // "Fast Ray / Axis-Aligned Bounding Box Overlap Tests using Ray Slopes"
- // by Martin Eisemann, Thorsten Grosch, Stefan Müller and Marcus Magnor
- // Computer Graphics Lab, TU Braunschweig, Germany and
- // University of Koblenz-Landau, Germany*/
- enum Classification {MMM, MMP, MPM, MPP, PMM, PMP, PPM, PPP, POO, MOO, OPO, OMO, OOP, OOM, OMM, OMP, OPM, OPP, MOM, MOP, POM, POP, MMO, MPO, PMO, PPO}; Classification classification;
- // ray slope
- float ibyj, jbyi, kbyj, jbyk, ibyk, kbyi;
- // Precomputed components
- float c_xy, c_xz, c_yx, c_yz, c_zx, c_zy;
-
-public:
-
- void set(const Vector3& origin, const Vector3& direction);
-
- inline const Vector3& origin() const {
- return m_origin;
- }
-
- /** Unit direction vector. */
- inline const Vector3& direction() const {
- return m_direction;
- }
-
- /** Component-wise inverse of direction vector. May have inf() components */
- inline const Vector3& invDirection() const {
- return m_invDirection;
- }
-
- inline Ray() {
- set(Vector3::zero(), Vector3::unitX());
- }
-
- inline Ray(const Vector3& origin, const Vector3& direction) {
- set(origin, direction);
- }
-
- Ray(class BinaryInput& b);
-
- void serialize(class BinaryOutput& b) const;
- void deserialize(class BinaryInput& b);
-
- /**
- Creates a Ray from a origin and a (nonzero) unit direction.
- */
- static Ray fromOriginAndDirection(const Vector3& point, const Vector3& direction) {
- return Ray(point, direction);
- }
-
- /** Advances the origin along the direction by @a distance */
- inline Ray bump(float distance) const {
- return Ray(m_origin + m_direction * distance, m_direction);
- }
-
- /** Advances the origin along the @a bumpDirection by @a distance and returns the new ray*/
- inline Ray bump(float distance, const Vector3& bumpDirection) const {
- return Ray(m_origin + bumpDirection * distance, m_direction);
- }
-
- /**
- Returns the closest point on the Ray to point.
- */
- Vector3 closestPoint(const Vector3& point) const {
- float t = m_direction.dot(point - m_origin);
- if (t < 0) {
- return m_origin;
- } else {
- return m_origin + m_direction * t;
- }
- }
-
- /**
- Returns the closest distance between point and the Ray
- */
- float distance(const Vector3& point) const {
- return (closestPoint(point) - point).magnitude();
- }
-
- /**
- Returns the point where the Ray and plane intersect. If there
- is no intersection, returns a point at infinity.
-
- Planes are considered one-sided, so the ray will not intersect
- a plane where the normal faces in the traveling direction.
- */
- Vector3 intersection(const class Plane& plane) const;
-
- /**
- Returns the distance until intersection with the sphere or the (solid) ball bounded by the sphere.
- Will be 0 if inside the sphere, inf if there is no intersection.
-
- The ray direction is <B>not</B> normalized. If the ray direction
- has unit length, the distance from the origin to intersection
- is equal to the time. If the direction does not have unit length,
- the distance = time * direction.length().
-
- See also the G3D::CollisionDetection "movingPoint" methods,
- which give more information about the intersection.
-
- \param solid If true, rays inside the sphere immediately intersect (good for collision detection). If false, they hit the opposite side of the sphere (good for ray tracing).
- */
- float intersectionTime(const class Sphere& sphere, bool solid = false) const;
-
- float intersectionTime(const class Plane& plane) const;
-
- float intersectionTime(const class Box& box) const;
-
- float intersectionTime(const class AABox& box) const;
-
- /**
- The three extra arguments are the weights of vertices 0, 1, and 2
- at the intersection point; they are useful for texture mapping
- and interpolated normals.
- */
- float intersectionTime(
- const Vector3& v0, const Vector3& v1, const Vector3& v2,
- const Vector3& edge01, const Vector3& edge02,
- double& w0, double& w1, double& w2) const;
-
- /**
- Ray-triangle intersection for a 1-sided triangle. Fastest version.
- @cite http://www.acm.org/jgt/papers/MollerTrumbore97/
- http://www.graphics.cornell.edu/pubs/1997/MT97.html
- */
- inline float intersectionTime(
- const Vector3& vert0,
- const Vector3& vert1,
- const Vector3& vert2,
- const Vector3& edge01,
- const Vector3& edge02) const;
-
-
- inline float intersectionTime(
- const Vector3& vert0,
- const Vector3& vert1,
- const Vector3& vert2) const {
-
- return intersectionTime(vert0, vert1, vert2, vert1 - vert0, vert2 - vert0);
- }
-
-
- inline float intersectionTime(
- const Vector3& vert0,
- const Vector3& vert1,
- const Vector3& vert2,
- double& w0,
- double& w1,
- double& w2) const {
-
- return intersectionTime(vert0, vert1, vert2, vert1 - vert0, vert2 - vert0, w0, w1, w2);
- }
-
- /* One-sided triangle
- */
- inline float intersectionTime(const Triangle& triangle) const {
- return intersectionTime(
- triangle.vertex(0), triangle.vertex(1), triangle.vertex(2),
- triangle.edge01(), triangle.edge02());
- }
-
- inline float intersectionTime(
- const Triangle& triangle,
- double& w0,
- double& w1,
- double& w2) const {
- return intersectionTime(triangle.vertex(0), triangle.vertex(1), triangle.vertex(2),
- triangle.edge01(), triangle.edge02(), w0, w1, w2);
- }
-
- /** Refracts about the normal
- using G3D::Vector3::refractionDirection
- and bumps the ray slightly from the newOrigin. */
- Ray refract(
- const Vector3& newOrigin,
- const Vector3& normal,
- float iInside,
- float iOutside) const;
-
- /** Reflects about the normal
- using G3D::Vector3::reflectionDirection
- and bumps the ray slightly from
- the newOrigin. */
- Ray reflect(
- const Vector3& newOrigin,
- const Vector3& normal) const;
-};
-
-
-#define EPSILON 0.000001
-#define CROSS(dest,v1,v2) \
- dest[0]=v1[1]*v2[2]-v1[2]*v2[1]; \
- dest[1]=v1[2]*v2[0]-v1[0]*v2[2]; \
- dest[2]=v1[0]*v2[1]-v1[1]*v2[0];
-
-#define DOT(v1,v2) (v1[0]*v2[0]+v1[1]*v2[1]+v1[2]*v2[2])
-
-#define SUB(dest,v1,v2) \
- dest[0]=v1[0]-v2[0]; \
- dest[1]=v1[1]-v2[1]; \
- dest[2]=v1[2]-v2[2];
-
-inline float Ray::intersectionTime(
- const Vector3& vert0,
- const Vector3& vert1,
- const Vector3& vert2,
- const Vector3& edge1,
- const Vector3& edge2) const {
-
- (void)vert1;
- (void)vert2;
-
- // Barycenteric coords
- float u, v;
-
- float tvec[3], pvec[3], qvec[3];
-
- // begin calculating determinant - also used to calculate U parameter
- CROSS(pvec, m_direction, edge2);
-
- // if determinant is near zero, ray lies in plane of triangle
- const float det = DOT(edge1, pvec);
-
- if (det < EPSILON) {
- return finf();
- }
-
- // calculate distance from vert0 to ray origin
- SUB(tvec, m_origin, vert0);
-
- // calculate U parameter and test bounds
- u = DOT(tvec, pvec);
- if ((u < 0.0f) || (u > det)) {
- // Hit the plane outside the triangle
- return finf();
- }
-
- // prepare to test V parameter
- CROSS(qvec, tvec, edge1);
-
- // calculate V parameter and test bounds
- v = DOT(m_direction, qvec);
- if ((v < 0.0f) || (u + v > det)) {
- // Hit the plane outside the triangle
- return finf();
- }
-
-
- // Case where we don't need correct (u, v):
- const float t = DOT(edge2, qvec);
-
- if (t >= 0.0f) {
- // Note that det must be positive
- return t / det;
- } else {
- // We had to travel backwards in time to intersect
- return finf();
- }
-}
-
-
-inline float Ray::intersectionTime(
- const Vector3& vert0,
- const Vector3& vert1,
- const Vector3& vert2,
- const Vector3& edge1,
- const Vector3& edge2,
- double& w0,
- double& w1,
- double& w2) const {
-
- (void)vert1;
- (void)vert2;
-
- // Barycenteric coords
- float u, v;
-
- float tvec[3], pvec[3], qvec[3];
-
- // begin calculating determinant - also used to calculate U parameter
- CROSS(pvec, m_direction, edge2);
-
- // if determinant is near zero, ray lies in plane of triangle
- const float det = DOT(edge1, pvec);
-
- if (det < EPSILON) {
- return finf();
- }
-
- // calculate distance from vert0 to ray origin
- SUB(tvec, m_origin, vert0);
-
- // calculate U parameter and test bounds
- u = DOT(tvec, pvec);
- if ((u < 0.0f) || (u > det)) {
- // Hit the plane outside the triangle
- return finf();
- }
-
- // prepare to test V parameter
- CROSS(qvec, tvec, edge1);
-
- // calculate V parameter and test bounds
- v = DOT(m_direction, qvec);
- if ((v < 0.0f) || (u + v > det)) {
- // Hit the plane outside the triangle
- return finf();
- }
-
- float t = DOT(edge2, qvec);
-
- if (t >= 0) {
- const float inv_det = 1.0f / det;
- t *= inv_det;
- u *= inv_det;
- v *= inv_det;
-
- w0 = (1.0f - u - v);
- w1 = u;
- w2 = v;
-
- return t;
- } else {
- // We had to travel backwards in time to intersect
- return finf();
- }
-}
-
-#undef EPSILON
-#undef CROSS
-#undef DOT
-#undef SUB
-
-}// namespace
-
-#endif
diff --git a/externals/g3dlite/G3D/Rect2D.h b/externals/g3dlite/G3D/Rect2D.h
deleted file mode 100644
index 2fb58c50465..00000000000
--- a/externals/g3dlite/G3D/Rect2D.h
+++ /dev/null
@@ -1,417 +0,0 @@
-/**
- @file Rect2D.h
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2003-11-13
- @created 2009-11-16
-
- Copyright 2000-2009, Morgan McGuire.
- All rights reserved.
- */
-
-#ifndef G3D_Rect2D_h
-#define G3D_Rect2D_h
-
-// Linux defines this as a macro
-#ifdef border
-#undef border
-#endif
-
-#include "G3D/platform.h"
-#include "G3D/Array.h"
-#include "G3D/Vector2.h"
-
-#ifdef _MSC_VER
-// Turn off "conditional expression is constant" warning; MSVC generates this
-// for debug assertions in inlined methods.
-# pragma warning (disable : 4127)
-#endif
-
-
-namespace G3D {
-
-class Any;
-
-/**
- If you are using this class for pixel rectangles, keep in mind that the last
- pixel you can draw to is at x0() + width() - 1.
- */
-class Rect2D {
-private:
- Vector2 min, max;
-
- /**
- Returns true if the whole polygon is clipped.
- @param p Value of the point
- @param axis Index [0 or 1] of the axis to clip along?
- @param clipGreater Are we clipping greater than or less than the line?
- @param inPoly Polygon being clipped
- @param outPoly The clipped polygon
- */
- template<class T>
- static bool clipSide2D(
- const float p, bool clipGreater, int axis,
- const Array<T>& inPoly, Array<T>& outPoly) {
-
- outPoly.clear();
- int i0 = -1;
-
- Vector2 pt1;
- bool c1 = true;
-
- float negate = clipGreater ? -1 : 1;
-
- // Find a point that is not clipped
- for (i0 = 0; (i0 < inPoly.length()) && c1; ++i0) {
- pt1 = inPoly[i0];
- c1 = (negate * pt1[axis]) < (negate * p);
- }
-
- // We incremented i0 one time to many
- --i0;
-
- if (c1) {
- // We could not find an unclipped point
- return true;
- }
-
- outPoly.append(pt1);
-
- // for each point in inPoly,
- // if the point is outside the side and the previous one was also outside, continue
- // if the point is outside the side and the previous one was inside, cut the line
- // if the point is inside the side and the previous one was also inside, append the points
- // if the point is inside the side and the previous one was outside, cut the line
- for (int i = 1; i <= inPoly.length(); ++i) {
- T pt2 = inPoly[(i + i0) % inPoly.length()];
- bool c2 = (negate * pt2[axis]) < (negate * p);
-
- if (c1 ^ c2) {
-
- if (!c1 && c2 && (i > 1)) {
- // Unclipped to clipped trasition and not the first iteration
- outPoly.append(pt1);
- }
-
- // only one point is clipped, find where the line crosses the clipping plane
-
-
- float alpha;
- if (pt2[axis] == pt1[axis]) {
- alpha = 0;
- } else {
- alpha = (p - pt1[axis]) / (pt2[axis] - pt1[axis]);
- }
- outPoly.append(pt1.lerp(pt2, alpha));
- } else if (! (c1 || c2) && (i != 1)) {
- // neither point is clipped (don't do this the first time
- // because we appended the first pt before the loop)
- outPoly.append(pt1);
- }
-
- pt1 = pt2;
- c1 = c2;
- }
-
- return false;
- }
-
-public:
-
- /** \param any Must either Rect2D::xywh(#, #, #, #) or Rect2D::xyxy(#, #, #, #)*/
- Rect2D(const Any& any);
-
- /** Converts the Rect2D to an Any. */
- operator Any() const;
-
- Rect2D() : min(0, 0), max(0, 0) {}
-
- /** Creates a rectangle at 0,0 with the given width and height*/
- Rect2D(const Vector2& wh) : min(0, 0), max(wh.x, wh.y) {}
-
- /** Computes a rectangle that contains both @a a and @a b.
- Note that even if @a or @b has zero area, its origin will be included.*/
- Rect2D(const Rect2D& a, const Rect2D& b) {
- min = a.min.min(b.min);
- max = a.max.max(b.max);
- }
-
- /** @brief Uniformly random point on the interior */
- Vector2 randomPoint() const {
- return Vector2(uniformRandom(0, max.x - min.x) + min.x,
- uniformRandom(0, max.y - min.y) + min.y);
- }
-
- float width() const {
- return max.x - min.x;
- }
-
- float height() const {
- return max.y - min.y;
- }
-
- float x0() const {
- return min.x;
- }
-
- float x1() const {
- return max.x;
- }
-
- float y0() const {
- return min.y;
- }
-
- float y1() const {
- return max.y;
- }
-
- /** Min, min corner */
- Vector2 x0y0() const {
- return min;
- }
-
- Vector2 x1y0() const {
- return Vector2(max.x, min.y);
- }
-
- Vector2 x0y1() const {
- return Vector2(min.x, max.y);
- }
-
- /** Max,max corner */
- Vector2 x1y1() const {
- return max;
- }
-
- /** Width and height */
- Vector2 wh() const {
- return max - min;
- }
-
- Vector2 center() const {
- return (max + min) * 0.5;
- }
-
- float area() const {
- return width() * height();
- }
-
- bool isFinite() const {
- return (min.isFinite() && max.isFinite());
- }
-
- Rect2D lerp(const Rect2D& other, float alpha) const {
- Rect2D out;
-
- out.min = min.lerp(other.min, alpha);
- out.max = max.lerp(other.max, alpha);
-
- return out;
- }
-
- static Rect2D xyxy(float x0, float y0, float x1, float y1) {
- Rect2D r;
-
- r.min.x = G3D::min(x0, x1);
- r.min.y = G3D::min(y0, y1);
- r.max.x = G3D::max(x0, x1);
- r.max.y = G3D::max(y0, y1);
-
- return r;
- }
-
- static Rect2D xyxy(const Vector2& v0, const Vector2& v1) {
- Rect2D r;
-
- r.min = v0.min(v1);
- r.max = v0.max(v1);
-
- return r;
- }
-
- static Rect2D xywh(float x, float y, float w, float h) {
- return xyxy(x, y, x + w, y + h);
- }
-
- static Rect2D xywh(const Vector2& v, const Vector2& w) {
- return xyxy(v.x, v.y, v.x + w.x, v.y + w.y);
- }
-
- /** Constructs a Rect2D with infinite boundaries.
- Use isFinite() to test either min or max.
- */
- static Rect2D inf() {
- return xyxy(Vector2::inf(), Vector2::inf());
- }
-
- bool contains(const Vector2& v) const {
- return (v.x >= min.x) && (v.y >= min.y) && (v.x <= max.x) && (v.y <= max.y);
- }
-
- bool contains(const Rect2D& r) const {
- return (min.x <= r.min.x) && (min.y <= r.min.y) &&
- (max.x >= r.max.x) && (max.y >= r.max.y);
- }
-
- /** True if there is non-zero area to the intersection between @a this and @a r.
- Note that two rectangles that are adjacent do not intersect because there is
- zero area to the overlap, even though one of them "contains" the corners of the other.*/
- bool intersects(const Rect2D& r) const {
- return (min.x < r.max.x) && (min.y < r.max.y) &&
- (max.x > r.min.x) && (max.y > r.min.y);
- }
-
- /** Like intersection, but counts the adjacent case as touching. */
- bool intersectsOrTouches(const Rect2D& r) const {
- return (min.x <= r.max.x) && (min.y <= r.max.y) &&
- (max.x >= r.min.x) && (max.y >= r.min.y);
- }
-
- Rect2D operator*(float s) const {
- return xyxy(min.x * s, min.y * s, max.x * s, max.y * s);
- }
-
- Rect2D operator/(float s) const {
- return xyxy(min / s, max / s);
- }
-
- Rect2D operator/(const Vector2& s) const {
- return xyxy(min / s, max / s);
- }
-
- Rect2D operator+(const Vector2& v) const {
- return xyxy(min + v, max + v);
- }
-
- Rect2D operator-(const Vector2& v) const {
- return xyxy(min - v, max - v);
- }
-
- bool operator==(const Rect2D& other) const {
- return (min == other.min) && (max == other.max);
- }
-
- bool operator!=(const Rect2D& other) const {
- return (min != other.min) || (max != other.max);
- }
-
- /** Returns the corners in the order: (min,min), (max,min), (max,max), (min,max). */
- Vector2 corner(int i) const {
- debugAssert(i >= 0 && i < 4);
- switch (i & 3) {
- case 0:
- return Vector2(min.x, min.y);
- case 1:
- return Vector2(max.x, min.y);
- case 2:
- return Vector2(max.x, max.y);
- case 3:
- return Vector2(min.x, max.y);
- default:
- // Should never get here
- return Vector2(0, 0);
- }
- }
-
-
- /** @deprecated
- @sa expand() */
- Rect2D border(float delta) const {
- return Rect2D::xywh(x0() + delta,
- y0() + delta,
- width() - 2.0f * delta,
- height() - 2.0f * delta);
- }
-
- /** Returns a new Rect2D that is bigger/smaller by the specified amount
- (negative is shrink.) */
- Rect2D expand(float delta) const {
- float newX = x0() - delta;
- float newY = y0() - delta;
- float newW = width() + 2.0f * delta;
- float newH = height() + 2.0f * delta;
-
- if (newW < 0.0f) {
- newX = (x0() + width()) / 2.0f;
- newW = 0.0f;
- }
-
- if (newH < 0.0f) {
- newY = (y0() + height()) / 2.0f;
- newH = 0.0f;
- }
- return Rect2D::xywh(newX, newY, newW, newH);
- }
-
- /**
- Clips so that the rightmost point of the outPoly is at rect.x1 (e.g. a 800x600 window produces
- rightmost point 799, not 800). The results are suitable for pixel rendering if iRounded.
- Templated so that it will work for Vector2,3,4 (the z and w components are interpolated linearly).
- The template parameter must define T.lerp and contain x and y components.
-
- If the entire polygon is clipped by a single side, the result will be empty.
- The result might also have zero area but not be empty.
- */
- template<class T>
- void clip(const Array<T>& inPoly, Array<T>& outPoly) const {
-
- const bool greaterThan = true;
- const bool lessThan = false;
- const int X = 0;
- const int Y = 1;
-
- Array<T> temp;
-
- bool entirelyClipped =
- clipSide2D(x0(), lessThan, X, inPoly, temp) ||
- clipSide2D(x1(), greaterThan, X, temp, outPoly) ||
- clipSide2D(y0(), lessThan, Y, outPoly, temp) ||
- clipSide2D(y1(), greaterThan, Y, temp, outPoly);
-
- if (entirelyClipped) {
- outPoly.clear();
- }
- }
-
-
- /** Returns the largest, centered Rect2D that can fit inside this
- while maintaining the aspect ratio of x:y. Convenient for
- displaying images in odd-shaped windows.
- */
- Rect2D largestCenteredSubRect(float ww, float hh) const {
- float textureAspect = hh / ww;
- float viewAspect = height() / width();
-
- if (viewAspect > textureAspect) {
- // The view is too tall
- float h = width() * textureAspect;
- float y = (height() - h) / 2;
- return Rect2D::xywh(0, y, width(), h) + corner(0);
- } else {
- // The view is too wide
- float w = height() / textureAspect;
- float x = (width() - w) / 2;
- return Rect2D::xywh(x, 0, w, height()) + corner(0);
- }
- }
-
- /**
- Returns the overlap region between the two rectangles. This may have zero area
- if they do not intersect. See the two-Rect2D constructor for a way to compute
- a union-like rectangle.
- */
- Rect2D intersect(const Rect2D& other) const {
- if (intersects(other)) {
- return Rect2D::xyxy(min.max(other.min), max.min(other.max));
- }else{
- return Rect2D::xywh(0, 0, 0, 0);
- }
- }
-};
-
-typedef Rect2D AABox2D;
-}
-
-#endif
diff --git a/externals/g3dlite/G3D/ReferenceCount.h b/externals/g3dlite/G3D/ReferenceCount.h
deleted file mode 100644
index 84591c6d8e5..00000000000
--- a/externals/g3dlite/G3D/ReferenceCount.h
+++ /dev/null
@@ -1,570 +0,0 @@
-/**
- @file ReferenceCount.h
-
- Reference Counting Garbage Collector for C++
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @cite Adapted and extended from Justin Miller's "RGC" class that appeared in BYTE magazine.
- @cite See also http://www.jelovic.com/articles/cpp_without_memory_errors_slides.htm
-
- @created 2001-10-23
- @edited 2009-04-25
-*/
-#ifndef G3D_ReferenceCount_h
-#define G3D_ReferenceCount_h
-
-#include "G3D/platform.h"
-#include "G3D/debug.h"
-#include "G3D/AtomicInt32.h"
-
-namespace G3D {
-
-#ifdef _MSC_VER
-// Turn off "conditional expression is constant" warning; MSVC generates this
-// for debug assertions in inlined methods.
-# pragma warning (disable : 4127)
-#endif
-
-/** Base class for WeakReferenceCountedPointer */
-class _WeakPtr {
-public:
- inline virtual ~_WeakPtr() {}
-
-protected:
- friend class ReferenceCountedObject;
-
- /** Called by ReferenceCountedObject to tell a weak pointer that its underlying object was collected. */
- virtual void objectCollected() = 0;
-};
-
-/** Used internally by ReferenceCountedObject */
-class _WeakPtrLinkedList {
-public:
- _WeakPtr* weakPtr;
- _WeakPtrLinkedList* next;
-
- inline _WeakPtrLinkedList() : weakPtr(NULL), next(NULL) {}
-
- /** Inserts this node into the head of the list that previously had n as its head. */
- inline _WeakPtrLinkedList(_WeakPtr* p, _WeakPtrLinkedList* n) : weakPtr(p), next(n) {}
-};
-
-/**
- Objects that are reference counted inherit from this. Subclasses
- <B>must</B> have a public destructor (the default destructor is fine)
- and <B>publicly</B> inherit ReferenceCountedObject.
-
- Multiple inheritance from a reference counted object is dangerous-- use
- at your own risk.
-
- ReferenceCountedPointer and ReferenceCountedObject are threadsafe.
- You can create and drop references on multiple threads without
- violating integrity. WeakReferenceCountedPointer is <i>not</i>
- threadsafe. Introducing a weak pointer destroys all thread safety,
- even for strong pointers to the same object (this is inherent in the
- design of the class; we cannot fix it without slowing down the
- performance of reference counted objects.)
-
- <B>Usage Example</B>
-
- <PRE>
-
-class Foo : public G3D::ReferenceCountedObject {
-public:
- int x;
-};
-
-class Bar : public Foo {};
-
-typedef G3D::ReferenceCountedPointer<Foo> FooRef;
-typedef G3D::WeakReferenceCountedPointer<Foo> WeakFooRef;
-typedef G3D::ReferenceCountedPointer<Bar> BarRef;
-
-
-int main(int argc, char *argv[]) {
-
- WeakFooRef x;
-
- {
- FooRef a = new Foo();
-
- // Reference count == 1
-
- x = a;
- // Weak references do not increase count
-
- {
- FooRef b = a;
- // Reference count == 2
- }
-
- // Reference count == 1
- }
- // No more strong references; object automatically deleted.
- // x is set to NULL automatically.
-
- // Example of using dynamic cast on reference counted objects
- BarRef b = new Bar();
-
- // No cast needed to go down the heirarchy.
- FooRef f = b;
-
- // We can't cast the reference object because it is a class.
- // Instead we must extract the pointer and cast that:
- b = dynamic_cast<Bar*>(&*f);
-
- return 0;
-}
-</PRE>
- */
-class ReferenceCountedObject {
-public:
-
- /**
- The long name is to keep this from accidentally conflicting with
- a subclass's variable name. Do not use or explicitly manipulate
- this value--its type may change in the future and is not part
- of the supported API.
- */
- AtomicInt32 ReferenceCountedObject_refCount;
-
- /**
- Linked list of all weak pointers that reference this (some may be
- on the stack!). Do not use or explicitly manipulate this value.
- */
- _WeakPtrLinkedList* ReferenceCountedObject_weakPointer;
-
-protected:
-
- ReferenceCountedObject();
-
-public:
-
- /** Automatically called immediately before the object is deleted.
- This is not called from the destructor because it needs to be invoked
- before the subclass destructor.
- */
- void ReferenceCountedObject_zeroWeakPointers();
-
- virtual ~ReferenceCountedObject();
-
-
- /**
- Note: copies will initially start out with 0
- references and 0 weak references like any other object.
- */
- ReferenceCountedObject(const ReferenceCountedObject& notUsed);
-
- ReferenceCountedObject& operator=(const ReferenceCountedObject& other);
-};
-
-
-
-/**
- Use ReferenceCountedPointer<T> in place of T* in your program.
- T must subclass ReferenceCountedObject.
-@deprecated To be replaced by boost::shared_ptr in 7.0
- */
-template <class T>
-class ReferenceCountedPointer {
-private:
-
- T* m_pointer;
-
-public:
- typedef T element_type;
-
- inline T* pointer() const {
- return m_pointer;
- }
-
-private:
-
- /** Nulls out the pointer and drops a reference. If the reference
- count hits zero. */
- void zeroPointer() {
- if (m_pointer != NULL) {
-
- ReferenceCountedObject* pointer = ((ReferenceCountedObject*)m_pointer);
- debugAssert(G3D::isValidHeapPointer(m_pointer));
- debugAssertM(pointer->ReferenceCountedObject_refCount.value() > 0,
- "Dangling reference detected.");
-
- // Only delete if this instance caused the count to hit
- // exactly zero. If there is a race condition, the value
- // may be zero after decrement returns, but only one of
- // the instances will get a zero return value.
- if (pointer->ReferenceCountedObject_refCount.decrement() == 0) {
- // We held the last reference, so delete the object.
- // This test is threadsafe because there is no way for
- // the reference count to increase after the last
- // reference was dropped (assuming the application does
- // not voilate the class abstraction).
- //debugPrintf(" delete 0x%x\n", m_pointer);
-
- // We must zero the weak pointers *before* deletion in case there
- // are cycles of weak references.
- // Note that since there are no strong references at this point,
- // it is perfectly fair to zero the weak pointers anyway.
- pointer->ReferenceCountedObject_zeroWeakPointers();
- delete pointer;
- }
-
- m_pointer = NULL;
- }
- }
-
- /** Non-atomic (except for the referencec increment). Can only be
- called in contexts like the copy constructor or initial
- constructor where it is known that the reference count will
- not hit zero on some other thread. */
- void setPointer(T* x) {
- if (x != m_pointer) {
- zeroPointer();
-
- if (x != NULL) {
- debugAssert(G3D::isValidHeapPointer(x));
-
- m_pointer = x;
-
- // Note that the ref count can be zero if this is the
- // first pointer to it
- ReferenceCountedObject* pointer = (ReferenceCountedObject*)m_pointer;
- debugAssertM(pointer->ReferenceCountedObject_refCount.value() >= 0,
- "Negative reference count detected.");
- pointer->ReferenceCountedObject_refCount.increment();
- }
- }
- }
-
-public:
-
- inline ReferenceCountedPointer() : m_pointer(NULL) {}
-
- /**
- Allow silent cast <i>to</i> the base class.
-
- <pre>
- SubRef s = new Sub();
- BaseRef b = s;
- </pre>
-
- i.e., compile-time subtyping rule
- RCP&lt;<I>T</I>&gt; &lt;: RCP&lt;<I>S</I>&gt; if <I>T</I> &lt;: <I>S</I>
- */
- template <class S>
- inline ReferenceCountedPointer(const ReferenceCountedPointer<S>& p) :
- m_pointer(NULL) {
- setPointer(p.pointer());
- }
-
-# if (! defined(MSC_VER) || (MSC_VER >= 1300))
- /**
- Explicit cast to a subclass. Acts like dynamic cast; the result will be NULL if
- the cast cannot succeed. Not supported on VC6.
- <pre>
- SubRef s = new Sub();
- BaseRef b = s;
- s = b.downcast<Sub>(); // Note that the template argument is the object type, not the pointer type.
- </pre>
- */
- template <class S>
- ReferenceCountedPointer<S> downcast() {
- return ReferenceCountedPointer<S>(dynamic_cast<S*>(m_pointer));
- }
-
- template <class S>
- const ReferenceCountedPointer<S> downcast() const {
- return ReferenceCountedPointer<S>(dynamic_cast<const S*>(m_pointer));
- }
-# endif
-
- // We need an explicit version of the copy constructor as well or
- // the default copy constructor will be used.
- inline ReferenceCountedPointer(const ReferenceCountedPointer<T>& p) : m_pointer(NULL) {
- setPointer(p.m_pointer);
- }
-
- /** Allows construction from a raw pointer. That object will thereafter be
- reference counted -- do not call delete on it.
-
- Use of const allows downcast on const references */
- inline ReferenceCountedPointer(const T* p) : m_pointer(NULL) {
- // only const constructor is defined to remove ambiguity using NULL
- setPointer(const_cast<T*>(p));
- }
-
-
- inline ~ReferenceCountedPointer() {
- zeroPointer();
- }
-
- inline size_t hashCode() const {
- return reinterpret_cast<size_t>(m_pointer);;
- }
-
- inline const ReferenceCountedPointer<T>& operator=(const ReferenceCountedPointer<T>& p) {
- setPointer(p.m_pointer);
- return *this;
- }
-
- inline ReferenceCountedPointer<T>& operator=(T* p) {
- setPointer(p);
- return *this;
- }
-
- inline bool operator==(const ReferenceCountedPointer<T>& y) const {
- return (m_pointer == y.m_pointer);
- }
-
- inline bool operator!=(const ReferenceCountedPointer<T>& y) const {
- return (m_pointer != y.m_pointer);
- }
-
- bool operator < (const ReferenceCountedPointer<T>& y) const {
- return (m_pointer < y.m_pointer);
- }
-
- bool operator > (const ReferenceCountedPointer<T>& y) const {
- return (m_pointer > y.m_pointer);
- }
-
- bool operator <= (const ReferenceCountedPointer<T>& y) const {
- return (m_pointer <= y.m_pointer);
- }
-
- bool operator >= (const ReferenceCountedPointer<T>& y) const {
- return (m_pointer >= y.m_pointer);
- }
-
- inline T& operator*() const {
- debugAssertM(m_pointer != NULL, "Dereferenced a NULL ReferenceCountedPointer");
- return (*m_pointer);
- }
-
- inline T* operator->() const {
- debugAssertM(m_pointer != NULL, "Dereferenced a NULL ReferenceCountedPointer");
- return m_pointer;
- }
-
- inline bool isNull() const {
- return (m_pointer == NULL);
- }
-
- inline bool notNull() const {
- return (m_pointer != NULL);
- }
-
- // TODO: distinguish between last strong and last any pointer
- /**
- Returns true if this is the last reference to an object.
- Useful for flushing memoization caches-- a cache that holds the last
- reference is unnecessarily keeping an object alive.
-
- <b>Not threadsafe.</b>
-
- @deprecated Use WeakReferenceCountedPointer for caches
- */
- inline int isLastReference() const {
- return (m_pointer->ReferenceCountedObject_refCount.value() == 1);
- }
-};
-
-
-/**
- A weak pointer allows the object it references to be garbage collected.
- Weak pointers are commonly used in caches, where it is important to hold
- a pointer to an object without keeping that object alive solely for the
- cache's benefit (i.e., the object can be collected as soon as all
- pointers to it <B>outside</B> the cache are gone). They are also convenient
- for adding back-pointers in tree and list structures.
-
- Weak pointers may become NULL at any point (when their target is collected).
- Therefore the only way to reference the target is to convert to a strong
- pointer and then check that it is not NULL.
-
-@deprecated To be replaced by boost::weak_ptr in 7.0
- */
-template <class T>
-class WeakReferenceCountedPointer : public _WeakPtr {
-private:
-
- /** NULL if the object has been collected. */
- T* pointer;
-
-public:
- /**
- Creates a strong pointer, which prevents the object from being
- garbage collected. The strong pointer may be NULL, which means
- that the underlying.
- */
- // There is intentionally no way to check if the
- // WeakReferenceCountedPointer has a null reference without
- // creating a strong pointer since there is no safe way to use
- // that information-- the pointer could be collected by a
- // subsequent statement.
- ReferenceCountedPointer<T> createStrongPtr() const {
- // TODO: What if the object's destructor is called while we
- // are in this method?
- return ReferenceCountedPointer<T>(pointer);
- }
-
-private:
-
- /** Thread issues: safe because this is only called when another
- object is guaranteed to keep p alive for the duration of this
- call. */
- void setPointer(T* p) {
- // TODO: must prevent the object from being collected while in
- // this method
-
- zeroPointer();
- pointer = p;
-
- if (pointer != NULL) {
- // TODO: threadsafe: must update the list atomically
-
- // Add myself to the head of my target's list of weak pointers
- _WeakPtrLinkedList* head =
- new _WeakPtrLinkedList
- (this,
- pointer->ReferenceCountedObject_weakPointer);
-
- pointer->ReferenceCountedObject_weakPointer = head;
- } else {
-
- }
- }
-
-
- /**
- Removes this from its target's list of weak pointers. Called
- when the weak pointer goes out of scope.
-
- Thread issues: depends on the thread safety of createStrongPtr.
- */
- void zeroPointer() {
- // Grab a strong reference to prevent the object from being collected while we
- // are traversing its list.
- ReferenceCountedPointer<T> strong = createStrongPtr();
-
- // If the following test fails then the object was collected before we
- // reached it.
- if (strong.notNull()) {
- debugAssertM(((ReferenceCountedObject*)pointer)->ReferenceCountedObject_weakPointer != NULL,
- "Weak pointer exists without a backpointer from the object.");
-
- // Remove myself from my target's list of weak pointers
- _WeakPtrLinkedList** node = &((ReferenceCountedObject*)pointer)->ReferenceCountedObject_weakPointer;
- while ((*node)->weakPtr != this) {
- node = &((*node)->next);
- debugAssertM(*node != NULL,
- "Weak pointer exists without a backpointer from the object (2).");
- }
-
- // Node must now point at the node for me. Remove node and
- // close the linked list behind it.
- _WeakPtrLinkedList* temp = *node;
- *node = temp->next;
-
- // Now delete the node corresponding to me
- delete temp;
- }
-
- pointer = NULL;
- }
-
-public:
-
- WeakReferenceCountedPointer() : pointer(0) {}
-
- /**
- Allow compile time subtyping rule
- RCP&lt;<I>T</I>&gt; &lt;: RCP&lt;<I>S</I>&gt; if <I>T</I> &lt;: <I>S</I>
- */
- template <class S>
- inline WeakReferenceCountedPointer(const WeakReferenceCountedPointer<S>& p) : pointer(0) {
- // Threadsafe: the object cannot be collected while the other pointer exists.
- setPointer(p.pointer);
- }
-
- template <class S>
- inline WeakReferenceCountedPointer(const ReferenceCountedPointer<S>& p) : pointer(0) {
- // Threadsafe: the object cannot be collected while the other
- // pointer exists.
- setPointer(p.pointer());
- }
-
- // Gets called a *lot* when weak pointers are on the stack
- WeakReferenceCountedPointer(
- const WeakReferenceCountedPointer<T>& weakPtr) : pointer(0) {
- setPointer(weakPtr.pointer);
- }
-
- WeakReferenceCountedPointer(
- const ReferenceCountedPointer<T>& strongPtr) : pointer(0) {
- setPointer(strongPtr.pointer());
- }
-
- ~WeakReferenceCountedPointer() {
- zeroPointer();
- }
-
- WeakReferenceCountedPointer<T>& operator=(const WeakReferenceCountedPointer<T>& other) {
- // Threadsafe: the object cannot be collected while the other pointer exists.
-
- // I now point at other's target
- setPointer(other.pointer);
-
- return *this;
- }
-
- WeakReferenceCountedPointer<T>& operator=(const ReferenceCountedPointer<T>& other) {
-
- // Threadsafe: the object cannot be collected while the other pointer exists.
-
- // I now point at other's target
- setPointer(other.pointer());
-
- return *this;
- }
-
- bool operator==(const WeakReferenceCountedPointer<T>& other) const {
- return pointer == other.pointer;
- }
-
- bool operator!=(const WeakReferenceCountedPointer<T>& other) const {
- return pointer != other.pointer;
- }
-
- bool operator < (const WeakReferenceCountedPointer<T>& y) const {
- return (pointer < y.pointer);
- }
-
- bool operator > (const WeakReferenceCountedPointer<T>& y) const {
- return (pointer > y.pointer);
- }
-
- bool operator <= (const WeakReferenceCountedPointer<T>& y) const {
- return (pointer <= y.pointer);
- }
-
- bool operator >= (const ReferenceCountedPointer<T>& y) const {
- return (pointer >= y.pointer);
- }
-
-protected:
-
- /** Invoked by the destructor on ReferenceCountedPointer. */
- void objectCollected() {
- debugAssertM(pointer != NULL,
- "Removed a weak pointer twice.");
- pointer = NULL;
- }
-
-};
-
-} // namespace
-
-#endif
-
diff --git a/externals/g3dlite/G3D/RegistryUtil.h b/externals/g3dlite/G3D/RegistryUtil.h
deleted file mode 100644
index 4b47be5f4bd..00000000000
--- a/externals/g3dlite/G3D/RegistryUtil.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/**
- @file RegistryUtil.h
-
- @created 2006-04-06
- @edited 2006-04-06
-
- Copyright 2000-2006, Morgan McGuire.
- All rights reserved.
-*/
-
-#ifndef G3D_REGISTRYUTIL_H
-#define G3D_REGISTRYUTIL_H
-
-#include "G3D/platform.h"
-#include "G3D/g3dmath.h"
-
-// This file is only used on Windows
-#ifdef G3D_WIN32
-
-#include <string>
-
-namespace G3D {
-
-/**
- Provides generalized Windows registry querying.
-
- All key names are one string in the format:
- "[base key]\[sub-keys]"
-
- A value must now be provided for every query.
- An empty value string will use the (Default) value.
-
- [base key] can be any of the following:
- HKEY_CLASSES_ROOT
- HKEY_CURRENT_CONFIG
- HKEY_CURRENT_USER
- HKEY_LOCAL_MACHINE
- HKEY_PERFORMANCE_DATA
- HKEY_PERFORMANCE_NLSTEXT
- HKEY_PERFORMANCE_TEXT
- HKEY_USERS
-
- valueExists() should be used to validate a key+value before reading or writing
- to ensure that a debug assert or false return is for a different error during
- reads and writes.
-
- All read and write calls will assert when a key will not open for reasons other
- that it does not exist. All read and write calls will assert when the value cannot
- be read or written for any reason.
-*/
-class RegistryUtil {
-
-public:
- /** returns true if the key exists and the current user has permission to read */
- static bool keyExists(const std::string& key);
-
- /** returns true if the key exists and the current user has permission to read */
- static bool valueExists(const std::string& key, const std::string& value);
-
- /** returns false if the key could not be read for any reason. */
- static bool readInt32(const std::string& key, const std::string& value, int32& data);
-
- /**
- Reads an arbitrary amount of data from a binary registry key.
- returns false if the key could not be read for any reason.
-
- @beta
- @param data pointer to the output buffer of sufficient size. Pass NULL as data in order to have available data size returned in dataSize.
- @param dataSize size of the output buffer. When NULL is passed for data, contains the size of available data on successful return.
- */
- static bool readBytes(const std::string& key, const std::string& value, uint8* data, uint32& dataSize);
-
- /** returns false if the key could not be read for any reason. */
- static bool readString(const std::string& key, const std::string& value, std::string& data);
-
- /** returns false if the key could not be written for any reason. */
- static bool writeInt32(const std::string& key, const std::string& value, int32 data);
-
- /**
- Writes an arbitrary amount of data to a binary registry key.
- returns false if the key could not be written for any reason.
-
- @param data pointer to the input buffer
- @param dataSize size of the input buffer that should be written
- */
- static bool writeBytes(const std::string& key, const std::string& value, const uint8* data, uint32 dataSize);
-
- /** returns false if the key could not be written for any reason. */
- static bool writeString(const std::string& key, const std::string& value, const std::string& data);
-
-};
-
-} // namespace G3D
-
-#endif // G3D_WIN32
-
-#endif // G3D_REGISTRYTUIL_H
diff --git a/externals/g3dlite/G3D/Set.h b/externals/g3dlite/G3D/Set.h
deleted file mode 100644
index 9a8e1b619bb..00000000000
--- a/externals/g3dlite/G3D/Set.h
+++ /dev/null
@@ -1,186 +0,0 @@
-/**
- @file Set.h
-
- Hash set
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2001-12-09
- @edited 2009-06-10
- */
-
-#ifndef G3D_Set_h
-#define G3D_Set_h
-
-#include "G3D/platform.h"
-#include "G3D/Table.h"
-#include "G3D/MemoryManager.h"
-#include <assert.h>
-#include <string>
-
-namespace G3D {
-
-/**
- An unordered data structure that has at most one of each element.
- Provides O(1) time insert, remove, and member test (contains).
-
- Set uses G3D::Table internally, which means that the template type T
- must define a hashCode and operator== function. See G3D::Table for
- a discussion of these functions.
- */
-// There is not copy constructor or assignment operator defined because
-// the default ones are correct for Set.
-template<class T, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T> >
-class Set {
-
- /**
- If an object is a member, it is contained in
- this table.
- */
- Table<T, bool, HashFunc, EqualsFunc> memberTable;
-
-public:
-
- void clearAndSetMemoryManager(const MemoryManager::Ref& m) {
- memberTable.clearAndSetMemoryManager(m);
- }
-
- virtual ~Set() {}
-
- int size() const {
- return (int)memberTable.size();
- }
-
- bool contains(const T& member) const {
- return memberTable.containsKey(member);
- }
-
- /**
- Inserts into the table if not already present.
- */
- void insert(const T& member) {
- memberTable.set(member, true);
- }
-
- /**
- Returns true if the element was present and removed. Returns false
- if the element was not present.
- */
- bool remove(const T& member) {
- return memberTable.remove(member);
- }
-
- /** If @a member is present, sets @a removed to the element
- being removed and returns true. Otherwise returns false
- and does not write to @a removed. This is useful when building
- efficient hashed data structures that wrap Set.
- */
- bool getRemove(const T& member, T& removed) {
- bool ignore;
- return memberTable.getRemove(member, removed, ignore);
- }
-
- /** If a value that is EqualsFunc to @a member is present, returns a pointer to the
- version stored in the data structure, otherwise returns NULL.
- */
- const T* getPointer(const T& member) const {
- return memberTable.getKeyPointer(member);
- }
-
- Array<T> getMembers() const {
- return memberTable.getKeys();
- }
-
- void getMembers(Array<T>& keyArray) const {
- memberTable.getKeys(keyArray);
- }
-
- void clear() {
- memberTable.clear();
- }
-
- void deleteAll() {
- getMembers().deleteAll();
- clear();
- }
-
- /**
- C++ STL style iterator variable. See begin().
- */
- class Iterator {
- private:
- friend class Set<T>;
-
- // Note: this is a Table iterator, we are currently defining
- // Set iterator
- typename Table<T, bool>::Iterator it;
-
- Iterator(const typename Table<T, bool>::Iterator& it) : it(it) {}
-
- public:
- inline bool operator!=(const Iterator& other) const {
- return !(*this == other);
- }
-
- bool hasMore() const {
- return it.hasMore();
- }
-
- bool operator==(const Iterator& other) const {
- return it == other.it;
- }
-
- /**
- Pre increment.
- */
- Iterator& operator++() {
- ++it;
- return *this;
- }
-
- /**
- Post increment (slower than preincrement).
- */
- Iterator operator++(int) {
- Iterator old = *this;
- ++(*this);
- return old;
- }
-
- const T& operator*() const {
- return it->key;
- }
-
- T* operator->() const {
- return &(it->key);
- }
-
- operator T*() const {
- return &(it->key);
- }
- };
-
-
- /**
- C++ STL style iterator method. Returns the first member.
- Use preincrement (++entry) to get to the next element.
- Do not modify the set while iterating.
- */
- Iterator begin() const {
- return Iterator(memberTable.begin());
- }
-
-
- /**
- C++ STL style iterator method. Returns one after the last iterator
- element.
- */
- const Iterator end() const {
- return Iterator(memberTable.end());
- }
-};
-
-}
-
-#endif
-
diff --git a/externals/g3dlite/G3D/SmallArray.h b/externals/g3dlite/G3D/SmallArray.h
deleted file mode 100644
index 41f9959e264..00000000000
--- a/externals/g3dlite/G3D/SmallArray.h
+++ /dev/null
@@ -1,155 +0,0 @@
-/**
- @file SmallArray.h
-
- @created 2009-04-26
- @edited 2009-04-26
-
- Copyright 2000-2009, Morgan McGuire, http://graphics.cs.williams.edu
- All rights reserved.
- */
-#ifndef G3D_SmallArray_h
-#define G3D_SmallArray_h
-
-#include "G3D/platform.h"
-#include "G3D/Array.h"
-
-namespace G3D {
-
-/** Embeds \a N elements to reduce allocation time and increase
- memory coherence when working with arrays of arrays.
- Offers a limited subset of the functionality of G3D::Array.*/
-template<class T, int N>
-class SmallArray {
-private:
- int m_size;
-
- /** First N elements */
- T m_embedded[N];
-
- /** Remaining elements */
- Array<T> m_rest;
-
-public:
-
- SmallArray() : m_size(0) {}
-
- inline int size() const {
- return m_size;
- }
-
- void resize(int n, bool shrinkIfNecessary = true) {
- m_rest.resize(std::max(0, n - N), shrinkIfNecessary);
- m_size = n;
- }
-
- void clear(bool shrinkIfNecessary = true) {
- resize(0, shrinkIfNecessary);
- }
-
- inline T& operator[](int i) {
- debugAssert(i < m_size && i >= 0);
- if (i < N) {
- return m_embedded[i];
- } else {
- return m_rest[i - N];
- }
- }
-
- inline const T& operator[](int i) const {
- debugAssert(i < m_size && i >= 0);
- if (i < N) {
- return m_embedded[i];
- } else {
- return m_rest[i - N];
- }
- }
-
- inline void push(const T& v) {
- ++m_size;
- if (m_size <= N) {
- m_embedded[m_size - 1] = v;
- } else {
- m_rest.append(v);
- }
- }
-
- inline void append(const T& v) {
- push(v);
- }
-
- void fastRemove(int i) {
- debugAssert(i < m_size && i >= 0);
- if (i < N) {
- if (m_size <= N) {
- // Exclusively embedded
- m_embedded[i] = m_embedded[m_size - 1];
- } else {
- // Move one down from the rest array
- m_embedded[i] = m_rest.pop();
- }
- } else {
- // Removing from the rest array
- m_rest.fastRemove(i - N);
- }
- --m_size;
- }
-
- T pop() {
- debugAssert(m_size > 0);
- if (m_size <= N) {
- // Popping from embedded, don't need a temporary
- --m_size;
- return m_embedded[m_size];
- } else {
- // Popping from rest
- --m_size;
- return m_rest.pop();
- }
- }
-
- inline void popDiscard() {
- debugAssert(m_size > 0);
- if (m_size > N) {
- m_rest.popDiscard();
- }
- --m_size;
- }
-
- inline T& next() {
- ++m_size;
- if (m_size <= N) {
- return m_embedded[m_size - 1];
- } else {
- return m_rest.next();
- }
- }
-
- bool contains(const T& value) const {
- for (int i = std::min(m_size, N) - 1; i >= 0; --i) {
- if (m_embedded[i] == value) {
- return true;
- }
- }
- return m_rest.contains(value);
- }
-
- template<int MIN_ELEMENTS, int MIN_BYTES>
- SmallArray<T, N>& operator=(const Array<T, MIN_ELEMENTS, MIN_BYTES>& src) {
- resize(src.size());
- for (int i = 0; i < src.size(); ++i) {
- (*this)[i] = src[i];
- }
- return *this;
- }
-
- inline const T& last() const {
- return (*this)[size() - 1];
- }
-
- inline T& last() {
- return (*this)[size() - 1];
- }
-};
-
-}
-#endif
diff --git a/externals/g3dlite/G3D/Sphere.h b/externals/g3dlite/G3D/Sphere.h
deleted file mode 100644
index 595b61c4bf1..00000000000
--- a/externals/g3dlite/G3D/Sphere.h
+++ /dev/null
@@ -1,148 +0,0 @@
-/**
- @file Sphere.h
-
- Sphere class
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2001-06-02
- @edited 2008-10-07
- */
-
-#ifndef G3D_SPHERE_H
-#define G3D_SPHERE_H
-
-#include "G3D/platform.h"
-#include "G3D/Vector3.h"
-#include "G3D/Array.h"
-#include "G3D/Sphere.h"
-
-namespace G3D {
-
-/**
- Sphere.
- */
-class Sphere {
-private:
-
- static int32 dummy;
-
-public:
- Vector3 center;
- float radius;
-
- Sphere() {
- center = Vector3::zero();
- radius = 0;
- }
-
- Sphere(class BinaryInput& b);
- void serialize(class BinaryOutput& b) const;
- void deserialize(class BinaryInput& b);
-
- Sphere(
- const Vector3& center,
- float radius) {
-
- this->center = center;
- this->radius = radius;
- }
-
- virtual ~Sphere() {}
-
- bool operator==(const Sphere& other) const {
- return (center == other.center) && (radius == other.radius);
- }
-
- bool operator!=(const Sphere& other) const {
- return !((center == other.center) && (radius == other.radius));
- }
-
- /**
- Returns true if point is less than or equal to radius away from
- the center.
- */
- bool contains(const Vector3& point) const;
-
- bool contains(const Sphere& other) const;
-
- /**
- @deprecated Use culledBy(Array<Plane>&)
- */
- bool culledBy(
- const class Plane* plane,
- int numPlanes,
- int32& cullingPlaneIndex,
- const uint32 testMask,
- uint32& childMask) const;
-
- /**
- @deprecated Use culledBy(Array<Plane>&)
- */
- bool culledBy(
- const class Plane* plane,
- int numPlanes,
- int32& cullingPlaneIndex = dummy,
- const uint32 testMask = 0xFFFFFFFF) const;
-
- /**
- See AABox::culledBy
- */
- bool culledBy(
- const Array<Plane>& plane,
- int32& cullingPlaneIndex,
- const uint32 testMask,
- uint32& childMask) const;
-
- /**
- Conservative culling test that does not produce a mask for children.
- */
- bool culledBy(
- const Array<Plane>& plane,
- int32& cullingPlaneIndex = dummy,
- const uint32 testMask = 0xFFFFFFFF) const;
-
- virtual std::string toString() const;
-
- float volume() const;
-
- float area() const;
-
- /**
- Uniformly distributed on the surface.
- */
- Vector3 randomSurfacePoint() const;
-
- /**
- Uniformly distributed on the interior (includes surface)
- */
- Vector3 randomInteriorPoint() const;
-
- void getBounds(class AABox& out) const;
-
- bool intersects(const Sphere& other) const;
-
- /** Translates the sphere */
- Sphere operator+(const Vector3& v) const {
- return Sphere(center + v, radius);
- }
-
- /** Translates the sphere */
- Sphere operator-(const Vector3& v) const {
- return Sphere(center - v, radius);
- }
-
- /** Sets this to the smallest sphere that encapsulates both */
- void merge(const Sphere& s);
-};
-
-}
-
-template <> struct HashTrait<G3D::Sphere> {
- static size_t hashCode(const G3D::Sphere& key) {
- return static_cast<size_t>(key.center.hashCode() + (key.radius * 13));
- }
-};
-
-
-#endif
diff --git a/externals/g3dlite/G3D/Spline.h b/externals/g3dlite/G3D/Spline.h
deleted file mode 100644
index fdd29e69ce9..00000000000
--- a/externals/g3dlite/G3D/Spline.h
+++ /dev/null
@@ -1,367 +0,0 @@
-/**
- @file Spline.h
-
- @author Morgan McGuire, http://graphics.cs.williams.edu
- */
-
-#ifndef G3D_SPLINE_H
-#define G3D_SPLINE_H
-
-#include "G3D/platform.h"
-#include "G3D/Array.h"
-#include "G3D/g3dmath.h"
-#include "G3D/Matrix4.h"
-#include "G3D/Vector4.h"
-
-namespace G3D {
-
-/** Common implementation code for all G3D::Spline template parameters */
-class SplineBase {
-public:
-
- /** Times at which control points occur. Must have the same
- number of elements as Spline::control. */
- Array<float> time;
-
- /** If cyclic, then the control points will be assumed to wrap around.
- If not cyclic, then the tangents at the ends of the spline
- point to the final control points.*/
- bool cyclic;
-
- /** For a cyclic spline, this is the time elapsed between the last
- control point and the first. If less than or equal to zero this is
- assumed to be:
-
- (time[0] - time[1] + .
- time[time.size() - 1] - time[time.size() - 2]) / 2.
- */
- float finalInterval;
-
- SplineBase() : cyclic(true), finalInterval(-1) {}
-
- virtual ~SplineBase() {}
-
- /** See specification for Spline::finalInterval; this handles the
- non-positive case. Returns 0 if not cyclic. */
- float getFinalInterval() const;
-
- /** Returns the amount of time covered by this spline in one
- period. For a cyclic spline, this contains the final
- interval.*/
- float duration() const;
-
- /** Computes the derivative spline basis from the control point version. */
- static Matrix4 computeBasis();
-
-protected:
-
- /** Assumes that t0 <= s < tn. called by computeIndex. */
- void computeIndexInBounds(float s, int& i, float& u) const;
-
-public:
-
- /**
- Given a time @a s, finds @a i and 0 <= @a u < 1 such that
- @a s = time[@a i] * @a u + time[@a i + 1] * (1 - @a u). Note that
- @a i may be outside the bounds of the time and control arrays;
- use getControl to handle wraparound and extrapolation issues.
-
- This function takes expected O(1) time for control points with
- uniform time sampled control points or for uniformly
- distributed random time samples, but may take O( log time.size() ) time
- in the worst case.
-
- Called from evaluate().
- */
- void computeIndex(float s, int& i, float& u) const;
-};
-
-
-/**
- Smooth parameteric curve implemented using a piecewise 3rd-order
- Catmull-Rom spline curve. The spline is considered infinite and may
- either continue linearly from the specified control points or cycle
- through them. Control points are spaced uniformly in time at unit
- intervals by default, but irregular spacing may be explicitly
- specified.
-
- The dimension of the spline can be set by varying the Control
- template parameter. For a 1D function, use Spline<float>. For a
- curve in the plane, Spline<Vector2>. Note that <i>any</i> template
- parameter that supports operator+(Control) and operator*(float) can
- be used; you can make splines out of G3D::Vector4, G3D::Matrix3, or
- your own classes.
-
- To provide shortest-path interpolation, subclass G3D::Spline and
- override ensureShortestPath(). To provide normalization of
- interpolated points (e.g., projecting Quats onto the unit
- hypersphere) override correct().
-
- See Real Time Rendering, 2nd edition, ch 12 for a general discussion
- of splines and their properties.
-
- @sa G3D::UprightSpline, G3D::QuatSpline
- */
-template<typename Control>
-class Spline : public SplineBase {
-protected:
- /** The additive identity control point. */
- Control zero;
-
-public:
-
- /** Control points. Must have the same number of elements as
- Spline::time.*/
- Array<Control> control;
-
- Spline() {
- static Control x;
- // Hide the fact from C++ that we are using an
- // uninitialized variable here by pointer arithmetic.
- // This is ok because any type that is a legal control
- // point also supports multiplication by float.
- zero = *(&x) * 0.0f;
- }
-
- /** Appends a control point at a specific time that must be
- greater than that of the previous point. */
- void append(float t, const Control& c) {
- debugAssertM((time.size() == 0) || (t > time.last()),
- "Control points must have monotonically increasing times.");
- time.append(t);
- control.append(c);
- debugAssert(control.size() == time.size());
- }
-
-
- /** Appends control point spaced in time based on the previous
- control point, or spaced at unit intervals if this is the
- first control point. */
- void append(const Control& c) {
- switch (time.size()) {
- case 0:
- append(0, c);
- break;
-
- case 1:
- if (time[0] == 0) {
- append(1, c);
- } else {
- append(time[0], c);
- }
- break;
-
- default:
- append(2 * time[time.size() - 1] - time[time.size() - 2], c);
- }
- debugAssert(control.size() == time.size());
- }
-
- /** Erases all control points and times, but retains the state of
- cyclic and finalInterval.
- */
- void clear() {
- control.clear();
- time.clear();
- }
-
-
- /** Number of control points */
- int size() const {
- debugAssert(time.size() == control.size());
- return control.size();
- }
-
-
- /** Returns the requested control point and time sample based on
- array index. If the array index is out of bounds, wraps (for
- a cyclic spline) or linearly extrapolates (for a non-cyclic
- spline), assuming time intervals follow the first or last
- sample recorded.
-
- Calls correct() on the control point if it was extrapolated.
-
- Returns 0 if there are no control points.
-
- @sa Spline::control and Spline::time for the underlying
- control point array; Spline::computeIndex to find the index
- given a time.
- */
- void getControl(int i, float& t, Control& c) const {
- int N = control.size();
- if (N == 0) {
- c = zero;
- t = 0;
- } else if (cyclic) {
- c = control[iWrap(i, N)];
-
- if (i < 0) {
- // Wrapped around bottom
-
- // Number of times we wrapped around the cyclic array
- int wraps = (N + 1 - i) / N;
- int j = (i + wraps * N) % N;
- t = time[j] - wraps * duration();
-
- } else if (i < N) {
-
- t = time[i];
-
- } else {
- // Wrapped around top
-
- // Number of times we wrapped around the cyclic array
- int wraps = i / N;
- int j = i % N;
- t = time[j] + wraps * duration();
- }
-
- } else if (i < 0) {
- // Are there enough points to extrapolate?
- if (N >= 2) {
- // Step away from control point 0
- float dt = time[1] - time[0];
-
- // Extrapolate (note; i is negative)
- c = control[1] * float(i) + control[0] * float(1 - i);
- correct(c);
- t = dt * i + time[0];
-
- } else {
- // Just clamp
- c = control[0];
-
- // Only 1 time; assume 1s intervals
- t = time[0] + i;
- }
-
- } else if (i >= N) {
- if (N >= 2) {
- float dt = time[N - 1] - time[N - 2];
-
- // Extrapolate
- c = control[N - 1] * float(i - N + 2) + control[N - 2] * -float(i - N + 1);
- correct(c);
- t = time[N - 1] + dt * (i - N + 1);
-
- } else {
- // Return the last, clamping
- c = control.last();
- // Only 1 time; assume 1s intervals
- t = time[0] + i;
- }
- } else {
- // In bounds
- c = control[i];
- t = time[i];
- }
- }
-
-protected:
-
- /** Returns a series of N control points and times, fixing
- boundary issues. The indices may be assumed to be treated
- cyclically. */
- void getControls(int i, float* T, Control* A, int N) const {
- for (int j = 0; j < N; ++j) {
- getControl(i + j, T[j], A[j]);
- }
- ensureShortestPath(A, N);
- }
-
- /**
- Mutates the array of N control points. It is useful to override this
- method by one that wraps the values if they are angles or quaternions
- for which "shortest path" interpolation is significant.
- */
- virtual void ensureShortestPath(Control* A, int N) const { (void)A; (void) N;}
-
- /** Normalize or otherwise adjust this interpolated Control. */
- virtual void correct(Control& A) const { (void)A; }
-
-public:
-
-
- /**
- Return the position at time s. The spline is defined outside
- of the time samples by extrapolation or cycling.
- */
- Control evaluate(float s) const {
- debugAssertM(control.size() == time.size(), "Corrupt spline: wrong number of control points.");
-
- /*
- @cite http://www.gamedev.net/reference/articles/article1497.asp
- Derivation of basis matrix follows.
-
- Given control points with positions p[i] at times t[i], 0 <= i <= 3, find the position
- at time t[1] <= s <= t[2].
-
- Let u = s - t[0]
- Let U = [u^0 u^1 u^2 u^3] = [1 u u^2 u^3]
- Let dt0 = t[0] - t[-1]
- Let dt1 = t[1] - t[0]
- Let dt2 = t[2] - t[1]
- */
-
- // Index of the first control point (i.e., the u = 0 point)
- int i = 0;
- // Fractional part of the time
- float u = 0;
-
- computeIndex(s, i, u);
-
- Control p[4];
- float t[4];
- getControls(i - 1, t, p, 4);
- float dt0 = t[1] - t[0];
- float dt1 = t[2] - t[1];
- float dt2 = t[3] - t[2];
-
- static const Matrix4 basis = computeBasis();
-
- // Powers of u
- Vector4 uvec((float)(u*u*u), (float)(u*u), (float)u, 1.0f);
-
- // Compute the weights on each of the control points.
- const Vector4& weights = uvec * basis;
-
- // Compute the weighted sum of the neighboring control points.
- Control sum;
-
- const Control& p0 = p[0];
- const Control& p1 = p[1];
- const Control& p2 = p[2];
- const Control& p3 = p[3];
-
- const Control& dp0 = p1 + (p0*-1.0f);
- const Control& dp1 = p2 + (p1*-1.0f);
- const Control& dp2 = p3 + (p2*-1.0f);
-
- // The factor of 1/2 from averaging two time intervals is
- // already factored into the basis
-
- // tan1 = (dp0 / dt0 + dp1 / dt1) * ((dt0 + dt1) * 0.5);
- // The last term normalizes for unequal time intervals
- float x = (dt0 + dt1) * 0.5f;
- float n0 = x / dt0;
- float n1 = x / dt1;
- float n2 = x / dt2;
- const Control& dp1n1 = dp1 * n1;
- const Control& tan1 = dp0 * n0 + dp1n1;
- const Control& tan2 = dp1n1 + dp2 * n2;
-
- sum =
- tan1 * weights[0]+
- p1 * weights[1] +
- p2 * weights[2] +
- tan2 * weights[3];
-
-
- correct(sum);
- return sum;
- }
-};
-
-}
-
-#endif
diff --git a/externals/g3dlite/G3D/Stopwatch.h b/externals/g3dlite/G3D/Stopwatch.h
deleted file mode 100644
index 3f2aa9c8d86..00000000000
--- a/externals/g3dlite/G3D/Stopwatch.h
+++ /dev/null
@@ -1,144 +0,0 @@
-/**
- @file Stopwatch.h
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2005-10-05
- @edited 2009-05-10
-
- Copyright 2000-2009, Morgan McGuire.
- All rights reserved.
- */
-
-#ifndef G3D_Stopwatch_h
-#define G3D_Stopwatch_h
-
-#include "G3D/platform.h"
-#include "G3D/Queue.h"
-#include "G3D/G3DGameUnits.h"
-#include "G3D/g3dmath.h"
-
-namespace G3D {
-
-/**
- \brief Accurately measure durations and framerates.
-
- Example 1: For profiling code in the context of a rendering loop:
- <pre>
- sw.tick();
- ...timed code...
- sw.tock();
-
- screenPrintf("%f\n", sw.smoothFPS());
- </pre>
-
-
- Example 2: For profiling pieces of a sequence:
- <pre>
- Stopwatch sw;
- slowOperation();
- sw.after("slowOperation");
- kdTree.balance();
- sw.after("Balance tree");
- </pre>
- */
-class Stopwatch {
-private:
-
- std::string myName;
- double startTime;
- std::string prevMark;
- double prevTime;
-
- /** True between tick and tock */
- bool inBetween;
-
- /** The initial cycle count. */
- uint64 cycleStart;
-
- /** The time at which tick was called. */
- RealTime timeStart;
-
- /** The time at which the previous tock was called, -1 if never. */
- RealTime lastTockTime;
-
- RealTime lastDuration;
- int64 lastCycleCount;
-
- /** Frames per second. */
- double m_fps;
-
- /** Weighted fps */
- double emwaFPS;
- double m_smoothFPS;
-
- /** Weighted duration */
- RealTime emwaDuration;
-
- /** The overhead for calling into the class. */
- int64 cycleOverhead;
-
- /** Called from the constructor. */
- void computeOverhead();
-
-public:
-
- Stopwatch(const std::string& name = "Stopwatch");
-
- /** Returns the number of times that tick was called per wall-clock second;
- e.g. frames-per-second. */
- double FPS() const {
- return m_fps;
- }
-
- /** Amount of time between the most recent tick and tock calls. 0 if tick has
- never been called. */
- RealTime elapsedTime() const {
- return lastDuration;
- }
-
- /** Time-smoothed value that is stable to the nearest 1%.
- This is useful if you are displaying elapsed time in real-time
- and want a stable number.*/
- RealTime smoothElapsedTime() const {
- return emwaDuration;
- }
-
- /** Time-smoothed value of fps that is stable to the nearest integer for fps > 10 and
- to the first decimal place for fps <= 10.
- This is useful if you
- are displaying the frame rate in real-time and want a stable (readable) number.*/
- double smoothFPS() const {
- return m_smoothFPS;
- }
-
- /** The elapsed cycle time between tick and tock. An attempt is made to factor out all
- tick/tock overhead, so that back-to-back calls should return zero.
- Unreliable on non-x86 platforms.*/
- uint64 elapsedCycles() const {
- return lastCycleCount;
- }
-
- /** Call at the beginning of the period that you want timed. */
- void tick();
-
- /** Call at the end of the period that you want timed. */
- void tock();
-
-
- /** Reset the start time used by after() and the emwa value.*/
- void reset();
-
- /** Call after an operation has completed, with the name of the operation, to
- print a debug message listing the time since the previous after() call. */
- void after(const std::string& s = "");
-
-};
-
-/** Because it is hard to remember the proper capitalization. */
-typedef Stopwatch StopWatch;
-
-}
-
-#endif
-
diff --git a/externals/g3dlite/G3D/System.h b/externals/g3dlite/G3D/System.h
deleted file mode 100644
index 56ef9c8e3dc..00000000000
--- a/externals/g3dlite/G3D/System.h
+++ /dev/null
@@ -1,507 +0,0 @@
-/**
- @file System.h
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @cite Rob Wyatt http://www.gamasutra.com/features/wyatts_world/19990709/processor_detection_01.htm
- @cite Benjamin Jurke http://www.flipcode.com/cgi-bin/msg.cgi?showThread=COTD-ProcessorDetectionClass&forum=cotd&id=-1
- @cite Michael Herf http://www.stereopsis.com/memcpy.html
-
- @created 2003-01-25
- @edited 2008-10-14
- */
-
-#ifndef G3D_System_h
-#define G3D_System_h
-
-#include "G3D/platform.h"
-#include "G3D/g3dmath.h"
-#include "G3D/G3DGameUnits.h"
-#include "G3D/BinaryFormat.h"
-#include <string>
-
-#ifdef G3D_OSX
-# include <CoreServices/CoreServices.h>
-#endif
-
-namespace G3D {
-
-/**
- Routine used by the demos to find the data. Searches in
- ../data, ../../data, etc. up to 5 levels back. Checks
- common locations like \verbatim c:\libraries\g3d-<version>\data \endverbatim
- and some hard-coded paths on the Brown University file
- system.
-
- @deprecated
- */
-std::string demoFindData(bool errorIfNotFound = true);
-
-/** G3D, SDL, and IJG libraries require license documentation
- to be distributed with your program. This generates the
- string that must appear in your documentation.
- <B>Your program can be commercial, closed-source</B> under
- any license you want.
- @deprecated Use System::license
-*/
-std::string license();
-
-/**
-@brief The order in which the bytes of an integer are stored on a
-machine.
-
-Intel/AMD chips tend to be G3D_LITTLE_ENDIAN, Mac PPC's and Suns are
-G3D_BIG_ENDIAN. However, this is primarily used to specify the byte
-order of file formats, which are fixed.
-*/
-enum G3DEndian {
- G3D_BIG_ENDIAN,
- G3D_LITTLE_ENDIAN
-};
-
-/**
- @brief OS and processor abstraction.
-
- The first time any method is called the processor will be analyzed.
- Future calls are then fast.
-
- Timing function overview:
- System::getCycleCount
- - actual cycle count
-
- System::getTick
- - High-resolution time in seconds since program started
-
- System::getLocalTime
- - High-resolution time in seconds since Jan 1, 1970
- (because it is stored in a double, this may be less
- accurate than getTick)
- */
-class System {
-public:
- /**
- @param size Size of memory that the system was trying to allocate
-
- @param recoverable If true, the system will attempt to allocate again
- if the callback returns true. If false, malloc is going to return
- NULL and this invocation is just to notify the application.
-
- @return Return true to force malloc to attempt allocation again if the
- error was recoverable.
- */
- typedef bool (*OutOfMemoryCallback)(size_t size, bool recoverable);
-
-private:
-
- bool m_initialized;
- int m_cpuSpeed;
- bool m_hasCPUID;
- bool m_hasRDTSC;
- bool m_hasMMX;
- bool m_hasSSE;
- bool m_hasSSE2;
- bool m_hasSSE3;
- bool m_has3DNOW;
- bool m_has3DNOW2;
- bool m_hasAMDMMX;
- std::string m_cpuVendor;
- int m_numCores;
-
- /** this holds the data directory set by the application (currently
- GApp) for use by findDataFile */
- std::string m_appDataDir;
-
- G3DEndian m_machineEndian;
- std::string m_cpuArch;
- std::string m_operatingSystem;
-
-# ifdef G3D_WIN32
- /** Used by getTick() for timing */
- LARGE_INTEGER m_start;
- LARGE_INTEGER m_counterFrequency;
-#else
- struct timeval m_start;
-#endif
-
- std::string m_version;
- OutOfMemoryCallback m_outOfMemoryCallback;
-
-#ifdef G3D_OSX
- /** In Cycles/Second */
- SInt32 m_OSXCPUSpeed;
- double m_secondsPerNS;
-#endif
-
- /** The Real-World time of System::getTick() time 0. Set by initTime */
- RealTime m_realWorldGetTickTime0;
-
- uint32 m_highestCPUIDFunction;
-
- /** @brief Used for the singleton instance only. */
- System();
-
- /** @brief The singleton instance.
-
- Used instead of a global variable to ensure that the order of
- intialization is correct, which is critical because other
- globals may allocate memory using System::malloc.
- */
- static System& instance();
-
- enum CPUIDFunction {
- CPUID_VENDOR_ID = 0x00000000,
- CPUID_PROCESSOR_FEATURES = 0x00000001,
- CPUID_NUM_CORES = 0x00000004,
- CPUID_GET_HIGHEST_FUNCTION = 0x80000000,
- CPUID_EXTENDED_FEATURES = 0x80000001};
-
- /** Helper macro to call cpuid functions and return all values
-
- See http://software.intel.com/en-us/articles/intel-64-architecture-processor-topology-enumeration/
- or http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/25481.pdf
-
- for description of the arguments.
- */
- static void cpuid(CPUIDFunction func, uint32& areg, uint32& breg, uint32& creg, uint32& dreg);
-
- void init();
-
- /** Called from init() */
- void getStandardProcessorExtensions();
-
- /** Called from init() */
- void initTime();
-
-public:
-
- /** Returns the speed of processor 0 in MHz.
- Always returns 0 on linux.*/
- inline static int cpuSpeedMHz() {
- return instance().m_cpuSpeed;
- }
-
- /** Returns the number of logical processor cores (i.e., the
- number of execution units for threads) */
- inline static int numCores() {
- return instance().m_numCores;
- }
-
- inline static bool hasCPUID() {
- return instance().m_hasCPUID;
- }
-
- inline static bool hasRDTSC() {
- return instance().m_hasRDTSC;
- }
-
- inline static bool hasSSE() {
- return instance().m_hasSSE;
- }
-
- inline static bool hasSSE2() {
- return instance().m_hasSSE2;
- }
-
- inline static bool hasSSE3() {
- return instance().m_hasSSE3;
- }
-
- inline static bool hasMMX() {
- return instance().m_hasMMX;
- }
-
- inline static bool has3DNow() {
- return instance().m_has3DNOW;
- }
-
- inline static const std::string& cpuVendor() {
- return instance().m_cpuVendor;
- }
-
- /**
- Returns the endianness of this machine.
- */
- inline static G3DEndian machineEndian() {
- return instance().m_machineEndian;
- }
-
- /** e.g., "Windows", "GNU/Linux" */
- inline static const std::string& operatingSystem() {
- return instance().m_operatingSystem;
- }
-
- /** e.g., 80686 */
- inline static const std::string& cpuArchitecture() {
- return instance().m_cpuArch;
- }
-
- /**
- Returns the current date as a string in the form YYYY-MM-DD
- */
- static std::string currentDateString();
-
- /**
- Guarantees that the start of the array is aligned to the
- specified number of bytes.
- */
- static void* alignedMalloc(size_t bytes, size_t alignment);
-
- /**
- Uses pooled storage to optimize small allocations (1 byte to 5
- kilobytes). Can be 10x to 100x faster than calling ::malloc or
- new.
-
- The result must be freed with free.
-
- Threadsafe on Win32.
-
- @sa calloc realloc OutOfMemoryCallback free
- */
- static void* malloc(size_t bytes);
-
- static void* calloc(size_t n, size_t x);
-
- /**
- Version of realloc that works with System::malloc.
- */
- static void* realloc(void* block, size_t bytes);
-
- /** Returns a string describing how well System::malloc is using
- its internal pooled storage. "heap" memory was slow to
- allocate; the other data sizes are comparatively fast.*/
- static std::string mallocPerformance();
- static void resetMallocPerformanceCounters();
-
- /**
- Returns a string describing the current usage of the buffer pools used for
- optimizing System::malloc.
- */
- static std::string mallocStatus();
-
- /**
- Free data allocated with System::malloc.
-
- Threadsafe on Win32.
- */
- static void free(void* p);
-
- /**
- Frees memory allocated with alignedMalloc.
- */
- static void alignedFree(void* ptr);
-
- /** An implementation of memcpy that may be up to 2x as fast as the C library
- one on some processors. Guaranteed to have the same behavior as memcpy
- in all cases. */
- static void memcpy(void* dst, const void* src, size_t numBytes);
-
- /** An implementation of memset that may be up to 2x as fast as the C library
- one on some processors. Guaranteed to have the same behavior as memset
- in all cases. */
- static void memset(void* dst, uint8 value, size_t numBytes);
-
- /**
- Returns the fully qualified filename for the currently running executable.
-
- This is more reliable than arg[0], which may be intentionally set
- to an incorrect value by a calling program, relative to a now
- non-current directory, or obfuscated by sym-links.
-
- @cite Linux version written by Nicolai Haehnle <prefect_@gmx.net>, http://www.flipcode.com/cgi-bin/msg.cgi?showThread=COTD-getexename&forum=cotd&id=-1
- */
- static std::string currentProgramFilename();
-
- /** Name of this program. Note that you can mutate this string to
- set your app name explicitly.*/
- static std::string& appName();
-
- /** G3D Version string */
- inline static const std::string& version() {
- return instance().m_version;
- }
-
- /**
- @brief The optimization status of the G3D library (not the program compiled against it)
-
- Either "Debug" or "Release", depending on whether _DEBUG was
- defined at compile-time for the library.
- */
- static const std::string& build();
-
- /**
- Causes the current thread to yield for the specified duration
- and consume almost no CPU.
- The sleep will be extremely precise; it uses System::time()
- to calibrate the exact yeild time.
- */
- static void sleep(RealTime t);
-
- /**
- Clears the console.
- Console programs only.
- */
- static void consoleClearScreen();
-
- /**
- Returns true if a key is waiting.
- Console programs only.
- */
- static bool consoleKeyPressed();
-
- /**
- Blocks until a key is read (use consoleKeyPressed to determine if
- a key is waiting to be read) then returns the character code for
- that key.
- */
- static int consoleReadKey();
-
- /**
- The actual time (measured in seconds since
- Jan 1 1970 midnight).
-
- Adjusted for local timezone and daylight savings
- time. This is as accurate and fast as getCycleCount().
- */
- static RealTime time();
-
- /**
- To count the number of cycles a given operation takes:
-
- <PRE>
- unsigned long count;
- System::beginCycleCount(count);
- ...
- System::endCycleCount(count);
- // count now contains the cycle count for the intervening operation.
- </PRE>
- */
- /* static void beginCycleCount(uint64& cycleCount);
- static void endCycleCount(uint64& cycleCount);
-
- static uint64 getCycleCount(); */
-
- inline static void setOutOfMemoryCallback(OutOfMemoryCallback c) {
- instance().m_outOfMemoryCallback = c;
- }
-
- /**
- When System::malloc fails to allocate memory because the system is
- out of memory, it invokes this handler (if it is not NULL).
- The argument to the callback is the amount of memory that malloc
- was trying to allocate when it ran out. If the callback returns
- true, System::malloc will attempt to allocate the memory again.
- If the callback returns false, then System::malloc will return NULL.
-
- You can use outOfMemoryCallback to free data structures or to
- register the failure.
- */
- inline static OutOfMemoryCallback outOfMemoryCallback() {
- return instance().m_outOfMemoryCallback;
- }
-
- /** Set an environment variable for the current process */
- static void setEnv(const std::string& name, const std::string& value);
-
- /** Get an environment variable for the current process. Returns NULL if the variable doesn't exist. */
- static const char* getEnv(const std::string& name);
-
- /**
- Prints a human-readable description of this machine
- to the text output stream. Either argument may be NULL.
- */
- static void describeSystem(
- class TextOutput& t);
-
- static void describeSystem(
- std::string& s);
-
- /** On Win32, returns the clipboard text contents. Does nothing on other
- platforms (yet) */
- static std::string getClipboardText();
-
- /** Copies the text to the clipboard on Win32. */
- static void setClipboardText(const std::string& s);
-
- /**
- Tries to locate the resource by looking in related directories.
- If found, returns the full path to the resource, otherwise
- returns the empty string.
- */
- static std::string findDataFile(const std::string& full, bool errorIfNotFound = true);
-
- /**
- Sets the path that the application is using as its data directory.
- Used by findDataDir as an initial search location. GApp sets this
- upon constrution.
- */
- static void setAppDataDir(const std::string& path);
-
-};
-
-/* don't need that for MaNGOS, not portable to Win64...
-#ifdef _MSC_VER
- inline uint64 System::getCycleCount() {
- uint32 timehi, timelo;
-
- // Use the assembly instruction rdtsc, which gets the current
- // cycle count (since the process started) and puts it in edx:eax.
- __asm
- {
- rdtsc;
- mov timehi, edx;
- mov timelo, eax;
- }
-
- return ((uint64)timehi << 32) + (uint64)timelo;
- }
-
-#elif defined(G3D_LINUX)
-
- inline uint64 System::getCycleCount() {
- uint32 timehi, timelo;
-
- __asm__ __volatile__ (
- "rdtsc "
- : "=a" (timelo),
- "=d" (timehi)
- : );
-
- return ((uint64)timehi << 32) + (uint64)timelo;
- }
-
-#elif defined(G3D_OSX)
-
- inline uint64 System::getCycleCount() {
- //Note: To put off extra processing until the end, this does not
- //return the actual clock cycle count. It is a bus cycle count.
- //When endCycleCount() is called, it converts the two into a difference
- //of clock cycles
-
- return (uint64) UnsignedWideToUInt64(UpTime());
- //return (uint64) mach_absolute_time();
- }
-
-#endif
-
-inline void System::beginCycleCount(uint64& cycleCount) {
- cycleCount = getCycleCount();
-}
-
-
-inline void System::endCycleCount(uint64& cycleCount) {
-#ifndef G3D_OSX
- cycleCount = getCycleCount() - cycleCount;
-#else
- AbsoluteTime end = UpTime();
- Nanoseconds diffNS =
- AbsoluteDeltaToNanoseconds(end, UInt64ToUnsignedWide(cycleCount));
- cycleCount =
- (uint64) ((double) (instance().m_OSXCPUSpeed) *
- (double) UnsignedWideToUInt64(diffNS) * instance().m_secondsPerNS);
-#endif
-}
- */
-
-} // namespace
-
-#endif
diff --git a/externals/g3dlite/G3D/Table.h b/externals/g3dlite/G3D/Table.h
deleted file mode 100644
index 287efa94d97..00000000000
--- a/externals/g3dlite/G3D/Table.h
+++ /dev/null
@@ -1,924 +0,0 @@
-/**
- @file Table.h
-
- Templated hash table class.
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @created 2001-04-22
- @edited 2010-01-28
- Copyright 2000-2010, Morgan McGuire.
- All rights reserved.
- */
-
-#ifndef G3D_Table_h
-#define G3D_Table_h
-
-#include <cstddef>
-#include <string>
-
-#include "G3D/platform.h"
-#include "G3D/Array.h"
-#include "G3D/debug.h"
-#include "G3D/System.h"
-#include "G3D/g3dmath.h"
-#include "G3D/EqualsTrait.h"
-#include "G3D/HashTrait.h"
-#include "G3D/MemoryManager.h"
-
-#ifdef _MSC_VER
-# pragma warning (push)
- // Debug name too long warning
-# pragma warning (disable : 4786)
-#endif
-
-namespace G3D {
-
-/**
- An unordered data structure mapping keys to values.
-
- There are two ways of definining custom hash functions (G3D provides built-in ones for most classes):
-
- <pre>
- class Foo {
- public:
- std::string name;
- int index;
- static size_t hashCode(const Foo& key) {
- return HashTrait<std::string>::hashCode(key.name) + key.index;
- }
- };
-
- template<> struct HashTrait<class Foo> {
- static size_t hashCode(const Foo& key) { return HashTrait<std::string>::hashCode(key.name) + key.index; }
- };
-
-
- // Use Foo::hashCode
- Table<Foo, std::string, Foo> fooTable1;
-
- // Use HashTrait<Foo>
- Table<Foo, std::string> fooTable2;
- </pre>
-
-
- Key must be a pointer, an int, a std::string or provide overloads for:
-
- <PRE>
- template<> struct HashTrait<class Key> {
- static size_t hashCode(const Key& key) { return reinterpret_cast<size_t>( ... ); }
- };
- </PRE>
-
- and one of
-
- <PRE>
- template<> struct EqualsTrait<class Key>{
- static bool equals(const Key& a, const Key& b) { return ... ; }
- };
-
-
- bool operator==(const Key&, const Key&);
- </PRE>
-
- G3D pre-defines HashTrait specializations for common types (like <CODE>int</CODE> and <CODE>std::string</CODE>).
- If you use a Table with a different type you must write those functions yourself. For example,
- an enum would use:
-
- <PRE>
- template<> struct HashTrait<MyEnum> {
- static size_t equals(const MyEnum& key) const { return reinterpret_cast<size_t>( key ); }
- };
- </PRE>
-
- And rely on the default enum operator==.
-
-
- Periodically check that debugGetLoad() is low (> 0.1). When it gets near
- 1.0 your hash function is badly designed and maps too many inputs to
- the same output.
- */
-template<class Key, class Value, class HashFunc = HashTrait<Key>, class EqualsFunc = EqualsTrait<Key> >
-class Table {
-public:
-
- /**
- The pairs returned by iterator.
- */
- class Entry {
- public:
- Key key;
- Value value;
- Entry() {}
- Entry(const Key& k) : key(k) {}
- Entry(const Key& k, const Value& v) : key(k), value(v) {}
- bool operator==(const Entry &peer) const { return (key == peer.key && value == peer.value); }
- bool operator!=(const Entry &peer) const { return !operator==(peer); }
- };
-
-private:
-
- typedef Table<Key, Value, HashFunc, EqualsFunc> ThisType;
-
- /**
- Linked list nodes used internally by HashTable.
- */
- class Node {
- public:
- Entry entry;
- size_t hashCode;
- Node* next;
-
- private:
-
- // Private to require use of the allocator
- Node(const Key& k, const Value& v, size_t h, Node* n)
- : entry(k, v), hashCode(h), next(n) {
- }
-
- Node(const Key& k, size_t h, Node* n)
- : entry(k), hashCode(h), next(n) {
- }
-
- public:
-
- static Node* create(const Key& k, const Value& v, size_t h, Node* n, MemoryManager::Ref& mm) {
- Node* node = (Node*)mm->alloc(sizeof(Node));
- return new (node) Node(k, v, h, n);
- }
-
- static Node* create(const Key& k, size_t hashCode, Node* n, MemoryManager::Ref& mm) {
- Node* node = (Node*)mm->alloc(sizeof(Node));
- return new (node) Node(k, hashCode, n);
- }
-
- static void destroy(Node* n, MemoryManager::Ref& mm) {
- n->~Node();
- mm->free(n);
- }
-
- /**
- Clones a whole chain;
- */
- Node* clone(MemoryManager::Ref& mm) {
- return create(this->entry.key, this->entry.value, hashCode, (next == NULL) ? NULL : next->clone(mm), mm);
- }
- };
-
- void checkIntegrity() const {
-# ifdef G3D_DEBUG
- debugAssert(m_bucket == NULL || isValidHeapPointer(m_bucket));
- for (size_t b = 0; b < m_numBuckets; ++b) {
- Node* node = m_bucket[b];
- debugAssert(node == NULL || isValidHeapPointer(node));
- while (node != NULL) {
- debugAssert(node == NULL || isValidHeapPointer(node));
- node = node->next;
- }
- }
-# endif
- }
-
- /** Number of elements in the table.*/
- size_t m_size;
-
- /**
- Array of Node*.
-
- We don't use Array<Node*> because Table is lower-level than Array.
- Some elements may be NULL.
- */
- Node** m_bucket;
-
- /**
- Length of the m_bucket array.
- */
- size_t m_numBuckets;
-
- MemoryManager::Ref m_memoryManager;
-
- void* alloc(size_t s) const {
- return m_memoryManager->alloc(s);
- }
-
- void free(void* p) const {
- return m_memoryManager->free(p);
- }
-
- /**
- Re-hashes for a larger m_bucket size.
- */
- void resize(size_t newSize) {
-
- // Hang onto the old m_bucket array
- Node** oldBucket = m_bucket;
-
- // Allocate a new m_bucket array with the new size
- m_bucket = (Node**)alloc(sizeof(Node*) * newSize);
- // Set all pointers to NULL
- System::memset(m_bucket, 0, newSize * sizeof(Node*));
- debugAssertM(m_bucket != NULL, "MemoryManager::alloc returned NULL. Out of memory.");
- // Move each node to its new hash location
- for (size_t b = 0; b < m_numBuckets; ++b) {
- Node* node = oldBucket[b];
-
- // There is a linked list of nodes at this m_bucket
- while (node != NULL) {
- // Hang onto the old next pointer
- Node* nextNode = node->next;
-
- // Insert at the head of the list for m_bucket[i]
- size_t i = node->hashCode % newSize;
- node->next = m_bucket[i];
- m_bucket[i] = node;
-
- // Move on to the next node
- node = nextNode;
- }
-
- // Drop the old pointer for cleanliness when debugging
- oldBucket[b] = NULL;
- }
-
- // Delete the old storage
- free(oldBucket);
- this->m_numBuckets = newSize;
-
- checkIntegrity();
- }
-
-
- void copyFrom(const ThisType& h) {
- if (&h == this) {
- return;
- }
-
- debugAssert(m_bucket == NULL);
- m_size = h.m_size;
- m_numBuckets = h.m_numBuckets;
- m_bucket = (Node**)alloc(sizeof(Node*) * m_numBuckets);
- // No need to NULL elements since we're about to overwrite them
-
- for (size_t b = 0; b < m_numBuckets; ++b) {
- if (h.m_bucket[b] != NULL) {
- m_bucket[b] = h.m_bucket[b]->clone(m_memoryManager);
- } else {
- m_bucket[b] = NULL;
- }
- }
-
- checkIntegrity();
- }
-
- /**
- Frees the heap structures for the nodes.
- */
- void freeMemory() {
- checkIntegrity();
-
- for (size_t b = 0; b < m_numBuckets; b++) {
- Node* node = m_bucket[b];
- while (node != NULL) {
- Node* next = node->next;
- Node::destroy(node, m_memoryManager);
- node = next;
- }
- m_bucket[b] = NULL;
- }
- free(m_bucket);
- m_bucket = NULL;
- m_numBuckets = 0;
- m_size = 0;
- }
-
-public:
-
- /**
- Creates an empty hash table using the default MemoryManager.
- */
- Table() : m_bucket(NULL) {
- m_memoryManager = MemoryManager::create();
- m_numBuckets = 0;
- m_size = 0;
- m_bucket = NULL;
- checkIntegrity();
- }
-
- /** Changes the internal memory manager to m */
- void clearAndSetMemoryManager(const MemoryManager::Ref& m) {
- clear();
- debugAssert(m_bucket == NULL);
- m_memoryManager = m;
- }
-
- /**
- Recommends that the table resize to anticipate at least this number of elements.
- */
- void setSizeHint(size_t n) {
- size_t s = n * 3;
- if (s > m_numBuckets) {
- resize(s);
- }
- }
-
- /**
- Destroys all of the memory allocated by the table, but does <B>not</B>
- call delete on keys or values if they are pointers. If you want to
- deallocate things that the table points at, use getKeys() and Array::deleteAll()
- to delete them.
- */
- virtual ~Table() {
- freeMemory();
- }
-
- /** Uses the default memory manager */
- Table(const ThisType& h) {
- m_memoryManager = MemoryManager::create();
- m_numBuckets = 0;
- m_size = 0;
- m_bucket = NULL;
- this->copyFrom(h);
- checkIntegrity();
- }
-
-
- Table& operator=(const ThisType& h) {
- // No need to copy if the argument is this
- if (this != &h) {
- // Free the existing nodes
- freeMemory();
- this->copyFrom(h);
- checkIntegrity();
- }
- return *this;
- }
-
- /**
- Returns the length of the deepest m_bucket.
- */
- size_t debugGetDeepestBucketSize() const {
- size_t deepest = 0;
-
- for (size_t b = 0; b < m_numBuckets; b++) {
- size_t count = 0;
- Node* node = m_bucket[b];
- while (node != NULL) {
- node = node->next;
- ++count;
- }
-
- if (count > deepest) {
- deepest = count;
- }
- }
-
- return deepest;
- }
-
- /**
- Returns the average size of non-empty buckets.
- */
- float debugGetAverageBucketSize() const {
- size_t num = 0;
- size_t count = 0;
-
- for (size_t b = 0; b < m_numBuckets; b++) {
- Node* node = m_bucket[b];
- if (node != NULL) {
- ++num;
- while (node != NULL) {
- node = node->next;
- ++count;
- }
- }
- }
-
- return (float)((double)count / num);
- }
-
- /**
- A small load (close to zero) means the hash table is acting very
- efficiently most of the time. A large load (close to 1) means
- the hash table is acting poorly-- all operations will be very slow.
- A large load will result from a bad hash function that maps too
- many keys to the same code.
- */
- double debugGetLoad() const {
- return debugGetDeepestBucketSize() / (double)size();
- }
-
- /**
- Returns the number of buckets.
- */
- size_t debugGetNumBuckets() const {
- return m_numBuckets;
- }
-
- /**
- C++ STL style iterator variable. See begin().
- */
- class Iterator {
- private:
- friend class Table<Key, Value, HashFunc, EqualsFunc>;
-
- /**
- Bucket index.
- */
- size_t index;
-
- /**
- Linked list node.
- */
- Node* node;
- ThisType* table;
- size_t m_numBuckets;
- Node** m_bucket;
- bool isDone;
-
- /**
- Creates the end iterator.
- */
- Iterator(const ThisType* table) : table(const_cast<ThisType*>(table)) {
- isDone = true;
- }
-
- Iterator(const ThisType* table, size_t m_numBuckets, Node** m_bucket) :
- table(const_cast<ThisType*>(table)),
- m_numBuckets(m_numBuckets),
- m_bucket(m_bucket) {
-
- if (m_numBuckets == 0) {
- // Empty table
- isDone = true;
- return;
- }
-
- index = 0;
- node = m_bucket[index];
- isDone = false;
- findNext();
- }
-
- /**
- Finds the next element, setting isDone if one can't be found.
- Looks at the current element first.
- */
- void findNext() {
- while (node == NULL) {
- index++;
- if (index >= m_numBuckets) {
- isDone = true;
- break;
- } else {
- node = m_bucket[index];
- }
- }
- }
-
- public:
- inline bool operator!=(const Iterator& other) const {
- return !(*this == other);
- }
-
- bool operator==(const Iterator& other) const {
- if (other.isDone || isDone) {
- // Common case; check against isDone.
- return (isDone == other.isDone) && (other.table == table);
- } else {
- return
- (table == other.table) &&
- (node == other.node) &&
- (index == other.index);
- }
- }
-
- /**
- Pre increment.
- */
- Iterator& operator++() {
- node = node->next;
- findNext();
- return *this;
- }
-
- /**
- Post increment (slower than preincrement).
- */
- Iterator operator++(int) {
- Iterator old = *this;
- ++(*this);
- return old;
- }
-
- const Entry& operator*() const {
- return node->entry;
- }
-
- Entry* operator->() const {
- return &(node->entry);
- }
-
- operator Entry*() const {
- return &(node->entry);
- }
-
- bool hasMore() const {
- return ! isDone;
- }
- };
-
-
- /**
- C++ STL style iterator method. Returns the first Entry, which
- contains a key and value. Use preincrement (++entry) to get to
- the next element. Do not modify the table while iterating.
- */
- Iterator begin() const {
- return Iterator(this, m_numBuckets, m_bucket);
- }
-
- /**
- C++ STL style iterator method. Returns one after the last iterator
- element.
- */
- const Iterator end() const {
- return Iterator(this);
- }
-
- /**
- Removes all elements
- */
- void clear() {
- freeMemory();
- m_numBuckets = 0;
- m_size = 0;
- m_bucket = NULL;
- }
-
-
- /**
- Returns the number of keys.
- */
- size_t size() const {
- return m_size;
- }
-
-
- /**
- If you insert a pointer into the key or value of a table, you are
- responsible for deallocating the object eventually. Inserting
- key into a table is O(1), but may cause a potentially slow rehashing.
- */
- void set(const Key& key, const Value& value) {
- getCreateEntry(key).value = value;
- }
-
-private:
-
- /** Helper for remove() and getRemove() */
- bool remove(const Key& key, Key& removedKey, Value& removedValue, bool updateRemoved) {
- if (m_numBuckets == 0) {
- return false;
- }
- size_t code = HashFunc::hashCode(key);
- size_t b = code % m_numBuckets;
-
- // Go to the m_bucket
- Node* n = m_bucket[b];
-
- if (n == NULL) {
- return false;
- }
-
- Node* previous = NULL;
-
- // Try to find the node
- do {
- if ((code == n->hashCode) && EqualsFunc::equals(n->entry.key, key)) {
- // This is the node; remove it
-
- // Replace the previous's next pointer
- if (previous == NULL) {
- m_bucket[b] = n->next;
- } else {
- previous->next = n->next;
- }
-
- if (updateRemoved) {
- removedKey = n->entry.key;
- removedValue = n->entry.value;
- }
- // Delete the node
- Node::destroy(n, m_memoryManager);
- --m_size;
- return true;
- }
-
- previous = n;
- n = n->next;
- } while (n != NULL);
-
- return false;
- //alwaysAssertM(false, "Tried to remove a key that was not in the table.");
- }
-
-public:
-
- /** If @a member is present, sets @a removed to the element
- being removed and returns true. Otherwise returns false
- and does not write to @a removed. */
- bool getRemove(const Key& key, Key& removedKey, Value& removedValue) {
- return remove(key, removedKey, removedValue, true);
- }
-
- /**
- Removes an element from the table if it is present.
- @return true if the element was found and removed, otherwise false
- */
- bool remove(const Key& key) {
- Key x;
- Value v;
- return remove(key, x, v, false);
- }
-
-private:
-
- Entry* getEntryPointer(const Key& key) const {
- if (m_numBuckets == 0) {
- return NULL;
- }
-
- size_t code = HashFunc::hashCode(key);
- size_t b = code % m_numBuckets;
-
- Node* node = m_bucket[b];
-
- while (node != NULL) {
- if ((node->hashCode == code) && EqualsFunc::equals(node->entry.key, key)) {
- return &(node->entry);
- }
- node = node->next;
- }
-
- return NULL;
- }
-
-public:
-
- /** If a value that is EqualsFunc to @a member is present, returns a pointer to the
- version stored in the data structure, otherwise returns NULL.
- */
- const Key* getKeyPointer(const Key& key) const {
- const Entry* e = getEntryPointer(key);
- if (e == NULL) {
- return NULL;
- } else {
- return &(e->key);
- }
- }
-
- /**
- Returns the value associated with key.
- @deprecated Use get(key, val) or getPointer(key)
- */
- Value& get(const Key& key) const {
- Entry* e = getEntryPointer(key);
- debugAssertM(e != NULL, "Key not found");
- return e->value;
- }
-
-
- /** Returns a pointer to the element if it exists, or NULL if it does not.
- Note that if your value type <i>is</i> a pointer, the return value is
- a pointer to a pointer. Do not remove the element while holding this
- pointer.
-
- It is easy to accidentally mis-use this method. Consider making
- a Table<Value*> and using get(key, val) instead, which makes you manage
- the memory for the values yourself and is less likely to result in
- pointer errors.
- */
- Value* getPointer(const Key& key) const {
- if (m_numBuckets == 0) {
- return NULL;
- }
-
- size_t code = HashFunc::hashCode(key);
- size_t b = code % m_numBuckets;
-
- Node* node = m_bucket[b];
-
- while (node != NULL) {
- if ((node->hashCode == code) && EqualsFunc::equals(node->entry.key, key)) {
- // found key
- return &(node->entry.value);
- }
- node = node->next;
- }
-
- // Failed to find key
- return NULL;
- }
-
- /**
- If the key is present in the table, val is set to the associated value and returns true.
- If the key is not present, returns false.
- */
- bool get(const Key& key, Value& val) const {
- Value* v = getPointer(key);
- if (v != NULL) {
- val = *v;
- return true;
- } else {
- return false;
- }
- }
-
-
-
- /** Called by getCreate() and set()
-
- \param created Set to true if the entry was created by this method.
- */
- Entry& getCreateEntry(const Key& key, bool& created) {
- created = false;
-
- if (m_numBuckets == 0) {
- resize(10);
- }
-
- size_t code = HashFunc::hashCode(key);
- size_t b = code % m_numBuckets;
-
- // Go to the m_bucket
- Node* n = m_bucket[b];
-
- // No m_bucket, so this must be the first
- if (n == NULL) {
- m_bucket[b] = Node::create(key, code, NULL, m_memoryManager);
- ++m_size;
- created = true;
- return m_bucket[b]->entry;
- }
-
- size_t bucketLength = 1;
-
- // Sometimes a bad hash code will cause all elements
- // to collide. Detect this case and don't rehash when
- // it occurs; nothing good will come from the rehashing.
- bool allSameCode = true;
-
- // Try to find the node
- do {
- allSameCode = allSameCode && (code == n->hashCode);
-
- if ((code == n->hashCode) && EqualsFunc::equals(n->entry.key, key)) {
- // This is the a pre-existing node
- return n->entry;
- }
-
- n = n->next;
- ++bucketLength;
- } while (n != NULL);
-
- const size_t maxBucketLength = 3;
- // (Don't bother changing the size of the table if all entries
- // have the same hashcode--they'll still collide)
- if ((bucketLength > maxBucketLength) &&
- ! allSameCode &&
- (m_numBuckets < m_size * 15)) {
-
- // This m_bucket was really large; rehash if all elements
- // don't have the same hashcode the number of buckets is
- // reasonable.
-
- // Back off the scale factor as the number of buckets gets
- // large
- float f = 3.0f;
- if (m_numBuckets > 1000000) {
- f = 1.5f;
- } else if (m_numBuckets > 100000) {
- f = 2.0f;
- }
- int newSize = iMax((int)(m_numBuckets * f) + 1, (int)(m_size * f));
- resize(newSize);
- }
-
- // Not found; insert at the head.
- b = code % m_numBuckets;
- m_bucket[b] = Node::create(key, code, m_bucket[b], m_memoryManager);
- ++m_size;
- created = true;
- return m_bucket[b]->entry;
- }
-
- Entry& getCreateEntry(const Key& key) {
- bool ignore;
- return getCreateEntry(key, ignore);
- }
-
-
- /** Returns the current value that key maps to, creating it if necessary.*/
- Value& getCreate(const Key& key) {
- return getCreateEntry(key).value;
- }
-
- /** \param created True if the element was created. */
- Value& getCreate(const Key& key, bool& created) {
- return getCreateEntry(key, created).value;
- }
-
-
- /**
- Returns true if key is in the table.
- */
- bool containsKey(const Key& key) const {
- if (m_numBuckets == 0) {
- return false;
- }
-
- size_t code = HashFunc::hashCode(key);
- size_t b = code % m_numBuckets;
-
- Node* node = m_bucket[b];
-
- while (node != NULL) {
- if ((node->hashCode == code) && EqualsFunc::equals(node->entry.key, key)) {
- return true;
- }
- node = node->next;
- } while (node != NULL);
-
- return false;
- }
-
-
- /**
- Short syntax for get.
- */
- inline Value& operator[](const Key &key) const {
- return get(key);
- }
-
- /**
- Returns an array of all of the keys in the table.
- You can iterate over the keys to get the values.
- @deprecated
- */
- Array<Key> getKeys() const {
- Array<Key> keyArray;
- getKeys(keyArray);
- return keyArray;
- }
-
- void getKeys(Array<Key>& keyArray) const {
- keyArray.resize(0, DONT_SHRINK_UNDERLYING_ARRAY);
- for (size_t i = 0; i < m_numBuckets; i++) {
- Node* node = m_bucket[i];
- while (node != NULL) {
- keyArray.append(node->entry.key);
- node = node->next;
- }
- }
- }
-
- /**
- Calls delete on all of the keys and then clears the table.
- */
- void deleteKeys() {
- for (size_t i = 0; i < m_numBuckets; i++) {
- Node* node = m_bucket[i];
- while (node != NULL) {
- delete node->entry.key;
- node = node->next;
- }
- }
- clear();
- }
-
- /**
- Calls delete on all of the values. This is unsafe--
- do not call unless you know that each value appears
- at most once.
-
- Does not clear the table, so you are left with a table
- of NULL pointers.
- */
- void deleteValues() {
- for (size_t i = 0; i < m_numBuckets; ++i) {
- Node* node = m_bucket[i];
- while (node != NULL) {
- delete node->entry.value;
- node->entry.value = NULL;
- node = node->next;
- }
- }
- }
-};
-
-} // namespace
-
-#ifdef _MSC_VER
-# pragma warning (pop)
-#endif
-
-#endif
diff --git a/externals/g3dlite/G3D/TextInput.h b/externals/g3dlite/G3D/TextInput.h
deleted file mode 100644
index 33eb8c48e53..00000000000
--- a/externals/g3dlite/G3D/TextInput.h
+++ /dev/null
@@ -1,801 +0,0 @@
-/**
- @file TextInput.h
-
- Simple text lexer/tokenizer.
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @cite Based on a lexer written by Aaron Orenstein.
-
- @created 2002-11-27
- @edited 2009-11-24
-
- Copyright 2000-2009, Morgan McGuire.
- All rights reserved.
- */
-
-#ifndef G3D_TextInput_h
-#define G3D_TextInput_h
-
-#include "G3D/platform.h"
-#include "G3D/Array.h"
-#include "G3D/Set.h"
-#include "G3D/ParseError.h"
-#include <string>
-#include <queue>
-#include <ctype.h>
-#include <stdio.h>
-
-namespace G3D {
-
-/**
- For use with TextInput.
- */
-class Token {
-public:
-
- /**
- More detailed type information than Type.
- */
- enum ExtendedType {
- DOUBLE_QUOTED_TYPE,
- SINGLE_QUOTED_TYPE,
- SYMBOL_TYPE,
- FLOATING_POINT_TYPE,
- INTEGER_TYPE,
- BOOLEAN_TYPE,
- LINE_COMMENT_TYPE,
- BLOCK_COMMENT_TYPE,
- NEWLINE_TYPE,
- END_TYPE
- };
-
- /**
- Strings are enclosed in quotes, symbols are not.
- */
- enum Type {
- STRING = DOUBLE_QUOTED_TYPE,
- SYMBOL = SYMBOL_TYPE,
- NUMBER = FLOATING_POINT_TYPE,
- BOOLEAN = BOOLEAN_TYPE,
- COMMENT = LINE_COMMENT_TYPE,
- NEWLINE = NEWLINE_TYPE,
- END = END_TYPE
- };
-
-private:
-
- friend class TextInput;
-
- /**
- Holds the actual value, which might be any type. If a number, it will be
- parsed at runtime.
- */
- std::string _string;
-
- bool _bool;
- int _line;
- int _character;
- Type _type;
- ExtendedType _extendedType;
-
-public:
-
- Token() :
- _string(""),
- _bool(false),
- _line(0),
- _character(0),
- _type(END),
- _extendedType(END_TYPE) {}
-
- Token(Type t, ExtendedType e, const std::string& s, int L, int c)
- : _string(s), _bool(false), _line(L), _character(c), _type(t), _extendedType(e) {}
-
- Token(Type t, ExtendedType e, const std::string& s, bool b, int L, int c)
- : _string(s), _bool(b), _line(L), _character(c), _type(t), _extendedType(e) {}
-
- Type type() const {
- return _type;
- }
-
- ExtendedType extendedType() const {
- return _extendedType;
- }
-
- /**
- The value of a single or double quote string (not including the quotes),
- the name of a symbol, or the exact textual representation of a number as
- parsed from the input.
- */
- const std::string& string() const {
- return _string;
- }
-
- bool boolean() const {
- return _bool;
- }
-
- /**
- Starting line of the input from which this token was parsed. Starts
- at 1.
- */
- int line() const {
- return _line;
- }
-
- /**
- Starting character position in the input line from which this token was
- parsed. Starts at 1.
- */
- int character() const {
- return _character;
- }
-
- /** Return the numeric value for a number type, or zero if this is
- not a number type.
- */
- double number() const;
-};
-
-
-/**
- A simple style tokenizer for reading text files. TextInput handles a
- superset of C++,Java, Matlab, and Bash code text including single
- line comments, block comments, quoted strings with escape sequences,
- and operators. TextInput recognizes several categories of tokens,
- which are separated by white space, quotation marks, or the end of a
- recognized operator:
-
- <ul>
- <li><CODE>Token::SINGLE_QUOTED_TYPE</CODE> string of characters surrounded by single quotes, e.g., 'x', '\\0', 'foo'.
- <li><CODE>Token::DOUBLE_QUOTED_TYPE</CODE> string of characters surrounded by double quotes, e.g., "x", "abc\txyz", "b o b".
- <li><CODE>Token::SYMBOL_TYPE</CODE> legal C++ operators, keywords, and identifiers. e.g., >=, Foo, _X, class, {
- <li><CODE>Token::INTEGER_TYPE</CODE> numbers without decimal places or exponential notation. e.g., 10, 0x17F, 32, 0, -155
- <li><CODE>Token::FLOATING_POINT_TYPE</CODE> numbers with decimal places or exponential notation. e.g., 1e3, -1.2, .4, 0.5
- <li><CODE>Token::BOOLEAN_TYPE</CODE> special symbols like "true" and "false"; the exact details can be configured in TextInput::Settings
- <li><CODE>Token::LINE_COMMENT_TYPE</CODE> (disabled by default); generated for line comments as specified by TextInput::Settings
- <li><CODE>Token::BLOCK_COMMENT_TYPE</CODE> (disabled by default); generated for c-style block comments as specified by TextInput::Settings
- <li><CODE>Token::NEWLINE_TYPE</CODE> (disabled by default); generated for any of "\\r", "\\n" or "\\r\\n"
- </ul>
-
- <P>The special ".." and "..." tokens are always recognized in
- addition to normal C++ operators. Additional tokens can be made
- available by changing the Settings.
-
- Negative numbers are handled specially because of the ambiguity between unary minus and negative numbers--
- see the note on TextInput::read.
-
- TextInput does not have helper functions for types with non-obvious
- formatting, or helpers that would be redundant. Use the serialize
- methods instead for parsing specific types like int, Vector3, and
- Color3.
-
- Inside quoted strings escape sequences are converted. Thus the
- string token for ["a\\nb"] is 'a', followed by a newline, followed by
- 'b'. Outside of quoted strings, escape sequences are not converted,
- so the token sequence for [a\\nb] is symbol 'a', symbol '\\', symbol
- 'nb' (this matches what a C++ parser would do). The exception is
- that a specified TextInput::Settings::otherCommentCharacter preceeded
- by a backslash is assumed to be an escaped comment character and is
- returned as a symbol token instead of being parsed as a comment
- (this is what a LaTex or VRML parser would do).
-
- <B>Examples</B>
-
- <PRE>
- TextInput ti(TextInput::FROM_STRING, "name = \"Max\", height = 6");
-
- Token t;
-
- t = ti.read();
- debugAssert(t.type == Token::SYMBOL);
- debugAssert(t.sval == "name");
-
- ti.read();
- debugAssert(t.type == Token::SYMBOL);
- debugAssert(t.sval == "=");
-
- std::string name = ti.read().sval;
- ti.read();
- </PRE>
-
- <PRE>
- TextInput ti(TextInput::FROM_STRING, "name = \"Max\", height = 6");
- ti.readSymbols("name", "=");
- std::string name = ti.readString();
- ti.readSymbols(",", "height", "=");
- double height = ti. readNumber();
- </PRE>
-
- Assumes that the file is not modified once opened.
- */
-class TextInput {
-public:
-
- /** Tokenizer configuration options. */
- class Settings {
- public:
- /** If true, C-style slash-star marks a multi-line comment.
-
- See generateCommentTokens for rules on how this is applied.
-
- Default is true.
- */
- bool cppBlockComments;
-
- /** If true, // begins a single line comment.
-
- See generateCommentTokens for rules on how this is applied.
-
- Default is true.
- */
- bool cppLineComments;
-
- /** If true, otherCommentCharacter and otherCommentCharacter2
- are used to begin single line comments in the same way
- cppLineComments is.
-
- See generateCommentTokens for rules on how this is applied.
-
- Default is true.
- */
- bool otherLineComments;
-
- /** If true, \\r, \\n, \\t, \\0, \\\\ and other escape sequences inside
- strings are converted to the equivalent C++ escaped character.
- If false, backslashes are treated literally. It is convenient to
- set to false if reading Windows paths, for example, like
- c:\\foo\\bar.
-
- Default is true.
- */
- bool escapeSequencesInStrings;
-
- /** If not '\\0', specifies a character that begins single line
- comments ('#' and '%' are popular choices). This is independent
- of the cppLineComments flag. If the character appears in text with
- a backslash in front of it, it is considered escaped and is not
- treated as a comment character.
-
- Default is '\\0'.
- */
- char otherCommentCharacter;
-
- /** Another (optional) 1-comment character. Useful for files that
- support multiple comment syntaxes. Default is '\\0'.
- */
- char otherCommentCharacter2;
-
- /** If true, comments enabled by cppBlockComments, cppLineComments
- and otherLineComments will generate their respective tokens.
- If false, the same settings will enable parsing and ignoring
- comments
-
- Default is false.
- */
- bool generateCommentTokens;
-
- /** If true, newlines will generate tokens.
- If false, newlines will be discarded as whitespace when parsed
- outside of other tokens.
-
- Default is false.
- */
- bool generateNewlineTokens;
-
- /** If true, "-1" parses as the number -1 instead of the
- symbol "-" followed by the number 1. Default is true.*/
- bool signedNumbers;
-
- /** If true, strings can be marked with single quotes (e.g.,
- 'aaa'). If false, the quote character is parsed as a
- symbol. Default is true. Backquote (`) is always parsed
- as a symbol. */
- bool singleQuotedStrings;
-
- /** The character to use as a single quote. Defaults to "'" (backquote),
- occasionally useful to set to "`" (forward quote) or to "," (comma) for
- reading CSV files. */
- char singleQuoteCharacter;
-
- /** If set to a non-empty string, that string will be used in
- place of the real file name (or in place of a pseudonym
- constructed from the buffer if given FROM_STRING) in
- tokens and exceptions.
-
- Default is empty.
- */
- std::string sourceFileName;
-
-
- /** Added to the line number reported by peekLineNumber and in
- exceptions. Useful for concatenating files that are
- parsed separately. Default is zero. */
- int startingLineNumberOffset;
-
- /**
- Parse -1.#IND00 as the floating point number returned by
- nan(), -1.#INF00 as -inf(), and 1.#INF00 as inf(). Note
- that the C99 standard specifies that a variety of formats
- like "NaN" and "nan" are to be used; these are easier to
- parse yourself and not currently supported by readNumber.
-
- An alternative to specifying msvcSpecials is to read numbers as:
- <pre>
- Token x = t.read();
- Token y = t.peek();
- if ((x.string() == "-1.") &&
- (y.string() == "#INF00") &&
- (y.character() == x.character() + 3) &&
- (y.line() == x.line()) {
- t.read();
- return nan();
- }
- // ... similar cases for inf
- </pre>
-
- If the single-comment character was #, the floating point
- special format overrides the comment and will be parsed
- instead.
-
- If signedNumbers is false msvcSpecials will not be parsed.
-
- Default is true. */
- bool msvcSpecials;
-
- /**
- Parse the following set of useful proof symbols:
-
- =>
- ::>
- <::
- :>
- <:
- |-
- ::=
- :=
- <-
-
- Default is false.
- */
- bool proofSymbols;
-
- /**
- When parsing booleans and msvcSpecials, is case significant?
- Default is {true}
- */
- bool caseSensitive;
-
- /** All symbols that will become the 'true' boolean token. See also caseSensitive.
- Clear this value to disable parsing of true booleans.
-
- Default is {true}.
- */
- Set<std::string> trueSymbols;
-
- /** See trueSymbols. Default is {false}*/
- Set<std::string> falseSymbols;
-
- Settings();
- };
-
-private:
-
- std::deque<Token> stack;
-
- /**
- Characters to be tokenized.
- */
- Array<char> buffer;
-
- /**
- Offset of current character (the next character to consumed) in
- input buffer.
- */
- int currentCharOffset;
-
- /**
- Line number of next character to be consumed from the input buffer. (1
- indicates first line of input.)
-
- Note that this is the line number of the @e next character to be
- consumed from the input, not the line number of the @e last character
- consumed!
- */
- int lineNumber;
-
- /**
- Character number (within the line) of the next character to be consumed
- from the input buffer. (1 indicates first character of the line).
-
- Note that this is the character number of the @e next character to be
- consumed from the input, not the character number of the @e last
- character consumed!
- */
- int charNumber;
-
- /** Configuration options. This includes the file name that will be
- reported in tokens and exceptions. */
- Settings options;
-
- void init();
-
- /**
- Consumes the next character from the input buffer, and returns that
- character. Updates lineNumber and charNumber to reflect the location of
- the next character in the input buffer.
-
- Note: you shouldn't be using the return value of this function in most
- cases. In general, you should peekInputChar() to get the next
- character, determine what to do with it, then consume it with this
- function (or with eatAndPeekInputChar()). Given that usage, in most
- instances you already know what this function would return!
- */
- int eatInputChar();
-
- /**
- Returns the next character from the input buffer, without consuming any
- characters. Can also be used to look deeper into the input buffer.
- Does not modify lineNumber or charNumber.
-
- @param distance Index of the character in the input buffer to peek at,
- relative to the next character. Default is 0, for the next character in
- the input buffer.
- */
- int peekInputChar(int distance = 0);
-
- /**
- Helper function to consume the next character in the input buffer and
- peek at the one following (without consuming it).
- */
- inline int eatAndPeekInputChar() {
- eatInputChar();
- return peekInputChar(0);
- }
-
- /**
- Read the next token, returning an END token if no more input is
- available.
- */
- Token nextToken();
-
- /**
- Helper for nextToken. Appends characters to t._string until the end
- delimiter is reached.
-
- When called, the next character in the input buffer should be first the
- first character after the opening delimiter character.
- */
- void parseQuotedString(unsigned char delimiter, Token& t);
-
-public:
-
- class TokenException : public ParseError {
- public:
- /** Name of file being parsed when exception occurred.
- \deprecated Use filename
- */
- std::string sourceFile;
-
- virtual ~TokenException() {}
-
- protected:
-
- TokenException(
- const std::string& src,
- int ln,
- int ch);
-
- };
-
- /** While parsing a number of the form 1.\#IN?00, ? was
- not 'D' or 'F'. */
- class BadMSVCSpecial : public TokenException {
- public:
-
- BadMSVCSpecial(
- const std::string& src,
- int ln,
- int ch);
- };
-
- /** Thrown by the read methods. */
- class WrongTokenType : public TokenException {
- public:
- Token::Type expected;
- Token::Type actual;
-
- WrongTokenType(
- const std::string& src,
- int ln,
- int ch,
- Token::Type e,
- Token::Type a);
- };
-
- class WrongSymbol : public TokenException {
- public:
- std::string expected;
- std::string actual;
-
- WrongSymbol(
- const std::string& src,
- int ln,
- int ch,
- const std::string& e,
- const std::string& a);
- };
-
-
- /** String read from input did not match expected string. */
- class WrongString : public TokenException {
- public:
- std::string expected;
- std::string actual;
-
- WrongString(
- const std::string& src,
- int ln,
- int ch,
- const std::string& e,
- const std::string& a);
- };
-
- TextInput(const std::string& filename, const Settings& settings = Settings());
-
- enum FS {FROM_STRING};
- /** Creates input directly from a string. The first argument must be
- TextInput::FROM_STRING.
- */
- TextInput(FS fs, const std::string& str, const Settings& settings = Settings());
-
- /** Returns true while there are tokens remaining. */
- bool hasMore();
-
- /** Read the next token (which will be the END token if ! hasMore()).
-
- Signed numbers can be handled in one of two modes. If the option
- TextInput::Settings::signedNumbers is true,
- A '+' or '-' immediately before a number is prepended onto that number and
- if there is intervening whitespace, it is read as a separate symbol.
-
- If TextInput::Settings::signedNumbers is false,
- read() does not distinguish between a plus or minus symbol next
- to a number and a positive/negative number itself. For example, "x - 1" and "x -1"
- will be parsed the same way by read().
-
- In both cases, readNumber() will contract a leading "-" or "+" onto
- a number.
- */
- Token read();
-
- /** Calls read() until the result is not a newline or comment */
- Token readSignificant();
-
- /** Read one token (or possibly two) as a number or throws
- WrongTokenType, and returns the number.
-
- If the first token in the input is a number, it is returned directly.
-
- If TextInput::Settings::signedNumbers is false and the input stream
- contains a '+' or '-' symbol token immediately followed by a number
- token, both tokens will be consumed and a single token will be
- returned by this method.
-
- WrongTokenType will be thrown if one of the input conditions
- described above is not satisfied. When an exception is thrown, no
- tokens are consumed.
- */
- double readNumber();
-
- bool readBoolean();
-
- /** Reads a string token or throws WrongTokenType, and returns the token.
-
- Use this method (rather than readString) if you want the token's
- location as well as its value.
-
- WrongTokenType will be thrown if the next token in the input stream
- is not a string. When an exception is thrown, no tokens are
- consumed.
- */
- Token readStringToken();
-
- /** Like readStringToken, but returns the token's string.
-
- Use this method (rather than readStringToken) if you want the token's
- value but don't really care about its location in the input. Use of
- readStringToken is encouraged for better error reporting.
- */
- std::string readString();
-
- /** Reads a specific string token or throws either WrongTokenType or
- WrongString. If the next token in the input is a string matching @p
- s, it will be consumed.
-
- Use this method if you want to match a specific string from the
- input. In that case, typically error reporting related to the token
- is only going to occur because of a mismatch, so no location
- information is needed by the caller.
-
- WrongTokenType will be thrown if the next token in the input stream
- is not a string. WrongString will be thrown if the next token in the
- input stream is a string but does not match the @p s parameter. When
- an exception is thrown, no tokens are consumed.
- */
- void readString(const std::string& s);
-
- /** Reads a comment token or throws WrongTokenType, and returns the token.
-
- Use this method (rather than readComment) if you want the token's
- location as well as its value.
-
- WrongTokenType will be thrown if the next token in the input stream
- is not a comment. When an exception is thrown, no tokens are
- consumed.
- */
- Token readCommentToken();
-
- /** Like readCommentToken, but returns the token's string.
-
- Use this method (rather than readCommentToken) if you want the token's
- value but don't really care about its location in the input. Use of
- readCommentToken is encouraged for better error reporting.
- */
- std::string readComment();
-
- /** Reads a specific comment token or throws either WrongTokenType or
- WrongString. If the next token in the input is a comment matching @p
- s, it will be consumed.
-
- Use this method if you want to match a specific comment from the
- input. In that case, typically error reporting related to the token
- is only going to occur because of a mismatch, so no location
- information is needed by the caller.
-
- WrongTokenType will be thrown if the next token in the input stream
- is not a comment. WrongString will be thrown if the next token in the
- input stream is a comment but does not match the @p s parameter. When
- an exception is thrown, no tokens are consumed.
- */
- void readComment(const std::string& s);
-
- /** Reads a newline token or throws WrongTokenType, and returns the token.
-
- Use this method (rather than readNewline) if you want the token's
- location as well as its value.
-
- WrongTokenType will be thrown if the next token in the input stream
- is not a newline. When an exception is thrown, no tokens are
- consumed.
- */
- Token readNewlineToken();
-
- /** Like readNewlineToken, but returns the token's string.
-
- Use this method (rather than readNewlineToken) if you want the token's
- value but don't really care about its location in the input. Use of
- readNewlineToken is encouraged for better error reporting.
- */
- std::string readNewline();
-
- /** Reads a specific newline token or throws either WrongTokenType or
- WrongString. If the next token in the input is a newline matching @p
- s, it will be consumed.
-
- Use this method if you want to match a specific newline from the
- input. In that case, typically error reporting related to the token
- is only going to occur because of a mismatch, so no location
- information is needed by the caller.
-
- WrongTokenType will be thrown if the next token in the input stream
- is not a newline. WrongString will be thrown if the next token in the
- input stream is a newlin but does not match the @p s parameter. When
- an exception is thrown, no tokens are consumed.
- */
- void readNewline(const std::string& s);
-
- /** Reads a symbol token or throws WrongTokenType, and returns the token.
-
- Use this method (rather than readSymbol) if you want the token's
- location as well as its value.
-
- WrongTokenType will be thrown if the next token in the input stream
- is not a symbol. When an exception is thrown, no tokens are
- consumed.
- */
- Token readSymbolToken();
-
- /** Like readSymbolToken, but returns the token's string.
-
- Use this method (rather than readSymbolToken) if you want the token's
- value but don't really care about its location in the input. Use of
- readSymbolToken is encouraged for better error reporting.
- */
- std::string readSymbol();
-
- /** Reads a specific symbol token or throws either WrongTokenType or
- WrongSymbol. If the next token in the input is a symbol matching @p
- symbol, it will be consumed.
-
- Use this method if you want to match a specific symbol from the
- input. In that case, typically error reporting related to the token
- is only going to occur because of a mismatch, so no location
- information is needed by the caller.
-
- WrongTokenType will be thrown if the next token in the input stream
- is not a symbol. WrongSymbol will be thrown if the next token in the
- input stream is a symbol but does not match the @p symbol parameter.
- When an exception is thrown, no tokens are consumed.
- */
- void readSymbol(const std::string& symbol);
-
-
- /** Read a series of two specific symbols. See readSymbol. */
- inline void readSymbols(const std::string& s1, const std::string& s2) {
- readSymbol(s1);
- readSymbol(s2);
- }
-
- /** Read a series of three specific symbols. See readSymbol. */
- inline void readSymbols(
- const std::string& s1,
- const std::string& s2,
- const std::string& s3) {
- readSymbol(s1);
- readSymbol(s2);
- readSymbol(s3);
- }
-
- /** Read a series of four specific symbols. See readSymbol. */
- inline void readSymbols(
- const std::string& s1,
- const std::string& s2,
- const std::string& s3,
- const std::string& s4) {
- readSymbol(s1);
- readSymbol(s2);
- readSymbol(s3);
- readSymbol(s4);
- }
-
- /** Return a copy of the next token in the input stream, but don't remove
- it from the input stream.
- */
- Token peek();
-
- /** Returns the line number for the @e next token. See also peek. */
- int peekLineNumber();
-
- /** Returns the character number (relative to the line) for the @e next
- token in the input stream. See also peek.
- */
- int peekCharacterNumber();
-
- /** Take a previously read token and push it back at the front of the
- input stream.
-
- Can be used in the case where more than one token of read-ahead is
- needed (i.e., when peek doesn't suffice).
- */
- void push(const Token& t);
-
- /** Returns the filename from which this input is drawn, or the first few
- characters of the string if created from a string.
- If settings::filename is non-empty that will replace the
- true filename.*/
- const std::string& filename() const;
-};
-
-void deserialize(bool& b, TextInput& ti);
-void deserialize(int& b, TextInput& ti);
-void deserialize(uint8& b, TextInput& ti);
-void deserialize(double& b, TextInput& ti);
-void deserialize(float& b, TextInput& ti);
-void deserialize(std::string& b, TextInput& ti);
-
-} // namespace
-
-#endif
-
diff --git a/externals/g3dlite/G3D/TextOutput.h b/externals/g3dlite/G3D/TextOutput.h
deleted file mode 100644
index 4c22b7d5653..00000000000
--- a/externals/g3dlite/G3D/TextOutput.h
+++ /dev/null
@@ -1,249 +0,0 @@
-/**
- @file TextOutput.h
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @created 2004-06-21
- @edited 2006-10-24
-
- Copyright 2000-2007, Morgan McGuire.
- All rights reserved.
- */
-
-#ifndef G3D_TEXTOUTPUT_H
-#define G3D_TEXTOUTPUT_H
-
-#include "G3D/platform.h"
-#include "G3D/Array.h"
-#include <string>
-
-namespace G3D {
-
-/**
- Convenient formatting of ASCII text written to a file.
- <P>
-
- The core writeString, writeNumber, and writeSymbol methods map to TextInput's
- methods. Number and Symbol each print an additional space that is used to
- separate adjacent tokens.
-
- TextOutput::printf allows arbitrary text to be conveniently dumped
- en-masse. Use [de]serialize(bool, TextOutput) and other overloads to read/write
- primitive types in a standardized manner and
-
- <P>
- When a word-wrap line break occurs, all whitespace between words is replaced
- with a single newline (the newline may be two characters-- see
- G3D::TextOutput::Options::NewlineStyle). Word wrapping occurs against
- the number of columns specified by Options::numColumns, <I>minus</I> the current
- indent level.
-
- Indenting adds the specified number of spaces immediately after a newline.
- If a newline was followed by spaces in the original string, these are added
- to the indent spaces. Indenting <B>will</B> indent blank lines and will leave
- indents after the last newline of a file (if the indent level is non-zero at the end).
-
- <P><B>Serialization/Marshalling</B>
- <DT>Text serialization is accomplished using TextOutput by defining the pair of
- methods:
-
- <PRE>
- void serialize(TextOutput& to) const;
- void deserialize(TextInput& ti);
- </PRE>
-
- See also G3D::TextInput.
-
- <P>
- <B>BETA API</B>
- <DT>This API is subject to change in future versions.
- */
-class TextOutput {
-public:
-
- class Settings {
- public:
- /**
- WRAP_NONE Word wrapping is disabled
- WRAP_WITHOUT_BREAKING Word-wrap, but don't break continuous lines that
- are longer than numColumns (default)
- WRAP_ALWAYS Wrap even if it means breaking a continuous line or
- a quoted string.
-
- Word wrapping is only allowed at whitespaces ('\\n', '\\r', '\\t', ' '); it
- will not occur after commas, punctuation, minus signs, or any other characters
- */
- enum WordWrapMode {WRAP_NONE, WRAP_WITHOUT_BREAKING, WRAP_ALWAYS};
-
- /** Defaults to WRAP_WITHOUT_BREAKING */
- WordWrapMode wordWrap;
-
- /** Is word-wrapping allowed to insert newlines inside double quotes?
- Default: false */
- bool allowWordWrapInsideDoubleQuotes;
-
- /** Number of columns for word wrapping. Default: 8 */
- int numColumns;
-
- /** Number of spaces in each indent. Default: 4 */
- int spacesPerIndent;
-
- /** Style of newline used by word wrapping and by (optional) conversion.
- default: Windows: NEWLINE_WINDOWS, Linux, OS X: NEWLINE_UNIX.
- */
- enum NewlineStyle {NEWLINE_WINDOWS, NEWLINE_UNIX};
-
- NewlineStyle newlineStyle;
-
- /** If true, all newlines are converted to NewlineStyle regardless of
- how they start out. Default: true. */
- bool convertNewlines;
-
- /** Used by writeBoolean */
- std::string trueSymbol;
-
- /** Used by writeBoolean */
- std::string falseSymbol;
-
- Settings() :
- wordWrap(WRAP_WITHOUT_BREAKING),
- allowWordWrapInsideDoubleQuotes(false),
- numColumns(80),
- spacesPerIndent(4),
- convertNewlines(true),
- trueSymbol("true"),
- falseSymbol("false") {
- #ifdef G3D_WIN32
- newlineStyle = NEWLINE_WINDOWS;
- #else
- newlineStyle = NEWLINE_UNIX;
- #endif
- }
- };
-
-private:
-
- /** Used by indentAndAppend to tell when we are writing the
- first character of a new line.
-
- So that push/popIndent work correctly, we cannot indent
- immediately after writing a newline. Instead we must
- indent on writing the first character <B>after</B> that
- newline.
- */
- bool startingNewLine;
-
- /** Number of characters at the end of the buffer since the last newline */
- int currentColumn;
-
- /** True if we have seen an open " and no close ".*/
- bool inDQuote;
-
- /** Empty if there is none */
- std::string filename;
-
- Array<char> data;
-
- Settings option;
-
- /** Number of indents to prepend before each line. Always set using setIndentLevel.*/
- int indentLevel;
-
- void setIndentLevel(int i);
-
- /** Actual number of spaces to indent. */
- int indentSpaces;
-
- /** the newline character(s) */
- std::string newline;
-
- void setOptions(const Settings& _opt);
-
- /** Converts to the desired newlines. Called from vprintf */
- void convertNewlines(const std::string& in, std::string& out);
-
- /** Called from vprintf */
- void wordWrapIndentAppend(const std::string& str);
-
- /** Appends the character to data, indenting whenever a newline is encountered.
- Called from wordWrapIndentAppend */
- void indentAppend(char c);
-
-public:
-
- explicit TextOutput(const std::string& filename, const Settings& options = Settings());
-
- /** Constructs a text output that can later be commited to a string instead of a file.*/
- explicit TextOutput(const Settings& options = Settings());
-
- /** Commit to the filename specified on the constructor.
- <B>Not</B> called from the destructor; you must call
- it yourself.
- @param flush If true (default) the file is ready for reading when the method returns, otherwise
- the method returns immediately and writes the file in the background.*/
- void commit(bool flush = true);
-
- /** Commits to this string */
- void commitString(std::string& string);
-
- /** Increase indent level by 1 */
- void pushIndent();
-
- void popIndent();
-
- /** Produces a new string that contains the output */
- std::string commitString();
-
- /** Writes a quoted string. Special characters in the string (e.g., \\, \\t, \\n) are escaped so that
- TextInput will produce the identical string on reading.*/
- void writeString(const std::string& string);
-
- void writeBoolean(bool b);
-
- void writeNumber(double n);
-
- void writeNumber(int n);
-
- void writeNewline();
- void writeNewlines(int numLines);
-
- /** The symbol is written without quotes. Symbols are required to begin with a
- letter or underscore and contain only letters, underscores, and numbers
- or be a C++ symbol (e.g. "{", "(", "++", etc.)
- so that they may be properly parsed by TextInput::readSymbol. Symbols are
- printed with a trailing space.*/
- void writeSymbol(const std::string& string);
-
- /** Convenient idiom for writing multiple symbols in a row, e.g.
- writeSymbols("name", "="); The empty symbols are not written.
- */
- void writeSymbols(
- const std::string& a,
- const std::string& b = "",
- const std::string& c = "",
- const std::string& d = "",
- const std::string& e = "",
- const std::string& f = "");
-
- /** Normal printf conventions. Note that the output will be reformatted
- for word-wrapping and newlines */
- void __cdecl printf(const char* fmt, ...)
- G3D_CHECK_PRINTF_METHOD_ARGS;
-
- // Can't pass by reference because that confuses va_start
- void __cdecl printf(const std::string fmt, ...);
- void __cdecl vprintf(const char* fmt, va_list argPtr)
- G3D_CHECK_VPRINTF_METHOD_ARGS;
-};
-
-// Primitive serializers
-void serialize(const bool& b, TextOutput& to);
-void serialize(const int& b, TextOutput& to);
-void serialize(const uint8& b, TextOutput& to);
-void serialize(const double& b, TextOutput& to);
-void serialize(const float& b, TextOutput& to);
-void serialize(const std::string& b, TextOutput& to);
-void serialize(const char* b, TextOutput& to);
-
-}
-
-#endif
diff --git a/externals/g3dlite/G3D/ThreadSet.h b/externals/g3dlite/G3D/ThreadSet.h
deleted file mode 100644
index 121f1415a1d..00000000000
--- a/externals/g3dlite/G3D/ThreadSet.h
+++ /dev/null
@@ -1,87 +0,0 @@
-#ifndef G3D_THREADSET_H
-#define G3D_THREADSET_H
-
-#include "G3D/platform.h"
-#include "G3D/Array.h"
-#include "G3D/ReferenceCount.h"
-#include "G3D/GThread.h"
-#include "G3D/GMutex.h"
-
-namespace G3D {
-
-/** Manages a set of threads. All methods are threadsafe except for
- the iterator begin/end.
-
- @beta*/
-class ThreadSet : public ReferenceCountedObject {
-public:
- /** Intended to allow future use with a template parameter.*/
- typedef GThread Thread;
-
- typedef ReferenceCountedPointer<Thread> ThreadRef;
- typedef ReferenceCountedPointer<ThreadSet> Ref;
- typedef Array<ThreadRef>::Iterator Iterator;
- typedef Array<ThreadRef>::ConstIterator ConstIterator;
-
-private:
-
- /** Protects m_thread */
- GMutex m_lock;
-
- /** Threads in the set */
- Array<ThreadRef> m_thread;
-
-public:
-
- /** Total number of threads (some of which may be completed). */
- int size() const;
-
- /** Number of threads that have been started */
- int numStarted() const;
-
- /** Start all threads that are not currently started.
-
- @param lastThreadBehavior If USE_CURRENT_THREAD, takes the last unstarted thread and executes it manually on
- the current thread. This helps to take full advantage of the machine when
- running a large number of jobs and avoids the overhead of a thread start for single-thread groups.
- Note that this forces start() to block until
- that thread is complete.
- */
- void start(GThread::SpawnBehavior lastThreadBehavior = GThread::USE_NEW_THREAD) const;
-
- /** Terminate all threads that are currently started */
- void terminate() const;
-
- /** Waits until all started threads have completed. */
- void waitForCompletion() const;
-
- /** Remove all (not stopping them) */
- void clear();
-
- /** Removes completed threads and returns the new size.*/
- int removeCompleted();
-
- /** Inserts a new thread, if it is not already present, and
- returns the new number of threads.*/
- int insert(const ThreadRef& t);
-
- /** Removes a thread. Returns true if the thread was present and
- removed. */
- bool remove(const ThreadRef& t);
-
- bool contains(const ThreadRef& t) const;
-
- /** It is an error to mutate the ThreadSet while iterating through it. */
- Iterator begin();
-
- Iterator end();
-
- ConstIterator begin() const;
-
- ConstIterator end() const;
-};
-
-
-} // namespace G3D
-
-#endif
diff --git a/externals/g3dlite/G3D/Triangle.h b/externals/g3dlite/G3D/Triangle.h
deleted file mode 100644
index 590dbaad946..00000000000
--- a/externals/g3dlite/G3D/Triangle.h
+++ /dev/null
@@ -1,160 +0,0 @@
-/**
- @file Triangle.h
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2003-04-05
- @edited 2008-10-06
-
- @cite Random point method by Greg Turk, Generating random points in triangles. In A. S. Glassner, ed., Graphics Gems, pp. 24-28. Academic Press, 1990
-
- Copyright 2000-2009, Morgan McGuire.
- All rights reserved.
- */
-
-#ifndef G3D_TRIANGLE_H
-#define G3D_TRIANGLE_H
-
-#include "G3D/platform.h"
-#include "G3D/g3dmath.h"
-#include "G3D/Vector3.h"
-#include "G3D/Plane.h"
-#include "G3D/BoundsTrait.h"
-#include "G3D/debugAssert.h"
-#include <string>
-
-namespace G3D {
-
-/**
- A generic triangle representation. This should not be used
- as the underlying triangle for creating models; it is intended
- for providing fast property queries but requires a lot of
- storage and is mostly immutable.
- */
-class Triangle {
-private:
- friend class CollisionDetection;
- friend class Ray;
-
- Vector3 _vertex[3];
-
- /** edgeDirection[i] is the normalized vector v[i+1] - v[i] */
- Vector3 edgeDirection[3];
- float edgeMagnitude[3];
- Plane _plane;
- Vector3::Axis _primaryAxis;
-
- /** vertex[1] - vertex[0] */
- Vector3 _edge01;
-
- /** vertex[2] - vertex[0] */
- Vector3 _edge02;
-
- float _area;
-
- void init(const Vector3& v0, const Vector3& v1, const Vector3& v2);
-
-public:
-
- Triangle(class BinaryInput& b);
- void serialize(class BinaryOutput& b);
- void deserialize(class BinaryInput& b);
-
- Triangle();
-
- Triangle(const Vector3& v0, const Vector3& v1, const Vector3& v2);
-
- ~Triangle();
-
- /** 0, 1, or 2 */
- inline const Vector3& vertex(int n) const {
- debugAssert((n >= 0) && (n < 3));
- return _vertex[n];
- }
-
- /** vertex[1] - vertex[0] */
- inline const Vector3& edge01() const {
- return _edge01;
- }
-
- /** vertex[2] - vertex[0] */
- inline const Vector3& edge02() const {
- return _edge02;
- }
-
- float area() const;
-
- Vector3::Axis primaryAxis() const {
- return _primaryAxis;
- }
-
- const Vector3& normal() const;
-
- /** Barycenter */
- Vector3 center() const;
-
- const Plane& plane() const;
-
- /** Returns a random point in the triangle. */
- Vector3 randomPoint() const;
-
- inline void getRandomSurfacePoint
- (Vector3& P,
- Vector3& N = Vector3::ignore()) const {
- P = randomPoint();
- N = normal();
- }
-
- /**
- For two triangles to be equal they must have
- the same vertices <I>in the same order</I>.
- That is, vertex[0] == vertex[0], etc.
- */
- inline bool operator==(const Triangle& other) const {
- for (int i = 0; i < 3; ++i) {
- if (_vertex[i] != other._vertex[i]) {
- return false;
- }
- }
-
- return true;
- }
-
- inline size_t hashCode() const {
- return
- _vertex[0].hashCode() +
- (_vertex[1].hashCode() >> 2) +
- (_vertex[2].hashCode() >> 3);
- }
-
- void getBounds(class AABox&) const;
-
- /**
- @brief Intersect the ray at distance less than @a distance.
-
- @param distance Set to the maximum distance (can be G3D::inf())
- to search for an intersection. On return, this is the smaller
- of the distance to the intersection, if one exists, and the original
- value.
-
- @param baryCoord If a triangle is hit before @a distance, a
- the barycentric coordinates of the hit location on the triangle.
- Otherwise, unmodified.
-
- @return True if there was an intersection before the original distance.
- */
- bool intersect(const class Ray& ray, float& distance, float baryCoord[3]) const;
-};
-
-} // namespace G3D
-
-template <> struct HashTrait<G3D::Triangle> {
- static size_t hashCode(const G3D::Triangle& key) { return key.hashCode(); }
-};
-
-
-template<> struct BoundsTrait<class G3D::Triangle> {
- static void getBounds(const G3D::Triangle& t, G3D::AABox& out) { t.getBounds(out); }
-};
-
-#endif
diff --git a/externals/g3dlite/G3D/UprightFrame.h b/externals/g3dlite/G3D/UprightFrame.h
deleted file mode 100644
index ad5157cb14b..00000000000
--- a/externals/g3dlite/G3D/UprightFrame.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/**
- @file UprightFrame.h
-
- @author Morgan McGuire, http://graphics.cs.williams.edu
- */
-
-#ifndef G3D_UPRIGHTFRAME_H
-#define G3D_UPRIGHTFRAME_H
-
-#include "G3D/platform.h"
-#include "G3D/Spline.h"
-#include "G3D/Vector3.h"
-#include "G3D/CoordinateFrame.h"
-
-namespace G3D {
-
-/**
- Coordinate frame expressed in Euler angles.
- Unlike a G3D::Quat, UprightFrame always keeps the reference frame from rolling about its own z axis.
- Particularly useful for cameras.
-
- @sa G3D::CoordinateFrame, G3D::Matrix4, G3D::PhysicsFrame, G3D::UprightSpline, G3D::UprightSplineManipulator
- */
-class UprightFrame {
-public:
-
- Vector3 translation;
-
- /** -pi/2 < pitch < pi/2 in radians about the X-axis */
- float pitch;
-
- /** In radians about the Y-axis */
- float yaw;
-
- inline UprightFrame(const Vector3& t = Vector3::zero(), float p = 0, float y = 0)
- : translation(t), pitch(p), yaw(y) {}
-
- UprightFrame(const CoordinateFrame& cframe);
-
- CoordinateFrame toCoordinateFrame() const;
-
- /** Supports implicit cast to CoordinateFrame */
- inline operator CoordinateFrame() const {
- return toCoordinateFrame();
- }
-
- /** Required for use with spline */
- UprightFrame operator+(const UprightFrame& other) const;
-
- /** Required for use with spline */
- UprightFrame operator*(const float k) const;
-
- /**
- Unwraps the yaw values in the elements of the array such that
- they still represent the same angles but strictly increase/decrease
- without wrapping about zero. For use with Spline<UprightFrame>
- */
- static void unwrapYaw(UprightFrame* a, int N);
-
- void serialize(class BinaryOutput& b) const;
- void deserialize(class BinaryInput& b);
-};
-
-/** Shortest-path linear velocity spline for camera positions. Always keeps the camera from rolling.
-@sa G3D::UprightSplineManipulator, G3D::UprightFrame
-*/
-class UprightSpline : public Spline<UprightFrame> {
-protected:
-
- virtual void ensureShortestPath(UprightFrame* A, int N) const {
- UprightFrame::unwrapYaw(A, N);
- }
-
-public:
-
- void serialize(class BinaryOutput& b) const;
- void deserialize(class BinaryInput& b);
-
-};
-
-}
-
-#endif
diff --git a/externals/g3dlite/G3D/Vector2.h b/externals/g3dlite/G3D/Vector2.h
deleted file mode 100644
index dba7353785e..00000000000
--- a/externals/g3dlite/G3D/Vector2.h
+++ /dev/null
@@ -1,454 +0,0 @@
-/**
- @file Vector2.h
-
- 2D vector class
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2001-06-02
- @edited 2008-11-30
-
- Copyright 2000-2009, Morgan McGuire.
- All rights reserved.
-*/
-
-#ifndef G3D_VECTOR2_H
-#define G3D_VECTOR2_H
-
-#include <string>
-
-#include "G3D/platform.h"
-#include "G3D/g3dmath.h"
-#include "G3D/Table.h"
-#include "G3D/HashTrait.h"
-#include "G3D/Vector2int16.h"
-#include "G3D/Random.h"
-
-namespace G3D {
-
-class Vector2;
-class Vector3;
-class Vector4;
-class Any;
-
-/**
- Do not subclass-- this implementation makes assumptions about the
- memory layout.
- */
-class Vector2 {
-private:
- // Hidden operators
- bool operator<(const Vector2&) const;
- bool operator>(const Vector2&) const;
- bool operator<=(const Vector2&) const;
- bool operator>=(const Vector2&) const;
-
-public:
- float x;
- float y;
-
- /** \param any Must either Vector2(#, #) or Vector2 {x = #, y = #}*/
- Vector2(const Any& any);
-
- /** Converts the Vector2 to an Any. */
- operator Any() const;
-
- /** Creates the zero vector */
- Vector2();
- Vector2(class TextInput& t);
- Vector2(class BinaryInput& b);
- Vector2(float x, float y);
- Vector2(float coordinate[2]);
- Vector2(double coordinate[2]);
- Vector2(const Vector2& other);
- Vector2(const Vector2int16& other);
-
- void serialize(class BinaryOutput& b) const;
- void deserialize(class BinaryInput& b);
-
- void serialize(class TextOutput& t) const;
- void deserialize(class TextInput& t);
-
- float& operator[](int i);
- const float& operator[](int i) const;
-
- // assignment and comparison
- Vector2& operator=(const Vector2& other);
- bool operator==(const Vector2& other) const;
- bool operator!=(const Vector2& other) const;
- size_t hashCode() const;
- bool fuzzyEq(const Vector2& other) const;
- bool fuzzyNe(const Vector2& other) const;
-
- /** Returns true if this vector has finite length */
- bool isFinite() const;
-
- /** Returns true if this vector has length == 0 */
- bool isZero() const;
-
- /** Returns true if this vector has length == 1 */
- bool isUnit() const;
-
- // arithmetic operations
- Vector2 operator+(const Vector2& v) const;
- Vector2 operator-(const Vector2& v) const;
- Vector2 operator*(float s) const;
-
- /** Array (pointwise) multiplication */
- Vector2 operator*(const Vector2& v) const;
-
- /** Array division */
- Vector2 operator/(const Vector2& v) const;
- Vector2 operator/(float s) const;
-
- /** Unary minus */
- Vector2 operator-() const;
-
- /** x + y */
- inline float sum() const {
- return x + y;
- }
-
- /**
- Linear interpolation
- */
- inline Vector2 lerp(const Vector2& v, float alpha) const {
- return (*this) + (v - *this) * alpha;
- }
-
- inline Vector2 clamp(const Vector2& low, const Vector2& high) const {
- return Vector2(
- G3D::clamp(x, low.x, high.x),
- G3D::clamp(y, low.y, high.y));
- }
-
- inline Vector2 clamp(float low, float high) const {
- return Vector2(
- (float)G3D::clamp(x, low, high),
- (float)G3D::clamp(y, low, high));
- }
-
- // arithmetic updates
- Vector2& operator+=(const Vector2&);
- Vector2& operator-=(const Vector2&);
- Vector2& operator*=(float);
- Vector2& operator/=(float);
- Vector2& operator*=(const Vector2&);
- Vector2& operator/=(const Vector2&);
-
- // vector operations
-
- /** */
- float length() const;
-
- /** Returns a unit-length vector */
- Vector2 direction() const;
-
- /**
- Potentially less accurate but faster than direction().
- Only works if System::hasSSE is true.
- */
- Vector2 fastDirection() const {
- return direction();
- }
-
- float squaredLength() const;
- float dot(const Vector2& s) const;
-
- /**
- Make this vector have unit length and return the old length.
- If the vector length was less than tolerance, do not normalize.
- */
- float unitize(float fTolerance = 1e-06);
-
- Vector2 min(const Vector2& v) const;
- Vector2 max(const Vector2& v) const;
-
- /** Uniformly distributed random vector on the unit sphere */
- static Vector2 random(Random& r = Random::common());
-
- // Special values.
- // Intentionally not inlined: see Matrix3::identity() for details.
- static const Vector2& zero();
- static const Vector2& one();
- static const Vector2& unitX();
- static const Vector2& unitY();
- static const Vector2& inf();
- static const Vector2& nan();
- /** smallest (most negative) representable vector */
- static const Vector2& minFinite();
- /** Largest representable vector */
- static const Vector2& maxFinite();
-
- std::string toString() const;
-
- // 2-char swizzles
-
- Vector2 xx() const;
- Vector2 yx() const;
- Vector2 xy() const;
- Vector2 yy() const;
-
- // 3-char swizzles
-
- Vector3 xxx() const;
- Vector3 yxx() const;
- Vector3 xyx() const;
- Vector3 yyx() const;
- Vector3 xxy() const;
- Vector3 yxy() const;
- Vector3 xyy() const;
- Vector3 yyy() const;
-
- // 4-char swizzles
-
- Vector4 xxxx() const;
- Vector4 yxxx() const;
- Vector4 xyxx() const;
- Vector4 yyxx() const;
- Vector4 xxyx() const;
- Vector4 yxyx() const;
- Vector4 xyyx() const;
- Vector4 yyyx() const;
- Vector4 xxxy() const;
- Vector4 yxxy() const;
- Vector4 xyxy() const;
- Vector4 yyxy() const;
- Vector4 xxyy() const;
- Vector4 yxyy() const;
- Vector4 xyyy() const;
- Vector4 yyyy() const;
-
-};
-
-inline Vector2 operator*(double s, const Vector2& v) {
- return v * (float)s;
-}
-
-inline Vector2 operator*(float s, const Vector2& v) {
- return v * s;
-}
-
-inline Vector2 operator*(int s, const Vector2& v) {
- return v * (float)s;
-}
-
-
-inline Vector2::Vector2 () : x(0.0f), y(0.0f) {
-}
-
-
-inline Vector2::Vector2(float _x, float _y) : x(_x), y(_y) {
-}
-
-
-inline Vector2::Vector2 (float afCoordinate[2]) {
- x = afCoordinate[0];
- y = afCoordinate[1];
-}
-
-
-
-inline Vector2::Vector2 (double afCoordinate[2]) {
- x = (float)afCoordinate[0];
- y = (float)afCoordinate[1];
-}
-
-
-inline Vector2::Vector2 (const Vector2& rkVector) {
- x = rkVector.x;
- y = rkVector.y;
-}
-
-
-inline Vector2::Vector2 (const Vector2int16& v) : x(v.x), y(v.y) {
-}
-
-
-inline float& Vector2::operator[] (int i) {
- return ((float*)this)[i];
-}
-
-
-inline const float& Vector2::operator[] (int i) const {
- return ((float*)this)[i];
-}
-
-
-inline Vector2& Vector2::operator= (const Vector2& rkVector) {
- x = rkVector.x;
- y = rkVector.y;
- return *this;
-}
-
-
-inline bool Vector2::operator== (const Vector2& rkVector) const {
- return ( x == rkVector.x && y == rkVector.y);
-}
-
-
-inline bool Vector2::operator!= (const Vector2& rkVector) const {
- return ( x != rkVector.x || y != rkVector.y);
-}
-
-
-inline Vector2 Vector2::operator+ (const Vector2& rkVector) const {
- return Vector2(x + rkVector.x, y + rkVector.y);
-}
-
-
-inline Vector2 Vector2::operator- (const Vector2& rkVector) const {
- return Vector2(x - rkVector.x, y - rkVector.y);
-}
-
-
-inline Vector2 Vector2::operator* (float fScalar) const {
- return Vector2(fScalar*x, fScalar*y);
-}
-
-
-
-inline Vector2 Vector2::operator- () const {
- return Vector2( -x, -y);
-}
-
-
-
-inline Vector2& Vector2::operator+= (const Vector2& rkVector) {
- x += rkVector.x;
- y += rkVector.y;
- return *this;
-}
-
-
-
-inline Vector2& Vector2::operator-= (const Vector2& rkVector) {
- x -= rkVector.x;
- y -= rkVector.y;
- return *this;
-}
-
-
-
-inline Vector2& Vector2::operator*= (float fScalar) {
- x *= fScalar;
- y *= fScalar;
- return *this;
-}
-
-
-
-
-inline Vector2& Vector2::operator*= (const Vector2& rkVector) {
- x *= rkVector.x;
- y *= rkVector.y;
- return *this;
-}
-
-
-
-inline Vector2& Vector2::operator/= (const Vector2& rkVector) {
- x /= rkVector.x;
- y /= rkVector.y;
- return *this;
-}
-
-
-inline Vector2 Vector2::operator* (const Vector2& rkVector) const {
- return Vector2(x * rkVector.x, y * rkVector.y);
-}
-
-
-
-inline Vector2 Vector2::operator/ (const Vector2& rkVector) const {
- return Vector2(x / rkVector.x, y / rkVector.y);
-}
-
-
-inline float Vector2::squaredLength () const {
- return x*x + y*y;
-}
-
-
-inline float Vector2::length () const {
- return sqrtf(x*x + y*y);
-}
-
-
-inline Vector2 Vector2::direction () const {
- float lenSquared = x * x + y * y;
-
- if (lenSquared != 1.0f) {
- return *this / sqrtf(lenSquared);
- } else {
- return *this;
- }
-}
-
-
-
-inline float Vector2::dot (const Vector2& rkVector) const {
- return x*rkVector.x + y*rkVector.y;
-}
-
-
-
-inline Vector2 Vector2::min(const Vector2 &v) const {
- return Vector2(G3D::min(v.x, x), G3D::min(v.y, y));
-}
-
-
-
-inline Vector2 Vector2::max(const Vector2 &v) const {
- return Vector2(G3D::max(v.x, x), G3D::max(v.y, y));
-}
-
-
-
-inline bool Vector2::fuzzyEq(const Vector2& other) const {
- return G3D::fuzzyEq((*this - other).squaredLength(), 0);
-}
-
-
-
-inline bool Vector2::fuzzyNe(const Vector2& other) const {
- return G3D::fuzzyNe((*this - other).squaredLength(), 0);
-}
-
-
-
-inline bool Vector2::isFinite() const {
- return G3D::isFinite(x) && G3D::isFinite(y);
-}
-
-
-
-inline bool Vector2::isZero() const {
- return (x == 0.0f) && (y == 0.0f);
-}
-
-
-
-inline bool Vector2::isUnit() const {
- return squaredLength() == 1.0f;
-}
-
-} // namespace G3D
-
-template <>
-struct HashTrait<G3D::Vector2> {
- static size_t hashCode(const G3D::Vector2& key) {
- return key.hashCode();
- }
-};
-
-
-// Intentionally outside namespace to avoid operator overloading confusion
-inline G3D::Vector2 operator*(double s, const G3D::Vector2& v) {
- return v * (float)s;
-}
-inline G3D::Vector2 operator*(int s, const G3D::Vector2& v) {
- return v * (float)s;
-}
-
-#endif
diff --git a/externals/g3dlite/G3D/Vector2.inl b/externals/g3dlite/G3D/Vector2.inl
deleted file mode 100644
index 4f7c55a39cf..00000000000
--- a/externals/g3dlite/G3D/Vector2.inl
+++ /dev/null
@@ -1,18 +0,0 @@
-/**
- @file Vector2.inl
-
- @maintainer Morgan McGuire, matrix@graphics3d.com
- @cite Portions by Laura Wollstadt, graphics3d.com
-
- @cite Portions based on Dave Eberly'x Magic Software Library
- at http://www.magic-software.com
-
- @created 2001-06-02
- @edited 2006-01-14
-
- Copyright 2000-2006, Morgan McGuire.
- All rights reserved.
- */
-
-}
-
diff --git a/externals/g3dlite/G3D/Vector2int16.h b/externals/g3dlite/G3D/Vector2int16.h
deleted file mode 100644
index ba72266d75a..00000000000
--- a/externals/g3dlite/G3D/Vector2int16.h
+++ /dev/null
@@ -1,127 +0,0 @@
-/**
- @file Vector2int16.h
-
- @maintainer Morgan McGuire, matrix@brown.edu
-
- @created 2003-08-09
- @edited 2004-01-03
-
- Copyright 2000-2006, Morgan McGuire.
- All rights reserved.
- */
-
-#ifndef VECTOR2INT16_H
-#define VECTOR2INT16_H
-
-#include "G3D/platform.h"
-#include "G3D/g3dmath.h"
-#include "G3D/HashTrait.h"
-
-namespace G3D {
-
-/**
- \class Vector2int16
- A Vector2 that packs its fields into uint16s.
- */
-G3D_BEGIN_PACKED_CLASS(2)
-class Vector2int16 {
-private:
- // Hidden operators
- bool operator<(const Vector2int16&) const;
- bool operator>(const Vector2int16&) const;
- bool operator<=(const Vector2int16&) const;
- bool operator>=(const Vector2int16&) const;
-
-public:
- G3D::int16 x;
- G3D::int16 y;
-
- Vector2int16() : x(0), y(0) {}
- Vector2int16(G3D::int16 _x, G3D::int16 _y) : x(_x), y(_y){}
- Vector2int16(const class Vector2& v);
- Vector2int16(class BinaryInput& bi);
-
- inline G3D::int16& operator[] (int i) {
- debugAssert(((unsigned int)i) <= 1);
- return ((G3D::int16*)this)[i];
- }
-
- inline const G3D::int16& operator[] (int i) const {
- debugAssert(((unsigned int)i) <= 1);
- return ((G3D::int16*)this)[i];
- }
-
- inline Vector2int16 operator+(const Vector2int16& other) const {
- return Vector2int16(x + other.x, y + other.y);
- }
-
- inline Vector2int16 operator-(const Vector2int16& other) const {
- return Vector2int16(x - other.x, y - other.y);
- }
-
- inline Vector2int16 operator*(const Vector2int16& other) const {
- return Vector2int16(x * other.x, y * other.y);
- }
-
- inline Vector2int16 operator*(const int s) const {
- return Vector2int16(x * s, y * s);
- }
-
- inline Vector2int16& operator+=(const Vector2int16& other) {
- x += other.x;
- y += other.y;
- return *this;
- }
-
- /** Shifts both x and y */
- inline Vector2int16 operator>>(const int s) const {
- return Vector2int16(x >> s, y >> s);
- }
-
- /** Shifts both x and y */
- inline Vector2int16 operator<<(const int s) const {
- return Vector2int16(x << s, y << s);
- }
-
- inline Vector2int16& operator-=(const Vector2int16& other) {
- x -= other.x;
- y -= other.y;
- return *this;
- }
-
- inline Vector2int16& operator*=(const Vector2int16& other) {
- x *= other.x;
- y *= other.y;
- return *this;
- }
-
- Vector2int16 clamp(const Vector2int16& lo, const Vector2int16& hi);
-
- inline bool operator== (const Vector2int16& rkVector) const {
- return ((int32*)this)[0] == ((int32*)&rkVector)[0];
- }
-
- inline bool operator!= (const Vector2int16& rkVector) const {
- return ((int32*)this)[0] != ((int32*)&rkVector)[0];
- }
-
- Vector2int16 max(const Vector2int16& v) const {
- return Vector2int16(iMax(x, v.x), iMax(y, v.y));
- }
-
- Vector2int16 min(const Vector2int16& v) const {
- return Vector2int16(iMin(x, v.x), iMin(y, v.y));
- }
-
- void serialize(class BinaryOutput& bo) const;
- void deserialize(class BinaryInput& bi);
-}
-G3D_END_PACKED_CLASS(2)
-
-}
-
-template<> struct HashTrait<G3D::Vector2int16> {
- static size_t hashCode(const G3D::Vector2int16& key) { return static_cast<size_t>(key.x + ((int)key.y << 16)); }
-};
-
-#endif
diff --git a/externals/g3dlite/G3D/Vector3.h b/externals/g3dlite/G3D/Vector3.h
deleted file mode 100644
index 4825efb9985..00000000000
--- a/externals/g3dlite/G3D/Vector3.h
+++ /dev/null
@@ -1,798 +0,0 @@
-/**
- @file Vector3.h
-
- 3D vector class
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2001-06-02
- @edited 2009-11-01
- Copyright 2000-2009, Morgan McGuire.
- All rights reserved.
- */
-
-#ifndef G3D_Vector3_h
-#define G3D_Vector3_h
-
-#include "G3D/platform.h"
-#include "G3D/g3dmath.h"
-#include "G3D/Random.h"
-#include "G3D/Vector2.h"
-#include "G3D/Table.h"
-#include "G3D/HashTrait.h"
-#include "G3D/PositionTrait.h"
-#include "G3D/Vector2.h"
-#include <iostream>
-#include <string>
-
-namespace G3D {
-
-class Vector2;
-class Vector4;
-class Vector4int8;
-class Vector3int32;
-class Any;
-
-/**
- <B>Swizzles</B>
- Vector classes have swizzle operators, e.g. <CODE>v.xy()</CODE>, that
- allow selection of arbitrary sub-fields. These cannot be used as write
- masks. Examples
-
- <PRE>
-Vector3 v(1, 2, 3);
-Vector3 j;
-Vector2 b;
-
-b = v.xz();
-j = b.xx();
-</PRE>
-
-
- <B>Warning</B>
-
- Do not subclass-- this implementation makes assumptions about the
- memory layout.
- */
-class Vector3 {
-public:
-
- // coordinates
- float x, y, z;
-
-private:
-
- // Hidden operators
- bool operator<(const Vector3&) const;
- bool operator>(const Vector3&) const;
- bool operator<=(const Vector3&) const;
- bool operator>=(const Vector3&) const;
-
-public:
- /** Initializes to zero */
- Vector3();
-
- /** \param any Must either Vector3(#, #, #) or Vector3 {x = #, y = #, z = #}*/
- Vector3(const Any& any);
-
- /** Converts the Vector3 to an Any. */
- operator Any() const;
-
- /** Divides by 127 */
- Vector3(const Vector4int8&);
- Vector3(const class Vector3int32& v);
- explicit Vector3(class BinaryInput& b);
- Vector3(float _x, float _y, float _z);
- explicit Vector3(const class Vector2& v, float _z);
- explicit Vector3(float coordinate[3]);
- explicit Vector3(double coordinate[3]);
- Vector3(const class Vector3int16& v);
- explicit Vector3(class TextInput& t);
- explicit Vector3(const class Color3& c);
-
- /** Format is three float32's */
- void serialize(class BinaryOutput& b) const;
- void deserialize(class BinaryInput& b);
-
- /** Format is "(%f, %f, %f)" */
- void serialize(class TextOutput& t) const;
- void deserialize(class TextInput& t);
-
- // access vector V as V[0] = V.x, V[1] = V.y, V[2] = V.z
- //
- // WARNING. These member functions rely on
- // (1) Vector3 not having virtual functions
- // (2) the data packed in a 3*sizeof(float) memory block
- const float& __fastcall operator[] (int i) const;
- float& operator[] (int i);
-
- enum Axis {X_AXIS=0, Y_AXIS=1, Z_AXIS=2, DETECT_AXIS=-1};
-
- /**
- Returns the largest dimension. Particularly convenient for determining
- which plane to project a triangle onto for point-in-polygon tests.
- */
- Axis primaryAxis() const;
-
- // assignment and comparison
- Vector3& __fastcall operator= (const Vector3& rkVector);
- bool operator== (const Vector3& rkVector) const;
- bool operator!= (const Vector3& rkVector) const;
- size_t hashCode() const;
- bool fuzzyEq(const Vector3& other) const;
- bool fuzzyNe(const Vector3& other) const;
-
- /** Returns true if this vector has finite length. */
- bool isFinite() const;
-
- /** Returns true if this vector has length ~= 0 */
- bool isZero() const;
-
- /** Returns true if this vector has length ~= 1 */
- bool isUnit() const;
-
- // arithmetic operations
- Vector3 __fastcall operator+ (const Vector3& v) const;
- Vector3 __fastcall operator- (const Vector3& v) const;
- Vector3 __fastcall operator* (float s) const;
- inline Vector3 __fastcall operator/ (float s) const {
- return *this * (1.0f / s);
- }
- Vector3 __fastcall operator* (const Vector3& v) const;
- Vector3 __fastcall operator/ (const Vector3& v) const;
- Vector3 __fastcall operator- () const;
-
- // arithmetic updates
- Vector3& __fastcall operator+= (const Vector3& v);
- Vector3& __fastcall operator-= (const Vector3& v);
- Vector3& __fastcall operator*= (float s);
- inline Vector3& __fastcall operator/= (float s) {
- return (*this *= (1.0f / s));
- }
- Vector3& __fastcall operator*= (const Vector3& v);
- Vector3& __fastcall operator/= (const Vector3& v);
-
- /** Same as magnitude */
- float length() const;
-
- float magnitude() const;
-
- /**
- The result is a nan vector if the length is almost zero.
- */
- Vector3 direction() const;
-
- /**
- Potentially less accurate but faster than direction().
- Only works if System::hasSSE is true.
- */
- Vector3 fastDirection() const;
-
- /**
- Reflect this vector about the (not necessarily unit) normal.
- Assumes that both the before and after vectors point away from
- the base of the normal.
-
- Note that if used for a collision or ray reflection you
- must negate the resulting vector to get a direction pointing
- <I>away</I> from the collision.
-
- <PRE>
- V' N V
-
- r ^ -,
- \ | /
- \|/
- </PRE>
-
- See also Vector3::reflectionDirection
- */
- Vector3 reflectAbout(const Vector3& normal) const;
-
- /**
- See also G3D::Ray::reflect.
- The length is 1.
- <PRE>
- V' N V
-
- r ^ /
- \ | /
- \|'-
- </PRE>
- */
- Vector3 reflectionDirection(const Vector3& normal) const;
-
-
- /**
- Returns Vector3::zero() if the length is nearly zero, otherwise
- returns a unit vector.
- */
- inline Vector3 directionOrZero() const {
- float mag = magnitude();
- if (G3D::fuzzyEq(mag, 0.0f)) {
- return Vector3::zero();
- } else if (G3D::fuzzyEq(mag, 1.0f)) {
- return *this;
- } else {
- return *this * (1.0f / mag);
- }
- }
-
- /**
- Returns the direction of a refracted ray,
- where iExit is the index of refraction for the
- previous material and iEnter is the index of refraction
- for the new material. Like Vector3::reflectionDirection,
- the result has length 1 and is
- pointed <I>away</I> from the intersection.
-
- Returns Vector3::zero() in the case of total internal refraction.
-
- @param iOutside The index of refraction (eta) outside
- (on the <I>positive</I> normal side) of the surface.
-
- @param iInside The index of refraction (eta) inside
- (on the <I>negative</I> normal side) of the surface.
-
- See also G3D::Ray::refract.
- <PRE>
- N V
-
- ^ /
- | /
- |'-
- __--
- V'<--
- </PRE>
- */
- Vector3 refractionDirection(
- const Vector3& normal,
- float iInside,
- float iOutside) const;
-
- /** Synonym for direction */
- inline Vector3 unit() const {
- return direction();
- }
-
- /** Returns a normalized vector. May be computed with lower
- precision than unit */
- inline Vector3 fastUnit() const {
- return fastDirection();
- }
-
- /** Same as squaredMagnitude */
- float squaredLength() const;
-
- float squaredMagnitude () const;
-
- float __fastcall dot(const Vector3& rkVector) const;
-
- float unitize(float tolerance = 1e-06);
-
- /** Cross product. Note that two cross products in a row
- can be computed more cheaply: v1 x (v2 x v3) = (v1 dot v3) v2 - (v1 dot v2) v3.
- */
- Vector3 __fastcall cross(const Vector3& rkVector) const;
- Vector3 unitCross(const Vector3& rkVector) const;
-
- /**
- Returns a matrix such that v.cross() * w = v.cross(w).
- <PRE>
- [ 0 -v.z v.y ]
- [ v.z 0 -v.x ]
- [ -v.y v.x 0 ]
- </PRE>
- */
- class Matrix3 cross() const;
-
- Vector3 __fastcall min(const Vector3 &v) const;
- Vector3 __fastcall max(const Vector3 &v) const;
-
- /** Smallest element */
- inline float min() const {
- return G3D::min(G3D::min(x, y), z);
- }
-
- /** Largest element */
- inline float max() const {
- return G3D::max(G3D::max(x, y), z);
- }
-
- std::string toString() const;
-
- inline Vector3 clamp(const Vector3& low, const Vector3& high) const {
- return Vector3(
- G3D::clamp(x, low.x, high.x),
- G3D::clamp(y, low.y, high.y),
- G3D::clamp(z, low.z, high.z));
- }
-
- inline Vector3 clamp(float low, float high) const {
- return Vector3(
- G3D::clamp(x, low, high),
- G3D::clamp(y, low, high),
- G3D::clamp(z, low, high));
- }
-
- /**
- Linear interpolation
- */
- inline Vector3 lerp(const Vector3& v, float alpha) const {
- return (*this) + (v - *this) * alpha;
- }
-
- /** Gram-Schmidt orthonormalization. */
- static void orthonormalize (Vector3 akVector[3]);
-
- /** \brief Random unit vector, uniformly distributed on the sphere.
-
- Distribution rendered by G3D::DirectionHistogram:
- \image html vector3-random.png
- */
- static Vector3 random(Random& r = Random::common());
-
- /** \brief Random unit vector, distributed according to \f$\max(\cos \theta,0)\f$.
-
- That is, so that the probability of \f$\vec{V}\f$ is proportional
- to \f$\max(\vec{v} \cdot \vec{n}, 0)\f$. Useful in photon mapping for
- Lambertian scattering.
-
- Distribution rendered by G3D::DirectionHistogram:
- \image html vector3-coshemirandom.png
-
- \param n Unit vector at the center of the distribution.
-
- @cite Henrik Wann Jensen, Realistic Image Synthesis using Photon Mapping eqn 2.24
- */
- static Vector3 cosHemiRandom(const Vector3& n, Random& r = Random::common());
-
- /** \brief Random unit vector, distributed according to \f$\max(\cos^k \theta,0)\f$.
-
- That is, so that the probability of \f$\vec{V}\f$ is
- proportional to \f$\max((\vec{v} \cdot \vec{n})^k, 0)\f$.
- Useful in photon mapping for glossy scattering.
-
- Distribution rendered by G3D::DirectionHistogram:
- \image html vector3-cospowhemirandom.png
-
- \param n Unit vector at the center of the distribution.
-
- @cite Ashikhmin and Shirley, An anisotropic Phong BRDF model, Journal of Graphics Tools, 2002
- */
- static Vector3 cosPowHemiRandom(const Vector3& n, const float k, Random& r = Random::common());
-
- /**
- \brief Random vector distributed over the hemisphere about normal.
-
- Distribution rendered by G3D::DirectionHistogram:
- \image html vector3-hemirandom.png
- */
- static Vector3 hemiRandom(const Vector3& normal, Random& r = Random::common());
-
- /** Input W must be initialize to a nonzero vector, output is {U,V,W}
- an orthonormal basis. A hint is provided about whether or not W
- is already unit length.
- @deprecated Use getTangents
- */
- static void generateOrthonormalBasis (Vector3& rkU, Vector3& rkV,
- Vector3& rkW, bool bUnitLengthW = true);
-
- inline float sum() const {
- return x + y + z;
- }
-
- inline float average() const {
- return sum() / 3.0f;
- }
-
- // Special values.
- static const Vector3& zero();
- static const Vector3& one();
- static const Vector3& unitX();
- static const Vector3& unitY();
- static const Vector3& unitZ();
- static const Vector3& inf();
- static const Vector3& nan();
-
- /** Smallest (most negative) representable vector */
- static const Vector3& minFinite();
-
- /** Largest representable vector */
- static const Vector3& maxFinite();
-
-
- /** Creates two orthonormal tangent vectors X and Y such that
- if Z = this, X x Y = Z.*/
- inline void getTangents(Vector3& X, Vector3& Y) const {
- debugAssertM(G3D::fuzzyEq(length(), 1.0f),
- "makeAxes requires Z to have unit length");
-
- // Choose another vector not perpendicular
- X = (abs(x) < 0.9f) ? Vector3::unitX() : Vector3::unitY();
-
- // Remove the part that is parallel to Z
- X -= *this * this->dot(X);
- X /= X.length();
-
- Y = this->cross(X);
- }
-
-
- // 2-char swizzles
-
- Vector2 xx() const;
- Vector2 yx() const;
- Vector2 zx() const;
- Vector2 xy() const;
- Vector2 yy() const;
- Vector2 zy() const;
- Vector2 xz() const;
- Vector2 yz() const;
- Vector2 zz() const;
-
- // 3-char swizzles
-
- Vector3 xxx() const;
- Vector3 yxx() const;
- Vector3 zxx() const;
- Vector3 xyx() const;
- Vector3 yyx() const;
- Vector3 zyx() const;
- Vector3 xzx() const;
- Vector3 yzx() const;
- Vector3 zzx() const;
- Vector3 xxy() const;
- Vector3 yxy() const;
- Vector3 zxy() const;
- Vector3 xyy() const;
- Vector3 yyy() const;
- Vector3 zyy() const;
- Vector3 xzy() const;
- Vector3 yzy() const;
- Vector3 zzy() const;
- Vector3 xxz() const;
- Vector3 yxz() const;
- Vector3 zxz() const;
- Vector3 xyz() const;
- Vector3 yyz() const;
- Vector3 zyz() const;
- Vector3 xzz() const;
- Vector3 yzz() const;
- Vector3 zzz() const;
-
- // 4-char swizzles
-
- Vector4 xxxx() const;
- Vector4 yxxx() const;
- Vector4 zxxx() const;
- Vector4 xyxx() const;
- Vector4 yyxx() const;
- Vector4 zyxx() const;
- Vector4 xzxx() const;
- Vector4 yzxx() const;
- Vector4 zzxx() const;
- Vector4 xxyx() const;
- Vector4 yxyx() const;
- Vector4 zxyx() const;
- Vector4 xyyx() const;
- Vector4 yyyx() const;
- Vector4 zyyx() const;
- Vector4 xzyx() const;
- Vector4 yzyx() const;
- Vector4 zzyx() const;
- Vector4 xxzx() const;
- Vector4 yxzx() const;
- Vector4 zxzx() const;
- Vector4 xyzx() const;
- Vector4 yyzx() const;
- Vector4 zyzx() const;
- Vector4 xzzx() const;
- Vector4 yzzx() const;
- Vector4 zzzx() const;
- Vector4 xxxy() const;
- Vector4 yxxy() const;
- Vector4 zxxy() const;
- Vector4 xyxy() const;
- Vector4 yyxy() const;
- Vector4 zyxy() const;
- Vector4 xzxy() const;
- Vector4 yzxy() const;
- Vector4 zzxy() const;
- Vector4 xxyy() const;
- Vector4 yxyy() const;
- Vector4 zxyy() const;
- Vector4 xyyy() const;
- Vector4 yyyy() const;
- Vector4 zyyy() const;
- Vector4 xzyy() const;
- Vector4 yzyy() const;
- Vector4 zzyy() const;
- Vector4 xxzy() const;
- Vector4 yxzy() const;
- Vector4 zxzy() const;
- Vector4 xyzy() const;
- Vector4 yyzy() const;
- Vector4 zyzy() const;
- Vector4 xzzy() const;
- Vector4 yzzy() const;
- Vector4 zzzy() const;
- Vector4 xxxz() const;
- Vector4 yxxz() const;
- Vector4 zxxz() const;
- Vector4 xyxz() const;
- Vector4 yyxz() const;
- Vector4 zyxz() const;
- Vector4 xzxz() const;
- Vector4 yzxz() const;
- Vector4 zzxz() const;
- Vector4 xxyz() const;
- Vector4 yxyz() const;
- Vector4 zxyz() const;
- Vector4 xyyz() const;
- Vector4 yyyz() const;
- Vector4 zyyz() const;
- Vector4 xzyz() const;
- Vector4 yzyz() const;
- Vector4 zzyz() const;
- Vector4 xxzz() const;
- Vector4 yxzz() const;
- Vector4 zxzz() const;
- Vector4 xyzz() const;
- Vector4 yyzz() const;
- Vector4 zyzz() const;
- Vector4 xzzz() const;
- Vector4 yzzz() const;
- Vector4 zzzz() const;
-
- /** Can be passed to ignore a vector3 parameter */
- static Vector3& ignore();
-};
-
-inline G3D::Vector3 operator*(float s, const G3D::Vector3& v) {
- return v * s;
-}
-
-inline G3D::Vector3 operator*(double s, const G3D::Vector3& v) {
- return v * (float)s;
-}
-
-inline G3D::Vector3 operator*(int s, const G3D::Vector3& v) {
- return v * (float)s;
-}
-
-std::ostream& operator<<(std::ostream& os, const Vector3&);
-
-
-void serialize(const Vector3::Axis& a, class BinaryOutput& bo);
-void deserialize(Vector3::Axis& a, class BinaryInput& bo);
-
-
-//----------------------------------------------------------------------------
-inline Vector3::Vector3() : x(0.0f), y(0.0f), z(0.0f) {
-}
-
-//----------------------------------------------------------------------------
-
-inline Vector3::Vector3 (float fX, float fY, float fZ) : x(fX), y(fY), z(fZ) {
-}
-
-//----------------------------------------------------------------------------
-inline Vector3::Vector3 (float V[3]) : x(V[0]), y(V[1]), z(V[2]){
-}
-
-//----------------------------------------------------------------------------
-inline Vector3::Vector3 (double V[3]) : x((float)V[0]), y((float)V[1]), z((float)V[2]){
-}
-
-//----------------------------------------------------------------------------
-inline const float& Vector3::operator[] (int i) const {
- return ((float*)this)[i];
-}
-
-inline float& Vector3::operator[] (int i) {
- return ((float*)this)[i];
-}
-
-
-//----------------------------------------------------------------------------
-inline Vector3& Vector3::operator= (const Vector3& rkVector) {
- x = rkVector.x;
- y = rkVector.y;
- z = rkVector.z;
- return *this;
-}
-
-//----------------------------------------------------------------------------
-
-inline bool Vector3::fuzzyEq(const Vector3& other) const {
- return G3D::fuzzyEq((*this - other).squaredMagnitude(), 0);
-}
-
-//----------------------------------------------------------------------------
-
-inline bool Vector3::fuzzyNe(const Vector3& other) const {
- return G3D::fuzzyNe((*this - other).squaredMagnitude(), 0);
-}
-
-//----------------------------------------------------------------------------
-
-inline bool Vector3::isFinite() const {
- return G3D::isFinite(x) && G3D::isFinite(y) && G3D::isFinite(z);
-}
-
-//----------------------------------------------------------------------------
-inline bool Vector3::operator== (const Vector3& rkVector) const {
- return ( x == rkVector.x && y == rkVector.y && z == rkVector.z );
-}
-
-//----------------------------------------------------------------------------
-inline bool Vector3::operator!= (const Vector3& rkVector) const {
- return ( x != rkVector.x || y != rkVector.y || z != rkVector.z );
-}
-
-//----------------------------------------------------------------------------
-inline Vector3 Vector3::operator+ (const Vector3& rkVector) const {
- return Vector3(x + rkVector.x, y + rkVector.y, z + rkVector.z);
-}
-
-//----------------------------------------------------------------------------
-inline Vector3 Vector3::operator- (const Vector3& rkVector) const {
- return Vector3(x - rkVector.x, y - rkVector.y, z - rkVector.z);
-}
-
-//----------------------------------------------------------------------------
-inline Vector3 Vector3::operator* (const Vector3& rkVector) const {
- return Vector3(x * rkVector.x, y * rkVector.y, z * rkVector.z);
-}
-
-inline Vector3 Vector3::operator*(float f) const {
- return Vector3(x * f, y * f, z * f);
-}
-
-//----------------------------------------------------------------------------
-inline Vector3 Vector3::operator/ (const Vector3& rkVector) const {
- return Vector3(x / rkVector.x, y / rkVector.y, z / rkVector.z);
-}
-
-//----------------------------------------------------------------------------
-inline Vector3 Vector3::operator- () const {
- return Vector3(-x, -y, -z);
-}
-
-//----------------------------------------------------------------------------
-inline Vector3& Vector3::operator+= (const Vector3& rkVector) {
- x += rkVector.x;
- y += rkVector.y;
- z += rkVector.z;
- return *this;
-}
-
-//----------------------------------------------------------------------------
-inline Vector3& Vector3::operator-= (const Vector3& rkVector) {
- x -= rkVector.x;
- y -= rkVector.y;
- z -= rkVector.z;
- return *this;
-}
-
-//----------------------------------------------------------------------------
-inline Vector3& Vector3::operator*= (float fScalar) {
- x *= fScalar;
- y *= fScalar;
- z *= fScalar;
- return *this;
-}
-
-//----------------------------------------------------------------------------
-inline Vector3& Vector3::operator*= (const Vector3& rkVector) {
- x *= rkVector.x;
- y *= rkVector.y;
- z *= rkVector.z;
- return *this;
-}
-
-//----------------------------------------------------------------------------
-inline Vector3& Vector3::operator/= (const Vector3& rkVector) {
- x /= rkVector.x;
- y /= rkVector.y;
- z /= rkVector.z;
- return *this;
-}
-
-//----------------------------------------------------------------------------
-inline float Vector3::squaredMagnitude () const {
- return x*x + y*y + z*z;
-}
-
-//----------------------------------------------------------------------------
-inline float Vector3::squaredLength () const {
- return squaredMagnitude();
-}
-
-//----------------------------------------------------------------------------
-inline float Vector3::magnitude() const {
- return ::sqrtf(x*x + y*y + z*z);
-}
-
-//----------------------------------------------------------------------------
-inline float Vector3::length() const {
- return magnitude();
-}
-
-//----------------------------------------------------------------------------
-inline Vector3 Vector3::direction () const {
- const float lenSquared = squaredMagnitude();
- const float invSqrt = 1.0f / sqrtf(lenSquared);
- return Vector3(x * invSqrt, y * invSqrt, z * invSqrt);
-}
-
-//----------------------------------------------------------------------------
-
-inline Vector3 Vector3::fastDirection () const {
- float lenSquared = x * x + y * y + z * z;
- float invSqrt = rsq(lenSquared);
- return Vector3(x * invSqrt, y * invSqrt, z * invSqrt);
-}
-
-//----------------------------------------------------------------------------
-inline float Vector3::dot (const Vector3& rkVector) const {
- return x*rkVector.x + y*rkVector.y + z*rkVector.z;
-}
-
-//----------------------------------------------------------------------------
-inline Vector3 Vector3::cross (const Vector3& rkVector) const {
- return Vector3(y*rkVector.z - z*rkVector.y, z*rkVector.x - x*rkVector.z,
- x*rkVector.y - y*rkVector.x);
-}
-
-//----------------------------------------------------------------------------
-inline Vector3 Vector3::unitCross (const Vector3& rkVector) const {
- Vector3 kCross(y*rkVector.z - z*rkVector.y, z*rkVector.x - x*rkVector.z,
- x*rkVector.y - y*rkVector.x);
- kCross.unitize();
- return kCross;
-}
-
-//----------------------------------------------------------------------------
-inline Vector3 Vector3::min(const Vector3 &v) const {
- return Vector3(G3D::min(v.x, x), G3D::min(v.y, y), G3D::min(v.z, z));
-}
-
-//----------------------------------------------------------------------------
-inline Vector3 Vector3::max(const Vector3 &v) const {
- return Vector3(G3D::max(v.x, x), G3D::max(v.y, y), G3D::max(v.z, z));
-}
-
-//----------------------------------------------------------------------------
-inline bool Vector3::isZero() const {
- return G3D::fuzzyEq(squaredMagnitude(), 0.0f);
-}
-
-//----------------------------------------------------------------------------
-
-inline bool Vector3::isUnit() const {
- return G3D::fuzzyEq(squaredMagnitude(), 1.0f);
-}
-
-} // namespace G3D
-
-
-template <>
-struct HashTrait<G3D::Vector3> {
- static size_t hashCode(const G3D::Vector3& key) {
- return key.hashCode();
- }
-};
-
-
-template<> struct PositionTrait<class G3D::Vector2> {
- static void getPosition(const G3D::Vector2& v, G3D::Vector3& p) { p = G3D::Vector3(v, 0); }
-};
-
-template<> struct PositionTrait<class G3D::Vector3> {
- static void getPosition(const G3D::Vector3& v, G3D::Vector3& p) { p = v; }
-};
-
-
-#endif
diff --git a/externals/g3dlite/G3D/Vector3.inl b/externals/g3dlite/G3D/Vector3.inl
deleted file mode 100644
index 9211c2a70fd..00000000000
--- a/externals/g3dlite/G3D/Vector3.inl
+++ /dev/null
@@ -1,249 +0,0 @@
-/**
- @file Vector3.inl
-
- @maintainer Morgan McGuire, matrix@graphics3d.com
-
- @cite Portions based on Dave Eberly's Magic Software Library at http://www.magic-software.com
-
- @created 2001-06-02
- @edited 2004-05-21
- Copyright 2000-2004, Morgan McGuire.
- All rights reserved.
- */
-
-//----------------------------------------------------------------------------
-#ifdef SSE
- // If you receive an error on this line, it is because you do not have the file
- // xmmintrin.h needed for MMX & SSE extensions. Download and install
- //
- // http://download.microsoft.com/download/vstudio60ent/SP5/Wideband-Full/WIN98Me/EN-US/vs6sp5.exe
- // and
- // http://download.microsoft.com/download/vb60ent/Update/6/W9X2KXP/EN-US/vcpp5.exe
- //
- // to get this file.
-# include <xmmintrin.h>
-#endif
-
-inline unsigned int hashCode(const G3D::Vector3& v) {
- return v.hashCode();
-}
-
-namespace G3D {
-
-//----------------------------------------------------------------------------
-inline Vector3::Vector3() : x(0.0f), y(0.0f), z(0.0f) {
-}
-
-//----------------------------------------------------------------------------
-
-inline Vector3::Vector3 (float fX, float fY, float fZ) : x(fX), y(fY), z(fZ) {
-}
-
-//----------------------------------------------------------------------------
-inline Vector3::Vector3 (float V[3]) : x(V[0]), y(V[1]), z(V[2]){
-}
-//----------------------------------------------------------------------------
-inline Vector3::Vector3 (double V[3]) : x((float)V[0]), y((float)V[1]), z((float)V[2]){
-}
-
-//----------------------------------------------------------------------------
-inline Vector3::Vector3 (const Vector3& V) : x(V.x), y(V.y), z(V.z) {
-}
-
-//----------------------------------------------------------------------------
-
-//inline Vector3::Vector3 (const __m128& m) {
- // Cast from SSE packed floats
-// *this = *(Vector3*)&m;
-//}
-
-//----------------------------------------------------------------------------
-inline const float& Vector3::operator[] (int i) const {
- return ((float*)this)[i];
-}
-
-inline float& Vector3::operator[] (int i) {
- return ((float*)this)[i];
-}
-
-//----------------------------------------------------------------------------
-inline Vector3& Vector3::operator= (const Vector3& rkVector) {
- x = rkVector.x;
- y = rkVector.y;
- z = rkVector.z;
- return *this;
-}
-
-//----------------------------------------------------------------------------
-
-inline bool Vector3::fuzzyEq(const Vector3& other) const {
- return G3D::fuzzyEq((*this - other).squaredMagnitude(), 0);
-}
-
-//----------------------------------------------------------------------------
-
-inline bool Vector3::fuzzyNe(const Vector3& other) const {
- return G3D::fuzzyNe((*this - other).squaredMagnitude(), 0);
-}
-
-//----------------------------------------------------------------------------
-
-inline bool Vector3::isFinite() const {
- return G3D::isFinite(x) && G3D::isFinite(y) && G3D::isFinite(z);
-}
-
-//----------------------------------------------------------------------------
-inline bool Vector3::operator== (const Vector3& rkVector) const {
- return ( x == rkVector.x && y == rkVector.y && z == rkVector.z );
-}
-
-//----------------------------------------------------------------------------
-inline bool Vector3::operator!= (const Vector3& rkVector) const {
- return ( x != rkVector.x || y != rkVector.y || z != rkVector.z );
-}
-
-//----------------------------------------------------------------------------
-inline Vector3 Vector3::operator+ (const Vector3& rkVector) const {
- return Vector3(x + rkVector.x, y + rkVector.y, z + rkVector.z);
-}
-
-//----------------------------------------------------------------------------
-inline Vector3 Vector3::operator- (const Vector3& rkVector) const {
- return Vector3(x - rkVector.x, y - rkVector.y, z - rkVector.z);
-}
-
-//----------------------------------------------------------------------------
-inline Vector3 Vector3::operator* (const Vector3& rkVector) const {
- return Vector3(x * rkVector.x, y * rkVector.y, z * rkVector.z);
-}
-
-inline Vector3 Vector3::operator*(float f) const {
- return Vector3(x * f, y * f, z * f);
-}
-
-//----------------------------------------------------------------------------
-inline Vector3 Vector3::operator/ (const Vector3& rkVector) const {
- return Vector3(x / rkVector.x, y / rkVector.y, z / rkVector.z);
-}
-
-//----------------------------------------------------------------------------
-inline Vector3 Vector3::operator- () const {
- return Vector3(-x, -y, -z);
-}
-
-//----------------------------------------------------------------------------
-inline Vector3& Vector3::operator+= (const Vector3& rkVector) {
- x += rkVector.x;
- y += rkVector.y;
- z += rkVector.z;
- return *this;
-}
-
-//----------------------------------------------------------------------------
-inline Vector3& Vector3::operator-= (const Vector3& rkVector) {
- x -= rkVector.x;
- y -= rkVector.y;
- z -= rkVector.z;
- return *this;
-}
-
-//----------------------------------------------------------------------------
-inline Vector3& Vector3::operator*= (float fScalar) {
- x *= fScalar;
- y *= fScalar;
- z *= fScalar;
- return *this;
-}
-
-//----------------------------------------------------------------------------
-inline Vector3& Vector3::operator*= (const Vector3& rkVector) {
- x *= rkVector.x;
- y *= rkVector.y;
- z *= rkVector.z;
- return *this;
-}
-
-//----------------------------------------------------------------------------
-inline Vector3& Vector3::operator/= (const Vector3& rkVector) {
- x /= rkVector.x;
- y /= rkVector.y;
- z /= rkVector.z;
- return *this;
-}
-
-//----------------------------------------------------------------------------
-inline float Vector3::squaredMagnitude () const {
- return x*x + y*y + z*z;
-}
-
-//----------------------------------------------------------------------------
-inline float Vector3::squaredLength () const {
- return squaredMagnitude();
-}
-
-//----------------------------------------------------------------------------
-inline float Vector3::magnitude() const {
- return sqrtf(x*x + y*y + z*z);
-}
-
-//----------------------------------------------------------------------------
-inline float Vector3::length() const {
- return magnitude();
-}
-
-//----------------------------------------------------------------------------
-inline Vector3 Vector3::direction () const {
- float lenSquared = squaredMagnitude();
- float invSqrt = 1.0f / sqrtf(lenSquared);
- return Vector3(x * invSqrt, y * invSqrt, z * invSqrt);
-}
-
-//----------------------------------------------------------------------------
-
-inline Vector3 Vector3::fastDirection () const {
- float lenSquared = x * x + y * y + z * z;
- float invSqrt = rsq(lenSquared);
- return Vector3(x * invSqrt, y * invSqrt, z * invSqrt);
-}
-
-//----------------------------------------------------------------------------
-inline float Vector3::dot (const Vector3& rkVector) const {
- return x*rkVector.x + y*rkVector.y + z*rkVector.z;
-}
-
-//----------------------------------------------------------------------------
-inline Vector3 Vector3::cross (const Vector3& rkVector) const {
- return Vector3(y*rkVector.z - z*rkVector.y, z*rkVector.x - x*rkVector.z,
- x*rkVector.y - y*rkVector.x);
-}
-
-//----------------------------------------------------------------------------
-inline Vector3 Vector3::unitCross (const Vector3& rkVector) const {
- Vector3 kCross(y*rkVector.z - z*rkVector.y, z*rkVector.x - x*rkVector.z,
- x*rkVector.y - y*rkVector.x);
- kCross.unitize();
- return kCross;
-}
-
-//----------------------------------------------------------------------------
-inline Vector3 Vector3::min(const Vector3 &v) const {
- return Vector3(G3D::min(v.x, x), G3D::min(v.y, y), G3D::min(v.z, z));
-}
-
-//----------------------------------------------------------------------------
-inline Vector3 Vector3::max(const Vector3 &v) const {
- return Vector3(G3D::max(v.x, x), G3D::max(v.y, y), G3D::max(v.z, z));
-}
-
-//----------------------------------------------------------------------------
-inline bool Vector3::isZero() const {
- return G3D::fuzzyEq(squaredMagnitude(), 0.0f);
-}
-
-//----------------------------------------------------------------------------
-
-inline bool Vector3::isUnit() const {
- return G3D::fuzzyEq(squaredMagnitude(), 1.0f);
-}
-
-} // namespace
diff --git a/externals/g3dlite/G3D/Vector3int16.h b/externals/g3dlite/G3D/Vector3int16.h
deleted file mode 100644
index 3197ea49d1a..00000000000
--- a/externals/g3dlite/G3D/Vector3int16.h
+++ /dev/null
@@ -1,127 +0,0 @@
-/**
- @file Vector3int16.h
-
- @maintainer Morgan McGuire, matrix@brown.edu
-
- @created 2003-04-07
- @edited 2003-06-24
- Copyright 2000-2004, Morgan McGuire.
- All rights reserved.
- */
-
-#ifndef VECTOR3INT16_H
-#define VECTOR3INT16_H
-
-#include "G3D/platform.h"
-#include "G3D/g3dmath.h"
-#include "G3D/HashTrait.h"
-
-#ifdef _MSC_VER
-// Turn off "conditional expression is constant" warning; MSVC generates this
-// for debug assertions in inlined methods.
-#pragma warning (disable : 4127)
-#endif
-
-
-namespace G3D {
-
-/**
- \class Vector3int16
- A Vector3 that packs its fields into uint16s.
- */
-G3D_BEGIN_PACKED_CLASS(2)
-class Vector3int16 {
-private:
- // Hidden operators
- bool operator<(const Vector3int16&) const;
- bool operator>(const Vector3int16&) const;
- bool operator<=(const Vector3int16&) const;
- bool operator>=(const Vector3int16&) const;
-
-public:
- G3D::int16 x;
- G3D::int16 y;
- G3D::int16 z;
-
- Vector3int16() : x(0), y(0), z(0) {}
- Vector3int16(G3D::int16 _x, G3D::int16 _y, G3D::int16 _z) : x(_x), y(_y), z(_z) {}
- Vector3int16(const class Vector3& v);
- Vector3int16(class BinaryInput& bi);
-
- void serialize(class BinaryOutput& bo) const;
- void deserialize(class BinaryInput& bi);
-
- inline G3D::int16& operator[] (int i) {
- debugAssert(i <= 2);
- return ((G3D::int16*)this)[i];
- }
-
- inline const G3D::int16& operator[] (int i) const {
- debugAssert(i <= 2);
- return ((G3D::int16*)this)[i];
- }
-
- inline Vector3int16 operator+(const Vector3int16& other) const {
- return Vector3int16(x + other.x, y + other.y, z + other.z);
- }
-
- inline Vector3int16 operator-(const Vector3int16& other) const {
- return Vector3int16(x - other.x, y - other.y, z - other.z);
- }
-
- inline Vector3int16 operator*(const Vector3int16& other) const {
- return Vector3int16(x * other.x, y * other.y, z * other.z);
- }
-
- inline Vector3int16 operator*(const int s) const {
- return Vector3int16(int16(x * s), int16(y * s), int16(z * s));
- }
-
- inline Vector3int16& operator+=(const Vector3int16& other) {
- x += other.x;
- y += other.y;
- z += other.y;
- return *this;
- }
-
- inline Vector3int16& operator-=(const Vector3int16& other) {
- x -= other.x;
- y -= other.y;
- z -= other.z;
- return *this;
- }
-
- inline Vector3int16& operator*=(const Vector3int16& other) {
- x *= other.x;
- y *= other.y;
- z *= other.z;
- return *this;
- }
-
- inline bool operator== (const Vector3int16& rkVector) const {
- return ( x == rkVector.x && y == rkVector.y && z == rkVector.z );
- }
-
- inline bool operator!= (const Vector3int16& rkVector) const {
- return ( x != rkVector.x || y != rkVector.y || z != rkVector.z );
- }
-
- Vector3int16 max(const Vector3int16& v) const {
- return Vector3int16(std::max(x, v.x), std::max(y, v.y), std::max(z, v.z));
- }
-
- Vector3int16 min(const Vector3int16& v) const {
- return Vector3int16(std::min(x, v.x), std::min(y, v.y), std::min(z, v.z));
- }
-
- std::string toString() const;
-}
-G3D_END_PACKED_CLASS(2)
-
-}
-
-template <> struct HashTrait<G3D::Vector3int16> {
- static size_t hashCode(const G3D::Vector3int16& key) { return static_cast<size_t>(key.x + ((int)key.y << 5) + ((int)key.z << 10)); }
-};
-
-#endif
diff --git a/externals/g3dlite/G3D/Vector3int32.h b/externals/g3dlite/G3D/Vector3int32.h
deleted file mode 100644
index 2f256ea0300..00000000000
--- a/externals/g3dlite/G3D/Vector3int32.h
+++ /dev/null
@@ -1,128 +0,0 @@
-/**
- @file Vector3int32.h
-
- @maintainer Morgan McGuire, matrix@brown.edu
-
- @created 2008-07-01
- @edited 2008-07-01
- Copyright 2000-2009, Morgan McGuire.
- All rights reserved.
- */
-
-#ifndef VECTOR3INT32_H
-#define VECTOR3INT32_H
-
-#include "G3D/platform.h"
-#include "G3D/g3dmath.h"
-#include "G3D/HashTrait.h"
-
-namespace G3D {
-
-/**
- \ Vector3int32
- A Vector3 that packs its fields into uint32s.
- */
-G3D_BEGIN_PACKED_CLASS(4)
-class Vector3int32 {
-private:
- // Hidden operators
- bool operator<(const Vector3int32&) const;
- bool operator>(const Vector3int32&) const;
- bool operator<=(const Vector3int32&) const;
- bool operator>=(const Vector3int32&) const;
-
-public:
- G3D::int32 x;
- G3D::int32 y;
- G3D::int32 z;
-
- Vector3int32() : x(0), y(0), z(0) {}
- Vector3int32(int _x, int _y, int _z) : x(_x), y(_y), z(_z) {}
- Vector3int32(const class Vector3int16& v);
- Vector3int32(const class Vector3& v);
- Vector3int32(class BinaryInput& bi);
-
- void serialize(class BinaryOutput& bo) const;
- void deserialize(class BinaryInput& bi);
-
- inline G3D::int32& operator[] (int i) {
- debugAssert(i <= 2);
- return ((G3D::int32*)this)[i];
- }
-
- inline const G3D::int32& operator[] (int i) const {
- debugAssert(i <= 2);
- return ((G3D::int32*)this)[i];
- }
-
- inline Vector3int32 operator+(const Vector3int32& other) const {
- return Vector3int32(x + other.x, y + other.y, z + other.z);
- }
-
- inline Vector3int32 operator-(const Vector3int32& other) const {
- return Vector3int32(x - other.x, y - other.y, z - other.z);
- }
-
- inline Vector3int32 operator*(const Vector3int32& other) const {
- return Vector3int32(x * other.x, y * other.y, z * other.z);
- }
-
- inline Vector3int32 operator*(const int s) const {
- return Vector3int32(x * s, y * s, z * s);
- }
-
- inline Vector3int32& operator+=(const Vector3int32& other) {
- x += other.x;
- y += other.y;
- z += other.y;
- return *this;
- }
-
- inline Vector3int32& operator-=(const Vector3int32& other) {
- x -= other.x;
- y -= other.y;
- z -= other.z;
- return *this;
- }
-
- inline Vector3int32& operator*=(const Vector3int32& other) {
- x *= other.x;
- y *= other.y;
- z *= other.z;
- return *this;
- }
-
- inline bool operator== (const Vector3int32& rkVector) const {
- return ( x == rkVector.x && y == rkVector.y && z == rkVector.z );
- }
-
- inline bool operator!= (const Vector3int32& rkVector) const {
- return ( x != rkVector.x || y != rkVector.y || z != rkVector.z );
- }
-
- Vector3int32 max(const Vector3int32& v) const {
- return Vector3int32(iMax(x, v.x), iMax(y, v.y), iMax(z, v.z));
- }
-
- Vector3int32 min(const Vector3int32& v) const {
- return Vector3int32(iMin(x, v.x), iMin(y, v.y), iMin(z, v.z));
- }
-
- std::string toString() const;
-}
-G3D_END_PACKED_CLASS(4)
-
-}
-
-template <> struct HashTrait<G3D::Vector3int32> {
- static size_t hashCode(const G3D::Vector3int32& key) {
- // Mask for the top bit of a uint32
- const G3D::uint32 top = (1UL << 31);
- // Mask for the bottom 10 bits of a uint32
- const G3D::uint32 bot = 0x000003FF;
- return static_cast<size_t>(((key.x & top) | ((key.y & top) >> 1) | ((key.z & top) >> 2)) |
- (((key.x & bot) << 19) ^ ((key.y & bot) << 10) ^ (key.z & bot)));
- }
-};
-
-#endif
diff --git a/externals/g3dlite/G3D/Vector4.h b/externals/g3dlite/G3D/Vector4.h
deleted file mode 100644
index 5e511451f86..00000000000
--- a/externals/g3dlite/G3D/Vector4.h
+++ /dev/null
@@ -1,716 +0,0 @@
-/**
- @file Vector4.h
-
- Homogeneous vector class.
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2002-07-09
- @edited 2008-11-01
-
- Copyright 2000-2009, Morgan McGuire.
- All rights reserved.
- */
-
-#ifndef G3D_Vector4_h
-#define G3D_Vector4_h
-
-#include "G3D/platform.h"
-#include "G3D/g3dmath.h"
-#include "G3D/Vector3.h"
-#include "G3D/Vector2.h"
-#include "G3D/Table.h"
-#include "G3D/HashTrait.h"
-#include "G3D/PositionTrait.h"
-#include <string>
-
-namespace G3D {
-
-class Vector2;
-class Vector3;
-class Vector4;
-class Vector4int8;
-class Any;
-
-/**
- Do not subclass-- this implementation makes assumptions about the
- memory layout.
- */
-class Vector4 {
-private:
- // Hidden operators
- bool operator<(const Vector4&) const;
- bool operator>(const Vector4&) const;
- bool operator<=(const Vector4&) const;
- bool operator>=(const Vector4&) const;
-
-public:
-
- /** \param any Must either Vector4(#, #, #, #) or Vector3 {x = #, y = #, z = #, w =#}*/
- Vector4(const Any& any);
-
- /** Converts the Vector4 to an Any. */
- operator Any() const;
-
- // construction
- Vector4();
- Vector4(float fX, float fY, float fZ, float fW);
- Vector4(float afCoordinate[4]);
- Vector4(const Vector4& rkVector);
- Vector4(const class Color4& c);
- Vector4(const Vector3& rkVector, float fW);
- Vector4(const Vector2& v1, const Vector2& v2);
- Vector4(const Vector2& v1, float fz, float fw);
-
- /** Divides by 127 when converting */
- Vector4(const Vector4int8&);
-
- Vector4(class BinaryInput& b);
- void serialize(class BinaryOutput& b) const;
- void deserialize(class BinaryInput& b);
-
- // coordinates
- float x, y, z, w;
-
- // access vector V as V[0] = V.x, V[1] = V.y, V[2] = V.z, etc.
- //
- // WARNING. These member functions rely on
- // (1) Vector4 not having virtual functions
- // (2) the data packed in a 4*sizeof(float) memory block
- float& operator[] (int i);
- const float& operator[] (int i) const;
-
- // assignment and comparison
- Vector4& operator= (const Vector4& rkVector);
- bool operator== (const Vector4& rkVector) const;
- bool operator!= (const Vector4& rkVector) const;
-
- static const Vector4& zero();
-
- inline void set(float _x, float _y, float _z, float _w) {
- x = _x;
- y = _y;
- z = _z;
- w = _w;
- }
-
- inline void set(const Vector3& v, float _w) {
- x = v.x;
- y = v.y;
- z = v.z;
- w = _w;
- }
-
- inline void set(const Vector2& v, float _z, float _w) {
- x = v.x;
- y = v.y;
- z = _z;
- w = _w;
- }
-
- size_t hashCode() const;
- bool fuzzyEq(const Vector4& other) const;
- bool fuzzyNe(const Vector4& other) const;
-
- static const Vector4& inf();
- static const Vector4& nan();
-
- /** sqrt(this->dot(*this)) */
- float length() const;
- float squaredLength() const;
-
- inline float sum() const {
- return x + y + z + w;
- }
-
- /** Returns true if this vector has finite length */
- bool isFinite() const;
-
- /** Returns true if this vector has length == 0 */
- bool isZero() const;
-
- /** Returns true if this vector has length == 1 */
- bool isUnit() const;
-
- // arithmetic operations
- Vector4 operator+ (const Vector4& rkVector) const;
- Vector4 operator- (const Vector4& rkVector) const;
-
- inline Vector4 operator*(const Vector4& rkVector) const {
- return Vector4(x * rkVector.x, y * rkVector.y, z * rkVector.z, w * rkVector.w);
- }
-
- inline Vector4 operator/(const Vector4& rkVector) const {
- return Vector4(x / rkVector.x, y / rkVector.y, z / rkVector.z, w / rkVector.w);
- }
-
- Vector4 operator*(const class Matrix4& M) const;
-
- Vector4 operator* (float fScalar) const;
- Vector4 operator/ (float fScalar) const;
- Vector4 operator- () const;
- friend Vector4 operator* (float, const Vector4& rkVector);
-
- // arithmetic updates
- Vector4& operator+= (const Vector4& rkVector);
- Vector4& operator-= (const Vector4& rkVector);
- Vector4& operator*= (float fScalar);
- Vector4& operator/= (float fScalar);
-
- inline Vector4 clamp(const Vector4& low, const Vector4& high) const {
- return Vector4(
- G3D::clamp(x, low.x, high.x),
- G3D::clamp(y, low.y, high.y),
- G3D::clamp(z, low.z, high.z),
- G3D::clamp(w, low.w, high.w));
- }
-
- inline Vector4 clamp(float low, float high) const {
- return Vector4(
- G3D::clamp(x, low, high),
- G3D::clamp(y, low, high),
- G3D::clamp(z, low, high),
- G3D::clamp(w, low, high));
- }
-
- float dot (const Vector4& rkVector) const;
-
- Vector4 min(const Vector4& v) const;
- Vector4 max(const Vector4& v) const;
-
- std::string toString() const;
-
- /**
- Linear interpolation
- */
- Vector4 lerp(const Vector4& v, float alpha) const;
-
- // 2-char swizzles
-
- Vector2 xx() const;
- Vector2 yx() const;
- Vector2 zx() const;
- Vector2 wx() const;
- Vector2 xy() const;
- Vector2 yy() const;
- Vector2 zy() const;
- Vector2 wy() const;
- Vector2 xz() const;
- Vector2 yz() const;
- Vector2 zz() const;
- Vector2 wz() const;
- Vector2 xw() const;
- Vector2 yw() const;
- Vector2 zw() const;
- Vector2 ww() const;
-
- // 3-char swizzles
-
- Vector3 xxx() const;
- Vector3 yxx() const;
- Vector3 zxx() const;
- Vector3 wxx() const;
- Vector3 xyx() const;
- Vector3 yyx() const;
- Vector3 zyx() const;
- Vector3 wyx() const;
- Vector3 xzx() const;
- Vector3 yzx() const;
- Vector3 zzx() const;
- Vector3 wzx() const;
- Vector3 xwx() const;
- Vector3 ywx() const;
- Vector3 zwx() const;
- Vector3 wwx() const;
- Vector3 xxy() const;
- Vector3 yxy() const;
- Vector3 zxy() const;
- Vector3 wxy() const;
- Vector3 xyy() const;
- Vector3 yyy() const;
- Vector3 zyy() const;
- Vector3 wyy() const;
- Vector3 xzy() const;
- Vector3 yzy() const;
- Vector3 zzy() const;
- Vector3 wzy() const;
- Vector3 xwy() const;
- Vector3 ywy() const;
- Vector3 zwy() const;
- Vector3 wwy() const;
- Vector3 xxz() const;
- Vector3 yxz() const;
- Vector3 zxz() const;
- Vector3 wxz() const;
- Vector3 xyz() const;
- Vector3 yyz() const;
- Vector3 zyz() const;
- Vector3 wyz() const;
- Vector3 xzz() const;
- Vector3 yzz() const;
- Vector3 zzz() const;
- Vector3 wzz() const;
- Vector3 xwz() const;
- Vector3 ywz() const;
- Vector3 zwz() const;
- Vector3 wwz() const;
- Vector3 xxw() const;
- Vector3 yxw() const;
- Vector3 zxw() const;
- Vector3 wxw() const;
- Vector3 xyw() const;
- Vector3 yyw() const;
- Vector3 zyw() const;
- Vector3 wyw() const;
- Vector3 xzw() const;
- Vector3 yzw() const;
- Vector3 zzw() const;
- Vector3 wzw() const;
- Vector3 xww() const;
- Vector3 yww() const;
- Vector3 zww() const;
- Vector3 www() const;
-
- // 4-char swizzles
-
- Vector4 xxxx() const;
- Vector4 yxxx() const;
- Vector4 zxxx() const;
- Vector4 wxxx() const;
- Vector4 xyxx() const;
- Vector4 yyxx() const;
- Vector4 zyxx() const;
- Vector4 wyxx() const;
- Vector4 xzxx() const;
- Vector4 yzxx() const;
- Vector4 zzxx() const;
- Vector4 wzxx() const;
- Vector4 xwxx() const;
- Vector4 ywxx() const;
- Vector4 zwxx() const;
- Vector4 wwxx() const;
- Vector4 xxyx() const;
- Vector4 yxyx() const;
- Vector4 zxyx() const;
- Vector4 wxyx() const;
- Vector4 xyyx() const;
- Vector4 yyyx() const;
- Vector4 zyyx() const;
- Vector4 wyyx() const;
- Vector4 xzyx() const;
- Vector4 yzyx() const;
- Vector4 zzyx() const;
- Vector4 wzyx() const;
- Vector4 xwyx() const;
- Vector4 ywyx() const;
- Vector4 zwyx() const;
- Vector4 wwyx() const;
- Vector4 xxzx() const;
- Vector4 yxzx() const;
- Vector4 zxzx() const;
- Vector4 wxzx() const;
- Vector4 xyzx() const;
- Vector4 yyzx() const;
- Vector4 zyzx() const;
- Vector4 wyzx() const;
- Vector4 xzzx() const;
- Vector4 yzzx() const;
- Vector4 zzzx() const;
- Vector4 wzzx() const;
- Vector4 xwzx() const;
- Vector4 ywzx() const;
- Vector4 zwzx() const;
- Vector4 wwzx() const;
- Vector4 xxwx() const;
- Vector4 yxwx() const;
- Vector4 zxwx() const;
- Vector4 wxwx() const;
- Vector4 xywx() const;
- Vector4 yywx() const;
- Vector4 zywx() const;
- Vector4 wywx() const;
- Vector4 xzwx() const;
- Vector4 yzwx() const;
- Vector4 zzwx() const;
- Vector4 wzwx() const;
- Vector4 xwwx() const;
- Vector4 ywwx() const;
- Vector4 zwwx() const;
- Vector4 wwwx() const;
- Vector4 xxxy() const;
- Vector4 yxxy() const;
- Vector4 zxxy() const;
- Vector4 wxxy() const;
- Vector4 xyxy() const;
- Vector4 yyxy() const;
- Vector4 zyxy() const;
- Vector4 wyxy() const;
- Vector4 xzxy() const;
- Vector4 yzxy() const;
- Vector4 zzxy() const;
- Vector4 wzxy() const;
- Vector4 xwxy() const;
- Vector4 ywxy() const;
- Vector4 zwxy() const;
- Vector4 wwxy() const;
- Vector4 xxyy() const;
- Vector4 yxyy() const;
- Vector4 zxyy() const;
- Vector4 wxyy() const;
- Vector4 xyyy() const;
- Vector4 yyyy() const;
- Vector4 zyyy() const;
- Vector4 wyyy() const;
- Vector4 xzyy() const;
- Vector4 yzyy() const;
- Vector4 zzyy() const;
- Vector4 wzyy() const;
- Vector4 xwyy() const;
- Vector4 ywyy() const;
- Vector4 zwyy() const;
- Vector4 wwyy() const;
- Vector4 xxzy() const;
- Vector4 yxzy() const;
- Vector4 zxzy() const;
- Vector4 wxzy() const;
- Vector4 xyzy() const;
- Vector4 yyzy() const;
- Vector4 zyzy() const;
- Vector4 wyzy() const;
- Vector4 xzzy() const;
- Vector4 yzzy() const;
- Vector4 zzzy() const;
- Vector4 wzzy() const;
- Vector4 xwzy() const;
- Vector4 ywzy() const;
- Vector4 zwzy() const;
- Vector4 wwzy() const;
- Vector4 xxwy() const;
- Vector4 yxwy() const;
- Vector4 zxwy() const;
- Vector4 wxwy() const;
- Vector4 xywy() const;
- Vector4 yywy() const;
- Vector4 zywy() const;
- Vector4 wywy() const;
- Vector4 xzwy() const;
- Vector4 yzwy() const;
- Vector4 zzwy() const;
- Vector4 wzwy() const;
- Vector4 xwwy() const;
- Vector4 ywwy() const;
- Vector4 zwwy() const;
- Vector4 wwwy() const;
- Vector4 xxxz() const;
- Vector4 yxxz() const;
- Vector4 zxxz() const;
- Vector4 wxxz() const;
- Vector4 xyxz() const;
- Vector4 yyxz() const;
- Vector4 zyxz() const;
- Vector4 wyxz() const;
- Vector4 xzxz() const;
- Vector4 yzxz() const;
- Vector4 zzxz() const;
- Vector4 wzxz() const;
- Vector4 xwxz() const;
- Vector4 ywxz() const;
- Vector4 zwxz() const;
- Vector4 wwxz() const;
- Vector4 xxyz() const;
- Vector4 yxyz() const;
- Vector4 zxyz() const;
- Vector4 wxyz() const;
- Vector4 xyyz() const;
- Vector4 yyyz() const;
- Vector4 zyyz() const;
- Vector4 wyyz() const;
- Vector4 xzyz() const;
- Vector4 yzyz() const;
- Vector4 zzyz() const;
- Vector4 wzyz() const;
- Vector4 xwyz() const;
- Vector4 ywyz() const;
- Vector4 zwyz() const;
- Vector4 wwyz() const;
- Vector4 xxzz() const;
- Vector4 yxzz() const;
- Vector4 zxzz() const;
- Vector4 wxzz() const;
- Vector4 xyzz() const;
- Vector4 yyzz() const;
- Vector4 zyzz() const;
- Vector4 wyzz() const;
- Vector4 xzzz() const;
- Vector4 yzzz() const;
- Vector4 zzzz() const;
- Vector4 wzzz() const;
- Vector4 xwzz() const;
- Vector4 ywzz() const;
- Vector4 zwzz() const;
- Vector4 wwzz() const;
- Vector4 xxwz() const;
- Vector4 yxwz() const;
- Vector4 zxwz() const;
- Vector4 wxwz() const;
- Vector4 xywz() const;
- Vector4 yywz() const;
- Vector4 zywz() const;
- Vector4 wywz() const;
- Vector4 xzwz() const;
- Vector4 yzwz() const;
- Vector4 zzwz() const;
- Vector4 wzwz() const;
- Vector4 xwwz() const;
- Vector4 ywwz() const;
- Vector4 zwwz() const;
- Vector4 wwwz() const;
- Vector4 xxxw() const;
- Vector4 yxxw() const;
- Vector4 zxxw() const;
- Vector4 wxxw() const;
- Vector4 xyxw() const;
- Vector4 yyxw() const;
- Vector4 zyxw() const;
- Vector4 wyxw() const;
- Vector4 xzxw() const;
- Vector4 yzxw() const;
- Vector4 zzxw() const;
- Vector4 wzxw() const;
- Vector4 xwxw() const;
- Vector4 ywxw() const;
- Vector4 zwxw() const;
- Vector4 wwxw() const;
- Vector4 xxyw() const;
- Vector4 yxyw() const;
- Vector4 zxyw() const;
- Vector4 wxyw() const;
- Vector4 xyyw() const;
- Vector4 yyyw() const;
- Vector4 zyyw() const;
- Vector4 wyyw() const;
- Vector4 xzyw() const;
- Vector4 yzyw() const;
- Vector4 zzyw() const;
- Vector4 wzyw() const;
- Vector4 xwyw() const;
- Vector4 ywyw() const;
- Vector4 zwyw() const;
- Vector4 wwyw() const;
- Vector4 xxzw() const;
- Vector4 yxzw() const;
- Vector4 zxzw() const;
- Vector4 wxzw() const;
- Vector4 xyzw() const;
- Vector4 yyzw() const;
- Vector4 zyzw() const;
- Vector4 wyzw() const;
- Vector4 xzzw() const;
- Vector4 yzzw() const;
- Vector4 zzzw() const;
- Vector4 wzzw() const;
- Vector4 xwzw() const;
- Vector4 ywzw() const;
- Vector4 zwzw() const;
- Vector4 wwzw() const;
- Vector4 xxww() const;
- Vector4 yxww() const;
- Vector4 zxww() const;
- Vector4 wxww() const;
- Vector4 xyww() const;
- Vector4 yyww() const;
- Vector4 zyww() const;
- Vector4 wyww() const;
- Vector4 xzww() const;
- Vector4 yzww() const;
- Vector4 zzww() const;
- Vector4 wzww() const;
- Vector4 xwww() const;
- Vector4 ywww() const;
- Vector4 zwww() const;
- Vector4 wwww() const;
-
-};
-
-
-//----------------------------------------------------------------------------
-inline Vector4::Vector4() {
- x = y = z = w = 0;
-}
-
-//----------------------------------------------------------------------------
-
-inline Vector4::Vector4 (float fX, float fY, float fZ, float fW) {
- x = fX;
- y = fY;
- z = fZ;
- w = fW;
-}
-
-//----------------------------------------------------------------------------
-inline Vector4::Vector4 (float afCoordinate[4]) {
- x = afCoordinate[0];
- y = afCoordinate[1];
- z = afCoordinate[2];
- w = afCoordinate[3];
-}
-
-//----------------------------------------------------------------------------
-inline Vector4::Vector4(const Vector4& rkVector) {
- x = rkVector.x;
- y = rkVector.y;
- z = rkVector.z;
- w = rkVector.w;
-}
-//----------------------------------------------------------------------------
-inline Vector4::Vector4(const Vector3& rkVector, float fW) {
- x = rkVector.x;
- y = rkVector.y;
- z = rkVector.z;
- w = fW;
-}
-
-//----------------------------------------------------------------------------
-inline float& Vector4::operator[] (int i) {
- return ((float*)this)[i];
-}
-
-//----------------------------------------------------------------------------
-inline const float& Vector4::operator[] (int i) const {
- return ((float*)this)[i];
-}
-
-//----------------------------------------------------------------------------
-inline Vector4& Vector4::operator= (const Vector4& rkVector) {
- x = rkVector.x;
- y = rkVector.y;
- z = rkVector.z;
- w = rkVector.w;
- return *this;
-}
-
-//----------------------------------------------------------------------------
-inline bool Vector4::operator== (const Vector4& rkVector) const {
- return ( (x == rkVector.x) && (y == rkVector.y) && (z == rkVector.z) && (w == rkVector.w));
-}
-
-//----------------------------------------------------------------------------
-inline bool Vector4::operator!= (const Vector4& rkVector) const {
- return ( x != rkVector.x || y != rkVector.y || z != rkVector.z || w != rkVector.w);
-}
-
-//----------------------------------------------------------------------------
-inline Vector4 Vector4::operator+ (const Vector4& rkVector) const {
- return Vector4(x + rkVector.x, y + rkVector.y, z + rkVector.z, w + rkVector.w);
-}
-
-//----------------------------------------------------------------------------
-inline Vector4 Vector4::operator- (const Vector4& rkVector) const {
- return Vector4(x - rkVector.x, y - rkVector.y, z - rkVector.z, w - rkVector.w);
-}
-
-//----------------------------------------------------------------------------
-inline Vector4 Vector4::operator* (float fScalar) const {
- return Vector4(fScalar*x, fScalar*y, fScalar*z, fScalar*w);
-}
-
-//----------------------------------------------------------------------------
-inline Vector4 Vector4::operator- () const {
- return Vector4( -x, -y, -z, -w);
-}
-
-//----------------------------------------------------------------------------
-inline Vector4& Vector4::operator+= (const Vector4& rkVector) {
- x += rkVector.x;
- y += rkVector.y;
- z += rkVector.z;
- w += rkVector.w;
- return *this;
-}
-
-//----------------------------------------------------------------------------
-inline Vector4& Vector4::operator-= (const Vector4& rkVector) {
- x -= rkVector.x;
- y -= rkVector.y;
- z -= rkVector.z;
- w -= rkVector.w;
- return *this;
-}
-
-//----------------------------------------------------------------------------
-
-inline Vector4 Vector4::lerp(const Vector4& v, float alpha) const {
- return (*this) + (v - *this) * alpha;
-}
-
-
-//----------------------------------------------------------------------------
-inline Vector4& Vector4::operator*= (float fScalar) {
- x *= fScalar;
- y *= fScalar;
- z *= fScalar;
- w *= fScalar;
- return *this;
-}
-
-
-//----------------------------------------------------------------------------
-inline float Vector4::dot(const Vector4& rkVector) const {
- return x*rkVector.x + y*rkVector.y + z*rkVector.z + w*rkVector.w;
-}
-
-//----------------------------------------------------------------------------
-inline Vector4 Vector4::min(const Vector4 &v) const {
- return Vector4(G3D::min(v.x, x), G3D::min(v.y, y), G3D::min(v.z, z), G3D::min(v.w, w));
-}
-
-//----------------------------------------------------------------------------
-inline Vector4 Vector4::max(const Vector4 &v) const {
- return Vector4(G3D::max(v.x, x), G3D::max(v.y, y), G3D::max(v.z, z), G3D::max(v.w, w));
-}
-
-//----------------------------------------------------------------------------
-inline bool Vector4::isZero() const {
- return (x == 0.0f) && (y == 0.0f) && (z == 0.0f) && (w == 0.0f);
-}
-
-//----------------------------------------------------------------------------
-
-inline bool Vector4::isFinite() const {
- return G3D::isFinite(x) && G3D::isFinite(y) && G3D::isFinite(z) && G3D::isFinite(w);
-}
-
-//----------------------------------------------------------------------------
-
-inline bool Vector4::isUnit() const {
- return squaredLength() == 1.0;
-}
-
-//----------------------------------------------------------------------------
-
-inline float Vector4::length() const {
- return sqrtf(squaredLength());
-}
-
-//----------------------------------------------------------------------------
-
-inline float Vector4::squaredLength() const {
- return x * x + y * y + z * z + w * w;
-}
-
-}
-
-template <> struct HashTrait<G3D::Vector4> {
- static size_t hashCode(const G3D::Vector4& key) { return key.hashCode(); }
-};
-
-
-template<> struct PositionTrait<class G3D::Vector4> {
- static void getPosition(const G3D::Vector4& v, G3D::Vector3& p) { p = v.xyz(); }
-};
-
-inline G3D::Vector4 operator* (float s, const G3D::Vector4& v) {
- return v * s;
-}
-
-#endif
diff --git a/externals/g3dlite/G3D/Vector4.inl b/externals/g3dlite/G3D/Vector4.inl
deleted file mode 100644
index 576cca83b56..00000000000
--- a/externals/g3dlite/G3D/Vector4.inl
+++ /dev/null
@@ -1,191 +0,0 @@
-/**
- @file Vector4.inl
-
- @maintainer Morgan McGuire, matrix@graphics3d.com
-
- @created 2002-07-09
- @edited 2003-02-10
- */
-
-//----------------------------------------------------------------------------
-
-inline unsigned int hashCode(const G3D::Vector4& v) {
- return v.hashCode();
-}
-
-namespace G3D {
-
-//----------------------------------------------------------------------------
-inline Vector4::Vector4() {
- x = y = z = w = 0;
-}
-
-//----------------------------------------------------------------------------
-
-inline Vector4::Vector4 (float fX, float fY, float fZ, float fW) {
- x = fX;
- y = fY;
- z = fZ;
- w = fW;
-}
-
-//----------------------------------------------------------------------------
-inline Vector4::Vector4 (float afCoordinate[4]) {
- x = afCoordinate[0];
- y = afCoordinate[1];
- z = afCoordinate[2];
- w = afCoordinate[3];
-}
-
-//----------------------------------------------------------------------------
-inline Vector4::Vector4(const Vector4& rkVector) {
- x = rkVector.x;
- y = rkVector.y;
- z = rkVector.z;
- w = rkVector.w;
-}
-//----------------------------------------------------------------------------
-inline Vector4::Vector4(const Vector3& rkVector, float fW) {
- x = rkVector.x;
- y = rkVector.y;
- z = rkVector.z;
- w = fW;
-}
-
-//----------------------------------------------------------------------------
-inline float& Vector4::operator[] (int i) {
- return ((float*)this)[i];
-}
-
-//----------------------------------------------------------------------------
-inline const float& Vector4::operator[] (int i) const {
- return ((float*)this)[i];
-}
-
-//----------------------------------------------------------------------------
-inline Vector4::operator float* () {
- return (float*)this;
-}
-
-inline Vector4::operator const float* () const {
- return (float*)this;
-}
-
-//----------------------------------------------------------------------------
-inline Vector4& Vector4::operator= (const Vector4& rkVector) {
- x = rkVector.x;
- y = rkVector.y;
- z = rkVector.z;
- w = rkVector.w;
- return *this;
-}
-
-//----------------------------------------------------------------------------
-inline bool Vector4::operator== (const Vector4& rkVector) const {
- return ( (x == rkVector.x) && (y == rkVector.y) && (z == rkVector.z) && (w == rkVector.w));
-}
-
-//----------------------------------------------------------------------------
-inline bool Vector4::operator!= (const Vector4& rkVector) const {
- return ( x != rkVector.x || y != rkVector.y || z != rkVector.z || w != rkVector.w);
-}
-
-//----------------------------------------------------------------------------
-inline Vector4 Vector4::operator+ (const Vector4& rkVector) const {
- return Vector4(x + rkVector.x, y + rkVector.y, z + rkVector.z, w + rkVector.w);
-}
-
-//----------------------------------------------------------------------------
-inline Vector4 Vector4::operator- (const Vector4& rkVector) const {
- return Vector4(x - rkVector.x, y - rkVector.y, z - rkVector.z, w - rkVector.w);
-}
-
-//----------------------------------------------------------------------------
-inline Vector4 Vector4::operator* (float fScalar) const {
- return Vector4(fScalar*x, fScalar*y, fScalar*z, fScalar*w);
-}
-
-//----------------------------------------------------------------------------
-inline Vector4 Vector4::operator- () const {
- return Vector4( -x, -y, -z, -w);
-}
-
-//----------------------------------------------------------------------------
-inline Vector4& Vector4::operator+= (const Vector4& rkVector) {
- x += rkVector.x;
- y += rkVector.y;
- z += rkVector.z;
- w += rkVector.w;
- return *this;
-}
-
-//----------------------------------------------------------------------------
-inline Vector4& Vector4::operator-= (const Vector4& rkVector) {
- x -= rkVector.x;
- y -= rkVector.y;
- z -= rkVector.z;
- w -= rkVector.w;
- return *this;
-}
-
-//----------------------------------------------------------------------------
-
-inline Vector4 Vector4::lerp(const Vector4& v, float alpha) const {
- return (*this) + (v - *this) * alpha;
-}
-
-//----------------------------------------------------------------------------
-inline Vector4& Vector4::operator*= (float fScalar) {
- x *= fScalar;
- y *= fScalar;
- z *= fScalar;
- w *= fScalar;
- return *this;
-}
-
-//----------------------------------------------------------------------------
-inline float Vector4::dot(const Vector4& rkVector) const {
- return x*rkVector.x + y*rkVector.y + z*rkVector.z + w*rkVector.w;
-}
-
-//----------------------------------------------------------------------------
-inline Vector4 Vector4::min(const Vector4 &v) const {
- return Vector4(G3D::min(v.x, x), G3D::min(v.y, y), G3D::min(v.z, z), G3D::min(v.w, w));
-}
-
-//----------------------------------------------------------------------------
-inline Vector4 Vector4::max(const Vector4 &v) const {
- return Vector4(G3D::max(v.x, x), G3D::max(v.y, y), G3D::max(v.z, z), G3D::max(v.w, w));
-}
-
-//----------------------------------------------------------------------------
-inline bool Vector4::isZero() const {
- return (x == 0.0f) && (y == 0.0f) && (z == 0.0f) && (w == 0.0f);
-}
-
-//----------------------------------------------------------------------------
-
-inline bool Vector4::isFinite() const {
- return G3D::isFinite(x) && G3D::isFinite(y) && G3D::isFinite(z) && G3D::isFinite(w);
-}
-
-//----------------------------------------------------------------------------
-
-inline bool Vector4::isUnit() const {
- return squaredLength() == 1.0;
-}
-
-//----------------------------------------------------------------------------
-
-inline float Vector4::length() const {
- return sqrtf(squaredLength());
-}
-
-//----------------------------------------------------------------------------
-
-inline float Vector4::squaredLength() const {
- return x * x + y * y + z * z + w * w;
-}
-
-}
-
diff --git a/externals/g3dlite/G3D/Vector4int8.h b/externals/g3dlite/G3D/Vector4int8.h
deleted file mode 100644
index 544b693e8b3..00000000000
--- a/externals/g3dlite/G3D/Vector4int8.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/**
- @file Vector4int8.h
-
- Homogeneous vector class.
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2007-02-09
- @edited 2007-02-09
-
- Copyright 2000-2007, Morgan McGuire.
- All rights reserved.
- */
-
-#ifndef G3D_VECTOR4INT8_H
-#define G3D_VECTOR4INT8_H
-
-#include "G3D/platform.h"
-#include "G3D/g3dmath.h"
-
-namespace G3D {
-
-class Vector3;
-class Vector4;
-
-/**
- Homogeneous vector stored efficiently in four signed int8s.
-
- */
-class Vector4int8 {
-private:
- // Hidden operators
- bool operator<(const Vector4int8&) const;
- bool operator>(const Vector4int8&) const;
- bool operator<=(const Vector4int8&) const;
- bool operator>=(const Vector4int8&) const;
-
-
- /** For fast operations, treat this packed data structure as
- an int32 */
- inline uint32& asInt32() {
- return *reinterpret_cast<uint32*>(this);
- }
-
- inline const uint32& asInt32() const {
- return *reinterpret_cast<const uint32*>(this);
- }
-
-public:
- // construction
- inline Vector4int8() : x(0), y(0), z(0), w(0) {}
-
- /** Multiplies the source by 127 and clamps to (-128, 127) when converting */
- Vector4int8(const Vector4& source);
-
- /** Multiplies the source by 127 and clamps to (-128, 127) when converting */
- Vector4int8(const Vector3& source, int8 w);
-
- inline Vector4int8(int8 x, int8 y, int8 z, int8 w) : x(x), y(y), z(z), w(w) {}
-
- Vector4int8(class BinaryInput& b);
- void serialize(class BinaryOutput& b) const;
- void deserialize(class BinaryInput& b);
-
- // coordinates
- int8 x, y, z, w;
-
- inline operator int8* () {
- return reinterpret_cast<int8*>(this);
- }
-
- inline operator const int8* () const {
- return reinterpret_cast<const int8*>(this);
- }
-
- // access vector V as V[0] = V.x, V[1] = V.y, V[2] = V.z, etc.
- //
- // WARNING. These member functions rely on
- // (1) Vector4int8 not having virtual functions
- // (2) the data packed in a 4*sizeof(int8) memory block
- inline int8& operator[] (int i) {
- debugAssert(i >= 0 && i <= 4);
- return ((int8*)this)[i];
- }
-
- const int8& operator[] (int i) const {
- debugAssert(i >= 0 && i <= 4);
- return ((const int8*)this)[i];
- }
-
- // assignment and comparison
- Vector4int8& operator= (const Vector4int8& other) {
- asInt32() = other.asInt32();
- return *this;
- }
-
- inline bool operator== (const Vector4int8& other) const {
- return asInt32() == other.asInt32();
- }
-
- inline bool operator!= (const Vector4int8& other) const {
- return ! (*this == other);
- }
-
- inline unsigned int hashCode() const {
- return asInt32();
- }
-};
-
-} // namespace G3D
-
-
-#endif
diff --git a/externals/g3dlite/G3D/WeakCache.h b/externals/g3dlite/G3D/WeakCache.h
deleted file mode 100644
index f9fdc4bbd5b..00000000000
--- a/externals/g3dlite/G3D/WeakCache.h
+++ /dev/null
@@ -1,122 +0,0 @@
-/**
- @file WeakCache.h
-
- @maintainer Morgan McGuire, graphics3d.com
-
- @created 2007-05-16
- @edited 2007-05-16
-
- Copyright 2000-2007, Morgan McGuire.
- All rights reserved.
- */
-#ifndef G3D_WEAKCACHE_H
-#define G3D_WEAKCACHE_H
-
-#include "G3D/ReferenceCount.h"
-#include "G3D/Table.h"
-
-namespace G3D {
-
-/**
- A cache that does not prevent its members from being garbage collected.
- Useful to avoid loading or computing an expression twice. Useful
- for memoization and dynamic programming.
-
- Maintains a table of weak pointers. Weak pointers do not prevent
- an object from being garbage collected. If the object is garbage
- collected, the cache removes its reference.
-
- There are no "contains" or "iterate" methods because elements can be
- flushed from the cache at any time if they are garbage collected.
-
- Example:
- <pre>
- WeakCache<std::string, TextureRef> textureCache;
-
- TextureRef loadTexture(std::string s) {
- TextureRef t = textureCache[s];
-
- if (t.isNull()) {
- t = Texture::fromFile(s);
- textureCache.set(s, t);
- }
-
- return t;
- }
-
-
- </pre>
- */
-template<class Key, class ValueRef>
-class WeakCache {
- typedef WeakReferenceCountedPointer<typename ValueRef::element_type> ValueWeakRef;
-
-private:
-
- Table<Key, ValueWeakRef> table;
-
-public:
- /**
- Returns NULL if the object is not in the cache
- */
- ValueRef operator[](const Key& k) {
- if (table.containsKey(k)) {
- ValueWeakRef w = table[k];
- ValueRef s = w.createStrongPtr();
- if (s.isNull()) {
- // This object has been collected; clean out its key
- table.remove(k);
- }
- return s;
- } else {
- return NULL;
- }
- }
-
- void set(const Key& k, ValueRef v) {
- table.set(k, v);
- }
-
- /** Removes k from the cache or does nothing if it is not currently in the cache.*/
- void remove(const Key& k) {
- if (table.containsKey(k)) {
- table.remove(k);
- }
- }
-};
-
-#if 0 // To turn off all WeakCaching
-template<class Key, class ValueRef>
-class WeakCache {
-private:
-
- Table<Key, ValueRef> table;
-
-public:
- /**
- Returns NULL if the object is not in the cache
- */
- ValueRef operator[](const Key& k) {
- if (table.containsKey(k)) {
- return table[k];
- } else {
- return NULL;
- }
- }
-
- void set(const Key& k, ValueRef v) {
- table.set(k, v);
- }
-
- /** Removes k from the cache or does nothing if it is not currently in the cache.*/
- void remove(const Key& k) {
- if (table.containsKey(k)) {
- table.remove(k);
- }
- }
-};
-#endif
-
-}
-#endif
-
diff --git a/externals/g3dlite/G3D/Welder.h b/externals/g3dlite/G3D/Welder.h
deleted file mode 100644
index 2c2554da7b6..00000000000
--- a/externals/g3dlite/G3D/Welder.h
+++ /dev/null
@@ -1,82 +0,0 @@
-#ifndef G3D_Welder_h
-#define G3D_Welder_h
-
-#include "G3D/platform.h"
-#include "G3D/Array.h"
-#include "G3D/Vector3.h"
-#include "G3D/Vector2.h"
-
-namespace G3D {
-
-class Any;
-
-class Welder {
-private:
-
- Welder() {}
-
-public:
-
- class Settings {
- public:
- /** Surfaces with normals that are within this angle of each
- other are considered to be curved. Default value is toRadians(70.0f).*/
- float normalSmoothingAngle;
- float vertexWeldRadius;
- float textureWeldRadius;
- float normalWeldRadius;
-
- inline Settings(float normalSmoothAngle = toRadians(70.0f)) :
- normalSmoothingAngle(normalSmoothAngle),
- vertexWeldRadius(0.0001f),
- textureWeldRadius(0.0001f),
- normalWeldRadius(0.01f) {}
-
-
- Settings(const Any& any);
- operator Any() const;
- };
-
-/**
- Mutates geometry, texCoord, and indexArray so that the output has collocated vertices collapsed (welded).
-
- @param vertices Input and output
- @param textureCoords Input and output
- @param normals Output only
- @param indices Input and output. This is an array of trilist indices.
- @param oldToNewIndex Output argument
- @param normalSmoothingAngle Varies from 0 (flat shading) to toRadians(180) for extremely smooth shading. Default is toRadians(70)
- */
- static void weld(
- Array<Vector3>& vertices,
- Array<Vector2>& textureCoords,
- Array<Vector3>& normals,
- Array<Array<int>*>& indices,
- const Settings& settings);
-
- /**
- Mutates geometry, texCoord, and indexArray so that the output has collocated vertices collapsed (welded).
-
- @param vertices Input and output
- @param textureCoords Input and output
- @param normals Output only
- @param indices Input and output. This is an array of trilist indices.
- @param oldToNewIndex Output argument
- @param normalSmoothingAngle Varies from 0 (flat shading) to toRadians(180) for extremely smooth shading. Default is toRadians(70)
- */
- inline static void weld(
- Array<Vector3>& vertices,
- Array<Vector2>& textureCoords,
- Array<Vector3>& normals,
- Array<int>& indices,
- const Settings& settings) {
-
- Array<Array<int>*> meta;
- meta.append(&indices);
- weld(vertices, textureCoords, normals, meta, settings);
- }
-};
-
-}
-
-#endif
diff --git a/externals/g3dlite/G3D/WrapMode.h b/externals/g3dlite/G3D/WrapMode.h
deleted file mode 100644
index 8ef38a77c23..00000000000
--- a/externals/g3dlite/G3D/WrapMode.h
+++ /dev/null
@@ -1,93 +0,0 @@
-/**
- @file WrapMode.h
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2007-04-17
- @edited 2007-04-17
-
- Copyright 2000-2010, Morgan McGuire.
- All rights reserved.
- */
-
-#ifndef G3D_WrapMode_h
-#define G3D_WrapMode_h
-
-#include "G3D/platform.h"
-#include "G3D/enumclass.h"
-
-#ifdef IGNORE
-# undef IGNORE
-#endif
-#ifdef ZERO
-# undef ZERO
-#endif
-#ifdef ERROR
-# undef ERROR
-#endif
-
-namespace G3D {
-
-/**
- Describes the behavior of G3D::Texture, G3D::Map2D, G3D::Image3,
- etc. when accessing an out-of-bounds pixel. Not all classes support
- all modes.
-
- Refer to these as scoped enums, e.g., <code>WrapMode m = WrapMode::CLAMP;</code>.
-
- WrapMode::IGNORE silently discards attempts to write to out
- of bounds locations and returns an undefined value for reading
- from out of bounds locations.
-
- WrapMode::ERROR generates an error when the
- pixel indices are out of bounds
-
- WrapMode::CLAMP makes out of bounds pixels equal to the last in-range pixel along that dimension.
-
- WrapMode::TILE computes out of bounds pixels modulo the dimension
-
- WrapMode::ZERO treats out of bounds values as the zero value, which varies in definition
- according to the class used. For example, with a G3D::Texture, ZERO = Color4(0,0,0,0).
-
- Uses the "Intelligent Enum" design pattern
- http://www.codeguru.com/cpp/cpp/cpp_mfc/article.php/c4001/
- */
-class WrapMode {
-public:
- /** Don't use this enum; use WrapMode instances instead. */
- enum Value {
- CLAMP,
- TILE,
- ZERO,
- IGNORE,
- ERROR
- };
-
-private:
-
- Value value;
-
-public:
-
- G3D_DECLARE_ENUM_CLASS_METHODS(WrapMode);
-
- inline const char* toString() const {
- static const char* s[] = {"CLAMP", "TILE", "ZERO", "IGNORE", "ERROR"};
- return s[value];
- }
-
- inline explicit WrapMode(const std::string& x) : value(ERROR) {
- static const char* s[] = {"CLAMP", "TILE", "ZERO", "IGNORE", "ERROR"};
- for (int i = 0; i < 5; ++i) {
- if (x == s[i]) {
- value = (Value)i;
- }
- }
- }
-};
-
-} // namespace G3D
-
-G3D_DECLARE_ENUM_CLASS_HASHCODE(G3D::WrapMode);
-
-#endif
diff --git a/externals/g3dlite/G3D/constants.h b/externals/g3dlite/G3D/constants.h
deleted file mode 100644
index dd5cb3649e5..00000000000
--- a/externals/g3dlite/G3D/constants.h
+++ /dev/null
@@ -1,129 +0,0 @@
-/**
- @file G3D/constants.h
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @created 2009-05-20
- @edited 2009-05-20
-*/
-#ifndef G3D_constants_h
-#define G3D_constants_h
-
-#include "G3D/platform.h"
-#include "G3D/enumclass.h"
-
-namespace G3D {
-
-/** These are defined to have the same value as the equivalent OpenGL
- constant. */
-class PrimitiveType {
-public:
- enum Value {
- POINTS = 0x0000,
- LINES = 0x0001,
- LINE_STRIP = 0x0003,
- TRIANGLES = 0x0004,
- TRIANGLE_STRIP = 0x0005,
- TRIANGLE_FAN = 0x0006,
- QUADS = 0x0007,
- QUAD_STRIP = 0x0008
- };
-
-private:
-
- Value value;
-
-public:
-
- G3D_DECLARE_ENUM_CLASS_METHODS(PrimitiveType);
-};
-
-
-/** Values for SuperSurface::GPUGeom::refractionHint. */
-class RefractionQuality {
-public:
- enum Value {
- /** No refraction; a translucent object will appear as if it had the same index of refraction
- as the surrounding medium and objects will be undistorted in the background. */
- NONE = 0,
-
- /** Use a static environment map (cube or paraboloid) for computing transmissivity.*/
- STATIC_ENV = 25,
-
- /** Use a dynamically rendered 2D environment map; distort the background. This looks good for many scenes
- but avoids the cost of rendering a cube map for DYNAMIC_ENV. */
- DYNAMIC_FLAT = 50,
-
- /** Use a dynamically rendered 2D environment map that is re-captured per transparent object. This works well
- for transparent objects that are separated by a significant camera space z distance but overlap in screen space.*/
- DYNAMIC_FLAT_MULTILAYER = 55,
-
- /** Render a dynamic environment map */
- DYNAMIC_ENV = 75,
-
- /** Use the best method available, ideally true ray tracing. */
- BEST = 100
- };
-
-private:
-
- /** Used for to/from string conversion. Last is the emtpy string as a sentinel */
- static const std::string str[7];
- static const Value enm[6];
- Value value;
-
-public:
- G3D_DECLARE_ENUM_CLASS_METHODS(RefractionQuality);
-
- RefractionQuality(const class Any&);
- RefractionQuality& operator=(const Any&);
- operator Any() const;
- const std::string& toString() const;
-};
-
-
-/** Values for SuperSurface::GPUGeom::mirrorHint. */
-class MirrorQuality {
-public:
-
- enum Value {
- /** Reflections are black */
- NONE = 0,
-
- /** Use a static environment map. This is what most games use */
- STATIC_ENV = 25,
-
- /** Planar reflection, typically for water or glass windows. This assumes that the mirror is flat;
- it is distinct from RefractionQuality::DYNAMIC_FLAT, which assumes the <i>background</i> is flat.*/
- DYNAMIC_PLANAR = 50,
-
- /** Render a dynamic environment map. */
- DYNAMIC_ENV = 75,
-
- /** Use the best method available, ideally true ray tracing. */
- BEST = 100
- };
-
-private:
-
- /** Used for to/from string conversion. Last is the emtpy string as a sentinel */
- static const std::string str[6];
- static const Value enm[5];
-
- Value value;
-
-public:
- G3D_DECLARE_ENUM_CLASS_METHODS(MirrorQuality);
- MirrorQuality(const class Any&);
- MirrorQuality& operator=(const Any&);
- operator Any() const;
- const std::string& toString() const;
-};
-
-} // namespace G3D
-
-G3D_DECLARE_ENUM_CLASS_HASHCODE(G3D::PrimitiveType)
-G3D_DECLARE_ENUM_CLASS_HASHCODE(G3D::RefractionQuality)
-G3D_DECLARE_ENUM_CLASS_HASHCODE(G3D::MirrorQuality)
-
-#endif
-
diff --git a/externals/g3dlite/G3D/debug.h b/externals/g3dlite/G3D/debug.h
deleted file mode 100644
index a7697fe9c01..00000000000
--- a/externals/g3dlite/G3D/debug.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/**
- @file debug.h
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2001-08-26
- @edited 2006-02-16
-
- Copyright 2000-2006, Morgan McGuire.
- All rights reserved.
-*/
-
-#ifndef G3D_DEBUG_H
-#define G3D_DEBUG_H
-
-#include "G3D/platform.h"
-#ifdef _MSC_VER
- #include <crtdbg.h>
-#endif
-
-#include "G3D/debugPrintf.h"
-#include "G3D/debugAssert.h"
-
-namespace G3D {
-
-#ifdef _MSC_VER
- // Turn off 64-bit warnings
-# pragma warning(push)
-# pragma warning( disable : 4312)
-# pragma warning( disable : 4267)
-# pragma warning( disable : 4311)
-#endif
-
-
-/**
- Useful for debugging purposes.
- */
-inline bool isValidHeapPointer(const void* x) {
- #ifdef _MSC_VER
- return
- (x != (void*)0xcccccccc) && (x != (void*)0xdeadbeef) && (x != (void*)0xfeeefeee);
- #else
- return x != NULL;
- #endif
-}
-
-/**
- Returns true if the pointer is likely to be
- a valid pointer (instead of an arbitrary number).
- Useful for debugging purposes.
- */
-inline bool isValidPointer(const void* x) {
- #ifdef _MSC_VER
- return x != ((void*)0xcccccccc) && (x != (void*)0xdeadbeef) && (x != (void*)0xfeeefeee);
- #else
- return x != NULL;
- #endif
-}
-
-#ifdef _MSC_VER
-# pragma warning(pop)
-#endif
-
-}
-
-#endif
diff --git a/externals/g3dlite/G3D/debugAssert.h b/externals/g3dlite/G3D/debugAssert.h
deleted file mode 100644
index 432e97e679d..00000000000
--- a/externals/g3dlite/G3D/debugAssert.h
+++ /dev/null
@@ -1,233 +0,0 @@
-/**
- @file debugAssert.h
-
- debugAssert(expression);
- debugAssertM(expression, message);
-
- @cite
- John Robbins, Microsoft Systems Journal Bugslayer Column, Feb 1999.
- <A HREF="http://msdn.microsoft.com/library/periodic/period99/feb99_BUGSLAYE_BUGSLAYE.htm">
- http://msdn.microsoft.com/library/periodic/period99/feb99_BUGSLAYE_BUGSLAYE.htm</A>
-
- @cite
- Douglas Cox, An assert() Replacement, Code of The Day, flipcode, Sept 19, 2000
- <A HREF="http://www.flipcode.com/cgi-bin/msg.cgi?showThread=COTD-AssertReplace&forum=cotd&id=-1">
- http://www.flipcode.com/cgi-bin/msg.cgi?showThread=COTD-AssertReplace&forum=cotd&id=-1</A>
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2001-08-26
- @edited 2006-01-12
-
- Copyright 2000-2006, Morgan McGuire.
- All rights reserved.
- */
-
-#ifndef G3D_DEBUGASSERT_H
-#define G3D_DEBUGASSERT_H
-
-#include <string>
-#include "G3D/platform.h"
-
-#include <cstdlib>
-
-#ifdef _MSC_VER
-// conditional expression is constant
-# pragma warning (disable : 4127)
-#endif
-
-#ifdef G3D_LINUX
- // Needed so we can define a global display
- // pointer for debugAssert.
-#if SOMEONE_MADE_THIS_USEFUL
- #include <X11/Xlib.h>
- #include <X11/Xutil.h>
- #include <X11/Xatom.h>
-#endif
-#endif
-
-
-/**
- @def debugBreak()
-
- Break at the current location (i.e. don't push a procedure stack frame
- before breaking).
- */
-
-/**
- @def debugAssert(exp)
- Breaks if the expression is false. If G3D_DEBUG_NOGUI is defined, prompts at
- the console, otherwise pops up a dialog. The user may then break (debug),
- ignore, or halt the program.
-
- The assertion is also posted to the clipboard under Win32.
- */
-
-/**
- @def debugAssertM(exp, msg)
- Breaks if the expression is false and displays a message. If G3D_DEBUG_NOGUI
- is defined, prompts at the console, otherwise pops up a dialog. The user may
- then break (debug), ignore, or halt the program.
-
- The assertion is also posted to the clipboard under Win32.
- */
-
-/**
- @def alwaysAssertM(exp, msg)
- Same as debugAssertM except that it asserts in release builds as well.
- */
-
-namespace G3D {
-typedef bool (*AssertionHook)(
- const char* _expression,
- const std::string& message,
- const char* filename,
- int lineNumber,
- bool useGuiPrompt);
-
-/**
- Allows customization of the global function invoked when a debugAssert fails.
- The initial value is G3D::_internal::_handleDebugAssert_. G3D will invoke
- rawBreak if the hook returns true. If NULL, assertions are not handled.
-*/
-void setAssertionHook(AssertionHook hook);
-
-AssertionHook assertionHook();
-
-/**
- Called by alwaysAssertM in case of failure in release mode. If returns
- true then the program exits with -1 (you can replace this with your own
- version that throws an exception or has other failure modes).
- */
-void setFailureHook(AssertionHook hook);
-AssertionHook failureHook();
-
-namespace _internal {
- extern AssertionHook _debugHook;
- extern AssertionHook _failureHook;
-} // internal
-} // G3D
-
-/**
- @def __debugPromptShowDialog__
- @internal
- */
-
-#ifdef G3D_DEBUG
-
-# if defined(_MSC_VER)
-# define rawBreak() ::DebugBreak();
-# elif defined(__i386__)
- // gcc on intel
-# define rawBreak() __asm__ __volatile__ ( "int $3" );
-# else
- // some other gcc
-# define rawBreak() ::abort()
-# endif
-
-
-# define debugBreak() G3D::_internal::_releaseInputGrab_(); rawBreak(); G3D::_internal::_restoreInputGrab_();
-# define debugAssert(exp) debugAssertM(exp, "Debug assertion failure")
-
- #ifdef G3D_DEBUG_NOGUI
- #define __debugPromptShowDialog__ false
- #else
- #define __debugPromptShowDialog__ true
- #endif
-
- #define debugAssertM(exp, message) do { \
- if (!(exp)) { \
- G3D::_internal::_releaseInputGrab_(); \
- if ((G3D::_internal::_debugHook != NULL) && \
- G3D::_internal::_debugHook((const char*)(#exp), message, __FILE__, __LINE__, __debugPromptShowDialog__)) { \
- rawBreak(); \
- } \
- G3D::_internal::_restoreInputGrab_(); \
- } \
- } while (0)
-
- #define alwaysAssertM debugAssertM
-
-#else // Release
- #ifdef G3D_DEBUG_NOGUI
- #define __debugPromptShowDialog__ false
- #else
- #define __debugPromptShowDialog__ true
- #endif
-
- // In the release build, just define away assertions.
- #define rawBreak() do {} while (0)
- #define debugAssert(exp) do {} while (0)
- #define debugAssertM(exp, message) do {} while (0)
- #define debugBreak() do {} while (0)
-
- // But keep the 'always' assertions
- #define alwaysAssertM(exp, message) { \
- if (!(exp)) { \
- G3D::_internal::_releaseInputGrab_(); \
- if ((G3D::_internal::_failureHook != NULL) && \
- G3D::_internal::_failureHook(#exp, message, __FILE__, __LINE__, __debugPromptShowDialog__)) { \
- ::exit(-1); \
- } \
- G3D::_internal::_restoreInputGrab_(); \
- } \
- }
-
-#endif // if debug
-
-
-
-namespace G3D { namespace _internal {
-
-#ifdef G3D_LINUX
-#if SOMEONE_MADE_THIS_USEFUL
- /**
- A pointer to the X11 display. Initially NULL. If set to a
- non-null value (e.g. by SDLWindow), debugAssert attempts to use
- this display to release the mouse/input grab when an assertion
- fails.
- */
- extern Display* x11Display;
-
- /**
- A pointer to the X11 window. Initially NULL. If set to a
- non-null value (e.g. by SDLWindow), debugAssert attempts to use
- this window to release the mouse/input grab when an assertion
- fails.
- */
- extern Window x11Window;
-#endif
-#endif
-
-/**
- Pops up an assertion dialog or prints an assertion
-
- ignoreAlways - return result of pressing the ignore button.
- useGuiPrompt - if true, shows a dialog
- */
-bool _handleDebugAssert_(
- const char* expression,
- const std::string& message,
- const char* filename,
- int lineNumber,
- bool useGuiPrompt);
-
-bool _handleErrorCheck_(
- const char* expression,
- const std::string& message,
- const char* filename,
- int lineNumber,
- bool useGuiPrompt);
-
-/** Attempts to give the user back their mouse and keyboard if they
- were locked to the current window.
- @internal*/
-void _releaseInputGrab_();
-
-/** Attempts to restore the state before _releaseInputGrab_.
- @internal*/
-void _restoreInputGrab_();
-
-}; }; // namespace
-
-#endif
diff --git a/externals/g3dlite/G3D/debugPrintf.h b/externals/g3dlite/G3D/debugPrintf.h
deleted file mode 100644
index b42151cae9e..00000000000
--- a/externals/g3dlite/G3D/debugPrintf.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/**
- @file debugPrintf.h
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2001-08-26
- @edited 2007-07-20
-
- Copyright 2000-2007, Morgan McGuire.
- All rights reserved.
- */
-
-#ifndef G3D_DEBUGPRINTF_H
-#define G3D_DEBUGPRINTF_H
-
-#include "G3D/platform.h"
-#include <stdio.h>
-#include <cstdarg>
-#include "G3D/format.h"
-#include <string>
-
-namespace G3D {
-
-typedef void (*ConsolePrintHook)(const std::string&);
-
-namespace _internal {
- extern ConsolePrintHook _consolePrintHook;
-}
-
-/** Called by consolePrintf after the log and terminal have been written to.
- Used by GConsole to intercept printing routines.*/
-void setConsolePrintHook(ConsolePrintHook h);
-
-ConsolePrintHook consolePrintHook();
-
-/**
- Sends output to the log and to the last GConsole instantiated.
-
- Guarantees that the output has been flushed by the time the routine
- returns.
- @sa G3D::logPrintf, G3D::screenPrintf
- @return The string that was printed
- */
-std::string __cdecl consolePrintf(const char* fmt ...) G3D_CHECK_PRINTF_ARGS;
-std::string consolePrint(const std::string&);
-
-/**
- Under visual studio, appears in the VS debug pane.
- On unix-based operating systems the output is sent to stderr.
-
- Also sends output to the console (G3D::consolePrintf) if there is a consolePrintHook,
- and log (G3D::logPrintf), and flushes before returning.
-
- @return The string that was printed
-*/
-std::string __cdecl debugPrintf(const char* fmt ...) G3D_CHECK_PRINTF_ARGS;
-std::string debugPrint(const std::string&);
-
-} // namespace G3D
-
-#endif
-
diff --git a/externals/g3dlite/G3D/enumclass.h b/externals/g3dlite/G3D/enumclass.h
deleted file mode 100644
index c7dfe45f14f..00000000000
--- a/externals/g3dlite/G3D/enumclass.h
+++ /dev/null
@@ -1,147 +0,0 @@
-/**
- @file G3D/enumclass.h
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @created 2007-01-27
- @edited 2007-07-20
-*/
-#ifndef G3D_enumclass_h
-#define G3D_enumclass_h
-
-#include "G3D/HashTrait.h"
-#include "G3D/BinaryInput.h"
-#include "G3D/BinaryOutput.h"
-
-/**
-\def G3D_DECLARE_ENUM_CLASS_METHODS
-
- \brief Creates a series of methods that turn a class into a scoped enumeration.
-
- Uses the "Intelligent Enum" design pattern
- http://www.codeguru.com/cpp/cpp/cpp_mfc/article.php/c4001/
-
- Enum classes are initialized to their zero value by default.
-
- See GLG3D/GKey.h for an example.
- \sa G3D_DECLARE_ENUM_CLASS_HASHCODE
- */
-#define G3D_DECLARE_ENUM_CLASS_METHODS(Classname)\
- inline Classname(char v) : value((Value)v) {}\
-\
- inline Classname() : value((Value)0) {}\
-\
- inline Classname(const Value v) : value(v) {}\
-\
- explicit inline Classname(int v) : value((Value)v) {}\
-\
- /** Support cast back to the Value type, which is needed to allow implicit assignment inside unions. */\
- /*inline operator Value() const {
- return value;
- }*/\
-\
- inline operator int() const {\
- return (int)value;\
- }\
-\
- inline bool operator== (const Classname other) const {\
- return value == other.value;\
- }\
-\
- inline bool operator== (const Classname::Value other) const {\
- return value == other;\
- }\
-\
- inline bool operator!= (const Classname other) const {\
- return value != other.value;\
- }\
-\
- inline bool operator!= (const Classname::Value other) const {\
- return value != other;\
- }\
-\
- inline bool operator< (const Classname other) const {\
- return value < other.value;\
- }\
-\
- inline bool operator> (const Classname other) const {\
- return value > other.value;\
- }\
-\
- inline bool operator>= (const Classname other) const {\
- return value >= other.value;\
- }\
-\
- inline bool operator<= (const Classname other) const {\
- return value <= other.value;\
- }\
-\
- inline bool operator< (const Value other) const {\
- return value < other;\
- }\
-\
- inline bool operator> (const Value other) const {\
- return value > other;\
- }\
-\
- inline bool operator<= (const Value other) const {\
- return value <= other;\
- }\
-\
- inline bool operator>= (const Value other) const {\
- return value >= other;\
- }\
-\
- inline Classname& operator-- () {\
- value = (Value)((int)value - 1);\
- return *this;\
- }\
-\
- inline Classname& operator++ () {\
- value = (Value)((int)value + 1);\
- return *this;\
- }\
-\
- inline Classname& operator+= (const int x) {\
- value = (Value)((int)value + x);\
- return *this;\
- }\
-\
- inline Classname& operator-= (const int x) {\
- value = (Value)((int)value - x);\
- return *this;\
- }\
-\
- inline Classname operator+ (const int x) const {\
- return Classname((int)value + x);\
- }\
-\
- inline Classname operator- (const int x) const {\
- return Classname((int)value - x);\
- }\
-\
- inline unsigned int hashCode() const {\
- return (unsigned int)value;\
- }\
-\
- inline void serialize(BinaryOutput& b) const {\
- b.writeInt32(value);\
- }\
-\
- inline void deserialize(BinaryInput& b) {\
- value = (Value)b.readInt32();\
- }
-
-/** \def G3D_DECLARE_ENUM_CLASS_HASHCODE
-*/
-#define G3D_DECLARE_ENUM_CLASS_HASHCODE(Classname)\
-template <> struct HashTrait<Classname::Value> \
-{ \
- static size_t hashCode(Classname::Value key) { return static_cast<size_t>(key); } \
-}; \
- \
-template <> struct HashTrait<Classname> \
-{ \
- static size_t hashCode(Classname key) { return static_cast<size_t>(key.hashCode()); } \
-};
-
-#endif
diff --git a/externals/g3dlite/G3D/fileutils.h b/externals/g3dlite/G3D/fileutils.h
deleted file mode 100644
index 9e49777d93a..00000000000
--- a/externals/g3dlite/G3D/fileutils.h
+++ /dev/null
@@ -1,254 +0,0 @@
-/**
- @file fileutils.h
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @author 2002-06-06
- @edited 2010-02-06
-
- Copyright 2000-2010, Morgan McGuire.
- All rights reserved.
- */
-
-#ifndef G3D_fileUtils_h
-#define G3D_fileUtils_h
-
-#include "G3D/platform.h"
-#include <string>
-#include <stdio.h>
-#include "G3D/Array.h"
-#include "G3D/Set.h"
-#include "G3D/g3dmath.h"
-
-#ifdef G3D_WIN32
-// For chdir, mkdir, etc.
-# include <direct.h>
-#endif
-
-namespace G3D {
-
- namespace _internal {
- extern Set<std::string> currentFilesUsed;
- }
-
-/** Returns all the files used by G3D and GLG3D during the current execution. */
-Array<std::string> filesUsed();
-
-std::string readWholeFile(
- const std::string& filename);
-
-
-/** Reads from a zip file and decompresses the desired contents
- into memory. Does not support recursive zip calls (i.e. a .zip
- stored within another .zip)
-
- @param file the path, of the format C:\\...\\something.zip\\...\\desiredfile.ext
- @param data a pointer to the memory where the file will be stored
- @param length the size of the file decompressed to memory */
-void zipRead(const std::string& file,
- void*& data,
- size_t& length);
-
-
-/** Closes the contents of a zip file that had been decompressed to
- memory. Must be called in tandem with zipRead() to avoid memory
- leaks.
-
- @param data the pointer to the decompressed file in memory */
-void zipClose(void* data);
-
-
-/**
- @param flush If true (default), the file is ready for reading as soon
- as the function returns. If false, the function returns immediately and
- writes the file in the background.
- */
-void writeWholeFile(
- const std::string& filename,
- const std::string& str,
- bool flush = true);
-
-/**
- Creates the directory (which may optionally end in a /)
- and any parents needed to reach it.
- */
-void createDirectory(
- const std::string& dir);
-
-/**
- Fully qualifies a filename. The filename may contain wildcards,
- in which case the wildcards will be preserved in the returned value.
- */
-std::string resolveFilename(const std::string& filename);
-
-/**
- Appends all files matching filespec to the files array. The names
- will not contain paths unless includePath == true. These may be
- relative to the current directory unless the filespec is fully qualified
- (can be done with resolveFilename).
- Wildcards can only appear to the right of the last slash in filespec.
- Works with .zip files used as paths, if filespec is passed in the form
- C:\\...\\something.zip\\* Does not work recursively with zipfiles (a
- .zip within a .zip will not work)
- */
-void getFiles(
- const std::string& filespec,
- Array<std::string>& files,
- bool includePath = false);
-
-/**
- Appends all directories matching filespec to the files array. The names
- will not contain paths unless includePath == true. These may be
- relative to the current directory unless the filespec is fully qualified
- (can be done with resolveFilename).
- Does not append special directories "." or "..".
- Works with .zip files used as paths, if filespec is passed in the form
- C:\\...\\something.zip\\* Does not work recursively with zipfiles (a
- .zip within a .zip will not work)
- */
-void getDirs(
- const std::string& filespec,
- Array<std::string>& files,
- bool includePath = false);
-
-
-/** Returns true if the specified path exists and is a directory */
-bool isDirectory(const std::string& filespec);
-
-
-/** Returns true if the specified filename exists and is a zipfile */
-bool isZipfile(const std::string& filename);
-
-
-/** Returns the length of the file. If
- filename specifies a path that contains a zipfile, but the
- contents within are specified correctly, returns the
- uncompressed size of the requested file. Returns -1 if
- the file does not exist.
-
- @param filename the path to test, may contain .zip
-*/
-int64 fileLength(const std::string& filename);
-
-/**
- Copies the file
- */
-void copyFile(
- const std::string& source,
- const std::string& dest);
-
-/** Returns a temporary file that is open for read/write access. This
- tries harder than the ANSI tmpfile, so it may succeed when that fails. */
-FILE* createTempFile();
-
-/**
- Returns true if the given file (or directory) exists.
-
- \param filename the path to test. must not end in a trailing slash.
- \param lookInZipfiles if the path does not exist, calls zipfileExists()
- \param trustCache If true and \a lookInZipfiles is true, cache directory and zipfile contents
- so that subsequent calls to the same directory are fast.
-
- \sa G3D::clearFileSystemCache, G3D::zipfileExists
- */
-bool fileExists
-(const std::string& filename,
- bool lookInZipfiles = true,
- bool trustCache = true);
-
-
-/** Clears the cache used by fileExists */
-void clearFileSystemCache();
-
-/**
- Returns true if the given file (or directory) exists
- within a zipfile. Called if fileExists initially
- returns false and the lookInZipfiles flag has been set.
- Must not end in a trailing slash. Does not work for recursive
- zipfiles (.zips within another .zip)
-
- @param filename the path to test
- @param outZipfile the path to the .zip file
- @param outInternalFile the path (within the .zip) where the desired file is located, if valid
-
- */
-bool zipfileExists
-(const std::string& filename,
- std::string& outZipfile,
- std::string& outInternalFile);
-
-bool zipfileExists(const std::string& filename);
-
-/**
- Parses a filename into four useful pieces.
-
- Examples:
-
- c:\\a\\b\\d.e
- root = "c:\\"
- path = "a" "b"
- base = "d"
- ext = "e"
-
- /a/b/d.e
- root = "/"
- path = "a" "b"
- base = "d"
- ext = "e"
-
- /a/b
- root = "/"
- path = "a"
- base = "b"
- ext = "e"
-
- */
-void parseFilename(
- const std::string& filename,
- std::string& drive,
- Array<std::string>& path,
- std::string& base,
- std::string& ext);
-
-
-/**
- Returns the part of the filename that includes the base and ext from
- parseFilename (i.e. everything to the right of the path).
- */
-std::string filenameBaseExt(const std::string& filename);
-
-/**
- Returns the extension on a filename.
- */
-std::string filenameExt(const std::string& filename);
-
-
-/** Returns the portion of a filename to the left of the last period
- and to the right of the last slash or colon.
- */
-std::string filenameBase(const std::string& filename);
-
-/** Creates a unique filename base in the current directory using the
- specified prefix and suffix.*/
-std::string generateFilenameBase(const std::string& prefix = "", const std::string& suffix = "");
-
-/**
- Returns the drive (if Win32) and path from a filename, including
- a slash if there was one.
- <CODE>filenamePath(f) + filenameBaseExt(f) == f</CODE>
- */
-std::string filenamePath(const std::string& filename);
-
-/** Returns true if '*' or '?' appears in the string */
-bool filenameContainsWildcards(const std::string& filename);
-
-/** Returns true if dst does not exist or src is newer than dst. Works on both files and directories. */
-bool fileIsNewer(const std::string& src, const std::string& dst);
-
-/** Appends file onto dirname, ensuring a / if needed. */
-std::string pathConcat(const std::string& dirname, const std::string& file);
-
-} // namespace
-
-#endif
-
diff --git a/externals/g3dlite/G3D/filter.h b/externals/g3dlite/G3D/filter.h
deleted file mode 100644
index 609477b79c9..00000000000
--- a/externals/g3dlite/G3D/filter.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/**
- @file G3D/filter.h
-
- @author Morgan McGuire, http://graphics.cs.williams.edu
- @created 2007-03-01
- @edited 2007-03-01
-
- Copyright 2000-2007, Morgan McGuire.
- All rights reserved.
- */
-#ifndef G3D_FILTER_H
-#define G3D_FILTER_H
-
-#include "G3D/platform.h"
-#include "G3D/Array.h"
-#include "G3D/g3dmath.h"
-
-namespace G3D {
-/**
- Generates a set of 1D gaussian filter coefficients of size N. The coefficients
- are centered on element (N-1)/2 and have standard deviation given by std. The coefficients
- are normalized such that the sum across coeff is 1.0.
-
- Matches the results returned by Matlab <code>fspecial('gaussian', [1, N], std)</code>
- */
-void gaussian1D(Array<float>& coeff, int N = 5, float std = 0.5f);
-}
-
-#endif
diff --git a/externals/g3dlite/G3D/format.h b/externals/g3dlite/G3D/format.h
deleted file mode 100644
index 3c7f0678876..00000000000
--- a/externals/g3dlite/G3D/format.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/**
- @file format.h
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @author 2000-09-09
- @edited 2005-11-03
-
- Copyright 2000-2005, Morgan McGuire.
- All rights reserved.
- */
-
-#ifndef G3D_FORMAT_H
-#define G3D_FORMAT_H
-
-#include "G3D/platform.h"
-#include <string>
-#include <stdio.h>
-#include <cstdarg>
-
-namespace G3D {
-
-/**
- Produces a string from arguments of the style of printf. This avoids
- problems with buffer overflows when using sprintf and makes it easy
- to use the result functionally. This function is fast when the resulting
- string is under 160 characters (not including terminator) and slower
- when the string is longer.
- */
-std::string __cdecl format(
- const char* fmt
- ...) G3D_CHECK_PRINTF_ARGS;
-
-/**
- Like format, but can be called with the argument list from a ... function.
- */
-std::string vformat(
- const char* fmt,
- va_list argPtr) G3D_CHECK_VPRINTF_ARGS;
-
-
-} // namespace
-
-#endif
diff --git a/externals/g3dlite/G3D/g3dfnmatch.h b/externals/g3dlite/G3D/g3dfnmatch.h
deleted file mode 100644
index 464b3927eee..00000000000
--- a/externals/g3dlite/G3D/g3dfnmatch.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*-
- * Copyright (c) 1992, 1993
- *The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- *This product includes software developed by the University of
- *California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- *@(#)fnmatch.h8.1 (Berkeley) 6/2/93
- *
- * From FreeBSD fnmatch.h 1.7
- * $Id: g3dfnmatch.h,v 1.1 2010/02/06 06:51:28 morgan3d Exp $
- */
-#ifndef G3D_g3dfnmatch_h
-#define G3D_g3dfnmatch_h
-
-#include "G3D/platform.h"
-
-namespace G3D {
-
-#if defined(G3D_WIN32)
-
-# if ! defined(FNM_NOMATCH)
-# define FNM_NOMATCH 1 /* Match failed. */
-# define FNM_NOESCAPE 0x01 /* Disable backslash escaping. */
-# define FNM_PATHNAME 0x02 /* Slash must be matched by slash. */
-# define FNM_PERIOD 0x04 /* Period must be matched by period. */
-# define FNM_LEADING_DIR 0x08 /* Ignore /<tail> after Imatch. */
-# define FNM_CASEFOLD 0x10 /* Case insensitive search. */
-# define FNM_PREFIX_DIRS 0x20 /* Directory prefixes of pattern match too. */
-# endif
-
-#else
-
- // On non-windows systems, include fnmatch directly
-# include <fnmatch.h>
-#endif
-
-
-/**
- Function fnmatch() as specified in POSIX 1003.2-1992, section B.6.
- Compares a filename or pathname to a pattern.
-
-The fnmatch() function checks whether the string argument matches the pattern argument, which is a shell wildcard pattern.
-The flags argument modifies the behaviour; it is the bitwise OR of zero or more of the following flags:
-
-- FNM_NOESCAPE If this flag is set, treat backslash as an ordinary character, instead of an escape character.
-- FNM_PATHNAME If this flag is set, match a slash in string only with a slash in pattern and not by an asterisk (*) or a question mark (?) metacharacter, nor by a bracket expression ([]) containing a slash.
-- FNM_PERIOD If this flag is set, a leading period in string has to be matched exactly by a period in pattern. A period is considered to be leading if it is the first character in string, or if both FNM_PATHNAME is set and the period immediately follows a slash.
-- FNM_FILE_NAME This is a GNU synonym for FNM_PATHNAME.
-- FNM_LEADING_DIR If this flag (a GNU extension) is set, the pattern is considered to be matched if it matches an initial segment of string which is followed by a slash. This flag is mainly for the internal use of glibc and is only implemented in certain cases.
-- FNM_CASEFOLD If this flag (a GNU extension) is set, the pattern is matched case-insensitively.
-
-\return Zero if \a string matches \a pattern, FNM_NOMATCH if there is no match or another non-zero value if there is an error
-
- */
-int g3dfnmatch(const char *pattern, const char *string, int flags);
-}
-#endif
diff --git a/externals/g3dlite/G3D/g3dmath.h b/externals/g3dlite/G3D/g3dmath.h
deleted file mode 100644
index d16214ebb37..00000000000
--- a/externals/g3dlite/G3D/g3dmath.h
+++ /dev/null
@@ -1,845 +0,0 @@
-/**
- @file g3dmath.h
-
- Math util class.
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @cite highestBit by Jukka Liimatta
-
- @created 2001-06-02
- @edited 2009-04-07
-
- Copyright 2000-2006, Morgan McGuire.
- All rights reserved.
- */
-
-#ifndef G3D_g3dmath_h
-#define G3D_g3dmath_h
-
-#ifdef _MSC_VER
-// Disable conditional expression is constant, which occurs incorrectly on inlined functions
-# pragma warning (push)
-# pragma warning (disable : 4127)
-// disable: "C++ exception handler used"
-# pragma warning (disable : 4530)
-#endif
-
-#include "G3D/platform.h"
-#include <ctype.h>
-#include <float.h>
-#include <limits>
-#include <stdlib.h>
-
-#ifdef _MSC_VER
- // Visual Studio is missing inttypes.h
-# ifndef PRId64
-# define PRId64 "I64d"
-# endif
-#else
-#include <inttypes.h>
-#endif
-
-/*These defines enable functionality introduced with the 1999 ISO C
-**standard. They must be defined before the inclusion of math.h to
-**engage them. If optimisation is enabled, these functions will be
-**inlined. With optimisation switched off, you have to link in the
-**maths library using -lm.
-*/
-
-#define _ISOC9X_SOURCE1
-#define _ISOC99_SOURCE1
-#define __USE_ISOC9X1
-#define __USE_ISOC991
-
-#include <math.h>
-
-#include "G3D/debug.h"
-
-#undef min
-#undef max
-
-namespace G3D {
-
-#ifdef _MSC_VER
-inline double __fastcall drand48() {
- return ::rand() / double(RAND_MAX);
-}
-
-#if !defined(_WIN64)
-
-/**
- Win32 implementation of the C99 fast rounding routines.
-
- @cite routines are
- Copyright (C) 2001 Erik de Castro Lopo <erikd AT mega-nerd DOT com>
-
- Permission to use, copy, modify, distribute, and sell this file for any
- purpose is hereby granted without fee, provided that the above copyright
- and this permission notice appear in all copies. No representations are
- made about the suitability of this software for any purpose. It is
- provided "as is" without express or implied warranty.
-*/
-
-__inline long int lrint (double flt) {
- int intgr;
-
- _asm {
- fld flt
- fistp intgr
- };
-
- return intgr;
-}
-
-__inline long int lrintf(float flt) {
- int intgr;
-
- _asm {
- fld flt
- fistp intgr
- };
-
- return intgr;
-}
-
-#else
-
- __inline long int lrint (double flt) {
- return (long int)floor(flt+0.5f);
- }
-
- __inline long int lrintf(float flt) {
- return (long int)floorf(flt+0.5f);
- }
-
-#endif
-
-#endif
-
-
-#define fuzzyEpsilon (0.00001f)
-/**
- This value should not be tested against directly, instead
- G3D::isNan() and G3D::isFinite() will return reliable results. */
-double inf();
-
-/** This value should not be tested against directly, instead
- G3D::isNan() and G3D::isFinite() will return reliable results. */
-double nan();
-
-float finf();
-
-float fnan();
-
-inline double pi() {
- return 3.1415926535898;
-}
-
-inline double halfPi() {
- return 1.57079633;
-}
-
-inline double twoPi() {
- return 6.28318531;
-}
-
-typedef signed char int8;
-typedef unsigned char uint8;
-typedef short int16;
-typedef unsigned short uint16;
-typedef int int32;
-typedef unsigned int uint32;
-
-#ifdef _MSC_EXTENSIONS
- typedef __int64 int64;
- typedef unsigned __int64 uint64;
-#elif ! defined(_MSC_VER)
- typedef int64_t int64;
- typedef uint64_t uint64;
-#else
- typedef long long int64;
- typedef unsigned long long uint64;
-#endif
-
-typedef float float32;
-typedef double float64;
-
-int iAbs(int iValue);
-int iCeil(double fValue);
-
-/**
- Clamps the value to the range [low, hi] (inclusive)
- */
-int iClamp(int val, int low, int hi);
-int16 iClamp(int16 val, int16 low, int16 hi);
-double clamp(double val, double low, double hi);
-float clamp(float val, float low, float hi);
-
-/**
- Returns a + (b - a) * f;
- */
-inline double lerp(double a, double b, double f) {
- return a + (b - a) * f;
-}
-
-inline float lerp(float a, float b, float f) {
- return a + (b - a) * f;
-}
-
-/**
- Wraps the value to the range [0, hi) (exclusive
- on the high end). This is like the clock arithmetic
- produced by % (modulo) except the result is guaranteed
- to be positive.
- */
-int iWrap(int val, int hi);
-
-int iFloor(double fValue);
-
-int iSign(int iValue);
-int iSign(double fValue);
-
-inline int iSign(float f) {
- return iSign((double)f);
-}
-
-
-/**
- Fast round to integer using the lrint routine.
- Typically 6x faster than casting to integer.
- */
-inline int iRound(double fValue) {
- return lrint(fValue);
-}
-
-/**
- Fast round to integer using the lrint routine.
- Typically 6x faster than casting to integer.
- */
-inline int iRound(float f) {
- return lrintf(f);
-}
-
-/**
- Returns a random number uniformly at random between low and hi
- (inclusive).
- @deprecated Use Random::integer
- */
-int iRandom(int low, int hi);
-
-double abs (double fValue);
-double aCos (double fValue);
-double aSin (double fValue);
-double aTan (double fValue);
-double aTan2 (double fY, double fX);
-double sign (double fValue);
-double square (double fValue);
-
-/**
- Returns true if the argument is a finite real number.
- */
-bool isFinite(double x);
-
-/**
- Returns true if the argument is NaN (not a number).
- You can't use x == nan to test this because all
- comparisons against nan return false.
- */
-bool isNaN(double x);
-bool isNaN(float x);
-inline bool isNaN(int x) {
- (void)x;
- return false;
-}
-
-/**
- Computes x % 3.
- */
-int iMod3(int x);
-
-/**
- Uniform random number between low and hi, inclusive. [low, hi]
- @deprecated
- @sa Random::uniform
- */
-float uniformRandom(float low = 0.0f, float hi = 1.0f);
-
-/**
- Normally distributed random number.
-
- @deprecated
- @sa Random::gaussian
- */
-float gaussRandom(float mean = 0.0f, float stdev = 1.0f);
-
-
-/** Returns x<sup>5</sup> */
-template <class T>
-inline T pow5(T x) {
- const T y = x * x;
- return y * y * x;
-}
-
-
-template <class T>
-inline T min(const T& x, const T& y) {
- return std::min<T>(x, y);
-}
-
-template <class T>
-inline T min(const T& x, const T& y, const T& z) {
- return std::min<T>(std::min<T>(x, y), z);
-}
-
-template <class T>
-inline T min(const T& x, const T& y, const T& z, const T& w) {
- return std::min<T>(std::min<T>(x, y), std::min<T>(z, w));
-}
-
-template <class T>
-inline T max(const T& x, const T& y) {
- return std::max<T>(x, y);
-}
-
-template <class T>
-inline T max(const T& x, const T& y, const T& z) {
- return std::max<T>(std::max<T>(x, y), z);
-}
-
-template <class T>
-inline T max(const T& x, const T& y, const T& z, const T& w) {
- return std::max<T>(std::max<T>(x, y), std::max<T>(z, w));
-}
-
-int iMin(int x, int y);
-int iMax(int x, int y);
-
-double square(double x);
-double sumSquares(double x, double y);
-double sumSquares(double x, double y, double z);
-double distance(double x, double y);
-double distance(double x, double y, double z);
-
-/**
- Returnes the 0-based index of the highest 1 bit from
- the left. -1 means the number was 0.
-
- @cite Based on code by jukka@liimatta.org
- */
-int highestBit(uint32 x);
-
-/**
- Note that fuzzyEq(a, b) && fuzzyEq(b, c) does not imply
- fuzzyEq(a, c), although that will be the case on some
- occasions.
- */
-bool fuzzyEq(double a, double b);
-
-/** True if a is definitely not equal to b.
- Guaranteed false if a == b.
- Possibly false when a != b.*/
-bool fuzzyNe(double a, double b);
-
-/** Is a strictly greater than b? (Guaranteed false if a <= b).
- (Possibly false if a > b) */
-bool fuzzyGt(double a, double b);
-
-/** Is a near or greater than b? */
-bool fuzzyGe(double a, double b);
-
-/** Is a strictly less than b? (Guaranteed false if a >= b)*/
-bool fuzzyLt(double a, double b);
-
-/** Is a near or less than b? */
-bool fuzzyLe(double a, double b);
-
-/**
- Computes 1 / sqrt(x).
- */
-inline float rsq(float x) {
- return 1.0f / sqrtf(x);
-}
-
-/**
- Return the next power of 2 higher than the input
- If the input is already a power of 2, the output will be the same
- as the input.
- */
-int ceilPow2(unsigned int in);
-
-/** Returns 2^x */
-inline int pow2(unsigned int x) {
- return 1 << x;
-}
-
-inline double log2(double x) {
- return ::log(x) * 1.442695;
-}
-
-inline float log2(float x) {
- return ::logf(x) * 1.442695f;
-}
-
-inline double log2(int x) {
- return log2((double)x);
-}
-
-
-/**
- * True if num is a power of two.
- */
-bool isPow2(int num);
-
-bool isOdd(int num);
-bool isEven(int num);
-
-double toRadians(double deg);
-double toDegrees(double rad);
-
-/**
- Returns true if x is not exactly equal to 0.0f.
- */
-inline bool any(float x) {
- return x != 0;
-}
-
-/**
- Returns true if x is not exactly equal to 0.0f.
- */
-inline bool all(float x) {
- return x != 0;
-}
-
-/**
- v / v (for DirectX/Cg support)
- */
-inline float normalize(float v) {
- return v / v;
-}
-
-/**
- a * b (for DirectX/Cg support)
- */
-inline float dot(float a, float b) {
- return a * b;
-}
-
-
-/**
- a * b (for DirectX/Cg support)
- */
-inline float mul(float a, float b) {
- return a * b;
-}
-
-/**
- 2^x
- */
-inline double exp2(double x) {
- return pow(2.0, x);
-}
-
-inline float exp2(float x) {
- return powf(2.0f, x);
-}
-
-/** @deprecated Use rsq */
-inline double rsqrt(double x) {
- return 1.0 / sqrt(x);
-}
-
-/** @deprecated Use rsq */
-inline float rsqrt(float x) {
- // TODO: default this to using the SSE2 instruction
- return 1.0 / sqrtf(x);
-}
-
-/**
- sin(x)/x
- */
-inline double sinc(double x) {
- double r = sin(x) / x;
-
- if (isNaN(r)) {
- return 1.0;
- } else {
- return r;
- }
-}
-
-/**
- Computes a floating point modulo; the result is t wrapped to the range [lo, hi).
- */
-inline float wrap(float t, float lo, float hi) {
- if ((t >= lo) && (t < hi)) {
- return t;
- }
-
- debugAssert(hi > lo);
-
- float interval = hi - lo;
-
- return t - interval * iFloor((t - lo) / interval);
-}
-
-
-inline double wrap(double t, double lo, double hi) {
- if ((t >= lo) && (t < hi)) {
- return t;
- }
-
- debugAssert(hi > lo);
-
- double interval = hi - lo;
-
- return t - interval * iFloor((t - lo) / interval);
-}
-
-inline double wrap(double t, double hi) {
- return wrap(t, 0.0, hi);
-}
-
-
-inline bool isFinite(double x) {
- return ! isNaN(x) && (x < G3D::inf()) && (x > -G3D::inf());
-}
-
-inline bool isFinite(float x) {
- return ! isNaN(x) && (x < G3D::finf()) && (x > -G3D::finf());
-}
-
-//----------------------------------------------------------------------------
-inline int iAbs (int iValue) {
- return ( iValue >= 0 ? iValue : -iValue );
-}
-
-//----------------------------------------------------------------------------
-inline int iCeil (double fValue) {
- return int(::ceil(fValue));
-}
-
-//----------------------------------------------------------------------------
-
-inline int iClamp(int val, int low, int hi) {
- debugAssert(low <= hi);
- if (val <= low) {
- return low;
- } else if (val >= hi) {
- return hi;
- } else {
- return val;
- }
-}
-
-//----------------------------------------------------------------------------
-
-inline int16 iClamp(int16 val, int16 low, int16 hi) {
- debugAssert(low <= hi);
- if (val <= low) {
- return low;
- } else if (val >= hi) {
- return hi;
- } else {
- return val;
- }
-}
-
-//----------------------------------------------------------------------------
-
-inline double clamp(double val, double low, double hi) {
- debugAssert(low <= hi);
- if (val <= low) {
- return low;
- } else if (val >= hi) {
- return hi;
- } else {
- return val;
- }
-}
-
-inline float clamp(float val, float low, float hi) {
- debugAssert(low <= hi);
- if (val <= low) {
- return low;
- } else if (val >= hi) {
- return hi;
- } else {
- return val;
- }
-}
-//----------------------------------------------------------------------------
-
-inline int iWrap(int val, int hi) {
- if (val < 0) {
- return ((val % hi) + hi) % hi;
- } else {
- return val % hi;
- }
-}
-
-//----------------------------------------------------------------------------
-inline int iFloor (double fValue) {
- return int(::floor(fValue));
-}
-
-//----------------------------------------------------------------------------
-inline int iSign (int iValue) {
- return ( iValue > 0 ? + 1 : ( iValue < 0 ? -1 : 0 ) );
-}
-
-inline int iSign (double fValue) {
- return ( fValue > 0.0 ? + 1 : ( fValue < 0.0 ? -1 : 0 ) );
-}
-
-//----------------------------------------------------------------------------
-inline double abs (double fValue) {
- return double(::fabs(fValue));
-}
-
-//----------------------------------------------------------------------------
-inline double aCos (double fValue) {
- if ( -1.0 < fValue ) {
- if ( fValue < 1.0 )
- return double(::acos(fValue));
- else
- return 0.0;
- } else {
- return pi();
- }
-}
-
-//----------------------------------------------------------------------------
-inline double aSin (double fValue) {
- if ( -1.0 < fValue ) {
- if ( fValue < 1.0 ) {
- return double(::asin(fValue));
- } else {
- return -halfPi();
- }
- } else {
- return halfPi();
- }
-}
-
-//----------------------------------------------------------------------------
-inline double aTan (double fValue) {
- return double(::atan(fValue));
-}
-
-//----------------------------------------------------------------------------
-inline double aTan2 (double fY, double fX) {
- return double(::atan2(fY, fX));
-}
-
-//----------------------------------------------------------------------------
-inline double sign (double fValue) {
- if (fValue > 0.0) {
- return 1.0;
- }
-
- if (fValue < 0.0) {
- return -1.0;
- }
-
- return 0.0;
-}
-
-inline float sign (float fValue) {
- if (fValue > 0.0f) {
- return 1.0f;
- }
-
- if (fValue < 0.0f) {
- return -1.0f;
- }
-
- return 0.0f;
-}
-
-
-inline float uniformRandom(float low, float hi) {
- return (hi - low) * float(::rand()) / float(RAND_MAX) + low;
-}
-
-inline double square(double x) {
- return x * x;
-}
-
-inline float square(float x) {
- return x * x;
-}
-
-inline int square(int x) {
- return x * x;
-}
-
-//----------------------------------------------------------------------------
-inline double sumSquares(double x, double y) {
- return x*x + y*y;
-}
-
-//----------------------------------------------------------------------------
-inline float sumSquares(float x, float y) {
- return x*x + y*y;
-}
-
-//----------------------------------------------------------------------------
-inline double sumSquares(double x, double y, double z) {
- return x*x + y*y + z*z;
-}
-
-//----------------------------------------------------------------------------
-inline float sumSquares(float x, float y, float z) {
- return x*x + y*y + z*z;
-}
-
-//----------------------------------------------------------------------------
-inline double distance(double x, double y) {
- return sqrt(sumSquares(x, y));
-}
-
-//----------------------------------------------------------------------------
-inline float distance(float x, float y) {
- return sqrt(sumSquares(x, y));
-}
-
-//----------------------------------------------------------------------------
-inline double distance(double x, double y, double z) {
- return sqrt(sumSquares(x, y, z));
-}
-
-//----------------------------------------------------------------------------
-inline float distance(float x, float y, float z) {
- return sqrt(sumSquares(x, y, z));
-}
-
-//----------------------------------------------------------------------------
-
-/** @deprecated use G3D::min */
-inline int iMin(int x, int y) {
- return (x >= y) ? y : x;
-}
-
-//----------------------------------------------------------------------------
-/** @deprecated use G3D::min */
-inline int iMax(int x, int y) {
- return (x >= y) ? x : y;
-}
-
-//----------------------------------------------------------------------------
-inline int ceilPow2(unsigned int in) {
- in -= 1;
-
- in |= in >> 16;
- in |= in >> 8;
- in |= in >> 4;
- in |= in >> 2;
- in |= in >> 1;
-
- return in + 1;
-}
-
-inline bool isPow2(int num) {
- return ((num & -num) == num);
-}
-
-inline bool isOdd(int num) {
- return (num & 1) == 1;
-}
-
-inline bool isEven(int num) {
- return (num & 1) == 0;
-}
-
-inline double toRadians(double deg) {
- return deg * pi() / 180.0;
-}
-
-inline double toDegrees(double rad) {
- return rad * 180.0 / pi();
-}
-
-inline float toRadians(float deg) {
- return deg * (float)pi() / 180.0f;
-}
-
-inline float toDegrees(float rad) {
- return rad * 180.0f / (float)pi();
-}
-
-inline float toRadians(int deg) {
- return deg * (float)pi() / 180.0f;
-}
-
-inline float toDegrees(int rad) {
- return rad * 180.0f / (float)pi();
-}
-/**
- Computes an appropriate epsilon for comparing a and b.
- */
-inline double eps(double a, double b) {
- // For a and b to be nearly equal, they must have nearly
- // the same magnitude. This means that we can ignore b
- // since it either has the same magnitude or the comparison
- // will fail anyway.
- (void)b;
- const double aa = abs(a) + 1.0;
- if (aa == inf()) {
- return fuzzyEpsilon;
- } else {
- return fuzzyEpsilon * aa;
- }
-}
-
-inline bool fuzzyEq(double a, double b) {
- return (a == b) || (abs(a - b) <= eps(a, b));
-}
-
-inline bool fuzzyNe(double a, double b) {
- return ! fuzzyEq(a, b);
-}
-
-inline bool fuzzyGt(double a, double b) {
- return a > b + eps(a, b);
-}
-
-inline bool fuzzyGe(double a, double b) {
- return a > b - eps(a, b);
-}
-
-inline bool fuzzyLt(double a, double b) {
- return a < b - eps(a, b);
-}
-
-inline bool fuzzyLe(double a, double b) {
- return a < b + eps(a, b);
-}
-
-inline int iMod3(int x) {
- return x % 3;
-}
-
-/**
- Given a 32-bit integer, returns the integer with the bytes in the opposite order.
- */
-inline uint32 flipEndian32(const uint32 x) {
- return (x << 24) | ((x & 0xFF00) << 8) |
- ((x & 0xFF0000) >> 8) | ((x & 0xFF000000) >> 24);
-}
-
-/**
- Given a 16-bit integer, returns the integer with the bytes in the opposite order.
- */
-inline uint16 flipEndian16(const uint16 x) {
- return (x << 8) | ((x & 0xFF00) >> 8);
-}
-
-
-} // namespace
-
-#ifdef _MSC_VER
-# pragma warning (pop)
-#endif
-
-#endif
-
diff --git a/externals/g3dlite/G3D/g3dmath.inl b/externals/g3dlite/G3D/g3dmath.inl
deleted file mode 100644
index 9bf661a7ebc..00000000000
--- a/externals/g3dlite/G3D/g3dmath.inl
+++ /dev/null
@@ -1,288 +0,0 @@
-/**
- @file g3dmath.inl
-
- @maintainer Morgan McGuire, matrix@graphics3d.com
-
- @created 2001-06-02
- @edited 2006-01-14
- */
-
-#include <stdlib.h>
-
-#ifdef _MSC_VER
-// Disable conditional expression is constant, which occurs incorrectly on inlined functions
-# pragma warning (push)
-# pragma warning( disable : 4127 )
-#endif
-
-namespace G3D {
-
-inline bool isNaN(double x) {
- bool b1 = (x < 0.0);
- bool b2 = (x >= 0.0);
- bool b3 = !(b1 || b2);
- return b3;
-}
-
-inline bool isFinite(double x) {
- return ! isNaN(x) && (x < G3D::inf()) && (x > -G3D::inf());
-}
-
-//----------------------------------------------------------------------------
-inline int iAbs (int iValue) {
- return ( iValue >= 0 ? iValue : -iValue );
-}
-
-//----------------------------------------------------------------------------
-inline int iCeil (double fValue) {
- return int(::ceil(fValue));
-}
-
-//----------------------------------------------------------------------------
-
-inline int iClamp(int val, int low, int hi) {
- debugAssert(low <= hi);
- if (val <= low) {
- return low;
- } else if (val >= hi) {
- return hi;
- } else {
- return val;
- }
-}
-
-//----------------------------------------------------------------------------
-
-inline double clamp(double val, double low, double hi) {
- debugAssert(low <= hi);
- if (val <= low) {
- return low;
- } else if (val >= hi) {
- return hi;
- } else {
- return val;
- }
-}
-
-inline float clamp(float val, float low, float hi) {
- debugAssert(low <= hi);
- if (val <= low) {
- return low;
- } else if (val >= hi) {
- return hi;
- } else {
- return val;
- }
-}
-//----------------------------------------------------------------------------
-
-inline int iWrap(int val, int hi) {
- if (val < 0) {
- return ((val % hi) + hi) % hi;
- } else {
- return val % hi;
- }
-}
-
-//----------------------------------------------------------------------------
-inline int iFloor (double fValue) {
- return int(::floor(fValue));
-}
-
-//----------------------------------------------------------------------------
-inline int iSign (int iValue) {
- return ( iValue > 0 ? + 1 : ( iValue < 0 ? -1 : 0 ) );
-}
-
-inline int iSign (double fValue) {
- return ( fValue > 0.0 ? + 1 : ( fValue < 0.0 ? -1 : 0 ) );
-}
-
-//----------------------------------------------------------------------------
-inline double abs (double fValue) {
- return double(::fabs(fValue));
-}
-
-//----------------------------------------------------------------------------
-inline double aCos (double fValue) {
- if ( -1.0 < fValue ) {
- if ( fValue < 1.0 )
- return double(::acos(fValue));
- else
- return 0.0;
- } else {
- return G3D_PI;
- }
-}
-
-//----------------------------------------------------------------------------
-inline double aSin (double fValue) {
- if ( -1.0 < fValue ) {
- if ( fValue < 1.0 ) {
- return double(::asin(fValue));
- } else {
- return -G3D_HALF_PI;
- }
- } else {
- return G3D_HALF_PI;
- }
-}
-
-//----------------------------------------------------------------------------
-inline double aTan (double fValue) {
- return double(::atan(fValue));
-}
-
-//----------------------------------------------------------------------------
-inline double aTan2 (double fY, double fX) {
- return double(::atan2(fY, fX));
-}
-
-//----------------------------------------------------------------------------
-inline double sign (double fValue) {
- if (fValue > 0.0) {
- return 1.0;
- }
-
- if (fValue < 0.0) {
- return -1.0;
- }
-
- return 0.0;
-}
-
-inline double G3D_DEPRECATED unitRandom () {
- return double(::rand()) / double(RAND_MAX);
-}
-
-inline float uniformRandom(float low, float hi) {
- return (hi - low) * float(::rand()) / float(RAND_MAX) + low;
-}
-
-//----------------------------------------------------------------------------
-inline double G3D_DEPRECATED symmetricRandom () {
- return 2.0 * double(::rand()) / double(RAND_MAX) - 1.0;
-}
-
-//----------------------------------------------------------------------------
-inline double square(double x) {
- return x * x;
-}
-
-//----------------------------------------------------------------------------
-inline double sumSquares(double x, double y) {
- return x*x + y*y;
-}
-
-//----------------------------------------------------------------------------
-inline double sumSquares(double x, double y, double z) {
- return x*x + y*y + z*z;
-}
-
-//----------------------------------------------------------------------------
-inline double distance(double x, double y) {
- return sqrt(sumSquares(x, y));
-}
-
-//----------------------------------------------------------------------------
-inline double distance(double x, double y, double z) {
- return sqrt(sumSquares(x, y, z));
-}
-
-//----------------------------------------------------------------------------
-
-/** @deprecated use G3D::min */
-inline int iMin(int x, int y) {
- return (x >= y) ? y : x;
-}
-
-//----------------------------------------------------------------------------
-/** @deprecated use G3D::min */
-inline int iMax(int x, int y) {
- return (x >= y) ? x : y;
-}
-
-//----------------------------------------------------------------------------
-inline int ceilPow2(unsigned int in) {
- in -= 1;
-
- in |= in >> 16;
- in |= in >> 8;
- in |= in >> 4;
- in |= in >> 2;
- in |= in >> 1;
-
- return in + 1;
-}
-
-inline bool isPow2(int num) {
- return ((num & -num) == num);
-}
-
-inline bool isOdd(int num) {
- return (num & 1) == 1;
-}
-
-inline bool isEven(int num) {
- return (num & 1) == 0;
-}
-
-inline double toRadians(double deg) {
- return deg * G3D_PI / 180.0;
-}
-
-inline double toDegrees(double rad) {
- return rad * 180.0 / G3D_PI;
-}
-
-/**
- Computes an appropriate epsilon for comparing a and b.
- */
-inline double eps(double a, double b) {
- // For a and b to be nearly equal, they must have nearly
- // the same magnitude. This means that we can ignore b
- // since it either has the same magnitude or the comparison
- // will fail anyway.
- (void)b;
- const double aa = abs(a) + 1;
- if (aa == inf()) {
- return fuzzyEpsilon;
- } else {
- return fuzzyEpsilon * aa;
- }
-}
-
-inline bool fuzzyEq(double a, double b) {
- return (a == b) || (abs(a - b) <= eps(a, b));
-}
-
-inline bool fuzzyNe(double a, double b) {
- return ! fuzzyEq(a, b);
-}
-
-inline bool fuzzyGt(double a, double b) {
- return a > b + eps(a, b);
-}
-
-inline bool fuzzyGe(double a, double b) {
- return a > b - eps(a, b);
-}
-
-inline bool fuzzyLt(double a, double b) {
- return a < b - eps(a, b);
-}
-
-inline bool fuzzyLe(double a, double b) {
- return a < b + eps(a, b);
-}
-
-inline int iMod3(int x) {
- return x % 3;
-}
-
-} // namespace G3D
-
-#ifdef _MSC_VER
-// Disable conditional expression is constant, which occurs incorrectly on inlined functions
-# pragma warning (pop)
-#endif
diff --git a/externals/g3dlite/G3D/platform.h b/externals/g3dlite/G3D/platform.h
deleted file mode 100644
index 11ba0127a16..00000000000
--- a/externals/g3dlite/G3D/platform.h
+++ /dev/null
@@ -1,331 +0,0 @@
-/**
- @file platform.h
-
- \#defines for platform specific issues.
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2003-06-09
- @edited 2010-01-11
- */
-
-#ifndef G3D_platform_h
-#define G3D_platform_h
-
-/**
- The version number of G3D in the form: MmmBB ->
- version M.mm [beta BB]
- */
-#define G3D_VER 80004
-
-// fatal error for unsupported architectures
-#if defined(__powerpc__)
-# error PowerPC is not supported by G3D!
-#endif
-
-#if defined(G3D_RELEASEDEBUG)
-# define G3D_DEBUGRELEASE
-#endif
-
-#if defined(G3D_DEBUGRELEASE) && defined(_DEBUG)
-# undef _DEBUG
-#endif
-
-/** @def G3D_DEBUG()
- Defined if G3D is built in debug mode. */
-#if !defined(G3D_DEBUG) && (defined(_DEBUG) || defined(G3D_DEBUGRELEASE))
-# define G3D_DEBUG
-#endif
-
-#ifndef _MSC_VER
-/// Fast call is a register-based optimized calling convention supported only by Visual C++
-#define __fastcall
-
-#endif
-
-#ifdef _MSC_VER
- #define G3D_WIN32
-#elif defined(__FreeBSD__) || defined(__OpenBSD__)
- #define G3D_FREEBSD
- #define G3D_LINUX
-#elif defined(__linux__)
- #define G3D_LINUX
-#elif defined(__APPLE__)
- #define G3D_OSX
-
- // Prevent OS X fp.h header from being included; it defines
- // pi as a constant, which creates a conflict with G3D
-#define __FP__
-#else
- #error Unknown platform
-#endif
-
-// Detect 64-bit under various compilers
-#if (defined(_M_X64) || defined(_WIN64) || defined(__LP64__) || defined(_LP64))
-# define G3D_64BIT
- #if defined(WIN32)
- #include <intrin.h>
- #endif
-#else
-# define G3D_32BIT
-#endif
-
-// Strongly encourage inlining on gcc
-#ifdef __GNUC__
-#define inline __inline__
-#endif
-
-
-// Verify that the supported compilers are being used and that this is a known
-// processor.
-
-#ifdef G3D_LINUX
-# ifndef __GNUC__
-# error G3D only supports the gcc compiler on Linux.
-# endif
-#endif
-
-#ifdef G3D_OSX
-# ifndef __GNUC__
-# error G3D only supports the gcc compiler on OS X.
-# endif
-
-# if defined(__i386__)
-# define G3D_OSX_INTEL
-# elif defined(__PPC__)
-# define G3D_OSX_PPC
-# else
-# define G3D_OSX_UNKNOWN
-# endif
-
-#endif
-
-
-#ifdef _MSC_VER
-// Microsoft Visual C++ 8.0 ("Express") = 1400
-// Microsoft Visual C++ 7.1 ("2003") _MSC_VER = 1310
-// Microsoft Visual C++ 7.0 ("2002") _MSC_VER = 1300
-// Microsoft Visual C++ 6.0 _MSC_VER = 1200
-// Microsoft Visual C++ 5.0 _MSC_VER = 1100
-
-// Turn off warnings about deprecated C routines
-# pragma warning (disable : 4996)
-
-// Turn off "conditional expression is constant" warning; MSVC generates this
-// for debug assertions in inlined methods.
-# pragma warning (disable : 4127)
-
-/** @def G3D_DEPRECATED()
- Creates deprecated warning. */
-# define G3D_DEPRECATED __declspec(deprecated)
-
-// Prevent Winsock conflicts by hiding the winsock API
-# ifndef _WINSOCKAPI_
-# define _G3D_INTERNAL_HIDE_WINSOCK_
-# define _WINSOCKAPI_
-# endif
-
-// Disable 'name too long for browse information' warning
-# pragma warning (disable : 4786)
-// TODO: remove
-# pragma warning (disable : 4244)
-
-# define restrict
-
-/** @def G3D_CHECK_PRINTF_METHOD_ARGS()
- Enables printf parameter validation on gcc. */
-# define G3D_CHECK_PRINTF_ARGS
-
-/** @def G3D_CHECK_PRINTF_METHOD_ARGS()
- Enables printf parameter validation on gcc. */
-# define G3D_CHECK_VPRINTF_ARGS
-
-/** @def G3D_CHECK_PRINTF_METHOD_ARGS()
- Enables printf parameter validation on gcc. */
-# define G3D_CHECK_PRINTF_METHOD_ARGS
-
-/** @def G3D_CHECK_PRINTF_METHOD_ARGS()
- Enables printf parameter validation on gcc. */
-# define G3D_CHECK_VPRINTF_METHOD_ARGS
-
- // On MSVC, we need to link against the multithreaded DLL version of
- // the C++ runtime because that is what SDL and ZLIB are compiled
- // against. This is not the default for MSVC, so we set the following
- // defines to force correct linking.
- //
- // For documentation on compiler options, see:
- // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccore/html/_core_.2f.md.2c_2f.ml.2c_2f.mt.2c_2f.ld.asp
- // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccore98/HTML/_core_Compiler_Reference.asp
- //
-
- // DLL runtime
- #ifndef _DLL
- #define _DLL
- #endif
-
- // Multithreaded runtime
- #ifndef _MT
- #define _MT 1
- #endif
-
- // Ensure that we aren't forced into the static lib
- #ifdef _STATIC_CPPLIB
- #undef _STATIC_CPPLIB
- #endif
-
- #ifdef _DEBUG
- #pragma comment (linker, "/NODEFAULTLIB:LIBCMTD.LIB")
- #pragma comment (linker, "/NODEFAULTLIB:LIBCPMTD.LIB")
- #pragma comment (linker, "/NODEFAULTLIB:LIBCPD.LIB")
- #pragma comment (linker, "/DEFAULTLIB:MSVCPRTD.LIB")
- #pragma comment(linker, "/NODEFAULTLIB:LIBCD.LIB")
- #pragma comment(linker, "/DEFAULTLIB:MSVCRTD.LIB")
- #else
- #pragma comment(linker, "/NODEFAULTLIB:LIBC.LIB")
- #pragma comment(linker, "/DEFAULTLIB:MSVCRT.LIB")
- #pragma comment (linker, "/NODEFAULTLIB:LIBCMT.LIB")
- #pragma comment (linker, "/NODEFAULTLIB:LIBCPMT.LIB")
- #pragma comment(linker, "/NODEFAULTLIB:LIBCP.LIB")
- #pragma comment (linker, "/DEFAULTLIB:MSVCPRT.LIB")
- #endif
-
- // Now set up external linking
-
-# ifdef _DEBUG
- // zlib was linked against the release MSVCRT; force
- // the debug version.
-# pragma comment(linker, "/NODEFAULTLIB:MSVCRT.LIB")
-# endif
-
-
-# ifndef WIN32_LEAN_AND_MEAN
-# define WIN32_LEAN_AND_MEAN 1
-# endif
-
-
-# define NOMINMAX 1
-# ifndef _WIN32_WINNT
-# define _WIN32_WINNT 0x0500
-# endif
-# include <windows.h>
-# undef WIN32_LEAN_AND_MEAN
-# undef NOMINMAX
-
-# ifdef _G3D_INTERNAL_HIDE_WINSOCK_
-# undef _G3D_INTERNAL_HIDE_WINSOCK_
-# undef _WINSOCKAPI_
-# endif
-
-
-/** @def G3D_START_AT_MAIN()
- Defines necessary wrapper around WinMain on Windows to allow transfer of execution to main(). */
-# define G3D_START_AT_MAIN()\
-int WINAPI G3D_WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw);\
-int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw) {\
- return G3D_WinMain(hInst, hPrev, szCmdLine, sw);\
-}
-
-#else
-
-/** @def G3D_START_AT_MAIN()
- Defines necessary wrapper around WinMain on Windows to allow transfer of execution to main(). */
-# define G3D_START_AT_MAIN()
-
-#endif // win32
-
-#ifdef __GNUC__
-
-# include <stdint.h>
-
-# if __STDC_VERSION__ < 199901
-# define restrict __restrict__
-# endif
-
-/** @def G3D_DEPRECATED()
- Creates deprecated warning. */
-# define G3D_DEPRECATED __attribute__((__deprecated__))
-
-// setup function calling conventions
-# if defined(__i386__) && ! defined(__x86_64__)
-
-# ifndef __cdecl
-# define __cdecl __attribute__((cdecl))
-# endif
-
-# ifndef __stdcall
-# define __stdcall __attribute__((stdcall))
-# endif
-
-# elif defined(__x86_64__)
-
-# ifndef __cdecl
-# define __cdecl
-# endif
-
-# ifndef __stdcall
-# define __stdcall
-# endif
-# endif // calling conventions
-
-/** @def G3D_CHECK_PRINTF_METHOD_ARGS()
- Enables printf parameter validation on gcc. */
-# define G3D_CHECK_PRINTF_METHOD_ARGS __attribute__((__format__(__printf__, 2, 3)))
-
-/** @def G3D_CHECK_PRINTF_METHOD_ARGS()
- Enables printf parameter validation on gcc. */
-# define G3D_CHECK_VPRINTF_METHOD_ARGS __attribute__((__format__(__printf__, 2, 0)))
-
-/** @def G3D_CHECK_PRINTF_METHOD_ARGS()
- Enables printf parameter validation on gcc. */
-# define G3D_CHECK_PRINTF_ARGS __attribute__((__format__(__printf__, 1, 2)))
-
-/** @def G3D_CHECK_PRINTF_METHOD_ARGS()
- Enables printf parameter validation on gcc. */
-# define G3D_CHECK_VPRINTF_ARGS __attribute__((__format__(__printf__, 1, 0)))
-#endif
-
-
-/**
- @def STR(expression)
-
- Creates a string from the expression. Frequently used with G3D::Shader
- to express shading programs inline.
-
- <CODE>STR(this becomes a string)\verbatim<PRE>\endverbatim evaluates the same as \verbatim<CODE>\endverbatim"this becomes a string"</CODE>
- */
-#define STR(x) #x
-
-/** @def PRAGMA(expression)
- \#pragma may not appear inside a macro, so this uses the pragma operator
- to create an equivalent statement.*/
-#ifdef _MSC_VER
-// Microsoft's version http://msdn.microsoft.com/en-us/library/d9x1s805.aspx
-# define PRAGMA(x) __pragma(x)
-#else
-// C99 standard http://www.delorie.com/gnu/docs/gcc/cpp_45.html
-# define PRAGMA(x) _Pragma(#x)
-#endif
-
-/** @def G3D_BEGIN_PACKED_CLASS(byteAlign)
- Switch to tight alignment
- See G3D::Color3uint8 for an example.*/
-#ifdef _MSC_VER
-# define G3D_BEGIN_PACKED_CLASS(byteAlign) PRAGMA( pack(push, byteAlign) )
-#else
-# define G3D_BEGIN_PACKED_CLASS(byteAlign)
-#endif
-
-/** @def G3D_END_PACKED_CLASS(byteAlign)
- End switch to tight alignment
- See G3D::Color3uint8 for an example.*/
-#ifdef _MSC_VER
-# define G3D_END_PACKED_CLASS(byteAlign) ; PRAGMA( pack(pop) )
-#elif defined(__GNUC__)
-# define G3D_END_PACKED_CLASS(byteAlign) __attribute((aligned(byteAlign))) ;
-#else
-# define G3D_END_PACKED_CLASS(byteAlign) ;
-#endif
-
-
-// Header guard
-#endif
diff --git a/externals/g3dlite/G3D/prompt.h b/externals/g3dlite/G3D/prompt.h
deleted file mode 100644
index c6df628099e..00000000000
--- a/externals/g3dlite/G3D/prompt.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/**
- @file prompt.h
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @cite Windows GUI code by Max McGuire
-
- @created 2001-08-26
- @edited 2006-08-13
- */
-
-#ifndef G3D_PROMPT_H
-#define G3D_PROMPT_H
-
-#include "platform.h"
-#include <string>
-
-namespace G3D {
-
-/**
- Prints a prompt to stdout and waits for user input. The return value is
- the number of the user's choice (the first is 0, if there are no
- choices, returns 0).
-
- @param useGui Under Win32, use a GUI, not stdout prompt.
- @param windowTitle The title for the prompt window
- @param promptx The text string to prompt the user with
- @param choice An array of strings that are the choices the user may make
- @param numChoices The length of choice.
-
- @cite Windows dialog interface by Max McGuire, mmcguire@ironlore.com
- @cite Font setting code by Kurt Miller, kurt@flipcode.com
- */
-int prompt(
- const char* windowTitle,
- const char* promptx,
- const char** choice,
- int numChoices,
- bool useGui);
-
-/**
- Prints a prompt and waits for user input. The return value is
- the number of the user's choice (the first is 0, if there are no
- choices, returns 0).
- <P>Uses GUI under Win32, stdout prompt otherwise.
- */
-inline int prompt(
- const char* windowTitle,
- const char* promptx,
- const char** choice,
- int numChoices) {
-
- return prompt(windowTitle, promptx, choice, numChoices, true);
-}
-
-
-/**
- Displays a GUI prompt with "Ok" as the only choice.
- */
-void msgBox(
- const std::string& message,
- const std::string& title = "Message");
-
-
-}; // namespace
-
-#endif
-
diff --git a/externals/g3dlite/G3D/serialize.h b/externals/g3dlite/G3D/serialize.h
deleted file mode 100644
index 2382c0ee0fd..00000000000
--- a/externals/g3dlite/G3D/serialize.h
+++ /dev/null
@@ -1,30 +0,0 @@
-#ifndef G3D_SERIALIZE_H
-#define G3D_SERIALIZE_H
-
-#include "G3D/BinaryInput.h"
-#include "G3D/BinaryOutput.h"
-#include "G3D/Array.h"
-
-namespace G3D {
-
-
-template<typename T>
-void serialize(const Array<T>& array, BinaryOutput& b) {
- b.writeInt32(array.size());
- for (int i = 0; i < array.size(); ++i) {
- serialize(array[i], b);
- }
-}
-
-template<typename T>
-void deserialize(Array<T>& array, BinaryInput& b) {
- int N = b.readInt32();
- array.resize(N);
- for (int i = 0; i < array.size(); ++i) {
- deserialize(array[i], b);
- }
-}
-
-}
-
-#endif
diff --git a/externals/g3dlite/G3D/splinefunc.h b/externals/g3dlite/G3D/splinefunc.h
deleted file mode 100644
index 3f3a018c292..00000000000
--- a/externals/g3dlite/G3D/splinefunc.h
+++ /dev/null
@@ -1,118 +0,0 @@
-/**
- @file spline.h
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2004-07-25
- @edited 2007-05-05
- */
-
-#ifndef G3D_SPLINEFUNC_H
-#define G3D_SPLINEFUNC_H
-
-#include "G3D/platform.h"
-#include "G3D/debug.h"
-#include "G3D/Array.h"
-#include "G3D/g3dmath.h"
-
-namespace G3D {
-
-/**
- Interpolates a property according to a piecewise linear spline. This provides
- C0 continuity but the derivatives are not smooth.
- <P>
- Example:
- <CODE>
- const double times[] = {MIDNIGHT, SUNRISE - HOUR, SUNRISE, SUNRISE + sunRiseAndSetTime / 4, SUNRISE + sunRiseAndSetTime, SUNSET - sunRiseAndSetTime, SUNSET - sunRiseAndSetTime / 2, SUNSET, SUNSET + HOUR/2, DAY};
- const Color3 color[] = {Color3(0, .0, .1), Color3(0, .0, .1), Color3::black(), Color3::black(), Color3::white() * .25, Color3::white() * .25, Color3(.5, .2, .2), Color3(.05, .05, .1), Color3(0, .0, .1), Color3(0, .0, .1)};
- ambient = linearSpline(time, times, color, 10);
- </CODE>
-
- See also G3D::Spline
-
- @param x The spline is a function of x; this is the sample to choose.
- @param controlX controlX[i], controlY[i] is a control points. It is assumed
- that controlX are strictly increasing. XType must support
- the "<" operator and a subtraction operator that returns
- a number.
- @param controlY YType must support multiplication and addition.
- @param numControl The number of control points.
- */
-template<class XType, class YType>
-YType linearSpline(double x, const XType* controlX, const YType* controlY, int numControl) {
- debugAssert(numControl >= 1);
-
- // Off the beginning
- if ((numControl == 1) || (x < controlX[0])) {
- return controlY[0];
- }
-
- for (int i = 1; i < numControl; ++i) {
- if (x < controlX[i]) {
- const double alpha = (double)(controlX[i] - x) / (controlX[i] - controlX[i - 1]);
- return controlY[i] * (1 - alpha) + controlY[i - 1] * alpha;
- }
- }
-
- // Off the end
- return controlY[numControl - 1];
-}
-
-
- /** See also G3D::Spline*/
-template<class YType> YType cyclicCatmullRomSpline(
- double t,
- const YType* controlY,
- int numPoints) {
-
- debugAssert(numPoints >= 3);
-
- t = wrap(t, numPoints);
-
- // Find the indices of adjacent control points
- int i = iFloor(t);
-
- // Compute the distance from the control point
- t = t - i;
-
- // Shift back one point for correct indexing
- i += numPoints - 1;
-
- // Pick up four control points
- const YType& P0 = controlY[(i + 0) % numPoints];
- const YType& P1 = controlY[(i + 1) % numPoints];
- const YType& P2 = controlY[(i + 2) % numPoints];
- const YType& P3 = controlY[(i + 3) % numPoints];
-
- return 0.5 * ((2 * P1) +
- (-P0 + P2) * t +
- (2*P0 - 5*P1 + 4*P2 - P3) * t*t +
- (-P0 + 3*P1- 3*P2 + P3) * t*t*t);
-}
-
-/**
- A cubic spline with regularly spaced
- control points. The spline interpolates
- the control points. The spline
- will wrap from the last point back to the first.
-
- The t parameter is on the range [0, controlY.size()],
- where integers correspond to control points exactly.
-
- See also G3D::Spline
-
- @cite http://www.mvps.org/directx/articles/catmull/
-*/
-template<class YType> YType cyclicCatmullRomSpline(
- double t,
- const Array<YType>& controlY) {
-
- int numPoints = controlY.size();
- return cyclicCatmullRomSpline(t, controlY.getCArray(), numPoints);
-}
-
-}
-
-#endif
-
-
diff --git a/externals/g3dlite/G3D/stringutils.h b/externals/g3dlite/G3D/stringutils.h
deleted file mode 100644
index e15a757a7a6..00000000000
--- a/externals/g3dlite/G3D/stringutils.h
+++ /dev/null
@@ -1,140 +0,0 @@
-/**
- @file stringutils.h
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @author 2000-09-09
- @edited 2008-08-05
- */
-
-#ifndef G3D_STRINGUTILS_H
-#define G3D_STRINGUTILS_H
-
-#include "G3D/platform.h"
-#include "G3D/Array.h"
-#include <cstring>
-
-namespace G3D {
-
-extern const char* NEWLINE;
-
-/** Separates a comma-separated line, properly escaping commas within
- double quotes (") and super quotes ("""). This matches Microsoft Excel's
- CSV output.
-
- \param stripQuotes If true, strips leading and trailing " and """
-
- \sa G3D::stringSplit, G3D::TextInput, G3D::readWholeFile
-*/
-void parseCommaSeparated(const std::string s, Array<std::string>& array, bool stripQuotes = true);
-
-/**
- Returns true if the test string begins with the pattern string.
- */
-bool beginsWith(
- const std::string& test,
- const std::string& pattern);
-
-/**
- Returns true if the test string ends with the pattern string.
- */
-bool endsWith(
- const std::string& test,
- const std::string& pattern);
-
-/**
- Produces a new string that is the input string
- wrapped at a certain number of columns (where
- the line is broken at the latest space before the
- column limit.) Platform specific NEWLINEs
- are inserted to wrap.
- */
-std::string wordWrap(
- const std::string& input,
- int numCols);
-
-/**
- A comparison function for passing to Array::sort.
- */
-int stringCompare(
- const std::string& s1,
- const std::string& s2);
-
-int stringPtrCompare(
- const std::string* s1,
- const std::string* s2);
-
-/**
- Returns a new string that is an uppercase version of x.
- */
-std::string toUpper(
- const std::string& x);
-
-std::string toLower(
- const std::string& x);
-
-/**
- Splits x at each occurance of splitChar.
- */
-G3D::Array<std::string> stringSplit(
- const std::string& x,
- char splitChar);
-
-/**
- joinChar is not inserted at the beginning or end, just in between
- elements.
- */
-std::string stringJoin(
- const G3D::Array<std::string>& a,
- char joinChar);
-
-std::string stringJoin(
- const G3D::Array<std::string>& a,
- const std::string& joinStr);
-
-/**
- Strips whitespace from both ends of the string.
- */
-std::string trimWhitespace(
- const std::string& s);
-
-/** These standard C functions are renamed for clarity/naming
- conventions and to return bool, not int.
- */
-inline bool isWhiteSpace(const unsigned char c) {
- return isspace(c) != 0;
-}
-
-/** These standard C functions are renamed for clarity/naming
- conventions and to return bool, not int.
- */
-inline bool isNewline(const unsigned char c) {
- return (c == '\n') || (c == '\r');
-}
-
-/** These standard C functions are renamed for clarity/naming
- conventions and to return bool, not int.
- */
-inline bool isDigit(const unsigned char c) {
- return isdigit(c) != 0;
-}
-
-/** These standard C functions are renamed for clarity/naming
- conventions and to return bool, not int.
- */
-inline bool isLetter(const unsigned char c) {
- return isalpha(c) != 0;
-}
-
-inline bool isSlash(const unsigned char c) {
- return (c == '\\') || (c == '/');
-}
-
-inline bool isQuote(const unsigned char c) {
- return (c == '\'') || (c == '\"');
-}
-
-}; // namespace
-
-#endif
-
diff --git a/externals/g3dlite/G3D/uint128.h b/externals/g3dlite/G3D/uint128.h
deleted file mode 100644
index da1af3ec272..00000000000
--- a/externals/g3dlite/G3D/uint128.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/**
- @file uint128.h
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @author Kyle Whitson
-
- @created 2008-07-17
- @edited 2008-07-17
- */
-
-#ifndef G3D_UINT128_H
-#define G3D_UINT128_H
-
-#include "G3D/g3dmath.h"
-
-namespace G3D {
-
-/** Limited functionality 128-bit unsigned integer. This is primarily to support FNV hashing and other
- cryptography applications. See the GMP library for high-precision C++ math support. */
-class uint128 {
-public:
-
- G3D::uint64 hi;
- G3D::uint64 lo;
-
- uint128(const uint64& lo);
-
- uint128(const uint64& hi, const uint64& lo);
-
- uint128& operator+=(const uint128& x);
-
- uint128& operator*=(const uint128& x);
-
- uint128& operator^=(const uint128& x);
-
- uint128& operator&=(const uint128& x);
-
- uint128& operator|=(const uint128& x);
-
- bool operator==(const uint128& x);
-
- uint128& operator>>=(const int x);
-
- uint128& operator<<=(const int x);
-
- uint128 operator&(const uint128& x);
-
-};
-}
-
-#endif
diff --git a/externals/g3dlite/G3D/units.h b/externals/g3dlite/G3D/units.h
deleted file mode 100644
index 2e30304dc62..00000000000
--- a/externals/g3dlite/G3D/units.h
+++ /dev/null
@@ -1,126 +0,0 @@
-/**
- @file units.h
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2009-08-21
- @edited 2009-08-21
- */
-#ifndef G3D_units_h
-#define G3D_units_h
-
-#include "G3D/platform.h"
-
-namespace G3D {
-/** Use <code>using namespace G3D::units;</code> to include all units
- into your program. The units system is specifically designed not to
- be general but to support commonly used units efficiently and
- clearly. See http://en.wikipedia.org/wiki/SI_prefix for interesting facts
- about SI/metric units and full definitions.*/
-namespace units {
-
-/** 1e-9 m */
-inline float nanometers() {
- return 1e-9f;
-}
-
-/** 1e-6 m */
-inline float micrometers() {
- return 1e-6f;
-}
-
-/** 0.001 m */
-inline float millimeters() {
- return 0.001f;
-}
-
-/** 0.01 m */
-inline float centimeters() {
- return 0.01f;
-}
-
-/** SI base unit of distance measure. */
-inline float meters() {
- return 1.0f;
-}
-
-/** 1000 m */
-inline float kilometers() {
- return 100.0f;
-}
-
-/** 0.0254 m */
-inline float inches() {
- return 0.0254f;
-}
-
-/** 0.3048 m */
-inline float feet() {
- return 0.3048f;
-}
-
-/** 0.9144 m */
-inline float yards() {
- return 0.9144f;
-}
-
-/** 1609.344 m */
-inline float miles() {
- return 1609.344f;
-}
-
-/////////////////////////////////////////////////////////////
-
-/** SI base unit of angular measure. */
-inline float radians() {
- return 1.0f;
-}
-
-/** pi/180 */
-inline float degrees() {
- return 0.0174532925f;
-}
-
-//////////////////////////////////////////////////////////////
-
-/** 1e-9 s */
-inline float nanoseconds() {
- return 1e-9f;
-}
-
-/** 1e-3 s */
-inline float milliseconds() {
- return 1e-3f;
-}
-
-/** Base unit of time */
-inline float seconds() {
- return 1.0;
-}
-
-/** 60 s */
-inline float minutes() {
- return 60.0f;
-}
-
-/** 3600 s */
-inline float hours() {
- return 3600.0f;
-}
-
-/** 86400 s */
-inline float days() {
- return 86400.0f;
-}
-
-/** 31556926 s */
-inline float years() {
- return 31556926.0f;
-}
-
-///////////////////////////////////////////
-
-}
-}
-
-#endif
diff --git a/externals/g3dlite/G3D/vectorMath.h b/externals/g3dlite/G3D/vectorMath.h
deleted file mode 100644
index ac6d2b32e9d..00000000000
--- a/externals/g3dlite/G3D/vectorMath.h
+++ /dev/null
@@ -1,235 +0,0 @@
-/**
- @file vectorMath.h
-
- Function aliases for popular vector methods.
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created: 2001-06-02
- @edited: 2004-02-02
- Copyright 2000-2004, Morgan McGuire.
- All rights reserved.
- */
-
-#ifndef G3D_VECTORMATH_H
-#define G3D_VECTORMATH_H
-
-#include "G3D/platform.h"
-#include "G3D/g3dmath.h"
-#include "G3D/Vector2.h"
-#include "G3D/Vector3.h"
-#include "G3D/Vector4.h"
-#include "G3D/Matrix3.h"
-#include "G3D/Matrix4.h"
-#include "G3D/Color1.h"
-#include "G3D/Color3.h"
-#include "G3D/Color4.h"
-
-
-namespace G3D {
-
-
-inline Matrix4 mul(const Matrix4& a, const Matrix4& b) {
- return a * b;
-}
-
-inline Vector4 mul(const Matrix4& m, const Vector4& v) {
- return m * v;
-}
-
-inline Vector3 mul(const Matrix3& m, const Vector3& v) {
- return m * v;
-}
-
-inline Matrix3 mul(const Matrix3& a, const Matrix3& b) {
- return a * b;
-}
-
-inline float dot(const Vector2& a, const Vector2& b) {
- return a.dot(b);
-}
-
-inline float dot(const Vector3& a, const Vector3& b) {
- return a.dot(b);
-}
-
-inline float dot(const Vector4& a, const Vector4& b) {
- return a.dot(b);
-}
-
-inline Vector2 normalize(const Vector2& v) {
- return v / v.length();
-}
-
-inline Vector3 normalize(const Vector3& v) {
- return v / v.magnitude();
-}
-
-inline Vector4 normalize(const Vector4& v) {
- return v / v.length();
-}
-
-inline Vector2 abs(const Vector2& v) {
- return Vector2(::fabsf(v.x), ::fabsf(v.y));
-}
-
-inline Vector3 abs(const Vector3& v) {
- return Vector3(::fabsf(v.x), ::fabsf(v.y), ::fabsf(v.z));
-}
-
-inline Vector4 abs(const Vector4& v) {
- return Vector4(::fabsf(v.x), ::fabsf(v.y), ::fabsf(v.z), ::fabsf(v.w));
-}
-
-inline bool all(const Vector2& v) {
- return (v.x != 0) && (v.y != 0);
-}
-
-inline bool all(const Vector3& v) {
- return (v.x != 0) && (v.y != 0) && (v.z != 0);
-}
-
-inline bool all(const Vector4& v) {
- return (v.x != 0) && (v.y != 0) && (v.z != 0) && (v.w != 0);
-}
-
-inline bool any(const Vector2& v) {
- return (v.x != 0) || (v.y != 0);
-}
-
-inline bool any(const Vector3& v) {
- return (v.x != 0) || (v.y != 0) || (v.z != 0);
-}
-
-inline bool any(const Vector4& v) {
- return (v.x != 0) || (v.y != 0) || (v.z != 0) || (v.w != 0);
-}
-
-inline Vector2 clamp(const Vector2& v, const Vector2& a, const Vector2& b) {
- return v.clamp(a, b);
-}
-
-inline Vector3 clamp(const Vector3& v, const Vector3& a, const Vector3& b) {
- return v.clamp(a, b);
-}
-
-inline Vector4 clamp(const Vector4& v, const Vector4& a, const Vector4& b) {
- return v.clamp(a, b);
-}
-
-inline Vector2 lerp(const Vector2& v1, const Vector2& v2, float f) {
- return v1.lerp(v2, f);
-}
-
-inline Vector3 lerp(const Vector3& v1, const Vector3& v2, float f) {
- return v1.lerp(v2, f);
-}
-
-inline Vector4 lerp(const Vector4& v1, const Vector4& v2, float f) {
- return v1.lerp(v2, f);
-}
-
-inline Color1 lerp(const Color1& v1, const Color1& v2, float f) {
- return v1.lerp(v2, f);
-}
-
-inline Color3 lerp(const Color3& v1, const Color3& v2, float f) {
- return v1.lerp(v2, f);
-}
-
-inline Color4 lerp(const Color4& v1, const Color4& v2, float f) {
- return v1.lerp(v2, f);
-}
-
-inline Vector3 cross(const Vector3& v1, const Vector3& v2) {
- return v1.cross(v2);
-}
-
-inline double determinant(const Matrix3& m) {
- return m.determinant();
-}
-
-inline double determinant(const Matrix4& m) {
- return m.determinant();
-}
-
-inline Vector2 min(const Vector2& v1, const Vector2& v2) {
- return v1.min(v2);
-}
-
-inline Vector3 min(const Vector3& v1, const Vector3& v2) {
- return v1.min(v2);
-}
-
-inline Vector4 min(const Vector4& v1, const Vector4& v2) {
- return v1.min(v2);
-}
-
-inline Color3 min(const Color3& v1, const Color3& v2) {
- return v1.min(v2);
-}
-
-inline Color4 min(const Color4& v1, const Color4& v2) {
- return v1.min(v2);
-}
-
-inline Vector2 max(const Vector2& v1, const Vector2& v2) {
- return v1.max(v2);
-}
-
-inline Vector3 max(const Vector3& v1, const Vector3& v2) {
- return v1.max(v2);
-}
-
-inline Vector4 max(const Vector4& v1, const Vector4& v2) {
- return v1.max(v2);
-}
-
-inline Color3 max(const Color3& v1, const Color3& v2) {
- return v1.max(v2);
-}
-
-inline Color4 max(const Color4& v1, const Color4& v2) {
- return v1.max(v2);
-}
-
-inline Vector2 sign(const Vector2& v) {
- return Vector2((float)sign(v.x), (float)sign(v.y));
-}
-
-inline Vector3 sign(const Vector3& v) {
- return Vector3((float)sign(v.x), (float)sign(v.y), (float)sign(v.z));
-}
-
-inline Vector4 sign(const Vector4& v) {
- return Vector4((float)sign(v.x), (float)sign(v.y), (float)sign(v.z), (float)sign(v.w));
-}
-
-inline float length(float v) {
- return ::fabsf(v);
-}
-
-inline float length(const Vector2& v) {
- return v.length();
-}
-
-inline float length(const Vector3& v) {
- return v.magnitude();
-}
-
-inline float length(const Vector4& v) {
- return v.length();
-}
-
-/**
- Computes the log of each component. Useful for
- inverting the monitor gamma function or simulating
- perceptual response.
- */
-inline Color3 log(const Color3& c) {
- return Color3(::logf(c.r), ::logf(c.g), ::logf(c.b));
-}
-
-}
-
-#endif
diff --git a/externals/g3dlite/Line.cpp b/externals/g3dlite/Line.cpp
deleted file mode 100644
index 195ae7197f2..00000000000
--- a/externals/g3dlite/Line.cpp
+++ /dev/null
@@ -1,89 +0,0 @@
-/**
- @file Line.cpp
-
- Line class
-
- @maintainer Morgan McGuire, graphics3d.com
-
- @created 2001-06-02
- @edited 2006-01-28
- */
-
-#include "G3D/Line.h"
-#include "G3D/Plane.h"
-
-namespace G3D {
-
-Vector3 Line::intersection(const Plane& plane) const {
- float d;
- Vector3 normal = plane.normal();
- plane.getEquation(normal, d);
- float rate = _direction.dot(normal);
-
- if (rate == 0) {
-
- return Vector3::inf();
-
- } else {
- float t = -(d + _point.dot(normal)) / rate;
-
- return _point + _direction * t;
- }
-}
-
-
-Line::Line(class BinaryInput& b) {
- deserialize(b);
-}
-
-
-void Line::serialize(class BinaryOutput& b) const {
- _point.serialize(b);
- _direction.serialize(b);
-}
-
-
-void Line::deserialize(class BinaryInput& b) {
- _point.deserialize(b);
- _direction.deserialize(b);
-}
-
-
-Vector3 Line::closestPoint(const Vector3& pt) const {
- float t = _direction.dot(pt - _point);
- return _point + _direction * t;
-}
-
-
-Vector3 Line::point() const {
- return _point;
-}
-
-
-Vector3 Line::direction() const {
- return _direction;
-}
-
-
-Vector3 Line::closestPoint(const Line& B, float& minDist) const {
- const Vector3& P1 = _point;
- const Vector3& U1 = _direction;
-
- Vector3 P2 = B.point();
- Vector3 U2 = B.direction();
-
- const Vector3& P21 = P2 - P1;
- const Vector3& M = U2.cross(U1);
- float m2 = M.length();
-
- Vector3 R = P21.cross(M) / m2;
-
- float t1 = R.dot(U2);
-
- minDist = abs(P21.dot(M)) / sqrt(m2);
-
- return P1 + t1 * U1;
-}
-
-}
-
diff --git a/externals/g3dlite/LineSegment.cpp b/externals/g3dlite/LineSegment.cpp
deleted file mode 100644
index 754600ad554..00000000000
--- a/externals/g3dlite/LineSegment.cpp
+++ /dev/null
@@ -1,236 +0,0 @@
-/**
- @file LineSegment.cpp
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2003-02-08
- @edited 2008-02-02
- */
-
-#include "G3D/platform.h"
-#include "G3D/LineSegment.h"
-#include "G3D/Sphere.h"
-#include "G3D/debug.h"
-
-namespace G3D {
-
-
-Vector3 LineSegment::closestPoint(const Vector3& p) const {
-
- // The vector from the end of the capsule to the point in question.
- Vector3 v(p - _point);
-
- // Projection of v onto the line segment scaled by
- // the length of direction.
- float t = direction.dot(v);
-
- // Avoid some square roots. Derivation:
- // t/direction.length() <= direction.length()
- // t <= direction.squaredLength()
-
- if ((t >= 0) && (t <= direction.squaredMagnitude())) {
-
- // The point falls within the segment. Normalize direction,
- // divide t by the length of direction.
- return _point + direction * t / direction.squaredMagnitude();
-
- } else {
-
- // The point does not fall within the segment; see which end is closer.
-
- // Distance from 0, squared
- float d0Squared = v.squaredMagnitude();
-
- // Distance from 1, squared
- float d1Squared = (v - direction).squaredMagnitude();
-
- if (d0Squared < d1Squared) {
-
- // Point 0 is closer
- return _point;
-
- } else {
-
- // Point 1 is closer
- return _point + direction;
-
- }
- }
-
-}
-
-Vector3 LineSegment::point(int i) const {
- switch (i) {
- case 0:
- return _point;
-
- case 1:
- return _point + direction;
-
- default:
- debugAssertM(i == 0 || i == 1, "Argument to point must be 0 or 1");
- return _point;
- }
-}
-
-
-bool LineSegment::intersectsSolidSphere(const class Sphere& s) const {
- return distanceSquared(s.center) <= square(s.radius);
-}
-
-
-LineSegment::LineSegment(class BinaryInput& b) {
- deserialize(b);
-}
-
-
-void LineSegment::serialize(class BinaryOutput& b) const {
- _point.serialize(b);
- direction.serialize(b);
-}
-
-
-void LineSegment::deserialize(class BinaryInput& b) {
- _point.deserialize(b);
- direction.deserialize(b);
-}
-
-
-Vector3 LineSegment::randomPoint() const {
- return _point + uniformRandom(0, 1) * direction;
-}
-
-
-/////////////////////////////////////////////////////////////////////////////////////
-
-LineSegment2D LineSegment2D::fromTwoPoints(const Vector2& p0, const Vector2& p1) {
- LineSegment2D s;
- s.m_origin = p0;
- s.m_direction = p1 - p0;
- s.m_length = s.m_direction.length();
- return s;
-}
-
-
-Vector2 LineSegment2D::point(int i) const {
- debugAssert(i == 0 || i == 1);
- if (i == 0) {
- return m_origin;
- } else {
- return m_direction + m_origin;
- }
-}
-
-
-Vector2 LineSegment2D::closestPoint(const Vector2& Q) const {
- // Two constants that appear in the result
- const Vector2 k1(m_origin - Q);
- const Vector2& k2 = m_direction;
-
- if (fuzzyEq(m_length, 0)) {
- // This line segment has no length
- return m_origin;
- }
-
- // Time [0, 1] at which we hit the closest point travelling from p0 to p1.
- // Derivation can be obtained by minimizing the expression
- // ||P0 + (P1 - P0)t - Q||.
- const float t = -k1.dot(k2) / (m_length * m_length);
-
- if (t < 0) {
- // Clipped to low end point
- return m_origin;
- } else if (t > 1) {
- // Clipped to high end point
- return m_origin + m_direction;
- } else {
- // Subsitute into the line equation to find
- // the point on the segment.
- return m_origin + k2 * t;
- }
-}
-
-
-float LineSegment2D::distance(const Vector2& p) const {
- Vector2 closest = closestPoint(p);
- return (closest - p).length();
-}
-
-
-float LineSegment2D::length() const {
- return m_length;
-}
-
-
-Vector2 LineSegment2D::intersection(const LineSegment2D& other) const {
-
- if ((m_origin == other.m_origin) ||
- (m_origin == other.m_origin + other.m_direction)) {
- return m_origin;
- }
-
- if (m_origin + m_direction == other.m_origin) {
- return other.m_origin;
- }
-
- // Note: Now that we've checked the endpoints, all other parallel lines can now be assumed
- // to not intersect (within numerical precision)
-
- Vector2 dir1 = m_direction;
- Vector2 dir2 = other.m_direction;
- Vector2 origin1 = m_origin;
- Vector2 origin2 = other.m_origin;
-
- if (dir1.x == 0) {
- // Avoid an upcoming divide by zero
- dir1 = dir1.yx();
- dir2 = dir2.yx();
- origin1 = origin1.yx();
- origin2 = origin2.yx();
- }
-
- // t1 = ((other.m_origin.x - m_origin.x) + other.m_direction.x * t2) / m_direction.x
- //
- // ((other.m_origin.x - m_origin.x) + other.m_direction.x * t2) * m_direction.y / m_direction.x =
- // (other.m_origin.y - m_origin.y) + other.m_direction.y * t2
- //
- // m = m_direction.y / m_direction.x
- // d = other.m_origin - m_origin
- //
- // (d.x + other.m_direction.x * t2) * m = d.y + other.m_direction.y * t2
- //
- // d.x * m + other.m_direction.x * m * t2 = d.y + other.m_direction.y * t2
- //
- // d.x * m - d.y = (other.m_direction.y - other.m_direction.x * m) * t2
- //
- // (d.x * m - d.y) / (other.m_direction.y - other.m_direction.x * m) = t2
- //
-
- Vector2 d = origin2 - origin1;
- float m = dir1.y / dir1.x;
-
- float t2 = (d.x * m - d.y) / (dir2.y - dir2.x * m);
- if (! isFinite(t2)) {
- // Parallel lines: no intersection
- return Vector2::inf();
- }
-
- if ((t2 < 0.0f) || (t2 > 1.0f)) {
- // Intersection occurs past the end of the line segments
- return Vector2::inf();
- }
-
- float t1 = (d.x + dir2.x * t2) / dir1.x;
- if ((t1 < 0.0f) || (t1 > 1.0f)) {
- // Intersection occurs past the end of the line segments
- return Vector2::inf();
- }
-
- // Return the intersection point (computed from non-transposed
- // variables even if we flipped above)
- return m_origin + m_direction * t1;
-
-}
-
-}
-
diff --git a/externals/g3dlite/Log.cpp b/externals/g3dlite/Log.cpp
deleted file mode 100644
index 07614fcf563..00000000000
--- a/externals/g3dlite/Log.cpp
+++ /dev/null
@@ -1,146 +0,0 @@
-/**
- @file Log.cpp
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @created 2001-08-04
- @edited 2009-01-15
- */
-
-#include "G3D/platform.h"
-#include "G3D/Log.h"
-#include "G3D/format.h"
-#include "G3D/Array.h"
-#include "G3D/fileutils.h"
-#include <time.h>
-
-#ifdef G3D_WIN32
- #include <imagehlp.h>
-#else
- #include <stdarg.h>
-#endif
-
-namespace G3D {
-
-void logPrintf(const char* fmt, ...) {
- va_list arg_list;
- va_start(arg_list, fmt);
- Log::common()->vprintf(fmt, arg_list);
- va_end(arg_list);
-}
-
-
-void logLazyPrintf(const char* fmt, ...) {
- va_list arg_list;
- va_start(arg_list, fmt);
- Log::common()->lazyvprintf(fmt, arg_list);
- va_end(arg_list);
-}
-
-Log* Log::commonLog = NULL;
-
-Log::Log(const std::string& filename, int stripFromStackBottom) :
- stripFromStackBottom(stripFromStackBottom) {
-
- this->filename = filename;
-
- logFile = fopen(filename.c_str(), "w");
-
- if (logFile == NULL) {
- std::string drive, base, ext;
- Array<std::string> path;
- parseFilename(filename, drive, path, base, ext);
- std::string logName = base + ((ext != "") ? ("." + ext) : "");
-
- // Write time is greater than 1ms. This may be a network drive.... try another file.
- #ifdef G3D_WIN32
- logName = std::string(std::getenv("TEMP")) + logName;
- #else
- logName = std::string("/tmp/") + logName;
- #endif
-
- logFile = fopen(logName.c_str(), "w");
- }
-
- // Use a large buffer (although we flush in logPrintf)
- setvbuf(logFile, NULL, _IOFBF, 2048);
-
- fprintf(logFile, "Application Log\n");
- time_t t;
- time(&t);
- fprintf(logFile, "Start: %s\n", ctime(&t));
- fflush(logFile);
-
- if (commonLog == NULL) {
- commonLog = this;
- }
-}
-
-
-Log::~Log() {
- section("Shutdown");
- println("Closing log file");
-
- // Make sure we don't leave a dangling pointer
- if (Log::commonLog == this) {
- Log::commonLog = NULL;
- }
-
- fclose(logFile);
-}
-
-
-FILE* Log::getFile() const {
- return logFile;
-}
-
-
-Log* Log::common() {
- if (commonLog == NULL) {
- commonLog = new Log();
- }
- return commonLog;
-}
-
-
-std::string Log::getCommonLogFilename() {
- return common()->filename;
-}
-
-
-void Log::section(const std::string& s) {
- fprintf(logFile, "_____________________________________________________\n");
- fprintf(logFile, "\n ### %s ###\n\n", s.c_str());
-}
-
-
-void __cdecl Log::printf(const char* fmt, ...) {
- va_list arg_list;
- va_start(arg_list, fmt);
- print(vformat(fmt, arg_list));
- va_end(arg_list);
-}
-
-
-void __cdecl Log::vprintf(const char* fmt, va_list argPtr) {
- vfprintf(logFile, fmt, argPtr);
- fflush(logFile);
-}
-
-
-void __cdecl Log::lazyvprintf(const char* fmt, va_list argPtr) {
- vfprintf(logFile, fmt, argPtr);
-}
-
-
-void Log::print(const std::string& s) {
- fprintf(logFile, "%s", s.c_str());
- fflush(logFile);
-}
-
-
-void Log::println(const std::string& s) {
- fprintf(logFile, "%s\n", s.c_str());
- fflush(logFile);
-}
-
-}
diff --git a/externals/g3dlite/Matrix3.cpp b/externals/g3dlite/Matrix3.cpp
deleted file mode 100644
index b32d938f0f9..00000000000
--- a/externals/g3dlite/Matrix3.cpp
+++ /dev/null
@@ -1,1927 +0,0 @@
-/**
- @file Matrix3.cpp
-
- 3x3 matrix class
-
- @author Morgan McGuire, graphics3d.com
-
- @created 2001-06-02
- @edited 2009-11-15
-
- Copyright 2000-2009, Morgan McGuire.
- All rights reserved.
-*/
-
-#include "G3D/platform.h"
-#include <memory.h>
-#include <assert.h>
-#include "G3D/Matrix3.h"
-#include "G3D/g3dmath.h"
-#include "G3D/BinaryInput.h"
-#include "G3D/BinaryOutput.h"
-#include "G3D/Quat.h"
-#include "G3D/Any.h"
-
-namespace G3D {
-
-const float Matrix3::EPSILON = 1e-06f;
-
-Matrix3::Matrix3(const Any& any) {
- any.verifyName("Matrix3");
- any.verifyType(Any::ARRAY);
- any.verifySize(9);
-
- for (int r = 0; r < 3; ++r) {
- for (int c = 0; c < 3; ++c) {
- elt[r][c] = any[r * 3 + c];
- }
- }
-}
-
-
-Matrix3::operator Any() const {
- Any any(Any::ARRAY, "Matrix3");
- any.resize(9);
- for (int r = 0; r < 3; ++r) {
- for (int c = 0; c < 3; ++c) {
- any[r * 3 + c] = elt[r][c];
- }
- }
-
- return any;
-}
-
-const Matrix3& Matrix3::zero() {
- static Matrix3 m(0, 0, 0, 0, 0, 0, 0, 0, 0);
- return m;
-}
-
-const Matrix3& Matrix3::identity() {
- static Matrix3 m(1, 0, 0, 0, 1, 0, 0, 0, 1);
- return m;
-}
-
-
-const float Matrix3::ms_fSvdEpsilon = 1e-04f;
-const int Matrix3::ms_iSvdMaxIterations = 32;
-
-Matrix3::Matrix3(BinaryInput& b) {
- deserialize(b);
-}
-
-bool Matrix3::fuzzyEq(const Matrix3& b) const {
- for (int r = 0; r < 3; ++r) {
- for (int c = 0; c < 3; ++c) {
- if (! G3D::fuzzyEq(elt[r][c], b[r][c])) {
- return false;
- }
- }
- }
- return true;
-}
-
-
-bool Matrix3::isRightHanded() const{
-
- const Vector3& X = column(0);
- const Vector3& Y = column(1);
- const Vector3& Z = column(2);
-
- const Vector3& W = X.cross(Y);
-
- return W.dot(Z) > 0.0f;
-}
-
-
-bool Matrix3::isOrthonormal() const {
- const Vector3& X = column(0);
- const Vector3& Y = column(1);
- const Vector3& Z = column(2);
-
- return
- (G3D::fuzzyEq(X.dot(Y), 0.0f) &&
- G3D::fuzzyEq(Y.dot(Z), 0.0f) &&
- G3D::fuzzyEq(X.dot(Z), 0.0f) &&
- G3D::fuzzyEq(X.squaredMagnitude(), 1.0f) &&
- G3D::fuzzyEq(Y.squaredMagnitude(), 1.0f) &&
- G3D::fuzzyEq(Z.squaredMagnitude(), 1.0f));
-}
-
-//----------------------------------------------------------------------------
-Matrix3::Matrix3(const Quat& _q) {
- // Implementation from Watt and Watt, pg 362
- // See also http://www.flipcode.com/documents/matrfaq.html#Q54
- Quat q = _q;
- q.unitize();
- float xx = 2.0f * q.x * q.x;
- float xy = 2.0f * q.x * q.y;
- float xz = 2.0f * q.x * q.z;
- float xw = 2.0f * q.x * q.w;
-
- float yy = 2.0f * q.y * q.y;
- float yz = 2.0f * q.y * q.z;
- float yw = 2.0f * q.y * q.w;
-
- float zz = 2.0f * q.z * q.z;
- float zw = 2.0f * q.z * q.w;
-
- set(1.0f - yy - zz, xy - zw, xz + yw,
- xy + zw, 1.0f - xx - zz, yz - xw,
- xz - yw, yz + xw, 1.0f - xx - yy);
-}
-
-//----------------------------------------------------------------------------
-
-Matrix3::Matrix3 (const float aafEntry[3][3]) {
- memcpy(elt, aafEntry, 9*sizeof(float));
-}
-
-//----------------------------------------------------------------------------
-Matrix3::Matrix3 (const Matrix3& rkMatrix) {
- memcpy(elt, rkMatrix.elt, 9*sizeof(float));
-}
-
-//----------------------------------------------------------------------------
-Matrix3::Matrix3(
- float fEntry00, float fEntry01, float fEntry02,
- float fEntry10, float fEntry11, float fEntry12,
- float fEntry20, float fEntry21, float fEntry22) {
- set(fEntry00, fEntry01, fEntry02,
- fEntry10, fEntry11, fEntry12,
- fEntry20, fEntry21, fEntry22);
-}
-
-void Matrix3::set(
- float fEntry00, float fEntry01, float fEntry02,
- float fEntry10, float fEntry11, float fEntry12,
- float fEntry20, float fEntry21, float fEntry22) {
-
- elt[0][0] = fEntry00;
- elt[0][1] = fEntry01;
- elt[0][2] = fEntry02;
- elt[1][0] = fEntry10;
- elt[1][1] = fEntry11;
- elt[1][2] = fEntry12;
- elt[2][0] = fEntry20;
- elt[2][1] = fEntry21;
- elt[2][2] = fEntry22;
-}
-
-
-void Matrix3::deserialize(BinaryInput& b) {
- int r,c;
- for (c = 0; c < 3; ++c) {
- for (r = 0; r < 3; ++r) {
- elt[r][c] = b.readFloat32();
- }
- }
-}
-
-
-void Matrix3::serialize(BinaryOutput& b) const {
- int r,c;
- for (c = 0; c < 3; ++c) {
- for (r = 0; r < 3; ++r) {
- b.writeFloat32(elt[r][c]);
- }
- }
-}
-
-
-//----------------------------------------------------------------------------
-Vector3 Matrix3::column (int iCol) const {
- assert((0 <= iCol) && (iCol < 3));
- return Vector3(elt[0][iCol], elt[1][iCol],
- elt[2][iCol]);
-}
-
-
-const Vector3& Matrix3::row (int iRow) const {
- assert((0 <= iRow) && (iRow < 3));
- return *reinterpret_cast<const Vector3*>(elt[iRow]);
-}
-
-
-void Matrix3::setColumn(int iCol, const Vector3 &vector) {
- debugAssert((iCol >= 0) && (iCol < 3));
- elt[0][iCol] = vector.x;
- elt[1][iCol] = vector.y;
- elt[2][iCol] = vector.z;
-}
-
-
-void Matrix3::setRow(int iRow, const Vector3 &vector) {
- debugAssert((iRow >= 0) && (iRow < 3));
- elt[iRow][0] = vector.x;
- elt[iRow][1] = vector.y;
- elt[iRow][2] = vector.z;
-}
-
-
-//----------------------------------------------------------------------------
-bool Matrix3::operator== (const Matrix3& rkMatrix) const {
- for (int iRow = 0; iRow < 3; iRow++) {
- for (int iCol = 0; iCol < 3; iCol++) {
- if ( elt[iRow][iCol] != rkMatrix.elt[iRow][iCol] )
- return false;
- }
- }
-
- return true;
-}
-
-//----------------------------------------------------------------------------
-bool Matrix3::operator!= (const Matrix3& rkMatrix) const {
- return !operator==(rkMatrix);
-}
-
-//----------------------------------------------------------------------------
-Matrix3 Matrix3::operator+ (const Matrix3& rkMatrix) const {
- Matrix3 kSum;
-
- for (int iRow = 0; iRow < 3; iRow++) {
- for (int iCol = 0; iCol < 3; iCol++) {
- kSum.elt[iRow][iCol] = elt[iRow][iCol] +
- rkMatrix.elt[iRow][iCol];
- }
- }
-
- return kSum;
-}
-
-//----------------------------------------------------------------------------
-Matrix3 Matrix3::operator- (const Matrix3& rkMatrix) const {
- Matrix3 kDiff;
-
- for (int iRow = 0; iRow < 3; iRow++) {
- for (int iCol = 0; iCol < 3; iCol++) {
- kDiff.elt[iRow][iCol] = elt[iRow][iCol] -
- rkMatrix.elt[iRow][iCol];
- }
- }
-
- return kDiff;
-}
-
-//----------------------------------------------------------------------------
-Matrix3 Matrix3::operator* (const Matrix3& rkMatrix) const {
- Matrix3 kProd;
-
- for (int iRow = 0; iRow < 3; iRow++) {
- for (int iCol = 0; iCol < 3; iCol++) {
- kProd.elt[iRow][iCol] =
- elt[iRow][0] * rkMatrix.elt[0][iCol] +
- elt[iRow][1] * rkMatrix.elt[1][iCol] +
- elt[iRow][2] * rkMatrix.elt[2][iCol];
- }
- }
-
- return kProd;
-}
-
-Matrix3& Matrix3::operator+= (const Matrix3& rkMatrix) {
- for (int iRow = 0; iRow < 3; iRow++) {
- for (int iCol = 0; iCol < 3; iCol++) {
- elt[iRow][iCol] = elt[iRow][iCol] + rkMatrix.elt[iRow][iCol];
- }
- }
-
- return *this;
-}
-
-Matrix3& Matrix3::operator-= (const Matrix3& rkMatrix) {
- for (int iRow = 0; iRow < 3; iRow++) {
- for (int iCol = 0; iCol < 3; iCol++) {
- elt[iRow][iCol] = elt[iRow][iCol] - rkMatrix.elt[iRow][iCol];
- }
- }
-
- return *this;
-}
-
-Matrix3& Matrix3::operator*= (const Matrix3& rkMatrix) {
- Matrix3 mulMat;
- for (int iRow = 0; iRow < 3; iRow++) {
- for (int iCol = 0; iCol < 3; iCol++) {
- mulMat.elt[iRow][iCol] =
- elt[iRow][0] * rkMatrix.elt[0][iCol] +
- elt[iRow][1] * rkMatrix.elt[1][iCol] +
- elt[iRow][2] * rkMatrix.elt[2][iCol];
- }
- }
-
- *this = mulMat;
- return *this;
-}
-
-//----------------------------------------------------------------------------
-Matrix3 Matrix3::operator- () const {
- Matrix3 kNeg;
-
- for (int iRow = 0; iRow < 3; iRow++) {
- for (int iCol = 0; iCol < 3; iCol++) {
- kNeg[iRow][iCol] = -elt[iRow][iCol];
- }
- }
-
- return kNeg;
-}
-
-//----------------------------------------------------------------------------
-Matrix3 Matrix3::operator* (float fScalar) const {
- Matrix3 kProd;
-
- for (int iRow = 0; iRow < 3; iRow++) {
- for (int iCol = 0; iCol < 3; iCol++) {
- kProd[iRow][iCol] = fScalar * elt[iRow][iCol];
- }
- }
-
- return kProd;
-}
-
-Matrix3& Matrix3::operator/= (float fScalar) {
- return *this *= (1.0f / fScalar);
-}
-
-Matrix3& Matrix3::operator*= (float fScalar) {
-
- for (int iRow = 0; iRow < 3; iRow++) {
- for (int iCol = 0; iCol < 3; iCol++) {
- elt[iRow][iCol] *= fScalar;
- }
- }
-
- return *this;
-}
-
-//----------------------------------------------------------------------------
-Matrix3 operator* (double fScalar, const Matrix3& rkMatrix) {
- Matrix3 kProd;
-
- for (int iRow = 0; iRow < 3; iRow++) {
- for (int iCol = 0; iCol < 3; iCol++) {
- kProd[iRow][iCol] = fScalar * rkMatrix.elt[iRow][iCol];
- }
- }
-
- return kProd;
-}
-
-Matrix3 operator* (float fScalar, const Matrix3& rkMatrix) {
- return (double)fScalar * rkMatrix;
-}
-
-
-Matrix3 operator* (int fScalar, const Matrix3& rkMatrix) {
- return (double)fScalar * rkMatrix;
-}
-//----------------------------------------------------------------------------
-Matrix3 Matrix3::transpose () const {
- Matrix3 kTranspose;
-
- for (int iRow = 0; iRow < 3; iRow++) {
- for (int iCol = 0; iCol < 3; iCol++) {
- kTranspose[iRow][iCol] = elt[iCol][iRow];
- }
- }
-
- return kTranspose;
-}
-
-//----------------------------------------------------------------------------
-bool Matrix3::inverse (Matrix3& rkInverse, float fTolerance) const {
- // Invert a 3x3 using cofactors. This is about 8 times faster than
- // the Numerical Recipes code which uses Gaussian elimination.
-
- rkInverse[0][0] = elt[1][1] * elt[2][2] -
- elt[1][2] * elt[2][1];
- rkInverse[0][1] = elt[0][2] * elt[2][1] -
- elt[0][1] * elt[2][2];
- rkInverse[0][2] = elt[0][1] * elt[1][2] -
- elt[0][2] * elt[1][1];
- rkInverse[1][0] = elt[1][2] * elt[2][0] -
- elt[1][0] * elt[2][2];
- rkInverse[1][1] = elt[0][0] * elt[2][2] -
- elt[0][2] * elt[2][0];
- rkInverse[1][2] = elt[0][2] * elt[1][0] -
- elt[0][0] * elt[1][2];
- rkInverse[2][0] = elt[1][0] * elt[2][1] -
- elt[1][1] * elt[2][0];
- rkInverse[2][1] = elt[0][1] * elt[2][0] -
- elt[0][0] * elt[2][1];
- rkInverse[2][2] = elt[0][0] * elt[1][1] -
- elt[0][1] * elt[1][0];
-
- float fDet =
- elt[0][0] * rkInverse[0][0] +
- elt[0][1] * rkInverse[1][0] +
- elt[0][2] * rkInverse[2][0];
-
- if ( G3D::abs(fDet) <= fTolerance )
- return false;
-
- float fInvDet = 1.0 / fDet;
-
- for (int iRow = 0; iRow < 3; iRow++) {
- for (int iCol = 0; iCol < 3; iCol++)
- rkInverse[iRow][iCol] *= fInvDet;
- }
-
- return true;
-}
-
-//----------------------------------------------------------------------------
-Matrix3 Matrix3::inverse (float fTolerance) const {
- Matrix3 kInverse = Matrix3::zero();
- inverse(kInverse, fTolerance);
- return kInverse;
-}
-
-//----------------------------------------------------------------------------
-float Matrix3::determinant () const {
- float fCofactor00 = elt[1][1] * elt[2][2] -
- elt[1][2] * elt[2][1];
- float fCofactor10 = elt[1][2] * elt[2][0] -
- elt[1][0] * elt[2][2];
- float fCofactor20 = elt[1][0] * elt[2][1] -
- elt[1][1] * elt[2][0];
-
- float fDet =
- elt[0][0] * fCofactor00 +
- elt[0][1] * fCofactor10 +
- elt[0][2] * fCofactor20;
-
- return fDet;
-}
-
-//----------------------------------------------------------------------------
-void Matrix3::bidiagonalize (Matrix3& kA, Matrix3& kL,
- Matrix3& kR) {
- float afV[3], afW[3];
- float fLength, fSign, fT1, fInvT1, fT2;
- bool bIdentity;
-
- // map first column to (*,0,0)
- fLength = sqrt(kA[0][0] * kA[0][0] + kA[1][0] * kA[1][0] +
- kA[2][0] * kA[2][0]);
-
- if ( fLength > 0.0 ) {
- fSign = (kA[0][0] > 0.0 ? 1.0 : -1.0);
- fT1 = kA[0][0] + fSign * fLength;
- fInvT1 = 1.0 / fT1;
- afV[1] = kA[1][0] * fInvT1;
- afV[2] = kA[2][0] * fInvT1;
-
- fT2 = -2.0 / (1.0 + afV[1] * afV[1] + afV[2] * afV[2]);
- afW[0] = fT2 * (kA[0][0] + kA[1][0] * afV[1] + kA[2][0] * afV[2]);
- afW[1] = fT2 * (kA[0][1] + kA[1][1] * afV[1] + kA[2][1] * afV[2]);
- afW[2] = fT2 * (kA[0][2] + kA[1][2] * afV[1] + kA[2][2] * afV[2]);
- kA[0][0] += afW[0];
- kA[0][1] += afW[1];
- kA[0][2] += afW[2];
- kA[1][1] += afV[1] * afW[1];
- kA[1][2] += afV[1] * afW[2];
- kA[2][1] += afV[2] * afW[1];
- kA[2][2] += afV[2] * afW[2];
-
- kL[0][0] = 1.0 + fT2;
- kL[0][1] = kL[1][0] = fT2 * afV[1];
- kL[0][2] = kL[2][0] = fT2 * afV[2];
- kL[1][1] = 1.0 + fT2 * afV[1] * afV[1];
- kL[1][2] = kL[2][1] = fT2 * afV[1] * afV[2];
- kL[2][2] = 1.0 + fT2 * afV[2] * afV[2];
- bIdentity = false;
- } else {
- kL = Matrix3::identity();
- bIdentity = true;
- }
-
- // map first row to (*,*,0)
- fLength = sqrt(kA[0][1] * kA[0][1] + kA[0][2] * kA[0][2]);
-
- if ( fLength > 0.0 ) {
- fSign = (kA[0][1] > 0.0 ? 1.0 : -1.0);
- fT1 = kA[0][1] + fSign * fLength;
- afV[2] = kA[0][2] / fT1;
-
- fT2 = -2.0 / (1.0 + afV[2] * afV[2]);
- afW[0] = fT2 * (kA[0][1] + kA[0][2] * afV[2]);
- afW[1] = fT2 * (kA[1][1] + kA[1][2] * afV[2]);
- afW[2] = fT2 * (kA[2][1] + kA[2][2] * afV[2]);
- kA[0][1] += afW[0];
- kA[1][1] += afW[1];
- kA[1][2] += afW[1] * afV[2];
- kA[2][1] += afW[2];
- kA[2][2] += afW[2] * afV[2];
-
- kR[0][0] = 1.0;
- kR[0][1] = kR[1][0] = 0.0;
- kR[0][2] = kR[2][0] = 0.0;
- kR[1][1] = 1.0 + fT2;
- kR[1][2] = kR[2][1] = fT2 * afV[2];
- kR[2][2] = 1.0 + fT2 * afV[2] * afV[2];
- } else {
- kR = Matrix3::identity();
- }
-
- // map second column to (*,*,0)
- fLength = sqrt(kA[1][1] * kA[1][1] + kA[2][1] * kA[2][1]);
-
- if ( fLength > 0.0 ) {
- fSign = (kA[1][1] > 0.0 ? 1.0 : -1.0);
- fT1 = kA[1][1] + fSign * fLength;
- afV[2] = kA[2][1] / fT1;
-
- fT2 = -2.0 / (1.0 + afV[2] * afV[2]);
- afW[1] = fT2 * (kA[1][1] + kA[2][1] * afV[2]);
- afW[2] = fT2 * (kA[1][2] + kA[2][2] * afV[2]);
- kA[1][1] += afW[1];
- kA[1][2] += afW[2];
- kA[2][2] += afV[2] * afW[2];
-
- float fA = 1.0 + fT2;
- float fB = fT2 * afV[2];
- float fC = 1.0 + fB * afV[2];
-
- if ( bIdentity ) {
- kL[0][0] = 1.0;
- kL[0][1] = kL[1][0] = 0.0;
- kL[0][2] = kL[2][0] = 0.0;
- kL[1][1] = fA;
- kL[1][2] = kL[2][1] = fB;
- kL[2][2] = fC;
- } else {
- for (int iRow = 0; iRow < 3; iRow++) {
- float fTmp0 = kL[iRow][1];
- float fTmp1 = kL[iRow][2];
- kL[iRow][1] = fA * fTmp0 + fB * fTmp1;
- kL[iRow][2] = fB * fTmp0 + fC * fTmp1;
- }
- }
- }
-}
-
-//----------------------------------------------------------------------------
-void Matrix3::golubKahanStep (Matrix3& kA, Matrix3& kL,
- Matrix3& kR) {
- float fT11 = kA[0][1] * kA[0][1] + kA[1][1] * kA[1][1];
- float fT22 = kA[1][2] * kA[1][2] + kA[2][2] * kA[2][2];
- float fT12 = kA[1][1] * kA[1][2];
- float fTrace = fT11 + fT22;
- float fDiff = fT11 - fT22;
- float fDiscr = sqrt(fDiff * fDiff + 4.0 * fT12 * fT12);
- float fRoot1 = 0.5 * (fTrace + fDiscr);
- float fRoot2 = 0.5 * (fTrace - fDiscr);
-
- // adjust right
- float fY = kA[0][0] - (G3D::abs(fRoot1 - fT22) <=
- G3D::abs(fRoot2 - fT22) ? fRoot1 : fRoot2);
- float fZ = kA[0][1];
- float fInvLength = 1.0 / sqrt(fY * fY + fZ * fZ);
- float fSin = fZ * fInvLength;
- float fCos = -fY * fInvLength;
-
- float fTmp0 = kA[0][0];
- float fTmp1 = kA[0][1];
- kA[0][0] = fCos * fTmp0 - fSin * fTmp1;
- kA[0][1] = fSin * fTmp0 + fCos * fTmp1;
- kA[1][0] = -fSin * kA[1][1];
- kA[1][1] *= fCos;
-
- int iRow;
-
- for (iRow = 0; iRow < 3; iRow++) {
- fTmp0 = kR[0][iRow];
- fTmp1 = kR[1][iRow];
- kR[0][iRow] = fCos * fTmp0 - fSin * fTmp1;
- kR[1][iRow] = fSin * fTmp0 + fCos * fTmp1;
- }
-
- // adjust left
- fY = kA[0][0];
-
- fZ = kA[1][0];
-
- fInvLength = 1.0 / sqrt(fY * fY + fZ * fZ);
-
- fSin = fZ * fInvLength;
-
- fCos = -fY * fInvLength;
-
- kA[0][0] = fCos * kA[0][0] - fSin * kA[1][0];
-
- fTmp0 = kA[0][1];
-
- fTmp1 = kA[1][1];
-
- kA[0][1] = fCos * fTmp0 - fSin * fTmp1;
-
- kA[1][1] = fSin * fTmp0 + fCos * fTmp1;
-
- kA[0][2] = -fSin * kA[1][2];
-
- kA[1][2] *= fCos;
-
- int iCol;
-
- for (iCol = 0; iCol < 3; iCol++) {
- fTmp0 = kL[iCol][0];
- fTmp1 = kL[iCol][1];
- kL[iCol][0] = fCos * fTmp0 - fSin * fTmp1;
- kL[iCol][1] = fSin * fTmp0 + fCos * fTmp1;
- }
-
- // adjust right
- fY = kA[0][1];
-
- fZ = kA[0][2];
-
- fInvLength = 1.0 / sqrt(fY * fY + fZ * fZ);
-
- fSin = fZ * fInvLength;
-
- fCos = -fY * fInvLength;
-
- kA[0][1] = fCos * kA[0][1] - fSin * kA[0][2];
-
- fTmp0 = kA[1][1];
-
- fTmp1 = kA[1][2];
-
- kA[1][1] = fCos * fTmp0 - fSin * fTmp1;
-
- kA[1][2] = fSin * fTmp0 + fCos * fTmp1;
-
- kA[2][1] = -fSin * kA[2][2];
-
- kA[2][2] *= fCos;
-
- for (iRow = 0; iRow < 3; iRow++) {
- fTmp0 = kR[1][iRow];
- fTmp1 = kR[2][iRow];
- kR[1][iRow] = fCos * fTmp0 - fSin * fTmp1;
- kR[2][iRow] = fSin * fTmp0 + fCos * fTmp1;
- }
-
- // adjust left
- fY = kA[1][1];
-
- fZ = kA[2][1];
-
- fInvLength = 1.0 / sqrt(fY * fY + fZ * fZ);
-
- fSin = fZ * fInvLength;
-
- fCos = -fY * fInvLength;
-
- kA[1][1] = fCos * kA[1][1] - fSin * kA[2][1];
-
- fTmp0 = kA[1][2];
-
- fTmp1 = kA[2][2];
-
- kA[1][2] = fCos * fTmp0 - fSin * fTmp1;
-
- kA[2][2] = fSin * fTmp0 + fCos * fTmp1;
-
- for (iCol = 0; iCol < 3; iCol++) {
- fTmp0 = kL[iCol][1];
- fTmp1 = kL[iCol][2];
- kL[iCol][1] = fCos * fTmp0 - fSin * fTmp1;
- kL[iCol][2] = fSin * fTmp0 + fCos * fTmp1;
- }
-}
-
-//----------------------------------------------------------------------------
-void Matrix3::singularValueDecomposition (Matrix3& kL, Vector3& kS,
- Matrix3& kR) const {
- int iRow, iCol;
-
- Matrix3 kA = *this;
- bidiagonalize(kA, kL, kR);
-
- for (int i = 0; i < ms_iSvdMaxIterations; i++) {
- float fTmp, fTmp0, fTmp1;
- float fSin0, fCos0, fTan0;
- float fSin1, fCos1, fTan1;
-
- bool bTest1 = (G3D::abs(kA[0][1]) <=
- ms_fSvdEpsilon * (G3D::abs(kA[0][0]) + G3D::abs(kA[1][1])));
- bool bTest2 = (G3D::abs(kA[1][2]) <=
- ms_fSvdEpsilon * (G3D::abs(kA[1][1]) + G3D::abs(kA[2][2])));
-
- if ( bTest1 ) {
- if ( bTest2 ) {
- kS[0] = kA[0][0];
- kS[1] = kA[1][1];
- kS[2] = kA[2][2];
- break;
- } else {
- // 2x2 closed form factorization
- fTmp = (kA[1][1] * kA[1][1] - kA[2][2] * kA[2][2] +
- kA[1][2] * kA[1][2]) / (kA[1][2] * kA[2][2]);
- fTan0 = 0.5 * (fTmp + sqrt(fTmp * fTmp + 4.0));
- fCos0 = 1.0 / sqrt(1.0 + fTan0 * fTan0);
- fSin0 = fTan0 * fCos0;
-
- for (iCol = 0; iCol < 3; iCol++) {
- fTmp0 = kL[iCol][1];
- fTmp1 = kL[iCol][2];
- kL[iCol][1] = fCos0 * fTmp0 - fSin0 * fTmp1;
- kL[iCol][2] = fSin0 * fTmp0 + fCos0 * fTmp1;
- }
-
- fTan1 = (kA[1][2] - kA[2][2] * fTan0) / kA[1][1];
- fCos1 = 1.0 / sqrt(1.0 + fTan1 * fTan1);
- fSin1 = -fTan1 * fCos1;
-
- for (iRow = 0; iRow < 3; iRow++) {
- fTmp0 = kR[1][iRow];
- fTmp1 = kR[2][iRow];
- kR[1][iRow] = fCos1 * fTmp0 - fSin1 * fTmp1;
- kR[2][iRow] = fSin1 * fTmp0 + fCos1 * fTmp1;
- }
-
- kS[0] = kA[0][0];
- kS[1] = fCos0 * fCos1 * kA[1][1] -
- fSin1 * (fCos0 * kA[1][2] - fSin0 * kA[2][2]);
- kS[2] = fSin0 * fSin1 * kA[1][1] +
- fCos1 * (fSin0 * kA[1][2] + fCos0 * kA[2][2]);
- break;
- }
- } else {
- if ( bTest2 ) {
- // 2x2 closed form factorization
- fTmp = (kA[0][0] * kA[0][0] + kA[1][1] * kA[1][1] -
- kA[0][1] * kA[0][1]) / (kA[0][1] * kA[1][1]);
- fTan0 = 0.5 * ( -fTmp + sqrt(fTmp * fTmp + 4.0));
- fCos0 = 1.0 / sqrt(1.0 + fTan0 * fTan0);
- fSin0 = fTan0 * fCos0;
-
- for (iCol = 0; iCol < 3; iCol++) {
- fTmp0 = kL[iCol][0];
- fTmp1 = kL[iCol][1];
- kL[iCol][0] = fCos0 * fTmp0 - fSin0 * fTmp1;
- kL[iCol][1] = fSin0 * fTmp0 + fCos0 * fTmp1;
- }
-
- fTan1 = (kA[0][1] - kA[1][1] * fTan0) / kA[0][0];
- fCos1 = 1.0 / sqrt(1.0 + fTan1 * fTan1);
- fSin1 = -fTan1 * fCos1;
-
- for (iRow = 0; iRow < 3; iRow++) {
- fTmp0 = kR[0][iRow];
- fTmp1 = kR[1][iRow];
- kR[0][iRow] = fCos1 * fTmp0 - fSin1 * fTmp1;
- kR[1][iRow] = fSin1 * fTmp0 + fCos1 * fTmp1;
- }
-
- kS[0] = fCos0 * fCos1 * kA[0][0] -
- fSin1 * (fCos0 * kA[0][1] - fSin0 * kA[1][1]);
- kS[1] = fSin0 * fSin1 * kA[0][0] +
- fCos1 * (fSin0 * kA[0][1] + fCos0 * kA[1][1]);
- kS[2] = kA[2][2];
- break;
- } else {
- golubKahanStep(kA, kL, kR);
- }
- }
- }
-
- // positize diagonal
- for (iRow = 0; iRow < 3; iRow++) {
- if ( kS[iRow] < 0.0 ) {
- kS[iRow] = -kS[iRow];
-
- for (iCol = 0; iCol < 3; iCol++)
- kR[iRow][iCol] = -kR[iRow][iCol];
- }
- }
-}
-
-//----------------------------------------------------------------------------
-void Matrix3::singularValueComposition (const Matrix3& kL,
- const Vector3& kS, const Matrix3& kR) {
- int iRow, iCol;
- Matrix3 kTmp;
-
- // product S*R
- for (iRow = 0; iRow < 3; iRow++) {
- for (iCol = 0; iCol < 3; iCol++)
- kTmp[iRow][iCol] = kS[iRow] * kR[iRow][iCol];
- }
-
- // product L*S*R
- for (iRow = 0; iRow < 3; iRow++) {
- for (iCol = 0; iCol < 3; iCol++) {
- elt[iRow][iCol] = 0.0;
-
- for (int iMid = 0; iMid < 3; iMid++)
- elt[iRow][iCol] += kL[iRow][iMid] * kTmp[iMid][iCol];
- }
- }
-}
-
-//----------------------------------------------------------------------------
-void Matrix3::orthonormalize () {
- // Algorithm uses Gram-Schmidt orthogonalization. If 'this' matrix is
- // M = [m0|m1|m2], then orthonormal output matrix is Q = [q0|q1|q2],
- //
- // q0 = m0/|m0|
- // q1 = (m1-(q0*m1)q0)/|m1-(q0*m1)q0|
- // q2 = (m2-(q0*m2)q0-(q1*m2)q1)/|m2-(q0*m2)q0-(q1*m2)q1|
- //
- // where |V| indicates length of vector V and A*B indicates dot
- // product of vectors A and B.
-
- // compute q0
- float fInvLength = 1.0 / sqrt(elt[0][0] * elt[0][0]
- + elt[1][0] * elt[1][0] +
- elt[2][0] * elt[2][0]);
-
- elt[0][0] *= fInvLength;
- elt[1][0] *= fInvLength;
- elt[2][0] *= fInvLength;
-
- // compute q1
- float fDot0 =
- elt[0][0] * elt[0][1] +
- elt[1][0] * elt[1][1] +
- elt[2][0] * elt[2][1];
-
- elt[0][1] -= fDot0 * elt[0][0];
- elt[1][1] -= fDot0 * elt[1][0];
- elt[2][1] -= fDot0 * elt[2][0];
-
- fInvLength = 1.0 / sqrt(elt[0][1] * elt[0][1] +
- elt[1][1] * elt[1][1] +
- elt[2][1] * elt[2][1]);
-
- elt[0][1] *= fInvLength;
- elt[1][1] *= fInvLength;
- elt[2][1] *= fInvLength;
-
- // compute q2
- float fDot1 =
- elt[0][1] * elt[0][2] +
- elt[1][1] * elt[1][2] +
- elt[2][1] * elt[2][2];
-
- fDot0 =
- elt[0][0] * elt[0][2] +
- elt[1][0] * elt[1][2] +
- elt[2][0] * elt[2][2];
-
- elt[0][2] -= fDot0 * elt[0][0] + fDot1 * elt[0][1];
- elt[1][2] -= fDot0 * elt[1][0] + fDot1 * elt[1][1];
- elt[2][2] -= fDot0 * elt[2][0] + fDot1 * elt[2][1];
-
- fInvLength = 1.0 / sqrt(elt[0][2] * elt[0][2] +
- elt[1][2] * elt[1][2] +
- elt[2][2] * elt[2][2]);
-
- elt[0][2] *= fInvLength;
- elt[1][2] *= fInvLength;
- elt[2][2] *= fInvLength;
-}
-
-//----------------------------------------------------------------------------
-void Matrix3::qDUDecomposition (Matrix3& kQ,
- Vector3& kD, Vector3& kU) const {
- // Factor M = QR = QDU where Q is orthogonal, D is diagonal,
- // and U is upper triangular with ones on its diagonal. Algorithm uses
- // Gram-Schmidt orthogonalization (the QR algorithm).
- //
- // If M = [ m0 | m1 | m2 ] and Q = [ q0 | q1 | q2 ], then
- //
- // q0 = m0/|m0|
- // q1 = (m1-(q0*m1)q0)/|m1-(q0*m1)q0|
- // q2 = (m2-(q0*m2)q0-(q1*m2)q1)/|m2-(q0*m2)q0-(q1*m2)q1|
- //
- // where |V| indicates length of vector V and A*B indicates dot
- // product of vectors A and B. The matrix R has entries
- //
- // r00 = q0*m0 r01 = q0*m1 r02 = q0*m2
- // r10 = 0 r11 = q1*m1 r12 = q1*m2
- // r20 = 0 r21 = 0 r22 = q2*m2
- //
- // so D = diag(r00,r11,r22) and U has entries u01 = r01/r00,
- // u02 = r02/r00, and u12 = r12/r11.
-
- // Q = rotation
- // D = scaling
- // U = shear
-
- // D stores the three diagonal entries r00, r11, r22
- // U stores the entries U[0] = u01, U[1] = u02, U[2] = u12
-
- // build orthogonal matrix Q
- float fInvLength = 1.0 / sqrt(elt[0][0] * elt[0][0]
- + elt[1][0] * elt[1][0] +
- elt[2][0] * elt[2][0]);
- kQ[0][0] = elt[0][0] * fInvLength;
- kQ[1][0] = elt[1][0] * fInvLength;
- kQ[2][0] = elt[2][0] * fInvLength;
-
- float fDot = kQ[0][0] * elt[0][1] + kQ[1][0] * elt[1][1] +
- kQ[2][0] * elt[2][1];
- kQ[0][1] = elt[0][1] - fDot * kQ[0][0];
- kQ[1][1] = elt[1][1] - fDot * kQ[1][0];
- kQ[2][1] = elt[2][1] - fDot * kQ[2][0];
- fInvLength = 1.0 / sqrt(kQ[0][1] * kQ[0][1] + kQ[1][1] * kQ[1][1] +
- kQ[2][1] * kQ[2][1]);
- kQ[0][1] *= fInvLength;
- kQ[1][1] *= fInvLength;
- kQ[2][1] *= fInvLength;
-
- fDot = kQ[0][0] * elt[0][2] + kQ[1][0] * elt[1][2] +
- kQ[2][0] * elt[2][2];
- kQ[0][2] = elt[0][2] - fDot * kQ[0][0];
- kQ[1][2] = elt[1][2] - fDot * kQ[1][0];
- kQ[2][2] = elt[2][2] - fDot * kQ[2][0];
- fDot = kQ[0][1] * elt[0][2] + kQ[1][1] * elt[1][2] +
- kQ[2][1] * elt[2][2];
- kQ[0][2] -= fDot * kQ[0][1];
- kQ[1][2] -= fDot * kQ[1][1];
- kQ[2][2] -= fDot * kQ[2][1];
- fInvLength = 1.0 / sqrt(kQ[0][2] * kQ[0][2] + kQ[1][2] * kQ[1][2] +
- kQ[2][2] * kQ[2][2]);
- kQ[0][2] *= fInvLength;
- kQ[1][2] *= fInvLength;
- kQ[2][2] *= fInvLength;
-
- // guarantee that orthogonal matrix has determinant 1 (no reflections)
- float fDet = kQ[0][0] * kQ[1][1] * kQ[2][2] + kQ[0][1] * kQ[1][2] * kQ[2][0] +
- kQ[0][2] * kQ[1][0] * kQ[2][1] - kQ[0][2] * kQ[1][1] * kQ[2][0] -
- kQ[0][1] * kQ[1][0] * kQ[2][2] - kQ[0][0] * kQ[1][2] * kQ[2][1];
-
- if ( fDet < 0.0 ) {
- for (int iRow = 0; iRow < 3; iRow++)
- for (int iCol = 0; iCol < 3; iCol++)
- kQ[iRow][iCol] = -kQ[iRow][iCol];
- }
-
- // build "right" matrix R
- Matrix3 kR;
-
- kR[0][0] = kQ[0][0] * elt[0][0] + kQ[1][0] * elt[1][0] +
- kQ[2][0] * elt[2][0];
-
- kR[0][1] = kQ[0][0] * elt[0][1] + kQ[1][0] * elt[1][1] +
- kQ[2][0] * elt[2][1];
-
- kR[1][1] = kQ[0][1] * elt[0][1] + kQ[1][1] * elt[1][1] +
- kQ[2][1] * elt[2][1];
-
- kR[0][2] = kQ[0][0] * elt[0][2] + kQ[1][0] * elt[1][2] +
- kQ[2][0] * elt[2][2];
-
- kR[1][2] = kQ[0][1] * elt[0][2] + kQ[1][1] * elt[1][2] +
- kQ[2][1] * elt[2][2];
-
- kR[2][2] = kQ[0][2] * elt[0][2] + kQ[1][2] * elt[1][2] +
- kQ[2][2] * elt[2][2];
-
- // the scaling component
- kD[0] = kR[0][0];
-
- kD[1] = kR[1][1];
-
- kD[2] = kR[2][2];
-
- // the shear component
- float fInvD0 = 1.0 / kD[0];
-
- kU[0] = kR[0][1] * fInvD0;
-
- kU[1] = kR[0][2] * fInvD0;
-
- kU[2] = kR[1][2] / kD[1];
-}
-
-//----------------------------------------------------------------------------
-void Matrix3::polarDecomposition(Matrix3 &R, Matrix3 &S) const{
- /*
- Polar decomposition of a matrix. Based on pseudocode from
- Nicholas J Higham, "Computing the Polar Decomposition -- with
- Applications Siam Journal of Science and Statistical Computing, Vol 7, No. 4,
- October 1986.
-
- Decomposes A into R*S, where R is orthogonal and S is symmetric.
-
- Ken Shoemake's "Matrix animation and polar decomposition"
- in Proceedings of the conference on Graphics interface '92
- seems to be better known in the world of graphics, but Higham's version
- uses a scaling constant that can lead to faster convergence than
- Shoemake's when the initial matrix is far from orthogonal.
- */
-
- Matrix3 X = *this;
- Matrix3 tmp = X.inverse();
- Matrix3 Xit = tmp.transpose();
- int iter = 0;
-
- const int MAX_ITERS = 100;
-
- const double eps = 50 * std::numeric_limits<float>::epsilon();
- const float BigEps = 50 * eps;
-
- /* Higham suggests using OneNorm(Xit-X) < eps * OneNorm(X)
- * as the convergence criterion, but OneNorm(X) should quickly
- * settle down to something between 1 and 1.7, so just comparing
- * with eps seems sufficient.
- *--------------------------------------------------------------- */
-
- double resid = X.diffOneNorm(Xit);
- while (resid > eps && iter < MAX_ITERS) {
-
- tmp = X.inverse();
- Xit = tmp.transpose();
-
- if (resid < BigEps) {
- // close enough use simple iteration
- X += Xit;
- X *= 0.5f;
- }
- else {
- // not close to convergence, compute acceleration factor
- float gamma = sqrt( sqrt(
- (Xit.l1Norm()* Xit.lInfNorm())/(X.l1Norm()*X.lInfNorm()) ) );
-
- X *= 0.5f * gamma;
- tmp = Xit;
- tmp *= 0.5f / gamma;
- X += tmp;
- }
-
- resid = X.diffOneNorm(Xit);
- iter++;
- }
-
- R = X;
- tmp = R.transpose();
-
- S = tmp * (*this);
-
- // S := (S + S^t)/2 one more time to make sure it is symmetric
- tmp = S.transpose();
-
- S += tmp;
- S *= 0.5f;
-
-#ifdef G3D_DEBUG
- // Check iter limit
- assert(iter < MAX_ITERS);
-
- // Check A = R*S
- tmp = R*S;
- resid = tmp.diffOneNorm(*this);
- assert(resid < eps);
-
- // Check R is orthogonal
- tmp = R*R.transpose();
- resid = tmp.diffOneNorm(Matrix3::identity());
- assert(resid < eps);
-
- // Check that S is symmetric
- tmp = S.transpose();
- resid = tmp.diffOneNorm(S);
- assert(resid < eps);
-#endif
-}
-
-//----------------------------------------------------------------------------
-float Matrix3::maxCubicRoot (float afCoeff[3]) {
- // Spectral norm is for A^T*A, so characteristic polynomial
- // P(x) = c[0]+c[1]*x+c[2]*x^2+x^3 has three positive float roots.
- // This yields the assertions c[0] < 0 and c[2]*c[2] >= 3*c[1].
-
- // quick out for uniform scale (triple root)
- const float fOneThird = 1.0f / 3.0f;
- const float fEpsilon = 1e-06f;
- float fDiscr = afCoeff[2] * afCoeff[2] - 3.0f * afCoeff[1];
-
- if ( fDiscr <= fEpsilon )
- return -fOneThird*afCoeff[2];
-
- // Compute an upper bound on roots of P(x). This assumes that A^T*A
- // has been scaled by its largest entry.
- float fX = 1.0f;
-
- float fPoly = afCoeff[0] + fX * (afCoeff[1] + fX * (afCoeff[2] + fX));
-
- if ( fPoly < 0.0f ) {
- // uses a matrix norm to find an upper bound on maximum root
- fX = G3D::abs(afCoeff[0]);
- float fTmp = 1.0 + G3D::abs(afCoeff[1]);
-
- if ( fTmp > fX )
- fX = fTmp;
-
- fTmp = 1.0 + G3D::abs(afCoeff[2]);
-
- if ( fTmp > fX )
- fX = fTmp;
- }
-
- // Newton's method to find root
- float fTwoC2 = 2.0f * afCoeff[2];
-
- for (int i = 0; i < 16; i++) {
- fPoly = afCoeff[0] + fX * (afCoeff[1] + fX * (afCoeff[2] + fX));
-
- if ( G3D::abs(fPoly) <= fEpsilon )
- return fX;
-
- float fDeriv = afCoeff[1] + fX * (fTwoC2 + 3.0f * fX);
-
- fX -= fPoly / fDeriv;
- }
-
- return fX;
-}
-
-//----------------------------------------------------------------------------
-float Matrix3::spectralNorm () const {
- Matrix3 kP;
- int iRow, iCol;
- float fPmax = 0.0;
-
- for (iRow = 0; iRow < 3; iRow++) {
- for (iCol = 0; iCol < 3; iCol++) {
- kP[iRow][iCol] = 0.0;
-
- for (int iMid = 0; iMid < 3; iMid++) {
- kP[iRow][iCol] +=
- elt[iMid][iRow] * elt[iMid][iCol];
- }
-
- if ( kP[iRow][iCol] > fPmax )
- fPmax = kP[iRow][iCol];
- }
- }
-
- float fInvPmax = 1.0 / fPmax;
-
- for (iRow = 0; iRow < 3; iRow++) {
- for (iCol = 0; iCol < 3; iCol++)
- kP[iRow][iCol] *= fInvPmax;
- }
-
- float afCoeff[3];
- afCoeff[0] = -(kP[0][0] * (kP[1][1] * kP[2][2] - kP[1][2] * kP[2][1]) +
- kP[0][1] * (kP[2][0] * kP[1][2] - kP[1][0] * kP[2][2]) +
- kP[0][2] * (kP[1][0] * kP[2][1] - kP[2][0] * kP[1][1]));
- afCoeff[1] = kP[0][0] * kP[1][1] - kP[0][1] * kP[1][0] +
- kP[0][0] * kP[2][2] - kP[0][2] * kP[2][0] +
- kP[1][1] * kP[2][2] - kP[1][2] * kP[2][1];
- afCoeff[2] = -(kP[0][0] + kP[1][1] + kP[2][2]);
-
- float fRoot = maxCubicRoot(afCoeff);
- float fNorm = sqrt(fPmax * fRoot);
- return fNorm;
-}
-
-//----------------------------------------------------------------------------
-float Matrix3::squaredFrobeniusNorm() const {
- float norm2 = 0;
- const float* e = &elt[0][0];
-
- for (int i = 0; i < 9; ++i){
- norm2 += (*e) * (*e);
- }
-
- return norm2;
-}
-
-//----------------------------------------------------------------------------
-float Matrix3::frobeniusNorm() const {
- return sqrtf(squaredFrobeniusNorm());
-}
-
-//----------------------------------------------------------------------------
-float Matrix3::l1Norm() const {
- // The one norm of a matrix is the max column sum in absolute value.
- float oneNorm = 0;
- for (int c = 0; c < 3; ++c) {
-
- float f = fabs(elt[0][c])+ fabs(elt[1][c]) + fabs(elt[2][c]);
-
- if (f > oneNorm) {
- oneNorm = f;
- }
- }
- return oneNorm;
-}
-
-//----------------------------------------------------------------------------
-float Matrix3::lInfNorm() const {
- // The infinity norm of a matrix is the max row sum in absolute value.
- float infNorm = 0;
-
- for (int r = 0; r < 3; ++r) {
-
- float f = fabs(elt[r][0]) + fabs(elt[r][1])+ fabs(elt[r][2]);
-
- if (f > infNorm) {
- infNorm = f;
- }
- }
- return infNorm;
-}
-
-//----------------------------------------------------------------------------
-float Matrix3::diffOneNorm(const Matrix3 &y) const{
- float oneNorm = 0;
-
- for (int c = 0; c < 3; ++c){
-
- float f = fabs(elt[0][c] - y[0][c]) + fabs(elt[1][c] - y[1][c])
- + fabs(elt[2][c] - y[2][c]);
-
- if (f > oneNorm) {
- oneNorm = f;
- }
- }
- return oneNorm;
-}
-
-//----------------------------------------------------------------------------
-void Matrix3::toAxisAngle (Vector3& rkAxis, float& rfRadians) const {
- //
- // Let (x,y,z) be the unit-length axis and let A be an angle of rotation.
- // The rotation matrix is R = I + sin(A)*P + (1-cos(A))*P^2 (Rodrigues' formula) where
- // I is the identity and
- //
- // +- -+
- // P = | 0 -z +y |
- // | +z 0 -x |
- // | -y +x 0 |
- // +- -+
- //
- // If A > 0, R represents a counterclockwise rotation about the axis in
- // the sense of looking from the tip of the axis vector towards the
- // origin. Some algebra will show that
- //
- // cos(A) = (trace(R)-1)/2 and R - R^t = 2*sin(A)*P
- //
- // In the event that A = pi, R-R^t = 0 which prevents us from extracting
- // the axis through P. Instead note that R = I+2*P^2 when A = pi, so
- // P^2 = (R-I)/2. The diagonal entries of P^2 are x^2-1, y^2-1, and
- // z^2-1. We can solve these for axis (x,y,z). Because the angle is pi,
- // it does not matter which sign you choose on the square roots.
-
- float fTrace = elt[0][0] + elt[1][1] + elt[2][2];
- float fCos = 0.5f * (fTrace - 1.0f);
- rfRadians = G3D::aCos(fCos); // in [0,PI]
-
- if ( rfRadians > 0.0 ) {
- if ( rfRadians < pi() ) {
- rkAxis.x = elt[2][1] - elt[1][2];
- rkAxis.y = elt[0][2] - elt[2][0];
- rkAxis.z = elt[1][0] - elt[0][1];
- rkAxis.unitize();
- } else {
- // angle is PI
- float fHalfInverse;
-
- if ( elt[0][0] >= elt[1][1] ) {
- // r00 >= r11
- if ( elt[0][0] >= elt[2][2] ) {
- // r00 is maximum diagonal term
- rkAxis.x = 0.5 * sqrt(elt[0][0] -
- elt[1][1] - elt[2][2] + 1.0);
- fHalfInverse = 0.5 / rkAxis.x;
- rkAxis.y = fHalfInverse * elt[0][1];
- rkAxis.z = fHalfInverse * elt[0][2];
- } else {
- // r22 is maximum diagonal term
- rkAxis.z = 0.5 * sqrt(elt[2][2] -
- elt[0][0] - elt[1][1] + 1.0);
- fHalfInverse = 0.5 / rkAxis.z;
- rkAxis.x = fHalfInverse * elt[0][2];
- rkAxis.y = fHalfInverse * elt[1][2];
- }
- } else {
- // r11 > r00
- if ( elt[1][1] >= elt[2][2] ) {
- // r11 is maximum diagonal term
- rkAxis.y = 0.5 * sqrt(elt[1][1] -
- elt[0][0] - elt[2][2] + 1.0);
- fHalfInverse = 0.5 / rkAxis.y;
- rkAxis.x = fHalfInverse * elt[0][1];
- rkAxis.z = fHalfInverse * elt[1][2];
- } else {
- // r22 is maximum diagonal term
- rkAxis.z = 0.5 * sqrt(elt[2][2] -
- elt[0][0] - elt[1][1] + 1.0);
- fHalfInverse = 0.5 / rkAxis.z;
- rkAxis.x = fHalfInverse * elt[0][2];
- rkAxis.y = fHalfInverse * elt[1][2];
- }
- }
- }
- } else {
- // The angle is 0 and the matrix is the identity. Any axis will
- // work, so just use the x-axis.
- rkAxis.x = 1.0;
- rkAxis.y = 0.0;
- rkAxis.z = 0.0;
- }
-}
-
-//----------------------------------------------------------------------------
-Matrix3 Matrix3::fromAxisAngle (const Vector3& _axis, float fRadians) {
- Vector3 axis = _axis.direction();
-
- Matrix3 m;
- float fCos = cos(fRadians);
- float fSin = sin(fRadians);
- float fOneMinusCos = 1.0 - fCos;
- float fX2 = square(axis.x);
- float fY2 = square(axis.y);
- float fZ2 = square(axis.z);
- float fXYM = axis.x * axis.y * fOneMinusCos;
- float fXZM = axis.x * axis.z * fOneMinusCos;
- float fYZM = axis.y * axis.z * fOneMinusCos;
- float fXSin = axis.x * fSin;
- float fYSin = axis.y * fSin;
- float fZSin = axis.z * fSin;
-
- m.elt[0][0] = fX2 * fOneMinusCos + fCos;
- m.elt[0][1] = fXYM - fZSin;
- m.elt[0][2] = fXZM + fYSin;
-
- m.elt[1][0] = fXYM + fZSin;
- m.elt[1][1] = fY2 * fOneMinusCos + fCos;
- m.elt[1][2] = fYZM - fXSin;
-
- m.elt[2][0] = fXZM - fYSin;
- m.elt[2][1] = fYZM + fXSin;
- m.elt[2][2] = fZ2 * fOneMinusCos + fCos;
-
- return m;
-}
-
-//----------------------------------------------------------------------------
-bool Matrix3::toEulerAnglesXYZ (float& rfXAngle, float& rfYAngle,
- float& rfZAngle) const {
- // rot = cy*cz -cy*sz sy
- // cz*sx*sy+cx*sz cx*cz-sx*sy*sz -cy*sx
- // -cx*cz*sy+sx*sz cz*sx+cx*sy*sz cx*cy
-
- if ( elt[0][2] < 1.0f ) {
- if ( elt[0][2] > -1.0f ) {
- rfXAngle = G3D::aTan2( -elt[1][2], elt[2][2]);
- rfYAngle = (float) G3D::aSin(elt[0][2]);
- rfZAngle = G3D::aTan2( -elt[0][1], elt[0][0]);
- return true;
- } else {
- // WARNING. Not unique. XA - ZA = -atan2(r10,r11)
- rfXAngle = -G3D::aTan2(elt[1][0], elt[1][1]);
- rfYAngle = -(float)halfPi();
- rfZAngle = 0.0f;
- return false;
- }
- } else {
- // WARNING. Not unique. XAngle + ZAngle = atan2(r10,r11)
- rfXAngle = G3D::aTan2(elt[1][0], elt[1][1]);
- rfYAngle = (float)halfPi();
- rfZAngle = 0.0f;
- return false;
- }
-}
-
-//----------------------------------------------------------------------------
-bool Matrix3::toEulerAnglesXZY (float& rfXAngle, float& rfZAngle,
- float& rfYAngle) const {
- // rot = cy*cz -sz cz*sy
- // sx*sy+cx*cy*sz cx*cz -cy*sx+cx*sy*sz
- // -cx*sy+cy*sx*sz cz*sx cx*cy+sx*sy*sz
-
- if ( elt[0][1] < 1.0f ) {
- if ( elt[0][1] > -1.0f ) {
- rfXAngle = G3D::aTan2(elt[2][1], elt[1][1]);
- rfZAngle = (float) asin( -elt[0][1]);
- rfYAngle = G3D::aTan2(elt[0][2], elt[0][0]);
- return true;
- } else {
- // WARNING. Not unique. XA - YA = atan2(r20,r22)
- rfXAngle = G3D::aTan2(elt[2][0], elt[2][2]);
- rfZAngle = (float)halfPi();
- rfYAngle = 0.0;
- return false;
- }
- } else {
- // WARNING. Not unique. XA + YA = atan2(-r20,r22)
- rfXAngle = G3D::aTan2( -elt[2][0], elt[2][2]);
- rfZAngle = -(float)halfPi();
- rfYAngle = 0.0f;
- return false;
- }
-}
-
-//----------------------------------------------------------------------------
-bool Matrix3::toEulerAnglesYXZ (float& rfYAngle, float& rfXAngle,
- float& rfZAngle) const {
- // rot = cy*cz+sx*sy*sz cz*sx*sy-cy*sz cx*sy
- // cx*sz cx*cz -sx
- // -cz*sy+cy*sx*sz cy*cz*sx+sy*sz cx*cy
-
- if ( elt[1][2] < 1.0 ) {
- if ( elt[1][2] > -1.0 ) {
- rfYAngle = G3D::aTan2(elt[0][2], elt[2][2]);
- rfXAngle = (float) asin( -elt[1][2]);
- rfZAngle = G3D::aTan2(elt[1][0], elt[1][1]);
- return true;
- } else {
- // WARNING. Not unique. YA - ZA = atan2(r01,r00)
- rfYAngle = G3D::aTan2(elt[0][1], elt[0][0]);
- rfXAngle = (float)halfPi();
- rfZAngle = 0.0;
- return false;
- }
- } else {
- // WARNING. Not unique. YA + ZA = atan2(-r01,r00)
- rfYAngle = G3D::aTan2( -elt[0][1], elt[0][0]);
- rfXAngle = -(float)halfPi();
- rfZAngle = 0.0f;
- return false;
- }
-}
-
-//----------------------------------------------------------------------------
-bool Matrix3::toEulerAnglesYZX (float& rfYAngle, float& rfZAngle,
- float& rfXAngle) const {
- // rot = cy*cz sx*sy-cx*cy*sz cx*sy+cy*sx*sz
- // sz cx*cz -cz*sx
- // -cz*sy cy*sx+cx*sy*sz cx*cy-sx*sy*sz
-
- if ( elt[1][0] < 1.0 ) {
- if ( elt[1][0] > -1.0 ) {
- rfYAngle = G3D::aTan2( -elt[2][0], elt[0][0]);
- rfZAngle = (float) asin(elt[1][0]);
- rfXAngle = G3D::aTan2( -elt[1][2], elt[1][1]);
- return true;
- } else {
- // WARNING. Not unique. YA - XA = -atan2(r21,r22);
- rfYAngle = -G3D::aTan2(elt[2][1], elt[2][2]);
- rfZAngle = -(float)halfPi();
- rfXAngle = 0.0;
- return false;
- }
- } else {
- // WARNING. Not unique. YA + XA = atan2(r21,r22)
- rfYAngle = G3D::aTan2(elt[2][1], elt[2][2]);
- rfZAngle = (float)halfPi();
- rfXAngle = 0.0f;
- return false;
- }
-}
-
-//----------------------------------------------------------------------------
-bool Matrix3::toEulerAnglesZXY (float& rfZAngle, float& rfXAngle,
- float& rfYAngle) const {
- // rot = cy*cz-sx*sy*sz -cx*sz cz*sy+cy*sx*sz
- // cz*sx*sy+cy*sz cx*cz -cy*cz*sx+sy*sz
- // -cx*sy sx cx*cy
-
- if ( elt[2][1] < 1.0 ) {
- if ( elt[2][1] > -1.0 ) {
- rfZAngle = G3D::aTan2( -elt[0][1], elt[1][1]);
- rfXAngle = (float) asin(elt[2][1]);
- rfYAngle = G3D::aTan2( -elt[2][0], elt[2][2]);
- return true;
- } else {
- // WARNING. Not unique. ZA - YA = -atan(r02,r00)
- rfZAngle = -G3D::aTan2(elt[0][2], elt[0][0]);
- rfXAngle = -(float)halfPi();
- rfYAngle = 0.0f;
- return false;
- }
- } else {
- // WARNING. Not unique. ZA + YA = atan2(r02,r00)
- rfZAngle = G3D::aTan2(elt[0][2], elt[0][0]);
- rfXAngle = (float)halfPi();
- rfYAngle = 0.0f;
- return false;
- }
-}
-
-//----------------------------------------------------------------------------
-bool Matrix3::toEulerAnglesZYX (float& rfZAngle, float& rfYAngle,
- float& rfXAngle) const {
- // rot = cy*cz cz*sx*sy-cx*sz cx*cz*sy+sx*sz
- // cy*sz cx*cz+sx*sy*sz -cz*sx+cx*sy*sz
- // -sy cy*sx cx*cy
-
- if ( elt[2][0] < 1.0 ) {
- if ( elt[2][0] > -1.0 ) {
- rfZAngle = atan2f(elt[1][0], elt[0][0]);
- rfYAngle = asinf(-(double)elt[2][1]);
- rfXAngle = atan2f(elt[2][1], elt[2][2]);
- return true;
- } else {
- // WARNING. Not unique. ZA - XA = -atan2(r01,r02)
- rfZAngle = -G3D::aTan2(elt[0][1], elt[0][2]);
- rfYAngle = (float)halfPi();
- rfXAngle = 0.0f;
- return false;
- }
- } else {
- // WARNING. Not unique. ZA + XA = atan2(-r01,-r02)
- rfZAngle = G3D::aTan2( -elt[0][1], -elt[0][2]);
- rfYAngle = -(float)halfPi();
- rfXAngle = 0.0f;
- return false;
- }
-}
-
-//----------------------------------------------------------------------------
-Matrix3 Matrix3::fromEulerAnglesXYZ (float fYAngle, float fPAngle,
- float fRAngle) {
- float fCos, fSin;
-
- fCos = cosf(fYAngle);
- fSin = sinf(fYAngle);
- Matrix3 kXMat(1.0f, 0.0f, 0.0f, 0.0f, fCos, -fSin, 0.0, fSin, fCos);
-
- fCos = cosf(fPAngle);
- fSin = sinf(fPAngle);
- Matrix3 kYMat(fCos, 0.0f, fSin, 0.0f, 1.0f, 0.0f, -fSin, 0.0f, fCos);
-
- fCos = cosf(fRAngle);
- fSin = sinf(fRAngle);
- Matrix3 kZMat(fCos, -fSin, 0.0f, fSin, fCos, 0.0f, 0.0f, 0.0f, 1.0f);
-
- return kXMat * (kYMat * kZMat);
-}
-
-//----------------------------------------------------------------------------
-Matrix3 Matrix3::fromEulerAnglesXZY (float fYAngle, float fPAngle,
- float fRAngle) {
-
- float fCos, fSin;
-
- fCos = cosf(fYAngle);
- fSin = sinf(fYAngle);
- Matrix3 kXMat(1.0, 0.0, 0.0, 0.0, fCos, -fSin, 0.0, fSin, fCos);
-
- fCos = cosf(fPAngle);
- fSin = sinf(fPAngle);
- Matrix3 kZMat(fCos, -fSin, 0.0, fSin, fCos, 0.0, 0.0, 0.0, 1.0);
-
- fCos = cosf(fRAngle);
- fSin = sinf(fRAngle);
- Matrix3 kYMat(fCos, 0.0, fSin, 0.0, 1.0, 0.0, -fSin, 0.0, fCos);
-
- return kXMat * (kZMat * kYMat);
-}
-
-//----------------------------------------------------------------------------
-Matrix3 Matrix3::fromEulerAnglesYXZ(
- float fYAngle,
- float fPAngle,
- float fRAngle) {
-
- float fCos, fSin;
-
- fCos = cos(fYAngle);
- fSin = sin(fYAngle);
- Matrix3 kYMat(fCos, 0.0f, fSin, 0.0f, 1.0f, 0.0f, -fSin, 0.0f, fCos);
-
- fCos = cos(fPAngle);
- fSin = sin(fPAngle);
- Matrix3 kXMat(1.0f, 0.0f, 0.0f, 0.0f, fCos, -fSin, 0.0f, fSin, fCos);
-
- fCos = cos(fRAngle);
- fSin = sin(fRAngle);
- Matrix3 kZMat(fCos, -fSin, 0.0f, fSin, fCos, 0.0f, 0.0f, 0.0f, 1.0f);
-
- return kYMat * (kXMat * kZMat);
-}
-
-//----------------------------------------------------------------------------
-Matrix3 Matrix3::fromEulerAnglesYZX(
- float fYAngle,
- float fPAngle,
- float fRAngle) {
-
- float fCos, fSin;
-
- fCos = cos(fYAngle);
- fSin = sin(fYAngle);
- Matrix3 kYMat(fCos, 0.0f, fSin, 0.0f, 1.0f, 0.0f, -fSin, 0.0f, fCos);
-
- fCos = cos(fPAngle);
- fSin = sin(fPAngle);
- Matrix3 kZMat(fCos, -fSin, 0.0f, fSin, fCos, 0.0f, 0.0f, 0.0f, 1.0f);
-
- fCos = cos(fRAngle);
- fSin = sin(fRAngle);
- Matrix3 kXMat(1.0f, 0.0f, 0.0f, 0.0f, fCos, -fSin, 0.0f, fSin, fCos);
-
- return kYMat * (kZMat * kXMat);
-}
-
-//----------------------------------------------------------------------------
-Matrix3 Matrix3::fromEulerAnglesZXY (float fYAngle, float fPAngle,
- float fRAngle) {
- float fCos, fSin;
-
- fCos = cos(fYAngle);
- fSin = sin(fYAngle);
- Matrix3 kZMat(fCos, -fSin, 0.0, fSin, fCos, 0.0, 0.0, 0.0, 1.0);
-
- fCos = cos(fPAngle);
- fSin = sin(fPAngle);
- Matrix3 kXMat(1.0, 0.0, 0.0, 0.0, fCos, -fSin, 0.0, fSin, fCos);
-
- fCos = cos(fRAngle);
- fSin = sin(fRAngle);
- Matrix3 kYMat(fCos, 0.0, fSin, 0.0, 1.0, 0.0, -fSin, 0.0, fCos);
-
- return kZMat * (kXMat * kYMat);
-}
-
-//----------------------------------------------------------------------------
-Matrix3 Matrix3::fromEulerAnglesZYX (float fYAngle, float fPAngle,
- float fRAngle) {
- float fCos, fSin;
-
- fCos = cos(fYAngle);
- fSin = sin(fYAngle);
- Matrix3 kZMat(fCos, -fSin, 0.0, fSin, fCos, 0.0, 0.0, 0.0, 1.0);
-
- fCos = cos(fPAngle);
- fSin = sin(fPAngle);
- Matrix3 kYMat(fCos, 0.0, fSin, 0.0, 1.0, 0.0, -fSin, 0.0, fCos);
-
- fCos = cos(fRAngle);
- fSin = sin(fRAngle);
- Matrix3 kXMat(1.0, 0.0, 0.0, 0.0, fCos, -fSin, 0.0, fSin, fCos);
-
- return kZMat * (kYMat * kXMat);
-}
-
-//----------------------------------------------------------------------------
-void Matrix3::tridiagonal (float afDiag[3], float afSubDiag[3]) {
- // Householder reduction T = Q^t M Q
- // Input:
- // mat, symmetric 3x3 matrix M
- // Output:
- // mat, orthogonal matrix Q
- // diag, diagonal entries of T
- // subd, subdiagonal entries of T (T is symmetric)
-
- float fA = elt[0][0];
- float fB = elt[0][1];
- float fC = elt[0][2];
- float fD = elt[1][1];
- float fE = elt[1][2];
- float fF = elt[2][2];
-
- afDiag[0] = fA;
- afSubDiag[2] = 0.0;
-
- if ( G3D::abs(fC) >= EPSILON ) {
- float fLength = sqrt(fB * fB + fC * fC);
- float fInvLength = 1.0 / fLength;
- fB *= fInvLength;
- fC *= fInvLength;
- float fQ = 2.0 * fB * fE + fC * (fF - fD);
- afDiag[1] = fD + fC * fQ;
- afDiag[2] = fF - fC * fQ;
- afSubDiag[0] = fLength;
- afSubDiag[1] = fE - fB * fQ;
- elt[0][0] = 1.0;
- elt[0][1] = 0.0;
- elt[0][2] = 0.0;
- elt[1][0] = 0.0;
- elt[1][1] = fB;
- elt[1][2] = fC;
- elt[2][0] = 0.0;
- elt[2][1] = fC;
- elt[2][2] = -fB;
- } else {
- afDiag[1] = fD;
- afDiag[2] = fF;
- afSubDiag[0] = fB;
- afSubDiag[1] = fE;
- elt[0][0] = 1.0;
- elt[0][1] = 0.0;
- elt[0][2] = 0.0;
- elt[1][0] = 0.0;
- elt[1][1] = 1.0;
- elt[1][2] = 0.0;
- elt[2][0] = 0.0;
- elt[2][1] = 0.0;
- elt[2][2] = 1.0;
- }
-}
-
-//----------------------------------------------------------------------------
-bool Matrix3::qLAlgorithm (float afDiag[3], float afSubDiag[3]) {
- // QL iteration with implicit shifting to reduce matrix from tridiagonal
- // to diagonal
-
- for (int i0 = 0; i0 < 3; i0++) {
- const int iMaxIter = 32;
- int iIter;
-
- for (iIter = 0; iIter < iMaxIter; iIter++) {
- int i1;
-
- for (i1 = i0; i1 <= 1; i1++) {
- float fSum = G3D::abs(afDiag[i1]) +
- G3D::abs(afDiag[i1 + 1]);
-
- if ( G3D::abs(afSubDiag[i1]) + fSum == fSum )
- break;
- }
-
- if ( i1 == i0 )
- break;
-
- float fTmp0 = (afDiag[i0 + 1] - afDiag[i0]) / (2.0 * afSubDiag[i0]);
-
- float fTmp1 = sqrt(fTmp0 * fTmp0 + 1.0);
-
- if ( fTmp0 < 0.0 )
- fTmp0 = afDiag[i1] - afDiag[i0] + afSubDiag[i0] / (fTmp0 - fTmp1);
- else
- fTmp0 = afDiag[i1] - afDiag[i0] + afSubDiag[i0] / (fTmp0 + fTmp1);
-
- float fSin = 1.0;
-
- float fCos = 1.0;
-
- float fTmp2 = 0.0;
-
- for (int i2 = i1 - 1; i2 >= i0; i2--) {
- float fTmp3 = fSin * afSubDiag[i2];
- float fTmp4 = fCos * afSubDiag[i2];
-
- if (G3D::abs(fTmp3) >= G3D::abs(fTmp0)) {
- fCos = fTmp0 / fTmp3;
- fTmp1 = sqrt(fCos * fCos + 1.0);
- afSubDiag[i2 + 1] = fTmp3 * fTmp1;
- fSin = 1.0 / fTmp1;
- fCos *= fSin;
- } else {
- fSin = fTmp3 / fTmp0;
- fTmp1 = sqrt(fSin * fSin + 1.0);
- afSubDiag[i2 + 1] = fTmp0 * fTmp1;
- fCos = 1.0 / fTmp1;
- fSin *= fCos;
- }
-
- fTmp0 = afDiag[i2 + 1] - fTmp2;
- fTmp1 = (afDiag[i2] - fTmp0) * fSin + 2.0 * fTmp4 * fCos;
- fTmp2 = fSin * fTmp1;
- afDiag[i2 + 1] = fTmp0 + fTmp2;
- fTmp0 = fCos * fTmp1 - fTmp4;
-
- for (int iRow = 0; iRow < 3; iRow++) {
- fTmp3 = elt[iRow][i2 + 1];
- elt[iRow][i2 + 1] = fSin * elt[iRow][i2] +
- fCos * fTmp3;
- elt[iRow][i2] = fCos * elt[iRow][i2] -
- fSin * fTmp3;
- }
- }
-
- afDiag[i0] -= fTmp2;
- afSubDiag[i0] = fTmp0;
- afSubDiag[i1] = 0.0;
- }
-
- if ( iIter == iMaxIter ) {
- // should not get here under normal circumstances
- return false;
- }
- }
-
- return true;
-}
-
-//----------------------------------------------------------------------------
-void Matrix3::eigenSolveSymmetric (float afEigenvalue[3],
- Vector3 akEigenvector[3]) const {
- Matrix3 kMatrix = *this;
- float afSubDiag[3];
- kMatrix.tridiagonal(afEigenvalue, afSubDiag);
- kMatrix.qLAlgorithm(afEigenvalue, afSubDiag);
-
- for (int i = 0; i < 3; i++) {
- akEigenvector[i][0] = kMatrix[0][i];
- akEigenvector[i][1] = kMatrix[1][i];
- akEigenvector[i][2] = kMatrix[2][i];
- }
-
- // make eigenvectors form a right--handed system
- Vector3 kCross = akEigenvector[1].cross(akEigenvector[2]);
-
- float fDet = akEigenvector[0].dot(kCross);
-
- if ( fDet < 0.0 ) {
- akEigenvector[2][0] = - akEigenvector[2][0];
- akEigenvector[2][1] = - akEigenvector[2][1];
- akEigenvector[2][2] = - akEigenvector[2][2];
- }
-}
-
-//----------------------------------------------------------------------------
-void Matrix3::tensorProduct (const Vector3& rkU, const Vector3& rkV,
- Matrix3& rkProduct) {
- for (int iRow = 0; iRow < 3; iRow++) {
- for (int iCol = 0; iCol < 3; iCol++) {
- rkProduct[iRow][iCol] = rkU[iRow] * rkV[iCol];
- }
- }
-}
-
-//----------------------------------------------------------------------------
-
-// Runs in 52 cycles on AMD, 76 cycles on Intel Centrino
-//
-// The loop unrolling is necessary for performance.
-// I was unable to improve performance further by flattening the matrices
-// into float*'s instead of 2D arrays.
-//
-// -morgan
-void Matrix3::_mul(const Matrix3& A, const Matrix3& B, Matrix3& out) {
- const float* ARowPtr = A.elt[0];
- float* outRowPtr = out.elt[0];
- outRowPtr[0] =
- ARowPtr[0] * B.elt[0][0] +
- ARowPtr[1] * B.elt[1][0] +
- ARowPtr[2] * B.elt[2][0];
- outRowPtr[1] =
- ARowPtr[0] * B.elt[0][1] +
- ARowPtr[1] * B.elt[1][1] +
- ARowPtr[2] * B.elt[2][1];
- outRowPtr[2] =
- ARowPtr[0] * B.elt[0][2] +
- ARowPtr[1] * B.elt[1][2] +
- ARowPtr[2] * B.elt[2][2];
-
- ARowPtr = A.elt[1];
- outRowPtr = out.elt[1];
-
- outRowPtr[0] =
- ARowPtr[0] * B.elt[0][0] +
- ARowPtr[1] * B.elt[1][0] +
- ARowPtr[2] * B.elt[2][0];
- outRowPtr[1] =
- ARowPtr[0] * B.elt[0][1] +
- ARowPtr[1] * B.elt[1][1] +
- ARowPtr[2] * B.elt[2][1];
- outRowPtr[2] =
- ARowPtr[0] * B.elt[0][2] +
- ARowPtr[1] * B.elt[1][2] +
- ARowPtr[2] * B.elt[2][2];
-
- ARowPtr = A.elt[2];
- outRowPtr = out.elt[2];
-
- outRowPtr[0] =
- ARowPtr[0] * B.elt[0][0] +
- ARowPtr[1] * B.elt[1][0] +
- ARowPtr[2] * B.elt[2][0];
- outRowPtr[1] =
- ARowPtr[0] * B.elt[0][1] +
- ARowPtr[1] * B.elt[1][1] +
- ARowPtr[2] * B.elt[2][1];
- outRowPtr[2] =
- ARowPtr[0] * B.elt[0][2] +
- ARowPtr[1] * B.elt[1][2] +
- ARowPtr[2] * B.elt[2][2];
-}
-
-//----------------------------------------------------------------------------
-void Matrix3::_transpose(const Matrix3& A, Matrix3& out) {
- out[0][0] = A.elt[0][0];
- out[0][1] = A.elt[1][0];
- out[0][2] = A.elt[2][0];
- out[1][0] = A.elt[0][1];
- out[1][1] = A.elt[1][1];
- out[1][2] = A.elt[2][1];
- out[2][0] = A.elt[0][2];
- out[2][1] = A.elt[1][2];
- out[2][2] = A.elt[2][2];
-}
-
-//-----------------------------------------------------------------------------
-std::string Matrix3::toString() const {
- return G3D::format("[%g, %g, %g; %g, %g, %g; %g, %g, %g]",
- elt[0][0], elt[0][1], elt[0][2],
- elt[1][0], elt[1][1], elt[1][2],
- elt[2][0], elt[2][1], elt[2][2]);
-}
-
-
-
-} // namespace
-
diff --git a/externals/g3dlite/Matrix4.cpp b/externals/g3dlite/Matrix4.cpp
deleted file mode 100644
index cd38a1a3602..00000000000
--- a/externals/g3dlite/Matrix4.cpp
+++ /dev/null
@@ -1,523 +0,0 @@
-/**
- @file Matrix4.cpp
-
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2003-10-02
- @edited 2010-01-29
- */
-
-#include "G3D/platform.h"
-#include "G3D/Matrix4.h"
-#include "G3D/Matrix3.h"
-#include "G3D/Vector4.h"
-#include "G3D/Vector3.h"
-#include "G3D/BinaryInput.h"
-#include "G3D/BinaryOutput.h"
-#include "G3D/CoordinateFrame.h"
-#include "G3D/Rect2D.h"
-#include "G3D/Any.h"
-#include "G3D/stringutils.h"
-
-namespace G3D {
-
-
-Matrix4::Matrix4(const Any& any) {
- any.verifyName("Matrix4");
- any.verifyType(Any::ARRAY);
-
- const std::string& name = toLower(any.name());
- if (name == "matrix4") {
- any.verifySize(16);
-
- for (int r = 0; r < 4; ++r) {
- for (int c = 0; c < 4; ++c) {
- elt[r][c] = any[r * 4 + c];
- }
- }
- } else if (name == "matrix4::scale") {
- if (any.size() == 1) {
- *this = scale(any[0].number());
- } else if (any.size() == 3) {
- *this = scale(any[0], any[1], any[2]);
- } else {
- any.verify(false, "Matrix4::scale() takes either 1 or 3 arguments");
- }
- } else {
- any.verify(false, "Expected Matrix4 constructor");
- }
-}
-
-
-Matrix4::operator Any() const {
- Any any(Any::ARRAY, "Matrix4");
- any.resize(16);
- for (int r = 0; r < 4; ++r) {
- for (int c = 0; c < 4; ++c) {
- any[r * 4 + c] = elt[r][c];
- }
- }
-
- return any;
-}
-
-const Matrix4& Matrix4::identity() {
- static Matrix4 m(
- 1, 0, 0, 0,
- 0, 1, 0, 0,
- 0, 0, 1, 0,
- 0, 0, 0, 1);
- return m;
-}
-
-
-const Matrix4& Matrix4::zero() {
- static Matrix4 m(
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0);
- return m;
-}
-
-
-Matrix4::Matrix4(const class CoordinateFrame& cframe) {
- for (int r = 0; r < 3; ++r) {
- for (int c = 0; c < 3; ++c) {
- elt[r][c] = cframe.rotation[r][c];
- }
- elt[r][3] = cframe.translation[r];
- }
- elt[3][0] = 0.0f;
- elt[3][1] = 0.0f;
- elt[3][2] = 0.0f;
- elt[3][3] = 1.0f;
-}
-
-Matrix4::Matrix4(const Matrix3& upper3x3, const Vector3& lastCol) {
- for (int r = 0; r < 3; ++r) {
- for (int c = 0; c < 3; ++c) {
- elt[r][c] = upper3x3[r][c];
- }
- elt[r][3] = lastCol[r];
- }
- elt[3][0] = 0.0f;
- elt[3][1] = 0.0f;
- elt[3][2] = 0.0f;
- elt[3][3] = 1.0f;
-}
-
-
-Matrix3 Matrix4::upper3x3() const {
- return Matrix3(elt[0][0], elt[0][1], elt[0][2],
- elt[1][0], elt[1][1], elt[1][2],
- elt[2][0], elt[2][1], elt[2][2]);
-}
-
-
-Matrix4 Matrix4::orthogonalProjection(
- const class Rect2D& rect,
- float nearval,
- float farval,
- float upDirection) {
- return Matrix4::orthogonalProjection(rect.x0(), rect.x1(), rect.y1(), rect.y0(), nearval, farval, upDirection);
-}
-
-
-Matrix4 Matrix4::orthogonalProjection(
- float left,
- float right,
- float bottom,
- float top,
- float nearval,
- float farval,
- float upDirection) {
-
- // Adapted from Mesa. Note that Microsoft (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/opengl/glfunc03_8qnj.asp)
- // and Linux (http://www.xfree86.org/current/glOrtho.3.html) have different matrices shown in their documentation.
-
- float x, y, z;
- float tx, ty, tz;
-
- x = 2.0f / (right-left);
- y = 2.0f / (top-bottom);
- z = -2.0f / (farval-nearval);
- tx = -(right+left) / (right-left);
- ty = -(top+bottom) / (top-bottom);
- tz = -(farval+nearval) / (farval-nearval);
-
- y *= upDirection;
- ty *= upDirection;
-
- return
- Matrix4( x , 0.0f, 0.0f, tx,
- 0.0f, y , 0.0f, ty,
- 0.0f, 0.0f, z , tz,
- 0.0f, 0.0f, 0.0f, 1.0f);
-}
-
-
-Matrix4 Matrix4::perspectiveProjection(
- float left,
- float right,
- float bottom,
- float top,
- float nearval,
- float farval,
- float upDirection) {
-
- float x, y, a, b, c, d;
-
- x = (2.0f*nearval) / (right-left);
- y = (2.0f*nearval) / (top-bottom);
- a = (right+left) / (right-left);
- b = (top+bottom) / (top-bottom);
-
- if (farval >= finf()) {
- // Infinite view frustum
- c = -1.0f;
- d = -2.0f * nearval;
- } else {
- c = -(farval+nearval) / (farval-nearval);
- d = -(2.0f*farval*nearval) / (farval-nearval);
- }
-
- debugAssertM(abs(upDirection) == 1.0f, "upDirection must be -1 or +1");
- y *= upDirection;
- b *= upDirection;
-
- return Matrix4(
- x, 0, a, 0,
- 0, y, b, 0,
- 0, 0, c, d,
- 0, 0, -1, 0);
-}
-
-
-void Matrix4::getPerspectiveProjectionParameters(
- float& left,
- float& right,
- float& bottom,
- float& top,
- float& nearval,
- float& farval,
- float upDirection) const {
-
- debugAssertM(abs(upDirection) == 1.0f, "upDirection must be -1 or +1");
-
- float x = elt[0][0];
- float y = elt[1][1] * upDirection;
- float a = elt[0][2];
- float b = elt[1][2] * upDirection;
- float c = elt[2][2];
- float d = elt[2][3];
-
- // Verify that this really is a projection matrix
- debugAssertM(elt[3][2] == -1, "Not a projection matrix");
- debugAssertM(elt[0][1] == 0, "Not a projection matrix");
- debugAssertM(elt[0][3] == 0, "Not a projection matrix");
- debugAssertM(elt[1][3] == 0, "Not a projection matrix");
- debugAssertM(elt[3][3] == 0, "Not a projection matrix");
- debugAssertM(elt[1][0] == 0, "Not a projection matrix");
- debugAssertM(elt[2][0] == 0, "Not a projection matrix");
- debugAssertM(elt[2][1] == 0, "Not a projection matrix");
- debugAssertM(elt[3][0] == 0, "Not a projection matrix");
- debugAssertM(elt[3][1] == 0, "Not a projection matrix");
-
- if (c == -1) {
- farval = finf();
- nearval = -d / 2.0f;
- } else {
- nearval = d * ((c - 1.0f) / (c + 1.0f) - 1.0f) / (-2.0f * (c - 1.0f) / (c + 1.0f));
- farval = nearval * ((c - 1.0f) / (c + 1.0f));
- }
-
-
- left = (a - 1.0f) * nearval / x;
- right = 2.0f * nearval / x + left;
-
- bottom = (b - 1.0f) * nearval / y;
- top = 2.0f * nearval / y + bottom;
-}
-
-
-Matrix4::Matrix4(
- float r1c1, float r1c2, float r1c3, float r1c4,
- float r2c1, float r2c2, float r2c3, float r2c4,
- float r3c1, float r3c2, float r3c3, float r3c4,
- float r4c1, float r4c2, float r4c3, float r4c4) {
- elt[0][0] = r1c1; elt[0][1] = r1c2; elt[0][2] = r1c3; elt[0][3] = r1c4;
- elt[1][0] = r2c1; elt[1][1] = r2c2; elt[1][2] = r2c3; elt[1][3] = r2c4;
- elt[2][0] = r3c1; elt[2][1] = r3c2; elt[2][2] = r3c3; elt[2][3] = r3c4;
- elt[3][0] = r4c1; elt[3][1] = r4c2; elt[3][2] = r4c3; elt[3][3] = r4c4;
-}
-
-/**
- init should be <B>row major</B>.
- */
-Matrix4::Matrix4(const float* init) {
- for (int r = 0; r < 4; ++r) {
- for (int c = 0; c < 4; ++c) {
- elt[r][c] = init[r * 4 + c];
- }
- }
-}
-
-
-Matrix4::Matrix4(const double* init) {
- for (int r = 0; r < 4; ++r) {
- for (int c = 0; c < 4; ++c) {
- elt[r][c] = (float)init[r * 4 + c];
- }
- }
-}
-
-
-Matrix4::Matrix4() {
- for (int r = 0; r < 4; ++r) {
- for (int c = 0; c < 4; ++c) {
- elt[r][c] = 0;
- }
- }
-}
-
-
-void Matrix4::setRow(int r, const Vector4& v) {
- for (int c = 0; c < 4; ++c) {
- elt[r][c] = v[c];
- }
-}
-
-
-void Matrix4::setColumn(int c, const Vector4& v) {
- for (int r = 0; r < 4; ++r) {
- elt[r][c] = v[r];
- }
-}
-
-
-const Vector4& Matrix4::row(int r) const {
- return reinterpret_cast<const Vector4*>(elt[r])[0];
-}
-
-
-Vector4 Matrix4::column(int c) const {
- Vector4 v;
- for (int r = 0; r < 4; ++r) {
- v[r] = elt[r][c];
- }
- return v;
-}
-
-
-Matrix4 Matrix4::operator*(const Matrix4& other) const {
- Matrix4 result;
- for (int r = 0; r < 4; ++r) {
- for (int c = 0; c < 4; ++c) {
- for (int i = 0; i < 4; ++i) {
- result.elt[r][c] += elt[r][i] * other.elt[i][c];
- }
- }
- }
-
- return result;
-}
-
-
-Matrix4 Matrix4::operator*(const float s) const {
- Matrix4 result;
- for (int r = 0; r < 4; ++r) {
- for (int c = 0; c < 4; ++c) {
- result.elt[r][c] = elt[r][c] * s;
- }
- }
-
- return result;
-}
-
-
-Vector3 Matrix4::homoMul(const class Vector3& v, float w) const {
- Vector4 r = (*this) * Vector4(v, w);
- return r.xyz() * (1.0f / r.w);
-}
-
-
-Vector4 Matrix4::operator*(const Vector4& vector) const {
- Vector4 result(0,0,0,0);
- for (int r = 0; r < 4; ++r) {
- for (int c = 0; c < 4; ++c) {
- result[r] += elt[r][c] * vector[c];
- }
- }
-
- return result;
-}
-
-
-Matrix4 Matrix4::transpose() const {
- Matrix4 result;
- for (int r = 0; r < 4; ++r) {
- for (int c = 0; c < 4; ++c) {
- result.elt[c][r] = elt[r][c];
- }
- }
-
- return result;
-}
-
-
-bool Matrix4::operator!=(const Matrix4& other) const {
- return ! (*this == other);
-}
-
-
-bool Matrix4::operator==(const Matrix4& other) const {
-
- // If the bit patterns are identical, they must be
- // the same matrix. If not, they *might* still have
- // equal elements due to floating point weirdness.
- if (memcmp(this, &other, sizeof(Matrix4) == 0)) {
- return true;
- }
-
- for (int r = 0; r < 4; ++r) {
- for (int c = 0; c < 4; ++c) {
- if (elt[r][c] != other.elt[r][c]) {
- return false;
- }
- }
- }
-
- return true;
-}
-
-
-float Matrix4::determinant() const {
- // Determinant is the dot product of the first row and the first row
- // of cofactors (i.e. the first col of the adjoint matrix)
- return cofactor().row(0).dot(row(0));
-}
-
-
-Matrix4 Matrix4::adjoint() const {
- return cofactor().transpose();
-}
-
-
-Matrix4 Matrix4::inverse() const {
- // Inverse = adjoint / determinant
-
- Matrix4 A = adjoint();
-
- // Determinant is the dot product of the first row and the first row
- // of cofactors (i.e. the first col of the adjoint matrix)
- float det = A.column(0).dot(row(0));
-
- return A * (1.0f / det);
-}
-
-
-Matrix4 Matrix4::cofactor() const {
- Matrix4 out;
-
- // We'll use i to incrementally compute -1 ^ (r+c)
- int i = 1;
-
- for (int r = 0; r < 4; ++r) {
- for (int c = 0; c < 4; ++c) {
- // Compute the determinant of the 3x3 submatrix
- float det = subDeterminant(r, c);
- out.elt[r][c] = i * det;
- i = -i;
- }
- i = -i;
- }
-
- return out;
-}
-
-
-float Matrix4::subDeterminant(int excludeRow, int excludeCol) const {
- // Compute non-excluded row and column indices
- int row[3];
- int col[3];
-
- for (int i = 0; i < 3; ++i) {
- row[i] = i;
- col[i] = i;
-
- if (i >= excludeRow) {
- ++row[i];
- }
- if (i >= excludeCol) {
- ++col[i];
- }
- }
-
- // Compute the first row of cofactors
- float cofactor00 =
- elt[row[1]][col[1]] * elt[row[2]][col[2]] -
- elt[row[1]][col[2]] * elt[row[2]][col[1]];
-
- float cofactor10 =
- elt[row[1]][col[2]] * elt[row[2]][col[0]] -
- elt[row[1]][col[0]] * elt[row[2]][col[2]];
-
- float cofactor20 =
- elt[row[1]][col[0]] * elt[row[2]][col[1]] -
- elt[row[1]][col[1]] * elt[row[2]][col[0]];
-
- // Product of the first row and the cofactors along the first row
- return
- elt[row[0]][col[0]] * cofactor00 +
- elt[row[0]][col[1]] * cofactor10 +
- elt[row[0]][col[2]] * cofactor20;
-}
-
-
-CoordinateFrame Matrix4::approxCoordinateFrame() const {
- CoordinateFrame cframe;
-
- for (int r = 0; r < 3; ++r) {
- for (int c = 0; c < 3; ++c) {
- cframe.rotation[r][c] = elt[r][c];
- }
- cframe.translation[r] = elt[r][3];
- }
-
- // Ensure that the rotation matrix is orthonormal
- cframe.rotation.orthonormalize();
-
- return cframe;
-}
-
-
-void Matrix4::serialize(class BinaryOutput& b) const {
- for (int r = 0; r < 4; ++r) {
- for (int c = 0; c < 4; ++c) {
- b.writeFloat32(elt[r][c]);
- }
- }
-}
-
-
-void Matrix4::deserialize(class BinaryInput& b) {
- for (int r = 0; r < 4; ++r) {
- for (int c = 0; c < 4; ++c) {
- elt[r][c] = b.readFloat32();
- }
- }
-}
-
-std::string Matrix4::toString() const {
- return G3D::format("[%g, %g, %g, %g; %g, %g, %g, %g; %g, %g, %g, %g; %g, %g, %g, %g]",
- elt[0][0], elt[0][1], elt[0][2], elt[0][3],
- elt[1][0], elt[1][1], elt[1][2], elt[1][3],
- elt[2][0], elt[2][1], elt[2][2], elt[2][3],
- elt[3][0], elt[3][1], elt[3][2], elt[3][3]);
-}
-
-} // namespace
-
-
diff --git a/externals/g3dlite/MemoryManager.cpp b/externals/g3dlite/MemoryManager.cpp
deleted file mode 100644
index 240188a1f0e..00000000000
--- a/externals/g3dlite/MemoryManager.cpp
+++ /dev/null
@@ -1,91 +0,0 @@
-/**
- @file MemoryManager.cpp
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @created 2009-04-20
- @edited 2009-05-29
-
- Copyright 2000-2009, Morgan McGuire.
- All rights reserved.
- */
-
-#include "G3D/MemoryManager.h"
-#include "G3D/System.h"
-
-namespace G3D {
-
-MemoryManager::MemoryManager() {}
-
-
-void* MemoryManager::alloc(size_t s) {
- return System::malloc(s);
-}
-
-
-void MemoryManager::free(void* ptr) {
- System::free(ptr);
-}
-
-
-bool MemoryManager::isThreadsafe() const {
- return true;
-}
-
-
-MemoryManager::Ref MemoryManager::create() {
- static MemoryManager::Ref m = new MemoryManager();
- return m;
-}
-
-
-///////////////////////////////////////////////////
-
-AlignedMemoryManager::AlignedMemoryManager() {}
-
-
-void* AlignedMemoryManager::alloc(size_t s) {
- return System::alignedMalloc(s, 16);
-}
-
-
-void AlignedMemoryManager::free(void* ptr) {
- System::alignedFree(ptr);
-}
-
-
-bool AlignedMemoryManager::isThreadsafe() const {
- return true;
-}
-
-
-AlignedMemoryManager::Ref AlignedMemoryManager::create() {
- static AlignedMemoryManager::Ref m = new AlignedMemoryManager();
- return m;
-}
-
-
-///////////////////////////////////////////////////
-
-CRTMemoryManager::CRTMemoryManager() {}
-
-
-void* CRTMemoryManager::alloc(size_t s) {
- return ::malloc(s);
-}
-
-
-void CRTMemoryManager::free(void* ptr) {
- return ::free(ptr);
-}
-
-
-bool CRTMemoryManager::isThreadsafe() const {
- return true;
-}
-
-
-CRTMemoryManager::Ref CRTMemoryManager::create() {
- static CRTMemoryManager::Ref m = new CRTMemoryManager();
- return m;
-}
-}
diff --git a/externals/g3dlite/Plane.cpp b/externals/g3dlite/Plane.cpp
deleted file mode 100644
index 9b7991c0333..00000000000
--- a/externals/g3dlite/Plane.cpp
+++ /dev/null
@@ -1,149 +0,0 @@
-/**
- @file Plane.cpp
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2003-02-06
- @edited 2006-01-29
- */
-
-#include "G3D/platform.h"
-#include "G3D/Plane.h"
-#include "G3D/BinaryOutput.h"
-#include "G3D/BinaryInput.h"
-#include "G3D/stringutils.h"
-
-namespace G3D {
-
-Plane::Plane(class BinaryInput& b) {
- deserialize(b);
-}
-
-
-void Plane::serialize(class BinaryOutput& b) const {
- _normal.serialize(b);
- b.writeFloat64(_distance);
-}
-
-
-void Plane::deserialize(class BinaryInput& b) {
- _normal.deserialize(b);
- _distance = (float)b.readFloat64();
-}
-
-
-Plane::Plane(
- Vector4 point0,
- Vector4 point1,
- Vector4 point2) {
-
- debugAssertM(
- point0.w != 0 ||
- point1.w != 0 ||
- point2.w != 0,
- "At least one point must be finite.");
-
- // Rotate the points around so that the finite points come first.
-
- while ((point0.w == 0) &&
- ((point1.w == 0) || (point2.w != 0))) {
- Vector4 temp = point0;
- point0 = point1;
- point1 = point2;
- point2 = temp;
- }
-
- Vector3 dir1;
- Vector3 dir2;
-
- if (point1.w == 0) {
- // 1 finite, 2 infinite points; the plane must contain
- // the direction of the two direcitons
- dir1 = point1.xyz();
- dir2 = point2.xyz();
- } else if (point2.w != 0) {
- // 3 finite points, the plane must contain the directions
- // betwseen the points.
- dir1 = point1.xyz() - point0.xyz();
- dir2 = point2.xyz() - point0.xyz();
- } else {
- // 2 finite, 1 infinite point; the plane must contain
- // the direction between the first two points and the
- // direction of the third point.
- dir1 = point1.xyz() - point0.xyz();
- dir2 = point2.xyz();
- }
-
- _normal = dir1.cross(dir2).direction();
- _distance = _normal.dot(point0.xyz());
-}
-
-
-Plane::Plane(
- const Vector3& point0,
- const Vector3& point1,
- const Vector3& point2) {
-
- _normal = (point1 - point0).cross(point2 - point0).direction();
- _distance = _normal.dot(point0);
-}
-
-
-Plane::Plane(
- const Vector3& __normal,
- const Vector3& point) {
-
- _normal = __normal.direction();
- _distance = _normal.dot(point);
-}
-
-
-Plane Plane::fromEquation(float a, float b, float c, float d) {
- Vector3 n(a, b, c);
- float magnitude = n.magnitude();
- d /= magnitude;
- n /= magnitude;
- return Plane(n, -d);
-}
-
-
-void Plane::flip() {
- _normal = -_normal;
- _distance = -_distance;
-}
-
-
-void Plane::getEquation(Vector3& n, float& d) const {
- double _d;
- getEquation(n, _d);
- d = (float)_d;
-}
-
-void Plane::getEquation(Vector3& n, double& d) const {
- n = _normal;
- d = -_distance;
-}
-
-
-void Plane::getEquation(float& a, float& b, float& c, float& d) const {
- double _a, _b, _c, _d;
- getEquation(_a, _b, _c, _d);
- a = (float)_a;
- b = (float)_b;
- c = (float)_c;
- d = (float)_d;
-}
-
-void Plane::getEquation(double& a, double& b, double& c, double& d) const {
- a = _normal.x;
- b = _normal.y;
- c = _normal.z;
- d = -_distance;
-}
-
-
-std::string Plane::toString() const {
- return format("Plane(%g, %g, %g, %g)", _normal.x, _normal.y, _normal.z, _distance);
-}
-
-}
diff --git a/externals/g3dlite/Quat.cpp b/externals/g3dlite/Quat.cpp
deleted file mode 100644
index 225c5b51acc..00000000000
--- a/externals/g3dlite/Quat.cpp
+++ /dev/null
@@ -1,583 +0,0 @@
-/**
- @file Quat.cpp
-
- Quaternion implementation based on Watt & Watt page 363
-
- @author Morgan McGuire, graphics3d.com
-
- @created 2002-01-23
- @edited 2006-01-31
- */
-
-#include "G3D/Quat.h"
-#include "G3D/BinaryInput.h"
-#include "G3D/BinaryOutput.h"
-
-namespace G3D {
-
-Quat Quat::fromAxisAngleRotation(
- const Vector3& axis,
- float angle) {
-
- Quat q;
-
- q.w = cos(angle / 2.0f);
- q.imag() = axis.direction() * sin(angle / 2.0f);
-
- return q;
-}
-
-
-Quat::Quat(
- const Matrix3& rot) {
-
- static const int plus1mod3[] = {1, 2, 0};
-
- // Find the index of the largest diagonal component
- // These ? operations hopefully compile to conditional
- // move instructions instead of branches.
- int i = (rot[1][1] > rot[0][0]) ? 1 : 0;
- i = (rot[2][2] > rot[i][i]) ? 2 : i;
-
- // Find the indices of the other elements
- int j = plus1mod3[i];
- int k = plus1mod3[j];
-
- // Index the elements of the vector part of the quaternion as a float*
- float* v = (float*)(this);
-
- // If we attempted to pre-normalize and trusted the matrix to be
- // perfectly orthonormal, the result would be:
- //
- // double c = sqrt((rot[i][i] - (rot[j][j] + rot[k][k])) + 1.0)
- // v[i] = -c * 0.5
- // v[j] = -(rot[i][j] + rot[j][i]) * 0.5 / c
- // v[k] = -(rot[i][k] + rot[k][i]) * 0.5 / c
- // w = (rot[j][k] - rot[k][j]) * 0.5 / c
- //
- // Since we're going to pay the sqrt anyway, we perform a post normalization, which also
- // fixes any poorly normalized input. Multiply all elements by 2*c in the above, giving:
-
- // nc2 = -c^2
- double nc2 = ((rot[j][j] + rot[k][k]) - rot[i][i]) - 1.0;
- v[i] = nc2;
- w = (rot[j][k] - rot[k][j]);
- v[j] = -(rot[i][j] + rot[j][i]);
- v[k] = -(rot[i][k] + rot[k][i]);
-
- // We now have the correct result with the wrong magnitude, so normalize it:
- float s = sqrt(x*x + y*y + z*z + w*w);
- if (s > 0.00001f) {
- s = 1.0f / s;
- x *= s;
- y *= s;
- z *= s;
- w *= s;
- } else {
- // The quaternion is nearly zero. Make it 0 0 0 1
- x = 0.0f;
- y = 0.0f;
- z = 0.0f;
- w = 1.0f;
- }
-}
-
-
-void Quat::toAxisAngleRotation(
- Vector3& axis,
- double& angle) const {
-
- // Decompose the quaternion into an angle and an axis.
-
- axis = Vector3(x, y, z);
- angle = 2 * acos(w);
-
- float len = sqrt(1.0f - w * w);
-
- if (fuzzyGt(abs(len), 0.0f)) {
- axis /= len;
- }
-
- // Reduce the range of the angle.
-
- if (angle < 0) {
- angle = -angle;
- axis = -axis;
- }
-
- while (angle > twoPi()) {
- angle -= twoPi();
- }
-
- if (abs(angle) > pi()) {
- angle -= twoPi();
- }
-
- // Make the angle positive.
-
- if (angle < 0.0f) {
- angle = -angle;
- axis = -axis;
- }
-}
-
-
-Matrix3 Quat::toRotationMatrix() const {
- Matrix3 out = Matrix3::zero();
-
- toRotationMatrix(out);
-
- return out;
-}
-
-
-void Quat::toRotationMatrix(
- Matrix3& rot) const {
-
- rot = Matrix3(*this);
-}
-
-
-Quat Quat::slerp(
- const Quat& _quat1,
- float alpha,
- float threshold) const {
-
- // From: Game Physics -- David Eberly pg 538-540
- // Modified to include lerp for small angles, which
- // is a common practice.
-
- // See also:
- // http://number-none.com/product/Understanding%20Slerp,%20Then%20Not%20Using%20It/index.html
-
- const Quat& quat0 = *this;
- Quat quat1 = _quat1;
-
- // angle between quaternion rotations
- float phi;
- float cosphi = quat0.dot(quat1);
-
-
- if (cosphi < 0) {
- // Change the sign and fix the dot product; we need to
- // loop the other way to get the shortest path
- quat1 = -quat1;
- cosphi = -cosphi;
- }
-
- // Using G3D::aCos will clamp the angle to 0 and pi
- phi = static_cast<float>(G3D::aCos(cosphi));
-
- if (phi >= threshold) {
- // For large angles, slerp
- float scale0, scale1;
-
- scale0 = sin((1.0f - alpha) * phi);
- scale1 = sin(alpha * phi);
-
- return ( (quat0 * scale0) + (quat1 * scale1) ) / sin(phi);
- } else {
- // For small angles, linear interpolate
- return quat0.nlerp(quat1, alpha);
- }
-}
-
-
-Quat Quat::nlerp(
- const Quat& quat1,
- float alpha) const {
-
- Quat result = (*this) * (1.0f - alpha) + quat1 * alpha;
- return result / result.magnitude();
-}
-
-
-Quat Quat::operator*(const Quat& other) const {
-
- // Following Watt & Watt, page 360
- const Vector3& v1 = imag();
- const Vector3& v2 = other.imag();
- float s1 = w;
- float s2 = other.w;
-
- return Quat(s1*v2 + s2*v1 + v1.cross(v2), s1*s2 - v1.dot(v2));
-}
-
-
-// From "Uniform Random Rotations", Ken Shoemake, Graphics Gems III.
-Quat Quat::unitRandom() {
- float x0 = uniformRandom();
- float r1 = sqrtf(1 - x0),
- r2 = sqrtf(x0);
- float t1 = (float)G3D::twoPi() * uniformRandom();
- float t2 = (float)G3D::twoPi() * uniformRandom();
- float c1 = cosf(t1),
- s1 = sinf(t1);
- float c2 = cosf(t2),
- s2 = sinf(t2);
- return Quat(s1 * r1, c1 * r1, s2 * r2, c2 * r2);
-}
-
-
-void Quat::deserialize(class BinaryInput& b) {
- x = b.readFloat32();
- y = b.readFloat32();
- z = b.readFloat32();
- w = b.readFloat32();
-}
-
-
-void Quat::serialize(class BinaryOutput& b) const {
- b.writeFloat32(x);
- b.writeFloat32(y);
- b.writeFloat32(z);
- b.writeFloat32(w);
-}
-
-
-// 2-char swizzles
-
-Vector2 Quat::xx() const { return Vector2 (x, x); }
-Vector2 Quat::yx() const { return Vector2 (y, x); }
-Vector2 Quat::zx() const { return Vector2 (z, x); }
-Vector2 Quat::wx() const { return Vector2 (w, x); }
-Vector2 Quat::xy() const { return Vector2 (x, y); }
-Vector2 Quat::yy() const { return Vector2 (y, y); }
-Vector2 Quat::zy() const { return Vector2 (z, y); }
-Vector2 Quat::wy() const { return Vector2 (w, y); }
-Vector2 Quat::xz() const { return Vector2 (x, z); }
-Vector2 Quat::yz() const { return Vector2 (y, z); }
-Vector2 Quat::zz() const { return Vector2 (z, z); }
-Vector2 Quat::wz() const { return Vector2 (w, z); }
-Vector2 Quat::xw() const { return Vector2 (x, w); }
-Vector2 Quat::yw() const { return Vector2 (y, w); }
-Vector2 Quat::zw() const { return Vector2 (z, w); }
-Vector2 Quat::ww() const { return Vector2 (w, w); }
-
-// 3-char swizzles
-
-Vector3 Quat::xxx() const { return Vector3 (x, x, x); }
-Vector3 Quat::yxx() const { return Vector3 (y, x, x); }
-Vector3 Quat::zxx() const { return Vector3 (z, x, x); }
-Vector3 Quat::wxx() const { return Vector3 (w, x, x); }
-Vector3 Quat::xyx() const { return Vector3 (x, y, x); }
-Vector3 Quat::yyx() const { return Vector3 (y, y, x); }
-Vector3 Quat::zyx() const { return Vector3 (z, y, x); }
-Vector3 Quat::wyx() const { return Vector3 (w, y, x); }
-Vector3 Quat::xzx() const { return Vector3 (x, z, x); }
-Vector3 Quat::yzx() const { return Vector3 (y, z, x); }
-Vector3 Quat::zzx() const { return Vector3 (z, z, x); }
-Vector3 Quat::wzx() const { return Vector3 (w, z, x); }
-Vector3 Quat::xwx() const { return Vector3 (x, w, x); }
-Vector3 Quat::ywx() const { return Vector3 (y, w, x); }
-Vector3 Quat::zwx() const { return Vector3 (z, w, x); }
-Vector3 Quat::wwx() const { return Vector3 (w, w, x); }
-Vector3 Quat::xxy() const { return Vector3 (x, x, y); }
-Vector3 Quat::yxy() const { return Vector3 (y, x, y); }
-Vector3 Quat::zxy() const { return Vector3 (z, x, y); }
-Vector3 Quat::wxy() const { return Vector3 (w, x, y); }
-Vector3 Quat::xyy() const { return Vector3 (x, y, y); }
-Vector3 Quat::yyy() const { return Vector3 (y, y, y); }
-Vector3 Quat::zyy() const { return Vector3 (z, y, y); }
-Vector3 Quat::wyy() const { return Vector3 (w, y, y); }
-Vector3 Quat::xzy() const { return Vector3 (x, z, y); }
-Vector3 Quat::yzy() const { return Vector3 (y, z, y); }
-Vector3 Quat::zzy() const { return Vector3 (z, z, y); }
-Vector3 Quat::wzy() const { return Vector3 (w, z, y); }
-Vector3 Quat::xwy() const { return Vector3 (x, w, y); }
-Vector3 Quat::ywy() const { return Vector3 (y, w, y); }
-Vector3 Quat::zwy() const { return Vector3 (z, w, y); }
-Vector3 Quat::wwy() const { return Vector3 (w, w, y); }
-Vector3 Quat::xxz() const { return Vector3 (x, x, z); }
-Vector3 Quat::yxz() const { return Vector3 (y, x, z); }
-Vector3 Quat::zxz() const { return Vector3 (z, x, z); }
-Vector3 Quat::wxz() const { return Vector3 (w, x, z); }
-Vector3 Quat::xyz() const { return Vector3 (x, y, z); }
-Vector3 Quat::yyz() const { return Vector3 (y, y, z); }
-Vector3 Quat::zyz() const { return Vector3 (z, y, z); }
-Vector3 Quat::wyz() const { return Vector3 (w, y, z); }
-Vector3 Quat::xzz() const { return Vector3 (x, z, z); }
-Vector3 Quat::yzz() const { return Vector3 (y, z, z); }
-Vector3 Quat::zzz() const { return Vector3 (z, z, z); }
-Vector3 Quat::wzz() const { return Vector3 (w, z, z); }
-Vector3 Quat::xwz() const { return Vector3 (x, w, z); }
-Vector3 Quat::ywz() const { return Vector3 (y, w, z); }
-Vector3 Quat::zwz() const { return Vector3 (z, w, z); }
-Vector3 Quat::wwz() const { return Vector3 (w, w, z); }
-Vector3 Quat::xxw() const { return Vector3 (x, x, w); }
-Vector3 Quat::yxw() const { return Vector3 (y, x, w); }
-Vector3 Quat::zxw() const { return Vector3 (z, x, w); }
-Vector3 Quat::wxw() const { return Vector3 (w, x, w); }
-Vector3 Quat::xyw() const { return Vector3 (x, y, w); }
-Vector3 Quat::yyw() const { return Vector3 (y, y, w); }
-Vector3 Quat::zyw() const { return Vector3 (z, y, w); }
-Vector3 Quat::wyw() const { return Vector3 (w, y, w); }
-Vector3 Quat::xzw() const { return Vector3 (x, z, w); }
-Vector3 Quat::yzw() const { return Vector3 (y, z, w); }
-Vector3 Quat::zzw() const { return Vector3 (z, z, w); }
-Vector3 Quat::wzw() const { return Vector3 (w, z, w); }
-Vector3 Quat::xww() const { return Vector3 (x, w, w); }
-Vector3 Quat::yww() const { return Vector3 (y, w, w); }
-Vector3 Quat::zww() const { return Vector3 (z, w, w); }
-Vector3 Quat::www() const { return Vector3 (w, w, w); }
-
-// 4-char swizzles
-
-Vector4 Quat::xxxx() const { return Vector4 (x, x, x, x); }
-Vector4 Quat::yxxx() const { return Vector4 (y, x, x, x); }
-Vector4 Quat::zxxx() const { return Vector4 (z, x, x, x); }
-Vector4 Quat::wxxx() const { return Vector4 (w, x, x, x); }
-Vector4 Quat::xyxx() const { return Vector4 (x, y, x, x); }
-Vector4 Quat::yyxx() const { return Vector4 (y, y, x, x); }
-Vector4 Quat::zyxx() const { return Vector4 (z, y, x, x); }
-Vector4 Quat::wyxx() const { return Vector4 (w, y, x, x); }
-Vector4 Quat::xzxx() const { return Vector4 (x, z, x, x); }
-Vector4 Quat::yzxx() const { return Vector4 (y, z, x, x); }
-Vector4 Quat::zzxx() const { return Vector4 (z, z, x, x); }
-Vector4 Quat::wzxx() const { return Vector4 (w, z, x, x); }
-Vector4 Quat::xwxx() const { return Vector4 (x, w, x, x); }
-Vector4 Quat::ywxx() const { return Vector4 (y, w, x, x); }
-Vector4 Quat::zwxx() const { return Vector4 (z, w, x, x); }
-Vector4 Quat::wwxx() const { return Vector4 (w, w, x, x); }
-Vector4 Quat::xxyx() const { return Vector4 (x, x, y, x); }
-Vector4 Quat::yxyx() const { return Vector4 (y, x, y, x); }
-Vector4 Quat::zxyx() const { return Vector4 (z, x, y, x); }
-Vector4 Quat::wxyx() const { return Vector4 (w, x, y, x); }
-Vector4 Quat::xyyx() const { return Vector4 (x, y, y, x); }
-Vector4 Quat::yyyx() const { return Vector4 (y, y, y, x); }
-Vector4 Quat::zyyx() const { return Vector4 (z, y, y, x); }
-Vector4 Quat::wyyx() const { return Vector4 (w, y, y, x); }
-Vector4 Quat::xzyx() const { return Vector4 (x, z, y, x); }
-Vector4 Quat::yzyx() const { return Vector4 (y, z, y, x); }
-Vector4 Quat::zzyx() const { return Vector4 (z, z, y, x); }
-Vector4 Quat::wzyx() const { return Vector4 (w, z, y, x); }
-Vector4 Quat::xwyx() const { return Vector4 (x, w, y, x); }
-Vector4 Quat::ywyx() const { return Vector4 (y, w, y, x); }
-Vector4 Quat::zwyx() const { return Vector4 (z, w, y, x); }
-Vector4 Quat::wwyx() const { return Vector4 (w, w, y, x); }
-Vector4 Quat::xxzx() const { return Vector4 (x, x, z, x); }
-Vector4 Quat::yxzx() const { return Vector4 (y, x, z, x); }
-Vector4 Quat::zxzx() const { return Vector4 (z, x, z, x); }
-Vector4 Quat::wxzx() const { return Vector4 (w, x, z, x); }
-Vector4 Quat::xyzx() const { return Vector4 (x, y, z, x); }
-Vector4 Quat::yyzx() const { return Vector4 (y, y, z, x); }
-Vector4 Quat::zyzx() const { return Vector4 (z, y, z, x); }
-Vector4 Quat::wyzx() const { return Vector4 (w, y, z, x); }
-Vector4 Quat::xzzx() const { return Vector4 (x, z, z, x); }
-Vector4 Quat::yzzx() const { return Vector4 (y, z, z, x); }
-Vector4 Quat::zzzx() const { return Vector4 (z, z, z, x); }
-Vector4 Quat::wzzx() const { return Vector4 (w, z, z, x); }
-Vector4 Quat::xwzx() const { return Vector4 (x, w, z, x); }
-Vector4 Quat::ywzx() const { return Vector4 (y, w, z, x); }
-Vector4 Quat::zwzx() const { return Vector4 (z, w, z, x); }
-Vector4 Quat::wwzx() const { return Vector4 (w, w, z, x); }
-Vector4 Quat::xxwx() const { return Vector4 (x, x, w, x); }
-Vector4 Quat::yxwx() const { return Vector4 (y, x, w, x); }
-Vector4 Quat::zxwx() const { return Vector4 (z, x, w, x); }
-Vector4 Quat::wxwx() const { return Vector4 (w, x, w, x); }
-Vector4 Quat::xywx() const { return Vector4 (x, y, w, x); }
-Vector4 Quat::yywx() const { return Vector4 (y, y, w, x); }
-Vector4 Quat::zywx() const { return Vector4 (z, y, w, x); }
-Vector4 Quat::wywx() const { return Vector4 (w, y, w, x); }
-Vector4 Quat::xzwx() const { return Vector4 (x, z, w, x); }
-Vector4 Quat::yzwx() const { return Vector4 (y, z, w, x); }
-Vector4 Quat::zzwx() const { return Vector4 (z, z, w, x); }
-Vector4 Quat::wzwx() const { return Vector4 (w, z, w, x); }
-Vector4 Quat::xwwx() const { return Vector4 (x, w, w, x); }
-Vector4 Quat::ywwx() const { return Vector4 (y, w, w, x); }
-Vector4 Quat::zwwx() const { return Vector4 (z, w, w, x); }
-Vector4 Quat::wwwx() const { return Vector4 (w, w, w, x); }
-Vector4 Quat::xxxy() const { return Vector4 (x, x, x, y); }
-Vector4 Quat::yxxy() const { return Vector4 (y, x, x, y); }
-Vector4 Quat::zxxy() const { return Vector4 (z, x, x, y); }
-Vector4 Quat::wxxy() const { return Vector4 (w, x, x, y); }
-Vector4 Quat::xyxy() const { return Vector4 (x, y, x, y); }
-Vector4 Quat::yyxy() const { return Vector4 (y, y, x, y); }
-Vector4 Quat::zyxy() const { return Vector4 (z, y, x, y); }
-Vector4 Quat::wyxy() const { return Vector4 (w, y, x, y); }
-Vector4 Quat::xzxy() const { return Vector4 (x, z, x, y); }
-Vector4 Quat::yzxy() const { return Vector4 (y, z, x, y); }
-Vector4 Quat::zzxy() const { return Vector4 (z, z, x, y); }
-Vector4 Quat::wzxy() const { return Vector4 (w, z, x, y); }
-Vector4 Quat::xwxy() const { return Vector4 (x, w, x, y); }
-Vector4 Quat::ywxy() const { return Vector4 (y, w, x, y); }
-Vector4 Quat::zwxy() const { return Vector4 (z, w, x, y); }
-Vector4 Quat::wwxy() const { return Vector4 (w, w, x, y); }
-Vector4 Quat::xxyy() const { return Vector4 (x, x, y, y); }
-Vector4 Quat::yxyy() const { return Vector4 (y, x, y, y); }
-Vector4 Quat::zxyy() const { return Vector4 (z, x, y, y); }
-Vector4 Quat::wxyy() const { return Vector4 (w, x, y, y); }
-Vector4 Quat::xyyy() const { return Vector4 (x, y, y, y); }
-Vector4 Quat::yyyy() const { return Vector4 (y, y, y, y); }
-Vector4 Quat::zyyy() const { return Vector4 (z, y, y, y); }
-Vector4 Quat::wyyy() const { return Vector4 (w, y, y, y); }
-Vector4 Quat::xzyy() const { return Vector4 (x, z, y, y); }
-Vector4 Quat::yzyy() const { return Vector4 (y, z, y, y); }
-Vector4 Quat::zzyy() const { return Vector4 (z, z, y, y); }
-Vector4 Quat::wzyy() const { return Vector4 (w, z, y, y); }
-Vector4 Quat::xwyy() const { return Vector4 (x, w, y, y); }
-Vector4 Quat::ywyy() const { return Vector4 (y, w, y, y); }
-Vector4 Quat::zwyy() const { return Vector4 (z, w, y, y); }
-Vector4 Quat::wwyy() const { return Vector4 (w, w, y, y); }
-Vector4 Quat::xxzy() const { return Vector4 (x, x, z, y); }
-Vector4 Quat::yxzy() const { return Vector4 (y, x, z, y); }
-Vector4 Quat::zxzy() const { return Vector4 (z, x, z, y); }
-Vector4 Quat::wxzy() const { return Vector4 (w, x, z, y); }
-Vector4 Quat::xyzy() const { return Vector4 (x, y, z, y); }
-Vector4 Quat::yyzy() const { return Vector4 (y, y, z, y); }
-Vector4 Quat::zyzy() const { return Vector4 (z, y, z, y); }
-Vector4 Quat::wyzy() const { return Vector4 (w, y, z, y); }
-Vector4 Quat::xzzy() const { return Vector4 (x, z, z, y); }
-Vector4 Quat::yzzy() const { return Vector4 (y, z, z, y); }
-Vector4 Quat::zzzy() const { return Vector4 (z, z, z, y); }
-Vector4 Quat::wzzy() const { return Vector4 (w, z, z, y); }
-Vector4 Quat::xwzy() const { return Vector4 (x, w, z, y); }
-Vector4 Quat::ywzy() const { return Vector4 (y, w, z, y); }
-Vector4 Quat::zwzy() const { return Vector4 (z, w, z, y); }
-Vector4 Quat::wwzy() const { return Vector4 (w, w, z, y); }
-Vector4 Quat::xxwy() const { return Vector4 (x, x, w, y); }
-Vector4 Quat::yxwy() const { return Vector4 (y, x, w, y); }
-Vector4 Quat::zxwy() const { return Vector4 (z, x, w, y); }
-Vector4 Quat::wxwy() const { return Vector4 (w, x, w, y); }
-Vector4 Quat::xywy() const { return Vector4 (x, y, w, y); }
-Vector4 Quat::yywy() const { return Vector4 (y, y, w, y); }
-Vector4 Quat::zywy() const { return Vector4 (z, y, w, y); }
-Vector4 Quat::wywy() const { return Vector4 (w, y, w, y); }
-Vector4 Quat::xzwy() const { return Vector4 (x, z, w, y); }
-Vector4 Quat::yzwy() const { return Vector4 (y, z, w, y); }
-Vector4 Quat::zzwy() const { return Vector4 (z, z, w, y); }
-Vector4 Quat::wzwy() const { return Vector4 (w, z, w, y); }
-Vector4 Quat::xwwy() const { return Vector4 (x, w, w, y); }
-Vector4 Quat::ywwy() const { return Vector4 (y, w, w, y); }
-Vector4 Quat::zwwy() const { return Vector4 (z, w, w, y); }
-Vector4 Quat::wwwy() const { return Vector4 (w, w, w, y); }
-Vector4 Quat::xxxz() const { return Vector4 (x, x, x, z); }
-Vector4 Quat::yxxz() const { return Vector4 (y, x, x, z); }
-Vector4 Quat::zxxz() const { return Vector4 (z, x, x, z); }
-Vector4 Quat::wxxz() const { return Vector4 (w, x, x, z); }
-Vector4 Quat::xyxz() const { return Vector4 (x, y, x, z); }
-Vector4 Quat::yyxz() const { return Vector4 (y, y, x, z); }
-Vector4 Quat::zyxz() const { return Vector4 (z, y, x, z); }
-Vector4 Quat::wyxz() const { return Vector4 (w, y, x, z); }
-Vector4 Quat::xzxz() const { return Vector4 (x, z, x, z); }
-Vector4 Quat::yzxz() const { return Vector4 (y, z, x, z); }
-Vector4 Quat::zzxz() const { return Vector4 (z, z, x, z); }
-Vector4 Quat::wzxz() const { return Vector4 (w, z, x, z); }
-Vector4 Quat::xwxz() const { return Vector4 (x, w, x, z); }
-Vector4 Quat::ywxz() const { return Vector4 (y, w, x, z); }
-Vector4 Quat::zwxz() const { return Vector4 (z, w, x, z); }
-Vector4 Quat::wwxz() const { return Vector4 (w, w, x, z); }
-Vector4 Quat::xxyz() const { return Vector4 (x, x, y, z); }
-Vector4 Quat::yxyz() const { return Vector4 (y, x, y, z); }
-Vector4 Quat::zxyz() const { return Vector4 (z, x, y, z); }
-Vector4 Quat::wxyz() const { return Vector4 (w, x, y, z); }
-Vector4 Quat::xyyz() const { return Vector4 (x, y, y, z); }
-Vector4 Quat::yyyz() const { return Vector4 (y, y, y, z); }
-Vector4 Quat::zyyz() const { return Vector4 (z, y, y, z); }
-Vector4 Quat::wyyz() const { return Vector4 (w, y, y, z); }
-Vector4 Quat::xzyz() const { return Vector4 (x, z, y, z); }
-Vector4 Quat::yzyz() const { return Vector4 (y, z, y, z); }
-Vector4 Quat::zzyz() const { return Vector4 (z, z, y, z); }
-Vector4 Quat::wzyz() const { return Vector4 (w, z, y, z); }
-Vector4 Quat::xwyz() const { return Vector4 (x, w, y, z); }
-Vector4 Quat::ywyz() const { return Vector4 (y, w, y, z); }
-Vector4 Quat::zwyz() const { return Vector4 (z, w, y, z); }
-Vector4 Quat::wwyz() const { return Vector4 (w, w, y, z); }
-Vector4 Quat::xxzz() const { return Vector4 (x, x, z, z); }
-Vector4 Quat::yxzz() const { return Vector4 (y, x, z, z); }
-Vector4 Quat::zxzz() const { return Vector4 (z, x, z, z); }
-Vector4 Quat::wxzz() const { return Vector4 (w, x, z, z); }
-Vector4 Quat::xyzz() const { return Vector4 (x, y, z, z); }
-Vector4 Quat::yyzz() const { return Vector4 (y, y, z, z); }
-Vector4 Quat::zyzz() const { return Vector4 (z, y, z, z); }
-Vector4 Quat::wyzz() const { return Vector4 (w, y, z, z); }
-Vector4 Quat::xzzz() const { return Vector4 (x, z, z, z); }
-Vector4 Quat::yzzz() const { return Vector4 (y, z, z, z); }
-Vector4 Quat::zzzz() const { return Vector4 (z, z, z, z); }
-Vector4 Quat::wzzz() const { return Vector4 (w, z, z, z); }
-Vector4 Quat::xwzz() const { return Vector4 (x, w, z, z); }
-Vector4 Quat::ywzz() const { return Vector4 (y, w, z, z); }
-Vector4 Quat::zwzz() const { return Vector4 (z, w, z, z); }
-Vector4 Quat::wwzz() const { return Vector4 (w, w, z, z); }
-Vector4 Quat::xxwz() const { return Vector4 (x, x, w, z); }
-Vector4 Quat::yxwz() const { return Vector4 (y, x, w, z); }
-Vector4 Quat::zxwz() const { return Vector4 (z, x, w, z); }
-Vector4 Quat::wxwz() const { return Vector4 (w, x, w, z); }
-Vector4 Quat::xywz() const { return Vector4 (x, y, w, z); }
-Vector4 Quat::yywz() const { return Vector4 (y, y, w, z); }
-Vector4 Quat::zywz() const { return Vector4 (z, y, w, z); }
-Vector4 Quat::wywz() const { return Vector4 (w, y, w, z); }
-Vector4 Quat::xzwz() const { return Vector4 (x, z, w, z); }
-Vector4 Quat::yzwz() const { return Vector4 (y, z, w, z); }
-Vector4 Quat::zzwz() const { return Vector4 (z, z, w, z); }
-Vector4 Quat::wzwz() const { return Vector4 (w, z, w, z); }
-Vector4 Quat::xwwz() const { return Vector4 (x, w, w, z); }
-Vector4 Quat::ywwz() const { return Vector4 (y, w, w, z); }
-Vector4 Quat::zwwz() const { return Vector4 (z, w, w, z); }
-Vector4 Quat::wwwz() const { return Vector4 (w, w, w, z); }
-Vector4 Quat::xxxw() const { return Vector4 (x, x, x, w); }
-Vector4 Quat::yxxw() const { return Vector4 (y, x, x, w); }
-Vector4 Quat::zxxw() const { return Vector4 (z, x, x, w); }
-Vector4 Quat::wxxw() const { return Vector4 (w, x, x, w); }
-Vector4 Quat::xyxw() const { return Vector4 (x, y, x, w); }
-Vector4 Quat::yyxw() const { return Vector4 (y, y, x, w); }
-Vector4 Quat::zyxw() const { return Vector4 (z, y, x, w); }
-Vector4 Quat::wyxw() const { return Vector4 (w, y, x, w); }
-Vector4 Quat::xzxw() const { return Vector4 (x, z, x, w); }
-Vector4 Quat::yzxw() const { return Vector4 (y, z, x, w); }
-Vector4 Quat::zzxw() const { return Vector4 (z, z, x, w); }
-Vector4 Quat::wzxw() const { return Vector4 (w, z, x, w); }
-Vector4 Quat::xwxw() const { return Vector4 (x, w, x, w); }
-Vector4 Quat::ywxw() const { return Vector4 (y, w, x, w); }
-Vector4 Quat::zwxw() const { return Vector4 (z, w, x, w); }
-Vector4 Quat::wwxw() const { return Vector4 (w, w, x, w); }
-Vector4 Quat::xxyw() const { return Vector4 (x, x, y, w); }
-Vector4 Quat::yxyw() const { return Vector4 (y, x, y, w); }
-Vector4 Quat::zxyw() const { return Vector4 (z, x, y, w); }
-Vector4 Quat::wxyw() const { return Vector4 (w, x, y, w); }
-Vector4 Quat::xyyw() const { return Vector4 (x, y, y, w); }
-Vector4 Quat::yyyw() const { return Vector4 (y, y, y, w); }
-Vector4 Quat::zyyw() const { return Vector4 (z, y, y, w); }
-Vector4 Quat::wyyw() const { return Vector4 (w, y, y, w); }
-Vector4 Quat::xzyw() const { return Vector4 (x, z, y, w); }
-Vector4 Quat::yzyw() const { return Vector4 (y, z, y, w); }
-Vector4 Quat::zzyw() const { return Vector4 (z, z, y, w); }
-Vector4 Quat::wzyw() const { return Vector4 (w, z, y, w); }
-Vector4 Quat::xwyw() const { return Vector4 (x, w, y, w); }
-Vector4 Quat::ywyw() const { return Vector4 (y, w, y, w); }
-Vector4 Quat::zwyw() const { return Vector4 (z, w, y, w); }
-Vector4 Quat::wwyw() const { return Vector4 (w, w, y, w); }
-Vector4 Quat::xxzw() const { return Vector4 (x, x, z, w); }
-Vector4 Quat::yxzw() const { return Vector4 (y, x, z, w); }
-Vector4 Quat::zxzw() const { return Vector4 (z, x, z, w); }
-Vector4 Quat::wxzw() const { return Vector4 (w, x, z, w); }
-Vector4 Quat::xyzw() const { return Vector4 (x, y, z, w); }
-Vector4 Quat::yyzw() const { return Vector4 (y, y, z, w); }
-Vector4 Quat::zyzw() const { return Vector4 (z, y, z, w); }
-Vector4 Quat::wyzw() const { return Vector4 (w, y, z, w); }
-Vector4 Quat::xzzw() const { return Vector4 (x, z, z, w); }
-Vector4 Quat::yzzw() const { return Vector4 (y, z, z, w); }
-Vector4 Quat::zzzw() const { return Vector4 (z, z, z, w); }
-Vector4 Quat::wzzw() const { return Vector4 (w, z, z, w); }
-Vector4 Quat::xwzw() const { return Vector4 (x, w, z, w); }
-Vector4 Quat::ywzw() const { return Vector4 (y, w, z, w); }
-Vector4 Quat::zwzw() const { return Vector4 (z, w, z, w); }
-Vector4 Quat::wwzw() const { return Vector4 (w, w, z, w); }
-Vector4 Quat::xxww() const { return Vector4 (x, x, w, w); }
-Vector4 Quat::yxww() const { return Vector4 (y, x, w, w); }
-Vector4 Quat::zxww() const { return Vector4 (z, x, w, w); }
-Vector4 Quat::wxww() const { return Vector4 (w, x, w, w); }
-Vector4 Quat::xyww() const { return Vector4 (x, y, w, w); }
-Vector4 Quat::yyww() const { return Vector4 (y, y, w, w); }
-Vector4 Quat::zyww() const { return Vector4 (z, y, w, w); }
-Vector4 Quat::wyww() const { return Vector4 (w, y, w, w); }
-Vector4 Quat::xzww() const { return Vector4 (x, z, w, w); }
-Vector4 Quat::yzww() const { return Vector4 (y, z, w, w); }
-Vector4 Quat::zzww() const { return Vector4 (z, z, w, w); }
-Vector4 Quat::wzww() const { return Vector4 (w, z, w, w); }
-Vector4 Quat::xwww() const { return Vector4 (x, w, w, w); }
-Vector4 Quat::ywww() const { return Vector4 (y, w, w, w); }
-Vector4 Quat::zwww() const { return Vector4 (z, w, w, w); }
-Vector4 Quat::wwww() const { return Vector4 (w, w, w, w); }
-}
-
diff --git a/externals/g3dlite/Random.cpp b/externals/g3dlite/Random.cpp
deleted file mode 100644
index 2dda744a1ac..00000000000
--- a/externals/g3dlite/Random.cpp
+++ /dev/null
@@ -1,212 +0,0 @@
-/**
- @file Random.cpp
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2009-01-02
- @edited 2009-03-29
-
- Copyright 2000-2009, Morgan McGuire.
- All rights reserved.
- */
-#include "G3D/Random.h"
-
-namespace G3D {
-
-Random& Random::common() {
- static Random r;
- return r;
-}
-
-Random::Random(void* x) : state(NULL), m_threadsafe(false) {
- (void)x;
-}
-
-
-Random::Random(uint32 seed, bool threadsafe) : m_threadsafe(threadsafe) {
- const uint32 X = 1812433253UL;
-
- state = new uint32[N];
- state[0] = seed;
- for (index = 1; index < (int)N; ++index) {
- state[index] = X * (state[index - 1] ^ (state[index - 1] >> 30)) + index;
- }
-}
-
-
-Random::~Random() {
- delete[] state;
- state = NULL;
-}
-
-
-uint32 Random::bits() {
- // See http://en.wikipedia.org/wiki/Mersenne_twister
-
- // Make a local copy of the index variable to ensure that it
- // is not out of bounds
- int localIndex = index;
-
- // Automatically checks for index < 0 if corrupted
- // by unsynchronized threads.
- if ((unsigned int)localIndex >= (unsigned int)N) {
- generate();
- localIndex = 0;
- }
- // Increment the global index. It may go out of bounds on
- // multiple threads, but the above check ensures that the
- // array index actually used never goes out of bounds.
- // It doesn't matter if we grab the same array index twice
- // on two threads, since the distribution of random numbers
- // will still be uniform.
- ++index;
- // Return the next random in the sequence
- uint32 r = state[localIndex];
-
- // Temper the result
- r ^= r >> U;
- r ^= (r << S) & B;
- r ^= (r << T) & C;
- r ^= r >> L;
-
- return r;
-}
-
-
-/** Generate the next N ints, and store them for readback later */
-void Random::generate() {
- // Lower R bits
- static const uint32 LOWER_MASK = (1LU << R) - 1;
-
- // Upper (32 - R) bits
- static const uint32 UPPER_MASK = 0xFFFFFFFF << R;
- static const uint32 mag01[2] = {0UL, (uint32)A};
-
- if (m_threadsafe) {
- bool contention = ! lock.lock();
- if (contention) {
- // Another thread just generated a set of numbers; no need for
- // this thread to do it too
- lock.unlock();
- return;
- }
- }
-
- // First N - M
- for (unsigned int i = 0; i < N - M; ++i) {
- uint32 x = (state[i] & UPPER_MASK) | (state[i + 1] & LOWER_MASK);
- state[i] = state[i + M] ^ (x >> 1) ^ mag01[x & 1];
- }
-
- // Rest
- for (unsigned int i = N - M + 1; i < N - 1; ++i) {
- uint32 x = (state[i] & UPPER_MASK) | (state[i + 1] & LOWER_MASK);
- state[i] = state[i + (M - N)] ^ (x >> 1) ^ mag01[x & 1];
- }
-
- uint32 y = (state[N - 1] & UPPER_MASK) | (state[0] & LOWER_MASK);
- state[N - 1] = state[M - 1] ^ (y >> 1) ^ mag01[y & 1];
- index = 0;
-
- if (m_threadsafe) {
- lock.unlock();
- }
-}
-
-
-int Random::integer(int low, int high) {
- int r = iFloor(low + (high - low + 1) * (double)bits() / 0xFFFFFFFFUL);
-
- // There is a *very small* chance of generating
- // a number larger than high.
- if (r > high) {
- return high;
- } else {
- return r;
- }
-}
-
-
-float Random::gaussian(float mean, float stdev) {
-
- // Using Box-Mueller method from http://www.taygeta.com/random/gaussian.html
- // Modified to specify standard deviation and mean of distribution
- float w, x1, x2;
-
- // Loop until w is less than 1 so that log(w) is negative
- do {
- x1 = uniform(-1.0, 1.0);
- x2 = uniform(-1.0, 1.0);
-
- w = float(square(x1) + square(x2));
- } while (w > 1.0f);
-
- // Transform to gassian distribution
- // Multiply by sigma (stdev ^ 2) and add mean.
- return x2 * (float)square(stdev) * sqrtf((-2.0f * logf(w) ) / w) + mean;
-}
-
-
-void Random::cosHemi(float& x, float& y, float& z) {
- const float e1 = uniform();
- const float e2 = uniform();
-
- // Jensen's method
- const float sin_theta = sqrtf(1.0f - e1);
- const float cos_theta = sqrtf(e1);
- const float phi = 6.28318531f * e2;
-
- x = cos(phi) * sin_theta;
- y = sin(phi) * sin_theta;
- z = cos_theta;
-
- // We could also use Malley's method (pbrt p.657), since they are the same cost:
- //
- // r = sqrt(e1);
- // t = 2*pi*e2;
- // x = cos(t)*r;
- // y = sin(t)*r;
- // z = sqrt(1.0 - x*x + y*y);
-}
-
-
-void Random::cosPowHemi(const float k, float& x, float& y, float& z) {
- const float e1 = uniform();
- const float e2 = uniform();
-
- const float cos_theta = pow(e1, 1.0f / (k + 1.0f));
- const float sin_theta = sqrtf(1.0f - square(cos_theta));
- const float phi = 6.28318531f * e2;
-
- x = cos(phi) * sin_theta;
- y = sin(phi) * sin_theta;
- z = cos_theta;
-}
-
-
-void Random::hemi(float& x, float& y, float& z) {
- sphere(x, y, z);
- z = fabsf(z);
-}
-
-
-void Random::sphere(float& x, float& y, float& z) {
- // Squared magnitude
- float m2;
-
- // Rejection sample
- do {
- x = uniform() * 2.0f - 1.0f,
- y = uniform() * 2.0f - 1.0f,
- z = uniform() * 2.0f - 1.0f;
- m2 = x*x + y*y + z*z;
- } while (m2 >= 1.0f);
-
- // Divide by magnitude to produce a unit vector
- float s = rsqrt(m2);
- x *= s;
- y *= s;
- z *= s;
-}
-
-} // G3D
diff --git a/externals/g3dlite/Ray.cpp b/externals/g3dlite/Ray.cpp
deleted file mode 100644
index 0436ef0b323..00000000000
--- a/externals/g3dlite/Ray.cpp
+++ /dev/null
@@ -1,218 +0,0 @@
-/**
- @file Ray.cpp
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2002-07-12
- @edited 2004-03-19
- */
-
-#include "G3D/platform.h"
-#include "G3D/Ray.h"
-#include "G3D/Plane.h"
-#include "G3D/Sphere.h"
-#include "G3D/CollisionDetection.h"
-
-namespace G3D {
-
-void Ray::set(const Vector3& origin, const Vector3& direction) {
- m_origin = origin;
- m_direction = direction;
- debugAssert(direction.isUnit());
-
- m_invDirection = Vector3::one() / direction;
-
- // ray slope
- ibyj = m_direction.x * m_invDirection.y;
- jbyi = m_direction.y * m_invDirection.x;
- jbyk = m_direction.y * m_invDirection.z;
- kbyj = m_direction.z * m_invDirection.y;
- ibyk = m_direction.x * m_invDirection.z;
- kbyi = m_direction.z * m_invDirection.x;
-
- // precomputed terms
- c_xy = m_origin.y - jbyi * m_origin.x;
- c_xz = m_origin.z - kbyi * m_origin.x;
- c_yx = m_origin.x - ibyj * m_origin.y;
- c_yz = m_origin.z - kbyj * m_origin.y;
- c_zx = m_origin.x - ibyk * m_origin.z;
- c_zy = m_origin.y - jbyk * m_origin.z;
-
- //ray slope classification
- if (m_direction.x < 0) {
- if (m_direction.y < 0) {
- if (m_direction.z < 0) {
- classification = MMM;
- } else if (m_direction.z > 0) {
- classification = MMP;
- } else { //(m_direction.z >= 0)
- classification = MMO;
- }
- } else { //(m_direction.y >= 0)
- if (m_direction.z < 0) {
- if (m_direction.y == 0) {
- classification = MOM;
- } else {
- classification = MPM;
- }
- } else { //(m_direction.z >= 0)
- if ((m_direction.y == 0) && (m_direction.z == 0)) {
- classification = MOO;
- } else if (m_direction.z == 0) {
- classification = MPO;
- } else if (m_direction.y == 0) {
- classification = MOP;
- } else {
- classification = MPP;
- }
- }
- }
- } else { //(m_direction.x >= 0)
- if (m_direction.y < 0) {
- if (m_direction.z < 0) {
- if (m_direction.x == 0) {
- classification = OMM;
- } else {
- classification = PMM;
- }
- } else { //(m_direction.z >= 0)
- if ((m_direction.x == 0) && (m_direction.z == 0)) {
- classification = OMO;
- } else if (m_direction.z == 0) {
- classification = PMO;
- } else if (m_direction.x == 0) {
- classification = OMP;
- } else {
- classification = PMP;
- }
- }
- } else { //(m_direction.y >= 0)
- if (m_direction.z < 0) {
- if ((m_direction.x == 0) && (m_direction.y == 0)) {
- classification = OOM;
- } else if (m_direction.x == 0) {
- classification = OPM;
- } else if (m_direction.y == 0) {
- classification = POM;
- } else {
- classification = PPM;
- }
- } else { //(m_direction.z > 0)
- if (m_direction.x == 0) {
- if (m_direction.y == 0) {
- classification = OOP;
- } else if (m_direction.z == 0) {
- classification = OPO;
- } else {
- classification = OPP;
- }
- } else {
- if ((m_direction.y == 0) && (m_direction.z == 0)) {
- classification = POO;
- } else if (m_direction.y == 0) {
- classification = POP;
- } else if (m_direction.z == 0) {
- classification = PPO;
- } else {
- classification = PPP;
- }
- }
- }
- }
- }
-}
-
-Ray::Ray(class BinaryInput& b) {
- deserialize(b);
-}
-
-
-void Ray::serialize(class BinaryOutput& b) const {
- m_origin.serialize(b);
- m_direction.serialize(b);
-}
-
-
-void Ray::deserialize(class BinaryInput& b) {
- m_origin.deserialize(b);
- m_direction.deserialize(b);
- set(m_origin, m_direction);
-}
-
-
-Ray Ray::refract(
- const Vector3& newOrigin,
- const Vector3& normal,
- float iInside,
- float iOutside) const {
-
- Vector3 D = m_direction.refractionDirection(normal, iInside, iOutside);
- return Ray(newOrigin + (m_direction + normal * (float)sign(m_direction.dot(normal))) * 0.001f, D);
-}
-
-
-Ray Ray::reflect(
- const Vector3& newOrigin,
- const Vector3& normal) const {
-
- Vector3 D = m_direction.reflectionDirection(normal);
- return Ray(newOrigin + (D + normal) * 0.001f, D);
-}
-
-
-Vector3 Ray::intersection(const Plane& plane) const {
- float d;
- Vector3 normal = plane.normal();
- plane.getEquation(normal, d);
- float rate = m_direction.dot(normal);
-
- if (rate >= 0.0f) {
- return Vector3::inf();
- } else {
- float t = -(d + m_origin.dot(normal)) / rate;
- return m_origin + m_direction * t;
- }
-}
-
-
-float Ray::intersectionTime(const class Sphere& sphere, bool solid) const {
- Vector3 dummy;
- return CollisionDetection::collisionTimeForMovingPointFixedSphere(
- m_origin, m_direction, sphere, dummy, dummy, solid);
-}
-
-
-float Ray::intersectionTime(const class Plane& plane) const {
- Vector3 dummy;
- return CollisionDetection::collisionTimeForMovingPointFixedPlane(
- m_origin, m_direction, plane, dummy);
-}
-
-
-float Ray::intersectionTime(const class Box& box) const {
- Vector3 dummy;
- float time = CollisionDetection::collisionTimeForMovingPointFixedBox(
- m_origin, m_direction, box, dummy);
-
- if ((time == finf()) && (box.contains(m_origin))) {
- return 0.0f;
- } else {
- return time;
- }
-}
-
-
-float Ray::intersectionTime(const class AABox& box) const {
- Vector3 dummy;
- bool inside;
- float time = CollisionDetection::collisionTimeForMovingPointFixedAABox(
- m_origin, m_direction, box, dummy, inside);
-
- if ((time == finf()) && inside) {
- return 0.0f;
- } else {
- return time;
- }
-}
-
-}
diff --git a/externals/g3dlite/ReferenceCount.cpp b/externals/g3dlite/ReferenceCount.cpp
deleted file mode 100644
index 2e1f117e0d9..00000000000
--- a/externals/g3dlite/ReferenceCount.cpp
+++ /dev/null
@@ -1,61 +0,0 @@
-/**
- @file ReferenceCount.cpp
-
- Reference Counting Garbage Collector for C++
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @cite Adapted and extended from Justin Miller's "RGC" class that appeared in BYTE magazine.
- @cite See also http://www.jelovic.com/articles/cpp_without_memory_errors_slides.htm
-
- @created 2001-10-23
- @edited 2009-04-25
-*/
-#include "G3D/platform.h"
-#include "G3D/ReferenceCount.h"
-
-namespace G3D {
-
-ReferenceCountedObject::ReferenceCountedObject() :
- ReferenceCountedObject_refCount(0),
- ReferenceCountedObject_weakPointer(0) {
-
- debugAssertM(isValidHeapPointer(this),
- "Reference counted objects must be allocated on the heap.");
-}
-
-void ReferenceCountedObject::ReferenceCountedObject_zeroWeakPointers() {
- // Tell all of my weak pointers that I'm gone.
-
- _WeakPtrLinkedList* node = ReferenceCountedObject_weakPointer;
-
- while (node != NULL) {
- // Notify the weak pointer that it is going away
- node->weakPtr->objectCollected();
-
- // Free the node and advance
- _WeakPtrLinkedList* tmp = node;
- node = node->next;
- delete tmp;
- }
-}
-
-ReferenceCountedObject::~ReferenceCountedObject() {}
-
-
-ReferenceCountedObject::ReferenceCountedObject(const ReferenceCountedObject& notUsed) :
- ReferenceCountedObject_refCount(0),
- ReferenceCountedObject_weakPointer(0) {
- (void)notUsed;
- debugAssertM(G3D::isValidHeapPointer(this),
- "Reference counted objects must be allocated on the heap.");
-}
-
-ReferenceCountedObject& ReferenceCountedObject::operator=(const ReferenceCountedObject& other) {
- (void)other;
- // Nothing changes when I am assigned; the reference count on
- // both objects is the same (although my super-class probably
- // changes).
- return *this;
-}
-
-} // G3D
diff --git a/externals/g3dlite/RegistryUtil.cpp b/externals/g3dlite/RegistryUtil.cpp
deleted file mode 100644
index fc4cebc2ee5..00000000000
--- a/externals/g3dlite/RegistryUtil.cpp
+++ /dev/null
@@ -1,290 +0,0 @@
-/**
- @file RegistryUtil.cpp
-
- @created 2006-04-06
- @edited 2006-04-24
-
- Copyright 2000-2006, Morgan McGuire.
- All rights reserved.
-*/
-
-#include "G3D/platform.h"
-
-// This file is only used on Windows
-#ifdef G3D_WIN32
-
-#include "G3D/RegistryUtil.h"
-#include "G3D/System.h"
-
-namespace G3D {
-
-// static helpers
-static HKEY getRootKeyFromString(const char* str, size_t length);
-
-
-bool RegistryUtil::keyExists(const std::string& key) {
- size_t pos = key.find('\\', 0);
- if (pos == std::string::npos) {
- return false;
- }
-
- HKEY hkey = getRootKeyFromString(key.c_str(), pos);
-
- if (hkey == NULL) {
- return false;
- }
-
- HKEY openKey;
- int32 result = RegOpenKeyExA(hkey, (key.c_str() + pos + 1), 0, KEY_READ, &openKey);
-
- debugAssert(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND);
-
- if (result == ERROR_SUCCESS) {
- RegCloseKey(openKey);
- return true;
- } else {
- return false;
- }
-}
-
-bool RegistryUtil::valueExists(const std::string& key, const std::string& value) {
- size_t pos = key.find('\\', 0);
- if (pos == std::string::npos) {
- return false;
- }
-
- HKEY hkey = getRootKeyFromString(key.c_str(), pos);
-
- if ( hkey == NULL ) {
- return false;
- }
-
- HKEY openKey;
- int32 result = RegOpenKeyExA(hkey, (key.c_str() + pos + 1), 0, KEY_READ, &openKey);
- debugAssert(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND);
-
- if (result == ERROR_SUCCESS) {
- uint32 dataSize = 0;
- result = RegQueryValueExA(openKey, value.c_str(), NULL, NULL, NULL, reinterpret_cast<LPDWORD>(&dataSize));
-
- debugAssert(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND);
- RegCloseKey(openKey);
- }
- return (result == ERROR_SUCCESS);
-}
-
-
-bool RegistryUtil::readInt32(const std::string& key, const std::string& value, int32& data) {
- size_t pos = key.find('\\', 0);
- if (pos == std::string::npos) {
- return false;
- }
-
- HKEY hkey = getRootKeyFromString(key.c_str(), pos);
-
- if ( hkey == NULL ) {
- return false;
- }
-
- HKEY openKey;
- int32 result = RegOpenKeyExA(hkey, (key.c_str() + pos + 1), 0, KEY_READ, &openKey);
- debugAssert(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND);
-
- if (result == ERROR_SUCCESS) {
- uint32 dataSize = sizeof(int32);
- result = RegQueryValueExA(openKey, value.c_str(), NULL, NULL, reinterpret_cast<LPBYTE>(&data), reinterpret_cast<LPDWORD>(&dataSize));
-
- debugAssertM(result == ERROR_SUCCESS, "Could not read registry key value.");
-
- RegCloseKey(openKey);
- }
- return (result == ERROR_SUCCESS);
-}
-
-bool RegistryUtil::readBytes(const std::string& key, const std::string& value, uint8* data, uint32& dataSize) {
- size_t pos = key.find('\\', 0);
- if (pos == std::string::npos) {
- return false;
- }
-
- HKEY hkey = getRootKeyFromString(key.c_str(), pos);
-
- if (hkey == NULL) {
- return false;
- }
-
- HKEY openKey;
- int32 result = RegOpenKeyExA(hkey, (key.c_str() + pos + 1), 0, KEY_READ, &openKey);
- debugAssert(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND);
-
- if (result == ERROR_SUCCESS) {
- if (data == NULL) {
- result = RegQueryValueExA(openKey, value.c_str(), NULL, NULL, NULL, reinterpret_cast<LPDWORD>(&dataSize));
- } else {
- result = RegQueryValueExA(openKey, value.c_str(), NULL, NULL, reinterpret_cast<LPBYTE>(&data), reinterpret_cast<LPDWORD>(&dataSize));
- }
-
- debugAssertM(result == ERROR_SUCCESS, "Could not read registry key value.");
-
- RegCloseKey(openKey);
- }
- return (result == ERROR_SUCCESS);
-}
-
-bool RegistryUtil::readString(const std::string& key, const std::string& value, std::string& data) {
- size_t pos = key.find('\\', 0);
- if (pos == std::string::npos) {
- return false;
- }
-
- HKEY hkey = getRootKeyFromString(key.c_str(), pos);
-
- if (hkey == NULL) {
- return false;
- }
-
- HKEY openKey;
- int32 result = RegOpenKeyExA(hkey, (key.c_str() + pos + 1), 0, KEY_READ, &openKey);
- debugAssert(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND);
-
- if (result == ERROR_SUCCESS) {
- uint32 dataSize = 0;
-
- result = RegQueryValueExA(openKey, value.c_str(), NULL, NULL, NULL, reinterpret_cast<LPDWORD>(&dataSize));
- debugAssertM(result == ERROR_SUCCESS, "Could not read registry key value.");
-
- // increment datasize to allow for non null-terminated strings in registry
- dataSize += 1;
-
- if (result == ERROR_SUCCESS) {
- char* tmpStr = static_cast<char*>(System::malloc(dataSize));
- System::memset(tmpStr, 0, dataSize);
-
- result = RegQueryValueExA(openKey, value.c_str(), NULL, NULL, reinterpret_cast<LPBYTE>(tmpStr), reinterpret_cast<LPDWORD>(&dataSize));
- debugAssertM(result == ERROR_SUCCESS, "Could not read registry key value.");
-
- if (result == ERROR_SUCCESS) {
- data = tmpStr;
- }
-
- RegCloseKey(openKey);
- System::free(tmpStr);
- }
- }
- return (result == ERROR_SUCCESS);
-}
-
-bool RegistryUtil::writeInt32(const std::string& key, const std::string& value, int32 data) {
- size_t pos = key.find('\\', 0);
- if (pos == std::string::npos) {
- return false;
- }
-
- HKEY hkey = getRootKeyFromString(key.c_str(), pos);
-
- if (hkey == NULL) {
- return false;
- }
-
- HKEY openKey;
- int32 result = RegOpenKeyExA(hkey, (key.c_str() + pos + 1), 0, KEY_WRITE, &openKey);
- debugAssert(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND);
-
- if (result == ERROR_SUCCESS) {
- result = RegSetValueExA(openKey, value.c_str(), 0, REG_DWORD, reinterpret_cast<const BYTE*>(&data), sizeof(int32));
-
- debugAssertM(result == ERROR_SUCCESS, "Could not write registry key value.");
-
- RegCloseKey(openKey);
- }
- return (result == ERROR_SUCCESS);
-}
-
-bool RegistryUtil::writeBytes(const std::string& key, const std::string& value, const uint8* data, uint32 dataSize) {
- debugAssert(data);
-
- size_t pos = key.find('\\', 0);
- if (pos == std::string::npos) {
- return false;
- }
-
- HKEY hkey = getRootKeyFromString(key.c_str(), pos);
-
- if (hkey == NULL) {
- return false;
- }
-
- HKEY openKey;
- int32 result = RegOpenKeyExA(hkey, (key.c_str() + pos + 1), 0, KEY_WRITE, &openKey);
- debugAssert(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND);
-
- if (result == ERROR_SUCCESS) {
- if (data) {
- result = RegSetValueExA(openKey, value.c_str(), 0, REG_BINARY, reinterpret_cast<const BYTE*>(data), dataSize);
- }
-
- debugAssertM(result == ERROR_SUCCESS, "Could not write registry key value.");
-
- RegCloseKey(openKey);
- }
- return (result == ERROR_SUCCESS);
-}
-
-bool RegistryUtil::writeString(const std::string& key, const std::string& value, const std::string& data) {
- size_t pos = key.find('\\', 0);
- if (pos == std::string::npos) {
- return false;
- }
-
- HKEY hkey = getRootKeyFromString(key.c_str(), pos);
-
- if (hkey == NULL) {
- return false;
- }
-
- HKEY openKey;
- int32 result = RegOpenKeyExA(hkey, (key.c_str() + pos + 1), 0, KEY_WRITE, &openKey);
- debugAssert(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND);
-
- if (result == ERROR_SUCCESS) {
- result = RegSetValueExA(openKey, value.c_str(), 0, REG_SZ, reinterpret_cast<const BYTE*>(data.c_str()), (data.size() + 1));
- debugAssertM(result == ERROR_SUCCESS, "Could not write registry key value.");
-
- RegCloseKey(openKey);
- }
- return (result == ERROR_SUCCESS);
-}
-
-
-// static helpers
-static HKEY getRootKeyFromString(const char* str, size_t length) {
- debugAssert(str);
-
- if (str) {
- if ( strncmp(str, "HKEY_CLASSES_ROOT", length) == 0 ) {
- return HKEY_CLASSES_ROOT;
- } else if ( strncmp(str, "HKEY_CURRENT_CONFIG", length) == 0 ) {
- return HKEY_CURRENT_CONFIG;
- } else if ( strncmp(str, "HKEY_CURRENT_USER", length) == 0 ) {
- return HKEY_CURRENT_USER;
- } else if ( strncmp(str, "HKEY_LOCAL_MACHINE", length) == 0 ) {
- return HKEY_LOCAL_MACHINE;
- } else if ( strncmp(str, "HKEY_PERFORMANCE_DATA", length) == 0 ) {
- return HKEY_PERFORMANCE_DATA;
- } else if ( strncmp(str, "HKEY_PERFORMANCE_NLSTEXT", length) == 0 ) {
- return HKEY_PERFORMANCE_NLSTEXT;
- } else if ( strncmp(str, "HKEY_PERFORMANCE_TEXT", length) == 0 ) {
- return HKEY_PERFORMANCE_TEXT;
- } else if ( strncmp(str, "HKEY_CLASSES_ROOT", length) == 0 ) {
- return HKEY_CLASSES_ROOT;
- } else {
- return NULL;
- }
- } else {
- return NULL;
- }
-}
-
-} // namespace G3D
-
-#endif // G3D_WIN32
diff --git a/externals/g3dlite/Sphere.cpp b/externals/g3dlite/Sphere.cpp
deleted file mode 100644
index 4ed0811cb29..00000000000
--- a/externals/g3dlite/Sphere.cpp
+++ /dev/null
@@ -1,223 +0,0 @@
-/**
- @file Sphere.cpp
-
- Sphere class
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2001-04-17
- @edited 2009-01-20
- */
-
-#include "G3D/platform.h"
-#include "G3D/Sphere.h"
-#include "G3D/stringutils.h"
-#include "G3D/BinaryOutput.h"
-#include "G3D/BinaryInput.h"
-#include "G3D/AABox.h"
-#include "G3D/Plane.h"
-
-namespace G3D {
-
-int32 Sphere::dummy;
-
-Sphere::Sphere(class BinaryInput& b) {
- deserialize(b);
-}
-
-
-void Sphere::serialize(class BinaryOutput& b) const {
- center.serialize(b);
- b.writeFloat64(radius);
-}
-
-
-void Sphere::deserialize(class BinaryInput& b) {
- center.deserialize(b);
- radius = (float)b.readFloat64();
-}
-
-
-std::string Sphere::toString() const {
- return format("Sphere(<%g, %g, %g>, %g)",
- center.x, center.y, center.z, radius);
-}
-
-
-bool Sphere::contains(const Vector3& point) const {
- float distance = (center - point).squaredMagnitude();
- return distance <= square(radius);
-}
-
-
-bool Sphere::contains(const Sphere& other) const {
- float distance = (center - other.center).squaredMagnitude();
- return (radius >= other.radius) && (distance <= square(radius - other.radius));
-}
-
-
-bool Sphere::intersects(const Sphere& other) const {
- return (other.center - center).length() <= (radius + other.radius);
-}
-
-
-void Sphere::merge(const Sphere& other) {
- if (other.contains(*this)) {
- *this = other;
- } else if (! contains(other)) {
- // The farthest distance is along the axis between the centers, which
- // must not be colocated since neither contains the other.
- Vector3 toMe = center - other.center;
- // Get a point on the axis from each
- toMe = toMe.direction();
- const Vector3& A = center + toMe * radius;
- const Vector3& B = other.center - toMe * other.radius;
-
- // Now just bound the A->B segment
- center = (A + B) * 0.5f;
- radius = (A - B).length();
- }
- // (if this contains other, we're done)
-}
-
-
-bool Sphere::culledBy(
- const Array<Plane>& plane,
- int& cullingPlaneIndex,
- const uint32 inMask,
- uint32& outMask) const {
-
- return culledBy(plane.getCArray(), plane.size(), cullingPlaneIndex, inMask, outMask);
-}
-
-
-bool Sphere::culledBy(
- const Array<Plane>& plane,
- int& cullingPlaneIndex,
- const uint32 inMask) const {
-
- return culledBy(plane.getCArray(), plane.size(), cullingPlaneIndex, inMask);
-}
-
-
-bool Sphere::culledBy(
- const class Plane* plane,
- int numPlanes,
- int& cullingPlane,
- const uint32 _inMask,
- uint32& childMask) const {
-
- if (radius == finf()) {
- // No plane can cull the infinite box
- return false;
- }
-
- uint32 inMask = _inMask;
- assert(numPlanes < 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) {
-
- bool culledLow = ! plane[p].halfSpaceContainsFinite(center + plane[p].normal() * radius);
- bool culledHigh = ! plane[p].halfSpaceContainsFinite(center - plane[p].normal() * radius);
-
- if (culledLow) {
- // Plane p culled the sphere
- 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;
-
- } else if (culledHigh) {
- // 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;
- }
-
- // None of the planes could cull this box
- cullingPlane = -1;
- return false;
-}
-
-
-bool Sphere::culledBy(
- const class Plane* plane,
- int numPlanes,
- int& cullingPlane,
- const uint32 _inMask) const {
-
- uint32 inMask = _inMask;
- assert(numPlanes < 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++) {
-
- // Only test planes that are not masked
- if ((inMask & 1) != 0) {
- bool culled = ! plane[p].halfSpaceContains(center + plane[p].normal() * radius);
- if (culled) {
- // Plane p culled the sphere
- cullingPlane = p;
- return true;
- }
- }
-
- // Move on to the next bit.
- inMask = inMask >> 1;
- }
-
- // None of the planes could cull this box
- cullingPlane = -1;
- return false;
-}
-
-
-Vector3 Sphere::randomSurfacePoint() const {
- return Vector3::random() * radius + center;
-}
-
-
-Vector3 Sphere::randomInteriorPoint() const {
- Vector3 result;
- do {
- result = Vector3(uniformRandom(-1, 1),
- uniformRandom(-1, 1),
- uniformRandom(-1, 1));
- } while (result.squaredMagnitude() >= 1.0f);
-
- return result * radius + center;
-}
-
-
-float Sphere::volume() const {
- return (float)pi() * (4.0f / 3.0f) * powf((float)radius, 3.0f);
-}
-
-
-float Sphere::area() const {
- return (float)pi() * 4.0f * powf((float)radius, 2.0f);
-}
-
-
-void Sphere::getBounds(AABox& out) const {
- Vector3 extent(radius, radius, radius);
- out = AABox(center - extent, center + extent);
-}
-
-} // namespace
diff --git a/externals/g3dlite/System.cpp b/externals/g3dlite/System.cpp
deleted file mode 100644
index e03c4e8c6fa..00000000000
--- a/externals/g3dlite/System.cpp
+++ /dev/null
@@ -1,1746 +0,0 @@
-/**
- @file System.cpp
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- Note: every routine must call init() first.
-
- There are two kinds of detection used in this file. At compile
- time, the _MSC_VER #define is used to determine whether x86 assembly
- can be used at all. At runtime, processor detection is used to
- determine if we can safely call the routines that use that assembly.
-
- @created 2003-01-25
- @edited 2010-01-03
- */
-
-#include "G3D/platform.h"
-#include "G3D/System.h"
-#include "G3D/debug.h"
-#include "G3D/fileutils.h"
-#include "G3D/TextOutput.h"
-#include "G3D/G3DGameUnits.h"
-#include "G3D/Crypto.h"
-#include "G3D/prompt.h"
-#include "G3D/stringutils.h"
-#include "G3D/Log.h"
-#include "G3D/Table.h"
-#include "G3D/GMutex.h"
-#include "G3D/units.h"
-#include <time.h>
-
-#include <cstring>
-#include <cstdio>
-
-// Uncomment the following line to turn off G3D::System memory
-// allocation and use the operating system's malloc.
-//#define NO_BUFFERPOOL
-
-#if defined(__i386__) || defined(__x86_64__) || defined(G3D_WIN32)
-# define G3D_NOT_OSX_PPC
-#endif
-
-#include <cstdlib>
-
-#ifdef G3D_WIN32
-
-# include <conio.h>
-# include <sys/timeb.h>
-# include "G3D/RegistryUtil.h"
-
-#elif defined(G3D_LINUX)
-
-# include <stdlib.h>
-# include <stdio.h>
-# include <errno.h>
-# include <sys/types.h>
-# include <sys/select.h>
-# include <termios.h>
-# include <unistd.h>
-# include <sys/ioctl.h>
-# include <sys/time.h>
-# include <pthread.h>
-
-#elif defined(G3D_OSX)
-
- #include <stdlib.h>
- #include <stdio.h>
- #include <errno.h>
- #include <sys/types.h>
- #include <sys/sysctl.h>
- #include <sys/select.h>
- #include <sys/time.h>
- #include <termios.h>
- #include <unistd.h>
- #include <pthread.h>
- #include <mach-o/arch.h>
-
- #include <sstream>
- #include <CoreServices/CoreServices.h>
-#endif
-
-// SIMM include
-#ifdef __SSE__
-#include <xmmintrin.h>
-#endif
-
-namespace G3D {
-
-
-/** Checks if the CPUID command is available on the processor (called from init) */
-static bool checkForCPUID();
-
-/** Called from init */
-static void getG3DVersion(std::string& s);
-
-/** Called from init */
-static G3DEndian checkEndian();
-
-
-System& System::instance() {
- static System thesystem;
- return thesystem;
-}
-
-
-System::System() :
- m_initialized(false),
- m_cpuSpeed(0),
- m_hasCPUID(false),
- m_hasRDTSC(false),
- m_hasMMX(false),
- m_hasSSE(false),
- m_hasSSE2(false),
- m_hasSSE3(false),
- m_has3DNOW(false),
- m_has3DNOW2(false),
- m_hasAMDMMX(false),
- m_cpuVendor("Uninitialized"),
- m_numCores(1),
- m_machineEndian(G3D_LITTLE_ENDIAN),
- m_cpuArch("Uninitialized"),
- m_operatingSystem("Uninitialized"),
- m_version("Uninitialized"),
- m_outOfMemoryCallback(NULL),
- m_realWorldGetTickTime0(0),
- m_highestCPUIDFunction(0) {
-
- init();
-}
-
-
-void System::init() {
- // NOTE: Cannot use most G3D data structures or utility functions
- // in here because they are not initialized.
-
- if (m_initialized) {
- return;
- } else {
- m_initialized = true;
- }
-
- getG3DVersion(m_version);
-
- m_machineEndian = checkEndian();
-
- m_hasCPUID = checkForCPUID();
- // Process the CPUID information
- if (m_hasCPUID) {
- // We read the standard CPUID level 0x00000000 which should
- // be available on every x86 processor. This fills out
- // a string with the processor vendor tag.
- unsigned int eaxreg = 0, ebxreg = 0, ecxreg = 0, edxreg = 0;
-
- cpuid(CPUID_VENDOR_ID, eaxreg, ebxreg, ecxreg, edxreg);
-
- {
- char c[100];
- // Then we connect the single register values to the vendor string
- *((unsigned int*) c) = ebxreg;
- *((unsigned int*) (c + 4)) = edxreg;
- *((unsigned int*) (c + 8)) = ecxreg;
- c[12] = '\0';
- m_cpuVendor = c;
- }
-
- switch (ebxreg) {
- case 0x756E6547: // GenuineIntel
- m_cpuArch = "Intel Processor";
- break;
-
- case 0x68747541: // AuthenticAMD
- m_cpuArch = "AMD Processor";
- break;
-
- case 0x69727943: // CyrixInstead
- m_cpuArch = "Cyrix Processor";
- break;
-
- default:
- m_cpuArch = "Unknown Processor Vendor";
- break;
- }
-
-
- unsigned int highestFunction = eaxreg;
- if (highestFunction >= CPUID_NUM_CORES) {
- cpuid(CPUID_NUM_CORES, eaxreg, ebxreg, ecxreg, edxreg);
- // Number of cores is in (eax>>26) + 1
- m_numCores = (eaxreg >> 26) + 1;
- }
-
- cpuid(CPUID_GET_HIGHEST_FUNCTION, m_highestCPUIDFunction, ebxreg, ecxreg, edxreg);
- }
-
-
- // Get the operating system name (also happens to read some other information)
-# ifdef G3D_WIN32
- // Note that this overrides some of the values computed above
- bool success = RegistryUtil::readInt32
- ("HKEY_LOCAL_MACHINE\\HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0",
- "~MHz", m_cpuSpeed);
-
- SYSTEM_INFO systemInfo;
- GetSystemInfo(&systemInfo);
- const char* arch = NULL;
- switch (systemInfo.wProcessorArchitecture) {
- case PROCESSOR_ARCHITECTURE_INTEL:
- arch = "Intel";
- break;
-
- case PROCESSOR_ARCHITECTURE_MIPS:
- arch = "MIPS";
- break;
-
- case PROCESSOR_ARCHITECTURE_ALPHA:
- arch = "Alpha";
- break;
-
- case PROCESSOR_ARCHITECTURE_PPC:
- arch = "Power PC";
- break;
-
- default:
- arch = "Unknown";
- }
-
- m_numCores = systemInfo.dwNumberOfProcessors;
- uint32 maxAddr = (uint32)systemInfo.lpMaximumApplicationAddress;
- {
- char c[1024];
- sprintf(c, "%d x %d-bit %s processor",
- systemInfo.dwNumberOfProcessors,
- (int)(::log((double)maxAddr) / ::log(2.0) + 2.0),
- arch);
- m_cpuArch = c;
- }
-
- OSVERSIONINFO osVersionInfo;
- osVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
- success = GetVersionEx(&osVersionInfo) != 0;
-
- if (success) {
- char c[1000];
- sprintf(c, "Windows %d.%d build %d Platform %d %s",
- osVersionInfo.dwMajorVersion,
- osVersionInfo.dwMinorVersion,
- osVersionInfo.dwBuildNumber,
- osVersionInfo.dwPlatformId,
- osVersionInfo.szCSDVersion);
- m_operatingSystem = c;
- } else {
- m_operatingSystem = "Windows";
- }
-
-# elif defined(G3D_LINUX) || defined(G3D_FREEBSD)
-
- {
- // Find the operating system using the 'uname' command
- FILE* f = popen("uname -a", "r");
-
- int len = 100;
- char* r = (char*)::malloc(len * sizeof(char));
- fgets(r, len, f);
- // Remove trailing newline
- if (r[strlen(r) - 1] == '\n') {
- r[strlen(r) - 1] = '\0';
- }
- fclose(f);
-
- m_operatingSystem = r;
- ::free(r);
- }
-
-# elif defined(G3D_OSX)
-
- // Operating System:
- SInt32 macVersion;
- Gestalt(gestaltSystemVersion, &macVersion);
-
- int major = (macVersion >> 8) & 0xFF;
- int minor = (macVersion >> 4) & 0xF;
- int revision = macVersion & 0xF;
-
- {
- char c[1000];
- sprintf(c, "OS X %x.%x.%x", major, minor, revision);
- m_operatingSystem = c;
- }
-
- // Clock Cycle Timing Information:
- Gestalt('pclk', &m_OSXCPUSpeed);
- m_cpuSpeed = iRound((double)m_OSXCPUSpeed / (1024 * 1024));
- m_secondsPerNS = 1.0 / 1.0e9;
-
- // System Architecture:
- const NXArchInfo* pInfo = NXGetLocalArchInfo();
-
- if (pInfo) {
- m_cpuArch = pInfo->description;
-
- switch (pInfo->cputype) {
- case CPU_TYPE_POWERPC:
- switch(pInfo->cpusubtype){
- case CPU_SUBTYPE_POWERPC_750:
- case CPU_SUBTYPE_POWERPC_7400:
- case CPU_SUBTYPE_POWERPC_7450:
- m_cpuVendor = "Motorola";
- break;
- case CPU_SUBTYPE_POWERPC_970:
- m_cpuVendor = "IBM";
- break;
- }
- break;
-
- case CPU_TYPE_I386:
- m_cpuVendor = "Intel";
- break;
- }
- }
-# endif
-
- initTime();
-
- getStandardProcessorExtensions();
-}
-
-
-void getG3DVersion(std::string& s) {
- char cstr[100];
- if ((G3D_VER % 100) != 0) {
- sprintf(cstr, "G3D %d.%02d beta %d",
- G3D_VER / 10000,
- (G3D_VER / 100) % 100,
- G3D_VER % 100);
- } else {
- sprintf(cstr, "G3D %d.%02d",
- G3D_VER / 10000,
- (G3D_VER / 100) % 100);
- }
- s = cstr;
-}
-
-#if 0 // TODO: delete
-struct Directory {
- std::string path;
- Array<std::string> contents;
-};
-
-static bool maybeAddDirectory(const std::string& newPath, Array<Directory>& directoryArray, bool recurse = true) {
- if (fileExists(newPath)) {
- Directory& d = directoryArray.next();
- d.path = newPath;
- getFiles(pathConcat(newPath, "*"), d.contents);
- Array<std::string> dirs;
- getDirs(pathConcat(newPath, "*"), dirs);
- d.contents.append(dirs);
-
- if (recurse) {
- // Look for subdirectories
- static const std::string subdirs[] =
- {"font", "gui", "SuperShader", "cubemap", "icon", "material", "image", "md2", "md3", "ifs", "3ds", "sky", ""};
-
- for (int j = 0; j < dirs.size(); ++j) {
- for (int i = 0; ! subdirs[i].empty(); ++i) {
- if (dirs[j] == subdirs[i]) {
- maybeAddDirectory(pathConcat(newPath, dirs[j]), directoryArray, false);
- }
- }
- }
- }
- return true;
- } else {
- return false;
- }
-}
-#endif
-
-std::string System::findDataFile
-(const std::string& full,
- bool errorIfNotFound) {
-
- // Places where specific files were most recently found. This is
- // used to cache seeking of common files.
- static Table<std::string, std::string> lastFound;
-
- // First check if the file exists as requested. This will go
- // through the FileSystemCache, so most calls do not touch disk.
- if (fileExists(full)) {
- return full;
- }
-
- // Now check where we previously found this file.
- std::string* last = lastFound.getPointer(full);
- if (last != NULL) {
- if (fileExists(*last)) {
- // Even if cwd has changed the file is still present.
- // We won't notice if it has been deleted, however.
- return *last;
- } else {
- // Remove this from the cache it is invalid
- lastFound.remove(full);
- }
- }
-
- // Places to look
- static Array<std::string> directoryArray;
-
- if (directoryArray.size() == 0) {
- // Initialize the directory array
- RealTime t0 = System::time();
-
- Array<std::string> baseDirArray;
-
- std::string initialAppDataDir(instance().m_appDataDir);
-
- baseDirArray.append("");
- if (! initialAppDataDir.empty()) {
- baseDirArray.append(initialAppDataDir);
- }
-
- const char* g3dPath = getenv("G3DDATA");
-
- if (g3dPath && (initialAppDataDir != g3dPath)) {
- baseDirArray.append(g3dPath);
- }
-
- static const std::string subdirs[] =
- {"font", "gui", "SuperShader", "cubemap", "icon", "material", "image", "md2", "md3", "ifs", "3ds", "sky", ""};
- for (int j = 0; j < baseDirArray.size(); ++j) {
- std::string d = baseDirArray[j];
- if (fileExists(d)) {
- directoryArray.append(d);
- for (int i = 0; ! subdirs[i].empty(); ++i) {
- const std::string& p = pathConcat(d, subdirs[i]);
- if (fileExists(p)) {
- directoryArray.append(p);
- }
- }
- }
- }
-
- logLazyPrintf("Initializing System::findDataFile took %fs\n", System::time() - t0);
- }
-
- for (int i = 0; i < directoryArray.size(); ++i) {
- const std::string& p = pathConcat(directoryArray[i], full);
- if (fileExists(p)) {
- lastFound.set(full, p);
- return p;
- }
- }
-
- if (errorIfNotFound) {
- // Generate an error message
- std::string locations;
- for (int i = 0; i < directoryArray.size(); ++i) {
- locations += pathConcat(directoryArray[i], full) + "\n";
- }
- alwaysAssertM(false, "Could not find '" + full + "' in:\n" + locations);
- }
-
- // Not found
- return "";
-}
-
-
-void System::setAppDataDir(const std::string& path) {
- instance().m_appDataDir = path;
-}
-
-
-std::string demoFindData(bool errorIfNotFound) {
- static const char* g3dPath = getenv("G3DDATA");
- if (g3dPath) {
- return g3dPath;
-# ifdef G3D_WIN32
- } else if (fileExists("../data")) {
- // G3D install on Windows
- return "../data";
- } else if (fileExists("../data-files")) {
- // G3D source on Windows
- return "../data-files";
-# else
- } else if (fileExists("../../../../data")) {
- // G3D install on Unix
- return "../../../../data";
- } else if (fileExists("../../../../data-files")) {
- // G3D source on Unix
- return "../../../../data-files";
-# endif
- } else {
- return "";
- }
-}
-
-
-const std::string& System::build() {
- const static std::string b =
-# ifdef _DEBUG
- "Debug";
-# else
- "Release";
-# endif
-
- return b;
-}
-
-
-static G3DEndian checkEndian() {
- int32 a = 1;
- if (*(uint8*)&a == 1) {
- return G3D_LITTLE_ENDIAN;
- } else {
- return G3D_BIG_ENDIAN;
- }
-}
-
-
-static bool checkForCPUID() {
- // all known supported architectures have cpuid
- // add cases for incompatible architectures if they are added
- // e.g., if we ever support __powerpc__ being defined again
-
- return true;
-}
-
-
-void System::getStandardProcessorExtensions() {
-#if ! defined(G3D_OSX) || defined(G3D_OSX_INTEL)
- if (! m_hasCPUID) {
- return;
- }
-
- uint32 eaxreg = 0, ebxreg = 0, ecxreg = 0, features = 0;
-
- cpuid(CPUID_PROCESSOR_FEATURES, eaxreg, ebxreg, ecxreg, features);
-
-# define checkBit(var, bit) ((var & (1 << bit)) ? true : false)
-
- m_hasRDTSC = checkBit(features, 4);
- m_hasMMX = checkBit(features, 23);
- m_hasSSE = checkBit(features, 25);
- m_hasSSE2 = checkBit(features, 26);
- // Bit 28 is HTT; not checked by G3D
-
- m_hasSSE3 = checkBit(ecxreg, 0);
-
- if (m_highestCPUIDFunction >= CPUID_EXTENDED_FEATURES) {
- cpuid(CPUID_EXTENDED_FEATURES, eaxreg, ebxreg, ecxreg, features);
- m_hasAMDMMX = checkBit(features, 22); // Only on AMD
- m_has3DNOW = checkBit(features, 31); // Only on AMD
- m_has3DNOW2 = checkBit(features, 30); // Only on AMD
- } else {
- m_hasAMDMMX = false;
- m_has3DNOW = false;
- m_has3DNOW2 = false;
- }
-
-# undef checkBit
-#endif
-}
-
-#if defined(G3D_WIN32) && !defined(G3D_64BIT)
- #pragma message("Port System::memcpy SIMD to all platforms")
-/** Michael Herf's fast memcpy */
-void memcpyMMX(void* dst, const void* src, int nbytes) {
- int remainingBytes = nbytes;
-
- if (nbytes > 64) {
- _asm {
- mov esi, src
- mov edi, dst
- mov ecx, nbytes
- shr ecx, 6 // 64 bytes per iteration
-
- loop1:
- movq mm1, 0[ESI] // Read in source data
- movq mm2, 8[ESI]
- movq mm3, 16[ESI]
- movq mm4, 24[ESI]
- movq mm5, 32[ESI]
- movq mm6, 40[ESI]
- movq mm7, 48[ESI]
- movq mm0, 56[ESI]
-
- movntq 0[EDI], mm1 // Non-temporal stores
- movntq 8[EDI], mm2
- movntq 16[EDI], mm3
- movntq 24[EDI], mm4
- movntq 32[EDI], mm5
- movntq 40[EDI], mm6
- movntq 48[EDI], mm7
- movntq 56[EDI], mm0
-
- add esi, 64
- add edi, 64
- dec ecx
- jnz loop1
-
- emms
- }
- remainingBytes -= ((nbytes >> 6) << 6);
- }
-
- if (remainingBytes > 0) {
- // Memcpy the rest
- memcpy((uint8*)dst + (nbytes - remainingBytes),
- (const uint8*)src + (nbytes - remainingBytes), remainingBytes);
- }
-}
-#endif
-
-void System::memcpy(void* dst, const void* src, size_t numBytes) {
-#if defined(G3D_WIN32) && !defined(G3D_64BIT)
- memcpyMMX(dst, src, numBytes);
-#else
- ::memcpy(dst, src, numBytes);
-#endif
-}
-
-
-/** Michael Herf's fastest memset. n32 must be filled with the same
- character repeated. */
-#if defined(G3D_WIN32) && !defined(G3D_64BIT)
- #pragma message("Port System::memfill SIMD to all platforms")
-
-// On x86 processors, use MMX
-void memfill(void *dst, int n32, unsigned long i) {
-
- int originalSize = i;
- int bytesRemaining = i;
-
- if (i > 16) {
-
- bytesRemaining = i % 16;
- i -= bytesRemaining;
- __asm {
- movq mm0, n32
- punpckldq mm0, mm0
- mov edi, dst
-
- loopwrite:
-
- movntq 0[edi], mm0
- movntq 8[edi], mm0
-
- add edi, 16
- sub i, 16
- jg loopwrite
-
- emms
- }
- }
-
- if (bytesRemaining > 0) {
- ::memset((uint8*)dst + (originalSize - bytesRemaining), n32, bytesRemaining);
- }
-}
-#endif
-
-
-void System::memset(void* dst, uint8 value, size_t numBytes) {
-#if defined(G3D_WIN32) && !defined(G3D_64BIT)
- uint32 v = value;
- v = v + (v << 8) + (v << 16) + (v << 24);
- G3D::memfill(dst, v, numBytes);
-#else
- ::memset(dst, value, numBytes);
-#endif
-}
-
-
-/** Removes the 'd' that icompile / Morgan's VC convention appends. */
-static std::string computeAppName(const std::string& start) {
- if (start.size() < 2) {
- return start;
- }
-
- if (start[start.size() - 1] == 'd') {
- // Maybe remove the 'd'; see if ../ or ../../ has the same name
- char tmp[1024];
- getcwd(tmp, sizeof(tmp));
- std::string drive, base, ext;
- Array<std::string> path;
- parseFilename(tmp, drive, path, base, ext);
-
- std::string shortName = start.substr(0, start.size() - 1);
-
- if ((path.size() > 1) && (toLower(path.last()) == toLower(shortName))) {
- return shortName;
- }
-
- if ((path.size() > 2) && (toLower(path[path.size() - 2]) == toLower(shortName))) {
- return shortName;
- }
- }
-
- return start;
-}
-
-
-std::string& System::appName() {
- static std::string n = computeAppName(filenameBase(currentProgramFilename()));
- return n;
-}
-
-
-std::string System::currentProgramFilename() {
- char filename[2048];
-
-# ifdef G3D_WIN32
- {
- GetModuleFileNameA(NULL, filename, sizeof(filename));
- }
-# elif defined(G3D_OSX)
- {
- // Run the 'ps' program to extract the program name
- // from the process ID.
- int pid;
- FILE* fd;
- char cmd[80];
- pid = getpid();
- sprintf(cmd, "ps -p %d -o comm=\"\"", pid);
-
- fd = popen(cmd, "r");
- int s = fread(filename, 1, sizeof(filename), fd);
- // filename will contain a newline. Overwrite it:
- filename[s - 1] = '\0';
- }
-# else
- {
- int ret = readlink("/proc/self/exe", filename, sizeof(filename));
-
- // In case of an error, leave the handling up to the caller
- if (ret == -1) {
- return "";
- }
-
- debugAssert((int)sizeof(filename) > ret);
-
- // Ensure proper NULL termination
- filename[ret] = 0;
- }
- #endif
-
- return filename;
-}
-
-
-void System::sleep(RealTime t) {
-
- // Overhead of calling this function, measured from a previous run.
- static const RealTime OVERHEAD = 0.00006f;
-
- RealTime now = time();
- RealTime wakeupTime = now + t - OVERHEAD;
-
- RealTime remainingTime = wakeupTime - now;
- RealTime sleepTime = 0;
-
- // On Windows, a "time slice" is measured in quanta of 3-5 ms (http://support.microsoft.com/kb/259025)
- // Sleep(0) yields the remainder of the time slice, which could be a long time.
- // A 1 ms minimum time experimentally kept the "Empty GApp" at nearly no CPU load at 100 fps,
- // yet nailed the frame timing perfectly.
- static RealTime minRealSleepTime = 3 * units::milliseconds();
-
- while (remainingTime > 0) {
-
- if (remainingTime > minRealSleepTime * 2.5) {
- // Safe to use Sleep with a time... sleep for half the remaining time
- sleepTime = max(remainingTime * 0.5, 0.0005);
- } else if (remainingTime > minRealSleepTime) {
- // Safe to use Sleep with a zero time;
- // causes the program to yield only
- // the current time slice, and then return.
- sleepTime = 0;
- } else {
- // Not safe to use Sleep; busy wait
- sleepTime = -1;
- }
-
- if (sleepTime >= 0) {
- #ifdef G3D_WIN32
- // Translate to milliseconds
- Sleep((int)(sleepTime * 1e3));
- #else
- // Translate to microseconds
- usleep((int)(sleepTime * 1e6));
- #endif
- }
-
- now = time();
- remainingTime = wakeupTime - now;
- }
-}
-
-
-void System::consoleClearScreen() {
-# ifdef G3D_WIN32
- system("cls");
-# else
- system("clear");
-# endif
-}
-
-
-bool System::consoleKeyPressed() {
- #ifdef G3D_WIN32
-
- return _kbhit() != 0;
-
- #else
-
- static const int STDIN = 0;
- static bool initialized = false;
-
- if (! initialized) {
- // Use termios to turn off line buffering
- termios term;
- tcgetattr(STDIN, &term);
- term.c_lflag &= ~ICANON;
- tcsetattr(STDIN, TCSANOW, &term);
- setbuf(stdin, NULL);
- initialized = true;
- }
-
- #ifdef G3D_LINUX
-
- int bytesWaiting;
- ioctl(STDIN, FIONREAD, &bytesWaiting);
- return bytesWaiting;
-
- #else
-
- timeval timeout;
- fd_set rdset;
-
- FD_ZERO(&rdset);
- FD_SET(STDIN, &rdset);
- timeout.tv_sec = 0;
- timeout.tv_usec = 0;
-
- return select(STDIN + 1, &rdset, NULL, NULL, &timeout);
- #endif
- #endif
-}
-
-
-int System::consoleReadKey() {
-# ifdef G3D_WIN32
- return _getch();
-# else
- char c;
- read(0, &c, 1);
- return c;
-# endif
-}
-
-
-void System::initTime() {
- #ifdef G3D_WIN32
- if (QueryPerformanceFrequency(&m_counterFrequency)) {
- QueryPerformanceCounter(&m_start);
- }
-
- struct _timeb t;
- _ftime(&t);
-
- m_realWorldGetTickTime0 = (RealTime)t.time - t.timezone * G3D::MINUTE + (t.dstflag ? G3D::HOUR : 0);
-
- #else
- gettimeofday(&m_start, NULL);
- // "sse" = "seconds since epoch". The time
- // function returns the seconds since the epoch
- // GMT (perhaps more correctly called UTC).
- time_t gmt = ::time(NULL);
-
- // No call to free or delete is needed, but subsequent
- // calls to asctime, ctime, mktime, etc. might overwrite
- // local_time_vals.
- tm* localTimeVals = localtime(&gmt);
-
- time_t local = gmt;
-
- if (localTimeVals) {
- // tm_gmtoff is already corrected for daylight savings.
- local = local + localTimeVals->tm_gmtoff;
- }
-
- m_realWorldGetTickTime0 = local;
- #endif
-}
-
-
-RealTime System::time() {
-# ifdef G3D_WIN32
- LARGE_INTEGER now;
- QueryPerformanceCounter(&now);
-
- return ((RealTime)(now.QuadPart - instance().m_start.QuadPart) /
- instance().m_counterFrequency.QuadPart) + instance().m_realWorldGetTickTime0;
-# else
- // Linux resolution defaults to 100Hz.
- // There is no need to do a separate RDTSC call as gettimeofday
- // actually uses RDTSC when on systems that support it, otherwise
- // it uses the system clock.
- struct timeval now;
- gettimeofday(&now, NULL);
-
- return (now.tv_sec - instance().m_start.tv_sec) +
- (now.tv_usec - instance().m_start.tv_usec) / 1e6
- + instance().m_realWorldGetTickTime0;
-# endif
-}
-
-
-////////////////////////////////////////////////////////////////
-
-#define REALPTR_TO_USERPTR(x) ((uint8*)(x) + sizeof (void *))
-#define USERPTR_TO_REALPTR(x) ((uint8*)(x) - sizeof (void *))
-#define REALBLOCK_SIZE(x) ((x) + sizeof (void *))
-
-class BufferPool {
-public:
-
- /** Only store buffers up to these sizes (in bytes) in each pool->
- Different pools have different management strategies.
-
- A large block is preallocated for tiny buffers; they are used with
- tremendous frequency. Other buffers are allocated as demanded.
- Tiny buffers are 128 bytes long because that seems to align well with
- cache sizes on many machines.
- */
- enum {tinyBufferSize = 128, smallBufferSize = 1024, medBufferSize = 4096};
-
- /**
- Most buffers we're allowed to store.
- 250000 * 128 = 32 MB (preallocated)
- 10000 * 1024 = 10 MB (allocated on demand)
- 1024 * 4096 = 4 MB (allocated on demand)
- */
- enum {maxTinyBuffers = 250000, maxSmallBuffers = 10000, maxMedBuffers = 1024};
-
-private:
-
- class MemBlock {
- public:
- void* ptr;
- size_t bytes;
-
- inline MemBlock() : ptr(NULL), bytes(0) {}
- inline MemBlock(void* p, size_t b) : ptr(p), bytes(b) {}
- };
-
- MemBlock smallPool[maxSmallBuffers];
- int smallPoolSize;
-
- MemBlock medPool[maxMedBuffers];
- int medPoolSize;
-
- /** The tiny pool is a single block of storage into which all tiny
- objects are allocated. This provides better locality for
- small objects and avoids the search time, since all tiny
- blocks are exactly the same size. */
- void* tinyPool[maxTinyBuffers];
- int tinyPoolSize;
-
- /** Pointer to the data in the tiny pool */
- void* tinyHeap;
-
- Spinlock m_lock;
-
- void lock() {
- m_lock.lock();
- }
-
- void unlock() {
- m_lock.unlock();
- }
-
-#if 0 //-----------------------------------------------old mutex
-# ifdef G3D_WIN32
- CRITICAL_SECTION mutex;
-# else
- pthread_mutex_t mutex;
-# endif
-
- /** Provide synchronization between threads */
- void lock() {
-# ifdef G3D_WIN32
- EnterCriticalSection(&mutex);
-# else
- pthread_mutex_lock(&mutex);
-# endif
- }
-
- void unlock() {
-# ifdef G3D_WIN32
- LeaveCriticalSection(&mutex);
-# else
- pthread_mutex_unlock(&mutex);
-# endif
- }
-#endif //-------------------------------------------old mutex
-
- /**
- Malloc out of the tiny heap. Returns NULL if allocation failed.
- */
- inline void* tinyMalloc(size_t bytes) {
- // Note that we ignore the actual byte size
- // and create a constant size block.
- (void)bytes;
- assert(tinyBufferSize >= bytes);
-
- void* ptr = NULL;
-
- if (tinyPoolSize > 0) {
- --tinyPoolSize;
-
- // Return the old last pointer from the freelist
- ptr = tinyPool[tinyPoolSize];
-
-# ifdef G3D_DEBUG
- if (tinyPoolSize > 0) {
- assert(tinyPool[tinyPoolSize - 1] != ptr);
- // "System::malloc heap corruption detected: "
- // "the last two pointers on the freelist are identical (during tinyMalloc).");
- }
-# endif
-
- // NULL out the entry to help detect corruption
- tinyPool[tinyPoolSize] = NULL;
- }
-
- return ptr;
- }
-
- /** Returns true if this is a pointer into the tiny heap. */
- bool inTinyHeap(void* ptr) {
- return
- (ptr >= tinyHeap) &&
- (ptr < (uint8*)tinyHeap + maxTinyBuffers * tinyBufferSize);
- }
-
- void tinyFree(void* ptr) {
- assert(ptr);
- assert(tinyPoolSize < maxTinyBuffers);
- // "Tried to free a tiny pool buffer when the tiny pool freelist is full.");
-
-# ifdef G3D_DEBUG
- if (tinyPoolSize > 0) {
- void* prevOnHeap = tinyPool[tinyPoolSize - 1];
- assert(prevOnHeap != ptr);
-// "System::malloc heap corruption detected: "
-// "the last two pointers on the freelist are identical (during tinyFree).");
- }
-# endif
-
- assert(tinyPool[tinyPoolSize] == NULL);
-
- // Put the pointer back into the free list
- tinyPool[tinyPoolSize] = ptr;
- ++tinyPoolSize;
-
- }
-
- void flushPool(MemBlock* pool, int& poolSize) {
- for (int i = 0; i < poolSize; ++i) {
- ::free(pool[i].ptr);
- pool[i].ptr = NULL;
- pool[i].bytes = 0;
- }
- poolSize = 0;
- }
-
-
- /** Allocate out of a specific pool-> Return NULL if no suitable
- memory was found.
-
- */
- void* malloc(MemBlock* pool, int& poolSize, size_t bytes) {
-
- // OPT: find the smallest block that satisfies the request.
-
- // See if there's something we can use in the buffer pool->
- // Search backwards since usually we'll re-use the last one.
- for (int i = (int)poolSize - 1; i >= 0; --i) {
- if (pool[i].bytes >= bytes) {
- // We found a suitable entry in the pool->
-
- // No need to offset the pointer; it is already offset
- void* ptr = pool[i].ptr;
-
- // Remove this element from the pool
- --poolSize;
- pool[i] = pool[poolSize];
-
- return ptr;
- }
- }
-
- return NULL;
- }
-
-public:
-
- /** Count of memory allocations that have occurred. */
- int totalMallocs;
- int mallocsFromTinyPool;
- int mallocsFromSmallPool;
- int mallocsFromMedPool;
-
- /** Amount of memory currently allocated (according to the application).
- This does not count the memory still remaining in the buffer pool,
- but does count extra memory required for rounding off to the size
- of a buffer.
- Primarily useful for detecting leaks.*/
- // TODO: make me an atomic int!
- volatile int bytesAllocated;
-
- BufferPool() {
- totalMallocs = 0;
-
- mallocsFromTinyPool = 0;
- mallocsFromSmallPool = 0;
- mallocsFromMedPool = 0;
-
- bytesAllocated = true;
-
- tinyPoolSize = 0;
- tinyHeap = NULL;
-
- smallPoolSize = 0;
-
- medPoolSize = 0;
-
-
- // Initialize the tiny heap as a bunch of pointers into one
- // pre-allocated buffer.
- tinyHeap = ::malloc(maxTinyBuffers * tinyBufferSize);
- for (int i = 0; i < maxTinyBuffers; ++i) {
- tinyPool[i] = (uint8*)tinyHeap + (tinyBufferSize * i);
- }
- tinyPoolSize = maxTinyBuffers;
-
-#if 0 ///---------------------------------- old mutex
-# ifdef G3D_WIN32
- InitializeCriticalSection(&mutex);
-# else
- pthread_mutex_init(&mutex, NULL);
-# endif
-#endif ///---------------------------------- old mutex
- }
-
-
- ~BufferPool() {
- ::free(tinyHeap);
-#if 0 //-------------------------------- old mutex
-# ifdef G3D_WIN32
- DeleteCriticalSection(&mutex);
-# else
- // No destruction on pthreads
-# endif
-#endif //--------------------------------old mutex
- }
-
-
- void* realloc(void* ptr, size_t bytes) {
- if (ptr == NULL) {
- return malloc(bytes);
- }
-
- if (inTinyHeap(ptr)) {
- if (bytes <= tinyBufferSize) {
- // The old pointer actually had enough space.
- return ptr;
- } else {
- // Free the old pointer and malloc
-
- void* newPtr = malloc(bytes);
- System::memcpy(newPtr, ptr, tinyBufferSize);
- tinyFree(ptr);
- return newPtr;
-
- }
- } else {
- // In one of our heaps.
-
- // See how big the block really was
- size_t realSize = *(uint32*)USERPTR_TO_REALPTR(ptr);
- if (bytes <= realSize) {
- // The old block was big enough.
- return ptr;
- }
-
- // Need to reallocate
- void* newPtr = malloc(bytes);
- System::memcpy(newPtr, ptr, realSize);
- free(ptr);
- return newPtr;
- }
- }
-
-
- void* malloc(size_t bytes) {
- lock();
- ++totalMallocs;
-
- if (bytes <= tinyBufferSize) {
-
- void* ptr = tinyMalloc(bytes);
-
- if (ptr) {
- ++mallocsFromTinyPool;
- unlock();
- return ptr;
- }
-
- }
-
- // Failure to allocate a tiny buffer is allowed to flow
- // through to a small buffer
- if (bytes <= smallBufferSize) {
-
- void* ptr = malloc(smallPool, smallPoolSize, bytes);
-
- if (ptr) {
- ++mallocsFromSmallPool;
- unlock();
- return ptr;
- }
-
- } else if (bytes <= medBufferSize) {
- // Note that a small allocation failure does *not* fall
- // through into a medium allocation because that would
- // waste the medium buffer's resources.
-
- void* ptr = malloc(medPool, medPoolSize, bytes);
-
- if (ptr) {
- ++mallocsFromMedPool;
- unlock();
- debugAssertM(ptr != NULL, "BufferPool::malloc returned NULL");
- return ptr;
- }
- }
-
- bytesAllocated += REALBLOCK_SIZE(bytes);
- unlock();
-
- // Heap allocate
-
- // Allocate 4 extra bytes for our size header (unfortunate,
- // since malloc already added its own header).
- void* ptr = ::malloc(REALBLOCK_SIZE(bytes));
-
- if (ptr == NULL) {
- // Flush memory pools to try and recover space
- flushPool(smallPool, smallPoolSize);
- flushPool(medPool, medPoolSize);
- ptr = ::malloc(REALBLOCK_SIZE(bytes));
- }
-
- if (ptr == NULL) {
- if ((System::outOfMemoryCallback() != NULL) &&
- (System::outOfMemoryCallback()(REALBLOCK_SIZE(bytes), true) == true)) {
- // Re-attempt the malloc
- ptr = ::malloc(REALBLOCK_SIZE(bytes));
- }
- }
-
- if (ptr == NULL) {
- if (System::outOfMemoryCallback() != NULL) {
- // Notify the application
- System::outOfMemoryCallback()(REALBLOCK_SIZE(bytes), false);
- }
-# ifdef G3D_DEBUG
- debugPrintf("::malloc(%d) returned NULL\n", (int)REALBLOCK_SIZE(bytes));
-# endif
- debugAssertM(ptr != NULL,
- "::malloc returned NULL. Either the "
- "operating system is out of memory or the "
- "heap is corrupt.");
- return NULL;
- }
-
- *(uint32*)ptr = bytes;
-
- return REALPTR_TO_USERPTR(ptr);
- }
-
-
- void free(void* ptr) {
- if (ptr == NULL) {
- // Free does nothing on null pointers
- return;
- }
-
- assert(isValidPointer(ptr));
-
- if (inTinyHeap(ptr)) {
- lock();
- tinyFree(ptr);
- unlock();
- return;
- }
-
- uint32 bytes = *(uint32*)USERPTR_TO_REALPTR(ptr);
-
- lock();
- if (bytes <= smallBufferSize) {
- if (smallPoolSize < maxSmallBuffers) {
- smallPool[smallPoolSize] = MemBlock(ptr, bytes);
- ++smallPoolSize;
- unlock();
- return;
- }
- } else if (bytes <= medBufferSize) {
- if (medPoolSize < maxMedBuffers) {
- medPool[medPoolSize] = MemBlock(ptr, bytes);
- ++medPoolSize;
- unlock();
- return;
- }
- }
- bytesAllocated -= REALBLOCK_SIZE(bytes);
- unlock();
-
- // Free; the buffer pools are full or this is too big to store.
- ::free(USERPTR_TO_REALPTR(ptr));
- }
-
- std::string performance() const {
- if (totalMallocs > 0) {
- int pooled = mallocsFromTinyPool +
- mallocsFromSmallPool +
- mallocsFromMedPool;
-
- int total = totalMallocs;
-
- return format("malloc performance: %5.1f%% <= %db, %5.1f%% <= %db, "
- "%5.1f%% <= %db, %5.1f%% > %db",
- 100.0 * mallocsFromTinyPool / total,
- BufferPool::tinyBufferSize,
- 100.0 * mallocsFromSmallPool / total,
- BufferPool::smallBufferSize,
- 100.0 * mallocsFromMedPool / total,
- BufferPool::medBufferSize,
- 100.0 * (1.0 - (double)pooled / total),
- BufferPool::medBufferSize);
- } else {
- return "No System::malloc calls made yet.";
- }
- }
-
- std::string status() const {
- return format("preallocated shared buffers: %5d/%d x %db",
- maxTinyBuffers - tinyPoolSize, maxTinyBuffers, tinyBufferSize);
- }
-};
-
-// Dynamically allocated because we need to ensure that
-// the buffer pool is still around when the last global variable
-// is deallocated.
-static BufferPool* bufferpool = NULL;
-
-std::string System::mallocPerformance() {
-#ifndef NO_BUFFERPOOL
- return bufferpool->performance();
-#else
- return "NO_BUFFERPOOL";
-#endif
-}
-
-std::string System::mallocStatus() {
-#ifndef NO_BUFFERPOOL
- return bufferpool->status();
-#else
- return "NO_BUFFERPOOL";
-#endif
-}
-
-
-void System::resetMallocPerformanceCounters() {
-#ifndef NO_BUFFERPOOL
- bufferpool->totalMallocs = 0;
- bufferpool->mallocsFromMedPool = 0;
- bufferpool->mallocsFromSmallPool = 0;
- bufferpool->mallocsFromTinyPool = 0;
-#endif
-}
-
-
-#ifndef NO_BUFFERPOOL
-inline void initMem() {
- // Putting the test here ensures that the system is always
- // initialized, even when globals are being allocated.
- static bool initialized = false;
- if (! initialized) {
- bufferpool = new BufferPool();
- initialized = true;
- }
-}
-#endif
-
-
-void* System::malloc(size_t bytes) {
-#ifndef NO_BUFFERPOOL
- initMem();
- return bufferpool->malloc(bytes);
-#else
- return ::malloc(bytes);
-#endif
-}
-
-void* System::calloc(size_t n, size_t x) {
-#ifndef NO_BUFFERPOOL
- void* b = System::malloc(n * x);
- debugAssertM(b != NULL, "System::malloc returned NULL");
- debugAssertM(isValidHeapPointer(b), "System::malloc returned an invalid pointer");
- System::memset(b, 0, n * x);
- return b;
-#else
- return ::calloc(n, x);
-#endif
-}
-
-
-void* System::realloc(void* block, size_t bytes) {
-#ifndef NO_BUFFERPOOL
- initMem();
- return bufferpool->realloc(block, bytes);
-#else
- return ::realloc(block, bytes);
-#endif
-}
-
-
-void System::free(void* p) {
-#ifndef NO_BUFFERPOOL
- bufferpool->free(p);
-#else
- return ::free(p);
-#endif
-}
-
-
-void* System::alignedMalloc(size_t bytes, size_t alignment) {
-
- alwaysAssertM(isPow2(alignment), "alignment must be a power of 2");
-
- // We must align to at least a word boundary.
- alignment = iMax(alignment, sizeof(void *));
-
- // Pad the allocation size with the alignment size and the
- // size of the redirect pointer.
- size_t totalBytes = bytes + alignment + sizeof(void*);
-
- size_t truePtr = (size_t)System::malloc(totalBytes);
-
- if (truePtr == 0) {
- // malloc returned NULL
- return NULL;
- }
-
- debugAssert(isValidHeapPointer((void*)truePtr));
- #ifdef G3D_WIN32
- // The blocks we return will not be valid Win32 debug heap
- // pointers because they are offset
- // debugAssert(_CrtIsValidPointer((void*)truePtr, totalBytes, TRUE) );
- #endif
-
- // The return pointer will be the next aligned location (we must at least
- // leave space for the redirect pointer, however).
- size_t alignedPtr = truePtr + sizeof(void*);
-
- // 2^n - 1 has the form 1111... in binary.
- uint32 bitMask = (alignment - 1);
-
- // Advance forward until we reach an aligned location.
- while ((alignedPtr & bitMask) != 0) {
- alignedPtr += sizeof(void*);
- }
-
- debugAssert(alignedPtr - truePtr + bytes <= totalBytes);
-
- // Immediately before the aligned location, write the true array location
- // so that we can free it correctly.
- size_t* redirectPtr = (size_t *)(alignedPtr - sizeof(void *));
- redirectPtr[0] = truePtr;
-
- debugAssert(isValidHeapPointer((void*)truePtr));
-
- #ifdef G3D_WIN32
- debugAssert( _CrtIsValidPointer((void*)alignedPtr, bytes, TRUE) );
- #endif
- return (void *)alignedPtr;
-}
-
-
-void System::alignedFree(void* _ptr) {
- if (_ptr == NULL) {
- return;
- }
-
- size_t alignedPtr = (size_t)_ptr;
-
- // Back up one word from the pointer the user passed in.
- // We now have a pointer to a pointer to the true start
- // of the memory block.
- size_t* redirectPtr = (size_t*)(alignedPtr - sizeof(void *));
-
- // Dereference that pointer so that ptr = true start
- void* truePtr = (void*)redirectPtr[0];
-
- debugAssert(isValidHeapPointer((void*)truePtr));
- System::free(truePtr);
-}
-
-
-void System::setEnv(const std::string& name, const std::string& value) {
- std::string cmd = name + "=" + value;
-# ifdef G3D_WIN32
- _putenv(cmd.c_str());
-# else
- // Many linux implementations of putenv expect char*
- putenv(const_cast<char*>(cmd.c_str()));
-# endif
-}
-
-
-const char* System::getEnv(const std::string& name) {
- return getenv(name.c_str());
-}
-
-
-static void var(TextOutput& t, const std::string& name, const std::string& val) {
- t.writeSymbols(name,"=");
- t.writeString(val);
- t.writeNewline();
-}
-
-
-static void var(TextOutput& t, const std::string& name, const bool val) {
- t.writeSymbols(name, "=", val ? "Yes" : "No");
- t.writeNewline();
-}
-
-
-static void var(TextOutput& t, const std::string& name, const int val) {
- t.writeSymbols(name,"=");
- t.writeNumber(val);
- t.writeNewline();
-}
-
-
-void System::describeSystem(
- std::string& s) {
-
- TextOutput t;
- describeSystem(t);
- t.commitString(s);
-}
-
-void System::describeSystem(
- TextOutput& t) {
-
- t.writeSymbols("App", "{");
- t.writeNewline();
- t.pushIndent();
- {
- var(t, "Name", System::currentProgramFilename());
- char cwd[1024];
- getcwd(cwd, 1024);
- var(t, "cwd", std::string(cwd));
- }
- t.popIndent();
- t.writeSymbols("}");
- t.writeNewline();
- t.writeNewline();
-
- t.writeSymbols("OS", "{");
- t.writeNewline();
- t.pushIndent();
- {
- var(t, "Name", System::operatingSystem());
- }
- t.popIndent();
- t.writeSymbols("}");
- t.writeNewline();
- t.writeNewline();
-
- t.writeSymbols("CPU", "{");
- t.writeNewline();
- t.pushIndent();
- {
- var(t, "Vendor", System::cpuVendor());
- var(t, "Architecture", System::cpuArchitecture());
- var(t, "hasCPUID", System::hasCPUID());
- var(t, "hasMMX", System::hasMMX());
- var(t, "hasSSE", System::hasSSE());
- var(t, "hasSSE2", System::hasSSE2());
- var(t, "hasSSE3", System::hasSSE3());
- var(t, "has3DNow", System::has3DNow());
- var(t, "hasRDTSC", System::hasRDTSC());
- var(t, "numCores", System::numCores());
- }
- t.popIndent();
- t.writeSymbols("}");
- t.writeNewline();
- t.writeNewline();
-
- t.writeSymbols("G3D", "{");
- t.writeNewline();
- t.pushIndent();
- {
- var(t, "Link version", G3D_VER);
- var(t, "Compile version", System::version());
- }
- t.popIndent();
- t.writeSymbols("}");
- t.writeNewline();
- t.writeNewline();
-}
-
-
-void System::setClipboardText(const std::string& s) {
-# ifdef G3D_WIN32
- if (OpenClipboard(NULL)) {
- HGLOBAL hMem = GlobalAlloc(GHND | GMEM_DDESHARE, s.size() + 1);
- if (hMem) {
- char *pMem = (char*)GlobalLock(hMem);
- strcpy(pMem, s.c_str());
- GlobalUnlock(hMem);
-
- EmptyClipboard();
- SetClipboardData(CF_TEXT, hMem);
- }
-
- CloseClipboard();
- GlobalFree(hMem);
- }
-# endif
-}
-
-
-std::string System::getClipboardText() {
- std::string s;
-
-# ifdef G3D_WIN32
- if (OpenClipboard(NULL)) {
- HANDLE h = GetClipboardData(CF_TEXT);
-
- if (h) {
- char* temp = (char*)GlobalLock(h);
- if (temp) {
- s = temp;
- }
- temp = NULL;
- GlobalUnlock(h);
- }
- CloseClipboard();
- }
-# endif
- return s;
-}
-
-
-std::string System::currentDateString() {
- time_t t1;
- ::time(&t1);
- tm* t = localtime(&t1);
- return format("%d-%02d-%02d", t->tm_year + 1900, t->tm_mon + 1, t->tm_mday);
-}
-
-#ifdef _MSC_VER
-
-// VC on Intel
-void System::cpuid(CPUIDFunction func, uint32& areg, uint32& breg, uint32& creg, uint32& dreg) {
-#if !defined(G3D_64BIT)
- // Can't copy from assembler direct to a function argument (which is on the stack) in VC.
- uint32 a,b,c,d;
-
- // Intel assembler syntax
- __asm {
- mov eax, func // eax <- func
- mov ecx, 0
- cpuid
- mov a, eax
- mov b, ebx
- mov c, ecx
- mov d, edx
- }
- areg = a;
- breg = b;
- creg = c;
- dreg = d;
-#else
- int CPUInfo[4];
- __cpuid(CPUInfo, func);
- memcpy(&areg, &CPUInfo[0], 4);
- memcpy(&breg, &CPUInfo[1], 4);
- memcpy(&creg, &CPUInfo[2], 4);
- memcpy(&dreg, &CPUInfo[3], 4);
-#endif
-}
-
-#elif defined(G3D_OSX) && ! defined(G3D_OSX_INTEL)
-
-// non-intel OS X; no CPUID
-void System::cpuid(CPUIDFunction func, uint32& eax, uint32& ebx, uint32& ecx, uint32& edx) {
- eax = 0;
- ebx = 0;
- ecx = 0;
- edx = 0;
-}
-
-#else
-
-// See http://sam.zoy.org/blog/2007-04-13-shlib-with-non-pic-code-have-inline-assembly-and-pic-mix-well
-// for a discussion of why the second version saves ebx; it allows 32-bit code to compile with the -fPIC option.
-// On 64-bit x86, PIC code has a dedicated rip register for PIC so there is no ebx conflict.
-void System::cpuid(CPUIDFunction func, uint32& eax, uint32& ebx, uint32& ecx, uint32& edx) {
-#if ! defined(__PIC__) || defined(__x86_64__)
- // AT&T assembler syntax
- asm volatile(
- "movl $0, %%ecx \n\n" /* Wipe ecx */
- "cpuid \n\t"
- : "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx)
- : "a"(func));
-#else
- // AT&T assembler syntax
- asm volatile(
- "pushl %%ebx \n\t" /* save ebx */
- "movl $0, %%ecx \n\n" /* Wipe ecx */
- "cpuid \n\t"
- "movl %%ebx, %1 \n\t" /* save what cpuid just put in %ebx */
- "popl %%ebx \n\t" /* restore the old ebx */
- : "=a"(eax), "=r"(ebx), "=c"(ecx), "=d"(edx)
- : "a"(func));
-#endif
-}
-
-#endif
-
-} // namespace
diff --git a/externals/g3dlite/TextInput.cpp b/externals/g3dlite/TextInput.cpp
deleted file mode 100644
index 7276d8c66b2..00000000000
--- a/externals/g3dlite/TextInput.cpp
+++ /dev/null
@@ -1,1136 +0,0 @@
-/**
- @file TextInput.cpp
-
- @author Morgan McGuire, graphics3d.com
-
- @cite Based on a lexer written by Aaron Orenstein.
-
- @created 2001-11-27
- @edited 2008-07-14
- */
-
-#include "G3D/fileutils.h"
-#include "G3D/TextInput.h"
-#include "G3D/BinaryInput.h"
-#include "G3D/stringutils.h"
-
-#ifdef _MSC_VER
-# pragma warning (push)
-// conversion from 'int' to 'char', possible loss of data (TODO: fix underlying problems)
-# pragma warning (disable: 4244)
-#endif
-
-namespace G3D {
-
-Token TextInput::readSignificant() {
- Token t;
- do {
- t = read();
- } while ((t.type() == Token::COMMENT) || (t.type() == Token::NEWLINE));
- return t;
-}
-
-
-double Token::number() const {
- if (_type == NUMBER) {
- std::string s = toLower(_string);
- if (s == "-1.#ind00") {
- return nan();
- }
-
- if (s == "1.#inf00") {
- return inf();
- }
-
- if (s == "-1.#inf00") {
- return -inf();
- }
-
- double n;
- if ((_string.length() > 2) &&
- (_string[0] == '0') &&
- (_string[1] == 'x')) {
- // Hex
- uint32 i;
- sscanf(_string.c_str(), "%x", &i);
- n = i;
- } else {
- sscanf(_string.c_str(), "%lg", &n);
- }
- return n;
- } else {
- return 0.0;
- }
-}
-
-
-TextInput::Settings::Settings () :
- cppBlockComments(true),
- cppLineComments(true),
- otherLineComments(true),
- escapeSequencesInStrings(true),
- otherCommentCharacter('\0'),
- otherCommentCharacter2('\0'),
- generateCommentTokens(false),
- generateNewlineTokens(false),
- signedNumbers(true),
- singleQuotedStrings(true),
- singleQuoteCharacter('\''),
- sourceFileName(),
- startingLineNumberOffset(0),
- msvcSpecials(true),
- proofSymbols(false),
- caseSensitive(true)
-{
- trueSymbols.insert("true");
- falseSymbols.insert("false");
-}
-
-
-Token TextInput::peek() {
- if (stack.size() == 0) {
- Token t = nextToken();
- push(t);
- }
-
- return stack.front();
-}
-
-
-int TextInput::peekLineNumber() {
- return peek().line();
-}
-
-
-int TextInput::peekCharacterNumber() {
- return peek().character();
-}
-
-
-Token TextInput::read() {
- if (stack.size() > 0) {
- Token t = stack.front();
- stack.pop_front();
- return t;
- } else {
- return nextToken();
- }
-}
-
-static void toUpper(Set<std::string>& set) {
- Array<std::string> symbols;
- set.getMembers(symbols);
- set.clear();
- for (int i = 0; i < symbols.size(); ++i) {
- set.insert(toUpper(symbols[i]));
- }
-}
-
-void TextInput::init() {
- currentCharOffset = 0;
- charNumber = 1;
- lineNumber = 1 + options.startingLineNumberOffset;
-
- if (! options.caseSensitive) {
- // Convert true and false symbols to all uppercase for fast comparisons
- toUpper(options.trueSymbols);
- toUpper(options.falseSymbols);
- }
-}
-
-
-void TextInput::push(const Token& t) {
- stack.push_front(t);
-}
-
-
-bool TextInput::hasMore() {
- return (peek()._type != Token::END);
-}
-
-
-int TextInput::eatInputChar() {
- // Don't go off the end
- if (currentCharOffset >= buffer.length()) {
- return EOF;
- }
-
- unsigned char c = buffer[currentCharOffset];
- ++currentCharOffset;
-
- // update lineNumber and charNumber to reflect the location of the *next*
- // character which will be read.
-
- // increment line number for \r, \n and \r\n which matches Token::NEWLINE parsing
- if (c == '\r') {
- ++lineNumber;
- charNumber = 1;
-
- // check for \r\n
- if (currentCharOffset < buffer.length()) {
- unsigned char c2 = buffer[currentCharOffset];
- if (c2 == '\n') {
- c = c2;
- ++currentCharOffset;
- }
- }
- } else if (c == '\n') {
- ++lineNumber;
- charNumber = 1;
- } else {
- ++charNumber;
- }
-
- return c;
-}
-
-int TextInput::peekInputChar(int distance) {
- // Don't go off the end
- if ((currentCharOffset + distance) >= buffer.length()) {
- return EOF;
- }
-
- unsigned char c = buffer[currentCharOffset + distance];
- return c;
-}
-
-
-Token TextInput::nextToken() {
- Token t;
-
- t._line = lineNumber;
- t._character = charNumber;
- t._type = Token::END;
- t._extendedType = Token::END_TYPE;
-
- int c = peekInputChar();
- if (c == EOF) {
- return t;
- }
-
- // loop through white space, newlines and comments
- // found before other tokens
- bool whitespaceDone = false;
- while (! whitespaceDone) {
- whitespaceDone = true;
-
- // generate newlines tokens for '\n' and '\r' and '\r\n'
- if (options.generateNewlineTokens && isNewline(c)) {
- t._type = Token::NEWLINE;
- t._extendedType = Token::NEWLINE_TYPE;
- t._string = c;
-
- int c2 = peekInputChar(1);
- if (c == '\r' && c2 == '\n') {
- t._string += c2;
- }
-
- eatInputChar();
- return t;
- } else {
- // Consume whitespace
- while (isWhiteSpace(c)) {
- c = eatAndPeekInputChar();
- }
- }
-
- // update line and character number to include discarded whitespace
- t._line = lineNumber;
- t._character = charNumber;
-
- int c2 = peekInputChar(1);
-
- // parse comments and generate tokens if enabled
- std::string commentString;
-
- // check for line comments first
- bool isLineComment = false;
- if (options.cppLineComments && (c == '/' && c2 == '/')) {
- // set start of line comment and eat markers
- isLineComment = true;
- eatInputChar();
- eatInputChar();
- } else if ( options.otherCommentCharacter &&
- (options.otherCommentCharacter != '\0' && c == options.otherCommentCharacter) ) {
- // set start of line comment and eat markers
- isLineComment = true;
- eatInputChar();
- } else if ( options.otherCommentCharacter &&
- (options.otherCommentCharacter2 != '\0' && c == options.otherCommentCharacter2) ) {
- // set start of line comment and eat markers
- isLineComment = true;
- eatInputChar();
- }
-
- if (isLineComment) {
-
- // consume line comment to newline or EOF
- c = peekInputChar();
- while (! isNewline(c) && c != EOF) {
- // build comment string for token
- commentString += c;
-
- c = eatAndPeekInputChar();
- }
-
- if (options.generateCommentTokens) {
- t._type = Token::COMMENT;
- t._extendedType = Token::LINE_COMMENT_TYPE;
- t._string = commentString;
- return t;
- } else {
- // There is whitespace after the comment (in particular, the
- // newline that terminates the comment). There might also be
- // whitespace at the start of the next line.
- whitespaceDone = false;
- }
-
- } else if (options.cppBlockComments && (c == '/' && c2 == '*')) {
- // consume block comment to end-marker or EOF
-
- // consume both start-comment chars, can't let the trailing one
- // help close the comment.
- eatInputChar();
- eatInputChar();
-
- c = peekInputChar();
- c2 = peekInputChar(1);
- while (! ((c == '*') && (c2 == '/')) && (c != EOF)) {
- commentString += c;
-
- eatInputChar();
- c = c2;
- c2 = peekInputChar(1);
- }
- eatInputChar(); // eat closing '*'
- eatInputChar(); // eat closing '/'
-
- c = peekInputChar();
-
- if (options.generateCommentTokens) {
- t._type = Token::COMMENT;
- t._extendedType = Token::BLOCK_COMMENT_TYPE;
- t._string = commentString;
- return t;
- } else {
- // There is whitespace after the comment (in particular, the
- // newline that terminates the comment). There might also be
- // whitespace at the start of the next line.
- whitespaceDone = false;
- }
- }
-
- } // while (! whitespaceDone)
-
- t._line = lineNumber;
- t._character = charNumber;
-
- // handle EOF
- if (c == EOF) {
- return t;
- }
-
- // Extended ASCII parses as itself, except for EOF
- if (c > 127 && c < 255) {
- t._type = Token::SYMBOL;
- t._extendedType = Token::SYMBOL_TYPE;
- t._string = c;
- c = eatAndPeekInputChar();
- }
-
-
- // Perform appropriate setup for a symbol (including setting up the token
- // string to start with c), eat the input character, and overwrite
- // 'c' with the peeked next input character.
-#define SETUP_SYMBOL(c) \
- { \
- t._type = Token::SYMBOL; \
- t._extendedType = Token::SYMBOL_TYPE; \
- t._string = c; \
- c = eatAndPeekInputChar(); \
- }
-
- switch (c) {
-
- case '@': // Simple symbols -> just themselves.
- case '(':
- case ')':
- case ',':
- case ';':
- case '{':
- case '}':
- case '[':
- case ']':
- case '#':
- case '$':
- case '?':
- case '%':
- SETUP_SYMBOL(c);
- return t;
-
- case '-': // negative number, -, --, -=, or ->
- SETUP_SYMBOL(c);
-
- switch (c) {
- case '>': // ->
- case '-': // --
- case '=': // -=
- t._string += c;
- eatInputChar();
- return t;
- }
-
- if (options.signedNumbers
- && (isDigit(c) || (c == '.' && isDigit(peekInputChar(1))))) {
-
- // Negative number. 'c' is still the first digit, and is
- // the next input char.
-
- goto numLabel;
- }
-
- // plain -
- return t;
-
- case '+': // positive number, +, ++, or +=
- SETUP_SYMBOL(c);
-
- switch (c) {
- case '+': // ++
- case '=': // +=
- t._string += c;
- eatInputChar();
- return t;
- }
-
- if (options.signedNumbers
- && (isDigit(c) || (c == '.' && isDigit(peekInputChar(1))))) {
-
- // Positive number. 'c' is still the first digit, and is
- // the next input char.
-
- goto numLabel;
- }
-
- return t;
-
- case ':': // : or :: or ::> or ::= or := or :>
- SETUP_SYMBOL(c);
-
- if (c == ':') {
- t._string += c;
- eatInputChar();
-
- if (options.proofSymbols) {
- c = peekInputChar(0);
-
- if ((c == '>') || (c == '=')) {
- t._string += c;
- eatInputChar();
- }
- }
- }
- else if (options.proofSymbols && (c == '=' || c == '>')) {
- t._string += c;
- eatInputChar();
- }
- return t;
-
- case '=': // = or == or =>
- SETUP_SYMBOL(c);
-
- if (c == '=') {
- t._string += c;
- eatInputChar();
- return t;
- } else if (options.proofSymbols && (c == '>')) {
- t._string += c;
- eatInputChar();
- return t;
- }
- return t;
-
- case '*': // * or *=
- case '/': // / or /=
- case '!': // ! or !=
- case '~': // ~ or ~=
- case '^': // ^ or ^=
- SETUP_SYMBOL(c);
-
- if (c == '=') {
- t._string += c;
- eatInputChar();
- return t;
- }
- return t;
-
- case '>': // >, >>,or >=
- case '<': // <<, <<, or <= or <- or <:
- case '|': // ||, ||, or |= or |-
- case '&': // &, &&, or &=
- {
- int orig_c = c;
- SETUP_SYMBOL(c);
-
- if ((c == '=') || (orig_c == c)) {
- t._string += c;
- eatInputChar();
- return t;
- } else if (options.proofSymbols) {
- if ((orig_c == '<') && (c == '-')) {
- t._string += c;
- eatInputChar();
- } else if ((orig_c == '|') && (c == '-')) {
- t._string += c;
- eatInputChar();
- } else if ((orig_c == '<') && (c == ':')) {
- t._string += c;
-
- c = eatAndPeekInputChar();
-
- if (c == ':') {
- t._string += c;
- eatInputChar();
- }
- }
- }
- }
- return t;
-
- case '\\': // backslash or escaped comment char.
- SETUP_SYMBOL(c);
-
- if ((options.otherCommentCharacter != '\0'
- && c == options.otherCommentCharacter)
- || (options.otherCommentCharacter2 != '\0'
- && c == options.otherCommentCharacter2)) {
-
- // escaped comment character. Return the raw comment
- // char (no backslash).
-
- t._string = c;
- eatInputChar();
- return t;
- }
- return t;
-
- case '.': // number, ., .., or ...
- if (isDigit(peekInputChar(1))) {
- // We're parsing a float that began without a leading zero
- goto numLabel;
- }
-
- SETUP_SYMBOL(c);
-
- if (c == '.') { // .. or ...
- t._string += c;
- c = eatAndPeekInputChar();
-
- if (c == '.') { // ...
- t._string += c;
- eatInputChar();
- }
- return t;
- }
-
- return t;
-
- } // switch (c)
-
-#undef SETUP_SYMBOL
-
-numLabel:
- if (isDigit(c) || (c == '.')) {
-
- // A number. Note-- single dots have been
- // parsed already, so a . indicates a number
- // less than 1 in floating point form.
-
- // [0-9]*(\.[0-9][f]) or [0-9]+ or 0x[0-9,A-F]+
-
- if (t._string != "-") {
- // If we picked up a leading "-" sign above, keep it,
- // otherwise drop the string parsed thus far
- t._string = "";
- }
- t._type = Token::NUMBER;
- if (c == '.') {
- t._extendedType = Token::FLOATING_POINT_TYPE;
- } else {
- t._extendedType = Token::INTEGER_TYPE;
- }
-
- if ((c == '0') && (peekInputChar(1) == 'x')) {
- // Hex number
- t._string += "0x";
-
- // skip the 0x
- eatInputChar();
- eatInputChar();
-
- c = peekInputChar();
- while (isDigit(c) || ((c >= 'A') && (c <= 'F')) || ((c >= 'a') && (c <= 'f'))) {
- t._string += c;
- c = eatAndPeekInputChar();
- }
-
- } else {
- // Non-hex number
-
- // Read the part before the decimal.
- while (isDigit(c)) {
- t._string += c;
- c = eatAndPeekInputChar();
- }
-
- // True if we are reading a floating-point special type
- bool isSpecial = false;
-
- // Read the decimal, if one exists
- if (c == '.') {
- t._extendedType = Token::FLOATING_POINT_TYPE;
-
- // The '.' character was a decimal point, not the start of a
- // method or range operator
- t._string += c;
- c = eatAndPeekInputChar();
-
- // Floating point specials (msvc format only)
- if (options.msvcSpecials && (c == '#')) {
- isSpecial = true;
- // We are reading a floating point special value
- // of the form -1.#IND00, -1.#INF00, or 1.#INF00
- c = eatAndPeekInputChar();
- char test = c;
- if (! options.caseSensitive) {
- test = toupper(c);
- }
- if (test != 'I') {
- throw BadMSVCSpecial
- (
- "Incorrect floating-point special (inf or nan) "
- "format.",
- t.line(), charNumber);
- }
- c = eatAndPeekInputChar();
- test = c;
- if (! options.caseSensitive) {
- test = toupper(c);
- }
- if (test != 'N') {
- throw BadMSVCSpecial
- (
- "Incorrect floating-point special (inf or nan) "
- "format.",
- t.line(), charNumber);
- }
- t._string += "#IN";
- c = eatAndPeekInputChar();
- test = c;
- if (! options.caseSensitive) {
- test = toupper(c);
- }
- if ((test != 'F') && (test != 'D')) {
- throw BadMSVCSpecial
- (
- "Incorrect floating-point special (inf or nan) "
- "format.",
- t.line(), charNumber);
- }
- t._string += c;
- for (int j = 0; j < 2; ++j) {
- c = eatAndPeekInputChar();
- if (c != '0') {
- throw BadMSVCSpecial
- (
- "Incorrect floating-point special (inf or"
- "nan) format.",
- t.line(), charNumber);
- }
- t._string += (char)c;
- }
-
- } else {
-
- // Read the part after the decimal
- while (isDigit((char)c)) {
- t._string += (char)c;
- c = eatAndPeekInputChar();
- }
- }
- }
-
- if (! isSpecial && ((c == 'e') || (c == 'E'))) {
- // Read exponent
- t._extendedType = Token::FLOATING_POINT_TYPE;
- t._string += c;
-
- c = eatAndPeekInputChar();
- if ((c == '-') || (c == '+')) {
- t._string += c;
- c = eatAndPeekInputChar();
- }
-
- while (isDigit(c)) {
- t._string += c;
- c = eatAndPeekInputChar();
- }
- }
-
- if (! isSpecial && (t._extendedType == Token::FLOATING_POINT_TYPE) && (c == 'f')) {
- // Trailing f on a float
- t._string += c;
- c = eatAndPeekInputChar();
- }
- }
- return t;
-
- } else if (isLetter(c) || (c == '_')) {
- // Identifier or keyword
- // [A-Za-z_][A-Za-z_0-9]*
-
- t._type = Token::SYMBOL;
- t._extendedType = Token::SYMBOL_TYPE;
- t._string = "";
- do {
- t._string += c;
- c = eatAndPeekInputChar();
- } while (isLetter(c) || isDigit(c) || (c == '_'));
-
- // See if this symbol is actually a boolean
- if ((options.trueSymbols.size() > 0) || (options.falseSymbols.size() > 0)) {
- std::string str = t._string;
- if (! options.caseSensitive) {
- str = toUpper(str);
- }
- if (options.trueSymbols.contains(str)) {
- t._type = Token::BOOLEAN;
- t._extendedType = Token::BOOLEAN_TYPE;
- t._bool = true;
- } else if (options.falseSymbols.contains(str)) {
- t._type = Token::BOOLEAN;
- t._extendedType = Token::BOOLEAN_TYPE;
- t._bool = false;
- }
- }
-
- return t;
-
- } else if (c == '\"') {
-
- // Discard the double-quote.
- eatInputChar();
-
- // Double quoted string
- parseQuotedString('\"', t);
- return t;
-
- } else if (c == options.singleQuoteCharacter) {
-
- // Discard the single-quote.
- eatInputChar();
-
- if (options.singleQuotedStrings) {
- // Single quoted string
- parseQuotedString(options.singleQuoteCharacter, t);
- } else {
- t._string = c;
- t._type = Token::SYMBOL;
- t._extendedType = Token::SYMBOL_TYPE;
- }
- return t;
-
- } // end of special case tokens
-
- if (c == EOF) {
- t._type = Token::END;
- t._extendedType = Token::END_TYPE;
- t._string = "";
- return t;
- }
-
- // Some unknown token
- debugAssertM(false,
- format("Unrecognized token type beginning with character '%c' (ASCII %d)",
- c, c));
- return t;
-}
-
-
-void TextInput::parseQuotedString(unsigned char delimiter, Token& t) {
-
- t._type = Token::STRING;
-
- if (delimiter == options.singleQuoteCharacter) {
- t._extendedType = Token::SINGLE_QUOTED_TYPE;
- } else {
- t._extendedType = Token::DOUBLE_QUOTED_TYPE;
- }
-
- while (true) {
- // We're definitely going to consume the next input char, so we get
- // it right now. This makes the condition handling below a bit easier.
- int c = eatInputChar();
-
- if (c == EOF) {
- // END inside a quoted string. (We finish the string.)
- break;
- }
-
- if (options.escapeSequencesInStrings && (c == '\\')) {
- // An escaped character. We're definitely going to consume it,
- // so we get it (and consume it) now.
-
- c = eatInputChar();
-
- switch (c) {
- case 'r':
- t._string += '\r';
- break;
- case 'n':
- t._string += '\n';
- break;
- case 't':
- t._string += '\t';
- break;
- case '0':
- t._string += '\0';
- break;
-
- case '\\':
- case '\"':
- t._string += (char)c;
- break;
-
- default:
- if (c == options.singleQuoteCharacter) {
- t._string += (char)c;
- break;
- }
-
- if (((c == options.otherCommentCharacter) &&
- (options.otherCommentCharacter != '\0')) ||
- ((c == options.otherCommentCharacter2) &&
- (options.otherCommentCharacter2 != '\0'))) {
- t._string += c;
- }
- // otherwise, some illegal escape sequence; skip it.
- break;
-
- } // switch
-
- } else if (c == delimiter) {
- // End of the string. Already consumed the character.
- break;
- } else {
- // All other chars, go on to the string. Already consumed the
- // character.
- t._string += (char)c;
- }
-
- }
-}
-
-bool TextInput::readBoolean() {
- Token t(read());
-
- if (t._type == Token::BOOLEAN) {
- return t.boolean();
- }
-
- // Push initial token back, and throw an error. We intentionally
- // indicate that the wrong type is the type of the initial token.
- // Logically, the number started there.
- push(t);
- throw WrongTokenType(options.sourceFileName, t.line(), t.character(),
- Token::BOOLEAN, t._type);
-}
-
-double TextInput::readNumber() {
- Token t(read());
-
- if (t._type == Token::NUMBER) {
- return t.number();
- }
-
- // Even if signedNumbers is disabled, readNumber attempts to
- // read a signed number, so we handle that case here.
- if (! options.signedNumbers
- && (t._type == Token::SYMBOL)
- && ((t._string == "-")
- || (t._string == "+"))) {
-
- Token t2(read());
-
- if ((t2._type == Token::NUMBER)
- && (t2._character == t._character + 1)) {
-
- if (t._string == "-") {
- return -t2.number();
- } else {
- return t2.number();
- }
- }
-
- // push back the second token.
- push(t2);
- }
-
- // Push initial token back, and throw an error. We intentionally
- // indicate that the wrong type is the type of the initial token.
- // Logically, the number started there.
- push(t);
- throw WrongTokenType(options.sourceFileName, t.line(), t.character(),
- Token::NUMBER, t._type);
-}
-
-
-Token TextInput::readStringToken() {
- Token t(read());
-
- if (t._type == Token::STRING) { // fast path
- return t;
- }
-
- push(t);
- throw WrongTokenType(options.sourceFileName, t.line(), t.character(),
- Token::STRING, t._type);
-}
-
-std::string TextInput::readString() {
- return readStringToken()._string;
-}
-
-void TextInput::readString(const std::string& s) {
- Token t(readStringToken());
-
- if (t._string == s) { // fast path
- return;
- }
-
- push(t);
- throw WrongString(options.sourceFileName, t.line(), t.character(),
- s, t._string);
-}
-
-Token TextInput::readCommentToken() {
- Token t(read());
-
- if (t._type == Token::COMMENT) { // fast path
- return t;
- }
-
- push(t);
- throw WrongTokenType(options.sourceFileName, t.line(), t.character(),
- Token::COMMENT, t._type);
-}
-
-std::string TextInput::readComment() {
- return readCommentToken()._string;
-}
-
-void TextInput::readComment(const std::string& s) {
- Token t(readCommentToken());
-
- if (t._string == s) { // fast path
- return;
- }
-
- push(t);
- throw WrongString(options.sourceFileName, t.line(), t.character(),
- s, t._string);
-}
-
-Token TextInput::readNewlineToken() {
- Token t(read());
-
- if (t._type == Token::NEWLINE) { // fast path
- return t;
- }
-
- push(t);
- throw WrongTokenType(options.sourceFileName, t.line(), t.character(),
- Token::NEWLINE, t._type);
-}
-
-std::string TextInput::readNewline() {
- return readNewlineToken()._string;
-}
-
-void TextInput::readNewline(const std::string& s) {
- Token t(readNewlineToken());
-
- if (t._string == s) { // fast path
- return;
- }
-
- push(t);
- throw WrongString(options.sourceFileName, t.line(), t.character(),
- s, t._string);
-}
-
-Token TextInput::readSymbolToken() {
- Token t(read());
-
- if (t._type == Token::SYMBOL) { // fast path
- return t;
- }
-
- push(t);
- throw WrongTokenType(options.sourceFileName, t.line(), t.character(),
- Token::SYMBOL, t._type);
-}
-
-
-std::string TextInput::readSymbol() {
- return readSymbolToken()._string;
-}
-
-void TextInput::readSymbol(const std::string& symbol) {
- Token t(readSymbolToken());
-
- if (t._string == symbol) { // fast path
- return;
- }
-
- push(t);
- throw WrongSymbol(options.sourceFileName, t.line(), t.character(),
- symbol, t._string);
-}
-
-
-TextInput::TextInput(const std::string& filename, const Settings& opt) : options(opt) {
- init();
- std::string input = readWholeFile(filename);
-
- if (options.sourceFileName.empty()) {
- options.sourceFileName = filename;
- }
- int n = input.size();
- buffer.resize(n);
- System::memcpy(buffer.getCArray(), input.c_str(), n);
-}
-
-
-TextInput::TextInput(FS fs, const std::string& str, const Settings& opt) : options(opt) {
- (void)fs;
- init();
- if (options.sourceFileName.empty()) {
- if (str.length() < 14) {
- options.sourceFileName = std::string("\"") + str + "\"";
- } else {
- options.sourceFileName = std::string("\"") + str.substr(0, 10) + "...\"";
- }
- }
- buffer.resize(str.length()); // we don't bother copying trailing NUL.
- System::memcpy(buffer.getCArray(), str.c_str(), buffer.size());
-}
-
-
-const std::string& TextInput::filename() const {
- return options.sourceFileName;
-}
-
-///////////////////////////////////////////////////////////////////////////////////
-
-TextInput::TokenException::TokenException(
- const std::string& src,
- int ln,
- int ch) : ParseError(src, ln, ch, format("%s(%d) : ", src.c_str(), ln)),
- sourceFile(src) {
-}
-
-///////////////////////////////////////////////////////////////////////////////////
-
-static const char* tokenTypeToString(Token::Type t) {
- switch (t) {
- case Token::SYMBOL:
- return "Token::SYMBOL";
- case Token::STRING:
- return "Token::STRING";
- case Token::NUMBER:
- return "Token::NUMBER";
- case Token::END:
- return "Token::END";
- default:
- debugAssertM(false, "Fell through switch");
- return "?";
- }
-}
-
-TextInput::WrongTokenType::WrongTokenType(
- const std::string& src,
- int ln,
- int ch,
- Token::Type e,
- Token::Type a) :
- TokenException(src, ln, ch), expected(e), actual(a) {
-
- message += format("Expected token of type %s, found type %s.",
- tokenTypeToString(e), tokenTypeToString(a));
-}
-
-
-TextInput::BadMSVCSpecial::BadMSVCSpecial(
- const std::string& src,
- int ln,
- int ch) :
- TokenException(src, ln, ch) {
-}
-
-
-TextInput::WrongSymbol::WrongSymbol(
- const std::string& src,
- int ln,
- int ch,
- const std::string& e,
- const std::string& a) :
- TokenException(src, ln, ch), expected(e), actual(a) {
-
- message += format("Expected symbol '%s', found symbol '%s'.",
- e.c_str(), a.c_str());
-}
-
-
-TextInput::WrongString::WrongString(
- const std::string& src,
- int ln,
- int ch,
- const std::string& e,
- const std::string& a) :
- TokenException(src, ln, ch), expected(e), actual(a) {
-
- message += format("Expected string '%s', found string '%s'.",
- e.c_str(), a.c_str());
-}
-
-
-void deserialize(bool& b, TextInput& ti) {
- b = ti.readSymbol() == "true";
-}
-
-
-void deserialize(int& b, TextInput& ti) {
- b = iRound(ti.readNumber());
-}
-
-
-void deserialize(uint8& b, TextInput& ti) {
- b = (uint8)iRound(ti.readNumber());
-}
-
-
-void deserialize(double& b, TextInput& ti) {
- b = ti.readNumber();
-}
-
-
-void deserialize(float& b, TextInput& ti) {
- b = (float)ti.readNumber();
-}
-
-} // namespace
-
-#ifdef _MSC_VER
-# pragma warning (pop)
-#endif
diff --git a/externals/g3dlite/TextOutput.cpp b/externals/g3dlite/TextOutput.cpp
deleted file mode 100644
index 11347252eba..00000000000
--- a/externals/g3dlite/TextOutput.cpp
+++ /dev/null
@@ -1,452 +0,0 @@
-/**
- @file TextOutput.cpp
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @created 2004-06-21
- @edited 2006-08-14
-
- Copyright 2000-2006, Morgan McGuire.
- All rights reserved.
- */
-
-#include "G3D/TextOutput.h"
-#include "G3D/Log.h"
-#include "G3D/fileutils.h"
-
-namespace G3D {
-
-TextOutput::TextOutput(const TextOutput::Settings& opt) :
- startingNewLine(true),
- currentColumn(0),
- inDQuote(false),
- filename(""),
- indentLevel(0)
-{
- setOptions(opt);
-}
-
-
-TextOutput::TextOutput(const std::string& fil, const TextOutput::Settings& opt) :
- startingNewLine(true),
- currentColumn(0),
- inDQuote(false),
- filename(fil),
- indentLevel(0)
-{
-
- setOptions(opt);
-}
-
-
-void TextOutput::setIndentLevel(int i) {
- indentLevel = i;
-
- // If there were more pops than pushes, don't let that take us below 0 indent.
- // Don't ever indent more than the number of columns.
- indentSpaces =
- iClamp(option.spacesPerIndent * indentLevel,
- 0,
- option.numColumns - 1);
-}
-
-
-void TextOutput::setOptions(const Settings& _opt) {
- option = _opt;
-
- debugAssert(option.numColumns > 1);
-
- setIndentLevel(indentLevel);
-
- newline = (option.newlineStyle == Settings::NEWLINE_WINDOWS) ? "\r\n" : "\n";
-}
-
-
-void TextOutput::pushIndent() {
- setIndentLevel(indentLevel + 1);
-}
-
-
-void TextOutput::popIndent() {
- setIndentLevel(indentLevel - 1);
-}
-
-
-static std::string escape(const std::string& string) {
- std::string result = "";
-
- for (std::string::size_type i = 0; i < string.length(); ++i) {
- char c = string.at(i);
- switch (c) {
- case '\0':
- result += "\\0";
- break;
-
- case '\r':
- result += "\\r";
- break;
-
- case '\n':
- result += "\\n";
- break;
-
- case '\t':
- result += "\\t";
- break;
-
- case '\\':
- result += "\\\\";
- break;
-
- default:
- result += c;
- }
- }
-
- return result;
-}
-
-void TextOutput::writeString(const std::string& string) {
- // Convert special characters to escape sequences
- this->printf("\"%s\"", escape(string).c_str());
-}
-
-
-void TextOutput::writeBoolean(bool b) {
- this->printf("%s ", b ? option.trueSymbol.c_str() : option.falseSymbol.c_str());
-}
-
-void TextOutput::writeNumber(double n) {
- this->printf("%f ", n);
-}
-
-
-void TextOutput::writeNumber(int n) {
- this->printf("%d ", n);
-}
-
-
-void TextOutput::writeSymbol(const std::string& string) {
- if (string.size() > 0) {
- // TODO: check for legal symbols?
- this->printf("%s ", string.c_str());
- }
-}
-
-void TextOutput::writeSymbols(
- const std::string& a,
- const std::string& b,
- const std::string& c,
- const std::string& d,
- const std::string& e,
- const std::string& f) {
-
- writeSymbol(a);
- writeSymbol(b);
- writeSymbol(c);
- writeSymbol(d);
- writeSymbol(e);
- writeSymbol(f);
-}
-
-
-void TextOutput::printf(const std::string formatString, ...) {
- va_list argList;
- va_start(argList, formatString);
- this->vprintf(formatString.c_str(), argList);
- va_end(argList);
-}
-
-
-void TextOutput::printf(const char* formatString, ...) {
- va_list argList;
- va_start(argList, formatString);
- this->vprintf(formatString, argList);
- va_end(argList);
-}
-
-
-void TextOutput::convertNewlines(const std::string& in, std::string& out) {
- // TODO: can be significantly optimized in cases where
- // single characters are copied in order by walking through
- // the array and copying substrings as needed.
-
- if (option.convertNewlines) {
- out = "";
- for (uint32 i = 0; i < in.size(); ++i) {
- if (in[i] == '\n') {
- // Unix newline
- out += newline;
- } else if ((in[i] == '\r') && (i + 1 < in.size()) && (in[i + 1] == '\n')) {
- // Windows newline
- out += newline;
- ++i;
- } else {
- out += in[i];
- }
- }
- } else {
- out = in;
- }
-}
-
-
-void TextOutput::writeNewline() {
- for (uint32 i = 0; i < newline.size(); ++i) {
- indentAppend(newline[i]);
- }
-}
-
-
-void TextOutput::writeNewlines(int numLines) {
- for (int i = 0; i < numLines; ++i) {
- writeNewline();
- }
-}
-
-
-void TextOutput::wordWrapIndentAppend(const std::string& str) {
- // TODO: keep track of the last space character we saw so we don't
- // have to always search.
-
- if ((option.wordWrap == Settings::WRAP_NONE) ||
- (currentColumn + (int)str.size() <= option.numColumns)) {
- // No word-wrapping is needed
-
- // Add one character at a time.
- // TODO: optimize for strings without newlines to add multiple
- // characters.
- for (uint32 i = 0; i < str.size(); ++i) {
- indentAppend(str[i]);
- }
- return;
- }
-
- // Number of columns to wrap against
- int cols = option.numColumns - indentSpaces;
-
- // Copy forward until we exceed the column size,
- // and then back up and try to insert newlines as needed.
- for (uint32 i = 0; i < str.size(); ++i) {
-
- indentAppend(str[i]);
- if ((str[i] == '\r') && (i + 1 < str.size()) && (str[i + 1] == '\n')) {
- // \r\n, we need to hit the \n to enter word wrapping.
- ++i;
- indentAppend(str[i]);
- }
-
- if (currentColumn >= cols) {
- debugAssertM(str[i] != '\n' && str[i] != '\r',
- "Should never enter word-wrapping on a newline character");
-
- // True when we're allowed to treat a space as a space.
- bool unquotedSpace = option.allowWordWrapInsideDoubleQuotes || ! inDQuote;
-
- // Cases:
- //
- // 1. Currently in a series of spaces that ends with a newline
- // strip all spaces and let the newline
- // flow through.
- //
- // 2. Currently in a series of spaces that does not end with a newline
- // strip all spaces and replace them with single newline
- //
- // 3. Not in a series of spaces
- // search backwards for a space, then execute case 2.
-
- // Index of most recent space
- uint32 lastSpace = data.size() - 1;
-
- // How far back we had to look for a space
- uint32 k = 0;
- uint32 maxLookBackward = currentColumn - indentSpaces;
-
- // Search backwards (from current character), looking for a space.
- while ((k < maxLookBackward) &&
- (lastSpace > 0) &&
- (! ((data[lastSpace] == ' ') && unquotedSpace))) {
- --lastSpace;
- ++k;
-
- if ((data[lastSpace] == '\"') && !option.allowWordWrapInsideDoubleQuotes) {
- unquotedSpace = ! unquotedSpace;
- }
- }
-
- if (k == maxLookBackward) {
- // We couldn't find a series of spaces
-
- if (option.wordWrap == Settings::WRAP_ALWAYS) {
- // Strip the last character we wrote, force a newline,
- // and replace the last character;
- data.pop();
- writeNewline();
- indentAppend(str[i]);
- } else {
- // Must be Settings::WRAP_WITHOUT_BREAKING
- //
- // Don't write the newline; we'll come back to
- // the word wrap code after writing another character
- }
- } else {
- // We found a series of spaces. If they continue
- // to the new string, strip spaces off both. Otherwise
- // strip spaces from data only and insert a newline.
-
- // Find the start of the spaces. firstSpace is the index of the
- // first non-space, looking backwards from lastSpace.
- uint32 firstSpace = lastSpace;
- while ((k < maxLookBackward) &&
- (firstSpace > 0) &&
- (data[firstSpace] == ' ')) {
- --firstSpace;
- ++k;
- }
-
- if (k == maxLookBackward) {
- ++firstSpace;
- }
-
- if (lastSpace == (uint32)data.size() - 1) {
- // Spaces continued up to the new string
- data.resize(firstSpace + 1);
- writeNewline();
-
- // Delete the spaces from the new string
- while ((i < str.size() - 1) && (str[i + 1] == ' ')) {
- ++i;
- }
- } else {
- // Spaces were somewhere in the middle of the old string.
- // replace them with a newline.
-
- // Copy over the characters that should be saved
- Array<char> temp;
- for (uint32 j = lastSpace + 1; j < (uint32)data.size(); ++j) {
- char c = data[j];
-
- if (c == '\"') {
- // Undo changes to quoting (they will be re-done
- // when we paste these characters back on).
- inDQuote = !inDQuote;
- }
- temp.append(c);
- }
-
- // Remove those characters and replace with a newline.
- data.resize(firstSpace + 1);
- writeNewline();
-
- // Write them back
- for (uint32 j = 0; j < (uint32)temp.size(); ++j) {
- indentAppend(temp[j]);
- }
-
- // We are now free to continue adding from the
- // new string, which may or may not begin with spaces.
-
- } // if spaces included new string
- } // if hit indent
- } // if line exceeded
- } // iterate over str
-}
-
-
-void TextOutput::indentAppend(char c) {
-
- if (startingNewLine) {
- for (int j = 0; j < indentSpaces; ++j) {
- data.push(' ');
- }
- startingNewLine = false;
- currentColumn = indentSpaces;
- }
-
- data.push(c);
-
- // Don't increment the column count on return character
- // newline is taken care of below.
- if (c != '\r') {
- ++currentColumn;
- }
-
- if (c == '\"') {
- inDQuote = ! inDQuote;
- }
-
- startingNewLine = (c == '\n');
- if (startingNewLine) {
- currentColumn = 0;
- }
-}
-
-
-void TextOutput::vprintf(const char* formatString, va_list argPtr) {
- std::string str = vformat(formatString, argPtr);
-
- std::string clean;
- convertNewlines(str, clean);
- wordWrapIndentAppend(clean);
-}
-
-
-void TextOutput::commit(bool flush) {
- std::string p = filenamePath(filename);
- if (! fileExists(p, false)) {
- createDirectory(p);
- }
-
- FILE* f = fopen(filename.c_str(), "wb");
- debugAssertM(f, "Could not open \"" + filename + "\"");
- fwrite(data.getCArray(), 1, data.size(), f);
- if (flush) {
- fflush(f);
- }
- fclose(f);
-}
-
-
-void TextOutput::commitString(std::string& out) {
- // Null terminate
- data.push('\0');
- out = data.getCArray();
- data.pop();
-}
-
-
-std::string TextOutput::commitString() {
- std::string str;
- commitString(str);
- return str;
-}
-
-
-
-/////////////////////////////////////////////////////////////////////
-
-void serialize(const float& b, TextOutput& to) {
- to.writeNumber(b);
-}
-
-
-void serialize(const bool& b, TextOutput& to) {
- to.writeSymbol(b ? "true" : "false");
-}
-
-
-void serialize(const int& b, TextOutput& to) {
- to.writeNumber(b);
-}
-
-
-void serialize(const uint8& b, TextOutput& to) {
- to.writeNumber(b);
-}
-
-
-void serialize(const double& b, TextOutput& to) {
- to.writeNumber(b);
-}
-
-
-}
diff --git a/externals/g3dlite/Triangle.cpp b/externals/g3dlite/Triangle.cpp
deleted file mode 100644
index 253438ad5fb..00000000000
--- a/externals/g3dlite/Triangle.cpp
+++ /dev/null
@@ -1,186 +0,0 @@
-/**
- @file Triangle.cpp
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2001-04-06
- @edited 2008-12-28
-
- Copyright 2000-2009, Morgan McGuire.
- All rights reserved.
- */
-
-#include "G3D/platform.h"
-#include "G3D/Triangle.h"
-#include "G3D/Plane.h"
-#include "G3D/BinaryInput.h"
-#include "G3D/BinaryOutput.h"
-#include "G3D/debugAssert.h"
-#include "G3D/AABox.h"
-#include "G3D/Ray.h"
-
-namespace G3D {
-
-
-void Triangle::init(const Vector3& v0, const Vector3& v1, const Vector3& v2) {
-
- _plane = Plane(v0, v1, v2);
- _vertex[0] = v0;
- _vertex[1] = v1;
- _vertex[2] = v2;
-
- static int next[] = {1,2,0};
-
- for (int i = 0; i < 3; ++i) {
- const Vector3& e = _vertex[next[i]] - _vertex[i];
- edgeMagnitude[i] = e.magnitude();
-
- if (edgeMagnitude[i] == 0) {
- edgeDirection[i] = Vector3::zero();
- } else {
- edgeDirection[i] = e / (float)edgeMagnitude[i];
- }
- }
-
- _edge01 = _vertex[1] - _vertex[0];
- _edge02 = _vertex[2] - _vertex[0];
-
- _primaryAxis = _plane.normal().primaryAxis();
- _area = 0.5f * edgeDirection[0].cross(edgeDirection[2]).magnitude() * (edgeMagnitude[0] * edgeMagnitude[2]);
- //0.5f * (_vertex[1] - _vertex[0]).cross(_vertex[2] - _vertex[0]).dot(_plane.normal());
-}
-
-
-Triangle::Triangle() {
- init(Vector3::zero(), Vector3::zero(), Vector3::zero());
-}
-
-
-Triangle::Triangle(const Vector3& v0, const Vector3& v1, const Vector3& v2) {
- init(v0, v1, v2);
-}
-
-
-Triangle::~Triangle() {
-}
-
-
-Triangle::Triangle(class BinaryInput& b) {
- deserialize(b);
-}
-
-
-void Triangle::serialize(class BinaryOutput& b) {
- _vertex[0].serialize(b);
- _vertex[1].serialize(b);
- _vertex[2].serialize(b);
-}
-
-
-void Triangle::deserialize(class BinaryInput& b) {
- _vertex[0].deserialize(b);
- _vertex[1].deserialize(b);
- _vertex[2].deserialize(b);
- init(_vertex[0], _vertex[1], _vertex[2]);
-}
-
-
-float Triangle::area() const {
- return _area;
-}
-
-
-const Vector3& Triangle::normal() const {
- return _plane.normal();
-}
-
-
-const Plane& Triangle::plane() const {
- return _plane;
-}
-
-
-Vector3 Triangle::center() const {
- return (_vertex[0] + _vertex[1] + _vertex[2]) / 3.0;
-}
-
-Vector3 Triangle::randomPoint() const {
- // Choose a random point in the parallelogram
-
- float s = uniformRandom();
- float t = uniformRandom();
-
- if (t > 1.0f - s) {
- // Outside the triangle; reflect about the
- // diagonal of the parallelogram
- t = 1.0f - t;
- s = 1.0f - s;
- }
-
- return _edge01 * s + _edge02 * t + _vertex[0];
-}
-
-
-void Triangle::getBounds(AABox& out) const {
- Vector3 lo = _vertex[0];
- Vector3 hi = lo;
-
- for (int i = 1; i < 3; ++i) {
- lo = lo.min(_vertex[i]);
- hi = hi.max(_vertex[i]);
- }
-
- out = AABox(lo, hi);
-}
-
-
-bool Triangle::intersect(const Ray& ray, float& distance, float baryCoord[3]) const {
- static const float EPS = 1e-5f;
-
- // See RTR2 ch. 13.7 for the algorithm.
-
- const Vector3& e1 = edge01();
- const Vector3& e2 = edge02();
- const Vector3 p(ray.direction().cross(e2));
- const float a = e1.dot(p);
-
- if (abs(a) < EPS) {
- // Determinant is ill-conditioned; abort early
- return false;
- }
-
- const float f = 1.0f / a;
- const Vector3 s(ray.origin() - vertex(0));
- const float u = f * s.dot(p);
-
- if ((u < 0.0f) || (u > 1.0f)) {
- // We hit the plane of the m_geometry, but outside the m_geometry
- return false;
- }
-
- const Vector3 q(s.cross(e1));
- const float v = f * ray.direction().dot(q);
-
- if ((v < 0.0f) || ((u + v) > 1.0f)) {
- // We hit the plane of the triangle, but outside the triangle
- return false;
- }
-
- const float t = f * e2.dot(q);
-
- if ((t > 0.0f) && (t < distance)) {
- // This is a new hit, closer than the previous one
- distance = t;
-
- baryCoord[0] = 1.0 - u - v;
- baryCoord[1] = u;
- baryCoord[2] = v;
-
- return true;
- } else {
- // This hit is after the previous hit, so ignore it
- return false;
- }
-}
-
-} // G3D
diff --git a/externals/g3dlite/UprightFrame.cpp b/externals/g3dlite/UprightFrame.cpp
deleted file mode 100644
index c80264bf4e8..00000000000
--- a/externals/g3dlite/UprightFrame.cpp
+++ /dev/null
@@ -1,132 +0,0 @@
-/**
- @file UprightFrame.cpp
- Box class
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2007-05-02
- @edited 2007-05-05
-*/
-
-#include "G3D/UprightFrame.h"
-#include "G3D/BinaryInput.h"
-#include "G3D/BinaryOutput.h"
-
-namespace G3D {
-
-UprightFrame::UprightFrame(const CoordinateFrame& cframe) {
- Vector3 look = cframe.lookVector();
-
- yaw = G3D::pi() + atan2(look.x, look.z);
- pitch = asin(look.y);
-
- translation = cframe.translation;
-}
-
-
-CoordinateFrame UprightFrame::toCoordinateFrame() const {
- CoordinateFrame cframe;
-
- Matrix3 P(Matrix3::fromAxisAngle(Vector3::unitX(), pitch));
- Matrix3 Y(Matrix3::fromAxisAngle(Vector3::unitY(), yaw));
-
- cframe.rotation = Y * P;
- cframe.translation = translation;
-
- return cframe;
-}
-
-
-UprightFrame UprightFrame::operator+(const UprightFrame& other) const {
- return UprightFrame(translation + other.translation, pitch + other.pitch, yaw + other.yaw);
-}
-
-
-UprightFrame UprightFrame::operator*(const float k) const {
- return UprightFrame(translation * k, pitch * k, yaw * k);
-}
-
-
-void UprightFrame::unwrapYaw(UprightFrame* a, int N) {
- // Use the first point to establish the wrapping convention
- for (int i = 1; i < N; ++i) {
- const float prev = a[i - 1].yaw;
- float& cur = a[i].yaw;
-
- // No two angles should be more than pi (i.e., 180-degrees) apart.
- if (abs(cur - prev) > G3D::pi()) {
- // These angles must have wrapped at zero, causing them
- // to be interpolated the long way.
-
- // Find canonical [0, 2pi] versions of these numbers
- float p = wrap(prev, twoPi());
- float c = wrap(cur, twoPi());
-
- // Find the difference -pi < diff < pi between the current and previous values
- float diff = c - p;
- if (diff < -G3D::pi()) {
- diff += twoPi();
- } else if (diff > G3D::pi()) {
- diff -= twoPi();
- }
-
- // Offset the current from the previous by the difference
- // between them.
- cur = prev + diff;
- }
- }
-}
-
-
-void UprightFrame::serialize(class BinaryOutput& b) const {
- translation.serialize(b);
- b.writeFloat32(pitch);
- b.writeFloat32(yaw);
-}
-
-
-void UprightFrame::deserialize(class BinaryInput& b) {
- translation.deserialize(b);
- pitch = b.readFloat32();
- yaw = b.readFloat32();
-}
-
-
-void UprightSpline::serialize(class BinaryOutput& b) const {
- b.writeBool8(cyclic);
-
- b.writeInt32(control.size());
- for (int i = 0; i < control.size(); ++i) {
- control[i].serialize(b);
- }
- b.writeInt32(time.size());
- for (int i = 0; i < time.size(); ++i) {
- b.writeFloat32(time[i]);
- }
-}
-
-
-void UprightSpline::deserialize(class BinaryInput& b) {
- cyclic = b.readBool8();
-
- control.resize(b.readInt32());
- for (int i = 0; i < control.size(); ++i) {
- control[i].deserialize(b);
- }
-
- if (b.hasMore()) {
- time.resize(b.readInt32());
- for (int i = 0; i < time.size(); ++i) {
- time[i] = b.readFloat32();
- }
- debugAssert(time.size() == control.size());
- } else {
- // Import legacy path
- time.resize(control.size());
- for (int i = 0; i < time.size(); ++i) {
- time[i] = i;
- }
- }
-}
-
-}
diff --git a/externals/g3dlite/Vector2.cpp b/externals/g3dlite/Vector2.cpp
deleted file mode 100644
index ec0737c3755..00000000000
--- a/externals/g3dlite/Vector2.cpp
+++ /dev/null
@@ -1,224 +0,0 @@
-/**
- @file Vector2.cpp
-
- 2D vector class, used for texture coordinates primarily.
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @cite Portions based on Dave Eberly'x Magic Software Library
- at http://www.magic-software.com
-
- @created 2001-06-02
- @edited 2009-11-16
- */
-
-#include "G3D/platform.h"
-#include <stdlib.h>
-#include "G3D/Vector2.h"
-#include "G3D/g3dmath.h"
-#include "G3D/format.h"
-#include "G3D/BinaryInput.h"
-#include "G3D/BinaryOutput.h"
-#include "G3D/TextInput.h"
-#include "G3D/TextOutput.h"
-#include "G3D/Any.h"
-
-namespace G3D {
-
-
-Vector2::Vector2(const Any& any) {
- any.verifyName("Vector2");
- any.verifyType(Any::TABLE, Any::ARRAY);
- any.verifySize(2);
-
- if (any.type() == Any::ARRAY) {
- x = any[0];
- y = any[1];
- } else {
- // Table
- x = any["x"];
- y = any["y"];
- }
-}
-
-
-Vector2::operator Any() const {
- Any any(Any::ARRAY, "Vector2");
- any.append(x, y);
- return any;
-}
-
-
-const Vector2& Vector2::one() {
- static const Vector2 v(1, 1); return v;
-}
-
-
-const Vector2& Vector2::zero() {
- static Vector2 v(0, 0);
- return v;
-}
-
-const Vector2& Vector2::unitX() {
- static Vector2 v(1, 0);
- return v;
-}
-
-const Vector2& Vector2::unitY() {
- static Vector2 v(0, 1);
- return v;
-}
-
-const Vector2& Vector2::inf() {
- static Vector2 v((float)G3D::finf(), (float)G3D::finf());
- return v;
-}
-
-
-const Vector2& Vector2::nan() {
- static Vector2 v((float)G3D::fnan(), (float)G3D::fnan());
- return v;
-}
-
-
-const Vector2& Vector2::minFinite() {
- static Vector2 v(-FLT_MAX, -FLT_MAX);
- return v;
-}
-
-
-const Vector2& Vector2::maxFinite() {
- static Vector2 v(FLT_MAX, FLT_MAX);
- return v;
-}
-
-
-size_t Vector2::hashCode() const {
- unsigned int xhash = (*(int*)(void*)(&x));
- unsigned int yhash = (*(int*)(void*)(&y));
-
- return xhash + (yhash * 37);
-}
-
-
-Vector2::Vector2(BinaryInput& b) {
- deserialize(b);
-}
-
-
-void Vector2::deserialize(BinaryInput& b) {
- x = b.readFloat32();
- y = b.readFloat32();
-}
-
-
-void Vector2::serialize(BinaryOutput& b) const {
- b.writeFloat32(x);
- b.writeFloat32(y);
-}
-
-
-void Vector2::deserialize(TextInput& t) {
- t.readSymbol("(");
- x = (float)t.readNumber();
- t.readSymbol(",");
- y = (float)t.readNumber();
- t.readSymbol(")");
-}
-
-
-void Vector2::serialize(TextOutput& t) const {
- t.writeSymbol("(");
- t.writeNumber(x);
- t.writeSymbol(",");
- t.writeNumber(y);
- t.writeSymbol(")");
-}
-
-//----------------------------------------------------------------------------
-
-Vector2 Vector2::random(G3D::Random& r) {
- Vector2 result;
-
- do {
- result = Vector2(r.uniform(-1, 1), r.uniform(-1, 1));
-
- } while (result.squaredLength() >= 1.0f);
-
- result.unitize();
-
- return result;
-}
-
-
-Vector2 Vector2::operator/ (float k) const {
- return *this * (1.0f / k);
-}
-
-Vector2& Vector2::operator/= (float k) {
- this->x /= k;
- this->y /= k;
- return *this;
-}
-
-//----------------------------------------------------------------------------
-float Vector2::unitize (float fTolerance) {
- float fLength = length();
-
- if (fLength > fTolerance) {
- float fInvLength = 1.0f / fLength;
- x *= fInvLength;
- y *= fInvLength;
- } else {
- fLength = 0.0;
- }
-
- return fLength;
-}
-
-//----------------------------------------------------------------------------
-
-std::string Vector2::toString() const {
- return G3D::format("(%g, %g)", x, y);
-}
-
-// 2-char swizzles
-
-Vector2 Vector2::xx() const { return Vector2 (x, x); }
-Vector2 Vector2::yx() const { return Vector2 (y, x); }
-Vector2 Vector2::xy() const { return Vector2 (x, y); }
-Vector2 Vector2::yy() const { return Vector2 (y, y); }
-
-// 3-char swizzles
-
-Vector3 Vector2::xxx() const { return Vector3 (x, x, x); }
-Vector3 Vector2::yxx() const { return Vector3 (y, x, x); }
-Vector3 Vector2::xyx() const { return Vector3 (x, y, x); }
-Vector3 Vector2::yyx() const { return Vector3 (y, y, x); }
-Vector3 Vector2::xxy() const { return Vector3 (x, x, y); }
-Vector3 Vector2::yxy() const { return Vector3 (y, x, y); }
-Vector3 Vector2::xyy() const { return Vector3 (x, y, y); }
-Vector3 Vector2::yyy() const { return Vector3 (y, y, y); }
-
-// 4-char swizzles
-
-Vector4 Vector2::xxxx() const { return Vector4 (x, x, x, x); }
-Vector4 Vector2::yxxx() const { return Vector4 (y, x, x, x); }
-Vector4 Vector2::xyxx() const { return Vector4 (x, y, x, x); }
-Vector4 Vector2::yyxx() const { return Vector4 (y, y, x, x); }
-Vector4 Vector2::xxyx() const { return Vector4 (x, x, y, x); }
-Vector4 Vector2::yxyx() const { return Vector4 (y, x, y, x); }
-Vector4 Vector2::xyyx() const { return Vector4 (x, y, y, x); }
-Vector4 Vector2::yyyx() const { return Vector4 (y, y, y, x); }
-Vector4 Vector2::xxxy() const { return Vector4 (x, x, x, y); }
-Vector4 Vector2::yxxy() const { return Vector4 (y, x, x, y); }
-Vector4 Vector2::xyxy() const { return Vector4 (x, y, x, y); }
-Vector4 Vector2::yyxy() const { return Vector4 (y, y, x, y); }
-Vector4 Vector2::xxyy() const { return Vector4 (x, x, y, y); }
-Vector4 Vector2::yxyy() const { return Vector4 (y, x, y, y); }
-Vector4 Vector2::xyyy() const { return Vector4 (x, y, y, y); }
-Vector4 Vector2::yyyy() const { return Vector4 (y, y, y, y); }
-
-
-
-} // namespace
diff --git a/externals/g3dlite/Vector3.cpp b/externals/g3dlite/Vector3.cpp
deleted file mode 100644
index a53fa8269b7..00000000000
--- a/externals/g3dlite/Vector3.cpp
+++ /dev/null
@@ -1,507 +0,0 @@
-/**
- @file Vector3.cpp
-
- 3D vector class
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @cite Portions based on Dave Eberly's Magic Software Library at http://www.magic-software.com
-
- @created 2001-06-02
- @edited 2009-11-27
- */
-
-#include <limits>
-#include <stdlib.h>
-#include "G3D/Vector3.h"
-#include "G3D/g3dmath.h"
-#include "G3D/stringutils.h"
-#include "G3D/BinaryInput.h"
-#include "G3D/BinaryOutput.h"
-#include "G3D/TextInput.h"
-#include "G3D/TextOutput.h"
-#include "G3D/Vector3int16.h"
-#include "G3D/Matrix3.h"
-#include "G3D/Vector2.h"
-#include "G3D/Color3.h"
-#include "G3D/Vector4int8.h"
-#include "G3D/Vector3int32.h"
-#include "G3D/Any.h"
-
-namespace G3D {
-
-Vector3::Vector3(const Any& any) {
- any.verifyName("Vector3");
- any.verifyType(Any::TABLE, Any::ARRAY);
- any.verifySize(3);
-
- if (any.type() == Any::ARRAY) {
- x = any[0];
- y = any[1];
- z = any[2];
- } else {
- // Table
- x = any["x"];
- y = any["y"];
- z = any["z"];
- }
-}
-
-Vector3::operator Any() const {
- Any any(Any::ARRAY, "Vector3");
- any.append(x, y, z);
- return any;
-}
-
-Vector3::Vector3(const class Color3& v) : x(v.r), y(v.g), z(v.b) {}
-
-Vector3::Vector3(const class Vector3int32& v) : x((float)v.x), y((float)v.y), z((float)v.z) {}
-
-Vector3::Vector3(const Vector4int8& v) : x(v.x / 127.0f), y(v.y / 127.0f), z(v.z / 127.0f) {}
-
-Vector3::Vector3(const class Vector2& v, float _z) : x(v.x), y(v.y), z(_z) {
-}
-
-Vector3& Vector3::ignore() {
- static Vector3 v;
- return v;
-}
-
-const Vector3& Vector3::zero() { static const Vector3 v(0, 0, 0); return v; }
-const Vector3& Vector3::one() { static const Vector3 v(1, 1, 1); return v; }
-const Vector3& Vector3::unitX() { static const Vector3 v(1, 0, 0); return v; }
-const Vector3& Vector3::unitY() { static const Vector3 v(0, 1, 0); return v; }
-const Vector3& Vector3::unitZ() { static const Vector3 v(0, 0, 1); return v; }
-const Vector3& Vector3::inf() { static const Vector3 v((float)G3D::finf(), (float)G3D::finf(), (float)G3D::finf()); return v; }
-const Vector3& Vector3::nan() { static const Vector3 v((float)G3D::fnan(), (float)G3D::fnan(), (float)G3D::fnan()); return v; }
-const Vector3& Vector3::minFinite(){ static const Vector3 v(-FLT_MAX, -FLT_MAX, -FLT_MAX); return v; }
-const Vector3& Vector3::maxFinite(){ static const Vector3 v(FLT_MAX, FLT_MAX, FLT_MAX); return v; }
-
-Vector3::Axis Vector3::primaryAxis() const {
-
- Axis a = X_AXIS;
-
- double nx = abs(x);
- double ny = abs(y);
- double nz = abs(z);
-
- if (nx > ny) {
- if (nx > nz) {
- a = X_AXIS;
- } else {
- a = Z_AXIS;
- }
- } else {
- if (ny > nz) {
- a = Y_AXIS;
- } else {
- a = Z_AXIS;
- }
- }
-
- return a;
-}
-
-
-size_t Vector3::hashCode() const {
- unsigned int xhash = (*(int*)(void*)(&x));
- unsigned int yhash = (*(int*)(void*)(&y));
- unsigned int zhash = (*(int*)(void*)(&z));
-
- return xhash + (yhash * 37) + (zhash * 101);
-}
-
-std::ostream& operator<<(std::ostream& os, const Vector3& v) {
- return os << v.toString();
-}
-
-
-//----------------------------------------------------------------------------
-
-double frand() {
- return rand() / (double) RAND_MAX;
-}
-
-Vector3::Vector3(TextInput& t) {
- deserialize(t);
-}
-
-Vector3::Vector3(BinaryInput& b) {
- deserialize(b);
-}
-
-
-Vector3::Vector3(const class Vector3int16& v) {
- x = v.x;
- y = v.y;
- z = v.z;
-}
-
-
-void Vector3::deserialize(BinaryInput& b) {
- x = b.readFloat32();
- y = b.readFloat32();
- z = b.readFloat32();
-}
-
-
-void Vector3::deserialize(TextInput& t) {
- t.readSymbol("(");
- x = (float)t.readNumber();
- t.readSymbol(",");
- y = (float)t.readNumber();
- t.readSymbol(",");
- z = (float)t.readNumber();
- t.readSymbol(")");
-}
-
-
-void Vector3::serialize(TextOutput& t) const {
- t.writeSymbol("(");
- t.writeNumber(x);
- t.writeSymbol(",");
- t.writeNumber(y);
- t.writeSymbol(",");
- t.writeNumber(z);
- t.writeSymbol(")");
-}
-
-
-void Vector3::serialize(BinaryOutput& b) const {
- b.writeFloat32(x);
- b.writeFloat32(y);
- b.writeFloat32(z);
-}
-
-
-Vector3 Vector3::random(Random& r) {
- Vector3 result;
- r.sphere(result.x, result.y, result.z);
- return result;
-}
-
-
-float Vector3::unitize(float fTolerance) {
- float fMagnitude = magnitude();
-
- if (fMagnitude > fTolerance) {
- float fInvMagnitude = 1.0f / fMagnitude;
- x *= fInvMagnitude;
- y *= fInvMagnitude;
- z *= fInvMagnitude;
- } else {
- fMagnitude = 0.0f;
- }
-
- return fMagnitude;
-}
-
-
-Vector3 Vector3::reflectAbout(const Vector3& normal) const {
- Vector3 out;
-
- Vector3 N = normal.direction();
-
- // 2 * normal.dot(this) * normal - this
- return N * 2 * this->dot(N) - *this;
-}
-
-
-Vector3 Vector3::cosHemiRandom(const Vector3& normal, Random& r) {
- debugAssertM(G3D::fuzzyEq(normal.length(), 1.0f),
- "cosHemiRandom requires its argument to have unit length");
-
- float x, y, z;
- r.cosHemi(x, y, z);
-
- // Make a coordinate system
- const Vector3& Z = normal;
-
- Vector3 X, Y;
- normal.getTangents(X, Y);
-
- return
- x * X +
- y * Y +
- z * Z;
-}
-
-
-Vector3 Vector3::cosPowHemiRandom(const Vector3& normal, const float k, Random& r) {
- debugAssertM(G3D::fuzzyEq(normal.length(), 1.0f),
- "cosPowHemiRandom requires its argument to have unit length");
-
- float x, y, z;
- r.cosPowHemi(k, x, y, z);
-
- // Make a coordinate system
- const Vector3& Z = normal;
-
- Vector3 X, Y;
- normal.getTangents(X, Y);
-
- return
- x * X +
- y * Y +
- z * Z;
-}
-
-
-Vector3 Vector3::hemiRandom(const Vector3& normal, Random& r) {
- const Vector3& V = Vector3::random(r);
-
- if (V.dot(normal) < 0) {
- return -V;
- } else {
- return V;
- }
-}
-
-//----------------------------------------------------------------------------
-
-Vector3 Vector3::reflectionDirection(const Vector3& normal) const {
- return -reflectAbout(normal).direction();
-}
-
-//----------------------------------------------------------------------------
-
-Vector3 Vector3::refractionDirection(
- const Vector3& normal,
- float iInside,
- float iOutside) const {
-
- // From pg. 24 of Henrik Wann Jensen. Realistic Image Synthesis
- // Using Photon Mapping. AK Peters. ISBN: 1568811470. July 2001.
-
- // Invert the directions from Wann Jensen's formulation
- // and normalize the vectors.
- const Vector3 W = -direction();
- Vector3 N = normal.direction();
-
- float h1 = iOutside;
- float h2 = iInside;
-
- if (normal.dot(*this) > 0.0f) {
- h1 = iInside;
- h2 = iOutside;
- N = -N;
- }
-
- const float hRatio = h1 / h2;
- const float WdotN = W.dot(N);
-
- float det = 1.0f - (float)square(hRatio) * (1.0f - (float)square(WdotN));
-
- if (det < 0) {
- // Total internal reflection
- return Vector3::zero();
- } else {
- return -hRatio * (W - WdotN * N) - N * sqrt(det);
- }
-}
-
-//----------------------------------------------------------------------------
-void Vector3::orthonormalize (Vector3 akVector[3]) {
- // If the input vectors are v0, v1, and v2, then the Gram-Schmidt
- // orthonormalization produces vectors u0, u1, and u2 as follows,
- //
- // u0 = v0/|v0|
- // u1 = (v1-(u0*v1)u0)/|v1-(u0*v1)u0|
- // u2 = (v2-(u0*v2)u0-(u1*v2)u1)/|v2-(u0*v2)u0-(u1*v2)u1|
- //
- // where |A| indicates length of vector A and A*B indicates dot
- // product of vectors A and B.
-
- // compute u0
- akVector[0].unitize();
-
- // compute u1
- float fDot0 = akVector[0].dot(akVector[1]);
- akVector[1] -= akVector[0] * fDot0;
- akVector[1].unitize();
-
- // compute u2
- float fDot1 = akVector[1].dot(akVector[2]);
- fDot0 = akVector[0].dot(akVector[2]);
- akVector[2] -= akVector[0] * fDot0 + akVector[1] * fDot1;
- akVector[2].unitize();
-}
-
-//----------------------------------------------------------------------------
-void Vector3::generateOrthonormalBasis (Vector3& rkU, Vector3& rkV,
- Vector3& rkW, bool bUnitLengthW) {
- if ( !bUnitLengthW )
- rkW.unitize();
-
- if ( G3D::abs(rkW.x) >= G3D::abs(rkW.y)
- && G3D::abs(rkW.x) >= G3D::abs(rkW.z) ) {
- rkU.x = -rkW.y;
- rkU.y = + rkW.x;
- rkU.z = 0.0;
- } else {
- rkU.x = 0.0;
- rkU.y = + rkW.z;
- rkU.z = -rkW.y;
- }
-
- rkU.unitize();
- rkV = rkW.cross(rkU);
-}
-
-//----------------------------------------------------------------------------
-
-std::string Vector3::toString() const {
- return G3D::format("(%g, %g, %g)", x, y, z);
-}
-
-
-//----------------------------------------------------------------------------
-
-Matrix3 Vector3::cross() const {
- return Matrix3( 0, -z, y,
- z, 0, -x,
- -y, x, 0);
-}
-
-
-void serialize(const Vector3::Axis& a, class BinaryOutput& bo) {
- bo.writeUInt8((uint8)a);
-}
-
-void deserialize(Vector3::Axis& a, class BinaryInput& bi) {
- a = (Vector3::Axis)bi.readUInt8();
-}
-
-//----------------------------------------------------------------------------
-// 2-char swizzles
-
-Vector2 Vector3::xx() const { return Vector2 (x, x); }
-Vector2 Vector3::yx() const { return Vector2 (y, x); }
-Vector2 Vector3::zx() const { return Vector2 (z, x); }
-Vector2 Vector3::xy() const { return Vector2 (x, y); }
-Vector2 Vector3::yy() const { return Vector2 (y, y); }
-Vector2 Vector3::zy() const { return Vector2 (z, y); }
-Vector2 Vector3::xz() const { return Vector2 (x, z); }
-Vector2 Vector3::yz() const { return Vector2 (y, z); }
-Vector2 Vector3::zz() const { return Vector2 (z, z); }
-
-// 3-char swizzles
-
-Vector3 Vector3::xxx() const { return Vector3 (x, x, x); }
-Vector3 Vector3::yxx() const { return Vector3 (y, x, x); }
-Vector3 Vector3::zxx() const { return Vector3 (z, x, x); }
-Vector3 Vector3::xyx() const { return Vector3 (x, y, x); }
-Vector3 Vector3::yyx() const { return Vector3 (y, y, x); }
-Vector3 Vector3::zyx() const { return Vector3 (z, y, x); }
-Vector3 Vector3::xzx() const { return Vector3 (x, z, x); }
-Vector3 Vector3::yzx() const { return Vector3 (y, z, x); }
-Vector3 Vector3::zzx() const { return Vector3 (z, z, x); }
-Vector3 Vector3::xxy() const { return Vector3 (x, x, y); }
-Vector3 Vector3::yxy() const { return Vector3 (y, x, y); }
-Vector3 Vector3::zxy() const { return Vector3 (z, x, y); }
-Vector3 Vector3::xyy() const { return Vector3 (x, y, y); }
-Vector3 Vector3::yyy() const { return Vector3 (y, y, y); }
-Vector3 Vector3::zyy() const { return Vector3 (z, y, y); }
-Vector3 Vector3::xzy() const { return Vector3 (x, z, y); }
-Vector3 Vector3::yzy() const { return Vector3 (y, z, y); }
-Vector3 Vector3::zzy() const { return Vector3 (z, z, y); }
-Vector3 Vector3::xxz() const { return Vector3 (x, x, z); }
-Vector3 Vector3::yxz() const { return Vector3 (y, x, z); }
-Vector3 Vector3::zxz() const { return Vector3 (z, x, z); }
-Vector3 Vector3::xyz() const { return Vector3 (x, y, z); }
-Vector3 Vector3::yyz() const { return Vector3 (y, y, z); }
-Vector3 Vector3::zyz() const { return Vector3 (z, y, z); }
-Vector3 Vector3::xzz() const { return Vector3 (x, z, z); }
-Vector3 Vector3::yzz() const { return Vector3 (y, z, z); }
-Vector3 Vector3::zzz() const { return Vector3 (z, z, z); }
-
-// 4-char swizzles
-
-Vector4 Vector3::xxxx() const { return Vector4 (x, x, x, x); }
-Vector4 Vector3::yxxx() const { return Vector4 (y, x, x, x); }
-Vector4 Vector3::zxxx() const { return Vector4 (z, x, x, x); }
-Vector4 Vector3::xyxx() const { return Vector4 (x, y, x, x); }
-Vector4 Vector3::yyxx() const { return Vector4 (y, y, x, x); }
-Vector4 Vector3::zyxx() const { return Vector4 (z, y, x, x); }
-Vector4 Vector3::xzxx() const { return Vector4 (x, z, x, x); }
-Vector4 Vector3::yzxx() const { return Vector4 (y, z, x, x); }
-Vector4 Vector3::zzxx() const { return Vector4 (z, z, x, x); }
-Vector4 Vector3::xxyx() const { return Vector4 (x, x, y, x); }
-Vector4 Vector3::yxyx() const { return Vector4 (y, x, y, x); }
-Vector4 Vector3::zxyx() const { return Vector4 (z, x, y, x); }
-Vector4 Vector3::xyyx() const { return Vector4 (x, y, y, x); }
-Vector4 Vector3::yyyx() const { return Vector4 (y, y, y, x); }
-Vector4 Vector3::zyyx() const { return Vector4 (z, y, y, x); }
-Vector4 Vector3::xzyx() const { return Vector4 (x, z, y, x); }
-Vector4 Vector3::yzyx() const { return Vector4 (y, z, y, x); }
-Vector4 Vector3::zzyx() const { return Vector4 (z, z, y, x); }
-Vector4 Vector3::xxzx() const { return Vector4 (x, x, z, x); }
-Vector4 Vector3::yxzx() const { return Vector4 (y, x, z, x); }
-Vector4 Vector3::zxzx() const { return Vector4 (z, x, z, x); }
-Vector4 Vector3::xyzx() const { return Vector4 (x, y, z, x); }
-Vector4 Vector3::yyzx() const { return Vector4 (y, y, z, x); }
-Vector4 Vector3::zyzx() const { return Vector4 (z, y, z, x); }
-Vector4 Vector3::xzzx() const { return Vector4 (x, z, z, x); }
-Vector4 Vector3::yzzx() const { return Vector4 (y, z, z, x); }
-Vector4 Vector3::zzzx() const { return Vector4 (z, z, z, x); }
-Vector4 Vector3::xxxy() const { return Vector4 (x, x, x, y); }
-Vector4 Vector3::yxxy() const { return Vector4 (y, x, x, y); }
-Vector4 Vector3::zxxy() const { return Vector4 (z, x, x, y); }
-Vector4 Vector3::xyxy() const { return Vector4 (x, y, x, y); }
-Vector4 Vector3::yyxy() const { return Vector4 (y, y, x, y); }
-Vector4 Vector3::zyxy() const { return Vector4 (z, y, x, y); }
-Vector4 Vector3::xzxy() const { return Vector4 (x, z, x, y); }
-Vector4 Vector3::yzxy() const { return Vector4 (y, z, x, y); }
-Vector4 Vector3::zzxy() const { return Vector4 (z, z, x, y); }
-Vector4 Vector3::xxyy() const { return Vector4 (x, x, y, y); }
-Vector4 Vector3::yxyy() const { return Vector4 (y, x, y, y); }
-Vector4 Vector3::zxyy() const { return Vector4 (z, x, y, y); }
-Vector4 Vector3::xyyy() const { return Vector4 (x, y, y, y); }
-Vector4 Vector3::yyyy() const { return Vector4 (y, y, y, y); }
-Vector4 Vector3::zyyy() const { return Vector4 (z, y, y, y); }
-Vector4 Vector3::xzyy() const { return Vector4 (x, z, y, y); }
-Vector4 Vector3::yzyy() const { return Vector4 (y, z, y, y); }
-Vector4 Vector3::zzyy() const { return Vector4 (z, z, y, y); }
-Vector4 Vector3::xxzy() const { return Vector4 (x, x, z, y); }
-Vector4 Vector3::yxzy() const { return Vector4 (y, x, z, y); }
-Vector4 Vector3::zxzy() const { return Vector4 (z, x, z, y); }
-Vector4 Vector3::xyzy() const { return Vector4 (x, y, z, y); }
-Vector4 Vector3::yyzy() const { return Vector4 (y, y, z, y); }
-Vector4 Vector3::zyzy() const { return Vector4 (z, y, z, y); }
-Vector4 Vector3::xzzy() const { return Vector4 (x, z, z, y); }
-Vector4 Vector3::yzzy() const { return Vector4 (y, z, z, y); }
-Vector4 Vector3::zzzy() const { return Vector4 (z, z, z, y); }
-Vector4 Vector3::xxxz() const { return Vector4 (x, x, x, z); }
-Vector4 Vector3::yxxz() const { return Vector4 (y, x, x, z); }
-Vector4 Vector3::zxxz() const { return Vector4 (z, x, x, z); }
-Vector4 Vector3::xyxz() const { return Vector4 (x, y, x, z); }
-Vector4 Vector3::yyxz() const { return Vector4 (y, y, x, z); }
-Vector4 Vector3::zyxz() const { return Vector4 (z, y, x, z); }
-Vector4 Vector3::xzxz() const { return Vector4 (x, z, x, z); }
-Vector4 Vector3::yzxz() const { return Vector4 (y, z, x, z); }
-Vector4 Vector3::zzxz() const { return Vector4 (z, z, x, z); }
-Vector4 Vector3::xxyz() const { return Vector4 (x, x, y, z); }
-Vector4 Vector3::yxyz() const { return Vector4 (y, x, y, z); }
-Vector4 Vector3::zxyz() const { return Vector4 (z, x, y, z); }
-Vector4 Vector3::xyyz() const { return Vector4 (x, y, y, z); }
-Vector4 Vector3::yyyz() const { return Vector4 (y, y, y, z); }
-Vector4 Vector3::zyyz() const { return Vector4 (z, y, y, z); }
-Vector4 Vector3::xzyz() const { return Vector4 (x, z, y, z); }
-Vector4 Vector3::yzyz() const { return Vector4 (y, z, y, z); }
-Vector4 Vector3::zzyz() const { return Vector4 (z, z, y, z); }
-Vector4 Vector3::xxzz() const { return Vector4 (x, x, z, z); }
-Vector4 Vector3::yxzz() const { return Vector4 (y, x, z, z); }
-Vector4 Vector3::zxzz() const { return Vector4 (z, x, z, z); }
-Vector4 Vector3::xyzz() const { return Vector4 (x, y, z, z); }
-Vector4 Vector3::yyzz() const { return Vector4 (y, y, z, z); }
-Vector4 Vector3::zyzz() const { return Vector4 (z, y, z, z); }
-Vector4 Vector3::xzzz() const { return Vector4 (x, z, z, z); }
-Vector4 Vector3::yzzz() const { return Vector4 (y, z, z, z); }
-Vector4 Vector3::zzzz() const { return Vector4 (z, z, z, z); }
-
-
-
-
-
-
-} // namespace
diff --git a/externals/g3dlite/Vector4.cpp b/externals/g3dlite/Vector4.cpp
deleted file mode 100644
index f6abc1a6e0c..00000000000
--- a/externals/g3dlite/Vector4.cpp
+++ /dev/null
@@ -1,520 +0,0 @@
-/**
- @file Vector4.cpp
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2001-07-09
- @edited 2009-11-29
- */
-
-#include <stdlib.h>
-#include <limits>
-#include "G3D/Vector4.h"
-#include "G3D/Color4.h"
-#include "G3D/g3dmath.h"
-#include "G3D/stringutils.h"
-#include "G3D/BinaryInput.h"
-#include "G3D/BinaryOutput.h"
-#include "G3D/Vector4int8.h"
-#include "G3D/Matrix4.h"
-#include "G3D/Any.h"
-
-namespace G3D {
-
-Vector4::Vector4(const Any& any) {
- any.verifyName("Vector4");
- any.verifyType(Any::TABLE, Any::ARRAY);
- any.verifySize(4);
-
- if (any.type() == Any::ARRAY) {
- x = any[0];
- y = any[1];
- z = any[2];
- w = any[3];
- } else {
- // Table
- x = any["x"];
- y = any["y"];
- z = any["z"];
- w = any["w"];
- }
-}
-
-Vector4::operator Any() const {
- Any any(Any::ARRAY, "Vector4");
- any.append(x, y, z, w);
- return any;
-}
-
-
-Vector4::Vector4(const Vector4int8& v) : x(v.x / 127.0f), y(v.y / 127.0f), z(v.z / 127.0f), w(v.w / 127.0f) {
-}
-
-
-const Vector4& Vector4::inf() {
- static const Vector4 v((float)G3D::finf(), (float)G3D::finf(), (float)G3D::finf(), (float)G3D::finf());
- return v;
-}
-
-
-const Vector4& Vector4::zero() {
- static const Vector4 v(0,0,0,0);
- return v;
-}
-
-const Vector4& Vector4::nan() {
- static Vector4 v((float)G3D::fnan(), (float)G3D::fnan(), (float)G3D::fnan(), (float)G3D::fnan());
- return v;
-}
-
-
-size_t Vector4::hashCode() const {
- unsigned int xhash = (*(int*)(void*)(&x));
- unsigned int yhash = (*(int*)(void*)(&y));
- unsigned int zhash = (*(int*)(void*)(&z));
- unsigned int whash = (*(int*)(void*)(&w));
-
- return xhash + (yhash * 37) + (zhash * 101) + (whash * 241);
-}
-
-
-Vector4::Vector4(const class Color4& c) {
- x = c.r;
- y = c.g;
- z = c.b;
- w = c.a;
-}
-
-
-Vector4::Vector4(const Vector2& v1, const Vector2& v2) {
- x = v1.x;
- y = v1.y;
- z = v2.x;
- w = v2.y;
-}
-
-
-Vector4::Vector4(const Vector2& v1, float fz, float fw) {
- x = v1.x;
- y = v1.y;
- z = fz;
- w = fw;
-}
-
-Vector4::Vector4(BinaryInput& b) {
- deserialize(b);
-}
-
-
-void Vector4::deserialize(BinaryInput& b) {
- x = b.readFloat32();
- y = b.readFloat32();
- z = b.readFloat32();
- w = b.readFloat32();
-}
-
-
-void Vector4::serialize(BinaryOutput& b) const {
- b.writeFloat32(x);
- b.writeFloat32(y);
- b.writeFloat32(z);
- b.writeFloat32(w);
-}
-
-//----------------------------------------------------------------------------
-
-Vector4 Vector4::operator*(const Matrix4& M) const {
- Vector4 result;
- for (int i = 0; i < 4; ++i) {
- result[i] = 0.0f;
- for (int j = 0; j < 4; ++j) {
- result[i] += (*this)[j] * M[j][i];
- }
- }
- return result;
-}
-
-
-Vector4 Vector4::operator/ (float fScalar) const {
- Vector4 kQuot;
-
- if ( fScalar != 0.0 ) {
- float fInvScalar = 1.0f / fScalar;
- kQuot.x = fInvScalar * x;
- kQuot.y = fInvScalar * y;
- kQuot.z = fInvScalar * z;
- kQuot.w = fInvScalar * w;
- return kQuot;
- } else {
- return Vector4::inf();
- }
-}
-
-//----------------------------------------------------------------------------
-Vector4& Vector4::operator/= (float fScalar) {
- if (fScalar != 0.0f) {
- float fInvScalar = 1.0f / fScalar;
- x *= fInvScalar;
- y *= fInvScalar;
- z *= fInvScalar;
- w *= fInvScalar;
- } else {
- *this = Vector4::inf();
- }
-
- return *this;
-}
-
-
-//----------------------------------------------------------------------------
-
-std::string Vector4::toString() const {
- return G3D::format("(%g, %g, %g, %g)", x, y, z, w);
-}
-// 2-char swizzles
-
-Vector2 Vector4::xx() const { return Vector2 (x, x); }
-Vector2 Vector4::yx() const { return Vector2 (y, x); }
-Vector2 Vector4::zx() const { return Vector2 (z, x); }
-Vector2 Vector4::wx() const { return Vector2 (w, x); }
-Vector2 Vector4::xy() const { return Vector2 (x, y); }
-Vector2 Vector4::yy() const { return Vector2 (y, y); }
-Vector2 Vector4::zy() const { return Vector2 (z, y); }
-Vector2 Vector4::wy() const { return Vector2 (w, y); }
-Vector2 Vector4::xz() const { return Vector2 (x, z); }
-Vector2 Vector4::yz() const { return Vector2 (y, z); }
-Vector2 Vector4::zz() const { return Vector2 (z, z); }
-Vector2 Vector4::wz() const { return Vector2 (w, z); }
-Vector2 Vector4::xw() const { return Vector2 (x, w); }
-Vector2 Vector4::yw() const { return Vector2 (y, w); }
-Vector2 Vector4::zw() const { return Vector2 (z, w); }
-Vector2 Vector4::ww() const { return Vector2 (w, w); }
-
-// 3-char swizzles
-
-Vector3 Vector4::xxx() const { return Vector3 (x, x, x); }
-Vector3 Vector4::yxx() const { return Vector3 (y, x, x); }
-Vector3 Vector4::zxx() const { return Vector3 (z, x, x); }
-Vector3 Vector4::wxx() const { return Vector3 (w, x, x); }
-Vector3 Vector4::xyx() const { return Vector3 (x, y, x); }
-Vector3 Vector4::yyx() const { return Vector3 (y, y, x); }
-Vector3 Vector4::zyx() const { return Vector3 (z, y, x); }
-Vector3 Vector4::wyx() const { return Vector3 (w, y, x); }
-Vector3 Vector4::xzx() const { return Vector3 (x, z, x); }
-Vector3 Vector4::yzx() const { return Vector3 (y, z, x); }
-Vector3 Vector4::zzx() const { return Vector3 (z, z, x); }
-Vector3 Vector4::wzx() const { return Vector3 (w, z, x); }
-Vector3 Vector4::xwx() const { return Vector3 (x, w, x); }
-Vector3 Vector4::ywx() const { return Vector3 (y, w, x); }
-Vector3 Vector4::zwx() const { return Vector3 (z, w, x); }
-Vector3 Vector4::wwx() const { return Vector3 (w, w, x); }
-Vector3 Vector4::xxy() const { return Vector3 (x, x, y); }
-Vector3 Vector4::yxy() const { return Vector3 (y, x, y); }
-Vector3 Vector4::zxy() const { return Vector3 (z, x, y); }
-Vector3 Vector4::wxy() const { return Vector3 (w, x, y); }
-Vector3 Vector4::xyy() const { return Vector3 (x, y, y); }
-Vector3 Vector4::yyy() const { return Vector3 (y, y, y); }
-Vector3 Vector4::zyy() const { return Vector3 (z, y, y); }
-Vector3 Vector4::wyy() const { return Vector3 (w, y, y); }
-Vector3 Vector4::xzy() const { return Vector3 (x, z, y); }
-Vector3 Vector4::yzy() const { return Vector3 (y, z, y); }
-Vector3 Vector4::zzy() const { return Vector3 (z, z, y); }
-Vector3 Vector4::wzy() const { return Vector3 (w, z, y); }
-Vector3 Vector4::xwy() const { return Vector3 (x, w, y); }
-Vector3 Vector4::ywy() const { return Vector3 (y, w, y); }
-Vector3 Vector4::zwy() const { return Vector3 (z, w, y); }
-Vector3 Vector4::wwy() const { return Vector3 (w, w, y); }
-Vector3 Vector4::xxz() const { return Vector3 (x, x, z); }
-Vector3 Vector4::yxz() const { return Vector3 (y, x, z); }
-Vector3 Vector4::zxz() const { return Vector3 (z, x, z); }
-Vector3 Vector4::wxz() const { return Vector3 (w, x, z); }
-Vector3 Vector4::xyz() const { return Vector3 (x, y, z); }
-Vector3 Vector4::yyz() const { return Vector3 (y, y, z); }
-Vector3 Vector4::zyz() const { return Vector3 (z, y, z); }
-Vector3 Vector4::wyz() const { return Vector3 (w, y, z); }
-Vector3 Vector4::xzz() const { return Vector3 (x, z, z); }
-Vector3 Vector4::yzz() const { return Vector3 (y, z, z); }
-Vector3 Vector4::zzz() const { return Vector3 (z, z, z); }
-Vector3 Vector4::wzz() const { return Vector3 (w, z, z); }
-Vector3 Vector4::xwz() const { return Vector3 (x, w, z); }
-Vector3 Vector4::ywz() const { return Vector3 (y, w, z); }
-Vector3 Vector4::zwz() const { return Vector3 (z, w, z); }
-Vector3 Vector4::wwz() const { return Vector3 (w, w, z); }
-Vector3 Vector4::xxw() const { return Vector3 (x, x, w); }
-Vector3 Vector4::yxw() const { return Vector3 (y, x, w); }
-Vector3 Vector4::zxw() const { return Vector3 (z, x, w); }
-Vector3 Vector4::wxw() const { return Vector3 (w, x, w); }
-Vector3 Vector4::xyw() const { return Vector3 (x, y, w); }
-Vector3 Vector4::yyw() const { return Vector3 (y, y, w); }
-Vector3 Vector4::zyw() const { return Vector3 (z, y, w); }
-Vector3 Vector4::wyw() const { return Vector3 (w, y, w); }
-Vector3 Vector4::xzw() const { return Vector3 (x, z, w); }
-Vector3 Vector4::yzw() const { return Vector3 (y, z, w); }
-Vector3 Vector4::zzw() const { return Vector3 (z, z, w); }
-Vector3 Vector4::wzw() const { return Vector3 (w, z, w); }
-Vector3 Vector4::xww() const { return Vector3 (x, w, w); }
-Vector3 Vector4::yww() const { return Vector3 (y, w, w); }
-Vector3 Vector4::zww() const { return Vector3 (z, w, w); }
-Vector3 Vector4::www() const { return Vector3 (w, w, w); }
-
-// 4-char swizzles
-
-Vector4 Vector4::xxxx() const { return Vector4 (x, x, x, x); }
-Vector4 Vector4::yxxx() const { return Vector4 (y, x, x, x); }
-Vector4 Vector4::zxxx() const { return Vector4 (z, x, x, x); }
-Vector4 Vector4::wxxx() const { return Vector4 (w, x, x, x); }
-Vector4 Vector4::xyxx() const { return Vector4 (x, y, x, x); }
-Vector4 Vector4::yyxx() const { return Vector4 (y, y, x, x); }
-Vector4 Vector4::zyxx() const { return Vector4 (z, y, x, x); }
-Vector4 Vector4::wyxx() const { return Vector4 (w, y, x, x); }
-Vector4 Vector4::xzxx() const { return Vector4 (x, z, x, x); }
-Vector4 Vector4::yzxx() const { return Vector4 (y, z, x, x); }
-Vector4 Vector4::zzxx() const { return Vector4 (z, z, x, x); }
-Vector4 Vector4::wzxx() const { return Vector4 (w, z, x, x); }
-Vector4 Vector4::xwxx() const { return Vector4 (x, w, x, x); }
-Vector4 Vector4::ywxx() const { return Vector4 (y, w, x, x); }
-Vector4 Vector4::zwxx() const { return Vector4 (z, w, x, x); }
-Vector4 Vector4::wwxx() const { return Vector4 (w, w, x, x); }
-Vector4 Vector4::xxyx() const { return Vector4 (x, x, y, x); }
-Vector4 Vector4::yxyx() const { return Vector4 (y, x, y, x); }
-Vector4 Vector4::zxyx() const { return Vector4 (z, x, y, x); }
-Vector4 Vector4::wxyx() const { return Vector4 (w, x, y, x); }
-Vector4 Vector4::xyyx() const { return Vector4 (x, y, y, x); }
-Vector4 Vector4::yyyx() const { return Vector4 (y, y, y, x); }
-Vector4 Vector4::zyyx() const { return Vector4 (z, y, y, x); }
-Vector4 Vector4::wyyx() const { return Vector4 (w, y, y, x); }
-Vector4 Vector4::xzyx() const { return Vector4 (x, z, y, x); }
-Vector4 Vector4::yzyx() const { return Vector4 (y, z, y, x); }
-Vector4 Vector4::zzyx() const { return Vector4 (z, z, y, x); }
-Vector4 Vector4::wzyx() const { return Vector4 (w, z, y, x); }
-Vector4 Vector4::xwyx() const { return Vector4 (x, w, y, x); }
-Vector4 Vector4::ywyx() const { return Vector4 (y, w, y, x); }
-Vector4 Vector4::zwyx() const { return Vector4 (z, w, y, x); }
-Vector4 Vector4::wwyx() const { return Vector4 (w, w, y, x); }
-Vector4 Vector4::xxzx() const { return Vector4 (x, x, z, x); }
-Vector4 Vector4::yxzx() const { return Vector4 (y, x, z, x); }
-Vector4 Vector4::zxzx() const { return Vector4 (z, x, z, x); }
-Vector4 Vector4::wxzx() const { return Vector4 (w, x, z, x); }
-Vector4 Vector4::xyzx() const { return Vector4 (x, y, z, x); }
-Vector4 Vector4::yyzx() const { return Vector4 (y, y, z, x); }
-Vector4 Vector4::zyzx() const { return Vector4 (z, y, z, x); }
-Vector4 Vector4::wyzx() const { return Vector4 (w, y, z, x); }
-Vector4 Vector4::xzzx() const { return Vector4 (x, z, z, x); }
-Vector4 Vector4::yzzx() const { return Vector4 (y, z, z, x); }
-Vector4 Vector4::zzzx() const { return Vector4 (z, z, z, x); }
-Vector4 Vector4::wzzx() const { return Vector4 (w, z, z, x); }
-Vector4 Vector4::xwzx() const { return Vector4 (x, w, z, x); }
-Vector4 Vector4::ywzx() const { return Vector4 (y, w, z, x); }
-Vector4 Vector4::zwzx() const { return Vector4 (z, w, z, x); }
-Vector4 Vector4::wwzx() const { return Vector4 (w, w, z, x); }
-Vector4 Vector4::xxwx() const { return Vector4 (x, x, w, x); }
-Vector4 Vector4::yxwx() const { return Vector4 (y, x, w, x); }
-Vector4 Vector4::zxwx() const { return Vector4 (z, x, w, x); }
-Vector4 Vector4::wxwx() const { return Vector4 (w, x, w, x); }
-Vector4 Vector4::xywx() const { return Vector4 (x, y, w, x); }
-Vector4 Vector4::yywx() const { return Vector4 (y, y, w, x); }
-Vector4 Vector4::zywx() const { return Vector4 (z, y, w, x); }
-Vector4 Vector4::wywx() const { return Vector4 (w, y, w, x); }
-Vector4 Vector4::xzwx() const { return Vector4 (x, z, w, x); }
-Vector4 Vector4::yzwx() const { return Vector4 (y, z, w, x); }
-Vector4 Vector4::zzwx() const { return Vector4 (z, z, w, x); }
-Vector4 Vector4::wzwx() const { return Vector4 (w, z, w, x); }
-Vector4 Vector4::xwwx() const { return Vector4 (x, w, w, x); }
-Vector4 Vector4::ywwx() const { return Vector4 (y, w, w, x); }
-Vector4 Vector4::zwwx() const { return Vector4 (z, w, w, x); }
-Vector4 Vector4::wwwx() const { return Vector4 (w, w, w, x); }
-Vector4 Vector4::xxxy() const { return Vector4 (x, x, x, y); }
-Vector4 Vector4::yxxy() const { return Vector4 (y, x, x, y); }
-Vector4 Vector4::zxxy() const { return Vector4 (z, x, x, y); }
-Vector4 Vector4::wxxy() const { return Vector4 (w, x, x, y); }
-Vector4 Vector4::xyxy() const { return Vector4 (x, y, x, y); }
-Vector4 Vector4::yyxy() const { return Vector4 (y, y, x, y); }
-Vector4 Vector4::zyxy() const { return Vector4 (z, y, x, y); }
-Vector4 Vector4::wyxy() const { return Vector4 (w, y, x, y); }
-Vector4 Vector4::xzxy() const { return Vector4 (x, z, x, y); }
-Vector4 Vector4::yzxy() const { return Vector4 (y, z, x, y); }
-Vector4 Vector4::zzxy() const { return Vector4 (z, z, x, y); }
-Vector4 Vector4::wzxy() const { return Vector4 (w, z, x, y); }
-Vector4 Vector4::xwxy() const { return Vector4 (x, w, x, y); }
-Vector4 Vector4::ywxy() const { return Vector4 (y, w, x, y); }
-Vector4 Vector4::zwxy() const { return Vector4 (z, w, x, y); }
-Vector4 Vector4::wwxy() const { return Vector4 (w, w, x, y); }
-Vector4 Vector4::xxyy() const { return Vector4 (x, x, y, y); }
-Vector4 Vector4::yxyy() const { return Vector4 (y, x, y, y); }
-Vector4 Vector4::zxyy() const { return Vector4 (z, x, y, y); }
-Vector4 Vector4::wxyy() const { return Vector4 (w, x, y, y); }
-Vector4 Vector4::xyyy() const { return Vector4 (x, y, y, y); }
-Vector4 Vector4::yyyy() const { return Vector4 (y, y, y, y); }
-Vector4 Vector4::zyyy() const { return Vector4 (z, y, y, y); }
-Vector4 Vector4::wyyy() const { return Vector4 (w, y, y, y); }
-Vector4 Vector4::xzyy() const { return Vector4 (x, z, y, y); }
-Vector4 Vector4::yzyy() const { return Vector4 (y, z, y, y); }
-Vector4 Vector4::zzyy() const { return Vector4 (z, z, y, y); }
-Vector4 Vector4::wzyy() const { return Vector4 (w, z, y, y); }
-Vector4 Vector4::xwyy() const { return Vector4 (x, w, y, y); }
-Vector4 Vector4::ywyy() const { return Vector4 (y, w, y, y); }
-Vector4 Vector4::zwyy() const { return Vector4 (z, w, y, y); }
-Vector4 Vector4::wwyy() const { return Vector4 (w, w, y, y); }
-Vector4 Vector4::xxzy() const { return Vector4 (x, x, z, y); }
-Vector4 Vector4::yxzy() const { return Vector4 (y, x, z, y); }
-Vector4 Vector4::zxzy() const { return Vector4 (z, x, z, y); }
-Vector4 Vector4::wxzy() const { return Vector4 (w, x, z, y); }
-Vector4 Vector4::xyzy() const { return Vector4 (x, y, z, y); }
-Vector4 Vector4::yyzy() const { return Vector4 (y, y, z, y); }
-Vector4 Vector4::zyzy() const { return Vector4 (z, y, z, y); }
-Vector4 Vector4::wyzy() const { return Vector4 (w, y, z, y); }
-Vector4 Vector4::xzzy() const { return Vector4 (x, z, z, y); }
-Vector4 Vector4::yzzy() const { return Vector4 (y, z, z, y); }
-Vector4 Vector4::zzzy() const { return Vector4 (z, z, z, y); }
-Vector4 Vector4::wzzy() const { return Vector4 (w, z, z, y); }
-Vector4 Vector4::xwzy() const { return Vector4 (x, w, z, y); }
-Vector4 Vector4::ywzy() const { return Vector4 (y, w, z, y); }
-Vector4 Vector4::zwzy() const { return Vector4 (z, w, z, y); }
-Vector4 Vector4::wwzy() const { return Vector4 (w, w, z, y); }
-Vector4 Vector4::xxwy() const { return Vector4 (x, x, w, y); }
-Vector4 Vector4::yxwy() const { return Vector4 (y, x, w, y); }
-Vector4 Vector4::zxwy() const { return Vector4 (z, x, w, y); }
-Vector4 Vector4::wxwy() const { return Vector4 (w, x, w, y); }
-Vector4 Vector4::xywy() const { return Vector4 (x, y, w, y); }
-Vector4 Vector4::yywy() const { return Vector4 (y, y, w, y); }
-Vector4 Vector4::zywy() const { return Vector4 (z, y, w, y); }
-Vector4 Vector4::wywy() const { return Vector4 (w, y, w, y); }
-Vector4 Vector4::xzwy() const { return Vector4 (x, z, w, y); }
-Vector4 Vector4::yzwy() const { return Vector4 (y, z, w, y); }
-Vector4 Vector4::zzwy() const { return Vector4 (z, z, w, y); }
-Vector4 Vector4::wzwy() const { return Vector4 (w, z, w, y); }
-Vector4 Vector4::xwwy() const { return Vector4 (x, w, w, y); }
-Vector4 Vector4::ywwy() const { return Vector4 (y, w, w, y); }
-Vector4 Vector4::zwwy() const { return Vector4 (z, w, w, y); }
-Vector4 Vector4::wwwy() const { return Vector4 (w, w, w, y); }
-Vector4 Vector4::xxxz() const { return Vector4 (x, x, x, z); }
-Vector4 Vector4::yxxz() const { return Vector4 (y, x, x, z); }
-Vector4 Vector4::zxxz() const { return Vector4 (z, x, x, z); }
-Vector4 Vector4::wxxz() const { return Vector4 (w, x, x, z); }
-Vector4 Vector4::xyxz() const { return Vector4 (x, y, x, z); }
-Vector4 Vector4::yyxz() const { return Vector4 (y, y, x, z); }
-Vector4 Vector4::zyxz() const { return Vector4 (z, y, x, z); }
-Vector4 Vector4::wyxz() const { return Vector4 (w, y, x, z); }
-Vector4 Vector4::xzxz() const { return Vector4 (x, z, x, z); }
-Vector4 Vector4::yzxz() const { return Vector4 (y, z, x, z); }
-Vector4 Vector4::zzxz() const { return Vector4 (z, z, x, z); }
-Vector4 Vector4::wzxz() const { return Vector4 (w, z, x, z); }
-Vector4 Vector4::xwxz() const { return Vector4 (x, w, x, z); }
-Vector4 Vector4::ywxz() const { return Vector4 (y, w, x, z); }
-Vector4 Vector4::zwxz() const { return Vector4 (z, w, x, z); }
-Vector4 Vector4::wwxz() const { return Vector4 (w, w, x, z); }
-Vector4 Vector4::xxyz() const { return Vector4 (x, x, y, z); }
-Vector4 Vector4::yxyz() const { return Vector4 (y, x, y, z); }
-Vector4 Vector4::zxyz() const { return Vector4 (z, x, y, z); }
-Vector4 Vector4::wxyz() const { return Vector4 (w, x, y, z); }
-Vector4 Vector4::xyyz() const { return Vector4 (x, y, y, z); }
-Vector4 Vector4::yyyz() const { return Vector4 (y, y, y, z); }
-Vector4 Vector4::zyyz() const { return Vector4 (z, y, y, z); }
-Vector4 Vector4::wyyz() const { return Vector4 (w, y, y, z); }
-Vector4 Vector4::xzyz() const { return Vector4 (x, z, y, z); }
-Vector4 Vector4::yzyz() const { return Vector4 (y, z, y, z); }
-Vector4 Vector4::zzyz() const { return Vector4 (z, z, y, z); }
-Vector4 Vector4::wzyz() const { return Vector4 (w, z, y, z); }
-Vector4 Vector4::xwyz() const { return Vector4 (x, w, y, z); }
-Vector4 Vector4::ywyz() const { return Vector4 (y, w, y, z); }
-Vector4 Vector4::zwyz() const { return Vector4 (z, w, y, z); }
-Vector4 Vector4::wwyz() const { return Vector4 (w, w, y, z); }
-Vector4 Vector4::xxzz() const { return Vector4 (x, x, z, z); }
-Vector4 Vector4::yxzz() const { return Vector4 (y, x, z, z); }
-Vector4 Vector4::zxzz() const { return Vector4 (z, x, z, z); }
-Vector4 Vector4::wxzz() const { return Vector4 (w, x, z, z); }
-Vector4 Vector4::xyzz() const { return Vector4 (x, y, z, z); }
-Vector4 Vector4::yyzz() const { return Vector4 (y, y, z, z); }
-Vector4 Vector4::zyzz() const { return Vector4 (z, y, z, z); }
-Vector4 Vector4::wyzz() const { return Vector4 (w, y, z, z); }
-Vector4 Vector4::xzzz() const { return Vector4 (x, z, z, z); }
-Vector4 Vector4::yzzz() const { return Vector4 (y, z, z, z); }
-Vector4 Vector4::zzzz() const { return Vector4 (z, z, z, z); }
-Vector4 Vector4::wzzz() const { return Vector4 (w, z, z, z); }
-Vector4 Vector4::xwzz() const { return Vector4 (x, w, z, z); }
-Vector4 Vector4::ywzz() const { return Vector4 (y, w, z, z); }
-Vector4 Vector4::zwzz() const { return Vector4 (z, w, z, z); }
-Vector4 Vector4::wwzz() const { return Vector4 (w, w, z, z); }
-Vector4 Vector4::xxwz() const { return Vector4 (x, x, w, z); }
-Vector4 Vector4::yxwz() const { return Vector4 (y, x, w, z); }
-Vector4 Vector4::zxwz() const { return Vector4 (z, x, w, z); }
-Vector4 Vector4::wxwz() const { return Vector4 (w, x, w, z); }
-Vector4 Vector4::xywz() const { return Vector4 (x, y, w, z); }
-Vector4 Vector4::yywz() const { return Vector4 (y, y, w, z); }
-Vector4 Vector4::zywz() const { return Vector4 (z, y, w, z); }
-Vector4 Vector4::wywz() const { return Vector4 (w, y, w, z); }
-Vector4 Vector4::xzwz() const { return Vector4 (x, z, w, z); }
-Vector4 Vector4::yzwz() const { return Vector4 (y, z, w, z); }
-Vector4 Vector4::zzwz() const { return Vector4 (z, z, w, z); }
-Vector4 Vector4::wzwz() const { return Vector4 (w, z, w, z); }
-Vector4 Vector4::xwwz() const { return Vector4 (x, w, w, z); }
-Vector4 Vector4::ywwz() const { return Vector4 (y, w, w, z); }
-Vector4 Vector4::zwwz() const { return Vector4 (z, w, w, z); }
-Vector4 Vector4::wwwz() const { return Vector4 (w, w, w, z); }
-Vector4 Vector4::xxxw() const { return Vector4 (x, x, x, w); }
-Vector4 Vector4::yxxw() const { return Vector4 (y, x, x, w); }
-Vector4 Vector4::zxxw() const { return Vector4 (z, x, x, w); }
-Vector4 Vector4::wxxw() const { return Vector4 (w, x, x, w); }
-Vector4 Vector4::xyxw() const { return Vector4 (x, y, x, w); }
-Vector4 Vector4::yyxw() const { return Vector4 (y, y, x, w); }
-Vector4 Vector4::zyxw() const { return Vector4 (z, y, x, w); }
-Vector4 Vector4::wyxw() const { return Vector4 (w, y, x, w); }
-Vector4 Vector4::xzxw() const { return Vector4 (x, z, x, w); }
-Vector4 Vector4::yzxw() const { return Vector4 (y, z, x, w); }
-Vector4 Vector4::zzxw() const { return Vector4 (z, z, x, w); }
-Vector4 Vector4::wzxw() const { return Vector4 (w, z, x, w); }
-Vector4 Vector4::xwxw() const { return Vector4 (x, w, x, w); }
-Vector4 Vector4::ywxw() const { return Vector4 (y, w, x, w); }
-Vector4 Vector4::zwxw() const { return Vector4 (z, w, x, w); }
-Vector4 Vector4::wwxw() const { return Vector4 (w, w, x, w); }
-Vector4 Vector4::xxyw() const { return Vector4 (x, x, y, w); }
-Vector4 Vector4::yxyw() const { return Vector4 (y, x, y, w); }
-Vector4 Vector4::zxyw() const { return Vector4 (z, x, y, w); }
-Vector4 Vector4::wxyw() const { return Vector4 (w, x, y, w); }
-Vector4 Vector4::xyyw() const { return Vector4 (x, y, y, w); }
-Vector4 Vector4::yyyw() const { return Vector4 (y, y, y, w); }
-Vector4 Vector4::zyyw() const { return Vector4 (z, y, y, w); }
-Vector4 Vector4::wyyw() const { return Vector4 (w, y, y, w); }
-Vector4 Vector4::xzyw() const { return Vector4 (x, z, y, w); }
-Vector4 Vector4::yzyw() const { return Vector4 (y, z, y, w); }
-Vector4 Vector4::zzyw() const { return Vector4 (z, z, y, w); }
-Vector4 Vector4::wzyw() const { return Vector4 (w, z, y, w); }
-Vector4 Vector4::xwyw() const { return Vector4 (x, w, y, w); }
-Vector4 Vector4::ywyw() const { return Vector4 (y, w, y, w); }
-Vector4 Vector4::zwyw() const { return Vector4 (z, w, y, w); }
-Vector4 Vector4::wwyw() const { return Vector4 (w, w, y, w); }
-Vector4 Vector4::xxzw() const { return Vector4 (x, x, z, w); }
-Vector4 Vector4::yxzw() const { return Vector4 (y, x, z, w); }
-Vector4 Vector4::zxzw() const { return Vector4 (z, x, z, w); }
-Vector4 Vector4::wxzw() const { return Vector4 (w, x, z, w); }
-Vector4 Vector4::xyzw() const { return Vector4 (x, y, z, w); }
-Vector4 Vector4::yyzw() const { return Vector4 (y, y, z, w); }
-Vector4 Vector4::zyzw() const { return Vector4 (z, y, z, w); }
-Vector4 Vector4::wyzw() const { return Vector4 (w, y, z, w); }
-Vector4 Vector4::xzzw() const { return Vector4 (x, z, z, w); }
-Vector4 Vector4::yzzw() const { return Vector4 (y, z, z, w); }
-Vector4 Vector4::zzzw() const { return Vector4 (z, z, z, w); }
-Vector4 Vector4::wzzw() const { return Vector4 (w, z, z, w); }
-Vector4 Vector4::xwzw() const { return Vector4 (x, w, z, w); }
-Vector4 Vector4::ywzw() const { return Vector4 (y, w, z, w); }
-Vector4 Vector4::zwzw() const { return Vector4 (z, w, z, w); }
-Vector4 Vector4::wwzw() const { return Vector4 (w, w, z, w); }
-Vector4 Vector4::xxww() const { return Vector4 (x, x, w, w); }
-Vector4 Vector4::yxww() const { return Vector4 (y, x, w, w); }
-Vector4 Vector4::zxww() const { return Vector4 (z, x, w, w); }
-Vector4 Vector4::wxww() const { return Vector4 (w, x, w, w); }
-Vector4 Vector4::xyww() const { return Vector4 (x, y, w, w); }
-Vector4 Vector4::yyww() const { return Vector4 (y, y, w, w); }
-Vector4 Vector4::zyww() const { return Vector4 (z, y, w, w); }
-Vector4 Vector4::wyww() const { return Vector4 (w, y, w, w); }
-Vector4 Vector4::xzww() const { return Vector4 (x, z, w, w); }
-Vector4 Vector4::yzww() const { return Vector4 (y, z, w, w); }
-Vector4 Vector4::zzww() const { return Vector4 (z, z, w, w); }
-Vector4 Vector4::wzww() const { return Vector4 (w, z, w, w); }
-Vector4 Vector4::xwww() const { return Vector4 (x, w, w, w); }
-Vector4 Vector4::ywww() const { return Vector4 (y, w, w, w); }
-Vector4 Vector4::zwww() const { return Vector4 (z, w, w, w); }
-Vector4 Vector4::wwww() const { return Vector4 (w, w, w, w); }
-
-
-}; // namespace
diff --git a/externals/g3dlite/debugAssert.cpp b/externals/g3dlite/debugAssert.cpp
deleted file mode 100644
index a87161b261f..00000000000
--- a/externals/g3dlite/debugAssert.cpp
+++ /dev/null
@@ -1,389 +0,0 @@
-/**
- @file debugAssert.cpp
-
- Windows implementation of assertion routines.
-
- @maintainer Morgan McGuire, graphics3d.com
-
- @created 2001-08-26
- @edited 2009-06-02
- */
-
-#include "G3D/debugAssert.h"
-#include "G3D/platform.h"
-#ifdef G3D_WIN32
- #include <tchar.h>
-#endif
-#include "G3D/format.h"
-#include "G3D/prompt.h"
-#include <string>
-#include "G3D/debugPrintf.h"
-#include "G3D/Log.h"
-
-#include <cstdlib>
-
-#ifdef _MSC_VER
- // disable: "C++ exception handler used"
-# pragma warning (push)
-# pragma warning (disable : 4530)
-#endif
-
-using namespace std;
-
-namespace G3D { namespace _internal {
-
-ConsolePrintHook _consolePrintHook;
-AssertionHook _debugHook = _handleDebugAssert_;
-AssertionHook _failureHook = _handleErrorCheck_;
-
-#ifdef G3D_LINUX
-#if SOMEONE_MADE_THIS_USEFUL
- Display* x11Display = NULL;
- Window x11Window = 0;
-#endif
-#endif
-
-
-#ifdef G3D_WIN32
-static void postToClipboard(const char *text) {
- if (OpenClipboard(NULL)) {
- HGLOBAL hMem = GlobalAlloc(GHND | GMEM_DDESHARE, strlen(text) + 1);
- if (hMem) {
- char *pMem = (char*)GlobalLock(hMem);
- strcpy(pMem, text);
- GlobalUnlock(hMem);
-
- EmptyClipboard();
- SetClipboardData(CF_TEXT, hMem);
- }
-
- CloseClipboard();
- GlobalFree(hMem);
- }
-}
-#endif
-
-/**
- outTitle should be set before the call
- */
-static void createErrorMessage(
- const char* expression,
- const std::string& message,
- const char* filename,
- int lineNumber,
- std::string& outTitle,
- std::string& outMessage) {
-
- std::string le = "";
- const char* newline = "\n";
-
- #ifdef G3D_WIN32
- newline = "\r\n";
-
- // The last error value. (Which is preserved across the call).
- DWORD lastErr = GetLastError();
-
- // The decoded message from FormatMessage
- LPTSTR formatMsg = NULL;
-
- if (NULL == formatMsg) {
- FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
- FORMAT_MESSAGE_IGNORE_INSERTS |
- FORMAT_MESSAGE_FROM_SYSTEM,
- NULL,
- lastErr,
- 0,
- (LPTSTR)&formatMsg,
- 0,
- NULL);
- }
-
- // Make sure the message got translated into something.
- LPTSTR realLastErr;
- if (NULL != formatMsg) {
- realLastErr = formatMsg;
- } else {
- realLastErr = _T("Last error code does not exist.");
- }
-
- if (lastErr != 0) {
- le = G3D::format("Last Error (0x%08X): %s\r\n\r\n", lastErr, (LPCSTR)realLastErr);
- }
-
- // Get rid of the allocated memory from FormatMessage.
- if (NULL != formatMsg) {
- LocalFree((LPVOID)formatMsg);
- }
-
- char modulePath[MAX_PATH];
- GetModuleFileNameA(NULL, modulePath, MAX_PATH);
-
- const char* moduleName = strrchr(modulePath, '\\');
- outTitle = outTitle + string(" - ") + string(moduleName ? (moduleName + 1) : modulePath);
-
- #endif
-
- // Build the message.
- outMessage =
- G3D::format("%s%s%sExpression: %s%s%s:%d%s%s%s",
- message.c_str(), newline, newline, expression, newline,
- filename, lineNumber, newline, newline, le.c_str());
-}
-
-
-bool _handleDebugAssert_(
- const char* expression,
- const std::string& message,
- const char* filename,
- int lineNumber,
- bool useGuiPrompt) {
-
- std::string dialogTitle = "Assertion Failure";
- std::string dialogText = "";
- createErrorMessage(expression, message, filename, lineNumber, dialogTitle, dialogText);
-
- #ifdef G3D_WIN32
- DWORD lastErr = GetLastError();
- postToClipboard(dialogText.c_str());
- debugPrintf("\n%s\n", dialogText.c_str());
- #endif
-
- const int cBreak = 0;
- const int cIgnore = 1;
- const int cAbort = 2;
-
- static const char* choices[] = {"Debug", "Ignore", "Exit"};
-
- // Log the error
- Log::common()->print(std::string("\n**************************\n\n") + dialogTitle + "\n" + dialogText);
-
- int result = G3D::prompt(dialogTitle.c_str(), dialogText.c_str(), (const char**)choices, 3, useGuiPrompt);
-
-# ifdef G3D_WIN32
- // Put the incoming last error back.
- SetLastError(lastErr);
-# endif
-
- switch (result) {
- // -1 shouldn't actually occur because it means
- // that we're in release mode.
- case -1:
- case cBreak:
- return true;
- break;
-
- case cIgnore:
- return false;
- break;
-
- case cAbort:
- exit(-1);
- break;
- }
-
- // Should never get here
- return false;
-}
-
-
-bool _handleErrorCheck_(
- const char* expression,
- const std::string& message,
- const char* filename,
- int lineNumber,
- bool useGuiPrompt) {
-
- std::string dialogTitle = "Critical Error";
- std::string dialogText = "";
-
- createErrorMessage(expression, message, filename, lineNumber, dialogTitle, dialogText);
-
- // Log the error
- Log::common()->print(std::string("\n**************************\n\n") + dialogTitle + "\n" + dialogText);
- #ifdef G3D_WIN32
- DWORD lastErr = GetLastError();
- (void)lastErr;
- postToClipboard(dialogText.c_str());
- debugPrintf("\n%s\n", dialogText.c_str());
- #endif
-
- static const char* choices[] = {"Ok"};
-
- const std::string& m =
- std::string("An internal error has occured in this program and it will now close. "
- "The specific error is below. More information has been saved in \"") +
- Log::getCommonLogFilename() + "\".\n" + dialogText;
-
- int result = G3D::prompt("Error", m.c_str(), (const char**)choices, 1, useGuiPrompt);
- (void)result;
-
- return true;
-}
-
-
-#ifdef G3D_WIN32
-static HCURSOR oldCursor;
-static RECT oldCursorRect;
-static POINT oldCursorPos;
-static int oldShowCursorCount;
-#endif
-
-void _releaseInputGrab_() {
- #ifdef G3D_WIN32
-
- GetCursorPos(&oldCursorPos);
-
- // Stop hiding the cursor if the application hid it.
- oldShowCursorCount = ShowCursor(true) - 1;
-
- if (oldShowCursorCount < -1) {
- for (int c = oldShowCursorCount; c < -1; ++c) {
- ShowCursor(true);
- }
- }
-
- // Set the default cursor in case the application
- // set the cursor to NULL.
- oldCursor = GetCursor();
- SetCursor(LoadCursor(NULL, IDC_ARROW));
-
- // Allow the cursor full access to the screen
- GetClipCursor(&oldCursorRect);
- ClipCursor(NULL);
-
- #elif defined(G3D_LINUX)
-#if SOMEONE_MADE_THIS_USEFUL
- if (x11Display != NULL) {
- XUngrabPointer(x11Display, CurrentTime);
- XUngrabKeyboard(x11Display, CurrentTime);
- if (x11Window != 0) {
- //XUndefineCursor(x11Display, x11Window);
- // TODO: Note that we leak this cursor; it should be
- // freed in the restore code.
- Cursor c = XCreateFontCursor(x11Display, 68);
- XDefineCursor(x11Display, x11Window, c);
- }
- XSync(x11Display, false);
- XAllowEvents(x11Display, AsyncPointer, CurrentTime);
- XFlush(x11Display);
- }
-#endif
- #elif defined(G3D_OSX)
- // TODO: OS X
- #endif
-}
-
-
-void _restoreInputGrab_() {
- #ifdef G3D_WIN32
-
- // Restore the old clipping region
- ClipCursor(&oldCursorRect);
-
- SetCursorPos(oldCursorPos.x, oldCursorPos.y);
-
- // Restore the old cursor
- SetCursor(oldCursor);
-
- // Restore old visibility count
- if (oldShowCursorCount < 0) {
- for (int c = 0; c > oldShowCursorCount; --c) {
- ShowCursor(false);
- }
- }
-
- #elif defined(G3D_LINUX)
- // TODO: Linux
- #elif defined(G3D_OSX)
- // TODO: OS X
- #endif
-}
-
-
-}; // internal namespace
-
-void setAssertionHook(AssertionHook hook) {
- G3D::_internal::_debugHook = hook;
-}
-
-AssertionHook assertionHook() {
- return G3D::_internal::_debugHook;
-}
-
-void setFailureHook(AssertionHook hook) {
- G3D::_internal::_failureHook = hook;
-}
-
-AssertionHook failureHook() {
- return G3D::_internal::_failureHook;
-}
-
-
-void setConsolePrintHook(ConsolePrintHook h) {
- G3D::_internal::_consolePrintHook = h;
-}
-
-ConsolePrintHook consolePrintHook() {
- return G3D::_internal::_consolePrintHook;
-}
-
-
-std::string __cdecl debugPrint(const std::string& s) {
-# ifdef G3D_WIN32
- const int MAX_STRING_LEN = 1024;
-
- // Windows can't handle really long strings sent to
- // the console, so we break the string.
- if (s.size() < MAX_STRING_LEN) {
- OutputDebugStringA(s.c_str());
- } else {
- for (unsigned int i = 0; i < s.size(); i += MAX_STRING_LEN) {
- std::string sub = s.substr(i, MAX_STRING_LEN);
- OutputDebugStringA(sub.c_str());
- }
- }
-# else
- fprintf(stderr, "%s", s.c_str());
- fflush(stderr);
-# endif
-
- return s;
-}
-
-std::string __cdecl debugPrintf(const char* fmt ...) {
- va_list argList;
- va_start(argList, fmt);
- std::string s = G3D::vformat(fmt, argList);
- va_end(argList);
-
- return debugPrint(s);
-// return debugPrint(consolePrint(s));
-}
-
-std::string consolePrint(const std::string& s) {
- FILE* L = Log::common()->getFile();
- fprintf(L, "%s", s.c_str());
-
- if (consolePrintHook()) {
- consolePrintHook()(s);
- }
-
- fflush(L);
- return s;
-}
-
-
-std::string __cdecl consolePrintf(const char* fmt ...) {
- va_list argList;
- va_start(argList, fmt);
- std::string s = G3D::vformat(fmt, argList);
- va_end(argList);
-
- return consolePrint(s);
-}
-
-} // namespace
-
-#ifdef _MSC_VER
-# pragma warning (pop)
-#endif
diff --git a/externals/g3dlite/fileutils.cpp b/externals/g3dlite/fileutils.cpp
deleted file mode 100644
index 3f5eb579ba9..00000000000
--- a/externals/g3dlite/fileutils.cpp
+++ /dev/null
@@ -1,1165 +0,0 @@
-/**
- @file fileutils.cpp
-
- @author Morgan McGuire, graphics3d.com
-
- @author 2002-06-06
- @edited 2010-02-05
- */
-
-#include <cstring>
-#include <cstdio>
-#include "G3D/platform.h"
-#include "G3D/fileutils.h"
-#include "G3D/BinaryInput.h"
-#include "G3D/BinaryOutput.h"
-#include "G3D/g3dmath.h"
-#include "G3D/stringutils.h"
-#include "G3D/Set.h"
-#include "G3D/g3dfnmatch.h"
-
-#include <sys/stat.h>
-#include <sys/types.h>
-#if _HAVE_ZIP
- #include "zip.h"
-#endif
-
-#ifdef G3D_WIN32
- // Needed for _getcwd
- #include <direct.h>
- #include <io.h>
-#else
- #include <dirent.h>
- #include <fnmatch.h>
- #include <unistd.h>
- #define _getcwd getcwd
- #define _stat stat
-#endif
-
-
-namespace G3D {
-
-namespace _internal {
- Set<std::string> currentFilesUsed;
-}
-
-std::string pathConcat(const std::string& dirname, const std::string& file) {
- // Ensure that the directory ends in a slash
- if ((dirname.size() != 0) &&
- (dirname[dirname.size() - 1] != '/') &&
- (dirname[dirname.size() - 1] != '\\') &&
- (dirname[dirname.size() - 1] != ':')) {
- return dirname + '/' + file;
- } else {
- return dirname + file;
- }
-}
-
-std::string resolveFilename(const std::string& filename) {
- if (filename.size() >= 1) {
- if ((filename[0] == '/') || (filename[0] == '\\')) {
- // Already resolved
- return filename;
- } else {
-
- #ifdef G3D_WIN32
- if ((filename.size() >= 2) && (filename[1] == ':')) {
- // There is a drive spec on the front.
- if ((filename.size() >= 3) && ((filename[2] == '\\') ||
- (filename[2] == '/'))) {
- // Already fully qualified
- return filename;
- } else {
- // The drive spec is relative to the
- // working directory on that drive.
- debugAssertM(false, "Files of the form d:path are"
- " not supported (use a fully qualified"
- " name).");
- return filename;
- }
- }
- #endif
- }
- }
-
- char buffer[1024];
-
- // Prepend the working directory.
- _getcwd(buffer, 1024);
-
- return format("%s/%s", buffer, filename.c_str());
-}
-
-bool zipfileExists(const std::string& filename) {
- std::string outZipfile;
- std::string outInternalFile;
- return zipfileExists(filename, outZipfile, outInternalFile);
-}
-
-std::string readWholeFile(
- const std::string& filename) {
-
- _internal::currentFilesUsed.insert(filename);
-
- std::string s;
-
- debugAssert(filename != "");
- if (fileExists(filename, false)) {
-
- int64 length = fileLength(filename);
-
- char* buffer = (char*)System::alignedMalloc(length + 1, 16);
- debugAssert(buffer);
- FILE* f = fopen(filename.c_str(), "rb");
- debugAssert(f);
- int ret = fread(buffer, 1, length, f);
- debugAssert(ret == length);(void)ret;
- fclose(f);
-
- buffer[length] = '\0';
- s = std::string(buffer);
-
- System::alignedFree(buffer);
-
- } else if (zipfileExists(filename)) {
-
- void* zipBuffer;
- size_t length;
- zipRead(filename, zipBuffer, length);
-
- char* buffer = (char*)System::alignedMalloc(length + 1, 16);
- System::memcpy(buffer,zipBuffer, length + 1);
- zipClose(zipBuffer);
-
- buffer[length] = '\0';
- s = std::string(buffer);
- System::alignedFree(buffer);
- } else {
- debugAssertM(false, filename + " not found");
- }
-
- return s;
-}
-
-
-void zipRead(const std::string& file,
- void*& data,
- size_t& length) {
- std::string zip, desiredFile;
-#if _HAVE_ZIP
- if (zipfileExists(file, zip, desiredFile)) {
- struct zip *z = zip_open( zip.c_str(), ZIP_CHECKCONS, NULL );
- {
- struct zip_stat info;
- zip_stat_init( &info ); // TODO: Docs unclear if zip_stat_init is required.
- zip_stat( z, desiredFile.c_str(), ZIP_FL_NOCASE, &info );
- length = info.size;
- // sets machines up to use MMX, if they want
- data = System::alignedMalloc(length, 16);
- struct zip_file *zf = zip_fopen( z, desiredFile.c_str(), ZIP_FL_NOCASE );
- {
- int test = zip_fread( zf, data, length );
- debugAssertM((size_t)test == length,
- desiredFile + " was corrupt because it unzipped to the wrong size.");
- (void)test;
- }
- zip_fclose( zf );
- }
- zip_close( z );
- } else {
- data = NULL;
- }
-#else
- data = NULL;
-#endif
-}
-
-
-void zipClose(void* data) {
- System::alignedFree(data);
-}
-
-
-int64 fileLength(const std::string& filename) {
- struct _stat st;
- int result = _stat(filename.c_str(), &st);
-
- if (result == -1) {
-#if _HAVE_ZIP
- std::string zip, contents;
- if(zipfileExists(filename, zip, contents)){
- int64 requiredMem;
-
- struct zip *z = zip_open( zip.c_str(), ZIP_CHECKCONS, NULL );
- debugAssertM(z != NULL, zip + ": zip open failed.");
- {
- struct zip_stat info;
- zip_stat_init( &info ); // TODO: Docs unclear if zip_stat_init is required.
- int success = zip_stat( z, contents.c_str(), ZIP_FL_NOCASE, &info );
- debugAssertM(success == 0, zip + ": " + contents + ": zip stat failed.");
- requiredMem = info.size;
- }
- zip_close( z );
- return requiredMem;
- } else {
- return -1;
- }
-#else
- return -1;
-#endif
- }
-
- return st.st_size;
-}
-
-/** Used by robustTmpfile. Returns nonzero if fread, fwrite, and fseek all
-succeed on the file.
- @author Morgan McGuire, http://graphics.cs.williams.edu */
-static int isFileGood(FILE* f) {
-
- int x, n, result;
-
- /* Must be a valid file handle */
- if (f == NULL) {
- return 0;
- }
-
- /* Try to write */
- x = 1234;
- n = fwrite(&x, sizeof(int), 1, f);
-
- if (n != 1) {
- return 0;
- }
-
- /* Seek back to the beginning */
- result = fseek(f, 0, SEEK_SET);
- if (result != 0) {
- return 0;
- }
-
- /* Read */
- n = fread(&x, sizeof(int), 1, f);
- if (n != 1) {
- return 0;
- }
-
- /* Seek back to the beginning again */
- fseek(f, 0, SEEK_SET);
-
- return 1;
-}
-
-FILE* createTempFile() {
- FILE* t = NULL;
-
-//# ifdef G3D_WIN32
- t = tmpfile();
-//# else
-// // On Unix, tmpfile generates a warning for any code that links against it.
-// const char* tempfilename = "/tmp/g3dtemp.XXXXXXXX";
-// mktemp(tempfilename);
-// t = fopen(tempfilename, "w");
-//# endif
-
-# ifdef _WIN32
- char* n = NULL;
-# endif
- char name[256];
-
- if (isFileGood(t)) {
- return t;
- }
-
-# ifdef G3D_WIN32
- /* tmpfile failed; try the tmpnam routine */
- t = fopen(tmpnam(NULL), "w+");
- if (isFileGood(t)) {
- return t;
- }
-
- n = _tempnam("c:/tmp/", "t");
- /* Try to create something in C:\tmp */
- t = fopen(n, "w+");
- if (isFileGood(t)) {
- return t;
- }
-
- /* Try c:\temp */
- n = _tempnam("c:/temp/", "t");
- t = fopen(n, "w+");
- if (isFileGood(t)) {
- return t;
- }
-
- /* try the current directory */
- n = _tempnam("./", "t");
- t = fopen(n, "w+");
- if (isFileGood(t)) {
- return t;
- }
-
- sprintf(name, "%s/tmp%d", "c:/temp", rand());
- t = fopen(name, "w+");
- if (isFileGood(t)) {
- return t;
- }
-
- /* Try some hardcoded paths */
- sprintf(name, "%s/tmp%d", "c:/tmp", rand());
- t = fopen(name, "w+");
- if (isFileGood(t)) {
- return t;
- }
-# else
- sprintf(name, "%s/tmp%d", "/tmp", rand());
- t = fopen(name, "w+");
- if (isFileGood(t)) {
- return t;
- }
-#endif
-
- sprintf(name, "tmp%d", rand());
- t = fopen(name, "w+");
- if (isFileGood(t)) {
- return t;
- }
-
- fprintf(stderr, "Unable to create a temporary file; robustTmpfile returning NULL\n");
-
- return NULL;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-void writeWholeFile(
- const std::string& filename,
- const std::string& str,
- bool flush) {
-
- // Make sure the directory exists.
- std::string root, base, ext, path;
- Array<std::string> pathArray;
- parseFilename(filename, root, pathArray, base, ext);
-
- path = root + stringJoin(pathArray, '/');
- if (! fileExists(path, false)) {
- createDirectory(path);
- }
-
- FILE* file = fopen(filename.c_str(), "wb");
-
- debugAssert(file);
-
- fwrite(str.c_str(), str.size(), 1, file);
-
- if (flush) {
- fflush(file);
- }
- fclose(file);
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-/**
- Creates the directory (which may optionally end in a /)
- and any parents needed to reach it.
- */
-void createDirectory(
- const std::string& dir) {
-
- if (dir == "") {
- return;
- }
-
- std::string d;
-
- // Add a trailing / if there isn't one.
- switch (dir[dir.size() - 1]) {
- case '/':
- case '\\':
- d = dir;
- break;
-
- default:
- d = dir + "/";
- }
-
- // If it already exists, do nothing
- if (fileExists(d.substr(0, d.size() - 1)), false) {
- return;
- }
-
- // Parse the name apart
- std::string root, base, ext;
- Array<std::string> path;
-
- std::string lead;
- parseFilename(d, root, path, base, ext);
- debugAssert(base == "");
- debugAssert(ext == "");
-
- // Begin with an extra period so "c:\" becomes "c:\.\" after
- // appending a path and "c:" becomes "c:.\", not root: "c:\"
- std::string p = root + ".";
-
- // Create any intermediate that doesn't exist
- for (int i = 0; i < path.size(); ++i) {
- p += "/" + path[i];
- if (! fileExists(p, false)) {
- // Windows only requires one argument to mkdir,
- // where as unix also requires the permissions.
-# ifndef G3D_WIN32
- mkdir(p.c_str(), 0777);
-# else
- _mkdir(p.c_str());
-# endif
- }
- }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-class FileSystemCache {
-private:
-
- Table<std::string, Array<std::string> > m_files;
-
-public:
-
- bool fileExists(const std::string& filename) {
- const std::string& path = resolveFilename(filenamePath(filename));
- const std::string& name = filenameBaseExt(filename);
-
- bool neverBeforeSeen = false;
- Array<std::string>& fileList = m_files.getCreate(path, neverBeforeSeen);
- if (neverBeforeSeen) {
- if (! G3D::fileExists(path, true, false)) {
- // The path itself doesn't exist... back out our insertion (which makes fileList& invalid)
- m_files.remove(path);
- return false;
- }
-
- std::string spec = pathConcat(path, "*");
-
- // Will automatically recurse into zipfiles
- getFiles(spec, fileList);
- getDirs(spec, fileList);
-
-# ifdef G3D_WIN32
- {
- // Case insensitive
- for (int i = 0; i < fileList.size(); ++i) {
- fileList[i] = toLower(fileList[i]);
- }
- }
-# endif
- }
-
- if (filenameContainsWildcards(name)) {
- // See if anything matches
- for (int i = 0; i < fileList.size(); ++i) {
- if (g3dfnmatch(name.c_str(), fileList[i].c_str(), 0) == 0) {
- return true;
- }
- }
- return false;
- } else {
- // On windows, this is a lower-lower comparison, so it is case insensitive
- return fileList.contains(name);
- }
- }
-
- void clear() {
- m_files.clear();
- }
-
- static FileSystemCache& instance() {
- static FileSystemCache i;
- return i;
- }
-};
-
-
-void clearFileSystemCache() {
- FileSystemCache::instance().clear();
-}
-
-bool fileExists
-(const std::string& _filename,
- bool lookInZipfiles,
- bool trustCache) {
-
- if (_filename.empty()) {
- return false;
- }
-
- // Remove trailing slash from directories
- const std::string& filename = (endsWith(_filename, "/") || endsWith(_filename, "\\")) ? _filename.substr(0, _filename.length() - 1) : _filename;
-
- if (trustCache && lookInZipfiles) {
-# ifdef G3D_WIN32
- // Case insensitive
- return FileSystemCache::instance().fileExists(toLower(filename));
-# else
- return FileSystemCache::instance().fileExists(filename);
-# endif
- }
-
- // Useful for debugging
- //char curdir[1024]; _getcwd(curdir, 1024);
-
- struct _stat st;
- int ret = _stat(filename.c_str(), &st);
-
- // _stat returns zero on success
- bool exists = (ret == 0);
-
- if (! exists && lookInZipfiles) {
- // Does not exist standalone, but might exist in a zipfile
-
- // These output arguments will be ignored
- std::string zipDir, internalPath;
- return zipfileExists(filename, zipDir, internalPath);
- } else {
- return exists;
- }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-#if _HAVE_ZIP
-/* Helper methods for zipfileExists()*/
-// Given a string (the drive) and an array (the path), computes the directory
-static void _zip_resolveDirectory(std::string& completeDir, const std::string& drive, const Array<std::string>& path, const int length){
- completeDir = drive;
- int tempLength;
- // if the given length is longer than the array, we correct it
- if(length > path.length()){
- tempLength = path.length();
- } else{
- tempLength = length;
- }
-
- for(int t = 0; t < tempLength; ++t){
- if(t > 0){
- completeDir += "/";
- }
- completeDir += path[t];
- }
-}
-
-
-// assumes that zipDir references a .zip file
-static bool _zip_zipContains(const std::string& zipDir, const std::string& desiredFile){
- struct zip *z = zip_open( zipDir.c_str(), ZIP_CHECKCONS, NULL );
- //the last parameter, an int, determines case sensitivity:
- //1 is sensitive, 2 is not, 0 is default
- int test = zip_name_locate( z, desiredFile.c_str(), ZIP_FL_NOCASE );
- zip_close( z );
- if(test == -1){
- return false;
- }
- return true;
-}
-#endif
-
-// If no zipfile exists, outZipfile and outInternalFile are unchanged
-bool zipfileExists(const std::string& filename, std::string& outZipfile,
- std::string& outInternalFile){
-#if _HAVE_ZIP
- Array<std::string> path;
- std::string drive, base, ext, zipfile, infile;
- parseFilename(filename, drive, path, base, ext);
-
- // Put the filename back together
- if ((base != "") && (ext != "")) {
- infile = base + "." + ext;
- } else {
- infile = base + ext;
- }
-
- // Remove "." from path
- for (int i = 0; i < path.length(); ++i) {
- if (path[i] == ".") {
- path.remove(i);
- --i;
- }
- }
-
- // Remove ".." from path
- for (int i = 1; i < path.length(); ++i) {
- if ((path[i] == "..") && (i > 0) && (path[i - 1] != "..")) {
- // Remove both i and i - 1
- path.remove(i - 1, 2);
- i -= 2;
- }
- }
-
- // Walk the path backwards, accumulating pieces onto the infile until
- // we find a zipfile that contains it
- for (int t = 0; t < path.length(); ++t){
- _zip_resolveDirectory(zipfile, drive, path, path.length() - t);
- if (t > 0) {
- infile = path[path.length() - t] + "/" + infile;
- }
-
- if (endsWith(zipfile, "..")) {
- return false;
- }
-
- if (fileExists(zipfile, false)) {
- // test if it actually is a zipfile
- // if not, return false, a bad
- // directory structure has been given,
- // not a .zip
- if (isZipfile(zipfile)){
-
- if (_zip_zipContains(zipfile, infile)){
- outZipfile = zipfile;
- outInternalFile = infile;
- return true;
- } else {
- return false;
- }
- } else {
- // the directory structure was valid but did not point to a .zip
- return false;
- }
- }
-
- }
-#endif
- // not a valid directory structure ever,
- // obviously no .zip was found within the path
- return false;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-std::string generateFilenameBase(const std::string& prefix, const std::string& suffix) {
- Array<std::string> exist;
-
- // Note "template" is a reserved word in C++
- std::string templat = prefix + System::currentDateString() + "_";
- getFiles(templat + "*", exist);
-
- // Remove extensions
- for (int i = 0; i < exist.size(); ++i) {
- exist[i] = filenameBase(exist[i]);
- }
-
- int num = 0;
- std::string result;
- templat += "%03d" + suffix;
- do {
- result = format(templat.c_str(), num);
- ++num;
- } while (exist.contains(result));
-
- return result;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-void copyFile(
- const std::string& source,
- const std::string& dest) {
-
- #ifdef G3D_WIN32
- CopyFileA(source.c_str(), dest.c_str(), FALSE);
- #else
- // TODO: don't use BinaryInput and BinaryOutput
- // Read it all in, then dump it out
- BinaryInput in(source, G3D_LITTLE_ENDIAN);
- BinaryOutput out(dest, G3D_LITTLE_ENDIAN);
- out.writeBytes(in.getCArray(), in.size());
- out.commit(false);
- #endif
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
-void parseFilename(
- const std::string& filename,
- std::string& root,
- Array<std::string>& path,
- std::string& base,
- std::string& ext) {
-
- std::string f = filename;
-
- root = "";
- path.clear();
- base = "";
- ext = "";
-
- if (f == "") {
- // Empty filename
- return;
- }
-
- // See if there is a root/drive spec.
- if ((f.size() >= 2) && (f[1] == ':')) {
-
- if ((f.size() > 2) && isSlash(f[2])) {
-
- // e.g. c:\foo
- root = f.substr(0, 3);
- f = f.substr(3, f.size() - 3);
-
- } else {
-
- // e.g. c:foo
- root = f.substr(2);
- f = f.substr(2, f.size() - 2);
-
- }
-
- } else if ((f.size() >= 2) & isSlash(f[0]) && isSlash(f[1])) {
-
- // e.g. //foo
- root = f.substr(0, 2);
- f = f.substr(2, f.size() - 2);
-
- } else if (isSlash(f[0])) {
-
- root = f.substr(0, 1);
- f = f.substr(1, f.size() - 1);
-
- }
-
- // Pull the extension off
- {
- // Find the period
- size_t i = f.rfind('.');
-
- if (i != std::string::npos) {
- // Make sure it is after the last slash!
- size_t j = iMax(f.rfind('/'), f.rfind('\\'));
- if ((j == std::string::npos) || (i > j)) {
- ext = f.substr(i + 1, f.size() - i - 1);
- f = f.substr(0, i);
- }
- }
- }
-
- // Pull the basename off
- {
- // Find the last slash
- size_t i = iMax(f.rfind('/'), f.rfind('\\'));
-
- if (i == std::string::npos) {
-
- // There is no slash; the basename is the whole thing
- base = f;
- f = "";
-
- } else if ((i != std::string::npos) && (i < f.size() - 1)) {
-
- base = f.substr(i + 1, f.size() - i - 1);
- f = f.substr(0, i);
-
- }
- }
-
- // Parse what remains into path.
- size_t prev, cur = 0;
-
- while (cur < f.size()) {
- prev = cur;
-
- // Allow either slash
- size_t i = f.find('/', prev + 1);
- size_t j = f.find('\\', prev + 1);
- if (i == std::string::npos) {
- i = f.size();
- }
-
- if (j == std::string::npos) {
- j = f.size();
- }
-
- cur = iMin(i, j);
-
- if (cur == std::string::npos) {
- cur = f.size();
- }
-
- path.append(f.substr(prev, cur - prev));
- ++cur;
- }
-}
-
-
-/**
- Helper for getFileList and getDirectoryList.
-
- @param wantFiles If false, returns the directories, otherwise
- returns the files.
- @param includePath If true, the names include paths
- */
-static void getFileOrDirListNormal
-(const std::string& filespec,
- Array<std::string>& files,
- bool wantFiles,
- bool includePath) {
-
- bool test = wantFiles ? true : false;
-
- std::string path = "";
-
- // Find the place where the path ends and the file-spec begins
- size_t i = filespec.rfind('/');
- size_t j = filespec.rfind('\\');
-
- // Drive letters on Windows can separate a path
- size_t k = filespec.rfind(':');
-
- if (((j != std::string::npos) && (j > i)) ||
- (i == std::string::npos)) {
- i = j;
- }
-
- if (((k != std::string::npos) && (k > i)) ||
- (i == std::string::npos)) {
- i = k;
- }
-
- // If there is a path, pull it off
- if (i != std::string::npos) {
- path = filespec.substr(0, i + 1);
- }
-
- std::string prefix = path;
-
- if (path.size() > 0) {
- // Strip the trailing character
- path = path.substr(0, path.size() - 1);
- }
-
-# ifdef G3D_WIN32
- {
- struct _finddata_t fileinfo;
-
- long handle = _findfirst(filespec.c_str(), &fileinfo);
- int result = handle;
-
- while (result != -1) {
- if ((((fileinfo.attrib & _A_SUBDIR) == 0) == test) &&
- strcmp(fileinfo.name, ".") &&
- strcmp(fileinfo.name, "..")) {
-
- if (includePath) {
- files.append(prefix + fileinfo.name);
- } else {
- files.append(fileinfo.name);
- }
- }
-
- result = _findnext(handle, &fileinfo);
- }
- }
-# else
- {
- if (path == "") {
- // Empty paths don't work on Unix
- path = ".";
- }
-
- // Unix implementation
- DIR* dir = opendir(path.c_str());
-
- if (dir != NULL) {
- struct dirent* entry = readdir(dir);
-
- while (entry != NULL) {
-
- // Exclude '.' and '..'
- if ((strcmp(entry->d_name, ".") != 0) &&
- (strcmp(entry->d_name, "..") != 0)) {
-
- // Form a name with a path
- std::string filename = prefix + entry->d_name;
- // See if this is a file or a directory
- struct _stat st;
- bool exists = _stat(filename.c_str(), &st) != -1;
-
- if (exists &&
-
- // Make sure it has the correct type
- (((st.st_mode & S_IFDIR) == 0) == test) &&
-
- // Make sure it matches the wildcard
- (fnmatch(filespec.c_str(),
- filename.c_str(),
- FNM_PATHNAME) == 0)) {
-
- if (includePath) {
- files.append(filename);
- } else {
- files.append(entry->d_name);
- }
- }
- }
-
- entry = readdir(dir);
- }
- closedir(dir);
- }
- }
-# endif
-}
-
-#if _HAVE_ZIP
-/**
- @param path The zipfile name (no trailing slash)
- @param prefix Directory inside the zipfile. No leading slash, must have trailing slash if non-empty.
- @param file Name inside the zipfile that we are testing to see if it matches prefix + "*"
- */
-static void _zip_addEntry(const std::string& path,
- const std::string& prefix,
- const std::string& file,
- Set<std::string>& files,
- bool wantFiles,
- bool includePath) {
-
- // Make certain we are within the desired parent folder (prefix)
- if (beginsWith(file, prefix)) {
- // validityTest was prefix/file
-
- // Extract everything to the right of the prefix
- std::string s = file.substr(prefix.length());
-
- if (s == "") {
- // This was the name of the prefix
- return;
- }
-
- // See if there are any slashes
- size_t slashPos = s.find('/');
-
- bool add = false;
-
- if (slashPos == std::string::npos) {
- // No slashes, so s must be a file
- add = wantFiles;
- } else if (! wantFiles) {
- // Not all zipfiles list directories as explicit entries.
- // Because of this, if we're looking for directories and see
- // any path longer than prefix, we must add the subdirectory.
- // The Set will fix duplicates for us.
- s = s.substr(0, slashPos);
- add = true;
- }
-
- if (add) {
- if (includePath) {
- files.insert(path + "/" + prefix + s);
- } else {
- files.insert(s);
- }
- }
- }
-}
-#endif
-
-static void getFileOrDirListZip(const std::string& path,
- const std::string& prefix,
- Array<std::string>& files,
- bool wantFiles,
- bool includePath){
-#if _HAVE_ZIP
- struct zip *z = zip_open( path.c_str(), ZIP_CHECKCONS, NULL );
-
- Set<std::string> fileSet;
-
- int count = zip_get_num_files( z );
- for( int i = 0; i < count; ++i ) {
- struct zip_stat info;
- zip_stat_init( &info ); // TODO: Docs unclear if zip_stat_init is required.
- zip_stat_index( z, i, ZIP_FL_NOCASE, &info );
- _zip_addEntry(path, prefix, info.name, fileSet, wantFiles, includePath);
- }
-
- zip_close( z );
-
- fileSet.getMembers(files);
-#endif
-}
-
-
-static void determineFileOrDirList(
- const std::string& filespec,
- Array<std::string>& files,
- bool wantFiles,
- bool includePath) {
-
- // if it is a .zip, prefix will specify the folder within
- // whose contents we want to see
- std::string prefix = "";
- std::string path = filenamePath(filespec);
-
- if ((path.size() > 0) && isSlash(path[path.size() - 1])) {
- // Strip the trailing slash
- path = path.substr(0, path.length() -1);
- }
-
- if ((path == "") || fileExists(path, false)) {
- if ((path != "") && isZipfile(path)) {
- // .zip should only work if * is specified as the Base + Ext
- // Here, we have been asked for the root's contents
- debugAssertM(filenameBaseExt(filespec) == "*", "Can only call getFiles/getDirs on zipfiles using '*' wildcard");
- getFileOrDirListZip(path, prefix, files, wantFiles, includePath);
- } else {
- // It is a normal directory
- getFileOrDirListNormal(filespec, files, wantFiles, includePath);
- }
- } else if (zipfileExists(filenamePath(filespec), path, prefix)) {
- // .zip should only work if * is specified as the Base + Ext
- // Here, we have been asked for the contents of a folder within the .zip
- debugAssertM(filenameBaseExt(filespec) == "*", "Can only call getFiles/getDirs on zipfiles using '*' wildcard");
- getFileOrDirListZip(path, prefix, files, wantFiles, includePath);
- }
-}
-
-
-void getFiles(const std::string& filespec,
- Array<std::string>& files,
- bool includePath) {
-
- determineFileOrDirList(filespec, files, true, includePath);
-}
-
-
-void getDirs(
- const std::string& filespec,
- Array<std::string>& files,
- bool includePath) {
-
- determineFileOrDirList(filespec, files, false, includePath);
-}
-
-
-std::string filenameBaseExt(const std::string& filename) {
- int i = filename.rfind("/");
- int j = filename.rfind("\\");
-
- if ((j > i) && (j >= 0)) {
- i = j;
- }
-
-# ifdef G3D_WIN32
- j = filename.rfind(":");
- if ((i == -1) && (j >= 0)) {
- i = j;
- }
-# endif
-
- if (i == -1) {
- return filename;
- } else {
- return filename.substr(i + 1, filename.length() - i);
- }
-}
-
-
-std::string filenameBase(const std::string& s) {
- std::string drive;
- std::string base;
- std::string ext;
- Array<std::string> path;
-
- parseFilename(s, drive, path, base, ext);
- return base;
-}
-
-
-std::string filenameExt(const std::string& filename) {
- int i = filename.rfind(".");
- if (i >= 0) {
- return filename.substr(i + 1, filename.length() - i);
- } else {
- return "";
- }
-}
-
-
-std::string filenamePath(const std::string& filename) {
- int i = filename.rfind("/");
- int j = filename.rfind("\\");
-
- if ((j > i) && (j >= 0)) {
- i = j;
- }
-
-# ifdef G3D_WIN32
- j = filename.rfind(":");
- if ((i == -1) && (j >= 0)) {
- i = j;
- }
-# endif
-
- if (i == -1) {
- return "";
- } else {
- return filename.substr(0, i+1);
- }
-}
-
-
-bool isZipfile(const std::string& filename) {
-
- FILE* f = fopen(filename.c_str(), "r");
- if (f == NULL) {
- return false;
- }
- uint8 header[4];
- fread(header, 4, 1, f);
-
- const uint8 zipHeader[4] = {0x50, 0x4b, 0x03, 0x04};
- for (int i = 0; i < 4; ++i) {
- if (header[i] != zipHeader[i]) {
- fclose(f);
- return false;
- }
- }
-
- fclose(f);
- return true;
-}
-
-
-bool isDirectory(const std::string& filename) {
- struct _stat st;
- bool exists = _stat(filename.c_str(), &st) != -1;
- return exists && ((st.st_mode & S_IFDIR) != 0);
-}
-
-
-bool filenameContainsWildcards(const std::string& filename) {
- return (filename.find('*') != std::string::npos) || (filename.find('?') != std::string::npos);
-}
-
-
-bool fileIsNewer(const std::string& src, const std::string& dst) {
- struct _stat sts;
- bool sexists = _stat(src.c_str(), &sts) != -1;
-
- struct _stat dts;
- bool dexists = _stat(dst.c_str(), &dts) != -1;
-
- return sexists && ((! dexists) || (sts.st_mtime > dts.st_mtime));
-}
-
-
-Array<std::string> filesUsed() {
- Array<std::string> f;
- _internal::currentFilesUsed.getMembers(f);
- return f;
-}
-
-}
-
-#ifndef G3D_WIN32
- #undef _stat
-#endif
diff --git a/externals/g3dlite/format.cpp b/externals/g3dlite/format.cpp
deleted file mode 100644
index d9d1b516393..00000000000
--- a/externals/g3dlite/format.cpp
+++ /dev/null
@@ -1,164 +0,0 @@
-/**
- @file format.cpp
-
- @author Morgan McGuire, graphics3d.com
-
- @created 2000-09-09
- @edited 2006-08-14
-*/
-
-#include "G3D/format.h"
-#include "G3D/platform.h"
-#include "G3D/System.h"
-
-#ifdef _MSC_VER
- // disable: "C++ exception handler used"
-# pragma warning (push)
-# pragma warning (disable : 4530)
-#endif // _MSC_VER
-
-// If your platform does not have vsnprintf, you can find a
-// implementation at http://www.ijs.si/software/snprintf/
-
-namespace G3D {
-
-std::string __cdecl format(const char* fmt,...) {
- va_list argList;
- va_start(argList,fmt);
- std::string result = vformat(fmt, argList);
- va_end(argList);
-
- return result;
-}
-
-#if defined(_MSC_VER) && (_MSC_VER >= 1300)
-// Both MSVC seems to use the non-standard vsnprintf
-// so we are using vscprintf to determine buffer size, however
-// only MSVC7 and up headers include vscprintf for some reason.
-std::string vformat(const char *fmt, va_list argPtr) {
- // We draw the line at a 1MB string.
- const int maxSize = 1000000;
-
- // If the string is less than 161 characters,
- // allocate it on the stack because this saves
- // the malloc/free time.
- const int bufSize = 161;
- char stackBuffer[bufSize];
-
- // MSVC does not support va_copy
- int actualSize = _vscprintf(fmt, argPtr) + 1;
-
- if (actualSize > bufSize) {
-
- // Now use the heap.
- char* heapBuffer = NULL;
-
- if (actualSize < maxSize) {
-
- heapBuffer = (char*)System::malloc(maxSize + 1);
- _vsnprintf(heapBuffer, maxSize, fmt, argPtr);
- heapBuffer[maxSize] = '\0';
- } else {
- heapBuffer = (char*)System::malloc(actualSize);
- vsprintf(heapBuffer, fmt, argPtr);
- }
-
- std::string formattedString(heapBuffer);
- System::free(heapBuffer);
- return formattedString;
- } else {
-
- vsprintf(stackBuffer, fmt, argPtr);
- return std::string(stackBuffer);
- }
-}
-
-#elif defined(_MSC_VER) && (_MSC_VER < 1300)
-
-std::string vformat(const char *fmt, va_list argPtr) {
- // We draw the line at a 1MB string.
- const int maxSize = 1000000;
-
- // If the string is less than 161 characters,
- // allocate it on the stack because this saves
- // the malloc/free time.
- const int bufSize = 161;
- char stackBuffer[bufSize];
-
- // MSVC6 doesn't support va_copy, however it also seems to compile
- // correctly if we just pass our argument list along. Note that
- // this whole code block is only compiled if we're on MSVC6 anyway
- int actualWritten = _vsnprintf(stackBuffer, bufSize, fmt, argPtr);
-
- // Not a big enough buffer, bufSize characters written
- if (actualWritten == -1) {
-
- int heapSize = 512;
- double powSize = 1.0;
- char* heapBuffer = (char*)System::malloc(heapSize);
-
- while ((_vsnprintf(heapBuffer, heapSize, fmt, argPtr) == -1) &&
- (heapSize < maxSize)) {
-
- heapSize = iCeil(heapSize * ::pow((double)2.0, powSize++));
- heapBuffer = (char*)System::realloc(heapBuffer, heapSize);
- }
-
- heapBuffer[heapSize-1] = '\0';
-
- std::string heapString(heapBuffer);
- System::free(heapBuffer);
-
- return heapString;
- } else {
-
- return std::string(stackBuffer);
- }
-}
-
-#else
-
-// glibc 2.1 has been updated to the C99 standard
-std::string vformat(const char* fmt, va_list argPtr) {
- // If the string is less than 161 characters,
- // allocate it on the stack because this saves
- // the malloc/free time. The number 161 is chosen
- // to support two lines of text on an 80 character
- // console (plus the null terminator).
- const int bufSize = 161;
- char stackBuffer[bufSize];
-
- va_list argPtrCopy;
- va_copy(argPtrCopy, argPtr);
- int numChars = vsnprintf(stackBuffer, bufSize, fmt, argPtrCopy);
- va_end(argPtrCopy);
-
- if (numChars >= bufSize) {
- // We didn't allocate a big enough string.
- char* heapBuffer = (char*)System::malloc((numChars + 1) * sizeof(char));
-
- debugAssert(heapBuffer);
- int numChars2 = vsnprintf(heapBuffer, numChars + 1, fmt, argPtr);
- debugAssert(numChars2 == numChars);
- (void)numChars2;
-
- std::string result(heapBuffer);
-
- System::free(heapBuffer);
-
- return result;
-
- } else {
-
- return std::string(stackBuffer);
-
- }
-}
-
-#endif
-
-} // namespace
-
-#ifdef _MSC_VER
-# pragma warning (pop)
-#endif
diff --git a/externals/g3dlite/g3dfnmatch.cpp b/externals/g3dlite/g3dfnmatch.cpp
deleted file mode 100644
index 39ef7b31914..00000000000
--- a/externals/g3dlite/g3dfnmatch.cpp
+++ /dev/null
@@ -1,204 +0,0 @@
-/*-
-* Copyright (c) 1992, 1993
-*The Regents of the University of California. All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions
-* are met:
-* 1. Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-* 2. Redistributions in binary form must reproduce the above copyright
-* notice, this list of conditions and the following disclaimer in the
-* documentation and/or other materials provided with the distribution.
-* 3. All advertising materials mentioning features or use of this software
-* must display the following acknowledgement:
-*This product includes software developed by the University of
-*California, Berkeley and its contributors.
-* 4. Neither the name of the University nor the names of its contributors
-* may be used to endorse or promote products derived from this software
-* without specific prior written permission.
-*
-* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
-* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
-* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-* SUCH DAMAGE.
-*
-*@(#)fnmatch.h8.1 (Berkeley) 6/2/93
-*
-* From FreeBSD fnmatch.h 1.7
-* $Id: g3dfnmatch.cpp,v 1.2 2010/02/06 10:03:24 corey_taylor Exp $
-*/
-#include "G3D/g3dfnmatch.h"
-
-#ifdef G3D_WIN32
-
-#include <ctype.h>
-#include <string.h>
-#include <stdio.h>
-
-namespace G3D {
-
-#define EOS '\0'
-
-static const char *rangematch(const char *, char, int);
-
-int g3dfnmatch(const char *pattern, const char *string, int flags)
-{
- const char *stringstart;
- char c, test;
-
- for (stringstart = string;;)
- switch (c = *pattern++) {
- case EOS:
- if ((flags & FNM_LEADING_DIR) && *string == '/')
- return (0);
- return (*string == EOS ? 0 : FNM_NOMATCH);
- case '?':
- if (*string == EOS)
- return (FNM_NOMATCH);
- if (*string == '/' && (flags & FNM_PATHNAME))
- return (FNM_NOMATCH);
- if (*string == '.' && (flags & FNM_PERIOD) &&
- (string == stringstart ||
- ((flags & FNM_PATHNAME) && *(string - 1) == '/')))
- return (FNM_NOMATCH);
- ++string;
- break;
- case '*':
- c = *pattern;
- /* Collapse multiple stars. */
- while (c == '*')
- c = *++pattern;
-
- if (*string == '.' && (flags & FNM_PERIOD) &&
- (string == stringstart ||
- ((flags & FNM_PATHNAME) && *(string - 1) == '/')))
- return (FNM_NOMATCH);
-
- /* Optimize for pattern with * at end or before /. */
- if (c == EOS)
- if (flags & FNM_PATHNAME)
- return ((flags & FNM_LEADING_DIR) ||
- strchr(string, '/') == NULL ?
- 0 : FNM_NOMATCH);
- else
- return (0);
- else if (c == '/' && flags & FNM_PATHNAME) {
- if ((string = strchr(string, '/')) == NULL)
- return (FNM_NOMATCH);
- break;
- }
-
- /* General case, use recursion. */
- while ((test = *string) != EOS) {
- if (!rangematch(pattern, *string, flags & ~FNM_PERIOD))
- return (0);
- if (test == '/' && flags & FNM_PATHNAME)
- break;
- ++string;
- }
- return (FNM_NOMATCH);
- case '[':
- if (*string == EOS)
- return (FNM_NOMATCH);
- if (*string == '/' && flags & FNM_PATHNAME)
- return (FNM_NOMATCH);
- if ((pattern =
- rangematch(pattern, *string, flags)) == NULL)
- return (FNM_NOMATCH);
- ++string;
- break;
- case '\\':
- if (!(flags & FNM_NOESCAPE)) {
- if ((c = *pattern++) == EOS) {
- c = '\\';
- --pattern;
- }
- }
- /* FALLTHROUGH */
- default:
- if (c == *string)
- ;
- else if ((flags & FNM_CASEFOLD) &&
- (tolower((unsigned char)c) ==
- tolower((unsigned char)*string)))
- ;
- else if ((flags & FNM_PREFIX_DIRS) && *string == EOS &&
- ((c == '/' && string != stringstart) ||
- (string == stringstart+1 && *stringstart == '/')))
- return (0);
- else
- return (FNM_NOMATCH);
- string++;
- break;
- }
- /* NOTREACHED */
-}
-
-static const char *
-rangematch(const char *pattern, char test, int flags)
-{
- int negate, ok;
- char c, c2;
-
- /*
- * A bracket expression starting with an unquoted circumflex
- * character produces unspecified results (IEEE 1003.2-1992,
- * 3.13.2). This implementation treats it like '!', for
- * consistency with the regular expression syntax.
- * J.T. Conklin (conklin@ngai.kaleida.com)
- */
- if ( (negate = (*pattern == '!' || *pattern == '^')) )
- ++pattern;
-
- if (flags & FNM_CASEFOLD)
- test = tolower((unsigned char)test);
-
- for (ok = 0; (c = *pattern++) != ']';) {
- if (c == '\\' && !(flags & FNM_NOESCAPE))
- c = *pattern++;
- if (c == EOS)
- return (NULL);
-
- if (flags & FNM_CASEFOLD)
- c = tolower((unsigned char)c);
-
- if (*pattern == '-'
- && (c2 = *(pattern+1)) != EOS && c2 != ']') {
- pattern += 2;
- if (c2 == '\\' && !(flags & FNM_NOESCAPE))
- c2 = *pattern++;
- if (c2 == EOS)
- return (NULL);
-
- if (flags & FNM_CASEFOLD)
- c2 = tolower((unsigned char)c2);
-
- if ((unsigned char)c <= (unsigned char)test &&
- (unsigned char)test <= (unsigned char)c2)
- ok = 1;
- } else if (c == test)
- ok = 1;
- }
- return (ok == negate ? NULL : pattern);
-}
-
-}
-
-#else
-
-namespace G3D {
-int g3dfnmatch(const char * a, const char *b, int c) {
- return fnmatch(a, b, c);
-}
-}
-
-#endif
-
diff --git a/externals/g3dlite/g3dmath.cpp b/externals/g3dlite/g3dmath.cpp
deleted file mode 100644
index ad85e9efb9b..00000000000
--- a/externals/g3dlite/g3dmath.cpp
+++ /dev/null
@@ -1,108 +0,0 @@
-/**
- @file g3dmath.cpp
-
- @author Morgan McGuire, graphics3d.com
-
- @created 2001-06-02
- @edited 2004-02-24
- */
-
-#include "G3D/g3dmath.h"
-#include <cstdlib>
-#include <cstring>
-
-namespace G3D {
-
-float gaussRandom(float mean, float stdev) {
-
- // Using Box-Mueller method from http://www.taygeta.com/random/gaussian.html
- // Modified to specify standard deviation and mean of distribution
- float w, x1, x2;
-
- // Loop until w is less than 1 so that log(w) is negative
- do {
- x1 = uniformRandom(-1.0, 1.0);
- x2 = uniformRandom(-1.0, 1.0);
-
- w = float(square(x1) + square(x2));
- } while (w > 1.0f);
-
- // Transform to gassian distribution
- // Multiply by sigma (stdev ^ 2) and add mean.
- return x2 * (float)square(stdev) * sqrtf((-2.0f * logf(w) ) / w) + mean;
-}
-
-/**
- This value should not be tested against directly, instead
- G3D::isNan() and G3D::isFinite() will return reliable results. */
-double inf() {
- return std::numeric_limits<double>::infinity();
-}
-
-bool isNaN(float x) {
- static const float n = nan();
- return memcmp(&x, &n, sizeof(float)) == 0;
-}
-
-bool isNaN(double x) {
- static const double n = nan();
- return memcmp(&x, &n, sizeof(double)) == 0;
-}
-
-
-/**
- This value should not be tested against directly, instead
- G3D::isNan() and G3D::isFinite() will return reliable results. */
-float finf() {
- return std::numeric_limits<float>::infinity();
-}
-
-/** This value should not be tested against directly, instead
- G3D::isNan() and G3D::isFinite() will return reliable results. */
-double nan() {
- // double is a standard type and should have quiet NaN
- return std::numeric_limits<double>::quiet_NaN();
-}
-
-float fnan() {
- // double is a standard type and should have quiet NaN
- return std::numeric_limits<float>::quiet_NaN();
-}
-
-
-int highestBit(uint32 x) {
- // Binary search.
- int base = 0;
-
- if (x & 0xffff0000) {
- base = 16;
- x >>= 16;
- }
- if (x & 0x0000ff00) {
- base += 8;
- x >>= 8;
- }
- if (x & 0x000000f0) {
- base += 4;
- x >>= 4;
- }
-
- static const int lut[] = {-1,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3};
- return base + lut[x];
-}
-
-
-int iRandom(int low, int high) {
- int r = iFloor(low + (high - low + 1) * (double)rand() / RAND_MAX);
-
- // There is a *very small* chance of generating
- // a number larger than high.
- if (r > high) {
- return high;
- } else {
- return r;
- }
-}
-
-
-}
diff --git a/externals/g3dlite/prompt.cpp b/externals/g3dlite/prompt.cpp
deleted file mode 100644
index 6a28e6462b4..00000000000
--- a/externals/g3dlite/prompt.cpp
+++ /dev/null
@@ -1,729 +0,0 @@
-/**
- @file prompt.cpp
-
- @author Morgan McGuire, http://graphics.cs.williams.edu
- @cite Windows dialog interface by Max McGuire, mmcguire@ironlore.com
- @cite Font setting code by Kurt Miller, kurt@flipcode.com
-
- @created 2000-08-26
- @edited 2005-01-14
- */
-
-#include "G3D/prompt.h"
-#include "G3D/platform.h"
-
-#include <stdio.h>
-
-#ifdef G3D_WIN32
-# include <sstream>
-# include <conio.h>
-#else
-# define _getch getchar
-#endif
-
-#ifdef G3D_OSX
-
-/*#ifdef __LP64__
-# undef __LP64__
-#endif
-*/
-
-# include <Carbon/Carbon.h>
-
-/*
-#ifdef G3D_64BIT
-# define __LP64__
-#endif
-*/
-
-#endif
-
-namespace G3D {
-
-#ifdef G3D_WIN32
-
-namespace _internal {
-/**
- Generic Win32 dialog facility.
- @author Max McGuire
- */
-class DialogTemplate {
-public:
-
- DialogTemplate(LPCSTR caption, DWORD style,
- int x, int y, int w, int h,
- LPCSTR font = NULL, WORD fontSize = 8) {
-
- usedBufferLength = sizeof(DLGTEMPLATE);
- totalBufferLength = usedBufferLength;
-
- dialogTemplate = (DLGTEMPLATE*)malloc(totalBufferLength);
-
- dialogTemplate->style = style;
-
- if (font != NULL) {
- dialogTemplate->style |= DS_SETFONT;
- }
-
- dialogTemplate->x = (short)x;
- dialogTemplate->y = (short)y;
- dialogTemplate->cx = (short)w;
- dialogTemplate->cy = (short)h;
- dialogTemplate->cdit = 0;
-
- dialogTemplate->dwExtendedStyle = 0;
-
- // The dialog box doesn't have a menu or a special class
- AppendData("\0", 2);
- AppendData("\0", 2);
-
- // Add the dialog's caption to the template
-
- AppendString(caption);
-
- if (font != NULL) {
- AppendData(&fontSize, sizeof(WORD));
- AppendString(font);
- }
- }
-
- void AddComponent(LPCSTR type, LPCSTR caption, DWORD style, DWORD exStyle, int x, int y, int w, int h, WORD id) {
-
- DLGITEMTEMPLATE item;
-
- item.style = style;
- item.x = (short)x;
- item.y = (short)y;
- item.cx = (short)w;
- item.cy = (short)h;
- item.id = id;
-
- item.dwExtendedStyle = exStyle;
-
- AppendData(&item, sizeof(DLGITEMTEMPLATE));
-
- AppendString(type);
- AppendString(caption);
-
- WORD creationDataLength = 0;
- AppendData(&creationDataLength, sizeof(WORD));
-
- // Increment the component count
- dialogTemplate->cdit++;
-
- }
-
-
- void AddButton(LPCSTR caption, DWORD style, DWORD exStyle, int x, int y, int w, int h, WORD id) {
-
- AddStandardComponent(0x0080, caption, style, exStyle, x, y, w, h, id);
-
- WORD creationDataLength = 0;
- AppendData(&creationDataLength, sizeof(WORD));
-
- }
-
-
- void AddEditBox(LPCSTR caption, DWORD style, DWORD exStyle, int x, int y, int w, int h, WORD id) {
-
- AddStandardComponent(0x0081, caption, style, exStyle, x, y, w, h, id);
-
- WORD creationDataLength = 0;
- AppendData(&creationDataLength, sizeof(WORD));
-
- }
-
-
- void AddStatic(LPCSTR caption, DWORD style, DWORD exStyle, int x, int y, int w, int h, WORD id) {
-
- AddStandardComponent(0x0082, caption, style, exStyle, x, y, w, h, id);
-
- WORD creationDataLength = 0;
- AppendData(&creationDataLength, sizeof(WORD));
-
- }
-
-
- void AddListBox(LPCSTR caption, DWORD style, DWORD exStyle, int x, int y, int w, int h, WORD id) {
-
- AddStandardComponent(0x0083, caption, style, exStyle, x, y, w, h, id);
-
- WORD creationDataLength = sizeof(WORD) + 5 * sizeof(WCHAR);
- AppendData(&creationDataLength, sizeof(WORD));
-
- AppendString("TEST");
-
- }
-
-
- void AddScrollBar(LPCSTR caption, DWORD style, DWORD exStyle, int x, int y, int w, int h, WORD id) {
-
- AddStandardComponent(0x0084, caption, style, exStyle, x, y, w, h, id);
-
- WORD creationDataLength = 0;
- AppendData(&creationDataLength, sizeof(WORD));
-
- }
-
-
- void AddComboBox(LPCSTR caption, DWORD style, DWORD exStyle, int x, int y, int w, int h, WORD id) {
-
- AddStandardComponent(0x0085, caption, style, exStyle, x, y, w, h, id);
-
- WORD creationDataLength = 0;
- AppendData(&creationDataLength, sizeof(WORD));
-
- }
-
-
- /**
- *
- * Returns a pointer to the Win32 dialog template which the object
- * represents. This pointer may become invalid if additional components
- * are added to the template.
- *
- */
- operator const DLGTEMPLATE*() const {
- return dialogTemplate;
- }
-
- virtual ~DialogTemplate() {
- free(dialogTemplate);
- }
-
-protected:
-
- void AddStandardComponent(WORD type, LPCSTR caption, DWORD style, DWORD exStyle,
- int x, int y, int w, int h, WORD id, LPSTR font = NULL, WORD fontSize = 8) {
-
- DLGITEMTEMPLATE item;
-
- // DWORD align the beginning of the component data
-
- AlignData(sizeof(DWORD));
-
- item.style = style;
- if (font != NULL) {
- item.style |= DS_SETFONT;
- }
- item.x = (short)x;
- item.y = (short)y;
- item.cx = (short)w;
- item.cy = (short)h;
- item.id = id;
-
- item.dwExtendedStyle = exStyle;
-
- AppendData(&item, sizeof(DLGITEMTEMPLATE));
-
- WORD preType = 0xFFFF;
-
- AppendData(&preType, sizeof(WORD));
- AppendData(&type, sizeof(WORD));
-
- AppendString(caption);
-
- if (font != NULL) {
- AppendData(&fontSize, sizeof(WORD));
- AppendString(font);
- }
-
- // Increment the component count
- dialogTemplate->cdit++;
- }
-
-
- void AlignData(int size) {
-
- int paddingSize = usedBufferLength % size;
-
- if (paddingSize != 0) {
- EnsureSpace(paddingSize);
- usedBufferLength += paddingSize;
- }
-
- }
-
- void AppendString(LPCSTR string) {
-
- int length = MultiByteToWideChar(CP_ACP, 0, string, -1, NULL, 0);
-
- WCHAR* wideString = (WCHAR*)malloc(sizeof(WCHAR) * length);
- MultiByteToWideChar(CP_ACP, 0, string, -1, wideString, length);
-
- AppendData(wideString, length * sizeof(WCHAR));
- free(wideString);
-
- }
-
- void AppendData(const void* data, int dataLength) {
-
- EnsureSpace(dataLength);
-
- memcpy((char*)dialogTemplate + usedBufferLength, data, dataLength);
- usedBufferLength += dataLength;
-
- }
-
- void EnsureSpace(int length) {
- if (length + usedBufferLength > totalBufferLength) {
- totalBufferLength += length * 2;
-
- void* newBuffer = malloc(totalBufferLength);
- memcpy(newBuffer, dialogTemplate, usedBufferLength);
-
- free(dialogTemplate);
- dialogTemplate = (DLGTEMPLATE*)newBuffer;
- }
- }
-
-private:
-
- DLGTEMPLATE* dialogTemplate;
-
- int totalBufferLength;
- int usedBufferLength;
-
-};
-
-
-struct PromptParams {
- const char* message;
- const char* title;
-};
-
-/**
- * Constants for controls.
- */
-#define IDC_MESSAGE 1000
-#define IDC_BUTTON0 2000
-
-INT_PTR CALLBACK PromptDlgProc(HWND hDlg, UINT msg,
- WPARAM wParam, LPARAM lParam) {
- switch(msg) {
- case WM_INITDIALOG:
- {
- PromptParams *params = (PromptParams*)lParam;
- ::SetWindowTextA(::GetDlgItem(hDlg, IDC_MESSAGE), params->message);
-
- ::SetFocus(::GetDlgItem(hDlg, IDC_BUTTON0));
-
- SetWindowTextA(hDlg, params->title);
-
- HFONT hfont =
- CreateFontA(16, 0, 0, 0, FW_NORMAL,
- FALSE, FALSE, FALSE,
- ANSI_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,
- PROOF_QUALITY, FIXED_PITCH | FF_MODERN, "Courier New");
-
- SendDlgItemMessage(hDlg, IDC_MESSAGE, WM_SETFONT, (WPARAM)hfont, MAKELPARAM(TRUE,0));
-
-
- break;
- }
- case WM_COMMAND:
- {
- int choiceNumber = LOWORD(wParam) - IDC_BUTTON0;
- if ((choiceNumber >= 0) && (choiceNumber < 10)) {
- EndDialog(hDlg, choiceNumber);
- return TRUE;
- }
- }
-
- break;
-
- case WM_NCDESTROY:
- // Under SDL 1.2.6 we get a NCDESTROY message for no reason and the
- // window is immediately closed. This is here to debug the problem.
- (void)0;
- break;
-
- }
-
- return FALSE;
-}
-
-}; // namespace _internal
-
-
-using namespace _internal;
-
-/**
- * Show a dialog prompt.
- */
-static int guiPrompt(
- const char* windowTitle,
- const char* prompt,
- const char** choice,
- int numChoices) {
-
- int width = 280;
- int height = 128;
-
- const int buttonSpacing = 2;
- const int buttonWidth =
- (width - buttonSpacing * 2 -
- buttonSpacing * (numChoices - 1)) / numChoices;
- const int buttonHeight = 13;
-
-
- DialogTemplate dialogTemplate(
- windowTitle,
- WS_CAPTION | DS_CENTER | WS_SYSMENU,
- 10, 10, width, height,
- "Tahoma");
-
- dialogTemplate.AddEditBox(
- "Edit", WS_VISIBLE | ES_READONLY | ES_OEMCONVERT | ES_MULTILINE | WS_TABSTOP, WS_EX_STATICEDGE,
- 2, 2, width - 4, height - buttonHeight - 7, IDC_MESSAGE);
-
- int i;
- for (i = 0; i < numChoices; i++) {
-
- int x = buttonSpacing + i * (buttonWidth + buttonSpacing);
- int y = height - buttonHeight - buttonSpacing;
-
- dialogTemplate.AddButton(choice[i], WS_VISIBLE | WS_TABSTOP, 0,
- x, y, buttonWidth, buttonHeight, IDC_BUTTON0 + (WORD)i);
-
- }
-
- // Convert all single \n characters to \r\n for proper printing
- int strLen = 0;
- const char* pStr = prompt;
-
- while (*pStr != '\0') {
- if ((*pStr == '\n') && (pStr != prompt)) {
- if (*(pStr - 1) != '\r') {
- ++strLen;
- }
- }
- ++strLen;
- ++pStr;
- }
-
- char* newStr = (char*)malloc(strLen + 1);
-
- const char* pStr2 = prompt;
- char* pNew = newStr;
-
- while (*pStr2 != '\0') {
- if ((*pStr2 == '\n') && (pStr2 != prompt)) {
- if (*(pStr2 - 1) != '\r') {
- *pNew = '\r';
- ++pNew;
- }
- }
- *pNew = *pStr2;
- ++pNew;
- ++pStr2;
- }
-
- *pNew = '\0';
-
- PromptParams params;
- params.message = newStr;;
- params.title = windowTitle;
-
- HMODULE module = GetModuleHandle(0);
- int ret = DialogBoxIndirectParam(module, dialogTemplate, NULL, (DLGPROC) PromptDlgProc, (DWORD)&params);
-
- free(newStr);
-
- /*
- For debugging when DialogBoxIndirectParam fails:
-
- // The last error value. (Which is preserved across the call).
- DWORD lastErr = GetLastError();
-
- // The decoded message from FormatMessage
- LPTSTR formatMsg = NULL;
-
- if (NULL == formatMsg) {
- FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
- FORMAT_MESSAGE_IGNORE_INSERTS |
- FORMAT_MESSAGE_FROM_SYSTEM,
- NULL,
- lastErr,
- 0,
- (LPTSTR)&formatMsg,
- 0,
- NULL);
- }
-
- // Make sure the message got translated into something.
- LPTSTR realLastErr;
- if (NULL != formatMsg) {
- realLastErr = formatMsg;
- } else {
- realLastErr = "Last error code does not exist.";
- }
-
- // Get rid of the allocated memory from FormatMessage.
- if (NULL != formatMsg) {
- LocalFree((LPVOID)formatMsg);
- }
- */
-
- return ret;
-}
-
-#endif
-
-
-/**
- * Show a prompt on stdout
- */
-static int textPrompt(
- const char* windowTitle,
- const char* prompt,
- const char** choice,
- int numChoices) {
-
- printf("\n___________________________________________________\n");
- printf("%s\n", windowTitle);
- printf("%s", prompt);
-
- if (numChoices > 10) {
- numChoices = 10;
- }
-
- int c = -1;
- if (numChoices > 1) {
- printf("\n");
- printf("Choose an option by number:");
-
- while ((c < 0) || (c >= numChoices)) {
- printf("\n");
-
- for (int i = 0; i < numChoices; i++) {
- if (numChoices <= 3) {
- printf(" (%d) %s ", i, choice[i]);
- } else {
- printf(" (%d) %s\n", i, choice[i]);
- }
- }
-
- printf("\n> ");
- c = _getch() - '0';
-
- if ((c < 0) || (c >= numChoices)) {
- printf("'%d' is not a valid choice.", c);
- } else {
- printf("%d", c);
- }
- }
-
- } else if (numChoices == 1) {
-
- printf("\nPress any key for '%s'...", choice[0]);
- _getch();
- c = 0;
-
- } else {
-
- printf("\nPress any key...");
- _getch();
- c = 0;
- }
-
- printf("\n___________________________________________________\n");
- return c;
-}
-
-#ifdef G3D_OSX
-
-// See http://developer.apple.com/documentation/Carbon/Reference/Carbon_Event_Manager_Ref/index.html
-
-#define CARBON_COMMANDID_START 128
-#define CARBON_BUTTON_SPACING 12
-#define CARBON_BUTTON_HEIGHT 20
-#define CARBON_BUTTON_MINWIDTH 69
-#define CARBON_WINDOW_PADDING 20
-
-struct CallbackData {
- WindowRef refWindow;
-
- /** Index of this particular button */
- int myIndex;
-
- /** Buttons store their index into here when pressed. */
- int* whichButton;
-};
-
-/**
- Assumes that userData is a pointer to a carbon_evt_data_t.
-
- */
-static pascal OSStatus DoCommandEvent(EventHandlerCallRef handlerRef, EventRef event, void* userData) {
- // See http://developer.apple.com/documentation/Carbon/Conceptual/HandlingWindowsControls/index.html
-
- CallbackData& callbackData = *(CallbackData*)userData;
-
-# pragma unused(handlerRef)
-
- callbackData.whichButton[0] = callbackData.myIndex;
-
- // If we get here we can close the window
- ::QuitAppModalLoopForWindow(callbackData.refWindow);
-
- // Return noErr to indicate that we handled the event
- return noErr;
-}
-
-static int guiPrompt
-(const char* windowTitle,
- const char* prompt,
- const char** choice,
- int numChoices) {
-
- WindowRef window;
-
- int iNumButtonRows = 0;
- int iButtonWidth = -1;
- OSStatus err = noErr;
-
- // Determine number of rows of buttons
- while (iButtonWidth < CARBON_BUTTON_MINWIDTH) {
- ++iNumButtonRows;
- iButtonWidth =
- (550 - (CARBON_WINDOW_PADDING*2 +
- (CARBON_BUTTON_SPACING*numChoices))) /
- (numChoices/iNumButtonRows);
- }
-
- // Window Variables
- Rect rectWin = {0, 0, 200 + ((iNumButtonRows-1) * (CARBON_BUTTON_HEIGHT+CARBON_BUTTON_SPACING)), 550}; // top, left, bottom, right
- CFStringRef szWindowTitle = CFStringCreateWithCString(kCFAllocatorDefault, windowTitle, kCFStringEncodingUTF8);
-
- window = NULL;
-
- err = CreateNewWindow(kMovableAlertWindowClass, kWindowStandardHandlerAttribute|kWindowCompositingAttribute, &rectWin, &window);
- err = SetWindowTitleWithCFString(window, szWindowTitle);
- err = SetThemeWindowBackground(window, kThemeBrushAlertBackgroundActive, false);
- assert(err == noErr);
-
- // Event Handler Variables
- EventTypeSpec buttonSpec[] = {{ kEventClassControl, kEventControlHit }, { kEventClassCommand, kEventCommandProcess }};
- EventHandlerUPP buttonHandler = NewEventHandlerUPP(DoCommandEvent);
-
- // Static Text Variables
- Rect rectStatic = {20, 20, 152, 530};
- CFStringRef szStaticText = CFStringCreateWithCString(kCFAllocatorDefault, prompt, kCFStringEncodingUTF8);
- ControlRef refStaticText = NULL;
- err = CreateStaticTextControl(window, &rectStatic, szStaticText, NULL, &refStaticText);
-
- // Button Variables
- Rect bounds[numChoices];
- CFStringRef caption[numChoices];
- ControlRef button[numChoices];
-
- int whichButton=-1;
- CallbackData callbackData[numChoices];
-
- // Create the Buttons and assign event handlers
- for (int i = 0; i < numChoices; ++i) {
- bounds[i].top = 160 + ((CARBON_BUTTON_HEIGHT+CARBON_BUTTON_SPACING)*(i%iNumButtonRows));
- bounds[i].right = 530 - ((iButtonWidth+CARBON_BUTTON_SPACING)*(i/iNumButtonRows));
- bounds[i].left = bounds[i].right - iButtonWidth;
- bounds[i].bottom = bounds[i].top + CARBON_BUTTON_HEIGHT;
-
- // Convert the button captions to Apple strings
- caption[i] = CFStringCreateWithCString(kCFAllocatorDefault, choice[i], kCFStringEncodingUTF8);
-
- err = CreatePushButtonControl(window, &bounds[i], caption[i], &button[i]);
- assert(err == noErr);
-
- err = SetControlCommandID(button[i], CARBON_COMMANDID_START + i);
- assert(err == noErr);
-
- callbackData[i].refWindow = window;
- callbackData[i].myIndex = i;
- callbackData[i].whichButton = &whichButton;
-
- err = InstallControlEventHandler(button[i], buttonHandler,
- GetEventTypeCount(buttonSpec), buttonSpec,
- &callbackData[i], NULL);
- assert(err == noErr);
- }
-
- // Show Dialog
- err = RepositionWindow(window, NULL, kWindowCenterOnMainScreen);
- ShowWindow(window);
- BringToFront(window);
- err = ActivateWindow(window, true);
-
- // Hack to get our window/process to the front...
- ProcessSerialNumber psn = { 0, kCurrentProcess};
- TransformProcessType(&psn, kProcessTransformToForegroundApplication);
- SetFrontProcess (&psn);
-
- // Run in Modal State
- err = RunAppModalLoopForWindow(window);
-
- // Dispose of Button Related Data
- for (int i = 0; i < numChoices; ++i) {
- // Dispose of controls
- DisposeControl(button[i]);
-
- // Release CFStrings
- CFRelease(caption[i]);
- }
-
- // Dispose of Other Controls
- DisposeControl(refStaticText);
-
- // Dispose of Event Handlers
- DisposeEventHandlerUPP(buttonHandler);
-
- // Dispose of Window
- DisposeWindow(window);
-
- // Release CFStrings
- CFRelease(szWindowTitle);
- CFRelease(szStaticText);
-
- // Return Selection
- return whichButton;
-}
-
-#endif
-
-int prompt(
- const char* windowTitle,
- const char* prompt,
- const char** choice,
- int numChoices,
- bool useGui) {
-
- #ifdef G3D_WIN32
- if (useGui) {
- // Build the message box
- return guiPrompt(windowTitle, prompt, choice, numChoices);
- }
- #endif
-
- #ifdef G3D_OSX
- if (useGui){
- //Will default to text prompt if numChoices > 4
- return guiPrompt(windowTitle, prompt, choice, numChoices);
- }
- #endif
- return textPrompt(windowTitle, prompt, choice, numChoices);
-}
-
-
-void msgBox(
- const std::string& message,
- const std::string& title) {
-
- const char *choice[] = {"Ok"};
- prompt(title.c_str(), message.c_str(), choice, 1, true);
-}
-
-#ifndef G3D_WIN32
- #undef _getch
-#endif
-
-};// namespace
-
diff --git a/externals/g3dlite/stringutils.cpp b/externals/g3dlite/stringutils.cpp
deleted file mode 100644
index c3876ebb6a4..00000000000
--- a/externals/g3dlite/stringutils.cpp
+++ /dev/null
@@ -1,275 +0,0 @@
-/**
- @file stringutils.cpp
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2000-09-09
- @edited 2008-01-10
-*/
-
-#include "G3D/platform.h"
-#include "G3D/stringutils.h"
-#include "G3D/BinaryInput.h"
-#include <algorithm>
-
-namespace G3D {
-
-#ifdef _MSC_VER
- // disable: "C++ exception handler used"
-# pragma warning (push)
-# pragma warning (disable : 4530)
-#endif
-#ifdef G3D_WIN32
- const char* NEWLINE = "\r\n";
-#else
- const char* NEWLINE = "\n";
- static bool iswspace(int ch) { return (ch==' ' || ch=='\t' || ch=='\n' || ch=='\r'); }
-#endif
-
-void parseCommaSeparated(const std::string s, Array<std::string>& array, bool stripQuotes) {
- array.fastClear();
- if (s == "") {
- return;
- }
-
- size_t begin = 0;
- const char delimiter = ',';
- const char quote = '\"';
- do {
- size_t end = begin;
- // Find the next comma, or the end of the string
- bool inQuotes = false;
- while ((end < s.length()) && (inQuotes || (s[end] != delimiter))) {
- if (s[end] == quote) {
- if ((end < s.length() - 2) && (s[end + 1] == quote) && (s[end + 2]) == quote) {
- // Skip over the superquote
- end += 2;
- }
- inQuotes = ! inQuotes;
- }
- ++end;
- }
- array.append(s.substr(begin, end - begin));
- begin = end + 1;
- } while (begin < s.length());
-
- if (stripQuotes) {
- for (int i = 0; i < array.length(); ++i) {
- std::string& t = array[i];
- int L = t.length();
- if ((L > 1) && (t[0] == quote) && (t[L - 1] == quote)) {
- if ((L > 6) && (t[1] == quote) && (t[2] == quote) && (t[L - 3] == quote) && (t[L - 2] == quote)) {
- // Triple-quote
- t = t.substr(3, L - 6);
- } else {
- // Double-quote
- t = t.substr(1, L - 2);
- }
- }
- }
- }
-}
-
-bool beginsWith(
- const std::string& test,
- const std::string& pattern) {
-
- if (test.size() >= pattern.size()) {
- for (int i = 0; i < (int)pattern.size(); ++i) {
- if (pattern[i] != test[i]) {
- return false;
- }
- }
- return true;
- } else {
- return false;
- }
-}
-
-
-bool endsWith(
- const std::string& test,
- const std::string& pattern) {
-
- if (test.size() >= pattern.size()) {
- int te = test.size() - 1;
- int pe = pattern.size() - 1;
- for (int i = pattern.size() - 1; i >= 0; --i) {
- if (pattern[pe - i] != test[te - i]) {
- return false;
- }
- }
- return true;
- } else {
- return false;
- }
-}
-
-
-std::string wordWrap(
- const std::string& input,
- int numCols) {
-
- std::string output;
- size_t c = 0;
- int len;
-
- // Don't make lines less than this length
- int minLength = numCols / 4;
- size_t inLen = input.size();
-
- bool first = true;
- while (c < inLen) {
- if (first) {
- first = false;
- } else {
- output += NEWLINE;
- }
-
- if ((int)inLen - (int)c - 1 < numCols) {
- // The end
- output += input.substr(c, inLen - c);
- break;
- }
-
- len = numCols;
-
- // Look at character c + numCols, see if it is a space.
- while ((len > minLength) &&
- (input[c + len] != ' ')) {
- len--;
- }
-
- if (len == minLength) {
- // Just crop
- len = numCols;
-
- }
-
- output += input.substr(c, len);
- c += len;
- if (c < input.size()) {
- // Collapse multiple spaces.
- while ((input[c] == ' ') && (c < input.size())) {
- c++;
- }
- }
- }
-
- return output;
-}
-
-
-int stringCompare(
- const std::string& s1,
- const std::string& s2) {
-
- return stringPtrCompare(&s1, &s2);
-}
-
-
-int stringPtrCompare(
- const std::string* s1,
- const std::string* s2) {
-
- return s1->compare(*s2);
-}
-
-
-std::string toUpper(const std::string& x) {
- std::string result = x;
- std::transform(result.begin(), result.end(), result.begin(), toupper);
- return result;
-}
-
-
-std::string toLower(const std::string& x) {
- std::string result = x;
- std::transform(result.begin(), result.end(), result.begin(), tolower);
- return result;
-}
-
-
-Array<std::string> stringSplit(
- const std::string& x,
- char splitChar) {
-
- Array<std::string> out;
-
- // Pointers to the beginning and end of the substring
- const char* start = x.c_str();
- const char* stop = start;
-
- while ((stop = strchr(start, splitChar))) {
- out.append(std::string(start, stop - start));
- start = stop + 1;
- }
-
- // Append the last one
- out.append(std::string(start));
-
- return out;
-}
-
-
-std::string stringJoin(
- const Array<std::string>& a,
- char joinChar) {
-
- std::string out;
-
- for (int i = 0; i < (int)a.size() - 1; ++i) {
- out += a[i] + joinChar;
- }
-
- if (a.size() > 0) {
- return out + a.last();
- } else {
- return out;
- }
-}
-
-
-std::string stringJoin(
- const Array<std::string>& a,
- const std::string& joinStr) {
-
- std::string out;
-
- for (int i = 0; i < (int)a.size() - 1; ++i) {
- out += a[i] + joinStr;
- }
-
- if (a.size() > 0) {
- return out + a.last();
- } else {
- return out;
- }
-}
-
-
-std::string trimWhitespace(
- const std::string& s) {
-
- size_t left = 0;
-
- // Trim from left
- while ((left < s.length()) && iswspace(s[left])) {
- ++left;
- }
-
- int right = s.length() - 1;
- // Trim from right
- while ((right > (int)left) && iswspace(s[right])) {
- --right;
- }
-
- return s.substr(left, right - left + 1);
-}
-
-}; // namespace
-
-#undef NEWLINE
-#ifdef _MSC_VER
-# pragma warning (pop)
-#endif