diff options
Diffstat (limited to 'externals/g3dlite')
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> </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> </code>r1c0<code>, </code>r1c1<code>, </code>r1c2<code>, - <br> </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> </code>r1c0<code>, </code>r1c1<code>, </code>r1c2<code>, </code>r1c3<code>, - <br> </code>r2c0<code>, </code>r2c1<code>, </code>r2c2<code>, </code>r2c3<code>, - <br> </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> </code>r1c0<code>, </code>r1c1<code>, </code>r1c2<code>, </code>r1c3<code>, - <br> </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> </code><i>symbol<sub>1</sub></i><code> = </code><i>value<sub>1</sub></i> - <br><code> </code>... - <br><code> </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(<Array != this); - debugAssert(&eqArray != this); - debugAssert(>Array != this); - debugAssert(<Array != &eqArray); - debugAssert(<Array != >Array); - debugAssert(&eqArray != >Array); - - // Clear the arrays - ltArray.fastClear(); - eqArray.fastClear(); - gtArray.fastClear(); - - // Form a table of buckets for lt, eq, and gt - Array<T>* bucket[3] = {<Array, &eqArray, >Array}; - - 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 = <Median; - Array<T>* eq = &eqMedian; - Array<T>* gt = >Median; - 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<<I>T</I>> <: RCP<<I>S</I>> if <I>T</I> <: <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<<I>T</I>> <: RCP<<I>S</I>> if <I>T</I> <: <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)¶ms); - - 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 |
