From 17bcfc31908772b9625aaf38b2f00de0de16dcf5 Mon Sep 17 00:00:00 2001 From: blueboy Date: Thu, 8 Nov 2012 19:52:53 +0000 Subject: [PATCH] [12262] Replace existing G3D files (.cpp/.h), with 8.01 distribution --- dep/include/g3dlite/G3D/AABox.h | 3 + dep/include/g3dlite/G3D/Any.h | 228 ++++- dep/include/g3dlite/G3D/BinaryInput.h | 9 +- dep/include/g3dlite/G3D/Color3uint8.h | 37 +- dep/include/g3dlite/G3D/Color4.h | 11 +- dep/include/g3dlite/G3D/Color4uint8.h | 14 +- dep/include/g3dlite/G3D/CoordinateFrame.h | 4 + dep/include/g3dlite/G3D/FileSystem.h | 466 ++++++++++ dep/include/g3dlite/G3D/G3D.h | 5 +- dep/include/g3dlite/G3D/GCamera.h | 19 +- dep/include/g3dlite/G3D/GImage.h | 8 +- dep/include/g3dlite/G3D/GLight.h | 7 + dep/include/g3dlite/G3D/HashTrait.h | 2 +- dep/include/g3dlite/G3D/ImageFormat.h | 28 +- dep/include/g3dlite/G3D/Matrix2.h | 33 +- dep/include/g3dlite/G3D/Matrix4.h | 9 + dep/include/g3dlite/G3D/MeshAlg.h | 2 +- dep/include/g3dlite/G3D/NetAddress.h | 30 +- dep/include/g3dlite/G3D/NetworkDevice.h | 5 +- dep/include/g3dlite/G3D/PhysicsFrame.h | 43 +- dep/include/g3dlite/G3D/PhysicsFrameSpline.h | 37 + dep/include/g3dlite/G3D/PointHashGrid.h | 54 +- dep/include/g3dlite/G3D/Quat.h | 166 ++-- dep/include/g3dlite/G3D/Set.h | 7 +- dep/include/g3dlite/G3D/SmallArray.h | 14 +- dep/include/g3dlite/G3D/Sphere.h | 1 - dep/include/g3dlite/G3D/Spline.h | 15 +- dep/include/g3dlite/G3D/System.h | 74 +- dep/include/g3dlite/G3D/Table.h | 7 +- dep/include/g3dlite/G3D/TextInput.h | 61 +- dep/include/g3dlite/G3D/Vector3.h | 4 +- dep/include/g3dlite/G3D/Vector3int16.h | 2 +- dep/include/g3dlite/G3D/WrapMode.h | 26 +- dep/include/g3dlite/G3D/XML.h | 204 +++++ dep/include/g3dlite/G3D/constants.h | 46 +- dep/include/g3dlite/G3D/debugAssert.h | 4 - dep/include/g3dlite/G3D/enumclass.h | 110 ++- dep/include/g3dlite/G3D/fileutils.h | 97 +-- dep/include/g3dlite/G3D/g3dmath.h | 31 +- dep/include/g3dlite/G3D/netheaders.h | 24 + dep/include/g3dlite/G3D/networkHelpers.h | 91 ++ dep/include/g3dlite/G3D/platform.h | 39 +- dep/include/g3dlite/G3D/stringutils.h | 33 +- dep/src/g3dlite/AABox.cpp | 4 + dep/src/g3dlite/Any.cpp | 153 +++- dep/src/g3dlite/BinaryInput.cpp | 85 +- dep/src/g3dlite/BinaryOutput.cpp | 26 +- dep/src/g3dlite/CoordinateFrame.cpp | 55 +- dep/src/g3dlite/FileSystem.cpp | 859 +++++++++++++++++++ dep/src/g3dlite/GCamera.cpp | 27 +- dep/src/g3dlite/GImage.cpp | 2 +- dep/src/g3dlite/GImage_png.cpp | 20 +- dep/src/g3dlite/GImage_ppm.cpp | 2 +- dep/src/g3dlite/GImage_tga.cpp | 97 ++- dep/src/g3dlite/GLight.cpp | 16 +- dep/src/g3dlite/ImageFormat.cpp | 33 +- dep/src/g3dlite/Log.cpp | 7 +- dep/src/g3dlite/Matrix3.cpp | 14 +- dep/src/g3dlite/Matrix4.cpp | 7 +- dep/src/g3dlite/MeshAlgAdjacency.cpp | 10 +- dep/src/g3dlite/NetworkDevice.cpp | 90 +- dep/src/g3dlite/PhysicsFrame.cpp | 37 +- dep/src/g3dlite/PhysicsFrameSpline.cpp | 80 ++ dep/src/g3dlite/Quat.cpp | 22 +- dep/src/g3dlite/RegistryUtil.cpp | 2 +- dep/src/g3dlite/System.cpp | 215 ++--- dep/src/g3dlite/TextInput.cpp | 198 +++-- dep/src/g3dlite/TextOutput.cpp | 13 +- dep/src/g3dlite/Vector3.cpp | 7 +- dep/src/g3dlite/Vector4.cpp | 9 +- dep/src/g3dlite/Welder.cpp | 73 +- dep/src/g3dlite/XML.cpp | 216 +++++ dep/src/g3dlite/constants.cpp | 66 -- dep/src/g3dlite/debugAssert.cpp | 4 - dep/src/g3dlite/fileutils.cpp | 291 +------ dep/src/g3dlite/g3dfnmatch.cpp | 367 ++++---- dep/src/g3dlite/g3dmath.cpp | 1 + dep/src/g3dlite/license.html | 115 --- dep/src/g3dlite/prompt.cpp | 11 +- src/shared/revision_nr.h | 2 +- 80 files changed, 3842 insertions(+), 1504 deletions(-) create mode 100644 dep/include/g3dlite/G3D/FileSystem.h create mode 100644 dep/include/g3dlite/G3D/PhysicsFrameSpline.h create mode 100644 dep/include/g3dlite/G3D/XML.h create mode 100644 dep/include/g3dlite/G3D/netheaders.h create mode 100644 dep/include/g3dlite/G3D/networkHelpers.h create mode 100644 dep/src/g3dlite/FileSystem.cpp create mode 100644 dep/src/g3dlite/PhysicsFrameSpline.cpp create mode 100644 dep/src/g3dlite/XML.cpp delete mode 100644 dep/src/g3dlite/license.html diff --git a/dep/include/g3dlite/G3D/AABox.h b/dep/include/g3dlite/G3D/AABox.h index 2e8da1f6098..d57320d73eb 100644 --- a/dep/include/g3dlite/G3D/AABox.h +++ b/dep/include/g3dlite/G3D/AABox.h @@ -20,6 +20,7 @@ #include "G3D/debug.h" #include "G3D/Array.h" #include "G3D/Plane.h" +#include "G3D/Sphere.h" namespace G3D { @@ -259,6 +260,8 @@ class AABox { void getBounds(AABox& out) const { out = *this; } + + void getBounds(Sphere& out) const; }; } diff --git a/dep/include/g3dlite/G3D/Any.h b/dep/include/g3dlite/G3D/Any.h index 49701202ca9..e2d0fbe7e62 100644 --- a/dep/include/g3dlite/G3D/Any.h +++ b/dep/include/g3dlite/G3D/Any.h @@ -5,7 +5,7 @@ @maintainer Morgan McGuire @created 2006-06-11 - @edited 2009-12-16 + @edited 2010-03-16 Copyright 2000-2010, Morgan McGuire. All rights reserved. @@ -17,7 +17,9 @@ #include "G3D/platform.h" #include "G3D/Table.h" #include "G3D/Array.h" +#include "G3D/Set.h" #include "G3D/AtomicInt32.h" +#include "G3D/stringutils.h" #include // needed for Token @@ -34,11 +36,14 @@ class TextOutput; /** \brief Easy loading and saving of human-readable configuration files. -Encodes typed, structured data and can serialize it to a human +Any 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. +syntax. It is 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 +syntax allows most C++ editors to properly highlight Any files, and +makes it easy to design little ad-hoc C-like languages in +configuration files. 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 @@ -50,15 +55,17 @@ Sample File: { shape = "round", - # in meters + // in meters radius = 3.7, position = Vector3(1.0, -1.0, 0.0), - texture = { format = "RGB8", size = (320, 200)} + video = { format = "RGB8", size = (320, 200)}, + + material = #include("rocks.mat") } -Sample code using: +Sample code using Any:
 Any x;
 x.load("ball.txt");
@@ -110,6 +117,21 @@ Vector3::Vector3(const Any& any) {
 }
 
+It is often convenient to iterate through the table portion: + +
+    for (Any::AnyTable::Iterator it = any.table().begin(); it.hasMore(); ++it) {
+        const std::string& k = toLower(it->key);
+        if (key == "hello") {
+           ...
+        } else if (key == "goodbye") {
+           ...
+        } else {
+           any.verify(false, "Unsupported key: " + it->key);
+        }
+    }
+
+ \section BNF Serialized format BNF: @@ -119,27 +141,38 @@ identifier-op ::= "::" | "->" | "." identifier-exp ::= [identifier-op] identifier (identifier-op identifier)* -comment ::= "#" "\n" +comment ::= C++ single or multi-line comments separator ::= "," | ";" number ::= string ::= boolean ::= "True" | "False" none ::= "None" -array ::= "(" [value ("," value)*] ")" +array ::= ("(" | "[") [ value (separator value)* [separator] ] (")" | "]") pair ::= (identifier | string) "=" value -table ::= "{" [pair (separator pair)*] "}" -named-array ::= identifier-exp tuple -named-table ::= identifier-exp dict +table ::= "{" [ pair (separator pair)* [separator] ] "}" +named-array ::= identifier-exp array +named-table ::= identifier-exp table +include ::= "#" "include" "(" string ")" -value ::= [comment] (none | number | boolean | string | array | table | named-array | named-table) +value ::= [comment] (none | number | boolean | string | array | table | named-array | named-table | include) Except for single-line comments, whitespace is not significant. All parsing is case-insensitive. +The include expression pastes the contents of the named file in as if +they appeared in the original source. Note that an include expression +can only appear in the locations where a value is expected. This means +that it cannot yield more than one element of an array and cannot serve +as the pair in a table. + The deserializer allows the substitution of [] for () when writing -tuples and ";" for ",". +tuples and ";" for ",". These are convenient when mimicing a +programming language, e.g., "[ printf("hello world."); clearScreen();]" +parses as an array containing two named arrays within it. The +deserializer also allows a trailing comma inside any array or table, +which also convenient when commenting out the last element. The serializer indents four spaces for each level of nesting. Tables are written with the keys in alphabetic order. @@ -407,9 +440,31 @@ class Any { const std::string& string() const; bool boolean() const; + /** If a valid string, takes the string value and creates a fully qualified filename. + If not found, the returned string is empty. + + The file is searched for the following ways: + + - In the directory from which the Any was loaded. + - By calling System::findDataFile as you would with other data files. + */ + std::string resolveStringAsFilename() const; + /** If this is named ARRAY or TABLE, returns the name. */ const std::string& name() const; + /** If this is named ARRAY or TABLE, returns true if the name begins with \a s. The comparision is case insensitive. */ + bool nameBeginsWith(const std::string& s) const; + + /** If this is named ARRAY or TABLE, returns true if the name begins with \a s. The comparision is case insensitive. */ + bool nameBeginsWith(const char* s) const; + + /** If this is named ARRAY or TABLE, returns true if the name is \a s. The comparision is case insensitive. */ + bool nameEquals(const std::string& s) const; + + /** If this is named ARRAY or TABLE, returns true if the name is\a s. The comparision is case insensitive. */ + bool nameEquals(const char* s) 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 @@ -439,6 +494,14 @@ class Any { const Any& operator[](int i) const; Any& operator[](int i); + const Any& last() const { + return (*this)[size() - 1]; + } + + Any& last() { + return (*this)[size() - 1]; + } + /** Directly exposes the underlying data structure for an ARRAY. */ const Array& array() const; void append(const Any& v0); @@ -456,7 +519,7 @@ class Any { // Needed to prevent the operator[](int) overload from catching // string literals - inline const Any& operator[](const char* key) const { + const Any& operator[](const char* key) const { return operator[](std::string(key)); } @@ -486,7 +549,7 @@ class Any { Any& operator[](const std::string& key); /** \copydoc Any::operator[](const std::string&) */ - inline Any& operator[](const char* key) { + Any& operator[](const char* key) { return operator[](std::string(key)); } @@ -503,6 +566,10 @@ class Any { /** for an ARRAY, resizes and returns the last element */ Any& next(); + /** The parent directory of the location from which this Any was loaded. This is useful for + interpreting filenames relative to the Any's source location, + which may not match the current directory if the Any was from an included file. */ + std::string sourceDirectory() const; /** True if the Anys are exactly equal, ignoring comments. Applies deeply on arrays and tables. */ bool operator==(const Any& x) const; @@ -542,10 +609,15 @@ class 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 */ + + /** Verifies that the name begins with identifier \a n (case insensitive). + It may contain identifier operators after this */ void verifyName(const std::string& n) const; + /** Verifies that the name begins with identifier \a n or \a m (case insensitive). + It may contain identifier operators after this */ + void verifyName(const std::string& n, const std::string& m) const; + /** Verifies that the type is \a t. */ void verifyType(Type t) const; @@ -565,6 +637,124 @@ class Any { }; // class Any + +/** + Convenient iteration over the keys of a Any::TABLE, usually + for implementing construction of an object from an Any. + + Getting an element using either iteration or explicit requests + consumes that element from the iterator (but not from the Any!) + It is an error to consume the same element more than once from + the same iterator. + +
+    AnyKeyIterator r(a);
+    r.getIfPresent("enabled",            enabled);
+    r.getIfPresent("showSamples",        showSamples);
+    r.getIfPresent("showTiles",          showTiles);
+
+    r.verifyDone();
+    
+ + \beta +*/ +class AnyTableReader { +private: + Any m_any; + Set m_alreadyRead; +public: + + /** Verifies that \a is a TABLE with the given \a name. */ + AnyTableReader(const std::string& name, const Any& a) : m_any(a) { + try { + m_any.verifyType(Any::TABLE); + m_any.verifyName(name); + } catch (const ParseError& e) { + // If an exception is thrown, the destructors will not be + // invoked automatically. + m_any.~Any(); + m_alreadyRead.~Set(); + throw e; + } + } + + /** Verifies that \a is a TABLE. */ + AnyTableReader(const Any& a) : m_any(a) { + try { + m_any.verifyType(Any::TABLE); + } catch (const ParseError& e) { + // If an exception is thrown, the destructors will not be + // invoked automatically. + m_any.~Any(); + m_alreadyRead.~Set(); + throw e; + } + } + + bool hasMore() const { + return m_any.size() > m_alreadyRead.size(); + } + + /** Verifies that all keys have been read. */ + void verifyDone() const { + if (hasMore()) { + // Generate all keys + // Remove the ones we've read + // Assert the rest + // any.verify(""); + } + } + +#if 0 + /** Returns the current key */ + const std::string& key() const; + + /** Returns the current value */ + const Any& value() const; + + AnyKeyIterator& operator++(); +#endif + + /** If key \s appears in the any, reads its value into \a v and + removes that key from the ones available to iterate over. + + If key \s does not appear in the any, throws a G3D::ParseError. + + Assumes that if key \s appears in the any it has not already been extracted + by this iterator. If it has been read before, an assertion will fail in debug mode. + + */ + template + void get(const std::string& s, ValueType& v) { + v = m_any[s]; + m_alreadyRead.insert(toLower(s)); + } + + /** Get the value associated with a key only if the key is actually present. + + If key \s appears in the any, reads its value into \a v and + removes that key from the ones available to iterate over. + + If key \s does not appear in the any, does nothing. + + Assumes that if key \s appears in the any it has not already been extracted + by this iterator. If it has been read before, an assertion will fail in debug mode. + + \return True if the value was read. + */ + template + bool getIfPresent(const std::string& s, ValueType& v) { + if (m_any.containsKey(s)) { + debugAssertM(! m_alreadyRead.contains(toLower(s)), "read twice"); + + get(s, v); + return true; + } else { + return false; + } + } +}; + } // namespace G3D #endif diff --git a/dep/include/g3dlite/G3D/BinaryInput.h b/dep/include/g3dlite/G3D/BinaryInput.h index 1dac93ea55e..e8a9b88618b 100644 --- a/dep/include/g3dlite/G3D/BinaryInput.h +++ b/dep/include/g3dlite/G3D/BinaryInput.h @@ -1,12 +1,12 @@ /** @file BinaryInput.h - @maintainer Morgan McGuire, graphics3d.com + @maintainer Morgan McGuire, http://graphics.cs.williams.edu @created 2001-08-09 - @edited 2006-07-19 + @edited 2010-03-19 - Copyright 2000-2009, Morgan McGuire. + Copyright 2000-2010, Morgan McGuire. All rights reserved. */ @@ -370,6 +370,9 @@ class BinaryInput { */ std::string readString(); + /** Reads until \r, \r\n, \n\r, \n or the end of the file is encountered. Consumes the newline.*/ + std::string readStringNewline(); + /** Reads until NULL or the end of the file is encountered. If the string has odd length (including NULL), reads diff --git a/dep/include/g3dlite/G3D/Color3uint8.h b/dep/include/g3dlite/G3D/Color3uint8.h index bd4b00d7fd6..7a1cc79d94d 100644 --- a/dep/include/g3dlite/G3D/Color3uint8.h +++ b/dep/include/g3dlite/G3D/Color3uint8.h @@ -1,20 +1,27 @@ /** @file Color3uint8.h - @maintainer Morgan McGuire, graphics3d.com + @maintainer Morgan McGuire, http://graphics.cs.williams.edu @created 2003-04-07 - @edited 2006-06-24 + @edited 2010-03-24 - Copyright 2000-2006, Morgan McGuire. + Copyright 2000-2010, Morgan McGuire. All rights reserved. */ -#ifndef G3D_COLOR3UINT8_H -#define G3D_COLOR3UINT8_H +#ifndef G3D_Color3uint8_h +#define G3D_Color3uint8_h #include "G3D/platform.h" #include "G3D/g3dmath.h" +#ifdef max +#undef max +#endif + +#ifdef min +#undef min +#endif namespace G3D { @@ -53,7 +60,7 @@ class Color3uint8 { Color3uint8(class BinaryInput& bi); - inline static Color3uint8 fromARGB(uint32 i) { + static Color3uint8 fromARGB(uint32 i) { Color3uint8 c; c.r = (i >> 16) & 0xFF; c.g = (i >> 8) & 0xFF; @@ -61,15 +68,23 @@ class Color3uint8 { return c; } - inline Color3uint8 bgr() const { + Color3uint8 bgr() const { return Color3uint8(b, g, r); } + Color3uint8 max(const Color3uint8 x) const { + return Color3uint8(G3D::max(r, x.r), G3D::max(g, x.g), G3D::max(b, x.b)); + } + + Color3uint8 min(const Color3uint8 x) const { + return Color3uint8(G3D::min(r, x.r), G3D::min(g, x.g), G3D::min(b, x.b)); + } + /** Returns the color packed into a uint32 (the upper byte is 0xFF) */ - inline uint32 asUInt32() const { + uint32 asUInt32() const { return (0xFF << 24) + ((uint32)r << 16) + ((uint32)g << 8) + b; } @@ -95,12 +110,12 @@ class Color3uint8 { return (uint8*)this; } - bool operator==(const Color3uint8& other) const { + 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); + bool operator!=(const Color3uint8 other) const { + return ! (*this == other); } } G3D_END_PACKED_CLASS(1) diff --git a/dep/include/g3dlite/G3D/Color4.h b/dep/include/g3dlite/G3D/Color4.h index d8858abbce2..0be0c25879f 100644 --- a/dep/include/g3dlite/G3D/Color4.h +++ b/dep/include/g3dlite/G3D/Color4.h @@ -117,9 +117,18 @@ class Color4 { Color4 operator+ (const Color4& rkVector) const; Color4 operator- (const Color4& rkVector) const; Color4 operator* (float fScalar) const; - inline Color4 operator* (const Color4& k) const { + Color4 operator* (const Color4& k) const { return Color4(r*k.r, g*k.g, b*k.b, a * k.a); } + + Color4& operator*= (const Color4& c) { + r *= c.r; + g *= c.g; + b *= c.b; + a *= c.a; + return *this; + } + Color4 operator/ (float fScalar) const; Color4 operator- () const; friend Color4 operator* (double fScalar, const Color4& rkVector); diff --git a/dep/include/g3dlite/G3D/Color4uint8.h b/dep/include/g3dlite/G3D/Color4uint8.h index ab8c0729276..2cd3c662788 100644 --- a/dep/include/g3dlite/G3D/Color4uint8.h +++ b/dep/include/g3dlite/G3D/Color4uint8.h @@ -1,12 +1,12 @@ /** @file Color4uint8.h - @maintainer Morgan McGuire, graphics3d.com + @maintainer Morgan McGuire, http://graphics.cs.williams.edu @created 2003-04-07 - @edited 2006-03-24 + @edited 2010-03-24 - Copyright 2000-2006, Morgan McGuire. + Copyright 2000-2010, Morgan McGuire. All rights reserved. */ @@ -50,6 +50,14 @@ class Color4uint8 { Color4uint8(const class Color4& c); + Color4uint8 max(const Color4uint8 x) const { + return Color4uint8(G3D::max(r, x.r), G3D::max(g, x.g), G3D::max(b, x.b), G3D::max(a, x.a)); + } + + Color4uint8 min(const Color4uint8 x) const { + return Color4uint8(G3D::min(r, x.r), G3D::min(g, x.g), G3D::min(b, x.b), G3D::min(a, x.a)); + } + 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) {} diff --git a/dep/include/g3dlite/G3D/CoordinateFrame.h b/dep/include/g3dlite/G3D/CoordinateFrame.h index 7ed4d0acc65..c83754abb77 100644 --- a/dep/include/g3dlite/G3D/CoordinateFrame.h +++ b/dep/include/g3dlite/G3D/CoordinateFrame.h @@ -68,6 +68,8 @@ class CoordinateFrame { - CFrame((matrix3 expr), (vector3 expr)) - CFrame::fromXYZYPRDegrees(#, #, #, #, #, #) - CFrame { rotation = (matrix3 expr), translation = (vector3 expr) } + - Vector3( ... ) + - Matrix3( ... ) */ CoordinateFrame(const Any& any); @@ -109,6 +111,8 @@ class CoordinateFrame { static CoordinateFrame fromXYZYPRRadians(float x, float y, float z, float yaw = 0.0f, float pitch = 0.0f, float roll = 0.0f); + std::string toXYZYPRDegreesString() const; + /** 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 diff --git a/dep/include/g3dlite/G3D/FileSystem.h b/dep/include/g3dlite/G3D/FileSystem.h new file mode 100644 index 00000000000..b2a6e86520c --- /dev/null +++ b/dep/include/g3dlite/G3D/FileSystem.h @@ -0,0 +1,466 @@ +/** + @file FileSystem.h + + @author Morgan McGuire, http://graphics.cs.williams.edu + + @author 2002-06-06 + @edited 2010-02-05 + */ +#ifndef G3D_FileSystem_h +#define G3D_FileSystem_h + +#include "G3D/platform.h" +#include "G3D/Array.h" +#include "G3D/Table.h" + +namespace G3D { + +/** + OS-independent file system layer that optimizes the performance + of queries by caching and prefetching. + + This class uses the following definitions: +
    +
  • "file" = document that can be opened for reading or writing +
  • "directory" = folder containing files and other directories +
  • "node" = file or directory +
  • "path" = string identifying a (see the FSPath class) +
  • "zipfile" = a compressed file storing an archive of files and directories in the zip format +
+ + In G3D, Zipfiles are transparently treated as if they were directories, provided: +
    +
  • The zipfile name contains an extension (e.g., map.pk3, files.zip) +
  • There are no nested zipfiles +
+ + The extension requirement allows G3D to quickly identify whether a path could enter a + zipfile without forcing it to open all parent directories for reading. + + \sa FilePath + TODO: make threadsafe! +*/ +class FileSystem { +public: + + class ListSettings { + public: + /** Defaults to true */ + bool files; + + /** Defaults to true */ + bool directories; + + /** Defaults to true on Windows, false on other platforms.*/ + bool caseSensitive; + + /** Can get recurse into subdirectories? Defaults to true. */ + bool recursive; + + /** Prefix the full path onto names that are returned. Defaults to true */ + bool includeParentPath; + + ListSettings() : + files(true), + directories(true), +# ifdef G3D_WIN32 + caseSensitive(true), +# else + caseSensitive(false), +# endif + recursive(false), + includeParentPath(true) {} + }; + +private: + + /** Drive letters. Only used on windows, but defined on all platforms to help + avoid breaking the Windows build when compiling on another platform. */ + Array m_winDrive; + + float m_cacheLifetime; + + enum Type { + /** Not yet checked */ + UNKNOWN, + FILE_TYPE, + DIR_TYPE + }; + + class Entry { + public: + /** Name, not including parent path */ + std::string name; + Type type; + Entry() : type(UNKNOWN) {} + Entry(const char* n) : name(n), type(UNKNOWN) {} + }; + + class Dir { + public: + + /** If false, this path did not exist (even inside a zipfile) when last checked, or it is not a directory. */ + bool exists; + + bool isZipfile; + bool inZipfile; + + /** Files and directories */ + Array nodeArray; + + /** When this entry was last updated */ + double lastChecked; + + /** Case-independent comparison on Windows */ + bool contains(const std::string& child) const; + + /** Compute the contents of nodeArray from this zipfile. */ + void computeZipListing(const std::string& zipfile, const std::string& pathInsideZipfile); + + Dir() : exists(false), isZipfile(false), inZipfile(false), lastChecked(0) {} + }; + + /** Maps path names (without trailing slashes, except for the file system root) to contents. + On Windows, all paths are lowercase */ + Table m_cache; + + /** Update the cache entry for path if it is not already present. + \param forceUpdate If true, always override the current cache value.*/ + Dir& getContents(const std::string& path, bool forceUpdate); + + /** Don't allow public construction. */ + FileSystem(); + + static FileSystem& instance(); + +# ifdef G3D_WIN32 + /** On Windows, the drive letters that form the file system roots.*/ + const Array& _drives(); +# endif + + /** Returns true if some sub-path of \a path is a zipfile. + + If the path itself is a zipfile, returns false. + + \param zipfile The part of \a path that was the zipfile */ + bool _inZipfile(const std::string& path, std::string& zipfile); + + /** Clears old cache entries so that exists() and list() will reflect recent changes to the file system. + \param path Clear only \a path and its subdirectories ("" means clear the entire cache) */ + void _clearCache(const std::string& path); + + bool _inZipfile(const std::string& path) { + std::string ignore; + return inZipfile(path, ignore); + } + + /** Set the cacheLifetime(). + \param t in seconds */ + void _setCacheLifetime(float t); + + + /** A cache is used to optimize repeated calls. A cache entry is considered + valid for this many seconds after it has been checked. */ + float _cacheLifetime() const { + return m_cacheLifetime; + } + + /** Creates the directory named, including any subdirectories + that do not already exist. + + The directory must not be inside a zipfile. + + Flushes the cache. + */ + void _createDirectory(const std::string& path); + + /** Returns true if a node named \a f exists. + + \param f If \a f contains wildcards, the function returns true if any file + matches those wildcards. Wildcards may only appear in the base or ext, not the + path. + + \param trustCache If true, uses the cache for optimizing repeated calls + in the same parent directory. + */ + bool _exists(const std::string& f, bool trustCache = true); + + /** Known bug: does not work inside zipfiles */ + bool _isDirectory(const std::string& path); + + /** Known bug: does not work inside zipfiles */ + bool _isFile(const std::string& path) { + return ! isDirectory(path); + } + + /** + \param srcPath Must name a file. + \param dstPath Must not contain a zipfile. + + Flushes the cache. + */ + void _copyFile(const std::string& srcPath, const std::string& dstPath); + + /** Fully qualifies a filename. + + The filename may contain wildcards, in which case the wildcards will be preserved in the returned value. + + \param cwd The directory to treat as the "current" directory when resolving a relative path. The default + value is the actual current directory. (G3D::Any::sourceDirectory is a common alternative) + */ + std::string _resolve(const std::string& path, const std::string& cwd = currentDirectory()); + + /** Returns true if \param dst does not exist or \param src is newer than \param dst, + according to their time stamps. + + Known bug: does not work inside zipfiles. + */ + bool _isNewer(const std::string& src, const std::string& dst); + + /** The current working directory (cwd). Only ends in a slash if this is the root of the file system. */ + std::string _currentDirectory(); + + /** Returns the length of the file in bytes, or -1 if the file could not be opened. */ + int64 _size(const std::string& path); + + /** Called from list() */ + void listHelper(const std::string& shortSpec, const std::string& parentPath, Array& result, const ListSettings& settings); + + /** Appends all nodes matching \a spec to the \a result array. + + Wildcards can only appear to the right of the last slash in \a spec. + + The names will not contain parent paths unless \a includePath == true. + These may be relative to the current directory unless \a spec + is fully qualified (can be done with resolveFilename). + + */ + void _list(const std::string& spec, Array& result, const ListSettings& listSettings = ListSettings()); + + /** Returns true if \a path is a file that is a zipfile. Note that G3D requires zipfiles to have + some extension, although it is not required to be "zip" */ + bool _isZipfile(const std::string& path); + + /** list() files */ + void _getFiles(const std::string& spec, Array& result, bool includeParentPath = false) { + ListSettings set; + set.includeParentPath = includeParentPath; + set.directories = false; + set.files = true; + return list(spec, result, set); + } + + /** list() directories */ + void _getDirectories(const std::string& spec, Array& result, bool includeParentPath = false) { + ListSettings set; + set.includeParentPath = includeParentPath; + set.directories = true; + set.files = false; + return list(spec, result, set); + } + + /** Same as the C standard library fopen, but updates the file cache + to acknowledge the new file on a write operation. */ + FILE* _fopen(const char* filename, const char* mode); + +public: + + + /** Create the common instance. */ + static void init(); + + /** Destroy the common instance. */ + static void cleanup(); + +# ifdef G3D_WIN32 + /** \copydoc _drives */ + static const Array& drives() { + return instance()._drives(); + } +# endif + + /** \copydoc _inZipfile */ + static bool inZipfile(const std::string& path, std::string& zipfile) { + return instance()._inZipfile(path, zipfile); + } + + /** \copydoc _clearCache */ + static void clearCache(const std::string& path = "") { + instance()._clearCache(path); + } + + /** \copydoc _fopen */ + static FILE* fopen(const char* filename, const char* mode) { + return instance()._fopen(filename, mode); + } + + static void fclose(FILE* f) { + ::fclose(f); + } + + static bool inZipfile(const std::string& path) { + return instance()._inZipfile(path); + } + + /** \copydoc isZipfile */ + static bool isZipfile(const std::string& path) { + return instance()._isZipfile(path); + } + + /** \copydoc _setCacheLifetime */ + void setCacheLifetime(float t) { + instance()._setCacheLifetime(t); + } + + /** \copydoc _cacheLifetime */ + static float cacheLifetime() { + return instance()._cacheLifetime(); + } + + /** \copydoc _createDirectory */ + static void createDirectory(const std::string& path) { + instance()._createDirectory(path); + } + + /** \copydoc _currentDirectory */ + static std::string currentDirectory() { + return instance()._currentDirectory(); + } + + /** \copydoc _copyFile */ + static void copyFile(const std::string& srcPath, const std::string& dstPath) { + instance()._copyFile(srcPath, dstPath); + } + + /** \copydoc _exists */ + static bool exists(const std::string& f, bool trustCache = true) { + return instance()._exists(f, trustCache); + } + + /** \copydoc _isDirectory */ + static bool isDirectory(const std::string& path) { + return instance()._isDirectory(path); + } + + /** \copydoc _isFile */ + static bool isFile(const std::string& path) { + return instance()._isFile(path); + } + + /** \copydoc _resolve */ + static std::string resolve(const std::string& path, const std::string& cwd = currentDirectory()) { + return instance()._resolve(path, cwd); + } + + /** \copydoc _isNewer */ + static bool isNewer(const std::string& src, const std::string& dst) { + return instance()._isNewer(src, dst); + } + + /** \copydoc _size */ + static int64 size(const std::string& path) { + return instance()._size(path); + } + + /** \copydoc _list */ + static void list(const std::string& spec, Array& result, + const ListSettings& listSettings = ListSettings()) { + return instance()._list(spec, result, listSettings); + } + + /** \copydoc _getFiles */ + static void getFiles(const std::string& spec, Array& result, bool includeParentPath = false) { + return instance()._getFiles(spec, result, includeParentPath); + } + + /** \copydoc getDirectories */ + static void getDirectories(const std::string& spec, Array& result, bool includeParentPath = false) { + return instance()._getDirectories(spec, result, includeParentPath); + } +}; + + +/** \brief Parsing of file system paths. + + None of these routines touch the disk--they are purely string manipulation. + + In "/a/b/base.ext", + +
    +
  • base = "base" +
  • ext = "ext" +
  • parentPath = "/a/b" +
  • baseExt = "base.ext" +
+ +*/ +class FilePath { +public: + + /** Appends file onto dirname, ensuring a / if needed. */ + static std::string concat(const std::string& a, const std::string& b); + + static bool isRoot(const std::string& f); + + /** Removes the trailing slash unless \a f is a filesystem root */ + static std::string removeTrailingSlash(const std::string& f); + + /** Returns everything to the right of the last '.' */ + static std::string ext(const std::string& path); + + /** Returns everything to the right of the last slash (or, on Windows, the last ':') */ + static std::string baseExt(const std::string& path); + + /** Returns everything between the right-most slash and the following '.' */ + static std::string base(const std::string& path); + + /** Returns everything to the left of the right-most slash */ + static std::string parent(const std::string& path); + + /** Returns true if '*' or '?' appear in the filename */ + static bool containsWildcards(const std::string& p); + + /** Convert all slashes to '/' */ + static std::string canonicalize(std::string x); + + /** + 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" + + */ + static void parse + (const std::string& filename, + std::string& drive, + Array& path, + std::string& base, + std::string& ext); + + + /** + Returns true if \a path matches \a pattern, with standard filesystem wildcards. + */ + static bool matches(const std::string& path, const std::string& pattern, bool caseSensitive = true); +}; + +} // namespace G3D +#endif + diff --git a/dep/include/g3dlite/G3D/G3D.h b/dep/include/g3dlite/G3D/G3D.h index 5b56b9c71dc..082d6434842 100644 --- a/dep/include/g3dlite/G3D/G3D.h +++ b/dep/include/g3dlite/G3D/G3D.h @@ -7,7 +7,7 @@ @maintainer Morgan McGuire, http://graphics.cs.williams.edu @created 2001-08-25 - @edited 2010-01-30 + @edited 2010-03-20 Copyright 2000-2010, Morgan McGuire. All rights reserved. @@ -44,6 +44,7 @@ #include "G3D/Matrix4.h" #include "G3D/CoordinateFrame.h" #include "G3D/PhysicsFrame.h" +#include "G3D/PhysicsFrameSpline.h" #include "G3D/Plane.h" #include "G3D/Line.h" #include "G3D/Ray.h" @@ -57,6 +58,7 @@ #include "G3D/stringutils.h" #include "G3D/prompt.h" #include "G3D/Table.h" +#include "G3D/FileSystem.h" #include "G3D/Set.h" #include "G3D/GUniqueID.h" #include "G3D/BinaryFormat.h" @@ -118,6 +120,7 @@ template struct HashTrait< G3D::ReferenceCountedPointer > { #include "G3D/ThreadSet.h" #include "G3D/RegistryUtil.h" #include "G3D/Any.h" +#include "G3D/XML.h" #include "G3D/PointHashGrid.h" #include "G3D/Map2D.h" #include "G3D/Image1.h" diff --git a/dep/include/g3dlite/G3D/GCamera.h b/dep/include/g3dlite/G3D/GCamera.h index 018fbc85d59..1b7b2511b43 100644 --- a/dep/include/g3dlite/G3D/GCamera.h +++ b/dep/include/g3dlite/G3D/GCamera.h @@ -38,6 +38,9 @@ class Any; All viewport arguments are the pixel bounds of the viewport-- e.g., RenderDevice::viewport(). + + See http://bittermanandy.wordpress.com/2009/04/10/a-view-to-a-thrill-part-one-camera-concepts/ + for a nice introduction to camera transformations. */ class GCamera { @@ -64,6 +67,8 @@ class GCamera { /** Horizontal or Vertical */ FOVDirection m_direction; + Vector2 m_pixelOffset; + public: /** Must be of the format produced by the Any cast, e.g., @@ -117,6 +122,18 @@ class GCamera { return m_cframe; } + /** Displacement from the upper left added in pixels in screen + space to the projection matrix. This is useful for shifting + the sampled location from the pixel center (OpenGL convention) + to other locations, such as the upper-left.*/ + void setPixelOffset(const Vector2& p) { + m_pixelOffset = p; + } + + const Vector2& pixelOffset() const { + return m_pixelOffset; + } + /** Sets c to the camera's coordinate frame */ void getCoordinateFrame(CoordinateFrame& c) const; @@ -154,7 +171,7 @@ class GCamera { This is the full angle, i.e., from the left side of the viewport to the right side. */ - void setFieldOfView(float angle, FOVDirection direction); + void setFieldOfView(float edgeToEdgeAngleRadians, FOVDirection direction); /** Returns the current full field of view angle (from the left side of the viewport to the right side) and direction */ diff --git a/dep/include/g3dlite/G3D/GImage.h b/dep/include/g3dlite/G3D/GImage.h index 8ae11134fc9..9a6851d32b3 100644 --- a/dep/include/g3dlite/G3D/GImage.h +++ b/dep/include/g3dlite/G3D/GImage.h @@ -43,9 +43,9 @@ 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 + (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 + and PBM. (Compressed) TGA 24, (Compressed) TGA 32, 8-bit paletted PCX, 24-bit PCX, and ICO are supported for decoding only. Sample usage: @@ -78,6 +78,10 @@ class BinaryOutput; recommended over GImage (we don't include it directly in G3D because their license is more restrictive than the BSD one). + \cite http://tfcduke.developpez.com/tutoriel/format/tga/fichiers/tga_specs.pdf + + \sa Image3, Image3uint8, Image4, Image4uint8, Image1, Image1uint8, Texture, Map2D + */ class GImage { private: diff --git a/dep/include/g3dlite/G3D/GLight.h b/dep/include/g3dlite/G3D/GLight.h index 3a95f1a8114..48e017d365d 100644 --- a/dep/include/g3dlite/G3D/GLight.h +++ b/dep/include/g3dlite/G3D/GLight.h @@ -90,6 +90,13 @@ class GLight { const Color3& color, float constAtt = 1, float linAtt = 0, float quadAtt = 0, bool specular = true, bool diffuse = true); + /** Creates a spot light that looks at a specific point (by calling spot() ) */ + static GLight spotTarget(const Vector3& pos, const Vector3& target, float cutOffAngleDegrees, + const Color3& color, float constAtt = 1, float linAtt = 0, float quadAtt = 0, + bool specular = true, bool diffuse = true) { + return spot(pos, target - pos, cutOffAngleDegrees, color, constAtt, linAtt, quadAtt, specular, diffuse); + } + /** 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; diff --git a/dep/include/g3dlite/G3D/HashTrait.h b/dep/include/g3dlite/G3D/HashTrait.h index ca35da48643..72de3da52fd 100644 --- a/dep/include/g3dlite/G3D/HashTrait.h +++ b/dep/include/g3dlite/G3D/HashTrait.h @@ -52,7 +52,7 @@ template <> struct HashTrait { static size_t hashCode(G3D::uint32 k) { return static_cast(k); } }; -#if 0 +#ifdef G3D_OSX template <> struct HashTrait { static size_t hashCode(G3D::uint32 k) { return static_cast(k); } }; diff --git a/dep/include/g3dlite/G3D/ImageFormat.h b/dep/include/g3dlite/G3D/ImageFormat.h index 7f098322d26..15d2564330f 100644 --- a/dep/include/g3dlite/G3D/ImageFormat.h +++ b/dep/include/g3dlite/G3D/ImageFormat.h @@ -4,7 +4,7 @@ @maintainer Morgan McGuire, http://graphics.cs.williams.edu @created 2003-05-23 - @edited 2010-01-01 + @edited 2010-05-01 */ #ifndef GLG3D_ImageFormat_H @@ -13,6 +13,7 @@ #include "G3D/platform.h" #include "G3D/Table.h" #include "G3D/enumclass.h" +#include "G3D/Any.h" namespace G3D { @@ -57,13 +58,19 @@ class ImageFormat { CODE_RGB8I, CODE_RGB8UI, + CODE_RGBA8UI, + CODE_ARGB8, CODE_BGR8, + CODE_R8, + CODE_RG8, CODE_RG8I, CODE_RG8UI, + CODE_RG16F, + CODE_RGBA8, CODE_RGBA16, CODE_RGBA16F, @@ -260,10 +267,14 @@ class ImageFormat { static const ImageFormat* BGR8(); + static const ImageFormat* R8(); + static const ImageFormat* RG8(); static const ImageFormat* RG8I(); static const ImageFormat* RG8UI(); + static const ImageFormat* RG16F(); + static const ImageFormat* RGB5(); static const ImageFormat* RGB5A1(); @@ -297,6 +308,8 @@ class ImageFormat { static const ImageFormat* RGB8I(); static const ImageFormat* RGB8UI(); + + static const ImageFormat* RGBA8UI(); static const ImageFormat* RGB_DXT1(); @@ -376,9 +389,18 @@ class ImageFormat { NEAREST, BILINEAR, MHC, - HIGH_QUALITY = MHC + BEST = MHC }; private: + static const char* toString(int i, Value& v) { + static const char* str[] = {"NEAREST", "BILINEAR", "MHC", "BEST", NULL}; + static const Value val[] = {NEAREST, BILINEAR, MHC, BEST}; + const char* s = str[i]; + if (s) { + v = val[i]; + } + return s; + } Value value; @@ -399,7 +421,7 @@ class ImageFormat { */ static bool convert(const Array& srcBytes, int srcWidth, int srcHeight, const ImageFormat* srcFormat, int srcRowPadBits, const Array& dstBytes, const ImageFormat* dstFormat, int dstRowPadBits, - bool invertY = false, BayerAlgorithm bayerAlg = BayerAlgorithm::HIGH_QUALITY); + bool invertY = false, BayerAlgorithm bayerAlg = BayerAlgorithm::MHC); /* 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); diff --git a/dep/include/g3dlite/G3D/Matrix2.h b/dep/include/g3dlite/G3D/Matrix2.h index eaf4aefa220..cab70c83e44 100644 --- a/dep/include/g3dlite/G3D/Matrix2.h +++ b/dep/include/g3dlite/G3D/Matrix2.h @@ -1,5 +1,5 @@ -#ifndef G3D_MATRIX2_H -#define G3D_MATRIX2_H +#ifndef G3D_Matrix2_h +#define G3D_Matrix2_h #include "G3D/platform.h" #include "G3D/Vector2.h" @@ -14,54 +14,59 @@ class Matrix2 { public: - inline Matrix2() { + 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) { + 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 { + static Matrix2 identity() { + return Matrix2(1.0f, 0.0f, 0.0f, 1.0f); + } + + 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()); + Matrix2 inverse() const { + return Matrix2(data[1][1], -data[0][1], + -data[1][0], data[0][0]) * (1.0f / determinant()); } - inline Matrix2 transpose() const { + Matrix2 transpose() const { return Matrix2(data[0][0], data[1][0], data[0][1], data[1][1]); } - inline float determinant() const { + float determinant() const { return data[0][0] * data[1][1] - data[0][1] * data[1][0]; } - inline Matrix2 operator*(float f) const { + 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 { + 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) { + float* operator[](int i) { debugAssert(i >= 0 && i <= 2); return data[i]; } - inline const float* operator[](int i) const { + const float* operator[](int i) const { debugAssert(i >= 0 && i <= 1); return data[i]; } + }; } diff --git a/dep/include/g3dlite/G3D/Matrix4.h b/dep/include/g3dlite/G3D/Matrix4.h index 9ce87d875b8..6b810ba77e8 100644 --- a/dep/include/g3dlite/G3D/Matrix4.h +++ b/dep/include/g3dlite/G3D/Matrix4.h @@ -119,6 +119,15 @@ class Matrix4 { } Matrix4 operator*(const Matrix4& other) const; + Matrix4 operator+(const Matrix4& other) const { + Matrix4 result; + for (int r = 0; r < 4; ++r) { + for (int c = 0; c < 4; ++c) { + result.elt[r][c] = elt[r][c] + other.elt[r][c]; + } + } + return result; + } class Matrix3 upper3x3() const; diff --git a/dep/include/g3dlite/G3D/MeshAlg.h b/dep/include/g3dlite/G3D/MeshAlg.h index 1decea10105..da55d13000a 100644 --- a/dep/include/g3dlite/G3D/MeshAlg.h +++ b/dep/include/g3dlite/G3D/MeshAlg.h @@ -600,7 +600,7 @@ class MeshAlg { outIndices.resize(N + (inSize - 2) * 3); bool atEven = false; - for (IndexType i = 0, outIndex = N; i <= (inSize - 2); ++i, outIndex += 3) { + for (IndexType i = 0, outIndex = N; i < (inSize - 2); ++i, outIndex += 3) { if (atEven) { outIndices[outIndex] = inIndices[i + 1]; outIndices[outIndex + 1] = inIndices[i]; diff --git a/dep/include/g3dlite/G3D/NetAddress.h b/dep/include/g3dlite/G3D/NetAddress.h index 8ed20a06690..fd5a199593b 100644 --- a/dep/include/g3dlite/G3D/NetAddress.h +++ b/dep/include/g3dlite/G3D/NetAddress.h @@ -1,33 +1,9 @@ -#ifndef G3D_NETADDRESS_H -#define G3D_NETADDRESS_H +#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 -# elif (G3D_WINSOCK_MAJOR_VERSION == 1) -# include -# endif -#else -# include -# include -# include -# ifndef SOCKADDR_IN -# define SOCKADDR_IN struct sockaddr_in -# endif -# ifndef SOCKET -# define SOCKET int -# endif -#endif +#include "G3D/netheaders.h" #include "G3D/g3dmath.h" diff --git a/dep/include/g3dlite/G3D/NetworkDevice.h b/dep/include/g3dlite/G3D/NetworkDevice.h index ea3290cbc09..7a3f8ed4aca 100644 --- a/dep/include/g3dlite/G3D/NetworkDevice.h +++ b/dep/include/g3dlite/G3D/NetworkDevice.h @@ -258,8 +258,8 @@ class ReliableConduit : public Conduit { ~ReliableConduit(); - // The message is actually copied from the socket to an internal buffer during - // this call. Receive only deserializes. + /** The message is actually copied from the socket to an internal buffer during + this call. Receive only deserializes.*/ virtual bool messageWaiting(); /** @@ -348,6 +348,7 @@ class ReliableConduit : public Conduit { messageWaiting(); } + /** The address of the other end of the conduit */ NetAddress address() const; }; diff --git a/dep/include/g3dlite/G3D/PhysicsFrame.h b/dep/include/g3dlite/G3D/PhysicsFrame.h index a5a9305b83e..9aee5e5a883 100644 --- a/dep/include/g3dlite/G3D/PhysicsFrame.h +++ b/dep/include/g3dlite/G3D/PhysicsFrame.h @@ -43,19 +43,27 @@ class PhysicsFrame { PhysicsFrame(); /** - Purely translational force + Purely translational. */ PhysicsFrame(const Vector3& translation) : translation(translation) {} - + PhysicsFrame(const Quat& rot, const Vector3& translation) : rotation(rot), translation(translation) {} + PhysicsFrame(const Matrix3& rot, const Vector3& translation) : rotation(rot), translation(translation) {} + PhysicsFrame(const Matrix3& rot) : rotation(rot), translation(Vector3::zero()) {} PhysicsFrame(const CoordinateFrame& coordinateFrame); + /** + - PhysicsFrame( [quat], [vec3] ) + - Vector3( ... ) + - CFrame( ... ) + - CFrame::from...( ... ) + */ + PhysicsFrame(const class Any& any); + /** Compose: create the transformation that is other followed by this.*/ PhysicsFrame operator*(const PhysicsFrame& other) const; virtual ~PhysicsFrame() {} - CoordinateFrame toCoordinateFrame() const; - /** Linear interpolation (spherical linear for the rotations). */ @@ -67,8 +75,35 @@ class PhysicsFrame { void serialize(class BinaryOutput& b) const; + operator CFrame() const; + + /** Multiplies both pieces by \a f; note that this will result in a non-unit + quaternion that needs to be normalized */ + PhysicsFrame& operator*=(float f) { + rotation *= f; + translation *= f; + return *this; + } + + /** Multiplies both pieces by \a f; note that this will result in a non-unit + quaternion that needs to be normalized */ + PhysicsFrame operator*(float f) const { + return PhysicsFrame(rotation * f, translation * f); + } + + PhysicsFrame operator+(const PhysicsFrame& f) const { + return PhysicsFrame(rotation + f.rotation, translation + f.translation); + } + + PhysicsFrame& operator+=(const PhysicsFrame& f) { + rotation += f.rotation; + translation += f.translation; + return *this; + } }; +typedef PhysicsFrame PFrame; + } // namespace #endif diff --git a/dep/include/g3dlite/G3D/PhysicsFrameSpline.h b/dep/include/g3dlite/G3D/PhysicsFrameSpline.h new file mode 100644 index 00000000000..4a21503df35 --- /dev/null +++ b/dep/include/g3dlite/G3D/PhysicsFrameSpline.h @@ -0,0 +1,37 @@ +/** + @file PhysicsFrameSpline.h + + @author Morgan McGuire, http://graphics.cs.williams.edu + */ +#ifndef G3D_PhysicsFrameSpline_h +#define G3D_PhysicsFrameSpline_h + +#include "G3D/platform.h" +#include "G3D/PhysicsFrame.h" +#include "G3D/Spline.h" + +namespace G3D { + +/** + A subclass of Spline that keeps the rotation field of a + PhysicsFrame normalized and rotating the short direction. + + \sa UprightFrameSpline + */ +class PhysicsFrameSpline : public Spline { +public: + PhysicsFrameSpline(); + + /** Accepts a table of properties, or any valid PhysicsFrame specification for a single control*/ + PhysicsFrameSpline(const Any& any); + + /** Clear and then reset all values from the any */ + PhysicsFrameSpline& operator=(const Any& any); + + virtual void correct(PhysicsFrame& frame) const; + virtual void ensureShortestPath(PhysicsFrame* A, int N) const; +}; + +} + +#endif diff --git a/dep/include/g3dlite/G3D/PointHashGrid.h b/dep/include/g3dlite/G3D/PointHashGrid.h index 0db9e677321..d0b60a88ae5 100644 --- a/dep/include/g3dlite/G3D/PointHashGrid.h +++ b/dep/include/g3dlite/G3D/PointHashGrid.h @@ -5,7 +5,7 @@ @created 2008-07-01 @edited 2009-05-28 - Copyright 2000-2009, Morgan McGuire. + Copyright 2000-2010, Morgan McGuire. All rights reserved. */ #ifndef G3D_PointHashGrid_h @@ -30,18 +30,44 @@ namespace G3D { approximately uniform density (with respect to the radius hint), the time cost of searching for neighbors is O(1). - Value must be supported by a G3D::PositionTrait, - G3D::EqualsTrait, and G3D::HashFunc. overrides are provided for - common G3D classes like G3D::Vector3. + Value must be supported by a G3D::PositionTrait and + G3D::EqualsTrait. Overloads are provided for + common G3D classes like G3D::Vector3. For example: + +
+    class EqualsFunc {
+    public:
+        static bool equals(const Data& p, const Data& q) {
+            return p == q;
+        }
+    };
+    
+    class PosFunc {
+    public:
+        static void getPosition(const Data& d, Vector3& pos) {
+            pos = d.location;
+        }
+    };
+
+    PointHashGrid grid;
+   
+ + If the Value class defines operator==, the Equalsfunc is optional: + +
+    PointHashGrid grid;
+   
+ */ template, - class EqualsFunc = EqualsTrait, - class HashFunc = HashTrait > + class EqualsFunc = EqualsTrait > class PointHashGrid { private: -#define ThisType PointHashGrid +# define expectedCellSize (3) + +# define ThisType PointHashGrid /** A value annotated with precomputed position and hash code.*/ class Entry { @@ -51,8 +77,8 @@ class PointHashGrid { }; /** One cell of the grid. */ - typedef Array Cell; - typedef Table CellTable; + typedef SmallArray Cell; + typedef Table CellTable; /** The cube of +/-1 along each dimension. Initialized by initOffsetArray.*/ Vector3int32 m_offsetArray[3*3*3]; @@ -182,11 +208,11 @@ class PointHashGrid { Array entry(init.size()); for (int i = 0; i < entry.size(); ++i) { const Value& value = init[i]; - Vector3 pos = m_posFunc(value); + Vector3 pos; entry[i].value = value; entry[i].hashCode = m_hashFunc(value); - entry[i].position = pos; + PosFunc::getPosition(value, entry[i].position); lo = lo.min(pos); hi = hi.max(pos); @@ -334,7 +360,7 @@ class PointHashGrid { m_arrayIndex(0), m_epoch(0) {} Iterator(const ThisType* grid) : - m_isEnd(false), + m_isEnd(grid->size() == 0), m_grid(grid), m_tableIterator( grid->m_data.begin() ), m_arrayIndex(0), @@ -361,6 +387,10 @@ class PointHashGrid { } } + bool hasMore() const { + return ! m_isEnd; + } + bool operator==(const Iterator& other) const { return !(*this != other); } diff --git a/dep/include/g3dlite/G3D/Quat.h b/dep/include/g3dlite/G3D/Quat.h index 9ef3d57b301..d8fdfafeca4 100644 --- a/dep/include/g3dlite/G3D/Quat.h +++ b/dep/include/g3dlite/G3D/Quat.h @@ -21,6 +21,8 @@ namespace G3D { /** + Arbitrary quaternion (not necessarily unit) + Unit quaternions are used in computer graphics to represent rotation about an axis. Any 3x3 rotation matrix can be stored as a quaternion. @@ -42,7 +44,7 @@ namespace G3D { Do not subclass. BETA API -- subject to change - @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. + \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: @@ -63,31 +65,100 @@ class Quat { float x, y, z, w; /** - Initializes to a zero degree rotation. + Initializes to a zero degree rotation, (0,0,0,1) */ - inline Quat() : x(0), y(0), z(0), w(1) {} + Quat() : x(0), y(0), z(0), w(1) {} + + /** Expects "Quat(x,y,z,w)" or a Matrix3 constructor. */ + Quat(const class Any& a); - Quat( - const Matrix3& rot); + Quat(const Matrix3& rot); - inline Quat(float _x, float _y, float _z, float _w) : + 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) { + 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 { + const float& real() const { return w; } - inline float& real() { + float& real() { return w; } + Quat operator-() const { + return Quat(-x, -y, -z, -w); + } + + Quat operator-(const Quat& other) const { + return Quat(x - other.x, y - other.y, z - other.z, w - other.w); + } + + Quat& operator-=(const Quat& q) { + x -= q.x; + y -= q.y; + z -= q.z; + w -= q.w; + return *this; + } + + Quat operator+(const Quat& q) const { + return Quat(x + q.x, y + q.y, z + q.z, w + q.w); + } + + Quat& operator+=(const Quat& q) { + x += q.x; + y += q.y; + z += q.z; + w += q.w; + return *this; + } + + /** + Negates the imaginary part. + */ + Quat conj() const { + return Quat(-x, -y, -z, w); + } + + float sum() const { + return x + y + z + w; + } + + float average() const { + return sum() / 4.0f; + } + + Quat operator*(float s) const { + return Quat(x * s, y * s, z * s, w * s); + } + + 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); + } + + float dot(const Quat& other) const { + return (x * other.x) + (y * other.y) + (z * other.z) + (w * other.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); @@ -100,18 +171,14 @@ class Quat { 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 { + const Vector3& imag() const { return *(reinterpret_cast(this)); } - inline Vector3& imag() { + Vector3& imag() { return *(reinterpret_cast(this)); } @@ -158,43 +225,7 @@ class Quat { /** 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-1 = q.conj() for a unit quaternion. @cite Dam99 page 13 */ @@ -202,10 +233,6 @@ class Quat { 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. @@ -217,18 +244,16 @@ class Quat { return (*this) * other.inverse(); } - /** Is the magnitude nearly 1.0? */ - inline bool isUnit(float tolerance = 1e-5) const { + bool isUnit(float tolerance = 1e-5) const { return abs(dot(*this) - 1.0f) < tolerance; - } - + } - inline float magnitude() const { + float magnitude() const { return sqrtf(dot(*this)); } - inline Quat log() const { + Quat log() const { if ((x == 0) && (y == 0) && (z == 0)) { if (w > 0) { return Quat(0, 0, 0, ::logf(w)); @@ -289,18 +314,16 @@ class Quat { return (log() * x).exp(); } - inline void unitize() { - float mag2 = dot(*this); - if (! G3D::fuzzyEq(mag2, 1.0f)) { - *this *= rsq(mag2); - } + /** Make unit length in place */ + void unitize() { + *this *= rsq(dot(*this)); } /** Returns a unit quaterion obtained by dividing through by the magnitude. */ - inline Quat toUnit() const { + Quat toUnit() const { Quat x = *this; x.unitize(); return x; @@ -312,7 +335,7 @@ class Quat { n(q) value used in Eberly's 1999 paper, which is the square of the norm. */ - inline float norm() const { + float norm() const { return magnitude(); } @@ -706,13 +729,6 @@ inline const float& Quat::operator[] (int i) const { 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 diff --git a/dep/include/g3dlite/G3D/Set.h b/dep/include/g3dlite/G3D/Set.h index 9a8e1b619bb..0ea96b880cf 100644 --- a/dep/include/g3dlite/G3D/Set.h +++ b/dep/include/g3dlite/G3D/Set.h @@ -57,9 +57,12 @@ class Set { /** Inserts into the table if not already present. + Returns true if this is the first time the element was added. */ - void insert(const T& member) { - memberTable.set(member, true); + bool insert(const T& member) { + bool isNew = false; + memberTable.getCreate(member, isNew) = true; + return isNew; } /** diff --git a/dep/include/g3dlite/G3D/SmallArray.h b/dep/include/g3dlite/G3D/SmallArray.h index 41f9959e264..900d2335ee1 100644 --- a/dep/include/g3dlite/G3D/SmallArray.h +++ b/dep/include/g3dlite/G3D/SmallArray.h @@ -2,9 +2,9 @@ @file SmallArray.h @created 2009-04-26 - @edited 2009-04-26 + @edited 2010-02-26 - Copyright 2000-2009, Morgan McGuire, http://graphics.cs.williams.edu + Copyright 2000-2010, Morgan McGuire, http://graphics.cs.williams.edu All rights reserved. */ #ifndef G3D_SmallArray_h @@ -12,6 +12,7 @@ #include "G3D/platform.h" #include "G3D/Array.h" +#include "G3D/MemoryManager.h" namespace G3D { @@ -46,6 +47,11 @@ class SmallArray { resize(0, shrinkIfNecessary); } + void clearAndSetMemoryManager(MemoryManager::Ref& m) { + clear(); + m_rest.clearAndSetMemoryManager(m); + } + inline T& operator[](int i) { debugAssert(i < m_size && i >= 0); if (i < N) { @@ -77,7 +83,7 @@ class SmallArray { push(v); } - void fastRemove(int i) { + void fastRemove(int i, bool shrinkIfNecessary = false) { debugAssert(i < m_size && i >= 0); if (i < N) { if (m_size <= N) { @@ -89,7 +95,7 @@ class SmallArray { } } else { // Removing from the rest array - m_rest.fastRemove(i - N); + m_rest.fastRemove(i - N, shrinkIfNecessary); } --m_size; } diff --git a/dep/include/g3dlite/G3D/Sphere.h b/dep/include/g3dlite/G3D/Sphere.h index 595b61c4bf1..d1448261d9f 100644 --- a/dep/include/g3dlite/G3D/Sphere.h +++ b/dep/include/g3dlite/G3D/Sphere.h @@ -15,7 +15,6 @@ #include "G3D/platform.h" #include "G3D/Vector3.h" #include "G3D/Array.h" -#include "G3D/Sphere.h" namespace G3D { diff --git a/dep/include/g3dlite/G3D/Spline.h b/dep/include/g3dlite/G3D/Spline.h index fdd29e69ce9..89f89194f1e 100644 --- a/dep/include/g3dlite/G3D/Spline.h +++ b/dep/include/g3dlite/G3D/Spline.h @@ -100,7 +100,7 @@ class SplineBase { See Real Time Rendering, 2nd edition, ch 12 for a general discussion of splines and their properties. - @sa G3D::UprightSpline, G3D::QuatSpline + \sa G3D::UprightSpline */ template class Spline : public SplineBase { @@ -270,7 +270,7 @@ class Spline : public SplineBase { } /** - Mutates the array of N control points. It is useful to override this + Mutates the array of N control points that begins at \a A. 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. */ @@ -333,10 +333,6 @@ class Spline : public SplineBase { 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 @@ -346,12 +342,17 @@ class Spline : public SplineBase { float n0 = x / dt0; float n1 = x / dt1; float n2 = x / dt2; + + const Control& dp0 = p1 + (p0*-1.0f); + const Control& dp1 = p2 + (p1*-1.0f); + const Control& dp2 = p3 + (p2*-1.0f); + const Control& dp1n1 = dp1 * n1; const Control& tan1 = dp0 * n0 + dp1n1; const Control& tan2 = dp1n1 + dp2 * n2; sum = - tan1 * weights[0]+ + tan1 * weights[0] + p1 * weights[1] + p2 * weights[2] + tan2 * weights[3]; diff --git a/dep/include/g3dlite/G3D/System.h b/dep/include/g3dlite/G3D/System.h index 56ef9c8e3dc..070ae10c69c 100644 --- a/dep/include/g3dlite/G3D/System.h +++ b/dep/include/g3dlite/G3D/System.h @@ -1,8 +1,8 @@ -/** +/** @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 @@ -39,7 +39,7 @@ 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. + string that must appear in your documentation. Your program can be commercial, closed-source under any license you want. @deprecated Use System::license @@ -48,19 +48,19 @@ std::string license(); /** @brief The order in which the bytes of an integer are stored on a -machine. +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_BIG_ENDIAN, G3D_LITTLE_ENDIAN }; /** - @brief OS and processor abstraction. + @brief OS and processor abstraction. The first time any method is called the processor will be analyzed. Future calls are then fast. @@ -83,7 +83,7 @@ class System { @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 + 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 @@ -140,7 +140,7 @@ class System { /** @brief Used for the singleton instance only. */ System(); - /** @brief The singleton instance. + /** @brief The singleton instance. Used instead of a global variable to ensure that the order of intialization is correct, which is critical because other @@ -155,7 +155,7 @@ class System { CPUID_GET_HIGHEST_FUNCTION = 0x80000000, CPUID_EXTENDED_FEATURES = 0x80000001}; - /** Helper macro to call cpuid functions and return all values + /** 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 @@ -171,10 +171,10 @@ class System { /** Called from init() */ void initTime(); - + public: - /** Returns the speed of processor 0 in MHz. + /** Returns the speed of processor 0 in MHz. Always returns 0 on linux.*/ inline static int cpuSpeedMHz() { return instance().m_cpuSpeed; @@ -229,7 +229,7 @@ class System { inline static const std::string& operatingSystem() { return instance().m_operatingSystem; } - + /** e.g., 80686 */ inline static const std::string& cpuArchitecture() { return instance().m_cpuArch; @@ -241,24 +241,24 @@ class System { static std::string currentDateString(); /** - Guarantees that the start of the array is aligned to the + 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); /** @@ -272,7 +272,7 @@ class System { static std::string mallocPerformance(); static void resetMallocPerformanceCounters(); - /** + /** Returns a string describing the current usage of the buffer pools used for optimizing System::malloc. */ @@ -294,12 +294,12 @@ class System { 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. @@ -331,7 +331,7 @@ class System { /** 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() + The sleep will be extremely precise; it uses System::time() to calibrate the exact yeild time. */ static void sleep(RealTime t); @@ -347,7 +347,7 @@ class System { 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 @@ -358,7 +358,7 @@ class System { /** 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(). */ @@ -375,10 +375,10 @@ class System { // count now contains the cycle count for the intervening operation. */ - /* static void beginCycleCount(uint64& cycleCount); + static void beginCycleCount(uint64& cycleCount); static void endCycleCount(uint64& cycleCount); - static uint64 getCycleCount(); */ + static uint64 getCycleCount(); inline static void setOutOfMemoryCallback(OutOfMemoryCallback c) { instance().m_outOfMemoryCallback = c; @@ -392,7 +392,7 @@ class System { 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 + You can use outOfMemoryCallback to free data structures or to register the failure. */ inline static OutOfMemoryCallback outOfMemoryCallback() { @@ -401,7 +401,7 @@ class System { /** 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); @@ -426,7 +426,7 @@ class System { 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); /** @@ -438,7 +438,7 @@ class System { }; -/* don't need that for MaNGOS, not portable to Win64... + #ifdef _MSC_VER inline uint64 System::getCycleCount() { uint32 timehi, timelo; @@ -472,11 +472,11 @@ class System { #elif defined(G3D_OSX) inline uint64 System::getCycleCount() { - //Note: To put off extra processing until the end, this does not + //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(); } @@ -493,14 +493,14 @@ inline void System::endCycleCount(uint64& cycleCount) { cycleCount = getCycleCount() - cycleCount; #else AbsoluteTime end = UpTime(); - Nanoseconds diffNS = + Nanoseconds diffNS = AbsoluteDeltaToNanoseconds(end, UInt64ToUnsignedWide(cycleCount)); - cycleCount = - (uint64) ((double) (instance().m_OSXCPUSpeed) * + cycleCount = + (uint64) ((double) (instance().m_OSXCPUSpeed) * (double) UnsignedWideToUInt64(diffNS) * instance().m_secondsPerNS); #endif } - */ + } // namespace diff --git a/dep/include/g3dlite/G3D/Table.h b/dep/include/g3dlite/G3D/Table.h index 287efa94d97..ab0b114b1c4 100644 --- a/dep/include/g3dlite/G3D/Table.h +++ b/dep/include/g3dlite/G3D/Table.h @@ -86,12 +86,11 @@ namespace G3D {
     template<> struct HashTrait {
-        static size_t equals(const MyEnum& key) const { return reinterpret_cast( key ); }
+        static size_t hashCode(const MyEnum& key) const { return reinterpret_cast( key ); }
     };
   
- And rely on the default enum operator==. - + 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 @@ -846,7 +845,7 @@ class Table { return true; } node = node->next; - } while (node != NULL); + } return false; } diff --git a/dep/include/g3dlite/G3D/TextInput.h b/dep/include/g3dlite/G3D/TextInput.h index 33eb8c48e53..7aefb50ffa8 100644 --- a/dep/include/g3dlite/G3D/TextInput.h +++ b/dep/include/g3dlite/G3D/TextInput.h @@ -8,9 +8,9 @@ @cite Based on a lexer written by Aaron Orenstein. @created 2002-11-27 - @edited 2009-11-24 + @edited 2010-07-03 - Copyright 2000-2009, Morgan McGuire. + Copyright 2000-2010, Morgan McGuire. All rights reserved. */ @@ -76,6 +76,7 @@ class Token { bool _bool; int _line; int _character; + uint64 _bytePosition; Type _type; ExtendedType _extendedType; @@ -86,14 +87,15 @@ class Token { _bool(false), _line(0), _character(0), + _bytePosition(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, int L, int c, uint64 byte) + : _string(s), _bool(false), _line(L), _character(c), _bytePosition(byte), _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) {} + Token(Type t, ExtendedType e, const std::string& s, bool b, int L, int c, uint64 byte) + : _string(s), _bool(b), _line(L), _character(c), _bytePosition(byte), _type(t), _extendedType(e) {} Type type() const { return _type; @@ -132,6 +134,12 @@ class Token { return _character; } + /** Number of bytes from the beginning of the buffer that this token was parsed from. + Begins at 0 */ + uint64 bytePosition() const { + return _bytePosition; + } + /** Return the numeric value for a number type, or zero if this is not a number type. */ @@ -212,6 +220,12 @@ class Token { */ class TextInput { public: + /** Includes MSVC specials parsing */ + static double parseNumber(const std::string& _string); + + /** toLower(_string) == "true" */ + static bool parseBoolean(const std::string& _string); + /** Tokenizer configuration options. */ class Settings { @@ -316,12 +330,13 @@ class TextInput { /** 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. + nan(), -1.#INF00 as -G3D::inf(), and 1.#INF00 as G3D::inf(). + + Note that the C99 standard specifies that a variety of formats + like "nan" are to be used; these are supported by + G3D::TextInput::Settings::simpleFloatSpecials. - An alternative to specifying msvcSpecials is to read numbers as: + An alternative to specifying msvcFloatSpecials is to read numbers as:
             Token x = t.read();
             Token y = t.peek();
@@ -339,10 +354,14 @@ class TextInput {
           special format overrides the comment and will be parsed
           instead.
 
-          If signedNumbers is false msvcSpecials will not be parsed.
+          If signedNumbers is false msvcFloatSpecials will not be parsed.
 
           Default is true. */
-        bool                msvcSpecials;
+        bool                msvcFloatSpecials;
+
+        /** Parses "+inf', "-inf", "inf", "nan" as floats instead of symbols. 
+            Defaults to true.*/
+        bool                simpleFloatSpecials;
 
         /**
          Parse the following set of useful proof symbols:
@@ -362,7 +381,7 @@ class TextInput {
         bool                proofSymbols;
 
         /**
-         When parsing booleans and msvcSpecials, is case significant?
+         When parsing booleans and msvcFloatSpecials, is case significant?
          Default is {true}
         */
         bool                caseSensitive;
@@ -623,9 +642,17 @@ class TextInput {
         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.
+
+        \sa readString(), readStringToken(), readUntilNewlineAsString()
       */
     void readString(const std::string& s);
 
+    /** Read from the beginning of the next token until the following newline 
+      and return the result as a string, ignoring all parsing in between. The newline 
+      is not returned in the string, and the following token read will be a newline or
+      end of file token (if they are enabled for parsing).*/
+    std::string readUntilNewlineAsString();
+
     /** Reads a comment token or throws WrongTokenType, and returns the token.
 
         Use this method (rather than readComment) if you want the token's
@@ -733,13 +760,13 @@ class TextInput {
 
 
     /** Read a series of two specific symbols.  See readSymbol.  */
-    inline void readSymbols(const std::string& s1, const std::string& s2) {
+    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(
+    void readSymbols(
         const std::string& s1, 
         const std::string& s2, 
         const std::string& s3) {
@@ -749,7 +776,7 @@ class TextInput {
     }
 
     /** Read a series of four specific symbols.  See readSymbol.  */
-    inline void readSymbols(
+    void readSymbols(
         const std::string& s1, 
         const std::string& s2, 
         const std::string& s3,     
diff --git a/dep/include/g3dlite/G3D/Vector3.h b/dep/include/g3dlite/G3D/Vector3.h
index 4825efb9985..b4e684b92e5 100644
--- a/dep/include/g3dlite/G3D/Vector3.h
+++ b/dep/include/g3dlite/G3D/Vector3.h
@@ -209,9 +209,9 @@ class Vector3 {
      */
     inline Vector3 directionOrZero() const {
         float mag = magnitude();
-        if (G3D::fuzzyEq(mag, 0.0f)) {
+        if (mag < 0.0000001f) {
             return Vector3::zero();
-        } else if (G3D::fuzzyEq(mag, 1.0f)) {
+        } else if (mag < 1.00001f && mag > 0.99999f) {
             return *this;
         } else {
             return *this * (1.0f / mag);
diff --git a/dep/include/g3dlite/G3D/Vector3int16.h b/dep/include/g3dlite/G3D/Vector3int16.h
index 3197ea49d1a..6043aea9f61 100644
--- a/dep/include/g3dlite/G3D/Vector3int16.h
+++ b/dep/include/g3dlite/G3D/Vector3int16.h
@@ -80,7 +80,7 @@ class Vector3int16 {
     inline Vector3int16& operator+=(const Vector3int16& other) {
         x += other.x;
         y += other.y;
-        z += other.y;
+        z += other.z;
         return *this;
     }
 
diff --git a/dep/include/g3dlite/G3D/WrapMode.h b/dep/include/g3dlite/G3D/WrapMode.h
index 8ef38a77c23..25a2fb47256 100644
--- a/dep/include/g3dlite/G3D/WrapMode.h
+++ b/dep/include/g3dlite/G3D/WrapMode.h
@@ -4,7 +4,7 @@
   @maintainer Morgan McGuire, http://graphics.cs.williams.edu
  
   @created 2007-04-17
-  @edited  2007-04-17
+  @edited  2010-04-17
 
   Copyright 2000-2010, Morgan McGuire.
   All rights reserved.
@@ -15,6 +15,7 @@
 
 #include "G3D/platform.h"
 #include "G3D/enumclass.h"
+#include "G3D/Any.h"
 
 #ifdef IGNORE
 #   undef IGNORE
@@ -65,25 +66,22 @@ class WrapMode {
 
 private:
     
+    static const char* toString(int i, Value& v) {
+        static const char* str[] = {"CLAMP", "TILE", "ZERO", "IGNORE", "ERROR", NULL}; 
+        static const Value val[] = {CLAMP, TILE, ZERO, IGNORE, ERROR};
+        const char* s = str[i];
+        if (s) {
+            v = val[i];
+        }
+        return s;
+    }
+
     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
diff --git a/dep/include/g3dlite/G3D/XML.h b/dep/include/g3dlite/G3D/XML.h
new file mode 100644
index 00000000000..9ff98f9d171
--- /dev/null
+++ b/dep/include/g3dlite/G3D/XML.h
@@ -0,0 +1,204 @@
+/**
+ @file XML.h
+  
+ @author Morgan McGuire
+ @maintainer Morgan McGuire
+  
+ @created 2010-02-11
+ @edited  2010-02-24
+
+ Copyright 2000-2010, Morgan McGuire.
+ All rights reserved.
+ */
+
+#ifndef G3D_XML_h
+#define G3D_XML_h
+
+#include "G3D/platform.h"
+#include "G3D/Table.h"
+#include "G3D/Array.h"
+#include "G3D/format.h"
+#include 
+
+namespace G3D {
+
+class TextInput;
+class TextOutput;
+
+/** 
+\brief Easy loading and saving of XML and HTML files.
+
+The XML class is intended primarily for interchange with other
+programs. We recommend using G3D::Any to make your own human-readable
+formats because it is a more general syntax, the implementation is
+more efficient, and contains better error handling.
+
+Every XML is either a VALUE, or a TAG that contains both
+a table of its XML attributes and an array of its children. Children
+are nested tags and the strings between the nested tags.
+
+No validation is performed, and the XML must be completely legal.  XML
+Entity references (e.g., the ampersand codes for greater than and less
+than) are not automatically converted.
+
+Tags with names that begin with "!" or "?" are ignored. Comment tags must
+end with "-->" e.g.,
+
+
+  
+  
+  
+
+ +\sa G3D::Any, http://www.grinninglizard.com/tinyxml/ + +
+
+  child0 ...
+  ...
+  child2 ...
+
+
+*/ +class XML { +public: + + enum Type {VALUE, TAG}; + + typedef Table AttributeTable; + +private: + + Type m_type; + std::string m_name; + std::string m_value; + AttributeTable m_attribute; + Array m_child; + +public: + + XML() : m_type(VALUE) {} + + XML(const std::string& v) : m_type(VALUE), m_value(v) {} + + XML(const double& v) : m_type(VALUE), m_value(format("%f", v)) {} + + XML(float v) : m_type(VALUE), m_value(format("%f", v)) {} + + XML(int v) : m_type(VALUE), m_value(format("%d", v)) {} + + /** \param tagType Must be XML::TAG to dismbiguate from the string constructor */ + XML(Type tagType, const std::string& name, const AttributeTable& at, const Array& ch = Array()) : m_type(TAG), m_name(name), m_attribute(at), m_child(ch) { + (void)tagType; + debugAssert(tagType == TAG); + } + + /** \param tagType Must be XML::TAG to dismbiguate from the string constructor */ + XML(Type tagType, const std::string& name, const Array& ch = Array()) : m_type(TAG), m_name(name), m_child(ch) { + (void)tagType; + debugAssert(tagType == TAG); + } + + XML(TextInput& t); + + void serialize(TextOutput& t) const; + + void deserialize(TextInput& t); + + void load(const std::string& filename); + + void save(const std::string& filename) const; + + void parse(const std::string &s); + + void unparse(std::string& s) const; + + const AttributeTable& attributeTable() const { + return m_attribute; + } + + const Array childArray() const { + return m_child; + } + + /** Array size; zero for a VALUE */ + int numChildren() const { + return m_child.size(); + } + + /** Attribute table size; zero for a TAG */ + int numAttributes() const { + return m_attribute.size(); + } + + /** Return child \a i. Children are nested tags and the unquoted + strings of characters between tags.*/ + const XML& operator[](int i) const { + return m_child[i]; + } + + /** Return the attribute with this name. */ + const XML& operator[](const std::string& k) const { + return m_attribute[k]; + } + + const bool containsAttribute(const std::string& k) const { + return m_attribute.containsKey(k); + } + + /** Note that the result is always copied, making this inefficient + for return values that are not VALUEs. */ + XML get(const std::string& k, const XML& defaultVal) const { + const XML* x = m_attribute.getPointer(k); + if (x) { + return *x; + } else { + return defaultVal; + } + } + + Type type() const { + return m_type; + } + + /** The name, if this is a TAG. */ + const std::string name() const { + return m_name; + } + + /** Returns "" if a TAG. */ + const std::string& string() const { + return m_value; + } + + /** Parse as a number. Returns nan() if a TAG or unparseable as a number. */ + double number() const; + + /** Returns false if a TAG. */ + bool boolean() const; + + operator std::string() const { + return m_value; + } + + operator bool() const { + return boolean(); + } + + operator double() const { + return number(); + } + + operator float() const { + return float(number()); + } + + operator int() const { + return iRound(number()); + } + +}; // class XML + +} // namespace G3D + +#endif diff --git a/dep/include/g3dlite/G3D/constants.h b/dep/include/g3dlite/G3D/constants.h index dd5cb3649e5..4121f744e17 100644 --- a/dep/include/g3dlite/G3D/constants.h +++ b/dep/include/g3dlite/G3D/constants.h @@ -3,13 +3,14 @@ @maintainer Morgan McGuire, http://graphics.cs.williams.edu @created 2009-05-20 - @edited 2009-05-20 + @edited 2010-05-20 */ #ifndef G3D_constants_h #define G3D_constants_h #include "G3D/platform.h" #include "G3D/enumclass.h" +#include "G3D/Any.h" namespace G3D { @@ -29,6 +30,16 @@ class PrimitiveType { }; private: + + static const char* toString(int i, Value& v) { + static const char* str[] = {"POINTS", "LINES", "LINE_STRIP", "TRIANGLES", "TRIANGLE_FAN", "QUADS", "QUAD_STRIP", NULL}; + static const Value val[] = {POINTS, LINES, LINE_STRIP, TRIANGLES, TRIANGLE_FAN, QUADS, QUAD_STRIP}; + const char* s = str[i]; + if (s) { + v = val[i]; + } + return s; + } Value value; @@ -66,18 +77,21 @@ class RefractionQuality { 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]; + static const char* toString(int i, Value& v) { + static const char* str[] = {"NONE", "STATIC_ENV", "DYNAMIC_FLAT", "DYNAMIC_FLAT_MULTILAYER", "DYNAMIC_ENV", "BEST", NULL}; + static const Value val[] = {NONE, STATIC_ENV, DYNAMIC_FLAT, DYNAMIC_FLAT_MULTILAYER, DYNAMIC_ENV, BEST}; + const char* s = str[i]; + if (s) { + v = val[i]; + } + return s; + } + 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; }; @@ -105,18 +119,20 @@ class MirrorQuality { 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]; + static const char* toString(int i, Value& v) { + static const char* str[] = {"NONE", "STATIC_ENV", "DYNAMIC_PLANAR", "DYNAMIC_ENV", "BEST", NULL}; + static const Value val[] = {NONE, STATIC_ENV, DYNAMIC_PLANAR, DYNAMIC_ENV, BEST}; + const char* s = str[i]; + if (s) { + v = val[i]; + } + return s; + } 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 diff --git a/dep/include/g3dlite/G3D/debugAssert.h b/dep/include/g3dlite/G3D/debugAssert.h index 432e97e679d..a16da6c56c4 100644 --- a/dep/include/g3dlite/G3D/debugAssert.h +++ b/dep/include/g3dlite/G3D/debugAssert.h @@ -39,12 +39,10 @@ #ifdef G3D_LINUX // Needed so we can define a global display // pointer for debugAssert. -#if SOMEONE_MADE_THIS_USEFUL #include #include #include #endif -#endif /** @@ -180,7 +178,6 @@ namespace _internal { 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 @@ -197,7 +194,6 @@ namespace G3D { namespace _internal { */ extern Window x11Window; #endif -#endif /** Pops up an assertion dialog or prints an assertion diff --git a/dep/include/g3dlite/G3D/enumclass.h b/dep/include/g3dlite/G3D/enumclass.h index c7dfe45f14f..2874a630ad9 100644 --- a/dep/include/g3dlite/G3D/enumclass.h +++ b/dep/include/g3dlite/G3D/enumclass.h @@ -22,112 +22,170 @@ Enum classes are initialized to their zero value by default. + You must implement the following method before calling G3D_DECLARE_ENUM_CLASS_METHODS, as either: + +
+    static const char* toString(int i, Value& v) {
+        static const char* str[] = {"FUEL", "FOOD", "WATER", NULL}; // Whatever your enum values are
+        static const Value val[] = {FUEL, FOOD, WATER};             // Whatever your enum values are
+        const char* s = str[i];
+        if (s) {
+            v = val[i];
+        }
+        return s;
+    }
+  
+ 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) {}\ +private: \ + void fromString(const std::string& x) {\ + Value v;\ + const char* s;\ + int i = 0;\ +\ + do {\ + s = toString(i, v);\ + if (x == s) {\ + value = v;\ + return;\ + }\ + ++i;\ + } while (s);\ + }\ +\ +public:\ +\ + const char* toString() const {\ + const char* s;\ + int i = 0;\ + Value v = (Value)0;\ + while (true) {\ + s = toString(i, v);\ + if ((s == NULL) || (v == value)) {\ + return s;\ + }\ + ++i;\ + }\ + return NULL;\ + }\ +\ + explicit Classname(const std::string& x) : value((Value)0) {\ + fromString(x);\ + }\ +\ + Classname(const Any& a) : value((Value)0) {\ + fromString(a.string());\ + }\ +\ + operator Any() const {\ + return Any(toString());\ + }\ +\ + Classname(char v) : value((Value)v) {}\ \ - inline Classname() : value((Value)0) {}\ + Classname() : value((Value)0) {}\ \ - inline Classname(const Value v) : value(v) {}\ + Classname(const Value v) : value(v) {}\ \ - explicit inline Classname(int v) : value((Value)v) {}\ + explicit 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 {\ + operator int() const {\ return (int)value;\ }\ \ - inline bool operator== (const Classname other) const {\ + bool operator== (const Classname other) const {\ return value == other.value;\ }\ \ - inline bool operator== (const Classname::Value other) const {\ + bool operator== (const Classname::Value other) const {\ return value == other;\ }\ \ - inline bool operator!= (const Classname other) const {\ + bool operator!= (const Classname other) const {\ return value != other.value;\ }\ \ - inline bool operator!= (const Classname::Value other) const {\ + bool operator!= (const Classname::Value other) const {\ return value != other;\ }\ \ - inline bool operator< (const Classname other) const {\ + bool operator< (const Classname other) const {\ return value < other.value;\ }\ \ - inline bool operator> (const Classname other) const {\ + bool operator> (const Classname other) const {\ return value > other.value;\ }\ \ - inline bool operator>= (const Classname other) const {\ + bool operator>= (const Classname other) const {\ return value >= other.value;\ }\ \ - inline bool operator<= (const Classname other) const {\ + bool operator<= (const Classname other) const {\ return value <= other.value;\ }\ \ - inline bool operator< (const Value other) const {\ + bool operator< (const Value other) const {\ return value < other;\ }\ \ - inline bool operator> (const Value other) const {\ + bool operator> (const Value other) const {\ return value > other;\ }\ \ - inline bool operator<= (const Value other) const {\ + bool operator<= (const Value other) const {\ return value <= other;\ }\ \ - inline bool operator>= (const Value other) const {\ + bool operator>= (const Value other) const {\ return value >= other;\ }\ \ - inline Classname& operator-- () {\ + Classname& operator-- () {\ value = (Value)((int)value - 1);\ return *this;\ }\ \ - inline Classname& operator++ () {\ + Classname& operator++ () {\ value = (Value)((int)value + 1);\ return *this;\ }\ \ - inline Classname& operator+= (const int x) {\ + Classname& operator+= (const int x) {\ value = (Value)((int)value + x);\ return *this;\ }\ \ - inline Classname& operator-= (const int x) {\ + Classname& operator-= (const int x) {\ value = (Value)((int)value - x);\ return *this;\ }\ \ - inline Classname operator+ (const int x) const {\ + Classname operator+ (const int x) const {\ return Classname((int)value + x);\ }\ \ - inline Classname operator- (const int x) const {\ + Classname operator- (const int x) const {\ return Classname((int)value - x);\ }\ \ - inline unsigned int hashCode() const {\ + unsigned int hashCode() const {\ return (unsigned int)value;\ }\ \ - inline void serialize(BinaryOutput& b) const {\ + void serialize(BinaryOutput& b) const {\ b.writeInt32(value);\ }\ \ - inline void deserialize(BinaryInput& b) {\ + void deserialize(BinaryInput& b) {\ value = (Value)b.readInt32();\ } diff --git a/dep/include/g3dlite/G3D/fileutils.h b/dep/include/g3dlite/G3D/fileutils.h index 9e49777d93a..89b41690206 100644 --- a/dep/include/g3dlite/G3D/fileutils.h +++ b/dep/include/g3dlite/G3D/fileutils.h @@ -4,14 +4,14 @@ @maintainer Morgan McGuire, http://graphics.cs.williams.edu @author 2002-06-06 - @edited 2010-02-06 + @edited 2010-03-06 Copyright 2000-2010, Morgan McGuire. All rights reserved. */ -#ifndef G3D_fileUtils_h -#define G3D_fileUtils_h +#ifndef G3D_fileutils_h +#define G3D_fileutils_h #include "G3D/platform.h" #include @@ -68,97 +68,11 @@ void writeWholeFile( 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& 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& 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 @@ -242,10 +156,7 @@ 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. */ +/** Appends file onto dirname, ensuring a / if needed. \deprecated Use FilePath::concat */ std::string pathConcat(const std::string& dirname, const std::string& file); } // namespace diff --git a/dep/include/g3dlite/G3D/g3dmath.h b/dep/include/g3dlite/G3D/g3dmath.h index d16214ebb37..beee5eb78e1 100644 --- a/dep/include/g3dlite/G3D/g3dmath.h +++ b/dep/include/g3dlite/G3D/g3dmath.h @@ -65,8 +65,6 @@ inline double __fastcall drand48() { return ::rand() / double(RAND_MAX); } -#if !defined(_WIN64) - /** Win32 implementation of the C99 fast rounding routines. @@ -101,19 +99,6 @@ __inline long int lrintf(float flt) { 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 @@ -135,6 +120,10 @@ inline double pi() { return 3.1415926535898; } +inline float pif() { + return 3.1415926535898f; +} + inline double halfPi() { return 1.57079633; } @@ -608,6 +597,18 @@ inline double aCos (double fValue) { } } +inline float acos (float fValue) { + if ( -1.0f < fValue ) { + if ( fValue < 1.0f ) { + return ::acos(fValue); + } else { + return 0.0f; + } + } else { + return pif(); + } +} + //---------------------------------------------------------------------------- inline double aSin (double fValue) { if ( -1.0 < fValue ) { diff --git a/dep/include/g3dlite/G3D/netheaders.h b/dep/include/g3dlite/G3D/netheaders.h new file mode 100644 index 00000000000..a82d7c36f36 --- /dev/null +++ b/dep/include/g3dlite/G3D/netheaders.h @@ -0,0 +1,24 @@ +#ifndef G3D_netheaders_h +#define G3D_netheaders_h + +#include "G3D/platform.h" + +#ifdef G3D_WIN32 +# if (G3D_WINSOCK_MAJOR_VERSION == 2) +# include +# elif (G3D_WINSOCK_MAJOR_VERSION == 1) +# include +# endif +#else +# include +# include +# include +# ifndef SOCKADDR_IN +# define SOCKADDR_IN struct sockaddr_in +# endif +# ifndef SOCKET +# define SOCKET int +# endif +#endif + +#endif diff --git a/dep/include/g3dlite/G3D/networkHelpers.h b/dep/include/g3dlite/G3D/networkHelpers.h new file mode 100644 index 00000000000..7a532d71ee6 --- /dev/null +++ b/dep/include/g3dlite/G3D/networkHelpers.h @@ -0,0 +1,91 @@ +// Included by NetworkDevice.cpp and TCPConduit.cpp to provide a platform-independent networking base + +#include +#include +#include + +#if defined(G3D_LINUX) || defined(G3D_OSX) || defined(G3D_FREEBSD) +# include +# include +# include +# include +# include +# ifdef __linux__ +# include +# include +# include +# include +// Match Linux to FreeBSD +# define AF_LINK AF_PACKET +# else +# include +# include +# endif + + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + + #include + + #define _alloca alloca + + /** Define an error code for non-windows platforms. */ + int WSAGetLastError() { + return -1; + } + + #define SOCKET_ERROR -1 + + static std::string socketErrorCode(int code) { + return G3D::format("CODE %d: %s\n", code, strerror(code)); + } + + static std::string socketErrorCode() { + return socketErrorCode(errno); + } + + static const int WSAEWOULDBLOCK = -100; + + typedef int SOCKET; + typedef struct sockaddr_in SOCKADDR_IN; + +#else + + // Windows + static std::string socketErrorCode(int code) { + LPTSTR formatMsg = NULL; + + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_IGNORE_INSERTS | + FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + code, + 0, + (LPTSTR)&formatMsg, + 0, + NULL); + + return G3D::format("CODE %d: %s\n", code, formatMsg); + } + + static std::string socketErrorCode() { + return socketErrorCode(GetLastError()); + } + +#endif + + +#ifndef _SOCKLEN_T +# if defined(G3D_WIN32) || defined(G3D_OSX) + typedef int socklen_t; +# endif +#endif diff --git a/dep/include/g3dlite/G3D/platform.h b/dep/include/g3dlite/G3D/platform.h index 11ba0127a16..7f26dcaf5c9 100644 --- a/dep/include/g3dlite/G3D/platform.h +++ b/dep/include/g3dlite/G3D/platform.h @@ -6,17 +6,17 @@ @maintainer Morgan McGuire, http://graphics.cs.williams.edu @created 2003-06-09 - @edited 2010-01-11 + @edited 2010-08-11 */ #ifndef G3D_platform_h #define G3D_platform_h /** - The version number of G3D in the form: MmmBB -> + The version number of G3D in the form: MmmBB -> version M.mm [beta BB] */ -#define G3D_VER 80004 +#define G3D_VER 80100 // fatal error for unsupported architectures #if defined(__powerpc__) @@ -37,13 +37,19 @@ # define G3D_DEBUG #endif +/** 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 + #ifndef _MSC_VER /// Fast call is a register-based optimized calling convention supported only by Visual C++ #define __fastcall - #endif -#ifdef _MSC_VER +#ifdef _MSC_VER #define G3D_WIN32 #elif defined(__FreeBSD__) || defined(__OpenBSD__) #define G3D_FREEBSD @@ -57,15 +63,12 @@ // pi as a constant, which creates a conflict with G3D #define __FP__ #else - #error Unknown platform + #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 - #endif #else # define G3D_32BIT #endif @@ -89,7 +92,7 @@ # ifndef __GNUC__ # error G3D only supports the gcc compiler on OS X. # endif - + # if defined(__i386__) # define G3D_OSX_INTEL # elif defined(__PPC__) @@ -130,11 +133,13 @@ // TODO: remove # pragma warning (disable : 4244) +# define ZLIB_WINAPI + # define restrict /** @def G3D_CHECK_PRINTF_METHOD_ARGS() Enables printf parameter validation on gcc. */ -# define G3D_CHECK_PRINTF_ARGS +# define G3D_CHECK_PRINTF_ARGS /** @def G3D_CHECK_PRINTF_METHOD_ARGS() Enables printf parameter validation on gcc. */ @@ -142,7 +147,7 @@ /** @def G3D_CHECK_PRINTF_METHOD_ARGS() Enables printf parameter validation on gcc. */ -# define G3D_CHECK_PRINTF_METHOD_ARGS +# define G3D_CHECK_PRINTF_METHOD_ARGS /** @def G3D_CHECK_PRINTF_METHOD_ARGS() Enables printf parameter validation on gcc. */ @@ -151,7 +156,7 @@ // 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. + // 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 @@ -285,18 +290,18 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw) {\ #endif -/** +/** @def STR(expression) Creates a string from the expression. Frequently used with G3D::Shader - to express shading programs inline. + to express shading programs inline. STR(this becomes a string)\verbatim
\endverbatim evaluates the same as \verbatim\endverbatim"this becomes a string"
  */
 #define STR(x) #x
 
 /** @def PRAGMA(expression)
-    \#pragma may not appear inside a macro, so this uses the pragma operator
+    \#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
@@ -322,7 +327,7 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw) {\
 #    define G3D_END_PACKED_CLASS(byteAlign)  ; PRAGMA( pack(pop) )
 #elif defined(__GNUC__)
 #    define G3D_END_PACKED_CLASS(byteAlign)  __attribute((aligned(byteAlign))) ;
-#else
+#else 
 #    define G3D_END_PACKED_CLASS(byteAlign)  ;
 #endif
 
diff --git a/dep/include/g3dlite/G3D/stringutils.h b/dep/include/g3dlite/G3D/stringutils.h
index e15a757a7a6..42a4886521a 100644
--- a/dep/include/g3dlite/G3D/stringutils.h
+++ b/dep/include/g3dlite/G3D/stringutils.h
@@ -4,11 +4,11 @@
  @maintainer Morgan McGuire, http://graphics.cs.williams.edu
  
  @author  2000-09-09
- @edited  2008-08-05
+ @edited  2010-03-05
  */
 
-#ifndef G3D_STRINGUTILS_H
-#define G3D_STRINGUTILS_H
+#ifndef G3D_stringutils_h
+#define G3D_stringutils_h
 
 #include "G3D/platform.h"
 #include "G3D/Array.h"
@@ -28,6 +28,33 @@ extern const char* NEWLINE;
 */
 void parseCommaSeparated(const std::string s, Array& array, bool stripQuotes = true);
 
+/** Finds the index of the first '\\' or '/' character, starting at index \a start. 
+  \sa G3D::findLastSlash, G3D::isSlash
+*/
+inline int findSlash(const std::string& f, int start = 0) {
+    int i = f.find('/', start);
+    int j = f.find('\\', start);
+    if (((i != -1) && (i < j)) || (j == -1)) {
+        return i;
+    } else {
+        return j;
+    }
+}
+
+
+/** Finds the index of the first '\\' or '/' character, starting at index \a start (if \a start is -1, starts at the end of the string).
+  \sa G3D::findSlash, G3D::isSlash
+  */
+inline int findLastSlash(const std::string& f, int start = -1) {
+    if (start == -1) {
+        start = f.length() - 1;
+    }
+
+    int i = f.rfind('/', start);
+    int j = f.rfind('\\', start);
+    return max(i, j);
+}
+
 /**
  Returns true if the test string begins with the pattern string.
  */
diff --git a/dep/src/g3dlite/AABox.cpp b/dep/src/g3dlite/AABox.cpp
index 035497aa3c4..8e66456c013 100644
--- a/dep/src/g3dlite/AABox.cpp
+++ b/dep/src/g3dlite/AABox.cpp
@@ -282,6 +282,10 @@ bool AABox::culledBy(
     return false;
 }
 
+void AABox::getBounds(Sphere& s) const {
+    s.center = center();
+    s.radius = extent().length() / 2;
+}
 
 bool AABox::intersects(const class Sphere& sphere) const {
     double d = 0; 
diff --git a/dep/src/g3dlite/Any.cpp b/dep/src/g3dlite/Any.cpp
index de4d32e83ea..92159bb1862 100644
--- a/dep/src/g3dlite/Any.cpp
+++ b/dep/src/g3dlite/Any.cpp
@@ -5,9 +5,9 @@
  @author Shawn Yarbrough
   
  @created 2006-06-11
- @edited  2009-11-15
+ @edited  2010-07-24
 
- Copyright 2000-2009, Morgan McGuire.
+ Copyright 2000-2010, Morgan McGuire.
  All rights reserved.
  */
 
@@ -15,11 +15,73 @@
 #include "G3D/TextOutput.h"
 #include "G3D/TextInput.h"
 #include "G3D/stringutils.h"
+#include "G3D/fileutils.h"
+#include "G3D/FileSystem.h"
 #include 
 #include 
 
 namespace G3D {
 
+std::string Any::resolveStringAsFilename() const {
+    verifyType(STRING);
+    std::string f = FileSystem::resolve(string(), sourceDirectory());
+    if (FileSystem::exists(f)) {
+        return f;
+    } else {
+        const std::string& s = System::findDataFile(string(), false);
+        if (s.empty()) {
+            return string();
+        } else {
+            return s;
+        }
+    }
+}
+
+
+bool Any::nameBeginsWith(const std::string& s) const {
+    return nameBeginsWith(s.c_str());
+}
+
+
+bool Any::nameEquals(const std::string& s) const {
+    // If std::string has a fast hash compare, use it first
+    return (name() == s) || nameEquals(s.c_str());
+}
+
+
+inline static char toLower(char c) {
+    return ((c >= 'A') && (c <= 'Z')) ? (c - 'A' + 'a') : c;
+}
+
+
+bool Any::nameBeginsWith(const char* s) const {
+    verifyType(Any::ARRAY, Any::TABLE);
+
+    const char* n = name().c_str();
+    // Walk through character-by-character
+    while ((*s != '\0') && (*n != '\0')) {
+        if (toLower(*s) != toLower(*n)) {
+            // Mismatch
+            return false;
+        }
+        ++s; ++n;
+    }
+    // Make sure s ran out no later than n
+    return (*s == '\0');
+}
+
+
+bool Any::nameEquals(const char* s) const {
+    verifyType(Any::ARRAY, Any::TABLE);
+#ifdef G3D_WIN32
+    return stricmp(name().c_str(), s) == 0;
+#else
+    return strcasecmp(name().c_str(), s) == 0;
+#endif
+
+}
+
+
 void Any::beforeRead() const {
     if (isPlaceholder()) {
         // Tried to read from a placeholder--throw an exception as if
@@ -675,11 +737,10 @@ bool Any::operator!=(const Any& x) const {
 static void getDeserializeSettings(TextInput::Settings& settings) {
     settings.cppBlockComments = true;
     settings.cppLineComments = true;
-    settings.otherLineComments = true;
-    settings.otherCommentCharacter = '#';
+    settings.otherLineComments = false;
     settings.generateCommentTokens = true;
     settings.singleQuotedStrings = false;
-    settings.msvcSpecials = false;
+    settings.msvcFloatSpecials = false;
     settings.caseSensitive = false;
 }
 
@@ -708,7 +769,7 @@ void Any::load(const std::string& filename) {
     TextInput::Settings settings;
     getDeserializeSettings(settings);
 
-    TextInput ti(filename, settings);
+    TextInput ti(FileSystem::resolve(filename), settings);
     deserialize(ti);
 }
 
@@ -870,12 +931,6 @@ static bool isClose(const char 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();
@@ -928,6 +983,9 @@ void Any::deserialize(TextInput& ti, Token& token) {
             "File ended without a properly formed Any");
     }
 
+    // Do we need to read one more token after the end? 
+    bool needRead = true;
+
     switch (token.type()) {
     case Token::STRING:
         m_type = STRING;
@@ -951,8 +1009,41 @@ void Any::deserialize(TextInput& ti, Token& token) {
         break;
 
     case Token::SYMBOL:
-        // Named Array, Named Table, Array, Table, or NONE
-        if (toUpper(token.string()) == "NONE") {
+        // Pragma, Named Array, Named Table, Array, Table, or NONE
+        if (token.string() == "#") {
+            // Pragma
+            
+            // Currently, "include" is the only pragma allowed
+            token = ti.read();
+            if (! ((token.type() == Token::SYMBOL) &&
+                   (token.string() == "include"))) {
+                throw ParseError(ti.filename(), token.line(), token.character(),
+                                 "Expected 'include' pragma after '#'");
+            }
+            
+            ti.readSymbol("(");
+            const std::string& includeName = ti.readString();
+
+            // Find the include file
+            const std::string& myPath = filenamePath(ti.filename());
+            std::string t = pathConcat(myPath, includeName);
+
+            if (! FileSystem::exists(t)) {
+                // Try and find it, starting with cwd
+                t = System::findDataFile(includeName);
+            }
+
+            // Read the included file
+            load(t);
+
+            // Update the source information
+            ensureData();
+            m_data->source.filename += 
+                format(" [included from %s:%d(%d)]", ti.filename().c_str(), token.line(), token.character());
+            
+            ti.readSymbol(")");
+
+        } else if (toUpper(token.string()) == "NONE") {
             // Nothing left to do; we initialized to NONE originally
             ensureData();
             m_data->source.set(ti, token);
@@ -982,6 +1073,7 @@ void Any::deserialize(TextInput& ti, Token& token) {
                 ensureData();
                 m_data->name = name;
             }
+            needRead = false;
         } // if NONE
         break;
 
@@ -996,7 +1088,7 @@ void Any::deserialize(TextInput& ti, Token& token) {
         m_data->comment = comment;
     }
 
-    if (m_type != ARRAY && m_type != TABLE) {
+    if (needRead) {
         // Array and table already consumed their last token
         token = ti.read();
     }
@@ -1016,9 +1108,9 @@ static bool isSeparator(char c) {
 
 
 void Any::readUntilCommaOrClose(TextInput& ti, Token& token) {
-    while (! ((token.type() == Token::SYMBOL) && 
-              (isClose(token.string()[0])) || 
-               isSeparator(token.string()[0]))) {
+    bool atClose = (token.type() == Token::SYMBOL) && isClose(token.string()[0]);
+    bool atComma = isSeparator(token.string()[0]);
+    while (! (atClose || atComma)) {
         switch (token.type()) {
         case Token::NEWLINE:
         case Token::COMMENT:
@@ -1030,6 +1122,10 @@ void Any::readUntilCommaOrClose(TextInput& ti, Token& token) {
             throw ParseError(ti.filename(), token.line(), token.character(), 
                 "Expected a comma or close paren");
         }
+
+	// Update checks
+        atComma = isSeparator(token.string()[0]);
+        atClose = (token.type() == Token::SYMBOL) && isClose(token.string()[0]);
     }
 }
 
@@ -1076,13 +1172,13 @@ void Any::deserializeBody(TextInput& ti, Token& token) {
             } 
             
             key = token.string();
-            // Consume everything up to the = sign
+            // Consume everything up to the = sign, returning 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).
+                // Read the next token, which is the value (don't consume comments--we want the value pointed to by a to get those).
                 token = ti.read();
             }
         }
@@ -1154,6 +1250,15 @@ const Any::Source& Any::source() const {
 }
 
 
+std::string Any::sourceDirectory() const {
+    if (m_data) {
+        return FilePath::parent(m_data->source.filename);
+    } else {
+        return "";
+    }
+}
+
+
 void Any::verify(bool value, const std::string& message) const {
     beforeRead();
     if (! value) {
@@ -1185,6 +1290,14 @@ void Any::verifyName(const std::string& n) const {
 }
 
 
+void Any::verifyName(const std::string& n, const std::string& m) const {
+    beforeRead();
+    const std::string& x = toUpper(name());
+    verify(beginsWith(x, toUpper(n)) ||
+           beginsWith(x, toUpper(m)), "Name must begin with " + n + " or " + m);
+}
+
+
 void Any::verifyType(Type t) const {
     beforeRead();
     if (type() != t) {
diff --git a/dep/src/g3dlite/BinaryInput.cpp b/dep/src/g3dlite/BinaryInput.cpp
index 65a9976fe04..c879715c3f0 100644
--- a/dep/src/g3dlite/BinaryInput.cpp
+++ b/dep/src/g3dlite/BinaryInput.cpp
@@ -5,7 +5,7 @@
  Copyright 2001-2007, Morgan McGuire.  All rights reserved.
  
  @created 2001-08-09
- @edited  2005-02-24
+ @edited  2010-03-05
 
 
   
@@ -37,8 +37,9 @@
 #include "G3D/Array.h"
 #include "G3D/fileutils.h"
 #include "G3D/Log.h"
+#include "G3D/FileSystem.h"
 #include 
-
+#include "zip.h"
 #include 
 
 namespace G3D {
@@ -272,28 +273,40 @@ BinaryInput::BinaryInput(
     _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(v);
-            m_bufferLength = m_length = s;
-            if (compressed) {
-                decompress();
+    std::string zipfile;
+    if (FileSystem::inZipfile(m_filename, zipfile)) {
+        // Load from zipfile
+//        zipRead(filename, v, s);
+
+        std::string internalFile = m_filename.substr(zipfile.length() + 1);
+        struct zip* z = zip_open(zipfile.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, internalFile.c_str(), ZIP_FL_NOCASE, &info);
+            m_bufferLength = m_length = info.size;
+            // sets machines up to use MMX, if they want
+            m_buffer = reinterpret_cast(System::alignedMalloc(m_length, 16));
+            struct zip_file* zf = zip_fopen( z, internalFile.c_str(), ZIP_FL_NOCASE );
+            {
+                int64 test = zip_fread( zf, m_buffer, m_length );
+                debugAssertM(test == m_length,
+                             internalFile + " was corrupt because it unzipped to the wrong size.");
+                (void)test;
             }
-            m_freeBuffer = true;
-        } else {
-            Log::common()->printf("Warning: File not found: %s\n", m_filename.c_str());
+            zip_fclose( zf );
+        }
+        zip_close( z );
+
+        if (compressed) {
+            decompress();
         }
+        m_freeBuffer = true;
         return;
     }
 
     // Figure out how big the file is and verify that it exists.
-    m_length = fileLength(m_filename);
+    m_length = FileSystem::size(m_filename);
 
     // Read the file into memory
     FILE* file = fopen(m_filename.c_str(), "rb");
@@ -460,6 +473,42 @@ std::string BinaryInput::readString() {
     return readString(n);
 }
 
+static bool isNewline(char c) {
+    return c == '\n' || c == '\r';
+}
+
+std::string BinaryInput::readStringNewline() {
+    int64 n = 0;
+
+    if ((m_pos + m_alreadyRead + n) < (m_length - 1)) {
+        prepareToRead(1);
+    }
+
+    if ( ((m_pos + m_alreadyRead + n) < (m_length - 1)) &&
+         ! isNewline(m_buffer[m_pos + n])) {
+
+        ++n;
+        while ( ((m_pos + m_alreadyRead + n) < (m_length - 1)) &&
+                ! isNewline(m_buffer[m_pos + n])) {
+
+            prepareToRead(1);
+            ++n;
+        }
+    }
+
+    const std::string s = readString(n);
+
+    // Consume the newline
+    char firstNLChar = readUInt8();
+
+    // Consume the 2nd newline
+    if (isNewline(m_buffer[m_pos + 1]) && (m_buffer[m_pos + 1] != firstNLChar)) {
+        readUInt8();
+    }
+
+    return s;
+}
+
 
 std::string BinaryInput::readStringEven() {
     std::string x = readString();
diff --git a/dep/src/g3dlite/BinaryOutput.cpp b/dep/src/g3dlite/BinaryOutput.cpp
index 2de46c6d4bb..054211d906c 100644
--- a/dep/src/g3dlite/BinaryOutput.cpp
+++ b/dep/src/g3dlite/BinaryOutput.cpp
@@ -1,22 +1,27 @@
 /**
  @file BinaryOutput.cpp
  
- @author Morgan McGuire, graphics3d.com
- Copyright 2002-2007, Morgan McGuire, All rights reserved.
+ @author Morgan McGuire, http://graphics.cs.williams.edu
+ Copyright 2002-2010, Morgan McGuire, All rights reserved.
  
  @created 2002-02-20
- @edited  2008-01-07
+ @edited  2010-03-17
  */
 
 #include "G3D/platform.h"
 #include "G3D/BinaryOutput.h"
 #include "G3D/fileutils.h"
+#include "G3D/FileSystem.h"
 #include "G3D/stringutils.h"
 #include "G3D/Array.h"
 #include 
-
+#include "G3D/Log.h"
 #include 
 
+#ifdef G3D_LINUX
+#    include 
+#endif
+
 // 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.
@@ -155,7 +160,7 @@ void BinaryOutput::reserveBytesWhenOutOfMemory(size_t bytes) {
         //debugPrintf("Writing %d bytes to disk\n", writeBytes);
 
         const char* mode = (m_alreadyWritten > 0) ? "ab" : "wb";
-        FILE* file = fopen(m_filename.c_str(), mode);
+        FILE* file = FileSystem::fopen(m_filename.c_str(), mode);
         debugAssert(file);
 
         size_t count = fwrite(m_buffer, 1, writeBytes, file);
@@ -317,14 +322,17 @@ void BinaryOutput::commit(bool flush) {
     parseFilename(m_filename, root, pathArray, base, ext); 
 
     path = root + stringJoin(pathArray, '/');
-    if (! fileExists(path, false)) {
-        createDirectory(path);
+    if (! FileSystem::exists(path, false)) {
+        FileSystem::createDirectory(path);
     }
 
     const char* mode = (m_alreadyWritten > 0) ? "ab" : "wb";
 
-    FILE* file = fopen(m_filename.c_str(), mode);
+    FILE* file = FileSystem::fopen(m_filename.c_str(), mode);
 
+    if (! file) {
+        logPrintf("Error %d while trying to open \"%s\"\n", errno, m_filename.c_str());
+    }
     m_ok = (file != NULL) && m_ok;
 
     if (m_ok) {
@@ -340,7 +348,7 @@ void BinaryOutput::commit(bool flush) {
         if (flush) {
             fflush(file);
         }
-        fclose(file);
+        FileSystem::fclose(file);
         file = NULL;
     }
 }
diff --git a/dep/src/g3dlite/CoordinateFrame.cpp b/dep/src/g3dlite/CoordinateFrame.cpp
index 9b639b62082..7f9a4c098a5 100644
--- a/dep/src/g3dlite/CoordinateFrame.cpp
+++ b/dep/src/g3dlite/CoordinateFrame.cpp
@@ -6,7 +6,7 @@
  @maintainer Morgan McGuire, http://graphics.cs.williams.edu
 
  @created 2001-06-02
- @edited  2009-11-13
+ @edited  2010-03-13
 
  Copyright 2000-2010, Morgan McGuire.
  All rights reserved.
@@ -26,23 +26,52 @@
 #include "G3D/UprightFrame.h"
 #include "G3D/Any.h"
 #include "G3D/stringutils.h"
+#include "G3D/PhysicsFrame.h"
+#include "G3D/UprightFrame.h"
 
 namespace G3D {
 
+
+std::string CoordinateFrame::toXYZYPRDegreesString() const {
+    UprightFrame uframe(*this);
+    
+    return format("CFrame::fromXYZYPRDegrees(% 5.1ff, % 5.1ff, % 5.1ff, % 5.1ff, % 5.1ff, % 5.1ff)", 
+                  uframe.translation.x, uframe.translation.y, uframe.translation.z, 
+                  toDegrees(uframe.yaw), toDegrees(uframe.pitch), 0.0f);
+}
+
+
 CoordinateFrame::CoordinateFrame(const Any& any) {
-    any.verifyName("CFrame");
-    if (toUpper(any.name()) == "CFRAME") {
+    *this = CFrame();
+
+    const std::string& n = toUpper(any.name());
+
+    if (beginsWith(n, "VECTOR3")) {
+        translation = any;
+    } else if (beginsWith(n, "MATRIX3")) {
+        rotation = any;
+    } else if ((n == "CFRAME") || (n == "COORDINATEFRAME")) {
         any.verifyType(Any::TABLE, Any::ARRAY);
-        if (any.type() == Any::TABLE) {
-            rotation    = any["rotation"];
-            translation = any["translation"];
-        } else {
+        if (any.type() == Any::ARRAY) {
             any.verifySize(2);
             rotation    = any[0];
             translation = any[1];
+        } else {
+            for (Any::AnyTable::Iterator it = any.table().begin(); it.hasMore(); ++it) {
+                const std::string& n = toLower(it->key);
+                if (n == "translation") {
+                    translation = Vector3(it->value);
+                } else if (n == "rotation") {
+                    rotation = Matrix3(it->value);
+                } else {
+                    any.verify(false, "Illegal table key: " + it->key);
+                }
+            }
         }
+    } else if (beginsWith(n, "PHYSICSFRAME") || beginsWith(n, "PFRAME")) {
+        *this = PhysicsFrame(any);
     } else {
-        any.verifyName("CFrame::fromXYZYPRDegrees");
+        any.verifyName("CFrame::fromXYZYPRDegrees", "CoordinateFrame::fromXYZYPRDegrees");
         any.verifyType(Any::ARRAY);
         any.verifySize(3, 6);
 
@@ -370,12 +399,12 @@ CoordinateFrame CoordinateFrame::lerp(
     } else if (alpha == 0.0f) {
         return *this;
     } else {
-        Quat q1 = Quat(this->rotation);
-        Quat q2 = Quat(other.rotation);
+        const Quat q1(this->rotation);
+        const Quat q2(other.rotation);
 
         return CoordinateFrame(
             q1.slerp(q2, alpha).toRotationMatrix(),
-            this->translation * (1 - alpha) + other.translation * alpha);
+            translation * (1 - alpha) + other.translation * alpha);
     }
 } 
 
@@ -383,7 +412,7 @@ CoordinateFrame CoordinateFrame::lerp(
 void CoordinateFrame::pointToWorldSpace(const Array& v, Array& vout) const {
     vout.resize(v.size());
 
-    for (int i = v.size() - 1; i >= 0; --i) {
+    for (int i = 0; i < v.size(); ++i) {
         vout[i] = pointToWorldSpace(v[i]);
     }
 }
@@ -392,7 +421,7 @@ void CoordinateFrame::pointToWorldSpace(const Array& v, Array&
 void CoordinateFrame::normalToWorldSpace(const Array& v, Array& vout) const  {
     vout.resize(v.size());
 
-    for (int i = v.size() - 1; i >= 0; --i) {
+    for (int i = 0; i < v.size(); ++i) {
         vout[i] = normalToWorldSpace(v[i]);
     }
 }
diff --git a/dep/src/g3dlite/FileSystem.cpp b/dep/src/g3dlite/FileSystem.cpp
new file mode 100644
index 00000000000..3a1765714b0
--- /dev/null
+++ b/dep/src/g3dlite/FileSystem.cpp
@@ -0,0 +1,859 @@
+/**
+ @file FileSystem.cpp
+ 
+ @author Morgan McGuire, http://graphics.cs.williams.edu
+ 
+ @author  2002-06-06
+ @edited  2010-04-10
+ */
+#include "G3D/FileSystem.h"
+#include "G3D/System.h"
+#include "G3D/stringutils.h"
+#include "G3D/fileutils.h"
+#include 
+#include 
+#include "zip.h"
+#include "G3D/g3dfnmatch.h"
+#include "G3D/BinaryInput.h"
+#include "G3D/BinaryOutput.h"
+
+#ifdef G3D_WIN32
+    // Needed for _getcwd
+#   include 
+
+    // Needed for _findfirst
+#   include 
+
+#define stat64 _stat64
+#else
+#   include 
+#   include 
+#   include 
+#   define _getcwd getcwd
+#   define _stat stat
+#endif
+
+namespace G3D {
+
+static FileSystem* common = NULL;
+
+FileSystem& FileSystem::instance() {
+    init();
+    return *common;
+}
+
+
+void FileSystem::init() {
+    if (common == NULL) {
+        common = new FileSystem();
+    }
+}
+
+
+void FileSystem::cleanup() {
+    if (common != NULL) {
+        delete common;
+        common = NULL;
+    }
+}
+
+FileSystem::FileSystem() : m_cacheLifetime(10) {}
+
+/////////////////////////////////////////////////////////////
+
+bool FileSystem::Dir::contains(const std::string& f) const {
+    
+    for (int i = 0; i < nodeArray.size(); ++i) {
+#       ifdef G3D_WIN32
+            if (stricmp(f.c_str(), nodeArray[i].name.c_str()) == 0) {
+                return true;
+            }
+#       else
+            if (f == nodeArray[i].name) {
+                return true;
+            }
+#       endif
+    }
+    return false;
+}
+    
+void FileSystem::Dir::computeZipListing(const std::string& zipfile, const std::string& pathInsideZipfile) {
+    struct zip* z = zip_open( FilePath::removeTrailingSlash(zipfile).c_str(), ZIP_CHECKCONS, NULL );
+    debugAssert(z);
+
+    int count = zip_get_num_files( z );
+    Set alreadyAdded;
+    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 );
+        
+        // Fully-qualified name of a file inside zipfile
+        std::string name = info.name;
+
+        if (beginsWith(name, pathInsideZipfile)) {
+            // We found something inside the directory we were looking for,
+            // so the directory itself must exist                        
+            exists = true;
+
+            // For building the cached directory listing, extract only elements that do not contain 
+            // additional subdirectories.
+
+            int start = pathInsideZipfile.size();
+            if ((int(name.length()) > start) && isSlash(name[start])) {
+                ++start;
+            }
+            int end = findSlash(name, start);
+            if (end == -1) {
+                // There are no more slashes; add this name
+                name = name.substr(start);
+                if (alreadyAdded.insert(name)) {
+                    Entry& e = nodeArray.next();
+                    e.name = name;
+                    e.type = FILE_TYPE;
+                }
+            } else {
+                // There are more slashes, indicating that this is a directory
+                name = name.substr(start, end);
+                if (alreadyAdded.insert(name)) {
+                    Entry& e = nodeArray.next();
+                    e.name = name;
+                    e.type = DIR_TYPE;
+                }
+            }
+        }
+    }
+    
+    zip_close(z);
+    z = NULL;
+}
+
+
+FileSystem::Dir& FileSystem::getContents(const std::string& path, bool forceUpdate) {
+    const std::string& key = 
+#   if defined(G3D_WIN32)
+        FilePath::canonicalize(FilePath::removeTrailingSlash(toLower(FilePath::canonicalize(resolve(path)))));
+#   else
+        FilePath::canonicalize(FilePath::removeTrailingSlash(FilePath::canonicalize(resolve(path))));
+#   endif
+    
+    RealTime now = System::time();
+    Dir& dir = m_cache.getCreate(key);
+
+    if ((now > dir.lastChecked + cacheLifetime()) || forceUpdate) {
+        dir = Dir();
+
+        // Out of date: update
+        dir.lastChecked = now;
+
+        struct _stat st;
+        const bool exists = _stat(key.c_str(), &st) != -1;
+        const bool isDirectory = (st.st_mode & S_IFDIR) != 0;
+
+        // Does this path exist on the real filesystem?
+        if (exists && isDirectory) {
+
+            // Is this path actually a directory?
+            if (isDirectory) {
+                dir.exists = true;
+                // Update contents
+#               ifdef G3D_WIN32
+                    const std::string& filespec = FilePath::concat(key, "*");
+                    struct _finddata_t fileinfo;
+                    intptr_t handle = _findfirst(filespec.c_str(), &fileinfo);
+                    debugAssert(handle != -1);
+                    int result = 0;
+                    do {
+                        if ((strcmp(fileinfo.name, ".") != 0) && (strcmp(fileinfo.name, "..") != 0)) {
+                            Entry& e = dir.nodeArray.next();
+                            e.name = fileinfo.name;
+                            if ((fileinfo.attrib & _A_SUBDIR) != 0) {
+                                e.type = DIR_TYPE;
+                            } else {
+                                e.type = FILE_TYPE;
+                            }
+                        }
+
+                        result = _findnext(handle, &fileinfo);
+                    } while (result == 0);
+                    _findclose(handle);
+
+#               else
+                    DIR* listing = opendir(key.c_str());
+                    debugAssertM(listing, "opendir failed on '" + key + "'");
+                    struct dirent* entry = readdir(listing);
+                    while (entry != NULL) {
+                        if ((strcmp(entry->d_name, "..") != 0) && (strcmp(entry->d_name, ".") != 0)) {
+                            Entry& e = dir.nodeArray.next();
+                            e.name = entry->d_name;
+
+#                           ifdef _DIRENT_HAVE_D_TYPE
+                                // Not all POSIX systems support this field
+                                // http://www.delorie.com/gnu/docs/glibc/libc_270.html
+                                switch (entry->d_type) {
+                                case DT_DIR:
+                                    e.type = DIR_TYPE;
+                                    break;
+                                    
+                                case DT_REG:
+                                    e.type = FILE_TYPE;
+                                    break;
+                                    
+                                case DT_UNKNOWN:
+                                default:
+                                    e.type = UNKNOWN;
+                                    break;
+                                }
+#                           endif
+                        }
+                        entry = readdir(listing);
+                    }
+                    closedir(listing);
+                    listing = NULL;
+                    entry = NULL;
+#               endif
+            }
+
+        } else {
+            std::string zip;
+
+            if (exists && isZipfile(path)) {
+                // This is a zipfile; get its root
+                dir.isZipfile = true;                
+                dir.computeZipListing(path, "");
+
+            } else if (inZipfile(path, zip)) {
+
+                // There is a zipfile somewhere in the path.  Does
+                // the rest of the path exist inside the zipfile?
+                dir.inZipfile = true;
+
+                dir.computeZipListing(zip, path.substr(zip.length() + 1));
+            }
+        }        
+    }
+
+    return dir;
+}
+
+
+bool FileSystem::_inZipfile(const std::string& path, std::string& z) {
+    // Reject trivial cases before parsing
+    if (path.find('.') == std::string::npos) {
+        // There is no zipfile possible, since G3D requires
+        // an extension on zipfiles.
+        return false;
+    }
+
+    // Look at all sub-paths containing periods.
+    // For each, ask if it is a zipfile.
+    int current = 0;
+    current = path.find('.', current);
+
+    while (current != -1) {
+        // xxxxx/foo.zip/yyyyy
+        current = path.find('.', current);
+
+        // Look forward for the next slash
+        int s = findSlash(path, current);
+
+        if (s == -1) {
+            // No more slashes
+            return false;
+        }
+
+        z = path.substr(0, s); 
+        if (_isZipfile(z)) {
+            return true;
+        }
+        
+        current = s + 1;
+    }
+
+    z = "";
+    return false;
+}
+
+
+bool FileSystem::_isZipfile(const std::string& filename) {
+    if (FilePath::ext(filename).empty()) {
+        return false;
+    }
+    
+    FILE* f = fopen(FilePath::removeTrailingSlash(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;
+}
+
+
+FILE* FileSystem::_fopen(const char* filename, const char* mode) {
+    for (const char* m = mode; *m != '\0'; ++m) {
+        if (*m == 'w') {
+            // Purge the cache entry for the parent of this directory
+            _clearCache(FilePath::parent(_resolve(filename)));
+            break;
+        }
+    }
+    return ::fopen(filename, mode);
+}
+
+
+void FileSystem::_clearCache(const std::string& path) {
+    if ((path == "") || FilePath::isRoot(path)) {
+        m_cache.clear();
+    } else {
+        Array keys;
+        m_cache.getKeys(keys);
+
+        const std::string& prefix = 
+#           ifdef G3D_WIN32
+                toLower(FilePath::canonicalize(FilePath::removeTrailingSlash(_resolve(path))));
+#           else
+                FilePath::canonicalize(FilePath::removeTrailingSlash(_resolve(path)));
+#           endif
+        const std::string& prefixSlash = prefix + "/";
+
+        for (int k = 0; k < keys.size(); ++k) {
+            const std::string& key = keys[k];
+            if ((key == prefix) || beginsWith(key, prefixSlash)) {
+                m_cache.remove(keys[k]);
+            }
+        }
+    }
+}
+
+
+void FileSystem::_setCacheLifetime(float t) {
+    m_cacheLifetime = t;
+}
+
+
+void FileSystem::_createDirectory(const std::string& dir) {
+    
+    if (dir == "") {
+        return;
+    }
+    
+    std::string d = _resolve(dir);
+    
+    // Add a trailing / if there isn't one.
+    switch (d[d.size() - 1]) {
+    case '/':
+    case '\\':
+        break;
+
+    default:
+        d += "/";
+    }
+
+    // If it already exists, do nothing
+    if (_exists(FilePath::removeTrailingSlash(d))) {
+        return;
+    }
+
+    // Parse the name apart
+    std::string root, base, ext;
+    Array path;
+
+    std::string lead;
+    FilePath::parse(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 (! _exists(p)) {
+            // 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
+        }
+    }
+
+    _clearCache(FilePath::parent(FilePath::removeTrailingSlash(d)));
+}
+
+
+void FileSystem::_copyFile(const std::string& source, const std::string& dest) {
+#   ifdef G3D_WIN32
+        // TODO: handle case where srcPath is in a zipfile
+        CopyFileA(source.c_str(), dest.c_str(), FALSE);
+        _clearCache(FilePath::parent(_resolve(dest)));
+#   else
+        // 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        
+}
+
+
+bool FileSystem::_exists(const std::string& f, bool trustCache) {
+
+    if (FilePath::isRoot(f)) {
+#       ifdef G3D_WIN32
+            const std::string& winname = toLower(f.substr(0, 1)) + ":\\";
+            return _drives().contains(winname);
+#       else
+            return true;
+#       endif
+    }
+
+    std::string path = FilePath::removeTrailingSlash(f);
+    std::string parentPath = FilePath::parent(path);
+
+    const Dir& entry = getContents(parentPath, ! trustCache);
+
+    if (FilePath::containsWildcards(f)) {
+        if (! entry.exists) {
+            // The directory didn't exist, so neither do its contents
+            return false;
+        } 
+
+        const std::string& pattern = FilePath::baseExt(path);
+
+#       ifdef G3D_WIN32
+            static const int flags = FNM_CASEFOLD;
+#       else
+            static const int flags = 0;
+#       endif
+
+        // See if any element of entry matches the wild card
+        for (int i = 0; i < entry.nodeArray.size(); ++i) {
+            if (FilePath::matches(entry.nodeArray[i].name, pattern, flags)) {
+                return true;
+            }
+        }
+
+        // Could not find a match
+        return false;
+
+    } else {
+        return entry.exists && entry.contains(FilePath::baseExt(path));
+    }
+}
+
+
+bool FileSystem::_isDirectory(const std::string& filename) {
+    // TODO: work with zipfiles and cache
+    struct _stat st;
+    const bool exists = _stat(FilePath::removeTrailingSlash(filename).c_str(), &st) != -1;
+    return exists && ((st.st_mode & S_IFDIR) != 0);
+}
+
+
+std::string FileSystem::_resolve(const std::string& filename, const std::string& cwd) {
+    if (filename.size() >= 1) {
+        if (isSlash(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) && isSlash(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
+        }
+    }
+
+    // Prepend the working directory.
+    return FilePath::concat(cwd, filename);
+}
+
+
+std::string FileSystem::_currentDirectory() {
+    static const int N = 2048;
+    char buffer[N];
+
+    _getcwd(buffer, N);
+    return std::string(buffer);
+}
+
+
+bool FileSystem::_isNewer(const std::string& src, const std::string& dst) {
+    // TODO: work with cache and zipfiles
+    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));
+}
+
+
+int64 FileSystem::_size(const std::string& filename) {
+    struct stat64 st;
+    int result = stat64(filename.c_str(), &st);
+    
+    if (result == -1) {
+        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 );    // 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;
+        }
+    }
+    
+    return st.st_size;
+}
+
+
+void FileSystem::listHelper(const std::string& shortSpec, const std::string& parentPath, Array& result, const ListSettings& settings) {
+    Dir& dir = getContents(parentPath, false);
+
+    if (! dir.exists) {
+        return;
+    }
+
+    for (int i = 0; i < dir.nodeArray.size(); ++i) {
+        Entry& entry = dir.nodeArray[i];
+        // See if it matches the spec
+        if (FilePath::matches(entry.name, shortSpec, settings.caseSensitive)) {
+
+            if ((entry.type == UNKNOWN) && ! (settings.files && settings.directories)) {
+                // Update the type
+                entry.type = isDirectory(FilePath::concat(parentPath, entry.name)) ? DIR_TYPE : FILE_TYPE;
+            }
+            
+            if ((settings.files && settings.directories) ||
+                (settings.files && (entry.type == FILE_TYPE)) ||
+                (settings.directories && (entry.type == DIR_TYPE))) {
+                
+                if (settings.includeParentPath) {
+                    result.append(FilePath::concat(parentPath, entry.name));
+                } else {
+                    result.append(entry.name);
+                }
+            }
+        } // match
+
+        if (settings.recursive && (entry.type == DIR_TYPE)) {
+            listHelper(shortSpec, FilePath::concat(parentPath, entry.name), result, settings);
+        }
+    } // for
+}
+
+
+void FileSystem::_list(const std::string& spec, Array& result, const ListSettings& settings) {
+    const std::string& shortSpec = FilePath::baseExt(spec);
+    const std::string& parentPath = FilePath::parent(spec);
+
+    listHelper(shortSpec, parentPath, result, settings);
+}
+
+
+
+#ifdef G3D_WIN32
+const Array& FileSystem::_drives() {
+    if (m_winDrive.length() == 0) {
+        // See http://msdn.microsoft.com/en-us/library/aa364975(VS.85).aspx
+        static const size_t bufSize = 5000;
+        char bufData[bufSize];
+        GetLogicalDriveStringsA(bufSize, bufData);
+
+        // Drive list is a series of NULL-terminated strings, itself terminated with a NULL.
+        for (int i = 0; bufData[i] != '\0'; ++i) {
+            const char* thisString = bufData + i;
+            m_winDrive.append(toLower(thisString));
+            i += strlen(thisString) + 1;
+        }
+    }
+
+    return m_winDrive;
+}
+#endif
+
+/////////////////////////////////////////////////////////////////////
+
+bool FilePath::isRoot(const std::string& f) {
+#   ifdef G3D_WIN32
+        if (f.length() < 2) {
+            return false;
+        }
+
+        if (f[1] == ':') {
+            if (f.length() == 2) {
+                // e.g.,   "x:"
+                return true;
+            } else if ((f.length() == 3) && isSlash(f[2])) {
+                // e.g.,   "x:\"
+                return true;
+            }
+        }
+
+        if (isSlash(f[0]) && isSlash(f[1])) {        
+            // e.g., "\\foo\"
+            return true;
+        }
+#   else
+        if (f == "/") {
+            return true;
+        }
+#   endif
+
+    return false;
+}
+
+
+std::string FilePath::removeTrailingSlash(const std::string& f) {
+    bool removeSlash = ((endsWith(f, "/") || endsWith(f, "\\"))) && ! isRoot(f);
+
+    return removeSlash ? f.substr(0, f.length() - 1) : f;
+}
+
+
+std::string FilePath::concat(const std::string& dirname, const std::string& file) {
+    // Ensure that the directory ends in a slash
+    if (! dirname.empty() && 
+        ! isSlash(dirname[dirname.size() - 1]) &&
+        (dirname[dirname.size() - 1] != ':')) {
+        return dirname + '/' + file;
+    } else {
+        return dirname + file;
+    }
+}
+
+
+std::string FilePath::ext(const std::string& filename) {
+    int i = filename.rfind(".");
+    if (i >= 0) {
+        return filename.substr(i + 1, filename.length() - i);
+    } else {
+        return "";
+    }
+}
+
+
+std::string FilePath::baseExt(const std::string& filename) {
+    int i = findLastSlash(filename);
+
+#   ifdef G3D_WIN32
+        int 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 FilePath::base(const std::string& path) {
+    std::string filename = baseExt(path);
+    int i = filename.rfind(".");
+    if (i == -1) {
+        // No extension
+        return filename;
+    } else {
+        return filename.substr(0, i);
+    }
+}
+
+
+std::string FilePath::parent(const std::string& path) {    
+    int i = findLastSlash(removeTrailingSlash(path));
+
+#   ifdef G3D_WIN32
+        int j = path.rfind(":");
+        if ((i == -1) && (j >= 0)) {
+            i = j;
+        }
+#   endif
+
+    if (i == -1) {
+        return "";
+    } else {
+        return path.substr(0, i + 1);
+    }
+}
+
+
+bool FilePath::containsWildcards(const std::string& filename) {
+    return (filename.find('*') != std::string::npos) || (filename.find('?') != std::string::npos);
+}
+
+
+bool FilePath::matches(const std::string& path, const std::string& pattern, bool caseSensitive) {
+    int flags = FNM_PERIOD | FNM_NOESCAPE | FNM_PATHNAME;
+    if (!  caseSensitive) {
+        flags |= FNM_CASEFOLD;
+    }
+    return g3dfnmatch(pattern.c_str(), path.c_str(), flags) == 0;
+}
+
+
+static int fixslash(int c) {
+    return (c == '\\') ? '/' : c;
+}
+
+
+std::string FilePath::canonicalize(std::string x) {
+    std::transform(x.begin(), x.end(), x.begin(), fixslash);
+    return x;
+}
+
+
+void FilePath::parse
+(const std::string&     filename,
+ std::string&           root,
+ Array&    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;
+    }
+}
+
+}
diff --git a/dep/src/g3dlite/GCamera.cpp b/dep/src/g3dlite/GCamera.cpp
index 64b0c94543e..0ffc7eb7374 100644
--- a/dep/src/g3dlite/GCamera.cpp
+++ b/dep/src/g3dlite/GCamera.cpp
@@ -5,7 +5,7 @@
   @author Jeff Marsceill, 08jcm@williams.edu
  
   @created 2005-07-20
-  @edited  2009-11-24
+  @edited  2010-02-22
 */
 #include "G3D/GCamera.h"
 #include "G3D/platform.h"
@@ -45,6 +45,8 @@ GCamera::GCamera(const Any& any) {
             m_nearPlaneZ = it->value;
         } else if (k == "FARPLANEZ") {
             m_farPlaneZ = it->value;
+        } else if (k == "PIXELOFFSET") {
+            m_pixelOffset = it->value;
         } else {
             any.verify(false, std::string("Illegal key in table: ") + it->key);
         }
@@ -61,6 +63,7 @@ GCamera::operator Any() const {
     any.set("nearPlaneZ", nearPlaneZ());
     any.set("farPlaneZ", farPlaneZ());
     any.set("coordinateFrame", coordinateFrame());
+    any.set("pixelOffset", pixelOffset());
 
     return any;
 }
@@ -68,7 +71,7 @@ GCamera::operator Any() const {
 
 GCamera::GCamera() {
     setNearPlaneZ(-0.2f);
-    setFarPlaneZ(-100.0f);
+    setFarPlaneZ(-150.0f);
     setFieldOfView((float)toRadians(90.0f), HORIZONTAL);
 }
 
@@ -171,8 +174,8 @@ void GCamera::getProjectPixelMatrix(const Rect2D& viewport, Matrix4& P) const {
     float sx = screenWidth / 2.0;
     float sy = screenHeight / 2.0;
 
-    P = Matrix4(sx, 0, 0, sx + viewport.x0(),
-                0, -sy, 0, sy + viewport.y0(),
+    P = Matrix4(sx, 0, 0, sx + viewport.x0() - m_pixelOffset.x,
+                0, -sy, 0, sy + viewport.y0() + m_pixelOffset.y,
                 0, 0,  1, 0,
                 0, 0,  0, 1) * P;
 }
@@ -185,24 +188,28 @@ void GCamera::getProjectUnitMatrix(const Rect2D& viewport, Matrix4& P) const {
 
     float r, l, t, b, n, f, x, y;
 
+    float s = 1.0f;
     if (m_direction == VERTICAL) {
         y = -m_nearPlaneZ * tan(m_fieldOfView / 2);
         x = y * (screenWidth / screenHeight);
+        s = screenHeight;
     } else { //m_direction == HORIZONTAL
         x = -m_nearPlaneZ * tan(m_fieldOfView / 2);
         y = x * (screenHeight / screenWidth);
+        s = screenWidth;
     }
 
     n = -m_nearPlaneZ;
     f = -m_farPlaneZ;
-    r = x;
-    l = -x;
-    t = y;
-    b = -y;
+    r = x  - m_pixelOffset.x/s;
+    l = -x - m_pixelOffset.x/s;
+    t = y  + m_pixelOffset.y/s;
+    b = -y + m_pixelOffset.y/s;
 
     P = Matrix4::perspectiveProjection(l, r, b, t, n, f);
 }
 
+
 Vector3 GCamera::projectUnit(const Vector3& point, const Rect2D& viewport) const {
     Matrix4 M;
     getProjectUnitMatrix(viewport, M);
@@ -244,7 +251,7 @@ Vector3 GCamera::unproject(const Vector3& v, const Rect2D& viewport) const {
         z = 1.0f / ((((1.0f / f) - (1.0f / n)) * v.z) + 1.0f / n);
     }
 
-    const Ray& ray = worldRay(v.x, v.y, viewport);
+    const Ray& ray = worldRay(v.x - m_pixelOffset.x, v.y - m_pixelOffset.y, viewport);
 
     // Find out where the ray reaches the specified depth.
     const Vector3& out = ray.origin() + ray.direction() * -z / (ray.direction().dot(m_cframe.lookVector()));
@@ -481,6 +488,7 @@ void GCamera::serialize(BinaryOutput& bo) const {
     bo.writeFloat32(farPlaneZ());
     m_cframe.serialize(bo);
     bo.writeInt8(m_direction);
+    m_pixelOffset.serialize(bo);
 }
 
 
@@ -492,6 +500,7 @@ void GCamera::deserialize(BinaryInput& bi) {
     debugAssert(m_farPlaneZ < 0.0f);
     m_cframe.deserialize(bi);
     m_direction = (FOVDirection)bi.readInt8();
+    m_pixelOffset.deserialize(bi);
 }
 
 
diff --git a/dep/src/g3dlite/GImage.cpp b/dep/src/g3dlite/GImage.cpp
index 9527e96cf67..19a2b1e71f4 100644
--- a/dep/src/g3dlite/GImage.cpp
+++ b/dep/src/g3dlite/GImage.cpp
@@ -639,7 +639,7 @@ void GImage::rotate90CW(int numTimes) {
     for (int j = 0; j < numTimes; ++j) {
         {
             uint8* temp = old;
-            uint8* old = m_byte;
+            old = m_byte;
             m_byte = temp;
         }
         
diff --git a/dep/src/g3dlite/GImage_png.cpp b/dep/src/g3dlite/GImage_png.cpp
index 0a515bf7ed2..875c7015cd1 100644
--- a/dep/src/g3dlite/GImage_png.cpp
+++ b/dep/src/g3dlite/GImage_png.cpp
@@ -71,10 +71,20 @@ void png_warning(
 void GImage::encodePNG(
     BinaryOutput&           out) const {
 
-    debugAssert( m_channels == 1 || m_channels == 3 || m_channels == 4 );
+    if (! (m_channels == 1 || m_channels == 3 || m_channels == 4)) {
+        throw GImage::Error(format("Illegal channels for PNG: %d", m_channels), out.getFilename());
+    }
+    if (m_width <= 0) {
+        throw GImage::Error(format("Illegal width for PNG: %d", m_width), out.getFilename());
+    }
+    if (m_height <= 0) {
+        throw GImage::Error(format("Illegal height for PNG: %d", m_height), out.getFilename());
+    }
 
-    if (m_height > (int)(PNG_UINT_32_MAX / png_sizeof(png_bytep)))
+    // PNG library requires that the height * pointer size fit within an int
+    if (png_uint_32(m_height) * png_sizeof(png_bytep) > PNG_UINT_32_MAX) {
         throw GImage::Error("Unsupported PNG height.", out.getFilename());
+    }
 
     out.setEndian(G3D_LITTLE_ENDIAN);
 
@@ -184,7 +194,7 @@ void GImage::decodePNG(
     int bit_depth, color_type, interlace_type;
     // this will validate the data it extracts from info_ptr
     png_get_IHDR(png_ptr, info_ptr, &png_width, &png_height, &bit_depth, &color_type,
-       &interlace_type, int_p_NULL, int_p_NULL);
+       &interlace_type, NULL, NULL);
 
     if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
         png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
@@ -206,7 +216,7 @@ void GImage::decodePNG(
 
     //Expand grayscale images to the full 8 bits from 1, 2, or 4 bits/pixel
     if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) {
-        png_set_gray_1_2_4_to_8(png_ptr);
+        png_set_expand(png_ptr);
     }
 
     //Expand paletted or RGB images with transparency to full alpha channels
@@ -253,7 +263,7 @@ void GImage::decodePNG(
     for (uint32 pass = 0; pass < number_passes; ++pass) {
         for (uint32 y = 0; y < (uint32)m_height; ++y) {
             png_bytep rowPointer = &m_byte[m_width * m_channels * y]; 
-            png_read_rows(png_ptr, &rowPointer, png_bytepp_NULL, 1);
+            png_read_rows(png_ptr, &rowPointer, NULL, 1);
         }
     }
 
diff --git a/dep/src/g3dlite/GImage_ppm.cpp b/dep/src/g3dlite/GImage_ppm.cpp
index 28f8cdf9ab0..f3065c6038b 100644
--- a/dep/src/g3dlite/GImage_ppm.cpp
+++ b/dep/src/g3dlite/GImage_ppm.cpp
@@ -183,7 +183,7 @@ void GImage::decodePPM(
     int w, h;
 
     input.readBytes(head, 2);
-    if (head[0] != 'P' || (head[1] != '6') && (head[1] != '5')) {
+    if (head[0] != 'P' || ((head[1] != '6') && (head[1] != '5'))) {
         throw GImage::Error("Invalid PPM Header.", input.getFilename());
     }
 
diff --git a/dep/src/g3dlite/GImage_tga.cpp b/dep/src/g3dlite/GImage_tga.cpp
index 9785f879a1f..fdcd59af726 100644
--- a/dep/src/g3dlite/GImage_tga.cpp
+++ b/dep/src/g3dlite/GImage_tga.cpp
@@ -94,6 +94,20 @@ void GImage::encodeTGA(
     out.writeString("TRUEVISION-XFILE ");
 }
 
+inline static void readBGR(uint8* byte, BinaryInput& bi) {
+    int b = bi.readUInt8();
+    int g = bi.readUInt8();
+    int r = bi.readUInt8();
+
+    byte[0] = r;
+    byte[1] = g;
+    byte[2] = b;
+}
+
+inline static void readBGRA(uint8* byte, BinaryInput& bi) {
+    readBGR(byte, bi);
+    byte[3] = bi.readUInt8();
+}
 
 void GImage::decodeTGA(
     BinaryInput&        input) {
@@ -117,8 +131,8 @@ void GImage::decodeTGA(
     (void)colorMapType;
 	
     // 2 is the type supported by this routine.
-    if (imageType != 2) {
-        throw Error("TGA images must be type 2 (Uncompressed truecolor)", input.getFilename());
+    if (imageType != 2 && imageType != 10) {
+        throw Error("TGA images must be type 2 (Uncompressed truecolor) or 10 (Run-length truecolor)", input.getFilename());
     }
 	
     // Color map specification
@@ -159,34 +173,63 @@ void GImage::decodeTGA(
     int x;
     int y;
 
-    if (m_channels == 3) {
-        for (y = m_height - 1; y >= 0; --y) {
-          for (x = 0; x < m_width; ++x) {
-            int b = input.readUInt8();
-            int g = input.readUInt8();
-            int r = input.readUInt8();
-		    
-            int i = (x + y * m_width) * 3;
-            m_byte[i + 0] = r;
-            m_byte[i + 1] = g;
-            m_byte[i + 2] = b;
-          }
+    if (imageType == 2) {
+        // Uncompressed
+        if (m_channels == 3) {
+            for (y = m_height - 1; y >= 0; --y) {
+              for (x = 0; x < m_width; ++x) {
+                int i = (x + y * m_width) * 3;
+                readBGR(m_byte + i, input);
+              }
+            }
+        } else {
+            for (y = m_height - 1; y >= 0; --y) {
+              for (x = 0; x < m_width; ++x) {
+                 int i = (x + y * m_width) * 4;
+                 readBGRA(m_byte + i, input);
+              }
+            }
         }
-    } else {
+    } else if (imageType == 10) {
+
+        // Run-length encoded 
         for (y = m_height - 1; y >= 0; --y) {
-          for (x = 0; x < m_width; ++x) {
-            int b = input.readUInt8();
-            int g = input.readUInt8();
-            int r = input.readUInt8();
-            int a = input.readUInt8();
-		    
-            int i = (x + y * m_width) * 4;
-            m_byte[i + 0] = r;
-            m_byte[i + 1] = g;
-            m_byte[i + 2] = b;
-            m_byte[i + 3] = a;
-          }
+            for (int x = 0; x < m_width; /* intentionally no x increment */) {
+                // The specification guarantees that no packet will wrap past the end of a row
+                const uint8 repetitionCount = input.readUInt8();
+                const uint8 numValues = (repetitionCount & (~128)) + 1;
+                int byteOffset = (x + y * m_width) * 3;
+
+                if (repetitionCount & 128) {
+                    // When the high bit is 1, this is a run-length packet
+                    if (m_channels == 3) {
+                        Color3uint8 value;
+                        readBGR((uint8*)(&value), input);
+                        for (int i = 0; i < numValues; ++i, ++x) {
+                            for (int b = 0; b < 3; ++b, ++byteOffset) {
+                                m_byte[byteOffset] = value[b];
+                            }
+                        }
+                    } else {
+                        Color4uint8 value;
+                        readBGRA((uint8*)(&value), input);
+                        for (int i = 0; i < numValues; ++i, ++x) {
+                            for (int b = 0; b < 3; ++b, ++byteOffset) {
+                                m_byte[byteOffset] = value[b];
+                            }
+                        }
+                    }
+
+                } else {
+                    // When the high bit is 0, this is a raw packet
+                    for (int i = 0; i < numValues; ++i, ++x, byteOffset += m_channels) {
+                        readBGR(m_byte + byteOffset, input);
+                    }
+                }
+            }
         }
+    } else {
+        alwaysAssertM(false, "Unsupported type");
     }
 }
 
diff --git a/dep/src/g3dlite/GLight.cpp b/dep/src/g3dlite/GLight.cpp
index 37c8054ff3d..553b493c1a3 100644
--- a/dep/src/g3dlite/GLight.cpp
+++ b/dep/src/g3dlite/GLight.cpp
@@ -19,6 +19,8 @@ GLight::GLight(const Any& any) {
 
     if (any.type() == Any::TABLE) {
         *this = GLight();
+        Vector3 spotTarget;
+        bool hasSpotTarget = false;
         for (Any::AnyTable::Iterator it = any.table().begin(); it.hasMore(); ++it) {
             const std::string& key = toLower(it->key);
             if (key == "position") {
@@ -26,7 +28,10 @@ GLight::GLight(const Any& any) {
             } else if (key == "rightdirection") {
                 rightDirection = it->value;
             } else if (key == "spotdirection") {
-                spotDirection = it->value;
+                spotDirection = Vector3(it->value).directionOrZero();
+            } else if (key == "spottarget") {
+                spotTarget = it->value;
+                hasSpotTarget = true;
             } else if (key == "spotcutoff") {
                 spotCutoff = it->value.number();
             } else if (key == "spotsquare") {
@@ -47,6 +52,9 @@ GLight::GLight(const Any& any) {
                 any.verify(false, "Illegal key: " + it->key);
             }
         }
+        if (hasSpotTarget) {
+            spotDirection = (spotTarget - position.xyz()).direction();
+        }
     } else if (toLower(any.name()) == "glight::directional") {
 
         *this = directional(any[0], any[1], 
@@ -67,9 +75,9 @@ GLight::GLight(const Any& any) {
         *this = spot(any[0], any[1], any[2], any[3],
             (any.size() > 4) ? any[4] : Any(1), 
             (any.size() > 5) ? any[5] : Any(0), 
-            (any.size() > 6) ? any[6] : Any(0.5f), 
-            (any.size() > 7) ? any[5] : Any(true), 
-            (any.size() > 8) ? any[6] : Any(true));
+            (any.size() > 6) ? any[6] : Any(0), 
+            (any.size() > 7) ? any[7] : Any(true), 
+            (any.size() > 8) ? any[8] : Any(true));
     } else {
         any.verify(false, "Unrecognized name");
     }
diff --git a/dep/src/g3dlite/ImageFormat.cpp b/dep/src/g3dlite/ImageFormat.cpp
index 70de878c11e..46618c64480 100644
--- a/dep/src/g3dlite/ImageFormat.cpp
+++ b/dep/src/g3dlite/ImageFormat.cpp
@@ -4,7 +4,7 @@
  @maintainer Morgan McGuire, http://graphics.cs.williams.edu
  
  @created 2003-05-23
- @edited  2009-12-10
+ @edited  2010-03-30
  */
 
 #include "GLG3D/glheaders.h"
@@ -130,13 +130,19 @@ const ImageFormat* ImageFormat::stencil(int bits) {
         "RGB8I",
         "RGB8UI",
 
+        "RGBA8UI",
+
         "ARGB8",
         "BGR8",
 
+        "R8",
+
         "RG8",
         "RG8I",
         "RG8UI",
 
+        "RG16F",
+
         "RGBA8",
         "RGBA16",
         "RGBA16F",
@@ -287,6 +293,9 @@ const ImageFormat* ImageFormat::fromCode(ImageFormat::Code code) {
     case ImageFormat::CODE_BGR8:
         return ImageFormat::BGR8();
 
+    case ImageFormat::CODE_R8:
+        return ImageFormat::R8();
+
     case ImageFormat::CODE_RG8:
         return ImageFormat::RG8();
 
@@ -296,6 +305,9 @@ const ImageFormat* ImageFormat::fromCode(ImageFormat::Code code) {
     case ImageFormat::CODE_RG8UI:
         return ImageFormat::RG8UI();
 
+    case ImageFormat::CODE_RG16F:
+        return ImageFormat::RG16F();
+
     case ImageFormat::CODE_RGBA8:
         return ImageFormat::RGBA8();
 
@@ -474,11 +486,16 @@ DEFINE_TEXTUREFORMAT_METHOD(LA32F,      2, UNCOMP_FORMAT,   GL_LUMINANCE_ALPHA32
 
 DEFINE_TEXTUREFORMAT_METHOD(BGR8,       3, UNCOMP_FORMAT,   GL_RGB8,            GL_BGR,     0,  0,  8,  8,  8,  0,  0, 32, 24,      GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INT_FORMAT, ImageFormat::CODE_BGR8, ImageFormat::COLOR_SPACE_RGB);
 
+DEFINE_TEXTUREFORMAT_METHOD(R8,         1, UNCOMP_FORMAT,   GL_R8,              GL_RED,    0,  0,  8,  0,  0,  0,  0, 8, 8,      GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INT_FORMAT, ImageFormat::CODE_R8, ImageFormat::COLOR_SPACE_RGB);
+
 DEFINE_TEXTUREFORMAT_METHOD(RG8,        2, UNCOMP_FORMAT,   GL_RG8,             GL_RG,     0,  0,  8,  8,  0,  0,  0, 16, 16,      GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INT_FORMAT, ImageFormat::CODE_RG8, ImageFormat::COLOR_SPACE_RGB);
 
-DEFINE_TEXTUREFORMAT_METHOD(RG8I,       2, UNCOMP_FORMAT,   GL_RG8I,            GL_RG,     0,  0,  8,  8,  0,  0,  0, 16, 16,      GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INT_FORMAT, ImageFormat::CODE_RG8I, ImageFormat::COLOR_SPACE_RGB);
+// The base format for integer formats must be *_INTEGER even though the spec doesn't state this
+DEFINE_TEXTUREFORMAT_METHOD(RG8I,       2, UNCOMP_FORMAT,   GL_RG8I,            GL_RG_INTEGER,     0,  0,  8,  8,  0,  0,  0, 16, 16,      GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INT_FORMAT, ImageFormat::CODE_RG8I, ImageFormat::COLOR_SPACE_RGB);
 
-DEFINE_TEXTUREFORMAT_METHOD(RG8UI,      2, UNCOMP_FORMAT,   GL_RG8UI,           GL_RG,     0,  0,  8,  8,  0,  0,  0, 16, 16,      GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INT_FORMAT, ImageFormat::CODE_RG8UI, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(RG8UI,      2, UNCOMP_FORMAT,   GL_RG8UI,           GL_RG_INTEGER,     0,  0,  8,  8,  0,  0,  0, 16, 16,      GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INT_FORMAT, ImageFormat::CODE_RG8UI, ImageFormat::COLOR_SPACE_RGB);
+
+DEFINE_TEXTUREFORMAT_METHOD(RG16F,      2, UNCOMP_FORMAT,   GL_RG16F,           GL_RG,     0,  0,  16, 16,  0,  0,  0, 32, 32,      GL_FLOAT, OPAQUE_FORMAT, FLOAT_FORMAT, ImageFormat::CODE_RG16F, ImageFormat::COLOR_SPACE_RGB);
 
 DEFINE_TEXTUREFORMAT_METHOD(RGB5,       3, UNCOMP_FORMAT,   GL_RGB5,            GL_RGBA,    0,  0,  5,  5,  5,  0,  0, 16, 16,      GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INT_FORMAT, ImageFormat::CODE_RGB5, ImageFormat::COLOR_SPACE_RGB);
 
@@ -504,7 +521,8 @@ DEFINE_TEXTUREFORMAT_METHOD(RGBA16F,    4, UNCOMP_FORMAT,   GL_RGBA16F_ARB,
 
 DEFINE_TEXTUREFORMAT_METHOD(RGBA32F,    4, UNCOMP_FORMAT,   GL_RGBA32F_ARB,                     GL_RGBA,    0, 32, 32, 32, 32, 0, 0, 32*4, 32*4,    GL_FLOAT, CLEAR_FORMAT, FLOAT_FORMAT, ImageFormat::CODE_RGBA32F, ImageFormat::COLOR_SPACE_RGB);
 
-DEFINE_TEXTUREFORMAT_METHOD(RGBA32UI,   4, UNCOMP_FORMAT,   GL_RGBA32UI,                        GL_RGBA,    0, 32, 32, 32, 32, 0, 0, 32*4, 32*4,    GL_UNSIGNED_INT, CLEAR_FORMAT, INT_FORMAT, ImageFormat::CODE_RGBA32UI, ImageFormat::COLOR_SPACE_RGB);
+// The base format for integer formats must be *_INTEGER even though the spec doesn't state this
+DEFINE_TEXTUREFORMAT_METHOD(RGBA32UI,   4, UNCOMP_FORMAT,   GL_RGBA32UI,                        GL_RGBA_INTEGER,    0, 32, 32, 32, 32, 0, 0, 32*4, 32*4,    GL_UNSIGNED_INT, CLEAR_FORMAT, INT_FORMAT, ImageFormat::CODE_RGBA32UI, ImageFormat::COLOR_SPACE_RGB);
 
 // Unsigned
 DEFINE_TEXTUREFORMAT_METHOD(R11G11B10F, 3, UNCOMP_FORMAT,   GL_R11F_G11F_B10F_EXT,              GL_RGB,     0,  0, 11, 11, 10, 0, 0,   32,   32,    GL_FLOAT, OPAQUE_FORMAT, FLOAT_FORMAT, ImageFormat::CODE_R11G11B10F, ImageFormat::COLOR_SPACE_RGB);
@@ -512,9 +530,12 @@ DEFINE_TEXTUREFORMAT_METHOD(R11G11B10F, 3, UNCOMP_FORMAT,   GL_R11F_G11F_B10F_EX
 // Unsigned
 DEFINE_TEXTUREFORMAT_METHOD(RGB9E5F,    3, UNCOMP_FORMAT,   GL_RGB9_E5_EXT,                     GL_RGB,     0,  0, 14, 14, 14, 0, 0,   32,   32,    GL_FLOAT, OPAQUE_FORMAT, FLOAT_FORMAT, ImageFormat::CODE_RGB9E5F, ImageFormat::COLOR_SPACE_RGB);
 
-DEFINE_TEXTUREFORMAT_METHOD(RGB8I,      3, UNCOMP_FORMAT,   GL_RGB8I_EXT,                       GL_RGB,     0,  0,  8,  8,  8,  0,  0, 32, 24,      GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INT_FORMAT, ImageFormat::CODE_RGB8I, ImageFormat::COLOR_SPACE_RGB);
+// The base format for integer formats must be *_INTEGER even though the spec doesn't state this
+DEFINE_TEXTUREFORMAT_METHOD(RGB8I,      3, UNCOMP_FORMAT,   GL_RGB8I_EXT,                       GL_RGB_INTEGER,     0,  0,  8,  8,  8,  0,  0, 32, 24,      GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INT_FORMAT, ImageFormat::CODE_RGB8I, ImageFormat::COLOR_SPACE_RGB);
+
+DEFINE_TEXTUREFORMAT_METHOD(RGB8UI,     3, UNCOMP_FORMAT,   GL_RGB8UI_EXT,                      GL_RGB_INTEGER,     0,  0,  8,  8,  8,  0,  0, 32, 24,      GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INT_FORMAT, ImageFormat::CODE_RGB8UI, ImageFormat::COLOR_SPACE_RGB);
 
-DEFINE_TEXTUREFORMAT_METHOD(RGB8UI,     3, UNCOMP_FORMAT,   GL_RGB8UI_EXT,                      GL_RGB,     0,  0,  8,  8,  8,  0,  0, 32, 24,      GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INT_FORMAT, ImageFormat::CODE_RGB8UI, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(RGBA8UI,    4, UNCOMP_FORMAT,   GL_RGBA8UI_EXT,                     GL_RGBA_INTEGER,    0,  0,  8,  8,  8,  8,  0, 32, 32,      GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INT_FORMAT, ImageFormat::CODE_RGBA8UI, ImageFormat::COLOR_SPACE_RGB);
 
 
 DEFINE_TEXTUREFORMAT_METHOD(RGB_DXT1,   3, COMP_FORMAT,     GL_COMPRESSED_RGB_S3TC_DXT1_EXT,    GL_RGB,     0, 0, 0, 0, 0, 0, 0, 64, 64,    GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INT_FORMAT, ImageFormat::CODE_RGB_DXT1, ImageFormat::COLOR_SPACE_RGB);
diff --git a/dep/src/g3dlite/Log.cpp b/dep/src/g3dlite/Log.cpp
index 07614fcf563..f437351cfbd 100644
--- a/dep/src/g3dlite/Log.cpp
+++ b/dep/src/g3dlite/Log.cpp
@@ -3,7 +3,7 @@
 
   @maintainer Morgan McGuire, http://graphics.cs.williams.edu
   @created 2001-08-04
-  @edited  2009-01-15
+  @edited  2010-01-15
  */
 
 #include "G3D/platform.h"
@@ -11,6 +11,7 @@
 #include "G3D/format.h"
 #include "G3D/Array.h"
 #include "G3D/fileutils.h"
+#include "G3D/FileSystem.h"
 #include 
 
 #ifdef G3D_WIN32
@@ -43,7 +44,7 @@ Log::Log(const std::string& filename, int stripFromStackBottom) :
 
     this->filename = filename;
 
-    logFile = fopen(filename.c_str(), "w");
+    logFile = FileSystem::fopen(filename.c_str(), "w");
 
     if (logFile == NULL) {
         std::string drive, base, ext;
@@ -58,7 +59,7 @@ Log::Log(const std::string& filename, int stripFromStackBottom) :
             logName = std::string("/tmp/") + logName;
         #endif
 
-        logFile = fopen(logName.c_str(), "w");
+        logFile = FileSystem::fopen(logName.c_str(), "w");
     }
 
     // Use a large buffer (although we flush in logPrintf)
diff --git a/dep/src/g3dlite/Matrix3.cpp b/dep/src/g3dlite/Matrix3.cpp
index b32d938f0f9..7e4de99621a 100644
--- a/dep/src/g3dlite/Matrix3.cpp
+++ b/dep/src/g3dlite/Matrix3.cpp
@@ -29,11 +29,17 @@ 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];
+    if (any.nameEquals("Matrix3::fromAxisAngle")) {
+        any.verifySize(2);
+        *this = Matrix3::fromAxisAngle(any[0], any[1].number());
+    } else {
+        any.verifySize(9);
+
+        for (int r = 0; r < 3; ++r) {
+            for (int c = 0; c < 3; ++c) {
+                elt[r][c] = any[r * 3 + c];
+            }
         }
     }
 }
diff --git a/dep/src/g3dlite/Matrix4.cpp b/dep/src/g3dlite/Matrix4.cpp
index cd38a1a3602..2ce14f6c5d4 100644
--- a/dep/src/g3dlite/Matrix4.cpp
+++ b/dep/src/g3dlite/Matrix4.cpp
@@ -44,7 +44,12 @@ Matrix4::Matrix4(const Any& any) {
         } else {
             any.verify(false, "Matrix4::scale() takes either 1 or 3 arguments");
         }
-    } else {
+    } else if (name == "matrix4::translation") {
+        if (any.size() == 3) {
+            *this = translation(any[0], any[1], any[2]);
+        } else {
+            any.verify(false, "Matrix4::translation() takes either 1 or 3 arguments");
+        }    } else {
         any.verify(false, "Expected Matrix4 constructor");
     }
 }
diff --git a/dep/src/g3dlite/MeshAlgAdjacency.cpp b/dep/src/g3dlite/MeshAlgAdjacency.cpp
index 24b5d207c88..f0bf3382131 100644
--- a/dep/src/g3dlite/MeshAlgAdjacency.cpp
+++ b/dep/src/g3dlite/MeshAlgAdjacency.cpp
@@ -3,9 +3,9 @@
 
   @maintainer Morgan McGuire, http://graphics.cs.williams.edu
   @created 2003-09-14
-  @edited  2009-04-26
+  @edited  2010-04-26
 
-  Copyright 2000-2009, Morgan McGuire.
+  Copyright 2000-2010, Morgan McGuire.
   All rights reserved.
 
  */
@@ -15,6 +15,7 @@
 #include "G3D/Set.h"
 #include "G3D/Stopwatch.h"
 #include "G3D/SmallArray.h"
+#include "G3D/AreaMemoryManager.h"
 
 namespace G3D {
 
@@ -43,6 +44,11 @@ class MeshEdgeTable {
 
 public:
 
+    MeshEdgeTable() {
+        AreaMemoryManager::Ref mm = AreaMemoryManager::create();
+        table.clearAndSetMemoryManager(mm);
+    }
+
     void clear() {
         table.clear();
     }
diff --git a/dep/src/g3dlite/NetworkDevice.cpp b/dep/src/g3dlite/NetworkDevice.cpp
index 246c97d4dbf..1fc794479f5 100644
--- a/dep/src/g3dlite/NetworkDevice.cpp
+++ b/dep/src/g3dlite/NetworkDevice.cpp
@@ -6,8 +6,6 @@
  @edited  2006-02-24
  */
 
-#include 
-#include 
 #include "G3D/platform.h"
 #include "G3D/TextOutput.h"
 #include "G3D/NetworkDevice.h"
@@ -18,94 +16,8 @@
 #include "G3D/G3DGameUnits.h"
 #include "G3D/stringutils.h"
 #include "G3D/debug.h"
+#include "G3D/networkHelpers.h"
 
-#include 
-
-#if defined(G3D_LINUX) || defined(G3D_OSX) || defined(G3D_FREEBSD)
-#   include 
-#   include 
-#   include 
-#   include 
-#   include 
-#   ifdef __linux__
-#       include 
-#       include 
-#       include 
-#       include 
-//    Match Linux to FreeBSD
-#       define AF_LINK AF_PACKET
-#   else
-#       include 
-#       include 
-#   endif
-
-    #include 
-    #include 
-    #include 
-    #include 
-    #include 
-    #include 
-    #include 
-    #include 
-    #include 
-    #include 
-    #include 
-
-    #include 
-
-    #define _alloca alloca
-
-    /** Define an error code for non-windows platforms. */
-    int WSAGetLastError() {
-        return -1;
-    }
-
-    #define SOCKET_ERROR -1
-
-    static std::string socketErrorCode(int code) {
-        return G3D::format("CODE %d: %s\n", code, strerror(code));
-    }
-
-    static std::string socketErrorCode() {
-        return socketErrorCode(errno);
-    }
-
-    static const int WSAEWOULDBLOCK = -100;
-
-    typedef int SOCKET;
-    typedef struct sockaddr_in SOCKADDR_IN;
-
-#else 
-
-    // Windows
-    static std::string socketErrorCode(int code) {
-        LPTSTR formatMsg = NULL;
-
-        FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
-                      FORMAT_MESSAGE_IGNORE_INSERTS |
-                      FORMAT_MESSAGE_FROM_SYSTEM,
-                        NULL,
-                        code,
-                        0,
-                        (LPTSTR)&formatMsg,
-                        0,
-                        NULL);
-
-        return G3D::format("CODE %d: %s\n", code, formatMsg);
-    }
-
-    static std::string socketErrorCode() {
-        return socketErrorCode(GetLastError());
-    }
-
-#endif
-
-
-#ifndef _SOCKLEN_T
-#   if defined(G3D_WIN32) || defined(G3D_OSX)
-        typedef int socklen_t;
-#   endif
-#endif
 
 namespace G3D {
 
diff --git a/dep/src/g3dlite/PhysicsFrame.cpp b/dep/src/g3dlite/PhysicsFrame.cpp
index 28ba8f8d477..30fbdf8d619 100644
--- a/dep/src/g3dlite/PhysicsFrame.cpp
+++ b/dep/src/g3dlite/PhysicsFrame.cpp
@@ -4,10 +4,12 @@
  @maintainer Morgan McGuire, http://graphics.cs.williams.edu
  
  @created 2002-07-09
- @edited  2006-01-25
+ @edited  2010-03-25
 */
 
 #include "G3D/platform.h"
+#include "G3D/Any.h"
+#include "G3D/stringutils.h"
 #include "G3D/PhysicsFrame.h"
 #include "G3D/BinaryInput.h"
 #include "G3D/BinaryOutput.h"
@@ -28,6 +30,37 @@ PhysicsFrame::PhysicsFrame(
 }
 
 
+PhysicsFrame::PhysicsFrame(const Any& a) {
+    const std::string& n = toLower(a.name());
+    *this = PhysicsFrame();
+
+    if (beginsWith(n, "vector3")) {
+        *this = PhysicsFrame(Vector3(a));
+    } else if (beginsWith(n, "matrix3")) {        
+        *this = PhysicsFrame(Matrix3(a));
+    } else if (beginsWith(n, "cframe") || beginsWith(n, "coordinateframe")) {        
+        *this = PhysicsFrame(CoordinateFrame(a));
+    } else if (beginsWith(n, "pframe") || beginsWith(n, "physicsframe")) {
+        if (a.type() == Any::ARRAY) {
+            a.verifySize(2);
+            rotation    = a[0];
+            translation = a[1];
+        } else {
+            for (Any::AnyTable::Iterator it = a.table().begin(); it.hasMore(); ++it) {
+                const std::string& n = toLower(it->key);
+                if (n == "translation") {
+                    translation = it->value;
+                } else if (n == "rotation") {
+                    rotation = it->value;
+                } else {
+                    a.verify(false, "Illegal table key: " + it->key);
+                }
+            }
+        }
+    }
+}
+
+
 PhysicsFrame PhysicsFrame::operator*(const PhysicsFrame& other) const {
     PhysicsFrame result;
 
@@ -38,7 +71,7 @@ PhysicsFrame PhysicsFrame::operator*(const PhysicsFrame& other) const {
 }
 
 
-CoordinateFrame PhysicsFrame::toCoordinateFrame() const {
+PhysicsFrame::operator CoordinateFrame() const {
     CoordinateFrame f;
     
     f.translation = translation;
diff --git a/dep/src/g3dlite/PhysicsFrameSpline.cpp b/dep/src/g3dlite/PhysicsFrameSpline.cpp
new file mode 100644
index 00000000000..2dfdb6f9139
--- /dev/null
+++ b/dep/src/g3dlite/PhysicsFrameSpline.cpp
@@ -0,0 +1,80 @@
+/**
+  \file PhysicsFrameSpline.cpp
+
+  \author Morgan McGuire, http://graphics.cs.williams.edu
+ */
+#include "G3D/PhysicsFrameSpline.h"
+#include "G3D/Any.h"
+#include "G3D/stringutils.h"
+
+namespace G3D {
+
+PhysicsFrameSpline::PhysicsFrameSpline() {}
+
+PhysicsFrameSpline::PhysicsFrameSpline(const Any& any) {
+    *this = any;
+}
+
+PhysicsFrameSpline& PhysicsFrameSpline::operator=(const Any& any) {
+    const std::string& n = toLower(any.name());
+    *this = PhysicsFrameSpline();
+
+    if (n == "physicsframespline" || n == "pframespline") {
+        any.verifyName("PhysicsFrameSpline", "PFrameSpline");
+        
+        for (Any::AnyTable::Iterator it = any.table().begin(); it.hasMore(); ++it) {
+            const std::string& k = toLower(it->key);
+            if (k == "cyclic") {
+                cyclic = it->value;
+            } else if (k == "control") {
+                const Any& v = it->value;
+                v.verifyType(Any::ARRAY);
+                control.resize(v.size());
+                for (int i = 0; i < control.size(); ++i) {
+                    control[i] = v[i];
+                }
+                if (! any.containsKey("time")) {
+                    time.resize(control.size());
+                    for (int i = 0; i < time.size(); ++i) {
+                        time[i] = i;
+                    }
+                }
+            } else if (k == "finalinterval") {
+                finalInterval = it->value;
+            } else if (k == "time") {
+                const Any& v = it->value;
+                v.verifyType(Any::ARRAY);
+                time.resize(v.size());
+                for (int i = 0; i < time.size(); ++i) {
+                    time[i] = v[i];
+                }
+            }
+        }
+    } else {
+        // Must be a PhysicsFrame constructor of some kind
+        append(any);
+    }
+    return *this;
+}
+
+
+void PhysicsFrameSpline::correct(PhysicsFrame& frame) const {
+    frame.rotation.unitize();
+}
+
+
+void PhysicsFrameSpline::ensureShortestPath(PhysicsFrame* A, int N) const {
+    for (int i = 1; i < N; ++i) {
+        const Quat& p = A[i - 1].rotation;
+        Quat& q = A[i].rotation;
+
+        float cosphi = p.dot(q);
+
+        if (cosphi < 0) {
+            // Going the long way, so change the order
+            q = -q;
+        }
+    }
+}
+
+}
diff --git a/dep/src/g3dlite/Quat.cpp b/dep/src/g3dlite/Quat.cpp
index 225c5b51acc..e06483b44cd 100644
--- a/dep/src/g3dlite/Quat.cpp
+++ b/dep/src/g3dlite/Quat.cpp
@@ -6,10 +6,12 @@
   @author Morgan McGuire, graphics3d.com
   
   @created 2002-01-23
-  @edited  2006-01-31
+  @edited  2010-03-31
  */
 
 #include "G3D/Quat.h"
+#include "G3D/Any.h"
+#include "G3D/stringutils.h"
 #include "G3D/BinaryInput.h"
 #include "G3D/BinaryOutput.h"
 
@@ -28,8 +30,22 @@ Quat Quat::fromAxisAngleRotation(
 }
 
 
-Quat::Quat(
-    const Matrix3& rot) {
+Quat::Quat(const class Any& a) {
+    *this = Quat();
+    if (beginsWith(toLower(a.name()), "matrix3")) {
+        *this = a;
+    } else {
+        a.verifyName("Quat");
+        a.verifyType(Any::ARRAY);
+        x = a[0];
+        y = a[1];
+        z = a[2];
+        w = a[3];
+    }
+}
+
+
+Quat::Quat(const Matrix3& rot) {
 
     static const int plus1mod3[] = {1, 2, 0};
 
diff --git a/dep/src/g3dlite/RegistryUtil.cpp b/dep/src/g3dlite/RegistryUtil.cpp
index fc4cebc2ee5..28ff6955d9b 100644
--- a/dep/src/g3dlite/RegistryUtil.cpp
+++ b/dep/src/g3dlite/RegistryUtil.cpp
@@ -257,7 +257,7 @@ bool RegistryUtil::writeString(const std::string& key, const std::string& value,
 
 
 // static helpers
-static HKEY getRootKeyFromString(const char* str, size_t length) {
+static HKEY getRootKeyFromString(const char* str, uint32 length) {
     debugAssert(str);
 
     if (str) {
diff --git a/dep/src/g3dlite/System.cpp b/dep/src/g3dlite/System.cpp
index e03c4e8c6fa..b820db78368 100644
--- a/dep/src/g3dlite/System.cpp
+++ b/dep/src/g3dlite/System.cpp
@@ -27,6 +27,7 @@
 #include "G3D/Table.h"
 #include "G3D/GMutex.h"
 #include "G3D/units.h"
+#include "G3D/FileSystem.h"
 #include 
 
 #include 
@@ -80,9 +81,8 @@
 #endif
 
 // SIMM include
-#ifdef __SSE__
 #include 
-#endif
+
 
 namespace G3D {
 
@@ -340,40 +340,6 @@ void getG3DVersion(std::string& s) {
     s = cstr;
 }
 
-#if 0 // TODO: delete
-struct Directory {
-    std::string          path;
-    Array   contents;
-};
-
-static bool maybeAddDirectory(const std::string& newPath, Array& directoryArray, bool recurse = true) {
-    if (fileExists(newPath)) {
-        Directory& d = directoryArray.next();
-        d.path = newPath;
-        getFiles(pathConcat(newPath, "*"), d.contents);
-        Array 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,
@@ -385,14 +351,14 @@ std::string System::findDataFile
 
     // First check if the file exists as requested.  This will go
     // through the FileSystemCache, so most calls do not touch disk.
-    if (fileExists(full)) {
+    if (FileSystem::exists(full)) {
         return full;
     }
 
     // Now check where we previously found this file.
     std::string* last = lastFound.getPointer(full);
     if (last != NULL) {
-        if (fileExists(*last)) {
+        if (FileSystem::exists(*last)) {
             // Even if cwd has changed the file is still present.
             // We won't notice if it has been deleted, however.
             return *last;
@@ -405,20 +371,33 @@ std::string System::findDataFile
     // Places to look
     static Array directoryArray;
 
+    std::string initialAppDataDir(instance().m_appDataDir);
+    const char* g3dPath = getenv("G3DDATA");
+
     if (directoryArray.size() == 0) {
         // Initialize the directory array
         RealTime t0 = System::time();
 
         Array baseDirArray;
-
-        std::string initialAppDataDir(instance().m_appDataDir);
         
         baseDirArray.append("");
         if (! initialAppDataDir.empty()) {
             baseDirArray.append(initialAppDataDir);
         }
 
-        const char* g3dPath = getenv("G3DDATA");
+#       ifdef G3D_WIN32
+        if (g3dPath == NULL) {
+            // If running the demos under visual studio from the G3D.sln file,
+            // this will locate the data directory.
+            const char* paths[] = {"../data-files/", "../../data-files/", "../../../data-files/", NULL};
+            for (int i = 0; paths[i]; ++i) {
+                if (FileSystem::exists(pathConcat(paths[i], "G3D-DATA-README.TXT"))) {
+                    g3dPath = paths[i];
+                    break;
+                }
+            }
+        }
+#       endif
 
         if (g3dPath && (initialAppDataDir != g3dPath)) {
             baseDirArray.append(g3dPath);
@@ -428,11 +407,11 @@ std::string System::findDataFile
             {"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)) {
+            if ((d == "") || FileSystem::exists(d)) {
                 directoryArray.append(d);
                 for (int i = 0; ! subdirs[i].empty(); ++i) {
                     const std::string& p = pathConcat(d, subdirs[i]);
-                    if (fileExists(p)) {
+                    if (FileSystem::exists(p)) {
                         directoryArray.append(p);
                     }
                 }
@@ -444,7 +423,7 @@ std::string System::findDataFile
 
     for (int i = 0; i < directoryArray.size(); ++i) {
         const std::string& p = pathConcat(directoryArray[i], full);
-        if (fileExists(p)) {
+        if (FileSystem::exists(p)) {
             lastFound.set(full, p);
             return p;
         }
@@ -454,9 +433,29 @@ std::string System::findDataFile
         // Generate an error message
         std::string locations;
         for (int i = 0; i < directoryArray.size(); ++i) {
-            locations += pathConcat(directoryArray[i], full) + "\n";
+            locations += "\'" + pathConcat(directoryArray[i], full) + "'\n";
+        }
+
+        std::string msg = "Could not find '" + full + "'.\n\n";
+        msg += "cwd = \'" + FileSystem::currentDirectory() + "\'\n";
+        if (g3dPath) {
+            msg += "G3DDATA = ";
+            if (! FileSystem::exists(g3dPath)) {
+                msg += "(illegal path!) ";
+            }
+            msg += std::string(g3dPath) + "\'\n";
+        } else {
+            msg += "(G3DDATA environment variable is undefined)\n";
+        }
+        msg += "GApp::Settings.dataDir = ";
+        if (! FileSystem::exists(initialAppDataDir)) {
+            msg += "(illegal path!) ";
         }
-        alwaysAssertM(false, "Could not find '" + full + "' in:\n" + locations);
+        msg += std::string(initialAppDataDir) + "\'\n";
+
+        msg += "\nLocations searched:\n" + locations;
+
+        alwaysAssertM(false, msg);
     }
 
     // Not found
@@ -474,19 +473,23 @@ std::string demoFindData(bool errorIfNotFound) {
     if (g3dPath) {
         return g3dPath;
 #   ifdef G3D_WIN32
-    } else if (fileExists("../data")) {
+    } else if (FileSystem::exists("../data")) {
         // G3D install on Windows
         return "../data";
-    } else if (fileExists("../data-files")) {
+    } else if (FileSystem::exists("../data-files")) {
         // G3D source on Windows
         return "../data-files";
+    } else if (FileSystem::exists("c:/libraries/G3D/data")) {
+        return "c:/libraries/G3D/data";
 #   else
-    } else if (fileExists("../../../../data")) {
+    } else if (FileSystem::exists("../../../../data")) {
         // G3D install on Unix
         return "../../../../data";
-    } else if (fileExists("../../../../data-files")) {
+    } else if (FileSystem::exists("../../../../data-files")) {
         // G3D source on Unix
         return "../../../../data-files";
+    } else if (FileSystem::exists("/usr/local/G3D/data")) {
+        return "/usr/local/G3D/data";
 #   endif
     } else {
         return "";
@@ -560,7 +563,7 @@ void System::getStandardProcessorExtensions() {
 #endif
 }
 
-#if defined(G3D_WIN32) && !defined(G3D_64BIT)
+#if defined(G3D_WIN32)
     #pragma message("Port System::memcpy SIMD to all platforms")
 /** Michael Herf's fast memcpy */
 void memcpyMMX(void* dst, const void* src, int nbytes) {
@@ -611,7 +614,7 @@ void memcpyMMX(void* dst, const void* src, int nbytes) {
 #endif
 
 void System::memcpy(void* dst, const void* src, size_t numBytes) {
-#if defined(G3D_WIN32) && !defined(G3D_64BIT)
+#if defined(G3D_WIN32)
     memcpyMMX(dst, src, numBytes);
 #else
     ::memcpy(dst, src, numBytes);
@@ -621,7 +624,7 @@ void System::memcpy(void* dst, const void* src, size_t numBytes) {
 
 /** Michael Herf's fastest memset. n32 must be filled with the same
     character repeated. */
-#if defined(G3D_WIN32) && !defined(G3D_64BIT)
+#if defined(G3D_WIN32)
     #pragma message("Port System::memfill SIMD to all platforms")
 
 // On x86 processors, use MMX
@@ -660,7 +663,7 @@ void memfill(void *dst, int n32, unsigned long i) {
 
 
 void System::memset(void* dst, uint8 value, size_t numBytes) {
-#if defined(G3D_WIN32) && !defined(G3D_64BIT)
+#if defined(G3D_WIN32)
     uint32 v = value;
     v = v + (v << 8) + (v << 16) + (v << 24); 
     G3D::memfill(dst, v, numBytes);
@@ -916,9 +919,12 @@ RealTime System::time() {
 
 ////////////////////////////////////////////////////////////////
 
-#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 *))
+
+#define REALPTR_TO_USERPTR(x)   ((uint8*)(x) + sizeof(uint32))
+#define USERPTR_TO_REALPTR(x)   ((uint8*)(x) - sizeof(uint32))
+#define USERSIZE_TO_REALSIZE(x)       ((x) + sizeof(uint32))
+#define REALSIZE_FROM_USERPTR(u) (*(uint32*)USERPTR_TO_REALPTR(ptr) + sizeof(uint32))
+#define USERSIZE_FROM_USERPTR(u) (*(uint32*)USERPTR_TO_REALPTR(ptr))
 
 class BufferPool {
 public:
@@ -943,13 +949,19 @@ class BufferPool {
 
 private:
 
+    /** Pointer given to the program.  Unless in the tiny heap, the user size of the block is stored right in front of the pointer as a uint32.*/
+    typedef void* UserPtr;
+
+    /** Actual block allocated on the heap */
+    typedef void* RealPtr;
+
     class MemBlock {
     public:
-        void*           ptr;
-        size_t          bytes;
+        UserPtr     ptr;
+        size_t      bytes;
 
         inline MemBlock() : ptr(NULL), bytes(0) {}
-        inline MemBlock(void* p, size_t b) : ptr(p), bytes(b) {}
+        inline MemBlock(UserPtr p, size_t b) : ptr(p), bytes(b) {}
     };
 
     MemBlock smallPool[maxSmallBuffers];
@@ -1006,13 +1018,13 @@ class BufferPool {
     /** 
      Malloc out of the tiny heap. Returns NULL if allocation failed.
      */
-    inline void* tinyMalloc(size_t bytes) {
+    inline UserPtr 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;
+        UserPtr ptr = NULL;
 
         if (tinyPoolSize > 0) {
             --tinyPoolSize;
@@ -1036,20 +1048,20 @@ class BufferPool {
     }
 
     /** Returns true if this is a pointer into the tiny heap. */
-    bool inTinyHeap(void* ptr) {
+    bool inTinyHeap(UserPtr ptr) {
         return 
             (ptr >= tinyHeap) && 
             (ptr < (uint8*)tinyHeap + maxTinyBuffers * tinyBufferSize);
     }
 
-    void tinyFree(void* ptr) {
+    void tinyFree(UserPtr 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];
+                UserPtr prevOnHeap = tinyPool[tinyPoolSize - 1];
                 assert(prevOnHeap != ptr); 
 //                    "System::malloc heap corruption detected: "
 //                    "the last two pointers on the freelist are identical (during tinyFree).");
@@ -1066,7 +1078,8 @@ class BufferPool {
 
     void flushPool(MemBlock* pool, int& poolSize) {
         for (int i = 0; i < poolSize; ++i) {
-            ::free(pool[i].ptr);
+            bytesAllocated -= USERSIZE_TO_REALSIZE(pool[i].bytes);
+            ::free(USERPTR_TO_REALPTR(pool[i].ptr));
             pool[i].ptr = NULL;
             pool[i].bytes = 0;
         }
@@ -1074,24 +1087,23 @@ class BufferPool {
     }
 
 
-    /**  Allocate out of a specific pool->  Return NULL if no suitable 
-         memory was found. 
-    
-         */
-    void* malloc(MemBlock* pool, int& poolSize, size_t bytes) {
+    /** Allocate out of a specific pool.  Return NULL if no suitable 
+        memory was found. */
+    UserPtr 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->
+        // 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->
+                // We found a suitable entry in the pool.
 
                 // No need to offset the pointer; it is already offset
-                void* ptr = pool[i].ptr;
+                UserPtr ptr = pool[i].ptr;
 
-                // Remove this element from the pool
+                // Remove this element from the pool, replacing it with
+                // the one from the end (same as Array::fastRemove)
                 --poolSize;
                 pool[i] = pool[poolSize];
 
@@ -1155,6 +1167,8 @@ class BufferPool {
 
     ~BufferPool() {
         ::free(tinyHeap);
+        flushPool(smallPool, smallPoolSize);
+        flushPool(medPool, medPoolSize);
 #if 0 //-------------------------------- old mutex
 #       ifdef G3D_WIN32
             DeleteCriticalSection(&mutex);
@@ -1165,7 +1179,7 @@ class BufferPool {
     }
 
     
-    void* realloc(void* ptr, size_t bytes) {
+    UserPtr realloc(UserPtr ptr, size_t bytes) {
         if (ptr == NULL) {
             return malloc(bytes);
         }
@@ -1177,7 +1191,7 @@ class BufferPool {
             } else {
                 // Free the old pointer and malloc
                 
-                void* newPtr = malloc(bytes);
+                UserPtr newPtr = malloc(bytes);
                 System::memcpy(newPtr, ptr, tinyBufferSize);
                 tinyFree(ptr);
                 return newPtr;
@@ -1187,28 +1201,28 @@ class BufferPool {
             // In one of our heaps.
 
             // See how big the block really was
-            size_t realSize = *(uint32*)USERPTR_TO_REALPTR(ptr);
-            if (bytes <= realSize) {
+            size_t userSize = USERSIZE_FROM_USERPTR(ptr);
+            if (bytes <= userSize) {
                 // The old block was big enough.
                 return ptr;
             }
 
-            // Need to reallocate
-            void* newPtr = malloc(bytes);
-            System::memcpy(newPtr, ptr, realSize);
+            // Need to reallocate and move
+            UserPtr newPtr = malloc(bytes);
+            System::memcpy(newPtr, ptr, userSize);
             free(ptr);
             return newPtr;
         }
     }
 
 
-    void* malloc(size_t bytes) {
+    UserPtr malloc(size_t bytes) {
         lock();
         ++totalMallocs;
 
         if (bytes <= tinyBufferSize) {
 
-            void* ptr = tinyMalloc(bytes);
+            UserPtr ptr = tinyMalloc(bytes);
 
             if (ptr) {
                 ++mallocsFromTinyPool;
@@ -1222,7 +1236,7 @@ class BufferPool {
         // through to a small buffer
         if (bytes <= smallBufferSize) {
             
-            void* ptr = malloc(smallPool, smallPoolSize, bytes);
+            UserPtr ptr = malloc(smallPool, smallPoolSize, bytes);
 
             if (ptr) {
                 ++mallocsFromSmallPool;
@@ -1235,7 +1249,7 @@ class BufferPool {
             // through into a medium allocation because that would
             // waste the medium buffer's resources.
 
-            void* ptr = malloc(medPool, medPoolSize, bytes);
+            UserPtr ptr = malloc(medPool, medPoolSize, bytes);
 
             if (ptr) {
                 ++mallocsFromMedPool;
@@ -1245,37 +1259,37 @@ class BufferPool {
             }
         }
 
-        bytesAllocated += REALBLOCK_SIZE(bytes);
+        bytesAllocated += USERSIZE_TO_REALSIZE(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));
+        RealPtr ptr = ::malloc(USERSIZE_TO_REALSIZE(bytes));
 
         if (ptr == NULL) {
             // Flush memory pools to try and recover space
             flushPool(smallPool, smallPoolSize);
             flushPool(medPool, medPoolSize);
-            ptr = ::malloc(REALBLOCK_SIZE(bytes));
+            ptr = ::malloc(USERSIZE_TO_REALSIZE(bytes));
         }
 
         if (ptr == NULL) {
             if ((System::outOfMemoryCallback() != NULL) &&
-                (System::outOfMemoryCallback()(REALBLOCK_SIZE(bytes), true) == true)) {
+                (System::outOfMemoryCallback()(USERSIZE_TO_REALSIZE(bytes), true) == true)) {
                 // Re-attempt the malloc
-                ptr = ::malloc(REALBLOCK_SIZE(bytes));
+                ptr = ::malloc(USERSIZE_TO_REALSIZE(bytes));
             }
         }
 
         if (ptr == NULL) {
             if (System::outOfMemoryCallback() != NULL) {
                 // Notify the application
-                System::outOfMemoryCallback()(REALBLOCK_SIZE(bytes), false);
+                System::outOfMemoryCallback()(USERSIZE_TO_REALSIZE(bytes), false);
             }
 #           ifdef G3D_DEBUG
-            debugPrintf("::malloc(%d) returned NULL\n", (int)REALBLOCK_SIZE(bytes));
+            debugPrintf("::malloc(%d) returned NULL\n", (int)USERSIZE_TO_REALSIZE(bytes));
 #           endif
             debugAssertM(ptr != NULL, 
                          "::malloc returned NULL. Either the "
@@ -1290,7 +1304,7 @@ class BufferPool {
     }
 
 
-    void free(void* ptr) {
+    void free(UserPtr ptr) {
         if (ptr == NULL) {
             // Free does nothing on null pointers
             return;
@@ -1305,7 +1319,7 @@ class BufferPool {
             return;
         }
 
-        uint32 bytes = *(uint32*)USERPTR_TO_REALPTR(ptr);
+        uint32 bytes = USERSIZE_FROM_USERPTR(ptr);
 
         lock();
         if (bytes <= smallBufferSize) {
@@ -1323,7 +1337,7 @@ class BufferPool {
                 return;
             }
         }
-        bytesAllocated -= REALBLOCK_SIZE(bytes);
+        bytesAllocated -= USERSIZE_TO_REALSIZE(bytes);
         unlock();
 
         // Free; the buffer pools are full or this is too big to store.
@@ -1677,7 +1691,6 @@ std::string System::currentDateString() {
 
 // 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;
 
@@ -1695,14 +1708,6 @@ void System::cpuid(CPUIDFunction func, uint32& areg, uint32& breg, uint32& creg,
     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)
diff --git a/dep/src/g3dlite/TextInput.cpp b/dep/src/g3dlite/TextInput.cpp
index 7276d8c66b2..354d0de13c0 100644
--- a/dep/src/g3dlite/TextInput.cpp
+++ b/dep/src/g3dlite/TextInput.cpp
@@ -6,7 +6,7 @@
  @cite Based on a lexer written by Aaron Orenstein. 
  
  @created 2001-11-27
- @edited  2008-07-14
+ @edited  2010-07-03
  */
 
 #include "G3D/fileutils.h"
@@ -33,36 +33,45 @@ Token TextInput::readSignificant() {
 
 double Token::number() const {
     if (_type == NUMBER) {
-        std::string s = toLower(_string);
-        if (s == "-1.#ind00") {
-            return nan();
-        }
+        return TextInput::parseNumber(_string);
+    } else {
+        return 0.0;
+    }
+}
 
-        if (s == "1.#inf00") {
-            return inf();
-        }
 
-        if (s == "-1.#inf00") {
-            return -inf();
-        }
+bool TextInput::parseBoolean(const std::string& _string) {
+     return toLower(_string) == "true";
+}
 
-        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;
+double TextInput::parseNumber(const std::string& _string) {
+    std::string s = toLower(_string);
+    if (s == "-1.#ind00" || s == "nan") {
+        return nan();
+    }
+    
+    if (s == "1.#inf00" || s == "inf" || s == "+inf") {
+        return inf();
+    }
+    
+    if (s == "-1.#inf00" || s == "-inf") {
+        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 {
-        return 0.0;
+        sscanf(_string.c_str(), "%lg", &n);
     }
-}
 
+    return n;
+}
 
 TextInput::Settings::Settings () :
     cppBlockComments(true),
@@ -78,7 +87,8 @@ TextInput::Settings::Settings () :
     singleQuoteCharacter('\''),
     sourceFileName(),
     startingLineNumberOffset(0),
-    msvcSpecials(true),
+    msvcFloatSpecials(true),
+    simpleFloatSpecials(true),
     proofSymbols(false),
     caseSensitive(true)
 { 
@@ -117,6 +127,41 @@ Token TextInput::read() {
     }
 }
 
+
+
+std::string TextInput::readUntilNewlineAsString() {
+/*
+    // Reset the read position back to the start of that token
+    currentCharOffset = t.bytePosition();
+    lineNumber = t.line();
+    charNumber = t.character();
+    stack.clear();
+
+    if (currentCharOffset == buffer.size()) {
+        // End of file
+        return "";
+    }
+    */
+    std::string s;
+
+    // Read until newline or eof
+    char c = '\0';
+    do {
+        c = buffer[currentCharOffset];
+        if (c == '\r' || c == '\n') {
+            // Done
+            break;
+        } else {
+            s += c;
+            ++currentCharOffset;
+            ++charNumber;
+        }
+    } while (currentCharOffset < buffer.size());
+
+    return s;    
+}
+
+
 static void toUpper(Set& set) {
     Array symbols;
     set.getMembers(symbols);
@@ -198,6 +243,7 @@ int TextInput::peekInputChar(int distance) {
 Token TextInput::nextToken() {
     Token t;
 
+    t._bytePosition = currentCharOffset;
     t._line         = lineNumber;
     t._character    = charNumber;
     t._type         = Token::END;
@@ -215,21 +261,24 @@ Token TextInput::nextToken() {
         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;
-            }
+        while (isWhiteSpace(c)) {
+            if (options.generateNewlineTokens && isNewline(c)) {
+                t._type         = Token::NEWLINE;
+                t._extendedType = Token::NEWLINE_TYPE;
+                t._bytePosition = currentCharOffset;
+                t._line         = lineNumber;
+                t._character    = charNumber;
+                t._string       = c;
+
+                int c2 = peekInputChar(1);
+                if (c == '\r' && c2 == '\n') {
+                    t._string  += c2;
+                }
 
-            eatInputChar();
-            return t;
-        } else {
-            // Consume whitespace
-            while (isWhiteSpace(c)) {
+                eatInputChar();
+                return t;
+            } else {
+                // Consume the single whitespace
                 c = eatAndPeekInputChar();
             }
         }
@@ -237,6 +286,7 @@ Token TextInput::nextToken() {
         // update line and character number to include discarded whitespace
         t._line         = lineNumber;
         t._character    = charNumber;
+        t._bytePosition = currentCharOffset;
 
         int c2 = peekInputChar(1);
 
@@ -293,13 +343,16 @@ Token TextInput::nextToken() {
             eatInputChar();
             eatInputChar();
 
+            // c is the next character we'll read, c2 is the one after *that*
             c = peekInputChar();
             c2 = peekInputChar(1);
             while (! ((c == '*') && (c2 == '/')) && (c != EOF)) {
                 commentString += c;
 
+                // Eat input char may consume more than one character if there is a newline
                 eatInputChar();
-                c = c2;
+
+                c = peekInputChar();
                 c2 = peekInputChar(1);
             }
             eatInputChar();      // eat closing '*'
@@ -324,6 +377,7 @@ Token TextInput::nextToken() {
 
     t._line      = lineNumber;
     t._character = charNumber;
+    t._bytePosition = currentCharOffset;
 
     // handle EOF
     if (c == EOF) {
@@ -380,15 +434,29 @@ Token TextInput::nextToken() {
             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.
+        if (options.signedNumbers) {
+            if (isDigit(c) || (c == '.' && isDigit(peekInputChar(1)))) {
+                // Negative number.  'c' is still the first digit, and is
+                // the next input char.
 
-            goto numLabel;
+                goto numLabel;
+            } else {
+                char terminal = peekInputChar(3);
+                if (options.simpleFloatSpecials && (c == 'i') && (peekInputChar(1) == 'n') && (peekInputChar(2) == 'f') && 
+                    ! isLetter(terminal) && (terminal != '_')) {
+                    // negative infinity
+                    t._type = Token::NUMBER;
+                    t._extendedType = Token::FLOATING_POINT_TYPE;
+                    t._string = "-inf";
+                    eatInputChar(); // i
+                    eatInputChar(); // n
+                    eatInputChar(); // f
+                    return t;
+                }
+            }
         }
 
+
         // plain -
         return t;
 
@@ -403,13 +471,26 @@ Token TextInput::nextToken() {
             return t;
         }
 
-        if (options.signedNumbers
-            && (isDigit(c) || (c == '.' && isDigit(peekInputChar(1))))) {
+        if (options.signedNumbers) {
+            if (isDigit(c) || (c == '.' && isDigit(peekInputChar(1)))) {
+                // Positive number.  'c' is still the first digit, and is
+                // the next input char.
 
-            // Positive number.  'c' is still the first digit, and is
-            // the next input char.
-
-            goto numLabel;
+                goto numLabel;
+            } else {
+                char terminal = peekInputChar(3);
+                if (options.simpleFloatSpecials && (c == 'i') && (peekInputChar(1) == 'n') && (peekInputChar(2) == 'f') && 
+                    ! isLetter(terminal) && (terminal != '_')) {
+                    // positive infinity
+                    t._type = Token::NUMBER;
+                    t._extendedType = Token::FLOATING_POINT_TYPE;
+                    t._string = "+inf";
+                    eatInputChar(); // i
+                    eatInputChar(); // n
+                    eatInputChar(); // f
+                    return t;
+                }
+            }
         }
 
         return t;
@@ -596,7 +677,7 @@ Token TextInput::nextToken() {
                 c = eatAndPeekInputChar();
 
                 // Floating point specials (msvc format only)
-                if (options.msvcSpecials && (c == '#')) {
+                if (options.msvcFloatSpecials && (c == '#')) {
                     isSpecial = true;
                     // We are reading a floating point special value
                     // of the form -1.#IND00, -1.#INF00, or 1.#INF00
@@ -607,8 +688,7 @@ Token TextInput::nextToken() {
                     }
                     if (test != 'I') {
                         throw BadMSVCSpecial
-                            (
-                             "Incorrect floating-point special (inf or nan) "
+                            ("Incorrect floating-point special (inf or nan) "
                              "format.",
                             t.line(), charNumber);
                     }
@@ -714,6 +794,10 @@ Token TextInput::nextToken() {
             }
         }
 
+        if (options.simpleFloatSpecials && ((t._string == "nan") || (t._string == "inf"))) {
+            t._type = Token::NUMBER;
+            t._extendedType = Token::FLOATING_POINT_TYPE;
+        }
         return t;
 
     } else if (c == '\"') {
@@ -1052,6 +1136,8 @@ static const char* tokenTypeToString(Token::Type t) {
         return "Token::NUMBER";
     case Token::END:
         return "Token::END";
+    case Token::NEWLINE:
+        return "Token::NEWLINE";
     default:
         debugAssertM(false, "Fell through switch");
         return "?";
diff --git a/dep/src/g3dlite/TextOutput.cpp b/dep/src/g3dlite/TextOutput.cpp
index 11347252eba..3257f6fb9ce 100644
--- a/dep/src/g3dlite/TextOutput.cpp
+++ b/dep/src/g3dlite/TextOutput.cpp
@@ -3,15 +3,16 @@
 
   @maintainer Morgan McGuire, http://graphics.cs.williams.edu
   @created 2004-06-21
-  @edited  2006-08-14
+  @edited  2010-03-14
 
-  Copyright 2000-2006, Morgan McGuire.
+  Copyright 2000-2010, Morgan McGuire.
   All rights reserved.
  */
 
 #include "G3D/TextOutput.h"
 #include "G3D/Log.h"
 #include "G3D/fileutils.h"
+#include "G3D/FileSystem.h"
 
 namespace G3D {
 
@@ -392,17 +393,17 @@ void TextOutput::vprintf(const char* formatString, va_list argPtr) {
 
 void TextOutput::commit(bool flush) {
     std::string p = filenamePath(filename);
-    if (! fileExists(p, false)) {
-        createDirectory(p);
+    if (! FileSystem::exists(p, false)) {
+        FileSystem::createDirectory(p);
     }
 
-    FILE* f = fopen(filename.c_str(), "wb");
+    FILE* f = FileSystem::fopen(filename.c_str(), "wb");
     debugAssertM(f, "Could not open \"" + filename + "\"");
     fwrite(data.getCArray(), 1, data.size(), f);
     if (flush) {
         fflush(f);
     }
-    fclose(f);
+    FileSystem::fclose(f);
 }
 
 
diff --git a/dep/src/g3dlite/Vector3.cpp b/dep/src/g3dlite/Vector3.cpp
index a53fa8269b7..55343e96ece 100644
--- a/dep/src/g3dlite/Vector3.cpp
+++ b/dep/src/g3dlite/Vector3.cpp
@@ -25,6 +25,7 @@
 #include "G3D/Vector2.h"
 #include "G3D/Color3.h"
 #include "G3D/Vector4int8.h"
+#include "G3D/Vector4.h"
 #include "G3D/Vector3int32.h"
 #include "G3D/Any.h"
  
@@ -104,11 +105,7 @@ Vector3::Axis Vector3::primaryAxis() const {
 
 
 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);
+    return Vector4(*this, 0.0f).hashCode();
 }
 
 std::ostream& operator<<(std::ostream& os, const Vector3& v) {
diff --git a/dep/src/g3dlite/Vector4.cpp b/dep/src/g3dlite/Vector4.cpp
index f6abc1a6e0c..b5f23d69950 100644
--- a/dep/src/g3dlite/Vector4.cpp
+++ b/dep/src/g3dlite/Vector4.cpp
@@ -4,7 +4,7 @@
  @maintainer Morgan McGuire, http://graphics.cs.williams.edu
   
  @created 2001-07-09
- @edited  2009-11-29
+ @edited  2010-07-05
  */
 
 #include 
@@ -69,12 +69,7 @@ const Vector4& Vector4::nan() {
 
 
 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);
+    return HashTrait::hashCode(*((uint128*)this));
 }
 
 
diff --git a/dep/src/g3dlite/Welder.cpp b/dep/src/g3dlite/Welder.cpp
index b4f752f38bd..2db47722e64 100644
--- a/dep/src/g3dlite/Welder.cpp
+++ b/dep/src/g3dlite/Welder.cpp
@@ -74,7 +74,7 @@ namespace G3D { namespace _internal {
 
 class WeldHelper {
 private:
-    /** Used by getIndex and updateTriLists */
+    /** Used by getIndex and updateTriLists. Deallocating this is slow. */
     PointHashGrid     weldGrid;
 
     Array*         outputVertexArray;
@@ -157,23 +157,25 @@ class WeldHelper {
         int numTriLists = indexArrayArray.size();
         int u = 0;
         for (int t = 0; t < numTriLists; ++t) {
-            Array& triList = *(indexArrayArray[t]);
-
-            // For all vertices in this list
-            for (int v = 0; v < triList.size(); ++v) {
-                // This vertex mapped to u in the flatVertexArray
-                triList[v] = getIndex(vertexArray[u], normalArray[u], texCoordArray[u]);
-
-                /*
-#           ifdef G3D_DEBUG
-            {
-                int i = triList[v];
-                Vector3 N = normalArray[i];
-                debugAssertM(N.length() > 0.9f, "Produced non-unit normal");
-            }
-#           endif
-            */
-                ++u;
+            if (indexArrayArray[t] != NULL) {
+                Array& triList = *(indexArrayArray[t]);
+
+                // For all vertices in this list
+                for (int v = 0; v < triList.size(); ++v) {
+                    // This vertex mapped to u in the flatVertexArray
+                    triList[v] = getIndex(vertexArray[u], normalArray[u], texCoordArray[u]);
+
+                    /*
+    #           ifdef G3D_DEBUG
+                {
+                    int i = triList[v];
+                    Vector3 N = normalArray[i];
+                    debugAssertM(N.length() > 0.9f, "Produced non-unit normal");
+                }
+    #           endif
+                */
+                    ++u;
+                }
             }
         }
     }
@@ -190,11 +192,13 @@ class WeldHelper {
 
         int numTriLists = indexArrayArray.size();
         for (int t = 0; t < numTriLists; ++t) {
-            const Array& triList = *(indexArrayArray[t]);
-            for (int v = 0; v < triList.size(); ++v) {
-                int i = triList[v];
-                unrolledVertexArray.append(vertexArray[i]);
-                unrolledTexCoordArray.append(texCoordArray[i]);
+            if (indexArrayArray[t] != NULL) {
+                const Array& triList = *(indexArrayArray[t]);
+                for (int v = 0; v < triList.size(); ++v) {
+                    int i = triList[v];
+                    unrolledVertexArray.append(vertexArray[i]);
+                    unrolledTexCoordArray.append(texCoordArray[i]);
+                }
             }
         }
     }
@@ -214,8 +218,9 @@ class WeldHelper {
             const Vector3& e1 = vertexArray[v + 2] - vertexArray[v];
 
             // Note that the length may be zero in the case of sliver polygons, e.g.,
-            // those correcting a T-junction.
-            const Vector3& n  = e0.cross(e1).directionOrZero(); 
+            // those correcting a T-junction.  Scale up by 256 to avoid underflow when
+            // multiplying very small edges
+            const Vector3& n  = (e0.cross(e1 * 256.0f)).directionOrZero();
 
             // Append the normal once per vertex.
             faceNormalArray.append(n, n, n);
@@ -230,15 +235,16 @@ class WeldHelper {
         const Array& vertexArray, 
         const Array& normalArray, 
         Array&       smoothNormalArray) {
-
-        // Create an area memory manager for fast deallocation
-        MemoryManager::Ref mm = AreaMemoryManager::create(iRound(sizeof(VN) * normalArray.size() * 1.5));
         
         if (normalSmoothingAngle <= 0) {
             smoothNormalArray = normalArray;
             return;
         }
 
+        
+        // Create an area memory manager for fast deallocation
+        MemoryManager::Ref mm = AreaMemoryManager::create(iRound(sizeof(VN) * normalArray.size() * 1.5));
+
         const float cosThresholdAngle = (float)cos(normalSmoothingAngle);
 
         debugAssert(vertexArray.size() == normalArray.size());
@@ -250,6 +256,7 @@ class WeldHelper {
             grid.insert(VN(vertexArray[v], normalArray[v]));
         }
 
+        // TODO: this step could be done on multiple threads
         for (int v = 0; v < normalArray.size(); ++v) {            
             // Compute the sum of all nearby normals within the cutoff angle.
             // Search within the vertexWeldRadius, since those are the vertices
@@ -265,8 +272,8 @@ class WeldHelper {
                 const float cosAngle = N.dot(original);
 
                 if (cosAngle > cosThresholdAngle) {
-                    // This normal is close enough to consider
-                    sum += N;
+                    // This normal is close enough to consider.  Avoid underflow by scaling up
+                    sum += (N * 256.0f);
                 }
                 ++it;
             }
@@ -366,8 +373,9 @@ class WeldHelper {
     }
 
     WeldHelper(float vertRadius) :
-        weldGrid(vertRadius),
-        vertexWeldRadius(vertRadius) {}
+        weldGrid(vertRadius, AreaMemoryManager::create()),
+        vertexWeldRadius(vertRadius) {
+    }
 
 };
 } // Internal
@@ -382,6 +390,7 @@ void Welder::weld(
     _internal::WeldHelper(settings.vertexWeldRadius).process(
         vertexArray, texCoordArray, normalArray, indexArrayArray, 
         settings.normalSmoothingAngle, settings.textureWeldRadius, settings.normalWeldRadius);
+        
 }
 
 
diff --git a/dep/src/g3dlite/XML.cpp b/dep/src/g3dlite/XML.cpp
new file mode 100644
index 00000000000..51f1a549ba0
--- /dev/null
+++ b/dep/src/g3dlite/XML.cpp
@@ -0,0 +1,216 @@
+/**
+ \file XML.h
+  
+ \author Morgan McGuire
+ \maintainer Morgan McGuire
+  
+ \created 2010-02-11
+ \edited  2010-02-24
+
+ Copyright 2000-2010, Morgan McGuire.
+ All rights reserved.
+ */
+
+#include "G3D/XML.h"
+#include "G3D/fileutils.h"
+#include "G3D/TextInput.h"
+#include "G3D/TextOutput.h"
+#include "G3D/stringutils.h"
+
+namespace G3D {
+
+XML::XML(TextInput& t) : m_type(VALUE) {
+    deserialize(t);
+}
+
+double XML::number() const {
+    return TextInput::parseNumber(m_value);
+}
+
+
+bool XML::boolean() const {
+    return TextInput::parseBoolean(m_value);
+}
+
+
+void XML::load(const std::string& filename) {
+    TextInput::Settings s;
+    s.cppBlockComments = false;
+    s.cppLineComments = false;
+    s.proofSymbols = false;
+
+    TextInput t(filename, s);
+    deserialize(t);
+}
+
+
+void XML::save(const std::string& filename) const {
+    std::string s;
+    unparse(s);
+    writeWholeFile(filename, s);
+}
+
+    
+void XML::unparse(std::string &s) const {
+    TextOutput::Settings set;
+    set.wordWrap = TextOutput::Settings::WRAP_WITHOUT_BREAKING;
+    TextOutput t(set);
+
+    serialize(t);
+
+    t.commitString(s);
+}
+
+
+void XML::serialize(TextOutput& t) const {
+    if (m_type == VALUE) {
+        // Raw string; no quotes
+        t.writeSymbol(m_value);
+    } else {
+        t.printf("<%s", m_name.c_str());
+        for (AttributeTable::Iterator it = m_attribute.begin(); it.hasMore(); ++it) {
+            t.printf(" %s=\"%s\"", it->key.c_str(), it->value.m_value.c_str());
+        }
+        t.printf(">");
+        t.writeNewline();
+        t.pushIndent();
+        for (int i = 0; i < m_child.size(); ++i) {
+            m_child[i].serialize(t);
+            if (m_child[i].m_type == VALUE) {
+                // Only tags know to append a newline
+                t.writeNewline();
+            }
+        }
+        t.popIndent();
+        t.printf("", m_name.c_str());
+        t.writeNewline();
+    }
+}
+
+
+void XML::parse(const std::string& s) {
+    TextInput t(TextInput::FROM_STRING, s);
+    deserialize(t);
+}
+
+
+/** True if the next token begins the close tag */
+static bool atClose(TextInput& t, const std::string name) {
+    if ((t.peek().type() == Token::SYMBOL) && (t.peek().string() == "<")) {
+        // Need to keep looking ahead
+        Token p0 = t.read();
+        if ((t.peek().type() == Token::SYMBOL) && (t.peek().string() == "/")) {
+            // Check the name on the close tag.  It *must* match if
+            // this is a well-formed document, but there might be a
+            // tag error.
+            Token p1 = t.read();
+            Token p2 = t.peek();
+            std::string s = p2.string();
+            debugAssertM(beginsWith(name, s), "Mismatched close tag");
+
+            // Put the tokens back
+            t.push(p1);
+            t.push(p0);
+            return true;
+        } else {
+            // Put the read token back
+            t.push(p0);
+            return false;
+        }
+    } else {
+        return false;
+    }
+}
+
+void XML::deserialize(TextInput& t) {
+ begin:
+    Token n = t.read();
+    m_attribute.clear();
+    m_child.clear();
+    m_name = "";
+    m_value = "";
+
+    if ((n.type() == Token::SYMBOL) && (n.string() == "<")) {
+        // Beginning a tag
+        
+        // Read name
+        n = t.read();
+        debugAssert(n.type() == Token::SYMBOL);
+        bool isComment = 
+            (n.string() == "!") && 
+            (t.peek().type() == Token::SYMBOL) &&
+            (t.peek().string() == "--");
+
+        // ignored tag:         or 
+        // comment tag:        
+
+        if ((n.string() == "?") || ((n.string() == "!") && ! isComment)) {
+            // Ignore this tag
+            while (t.hasMore() && ! ((n.type() == Token::SYMBOL) && (n.string() == ">"))) {
+                n = t.read();
+            }
+            goto begin;
+        } else if (isComment) {
+            // Ignore until "-->"
+            bool prevWasDash = false;
+            while (t.hasMore() && ! ((n.type() == Token::SYMBOL) && (n.string() == ">") && prevWasDash)) {
+                prevWasDash = (n.type() == Token::SYMBOL) && (n.string() == "--");
+                n = t.read();
+            }
+            goto begin;
+        }
+
+        // Keep reading until no colon
+        m_name += n.string();
+        n = t.read();
+        while ((n.type() == Token::SYMBOL) && (n.string() == ":")) {
+            //  tag with namespace: 
+            m_name += ":" + t.readSymbol();
+            n = t.read();
+        }
+        
+        // Read end of tag/close
+        bool done = false;
+        while (! done) {
+            debugAssert(n.type() == Token::SYMBOL);
+            if (n.string() == "/") {
+                // empty-element tag:  
+                // Consume the close tag
+                t.readSymbol(">");
+                done = true;
+
+            } else if (n.string() == ">") {
+                // End of open tag: read children until close tag
+                while (! atClose(t, m_name)) {
+                    m_child.next().deserialize(t);
+                }
+
+                // Read close tag (we wouldn't be here unless it parses correctly)
+                while (t.hasMore() && ! (t.readSymbol() == ">")) {}
+                
+                done = true;
+            } else {
+                // Attribute pair
+                std::string k = n.string();
+                t.readSymbol("=");
+                std::string v = t.read().string();
+                m_attribute.set(k, v);
+
+                // Advance to next
+                n = t.read();
+            }
+        }
+    } else {
+        // Beginning embedded content.  Read until the end of file or the next tag.
+        m_type = VALUE;
+        m_value += n.string();
+
+        n = t.peek();
+        while (t.hasMore() && ! ((n.type() == Token::SYMBOL) && (n.string() == "<"))) {
+            m_value += " " + t.read().string();
+            n = t.peek();
+        }
+    }
+}
+
+}
diff --git a/dep/src/g3dlite/constants.cpp b/dep/src/g3dlite/constants.cpp
index 52cad3cd90b..9ee3eb8736b 100644
--- a/dep/src/g3dlite/constants.cpp
+++ b/dep/src/g3dlite/constants.cpp
@@ -11,72 +11,6 @@
 
 namespace G3D {
 
-const std::string MirrorQuality::str[] = {"NONE", "STATIC_ENV", "DYNAMIC_PLANAR", "DYNAMIC_ENV", "BEST"};
-const MirrorQuality::Value MirrorQuality::enm[] = {MirrorQuality::NONE, MirrorQuality::STATIC_ENV, 
-    MirrorQuality::DYNAMIC_PLANAR, MirrorQuality::DYNAMIC_ENV, MirrorQuality::BEST};
 
-MirrorQuality::MirrorQuality(const class Any& any) {
-    *this = any;
-}
-
-
-MirrorQuality& MirrorQuality::operator=(const Any& any) {
-    const std::string& s = toUpper(any.string());
-
-    for (int i = 0; ! str[i].empty(); ++i) {
-        if (s == str[i]) {
-            value = enm[i];
-            return *this;
-        }
-    }
-
-    any.verify(false, "Unrecognized MirrorQuality constant");
-    return *this;
-}
-
-
-MirrorQuality::operator Any() const {
-    return toString();
-}
-
-
-const std::string& MirrorQuality::toString() const {
-    return str[value];
-}
-
-/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-const std::string RefractionQuality::str[] = {"NONE", "STATIC_ENV", "DYNAMIC_FLAT", "DYNAMIC_FLAT_MULTILAYER", "DYNAMIC_ENV", "BEST"};
-const RefractionQuality::Value RefractionQuality::enm[] = {RefractionQuality::NONE, RefractionQuality::STATIC_ENV, 
-    RefractionQuality::DYNAMIC_FLAT, RefractionQuality::DYNAMIC_FLAT_MULTILAYER, RefractionQuality::DYNAMIC_ENV, RefractionQuality::BEST};
-
-RefractionQuality::RefractionQuality(const class Any& any) {
-    *this = any;
-}
-
-
-RefractionQuality& RefractionQuality::operator=(const Any& any) {
-    const std::string& s = toUpper(any.string());
-
-    for (int i = 0; ! str[i].empty(); ++i) {
-        if (s == str[i]) {
-            value = enm[i];
-            return *this;
-        }
-    }
-
-    any.verify(false, "Unrecognized RefractionQuality constant");
-    return *this;
-}
-
-
-RefractionQuality::operator Any() const {
-    return toString();
-}
-
-
-const std::string& RefractionQuality::toString() const {
-    return str[value];
-}
 
 } // G3D
diff --git a/dep/src/g3dlite/debugAssert.cpp b/dep/src/g3dlite/debugAssert.cpp
index a87161b261f..d29600e8c73 100644
--- a/dep/src/g3dlite/debugAssert.cpp
+++ b/dep/src/g3dlite/debugAssert.cpp
@@ -37,11 +37,9 @@ 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
@@ -252,7 +250,6 @@ void _releaseInputGrab_() {
         ClipCursor(NULL);
         
     #elif defined(G3D_LINUX)
-#if SOMEONE_MADE_THIS_USEFUL
         if (x11Display != NULL) {
             XUngrabPointer(x11Display, CurrentTime);
             XUngrabKeyboard(x11Display, CurrentTime);
@@ -267,7 +264,6 @@ void _releaseInputGrab_() {
             XAllowEvents(x11Display, AsyncPointer, CurrentTime);
             XFlush(x11Display);
         }
-#endif
     #elif defined(G3D_OSX)
         // TODO: OS X
     #endif
diff --git a/dep/src/g3dlite/fileutils.cpp b/dep/src/g3dlite/fileutils.cpp
index 3f5eb579ba9..16f2a2b3c3b 100644
--- a/dep/src/g3dlite/fileutils.cpp
+++ b/dep/src/g3dlite/fileutils.cpp
@@ -17,12 +17,11 @@
 #include "G3D/stringutils.h"
 #include "G3D/Set.h"
 #include "G3D/g3dfnmatch.h"
+#include "G3D/FileSystem.h"
 
 #include 
 #include 
-#if _HAVE_ZIP
-    #include "zip.h"
-#endif
+#include "zip.h"
 
 #ifdef G3D_WIN32
    // Needed for _getcwd
@@ -104,17 +103,18 @@ std::string readWholeFile(
     std::string s;
 
     debugAssert(filename != "");
-    if (fileExists(filename, false)) {
+    debugAssertM(FileSystem::exists(filename), filename + " not found");
 
-        int64 length = fileLength(filename);
+    if (! FileSystem::inZipfile(filename)) {
+        int64 length = FileSystem::size(filename);
 
         char* buffer = (char*)System::alignedMalloc(length + 1, 16);
         debugAssert(buffer);
-        FILE* f = fopen(filename.c_str(), "rb");
+        FILE* f = FileSystem::fopen(filename.c_str(), "rb");
         debugAssert(f);
         int ret = fread(buffer, 1, length, f);
 	    debugAssert(ret == length);(void)ret;
-        fclose(f);
+        FileSystem::fclose(f);
 
         buffer[length] = '\0';    
         s = std::string(buffer);
@@ -134,8 +134,6 @@ std::string readWholeFile(
         buffer[length] = '\0';
         s = std::string(buffer);
         System::alignedFree(buffer);
-    } else {
-        debugAssertM(false, filename + " not found");
     }
 
     return s;
@@ -146,7 +144,7 @@ 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 );
         {
@@ -169,9 +167,6 @@ void zipRead(const std::string& file,
     } else {
         data = NULL;
     }
-#else
-    data = NULL;
-#endif
 }
 
 
@@ -185,7 +180,6 @@ int64 fileLength(const std::string& filename) {
     int result = _stat(filename.c_str(), &st);
     
     if (result == -1) {
-#if _HAVE_ZIP
 		std::string zip, contents;
 		if(zipfileExists(filename, zip, contents)){
 			int64 requiredMem;
@@ -196,6 +190,7 @@ int64 fileLength(const std::string& filename) {
                                 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 );
+				(void)success;
                                 debugAssertM(success == 0, zip + ": " + contents + ": zip stat failed.");
                                 requiredMem = info.size;
 			}
@@ -204,132 +199,11 @@ int64 fileLength(const std::string& filename) {
 		} 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,
@@ -342,11 +216,11 @@ void writeWholeFile(
     parseFilename(filename, root, pathArray, base, ext); 
 
     path = root + stringJoin(pathArray, '/');
-    if (! fileExists(path, false)) {
-        createDirectory(path);
+    if (! FileSystem::exists(path, false)) {
+        FileSystem::createDirectory(path);
     }
 
-    FILE* file = fopen(filename.c_str(), "wb");
+    FILE* file = FileSystem::fopen(filename.c_str(), "wb");
 
     debugAssert(file);
 
@@ -355,7 +229,8 @@ void writeWholeFile(
     if (flush) {
         fflush(file);
     }
-    fclose(file);
+
+    FileSystem::fclose(file);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -385,7 +260,7 @@ void createDirectory(
     }
 
     // If it already exists, do nothing
-    if (fileExists(d.substr(0, d.size() - 1)), false) {
+    if (FileSystem::exists(d.substr(0, d.size() - 1))) {
         return;
     }
 
@@ -405,129 +280,21 @@ void createDirectory(
     // Create any intermediate that doesn't exist
     for (int i = 0; i < path.size(); ++i) {
         p += "/" + path[i];
-        if (! fileExists(p, false)) {
+        if (! FileSystem::exists(p)) {
             // Windows only requires one argument to mkdir,
             // where as unix also requires the permissions.
 #           ifndef G3D_WIN32
                 mkdir(p.c_str(), 0777);
-#	    else
+#	        else
                 _mkdir(p.c_str());
-#	    endif
+#	        endif
         }
     }
 }
 
-///////////////////////////////////////////////////////////////////////////////
-
-class FileSystemCache {
-private:
-
-    Table > 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& 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& path, const int length){
@@ -561,12 +328,12 @@ static bool _zip_zipContains(const std::string& zipDir, const std::string& desir
 	}
 	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 path;
     std::string drive, base, ext, zipfile, infile;
     parseFilename(filename, drive, path, base, ext);
@@ -607,12 +374,12 @@ bool zipfileExists(const std::string& filename, std::string& outZipfile,
             return false;
         }
         
-        if (fileExists(zipfile, false)) {
+        if (FileSystem::exists(zipfile)) {
             // 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 (FileSystem::isZipfile(zipfile)){
                 
                 if (_zip_zipContains(zipfile, infile)){
                     outZipfile = zipfile;
@@ -628,7 +395,7 @@ bool zipfileExists(const std::string& filename, std::string& outZipfile,
         }
         
     }
-#endif
+    
     // not a valid directory structure ever, 
     // obviously no .zip was found within the path 
     return false;
@@ -641,7 +408,7 @@ std::string generateFilenameBase(const std::string& prefix, const std::string& s
 
     // Note "template" is a reserved word in C++
     std::string templat = prefix + System::currentDateString() + "_";
-    getFiles(templat + "*", exist);
+    FileSystem::getFiles(templat + "*", exist);
     
     // Remove extensions
     for (int i = 0; i < exist.size(); ++i) {
@@ -910,7 +677,7 @@ static void getFileOrDirListNormal
 #   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.
@@ -961,14 +728,13 @@ static void _zip_addEntry(const std::string& path,
         }
     }
 }
-#endif
+
 
 static void getFileOrDirListZip(const std::string& path,
                                 const std::string& prefix,
                                 Array& files,
                                 bool wantFiles,
                                 bool includePath){
-#if _HAVE_ZIP
     struct zip *z = zip_open( path.c_str(), ZIP_CHECKCONS, NULL );
 
     Set fileSet;
@@ -984,7 +750,6 @@ static void getFileOrDirListZip(const std::string& path,
     zip_close( z );
     
     fileSet.getMembers(files);
-#endif
 }
 
 
@@ -1004,8 +769,8 @@ static void determineFileOrDirList(
         path = path.substr(0, path.length() -1);
     }
     
-    if ((path == "") || fileExists(path, false)) {
-        if ((path != "") && isZipfile(path)) {
+    if ((path == "") || FileSystem::exists(path)) {
+        if ((path != "") && FileSystem::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");
diff --git a/dep/src/g3dlite/g3dfnmatch.cpp b/dep/src/g3dlite/g3dfnmatch.cpp
index 39ef7b31914..2d24c4126e6 100644
--- a/dep/src/g3dlite/g3dfnmatch.cpp
+++ b/dep/src/g3dlite/g3dfnmatch.cpp
@@ -1,40 +1,42 @@
-/*-
-* 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 $
-*/
+/* $Id: g3dfnmatch.cpp,v 1.3 2010/03/15 05:01:23 morgan3d Exp $ */
+
+/*	$OpenBSD: fnmatch.c,v 1.7 2000/03/23 19:13:51 millert Exp $	*/
+
+/*
+ * Copyright (c) 1989, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Guido van Rossum.
+ *
+ * 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.
+ */
 #include "G3D/g3dfnmatch.h"
 
 #ifdef G3D_WIN32
@@ -45,149 +47,166 @@
 
 namespace G3D {
 
-#define EOS '\0'
+#define	EOS	'\0'
 
-static const char *rangematch(const char *, char, int);
+#define	RANGE_MATCH	1
+#define	RANGE_NOMATCH	0
+#define	RANGE_ERROR	(-1)
 
-int g3dfnmatch(const char *pattern, const char *string, int flags)
+static int rangematch(const char *, char, int, char **);
+
+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 */
+	const char *stringstart;
+	char *newp;
+	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 (!g3dfnmatch(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 (*string == '.' && (flags & FNM_PERIOD) &&
+			    (string == stringstart ||
+			    ((flags & FNM_PATHNAME) && *(string - 1) == '/')))
+				return (FNM_NOMATCH);
+
+			switch (rangematch(pattern, *string, flags, &newp)) {
+			case RANGE_ERROR:
+				/* not a good range, treat as normal text */
+				goto normal;
+			case RANGE_MATCH:
+				pattern = newp;
+				break;
+			case RANGE_NOMATCH:
+				return (FNM_NOMATCH);
+			}
+			++string;
+			break;
+		case '\\':
+			if (!(flags & FNM_NOESCAPE)) {
+				if ((c = *pattern++) == EOS) {
+					c = '\\';
+					--pattern;
+				}
+			}
+			/* FALLTHROUGH */
+		default:
+		normal:
+			if (c != *string && !((flags & FNM_CASEFOLD) &&
+				 (tolower((unsigned char)c) ==
+				 tolower((unsigned char)*string))))
+				return (FNM_NOMATCH);
+			++string;
+			break;
+		}
+	/* NOTREACHED */
 }
 
-static const char *
-rangematch(const char *pattern, char test, int flags)
+static int
+rangematch(const char *pattern, char test, int flags, char **newp)
 {
-    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);
+	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);
+
+	/*
+	 * A right bracket shall lose its special meaning and represent
+	 * itself in a bracket expression if it occurs first in the list.
+	 * -- POSIX.2 2.8.3.2
+	 */
+	ok = 0;
+	c = *pattern++;
+	do {
+		if (c == '\\' && !(flags & FNM_NOESCAPE))
+			c = *pattern++;
+		if (c == EOS)
+			return (RANGE_ERROR);
+		if (c == '/' && (flags & FNM_PATHNAME))
+			return (RANGE_NOMATCH);
+		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 (RANGE_ERROR);
+			if (flags & FNM_CASEFOLD)
+				c2 = tolower((unsigned char)c2);
+			if (c <= test && test <= c2)
+				ok = 1;
+		} else if (c == test)
+			ok = 1;
+	} while ((c = *pattern++) != ']');
+
+	*newp = (char *)pattern;
+	return (ok == negate ? RANGE_NOMATCH : RANGE_MATCH);
 }
 
 }
diff --git a/dep/src/g3dlite/g3dmath.cpp b/dep/src/g3dlite/g3dmath.cpp
index ad85e9efb9b..84e8345bff4 100644
--- a/dep/src/g3dlite/g3dmath.cpp
+++ b/dep/src/g3dlite/g3dmath.cpp
@@ -11,6 +11,7 @@
 #include 
 #include 
 
+
 namespace G3D {
 
 float gaussRandom(float mean, float stdev) {
diff --git a/dep/src/g3dlite/license.html b/dep/src/g3dlite/license.html
deleted file mode 100644
index 11c33882248..00000000000
--- a/dep/src/g3dlite/license.html
+++ /dev/null
@@ -1,115 +0,0 @@
-
-
-
-
-	
-	G3D Innovation Engine: License
-	
-
-
-
-
- - - - - - - - - -
- - - - - -
- Support Forum       - Library Source       - SourceForge Page       - Web Page -
-
-
- - - Wiki Doc - - - Data - - - API Index - - - APIs by Level - - - APIs by Task - -
-
-
- -
- - - - -
- - -

License

-Intent of License

-

(This section is informal and not legally binding.)

-


- This library is free code-- you can use it without charge and it is minimally legally encumbered. Unlike some other free libraries, we do not require you to release your source code or make your own program open source.

-

I intend the license (below) to protect me and the other contributors from liability and allow you to use the source however you want. You can make your own closed or open-source programs, sell them, give them away, whatever.

-

The license for G3D itself and the libaries included in the G3D distribution create certain documentation obligations for you. For convenience, G3D::license is a function that returns the license string you must put in your documentation. G3D::GApp will automatically write a file (g3d-license.txt) to disk with the contents of this license unless you tell it not to, thus automatically satisfying your documentation requirement after the first time you run a G3D program.

-

Most of the data resources have either entered the public domain and have been in several published papers or are data that I have explicitly received permission to distribute with G3D. The G3D fonts are actually font images, not TrueType font descriptions and may be freely distributed. As a rule of thumb, you can freely use and distribute anything you find in the data directory but may need permission to use it in a commercial product. Check the various copyright.txt files in the data directories for specific information.

-

You are required by the BSD license to acknowledge G3D in your documentation. This can be as minimal as a note buried in the fine print at the end of a manual or a text file accompanying your program. I appreciate it if you acknowledged the library more publicly but you aren't required to.

-

Likewise, you are encouraged but not required to submit patches to improve the library for the benefit of all. Post bugs, patches, and questions to the g3d-users forum linked at the top of this page.

-

-Morgan McGuire <morgan@cs.williams.edu>

-
-

-License

-

G3D is licensed under the BSD license, with portions controlled by the IJG license, PNG Reference Library license.

-

-
-osi-certified-120x100.gif -
-

-

This product uses software from the G3D project (http://g3d.sf.net)

-

Copyright © 2000-2010, Morgan McGuire

-

All rights reserved.

-

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

-

Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.

-

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.

-

Neither the name of Morgan McGuire, Williams College, Brown 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.

-
- -
-G3D Innovation Engine documentation generated on Thu Mar 25 14:54:30 2010 using -doxygen - 1.6.1
- - - - - - - - - diff --git a/dep/src/g3dlite/prompt.cpp b/dep/src/g3dlite/prompt.cpp index d78f8b75a66..6a28e6462b4 100644 --- a/dep/src/g3dlite/prompt.cpp +++ b/dep/src/g3dlite/prompt.cpp @@ -21,7 +21,6 @@ # define _getch getchar #endif -#if 0 /* MANGOS exclude for disabled gui prompt */ #ifdef G3D_OSX /*#ifdef __LP64__ @@ -38,11 +37,9 @@ */ #endif -#endif /* MANGOS exclude for disabled gui prompt */ namespace G3D { -#if 0 /* MANGOS exclude for disabled gui prompt */ #ifdef G3D_WIN32 namespace _internal { @@ -472,7 +469,6 @@ static int guiPrompt( } #endif -#endif /* MANGOS exclude for disabled gui prompt */ /** @@ -535,8 +531,6 @@ static int textPrompt( return c; } -#if 0 /* MANGOS exclude for disabled gui prompt */ - #ifdef G3D_OSX // See http://developer.apple.com/documentation/Carbon/Reference/Carbon_Event_Manager_Ref/index.html @@ -695,15 +689,13 @@ static int guiPrompt #endif -#endif /* MANGOS exclude for disabled gui prompt */ - int prompt( const char* windowTitle, const char* prompt, const char** choice, int numChoices, bool useGui) { -#if 0 /* MANGOS: disable guid prompt at all platforms, MacOS case have build problems, other just useless */ + #ifdef G3D_WIN32 if (useGui) { // Build the message box @@ -717,7 +709,6 @@ int prompt( return guiPrompt(windowTitle, prompt, choice, numChoices); } #endif -#endif /* MANGOS exclude for disabled gui prompt */ return textPrompt(windowTitle, prompt, choice, numChoices); } diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index cd72a4d4212..1074389e852 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "12261" + #define REVISION_NR "12262" #endif // __REVISION_NR_H__