AABox(low.min(high), low.max(high));
*/
- inline AABox(const Vector3& low, const Vector3& high) {
+ AABox(const Point3& low, const Point3& high) {
set(low, high);
}
+ AABox operator*(float f) const {
+ if (f < 0) {
+ return AABox(hi * f, lo * f);
+ } else {
+ return AABox(lo * f, hi * f);
+ }
+ }
+
+ AABox operator/(float f) const {
+ return *this * (1.0f / f);
+ }
+
/** Assumes that low is less than or equal to high along each dimension.
*/
- inline void set(const Vector3& low, const Vector3& high) {
+ inline void set(const Point3& low, const Point3& high) {
debugAssert(
(low.x <= high.x) &&
(low.y <= high.y) &&
(low.z <= high.z));
+ debugAssert(! low.isNaN() && ! high.isNaN());
lo = low;
hi = high;
}
/**
- Grows to include the bounds of a
+ Grows to include the bounds of \a a
*/
inline void merge(const AABox& a) {
- lo = lo.min(a.lo);
- hi = hi.max(a.hi);
+ if (isEmpty()) {
+ lo = a.lo;
+ hi = a.hi;
+ } else if (! a.isEmpty()) {
+ lo = lo.min(a.lo);
+ hi = hi.max(a.hi);
+ }
}
- inline void merge(const Vector3& a) {
- lo = lo.min(a);
- hi = hi.max(a);
+ inline void merge(const Point3& a) {
+ if (isEmpty()) {
+ lo = hi = a;
+ } else {
+ lo = lo.min(a);
+ hi = hi.max(a);
+ }
}
+ void merge(const class Box& b);
+
void serialize(class BinaryOutput& b) const;
void deserialize(class BinaryInput& b);
inline bool isFinite() const {
- return lo.isFinite() && hi.isFinite();
+ return isEmpty() || (lo.isFinite() && hi.isFinite());
}
- inline const Vector3& low() const {
+ /** Returns not-a-number if empty */
+ inline const Point3& low() const {
return lo;
}
- inline const Vector3& high() const {
+ /** Returns not-a-number if empty */
+ inline const Point3& high() const {
return hi;
}
@@ -110,25 +155,33 @@ public:
static const AABox& zero();
+ static const AABox& empty();
+
/**
- Returns the centroid of the box.
+ Returns the centroid of the box (NaN if empty)
*/
- inline Vector3 center() const {
+ inline Point3 center() const {
return (lo + hi) * 0.5;
}
- Vector3 corner(int index) const;
+ Point3 corner(int index) const;
/**
Distance from corner(0) to the next corner along axis a.
*/
inline float extent(int a) const {
+ if (isEmpty()) {
+ return 0.0f;
+ }
debugAssert(a < 3);
return hi[a] - lo[a];
}
inline Vector3 extent() const {
+ if (isEmpty()) {
+ return Vector3::zero();
+ }
return hi - lo;
}
@@ -140,46 +193,46 @@ public:
*/
void split(const Vector3::Axis& axis, float location, AABox& low, AABox& high) const;
- /**
- Conservative culling test for up to 32 planes.
- Returns true if there exists a plane[p] for
+ /**
+ Conservative culling test for up to 32 planes.
+ Returns true if there exists a plane[p] for
which the entire object is in the negative half space
(opposite the plane normal).
- testMask and childMask
- are used for optimizing bounding volume hierarchies.
+ testMask and childMask
+ are used for optimizing bounding volume hierarchies.
The version of this method that produces childMask
is slower than the version without; it should only
be used for parent nodes.
- @param cullingPlaneIndex The index of the first plane for which
- the entire object is in the negative half-space. The function
- exits early when one plane is found. -1 when the function
- returns false (i.e. when no plane culls the whole object).
+ @param cullingPlaneIndex The index of the first plane for which
+ the entire object is in the negative half-space. The function
+ exits early when one plane is found. -1 when the function
+ returns false (i.e. when no plane culls the whole object).
- @param testMask If bit p is 0, the
- bounding volume automatically passes the culling test for
- plane[p] (i.e. it is known that the volume
- is entirely within the positive half space). The function
+ @param testMask If bit p is 0, the
+ bounding volume automatically passes the culling test for
+ plane[p] (i.e. it is known that the volume
+ is entirely within the positive half space). The function
must return false if testMask is 0 and test all planes
when testMask is -1 (0xFFFFFFFF).
@param childMask Test mask for the children of this volume.
- */
- bool culledBy(
- const Array\#include(filename) allows subsitution of the contents of
+filename for any single expression in an Any. The filename is interpreted
+relative to the file being parsed, and inside of the included file, relative filenames
+are interpreted with respect to the included file (and so on, recursively for nested
+inclusion).
+
+Filenames are resolved with System::resolve and then System::findDataFile if not found,
+so they may contain environment variables.
\section Parsing
@@ -117,24 +130,12 @@ Vector3::Vector3(const Any& any) {
}
-It is often convenient to iterate through the table portion:
-
-
- for (Any::AnyTable::Iterator it = any.table().begin(); it.hasMore(); ++it) {
- const std::string& k = toLower(it->key);
- if (key == "hello") {
- ...
- } else if (key == "goodbye") {
- ...
- } else {
- any.verify(false, "Unsupported key: " + it->key);
- }
- }
-
+It is often convenient to iterate through the table portion using G3D::AnyTableReader.
\section BNF
Serialized format BNF:
+\htmlonly
identifier ::= (letter | "_") (letter | digit | "_")* identifier-op ::= "::" | "->" | "." @@ -145,18 +146,19 @@ comment ::= C++ single or multi-line comments separator ::= "," | ";" number ::=+\endhtmlonly Except for single-line comments, whitespace is not significant. All parsing is case-insensitive. @@ -167,7 +169,7 @@ can only appear in the locations where a value is expected. This means that it cannot yield more than one element of an array and cannot serve as the pair in a table. -The deserializer allows the substitution of [] for () when writing +The deserializer allows the substitution of [] or {} for () when writing tuples and ";" for ",". These are convenient when mimicing a programming language, e.g.,-string ::= +string ::= boolean ::= "True" | "False" -none ::= "None" -array ::= ("(" | "[") [ value (separator value)* [separator] ] (")" | "]") -pair ::= (identifier | string) "=" value -table ::= "{" [ pair (separator pair)* [separator] ] "}" +nil ::= "Nil" | "None" +array ::= ("(" | "[" | "{") [value (separator value)* [separator] ] (")" | "]" | "}") +pair ::= (identifier | string) ("=" | ":") value +table ::= ("(" | "[" | "{") [ pair (separator pair)* [separator] ] (")" | "]" | "}") named-array ::= identifier-exp array named-table ::= identifier-exp table include ::= "#" "include" "(" string ")" -value ::= [comment] (none | number | boolean | string | array | table | named-array | named-table | include) +value ::= [comment] (nil | number | boolean | string | array | table | named-array | named-table | include)
"[ printf("hello world."); clearScreen();]"
parses as an array containing two named arrays within it. The
@@ -176,11 +178,13 @@ which also convenient when commenting out the last element.
The serializer indents four spaces for each level of nesting.
Tables are written with the keys in alphabetic order.
+
+\sa G3D::AnyTableReader
*/
class Any {
public:
- enum Type {NONE, BOOLEAN, NUMBER, STRING, ARRAY, TABLE};
+ enum Type {NIL, BOOLEAN, NUMBER, STRING, ARRAY, TABLE, EMPTY_CONTAINER};
static std::string toString(Type t);
@@ -208,7 +212,7 @@ private:
/** Called from deserialize() */
static void deserializeComment(TextInput& ti, Token& token, std::string& comment);
- /** NONE, BOOLEAN, and NUMBER are stored directly in the Any */
+ /** NIL, BOOLEAN, and NUMBER are stored directly in the Any */
union SimpleValue {
bool b;
double n;
@@ -218,6 +222,11 @@ private:
inline SimpleValue(double x) : n(x) {}
};
+ /** The three options for Data::bracket */
+ static const char* PAREN;
+ static const char* BRACKET;
+ static const char* BRACE;
+
class Data {
public:
/** ARRAY, TABLE, or STRING value only. NULL otherwise. */
@@ -240,6 +249,16 @@ private:
std::string name;
+ /** If this Any was created by parsing an #include expression and
+ has not been modified since, this is the original comment and
+ include statement, as
+ it originally appeared in the file (e.g., it may contain a relative
+ filename). If this is non-empty, then when serialized, this
+ Any will turn into an #include expression instead of unparsing
+ its contents of the any.
+ */
+ std::string includeLine;
+
/** 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
@@ -249,10 +268,16 @@ private:
Source source;
+ /** Two-character string of "{}", "[]", or "()"; to be used when unparsing. */
+ const char* bracket;
+
+ /** ';' or ',' separator to be used when unparsing */
+ char separator;
+
private:
/** Called by create() */
- inline Data(Type t) : type(t), referenceCount(1) {}
+ inline Data(Type t, const char* b, char s) : type(t), referenceCount(1), bracket(b), separator(s) {}
/** Called by destroy */
~Data();
@@ -261,12 +286,11 @@ private:
/** Clones the argument */
static Data* create(const Data* d);
- static Data* create(Type t);
+ static Data* create(Type t, const char* b = NULL, char s = '\0');
/** 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
@@ -283,12 +307,11 @@ private:
SimpleValue m_simpleValue;
mutable Data* m_data;
- /** Called before every read operation to ensure that this object
- is not a placeholder. */
+ /** Called before every read operation. */
void beforeRead() const;
- /** Called before every write operation to wipe the placeholder
- status. */
+ /** Called before every write operation to this Any. Wipes the placeholder
+ status and includedFrom entry. */
void beforeWrite();
/** Decrements the reference count (if there is one). If the
@@ -316,43 +339,61 @@ private:
/** 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
+ /** Read until a separator 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);
+ static void readUntilSeparatorOrClose(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 {
+ bool isPlaceholder() const {
return ! m_placeholderName.empty();
}
+
+ 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);
+ Any _get(const std::string& key, const Any& defaultVal) const;
+ void _set(const std::string& key, const Any& val);
+
+ void _parse(const std::string& src);
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;
+
+ KeyNotFound(const Data* data) {
+ if (data) {
+ filename = data->source.filename;
+ line = data->source.line;
+ character = data->source.character;
+ }
+ }
};
/** Thrown by operator[] when an array index is not present. */
- class IndexOutOfBounds : public Exception {
+ class IndexOutOfBounds : public ParseError {
public:
int index;
int size;
- inline IndexOutOfBounds() : index(0), size(0) {}
- inline IndexOutOfBounds(int i, int s) : index(i), size(s) {}
+ IndexOutOfBounds() : index(0), size(0) {}
+ IndexOutOfBounds(const Data* data, int i, int s) : index(i), size(s) {
+ if (data) {
+ filename = data->source.filename;
+ line = data->source.line;
+ character = data->source.character;
+ }
+ message = format("Index out of bounds: index = %d, array size = %d", i, s);
+ }
};
- /** NONE constructor */
+ /** NIL constructor */
Any();
/** Deserialize */
@@ -361,108 +402,133 @@ public:
Any(const Any& x);
/** NUMBER constructor */
- Any(double x);
+ explicit Any(double x);
-#ifdef G3D_32BIT
- /** NUMBER constructor */
- Any(int64 x);
-#endif // G3D_32BIT
+ explicit Any(float x);
-#if 0
+ #if defined(G3D_32Bit) || defined(_MSC_VER)
/** NUMBER constructor */
- Any(int32 x);
-#endif // 0
+ explicit Any(int64 x) : m_type(NUMBER), m_simpleValue((double)x), m_data(NULL) {}
+ #endif
/** NUMBER constructor */
- Any(long x);
+ explicit Any(long x);
/** NUMBER constructor */
- Any(int x);
+ explicit Any(int x);
/** NUMBER constructor */
- Any(short x);
+ explicit Any(char x);
+
+ /** NUMBER constructor */
+ explicit Any(short x);
/** BOOLEAN constructor */
- Any(bool x);
+ explicit Any(bool x);
/** STRING constructor */
- Any(const std::string& x);
+ explicit Any(const std::string& x);
/** STRING constructor */
- Any(const char* x);
+ explicit Any(const char* x);
+
+ /** \a t must be ARRAY or TABLE
+ \param brackets must be "" (defaults to {} for table, () for array), "[]", "()", or "{}"
+ \param separator must be ';', ',', or '\0' (defaults to ',' for array and ';' for table)
+ */
+ explicit Any(Type t, const std::string& name = "", const std::string& brackets = "", const char separator = '\0');
+
+ /** Extensible constructor: call the toAny() method of any class. */
+ template
- AnyKeyIterator r(a);
- r.getIfPresent("enabled", enabled);
- r.getIfPresent("showSamples", showSamples);
- r.getIfPresent("showTiles", showTiles);
+ \code
+ AnyTableReader r(a);
+ r.getIfPresent("enabled", enabled);
+ r.getIfPresent("showSamples", showSamples);
+ r.get("showTiles", showTiles);
r.verifyDone();
-
+ \endcode
\beta
*/
@@ -665,44 +894,21 @@ private:
public:
/** Verifies that \a is a TABLE with the given \a name. */
- AnyTableReader(const std::string& name, const Any& a) : m_any(a) {
- try {
- m_any.verifyType(Any::TABLE);
- m_any.verifyName(name);
- } catch (const ParseError& e) {
- // If an exception is thrown, the destructors will not be
- // invoked automatically.
- m_any.~Any();
- m_alreadyRead.~Set();
- throw e;
- }
- }
+ AnyTableReader(const std::string& name, const Any& a);
/** Verifies that \a is a TABLE. */
- AnyTableReader(const Any& a) : m_any(a) {
- try {
- m_any.verifyType(Any::TABLE);
- } catch (const ParseError& e) {
- // If an exception is thrown, the destructors will not be
- // invoked automatically.
- m_any.~Any();
- m_alreadyRead.~Set();
- throw e;
- }
- }
+ AnyTableReader(const Any& a);
bool hasMore() const {
return m_any.size() > m_alreadyRead.size();
}
/** Verifies that all keys have been read. */
- void verifyDone() const {
- if (hasMore()) {
- // Generate all keys
- // Remove the ones we've read
- // Assert the rest
- // any.verify("");
- }
+ void verifyDone() const;
+
+ /** Return the underlying Any. */
+ const Any& any() const {
+ return m_any;
}
#if 0
@@ -714,30 +920,67 @@ public:
AnyKeyIterator& operator++();
#endif
+
+ /** \copydoc get(const std::string& s, ValueType& v) */
+ void get(const std::string& s, std::string& v) {
+ v = m_any[s].string();
+ m_alreadyRead.insert(s);
+ }
+
+ /** \copydoc get(const std::string& s, ValueType& v) */
+ void get(const std::string& s, uint8& v) {
+ v = uint8(m_any[s].number());
+ m_alreadyRead.insert(s);
+ }
+
+ /** \copydoc get(const std::string& s, ValueType& v) */
+ void get(const std::string& s, uint16& v) {
+ v = uint16(m_any[s].number());
+ m_alreadyRead.insert(s);
+ }
+
+ /** Read an entire array at once.*/
+ template
+ \code
bool __cdecl myLT(const MyClass& elem1, const MyClass& elem2) {
return elem1.x < elem2.x;
}
-
+ \endcode
Note that for pointer arrays, the const must come
after the class name, e.g., Array uses:
-
+ \code
bool __cdecl myLT(MyClass*const& elem1, MyClass*const& elem2) {
return elem1->x < elem2->x;
}
-
+ \endcode
or a functor, e.g.,
-
+ \code
bool
less_than_functor::operator()( const double& lhs, const double& rhs ) const
{
return( lhs < rhs? true : false );
}
-
+\endcode
*/
// void sort(bool (__cdecl *lessThan)(const T& elem1, const T& elem2)) {
// std::sort(data, data + num, lessThan);
@@ -955,14 +1118,14 @@ return( lhs < rhs? true : false );
Sorts the array in increasing order using the > or < operator. To
invoke this method on Array
+ \code
bool T::operator>(const T& other) const {
return ...;
}
bool T::operator<(const T& other) const {
return ...;
}
-
+ \endcode
*/
void sort(int direction = SORT_INCREASING) {
if (direction == SORT_INCREASING) {
@@ -1053,7 +1216,7 @@ return( lhs < rhs? true : false );
// Form a table of buckets for lt, eq, and gt
Array
BinaryInput master(...);
@@ -176,6 +180,7 @@ public:
// Now read from subset (it is ok for master to go out of scope)
+ \endhtmlonly
*/
BinaryInput(
const uint8* data,
@@ -199,24 +204,13 @@ public:
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) {
+ uint8 operator[](int64 n) {
setPosition(n);
return readUInt8();
}
@@ -224,11 +218,11 @@ public:
/**
Returns the length of the file in bytes.
*/
- inline int64 getLength() const {
+ int64 getLength() const {
return m_length;
}
- inline int64 size() const {
+ int64 size() const {
return getLength();
}
@@ -236,15 +230,26 @@ public:
Returns the current byte position in the file,
where 0 is the beginning and getLength() - 1 is the end.
*/
- inline int64 getPosition() const {
+ int64 getPosition() const {
return m_pos + m_alreadyRead;
}
+ /**
+ Returns a pointer to the internal memory buffer.
+ May throw an exception for huge files.
+ */
+ const uint8* getCArray() {
+ if (m_alreadyRead > 0 || m_bufferLength < m_length) {
+ throw "Cannot getCArray for a huge file";
+ }
+ return m_buffer;
+ }
+
/**
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) {
+ 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)) {
@@ -255,25 +260,31 @@ public:
/**
Goes back to the beginning of the file.
*/
- inline void reset() {
+ void reset() {
setPosition(0);
}
- inline int8 readInt8() {
+ void readBytes(void* bytes, int64 n);
+
+ int8 readInt8() {
prepareToRead(1);
return m_buffer[m_pos++];
}
-
- inline bool readBool8() {
+
+ bool readBool8() {
return (readInt8() != 0);
}
-
- inline uint8 readUInt8() {
+
+ uint8 readUInt8() {
prepareToRead(1);
return ((uint8*)m_buffer)[m_pos++];
}
+
+ unorm8 readUNorm8() {
+ return unorm8::fromBits(readUInt8());
+ }
- uint16 inline readUInt16() {
+ uint16 readUInt16() {
prepareToRead(2);
m_pos += 2;
@@ -295,12 +306,12 @@ public:
}
- inline int16 readInt16() {
+ int16 readInt16() {
uint16 a = readUInt16();
return *(int16*)&a;
}
- inline uint32 readUInt32() {
+ uint32 readUInt32() {
prepareToRead(4);
m_pos += 4;
@@ -326,19 +337,19 @@ public:
}
- inline int32 readInt32() {
+ int32 readInt32() {
uint32 a = readUInt32();
return *(int32*)&a;
}
uint64 readUInt64();
- inline int64 readInt64() {
+ int64 readInt64() {
uint64 a = readUInt64();
return *(int64*)&a;
}
- inline float32 readFloat32() {
+ float32 readFloat32() {
union {
uint32 a;
float32 b;
@@ -347,7 +358,7 @@ public:
return b;
}
- inline float64 readFloat64() {
+ float64 readFloat64() {
union {
uint64 a;
float64 b;
@@ -356,31 +367,34 @@ public:
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.
+ Always consumes \a maxLength characters. Reads a string until NULL or \a maxLength characters. Does not require NULL termination.
*/
- std::string readString(int64 n);
+ std::string readString(int64 maxLength);
/**
- Reads until NULL or the end of the file is encountered.
+ Reads a string until NULL or end of file.
*/
std::string readString();
- /** Reads until \r, \r\n, \n\r, \n or the end of the file is encountered. Consumes the newline.*/
+ /** Read a string (which may contain NULLs) of exactly numBytes bytes, including the final terminator if there is one. If there is a NULL in the string before
+ the end, then only the part up to the first NULL is returned although all bytes are read.*/
+ std::string readFixedLengthString(int numBytes);
+
+ /**
+ Reads a string until NULL, newline ("\r", "\n", "\r\n", "\n\r") or the end of the file is encountered. Consumes the newline.
+ */
std::string readStringNewline();
/**
Reads until NULL or the end of the file is encountered.
If the string has odd length (including NULL), reads
- another byte.
+ another byte. This is a common format for 16-bit alignment
+ in files.
*/
std::string readStringEven();
-
+ /** Reads a uint32 and then calls readString(maxLength) with that value as the length. */
std::string readString32();
Vector4 readVector4();
@@ -393,15 +407,15 @@ public:
/**
Skips ahead n bytes.
*/
- inline void skip(int64 n) {
+ 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;
+ bool hasMore() const {
+ return m_pos + m_alreadyRead < m_length;
}
/** Prepares for bit reading via readBits. Only readBits can be
diff --git a/deps/g3dlite/include/G3D/BinaryOutput.h b/deps/g3dlite/include/G3D/BinaryOutput.h
index d81ec56a6..45e1124d7 100644
--- a/deps/g3dlite/include/G3D/BinaryOutput.h
+++ b/deps/g3dlite/include/G3D/BinaryOutput.h
@@ -1,17 +1,17 @@
/**
- @file BinaryOutput.h
+ \file G3D/BinaryOutput.h
- @maintainer Morgan McGuire, graphics3d.com
+ \maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @created 2001-08-09
- @edited 2008-01-24
+ \created 2001-08-09
+ \edited 2011-08-24
- Copyright 2000-2006, Morgan McGuire.
+ Copyright 2000-2012, Morgan McGuire.
All rights reserved.
*/
-#ifndef G3D_BINARYOUTPUT_H
-#define G3D_BINARYOUTPUT_H
+#ifndef G3D_BinaryOutput_h
+#define G3D_BinaryOutput_h
#include "G3D/platform.h"
#include Box box = cframe.toObjectSpace(Box(center - extent/2, center + extent/2));
*/
class Box {
@@ -41,29 +40,14 @@ private:
friend class CoordinateFrame;
/**
- - 3 2 7 6 - - 0 1 4 5 - - front back (seen through front) -+ Axes with length equal to the 4 edges that run along each of them */ - Vector3 _corner[8]; - - /** - Unit axes. - */ - Vector3 _axis[3]; + Vector3 _edgeVector[3]; - Vector3 _center; - - /** - Extent along each axis. - */ - Vector3 _extent; + Point3 _center; float _area; + float _volume; void init( @@ -72,38 +56,47 @@ private: public: - /** - Does not initialize the fields. - */ Box(); + explicit Box(const Any& a); + /** Constructs a box from two opposite corners. */ - Box( - const Vector3& min, + Box(const Vector3& min, const Vector3& max); - static Box inf(); + Box(const Vector3& osMin, + const Vector3& osMax, + const CoordinateFrame& frame); - Box(class BinaryInput& b); + Box(class BinaryInput& b); Box(const class AABox& b); - void serialize(class BinaryOutput& b) const; - void deserialize(class BinaryInput& b); + explicit Box(const Point3& p); + static Box inf(); + + Any toAny() const; + + void serialize(class BinaryOutput& b) const; + void deserialize(class BinaryInput& b); + /** Returns the object to world transformation for - this box. localFrame().worldToObject(...) takes + this box, where the origin is the center of the box. localFrame().worldToObject(...) takes objects into the space where the box axes are (1,0,0), (0,1,0), (0,0,1). Note that there is no scaling in this transformation. */ CoordinateFrame localFrame() const; + /** \sa localFrame */ void getLocalFrame(CoordinateFrame& frame) const; + Box operator*(float f) const; + /** Returns the centroid of the box. */ @@ -111,18 +104,39 @@ public: return _center; } + /** + \htmlonly +
+
- inline Vector3 corner(int i) const {
- debugAssert(i < 8);
- return _corner[i];
- }
+ 2--------3
+ / : /|
+ / : / |
+ 6--------7 |
+ | : | |
+ | 0....|..1
+ | / | /
+ |/ |/
+ 4--------5
+
+ y
+ ^
+ |
+ |-->x
+ z/
+
+
+
+ \endhtmlonly
+ */
+ Vector3 corner(int i) const;
/**
Unit length.
*/
inline Vector3 axis(int a) const {
debugAssert(a < 3);
- return _axis[a];
+ return _edgeVector[a].direction();
}
/**
@@ -131,17 +145,43 @@ public:
*/
inline float extent(int a) const {
debugAssert(a < 3);
- return (float)_extent[a];
+ return _edgeVector[a].length();
}
inline Vector3 extent() const {
- return _extent;
+ return Vector3(_edgeVector[0].length(), _edgeVector[1].length(), _edgeVector[2].length());
}
/**
Returns the four corners of a face (0 <= f < 6).
- The corners are returned to form a counter clockwise quad facing outwards.
- */
+ The corners are returned to form a clockwise quad facing outwards.
+
+
+
+ +--------+
+ / : /|
+ / : / |
+ +--------+ |
+ | : | |
+ | +....|..+
+ | / | /
+ |/ |/
+ +--------+
+
+ y
+ ^
+ |
+ |-->x
+z/
+ Faces are in the following order:
+ 0: -Z
+ 1: X
+ 2: Z
+ 3: Y
+ 4: -X
+ 5: -Y
+
+ */
void getFaceCorners(
int f,
Vector3& v0,
@@ -150,24 +190,24 @@ public:
Vector3& v3) const;
- /**
+ /**
See AABox::culledBy
- */
+ */
bool culledBy
(
- const Array| Vector3 | LineSegment | Ray * | Line | Plane | Triangle | Sphere | Cylinder | Capsule | AABox | Box | |
| Vector3 | \link Vector3::operator== V3::==\endlink \link Vector3::fuzzyEq V3::fuzzy \endlink \link G3D::distance distance \endlink | ||||||||||
| Point3 | LineSegment | Ray * | Line | Plane | Triangle | Sphere | Cylinder | Capsule | AABox | Box | |
| Point3 | \link Vector3::operator== P3::==\endlink \link Vector3::fuzzyEq V3::fuzzy \endlink \link G3D::distance distance \endlink | ||||||||||
| LineSegment | \link LineSegment::closestPoint LS::closestPoint\endlink \link LineSegment::distance LS::distance\endlink \link CollisionDetection::closestPointOnLineSegment CD\endlink | ||||||||||
| Ray * | Ray::closestPoint Ray::distance | ||||||||||
| Line | Line::closestPoint Line::distance | \link CollisionDetection::closestPointsBetweenLineAndLine CD\endlink | |||||||||
| Plane | |||||||||||
| Triangle | |||||||||||
| Sphere | Sphere::contains | \link CollisionDetection::collisionTimeForMovingPointFixedSphere CD \endlink, \link Ray::intersectionTime R::time\endlink | |||||||||
| Sphere | Sphere::contains | \link CollisionDetection::collisionTimeForMovingPointFixedSphere CD \endlink, \link Ray::intersectionTime R::time\endlink | \link G3D::CollisionDetection::fixedSolidSphereIntersectsFixedTriangle CD\endlink | +\link G3D::CollisionDetection::penetrationDepthForFixedSphereFixedSphere CD\endlink | |||||||
| Cylinder | Cylinder::contains | ||||||||||
| Capsule | Capsule::contains | ||||||||||
| Capsule | Capsule::contains | \link G3D::CollisionDetection::collisionTimeForMovingSphereFixedTriangle CD\endlink | |||||||||
| AABox | AABox::contains | \link CollisionDetection::fixedSolidBoxIntersectsFixedTriangle CD\endlink | |||||||||
| Box | Box::contains | (treat as Ray) | \link CollisionDetection::collisionTimeForMovingPointFixedBox CD\endlink | (treat as Ray) | \link CollisionDetection::penetrationDepthForFixedBoxFixedPlane CD \endlink | \link CollisionDetection::penetrationDepthForFixedBoxFixedPlane CD\endlink | \link CollisionDetection::penetrationDepthForFixedSphereFixedBox CD\endlink | None (use OPCODE) | \link CollisionDetection::movingSpherePassesThroughFixedBox CD \endlink | \link CollisionDetection::penetrationDepthForFixedBoxFixedBox CD\endlink | \link CollisionDetection::penetrationDepthForFixedBoxFixedBox CD\endlink |
point on the line segment.
- */
- static Vector3 closestPointOnLineSegment(
- const Vector3& v0,
- const Vector3& v1,
- const Vector3& point);
+ const class Sphere& sphere,
+ const Vector3& velocity,
+ const float collisionTime,
+ const Vector3& collisionLocation);
/**
- Finds the closest point on a line segment to a given point.
+ Finds the closest point on a line segment to a given point.
- @note This is an optimization to closestPointOnLineSegment. Edge length
- and direction can be used in this function if already pre-calculated. This
- prevents doing the same work twice.
+ @param v0 line vertex 1.
+ @param v1 line vertex 2.
+ @param point External point.
- @param v0 line vertex 0.
- @param v1 line vertex 1.
+ @return Closests point to point on the line segment.
+ */
+ static Vector3 closestPointOnLineSegment(
+ const Vector3& v0,
+ const Vector3& v1,
+ const Vector3& point);
+
+ /**
+ Finds the closest point on a line segment to a given point.
+
+ @note This is an optimization to closestPointOnLineSegment. Edge length
+ and direction can be used in this function if already pre-calculated. This
+ prevents doing the same work twice.
+
+ @param v0 line vertex 0.
+ @param v1 line vertex 1.
@param edgeDirection The direction of the segment (unit length).
@param edgeLength The length of the segment.
@param point External point.
- @return Closests point to point on the line segment.
- */
+ @return Closests point to point on the line segment.
+ */
static Vector3 closestPointOnLineSegment(
- const Vector3& v0,
- const Vector3& v1,
+ const Vector3& v0,
+ const Vector3& v1,
const Vector3& edgeDirection,
float edgeLength,
- const Vector3& point);
+ 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.
+ Finds the closest point on the perimeter of the triangle to an external point;
+ given a triangle defined by three points v0, v1, & v2, and the external point.
- @param v0 Triangle vertex 0.
- @param v1 Triangle vertex 1.
- @param v2 Triangle vertex 2.
- @param point External point.
+ @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.
- */
+ @return Closests point to point on the perimeter of the
+ triangle.
+ */
static Vector3 closestPointOnTrianglePerimeter(
- const Vector3& v0,
- const Vector3& v1,
- const Vector3& v2,
- const Vector3& point);
+ const Vector3& v0,
+ const Vector3& v1,
+ const Vector3& v2,
+ const Vector3& point);
- /**
- Finds the closest point on the perimeter of the triangle to an external point;
- given a triangle defined by the array of points v, its edge directions and
- their lengths, as well as the external point.
+ /**
+ Finds the closest point on the perimeter of the triangle to an external point;
+ given a triangle defined by the array of points v, its edge directions and
+ their lengths, as well as the external point.
- @note This is an optimization to closestPointToTrianglePerimeter. Edge length
- and direction can be used in this function if already pre-calculated. This
- prevents doing the same work twice.
+ @note This is an optimization to closestPointToTrianglePerimeter. Edge length
+ and direction can be used in this function if already pre-calculated. This
+ prevents doing the same work twice.
- @param v Triangle vertices.
- @param point External point.
+ @param v Triangle vertices.
+ @param point External point.
@param edgeIndex The point lies on the edge between v[edgeIndex] and v[(edgeIndex + 1) % 3]
- @return Closest point to point on the perimeter of the
- triangle.
- */
+ @return Closest point to point on the perimeter of the
+ triangle.
+ */
static Vector3 closestPointOnTrianglePerimeter(
const Vector3 v[3],
const Vector3 edgeDirection[3],
const float edgeLength[3],
- const Vector3& point,
+ const Vector3& point,
int& edgeIndex);
/**
- Tests whether a point is contained within the triangle defined by
- v0, v1, and v2 and its plane's normal.
+ Tests whether a point is contained within the triangle defined by
+ v0, v1, and v2 and its plane's normal.
- @param v0 Triangle vertex 0.
- @param v1 Triangle vertex 1.
- @param v2 Triangle vertex 2.
- @param normal Normal to triangle's plane.
- @param point The point in question.
- @param primaryAxis Primary axis of triangle. This will be detected
- if not given. This parameter is provided as an optimization.
+ @param 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
- */
+ @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& 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,
+ const Vector3& v0,
+ const Vector3& v1,
+ const Vector3& v2,
+ const Vector3& normal,
+ const Vector3& point,
Vector3::Axis primaryAxis = Vector3::DETECT_AXIS) {
float b[3];
@@ -1060,70 +1060,70 @@ public:
}
/**
- Tests for the intersection of a moving sphere and a fixed box in a
- given time limit.
+ Tests for the intersection of a moving sphere and a fixed box in a
+ given time limit.
- @note Returns true if any part of the sphere is inside the box
- during the time period (inf means "ever"). Useful for
- performing bounding-box collision detection.
+ @note Returns true if any part of the sphere is inside the box
+ during the time period (inf means "ever"). Useful for
+ performing bounding-box collision detection.
- @param sphere Moving sphere.
- @param velocity Velocity of moving sphere.
- @param box Fixed box.
- @param timeLimit Time limit for intersection test.
+ @param sphere Moving sphere.
+ @param velocity Velocity of moving sphere.
+ @param box Fixed box.
+ @param timeLimit Time limit for intersection test.
- @return true - if the two objects will touch.
- @return false - if there is no intersection.
- */
+ @return true - if the two objects will touch.
+ @return false - if there is no intersection.
+ */
static bool movingSpherePassesThroughFixedBox(
const Sphere& sphere,
const Vector3& velocity,
const Box& box,
double timeLimit = inf());
- /**
- Tests for the intersection of a moving sphere and a fixed sphere in a
- given time limit.
+ /**
+ Tests for the intersection of a moving sphere and a fixed sphere in a
+ given time limit.
- @note This function will not detect an intersection between a moving object
- that is already interpenetrating the fixed object.
+ @note This function will not detect an intersection between a moving object
+ that is already interpenetrating the fixed object.
- @param sphere Moving sphere.
- @param velocity Velocity of moving sphere.
- @param fixedSphere Fixed sphere.
- @param timeLimit Time limit for intersection test.
+ @param sphere Moving sphere.
+ @param velocity Velocity of moving sphere.
+ @param fixedSphere Fixed sphere.
+ @param timeLimit Time limit for intersection test.
- @return true - if the two spheres will touch.
- @return false - if there is no intersection.
- */
+ @return true - if the two spheres will touch.
+ @return false - if there is no intersection.
+ */
static bool movingSpherePassesThroughFixedSphere(
const Sphere& sphere,
const Vector3& velocity,
const Sphere& fixedSphere,
double timeLimit = inf());
- /**
- Tests for the intersection of two fixed spheres.
+ /**
+ Tests for the intersection of two fixed spheres.
- @param sphere1 Fixed sphere 1.
- @param sphere2 Fixed sphere 2.
+ @param sphere1 Fixed sphere 1.
+ @param sphere2 Fixed sphere 2.
- @return true - if the two spheres touch.
- @return false - if there is no intersection.
- */
+ @return true - if the two spheres touch.
+ @return false - if there is no intersection.
+ */
static bool fixedSolidSphereIntersectsFixedSolidSphere(
const Sphere& sphere1,
const Sphere& sphere2);
- /**
- Tests for the intersection of a fixed sphere and a fixed box.
+ /**
+ Tests for the intersection of a fixed sphere and a fixed box.
- @param sphere Fixed sphere.
- @param box Fixed box.
+ @param sphere Fixed sphere.
+ @param box Fixed box.
- @return true - if the two objects touch.
- @return false - if there is no intersection.
- */
+ @return true - if the two objects touch.
+ @return false - if there is no intersection.
+ */
static bool fixedSolidSphereIntersectsFixedSolidBox(
const Sphere& sphere,
const Box& box);
@@ -1137,67 +1137,67 @@ public:
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.
+ Tests whether a point is inside a rectangle defined by the vertexes
+ v0, v1, v2, & v3, and the rectangle's plane normal.
- @param v0 Rectangle vertex 1.
- @param v1 Rectangle vertex 2.
- @param v2 Rectangle vertex 3.
- @param v3 Rectangle vertex 4.
- @param normal Normal to rectangle's plane.
- @param point The point in question.
+ @param v0 Rectangle vertex 1.
+ @param v1 Rectangle vertex 2.
+ @param v2 Rectangle vertex 3.
+ @param v3 Rectangle vertex 4.
+ @param normal Normal to rectangle's plane.
+ @param point The point in question.
- @return true - if point is inside the rectangle.
- @return false - otherwise
- */
+ @return true - if point is inside the rectangle.
+ @return false - otherwise
+ */
static bool isPointInsideRectangle(
- const Vector3& v0,
- const Vector3& v1,
- const Vector3& v2,
- const Vector3& v3,
- const Vector3& normal,
- const Vector3& point);
+ const Vector3& v0,
+ const Vector3& v1,
+ const Vector3& v2,
+ const Vector3& v3,
+ const Vector3& normal,
+ const Vector3& point);
/**
- Finds the closest point on the perimeter of the rectangle to an
- external point; given a rectangle defined by four points v0, v1,
- v2, & v3, and the external point.
+ Finds the closest point on the perimeter of the rectangle to an
+ external point; given a rectangle defined by four points v0, v1,
+ v2, & v3, and the external point.
- @param v0 Rectangle vertex 1.
- @param v1 Rectangle vertex 2.
- @param v2 Rectangle vertex 3.
- @param v3 Rectangle vertex 4.
- @param point External point.
+ @param v0 Rectangle vertex 1.
+ @param v1 Rectangle vertex 2.
+ @param v2 Rectangle vertex 3.
+ @param v3 Rectangle vertex 4.
+ @param point External point.
- @return Closests point to point on the perimeter of the
- rectangle.
- */
+ @return Closests point to point on the perimeter of the
+ rectangle.
+ */
static Vector3 closestPointToRectanglePerimeter(
- const Vector3& v0,
- const Vector3& v1,
- const Vector3& v2,
- const Vector3& v3,
- const Vector3& point);
+ const Vector3& v0,
+ const Vector3& v1,
+ const Vector3& v2,
+ const Vector3& v3,
+ const Vector3& point);
/**
- Finds the closest point in the rectangle to an external point; Given
- a rectangle defined by four points v0, v1, v2, & v3, and the external
- point.
+ Finds the closest point in the rectangle to an external point; Given
+ a rectangle defined by four points v0, v1, v2, & v3, and the external
+ point.
- @param v0 Rectangle vertex 1.
- @param v1 Rectangle vertex 2.
- @param v2 Rectangle vertex 3
- @param v3 Rectangle vertex 4.
- @param point External point.
+ @param v0 Rectangle vertex 1.
+ @param v1 Rectangle vertex 2.
+ @param v2 Rectangle vertex 3
+ @param v3 Rectangle vertex 4.
+ @param point External point.
@return Closet point in the rectangle to the external point.
- */
- static Vector3 closestPointToRectangle(
- const Vector3& v0,
- const Vector3& v1,
- const Vector3& v2,
- const Vector3& v3,
- const Vector3& point);
+ */
+ static Vector3 closestPointToRectangle(
+ const Vector3& v0,
+ const Vector3& v1,
+ const Vector3& v2,
+ const Vector3& v3,
+ const Vector3& point);
};
} // namespace
diff --git a/deps/g3dlite/include/G3D/Color1.h b/deps/g3dlite/include/G3D/Color1.h
index 0f68c84b3..6066fdcb7 100644
--- a/deps/g3dlite/include/G3D/Color1.h
+++ b/deps/g3dlite/include/G3D/Color1.h
@@ -1,30 +1,29 @@
/**
- @file Color1.h
+ \file G3D/Color1.h
Monochrome Color class
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @created 2007-01-31
- @edited 2009-03-20
+ \maintainer Morgan McGuire, http://graphics.cs.williams.edu
+ \created 2007-01-31
+ \edited 2011-08-20
- Copyright 2000-2009, Morgan McGuire.
+ Copyright 2000-2012, Morgan McGuire.
All rights reserved.
*/
-#ifndef G3D_COLOR1_H
-#define G3D_COLOR1_H
+#ifndef G3D_Color1_h
+#define G3D_Color1_h
#include "G3D/platform.h"
#include "G3D/g3dmath.h"
+#include "G3D/unorm8.h"
#include "G3D/HashTrait.h"
#include $VAR and $(VAR) patterns with the corresponding environment variable.
+ Throws std::string if the environment variable is not defined.
+ */
+ static std::string expandEnvironmentVariables(const std::string& path);
+
/**
Parses a filename into four useful pieces.
@@ -454,11 +593,13 @@ public:
std::string& base,
std::string& ext);
-
/**
Returns true if \a path matches \a pattern, with standard filesystem wildcards.
*/
static bool matches(const std::string& path, const std::string& pattern, bool caseSensitive = true);
+
+ /** Replaces characters that are illegal in a filename with legal equivalents.*/
+ static std::string makeLegalFilename(const std::string& f, size_t maxLength = 100000);
};
} // namespace G3D
diff --git a/deps/g3dlite/include/G3D/Frustum.h b/deps/g3dlite/include/G3D/Frustum.h
new file mode 100644
index 000000000..6c2d2a413
--- /dev/null
+++ b/deps/g3dlite/include/G3D/Frustum.h
@@ -0,0 +1,57 @@
+/**
+ \file G3D/Frustum.h
+
+ \maintainer Morgan McGuire, http://graphics.cs.williams.edu
+
+ \created 2005-07-20
+ \edited 2013-06-11
+*/
+
+#ifndef G3D_Frustum_h
+#define G3D_Frustum_h
+
+#include "G3D/platform.h"
+#include "G3D/g3dmath.h"
+#include "G3D/Plane.h"
+#include "G3D/SmallArray.h"
+#include "G3D/Vector4.h"
+
+namespace G3D {
+
+class Box;
+
+/** \see Projection */
+class Frustum {
+public:
+ class Face {
+ public:
+ /** Counter clockwise indices into vertexPos */
+ int vertexIndex[4];
+
+ /** The plane containing the face. */
+ Plane plane;
+ };
+
+ /** The vertices, in homogeneous space. The order is that of
+ the near face, starting from the (object space) +x,+y corner
+ and proceeding CCW from the camera's point of view; followed
+ by the far face also in CCW order.
+
+ If w == 0,
+ a vertex is at infinity. */
+ SmallArray Evaluates \a
+ object->\a method(\a x, \a y) for every start.x <= x <
+ upTo.x and start.y <= y < upTo.y.
+ Iteration is row major, so each thread can expect to see
+ successive x values.
void callback(const Ray& ray, const T& object, float& distance). If the ray hits the object
- before travelling distance distance, updates distance with the new distance to
- the intersection, otherwise leaves it unmodified. A common example is:
-
+ @param intersectCallback Either a function or an instance of a class with an overloaded operator() of the form:
+ + void callback(const Ray& ray, const T& object, float& distance). ++ If the ray hits the object before travelling distance
distance, updates
+ distance with the new distance to the intersection, otherwise leaves it
+ unmodified. A common example is:
+ \htmlonly
class Entity {
public:
+ void intersect(const Ray& ray, float& maxDist, Vector3& outLocation, Vector3& outNormal) {
+ float d = maxDist;
- void intersect(const Ray& ray, float& maxDist, Vector3& outLocation, Vector3& outNormal) {
- float d = maxDist;
+ // ... search for intersection distance d
- // ... search for intersection distance d
+ if ((d > 0) && (d < maxDist)) {
+ // Intersection occured
+ maxDist = d;
+ outLocation = ...;
+ outNormal = ...;
+ }
+ }
+ };
- if ((d > 0) && (d < maxDist)) {
- // Intersection occured
- maxDist = d;
- outLocation = ...;
- outNormal = ...;
- }
- }
- };
+ // Finds the surface normal and location of the first intersection with the scene
+ class Intersection {
+ public:
+ Entity* closestEntity;
+ Vector3 hitLocation;
+ Vector3 hitNormal;
- // Finds the surface normal and location of the first intersection with the scene
- class Intersection {
- public:
- Entity* closestEntity;
- Vector3 hitLocation;
- Vector3 hitNormal;
+ void operator()(const Ray& ray, const Entity* entity, float& distance) {
+ entity->intersect(ray, distance, hitLocation, hitNormal);
+ }
+ };
- void operator()(const Ray& ray, const Entity* entity, float& distance) {
- entity->intersect(ray, distance, hitLocation, hitNormal);
- }
- };
-
- KDTree scene;
-
- Intersection intersection;
- float distance = finf();
- scene.intersectRay(camera.worldRay(x, y), intersection, distance);
-
+ KDTreeMatrix4(#, #, # .... #)*/
- Matrix4(const Any& any);
- operator Any() const;
+ /** Must be in one of the following forms:
+ - Matrix4(#, #, # .... #)
+ - Matrix4::scale(#)
+ - Matrix4::scale(#, #, #)
+ - Matrix4::translation(#, #, #)
+ - Matrix4::identity()
+ - Matrix4::rollDegrees(#)
+ - Matrix4::pitchDegrees(#)
+ - Matrix4::yawDegrees(#)
+ */
+ explicit Matrix4(const Any& any);
+
+ Any toAny() const;
Matrix4(
float r1c1, float r1c2, float r1c3, float r1c4,
@@ -66,17 +77,25 @@ public:
*/
Matrix4(const float* init);
- /**
- a is the upper left 3x3 submatrix and b is the upper right 3x1 submatrix. The last row of the created matrix is (0,0,0,1).
- */
+ /**
+ a is the upper left 3x3 submatrix and b is the upper right 3x1 submatrix. The last row of the created matrix is (0,0,0,1).
+ */
Matrix4(const class Matrix3& upper3x3, const class Vector3& lastCol = Vector3::zero());
Matrix4(const class CoordinateFrame& c);
Matrix4(const double* init);
+ /** Matrix4::zero() */
Matrix4();
+ static Matrix4 diagonal(float e00, float e11, float e22, float e33) {
+ return Matrix4(e00, 0, 0, 0,
+ 0, e11, 0, 0,
+ 0, 0, e22, 0,
+ 0, 0, 0, e33);
+ }
+
/** Produces an RT transformation that nearly matches this Matrix4.
Because a Matrix4 may not be precisely a rotation and translation,
this may introduce error. */
@@ -88,14 +107,19 @@ public:
static const Matrix4& zero();
/** If this is a perspective projection matrix created by
- Matrix4::perspectiveProjection, extract its parameters. */
+ Matrix4::perspectiveProjection, extract its parameters.
+
+ Uses double precision because the operations involved in
+ projection involve divisions that can significantly impact
+ precision.
+ */
void getPerspectiveProjectionParameters
- (float& left,
- float& right,
- float& bottom,
- float& top,
- float& nearval,
- float& farval,
+ (double& left,
+ double& right,
+ double& bottom,
+ double& top,
+ double& nearval,
+ double& farval,
float updirection = -1.0f) const;
inline float* operator[](int r) {
@@ -110,6 +134,7 @@ public:
return (const float*)&elt[r];
}
+ /** Returns a row-major pointer. */
inline operator float* () {
return (float*)&elt[0][0];
}
@@ -131,6 +156,8 @@ public:
class Matrix3 upper3x3() const;
+ class Matrix2 upper2x2() const;
+
/** Homogeneous multiplication. Let k = M * [v w]^T. result = k.xyz() / k.w */
class Vector3 homoMul(const class Vector3& v, float w) const;
@@ -151,7 +178,6 @@ public:
float farval,
float upDirection = -1.0f);
-
/** \param upDirection Use -1.0 for 2D Y increasing downwards (the G3D 8.x default convention),
1.0 for 2D Y increasing upwards (the G3D 7.x default and OpenGL convention)
*/
@@ -163,15 +189,18 @@ public:
/** \param upDirection Use -1.0 for 2D Y increasing downwards (the G3D 8.x default convention),
1.0 for 2D Y increasing upwards (the G3D 7.x default and OpenGL convention)
- */
+
+ Uses double precision because the operations involved in
+ projection involve divisions that can significantly impact
+ precision. */
static Matrix4 perspectiveProjection(
- float left,
- float right,
- float bottom,
- float top,
- float nearval,
- float farval,
- float upDirection = -1.0f);
+ double left,
+ double right,
+ double bottom,
+ double top,
+ double nearval,
+ double farval,
+ float upDirection = -1.0f);
void setRow(int r, const class Vector4& v);
void setColumn(int c, const Vector4& v);
@@ -248,6 +277,67 @@ public:
};
+/** Double-precision 4x4 matrix */
+class Matrix4float64 {
+private:
+
+ double elt[4][4];
+
+public:
+
+ explicit Matrix4float64(const Matrix4& m);
+
+ /** all zeros */
+ Matrix4float64();
+
+ Matrix4float64(
+ double r1c1, double r1c2, double r1c3, double r1c4,
+ double r2c1, double r2c2, double r2c3, double r2c4,
+ double r3c1, double r3c2, double r3c3, double r3c4,
+ double r4c1, double r4c2, double r4c3, double r4c4);
+
+ // Special values.
+ // Intentionally not inlined: see Matrix3::identity() for details.
+ static const Matrix4float64& identity();
+
+ static const Matrix4float64& zero();
+
+ bool operator!=(const Matrix4float64& other) const;
+
+ bool operator==(const Matrix4float64& other) const;
+
+ Vector4 operator*(const Vector4& vector) const;
+
+ static Matrix4float64 perspectiveProjection(
+ double left,
+ double right,
+ double bottom,
+ double top,
+ double nearval,
+ double farval,
+ float upDirection = -1.0f);
+
+ inline double* operator[](int r) {
+ debugAssert(r >= 0);
+ debugAssert(r < 4);
+ return (double*)&elt[r];
+ }
+
+ inline const double* operator[](int r) const {
+ debugAssert(r >= 0);
+ debugAssert(r < 4);
+ return (const double*)&elt[r];
+ }
+
+ inline operator double* () {
+ return (double*)&elt[0][0];
+ }
+
+ inline operator const double* () const {
+ return (const double*)&elt[0][0];
+ }
+};
+
} // namespace
diff --git a/deps/g3dlite/include/G3D/MemoryManager.h b/deps/g3dlite/include/G3D/MemoryManager.h
index 15bf6d8be..be6f6400c 100644
--- a/deps/g3dlite/include/G3D/MemoryManager.h
+++ b/deps/g3dlite/include/G3D/MemoryManager.h
@@ -20,7 +20,7 @@ namespace G3D {
Abstraction of memory management.
Default implementation uses G3D::System::malloc and is threadsafe.
- \sa CRTMemoryManager, AlignedMemoryManager, AreaMemoryManager */
+ \sa LargePoolMemoryManager, CRTMemoryManager, AlignedMemoryManager, AreaMemoryManager */
class MemoryManager : public ReferenceCountedObject {
protected:
@@ -28,7 +28,7 @@ protected:
public:
- typedef ReferenceCountedPointernormal.Dot(Vector3(x, y, z)) + d = 0
*/
- void getEquation(Vector3 &normal, double& d) const;
- void getEquation(Vector3 &normal, float& d) const;
+ void getEquation(Vector3& normal, double& d) const;
+ void getEquation(Vector3& normal, float& d) const;
/**
ax + by + cz + d = 0
diff --git a/deps/g3dlite/include/G3D/PointHashGrid.h b/deps/g3dlite/include/G3D/PointHashGrid.h
index d0b60a88a..85c502296 100644
--- a/deps/g3dlite/include/G3D/PointHashGrid.h
+++ b/deps/g3dlite/include/G3D/PointHashGrid.h
@@ -1,11 +1,11 @@
/**
- @file PointHashGrid.h
+ \file PointHashGrid.h
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @created 2008-07-01
- @edited 2009-05-28
+ \maintainer Morgan McGuire, http://graphics.cs.williams.edu
+ \created 2008-07-01
+ \edited 2010-11-28
- Copyright 2000-2010, Morgan McGuire.
+ Copyright 2000-2012, Morgan McGuire.
All rights reserved.
*/
#ifndef G3D_PointHashGrid_h
@@ -25,23 +25,23 @@
namespace G3D {
/**
- Storage of data in a sparse 3D grid of point-based data. The
- space cost for n elements is O(n). For data with
+ \brief A sparse 3D grid of point-based data.
+
+ The space cost for n elements is O(n). For data with
approximately uniform density (with respect to the radius hint),
the time cost of searching for neighbors is O(1).
- Value must be supported by a G3D::PositionTrait and
- G3D::EqualsTrait. Overloads are provided for
- common G3D classes like G3D::Vector3. For example:
-
-
- class EqualsFunc {
- public:
- static bool equals(const Data& p, const Data& q) {
- return p == q;
- }
- };
+ You can move members of the data set by first removing them and then
+ adding them with a new location.
+ Template argument \a PosFunc must provide a static getPosition method
+ and \a EqualsFunc must provide a static equals method, as described below.
+ You can either write classes that support these yourself, provide template specializations of
+ G3D::PositionTrait and
+ G3D::EqualsTrait, or rely on the default template specializations, which already exist for
+ common G3D classes like G3D::Point3. For example:
+
+ \code
class PosFunc {
public:
static void getPosition(const Data& d, Vector3& pos) {
@@ -49,14 +49,43 @@ namespace G3D {
}
};
+ class EqualsFunc {
+ public:
+ static bool equals(const Data& p, const Data& q) {
+ return p == q;
+ }
+ };
+
PointHashGrid grid;
-
+ \endcode
- If the Value class defines operator==, the Equalsfunc is optional:
+ If the \a Value class defines operator==, then the \a Equalsfunc is optional, so you can just write:
-
+ \code
PointHashGrid grid;
-
+ \endcode
+
+ The simplest way to define these is often to make them both methods
+ of the parameter class itself, e.g.,
+
+ \code
+
+ class Data {
+ public:
+ Point3 location;
+ ...
+
+ bool operator==(const Data& other) const {
+ return (location == other.location) && ...;
+ }
+
+ static void getPosition(const Data& p, Vector3& pos) {
+ pos = p.location;
+ }
+ };
+
+ typedef PointHashGrid DataGrid;
+ \endcode
*/
template