+
+The custom serialization format was chosen to be terse, easy for
+humans to read, and easy for machines to parse. It was specifically
+chosen over formats like XML, YAML, JSON, S-expressions, and Protocol
+Buffers, although there is no reason you could not write readers and
+writers for G3D::Any that support those.
+
+G3D::Any assumes that structures do not contain cycles; it is an
+error to create a structure like:
+
+
+Any x(Any::ARRAY);
+x.array().append(x); // don't do this!
+
+
+although no exception will be thrown at runtime during that append.
+
+
+\section Parsing
+
+The primary use of Any is to create your own text file formats.
+The Vector3 constructor is a good example of how to use the Any::verify
+methods to provide good error checking while parsing such formats:
+
+
+Vector3::Vector3(const Any& any) {
+ any.verifyName("Vector3");
+ any.verifyType(Any::TABLE, Any::ARRAY);
+ any.verifySize(3);
+
+ if (any.type() == Any::ARRAY) {
+ x = any[0];
+ y = any[1];
+ z = any[2];
+ } else {
+ // Table
+ x = any["x"];
+ y = any["y"];
+ z = any["z"];
+ }
+}
+
+
+Except for single-line comments, whitespace is not significant.
+All parsing is case-insensitive.
+
+The deserializer allows the substitution of [] for () when writing
+tuples and ";" for ",".
+
+The serializer indents four spaces for each level of nesting.
+Tables are written with the keys in alphabetic order.
+*/
+class Any {
+public:
+
+ enum Type {NONE, BOOLEAN, NUMBER, STRING, ARRAY, TABLE};
+
+ static std::string toString(Type t);
+
+ /** Where an Any came from in a file. Useful for throwing parsing errors */
+ class Source {
+ public:
+ std::string filename;
+ int line;
+ int character;
+
+ Source() : line(0), character(0) {}
+
+ void set(const TextInput& ti, const Token& t) {
+ filename = ti.filename();
+ line = t.line();
+ character = t.character();
+ }
+ };
+
+ typedef Array AnyArray;
+ typedef Table AnyTable;
+
+private:
+
+ /** Called from deserialize() */
+ static void deserializeComment(TextInput& ti, Token& token, std::string& comment);
+
+ /** NONE, BOOLEAN, and NUMBER are stored directly in the Any */
+ union SimpleValue {
+ bool b;
+ double n;
+
+ inline SimpleValue() : n(0.0) {}
+ inline SimpleValue(bool x) : b(x) {}
+ inline SimpleValue(double x) : n(x) {}
+ };
+
+ class Data {
+ public:
+ /** ARRAY, TABLE, or STRING value only. NULL otherwise. */
+ union Value {
+ std::string* s;
+ Array* a;
+ AnyTable* t;
+ inline Value() : s(NULL) {}
+ };
+
+ // Needed so that the destructor knows what is in Value
+ // and can call its destructor.
+ Type type;
+
+ /** Always points to memory that is allocated with the Data, so
+ the destructor does not delete this. */
+ Value value;
+
+ std::string comment;
+
+ std::string name;
+
+ /** For STRING, ARRAY and TABLE types, m_value is shared between
+ multiple instances. Mutation is allowed only if the reference
+ count is exactly 1, otherwise the mutating instance must copy
+ the value. This is not used for other types.
+ */
+ AtomicInt32 referenceCount;
+
+ Source source;
+
+ private:
+
+ /** Called by create() */
+ inline Data(Type t) : type(t), referenceCount(1) {}
+
+ /** Called by destroy */
+ ~Data();
+
+ public:
+
+ /** Clones the argument */
+ static Data* create(const Data* d);
+ static Data* create(Type t);
+
+ /** Free d, invoking its destructor and freeing the memory for
+ the value. */
+ static void destroy(Data* d);
+
+ };
+
+ /** If not empty, this Any was created from operator[] on a table
+ and perhaps was not intended to exist. The name is needed to
+ format the error message if it is read from before it is
+ written to.
+
+ The source of a placeholder object is that of the parent
+ object until it is written.
+ */
+ std::string m_placeholderName;
+
+ Type m_type;
+ SimpleValue m_simpleValue;
+ mutable Data* m_data;
+
+ /** Called before every read operation to ensure that this object
+ is not a placeholder. */
+ void beforeRead() const;
+
+ /** Called before every write operation to wipe the placeholder
+ status. */
+ void beforeWrite();
+
+ /** Decrements the reference count (if there is one). If the
+ reference count is zero after decrement, calls delete on @a m_data
+ and sets it to NULL.
+ */
+ void dropReference();
+
+ /** Allocate the Data object if it does not exist */
+ void ensureData();
+
+ /** If m_data is not NULL, ensure that it has a unique reference
+ and contains a valid m_data. This has a race condition if two
+ threads are both trying to modify the same Any
+ simultaneously.*/
+ void ensureMutable();
+
+ /** Read an unnamed a TABLE or ARRAY. Token should be the open
+ paren token; it is the next token after the close on
+ return. Called from deserialize().*/
+ void deserializeBody(TextInput& ti, Token& token);
+
+ void deserialize(TextInput& ti, Token& token);
+
+ /** Read the name of a named Array or Table. */
+ static void deserializeName(TextInput& ti, Token& token, std::string& name);
+
+ /** Read until a comma is consumed or a close paren is hit, and
+ return that token. Considers the passed in token to be the first
+ value read. */
+ static void readUntilCommaOrClose(TextInput& ti, Token& token);
+
+ /** Construct an Any that is a proxy for a table fetch from \a data.
+ This proxy can be copied exactly once on return from operator[].*/
+ Any(const std::string& key, Data* data);
+
+ inline bool isPlaceholder() const {
+ return ! m_placeholderName.empty();
+ }
+
+public:
+
+ /** Base class for all Any exceptions.*/
+ class Exception {
+ public:
+ virtual ~Exception() {}
+ };
+
+ /** Thrown by operator[] when a key is not present in a const table. */
+ class KeyNotFound : public ParseError {
+ public:
+ std::string key;
+ };
+
+ /** Thrown by operator[] when an array index is not present. */
+ class IndexOutOfBounds : public Exception {
+ public:
+ int index;
+ int size;
+ inline IndexOutOfBounds() : index(0), size(0) {}
+ inline IndexOutOfBounds(int i, int s) : index(i), size(s) {}
+ };
+
+ /** NONE constructor */
+ Any();
+
+ /** Deserialize */
+ explicit Any(TextInput& t);
+
+ Any(const Any& x);
+
+ /** NUMBER constructor */
+ Any(double x);
+
+#ifdef G3D_32BIT
+ /** NUMBER constructor */
+ Any(int64 x);
+#endif // G3D_32BIT
+
+#if 0
+ /** NUMBER constructor */
+ Any(int32 x);
+#endif // 0
+
+ /** NUMBER constructor */
+ Any(long x);
+
+ /** NUMBER constructor */
+ Any(int x);
+
+ /** NUMBER constructor */
+ Any(short x);
+
+ /** BOOLEAN constructor */
+ Any(bool x);
+
+ /** STRING constructor */
+ Any(const std::string& x);
+
+ /** STRING constructor */
+ Any(const char* x);
+
+ /** \a t must be ARRAY or TABLE */
+ Any(Type t, const std::string& name = "");
+
+ ~Any();
+
+ /** Removes the comment and name */
+ Any& operator=(const Any& x);
+
+ /** Removes the comment and name */
+ Any& operator=(double x);
+
+ /** Removes the comment and name */
+ Any& operator=(int x);
+
+ /** Removes the comment and name */
+ Any& operator=(bool x);
+
+ /** Removes the comment and name */
+ Any& operator=(const std::string& x);
+
+ /** Removes the comment and name */
+ Any& operator=(const char* x);
+
+ /** \a t must be ARRAY, TABLE, or NONE. Removes the comment and name */
+ Any& operator=(Type t);
+
+ Type type() const;
+
+ /** Same as deserialize or load, but operates on a string instead
+ of a stream or file.
+
+ \sa deserialize, load
+ */
+ void parse(const std::string& src);
+
+ std::string unparse() const;
+
+ /** Comments appear before values when they are in serialized form.*/
+ const std::string& comment() const;
+ void setComment(const std::string& c);
+
+ /** True if this is the NONE value */
+ bool isNone() const;
+
+ /** Throws a ParseError exception if this is not a number */
+ double number() const;
+ const std::string& string() const;
+ bool boolean() const;
+
+ /** If this is named ARRAY or TABLE, returns the name. */
+ const std::string& name() const;
+
+ /** \brief Set the name used when serializing an ARRAY or TABLE.
+
+ Only legal for ARRAY or TABLE. The \a name must begin with a letter
+ and contain only letters, numbers, underscores and scope operators.
+
+
+
+
+ The scope operators "::", "->", and
+ ".", may have spaces around them. The name may not
+ contain parentheses.
+ */
+ void setName(const std::string& name);
+
+ /** Number of elements if this is an ARRAY or TABLE */
+ int size() const;
+ int length() const;
+
+ /** For an array, returns the ith element */
+ const Any& operator[](int i) const;
+ Any& operator[](int i);
+
+ /** Directly exposes the underlying data structure for an ARRAY. */
+ const Array& array() const;
+ void append(const Any& v0);
+ void append(const Any& v0, const Any& v1);
+ void append(const Any& v0, const Any& v1, const Any& v2);
+ void append(const Any& v0, const Any& v1, const Any& v2, const Any& v3);
+
+ /** Directly exposes the underlying data structure for table.*/
+ const Table& table() const;
+
+ /** For a table, returns the element for \a key. Throws KeyNotFound
+ exception if the element does not exist.
+ */
+ const Any& operator[](const std::string& key) const;
+
+ // Needed to prevent the operator[](int) overload from catching
+ // string literals
+ inline const Any& operator[](const char* key) const {
+ return operator[](std::string(key));
+ }
+
+ /**
+ Fetch an element from a table. This can be used as:
+
+
+ a["key"] = value; (create the key if it did not exist)
+
+
+ or
+
+
+ value = a["key"]; (throw an error if the key did not exist)
+
+
+ Note:
+ In order to cause elements to be correctly created in the
+ first case while still providing "key not found" errors in the
+ second case, the Any returned is a special object that delays
+ the actual fetch until the following assignment or method
+ call. This means that in the event of an error, the exception
+ may be thrown from a line other than the actual fetch. Use
+ the Any::get() or the const Any::operator[]() methods to avoid
+ this behavior and ensure error-checking at fetch time.
+ */
+ Any& operator[](const std::string& key);
+
+ /** \copydoc Any::operator[](const std::string&) */
+ inline Any& operator[](const char* key) {
+ return operator[](std::string(key));
+ }
+
+ /** For a table, returns the element for key \a x and \a
+ defaultVal if it does not exist. */
+ const Any& get(const std::string& key, const Any& defaultVal) const;
+
+ /** Returns true if this key is in the TABLE. Illegal to call on an object that is not a TABLE. */
+ bool containsKey(const std::string& key) const;
+
+ /** For a table, assigns the element for key k. */
+ void set(const std::string& key, const Any& val);
+
+ /** for an ARRAY, resizes and returns the last element */
+ Any& next();
+
+
+ /** True if the Anys are exactly equal, ignoring comments. Applies deeply on arrays and tables. */
+ bool operator==(const Any& x) const;
+ bool operator!=(const Any& x) const;
+
+ operator int() const;
+ operator float() const;
+ operator double() const;
+ operator bool() const;
+ operator std::string() const;
+
+ /** Resize to \a n elements, where new elements are NIL
+ It is an error to call this method if this is not an Any::ARRAY */
+ void resize(int n);
+
+ /**
+ Clears all entries.
+ This must be a TABLE or ARRAY */
+ void clear();
+
+ /** Parse from a file.
+ \sa deserialize, parse */
+ void load(const std::string& filename);
+
+ /** Uses the serialize method. */
+ void save(const std::string& filename) const;
+
+ void serialize(TextOutput& to) const;
+ /** Parse from a stream.
+ \sa load, parse */
+ void deserialize(TextInput& ti);
+
+ const Source& source() const;
+
+ /** Throws a ParseError if \a value is false. Useful for quickly
+ creating parse rules in classes that deserialize from Any.
+ */
+ void verify(bool value, const std::string& message = "") const;
+
+ /** Verifies that the name begins with identifier \a n. It may contain
+ identifier operators after this */
+ void verifyName(const std::string& n) const;
+
+ /** Verifies that the type is \a t. */
+ void verifyType(Type t) const;
+
+ /** Throws an exception if the type is not \a t0 or \a t1. */
+ void verifyType(Type t0, Type t1) const;
+
+ /** Verifies that the size is between \a low and \a high, inclusive */
+ void verifySize(int low, int high) const;
+
+ /** Verifies that the size is exactly \a s */
+ void verifySize(int s) const;
+
+private:
+
+ void deserializeTable(TextInput& ti);
+ void deserializeArray(TextInput& ti,const std::string& term);
+
+}; // class Any
+
+} // namespace G3D
+
+#endif
diff --git a/dep/include/g3dlite/G3D/AnyVal.h b/dep/include/g3dlite/G3D/AnyVal.h
new file mode 100644
index 000000000..8c1bc72f2
--- /dev/null
+++ b/dep/include/g3dlite/G3D/AnyVal.h
@@ -0,0 +1,512 @@
+/**
+ @file AnyVal.h
+ @author Morgan McGuire
+ @created 2006-06-11
+ @edited 2008-07-14
+ */
+
+#ifndef G3D_ANYVAL_H
+#define G3D_ANYVAL_H
+
+#include "G3D/platform.h"
+#include
+#include "G3D/Array.h"
+#include "G3D/TextInput.h"
+
+namespace G3D {
+// Forward declarations for G3D types
+class Vector2;
+class Vector3;
+class Vector4;
+class Color1;
+class Color3;
+class Color4;
+class Quat;
+class Matrix2;
+class Matrix3;
+class Matrix4;
+class CoordinateFrame;
+class TextInput;
+class TextOutput;
+class BinaryInput;
+class BinaryOutput;
+class Rect2D;
+class AABox;
+
+/**
+ \deprecated
+ Use the G3D::Any class instead. This is only provided for
+ backwards compatibility to G3D 7.xx.
+
+ A generic value, useful for defining property trees that can
+ be loaded from and saved to disk. The values are intentionally
+ restricted to a small set.
+
+ When written to files, the syntax is as follows. Note that you can
+ nest arrays and tables in order to create full tree (i.e., XML-like)
+ structures as configuration files:
+
+
+
+ See also boost::any for a more general purpose but slightly harder to use
+ "any" for C++.
+
+ The semantics of operator[] and the get() methods are slightly different;
+ operator[] acts more like a scripting language that automatically extends
+ arrays and tables instead of generating errors. get() has more strict semantics,
+ like a C++ class.
+
+ AnyVal uses copy-on-mutate, so that AnyVal a = b semantically copies b (like int a = b would), although in practice
+ it delays the copy until one is mutated so that it is still fast to "copy" large arrays and tables.
+
+ Reading example:
+
+ AnyVal property = AnyVal::fromFile("c:/tmp/test.txt"));
+
+ Vector3 vel = property["angular velocity"]
+
+ Using defaults to handle errors:
+ If there was no "enabled" value, this will return the default instead of failing
+ bool enabled = property["enabled"].boolean(true);
+
+
+ {
+ heights = [1, 17, 32]
+ model =
+ {
+ color = C3(1, 1, 1)
+ filename = "foo.md2"
+ }
+ position = V3(23, 14, 0)
+ name = "Elmer"
+ }
+
+
+
+ What's the difference from boost::any?
+ I think that AnyVal will be easier for novice C++ users. It addresses the problem that
+ even though G3D::TextInput makes reading configuration files extremely simple, many people
+ still don't use it. So AnyVal makes it ridiculously simple to read and write a tree of G3D
+ types to a file.
+
+ AnyVal:
+
+
+ Use this so you can make vertex arrays of your own classes and not just
+ the standard ones.
+ */
+#define DECLARE_BINARYFORMATOF(CType, EnumType) \
+namespace G3D { \
+ namespace _internal { \
+ template<> class _BinaryFormat { \
+ public: \
+ static BinaryFormat x() { \
+ return EnumType; \
+ } \
+ }; \
+ } \
+}
+
+DECLARE_BINARYFORMATOF( bool, BOOL8_BINFMT )
+
+DECLARE_BINARYFORMATOF( uint8, UINT8_BINFMT )
+DECLARE_BINARYFORMATOF( int8, INT8_BINFMT )
+DECLARE_BINARYFORMATOF( uint16, UINT16_BINFMT )
+DECLARE_BINARYFORMATOF( int16, INT16_BINFMT )
+DECLARE_BINARYFORMATOF( uint32, UINT32_BINFMT )
+DECLARE_BINARYFORMATOF( int32, INT32_BINFMT )
+DECLARE_BINARYFORMATOF( uint64, UINT64_BINFMT )
+DECLARE_BINARYFORMATOF( int64, INT64_BINFMT )
+
+DECLARE_BINARYFORMATOF( float32, FLOAT32_BINFMT )
+DECLARE_BINARYFORMATOF( float64, FLOAT64_BINFMT )
+
+DECLARE_BINARYFORMATOF( Vector2, VECTOR2_BINFMT )
+DECLARE_BINARYFORMATOF( Vector2int16, VECTOR2INT16_BINFMT )
+DECLARE_BINARYFORMATOF( Vector3, VECTOR3_BINFMT )
+DECLARE_BINARYFORMATOF( Vector3int16, VECTOR3INT16_BINFMT )
+DECLARE_BINARYFORMATOF( Vector4, VECTOR4_BINFMT )
+DECLARE_BINARYFORMATOF( Vector4int16, VECTOR4INT16_BINFMT )
+
+DECLARE_BINARYFORMATOF( Color3, COLOR3_BINFMT )
+DECLARE_BINARYFORMATOF( Color3uint8, COLOR3UINT8_BINFMT )
+DECLARE_BINARYFORMATOF( Color4, COLOR4_BINFMT )
+DECLARE_BINARYFORMATOF( Color4uint8, COLOR4UINT8_BINFMT )
+
+namespace G3D {
+
+/** Returns -1 if the format is custom, otherwise the byte size
+ of a single element in this format.*/
+int32 byteSize(BinaryFormat f);
+
+
+} //G3D
+
+#endif
diff --git a/dep/include/g3dlite/G3D/BinaryInput.h b/dep/include/g3dlite/G3D/BinaryInput.h
new file mode 100644
index 000000000..1dac93ea5
--- /dev/null
+++ b/dep/include/g3dlite/G3D/BinaryInput.h
@@ -0,0 +1,441 @@
+/**
+ @file BinaryInput.h
+
+ @maintainer Morgan McGuire, graphics3d.com
+
+ @created 2001-08-09
+ @edited 2006-07-19
+
+ Copyright 2000-2009, Morgan McGuire.
+ All rights reserved.
+ */
+
+#ifndef G3D_BinaryInput_h
+#define G3D_BinaryInput_h
+
+#ifdef _MSC_VER
+// Disable conditional expression is constant, which occurs incorrectly on inlined functions
+# pragma warning(push)
+# pragma warning( disable : 4127 )
+#endif
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include "G3D/platform.h"
+#include "G3D/Array.h"
+#include "G3D/Color4.h"
+#include "G3D/Color3.h"
+#include "G3D/Vector4.h"
+#include "G3D/Vector3.h"
+#include "G3D/Vector2.h"
+#include "G3D/g3dmath.h"
+#include "G3D/debug.h"
+#include "G3D/System.h"
+
+
+namespace G3D {
+
+#if defined(G3D_WIN32) || defined(G3D_LINUX)
+ // Allow writing of integers to non-word aligned locations.
+ // This is legal on x86, but not on other platforms.
+ #define G3D_ALLOW_UNALIGNED_WRITES
+#endif
+
+/**
+ Sequential or random access byte-order independent binary file access.
+ Files compressed with zlib and beginning with an unsigned 32-bit int
+ size are transparently decompressed when the compressed = true flag is
+ specified to the constructor.
+
+ For every readX method there are also versions that operate on a whole
+ Array, std::vector, or C-array. e.g. readFloat32(Array& array, n)
+ These methods resize the array or std::vector to the appropriate size
+ before reading. For a C-array, they require the pointer to reference
+ a memory block at least large enough to hold n elements.
+
+ Most classes define serialize/deserialize methods that use BinaryInput,
+ BinaryOutput, TextInput, and TextOutput. There are text serializer
+ functions for primitive types (e.g. int, std::string, float, double) but not
+ binary serializers-- you must call the BinaryInput::readInt32 or
+ other appropriate function. This is because it would be very hard to
+ debug the error sequence: serialize(1.0, bo); ... float f; deserialize(f, bi);
+ in which a double is serialized and then deserialized as a float.
+ */
+class BinaryInput {
+private:
+
+ // The initial buffer will be no larger than this, but
+ // may grow if a large memory read occurs. 50 MB
+ enum {INITIAL_BUFFER_LENGTH = 50000000};
+
+ /**
+ is the file big or little endian
+ */
+ G3DEndian m_fileEndian;
+ std::string m_filename;
+
+ bool m_swapBytes;
+
+ /** Next position to read from in bitString during readBits. */
+ int m_bitPos;
+
+ /** Bits currently being read by readBits.
+ Contains at most 8 (low) bits. Note that
+ beginBits/readBits actually consumes one extra byte, which
+ will be restored by writeBits.*/
+ uint32 m_bitString;
+
+ /** 1 when between beginBits and endBits, 0 otherwise. */
+ int m_beginEndBits;
+
+ /** When operating on huge files, we cannot load the whole file into memory.
+ This is the file position to which buffer[0] corresponds.
+ */
+ int64 m_alreadyRead;
+
+ /**
+ Length of the entire file, in bytes.
+ For the length of the buffer, see bufferLength
+ */
+ int64 m_length;
+
+ /** Length of the array referenced by buffer. May go past the end of the file!*/
+ int64 m_bufferLength;
+ uint8* m_buffer;
+
+ /**
+ Next byte in file, relative to buffer.
+ */
+ int64 m_pos;
+
+ /**
+ When true, the buffer is freed in the destructor.
+ */
+ bool m_freeBuffer;
+
+ /** Ensures that we are able to read at least minLength from startPosition (relative
+ to start of file). */
+ void loadIntoMemory(int64 startPosition, int64 minLength = 0);
+
+ /** Verifies that at least this number of bytes can be read.*/
+ inline void prepareToRead(int64 nbytes) {
+ debugAssertM(m_length > 0, m_filename + " not found or corrupt.");
+ debugAssertM(m_pos + nbytes + m_alreadyRead <= m_length, "Read past end of file.");
+
+ if (m_pos + nbytes > m_bufferLength) {
+ loadIntoMemory(m_pos + m_alreadyRead, nbytes);
+ }
+ }
+
+ // Not implemented on purpose, don't use
+ BinaryInput(const BinaryInput&);
+ BinaryInput& operator=(const BinaryInput&);
+ bool operator==(const BinaryInput&);
+
+ /** Buffer is compressed; replace it with a decompressed version */
+ void decompress();
+public:
+
+ /** false, constant to use with the copyMemory option */
+ static const bool NO_COPY;
+
+ /**
+ If the file cannot be opened, a zero length buffer is presented.
+ Automatically opens files that are inside zipfiles.
+
+ @param compressed Set to true if and only if the file was
+ compressed using BinaryOutput's zlib compression. This has
+ nothing to do with whether the input is in a zipfile.
+ */
+ BinaryInput(
+ const std::string& filename,
+ G3DEndian fileEndian,
+ bool compressed = false);
+
+ /**
+ Creates input stream from an in memory source.
+ Unless you specify copyMemory = false, the data is copied
+ from the pointer, so you may deallocate it as soon as the
+ object is constructed. It is an error to specify copyMemory = false
+ and compressed = true.
+
+ To decompress part of a file, you can follow the following paradigm:
+
+
+ BinaryInput master(...);
+
+ // read from master to point where compressed data exists.
+
+ BinaryInput subset(master.getCArray() + master.getPosition(),
+ master.length() - master.getPosition(),
+ master.endian(), true, true);
+
+ // Now read from subset (it is ok for master to go out of scope)
+
+ */
+ BinaryInput(
+ const uint8* data,
+ int64 dataLen,
+ G3DEndian dataEndian,
+ bool compressed = false,
+ bool copyMemory = true);
+
+ virtual ~BinaryInput();
+
+ /** Change the endian-ness of the file. This only changes the
+ interpretation of the file for future read calls; the
+ underlying data is unmodified.*/
+ void setEndian(G3DEndian endian);
+
+ G3DEndian endian() const {
+ return m_fileEndian;
+ }
+
+ std::string getFilename() const {
+ return m_filename;
+ }
+
+ /**
+ Returns a pointer to the internal memory buffer.
+ May throw an exception for huge files.
+ */
+ const uint8* getCArray() const {
+ if (m_alreadyRead > 0) {
+ throw "Cannot getCArray for a huge file";
+ }
+ return m_buffer;
+ }
+
+ /**
+ Performs bounds checks in debug mode. [] are relative to
+ the start of the file, not the current position.
+ Seeks to the new position before reading (and leaves
+ that as the current position)
+ */
+ inline uint8 operator[](int64 n) {
+ setPosition(n);
+ return readUInt8();
+ }
+
+ /**
+ Returns the length of the file in bytes.
+ */
+ inline int64 getLength() const {
+ return m_length;
+ }
+
+ inline int64 size() const {
+ return getLength();
+ }
+
+ /**
+ Returns the current byte position in the file,
+ where 0 is the beginning and getLength() - 1 is the end.
+ */
+ inline int64 getPosition() const {
+ return m_pos + m_alreadyRead;
+ }
+
+ /**
+ Sets the position. Cannot set past length.
+ May throw a char* when seeking backwards more than 10 MB on a huge file.
+ */
+ inline void setPosition(int64 p) {
+ debugAssertM(p <= m_length, "Read past end of file");
+ m_pos = p - m_alreadyRead;
+ if ((m_pos < 0) || (m_pos > m_bufferLength)) {
+ loadIntoMemory(m_pos + m_alreadyRead);
+ }
+ }
+
+ /**
+ Goes back to the beginning of the file.
+ */
+ inline void reset() {
+ setPosition(0);
+ }
+
+ inline int8 readInt8() {
+ prepareToRead(1);
+ return m_buffer[m_pos++];
+ }
+
+ inline bool readBool8() {
+ return (readInt8() != 0);
+ }
+
+ inline uint8 readUInt8() {
+ prepareToRead(1);
+ return ((uint8*)m_buffer)[m_pos++];
+ }
+
+ uint16 inline readUInt16() {
+ prepareToRead(2);
+
+ m_pos += 2;
+ if (m_swapBytes) {
+ uint8 out[2];
+ out[0] = m_buffer[m_pos - 1];
+ out[1] = m_buffer[m_pos - 2];
+ return *(uint16*)out;
+ } else {
+ #ifdef G3D_ALLOW_UNALIGNED_WRITES
+ return *(uint16*)(&m_buffer[m_pos - 2]);
+ #else
+ uint8 out[2];
+ out[0] = m_buffer[m_pos - 2];
+ out[1] = m_buffer[m_pos - 1];
+ return *(uint16*)out;
+ #endif
+ }
+
+ }
+
+ inline int16 readInt16() {
+ uint16 a = readUInt16();
+ return *(int16*)&a;
+ }
+
+ inline uint32 readUInt32() {
+ prepareToRead(4);
+
+ m_pos += 4;
+ if (m_swapBytes) {
+ uint8 out[4];
+ out[0] = m_buffer[m_pos - 1];
+ out[1] = m_buffer[m_pos - 2];
+ out[2] = m_buffer[m_pos - 3];
+ out[3] = m_buffer[m_pos - 4];
+ return *(uint32*)out;
+ } else {
+ #ifdef G3D_ALLOW_UNALIGNED_WRITES
+ return *(uint32*)(&m_buffer[m_pos - 4]);
+ #else
+ uint8 out[4];
+ out[0] = m_buffer[m_pos - 4];
+ out[1] = m_buffer[m_pos - 3];
+ out[2] = m_buffer[m_pos - 2];
+ out[3] = m_buffer[m_pos - 1];
+ return *(uint32*)out;
+ #endif
+ }
+ }
+
+
+ inline int32 readInt32() {
+ uint32 a = readUInt32();
+ return *(int32*)&a;
+ }
+
+ uint64 readUInt64();
+
+ inline int64 readInt64() {
+ uint64 a = readUInt64();
+ return *(int64*)&a;
+ }
+
+ inline float32 readFloat32() {
+ union {
+ uint32 a;
+ float32 b;
+ };
+ a = readUInt32();
+ return b;
+ }
+
+ inline float64 readFloat64() {
+ union {
+ uint64 a;
+ float64 b;
+ };
+ a = readUInt64();
+ return b;
+ }
+
+ void readBytes(void* bytes, int64 n);
+
+ /**
+ Reads an n character string. The string is not
+ required to end in NULL in the file but will
+ always be a proper std::string when returned.
+ */
+ std::string readString(int64 n);
+
+ /**
+ Reads until NULL or the end of the file is encountered.
+ */
+ std::string readString();
+
+ /**
+ Reads until NULL or the end of the file is encountered.
+ If the string has odd length (including NULL), reads
+ another byte.
+ */
+ std::string readStringEven();
+
+
+ std::string readString32();
+
+ Vector4 readVector4();
+ Vector3 readVector3();
+ Vector2 readVector2();
+
+ Color4 readColor4();
+ Color3 readColor3();
+
+ /**
+ Skips ahead n bytes.
+ */
+ inline void skip(int64 n) {
+ setPosition(m_pos + m_alreadyRead + n);
+ }
+
+ /**
+ Returns true if the position is not at the end of the file
+ */
+ inline bool hasMore() const {
+ return m_pos + m_alreadyRead < m_length;
+ }
+
+ /** Prepares for bit reading via readBits. Only readBits can be
+ called between beginBits and endBits without corrupting the
+ data stream. */
+ void beginBits();
+
+ /** Can only be called between beginBits and endBits */
+ uint32 readBits(int numBits);
+
+ /** Ends bit-reading. */
+ void endBits();
+
+# define DECLARE_READER(ucase, lcase)\
+ void read##ucase(lcase* out, int64 n);\
+ void read##ucase(std::vector& out, int64 n);\
+ void read##ucase(Array& out, int64 n);
+
+ DECLARE_READER(Bool8, bool)
+ DECLARE_READER(UInt8, uint8)
+ DECLARE_READER(Int8, int8)
+ DECLARE_READER(UInt16, uint16)
+ DECLARE_READER(Int16, int16)
+ DECLARE_READER(UInt32, uint32)
+ DECLARE_READER(Int32, int32)
+ DECLARE_READER(UInt64, uint64)
+ DECLARE_READER(Int64, int64)
+ DECLARE_READER(Float32, float32)
+ DECLARE_READER(Float64, float64)
+# undef DECLARE_READER
+};
+
+
+}
+
+#ifdef _MSC_VER
+# pragma warning(pop)
+#endif
+
+#endif
diff --git a/dep/include/g3dlite/G3D/BinaryOutput.h b/dep/include/g3dlite/G3D/BinaryOutput.h
new file mode 100644
index 000000000..d81ec56a6
--- /dev/null
+++ b/dep/include/g3dlite/G3D/BinaryOutput.h
@@ -0,0 +1,421 @@
+/**
+ @file BinaryOutput.h
+
+ @maintainer Morgan McGuire, graphics3d.com
+
+ @created 2001-08-09
+ @edited 2008-01-24
+
+ Copyright 2000-2006, Morgan McGuire.
+ All rights reserved.
+ */
+
+#ifndef G3D_BINARYOUTPUT_H
+#define G3D_BINARYOUTPUT_H
+
+#include "G3D/platform.h"
+#include
+#include
+#include
+#include
+#include
+#include "G3D/Color4.h"
+#include "G3D/Color3.h"
+#include "G3D/Vector4.h"
+#include "G3D/Vector3.h"
+#include "G3D/Vector2.h"
+#include "G3D/g3dmath.h"
+#include "G3D/debug.h"
+#include "G3D/BinaryInput.h"
+#include "G3D/System.h"
+
+#ifdef _MSC_VER
+# pragma warning (push)
+// Conditional is constant (wrong in inline)
+# pragma warning (disable : 4127)
+#endif
+namespace G3D {
+
+/**
+ Sequential or random access byte-order independent binary file access.
+
+ The compress() call can be used to compress with zlib.
+
+ Any method call can trigger an out of memory error (thrown as char*)
+ when writing to "" instead of a file.
+
+ Compressed writing and seeking backwards is not supported for huge files
+ (i.e., BinaryOutput may have to dump the contents to disk if they
+ exceed available RAM).
+ */
+class BinaryOutput {
+private:
+ std::string m_filename;
+
+ bool m_committed;
+
+ /** 0 outside of beginBits...endBits, 1 inside */
+ int m_beginEndBits;
+
+ /** The current string of bits being built up by beginBits...endBits.
+ This string is treated semantically, as if the lowest bit was
+ on the left and the highest was on the right.*/
+ int8 m_bitString;
+
+ /** Position (from the lowest bit) currently used in bitString.*/
+ int m_bitPos;
+
+ // True if the file endianess does not match the machine endian
+ bool m_swapBytes;
+
+ G3DEndian m_fileEndian;
+
+ uint8* m_buffer;
+
+ /** Size of the elements used */
+ int m_bufferLen;
+
+ /** Underlying size of memory allocaded */
+ int m_maxBufferLen;
+
+ /** Next byte in file */
+ int m_pos;
+
+ /** is this initialized? */
+ bool m_init;
+
+ /** Number of bytes already written to the file.*/
+ size_t m_alreadyWritten;
+
+ bool m_ok;
+
+ void reserveBytesWhenOutOfMemory(size_t bytes);
+
+ void reallocBuffer(size_t bytes, size_t oldBufferLen);
+
+ /**
+ Make sure at least bytes can be written, resizing if
+ necessary.
+ */
+ inline void reserveBytes(int bytes) {
+ debugAssert(bytes > 0);
+ size_t oldBufferLen = (size_t)m_bufferLen;
+
+ m_bufferLen = iMax(m_bufferLen, (m_pos + bytes));
+ if (m_bufferLen > m_maxBufferLen) {
+ reallocBuffer(bytes, oldBufferLen);
+ }
+ }
+
+ // Not implemented on purpose, don't use
+ BinaryOutput(const BinaryOutput&);
+ BinaryOutput& operator=(const BinaryOutput&);
+ bool operator==(const BinaryOutput&);
+
+public:
+
+ /**
+ You must call setEndian() if you use this (memory) constructor.
+ */
+ BinaryOutput();
+
+ /**
+ Doesn't actually open the file; commit() does that.
+ Use "" as the filename if you're going to commit
+ to memory.
+ */
+ BinaryOutput(
+ const std::string& filename,
+ G3DEndian fileEndian);
+
+ ~BinaryOutput();
+
+ /** Compresses the data in the buffer in place,
+ preceeding it with a little-endian uint32 indicating
+ the uncompressed size.
+
+ Call immediately before commit().
+
+ Cannot be used for huge files (ones where the data
+ was already written to disk)-- will throw char*.
+ */
+ void compress();
+
+ /** True if no errors have been encountered.*/
+ bool ok() const;
+
+ /**
+ Returns a pointer to the internal memory buffer.
+ */
+ inline const uint8* getCArray() const {
+ return m_buffer;
+ }
+
+ void setEndian(G3DEndian fileEndian);
+
+ G3DEndian endian() const {
+ return m_fileEndian;
+ }
+
+ std::string getFilename() const {
+ return m_filename;
+ }
+
+ /**
+ Write the bytes to disk. It is ok to call this
+ multiple times; it will just overwrite the previous file.
+
+ Parent directories are created as needed if they do
+ not exist.
+
+ Not called from the destructor; you must call
+ it yourself.
+
+ @param flush If true (default) the file is ready for reading when the method returns, otherwise
+ the method returns immediately and writes the file in the background.
+ */
+ void commit(bool flush = true);
+
+ /**
+ Write the bytes to memory (which must be of
+ at least size() bytes).
+ */
+ void commit(uint8*);
+
+ /**
+ A memory BinaryOutput may be reset so that it can be written to again
+ without allocating new memory. The underlying array will not be deallocated,
+ but the reset structure will act like a newly intialized one.
+ */
+ void reset();
+
+
+ inline int length() const {
+ return (int)m_bufferLen + (int)m_alreadyWritten;
+ }
+
+ inline int size() const {
+ return length();
+ }
+
+ /**
+ Sets the length of the file to n, padding
+ with 0's past the current end. Does not
+ change the position of the next byte to be
+ written unless n < size().
+
+ Throws char* when resetting a huge file to be shorter
+ than its current length.
+ */
+ inline void setLength(int n) {
+ n = n - (int)m_alreadyWritten;
+
+ if (n < 0) {
+ throw "Cannot resize huge files to be shorter.";
+ }
+
+ if (n < m_bufferLen) {
+ m_pos = n;
+ }
+ if (n > m_bufferLen) {
+ reserveBytes(n - m_bufferLen);
+ }
+ }
+
+ /**
+ Returns the current byte position in the file,
+ where 0 is the beginning and getLength() - 1 is the end.
+ */
+ inline int64 position() const {
+ return (int64)m_pos + (int64)m_alreadyWritten;
+ }
+
+
+ /**
+ Sets the position. Can set past length, in which case
+ the file is padded with zeros up to one byte before the
+ next to be written.
+
+ May throw a char* exception when seeking backwards on a huge file.
+ */
+ inline void setPosition(int64 p) {
+ p = p - (int64)m_alreadyWritten;
+
+ if (p > m_bufferLen) {
+ setLength((int)(p + (int64)m_alreadyWritten));
+ }
+
+ if (p < 0) {
+ throw "Cannot seek more than 10 MB backwards on huge files.";
+ }
+
+ m_pos = (int)p;
+ }
+
+
+ void writeBytes(
+ const void* b,
+ int count) {
+
+ reserveBytes(count);
+ debugAssert(m_pos >= 0);
+ debugAssert(m_bufferLen >= count);
+ System::memcpy(m_buffer + m_pos, b, count);
+ m_pos += count;
+ }
+
+ /**
+ Writes a signed 8-bit integer to the current position.
+ */
+ inline void writeInt8(int8 i) {
+ reserveBytes(1);
+ m_buffer[m_pos] = *(uint8*)&i;
+ m_pos++;
+ }
+
+ inline void writeBool8(bool b) {
+ writeInt8(b ? 1 : 0);
+ }
+
+ inline void writeUInt8(uint8 i) {
+ reserveBytes(1);
+ m_buffer[m_pos] = i;
+ m_pos++;
+ }
+
+ void writeUInt16(uint16 u);
+
+ inline void writeInt16(int16 i) {
+ writeUInt16(*(uint16*)&i);
+ }
+
+ void writeUInt32(uint32 u);
+
+ inline void writeInt32(int32 i) {
+ debugAssert(m_beginEndBits == 0);
+ writeUInt32(*(uint32*)&i);
+ }
+
+ void writeUInt64(uint64 u);
+
+ inline void writeInt64(int64 i) {
+ writeUInt64(*(uint64*)&i);
+ }
+
+ inline void writeFloat32(float32 f) {
+ debugAssert(m_beginEndBits == 0);
+ union {
+ float32 a;
+ uint32 b;
+ };
+ a = f;
+ writeUInt32(b);
+ }
+
+ inline void writeFloat64(float64 f) {
+ union {
+ float64 a;
+ uint64 b;
+ };
+ a = f;
+ writeUInt64(b);
+ }
+
+ /**
+ Write a string with NULL termination.
+ */
+ inline void writeString(const std::string& s) {
+ writeString(s.c_str());
+ }
+
+ void writeString(const char* s);
+
+ /**
+ Write a string, ensuring that the total length
+ including NULL is even.
+ */
+ void writeStringEven(const std::string& s) {
+ writeStringEven(s.c_str());
+ }
+
+ void writeStringEven(const char* s);
+
+
+ void writeString32(const char* s);
+
+ /**
+ Write a string with a 32-bit length field in front
+ of it.
+ */
+ void writeString32(const std::string& s) {
+ writeString32(s.c_str());
+ }
+
+ void writeVector4(const Vector4& v);
+
+ void writeVector3(const Vector3& v);
+
+ void writeVector2(const Vector2& v);
+
+ void writeColor4(const Color4& v);
+
+ void writeColor3(const Color3& v);
+
+ /**
+ Skips ahead n bytes.
+ */
+ inline void skip(int n) {
+ if (m_pos + n > m_bufferLen) {
+ setLength((int)m_pos + (int)m_alreadyWritten + n);
+ }
+ m_pos += n;
+ }
+
+ /** Call before a series of BinaryOutput::writeBits calls. Only writeBits
+ can be called between beginBits and endBits without corrupting the stream.*/
+ void beginBits();
+
+ /** Write numBits from bitString to the output stream. Bits are numbered from
+ low to high.
+
+ Can only be
+ called between beginBits and endBits. Bits written are semantically
+ little-endian, regardless of the actual endian-ness of the system. That is,
+ writeBits(0xABCD, 16) writes 0xCD to the first byte and
+ 0xAB to the second byte. However, if used with BinaryInput::readBits, the ordering
+ is transparent to the caller.
+ */
+ void writeBits(uint32 bitString, int numBits);
+
+ /** Call after a series of BinaryOutput::writeBits calls. This will
+ finish out with zeros the last byte into which bits were written.*/
+ void endBits();
+
+
+# define DECLARE_WRITER(ucase, lcase)\
+ void write##ucase(const lcase* out, int n);\
+ void write##ucase(const std::vector& out, int n);\
+ void write##ucase(const Array& out, int n);
+
+ DECLARE_WRITER(Bool8, bool)
+ DECLARE_WRITER(UInt8, uint8)
+ DECLARE_WRITER(Int8, int8)
+ DECLARE_WRITER(UInt16, uint16)
+ DECLARE_WRITER(Int16, int16)
+ DECLARE_WRITER(UInt32, uint32)
+ DECLARE_WRITER(Int32, int32)
+ DECLARE_WRITER(UInt64, uint64)
+ DECLARE_WRITER(Int64, int64)
+ DECLARE_WRITER(Float32, float32)
+ DECLARE_WRITER(Float64, float64)
+# undef DECLARE_WRITER
+
+};
+
+}
+
+#ifdef _MSC_VER
+# pragma warning (pop)
+#endif
+
+#endif
diff --git a/dep/include/g3dlite/G3D/BoundsTrait.h b/dep/include/g3dlite/G3D/BoundsTrait.h
new file mode 100644
index 000000000..15e141801
--- /dev/null
+++ b/dep/include/g3dlite/G3D/BoundsTrait.h
@@ -0,0 +1,20 @@
+/**
+ @file BoundsTrait.h
+
+ @maintainer Morgan McGuire, http://graphics.cs.williams.edu
+ @created 2008-10-01
+ @edited 2008-10-01
+ Copyright 2000-2009, Morgan McGuire.
+ All rights reserved.
+ */
+
+#ifndef G3D_BOUNDSTRAIT_H
+#define G3D_BOUNDSTRAIT_H
+
+#include "G3D/platform.h"
+
+template
+struct BoundsTrait{};
+
+#endif
+
diff --git a/dep/include/g3dlite/G3D/Box.h b/dep/include/g3dlite/G3D/Box.h
index f097c10e1..82af9125b 100644
--- a/dep/include/g3dlite/G3D/Box.h
+++ b/dep/include/g3dlite/G3D/Box.h
@@ -3,11 +3,11 @@
Box class
- @maintainer Morgan McGuire, matrix@graphics3d.com
+ @maintainer Morgan McGuire, http://graphics.cs.williams.edu
@cite Portions based on Dave Eberly's Magic Software Library at http://www.magic-software.com
@created 2001-06-02
- @edited 2006-01-05
+ @edited 2007-06-05
Copyright 2000-2006, Morgan McGuire.
All rights reserved.
@@ -84,8 +84,14 @@ public:
const Vector3& min,
const Vector3& max);
+ static Box inf();
+
+ Box(class BinaryInput& b);
+
Box(const class AABox& b);
+ void serialize(class BinaryOutput& b) const;
+ void deserialize(class BinaryInput& b);
/**
Returns the object to world transformation for
@@ -105,18 +111,6 @@ public:
return _center;
}
- inline Vector3 getCenter() const {
- return center();
- }
-
- /**
- Returns a corner (0 <= i < 8)
- @deprecated
- */
- inline Vector3 getCorner(int i) const {
- debugAssert(i < 8);
- return _corner[i];
- }
inline Vector3 corner(int i) const {
debugAssert(i < 8);
@@ -155,65 +149,34 @@ public:
Vector3& v2,
Vector3& v3) const;
-/**
- @deprecated Use culledBy(Array&)
- */
- bool culledBy(
- const class Plane* plane,
- int numPlanes,
- int32& cullingPlaneIndex,
- const uint32 testMask,
- uint32& childMask) const;
-
- /**
- @deprecated Use culledBy(Array&)
- */
- bool culledBy(
- const class Plane* plane,
- int numPlanes,
- int32& cullingPlaneIndex = dummy,
- const uint32 testMask = -1) const;
/**
See AABox::culledBy
*/
- bool culledBy(
- const Array& plane,
- int32& cullingPlaneIndex,
- const uint32 testMask,
- uint32& childMask) const;
+ bool culledBy
+ (
+ const Array& plane,
+ int32& cullingPlaneIndex,
+ const uint32 testMask,
+ uint32& childMask) const;
/**
Conservative culling test that does not produce a mask for children.
*/
- bool culledBy(
- const Array& plane,
- int32& cullingPlaneIndex = dummy,
- const uint32 testMask = -1) const;
+ bool culledBy
+ (
+ const Array& plane,
+ int32& cullingPlaneIndex = dummy,
+ const uint32 testMask = -1) const;
bool contains(
const Vector3& point) const;
- /** @deprecated */
- float surfaceArea() const;
-
- inline float area() const {
- return surfaceArea();
- }
+ float area() const;
float volume() const;
- void getRandomSurfacePoint(Vector3& P, Vector3& N = Vector3::dummy) const;
-
- /**
- @deprecated
- Uniformly distributed on the surface.
- */
- inline Vector3 randomSurfacePoint() const {
- Vector3 V;
- getRandomSurfacePoint(V);
- return V;
- }
+ void getRandomSurfacePoint(Vector3& P, Vector3& N = Vector3::ignore()) const;
/**
Uniformly distributed on the interior (includes surface)
@@ -221,6 +184,10 @@ public:
Vector3 randomInteriorPoint() const;
void getBounds(class AABox&) const;
+
+ bool isFinite() const {
+ return G3D::isFinite(_volume);
+ }
};
}
diff --git a/dep/include/g3dlite/G3D/Box2D.h b/dep/include/g3dlite/G3D/Box2D.h
new file mode 100644
index 000000000..80accad89
--- /dev/null
+++ b/dep/include/g3dlite/G3D/Box2D.h
@@ -0,0 +1,121 @@
+/**
+ @file Box2D.h
+
+ @maintainer Morgan McGuire, http://graphics.cs.williams.edu
+
+ @created 2001-06-02
+ @edited 2008-12-27
+
+ Copyright 2000-2009, Morgan McGuire.
+ All rights reserved.
+ */
+
+#ifndef G3D_Box2D_h
+#define G3D_Box2D_h
+
+#include "G3D/platform.h"
+#include "G3D/Vector2.h"
+
+namespace G3D {
+
+class CoordinateFrame;
+typedef class CoordinateFrame CFrame;
+class Rect2D;
+typedef class Rect2D AABox2D;
+
+/**
+ 2D oriented box
+ @cite http://www.flipcode.com/archives/2D_OBB_Intersection.shtml
+ */
+class Box2D {
+private:
+ /** Corners of the box, where 0 is the lower left. */
+ Vector2 m_corner[4];
+
+ /** Two edges of the box extended away from corner[0], with length
+ = 1 / extentSquared */
+ Vector2 m_axisin[2];
+
+ /** Two edges of the box extended away from corner[0], with unit length */
+ Vector2 m_axis[2];
+
+ /** Centroid of the box */
+ Vector2 m_center;
+
+ /** origin[a] = m_corner[0].dot(m_axisin[a]); */
+ float origin[2];
+
+ /** Surface area */
+ float m_area;
+
+ Vector2 m_extent;
+
+ /** Returns true if other overlaps one dimension of this. */
+ bool overlaps1Way(const Box2D& other) const;
+
+
+ /** Updates the axes after the m_corners move. Assumes the
+ m_corners actually form a rectangle. */
+ void computeAxes();
+
+public:
+
+ /**
+ @param center World-space center
+ @param w Width along object-space x-axis
+ @param h Height along object-space y-axis
+ @param angle Counter-clockwise angle from object-space x-axis in radians
+ */
+ Box2D(const Vector2& center = Vector2(0, 0), float w = 0, float h = 0, float angle = 0);
+
+ Box2D(const AABox2D& b);
+
+ Box2D(const Vector2& min, const Vector2& max);
+
+ /** Transform @a b by @a frame, discarding the Z components, and
+ compute the new box.*/
+ Box2D(const CFrame& frame, Box2D& b);
+
+ inline bool contains(const Vector2& v) const {
+ // Take to object space:
+ const Vector2& p = v - m_center;
+ float x = p.dot(m_axisin[0]);
+ float y = p.dot(m_axisin[1]);
+
+ // Must be within extent/2 on both axes in object space
+ return (abs(x) <= 0.5f) && (abs(y) <= 0.5f);
+ }
+
+ /** @brief Distance from corner(0) to the next corner along the box's local axis a. */
+ inline const Vector2& extent() const {
+ return m_extent;
+ }
+
+ /** @brief Unit length vector along axis @a a */
+ inline const Vector2& axis(int a) const {
+ debugAssert(a == 0 || a == 1);
+ return m_axis[a];
+ }
+
+ /** @brief Surface area */
+ inline float area() const {
+ return m_area;
+ }
+
+ inline const Vector2& corner(int i) const {
+ debugAssert(i >=0 && i <= 3);
+ return m_corner[i];
+ }
+
+ inline const Vector2& center() const {
+ return m_center;
+ }
+
+ /** Returns true if the intersection of the boxes is non-empty. */
+ inline bool overlaps(const Box2D& other) const {
+ return overlaps1Way(other) && other.overlaps1Way(*this);
+ }
+};
+
+} // G3D
+#endif
diff --git a/dep/include/g3dlite/G3D/BumpMapPreprocess.h b/dep/include/g3dlite/G3D/BumpMapPreprocess.h
new file mode 100644
index 000000000..955f99e61
--- /dev/null
+++ b/dep/include/g3dlite/G3D/BumpMapPreprocess.h
@@ -0,0 +1,61 @@
+/**
+ \file BumpMapPreprocess.h
+
+ \maintainer Morgan McGuire, http://graphics.cs.williams.edu
+
+ \created 2010-01-28
+ \edited 2010-01-28
+
+ Copyright 2000-2010, Morgan McGuire.
+ All rights reserved.
+ */
+
+#ifndef G3D_BumpMapPreprocess_h
+#define G3D_BumpMapPreprocess_h
+
+#include "G3D/platform.h"
+
+namespace G3D {
+class Any;
+
+/**
+Not in the BumpMap class to avoid a circular dependency between Texture and BumpMap.
+G3D::GImage::computeNormalMap().
+*/
+class BumpMapPreprocess {
+public:
+
+ /** If true, the elevations are box filtered after computing normals
+ and before uploading, which produces better results for parallax offset mapping
+ Defaults to false. */
+ bool lowPassFilter;
+
+ /** Height of the maximum ("white") value, in pixels, for the purpose of computing normals.
+ A value of 255 means that a 255 x 255 bump image with a full black-to-white gradient
+ will produce a 45-degree ramp (this also results in "cubic" voxels).
+ A negative value means to set zExtentPixels to -zExtentPixels * max(width, height).
+ The default is -0.02.
+ */
+ float zExtentPixels;
+
+ /** After computing normals, scale the height by |N.z|, a trick that reduces texture swim in steep areas for parallax offset
+ mapping. Defaults to false.*/
+ bool scaleZByNz;
+
+ BumpMapPreprocess() : lowPassFilter(false), zExtentPixels(-0.02f), scaleZByNz(false) {}
+
+ BumpMapPreprocess(const Any& any);
+
+ operator Any() const;
+
+ bool operator==(const BumpMapPreprocess& other) const {
+ return
+ (lowPassFilter == other.lowPassFilter) &&
+ (zExtentPixels == other.zExtentPixels) &&
+ (scaleZByNz == other.scaleZByNz);
+ }
+};
+
+}
+
+#endif
diff --git a/dep/include/g3dlite/G3D/Capsule.h b/dep/include/g3dlite/G3D/Capsule.h
new file mode 100644
index 000000000..baeea3aa8
--- /dev/null
+++ b/dep/include/g3dlite/G3D/Capsule.h
@@ -0,0 +1,90 @@
+/**
+ @file Capsule.h
+
+ @maintainer Morgan McGuire, http://graphics.cs.williams.edu
+
+ @created 2003-02-07
+ @edited 2005-08-20
+
+ Copyright 2000-2006, Morgan McGuire.
+ All rights reserved.
+ */
+
+#ifndef G3D_CAPSULE_H
+#define G3D_CAPSULE_H
+
+#include "G3D/platform.h"
+#include "G3D/g3dmath.h"
+#include "G3D/Vector3.h"
+
+namespace G3D {
+
+class Line;
+class AABox;
+/**
+ A shape formed by extruding a sphere along a line segment.
+ */
+class Capsule {
+private:
+ Vector3 p1;
+ Vector3 p2;
+
+ float _radius;
+public:
+
+
+ /** Uninitialized */
+ Capsule();
+ Capsule(class BinaryInput& b);
+ Capsule(const Vector3& _p1, const Vector3& _p2, float _r);
+ void serialize(class BinaryOutput& b) const;
+ void deserialize(class BinaryInput& b);
+
+ /** The line down the center of the capsule */
+ Line axis() const;
+
+ inline float radius() const {
+ return _radius;
+ }
+
+ /** Argument may be 0 or 1 */
+ inline Vector3 point(int i) const {
+ debugAssert(i == 0 || i == 1);
+ return (i == 0) ? p1 : p2;
+ }
+
+ /** Distance between the sphere centers. The total extent of the cylinder is
+ 2r + h. */
+ inline float height() const {
+ return (p1 - p2).magnitude();
+ }
+
+ inline Vector3 center() const {
+ return (p1 + p2) / 2.0;
+ }
+
+ /** Get a reference frame in which the center of mass is the origin and Y is the axis of the capsule.*/
+ void getReferenceFrame(class CoordinateFrame& cframe) const;
+
+ /**
+ Returns true if the point is inside the capsule or on its surface.
+ */
+ bool contains(const Vector3& p) const;
+
+ float volume() const;
+
+ float area() const;
+
+ /** Get axis aligned bounding box */
+ void getBounds(AABox& out) const;
+
+ /** Random world space point with outward facing normal. */
+ void getRandomSurfacePoint(Vector3& P, Vector3& N) const;
+
+ /** Point selected uniformly at random over the volume. */
+ Vector3 randomInteriorPoint() const;
+};
+
+} // namespace
+
+#endif
diff --git a/dep/include/g3dlite/G3D/CollisionDetection.h b/dep/include/g3dlite/G3D/CollisionDetection.h
index 4dc8b2653..c8fcf5534 100644
--- a/dep/include/g3dlite/G3D/CollisionDetection.h
+++ b/dep/include/g3dlite/G3D/CollisionDetection.h
@@ -4,17 +4,18 @@
Moving collision detection for simple primitives.
- @author Morgan McGuire, matrix@graphics3d.com
+ @author Morgan McGuire, http://graphics.cs.williams.edu
@cite Spherical collision based on Paul Nettle's
ftp://ftp.3dmaileffects.com/pub/FluidStudios/CollisionDetection/Fluid_Studios_Generic_Collision_Detection_for_Games_Using_Ellipsoids.pdf
and comments by Max McGuire. Ray-sphere intersection by Eric Haines.
Box-Box intersection written by Kevin Egan.
Thanks to Max McGuire of Iron Lore for various bug fixes.
+ Box-Triangle by Tomas Akenine-Moller
@created 2001-11-19
- @edited 2006-01-10
+ @edited 2008-12-19
- Copyright 2000-2006, Morgan McGuire.
+ Copyright 2000-2009, Morgan McGuire.
All rights reserved.
*/
@@ -68,17 +69,17 @@ namespace G3D {
@@ -86,6 +87,8 @@ namespace G3D {
* Note: Moving collision detection against certain primitives is equivalent to static collision
detection against a bigger primitive. Ray, Line Segment == ``moving Point''; Capsule ==``moving Sphere''; Plane == ``moving Line''
+
+ @deprecated Routines moving to the G3D::Intersect class in G3D 8.0
*/
class CollisionDetection {
private:
@@ -404,11 +407,11 @@ public:
Plane as well as the deepest point of the sphere that penetrates the plane
and the plane normal at that intersection.
- @param sphere Fixed Sphere.
- @param plane Fixed Plane.
- @param contactPoints Sphere point that penetrates the plane.
+ @param sphereA Fixed Sphere.
+ @param planeB Fixed Plane.
+ @param contactPoints Sphere point that penetrates the plane.
[Post Condition]
- @param contactNormals Normal at penetration point. [Post Condition]
+ @param contactNormals Normal at penetration point. [Post Condition]
@return Depth of penetration. If there is no intersection between the
objects then the depth will be a negative value.
@@ -477,8 +480,6 @@ public:
@param v0 Triangle vertex 1.
@param v1 Triangle vertex 2.
@param v2 Triangle vertex 3
- @param location Location of collision. [Post Condition]
- (Infinite vector on no collision)
@return Time til collision. If there is no collision then the return
value will be inf().
@@ -519,7 +520,7 @@ public:
const Vector3& v2,
Vector3& location) {
float t = collisionTimeForMovingPointFixedTriangle(orig, dir, v0, v1, v2);
- if (t < inf()) {
+ if (t < finf()) {
location = orig + dir * t;
}
return t;
@@ -553,7 +554,7 @@ public:
float t = collisionTimeForMovingPointFixedTriangle(
orig, dir, tri.vertex(0), tri.vertex(1), tri.vertex(2));
- if ((t < inf()) && (&location != &ignore)) {
+ if ((t < finf()) && (&location != &ignore)) {
location = orig + dir * t;
normal = tri.normal();
}
@@ -589,21 +590,20 @@ public:
Vector3& location,
Vector3& normal) {
float t = collisionTimeForMovingPointFixedTriangle(orig, dir, v0, v1, v2);
- if (t < inf()) {
+ if (t < finf()) {
location = orig + dir * t;
- normal = (v2 - v0).cross(v1 - v0).direction();
+ normal = (v1 - v0).cross(v2 - v0).direction();
}
return t;
}
/**
- Unlike other methods, does not support an output normal.
If the ray origin is inside the box, returns inf() but inside
is set to true.
Beta API
@cite Andrew Woo, from "Graphics Gems", Academic Press, 1990
- @cite Optimized code by Pierre Terdiman, 2000 (~20-30% faster on my Celeron 500)
+ @cite Optimized code by Pierre Terdiman, 2000 (~20-30% faster on Celeron 500)
@cite Epsilon value added by Klaus Hartmann
@cite http://www.codercorner.com/RayAABB.cpp
*/
@@ -639,6 +639,29 @@ public:
bool& inside = ignoreBool,
Vector3& normal = ignore);
+
+ /**
+ @brief Calculates intersection of a ray and a static
+ Axis-Aligned Box (AABox).
+
+ @note Avoids the sqrt from collisionTimeForMovingPointFixedAABox;
+ early-out branches and operations optimized for Intel Core2 architecture.
+
+ @param invDir 1/dir
+ @param location Location of collision. [Post Condition]
+ @param inside Does the ray originate inside the box? [Post Condition]
+
+ @return True if the ray hits the box
+ */
+ static bool __fastcall rayAABox(
+ const Ray& ray,
+ const Vector3& invDir,
+ const AABox& box,
+ const Vector3& boxCenter,
+ float boundingRadiusSquared,
+ Vector3& location,
+ bool& inside);
+
/**
Calculates time between the intersection of a moving point and a fixed
sphere.
@@ -648,11 +671,12 @@ public:
@param point Moving point.
@param velocity Point's velocity.
- @param Sphere Fixed Sphere.
- @param location Location of collision. [Post Condition]
+ @param sphere Fixed Sphere.
+ @param outLocation Location of collision. [Post Condition]
@param outNormal Sphere's surface normal to collision [Post Condition]
+ \param solid If true, rays inside the sphere immediately intersect (good for collision detection). If false, they hit the opposite side of the sphere (good for ray tracing).
- @return Time til collision. If there is no collision then the return
+ @return Time until collision. If there is no collision then the return
value will be inf().
*/
static float collisionTimeForMovingPointFixedSphere(
@@ -660,7 +684,8 @@ public:
const Vector3& velocity,
const class Sphere& sphere,
Vector3& outLocation,
- Vector3& outNormal = ignore);
+ Vector3& outNormal = ignore,
+ bool solid = false);
/**
Calculates time between the intersection of a moving point and a fixed
@@ -721,7 +746,7 @@ public:
@param point Moving point.
@param velocity Point's velocity.
@param capsule Fixed capsule.
- @param location Location of collision. [Post Condition]
+ @param outLocation Location of collision. [Post Condition]
@param outNormal Capsule's surface normal to collision [Post Condition]
@return Time til collision. If there is no collision then the return
@@ -741,7 +766,7 @@ public:
@param sphere Moving sphere.
@param velocity Sphere's velocity.
@param plane Fixed Plane.
- @param location Location of collision -- not center position of sphere
+ @param outLocation Location of collision -- not center position of sphere
at the collision time. [Post Condition]
@param outNormal Box's surface normal to collision [Post Condition]
@@ -761,10 +786,11 @@ public:
@param sphere Moving sphere.
@param velocity Sphere's velocity.
- @param triangle Fixed Triangle.
- @param location Location of collision -- not center position of sphere
- at the collision time. [Post Condition]
- @param outNormal Box's surface normal to collision [Post Condition]
+ @param triangle Fixed Triangle. (collisions can happen on the back side of the triangle)
+ @param outLocation Location of collision, if collision occurs -- not center position of sphere
+ at the collision time. If there is interpenetration at the start, this point may be inside
+ the sphere.
+ @param b Barycentric coordinates. These are not valid unless collision occurs.
@return Time til collision. If there is no collision then the return
value will be inf().
@@ -772,9 +798,9 @@ public:
static float collisionTimeForMovingSphereFixedTriangle(
const class Sphere& sphere,
const Vector3& velocity,
- const Triangle& triangle,
+ const Triangle& triangle,
Vector3& outLocation,
- Vector3& outNormal = ignore);
+ float b[3] = (float*)&ignore);
/**
Calculates time between the intersection of a moving sphere and a fixed
@@ -786,7 +812,7 @@ public:
@param v1 Rectangle vertex 2.
@param v2 Rectangle vertex 3
@param v3 Rectangle vertex 4.
- @param location Location of collision -- not center position of sphere
+ @param outLocation Location of collision -- not center position of sphere
at the collision time. [Post Condition]
@param outNormal Box's surface normal to collision [Post Condition]
@@ -827,29 +853,29 @@ public:
Vector3& outLocation,
Vector3& outNormal = ignore);
- /**
- Calculates time between the intersection of a moving sphere and a fixed
- sphere.
+ /** Calculates time between the intersection of a moving sphere
+ and a fixed sphere.
- @note This won't detect a collision if the sphere is already interpenetrating
- the fixed sphere.
-
- @param movingSphere Moving sphere.
- @param velocity Sphere's velocity.
- @param fixedSphere Fixed Sphere.
- @param location Location of collision -- not center position of sphere
- at the collision time. [Post Condition]
- @param outNormal Sphere's surface normal to collision [Post Condition]
-
- @return Time til collision. If there is no collision then the return
- value will be inf().
- */
- static float collisionTimeForMovingSphereFixedSphere(
- const class Sphere& sphere,
- const Vector3& velocity,
- const class Sphere& fixedSphere,
- Vector3& outLocation,
- Vector3& outNormal = ignore);
+ If they are already interpenetrating, returns 0 and @a
+ location is the closest point on the surface of the fixed sphere
+ to the center of the moving sphere.
+
+ @param sphere Moving sphere.
+ @param velocity Sphere's velocity.
+ @param fixedSphere Fixed Sphere.
+ @param outLocation Location of collision -- not center position of sphere
+ at the collision time. [Post Condition]
+ @param outNormal Moving sphere's surface normal to collision [Post Condition]
+
+ @return Time until collision. If there is no collision then the return
+ value will be inf().
+ */
+ static float collisionTimeForMovingSphereFixedSphere(
+ const Sphere& sphere,
+ const Vector3& velocity,
+ const Sphere& fixedSphere,
+ Vector3& outLocation,
+ Vector3& outNormal = ignore);
/**
Calculates time between the intersection of a moving sphere and a fixed
@@ -940,8 +966,8 @@ public:
and direction can be used in this function if already pre-calculated. This
prevents doing the same work twice.
- @param v0 line vertex 1.
- @param v1 line vertex 2.
+ @param v0 line vertex 0.
+ @param v1 line vertex 1.
@param edgeDirection The direction of the segment (unit length).
@param edgeLength The length of the segment.
@param point External point.
@@ -952,22 +978,22 @@ public:
const Vector3& v0,
const Vector3& v1,
const Vector3& edgeDirection,
- float edgeLength,
+ float edgeLength,
const Vector3& point);
/**
Finds the closest point on the perimeter of the triangle to an external point;
given a triangle defined by three points v0, v1, & v2, and the external point.
- @param v0 Triangle vertex 1.
- @param v1 Triangle vertex 2.
- @param v2 Triangle vertex 3.
+ @param v0 Triangle vertex 0.
+ @param v1 Triangle vertex 1.
+ @param v2 Triangle vertex 2.
@param point External point.
@return Closests point to point on the perimeter of the
triangle.
*/
- static Vector3 closestPointToTrianglePerimeter(
+ static Vector3 closestPointOnTrianglePerimeter(
const Vector3& v0,
const Vector3& v1,
const Vector3& v2,
@@ -982,42 +1008,56 @@ public:
and direction can be used in this function if already pre-calculated. This
prevents doing the same work twice.
- @param v0 Triangle vertex 1.
- @param v1 Triangle vertex 2.
- @param v2 Triangle vertex 3.
- @param point External point.
+ @param v Triangle vertices.
+ @param point External point.
+ @param edgeIndex The point lies on the edge between v[edgeIndex] and v[(edgeIndex + 1) % 3]
- @return Closests point to point on the perimeter of the
+ @return Closest point to point on the perimeter of the
triangle.
*/
- static Vector3 closestPointToTrianglePerimeter(
+ static Vector3 closestPointOnTrianglePerimeter(
const Vector3 v[3],
const Vector3 edgeDirection[3],
- const double edgeLength[3],
- const Vector3& point);
+ const float edgeLength[3],
+ const Vector3& point,
+ int& edgeIndex);
/**
Tests whether a point is contained within the triangle defined by
- v0, v1, & v2 and its plane's normal.
+ v0, v1, and v2 and its plane's normal.
- @param v0 Triangle vertex 1.
- @param v1 Triangle vertex 2.
- @param v2 Triangle vertex 3.
+ @param v0 Triangle vertex 0.
+ @param v1 Triangle vertex 1.
+ @param v2 Triangle vertex 2.
@param normal Normal to triangle's plane.
@param point The point in question.
@param primaryAxis Primary axis of triangle. This will be detected
if not given. This parameter is provided as an optimization.
+ @param b Barycentric coordinates; b[i] is the weight on v[i]
@return true - if point is inside the triangle.
@return false - otherwise
*/
static bool isPointInsideTriangle(
+ const Vector3& v0,
+ const Vector3& v1,
+ const Vector3& v2,
+ const Vector3& normal,
+ const Vector3& point,
+ float b[3],
+ Vector3::Axis primaryAxis = Vector3::DETECT_AXIS);
+
+ inline static bool isPointInsideTriangle(
const Vector3& v0,
const Vector3& v1,
const Vector3& v2,
const Vector3& normal,
const Vector3& point,
- Vector3::Axis primaryAxis = Vector3::DETECT_AXIS);
+ Vector3::Axis primaryAxis = Vector3::DETECT_AXIS) {
+
+ float b[3];
+ return isPointInsideTriangle(v0, v1, v2, normal, point, b, primaryAxis);
+ }
/**
Tests for the intersection of a moving sphere and a fixed box in a
@@ -1088,6 +1128,14 @@ public:
const Sphere& sphere,
const Box& box);
+ static bool fixedSolidSphereIntersectsFixedTriangle(
+ const Sphere& sphere,
+ const Triangle& triangle);
+
+ static bool fixedSolidBoxIntersectsFixedTriangle(
+ const AABox& box,
+ const Triangle& triangle);
+
/**
Tests whether a point is inside a rectangle defined by the vertexes
v0, v1, v2, & v3, and the rectangle's plane normal.
diff --git a/dep/include/g3dlite/G3D/Color1.h b/dep/include/g3dlite/G3D/Color1.h
new file mode 100644
index 000000000..0f68c84b3
--- /dev/null
+++ b/dep/include/g3dlite/G3D/Color1.h
@@ -0,0 +1,144 @@
+/**
+ @file Color1.h
+
+ Monochrome Color class
+
+ @maintainer Morgan McGuire, http://graphics.cs.williams.edu
+ @created 2007-01-31
+ @edited 2009-03-20
+
+ Copyright 2000-2009, Morgan McGuire.
+ All rights reserved.
+ */
+
+#ifndef G3D_COLOR1_H
+#define G3D_COLOR1_H
+
+#include "G3D/platform.h"
+#include "G3D/g3dmath.h"
+#include "G3D/HashTrait.h"
+#include
+
+namespace G3D {
+
+/**
+ Monochrome color. This is just a float, but it has nice semantics
+ because a scaling by 255 automatically occurs when switching between
+ fixed point (Color1uint8) and floating point (Color1) formats.
+ */
+class Color1 {
+private:
+ // Hidden operators
+ bool operator<(const Color1&) const;
+ bool operator>(const Color1&) const;
+ bool operator<=(const Color1&) const;
+ bool operator>=(const Color1&) const;
+
+public:
+ float value;
+
+ /**
+ Initializes to 0
+ */
+ inline Color1() : value(0) {}
+
+ Color1(class BinaryInput& bi);
+
+ inline explicit Color1(float v) : value(v) {
+ }
+
+ inline bool isZero() const {
+ return value == 0.0f;
+ }
+
+ inline bool isOne() const {
+ return value == 1.0f;
+ }
+
+ static const Color1& one();
+
+ static const Color1& zero();
+
+ /** Returns the value three times */
+ class Color3 rgb() const;
+
+ Color1 (const class Color1uint8& other);
+
+ void serialize(class BinaryOutput& bo) const;
+ void deserialize(class BinaryInput& bi);
+
+ Color1 operator+ (const Color1& other) const {
+ return Color1(value + other.value);
+ }
+
+ Color1 operator+ (const float other) const {
+ return Color1(value + other);
+ }
+
+ Color1& operator+= (const Color1 other) {
+ value += other.value;
+ return *this;
+ }
+
+ Color1& operator-= (const Color1 other) {
+ value -= other.value;
+ return *this;
+ }
+
+ Color1 operator- (const Color1& other) const {
+ return Color1(value - other.value);
+ }
+
+ Color1 operator- (const float other) const {
+ return Color1(value - other);
+ }
+
+ Color1 operator- () const {
+ return Color1(-value);
+ }
+
+ Color1 operator* (const Color1& other) const {
+ return Color1(value * other.value);
+ }
+
+ Color1 operator* (const float other) const {
+ return Color1(value * other);
+ }
+
+ Color1 operator/ (const Color1& other) const {
+ return Color1(value / other.value);
+ }
+
+ Color1 operator/ (const float other) const {
+ return Color1(value / other);
+ }
+
+ inline Color1 max(const Color1& other) const {
+ return Color1(G3D::max(value, other.value));
+ }
+
+ inline Color1 min(const Color1& other) const {
+ return Color1(G3D::min(value, other.value));
+ }
+
+ inline Color1 lerp(const Color1& other, float a) const {
+ return Color1(value + (other.value - value) * a);
+
+ }
+
+ inline size_t hashCode() const {
+ return (size_t)(value * 0xFFFFFF);
+ }
+};
+
+}
+
+template <>
+struct HashTrait {
+ static size_t hashCode(const G3D::Color1& key) {
+ return key.hashCode();
+ }
+};
+
+
+#endif
diff --git a/dep/include/g3dlite/G3D/Color1uint8.h b/dep/include/g3dlite/G3D/Color1uint8.h
new file mode 100644
index 000000000..092099d0d
--- /dev/null
+++ b/dep/include/g3dlite/G3D/Color1uint8.h
@@ -0,0 +1,91 @@
+/**
+ @file Color1uint8.h
+
+ @maintainer Morgan McGuire, graphics3d.com
+
+ @created 2007-01-30
+ @edited 2007-01-30
+
+ Copyright 2000-2007, Morgan McGuire.
+ All rights reserved.
+ */
+
+#ifndef G3D_COLOR1UINT8_H
+#define G3D_COLOR1UINT8_H
+
+#include "G3D/platform.h"
+#include "G3D/g3dmath.h"
+
+namespace G3D {
+
+/**
+ Represents a Color1 as a packed integer. Convenient
+ for creating unsigned int vertex arrays.
+
+ WARNING: Integer color formats are different than
+ integer vertex formats. The color channels are automatically
+ scaled by 255 (because OpenGL automatically scales integer
+ colors back by this factor). So Color3(1,1,1) == Color3uint8(255,255,255)
+ but Vector3(1,1,1) == Vector3int16(1,1,1).
+
+ Note:
+ Conversion of a float32 to uint8 is accomplished by min(iFloor(f * 256)) and
+ back to float32 by u / 255.0f. This gives equal size intervals.
+Consider a number line from 0 to 1 and a corresponding one from 0 to 255. If we use iRound(x * 255), then the mapping for three critical intervals are:
+
+
+let s = 0.5/255
+ float int size
+[0, s) -> 0 s
+[s, s * 3) -> 1 2*s
+(1 - s, 1] -> 255 s
+
+
+If we use max(floor(x * 256), 255), then we get:
+
+
+let s = 1/256
+ float int size
+[0, s) -> 0 s
+[s, 2 * s) -> 1 s
+(1 - s, 1] -> 255 s
+
+and the intervals are all the same size, thus giving equal precision to all values.
+ */
+G3D_BEGIN_PACKED_CLASS(1)
+class Color1uint8 {
+private:
+ // Hidden operators
+ bool operator<(const Color1uint8&) const;
+ bool operator>(const Color1uint8&) const;
+ bool operator<=(const Color1uint8&) const;
+ bool operator>=(const Color1uint8&) const;
+
+public:
+
+ uint8 value;
+
+ Color1uint8() : value(0) {}
+
+ explicit Color1uint8(const uint8 _v) : value(_v) {}
+
+ Color1uint8(const class Color1& c);
+
+ Color1uint8(class BinaryInput& bi);
+
+ void serialize(class BinaryOutput& bo) const;
+
+ void deserialize(class BinaryInput& bi);
+
+ inline bool operator==(const Color1uint8& other) const {
+ return value == other.value;
+ }
+
+ inline bool operator!=(const Color1uint8& other) const {
+ return value != other.value;
+ }
+
+}
+G3D_END_PACKED_CLASS(1)
+}
+#endif
diff --git a/dep/include/g3dlite/G3D/Color3.h b/dep/include/g3dlite/G3D/Color3.h
new file mode 100644
index 000000000..bffe434fc
--- /dev/null
+++ b/dep/include/g3dlite/G3D/Color3.h
@@ -0,0 +1,432 @@
+/**
+ @file Color3.h
+
+ Color class
+
+ @maintainer Morgan McGuire, http://graphics.cs.williams.edu
+ @cite Portions based on Dave Eberly's Magic Software Library
+ at http://www.magic-software.com
+
+ @created 2001-06-02
+ @edited 2009-04-28
+
+ Copyright 2000-2009, Morgan McGuire.
+ All rights reserved.
+ */
+
+#ifndef G3D_Color3_h
+#define G3D_Color3_h
+
+#include "G3D/platform.h"
+#include "G3D/g3dmath.h"
+#include "G3D/HashTrait.h"
+#include "G3D/Color1.h"
+#include
+
+namespace G3D {
+class Any;
+
+/**
+ Do not subclass-- this implementation makes assumptions about the
+ memory layout.
+ */
+class Color3 {
+private:
+ // Hidden operators
+ bool operator<(const Color3&) const;
+ bool operator>(const Color3&) const;
+ bool operator<=(const Color3&) const;
+ bool operator>=(const Color3&) const;
+
+public:
+ /**
+ Does not initialize fields.
+ */
+ Color3();
+
+ /** \param any Must be in one of the following forms:
+ - Color3(#, #, #)
+ - Color3::fromARGB(#)
+ - Color3{r = #, g = #, b = #)
+ - Color3::one()
+ - Color3::zero()
+ */
+ Color3(const Any& any);
+
+ /** Converts the Color3 to an Any. */
+ operator Any() const;
+
+ explicit Color3(class BinaryInput& bi);
+
+ Color3(float r, float g, float b);
+ Color3(float v) : r(v), g(v), b(v) {}
+
+ explicit Color3(const class Vector3& v);
+
+ explicit Color3(const float value[3]);
+
+ /** Returns this color */
+ const Color3& rgb() const {
+ return *this;
+ }
+
+ /**
+ Initialize from another color.
+ */
+ Color3 (const Color3& other);
+
+ Color3 (const class Color3uint8& other);
+
+ inline bool isZero() const {
+ return (r == 0.0f) && (g == 0.0f) && (b == 0.0f);
+ }
+
+ inline bool isOne() const {
+ return (r == 1.0f) && (g == 1.0f) && (b == 1.0f);
+ }
+
+ bool isFinite() const;
+
+ /**
+ Initialize from an HTML-style color (e.g. 0xFF0000 == RED)
+ */
+ static Color3 fromARGB(uint32);
+
+ /** Returns one of the color wheel colors (e.g. RED, GREEN, CYAN).
+ Does not include white, black, or gray. */
+ static const Color3& wheelRandom();
+
+ /** Generate colors according to the ANSI color set, mod 16.
+ \sa pastelMap */
+ static Color3 ansiMap(uint32 i);
+
+ /**
+ Generate colors using a hash such that adjacent values
+ are unlikely to have similar colors.
+
+ Useful for rendering with
+ stable but arbitrary colors, e.g., when debugging a mesh
+ algorithm.
+
+ \sa ansiMap
+ */
+ static Color3 pastelMap(uint32 i);
+
+ /**
+ * Channel value.
+ */
+ float r, g, b;
+
+ void serialize(class BinaryOutput& bo) const;
+ void deserialize(class BinaryInput& bi);
+
+ // access vector V as V[0] = V.r, V[1] = V.g, V[2] = V.b
+ //
+ // WARNING. These member functions rely on
+ // (1) Color3 not having virtual functions
+ // (2) the data packed in a 3*sizeof(float) memory block
+ const float& operator[] (int i) const;
+ float& operator[] (int i);
+
+ // assignment and comparison
+ Color3& operator= (const Color3& rkVector);
+ bool operator== (const Color3& rkVector) const;
+ bool operator!= (const Color3& rkVector) const;
+ size_t hashCode() const;
+
+ // arithmetic operations
+ Color3 operator+ (const Color3& rkVector) const;
+ Color3 operator- (const Color3& rkVector) const;
+ inline Color3 operator* (float s) const {
+ return Color3(r * s, g * s, b * s);
+ }
+ Color3 operator* (const Color3& rkVector) const;
+ inline Color3 operator/ (float fScalar) const {
+ return (*this) * (1.0f / fScalar);
+ }
+ Color3 operator- () const;
+
+ // arithmetic updates
+ Color3& operator+= (const Color3& rkVector);
+ Color3& operator-= (const Color3& rkVector);
+ Color3& operator*= (const Color3& rkVector);
+ Color3& operator*= (float fScalar);
+ Color3& operator/= (float fScalar);
+
+ bool fuzzyEq(const Color3& other) const;
+ bool fuzzyNe(const Color3& other) const;
+
+ // vector operations
+ float length () const;
+ Color3 direction() const;
+ float squaredLength () const;
+ float dot (const Color3& rkVector) const;
+ float unitize (float fTolerance = 1e-06);
+ Color3 cross (const Color3& rkVector) const;
+ Color3 unitCross (const Color3& rkVector) const;
+
+ inline Color3 pow(const Color3& other) const {
+ return Color3(::pow(r, other.r), ::pow(g, other.g), ::pow(b, other.b));
+ }
+
+ inline Color3 pow(float other) const {
+ return Color3(::pow(r, other), ::pow(g, other), ::pow(b, other));
+ }
+
+ inline Color3 max(const Color3& other) const {
+ return Color3(G3D::max(r, other.r), G3D::max(g, other.g), G3D::max(b, other.b));
+ }
+
+ inline Color3 min(const Color3& other) const {
+ return Color3(G3D::min(r, other.r), G3D::min(g, other.g), G3D::min(b, other.b));
+ }
+
+ /** Smallest element */
+ inline float min() const {
+ return G3D::min(G3D::min(r, g), b);
+ }
+
+ /** Largest element */
+ inline float max() const {
+ return G3D::max(G3D::max(r, g), b);
+ }
+
+ inline Color3 lerp(const Color3& other, float a) const {
+ return (*this) + (other - *this) * a;
+
+ }
+
+ inline float sum() const {
+ return r + g + b;
+ }
+
+ inline float average() const {
+ return sum() / 3.0f;
+ }
+
+
+ /**
+ * Converts from HSV to RGB , note: toHSV(fromHSV(_hsv)) may not be _hsv, if it is at a grey point or black point.
+ * The components of _hsv should lie in the unit interval.
+ * @cite Alvy Ray Smith SIGGRAPH 1978 "Color Gamut Transform Pairs"
+ **/
+ static Color3 fromHSV(const Vector3& _hsv);
+ static Vector3 toHSV(const Color3& _rgb);
+
+ /** Duplicates the matlab jet colormap maps [0,1] --> (r,g,b) where blue is close to 0 and red is close to 1. */
+ static Color3 jetColorMap(const float& val);
+
+ /** Returns colors with maximum saturation and value @param hue [0, 1]*/
+ static Color3 rainbowColorMap(float hue);
+
+ std::string toString() const;
+
+ /** Random unit vector */
+ static Color3 random();
+
+ // Special values.
+ // Intentionally not inlined: see Matrix3::identity() for details.
+ static const Color3& red();
+ static const Color3& green();
+ static const Color3& blue();
+ static const Color3& purple();
+ static const Color3& cyan();
+ static const Color3& yellow();
+ static const Color3& brown();
+ static const Color3& orange();
+ static const Color3& black();
+ static const Color3& gray();
+ static const Color3& white();
+
+ static const Color3& zero();
+ static const Color3& one();
+
+ inline Color3 bgr() const {
+ return Color3(b, g, r);
+ }
+};
+
+inline G3D::Color3 operator* (float s, const G3D::Color3& c) {
+ return c * s;
+}
+
+inline G3D::Color3 operator* (G3D::Color1& s, const G3D::Color3& c) {
+ return c * s.value;
+}
+
+inline G3D::Color3 operator* (const G3D::Color3& c, G3D::Color1& s) {
+ return c * s.value;
+}
+
+
+//----------------------------------------------------------------------------
+inline Color3::Color3 () {
+}
+
+//----------------------------------------------------------------------------
+
+inline Color3::Color3(float fX, float fY, float fZ) {
+ r = fX;
+ g = fY;
+ b = fZ;
+}
+
+//----------------------------------------------------------------------------
+inline Color3::Color3(const float afCoordinate[3]) {
+ r = afCoordinate[0];
+ g = afCoordinate[1];
+ b = afCoordinate[2];
+}
+
+//----------------------------------------------------------------------------
+inline Color3::Color3 (const Color3& rkVector) {
+ r = rkVector.r;
+ g = rkVector.g;
+ b = rkVector.b;
+}
+
+//----------------------------------------------------------------------------
+inline float& Color3::operator[] (int i) {
+ return ((float*)this)[i];
+}
+
+//----------------------------------------------------------------------------
+
+inline const float& Color3::operator[] (int i) const {
+ return ((float*)this)[i];
+}
+
+//----------------------------------------------------------------------------
+
+inline bool Color3::fuzzyEq(const Color3& other) const {
+ return G3D::fuzzyEq((*this - other).squaredLength(), 0);
+}
+
+//----------------------------------------------------------------------------
+
+inline bool Color3::fuzzyNe(const Color3& other) const {
+ return G3D::fuzzyNe((*this - other).squaredLength(), 0);
+}
+
+
+//----------------------------------------------------------------------------
+inline Color3& Color3::operator= (const Color3& rkVector) {
+ r = rkVector.r;
+ g = rkVector.g;
+ b = rkVector.b;
+ return *this;
+}
+
+//----------------------------------------------------------------------------
+inline bool Color3::operator== (const Color3& rkVector) const {
+ return ( r == rkVector.r && g == rkVector.g && b == rkVector.b );
+}
+
+//----------------------------------------------------------------------------
+inline bool Color3::operator!= (const Color3& rkVector) const {
+ return ( r != rkVector.r || g != rkVector.g || b != rkVector.b );
+}
+
+//----------------------------------------------------------------------------
+inline Color3 Color3::operator+ (const Color3& rkVector) const {
+ return Color3(r + rkVector.r, g + rkVector.g, b + rkVector.b);
+}
+
+//----------------------------------------------------------------------------
+inline Color3 Color3::operator- (const Color3& rkVector) const {
+ return Color3(r -rkVector.r, g - rkVector.g, b - rkVector.b);
+}
+
+//----------------------------------------------------------------------------
+inline Color3 Color3::operator* (const Color3& rkVector) const {
+ return Color3(r * rkVector.r, g * rkVector.g, b * rkVector.b);
+}
+
+//----------------------------------------------------------------------------
+inline Color3 Color3::operator- () const {
+ return Color3( -r, -g, -b);
+}
+
+//----------------------------------------------------------------------------
+inline Color3& Color3::operator+= (const Color3& rkVector) {
+ r += rkVector.r;
+ g += rkVector.g;
+ b += rkVector.b;
+ return *this;
+}
+
+//----------------------------------------------------------------------------
+inline Color3& Color3::operator-= (const Color3& rkVector) {
+ r -= rkVector.r;
+ g -= rkVector.g;
+ b -= rkVector.b;
+ return *this;
+}
+
+//----------------------------------------------------------------------------
+inline Color3& Color3::operator*= (float fScalar) {
+ r *= fScalar;
+ g *= fScalar;
+ b *= fScalar;
+ return *this;
+}
+
+//----------------------------------------------------------------------------
+inline Color3& Color3::operator*= (const Color3& rkVector) {
+ r *= rkVector.r;
+ g *= rkVector.g;
+ b *= rkVector.b;
+ return *this;
+}
+//----------------------------------------------------------------------------
+inline float Color3::squaredLength () const {
+ return r*r + g*g + b*b;
+}
+
+//----------------------------------------------------------------------------
+inline float Color3::length () const {
+ return sqrtf(r*r + g*g + b*b);
+}
+
+//----------------------------------------------------------------------------
+inline Color3 Color3::direction () const {
+ float lenSquared = r * r + g * g + b * b;
+
+ if (lenSquared != 1.0f) {
+ return *this / sqrtf(lenSquared);
+ } else {
+ return *this;
+ }
+}
+
+//----------------------------------------------------------------------------
+inline float Color3::dot (const Color3& rkVector) const {
+ return r*rkVector.r + g*rkVector.g + b*rkVector.b;
+}
+
+//----------------------------------------------------------------------------
+inline Color3 Color3::cross (const Color3& rkVector) const {
+ return Color3(g*rkVector.b - b*rkVector.g, b*rkVector.r - r*rkVector.b,
+ r*rkVector.g - g*rkVector.r);
+}
+
+//----------------------------------------------------------------------------
+inline Color3 Color3::unitCross (const Color3& rkVector) const {
+ Color3 kCross(g*rkVector.b - b*rkVector.g, b*rkVector.r - r*rkVector.b,
+ r*rkVector.g - g*rkVector.r);
+ kCross.unitize();
+ return kCross;
+}
+
+
+} // namespace
+
+
+template <> struct HashTrait {
+ static size_t hashCode(const G3D::Color3& key) {
+ return key.hashCode();
+ }
+};
+
+
+#endif
diff --git a/dep/include/g3dlite/G3D/Color3uint8.h b/dep/include/g3dlite/G3D/Color3uint8.h
new file mode 100644
index 000000000..bd4b00d7f
--- /dev/null
+++ b/dep/include/g3dlite/G3D/Color3uint8.h
@@ -0,0 +1,110 @@
+/**
+ @file Color3uint8.h
+
+ @maintainer Morgan McGuire, graphics3d.com
+
+ @created 2003-04-07
+ @edited 2006-06-24
+
+ Copyright 2000-2006, Morgan McGuire.
+ All rights reserved.
+ */
+
+#ifndef G3D_COLOR3UINT8_H
+#define G3D_COLOR3UINT8_H
+
+#include "G3D/platform.h"
+#include "G3D/g3dmath.h"
+
+namespace G3D {
+
+/**
+ Represents a Color3 as a packed integer. Convenient
+ for creating unsigned int vertex arrays. Used by
+ G3D::GImage as the underlying format.
+
+ WARNING: Integer color formats are different than
+ integer vertex formats. The color channels are automatically
+ scaled by 255 (because OpenGL automatically scales integer
+ colors back by this factor). So Color3(1,1,1) == Color3uint8(255,255,255)
+ but Vector3(1,1,1) == Vector3int16(1,1,1).
+ */
+
+G3D_BEGIN_PACKED_CLASS(1)
+
+class Color3uint8 {
+private:
+ // Hidden operators
+ bool operator<(const Color3uint8&) const;
+ bool operator>(const Color3uint8&) const;
+ bool operator<=(const Color3uint8&) const;
+ bool operator>=(const Color3uint8&) const;
+
+public:
+ uint8 r;
+ uint8 g;
+ uint8 b;
+
+ Color3uint8() : r(0), g(0), b(0) {}
+
+ Color3uint8(const uint8 _r, const uint8 _g, const uint8 _b) : r(_r), g(_g), b(_b) {}
+
+ Color3uint8(const class Color3& c);
+
+ Color3uint8(class BinaryInput& bi);
+
+ inline static Color3uint8 fromARGB(uint32 i) {
+ Color3uint8 c;
+ c.r = (i >> 16) & 0xFF;
+ c.g = (i >> 8) & 0xFF;
+ c.b = i & 0xFF;
+ return c;
+ }
+
+ inline Color3uint8 bgr() const {
+ return Color3uint8(b, g, r);
+ }
+
+ /**
+ Returns the color packed into a uint32
+ (the upper byte is 0xFF)
+ */
+ inline uint32 asUInt32() const {
+ return (0xFF << 24) + ((uint32)r << 16) + ((uint32)g << 8) + b;
+ }
+
+ void serialize(class BinaryOutput& bo) const;
+
+ void deserialize(class BinaryInput& bi);
+
+ // access vector V as V[0] = V.r, V[1] = V.g, V[2] = V.b
+ //
+ // WARNING. These member functions rely on
+ // (1) Color3 not having virtual functions
+ // (2) the data packed in a 3*sizeof(uint8) memory block
+ uint8& operator[] (int i) const {
+ debugAssert((unsigned int)i < 3);
+ return ((uint8*)this)[i];
+ }
+
+ operator uint8* () {
+ return (G3D::uint8*)this;
+ }
+
+ operator const uint8* () const {
+ return (uint8*)this;
+ }
+
+ bool operator==(const Color3uint8& other) const {
+ return (other.r == r) && (other.g == g) && (other.b == b);
+ }
+
+ bool operator!=(const Color3uint8& other) const {
+ return (other.r != r) && (other.g != g) && (other.b != b);
+ }
+}
+G3D_END_PACKED_CLASS(1)
+
+} // namespace G3D
+
+#endif
diff --git a/dep/include/g3dlite/G3D/Color4.h b/dep/include/g3dlite/G3D/Color4.h
new file mode 100644
index 000000000..d8858abbc
--- /dev/null
+++ b/dep/include/g3dlite/G3D/Color4.h
@@ -0,0 +1,338 @@
+/**
+ @file Color4.h
+
+ Color class
+
+ @maintainer Morgan McGuire, http://graphics.cs.williams.edu
+ @cite Portions based on Dave Eberly's Magic Software Library
+ at http://www.magic-software.com
+
+ @created 2002-06-25
+ @edited 2009-11-15
+
+ Copyright 2000-2009, Morgan McGuire.
+ All rights reserved.
+ */
+
+#ifndef G3D_Color4_h
+#define G3D_Color4_h
+
+#include "G3D/platform.h"
+#include "G3D/g3dmath.h"
+#include "G3D/Color3.h"
+#include
+
+namespace G3D {
+
+class Any;
+
+/**
+ Do not subclass-- this implementation makes assumptions about the
+ memory layout.
+ */
+class Color4 {
+private:
+ // Hidden operators
+ bool operator<(const Color4&) const;
+ bool operator>(const Color4&) const;
+ bool operator<=(const Color4&) const;
+ bool operator>=(const Color4&) const;
+
+public:
+
+ /** \param any Must be in one of the following forms:
+ - Color4(#, #, #, #)
+ - Color4::fromARGB(#)
+ - Color4{r = #, g = #, b = #, a = #)
+ */
+ Color4(const Any& any);
+
+ /** Converts the Color4 to an Any. */
+ operator Any() const;
+
+ /**
+ * Does not initialize fields.
+ */
+ Color4 ();
+
+ Color4(const Color3& c3, float a = 1.0);
+
+ Color4(const class Color4uint8& c);
+
+ Color4(class BinaryInput& bi);
+
+ Color4(const class Vector4& v);
+
+ Color4(float r, float g, float b, float a = 1.0);
+
+ static const Color4& one();
+
+ Color4(float value[4]);
+
+ /**
+ * Initialize from another color.
+ */
+ Color4(const Color4& other);
+
+
+ inline bool isZero() const {
+ return (r == 0.0f) && (g == 0.0f) && (b == 0.0f) && (a == 0.0f);
+ }
+
+ inline bool isOne() const {
+ return (r == 1.0f) && (g == 1.0f) && (b == 1.0f) && (a == 1.0f);
+ }
+
+ void serialize(class BinaryOutput& bo) const;
+ void deserialize(class BinaryInput& bi);
+
+ /**
+ Initialize from an HTML-style color (e.g. 0xFFFF0000 == RED)
+ */
+ static Color4 fromARGB(uint32);
+
+ /**
+ * Channel values.
+ */
+ float r, g, b, a;
+
+ inline Color3 rgb() const {
+ return Color3(r, g, b);
+ }
+
+ // access vector V as V[0] = V.r, V[1] = V.g, V[2] = V.b, v[3] = V.a
+ //
+ // WARNING. These member functions rely on
+ // (1) Color4 not having virtual functions
+ // (2) the data packed in a 3*sizeof(float) memory block
+ float& operator[] (int i) const;
+
+ // assignment and comparison
+ Color4& operator= (const Color4& rkVector);
+ bool operator== (const Color4& rkVector) const;
+ bool operator!= (const Color4& rkVector) const;
+ size_t hashCode() const;
+
+ // arithmetic operations
+ Color4 operator+ (const Color4& rkVector) const;
+ Color4 operator- (const Color4& rkVector) const;
+ Color4 operator* (float fScalar) const;
+ inline Color4 operator* (const Color4& k) const {
+ return Color4(r*k.r, g*k.g, b*k.b, a * k.a);
+ }
+ Color4 operator/ (float fScalar) const;
+ Color4 operator- () const;
+ friend Color4 operator* (double fScalar, const Color4& rkVector);
+
+ // arithmetic updates
+ Color4& operator+= (const Color4& rkVector);
+ Color4& operator-= (const Color4& rkVector);
+ Color4& operator*= (float fScalar);
+ Color4& operator/= (float fScalar);
+
+ bool fuzzyEq(const Color4& other) const;
+ bool fuzzyNe(const Color4& other) const;
+
+ std::string toString() const;
+
+ inline Color4 max(const Color4& other) const {
+ return Color4(G3D::max(r, other.r), G3D::max(g, other.g), G3D::max(b, other.b), G3D::max(a, other.a));
+ }
+
+ inline Color4 min(const Color4& other) const {
+ return Color4(G3D::min(r, other.r), G3D::min(g, other.g), G3D::min(b, other.b), G3D::min(a, other.a));
+ }
+
+ /** r + g + b + a */
+ inline float sum() const {
+ return r + g + b + a;
+ }
+
+ inline Color4 lerp(const Color4& other, float a) const {
+ return (*this) + (other - *this) * a;
+
+ }
+
+ // Special values.
+ // Intentionally not inlined: see Matrix3::identity() for details.
+ static const Color4& zero();
+ static const Color4& clear();
+
+ static const Color4& inf();
+ static const Color4& nan();
+
+ inline bool isFinite() const {
+ return G3D::isFinite(r) && G3D::isFinite(g) && G3D::isFinite(b) && G3D::isFinite(a);
+ }
+
+ inline Color3 bgr() const {
+ return Color3(b, g, r);
+ }
+};
+
+/**
+ Extends the c3 with alpha = 1.0
+ */
+Color4 operator*(const Color3& c3, const Color4& c4);
+
+
+inline Color4 operator*(const Color3& c3, const Color4& c4) {
+ return Color4(c3.r * c4.r, c3.g * c4.g, c3.b * c4.b, c4.a);
+}
+
+//----------------------------------------------------------------------------
+
+inline Color4::Color4 () {
+ // For efficiency in construction of large arrays of vectors, the
+ // default constructor does not initialize the vector.
+}
+
+//----------------------------------------------------------------------------
+
+inline Color4::Color4(const Color3& c3, float a) {
+ r = c3.r;
+ g = c3.g;
+ b = c3.b;
+ this->a = a;
+}
+
+//----------------------------------------------------------------------------
+
+inline Color4::Color4(
+ float r,
+ float g,
+ float b,
+ float a) :
+ r(r), g(g), b(b), a(a) {
+}
+
+//----------------------------------------------------------------------------
+inline Color4::Color4 (float afCoordinate[4]) {
+ r = afCoordinate[0];
+ g = afCoordinate[1];
+ b = afCoordinate[2];
+ a = afCoordinate[3];
+}
+
+//----------------------------------------------------------------------------
+
+inline Color4::Color4(
+ const Color4& other) {
+
+ r = other.r;
+ g = other.g;
+ b = other.b;
+ a = other.a;
+}
+
+//----------------------------------------------------------------------------
+
+inline float& Color4::operator[] (int i) const {
+ return ((float*)this)[i];
+}
+
+//----------------------------------------------------------------------------
+
+inline bool Color4::fuzzyEq(const Color4& other) const {
+ Color4 dif = (*this - other);
+ return G3D::fuzzyEq(dif.r * dif.r + dif.g * dif.g + dif.b * dif.b + dif.a * dif.a, 0);
+}
+
+//----------------------------------------------------------------------------
+
+inline bool Color4::fuzzyNe(const Color4& other) const {
+ Color4 dif = (*this - other);
+ return G3D::fuzzyNe(dif.r * dif.r + dif.g * dif.g + dif.b * dif.b + dif.a * dif.a, 0);
+}
+
+
+//----------------------------------------------------------------------------
+inline Color4& Color4::operator= (const Color4& other) {
+ r = other.r;
+ g = other.g;
+ b = other.b;
+ a = other.a;
+ return *this;
+}
+
+//----------------------------------------------------------------------------
+
+inline bool Color4::operator== (const Color4& other) const {
+ return ( r == other.r && g == other.g && b == other.b && a == other.a);
+}
+
+//----------------------------------------------------------------------------
+
+inline bool Color4::operator!= (const Color4& other) const {
+ return ( r != other.r || g != other.g || b != other.b || a != other.a);
+}
+
+//----------------------------------------------------------------------------
+inline Color4 Color4::operator+ (const Color4& other) const {
+ return Color4(r + other.r, g + other.g, b + other.b, a + other.a);
+}
+
+//----------------------------------------------------------------------------
+inline Color4 Color4::operator- (const Color4& other) const {
+ return Color4(r - other.r, g - other.g, b - other.b, a - other.a);
+}
+
+//----------------------------------------------------------------------------
+
+inline Color4 Color4::operator* (float fScalar) const {
+ return Color4(fScalar * r, fScalar * g, fScalar * b, fScalar * a);
+}
+
+//----------------------------------------------------------------------------
+
+inline Color4 Color4::operator- () const {
+ return Color4(-r, -g, -b, -a);
+}
+
+//----------------------------------------------------------------------------
+
+inline Color4 operator* (float fScalar, const Color4& other) {
+ return Color4(fScalar * other.r, fScalar * other.g,
+ fScalar * other.b, fScalar * other.a);
+}
+
+//----------------------------------------------------------------------------
+
+inline Color4& Color4::operator+= (const Color4& other) {
+ r += other.r;
+ g += other.g;
+ b += other.b;
+ a += other.a;
+ return *this;
+}
+
+//----------------------------------------------------------------------------
+
+inline Color4& Color4::operator-= (const Color4& other) {
+ r -= other.r;
+ g -= other.g;
+ b -= other.b;
+ a -= other.a;
+ return *this;
+}
+
+//----------------------------------------------------------------------------
+
+inline Color4& Color4::operator*= (float fScalar) {
+ r *= fScalar;
+ g *= fScalar;
+ b *= fScalar;
+ a *= fScalar;
+ return *this;
+}
+
+} // namespace
+
+template <>
+struct HashTrait {
+ static size_t hashCode(const G3D::Color4& key) {
+ return key.hashCode();
+ }
+};
+
+#endif
diff --git a/dep/include/g3dlite/G3D/Color4uint8.h b/dep/include/g3dlite/G3D/Color4uint8.h
new file mode 100644
index 000000000..ab8c07292
--- /dev/null
+++ b/dep/include/g3dlite/G3D/Color4uint8.h
@@ -0,0 +1,115 @@
+/**
+ @file Color4uint8.h
+
+ @maintainer Morgan McGuire, graphics3d.com
+
+ @created 2003-04-07
+ @edited 2006-03-24
+
+ Copyright 2000-2006, Morgan McGuire.
+ All rights reserved.
+ */
+
+#ifndef COLOR4UINT8_H
+#define COLOR4UINT8_H
+
+#include "G3D/g3dmath.h"
+#include "G3D/platform.h"
+#include "G3D/Color3uint8.h"
+
+namespace G3D {
+
+/**
+ Represents a Color4 as a packed integer. Convenient
+ for creating unsigned int vertex arrays. Used by
+ G3D::GImage as the underlying format.
+
+ WARNING: Integer color formats are different than
+ integer vertex formats. The color channels are automatically
+ scaled by 255 (because OpenGL automatically scales integer
+ colors back by this factor). So Color4(1,1,1) == Color4uint8(255,255,255)
+ but Vector3(1,1,1) == Vector3int16(1,1,1).
+
+ */
+G3D_BEGIN_PACKED_CLASS(1)
+class Color4uint8 {
+private:
+ // Hidden operators
+ bool operator<(const Color4uint8&) const;
+ bool operator>(const Color4uint8&) const;
+ bool operator<=(const Color4uint8&) const;
+ bool operator>=(const Color4uint8&) const;
+
+public:
+ uint8 r;
+ uint8 g;
+ uint8 b;
+ uint8 a;
+
+ Color4uint8() : r(0), g(0), b(0), a(0) {}
+
+ Color4uint8(const class Color4& c);
+
+ Color4uint8(const uint8 _r, const uint8 _g, const uint8 _b, const uint8 _a) : r(_r), g(_g), b(_b), a(_a) {}
+
+ Color4uint8(const Color3uint8& c, const uint8 _a) : r(c.r), g(c.g), b(c.b), a(_a) {}
+
+ Color4uint8(class BinaryInput& bi);
+
+ inline static Color4uint8 fromARGB(uint32 i) {
+ Color4uint8 c;
+ c.a = (i >> 24) & 0xFF;
+ c.r = (i >> 16) & 0xFF;
+ c.g = (i >> 8) & 0xFF;
+ c.b = i & 0xFF;
+ return c;
+ }
+
+ inline uint32 asUInt32() const {
+ return ((uint32)a << 24) + ((uint32)r << 16) + ((uint32)g << 8) + b;
+ }
+
+ // access vector V as V[0] = V.r, V[1] = V.g, V[2] = V.b
+ //
+ // WARNING. These member functions rely on
+ // (1) Color4uint8 not having virtual functions
+ // (2) the data packed in a 3*sizeof(uint8) memory block
+ uint8& operator[] (int i) const {
+ return ((uint8*)this)[i];
+ }
+
+ operator uint8* () {
+ return (uint8*)this;
+ }
+
+ operator const uint8* () const {
+ return (uint8*)this;
+ }
+
+
+ inline Color3uint8 bgr() const {
+ return Color3uint8(b, g, r);
+ }
+
+ void serialize(class BinaryOutput& bo) const;
+
+ void deserialize(class BinaryInput& bi);
+
+ inline Color3uint8 rgb() const {
+ return Color3uint8(r, g, b);
+ }
+
+ bool operator==(const Color4uint8& other) const {
+ return *reinterpret_cast(this) == *reinterpret_cast(&other);
+ }
+
+ bool operator!=(const Color4uint8& other) const {
+ return *reinterpret_cast(this) != *reinterpret_cast(&other);
+ }
+
+}
+G3D_END_PACKED_CLASS(1)
+
+} // namespace G3D
+
+#endif
diff --git a/dep/include/g3dlite/G3D/Cone.h b/dep/include/g3dlite/G3D/Cone.h
new file mode 100644
index 000000000..d801a9b34
--- /dev/null
+++ b/dep/include/g3dlite/G3D/Cone.h
@@ -0,0 +1,68 @@
+/**
+ @file Cone.h
+
+ Cone class
+
+ @maintainer Morgan McGuire, http://graphics.cs.williams.edu
+ @cite Portions based on Dave Eberly's Magic Software Library at http://www.magic-software.com
+
+ @created 2001-06-02
+ @edited 2006-02-23
+
+ Copyright 2000-2006, Morgan McGuire.
+ All rights reserved.
+ */
+
+#ifndef G3D_CONE_H
+#define G3D_CONE_H
+
+#include "G3D/platform.h"
+#include "G3D/g3dmath.h"
+#include "G3D/Vector3.h"
+
+namespace G3D {
+
+/**
+ An infinite cone.
+ */
+class Cone {
+
+private:
+ Vector3 tip;
+ Vector3 direction;
+
+ /** Angle from the center line to the edge. */
+ float angle;
+
+public:
+
+ /**
+ @param angle Angle from the center line to the edge, in radians
+ */
+ Cone(const Vector3& tip, const Vector3& direction, float angle);
+
+ /**
+ Forms the smallest cone that contains the box. Undefined if
+ the tip is inside or on the box.
+ */
+ Cone(const Vector3& tip, const class Box& box);
+
+ virtual ~Cone() {}
+
+ /**
+ Returns true if the cone touches, intersects, or contains b.
+
+ If c.intersects(s) and c.intersects(Sphere(s.center, s.radius * 2)
+ then the sphere s is entirely within cone c.
+ */
+ bool intersects(const class Sphere& s) const;
+
+ /**
+ True if v is a point inside the cone.
+ */
+ bool contains(const class Vector3& v) const;
+};
+
+} // namespace
+
+#endif
diff --git a/dep/include/g3dlite/G3D/ConvexPolyhedron.h b/dep/include/g3dlite/G3D/ConvexPolyhedron.h
new file mode 100644
index 000000000..a6fdd62cf
--- /dev/null
+++ b/dep/include/g3dlite/G3D/ConvexPolyhedron.h
@@ -0,0 +1,180 @@
+/**
+ @file ConvexPolyhedron.h
+
+ @maintainer Morgan McGuire, http://graphics.cs.williams.edu
+
+ @created 2001-11-11
+ @edited 2006-04-10
+
+ Copyright 2000-2006, Morgan McGuire.
+ All rights reserved.
+ */
+
+#ifndef G3D_CONVEXPOLYHEDRON_H
+#define G3D_CONVEXPOLYHEDRON_H
+
+#include "G3D/platform.h"
+#include "G3D/Vector3.h"
+#include "G3D/Vector2.h"
+#include "G3D/CoordinateFrame.h"
+#include "G3D/Plane.h"
+#include "G3D/Line.h"
+#include "G3D/Array.h"
+
+namespace G3D {
+
+class DirectedEdge {
+public:
+ Vector3 start;
+ Vector3 stop;
+};
+
+class ConvexPolygon {
+private:
+
+ friend class ConvexPolyhedron;
+
+ Array _vertex;
+
+public:
+
+ ConvexPolygon() {}
+ ConvexPolygon(const Vector3& v0, const Vector3& v1, const Vector3& v2);
+ ConvexPolygon(const Array& __vertex);
+ virtual ~ConvexPolygon() {}
+
+ /**
+ Counter clockwise winding order.
+ */
+ inline const Vector3& vertex(int i) const {
+ return _vertex[i];
+ }
+
+ inline void setVertex(int i, const Vector3& v) {
+ _vertex[i] = v;
+ }
+
+ /**
+ Zero vertices indicates an empty polygon (zero area).
+ */
+ inline int numVertices() const {
+ return _vertex.size();
+ }
+
+ inline void setNumVertices(int n) {
+ _vertex.resize(n);
+ }
+
+ /**
+ O(n) in the number of edges
+ */
+ bool isEmpty() const;
+
+ /**
+ Cuts the polygon at the plane. If the polygon is entirely above or below
+ the plane, one of the returned polygons will be empty.
+
+ @param above The part of the polygon above (on the side the
+ normal points to or in the plane) the plane
+ @param below The part of the polygon below the plane.
+ @param newEdge If a new edge was introduced, this is that edge (on the above portion; the below portion is the opposite winding.
+ */
+ void cut(const Plane& plane, ConvexPolygon &above, ConvexPolygon &below, DirectedEdge& newEdge);
+ void cut(const Plane& plane, ConvexPolygon &above, ConvexPolygon &below);
+
+ /**
+ When a cut plane grazes a vertex in the polygon, two near-identical vertices may be created.
+ The closeness of these two points can cause a number of problems, such as ConvexPolygon::normal()
+ returning an infinite vector. It should be noted, however, that not all applications are
+ sensitive to near-identical vertices.
+
+ removeDuplicateVertices() detects and eliminates redundant vertices.
+ */
+ void removeDuplicateVertices();
+
+ /**
+ O(n) in the number of edges
+ */
+ float getArea() const;
+
+ inline Vector3 normal() const {
+ debugAssert(_vertex.length() >= 3);
+ return (_vertex[1] - _vertex[0]).cross(_vertex[2] - _vertex[0]).direction();
+ }
+
+ /**
+ Returns the same polygon with inverse winding.
+ */
+ ConvexPolygon inverse() const;
+};
+
+
+
+class ConvexPolyhedron {
+public:
+ /**
+ Zero faces indicates an empty polyhedron
+ */
+ Array face;
+
+ ConvexPolyhedron() {}
+ ConvexPolyhedron(const Array& _face);
+
+ /**
+ O(n) in the number of edges
+ */
+ bool isEmpty() const;
+
+ /**
+ O(n) in the number of edges
+ */
+ float getVolume() const;
+
+ /**
+ Cuts the polyhedron at the plane. If the polyhedron is entirely above or below
+ the plane, one of the returned polyhedra will be empty.
+
+ @param above The part of the polyhedron above (on the side the
+ normal points to or in the plane) the plane
+ @param below The part of the polyhedron below the plane.
+ */
+ void cut(const Plane& plane, ConvexPolyhedron &above, ConvexPolyhedron &below);
+};
+
+/**
+
+ */
+class ConvexPolygon2D {
+private:
+
+ Array m_vertex;
+
+public:
+
+ ConvexPolygon2D() {}
+
+ /**
+ Points are counter-clockwise in a Y = down, X = right coordinate
+ system.
+
+ @param reverse If true, the points are reversed (i.e. winding direction is changed)
+ before the polygon is created.
+ */
+ ConvexPolygon2D(const Array& pts, bool reverse = false);
+
+ inline int numVertices() const {
+ return m_vertex.size();
+ }
+
+ inline const Vector2& vertex(int index) const {
+ debugAssert((index >= 0) && (index <= m_vertex.size()));
+ return m_vertex[index];
+ }
+
+ /** @param reverseWinding If true, the winding direction of the polygon is reversed for this test.*/
+ bool contains(const Vector2& p, bool reverseWinding = false) const;
+};
+
+
+} // namespace
+#endif
diff --git a/dep/include/g3dlite/G3D/CoordinateFrame.h b/dep/include/g3dlite/G3D/CoordinateFrame.h
index 657323eea..7ed4d0acc 100644
--- a/dep/include/g3dlite/G3D/CoordinateFrame.h
+++ b/dep/include/g3dlite/G3D/CoordinateFrame.h
@@ -1,17 +1,17 @@
/**
@file CoordinateFrame.h
- @maintainer Morgan McGuire, matrix@graphics3d.com
+ @maintainer Morgan McGuire, http://graphics.cs.williams.edu
@created 2001-03-04
- @edited 2006-04-07
+ @edited 2009-04-29
- Copyright 2000-2006, Morgan McGuire.
+ Copyright 2000-2009, Morgan McGuire.
All rights reserved.
*/
-#ifndef G3D_COORDINATEFRAME_H
-#define G3D_COORDINATEFRAME_H
+#ifndef G3D_CFrame_h
+#define G3D_CFrame_h
#include "G3D/platform.h"
#include "G3D/Vector3.h"
@@ -24,7 +24,15 @@
#include
#include
+#ifdef _MSC_VER
+// Turn off "conditional expression is constant" warning; MSVC generates this
+// for debug assertions in inlined methods.
+# pragma warning (disable : 4127)
+#endif
+
+
namespace G3D {
+class Any;
/**
A rigid body RT (rotation-translation) transformation.
@@ -45,26 +53,26 @@ Convert to Matrix4 using CoordinateFrame::toMatrix4. You can construct a
from a Matrix4 using Matrix4::approxCoordinateFrame, however, because a Matrix4 is more
general than a CoordinateFrame, some information may be lost.
-See also: G3D::Matrix4, G3D::Quat
+@sa G3D::UprightFrame, G3D::PhysicsFrame, G3D::Matrix4, G3D::Quat
*/
class CoordinateFrame {
public:
- /**
- Takes object space points to world space.
- */
+ /** Takes object space points to world space. */
Matrix3 rotation;
- /**
- Takes object space points to world space.
- */
+ /** Takes object space points to world space. */
Vector3 translation;
- /**
- The direction an object "looks" relative to its own axes.
- @deprecated This is always -1 and will be fixed at that value in future releases.
- */
- static const float zLookDirection;
+ /** \param any Must be in one of the following forms:
+ - CFrame((matrix3 expr), (vector3 expr))
+ - CFrame::fromXYZYPRDegrees(#, #, #, #, #, #)
+ - CFrame { rotation = (matrix3 expr), translation = (vector3 expr) }
+ */
+ CoordinateFrame(const Any& any);
+
+ /** Converts the CFrame to an Any. */
+ operator Any() const;
inline bool operator==(const CoordinateFrame& other) const {
return (translation == other.translation) && (rotation == other.rotation);
@@ -83,14 +91,12 @@ public:
/**
Initializes to the identity coordinate frame.
*/
- inline CoordinateFrame() :
- rotation(Matrix3::identity()), translation(Vector3::zero()) {
- }
+ CoordinateFrame();
- CoordinateFrame(const Vector3& _translation) :
+ CoordinateFrame(const Vector3& _translation) :
rotation(Matrix3::identity()), translation(_translation) {
- }
-
+ }
+
CoordinateFrame(const Matrix3 &rotation, const Vector3 &translation) :
rotation(rotation), translation(translation) {
}
@@ -99,6 +105,23 @@ public:
rotation(rotation), translation(Vector3::zero()) {
}
+ CoordinateFrame(const class UprightFrame& f);
+
+ static CoordinateFrame fromXYZYPRRadians(float x, float y, float z, float yaw = 0.0f, float pitch = 0.0f, float roll = 0.0f);
+
+ /** Construct a coordinate frame from translation = (x,y,z) and
+ rotations (in that order) about Y, object space X, object space
+ Z. Note that because object-space axes are used, these are not
+ equivalent to Euler angles; they are known as Tait-Bryan
+ rotations and are more convenient for intuitive positioning.*/
+ static CoordinateFrame fromXYZYPRDegrees(float x, float y, float z, float yaw = 0.0f, float pitch = 0.0f, float roll = 0.0f);
+
+ CoordinateFrame(class BinaryInput& b);
+
+ void deserialize(class BinaryInput& b);
+
+ void serialize(class BinaryOutput& b) const;
+
CoordinateFrame(const CoordinateFrame &other) :
rotation(other.rotation), translation(other.translation) {}
@@ -117,8 +140,13 @@ public:
/** See also Matrix4::approxCoordinateFrame */
class Matrix4 toMatrix4() const;
+ void getXYZYPRRadians(float& x, float& y, float& z, float& yaw, float& pitch, float& roll) const;
+ void getXYZYPRDegrees(float& x, float& y, float& z, float& yaw, float& pitch, float& roll) const;
+
+
/**
Produces an XML serialization of this coordinate frame.
+ @deprecated
*/
std::string toXML() const;
@@ -131,7 +159,7 @@ public:
object has an inverted heading.
*/
inline float getHeading() const {
- Vector3 look = rotation.getColumn(2);
+ Vector3 look = rotation.column(2);
float angle = -(float) atan2(-look.x, look.z);
return angle;
}
@@ -163,17 +191,18 @@ public:
}
/**
- Transforms the point into object space.
+ Transforms the point into object space. Assumes that the rotation matrix is orthonormal.
*/
- inline Vector3 pointToObjectSpace(const Vector3& v) const {
- float p[3];
- p[0] = v[0] - translation[0];
- p[1] = v[1] - translation[1];
- p[2] = v[2] - translation[2];
- return Vector3(
- rotation[0][0] * p[0] + rotation[1][0] * p[1] + rotation[2][0] * p[2],
- rotation[0][1] * p[0] + rotation[1][1] * p[1] + rotation[2][1] * p[2],
- rotation[0][2] * p[0] + rotation[1][2] * p[1] + rotation[2][2] * p[2]);
+ inline Vector3 pointToObjectSpace(const Vector3& v) const {
+ float p[3];
+ p[0] = v[0] - translation[0];
+ p[1] = v[1] - translation[1];
+ p[2] = v[2] - translation[2];
+ debugAssert(G3D::fuzzyEq(rotation.determinant(), 1.0f));
+ return Vector3(
+ rotation[0][0] * p[0] + rotation[1][0] * p[1] + rotation[2][0] * p[2],
+ rotation[0][1] * p[0] + rotation[1][1] * p[1] + rotation[2][1] * p[2],
+ rotation[0][2] * p[0] + rotation[1][2] * p[1] + rotation[2][2] * p[2]);
}
/**
@@ -260,14 +289,9 @@ public:
const Vector3& target,
Vector3 up);
- /** @deprecated See lookVector */
- inline Vector3 getLookVector() const {
- return rotation.getColumn(2) * zLookDirection;
- }
-
/** The direction this camera is looking (its negative z axis)*/
inline Vector3 lookVector() const {
- return rotation.getColumn(2) * zLookDirection;
+ return -rotation.column(2);
}
/** Returns the ray starting at the camera origin travelling in direction CoordinateFrame::lookVector. */
@@ -275,20 +299,11 @@ public:
/** Up direction for this camera (its y axis). */
inline Vector3 upVector() const {
- return rotation.getColumn(1);
+ return rotation.column(1);
}
- /**
- If a viewer looks along the look vector, this is the viewer's "left"
- @deprecated leftVector
- */
- inline Vector3 getLeftVector() const {
- return -rotation.getColumn(0);
- }
-
- /** @deprecated See rightVector */
- inline Vector3 getRightVector() const {
- return rotation.getColumn(0);
+ inline Vector3 rightVector() const {
+ return rotation.column(0);
}
/**
@@ -296,11 +311,7 @@ public:
Useful for strafing motions and building alternative coordinate frames.
*/
inline Vector3 leftVector() const {
- return -rotation.getColumn(0);
- }
-
- inline Vector3 rightVector() const {
- return rotation.getColumn(0);
+ return -rotation.column(0);
}
/**
@@ -313,6 +324,8 @@ public:
};
+typedef CoordinateFrame CFrame;
+
} // namespace
#endif
diff --git a/dep/include/g3dlite/G3D/Crypto.h b/dep/include/g3dlite/G3D/Crypto.h
index f4e7bfad6..56c816a49 100644
--- a/dep/include/g3dlite/G3D/Crypto.h
+++ b/dep/include/g3dlite/G3D/Crypto.h
@@ -1,7 +1,7 @@
/**
@file Crypto.h
- @maintainer Morgan McGuire, matrix@graphics3d.com
+ @maintainer Morgan McGuire, http://graphics.cs.williams.edu
@created 2006-03-29
@@ -17,6 +17,48 @@
namespace G3D {
+/** See G3D::Crypto::md5 */
+class MD5Hash {
+private:
+
+ uint8 value[16];
+
+public:
+
+ MD5Hash() {
+ for (int i = 0; i < 16; ++i) {
+ value[i] = 0;
+ }
+ }
+
+ explicit MD5Hash(class BinaryInput& b);
+
+ uint8& operator[](int i) {
+ return value[i];
+ }
+
+ const uint8& operator[](int i) const {
+ return value[i];
+ }
+
+ bool operator==(const MD5Hash& other) const {
+ bool match = true;
+ for (int i = 0; i < 16; ++i) {
+ match = match && (other.value[i] == value[i]);
+ }
+ return match;
+ }
+
+ inline bool operator!=(const MD5Hash& other) const {
+ return !(*this == other);
+ }
+
+ void deserialize(class BinaryInput& b);
+
+ void serialize(class BinaryOutput& b) const;
+};
+
+
/** Cryptography and hashing helper functions */
class Crypto {
public:
@@ -31,6 +73,14 @@ public:
*/
static uint32 crc32(const void* bytes, size_t numBytes);
+ /**
+ Computes the MD5 hash (message digest) of a byte stream, as defined by
+ http://www.ietf.org/rfc/rfc1321.txt.
+
+ @cite Based on implementation by L. Peter Deutsch, ghost@aladdin.com
+ */
+ MD5Hash md5(const void* bytes, size_t numBytes);
+
/**
Returns the nth prime less than 2000 in constant time. The first prime has index
0 and is the number 2.
diff --git a/dep/include/g3dlite/G3D/Cylinder.h b/dep/include/g3dlite/G3D/Cylinder.h
new file mode 100644
index 000000000..85eba77b7
--- /dev/null
+++ b/dep/include/g3dlite/G3D/Cylinder.h
@@ -0,0 +1,92 @@
+/**
+ @file Cylinder.h
+
+ @maintainer Morgan McGuire, http://graphics.cs.williams.edu
+
+ @created 2003-02-07
+ @edited 2005-09-26
+
+ Copyright 2000-2005, Morgan McGuire.
+ All rights reserved.
+ */
+
+#ifndef G3D_Cylinder_H
+#define G3D_Cylinder_H
+
+#include "G3D/platform.h"
+#include "G3D/g3dmath.h"
+#include "G3D/Vector3.h"
+
+namespace G3D {
+
+class Line;
+class AABox;
+/**
+ Right cylinder
+ */
+class Cylinder {
+private:
+ Vector3 p1;
+ Vector3 p2;
+
+ float mRadius;
+
+public:
+
+ /** Uninitialized */
+ Cylinder();
+ Cylinder(class BinaryInput& b);
+ Cylinder(const Vector3& _p1, const Vector3& _p2, float _r);
+ void serialize(class BinaryOutput& b) const;
+ void deserialize(class BinaryInput& b);
+
+ /** The line down the center of the Cylinder */
+ Line axis() const;
+
+ /**
+ A reference frame in which the center of mass is at the origin and
+ the Y-axis is the cylinder's axis. If the cylinder is transformed, this reference frame
+ may freely rotate around its axis.*/
+ void getReferenceFrame(class CoordinateFrame& cframe) const;
+
+ /** Returns point 0 or 1 */
+ inline const Vector3& point(int i) const {
+ debugAssert(i >= 0 && i <= 1);
+ return (i == 0) ? p1 : p2;
+ }
+
+ /**
+ Returns true if the point is inside the Cylinder or on its surface.
+ */
+ bool contains(const Vector3& p) const;
+
+ float area() const;
+
+ float volume() const;
+
+ float radius() const;
+
+ /** Center of mass */
+ inline Vector3 center() const {
+ return (p1 + p2) / 2.0f;
+ }
+
+ inline float height() const {
+ return (p1 - p2).magnitude();
+ }
+
+ /**
+ Get close axis aligned bounding box.
+ With vertical world orientation, the top and bottom might not be very tight. */
+ void getBounds(AABox& out) const;
+
+ /** Random world space point with outward facing normal. */
+ void getRandomSurfacePoint(Vector3& P, Vector3& N) const;
+
+ /** Point selected uniformly at random over the volume. */
+ Vector3 randomInteriorPoint() const;
+};
+
+} // namespace
+
+#endif
diff --git a/dep/include/g3dlite/G3D/EqualsTrait.h b/dep/include/g3dlite/G3D/EqualsTrait.h
new file mode 100644
index 000000000..349cb5088
--- /dev/null
+++ b/dep/include/g3dlite/G3D/EqualsTrait.h
@@ -0,0 +1,26 @@
+/**
+ @file EqualsTrait.h
+
+ @maintainer Morgan McGuire, http://graphics.cs.williams.edu
+ @created 2008-10-01
+ @edited 2008-10-01
+ Copyright 2000-2009, Morgan McGuire.
+ All rights reserved.
+ */
+
+#ifndef G3D_EQUALSTRAIT_H
+#define G3D_EQUALSTRAIT_H
+
+#include "G3D/platform.h"
+
+/** Default implementation of EqualsTrait.
+ @see G3D::Table for specialization requirements.
+*/
+template struct EqualsTrait {
+ static bool equals(const Key& a, const Key& b) {
+ return a == b;
+ }
+};
+
+#endif
+
diff --git a/dep/include/g3dlite/G3D/G3D.h b/dep/include/g3dlite/G3D/G3D.h
new file mode 100644
index 000000000..5b56b9c71
--- /dev/null
+++ b/dep/include/g3dlite/G3D/G3D.h
@@ -0,0 +1,162 @@
+/**
+ @file G3D.h
+
+ This header includes all of the G3D libraries in
+ appropriate namespaces.
+
+ @maintainer Morgan McGuire, http://graphics.cs.williams.edu
+
+ @created 2001-08-25
+ @edited 2010-01-30
+
+ Copyright 2000-2010, Morgan McGuire.
+ All rights reserved.
+*/
+
+#ifndef G3D_G3D_h
+#define G3D_G3D_h
+
+#define NOMINMAX 1
+#ifdef min
+ #undef min
+#endif
+#ifdef max
+ #undef max
+#endif
+
+#include "G3D/platform.h"
+#include "G3D/units.h"
+#include "G3D/ParseError.h"
+#include "G3D/Random.h"
+#include "G3D/Array.h"
+#include "G3D/SmallArray.h"
+#include "G3D/Queue.h"
+#include "G3D/Crypto.h"
+#include "G3D/format.h"
+#include "G3D/Vector2.h"
+#include "G3D/Vector3.h"
+#include "G3D/Vector4.h"
+#include "G3D/Color1.h"
+#include "G3D/Color3.h"
+#include "G3D/Color4.h"
+#include "G3D/Matrix2.h"
+#include "G3D/Matrix3.h"
+#include "G3D/Matrix4.h"
+#include "G3D/CoordinateFrame.h"
+#include "G3D/PhysicsFrame.h"
+#include "G3D/Plane.h"
+#include "G3D/Line.h"
+#include "G3D/Ray.h"
+#include "G3D/Sphere.h"
+#include "G3D/Box.h"
+#include "G3D/Box2D.h"
+#include "G3D/AABox.h"
+#include "G3D/WrapMode.h"
+#include "G3D/Cone.h"
+#include "G3D/Quat.h"
+#include "G3D/stringutils.h"
+#include "G3D/prompt.h"
+#include "G3D/Table.h"
+#include "G3D/Set.h"
+#include "G3D/GUniqueID.h"
+#include "G3D/BinaryFormat.h"
+#include "G3D/BinaryInput.h"
+#include "G3D/BinaryOutput.h"
+#include "G3D/debug.h"
+#include "G3D/g3dfnmatch.h"
+#include "G3D/G3DGameUnits.h"
+#include "G3D/g3dmath.h"
+#include "G3D/uint128.h"
+#include "G3D/fileutils.h"
+#include "G3D/ReferenceCount.h"
+#include "G3D/Welder.h"
+#include "G3D/GMutex.h"
+#include "G3D/PrecomputedRandom.h"
+#include "G3D/MemoryManager.h"
+#include "G3D/AreaMemoryManager.h"
+#include "G3D/BumpMapPreprocess.h"
+
+template struct HashTrait< G3D::ReferenceCountedPointer > {
+ static size_t hashCode(G3D::ReferenceCountedPointer key) { return reinterpret_cast( key.pointer() ); }
+};
+
+#include "G3D/GImage.h"
+#include "G3D/CollisionDetection.h"
+#include "G3D/Intersect.h"
+#include "G3D/Log.h"
+#include "G3D/serialize.h"
+#include "G3D/TextInput.h"
+#include "G3D/NetAddress.h"
+#include "G3D/NetworkDevice.h"
+#include "G3D/System.h"
+#include "G3D/splinefunc.h"
+#include "G3D/Spline.h"
+#include "G3D/UprightFrame.h"
+#include "G3D/LineSegment.h"
+#include "G3D/Capsule.h"
+#include "G3D/Cylinder.h"
+#include "G3D/Triangle.h"
+#include "G3D/Color3uint8.h"
+#include "G3D/Color4uint8.h"
+#include "G3D/Vector2int16.h"
+#include "G3D/Vector3int16.h"
+#include "G3D/Vector3int32.h"
+#include "G3D/Vector4int8.h"
+#include "G3D/ConvexPolyhedron.h"
+#include "G3D/MeshAlg.h"
+#include "G3D/vectorMath.h"
+#include "G3D/Rect2D.h"
+#include "G3D/GCamera.h"
+#include "G3D/GLight.h"
+#include "G3D/KDTree.h"
+#include "G3D/PointKDTree.h"
+#include "G3D/TextOutput.h"
+#include "G3D/MeshBuilder.h"
+#include "G3D/Stopwatch.h"
+#include "G3D/AtomicInt32.h"
+#include "G3D/GThread.h"
+#include "G3D/ThreadSet.h"
+#include "G3D/RegistryUtil.h"
+#include "G3D/Any.h"
+#include "G3D/PointHashGrid.h"
+#include "G3D/Map2D.h"
+#include "G3D/Image1.h"
+#include "G3D/Image1uint8.h"
+#include "G3D/Image3.h"
+#include "G3D/Image3uint8.h"
+#include "G3D/Image4.h"
+#include "G3D/Image4uint8.h"
+#include "G3D/filter.h"
+#include "G3D/WeakCache.h"
+#include "G3D/Pointer.h"
+#include "G3D/Matrix.h"
+#include "G3D/ImageFormat.h"
+
+#ifdef _MSC_VER
+# pragma comment(lib, "zlib")
+# pragma comment(lib, "ws2_32")
+# pragma comment(lib, "winmm")
+# pragma comment(lib, "imagehlp")
+# pragma comment(lib, "gdi32")
+# pragma comment(lib, "user32")
+# pragma comment(lib, "kernel32")
+# pragma comment(lib, "version")
+# pragma comment(lib, "advapi32")
+# pragma comment(lib, "png")
+# pragma comment(lib, "jpeg")
+# pragma comment(lib, "zip")
+# ifdef _DEBUG
+ // Don't link against G3D when building G3D itself.
+# ifndef G3D_BUILDING_LIBRARY_DLL
+# pragma comment(lib, "G3Dd.lib")
+# endif
+# else
+ // Don't link against G3D when building G3D itself.
+# ifndef G3D_BUILDING_LIBRARY_DLL
+# pragma comment(lib, "G3D.lib")
+# endif
+# endif
+#endif
+
+#endif
+
diff --git a/dep/include/g3dlite/G3D/G3DAll.h b/dep/include/g3dlite/G3D/G3DAll.h
new file mode 100644
index 000000000..1176fe742
--- /dev/null
+++ b/dep/include/g3dlite/G3D/G3DAll.h
@@ -0,0 +1,26 @@
+/**
+ @file G3DAll.h
+
+ Includes all G3D and GLG3D files and uses the G3D namespace.
+
+ This requires OpenGL and SDL headers. If you don't want all of this,
+ \#include separately.
+
+ @maintainer Morgan McGuire, http://graphics.cs.williams.edu
+
+ @created 2002-01-01
+ @edited 2006-08-13
+
+ Copyright 2000-2006, Morgan McGuire.
+ All rights reserved.
+ */
+
+#ifndef G3D_G3DALL_H
+#define G3D_G3DALL_H
+
+#include "G3D/G3D.h"
+#include "GLG3D/GLG3D.h"
+
+using namespace G3D;
+
+#endif
diff --git a/dep/include/g3dlite/G3D/G3DGameUnits.h b/dep/include/g3dlite/G3D/G3DGameUnits.h
new file mode 100644
index 000000000..e2bc2c811
--- /dev/null
+++ b/dep/include/g3dlite/G3D/G3DGameUnits.h
@@ -0,0 +1,42 @@
+/**
+ @file G3DGameUnits.h
+
+ @maintainer Morgan McGuire, http://graphics.cs.williams.edu
+ @created 2002-10-05
+ @edited 2006-11-10
+ */
+
+#ifndef G3D_GAMEUNITS_H
+#define G3D_GAMEUNITS_H
+
+#include "G3D/platform.h"
+
+namespace G3D {
+/**
+ Time, in seconds.
+ */
+typedef double GameTime;
+typedef double SimTime;
+
+/**
+ Actual wall clock time in seconds.
+ */
+typedef double RealTime;
+
+enum AMPM {AM, PM};
+
+/** \deprecated */
+enum {SECOND=1, MINUTE=60, HOUR = 60*60, DAY=24*60*60, SUNRISE=24*60*60/4, SUNSET=24*60*60*3/4, MIDNIGHT=0, METER=1, KILOMETER=1000};
+
+/**
+ Converts a 12 hour clock time into the number of seconds since
+ midnight. Note that 12:00 PM is noon and 12:00 AM is midnight.
+
+ Example: toSeconds(10, 00, AM)
+ */
+SimTime toSeconds(int hour, int minute, double seconds, AMPM ap);
+SimTime toSeconds(int hour, int minute, AMPM ap);
+
+}
+
+#endif
diff --git a/dep/include/g3dlite/G3D/GCamera.h b/dep/include/g3dlite/G3D/GCamera.h
index 3205f3904..018fbc85d 100644
--- a/dep/include/g3dlite/G3D/GCamera.h
+++ b/dep/include/g3dlite/G3D/GCamera.h
@@ -1,58 +1,87 @@
/**
@file GCamera.h
- @maintainer Morgan McGuire, matrix@graphics3d.com
+ @maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @created 2001-06-02
- @edited 2006-02-11
+ @created 2005-07-20
+ @edited 2009-04-20
*/
-#ifndef G3D_GCAMERA_H
-#define G3D_GCAMERA_H
+#ifndef G3D_GCamera_H
+#define G3D_GCamera_H
#include "G3D/platform.h"
#include "G3D/CoordinateFrame.h"
#include "G3D/Vector3.h"
#include "G3D/Plane.h"
+#include "G3D/debugAssert.h"
namespace G3D {
+class Matrix4;
+class Rect2D;
+class Any;
+
/**
- There is a viewport of width x height size in world space that corresponds to
- a screenWidth x screenHeight pixel grid on a
- renderDevice->getWidth() x renderDevice->getHeight()
- window.
+ Abstraction of a pinhole camera.
+
+ The area a camera sees is called a frustum. It is bounded by the
+ near plane, the far plane, and the sides of the view frame projected
+ into the scene. It has the shape of a pyramid with the top cut off.
+
+ Cameras can project points from 3D to 2D. The "unit" projection
+ matches OpenGL. It maps the entire view frustum to a cube of unit
+ radius (i.e., edges of length 2) centered at the origin. The
+ non-unit projection then maps that cube to the specified pixel
+ viewport in X and Y and the range [0, 1] in Z. The projection is
+ reversable as long as the projected Z value is known.
All viewport arguments are the pixel bounds of the viewport-- e.g.,
- RenderDevice::getViewport().
+ RenderDevice::viewport().
*/
class GCamera {
-private:
-
- /**
- Vertical field of view (in radians)
- */
- float fieldOfView;
-
- /**
- The image plane depth corresponding to a vertical field of
- view, where the film size is 1x1.
- */
- float imagePlaneDepth;
-
- /**
- Clipping plane, *not* imaging plane. Positive numbers.
- */
- float nearPlane;
-
- /**
- Positive
- */
- float farPlane;
-
- CoordinateFrame cframe;
public:
+ /**
+ Stores the direction of the field of view
+ */
+ enum FOVDirection {HORIZONTAL, VERTICAL};
+
+private:
+
+ /** Full field of view (in radians) */
+ float m_fieldOfView;
+
+ /** Clipping plane, *not* imaging plane. Negative numbers. */
+ float m_nearPlaneZ;
+
+ /** Negative */
+ float m_farPlaneZ;
+
+ /** Stores the camera's location and orientation */
+ CoordinateFrame m_cframe;
+
+ /** Horizontal or Vertical */
+ FOVDirection m_direction;
+
+public:
+
+ /** Must be of the format produced by the Any cast, e.g.,
+
+
+
+ Missing fields are filled from the default GCamera constructor.
+ */
+ GCamera(const Any& any);
+
+ operator Any() const;
class Frustum {
public:
@@ -77,53 +106,97 @@ public:
Array faceArray;
};
- GCamera();
+ GCamera();
+
+ GCamera(const Matrix4& proj, const CFrame& frame);
virtual ~GCamera();
+ /** Returns the current coordinate frame */
+ const CoordinateFrame& coordinateFrame() const {
+ return m_cframe;
+ }
- CoordinateFrame getCoordinateFrame() const;
- void getCoordinateFrame(CoordinateFrame& c) const;
- void setCoordinateFrame(const CoordinateFrame& c);
+ /** Sets c to the camera's coordinate frame */
+ void getCoordinateFrame(CoordinateFrame& c) const;
+
+ /** Sets a new coordinate frame for the camera */
+ void setCoordinateFrame(const CoordinateFrame& c);
- /**
- Sets the horizontal field of view, in radians. The
- initial angle is toRadians(55).
-
-
toRadians(50) - Telephoto
-
toRadians(110) - Normal
-
toRadians(140) - Wide angle
-
- */
- void setFieldOfView(float angle);
+ /** Sets \a P equal to the camera's projection matrix. This is the
+ matrix that maps points to the homogeneous clip cube that
+ varies from -1 to 1 on all axes. The projection matrix does
+ not include the camera transform.
- /**
- Sets the field of view based on a desired image plane depth
- (s') and film dimensions in world space. Depth must be positive. Width,
- depth, and height are measured in the same units (meters are
- recommended). The field of view will span the diagonal to the
- image.
Note: to simulate a 35mm GCamera, set width =
- 0.36 mm and height = 0.24 mm. The width and height used are
- generally not the pixel dimensions of the image.
- */
- void setImagePlaneDepth(
- float depth,
- const class Rect2D& viewport);
+ This is the matrix that a RenderDevice (or OpenGL) uses as the projection matrix.
+ @sa RenderDevice::setProjectionAndCameraMatrix, RenderDevice::setProjectionMatrix, Matrix4::perspectiveProjection
+ */
+ void getProjectUnitMatrix(const Rect2D& viewport, Matrix4& P) const;
- inline double getFieldOfView() const {
- return fieldOfView;
- }
+ /** Sets \a P equal to the matrix that transforms points to pixel
+ coordinates on the given viewport. A point correspoinding to
+ the top-left corner of the viewport in camera space will
+ transform to viewport.x0y0() and the bottom-right to viewport.x1y1(). */
+ void getProjectPixelMatrix(const Rect2D& viewport, Matrix4& P) const;
+
+ /** Converts projected points from OpenGL standards
+ (-1, 1) to normal 3D coordinate standards (0, 1)
+
+ \deprecated
+ */ // TODO: Remove
+ Vector3 convertFromUnitToNormal(const Vector3& in, const Rect2D& viewport) const;
+
+ /**
+ Sets the field of view, in radians. The
+ initial angle is toRadians(55). Must specify
+ the direction of the angle.
+
+ This is the full angle, i.e., from the left side of the
+ viewport to the right side.
+ */
+ void setFieldOfView(float angle, FOVDirection direction);
+
+ /** Returns the current full field of view angle (from the left side of the
+ viewport to the right side) and direction */
+ inline void getFieldOfView(float& angle, FOVDirection& direction) const {
+ angle = m_fieldOfView;
+ direction = m_direction;
+ }
/**
Projects a world space point onto a width x height screen. The
returned coordinate uses pixmap addressing: x = right and y =
- down. The resulting z value is rhw.
+ down. The resulting z value is 0 at the near plane, 1 at the far plane,
+ and is a linear compression of unit cube projection.
If the point is behind the camera, Vector3::inf() is returned.
*/
- G3D::Vector3 project(
- const G3D::Vector3& point,
- const class Rect2D& viewport) const;
+ Vector3 project(const G3D::Vector3& point,
+ const class Rect2D& viewport) const;
+
+ /**
+ Projects a world space point onto a unit cube. The resulting
+ x,y,z values range between -1 and 1, where z is -1
+ at the near plane and 1 at the far plane and varies hyperbolically in between.
+
+ If the point is behind the camera, Vector3::inf() is returned.
+ */
+ Vector3 projectUnit(const G3D::Vector3& point,
+ const class Rect2D& viewport) const;
+
+ /**
+ Gives the world-space coordinates of screen space point v, where
+ v.x is in pixels from the left, v.y is in pixels from
+ the top, and v.z is on the range 0 (near plane) to 1 (far plane).
+ */
+ Vector3 unproject(const Vector3& v, const Rect2D& viewport) const;
+
+ /**
+ Gives the world-space coordinates of unit cube point v, where
+ v varies from -1 to 1 on all axes. The unproject first
+ transforms the point into a pixel location for the viewport, then calls unproject
+ */
+ Vector3 unprojectUnit(const Vector3& v, const Rect2D& viewport) const;
/**
Returns the pixel area covered by a shape of the given
@@ -134,24 +207,29 @@ public:
/**
Returns the world space 3D viewport corners. These
are at the near clipping plane. The corners are constructed
- from the nearPlaneZ, getViewportWidth, and getViewportHeight.
+ from the nearPlaneZ, viewportWidth, and viewportHeight.
"left" and "right" are from the GCamera's perspective.
*/
- void get3DViewportCorners(
- const class Rect2D& viewport,
- Vector3& outUR,
- Vector3& outUL,
- Vector3& outLL,
- Vector3& outLR) const;
+ void getNearViewportCorners(const class Rect2D& viewport,
+ Vector3& outUR, Vector3& outUL,
+ Vector3& outLL, Vector3& outLR) const;
/**
- Returns the image plane depth, s', given the current field
- of view for film of dimensions width x height. See
- setImagePlaneDepth for a discussion of worldspace values width and height.
- */
- float getImagePlaneDepth(
- const class Rect2D& viewport) const;
+ Returns the world space 3D viewport corners. These
+ are at the Far clipping plane. The corners are constructed
+ from the nearPlaneZ, farPlaneZ, viewportWidth, and viewportHeight.
+ "left" and "right" are from the GCamera's perspective.
+ */
+ void getFarViewportCorners(const class Rect2D& viewport,
+ Vector3& outUR, Vector3& outUL,
+ Vector3& outLL, Vector3& outLR) const;
+ /**
+ Returns the image plane depth, assumes imagePlane
+ is the same as the near clipping plane.
+ returns a positive number.
+ */
+ float imagePlaneDepth() const;
/**
Returns the world space ray passing through the center of pixel
@@ -159,91 +237,99 @@ public:
the 3D object space axes: (0,0) is the upper left corner of the screen.
They are in viewport coordinates, not screen coordinates.
+ The ray origin is at the origin. To start it at the image plane,
+ move it forward by imagePlaneDepth/ray.direction.z
Integer (x, y) values correspond to
the upper left corners of pixels. If you want to cast rays
through pixel centers, add 0.5 to x and y.
- */
+ */
Ray worldRay(
float x,
float y,
const class Rect2D& viewport) const;
-
/**
Returns a negative z-value.
*/
- inline float getNearPlaneZ() const {
- return -nearPlane;
+ inline float nearPlaneZ() const {
+ return m_nearPlaneZ;
}
/**
Returns a negative z-value.
*/
- inline float getFarPlaneZ() const {
- return -farPlane;
+ inline float farPlaneZ() const {
+ return m_farPlaneZ;
}
- inline void setFarPlaneZ(float z) {
- debugAssert(z < 0);
- farPlane = -z;
- }
-
- inline void setNearPlaneZ(float z) {
- debugAssert(z < 0);
- nearPlane = -z;
- }
+ /**
+ Sets a new value for the far clipping plane
+ Expects a negative value
+ */
+ inline void setFarPlaneZ(float z) {
+ debugAssert(z < 0);
+ m_farPlaneZ = z;
+ }
+
+ /**
+ Sets a new value for the near clipping plane
+ Expects a negative value
+ */
+ inline void setNearPlaneZ(float z) {
+ debugAssert(z < 0);
+ m_nearPlaneZ = z;
+ }
/**
- Returns the GCamera space width of the viewport.
+ Returns the camera space width of the viewport at the near plane.
*/
- float getViewportWidth(
- const class Rect2D& viewport) const;
+ float viewportWidth(const class Rect2D& viewport) const;
/**
- Returns the GCamera space height of the viewport.
- */
- float getViewportHeight(
- const class Rect2D& viewport) const;
-
- /**
- Read back a GCamera space z-value at pixel (x, y) from the depth buffer.
- double getZValue(
- double x,
- double y,
- const class Rect2D& viewport,
- double polygonOffset = 0) const;
+ Returns the camera space height of the viewport at the near plane.
*/
+ float viewportHeight(const class Rect2D& viewport) const;
void setPosition(const Vector3& t);
+ /** Rotate the camera in place to look at the target. Does not
+ persistently look at that location when the camera moves;
+ i.e., if you move the camera and still want it to look at the
+ old target, you must call lookAt again after moving the
+ camera.)*/
void lookAt(const Vector3& position, const Vector3& up = Vector3::unitY());
- /**
- Returns the clipping planes of the frustum, in world space.
- The planes have normals facing into the view frustum.
-
- The plane order is guaranteed to be:
- Near, Right, Left, Top, Bottom, [Far]
-
- If the far plane is at infinity, the resulting array will have
- 5 planes, otherwise there will be 6.
-
- The viewport is used only to determine the aspect ratio of the screen; the
- absolute dimensions and xy values don't matter.
+ /**
+ Returns the clipping planes of the frustum, in world space.
+ The planes have normals facing into the view frustum.
+
+ The plane order is guaranteed to be:
+ Near, Right, Left, Top, Bottom, [Far]
+
+ If the far plane is at infinity, the resulting array will have
+ 5 planes, otherwise there will be 6.
+
+ The viewport is used only to determine the aspect ratio of the screen; the
+ absolute dimensions and xy values don't matter.
*/
- void getClipPlanes(
- const Rect2D& viewport,
- Array& outClip) const;
+ void getClipPlanes
+ (
+ const Rect2D& viewport,
+ Array& outClip) const;
- /**
- Returns the world space view frustum, which is a truncated pyramid describing
- the volume of space seen by this camera.
+ /**
+ Returns the world space view frustum, which is a truncated pyramid describing
+ the volume of space seen by this camera.
*/
- void getFrustum(const Rect2D& viewport, GCamera::Frustum& f) const;
-
- GCamera::Frustum frustum(const Rect2D& viewport) const;
+ void frustum(const Rect2D& viewport, GCamera::Frustum& f) const;
+ GCamera::Frustum frustum(const Rect2D& viewport) const;
+
+ /** Read and Write camera parameters */
+ void serialize(class BinaryOutput& bo) const;
+ void deserialize(class BinaryInput& bi);
+
};
} // namespace G3D
diff --git a/dep/include/g3dlite/G3D/GImage.h b/dep/include/g3dlite/G3D/GImage.h
new file mode 100644
index 000000000..8ae11134f
--- /dev/null
+++ b/dep/include/g3dlite/G3D/GImage.h
@@ -0,0 +1,607 @@
+/**
+ \file GImage.h
+
+ See G3D::GImage for details.
+
+ @cite JPEG compress/decompressor is the IJG library, used in accordance with their license.
+ @cite JPG code by John Chisholm, using the IJG Library
+ @cite TGA code by Morgan McGuire
+ @cite BMP code by John Chisholm, based on code by Edward "CGameProgrammer" Resnick mailto:cgp@gdnmail.net at ftp://ftp.flipcode.com/cotd/LoadPicture.txt
+ @cite PCX format described in the ZSOFT PCX manual http://www.nist.fss.ru/hr/doc/spec/pcx.htm#2
+ @cite PNG compress/decompressor is the libpng library, used in accordance with their license.
+ @cite PPM code by Morgan McGuire based on http://netpbm.sourceforge.net/doc/ppm.html
+
+ \maintainer Morgan McGuire, http://graphics.cs.williams.edu
+
+ \created 2002-05-27
+ \edited 2010-01-04
+
+ Copyright 2000-2010, Morgan McGuire.
+ All rights reserved.
+ */
+
+#ifndef G3D_GImage_h
+#define G3D_GImage_h
+
+#include "G3D/platform.h"
+#include
+#include "G3D/Array.h"
+#include "G3D/g3dmath.h"
+#include "G3D/stringutils.h"
+#include "G3D/Color1uint8.h"
+#include "G3D/Color3uint8.h"
+#include "G3D/Color4uint8.h"
+#include "G3D/MemoryManager.h"
+#include "G3D/BumpMapPreprocess.h"
+
+namespace G3D {
+class BinaryInput;
+class BinaryOutput;
+
+
+/**
+ Interface to image compression & file formats.
+
+ Supported formats (decode and encode): Color JPEG, PNG,
+ (Uncompressed)TGA 24, (Uncompressed)TGA 32, BMP 1, BMP 4, BMP 8, BMP
+ 24, PPM (P6), and PPM ASCII (P1, P2, P3), which includes PPM, PGM,
+ and PBM. 8-bit paletted PCX, 24-bit PCX, and ICO are supported for
+ decoding only.
+
+ Sample usage:
+
+ \verbatim
+ // Loading from disk:
+ G3D::GImage im1("test.jpg");
+
+ // Loading from memory:
+ G3D::GImage im2(data, length);
+
+ // im.pixel is a pointer to RGB color data. If you want
+ // an alpha channel, call RGBtoRGBA or RGBtoARGB for
+ // conversion.
+
+ // Saving to memory:
+ G3D::GImage im3(width, height);
+ // (Set the pixels of im3...)
+ uint8* data2;
+ int len2;
+ im3.encode(G3D::GImage::JPEG, data2, len2);
+
+ // Saving to disk
+ im3.save("out.jpg");
+ \endverbatim
+
+ The free Image Magick Magick Wand API
+ (http://www.imagemagick.org/www/api/magick_wand.html) provides a more powerful
+ API for image manipulation and wider set of image load/save formats. It is
+ recommended over GImage (we don't include it directly in G3D because their license
+ is more restrictive than the BSD one).
+
+ */
+class GImage {
+private:
+
+ /** Used exclusively for allocating m_byte; this may be an
+ implementation that allocates directly on a GPU.*/
+ MemoryManager::Ref m_memMan;
+ uint8* m_byte;
+
+ int m_channels;
+ int m_width;
+ int m_height;
+
+public:
+
+ class Error {
+ public:
+ Error(
+ const std::string& reason,
+ const std::string& filename = "") :
+ reason(reason), filename(filename) {}
+
+ std::string reason;
+ std::string filename;
+ };
+
+ /** PGM, PPM, and PBM all come in two versions and are classified as PPM_* files */
+ enum Format {JPEG, BMP, TGA, PCX, ICO, PNG,
+ PPM_BINARY, PGM_BINARY = PPM_BINARY,
+ PPM_ASCII, PGM_ASCII = PPM_ASCII,
+ AUTODETECT, UNKNOWN};
+
+
+ /**
+ The number of channels; either 3 (RGB) or 4 (RGBA)
+ */
+ inline int channels() const {
+ return m_channels;
+ }
+
+ inline int width() const {
+ return m_width;
+ }
+
+ inline int height() const {
+ return m_height;
+ }
+
+ inline const uint8* byte() const {
+ return m_byte;
+ }
+
+ /** Returns a pointer to the underlying data, which is stored
+ in row-major order without row padding.
+ e.g., uint8* ptr = image.rawData();
+ */
+ template
+ inline const Type* rawData() const {
+ return (Type*)m_byte;
+ }
+
+ /** \copybrief GImage::rawData() const */
+ template
+ inline Type* rawData() {
+ return (Type*)m_byte;
+ }
+
+ inline const Color1uint8* pixel1() const {
+ debugAssertM(m_channels == 1, format("Tried to call GImage::pixel1 on an image with %d channels", m_channels));
+ return (Color1uint8*)m_byte;
+ }
+
+ inline Color1uint8* pixel1() {
+ debugAssertM(m_channels == 1, format("Tried to call GImage::pixel1 on an image with %d channels", m_channels));
+ return (Color1uint8*)m_byte;
+ }
+
+ /** Returns a pointer to the upper left pixel
+ as Color4uint8.
+ */
+ inline const Color4uint8* pixel4() const {
+ debugAssertM(m_channels == 4, format("Tried to call GImage::pixel4 on an image with %d channels", m_channels));
+ return (Color4uint8*)m_byte;
+ }
+
+ inline Color4uint8* pixel4() {
+ debugAssert(m_channels == 4);
+ return (Color4uint8*)m_byte;
+ }
+
+ /** Returns a pointer to the upper left pixel
+ as Color3uint8.
+ */
+ inline const Color3uint8* pixel3() const {
+ debugAssertM(m_channels == 3, format("Tried to call GImage::pixel3 on an image with %d channels", m_channels));
+ return (Color3uint8*)m_byte;
+ }
+
+ inline Color3uint8* pixel3() {
+ debugAssert(m_channels == 3);
+ return (Color3uint8*)m_byte;
+ }
+
+ /** Returns the pixel at (x, y), where (0,0) is the upper left. */
+ inline const Color1uint8& pixel1(int x, int y) const {
+ debugAssert(x >= 0 && x < m_width);
+ debugAssert(y >= 0 && y < m_height);
+ return pixel1()[x + y * m_width];
+ }
+
+ /** Returns the pixel at (x, y), where (0,0) is the upper left. */
+ inline Color1uint8& pixel1(int x, int y) {
+ debugAssert(x >= 0 && x < m_width);
+ debugAssert(y >= 0 && y < m_height);
+ return pixel1()[x + y * m_width];
+ }
+
+ /** Returns the pixel at (x, y), where (0,0) is the upper left. */
+ inline const Color3uint8& pixel3(int x, int y) const {
+ debugAssert(x >= 0 && x < m_width);
+ debugAssert(y >= 0 && y < m_height);
+ return pixel3()[x + y * m_width];
+ }
+
+ inline Color3uint8& pixel3(int x, int y) {
+ debugAssert(x >= 0 && x < m_width);
+ debugAssert(y >= 0 && y < m_height);
+ return pixel3()[x + y * m_width];
+ }
+
+ /** Returns the pixel at (x, y), where (0,0) is the upper left. */
+ inline const Color4uint8& pixel4(int x, int y) const {
+ debugAssert(x >= 0 && x < m_width);
+ debugAssert(y >= 0 && y < m_height);
+ return pixel4()[x + y * m_width];
+ }
+
+ inline Color4uint8& pixel4(int x, int y) {
+ debugAssert(x >= 0 && x < m_width);
+ debugAssert(y >= 0 && y < m_height);
+ return pixel4()[x + y * m_width];
+ }
+
+ inline uint8* byte() {
+ return m_byte;
+ }
+
+private:
+
+ void encodeBMP(
+ BinaryOutput& out) const;
+
+ /**
+ The TGA file will be either 24- or 32-bit depending
+ on the number of channels.
+ */
+ void encodeTGA(
+ BinaryOutput& out) const;
+
+ /**
+ Converts this image into a JPEG
+ */
+ void encodeJPEG(
+ BinaryOutput& out) const;
+
+ /**
+ Converts this image into a JPEG
+ */
+ void encodePNG(
+ BinaryOutput& out) const;
+
+ void encodePPM(
+ BinaryOutput& out) const;
+
+ void encodePPMASCII(
+ BinaryOutput& out) const;
+
+ void decodeTGA(
+ BinaryInput& input);
+
+ void decodeBMP(
+ BinaryInput& input);
+
+ void decodeJPEG(
+ BinaryInput& input);
+
+ void decodePCX(
+ BinaryInput& input);
+
+ void decodeICO(
+ BinaryInput& input);
+
+ void decodePNG(
+ BinaryInput& input);
+
+ void decodePPM(
+ BinaryInput& input);
+
+ void decodePPMASCII(
+ BinaryInput& input);
+
+ /**
+ Given [maybe] a filename, memory buffer, and [maybe] a format,
+ returns the most likely format of this file.
+ */
+ static Format resolveFormat(
+ const std::string& filename,
+ const uint8* data,
+ int dataLen,
+ Format maybeFormat);
+
+ void _copy(
+ const GImage& other);
+
+public:
+
+ /** Predicts the image file format of \a filename */
+ static Format resolveFormat(const std::string& filename);
+
+ void flipHorizontal();
+ void flipVertical();
+ void rotate90CW(int numTimes = 1);
+
+ /**
+ Create an empty image of the given size.
+ \sa load()
+ */
+ GImage(
+ int width = 0,
+ int height = 0,
+ int channels = 3,
+ const MemoryManager::Ref& m = MemoryManager::create());
+
+ /**
+ Load an encoded image from disk and decode it.
+ Throws GImage::Error if something goes wrong.
+ */
+ GImage(
+ const std::string& filename,
+ Format format = AUTODETECT,
+ const MemoryManager::Ref& m = MemoryManager::create());
+
+ /**
+ Decodes an image stored in a buffer.
+ */
+ GImage(
+ const unsigned char*data,
+ int length,
+ Format format = AUTODETECT,
+ const MemoryManager::Ref& m = MemoryManager::create());
+
+ GImage(
+ const GImage& other,
+ const MemoryManager::Ref& m = MemoryManager::create());
+
+ GImage& operator=(const GImage& other);
+
+ /**
+ Returns a new GImage that has 4 channels. RGB is
+ taken from this GImage and the alpha from the red
+ channel of the supplied image. The new GImage is passed
+ as a reference parameter for speed.
+ */
+ void insertRedAsAlpha(const GImage& alpha, GImage& output) const;
+
+ /**
+ Returns a new GImage with 3 channels, removing
+ the alpha channel if there is one. The new GImage
+ is passed as a reference parameter for speed.
+ */
+ void stripAlpha(GImage& output) const;
+
+ /**
+ Loads an image from disk (clearing the old one first),
+ using the existing memory manager.
+ */
+ void load(
+ const std::string& filename,
+ Format format = AUTODETECT);
+
+ /**
+ Frees memory and resets to a 0x0 image.
+ */
+ void clear();
+
+ /**
+ Deallocates the pixels.
+ */
+ virtual ~GImage();
+
+ /**
+ Resizes the internal buffer to (\a width x \a height) with the
+ number of \a channels specified.
+
+ \param zero If true, all data is set to 0 (black).
+ */
+ void resize(int width, int height, int channels, bool zero = true);
+
+ /**
+ Copies src sub-image data into dest at a certain offset.
+ The dest variable must already contain an image that is large
+ enough to contain the src sub-image at the specified offset.
+ Returns true on success and false if the src sub-image cannot
+ completely fit within dest at the specified offset. Both
+ src and dest must have the same number of channels.
+ */
+ static bool pasteSubImage(
+ GImage& dest,
+ const GImage& src,
+ int destX,
+ int destY,
+ int srcX,
+ int srcY,
+ int srcWidth,
+ int srcHeight);
+
+ /**
+ creates dest from src sub-image data.
+ Returns true on success and false if the src sub-image
+ is not within src.
+ */
+ static bool copySubImage(GImage & dest, const GImage & src,
+ int srcX, int srcY, int srcWidth, int srcHeight);
+
+ void convertToRGBA();
+
+ void convertToRGB();
+
+ /** Averages color channels if they exist */
+ void convertToL8();
+
+ /**
+ Returns true if format is supported. Format
+ should be an extension string (e.g. "BMP").
+ */
+ static bool supportedFormat(
+ const std::string& format);
+
+ /**
+ Converts a string to an enum, returns UNKNOWN if not recognized.
+ */
+ static Format stringToFormat(
+ const std::string& format);
+
+ /**
+ Encode and save to disk.
+ */
+ void save(
+ const std::string& filename,
+ Format format = AUTODETECT) const;
+
+ /**
+ The caller must delete the returned buffer.
+ TODO: provide a memory manager
+ */
+ void encode(
+ Format format,
+ uint8*& outData,
+ int& outLength) const;
+
+ /**
+ Does not commit the BinaryOutput when done.
+ */
+ void encode(
+ Format format,
+ BinaryOutput& out) const;
+
+ /**
+ Decodes the buffer into this image.
+ @param format Must be the correct format.
+ */
+ void decode(
+ BinaryInput& input,
+ Format format);
+
+ /** Returns the size of this object in bytes */
+ int sizeInMemory() const;
+
+ /** Ok for in == out */
+ static void R8G8B8_to_Y8U8V8(int width, int height, const uint8* in, uint8* out);
+
+ /** Ok for in == out */
+ static void Y8U8V8_to_R8G8B8(int width, int height, const uint8* in, uint8* out);
+
+ /**
+ @param in RGB buffer of numPixels * 3 bytes
+ @param out Buffer of numPixels * 4 bytes
+ @param numPixels Number of RGB pixels to convert
+ */
+ static void RGBtoRGBA(
+ const uint8* in,
+ uint8* out,
+ int numPixels);
+
+ static void RGBtoARGB(
+ const uint8* in,
+ uint8* out,
+ int numPixels);
+
+ static void LtoRGB
+ (const uint8* in,
+ uint8* out,
+ int numPixels);
+
+ static void LtoRGBA
+ (const uint8* in,
+ uint8* out,
+ int numPixels);
+
+ /** Safe for in == out */
+ static void RGBtoBGR(
+ const uint8* in,
+ uint8* out,
+ int numPixels);
+
+ /**
+ Win32 32-bit HDC format.
+ */
+ static void RGBtoBGRA(
+ const uint8* in,
+ uint8* out,
+ int numPixels);
+
+ static void RGBAtoRGB(
+ const uint8* in,
+ uint8* out,
+ int numPixels);
+ /**
+ Uses the red channel of the second image as an alpha channel.
+ */
+ static void RGBxRGBtoRGBA(
+ const uint8* colorRGB,
+ const uint8* alphaRGB,
+ uint8* out,
+ int numPixels);
+
+ /**
+ Flips the image along the vertical axis.
+ Safe for in == out.
+ */
+ static void flipRGBVertical(
+ const uint8* in,
+ uint8* out,
+ int width,
+ int height);
+
+ static void flipRGBAVertical(
+ const uint8* in,
+ uint8* out,
+ int width,
+ int height);
+
+ /**
+ Given a tangent space bump map, computes a new image where the
+ RGB channels are a tangent space normal map and the alpha channel
+ is the original bump map. Assumes the input image is tileable.
+
+ In the resulting image, x = red = tangent, y = green = binormal, and z = blue = normal.
+
+ Particularly useful as part of the idiom:
+
+
+ G3D provides these for common classes like G3D::Vector3 and G3D::Sphere.
+ If you use a custom class, or a pointer to a custom class, you will need
+ to define those functions.
+
+ Moving %Set Members
+
+ No mesh class is provided with G3D because there isn't an "ideal"
+ mesh format-- one application needs keyframed animation, another
+ skeletal animation, a third texture coordinates, a fourth
+ cannot precompute information, etc. Instead of compromising, this
+ class implements the hard parts of mesh computation and you can write
+ your own ideal mesh class on top of it.
+
+ \sa G3D::ArticulatedModel, G3D::IFSModel
+ */
+class MeshAlg {
+public:
+
+ /** \deprecated */
+ typedef PrimitiveType Primitive;
+
+ /** Adjacency information for a vertex.
+ Does not contain the vertex position or normal,
+ which are stored in the MeshAlg::Geometry object.
+ Vertexs must be stored in an array
+ parallel to (indexed in the same way as)
+ MeshAlg::Geometry::vertexArray.
+ */
+ class Vertex {
+ public:
+ Vertex() {}
+
+ /**
+ Array of edges adjacent to this vertex.
+ Let e = edgeIndex[i].
+ edge[(e >= 0) ? e : ~e].vertexIndex[0] == this
+ vertex index.
+
+ Edges may be listed multiple times if they are
+ degenerate.
+ */
+ SmallArray edgeIndex;
+
+ /**
+ Returns true if e or ~e is in the edgeIndex list.
+ */
+ inline bool inEdge(int e) const {
+ return edgeIndex.contains(~e) || edgeIndex.contains(e);
+ }
+
+ /**
+ Array of faces containing this vertex. Faces
+ may be listed multiple times if they are degenerate.
+ */
+ SmallArray faceIndex;
+
+ inline bool inFace(int f) const {
+ debugAssert(f >= 0);
+ return faceIndex.contains(f);
+ }
+ };
+
+
+ /**
+ Oriented, indexed triangle.
+ */
+ class Face {
+ public:
+ Face();
+
+ /**
+ Used by Edge::faceIndex to indicate a missing face.
+ This is a large negative value.
+ */
+ static const int NONE;
+
+
+ /**
+ Vertices in the face in counter-clockwise order.
+ Degenerate faces may include the same vertex multiple times.
+ */
+ int vertexIndex[3];
+
+ inline bool containsVertex(int v) const {
+ return contains(vertexIndex, 3, v);
+ }
+
+ /**
+ Edge indices in counter-clockwise order. Edges are
+ undirected, so it is important to know which way
+ each edge is pointing in a face. This is encoded
+ using negative indices.
+
+ If edgeIndex[i] >= 0 then this face
+ contains the directed edge
+ between vertex indices
+ edgeArray[face.edgeIndex[i]].vertexIndex[0]
+ and
+ edgeArray[face.edgeIndex[i]].vertexIndex[1].
+
+ If edgeIndex[i] < 0 then
+ ~edgeIndex[i] (i.e. the two's
+ complement of) is used and this face contains the directed
+ edge between vertex indices
+ edgeArray[~face.edgeIndex[i]].vertexIndex[0]
+ and
+ edgeArray[~face.edgeIndex[i]].vertexIndex[1].
+
+ Degenerate faces may include the same edge multiple times.
+ */
+ // Temporarily takes on the value Face::NONE during adjacency
+ // computation to indicate an edge that has not yet been assigned.
+ int edgeIndex[3];
+
+ inline bool containsEdge(int e) const {
+ if (e < 0) {
+ e = ~e;
+ }
+ return contains(edgeIndex, 3, e) || contains(edgeIndex, 3, ~e);
+ }
+
+ /** Contains the forward edge e if e >= 0 and the backward edge
+ ~e otherwise. */
+ inline bool containsDirectedEdge(int e) const {
+ return contains(edgeIndex, 3, e);
+ }
+ };
+
+
+ /** Oriented, indexed edge */
+ class Edge {
+ public:
+ Edge();
+
+ /** Degenerate edges may include the same vertex times. */
+ int vertexIndex[2];
+
+ inline bool containsVertex(int v) const {
+ return contains(vertexIndex, 2, v);
+ }
+
+ /**
+ The edge is directed forward in face 0
+ backward in face 1. Face index of MeshAlg::Face::NONE
+ indicates a boundary (a.k.a. crack, broken) edge.
+ */
+ int faceIndex[2];
+
+ /** Returns true if f is contained in the faceIndex array in either slot.
+ To see if it is forward in that face, just check edge.faceIndex[0] == f.*/
+ inline bool inFace(int f) const {
+ return contains(faceIndex, 2, f);
+ }
+
+ /**
+ Returns true if either faceIndex is NONE.
+ */
+ inline bool boundary() const {
+ return (faceIndex[0] == Face::NONE) ||
+ (faceIndex[1] == Face::NONE);
+ }
+
+ /**
+ Returns the reversed edge.
+ */
+ inline Edge reverse() const {
+ Edge e;
+ e.vertexIndex[0] = vertexIndex[1];
+ e.vertexIndex[1] = vertexIndex[0];
+ e.faceIndex[0] = faceIndex[1];
+ e.faceIndex[1] = faceIndex[0];
+ return e;
+ }
+ };
+
+
+ /**
+ Convenient for passing around the per-vertex data that changes under
+ animation. The faces and edges are needed to interpret
+ these values.
+ */
+ class Geometry {
+ public:
+ /** Vertex positions */
+ Array vertexArray;
+
+ /** Vertex normals */
+ Array normalArray;
+
+ /**
+ Assignment is optimized using SSE.
+ */
+ Geometry& operator=(const Geometry& src);
+
+ void clear() {
+ vertexArray.clear();
+ normalArray.clear();
+ }
+ };
+
+ /**
+ Given a set of vertices and a set of indices for traversing them
+ to create triangles, computes other mesh properties.
+
+