aboutsummaryrefslogtreecommitdiff
path: root/dep/g3dlite/source
diff options
context:
space:
mode:
Diffstat (limited to 'dep/g3dlite/source')
-rw-r--r--dep/g3dlite/source/AABox.cpp157
-rw-r--r--dep/g3dlite/source/Any.cpp783
-rw-r--r--dep/g3dlite/source/AnyTableReader.cpp50
-rw-r--r--dep/g3dlite/source/AnyVal.cpp1379
-rw-r--r--dep/g3dlite/source/AreaMemoryManager.cpp4
-rw-r--r--dep/g3dlite/source/BinaryInput.cpp503
-rw-r--r--dep/g3dlite/source/BinaryOutput.cpp109
-rw-r--r--dep/g3dlite/source/Box.cpp394
-rw-r--r--dep/g3dlite/source/BumpMapPreprocess.cpp6
-rw-r--r--dep/g3dlite/source/Capsule.cpp44
-rw-r--r--dep/g3dlite/source/CollisionDetection.cpp389
-rw-r--r--dep/g3dlite/source/Color1.cpp14
-rw-r--r--dep/g3dlite/source/Color1uint8.cpp38
-rw-r--r--dep/g3dlite/source/Color3.cpp164
-rw-r--r--dep/g3dlite/source/Color3uint8.cpp45
-rw-r--r--dep/g3dlite/source/Color4.cpp71
-rw-r--r--dep/g3dlite/source/Color4uint8.cpp47
-rw-r--r--dep/g3dlite/source/Cone.cpp54
-rw-r--r--dep/g3dlite/source/ConvexPolyhedron.cpp32
-rw-r--r--dep/g3dlite/source/CoordinateFrame.cpp168
-rw-r--r--dep/g3dlite/source/Crypto.cpp5
-rw-r--r--dep/g3dlite/source/Crypto_md5.cpp134
-rw-r--r--dep/g3dlite/source/Cylinder.cpp30
-rw-r--r--dep/g3dlite/source/FileSystem.cpp369
-rw-r--r--dep/g3dlite/source/GCamera.cpp511
-rw-r--r--dep/g3dlite/source/GImage.cpp1166
-rw-r--r--dep/g3dlite/source/GImage_bayer.cpp298
-rw-r--r--dep/g3dlite/source/GImage_bmp.cpp717
-rw-r--r--dep/g3dlite/source/GImage_jpeg.cpp446
-rw-r--r--dep/g3dlite/source/GImage_png.cpp276
-rw-r--r--dep/g3dlite/source/GImage_ppm.cpp217
-rw-r--r--dep/g3dlite/source/GImage_tga.cpp236
-rw-r--r--dep/g3dlite/source/GLight.cpp275
-rw-r--r--dep/g3dlite/source/GThread.cpp61
-rw-r--r--dep/g3dlite/source/GUniqueID.cpp46
-rw-r--r--dep/g3dlite/source/Image1.cpp123
-rw-r--r--dep/g3dlite/source/Image1uint8.cpp212
-rw-r--r--dep/g3dlite/source/Image3.cpp116
-rw-r--r--dep/g3dlite/source/Image3uint8.cpp225
-rw-r--r--dep/g3dlite/source/Image4.cpp114
-rw-r--r--dep/g3dlite/source/Image4uint8.cpp222
-rw-r--r--dep/g3dlite/source/ImageFormat.cpp494
-rw-r--r--dep/g3dlite/source/ImageFormat_convert.cpp682
-rw-r--r--dep/g3dlite/source/Intersect.cpp1533
-rw-r--r--dep/g3dlite/source/Line.cpp12
-rw-r--r--dep/g3dlite/source/LineSegment.cpp10
-rw-r--r--dep/g3dlite/source/Log.cpp16
-rw-r--r--dep/g3dlite/source/Matrix.cpp125
-rw-r--r--dep/g3dlite/source/Matrix3.cpp363
-rw-r--r--dep/g3dlite/source/Matrix4.cpp291
-rw-r--r--dep/g3dlite/source/MemoryManager.cpp6
-rw-r--r--dep/g3dlite/source/MeshAlg.cpp98
-rw-r--r--dep/g3dlite/source/MeshAlgAdjacency.cpp11
-rw-r--r--dep/g3dlite/source/MeshAlgWeld.cpp27
-rw-r--r--dep/g3dlite/source/MeshBuilder.cpp26
-rw-r--r--dep/g3dlite/source/NetAddress.cpp45
-rw-r--r--dep/g3dlite/source/NetworkDevice.cpp99
-rw-r--r--dep/g3dlite/source/PhysicsFrame.cpp40
-rw-r--r--dep/g3dlite/source/PhysicsFrameSpline.cpp77
-rw-r--r--dep/g3dlite/source/Plane.cpp38
-rw-r--r--dep/g3dlite/source/Quat.cpp122
-rw-r--r--dep/g3dlite/source/Random.cpp30
-rw-r--r--dep/g3dlite/source/Ray.cpp221
-rw-r--r--dep/g3dlite/source/Rect2D.cpp46
-rw-r--r--dep/g3dlite/source/ReferenceCount.cpp61
-rw-r--r--dep/g3dlite/source/RegistryUtil.cpp8
-rw-r--r--dep/g3dlite/source/Sphere.cpp122
-rw-r--r--dep/g3dlite/source/SplineBase.cpp6
-rw-r--r--dep/g3dlite/source/Stopwatch.cpp15
-rw-r--r--dep/g3dlite/source/System.cpp526
-rw-r--r--dep/g3dlite/source/TextInput.cpp310
-rw-r--r--dep/g3dlite/source/TextOutput.cpp79
-rw-r--r--dep/g3dlite/source/ThreadSet.cpp14
-rw-r--r--dep/g3dlite/source/Triangle.cpp2
-rw-r--r--dep/g3dlite/source/UprightFrame.cpp112
-rw-r--r--dep/g3dlite/source/Vector2.cpp57
-rw-r--r--dep/g3dlite/source/Vector2int16.cpp40
-rw-r--r--dep/g3dlite/source/Vector3.cpp146
-rw-r--r--dep/g3dlite/source/Vector3int16.cpp10
-rw-r--r--dep/g3dlite/source/Vector3int32.cpp83
-rw-r--r--dep/g3dlite/source/Vector4.cpp24
-rw-r--r--dep/g3dlite/source/Welder.cpp276
-rw-r--r--dep/g3dlite/source/WinMain.cpp2
-rw-r--r--dep/g3dlite/source/XML.cpp4
-rw-r--r--dep/g3dlite/source/constants.cpp28
-rw-r--r--dep/g3dlite/source/debugAssert.cpp30
-rw-r--r--dep/g3dlite/source/fileutils.cpp314
-rw-r--r--dep/g3dlite/source/format.cpp12
-rw-r--r--dep/g3dlite/source/g3dfnmatch.cpp306
-rw-r--r--dep/g3dlite/source/g3dmath.cpp24
-rw-r--r--dep/g3dlite/source/license.cpp4
-rw-r--r--dep/g3dlite/source/prompt.cpp179
-rw-r--r--dep/g3dlite/source/stringutils.cpp68
-rw-r--r--dep/g3dlite/source/uint128.cpp8
94 files changed, 6602 insertions, 10930 deletions
diff --git a/dep/g3dlite/source/AABox.cpp b/dep/g3dlite/source/AABox.cpp
index 8e66456c013..72695b48743 100644
--- a/dep/g3dlite/source/AABox.cpp
+++ b/dep/g3dlite/source/AABox.cpp
@@ -1,10 +1,13 @@
/**
- @file AABox.cpp
+ \file G3D.lib/source/AABox.cpp
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
+ \maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @created 2004-01-10
- @edited 2006-01-11
+ \created 2004-01-10
+ \edited 2013-06-11
+
+ Copyright 2000-2013, Morgan McGuire.
+ All rights reserved.
*/
#include "G3D/platform.h"
@@ -14,10 +17,53 @@
#include "G3D/Sphere.h"
#include "G3D/BinaryInput.h"
#include "G3D/BinaryOutput.h"
+#include "G3D/Any.h"
namespace G3D {
+AABox::AABox(const Any& a) {
+ if (a.name() == "AABox::empty") {
+ *this = AABox::empty();
+ } else if (a.name() == "AABox::inf") {
+ *this = AABox::inf();
+ } else {
+ a.verifyName("AABox");
+ a.verifyType(Any::ARRAY);
+ if (a.size() == 1) {
+ *this = AABox(Point3(a[0]));
+ } else if (a.size() == 2) {
+ set(Point3(a[0]), Point3(a[1]));
+ } else {
+ a.verify(false, "AABox must recieve exactly 1 or two arguments.");
+ }
+ }
+}
+
+
+Any AABox::toAny() const {
+ if (isEmpty()) {
+ return Any(Any::ARRAY, "AABox::empty");
+ } else if (! isFinite()) {
+ return Any(Any::ARRAY, "AABox::inf");
+ } else {
+ Any a(Any::ARRAY, "AABox");
+ if (lo == hi) {
+ a.append(lo);
+ } else {
+ a.append(lo, hi);
+ }
+ return a;
+ }
+}
+
+
+const AABox& AABox::empty() {
+ static const AABox b;
+ return b;
+}
+
+
const AABox& AABox::maxFinite() {
static const AABox b = AABox(Vector3::minFinite(),
Vector3::maxFinite());
@@ -56,6 +102,13 @@ void AABox::deserialize(class BinaryInput& b) {
}
+void AABox::merge(const Box& b) {
+ AABox aab;
+ b.getBounds(aab);
+ merge(aab);
+}
+
+
void AABox::split(const Vector3::Axis& axis, float location, AABox& low, AABox& high) const {
// Low, medium, and high along the chosen axis
float L = G3D::min(location, lo[axis]);
@@ -139,11 +192,11 @@ bool AABox::intersects(const AABox& other) const {
int AABox::dummy = 0;
-bool AABox::culledBy(
- const Array<Plane>& plane,
- int& cullingPlane,
- const uint32 _inMask,
- uint32& childMask) const {
+bool AABox::culledBy
+ (const Array<Plane>& plane,
+ int& cullingPlane,
+ const uint32 _inMask,
+ uint32& childMask) const {
uint32 inMask = _inMask;
assert(plane.size() < 31);
@@ -159,13 +212,13 @@ bool AABox::culledBy(
(abs(hi.z) < G3D::finf());
// See if there is one plane for which all of the
- // vertices are in the negative half space.
+ // vertices are in the negative half space.
for (int p = 0; p < plane.size(); ++p) {
- // Only test planes that are not masked
- if ((inMask & 1) != 0) {
-
- Vector3 corner;
+ // Only test planes that are not masked
+ if ((inMask & 1) != 0) {
+
+ Vector3 corner;
int numContained = 0;
int v = 0;
@@ -173,12 +226,12 @@ bool AABox::culledBy(
// We can early-out only if we have found one point on each
// side of the plane (i.e. if we are straddling). That
// occurs when (numContained < v) && (numContained > 0)
- for (v = 0; (v < 8) && ((numContained == v) || (numContained == 0)); ++v) {
+ for (v = 0; (v < 8) && ((numContained == v) || (numContained == 0)); ++v) {
// Unrolling these 3 if's into a switch decreases performance
// by about 2x
- corner.x = (v & 1) ? hi.x : lo.x;
- corner.y = (v & 2) ? hi.y : lo.y;
- corner.z = (v & 4) ? hi.z : lo.z;
+ corner.x = (v & 1) ? hi.x : lo.x;
+ corner.y = (v & 2) ? hi.y : lo.y;
+ corner.z = (v & 4) ? hi.z : lo.z;
if (finite) { // this branch is highly predictable
if (plane[p].halfSpaceContainsFinite(corner)) {
@@ -189,43 +242,43 @@ bool AABox::culledBy(
++numContained;
}
}
- }
+ }
- if (numContained == 0) {
- // Plane p culled the box
- cullingPlane = p;
+ if (numContained == 0) {
+ // Plane p culled the box
+ cullingPlane = p;
// The caller should not recurse into the children,
// since the parent is culled. If they do recurse,
// make them only test against this one plane, which
// will immediately cull the volume.
childMask = 1 << p;
- return true;
+ return true;
} else if (numContained < v) {
// The bounding volume straddled the plane; we have
// to keep testing against this plane
childMask |= (1 << p);
}
- }
+ }
// Move on to the next bit.
- inMask = inMask >> 1;
+ inMask = inMask >> 1;
}
// None of the planes could cull this box
- cullingPlane = -1;
+ cullingPlane = -1;
return false;
}
bool AABox::culledBy(
const Array<Plane>& plane,
- int& cullingPlane,
- const uint32 _inMask) const {
+ int& cullingPlane,
+ const uint32 _inMask) const {
- uint32 inMask = _inMask;
- assert(plane.size() < 31);
+ uint32 inMask = _inMask;
+ assert(plane.size() < 31);
const bool finite =
(abs(lo.x) < G3D::finf()) &&
@@ -236,58 +289,60 @@ bool AABox::culledBy(
(abs(hi.z) < G3D::finf());
// See if there is one plane for which all of the
- // vertices are in the negative half space.
+ // vertices are in the negative half space.
for (int p = 0; p < plane.size(); ++p) {
- // Only test planes that are not masked
- if ((inMask & 1) != 0) {
-
- bool culled = true;
- Vector3 corner;
+ // Only test planes that are not masked
+ if ((inMask & 1) != 0) {
+
+ bool culled = true;
+ Vector3 corner;
int v;
- // Assume this plane culls all points. See if there is a point
- // not culled by the plane... early out when at least one point
+ // Assume this plane culls all points. See if there is a point
+ // not culled by the plane... early out when at least one point
// is in the positive half space.
- for (v = 0; (v < 8) && culled; ++v) {
+ for (v = 0; (v < 8) && culled; ++v) {
// Unrolling these 3 if's into a switch decreases performance
// by about 2x
- corner.x = (v & 1) ? hi.x : lo.x;
- corner.y = (v & 2) ? hi.y : lo.y;
- corner.z = (v & 4) ? hi.z : lo.z;
+ corner.x = (v & 1) ? hi.x : lo.x;
+ corner.y = (v & 2) ? hi.y : lo.y;
+ corner.z = (v & 4) ? hi.z : lo.z;
if (finite) { // this branch is highly predictable
culled = ! plane[p].halfSpaceContainsFinite(corner);
} else {
culled = ! plane[p].halfSpaceContains(corner);
}
- }
+ }
- if (culled) {
- // Plane p culled the box
- cullingPlane = p;
+ if (culled) {
+ // Plane p culled the box
+ cullingPlane = p;
- return true;
+ return true;
}
- }
+ }
// Move on to the next bit.
- inMask = inMask >> 1;
+ inMask = inMask >> 1;
}
// None of the planes could cull this box
- cullingPlane = -1;
+ cullingPlane = -1;
return false;
}
+
void AABox::getBounds(Sphere& s) const {
s.center = center();
s.radius = extent().length() / 2;
}
-bool AABox::intersects(const class Sphere& sphere) const {
+
+bool AABox::intersects(const Sphere& sphere) const {
double d = 0;
//find the square of the distance
diff --git a/dep/g3dlite/source/Any.cpp b/dep/g3dlite/source/Any.cpp
index 92159bb1862..9204f9efc12 100644
--- a/dep/g3dlite/source/Any.cpp
+++ b/dep/g3dlite/source/Any.cpp
@@ -1,19 +1,21 @@
/**
- @file Any.cpp
+ \file Any.cpp
- @author Morgan McGuire
- @author Shawn Yarbrough
+ \author Morgan McGuire
+ \author Shawn Yarbrough
- @created 2006-06-11
- @edited 2010-07-24
+ \created 2006-06-11
+ \edited 2013-03-29
- Copyright 2000-2010, Morgan McGuire.
+ Copyright 2000-2013, Morgan McGuire.
All rights reserved.
*/
#include "G3D/Any.h"
#include "G3D/TextOutput.h"
#include "G3D/TextInput.h"
+#include "G3D/BinaryOutput.h"
+#include "G3D/BinaryInput.h"
#include "G3D/stringutils.h"
#include "G3D/fileutils.h"
#include "G3D/FileSystem.h"
@@ -21,14 +23,40 @@
#include <iostream>
namespace G3D {
+const char* Any::PAREN = "()";
+const char* Any::BRACKET = "[]";
+const char* Any::BRACE = "{}";
-std::string Any::resolveStringAsFilename() const {
+static bool isContainerType(Any::Type& t) {
+ return (t == Any::ARRAY) || (t == Any::TABLE) || (t == Any::EMPTY_CONTAINER);
+}
+
+void Any::serialize(BinaryOutput& b) const {
+ TextOutput::Settings s;
+ s.wordWrap = TextOutput::Settings::WRAP_NONE;
+ b.writeInt32(1);
+ b.writeString32(unparse(s));
+}
+
+
+void Any::deserialize(BinaryInput& b) {
+ const int version = b.readInt32();
+ alwaysAssertM(version == 1, "Wrong Any serialization version");
+ _parse(b.readString32());
+}
+
+
+std::string Any::resolveStringAsFilename(bool errorIfNotFound) const {
verifyType(STRING);
- std::string f = FileSystem::resolve(string(), sourceDirectory());
+ if ((string().length() > 0) && (string()[0] == '<') && (string()[string().length() - 1] == '>')) {
+ return string();
+ }
+
+ const std::string& f = FileSystem::resolve(string(), sourceDirectory());
if (FileSystem::exists(f)) {
return f;
} else {
- const std::string& s = System::findDataFile(string(), false);
+ const std::string& s = System::findDataFile(string(), errorIfNotFound);
if (s.empty()) {
return string();
} else {
@@ -37,6 +65,47 @@ std::string Any::resolveStringAsFilename() const {
}
}
+void Any::become(const Type& t) {
+ if ((t == ARRAY) || (t == TABLE)) {
+ debugAssert(m_type == EMPTY_CONTAINER);
+ m_type = t;
+ m_data->type = m_type;
+ if(t == ARRAY) {
+ m_data->value.a = new AnyArray();
+ } else {
+ m_data->value.t = new AnyTable();
+ }
+ }
+}
+
+
+void Any::remove(const std::string& key) {
+ verifyType(TABLE);
+ ensureMutable();
+ m_data->value.t->remove(key);
+}
+
+
+void Any::remove(int i) {
+ verifyType(ARRAY);
+ ensureMutable();
+ m_data->value.a->remove(i);
+}
+
+
+Any Any::fromFile(const std::string& filename) {
+ Any a;
+ a.load(filename);
+ return a;
+}
+
+
+void Any::loadIfExists(const std::string& filename) {
+ if (FileSystem::exists(filename)) {
+ load(filename);
+ }
+}
+
bool Any::nameBeginsWith(const std::string& s) const {
return nameBeginsWith(s.c_str());
@@ -73,7 +142,7 @@ bool Any::nameBeginsWith(const char* s) const {
bool Any::nameEquals(const char* s) const {
verifyType(Any::ARRAY, Any::TABLE);
-#ifdef G3D_WIN32
+#ifdef G3D_WINDOWS
return stricmp(name().c_str(), s) == 0;
#else
return strcasecmp(name().c_str(), s) == 0;
@@ -86,16 +155,11 @@ void Any::beforeRead() const {
if (isPlaceholder()) {
// Tried to read from a placeholder--throw an exception as if
// the original operator[] had failed.
- KeyNotFound e;
alwaysAssertM(m_data, "Corrupt placeholder");
+ KeyNotFound e(m_data);
- e.filename = m_data->source.filename;
- e.line = m_data->source.line;
- e.character = m_data->source.character;
e.key = m_placeholderName;
- e.message =
- "This exception may have been thrown later than "
- "the actual operator[] invocation.";
+ e.message = "Key \"" + m_placeholderName + "\" not found in operator[] lookup.";
throw e;
}
@@ -105,13 +169,18 @@ void Any::beforeRead() const {
Any::Data* Any::Data::create(const Data* d) {
Data* p = create(d->type);
- p->comment = d->comment;
- p->name = d->name;
+ p->includeLine = d->includeLine;
+ p->bracket = d->bracket;
+ p->separator = d->separator;
+ p->comment = d->comment;
+ p->name = d->name;
+ p->source = d->source;
switch (d->type) {
- case NONE:
+ case NIL:
case BOOLEAN:
case NUMBER:
+ case EMPTY_CONTAINER:
// No clone needed
break;
@@ -134,11 +203,11 @@ Any::Data* Any::Data::create(const Data* d) {
}
-Any::Data* Any::Data::create(Any::Type t) {
+Any::Data* Any::Data::create(Any::Type t, const char* b, char sep) {
size_t s = sizeof(Data);
switch (t) {
- case NONE:
+ case NIL:
case BOOLEAN:
case NUMBER:
// No extra space needed
@@ -148,23 +217,38 @@ Any::Data* Any::Data::create(Any::Type t) {
s += sizeof(std::string);
break;
+ case EMPTY_CONTAINER:
+ // We need to allocate space for the worst-case
+ s += max(sizeof(AnyArray), sizeof(AnyTable));
+ // If no separator and brackets were provided, substitute defaults
+ if (b == NULL) { b = PAREN; }
+ if (sep == '\0') { sep = ','; }
+ break;
+
case ARRAY:
s += sizeof(AnyArray);
+ // If no separator and brackets were provided, substitute defaults
+ if (b == NULL) { b = PAREN; }
+ if (sep == '\0') { sep = ','; }
break;
case TABLE:
s += sizeof(AnyTable);
+ // If no separator and brackets were provided, substitute defaults
+ if (b == NULL) { b = BRACE; }
+ if (sep == '\0') { sep = ';'; }
break;
}
// Allocate the data object
- Data* p = new (MemoryManager::create()->alloc(s)) Data(t);
+ Data* p = new (MemoryManager::create()->alloc(s)) Data(t, b, sep);
- // Create the (empyt) value object at the end of the Data object
+ // Create the (empty) value object at the end of the Data object
switch (t) {
- case NONE:
+ case NIL:
case BOOLEAN:
case NUMBER:
+ case EMPTY_CONTAINER:
// No value
break;
@@ -179,7 +263,9 @@ Any::Data* Any::Data::create(Any::Type t) {
case TABLE:
p->value.t = new (p + 1) AnyTable();
break;
- }
+ }
+
+ if (isContainerType(p->type)) debugAssert(p->separator != '\0');
return p;
}
@@ -227,7 +313,10 @@ Any::Data::~Data() {
bool Any::containsKey(const std::string& x) const {
beforeRead();
verifyType(TABLE);
-
+ if (size() == 0) {
+ //catches the case of an empty container, where value.t is null
+ return false;
+ }
Any* a = m_data->value.t->getPointer(x);
// Don't return true for placeholder objects
@@ -255,16 +344,16 @@ void Any::ensureMutable() {
}
-Any::Any() : m_type(NONE), m_data(NULL) {
+Any::Any() : m_type(NIL), m_data(NULL) {
}
-Any::Any(TextInput& t) : m_type(NONE), m_data(NULL) {
+Any::Any(TextInput& t) : m_type(NIL), m_data(NULL) {
deserialize(t);
}
-Any::Any(const Any& x) : m_type(NONE), m_data(NULL) {
+Any::Any(const Any& x) : m_type(NIL), m_data(NULL) {
x.beforeRead();
*this = x;
}
@@ -274,15 +363,15 @@ Any::Any(double x) : m_type(NUMBER), m_simpleValue(x), m_data(NULL) {
}
-#ifdef G3D_32BIT
-Any::Any(int64 x) : m_type(NUMBER), m_simpleValue((double)x), m_data(NULL) {
+Any::Any(float x) : m_type(NUMBER), m_simpleValue(double(x)), m_data(NULL) {
}
-#endif // G3D_32BIT
-Any::Any(long x) : m_type(NUMBER), m_simpleValue((double)x), m_data(NULL) {
+Any::Any(char x) : m_type(NUMBER), m_simpleValue(double(x)), m_data(NULL) {
}
+Any::Any(long x) : m_type(NUMBER), m_simpleValue((double)x), m_data(NULL) {
+}
Any::Any(int x) : m_type(NUMBER), m_simpleValue((double)x), m_data(NULL) {
}
@@ -303,7 +392,7 @@ Any::Any(const std::string& s) : m_type(STRING), m_data(Data::create(STRING)) {
Any::Any(const char* s) : m_type(STRING), m_data(NULL) {
if (s == NULL) {
- m_type = NONE;
+ m_type = NIL;
} else {
ensureData();
*(m_data->value.s) = s;
@@ -311,13 +400,43 @@ Any::Any(const char* s) : m_type(STRING), m_data(NULL) {
}
-Any::Any(Type t, const std::string& name) : m_type(t), m_data(NULL) {
- alwaysAssertM(t == ARRAY || t == TABLE, "Can only create ARRAY or TABLE from Type enum.");
+
+
+Any::Any(Type t, const std::string& name, const std::string& brackets, char separator) : m_type(t), m_data(NULL) {
+ alwaysAssertM(isContainerType(t), "Can only create ARRAY or TABLE from Type enum.");
ensureData();
if (name != "") {
m_data->name = name;
}
+
+ if (brackets == "") {
+ if (t == ARRAY) {
+ m_data->bracket = PAREN;
+ } else {
+ m_data->bracket = BRACE;
+ }
+ } else if (brackets == PAREN) {
+ m_data->bracket = PAREN;
+ } else if (brackets == BRACE) {
+ m_data->bracket = BRACE;
+ } else if (brackets == BRACKET) {
+ m_data->bracket = BRACKET;
+ } else {
+ alwaysAssertM(false, std::string("illegal brackets: ") + brackets);
+ }
+
+ if (separator == '\0') {
+ if (t == ARRAY) {
+ m_data->separator = ',';
+ } else {
+ m_data->separator = ';';
+ }
+ } else if (separator == ',' || separator == ';') {
+ m_data->separator = separator;
+ } else {
+ alwaysAssertM(false, std::string("illegal separator: ") + separator);
+ }
}
@@ -329,10 +448,17 @@ Any::~Any() {
void Any::beforeWrite() {
if (isPlaceholder()) {
// This is no longer a placeholder
- m_placeholderName = "";
+ m_placeholderName.clear();
+ }
+
+ if (m_data && ! m_data->includeLine.empty()) {
+ // Forget where this Any was included from...it no
+ // longer matches the contents there.
+ m_data->includeLine = "";
}
}
+
Any& Any::operator=(const Any& x) {
x.beforeRead();
@@ -356,48 +482,20 @@ Any& Any::operator=(const Any& x) {
}
-Any& Any::operator=(double x) {
- *this = Any(x);
- return *this;
-}
-
-
-Any& Any::operator=(int x) {
- return (*this = Any(x));
-}
-
-
-Any& Any::operator=(bool x) {
- *this = Any(x);
- return *this;
-}
-
-
-Any& Any::operator=(const std::string& x) {
- *this = Any(x);
- return *this;
-}
-
-
-Any& Any::operator=(const char* x) {
- *this = Any(x);
- return *this;
-}
-
-
Any& Any::operator=(Type t) {
switch (t) {
- case NONE:
+ case NIL:
*this = Any();
break;
- case TABLE:
- case ARRAY:
+ case TABLE: // All 3 cases intentionally fall through
+ case ARRAY:
+ case EMPTY_CONTAINER:
*this = Any(t);
break;
default:
- alwaysAssertM(false, "Can only assign NONE, TABLE, or ARRAY Type enum.");
+ alwaysAssertM(false, "Can only assign NIL, TABLE, or ARRAY Type enum.");
}
return *this;
@@ -429,18 +527,23 @@ void Any::setComment(const std::string& c) {
}
-bool Any::isNone() const {
+bool Any::isNil() const {
beforeRead();
- return (m_type == NONE);
+ return (m_type == NIL);
}
-
double Any::number() const {
beforeRead();
verifyType(NUMBER);
return m_simpleValue.n;
}
+float Any::floatValue() const {
+ beforeRead();
+ verifyType(NUMBER);
+ return (float)m_simpleValue.n;
+}
+
const std::string& Any::string() const {
beforeRead();
@@ -479,14 +582,14 @@ int Any::size() const {
verifyType(ARRAY, TABLE);
switch (m_type) {
case TABLE:
- return m_data->value.t->size();
+ return (int)m_data->value.t->size();
case ARRAY:
return m_data->value.a->size();
- default:;
+ default:
return 0;
- } // switch (m_type)
+ }
}
@@ -500,6 +603,9 @@ void Any::resize(int n) {
beforeRead();
alwaysAssertM(n >= 0, "Cannot resize less than 0.");
verifyType(ARRAY);
+ if (type() == EMPTY_CONTAINER) {
+ become(ARRAY);
+ }
m_data->value.a->resize(n);
}
@@ -515,7 +621,6 @@ void Any::clear() {
case TABLE:
m_data->value.t->clear();
break;
-
default:;
}
}
@@ -526,6 +631,9 @@ const Any& Any::operator[](int i) const {
verifyType(ARRAY);
debugAssert(m_data != NULL);
Array<Any>& array = *(m_data->value.a);
+ if (i < 0 || i >= array.size()) {
+ throw IndexOutOfBounds(m_data, i, array.size());
+ }
return array[i];
}
@@ -541,9 +649,13 @@ Any& Any::next() {
Any& Any::operator[](int i) {
beforeRead();
+ ensureMutable();
verifyType(ARRAY);
debugAssert(m_data != NULL);
Array<Any>& array = *(m_data->value.a);
+ if (i < 0 || i >= array.size()) {
+ throw IndexOutOfBounds(m_data, i, array.size());
+ }
return array[i];
}
@@ -556,22 +668,25 @@ const Array<Any>& Any::array() const {
}
-void Any::append(const Any& x0) {
+void Any::_append(const Any& x0) {
beforeRead();
verifyType(ARRAY);
debugAssert(m_data != NULL);
+ if (type() == EMPTY_CONTAINER) {
+ become(ARRAY);
+ }
m_data->value.a->append(x0);
}
-void Any::append(const Any& x0, const Any& x1) {
+void Any::_append(const Any& x0, const Any& x1) {
beforeRead();
append(x0);
append(x1);
}
-void Any::append(const Any& x0, const Any& x1, const Any& x2) {
+void Any::_append(const Any& x0, const Any& x1, const Any& x2) {
beforeRead();
append(x0);
append(x1);
@@ -579,7 +694,7 @@ void Any::append(const Any& x0, const Any& x1, const Any& x2) {
}
-void Any::append(const Any& x0, const Any& x1, const Any& x2, const Any& x3) {
+void Any::_append(const Any& x0, const Any& x1, const Any& x2, const Any& x3) {
beforeRead();
append(x0);
append(x1);
@@ -592,6 +707,12 @@ const Table<std::string, Any>& Any::table() const {
beforeRead();
verifyType(TABLE);
debugAssert(m_data != NULL);
+
+ if (type() == Any::EMPTY_CONTAINER) {
+ // if empty, m_data->value.t will not be initialized as it is unknown whether this is supposed to be an array or a table
+ static const Table<std::string, Any> emptyTable;
+ return emptyTable;
+ }
return *(m_data->value.t);
}
@@ -603,13 +724,9 @@ const Any& Any::operator[](const std::string& x) const {
const Table<std::string, Any>& table = *(m_data->value.t);
Any* value = table.getPointer(x);
if (value == NULL) {
- KeyNotFound e;
- if (m_data) {
- e.filename = m_data->source.filename;
- e.line = m_data->source.line;
- e.character = m_data->source.character;
- }
+ KeyNotFound e(m_data);
e.key = x;
+ e.message = "Key not found in operator[] lookup.";
throw e;
}
return *value;
@@ -618,6 +735,7 @@ const Any& Any::operator[](const std::string& x) const {
Any& Any::operator[](const std::string& key) {
beforeRead();
+ ensureMutable();
verifyType(TABLE);
bool created = false;
@@ -637,17 +755,20 @@ Any& Any::operator[](const std::string& key) {
}
-void Any::set(const std::string& k, const Any& v) {
+void Any::_set(const std::string& k, const Any& v) {
beforeRead();
v.beforeRead();
verifyType(TABLE);
debugAssert(m_data != NULL);
+ if ( type() == EMPTY_CONTAINER) {
+ become(TABLE);
+ }
Table<std::string, Any>& table = *(m_data->value.t);
table.set(k, v);
}
-const Any& Any::get(const std::string& x, const Any& defaultVal) const {
+Any Any::_get(const std::string& x, const Any& defaultVal) const {
beforeRead();
defaultVal.beforeRead();
try {
@@ -661,12 +782,13 @@ const Any& Any::get(const std::string& x, const Any& defaultVal) const {
bool Any::operator==(const Any& x) const {
beforeRead();
x.beforeRead();
+
if (m_type != x.m_type) {
return false;
}
switch (m_type) {
- case NONE:
+ case NIL:
return true;
case BOOLEAN:
@@ -687,14 +809,17 @@ bool Any::operator==(const Any& x) const {
if (m_data->name != x.m_data->name) {
return false;
}
- Table<std::string, Any>& cmptable = *( m_data->value.t);
- Table<std::string, Any>& xcmptable = *(x.m_data->value.t);
- for (Table<std::string,Any>::Iterator it1 = cmptable.begin(), it2 = xcmptable.begin();
- it1 != cmptable.end() && it2 != xcmptable.end();
- ++it1, ++it2) {
- if (*it1 != *it2) {
+ const Table<std::string, Any>& table1 = table();
+ const Table<std::string, Any>& table2 = x.table();
+ for (Table<std::string, Any>::Iterator it = table1.begin(); it.isValid(); ++it) {
+ const Any* p2 = table2.getPointer(it->key);
+ if (p2 == NULL) {
+ // Key not found
+ return false;
+ } else if (*p2 != it->value) {
+ // Different value
return false;
- }
+ }
}
return true;
}
@@ -718,19 +843,19 @@ bool Any::operator==(const Any& x) const {
}
return true;
}
-
+
+ case EMPTY_CONTAINER:
+ return true;
default:
alwaysAssertM(false, "Unknown type.");
return false;
- } // switch (m_type)
+ }
}
bool Any::operator!=(const Any& x) const {
- beforeRead();
- x.beforeRead();
- return !operator==(x);
+ return ! operator==(x);
}
@@ -740,21 +865,35 @@ static void getDeserializeSettings(TextInput::Settings& settings) {
settings.otherLineComments = false;
settings.generateCommentTokens = true;
settings.singleQuotedStrings = false;
- settings.msvcFloatSpecials = false;
+ settings.msvcFloatSpecials = true;
settings.caseSensitive = false;
}
-std::string Any::unparse() const {
+std::string Any::unparseJSON(const TextOutput::Settings& settings, bool allowCoercion) const {
+ beforeRead();
+ TextOutput to(settings);
+ serialize(to, true, allowCoercion);
+ return to.commitString();
+}
+
+
+std::string Any::unparse(const TextOutput::Settings& settings) const {
beforeRead();
- TextOutput::Settings settings;
TextOutput to(settings);
serialize(to);
return to.commitString();
}
-void Any::parse(const std::string& src) {
+Any Any::parse(const std::string& src) {
+ Any a;
+ a._parse(src);
+ return a;
+}
+
+
+void Any::_parse(const std::string& src) {
beforeRead();
TextInput::Settings settings;
getDeserializeSettings(settings);
@@ -814,16 +953,41 @@ static bool needsQuotes(const std::string& s) {
}
-// TODO: if the output will fit on one line, compress tables and arrays into a single line
-void Any::serialize(TextOutput& to) const {
+void Any::serialize(TextOutput& to, bool json, bool coerce) const {
beforeRead();
+
+ if (m_data && ! m_data->includeLine.empty()) {
+ if (json) {
+ if (! coerce) {
+ throw "Could not coerce to JSON";
+ }
+
+ // Silently fall through
+ } else {
+ // This value came from a #include...preserve it. This includes the comment
+ // if any.
+ to.printf("%s", m_data->includeLine.c_str());
+ return;
+ }
+ }
+
if (m_data && ! m_data->comment.empty()) {
- to.printf("\n/* %s */\n", m_data->comment.c_str());
+ if (json) {
+ if (! coerce) {
+ throw "Could not coerce to JSON";
+ }
+ } else {
+ to.printf("\n/* %s */\n", m_data->comment.c_str());
+ }
}
switch (m_type) {
- case NONE:
- to.writeSymbol("NONE");
+ case NIL:
+ if (json) {
+ to.writeSymbol("null");
+ } else {
+ to.writeSymbol("NIL");
+ }
break;
case BOOLEAN:
@@ -831,7 +995,24 @@ void Any::serialize(TextOutput& to) const {
break;
case NUMBER:
- to.writeNumber(m_simpleValue.n);
+ if (json) {
+ // Specials have no legal syntax in JSON, so insert values that will parse
+ // to something close to what we want (there is no good solution for NaN, unfortunately)
+ if (m_simpleValue.n == inf()) {
+ to.writeSymbol("1e10000");
+ } else if (m_simpleValue.n == -inf()) {
+ to.writeSymbol("-1e10000");
+ } else if (isNaN(m_simpleValue.n)) {
+ if (! coerce) {
+ throw "There is no way to represent NaN in JSON";
+ }
+ to.writeSymbol("null");
+ } else {
+ to.writeNumber(m_simpleValue.n);
+ }
+ } else {
+ to.writeNumber(m_simpleValue.n);
+ }
break;
case STRING:
@@ -841,14 +1022,26 @@ void Any::serialize(TextOutput& to) const {
case TABLE: {
debugAssert(m_data != NULL);
+ debugAssert(m_data->separator != '\0');
+
if (! m_data->name.empty()) {
- if (needsQuotes(m_data->name)) {
- to.writeString(m_data->name);
+ if (json) {
+ if (! coerce) {
+ throw "Could not coerce to JSON";
+ }
} else {
- to.writeSymbol(m_data->name);
+ if (needsQuotes(m_data->name)) {
+ to.writeString(m_data->name);
+ } else {
+ to.writeSymbol(m_data->name);
+ }
}
}
- to.writeSymbol("{");
+ if (json) {
+ to.writeSymbol("{");
+ } else {
+ to.writeSymbol(m_data->bracket[0]);
+ }
to.writeNewline();
to.pushIndent();
AnyTable& table = *(m_data->value.t);
@@ -858,56 +1051,134 @@ void Any::serialize(TextOutput& to) const {
for (int i = 0; i < keys.size(); ++i) {
- to.writeSymbol(keys[i]);
- to.writeSymbol("=");
- table[keys[i]].serialize(to);
+ int prevLine = to.line();
+ if (needsQuotes(keys[i]) || json) {
+ to.writeString(keys[i]);
+ } else {
+ to.writeSymbol(keys[i]);
+ }
- if (i < keys.size() - 1) {
- to.writeSymbol(",");
+ if (json) {
+ to.writeSymbol(":");
+ } else {
+ to.writeSymbol("=");
+ }
+ table[keys[i]].serialize(to, json, coerce);
+
+ to.deleteSpace();
+ if (json) {
+ // Don't put a separator after the last
+ if (i != keys.size() - 1) {
+ to.writeSymbol(",");
+ }
+ } else {
+ to.writeSymbol(m_data->separator);
+ }
+
+ // Skip an extra line between table entries that are longer than a line
+ if (prevLine != to.line()) {
+ to.writeNewline();
}
- to.writeNewline();
- // Skip a line between table entries
to.writeNewline();
}
to.popIndent();
- to.writeSymbol("}");
+ to.writeSymbol(m_data->bracket[1]);
break;
}
case ARRAY: {
debugAssert(m_data != NULL);
+ debugAssert(m_data->separator != '\0');
+
if (! m_data->name.empty()) {
- // For arrays, leave no trailing space between the name and the paren
- to.writeSymbol(format("%s(", m_data->name.c_str()));
+ if (json) {
+ if (! coerce) {
+ throw "Could not coerce to JSON";
+ }
+ to.writeSymbol("[");
+ } else {
+ // For arrays, leave no trailing space between the name and the paren
+ to.printf("%s%c", m_data->name.c_str(), m_data->bracket[0]);
+ }
} else {
- to.writeSymbol("(");
+ if (json) {
+ to.writeSymbol("[");
+ } else {
+ to.writeSymbol(m_data->bracket[0]);
+ }
}
- to.writeNewline();
+ const Array<Any>& array = *(m_data->value.a);
+ const bool longForm = (array.size() > 0) && ((array[0].type() == ARRAY) || (array[0].type() == TABLE));
+
+ if (longForm) {
+ to.writeNewline();
+ }
+
to.pushIndent();
- Array<Any>& array = *(m_data->value.a);
for (int ii = 0; ii < size(); ++ii) {
- array[ii].serialize(to);
+ array[ii].serialize(to, json, coerce);
if (ii < size() - 1) {
- to.writeSymbol(",");
- to.writeNewline();
+ to.deleteSpace();
+ if (longForm) {
+ // Probably a long-form array
+ if (json) {
+ to.writeSymbol(",");
+ } else {
+ to.writeSymbol(m_data->separator);
+ }
+ to.writeNewline();
+ } else {
+ // Probably a short-form array
+ if (json) {
+ to.writeSymbol(",");
+ } else {
+ to.writeSymbol(m_data->separator);
+ }
+ }
}
// Put the close paren on an array right behind the last element
}
to.popIndent();
- to.writeSymbol(")");
+ if (json) {
+ to.writeSymbol("]");
+ } else {
+ to.writeSymbol(m_data->bracket[1]);
+ }
+ break;
+ }
+
+ case EMPTY_CONTAINER: {
+ debugAssert(m_data != NULL);
+ debugAssert(m_data->separator != '\0');
+
+ if (json) {
+ if (! coerce) {
+ throw "Cannot strictly convert the ambiguous Any empty container to JSON";
+ }
+ to.writeSymbols("[", "]");
+ } else {
+ if (! m_data->name.empty()) {
+ // Leave no trailing space between the name and the paren
+ to.printf("%s%c", m_data->name.c_str(), m_data->bracket[0]);
+ } else {
+ to.writeSymbol(m_data->bracket[0]);
+ }
+ to.writeSymbol(m_data->bracket[1]);
+ }
break;
}
}
+
}
void Any::deserializeComment(TextInput& ti, Token& token, std::string& comment) {
// Parse comments
while (token.type() == Token::COMMENT) {
- comment += trimWhitespace(token.string()) + "\n";
+ comment += trimWhitespace(token.string());
// Allow comments to contain newlines.
do {
@@ -919,6 +1190,7 @@ void Any::deserializeComment(TextInput& ti, Token& token, std::string& comment)
comment = trimWhitespace(comment);
}
+
/** True if \a c is an open paren of some form */
static bool isOpen(const char c) {
return c == '(' || c == '[' || c == '{';
@@ -961,7 +1233,7 @@ void Any::deserialize(TextInput& ti) {
void Any::deserialize(TextInput& ti, Token& token) {
// Deallocate old data
dropReference();
- m_type = NONE;
+ m_type = NIL;
m_simpleValue.b = false;
// Skip leading newlines
@@ -1009,7 +1281,7 @@ void Any::deserialize(TextInput& ti, Token& token) {
break;
case Token::SYMBOL:
- // Pragma, Named Array, Named Table, Array, Table, or NONE
+ // Pragma, Named Array, Named Table, Array, Table, or NIL
if (token.string() == "#") {
// Pragma
@@ -1022,14 +1294,16 @@ void Any::deserialize(TextInput& ti, Token& token) {
}
ti.readSymbol("(");
+ // The string typed into the file, which may be relative
const std::string& includeName = ti.readString();
// Find the include file
- const std::string& myPath = filenamePath(ti.filename());
- std::string t = pathConcat(myPath, includeName);
+ const std::string& myPath = FilePath::parent(ti.filename());
+
+ std::string t = FileSystem::resolve(includeName, myPath);
if (! FileSystem::exists(t)) {
- // Try and find it, starting with cwd
+ // Try and find the path, starting with the cwd
t = System::findDataFile(includeName);
}
@@ -1038,20 +1312,29 @@ void Any::deserialize(TextInput& ti, Token& token) {
// Update the source information
ensureData();
- m_data->source.filename +=
+ if (! comment.empty()) {
+ m_data->includeLine = format("\n/* %s */\n", comment.c_str());
+ }
+ m_data->includeLine += format("#include(\"%s\")", includeName.c_str());
+ m_data->source.filename +=
format(" [included from %s:%d(%d)]", ti.filename().c_str(), token.line(), token.character());
ti.readSymbol(")");
- } else if (toUpper(token.string()) == "NONE") {
- // Nothing left to do; we initialized to NONE originally
+ } else if (toUpper(token.string()) == "NIL" || token.string() == "None") {
+ // Nothing left to do; we initialized to NIL originally
+ ensureData();
+ m_data->source.set(ti, token);
+ } else if (isValidIdentifier(token.string()) && !isOpen(ti.peek().string()[0]) && ti.peek().string() != "::") {
+ // Valid unquoted string
+ m_type = STRING;
ensureData();
+ *(m_data->value.s) = token.string();
m_data->source.set(ti, token);
} else {
// Array or Table
// Parse the name
-
// s must have at least one element or this would not have
// been parsed as a symbol
std::string name;
@@ -1074,7 +1357,7 @@ void Any::deserialize(TextInput& ti, Token& token) {
m_data->name = name;
}
needRead = false;
- } // if NONE
+ } // if NIL
break;
default:
@@ -1107,10 +1390,11 @@ static bool isSeparator(char c) {
}
-void Any::readUntilCommaOrClose(TextInput& ti, Token& token) {
+void Any::readUntilSeparatorOrClose(TextInput& ti, Token& token) {
bool atClose = (token.type() == Token::SYMBOL) && isClose(token.string()[0]);
- bool atComma = isSeparator(token.string()[0]);
- while (! (atClose || atComma)) {
+ bool atSeparator = isSeparator(token.string()[0]);
+
+ while (! (atClose || atSeparator)) {
switch (token.type()) {
case Token::NEWLINE:
case Token::COMMENT:
@@ -1123,28 +1407,85 @@ void Any::readUntilCommaOrClose(TextInput& ti, Token& token) {
"Expected a comma or close paren");
}
- // Update checks
- atComma = isSeparator(token.string()[0]);
+ // Update checks
+ atSeparator = isSeparator(token.string()[0]);
atClose = (token.type() == Token::SYMBOL) && isClose(token.string()[0]);
}
}
+/**
+ Determines the type [TABLE, ARRAY, or EMPTY_CONTAINER] from the given TextInput
+ TextInput is the same at the end as it was beofr
+*/
+static Any::Type findType(TextInput& ti, const char closeSymbol) {
+ Any::Type type = Any::NIL;
+ std::vector<Token> tokens;
+ // consumes the open symbol
+ Token token = ti.read();
+ tokens.push_back(token);
+
+ bool hasAnElement = false;
+ while (type == Any::NIL) {
+ if (token.type() == Token::COMMENT) {
+ // consumes tokens and prepares to push them back onto the TextInput
+ token = ti.read();
+ tokens.push_back(token);
+ } else if ((token.type() == Token::SYMBOL) && ((token.string() == "=") || (token.string() == ":"))) {
+ // an '=' indicates a key = value pairing, and thus a table
+ type = Any::TABLE;
+ } else if (hasAnElement) {
+ // any non-comment, non-'=' token after any element indicates an array
+ type = Any::ARRAY;
+ } else if ((token.type() == Token::SYMBOL) && (token.string()[0] == closeSymbol)) {
+ // catches no previous element and a closing symbol (e.g [])
+ type = Any::EMPTY_CONTAINER;
+ } else {
+ // consumes elements, indicating one has been seen, and prepares to push them back onto TextInput
+ hasAnElement = true;
+ token = ti.read();
+ tokens.push_back(token);
+ }
+ }
+ // pushes everything back to the TextInput
+ while (!tokens.empty()) {
+ token = tokens.back();
+ ti.push(token);
+ tokens.pop_back();
+ }
+ return type;
+}
+
void Any::deserializeBody(TextInput& ti, Token& token) {
- char closeSymbol = '}';
+ char closeSymbol = '\0';
m_type = TABLE;
const char c = token.string()[0];
-
- if (c != '{') {
- m_type = ARRAY;
- // Chose the appropriate close symbol
- closeSymbol = (c == '(') ? ')' : ']';
+
+ // Chose the appropriate close symbol based on the open symbol
+ const char* bracket;
+ if (c == '(') {
+ bracket = PAREN;
+ } else if (c == '[') {
+ bracket = BRACKET;
+ } else if (c == '{') {
+ bracket = BRACE;
+ } else {
+ debugAssertM(false, "Illegal bracket type");
+ bracket = PAREN;
}
+ closeSymbol = bracket[1];
+
+ // We must set the type before we allocate m_data in ensureData().
+ m_type = findType(ti, closeSymbol);
// Allocate the underlying data structure
ensureData();
m_data->source.set(ti, token);
+ m_data->bracket = bracket;
+
+ debugAssert(m_data->type == m_type);
+ debugAssert(m_data->separator != '\0');
// Consume the open token
token = ti.read();
@@ -1157,12 +1498,12 @@ void Any::deserializeBody(TextInput& ti, Token& token) {
deserializeComment(ti, token, comment);
if ((token.type() == Token::SYMBOL) && (token.string()[0] == closeSymbol)) {
- // We're done; this catches the case where the array is empty
+ // We're done; this catches the case where the container is empty
break;
}
// Pointer the value being read
- Any a = NULL;
+ Any a;
std::string key;
if (m_type == TABLE) {
@@ -1175,8 +1516,8 @@ void Any::deserializeBody(TextInput& ti, Token& token) {
// Consume everything up to the = sign, returning the "=" sign.
token = ti.readSignificant();
- if ((token.type() != Token::SYMBOL) || (token.string() != "=")) {
- throw ParseError(ti.filename(), token.line(), token.character(), "Expected =");
+ if ((token.type() != Token::SYMBOL) || ((token.string() != "=") && token.string() != ":")) {
+ throw ParseError(ti.filename(), token.line(), token.character(), "Expected = or :");
} else {
// Read the next token, which is the value (don't consume comments--we want the value pointed to by a to get those).
token = ti.read();
@@ -1196,12 +1537,16 @@ void Any::deserializeBody(TextInput& ti, Token& token) {
append(a);
}
- // Read until the comma or close paren, discarding trailing comments and newlines
- readUntilCommaOrClose(ti, token);
+ // Read until the separator or close paren, discarding trailing comments and newlines
+ readUntilSeparatorOrClose(ti, token);
- // Consume the comma
- if (isSeparator(token.string()[0])) {
+ char s = token.string()[0];
+
+ // Consume the separator
+ if (isSeparator(s)) {
token = ti.read();
+ m_data->separator = s;
+ debugAssert(m_data->separator != '\0');
}
}
@@ -1216,6 +1561,12 @@ Any::operator int() const {
}
+Any::operator uint32() const {
+ beforeRead();
+ return uint32(number() + 0.5);
+}
+
+
Any::operator float() const {
beforeRead();
return float(number());
@@ -1258,7 +1609,6 @@ std::string Any::sourceDirectory() const {
}
}
-
void Any::verify(bool value, const std::string& message) const {
beforeRead();
if (! value) {
@@ -1286,21 +1636,109 @@ void Any::verify(bool value, const std::string& message) const {
void Any::verifyName(const std::string& n) const {
beforeRead();
- verify(beginsWith(toUpper(name()), toUpper(n)), "Name must begin with " + n);
+ verify(name() == n, "Name must be " + n);
}
void Any::verifyName(const std::string& n, const std::string& m) const {
beforeRead();
- const std::string& x = toUpper(name());
- verify(beginsWith(x, toUpper(n)) ||
- beginsWith(x, toUpper(m)), "Name must begin with " + n + " or " + m);
+ const std::string& x = name();
+ verify(x == n ||
+ x == m, "Name must be " + n + " or " + m);
+}
+
+
+void Any::verifyName(const std::string& n, const std::string& m, const std::string& p) const {
+ beforeRead();
+ const std::string& x = name();
+ verify(x == n ||
+ x == m ||
+ x == p, "Name must be " + n + ", " + m + ", or " + p);
+}
+
+
+void Any::verifyName(const std::string& n, const std::string& m, const std::string& p, const std::string& q) const {
+ beforeRead();
+ const std::string& x = name();
+ verify(x == n ||
+ x == m ||
+ x == p ||
+ x == q, "Name must be " + n + ", " + m + ", " + p + ", or " + q);
+}
+
+
+void Any::verifyNameBeginsWith(const std::string& n) const {
+ beforeRead();
+ verify(beginsWith(name(), n), "Name must begin with " + n);
+}
+
+
+void Any::verifyNameBeginsWith(const std::string& n, const std::string& m) const {
+ beforeRead();
+ const std::string& x = name();
+ verify(beginsWith(x, n) ||
+ beginsWith(x, m), "Name must be " + n + " or " + m);
+}
+
+
+void Any::verifyNameBeginsWith(const std::string& n, const std::string& m, const std::string& p) const {
+ beforeRead();
+ const std::string& x = name();
+ verify(beginsWith(x, n) ||
+ beginsWith(x, m) ||
+ beginsWith(x, p), "Name must be " + n + ", " + m + ", or " + p);
+}
+
+
+void Any::verifyNameBeginsWith(const std::string& n, const std::string& m, const std::string& p, const std::string& q) const {
+ beforeRead();
+ const std::string& x = name();
+ verify(beginsWith(x, n) ||
+ beginsWith(x, m) ||
+ beginsWith(x, p) ||
+ beginsWith(x, q), "Name must be " + n + ", " + m + ", " + p + ", or " + q);
+}
+
+
+void Any::verifyNameBeginsWith(const std::string& n, const std::string& m, const std::string& p, const std::string& q, const std::string& r) const {
+ beforeRead();
+ const std::string& x = name();
+ verify(beginsWith(x, n) ||
+ beginsWith(x, m) ||
+ beginsWith(x, p) ||
+ beginsWith(x, q) ||
+ beginsWith(x, r), "Name must be " + n + ", " + m + ", " + p + ", or " + q + ", or " + r);
+}
+
+
+void Any::verifyNameBeginsWith(const std::string& n, const std::string& m, const std::string& p, const std::string& q, const std::string& r, const std::string& s) const {
+ beforeRead();
+ const std::string& x = name();
+ verify(beginsWith(x, n) ||
+ beginsWith(x, m) ||
+ beginsWith(x, p) ||
+ beginsWith(x, q) ||
+ beginsWith(x, r) ||
+ beginsWith(x, s), "Name must be " + n + ", " + m + ", " + p + ", or " + q + ", or " + r + ", or " + s);
+}
+
+
+void Any::verifyNameBeginsWith(const std::string& n, const std::string& m, const std::string& p, const std::string& q, const std::string& r, const std::string& s, const std::string& t) const {
+ beforeRead();
+ const std::string& x = name();
+ verify(beginsWith(x, n) ||
+ beginsWith(x, m) ||
+ beginsWith(x, p) ||
+ beginsWith(x, q) ||
+ beginsWith(x, r) ||
+ beginsWith(x, s) ||
+ beginsWith(x, t), "Name must be " + n + ", " + m + ", " + p + ", or " + q + ", or " + r + ", or " + s + ", or " + t);
}
void Any::verifyType(Type t) const {
beforeRead();
- if (type() != t) {
+ if ((type() != t) && ! ((type() == EMPTY_CONTAINER) && isContainerType(t))) {
verify(false, "Must have type " + toString(t));
}
}
@@ -1308,7 +1746,8 @@ void Any::verifyType(Type t) const {
void Any::verifyType(Type t0, Type t1) const {
beforeRead();
- if (type() != t0 && type() != t1) {
+ if ((type() != t0 && !((type() == EMPTY_CONTAINER) && isContainerType(t0))) &&
+ (type() != t1 && !((type() == EMPTY_CONTAINER) && isContainerType(t1)))) {
verify(false, "Must have type " + toString(t0) + " or " + toString(t1));
}
}
@@ -1334,7 +1773,7 @@ void Any::verifySize(int s) const {
std::string Any::toString(Type t) {
switch(t) {
- case NONE: return "NONE";
+ case NIL: return "NIL";
case BOOLEAN: return "BOOLEAN";
case NUMBER: return "NUMBER";
case STRING: return "STRING";
diff --git a/dep/g3dlite/source/AnyTableReader.cpp b/dep/g3dlite/source/AnyTableReader.cpp
new file mode 100644
index 00000000000..7fff1983e46
--- /dev/null
+++ b/dep/g3dlite/source/AnyTableReader.cpp
@@ -0,0 +1,50 @@
+#include "G3D/Any.h"
+
+namespace G3D {
+
+/** Verifies that \a is a TABLE with the given \a name. */
+AnyTableReader::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::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;
+ }
+}
+
+
+void AnyTableReader::verifyDone() const {
+ if (hasMore()) {
+ // Some entries were unread. Find them.
+ const Table<std::string, Any>& table = m_any.table();
+
+ for (Table<std::string, Any>::Iterator it = table.begin();
+ it.hasMore();
+ ++it) {
+
+ if (containsUnread(it->key)) {
+ it->value.verify(false, std::string("Unread Any table key \"") + it->key + "\"");
+ }
+ }
+ }
+}
+
+
+} // namespace G3D
diff --git a/dep/g3dlite/source/AnyVal.cpp b/dep/g3dlite/source/AnyVal.cpp
deleted file mode 100644
index 7b98486523a..00000000000
--- a/dep/g3dlite/source/AnyVal.cpp
+++ /dev/null
@@ -1,1379 +0,0 @@
-/**
- @file AnyVal.cpp
- @author Morgan McGuire
- @maintainer Morgan McGuire
- @created 2006-06-11
- @edited 2008-07-14
- */
-
-#include "G3D/AnyVal.h"
-#include "G3D/Array.h"
-#include "G3D/stringutils.h"
-#include "G3D/Table.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/Rect2D.h"
-#include "G3D/AABox.h"
-#include "G3D/CoordinateFrame.h"
-#include "G3D/Quat.h"
-#include "G3D/TextInput.h"
-#include "G3D/TextOutput.h"
-#include "G3D/BinaryInput.h"
-#include "G3D/BinaryOutput.h"
-
-namespace G3D {
-
-AnyVal AnyVal::fromFile(const std::string& filename) {
- TextInput t(filename);
- return AnyVal(t);
-}
-
-
-void AnyVal::load(const std::string& filename) {
- *this = fromFile(filename);
-}
-
-
-void AnyVal::save(const std::string& filename) const {
- TextOutput t(filename);
- serialize(t);
- t.commit();
-}
-
-
-AnyVal::AnyVal() : m_type(NIL), m_value(NULL), m_referenceCount(NULL) {
-}
-
-
-AnyVal::AnyVal(bool b) : m_type(BOOLEAN), m_value(new bool(b)), m_referenceCount(NULL) {
-}
-
-
-AnyVal::AnyVal(G3D::TextInput& t) : m_type(NIL), m_value(NULL), m_referenceCount(NULL) {
- deserialize(t);
-}
-
-
-/*AnyVal::AnyVal(G3D::BinaryInput& b) {
- deserialize(b);
-}
-*/
-
-AnyVal::AnyVal(double v) : m_type(NUMBER), m_referenceCount(NULL) {
- m_value = new double(v);
-}
-
-
-AnyVal::AnyVal(int v) : m_type(NUMBER), m_referenceCount(NULL) {
- m_value = new double(v);
-}
-
-
-AnyVal::AnyVal(const Rect2D& v) : m_type(RECT2D), m_referenceCount(NULL) {
- m_value = new Rect2D(v);
-}
-
-
-AnyVal::AnyVal(const AABox& v) : m_type(AABOX), m_referenceCount(NULL) {
- m_value = new AABox(v);
-}
-
-
-AnyVal::AnyVal(const Vector2& v) : m_type(VECTOR2), m_referenceCount(NULL) {
- m_value = new Vector2(v);
-}
-
-
-AnyVal::AnyVal(const Vector3& v) : m_type(VECTOR3), m_referenceCount(NULL) {
- m_value = new Vector3(v);
-}
-
-
-AnyVal::AnyVal(const Vector4& v) : m_type(VECTOR4), m_referenceCount(NULL) {
- m_value = new Vector4(v);
-}
-
-
-AnyVal::AnyVal(const Color1& v) : m_type(COLOR1), m_referenceCount(NULL) {
- m_value = new Color1(v);
-}
-
-
-AnyVal::AnyVal(const Color3& v) : m_type(COLOR3), m_referenceCount(NULL) {
- m_value = new Color3(v);
-}
-
-
-AnyVal::AnyVal(const Color4& v) : m_type(COLOR4), m_referenceCount(NULL) {
- m_value = new Color4(v);
-}
-
-
-AnyVal::AnyVal(const std::string& v) : m_type(STRING), m_referenceCount(NULL) {
- m_value = new std::string(v);
-}
-
-
-AnyVal::AnyVal(const char* v) : m_type(STRING), m_referenceCount(NULL) {
- m_value = new std::string(v);
-}
-
-
-AnyVal::AnyVal(const Quat& v) : m_type(QUAT), m_referenceCount(NULL) {
- m_value = new Quat(v);
-}
-
-
-AnyVal::AnyVal(const CoordinateFrame& v) : m_type(COORDINATEFRAME), m_referenceCount(NULL) {
- m_value = new CoordinateFrame(v);
-}
-
-
-AnyVal::AnyVal(const Matrix2& v) : m_type(MATRIX2), m_referenceCount(NULL) {
- m_value = new Matrix2(v);
-}
-
-AnyVal::AnyVal(const Matrix3& v) : m_type(MATRIX3), m_referenceCount(NULL) {
- m_value = new Matrix3(v);
-}
-
-
-AnyVal::AnyVal(const Matrix4& v) : m_type(MATRIX4), m_referenceCount(NULL) {
- m_value = new Matrix4(v);
-}
-
-
-AnyVal::AnyVal(const AnyVal& c) : m_type(NIL), m_value(NULL), m_referenceCount(NULL) {
- *this = c;
-}
-
-
-AnyVal::AnyVal(Type arrayOrTable) : m_type(NIL), m_value(NULL), m_referenceCount(new int(1)) {
- // TODO: make AnyVal::createArray()
- switch (arrayOrTable) {
- case ARRAY:
- m_type = ARRAY;
- m_value = new Array<AnyVal>();
- break;
-
- case TABLE:
- m_type = TABLE;
- m_value = new Table<std::string, AnyVal>();
- break;
-
- default:
- debugAssertM(false, "Cannot construct AnyVal from constants except ARRAY or TABLE.");
- }
-}
-
-
-AnyVal::~AnyVal() {
- deleteValue();
-}
-
-
-void AnyVal::deleteValue() {
- if (m_referenceCount) {
- --(*m_referenceCount);
- if (*m_referenceCount <= 0) {
- delete m_referenceCount;
- m_referenceCount = NULL;
- // Pass through and delete the real object now
- } else {
- // Someone else is holding a reference, so we can't delete
- // the object.
- m_referenceCount = NULL;
- return;
- }
- }
-
- switch (m_type) {
- case NIL:
- // Nothing to do
- break;
-
- case NUMBER:
- delete (double*)m_value;
- break;
-
- case BOOLEAN:
- delete (bool*)m_value;
- break;
-
- case STRING:
- delete (std::string*)m_value;
- break;
-
- case RECT2D:
- delete (Rect2D*)m_value;
- break;
-
- case AABOX:
- delete (AABox*)m_value;
- break;
-
- case VECTOR2:
- delete (Vector2*)m_value;
- break;
-
- case VECTOR3:
- delete (Vector3*)m_value;
- break;
-
- case VECTOR4:
- delete (Vector4*)m_value;
- break;
-
- case MATRIX2:
- delete (Matrix2*)m_value;
- break;
-
- case MATRIX3:
- delete (Matrix3*)m_value;
- break;
-
- case MATRIX4:
- delete (Matrix4*)m_value;
- break;
-
- case QUAT:
- delete (Quat*)m_value;
- break;
-
- case COORDINATEFRAME:
- delete (CoordinateFrame*)m_value;
- break;
-
- case COLOR1:
- delete (Color1*)m_value;
- break;
-
- case COLOR3:
- delete (Color3*)m_value;
- break;
-
- case COLOR4:
- delete (Color4*)m_value;
- break;
-
- case ARRAY:
- delete (Array<AnyVal>*)m_value;
- break;
-
- case TABLE:
- delete (Table<std::string, AnyVal>*)m_value;
- break;
-
- default:
- debugAssertM(false, "Internal error: no destructor for this type.");
- }
-
- m_value = NULL;
-}
-
-
-AnyVal& AnyVal::operator=(const AnyVal& v) {
- deleteValue();
-
- m_type = v.m_type;
-
- m_referenceCount = v.m_referenceCount;
-
- if (isSharedType()) {
- ++(*m_referenceCount);
- m_value = v.m_value;
- } else {
- m_value = v.copyValue();
- }
-
- return *this;
-}
-
-
-void* AnyVal::copyValue() const {
- switch (m_type) {
- case NIL:
- return NULL;
-
- case NUMBER:
- return new double(*(double*)m_value);
-
- case BOOLEAN:
- return new bool(*(bool*)m_value);
-
- case STRING:
- return new std::string(*(std::string*)m_value);
-
- case RECT2D:
- return new Rect2D(*(Rect2D*)m_value);
-
- case AABOX:
- return new AABox(*(AABox*)m_value);
-
- case VECTOR2:
- return new Vector2(*(Vector2*)m_value);
-
- case VECTOR3:
- return new Vector3(*(Vector3*)m_value);
-
- case VECTOR4:
- return new Vector4(*(Vector4*)m_value);
-
- case MATRIX2:
- return new Matrix2(*(Matrix2*)m_value);
-
- case MATRIX3:
- return new Matrix3(*(Matrix3*)m_value);
-
- case MATRIX4:
- return new Matrix4(*(Matrix4*)m_value);
-
- case QUAT:
- return new Quat(*(Quat*)m_value);
-
- case COORDINATEFRAME:
- return new CoordinateFrame(*(CoordinateFrame*)m_value);
-
- case COLOR1:
- return new Color1(*(Color1*)m_value);
-
- case COLOR3:
- return new Color3(*(Color3*)m_value);
-
- case COLOR4:
- return new Color4(*(Color4*)m_value);
-
- case ARRAY:
- return new Array<AnyVal>(*(Array<AnyVal>*)m_value);
-
- case TABLE:
- return new Table<std::string, AnyVal>(*(Table<std::string, AnyVal>*)m_value);
-
- default:
- debugAssertM(false, "Internal error: no assignment operator for this type.");
- return NULL;
- }
-}
-
-AnyVal::Type AnyVal::type() const {
- return m_type;
-}
-
-
-static bool legalIdentifier(const std::string& s) {
- if (s.size() == 0) {
- return false;
- }
-
- if (! isLetter(s[0]) || (s[0] == '_')) {
- return false;
- }
-
- bool ok = true;
-
- for (unsigned int i = 1; i < s.size(); ++i) {
- ok &= isDigit(s[i]) || isLetter(s[i]) || (s[i] == '_');
- }
-
- return ok;
-}
-
-
-void AnyVal::serialize(G3D::TextOutput& t) const {
- switch (m_type) {
- case NIL:
- t.writeSymbol("Nil");
- break;
-
- case NUMBER:
- t.printf("%g", *(double*)m_value);
- break;
-
- case BOOLEAN:
- t.writeBoolean(*(bool*)m_value);
- break;
-
- case STRING:
- t.writeString(*(std::string*)m_value);
- break;
-
- case RECT2D:
- t.printf("R(%g, %g, %g, %g)", ((Rect2D*)m_value)->x0(), ((Rect2D*)m_value)->y0(),
- ((Rect2D*)m_value)->width(), ((Rect2D*)m_value)->height());
- break;
-
- case AABOX:
- t.printf("AAB(V3(%g, %g, %g), V3(%g, %g, %g))",
- aabox().low().x,
- aabox().low().y,
- aabox().low().z,
- aabox().high().x,
- aabox().high().y,
- aabox().high().z);
- break;
-
- case VECTOR2:
- t.printf("V2(%g, %g)", ((Vector2*)m_value)->x, ((Vector2*)m_value)->y);
- break;
-
- case VECTOR3:
- t.printf("V3(%g, %g, %g)", ((Vector3*)m_value)->x, ((Vector3*)m_value)->y, ((Vector3*)m_value)->z);
- break;
-
- case VECTOR4:
- t.printf("V4(%g, %g, %g, %g)", ((Vector4*)m_value)->x, ((Vector4*)m_value)->y, ((Vector4*)m_value)->z, ((Vector4*)m_value)->w);
- break;
-
- case MATRIX2:
- {
- const Matrix2& m = *(Matrix2*)m_value;
- t.printf("M2(\n");
- t.pushIndent();
- t.printf("%10.5f, %10.5f,\n%10.5f, %10.5f)",
- m[0][0], m[0][1],
- m[1][0], m[1][1]);
- t.popIndent();
- }
- break;
-
- case MATRIX3:
- {
- const Matrix3& m = *(Matrix3*)m_value;
- t.printf("M3(\n");
- t.pushIndent();
- t.printf("%10.5f, %10.5f, %10.5f,\n%10.5f, %10.5f, %10.5f,\n%10.5f, %10.5f, %10.5f)",
- m[0][0], m[0][1], m[0][2],
- m[1][0], m[1][1], m[1][2],
- m[2][0], m[2][1], m[2][2]);
- t.popIndent();
- }
- break;
-
- case MATRIX4:
- {
- const Matrix4& m = *(Matrix4*)m_value;
- t.printf("M4(\n");
- t.pushIndent();
- t.printf(
- "%10.5f, %10.5f, %10.5f, %10.5f,\n"
- "%10.5f, %10.5f, %10.5f, %10.5f,\n"
- "%10.5f, %10.5f, %10.5f, %10.5f,\n"
- "%10.5f, %10.5f, %10.5f, %10.5f)",
- m[0][0], m[0][1], m[0][2], m[0][3],
- m[1][0], m[1][1], m[1][2], m[1][3],
- m[2][0], m[2][1], m[2][2], m[2][3],
- m[3][0], m[3][1], m[3][2], m[3][3]);
- t.popIndent();
- }
- break;
-
- case QUAT:
- t.printf("Q(%g, %g, %g, %g)", ((Quat*)m_value)->x, ((Quat*)m_value)->y, ((Quat*)m_value)->z, ((Quat*)m_value)->w);
- break;
-
- case COORDINATEFRAME:
- {
- const CoordinateFrame& c = *(CoordinateFrame*)m_value;
- float x,y,z,yaw,pitch,roll;
- c.getXYZYPRDegrees(x,y,z,yaw,pitch,roll);
- t.printf("CF(V3(%g,%g,%g), %g, %g, %g)", x, y, z, yaw, pitch, roll);
- /*
- t.pushIndent();
- t.printf(
- "CF(\n%10.5f, %10.5f, %10.5f, %10.5f,\n"
- "%10.5f, %10.5f, %10.5f, %10.5f,\n"
- "%10.5f, %10.5f, %10.5f, %10.5f)",
- c.rotation[0][0], c.rotation[0][1], c.rotation[0][2], c.translation.x,
- c.rotation[1][0], c.rotation[1][1], c.rotation[1][2], c.translation.y,
- c.rotation[2][0], c.rotation[2][1], c.rotation[2][2], c.translation.z);
- t.popIndent();
- */
- }
- break;
-
- case COLOR1:
- t.printf("C1(%g)", ((Color1*)m_value)->value);
- break;
-
- case COLOR3:
- t.printf("C3(%g, %g, %g)", ((Color3*)m_value)->r, ((Color3*)m_value)->g, ((Color3*)m_value)->b);
- break;
-
- case COLOR4:
- t.printf("C4(%g, %g, %g, %g)", ((Color4*)m_value)->r, ((Color4*)m_value)->g, ((Color4*)m_value)->b, ((Color4*)m_value)->a);
- break;
-
- case ARRAY:
- {
- const Array<AnyVal>& a = *(Array<AnyVal>*)m_value;
- t.printf("[\n");
- t.pushIndent();
- for (int i = 0; i < a.size(); ++i) {
- a[i].serialize(t);
- if (i != a.size() - 1) {
- t.printf(", \n");
- }
- }
- t.printf("]");
- t.popIndent();
- }
- break;
-
- case TABLE:
- {
- const Table<std::string, AnyVal>& a = *(Table<std::string, AnyVal>*)m_value;
- t.printf("{\n");
- t.pushIndent();
- Table<std::string, AnyVal>::Iterator i = a.begin();
- const Table<std::string, AnyVal>::Iterator end = a.end();
- while (i != end) {
- // Quote names that are not legal C++ identifiers
- if (! legalIdentifier(i->key)) {
- t.printf("'%s' ", i->key.c_str());
- } else {
- t.writeSymbol(i->key);
- }
- t.printf("= ");
-
- i->value.serialize(t);
-
- if (i != end) {
- t.printf("\n");
- }
- ++i;
- }
- t.popIndent();
- t.printf("}");
- }
- break;
-
- default:
- debugAssertM(false, "Internal error: no serialize method for this type.");
- }
-}
-
-
-std::string AnyVal::toString() const {
- TextOutput t;
- serialize(t);
- std::string s;
- t.commitString(s);
- return s;
-}
-
-void AnyVal::deserialize(G3D::TextInput& t) {
- deleteValue();
- m_type = NIL;
- m_value = NULL;
-
- if (! t.hasMore()) {
- return;
- }
-
- switch (t.peek().type()) {
- case Token::END:
- // should never get here because of the hasMore check above
- return;
- break;
-
- case Token::NUMBER:
- m_type = NUMBER;
- m_value = new double(t.readNumber());
- break;
-
- case Token::STRING:
- m_type = STRING;
- m_value = new std::string(t.readString());
- break;
-
- case Token::NEWLINE:
- m_type = STRING;
- m_value = new std::string(t.readNewline());
- break;
-
- case Token::COMMENT:
- m_type = STRING;
- m_value = new std::string(t.readComment());
- break;
-
- case Token::BOOLEAN:
- m_type = BOOLEAN;
- m_value = new bool(t.readBoolean());
- break;
-
- case Token::SYMBOL:
- {
- std::string s = t.readSymbol();
- if (s == "NIL") {
- break;
-
- } else if (s == "true") {
-
- m_type = BOOLEAN;
- m_value = new bool(true);
-
- } else if (s == "false") {
-
- m_type = BOOLEAN;
- m_value = new bool(false);
-
- } else if (s == "R") {
-
- m_type = RECT2D;
- t.readSymbol("(");
- float x,y,w,h;
- x = (float)t.readNumber();
- t.readSymbol(",");
- y = (float)t.readNumber();
- t.readSymbol(",");
- w = (float)t.readNumber();
- t.readSymbol(",");
- h = (float)t.readNumber();
- t.readSymbol(")");
- m_value = new Rect2D(Rect2D::xywh(x, y, w, h));
-
- } else if (s == "AAB") {
-
- m_type = AABOX;
- Vector3 v[2];
- t.readSymbol("(");
- for (int i = 0; i < 2; ++i) {
- t.readSymbols("V3", "(");
- v[i].x = (float)t.readNumber();
- t.readSymbol(",");
- v[i].y = (float)t.readNumber();
- t.readSymbol(",");
- v[i].z = (float)t.readNumber();
- t.readSymbol(",");
- if (i == 0) {
- t.readSymbol(",");
- }
- }
- t.readSymbol(")");
- m_value = new AABox(v[0], v[1]);
-
- } else if (s == "V2") {
-
- t.readSymbol("(");
- Vector2 v;
- v.x = (float)t.readNumber();
- t.readSymbol(",");
- v.y = (float)t.readNumber();
- t.readSymbol(")");
- m_value = new Vector2(v);
- m_type = VECTOR2;
-
- } else if (s == "V3") {
-
- t.readSymbol("(");
- Vector3 v;
- v.x = (float)t.readNumber();
- t.readSymbol(",");
- v.y = (float)t.readNumber();
- t.readSymbol(",");
- v.z = (float)t.readNumber();
- t.readSymbol(")");
- m_value = new Vector3(v);
- m_type = VECTOR3;
-
- } else if (s == "V4") {
-
- t.readSymbol("(");
- Vector4 v;
- v.x = (float)t.readNumber();
- t.readSymbol(",");
- v.y = (float)t.readNumber();
- t.readSymbol(",");
- v.z = (float)t.readNumber();
- t.readSymbol(",");
- v.w = (float)t.readNumber();
- t.readSymbol(")");
- m_value = new Vector4(v);
- m_type = VECTOR4;
-
- } else if (s == "M2") {
-
- t.readSymbol("(");
- Matrix2 m;
- for (int r = 0; r < 2; ++r) {
- for (int c = 0; c < 2; ++c) {
- m[r][c] = (float)t.readNumber();
- if ((c != 1) || (r != 1)) {
- t.readSymbol(",");
- }
- }
- }
- t.readSymbol(")");
- m_value = new Matrix2(m);
- m_type = MATRIX2;
-
- } else if (s == "M3") {
-
- t.readSymbol("(");
- Matrix3 m;
- for (int r = 0; r < 3; ++r) {
- for (int c = 0; c < 3; ++c) {
- m[r][c] = (float)t.readNumber();
- if ((c != 2) || (r != 2)) {
- t.readSymbol(",");
- }
- }
- }
- t.readSymbol(")");
- m_value = new Matrix3(m);
- m_type = MATRIX3;
-
- } else if (s == "M4") {
-
- t.readSymbol("(");
- Matrix4 m;
- for (int r = 0; r < 4; ++r) {
- for (int c = 0; c < 4; ++c) {
- m[r][c] = (float)t.readNumber();
- if ((c != 3) || (r != 3)) {
- t.readSymbol(",");
- }
- }
- }
- t.readSymbol(")");
- m_value = new Matrix4(m);
- m_type = MATRIX4;
-
- } else if (s == "Q") {
-
- t.readSymbol("(");
- Quat q;
- q.x = (float)t.readNumber();
- t.readSymbol(",");
- q.y = (float)t.readNumber();
- t.readSymbol(",");
- q.z = (float)t.readNumber();
- t.readSymbol(",");
- q.w = (float)t.readNumber();
- t.readSymbol(")");
- m_value = new Quat(q);
- m_type = QUAT;
-
- } else if (s == "CF") {
-
- t.readSymbol("(");
- CoordinateFrame m;
- if (t.peek().type() == Token::SYMBOL) {
- // Angle format
- float x, y, z, yaw, roll, pitch;
- t.readSymbols("V3", "(");
- x = (float)t.readNumber();
- t.readSymbol(",");
- y = (float)t.readNumber();
- t.readSymbol(",");
- z = (float)t.readNumber();
- t.readSymbols(")", ",");
- yaw = (float)t.readNumber();
- t.readSymbol(",");
- pitch = (float)t.readNumber();
- roll = 0;
- if (t.peek().string() == ",") {
- t.readSymbol(",");
- roll = (float)t.readNumber();
- }
- m = CoordinateFrame::fromXYZYPRDegrees(x, y, z, yaw, pitch, roll);
- } else {
- // Matrix format
- for (int r = 0; r < 3; ++r) {
- for (int c = 0; c < 3; ++c) {
- m.rotation[r][c] = (float)t.readNumber();
- }
- m.translation[r] = (float)t.readNumber();
- if (r != 2) {
- t.readSymbol(",");
- }
- }
- }
- t.readSymbol(")");
- m_value = new CoordinateFrame(m);
- m_type = COORDINATEFRAME;
-
- } else if (s == "C1") {
-
- t.readSymbol("(");
- float v = (float)t.readNumber();
- t.readSymbol(")");
- m_value = new Color1(v);
- m_type = COLOR1;
-
- } else if (s == "C3") {
-
- t.readSymbol("(");
- Color3 c;
- c.r = (float)t.readNumber();
- t.readSymbol(",");
- c.g = (float)t.readNumber();
- t.readSymbol(",");
- c.b = (float)t.readNumber();
- t.readSymbol(")");
- m_value = new Color3(c);
- m_type = COLOR3;
-
- } else if (s == "C4") {
-
- t.readSymbol("(");
- Color4 c;
- c.r = (float)t.readNumber();
- t.readSymbol(",");
- c.g = (float)t.readNumber();
- t.readSymbol(",");
- c.b = (float)t.readNumber();
- t.readSymbol(",");
- c.a = (float)t.readNumber();
- t.readSymbol(")");
- m_value = new Color4(c);
- m_type = COLOR4;
-
- } else if (s == "[") {
-
- // Array
- m_type = ARRAY;
- m_value = new Array<AnyVal>();
- m_referenceCount = new int(1);
- Array<AnyVal>& a = *(Array<AnyVal>*)m_value;
-
- Token peek = t.peek();
- while ((peek.type() != Token::SYMBOL) || (peek.string() != "]")) {
- // Avoid copying large objects
- a.next().deserialize(t);
-
- peek = t.peek();
- if (peek.type() != Token::SYMBOL) {
- throw CorruptText("Expected ',' or ']'", peek);
- } else if (peek.string() == ",") {
- t.readSymbol(",");
- } else if (peek.string() != "]") {
- throw CorruptText("Missing ']'", peek);
- }
- }
- t.readSymbol("]");
-
- } else if (s == "{") {
-
- // Table
- m_type = TABLE;
- m_value = new Table<std::string, AnyVal>();
- m_referenceCount = new int(1);
- Table<std::string, AnyVal>& a = *(Table<std::string, AnyVal>*)m_value;
-
- Token peek = t.peek();
- while ((peek.type() != Token::SYMBOL) || (peek.string() != "}")) {
-
- std::string key;
- // Get the name
- if (peek.type() == Token::SYMBOL) {
- key = t.readSymbol();
- } else if (peek.extendedType() == Token::SINGLE_QUOTED_TYPE) {
- key = t.readString();
- } else {
- throw CorruptText("Expected name inside table", peek);
- }
-
- t.readSymbol("=");
-
- // Avoid copying large values
- a.set(key, AnyVal());
- a[key].deserialize(t);
-
- peek = t.peek();
- if ((peek.type() != Token::SYMBOL) && (peek.extendedType() != Token::SINGLE_QUOTED_TYPE)) {
- throw CorruptText("Missing expected name or '}'", peek);
- }
- }
- t.readSymbol("}");
-
- } else {
- throw CorruptText("Invalid value type.", t.peek());
- } // dispatch on symbol type
- } // scope
- break;
- }
-}
-
-
-AnyVal& AnyVal::operator[](const char* key) {
- return this->operator[]((std::string)key);
-}
-
-
-const AnyVal& AnyVal::operator[](const char* key) const {
- return this->operator[]((std::string)key);
-}
-
-
-AnyVal& AnyVal::operator[](const std::string& key) {
- if (m_type != TABLE) {
- throw WrongType(TABLE, m_type);
- }
-
- makeMutable();
-
- Table<std::string, AnyVal>& t = *(Table<std::string, AnyVal>*)m_value;
-
- if (! t.containsKey(key)) {
- t.set(key, AnyVal());
- }
-
- return t[key];
-}
-
-
-const AnyVal& AnyVal::operator[](const std::string& key) const {
- if (m_type != TABLE) {
- throw WrongType(TABLE, m_type);
- }
-
- const Table<std::string, AnyVal>& t = *(const Table<std::string, AnyVal>*)m_value;
-
- if (! t.containsKey(key)) {
- throw KeyNotFound(key);
- }
-
- return t[key];
-}
-
-
-void AnyVal::append(const AnyVal& v) {
- if (m_type != ARRAY) {
- throw WrongType(ARRAY, m_type);
- }
- makeMutable();
-
- Array<AnyVal>& a = *(Array<AnyVal>*)m_value;
- a.append(v);
-}
-
-
-void AnyVal::getKeys(Array<std::string>& keys) const {
- if (m_type != TABLE) {
- throw WrongType(TABLE, m_type);
- }
-
- const Table<std::string, AnyVal>& t = *(const Table<std::string, AnyVal>*)m_value;
- t.getKeys(keys);
-}
-
-
-int AnyVal::size() const {
- switch (m_type) {
- case TABLE:
- {
- const Table<std::string, AnyVal>& t = *(const Table<std::string, AnyVal>*)m_value;
- return t.size();
- }
-
- case ARRAY:
- {
- const Array<AnyVal>& a = *(Array<AnyVal>*)m_value;
- return a.size();
- }
-
- default:
- throw WrongType(ARRAY, m_type);
- }
-}
-
-
-AnyVal& AnyVal::operator[](int i) {
- if (m_type != ARRAY) {
- throw WrongType(ARRAY, m_type);
- }
- makeMutable();
-
- Array<AnyVal>& a = *(Array<AnyVal>*)m_value;
-
- if (i < 0) {
- throw IndexOutOfBounds(i, a.size());
- }
-
- if (a.size() <= i) {
- a.resize(i + 1);
- }
-
- return a[i];
-}
-
-
-const AnyVal& AnyVal::operator[](int i) const {
- if (m_type != ARRAY) {
- throw WrongType(ARRAY, m_type);
- }
-
- const Array<AnyVal>& a = *(Array<AnyVal>*)m_value;
-
- if (a.size() <= i || i < 0) {
- throw IndexOutOfBounds(i, a.size());
- }
-
- return a[i];
-}
-
-
-void AnyVal::makeMutable() {
- if (*m_referenceCount > 1) {
- // This is a shared instance
- --(*m_referenceCount);
- m_referenceCount = new int(1);
- m_value = copyValue();
- }
-}
-
-bool AnyVal::boolean() const {
- if (m_type != BOOLEAN) {
- throw WrongType(BOOLEAN, m_type);
- }
-
- return *(bool*)m_value;
-}
-
-
-bool AnyVal::boolean(bool defaultVal) const {
- if (m_type != BOOLEAN) {
- return defaultVal;
- }
-
- return *(bool*)m_value;
-}
-
-
-const std::string& AnyVal::string() const {
- if (m_type != STRING) {
- throw WrongType(STRING, m_type);
- }
-
- return *(std::string*)m_value;
-}
-
-
-const std::string& AnyVal::string(const std::string& defaultVal) const {
- if (m_type != STRING) {
- return defaultVal;
- } else {
- return *(std::string*)m_value;
- }
-}
-
-
-double AnyVal::number() const {
- if (m_type != NUMBER) {
- throw WrongType(NUMBER, m_type);
- }
-
- return *(double*)m_value;
-}
-
-
-double AnyVal::number(double defaultVal) const {
- if (m_type != NUMBER) {
- return defaultVal;
- } else {
- return *(double*)m_value;
- }
-}
-
-
-const Rect2D& AnyVal::rect2D() const {
- if (m_type != RECT2D) {
- throw WrongType(RECT2D, m_type);
- }
-
- return *(Rect2D*)m_value;
-}
-
-
-const Rect2D& AnyVal::rect2D(const Rect2D& defaultVal) const {
- if (m_type != RECT2D) {
- return defaultVal;
- } else {
- return *(Rect2D*)m_value;
- }
-}
-
-
-const AABox& AnyVal::aabox() const {
- if (m_type != AABOX) {
- throw WrongType(AABOX, m_type);
- }
-
- return *(AABox*)m_value;
-}
-
-
-const AABox& AnyVal::aabox(const AABox& defaultVal) const {
- if (m_type != AABOX) {
- return defaultVal;
- } else {
- return *(AABox*)m_value;
- }
-}
-
-
-const Color1& AnyVal::color1() const {
- if (m_type != COLOR1) {
- throw WrongType(COLOR1, m_type);
- }
-
- return *(Color1*)m_value;
-}
-
-
-const Color1& AnyVal::color1(const Color1& defaultVal) const {
- if (m_type != COLOR1) {
- return defaultVal;
- } else {
- return *(Color1*)m_value;
- }
-}
-
-
-const Color3& AnyVal::color3() const {
- if (m_type != COLOR3) {
- throw WrongType(COLOR3, m_type);
- }
-
- return *(Color3*)m_value;
-}
-
-
-const Color3& AnyVal::color3(const Color3& defaultVal) const {
- if (m_type != COLOR3) {
- return defaultVal;
- } else {
- return *(Color3*)m_value;
- }
-}
-
-
-const Color4& AnyVal::color4() const {
- if (m_type != COLOR4) {
- throw WrongType(COLOR4, m_type);
- }
-
- return *(Color4*)m_value;
-}
-
-
-const Color4& AnyVal::color4(const Color4& defaultVal) const {
- if (m_type != COLOR4) {
- return defaultVal;
- } else {
- return *(Color4*)m_value;
- }
-}
-
-
-const Vector2& AnyVal::vector2() const {
- if (m_type != VECTOR2) {
- throw WrongType(VECTOR2, m_type);
- }
-
- return *(Vector2*)m_value;
-}
-
-
-const Vector2& AnyVal::vector2(const Vector2& defaultVal) const {
- if (m_type != VECTOR2) {
- return defaultVal;
- } else {
- return *(Vector2*)m_value;
- }
-}
-
-
-const Vector3& AnyVal::vector3() const {
- if (m_type != VECTOR3) {
- throw WrongType(VECTOR3, m_type);
- }
-
- return *(Vector3*)m_value;
-}
-
-
-const Vector3& AnyVal::vector3(const Vector3& defaultVal) const {
- if (m_type != VECTOR3) {
- return defaultVal;
- } else {
- return *(Vector3*)m_value;
- }
-}
-
-
-const Vector4& AnyVal::vector4() const {
- if (m_type != VECTOR4) {
- throw WrongType(VECTOR4, m_type);
- }
-
- return *(Vector4*)m_value;
-}
-
-
-const Vector4& AnyVal::vector4(const Vector4& defaultVal) const {
- if (m_type != VECTOR4) {
- return defaultVal;
- } else {
- return *(Vector4*)m_value;
- }
-}
-
-
-const CoordinateFrame& AnyVal::coordinateFrame() const {
- if (m_type != COORDINATEFRAME) {
- throw WrongType(COORDINATEFRAME, m_type);
- }
-
- return *(CoordinateFrame*)m_value;
-}
-
-
-const CoordinateFrame& AnyVal::coordinateFrame(const CoordinateFrame& defaultVal) const {
- if (m_type != COORDINATEFRAME) {
- return defaultVal;
- } else {
- return *(CoordinateFrame*)m_value;
- }
-}
-
-const Matrix2& AnyVal::matrix2(const Matrix2& defaultVal) const {
- if (m_type != MATRIX2) {
- return defaultVal;
- } else {
- return *(Matrix2*)m_value;
- }
-}
-
-
-const Matrix2& AnyVal::matrix2() const {
- if (m_type != MATRIX2) {
- throw WrongType(MATRIX2, m_type);
- }
-
- return *(Matrix2*)m_value;
-}
-
-
-const Matrix3& AnyVal::matrix3(const Matrix3& defaultVal) const {
- if (m_type != MATRIX3) {
- return defaultVal;
- } else {
- return *(Matrix3*)m_value;
- }
-}
-
-
-const Matrix3& AnyVal::matrix3() const {
- if (m_type != MATRIX3) {
- throw WrongType(MATRIX3, m_type);
- }
-
- return *(Matrix3*)m_value;
-}
-
-
-const Matrix4& AnyVal::matrix4(const Matrix4& defaultVal) const {
- if (m_type != MATRIX4) {
- return defaultVal;
- } else {
- return *(Matrix4*)m_value;
- }
-}
-
-
-const Matrix4& AnyVal::matrix4() const {
- if (m_type != MATRIX4) {
- throw WrongType(MATRIX4, m_type);
- }
-
- return *(Matrix4*)m_value;
-}
-
-
-const Quat& AnyVal::quat(const Quat& defaultVal) const {
- if (m_type != QUAT) {
- return defaultVal;
- } else {
- return *(Quat*)m_value;
- }
-}
-
-
-const Quat& AnyVal::quat() const {
- if (m_type != QUAT) {
- throw WrongType(QUAT, m_type);
- }
-
- return *(Quat*)m_value;
-}
-
-
-const AnyVal& AnyVal::get(const std::string& key, const AnyVal& defaultVal) const {
- if (m_type != TABLE) {
- return defaultVal;
- }
-
- const Table<std::string, AnyVal>& t = *(const Table<std::string, AnyVal>*)m_value;
-
- if (t.containsKey(key)) {
- return t[key];
- } else {
- return defaultVal;
- }
-}
-
-
-const AnyVal& AnyVal::get(const std::string& key) const {
- if (m_type != TABLE) {
- throw WrongType(TABLE, m_type);
- }
-
- const Table<std::string, AnyVal>& t = *(const Table<std::string, AnyVal>*)m_value;
-
- if (t.containsKey(key)) {
- return t[key];
- } else {
- throw KeyNotFound(key);
- }
-}
-
-
-const AnyVal& AnyVal::get(int i, const AnyVal& defaultVal) const {
- if (m_type != ARRAY) {
- return defaultVal;
- }
-
- const Array<AnyVal>& a = *(const Array<AnyVal>*)m_value;
-
- if ((i >= 0) && (i < a.size())) {
- return a[i];
- } else {
- return defaultVal;
- }
-}
-
-
-const AnyVal& AnyVal::get(int i) const {
- if (m_type != ARRAY) {
- throw WrongType(ARRAY, m_type);
- }
-
- const Array<AnyVal>& a = *(const Array<AnyVal>*)m_value;
-
- if ((i >= 0) && (i < a.size())) {
- return a[i];
- } else {
- throw IndexOutOfBounds(i, a.size());
- }
-}
-
-}
diff --git a/dep/g3dlite/source/AreaMemoryManager.cpp b/dep/g3dlite/source/AreaMemoryManager.cpp
index 00cb33dc91f..33e5099c380 100644
--- a/dep/g3dlite/source/AreaMemoryManager.cpp
+++ b/dep/g3dlite/source/AreaMemoryManager.cpp
@@ -43,7 +43,7 @@ bool AreaMemoryManager::isThreadsafe() const {
AreaMemoryManager::Ref AreaMemoryManager::create(size_t sizeHint) {
- return new AreaMemoryManager(sizeHint);
+ return shared_ptr<AreaMemoryManager>(new AreaMemoryManager(sizeHint));
}
@@ -80,7 +80,7 @@ void AreaMemoryManager::free(void* x) {
void AreaMemoryManager::deallocateAll() {
- m_bufferArray.deleteAll();
+ m_bufferArray.invokeDeleteOnAllElements();
m_bufferArray.clear();
}
diff --git a/dep/g3dlite/source/BinaryInput.cpp b/dep/g3dlite/source/BinaryInput.cpp
index 19ab2722c5c..c6eafa5ce09 100644
--- a/dep/g3dlite/source/BinaryInput.cpp
+++ b/dep/g3dlite/source/BinaryInput.cpp
@@ -1,11 +1,11 @@
/**
- @file BinaryInput.cpp
+ \file BinaryInput.cpp
- @author Morgan McGuire, graphics3d.com
- Copyright 2001-2007, Morgan McGuire. All rights reserved.
+ \author Morgan McGuire, graphics3d.com
+ Copyright 2001-2013, Morgan McGuire. All rights reserved.
- @created 2001-08-09
- @edited 2010-03-05
+ \created 2001-08-09
+ \edited 2013-01-03
<PRE>
@@ -40,154 +40,17 @@
#include "G3D/FileSystem.h"
#include <zlib.h>
#if _HAVE_ZIP /* G3DFIX: Use ZIP-library only if defined */
- #include "zip.h"
+#include "../../zip.lib/include/zip.h"
#endif
#include <cstring>
namespace G3D {
-void BinaryInput::readBool8(std::vector<bool>& out, int64 n) {
- out.resize((int)n);
- // std::vector optimizes bool in a way that prevents fast reading
- for (int64 i = 0; i < n ; ++i) {
- out[i] = readBool8();
- }
-}
-
-
-void BinaryInput::readBool8(Array<bool>& out, int64 n) {
- out.resize(n);
- readBool8(out.begin(), n);
-}
-
-
-#define IMPLEMENT_READER(ucase, lcase)\
-void BinaryInput::read##ucase(std::vector<lcase>& out, int64 n) {\
- out.resize(n);\
- read##ucase(&out[0], n);\
-}\
-\
-\
-void BinaryInput::read##ucase(Array<lcase>& out, int64 n) {\
- out.resize(n);\
- read##ucase(out.begin(), n);\
-}
-
-
-IMPLEMENT_READER(UInt8, uint8)
-IMPLEMENT_READER(Int8, int8)
-IMPLEMENT_READER(UInt16, uint16)
-IMPLEMENT_READER(Int16, int16)
-IMPLEMENT_READER(UInt32, uint32)
-IMPLEMENT_READER(Int32, int32)
-IMPLEMENT_READER(UInt64, uint64)
-IMPLEMENT_READER(Int64, int64)
-IMPLEMENT_READER(Float32, float32)
-IMPLEMENT_READER(Float64, float64)
-
-#undef IMPLEMENT_READER
-
-// Data structures that are one byte per element can be
-// directly copied, regardles of endian-ness.
-#define IMPLEMENT_READER(ucase, lcase)\
-void BinaryInput::read##ucase(lcase* out, int64 n) {\
- if (sizeof(lcase) == 1) {\
- readBytes(out, n);\
- } else {\
- for (int64 i = 0; i < n ; ++i) {\
- out[i] = read##ucase();\
- }\
- }\
-}
-
-IMPLEMENT_READER(Bool8, bool)
-IMPLEMENT_READER(UInt8, uint8)
-IMPLEMENT_READER(Int8, int8)
-
-#undef IMPLEMENT_READER
-
-
-#define IMPLEMENT_READER(ucase, lcase)\
-void BinaryInput::read##ucase(lcase* out, int64 n) {\
- if (m_swapBytes) {\
- for (int64 i = 0; i < n; ++i) {\
- out[i] = read##ucase();\
- }\
- } else {\
- readBytes(out, sizeof(lcase) * n);\
- }\
-}
-
-
-IMPLEMENT_READER(UInt16, uint16)
-IMPLEMENT_READER(Int16, int16)
-IMPLEMENT_READER(UInt32, uint32)
-IMPLEMENT_READER(Int32, int32)
-IMPLEMENT_READER(UInt64, uint64)
-IMPLEMENT_READER(Int64, int64)
-IMPLEMENT_READER(Float32, float32)
-IMPLEMENT_READER(Float64, float64)
-
-#undef IMPLEMENT_READER
-
-void BinaryInput::loadIntoMemory(int64 startPosition, int64 minLength) {
- // Load the next section of the file
- debugAssertM(m_filename != "<memory>", "Read past end of file.");
-
- int64 absPos = m_alreadyRead + m_pos;
-
- if (m_bufferLength < minLength) {
- // The current buffer isn't big enough to hold the chunk we want to read.
- // This happens if there was little memory available during the initial constructor
- // read but more memory has since been freed.
- m_bufferLength = minLength;
- debugAssert(m_freeBuffer);
- m_buffer = (uint8*)System::realloc(m_buffer, m_bufferLength);
- if (m_buffer == NULL) {
- throw "Tried to read a larger memory chunk than could fit in memory. (2)";
- }
- }
-
- m_alreadyRead = startPosition;
-
-# ifdef G3D_WIN32
- FILE* file = fopen(m_filename.c_str(), "rb");
- debugAssert(file);
- int ret = fseek(file, (off_t)m_alreadyRead, SEEK_SET);
- debugAssert(ret == 0);
- size_t toRead = (size_t)G3D::min(m_bufferLength, m_length - m_alreadyRead);
- ret = fread(m_buffer, 1, toRead, file);
- debugAssert(ret == toRead);
- fclose(file);
- file = NULL;
-
-# else
- FILE* file = fopen(m_filename.c_str(), "rb");
- debugAssert(file);
- int ret = fseeko(file, (off_t)m_alreadyRead, SEEK_SET);
- debugAssert(ret == 0);
- size_t toRead = (size_t)G3D::min<int64>(m_bufferLength, m_length - m_alreadyRead);
- ret = fread(m_buffer, 1, toRead, file);
- debugAssert((size_t)ret == (size_t)toRead);
- fclose(file);
- file = NULL;
-# endif
-
- m_pos = absPos - m_alreadyRead;
- debugAssert(m_pos >= 0);
-}
-
-
-
const bool BinaryInput::NO_COPY = false;
-
-static bool needSwapBytes(G3DEndian fileEndian) {
- return (fileEndian != System::machineEndian());
-}
/** Helper used by the constructors for decompression */
-static uint32 readUInt32(const uint8* data, bool swapBytes) {
+static uint32 readUInt32FromBuffer(const uint8* data, bool swapBytes) {
if (swapBytes) {
uint8 out[4];
out[0] = data[3];
@@ -201,12 +64,6 @@ static uint32 readUInt32(const uint8* data, bool swapBytes) {
}
-void BinaryInput::setEndian(G3DEndian e) {
- m_fileEndian = e;
- m_swapBytes = needSwapBytes(m_fileEndian);
-}
-
-
BinaryInput::BinaryInput(
const uint8* data,
int64 dataLen,
@@ -227,26 +84,26 @@ BinaryInput::BinaryInput(
if (compressed) {
// Read the decompressed size from the first 4 bytes
- m_length = G3D::readUInt32(data, m_swapBytes);
+ m_length = readUInt32FromBuffer(data, m_swapBytes);
debugAssert(m_freeBuffer);
m_buffer = (uint8*)System::alignedMalloc(m_length, 16);
- unsigned long L = m_length;
+ unsigned long L = (unsigned long)m_length;
// Decompress with zlib
- int64 result = uncompress(m_buffer, (unsigned long*)&L, data + 4, dataLen - 4);
+ int64 result = uncompress(m_buffer, &L, data + 4, (uLong)dataLen - 4);
m_length = L;
m_bufferLength = L;
debugAssert(result == Z_OK); (void)result;
} else {
- m_length = dataLen;
+ m_length = dataLen;
m_bufferLength = m_length;
if (! copyMemory) {
- debugAssert(!m_freeBuffer);
+ debugAssert(!m_freeBuffer);
m_buffer = const_cast<uint8*>(data);
} else {
- debugAssert(m_freeBuffer);
+ debugAssert(m_freeBuffer);
m_buffer = (uint8*)System::alignedMalloc(m_length, 16);
System::memcpy(m_buffer, data, dataLen);
}
@@ -254,10 +111,10 @@ BinaryInput::BinaryInput(
}
-BinaryInput::BinaryInput(
- const std::string& filename,
- G3DEndian fileEndian,
- bool compressed) :
+BinaryInput::BinaryInput
+(const std::string& filename,
+ G3DEndian fileEndian,
+ bool compressed) :
m_filename(filename),
m_bitPos(0),
m_bitString(0),
@@ -270,18 +127,16 @@ BinaryInput::BinaryInput(
m_freeBuffer(true) {
setEndian(fileEndian);
-
- // Update global file tracker
- _internal::currentFilesUsed.insert(m_filename);
-
#if _HAVE_ZIP /* G3DFIX: Use ZIP-library only if defined */
std::string zipfile;
if (FileSystem::inZipfile(m_filename, zipfile)) {
// Load from zipfile
-// zipRead(filename, v, s);
+ FileSystem::markFileUsed(m_filename);
+ FileSystem::markFileUsed(zipfile);
- std::string internalFile = m_filename.substr(zipfile.length() + 1);
+ // Zipfiles require Unix-style slashes
+ std::string internalFile = FilePath::canonicalize(m_filename.substr(zipfile.length() + 1));
struct zip* z = zip_open(zipfile.c_str(), ZIP_CHECKCONS, NULL);
{
struct zip_stat info;
@@ -291,29 +146,31 @@ BinaryInput::BinaryInput(
// sets machines up to use MMX, if they want
m_buffer = reinterpret_cast<uint8*>(System::alignedMalloc(m_length, 16));
struct zip_file* zf = zip_fopen( z, internalFile.c_str(), ZIP_FL_NOCASE );
- {
- int64 test = zip_fread( zf, m_buffer, m_length );
- debugAssertM(test == m_length,
+ if (zf == NULL) {
+ throw std::string("\"") + internalFile + "\" inside \"" + zipfile + "\" could not be opened.";
+ } else {
+ const int64 bytesRead = zip_fread( zf, m_buffer, m_length );
+ debugAssertM(bytesRead == m_length,
internalFile + " was corrupt because it unzipped to the wrong size.");
- (void)test;
+ (void)bytesRead;
+ zip_fclose( zf );
}
- zip_fclose( zf );
}
zip_close( z );
if (compressed) {
decompress();
}
+
m_freeBuffer = true;
return;
}
#endif
-
// Figure out how big the file is and verify that it exists.
m_length = FileSystem::size(m_filename);
// Read the file into memory
- FILE* file = fopen(m_filename.c_str(), "rb");
+ FILE* file = FileSystem::fopen(m_filename.c_str(), "rb");
if (! file || (m_length == -1)) {
throw format("File not found: \"%s\"", m_filename.c_str());
@@ -346,8 +203,8 @@ BinaryInput::BinaryInput(
}
debugAssert(m_buffer);
- fread(m_buffer, m_bufferLength, sizeof(int8), file);
- fclose(file);
+ (void)fread(m_buffer, m_bufferLength, sizeof(int8), file);
+ FileSystem::fclose(file);
file = NULL;
if (compressed) {
@@ -359,13 +216,36 @@ BinaryInput::BinaryInput(
}
}
+BinaryInput::~BinaryInput() {
+
+ if (m_freeBuffer) {
+ System::alignedFree(m_buffer);
+ }
+ m_buffer = NULL;
+}
+
+
+std::string BinaryInput::readFixedLengthString(int numBytes) {
+ Array<char> str;
+ str.resize(numBytes + 1);
+
+ // Ensure NULL termination
+ str.last() = '\0';
+
+ readBytes(str.getCArray(), numBytes);
+
+ // Copy up to the first NULL
+ return std::string(str.getCArray());
+}
+
+
void BinaryInput::decompress() {
// Decompress
// Use the existing buffer as the source, allocate
// a new buffer to use as the destination.
int64 tempLength = m_length;
- m_length = G3D::readUInt32(m_buffer, m_swapBytes);
+ m_length = readUInt32FromBuffer(m_buffer, m_swapBytes);
// The file couldn't have better than 500:1 compression
alwaysAssertM(m_length < m_bufferLength * 500, "Compressed file header is corrupted");
@@ -377,8 +257,8 @@ void BinaryInput::decompress() {
debugAssert(isValidHeapPointer(tempBuffer));
debugAssert(isValidHeapPointer(m_buffer));
- unsigned long L = m_length;
- int64 result = uncompress(m_buffer, &L, tempBuffer + 4, tempLength - 4);
+ unsigned long L = (unsigned long)m_length;
+ int64 result = (int64)uncompress(m_buffer, &L, tempBuffer + 4, (uLong)tempLength - 4);
m_length = L;
m_bufferLength = m_length;
@@ -389,6 +269,70 @@ void BinaryInput::decompress() {
}
+void BinaryInput::setEndian(G3DEndian e) {
+ m_fileEndian = e;
+ m_swapBytes = (m_fileEndian != System::machineEndian());
+}
+
+
+void BinaryInput::loadIntoMemory(int64 startPosition, int64 minLength) {
+ // Load the next section of the file
+ debugAssertM(m_filename != "<memory>", "Read past end of file.");
+
+ int64 absPos = m_alreadyRead + m_pos;
+
+ if (m_bufferLength < minLength) {
+ // The current buffer isn't big enough to hold the chunk we want to read.
+ // This happens if there was little memory available during the initial constructor
+ // read but more memory has since been freed.
+ m_bufferLength = minLength;
+ debugAssert(m_freeBuffer);
+ m_buffer = (uint8*)System::realloc(m_buffer, m_bufferLength);
+ if (m_buffer == NULL) {
+ throw "Tried to read a larger memory chunk than could fit in memory. (2)";
+ }
+ }
+
+ m_alreadyRead = startPosition;
+
+# ifdef G3D_WINDOWS
+ FILE* file = fopen(m_filename.c_str(), "rb");
+ debugAssert(file);
+ size_t ret = fseek(file, (off_t)m_alreadyRead, SEEK_SET);
+ debugAssert(ret == 0);
+ size_t toRead = (size_t)G3D::min(m_bufferLength, m_length - m_alreadyRead);
+ ret = fread(m_buffer, 1, toRead, file);
+ debugAssert(ret == toRead);
+ fclose(file);
+ file = NULL;
+
+# else
+ FILE* file = fopen(m_filename.c_str(), "rb");
+ debugAssert(file);
+ int ret = fseeko(file, (off_t)m_alreadyRead, SEEK_SET);
+ debugAssert(ret == 0);
+ size_t toRead = (size_t)G3D::min<int64>(m_bufferLength, m_length - m_alreadyRead);
+ ret = fread(m_buffer, 1, toRead, file);
+ debugAssert((size_t)ret == (size_t)toRead);
+ fclose(file);
+ file = NULL;
+# endif
+
+ m_pos = absPos - m_alreadyRead;
+ debugAssert(m_pos >= 0);
+}
+
+
+void BinaryInput::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);
+ }
+}
+
+
void BinaryInput::readBytes(void* bytes, int64 n) {
prepareToRead(n);
debugAssert(isValidPointer(bytes));
@@ -398,14 +342,6 @@ void BinaryInput::readBytes(void* bytes, int64 n) {
}
-BinaryInput::~BinaryInput() {
-
- if (m_freeBuffer) {
- System::alignedFree(m_buffer);
- }
- m_buffer = NULL;
-}
-
uint64 BinaryInput::readUInt64() {
prepareToRead(8);
@@ -429,52 +365,47 @@ uint64 BinaryInput::readUInt64() {
}
-std::string BinaryInput::readString(int64 n) {
- prepareToRead(n);
- debugAssertM((m_pos + n) <= m_length, "Read past end of file");
-
- char *s = (char*)System::alignedMalloc(n + 1, 16);
- assert(s != NULL);
+std::string BinaryInput::readString(int64 maxLength) {
+ prepareToRead(maxLength);
- memcpy(s, m_buffer + m_pos, n);
- // There may not be a null, so make sure
- // we add one.
- s[n] = '\0';
-
- std::string out = s;
- System::alignedFree(s);
- s = NULL;
+ int64 n = 0;
+ while ((m_buffer[m_pos + n] != '\0') && (n != maxLength)) {
+ ++n;
+ }
- m_pos += n;
+ std::string s((char*)(m_buffer + m_pos), n);
- return out;
+ m_pos += maxLength;
+ return s;
}
std::string BinaryInput::readString() {
- int64 n = 0;
-
- if ((m_pos + m_alreadyRead + n) < (m_length - 1)) {
- prepareToRead(1);
- }
+ prepareToRead(1);
- if ( ((m_pos + m_alreadyRead + n) < (m_length - 1)) &&
- (m_buffer[m_pos + n] != '\0')) {
+ int64 n = 0;
+ bool hasNull = true;
+ while(m_buffer[m_pos + n] != '\0') {
++n;
- while ( ((m_pos + m_alreadyRead + n) < (m_length - 1)) &&
- (m_buffer[m_pos + n] != '\0')) {
- prepareToRead(1);
- ++n;
+ if ((m_pos + m_alreadyRead + n) == m_length) {
+ hasNull = false;
+ break;
}
+
+ prepareToRead(n + 1);
}
- // Consume NULL
- ++n;
+ std::string s((char*)(m_buffer + m_pos), n);
+ m_pos += n;
- return readString(n);
+ if (hasNull) {
+ skip(1);
+ }
+
+ return s;
}
static bool isNewline(char c) {
@@ -482,32 +413,48 @@ static bool isNewline(char c) {
}
std::string BinaryInput::readStringNewline() {
+ prepareToRead(1);
+
int64 n = 0;
+ bool hasNull = true;
+ bool hasNewline = false;
- if ((m_pos + m_alreadyRead + n) < (m_length - 1)) {
- prepareToRead(1);
- }
+ while(m_buffer[m_pos + n] != '\0') {
+ if ((m_pos + m_alreadyRead + n + 1) == m_length) {
+ hasNull = false;
+ break;
+ }
- if ( ((m_pos + m_alreadyRead + n) < (m_length - 1)) &&
- ! isNewline(m_buffer[m_pos + n])) {
+ if (isNewline(m_buffer[m_pos + n])) {
+ hasNull = false;
+ hasNewline = true;
+ break;
+ }
++n;
- while ( ((m_pos + m_alreadyRead + n) < (m_length - 1)) &&
- ! isNewline(m_buffer[m_pos + n])) {
-
- prepareToRead(1);
- ++n;
- }
+ prepareToRead(n + 1);
}
- const std::string s = readString(n);
-
- // Consume the newline
- char firstNLChar = readUInt8();
+ std::string s((char*)(m_buffer + m_pos), n);
+ m_pos += n;
- // Consume the 2nd newline
- if (isNewline(m_buffer[m_pos + 1]) && (m_buffer[m_pos + 1] != firstNLChar)) {
- readUInt8();
+ if (hasNull) {
+ skip(1);
+ }
+
+ if (hasNewline) {
+ if ((m_pos + m_alreadyRead + 2) != m_length) {
+ prepareToRead(2);
+ if (m_buffer[m_pos] == '\r' && m_buffer[m_pos + 1] == '\n') {
+ skip(2);
+ } else if (m_buffer[m_pos] == '\n' && m_buffer[m_pos + 1] == '\r') {
+ skip(2);
+ } else {
+ skip(1);
+ }
+ } else {
+ skip(1);
+ }
}
return s;
@@ -516,7 +463,7 @@ std::string BinaryInput::readStringNewline() {
std::string BinaryInput::readStringEven() {
std::string x = readString();
- if (hasMore() && (G3D::isOdd(x.length() + 1))) {
+ if (hasMore() && (G3D::isOdd((int)x.length() + 1))) {
skip(1);
}
return x;
@@ -618,4 +565,90 @@ void BinaryInput::endBits() {
m_bitPos = 0;
}
+
+void BinaryInput::readBool8(std::vector<bool>& out, int64 n) {
+ out.resize((int)n);
+ // std::vector optimizes bool in a way that prevents fast reading
+ for (int64 i = 0; i < n ; ++i) {
+ out[i] = readBool8();
+ }
+}
+
+
+void BinaryInput::readBool8(Array<bool>& out, int64 n) {
+ out.resize(n);
+ readBool8(out.begin(), n);
}
+
+
+#define IMPLEMENT_READER(ucase, lcase)\
+void BinaryInput::read##ucase(std::vector<lcase>& out, int64 n) {\
+ out.resize(n);\
+ read##ucase(&out[0], n);\
+}\
+\
+\
+void BinaryInput::read##ucase(Array<lcase>& out, int64 n) {\
+ out.resize(n);\
+ read##ucase(out.begin(), n);\
+}
+
+
+IMPLEMENT_READER(UInt8, uint8)
+IMPLEMENT_READER(Int8, int8)
+IMPLEMENT_READER(UInt16, uint16)
+IMPLEMENT_READER(Int16, int16)
+IMPLEMENT_READER(UInt32, uint32)
+IMPLEMENT_READER(Int32, int32)
+IMPLEMENT_READER(UInt64, uint64)
+IMPLEMENT_READER(Int64, int64)
+IMPLEMENT_READER(Float32, float32)
+IMPLEMENT_READER(Float64, float64)
+
+#undef IMPLEMENT_READER
+
+// Data structures that are one byte per element can be
+// directly copied, regardles of endian-ness.
+#define IMPLEMENT_READER(ucase, lcase)\
+void BinaryInput::read##ucase(lcase* out, int64 n) {\
+ if (sizeof(lcase) == 1) {\
+ readBytes(out, n);\
+ } else {\
+ for (int64 i = 0; i < n ; ++i) {\
+ out[i] = read##ucase();\
+ }\
+ }\
+}
+
+IMPLEMENT_READER(Bool8, bool)
+IMPLEMENT_READER(UInt8, uint8)
+IMPLEMENT_READER(Int8, int8)
+
+#undef IMPLEMENT_READER
+
+
+#define IMPLEMENT_READER(ucase, lcase)\
+void BinaryInput::read##ucase(lcase* out, int64 n) {\
+ if (m_swapBytes) {\
+ for (int64 i = 0; i < n; ++i) {\
+ out[i] = read##ucase();\
+ }\
+ } else {\
+ readBytes(out, sizeof(lcase) * n);\
+ }\
+}
+
+
+IMPLEMENT_READER(UInt16, uint16)
+IMPLEMENT_READER(Int16, int16)
+IMPLEMENT_READER(UInt32, uint32)
+IMPLEMENT_READER(Int32, int32)
+IMPLEMENT_READER(UInt64, uint64)
+IMPLEMENT_READER(Int64, int64)
+IMPLEMENT_READER(Float32, float32)
+IMPLEMENT_READER(Float64, float64)
+
+#undef IMPLEMENT_READER
+
+} // namespace G3D
+
diff --git a/dep/g3dlite/source/BinaryOutput.cpp b/dep/g3dlite/source/BinaryOutput.cpp
index 81fa9822206..b174751c8c3 100644
--- a/dep/g3dlite/source/BinaryOutput.cpp
+++ b/dep/g3dlite/source/BinaryOutput.cpp
@@ -2,7 +2,7 @@
@file BinaryOutput.cpp
@author Morgan McGuire, http://graphics.cs.williams.edu
- Copyright 2002-2010, Morgan McGuire, All rights reserved.
+ Copyright 2002-2011, Morgan McGuire, All rights reserved.
@created 2002-02-20
@edited 2010-03-17
@@ -22,10 +22,6 @@
# include <errno.h>
#endif
-#ifdef __CYGWIN__
-# include <errno.h>
-#endif
-
// Largest memory buffer that the system will use for writing to
// disk. After this (or if the system runs out of memory)
// chunks of the file will be dumped to disk.
@@ -121,10 +117,11 @@ void BinaryOutput::reallocBuffer(size_t bytes, size_t oldBufferLen) {
uint8* newBuffer = NULL;
if ((m_filename == "<memory>") || (newBufferLen < MAX_BINARYOUTPUT_BUFFER_SIZE)) {
- // We're either writing to memory (in which case we *have* to try and allocate)
- // or we've been asked to allocate a reasonable size buffer.
+ // We're either writing to memory (in which case we *have* to
+ // try and allocate) or we've been asked to allocate a
+ // reasonable size buffer.
- //debugPrintf(" realloc(%d)\n", newBufferLen);
+ // debugPrintf(" realloc(%d)\n", newBufferLen);
newBuffer = (uint8*)System::realloc(m_buffer, newBufferLen);
if (newBuffer != NULL) {
m_maxBufferLen = newBufferLen;
@@ -134,9 +131,11 @@ void BinaryOutput::reallocBuffer(size_t bytes, size_t oldBufferLen) {
if ((newBuffer == NULL) && (bytes > 0)) {
// Realloc failed; we're probably out of memory. Back out
// the entire call and try to dump some data to disk.
+ alwaysAssertM(m_filename != "<memory>", "Realloc failed while writing to memory.");
m_bufferLen = oldBufferLen;
reserveBytesWhenOutOfMemory(bytes);
} else {
+ // Realloc succeeded
m_buffer = newBuffer;
debugAssert(isValidHeapPointer(m_buffer));
}
@@ -152,7 +151,7 @@ void BinaryOutput::reserveBytesWhenOutOfMemory(size_t bytes) {
// Dump the contents to disk. In order to enable seeking backwards,
// we keep the last 10 MB in memory.
- int writeBytes = m_bufferLen - 10 * 1024 * 1024;
+ size_t writeBytes = m_bufferLen - 10 * 1024 * 1024;
if (writeBytes < m_bufferLen / 3) {
// We're going to write less than 1/3 of the file;
@@ -164,11 +163,12 @@ void BinaryOutput::reserveBytesWhenOutOfMemory(size_t bytes) {
//debugPrintf("Writing %d bytes to disk\n", writeBytes);
const char* mode = (m_alreadyWritten > 0) ? "ab" : "wb";
+ alwaysAssertM(m_filename != "<memory>", "Writing memory file");
FILE* file = FileSystem::fopen(m_filename.c_str(), mode);
debugAssert(file);
size_t count = fwrite(m_buffer, 1, writeBytes, file);
- debugAssert((int)count == writeBytes); (void)count;
+ debugAssert(count == writeBytes); (void)count;
fclose(file);
file = NULL;
@@ -181,7 +181,7 @@ void BinaryOutput::reserveBytesWhenOutOfMemory(size_t bytes) {
debugAssert(m_bufferLen < m_maxBufferLen);
debugAssert(m_bufferLen >= 0);
debugAssert(m_pos >= 0);
- debugAssert(m_pos <= m_bufferLen);
+ debugAssert(m_pos <= (int64)m_bufferLen);
// Shift the unwritten data back appropriately in the buffer.
debugAssert(isValidHeapPointer(m_buffer));
@@ -273,45 +273,49 @@ bool BinaryOutput::ok() const {
}
-void BinaryOutput::compress() {
+void BinaryOutput::compress(int level) {
if (m_alreadyWritten > 0) {
throw "Cannot compress huge files (part of this file has already been written to disk).";
}
+ debugAssertM(! m_committed, "Cannot compress after committing.");
+ alwaysAssertM(m_bufferLen < 0xFFFFFFFF, "Compress only works for 32-bit files.");
+
+ // This is the worst-case size, as mandated by zlib
+ unsigned long compressedSize = iCeil(m_bufferLen * 1.001) + 12;
+
+ // Save the old buffer and reallocate to the worst-case size
+ const uint8* src = m_buffer;
+ const uint32 srcSize = (uint32)m_bufferLen;
+
+ // add space for the 4-byte header
+ m_maxBufferLen = compressedSize + 4;
+ m_buffer = (uint8*)System::malloc(m_maxBufferLen);
+
+ // Write the header containing the old buffer size, which is needed for decompression
+ {
+ const uint8* convert = (const uint8*)&srcSize;
+ if (m_swapBytes) {
+ m_buffer[0] = convert[3];
+ m_buffer[1] = convert[2];
+ m_buffer[2] = convert[1];
+ m_buffer[3] = convert[0];
+ } else {
+ m_buffer[0] = convert[0];
+ m_buffer[1] = convert[1];
+ m_buffer[2] = convert[2];
+ m_buffer[3] = convert[3];
+ }
+ }
- // Old buffer size
- int L = m_bufferLen;
- uint8* convert = (uint8*)&L;
-
- // Zlib requires the output buffer to be this big
- unsigned long newSize = iCeil(m_bufferLen * 1.01) + 12;
- uint8* temp = (uint8*)System::malloc(newSize);
- int result = compress2(temp, &newSize, m_buffer, m_bufferLen, 9);
+ // Compress and write after the header
+ int result = compress2(m_buffer + 4, &compressedSize, src, srcSize, iClamp(level, 0, 9));
debugAssert(result == Z_OK); (void)result;
-
- // Write the header
- if (m_swapBytes) {
- m_buffer[0] = convert[3];
- m_buffer[1] = convert[2];
- m_buffer[2] = convert[1];
- m_buffer[3] = convert[0];
- } else {
- m_buffer[0] = convert[0];
- m_buffer[1] = convert[1];
- m_buffer[2] = convert[2];
- m_buffer[3] = convert[3];
- }
-
- // Write the data
- if ((int64)newSize + 4 > (int64)m_maxBufferLen) {
- m_maxBufferLen = newSize + 4;
- m_buffer = (uint8*)System::realloc(m_buffer, m_maxBufferLen);
- }
- m_bufferLen = newSize + 4;
- System::memcpy(m_buffer + 4, temp, newSize);
+ m_bufferLen = compressedSize + 4;
m_pos = m_bufferLen;
- System::free(temp);
+ // Free the old data
+ System::free((void*)src);
}
@@ -320,6 +324,10 @@ void BinaryOutput::commit(bool flush) {
m_committed = true;
debugAssertM(m_beginEndBits == 0, "Missing endBits before commit");
+ if (m_filename == "<memory>") {
+ return;
+ }
+
// Make sure the directory exists.
std::string root, base, ext, path;
Array<std::string> pathArray;
@@ -332,6 +340,7 @@ void BinaryOutput::commit(bool flush) {
const char* mode = (m_alreadyWritten > 0) ? "ab" : "wb";
+ alwaysAssertM(m_filename != "<memory>", "Writing to memory file");
FILE* file = FileSystem::fopen(m_filename.c_str(), mode);
if (! file) {
@@ -345,7 +354,7 @@ void BinaryOutput::commit(bool flush) {
if (m_buffer != NULL) {
m_alreadyWritten += m_bufferLen;
- int success = fwrite(m_buffer, m_bufferLen, 1, file);
+ size_t success = fwrite(m_buffer, m_bufferLen, 1, file);
(void)success;
debugAssertM(success == 1, std::string("Could not write to '") + m_filename + "'");
}
@@ -427,7 +436,7 @@ void BinaryOutput::writeUInt64(uint64 u) {
void BinaryOutput::writeString(const char* s) {
// +1 is because strlen doesn't count the null
- int len = strlen(s) + 1;
+ size_t len = strlen(s) + 1;
debugAssert(m_beginEndBits == 0);
reserveBytes(len);
@@ -438,7 +447,7 @@ void BinaryOutput::writeString(const char* s) {
void BinaryOutput::writeStringEven(const char* s) {
// +1 is because strlen doesn't count the null
- int len = strlen(s) + 1;
+ size_t len = strlen(s) + 1;
reserveBytes(len);
System::memcpy(m_buffer + m_pos, s, len);
@@ -452,8 +461,14 @@ void BinaryOutput::writeStringEven(const char* s) {
void BinaryOutput::writeString32(const char* s) {
- writeUInt32(strlen(s) + 1);
- writeString(s);
+ // Write the NULL and count it
+ size_t len = strlen(s) + 1;
+ writeUInt32((uint32)len);
+
+ debugAssert(m_beginEndBits == 0);
+ reserveBytes(len);
+ System::memcpy(m_buffer + m_pos, s, len);
+ m_pos += len;
}
diff --git a/dep/g3dlite/source/Box.cpp b/dep/g3dlite/source/Box.cpp
index f7c112ae3a5..3ee3dc04013 100644
--- a/dep/g3dlite/source/Box.cpp
+++ b/dep/g3dlite/source/Box.cpp
@@ -1,11 +1,11 @@
/**
- @file Box.cpp
+ \file G3D.lib/source/Box.cpp
Box class
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
+ \maintainer Morgan McGuire, http://graphics.cs.williams.edu, Michael Mara
- @created 2001-06-02
- @edited 2006-02-05
+ \created 2001-06-02
+ \edited 2013-04-13
*/
#include "G3D/Box.h"
@@ -13,126 +13,207 @@
#include "G3D/Plane.h"
#include "G3D/AABox.h"
#include "G3D/CoordinateFrame.h"
+#include "G3D/vectorMath.h"
+#include "G3D/Any.h"
namespace G3D {
-/**
- Sets a field on four vertices. Used by the constructor.
- */
-#define setMany(i0, i1, i2, i3, field, extreme) \
- _corner[i0].field = _corner[i1].field = \
- _corner[i2].field = _corner[i3].field = \
- (extreme).field
-
-Box::Box() {
+Box::Box() : _area(0), _volume(0) {
+}
+
+
+Box::Box
+ (const Point3& min,
+ const Point3& max) {
+ init(min.min(max), min.max(max));
+}
+
+
+Box::Box(const Point3& min) {
+ init(min, min);
+}
+
+
+Box::Box
+ (const Point3& min,
+ const Point3& max,
+ const CFrame& c) {
+ init(min.min(max), min.max(max));
+ *this = c.toWorldSpace(*this);
}
Box::Box(const AABox& b) {
+ debugAssert(! b.isEmpty());
init(b.low(), b.high());
}
-Box::Box(class BinaryInput& b) {
- deserialize(b);
+
+Box::Box(BinaryInput& b) {
+ deserialize(b);
}
-void Box::serialize(class BinaryOutput& b) const {
- int i;
- for (i = 0; i < 8; ++i) {
- _corner[i].serialize(b);
- }
+Box::Box(const Any& a) {
+ if (a.name() == "Box::inf") {
+ *this = Box::inf();
+ } else {
+ a.verifyName("Box", "AABox", "Point3");
+
+ if (a.name() == "Point3") {
+ *this = Box(Point3(a));
+ } else if (a.size() == 1) {
+ // Single point
+ *this = Box(Point3(a[0]));
+ } else if (a.size() == 2) {
+ *this = Box(Point3(a[0]), Point3(a[1]));
+ } else {
+ // Oriented box
+ a.verifySize(2);
+ a.verifyName("Box");
+ *this = Box(Point3(a[0]), Point3(a[1]), CFrame(a[2]));
+ }
+ }
+}
+
- // Other state can be reconstructed
+Any Box::toAny() const {
+ if (! isFinite()) {
+ return Any(Any::ARRAY, "Box::inf");
+ } else {
+ CFrame c;
+ getLocalFrame(c);
+ if (c.rotation == Matrix3::identity()) {
+ // Aligned box
+ AABox b;
+ getBounds(b);
+ return b.toAny();
+ } else {
+ // Oriented box
+ Any a(Any::ARRAY, "Box");
+
+ AABox b;
+ c.toObjectSpace(*this).getBounds(b);
+ a.append(b.low(), b.high(), c);
+ return a;
+ }
+ }
}
-void Box::deserialize(class BinaryInput& b) {
- int i;
+Box Box::operator*(float f) const {
+ Box b;
+
+ for (int i = 0; i < 3; ++i) {
+ b._edgeVector[i] = _edgeVector[i] * f;
+ b._center = _center * f;
+ b._area = _area * square(f * f);
+ b._volume = _area * (f * f * f);
+ }
- _center = Vector3::zero();
- for (i = 0; i < 8; ++i) {
- _corner[i].deserialize(b);
- _center += _corner[i];
- }
+ return b;
+}
- _center = _center / 8;
-
- // Reconstruct other state from the corners
- _axis[0] = _corner[5] - _corner[4];
- _axis[1] = _corner[7] - _corner[4];
- _axis[2] = _corner[0] - _corner[4];
+void Box::serialize(BinaryOutput& b) const {
+ int i;
for (i = 0; i < 3; ++i) {
- _extent[i] = _axis[i].magnitude();
- _axis[i] /= _extent[i];
+ _edgeVector[i].serialize(b);
}
+ _center.serialize(b);
- _volume = _extent.x * _extent.y * _extent.z;
-
- _area = 2 *
- (_extent.x * _extent.y +
- _extent.y * _extent.z +
- _extent.z * _extent.x);
+ // Other state can be reconstructed
}
-Box::Box(
- const Vector3& min,
- const Vector3& max) {
+void Box::deserialize(class BinaryInput& b) {
+ int i;
+ for (i = 0; i < 3; ++i) {
+ _edgeVector[i].deserialize(b);
+ }
+ _center.deserialize(b);
- init(min.min(max), min.max(max));
+ float extent0 = extent(0);
+ float extent1 = extent(1);
+ float extent2 = extent(2);
+ _volume = extent0 * extent1 * extent2;
+ _area = 2 *
+ (extent0 * extent1 +
+ extent1 * extent2 +
+ extent2 * extent0);
}
-void Box::init(
- const Vector3& min,
- const Vector3& max) {
+
+void Box::init
+ (const Point3& min,
+ const Point3& max) {
debugAssert(
(min.x <= max.x) &&
(min.y <= max.y) &&
(min.z <= max.z));
- setMany(0, 1, 2, 3, z, max);
- setMany(4, 5, 6, 7, z, min);
-
- setMany(1, 2, 5, 6, x, max);
- setMany(0, 3, 4, 7, x, min);
-
- setMany(3, 2, 6, 7, y, max);
- setMany(0, 1, 5, 4, y, min);
+ _center = (max + min) * 0.5f;
- _extent = max - min;
+ Vector3 bounds = Vector3(max.x - min.x, max.y - min.y, max.z - min.z);
+ _edgeVector[0] = Vector3(bounds.x, 0, 0);
+ _edgeVector[1] = Vector3(0, bounds.y, 0);
+ _edgeVector[2] = Vector3(0, 0, bounds.z);
+ bool finiteExtent = true;
+
+ for (int i = 0; i < 3; ++i) {
+ if (! G3D::isFinite(extent(i))) {
+ finiteExtent = false;
+ // If the extent is infinite along an axis, make the center zero to avoid NaNs
+ _center[i] = 0.0f;
+ }
+ }
- _axis[0] = Vector3::unitX();
- _axis[1] = Vector3::unitY();
- _axis[2] = Vector3::unitZ();
- if (_extent.isFinite()) {
- _volume = _extent.x * _extent.y * _extent.z;
+ if (finiteExtent) {
+ _volume = bounds.x * bounds.y * bounds.z;
} else {
_volume = G3D::finf();
}
- debugAssert(! isNaN(_extent.x));
+ debugAssert(! _edgeVector[0].isNaN());
_area = 2 *
- (_extent.x * _extent.y +
- _extent.y * _extent.z +
- _extent.z * _extent.x);
+ (bounds.x * bounds.y +
+ bounds.y * bounds.z +
+ bounds.z * bounds.x);
+}
- _center = (max + min) * 0.5f;
- // If the extent is infinite along an axis, make the center zero to avoid NaNs
- for (int i = 0; i < 3; ++i) {
- if (! G3D::isFinite(_extent[i])) {
- _center[i] = 0.0f;
- }
+Vector3 Box::corner(int i) const{
+ debugAssert(i < 8);
+ // The corner forms a bit mask (xyz), where a one indicates we should
+ // add half of the corresponding edge vector from center, and a zero indicates
+ // we should subtract it. Note:
+ // 1 = 001
+ // 2 = 010
+ // 4 = 100
+ //
+ // The following bit-hacky code shows this directly:
+ // return _center + ((_edgeVector[0] * ((i&1) - 0.5) +
+ // _edgeVector[1] * (((i>>1)&1) - 0.5) +
+ // _edgeVector[2] * (((i>>2)&1) - 0.5)));
+ // This method is implemented as a swtich statement due to being marginally faster than the bit-hack method
+ // Also, the _center + 0.5f * (...) is repeated every time for similarly speed-based reasons.
+ switch(i) {
+ case 0: return _center + (0.5f * (-_edgeVector[0] - _edgeVector[1] - _edgeVector[2]));
+ case 1: return _center + (0.5f * ( _edgeVector[0] - _edgeVector[1] - _edgeVector[2]));
+ case 2: return _center + (0.5f * (-_edgeVector[0] + _edgeVector[1] - _edgeVector[2]));
+ case 3: return _center + (0.5f * ( _edgeVector[0] + _edgeVector[1] - _edgeVector[2]));
+ case 4: return _center + (0.5f * (-_edgeVector[0] - _edgeVector[1] + _edgeVector[2]));
+ case 5: return _center + (0.5f * ( _edgeVector[0] - _edgeVector[1] + _edgeVector[2]));
+ case 6: return _center + (0.5f * (-_edgeVector[0] + _edgeVector[1] + _edgeVector[2]));
+ default: return _center + (0.5f * ( _edgeVector[0] + _edgeVector[1] + _edgeVector[2]));//case 7
}
+
}
-
float Box::volume() const {
return _volume;
}
@@ -144,11 +225,14 @@ float Box::area() const {
void Box::getLocalFrame(CoordinateFrame& frame) const {
+ const Vector3& axis0 = axis(0);
+ const Vector3& axis1 = axis(1);
+ const Vector3& axis2 = axis(2);
frame.rotation = Matrix3(
- _axis[0][0], _axis[1][0], _axis[2][0],
- _axis[0][1], _axis[1][1], _axis[2][1],
- _axis[0][2], _axis[1][2], _axis[2][2]);
+ axis0[0], axis1[0], axis2[0],
+ axis0[1], axis1[1], axis2[1],
+ axis0[2], axis1[2], axis2[2]);
frame.translation = _center;
}
@@ -161,30 +245,30 @@ CoordinateFrame Box::localFrame() const {
}
-void Box::getFaceCorners(int f, Vector3& v0, Vector3& v1, Vector3& v2, Vector3& v3) const {
+void Box::getFaceCorners(int f, Point3& v0, Point3& v1, Point3& v2, Point3& v3) const {
switch (f) {
case 0:
- v0 = _corner[0]; v1 = _corner[1]; v2 = _corner[2]; v3 = _corner[3];
+ v0 = corner(0); v1 = corner(2); v2 = corner(3); v3 = corner(1);
break;
case 1:
- v0 = _corner[1]; v1 = _corner[5]; v2 = _corner[6]; v3 = _corner[2];
+ v0 = corner(1); v1 = corner(3); v2 = corner(7); v3 = corner(5);
break;
case 2:
- v0 = _corner[7]; v1 = _corner[6]; v2 = _corner[5]; v3 = _corner[4];
+ v0 = corner(6); v1 = corner(4); v2 = corner(5); v3 = corner(7);
break;
case 3:
- v0 = _corner[2]; v1 = _corner[6]; v2 = _corner[7]; v3 = _corner[3];
+ v0 = corner(3); v1 = corner(2); v2 = corner(6); v3 = corner(7);
break;
case 4:
- v0 = _corner[3]; v1 = _corner[7]; v2 = _corner[4]; v3 = _corner[0];
+ v0 = corner(2); v1 = corner(0); v2 = corner(4); v3 = corner(6);
break;
case 5:
- v0 = _corner[1]; v1 = _corner[0]; v2 = _corner[4]; v3 = _corner[5];
+ v0 = corner(1); v1 = corner(5); v2 = corner(4); v3 = corner(0);
break;
default:
@@ -196,8 +280,8 @@ void Box::getFaceCorners(int f, Vector3& v0, Vector3& v1, Vector3& v2, Vector3&
int Box::dummy = 0;
-bool Box::culledBy(
- const Array<Plane>& plane,
+bool Box::culledBy
+ (const Array<Plane>& plane,
int& cullingPlane,
const uint32 _inMask,
uint32& childMask) const {
@@ -208,13 +292,11 @@ bool Box::culledBy(
childMask = 0;
// See if there is one plane for which all of the
- // vertices are in the negative half space.
+ // vertices are in the negative half space.
for (int p = 0; p < plane.size(); ++p) {
- // Only test planes that are not masked
- if ((inMask & 1) != 0) {
-
- Vector3 corner;
+ // Only test planes that are not masked
+ if ((inMask & 1) != 0) {
int numContained = 0;
int v = 0;
@@ -222,93 +304,94 @@ bool Box::culledBy(
// We can early-out only if we have found one point on each
// side of the plane (i.e. if we are straddling). That
// occurs when (numContained < v) && (numContained > 0)
- for (v = 0; (v < 8) && ((numContained == v) || (numContained == 0)); ++v) {
- if (plane[p].halfSpaceContains(_corner[v])) {
+ for (v = 0; (v < 8) && ((numContained == v) || (numContained == 0)); ++v) {
+ if (plane[p].halfSpaceContains(corner(v))) {
++numContained;
}
- }
+ }
- if (numContained == 0) {
- // Plane p culled the box
- cullingPlane = p;
+ if (numContained == 0) {
+ // Plane p culled the box
+ cullingPlane = p;
// The caller should not recurse into the children,
// since the parent is culled. If they do recurse,
// make them only test against this one plane, which
// will immediately cull the volume.
childMask = 1 << p;
- return true;
+ return true;
} else if (numContained < v) {
// The bounding volume straddled the plane; we have
// to keep testing against this plane
childMask |= (1 << p);
}
- }
+ }
// Move on to the next bit.
- inMask = inMask >> 1;
+ inMask = inMask >> 1;
}
// None of the planes could cull this box
- cullingPlane = -1;
+ cullingPlane = -1;
return false;
}
-bool Box::culledBy(
- const Array<Plane>& plane,
- int& cullingPlane,
- const uint32 _inMask) const {
+bool Box::culledBy
+ (const Array<Plane>& plane,
+ int& cullingPlane,
+ const uint32 _inMask) const {
- uint32 inMask = _inMask;
- assert(plane.size() < 31);
+ uint32 inMask = _inMask;
+ assert(plane.size() < 31);
// See if there is one plane for which all of the
- // vertices are in the negative half space.
+ // vertices are in the negative half space.
for (int p = 0; p < plane.size(); ++p) {
- // Only test planes that are not masked
- if ((inMask & 1) != 0) {
-
- bool culled = true;
+ // Only test planes that are not masked
+ if ((inMask & 1) != 0) {
+
+ bool culled = true;
int v;
- // Assume this plane culls all points. See if there is a point
- // not culled by the plane... early out when at least one point
+ // Assume this plane culls all points. See if there is a point
+ // not culled by the plane... early out when at least one point
// is in the positive half space.
- for (v = 0; (v < 8) && culled; ++v) {
+ for (v = 0; (v < 8) && culled; ++v) {
culled = ! plane[p].halfSpaceContains(corner(v));
- }
+ }
- if (culled) {
- // Plane p culled the box
- cullingPlane = p;
+ if (culled) {
+ // Plane p culled the box
+ cullingPlane = p;
- return true;
+ return true;
}
- }
+ }
// Move on to the next bit.
- inMask = inMask >> 1;
+ inMask = inMask >> 1;
}
// None of the planes could cull this box
- cullingPlane = -1;
+ cullingPlane = -1;
return false;
}
-bool Box::contains(
- const Vector3& point) const {
+bool Box::contains
+ (const Point3& point) const {
// Form axes from three edges, transform the point into that
// space, and perform 3 interval tests
-
- Vector3 u = _corner[4] - _corner[0];
- Vector3 v = _corner[3] - _corner[0];
- Vector3 w = _corner[1] - _corner[0];
+ // TODO: Write in a more intuitive way. I left it as it was before after figuring it out, but
+ // this should make no sense to someone who is just starting to read this code.
+ const Vector3& u = _edgeVector[2];
+ const Vector3& v = _edgeVector[1];
+ const Vector3& w = _edgeVector[0];
Matrix3 M = Matrix3(u.x, v.x, w.x,
u.y, v.y, w.y,
@@ -316,7 +399,7 @@ bool Box::contains(
// M^-1 * (point - _corner[0]) = point in unit cube's object space
// compute the inverse of M
- Vector3 osPoint = M.inverse() * (point - _corner[0]);
+ Vector3 osPoint = M.inverse() * (point - corner(0));
return
(osPoint.x >= 0) &&
@@ -327,13 +410,13 @@ bool Box::contains(
(osPoint.z <= 1);
}
-#undef setMany
+
void Box::getRandomSurfacePoint(Vector3& P, Vector3& N) const {
- float aXY = _extent.x * _extent.y;
- float aYZ = _extent.y * _extent.z;
- float aZX = _extent.z * _extent.x;
+ float aXY = extent(0) * extent(1);
+ float aYZ = extent(1) * extent(2);
+ float aZX = extent(2) * extent(0);
float r = (float)uniformRandom(0, aXY + aYZ + aZX);
@@ -343,20 +426,20 @@ void Box::getRandomSurfacePoint(Vector3& P, Vector3& N) const {
// The probability of choosing a given face is proportional to
// its area.
if (r < aXY) {
- P = _axis[0] * (float)uniformRandom(-0.5, 0.5) * _extent.x +
- _axis[1] * (float)uniformRandom(-0.5, 0.5) * _extent.y +
- _center + _axis[2] * d * _extent.z * 0.5f;
- N = _axis[2] * d;
+ P = _edgeVector[0] * (float)uniformRandom(-0.5, 0.5) +
+ _edgeVector[1] * (float)uniformRandom(-0.5, 0.5) +
+ _center + _edgeVector[2] * d * 0.5f;
+ N = axis(2) * d;
} else if (r < aYZ) {
- P = _axis[1] * (float)uniformRandom(-0.5, 0.5) * _extent.y +
- _axis[2] * (float)uniformRandom(-0.5, 0.5) * _extent.z +
- _center + _axis[0] * d * _extent.x * 0.5f;
- N = _axis[0] * d;
+ P = _edgeVector[1] * (float)uniformRandom(-0.5, 0.5) +
+ _edgeVector[2] * (float)uniformRandom(-0.5, 0.5) +
+ _center + _edgeVector[0] * d * 0.5f;
+ N = axis(0) * d;
} else {
- P = _axis[2] * (float)uniformRandom(-0.5, 0.5) * _extent.z +
- _axis[0] *(float) uniformRandom(-0.5, 0.5) * _extent.x +
- _center + _axis[1] * d * _extent.y * 0.5f;
- N = _axis[1] * d;
+ P = _edgeVector[2] * (float)uniformRandom(-0.5, 0.5) +
+ _edgeVector[0] *(float) uniformRandom(-0.5, 0.5) +
+ _center + _edgeVector[1] * d * 0.5f;
+ N = axis(1) * d;
}
}
@@ -365,28 +448,25 @@ Vector3 Box::randomInteriorPoint() const {
Vector3 sum = _center;
for (int a = 0; a < 3; ++a) {
- sum += _axis[a] * (float)uniformRandom(-0.5, 0.5) * _extent[a];
+ sum += _edgeVector[a] * (float)uniformRandom(-0.5, 0.5);
}
return sum;
}
+
Box Box::inf() {
return Box(-Vector3::inf(), Vector3::inf());
}
-void Box::getBounds(class AABox& aabb) const {
-
- Vector3 lo = _corner[0];
- Vector3 hi = lo;
- for (int v = 1; v < 8; ++v) {
- const Vector3& C = _corner[v];
- lo = lo.min(C);
- hi = hi.max(C);
+void Box::getBounds(AABox& aabb) const {
+ debugAssert(! _edgeVector[0].isNaN());
+ debugAssert(! _center.isNaN());
+ aabb = AABox::empty();
+ for (int i = 0; i < 8; ++i) {
+ aabb.merge(corner(i));
}
-
- aabb = AABox(lo, hi);
}
diff --git a/dep/g3dlite/source/BumpMapPreprocess.cpp b/dep/g3dlite/source/BumpMapPreprocess.cpp
index 20281caf8cb..df5a23c13a6 100644
--- a/dep/g3dlite/source/BumpMapPreprocess.cpp
+++ b/dep/g3dlite/source/BumpMapPreprocess.cpp
@@ -6,7 +6,7 @@
\created 2010-01-28
\edited 2010-01-28
- Copyright 2000-2010, Morgan McGuire.
+ Copyright 2000-2012, Morgan McGuire.
All rights reserved.
*/
#include "G3D/BumpMapPreprocess.h"
@@ -17,7 +17,7 @@ namespace G3D {
BumpMapPreprocess::BumpMapPreprocess(const Any& any) {
*this = BumpMapPreprocess();
- for (Any::AnyTable::Iterator it = any.table().begin(); it.hasMore(); ++it) {
+ for (Any::AnyTable::Iterator it = any.table().begin(); it.isValid(); ++it) {
const std::string& key = toLower(it->key);
if (key == "lowpassfilter") {
lowPassFilter = it->value;
@@ -32,7 +32,7 @@ BumpMapPreprocess::BumpMapPreprocess(const Any& any) {
}
-BumpMapPreprocess::operator Any() const {
+Any BumpMapPreprocess::toAny() const {
Any any(Any::TABLE, "BumpMapPreprocess");
any["lowPassFilter"] = lowPassFilter;
any["zExtentPixels"] = zExtentPixels;
diff --git a/dep/g3dlite/source/Capsule.cpp b/dep/g3dlite/source/Capsule.cpp
index 2ad3891c960..14df8d31b9e 100644
--- a/dep/g3dlite/source/Capsule.cpp
+++ b/dep/g3dlite/source/Capsule.cpp
@@ -22,7 +22,7 @@
namespace G3D {
Capsule::Capsule(class BinaryInput& b) {
- deserialize(b);
+ deserialize(b);
}
@@ -31,47 +31,47 @@ Capsule::Capsule() {
Capsule::Capsule(const Vector3& _p1, const Vector3& _p2, float _r)
- : p1(_p1), p2(_p2), _radius(_r) {
+ : p1(_p1), p2(_p2), _radius(_r) {
}
void Capsule::serialize(class BinaryOutput& b) const {
- p1.serialize(b);
- p2.serialize(b);
- b.writeFloat64(_radius);
+ p1.serialize(b);
+ p2.serialize(b);
+ b.writeFloat64(_radius);
}
void Capsule::deserialize(class BinaryInput& b) {
- p1.deserialize(b);
- p2.deserialize(b);
- _radius = b.readFloat64();
+ p1.deserialize(b);
+ p2.deserialize(b);
+ _radius = (float)b.readFloat64();
}
Line Capsule::axis() const {
- return Line::fromTwoPoints(p1, p2);
+ return Line::fromTwoPoints(p1, p2);
}
float Capsule::volume() const {
- return
- // Sphere volume
- pow(_radius, 3) * pi() * 4 / 3 +
+ return
+ // Sphere volume
+ pow(_radius, 3) * (float)pi() * 4 / 3 +
- // Cylinder volume
- pow(_radius, 2) * (p1 - p2).magnitude();
+ // Cylinder volume
+ pow(_radius, 2) * (p1 - p2).magnitude();
}
float Capsule::area() const {
- return
- // Sphere area
- pow(_radius, 2) * 4 * pi() +
+ return
+ // Sphere area
+ pow(_radius, 2) * 4 * (float)pi() +
- // Cylinder area
- twoPi() * _radius * (p1 - p2).magnitude();
+ // Cylinder area
+ (float)twoPi() * _radius * (p1 - p2).magnitude();
}
@@ -147,10 +147,10 @@ Vector3 Capsule::randomInteriorPoint() const {
Vector3 p;
- float hemiVolume = pi() * (r*r*r) * 4 / 6.0;
- float cylVolume = pi() * square(r) * h;
+ float hemiVolume = (float)pi() * (r*r*r) * 4 / 6.0f;
+ float cylVolume = (float)pi() * square(r) * h;
- float r1 = uniformRandom(0, 2.0 * hemiVolume + cylVolume);
+ float r1 = uniformRandom(0, 2.0f * hemiVolume + cylVolume);
if (r1 < 2.0 * hemiVolume) {
diff --git a/dep/g3dlite/source/CollisionDetection.cpp b/dep/g3dlite/source/CollisionDetection.cpp
index 77eef0a5500..ef48a5bb98f 100644
--- a/dep/g3dlite/source/CollisionDetection.cpp
+++ b/dep/g3dlite/source/CollisionDetection.cpp
@@ -37,7 +37,7 @@
namespace G3D {
bool CollisionDetection::ignoreBool;
-Vector3 CollisionDetection::ignore;
+Vector3 CollisionDetection::ignore;
Array<Vector3> CollisionDetection::ignoreArray;
@@ -186,7 +186,7 @@ bool CollisionDetection::parallelAxisForSolidBoxSolidBox(
int & axis1,
int & axis2) {
const double parallelDot = 1.0 - epsilon;
- for (int i = 0; i < 9; i++) {
+ for (int i = 0; i < 9; ++i) {
if (ca[i] >= parallelDot) {
axis1 = i / 3;
axis2 = i % 3;
@@ -221,14 +221,14 @@ void CollisionDetection::fillSolidBoxSolidBoxInfo(
// corresponds to c[row * 3 + col] for this 9 element array.
//
// c[] holds signed values, ca[] hold absolute values
- for (int i = 0; i < 9; i++) {
+ for (int i = 0; i < 9; ++i) {
c[i] = dot(box1.axis(i / 3), box2.axis(i % 3));
ca[i] = fabs(c[i]);
}
// store all possible dot products between the axes of box1 and D,
// as well as the axes of box2 and D
- for (int i = 0; i < 3; i++) {
+ for (int i = 0; i < 3; ++i) {
ad[i] = dot(box1.axis(i), D);
bd[i] = dot(box2.axis(i), D);
}
@@ -251,7 +251,7 @@ bool CollisionDetection::conservativeBoxBoxTest(
bool CollisionDetection::fixedSolidBoxIntersectsFixedSolidBox(
const Box& box1,
const Box& box2,
- const int lastSeparatingAxis) {
+ const int lastSeparatingAxis) {
// for explanations of the variable please refer to the
// paper and fillSolidBoxSolidBoxInfo()
Vector3 a;
@@ -285,7 +285,7 @@ bool CollisionDetection::fixedSolidBoxIntersectsFixedSolidBox(
// any of the three axes of box1, any of the three axes of box2,
// or any of the 9 possible cross products of axes from box1
// and box2
- for (int i = 0; i < 15; i++) {
+ for (int i = 0; i < 15; ++i) {
// do not need to check edge-edge cases if any two of
// the axes are parallel
if (parallelAxes && i == 6) {
@@ -388,10 +388,10 @@ float CollisionDetection::penetrationDepthForFixedBoxFixedBox(
// test if the boxes can be separated by a plane normal to
// any of the three axes of box1, any of the three axes of box2,
// (test 9 possible cross products later)
- float penetration = -finf();
+ float penetration = -finf();
int penetrationAxisIndex = -1;
- for (int i = 0; i < 6; i++) {
+ for (int i = 0; i < 6; ++i) {
float projectedDistance =
projectedDistanceForSolidBoxSolidBox(i, a, b, D, c, ca, ad, bd);
@@ -411,44 +411,45 @@ float CollisionDetection::penetrationDepthForFixedBoxFixedBox(
// for each edge-edge case we have to adjust the magnitude of
// penetration since we did not include the dot(L, L) denominator
// that can be smaller than 1.0 for the edge-edge cases.
- if (!parallelAxes) {
- double edgeDistances[9];
-
- // run through edge-edge cases to see if we can find a separating axis
- for (int i = 6; i < 15; i++) {
- float projectedDistance =
- projectedDistanceForSolidBoxSolidBox(i, a, b, D, c, ca, ad, bd);
-
- // found a separating axis, the boxes do not intersect,
- // correct magnitude and return projected distance
- if (projectedDistance > 0.0) {
- Vector3 L = separatingAxisForSolidBoxSolidBox(i, box1, box2);
- projectedDistance /= dot(L, L);
- return -projectedDistance;
- }
-
- edgeDistances[i - 6] = projectedDistance;
- }
-
- // no separating axis found, the boxes do intersect,
- // correct the magnitudes of the projectedDistance values
- for (int i = 6; i < 15; i++) {
- // find the negative penetration value with the smallest magnitude,
- // the adjustment done for the edge-edge cases only increases
- // magnitude by dividing by a number smaller than 1 and greater than 0
- float projectedDistance = (float)edgeDistances[i - 6];
- if (projectedDistance > penetration) {
- Vector3 L = separatingAxisForSolidBoxSolidBox(i, box1, box2);
- projectedDistance /= dot(L, L);
- if (projectedDistance > penetration) {
- penetration = projectedDistance;
- penetrationAxisIndex = i;
- }
- }
- }
- }
-
- // get final separating axis vector
+
+ if (!parallelAxes) {
+ double edgeDistances[9];
+
+ // run through edge-edge cases to see if we can find a separating axis
+ for (int i = 6; i < 15; ++i) {
+ float projectedDistance =
+ projectedDistanceForSolidBoxSolidBox(i, a, b, D, c, ca, ad, bd);
+
+ // found a separating axis, the boxes do not intersect,
+ // correct magnitude and return projected distance
+ if (projectedDistance > 0.0) {
+ Vector3 L = separatingAxisForSolidBoxSolidBox(i, box1, box2);
+ projectedDistance /= dot(L, L);
+ return -projectedDistance;
+ }
+
+ edgeDistances[i - 6] = projectedDistance;
+ }
+
+ // no separating axis found, the boxes do intersect,
+ // correct the magnitudes of the projectedDistance values
+ for (int i = 6; i < 15; ++i) {
+ // find the negative penetration value with the smallest magnitude,
+ // the adjustment done for the edge-edge cases only increases
+ // magnitude by dividing by a number smaller than 1 and greater than 0
+ float projectedDistance = (float)edgeDistances[i - 6];
+ if (projectedDistance > penetration) {
+ Vector3 L = separatingAxisForSolidBoxSolidBox(i, box1, box2);
+ projectedDistance /= dot(L, L);
+ if (projectedDistance > penetration) {
+ penetration = projectedDistance;
+ penetrationAxisIndex = i;
+ }
+ }
+ }
+ }
+
+ // get final separating axis vector
Vector3 L = separatingAxisForSolidBoxSolidBox(penetrationAxisIndex,
box1, box2);
@@ -462,18 +463,15 @@ float CollisionDetection::penetrationDepthForFixedBoxFixedBox(
if (penetrationAxisIndex < 6) {
// vertex to face collision, find deepest colliding vertex
const Box* vertexBox;
- const Box* faceBox;
Vector3 faceNormal = L;
// L will be the outward facing normal for the faceBox
if (penetrationAxisIndex < 3) {
- faceBox = & box1;
vertexBox = & box2;
if (dot(L, D) < 0) {
faceNormal = -L;
}
} else {
- faceBox = & box2;
vertexBox = & box1;
if (dot(L, D) > 0) {
faceNormal = -L;
@@ -484,7 +482,7 @@ float CollisionDetection::penetrationDepthForFixedBoxFixedBox(
// face normal direction
int deepestPointIndex = 0;
float deepestPointDot = dot(faceNormal, vertexBox->corner(0));
- for (int i = 1; i < 8; i++) {
+ for (int i = 1; i < 8; ++i) {
float dotProduct = dot(faceNormal, vertexBox->corner(i));
if (dotProduct < deepestPointDot) {
deepestPointDot = dotProduct;
@@ -507,7 +505,7 @@ float CollisionDetection::penetrationDepthForFixedBoxFixedBox(
// find edge line by finding the edge axis, and the
// other two axes that are closest to the other box
- for (int i = 0; i < 3; i++ ) {
+ for (int i = 0; i < 3; ++i) {
if (i == edge1) {
lineDir1 = box1.axis(i);
} else {
@@ -854,27 +852,27 @@ float CollisionDetection::collisionTimeForMovingPointFixedPlane(
Vector3& outNormal) {
// Solve for the time at which normal.dot(point + velocity) + d == 0.
- double d;
+ float d;
Vector3 normal;
plane.getEquation(normal, d);
- float vdotN = velocity.dot(normal);
- float pdotN = point.dot(normal);
+ const float vdotN = velocity.dot(normal);
+ const float pdotN = point.dot(normal);
- if (fuzzyEq(pdotN + d, 0)) {
+ if (fuzzyEq(pdotN + d, 0.0f)) {
// The point is *in* the plane.
location = point;
outNormal = normal;
return 0;
}
- if (vdotN >= 0) {
+ if (vdotN >= 0.0f) {
// no collision will occur
location = Vector3::inf();
return finf();
}
- float t = -(pdotN + d) / vdotN;
+ const float t = -(pdotN + d) / vdotN;
if (t < 0) {
location = Vector3::inf();
return finf();
@@ -921,7 +919,7 @@ bool __fastcall CollisionDetection::rayAABox(
// Find candidate planes.
for (int i = 0; i < 3; ++i) {
if (ray.origin()[i] < MinB[i]) {
- location[i] = MinB[i];
+ location[i] = MinB[i];
inside = false;
// Calculate T distances to candidate planes
@@ -929,7 +927,7 @@ bool __fastcall CollisionDetection::rayAABox(
MaxT[i] = (MinB[i] - ray.origin()[i]) * invDir[i];
}
} else if (ray.origin()[i] > MaxB[i]) {
- location[i] = MaxB[i];
+ location[i] = MaxB[i];
inside = false;
// Calculate T distances to candidate planes
@@ -940,7 +938,7 @@ bool __fastcall CollisionDetection::rayAABox(
}
if (inside) {
- // Ray origin inside bounding box
+ // Ray origin inside bounding box
location = ray.origin();
return true;
}
@@ -1065,10 +1063,10 @@ float CollisionDetection::collisionTimeForMovingSphereFixedSphere(
/*
float CollisionDetection::collisionTimeForMovingPointFixedTriangle(
- const Vector3& point,
- const Vector3& velocity,
+ const Vector3& point,
+ const Vector3& velocity,
const Triangle& triangle,
- Vector3& outLocation,
+ Vector3& outLocation,
Vector3& outNormal) {
double time = collisionTimeForMovingPointFixedPlane(point, velocity, triangle.plane(), outLocation, outNormal);
@@ -1234,73 +1232,73 @@ bool CollisionDetection::collisionLocationForMovingPointFixedAABox(
Vector3& normal) {
// Integer representation of a floating-point value.
- #define IR(x) ((uint32&)x)
+ #define IR(x) ((uint32&)x)
Inside = true;
- const Vector3& MinB = box.low();
- const Vector3& MaxB = box.high();
- Vector3 MaxT(-1.0f, -1.0f, -1.0f);
+ const Vector3& MinB = box.low();
+ const Vector3& MaxB = box.high();
+ Vector3 MaxT(-1.0f, -1.0f, -1.0f);
- // Find candidate planes.
+ // Find candidate planes.
for (int i = 0; i < 3; ++i) {
- if (origin[i] < MinB[i]) {
- location[i] = MinB[i];
- Inside = false;
+ if (origin[i] < MinB[i]) {
+ location[i] = MinB[i];
+ Inside = false;
- // Calculate T distances to candidate planes
+ // Calculate T distances to candidate planes
if (IR(dir[i])) {
MaxT[i] = (MinB[i] - origin[i]) / dir[i];
}
} else if (origin[i] > MaxB[i]) {
- location[i] = MaxB[i];
- Inside = false;
+ location[i] = MaxB[i];
+ Inside = false;
- // Calculate T distances to candidate planes
+ // Calculate T distances to candidate planes
if (IR(dir[i])) {
MaxT[i] = (MaxB[i] - origin[i]) / dir[i];
}
- }
- }
+ }
+ }
- if (Inside) {
- // Ray origin inside bounding box
+ if (Inside) {
+ // Ray origin inside bounding box
location = origin;
- return false;
- }
+ return false;
+ }
- // Get largest of the maxT's for final choice of intersection
- int WhichPlane = 0;
- if (MaxT[1] > MaxT[WhichPlane]) {
+ // Get largest of the maxT's for final choice of intersection
+ int WhichPlane = 0;
+ if (MaxT[1] > MaxT[WhichPlane]) {
WhichPlane = 1;
}
- if (MaxT[2] > MaxT[WhichPlane]) {
+ if (MaxT[2] > MaxT[WhichPlane]) {
WhichPlane = 2;
}
- // Check final candidate actually inside box
+ // Check final candidate actually inside box
if (IR(MaxT[WhichPlane]) & 0x80000000) {
// Miss the box
return false;
}
- for (int i = 0; i < 3; ++i) {
+ for (int i = 0; i < 3; ++i) {
if (i != WhichPlane) {
- location[i] = origin[i] + MaxT[WhichPlane] * dir[i];
+ location[i] = origin[i] + MaxT[WhichPlane] * dir[i];
if ((location[i] < MinB[i]) ||
(location[i] > MaxB[i])) {
// On this plane we're outside the box extents, so
// we miss the box
return false;
}
- }
- }
+ }
+ }
// Choose the normal to be the plane normal facing into the ray
normal = Vector3::zero();
normal[WhichPlane] = (dir[WhichPlane] > 0) ? -1.0 : 1.0;
- return true;
+ return true;
#undef IR
}
@@ -1338,19 +1336,24 @@ float CollisionDetection::collisionTimeForMovingPointFixedRectangle(
/** Used by findRayCapsuleIntersection.
@cite From magic software http://www.magic-software.com/Source/Intersection3D/MgcIntr3DLinCap.cpp */
static int findRayCapsuleIntersectionAux(
- const Vector3& rkOrigin,
- const Vector3& rkDirection,
- const Capsule& rkCapsule,
- double afT[2]) {
+ const Vector3& rkOrigin,
+ const Vector3& rkDirection,
+ const Capsule& rkCapsule,
+ double afT[2]) {
- Vector3 capsuleDirection = rkCapsule.point(1) - rkCapsule.point(0);
+ Vector3 capsuleDirection = rkCapsule.point(1) - rkCapsule.point(0);
// set up quadratic Q(t) = a*t^2 + 2*b*t + c
- Vector3 kU, kV, kW = capsuleDirection;
- float fWLength = kW.unitize();
- Vector3::generateOrthonormalBasis(kU, kV, kW);
+ Vector3 kW = capsuleDirection;
+ float fWLength = kW.length();
+ kW = kW.direction();
+
+ Vector3 kU, kV;
+ kW.getTangents(kU, kV);
Vector3 kD(kU.dot(rkDirection), kV.dot(rkDirection), kW.dot(rkDirection));
- float fDLength = kD.unitize();
+
+ float fDLength = kD.length();
+ kD = kD.direction();
float fEpsilon = 1e-6f;
@@ -1405,15 +1408,15 @@ static int findRayCapsuleIntersectionAux(
fTmp = kP.z + fT*kD.z;
if ((0.0f <= fTmp) && (fTmp <= fWLength)) {
afT[iQuantity] = fT * fInvDLength;
- iQuantity++;
- }
+ ++iQuantity;
+ }
fT = (-fB + fRoot)*fInv;
fTmp = kP.z + fT*kD.z;
- if ((0.0f <= fTmp) && (fTmp <= fWLength)) {
+ if ((0.0f <= fTmp) && (fTmp <= fWLength)) {
afT[iQuantity++] = fT*fInvDLength;
- }
+ }
if (iQuantity == 2) {
// line intersects capsule wall in two places
@@ -1442,7 +1445,7 @@ static int findRayCapsuleIntersectionAux(
afT[iQuantity++] = fT*fInvDLength;
if (iQuantity == 2) {
return 2;
- }
+ }
}
fT = -fB + fRoot;
@@ -1451,7 +1454,7 @@ static int findRayCapsuleIntersectionAux(
afT[iQuantity++] = fT*fInvDLength;
if (iQuantity == 2) {
return 2;
- }
+ }
}
} else if (fDiscr == 0.0f) {
fT = -fB;
@@ -1460,7 +1463,7 @@ static int findRayCapsuleIntersectionAux(
afT[iQuantity++] = fT*fInvDLength;
if (iQuantity == 2) {
return 2;
- }
+ }
}
}
@@ -1478,7 +1481,7 @@ static int findRayCapsuleIntersectionAux(
afT[iQuantity++] = fT*fInvDLength;
if (iQuantity == 2) {
return 2;
- }
+ }
}
fT = -fB + fRoot;
@@ -1487,7 +1490,7 @@ static int findRayCapsuleIntersectionAux(
afT[iQuantity++] = fT*fInvDLength;
if (iQuantity == 2) {
return 2;
- }
+ }
}
} else if (fDiscr == 0.0f) {
fT = -fB;
@@ -1496,7 +1499,7 @@ static int findRayCapsuleIntersectionAux(
afT[iQuantity++] = fT*fInvDLength;
if (iQuantity == 2) {
return 2;
- }
+ }
}
}
@@ -1506,25 +1509,25 @@ static int findRayCapsuleIntersectionAux(
/** Used by collisionTimeForMovingPointFixedCapsule.
@cite From magic software http://www.magic-software.com/Source/Intersection3D/MgcIntr3DLinCap.cpp
-
- @param rkRay The ray
- @param rkCapsule The capsule
- @param riQuantity The number of intersections found
- @param akPoint The intersections found
- @return True if there is at least one intersection
- */
+
+ @param rkRay The ray
+ @param rkCapsule The capsule
+ @param riQuantity The number of intersections found
+ @param akPoint The intersections found
+ @return True if there is at least one intersection
+ */
static bool findRayCapsuleIntersection(
- const Ray& rkRay,
- const Capsule& rkCapsule,
- int& riQuantity,
- Vector3 akPoint[2]) {
+ const Ray& rkRay,
+ const Capsule& rkCapsule,
+ int& riQuantity,
+ Vector3 akPoint[2]) {
double afT[2];
riQuantity = findRayCapsuleIntersectionAux(rkRay.origin(), rkRay.direction(), rkCapsule, afT);
// Only return intersections that occur in the future
int iClipQuantity = 0;
- int i;
+ int i;
for (i = 0; i < riQuantity; ++i) {
if (afT[i] >= 0.0f) {
akPoint[iClipQuantity] = rkRay.origin() + afT[i] * rkRay.direction();
@@ -1537,30 +1540,30 @@ static bool findRayCapsuleIntersection(
}
float CollisionDetection::collisionTimeForMovingPointFixedCapsule(
- const Vector3& _point,
- const Vector3& velocity,
- const Capsule& capsule,
- Vector3& location,
+ const Vector3& _point,
+ const Vector3& velocity,
+ const Capsule& capsule,
+ Vector3& location,
Vector3& outNormal) {
- float timeScale = velocity.magnitude();
+ float timeScale = velocity.magnitude();
if (timeScale == 0.0f) {
timeScale = 1;
}
- Vector3 direction = velocity / timeScale;
- int numIntersections;
- Vector3 intersection[2];
- findRayCapsuleIntersection(Ray::fromOriginAndDirection(_point, direction), capsule, numIntersections, intersection);
+ Vector3 direction = velocity / timeScale;
+ int numIntersections;
+ Vector3 intersection[2];
+ findRayCapsuleIntersection(Ray::fromOriginAndDirection(_point, direction), capsule, numIntersections, intersection);
- if (numIntersections == 2) {
- // A collision can only occur if there are two intersections. If there is one
- // intersection, that one is exiting the capsule.
+ if (numIntersections == 2) {
+ // A collision can only occur if there are two intersections. If there is one
+ // intersection, that one is exiting the capsule.
- // Find the entering intersection (the first one that occurs).
- float d0 = (intersection[0] - _point).squaredMagnitude();
- float d1 = (intersection[1] - _point).squaredMagnitude();
+ // Find the entering intersection (the first one that occurs).
+ float d0 = (intersection[0] - _point).squaredMagnitude();
+ float d1 = (intersection[1] - _point).squaredMagnitude();
// Compute the surface normal (if we aren't ignoring the result)
if (&outNormal != &ignore) {
@@ -1569,40 +1572,41 @@ float CollisionDetection::collisionTimeForMovingPointFixedCapsule(
}
if (d0 > d1) {
- location = intersection[1];
- return sqrt(d1) / timeScale;
- } else {
- location = intersection[0];
- return sqrt(d0) / timeScale;
- }
- } else {
- // No entering intersection discovered; return no intersection.
- location = Vector3::inf();
- return finf();
- }
+ location = intersection[1];
+ return sqrt(d1) / timeScale;
+ } else {
+ location = intersection[0];
+ return sqrt(d0) / timeScale;
+ }
+ } else {
+ // No entering intersection discovered; return no intersection.
+ location = Vector3::inf();
+ return finf();
+ }
}
float CollisionDetection::collisionTimeForMovingSphereFixedPlane(
- const Sphere& sphere,
- const Vector3& velocity,
- const Plane& plane,
- Vector3& location,
+ const Sphere& sphere,
+ const Vector3& velocity,
+ const Plane& plane,
+ Vector3& location,
Vector3& outNormal) {
- if (sphere.radius == 0) {
- // Optimization for zero radius sphere
+ if (sphere.radius == 0) {
+ // Optimization for zero radius sphere
return collisionTimeForMovingPointFixedPlane(sphere.center, velocity, plane, location, outNormal);
- }
+ }
- // The collision point on the sphere will be the point at
- // center - (radius * normal). Collisions only occur when
+ // The world-space collision point, which lies on the surface of the sphere, will be the point at
+ // center + velocity * time - (radius * planeNormal). Collisions only occur when
// the sphere is travelling into the plane.
- double d;
+ float d;
plane.getEquation(outNormal, d);
- double vdotN = velocity.dot(outNormal);
+ // Rate at which the sphere is approaching the plane
+ const float vdotN = velocity.dot(outNormal);
if (fuzzyGt(vdotN, 0)) {
// No collision when the sphere is moving towards a backface.
@@ -1610,34 +1614,37 @@ float CollisionDetection::collisionTimeForMovingSphereFixedPlane(
return (float)finf();
}
- float cdotN = sphere.center.dot(outNormal);
-
- // Distance from the center to the plane
- float distance = cdotN + (float)d;
-
- // Where is the collision on the sphere?
- Vector3 point = sphere.center - (sphere.radius * outNormal);
+ // Initial distance from the sphere center to the plane
+ const float distance = sphere.center.dot(outNormal) + d;
if (fuzzyLe(G3D::abs(distance), sphere.radius)) {
// Already interpenetrating
location = sphere.center - distance * outNormal;
return 0;
} else {
+ // The point on the sphere (in world space) that will eventually first contact the plane
+ const Point3& point = sphere.center - (sphere.radius * outNormal);
+
+ // The problem is now reduced to finding when the point hits the plane
return collisionTimeForMovingPointFixedPlane(point, velocity, plane, location, outNormal);
}
}
-float CollisionDetection::collisionTimeForMovingSphereFixedTriangle(
- const class Sphere& sphere,
- const Vector3& velocity,
- const Triangle& triangle,
- Vector3& outLocation,
- float b[3]) {
+float CollisionDetection::collisionTimeForMovingSphereFixedTriangle
+(const Sphere& sphere,
+ const Vector3& velocity,
+ const Triangle& triangle,
+ Vector3& outLocation,
+ float b[3]) {
+ if (velocity.dot(triangle.normal()) > 0.0f) {
+ // No collision if moving towards a backface
+ return finf();
+ }
Vector3 dummy;
- float time = collisionTimeForMovingSphereFixedPlane(sphere, velocity, triangle.plane(),
+ const float time = collisionTimeForMovingSphereFixedPlane(sphere, velocity, triangle.plane(),
outLocation, dummy);
if (time == finf()) {
@@ -1660,7 +1667,7 @@ float CollisionDetection::collisionTimeForMovingSphereFixedTriangle(
debugAssertM(b[0] >= 0.0 && b[0] <= 1.0f, "Intersection is outside triangle.");
debugAssertM(b[1] >= 0.0 && b[1] <= 1.0f, "Intersection is outside triangle.");
debugAssertM(b[2] >= 0.0 && b[2] <= 1.0f, "Intersection is outside triangle.");
- Vector3 blend =
+ const Vector3& blend =
b[0] * triangle.vertex(0) +
b[1] * triangle.vertex(1) +
b[2] * triangle.vertex(2);
@@ -1817,18 +1824,18 @@ float CollisionDetection::collisionTimeForMovingSphereFixedBox(
float CollisionDetection::collisionTimeForMovingSphereFixedCapsule(
- const Sphere& sphere,
- const Vector3& velocity,
- const Capsule& capsule,
- Vector3& location,
+ const Sphere& sphere,
+ const Vector3& velocity,
+ const Capsule& capsule,
+ Vector3& location,
Vector3& outNormal) {
(void)outNormal;
- Capsule _capsule(capsule.point(0), capsule.point(1), capsule.radius() + sphere.radius);
+ Capsule _capsule(capsule.point(0), capsule.point(1), capsule.radius() + sphere.radius);
Vector3 normal;
- double time = collisionTimeForMovingPointFixedCapsule(sphere.center, velocity, _capsule, location, normal);
+ double time = collisionTimeForMovingPointFixedCapsule(sphere.center, velocity, _capsule, location, normal);
if (time < finf()) {
// Location is now the position of the center of the sphere at the time of collision.
@@ -1847,14 +1854,14 @@ Vector3 CollisionDetection::bounceDirection(
const Vector3& collisionLocation,
const Vector3& collisionNormal) {
- // Location when the collision occurs
+ // Location when the collision occurs
Vector3 sphereLocation = sphere.center + velocity * collisionTime;
Vector3 normal = (sphereLocation - collisionLocation);
if (fuzzyEq(normal.squaredMagnitude(), 0)) {
normal = collisionNormal;
} else {
- normal.unitize();
+ normal = normal.direction();
}
Vector3 direction = velocity.direction();
@@ -1926,10 +1933,10 @@ Vector3 CollisionDetection::closestPointOnLineSegment(
Vector3 CollisionDetection::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) {
Vector3 v[3] = {v0, v1, v2};
Vector3 edgeDirection[3] = {(v1 - v0), (v2 - v1), (v0 - v2)};
@@ -2000,11 +2007,11 @@ Vector3 CollisionDetection::closestPointOnTrianglePerimeter(
bool CollisionDetection::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,
float b[3],
Vector3::Axis primaryAxis) {
diff --git a/dep/g3dlite/source/Color1.cpp b/dep/g3dlite/source/Color1.cpp
index 04f3f9412b1..6347a4a05da 100644
--- a/dep/g3dlite/source/Color1.cpp
+++ b/dep/g3dlite/source/Color1.cpp
@@ -1,17 +1,17 @@
/**
- @file Color1.cpp
+ \file Color1.cpp
Color class.
- @author Morgan McGuire, http://graphics.cs.williams.edu
+ \author Morgan McGuire, http://graphics.cs.williams.edu
- @created 2007-01-30
- @edited 2009-03-27
+ \created 2007-01-30
+ \edited 2011-08-27
*/
#include "G3D/platform.h"
#include "G3D/Color1.h"
-#include "G3D/Color1uint8.h"
+#include "G3D/Color1unorm8.h"
#include "G3D/BinaryInput.h"
#include "G3D/BinaryOutput.h"
#include "G3D/Color3.h"
@@ -50,8 +50,8 @@ void Color1::serialize(BinaryOutput& bo) const {
}
-Color1::Color1(const class Color1uint8& other) {
- value = other.value / 255.0f;
+Color1::Color1(const class Color1unorm8& other) {
+ value = other.value;
}
} // namespace G3D
diff --git a/dep/g3dlite/source/Color1uint8.cpp b/dep/g3dlite/source/Color1uint8.cpp
deleted file mode 100644
index 21cd564ba92..00000000000
--- a/dep/g3dlite/source/Color1uint8.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-/**
- @file Color1uint8.cpp
-
- @author Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2007-01-30
- @edited 2007-01-30
- */
-
-#include "G3D/platform.h"
-#include "G3D/g3dmath.h"
-#include "G3D/Color1uint8.h"
-#include "G3D/Color1.h"
-#include "G3D/BinaryInput.h"
-#include "G3D/BinaryOutput.h"
-
-namespace G3D {
-
-Color1uint8::Color1uint8(const class Color1& c) : value(iClamp(iFloor(c.value * 256), 0, 255)) {
-}
-
-
-Color1uint8::Color1uint8(class BinaryInput& bi) {
- deserialize(bi);
-}
-
-
-void Color1uint8::serialize(class BinaryOutput& bo) const {
- bo.writeUInt8(value);
-}
-
-
-void Color1uint8::deserialize(class BinaryInput& bi) {
- value = bi.readUInt8();
-}
-
-
-}
diff --git a/dep/g3dlite/source/Color3.cpp b/dep/g3dlite/source/Color3.cpp
index deb0bd87ee7..bc50aaf40ab 100644
--- a/dep/g3dlite/source/Color3.cpp
+++ b/dep/g3dlite/source/Color3.cpp
@@ -1,12 +1,12 @@
/**
- @file Color3.cpp
+ \file Color3.cpp
Color class.
- @author Morgan McGuire, http://graphics.cs.williams.edu
+ \author Morgan McGuire, http://graphics.cs.williams.edu
- @created 2001-06-02
- @edited 2010-01-28
+ \created 2001-06-02
+ \edited 2013-03-29
*/
#include "G3D/platform.h"
@@ -16,21 +16,26 @@
#include "G3D/format.h"
#include "G3D/BinaryInput.h"
#include "G3D/BinaryOutput.h"
-#include "G3D/Color3uint8.h"
+#include "G3D/Color3unorm8.h"
#include "G3D/Any.h"
#include "G3D/stringutils.h"
namespace G3D {
+Color3& Color3::operator=(const Any& a) {
+ *this = Color3(a);
+ return *this;
+}
+
+
Color3::Color3(const Any& any) {
*this = Color3::zero();
- any.verifyName("Color3");
- std::string name = toLower(any.name());
+ any.verifyNameBeginsWith("Color3", "Power3", "Radiance3", "Irradiance3", "Energy3", "Radiosity3", "Biradiance3");
switch (any.type()) {
case Any::TABLE:
- for (Any::AnyTable::Iterator it = any.table().begin(); it.hasMore(); ++it) {
+ for (Any::AnyTable::Iterator it = any.table().begin(); it.isValid(); ++it) {
const std::string& key = toLower(it->key);
if (key == "r") {
r = it->value;
@@ -44,22 +49,38 @@ Color3::Color3(const Any& any) {
}
break;
- case Any::ARRAY:
- if (name == "color3") {
- any.verifySize(3);
- r = any[0];
- g = any[1];
- b = any[2];
- } else if (name == "color3::one") {
- any.verifySize(0);
- *this = one();
- } else if (name == "color3::zero") {
- any.verifySize(0);
- *this = zero();
- } else if (name == "color3::fromargb") {
- *this = Color3::fromARGB((int)any[0].number());
- } else {
- any.verify(false, "Expected Color3 constructor");
+ case Any::ARRAY: // Intentionally falls through
+ case Any::EMPTY_CONTAINER:
+ {
+ const std::string& name = any.name();
+ std::string factoryName;
+ size_t i = name.find("::");
+ if (i != std::string::npos && i > 1) {
+ factoryName = name.substr(i + 2);
+ }
+
+ if (factoryName == "") {
+ if (any.size() == 1) {
+ r = g = b = any[0];
+ } else {
+ any.verifySize(3);
+ r = any[0];
+ g = any[1];
+ b = any[2];
+ }
+ } else if (factoryName == "one") {
+ any.verifySize(0);
+ *this = one();
+ } else if (factoryName == "zero") {
+ any.verifySize(0);
+ *this = zero();
+ } else if (factoryName == "fromARGB") {
+ *this = Color3::fromARGB((int)any[0].number());
+ } else if (factoryName == "fromASRGB") {
+ *this = Color3::fromASRGB((int)any[0].number());
+ } else {
+ any.verify(false, "Expected Color3 constructor");
+ }
}
break;
@@ -69,7 +90,7 @@ Color3::Color3(const Any& any) {
}
-Color3::operator Any() const {
+Any Color3::toAny() const {
Any a(Any::ARRAY, "Color3");
a.append(r, g, b);
return a;
@@ -169,7 +190,7 @@ const Color3& Color3::gray() {
const Color3& Color3::white() {
- static Color3 c(1, 1, 1);
+ static Color3 c(1.0f, 1.0f, 1.0f);
return c;
}
@@ -224,15 +245,16 @@ Color3::Color3(const Vector3& v) {
}
-Color3::Color3(const class Color3uint8& other) {
- r = other.r / 255.0f;
- g = other.g / 255.0f;
- b = other.b / 255.0f;
+Color3::Color3(const class Color3unorm8& other) : r(other.r), g(other.g), b(other.b) {
}
Color3 Color3::fromARGB(uint32 x) {
- return Color3((float)((x >> 16) & 0xFF), (float)((x >> 8) & 0xFF), (float)(x & 0xFF)) / 255.0f;
+ return Color3(Color3unorm8::fromARGB(x));
+}
+
+Color3 Color3::fromASRGB(uint32 x) {
+ return Color3(Color3unorm8::fromARGB(x)).pow(2.2f);
}
//----------------------------------------------------------------------------
@@ -247,7 +269,7 @@ Color3 Color3::random() {
//----------------------------------------------------------------------------
Color3& Color3::operator/= (float fScalar) {
if (fScalar != 0.0f) {
- float fInvScalar = 1.0f / fScalar;
+ float fInvScalar = 1.0f / fScalar;
r *= fInvScalar;
g *= fInvScalar;
b *= fInvScalar;
@@ -262,10 +284,10 @@ Color3& Color3::operator/= (float fScalar) {
//----------------------------------------------------------------------------
float Color3::unitize (float fTolerance) {
- float fLength = length();
+ float fLength = length();
if ( fLength > fTolerance ) {
- float fInvLength = 1.0f / fLength;
+ float fInvLength = 1.0f / fLength;
r *= fInvLength;
g *= fInvLength;
b *= fInvLength;
@@ -313,56 +335,56 @@ Color3 Color3::fromHSV(const Vector3& _hsv) {
Vector3 Color3::toHSV(const Color3& _rgb) {
- debugAssertM((_rgb.r <= 1.0f && _rgb.r >= 0.0f)
- && (_rgb.g <= 1.0f && _rgb.g >= 0.0f)
- && (_rgb.b <= 1.0f && _rgb.b >= 0.0f), "R,G,B must be between [0,1]");
- Vector3 hsv = Vector3::zero();
- hsv.z = G3D::max(G3D::max(_rgb.r, _rgb.g), _rgb.b);
- if (G3D::fuzzyEq(hsv.z, 0.0f)) {
- return hsv;
- }
-
+ debugAssertM((_rgb.r <= 1.0f && _rgb.r >= 0.0f)
+ && (_rgb.g <= 1.0f && _rgb.g >= 0.0f)
+ && (_rgb.b <= 1.0f && _rgb.b >= 0.0f), "R,G,B must be between [0,1]");
+ Vector3 hsv = Vector3::zero();
+ hsv.z = G3D::max(G3D::max(_rgb.r, _rgb.g), _rgb.b);
+ if (G3D::fuzzyEq(hsv.z, 0.0f)) {
+ return hsv;
+ }
+
const float x = G3D::min(G3D::min(_rgb.r, _rgb.g), _rgb.b);
- hsv.y = (hsv.z - x) / hsv.z;
+ hsv.y = (hsv.z - x) / hsv.z;
if (G3D::fuzzyEq(hsv.y, 0.0f)) {
- return hsv;
- }
-
- Vector3 rgbN;
- rgbN.x = (hsv.z - _rgb.r) / (hsv.z - x);
- rgbN.y = (hsv.z - _rgb.g) / (hsv.z - x);
- rgbN.z = (hsv.z - _rgb.b) / (hsv.z - x);
-
- if (_rgb.r == hsv.z) { // note from the max we know that it exactly equals one of the three.
- hsv.x = (_rgb.g == x)? 5.0f + rgbN.z : 1.0f - rgbN.y;
- } else if (_rgb.g == hsv.z) {
- hsv.x = (_rgb.b == x)? 1.0f + rgbN.x : 3.0f - rgbN.z;
- } else {
- hsv.x = (_rgb.r == x)? 3.0f + rgbN.y : 5.0f - rgbN.x;
- }
-
+ return hsv;
+ }
+
+ Vector3 rgbN;
+ rgbN.x = (hsv.z - _rgb.r) / (hsv.z - x);
+ rgbN.y = (hsv.z - _rgb.g) / (hsv.z - x);
+ rgbN.z = (hsv.z - _rgb.b) / (hsv.z - x);
+
+ if (_rgb.r == hsv.z) { // note from the max we know that it exactly equals one of the three.
+ hsv.x = (_rgb.g == x)? 5.0f + rgbN.z : 1.0f - rgbN.y;
+ } else if (_rgb.g == hsv.z) {
+ hsv.x = (_rgb.b == x)? 1.0f + rgbN.x : 3.0f - rgbN.z;
+ } else {
+ hsv.x = (_rgb.r == x)? 3.0f + rgbN.y : 5.0f - rgbN.x;
+ }
+
hsv.x /= 6.0f;
- return hsv;
+ return hsv;
}
Color3 Color3::jetColorMap(const float& val) {
- debugAssertM(val <= 1.0f && val >= 0.0f , "value should be in [0,1]");
+ debugAssertM(val <= 1.0f && val >= 0.0f , "value should be in [0,1]");
- //truncated triangles where sides have slope 4
- Color3 jet;
+ //truncated triangles where sides have slope 4
+ Color3 jet;
- jet.r = G3D::min(4.0f * val - 1.5f,-4.0f * val + 4.5f) ;
- jet.g = G3D::min(4.0f * val - 0.5f,-4.0f * val + 3.5f) ;
- jet.b = G3D::min(4.0f * val + 0.5f,-4.0f * val + 2.5f) ;
+ jet.r = G3D::min(4.0f * val - 1.5f,-4.0f * val + 4.5f) ;
+ jet.g = G3D::min(4.0f * val - 0.5f,-4.0f * val + 3.5f) ;
+ jet.b = G3D::min(4.0f * val + 0.5f,-4.0f * val + 2.5f) ;
- jet.r = G3D::clamp(jet.r, 0.0f, 1.0f);
- jet.g = G3D::clamp(jet.g, 0.0f, 1.0f);
- jet.b = G3D::clamp(jet.b, 0.0f, 1.0f);
+ jet.r = G3D::clamp(jet.r, 0.0f, 1.0f);
+ jet.g = G3D::clamp(jet.g, 0.0f, 1.0f);
+ jet.b = G3D::clamp(jet.b, 0.0f, 1.0f);
- return jet;
+ return jet;
}
diff --git a/dep/g3dlite/source/Color3uint8.cpp b/dep/g3dlite/source/Color3uint8.cpp
deleted file mode 100644
index a744710c752..00000000000
--- a/dep/g3dlite/source/Color3uint8.cpp
+++ /dev/null
@@ -1,45 +0,0 @@
-/**
- @file Color3uint8.cpp
-
- @author Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2003-04-07
- @edited 2006-01-07
- */
-
-#include "G3D/platform.h"
-#include "G3D/g3dmath.h"
-#include "G3D/Color3uint8.h"
-#include "G3D/Color3.h"
-#include "G3D/BinaryInput.h"
-#include "G3D/BinaryOutput.h"
-
-namespace G3D {
-
-Color3uint8::Color3uint8(const class Color3& c) {
- r = iMin(255, iFloor(c.r * 256));
- g = iMin(255, iFloor(c.g * 256));
- b = iMin(255, iFloor(c.b * 256));
-}
-
-
-Color3uint8::Color3uint8(class BinaryInput& bi) {
- deserialize(bi);
-}
-
-
-void Color3uint8::serialize(class BinaryOutput& bo) const {
- bo.writeUInt8(r);
- bo.writeUInt8(g);
- bo.writeUInt8(b);
-}
-
-
-void Color3uint8::deserialize(class BinaryInput& bi) {
- r = bi.readUInt8();
- g = bi.readUInt8();
- b = bi.readUInt8();
-}
-
-
-}
diff --git a/dep/g3dlite/source/Color4.cpp b/dep/g3dlite/source/Color4.cpp
index eab09eb9c7e..5c1117c6b0e 100644
--- a/dep/g3dlite/source/Color4.cpp
+++ b/dep/g3dlite/source/Color4.cpp
@@ -1,20 +1,17 @@
/**
- @file Color4.cpp
+ \file Color4.cpp
Color class.
- @author Morgan McGuire, http://graphics.cs.williams.edu
- @cite Portions by Laura Wollstadt, graphics3d.com
- @cite Portions based on Dave Eberly's Magic Software Library at http://www.magic-software.com
+ \author Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2002-06-25
- @edited 2009-11-10
+ \created 2002-06-25
+ \edited 2011-09-10
*/
#include <stdlib.h>
#include "G3D/Color4.h"
-#include "G3D/Color4uint8.h"
+#include "G3D/Color4unorm8.h"
#include "G3D/Vector4.h"
#include "G3D/format.h"
#include "G3D/BinaryInput.h"
@@ -24,38 +21,39 @@
namespace G3D {
+
Color4::Color4(const Any& any) {
*this = Color4::zero();
- any.verifyName("Color4");
-
- if (any.type() == Any::TABLE) {
- for (Any::AnyTable::Iterator it = any.table().begin(); it.hasMore(); ++it) {
- const std::string& key = toLower(it->key);
- if (key == "r") {
- r = it->value;
- } else if (key == "g") {
- g = it->value;
- } else if (key == "b") {
- b = it->value;
- } else if (key == "a") {
- a = it->value;
- } else {
- any.verify(false, "Illegal key: " + it->key);
- }
- }
- } else if (toLower(any.name()) == "color4") {
- r = any[0];
- g = any[1];
- b = any[2];
- a = any[3];
+
+ any.verifyNameBeginsWith("Color", "Power", "Radiance", "Irradiance", "Energy", "Radiosity", "Biradiance");
+
+ if (any.name().find('3') != std::string::npos) {
+ // This is a Color3 constructor--extend with alpha = 1
+ *this = Color4(Color3(any), 1.0f);
} else {
- any.verifyName("Color4::fromARGB");
- *this = Color4::fromARGB((int)any[0].number());
+
+ if (any.type() == Any::TABLE) {
+ any.verifyName("Color4");
+ AnyTableReader atr(any);
+ atr.getIfPresent("r", r);
+ atr.getIfPresent("g", g);
+ atr.getIfPresent("b", b);
+ atr.getIfPresent("a", a);
+ atr.verifyDone();
+ } else if (toLower(any.name()) == "color4") {
+ r = any[0];
+ g = any[1];
+ b = any[2];
+ a = any[3];
+ } else {
+ any.verifyName("Color4::fromARGB");
+ *this = Color4::fromARGB((uint32)any[0].number());
+ }
}
}
-Color4::operator Any() const {
+Any Color4::toAny() const {
Any any(Any::ARRAY, "Color4");
any.append(r, g, b, a);
return any;
@@ -99,8 +97,7 @@ Color4::Color4(const Vector4& v) {
}
-Color4::Color4(const Color4uint8& c) : r(c.r), g(c.g), b(c.b), a(c.a) {
- *this /= 255.0f;
+Color4::Color4(const Color4unorm8& c) : r(c.r), g(c.g), b(c.b), a(c.a) {
}
size_t Color4::hashCode() const {
@@ -148,7 +145,7 @@ Color4 Color4::operator/ (float fScalar) const {
Color4 kQuot;
if (fScalar != 0.0f) {
- float fInvScalar = 1.0f / fScalar;
+ float fInvScalar = 1.0f / fScalar;
kQuot.r = fInvScalar * r;
kQuot.g = fInvScalar * g;
kQuot.b = fInvScalar * b;
@@ -165,7 +162,7 @@ Color4 Color4::operator/ (float fScalar) const {
Color4& Color4::operator/= (float fScalar) {
if (fScalar != 0.0f) {
- float fInvScalar = 1.0f / fScalar;
+ float fInvScalar = 1.0f / fScalar;
r *= fInvScalar;
g *= fInvScalar;
b *= fInvScalar;
diff --git a/dep/g3dlite/source/Color4uint8.cpp b/dep/g3dlite/source/Color4uint8.cpp
deleted file mode 100644
index 5cc3a578aca..00000000000
--- a/dep/g3dlite/source/Color4uint8.cpp
+++ /dev/null
@@ -1,47 +0,0 @@
-/**
- @file Color4uint8.cpp
-
- @author Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2003-04-07
- @edited 2006-01-07
- */
-#include "G3D/platform.h"
-#include "G3D/g3dmath.h"
-#include "G3D/Color4uint8.h"
-#include "G3D/Color4.h"
-#include "G3D/BinaryInput.h"
-#include "G3D/BinaryOutput.h"
-
-namespace G3D {
-
-Color4uint8::Color4uint8(const class Color4& c) {
- r = iMin(255, iFloor(c.r * 256));
- g = iMin(255, iFloor(c.g * 256));
- b = iMin(255, iFloor(c.b * 256));
- a = iMin(255, iFloor(c.a * 256));
-}
-
-
-Color4uint8::Color4uint8(class BinaryInput& bi) {
- deserialize(bi);
-}
-
-
-void Color4uint8::serialize(class BinaryOutput& bo) const {
- bo.writeUInt8(r);
- bo.writeUInt8(g);
- bo.writeUInt8(b);
- bo.writeUInt8(a);
-}
-
-
-void Color4uint8::deserialize(class BinaryInput& bi) {
- r = bi.readUInt8();
- g = bi.readUInt8();
- b = bi.readUInt8();
- a = bi.readUInt8();
-}
-
-
-}
diff --git a/dep/g3dlite/source/Cone.cpp b/dep/g3dlite/source/Cone.cpp
index 3104b8424a7..586ccfd6761 100644
--- a/dep/g3dlite/source/Cone.cpp
+++ b/dep/g3dlite/source/Cone.cpp
@@ -17,6 +17,24 @@
namespace G3D {
+
+float Cone::solidAngleFromHalfAngle(float halfAngle){
+ return 2.0f * pif() * (1 - cosf(halfAngle));
+}
+
+double Cone::solidAngleFromHalfAngle(double halfAngle){
+ return 2.0 * pi() * (1.0 - cos(halfAngle));
+}
+
+float Cone::halfAngleFromSolidAngle(float solidAngle){
+ return acos((1.0f - (solidAngle / (2.0f * pif()))));
+}
+
+double Cone::halfAngleFromSolidAngle(double solidAngle){
+ return aCos((1.0 - (solidAngle / (2.0 * pi()))));
+}
+
+
Cone::Cone(const Vector3 &tip, const Vector3 &direction, float angle) {
this->tip = tip;
this->direction = direction.direction();
@@ -26,6 +44,42 @@ Cone::Cone(const Vector3 &tip, const Vector3 &direction, float angle) {
debugAssert(angle <= pi());
}
+Vector3 Cone::randomDirectionInCone(Random& rng) const {
+ const float cosThresh = cos(angle);
+
+ float cosAngle;
+ float normalizer;
+ Vector3 v;
+ do {
+ float vlenSquared;
+
+ // Sample uniformly on a sphere by rejection sampling and then normalizing
+ do {
+ v.x = rng.uniform(-1, 1);
+ v.y = rng.uniform(-1, 1);
+ v.z = rng.uniform(-1, 1);
+
+ // Sample uniformly on a cube
+ vlenSquared = v.squaredLength();
+ } while (vlenSquared > 1);
+
+
+ const float temp = v.dot(direction);
+
+ // Compute 1 / ||v||, but
+ // if the vector is in the wrong hemisphere, flip the sign
+ normalizer = rsqrt(vlenSquared) * sign(temp);
+
+ // Cosine of the angle between v and the light's negative-z axis
+ cosAngle = temp * normalizer;
+
+ } while (cosAngle < cosThresh);
+
+ // v was within the cone. Normalize it and maybe flip the hemisphere.
+ return v * normalizer;
+ }
+
+
/**
Forms the smallest cone that contains the box. Undefined if
the tip is inside or on the box.
diff --git a/dep/g3dlite/source/ConvexPolyhedron.cpp b/dep/g3dlite/source/ConvexPolyhedron.cpp
index 5fa76e3ed41..b76d9160b34 100644
--- a/dep/g3dlite/source/ConvexPolyhedron.cpp
+++ b/dep/g3dlite/source/ConvexPolyhedron.cpp
@@ -27,7 +27,7 @@ ConvexPolygon::ConvexPolygon(const Vector3& v0, const Vector3& v1, const Vector3
bool ConvexPolygon::isEmpty() const {
- return (_vertex.length() == 0) || (getArea() <= fuzzyEpsilon);
+ return (_vertex.length() == 0) || (getArea() <= fuzzyEpsilon32);
}
@@ -41,7 +41,7 @@ float ConvexPolygon::getArea() const {
int length = _vertex.length();
// Split into triangle fan, compute individual area
- for (int v = 2; v < length; v++) {
+ for (int v = 2; v < length; ++v) {
int i0 = 0;
int i1 = v - 1;
int i2 = v;
@@ -110,7 +110,7 @@ void ConvexPolygon::cut(const Plane& plane, ConvexPolygon &above, ConvexPolygon
below._vertex.append(_vertex[v]);
}
- for (v = 1; v < length; v++) {
+ for (v = 1; v < length; ++v) {
bool isAbove = plane.halfSpaceContains(_vertex[v]);
if (lastAbove ^ isAbove) {
@@ -141,7 +141,7 @@ void ConvexPolygon::cut(const Plane& plane, ConvexPolygon &above, ConvexPolygon
} else {
newEdge.start = interp;
}
- count++;
+ ++count;
}
lastAbove = isAbove;
@@ -191,7 +191,7 @@ ConvexPolygon ConvexPolygon::inverse() const {
int length = _vertex.length();
result._vertex.resize(length);
- for (int v = 0; v < length; v++) {
+ for (int v = 0; v < length; ++v) {
result._vertex[v] = _vertex[length - v - 1];
}
@@ -210,7 +210,7 @@ void ConvexPolygon::removeDuplicateVertices(){
--i; // Don't move forward.
}
}
-
+
// Check the last vertex against the first.
if (_vertex[_vertex.size()-1].fuzzyEq(_vertex[0])){
_vertex.pop();
@@ -239,7 +239,7 @@ float ConvexPolyhedron::getVolume() const {
// Choose the first _vertex of the first face as the origin.
// This lets us skip one face, too, and avoids negative heights.
Vector3 v0 = face[0]._vertex[0];
- for (int f = 1; f < face.length(); f++) {
+ for (int f = 1; f < face.length(); ++f) {
const ConvexPolygon& poly = face[f];
float height = (poly._vertex[0] - v0).dot(poly.normal());
@@ -252,7 +252,7 @@ float ConvexPolyhedron::getVolume() const {
}
bool ConvexPolyhedron::isEmpty() const {
- return (face.length() == 0) || (getVolume() <= fuzzyEpsilon);
+ return (face.length() == 0) || (getVolume() <= fuzzyEpsilon32);
}
void ConvexPolyhedron::cut(const Plane& plane, ConvexPolyhedron &above, ConvexPolyhedron &below) {
@@ -280,11 +280,11 @@ void ConvexPolyhedron::cut(const Plane& plane, ConvexPolyhedron &above, ConvexPo
for (int v = poly._vertex.length() - 1; (v >= 0) && (!ruledOut); v--) {
double r = abc.dot(poly._vertex[v]) + d;
if (r > eps) {
- numAbove++;
+ ++numAbove;
} else if (r < -eps) {
- numBelow++;
+ ++numBelow;
} else {
- numIn++;
+ ++numIn;
}
ruledOut = (numAbove != 0) && (numBelow !=0);
@@ -333,11 +333,11 @@ void ConvexPolyhedron::cut(const Plane& plane, ConvexPolyhedron &above, ConvexPo
const Array<Vector3>& _vertex = (aEmpty ? b._vertex : a._vertex);
int L = _vertex.length();
int count = 0;
- for (int v = 0; v < L; v++) {
+ for (int v = 0; v < L; ++v) {
if (plane.fuzzyContains(_vertex[v]) && plane.fuzzyContains(_vertex[(v + 1) % L])) {
e.start = _vertex[v];
e.stop = _vertex[(v + 1) % L];
- count++;
+ ++count;
}
}
@@ -366,7 +366,7 @@ void ConvexPolyhedron::cut(const Plane& plane, ConvexPolyhedron &above, ConvexPo
// Collect the final polgyon by sorting the edges
int numVertices = edge.length();
/*debugPrintf("\n");
-for (int xx=0; xx < numVertices; xx++) {
+for (int xx=0; xx < numVertices; ++xx) {
std::string s1 = edge[xx].start.toString();
std::string s2 = edge[xx].stop.toString();
debugPrintf("%s -> %s\n", s1.c_str(), s2.c_str());
@@ -387,7 +387,7 @@ for (int xx=0; xx < numVertices; xx++) {
int index = 0;
int num = edge.length();
double distance = (edge[index].start - last_vertex).squaredMagnitude();
- for (int e = 1; e < num; e++) {
+ for (int e = 1; e < num; ++e) {
double d = (edge[e].start - last_vertex).squaredMagnitude();
if (d < distance) {
@@ -430,7 +430,7 @@ bool ConvexPolygon2D::contains(const Vector2& p, bool reverse) const {
// the polygon. (To adapt this algorithm for a concave polygon,
// the *sum* of the areas must be non-negative).
- float r = reverse ? -1 : 1;
+ float r = reverse ? -1.0f : 1.0f;
for (int i0 = 0; i0 < m_vertex.size(); ++i0) {
int i1 = (i0 + 1) % m_vertex.size();
diff --git a/dep/g3dlite/source/CoordinateFrame.cpp b/dep/g3dlite/source/CoordinateFrame.cpp
index 7f9a4c098a5..e2c08a54e80 100644
--- a/dep/g3dlite/source/CoordinateFrame.cpp
+++ b/dep/g3dlite/source/CoordinateFrame.cpp
@@ -1,14 +1,14 @@
/**
- @file CoordinateFrame.cpp
+ \file CoordinateFrame.cpp
Coordinate frame class
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
+ \maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @created 2001-06-02
- @edited 2010-03-13
+ \created 2001-06-02
+ \edited 2012-09-29
- Copyright 2000-2010, Morgan McGuire.
+ Copyright 2000-2012, Morgan McGuire.
All rights reserved.
*/
@@ -28,16 +28,17 @@
#include "G3D/stringutils.h"
#include "G3D/PhysicsFrame.h"
#include "G3D/UprightFrame.h"
+#include "G3D/Frustum.h"
namespace G3D {
std::string CoordinateFrame::toXYZYPRDegreesString() const {
- UprightFrame uframe(*this);
+ float x,y,z,yaw,pitch,roll;
+ getXYZYPRDegrees(x,y,z,yaw,pitch,roll);
return format("CFrame::fromXYZYPRDegrees(% 5.1ff, % 5.1ff, % 5.1ff, % 5.1ff, % 5.1ff, % 5.1ff)",
- uframe.translation.x, uframe.translation.y, uframe.translation.z,
- toDegrees(uframe.yaw), toDegrees(uframe.pitch), 0.0f);
+ x,y,z,yaw,pitch,roll);
}
@@ -46,10 +47,12 @@ CoordinateFrame::CoordinateFrame(const Any& any) {
const std::string& n = toUpper(any.name());
- if (beginsWith(n, "VECTOR3")) {
- translation = any;
+ if (beginsWith(n, "VECTOR3") || beginsWith(n, "POINT3")) {
+ translation = Point3(any);
} else if (beginsWith(n, "MATRIX3")) {
- rotation = any;
+ rotation = Matrix3(any);
+ } else if (beginsWith(n, "MATRIX4")) {
+ *this = Matrix4(any).approxCoordinateFrame();
} else if ((n == "CFRAME") || (n == "COORDINATEFRAME")) {
any.verifyType(Any::TABLE, Any::ARRAY);
if (any.type() == Any::ARRAY) {
@@ -57,19 +60,15 @@ CoordinateFrame::CoordinateFrame(const Any& any) {
rotation = any[0];
translation = any[1];
} else {
- for (Any::AnyTable::Iterator it = any.table().begin(); it.hasMore(); ++it) {
- const std::string& n = toLower(it->key);
- if (n == "translation") {
- translation = Vector3(it->value);
- } else if (n == "rotation") {
- rotation = Matrix3(it->value);
- } else {
- any.verify(false, "Illegal table key: " + it->key);
- }
- }
+ AnyTableReader r(any);
+ r.getIfPresent("translation", translation);
+ r.getIfPresent("rotation", rotation);
+ r.verifyDone();
}
} else if (beginsWith(n, "PHYSICSFRAME") || beginsWith(n, "PFRAME")) {
*this = PhysicsFrame(any);
+// } else if (beginsWith(n, "UPRIGHTFRAME") || beginsWith(n, "UFRAME")) {
+// *this = UprightFrame(any);
} else {
any.verifyName("CFrame::fromXYZYPRDegrees", "CoordinateFrame::fromXYZYPRDegrees");
any.verifyType(Any::ARRAY);
@@ -78,18 +77,18 @@ CoordinateFrame::CoordinateFrame(const Any& any) {
int s = any.size();
*this = fromXYZYPRDegrees(any[0], any[1], any[2],
- (s > 3) ? any[3].number() : 0.0f,
- (s > 4) ? any[4].number() : 0.0f,
- (s > 5) ? any[5].number() : 0.0f);
+ (s > 3) ? (float)any[3].number() : 0.0f,
+ (s > 4) ? (float)any[4].number() : 0.0f,
+ (s > 5) ? (float)any[5].number() : 0.0f);
}
}
-CoordinateFrame::operator Any() const {
+Any CoordinateFrame::toAny() const {
float x, y, z, yaw, pitch, roll;
getXYZYPRDegrees(x, y, z, yaw, pitch, roll);
Any a(Any::ARRAY, "CFrame::fromXYZYPRDegrees");
- a.append(x, y, z, yaw);
+ a.append(x, y, z);
if ( ! G3D::fuzzyEq(yaw, 0.0f) || ! G3D::fuzzyEq(pitch, 0.0f) || ! G3D::fuzzyEq(roll, 0.0f)) {
a.append(yaw);
if (! G3D::fuzzyEq(pitch, 0.0f) || ! G3D::fuzzyEq(roll, 0.0f)) {
@@ -114,11 +113,7 @@ CoordinateFrame::CoordinateFrame() :
CoordinateFrame CoordinateFrame::fromXYZYPRRadians(float x, float y, float z, float yaw,
float pitch, float roll) {
- Matrix3 rotation = Matrix3::fromAxisAngle(Vector3::unitY(), yaw);
-
- rotation = Matrix3::fromAxisAngle(rotation.column(0), pitch) * rotation;
- rotation = Matrix3::fromAxisAngle(rotation.column(2), roll) * rotation;
-
+ const Matrix3& rotation = Matrix3::fromEulerAnglesYXZ(yaw, pitch, roll);
const Vector3 translation(x, y, z);
return CoordinateFrame(rotation, translation);
@@ -131,28 +126,7 @@ void CoordinateFrame::getXYZYPRRadians(float& x, float& y, float& z,
y = translation.y;
z = translation.z;
- const Vector3& look = lookVector();
-
- if (abs(look.y) > 0.99f) {
- // Looking nearly straight up or down
-
- yaw = G3D::pi() + atan2(look.x, look.z);
- pitch = asin(look.y);
- roll = 0.0f;
-
- } else {
-
- // Yaw cannot be affected by others, so pull it first
- yaw = G3D::pi() + atan2(look.x, look.z);
-
- // Pitch is the elevation of the yaw vector
- pitch = asin(look.y);
-
- Vector3 actualRight = rightVector();
- Vector3 expectedRight = look.cross(Vector3::unitY());
-
- roll = 0;//acos(actualRight.dot(expectedRight)); TODO
- }
+ rotation.toEulerAnglesYXZ(yaw, pitch, roll);
}
@@ -234,24 +208,55 @@ std::string CoordinateFrame::toXML() const {
Plane CoordinateFrame::toObjectSpace(const Plane& p) const {
+ // TODO
Vector3 N, P;
double d;
p.getEquation(N, d);
P = N * (float)d;
P = pointToObjectSpace(P);
N = normalToObjectSpace(N);
+ debugAssertM(isFinite(d), "Not implemented for infinite planes");
return Plane(N, P);
}
-Plane CoordinateFrame::toWorldSpace(const Plane& p) const {
- Vector3 N, P;
- double d;
- p.getEquation(N, d);
- P = N * (float)d;
- P = pointToWorldSpace(P);
- N = normalToWorldSpace(N);
- return Plane(N, P);
+Frustum CoordinateFrame::toWorldSpace(const Frustum& f) const {
+ Frustum g;
+ g.vertexPos.resize(f.vertexPos.size());
+ g.faceArray.resize(f.faceArray.size());
+
+ for (int i = 0; i < f.vertexPos.size(); ++i) {
+ g.vertexPos[i] = toWorldSpace(f.vertexPos[i]);
+ }
+ for (int i = 0; i < f.faceArray.size(); ++i) {
+ g.faceArray[i].plane = toWorldSpace(f.faceArray[i].plane);
+ for (int j = 0; j < 4; ++j) {
+ g.faceArray[i].vertexIndex[j] = f.faceArray[i].vertexIndex[j];
+ }
+ }
+
+ return g;
+}
+
+
+Plane CoordinateFrame::toWorldSpace(const Plane& plane) const {
+ // Since there is no scale factor, we don't have to
+ // worry about the inverse transpose of the normal.
+ Vector3 normal;
+ float d;
+
+ plane.getEquation(normal, d);
+
+ const Vector3& newNormal = rotation * normal;
+
+ if (isFinite(d)) {
+ d = (newNormal * -d + translation).dot(newNormal);
+ return Plane(newNormal, newNormal * d);
+ } else {
+ // When d is infinite, we can't multiply 0's by it without
+ // generating NaNs.
+ return Plane::fromEquation(newNormal.x, newNormal.y, newNormal.z, d);
+ }
}
@@ -285,6 +290,20 @@ Capsule CoordinateFrame::toWorldSpace(const Capsule& c) const {
}
+void CoordinateFrame::toWorldSpace(const AABox& b, AABox& result) const {
+ if (b.isEmpty()) {
+ result = b;
+ } else if (! b.isFinite()) {
+ // We can't combine infinite elements under a matrix
+ // multiplication: if the computation performs inf-inf we'll
+ // get NaN. So treat the box as infinite in all directions.
+ result = AABox::inf();
+ } else {
+ toWorldSpace(Box(b)).getBounds(result);
+ }
+}
+
+
Box CoordinateFrame::toWorldSpace(const AABox& b) const {
Box b2(b);
return toWorldSpace(b2);
@@ -292,18 +311,17 @@ Box CoordinateFrame::toWorldSpace(const AABox& b) const {
Box CoordinateFrame::toWorldSpace(const Box& b) const {
- Box out(b);
-
- for (int i = 0; i < 8; ++i) {
- out._corner[i] = pointToWorldSpace(b._corner[i]);
- debugAssert(! isNaN(out._corner[i].x));
+ if(!b.isFinite()) {
+ return b;
}
-
+ Box out(b);
+ out._center = pointToWorldSpace(b._center);
for (int i = 0; i < 3; ++i) {
- out._axis[i] = vectorToWorldSpace(b._axis[i]);
+ out._edgeVector[i] = vectorToWorldSpace(out._edgeVector[i]);
}
- out._center = pointToWorldSpace(b._center);
+ out._area = b._area;
+ out._volume = b._volume;
return out;
}
@@ -376,11 +394,11 @@ void CoordinateFrame::lookAt(
}
up -= look * look.dot(up);
- up.unitize();
+ up = up.direction();
Vector3 z = -look;
Vector3 x = -z.cross(up);
- x.unitize();
+ x = x.direction();
Vector3 y = z.cross(x);
@@ -390,6 +408,14 @@ void CoordinateFrame::lookAt(
}
+void CoordinateFrame::moveTowards(const CoordinateFrame& goal, float maxTranslation, float maxRotation) {
+ translation.moveTowards(goal.translation, maxTranslation);
+ Quat q(rotation);
+ q.moveTowards(Quat(goal.rotation), maxRotation);
+ rotation = Matrix3(q);
+}
+
+
CoordinateFrame CoordinateFrame::lerp(
const CoordinateFrame& other,
float alpha) const {
diff --git a/dep/g3dlite/source/Crypto.cpp b/dep/g3dlite/source/Crypto.cpp
index c69b23375ce..8d54fbeeac7 100644
--- a/dep/g3dlite/source/Crypto.cpp
+++ b/dep/g3dlite/source/Crypto.cpp
@@ -11,7 +11,7 @@
#include "G3D/platform.h"
#include "G3D/Crypto.h"
#include "G3D/g3dmath.h"
-#include <zlib.h>
+#include "zlib.h"
namespace G3D {
@@ -64,7 +64,8 @@ int Crypto::numSmallPrimes() {
}
uint32 Crypto::crc32(const void* byte, size_t numBytes) {
- return ::crc32(::crc32(0, Z_NULL, 0), static_cast<const Bytef *>(byte), numBytes);
+ alwaysAssertM(numBytes < 0xFFFFFFFF, "Not implemented for arrays larger than 2^32 bytes");
+ return ::crc32(::crc32(0, Z_NULL, 0), static_cast<const Bytef *>(byte), (int)numBytes);
}
} // G3D
diff --git a/dep/g3dlite/source/Crypto_md5.cpp b/dep/g3dlite/source/Crypto_md5.cpp
index c7ee535d61e..6fca6383f93 100644
--- a/dep/g3dlite/source/Crypto_md5.cpp
+++ b/dep/g3dlite/source/Crypto_md5.cpp
@@ -38,9 +38,9 @@ typedef unsigned int md5_word_t; /* 32-bit word */
/* Define the state of the MD5 Algorithm. */
typedef struct md5_state_s {
- md5_word_t count[2]; /* message length in bits, lsw first */
- md5_word_t abcd[4]; /* digest buffer */
- md5_byte_t buf[64]; /* accumulate block */
+ md5_word_t count[2]; /* message length in bits, lsw first */
+ md5_word_t abcd[4]; /* digest buffer */
+ md5_byte_t buf[64]; /* accumulate block */
} md5_state_t;
#ifdef __cplusplus
@@ -55,7 +55,7 @@ static void md5_init(md5_state_t *pms);
static void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes);
/* Finish the message and return the digest. */
-void md5_finish(md5_state_t *pms, md5_byte_t digest[16]);
+static void md5_finish(md5_state_t *pms, md5_byte_t digest[16]);
#ifdef __cplusplus
}
#endif
@@ -100,7 +100,7 @@ MD5Hash Crypto::md5(const void* data, size_t n) {
This code implements the MD5 Algorithm defined in RFC 1321, whose
text is available at
- http://www.ietf.org/rfc/rfc1321.txt
+ http://www.ietf.org/rfc/rfc1321.txt
The code is derived from the text of the RFC, including the test suite
(section A.5) but excluding the rest of Appendix A. It does not include
any code or documentation that is identified in the RFC as being
@@ -111,14 +111,14 @@ MD5Hash Crypto::md5(const void* data, size_t n) {
that follows (in reverse chronological order):
2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order
- either statically or dynamically; added missing #include <string.h>
- in library.
+ either statically or dynamically; added missing #include <string.h>
+ in library.
2002-03-11 lpd Corrected argument list for main(), and added int return
- type, in test program and T value program.
+ type, in test program and T value program.
2002-02-21 lpd Added missing #include <stdio.h> in test program.
2000-07-03 lpd Patched to eliminate warnings about "constant is
- unsigned in ANSI C, signed in traditional"; made test program
- self-checking.
+ unsigned in ANSI C, signed in traditional"; made test program
+ self-checking.
1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5).
1999-05-03 lpd Original version.
@@ -220,8 +220,8 @@ static void
md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/)
{
md5_word_t
- a = pms->abcd[0], b = pms->abcd[1],
- c = pms->abcd[2], d = pms->abcd[3];
+ a = pms->abcd[0], b = pms->abcd[1],
+ c = pms->abcd[2], d = pms->abcd[3];
md5_word_t t;
#if BYTE_ORDER > 0
/* Define storage only for big-endian CPUs. */
@@ -234,51 +234,51 @@ md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/)
{
#if BYTE_ORDER == 0
- /*
- * Determine dynamically whether this is a big-endian or
- * little-endian machine, since we can use a more efficient
- * algorithm on the latter.
- */
- static const int w = 1;
-
- if (*((const md5_byte_t *)&w)) /* dynamic little-endian */
+ /*
+ * Determine dynamically whether this is a big-endian or
+ * little-endian machine, since we can use a more efficient
+ * algorithm on the latter.
+ */
+ static const int w = 1;
+
+ if (*((const md5_byte_t *)&w)) /* dynamic little-endian */
#endif
-#if BYTE_ORDER <= 0 /* little-endian */
- {
- /*
- * On little-endian machines, we can process properly aligned
- * data without copying it.
- */
- if (!((data - (const md5_byte_t *)0) & 3)) {
- /* data are properly aligned */
- X = (const md5_word_t *)data;
- } else {
- /* not aligned */
- memcpy(xbuf, data, 64);
- X = xbuf;
- }
- }
+#if BYTE_ORDER <= 0 /* little-endian */
+ {
+ /*
+ * On little-endian machines, we can process properly aligned
+ * data without copying it.
+ */
+ if (!((data - (const md5_byte_t *)0) & 3)) {
+ /* data are properly aligned */
+ X = (const md5_word_t *)data;
+ } else {
+ /* not aligned */
+ memcpy(xbuf, data, 64);
+ X = xbuf;
+ }
+ }
#endif
#if BYTE_ORDER == 0
- else /* dynamic big-endian */
+ else /* dynamic big-endian */
#endif
-#if BYTE_ORDER >= 0 /* big-endian */
- {
- /*
- * On big-endian machines, we must arrange the bytes in the
- * right order.
- */
- const md5_byte_t *xp = data;
- int i;
+#if BYTE_ORDER >= 0 /* big-endian */
+ {
+ /*
+ * On big-endian machines, we must arrange the bytes in the
+ * right order.
+ */
+ const md5_byte_t *xp = data;
+ int i;
# if BYTE_ORDER == 0
- X = xbuf; /* (dynamic only) */
+ X = xbuf; /* (dynamic only) */
# else
-# define xbuf X /* (static only) */
+# define xbuf X /* (static only) */
# endif
- for (i = 0; i < 16; ++i, xp += 4)
- xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
- }
+ for (i = 0; i < 16; ++i, xp += 4)
+ xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
+ }
#endif
}
@@ -416,56 +416,56 @@ md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes)
md5_word_t nbits = (md5_word_t)(nbytes << 3);
if (nbytes <= 0)
- return;
+ return;
/* Update the message length. */
pms->count[1] += nbytes >> 29;
pms->count[0] += nbits;
if (pms->count[0] < nbits)
- pms->count[1]++;
+ pms->count[1]++;
/* Process an initial partial block. */
if (offset) {
- int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
-
- memcpy(pms->buf + offset, p, copy);
- if (offset + copy < 64)
- return;
- p += copy;
- left -= copy;
- md5_process(pms, pms->buf);
+ int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
+
+ memcpy(pms->buf + offset, p, copy);
+ if (offset + copy < 64)
+ return;
+ p += copy;
+ left -= copy;
+ md5_process(pms, pms->buf);
}
/* Process full blocks. */
for (; left >= 64; p += 64, left -= 64)
- md5_process(pms, p);
+ md5_process(pms, p);
/* Process a final partial block. */
if (left)
- memcpy(pms->buf, p, left);
+ memcpy(pms->buf, p, left);
}
void
md5_finish(md5_state_t *pms, md5_byte_t digest[16])
{
static const md5_byte_t pad[64] = {
- 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
md5_byte_t data[8];
int i;
/* Save the length before padding. */
for (i = 0; i < 8; ++i)
- data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3));
+ data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3));
/* Pad to 56 bytes mod 64. */
md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1);
/* Append the length. */
md5_append(pms, data, 8);
for (i = 0; i < 16; ++i)
- digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3));
+ digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3));
}
}
diff --git a/dep/g3dlite/source/Cylinder.cpp b/dep/g3dlite/source/Cylinder.cpp
index 7a7b9f9440d..32d14e96bb8 100644
--- a/dep/g3dlite/source/Cylinder.cpp
+++ b/dep/g3dlite/source/Cylinder.cpp
@@ -22,7 +22,7 @@
namespace G3D {
Cylinder::Cylinder(class BinaryInput& b) {
- deserialize(b);
+ deserialize(b);
}
@@ -31,48 +31,48 @@ Cylinder::Cylinder() {
Cylinder::Cylinder(const Vector3& _p1, const Vector3& _p2, float _r)
- : p1(_p1), p2(_p2), mRadius(_r) {
+ : p1(_p1), p2(_p2), mRadius(_r) {
}
void Cylinder::serialize(class BinaryOutput& b) const {
- p1.serialize(b);
- p2.serialize(b);
- b.writeFloat64(mRadius);
+ p1.serialize(b);
+ p2.serialize(b);
+ b.writeFloat64(mRadius);
}
void Cylinder::deserialize(class BinaryInput& b) {
- p1.deserialize(b);
- p2.deserialize(b);
- mRadius = b.readFloat64();
+ p1.deserialize(b);
+ p2.deserialize(b);
+ mRadius = (float)b.readFloat64();
}
Line Cylinder::axis() const {
- return Line::fromTwoPoints(p1, p2);
+ return Line::fromTwoPoints(p1, p2);
}
float Cylinder::radius() const {
- return mRadius;
+ return mRadius;
}
float Cylinder::volume() const {
- return
- (float)pi() * square(mRadius) * (p1 - p2).magnitude();
+ return
+ (float)pi() * square(mRadius) * (p1 - p2).magnitude();
}
float Cylinder::area() const {
- return
+ return
// Sides
- (twoPi() * mRadius) * height() +
+ ((float)twoPi() * mRadius) * height() +
// Caps
- twoPi() * square(mRadius);
+ (float)twoPi() * square(mRadius);
}
void Cylinder::getBounds(AABox& out) const {
diff --git a/dep/g3dlite/source/FileSystem.cpp b/dep/g3dlite/source/FileSystem.cpp
index f082937a908..32a84e77048 100644
--- a/dep/g3dlite/source/FileSystem.cpp
+++ b/dep/g3dlite/source/FileSystem.cpp
@@ -1,10 +1,10 @@
/**
- @file FileSystem.cpp
+ \file FileSystem.cpp
- @author Morgan McGuire, http://graphics.cs.williams.edu
+ \author Morgan McGuire, http://graphics.cs.williams.edu
- @author 2002-06-06
- @edited 2010-04-10
+ \author 2002-06-06
+ \edited 2010-10-10
*/
#include "G3D/FileSystem.h"
#include "G3D/System.h"
@@ -19,7 +19,7 @@
#include "G3D/BinaryInput.h"
#include "G3D/BinaryOutput.h"
-#ifdef G3D_WIN32
+#ifdef G3D_WINDOWS
// Needed for _getcwd
# include <direct.h>
@@ -36,16 +36,16 @@
# include <unistd.h>
# define _getcwd getcwd
# define _stat stat
-#endif
-
-#ifdef __CYGWIN__
-#define stat64 stat
+# define stricmp strcasecmp
+# define strnicmp strncasecmp
#endif
namespace G3D {
static FileSystem* common = NULL;
+GMutex FileSystem::mutex;
+
FileSystem& FileSystem::instance() {
init();
return *common;
@@ -70,24 +70,24 @@ FileSystem::FileSystem() : m_cacheLifetime(10) {}
/////////////////////////////////////////////////////////////
-bool FileSystem::Dir::contains(const std::string& f) const {
+bool FileSystem::Dir::contains(const std::string& f, bool caseSensitive) const {
for (int i = 0; i < nodeArray.size(); ++i) {
-# ifdef G3D_WIN32
- if (stricmp(f.c_str(), nodeArray[i].name.c_str()) == 0) {
- return true;
- }
-# else
+ if (caseSensitive) {
if (f == nodeArray[i].name) {
return true;
}
-# endif
+ } else if (stricmp(f.c_str(), nodeArray[i].name.c_str()) == 0) {
+ return true;
+ }
}
return false;
}
+
-void FileSystem::Dir::computeZipListing(const std::string& zipfile, const std::string& pathInsideZipfile) {
+void FileSystem::Dir::computeZipListing(const std::string& zipfile, const std::string& _pathInsideZipfile) {
#if _HAVE_ZIP /* G3DFIX: Use ZIP-library only if defined */
+ const std::string& pathInsideZipfile = FilePath::canonicalize(_pathInsideZipfile);
struct zip* z = zip_open( FilePath::removeTrailingSlash(zipfile).c_str(), ZIP_CHECKCONS, NULL );
debugAssert(z);
@@ -99,22 +99,23 @@ void FileSystem::Dir::computeZipListing(const std::string& zipfile, const std::s
zip_stat_index( z, i, ZIP_FL_NOCASE, &info );
// Fully-qualified name of a file inside zipfile
- std::string name = info.name;
+ std::string name = FilePath::canonicalize(info.name);
if (beginsWith(name, pathInsideZipfile)) {
// We found something inside the directory we were looking for,
- // so the directory itself must exist
+ // so the directory itself must exist
exists = true;
// For building the cached directory listing, extract only elements that do not contain
// additional subdirectories.
- int start = pathInsideZipfile.size();
- if ((int(name.length()) > start) && isSlash(name[start])) {
+ size_t start = pathInsideZipfile.size();
+ if ((name.length() > start) && isSlash(name[start])) {
++start;
}
- int end = findSlash(name, start);
- if (end == -1) {
+
+ size_t end = findSlash(name, start);
+ if (end == std::string::npos) {
// There are no more slashes; add this name
name = name.substr(start);
if (alreadyAdded.insert(name)) {
@@ -126,8 +127,8 @@ void FileSystem::Dir::computeZipListing(const std::string& zipfile, const std::s
// There are more slashes, indicating that this is a directory
name = name.substr(start, end);
if (alreadyAdded.insert(name)) {
- Entry& e = nodeArray.next();
- e.name = name;
+ Entry& e = nodeArray.next();
+ e.name = FilePath::removeTrailingSlash(name);
e.type = DIR_TYPE;
}
}
@@ -142,7 +143,7 @@ void FileSystem::Dir::computeZipListing(const std::string& zipfile, const std::s
FileSystem::Dir& FileSystem::getContents(const std::string& path, bool forceUpdate) {
const std::string& key =
-# if defined(G3D_WIN32)
+# if defined(G3D_WINDOWS)
FilePath::canonicalize(FilePath::removeTrailingSlash(toLower(FilePath::canonicalize(resolve(path)))));
# else
FilePath::canonicalize(FilePath::removeTrailingSlash(FilePath::canonicalize(resolve(path))));
@@ -156,10 +157,17 @@ FileSystem::Dir& FileSystem::getContents(const std::string& path, bool forceUpda
// Out of date: update
dir.lastChecked = now;
-
- struct _stat st;
- const bool exists = _stat(key.c_str(), &st) != -1;
- const bool isDirectory = (st.st_mode & S_IFDIR) != 0;
+# ifdef G3D_WINDOWS
+ // On windows, we have to use GetFileAttributes (http://msdn.microsoft.com/en-us/library/aa364944(v=vs.85).aspx) instead of
+ // stat in order to work with network shares
+ const DWORD st = GetFileAttributesA(key.c_str());
+ const bool exists = (st != INVALID_FILE_ATTRIBUTES);
+ const bool isDirectory = (st & FILE_ATTRIBUTE_DIRECTORY) != 0;
+# else
+ struct _stat st;
+ const bool exists = _stat(key.c_str(), &st) != -1;
+ const bool isDirectory = (st.st_mode & S_IFDIR) != 0;
+# endif
// Does this path exist on the real filesystem?
if (exists && isDirectory) {
@@ -168,7 +176,7 @@ FileSystem::Dir& FileSystem::getContents(const std::string& path, bool forceUpda
if (isDirectory) {
dir.exists = true;
// Update contents
-# ifdef G3D_WIN32
+# ifdef G3D_WINDOWS
const std::string& filespec = FilePath::concat(key, "*");
struct _finddata_t fileinfo;
intptr_t handle = _findfirst(filespec.c_str(), &fileinfo);
@@ -238,7 +246,6 @@ FileSystem::Dir& FileSystem::getContents(const std::string& path, bool forceUpda
// There is a zipfile somewhere in the path. Does
// the rest of the path exist inside the zipfile?
dir.inZipfile = true;
-
dir.computeZipListing(zip, path.substr(zip.length() + 1));
}
}
@@ -248,27 +255,24 @@ FileSystem::Dir& FileSystem::getContents(const std::string& path, bool forceUpda
}
-bool FileSystem::_inZipfile(const std::string& path, std::string& z) {
+bool FileSystem::_inZipfile(const std::string& _path, std::string& z) {
+ const std::string& path = FilePath::expandEnvironmentVariables(_path);
+
// Reject trivial cases before parsing
- if (path.find('.') == std::string::npos) {
- // There is no zipfile possible, since G3D requires
- // an extension on zipfiles.
- return false;
- }
// Look at all sub-paths containing periods.
// For each, ask if it is a zipfile.
- int current = 0;
+ size_t current = 0;
current = path.find('.', current);
- while (current != -1) {
+ while (current != std::string::npos) {
// xxxxx/foo.zip/yyyyy
current = path.find('.', current);
// Look forward for the next slash
- int s = findSlash(path, current);
+ size_t s = findSlash(path, current);
- if (s == -1) {
+ if (s == std::string::npos) {
// No more slashes
return false;
}
@@ -286,17 +290,17 @@ bool FileSystem::_inZipfile(const std::string& path, std::string& z) {
}
-bool FileSystem::_isZipfile(const std::string& filename) {
- if (FilePath::ext(filename).empty()) {
- return false;
- }
+bool FileSystem::_isZipfile(const std::string& _filename) {
+ const std::string& filename = FilePath::canonicalize(FilePath::expandEnvironmentVariables(_filename));
+
+
FILE* f = fopen(FilePath::removeTrailingSlash(filename).c_str(), "r");
if (f == NULL) {
return false;
}
uint8 header[4];
- fread(header, 4, 1, f);
+ (void)fread(header, 4, 1, f);
const uint8 zipHeader[4] = {0x50, 0x4b, 0x03, 0x04};
for (int i = 0; i < 4; ++i) {
@@ -311,7 +315,9 @@ bool FileSystem::_isZipfile(const std::string& filename) {
}
-FILE* FileSystem::_fopen(const char* filename, const char* mode) {
+FILE* FileSystem::_fopen(const char* _filename, const char* mode) {
+ const std::string& filename = FilePath::canonicalize(FilePath::expandEnvironmentVariables(_filename));
+
for (const char* m = mode; *m != '\0'; ++m) {
if (*m == 'w') {
// Purge the cache entry for the parent of this directory
@@ -319,11 +325,15 @@ FILE* FileSystem::_fopen(const char* filename, const char* mode) {
break;
}
}
- return ::fopen(filename, mode);
+
+ markFileUsed(filename);
+ return ::fopen(filename.c_str(), mode);
}
-void FileSystem::_clearCache(const std::string& path) {
+void FileSystem::_clearCache(const std::string& _path) {
+ const std::string& path = FilePath::expandEnvironmentVariables(_path);
+
if ((path == "") || FilePath::isRoot(path)) {
m_cache.clear();
} else {
@@ -331,7 +341,7 @@ void FileSystem::_clearCache(const std::string& path) {
m_cache.getKeys(keys);
const std::string& prefix =
-# ifdef G3D_WIN32
+# ifdef G3D_WINDOWS
toLower(FilePath::canonicalize(FilePath::removeTrailingSlash(_resolve(path))));
# else
FilePath::canonicalize(FilePath::removeTrailingSlash(_resolve(path)));
@@ -353,8 +363,9 @@ void FileSystem::_setCacheLifetime(float t) {
}
-void FileSystem::_createDirectory(const std::string& dir) {
-
+void FileSystem::_createDirectory(const std::string& _dir) {
+ const std::string& dir = FilePath::expandEnvironmentVariables(_dir);
+
if (dir == "") {
return;
}
@@ -395,7 +406,7 @@ void FileSystem::_createDirectory(const std::string& dir) {
if (! _exists(p)) {
// Windows only requires one argument to mkdir,
// where as unix also requires the permissions.
-# ifndef G3D_WIN32
+# ifndef G3D_WINDOWS
mkdir(p.c_str(), 0777);
# else
_mkdir(p.c_str());
@@ -407,8 +418,10 @@ void FileSystem::_createDirectory(const std::string& dir) {
}
-void FileSystem::_copyFile(const std::string& source, const std::string& dest) {
-# ifdef G3D_WIN32
+void FileSystem::_copyFile(const std::string& _source, const std::string& _dest) {
+ const std::string& source = FilePath::expandEnvironmentVariables(_source);
+ const std::string& dest = FilePath::expandEnvironmentVariables(_dest);
+# ifdef G3D_WINDOWS
// TODO: handle case where srcPath is in a zipfile
CopyFileA(source.c_str(), dest.c_str(), FALSE);
_clearCache(FilePath::parent(_resolve(dest)));
@@ -422,10 +435,11 @@ void FileSystem::_copyFile(const std::string& source, const std::string& dest) {
}
-bool FileSystem::_exists(const std::string& f, bool trustCache) {
+bool FileSystem::_exists(const std::string& _f, bool trustCache, bool caseSensitive) {
+ const std::string& f = FilePath::expandEnvironmentVariables(_f);
if (FilePath::isRoot(f)) {
-# ifdef G3D_WIN32
+# ifdef G3D_WINDOWS
const std::string& winname = toLower(f.substr(0, 1)) + ":\\";
return _drives().contains(winname);
# else
@@ -433,10 +447,11 @@ bool FileSystem::_exists(const std::string& f, bool trustCache) {
# endif
}
- std::string path = FilePath::removeTrailingSlash(f);
- std::string parentPath = FilePath::parent(path);
+ const std::string& path = FilePath::removeTrailingSlash(f);
+ const std::string& parentPath = FilePath::parent(path);
- const Dir& entry = getContents(parentPath, ! trustCache);
+ const bool forceUpdate = ! trustCache;
+ const Dir& entry = getContents(parentPath, forceUpdate);
if (FilePath::containsWildcards(f)) {
if (! entry.exists) {
@@ -446,15 +461,9 @@ bool FileSystem::_exists(const std::string& f, bool trustCache) {
const std::string& pattern = FilePath::baseExt(path);
-# ifdef G3D_WIN32
- static const int flags = FNM_CASEFOLD;
-# else
- static const int flags = 0;
-# endif
-
// See if any element of entry matches the wild card
for (int i = 0; i < entry.nodeArray.size(); ++i) {
- if (FilePath::matches(entry.nodeArray[i].name, pattern, flags)) {
+ if (FilePath::matches(entry.nodeArray[i].name, pattern, caseSensitive)) {
return true;
}
}
@@ -463,12 +472,13 @@ bool FileSystem::_exists(const std::string& f, bool trustCache) {
return false;
} else {
- return entry.exists && entry.contains(FilePath::baseExt(path));
+ return entry.exists && entry.contains(FilePath::baseExt(path), caseSensitive);
}
}
-bool FileSystem::_isDirectory(const std::string& filename) {
+bool FileSystem::_isDirectory(const std::string& _filename) {
+ const std::string& filename = FilePath::expandEnvironmentVariables(_filename);
// TODO: work with zipfiles and cache
struct _stat st;
const bool exists = _stat(FilePath::removeTrailingSlash(filename).c_str(), &st) != -1;
@@ -476,14 +486,33 @@ bool FileSystem::_isDirectory(const std::string& filename) {
}
-std::string FileSystem::_resolve(const std::string& filename, const std::string& cwd) {
+void FileSystem::_removeFile(const std::string& path) {
+ alwaysAssertM(! inZipfile(path), "Cannot invoke removeFile() on files inside zipfiles.");
+ Array<std::string> files;
+ getFiles(path, files, true);
+
+ for (int i = 0; i < files.size(); ++i) {
+ const std::string& filename = files[i];
+ int retval = ::remove(filename.c_str());
+ (void)retval;
+ }
+
+ // Remove from cache
+ _clearCache(FilePath::parent(path));
+}
+
+
+std::string FileSystem::_resolve(const std::string& _filename, const std::string& _cwd) {
+ const std::string& filename = FilePath::expandEnvironmentVariables(_filename);
+ const std::string& cwd = FilePath::expandEnvironmentVariables(_cwd);
+
if (filename.size() >= 1) {
if (isSlash(filename[0])) {
// Already resolved
return filename;
} else {
- #ifdef G3D_WIN32
+ #ifdef G3D_WINDOWS
if ((filename.size() >= 2) && (filename[1] == ':')) {
// There is a drive spec on the front.
if ((filename.size() >= 3) && isSlash(filename[2])) {
@@ -511,12 +540,29 @@ std::string FileSystem::_currentDirectory() {
static const int N = 2048;
char buffer[N];
- _getcwd(buffer, N);
+ (void)_getcwd(buffer, N);
return std::string(buffer);
}
-bool FileSystem::_isNewer(const std::string& src, const std::string& dst) {
+static Set<std::string> _filesUsed;
+
+void FileSystem::markFileUsed(const std::string& filename) {
+ mutex.lock();
+ _filesUsed.insert(filename);
+ mutex.unlock();
+}
+
+
+const Set<std::string>& FileSystem::usedFiles() {
+ return _filesUsed;
+}
+
+
+bool FileSystem::_isNewer(const std::string& _src, const std::string& _dst) {
+ const std::string& src = FilePath::expandEnvironmentVariables(_src);
+ const std::string& dst = FilePath::expandEnvironmentVariables(_dst);
+
// TODO: work with cache and zipfiles
struct _stat sts;
bool sexists = _stat(src.c_str(), &sts) != -1;
@@ -528,7 +574,9 @@ bool FileSystem::_isNewer(const std::string& src, const std::string& dst) {
}
-int64 FileSystem::_size(const std::string& filename) {
+int64 FileSystem::_size(const std::string& _filename) {
+ const std::string& filename = FilePath::canonicalize(FilePath::expandEnvironmentVariables(_filename));
+
struct stat64 st;
int result = stat64(filename.c_str(), &st);
@@ -544,6 +592,7 @@ int64 FileSystem::_size(const std::string& filename) {
struct zip_stat info;
zip_stat_init( &info ); // Docs unclear if zip_stat_init is required.
int success = zip_stat( z, contents.c_str(), ZIP_FL_NOCASE, &info );
+ (void) success;
debugAssertM(success == 0, zip + ": " + contents + ": zip stat failed.");
requiredMem = info.size;
}
@@ -553,7 +602,7 @@ int64 FileSystem::_size(const std::string& filename) {
#endif
return -1;
#if _HAVE_ZIP /* G3DFIX: Use ZIP-library only if defined */
- }
+ }
#endif
}
@@ -561,7 +610,12 @@ int64 FileSystem::_size(const std::string& filename) {
}
-void FileSystem::listHelper(const std::string& shortSpec, const std::string& parentPath, Array<std::string>& result, const ListSettings& settings) {
+void FileSystem::listHelper
+(const std::string& shortSpec,
+ const std::string& parentPath,
+ Array<std::string>& result,
+ const ListSettings& settings) {
+
Dir& dir = getContents(parentPath, false);
if (! dir.exists) {
@@ -573,8 +627,10 @@ void FileSystem::listHelper(const std::string& shortSpec, const std::string& par
// See if it matches the spec
if (FilePath::matches(entry.name, shortSpec, settings.caseSensitive)) {
- if ((entry.type == UNKNOWN) && ! (settings.files && settings.directories)) {
- // Update the type
+ if ((entry.type == UNKNOWN) &&
+ (! (settings.files && settings.directories) ||
+ settings.recursive)) {
+ // Update the type: it is unknown and we'll need to branch onit below
entry.type = isDirectory(FilePath::concat(parentPath, entry.name)) ? DIR_TYPE : FILE_TYPE;
}
@@ -589,15 +645,23 @@ void FileSystem::listHelper(const std::string& shortSpec, const std::string& par
}
}
} // match
+
+ if (settings.recursive) {
+ if (entry.type == UNKNOWN) {
+ entry.type = isDirectory(FilePath::concat(parentPath, entry.name)) ? DIR_TYPE : FILE_TYPE;
+ }
- if (settings.recursive && (entry.type == DIR_TYPE)) {
- listHelper(shortSpec, FilePath::concat(parentPath, entry.name), result, settings);
+ if (entry.type == DIR_TYPE) {
+ listHelper(shortSpec, FilePath::concat(parentPath, entry.name), result, settings);
+ }
}
} // for
}
-void FileSystem::_list(const std::string& spec, Array<std::string>& result, const ListSettings& settings) {
+void FileSystem::_list(const std::string& _spec, Array<std::string>& result, const ListSettings& settings) {
+ const std::string& spec = FilePath::expandEnvironmentVariables(_spec);
+
const std::string& shortSpec = FilePath::baseExt(spec);
const std::string& parentPath = FilePath::parent(spec);
@@ -606,7 +670,7 @@ void FileSystem::_list(const std::string& spec, Array<std::string>& result, cons
-#ifdef G3D_WIN32
+#ifdef G3D_WINDOWS
const Array<std::string>& FileSystem::_drives() {
if (m_winDrive.length() == 0) {
// See http://msdn.microsoft.com/en-us/library/aa364975(VS.85).aspx
@@ -615,10 +679,10 @@ const Array<std::string>& FileSystem::_drives() {
GetLogicalDriveStringsA(bufSize, bufData);
// Drive list is a series of NULL-terminated strings, itself terminated with a NULL.
- for (int i = 0; bufData[i] != '\0'; ++i) {
+ for (size_t i = 0; bufData[i] != '\0'; ++i) {
const char* thisString = bufData + i;
m_winDrive.append(toLower(thisString));
- i += strlen(thisString) + 1;
+ i += strlen(thisString);
}
}
@@ -629,7 +693,7 @@ const Array<std::string>& FileSystem::_drives() {
/////////////////////////////////////////////////////////////////////
bool FilePath::isRoot(const std::string& f) {
-# ifdef G3D_WIN32
+# ifdef G3D_WINDOWS
if (f.length() < 2) {
return false;
}
@@ -644,9 +708,17 @@ bool FilePath::isRoot(const std::string& f) {
}
}
- if (isSlash(f[0]) && isSlash(f[1])) {
- // e.g., "\\foo\"
- return true;
+ // Windows shares are considered roots, but only if this does not include a path inside the share
+ if (isSlash(f[0]) && isSlash(f[1])) {
+ size_t i = f.find("/", 3);
+ size_t j = f.find("\\", 3);
+
+ if (i == std::string::npos) {
+ i = j;
+ }
+
+ // e.g., "\\foo\", "\\foo"
+ return ((i == std::string::npos) || (i == f.length() - 1));
}
# else
if (f == "/") {
@@ -678,8 +750,8 @@ std::string FilePath::concat(const std::string& dirname, const std::string& file
std::string FilePath::ext(const std::string& filename) {
- int i = filename.rfind(".");
- if (i >= 0) {
+ size_t i = filename.rfind(".");
+ if (i != std::string::npos) {
return filename.substr(i + 1, filename.length() - i);
} else {
return "";
@@ -688,16 +760,16 @@ std::string FilePath::ext(const std::string& filename) {
std::string FilePath::baseExt(const std::string& filename) {
- int i = findLastSlash(filename);
+ size_t i = findLastSlash(filename);
-# ifdef G3D_WIN32
- int j = filename.rfind(":");
- if ((i == -1) && (j >= 0)) {
+# ifdef G3D_WINDOWS
+ size_t j = filename.rfind(":");
+ if ((i == std::string::npos) && (j != std::string::npos)) {
i = j;
}
# endif
- if (i == -1) {
+ if (i == std::string::npos) {
return filename;
} else {
return filename.substr(i + 1, filename.length() - i);
@@ -707,8 +779,8 @@ std::string FilePath::baseExt(const std::string& filename) {
std::string FilePath::base(const std::string& path) {
std::string filename = baseExt(path);
- int i = filename.rfind(".");
- if (i == -1) {
+ size_t i = filename.rfind(".");
+ if (i == std::string::npos) {
// No extension
return filename;
} else {
@@ -718,16 +790,16 @@ std::string FilePath::base(const std::string& path) {
std::string FilePath::parent(const std::string& path) {
- int i = findLastSlash(removeTrailingSlash(path));
+ size_t i = findLastSlash(removeTrailingSlash(path));
-# ifdef G3D_WIN32
- int j = path.rfind(":");
- if ((i == -1) && (j >= 0)) {
+# ifdef G3D_WINDOWS
+ size_t j = path.rfind(":");
+ if ((i == std::string::npos) && (j != std::string::npos)) {
i = j;
}
# endif
- if (i == -1) {
+ if (i == std::string::npos) {
return "";
} else {
return path.substr(0, i + 1);
@@ -759,7 +831,6 @@ std::string FilePath::canonicalize(std::string x) {
return x;
}
-
void FilePath::parse
(const std::string& filename,
std::string& root,
@@ -796,7 +867,7 @@ void FilePath::parse
}
- } else if ((f.size() >= 2) & isSlash(f[0]) && isSlash(f[1])) {
+ } else if ((f.size() >= 2) && isSlash(f[0]) && isSlash(f[1])) {
// e.g. //foo
root = f.substr(0, 2);
@@ -816,7 +887,7 @@ void FilePath::parse
if (i != std::string::npos) {
// Make sure it is after the last slash!
- size_t j = iMax(f.rfind('/'), f.rfind('\\'));
+ size_t j = findLastSlash(f);
if ((j == std::string::npos) || (i > j)) {
ext = f.substr(i + 1, f.size() - i - 1);
f = f.substr(0, i);
@@ -827,7 +898,7 @@ void FilePath::parse
// Pull the basename off
{
// Find the last slash
- size_t i = iMax(f.rfind('/'), f.rfind('\\'));
+ size_t i = findLastSlash(f);
if (i == std::string::npos) {
@@ -860,7 +931,7 @@ void FilePath::parse
j = f.size();
}
- cur = iMin(i, j);
+ cur = min(i, j);
if (cur == std::string::npos) {
cur = f.size();
@@ -871,4 +942,86 @@ void FilePath::parse
}
}
+
+std::string FilePath::expandEnvironmentVariables(const std::string& path) {
+ // Search for pattern
+ size_t end = path.find_first_of('$', 0);
+ if (end == std::string::npos) {
+ // Pattern does not exist
+ return path;
+ }
+
+ size_t start = 0;
+ std::string result;
+ while (end != std::string::npos) {
+ const std::string& before = path.substr(start, end - start);
+ result += before;
+ start = end + 1;
+ std::string var;
+ if (path[start] == '(') {
+ // Search for close paren
+ end = path.find_first_of(')', start + 1);
+ if (end == std::string::npos) {
+ throw std::string("Missing close paren in environment variable in \"") + path + "\"";
+ }
+ var = path.substr(start + 1, end - start - 1);
+ } else {
+ // Search for slash or end of string
+ end = path.find_first_of('/', start);
+ size_t i = path.find_first_of('\\', start);
+ if ((size_t(i) != std::string::npos) && ((end == std::string::npos) || (size_t(i) < end))) {
+ end = i;
+ }
+ if (end == std::string::npos) {
+ // If the varible goes to the end of the string, it is the rest of the string
+ end = path.size();
+ } else {
+ --end;
+ }
+ var = path.substr(start, end - start + 1);
+ }
+
+ if (! var.empty()) {
+ const char* value = getenv(var.c_str());
+
+ if (value == NULL) {
+ throw (std::string("LocalLightingEnvironment variable \"") + var + "\" not defined for path \"" + path + "\"");
+ } else {
+ result += value;
+ }
+ } else {
+ // We just parsed an "empty" variable, which was probably a default share on Windows, e.g.,
+ // "\\mycomputer\c$", and not a variable name.
+ result += "$";
+ }
+
+ start = end + 1;
+ end = path.find_first_of('$', start);
+ }
+
+ // Paste on the remainder of the source path
+ if (start < path.size()) {
+ result += path.substr(start);
+ }
+
+ return result;
+}
+
+
+/** Generate a unique filename based on the provided hint */
+std::string FilePath::makeLegalFilename(const std::string& f, size_t maxLength) {
+ std::string tentative;
+
+ for (size_t i = 0; i < G3D::min(maxLength, f.size()); ++i) {
+ const char c = f[i];
+ if (isLetter(c) || isDigit(c) || (c == '-') || (c == '+') || (c == '=') || (c == '(') || (c == ')')) {
+ tentative += c;
+ } else {
+ tentative += "_";
+ }
+ }
+
+ return tentative;
+}
+
}
diff --git a/dep/g3dlite/source/GCamera.cpp b/dep/g3dlite/source/GCamera.cpp
deleted file mode 100644
index 0ffc7eb7374..00000000000
--- a/dep/g3dlite/source/GCamera.cpp
+++ /dev/null
@@ -1,511 +0,0 @@
-/**
- @file GCamera.cpp
-
- @author Morgan McGuire, http://graphics.cs.williams.edu
- @author Jeff Marsceill, 08jcm@williams.edu
-
- @created 2005-07-20
- @edited 2010-02-22
-*/
-#include "G3D/GCamera.h"
-#include "G3D/platform.h"
-#include "G3D/Rect2D.h"
-#include "G3D/BinaryInput.h"
-#include "G3D/BinaryOutput.h"
-#include "G3D/Ray.h"
-#include "G3D/Matrix4.h"
-#include "G3D/Any.h"
-#include "G3D/stringutils.h"
-
-namespace G3D {
-
-GCamera::GCamera(const Any& any) {
- any.verifyName("GCamera");
- any.verifyType(Any::TABLE);
- *this = GCamera();
-
- const Any::AnyTable& table = any.table();
- Any::AnyTable::Iterator it = table.begin();
- while (it.hasMore()) {
- const std::string& k = toUpper(it->key);
- if (k == "FOVDIRECTION") {
- const std::string& v = toUpper(it->value);
- if (v == "HORIZONTAL") {
- m_direction = HORIZONTAL;
- } else if (v == "VERTICAL") {
- m_direction = VERTICAL;
- } else {
- any.verify(false, "fovDirection must be \"HORIZONTAL\" or \"VERTICAL\"");
- }
- } else if (k == "COORDINATEFRAME") {
- m_cframe = it->value;
- } else if (k == "FOVDEGREES") {
- m_fieldOfView = toRadians(it->value.number());
- } else if (k == "NEARPLANEZ") {
- m_nearPlaneZ = it->value;
- } else if (k == "FARPLANEZ") {
- m_farPlaneZ = it->value;
- } else if (k == "PIXELOFFSET") {
- m_pixelOffset = it->value;
- } else {
- any.verify(false, std::string("Illegal key in table: ") + it->key);
- }
- ++it;
- }
-}
-
-
-GCamera::operator Any() const {
- Any any(Any::TABLE, "GCamera");
-
- any.set("fovDirection", std::string((m_direction == HORIZONTAL) ? "HORIZONTAL" : "VERTICAL"));
- any.set("fovDegrees", toDegrees(m_fieldOfView));
- any.set("nearPlaneZ", nearPlaneZ());
- any.set("farPlaneZ", farPlaneZ());
- any.set("coordinateFrame", coordinateFrame());
- any.set("pixelOffset", pixelOffset());
-
- return any;
-}
-
-
-GCamera::GCamera() {
- setNearPlaneZ(-0.2f);
- setFarPlaneZ(-150.0f);
- setFieldOfView((float)toRadians(90.0f), HORIZONTAL);
-}
-
-
-GCamera::GCamera(const Matrix4& proj, const CFrame& frame) {
- float left, right, bottom, top, nearval, farval;
- proj.getPerspectiveProjectionParameters(left, right, bottom, top, nearval, farval);
- setNearPlaneZ(-nearval);
- setFarPlaneZ(-farval);
- float x = right;
-
- // Assume horizontal field of view
- setFieldOfView(atan2(x, -m_nearPlaneZ) * 2.0f, HORIZONTAL);
- setCoordinateFrame(frame);
-}
-
-
-GCamera::~GCamera() {
-}
-
-
-void GCamera::getCoordinateFrame(CoordinateFrame& c) const {
- c = m_cframe;
-}
-
-
-void GCamera::setCoordinateFrame(const CoordinateFrame& c) {
- m_cframe = c;
-}
-
-
-void GCamera::setFieldOfView(float angle, FOVDirection dir) {
- debugAssert((angle < pi()) && (angle > 0));
-
- m_fieldOfView = angle;
- m_direction = dir;
-}
-
-
-float GCamera::imagePlaneDepth() const{
- return -m_nearPlaneZ;
-}
-
-float GCamera::viewportWidth(const Rect2D& viewport) const {
- // Compute the side of a square at the near plane based on our field of view
- float s = 2.0f * -m_nearPlaneZ * tan(m_fieldOfView * 0.5f);
-
- if (m_direction == VERTICAL) {
- s *= viewport.width() / viewport.height();
- }
-
- return s;
-}
-
-
-float GCamera::viewportHeight(const Rect2D& viewport) const {
- // Compute the side of a square at the near plane based on our field of view
- float s = 2.0f * -m_nearPlaneZ * tan(m_fieldOfView * 0.5f);
-
- debugAssert(m_fieldOfView < toRadians(180));
- if (m_direction == HORIZONTAL) {
- s *= viewport.height() / viewport.width();
- }
-
- return s;
-}
-
-
-Ray GCamera::worldRay(float x, float y, const Rect2D& viewport) const {
-
- int screenWidth = iFloor(viewport.width());
- int screenHeight = iFloor(viewport.height());
-
- Vector3 origin = m_cframe.translation;
-
- float cx = screenWidth / 2.0f;
- float cy = screenHeight / 2.0f;
-
- float vw = viewportWidth(viewport);
- float vh = viewportHeight(viewport);
-
- Vector3 direction = Vector3( (x - cx) * vw / screenWidth,
- -(y - cy) * vh / screenHeight,
- m_nearPlaneZ);
-
- direction = m_cframe.vectorToWorldSpace(direction);
-
- // Normalize the direction (we didn't do it before)
- direction = direction.direction();
-
- return Ray::fromOriginAndDirection(origin, direction);
-}
-
-
-void GCamera::getProjectPixelMatrix(const Rect2D& viewport, Matrix4& P) const {
- getProjectUnitMatrix(viewport, P);
- float screenWidth = viewport.width();
- float screenHeight = viewport.height();
-
- float sx = screenWidth / 2.0;
- float sy = screenHeight / 2.0;
-
- P = Matrix4(sx, 0, 0, sx + viewport.x0() - m_pixelOffset.x,
- 0, -sy, 0, sy + viewport.y0() + m_pixelOffset.y,
- 0, 0, 1, 0,
- 0, 0, 0, 1) * P;
-}
-
-
-void GCamera::getProjectUnitMatrix(const Rect2D& viewport, Matrix4& P) const {
-
- float screenWidth = viewport.width();
- float screenHeight = viewport.height();
-
- float r, l, t, b, n, f, x, y;
-
- float s = 1.0f;
- if (m_direction == VERTICAL) {
- y = -m_nearPlaneZ * tan(m_fieldOfView / 2);
- x = y * (screenWidth / screenHeight);
- s = screenHeight;
- } else { //m_direction == HORIZONTAL
- x = -m_nearPlaneZ * tan(m_fieldOfView / 2);
- y = x * (screenHeight / screenWidth);
- s = screenWidth;
- }
-
- n = -m_nearPlaneZ;
- f = -m_farPlaneZ;
- r = x - m_pixelOffset.x/s;
- l = -x - m_pixelOffset.x/s;
- t = y + m_pixelOffset.y/s;
- b = -y + m_pixelOffset.y/s;
-
- P = Matrix4::perspectiveProjection(l, r, b, t, n, f);
-}
-
-
-Vector3 GCamera::projectUnit(const Vector3& point, const Rect2D& viewport) const {
- Matrix4 M;
- getProjectUnitMatrix(viewport, M);
-
- Vector4 cameraSpacePoint(coordinateFrame().pointToObjectSpace(point), 1.0f);
- const Vector4& screenSpacePoint = M * cameraSpacePoint;
-
- return Vector3(screenSpacePoint.xyz() / screenSpacePoint.w);
-}
-
-Vector3 GCamera::project(const Vector3& point,
- const Rect2D& viewport) const {
-
- // Find the point in the homogeneous cube
- const Vector3& cube = projectUnit(point, viewport);
-
- return convertFromUnitToNormal(cube, viewport);
-}
-
-Vector3 GCamera::unprojectUnit(const Vector3& v, const Rect2D& viewport) const {
-
- const Vector3& projectedPoint = convertFromUnitToNormal(v, viewport);
-
- return unproject(projectedPoint, viewport);
-}
-
-
-Vector3 GCamera::unproject(const Vector3& v, const Rect2D& viewport) const {
-
- const float n = m_nearPlaneZ;
- const float f = m_farPlaneZ;
-
- float z;
-
- if (-f >= finf()) {
- // Infinite far plane
- z = 1.0f / (((-1.0f / n) * v.z) + 1.0f / n);
- } else {
- z = 1.0f / ((((1.0f / f) - (1.0f / n)) * v.z) + 1.0f / n);
- }
-
- const Ray& ray = worldRay(v.x - m_pixelOffset.x, v.y - m_pixelOffset.y, viewport);
-
- // Find out where the ray reaches the specified depth.
- const Vector3& out = ray.origin() + ray.direction() * -z / (ray.direction().dot(m_cframe.lookVector()));
-
- return out;
-}
-
-
-float GCamera::worldToScreenSpaceArea(float area, float z, const Rect2D& viewport) const {
- (void)viewport;
- if (z >= 0) {
- return finf();
- }
- return area * (float)square(imagePlaneDepth() / z);
-}
-
-
-void GCamera::getClipPlanes(
- const Rect2D& viewport,
- Array<Plane>& clip) const {
-
- Frustum fr;
- frustum(viewport, fr);
- clip.resize(fr.faceArray.size(), DONT_SHRINK_UNDERLYING_ARRAY);
- for (int f = 0; f < clip.size(); ++f) {
- clip[f] = fr.faceArray[f].plane;
- }
-}
-
-
-GCamera::Frustum GCamera::frustum(const Rect2D& viewport) const {
- Frustum f;
- frustum(viewport, f);
- return f;
-}
-
-
-void GCamera::frustum(const Rect2D& viewport, Frustum& fr) const {
-
- // The volume is the convex hull of the vertices definining the view
- // frustum and the light source point at infinity.
-
- const float x = viewportWidth(viewport) / 2;
- const float y = viewportHeight(viewport) / 2;
- const float zn = m_nearPlaneZ;
- const float zf = m_farPlaneZ;
- float xx, zz, yy;
-
- float halfFOV = m_fieldOfView * 0.5f;
-
- // This computes the normal, which is based on the complement of the
- // halfFOV angle, so the equations are "backwards"
- if (m_direction == VERTICAL) {
- yy = -cosf(halfFOV);
- xx = yy * viewport.height() / viewport.width();
- zz = -sinf(halfFOV);
- } else {
- xx = -cosf(halfFOV);
- yy = xx * viewport.width() / viewport.height();
- zz = -sinf(halfFOV);
- }
-
- // Near face (ccw from UR)
- fr.vertexPos.append(
- Vector4( x, y, zn, 1),
- Vector4(-x, y, zn, 1),
- Vector4(-x, -y, zn, 1),
- Vector4( x, -y, zn, 1));
-
- // Far face (ccw from UR, from origin)
- if (m_farPlaneZ == -finf()) {
- fr.vertexPos.append(Vector4( x, y, zn, 0),
- Vector4(-x, y, zn, 0),
- Vector4(-x, -y, zn, 0),
- Vector4( x, -y, zn, 0));
- } else {
- // Finite
- const float s = zf / zn;
- fr.vertexPos.append(Vector4( x * s, y * s, zf, 1),
- Vector4(-x * s, y * s, zf, 1),
- Vector4(-x * s, -y * s, zf, 1),
- Vector4( x * s, -y * s, zf, 1));
- }
-
- Frustum::Face face;
-
- // Near plane (wind backwards so normal faces into frustum)
- // Recall that nearPlane, farPlane are positive numbers, so
- // we need to negate them to produce actual z values.
- face.plane = Plane(Vector3(0,0,-1), Vector3(0,0,m_nearPlaneZ));
- face.vertexIndex[0] = 3;
- face.vertexIndex[1] = 2;
- face.vertexIndex[2] = 1;
- face.vertexIndex[3] = 0;
- fr.faceArray.append(face);
-
- // Right plane
- face.plane = Plane(Vector3(xx, 0, zz), Vector3::zero());
- face.vertexIndex[0] = 0;
- face.vertexIndex[1] = 4;
- face.vertexIndex[2] = 7;
- face.vertexIndex[3] = 3;
- fr.faceArray.append(face);
-
- // Left plane
- face.plane = Plane(Vector3(-fr.faceArray.last().plane.normal().x, 0, fr.faceArray.last().plane.normal().z), Vector3::zero());
- face.vertexIndex[0] = 5;
- face.vertexIndex[1] = 1;
- face.vertexIndex[2] = 2;
- face.vertexIndex[3] = 6;
- fr.faceArray.append(face);
-
- // Top plane
- face.plane = Plane(Vector3(0, yy, zz), Vector3::zero());
- face.vertexIndex[0] = 1;
- face.vertexIndex[1] = 5;
- face.vertexIndex[2] = 4;
- face.vertexIndex[3] = 0;
- fr.faceArray.append(face);
-
- // Bottom plane
- face.plane = Plane(Vector3(0, -fr.faceArray.last().plane.normal().y, fr.faceArray.last().plane.normal().z), Vector3::zero());
- face.vertexIndex[0] = 2;
- face.vertexIndex[1] = 3;
- face.vertexIndex[2] = 7;
- face.vertexIndex[3] = 6;
- fr.faceArray.append(face);
-
- // Far plane
- if (-m_farPlaneZ < finf()) {
- face.plane = Plane(Vector3(0, 0, 1), Vector3(0, 0, m_farPlaneZ));
- face.vertexIndex[0] = 4;
- face.vertexIndex[1] = 5;
- face.vertexIndex[2] = 6;
- face.vertexIndex[3] = 7;
- fr.faceArray.append(face);
- }
-
- // Transform vertices to world space
- for (int v = 0; v < fr.vertexPos.size(); ++v) {
- fr.vertexPos[v] = m_cframe.toWorldSpace(fr.vertexPos[v]);
- }
-
- // Transform planes to world space
- for (int p = 0; p < fr.faceArray.size(); ++p) {
- // Since there is no scale factor, we don't have to
- // worry about the inverse transpose of the normal.
- Vector3 normal;
- float d;
-
- fr.faceArray[p].plane.getEquation(normal, d);
-
- Vector3 newNormal = m_cframe.rotation * normal;
-
- if (isFinite(d)) {
- d = (newNormal * -d + m_cframe.translation).dot(newNormal);
- fr.faceArray[p].plane = Plane(newNormal, newNormal * d);
- } else {
- // When d is infinite, we can't multiply 0's by it without
- // generating NaNs.
- fr.faceArray[p].plane = Plane::fromEquation(newNormal.x, newNormal.y, newNormal.z, d);
- }
- }
-}
-
-void GCamera::getNearViewportCorners
-(const Rect2D& viewport,
- Vector3& outUR,
- Vector3& outUL,
- Vector3& outLL,
- Vector3& outLR) const {
-
- // Must be kept in sync with getFrustum()
- const float w = viewportWidth(viewport) / 2.0f;
- const float h = viewportHeight(viewport) / 2.0f;
- const float z = nearPlaneZ();
-
- // Compute the points
- outUR = Vector3( w, h, z);
- outUL = Vector3(-w, h, z);
- outLL = Vector3(-w, -h, z);
- outLR = Vector3( w, -h, z);
-
- // Take to world space
- outUR = m_cframe.pointToWorldSpace(outUR);
- outUL = m_cframe.pointToWorldSpace(outUL);
- outLR = m_cframe.pointToWorldSpace(outLR);
- outLL = m_cframe.pointToWorldSpace(outLL);
-}
-
-void GCamera::getFarViewportCorners(
- const Rect2D& viewport,
- Vector3& outUR,
- Vector3& outUL,
- Vector3& outLL,
- Vector3& outLR) const {
-
- // Must be kept in sync with getFrustum()
- const float w = viewportWidth(viewport) * m_farPlaneZ / m_nearPlaneZ;
- const float h = viewportHeight(viewport) * m_farPlaneZ / m_nearPlaneZ;
- const float z = m_farPlaneZ;
-
- // Compute the points
- outUR = Vector3( w/2, h/2, z);
- outUL = Vector3(-w/2, h/2, z);
- outLL = Vector3(-w/2, -h/2, z);
- outLR = Vector3( w/2, -h/2, z);
-
- // Take to world space
- outUR = m_cframe.pointToWorldSpace(outUR);
- outUL = m_cframe.pointToWorldSpace(outUL);
- outLR = m_cframe.pointToWorldSpace(outLR);
- outLL = m_cframe.pointToWorldSpace(outLL);
-}
-
-
-
-void GCamera::setPosition(const Vector3& t) {
- m_cframe.translation = t;
-}
-
-
-void GCamera::lookAt(const Vector3& position, const Vector3& up) {
- m_cframe.lookAt(position, up);
-}
-
-
-void GCamera::serialize(BinaryOutput& bo) const {
- bo.writeFloat32(m_fieldOfView);
- bo.writeFloat32(imagePlaneDepth());
- debugAssert(nearPlaneZ() < 0.0f);
- bo.writeFloat32(nearPlaneZ());
- debugAssert(farPlaneZ() < 0.0f);
- bo.writeFloat32(farPlaneZ());
- m_cframe.serialize(bo);
- bo.writeInt8(m_direction);
- m_pixelOffset.serialize(bo);
-}
-
-
-void GCamera::deserialize(BinaryInput& bi) {
- m_fieldOfView = bi.readFloat32();
- m_nearPlaneZ = bi.readFloat32();
- debugAssert(m_nearPlaneZ < 0.0f);
- m_farPlaneZ = bi.readFloat32();
- debugAssert(m_farPlaneZ < 0.0f);
- m_cframe.deserialize(bi);
- m_direction = (FOVDirection)bi.readInt8();
- m_pixelOffset.deserialize(bi);
-}
-
-
-Vector3 GCamera::convertFromUnitToNormal(const Vector3& in, const Rect2D& viewport) const{
- return (in + Vector3(1,1,1)) * 0.5 * Vector3(viewport.width(), -viewport.height(), 1) +
- Vector3(viewport.x0(), viewport.y1(), 0);
-}
-} // namespace
diff --git a/dep/g3dlite/source/GImage.cpp b/dep/g3dlite/source/GImage.cpp
deleted file mode 100644
index 19a2b1e71f4..00000000000
--- a/dep/g3dlite/source/GImage.cpp
+++ /dev/null
@@ -1,1166 +0,0 @@
-/**
- \file GImage.cpp
- \author Morgan McGuire, http://graphics.cs.williams.edu
- Copyright 2002-2010, Morgan McGuire
-
- \created 2002-05-27
- \edited 2010-01-04
- */
-#include "G3D/platform.h"
-#include "G3D/GImage.h"
-#include "G3D/debug.h"
-#include "G3D/stringutils.h"
-#include "G3D/TextInput.h"
-#include "G3D/TextOutput.h"
-#include "G3D/BinaryInput.h"
-#include "G3D/BinaryOutput.h"
-#include "G3D/Log.h"
-#include "G3D/fileutils.h"
-
-#ifdef G3D_LINUX
-# include <png.h>
-#else
-# include "png.h"
-#endif
-
-#include <sys/stat.h>
-#include <assert.h>
-#include <sys/types.h>
-
-//////////////////////////////////////////////////////////////////////////////////////////////
-
-namespace G3D {
-
-void GImage::LtoRGBA(
- const uint8* in,
- uint8* out,
- int numPixels) {
-
- for (int i = 0; i < numPixels; ++i) {
- int v = in[i];
- int i4 = i * 4;
-
- out[i4 + 0] = v;
- out[i4 + 1] = v;
- out[i4 + 2] = v;
- out[i4 + 3] = 255;
- }
-}
-
-
-void GImage::LtoRGB(
- const uint8* in,
- uint8* out,
- int numPixels) {
-
- for (int i = 0; i < numPixels; ++i) {
- int v = in[i];
- int i3 = i * 3;
-
- out[i3 + 0] = v;
- out[i3 + 1] = v;
- out[i3 + 2] = v;
- }
-}
-
-
-void GImage::RGBtoRGBA(
- const uint8* in,
- uint8* out,
- int numPixels) {
-
- for (int i = 0; i < numPixels; ++i) {
- int i3 = i * 3;
- int i4 = i3 + i;
-
- out[i4 + 0] = in[i3 + 0];
- out[i4 + 1] = in[i3 + 1];
- out[i4 + 2] = in[i3 + 2];
- out[i4 + 3] = 255;
- }
-}
-
-
-void GImage::RGBAtoRGB(
- const uint8* in,
- uint8* out,
- int numPixels) {
-
- for (int i = 0; i < numPixels; ++i) {
- int i3 = i * 3;
- int i4 = i3 + i;
-
- out[i3 + 0] = in[i4 + 0];
- out[i3 + 1] = in[i4 + 1];
- out[i3 + 2] = in[i4 + 2];
- }
-}
-
-
-void GImage::RGBtoBGRA(
- const uint8* in,
- uint8* out,
- int numPixels) {
-
- for (int i = 0; i < numPixels; ++i) {
- int i3 = i * 3;
- int i4 = i3 + i;
-
- out[i4 + 2] = in[i3 + 0];
- out[i4 + 1] = in[i3 + 1];
- out[i4 + 0] = in[i3 + 2];
- out[i4 + 3] = 255;
- }
-}
-
-
-
-void GImage::RGBtoBGR(
- const uint8* in,
- uint8* out,
- int numPixels) {
-
- for (int i = 0; i < numPixels; ++i) {
- int i3 = i * 3;
-
- int r = in[i3 + 0];
- int g = in[i3 + 1];
- int b = in[i3 + 2];
-
- out[i3 + 2] = r;
- out[i3 + 1] = g;
- out[i3 + 0] = b;
- }
-}
-
-
-void GImage::RGBxRGBtoRGBA(
- const uint8* colorRGB,
- const uint8* alphaRGB,
- uint8* out,
- int numPixels) {
-
- for (int i = numPixels - 1; i >= 0; --i) {
- int i3 = i * 3;
- int i4 = i3 + i;
-
- out[i4 + 0] = colorRGB[i3 + 0];
- out[i4 + 1] = colorRGB[i3 + 1];
- out[i4 + 2] = colorRGB[i3 + 2];
- out[i4 + 3] = alphaRGB[i3 + 0];
- }
-}
-
-
-void GImage::RGBtoARGB(
- const uint8* in,
- uint8* out,
- int numPixels) {
-
- for (int i = 0; i < numPixels; ++i) {
- int i3 = i * 3;
- int i4 = i3 + i;
-
- out[i4 + 0] = 255;
- out[i4 + 1] = in[i3 + 0];
- out[i4 + 2] = in[i3 + 1];
- out[i4 + 3] = in[i3 + 2];
- }
-}
-
-
-void GImage::flipRGBVertical(
- const uint8* in,
- uint8* out,
- int width,
- int height) {
-
-
- // Allocate a temp row so the operation
- // is still safe if in == out
- uint8* temp = (uint8*)System::malloc(width * 3);
- alwaysAssertM(temp != NULL, "Out of memory");
-
- int oneRow = width * 3;
- int N = height / 2;
-
- // if height is an odd value, don't swap odd middle row
- for (int i = 0; i < N; ++i) {
- int topOff = i * oneRow;
- int botOff = (height - i - 1) * oneRow;
- System::memcpy(temp, in + topOff, oneRow);
- System::memcpy(out + topOff, in + botOff, oneRow);
- System::memcpy(out + botOff, temp, oneRow);
- }
-
- System::free(temp);
-}
-
-
-void GImage::flipRGBAVertical(
- const uint8* in,
- uint8* out,
- int width,
- int height) {
-
-
- // Allocate a temp row so the operation
- // is still safe if in == out
- uint8* temp = (uint8*)System::malloc(width * 4);
- alwaysAssertM(temp != NULL, "Out of memory");
-
- int oneRow = width * 4;
-
- // if height is an odd value, don't swap odd middle row
- for (int i = 0; i < height / 2; ++i) {
- int topOff = i * oneRow;
- int botOff = (height - i - 1) * oneRow;
- System::memcpy(temp, in + topOff, oneRow);
- System::memcpy(out + topOff, in + botOff, oneRow);
- System::memcpy(out + botOff, temp, oneRow);
- }
-
- System::free(temp);
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-
-void GImage::decode(
- BinaryInput& input,
- Format format) {
-
- switch (format) {
- case PPM_ASCII:
- decodePPMASCII(input);
- break;
-
- case PPM_BINARY:
- decodePPM(input);
- break;
-
- case PNG:
- decodePNG(input);
- break;
-
- case JPEG:
- decodeJPEG(input);
- break;
-
- case TGA:
- decodeTGA(input);
- break;
-
- case BMP:
- decodeBMP(input);
- break;
-
- case ICO:
- decodeICO(input);
- break;
-
- case PCX:
- decodePCX(input);
- break;
-
- default:
- debugAssert(false);
- }
-
- debugAssert(m_width >= 0);
- debugAssert(m_height >= 0);
- debugAssert(m_channels == 1 || m_channels == 3 || m_channels == 4);
- debugAssert(m_byte != NULL);
-}
-
-
-void GImage::decodePCX(
- BinaryInput& input) {
-
- uint8 manufacturer = input.readUInt8();
- uint8 version = input.readUInt8();
- uint8 encoding = input.readUInt8();
- uint8 bitsPerPixel = input.readUInt8();
-
- uint16 xmin = input.readUInt16();
- uint16 ymin = input.readUInt16();
- uint16 xmax = input.readUInt16();
- uint16 ymax = input.readUInt16();
-
- uint16 horizDPI = input.readUInt16();
- uint16 vertDPI = input.readUInt16();
-
- Color3uint8 colorMap[16];
- input.readBytes(colorMap, 48);
-
- input.skip(1);
-
- uint8 planes = input.readUInt8();
- uint16 bytesPerLine = input.readUInt16();
- uint16 paletteType = input.readUInt16();
- input.skip(4 + 54);
-
- (void)bytesPerLine;
-
- m_width = xmax - xmin + 1;
- m_height = ymax - ymin + 1;
- m_channels = 3;
-
- if ((manufacturer != 0x0A) || (encoding != 0x01)) {
- throw GImage::Error("PCX file is corrupted", input.getFilename());
- }
-
- (void)version;
- (void)vertDPI;
- (void)horizDPI;
-
- if ((bitsPerPixel != 8) || ((planes != 1) && (planes != 3))) {
- throw GImage::Error("Only 8-bit paletted and 24-bit PCX files supported.", input.getFilename());
- }
-
- // Prepare the pointer object for the pixel data
- m_byte = (uint8*)m_memMan->alloc(m_width * m_height * 3);
-
- if ((paletteType == 1) && (planes == 3)) {
-
- Color3uint8* pixel = pixel3();
-
- // Iterate over each scan line
- for (int row = 0; row < m_height; ++row) {
- // Read each scan line once per plane
- for (int plane = 0; plane < planes; ++plane) {
- int p = row * m_width;
- int p1 = p + m_width;
- while (p < p1) {
- uint8 value = input.readUInt8();
- int length = 1;
-
- if (value >= 192) {
- // This is the length, not the value. Mask off
- // the two high bits and read the true index.
- length = value & 0x3F;
- value = input.readUInt8();
- }
-
- // Set the whole run
- for (int i = length - 1; i >= 0; --i, ++p) {
- debugAssert(p < m_width * m_height);
- pixel[p][plane] = value;
- }
- }
- }
- }
-
- } else if (planes == 1) {
-
- Color3uint8 palette[256];
-
- int imageBeginning = input.getPosition();
- int paletteBeginning = input.getLength() - 769;
-
- input.setPosition(paletteBeginning);
-
- uint8 dummy = input.readUInt8();
-
- if (dummy != 12) {
- Log::common()->println("\n*********************");
- Log::common()->printf("Warning: Corrupted PCX file (palette marker byte was missing) \"%s\"\nLoading anyway\n\n", input.getFilename().c_str());
- }
-
- input.readBytes(palette, sizeof(palette));
- input.setPosition(imageBeginning);
-
- Color3uint8* pixel = pixel3();
-
- // The palette indices are run length encoded.
- int p = 0;
- while (p < m_width * m_height) {
- uint8 index = input.readUInt8();
- uint8 length = 1;
-
- if (index >= 192) {
- // This is the length, not the index. Mask off
- // the two high bits and read the true index.
- length = index & 0x3F;
- index = input.readUInt8();
- }
-
- Color3uint8 color = palette[index];
-
- // Set the whole run
- for (int i = length - 1; i >= 0; --i, ++p) {
- if (p > m_width * m_height) {
- break;
- }
- pixel[p] = color;
- }
-
- }
-
- } else {
- throw GImage::Error("Unsupported PCX file type.", input.getFilename());
- }
-}
-
-
-GImage::Format GImage::resolveFormat(const std::string& filename) {
- BinaryInput b(filename, G3D_LITTLE_ENDIAN);
- if (b.size() <= 0) {
- throw Error("File not found.", filename);
- }
-
- return resolveFormat(filename, b.getCArray(), b.size(), AUTODETECT);
-}
-
-
-GImage::Format GImage::resolveFormat(
- const std::string& filename,
- const uint8* data,
- int dataLen,
- Format maybeFormat) {
-
- // Return the provided format if it is specified.
- if (maybeFormat != AUTODETECT) {
- return maybeFormat;
- }
-
- std::string extension = toUpper(filenameExt(filename));
-
- if ((extension == "PPM") || (extension == "PGM") || (extension == "PBM")) {
- // There are two PPM formats (binary and ASCII); we handle them differently
- if (dataLen > 3) {
- if (!memcmp(data, "P6", 2) || !memcmp(data, "P5", 2)) {
- return PPM_BINARY;
- } else {
- return PPM_ASCII;
- }
- }
- }
-
- Format tmp = stringToFormat(extension);
- if ((tmp != AUTODETECT) && (tmp != UNKNOWN)) {
- return tmp;
- }
-
- // Try and autodetect from the file itself by looking at the first
- // character.
-
- // We can't look at the character if it is null.
- debugAssert(data != NULL);
-
- if ((dataLen > 3) && (! memcmp(data, "P3", 2) || (! memcmp(data, "P2", 2)) || (! memcmp(data, "P1", 2)))) {
- return PPM_ASCII;
- }
-
- if ((dataLen > 3) && (!memcmp(data, "P6", 2) ||!memcmp(data, "P5", 2))) {
- return PPM_BINARY;
- }
-
- if (dataLen > 8) {
- if (!png_sig_cmp((png_bytep)data, 0, 8)) {
- return PNG;
- }
- }
-
- if ((dataLen > 0) && (data[0] == 'B')) {
- return BMP;
- }
-
- if (dataLen > 10) {
- if ((dataLen > 11) && (data[0] == 0xFF) &&
- (memcmp(&data[6], "JFIF", 4) == 0)) {
- return JPEG;
- }
- }
-
- if (dataLen > 40) {
- if (memcmp(&data[dataLen - 18], "TRUEVISION-XFILE", 16) == 0) {
- return TGA;
- }
- }
-
- if ((dataLen > 4) && (data[0] == 0) && (data[1] == 0) && (data[2] == 0) && (data[3] == 1)) {
- return ICO;
- }
-
- if ((dataLen > 0) && (data[0] == 10)) {
- return PCX;
- }
-
- return UNKNOWN;
-}
-
-
-GImage::GImage(
- const std::string& filename,
- Format format,
- const MemoryManager::Ref& m) :
- m_memMan(m),
- m_byte(NULL),
- m_channels(0),
- m_width(0),
- m_height(0) {
-
- load(filename, format);
-}
-
-
-void GImage::load(
- const std::string& filename,
- Format format) {
-
- clear();
-
- try {
- BinaryInput b(filename, G3D_LITTLE_ENDIAN);
- if (b.size() <= 0) {
- throw Error("File not found.", filename);
- }
-
- alwaysAssertM(this != NULL, "Corrupt GImage");
- decode(b, resolveFormat(filename, b.getCArray(), b.size(), format));
- } catch (const std::string& error) {
- throw Error(error, filename);
- }
-}
-
-
-GImage::GImage(
- const uint8* data,
- int length,
- Format format,
- const MemoryManager::Ref& m) :
- m_memMan(m),
- m_byte(NULL),
- m_channels(0),
- m_width(0),
- m_height(0) {
-
- BinaryInput b(data, length, G3D_LITTLE_ENDIAN);
- // It is safe to cast away the const because we
- // know we don't corrupt the data.
-
- decode(b, resolveFormat("", data, length, format));
-}
-
-
-GImage::GImage(
- int width,
- int height,
- int channels,
- const MemoryManager::Ref& mem) :
- m_memMan(mem),
- m_byte(0),
- m_channels(0),
- m_width(0),
- m_height(0) {
-
- resize(width, height, channels);
-}
-
-
-void GImage::resize(
- int width,
- int height,
- int channels,
- bool zero) {
-
- debugAssert(width >= 0);
- debugAssert(height >= 0);
- debugAssert(channels >= 1);
-
- clear();
-
- m_width = width;
- m_height = height;
- m_channels = channels;
- size_t sz = width * height * channels;
-
- if (sz > 0) {
- m_byte = (uint8*)m_memMan->alloc(sz);
- if (zero) {
- System::memset(m_byte, 0, sz);
- }
- debugAssert(isValidHeapPointer(m_byte));
- }
-}
-
-
-void GImage::_copy(
- const GImage& other) {
-
- clear();
-
- m_width = other.m_width;
- m_height = other.m_height;
- m_channels = other.m_channels;
- int s = m_width * m_height * m_channels * sizeof(uint8);
- m_byte = (uint8*)m_memMan->alloc(s);
- debugAssert(isValidHeapPointer(m_byte));
- memcpy(m_byte, other.m_byte, s);
-}
-
-
-void GImage::flipHorizontal() {
- uint8 temp[4];
- int rowBytes = m_width * m_channels;
- for (int y = 0; y < m_height; ++y) {
- uint8* row = m_byte + y * rowBytes;
- for (int x = 0; x < m_width / 2; ++x) {
- System::memcpy(temp, row + x * m_channels, m_channels);
- System::memcpy(row + x * m_channels, row + (m_width - x - 1) * m_channels, m_channels);
- System::memcpy(row + (m_width - x - 1) * m_channels, temp, m_channels);
- }
- }
-}
-
-
-void GImage::flipVertical() {
- uint8* old = m_byte;
- m_byte = (uint8*)m_memMan->alloc(m_width * m_height * m_channels);
-
- // We could do this with only a single-row temp buffer, but then
- // we'd have to copy twice as much data.
- int rowBytes = m_width * m_channels;
- for (int y = 0; y < m_height; ++y) {
- System::memcpy(m_byte + y * rowBytes, old + (m_height - y - 1) * rowBytes, rowBytes);
- }
-
- m_memMan->free(old);
-}
-
-
-void GImage::rotate90CW(int numTimes) {
-
- uint8* old = NULL;
- numTimes = iWrap(numTimes, 4);
- if (numTimes > 0) {
- (uint8*)m_memMan->alloc(m_width * m_height * m_channels);
- }
- for (int j = 0; j < numTimes; ++j) {
- {
- uint8* temp = old;
- old = m_byte;
- m_byte = temp;
- }
-
- {
- int temp = m_width;
- m_width = m_height;
- m_height = temp;
- }
-
- int rowBytes = m_width * m_channels;
- for (int y = 0; y < m_height; ++y) {
- for (int x = 0; x < m_width; ++x) {
- uint8* dst = m_byte + x + y * rowBytes;
- uint8* src = old + y + (m_height - x - 1) * rowBytes;
- System::memcpy(dst, src, m_channels);
- }
- }
- }
- m_memMan->free(old);
-}
-
-
-
-GImage::GImage(
- const GImage& other,
- const MemoryManager::Ref& m) : m_memMan(m), m_byte(NULL) {
-
- _copy(other);
-}
-
-
-GImage::~GImage() {
- clear();
-}
-
-
-void GImage::clear() {
- m_width = 0;
- m_height = 0;
- m_memMan->free(m_byte);
- m_byte = NULL;
-}
-
-
-GImage& GImage::operator=(const GImage& other) {
- _copy(other);
- return *this;
-}
-
-
-bool GImage::copySubImage(
- GImage & dest, const GImage & src,
- int srcX, int srcY, int srcWidth, int srcHeight) {
- if ((src.m_width < srcX + srcWidth) ||
- (src.m_height < srcY + srcHeight) ||
- (srcY < 0) ||
- (srcX < 0)) {
-
- return false;
- }
-
- dest.resize(srcWidth, srcHeight, src.m_channels);
-
- bool ret;
- ret = pasteSubImage(dest, src, 0, 0, srcX, srcY, srcWidth, srcHeight);
- debugAssert(ret);
-
- return true;
-}
-
-
-bool GImage::pasteSubImage(
- GImage & dest, const GImage & src,
- int destX, int destY,
- int srcX, int srcY, int srcWidth, int srcHeight) {
-
- if ((src.m_width < srcX + srcWidth) ||
- (src.m_height < srcY + srcHeight) ||
- (dest.m_width < destX + srcWidth) ||
- (dest.m_height < destY + srcHeight) ||
- (srcY < 0) ||
- (srcX < 0) ||
- (destY < 0) ||
- (destX < 0) ||
- (src.channels() != dest.channels())) {
-
- return false;
- }
-
- for (int i = 0; i < srcHeight; i++) {
- const uint8* srcRow = src.byte() +
- ((i + srcY) * src.m_width + srcX) * src.channels();
- uint8* destRow = dest.byte() +
- ((i + destY) * dest.width() + destX) * dest.channels();
- memcpy(destRow, srcRow, srcWidth * src.m_channels);
- }
-
- return true;
-}
-
-
-bool GImage::supportedFormat(
- const std::string& format) {
-
- return (stringToFormat(format) != UNKNOWN);
-}
-
-
-GImage::Format GImage::stringToFormat(
- const std::string& format) {
-
- std::string extension = toUpper(format);
-
- if ((extension == "JPG") || (extension == "JPEG")) {
- return JPEG;
- } else if (extension == "TGA") {
- return TGA;
- } else if (extension == "BMP") {
- return BMP;
- } else if (extension == "PCX") {
- return PCX;
- } else if (extension == "ICO") {
- return ICO;
- } else if (extension == "PNG") {
- return PNG;
- } else {
- return UNKNOWN;
- }
- // Don't put PPM here, since it has two versions
-}
-
-
-void GImage::save(
- const std::string& filename,
- Format format) const {
-
- BinaryOutput b(filename, G3D_LITTLE_ENDIAN);
- encode(resolveFormat(filename, NULL, 0, format), b);
- b.commit(false);
-}
-
-
-void GImage::encode(
- Format format,
- uint8*& outData,
- int& outLength) const {
-
- BinaryOutput out;
-
- encode(format, out);
-
- outData = (uint8*)System::malloc(out.size());
- debugAssert(outData);
- outLength = out.size();
-
- out.commit(outData);
-}
-
-
-void GImage::encode(
- Format format,
- BinaryOutput& out) const {
-
- switch (format) {
- case PPM_ASCII:
- encodePPMASCII(out);
- break;
-
- case PPM_BINARY:
- encodePPM(out);
- break;
-
- case PNG:
- encodePNG(out);
- break;
-
- case JPEG:
- encodeJPEG(out);
- break;
-
- case BMP:
- encodeBMP(out);
- break;
-
- case TGA:
- encodeTGA(out);
- break;
-
- default:
- debugAssert(false);
- }
-}
-
-
-void GImage::insertRedAsAlpha(const GImage& alpha, GImage& output) const {
- debugAssert(alpha.width() == width());
- debugAssert(alpha.height() == height());
-
- // make sure output GImage is valid
- if (output.width() != width() || output.height() != height() || output.channels() != 4) {
- output.resize(width(), height(), 4);
- }
-
- int N = m_width * m_height;
- for (int i = 0; i < N; ++i) {
- output.byte()[i * 4 + 0] = byte()[i * m_channels + 0];
- output.byte()[i * 4 + 1] = byte()[i * m_channels + 1];
- output.byte()[i * 4 + 2] = byte()[i * m_channels + 2];
- output.byte()[i * 4 + 3] = alpha.byte()[i * alpha.m_channels];
- }
-}
-
-
-void GImage::stripAlpha(GImage& output) const {
-
- if (output.m_width != m_width || output.m_height != m_height || output.m_channels != 3) {
- output.resize(m_width, m_height, 3);
- }
-
- int N = m_width * m_height;
- for (int i = 0; i < N; ++i) {
- output.byte()[i * 3 + 0] = byte()[i * m_channels + 0];
- output.byte()[i * 3 + 1] = byte()[i * m_channels + 1];
- output.byte()[i * 3 + 2] = byte()[i * m_channels + 2];
- }
-}
-
-
-int GImage::sizeInMemory() const {
- return sizeof(GImage) + m_width * m_height * m_channels;
-}
-
-
-void GImage::computeNormalMap(
- const GImage& bump,
- GImage& normal,
- const BumpMapPreprocess& preprocess) {
- computeNormalMap(bump.m_width, bump.m_height, bump.m_channels,
- bump.byte(), normal, preprocess);
-}
-
-void GImage::computeNormalMap(
- int width,
- int height,
- int channels,
- const uint8* src,
- GImage& normal,
- const BumpMapPreprocess& preprocess) {
-
- float whiteHeightInPixels = preprocess.zExtentPixels;
- bool lowPassBump = preprocess.lowPassFilter;
- bool scaleHeightByNz = preprocess.scaleZByNz;
-
- if (whiteHeightInPixels < 0.0f) {
- // Default setting scales so that a gradient ramp
- // over the whole image becomes a 45-degree angle
-
- // Account for potentially non-square aspect ratios
- whiteHeightInPixels = max(width, height) * -whiteHeightInPixels;
- }
-
- debugAssert(whiteHeightInPixels >= 0);
-
- const int w = width;
- const int h = height;
- const int stride = channels;
-
- normal.resize(w, h, 4);
-
- const uint8* const B = src;
- Color4uint8* const N = normal.pixel4();
-
- // 1/s for the scale factor that each ELEVATION should be multiplied by.
- // We avoid actually multiplying by this and instead just divide it out of z.
- float elevationInvScale = 255.0f / whiteHeightInPixels;
-
- for (int y = 0; y < h; ++y) {
- for (int x = 0; x < w; ++x) {
- // Index into normal map pixel
- int i = x + y * w;
-
- // Index into bump map *byte*
- int j = stride * i;
-
- Vector3 delta;
-
- // Get a value from B (with wrapping lookup) relative to (x, y)
- // and divide by 255
- #define ELEVATION(DX, DY) ((int)B[(((DX + x + w) % w) + \
- ((DY + y + h) % h) * w) * stride])
-
-
- // Sobel filter to compute the normal.
- //
- // Y Filter (X filter is the transpose)
- // [ -1 -2 -1 ]
- // [ 0 0 0 ]
- // [ 1 2 1 ]
-
- // Write the Y value directly into the x-component so we don't have
- // to explicitly compute a cross product at the end. Does not
- // go out of bounds because the above is computed mod (width, height)
- delta.y = -( ELEVATION(-1, -1) * 1 + ELEVATION( 0, -1) * 2 + ELEVATION( 1, -1) * 1 +
- -ELEVATION(-1, 1) * 1 + -ELEVATION( 0, 1) * 2 + -ELEVATION( 1, 1) * 1);
-
- delta.x = -(-ELEVATION(-1, -1) * 1 + ELEVATION( 1, -1) * 1 +
- -ELEVATION(-1, 0) * 2 + ELEVATION( 1, 0) * 2 +
- -ELEVATION(-1, 1) * 1 + ELEVATION( 1, 1) * 1);
-
- // The scale of each filter row is 4, the filter width is two pixels,
- // and the "normal" range is 0-255.
- delta.z = 4 * 2 * elevationInvScale;
-
- // Delta is now scaled in pixels; normalize
- delta = delta.direction();
-
- // Copy over the bump value into the alpha channel.
- float H = B[j] / 255.0f;
-
- if (lowPassBump) {
- H = (ELEVATION(-1, -1) + ELEVATION( 0, -1) + ELEVATION(1, -1) +
- ELEVATION(-1, 0) + ELEVATION( 0, 0) + ELEVATION(1, 0) +
- ELEVATION(-1, 1) + ELEVATION( 0, 1) + ELEVATION(1, 1)) / (255.0f * 9.0f);
- }
-# undef ELEVATION
-
- if (scaleHeightByNz) {
- // delta.z can't possibly be negative, so we avoid actually
- // computing the absolute value.
- H *= delta.z;
- }
-
- N[i].a = iRound(H * 255.0f);
-
- // Pack into byte range
- delta = delta * 127.5f + Vector3(127.5f, 127.5f, 127.5f);
- N[i].r = iClamp(iRound(delta.x), 0, 255);
- N[i].g = iClamp(iRound(delta.y), 0, 255);
- N[i].b = iClamp(iRound(delta.z), 0, 255);
- }
- }
-}
-
-
-/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-void GImage::convertToL8() {
- switch (m_channels) {
- case 1:
- return;
-
- case 3:
- {
- // Average
- Color3uint8* src = (Color3uint8*)m_byte;
- m_byte = NULL;
- resize(m_width, m_height, 1);
- for (int i = m_width * m_height - 1; i >= 0; --i) {
- const Color3uint8 s = src[i];
- uint8& d = m_byte[i];
- d = ((int)s.r + (int)s.g + (int)s.b) / 3;
- }
- m_memMan->free(src);
- }
- break;
-
- case 4:
- {
- // Average
- Color4uint8* src = (Color4uint8*)m_byte;
- m_byte = NULL;
- resize(m_width, m_height, 1);
- for (int i = m_width * m_height - 1; i >= 0; --i) {
- const Color4uint8 s = src[i];
- uint8& d = m_byte[i];
- d = ((int)s.r + (int)s.g + (int)s.b) / 3;
- }
- m_memMan->free(src);
- }
- return;
-
- default:
- alwaysAssertM(false, "Bad number of channels in input image");
- }
-}
-
-
-void GImage::convertToRGBA() {
- switch (m_channels) {
- case 1:
- {
- // Spread
- uint8* old = m_byte;
- m_byte = NULL;
- resize(m_width, m_height, 4);
- for (int i = m_width * m_height - 1; i >= 0; --i) {
- const uint8 s = old[i];
- Color4uint8& d = ((Color4uint8*)m_byte)[i];
- d.r = d.g = d.b = s;
- d.a = 255;
- }
- m_memMan->free(m_byte);
- }
- break;
-
- case 3:
- {
- // Add alpha
- Color3uint8* old = (Color3uint8*)m_byte;
- m_byte = NULL;
- resize(m_width, m_height, 4);
- for (int i = m_width * m_height - 1; i >= 0; --i) {
- const Color3uint8 s = old[i];
- Color4uint8& d = ((Color4uint8*)m_byte)[i];
- d.r = s.r;
- d.g = s.g;
- d.b = s.b;
- d.a = 255;
- }
- m_memMan->free(old);
- }
- break;
-
- case 4:
- // Already RGBA
- return;
-
- default:
- alwaysAssertM(false, "Bad number of channels in input image");
- }
-}
-
-
-void GImage::convertToRGB() {
- switch (m_channels) {
- case 1:
- {
- // Spread
- uint8* old = m_byte;
- m_byte = NULL;
- resize(m_width, m_height, 3);
- for (int i = m_width * m_height - 1; i >= 0; --i) {
- const uint8 s = old[i];
- Color3uint8& d = ((Color3uint8*)m_byte)[i];
- d.r = d.g = d.b = s;
- }
- m_memMan->free(old);
- }
- break;
-
- case 3:
- return;
-
- case 4:
- // Strip alpha
- {
- Color4uint8* old = (Color4uint8*)m_byte;
- m_byte = NULL;
- resize(m_width, m_height, 3);
- for (int i = m_width * m_height - 1; i >= 0; --i) {
- const Color4uint8 s = old[i];
- Color3uint8& d = ((Color3uint8*)m_byte)[i];
- d.r = s.r;
- d.g = s.g;
- d.b = s.b;
- }
- m_memMan->free(old);
- }
- break;
-
- default:
- alwaysAssertM(false, "Bad number of channels in input image");
- }
-}
-
-
-void GImage::R8G8B8_to_Y8U8V8(int width, int height, const uint8* _in, uint8* _out) {
- const Color3uint8* in = reinterpret_cast<const Color3uint8*>(_in);
- Color3uint8* out = reinterpret_cast<Color3uint8*>(_out);
-
- Color3uint8 p;
- for (int i = width * height - 1; i >= 0; --i) {
- p.r = iClamp(iRound(in->r * 0.229 + in->g * 0.587 + in->b * 0.114), 0, 255);
- p.g = iClamp(iRound(in->r * -0.147 + in->g * -0.289 + in->b * 0.436) + 127, 0, 255);
- p.b = iClamp(iRound(in->r * 0.615 + in->g * -0.515 + in->b * -0.100) + 127, 0, 255);
- *out = p;
- ++in;
- ++out;
- }
-}
-
-
-
-void GImage::Y8U8V8_to_R8G8B8(int width, int height, const uint8* _in, uint8* _out) {
- const Color3uint8* in = reinterpret_cast<const Color3uint8*>(_in);
- Color3uint8* out = reinterpret_cast<Color3uint8*>(_out);
-
- Color3uint8 p;
- for (int i = width * height - 1; i >= 0; --i) {
- p.r = iClamp(iRound(in->r * 1.0753 + (in->b - 127) * 1.2256), 0, 255);
- p.g = iClamp(iRound(in->r * 1.0753 + (in->g - 127) * -0.3946 + (in->b - 127) * -0.4947), 0, 255);
- p.b = iClamp(iRound(in->r * 1.0753 + (in->g - 127) * 2.0320 + (in->b - 127) * 0.0853), 0, 255);
- *out = p;
- ++in;
- ++out;
- }
-}
-
-
-void GImage::makeCheckerboard(GImage& im, int checkerSize, const Color4uint8& A, const Color4uint8& B) {
- for (int y = 0; y < im.m_height; ++y) {
- for (int x = 0; x < im.m_width; ++x) {
- bool checker = isOdd((x / checkerSize) + (y / checkerSize));
- const Color4uint8& color = checker ? A : B;
- for (int c = 0; c < im.m_channels; ++c) {
- uint8* v = im.byte() + (x + y * im.m_width) * im.m_channels + c;
- *v = color[c];
- }
- }
- }
-}
-
-}
-
diff --git a/dep/g3dlite/source/GImage_bayer.cpp b/dep/g3dlite/source/GImage_bayer.cpp
deleted file mode 100644
index 3d08e8ade5f..00000000000
--- a/dep/g3dlite/source/GImage_bayer.cpp
+++ /dev/null
@@ -1,298 +0,0 @@
-/**
- @file GImage_bayer.cpp
- @author Morgan McGuire, http://graphics.cs.williams.edu
- @created 2002-05-27
- @edited 2006-05-10
- */
-#include "G3D/platform.h"
-#include "G3D/GImage.h"
-
-namespace G3D {
-
-void GImage::BAYER_G8B8_R8G8_to_Quarter_R8G8B8(int width, int height, const uint8* in, uint8* out) {
- debugAssert(in != out);
-
- int halfHeight = height / 2;
- int halfWidth = width / 2;
-
- int dst_off = 0;
- for (int y = 0; y < halfHeight; ++y) {
- for (int x = 0; x < halfWidth; ++x) {
- // GBRG
- int src_off = x*2 + y*2*width;
- out[dst_off] = in[src_off+width]; // red
- out[dst_off+1] = ((int)in[src_off] + (int)in[src_off+width+1])/2; // green
- out[dst_off+2] = in[src_off+1]; // blue
-
- dst_off = dst_off + 3;
- }
- }
-}
-
-
-void GImage::Quarter_R8G8B8_to_BAYER_G8B8_R8G8(int inWidth, int inHeight, const uint8* in, uint8* out) {
- // Undo quarter-size Bayer as best we can. This code isn't very efficient, but it
- // also isn't used very frequently.
-
- debugAssert(out != in);
-
- int outWidth = 2 * inWidth;
- int outHeight = 2 * inHeight;
-
- for (int y = 0; y < outHeight; ++y) {
- for (int x = 0; x < outWidth; ++x) {
- const Color3uint8* inp = ((const Color3uint8*)in) + ((x/2) + (y/2)* inWidth);
- uint8* outp = out + x + y * outWidth;
-
- if (isEven(y)) {
- // GB row
- if (isEven(x)) {
- // Green
- *outp = inp->g;
- } else {
- // Blue
- *outp = inp->b;
- }
- } else {
- // RG row
- if (isEven(x)) {
- // Red
- *outp = inp->r;
- } else {
- // Green
- *outp = inp->g;
- }
- }
- }
- }
-}
-
-
-/** Applies a 5x5 filter to monochrome image I (wrapping at the boundaries) */
-static uint8 applyFilter(
- const uint8* I,
- int x,
- int y,
- int w,
- int h,
- const float filter[5][5]) {
-
- debugAssert(isEven(w));
- debugAssert(isEven(h));
-
- float sum = 0.0f;
- float denom = 0.0f;
-
- for (int dy = 0; dy < 5; ++dy) {
- int offset = ((y + dy + h - 2) % h) * w;
-
- for (int dx = 0; dx < 5; ++dx) {
- float f = filter[dy][dx];
- sum += f * I[((x + dx + w - 2) % w) + offset];
- denom += f;
- }
- }
-
- return (uint8)iClamp(iRound(sum / denom), 0, 255);
-}
-
-////////////////////////////////////////////////////////////////////////////////////////////////
-//
-// Bayer conversions
-//
-
-// There are two kinds of rows (GR and BG).
-// In each row, there are two kinds of pixels (G/R, B/G).
-// We express the four kinds of INPUT pixels as:
-// GRG, GRG, BGB, BGG
-//
-// There are three kinds of OUTPUT pixels: R, G, B.
-// Thus there are nominally 12 different I/O combinations,
-// but several are impulses because needed output at that
-// location *is* the input (e.g., G_GRG and G_BGG).
-//
-// The following 5x5 row-major filters are named as output_input.
-
-// Green
-static const float G_GRR[5][5] =
-{{ 0.0f, 0.0f, -1.0f, 0.0f, 0.0f},
-{ 0.0f, 0.0f, 2.0f, 0.0f, 0.0f},
-{ -1.0f, 2.0f, 4.0f, 2.0f, -1.0f},
-{ 0.0f, 0.0f, 2.0f, 0.0f, 0.0f},
-{ 0.0f, 0.0f, -1.0f, 0.0f, 0.0f}};
-
-static const float G_BGB[5][5] =
-{{ 0.0f, 0.0f, -1.0f, 0.0f, 0.0f},
-{ 0.0f, 0.0f, 2.0f, 0.0f, 0.0f},
-{ -1.0f, 2.0f, 4.0f, 2.0f, -1.0f},
-{ 0.0f, 0.0f, 2.0f, 0.0f, 0.0f},
-{ 0.0f, 0.0f, -1.0f, 0.0f, 0.0f}};
-
-// Red
-//(the caption in the paper is wrong for this case:
-// "R row B column really means R row G column"
-static const float R_GRG[5][5] =
-{{ 0.0f, 0.0f, 0.5f, 0.0f, 0.0f},
-{ 0.0f, -1.0f, 0.0f, -1.0f, 0.0f},
-{ -1.0f, 4.0f, 5.0f, 4.0f, -1.0f},
-{ 0.0f, -1.0f, 0.0f, -1.0f, 0.0f},
-{ 0.0f, 0.0f, 0.5f, 0.0f, 0.0f}};
-
-static const float R_BGG[5][5] =
-{{ 0.0f, 0.0f, -1.0f, 0.0f, 0.0f},
-{ 0.0f, -1.0f, 4.0f, -1.0f, 0.0f},
-{ 0.5f, 0.0f, 5.0f, 0.0f, 0.5f},
-{ 0.0f, -1.0f, 4.0f, -1.0f, 0.0f},
-{ 0.0f, 0.0f, -1.0f, 0.0f, 0.0f}};
-
-static const float R_BGB[5][5] =
-{{ 0.0f, 0.0f, -3.0f/2.0f, 0.0f, 0.0f},
-{ 0.0f, 2.0f, 0.0f, 2.0f, 0.0f},
-{-3.0f/2.0f, 0.0f, 6.0f, 0.0f, -3.0f/2.0f},
-{ 0.0f, 2.0f, 0.0f, 2.0f, 0.0f},
-{ 0.0f, 0.0f, -3.0f/2.0f, 0.0f, 0.0f}};
-
-
-// Blue
-//(the caption in the paper is wrong for this case:
-// "B row R column really means B row G column")
-#define B_BGG R_GRG
-#define B_GRG R_BGG
-#define B_GRR R_BGB
-
-
-void GImage::BAYER_R8G8_G8B8_to_R8G8B8_MHC(int w, int h, const uint8* in, uint8* _out) {
- debugAssert(in != _out);
-
- Color3uint8* out = (Color3uint8*)_out;
-
- for (int y = 0; y < h; ++y) {
-
- // Row beginning in the input array.
- int offset = y * w;
-
- // RG row
- for (int x = 0; x < w; ++x, ++out) {
- // R pixel
- {
- out->r = in[x + offset];
- out->g = applyFilter(in, x, y, w, h, G_GRR);
- out->b = applyFilter(in, x, y, w, h, B_GRR);
- }
- ++x; ++out;
-
- // G pixel
- {
- out->r = applyFilter(in, x, y, w, h, R_GRG);
- out->g = in[x + offset];
- out->b = applyFilter(in, x, y, w, h, B_GRG);
- }
- }
-
- ++y;
- offset += w;
-
- // GB row
- for (int x = 0; x < w; ++x, ++out) {
- // G pixel
- {
- out->r = applyFilter(in, x, y, w, h, R_BGG);
- out->g = in[x + offset];
- out->b = applyFilter(in, x, y, w, h, B_BGG);
- }
- ++x; ++out;
-
- // B pixel
- {
- out->r = applyFilter(in, x, y, w, h, R_BGB);
- out->g = applyFilter(in, x, y, w, h, G_BGB);
- out->b = in[x + offset];
- }
- }
- }
-}
-
-static void swapRedAndBlue(int N, Color3uint8* out) {
- for (int i = N - 1; i >= 0; --i) {
- uint8 tmp = out[i].r;
- out[i].r = out[i].b;
- out[i].b = tmp;
- }
-}
-
-void GImage::BAYER_G8R8_B8G8_to_R8G8B8_MHC(int w, int h, const uint8* in, uint8* _out) {
- // Run the equivalent function for red
- BAYER_G8B8_R8G8_to_R8G8B8_MHC(w, h, in, _out);
-
- // Now swap red and blue
- swapRedAndBlue(w * h, (Color3uint8*)_out);
-}
-
-
-void GImage::BAYER_B8G8_G8R8_to_R8G8B8_MHC(int w, int h, const uint8* in, uint8* _out) {
- // Run the equivalent function for red
- BAYER_R8G8_G8B8_to_R8G8B8_MHC(w, h, in, _out);
-
- // Now swap red and blue
- swapRedAndBlue(w * h, (Color3uint8*)_out);
-}
-
-
-void GImage::BAYER_G8B8_R8G8_to_R8G8B8_MHC(int w, int h, const uint8* in, uint8* _out) {
-
- debugAssert(in != _out);
-
- Color3uint8* out = (Color3uint8*)_out;
-
- for (int y = 0; y < h; ++y) {
-
- // Row beginning in the input array.
- int offset = y * w;
-
- // GB row
- for (int x = 0; x < w; ++x, ++out) {
- // G pixel
- {
- out->r = applyFilter(in, x, y, w, h, R_BGG);
- out->g = in[x + offset];
- out->b = applyFilter(in, x, y, w, h, B_BGG);
- }
- ++x; ++out;
-
- // B pixel
- {
- out->r = applyFilter(in, x, y, w, h, R_BGB);
- out->g = applyFilter(in, x, y, w, h, G_BGB);
- out->b = in[x + offset];
- }
- }
-
- ++y;
- offset += w;
-
- // RG row
- for (int x = 0; x < w; ++x, ++out) {
- // R pixel
- {
- out->r = in[x + offset];
- out->g = applyFilter(in, x, y, w, h, G_GRR);
- out->b = applyFilter(in, x, y, w, h, B_GRR);
- }
- ++x; ++out;
-
- // G pixel
- {
- out->r = applyFilter(in, x, y, w, h, R_GRG);
- out->g = in[x + offset];
- out->b = applyFilter(in, x, y, w, h, B_GRG);
- }
- }
- }
-
-}
-
-#undef B_BGG
-#undef B_GRG
-#undef B_GRR
-
-}
diff --git a/dep/g3dlite/source/GImage_bmp.cpp b/dep/g3dlite/source/GImage_bmp.cpp
deleted file mode 100644
index 425a7e1a1d2..00000000000
--- a/dep/g3dlite/source/GImage_bmp.cpp
+++ /dev/null
@@ -1,717 +0,0 @@
-/**
- @file GImage_bmp.cpp
- @author Morgan McGuire, http://graphics.cs.williams.edu
- @created 2002-05-27
- @edited 2006-05-10
- */
-#include "G3D/platform.h"
-#include "G3D/GImage.h"
-#include "G3D/BinaryInput.h"
-#include "G3D/BinaryOutput.h"
-#include "G3D/Log.h"
-
-namespace G3D {
-
-#ifndef G3D_WIN32
-/**
- This is used by the Windows bitmap I/O.
- */
-static const int BI_RGB = 0;
-#endif
-
-void GImage::encodeBMP(
- BinaryOutput& out) const {
-
- debugAssert(m_channels == 1 || m_channels == 3);
- out.setEndian(G3D_LITTLE_ENDIAN);
-
- uint8 red;
- uint8 green;
- uint8 blue;
- int pixelBufferSize = m_width * m_height * 3;
- int fileHeaderSize = 14;
- int infoHeaderSize = 40;
- int BMScanWidth;
- int BMPadding;
-
- // First write the BITMAPFILEHEADER
- //
- // WORD bfType;
- // DWORD bfSize;
- // WORD bfReserved1;
- // WORD bfReserved2;
- // DWORD bfOffBits;
-
- // Type
- out.writeUInt8('B');
- out.writeUInt8('M');
-
- // File size
- out.writeUInt32(fileHeaderSize + infoHeaderSize + pixelBufferSize);
-
- // Two reserved fields set to zero
- out.writeUInt16(0);
- out.writeUInt16(0);
-
- // The offset, in bytes, from the BITMAPFILEHEADER structure
- // to the bitmap bits.
- out.writeUInt32(infoHeaderSize + fileHeaderSize);
-
- // Now the BITMAPINFOHEADER
- //
- // DWORD biSize;
- // LONG biWidth;
- // LONG biHeight;
- // WORD biPlanes;
- // WORD biBitCount
- // DWORD biCompression;
- // DWORD biSizeImage;
- // LONG biXPelsPerMeter;
- // LONG biYPelsPerMeter;
- // DWORD biClrUsed;
- // DWORD biClrImportant;
-
- // Size of the info header
- out.writeUInt32(infoHeaderSize);
-
- // Width and height of the image
- out.writeUInt32(m_width);
- out.writeUInt32(m_height);
-
- // Planes ("must be set to 1")
- out.writeUInt16(1);
-
- // BitCount and CompressionType
- out.writeUInt16(24);
- out.writeUInt32(BI_RGB);
-
- // Image size ("may be zero for BI_RGB bitmaps")
- out.writeUInt32(0);
-
- // biXPelsPerMeter
- out.writeUInt32(0);
- // biYPelsPerMeter
- out.writeUInt32(0);
-
- // biClrUsed
- out.writeUInt32(0);
-
- // biClrImportant
- out.writeUInt32(0);
-
- BMScanWidth = m_width * 3;
-
- if (BMScanWidth & 3) {
- BMPadding = 4 - (BMScanWidth & 3);
- } else {
- BMPadding = 0;
- }
-
- int hStart = m_height - 1;
- int hEnd = -1;
- int hDir = -1;
- int dest;
-
- // Write the pixel data
- for (int h = hStart; h != hEnd; h += hDir) {
- dest = m_channels * h * m_width;
- for (int w = 0; w < m_width; ++w) {
-
- if (m_channels == 3) {
- red = m_byte[dest];
- green = m_byte[dest + 1];
- blue = m_byte[dest + 2];
- } else {
- red = m_byte[dest];
- green = m_byte[dest];
- blue = m_byte[dest];
- }
-
- out.writeUInt8(blue);
- out.writeUInt8(green);
- out.writeUInt8(red);
-
- dest += m_channels;
- }
-
- if (BMPadding > 0) {
- out.skip(BMPadding);
- }
- }
-}
-
-
-void GImage::decodeBMP(
- BinaryInput& input) {
-
- // The BMP decoding uses these flags.
- static const uint16 PICTURE_NONE = 0x0000;
- static const uint16 PICTURE_BITMAP = 0x1000;
-
- // Compression Flags
- static const uint16 PICTURE_UNCOMPRESSED = 0x0100;
- static const uint16 PICTURE_MONOCHROME = 0x0001;
- static const uint16 PICTURE_4BIT = 0x0002;
- static const uint16 PICTURE_8BIT = 0x0004;
- static const uint16 PICTURE_16BIT = 0x0008;
- static const uint16 PICTURE_24BIT = 0x0010;
- static const uint16 PICTURE_32BIT = 0x0020;
-
- (void)PICTURE_16BIT;
- (void)PICTURE_32BIT;
-
- // This is a simple BMP loader that can handle uncompressed BMP files.
- // Verify this is a BMP file by looking for the BM tag.
- input.reset();
- std::string tag = input.readString(2);
- if (tag != "BM") {
- throw Error("Not a BMP file", input.getFilename());
- }
-
- m_channels = 3;
- // Skip to the BITMAPINFOHEADER's width and height
- input.skip(16);
-
- m_width = input.readUInt32();
- m_height = input.readUInt32();
-
- // Skip to the bit count and compression type
- input.skip(2);
-
- uint16 bitCount = input.readUInt16();
- uint32 compressionType = input.readUInt32();
-
- uint8 red;
- uint8 green;
- uint8 blue;
- uint8 blank;
-
- // Only uncompressed bitmaps are supported by this code
- if ((int32)compressionType != BI_RGB) {
- throw Error("BMP images must be uncompressed", input.getFilename());
- }
-
- uint8* palette = NULL;
-
- // Create the palette if needed
- if (bitCount <= 8) {
-
- // Skip to the palette color count in the header
- input.skip(12);
-
- int numColors = input.readUInt32();
-
- palette = (uint8*)System::malloc(numColors * 3);
- debugAssert(palette);
-
- // Skip past the end of the header to the palette info
- input.skip(4);
-
- int c;
- for(c = 0; c < numColors * 3; c += 3) {
- // Palette information in bitmaps is stored in BGR_ format.
- // That means it's blue-green-red-blank, for each entry.
- blue = input.readUInt8();
- green = input.readUInt8();
- red = input.readUInt8();
- blank = input.readUInt8();
-
- palette[c] = red;
- palette[c + 1] = green;
- palette[c + 2] = blue;
- }
- }
-
- int hStart = 0;
- int hEnd = 0;
- int hDir = 0;
-
- if (m_height < 0) {
- m_height = -m_height;
- hStart = 0;
- hEnd = m_height;
- hDir = 1;
- } else {
- //height = height;
- hStart = m_height - 1;
- hEnd = -1;
- hDir = -1;
- }
-
- m_byte = (uint8*)m_memMan->alloc(m_width * m_height * 3);
- debugAssert(m_byte);
-
- int BMScanWidth;
- int BMPadding;
- uint8 BMGroup;
- uint8 BMPixel8;
- int currPixel;
- int dest;
- int flags = PICTURE_NONE;
-
- if (bitCount == 1) {
- // Note that this file is not necessarily grayscale, since it's possible
- // the palette is blue-and-white, or whatever. But of course most image
- // programs only write 1-bit images if they're black-and-white.
- flags = PICTURE_BITMAP | PICTURE_UNCOMPRESSED | PICTURE_MONOCHROME;
-
- // For bitmaps, each scanline is dword-aligned.
- BMScanWidth = (m_width + 7) >> 3;
- if (BMScanWidth & 3) {
- BMScanWidth += 4 - (BMScanWidth & 3);
- }
-
- // Powers of 2
- int pow2[8] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
-
- for (int h = hStart; h != hEnd; h += hDir) {
-
- currPixel = 0;
- dest = 3 * h * m_width;
-
- for (int w = 0; w < BMScanWidth; ++w) {
-
- BMGroup = input.readUInt8();
-
- // Now we read the pixels. Usually there are eight pixels per byte,
- // since each pixel is represented by one bit, but if the width
- // is not a multiple of eight, the last byte will have some bits
- // set, with the others just being extra. Plus there's the
- // dword-alignment padding. So we keep checking to see if we've
- // already read "width" number of pixels.
- for (int i = 7; i >= 0; --i) {
- if (currPixel < m_width) {
- int src = 3 * ((BMGroup & pow2[i]) >> i);
-
- m_byte[dest] = palette[src];
- m_byte[dest + 1] = palette[src + 1];
- m_byte[dest + 2] = palette[src + 2];
-
- ++currPixel;
- dest += 3;
- }
- }
- }
- }
-
- } else if (bitCount == 4) {
-
- flags = PICTURE_BITMAP | PICTURE_UNCOMPRESSED | PICTURE_4BIT;
-
- // For bitmaps, each scanline is dword-aligned.
- int BMScanWidth = (m_width + 1) >> 1;
- if (BMScanWidth & 3) {
- BMScanWidth += 4 - (BMScanWidth & 3);
- }
-
- for (int h = hStart; h != hEnd; h += hDir) {
-
- currPixel = 0;
- dest = 3 * h * m_width;
-
- for (int w = 0; w < BMScanWidth; w++) {
-
- BMGroup = input.readUInt8();
- int src[2];
- src[0] = 3 * ((BMGroup & 0xF0) >> 4);
- src[1] = 3 * (BMGroup & 0x0F);
-
- // Now we read the pixels. Usually there are two pixels per byte,
- // since each pixel is represented by four bits, but if the width
- // is not a multiple of two, the last byte will have only four bits
- // set, with the others just being extra. Plus there's the
- // dword-alignment padding. So we keep checking to see if we've
- // already read "Width" number of pixels.
-
- for (int i = 0; i < 2; ++i) {
- if (currPixel < m_width) {
- int tsrc = src[i];
-
- m_byte[dest] = palette[tsrc];
- m_byte[dest + 1] = palette[tsrc + 1];
- m_byte[dest + 2] = palette[tsrc + 2];
-
- ++currPixel;
- dest += 3;
- }
- }
- }
- }
-
- } else if (bitCount == 8) {
-
- flags = PICTURE_BITMAP | PICTURE_UNCOMPRESSED | PICTURE_8BIT;
-
- // For bitmaps, each scanline is dword-aligned.
- BMScanWidth = m_width;
- if (BMScanWidth & 3) {
- BMScanWidth += 4 - (BMScanWidth & 3);
- }
-
- for (int h = hStart; h != hEnd; h += hDir) {
-
- currPixel = 0;
-
- for (int w = 0; w < BMScanWidth; ++w) {
-
- BMPixel8 = input.readUInt8();
-
- if (currPixel < m_width) {
- dest = 3 * ((h * m_width) + currPixel);
- int src = 3 * BMPixel8;
-
- m_byte[dest] = palette[src];
- m_byte[dest + 1] = palette[src + 1];
- m_byte[dest + 2] = palette[src + 2];
-
- ++currPixel;
- }
- }
- }
-
- } else if (bitCount == 16) {
-
- m_memMan->free(m_byte);
- m_byte = NULL;
- System::free(palette);
- palette = NULL;
- throw Error("16-bit bitmaps not supported", input.getFilename());
-
- } else if (bitCount == 24) {
- input.skip(20);
-
- flags = PICTURE_BITMAP | PICTURE_UNCOMPRESSED | PICTURE_24BIT;
-
- // For bitmaps, each scanline is dword-aligned.
- BMScanWidth = m_width * 3;
-
- if (BMScanWidth & 3) {
- BMPadding = 4 - (BMScanWidth & 3);
- } else {
- BMPadding = 0;
- }
-
- for (int h = hStart; h != hEnd; h += hDir) {
- dest = 3 * h * m_width;
- for (int w = 0; w < m_width; ++w) {
-
- blue = input.readUInt8();
- green = input.readUInt8();
- red = input.readUInt8();
-
- m_byte[dest] = red;
- m_byte[dest + 1] = green;
- m_byte[dest + 2] = blue;
-
- dest += 3;
- }
-
- if (BMPadding) {
- input.skip(2);
- }
- }
-
- } else if (bitCount == 32) {
-
- m_memMan->free(m_byte);
- m_byte = NULL;
- System::free(palette);
- palette = NULL;
- throw Error("32 bit bitmaps not supported", input.getFilename());
-
- } else {
- // We support all possible bit depths, so if the
- // code gets here, it's not even a real bitmap.
- m_memMan->free(m_byte);
- m_byte = NULL;
- throw Error("Not a bitmap!", input.getFilename());
- }
-
- System::free(palette);
- palette = NULL;
-}
-
-
-void GImage::decodeICO(
- BinaryInput& input) {
-
- // Header
- uint16 r = input.readUInt16();
- debugAssert(r == 0);
- r = input.readUInt16();
- debugAssert(r == 1);
-
- // Read the number of icons, although we'll only load the
- // first one.
- int count = input.readUInt16();
-
- m_channels = 4;
-
- debugAssert(count > 0);
-
- const uint8* headerBuffer = input.getCArray() + input.getPosition();
- int maxWidth = 0, maxHeight = 0;
- int maxHeaderNum = 0;
- for (int currentHeader = 0; currentHeader < count; ++currentHeader) {
-
- const uint8* curHeaderBuffer = headerBuffer + (currentHeader * 16);
- int tmpWidth = curHeaderBuffer[0];
- int tmpHeight = curHeaderBuffer[1];
- // Just in case there is a non-square icon, checking area
- if ((tmpWidth * tmpHeight) > (maxWidth * maxHeight)) {
- maxWidth = tmpWidth;
- maxHeight = tmpHeight;
- maxHeaderNum = currentHeader;
- }
- }
-
- input.skip(maxHeaderNum * 16);
-
- m_width = input.readUInt8();
- m_height = input.readUInt8();
- int numColors = input.readUInt8();
-
- m_byte = (uint8*)m_memMan->alloc(m_width * m_height * m_channels);
- debugAssert(m_byte);
-
- // Bit mask for packed bits
- int mask = 0;
-
- int bitsPerPixel = 8;
-
- switch (numColors) {
- case 2:
- mask = 0x01;
- bitsPerPixel = 1;
- break;
-
- case 16:
- mask = 0x0F;
- bitsPerPixel = 4;
- break;
-
- case 0:
- numColors = 256;
- mask = 0xFF;
- bitsPerPixel = 8;
- break;
-
- default:
- throw Error("Unsupported ICO color count.", input.getFilename());
- }
-
- input.skip(5);
- // Skip 'size' unused
- input.skip(4);
-
- int offset = input.readUInt32();
-
- // Skip over any other icon descriptions
- input.setPosition(offset);
-
- // Skip over bitmap header; it is redundant
- input.skip(40);
-
- Array<Color4uint8> palette;
- palette.resize(numColors, true);
- for (int c = 0; c < numColors; ++c) {
- palette[c].b = input.readUInt8();
- palette[c].g = input.readUInt8();
- palette[c].r = input.readUInt8();
- palette[c].a = input.readUInt8();
- }
-
- // The actual image and mask follow
-
- // The XOR Bitmap is stored as 1-bit, 4-bit or 8-bit uncompressed Bitmap
- // using the same encoding as BMP files. The AND Bitmap is stored in as
- // 1-bit uncompressed Bitmap.
- //
- // Pixels are stored bottom-up, left-to-right. Pixel lines are padded
- // with zeros to end on a 32bit (4byte) boundary. Every line will have the
- // same number of bytes. Color indices are zero based, meaning a pixel color
- // of 0 represents the first color table entry, a pixel color of 255 (if there
- // are that many) represents the 256th entry.
-/*
- int bitsPerRow = width * bitsPerPixel;
- int bytesPerRow = iCeil((double)bitsPerRow / 8);
- // Rows are padded to 32-bit boundaries
- bytesPerRow += bytesPerRow % 4;
-
- // Read the XOR values into the color channel
- for (int y = height - 1; y >= 0; --y) {
- int x = 0;
- // Read the row
- for (int i = 0; i < bytesPerRow; ++i) {
- uint8 byte = input.readUInt8();
- for (int j = 0; (j < 8) && (x < width); ++x, j += bitsPerPixel) {
- int bit = ((byte << j) >> (8 - bitsPerPixel)) & mask;
- pixel4(x, y) = colorTable[bit];
- }
- }
- }
-*/
- int hStart = 0;
- int hEnd = 0;
- int hDir = 0;
-
- if (m_height < 0) {
- m_height = -m_height;
- hStart = 0;
- hEnd = m_height;
- hDir = 1;
- } else {
- //height = height;
- hStart = m_height - 1;
- hEnd = -1;
- hDir = -1;
- }
-
- int BMScanWidth;
- uint8 BMGroup;
- uint8 BMPixel8;
- int currPixel;
- int dest;
-
- if (bitsPerPixel == 1) {
- // Note that this file is not necessarily grayscale, since it's possible
- // the palette is blue-and-white, or whatever. But of course most image
- // programs only write 1-bit images if they're black-and-white.
-
- // For bitmaps, each scanline is dword-aligned.
- BMScanWidth = (m_width + 7) >> 3;
- if (BMScanWidth & 3) {
- BMScanWidth += 4 - (BMScanWidth & 3);
- }
-
- // Powers of 2
- int pow2[8] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
-
- for (int h = hStart; h != hEnd; h += hDir) {
-
- currPixel = 0;
- dest = 3 * h * m_width;
-
- for (int w = 0; w < BMScanWidth; ++w) {
-
- BMGroup = input.readUInt8();
-
- // Now we read the pixels. Usually there are eight pixels per byte,
- // since each pixel is represented by one bit, but if the width
- // is not a multiple of eight, the last byte will have some bits
- // set, with the others just being extra. Plus there's the
- // dword-alignment padding. So we keep checking to see if we've
- // already read "width" number of pixels.
- for (int i = 7; i >= 0; --i) {
- if (currPixel < m_width) {
- int src = ((BMGroup & pow2[i]) >> i);
-
- m_byte[dest] = palette[src].r;
- m_byte[dest + 1] = palette[src].g;
- m_byte[dest + 2] = palette[src].b;
-
- ++currPixel;
- dest += 4;
- }
- }
- }
- }
-
- } else if (bitsPerPixel == 4) {
-
- // For bitmaps, each scanline is dword-aligned.
- int BMScanWidth = (m_width + 1) >> 1;
- if (BMScanWidth & 3) {
- BMScanWidth += 4 - (BMScanWidth & 3);
- }
-
- for (int h = hStart; h != hEnd; h += hDir) {
-
- currPixel = 0;
- dest = 4 * h * m_width;
-
- for (int w = 0; w < BMScanWidth; w++) {
-
- BMGroup = input.readUInt8();
- int src[2];
- src[0] = ((BMGroup & 0xF0) >> 4);
- src[1] = (BMGroup & 0x0F);
-
- // Now we read the pixels. Usually there are two pixels per byte,
- // since each pixel is represented by four bits, but if the width
- // is not a multiple of two, the last byte will have only four bits
- // set, with the others just being extra. Plus there's the
- // dword-alignment padding. So we keep checking to see if we've
- // already read "Width" number of pixels.
-
- for (int i = 0; i < 2; ++i) {
- if (currPixel < m_width) {
- int tsrc = src[i];
-
- m_byte[dest] = palette[tsrc].r;
- m_byte[dest + 1] = palette[tsrc].g;
- m_byte[dest + 2] = palette[tsrc].b;
-
- ++currPixel;
- dest += 4;
- }
- }
- }
- }
-
- } else if (bitsPerPixel == 8) {
-
- // For bitmaps, each scanline is dword-aligned.
- BMScanWidth = m_width;
- if (BMScanWidth & 3) {
- BMScanWidth += 4 - (BMScanWidth & 3);
- }
-
- for (int h = hStart; h != hEnd; h += hDir) {
-
- currPixel = 0;
-
- for (int w = 0; w < BMScanWidth; ++w) {
-
- BMPixel8 = input.readUInt8();
-
- if (currPixel < m_width) {
- dest = 4 * ((h * m_width) + currPixel);
- int src = BMPixel8;
-
- m_byte[dest] = palette[src].r;
- m_byte[dest + 1] = palette[src].g;
- m_byte[dest + 2] = palette[src].b;
-
- ++currPixel;
- }
- }
- }
- }
-
- // Read the mask into the alpha channel
- int bitsPerRow = m_width;
- int bytesPerRow = iCeil((double)bitsPerRow / 8);
-
- // For bitmaps, each scanline is dword-aligned.
- //BMScanWidth = (width + 1) >> 1;
- if (bytesPerRow & 3) {
- bytesPerRow += 4 - (bytesPerRow & 3);
- }
-
- for (int y = m_height - 1; y >= 0; --y) {
- int x = 0;
- // Read the row
- for (int i = 0; i < bytesPerRow; ++i) {
- uint8 byte = input.readUInt8();
- for (int j = 0; (j < 8) && (x < m_width); ++x, ++j) {
- int bit = (byte >> (7 - j)) & 0x01;
- pixel4(x, y).a = (1 - bit) * 0xFF;
- }
- }
- }
-
-}
-
-
-}
diff --git a/dep/g3dlite/source/GImage_jpeg.cpp b/dep/g3dlite/source/GImage_jpeg.cpp
deleted file mode 100644
index 0b0521f31e7..00000000000
--- a/dep/g3dlite/source/GImage_jpeg.cpp
+++ /dev/null
@@ -1,446 +0,0 @@
-/**
- @file GImage_jpeg.cpp
- @author Morgan McGuire, http://graphics.cs.williams.edu
- @created 2002-05-27
- @edited 2009-04-20
- */
-#include "G3D/platform.h"
-#include "G3D/GImage.h"
-#include "G3D/BinaryInput.h"
-#include "G3D/BinaryOutput.h"
-
-#include <cstring>
-
-extern "C" {
-#ifdef G3D_LINUX
-# include <jconfig.h>
-# include <jpeglib.h>
-#else
-# include "jconfig.h"
-# include "jpeglib.h"
-#endif
-}
-
-namespace G3D {
-
-
-const int jpegQuality = 96;
-
-/**
- The IJG library needs special setup for compress/decompressing
- from memory. These classes provide them.
-
- The format of this class is defined by the IJG library; do not
- change it.
- */
-class memory_destination_mgr {
-public:
- struct jpeg_destination_mgr pub;
- JOCTET* buffer;
- int size;
- int count;
-};
-
-typedef memory_destination_mgr* mem_dest_ptr;
-
-/**
- Signature dictated by IJG.
- */
-static void init_destination (
- j_compress_ptr cinfo) {
-
- mem_dest_ptr dest = (mem_dest_ptr) cinfo->dest;
-
- dest->pub.next_output_byte = dest->buffer;
- dest->pub.free_in_buffer = dest->size;
- dest->count=0;
-}
-
-/**
- Signature dictated by IJG.
- */
-static boolean empty_output_buffer (
- j_compress_ptr cinfo) {
-
- mem_dest_ptr dest = (mem_dest_ptr) cinfo->dest;
-
- dest->pub.next_output_byte = dest->buffer;
- dest->pub.free_in_buffer = dest->size;
-
- return TRUE;
-}
-
-/**
- Signature dictated by IJG.
- */
-static void term_destination (
- j_compress_ptr cinfo) {
-
- mem_dest_ptr dest = (mem_dest_ptr) cinfo->dest;
- dest->count = dest->size - dest->pub.free_in_buffer;
-}
-
-/**
- Signature dictated by IJG.
- */
-static void jpeg_memory_dest (
- j_compress_ptr cinfo,
- JOCTET* buffer,
- int size) {
-
- mem_dest_ptr dest;
-
- if (cinfo->dest == NULL) {
- // First time for this JPEG object; call the
- // IJG allocator to get space.
- cinfo->dest = (struct jpeg_destination_mgr*)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo,
- JPOOL_PERMANENT,
- sizeof(memory_destination_mgr));
- }
-
- dest = (mem_dest_ptr) cinfo->dest;
- dest->size = size;
- dest->buffer = buffer;
- dest->pub.init_destination = init_destination;
- dest->pub.empty_output_buffer = empty_output_buffer;
- dest->pub.term_destination = term_destination;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-
-#define INPUT_BUF_SIZE 4096
-
-/**
- Structure dictated by IJG.
- */
-class memory_source_mgr {
-public:
- struct jpeg_source_mgr pub;
- int source_size;
- unsigned char* source_data;
- boolean start_of_data;
- JOCTET* buffer;
-};
-
-
-typedef memory_source_mgr* mem_src_ptr;
-
-
-/**
- Signature dictated by IJG.
- */
-static void init_source(
- j_decompress_ptr cinfo) {
-
- mem_src_ptr src = (mem_src_ptr) cinfo->src;
-
- src->start_of_data = TRUE;
-}
-
-
-/**
- Signature dictated by IJG.
- */
-static boolean fill_input_buffer(
- j_decompress_ptr cinfo) {
-
- mem_src_ptr src = (mem_src_ptr) cinfo->src;
-
- size_t bytes_read = 0;
-
- if (src->source_size > INPUT_BUF_SIZE)
- bytes_read = INPUT_BUF_SIZE;
- else
- bytes_read = src->source_size;
-
- memcpy (src->buffer, src->source_data, bytes_read);
-
- src->source_data += bytes_read;
- src->source_size -= bytes_read;
-
- src->pub.next_input_byte = src->buffer;
- src->pub.bytes_in_buffer = bytes_read;
- src->start_of_data = FALSE;
-
-
- return TRUE;
-}
-
-
-/**
- Signature dictated by IJG.
- */
-static void skip_input_data(
- j_decompress_ptr cinfo,
- long num_bytes) {
-
- mem_src_ptr src = (mem_src_ptr)cinfo->src;
-
- if (num_bytes > 0) {
- while (num_bytes > (long) src->pub.bytes_in_buffer) {
- num_bytes -= (long) src->pub.bytes_in_buffer;
- boolean s = fill_input_buffer(cinfo);
- debugAssert(s); (void)s;
- }
-
- src->pub.next_input_byte += (size_t) num_bytes;
- src->pub.bytes_in_buffer -= (size_t) num_bytes;
- }
-}
-
-
-/**
- Signature dictated by IJG.
- */
-static void term_source (
- j_decompress_ptr cinfo) {
- (void)cinfo;
- // Intentionally empty
-}
-
-
-/**
- Signature dictated by IJG.
- */
-static void jpeg_memory_src (
- j_decompress_ptr cinfo,
- JOCTET* buffer,
- int size) {
-
- mem_src_ptr src;
-
- if (cinfo->src == NULL) {
- // First time for this JPEG object
- cinfo->src = (struct jpeg_source_mgr*)
- (*cinfo->mem->alloc_small)(
- (j_common_ptr) cinfo,
- JPOOL_PERMANENT,
- sizeof(memory_source_mgr));
-
- src = (mem_src_ptr)cinfo->src;
-
- src->buffer = (JOCTET*)
- (*cinfo->mem->alloc_small)(
- (j_common_ptr) cinfo,
- JPOOL_PERMANENT,
- INPUT_BUF_SIZE * sizeof(JOCTET));
- }
-
- src = (mem_src_ptr)cinfo->src;
- src->pub.init_source = init_source;
- src->pub.fill_input_buffer = fill_input_buffer;
- src->pub.skip_input_data = skip_input_data;
-
- // use default method
- src->pub.resync_to_restart = jpeg_resync_to_restart;
- src->pub.term_source = term_source;
- src->source_data = buffer;
- src->source_size = size;
-
- // forces fill_input_buffer on first read
- src->pub.bytes_in_buffer = 0;
-
- // until buffer loaded
- src->pub.next_input_byte = NULL;
-}
-
-
-void GImage::encodeJPEG(
- BinaryOutput& out) const {
-
- if (m_channels != 3) {
- // Convert to three channel
- GImage tmp = *this;
- tmp.convertToRGB();
- tmp.encodeJPEG(out);
- return;
- }
-
- debugAssert(m_channels == 3);
- out.setEndian(G3D_LITTLE_ENDIAN);
-
- // Allocate and initialize a compression object
- jpeg_compress_struct cinfo;
- jpeg_error_mgr jerr;
-
- cinfo.err = jpeg_std_error(&jerr);
- jpeg_create_compress(&cinfo);
-
- // Specify the destination for the compressed data.
- // (Overestimate the size)
- int buffer_size = m_width * m_height * 3 + 200;
- JOCTET* compressed_data = (JOCTET*)System::malloc(buffer_size);
- jpeg_memory_dest(&cinfo, compressed_data, buffer_size);
-
-
- cinfo.image_width = m_width;
- cinfo.image_height = m_height;
-
- // # of color components per pixel
- cinfo.input_components = 3;
-
- // colorspace of input image
- cinfo.in_color_space = JCS_RGB;
- cinfo.input_gamma = 1.0;
-
- // Set parameters for compression, including image size & colorspace
- jpeg_set_defaults(&cinfo);
- jpeg_set_quality(&cinfo, jpegQuality, false);
- cinfo.smoothing_factor = 0;
- cinfo.optimize_coding = TRUE;
-// cinfo.dct_method = JDCT_FLOAT;
- cinfo.dct_method = JDCT_ISLOW;
- cinfo.jpeg_color_space = JCS_YCbCr;
-
- // Initialize the compressor
- jpeg_start_compress(&cinfo, TRUE);
-
- // Iterate over all scanlines from top to bottom
- // pointer to a single row
- JSAMPROW row_pointer[1];
-
- // JSAMPLEs per row in image_buffer
- int row_stride = cinfo.image_width * 3;
- while (cinfo.next_scanline < cinfo.image_height) {
- row_pointer[0] = &(m_byte[cinfo.next_scanline * row_stride]);
- jpeg_write_scanlines(&cinfo, row_pointer, 1);
- }
-
- // Shut down the compressor
- jpeg_finish_compress(&cinfo);
-
- // Figure out how big the result was.
- int outLength = ((mem_dest_ptr)cinfo.dest)->count;
-
- // Release the JPEG compression object
- jpeg_destroy_compress(&cinfo);
-
- // Copy into an appropriately sized output buffer.
- out.writeBytes(compressed_data, outLength);
-
- // Free the conservative buffer.
- System::free(compressed_data);
- compressed_data = NULL;
-}
-
-
-void GImage::decodeJPEG(
- BinaryInput& input) {
-
- struct jpeg_decompress_struct cinfo;
- struct jpeg_error_mgr jerr;
- int loc = 0;
-
- m_channels = 3;
- // We have to set up the error handler, in case initialization fails.
- cinfo.err = jpeg_std_error(&jerr);
-
- // Initialize the JPEG decompression object.
- jpeg_create_decompress(&cinfo);
-
- // Specify data source (eg, a file, for us, memory)
- jpeg_memory_src(&cinfo, const_cast<uint8*>(input.getCArray()), input.size());
-
- // Read the parameters with jpeg_read_header()
- jpeg_read_header(&cinfo, TRUE);
-
- // Set parameters for decompression
- // (We do nothing here since the defaults are fine)
-
- // Start decompressor
- jpeg_start_decompress(&cinfo);
-
- // Get and set the values of interest to this object
- m_width = cinfo.output_width;
- m_height = cinfo.output_height;
-
- // Prepare the pointer object for the pixel data
- m_byte = (uint8*)m_memMan->alloc(m_width * m_height * 3);
-
- // JSAMPLEs per row in output buffer
- int bpp = cinfo.output_components;
- int row_stride = cinfo.output_width * bpp;
-
- // Make a one-row-high sample array that will go away when done with image
- JSAMPARRAY temp = (*cinfo.mem->alloc_sarray)
- ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
-
- // Read data on a scanline by scanline basis
- while (cinfo.output_scanline < cinfo.output_height) {
-
- // We may need to adjust the output based on the
- // number of channels it has.
- switch (bpp) {
- case 1:
- // Grayscale; decompress to temp.
- jpeg_read_scanlines(&cinfo, temp, 1);
-
- // Expand to three channels
- {
- uint8* scan = &(m_byte[loc * 3]);
- uint8* endScan = scan + (m_width * 3);
- uint8* t = *temp;
-
- while (scan < endScan) {
- uint8 value = t[0];
-
- // Spread the value 3x.
- scan[0] = value;
- scan[1] = value;
- scan[2] = value;
-
- scan += 3;
- t += 1;
- }
- }
- break;
-
- case 3:
- // Read directly into the array
- {
- // Need one extra level of indirection.
- uint8* scan = m_byte + loc;
- JSAMPARRAY ptr = &scan;
- jpeg_read_scanlines(&cinfo, ptr, 1);
- }
- break;
-
- case 4:
- // RGBA; decompress to temp.
- jpeg_read_scanlines(&cinfo, temp, 1);
-
- // Drop the 3rd channel
- {
- uint8* scan = &(m_byte[loc * 3]);
- uint8* endScan = scan + m_width * 3;
- uint8* t = *temp;
-
- while (scan < endScan) {
- scan[0] = t[0];
- scan[1] = t[1];
- scan[2] = t[2];
-
- scan += 3;
- t += 4;
- }
- }
- break;
-
- default:
- throw Error("Unexpected number of channels.", input.getFilename());
- }
-
- loc += row_stride;
- }
-
- // Finish decompression
- jpeg_finish_decompress(&cinfo);
-
- alwaysAssertM(this, "Corrupt GImage");
- // Release JPEG decompression object
- jpeg_destroy_decompress(&cinfo);
-}
-
-
-}
diff --git a/dep/g3dlite/source/GImage_png.cpp b/dep/g3dlite/source/GImage_png.cpp
deleted file mode 100644
index 875c7015cd1..00000000000
--- a/dep/g3dlite/source/GImage_png.cpp
+++ /dev/null
@@ -1,276 +0,0 @@
-/**
- @file GImage_png.cpp
- @author Morgan McGuire, http://graphics.cs.williams.edu
- @created 2002-05-27
- @edited 2009-04-20
- */
-#include "G3D/platform.h"
-#include "G3D/GImage.h"
-#include "G3D/BinaryInput.h"
-#include "G3D/BinaryOutput.h"
-#include "G3D/Log.h"
-#include <png.h>
-
-namespace G3D {
-
-
-//libpng required function signature
-static void png_read_data(
- png_structp png_ptr,
- png_bytep data,
- png_size_t length) {
-
-
- debugAssert( png_ptr->io_ptr != NULL );
- debugAssert( length >= 0 );
- debugAssert( data != NULL );
-
- ((BinaryInput*)png_ptr->io_ptr)->readBytes(data, length);
-}
-
-//libpng required function signature
-static void png_write_data(png_structp png_ptr,
- png_bytep data,
- png_size_t length) {
-
- debugAssert( png_ptr->io_ptr != NULL );
- debugAssert( data != NULL );
-
- ((BinaryOutput*)png_ptr->io_ptr)->writeBytes(data, length);
-}
-
-//libpng required function signature
-static void png_flush_data(
- png_structp png_ptr) {
- (void)png_ptr;
- //Do nothing.
-}
-
-//libpng required function signature
-static void png_error(
- png_structp png_ptr,
- png_const_charp error_msg) {
-
- (void)png_ptr;
- debugAssert( error_msg != NULL );
- throw GImage::Error(error_msg, "PNG");
-}
-
-
-//libpng required function signature
-void png_warning(
- png_structp png_ptr,
- png_const_charp warning_msg) {
-
- (void)png_ptr;
- debugAssert( warning_msg != NULL );
- Log::common()->println(warning_msg);
-}
-
-
-void GImage::encodePNG(
- BinaryOutput& out) const {
-
- if (! (m_channels == 1 || m_channels == 3 || m_channels == 4)) {
- throw GImage::Error(format("Illegal channels for PNG: %d", m_channels), out.getFilename());
- }
- if (m_width <= 0) {
- throw GImage::Error(format("Illegal width for PNG: %d", m_width), out.getFilename());
- }
- if (m_height <= 0) {
- throw GImage::Error(format("Illegal height for PNG: %d", m_height), out.getFilename());
- }
-
- // PNG library requires that the height * pointer size fit within an int
- if (png_uint_32(m_height) * png_sizeof(png_bytep) > PNG_UINT_32_MAX) {
- throw GImage::Error("Unsupported PNG height.", out.getFilename());
- }
-
- out.setEndian(G3D_LITTLE_ENDIAN);
-
- png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, png_error, png_warning);
- if (! png_ptr) {
- throw GImage::Error("Unable to initialize PNG encoder.", out.getFilename());
- }
-
- png_infop info_ptr = png_create_info_struct(png_ptr);
- if (! info_ptr) {
- png_destroy_write_struct(&png_ptr, &info_ptr);
- throw GImage::Error("Unable to initialize PNG encoder.", out.getFilename());
- }
-
- //setup libpng write handler so can use BinaryOutput
- png_set_write_fn(png_ptr, (void*)&out, png_write_data, png_flush_data);
- png_color_8_struct sig_bit;
-
- switch (m_channels) {
- case 1:
- png_set_IHDR(png_ptr, info_ptr, m_width, m_height, 8, PNG_COLOR_TYPE_GRAY,
- PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
- sig_bit.red = 0;
- sig_bit.green = 0;
- sig_bit.blue = 0;
- sig_bit.alpha = 0;
- sig_bit.gray = 8;
- break;
-
- case 3:
- png_set_IHDR(png_ptr, info_ptr, m_width, m_height, 8, PNG_COLOR_TYPE_RGB,
- PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
-
- sig_bit.red = 8;
- sig_bit.green = 8;
- sig_bit.blue = 8;
- sig_bit.alpha = 0;
- sig_bit.gray = 0;
- break;
-
- case 4:
- png_set_IHDR(png_ptr, info_ptr, m_width, m_height, 8, PNG_COLOR_TYPE_RGBA,
- PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
- sig_bit.red = 8;
- sig_bit.green = 8;
- sig_bit.blue = 8;
- sig_bit.alpha = 8;
- sig_bit.gray = 0;
- break;
-
- default:
- png_destroy_write_struct(&png_ptr, &info_ptr);
- throw GImage::Error("Unsupported number of channels for PNG.", out.getFilename());
- }
-
-
- png_set_sBIT(png_ptr, info_ptr, &sig_bit);
-
- //write the png header
- png_write_info(png_ptr, info_ptr);
-
- png_bytepp row_pointers = new png_bytep[m_height];
-
- for (int i=0; i < m_height; ++i) {
- row_pointers[i] = (png_bytep)&m_byte[m_width * m_channels * i];
- }
-
- png_write_image(png_ptr, row_pointers);
-
- png_write_end(png_ptr, info_ptr);
-
- delete[] row_pointers;
-
- png_destroy_write_struct(&png_ptr, &info_ptr);
-}
-
-
-void GImage::decodePNG(
- BinaryInput& input) {
-
- png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, png_error, png_warning);
- if (png_ptr == NULL) {
- throw GImage::Error("Unable to initialize PNG decoder.", input.getFilename());
- }
-
- png_infop info_ptr = png_create_info_struct(png_ptr);
- if (info_ptr == NULL) {
- png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
- throw GImage::Error("Unable to initialize PNG decoder.", input.getFilename());
- }
-
- png_infop end_info = png_create_info_struct(png_ptr);
- if (end_info == NULL) {
- png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
- throw GImage::Error("Unable to initialize PNG decoder.", input.getFilename());
- }
-
- // now that the libpng structures are setup, change the error handlers and read routines
- // to use G3D functions so that BinaryInput can be used.
-
- png_set_read_fn(png_ptr, (png_voidp)&input, png_read_data);
-
- // read in sequentially so that three copies of the file are not in memory at once
- png_read_info(png_ptr, info_ptr);
-
- png_uint_32 png_width, png_height;
- int bit_depth, color_type, interlace_type;
- // this will validate the data it extracts from info_ptr
- png_get_IHDR(png_ptr, info_ptr, &png_width, &png_height, &bit_depth, &color_type,
- &interlace_type, NULL, NULL);
-
- if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
- png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
- throw GImage::Error("Unsupported PNG color type - PNG_COLOR_TYPE_GRAY_ALPHA.", input.getFilename());
- }
-
- m_width = static_cast<uint32>(png_width);
- m_height = static_cast<uint32>(png_height);
-
- //swap bytes of 16 bit files to least significant byte first
- png_set_swap(png_ptr);
-
- png_set_strip_16(png_ptr);
-
- //Expand paletted colors into true RGB triplets
- if (color_type == PNG_COLOR_TYPE_PALETTE) {
- png_set_palette_to_rgb(png_ptr);
- }
-
- //Expand grayscale images to the full 8 bits from 1, 2, or 4 bits/pixel
- if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) {
- png_set_expand(png_ptr);
- }
-
- //Expand paletted or RGB images with transparency to full alpha channels
- //so the data will be available as RGBA quartets.
- if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
- png_set_tRNS_to_alpha(png_ptr);
- }
-
- // Fix sub-8 bit_depth to 8bit
- if (bit_depth < 8) {
- png_set_packing(png_ptr);
- }
-
- if ((color_type == PNG_COLOR_TYPE_RGBA) ||
- ((color_type == PNG_COLOR_TYPE_PALETTE) && (png_ptr->num_trans > 0)) ) {
-
- m_channels = 4;
- m_byte = (uint8*)m_memMan->alloc(m_width * m_height * 4);
-
- } else if ((color_type == PNG_COLOR_TYPE_RGB) ||
- (color_type == PNG_COLOR_TYPE_PALETTE)) {
-
- m_channels = 3;
- m_byte = (uint8*)System::malloc(m_width * m_height * 3);
-
- } else if (color_type == PNG_COLOR_TYPE_GRAY) {
-
- m_channels = 1;
-
- // Round up to the nearest 8 rows to avoid a bug in the PNG decoder
- int h = iCeil(m_height / 8) * 8;
- int sz = m_width * h;
- m_byte = (uint8*)m_memMan->alloc(sz);
-
- } else {
- throw GImage::Error("Unsupported PNG bit-depth or type.", input.getFilename());
- }
-
- //since we are reading row by row, required to handle interlacing
- uint32 number_passes = png_set_interlace_handling(png_ptr);
-
- png_read_update_info(png_ptr, info_ptr);
-
- for (uint32 pass = 0; pass < number_passes; ++pass) {
- for (uint32 y = 0; y < (uint32)m_height; ++y) {
- png_bytep rowPointer = &m_byte[m_width * m_channels * y];
- png_read_rows(png_ptr, &rowPointer, NULL, 1);
- }
- }
-
-// png_read_image(png_ptr, &_byte);
- png_read_end(png_ptr, info_ptr);
-
- png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
-}
-
-}
diff --git a/dep/g3dlite/source/GImage_ppm.cpp b/dep/g3dlite/source/GImage_ppm.cpp
deleted file mode 100644
index f3065c6038b..00000000000
--- a/dep/g3dlite/source/GImage_ppm.cpp
+++ /dev/null
@@ -1,217 +0,0 @@
-/**
- @file GImage_ppm.cpp
- @author Morgan McGuire, http://graphics.cs.williams.edu
- @created 2002-05-27
- @edited 2006-05-10
- */
-#include "G3D/platform.h"
-#include "G3D/GImage.h"
-#include "G3D/BinaryInput.h"
-#include "G3D/BinaryOutput.h"
-#include "G3D/TextInput.h"
-#include "G3D/TextOutput.h"
-#include "G3D/Log.h"
-
-namespace G3D {
-
-void GImage::encodePPMASCII(
- BinaryOutput& out) const {
-
- TextOutput::Settings ppmOptions;
- ppmOptions.convertNewlines = false;
- ppmOptions.numColumns = 70;
- ppmOptions.wordWrap = TextOutput::Settings::WRAP_WITHOUT_BREAKING;
- TextOutput ppm(ppmOptions);
-
- switch (m_channels) {
- case 1:
- {
- ppm.printf("P2\n%d %d\n255\n", m_width, m_height);
-
- const Color1uint8* c = this->pixel1();
- // Insert newlines every 70 characters max
- for (uint32 i = 0; i < (uint32)(m_width * m_height); ++i) {
- ppm.printf("%d%c", c[i].value, (i % (70/4) == 0) ? '\n' : ' ');
- }
- }
- break;
-
- case 3:
- {
- ppm.printf("P3\n%d %d\n255\n", m_width, m_height);
-
- const Color3uint8* c = this->pixel3();
- // Insert newlines every 70 characters max
- for (uint32 i = 0; i < (uint32)(m_width * m_height); ++i) {
- ppm.printf("%d %d %d%c", c[i].r, c[i].g, c[i].b,
- (i % (70/12) == 0) ?
- '\n' : ' ');
- }
- }
- break;
- default:
- alwaysAssertM(false, "PPM requires either 1 or 3 channels exactly.");
- }
-
- const std::string& s = ppm.commitString();
- out.writeBytes(s.c_str(), s.length());
-}
-
-
-void GImage::encodePPM(
- BinaryOutput& out) const {
-
- // http://netpbm.sourceforge.net/doc/ppm.html
- if (m_channels == 3) {
- std::string header = format("P6 %d %d 255 ", m_width, m_height);
- out.writeBytes(header.c_str(), header.size());
- out.writeBytes(this->pixel3(), m_width * m_height * 3);
- } else if (m_channels == 1) {
- std::string header = format("P5 %d %d 255 ", m_width, m_height);
- out.writeBytes(header.c_str(), header.size());
- out.writeBytes(this->pixel1(), m_width * m_height);
- } else {
- alwaysAssertM(false, "PPM requires either 1 or 3 channels exactly.");
- }
-}
-
-
-void GImage::decodePPMASCII(
- BinaryInput& input) {
-
- int ppmWidth;
- int ppmHeight;
-
- double maxColor;
-
- // Create a TextInput object to parse ascii format
- // Mixed binary/ascii formats will require more
-
- const std::string inputStr = input.readString();
-
- TextInput::Settings ppmOptions;
- ppmOptions.cppLineComments = false;
- ppmOptions.otherCommentCharacter = '#';
- ppmOptions.signedNumbers = true;
- ppmOptions.singleQuotedStrings = false;
-
- TextInput ppmInput(TextInput::FROM_STRING, inputStr, ppmOptions);
-
- //Skip first line in header P#
- std::string ppmType = ppmInput.readSymbol();
-
- ppmWidth = (int)ppmInput.readNumber();
- ppmHeight = (int)ppmInput.readNumber();
-
- // Everything but a PBM will have a max color value
- if (ppmType != "P2") {
- maxColor = ppmInput.readNumber();
- } else {
- maxColor = 255;
- }
-
- if ((ppmWidth < 0) ||
- (ppmHeight < 0) ||
- (maxColor <= 0)) {
- throw GImage::Error("Invalid PPM Header.", input.getFilename());
- }
-
- // I don't think it's proper to scale values less than 255
- if (maxColor <= 255.0) {
- maxColor = 255.0;
- }
-
- m_width = ppmWidth;
- m_height = ppmHeight;
- m_channels = 3;
- // always scale down to 1 byte per channel
- m_byte = (uint8*)m_memMan->alloc(m_width * m_height * 3);
-
- // Read in the image data. I am not validating if the values match the maxColor
- // requirements. I only scale if needed to fit within the byte available.
- for (uint32 i = 0; i < (uint32)(m_width * m_height); ++i) {
- // read in color and scale to max pixel defined in header
- // A max color less than 255 might need to be left alone and not scaled.
- Color3uint8& curPixel = *(pixel3() + i);
-
- if (ppmType == "P3") {
- curPixel.r = (uint8)(ppmInput.readNumber() * (255.0 / maxColor));
- curPixel.g = (uint8)(ppmInput.readNumber() * (255.0 / maxColor));
- curPixel.b = (uint8)(ppmInput.readNumber() * (255.0 / maxColor));
- } else if (ppmType == "P2") {
- uint8 pixel = (uint8)(ppmInput.readNumber() * (255.0 / maxColor));
- curPixel.r = pixel;
- curPixel.g = pixel;
- curPixel.b = pixel;
- } else if (ppmType == "P1") {
- int pixel = (uint8)(ppmInput.readNumber() * maxColor);
- curPixel.r = pixel;
- curPixel.g = pixel;
- curPixel.b = pixel;
- }
- }
-}
-
-/** Consumes whitespace up to and including a number, but not the following character */
-static int scanUInt(BinaryInput& input) {
- char c = input.readUInt8();
- while (isWhiteSpace(c)) {
- c = input.readUInt8();
- }
-
- std::string s;
- s += c;
- c = input.readUInt8();
- while (!isWhiteSpace(c)) {
- s += c;
- c = input.readUInt8();
- }
-
- // Back up one to avoid consuming the last character
- input.setPosition(input.getPosition() - 1);
-
- int x;
- sscanf(s.c_str(), "%d", &x);
- return x;
-}
-
-
-void GImage::decodePPM(
- BinaryInput& input) {
-
- char head[2];
- int w, h;
-
- input.readBytes(head, 2);
- if (head[0] != 'P' || ((head[1] != '6') && (head[1] != '5'))) {
- throw GImage::Error("Invalid PPM Header.", input.getFilename());
- }
-
- w = scanUInt(input);
- h = scanUInt(input);
-
- // Skip the max color specifier
- scanUInt(input);
-
- if ((w < 0) ||
- (h < 0) ||
- (w > 100000) ||
- (h > 100000)) {
- throw GImage::Error("Invalid PPM size in header.", input.getFilename());
- }
-
- // Trailing whitespace
- input.readUInt8();
-
- if (head[1] == '6') {
- // 3 channel
- resize(w, h, 3);
- input.readBytes(m_byte, m_width * m_height * 3);
- } else if (head[1] == '5') {
- // 1 channel
- resize(w, h, 1);
- input.readBytes(m_byte, m_width * m_height);
- }
-}
-
-}
diff --git a/dep/g3dlite/source/GImage_tga.cpp b/dep/g3dlite/source/GImage_tga.cpp
deleted file mode 100644
index fdcd59af726..00000000000
--- a/dep/g3dlite/source/GImage_tga.cpp
+++ /dev/null
@@ -1,236 +0,0 @@
-/**
- @file GImage_tga.cpp
- @author Morgan McGuire, http://graphics.cs.williams.edu
- @created 2002-05-27
- @edited 2009-05-10
- */
-#include "G3D/platform.h"
-#include "G3D/GImage.h"
-#include "G3D/BinaryInput.h"
-#include "G3D/BinaryOutput.h"
-#include "G3D/Log.h"
-
-namespace G3D {
-
-void GImage::encodeTGA(
- BinaryOutput& out) const {
-
- out.setEndian(G3D_LITTLE_ENDIAN);
-
- // ID length
- out.writeUInt8(0);
-
- // Color map Type
- out.writeUInt8(0);
-
- // Type
- out.writeUInt8(2);
-
- // Color map
- out.skip(5);
-
- // x, y offsets
- out.writeUInt16(0);
- out.writeUInt16(0);
-
- // Width & height
- out.writeUInt16(m_width);
- out.writeUInt16(m_height);
-
- // Color depth
- if (m_channels == 1) {
- // Force RGB mode
- out.writeUInt8(8 * 3);
- } else {
- out.writeUInt8(8 * m_channels);
- }
-
- // Image descriptor
- if (m_channels < 4) {
- // 0 alpha bits
- out.writeUInt8(0);
- } else {
- // 8 alpha bits
- out.writeUInt8(8);
- }
-
- // Image ID (zero length)
-
- if (m_channels == 1) {
- // Pixels are upside down in BGR format.
- for (int y = m_height - 1; y >= 0; --y) {
- for (int x = 0; x < m_width; ++x) {
- uint8 p = (m_byte[(y * m_width + x)]);
- out.writeUInt8(p);
- out.writeUInt8(p);
- out.writeUInt8(p);
- }
- }
- } else if (m_channels == 3) {
- // Pixels are upside down in BGR format.
- for (int y = m_height - 1; y >= 0; --y) {
- for (int x = 0; x < m_width; ++x) {
- uint8* p = &(m_byte[3 * (y * m_width + x)]);
- out.writeUInt8(p[2]);
- out.writeUInt8(p[1]);
- out.writeUInt8(p[0]);
- }
- }
- } else {
- // Pixels are upside down in BGRA format.
- for (int y = m_height - 1; y >= 0; --y) {
- for (int x = 0; x < m_width; ++x) {
- uint8* p = &(m_byte[4 * (y * m_width + x)]);
- out.writeUInt8(p[2]);
- out.writeUInt8(p[1]);
- out.writeUInt8(p[0]);
- out.writeUInt8(p[3]);
- }
- }
- }
-
- // Write "TRUEVISION-XFILE " 18 bytes from the end
- // (with null termination)
- out.writeString("TRUEVISION-XFILE ");
-}
-
-inline static void readBGR(uint8* byte, BinaryInput& bi) {
- int b = bi.readUInt8();
- int g = bi.readUInt8();
- int r = bi.readUInt8();
-
- byte[0] = r;
- byte[1] = g;
- byte[2] = b;
-}
-
-inline static void readBGRA(uint8* byte, BinaryInput& bi) {
- readBGR(byte, bi);
- byte[3] = bi.readUInt8();
-}
-
-void GImage::decodeTGA(
- BinaryInput& input) {
-
- // This is a simple TGA loader that can handle uncompressed
- // truecolor TGA files (TGA type 2).
- // Verify this is a TGA file by looking for the TRUEVISION tag.
- int pos = input.getPosition();
- input.setPosition(input.size() - 18);
- std::string tag = input.readString(16);
- if (tag != "TRUEVISION-XFILE") {
- throw Error("Not a TGA file", input.getFilename());
- }
-
- input.setPosition(pos);
-
- int IDLength = input.readUInt8();
- int colorMapType = input.readUInt8();
- int imageType = input.readUInt8();
-
- (void)colorMapType;
-
- // 2 is the type supported by this routine.
- if (imageType != 2 && imageType != 10) {
- throw Error("TGA images must be type 2 (Uncompressed truecolor) or 10 (Run-length truecolor)", input.getFilename());
- }
-
- // Color map specification
- input.skip(5);
-
- // Image specification
-
- // Skip x and y offsets
- input.skip(4);
-
- m_width = input.readInt16();
- m_height = input.readInt16();
-
- int colorDepth = input.readUInt8();
-
- if ((colorDepth != 24) && (colorDepth != 32)) {
- throw Error("TGA files must be 24 or 32 bit.", input.getFilename());
- }
-
- if (colorDepth == 32) {
- m_channels = 4;
- } else {
- m_channels = 3;
- }
-
- // Image descriptor contains overlay data as well
- // as data indicating where the origin is
- int imageDescriptor = input.readUInt8();
- (void)imageDescriptor;
-
- // Image ID
- input.skip(IDLength);
-
- m_byte = (uint8*)m_memMan->alloc(m_width * m_height * m_channels);
- debugAssert(m_byte);
-
- // Pixel data
- int x;
- int y;
-
- if (imageType == 2) {
- // Uncompressed
- if (m_channels == 3) {
- for (y = m_height - 1; y >= 0; --y) {
- for (x = 0; x < m_width; ++x) {
- int i = (x + y * m_width) * 3;
- readBGR(m_byte + i, input);
- }
- }
- } else {
- for (y = m_height - 1; y >= 0; --y) {
- for (x = 0; x < m_width; ++x) {
- int i = (x + y * m_width) * 4;
- readBGRA(m_byte + i, input);
- }
- }
- }
- } else if (imageType == 10) {
-
- // Run-length encoded
- for (y = m_height - 1; y >= 0; --y) {
- for (int x = 0; x < m_width; /* intentionally no x increment */) {
- // The specification guarantees that no packet will wrap past the end of a row
- const uint8 repetitionCount = input.readUInt8();
- const uint8 numValues = (repetitionCount & (~128)) + 1;
- int byteOffset = (x + y * m_width) * 3;
-
- if (repetitionCount & 128) {
- // When the high bit is 1, this is a run-length packet
- if (m_channels == 3) {
- Color3uint8 value;
- readBGR((uint8*)(&value), input);
- for (int i = 0; i < numValues; ++i, ++x) {
- for (int b = 0; b < 3; ++b, ++byteOffset) {
- m_byte[byteOffset] = value[b];
- }
- }
- } else {
- Color4uint8 value;
- readBGRA((uint8*)(&value), input);
- for (int i = 0; i < numValues; ++i, ++x) {
- for (int b = 0; b < 3; ++b, ++byteOffset) {
- m_byte[byteOffset] = value[b];
- }
- }
- }
-
- } else {
- // When the high bit is 0, this is a raw packet
- for (int i = 0; i < numValues; ++i, ++x, byteOffset += m_channels) {
- readBGR(m_byte + byteOffset, input);
- }
- }
- }
- }
- } else {
- alwaysAssertM(false, "Unsupported type");
- }
-}
-
-}
diff --git a/dep/g3dlite/source/GLight.cpp b/dep/g3dlite/source/GLight.cpp
deleted file mode 100644
index 553b493c1a3..00000000000
--- a/dep/g3dlite/source/GLight.cpp
+++ /dev/null
@@ -1,275 +0,0 @@
-/**
- @file GLight.cpp
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2003-11-12
- @edited 2009-11-16
-*/
-#include "G3D/GLight.h"
-#include "G3D/Sphere.h"
-#include "G3D/CoordinateFrame.h"
-#include "G3D/Any.h"
-#include "G3D/stringutils.h"
-
-namespace G3D {
-
-GLight::GLight(const Any& any) {
- any.verifyName("GLight");
-
- if (any.type() == Any::TABLE) {
- *this = GLight();
- Vector3 spotTarget;
- bool hasSpotTarget = false;
- for (Any::AnyTable::Iterator it = any.table().begin(); it.hasMore(); ++it) {
- const std::string& key = toLower(it->key);
- if (key == "position") {
- position = it->value;
- } else if (key == "rightdirection") {
- rightDirection = it->value;
- } else if (key == "spotdirection") {
- spotDirection = Vector3(it->value).directionOrZero();
- } else if (key == "spottarget") {
- spotTarget = it->value;
- hasSpotTarget = true;
- } else if (key == "spotcutoff") {
- spotCutoff = it->value.number();
- } else if (key == "spotsquare") {
- spotSquare = it->value.boolean();
- } else if (key == "attenuation") {
- attenuation[0] = it->value[0].number();
- attenuation[1] = it->value[1].number();
- attenuation[2] = it->value[2].number();
- } else if (key == "color") {
- color = it->value;
- } else if (key == "enabled") {
- enabled = it->value.boolean();
- } else if (key == "specular") {
- specular = it->value.boolean();
- } else if (key == "diffuse") {
- diffuse = it->value.boolean();
- } else {
- any.verify(false, "Illegal key: " + it->key);
- }
- }
- if (hasSpotTarget) {
- spotDirection = (spotTarget - position.xyz()).direction();
- }
- } else if (toLower(any.name()) == "glight::directional") {
-
- *this = directional(any[0], any[1],
- (any.size() > 2) ? any[2] : Any(true),
- (any.size() > 3) ? any[3] : Any(true));
-
- } else if (toLower(any.name()) == "glight::point") {
-
- *this = point(any[0], any[1],
- (any.size() > 2) ? any[2] : Any(1),
- (any.size() > 3) ? any[3] : Any(0),
- (any.size() > 4) ? any[4] : Any(0.5f),
- (any.size() > 5) ? any[5] : Any(true),
- (any.size() > 6) ? any[6] : Any(true));
-
- } else if (toLower(any.name()) == "glight::spot") {
-
- *this = spot(any[0], any[1], any[2], any[3],
- (any.size() > 4) ? any[4] : Any(1),
- (any.size() > 5) ? any[5] : Any(0),
- (any.size() > 6) ? any[6] : Any(0),
- (any.size() > 7) ? any[7] : Any(true),
- (any.size() > 8) ? any[8] : Any(true));
- } else {
- any.verify(false, "Unrecognized name");
- }
-}
-
-
-GLight::operator Any() const {
- Any a(Any::TABLE, "GLight");
- a.set("position", position.operator Any());
- a.set("rightDirection", rightDirection.operator Any());
- a.set("spotDirection", spotDirection.operator Any());
- a.set("spotCutoff", spotCutoff);
- a.set("spotSquare", spotSquare);
-
- Any att(Any::ARRAY);
- att.append(attenuation[0], attenuation[1], attenuation[2]);
- a.set("attenuation", att);
- a.set("color", color.operator Any());
- a.set("enabled", enabled);
- a.set("specular", specular);
- a.set("diffuse", diffuse);
- return a;
-}
-
-
-GLight::GLight() :
- position(0, 0, 0, 0),
- rightDirection(0,0,0),
- spotDirection(0, 0, -1),
- spotCutoff(180),
- spotSquare(false),
- color(Color3::white()),
- enabled(false),
- specular(true),
- diffuse(true) {
-
- attenuation[0] = 1.0;
- attenuation[1] = 0.0;
- attenuation[2] = 0.0;
-}
-
-
-GLight GLight::directional(const Vector3& toLight, const Color3& color, bool s, bool d) {
- GLight L;
- L.position = Vector4(toLight.direction(), 0);
- L.color = color;
- L.specular = s;
- L.diffuse = d;
- return L;
-}
-
-
-GLight GLight::point(const Vector3& pos, const Color3& color, float constAtt, float linAtt, float quadAtt, bool s, bool d) {
- GLight L;
- L.position = Vector4(pos, 1);
- L.color = color;
- L.attenuation[0] = constAtt;
- L.attenuation[1] = linAtt;
- L.attenuation[2] = quadAtt;
- L.specular = s;
- L.diffuse = d;
- return L;
-}
-
-
-GLight GLight::spot(const Vector3& pos, const Vector3& pointDirection, float cutOffAngleDegrees, const Color3& color, float constAtt, float linAtt, float quadAtt, bool s, bool d) {
- GLight L;
- L.position = Vector4(pos, 1.0f);
- L.spotDirection = pointDirection.direction();
- debugAssert(cutOffAngleDegrees <= 90);
- L.spotCutoff = cutOffAngleDegrees;
- L.color = color;
- L.attenuation[0] = constAtt;
- L.attenuation[1] = linAtt;
- L.attenuation[2] = quadAtt;
- L.specular = s;
- L.diffuse = d;
- return L;
-}
-
-
-bool GLight::operator==(const GLight& other) const {
- return (position == other.position) &&
- (rightDirection == other.rightDirection) &&
- (spotDirection == other.spotDirection) &&
- (spotCutoff == other.spotCutoff) &&
- (spotSquare == other.spotSquare) &&
- (attenuation[0] == other.attenuation[0]) &&
- (attenuation[1] == other.attenuation[1]) &&
- (attenuation[2] == other.attenuation[2]) &&
- (color == other.color) &&
- (enabled == other.enabled) &&
- (specular == other.specular) &&
- (diffuse == other.diffuse);
-}
-
-
-bool GLight::operator!=(const GLight& other) const {
- return !(*this == other);
-}
-
-
-Sphere GLight::effectSphere(float cutoff) const {
- if (position.w == 0) {
- // Directional light
- return Sphere(Vector3::zero(), finf());
- } else {
- // Avoid divide by zero
- cutoff = max(cutoff, 0.00001f);
- float maxIntensity = max(color.r, max(color.g, color.b));
-
- float radius = finf();
-
- if (attenuation[2] != 0) {
-
- // Solve I / attenuation.dot(1, r, r^2) < cutoff for r
- //
- // a[0] + a[1] r + a[2] r^2 > I/cutoff
- //
-
- float a = attenuation[2];
- float b = attenuation[1];
- float c = attenuation[0] - maxIntensity / cutoff;
-
- float discrim = square(b) - 4 * a * c;
-
- if (discrim >= 0) {
- discrim = sqrt(discrim);
-
- float r1 = (-b + discrim) / (2 * a);
- float r2 = (-b - discrim) / (2 * a);
-
- if (r1 < 0) {
- if (r2 > 0) {
- radius = r2;
- }
- } else if (r2 > 0) {
- radius = min(r1, r2);
- } else {
- radius = r1;
- }
- }
-
- } else if (attenuation[1] != 0) {
-
- // Solve I / attenuation.dot(1, r) < cutoff for r
- //
- // r * a[1] + a[0] = I / cutoff
- // r = (I / cutoff - a[0]) / a[1]
-
- float radius = (maxIntensity / cutoff - attenuation[0]) / attenuation[1];
- radius = max(radius, 0.0f);
- }
-
- return Sphere(position.xyz(), radius);
-
- }
-}
-
-
-CoordinateFrame GLight::frame() const {
- CoordinateFrame f;
- if (rightDirection == Vector3::zero()) {
- // No specified right direction; choose one automatically
- if (position.w == 0) {
- // Directional light
- f.lookAt(-position.xyz());
- } else {
- // Spot light
- f.lookAt(spotDirection);
- }
- } else {
- const Vector3& Z = -spotDirection.direction();
- Vector3 X = rightDirection.direction();
-
- // Ensure the vectors are not too close together
- while (abs(X.dot(Z)) > 0.9f) {
- X = Vector3::random();
- }
-
- // Ensure perpendicular
- X -= Z * Z.dot(X);
- const Vector3& Y = Z.cross(X);
-
- f.rotation.setColumn(Vector3::X_AXIS, X);
- f.rotation.setColumn(Vector3::Y_AXIS, Y);
- f.rotation.setColumn(Vector3::Z_AXIS, Z);
- }
- f.translation = position.xyz();
-
- return f;
-}
-
-
-} // G3D
diff --git a/dep/g3dlite/source/GThread.cpp b/dep/g3dlite/source/GThread.cpp
index 607e4b3572f..5f3f7ffd64e 100644
--- a/dep/g3dlite/source/GThread.cpp
+++ b/dep/g3dlite/source/GThread.cpp
@@ -4,7 +4,7 @@
GThread class.
@created 2005-09-24
- @edited 2005-10-22
+ @edited 2010-09-22
*/
#include "G3D/GThread.h"
@@ -38,7 +38,7 @@ GThread::GThread(const std::string& name):
m_status(STATUS_CREATED),
m_name(name) {
-#ifdef G3D_WIN32
+#ifdef G3D_WINDOWS
m_event = NULL;
#endif
@@ -56,15 +56,16 @@ GThread::~GThread() {
# pragma warning( pop )
#endif
-#ifdef G3D_WIN32
+#ifdef G3D_WINDOWS
if (m_event) {
::CloseHandle(m_event);
}
#endif
}
+
GThreadRef GThread::create(const std::string& name, void (*proc)(void*), void* param) {
- return new _internal::BasicThread(name, proc, param);
+ return shared_ptr<GThread>(new _internal::BasicThread(name, proc, param));
}
@@ -72,6 +73,38 @@ bool GThread::started() const {
return m_status != STATUS_CREATED;
}
+
+int GThread::numCores() {
+ return System::numCores();
+}
+
+#ifdef G3D_WINDOWS
+// From http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx
+const DWORD MS_VC_EXCEPTION=0x406D1388;
+
+#pragma pack(push,8)
+typedef struct tagTHREADNAME_INFO {
+ DWORD dwType; // Must be 0x1000.
+ LPCSTR szName; // Pointer to name (in user addr space).
+ DWORD dwThreadID; // Thread ID (-1=caller thread).
+ DWORD dwFlags; // Reserved for future use, must be zero.
+} THREADNAME_INFO;
+#pragma pack(pop)
+
+static void SetThreadName(DWORD dwThreadID, const char* threadName) {
+ THREADNAME_INFO info;
+ info.dwType = 0x1000;
+ info.szName = threadName;
+ info.dwThreadID = dwThreadID;
+ info.dwFlags = 0;
+
+ __try {
+ RaiseException( MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(ULONG_PTR), (ULONG_PTR*)&info );
+ } __except(EXCEPTION_EXECUTE_HANDLER) {}
+}
+#endif
+
+
bool GThread::start(SpawnBehavior behavior) {
debugAssertM(! started(), "Thread has already executed.");
@@ -89,7 +122,7 @@ bool GThread::start(SpawnBehavior behavior) {
return true;
}
-# ifdef G3D_WIN32
+# ifdef G3D_WINDOWS
DWORD threadId;
m_event = ::CreateEvent(NULL, TRUE, FALSE, NULL);
@@ -102,6 +135,8 @@ bool GThread::start(SpawnBehavior behavior) {
m_event = NULL;
}
+ SetThreadName(threadId, m_name.c_str());
+
return (m_handle != NULL);
# else
if (!pthread_create(&m_handle, NULL, &internalThreadProc, this)) {
@@ -117,7 +152,7 @@ bool GThread::start(SpawnBehavior behavior) {
void GThread::terminate() {
if (m_handle) {
-# ifdef G3D_WIN32
+# ifdef G3D_WINDOWS
::TerminateThread(m_handle, 0);
# else
pthread_kill(m_handle, SIGSTOP);
@@ -144,7 +179,7 @@ void GThread::waitForCompletion() {
return;
}
-# ifdef G3D_WIN32
+# ifdef G3D_WINDOWS
debugAssert(m_event);
::WaitForSingleObject(m_event, INFINITE);
# else
@@ -154,7 +189,7 @@ void GThread::waitForCompletion() {
}
-#ifdef G3D_WIN32
+#ifdef G3D_WINDOWS
DWORD WINAPI GThread::internalThreadProc(LPVOID param) {
GThread* current = reinterpret_cast<GThread*>(param);
debugAssert(current->m_event);
@@ -178,7 +213,7 @@ void* GThread::internalThreadProc(void* param) {
//GMutex implementation
GMutex::GMutex() {
-#ifdef G3D_WIN32
+#ifdef G3D_WINDOWS
::InitializeCriticalSection(&m_handle);
#else
int ret = pthread_mutexattr_init(&m_attr);
@@ -192,7 +227,7 @@ GMutex::GMutex() {
GMutex::~GMutex() {
//TODO: Debug check for locked
-#ifdef G3D_WIN32
+#ifdef G3D_WINDOWS
::DeleteCriticalSection(&m_handle);
#else
int ret = pthread_mutex_destroy(&m_handle);
@@ -203,7 +238,7 @@ GMutex::~GMutex() {
}
bool GMutex::tryLock() {
-#ifdef G3D_WIN32
+#ifdef G3D_WINDOWS
return (::TryEnterCriticalSection(&m_handle) != 0);
#else
return (pthread_mutex_trylock(&m_handle) == 0);
@@ -211,7 +246,7 @@ bool GMutex::tryLock() {
}
void GMutex::lock() {
-#ifdef G3D_WIN32
+#ifdef G3D_WINDOWS
::EnterCriticalSection(&m_handle);
#else
pthread_mutex_lock(&m_handle);
@@ -219,7 +254,7 @@ void GMutex::lock() {
}
void GMutex::unlock() {
-#ifdef G3D_WIN32
+#ifdef G3D_WINDOWS
::LeaveCriticalSection(&m_handle);
#else
pthread_mutex_unlock(&m_handle);
diff --git a/dep/g3dlite/source/GUniqueID.cpp b/dep/g3dlite/source/GUniqueID.cpp
index 84c853e0e31..7dcc3ccd254 100644
--- a/dep/g3dlite/source/GUniqueID.cpp
+++ b/dep/g3dlite/source/GUniqueID.cpp
@@ -8,8 +8,27 @@
#include "G3D/BinaryOutput.h"
#include "G3D/TextOutput.h"
#include "G3D/NetworkDevice.h"
+#include "G3D/Any.h"
namespace G3D {
+
+GUniqueID& GUniqueID::operator=(const Any& a) {
+ a.verifyName("GUniqueID");
+ a.verifyType(Any::ARRAY);
+ a.verifySize(1);
+ std::string s = a[0];
+ a.verify(s.length() == 16);
+ id = GUniqueID::fromString16(s);
+ return *this;
+}
+
+
+Any GUniqueID::toAny() const {
+ Any a(Any::ARRAY, "GUniqueID");
+ a.append(toString16());
+ return a;
+}
+
void GUniqueID::serialize(BinaryOutput& b) const {
b.writeUInt64(id);
@@ -34,6 +53,33 @@ void GUniqueID::deserialize(TextInput& t) {
}
+GUniqueID GUniqueID::NONE(uint16 tag) {
+ GUniqueID i;
+ uint64 t = tag;
+ i.id = (t << 54);
+ return i;
+}
+
+
+std::string GUniqueID::toString16() const {
+ return format("%08x%08x", uint32(id >> 32), uint32(id & 0xFFFFFFFF));
+}
+
+
+GUniqueID GUniqueID::fromString16(const std::string& s) {
+ if (s.length() != 16) {
+ debugAssertM(false, "Corrupt 16-character string");
+ return GUniqueID();
+ }
+
+ uint32 high = 0, low = 0;
+ sscanf(s.c_str(), "%08x%08x", &high, &low);
+ GUniqueID i;
+ i.id = (uint64(high) << 32) | low;
+ return i;
+}
+
+
GUniqueID GUniqueID::create(uint16 tag) {
static uint64 counter = 0;
static uint64 systemID = 0;
diff --git a/dep/g3dlite/source/Image1.cpp b/dep/g3dlite/source/Image1.cpp
index a61f7faa633..ed125adad18 100644
--- a/dep/g3dlite/source/Image1.cpp
+++ b/dep/g3dlite/source/Image1.cpp
@@ -1,21 +1,23 @@
/**
- @file Image1.cpp
+ \file G3D/Image1.cpp
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
+ \maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @created 2007-01-31
- @edited 2007-01-31
+ \created 2007-01-31
+ \edited 2012-12-25
*/
#include "G3D/Image1.h"
-#include "G3D/Image1uint8.h"
-#include "G3D/GImage.h"
+#include "G3D/Image1unorm8.h"
+#include "G3D/Image.h"
#include "G3D/Color4.h"
-#include "G3D/Color4uint8.h"
+#include "G3D/Color4unorm8.h"
#include "G3D/Color1.h"
-#include "G3D/Color1uint8.h"
+#include "G3D/Color1unorm8.h"
#include "G3D/ImageFormat.h"
+#include "G3D/PixelTransferBuffer.h"
+#include "G3D/CPUPixelTransferBuffer.h"
namespace G3D {
@@ -24,30 +26,12 @@ Image1::Image1(int w, int h, WrapMode wrap) : Map2D<Color1, Color1>(w, h, wrap)
}
-Image1::Ref Image1::fromGImage(const GImage& im, WrapMode wrap) {
- switch (im.channels()) {
- case 1:
- return fromArray(im.pixel1(), im.width(), im.height(), wrap);
-
- case 3:
- return fromArray(im.pixel3(), im.width(), im.height(), wrap);
-
- case 4:
- return fromArray(im.pixel4(), im.width(), im.height(), wrap);
-
- default:
- debugAssertM(false, "Input GImage must have 1, 3, or 4 channels.");
- return NULL;
- }
-}
-
-
-Image1::Ref Image1::fromImage1uint8(const ReferenceCountedPointer<Image1uint8>& im) {
+Image1::Ref Image1::fromImage1unorm8(const shared_ptr<Image1unorm8>& im) {
Ref out = createEmpty(static_cast<WrapMode>(im->wrapMode()));
out->resize(im->width(), im->height());
int N = im->width() * im->height();
- const Color1uint8* src = reinterpret_cast<Color1uint8*>(im->getCArray());
+ const Color1unorm8* src = reinterpret_cast<Color1unorm8*>(im->getCArray());
for (int i = 0; i < N; ++i) {
out->data[i] = Color1(src[i]);
}
@@ -57,7 +41,7 @@ Image1::Ref Image1::fromImage1uint8(const ReferenceCountedPointer<Image1uint8>&
Image1::Ref Image1::createEmpty(int width, int height, WrapMode wrap) {
- return new Type(width, height, wrap);
+ return Image1::Ref(new Type(width, height, wrap));
}
@@ -66,20 +50,49 @@ Image1::Ref Image1::createEmpty(WrapMode wrap) {
}
-Image1::Ref Image1::fromFile(const std::string& filename, WrapMode wrap, GImage::Format fmt) {
+Image1::Ref Image1::fromFile(const std::string& filename, WrapMode wrap) {
Ref out = createEmpty(wrap);
- out->load(filename, fmt);
+ out->load(filename);
return out;
}
-void Image1::load(const std::string& filename, GImage::Format fmt) {
- copyGImage(GImage(filename, fmt));
+void Image1::load(const std::string& filename) {
+ shared_ptr<Image> image = Image::fromFile(filename);
+ if (image->format() != ImageFormat::L32F()) {
+ image->convertToL8();
+ }
+
+ switch (image->format()->code)
+ {
+ case ImageFormat::CODE_L8:
+ copyArray(static_cast<const Color1unorm8*>(image->toPixelTransferBuffer()->buffer()), image->width(), image->height());
+ break;
+ case ImageFormat::CODE_L32F:
+ copyArray(static_cast<const Color1*>(image->toPixelTransferBuffer()->buffer()), image->width(), image->height());
+ break;
+ case ImageFormat::CODE_RGB8:
+ copyArray(static_cast<const Color3unorm8*>(image->toPixelTransferBuffer()->buffer()), image->width(), image->height());
+ break;
+ case ImageFormat::CODE_RGB32F:
+ copyArray(static_cast<const Color3*>(image->toPixelTransferBuffer()->buffer()), image->width(), image->height());
+ break;
+ case ImageFormat::CODE_RGBA8:
+ copyArray(static_cast<const Color4unorm8*>(image->toPixelTransferBuffer()->buffer()), image->width(), image->height());
+ break;
+ case ImageFormat::CODE_RGBA32F:
+ copyArray(static_cast<const Color4*>(image->toPixelTransferBuffer()->buffer()), image->width(), image->height());
+ break;
+ default:
+ debugAssertM(false, "Trying to load unsupported image format");
+ break;
+ }
+
setChanged(true);
}
-Image1::Ref Image1::fromArray(const class Color3uint8* ptr, int w, int h, WrapMode wrap) {
+Image1::Ref Image1::fromArray(const class Color3unorm8* ptr, int w, int h, WrapMode wrap) {
Ref out = createEmpty(wrap);
out->copyArray(ptr, w, h);
return out;
@@ -93,7 +106,7 @@ Image1::Ref Image1::fromArray(const class Color1* ptr, int w, int h, WrapMode wr
}
-Image1::Ref Image1::fromArray(const class Color1uint8* ptr, int w, int h, WrapMode wrap) {
+Image1::Ref Image1::fromArray(const class Color1unorm8* ptr, int w, int h, WrapMode wrap) {
Ref out = createEmpty(wrap);
out->copyArray(ptr, w, h);
return out;
@@ -107,7 +120,7 @@ Image1::Ref Image1::fromArray(const class Color3* ptr, int w, int h, WrapMode wr
}
-Image1::Ref Image1::fromArray(const class Color4uint8* ptr, int w, int h, WrapMode wrap) {
+Image1::Ref Image1::fromArray(const class Color4unorm8* ptr, int w, int h, WrapMode wrap) {
Ref out = createEmpty(wrap);
out->copyArray(ptr, w, h);
return out;
@@ -120,24 +133,7 @@ Image1::Ref Image1::fromArray(const class Color4* ptr, int w, int h, WrapMode wr
return out;
}
-void Image1::copyGImage(const GImage& im) {
- switch (im.channels()) {
- case 1:
- copyArray(im.pixel1(), im.width(), im.height());
- break;
-
- case 3:
- copyArray(im.pixel3(), im.width(), im.height());
- break;
-
- case 4:
- copyArray(im.pixel4(), im.width(), im.height());
- break;
- }
-}
-
-
-void Image1::copyArray(const Color3uint8* src, int w, int h) {
+void Image1::copyArray(const Color3unorm8* src, int w, int h) {
resize(w, h);
int N = w * h;
@@ -149,7 +145,7 @@ void Image1::copyArray(const Color3uint8* src, int w, int h) {
}
-void Image1::copyArray(const Color4uint8* src, int w, int h) {
+void Image1::copyArray(const Color4unorm8* src, int w, int h) {
resize(w, h);
int N = w * h;
@@ -181,7 +177,7 @@ void Image1::copyArray(const Color4* src, int w, int h) {
}
-void Image1::copyArray(const Color1uint8* src, int w, int h) {
+void Image1::copyArray(const Color1unorm8* src, int w, int h) {
resize(w, h);
int N = w * h;
@@ -203,17 +199,10 @@ void Image1::copyArray(const Color3* src, int w, int h) {
}
-/** Saves in any of the formats supported by G3D::GImage. */
-void Image1::save(const std::string& filename, GImage::Format fmt) {
- GImage im(width(), height(), 1);
-
- int N = im.width() * im.height();
- Color1uint8* dst = im.pixel1();
- for (int i = 0; i < N; ++i) {
- dst[i] = Color1uint8(data[i]);
- }
-
- im.save(filename, fmt);
+void Image1::save(const std::string& filename) {
+ // To avoid saving as floating point image. FreeImage cannot convert floating point to L8.
+ Image1unorm8::Ref unorm8 = Image1unorm8::fromImage1(dynamic_pointer_cast<Image1>(shared_from_this()));
+ unorm8->save(filename);
}
diff --git a/dep/g3dlite/source/Image1uint8.cpp b/dep/g3dlite/source/Image1uint8.cpp
deleted file mode 100644
index de2cbbc130b..00000000000
--- a/dep/g3dlite/source/Image1uint8.cpp
+++ /dev/null
@@ -1,212 +0,0 @@
-/**
- @file Image1uint8.cpp
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2007-01-31
- @edited 2008-01-13
-*/
-
-#include "G3D/Image1uint8.h"
-#include "G3D/Image3uint8.h"
-#include "G3D/Image1.h"
-#include "G3D/GImage.h"
-#include "G3D/Color1.h"
-#include "G3D/Color1uint8.h"
-#include "G3D/Color4.h"
-#include "G3D/Color4uint8.h"
-#include "G3D/ImageFormat.h"
-
-namespace G3D {
-
-Image1uint8::Image1uint8(int w, int h, WrapMode wrap) : Map2D<Color1uint8, Color1>(w, h, wrap) {
- setAll(Color1uint8(0));
-}
-
-
-Image1uint8::Ref Image1uint8::fromImage3uint8(const ReferenceCountedPointer<class Image3uint8>& im) {
- return fromArray(im->getCArray(), im->width(), im->height(), im->wrapMode());
-}
-
-
-Image1uint8::Ref Image1uint8::fromGImage(const GImage& im, WrapMode wrap) {
- switch (im.channels()) {
- case 1:
- return fromArray(im.pixel1(), im.width(), im.height(), wrap);
-
- case 3:
- return fromArray(im.pixel3(), im.width(), im.height(), wrap);
-
- case 4:
- return fromArray(im.pixel4(), im.width(), im.height(), wrap);
-
- default:
- debugAssertM(false, "Input GImage must have 1, 3, or 4 channels.");
- return NULL;
- }
-}
-
-
-Image1uint8::Ref Image1uint8::fromImage1(const ReferenceCountedPointer<Image1>& im) {
- Ref out = createEmpty(static_cast<WrapMode>(im->wrapMode()));
- out->copyArray(im->getCArray(), im->width(), im->height());
-
- return out;
-}
-
-
-Image1uint8::Ref Image1uint8::createEmpty(int width, int height, WrapMode wrap) {
- return new Type(width, height, wrap);
-}
-
-
-Image1uint8::Ref Image1uint8::createEmpty(WrapMode wrap) {
- return createEmpty(0, 0, wrap);
-}
-
-
-Image1uint8::Ref Image1uint8::fromFile(const std::string& filename, WrapMode wrap, GImage::Format fmt) {
- Ref out = createEmpty(wrap);
- out->load(filename, fmt);
- return out;
-}
-
-
-Image1uint8::Ref Image1uint8::fromArray(const class Color3uint8* ptr, int w, int h, WrapMode wrap) {
- Ref out = createEmpty(wrap);
- out->copyArray(ptr, w, h);
- return out;
-}
-
-
-Image1uint8::Ref Image1uint8::fromArray(const class Color1* ptr, int w, int h, WrapMode wrap) {
- Ref out = createEmpty(wrap);
- out->copyArray(ptr, w, h);
- return out;
-}
-
-
-Image1uint8::Ref Image1uint8::fromArray(const class Color1uint8* ptr, int w, int h, WrapMode wrap) {
- Ref out = createEmpty(wrap);
- out->copyArray(ptr, w, h);
- return out;
-}
-
-
-Image1uint8::Ref Image1uint8::fromArray(const class Color3* ptr, int w, int h, WrapMode wrap) {
- Ref out = createEmpty(wrap);
- out->copyArray(ptr, w, h);
- return out;
-}
-
-
-Image1uint8::Ref Image1uint8::fromArray(const class Color4uint8* ptr, int w, int h, WrapMode wrap) {
- Ref out = createEmpty(wrap);
- out->copyArray(ptr, w, h);
- return out;
-}
-
-
-Image1uint8::Ref Image1uint8::fromArray(const class Color4* ptr, int w, int h, WrapMode wrap) {
- Ref out = createEmpty(wrap);
- out->copyArray(ptr, w, h);
- return out;
-}
-
-
-void Image1uint8::load(const std::string& filename, GImage::Format fmt) {
- copyGImage(GImage(filename, fmt));
- setChanged(true);
-}
-
-
-void Image1uint8::copyGImage(const GImage& im) {
- switch (im.channels()) {
- case 1:
- copyArray(im.pixel1(), im.width(), im.height());
- break;
-
- case 3:
- copyArray(im.pixel3(), im.width(), im.height());
- break;
-
- case 4:
- copyArray(im.pixel4(), im.width(), im.height());
- break;
- }
-}
-
-
-void Image1uint8::copyArray(const Color3uint8* src, int w, int h) {
- resize(w, h);
- int N = w * h;
-
- Color1uint8* dst = getCArray();
- for (int i = 0; i < N; ++i) {
- dst[i].value = (src[i].r + src[i].g + src[i].b) / 3;
- }
-}
-
-void Image1uint8::copyArray(const Color3* src, int w, int h) {
- resize(w, h);
- int N = w * h;
-
- Color1uint8* dst = getCArray();
- for (int i = 0; i < N; ++i) {
- dst[i] = Color1uint8(Color1(src[i].average()));
- }
-}
-
-
-void Image1uint8::copyArray(const Color1uint8* ptr, int w, int h) {
- resize(w, h);
- System::memcpy(getCArray(), ptr, w * h);
-}
-
-
-void Image1uint8::copyArray(const Color1* src, int w, int h) {
- resize(w, h);
- int N = w * h;
-
- Color1uint8* dst = getCArray();
- for (int i = 0; i < N; ++i) {
- dst[i] = Color1uint8(src[i]);
- }
-}
-
-
-void Image1uint8::copyArray(const Color4uint8* ptr, int w, int h) {
- resize(w, h);
- int N = w * h;
-
- Color1uint8* dst = getCArray();
- for (int i = 0; i < N; ++i) {
- dst[i].value = (ptr[i].r + ptr[i].g + ptr[i].b) / 3;
- }
-}
-
-
-void Image1uint8::copyArray(const Color4* src, int w, int h) {
- resize(w, h);
- int N = w * h;
-
- Color1uint8* dst = getCArray();
- for (int i = 0; i < N; ++i) {
- dst[i] = Color1uint8(Color1(src[i].rgb().average()));
- }
-}
-
-
-/** Saves in any of the formats supported by G3D::GImage. */
-void Image1uint8::save(const std::string& filename, GImage::Format fmt) {
- GImage im(width(), height(), 1);
- System::memcpy(im.byte(), getCArray(), width() * height());
- im.save(filename, fmt);
-}
-
-
-const ImageFormat* Image1uint8::format() const {
- return ImageFormat::L8();
-}
-
-} // G3D
diff --git a/dep/g3dlite/source/Image3.cpp b/dep/g3dlite/source/Image3.cpp
index 0d85bdf45da..671ad4b84c7 100644
--- a/dep/g3dlite/source/Image3.cpp
+++ b/dep/g3dlite/source/Image3.cpp
@@ -4,18 +4,20 @@
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
@created 2007-01-31
- @edited 2007-01-31
+ @edited 2012-12-25
*/
#include "G3D/Image3.h"
-#include "G3D/Image3uint8.h"
-#include "G3D/GImage.h"
+#include "G3D/Image3unorm8.h"
+#include "G3D/Image.h"
#include "G3D/Color4.h"
-#include "G3D/Color4uint8.h"
+#include "G3D/Color4unorm8.h"
#include "G3D/Color1.h"
-#include "G3D/Color1uint8.h"
+#include "G3D/Color1unorm8.h"
#include "G3D/ImageFormat.h"
+#include "G3D/PixelTransferBuffer.h"
+#include "G3D/CPUPixelTransferBuffer.h"
namespace G3D {
@@ -24,30 +26,12 @@ Image3::Image3(int w, int h, WrapMode wrap) : Map2D<Color3, Color3>(w, h, wrap)
}
-Image3::Ref Image3::fromGImage(const GImage& im, WrapMode wrap) {
- switch (im.channels()) {
- case 1:
- return fromArray(im.pixel1(), im.width(), im.height(), wrap);
-
- case 3:
- return fromArray(im.pixel3(), im.width(), im.height(), wrap);
-
- case 4:
- return fromArray(im.pixel4(), im.width(), im.height(), wrap);
-
- default:
- debugAssertM(false, "Input GImage must have 1, 3, or 4 channels.");
- return NULL;
- }
-}
-
-
-Image3::Ref Image3::fromImage3uint8(const ReferenceCountedPointer<Image3uint8>& im) {
+Image3::Ref Image3::fromImage3unorm8(const shared_ptr<Image3unorm8>& im) {
Ref out = createEmpty(im->wrapMode());
out->resize(im->width(), im->height());
int N = im->width() * im->height();
- const Color3uint8* src = reinterpret_cast<Color3uint8*>(im->getCArray());
+ const Color3unorm8* src = reinterpret_cast<Color3unorm8*>(im->getCArray());
for (int i = 0; i < N; ++i) {
out->data[i] = Color3(src[i]);
}
@@ -57,7 +41,7 @@ Image3::Ref Image3::fromImage3uint8(const ReferenceCountedPointer<Image3uint8>&
Image3::Ref Image3::createEmpty(int width, int height, WrapMode wrap) {
- return new Image3(width, height, wrap);
+ return shared_ptr<Image3>(new Image3(width, height, wrap));
}
@@ -66,20 +50,49 @@ Image3::Ref Image3::createEmpty(WrapMode wrap) {
}
-Image3::Ref Image3::fromFile(const std::string& filename, WrapMode wrap, GImage::Format fmt) {
+Image3::Ref Image3::fromFile(const std::string& filename, WrapMode wrap) {
Ref out = createEmpty(wrap);
- out->load(filename, fmt);
+ out->load(filename);
return out;
}
-void Image3::load(const std::string& filename, GImage::Format fmt) {
- copyGImage(GImage(filename, fmt));
+void Image3::load(const std::string& filename) {
+ shared_ptr<Image> image = Image::fromFile(filename);
+ if (image->format() != ImageFormat::RGB32F()) {
+ image->convertToRGB8();
+ }
+
+ switch (image->format()->code)
+ {
+ case ImageFormat::CODE_L8:
+ copyArray(static_cast<const Color1unorm8*>(image->toPixelTransferBuffer()->buffer()), image->width(), image->height());
+ break;
+ case ImageFormat::CODE_L32F:
+ copyArray(static_cast<const Color1*>(image->toPixelTransferBuffer()->buffer()), image->width(), image->height());
+ break;
+ case ImageFormat::CODE_RGB8:
+ copyArray(static_cast<const Color3unorm8*>(image->toPixelTransferBuffer()->buffer()), image->width(), image->height());
+ break;
+ case ImageFormat::CODE_RGB32F:
+ copyArray(static_cast<const Color3*>(image->toPixelTransferBuffer()->buffer()), image->width(), image->height());
+ break;
+ case ImageFormat::CODE_RGBA8:
+ copyArray(static_cast<const Color4unorm8*>(image->toPixelTransferBuffer()->buffer()), image->width(), image->height());
+ break;
+ case ImageFormat::CODE_RGBA32F:
+ copyArray(static_cast<const Color4*>(image->toPixelTransferBuffer()->buffer()), image->width(), image->height());
+ break;
+ default:
+ debugAssertM(false, "Trying to load unsupported image format");
+ break;
+ }
+
setChanged(true);
}
-Image3::Ref Image3::fromArray(const class Color3uint8* ptr, int w, int h, WrapMode wrap) {
+Image3::Ref Image3::fromArray(const class Color3unorm8* ptr, int w, int h, WrapMode wrap) {
Ref out = createEmpty(wrap);
out->copyArray(ptr, w, h);
return out;
@@ -93,7 +106,7 @@ Image3::Ref Image3::fromArray(const class Color1* ptr, int w, int h, WrapMode wr
}
-Image3::Ref Image3::fromArray(const class Color1uint8* ptr, int w, int h, WrapMode wrap) {
+Image3::Ref Image3::fromArray(const class Color1unorm8* ptr, int w, int h, WrapMode wrap) {
Ref out = createEmpty(wrap);
out->copyArray(ptr, w, h);
return out;
@@ -107,7 +120,7 @@ Image3::Ref Image3::fromArray(const class Color3* ptr, int w, int h, WrapMode wr
}
-Image3::Ref Image3::fromArray(const class Color4uint8* ptr, int w, int h, WrapMode wrap) {
+Image3::Ref Image3::fromArray(const class Color4unorm8* ptr, int w, int h, WrapMode wrap) {
Ref out = createEmpty(wrap);
out->copyArray(ptr, w, h);
return out;
@@ -121,24 +134,7 @@ Image3::Ref Image3::fromArray(const class Color4* ptr, int w, int h, WrapMode wr
}
-void Image3::copyGImage(const GImage& im) {
- switch (im.channels()) {
- case 1:
- copyArray(im.pixel1(), im.width(), im.height());
- break;
-
- case 3:
- copyArray(im.pixel3(), im.width(), im.height());
- break;
-
- case 4:
- copyArray(im.pixel4(), im.width(), im.height());
- break;
- }
-}
-
-
-void Image3::copyArray(const Color3uint8* src, int w, int h) {
+void Image3::copyArray(const Color3unorm8* src, int w, int h) {
resize(w, h);
int N = w * h;
@@ -150,7 +146,7 @@ void Image3::copyArray(const Color3uint8* src, int w, int h) {
}
-void Image3::copyArray(const Color4uint8* src, int w, int h) {
+void Image3::copyArray(const Color4unorm8* src, int w, int h) {
resize(w, h);
int N = w * h;
@@ -182,7 +178,7 @@ void Image3::copyArray(const Color4* src, int w, int h) {
}
-void Image3::copyArray(const Color1uint8* src, int w, int h) {
+void Image3::copyArray(const Color1unorm8* src, int w, int h) {
resize(w, h);
int N = w * h;
@@ -205,16 +201,10 @@ void Image3::copyArray(const Color1* src, int w, int h) {
/** Saves in any of the formats supported by G3D::GImage. */
-void Image3::save(const std::string& filename, GImage::Format fmt) {
- GImage im(width(), height(), 3);
-
- int N = im.width() * im.height();
- Color3uint8* dst = im.pixel3();
- for (int i = 0; i < N; ++i) {
- dst[i] = Color3uint8(data[i]);
- }
-
- im.save(filename, fmt);
+void Image3::save(const std::string& filename) {
+ // To avoid saving as floating point image. FreeImage cannot convert floating point to RGB8.
+ Image3unorm8::Ref unorm8 = Image3unorm8::fromImage3(dynamic_pointer_cast<Image3>(shared_from_this()));
+ unorm8->save(filename);
}
diff --git a/dep/g3dlite/source/Image3uint8.cpp b/dep/g3dlite/source/Image3uint8.cpp
deleted file mode 100644
index 86595bbd1f6..00000000000
--- a/dep/g3dlite/source/Image3uint8.cpp
+++ /dev/null
@@ -1,225 +0,0 @@
-/**
- @file Image3uint8.cpp
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2007-01-31
- @edited 2008-01-08
-*/
-
-#include "G3D/Image1uint8.h"
-#include "G3D/Image3uint8.h"
-#include "G3D/Image3.h"
-#include "G3D/GImage.h"
-#include "G3D/Color1.h"
-#include "G3D/Color1uint8.h"
-#include "G3D/Color4.h"
-#include "G3D/Color4uint8.h"
-#include "G3D/ImageFormat.h"
-
-namespace G3D {
-
-Image3uint8::Ref Image3uint8::fromImage1uint8(const ReferenceCountedPointer<class Image1uint8>& im) {
- return fromArray(im->getCArray(), im->width(), im->height(), im->wrapMode());
-}
-
-
-Image3uint8::Image3uint8(int w, int h, WrapMode wrap) : Map2D<Color3uint8>(w, h, wrap) {
- setAll(Color3::black());
-}
-
-
-Image3uint8::Ref Image3uint8::fromGImage(const GImage& im, WrapMode wrap) {
- switch (im.channels()) {
- case 1:
- return fromArray(im.pixel1(), im.width(), im.height(), wrap);
-
- case 3:
- return fromArray(im.pixel3(), im.width(), im.height(), wrap);
-
- case 4:
- return fromArray(im.pixel4(), im.width(), im.height(), wrap);
-
- default:
- debugAssertM(false, "Input GImage must have 1, 3, or 4 channels.");
- return NULL;
- }
-}
-
-
-Image3uint8::Ref Image3uint8::fromImage3(const ReferenceCountedPointer<Image3>& im) {
- Ref out = createEmpty(static_cast<WrapMode>(im->wrapMode()));
- out->copyArray(im->getCArray(), im->width(), im->height());
-
- return out;
-}
-
-
-Image3uint8::Ref Image3uint8::createEmpty(int width, int height, WrapMode wrap) {
- return new Type(width, height, wrap);
-}
-
-
-Image3uint8::Ref Image3uint8::createEmpty(WrapMode wrap) {
- return createEmpty(0, 0, wrap);
-}
-
-
-Image3uint8::Ref Image3uint8::fromFile(const std::string& filename, WrapMode wrap, GImage::Format fmt) {
- Ref out = createEmpty(wrap);
- out->load(filename, fmt);
- return out;
-}
-
-
-Image3uint8::Ref Image3uint8::fromArray(const class Color3uint8* ptr, int w, int h, WrapMode wrap) {
- Ref out = createEmpty(wrap);
- out->copyArray(ptr, w, h);
- return out;
-}
-
-
-Image3uint8::Ref Image3uint8::fromArray(const class Color1* ptr, int w, int h, WrapMode wrap) {
- Ref out = createEmpty(wrap);
- out->copyArray(ptr, w, h);
- return out;
-}
-
-
-Image3uint8::Ref Image3uint8::fromArray(const class Color1uint8* ptr, int w, int h, WrapMode wrap) {
- Ref out = createEmpty(wrap);
- out->copyArray(ptr, w, h);
- return out;
-}
-
-
-Image3uint8::Ref Image3uint8::fromArray(const class Color3* ptr, int w, int h, WrapMode wrap) {
- Ref out = createEmpty(wrap);
- out->copyArray(ptr, w, h);
- return out;
-}
-
-
-Image3uint8::Ref Image3uint8::fromArray(const class Color4uint8* ptr, int w, int h, WrapMode wrap) {
- Ref out = createEmpty(wrap);
- out->copyArray(ptr, w, h);
- return out;
-}
-
-
-Image3uint8::Ref Image3uint8::fromArray(const class Color4* ptr, int w, int h, WrapMode wrap) {
- Ref out = createEmpty(wrap);
- out->copyArray(ptr, w, h);
- return out;
-}
-
-
-void Image3uint8::load(const std::string& filename, GImage::Format fmt) {
- copyGImage(GImage(filename, fmt));
- setChanged(true);
-}
-
-
-void Image3uint8::copyGImage(const GImage& im) {
- switch (im.channels()) {
- case 1:
- copyArray(im.pixel1(), im.width(), im.height());
- break;
-
- case 3:
- copyArray(im.pixel3(), im.width(), im.height());
- break;
-
- case 4:
- copyArray(im.pixel4(), im.width(), im.height());
- break;
- }
-}
-
-
-void Image3uint8::copyArray(const Color1uint8* src, int w, int h) {
- resize(w, h);
- int N = w * h;
-
- Color3uint8* dst = getCArray();
- for (int i = 0; i < N; ++i) {
- dst[i].r = dst[i].g = dst[i].b = src[i].value;
- }
-}
-
-void Image3uint8::copyArray(const Color1* src, int w, int h) {
- resize(w, h);
- int N = w * h;
-
- Color3uint8* dst = getCArray();
- for (int i = 0; i < N; ++i) {
- dst[i].r = dst[i].g = dst[i].b = Color1uint8(src[i]).value;
- }
-}
-
-
-void Image3uint8::copyArray(const Color3uint8* ptr, int w, int h) {
- resize(w, h);
- System::memcpy(getCArray(), ptr, w * h * 3);
-}
-
-
-void Image3uint8::copyArray(const Color3* src, int w, int h) {
- resize(w, h);
- int N = w * h;
-
- Color3uint8* dst = getCArray();
- for (int i = 0; i < N; ++i) {
- dst[i] = Color3uint8(src[i]);
- }
-}
-
-
-void Image3uint8::copyArray(const Color4uint8* ptr, int w, int h) {
- resize(w, h);
-
- // Copy 3/4 bytes
- GImage::RGBAtoRGB((const uint8*)ptr, (uint8*)getCArray(), w * h);
-}
-
-
-void Image3uint8::copyArray(const Color4* src, int w, int h) {
- resize(w, h);
- int N = w * h;
-
- Color3uint8* dst = getCArray();
- for (int i = 0; i < N; ++i) {
- dst[i] = Color3uint8(src[i].rgb());
- }
-}
-
-
-/** Saves in any of the formats supported by G3D::GImage. */
-void Image3uint8::save(const std::string& filename, GImage::Format fmt) {
- GImage im(width(), height(), 3);
- System::memcpy(im.byte(), getCArray(), width() * height() * 3);
- im.save(filename, fmt);
-}
-
-
-ReferenceCountedPointer<class Image1uint8> Image3uint8::getChannel(int c) const {
- debugAssert(c >= 0 && c <= 2);
-
- Image1uint8Ref dst = Image1uint8::createEmpty(width(), height(), wrapMode());
- const Color3uint8* srcArray = getCArray();
- Color1uint8* dstArray = dst->getCArray();
-
- const int N = width() * height();
- for (int i = 0; i < N; ++i) {
- dstArray[i] = Color1uint8(srcArray[i][c]);
- }
-
- return dst;
-}
-
-
-const ImageFormat* Image3uint8::format() const {
- return ImageFormat::RGB8();
-}
-
-} // G3D
diff --git a/dep/g3dlite/source/Image4.cpp b/dep/g3dlite/source/Image4.cpp
index c6f2b10640d..fa36050d370 100644
--- a/dep/g3dlite/source/Image4.cpp
+++ b/dep/g3dlite/source/Image4.cpp
@@ -4,18 +4,20 @@
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
@created 2007-01-31
- @edited 2008-07-27
+ @edited 2011-08-27
*/
#include "G3D/Image4.h"
-#include "G3D/Image4uint8.h"
-#include "G3D/GImage.h"
+#include "G3D/Image4unorm8.h"
+#include "G3D/Image.h"
#include "G3D/Color3.h"
-#include "G3D/Color3uint8.h"
+#include "G3D/Color3unorm8.h"
#include "G3D/Color1.h"
-#include "G3D/Color1uint8.h"
+#include "G3D/Color1unorm8.h"
#include "G3D/ImageFormat.h"
+#include "G3D/PixelTransferBuffer.h"
+#include "G3D/CPUPixelTransferBuffer.h"
namespace G3D {
@@ -24,30 +26,12 @@ Image4::Image4(int w, int h, WrapMode wrap) : Map2D<Color4, Color4>(w, h, wrap)
}
-Image4::Ref Image4::fromGImage(const GImage& im, WrapMode wrap) {
- switch (im.channels()) {
- case 1:
- return fromArray(im.pixel1(), im.width(), im.height(), wrap);
-
- case 3:
- return fromArray(im.pixel3(), im.width(), im.height(), wrap);
-
- case 4:
- return fromArray(im.pixel4(), im.width(), im.height(), wrap);
-
- default:
- debugAssertM(false, "Input GImage must have 1, 3, or 4 channels.");
- return NULL;
- }
-}
-
-
-Image4::Ref Image4::fromImage4uint8(const ReferenceCountedPointer<Image4uint8>& im) {
+Image4::Ref Image4::fromImage4unorm8(const shared_ptr<Image4unorm8>& im) {
Ref out = createEmpty(static_cast<WrapMode>(im->wrapMode()));
out->resize(im->width(), im->height());
int N = im->width() * im->height();
- const Color4uint8* src = reinterpret_cast<Color4uint8*>(im->getCArray());
+ const Color4unorm8* src = reinterpret_cast<Color4unorm8*>(im->getCArray());
for (int i = 0; i < N; ++i) {
out->data[i] = Color4(src[i]);
}
@@ -57,7 +41,7 @@ Image4::Ref Image4::fromImage4uint8(const ReferenceCountedPointer<Image4uint8>&
Image4::Ref Image4::createEmpty(int width, int height, WrapMode wrap) {
- return new Type(width, height, wrap);
+ return shared_ptr<Image4>(new Type(width, height, wrap));
}
@@ -66,20 +50,49 @@ Image4::Ref Image4::createEmpty(WrapMode wrap) {
}
-Image4::Ref Image4::fromFile(const std::string& filename, WrapMode wrap, GImage::Format fmt) {
+Image4::Ref Image4::fromFile(const std::string& filename, WrapMode wrap) {
Ref out = createEmpty(wrap);
out->load(filename);
return out;
}
-void Image4::load(const std::string& filename, GImage::Format fmt) {
- copyGImage(GImage(filename, fmt));
+void Image4::load(const std::string& filename) {
+ shared_ptr<Image> image = Image::fromFile(filename);
+ if (image->format() != ImageFormat::RGBA32F()) {
+ image->convertToRGBA8();
+ }
+
+ switch (image->format()->code)
+ {
+ case ImageFormat::CODE_L8:
+ copyArray(static_cast<const Color1unorm8*>(image->toPixelTransferBuffer()->buffer()), image->width(), image->height());
+ break;
+ case ImageFormat::CODE_L32F:
+ copyArray(static_cast<const Color1*>(image->toPixelTransferBuffer()->buffer()), image->width(), image->height());
+ break;
+ case ImageFormat::CODE_RGB8:
+ copyArray(static_cast<const Color3unorm8*>(image->toPixelTransferBuffer()->buffer()), image->width(), image->height());
+ break;
+ case ImageFormat::CODE_RGB32F:
+ copyArray(static_cast<const Color3*>(image->toPixelTransferBuffer()->buffer()), image->width(), image->height());
+ break;
+ case ImageFormat::CODE_RGBA8:
+ copyArray(static_cast<const Color4unorm8*>(image->toPixelTransferBuffer()->buffer()), image->width(), image->height());
+ break;
+ case ImageFormat::CODE_RGBA32F:
+ copyArray(static_cast<const Color4*>(image->toPixelTransferBuffer()->buffer()), image->width(), image->height());
+ break;
+ default:
+ debugAssertM(false, "Trying to load unsupported image format");
+ break;
+ }
+
setChanged(true);
}
-Image4::Ref Image4::fromArray(const class Color3uint8* ptr, int w, int h, WrapMode wrap) {
+Image4::Ref Image4::fromArray(const class Color3unorm8* ptr, int w, int h, WrapMode wrap) {
Ref out = createEmpty(wrap);
out->copyArray(ptr, w, h);
return out;
@@ -93,7 +106,7 @@ Image4::Ref Image4::fromArray(const class Color1* ptr, int w, int h, WrapMode wr
}
-Image4::Ref Image4::fromArray(const class Color1uint8* ptr, int w, int h, WrapMode wrap) {
+Image4::Ref Image4::fromArray(const class Color1unorm8* ptr, int w, int h, WrapMode wrap) {
Ref out = createEmpty(wrap);
out->copyArray(ptr, w, h);
return out;
@@ -107,7 +120,7 @@ Image4::Ref Image4::fromArray(const class Color3* ptr, int w, int h, WrapMode wr
}
-Image4::Ref Image4::fromArray(const class Color4uint8* ptr, int w, int h, WrapMode wrap) {
+Image4::Ref Image4::fromArray(const class Color4unorm8* ptr, int w, int h, WrapMode wrap) {
Ref out = createEmpty(wrap);
out->copyArray(ptr, w, h);
return out;
@@ -121,24 +134,7 @@ Image4::Ref Image4::fromArray(const class Color4* ptr, int w, int h, WrapMode wr
}
-void Image4::copyGImage(const GImage& im) {
- switch (im.channels()) {
- case 1:
- copyArray(im.pixel1(), im.width(), im.height());
- break;
-
- case 3:
- copyArray(im.pixel3(), im.width(), im.height());
- break;
-
- case 4:
- copyArray(im.pixel4(), im.width(), im.height());
- break;
- }
-}
-
-
-void Image4::copyArray(const Color4uint8* src, int w, int h) {
+void Image4::copyArray(const Color4unorm8* src, int w, int h) {
resize(w, h);
int N = w * h;
@@ -150,7 +146,7 @@ void Image4::copyArray(const Color4uint8* src, int w, int h) {
}
-void Image4::copyArray(const Color3uint8* src, int w, int h) {
+void Image4::copyArray(const Color3unorm8* src, int w, int h) {
resize(w, h);
int N = w * h;
@@ -182,7 +178,7 @@ void Image4::copyArray(const Color3* src, int w, int h) {
}
-void Image4::copyArray(const Color1uint8* src, int w, int h) {
+void Image4::copyArray(const Color1unorm8* src, int w, int h) {
resize(w, h);
int N = w * h;
@@ -207,16 +203,10 @@ void Image4::copyArray(const Color1* src, int w, int h) {
/** Saves in any of the formats supported by G3D::GImage. */
-void Image4::save(const std::string& filename, GImage::Format fmt) {
- GImage im(width(), height(), 4);
-
- int N = im.width() * im.height();
- Color4uint8* dst = im.pixel4();
- for (int i = 0; i < N; ++i) {
- dst[i] = Color4uint8(data[i]);
- }
-
- im.save(filename, fmt);
+void Image4::save(const std::string& filename) {
+ // To avoid saving as floating point image. FreeImage cannot convert floating point to RGBA8.
+ Image4unorm8::Ref unorm8 = Image4unorm8::fromImage4(dynamic_pointer_cast<Image4>(shared_from_this()));
+ unorm8->save(filename);
}
const ImageFormat* Image4::format() const {
diff --git a/dep/g3dlite/source/Image4uint8.cpp b/dep/g3dlite/source/Image4uint8.cpp
deleted file mode 100644
index a94ddb12d03..00000000000
--- a/dep/g3dlite/source/Image4uint8.cpp
+++ /dev/null
@@ -1,222 +0,0 @@
-/**
- @file Image4uint8.cpp
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2007-01-31
- @edited 2008-07-31
-*/
-
-#include "G3D/Image4uint8.h"
-#include "G3D/Image4.h"
-#include "G3D/Image3uint8.h"
-#include "G3D/Image3.h"
-#include "G3D/GImage.h"
-#include "G3D/Color1.h"
-#include "G3D/Color1uint8.h"
-#include "G3D/Color4.h"
-#include "G3D/Color4uint8.h"
-#include "G3D/ImageFormat.h"
-
-namespace G3D {
-
-Image4uint8::Image4uint8(int w, int h, WrapMode wrap) : Map2D<Color4uint8, Color4>(w, h, wrap) {
- setAll(Color4::zero());
-}
-
-
-Image4uint8::Ref Image4uint8::fromGImage(const GImage& im, WrapMode wrap) {
- switch (im.channels()) {
- case 1:
- return fromArray(im.pixel1(), im.width(), im.height(), wrap);
-
- case 3:
- return fromArray(im.pixel3(), im.width(), im.height(), wrap);
-
- case 4:
- return fromArray(im.pixel4(), im.width(), im.height(), wrap);
-
- default:
- debugAssertM(false, "Input GImage must have 1, 3, or 4 channels.");
- return NULL;
- }
-}
-
-
-Image4uint8::Ref Image4uint8::fromImage4(const ReferenceCountedPointer<Image4>& im) {
- Ref out = createEmpty(static_cast<WrapMode>(im->wrapMode()));
- out->copyArray(im->getCArray(), im->width(), im->height());
-
- return out;
-}
-
-
-Image4uint8::Ref Image4uint8::createEmpty(int width, int height, WrapMode wrap) {
- return new Type(width, height, wrap);
-}
-
-
-Image4uint8::Ref Image4uint8::createEmpty(WrapMode wrap) {
- return createEmpty(0, 0, wrap);
-}
-
-
-Image4uint8::Ref Image4uint8::fromFile(const std::string& filename, WrapMode wrap, GImage::Format fmt) {
- Ref out = createEmpty(wrap);
- out->load(filename, fmt);
- return out;
-}
-
-
-Image4uint8::Ref Image4uint8::fromArray(const class Color3uint8* ptr, int w, int h, WrapMode wrap) {
- Ref out = createEmpty(wrap);
- out->copyArray(ptr, w, h);
- return out;
-}
-
-
-Image4uint8::Ref Image4uint8::fromArray(const class Color1* ptr, int w, int h, WrapMode wrap) {
- Ref out = createEmpty(wrap);
- out->copyArray(ptr, w, h);
- return out;
-}
-
-
-Image4uint8::Ref Image4uint8::fromArray(const class Color1uint8* ptr, int w, int h, WrapMode wrap) {
- Ref out = createEmpty(wrap);
- out->copyArray(ptr, w, h);
- return out;
-}
-
-
-Image4uint8::Ref Image4uint8::fromArray(const class Color3* ptr, int w, int h, WrapMode wrap) {
- Ref out = createEmpty(wrap);
- out->copyArray(ptr, w, h);
- return out;
-}
-
-
-Image4uint8::Ref Image4uint8::fromArray(const class Color4uint8* ptr, int w, int h, WrapMode wrap) {
- Ref out = createEmpty(wrap);
- out->copyArray(ptr, w, h);
- return out;
-}
-
-
-Image4uint8::Ref Image4uint8::fromArray(const class Color4* ptr, int w, int h, WrapMode wrap) {
- Ref out = createEmpty(wrap);
- out->copyArray(ptr, w, h);
- return out;
-}
-
-
-void Image4uint8::load(const std::string& filename, GImage::Format fmt) {
- copyGImage(GImage(filename, fmt));
- setChanged(true);
-}
-
-
-void Image4uint8::copyGImage(const GImage& im) {
- switch (im.channels()) {
- case 1:
- copyArray(im.pixel1(), im.width(), im.height());
- break;
-
- case 3:
- copyArray(im.pixel3(), im.width(), im.height());
- break;
-
- case 4:
- copyArray(im.pixel4(), im.width(), im.height());
- break;
- }
-}
-
-
-void Image4uint8::copyArray(const Color1uint8* src, int w, int h) {
- resize(w, h);
- int N = w * h;
-
- Color4uint8* dst = getCArray();
- for (int i = 0; i < N; ++i) {
- dst[i].r = dst[i].g = dst[i].b = src[i].value;
- dst[i].a = 255;
- }
-}
-
-void Image4uint8::copyArray(const Color1* src, int w, int h) {
- resize(w, h);
- int N = w * h;
-
- Color4uint8* dst = getCArray();
- for (int i = 0; i < N; ++i) {
- dst[i].r = dst[i].g = dst[i].b = Color1uint8(src[i]).value;
- dst[i].a = 255;
- }
-}
-
-
-void Image4uint8::copyArray(const Color4uint8* ptr, int w, int h) {
- resize(w, h);
- System::memcpy(getCArray(), ptr, w * h * 4);
-}
-
-
-void Image4uint8::copyArray(const Color4* src, int w, int h) {
- resize(w, h);
- int N = w * h;
-
- Color4uint8* dst = getCArray();
- for (int i = 0; i < N; ++i) {
- dst[i] = Color4uint8(src[i]);
- }
-}
-
-
-void Image4uint8::copyArray(const Color3uint8* ptr, int w, int h) {
- resize(w, h);
-
- GImage::RGBtoRGBA((const uint8*)ptr, (uint8*)getCArray(), w * h);
-}
-
-
-void Image4uint8::copyArray(const Color3* src, int w, int h) {
- resize(w, h);
- int N = w * h;
-
- Color4uint8* dst = getCArray();
- for (int i = 0; i < N; ++i) {
- dst[i] = Color4uint8(Color4(src[i], 1.0f));
- }
-}
-
-
-/** Saves in any of the formats supported by G3D::GImage. */
-void Image4uint8::save(const std::string& filename, GImage::Format fmt) {
- GImage im(width(), height(), 4);
- System::memcpy(im.byte(), getCArray(), width() * height() * 4);
- im.save(filename, fmt);
-}
-
-
-ReferenceCountedPointer<class Image1uint8> Image4uint8::getChannel(int c) const {
- debugAssert(c >= 0 && c <= 3);
-
- Image1uint8Ref dst = Image1uint8::createEmpty(width(), height(), wrapMode());
- const Color4uint8* srcArray = getCArray();
- Color1uint8* dstArray = dst->getCArray();
-
- const int N = width() * height();
- for (int i = 0; i < N; ++i) {
- dstArray[i] = Color1uint8(srcArray[i][c]);
- }
-
- return dst;
-}
-
-
-const ImageFormat* Image4uint8::format() const {
- return ImageFormat::RGBA8();
-}
-
-} // G3D
diff --git a/dep/g3dlite/source/ImageFormat.cpp b/dep/g3dlite/source/ImageFormat.cpp
index 46618c64480..0ffc27b661b 100644
--- a/dep/g3dlite/source/ImageFormat.cpp
+++ b/dep/g3dlite/source/ImageFormat.cpp
@@ -1,14 +1,15 @@
/**
- @file ImageFormat.cpp
+ \file ImageFormat.cpp
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
+ \maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @created 2003-05-23
- @edited 2010-03-30
+ \created 2003-05-23
+ \edited 2013-01-12
*/
#include "GLG3D/glheaders.h"
#include "G3D/ImageFormat.h"
+#include "G3D/stringutils.h"
namespace G3D {
@@ -24,11 +25,11 @@ ImageFormat::ImageFormat(
int _blueBits,
int _depthBits,
int _stencilBits,
- int _hardwareBitsPerTexel,
- int _packedBitsPerTexel,
+ int _openGLBitsPerPixel,
+ int _cpuBitsPerPixel,
int glDataFormat,
bool _opaque,
- bool _floatingPoint,
+ NumberFormat _numberFormat,
Code _code,
ColorSpace _colorSpace,
BayerPattern _bayerPattern) :
@@ -47,17 +48,30 @@ ImageFormat::ImageFormat(
blueBits(_blueBits),
stencilBits(_stencilBits),
depthBits(_depthBits),
- cpuBitsPerPixel(_packedBitsPerTexel),
- packedBitsPerTexel(_packedBitsPerTexel),
- openGLBitsPerPixel(_hardwareBitsPerTexel),
- hardwareBitsPerTexel(_hardwareBitsPerTexel),
+ cpuBitsPerPixel(_cpuBitsPerPixel),
+ openGLBitsPerPixel(_openGLBitsPerPixel),
openGLDataFormat(glDataFormat),
opaque(_opaque),
- floatingPoint(_floatingPoint) {
+ numberFormat(_numberFormat){
- debugAssert(_packedBitsPerTexel <= _hardwareBitsPerTexel);
+ floatingPoint = (numberFormat == FLOATING_POINT_FORMAT);
+ debugAssert(cpuBitsPerPixel <= openGLBitsPerPixel);
}
+
+bool ImageFormat::sameComponents(const ImageFormat* other) const {
+ return
+ (numComponents == other->numComponents) &&
+ ((alphaBits != 0) == (other->alphaBits != 0)) &&
+ ((redBits != 0) == (other->redBits != 0)) &&
+ ((greenBits != 0) == (other->greenBits != 0)) &&
+ ((blueBits != 0) == (other->blueBits != 0)) &&
+ ((luminanceBits != 0) == (other->luminanceBits != 0)) &&
+ ((stencilBits != 0) == (other->stencilBits != 0)) &&
+ ((depthBits != 0) == (other->depthBits != 0));
+}
+
+
const ImageFormat* ImageFormat::depth(int depthBits) {
switch (depthBits) {
@@ -98,7 +112,7 @@ const ImageFormat* ImageFormat::stencil(int bits) {
}
- static const std::string nameArray[] =
+ static const std::string nameArray[ImageFormat::CODE_NUM] =
{
"L8",
"L16",
@@ -125,29 +139,62 @@ const ImageFormat* ImageFormat::stencil(int bits) {
"RGB16F",
"RGB32F",
"R11G11B10F",
- "RGB9E10F",
+ "RGB9E5F",
"RGB8I",
"RGB8UI",
+ "RGBA8I",
"RGBA8UI",
+ "RGB8_SNORM",
+ "RGBA8_SNORM",
+ "RGB16_SNORM",
+ "RGBA16_SNORM",
+
"ARGB8",
"BGR8",
+ "BGRA8",
"R8",
+ "R8I",
+ "R8UI",
+
+ "R16",
+ "R16I",
+ "R16UI",
+
+ "R32I",
+ "R32UI",
"RG8",
"RG8I",
"RG8UI",
+ "RG16",
+ "RG16I",
+ "RG16UI",
+
+ "R16F",
"RG16F",
+ "RG32I",
+ "RG32UI",
+
+ "R32F",
+ "RG32F",
+
"RGBA8",
"RGBA16",
"RGBA16F",
"RGBA32F",
+ "RGBA16I",
+ "RGBA16UI",
+
+ "RGB32I",
+ "RGB32UI",
+ "RGBA32I",
"RGBA32UI",
"BAYER_RGGB8",
@@ -192,8 +239,7 @@ const ImageFormat* ImageFormat::stencil(int bits) {
"STENCIL8",
"STENCIL16",
- "DEPTH24_STENCIL8",
- ""
+ "DEPTH24_STENCIL8"
};
const std::string& ImageFormat::name() const {
@@ -201,10 +247,148 @@ const std::string& ImageFormat::name() const {
return nameArray[code];
}
+bool ImageFormat::canInterpretAs(const ImageFormat* otherFormat) const {
+ if (this == otherFormat) {
+ return true;
+ }
+
+ if (compressed || otherFormat->compressed) {
+ return false;
+ }
+
+ if (colorSpace != otherFormat->colorSpace) {
+ return false;
+ }
+
+ if (floatingPoint != otherFormat->floatingPoint) {
+ return false;
+ }
+
+ if (numComponents != otherFormat->numComponents) {
+ return false;
+ }
+
+ if (cpuBitsPerPixel != otherFormat->cpuBitsPerPixel) {
+ return false;
+ }
+
+ if (openGLDataFormat != otherFormat->openGLDataFormat) {
+ return false;
+ }
+
+ return true;
+}
+
+
+const ImageFormat* ImageFormat::getSRGBFormat(const ImageFormat* otherFormat) {
+ switch (otherFormat->code) {
+ case CODE_RGB8:
+ return SRGB8();
+
+ case CODE_RGBA8:
+ return SRGBA8();
+
+ case CODE_RGB_DXT1:
+ return SRGB_DXT1();
+
+ case CODE_RGBA_DXT1:
+ return SRGBA_DXT1();
+
+ case CODE_RGBA_DXT3:
+ return SRGBA_DXT3();
+
+ case CODE_RGBA_DXT5:
+ return SRGBA_DXT5();
+
+ default:
+ return otherFormat;
+ }
+}
+
+
+const ImageFormat* ImageFormat::getFormatWithAlpha(const ImageFormat* otherFormat) {
+ if (! otherFormat->opaque) {
+ return otherFormat;
+ }
+
+ switch (otherFormat->code) {
+ case CODE_L8:
+ return LA8();
+ break;
+
+ case CODE_L16F:
+ return LA16F();
+ break;
+
+ case CODE_RGB8:
+ return RGBA8();
+ break;
+
+ case CODE_RGB8I:
+ return RGBA8I();
+ break;
+
+ case CODE_RGB32I:
+ return RGBA32I();
+ break;
+
+ case CODE_RGB32UI:
+ return RGBA32UI();
+ break;
+
+ case CODE_RGB8UI:
+ return RGBA8UI();
+ break;
+
+ case CODE_RGB8_SNORM:
+ return RGB8_SNORM();
+ break;
+ case CODE_RGBA8_SNORM:
+ return RGBA8_SNORM();
+ break;
+
+ case CODE_RGB16_SNORM:
+ return RGB16_SNORM();
+ break;
+
+ case CODE_RGBA16_SNORM:
+ return RGBA16_SNORM();
+ break;
+
+ case CODE_BGR8:
+ return BGRA8();
+ break;
+
+ case CODE_RGB16:
+ return RGBA16();
+ break;
+
+ case CODE_RGB16F:
+ return RGBA16F();
+ break;
+
+ case CODE_RGB32F:
+ return RGBA32F();
+ break;
+
+ case CODE_R11G11B10F:
+ return RGBA16F();
+ break;
+
+ default:
+ break;
+ }
+
+ return NULL;
+}
+
const ImageFormat* ImageFormat::fromString(const std::string& s) {
-
- for (int i = 0; ! nameArray[i].empty(); ++i) {
+ if (toLower(s) == "auto") {
+ return NULL;
+ }
+
+ for (int i = 0; i < CODE_NUM; ++i) {
if (s == nameArray[i]) {
return fromCode(ImageFormat::Code(i));
}
@@ -212,7 +396,6 @@ const ImageFormat* ImageFormat::fromString(const std::string& s) {
return NULL;
}
-
const ImageFormat* ImageFormat::fromCode(ImageFormat::Code code) {
switch (code) {
case ImageFormat::CODE_L8:
@@ -250,7 +433,7 @@ const ImageFormat* ImageFormat::fromCode(ImageFormat::Code code) {
case ImageFormat::CODE_LA16F:
return ImageFormat::LA16F();
- break;
+
case ImageFormat::CODE_LA32F:
return ImageFormat::LA32F();
@@ -287,15 +470,54 @@ const ImageFormat* ImageFormat::fromCode(ImageFormat::Code code) {
case ImageFormat::CODE_RGB8UI:
return ImageFormat::RGB8UI();
+ case ImageFormat::CODE_RGBA8I:
+ return ImageFormat::RGBA8I();
+
+ case ImageFormat::CODE_RGBA8UI:
+ return ImageFormat::RGBA8UI();
+
+ case ImageFormat::CODE_RGB8_SNORM:
+ return ImageFormat::RGB8_SNORM();
+ case ImageFormat::CODE_RGBA8_SNORM:
+ return ImageFormat::RGBA8_SNORM();
+ case ImageFormat::CODE_RGB16_SNORM:
+ return ImageFormat::RGB16_SNORM();
+ case ImageFormat::CODE_RGBA16_SNORM:
+ return ImageFormat::RGBA16_SNORM();
+
case ImageFormat::CODE_ARGB8:
return NULL;
case ImageFormat::CODE_BGR8:
return ImageFormat::BGR8();
+ case ImageFormat::CODE_BGRA8:
+ return ImageFormat::BGRA8();
+
case ImageFormat::CODE_R8:
return ImageFormat::R8();
+ case ImageFormat::CODE_R8I:
+ return ImageFormat::R8I();
+
+ case ImageFormat::CODE_R8UI:
+ return ImageFormat::R8UI();
+
+ case ImageFormat::CODE_R16:
+ return ImageFormat::R16();
+
+ case ImageFormat::CODE_R16I:
+ return ImageFormat::R16I();
+
+ case ImageFormat::CODE_R16UI:
+ return ImageFormat::R16UI();
+
+ case ImageFormat::CODE_R32I:
+ return ImageFormat::R32I();
+
+ case ImageFormat::CODE_R32UI:
+ return ImageFormat::R32UI();
+
case ImageFormat::CODE_RG8:
return ImageFormat::RG8();
@@ -305,9 +527,18 @@ const ImageFormat* ImageFormat::fromCode(ImageFormat::Code code) {
case ImageFormat::CODE_RG8UI:
return ImageFormat::RG8UI();
+ case ImageFormat::CODE_R16F:
+ return ImageFormat::R16F();
+
case ImageFormat::CODE_RG16F:
return ImageFormat::RG16F();
+ case ImageFormat::CODE_R32F:
+ return ImageFormat::R32F();
+
+ case ImageFormat::CODE_RG32F:
+ return ImageFormat::RG32F();
+
case ImageFormat::CODE_RGBA8:
return ImageFormat::RGBA8();
@@ -320,6 +551,15 @@ const ImageFormat* ImageFormat::fromCode(ImageFormat::Code code) {
case ImageFormat::CODE_RGBA32F:
return ImageFormat::RGBA32F();
+ case ImageFormat::CODE_RGB32I:
+ return ImageFormat::RGB32I();
+
+ case ImageFormat::CODE_RGBA32I:
+ return ImageFormat::RGBA32I();
+
+ case ImageFormat::CODE_RGB32UI:
+ return ImageFormat::RGB32UI();
+
case ImageFormat::CODE_RGBA32UI:
return ImageFormat::RGBA32UI();
@@ -439,11 +679,49 @@ const ImageFormat* ImageFormat::fromCode(ImageFormat::Code code) {
}
}
-// Helper variables for defining texture formats
-// Is floating point format
-static const bool FLOAT_FORMAT = true;
-static const bool INT_FORMAT = false;
+bool ImageFormat::representableAsColor1unorm8() const {
+ return (numComponents == 1) &&
+ (cpuBitsPerPixel == 8) &&
+ ((luminanceBits == 8) ||
+ (redBits == 8) ||
+ (alphaBits == 8));
+}
+
+
+bool ImageFormat::representableAsColor2unorm8() const {
+ return (numComponents == 2) &&
+ (cpuBitsPerPixel == 16) &&
+ ((redBits == 8 && greenBits == 8) ||
+ (luminanceBits == 8 && alphaBits == 8) ||
+ (redBits == 8 && alphaBits == 8));
+}
+
+
+bool ImageFormat::representableAsColor3unorm8() const {
+ return (numComponents == 3) &&
+ (cpuBitsPerPixel == 24) &&
+ (redBits == 8 && greenBits == 8 && blueBits == 8);
+}
+
+
+bool ImageFormat::representableAsColor4unorm8() const {
+ return (numComponents == 4) &&
+ (cpuBitsPerPixel == 32) &&
+ (redBits == 8 && greenBits == 8 && blueBits == 8 && alphaBits == 8);
+}
+
+Color4 ImageFormat::channelMask() const{
+ Color4 mask;
+ mask.r = (redBits > 0 || luminanceBits > 0) ? 1.0f : 0.0f;
+ mask.b = (blueBits > 0) ? 1.0f : 0.0f;
+ mask.g = (greenBits > 0) ? 1.0f : 0.0f;
+ mask.a = (alphaBits > 0) ? 1.0f : 0.0f;
+ return mask;
+
+}
+
+// Helper variables for defining texture formats
// Is opaque format (no alpha)
static const bool OPAQUE_FORMAT = true;
@@ -453,136 +731,176 @@ static const bool CLEAR_FORMAT = false;
static const bool COMP_FORMAT = true;
static const bool UNCOMP_FORMAT = false;
+
#define DEFINE_TEXTUREFORMAT_METHOD(enumname, cmpnts, cmprssd, glf, glbf, lb, ab, rb, gb, bb, db, sb, hbpt, pbpt, gldf, opq, fp, code, cs) \
const ImageFormat* ImageFormat::enumname() { \
static const ImageFormat format(cmpnts, cmprssd, glf, glbf, lb, ab, rb, gb, bb, db, sb, hbpt, pbpt, gldf, opq, fp, code, cs); \
return &format; }
-DEFINE_TEXTUREFORMAT_METHOD(L8, 1, UNCOMP_FORMAT, GL_LUMINANCE8, GL_LUMINANCE, 8, 0, 0, 0, 0, 0, 0, 8, 8, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INT_FORMAT, CODE_L8, COLOR_SPACE_NONE);
+DEFINE_TEXTUREFORMAT_METHOD(L8, 1, UNCOMP_FORMAT, GL_LUMINANCE8, GL_LUMINANCE, 8, 0, 0, 0, 0, 0, 0, 8, 8, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, NORMALIZED_FIXED_POINT_FORMAT, CODE_L8, COLOR_SPACE_NONE);
+
+DEFINE_TEXTUREFORMAT_METHOD(L16, 1, UNCOMP_FORMAT, GL_LUMINANCE16, GL_LUMINANCE, 16, 0, 0, 0, 0, 0, 0, 16, 16,GL_UNSIGNED_SHORT, OPAQUE_FORMAT, INTEGER_FORMAT, CODE_L16, COLOR_SPACE_NONE);
+
+DEFINE_TEXTUREFORMAT_METHOD(L16F, 1, UNCOMP_FORMAT, GL_LUMINANCE16F_ARB,GL_LUMINANCE, 16, 0, 0, 0, 0, 0, 0, 16, 16, GL_HALF_FLOAT, OPAQUE_FORMAT, FLOATING_POINT_FORMAT, CODE_L16F, COLOR_SPACE_NONE);
+
+DEFINE_TEXTUREFORMAT_METHOD(L32F, 1, UNCOMP_FORMAT, GL_LUMINANCE32F_ARB,GL_LUMINANCE, 32, 0, 0, 0, 0, 0, 0, 32, 32, GL_FLOAT, OPAQUE_FORMAT, FLOATING_POINT_FORMAT, CODE_L32F, COLOR_SPACE_NONE);
+
+DEFINE_TEXTUREFORMAT_METHOD(A8, 1, UNCOMP_FORMAT, GL_ALPHA8, GL_ALPHA, 0, 8, 0, 0, 0, 0, 0, 8, 8, GL_UNSIGNED_BYTE, CLEAR_FORMAT, NORMALIZED_FIXED_POINT_FORMAT, CODE_A8, COLOR_SPACE_NONE);
+
+DEFINE_TEXTUREFORMAT_METHOD(A16, 1, UNCOMP_FORMAT, GL_ALPHA16, GL_ALPHA, 0, 16, 0, 0, 0, 0, 0, 16, 16, GL_UNSIGNED_SHORT, CLEAR_FORMAT, NORMALIZED_FIXED_POINT_FORMAT, CODE_A16, COLOR_SPACE_NONE);
+
+DEFINE_TEXTUREFORMAT_METHOD(A16F, 1, UNCOMP_FORMAT, GL_ALPHA16F_ARB, GL_ALPHA, 0, 16, 0, 0, 0, 0, 0, 16, 16, GL_HALF_FLOAT, CLEAR_FORMAT, FLOATING_POINT_FORMAT, CODE_A16F, COLOR_SPACE_NONE);
-DEFINE_TEXTUREFORMAT_METHOD(L16, 1, UNCOMP_FORMAT, GL_LUMINANCE16, GL_LUMINANCE, 16, 0, 0, 0, 0, 0, 0, 16, 16,GL_UNSIGNED_SHORT, OPAQUE_FORMAT, INT_FORMAT, CODE_L16, COLOR_SPACE_NONE);
+DEFINE_TEXTUREFORMAT_METHOD(A32F, 1, UNCOMP_FORMAT, GL_ALPHA32F_ARB, GL_ALPHA, 0, 32, 0, 0, 0, 0, 0, 32, 32, GL_FLOAT, CLEAR_FORMAT, FLOATING_POINT_FORMAT, CODE_A32F, COLOR_SPACE_NONE);
-DEFINE_TEXTUREFORMAT_METHOD(L16F, 1, UNCOMP_FORMAT, GL_LUMINANCE16F_ARB,GL_LUMINANCE, 16, 0, 0, 0, 0, 0, 0, 16, 16, GL_FLOAT, OPAQUE_FORMAT, FLOAT_FORMAT, CODE_L16F, COLOR_SPACE_NONE);
+DEFINE_TEXTUREFORMAT_METHOD(LA4, 2, UNCOMP_FORMAT, GL_LUMINANCE4_ALPHA4, GL_LUMINANCE_ALPHA, 4, 4, 0, 0, 0, 0, 0, 8, 8, GL_UNSIGNED_BYTE, CLEAR_FORMAT, NORMALIZED_FIXED_POINT_FORMAT, CODE_LA4, COLOR_SPACE_NONE);
-DEFINE_TEXTUREFORMAT_METHOD(L32F, 1, UNCOMP_FORMAT, GL_LUMINANCE32F_ARB,GL_LUMINANCE, 32, 0, 0, 0, 0, 0, 0, 32, 32, GL_FLOAT, OPAQUE_FORMAT, FLOAT_FORMAT, CODE_L32F, COLOR_SPACE_NONE);
+DEFINE_TEXTUREFORMAT_METHOD(LA8, 2, UNCOMP_FORMAT, GL_LUMINANCE8_ALPHA8, GL_LUMINANCE_ALPHA, 8, 8, 0, 0, 0, 0, 0, 16, 16, GL_UNSIGNED_BYTE, CLEAR_FORMAT, NORMALIZED_FIXED_POINT_FORMAT, CODE_LA8, COLOR_SPACE_NONE);
-DEFINE_TEXTUREFORMAT_METHOD(A8, 1, UNCOMP_FORMAT, GL_ALPHA8, GL_ALPHA, 0, 8, 0, 0, 0, 0, 0, 8, 8, GL_UNSIGNED_BYTE, CLEAR_FORMAT, INT_FORMAT, CODE_A8, COLOR_SPACE_NONE);
+DEFINE_TEXTUREFORMAT_METHOD(LA16, 2, UNCOMP_FORMAT, GL_LUMINANCE16_ALPHA16, GL_LUMINANCE_ALPHA, 16, 16, 0, 0, 0, 0, 0, 16*2, 16*2, GL_UNSIGNED_SHORT, CLEAR_FORMAT, NORMALIZED_FIXED_POINT_FORMAT, CODE_LA16, COLOR_SPACE_NONE);
-DEFINE_TEXTUREFORMAT_METHOD(A16, 1, UNCOMP_FORMAT, GL_ALPHA16, GL_ALPHA, 0, 16, 0, 0, 0, 0, 0, 16, 16, GL_UNSIGNED_SHORT, CLEAR_FORMAT, INT_FORMAT, CODE_A16, COLOR_SPACE_NONE);
+DEFINE_TEXTUREFORMAT_METHOD(LA16F, 2, UNCOMP_FORMAT, GL_LUMINANCE_ALPHA16F_ARB, GL_LUMINANCE_ALPHA, 16, 16, 0, 0, 0, 0, 0, 16*2, 16*2, GL_HALF_FLOAT, CLEAR_FORMAT, FLOATING_POINT_FORMAT, ImageFormat::CODE_LA16F, ImageFormat::COLOR_SPACE_NONE);
-DEFINE_TEXTUREFORMAT_METHOD(A16F, 1, UNCOMP_FORMAT, GL_ALPHA16F_ARB, GL_ALPHA, 0, 16, 0, 0, 0, 0, 0, 16, 16, GL_FLOAT, CLEAR_FORMAT, FLOAT_FORMAT, CODE_A16F, COLOR_SPACE_NONE);
+DEFINE_TEXTUREFORMAT_METHOD(LA32F, 2, UNCOMP_FORMAT, GL_LUMINANCE_ALPHA32F_ARB, GL_LUMINANCE_ALPHA, 32, 32, 0, 0, 0, 0, 0, 32*2, 32*2, GL_FLOAT, CLEAR_FORMAT, FLOATING_POINT_FORMAT, ImageFormat::CODE_LA32F, ImageFormat::COLOR_SPACE_NONE);
-DEFINE_TEXTUREFORMAT_METHOD(A32F, 1, UNCOMP_FORMAT, GL_ALPHA32F_ARB, GL_ALPHA, 0, 32, 0, 0, 0, 0, 0, 32, 32, GL_FLOAT, CLEAR_FORMAT, FLOAT_FORMAT, CODE_A32F, COLOR_SPACE_NONE);
+DEFINE_TEXTUREFORMAT_METHOD(BGR8, 3, UNCOMP_FORMAT, GL_RGB8, GL_BGR, 0, 0, 8, 8, 8, 0, 0, 32, 24, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, NORMALIZED_FIXED_POINT_FORMAT, ImageFormat::CODE_BGR8, ImageFormat::COLOR_SPACE_RGB);
-DEFINE_TEXTUREFORMAT_METHOD(LA4, 2, UNCOMP_FORMAT, GL_LUMINANCE4_ALPHA4, GL_LUMINANCE_ALPHA, 4, 4, 0, 0, 0, 0, 0, 8, 8, GL_UNSIGNED_BYTE, CLEAR_FORMAT, INT_FORMAT, CODE_LA4, COLOR_SPACE_NONE);
+DEFINE_TEXTUREFORMAT_METHOD(BGRA8, 4, UNCOMP_FORMAT, GL_RGBA8, GL_BGRA, 0, 8, 8, 8, 8, 0, 0, 32, 32, GL_UNSIGNED_BYTE, CLEAR_FORMAT, NORMALIZED_FIXED_POINT_FORMAT, ImageFormat::CODE_BGRA8, ImageFormat::COLOR_SPACE_RGB);
-DEFINE_TEXTUREFORMAT_METHOD(LA8, 2, UNCOMP_FORMAT, GL_LUMINANCE8_ALPHA8, GL_LUMINANCE_ALPHA, 8, 8, 0, 0, 0, 0, 0, 16, 16, GL_UNSIGNED_BYTE, CLEAR_FORMAT, INT_FORMAT, CODE_LA8, COLOR_SPACE_NONE);
+DEFINE_TEXTUREFORMAT_METHOD(R8, 1, UNCOMP_FORMAT, GL_R8, GL_RED, 0, 0, 8, 0, 0, 0, 0, 8, 8, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, NORMALIZED_FIXED_POINT_FORMAT, ImageFormat::CODE_R8, ImageFormat::COLOR_SPACE_RGB);
-DEFINE_TEXTUREFORMAT_METHOD(LA16, 2, UNCOMP_FORMAT, GL_LUMINANCE16_ALPHA16, GL_LUMINANCE_ALPHA, 16, 16, 0, 0, 0, 0, 0, 16*2, 16*2, GL_UNSIGNED_SHORT, CLEAR_FORMAT, INT_FORMAT, CODE_LA16, COLOR_SPACE_NONE);
+DEFINE_TEXTUREFORMAT_METHOD(R8I, 1, UNCOMP_FORMAT, GL_R8I, GL_RED_INTEGER, 0, 0, 8, 0, 0, 0, 0, 8, 8, GL_BYTE, OPAQUE_FORMAT, INTEGER_FORMAT, ImageFormat::CODE_R8I, ImageFormat::COLOR_SPACE_RGB);
-DEFINE_TEXTUREFORMAT_METHOD(LA16F, 2, UNCOMP_FORMAT, GL_LUMINANCE_ALPHA16F_ARB, GL_LUMINANCE_ALPHA, 16, 16, 0, 0, 0, 0, 0, 16*2, 16*2, GL_FLOAT, CLEAR_FORMAT, FLOAT_FORMAT, ImageFormat::CODE_LA16F, ImageFormat::COLOR_SPACE_NONE);
+DEFINE_TEXTUREFORMAT_METHOD(R8UI, 1, UNCOMP_FORMAT, GL_R8UI, GL_RED_INTEGER, 0, 0, 8, 0, 0, 0, 0, 8, 8, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INTEGER_FORMAT, ImageFormat::CODE_R8UI, ImageFormat::COLOR_SPACE_RGB);
-DEFINE_TEXTUREFORMAT_METHOD(LA32F, 2, UNCOMP_FORMAT, GL_LUMINANCE_ALPHA32F_ARB, GL_LUMINANCE_ALPHA, 32, 32, 0, 0, 0, 0, 0, 32*2, 32*2, GL_FLOAT, CLEAR_FORMAT, FLOAT_FORMAT, ImageFormat::CODE_LA32F, ImageFormat::COLOR_SPACE_NONE);
+DEFINE_TEXTUREFORMAT_METHOD(R16, 1, UNCOMP_FORMAT, GL_R16, GL_RED, 0, 0, 16, 0, 0, 0, 0, 16, 16, GL_UNSIGNED_SHORT, OPAQUE_FORMAT, NORMALIZED_FIXED_POINT_FORMAT, ImageFormat::CODE_R16, ImageFormat::COLOR_SPACE_RGB);
-DEFINE_TEXTUREFORMAT_METHOD(BGR8, 3, UNCOMP_FORMAT, GL_RGB8, GL_BGR, 0, 0, 8, 8, 8, 0, 0, 32, 24, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INT_FORMAT, ImageFormat::CODE_BGR8, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(R16I, 1, UNCOMP_FORMAT, GL_R16I, GL_RED_INTEGER, 0, 0, 16, 0, 0, 0, 0, 16, 16, GL_SHORT, OPAQUE_FORMAT, INTEGER_FORMAT, ImageFormat::CODE_R16I, ImageFormat::COLOR_SPACE_RGB);
-DEFINE_TEXTUREFORMAT_METHOD(R8, 1, UNCOMP_FORMAT, GL_R8, GL_RED, 0, 0, 8, 0, 0, 0, 0, 8, 8, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INT_FORMAT, ImageFormat::CODE_R8, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(R16UI, 1, UNCOMP_FORMAT, GL_R16UI, GL_RED_INTEGER, 0, 0, 16, 0, 0, 0, 0, 16, 16, GL_UNSIGNED_SHORT, OPAQUE_FORMAT, INTEGER_FORMAT, ImageFormat::CODE_R16UI, ImageFormat::COLOR_SPACE_RGB);
-DEFINE_TEXTUREFORMAT_METHOD(RG8, 2, UNCOMP_FORMAT, GL_RG8, GL_RG, 0, 0, 8, 8, 0, 0, 0, 16, 16, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INT_FORMAT, ImageFormat::CODE_RG8, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(R32I, 1, UNCOMP_FORMAT, GL_R32I, GL_RED_INTEGER, 0, 0, 32, 0, 0, 0, 0, 32, 32, GL_INT, OPAQUE_FORMAT, INTEGER_FORMAT, ImageFormat::CODE_R32I, ImageFormat::COLOR_SPACE_RGB);
+
+DEFINE_TEXTUREFORMAT_METHOD(R32UI, 1, UNCOMP_FORMAT, GL_R32UI, GL_RED_INTEGER, 0, 0, 32, 0, 0, 0, 0, 32, 32, GL_UNSIGNED_INT, OPAQUE_FORMAT, INTEGER_FORMAT, ImageFormat::CODE_R32UI, ImageFormat::COLOR_SPACE_RGB);
+
+DEFINE_TEXTUREFORMAT_METHOD(RG8, 2, UNCOMP_FORMAT, GL_RG8, GL_RG, 0, 0, 8, 8, 0, 0, 0, 16, 16, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, NORMALIZED_FIXED_POINT_FORMAT, ImageFormat::CODE_RG8, ImageFormat::COLOR_SPACE_RGB);
// The base format for integer formats must be *_INTEGER even though the spec doesn't state this
-DEFINE_TEXTUREFORMAT_METHOD(RG8I, 2, UNCOMP_FORMAT, GL_RG8I, GL_RG_INTEGER, 0, 0, 8, 8, 0, 0, 0, 16, 16, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INT_FORMAT, ImageFormat::CODE_RG8I, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(RG8I, 2, UNCOMP_FORMAT, GL_RG8I, GL_RG_INTEGER, 0, 0, 8, 8, 0, 0, 0, 16, 16, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INTEGER_FORMAT, ImageFormat::CODE_RG8I, ImageFormat::COLOR_SPACE_RGB);
+
+DEFINE_TEXTUREFORMAT_METHOD(RG8UI, 2, UNCOMP_FORMAT, GL_RG8UI, GL_RG_INTEGER, 0, 0, 8, 8, 0, 0, 0, 16, 16, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INTEGER_FORMAT, ImageFormat::CODE_RG8UI, ImageFormat::COLOR_SPACE_RGB);
+
+DEFINE_TEXTUREFORMAT_METHOD(RG16, 2, UNCOMP_FORMAT, GL_RG16, GL_RG, 0, 0, 16, 16, 0, 0, 0, 16*2, 16*2, GL_UNSIGNED_SHORT, OPAQUE_FORMAT, NORMALIZED_FIXED_POINT_FORMAT, ImageFormat::CODE_RG16, ImageFormat::COLOR_SPACE_RGB);
-DEFINE_TEXTUREFORMAT_METHOD(RG8UI, 2, UNCOMP_FORMAT, GL_RG8UI, GL_RG_INTEGER, 0, 0, 8, 8, 0, 0, 0, 16, 16, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INT_FORMAT, ImageFormat::CODE_RG8UI, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(RG16I, 2, UNCOMP_FORMAT, GL_RG16I, GL_RG_INTEGER, 0, 0, 16, 16, 0, 0, 0, 16*2, 16*2, GL_SHORT, OPAQUE_FORMAT, INTEGER_FORMAT, ImageFormat::CODE_RG16I, ImageFormat::COLOR_SPACE_RGB);
-DEFINE_TEXTUREFORMAT_METHOD(RG16F, 2, UNCOMP_FORMAT, GL_RG16F, GL_RG, 0, 0, 16, 16, 0, 0, 0, 32, 32, GL_FLOAT, OPAQUE_FORMAT, FLOAT_FORMAT, ImageFormat::CODE_RG16F, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(RG16UI, 2, UNCOMP_FORMAT, GL_RG16UI, GL_RG_INTEGER, 0, 0, 16, 16, 0, 0, 0, 16*2, 16*2, GL_UNSIGNED_SHORT, OPAQUE_FORMAT, INTEGER_FORMAT, ImageFormat::CODE_RG16UI, ImageFormat::COLOR_SPACE_RGB);
-DEFINE_TEXTUREFORMAT_METHOD(RGB5, 3, UNCOMP_FORMAT, GL_RGB5, GL_RGBA, 0, 0, 5, 5, 5, 0, 0, 16, 16, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INT_FORMAT, ImageFormat::CODE_RGB5, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(R16F, 1, UNCOMP_FORMAT, GL_R16F, GL_RED, 0, 0, 16, 0, 0, 0, 0, 16, 16, GL_HALF_FLOAT, OPAQUE_FORMAT, FLOATING_POINT_FORMAT, ImageFormat::CODE_R16F, ImageFormat::COLOR_SPACE_RGB);
-DEFINE_TEXTUREFORMAT_METHOD(RGB5A1, 4, UNCOMP_FORMAT, GL_RGB5_A1, GL_RGBA, 0, 1, 5, 5, 5, 0, 0, 16, 16, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INT_FORMAT, ImageFormat::CODE_RGB5A1, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(RG16F, 2, UNCOMP_FORMAT, GL_RG16F, GL_RG, 0, 0, 16, 16, 0, 0, 0, 32, 32, GL_HALF_FLOAT, OPAQUE_FORMAT, FLOATING_POINT_FORMAT, ImageFormat::CODE_RG16F, ImageFormat::COLOR_SPACE_RGB);
-DEFINE_TEXTUREFORMAT_METHOD(RGB8, 3, UNCOMP_FORMAT, GL_RGB8, GL_RGB, 0, 0, 8, 8, 8, 0, 0, 32, 24, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INT_FORMAT, ImageFormat::CODE_RGB8, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(RG32I, 2, UNCOMP_FORMAT, GL_RG32I, GL_RG_INTEGER, 0, 0, 32, 32, 0, 0, 0, 32*2, 32*2, GL_INT, OPAQUE_FORMAT, INTEGER_FORMAT, ImageFormat::CODE_RG32I, ImageFormat::COLOR_SPACE_RGB);
-DEFINE_TEXTUREFORMAT_METHOD(RGB10, 3, UNCOMP_FORMAT, GL_RGB10, GL_RGB, 0, 0, 10, 10, 10, 0, 0, 32, 10*3, GL_UNSIGNED_SHORT, OPAQUE_FORMAT, INT_FORMAT, ImageFormat::CODE_RGB10, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(RG32UI, 2, UNCOMP_FORMAT, GL_RG32UI, GL_RG_INTEGER, 0, 0, 32, 32, 0, 0, 0, 32*2, 32*2, GL_UNSIGNED_INT, OPAQUE_FORMAT, INTEGER_FORMAT, ImageFormat::CODE_RG32UI, ImageFormat::COLOR_SPACE_RGB);
-DEFINE_TEXTUREFORMAT_METHOD(RGB10A2, 4, UNCOMP_FORMAT, GL_RGB10_A2, GL_RGBA, 0, 2, 10, 10, 10, 0, 0, 32, 32, GL_UNSIGNED_INT_10_10_10_2, OPAQUE_FORMAT, INT_FORMAT, ImageFormat::CODE_RGB10A2, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(R32F, 1, UNCOMP_FORMAT, GL_R32F, GL_RED, 0, 0, 32, 0, 0, 0, 0, 32, 32, GL_FLOAT, OPAQUE_FORMAT, FLOATING_POINT_FORMAT, ImageFormat::CODE_R32F, ImageFormat::COLOR_SPACE_RGB);
-DEFINE_TEXTUREFORMAT_METHOD(RGB16, 3, UNCOMP_FORMAT, GL_RGB16, GL_RGB, 0, 0, 16, 16, 16, 0, 0, 16*3, 16*3, GL_UNSIGNED_SHORT, OPAQUE_FORMAT, INT_FORMAT, ImageFormat::CODE_RGB16, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(RG32F, 2, UNCOMP_FORMAT, GL_RG32F, GL_RG, 0, 0, 32, 32, 0, 0, 0, 64, 64, GL_FLOAT, OPAQUE_FORMAT, FLOATING_POINT_FORMAT, ImageFormat::CODE_RG32F, ImageFormat::COLOR_SPACE_RGB);
-DEFINE_TEXTUREFORMAT_METHOD(RGB16F, 3, UNCOMP_FORMAT, GL_RGB16F_ARB, GL_RGB, 0, 0, 16, 16, 16, 0, 0, 16*3, 16*3, GL_FLOAT, OPAQUE_FORMAT, FLOAT_FORMAT, ImageFormat::CODE_RGB16F, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(RGB5, 3, UNCOMP_FORMAT, GL_RGB5, GL_RGBA, 0, 0, 5, 5, 5, 0, 0, 16, 16, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, NORMALIZED_FIXED_POINT_FORMAT, ImageFormat::CODE_RGB5, ImageFormat::COLOR_SPACE_RGB);
-DEFINE_TEXTUREFORMAT_METHOD(RGB32F, 3, UNCOMP_FORMAT, GL_RGB32F_ARB, GL_RGB, 0, 0, 32, 32, 32, 0, 0, 32*3, 32*3, GL_FLOAT, OPAQUE_FORMAT, FLOAT_FORMAT, ImageFormat::CODE_RGB32F, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(RGB5A1, 4, UNCOMP_FORMAT, GL_RGB5_A1, GL_RGBA, 0, 1, 5, 5, 5, 0, 0, 16, 16, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, NORMALIZED_FIXED_POINT_FORMAT, ImageFormat::CODE_RGB5A1, ImageFormat::COLOR_SPACE_RGB);
-DEFINE_TEXTUREFORMAT_METHOD(RGBA8, 4, UNCOMP_FORMAT, GL_RGBA8, GL_RGBA, 0, 8, 8, 8, 8, 0, 0, 32, 32, GL_UNSIGNED_BYTE, CLEAR_FORMAT, INT_FORMAT, ImageFormat::CODE_RGBA8, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(RGB8, 3, UNCOMP_FORMAT, GL_RGB8, GL_RGB, 0, 0, 8, 8, 8, 0, 0, 32, 24, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, NORMALIZED_FIXED_POINT_FORMAT, ImageFormat::CODE_RGB8, ImageFormat::COLOR_SPACE_RGB);
-DEFINE_TEXTUREFORMAT_METHOD(RGBA16, 4, UNCOMP_FORMAT, GL_RGBA16, GL_RGBA, 0, 16, 16, 16, 16, 0, 0, 16*4, 16*4, GL_UNSIGNED_SHORT, CLEAR_FORMAT, INT_FORMAT, ImageFormat::CODE_RGBA16, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(RGB10, 3, UNCOMP_FORMAT, GL_RGB10, GL_RGB, 0, 0, 10, 10, 10, 0, 0, 32, 10*3, GL_UNSIGNED_SHORT, OPAQUE_FORMAT, NORMALIZED_FIXED_POINT_FORMAT, ImageFormat::CODE_RGB10, ImageFormat::COLOR_SPACE_RGB);
-DEFINE_TEXTUREFORMAT_METHOD(RGBA16F, 4, UNCOMP_FORMAT, GL_RGBA16F_ARB, GL_RGBA, 0, 16, 16, 16, 16, 0, 0, 16*4, 16*4, GL_FLOAT, CLEAR_FORMAT, FLOAT_FORMAT, ImageFormat::CODE_RGBA16F, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(RGB10A2, 4, UNCOMP_FORMAT, GL_RGB10_A2, GL_RGBA, 0, 2, 10, 10, 10, 0, 0, 32, 32, GL_UNSIGNED_INT_10_10_10_2, OPAQUE_FORMAT, NORMALIZED_FIXED_POINT_FORMAT, ImageFormat::CODE_RGB10A2, ImageFormat::COLOR_SPACE_RGB);
+
+DEFINE_TEXTUREFORMAT_METHOD(RGB16, 3, UNCOMP_FORMAT, GL_RGB16, GL_RGB, 0, 0, 16, 16, 16, 0, 0, 16*3, 16*3, GL_UNSIGNED_SHORT, OPAQUE_FORMAT, NORMALIZED_FIXED_POINT_FORMAT, ImageFormat::CODE_RGB16, ImageFormat::COLOR_SPACE_RGB);
+
+DEFINE_TEXTUREFORMAT_METHOD(RGB16F, 3, UNCOMP_FORMAT, GL_RGB16F_ARB, GL_RGB, 0, 0, 16, 16, 16, 0, 0, 16*3, 16*3, GL_HALF_FLOAT, OPAQUE_FORMAT, FLOATING_POINT_FORMAT, ImageFormat::CODE_RGB16F, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(RGB32F, 3, UNCOMP_FORMAT, GL_RGB32F_ARB, GL_RGB, 0, 0, 32, 32, 32, 0, 0, 32*3, 32*3, GL_FLOAT, OPAQUE_FORMAT, FLOATING_POINT_FORMAT, ImageFormat::CODE_RGB32F, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(RGBA8, 4, UNCOMP_FORMAT, GL_RGBA8, GL_RGBA, 0, 8, 8, 8, 8, 0, 0, 32, 32, GL_UNSIGNED_BYTE, CLEAR_FORMAT, NORMALIZED_FIXED_POINT_FORMAT, ImageFormat::CODE_RGBA8, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(RGBA16, 4, UNCOMP_FORMAT, GL_RGBA16, GL_RGBA, 0, 16, 16, 16, 16, 0, 0, 16*4, 16*4, GL_UNSIGNED_SHORT, CLEAR_FORMAT, NORMALIZED_FIXED_POINT_FORMAT, ImageFormat::CODE_RGBA16, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(RGBA16F, 4, UNCOMP_FORMAT, GL_RGBA16F_ARB, GL_RGBA, 0, 16, 16, 16, 16, 0, 0, 16*4, 16*4, GL_HALF_FLOAT, CLEAR_FORMAT, FLOATING_POINT_FORMAT, ImageFormat::CODE_RGBA16F, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(RGBA32F, 4, UNCOMP_FORMAT, GL_RGBA32F_ARB, GL_RGBA, 0, 32, 32, 32, 32, 0, 0, 32*4, 32*4, GL_FLOAT, CLEAR_FORMAT, FLOATING_POINT_FORMAT, ImageFormat::CODE_RGBA32F, ImageFormat::COLOR_SPACE_RGB);
+
+DEFINE_TEXTUREFORMAT_METHOD(RGBA16I, 4, UNCOMP_FORMAT, GL_RGBA16I, GL_RGBA_INTEGER, 0, 16, 16, 16, 16, 0, 0, 16*4, 16*4, GL_SHORT, CLEAR_FORMAT, INTEGER_FORMAT, ImageFormat::CODE_RGBA16I, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(RGBA16UI, 4, UNCOMP_FORMAT, GL_RGBA16UI, GL_RGBA_INTEGER, 0, 16, 16, 16, 16, 0, 0, 16*4, 16*4, GL_UNSIGNED_SHORT, CLEAR_FORMAT, INTEGER_FORMAT, ImageFormat::CODE_RGBA16UI, ImageFormat::COLOR_SPACE_RGB);
-DEFINE_TEXTUREFORMAT_METHOD(RGBA32F, 4, UNCOMP_FORMAT, GL_RGBA32F_ARB, GL_RGBA, 0, 32, 32, 32, 32, 0, 0, 32*4, 32*4, GL_FLOAT, CLEAR_FORMAT, FLOAT_FORMAT, ImageFormat::CODE_RGBA32F, ImageFormat::COLOR_SPACE_RGB);
// The base format for integer formats must be *_INTEGER even though the spec doesn't state this
-DEFINE_TEXTUREFORMAT_METHOD(RGBA32UI, 4, UNCOMP_FORMAT, GL_RGBA32UI, GL_RGBA_INTEGER, 0, 32, 32, 32, 32, 0, 0, 32*4, 32*4, GL_UNSIGNED_INT, CLEAR_FORMAT, INT_FORMAT, ImageFormat::CODE_RGBA32UI, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(RGB32I, 3, UNCOMP_FORMAT, GL_RGB32I, GL_RGBA_INTEGER, 0, 32, 32, 32, 0, 0, 0, 32*3, 32*3, GL_INT, OPAQUE_FORMAT, INTEGER_FORMAT, ImageFormat::CODE_RGB32I, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(RGB32UI, 3, UNCOMP_FORMAT, GL_RGB32UI, GL_RGBA_INTEGER, 0, 32, 32, 32, 0, 0, 0, 32*3, 32*3, GL_UNSIGNED_INT, OPAQUE_FORMAT, INTEGER_FORMAT, ImageFormat::CODE_RGB32UI, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(RGBA32I, 4, UNCOMP_FORMAT, GL_RGBA32I, GL_RGBA_INTEGER, 0, 32, 32, 32, 32, 0, 0, 32*4, 32*4, GL_INT, CLEAR_FORMAT, INTEGER_FORMAT, ImageFormat::CODE_RGBA32I, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(RGBA32UI, 4, UNCOMP_FORMAT, GL_RGBA32UI, GL_RGBA_INTEGER, 0, 32, 32, 32, 32, 0, 0, 32*4, 32*4, GL_UNSIGNED_INT, CLEAR_FORMAT, INTEGER_FORMAT, ImageFormat::CODE_RGBA32UI, ImageFormat::COLOR_SPACE_RGB);
-// Unsigned
-DEFINE_TEXTUREFORMAT_METHOD(R11G11B10F, 3, UNCOMP_FORMAT, GL_R11F_G11F_B10F_EXT, GL_RGB, 0, 0, 11, 11, 10, 0, 0, 32, 32, GL_FLOAT, OPAQUE_FORMAT, FLOAT_FORMAT, ImageFormat::CODE_R11G11B10F, ImageFormat::COLOR_SPACE_RGB);
-// Unsigned
-DEFINE_TEXTUREFORMAT_METHOD(RGB9E5F, 3, UNCOMP_FORMAT, GL_RGB9_E5_EXT, GL_RGB, 0, 0, 14, 14, 14, 0, 0, 32, 32, GL_FLOAT, OPAQUE_FORMAT, FLOAT_FORMAT, ImageFormat::CODE_RGB9E5F, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(R11G11B10F, 3, UNCOMP_FORMAT, GL_R11F_G11F_B10F_EXT,GL_RGB, 0, 0, 11, 11, 10, 0, 0, 32, 32, GL_FLOAT, OPAQUE_FORMAT, FLOATING_POINT_FORMAT, ImageFormat::CODE_R11G11B10F, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(RGB9E5F, 3, UNCOMP_FORMAT, GL_RGB9_E5_EXT, GL_RGB, 0, 0, 14, 14, 14, 0, 0, 32, 32, GL_FLOAT, OPAQUE_FORMAT, FLOATING_POINT_FORMAT, ImageFormat::CODE_RGB9E5F, ImageFormat::COLOR_SPACE_RGB);
// The base format for integer formats must be *_INTEGER even though the spec doesn't state this
-DEFINE_TEXTUREFORMAT_METHOD(RGB8I, 3, UNCOMP_FORMAT, GL_RGB8I_EXT, GL_RGB_INTEGER, 0, 0, 8, 8, 8, 0, 0, 32, 24, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INT_FORMAT, ImageFormat::CODE_RGB8I, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(RGB8I, 3, UNCOMP_FORMAT, GL_RGB8I_EXT, GL_RGB_INTEGER, 0, 0, 8, 8, 8, 0, 0, 32, 24, GL_BYTE, OPAQUE_FORMAT, INTEGER_FORMAT, ImageFormat::CODE_RGB8I, ImageFormat::COLOR_SPACE_RGB);
-DEFINE_TEXTUREFORMAT_METHOD(RGB8UI, 3, UNCOMP_FORMAT, GL_RGB8UI_EXT, GL_RGB_INTEGER, 0, 0, 8, 8, 8, 0, 0, 32, 24, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INT_FORMAT, ImageFormat::CODE_RGB8UI, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(RGB8UI, 3, UNCOMP_FORMAT, GL_RGB8UI_EXT, GL_RGB_INTEGER, 0, 0, 8, 8, 8, 0, 0, 32, 24, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INTEGER_FORMAT, ImageFormat::CODE_RGB8UI, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(RGBA8I, 4, UNCOMP_FORMAT, GL_RGBA8I_EXT, GL_RGBA_INTEGER, 0, 8, 8, 8, 8, 0, 0, 32, 32, GL_BYTE, CLEAR_FORMAT, INTEGER_FORMAT, ImageFormat::CODE_RGBA8I, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(RGBA8UI, 4, UNCOMP_FORMAT, GL_RGBA8UI_EXT, GL_RGBA_INTEGER, 0, 8, 8, 8, 8, 0, 0, 32, 32, GL_UNSIGNED_BYTE, CLEAR_FORMAT, INTEGER_FORMAT, ImageFormat::CODE_RGBA8UI, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(RGB8_SNORM, 3, UNCOMP_FORMAT, GL_RGB8_SNORM, GL_RGB, 0, 0, 8, 8, 8, 0, 0, 32, 32, GL_BYTE, OPAQUE_FORMAT, NORMALIZED_FIXED_POINT_FORMAT, ImageFormat::CODE_RGB8_SNORM, ImageFormat::COLOR_SPACE_RGB);
-DEFINE_TEXTUREFORMAT_METHOD(RGBA8UI, 4, UNCOMP_FORMAT, GL_RGBA8UI_EXT, GL_RGBA_INTEGER, 0, 0, 8, 8, 8, 8, 0, 32, 32, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INT_FORMAT, ImageFormat::CODE_RGBA8UI, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(RGBA8_SNORM,4, UNCOMP_FORMAT, GL_RGBA8_SNORM, GL_RGBA, 0, 8, 8, 8, 8, 0, 0, 32, 32, GL_BYTE, CLEAR_FORMAT, NORMALIZED_FIXED_POINT_FORMAT, ImageFormat::CODE_RGBA8_SNORM, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(RGB16_SNORM,3, UNCOMP_FORMAT, GL_RGB16_SNORM, GL_RGB, 0, 0, 16, 16, 16, 0, 0, 64, 64, GL_SHORT, OPAQUE_FORMAT, NORMALIZED_FIXED_POINT_FORMAT, ImageFormat::CODE_RGB16_SNORM, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(RGBA16_SNORM,4,UNCOMP_FORMAT, GL_RGBA16_SNORM, GL_RGB, 0, 16, 16, 16, 16, 0, 0, 64, 64, GL_SHORT, CLEAR_FORMAT, NORMALIZED_FIXED_POINT_FORMAT, ImageFormat::CODE_RGBA16_SNORM, ImageFormat::COLOR_SPACE_RGB);
-DEFINE_TEXTUREFORMAT_METHOD(RGB_DXT1, 3, COMP_FORMAT, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_RGB, 0, 0, 0, 0, 0, 0, 0, 64, 64, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INT_FORMAT, ImageFormat::CODE_RGB_DXT1, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(RGB_DXT1, 3, COMP_FORMAT, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_RGB, 0, 0, 0, 0, 0, 0, 0, 64, 64, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, OTHER, ImageFormat::CODE_RGB_DXT1, ImageFormat::COLOR_SPACE_RGB);
-DEFINE_TEXTUREFORMAT_METHOD(RGBA_DXT1, 4, COMP_FORMAT, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_RGBA, 0, 0, 0, 0, 0, 0, 0, 64, 64, GL_UNSIGNED_BYTE, CLEAR_FORMAT, INT_FORMAT, ImageFormat::CODE_RGBA_DXT1, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(RGBA_DXT1, 4, COMP_FORMAT, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_RGBA, 0, 0, 0, 0, 0, 0, 0, 64, 64, GL_UNSIGNED_BYTE, CLEAR_FORMAT, OTHER, ImageFormat::CODE_RGBA_DXT1, ImageFormat::COLOR_SPACE_RGB);
-DEFINE_TEXTUREFORMAT_METHOD(RGBA_DXT3, 4, COMP_FORMAT, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_RGBA, 0, 0, 0, 0, 0, 0, 0, 128, 128, GL_UNSIGNED_BYTE, CLEAR_FORMAT, INT_FORMAT, ImageFormat::CODE_RGBA_DXT3, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(RGBA_DXT3, 4, COMP_FORMAT, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_RGBA, 0, 0, 0, 0, 0, 0, 0, 128, 128, GL_UNSIGNED_BYTE, CLEAR_FORMAT, OTHER, ImageFormat::CODE_RGBA_DXT3, ImageFormat::COLOR_SPACE_RGB);
-DEFINE_TEXTUREFORMAT_METHOD(RGBA_DXT5, 4, COMP_FORMAT, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_RGBA, 0, 0, 0, 0, 0, 0, 0, 128, 128, GL_UNSIGNED_BYTE, CLEAR_FORMAT, INT_FORMAT, ImageFormat::CODE_RGBA_DXT5, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(RGBA_DXT5, 4, COMP_FORMAT, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_RGBA, 0, 0, 0, 0, 0, 0, 0, 128, 128, GL_UNSIGNED_BYTE, CLEAR_FORMAT, OTHER, ImageFormat::CODE_RGBA_DXT5, ImageFormat::COLOR_SPACE_RGB);
-DEFINE_TEXTUREFORMAT_METHOD(SRGB8, 3, UNCOMP_FORMAT, GL_SRGB8, GL_RGB, 0, 0, 8, 8, 8, 0, 0, 32, 24, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INT_FORMAT, ImageFormat::CODE_SRGB8, ImageFormat::COLOR_SPACE_SRGB);
+DEFINE_TEXTUREFORMAT_METHOD(SRGB8, 3, UNCOMP_FORMAT, GL_SRGB8, GL_RGB, 0, 0, 8, 8, 8, 0, 0, 32, 24, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, NORMALIZED_FIXED_POINT_FORMAT, ImageFormat::CODE_SRGB8, ImageFormat::COLOR_SPACE_SRGB);
-DEFINE_TEXTUREFORMAT_METHOD(SRGBA8, 4, UNCOMP_FORMAT, GL_SRGB8_ALPHA8, GL_RGBA, 0, 8, 8, 8, 8, 0, 0, 32, 24, GL_UNSIGNED_BYTE, CLEAR_FORMAT, INT_FORMAT, ImageFormat::CODE_SRGBA8, ImageFormat::COLOR_SPACE_SRGB);
+DEFINE_TEXTUREFORMAT_METHOD(SRGBA8, 4, UNCOMP_FORMAT, GL_SRGB8_ALPHA8, GL_RGBA, 0, 8, 8, 8, 8, 0, 0, 32, 24, GL_UNSIGNED_BYTE, CLEAR_FORMAT, NORMALIZED_FIXED_POINT_FORMAT, ImageFormat::CODE_SRGBA8, ImageFormat::COLOR_SPACE_SRGB);
-DEFINE_TEXTUREFORMAT_METHOD(SL8, 1, UNCOMP_FORMAT, GL_SLUMINANCE8, GL_LUMINANCE, 8, 0, 0, 0, 0, 0, 0, 8, 8, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INT_FORMAT, ImageFormat::CODE_SL8, ImageFormat::COLOR_SPACE_SRGB);
+DEFINE_TEXTUREFORMAT_METHOD(SL8, 1, UNCOMP_FORMAT, GL_SLUMINANCE8, GL_LUMINANCE, 8, 0, 0, 0, 0, 0, 0, 8, 8, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, NORMALIZED_FIXED_POINT_FORMAT, ImageFormat::CODE_SL8, ImageFormat::COLOR_SPACE_SRGB);
-DEFINE_TEXTUREFORMAT_METHOD(SLA8, 2, UNCOMP_FORMAT, GL_SLUMINANCE8_ALPHA8, GL_LUMINANCE_ALPHA, 8, 8, 0, 0, 0, 0, 0, 16, 16, GL_UNSIGNED_BYTE, CLEAR_FORMAT, INT_FORMAT, ImageFormat::CODE_SLA8, ImageFormat::COLOR_SPACE_SRGB);
+DEFINE_TEXTUREFORMAT_METHOD(SLA8, 2, UNCOMP_FORMAT, GL_SLUMINANCE8_ALPHA8, GL_LUMINANCE_ALPHA, 8, 8, 0, 0, 0, 0, 0, 16, 16, GL_UNSIGNED_BYTE, CLEAR_FORMAT, NORMALIZED_FIXED_POINT_FORMAT, ImageFormat::CODE_SLA8, ImageFormat::COLOR_SPACE_SRGB);
-DEFINE_TEXTUREFORMAT_METHOD(SRGB_DXT1, 3, COMP_FORMAT, GL_COMPRESSED_SRGB_S3TC_DXT1_EXT, GL_RGB, 0, 0, 0, 0, 0, 0, 0, 64, 64, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INT_FORMAT, ImageFormat::CODE_SRGB_DXT1, ImageFormat::COLOR_SPACE_SRGB);
+DEFINE_TEXTUREFORMAT_METHOD(SRGB_DXT1, 3, COMP_FORMAT, GL_COMPRESSED_SRGB_S3TC_DXT1_EXT, GL_RGB, 0, 0, 0, 0, 0, 0, 0, 64, 64, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, OTHER, ImageFormat::CODE_SRGB_DXT1, ImageFormat::COLOR_SPACE_SRGB);
-DEFINE_TEXTUREFORMAT_METHOD(SRGBA_DXT1, 4, COMP_FORMAT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, GL_RGBA, 0, 0, 0, 0, 0, 0, 0, 64, 64, GL_UNSIGNED_BYTE, CLEAR_FORMAT, INT_FORMAT, ImageFormat::CODE_SRGBA_DXT1, ImageFormat::COLOR_SPACE_SRGB);
+DEFINE_TEXTUREFORMAT_METHOD(SRGBA_DXT1, 4, COMP_FORMAT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, GL_RGBA, 0, 0, 0, 0, 0, 0, 0, 64, 64, GL_UNSIGNED_BYTE, CLEAR_FORMAT, OTHER, ImageFormat::CODE_SRGBA_DXT1, ImageFormat::COLOR_SPACE_SRGB);
-DEFINE_TEXTUREFORMAT_METHOD(SRGBA_DXT3, 4, COMP_FORMAT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, GL_RGBA, 0, 0, 0, 0, 0, 0, 0, 128, 128, GL_UNSIGNED_BYTE, CLEAR_FORMAT, INT_FORMAT, ImageFormat::CODE_SRGBA_DXT3, ImageFormat::COLOR_SPACE_SRGB);
+DEFINE_TEXTUREFORMAT_METHOD(SRGBA_DXT3, 4, COMP_FORMAT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, GL_RGBA, 0, 0, 0, 0, 0, 0, 0, 128, 128, GL_UNSIGNED_BYTE, CLEAR_FORMAT, OTHER, ImageFormat::CODE_SRGBA_DXT3, ImageFormat::COLOR_SPACE_SRGB);
-DEFINE_TEXTUREFORMAT_METHOD(SRGBA_DXT5, 4, COMP_FORMAT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, GL_RGBA, 0, 0, 0, 0, 0, 0, 0, 128, 128, GL_UNSIGNED_BYTE, CLEAR_FORMAT, INT_FORMAT, ImageFormat::CODE_SRGBA_DXT5, ImageFormat::COLOR_SPACE_SRGB);
+DEFINE_TEXTUREFORMAT_METHOD(SRGBA_DXT5, 4, COMP_FORMAT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, GL_RGBA, 0, 0, 0, 0, 0, 0, 0, 128, 128, GL_UNSIGNED_BYTE, CLEAR_FORMAT, OTHER, ImageFormat::CODE_SRGBA_DXT5, ImageFormat::COLOR_SPACE_SRGB);
-DEFINE_TEXTUREFORMAT_METHOD(DEPTH16, 1, UNCOMP_FORMAT, GL_DEPTH_COMPONENT16_ARB, GL_DEPTH_COMPONENT, 0, 0, 0, 0, 0, 16, 0, 16, 16, GL_UNSIGNED_SHORT, CLEAR_FORMAT, INT_FORMAT, ImageFormat::CODE_DEPTH16, ImageFormat::COLOR_SPACE_NONE);
+DEFINE_TEXTUREFORMAT_METHOD(DEPTH16, 1, UNCOMP_FORMAT, GL_DEPTH_COMPONENT16_ARB, GL_DEPTH_COMPONENT, 0, 0, 0, 0, 0, 16, 0, 16, 16, GL_UNSIGNED_SHORT, CLEAR_FORMAT, NORMALIZED_FIXED_POINT_FORMAT, ImageFormat::CODE_DEPTH16, ImageFormat::COLOR_SPACE_NONE);
-DEFINE_TEXTUREFORMAT_METHOD(DEPTH24, 1, UNCOMP_FORMAT, GL_DEPTH_COMPONENT24_ARB, GL_DEPTH_COMPONENT, 0, 0, 0, 0, 0, 24, 0, 32, 24, GL_UNSIGNED_INT, CLEAR_FORMAT, INT_FORMAT, ImageFormat::CODE_DEPTH24, ImageFormat::COLOR_SPACE_NONE);
+DEFINE_TEXTUREFORMAT_METHOD(DEPTH24, 1, UNCOMP_FORMAT, GL_DEPTH_COMPONENT24_ARB, GL_DEPTH_COMPONENT, 0, 0, 0, 0, 0, 24, 0, 32, 24, GL_UNSIGNED_INT, CLEAR_FORMAT, NORMALIZED_FIXED_POINT_FORMAT, ImageFormat::CODE_DEPTH24, ImageFormat::COLOR_SPACE_NONE);
-DEFINE_TEXTUREFORMAT_METHOD(DEPTH32, 1, UNCOMP_FORMAT, GL_DEPTH_COMPONENT32_ARB, GL_DEPTH_COMPONENT, 0, 0, 0, 0, 0, 32, 0, 32, 32, GL_UNSIGNED_INT, CLEAR_FORMAT, INT_FORMAT, ImageFormat::CODE_DEPTH32, ImageFormat::COLOR_SPACE_NONE);
+DEFINE_TEXTUREFORMAT_METHOD(DEPTH32, 1, UNCOMP_FORMAT, GL_DEPTH_COMPONENT32_ARB, GL_DEPTH_COMPONENT, 0, 0, 0, 0, 0, 32, 0, 32, 32, GL_UNSIGNED_INT, CLEAR_FORMAT, NORMALIZED_FIXED_POINT_FORMAT, ImageFormat::CODE_DEPTH32, ImageFormat::COLOR_SPACE_NONE);
-DEFINE_TEXTUREFORMAT_METHOD(DEPTH32F, 1, UNCOMP_FORMAT, GL_DEPTH_COMPONENT32_ARB, GL_DEPTH_COMPONENT, 0, 0, 0, 0, 0, 32, 0, 32, 32, GL_FLOAT, CLEAR_FORMAT, FLOAT_FORMAT, ImageFormat::CODE_DEPTH32F, ImageFormat::COLOR_SPACE_NONE);
+DEFINE_TEXTUREFORMAT_METHOD(DEPTH32F, 1, UNCOMP_FORMAT, GL_DEPTH_COMPONENT32_ARB, GL_DEPTH_COMPONENT, 0, 0, 0, 0, 0, 32, 0, 32, 32, GL_FLOAT, CLEAR_FORMAT, FLOATING_POINT_FORMAT, ImageFormat::CODE_DEPTH32F, ImageFormat::COLOR_SPACE_NONE);
// These formats are for use with Renderbuffers only!
-DEFINE_TEXTUREFORMAT_METHOD(STENCIL1, 1, UNCOMP_FORMAT, GL_STENCIL_INDEX1_EXT, GL_STENCIL_INDEX, 0, 0, 0, 0, 0, 0, 1, 1, 1, GL_UNSIGNED_BYTE, CLEAR_FORMAT, INT_FORMAT, ImageFormat::CODE_STENCIL1, ImageFormat::COLOR_SPACE_NONE);
+DEFINE_TEXTUREFORMAT_METHOD(STENCIL1, 1, UNCOMP_FORMAT, GL_STENCIL_INDEX1_EXT, GL_STENCIL_INDEX, 0, 0, 0, 0, 0, 0, 1, 1, 1, GL_UNSIGNED_BYTE, CLEAR_FORMAT, NORMALIZED_FIXED_POINT_FORMAT, ImageFormat::CODE_STENCIL1, ImageFormat::COLOR_SPACE_NONE);
+
+DEFINE_TEXTUREFORMAT_METHOD(STENCIL4, 1, UNCOMP_FORMAT, GL_STENCIL_INDEX4_EXT, GL_STENCIL_INDEX, 0, 0, 0, 0, 0, 0, 4, 4, 4, GL_UNSIGNED_BYTE, CLEAR_FORMAT, NORMALIZED_FIXED_POINT_FORMAT, ImageFormat::CODE_STENCIL4, ImageFormat::COLOR_SPACE_NONE);
-DEFINE_TEXTUREFORMAT_METHOD(STENCIL4, 1, UNCOMP_FORMAT, GL_STENCIL_INDEX4_EXT, GL_STENCIL_INDEX, 0, 0, 0, 0, 0, 0, 4, 4, 4, GL_UNSIGNED_BYTE, CLEAR_FORMAT, INT_FORMAT, ImageFormat::CODE_STENCIL4, ImageFormat::COLOR_SPACE_NONE);
+DEFINE_TEXTUREFORMAT_METHOD(STENCIL8, 1, UNCOMP_FORMAT, GL_STENCIL_INDEX8_EXT, GL_STENCIL_INDEX, 0, 0, 0, 0, 0, 0, 8, 8, 8, GL_UNSIGNED_BYTE, CLEAR_FORMAT, NORMALIZED_FIXED_POINT_FORMAT, ImageFormat::CODE_STENCIL8, ImageFormat::COLOR_SPACE_NONE);
-DEFINE_TEXTUREFORMAT_METHOD(STENCIL8, 1, UNCOMP_FORMAT, GL_STENCIL_INDEX8_EXT, GL_STENCIL_INDEX, 0, 0, 0, 0, 0, 0, 8, 8, 8, GL_UNSIGNED_BYTE, CLEAR_FORMAT, INT_FORMAT, ImageFormat::CODE_STENCIL8, ImageFormat::COLOR_SPACE_NONE);
+DEFINE_TEXTUREFORMAT_METHOD(STENCIL16, 1, UNCOMP_FORMAT, GL_STENCIL_INDEX16_EXT, GL_STENCIL_INDEX, 0, 0, 0, 0, 0, 0, 16, 16, 16, GL_UNSIGNED_SHORT, CLEAR_FORMAT, NORMALIZED_FIXED_POINT_FORMAT, ImageFormat::CODE_STENCIL16, ImageFormat::COLOR_SPACE_NONE);
-DEFINE_TEXTUREFORMAT_METHOD(STENCIL16, 1, UNCOMP_FORMAT, GL_STENCIL_INDEX16_EXT, GL_STENCIL_INDEX, 0, 0, 0, 0, 0, 0, 16, 16, 16, GL_UNSIGNED_SHORT, CLEAR_FORMAT, INT_FORMAT, ImageFormat::CODE_STENCIL16, ImageFormat::COLOR_SPACE_NONE);
+DEFINE_TEXTUREFORMAT_METHOD(DEPTH24_STENCIL8, 2, UNCOMP_FORMAT, GL_DEPTH24_STENCIL8_EXT, GL_DEPTH_STENCIL_EXT,0, 0, 0, 0, 0, 24, 8, 32, 32, GL_UNSIGNED_INT_24_8, CLEAR_FORMAT, NORMALIZED_FIXED_POINT_FORMAT, ImageFormat::CODE_DEPTH24_STENCIL8, ImageFormat::COLOR_SPACE_NONE);
-DEFINE_TEXTUREFORMAT_METHOD(DEPTH24_STENCIL8, 2, UNCOMP_FORMAT, GL_DEPTH24_STENCIL8_EXT, GL_DEPTH_STENCIL_EXT,0, 0, 0, 0, 0, 24, 8, 32, 32, GL_UNSIGNED_INT, CLEAR_FORMAT, INT_FORMAT, ImageFormat::CODE_DEPTH24_STENCIL8, ImageFormat::COLOR_SPACE_NONE);
-DEFINE_TEXTUREFORMAT_METHOD(YUV420_PLANAR, 3, UNCOMP_FORMAT, GL_NONE, GL_NONE, 0, 0, 0, 0, 0, 0, 0, 12, 12, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INT_FORMAT, ImageFormat::CODE_YUV420_PLANAR, ImageFormat::COLOR_SPACE_YUV);
-DEFINE_TEXTUREFORMAT_METHOD(YUV422, 3, UNCOMP_FORMAT, GL_NONE, GL_NONE, 0, 0, 0, 0, 0, 0, 0, 16, 16, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INT_FORMAT, ImageFormat::CODE_YUV422, ImageFormat::COLOR_SPACE_YUV);
-DEFINE_TEXTUREFORMAT_METHOD(YUV444, 3, UNCOMP_FORMAT, GL_NONE, GL_NONE, 0, 0, 0, 0, 0, 0, 0, 24, 24, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INT_FORMAT, ImageFormat::CODE_YUV444, ImageFormat::COLOR_SPACE_YUV);
+// TODO: Find out if these are acutally NFP, not integer, formats.
+DEFINE_TEXTUREFORMAT_METHOD(YUV420_PLANAR, 3, UNCOMP_FORMAT, GL_NONE, GL_NONE, 0, 0, 0, 0, 0, 0, 0, 12, 12, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, NORMALIZED_FIXED_POINT_FORMAT, ImageFormat::CODE_YUV420_PLANAR, ImageFormat::COLOR_SPACE_YUV);
+DEFINE_TEXTUREFORMAT_METHOD(YUV422, 3, UNCOMP_FORMAT, GL_NONE, GL_NONE, 0, 0, 0, 0, 0, 0, 0, 16, 16, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, NORMALIZED_FIXED_POINT_FORMAT, ImageFormat::CODE_YUV422, ImageFormat::COLOR_SPACE_YUV);
+DEFINE_TEXTUREFORMAT_METHOD(YUV444, 3, UNCOMP_FORMAT, GL_NONE, GL_NONE, 0, 0, 0, 0, 0, 0, 0, 24, 24, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, NORMALIZED_FIXED_POINT_FORMAT, ImageFormat::CODE_YUV444, ImageFormat::COLOR_SPACE_YUV);
}
diff --git a/dep/g3dlite/source/ImageFormat_convert.cpp b/dep/g3dlite/source/ImageFormat_convert.cpp
index ecefe6319c7..69b9c71aeca 100644
--- a/dep/g3dlite/source/ImageFormat_convert.cpp
+++ b/dep/g3dlite/source/ImageFormat_convert.cpp
@@ -1,7 +1,7 @@
#include "G3D/ImageFormat.h"
-#include "G3D/Color1uint8.h"
-#include "G3D/Color3uint8.h"
-#include "G3D/Color4uint8.h"
+#include "G3D/Color1unorm8.h"
+#include "G3D/Color3unorm8.h"
+#include "G3D/Color4unorm8.h"
#include "G3D/Color1.h"
#include "G3D/Color3.h"
#include "G3D/Color4.h"
@@ -212,8 +212,8 @@ bool ImageFormat::convert(const Array<const void*>& srcBytes, int srcWidth, int
static void l8_to_rgb8(const Array<const void*>& srcBytes, int srcWidth, int srcHeight, const ImageFormat* srcFormat, int srcRowPadBits, const Array<void*>& dstBytes, const ImageFormat* dstFormat, int dstRowPadBits, bool invertY, ImageFormat::BayerAlgorithm bayerAlg) {
(void)bayerAlg;
(void)dstRowPadBits;
- uint8* dst = static_cast<uint8*>(dstBytes[0]);
- const uint8* src = static_cast<const uint8*>(srcBytes[0]);
+ unorm8* dst = static_cast<unorm8*>(dstBytes[0]);
+ const unorm8* src = static_cast<const unorm8*>(srcBytes[0]);
for (int y = 0; y < srcHeight; ++y) {
for (int x = 0; x < srcWidth; ++x) {
int i = (invertY) ? ((srcHeight-1-y) * srcWidth +x) : (y * srcWidth + x);
@@ -230,7 +230,7 @@ static void l8_to_rgb8(const Array<const void*>& srcBytes, int srcWidth, int src
static void l32f_to_rgb8(const Array<const void*>& srcBytes, int srcWidth, int srcHeight, const ImageFormat* srcFormat, int srcRowPadBits, const Array<void*>& dstBytes, const ImageFormat* dstFormat, int dstRowPadBits, bool invertY, ImageFormat::BayerAlgorithm bayerAlg) {
int srcIndex = 0;
int dstByteOffset = 0;
- uint8* dst = static_cast<uint8*>(dstBytes[0]);
+ unorm8* dst = static_cast<unorm8*>(dstBytes[0]);
const float* src = static_cast<const float*>(srcBytes[0]);
for (int y = 0; y < srcHeight; ++y) {
@@ -239,19 +239,18 @@ static void l32f_to_rgb8(const Array<const void*>& srcBytes, int srcWidth, int s
}
for (int x = 0; x < srcWidth; ++x, ++srcIndex, dstByteOffset += 3) {
- Color3uint8& d = *reinterpret_cast<Color3uint8*>(dst + dstByteOffset);
- float s = src[srcIndex];
-
- uint8 c = iMin(255, iFloor(s * 256));
- d = Color3uint8(c, c, c);
+ Color3unorm8& d = *reinterpret_cast<Color3unorm8*>(dst + dstByteOffset);
+ const float s = src[srcIndex];
+ const unorm8 c(s);
+ d = Color3unorm8(c, c, c);
}
}
}
// RGB8 ->
static void rgb8_to_rgba8(const Array<const void*>& srcBytes, int srcWidth, int srcHeight, const ImageFormat* srcFormat, int srcRowPadBits, const Array<void*>& dstBytes, const ImageFormat* dstFormat, int dstRowPadBits, bool invertY, ImageFormat::BayerAlgorithm bayerAlg) {
- uint8* dst = static_cast<uint8*>(dstBytes[0]);
- const uint8* src = static_cast<const uint8*>(srcBytes[0]);
+ unorm8* dst = static_cast<unorm8*>(dstBytes[0]);
+ const unorm8* src = static_cast<const unorm8*>(srcBytes[0]);
for (int y = 0; y < srcHeight; ++y) {
for (int x = 0; x < srcWidth; ++x) {
int i = (invertY) ? ((srcHeight-1-y) * srcWidth +x) : (y * srcWidth + x);
@@ -261,14 +260,14 @@ static void rgb8_to_rgba8(const Array<const void*>& srcBytes, int srcWidth, int
dst[i4 + 0] = src[i3 + 0];
dst[i4 + 1] = src[i3 + 1];
dst[i4 + 2] = src[i3 + 2];
- dst[i4 + 3] = 255;
+ dst[i4 + 3] = unorm8::one();
}
}
}
static void rgb8_to_bgr8(const Array<const void*>& srcBytes, int srcWidth, int srcHeight, const ImageFormat* srcFormat, int srcRowPadBits, const Array<void*>& dstBytes, const ImageFormat* dstFormat, int dstRowPadBits, bool invertY, ImageFormat::BayerAlgorithm bayerAlg) {
- uint8* dst = static_cast<uint8*>(dstBytes[0]);
- const uint8* src = static_cast<const uint8*>(srcBytes[0]);
+ unorm8* dst = static_cast<unorm8*>(dstBytes[0]);
+ const unorm8* src = static_cast<const unorm8*>(srcBytes[0]);
for (int y = 0; y < srcHeight; ++y) {
for (int x = 0; x < srcWidth; ++x) {
int i = (invertY) ? ((srcHeight-1-y) * srcWidth +x) : (y * srcWidth + x);
@@ -287,14 +286,14 @@ static void rgb8_to_rgba32f(const Array<const void*>& srcBytes, int srcWidth, in
int srcByteOffset = 0;
int srcRowPadBytes = srcRowPadBits / 8;
Color4* dst = static_cast<Color4*>(dstBytes[0]);
- const uint8* src = static_cast<const uint8*>(srcBytes[0]);
+ const unorm8* src = static_cast<const unorm8*>(srcBytes[0]);
for (int y = 0; y < srcHeight; ++y) {
if (invertY) {
dstIndex = srcWidth * (srcHeight - 1 - y);
}
for (int x = 0; x < srcWidth; ++x, ++dstIndex, srcByteOffset += 3) {
- const Color3uint8& s = *reinterpret_cast<const Color3uint8*>(src + srcByteOffset);
+ const Color3unorm8& s = *reinterpret_cast<const Color3unorm8*>(src + srcByteOffset);
dst[dstIndex] = Color4(Color3(s), 1.0f);
}
srcByteOffset += srcRowPadBytes;
@@ -303,8 +302,8 @@ static void rgb8_to_rgba32f(const Array<const void*>& srcBytes, int srcWidth, in
// BGR8 ->
static void bgr8_to_rgb8(const Array<const void*>& srcBytes, int srcWidth, int srcHeight, const ImageFormat* srcFormat, int srcRowPadBits, const Array<void*>& dstBytes, const ImageFormat* dstFormat, int dstRowPadBits, bool invertY, ImageFormat::BayerAlgorithm bayerAlg) {
- uint8* dst = static_cast<uint8*>(dstBytes[0]);
- const uint8* src = static_cast<const uint8*>(srcBytes[0]);
+ unorm8* dst = static_cast<unorm8*>(dstBytes[0]);
+ const unorm8* src = static_cast<const unorm8*>(srcBytes[0]);
for (int y = 0; y < srcHeight; ++y) {
for (int x = 0; x < srcWidth; ++x) {
int i = (invertY) ? ((srcHeight-1-y) * srcWidth +x) : (y * srcWidth + x);
@@ -317,8 +316,8 @@ static void bgr8_to_rgb8(const Array<const void*>& srcBytes, int srcWidth, int s
}
static void bgr8_to_rgba8(const Array<const void*>& srcBytes, int srcWidth, int srcHeight, const ImageFormat* srcFormat, int srcRowPadBits, const Array<void*>& dstBytes, const ImageFormat* dstFormat, int dstRowPadBits, bool invertY, ImageFormat::BayerAlgorithm bayerAlg) {
- uint8* dst = static_cast<uint8*>(dstBytes[0]);
- const uint8* src = static_cast<const uint8*>(srcBytes[0]);
+ unorm8* dst = static_cast<unorm8*>(dstBytes[0]);
+ const unorm8* src = static_cast<const unorm8*>(srcBytes[0]);
for (int y = 0; y < srcHeight; ++y) {
for (int x = 0; x < srcWidth; ++x) {
int i = (invertY) ? ((srcHeight-1-y) * srcWidth +x) : (y * srcWidth + x);
@@ -328,7 +327,7 @@ static void bgr8_to_rgba8(const Array<const void*>& srcBytes, int srcWidth, int
dst[i4 + 0] = src[i3 + 2];
dst[i4 + 1] = src[i3 + 1];
dst[i4 + 2] = src[i3 + 0];
- dst[i4 + 3] = 255;
+ dst[i4 + 3] = unorm8::one();
}
}
}
@@ -340,7 +339,7 @@ static void bgr8_to_rgba32f(const Array<const void*>& srcBytes, int srcWidth, in
int srcByteOffset = 0;
int srcRowPadBytes = srcRowPadBits / 8;
Color4* dst = static_cast<Color4*>(dstBytes[0]);
- const uint8* src = static_cast<const uint8*>(srcBytes[0]);
+ const unorm8* src = static_cast<const unorm8*>(srcBytes[0]);
for (int y = 0; y < srcHeight; ++y) {
if (invertY) {
@@ -348,7 +347,7 @@ static void bgr8_to_rgba32f(const Array<const void*>& srcBytes, int srcWidth, in
}
for (int x = 0; x < srcWidth; ++x, ++dstIndex, srcByteOffset += 3) {
- const Color3uint8& s = *reinterpret_cast<const Color3uint8*>(src + srcByteOffset);
+ const Color3unorm8& s = *reinterpret_cast<const Color3unorm8*>(src + srcByteOffset);
dst[dstIndex] = Color4(Color3(s).bgr(), 1.0f);
}
srcByteOffset += srcRowPadBytes;
@@ -357,8 +356,8 @@ static void bgr8_to_rgba32f(const Array<const void*>& srcBytes, int srcWidth, in
// RGBA8 ->
static void rgba8_to_rgb8(const Array<const void*>& srcBytes, int srcWidth, int srcHeight, const ImageFormat* srcFormat, int srcRowPadBits, const Array<void*>& dstBytes, const ImageFormat* dstFormat, int dstRowPadBits, bool invertY, ImageFormat::BayerAlgorithm bayerAlg) {
- uint8* dst = static_cast<uint8*>(dstBytes[0]);
- const uint8* src = static_cast<const uint8*>(srcBytes[0]);
+ unorm8* dst = static_cast<unorm8*>(dstBytes[0]);
+ const unorm8* src = static_cast<const unorm8*>(srcBytes[0]);
for (int y = 0; y < srcHeight; ++y) {
for (int x = 0; x < srcWidth; ++x) {
int i = (invertY) ? ((srcHeight-1-y) * srcWidth +x) : (y * srcWidth + x);
@@ -373,8 +372,8 @@ static void rgba8_to_rgb8(const Array<const void*>& srcBytes, int srcWidth, int
}
static void rgba8_to_bgr8(const Array<const void*>& srcBytes, int srcWidth, int srcHeight, const ImageFormat* srcFormat, int srcRowPadBits, const Array<void*>& dstBytes, const ImageFormat* dstFormat, int dstRowPadBits, bool invertY, ImageFormat::BayerAlgorithm bayerAlg) {
- uint8* dst = static_cast<uint8*>(dstBytes[0]);
- const uint8* src = static_cast<const uint8*>(srcBytes[0]);
+ unorm8* dst = static_cast<unorm8*>(dstBytes[0]);
+ const unorm8* src = static_cast<const unorm8*>(srcBytes[0]);
for (int y = 0; y < srcHeight; ++y) {
for (int x = 0; x < srcWidth; ++x) {
int i = (invertY) ? ((srcHeight-1-y) * srcWidth +x) : (y * srcWidth + x);
@@ -395,7 +394,7 @@ static void rgba8_to_rgba32f(const Array<const void*>& srcBytes, int srcWidth, i
int srcByteOffset = 0;
int srcRowPadBytes = srcRowPadBits / 8;
Color4* dst = static_cast<Color4*>(dstBytes[0]);
- const uint8* src = static_cast<const uint8*>(srcBytes[0]);
+ const unorm8* src = static_cast<const unorm8*>(srcBytes[0]);
for (int y = 0; y < srcHeight; ++y) {
if (invertY) {
@@ -403,7 +402,7 @@ static void rgba8_to_rgba32f(const Array<const void*>& srcBytes, int srcWidth, i
}
for (int x = 0; x < srcWidth; ++x, ++dstIndex, srcByteOffset += 4) {
- const Color4uint8& s = *reinterpret_cast<const Color4uint8*>(src + srcByteOffset);
+ const Color4unorm8& s = *reinterpret_cast<const Color4unorm8*>(src + srcByteOffset);
dst[dstIndex] = Color4(s);
}
srcByteOffset += srcRowPadBytes;
@@ -418,7 +417,7 @@ static void rgb32f_to_rgba32f(const Array<const void*>& srcBytes, int srcWidth,
int srcByteOffset = 0;
int srcRowPadBytes = srcRowPadBits / 8;
Color4* dst = static_cast<Color4*>(dstBytes[0]);
- const uint8* src = static_cast<const uint8*>(srcBytes[0]);
+ const unorm8* src = static_cast<const unorm8*>(srcBytes[0]);
for (int y = 0; y < srcHeight; ++y) {
if (invertY) {
@@ -440,7 +439,7 @@ static void rgba32f_to_rgb8(const Array<const void*>& srcBytes, int srcWidth, in
int srcIndex = 0;
int dstByteOffset = 0;
int dstRowPadBytes = dstRowPadBits / 8;
- uint8* dst = static_cast<uint8*>(dstBytes[0]);
+ unorm8* dst = static_cast<unorm8*>(dstBytes[0]);
const Color4* src = static_cast<const Color4*>(srcBytes[0]);
for (int y = 0; y < srcHeight; ++y) {
@@ -449,10 +448,10 @@ static void rgba32f_to_rgb8(const Array<const void*>& srcBytes, int srcWidth, in
}
for (int x = 0; x < srcWidth; ++x, ++srcIndex, dstByteOffset += 3) {
- Color3uint8& d = *reinterpret_cast<Color3uint8*>(dst + dstByteOffset);
+ Color3unorm8& d = *reinterpret_cast<Color3unorm8*>(dst + dstByteOffset);
const Color4& s = src[srcIndex];
- d = Color3uint8(s.rgb());
+ d = Color3unorm8(s.rgb());
}
dstByteOffset += dstRowPadBytes;
}
@@ -464,7 +463,7 @@ static void rgba32f_to_rgba8(const Array<const void*>& srcBytes, int srcWidth, i
int srcIndex = 0;
int dstByteOffset = 0;
int dstRowPadBytes = dstRowPadBits / 8;
- uint8* dst = static_cast<uint8*>(dstBytes[0]);
+ unorm8* dst = static_cast<unorm8*>(dstBytes[0]);
const Color4* src = static_cast<const Color4*>(srcBytes[0]);
for (int y = 0; y < srcHeight; ++y) {
@@ -472,10 +471,10 @@ static void rgba32f_to_rgba8(const Array<const void*>& srcBytes, int srcWidth, i
srcIndex = srcWidth * (srcHeight - 1 - y);
}
for (int x = 0; x < srcWidth; ++x, ++srcIndex, dstByteOffset += 4) {
- Color4uint8& d = *reinterpret_cast<Color4uint8*>(dst + dstByteOffset);
+ Color4unorm8& d = *reinterpret_cast<Color4unorm8*>(dst + dstByteOffset);
const Color4& s = src[srcIndex];
- d = Color4uint8(s);
+ d = Color4unorm8(s);
}
dstByteOffset += dstRowPadBytes;
}
@@ -487,7 +486,7 @@ static void rgba32f_to_bgr8(const Array<const void*>& srcBytes, int srcWidth, in
int srcIndex = 0;
int dstByteOffset = 0;
int dstRowPadBytes = dstRowPadBits / 8;
- uint8* dst = static_cast<uint8*>(dstBytes[0]);
+ unorm8* dst = static_cast<unorm8*>(dstBytes[0]);
const Color4* src = static_cast<const Color4*>(srcBytes[0]);
for (int y = 0; y < srcHeight; ++y) {
@@ -496,10 +495,10 @@ static void rgba32f_to_bgr8(const Array<const void*>& srcBytes, int srcWidth, in
}
for (int x = 0; x < srcWidth; ++x, ++srcIndex, dstByteOffset += 3) {
- Color3uint8& d = *reinterpret_cast<Color3uint8*>(dst + dstByteOffset);
+ Color3unorm8& d = *reinterpret_cast<Color3unorm8*>(dst + dstByteOffset);
const Color4& s = src[srcIndex];
- d = Color3uint8(s.rgb()).bgr();
+ d = Color3unorm8(s.rgb()).bgr();
}
dstByteOffset += dstRowPadBytes;
}
@@ -511,7 +510,7 @@ static void rgba32f_to_rgb32f(const Array<const void*>& srcBytes, int srcWidth,
int srcIndex = 0;
int dstByteOffset = 0;
int dstRowPadBytes = dstRowPadBits / 8;
- uint8* dst = static_cast<uint8*>(dstBytes[0]);
+ unorm8* dst = static_cast<unorm8*>(dstBytes[0]);
const Color4* src = static_cast<const Color4*>(srcBytes[0]);
for (int y = 0; y < srcHeight; ++y) {
@@ -520,7 +519,7 @@ static void rgba32f_to_rgb32f(const Array<const void*>& srcBytes, int srcWidth,
}
for (int x = 0; x < srcWidth; ++x, ++srcIndex, dstByteOffset += 3 * sizeof(float)) {
Color3& d = *reinterpret_cast<Color3*>(dst + dstByteOffset);
- const Color4& s = src[srcIndex];
+ const Color4& s = src[srcIndex];
d = s.rgb();
}
dstByteOffset += dstRowPadBytes;
@@ -545,19 +544,19 @@ static uint32 blendPixels(uint32 pixel1, uint32 pixel2) {
return ((rb & rbMask) | (ag & agMask));
}
-#define PIXEL_RGB8_TO_YUV_Y(r, g, b) static_cast<uint8>(iClamp(((66 * r + 129 * g + 25 * b + 128) >> 8) + 16, 0, 255))
-#define PIXEL_RGB8_TO_YUV_U(r, g, b) static_cast<uint8>(iClamp(((-38 * r - 74 * g + 112 * b + 128) >> 8) + 128, 0, 255))
-#define PIXEL_RGB8_TO_YUV_V(r, g, b) static_cast<uint8>(iClamp(((112 * r - 94 * g - 18 * b + 128) >> 8) + 128, 0, 255))
+#define PIXEL_RGB8_TO_YUV_Y(r, g, b) unorm8::fromBits(iClamp(((66 * r.bits() + 129 * g.bits() + 25 * b.bits() + 128) >> 8) + 16, 0, 255))
+#define PIXEL_RGB8_TO_YUV_U(r, g, b) unorm8::fromBits(iClamp(((-38 * r.bits() - 74 * g.bits() + 112 * b.bits() + 128) >> 8) + 128, 0, 255))
+#define PIXEL_RGB8_TO_YUV_V(r, g, b) unorm8::fromBits(iClamp(((112 * r.bits() - 94 * g.bits() - 18 * b.bits() + 128) >> 8) + 128, 0, 255))
static void rgb8_to_yuv420p(const Array<const void*>& srcBytes, int srcWidth, int srcHeight, const ImageFormat* srcFormat, int srcRowPadBits, const Array<void*>& dstBytes, const ImageFormat* dstFormat, int dstRowPadBits, bool invertY, ImageFormat::BayerAlgorithm bayerAlg) {
debugAssertM(srcRowPadBits == 0, "Source row padding must be 0 for this format");
debugAssertM((srcWidth % 2 == 0) && (srcHeight % 2 == 0), "Source width and height must be a multiple of two");
- const Color3uint8* src = static_cast<const Color3uint8*>(srcBytes[0]);
+ const Color3unorm8* src = static_cast<const Color3unorm8*>(srcBytes[0]);
- uint8* dstY = static_cast<uint8*>(dstBytes[0]);
- uint8* dstU = static_cast<uint8*>(dstBytes[1]);
- uint8* dstV = static_cast<uint8*>(dstBytes[2]);
+ unorm8* dstY = static_cast<unorm8*>(dstBytes[0]);
+ unorm8* dstU = static_cast<unorm8*>(dstBytes[1]);
+ unorm8* dstV = static_cast<unorm8*>(dstBytes[2]);
for (int y = 0; y < srcHeight; y += 2) {
for (int x = 0; x < srcWidth; x += 2) {
@@ -578,7 +577,7 @@ static void rgb8_to_yuv420p(const Array<const void*>& srcBytes, int srcWidth, in
dstY[yIndex + 1] = PIXEL_RGB8_TO_YUV_Y(src[srcPixelOffset3].r, src[srcPixelOffset3].g, src[srcPixelOffset3].b);
uint32 blendedPixel = blendPixels(src[srcPixelOffset0].asUInt32(), src[srcPixelOffset2].asUInt32());
- Color3uint8 uvSrcColor = Color3uint8::fromARGB(blendedPixel);
+ Color3unorm8 uvSrcColor = Color3unorm8::fromARGB(blendedPixel);
int uvIndex = y / 2 * srcWidth / 2 + x / 2;
dstU[uvIndex] = PIXEL_RGB8_TO_YUV_U(uvSrcColor.r, uvSrcColor.g, uvSrcColor.b);
@@ -591,9 +590,9 @@ static void rgb8_to_yuv422(const Array<const void*>& srcBytes, int srcWidth, int
debugAssertM(srcRowPadBits == 0, "Source row padding must be 0 for this format");
debugAssertM((srcWidth % 2 == 0), "Source width must be a multiple of two");
- const Color3uint8* src = static_cast<const Color3uint8*>(srcBytes[0]);
+ const Color3unorm8* src = static_cast<const Color3unorm8*>(srcBytes[0]);
- uint8* dst = static_cast<uint8*>(dstBytes[0]);
+ unorm8* dst = static_cast<unorm8*>(dstBytes[0]);
for (int y = 0; y < srcHeight; ++y) {
for (int x = 0; x < srcWidth; x += 2) {
@@ -603,7 +602,7 @@ static void rgb8_to_yuv422(const Array<const void*>& srcBytes, int srcWidth, int
int dstIndex = srcIndex * 2;
uint32 blendedPixel = blendPixels(src[srcIndex].asUInt32(), src[srcIndex + 1].asUInt32());
- Color3uint8 uvSrcColor = Color3uint8::fromARGB(blendedPixel);
+ Color3unorm8 uvSrcColor = Color3unorm8::fromARGB(blendedPixel);
dst[dstIndex] = PIXEL_RGB8_TO_YUV_Y(src[srcIndex].r, src[srcIndex].g, src[srcIndex].b);
@@ -620,18 +619,18 @@ static void rgb8_to_yuv422(const Array<const void*>& srcBytes, int srcWidth, int
static void rgb8_to_yuv444(const Array<const void*>& srcBytes, int srcWidth, int srcHeight, const ImageFormat* srcFormat, int srcRowPadBits, const Array<void*>& dstBytes, const ImageFormat* dstFormat, int dstRowPadBits, bool invertY, ImageFormat::BayerAlgorithm bayerAlg) {
debugAssertM(srcRowPadBits == 0, "Source row padding must be 0 for this format");
- const Color3uint8* src = static_cast<const Color3uint8*>(srcBytes[0]);
+ const Color3unorm8* src = static_cast<const Color3unorm8*>(srcBytes[0]);
- Color3uint8* dst = static_cast<Color3uint8*>(dstBytes[0]);
+ Color3unorm8* dst = static_cast<Color3unorm8*>(dstBytes[0]);
for (int y = 0; y < srcHeight; ++y) {
for (int x = 0; x < srcWidth; ++x) {
// convert 1-pixels at a time
int index = y * srcWidth + x;
- uint8 y = PIXEL_RGB8_TO_YUV_Y(src[index].r, src[index].g, src[index].b);
- uint8 u = PIXEL_RGB8_TO_YUV_U(src[index].r, src[index].g, src[index].b);
- uint8 v = PIXEL_RGB8_TO_YUV_V(src[index].r, src[index].g, src[index].b);
+ unorm8 y = PIXEL_RGB8_TO_YUV_Y(src[index].r, src[index].g, src[index].b);
+ unorm8 u = PIXEL_RGB8_TO_YUV_U(src[index].r, src[index].g, src[index].b);
+ unorm8 v = PIXEL_RGB8_TO_YUV_V(src[index].r, src[index].g, src[index].b);
dst[index].r = y;
dst[index].g = u;
@@ -641,25 +640,25 @@ static void rgb8_to_yuv444(const Array<const void*>& srcBytes, int srcWidth, int
}
-#define PIXEL_YUV_TO_RGB8_R(y, u, v) static_cast<uint8>(iClamp((298 * (y - 16) + 409 * (v - 128) + 128) >> 8, 0, 255))
-#define PIXEL_YUV_TO_RGB8_G(y, u, v) static_cast<uint8>(iClamp((298 * (y - 16) - 100 * (u - 128) - 208 * (v - 128) + 128) >> 8, 0, 255))
-#define PIXEL_YUV_TO_RGB8_B(y, u, v) static_cast<uint8>(iClamp((298 * (y - 16) + 516 * (u - 128) + 128) >> 8, 0, 255))
+#define PIXEL_YUV_TO_RGB8_R(y, u, v) unorm8::fromBits(iClamp((298 * (y.bits() - 16) + 409 * (v.bits() - 128) + 128) >> 8, 0, 255))
+#define PIXEL_YUV_TO_RGB8_G(y, u, v) unorm8::fromBits(iClamp((298 * (y.bits() - 16) - 100 * (u.bits() - 128) - 208 * (v.bits() - 128) + 128) >> 8, 0, 255))
+#define PIXEL_YUV_TO_RGB8_B(y, u, v) unorm8::fromBits(iClamp((298 * (y.bits() - 16) + 516 * (u.bits() - 128) + 128) >> 8, 0, 255))
static void yuv420p_to_rgb8(const Array<const void*>& srcBytes, int srcWidth, int srcHeight, const ImageFormat* srcFormat, int srcRowPadBits, const Array<void*>& dstBytes, const ImageFormat* dstFormat, int dstRowPadBits, bool invertY, ImageFormat::BayerAlgorithm bayerAlg) {
debugAssertM(srcRowPadBits == 0, "Source row padding must be 0 for this format");
debugAssertM((srcWidth % 2 == 0) && (srcHeight % 2 == 0), "Source width and height must be a multiple of two");
- const uint8* srcY = static_cast<const uint8*>(srcBytes[0]);
- const uint8* srcU = static_cast<const uint8*>(srcBytes[1]);
- const uint8* srcV = static_cast<const uint8*>(srcBytes[2]);
+ const unorm8* srcY = static_cast<const unorm8*>(srcBytes[0]);
+ const unorm8* srcU = static_cast<const unorm8*>(srcBytes[1]);
+ const unorm8* srcV = static_cast<const unorm8*>(srcBytes[2]);
- Color3uint8* dst = static_cast<Color3uint8*>(dstBytes[0]);
+ Color3unorm8* dst = static_cast<Color3unorm8*>(dstBytes[0]);
for (int y = 0; y < srcHeight; ++y) {
for (int x = 0; x < srcWidth; x += 2) {
// convert to two rgb pixels in a row
- Color3uint8* rgb = &dst[y * srcWidth + x];
+ Color3unorm8* rgb = &dst[y * srcWidth + x];
int yOffset = y * srcWidth + x;
int uvOffset = y / 2 * srcWidth / 2 + x / 2;
@@ -680,21 +679,21 @@ static void yuv422_to_rgb8(const Array<const void*>& srcBytes, int srcWidth, int
debugAssertM(srcRowPadBits == 0, "Source row padding must be 0 for this format");
debugAssertM((srcWidth % 2 == 0), "Source width must be a multiple of two");
- const uint8* src = static_cast<const uint8*>(srcBytes[0]);
+ const unorm8* src = static_cast<const unorm8*>(srcBytes[0]);
- Color3uint8* dst = static_cast<Color3uint8*>(dstBytes[0]);
+ Color3unorm8* dst = static_cast<Color3unorm8*>(dstBytes[0]);
for (int y = 0; y < srcHeight; ++y) {
for (int x = 0; x < srcWidth; x += 2) {
// convert to two rgb pixels in a row
- Color3uint8* rgb = &dst[y * srcWidth + x];
+ Color3unorm8* rgb = &dst[y * srcWidth + x];
- int srcIndex = (y * srcWidth + x) * 2;
- uint8 y = src[srcIndex];
- uint8 u = src[srcIndex + 1];
- uint8 y2 = src[srcIndex + 2];
- uint8 v = src[srcIndex + 3];
+ const int srcIndex = (y * srcWidth + x) * 2;
+ const unorm8 y = src[srcIndex];
+ const unorm8 u = src[srcIndex + 1];
+ const unorm8 y2 = src[srcIndex + 2];
+ const unorm8 v = src[srcIndex + 3];
rgb->r = PIXEL_YUV_TO_RGB8_R(y, u, v);
rgb->g = PIXEL_YUV_TO_RGB8_G(y, u, v);
@@ -711,20 +710,21 @@ static void yuv422_to_rgb8(const Array<const void*>& srcBytes, int srcWidth, int
static void yuv444_to_rgb8(const Array<const void*>& srcBytes, int srcWidth, int srcHeight, const ImageFormat* srcFormat, int srcRowPadBits, const Array<void*>& dstBytes, const ImageFormat* dstFormat, int dstRowPadBits, bool invertY, ImageFormat::BayerAlgorithm bayerAlg) {
debugAssertM(srcRowPadBits == 0, "Source row padding must be 0 for this format");
- const Color3uint8* src = static_cast<const Color3uint8*>(srcBytes[0]);
+ const Color3unorm8* src = static_cast<const Color3unorm8*>(srcBytes[0]);
- Color3uint8* dst = static_cast<Color3uint8*>(dstBytes[0]);
+ Color3unorm8* dst = static_cast<Color3unorm8*>(dstBytes[0]);
for (int y = 0; y < srcHeight; ++y) {
for (int x = 0; x < srcWidth; ++x) {
// convert to one rgb pixels at a time
- int index = y * srcWidth + x;
- Color3uint8* rgb = &dst[index];
-
- rgb->r = PIXEL_YUV_TO_RGB8_R(src[index].r, src[index].g, src[index].b);
- rgb->g = PIXEL_YUV_TO_RGB8_G(src[index].r, src[index].g, src[index].b);
- rgb->b = PIXEL_YUV_TO_RGB8_B(src[index].r, src[index].g, src[index].b);
+ const int index = y * srcWidth + x;
+ const Color3unorm8 s = src[index];
+
+ Color3unorm8& rgb = dst[index];
+ rgb.r = PIXEL_YUV_TO_RGB8_R(s.r, s.g, s.b);
+ rgb.g = PIXEL_YUV_TO_RGB8_G(s.r, s.g, s.b);
+ rgb.b = PIXEL_YUV_TO_RGB8_B(s.r, s.g, s.b);
}
}
}
@@ -799,12 +799,12 @@ static const float R_BGB[5][5] =
/** Applies a 5x5 filter to monochrome image I (wrapping at the boundaries) */
-static uint8 applyFilter(const uint8* I,
- int x,
- int y,
- int w,
- int h,
- const float filter[5][5]) {
+static unorm8 applyFilter(const unorm8* I,
+ int x,
+ int y,
+ int w,
+ int h,
+ const float filter[5][5]) {
debugAssert(isEven(w));
debugAssert(isEven(h));
@@ -813,24 +813,24 @@ static uint8 applyFilter(const uint8* I,
float denom = 0.0f;
for (int dy = 0; dy < 5; ++dy) {
- int offset = ((y + dy + h - 2) % h) * w;
+ int offset = ((y + dy + h - 2) % h) * w;
- for (int dx = 0; dx < 5; ++dx) {
- float f = filter[dy][dx];
- sum += f * I[((x + dx + w - 2) % w) + offset];
- denom += f;
- }
+ for (int dx = 0; dx < 5; ++dx) {
+ float f = filter[dy][dx];
+ sum += f * (float)I[((x + dx + w - 2) % w) + offset];
+ denom += f;
+ }
}
- return (uint8)iClamp(iRound(sum / denom), 0, 255);
+ return unorm8(sum / denom);
}
/** Helper method for Bayer grbg and bggr --> rgb8 */
-static void swapRedAndBlue(int N, Color3uint8* out) {
+static void swapRedAndBlue(int N, Color3unorm8* out) {
for (int i = N - 1; i >= 0; --i) {
- uint8 tmp = out[i].r;
- out[i].r = out[i].b;
- out[i].b = tmp;
+ unorm8 tmp = out[i].r;
+ out[i].r = out[i].b;
+ out[i].b = tmp;
}
}
@@ -840,149 +840,149 @@ static void swapRedAndBlue(int N, Color3uint8* out) {
// rgb8 --> bayer helpers
// =====================================================================
static void rgb8_to_bayer_rggb8(const int w, const int h,
- const uint8* src, uint8* dst) {
- Color3uint8* srcColor = (Color3uint8*)src;
- Color1uint8* dstColor = (Color1uint8*)dst;
+ const unorm8* src, unorm8* dst) {
+ Color3unorm8* srcColor = (Color3unorm8*)src;
+ Color1unorm8* dstColor = (Color1unorm8*)dst;
// Top row pixels
for (int y = 0; y < h - 1; y += 2) {
- int offset = y * w;
+ int offset = y * w;
- // Top left pixels
- for(int x = 0; x < w - 1; x += 2) {
- dstColor[x + offset] = Color1(srcColor[x + offset].r);
- }
+ // Top left pixels
+ for(int x = 0; x < w - 1; x += 2) {
+ dstColor[x + offset] = Color1unorm8(srcColor[x + offset].r);
+ }
- // Top right pixels
- for(int x = 1; x < w - 1; x += 2) {
- dstColor[x + offset] = Color1(srcColor[x + offset].g);
- }
- }
+ // Top right pixels
+ for(int x = 1; x < w - 1; x += 2) {
+ dstColor[x + offset] = Color1unorm8(srcColor[x + offset].g);
+ }
+ }
- // Bottom row pixels
- for (int y = 1; y < h - 1; y += 2) {
- int offset = y * w;
+ // Bottom row pixels
+ for (int y = 1; y < h - 1; y += 2) {
+ int offset = y * w;
- // Bottom left pixels
- for (int x = 0; x < w - 1; x += 2) {
- dstColor[x + offset] = Color1(srcColor[x + offset].g);
- }
+ // Bottom left pixels
+ for (int x = 0; x < w - 1; x += 2) {
+ dstColor[x + offset] = Color1unorm8(srcColor[x + offset].g);
+ }
- // Bottom right pixels
- for (int x = 1; x < w - 1; x += 2) {
- dstColor[x + offset] = Color1(srcColor[x + offset].b);
- }
+ // Bottom right pixels
+ for (int x = 1; x < w - 1; x += 2) {
+ dstColor[x + offset] = Color1unorm8(srcColor[x + offset].b);
+ }
}
}
static void rgb8_to_bayer_grbg8(const int w, const int h,
- const uint8* src, uint8* dst) {
- Color3uint8* srcColor = (Color3uint8*)src;
- Color1uint8* dstColor = (Color1uint8*)dst;
+ const unorm8* src, unorm8* dst) {
+ Color3unorm8* srcColor = (Color3unorm8*)src;
+ Color1unorm8* dstColor = (Color1unorm8*)dst;
// Top row pixels
for (int y = 0; y < h - 1; y += 2) {
- int offset = y * w;
+ int offset = y * w;
- // Top left pixels
- for (int x = 0; x < w - 1; x += 2) {
- dstColor[x + offset] = Color1(srcColor[x + offset].g);
- }
+ // Top left pixels
+ for (int x = 0; x < w - 1; x += 2) {
+ dstColor[x + offset] = Color1unorm8(srcColor[x + offset].g);
+ }
- // Top right pixels
- for (int x = 1; x < w - 1; x += 2) {
- dstColor[x + offset] = Color1(srcColor[x + offset].r);
- }
+ // Top right pixels
+ for (int x = 1; x < w - 1; x += 2) {
+ dstColor[x + offset] = Color1unorm8(srcColor[x + offset].r);
+ }
}
// Bottom row pixels
for (int y = 1; y < h - 1; y += 2) {
- int offset = y * w;
+ int offset = y * w;
- // Bottom left pixels
- for (int x = 0; x < w - 1; x += 2) {
- dstColor[x + offset] = Color1(srcColor[x + offset].b);
- }
+ // Bottom left pixels
+ for (int x = 0; x < w - 1; x += 2) {
+ dstColor[x + offset] = Color1unorm8(srcColor[x + offset].b);
+ }
- // Bottom right pixels
- for (int x = 1; x < w - 1; x += 2) {
- dstColor[x + offset] = Color1(srcColor[x + offset].g);
- }
+ // Bottom right pixels
+ for (int x = 1; x < w - 1; x += 2) {
+ dstColor[x + offset] = Color1unorm8(srcColor[x + offset].g);
+ }
}
}
static void rgb8_to_bayer_bggr8(const int w, const int h,
- const uint8* src, uint8* dst) {
- Color3uint8* srcColor = (Color3uint8*)src;
- Color1uint8* dstColor = (Color1uint8*)dst;
+ const unorm8* src, unorm8* dst) {
+ Color3unorm8* srcColor = (Color3unorm8*)src;
+ Color1unorm8* dstColor = (Color1unorm8*)dst;
// Top row pixels
for (int y = 0; y < h - 1; y += 2) {
- int offset = y * w;
+ int offset = y * w;
- // Top left pixels
- for (int x = 0; x < w - 1; x += 2) {
- dstColor[x + offset] = Color1(srcColor[x + offset].b);
- }
+ // Top left pixels
+ for (int x = 0; x < w - 1; x += 2) {
+ dstColor[x + offset] = Color1unorm8(srcColor[x + offset].b);
+ }
- // Top right pixels
- for (int x = 1; x < w - 1; x += 2) {
- dstColor[x + offset] = Color1(srcColor[x + offset].g);
- }
+ // Top right pixels
+ for (int x = 1; x < w - 1; x += 2) {
+ dstColor[x + offset] = Color1unorm8(srcColor[x + offset].g);
+ }
}
// Bottom row pixels
for (int y = 1; y < h - 1; y += 2) {
- int offset = y * w;
+ int offset = y * w;
- // Bottom left pixels
- for(int x = 0; x < w - 1; x += 2) {
- dstColor[x + offset] = Color1(srcColor[x + offset].g);
- }
+ // Bottom left pixels
+ for(int x = 0; x < w - 1; x += 2) {
+ dstColor[x + offset] = Color1unorm8(srcColor[x + offset].g);
+ }
- // Bottom right pixels
- for(int x = 1; x < w - 1; x += 2) {
- dstColor[x + offset] = Color1(srcColor[x + offset].r);
- }
+ // Bottom right pixels
+ for(int x = 1; x < w - 1; x += 2) {
+ dstColor[x + offset] = Color1unorm8(srcColor[x + offset].r);
+ }
}
}
static void rgb8_to_bayer_gbrg8(const int w, const int h,
- const uint8* src, uint8* dst) {
- Color3uint8* srcColor = (Color3uint8*)src;
- Color1uint8* dstColor = (Color1uint8*)dst;
+ const unorm8* src, unorm8* dst) {
+ Color3unorm8* srcColor = (Color3unorm8*)src;
+ Color1unorm8* dstColor = (Color1unorm8*)dst;
// Top row pixels
for(int y = 0; y < h - 1; y += 2) {
- int offset = y * w;
+ int offset = y * w;
- // Top left pixels
- for(int x = 0; x < w - 1; x += 2) {
- dstColor[x + offset] = Color1(srcColor[x + offset].g);
- }
+ // Top left pixels
+ for(int x = 0; x < w - 1; x += 2) {
+ dstColor[x + offset] = Color1unorm8(srcColor[x + offset].g);
+ }
- // Top right pixels
- for(int x = 1; x < w - 1; x += 2) {
- dstColor[x + offset] = Color1(srcColor[x + offset].b);
- }
+ // Top right pixels
+ for(int x = 1; x < w - 1; x += 2) {
+ dstColor[x + offset] = Color1unorm8(srcColor[x + offset].b);
+ }
}
// Bottom row pixels
for(int y = 1; y < h - 1; y += 2) {
- int offset = y * w;
+ int offset = y * w;
- // Bottom left pixels
- for(int x = 0; x < w - 1; x += 2) {
- dstColor[x + offset] = Color1(srcColor[x + offset].r);
- }
+ // Bottom left pixels
+ for(int x = 0; x < w - 1; x += 2) {
+ dstColor[x + offset] = Color1unorm8(srcColor[x + offset].r);
+ }
- // Bottom right pixels
- for(int x = 1; x < w - 1; x += 2) {
- dstColor[x + offset] = Color1(srcColor[x + offset].g);
- }
+ // Bottom right pixels
+ for(int x = 1; x < w - 1; x += 2) {
+ dstColor[x + offset] = Color1unorm8(srcColor[x + offset].g);
+ }
}
}
@@ -991,40 +991,40 @@ static void rgb8_to_bayer_gbrg8(const int w, const int h,
// =====================================================================
static void rgba32f_to_bayer_rggb8(const Array<const void*>& srcBytes, int srcWidth, int srcHeight, const ImageFormat* srcFormat, int srcRowPadBits, const Array<void*>& dstBytes, const ImageFormat* dstFormat, int dstRowPadBits, bool invertY, ImageFormat::BayerAlgorithm bayerAlg) {
Array<void*> tmp;
- tmp.append(System::malloc(srcWidth * srcHeight * sizeof(Color3uint8)));
+ tmp.append(System::malloc(srcWidth * srcHeight * sizeof(Color3unorm8)));
rgba32f_to_rgb8(srcBytes, srcWidth, srcHeight, ImageFormat::RGBA32F(), 0, tmp, ImageFormat::RGB8(), 0, invertY, bayerAlg);
- rgb8_to_bayer_rggb8(srcWidth, srcHeight, static_cast<uint8*>(tmp[0]), static_cast<uint8*>(dstBytes[0]));
+ rgb8_to_bayer_rggb8(srcWidth, srcHeight, static_cast<unorm8*>(tmp[0]), static_cast<unorm8*>(dstBytes[0]));
System::free(tmp[0]);
}
static void rgba32f_to_bayer_gbrg8(const Array<const void*>& srcBytes, int srcWidth, int srcHeight, const ImageFormat* srcFormat, int srcRowPadBits, const Array<void*>& dstBytes, const ImageFormat* dstFormat, int dstRowPadBits, bool invertY, ImageFormat::BayerAlgorithm bayerAlg) {
Array<void*> tmp;
- tmp.append(System::malloc(srcWidth * srcHeight * sizeof(Color3uint8)));
+ tmp.append(System::malloc(srcWidth * srcHeight * sizeof(Color3unorm8)));
rgba32f_to_rgb8(srcBytes, srcWidth, srcHeight, ImageFormat::RGBA32F(), 0, tmp, ImageFormat::RGB8(), 0, invertY, bayerAlg);
- rgb8_to_bayer_grbg8(srcWidth, srcHeight, static_cast<uint8*>(tmp[0]), static_cast<uint8*>(dstBytes[0]));
+ rgb8_to_bayer_grbg8(srcWidth, srcHeight, static_cast<unorm8*>(tmp[0]), static_cast<unorm8*>(dstBytes[0]));
System::free(tmp[0]);
}
static void rgba32f_to_bayer_grbg8(const Array<const void*>& srcBytes, int srcWidth, int srcHeight, const ImageFormat* srcFormat, int srcRowPadBits, const Array<void*>& dstBytes, const ImageFormat* dstFormat, int dstRowPadBits, bool invertY, ImageFormat::BayerAlgorithm bayerAlg) {
Array<void*> tmp;
- tmp.append(System::malloc(srcWidth * srcHeight * sizeof(Color3uint8)));
+ tmp.append(System::malloc(srcWidth * srcHeight * sizeof(Color3unorm8)));
rgba32f_to_rgb8(srcBytes, srcWidth, srcHeight, ImageFormat::RGBA32F(), 0, tmp, ImageFormat::RGB8(), 0, invertY, bayerAlg);
- rgb8_to_bayer_gbrg8(srcWidth, srcHeight, static_cast<uint8*>(tmp[0]), static_cast<uint8*>(dstBytes[0]));
+ rgb8_to_bayer_gbrg8(srcWidth, srcHeight, static_cast<unorm8*>(tmp[0]), static_cast<unorm8*>(dstBytes[0]));
System::free(tmp[0]);
}
static void rgba32f_to_bayer_bggr8(const Array<const void*>& srcBytes, int srcWidth, int srcHeight, const ImageFormat* srcFormat, int srcRowPadBits, const Array<void*>& dstBytes, const ImageFormat* dstFormat, int dstRowPadBits, bool invertY, ImageFormat::BayerAlgorithm bayerAlg) {
Array<void*> tmp;
- tmp.append(System::malloc(srcWidth * srcHeight * sizeof(Color3uint8)));
+ tmp.append(System::malloc(srcWidth * srcHeight * sizeof(Color3unorm8)));
rgba32f_to_rgb8(srcBytes, srcWidth, srcHeight, ImageFormat::RGBA32F(), 0, tmp, ImageFormat::RGB8(), 0, invertY, bayerAlg);
- rgb8_to_bayer_bggr8(srcWidth, srcHeight, static_cast<uint8*>(tmp[0]), static_cast<uint8*>(dstBytes[0]));
+ rgb8_to_bayer_bggr8(srcWidth, srcHeight, static_cast<unorm8*>(tmp[0]), static_cast<unorm8*>(dstBytes[0]));
System::free(tmp[0]);
}
@@ -1035,109 +1035,109 @@ static void rgba32f_to_bayer_bggr8(const Array<const void*>& srcBytes, int srcWi
// bayer --> rgb8 helpers
// =====================================================================
static void bayer_rggb8_to_rgb8_mhc(int w, int h,
- const uint8* in, uint8* _out) {
+ const unorm8* in, unorm8* _out) {
debugAssert(in != _out);
- Color3uint8* out = (Color3uint8*)_out;
+ Color3unorm8* out = (Color3unorm8*)_out;
for (int y = 0; y < h; ++y) {
- // Row beginning in the input array.
- int offset = y * w;
-
- // RG row
- for (int x = 0; x < w; ++x, ++out) {
- // R pixel
- {
- out->r = in[x + offset];
- out->g = applyFilter(in, x, y, w, h, G_GRR);
- out->b = applyFilter(in, x, y, w, h, B_GRR);
- }
- ++x; ++out;
-
- // G pixel
- {
- out->r = applyFilter(in, x, y, w, h, R_GRG);
- out->g = in[x + offset];
- out->b = applyFilter(in, x, y, w, h, B_GRG);
- }
- }
-
- ++y;
- offset += w;
-
- // GB row
- for (int x = 0; x < w; ++x, ++out) {
- // G pixel
- {
- out->r = applyFilter(in, x, y, w, h, R_BGG);
- out->g = in[x + offset];
- out->b = applyFilter(in, x, y, w, h, B_BGG);
- }
- ++x; ++out;
-
- // B pixel
- {
- out->r = applyFilter(in, x, y, w, h, R_BGB);
- out->g = applyFilter(in, x, y, w, h, G_BGB);
- out->b = in[x + offset];
- }
- }
+ // Row beginning in the input array.
+ int offset = y * w;
+
+ // RG row
+ for (int x = 0; x < w; ++x, ++out) {
+ // R pixel
+ {
+ out->r = in[x + offset];
+ out->g = applyFilter(in, x, y, w, h, G_GRR);
+ out->b = applyFilter(in, x, y, w, h, B_GRR);
+ }
+ ++x; ++out;
+
+ // G pixel
+ {
+ out->r = applyFilter(in, x, y, w, h, R_GRG);
+ out->g = in[x + offset];
+ out->b = applyFilter(in, x, y, w, h, B_GRG);
+ }
+ }
+
+ ++y;
+ offset += w;
+
+ // GB row
+ for (int x = 0; x < w; ++x, ++out) {
+ // G pixel
+ {
+ out->r = applyFilter(in, x, y, w, h, R_BGG);
+ out->g = in[x + offset];
+ out->b = applyFilter(in, x, y, w, h, B_BGG);
+ }
+ ++x; ++out;
+
+ // B pixel
+ {
+ out->r = applyFilter(in, x, y, w, h, R_BGB);
+ out->g = applyFilter(in, x, y, w, h, G_BGB);
+ out->b = in[x + offset];
+ }
+ }
}
}
static void bayer_gbrg8_to_rgb8_mhc(int w, int h,
- const uint8* in, uint8* _out) {
+ const unorm8* in, unorm8* _out) {
debugAssert(in != _out);
- Color3uint8* out = (Color3uint8*)_out;
+ Color3unorm8* out = (Color3unorm8*)_out;
for (int y = 0; y < h; ++y) {
- // Row beginning in the input array.
- int offset = y * w;
-
- // GB row
- for (int x = 0; x < w; ++x, ++out) {
- // G pixel
- {
- out->r = applyFilter(in, x, y, w, h, R_BGG);
- out->g = in[x + offset];
- out->b = applyFilter(in, x, y, w, h, B_BGG);
- }
- ++x; ++out;
-
- // B pixel
- {
- out->r = applyFilter(in, x, y, w, h, R_BGB);
- out->g = applyFilter(in, x, y, w, h, G_BGB);
- out->b = in[x + offset];
- }
- }
+ // Row beginning in the input array.
+ int offset = y * w;
+
+ // GB row
+ for (int x = 0; x < w; ++x, ++out) {
+ // G pixel
+ {
+ out->r = applyFilter(in, x, y, w, h, R_BGG);
+ out->g = in[x + offset];
+ out->b = applyFilter(in, x, y, w, h, B_BGG);
+ }
+ ++x; ++out;
+
+ // B pixel
+ {
+ out->r = applyFilter(in, x, y, w, h, R_BGB);
+ out->g = applyFilter(in, x, y, w, h, G_BGB);
+ out->b = in[x + offset];
+ }
+ }
}
}
static void bayer_grbg8_to_rgb8_mhc(int w, int h,
- const uint8* in, uint8* _out) {
+ const unorm8* in, unorm8* _out) {
// Run the equivalent function for red
bayer_gbrg8_to_rgb8_mhc(w, h, in, _out);
// Now swap red and blue
- swapRedAndBlue(w * h, (Color3uint8*)_out);
+ swapRedAndBlue(w * h, (Color3unorm8*)_out);
}
static void bayer_bggr8_to_rgb8_mhc(int w, int h,
- const uint8* in, uint8* _out) {
+ const unorm8* in, unorm8* _out) {
// Run the equivalent function for red
bayer_rggb8_to_rgb8_mhc(w, h, in, _out);
// Now swap red and blue
- swapRedAndBlue(w * h, (Color3uint8*)_out);
+ swapRedAndBlue(w * h, (Color3unorm8*)_out);
}
// =====================================================================
@@ -1145,9 +1145,9 @@ static void bayer_bggr8_to_rgb8_mhc(int w, int h,
// =====================================================================
static void bayer_rggb8_to_rgba32f(const Array<const void*>& srcBytes, int srcWidth, int srcHeight, const ImageFormat* srcFormat, int srcRowPadBits, const Array<void*>& dstBytes, const ImageFormat* dstFormat, int dstRowPadBits, bool invertY, ImageFormat::BayerAlgorithm bayerAlg) {
Array<void*> tmp;
- tmp.append(System::malloc(srcWidth * srcHeight * sizeof(Color3uint8)));
+ tmp.append(System::malloc(srcWidth * srcHeight * sizeof(Color3unorm8)));
- bayer_rggb8_to_rgb8_mhc(srcWidth, srcHeight, static_cast<const uint8*>(srcBytes[0]), static_cast<uint8*>(tmp[0]));
+ bayer_rggb8_to_rgb8_mhc(srcWidth, srcHeight, static_cast<const unorm8*>(srcBytes[0]), static_cast<unorm8*>(tmp[0]));
rgb8_to_rgba32f(reinterpret_cast<Array<const void*>&>(tmp), srcWidth, srcHeight, ImageFormat::RGB8(), 0, dstBytes, ImageFormat::RGBA32F(), 0, invertY, bayerAlg);
System::free(tmp[0]);
@@ -1155,9 +1155,9 @@ static void bayer_rggb8_to_rgba32f(const Array<const void*>& srcBytes, int srcWi
static void bayer_gbrg8_to_rgba32f(const Array<const void*>& srcBytes, int srcWidth, int srcHeight, const ImageFormat* srcFormat, int srcRowPadBits, const Array<void*>& dstBytes, const ImageFormat* dstFormat, int dstRowPadBits, bool invertY, ImageFormat::BayerAlgorithm bayerAlg) {
Array<void*> tmp;
- tmp.append(System::malloc(srcWidth * srcHeight * sizeof(Color3uint8)));
+ tmp.append(System::malloc(srcWidth * srcHeight * sizeof(Color3unorm8)));
- bayer_grbg8_to_rgb8_mhc(srcWidth, srcHeight, static_cast<const uint8*>(srcBytes[0]), static_cast<uint8*>(tmp[0]));
+ bayer_grbg8_to_rgb8_mhc(srcWidth, srcHeight, static_cast<const unorm8*>(srcBytes[0]), static_cast<unorm8*>(tmp[0]));
rgb8_to_rgba32f(reinterpret_cast<Array<const void*>&>(tmp), srcWidth, srcHeight, ImageFormat::RGB8(), 0, dstBytes, ImageFormat::RGBA32F(), 0, invertY, bayerAlg);
System::free(tmp[0]);
@@ -1165,9 +1165,9 @@ static void bayer_gbrg8_to_rgba32f(const Array<const void*>& srcBytes, int srcWi
static void bayer_grbg8_to_rgba32f(const Array<const void*>& srcBytes, int srcWidth, int srcHeight, const ImageFormat* srcFormat, int srcRowPadBits, const Array<void*>& dstBytes, const ImageFormat* dstFormat, int dstRowPadBits, bool invertY, ImageFormat::BayerAlgorithm bayerAlg) {
Array<void*> tmp;
- tmp.append(System::malloc(srcWidth * srcHeight * sizeof(Color3uint8)));
+ tmp.append(System::malloc(srcWidth * srcHeight * sizeof(Color3unorm8)));
- bayer_gbrg8_to_rgb8_mhc(srcWidth, srcHeight, static_cast<const uint8*>(srcBytes[0]), static_cast<uint8*>(tmp[0]));
+ bayer_gbrg8_to_rgb8_mhc(srcWidth, srcHeight, static_cast<const unorm8*>(srcBytes[0]), static_cast<unorm8*>(tmp[0]));
rgb8_to_rgba32f(reinterpret_cast<Array<const void*>&>(tmp), srcWidth, srcHeight, ImageFormat::RGB8(), 0, dstBytes, ImageFormat::RGBA32F(), 0, invertY, bayerAlg);
System::free(tmp[0]);
@@ -1175,9 +1175,9 @@ static void bayer_grbg8_to_rgba32f(const Array<const void*>& srcBytes, int srcWi
static void bayer_bggr8_to_rgba32f(const Array<const void*>& srcBytes, int srcWidth, int srcHeight, const ImageFormat* srcFormat, int srcRowPadBits, const Array<void*>& dstBytes, const ImageFormat* dstFormat, int dstRowPadBits, bool invertY, ImageFormat::BayerAlgorithm bayerAlg) {
Array<void*> tmp;
- tmp.append(System::malloc(srcWidth * srcHeight * sizeof(Color3uint8)));
+ tmp.append(System::malloc(srcWidth * srcHeight * sizeof(Color3unorm8)));
- bayer_bggr8_to_rgb8_mhc(srcWidth, srcHeight, static_cast<const uint8*>(srcBytes[0]), static_cast<uint8*>(tmp[0]));
+ bayer_bggr8_to_rgb8_mhc(srcWidth, srcHeight, static_cast<const unorm8*>(srcBytes[0]), static_cast<unorm8*>(tmp[0]));
rgb8_to_rgba32f(reinterpret_cast<Array<const void*>&>(tmp), srcWidth, srcHeight, ImageFormat::RGB8(), 0, dstBytes, ImageFormat::RGBA32F(), 0, invertY, bayerAlg);
System::free(tmp[0]);
@@ -1198,106 +1198,106 @@ static void bayer_bggr8_to_rgba32f(const Array<const void*>& srcBytes, int srcWi
// // =====================================================================
// static void bayer_rggb8_to_bgr8_mhc(int w, int h,
-// const uint8* in, uint8* _out) {
+// const unorm8* in, unorm8* _out) {
// debugAssert(in != _out);
-// Color3uint8* out = (Color3uint8*)_out;
+// Color3unorm8* out = (Color3unorm8*)_out;
// for (int y = 0; y < h; ++y) {
-// // Row beginning in the input array.
-// int offset = y * w;
-
-// // RG row
-// for (int x = 0; x < w; ++x, ++out) {
-// // R pixel
-// {
-// out->b = in[x + offset];
-// out->g = applyFilter(in, x, y, w, h, G_GRR);
-// out->r = applyFilter(in, x, y, w, h, B_GRR);
-// }
-// ++x; ++out;
-
-// // G pixel
-// {
-// out->b = applyFilter(in, x, y, w, h, R_GRG);
-// out->g = in[x + offset];
-// out->r = applyFilter(in, x, y, w, h, B_GRG);
-// }
-// }
-
-// ++y;
-// offset += w;
-
-// // GB row
-// for (int x = 0; x < w; ++x, ++out) {
-// // G pixel
-// {
-// out->b = applyFilter(in, x, y, w, h, R_BGG);
-// out->g = in[x + offset];
-// out->r = applyFilter(in, x, y, w, h, B_BGG);
-// }
-// ++x; ++out;
-
-// // B pixel
-// {
-// out->b = applyFilter(in, x, y, w, h, R_BGB);
-// out->g = applyFilter(in, x, y, w, h, G_BGB);
-// out->r = in[x + offset];
-// }
-// }
+// // Row beginning in the input array.
+// int offset = y * w;
+
+// // RG row
+// for (int x = 0; x < w; ++x, ++out) {
+// // R pixel
+// {
+// out->b = in[x + offset];
+// out->g = applyFilter(in, x, y, w, h, G_GRR);
+// out->r = applyFilter(in, x, y, w, h, B_GRR);
+// }
+// ++x; ++out;
+
+// // G pixel
+// {
+// out->b = applyFilter(in, x, y, w, h, R_GRG);
+// out->g = in[x + offset];
+// out->r = applyFilter(in, x, y, w, h, B_GRG);
+// }
+// }
+
+// ++y;
+// offset += w;
+
+// // GB row
+// for (int x = 0; x < w; ++x, ++out) {
+// // G pixel
+// {
+// out->b = applyFilter(in, x, y, w, h, R_BGG);
+// out->g = in[x + offset];
+// out->r = applyFilter(in, x, y, w, h, B_BGG);
+// }
+// ++x; ++out;
+
+// // B pixel
+// {
+// out->b = applyFilter(in, x, y, w, h, R_BGB);
+// out->g = applyFilter(in, x, y, w, h, G_BGB);
+// out->r = in[x + offset];
+// }
+// }
// }
// }
// static void bayer_gbrg8_to_bgr8_mhc(int w, int h,
-// const uint8* in, uint8* _out) {
+// const unorm8* in, unorm8* _out) {
// debugAssert(in != _out);
-// Color3uint8* out = (Color3uint8*)_out;
+// Color3unorm8* out = (Color3unorm8*)_out;
// for (int y = 0; y < h; ++y) {
-// // Row beginning in the input array.
-// int offset = y * w;
-
-// // GB row
-// for (int x = 0; x < srcWidth; ++x, ++out) {
-// // G pixel
-// {
-// out->b = applyFilter(in, x, y, w, h, R_BGG);
-// out->g = in[x + offset];
-// out->r = applyFilter(in, x, y, w, h, B_BGG);
-// }
-// ++x; ++out;
-
-// // B pixel
-// {
-// out->b = applyFilter(in, x, y, w, h, R_BGB);
-// out->g = applyFilter(in, x, y, w, h, G_BGB);
-// out->r = in[x + offset];
-// }
-// }
+// // Row beginning in the input array.
+// int offset = y * w;
+
+// // GB row
+// for (int x = 0; x < srcWidth; ++x, ++out) {
+// // G pixel
+// {
+// out->b = applyFilter(in, x, y, w, h, R_BGG);
+// out->g = in[x + offset];
+// out->r = applyFilter(in, x, y, w, h, B_BGG);
+// }
+// ++x; ++out;
+
+// // B pixel
+// {
+// out->b = applyFilter(in, x, y, w, h, R_BGB);
+// out->g = applyFilter(in, x, y, w, h, G_BGB);
+// out->r = in[x + offset];
+// }
+// }
// }
// }
// static void bayer_grbg8_to_bgr8_mhc(int w, int h,
-// const uint8* in, uint8* _out) {
+// const unorm8* in, unorm8* _out) {
// // Run the equivalent function for red
// bayer_gbrg8_to_bgr8_mhc(w, h, in, _out);
// // Now swap red and blue
-// swapRedAndBlue(srcWidth * h, (Color3uint8*)_out);
+// swapRedAndBlue(srcWidth * h, (Color3unorm8*)_out);
// }
// static void bayer_bggr8_to_bgr8_mhc(int w, int h,
-// const uint8* in, uint8* _out) {
+// const unorm8* in, unorm8* _out) {
// // Run the equivalent function for red
// bayer_rggb8_to_bgr8_mhc(w, h, in, _out);
// // Now swap red and blue
-// swapRedAndBlue(srcWidth * h, (Color3uint8*)_out);
+// swapRedAndBlue(srcWidth * h, (Color3unorm8*)_out);
// }
diff --git a/dep/g3dlite/source/Intersect.cpp b/dep/g3dlite/source/Intersect.cpp
index 929a2e4e670..06c9630c170 100644
--- a/dep/g3dlite/source/Intersect.cpp
+++ b/dep/g3dlite/source/Intersect.cpp
@@ -1,23 +1,23 @@
/**
- @file Intersect.cpp
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2009-06-29
- @edited 2009-06-29
-
- Copyright 2000-2009, Morgan McGuire.
- All rights reserved.
-
- From the G3D Innovation Engine
- http://g3d.sf.net
- */
+@file Intersect.cpp
+
+@maintainer Morgan McGuire, http://graphics.cs.williams.edu
+
+@created 2009-06-29
+@edited 2009-06-29
+
+Copyright 2000-2009, Morgan McGuire.
+All rights reserved.
+
+From the G3D Innovation Engine
+http://g3d.sf.net
+*/
#include "G3D/Intersect.h"
namespace G3D {
#ifdef _MSC_VER
-// Turn on fast floating-point optimizations
+ // Turn on fast floating-point optimizations
#pragma float_control( push )
#pragma fp_contract( on )
#pragma fenv_access( off )
@@ -28,816 +28,821 @@ namespace G3D {
bool __fastcall Intersect::rayAABox(const Ray& ray, const AABox& box) {
switch (ray.classification) {
case Ray::MMM:
-
- if ((ray.m_origin.x < box.lo.x) || (ray.m_origin.y < box.lo.y) || (ray.m_origin.z < box.lo.z)
- || (ray.jbyi * box.lo.x - box.hi.y + ray.c_xy > 0)
- || (ray.ibyj * box.lo.y - box.hi.x + ray.c_yx > 0)
- || (ray.jbyk * box.lo.z - box.hi.y + ray.c_zy > 0)
- || (ray.kbyj * box.lo.y - box.hi.z + ray.c_yz > 0)
- || (ray.kbyi * box.lo.x - box.hi.z + ray.c_xz > 0)
- || (ray.ibyk * box.lo.z - box.hi.x + ray.c_zx > 0)
- )
- return false;
-
- return true;
-
- case Ray::MMP:
-
- if ((ray.m_origin.x < box.lo.x) || (ray.m_origin.y < box.lo.y) || (ray.m_origin.z > box.hi.z)
- || (ray.jbyi * box.lo.x - box.hi.y + ray.c_xy > 0)
- || (ray.ibyj * box.lo.y - box.hi.x + ray.c_yx > 0)
- || (ray.jbyk * box.hi.z - box.hi.y + ray.c_zy > 0)
- || (ray.kbyj * box.lo.y - box.lo.z + ray.c_yz < 0)
- || (ray.kbyi * box.lo.x - box.lo.z + ray.c_xz < 0)
- || (ray.ibyk * box.hi.z - box.hi.x + ray.c_zx > 0)
- )
- return false;
-
- return true;
-
- case Ray::MPM:
-
- if ((ray.m_origin.x < box.lo.x) || (ray.m_origin.y > box.hi.y) || (ray.m_origin.z < box.lo.z)
- || (ray.jbyi * box.lo.x - box.lo.y + ray.c_xy < 0)
- || (ray.ibyj * box.hi.y - box.hi.x + ray.c_yx > 0)
- || (ray.jbyk * box.lo.z - box.lo.y + ray.c_zy < 0)
- || (ray.kbyj * box.hi.y - box.hi.z + ray.c_yz > 0)
- || (ray.kbyi * box.lo.x - box.hi.z + ray.c_xz > 0)
- || (ray.ibyk * box.lo.z - box.hi.x + ray.c_zx > 0)
- )
- return false;
-
- return true;
-
- case Ray::MPP:
-
- if ((ray.m_origin.x < box.lo.x) || (ray.m_origin.y > box.hi.y) || (ray.m_origin.z > box.hi.z)
- || (ray.jbyi * box.lo.x - box.lo.y + ray.c_xy < 0)
- || (ray.ibyj * box.hi.y - box.hi.x + ray.c_yx > 0)
- || (ray.jbyk * box.hi.z - box.lo.y + ray.c_zy < 0)
- || (ray.kbyj * box.hi.y - box.lo.z + ray.c_yz < 0)
- || (ray.kbyi * box.lo.x - box.lo.z + ray.c_xz < 0)
- || (ray.ibyk * box.hi.z - box.hi.x + ray.c_zx > 0)
- )
- return false;
-
- return true;
-
- case Ray::PMM:
-
- if ((ray.m_origin.x > box.hi.x) || (ray.m_origin.y < box.lo.y) || (ray.m_origin.z < box.lo.z)
- || (ray.jbyi * box.hi.x - box.hi.y + ray.c_xy > 0)
- || (ray.ibyj * box.lo.y - box.lo.x + ray.c_yx < 0)
- || (ray.jbyk * box.lo.z - box.hi.y + ray.c_zy > 0)
- || (ray.kbyj * box.lo.y - box.hi.z + ray.c_yz > 0)
- || (ray.kbyi * box.hi.x - box.hi.z + ray.c_xz > 0)
- || (ray.ibyk * box.lo.z - box.lo.x + ray.c_zx < 0)
- )
- return false;
-
- return true;
-
- case Ray::PMP:
-
- if ((ray.m_origin.x > box.hi.x) || (ray.m_origin.y < box.lo.y) || (ray.m_origin.z > box.hi.z)
- || (ray.jbyi * box.hi.x - box.hi.y + ray.c_xy > 0)
- || (ray.ibyj * box.lo.y - box.lo.x + ray.c_yx < 0)
- || (ray.jbyk * box.hi.z - box.hi.y + ray.c_zy > 0)
- || (ray.kbyj * box.lo.y - box.lo.z + ray.c_yz < 0)
- || (ray.kbyi * box.hi.x - box.lo.z + ray.c_xz < 0)
- || (ray.ibyk * box.hi.z - box.lo.x + ray.c_zx < 0)
- )
- return false;
-
- return true;
-
- case Ray::PPM:
-
- if ((ray.m_origin.x > box.hi.x) || (ray.m_origin.y > box.hi.y) || (ray.m_origin.z < box.lo.z)
- || (ray.jbyi * box.hi.x - box.lo.y + ray.c_xy < 0)
- || (ray.ibyj * box.hi.y - box.lo.x + ray.c_yx < 0)
- || (ray.jbyk * box.lo.z - box.lo.y + ray.c_zy < 0)
- || (ray.kbyj * box.hi.y - box.hi.z + ray.c_yz > 0)
- || (ray.kbyi * box.hi.x - box.hi.z + ray.c_xz > 0)
- || (ray.ibyk * box.lo.z - box.lo.x + ray.c_zx < 0)
- )
- return false;
-
- return true;
-
- case Ray::PPP:
-
- if ((ray.m_origin.x > box.hi.x) || (ray.m_origin.y > box.hi.y) || (ray.m_origin.z > box.hi.z)
- || (ray.jbyi * box.hi.x - box.lo.y + ray.c_xy < 0)
- || (ray.ibyj * box.hi.y - box.lo.x + ray.c_yx < 0)
- || (ray.jbyk * box.hi.z - box.lo.y + ray.c_zy < 0)
- || (ray.kbyj * box.hi.y - box.lo.z + ray.c_yz < 0)
- || (ray.kbyi * box.hi.x - box.lo.z + ray.c_xz < 0)
- || (ray.ibyk * box.hi.z - box.lo.x + ray.c_zx < 0)) {
- return false;
- }
-
- return true;
-
- case Ray::OMM:
-
- if((ray.m_origin.x < box.lo.x) || (ray.m_origin.x > box.hi.x)
- || (ray.m_origin.y < box.lo.y) || (ray.m_origin.z < box.lo.z)
- || (ray.jbyk * box.lo.z - box.hi.y + ray.c_zy > 0)
- || (ray.kbyj * box.lo.y - box.hi.z + ray.c_yz > 0)
- )
- return false;
-
- return true;
- case Ray::OMP:
-
- if((ray.m_origin.x < box.lo.x) || (ray.m_origin.x > box.hi.x)
- || (ray.m_origin.y < box.lo.y) || (ray.m_origin.z > box.hi.z)
- || (ray.jbyk * box.hi.z - box.hi.y + ray.c_zy > 0)
- || (ray.kbyj * box.lo.y - box.lo.z + ray.c_yz < 0)
- )
- return false;
-
- return true;
-
- case Ray::OPM:
-
- if((ray.m_origin.x < box.lo.x) || (ray.m_origin.x > box.hi.x)
- || (ray.m_origin.y > box.hi.y) || (ray.m_origin.z < box.lo.z)
- || (ray.jbyk * box.lo.z - box.lo.y + ray.c_zy < 0)
- || (ray.kbyj * box.hi.y - box.hi.z + ray.c_yz > 0)
- )
- return false;
-
- return true;
-
- case Ray::OPP:
-
- if((ray.m_origin.x < box.lo.x) || (ray.m_origin.x > box.hi.x)
- || (ray.m_origin.y > box.hi.y) || (ray.m_origin.z > box.hi.z)
- || (ray.jbyk * box.hi.z - box.lo.y + ray.c_zy < 0)
- || (ray.kbyj * box.hi.y - box.lo.z + ray.c_yz < 0)
- )
- return false;
-
- return true;
+ if ((ray.m_origin.x < box.lo.x) || (ray.m_origin.y < box.lo.y) || (ray.m_origin.z < box.lo.z)
+ || (ray.jbyi * box.lo.x - box.hi.y + ray.c_xy > 0)
+ || (ray.ibyj * box.lo.y - box.hi.x + ray.c_yx > 0)
+ || (ray.jbyk * box.lo.z - box.hi.y + ray.c_zy > 0)
+ || (ray.kbyj * box.lo.y - box.hi.z + ray.c_yz > 0)
+ || (ray.kbyi * box.lo.x - box.hi.z + ray.c_xz > 0)
+ || (ray.ibyk * box.lo.z - box.hi.x + ray.c_zx > 0)
+ )
+ return false;
+ else
+ return true;
+
+ case Ray::MMP:
+
+ if ((ray.m_origin.x < box.lo.x) || (ray.m_origin.y < box.lo.y) || (ray.m_origin.z > box.hi.z)
+ || (ray.jbyi * box.lo.x - box.hi.y + ray.c_xy > 0)
+ || (ray.ibyj * box.lo.y - box.hi.x + ray.c_yx > 0)
+ || (ray.jbyk * box.hi.z - box.hi.y + ray.c_zy > 0)
+ || (ray.kbyj * box.lo.y - box.lo.z + ray.c_yz < 0)
+ || (ray.kbyi * box.lo.x - box.lo.z + ray.c_xz < 0)
+ || (ray.ibyk * box.hi.z - box.hi.x + ray.c_zx > 0)
+ )
+ return false;
+ else
+ return true;
+
+ case Ray::MPM:
+
+ if ((ray.m_origin.x < box.lo.x) || (ray.m_origin.y > box.hi.y) || (ray.m_origin.z < box.lo.z)
+ || (ray.jbyi * box.lo.x - box.lo.y + ray.c_xy < 0)
+ || (ray.ibyj * box.hi.y - box.hi.x + ray.c_yx > 0)
+ || (ray.jbyk * box.lo.z - box.lo.y + ray.c_zy < 0)
+ || (ray.kbyj * box.hi.y - box.hi.z + ray.c_yz > 0)
+ || (ray.kbyi * box.lo.x - box.hi.z + ray.c_xz > 0)
+ || (ray.ibyk * box.lo.z - box.hi.x + ray.c_zx > 0)
+ )
+ return false;
+ else
+ return true;
+
+ case Ray::MPP:
+
+ if ((ray.m_origin.x < box.lo.x) || (ray.m_origin.y > box.hi.y) || (ray.m_origin.z > box.hi.z)
+ || (ray.jbyi * box.lo.x - box.lo.y + ray.c_xy < 0)
+ || (ray.ibyj * box.hi.y - box.hi.x + ray.c_yx > 0)
+ || (ray.jbyk * box.hi.z - box.lo.y + ray.c_zy < 0)
+ || (ray.kbyj * box.hi.y - box.lo.z + ray.c_yz < 0)
+ || (ray.kbyi * box.lo.x - box.lo.z + ray.c_xz < 0)
+ || (ray.ibyk * box.hi.z - box.hi.x + ray.c_zx > 0)
+ )
+ return false;
+ else
+ return true;
+
+ case Ray::PMM:
+
+ if ((ray.m_origin.x > box.hi.x) || (ray.m_origin.y < box.lo.y) || (ray.m_origin.z < box.lo.z)
+ || (ray.jbyi * box.hi.x - box.hi.y + ray.c_xy > 0)
+ || (ray.ibyj * box.lo.y - box.lo.x + ray.c_yx < 0)
+ || (ray.jbyk * box.lo.z - box.hi.y + ray.c_zy > 0)
+ || (ray.kbyj * box.lo.y - box.hi.z + ray.c_yz > 0)
+ || (ray.kbyi * box.hi.x - box.hi.z + ray.c_xz > 0)
+ || (ray.ibyk * box.lo.z - box.lo.x + ray.c_zx < 0)
+ )
+ return false;
+ else
+ return true;
+
+ case Ray::PMP:
+
+ if ((ray.m_origin.x > box.hi.x) || (ray.m_origin.y < box.lo.y) || (ray.m_origin.z > box.hi.z)
+ || (ray.jbyi * box.hi.x - box.hi.y + ray.c_xy > 0)
+ || (ray.ibyj * box.lo.y - box.lo.x + ray.c_yx < 0)
+ || (ray.jbyk * box.hi.z - box.hi.y + ray.c_zy > 0)
+ || (ray.kbyj * box.lo.y - box.lo.z + ray.c_yz < 0)
+ || (ray.kbyi * box.hi.x - box.lo.z + ray.c_xz < 0)
+ || (ray.ibyk * box.hi.z - box.lo.x + ray.c_zx < 0)
+ )
+ return false;
+ else
+ return true;
+
+ case Ray::PPM:
+
+ if ((ray.m_origin.x > box.hi.x) || (ray.m_origin.y > box.hi.y) || (ray.m_origin.z < box.lo.z)
+ || (ray.jbyi * box.hi.x - box.lo.y + ray.c_xy < 0)
+ || (ray.ibyj * box.hi.y - box.lo.x + ray.c_yx < 0)
+ || (ray.jbyk * box.lo.z - box.lo.y + ray.c_zy < 0)
+ || (ray.kbyj * box.hi.y - box.hi.z + ray.c_yz > 0)
+ || (ray.kbyi * box.hi.x - box.hi.z + ray.c_xz > 0)
+ || (ray.ibyk * box.lo.z - box.lo.x + ray.c_zx < 0)
+ )
+ return false;
+ else
+ return true;
- case Ray::MOM:
+ case Ray::PPP:
- if((ray.m_origin.y < box.lo.y) || (ray.m_origin.y > box.hi.y)
- || (ray.m_origin.x < box.lo.x) || (ray.m_origin.z < box.lo.z)
- || (ray.kbyi * box.lo.x - box.hi.z + ray.c_xz > 0)
- || (ray.ibyk * box.lo.z - box.hi.x + ray.c_zx > 0)
- )
- return false;
+ if ((ray.m_origin.x > box.hi.x) || (ray.m_origin.y > box.hi.y) || (ray.m_origin.z > box.hi.z)
+ || (ray.jbyi * box.hi.x - box.lo.y + ray.c_xy < 0)
+ || (ray.ibyj * box.hi.y - box.lo.x + ray.c_yx < 0)
+ || (ray.jbyk * box.hi.z - box.lo.y + ray.c_zy < 0)
+ || (ray.kbyj * box.hi.y - box.lo.z + ray.c_yz < 0)
+ || (ray.kbyi * box.hi.x - box.lo.z + ray.c_xz < 0)
+ || (ray.ibyk * box.hi.z - box.lo.x + ray.c_zx < 0)) {
+ return false;
+ } else
+ return true;
- return true;
+ case Ray::OMM:
- case Ray::MOP:
+ if((ray.m_origin.x < box.lo.x) || (ray.m_origin.x > box.hi.x)
+ || (ray.m_origin.y < box.lo.y) || (ray.m_origin.z < box.lo.z)
+ || (ray.jbyk * box.lo.z - box.hi.y + ray.c_zy > 0)
+ || (ray.kbyj * box.lo.y - box.hi.z + ray.c_yz > 0)
+ )
+ return false;
+ else
+ return true;
- if((ray.m_origin.y < box.lo.y) || (ray.m_origin.y > box.hi.y)
- || (ray.m_origin.x < box.lo.x) || (ray.m_origin.z > box.hi.z)
- || (ray.kbyi * box.lo.x - box.lo.z + ray.c_xz < 0)
- || (ray.ibyk * box.hi.z - box.hi.x + ray.c_zx > 0)
- )
- return false;
+ case Ray::OMP:
- return true;
+ if((ray.m_origin.x < box.lo.x) || (ray.m_origin.x > box.hi.x)
+ || (ray.m_origin.y < box.lo.y) || (ray.m_origin.z > box.hi.z)
+ || (ray.jbyk * box.hi.z - box.hi.y + ray.c_zy > 0)
+ || (ray.kbyj * box.lo.y - box.lo.z + ray.c_yz < 0)
+ )
+ return false;
+ else
+ return true;
- case Ray::POM:
+ case Ray::OPM:
- if((ray.m_origin.y < box.lo.y) || (ray.m_origin.y > box.hi.y)
- || (ray.m_origin.x > box.hi.x) || (ray.m_origin.z < box.lo.z)
- || (ray.kbyi * box.hi.x - box.hi.z + ray.c_xz > 0)
- || (ray.ibyk * box.lo.z - box.lo.x + ray.c_zx < 0)
- )
- return false;
+ if((ray.m_origin.x < box.lo.x) || (ray.m_origin.x > box.hi.x)
+ || (ray.m_origin.y > box.hi.y) || (ray.m_origin.z < box.lo.z)
+ || (ray.jbyk * box.lo.z - box.lo.y + ray.c_zy < 0)
+ || (ray.kbyj * box.hi.y - box.hi.z + ray.c_yz > 0)
+ )
+ return false;
+ else
+ return true;
- return true;
+ case Ray::OPP:
- case Ray::POP:
+ if((ray.m_origin.x < box.lo.x) || (ray.m_origin.x > box.hi.x)
+ || (ray.m_origin.y > box.hi.y) || (ray.m_origin.z > box.hi.z)
+ || (ray.jbyk * box.hi.z - box.lo.y + ray.c_zy < 0)
+ || (ray.kbyj * box.hi.y - box.lo.z + ray.c_yz < 0)
+ )
+ return false;
+ else
+ return true;
- if((ray.m_origin.y < box.lo.y) || (ray.m_origin.y > box.hi.y)
- || (ray.m_origin.x > box.hi.x) || (ray.m_origin.z > box.hi.z)
- || (ray.kbyi * box.hi.x - box.lo.z + ray.c_xz < 0)
- || (ray.ibyk * box.hi.z - box.lo.x + ray.c_zx < 0)
- )
- return false;
+ case Ray::MOM:
- return true;
+ if((ray.m_origin.y < box.lo.y) || (ray.m_origin.y > box.hi.y)
+ || (ray.m_origin.x < box.lo.x) || (ray.m_origin.z < box.lo.z)
+ || (ray.kbyi * box.lo.x - box.hi.z + ray.c_xz > 0)
+ || (ray.ibyk * box.lo.z - box.hi.x + ray.c_zx > 0)
+ )
+ return false;
+ else
+ return true;
- case Ray::MMO:
+ case Ray::MOP:
- if((ray.m_origin.z < box.lo.z) || (ray.m_origin.z > box.hi.z)
- || (ray.m_origin.x < box.lo.x) || (ray.m_origin.y < box.lo.y)
- || (ray.jbyi * box.lo.x - box.hi.y + ray.c_xy > 0)
- || (ray.ibyj * box.lo.y - box.hi.x + ray.c_yx > 0)
- )
- return false;
+ if((ray.m_origin.y < box.lo.y) || (ray.m_origin.y > box.hi.y)
+ || (ray.m_origin.x < box.lo.x) || (ray.m_origin.z > box.hi.z)
+ || (ray.kbyi * box.lo.x - box.lo.z + ray.c_xz < 0)
+ || (ray.ibyk * box.hi.z - box.hi.x + ray.c_zx > 0)
+ )
+ return false;
+ else
+ return true;
- return true;
+ case Ray::POM:
- case Ray::MPO:
+ if((ray.m_origin.y < box.lo.y) || (ray.m_origin.y > box.hi.y)
+ || (ray.m_origin.x > box.hi.x) || (ray.m_origin.z < box.lo.z)
+ || (ray.kbyi * box.hi.x - box.hi.z + ray.c_xz > 0)
+ || (ray.ibyk * box.lo.z - box.lo.x + ray.c_zx < 0)
+ )
+ return false;
+ else
+ return true;
- if((ray.m_origin.z < box.lo.z) || (ray.m_origin.z > box.hi.z)
- || (ray.m_origin.x < box.lo.x) || (ray.m_origin.y > box.hi.y)
- || (ray.jbyi * box.lo.x - box.lo.y + ray.c_xy < 0)
- || (ray.ibyj * box.hi.y - box.hi.x + ray.c_yx > 0)
- )
- return false;
+ case Ray::POP:
- return true;
+ if((ray.m_origin.y < box.lo.y) || (ray.m_origin.y > box.hi.y)
+ || (ray.m_origin.x > box.hi.x) || (ray.m_origin.z > box.hi.z)
+ || (ray.kbyi * box.hi.x - box.lo.z + ray.c_xz < 0)
+ || (ray.ibyk * box.hi.z - box.lo.x + ray.c_zx < 0)
+ )
+ return false;
+ else
+ return true;
- case Ray::PMO:
+ case Ray::MMO:
- if((ray.m_origin.z < box.lo.z) || (ray.m_origin.z > box.hi.z)
- || (ray.m_origin.x > box.hi.x) || (ray.m_origin.y < box.lo.y)
- || (ray.jbyi * box.hi.x - box.hi.y + ray.c_xy > 0)
- || (ray.ibyj * box.lo.y - box.lo.x + ray.c_yx < 0)
- )
- return false;
+ if((ray.m_origin.z < box.lo.z) || (ray.m_origin.z > box.hi.z)
+ || (ray.m_origin.x < box.lo.x) || (ray.m_origin.y < box.lo.y)
+ || (ray.jbyi * box.lo.x - box.hi.y + ray.c_xy > 0)
+ || (ray.ibyj * box.lo.y - box.hi.x + ray.c_yx > 0)
+ )
+ return false;
+ else
+ return true;
- return true;
+ case Ray::MPO:
- case Ray::PPO:
+ if((ray.m_origin.z < box.lo.z) || (ray.m_origin.z > box.hi.z)
+ || (ray.m_origin.x < box.lo.x) || (ray.m_origin.y > box.hi.y)
+ || (ray.jbyi * box.lo.x - box.lo.y + ray.c_xy < 0)
+ || (ray.ibyj * box.hi.y - box.hi.x + ray.c_yx > 0)
+ )
+ return false;
+ else
+ return true;
- if((ray.m_origin.z < box.lo.z) || (ray.m_origin.z > box.hi.z)
- || (ray.m_origin.x > box.hi.x) || (ray.m_origin.y > box.hi.y)
- || (ray.jbyi * box.hi.x - box.lo.y + ray.c_xy < 0)
- || (ray.ibyj * box.hi.y - box.lo.x + ray.c_yx < 0)
- )
- return false;
+ case Ray::PMO:
- return true;
+ if((ray.m_origin.z < box.lo.z) || (ray.m_origin.z > box.hi.z)
+ || (ray.m_origin.x > box.hi.x) || (ray.m_origin.y < box.lo.y)
+ || (ray.jbyi * box.hi.x - box.hi.y + ray.c_xy > 0)
+ || (ray.ibyj * box.lo.y - box.lo.x + ray.c_yx < 0)
+ )
+ return false;
+ else
+ return true;
- case Ray::MOO:
+ case Ray::PPO:
- if((ray.m_origin.x < box.lo.x)
- || (ray.m_origin.y < box.lo.y) || (ray.m_origin.y > box.hi.y)
- || (ray.m_origin.z < box.lo.z) || (ray.m_origin.z > box.hi.z)
- )
- return false;
+ if((ray.m_origin.z < box.lo.z) || (ray.m_origin.z > box.hi.z)
+ || (ray.m_origin.x > box.hi.x) || (ray.m_origin.y > box.hi.y)
+ || (ray.jbyi * box.hi.x - box.lo.y + ray.c_xy < 0)
+ || (ray.ibyj * box.hi.y - box.lo.x + ray.c_yx < 0)
+ )
+ return false;
+ else
+ return true;
- return true;
+ case Ray::MOO:
- case Ray::POO:
+ if((ray.m_origin.x < box.lo.x)
+ || (ray.m_origin.y < box.lo.y) || (ray.m_origin.y > box.hi.y)
+ || (ray.m_origin.z < box.lo.z) || (ray.m_origin.z > box.hi.z)
+ )
+ return false;
+ else
+ return true;
- if((ray.m_origin.x > box.hi.x)
- || (ray.m_origin.y < box.lo.y) || (ray.m_origin.y > box.hi.y)
- || (ray.m_origin.z < box.lo.z) || (ray.m_origin.z > box.hi.z)
- )
- return false;
+ case Ray::POO:
- return true;
+ if((ray.m_origin.x > box.hi.x)
+ || (ray.m_origin.y < box.lo.y) || (ray.m_origin.y > box.hi.y)
+ || (ray.m_origin.z < box.lo.z) || (ray.m_origin.z > box.hi.z)
+ )
+ return false;
+ else
+ return true;
- case Ray::OMO:
+ case Ray::OMO:
- if((ray.m_origin.y < box.lo.y)
- || (ray.m_origin.x < box.lo.x) || (ray.m_origin.x > box.hi.x)
- || (ray.m_origin.z < box.lo.z) || (ray.m_origin.z > box.hi.z)
- )
- return false;
+ if((ray.m_origin.y < box.lo.y)
+ || (ray.m_origin.x < box.lo.x) || (ray.m_origin.x > box.hi.x)
+ || (ray.m_origin.z < box.lo.z) || (ray.m_origin.z > box.hi.z)
+ )
+ return false;
+ else
+ return true;
- case Ray::OPO:
+ case Ray::OPO:
- if((ray.m_origin.y > box.hi.y)
- || (ray.m_origin.x < box.lo.x) || (ray.m_origin.x > box.hi.x)
- || (ray.m_origin.z < box.lo.z) || (ray.m_origin.z > box.hi.z)
- )
- return false;
+ if((ray.m_origin.y > box.hi.y)
+ || (ray.m_origin.x < box.lo.x) || (ray.m_origin.x > box.hi.x)
+ || (ray.m_origin.z < box.lo.z) || (ray.m_origin.z > box.hi.z)
+ )
+ return false;
+ else
+ return true;
- case Ray::OOM:
+ case Ray::OOM:
- if((ray.m_origin.z < box.lo.z)
- || (ray.m_origin.x < box.lo.x) || (ray.m_origin.x > box.hi.x)
- || (ray.m_origin.y < box.lo.y) || (ray.m_origin.y > box.hi.y)
- )
- return false;
+ if((ray.m_origin.z < box.lo.z)
+ || (ray.m_origin.x < box.lo.x) || (ray.m_origin.x > box.hi.x)
+ || (ray.m_origin.y < box.lo.y) || (ray.m_origin.y > box.hi.y)
+ )
+ return false;
+ else
+ return true;
- case Ray::OOP:
+ case Ray::OOP:
- if((ray.m_origin.z > box.hi.z)
- || (ray.m_origin.x < box.lo.x) || (ray.m_origin.x > box.hi.x)
- || (ray.m_origin.y < box.lo.y) || (ray.m_origin.y > box.hi.y)
- )
- return false;
+ if((ray.m_origin.z > box.hi.z)
+ || (ray.m_origin.x < box.lo.x) || (ray.m_origin.x > box.hi.x)
+ || (ray.m_origin.y < box.lo.y) || (ray.m_origin.y > box.hi.y)
+ )
+ return false;
+ else
+ return true;
- return true;
-
- }
+ }
- return false;
+ return false;
}
bool __fastcall Intersect::rayAABox(const Ray& ray, const AABox& box, float& time) {
- switch (ray.classification) {
- case Ray::MMM:
- {
- if ((ray.m_origin.x < box.lo.x) || (ray.m_origin.y < box.lo.y) || (ray.m_origin.z < box.lo.z)
- || (ray.jbyi * box.lo.x - box.hi.y + ray.c_xy > 0)
- || (ray.ibyj * box.lo.y - box.hi.x + ray.c_yx > 0)
- || (ray.jbyk * box.lo.z - box.hi.y + ray.c_zy > 0)
- || (ray.kbyj * box.lo.y - box.hi.z + ray.c_yz > 0)
- || (ray.kbyi * box.lo.x - box.hi.z + ray.c_xz > 0)
- || (ray.ibyk * box.lo.z - box.hi.x + ray.c_zx > 0)) {
- return false;
- }
-
- // compute the intersection distance
-
- time = (box.hi.x - ray.m_origin.x) * ray.m_invDirection.x;
- float t1 = (box.hi.y - ray.m_origin.y) * ray.m_invDirection.y;
- if (t1 > time) {
- time = t1;
- }
-
- float t2 = (box.hi.z - ray.m_origin.z) * ray.m_invDirection.z;
- if (t2 > time) {
- time = t2;
- }
-
- return true;
- }
-
- case Ray::MMP:
- {
- if ((ray.m_origin.x < box.lo.x) || (ray.m_origin.y < box.lo.y) || (ray.m_origin.z > box.hi.z)
- || (ray.jbyi * box.lo.x - box.hi.y + ray.c_xy > 0)
- || (ray.ibyj * box.lo.y - box.hi.x + ray.c_yx > 0)
- || (ray.jbyk * box.hi.z - box.hi.y + ray.c_zy > 0)
- || (ray.kbyj * box.lo.y - box.lo.z + ray.c_yz < 0)
- || (ray.kbyi * box.lo.x - box.lo.z + ray.c_xz < 0)
- || (ray.ibyk * box.hi.z - box.hi.x + ray.c_zx > 0)) {
- return false;
- }
-
- time = (box.hi.x - ray.m_origin.x) * ray.m_invDirection.x;
- float t1 = (box.hi.y - ray.m_origin.y) * ray.m_invDirection.y;
- if (t1 > time) {
- time = t1;
- }
- float t2 = (box.lo.z - ray.m_origin.z) * ray.m_invDirection.z;
- if (t2 > time) {
- time = t2;
- }
-
- return true;
- }
-
- case Ray::MPM:
- {
- if ((ray.m_origin.x < box.lo.x) || (ray.m_origin.y > box.hi.y) || (ray.m_origin.z < box.lo.z)
- || (ray.jbyi * box.lo.x - box.lo.y + ray.c_xy < 0)
- || (ray.ibyj * box.hi.y - box.hi.x + ray.c_yx > 0)
- || (ray.jbyk * box.lo.z - box.lo.y + ray.c_zy < 0)
- || (ray.kbyj * box.hi.y - box.hi.z + ray.c_yz > 0)
- || (ray.kbyi * box.lo.x - box.hi.z + ray.c_xz > 0)
- || (ray.ibyk * box.lo.z - box.hi.x + ray.c_zx > 0)) {
- return false;
- }
-
- time = (box.hi.x - ray.m_origin.x) * ray.m_invDirection.x;
- float t1 = (box.lo.y - ray.m_origin.y) * ray.m_invDirection.y;
- if (t1 > time) {
- time = t1;
- }
- float t2 = (box.hi.z - ray.m_origin.z) * ray.m_invDirection.z;
- if (t2 > time) {
- time = t2;
- }
-
- return true;
- }
-
- case Ray::MPP:
- {
- if ((ray.m_origin.x < box.lo.x) || (ray.m_origin.y > box.hi.y) || (ray.m_origin.z > box.hi.z)
- || (ray.jbyi * box.lo.x - box.lo.y + ray.c_xy < 0)
- || (ray.ibyj * box.hi.y - box.hi.x + ray.c_yx > 0)
- || (ray.jbyk * box.hi.z - box.lo.y + ray.c_zy < 0)
- || (ray.kbyj * box.hi.y - box.lo.z + ray.c_yz < 0)
- || (ray.kbyi * box.lo.x - box.lo.z + ray.c_xz < 0)
- || (ray.ibyk * box.hi.z - box.hi.x + ray.c_zx > 0)) {
- return false;
- }
-
- time = (box.hi.x - ray.m_origin.x) * ray.m_invDirection.x;
- float t1 = (box.lo.y - ray.m_origin.y) * ray.m_invDirection.y;
- if (t1 > time) {
- time = t1;
- }
- float t2 = (box.lo.z - ray.m_origin.z) * ray.m_invDirection.z;
- if (t2 > time) {
- time = t2;
- }
-
- return true;
- }
-
- case Ray::PMM:
- {
- if ((ray.m_origin.x > box.hi.x) || (ray.m_origin.y < box.lo.y) || (ray.m_origin.z < box.lo.z)
- || (ray.jbyi * box.hi.x - box.hi.y + ray.c_xy > 0)
- || (ray.ibyj * box.lo.y - box.lo.x + ray.c_yx < 0)
- || (ray.jbyk * box.lo.z - box.hi.y + ray.c_zy > 0)
- || (ray.kbyj * box.lo.y - box.hi.z + ray.c_yz > 0)
- || (ray.kbyi * box.hi.x - box.hi.z + ray.c_xz > 0)
- || (ray.ibyk * box.lo.z - box.lo.x + ray.c_zx < 0)) {
- return false;
- }
-
- time = (box.lo.x - ray.m_origin.x) * ray.m_invDirection.x;
- float t1 = (box.hi.y - ray.m_origin.y) * ray.m_invDirection.y;
- if (t1 > time) {
- time = t1;
- }
- float t2 = (box.hi.z - ray.m_origin.z) * ray.m_invDirection.z;
- if (t2 > time) {
- time = t2;
- }
-
- return true;
- }
-
-
- case Ray::PMP:
- {
- if ((ray.m_origin.x > box.hi.x) || (ray.m_origin.y < box.lo.y) || (ray.m_origin.z > box.hi.z)
- || (ray.jbyi * box.hi.x - box.hi.y + ray.c_xy > 0)
- || (ray.ibyj * box.lo.y - box.lo.x + ray.c_yx < 0)
- || (ray.jbyk * box.hi.z - box.hi.y + ray.c_zy > 0)
- || (ray.kbyj * box.lo.y - box.lo.z + ray.c_yz < 0)
- || (ray.kbyi * box.hi.x - box.lo.z + ray.c_xz < 0)
- || (ray.ibyk * box.hi.z - box.lo.x + ray.c_zx < 0)) {
- return false;
- }
-
- time = (box.lo.x - ray.m_origin.x) * ray.m_invDirection.x;
- float t1 = (box.hi.y - ray.m_origin.y) * ray.m_invDirection.y;
- if (t1 > time) {
- time = t1;
- }
- float t2 = (box.lo.z - ray.m_origin.z) * ray.m_invDirection.z;
- if (t2 > time) {
- time = t2;
- }
-
- return true;
- }
-
- case Ray::PPM:
- {
- if ((ray.m_origin.x > box.hi.x) || (ray.m_origin.y > box.hi.y) || (ray.m_origin.z < box.lo.z)
- || (ray.jbyi * box.hi.x - box.lo.y + ray.c_xy < 0)
- || (ray.ibyj * box.hi.y - box.lo.x + ray.c_yx < 0)
- || (ray.jbyk * box.lo.z - box.lo.y + ray.c_zy < 0)
- || (ray.kbyj * box.hi.y - box.hi.z + ray.c_yz > 0)
- || (ray.kbyi * box.hi.x - box.hi.z + ray.c_xz > 0)
- || (ray.ibyk * box.lo.z - box.lo.x + ray.c_zx < 0)) {
- return false;
- }
-
- time = (box.lo.x - ray.m_origin.x) * ray.m_invDirection.x;
- float t1 = (box.lo.y - ray.m_origin.y) * ray.m_invDirection.y;
- if (t1 > time) {
- time = t1;
- }
- float t2 = (box.hi.z - ray.m_origin.z) * ray.m_invDirection.z;
- if (t2 > time) {
- time = t2;
- }
-
- return true;
- }
-
- case Ray::PPP:
- {
- if ((ray.m_origin.x > box.hi.x) || (ray.m_origin.y > box.hi.y) || (ray.m_origin.z > box.hi.z)
- || (ray.jbyi * box.hi.x - box.lo.y + ray.c_xy < 0)
- || (ray.ibyj * box.hi.y - box.lo.x + ray.c_yx < 0)
- || (ray.jbyk * box.hi.z - box.lo.y + ray.c_zy < 0)
- || (ray.kbyj * box.hi.y - box.lo.z + ray.c_yz < 0)
- || (ray.kbyi * box.hi.x - box.lo.z + ray.c_xz < 0)
- || (ray.ibyk * box.hi.z - box.lo.x + ray.c_zx < 0)) {
- return false;
- }
-
- time = (box.lo.x - ray.m_origin.x) * ray.m_invDirection.x;
- float t1 = (box.lo.y - ray.m_origin.y) * ray.m_invDirection.y;
- if (t1 > time) {
- time = t1;
- }
- float t2 = (box.lo.z - ray.m_origin.z) * ray.m_invDirection.z;
- if (t2 > time) {
- time = t2;
- }
-
- return true;
- }
-
- case Ray::OMM:
- {
- if((ray.m_origin.x < box.lo.x) || (ray.m_origin.x > box.hi.x)
- || (ray.m_origin.y < box.lo.y) || (ray.m_origin.z < box.lo.z)
- || (ray.jbyk * box.lo.z - box.hi.y + ray.c_zy > 0)
- || (ray.kbyj * box.lo.y - box.hi.z + ray.c_yz > 0)) {
- return false;
- }
-
- time = (box.hi.y - ray.m_origin.y) * ray.m_invDirection.y;
- float t2 = (box.hi.z - ray.m_origin.z) * ray.m_invDirection.z;
- if (t2 > time) {
- time = t2;
- }
-
- return true;
- }
-
- case Ray::OMP:
- {
- if((ray.m_origin.x < box.lo.x) || (ray.m_origin.x > box.hi.x)
- || (ray.m_origin.y < box.lo.y) || (ray.m_origin.z > box.hi.z)
- || (ray.jbyk * box.hi.z - box.hi.y + ray.c_zy > 0)
- || (ray.kbyj * box.lo.y - box.lo.z + ray.c_yz < 0)) {
- return false;
- }
-
- time = (box.hi.y - ray.m_origin.y) * ray.m_invDirection.y;
- float t2 = (box.lo.z - ray.m_origin.z) * ray.m_invDirection.z;
- if (t2 > time) {
- time = t2;
- }
-
- return true;
- }
-
- case Ray::OPM:
- {
- if((ray.m_origin.x < box.lo.x) || (ray.m_origin.x > box.hi.x)
- || (ray.m_origin.y > box.hi.y) || (ray.m_origin.z < box.lo.z)
- || (ray.jbyk * box.lo.z - box.lo.y + ray.c_zy < 0)
- || (ray.kbyj * box.hi.y - box.hi.z + ray.c_yz > 0)) {
- return false;
- }
-
- time = (box.lo.y - ray.m_origin.y) * ray.m_invDirection.y;
- float t2 = (box.hi.z - ray.m_origin.z) * ray.m_invDirection.z;
- if (t2 > time) {
- time = t2;
- }
-
- return true;
- }
-
- case Ray::OPP:
- {
- if((ray.m_origin.x < box.lo.x) || (ray.m_origin.x > box.hi.x)
- || (ray.m_origin.y > box.hi.y) || (ray.m_origin.z > box.hi.z)
- || (ray.jbyk * box.hi.z - box.lo.y + ray.c_zy < 0)
- || (ray.kbyj * box.hi.y - box.lo.z + ray.c_yz < 0)) {
- return false;
- }
-
- time = (box.lo.y - ray.m_origin.y) * ray.m_invDirection.y;
- float t2 = (box.lo.z - ray.m_origin.z) * ray.m_invDirection.z;
- if (t2 > time) {
- time = t2;
- }
-
- return true;
- }
-
-
- case Ray::MOM:
- {
- if((ray.m_origin.y < box.lo.y) || (ray.m_origin.y > box.hi.y)
- || (ray.m_origin.x < box.lo.x) || (ray.m_origin.z < box.lo.z)
- || (ray.kbyi * box.lo.x - box.hi.z + ray.c_xz > 0)
- || (ray.ibyk * box.lo.z - box.hi.x + ray.c_zx > 0)) {
- return false;
- }
-
- time = (box.hi.x - ray.m_origin.x) * ray.m_invDirection.x;
- float t2 = (box.hi.z - ray.m_origin.z) * ray.m_invDirection.z;
- if (t2 > time) {
- time = t2;
- }
-
- return true;
- }
-
-
- case Ray::MOP:
- {
- if((ray.m_origin.y < box.lo.y) || (ray.m_origin.y > box.hi.y)
- || (ray.m_origin.x < box.lo.x) || (ray.m_origin.z > box.hi.z)
- || (ray.kbyi * box.lo.x - box.lo.z + ray.c_xz < 0)
- || (ray.ibyk * box.hi.z - box.hi.x + ray.c_zx > 0)) {
- return false;
- }
-
- time = (box.hi.x - ray.m_origin.x) * ray.m_invDirection.x;
- float t2 = (box.lo.z - ray.m_origin.z) * ray.m_invDirection.z;
- if (t2 > time) {
- time = t2;
- }
-
- return true;
- }
-
- case Ray::POM:
- {
- if((ray.m_origin.y < box.lo.y) || (ray.m_origin.y > box.hi.y)
- || (ray.m_origin.x > box.hi.x) || (ray.m_origin.z < box.lo.z)
- || (ray.kbyi * box.hi.x - box.hi.z + ray.c_xz > 0)
- || (ray.ibyk * box.lo.z - box.lo.x + ray.c_zx < 0)) {
- return false;
- }
-
- time = (box.lo.x - ray.m_origin.x) * ray.m_invDirection.x;
- float t2 = (box.hi.z - ray.m_origin.z) * ray.m_invDirection.z;
- if (t2 > time) {
- time = t2;
- }
-
- return true;
- }
-
-
- case Ray::POP:
- {
- if((ray.m_origin.y < box.lo.y) || (ray.m_origin.y > box.hi.y)
- || (ray.m_origin.x > box.hi.x) || (ray.m_origin.z > box.hi.z)
- || (ray.kbyi * box.hi.x - box.lo.z + ray.c_xz < 0)
- || (ray.ibyk * box.hi.z - box.lo.x + ray.c_zx < 0)) {
- return false;
- }
-
- time = (box.lo.x - ray.m_origin.x) * ray.m_invDirection.x;
- float t2 = (box.lo.z - ray.m_origin.z) * ray.m_invDirection.z;
- if (t2 > time) {
- time = t2;
- }
-
- return true;
- }
-
- case Ray::MMO:
- {
- if((ray.m_origin.z < box.lo.z) || (ray.m_origin.z > box.hi.z)
- || (ray.m_origin.x < box.lo.x) || (ray.m_origin.y < box.lo.y)
- || (ray.jbyi * box.lo.x - box.hi.y + ray.c_xy > 0)
- || (ray.ibyj * box.lo.y - box.hi.x + ray.c_yx > 0)) {
- return false;
- }
-
- time = (box.hi.x - ray.m_origin.x) * ray.m_invDirection.x;
- float t1 = (box.hi.y - ray.m_origin.y) * ray.m_invDirection.y;
- if (t1 > time) {
- time = t1;
- }
-
- return true;
- }
-
- case Ray::MPO:
- {
- if((ray.m_origin.z < box.lo.z) || (ray.m_origin.z > box.hi.z)
- || (ray.m_origin.x < box.lo.x) || (ray.m_origin.y > box.hi.y)
- || (ray.jbyi * box.lo.x - box.lo.y + ray.c_xy < 0)
- || (ray.ibyj * box.hi.y - box.hi.x + ray.c_yx > 0)) {
- return false;
- }
-
- time = (box.hi.x - ray.m_origin.x) * ray.m_invDirection.x;
- float t1 = (box.lo.y - ray.m_origin.y) * ray.m_invDirection.y;
- if (t1 > time) {
- time = t1;
- }
-
- return true;
- }
-
-
- case Ray::PMO:
- {
- if((ray.m_origin.z < box.lo.z) || (ray.m_origin.z > box.hi.z)
- || (ray.m_origin.x > box.hi.x) || (ray.m_origin.y < box.lo.y)
- || (ray.jbyi * box.hi.x - box.hi.y + ray.c_xy > 0)
- || (ray.ibyj * box.lo.y - box.lo.x + ray.c_yx < 0)) {
- return false;
- }
-
- time = (box.lo.x - ray.m_origin.x) * ray.m_invDirection.x;
- float t1 = (box.hi.y - ray.m_origin.y) * ray.m_invDirection.y;
- if (t1 > time) {
- time = t1;
- }
-
- return true;
- }
-
- case Ray::PPO:
- {
- if((ray.m_origin.z < box.lo.z) || (ray.m_origin.z > box.hi.z)
- || (ray.m_origin.x > box.hi.x) || (ray.m_origin.y > box.hi.y)
- || (ray.jbyi * box.hi.x - box.lo.y + ray.c_xy < 0)
- || (ray.ibyj * box.hi.y - box.lo.x + ray.c_yx < 0)) {
- return false;
- }
-
- time = (box.lo.x - ray.m_origin.x) * ray.m_invDirection.x;
- float t1 = (box.lo.y - ray.m_origin.y) * ray.m_invDirection.y;
- if (t1 > time) {
- time = t1;
- }
-
- return true;
- }
-
-
- case Ray::MOO:
- {
- if((ray.m_origin.x < box.lo.x)
- || (ray.m_origin.y < box.lo.y) || (ray.m_origin.y > box.hi.y)
- || (ray.m_origin.z < box.lo.z) || (ray.m_origin.z > box.hi.z)) {
- return false;
+ switch (ray.classification) {
+ case Ray::MMM:
+ {
+ if ((ray.m_origin.x < box.lo.x) || (ray.m_origin.y < box.lo.y) || (ray.m_origin.z < box.lo.z)
+ || (ray.jbyi * box.lo.x - box.hi.y + ray.c_xy > 0)
+ || (ray.ibyj * box.lo.y - box.hi.x + ray.c_yx > 0)
+ || (ray.jbyk * box.lo.z - box.hi.y + ray.c_zy > 0)
+ || (ray.kbyj * box.lo.y - box.hi.z + ray.c_yz > 0)
+ || (ray.kbyi * box.lo.x - box.hi.z + ray.c_xz > 0)
+ || (ray.ibyk * box.lo.z - box.hi.x + ray.c_zx > 0)) {
+ return false;
+ }
+
+ // compute the intersection distance
+
+ time = (box.hi.x - ray.m_origin.x) * ray.m_invDirection.x;
+ float t1 = (box.hi.y - ray.m_origin.y) * ray.m_invDirection.y;
+ if (t1 > time) {
+ time = t1;
+ }
+
+ float t2 = (box.hi.z - ray.m_origin.z) * ray.m_invDirection.z;
+ if (t2 > time) {
+ time = t2;
+ }
+
+ return true;
+ }
+
+ case Ray::MMP:
+ {
+ if ((ray.m_origin.x < box.lo.x) || (ray.m_origin.y < box.lo.y) || (ray.m_origin.z > box.hi.z)
+ || (ray.jbyi * box.lo.x - box.hi.y + ray.c_xy > 0)
+ || (ray.ibyj * box.lo.y - box.hi.x + ray.c_yx > 0)
+ || (ray.jbyk * box.hi.z - box.hi.y + ray.c_zy > 0)
+ || (ray.kbyj * box.lo.y - box.lo.z + ray.c_yz < 0)
+ || (ray.kbyi * box.lo.x - box.lo.z + ray.c_xz < 0)
+ || (ray.ibyk * box.hi.z - box.hi.x + ray.c_zx > 0)) {
+ return false;
+ }
+
+ time = (box.hi.x - ray.m_origin.x) * ray.m_invDirection.x;
+ float t1 = (box.hi.y - ray.m_origin.y) * ray.m_invDirection.y;
+ if (t1 > time) {
+ time = t1;
+ }
+ float t2 = (box.lo.z - ray.m_origin.z) * ray.m_invDirection.z;
+ if (t2 > time) {
+ time = t2;
+ }
+
+ return true;
+ }
+
+ case Ray::MPM:
+ {
+ if ((ray.m_origin.x < box.lo.x) || (ray.m_origin.y > box.hi.y) || (ray.m_origin.z < box.lo.z)
+ || (ray.jbyi * box.lo.x - box.lo.y + ray.c_xy < 0)
+ || (ray.ibyj * box.hi.y - box.hi.x + ray.c_yx > 0)
+ || (ray.jbyk * box.lo.z - box.lo.y + ray.c_zy < 0)
+ || (ray.kbyj * box.hi.y - box.hi.z + ray.c_yz > 0)
+ || (ray.kbyi * box.lo.x - box.hi.z + ray.c_xz > 0)
+ || (ray.ibyk * box.lo.z - box.hi.x + ray.c_zx > 0)) {
+ return false;
+ }
+
+ time = (box.hi.x - ray.m_origin.x) * ray.m_invDirection.x;
+ float t1 = (box.lo.y - ray.m_origin.y) * ray.m_invDirection.y;
+ if (t1 > time) {
+ time = t1;
+ }
+ float t2 = (box.hi.z - ray.m_origin.z) * ray.m_invDirection.z;
+ if (t2 > time) {
+ time = t2;
+ }
+
+ return true;
+ }
+
+ case Ray::MPP:
+ {
+ if ((ray.m_origin.x < box.lo.x) || (ray.m_origin.y > box.hi.y) || (ray.m_origin.z > box.hi.z)
+ || (ray.jbyi * box.lo.x - box.lo.y + ray.c_xy < 0)
+ || (ray.ibyj * box.hi.y - box.hi.x + ray.c_yx > 0)
+ || (ray.jbyk * box.hi.z - box.lo.y + ray.c_zy < 0)
+ || (ray.kbyj * box.hi.y - box.lo.z + ray.c_yz < 0)
+ || (ray.kbyi * box.lo.x - box.lo.z + ray.c_xz < 0)
+ || (ray.ibyk * box.hi.z - box.hi.x + ray.c_zx > 0)) {
+ return false;
+ }
+
+ time = (box.hi.x - ray.m_origin.x) * ray.m_invDirection.x;
+ float t1 = (box.lo.y - ray.m_origin.y) * ray.m_invDirection.y;
+ if (t1 > time) {
+ time = t1;
+ }
+ float t2 = (box.lo.z - ray.m_origin.z) * ray.m_invDirection.z;
+ if (t2 > time) {
+ time = t2;
+ }
+
+ return true;
+ }
+
+ case Ray::PMM:
+ {
+ if ((ray.m_origin.x > box.hi.x) || (ray.m_origin.y < box.lo.y) || (ray.m_origin.z < box.lo.z)
+ || (ray.jbyi * box.hi.x - box.hi.y + ray.c_xy > 0)
+ || (ray.ibyj * box.lo.y - box.lo.x + ray.c_yx < 0)
+ || (ray.jbyk * box.lo.z - box.hi.y + ray.c_zy > 0)
+ || (ray.kbyj * box.lo.y - box.hi.z + ray.c_yz > 0)
+ || (ray.kbyi * box.hi.x - box.hi.z + ray.c_xz > 0)
+ || (ray.ibyk * box.lo.z - box.lo.x + ray.c_zx < 0)) {
+ return false;
+ }
+
+ time = (box.lo.x - ray.m_origin.x) * ray.m_invDirection.x;
+ float t1 = (box.hi.y - ray.m_origin.y) * ray.m_invDirection.y;
+ if (t1 > time) {
+ time = t1;
+ }
+ float t2 = (box.hi.z - ray.m_origin.z) * ray.m_invDirection.z;
+ if (t2 > time) {
+ time = t2;
+ }
+
+ return true;
+ }
+
+
+ case Ray::PMP:
+ {
+ if ((ray.m_origin.x > box.hi.x) || (ray.m_origin.y < box.lo.y) || (ray.m_origin.z > box.hi.z)
+ || (ray.jbyi * box.hi.x - box.hi.y + ray.c_xy > 0)
+ || (ray.ibyj * box.lo.y - box.lo.x + ray.c_yx < 0)
+ || (ray.jbyk * box.hi.z - box.hi.y + ray.c_zy > 0)
+ || (ray.kbyj * box.lo.y - box.lo.z + ray.c_yz < 0)
+ || (ray.kbyi * box.hi.x - box.lo.z + ray.c_xz < 0)
+ || (ray.ibyk * box.hi.z - box.lo.x + ray.c_zx < 0)) {
+ return false;
+ }
+
+ time = (box.lo.x - ray.m_origin.x) * ray.m_invDirection.x;
+ float t1 = (box.hi.y - ray.m_origin.y) * ray.m_invDirection.y;
+ if (t1 > time) {
+ time = t1;
+ }
+ float t2 = (box.lo.z - ray.m_origin.z) * ray.m_invDirection.z;
+ if (t2 > time) {
+ time = t2;
+ }
+
+ return true;
+ }
+
+ case Ray::PPM:
+ {
+ if ((ray.m_origin.x > box.hi.x) || (ray.m_origin.y > box.hi.y) || (ray.m_origin.z < box.lo.z)
+ || (ray.jbyi * box.hi.x - box.lo.y + ray.c_xy < 0)
+ || (ray.ibyj * box.hi.y - box.lo.x + ray.c_yx < 0)
+ || (ray.jbyk * box.lo.z - box.lo.y + ray.c_zy < 0)
+ || (ray.kbyj * box.hi.y - box.hi.z + ray.c_yz > 0)
+ || (ray.kbyi * box.hi.x - box.hi.z + ray.c_xz > 0)
+ || (ray.ibyk * box.lo.z - box.lo.x + ray.c_zx < 0)) {
+ return false;
+ }
+
+ time = (box.lo.x - ray.m_origin.x) * ray.m_invDirection.x;
+ float t1 = (box.lo.y - ray.m_origin.y) * ray.m_invDirection.y;
+ if (t1 > time) {
+ time = t1;
+ }
+ float t2 = (box.hi.z - ray.m_origin.z) * ray.m_invDirection.z;
+ if (t2 > time) {
+ time = t2;
+ }
+
+ return true;
+ }
+
+ case Ray::PPP:
+ {
+ if ((ray.m_origin.x > box.hi.x) || (ray.m_origin.y > box.hi.y) || (ray.m_origin.z > box.hi.z)
+ || (ray.jbyi * box.hi.x - box.lo.y + ray.c_xy < 0)
+ || (ray.ibyj * box.hi.y - box.lo.x + ray.c_yx < 0)
+ || (ray.jbyk * box.hi.z - box.lo.y + ray.c_zy < 0)
+ || (ray.kbyj * box.hi.y - box.lo.z + ray.c_yz < 0)
+ || (ray.kbyi * box.hi.x - box.lo.z + ray.c_xz < 0)
+ || (ray.ibyk * box.hi.z - box.lo.x + ray.c_zx < 0)) {
+ return false;
+ }
+
+ time = (box.lo.x - ray.m_origin.x) * ray.m_invDirection.x;
+ float t1 = (box.lo.y - ray.m_origin.y) * ray.m_invDirection.y;
+ if (t1 > time) {
+ time = t1;
+ }
+ float t2 = (box.lo.z - ray.m_origin.z) * ray.m_invDirection.z;
+ if (t2 > time) {
+ time = t2;
+ }
+
+ return true;
+ }
+
+ case Ray::OMM:
+ {
+ if((ray.m_origin.x < box.lo.x) || (ray.m_origin.x > box.hi.x)
+ || (ray.m_origin.y < box.lo.y) || (ray.m_origin.z < box.lo.z)
+ || (ray.jbyk * box.lo.z - box.hi.y + ray.c_zy > 0)
+ || (ray.kbyj * box.lo.y - box.hi.z + ray.c_yz > 0)) {
+ return false;
+ }
+
+ time = (box.hi.y - ray.m_origin.y) * ray.m_invDirection.y;
+ float t2 = (box.hi.z - ray.m_origin.z) * ray.m_invDirection.z;
+ if (t2 > time) {
+ time = t2;
+ }
+
+ return true;
+ }
+
+ case Ray::OMP:
+ {
+ if((ray.m_origin.x < box.lo.x) || (ray.m_origin.x > box.hi.x)
+ || (ray.m_origin.y < box.lo.y) || (ray.m_origin.z > box.hi.z)
+ || (ray.jbyk * box.hi.z - box.hi.y + ray.c_zy > 0)
+ || (ray.kbyj * box.lo.y - box.lo.z + ray.c_yz < 0)) {
+ return false;
+ }
+
+ time = (box.hi.y - ray.m_origin.y) * ray.m_invDirection.y;
+ float t2 = (box.lo.z - ray.m_origin.z) * ray.m_invDirection.z;
+ if (t2 > time) {
+ time = t2;
+ }
+
+ return true;
+ }
+
+ case Ray::OPM:
+ {
+ if((ray.m_origin.x < box.lo.x) || (ray.m_origin.x > box.hi.x)
+ || (ray.m_origin.y > box.hi.y) || (ray.m_origin.z < box.lo.z)
+ || (ray.jbyk * box.lo.z - box.lo.y + ray.c_zy < 0)
+ || (ray.kbyj * box.hi.y - box.hi.z + ray.c_yz > 0)) {
+ return false;
+ }
+
+ time = (box.lo.y - ray.m_origin.y) * ray.m_invDirection.y;
+ float t2 = (box.hi.z - ray.m_origin.z) * ray.m_invDirection.z;
+ if (t2 > time) {
+ time = t2;
+ }
+
+ return true;
+ }
+
+ case Ray::OPP:
+ {
+ if((ray.m_origin.x < box.lo.x) || (ray.m_origin.x > box.hi.x)
+ || (ray.m_origin.y > box.hi.y) || (ray.m_origin.z > box.hi.z)
+ || (ray.jbyk * box.hi.z - box.lo.y + ray.c_zy < 0)
+ || (ray.kbyj * box.hi.y - box.lo.z + ray.c_yz < 0)) {
+ return false;
+ }
+
+ time = (box.lo.y - ray.m_origin.y) * ray.m_invDirection.y;
+ float t2 = (box.lo.z - ray.m_origin.z) * ray.m_invDirection.z;
+ if (t2 > time) {
+ time = t2;
+ }
+
+ return true;
+ }
+
+
+ case Ray::MOM:
+ {
+ if((ray.m_origin.y < box.lo.y) || (ray.m_origin.y > box.hi.y)
+ || (ray.m_origin.x < box.lo.x) || (ray.m_origin.z < box.lo.z)
+ || (ray.kbyi * box.lo.x - box.hi.z + ray.c_xz > 0)
+ || (ray.ibyk * box.lo.z - box.hi.x + ray.c_zx > 0)) {
+ return false;
+ }
+
+ time = (box.hi.x - ray.m_origin.x) * ray.m_invDirection.x;
+ float t2 = (box.hi.z - ray.m_origin.z) * ray.m_invDirection.z;
+ if (t2 > time) {
+ time = t2;
+ }
+
+ return true;
+ }
+
+
+ case Ray::MOP:
+ {
+ if((ray.m_origin.y < box.lo.y) || (ray.m_origin.y > box.hi.y)
+ || (ray.m_origin.x < box.lo.x) || (ray.m_origin.z > box.hi.z)
+ || (ray.kbyi * box.lo.x - box.lo.z + ray.c_xz < 0)
+ || (ray.ibyk * box.hi.z - box.hi.x + ray.c_zx > 0)) {
+ return false;
+ }
+
+ time = (box.hi.x - ray.m_origin.x) * ray.m_invDirection.x;
+ float t2 = (box.lo.z - ray.m_origin.z) * ray.m_invDirection.z;
+ if (t2 > time) {
+ time = t2;
+ }
+
+ return true;
+ }
+
+ case Ray::POM:
+ {
+ if((ray.m_origin.y < box.lo.y) || (ray.m_origin.y > box.hi.y)
+ || (ray.m_origin.x > box.hi.x) || (ray.m_origin.z < box.lo.z)
+ || (ray.kbyi * box.hi.x - box.hi.z + ray.c_xz > 0)
+ || (ray.ibyk * box.lo.z - box.lo.x + ray.c_zx < 0)) {
+ return false;
+ }
+
+ time = (box.lo.x - ray.m_origin.x) * ray.m_invDirection.x;
+ float t2 = (box.hi.z - ray.m_origin.z) * ray.m_invDirection.z;
+ if (t2 > time) {
+ time = t2;
+ }
+
+ return true;
+ }
+
+
+ case Ray::POP:
+ {
+ if((ray.m_origin.y < box.lo.y) || (ray.m_origin.y > box.hi.y)
+ || (ray.m_origin.x > box.hi.x) || (ray.m_origin.z > box.hi.z)
+ || (ray.kbyi * box.hi.x - box.lo.z + ray.c_xz < 0)
+ || (ray.ibyk * box.hi.z - box.lo.x + ray.c_zx < 0)) {
+ return false;
+ }
+
+ time = (box.lo.x - ray.m_origin.x) * ray.m_invDirection.x;
+ float t2 = (box.lo.z - ray.m_origin.z) * ray.m_invDirection.z;
+ if (t2 > time) {
+ time = t2;
+ }
+
+ return true;
+ }
+
+ case Ray::MMO:
+ {
+ if((ray.m_origin.z < box.lo.z) || (ray.m_origin.z > box.hi.z)
+ || (ray.m_origin.x < box.lo.x) || (ray.m_origin.y < box.lo.y)
+ || (ray.jbyi * box.lo.x - box.hi.y + ray.c_xy > 0)
+ || (ray.ibyj * box.lo.y - box.hi.x + ray.c_yx > 0)) {
+ return false;
+ }
+
+ time = (box.hi.x - ray.m_origin.x) * ray.m_invDirection.x;
+ float t1 = (box.hi.y - ray.m_origin.y) * ray.m_invDirection.y;
+ if (t1 > time) {
+ time = t1;
+ }
+
+ return true;
+ }
+
+ case Ray::MPO:
+ {
+ if((ray.m_origin.z < box.lo.z) || (ray.m_origin.z > box.hi.z)
+ || (ray.m_origin.x < box.lo.x) || (ray.m_origin.y > box.hi.y)
+ || (ray.jbyi * box.lo.x - box.lo.y + ray.c_xy < 0)
+ || (ray.ibyj * box.hi.y - box.hi.x + ray.c_yx > 0)) {
+ return false;
+ }
+
+ time = (box.hi.x - ray.m_origin.x) * ray.m_invDirection.x;
+ float t1 = (box.lo.y - ray.m_origin.y) * ray.m_invDirection.y;
+ if (t1 > time) {
+ time = t1;
+ }
+
+ return true;
}
-
- time = (box.hi.x - ray.m_origin.x) * ray.m_invDirection.x;
- return true;
- }
-
- case Ray::POO:
- {
- if ((ray.m_origin.x > box.hi.x)
- || (ray.m_origin.y < box.lo.y) || (ray.m_origin.y > box.hi.y)
- || (ray.m_origin.z < box.lo.z) || (ray.m_origin.z > box.hi.z)) {
- return false;
+
+
+ case Ray::PMO:
+ {
+ if((ray.m_origin.z < box.lo.z) || (ray.m_origin.z > box.hi.z)
+ || (ray.m_origin.x > box.hi.x) || (ray.m_origin.y < box.lo.y)
+ || (ray.jbyi * box.hi.x - box.hi.y + ray.c_xy > 0)
+ || (ray.ibyj * box.lo.y - box.lo.x + ray.c_yx < 0)) {
+ return false;
+ }
+
+ time = (box.lo.x - ray.m_origin.x) * ray.m_invDirection.x;
+ float t1 = (box.hi.y - ray.m_origin.y) * ray.m_invDirection.y;
+ if (t1 > time) {
+ time = t1;
+ }
+
+ return true;
+ }
+
+ case Ray::PPO:
+ {
+ if((ray.m_origin.z < box.lo.z) || (ray.m_origin.z > box.hi.z)
+ || (ray.m_origin.x > box.hi.x) || (ray.m_origin.y > box.hi.y)
+ || (ray.jbyi * box.hi.x - box.lo.y + ray.c_xy < 0)
+ || (ray.ibyj * box.hi.y - box.lo.x + ray.c_yx < 0)) {
+ return false;
+ }
+
+ time = (box.lo.x - ray.m_origin.x) * ray.m_invDirection.x;
+ float t1 = (box.lo.y - ray.m_origin.y) * ray.m_invDirection.y;
+ if (t1 > time) {
+ time = t1;
+ }
+
+ return true;
+ }
+
+
+ case Ray::MOO:
+ {
+ if((ray.m_origin.x < box.lo.x)
+ || (ray.m_origin.y < box.lo.y) || (ray.m_origin.y > box.hi.y)
+ || (ray.m_origin.z < box.lo.z) || (ray.m_origin.z > box.hi.z)) {
+ return false;
+ }
+
+ time = (box.hi.x - ray.m_origin.x) * ray.m_invDirection.x;
+ return true;
+ }
+
+ case Ray::POO:
+ {
+ if ((ray.m_origin.x > box.hi.x)
+ || (ray.m_origin.y < box.lo.y) || (ray.m_origin.y > box.hi.y)
+ || (ray.m_origin.z < box.lo.z) || (ray.m_origin.z > box.hi.z)) {
+ return false;
+ }
+
+ time = (box.lo.x - ray.m_origin.x) * ray.m_invDirection.x;
+ return true;
+ }
+
+ case Ray::OMO:
+ {
+ if ((ray.m_origin.y < box.lo.y)
+ || (ray.m_origin.x < box.lo.x) || (ray.m_origin.x > box.hi.x)
+ || (ray.m_origin.z < box.lo.z) || (ray.m_origin.z > box.hi.z)) {
+ return false;
+ }
+
+ time = (box.hi.y - ray.m_origin.y) * ray.m_invDirection.y;
+ return true;
}
- time = (box.lo.x - ray.m_origin.x) * ray.m_invDirection.x;
- return true;
- }
-
- case Ray::OMO:
- {
- if ((ray.m_origin.y < box.lo.y)
- || (ray.m_origin.x < box.lo.x) || (ray.m_origin.x > box.hi.x)
- || (ray.m_origin.z < box.lo.z) || (ray.m_origin.z > box.hi.z)) {
- return false;
- }
-
- time = (box.hi.y - ray.m_origin.y) * ray.m_invDirection.y;
- return true;
- }
-
- case Ray::OPO:
- {
- if ((ray.m_origin.y > box.hi.y)
- || (ray.m_origin.x < box.lo.x) || (ray.m_origin.x > box.hi.x)
- || (ray.m_origin.z < box.lo.z) || (ray.m_origin.z > box.hi.z)) {
- return false;
+ case Ray::OPO:
+ {
+ if ((ray.m_origin.y > box.hi.y)
+ || (ray.m_origin.x < box.lo.x) || (ray.m_origin.x > box.hi.x)
+ || (ray.m_origin.z < box.lo.z) || (ray.m_origin.z > box.hi.z)) {
+ return false;
+ }
+
+ time = (box.lo.y - ray.m_origin.y) * ray.m_invDirection.y;
+ return true;
}
- time = (box.lo.y - ray.m_origin.y) * ray.m_invDirection.y;
- return true;
- }
+ case Ray::OOM:
+ {
+ if ((ray.m_origin.z < box.lo.z)
+ || (ray.m_origin.x < box.lo.x) || (ray.m_origin.x > box.hi.x)
+ || (ray.m_origin.y < box.lo.y) || (ray.m_origin.y > box.hi.y)) {
+ return false;
+ }
- case Ray::OOM:
- {
- if ((ray.m_origin.z < box.lo.z)
- || (ray.m_origin.x < box.lo.x) || (ray.m_origin.x > box.hi.x)
- || (ray.m_origin.y < box.lo.y) || (ray.m_origin.y > box.hi.y)) {
- return false;
+ time = (box.hi.z - ray.m_origin.z) * ray.m_invDirection.z;
+ return true;
}
- time = (box.hi.z - ray.m_origin.z) * ray.m_invDirection.z;
- return true;
- }
-
- case Ray::OOP:
- {
- if ((ray.m_origin.z > box.hi.z)
- || (ray.m_origin.x < box.lo.x) || (ray.m_origin.x > box.hi.x)
- || (ray.m_origin.y < box.lo.y) || (ray.m_origin.y > box.hi.y)) {
- return false;
- }
+ case Ray::OOP:
+ {
+ if ((ray.m_origin.z > box.hi.z)
+ || (ray.m_origin.x < box.lo.x) || (ray.m_origin.x > box.hi.x)
+ || (ray.m_origin.y < box.lo.y) || (ray.m_origin.y > box.hi.y)) {
+ return false;
+ }
- time = (box.lo.z - ray.m_origin.z) * ray.m_invDirection.z;
- return true;
- }
- }
+ time = (box.lo.z - ray.m_origin.z) * ray.m_invDirection.z;
+ return true;
+ }
+ }
- return false;
+ return false;
}
#ifdef _MSC_VER
-// Turn off fast floating-point optimizations
+ // Turn off fast floating-point optimizations
#pragma float_control( pop )
#endif
diff --git a/dep/g3dlite/source/Line.cpp b/dep/g3dlite/source/Line.cpp
index 195ae7197f2..2ced4a78bd8 100644
--- a/dep/g3dlite/source/Line.cpp
+++ b/dep/g3dlite/source/Line.cpp
@@ -33,19 +33,19 @@ Vector3 Line::intersection(const Plane& plane) const {
Line::Line(class BinaryInput& b) {
- deserialize(b);
+ deserialize(b);
}
void Line::serialize(class BinaryOutput& b) const {
- _point.serialize(b);
- _direction.serialize(b);
+ _point.serialize(b);
+ _direction.serialize(b);
}
void Line::deserialize(class BinaryInput& b) {
- _point.deserialize(b);
- _direction.deserialize(b);
+ _point.deserialize(b);
+ _direction.deserialize(b);
}
@@ -80,7 +80,7 @@ Vector3 Line::closestPoint(const Line& B, float& minDist) const {
float t1 = R.dot(U2);
- minDist = abs(P21.dot(M)) / sqrt(m2);
+ minDist = (float)abs(P21.dot(M)) / sqrt(m2);
return P1 + t1 * U1;
}
diff --git a/dep/g3dlite/source/LineSegment.cpp b/dep/g3dlite/source/LineSegment.cpp
index 754600ad554..63a28fce6e6 100644
--- a/dep/g3dlite/source/LineSegment.cpp
+++ b/dep/g3dlite/source/LineSegment.cpp
@@ -80,19 +80,19 @@ bool LineSegment::intersectsSolidSphere(const class Sphere& s) const {
LineSegment::LineSegment(class BinaryInput& b) {
- deserialize(b);
+ deserialize(b);
}
void LineSegment::serialize(class BinaryOutput& b) const {
- _point.serialize(b);
- direction.serialize(b);
+ _point.serialize(b);
+ direction.serialize(b);
}
void LineSegment::deserialize(class BinaryInput& b) {
- _point.deserialize(b);
- direction.deserialize(b);
+ _point.deserialize(b);
+ direction.deserialize(b);
}
diff --git a/dep/g3dlite/source/Log.cpp b/dep/g3dlite/source/Log.cpp
index f437351cfbd..c113b0b0f79 100644
--- a/dep/g3dlite/source/Log.cpp
+++ b/dep/g3dlite/source/Log.cpp
@@ -14,7 +14,7 @@
#include "G3D/FileSystem.h"
#include <time.h>
-#ifdef G3D_WIN32
+#ifdef G3D_WINDOWS
#include <imagehlp.h>
#else
#include <stdarg.h>
@@ -23,16 +23,16 @@
namespace G3D {
void logPrintf(const char* fmt, ...) {
- va_list arg_list;
- va_start(arg_list, fmt);
+ va_list arg_list;
+ va_start(arg_list, fmt);
Log::common()->vprintf(fmt, arg_list);
va_end(arg_list);
}
void logLazyPrintf(const char* fmt, ...) {
- va_list arg_list;
- va_start(arg_list, fmt);
+ va_list arg_list;
+ va_start(arg_list, fmt);
Log::common()->lazyvprintf(fmt, arg_list);
va_end(arg_list);
}
@@ -53,7 +53,7 @@ Log::Log(const std::string& filename, int stripFromStackBottom) :
std::string logName = base + ((ext != "") ? ("." + ext) : "");
// Write time is greater than 1ms. This may be a network drive.... try another file.
- #ifdef G3D_WIN32
+ #ifdef G3D_WINDOWS
logName = std::string(std::getenv("TEMP")) + logName;
#else
logName = std::string("/tmp/") + logName;
@@ -86,7 +86,9 @@ Log::~Log() {
Log::commonLog = NULL;
}
- fclose(logFile);
+ if (logFile) {
+ FileSystem::fclose(logFile);
+ }
}
diff --git a/dep/g3dlite/source/Matrix.cpp b/dep/g3dlite/source/Matrix.cpp
index 7a668e59e2c..77188f47e05 100644
--- a/dep/g3dlite/source/Matrix.cpp
+++ b/dep/g3dlite/source/Matrix.cpp
@@ -43,21 +43,21 @@ void Matrix::serialize(TextOutput& t) const {
std::string Matrix::toString(const std::string& name) const {
- std::string s;
+ std::string s;
if (name != "") {
s += format("%s = \n", name.c_str());
}
- s += "[";
+ s += "[";
for (int r = 0; r < rows(); ++r) {
for (int c = 0; c < cols(); ++c) {
double v = impl->get(r, c);
- if (::fabs(v) < 0.00001) {
- // Don't print "negative zero"
+ if (::fabs(v) < 0.00001) {
+ // Don't print "negative zero"
s += format("% 10.04g", 0.0);
- } else if (v == iRound(v)) {
+ } else if (v == iRound(v)) {
// Print integers nicely
s += format("% 10.04g", v);
} else {
@@ -68,20 +68,20 @@ std::string Matrix::toString(const std::string& name) const {
s += ",";
} else if (r < rows() - 1) {
s += ";\n ";
- } else {
- s += "]\n";
- }
+ } else {
+ s += "]\n";
+ }
}
}
- return s;
+ return s;
}
#define INPLACE(OP)\
ImplRef A = impl;\
\
- if (! A.isLastReference()) {\
- impl = new Impl(A->R, A->C);\
+ if (! A.unique()) {\
+ impl.reset(new Impl(A->R, A->C));\
}\
\
A->OP(B, *impl);
@@ -157,9 +157,9 @@ Matrix Matrix::fromDiagonal(const Matrix& d) {
}
void Matrix::set(int r, int c, T v) {
- if (! impl.isLastReference()) {
+ if (! impl.unique()) {
// Copy the data before mutating; this object is shared
- impl = new Impl(*impl);
+ impl.reset(new Impl(*impl));
}
impl->set(r, c, v);
}
@@ -174,9 +174,9 @@ void Matrix::setRow(int r, const Matrix& vec) {
debugAssert(r >= 0);
debugAssert(r < rows());
- if (! impl.isLastReference()) {
+ if (! impl.unique()) {
// Copy the data before mutating; this object is shared
- impl = new Impl(*impl);
+ impl.reset(new Impl(*impl));
}
impl->setRow(r, vec.impl->data);
}
@@ -192,9 +192,9 @@ void Matrix::setCol(int c, const Matrix& vec) {
debugAssert(c < cols());
- if (! impl.isLastReference()) {
+ if (! impl.unique()) {
// Copy the data before mutating; this object is shared
- impl = new Impl(*impl);
+ impl.reset(new Impl(*impl));
}
impl->setCol(c, vec.impl->data);
}
@@ -272,7 +272,7 @@ Matrix Matrix::identity(int N) {
// Implement an explicit-output unary method by trampolining to the impl
#define TRAMPOLINE_EXPLICIT_1(method)\
void Matrix::method(Matrix& out) const {\
- if ((out.impl == impl) && impl.isLastReference()) {\
+ if ((out.impl == impl) && impl.unique()) {\
impl->method(*out.impl);\
} else {\
out = this->method();\
@@ -289,8 +289,8 @@ TRAMPOLINE_EXPLICIT_1(arraySin)
void Matrix::mulRow(int r, const T& v) {
debugAssert(r >= 0 && r < rows());
- if (! impl.isLastReference()) {
- impl = new Impl(*impl);
+ if (! impl.unique()) {
+ impl.reset(new Impl(*impl));
}
impl->mulRow(r, v);
@@ -298,7 +298,7 @@ void Matrix::mulRow(int r, const T& v) {
void Matrix::transpose(Matrix& out) const {
- if ((out.impl == impl) && impl.isLastReference() && (impl->R == impl->C)) {
+ if ((out.impl == impl) && impl.unique() && (impl->R == impl->C)) {
// In place
impl->transpose(*out.impl);
} else {
@@ -369,8 +369,8 @@ void Matrix::swapRows(int r0, int r1) {
return;
}
- if (! impl.isLastReference()) {
- impl = new Impl(*impl);
+ if (! impl.unique()) {
+ impl.reset(new Impl(*impl));
}
impl->swapRows(r0, r1);
@@ -385,8 +385,8 @@ void Matrix::swapAndNegateCols(int c0, int c1) {
return;
}
- if (! impl.isLastReference()) {
- impl = new Impl(*impl);
+ if (! impl.unique()) {
+ impl.reset(new Impl(*impl));
}
impl->swapAndNegateCols(c0, c1);
@@ -432,15 +432,15 @@ void Matrix::svd(Matrix& U, Array<T>& d, Matrix& V, bool sort) const {
int C = cols();
// Make sure we don't overwrite a shared matrix
- if (! V.impl.isLastReference()) {
+ if (! V.impl.unique()) {
V = Matrix::zero(C, C);
} else {
V.impl->setSize(C, C);
}
- if (&U != this || ! impl.isLastReference()) {
+ if (&U != this || ! impl.unique()) {
// Make a copy of this for in-place SVD
- U.impl = new Impl(*impl);
+ U.impl.reset(new Impl(*impl));
}
d.resize(C);
@@ -746,7 +746,7 @@ void Matrix::Impl::inverseViaAdjoint(Impl& out) const {
det += elt[0][r] * out.elt[r][0];
}
- out.div(Matrix::T(det), out);
+ out.div(Matrix::T(det), out);
}
@@ -848,7 +848,7 @@ Matrix::T Matrix::Impl::determinant() const {
float cofactor10 = elt[1][2] * elt[2][0] - elt[1][0] * elt[2][2];
float cofactor20 = elt[1][0] * elt[2][1] - elt[1][1] * elt[2][0];
- return Matrix::T(
+ return Matrix::T(
elt[0][0] * cofactor00 +
elt[0][1] * cofactor10 +
elt[0][2] * cofactor20);
@@ -896,10 +896,11 @@ Matrix Matrix::pseudoInverse(float tolerance) const {
Public function for testing purposes only. Use pseudoInverse(), as it contains optimizations for
nonsingular matrices with at least one small (<5) dimension.
*/
+// See http://en.wikipedia.org/wiki/Moore%E2%80%93Penrose_pseudoinverse
Matrix Matrix::svdPseudoInverse(float tolerance) const {
- if (cols() > rows()) {
- return transpose().svdPseudoInverse(tolerance).transpose();
- }
+ if (cols() > rows()) {
+ return transpose().svdPseudoInverse(tolerance).transpose();
+ }
// Matrices from SVD
Matrix U, V;
@@ -907,32 +908,32 @@ Matrix Matrix::svdPseudoInverse(float tolerance) const {
// Diagonal elements
Array<T> d;
- svd(U, d, V);
+ svd(U, d, V);
if (rows() == 1) {
d.resize(1, false);
}
- if (tolerance < 0) {
- // TODO: Should be eps(d[0]), which is the largest diagonal
- tolerance = G3D::max(rows(), cols()) * 0.0001f;
- }
-
- Matrix X;
-
- int r = 0;
- for (int i = 0; i < d.size(); ++i) {
- if (d[i] > tolerance) {
- d[i] = Matrix::T(1) / d[i];
- ++r;
- }
- }
+ if (tolerance < 0) {
+ // TODO: Should be eps(d[0]), which is the largest diagonal
+ tolerance = G3D::max(rows(), cols()) * 0.0001f;
+ }
- if (r == 0) {
- // There were no non-zero elements
- X = zero(cols(), rows());
- } else {
- // Use the first r columns
+ Matrix X;
+
+ int r = 0;
+ for (int i = 0; i < d.size(); ++i) {
+ if (d[i] > tolerance) {
+ d[i] = Matrix::T(1) / d[i];
+ ++r;
+ }
+ }
+
+ if (r == 0) {
+ // There were no non-zero elements
+ X = zero(cols(), rows());
+ } else {
+ // Use the first r columns
// Test code (the rest is below)
/*
@@ -1003,7 +1004,8 @@ Matrix Matrix::svdPseudoInverse(float tolerance) const {
debugAssert(n < 0.0001);
*/
}
- return X;
+
+ return X;
}
// Computes pseudoinverse for a vector
@@ -1426,7 +1428,7 @@ void Matrix::Impl::inverseInPlaceGaussJordan() {
elt[col][col] = 1.0;
for (int k = 0; k < R; ++k) {
- elt[col][k] *= Matrix::T(pivotInverse);
+ elt[col][k] *= Matrix::T(pivotInverse);
}
// Reduce all rows
@@ -1438,7 +1440,7 @@ void Matrix::Impl::inverseInPlaceGaussJordan() {
elt[r][col] = 0.0;
for (int k = 0; k < R; ++k) {
- elt[r][k] -= Matrix::T(elt[col][k] * oldValue);
+ elt[r][k] -= Matrix::T(elt[col][k] * oldValue);
}
}
}
@@ -1537,13 +1539,12 @@ const char* Matrix::svdCore(float** U, int rows, int cols, float* D, float** V)
f = (double)U[i][i];
- // TODO: what is this 2-arg sign function?
- g = -SIGN(sqrt(s), f);
+ g = -sign(f)*(sqrt(s));
h = f * g - s;
U[i][i] = (float)(f - g);
if (i != cols - 1) {
- for (j = l; j < cols; j++) {
+ for (j = l; j < cols; ++j) {
for (s = 0.0, k = i; k < rows; ++k) {
s += ((double)U[k][i] * (double)U[k][j]);
@@ -1610,13 +1611,13 @@ const char* Matrix::svdCore(float** U, int rows, int cols, float* D, float** V)
for (i = cols - 1; i >= 0; --i) {
if (i < cols - 1) {
if (g) {
- for (j = l; j < cols; j++) {
+ for (j = l; j < cols; ++j) {
V[j][i] = (float)(((double)U[i][j] / (double)U[i][l]) / g);
}
// double division to avoid underflow
for (j = l; j < cols; ++j) {
- for (s = 0.0, k = l; k < cols; k++) {
+ for (s = 0.0, k = l; k < cols; ++k) {
s += ((double)U[i][k] * (double)V[k][j]);
}
@@ -1778,7 +1779,7 @@ const char* Matrix::svdCore(float** U, int rows, int cols, float* D, float** V)
}
f = (c * g) + (s * y);
x = (c * y) - (s * g);
- for (jj = 0; jj < rows; jj++) {
+ for (jj = 0; jj < rows; ++jj) {
y = (double)U[jj][j];
z = (double)U[jj][i];
U[jj][j] = (float)(y * c + z * s);
diff --git a/dep/g3dlite/source/Matrix3.cpp b/dep/g3dlite/source/Matrix3.cpp
index 7e4de99621a..2f704c8f87b 100644
--- a/dep/g3dlite/source/Matrix3.cpp
+++ b/dep/g3dlite/source/Matrix3.cpp
@@ -6,9 +6,9 @@
@author Morgan McGuire, graphics3d.com
@created 2001-06-02
- @edited 2009-11-15
+ @edited 2010-08-15
- Copyright 2000-2009, Morgan McGuire.
+ Copyright 2000-2012, Morgan McGuire.
All rights reserved.
*/
@@ -32,7 +32,12 @@ Matrix3::Matrix3(const Any& any) {
if (any.nameEquals("Matrix3::fromAxisAngle")) {
any.verifySize(2);
- *this = Matrix3::fromAxisAngle(any[0], any[1].number());
+ *this = fromAxisAngle(Vector3(any[0]), any[1].floatValue());
+ } else if (any.nameEquals("Matrix3::diagonal")) {
+ any.verifySize(3);
+ *this = diagonal(any[0], any[1], any[2]);
+ } else if (any.nameEquals("Matrix3::identity")) {
+ *this = identity();
} else {
any.verifySize(9);
@@ -45,7 +50,7 @@ Matrix3::Matrix3(const Any& any) {
}
-Matrix3::operator Any() const {
+Any Matrix3::toAny() const {
Any any(Any::ARRAY, "Matrix3");
any.resize(9);
for (int r = 0; r < 3; ++r) {
@@ -116,7 +121,7 @@ bool Matrix3::isOrthonormal() const {
//----------------------------------------------------------------------------
Matrix3::Matrix3(const Quat& _q) {
// Implementation from Watt and Watt, pg 362
- // See also http://www.flipcode.com/documents/matrfaq.html#Q54
+ // See also http://www.flipcode.com/documents/matrfaq.html#Q54
Quat q = _q;
q.unitize();
float xx = 2.0f * q.x * q.x;
@@ -226,8 +231,8 @@ void Matrix3::setRow(int iRow, const Vector3 &vector) {
//----------------------------------------------------------------------------
bool Matrix3::operator== (const Matrix3& rkMatrix) const {
- for (int iRow = 0; iRow < 3; iRow++) {
- for (int iCol = 0; iCol < 3; iCol++) {
+ for (int iRow = 0; iRow < 3; ++iRow) {
+ for (int iCol = 0; iCol < 3; ++iCol) {
if ( elt[iRow][iCol] != rkMatrix.elt[iRow][iCol] )
return false;
}
@@ -245,8 +250,8 @@ bool Matrix3::operator!= (const Matrix3& rkMatrix) const {
Matrix3 Matrix3::operator+ (const Matrix3& rkMatrix) const {
Matrix3 kSum;
- for (int iRow = 0; iRow < 3; iRow++) {
- for (int iCol = 0; iCol < 3; iCol++) {
+ for (int iRow = 0; iRow < 3; ++iRow) {
+ for (int iCol = 0; iCol < 3; ++iCol) {
kSum.elt[iRow][iCol] = elt[iRow][iCol] +
rkMatrix.elt[iRow][iCol];
}
@@ -259,8 +264,8 @@ Matrix3 Matrix3::operator+ (const Matrix3& rkMatrix) const {
Matrix3 Matrix3::operator- (const Matrix3& rkMatrix) const {
Matrix3 kDiff;
- for (int iRow = 0; iRow < 3; iRow++) {
- for (int iCol = 0; iCol < 3; iCol++) {
+ for (int iRow = 0; iRow < 3; ++iRow) {
+ for (int iCol = 0; iCol < 3; ++iCol) {
kDiff.elt[iRow][iCol] = elt[iRow][iCol] -
rkMatrix.elt[iRow][iCol];
}
@@ -273,8 +278,8 @@ Matrix3 Matrix3::operator- (const Matrix3& rkMatrix) const {
Matrix3 Matrix3::operator* (const Matrix3& rkMatrix) const {
Matrix3 kProd;
- for (int iRow = 0; iRow < 3; iRow++) {
- for (int iCol = 0; iCol < 3; iCol++) {
+ for (int iRow = 0; iRow < 3; ++iRow) {
+ for (int iCol = 0; iCol < 3; ++iCol) {
kProd.elt[iRow][iCol] =
elt[iRow][0] * rkMatrix.elt[0][iCol] +
elt[iRow][1] * rkMatrix.elt[1][iCol] +
@@ -286,8 +291,8 @@ Matrix3 Matrix3::operator* (const Matrix3& rkMatrix) const {
}
Matrix3& Matrix3::operator+= (const Matrix3& rkMatrix) {
- for (int iRow = 0; iRow < 3; iRow++) {
- for (int iCol = 0; iCol < 3; iCol++) {
+ for (int iRow = 0; iRow < 3; ++iRow) {
+ for (int iCol = 0; iCol < 3; ++iCol) {
elt[iRow][iCol] = elt[iRow][iCol] + rkMatrix.elt[iRow][iCol];
}
}
@@ -296,8 +301,8 @@ Matrix3& Matrix3::operator+= (const Matrix3& rkMatrix) {
}
Matrix3& Matrix3::operator-= (const Matrix3& rkMatrix) {
- for (int iRow = 0; iRow < 3; iRow++) {
- for (int iCol = 0; iCol < 3; iCol++) {
+ for (int iRow = 0; iRow < 3; ++iRow) {
+ for (int iCol = 0; iCol < 3; ++iCol) {
elt[iRow][iCol] = elt[iRow][iCol] - rkMatrix.elt[iRow][iCol];
}
}
@@ -307,8 +312,8 @@ Matrix3& Matrix3::operator-= (const Matrix3& rkMatrix) {
Matrix3& Matrix3::operator*= (const Matrix3& rkMatrix) {
Matrix3 mulMat;
- for (int iRow = 0; iRow < 3; iRow++) {
- for (int iCol = 0; iCol < 3; iCol++) {
+ for (int iRow = 0; iRow < 3; ++iRow) {
+ for (int iCol = 0; iCol < 3; ++iCol) {
mulMat.elt[iRow][iCol] =
elt[iRow][0] * rkMatrix.elt[0][iCol] +
elt[iRow][1] * rkMatrix.elt[1][iCol] +
@@ -324,8 +329,8 @@ Matrix3& Matrix3::operator*= (const Matrix3& rkMatrix) {
Matrix3 Matrix3::operator- () const {
Matrix3 kNeg;
- for (int iRow = 0; iRow < 3; iRow++) {
- for (int iCol = 0; iCol < 3; iCol++) {
+ for (int iRow = 0; iRow < 3; ++iRow) {
+ for (int iCol = 0; iCol < 3; ++iCol) {
kNeg[iRow][iCol] = -elt[iRow][iCol];
}
}
@@ -337,8 +342,8 @@ Matrix3 Matrix3::operator- () const {
Matrix3 Matrix3::operator* (float fScalar) const {
Matrix3 kProd;
- for (int iRow = 0; iRow < 3; iRow++) {
- for (int iCol = 0; iCol < 3; iCol++) {
+ for (int iRow = 0; iRow < 3; ++iRow) {
+ for (int iCol = 0; iCol < 3; ++iCol) {
kProd[iRow][iCol] = fScalar * elt[iRow][iCol];
}
}
@@ -352,8 +357,8 @@ Matrix3& Matrix3::operator/= (float fScalar) {
Matrix3& Matrix3::operator*= (float fScalar) {
- for (int iRow = 0; iRow < 3; iRow++) {
- for (int iCol = 0; iCol < 3; iCol++) {
+ for (int iRow = 0; iRow < 3; ++iRow) {
+ for (int iCol = 0; iCol < 3; ++iCol) {
elt[iRow][iCol] *= fScalar;
}
}
@@ -365,9 +370,9 @@ Matrix3& Matrix3::operator*= (float fScalar) {
Matrix3 operator* (double fScalar, const Matrix3& rkMatrix) {
Matrix3 kProd;
- for (int iRow = 0; iRow < 3; iRow++) {
- for (int iCol = 0; iCol < 3; iCol++) {
- kProd[iRow][iCol] = fScalar * rkMatrix.elt[iRow][iCol];
+ for (int iRow = 0; iRow < 3; ++iRow) {
+ for (int iCol = 0; iCol < 3; ++iCol) {
+ kProd[iRow][iCol] = (float)fScalar * rkMatrix.elt[iRow][iCol];
}
}
@@ -386,8 +391,8 @@ Matrix3 operator* (int fScalar, const Matrix3& rkMatrix) {
Matrix3 Matrix3::transpose () const {
Matrix3 kTranspose;
- for (int iRow = 0; iRow < 3; iRow++) {
- for (int iCol = 0; iCol < 3; iCol++) {
+ for (int iRow = 0; iRow < 3; ++iRow) {
+ for (int iCol = 0; iCol < 3; ++iCol) {
kTranspose[iRow][iCol] = elt[iCol][iRow];
}
}
@@ -427,10 +432,10 @@ bool Matrix3::inverse (Matrix3& rkInverse, float fTolerance) const {
if ( G3D::abs(fDet) <= fTolerance )
return false;
- float fInvDet = 1.0 / fDet;
+ float fInvDet = 1.0f / fDet;
- for (int iRow = 0; iRow < 3; iRow++) {
- for (int iCol = 0; iCol < 3; iCol++)
+ for (int iRow = 0; iRow < 3; ++iRow) {
+ for (int iCol = 0; iCol < 3; ++iCol)
rkInverse[iRow][iCol] *= fInvDet;
}
@@ -473,13 +478,13 @@ void Matrix3::bidiagonalize (Matrix3& kA, Matrix3& kL,
kA[2][0] * kA[2][0]);
if ( fLength > 0.0 ) {
- fSign = (kA[0][0] > 0.0 ? 1.0 : -1.0);
- fT1 = kA[0][0] + fSign * fLength;
- fInvT1 = 1.0 / fT1;
+ fSign = (kA[0][0] > 0.0 ? 1.0f : -1.0f);
+ fT1 = (float)kA[0][0] + fSign * fLength;
+ fInvT1 = 1.0f / fT1;
afV[1] = kA[1][0] * fInvT1;
afV[2] = kA[2][0] * fInvT1;
- fT2 = -2.0 / (1.0 + afV[1] * afV[1] + afV[2] * afV[2]);
+ fT2 = -2.0f / (1.0f + afV[1] * afV[1] + afV[2] * afV[2]);
afW[0] = fT2 * (kA[0][0] + kA[1][0] * afV[1] + kA[2][0] * afV[2]);
afW[1] = fT2 * (kA[0][1] + kA[1][1] * afV[1] + kA[2][1] * afV[2]);
afW[2] = fT2 * (kA[0][2] + kA[1][2] * afV[1] + kA[2][2] * afV[2]);
@@ -491,12 +496,12 @@ void Matrix3::bidiagonalize (Matrix3& kA, Matrix3& kL,
kA[2][1] += afV[2] * afW[1];
kA[2][2] += afV[2] * afW[2];
- kL[0][0] = 1.0 + fT2;
+ kL[0][0] = 1.0f + fT2;
kL[0][1] = kL[1][0] = fT2 * afV[1];
kL[0][2] = kL[2][0] = fT2 * afV[2];
- kL[1][1] = 1.0 + fT2 * afV[1] * afV[1];
+ kL[1][1] = 1.0f + fT2 * afV[1] * afV[1];
kL[1][2] = kL[2][1] = fT2 * afV[1] * afV[2];
- kL[2][2] = 1.0 + fT2 * afV[2] * afV[2];
+ kL[2][2] = 1.0f + fT2 * afV[2] * afV[2];
bIdentity = false;
} else {
kL = Matrix3::identity();
@@ -507,11 +512,11 @@ void Matrix3::bidiagonalize (Matrix3& kA, Matrix3& kL,
fLength = sqrt(kA[0][1] * kA[0][1] + kA[0][2] * kA[0][2]);
if ( fLength > 0.0 ) {
- fSign = (kA[0][1] > 0.0 ? 1.0 : -1.0);
+ fSign = (kA[0][1] > 0.0 ? 1.0f : -1.0f);
fT1 = kA[0][1] + fSign * fLength;
afV[2] = kA[0][2] / fT1;
- fT2 = -2.0 / (1.0 + afV[2] * afV[2]);
+ fT2 = -2.0f / (1.0f + afV[2] * afV[2]);
afW[0] = fT2 * (kA[0][1] + kA[0][2] * afV[2]);
afW[1] = fT2 * (kA[1][1] + kA[1][2] * afV[2]);
afW[2] = fT2 * (kA[2][1] + kA[2][2] * afV[2]);
@@ -521,12 +526,12 @@ void Matrix3::bidiagonalize (Matrix3& kA, Matrix3& kL,
kA[2][1] += afW[2];
kA[2][2] += afW[2] * afV[2];
- kR[0][0] = 1.0;
- kR[0][1] = kR[1][0] = 0.0;
- kR[0][2] = kR[2][0] = 0.0;
- kR[1][1] = 1.0 + fT2;
+ kR[0][0] = 1.0f;
+ kR[0][1] = kR[1][0] = 0.0f;
+ kR[0][2] = kR[2][0] = 0.0f;
+ kR[1][1] = 1.0f + fT2;
kR[1][2] = kR[2][1] = fT2 * afV[2];
- kR[2][2] = 1.0 + fT2 * afV[2] * afV[2];
+ kR[2][2] = 1.0f + fT2 * afV[2] * afV[2];
} else {
kR = Matrix3::identity();
}
@@ -535,20 +540,20 @@ void Matrix3::bidiagonalize (Matrix3& kA, Matrix3& kL,
fLength = sqrt(kA[1][1] * kA[1][1] + kA[2][1] * kA[2][1]);
if ( fLength > 0.0 ) {
- fSign = (kA[1][1] > 0.0 ? 1.0 : -1.0);
+ fSign = (kA[1][1] > 0.0 ? 1.0f : -1.0f);
fT1 = kA[1][1] + fSign * fLength;
afV[2] = kA[2][1] / fT1;
- fT2 = -2.0 / (1.0 + afV[2] * afV[2]);
+ fT2 = -2.0f / (1.0f + afV[2] * afV[2]);
afW[1] = fT2 * (kA[1][1] + kA[2][1] * afV[2]);
afW[2] = fT2 * (kA[1][2] + kA[2][2] * afV[2]);
kA[1][1] += afW[1];
kA[1][2] += afW[2];
kA[2][2] += afV[2] * afW[2];
- float fA = 1.0 + fT2;
+ float fA = 1.0f + fT2;
float fB = fT2 * afV[2];
- float fC = 1.0 + fB * afV[2];
+ float fC = 1.0f + fB * afV[2];
if ( bIdentity ) {
kL[0][0] = 1.0;
@@ -558,7 +563,7 @@ void Matrix3::bidiagonalize (Matrix3& kA, Matrix3& kL,
kL[1][2] = kL[2][1] = fB;
kL[2][2] = fC;
} else {
- for (int iRow = 0; iRow < 3; iRow++) {
+ for (int iRow = 0; iRow < 3; ++iRow) {
float fTmp0 = kL[iRow][1];
float fTmp1 = kL[iRow][2];
kL[iRow][1] = fA * fTmp0 + fB * fTmp1;
@@ -576,15 +581,15 @@ void Matrix3::golubKahanStep (Matrix3& kA, Matrix3& kL,
float fT12 = kA[1][1] * kA[1][2];
float fTrace = fT11 + fT22;
float fDiff = fT11 - fT22;
- float fDiscr = sqrt(fDiff * fDiff + 4.0 * fT12 * fT12);
- float fRoot1 = 0.5 * (fTrace + fDiscr);
- float fRoot2 = 0.5 * (fTrace - fDiscr);
+ float fDiscr = sqrt(fDiff * fDiff + 4.0f * fT12 * fT12);
+ float fRoot1 = 0.5f * (fTrace + fDiscr);
+ float fRoot2 = 0.5f * (fTrace - fDiscr);
// adjust right
float fY = kA[0][0] - (G3D::abs(fRoot1 - fT22) <=
G3D::abs(fRoot2 - fT22) ? fRoot1 : fRoot2);
float fZ = kA[0][1];
- float fInvLength = 1.0 / sqrt(fY * fY + fZ * fZ);
+ float fInvLength = 1.0f / sqrt(fY * fY + fZ * fZ);
float fSin = fZ * fInvLength;
float fCos = -fY * fInvLength;
@@ -597,7 +602,7 @@ void Matrix3::golubKahanStep (Matrix3& kA, Matrix3& kL,
int iRow;
- for (iRow = 0; iRow < 3; iRow++) {
+ for (iRow = 0; iRow < 3; ++iRow) {
fTmp0 = kR[0][iRow];
fTmp1 = kR[1][iRow];
kR[0][iRow] = fCos * fTmp0 - fSin * fTmp1;
@@ -609,7 +614,7 @@ void Matrix3::golubKahanStep (Matrix3& kA, Matrix3& kL,
fZ = kA[1][0];
- fInvLength = 1.0 / sqrt(fY * fY + fZ * fZ);
+ fInvLength = 1.0f / sqrt(fY * fY + fZ * fZ);
fSin = fZ * fInvLength;
@@ -631,7 +636,7 @@ void Matrix3::golubKahanStep (Matrix3& kA, Matrix3& kL,
int iCol;
- for (iCol = 0; iCol < 3; iCol++) {
+ for (iCol = 0; iCol < 3; ++iCol) {
fTmp0 = kL[iCol][0];
fTmp1 = kL[iCol][1];
kL[iCol][0] = fCos * fTmp0 - fSin * fTmp1;
@@ -643,7 +648,7 @@ void Matrix3::golubKahanStep (Matrix3& kA, Matrix3& kL,
fZ = kA[0][2];
- fInvLength = 1.0 / sqrt(fY * fY + fZ * fZ);
+ fInvLength = 1.0f / sqrt(fY * fY + fZ * fZ);
fSin = fZ * fInvLength;
@@ -663,7 +668,7 @@ void Matrix3::golubKahanStep (Matrix3& kA, Matrix3& kL,
kA[2][2] *= fCos;
- for (iRow = 0; iRow < 3; iRow++) {
+ for (iRow = 0; iRow < 3; ++iRow) {
fTmp0 = kR[1][iRow];
fTmp1 = kR[2][iRow];
kR[1][iRow] = fCos * fTmp0 - fSin * fTmp1;
@@ -675,7 +680,7 @@ void Matrix3::golubKahanStep (Matrix3& kA, Matrix3& kL,
fZ = kA[2][1];
- fInvLength = 1.0 / sqrt(fY * fY + fZ * fZ);
+ fInvLength = 1.0f / sqrt(fY * fY + fZ * fZ);
fSin = fZ * fInvLength;
@@ -691,7 +696,7 @@ void Matrix3::golubKahanStep (Matrix3& kA, Matrix3& kL,
kA[2][2] = fSin * fTmp0 + fCos * fTmp1;
- for (iCol = 0; iCol < 3; iCol++) {
+ for (iCol = 0; iCol < 3; ++iCol) {
fTmp0 = kL[iCol][1];
fTmp1 = kL[iCol][2];
kL[iCol][1] = fCos * fTmp0 - fSin * fTmp1;
@@ -707,7 +712,7 @@ void Matrix3::singularValueDecomposition (Matrix3& kL, Vector3& kS,
Matrix3 kA = *this;
bidiagonalize(kA, kL, kR);
- for (int i = 0; i < ms_iSvdMaxIterations; i++) {
+ for (int i = 0; i < ms_iSvdMaxIterations; ++i) {
float fTmp, fTmp0, fTmp1;
float fSin0, fCos0, fTan0;
float fSin1, fCos1, fTan1;
@@ -727,11 +732,11 @@ void Matrix3::singularValueDecomposition (Matrix3& kL, Vector3& kS,
// 2x2 closed form factorization
fTmp = (kA[1][1] * kA[1][1] - kA[2][2] * kA[2][2] +
kA[1][2] * kA[1][2]) / (kA[1][2] * kA[2][2]);
- fTan0 = 0.5 * (fTmp + sqrt(fTmp * fTmp + 4.0));
- fCos0 = 1.0 / sqrt(1.0 + fTan0 * fTan0);
+ fTan0 = 0.5f * (fTmp + sqrt(fTmp * fTmp + 4.0f));
+ fCos0 = 1.0f / sqrt(1.0f + fTan0 * fTan0);
fSin0 = fTan0 * fCos0;
- for (iCol = 0; iCol < 3; iCol++) {
+ for (iCol = 0; iCol < 3; ++iCol) {
fTmp0 = kL[iCol][1];
fTmp1 = kL[iCol][2];
kL[iCol][1] = fCos0 * fTmp0 - fSin0 * fTmp1;
@@ -739,10 +744,10 @@ void Matrix3::singularValueDecomposition (Matrix3& kL, Vector3& kS,
}
fTan1 = (kA[1][2] - kA[2][2] * fTan0) / kA[1][1];
- fCos1 = 1.0 / sqrt(1.0 + fTan1 * fTan1);
+ fCos1 = 1.0f / sqrt(1.0f + fTan1 * fTan1);
fSin1 = -fTan1 * fCos1;
- for (iRow = 0; iRow < 3; iRow++) {
+ for (iRow = 0; iRow < 3; ++iRow) {
fTmp0 = kR[1][iRow];
fTmp1 = kR[2][iRow];
kR[1][iRow] = fCos1 * fTmp0 - fSin1 * fTmp1;
@@ -761,11 +766,11 @@ void Matrix3::singularValueDecomposition (Matrix3& kL, Vector3& kS,
// 2x2 closed form factorization
fTmp = (kA[0][0] * kA[0][0] + kA[1][1] * kA[1][1] -
kA[0][1] * kA[0][1]) / (kA[0][1] * kA[1][1]);
- fTan0 = 0.5 * ( -fTmp + sqrt(fTmp * fTmp + 4.0));
- fCos0 = 1.0 / sqrt(1.0 + fTan0 * fTan0);
+ fTan0 = 0.5f * ( -fTmp + sqrt(fTmp * fTmp + 4.0f));
+ fCos0 = 1.0f / sqrt(1.0f + fTan0 * fTan0);
fSin0 = fTan0 * fCos0;
- for (iCol = 0; iCol < 3; iCol++) {
+ for (iCol = 0; iCol < 3; ++iCol) {
fTmp0 = kL[iCol][0];
fTmp1 = kL[iCol][1];
kL[iCol][0] = fCos0 * fTmp0 - fSin0 * fTmp1;
@@ -773,10 +778,10 @@ void Matrix3::singularValueDecomposition (Matrix3& kL, Vector3& kS,
}
fTan1 = (kA[0][1] - kA[1][1] * fTan0) / kA[0][0];
- fCos1 = 1.0 / sqrt(1.0 + fTan1 * fTan1);
+ fCos1 = 1.0f / sqrt(1.0f + fTan1 * fTan1);
fSin1 = -fTan1 * fCos1;
- for (iRow = 0; iRow < 3; iRow++) {
+ for (iRow = 0; iRow < 3; ++iRow) {
fTmp0 = kR[0][iRow];
fTmp1 = kR[1][iRow];
kR[0][iRow] = fCos1 * fTmp0 - fSin1 * fTmp1;
@@ -796,11 +801,11 @@ void Matrix3::singularValueDecomposition (Matrix3& kL, Vector3& kS,
}
// positize diagonal
- for (iRow = 0; iRow < 3; iRow++) {
+ for (iRow = 0; iRow < 3; ++iRow) {
if ( kS[iRow] < 0.0 ) {
kS[iRow] = -kS[iRow];
- for (iCol = 0; iCol < 3; iCol++)
+ for (iCol = 0; iCol < 3; ++iCol)
kR[iRow][iCol] = -kR[iRow][iCol];
}
}
@@ -813,17 +818,17 @@ void Matrix3::singularValueComposition (const Matrix3& kL,
Matrix3 kTmp;
// product S*R
- for (iRow = 0; iRow < 3; iRow++) {
- for (iCol = 0; iCol < 3; iCol++)
+ for (iRow = 0; iRow < 3; ++iRow) {
+ for (iCol = 0; iCol < 3; ++iCol)
kTmp[iRow][iCol] = kS[iRow] * kR[iRow][iCol];
}
// product L*S*R
- for (iRow = 0; iRow < 3; iRow++) {
- for (iCol = 0; iCol < 3; iCol++) {
+ for (iRow = 0; iRow < 3; ++iRow) {
+ for (iCol = 0; iCol < 3; ++iCol) {
elt[iRow][iCol] = 0.0;
- for (int iMid = 0; iMid < 3; iMid++)
+ for (int iMid = 0; iMid < 3; ++iMid)
elt[iRow][iCol] += kL[iRow][iMid] * kTmp[iMid][iCol];
}
}
@@ -842,7 +847,7 @@ void Matrix3::orthonormalize () {
// product of vectors A and B.
// compute q0
- float fInvLength = 1.0 / sqrt(elt[0][0] * elt[0][0]
+ float fInvLength = 1.0f / sqrt(elt[0][0] * elt[0][0]
+ elt[1][0] * elt[1][0] +
elt[2][0] * elt[2][0]);
@@ -860,7 +865,7 @@ void Matrix3::orthonormalize () {
elt[1][1] -= fDot0 * elt[1][0];
elt[2][1] -= fDot0 * elt[2][0];
- fInvLength = 1.0 / sqrt(elt[0][1] * elt[0][1] +
+ fInvLength = 1.0f / sqrt(elt[0][1] * elt[0][1] +
elt[1][1] * elt[1][1] +
elt[2][1] * elt[2][1]);
@@ -883,7 +888,7 @@ void Matrix3::orthonormalize () {
elt[1][2] -= fDot0 * elt[1][0] + fDot1 * elt[1][1];
elt[2][2] -= fDot0 * elt[2][0] + fDot1 * elt[2][1];
- fInvLength = 1.0 / sqrt(elt[0][2] * elt[0][2] +
+ fInvLength = 1.0f / sqrt(elt[0][2] * elt[0][2] +
elt[1][2] * elt[1][2] +
elt[2][2] * elt[2][2]);
@@ -923,7 +928,7 @@ void Matrix3::qDUDecomposition (Matrix3& kQ,
// U stores the entries U[0] = u01, U[1] = u02, U[2] = u12
// build orthogonal matrix Q
- float fInvLength = 1.0 / sqrt(elt[0][0] * elt[0][0]
+ float fInvLength = 1.0f / sqrt(elt[0][0] * elt[0][0]
+ elt[1][0] * elt[1][0] +
elt[2][0] * elt[2][0]);
kQ[0][0] = elt[0][0] * fInvLength;
@@ -935,7 +940,7 @@ void Matrix3::qDUDecomposition (Matrix3& kQ,
kQ[0][1] = elt[0][1] - fDot * kQ[0][0];
kQ[1][1] = elt[1][1] - fDot * kQ[1][0];
kQ[2][1] = elt[2][1] - fDot * kQ[2][0];
- fInvLength = 1.0 / sqrt(kQ[0][1] * kQ[0][1] + kQ[1][1] * kQ[1][1] +
+ fInvLength = 1.0f / sqrt(kQ[0][1] * kQ[0][1] + kQ[1][1] * kQ[1][1] +
kQ[2][1] * kQ[2][1]);
kQ[0][1] *= fInvLength;
kQ[1][1] *= fInvLength;
@@ -951,7 +956,7 @@ void Matrix3::qDUDecomposition (Matrix3& kQ,
kQ[0][2] -= fDot * kQ[0][1];
kQ[1][2] -= fDot * kQ[1][1];
kQ[2][2] -= fDot * kQ[2][1];
- fInvLength = 1.0 / sqrt(kQ[0][2] * kQ[0][2] + kQ[1][2] * kQ[1][2] +
+ fInvLength = 1.0f / sqrt(kQ[0][2] * kQ[0][2] + kQ[1][2] * kQ[1][2] +
kQ[2][2] * kQ[2][2]);
kQ[0][2] *= fInvLength;
kQ[1][2] *= fInvLength;
@@ -963,8 +968,8 @@ void Matrix3::qDUDecomposition (Matrix3& kQ,
kQ[0][1] * kQ[1][0] * kQ[2][2] - kQ[0][0] * kQ[1][2] * kQ[2][1];
if ( fDet < 0.0 ) {
- for (int iRow = 0; iRow < 3; iRow++)
- for (int iCol = 0; iCol < 3; iCol++)
+ for (int iRow = 0; iRow < 3; ++iRow)
+ for (int iCol = 0; iCol < 3; ++iCol)
kQ[iRow][iCol] = -kQ[iRow][iCol];
}
@@ -997,7 +1002,7 @@ void Matrix3::qDUDecomposition (Matrix3& kQ,
kD[2] = kR[2][2];
// the shear component
- float fInvD0 = 1.0 / kD[0];
+ float fInvD0 = 1.0f / kD[0];
kU[0] = kR[0][1] * fInvD0;
@@ -1031,7 +1036,7 @@ void Matrix3::polarDecomposition(Matrix3 &R, Matrix3 &S) const{
const int MAX_ITERS = 100;
const double eps = 50 * std::numeric_limits<float>::epsilon();
- const float BigEps = 50 * eps;
+ const float BigEps = 50.0f * (float)eps;
/* Higham suggests using OneNorm(Xit-X) < eps * OneNorm(X)
* as the convergence criterion, but OneNorm(X) should quickly
@@ -1046,23 +1051,23 @@ void Matrix3::polarDecomposition(Matrix3 &R, Matrix3 &S) const{
Xit = tmp.transpose();
if (resid < BigEps) {
- // close enough use simple iteration
- X += Xit;
- X *= 0.5f;
+ // close enough use simple iteration
+ X += Xit;
+ X *= 0.5f;
}
else {
- // not close to convergence, compute acceleration factor
+ // not close to convergence, compute acceleration factor
float gamma = sqrt( sqrt(
(Xit.l1Norm()* Xit.lInfNorm())/(X.l1Norm()*X.lInfNorm()) ) );
- X *= 0.5f * gamma;
- tmp = Xit;
- tmp *= 0.5f / gamma;
- X += tmp;
+ X *= 0.5f * gamma;
+ tmp = Xit;
+ tmp *= 0.5f / gamma;
+ X += tmp;
}
resid = X.diffOneNorm(Xit);
- iter++;
+ ++iter;
}
R = X;
@@ -1119,13 +1124,13 @@ float Matrix3::maxCubicRoot (float afCoeff[3]) {
if ( fPoly < 0.0f ) {
// uses a matrix norm to find an upper bound on maximum root
- fX = G3D::abs(afCoeff[0]);
- float fTmp = 1.0 + G3D::abs(afCoeff[1]);
+ fX = (float)G3D::abs(afCoeff[0]);
+ float fTmp = 1.0f + (float)G3D::abs(afCoeff[1]);
if ( fTmp > fX )
fX = fTmp;
- fTmp = 1.0 + G3D::abs(afCoeff[2]);
+ fTmp = 1.0f + (float)G3D::abs(afCoeff[2]);
if ( fTmp > fX )
fX = fTmp;
@@ -1134,7 +1139,7 @@ float Matrix3::maxCubicRoot (float afCoeff[3]) {
// Newton's method to find root
float fTwoC2 = 2.0f * afCoeff[2];
- for (int i = 0; i < 16; i++) {
+ for (int i = 0; i < 16; ++i) {
fPoly = afCoeff[0] + fX * (afCoeff[1] + fX * (afCoeff[2] + fX));
if ( G3D::abs(fPoly) <= fEpsilon )
@@ -1154,11 +1159,11 @@ float Matrix3::spectralNorm () const {
int iRow, iCol;
float fPmax = 0.0;
- for (iRow = 0; iRow < 3; iRow++) {
- for (iCol = 0; iCol < 3; iCol++) {
+ for (iRow = 0; iRow < 3; ++iRow) {
+ for (iCol = 0; iCol < 3; ++iCol) {
kP[iRow][iCol] = 0.0;
- for (int iMid = 0; iMid < 3; iMid++) {
+ for (int iMid = 0; iMid < 3; ++iMid) {
kP[iRow][iCol] +=
elt[iMid][iRow] * elt[iMid][iCol];
}
@@ -1168,10 +1173,10 @@ float Matrix3::spectralNorm () const {
}
}
- float fInvPmax = 1.0 / fPmax;
+ float fInvPmax = 1.0f / fPmax;
- for (iRow = 0; iRow < 3; iRow++) {
- for (iCol = 0; iCol < 3; iCol++)
+ for (iRow = 0; iRow < 3; ++iRow) {
+ for (iCol = 0; iCol < 3; ++iCol)
kP[iRow][iCol] *= fInvPmax;
}
@@ -1215,7 +1220,7 @@ float Matrix3::l1Norm() const {
float f = fabs(elt[0][c])+ fabs(elt[1][c]) + fabs(elt[2][c]);
if (f > oneNorm) {
- oneNorm = f;
+ oneNorm = f;
}
}
return oneNorm;
@@ -1231,7 +1236,7 @@ float Matrix3::lInfNorm() const {
float f = fabs(elt[r][0]) + fabs(elt[r][1])+ fabs(elt[r][2]);
if (f > infNorm) {
- infNorm = f;
+ infNorm = f;
}
}
return infNorm;
@@ -1244,10 +1249,10 @@ float Matrix3::diffOneNorm(const Matrix3 &y) const{
for (int c = 0; c < 3; ++c){
float f = fabs(elt[0][c] - y[0][c]) + fabs(elt[1][c] - y[1][c])
- + fabs(elt[2][c] - y[2][c]);
+ + fabs(elt[2][c] - y[2][c]);
if (f > oneNorm) {
- oneNorm = f;
+ oneNorm = f;
}
}
return oneNorm;
@@ -1280,14 +1285,14 @@ void Matrix3::toAxisAngle (Vector3& rkAxis, float& rfRadians) const {
float fTrace = elt[0][0] + elt[1][1] + elt[2][2];
float fCos = 0.5f * (fTrace - 1.0f);
- rfRadians = G3D::aCos(fCos); // in [0,PI]
+ rfRadians = (float)G3D::aCos(fCos); // in [0,PI]
if ( rfRadians > 0.0 ) {
if ( rfRadians < pi() ) {
rkAxis.x = elt[2][1] - elt[1][2];
rkAxis.y = elt[0][2] - elt[2][0];
rkAxis.z = elt[1][0] - elt[0][1];
- rkAxis.unitize();
+ rkAxis = rkAxis.direction();
} else {
// angle is PI
float fHalfInverse;
@@ -1296,16 +1301,16 @@ void Matrix3::toAxisAngle (Vector3& rkAxis, float& rfRadians) const {
// r00 >= r11
if ( elt[0][0] >= elt[2][2] ) {
// r00 is maximum diagonal term
- rkAxis.x = 0.5 * sqrt(elt[0][0] -
- elt[1][1] - elt[2][2] + 1.0);
- fHalfInverse = 0.5 / rkAxis.x;
+ rkAxis.x = 0.5f * sqrt(elt[0][0] -
+ elt[1][1] - elt[2][2] + 1.0f);
+ fHalfInverse = 0.5f / rkAxis.x;
rkAxis.y = fHalfInverse * elt[0][1];
rkAxis.z = fHalfInverse * elt[0][2];
} else {
// r22 is maximum diagonal term
- rkAxis.z = 0.5 * sqrt(elt[2][2] -
- elt[0][0] - elt[1][1] + 1.0);
- fHalfInverse = 0.5 / rkAxis.z;
+ rkAxis.z = 0.5f * sqrt(elt[2][2] -
+ elt[0][0] - elt[1][1] + 1.0f);
+ fHalfInverse = 0.5f / rkAxis.z;
rkAxis.x = fHalfInverse * elt[0][2];
rkAxis.y = fHalfInverse * elt[1][2];
}
@@ -1313,16 +1318,16 @@ void Matrix3::toAxisAngle (Vector3& rkAxis, float& rfRadians) const {
// r11 > r00
if ( elt[1][1] >= elt[2][2] ) {
// r11 is maximum diagonal term
- rkAxis.y = 0.5 * sqrt(elt[1][1] -
- elt[0][0] - elt[2][2] + 1.0);
- fHalfInverse = 0.5 / rkAxis.y;
+ rkAxis.y = 0.5f * sqrt(elt[1][1] -
+ elt[0][0] - elt[2][2] + 1.0f);
+ fHalfInverse = 0.5f / rkAxis.y;
rkAxis.x = fHalfInverse * elt[0][1];
rkAxis.z = fHalfInverse * elt[1][2];
} else {
// r22 is maximum diagonal term
- rkAxis.z = 0.5 * sqrt(elt[2][2] -
- elt[0][0] - elt[1][1] + 1.0);
- fHalfInverse = 0.5 / rkAxis.z;
+ rkAxis.z = 0.5f * sqrt(elt[2][2] -
+ elt[0][0] - elt[1][1] + 1.0f);
+ fHalfInverse = 0.5f / rkAxis.z;
rkAxis.x = fHalfInverse * elt[0][2];
rkAxis.y = fHalfInverse * elt[1][2];
}
@@ -1339,12 +1344,16 @@ void Matrix3::toAxisAngle (Vector3& rkAxis, float& rfRadians) const {
//----------------------------------------------------------------------------
Matrix3 Matrix3::fromAxisAngle (const Vector3& _axis, float fRadians) {
- Vector3 axis = _axis.direction();
+ return fromUnitAxisAngle(_axis.direction(), fRadians);
+}
+
+Matrix3 Matrix3::fromUnitAxisAngle (const Vector3& axis, float fRadians) {
+ debugAssertM(axis.isUnit(), "Matrix3::fromUnitAxisAngle requires ||axis|| = 1");
Matrix3 m;
float fCos = cos(fRadians);
float fSin = sin(fRadians);
- float fOneMinusCos = 1.0 - fCos;
+ float fOneMinusCos = 1.0f - fCos;
float fX2 = square(axis.x);
float fY2 = square(axis.y);
float fZ2 = square(axis.z);
@@ -1379,20 +1388,20 @@ bool Matrix3::toEulerAnglesXYZ (float& rfXAngle, float& rfYAngle,
if ( elt[0][2] < 1.0f ) {
if ( elt[0][2] > -1.0f ) {
- rfXAngle = G3D::aTan2( -elt[1][2], elt[2][2]);
+ rfXAngle = (float) G3D::aTan2( -elt[1][2], elt[2][2]);
rfYAngle = (float) G3D::aSin(elt[0][2]);
- rfZAngle = G3D::aTan2( -elt[0][1], elt[0][0]);
+ rfZAngle = (float) G3D::aTan2( -elt[0][1], elt[0][0]);
return true;
} else {
// WARNING. Not unique. XA - ZA = -atan2(r10,r11)
- rfXAngle = -G3D::aTan2(elt[1][0], elt[1][1]);
+ rfXAngle = -(float)G3D::aTan2(elt[1][0], elt[1][1]);
rfYAngle = -(float)halfPi();
rfZAngle = 0.0f;
return false;
}
} else {
// WARNING. Not unique. XAngle + ZAngle = atan2(r10,r11)
- rfXAngle = G3D::aTan2(elt[1][0], elt[1][1]);
+ rfXAngle = (float)G3D::aTan2(elt[1][0], elt[1][1]);
rfYAngle = (float)halfPi();
rfZAngle = 0.0f;
return false;
@@ -1408,20 +1417,20 @@ bool Matrix3::toEulerAnglesXZY (float& rfXAngle, float& rfZAngle,
if ( elt[0][1] < 1.0f ) {
if ( elt[0][1] > -1.0f ) {
- rfXAngle = G3D::aTan2(elt[2][1], elt[1][1]);
+ rfXAngle = (float) G3D::aTan2(elt[2][1], elt[1][1]);
rfZAngle = (float) asin( -elt[0][1]);
- rfYAngle = G3D::aTan2(elt[0][2], elt[0][0]);
+ rfYAngle = (float) G3D::aTan2(elt[0][2], elt[0][0]);
return true;
} else {
// WARNING. Not unique. XA - YA = atan2(r20,r22)
- rfXAngle = G3D::aTan2(elt[2][0], elt[2][2]);
+ rfXAngle = (float)G3D::aTan2(elt[2][0], elt[2][2]);
rfZAngle = (float)halfPi();
- rfYAngle = 0.0;
+ rfYAngle = 0.0f;
return false;
}
} else {
// WARNING. Not unique. XA + YA = atan2(-r20,r22)
- rfXAngle = G3D::aTan2( -elt[2][0], elt[2][2]);
+ rfXAngle = (float)G3D::aTan2( -elt[2][0], elt[2][2]);
rfZAngle = -(float)halfPi();
rfYAngle = 0.0f;
return false;
@@ -1437,20 +1446,20 @@ bool Matrix3::toEulerAnglesYXZ (float& rfYAngle, float& rfXAngle,
if ( elt[1][2] < 1.0 ) {
if ( elt[1][2] > -1.0 ) {
- rfYAngle = G3D::aTan2(elt[0][2], elt[2][2]);
+ rfYAngle = (float) G3D::aTan2(elt[0][2], elt[2][2]);
rfXAngle = (float) asin( -elt[1][2]);
- rfZAngle = G3D::aTan2(elt[1][0], elt[1][1]);
+ rfZAngle = (float) G3D::aTan2(elt[1][0], elt[1][1]);
return true;
} else {
// WARNING. Not unique. YA - ZA = atan2(r01,r00)
- rfYAngle = G3D::aTan2(elt[0][1], elt[0][0]);
+ rfYAngle = (float)G3D::aTan2(elt[0][1], elt[0][0]);
rfXAngle = (float)halfPi();
- rfZAngle = 0.0;
+ rfZAngle = 0.0f;
return false;
}
} else {
// WARNING. Not unique. YA + ZA = atan2(-r01,r00)
- rfYAngle = G3D::aTan2( -elt[0][1], elt[0][0]);
+ rfYAngle = (float)G3D::aTan2( -elt[0][1], elt[0][0]);
rfXAngle = -(float)halfPi();
rfZAngle = 0.0f;
return false;
@@ -1466,20 +1475,20 @@ bool Matrix3::toEulerAnglesYZX (float& rfYAngle, float& rfZAngle,
if ( elt[1][0] < 1.0 ) {
if ( elt[1][0] > -1.0 ) {
- rfYAngle = G3D::aTan2( -elt[2][0], elt[0][0]);
+ rfYAngle = (float) G3D::aTan2( -elt[2][0], elt[0][0]);
rfZAngle = (float) asin(elt[1][0]);
- rfXAngle = G3D::aTan2( -elt[1][2], elt[1][1]);
+ rfXAngle = (float) G3D::aTan2( -elt[1][2], elt[1][1]);
return true;
} else {
// WARNING. Not unique. YA - XA = -atan2(r21,r22);
- rfYAngle = -G3D::aTan2(elt[2][1], elt[2][2]);
+ rfYAngle = -(float)G3D::aTan2(elt[2][1], elt[2][2]);
rfZAngle = -(float)halfPi();
- rfXAngle = 0.0;
+ rfXAngle = 0.0f;
return false;
}
} else {
// WARNING. Not unique. YA + XA = atan2(r21,r22)
- rfYAngle = G3D::aTan2(elt[2][1], elt[2][2]);
+ rfYAngle = (float)G3D::aTan2(elt[2][1], elt[2][2]);
rfZAngle = (float)halfPi();
rfXAngle = 0.0f;
return false;
@@ -1495,20 +1504,20 @@ bool Matrix3::toEulerAnglesZXY (float& rfZAngle, float& rfXAngle,
if ( elt[2][1] < 1.0 ) {
if ( elt[2][1] > -1.0 ) {
- rfZAngle = G3D::aTan2( -elt[0][1], elt[1][1]);
+ rfZAngle = (float) G3D::aTan2( -elt[0][1], elt[1][1]);
rfXAngle = (float) asin(elt[2][1]);
- rfYAngle = G3D::aTan2( -elt[2][0], elt[2][2]);
+ rfYAngle = (float) G3D::aTan2( -elt[2][0], elt[2][2]);
return true;
} else {
// WARNING. Not unique. ZA - YA = -atan(r02,r00)
- rfZAngle = -G3D::aTan2(elt[0][2], elt[0][0]);
+ rfZAngle = -(float)G3D::aTan2(elt[0][2], elt[0][0]);
rfXAngle = -(float)halfPi();
rfYAngle = 0.0f;
return false;
}
} else {
// WARNING. Not unique. ZA + YA = atan2(r02,r00)
- rfZAngle = G3D::aTan2(elt[0][2], elt[0][0]);
+ rfZAngle = (float)G3D::aTan2(elt[0][2], elt[0][0]);
rfXAngle = (float)halfPi();
rfYAngle = 0.0f;
return false;
@@ -1525,19 +1534,19 @@ bool Matrix3::toEulerAnglesZYX (float& rfZAngle, float& rfYAngle,
if ( elt[2][0] < 1.0 ) {
if ( elt[2][0] > -1.0 ) {
rfZAngle = atan2f(elt[1][0], elt[0][0]);
- rfYAngle = asinf(-(double)elt[2][1]);
+ rfYAngle = asinf(-elt[2][0]);
rfXAngle = atan2f(elt[2][1], elt[2][2]);
return true;
} else {
// WARNING. Not unique. ZA - XA = -atan2(r01,r02)
- rfZAngle = -G3D::aTan2(elt[0][1], elt[0][2]);
+ rfZAngle = -(float)G3D::aTan2(elt[0][1], elt[0][2]);
rfYAngle = (float)halfPi();
rfXAngle = 0.0f;
return false;
}
} else {
// WARNING. Not unique. ZA + XA = atan2(-r01,-r02)
- rfZAngle = G3D::aTan2( -elt[0][1], -elt[0][2]);
+ rfZAngle = (float)G3D::aTan2( -elt[0][1], -elt[0][2]);
rfYAngle = -(float)halfPi();
rfXAngle = 0.0f;
return false;
@@ -1693,10 +1702,10 @@ void Matrix3::tridiagonal (float afDiag[3], float afSubDiag[3]) {
if ( G3D::abs(fC) >= EPSILON ) {
float fLength = sqrt(fB * fB + fC * fC);
- float fInvLength = 1.0 / fLength;
+ float fInvLength = 1.0f / fLength;
fB *= fInvLength;
fC *= fInvLength;
- float fQ = 2.0 * fB * fE + fC * (fF - fD);
+ float fQ = 2.0f * fB * fE + fC * (fF - fD);
afDiag[1] = fD + fC * fQ;
afDiag[2] = fF - fC * fQ;
afSubDiag[0] = fLength;
@@ -1732,16 +1741,16 @@ bool Matrix3::qLAlgorithm (float afDiag[3], float afSubDiag[3]) {
// QL iteration with implicit shifting to reduce matrix from tridiagonal
// to diagonal
- for (int i0 = 0; i0 < 3; i0++) {
+ for (int i0 = 0; i0 < 3; ++i0) {
const int iMaxIter = 32;
int iIter;
- for (iIter = 0; iIter < iMaxIter; iIter++) {
+ for (iIter = 0; iIter < iMaxIter; ++iIter) {
int i1;
- for (i1 = i0; i1 <= 1; i1++) {
- float fSum = G3D::abs(afDiag[i1]) +
- G3D::abs(afDiag[i1 + 1]);
+ for (i1 = i0; i1 <= 1; ++i1) {
+ float fSum = float(G3D::abs(afDiag[i1]) +
+ G3D::abs(afDiag[i1 + 1]));
if ( G3D::abs(afSubDiag[i1]) + fSum == fSum )
break;
@@ -1750,9 +1759,9 @@ bool Matrix3::qLAlgorithm (float afDiag[3], float afSubDiag[3]) {
if ( i1 == i0 )
break;
- float fTmp0 = (afDiag[i0 + 1] - afDiag[i0]) / (2.0 * afSubDiag[i0]);
+ float fTmp0 = (afDiag[i0 + 1] - afDiag[i0]) / (2.0f * afSubDiag[i0]);
- float fTmp1 = sqrt(fTmp0 * fTmp0 + 1.0);
+ float fTmp1 = sqrt(fTmp0 * fTmp0 + 1.0f);
if ( fTmp0 < 0.0 )
fTmp0 = afDiag[i1] - afDiag[i0] + afSubDiag[i0] / (fTmp0 - fTmp1);
@@ -1771,25 +1780,25 @@ bool Matrix3::qLAlgorithm (float afDiag[3], float afSubDiag[3]) {
if (G3D::abs(fTmp3) >= G3D::abs(fTmp0)) {
fCos = fTmp0 / fTmp3;
- fTmp1 = sqrt(fCos * fCos + 1.0);
+ fTmp1 = sqrt(fCos * fCos + 1.0f);
afSubDiag[i2 + 1] = fTmp3 * fTmp1;
- fSin = 1.0 / fTmp1;
+ fSin = 1.0f / fTmp1;
fCos *= fSin;
} else {
fSin = fTmp3 / fTmp0;
- fTmp1 = sqrt(fSin * fSin + 1.0);
+ fTmp1 = sqrt(fSin * fSin + 1.0f);
afSubDiag[i2 + 1] = fTmp0 * fTmp1;
- fCos = 1.0 / fTmp1;
+ fCos = 1.0f / fTmp1;
fSin *= fCos;
}
fTmp0 = afDiag[i2 + 1] - fTmp2;
- fTmp1 = (afDiag[i2] - fTmp0) * fSin + 2.0 * fTmp4 * fCos;
+ fTmp1 = (afDiag[i2] - fTmp0) * fSin + 2.0f * fTmp4 * fCos;
fTmp2 = fSin * fTmp1;
afDiag[i2 + 1] = fTmp0 + fTmp2;
fTmp0 = fCos * fTmp1 - fTmp4;
- for (int iRow = 0; iRow < 3; iRow++) {
+ for (int iRow = 0; iRow < 3; ++iRow) {
fTmp3 = elt[iRow][i2 + 1];
elt[iRow][i2 + 1] = fSin * elt[iRow][i2] +
fCos * fTmp3;
@@ -1820,7 +1829,7 @@ void Matrix3::eigenSolveSymmetric (float afEigenvalue[3],
kMatrix.tridiagonal(afEigenvalue, afSubDiag);
kMatrix.qLAlgorithm(afEigenvalue, afSubDiag);
- for (int i = 0; i < 3; i++) {
+ for (int i = 0; i < 3; ++i) {
akEigenvector[i][0] = kMatrix[0][i];
akEigenvector[i][1] = kMatrix[1][i];
akEigenvector[i][2] = kMatrix[2][i];
@@ -1841,8 +1850,8 @@ void Matrix3::eigenSolveSymmetric (float afEigenvalue[3],
//----------------------------------------------------------------------------
void Matrix3::tensorProduct (const Vector3& rkU, const Vector3& rkV,
Matrix3& rkProduct) {
- for (int iRow = 0; iRow < 3; iRow++) {
- for (int iCol = 0; iCol < 3; iCol++) {
+ for (int iRow = 0; iRow < 3; ++iRow) {
+ for (int iCol = 0; iCol < 3; ++iCol) {
rkProduct[iRow][iCol] = rkU[iRow] * rkV[iCol];
}
}
@@ -1922,9 +1931,9 @@ void Matrix3::_transpose(const Matrix3& A, Matrix3& out) {
//-----------------------------------------------------------------------------
std::string Matrix3::toString() const {
return G3D::format("[%g, %g, %g; %g, %g, %g; %g, %g, %g]",
- elt[0][0], elt[0][1], elt[0][2],
- elt[1][0], elt[1][1], elt[1][2],
- elt[2][0], elt[2][1], elt[2][2]);
+ elt[0][0], elt[0][1], elt[0][2],
+ elt[1][0], elt[1][1], elt[1][2],
+ elt[2][0], elt[2][1], elt[2][2]);
}
diff --git a/dep/g3dlite/source/Matrix4.cpp b/dep/g3dlite/source/Matrix4.cpp
index fbc918f8f3e..f3b25ad5837 100644
--- a/dep/g3dlite/source/Matrix4.cpp
+++ b/dep/g3dlite/source/Matrix4.cpp
@@ -1,16 +1,16 @@
/**
- @file Matrix4.cpp
+ \file G3D/source/Matrix4.cpp
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
+ \maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @created 2003-10-02
- @edited 2010-01-29
+ \created 2003-10-02
+ \edited 2012-02-19
*/
#include "G3D/platform.h"
#include "G3D/Matrix4.h"
#include "G3D/Matrix3.h"
+#include "G3D/Matrix2.h"
#include "G3D/Vector4.h"
#include "G3D/Vector3.h"
#include "G3D/BinaryInput.h"
@@ -24,11 +24,11 @@ namespace G3D {
Matrix4::Matrix4(const Any& any) {
- any.verifyName("Matrix4");
+ any.verifyNameBeginsWith("Matrix4", "CFrame", "CoordinateFrame");
any.verifyType(Any::ARRAY);
- const std::string& name = toLower(any.name());
- if (name == "matrix4") {
+ const std::string& name = any.name();
+ if (name == "Matrix4") {
any.verifySize(16);
for (int r = 0; r < 4; ++r) {
@@ -36,26 +36,43 @@ Matrix4::Matrix4(const Any& any) {
elt[r][c] = any[r * 4 + c];
}
}
- } else if (name == "matrix4::scale") {
+ } else if (name == "Matrix4::scale") {
if (any.size() == 1) {
- *this = scale(any[0].number());
+ *this = scale(any[0].floatValue());
} else if (any.size() == 3) {
*this = scale(any[0], any[1], any[2]);
} else {
any.verify(false, "Matrix4::scale() takes either 1 or 3 arguments");
}
- } else if (name == "matrix4::translation") {
+ } else if (name == "Matrix4::rollDegrees") {
+ any.verifySize(1);
+ *this = rollDegrees(any[0].floatValue());
+ } else if (name == "Matrix4::yawDegrees") {
+ any.verifySize(1);
+ *this = yawDegrees(any[0].floatValue());
+ } else if (name == "Matrix4::pitchDegrees") {
+ any.verifySize(1);
+ *this = pitchDegrees(any[0].floatValue());
+ } else if (name == "Matrix4::translation") {
if (any.size() == 3) {
*this = translation(any[0], any[1], any[2]);
} else {
- any.verify(false, "Matrix4::translation() takes either 1 or 3 arguments");
- } } else {
+ any.verify(false, "Matrix4::translation() requires 3 arguments");
+ }
+ } else if (name == "Matrix4::diagonal") {
+ any.verifySize(4);
+ *this = diagonal(any[0], any[1], any[2], any[3]);
+ } else if (name == "Matrix4::identity") {
+ *this = identity();
+ } else if (beginsWith(name, "CFrame") || beginsWith(name, "CoordinateFrame")) {
+ *this = CFrame(any);
+ } else {
any.verify(false, "Expected Matrix4 constructor");
}
}
-Matrix4::operator Any() const {
+Any Matrix4::toAny() const {
Any any(Any::ARRAY, "Matrix4");
any.resize(16);
for (int r = 0; r < 4; ++r) {
@@ -121,6 +138,12 @@ Matrix3 Matrix4::upper3x3() const {
}
+Matrix2 Matrix4::upper2x2() const {
+ return Matrix2(elt[0][0], elt[0][1],
+ elt[1][0], elt[1][1]);
+}
+
+
Matrix4 Matrix4::orthogonalProjection(
const class Rect2D& rect,
float nearval,
@@ -164,59 +187,59 @@ Matrix4 Matrix4::orthogonalProjection(
Matrix4 Matrix4::perspectiveProjection(
- float left,
- float right,
- float bottom,
- float top,
- float nearval,
- float farval,
- float upDirection) {
-
- float x, y, a, b, c, d;
-
- x = (2.0f*nearval) / (right-left);
- y = (2.0f*nearval) / (top-bottom);
+ double left,
+ double right,
+ double bottom,
+ double top,
+ double nearval,
+ double farval,
+ float upDirection) {
+
+ double x, y, a, b, c, d;
+
+ x = (2.0*nearval) / (right-left);
+ y = (2.0*nearval) / (top-bottom);
a = (right+left) / (right-left);
b = (top+bottom) / (top-bottom);
- if (farval >= finf()) {
+ if (farval >= inf()) {
// Infinite view frustum
- c = -1.0f;
- d = -2.0f * nearval;
+ c = -1.0;
+ d = -2.0 * nearval;
} else {
c = -(farval+nearval) / (farval-nearval);
- d = -(2.0f*farval*nearval) / (farval-nearval);
+ d = -(2.0*farval*nearval) / (farval-nearval);
}
- debugAssertM(abs(upDirection) == 1.0f, "upDirection must be -1 or +1");
+ debugAssertM(abs(upDirection) == 1.0, "upDirection must be -1 or +1");
y *= upDirection;
b *= upDirection;
return Matrix4(
- x, 0, a, 0,
- 0, y, b, 0,
- 0, 0, c, d,
+ (float)x, 0, (float)a, 0,
+ 0, (float)y, (float)b, 0,
+ 0, 0, (float)c, (float)d,
0, 0, -1, 0);
}
void Matrix4::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) const {
debugAssertM(abs(upDirection) == 1.0f, "upDirection must be -1 or +1");
- float x = elt[0][0];
- float y = elt[1][1] * upDirection;
- float a = elt[0][2];
- float b = elt[1][2] * upDirection;
- float c = elt[2][2];
- float d = elt[2][3];
+ double x = elt[0][0];
+ double y = elt[1][1] * upDirection;
+ double a = elt[0][2];
+ double b = elt[1][2] * upDirection;
+ double c = elt[2][2];
+ double d = elt[2][3];
// Verify that this really is a projection matrix
debugAssertM(elt[3][2] == -1, "Not a projection matrix");
@@ -232,18 +255,18 @@ void Matrix4::getPerspectiveProjectionParameters(
if (c == -1) {
farval = finf();
- nearval = -d / 2.0f;
+ nearval = -d / 2.0;
} else {
- nearval = d * ((c - 1.0f) / (c + 1.0f) - 1.0f) / (-2.0f * (c - 1.0f) / (c + 1.0f));
- farval = nearval * ((c - 1.0f) / (c + 1.0f));
+ nearval = d * ((c - 1.0) / (c + 1.0) - 1.0) / (-2.0 * (c - 1.0) / (c + 1.0));
+ farval = nearval * ((c - 1.0) / (c + 1.0));
}
- left = (a - 1.0f) * nearval / x;
- right = 2.0f * nearval / x + left;
+ left = (a - 1.0) * nearval / x;
+ right = 2.0 * nearval / x + left;
- bottom = (b - 1.0f) * nearval / y;
- top = 2.0f * nearval / y + bottom;
+ bottom = (b - 1.0) * nearval / y;
+ top = 2.0 * nearval / y + bottom;
}
@@ -401,7 +424,7 @@ bool Matrix4::operator==(const Matrix4& other) const {
float Matrix4::determinant() const {
// Determinant is the dot product of the first row and the first row
// of cofactors (i.e. the first col of the adjoint matrix)
- return cofactor().row(0).dot(row(0));
+ return cofactor().row(0).dot(row(0));
}
@@ -417,14 +440,14 @@ Matrix4 Matrix4::inverse() const {
// Determinant is the dot product of the first row and the first row
// of cofactors (i.e. the first col of the adjoint matrix)
- float det = A.column(0).dot(row(0));
+ float det = A.column(0).dot(row(0));
- return A * (1.0f / det);
+ return A * (1.0f / det);
}
Matrix4 Matrix4::cofactor() const {
- Matrix4 out;
+ Matrix4 out;
// We'll use i to incrementally compute -1 ^ (r+c)
int i = 1;
@@ -482,19 +505,19 @@ float Matrix4::subDeterminant(int excludeRow, int excludeCol) const {
CoordinateFrame Matrix4::approxCoordinateFrame() const {
- CoordinateFrame cframe;
+ CoordinateFrame cframe;
- for (int r = 0; r < 3; ++r) {
- for (int c = 0; c < 3; ++c) {
- cframe.rotation[r][c] = elt[r][c];
- }
- cframe.translation[r] = elt[r][3];
- }
+ for (int r = 0; r < 3; ++r) {
+ for (int c = 0; c < 3; ++c) {
+ cframe.rotation[r][c] = elt[r][c];
+ }
+ cframe.translation[r] = elt[r][3];
+ }
- // Ensure that the rotation matrix is orthonormal
- cframe.rotation.orthonormalize();
+ // Ensure that the rotation matrix is orthonormal
+ cframe.rotation.orthonormalize();
- return cframe;
+ return cframe;
}
@@ -517,12 +540,138 @@ void Matrix4::deserialize(class BinaryInput& b) {
std::string Matrix4::toString() const {
return G3D::format("[%g, %g, %g, %g; %g, %g, %g, %g; %g, %g, %g, %g; %g, %g, %g, %g]",
- elt[0][0], elt[0][1], elt[0][2], elt[0][3],
- elt[1][0], elt[1][1], elt[1][2], elt[1][3],
- elt[2][0], elt[2][1], elt[2][2], elt[2][3],
- elt[3][0], elt[3][1], elt[3][2], elt[3][3]);
+ elt[0][0], elt[0][1], elt[0][2], elt[0][3],
+ elt[1][0], elt[1][1], elt[1][2], elt[1][3],
+ elt[2][0], elt[2][1], elt[2][2], elt[2][3],
+ elt[3][0], elt[3][1], elt[3][2], elt[3][3]);
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+Matrix4float64::Matrix4float64(const Matrix4& m) {
+ for (int r = 0; r < 4; ++r) {
+ for (int c = 0; c < 4; ++c) {
+ elt[r][c] = m[r][c];
+ }
+ }
+}
+
+
+Matrix4float64::Matrix4float64() {
+ for (int r = 0; r < 4; ++r) {
+ for (int c = 0; c < 4; ++c) {
+ elt[r][c] = 0.0;
+ }
+ }
+}
+
+
+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) {
+ elt[0][0] = r1c1; elt[0][1] = r1c2; elt[0][2] = r1c3; elt[0][3] = r1c4;
+ elt[1][0] = r2c1; elt[1][1] = r2c2; elt[1][2] = r2c3; elt[1][3] = r2c4;
+ elt[2][0] = r3c1; elt[2][1] = r3c2; elt[2][2] = r3c3; elt[2][3] = r3c4;
+ elt[3][0] = r4c1; elt[3][1] = r4c2; elt[3][2] = r4c3; elt[3][3] = r4c4;
+}
+
+
+const Matrix4float64& Matrix4float64::identity() {
+ static Matrix4float64 m(
+ 1, 0, 0, 0,
+ 0, 1, 0, 0,
+ 0, 0, 1, 0,
+ 0, 0, 0, 1);
+ return m;
+}
+
+
+const Matrix4float64& Matrix4float64::zero() {
+ static Matrix4float64 m;
+ return m;
+}
+
+
+bool Matrix4float64::operator!=(const Matrix4float64& other) const {
+ return ! (*this == other);
+}
+
+
+bool Matrix4float64::operator==(const Matrix4float64& other) const {
+
+ // If the bit patterns are identical, they must be
+ // the same matrix. If not, they *might* still have
+ // equal elements due to floating point weirdness.
+ if (memcmp(this, &other, sizeof(Matrix4float64) == 0)) {
+ return true;
+ }
+
+ for (int r = 0; r < 4; ++r) {
+ for (int c = 0; c < 4; ++c) {
+ if (elt[r][c] != other.elt[r][c]) {
+ return false;
+ }
+ }
+ }
+
+ return true;
}
+
+Vector4 Matrix4float64::operator*(const Vector4& vector) const {
+ Vector4 result;
+ for (int r = 0; r < 4; ++r) {
+ double sum = 0;
+ for (int c = 0; c < 4; ++c) {
+ sum += elt[r][c] * vector[c];
+ }
+ result[r] = (float)sum;
+ }
+
+ return result;
+}
+
+
+Matrix4float64 Matrix4float64::perspectiveProjection(
+ double left,
+ double right,
+ double bottom,
+ double top,
+ double nearval,
+ double farval,
+ float upDirection) {
+ double x, y, a, b, c, d;
+
+ x = (2.0*nearval) / (right-left);
+ y = (2.0*nearval) / (top-bottom);
+ a = (right+left) / (right-left);
+ b = (top+bottom) / (top-bottom);
+
+ if (farval >= inf()) {
+ // Infinite view frustum
+ c = -1.0;
+ d = -2.0 * nearval;
+ } else {
+ c = -(farval+nearval) / (farval-nearval);
+ d = -(2.0*farval*nearval) / (farval-nearval);
+ }
+
+ debugAssertM(abs(upDirection) == 1.0, "upDirection must be -1 or +1");
+ y *= upDirection;
+ b *= upDirection;
+
+ return Matrix4float64(
+ (float)x, 0, (float)a, 0,
+ 0, (float)y, (float)b, 0,
+ 0, 0, (float)c, (float)d,
+ 0, 0, -1, 0);
+}
+
+
} // namespace
diff --git a/dep/g3dlite/source/MemoryManager.cpp b/dep/g3dlite/source/MemoryManager.cpp
index 240188a1f0e..7346b0f0706 100644
--- a/dep/g3dlite/source/MemoryManager.cpp
+++ b/dep/g3dlite/source/MemoryManager.cpp
@@ -33,7 +33,7 @@ bool MemoryManager::isThreadsafe() const {
MemoryManager::Ref MemoryManager::create() {
- static MemoryManager::Ref m = new MemoryManager();
+ static MemoryManager::Ref m(new MemoryManager());
return m;
}
@@ -59,7 +59,7 @@ bool AlignedMemoryManager::isThreadsafe() const {
AlignedMemoryManager::Ref AlignedMemoryManager::create() {
- static AlignedMemoryManager::Ref m = new AlignedMemoryManager();
+ static AlignedMemoryManager::Ref m(new AlignedMemoryManager());
return m;
}
@@ -85,7 +85,7 @@ bool CRTMemoryManager::isThreadsafe() const {
CRTMemoryManager::Ref CRTMemoryManager::create() {
- static CRTMemoryManager::Ref m = new CRTMemoryManager();
+ static CRTMemoryManager::Ref m(new CRTMemoryManager());
return m;
}
}
diff --git a/dep/g3dlite/source/MeshAlg.cpp b/dep/g3dlite/source/MeshAlg.cpp
index 626fed92920..75dee727464 100644
--- a/dep/g3dlite/source/MeshAlg.cpp
+++ b/dep/g3dlite/source/MeshAlg.cpp
@@ -50,7 +50,7 @@ void MeshAlg::generateGrid(
texCoord.append(t);
- if (height.notNull()) {
+ if (height) {
v.y = height->nearest(v.x * (height->width() - 1), v.z * (height->height() - 1)).value;
}
if (spaceCentered) {
@@ -253,7 +253,7 @@ void MeshAlg::identifyBackfaces(
backface.resize(faceArray.size());
- if (fuzzyEq(HP.w, 0.0)) {
+ if (fuzzyEq(HP.w, 0.0f)) {
// Infinite case
for (int f = faceArray.size() - 1; f >= 0; --f) {
const MeshAlg::Face& face = faceArray[f];
@@ -294,7 +294,7 @@ void MeshAlg::identifyBackfaces(
backface.resize(faceArray.size());
- if (fuzzyEq(HP.w, 0.0)) {
+ if (fuzzyEq(HP.w, 0.0f)) {
// Infinite case
for (int f = faceArray.size() - 1; f >= 0; --f) {
const Vector3& N = faceNormals[f];
@@ -417,6 +417,7 @@ void MeshAlg::computeBounds(
AABox& box,
Sphere& sphere) {
+ // Makes a copy so as to re-use the existing computebounds code
Array<Vector3> newArray;
newArray.resize(indexArray.size());
for (int i = 0; i < indexArray.size(); ++i) {
@@ -441,54 +442,54 @@ void MeshAlg::computeBounds(
const Vector3& vertex = vertexArray[v];
if (vertex.x < xmin.x) {
- xmin = vertex;
+ xmin = vertex;
}
if (vertex.x > xmax.x) {
- xmax = vertex;
+ xmax = vertex;
}
if (vertex.y < ymin.y) {
- ymin = vertex;
+ ymin = vertex;
}
if (vertex.y > ymax.y) {
- ymax = vertex;
+ ymax = vertex;
}
if (vertex.z < zmin.z) {
- zmin = vertex;
+ zmin = vertex;
}
if (vertex.z > zmax.z) {
- zmax = vertex;
+ zmax = vertex;
}
- }
+ }
// Set points dia1 & dia2 to the maximally separated pair
Vector3 dia1 = xmin;
Vector3 dia2 = xmax;
{
// Set xspan = distance between the 2 points xmin & xmax (squared)
- double xspan = (xmax - xmin).squaredMagnitude();
+ float xspan = (xmax - xmin).squaredMagnitude();
// Same for y & z spans
- double yspan = (ymax - ymin).squaredMagnitude();
- double zspan = (zmax - zmin).squaredMagnitude();
+ float yspan = (ymax - ymin).squaredMagnitude();
+ float zspan = (zmax - zmin).squaredMagnitude();
- double maxspan = xspan;
+ float maxspan = xspan;
if (yspan > maxspan) {
- maxspan = yspan;
- dia1 = ymin;
+ maxspan = yspan;
+ dia1 = ymin;
dia2 = ymax;
- }
+ }
if (zspan > maxspan) {
maxspan = zspan;
- dia1 = zmin;
+ dia1 = zmin;
dia2 = zmax;
- }
+ }
}
@@ -500,52 +501,52 @@ void MeshAlg::computeBounds(
// calculate initial radius^2 and radius
Vector3 d = dia2 - sphere.center;
- double radSq = d.squaredMagnitude();
- double rad = sqrt(radSq);
+ float radSq = d.squaredMagnitude();
+ float rad = sqrt(radSq);
// SECOND PASS: increment current sphere
- double old_to_p, old_to_new;
+ float old_to_p, old_to_new;
for (int v = 0; v < vertexArray.size(); ++v) {
const Vector3& vertex = vertexArray[v];
d = vertex - center;
- double old_to_p_sq = d.squaredMagnitude();
+ float old_to_p_sq = d.squaredMagnitude();
- // do r^2 test first
+ // do r^2 test first
if (old_to_p_sq > radSq) {
- // this point is outside of current sphere
- old_to_p = sqrt(old_to_p_sq);
+ // this point is outside of current sphere
+ old_to_p = sqrt(old_to_p_sq);
- // calc radius of new sphere
- rad = (rad + old_to_p) / 2.0;
+ // calc radius of new sphere
+ rad = (rad + old_to_p) / 2.0f;
// for next r^2 compare
- radSq = rad * rad;
- old_to_new = old_to_p - rad;
+ radSq = rad * rad;
+ old_to_new = old_to_p - rad;
- // calc center of new sphere
+ // calc center of new sphere
center = (rad * center + old_to_new * vertex) / old_to_p;
- }
- }
+ }
+ }
- const Vector3 min(xmin.x, ymin.y, zmin.z);
- const Vector3 max(xmax.x, ymax.y, zmax.z);
+ const Vector3 min(xmin.x, ymin.y, zmin.z);
+ const Vector3 max(xmax.x, ymax.y, zmax.z);
- box = AABox(min, max);
+ box = AABox(min, max);
- const float boxRadSq = (max - min).squaredMagnitude() * 0.25f;
+ const float boxRadSq = (max - min).squaredMagnitude() * 0.25f;
- if (boxRadSq >= radSq){
- if (isNaN(center.x) || ! isFinite(rad)) {
- sphere = Sphere(Vector3::zero(), finf());
- } else {
- sphere = Sphere(center, rad);
- }
- } else {
- sphere = Sphere((max + min) * 0.5f, sqrt(boxRadSq));
- }
+ if (boxRadSq >= radSq){
+ if (isNaN(center.x) || ! isFinite(rad)) {
+ sphere = Sphere(Vector3::zero(), finf());
+ } else {
+ sphere = Sphere(center, rad);
+ }
+ } else {
+ sphere = Sphere((max + min) * 0.5f, sqrt(boxRadSq));
+ }
}
void MeshAlg::computeTangentSpaceBasis(
@@ -600,7 +601,10 @@ void MeshAlg::computeTangentSpaceBasis(
float r = te1.x * te2.y - te1.y * te2.x;
if (r == 0.0) {
// degenerate case
- Vector3::generateOrthonormalBasis(t, b, n, true);
+ if (! n.isFinite() || n.isZero()) {
+ n = Vector3::unitY();
+ }
+ n.getTangents(t, b);
} else {
r = 1.0f / r;
t = (te2.y * ve1 - te1.y * ve2) * r;
diff --git a/dep/g3dlite/source/MeshAlgAdjacency.cpp b/dep/g3dlite/source/MeshAlgAdjacency.cpp
index f0bf3382131..e3bdbd635e1 100644
--- a/dep/g3dlite/source/MeshAlgAdjacency.cpp
+++ b/dep/g3dlite/source/MeshAlgAdjacency.cpp
@@ -5,7 +5,7 @@
@created 2003-09-14
@edited 2010-04-26
- Copyright 2000-2010, Morgan McGuire.
+ Copyright 2000-2012, Morgan McGuire.
All rights reserved.
*/
@@ -125,6 +125,11 @@ public:
return *this;
}
+ bool isValid() const {
+ return ! m_end;
+ }
+
+ /** @deprecated Use isValid */
bool hasMore() const {
return ! m_end;
}
@@ -254,7 +259,7 @@ void MeshAlg::computeAdjacency(
MeshEdgeTable::Iterator cur = edgeTable.begin();
Array<Edge> tempEdgeArray;
- while (cur.hasMore()) {
+ while (cur.isValid()) {
MeshEdgeTable::FaceIndexArray& faceIndexArray = cur.faceIndex();
// Process this edge
@@ -620,7 +625,7 @@ void MeshAlg::weldAdjacency(
Array<Face>& faceArray,
Array<Edge>& edgeArray,
Array<Vertex>& vertexArray,
- double radius) {
+ float radius) {
// Num vertices
const int n = originalGeometry.size();
diff --git a/dep/g3dlite/source/MeshAlgWeld.cpp b/dep/g3dlite/source/MeshAlgWeld.cpp
index 6067f17c2fb..b1e602f9566 100644
--- a/dep/g3dlite/source/MeshAlgWeld.cpp
+++ b/dep/g3dlite/source/MeshAlgWeld.cpp
@@ -40,18 +40,18 @@ public:
Array<int>& toOld;
/** Must be less than one grid cell, not checked */
- const double radius;
+ const float radius;
/** (oldVertexArray[i] - offset) * scale is on the range [0, 1] */
Vector3 offset;
Vector3 scale;
- Welder(
- const Array<Vector3>& _oldVertexArray,
- Array<Vector3>& _newVertexArray,
- Array<int>& _toNew,
- Array<int>& _toOld,
- double _radius);
+ Welder
+ (const Array<Vector3>& _oldVertexArray,
+ Array<Vector3>& _newVertexArray,
+ Array<int>& _toNew,
+ Array<int>& _toOld,
+ float _radius);
/**
Computes the grid index from an ordinate.
@@ -73,6 +73,7 @@ template<> struct HashTrait<G3D::_internal::Welder::List*> {
static size_t hashCode(const G3D::_internal::Welder::List* key) { return reinterpret_cast<size_t>(key); }
};
+
namespace G3D {
namespace _internal {
@@ -81,7 +82,7 @@ Welder::Welder(
Array<Vector3>& _newVertexArray,
Array<int>& _toNew,
Array<int>& _toOld,
- double _radius) :
+ float _radius) :
oldVertexArray(_oldVertexArray),
newVertexArray(_newVertexArray),
toNew(_toNew),
@@ -102,10 +103,10 @@ Welder::Welder(
scale = maxBound - minBound;
for (int i = 0; i < 3; ++i) {
// The model might have zero extent along some axis
- if (fuzzyEq(scale[i], 0.0)) {
+ if (fuzzyEq(scale[i], 0.0f)) {
scale[i] = 1.0;
} else {
- scale[i] = 1.0 / scale[i];
+ scale[i] = 1.0f / scale[i];
}
}
}
@@ -204,10 +205,10 @@ void MeshAlg::computeWeld(
Array<Vector3>& newVertexArray,
Array<int>& toNew,
Array<int>& toOld,
- double radius) {
+ float radius) {
- _internal::Welder welder(oldVertexArray, newVertexArray, toNew, toOld, radius);
- welder.weld();
+ shared_ptr<_internal::Welder> welder = shared_ptr<_internal::Welder> (new _internal::Welder(oldVertexArray, newVertexArray, toNew, toOld, radius));
+ welder->weld();
}
} // G3D namespace
diff --git a/dep/g3dlite/source/MeshBuilder.cpp b/dep/g3dlite/source/MeshBuilder.cpp
index 1bf2bab5d1c..6109af94697 100644
--- a/dep/g3dlite/source/MeshBuilder.cpp
+++ b/dep/g3dlite/source/MeshBuilder.cpp
@@ -36,7 +36,7 @@ void MeshBuilder::commit(std::string& n, Array<int>& indexArray, Array<Vector3>&
close = minEdgeLen * 0.1;
}
- MeshAlg::computeWeld(triList, outvertexArray, toNew, toOld, close);
+ MeshAlg::computeWeld(triList, outvertexArray, toNew, toOld, (float)close);
// Construct triangles
for (int t = 0; t < triList.size(); t += 3) {
@@ -62,19 +62,21 @@ void MeshBuilder::centerTriList() {
computeBounds(vmin, vmax);
- Vector3 diagonal = vmax - vmin;
- double scale = max(max(diagonal.x, diagonal.y), diagonal.z) / 2;
+ const Vector3 diagonal = vmax - vmin;
+ float scale = max(max(diagonal.x, diagonal.y), diagonal.z) / 2.0f;
debugAssert(scale > 0);
- Vector3 translation = vmin + diagonal / 2;
+ const Vector3 translation = vmin + diagonal / 2.0f;
// Center and scale all vertices in the input list
int v;
- //Matrix3 rot90 = Matrix3::fromAxisAngle(Vector3::UNIT_Y, toRadians(180)) * Matrix3::fromAxisAngle(Vector3::UNIT_X, toRadians(90));
- for (v = 0; v < triList.size(); ++v) {
- triList[v] = (triList[v] - translation) / scale;
- //triList[v] = rot90 * triList[v];
+ if (scaleAndCenter) {
+ //Matrix3 rot90 = Matrix3::fromAxisAngle(Vector3::UNIT_Y, toRadians(180)) * Matrix3::fromAxisAngle(Vector3::UNIT_X, toRadians(90));
+ for (v = 0; v < triList.size(); ++v) {
+ triList[v] = (triList[v] - translation) / scale;
+ //triList[v] = rot90 * triList[v];
+ }
}
}
@@ -94,9 +96,9 @@ void MeshBuilder::computeBounds(Vector3& min, Vector3& max) {
void MeshBuilder::addTriangle(const Vector3& a, const Vector3& b, const Vector3& c) {
triList.append(a, b, c);
- if (_twoSided) {
- triList.append(c, b, a);
- }
+ if (_twoSided) {
+ triList.append(c, b, a);
+ }
}
@@ -107,7 +109,7 @@ void MeshBuilder::addQuad(const Vector3& a, const Vector3& b, const Vector3& c,
void MeshBuilder::addTriangle(const Triangle& t) {
- addTriangle(t.vertex(0), t.vertex(1), t.vertex(2));
+ addTriangle(t.vertex(0), t.vertex(1), t.vertex(2));
}
} // namespace
diff --git a/dep/g3dlite/source/NetAddress.cpp b/dep/g3dlite/source/NetAddress.cpp
index 64d692d4763..95f975b0ca0 100644
--- a/dep/g3dlite/source/NetAddress.cpp
+++ b/dep/g3dlite/source/NetAddress.cpp
@@ -1,9 +1,9 @@
/**
- @file NetMessage.cpp
+ \file NetAddress.cpp
- @maintainer Morgan McGuire, morgan@cs.brown.edu
- @created 2005-02-06
- @edited 2005-02-06
+ \maintainer Morgan McGuire, http://graphics.cs.williams.edu
+ \created 2005-02-06
+ \edited 2013-03-17
*/
#include "G3D/platform.h"
#include "G3D/NetAddress.h"
@@ -13,6 +13,7 @@
#include "G3D/stringutils.h"
#include "G3D/System.h"
#include "G3D/NetworkDevice.h"
+#include "G3D/Log.h"
#if defined(G3D_LINUX) || defined(G3D_OSX)
#include <unistd.h>
@@ -23,6 +24,7 @@
#include <netdb.h>
#include <netinet/tcp.h>
#define _alloca alloca
+ #define SOCKET_ERROR -1
# ifndef SOCKADDR_IN
# define SOCKADDR_IN struct sockaddr_in
@@ -40,6 +42,7 @@
namespace G3D {
+
NetAddress::NetAddress() {
System::memset(&addr, 0, sizeof(addr));
}
@@ -58,15 +61,15 @@ void NetAddress::init(uint32 host, uint16 port) {
}
-NetAddress::NetAddress(
- const std::string& hostname,
+NetAddress::NetAddress
+ (const std::string& hostname,
uint16 port) {
init(hostname, port);
}
-void NetAddress::init(
- const std::string& hostname,
+void NetAddress::init
+ (const std::string& hostname,
uint16 port) {
uint32 addr;
@@ -77,7 +80,7 @@ void NetAddress::init(
addr = inet_addr(hostname.c_str());
}
- // The address wasn't in numeric form, resolve it
+ // The address wasn't in numeric form, resolve it
if (addr == INADDR_NONE) {
// Get the IP address of the server and store it in host
struct hostent* host = gethostbyname(hostname.c_str());
@@ -122,13 +125,35 @@ NetAddress::NetAddress(const SOCKADDR_IN& a) {
NetAddress::NetAddress(const struct in_addr& addr, uint16 port) {
- #ifdef G3D_WIN32
+ #ifdef G3D_WINDOWS
init(ntohl(addr.S_un.S_addr), port);
#else
init(htonl(addr.s_addr), port);
#endif
}
+void NetAddress::localHostAddresses(Array<NetAddress>& array) {
+ array.resize(0);
+
+ char ac[256];
+
+ if (gethostname(ac, sizeof(ac)) == SOCKET_ERROR) {
+ Log::common()->printf("Error while getting local host name\n");
+ return;
+ }
+
+ struct hostent* phe = gethostbyname(ac);
+ if (phe == 0) {
+ Log::common()->printf("Error while getting local host address\n");
+ return;
+ }
+
+ for (int i = 0; (phe->h_addr_list[i] != 0); ++i) {
+ struct in_addr addr;
+ memcpy(&addr, phe->h_addr_list[i], sizeof(struct in_addr));
+ array.append(NetAddress(addr));
+ }
+}
void NetAddress::serialize(class BinaryOutput& b) const {
b.writeUInt32(ip());
diff --git a/dep/g3dlite/source/NetworkDevice.cpp b/dep/g3dlite/source/NetworkDevice.cpp
index 1fc794479f5..e9d4f112c5a 100644
--- a/dep/g3dlite/source/NetworkDevice.cpp
+++ b/dep/g3dlite/source/NetworkDevice.cpp
@@ -31,19 +31,18 @@ std::ostream& operator<<(std::ostream& os, const NetAddress& a) {
static void logSocketInfo(const SOCKET& sock) {
uint32 val;
socklen_t sz = 4;
- int ret;
- ret = getsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char*)&val, (socklen_t*)&sz);
+ getsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char*)&val, (socklen_t*)&sz);
logPrintf("SOL_SOCKET/SO_RCVBUF = %d\n", val);
- ret = getsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char*)&val, (socklen_t*)&sz);
+ getsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char*)&val, (socklen_t*)&sz);
logPrintf("SOL_SOCKET/SO_SNDBUF = %d\n", val);
// Note: timeout = 0 means no timeout
- ret = getsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char*)&val, (socklen_t*)&sz);
+ getsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char*)&val, (socklen_t*)&sz);
logPrintf("SOL_SOCKET/SO_RCVTIMEO = %d\n", val);
- ret = getsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (char*)&val, (socklen_t*)&sz);
+ getsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (char*)&val, (socklen_t*)&sz);
logPrintf("SOL_SOCKET/SO_SNDTIMEO = %d\n", val);
}
@@ -63,7 +62,7 @@ static int selectOneReadSocket(const SOCKET& sock) {
FD_ZERO(&socketSet);
FD_SET(sock, &socketSet);
- int ret = select(sock + 1, &socketSet, NULL, NULL, &timeout);
+ int ret = select((int)sock + 1, &socketSet, NULL, NULL, &timeout);
return ret;
}
@@ -102,7 +101,7 @@ static int selectOneWriteSocket(const SOCKET& sock) {
FD_ZERO(&socketSet);
FD_SET(sock, &socketSet);
- return select(sock + 1, NULL, &socketSet, NULL, &timeout);
+ return select((int)sock + 1, NULL, &socketSet, NULL, &timeout);
}
///////////////////////////////////////////////////////////////////////////////
@@ -146,7 +145,7 @@ std::string NetworkDevice::localHostName() const {
return gethostbyname(ac)->h_name;
}
-#ifndef G3D_WIN32
+#ifndef G3D_WINDOWS
const char* errnoToString() {
switch (errno) {
case EBADF:
@@ -192,31 +191,31 @@ void NetworkDevice::EthernetAdapter::describe(TextOutput& t) const {
t.writeNewline();
t.writeSymbols("hostname", "=");
- t.writeString(hostname);
+ t.writeString(hostname + ";");
t.writeNewline();
t.writeSymbols("name", "=");
- t.writeString(name);
+ t.writeString(name + ";");
t.writeNewline();
t.writeSymbols("ip", "=");
- t.writeSymbol(formatIP(ip));
+ t.writeSymbol("\"" + formatIP(ip) + "\";");
t.writeNewline();
t.writeSymbols("subnet", "=");
- t.writeSymbol(formatIP(subnet));
+ t.writeSymbol("\"" + formatIP(subnet) + "\";");
t.writeNewline();
t.writeSymbols("broadcast", "=");
- t.writeSymbol(formatIP(broadcast));
+ t.writeSymbol("\"" + formatIP(broadcast) + "\";");
t.writeNewline();
t.writeSymbols("mac", "=");
- t.writeSymbol(formatMAC(mac));
+ t.writeSymbol("\"" + formatMAC(mac) + "\";");
t.writeNewline();
t.popIndent();
- t.writeSymbol("}");
+ t.writeSymbol("};");
t.writeNewline();
}
@@ -243,15 +242,17 @@ std::string NetworkDevice::formatMAC(const uint8 MAC[6]) {
}
-#ifdef G3D_WIN32
+#ifdef G3D_WINDOWS
bool NetworkDevice::init() {
debugAssert(! initialized);
logPrintf("Network Startup");
logPrintf("Starting WinSock networking.\n");
- WSADATA wsda;
- WSAStartup(MAKEWORD(G3D_WINSOCK_MAJOR_VERSION, G3D_WINSOCK_MINOR_VERSION), &wsda);
+
+// G3D now initializes winsock through ENet
+// WSADATA wsda;
+// WSAStartup(MAKEWORD(G3D_WINSOCK_MAJOR_VERSION, G3D_WINSOCK_MINOR_VERSION), &wsda);
std::string hostname = "localhost";
{
@@ -280,7 +281,9 @@ bool NetworkDevice::init() {
std::string machine = localHostName();
std::string addr = NetAddress(machine, 0).ipString();
+ /*
logPrintf(
+
"Network:\n"
" Status: %s\n"
" Loaded winsock specification version %d (%d is "
@@ -293,6 +296,7 @@ bool NetworkDevice::init() {
wsda.wHighVersion,
wsda.iMaxSockets,
wsda.iMaxUdpDg);
+ */
// TODO: WSAIoctl for subnet and broadcast addresses
// http://msdn.microsoft.com/en-us/library/ms741621(VS.85).aspx
@@ -449,7 +453,7 @@ bool NetworkDevice::init() {
}
// Extract all interesting adapters from the table
- for (AdapterTable::Iterator it = table.begin(); it.hasMore(); ++it) {
+ for (AdapterTable::Iterator it = table.begin(); it.isValid(); ++it) {
const EthernetAdapter& adapter = it->value;
// Only add adapters that have IP addresses
@@ -471,11 +475,10 @@ bool NetworkDevice::init() {
void NetworkDevice::_cleanup() {
debugAssert(initialized);
- logPrintf("Network Cleanup");
-# ifdef G3D_WIN32
- WSACleanup();
+# ifdef G3D_WINDOWS
+ // Now handled through enet
+// WSACleanup();
# endif
- logPrintf("Network cleaned up.");
}
bool NetworkDevice::bind(SOCKET sock, const NetAddress& addr) const {
@@ -497,7 +500,7 @@ bool NetworkDevice::bind(SOCKET sock, const NetAddress& addr) const {
void NetworkDevice::closesocket(SOCKET& sock) const {
if (sock != 0) {
- #ifdef G3D_WIN32
+ #ifdef G3D_WINDOWS
::closesocket(sock);
#else
close(sock);
@@ -512,7 +515,7 @@ void NetworkDevice::closesocket(SOCKET& sock) const {
void NetworkDevice::localHostAddresses(Array<NetAddress>& array) const {
array.resize(0);
- char ac[128];
+ char ac[256];
if (gethostname(ac, sizeof(ac)) == SOCKET_ERROR) {
Log::common()->printf("Error while getting local host name\n");
@@ -606,13 +609,16 @@ static void increaseBufferSize(SOCKET sock) {
//////////////////////////////////////////////////////////////////////////////
ReliableConduitRef ReliableConduit::create(const NetAddress& address) {
- return new ReliableConduit(address);
+ return ReliableConduitRef(new ReliableConduit(address));
}
-ReliableConduit::ReliableConduit(
- const NetAddress& _addr) : state(NO_MESSAGE), receiveBuffer(NULL),
- receiveBufferTotalSize(0), receiveBufferUsedSize(0) {
+ReliableConduit::ReliableConduit
+ (const NetAddress& _addr) :
+ state(NO_MESSAGE),
+ receiveBuffer(NULL),
+ receiveBufferTotalSize(0),
+ receiveBufferUsedSize(0) {
NetworkDevice* nd = NetworkDevice::instance();
@@ -829,7 +835,7 @@ uint32 ReliableConduit::waitingMessageType() {
void ReliableConduit::sendBuffer(const BinaryOutput& b) {
NetworkDevice* nd = NetworkDevice::instance();
- int ret = ::send(sock, (const char*)b.getCArray(), b.size(), 0);
+ int ret = ::send(sock, (const char*)b.getCArray(), (int)b.size(), 0);
if (ret == SOCKET_ERROR) {
Log::common()->println("Error occured while sending message.");
@@ -938,11 +944,11 @@ void ReliableConduit::receiveIntoBuffer() {
// Read the data itself
int ret = 0;
- uint32 left = messageSize - receiveBufferUsedSize;
+ uint32 left = messageSize - (uint32)receiveBufferUsedSize;
int count = 0;
while ((ret != SOCKET_ERROR) && (left > 0) && (count < 100)) {
- ret = recv(sock, ((char*)receiveBuffer) + receiveBufferUsedSize, left, 0);
+ ret = recv(sock, ((char*)receiveBuffer) + (uint32)receiveBufferUsedSize, left, 0);
if (ret > 0) {
left -= ret;
@@ -985,11 +991,12 @@ LightweightConduitRef LightweightConduit::create(
bool enableReceive,
bool enableBroadcast) {
- return new LightweightConduit(receivePort, enableReceive, enableBroadcast);
+ return LightweightConduitRef(new LightweightConduit(receivePort, enableReceive, enableBroadcast));
}
-LightweightConduit::LightweightConduit(
- uint16 port,
+
+LightweightConduit::LightweightConduit
+ (uint16 port,
bool enableReceive,
bool enableBroadcast) {
NetworkDevice* nd = NetworkDevice::instance();
@@ -1064,7 +1071,7 @@ bool LightweightConduit::receive(NetAddress& sender) {
void LightweightConduit::sendBuffer(const NetAddress& a, BinaryOutput& b) {
NetworkDevice* nd = NetworkDevice::instance();
- if (sendto(sock, (const char*)b.getCArray(), b.size(), 0,
+ if (sendto(sock, (const char*)b.getCArray(), (int)b.size(), 0,
(struct sockaddr *) &(a.addr), sizeof(a.addr)) == SOCKET_ERROR) {
Log::common()->printf("Error occured while sending packet "
"to %s\n", inet_ntoa(a.addr.sin_addr));
@@ -1137,7 +1144,7 @@ uint32 LightweightConduit::waitingMessageType() {
///////////////////////////////////////////////////////////////////////////////
NetListenerRef NetListener::create(const uint16 port) {
- return new NetListener(port);
+ return NetListenerRef(new NetListener(port));
}
@@ -1215,20 +1222,20 @@ ReliableConduitRef NetListener::waitForConnection() {
Log::common()->println("Error in NetListener::acceptConnection.");
Log::common()->println(socketErrorCode());
nd->closesocket(sock);
- return NULL;
+ return ReliableConduitRef();
}
Log::common()->printf("%s connected, transferred to socket %d.\n",
inet_ntoa(remote_addr.sin_addr), sClient);
- #ifndef G3D_WIN32
- return new ReliableConduit(sClient,
+ #ifndef G3D_WINDOWS
+ return ReliableConduitRef(new ReliableConduit(sClient,
NetAddress(htonl(remote_addr.sin_addr.s_addr),
- ntohs(remote_addr.sin_port)));
+ ntohs(remote_addr.sin_port))));
#else
- return new ReliableConduit(sClient,
+ return ReliableConduitRef(ReliableConduitRef(new ReliableConduit(sClient,
NetAddress(ntohl(remote_addr.sin_addr.S_un.S_addr),
- ntohs(remote_addr.sin_port)));
+ ntohs(remote_addr.sin_port)))));
#endif
}
@@ -1247,17 +1254,17 @@ bool NetListener::clientWaiting() const {
void NetworkDevice::describeSystem(
TextOutput& t) {
- t.writeSymbols("Network", "{");
+ t.writeSymbols("Network", "=", "{");
t.writeNewline();
t.pushIndent();
for (int i = 0; i < m_adapterArray.size(); ++i) {
+ t.printf("Adapter%d =", i);
m_adapterArray[i].describe(t);
}
-
t.popIndent();
- t.writeSymbols("}");
+ t.writeSymbols("};");
t.writeNewline();
t.writeNewline();
}
diff --git a/dep/g3dlite/source/PhysicsFrame.cpp b/dep/g3dlite/source/PhysicsFrame.cpp
index 30fbdf8d619..9146d78ff5b 100644
--- a/dep/g3dlite/source/PhysicsFrame.cpp
+++ b/dep/g3dlite/source/PhysicsFrame.cpp
@@ -1,10 +1,10 @@
/**
- @file PhysicsFrame.cpp
+ \file PhysicsFrame.cpp
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
+ \maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @created 2002-07-09
- @edited 2010-03-25
+ \created 2002-07-09
+ \edited 2013-04-25
*/
#include "G3D/platform.h"
@@ -13,6 +13,7 @@
#include "G3D/PhysicsFrame.h"
#include "G3D/BinaryInput.h"
#include "G3D/BinaryOutput.h"
+#include "G3D/UprightFrame.h"
namespace G3D {
@@ -22,31 +23,44 @@ PhysicsFrame::PhysicsFrame() {
}
-PhysicsFrame::PhysicsFrame(
- const CoordinateFrame& coordinateFrame) {
-
+PhysicsFrame::PhysicsFrame
+ (const CoordinateFrame& coordinateFrame) {
translation = coordinateFrame.translation;
rotation = Quat(coordinateFrame.rotation);
}
+Any PhysicsFrame::toAny() const {
+ // Prefer to serialize as a CFrame, which is easier to read
+ if (false) {
+ Any a(Any::ARRAY, "PFrame");
+ a.append(rotation, translation.toAny("Point3"));
+ return a;
+ } else {
+ return CFrame(*this).toAny();
+ }
+}
+
+
PhysicsFrame::PhysicsFrame(const Any& a) {
const std::string& n = toLower(a.name());
*this = PhysicsFrame();
- if (beginsWith(n, "vector3")) {
- *this = PhysicsFrame(Vector3(a));
+ if (beginsWith(n, "vector3") || beginsWith(n, "point3")) {
+ *this = PhysicsFrame(Point3(a));
} else if (beginsWith(n, "matrix3")) {
*this = PhysicsFrame(Matrix3(a));
- } else if (beginsWith(n, "cframe") || beginsWith(n, "coordinateframe")) {
- *this = PhysicsFrame(CoordinateFrame(a));
+ } else if (beginsWith(n, "cframe") || beginsWith(n, "coordinateframe") || beginsWith(n, "matrix4")) {
+ *this = CoordinateFrame(a);
+ } else if (beginsWith(n, "uprightframe")) {
+ *this = UprightFrame(a).toCoordinateFrame();
} else if (beginsWith(n, "pframe") || beginsWith(n, "physicsframe")) {
if (a.type() == Any::ARRAY) {
a.verifySize(2);
rotation = a[0];
translation = a[1];
} else {
- for (Any::AnyTable::Iterator it = a.table().begin(); it.hasMore(); ++it) {
+ for (Any::AnyTable::Iterator it = a.table().begin(); it.isValid(); ++it) {
const std::string& n = toLower(it->key);
if (n == "translation") {
translation = it->value;
@@ -57,6 +71,8 @@ PhysicsFrame::PhysicsFrame(const Any& a) {
}
}
}
+ } else {
+ a.verify(false, "Unrecognized class name where a PhysicsFrame or equivalent was expected.");
}
}
diff --git a/dep/g3dlite/source/PhysicsFrameSpline.cpp b/dep/g3dlite/source/PhysicsFrameSpline.cpp
index 2dfdb6f9139..ca9d6cc55d7 100644
--- a/dep/g3dlite/source/PhysicsFrameSpline.cpp
+++ b/dep/g3dlite/source/PhysicsFrameSpline.cpp
@@ -6,55 +6,53 @@
#include "G3D/PhysicsFrameSpline.h"
#include "G3D/Any.h"
#include "G3D/stringutils.h"
+#include "G3D/UprightFrame.h"
namespace G3D {
PhysicsFrameSpline::PhysicsFrameSpline() {}
+
PhysicsFrameSpline::PhysicsFrameSpline(const Any& any) {
- *this = any;
+ if (beginsWith(any.name(), "PFrameSpline") ||
+ beginsWith(any.name(), "PhysicsFrameSpline") ||
+ beginsWith(any.name(), "CFrameSpline") ||
+ beginsWith(any.name(), "CoordinateFrameSpline") ||
+ beginsWith(any.name(), "UprightSpline") ||
+ beginsWith(any.name(), "UprightFrameSpline")) {
+ AnyTableReader t(any);
+ init(t);
+ t.verifyDone();
+ } else {
+ // Must be a single control point
+ control.append(any);
+ time.append(0);
+ }
}
-PhysicsFrameSpline& PhysicsFrameSpline::operator=(const Any& any) {
- const std::string& n = toLower(any.name());
- *this = PhysicsFrameSpline();
-
- if (n == "physicsframespline" || n == "pframespline") {
- any.verifyName("PhysicsFrameSpline", "PFrameSpline");
-
- for (Any::AnyTable::Iterator it = any.table().begin(); it.hasMore(); ++it) {
- const std::string& k = toLower(it->key);
- if (k == "cyclic") {
- cyclic = it->value;
- } else if (k == "control") {
- const Any& v = it->value;
- v.verifyType(Any::ARRAY);
- control.resize(v.size());
- for (int i = 0; i < control.size(); ++i) {
- control[i] = v[i];
- }
- if (! any.containsKey("time")) {
- time.resize(control.size());
- for (int i = 0; i < time.size(); ++i) {
- time[i] = i;
- }
- }
- } else if (k == "finalinterval") {
- finalInterval = it->value;
- } else if (k == "time") {
- const Any& v = it->value;
- v.verifyType(Any::ARRAY);
- time.resize(v.size());
- for (int i = 0; i < time.size(); ++i) {
- time[i] = v[i];
- }
+
+bool PhysicsFrameSpline::operator==(const PhysicsFrameSpline& other) const {
+ if ((extrapolationMode == other.extrapolationMode) &&
+ (time.size() == other.size()) &&
+ (finalInterval == other.finalInterval) &&
+ (control.size() == other.control.size())) {
+ // Check actual values
+ for (int i = 0; i < time.size(); ++i) {
+ if (time[i] != other.time[i]) {
+ return false;
+ }
+ }
+
+ for (int i = 0; i < control.size(); ++i) {
+ if (control[i] != other.control[i]) {
+ return false;
}
}
+
+ return true;
} else {
- // Must be a PhysicsFrame constructor of some kind
- append(any);
+ return false;
}
- return *this;
}
@@ -62,6 +60,11 @@ void PhysicsFrameSpline::correct(PhysicsFrame& frame) const {
frame.rotation.unitize();
}
+void PhysicsFrameSpline::scaleControlPoints(float scaleFactor) {
+ for (int i = 0; i < control.size(); ++i) {
+ control[i].translation *= scaleFactor;
+ }
+}
void PhysicsFrameSpline::ensureShortestPath(PhysicsFrame* A, int N) const {
for (int i = 1; i < N; ++i) {
diff --git a/dep/g3dlite/source/Plane.cpp b/dep/g3dlite/source/Plane.cpp
index 9b7991c0333..d6b41d3605d 100644
--- a/dep/g3dlite/source/Plane.cpp
+++ b/dep/g3dlite/source/Plane.cpp
@@ -4,7 +4,7 @@
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
@created 2003-02-06
- @edited 2006-01-29
+ \edited 2011-02-29
*/
#include "G3D/platform.h"
@@ -12,31 +12,47 @@
#include "G3D/BinaryOutput.h"
#include "G3D/BinaryInput.h"
#include "G3D/stringutils.h"
+#include "G3D/Any.h"
namespace G3D {
+Plane::Plane(const Any& a) {
+ a.verifyName("Plane");
+ a.verifySize(2);
+ a.verifyType(Any::ARRAY);
+ *this = Plane(Vector3(a[0]), Point3(a[1]));
+}
+
+
+Any Plane::toAny() const {
+ Any a(Any::ARRAY, "Plane");
+ a.append(normal(), normal() * _distance);
+ return a;
+}
+
+
Plane::Plane(class BinaryInput& b) {
- deserialize(b);
+ deserialize(b);
}
void Plane::serialize(class BinaryOutput& b) const {
- _normal.serialize(b);
- b.writeFloat64(_distance);
+ _normal.serialize(b);
+ b.writeFloat64(_distance);
}
void Plane::deserialize(class BinaryInput& b) {
- _normal.deserialize(b);
- _distance = (float)b.readFloat64();
+ _normal.deserialize(b);
+ _distance = (float)b.readFloat64();
}
-Plane::Plane(
- Vector4 point0,
- Vector4 point1,
- Vector4 point2) {
-
+Plane::Plane
+(Vector4 point0,
+ Vector4 point1,
+ Vector4 point2) {
+
debugAssertM(
point0.w != 0 ||
point1.w != 0 ||
diff --git a/dep/g3dlite/source/Quat.cpp b/dep/g3dlite/source/Quat.cpp
index e06483b44cd..25c1711a94b 100644
--- a/dep/g3dlite/source/Quat.cpp
+++ b/dep/g3dlite/source/Quat.cpp
@@ -1,12 +1,12 @@
/**
- @file Quat.cpp
+ \file G3D/Quat.cpp
Quaternion implementation based on Watt & Watt page 363
- @author Morgan McGuire, graphics3d.com
+ \uthor Morgan McGuire, graphics3d.com
- @created 2002-01-23
- @edited 2010-03-31
+ \created 2002-01-23
+ \edited 2010-05-31
*/
#include "G3D/Quat.h"
@@ -45,50 +45,57 @@ Quat::Quat(const class Any& a) {
}
+Any Quat::toAny() const {
+ Any a(Any::ARRAY, "Quat");
+ a.append(x, y, z, w);
+ return a;
+}
+
+
Quat::Quat(const Matrix3& rot) {
static const int plus1mod3[] = {1, 2, 0};
// Find the index of the largest diagonal component
- // These ? operations hopefully compile to conditional
- // move instructions instead of branches.
+ // These ? operations hopefully compile to conditional
+ // move instructions instead of branches.
int i = (rot[1][1] > rot[0][0]) ? 1 : 0;
i = (rot[2][2] > rot[i][i]) ? 2 : i;
- // Find the indices of the other elements
+ // Find the indices of the other elements
int j = plus1mod3[i];
int k = plus1mod3[j];
- // Index the elements of the vector part of the quaternion as a float*
+ // Index the elements of the vector part of the quaternion as a float*
float* v = (float*)(this);
- // If we attempted to pre-normalize and trusted the matrix to be
- // perfectly orthonormal, the result would be:
- //
+ // If we attempted to pre-normalize and trusted the matrix to be
+ // perfectly orthonormal, the result would be:
+ //
// double c = sqrt((rot[i][i] - (rot[j][j] + rot[k][k])) + 1.0)
// v[i] = -c * 0.5
// v[j] = -(rot[i][j] + rot[j][i]) * 0.5 / c
// v[k] = -(rot[i][k] + rot[k][i]) * 0.5 / c
// w = (rot[j][k] - rot[k][j]) * 0.5 / c
- //
- // Since we're going to pay the sqrt anyway, we perform a post normalization, which also
- // fixes any poorly normalized input. Multiply all elements by 2*c in the above, giving:
+ //
+ // Since we're going to pay the sqrt anyway, we perform a post normalization, which also
+ // fixes any poorly normalized input. Multiply all elements by 2*c in the above, giving:
- // nc2 = -c^2
+ // nc2 = -c^2
double nc2 = ((rot[j][j] + rot[k][k]) - rot[i][i]) - 1.0;
- v[i] = nc2;
+ v[i] = (float)nc2;
w = (rot[j][k] - rot[k][j]);
v[j] = -(rot[i][j] + rot[j][i]);
v[k] = -(rot[i][k] + rot[k][i]);
- // We now have the correct result with the wrong magnitude, so normalize it:
+ // We now have the correct result with the wrong magnitude, so normalize it:
float s = sqrt(x*x + y*y + z*z + w*w);
if (s > 0.00001f) {
- s = 1.0f / s;
- x *= s;
- y *= s;
- z *= s;
- w *= s;
+ s = 1.0f / s;
+ x *= s;
+ y *= s;
+ z *= s;
+ w *= s;
} else {
// The quaternion is nearly zero. Make it 0 0 0 1
x = 0.0f;
@@ -116,25 +123,25 @@ void Quat::toAxisAngleRotation(
// Reduce the range of the angle.
- if (angle < 0) {
- angle = -angle;
- axis = -axis;
+ if (angle < 0) {
+ angle = -angle;
+ axis = -axis;
}
- while (angle > twoPi()) {
+ while (angle > twoPi()) {
angle -= twoPi();
}
- if (abs(angle) > pi()) {
- angle -= twoPi();
+ if (abs(angle) > pi()) {
+ angle -= twoPi();
}
// Make the angle positive.
- if (angle < 0.0f) {
- angle = -angle;
+ if (angle < 0.0f) {
+ angle = -angle;
axis = -axis;
- }
+ }
}
@@ -153,58 +160,71 @@ void Quat::toRotationMatrix(
rot = Matrix3(*this);
}
-
-Quat Quat::slerp(
- const Quat& _quat1,
+
+Quat Quat::slerp
+ (const Quat& _quat1,
float alpha,
- float threshold) const {
+ float threshold,
+ float maxAngle) const {
// From: Game Physics -- David Eberly pg 538-540
// Modified to include lerp for small angles, which
- // is a common practice.
+ // is a common practice.
- // See also:
- // http://number-none.com/product/Understanding%20Slerp,%20Then%20Not%20Using%20It/index.html
+ // See also:
+ // http://number-none.com/product/Understanding%20Slerp,%20Then%20Not%20Using%20It/index.html
const Quat& quat0 = *this;
Quat quat1 = _quat1;
// angle between quaternion rotations
- float phi;
- float cosphi = quat0.dot(quat1);
+ float halfPhi;
+ float cosHalfPhi = quat0.dot(quat1);
- if (cosphi < 0) {
+ if (cosHalfPhi < 0) {
// Change the sign and fix the dot product; we need to
// loop the other way to get the shortest path
quat1 = -quat1;
- cosphi = -cosphi;
+ cosHalfPhi = -cosHalfPhi;
}
// Using G3D::aCos will clamp the angle to 0 and pi
- phi = static_cast<float>(G3D::aCos(cosphi));
+ halfPhi = static_cast<float>(G3D::aCos(cosHalfPhi));
- if (phi >= threshold) {
+ debugAssertM(halfPhi >= 0.0f, "Assumed acos returned a value >= 0");
+ if (halfPhi * 2.0f * alpha > maxAngle) {
+ // Back off alpha
+ alpha = maxAngle * 0.5f / halfPhi;
+ }
+
+ if (halfPhi >= threshold) {
// For large angles, slerp
float scale0, scale1;
- scale0 = sin((1.0f - alpha) * phi);
- scale1 = sin(alpha * phi);
+ scale0 = sin((1.0f - alpha) * halfPhi);
+ scale1 = sin(alpha * halfPhi);
- return ( (quat0 * scale0) + (quat1 * scale1) ) / sin(phi);
+ return ( (quat0 * scale0) + (quat1 * scale1) ) / sin(halfPhi);
} else {
// For small angles, linear interpolate
- return quat0.nlerp(quat1, alpha);
+ return quat0.nlerp(quat1, alpha);
}
}
-Quat Quat::nlerp(
- const Quat& quat1,
+float Quat::angleBetween(const Quat& other) const {
+ const float d = this->dot(other);
+ return 2.0f * acos(fabsf(d));
+}
+
+
+Quat Quat::nlerp
+ (const Quat& quat1,
float alpha) const {
Quat result = (*this) * (1.0f - alpha) + quat1 * alpha;
- return result / result.magnitude();
+ return result / result.magnitude();
}
diff --git a/dep/g3dlite/source/Random.cpp b/dep/g3dlite/source/Random.cpp
index 2dda744a1ac..cbfa07dec0b 100644
--- a/dep/g3dlite/source/Random.cpp
+++ b/dep/g3dlite/source/Random.cpp
@@ -1,12 +1,12 @@
/**
- @file Random.cpp
+ \file Random.cpp
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
+ \maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @created 2009-01-02
- @edited 2009-03-29
+ \created 2009-01-02
+ \edited 2012-03-29
- Copyright 2000-2009, Morgan McGuire.
+ Copyright 2000-2012, Morgan McGuire.
All rights reserved.
*/
#include "G3D/Random.h"
@@ -18,15 +18,23 @@ Random& Random::common() {
return r;
}
+
Random::Random(void* x) : state(NULL), m_threadsafe(false) {
(void)x;
}
Random::Random(uint32 seed, bool threadsafe) : m_threadsafe(threadsafe) {
+ state = new uint32[N];
+ reset(seed, threadsafe);
+}
+
+
+void Random::reset(uint32 seed, bool threadsafe) {
+ m_threadsafe = threadsafe;
+
const uint32 X = 1812433253UL;
- state = new uint32[N];
state[0] = seed;
for (index = 1; index < (int)N; ++index) {
state[index] = X * (state[index - 1] ^ (state[index - 1] >> 30)) + index;
@@ -115,6 +123,7 @@ void Random::generate() {
int Random::integer(int low, int high) {
+ debugAssert(high >= low);
int r = iFloor(low + (high - low + 1) * (double)bits() / 0xFFFFFFFFUL);
// There is a *very small* chance of generating
@@ -147,6 +156,15 @@ float Random::gaussian(float mean, float stdev) {
}
+void Random::cosSphere(float& x, float& y, float& z) {
+ cosHemi(x, y, z);
+ if (bits() & 1) {
+ // Choose the axis direction uniformly at random
+ z = -z;
+ }
+}
+
+
void Random::cosHemi(float& x, float& y, float& z) {
const float e1 = uniform();
const float e2 = uniform();
diff --git a/dep/g3dlite/source/Ray.cpp b/dep/g3dlite/source/Ray.cpp
index 0436ef0b323..8a8cf77c5b7 100644
--- a/dep/g3dlite/source/Ray.cpp
+++ b/dep/g3dlite/source/Ray.cpp
@@ -16,127 +16,128 @@
namespace G3D {
void Ray::set(const Vector3& origin, const Vector3& direction) {
- m_origin = origin;
- m_direction = direction;
- debugAssert(direction.isUnit());
-
- m_invDirection = Vector3::one() / direction;
-
- // ray slope
- ibyj = m_direction.x * m_invDirection.y;
- jbyi = m_direction.y * m_invDirection.x;
- jbyk = m_direction.y * m_invDirection.z;
- kbyj = m_direction.z * m_invDirection.y;
- ibyk = m_direction.x * m_invDirection.z;
- kbyi = m_direction.z * m_invDirection.x;
-
- // precomputed terms
- c_xy = m_origin.y - jbyi * m_origin.x;
- c_xz = m_origin.z - kbyi * m_origin.x;
- c_yx = m_origin.x - ibyj * m_origin.y;
- c_yz = m_origin.z - kbyj * m_origin.y;
- c_zx = m_origin.x - ibyk * m_origin.z;
- c_zy = m_origin.y - jbyk * m_origin.z;
-
- //ray slope classification
- if (m_direction.x < 0) {
- if (m_direction.y < 0) {
- if (m_direction.z < 0) {
- classification = MMM;
- } else if (m_direction.z > 0) {
- classification = MMP;
- } else { //(m_direction.z >= 0)
- classification = MMO;
- }
- } else { //(m_direction.y >= 0)
- if (m_direction.z < 0) {
- if (m_direction.y == 0) {
- classification = MOM;
- } else {
- classification = MPM;
- }
- } else { //(m_direction.z >= 0)
- if ((m_direction.y == 0) && (m_direction.z == 0)) {
- classification = MOO;
- } else if (m_direction.z == 0) {
- classification = MPO;
- } else if (m_direction.y == 0) {
- classification = MOP;
- } else {
- classification = MPP;
- }
- }
- }
- } else { //(m_direction.x >= 0)
- if (m_direction.y < 0) {
- if (m_direction.z < 0) {
- if (m_direction.x == 0) {
- classification = OMM;
- } else {
- classification = PMM;
- }
- } else { //(m_direction.z >= 0)
- if ((m_direction.x == 0) && (m_direction.z == 0)) {
- classification = OMO;
- } else if (m_direction.z == 0) {
- classification = PMO;
- } else if (m_direction.x == 0) {
- classification = OMP;
- } else {
- classification = PMP;
- }
- }
- } else { //(m_direction.y >= 0)
- if (m_direction.z < 0) {
- if ((m_direction.x == 0) && (m_direction.y == 0)) {
- classification = OOM;
- } else if (m_direction.x == 0) {
- classification = OPM;
- } else if (m_direction.y == 0) {
- classification = POM;
- } else {
- classification = PPM;
- }
- } else { //(m_direction.z > 0)
- if (m_direction.x == 0) {
- if (m_direction.y == 0) {
- classification = OOP;
- } else if (m_direction.z == 0) {
- classification = OPO;
- } else {
- classification = OPP;
- }
- } else {
- if ((m_direction.y == 0) && (m_direction.z == 0)) {
- classification = POO;
- } else if (m_direction.y == 0) {
- classification = POP;
- } else if (m_direction.z == 0) {
- classification = PPO;
- } else {
- classification = PPP;
- }
- }
- }
- }
- }
+ m_origin = origin;
+ m_direction = direction;
+ debugAssert(direction.isUnit());
+
+ m_invDirection = Vector3::one() / direction;
+
+ // ray slope
+ ibyj = m_direction.x * m_invDirection.y;
+ jbyi = m_direction.y * m_invDirection.x;
+ jbyk = m_direction.y * m_invDirection.z;
+ kbyj = m_direction.z * m_invDirection.y;
+ ibyk = m_direction.x * m_invDirection.z;
+ kbyi = m_direction.z * m_invDirection.x;
+
+ // precomputed terms
+ c_xy = m_origin.y - jbyi * m_origin.x;
+ c_xz = m_origin.z - kbyi * m_origin.x;
+ c_yx = m_origin.x - ibyj * m_origin.y;
+ c_yz = m_origin.z - kbyj * m_origin.y;
+ c_zx = m_origin.x - ibyk * m_origin.z;
+ c_zy = m_origin.y - jbyk * m_origin.z;
+
+ //ray slope classification
+ if (m_direction.x < 0) {
+ if (m_direction.y < 0) {
+ if (m_direction.z < 0) {
+ classification = MMM;
+ } else if (m_direction.z > 0) {
+ classification = MMP;
+ } else { //(m_direction.z >= 0)
+ classification = MMO;
+ }
+ } else { //(m_direction.y >= 0)
+ if (m_direction.z < 0) {
+ if (m_direction.y == 0) {
+ classification = MOM;
+ } else {
+ classification = MPM;
+ }
+ } else { //(m_direction.z >= 0)
+ if ((m_direction.y == 0) && (m_direction.z == 0)) {
+ classification = MOO;
+ } else if (m_direction.z == 0) {
+ classification = MPO;
+ } else if (m_direction.y == 0) {
+ classification = MOP;
+ } else {
+ classification = MPP;
+ }
+ }
+ }
+ } else { //(m_direction.x >= 0)
+ if (m_direction.y < 0) {
+ if (m_direction.z < 0) {
+ if (m_direction.x == 0) {
+ classification = OMM;
+ } else {
+ classification = PMM;
+ }
+ } else { //(m_direction.z >= 0)
+ if ((m_direction.x == 0) && (m_direction.z == 0)) {
+ classification = OMO;
+ } else if (m_direction.z == 0) {
+ classification = PMO;
+ } else if (m_direction.x == 0) {
+ classification = OMP;
+ } else {
+ classification = PMP;
+ }
+ }
+ } else { //(m_direction.y >= 0)
+ if (m_direction.z < 0) {
+ if ((m_direction.x == 0) && (m_direction.y == 0)) {
+ classification = OOM;
+ } else if (m_direction.x == 0) {
+ classification = OPM;
+ } else if (m_direction.y == 0) {
+ classification = POM;
+ } else {
+ classification = PPM;
+ }
+ } else { //(m_direction.z > 0)
+ if (m_direction.x == 0) {
+ if (m_direction.y == 0) {
+ classification = OOP;
+ } else if (m_direction.z == 0) {
+ classification = OPO;
+ } else {
+ classification = OPP;
+ }
+ } else {
+ if ((m_direction.y == 0) && (m_direction.z == 0)) {
+ classification = POO;
+ } else if (m_direction.y == 0) {
+ classification = POP;
+ } else if (m_direction.z == 0) {
+ classification = PPO;
+ } else {
+ classification = PPP;
+ }
+ }
+ }
+ }
+ }
}
+
Ray::Ray(class BinaryInput& b) {
- deserialize(b);
+ deserialize(b);
}
void Ray::serialize(class BinaryOutput& b) const {
- m_origin.serialize(b);
- m_direction.serialize(b);
+ m_origin.serialize(b);
+ m_direction.serialize(b);
}
void Ray::deserialize(class BinaryInput& b) {
- m_origin.deserialize(b);
- m_direction.deserialize(b);
- set(m_origin, m_direction);
+ m_origin.deserialize(b);
+ m_direction.deserialize(b);
+ set(m_origin, m_direction);
}
diff --git a/dep/g3dlite/source/Rect2D.cpp b/dep/g3dlite/source/Rect2D.cpp
index e4148315a58..3aea02f512e 100644
--- a/dep/g3dlite/source/Rect2D.cpp
+++ b/dep/g3dlite/source/Rect2D.cpp
@@ -4,9 +4,9 @@
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
@created 2003-11-13
- @created 2009-11-16
+ @created 2011-06-16
- Copyright 2000-2009, Morgan McGuire.
+ Copyright 2000-2012, Morgan McGuire.
All rights reserved.
*/
@@ -14,28 +14,56 @@
#include "G3D/Rect2D.h"
#include "G3D/Any.h"
#include "G3D/stringutils.h"
+#include "G3D/BinaryInput.h"
+#include "G3D/BinaryOutput.h"
namespace G3D {
+const Rect2D& Rect2D::empty() {
+ static Rect2D r;
+ return r;
+}
+
+
+void Rect2D::serialize(class BinaryOutput& b) const {
+ min.serialize(b);
+ max.serialize(b);
+}
+
+
+void Rect2D::deserialize(class BinaryInput& b) {
+ min.deserialize(b);
+ max.deserialize(b);
+}
+
+
/** \param any Must either Rect2D::xywh(#, #, #, #) or Rect2D::xyxy(#, #, #, #)*/
Rect2D::Rect2D(const Any& any) {
- any.verifyName("Rect2D");
+ if (any.name() == "Rect2D::empty" || any.name() == "AABox2D::empty") {
+ *this = empty();
+ return;
+ }
+
+ any.verifyName("Rect2D::xyxy", "Rect2D::xywh");
any.verifyType(Any::ARRAY);
any.verifySize(4);
- if (toUpper(any.name()) == "RECT2D::XYWH") {
+ if (any.name() == "Rect2D::xywh") {
*this = Rect2D::xywh(any[0], any[1], any[2], any[3]);
} else {
- any.verifyName("Rect2D::xyxy");
*this = Rect2D::xyxy(any[0], any[1], any[2], any[3]);
}
}
/** Converts the Rect2D to an Any. */
-Rect2D::operator Any() const {
- Any any(Any::ARRAY, "Rect2D::xywh");
- any.append(x0(), y0(), width(), height());
- return any;
+Any Rect2D::toAny() const {
+ if (isEmpty()) {
+ return Any(Any::ARRAY, "Rect2D::empty");
+ } else {
+ Any any(Any::ARRAY, "Rect2D::xywh");
+ any.append(Any(x0()), Any(y0()), Any(width()), Any(height()));
+ return any;
+ }
}
}
diff --git a/dep/g3dlite/source/ReferenceCount.cpp b/dep/g3dlite/source/ReferenceCount.cpp
deleted file mode 100644
index 2e1f117e0d9..00000000000
--- a/dep/g3dlite/source/ReferenceCount.cpp
+++ /dev/null
@@ -1,61 +0,0 @@
-/**
- @file ReferenceCount.cpp
-
- Reference Counting Garbage Collector for C++
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @cite Adapted and extended from Justin Miller's "RGC" class that appeared in BYTE magazine.
- @cite See also http://www.jelovic.com/articles/cpp_without_memory_errors_slides.htm
-
- @created 2001-10-23
- @edited 2009-04-25
-*/
-#include "G3D/platform.h"
-#include "G3D/ReferenceCount.h"
-
-namespace G3D {
-
-ReferenceCountedObject::ReferenceCountedObject() :
- ReferenceCountedObject_refCount(0),
- ReferenceCountedObject_weakPointer(0) {
-
- debugAssertM(isValidHeapPointer(this),
- "Reference counted objects must be allocated on the heap.");
-}
-
-void ReferenceCountedObject::ReferenceCountedObject_zeroWeakPointers() {
- // Tell all of my weak pointers that I'm gone.
-
- _WeakPtrLinkedList* node = ReferenceCountedObject_weakPointer;
-
- while (node != NULL) {
- // Notify the weak pointer that it is going away
- node->weakPtr->objectCollected();
-
- // Free the node and advance
- _WeakPtrLinkedList* tmp = node;
- node = node->next;
- delete tmp;
- }
-}
-
-ReferenceCountedObject::~ReferenceCountedObject() {}
-
-
-ReferenceCountedObject::ReferenceCountedObject(const ReferenceCountedObject& notUsed) :
- ReferenceCountedObject_refCount(0),
- ReferenceCountedObject_weakPointer(0) {
- (void)notUsed;
- debugAssertM(G3D::isValidHeapPointer(this),
- "Reference counted objects must be allocated on the heap.");
-}
-
-ReferenceCountedObject& ReferenceCountedObject::operator=(const ReferenceCountedObject& other) {
- (void)other;
- // Nothing changes when I am assigned; the reference count on
- // both objects is the same (although my super-class probably
- // changes).
- return *this;
-}
-
-} // G3D
diff --git a/dep/g3dlite/source/RegistryUtil.cpp b/dep/g3dlite/source/RegistryUtil.cpp
index 7c9e56f79ae..72c31212049 100644
--- a/dep/g3dlite/source/RegistryUtil.cpp
+++ b/dep/g3dlite/source/RegistryUtil.cpp
@@ -11,7 +11,7 @@
#include "G3D/platform.h"
// This file is only used on Windows
-#ifdef G3D_WIN32
+#ifdef G3D_WINDOWS
#include "G3D/RegistryUtil.h"
#include "G3D/System.h"
@@ -24,7 +24,6 @@
# define HKEY_PERFORMANCE_NLSTEXT ((HKEY)((LONG)0x80000060))
# endif
#endif
-
namespace G3D {
// static helpers
@@ -256,7 +255,8 @@ bool RegistryUtil::writeString(const std::string& key, const std::string& value,
debugAssert(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND);
if (result == ERROR_SUCCESS) {
- result = RegSetValueExA(openKey, value.c_str(), 0, REG_SZ, reinterpret_cast<const BYTE*>(data.c_str()), (data.size() + 1));
+ alwaysAssertM(data.size() < 0xFFFFFFFE, "String too long");
+ result = RegSetValueExA(openKey, value.c_str(), 0, REG_SZ, reinterpret_cast<const BYTE*>(data.c_str()), (int)(data.size() + 1));
debugAssertM(result == ERROR_SUCCESS, "Could not write registry key value.");
RegCloseKey(openKey);
@@ -296,4 +296,4 @@ static HKEY getRootKeyFromString(const char* str, size_t length) {
} // namespace G3D
-#endif // G3D_WIN32
+#endif // G3D_WINDOWS
diff --git a/dep/g3dlite/source/Sphere.cpp b/dep/g3dlite/source/Sphere.cpp
index 4ed0811cb29..5c2eb91cd2a 100644
--- a/dep/g3dlite/source/Sphere.cpp
+++ b/dep/g3dlite/source/Sphere.cpp
@@ -1,12 +1,12 @@
/**
- @file Sphere.cpp
+ \file G3D.lib/source/Sphere.cpp
Sphere class
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
+ \maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @created 2001-04-17
- @edited 2009-01-20
+ \created 2001-04-17
+ \edited 2011-02-10
*/
#include "G3D/platform.h"
@@ -16,11 +16,37 @@
#include "G3D/BinaryInput.h"
#include "G3D/AABox.h"
#include "G3D/Plane.h"
+#include "G3D/Any.h"
namespace G3D {
int32 Sphere::dummy;
+Sphere::Sphere(const Any& a) : radius(0) {
+ a.verifyName("Sphere");
+ a.verifyType(Any::ARRAY);
+ if (a.size() == 1) {
+ radius = a[0];
+ } else if (a.size() == 2) {
+ center = a[0];
+ radius = a[1];
+ } else {
+ a.verify(false, "Sphere must recieve exactly 1 or two arguments.");
+ }
+}
+
+
+Any Sphere::toAny() const {
+ Any a(Any::ARRAY, "Sphere");
+ if (center != Point3::zero()) {
+ a.append(center);
+ }
+
+ a.append(radius);
+ return a;
+}
+
+
Sphere::Sphere(class BinaryInput& b) {
deserialize(b);
}
@@ -38,6 +64,12 @@ void Sphere::deserialize(class BinaryInput& b) {
}
+const Sphere& Sphere::inf() {
+ static const Sphere s(Point3::zero(), finf());
+ return s;
+}
+
+
std::string Sphere::toString() const {
return format("Sphere(<%g, %g, %g>, %g)",
center.x, center.y, center.z, radius);
@@ -82,19 +114,19 @@ void Sphere::merge(const Sphere& other) {
bool Sphere::culledBy(
- const Array<Plane>& plane,
- int& cullingPlaneIndex,
- const uint32 inMask,
- uint32& outMask) const {
+ const Array<Plane>& plane,
+ int& cullingPlaneIndex,
+ const uint32 inMask,
+ uint32& outMask) const {
return culledBy(plane.getCArray(), plane.size(), cullingPlaneIndex, inMask, outMask);
}
bool Sphere::culledBy(
- const Array<Plane>& plane,
- int& cullingPlaneIndex,
- const uint32 inMask) const {
+ const Array<Plane>& plane,
+ int& cullingPlaneIndex,
+ const uint32 inMask) const {
return culledBy(plane.getCArray(), plane.size(), cullingPlaneIndex, inMask);
}
@@ -103,8 +135,8 @@ bool Sphere::culledBy(
bool Sphere::culledBy(
const class Plane* plane,
int numPlanes,
- int& cullingPlane,
- const uint32 _inMask,
+ int& cullingPlane,
+ const uint32 _inMask,
uint32& childMask) const {
if (radius == finf()) {
@@ -112,45 +144,45 @@ bool Sphere::culledBy(
return false;
}
- uint32 inMask = _inMask;
- assert(numPlanes < 31);
+ uint32 inMask = _inMask;
+ assert(numPlanes < 31);
childMask = 0;
// See if there is one plane for which all of the
- // vertices are in the negative half space.
- for (int p = 0; p < numPlanes; p++) {
+ // vertices are in the negative half space.
+ for (int p = 0; p < numPlanes; ++p) {
- // Only test planes that are not masked
- if ((inMask & 1) != 0) {
-
+ // Only test planes that are not masked
+ if ((inMask & 1) != 0) {
+
bool culledLow = ! plane[p].halfSpaceContainsFinite(center + plane[p].normal() * radius);
bool culledHigh = ! plane[p].halfSpaceContainsFinite(center - plane[p].normal() * radius);
- if (culledLow) {
- // Plane p culled the sphere
- cullingPlane = p;
+ if (culledLow) {
+ // Plane p culled the sphere
+ cullingPlane = p;
// The caller should not recurse into the children,
// since the parent is culled. If they do recurse,
// make them only test against this one plane, which
// will immediately cull the volume.
childMask = 1 << p;
- return true;
+ return true;
} else if (culledHigh) {
// The bounding volume straddled the plane; we have
// to keep testing against this plane
childMask |= (1 << p);
}
- }
+ }
// Move on to the next bit.
- inMask = inMask >> 1;
+ inMask = inMask >> 1;
}
// None of the planes could cull this box
- cullingPlane = -1;
+ cullingPlane = -1;
return false;
}
@@ -158,32 +190,34 @@ bool Sphere::culledBy(
bool Sphere::culledBy(
const class Plane* plane,
int numPlanes,
- int& cullingPlane,
- const uint32 _inMask) const {
+ int& cullingPlane,
+ const uint32 _inMask) const {
+ // Don't cull if the sphere has infinite radius
+ if(!isFinite(radius)) return false;
- uint32 inMask = _inMask;
- assert(numPlanes < 31);
+ uint32 inMask = _inMask;
+ assert(numPlanes < 31);
// See if there is one plane for which all of the
- // vertices are in the negative half space.
- for (int p = 0; p < numPlanes; p++) {
-
- // Only test planes that are not masked
- if ((inMask & 1) != 0) {
- bool culled = ! plane[p].halfSpaceContains(center + plane[p].normal() * radius);
- if (culled) {
- // Plane p culled the sphere
- cullingPlane = p;
- return true;
+ // vertices are in the negative half space.
+ for (int p = 0; p < numPlanes; ++p) {
+
+ // Only test planes that are not masked
+ if ((inMask & 1) != 0) {
+ bool culled = ! plane[p].halfSpaceContains(center + plane[p].normal() * radius);
+ if (culled) {
+ // Plane p culled the sphere
+ cullingPlane = p;
+ return true;
}
- }
+ }
// Move on to the next bit.
- inMask = inMask >> 1;
+ inMask = inMask >> 1;
}
// None of the planes could cull this box
- cullingPlane = -1;
+ cullingPlane = -1;
return false;
}
diff --git a/dep/g3dlite/source/SplineBase.cpp b/dep/g3dlite/source/SplineBase.cpp
index 41221624b06..5904e9a1aa2 100644
--- a/dep/g3dlite/source/SplineBase.cpp
+++ b/dep/g3dlite/source/SplineBase.cpp
@@ -4,7 +4,7 @@
namespace G3D {
float SplineBase::getFinalInterval() const {
- if (! cyclic) {
+ if (extrapolationMode != SplineExtrapolationMode::CYCLIC) {
return 0;
} else if (finalInterval <= 0) {
int N = time.size();
@@ -97,7 +97,7 @@ void SplineBase::computeIndex(float s, int& i, float& u) const {
// No control points to work with
i = 0;
u = 0.0;
- } else if (cyclic) {
+ } else if (extrapolationMode == SplineExtrapolationMode::CYCLIC) {
float fi = getFinalInterval();
// Cyclic spline
@@ -156,7 +156,7 @@ void SplineBase::computeIndex(float s, int& i, float& u) const {
computeIndexInBounds(s, i, u);
} // if in bounds
- } // if cyclic
+ } // extrapolation Mode
}
}
diff --git a/dep/g3dlite/source/Stopwatch.cpp b/dep/g3dlite/source/Stopwatch.cpp
index 9b785d50295..713835ea7ab 100644
--- a/dep/g3dlite/source/Stopwatch.cpp
+++ b/dep/g3dlite/source/Stopwatch.cpp
@@ -105,15 +105,16 @@ void Stopwatch::reset() {
void Stopwatch::after(const std::string& s) {
RealTime now = System::time();
- debugPrintf("%s: %10s - %8fs since %s (%fs since start)\n",
- myName.c_str(),
- s.c_str(),
- now - prevTime,
- prevMark.c_str(),
- now - startTime);
+ if (m_enabled) {
+ debugPrintf("%s: %10s - %8fs since %s (%fs since start)\n",
+ myName.c_str(),
+ s.c_str(),
+ now - prevTime,
+ prevMark.c_str(),
+ now - startTime);
+ }
prevTime = now;
prevMark = s;
}
}
-
diff --git a/dep/g3dlite/source/System.cpp b/dep/g3dlite/source/System.cpp
index 281104d39f1..b2f8cb886da 100644
--- a/dep/g3dlite/source/System.cpp
+++ b/dep/g3dlite/source/System.cpp
@@ -1,7 +1,7 @@
/**
- @file System.cpp
+ \file System.cpp
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
+ \maintainer Morgan McGuire, http://graphics.cs.williams.edu
Note: every routine must call init() first.
@@ -10,8 +10,8 @@
can be used at all. At runtime, processor detection is used to
determine if we can safely call the routines that use that assembly.
- @created 2003-01-25
- @edited 2010-01-03
+ \created 2003-01-25
+ \edited 2012-01-05
*/
#include "G3D/platform.h"
@@ -37,17 +37,14 @@
// allocation and use the operating system's malloc.
//#define NO_BUFFERPOOL
-#if defined(__i386__) || defined(__x86_64__) || defined(G3D_WIN32)
-# define G3D_NOT_OSX_PPC
-#endif
-
#include <cstdlib>
-#ifdef G3D_WIN32
+#ifdef G3D_WINDOWS
# include <conio.h>
# include <sys/timeb.h>
# include "G3D/RegistryUtil.h"
+#include <Ole2.h>
#elif defined(G3D_LINUX)
@@ -81,13 +78,11 @@
#endif
// SIMM include
-#ifdef __SSE__
#include <xmmintrin.h>
-#endif
-
-namespace G3D {
+namespace G3D {
+
/** Checks if the CPUID command is available on the processor (called from init) */
static bool checkForCPUID();
@@ -173,10 +168,6 @@ void System::init() {
m_cpuArch = "AMD Processor";
break;
- case 0x69727943: // CyrixInstead
- m_cpuArch = "Cyrix Processor";
- break;
-
default:
m_cpuArch = "Unknown Processor Vendor";
break;
@@ -195,43 +186,40 @@ void System::init() {
// Get the operating system name (also happens to read some other information)
-# ifdef G3D_WIN32
+# ifdef G3D_WINDOWS
+ HRESULT r = OleInitialize(NULL);
// Note that this overrides some of the values computed above
bool success = RegistryUtil::readInt32
("HKEY_LOCAL_MACHINE\\HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0",
"~MHz", m_cpuSpeed);
-
+ HRESULT s = OleInitialize(NULL);
SYSTEM_INFO systemInfo;
GetSystemInfo(&systemInfo);
const char* arch = NULL;
switch (systemInfo.wProcessorArchitecture) {
case PROCESSOR_ARCHITECTURE_INTEL:
- arch = "Intel";
+ arch = "x86 Intel";
break;
- case PROCESSOR_ARCHITECTURE_MIPS:
- arch = "MIPS";
- break;
+ case PROCESSOR_ARCHITECTURE_AMD64:
+ arch = "x64 Intel/AMD";
+ break;
- case PROCESSOR_ARCHITECTURE_ALPHA:
- arch = "Alpha";
- break;
-
- case PROCESSOR_ARCHITECTURE_PPC:
- arch = "Power PC";
- break;
+ case PROCESSOR_ARCHITECTURE_ARM:
+ arch = "ARM";
+ break;
default:
arch = "Unknown";
+ break;
}
m_numCores = systemInfo.dwNumberOfProcessors;
- uint32 maxAddr = (uint32)systemInfo.lpMaximumApplicationAddress;
+ uint64_t maxAddr = reinterpret_cast<uint64_t>(systemInfo.lpMaximumApplicationAddress);
{
char c[1024];
- sprintf(c, "%d x %d-bit %s processor",
+ sprintf(c, "%d - %s cores",
systemInfo.dwNumberOfProcessors,
- (int)(::log((double)maxAddr) / ::log(2.0) + 2.0),
arch);
m_cpuArch = c;
}
@@ -261,12 +249,13 @@ void System::init() {
int len = 100;
char* r = (char*)::malloc(len * sizeof(char));
- fgets(r, len, f);
+ (void)fgets(r, len, f);
// Remove trailing newline
if (r[strlen(r) - 1] == '\n') {
r[strlen(r) - 1] = '\0';
}
fclose(f);
+ f = NULL;
m_operatingSystem = r;
::free(r);
@@ -294,72 +283,103 @@ void System::init() {
m_secondsPerNS = 1.0 / 1.0e9;
// System Architecture:
- const NXArchInfo* pInfo = NXGetLocalArchInfo();
-
- if (pInfo) {
- m_cpuArch = pInfo->description;
-
- switch (pInfo->cputype) {
- case CPU_TYPE_POWERPC:
- switch(pInfo->cpusubtype){
- case CPU_SUBTYPE_POWERPC_750:
- case CPU_SUBTYPE_POWERPC_7400:
- case CPU_SUBTYPE_POWERPC_7450:
- m_cpuVendor = "Motorola";
- break;
- case CPU_SUBTYPE_POWERPC_970:
- m_cpuVendor = "IBM";
- break;
- }
- break;
-
+ const NXArchInfo* pInfo = NXGetLocalArchInfo();
+
+ if (pInfo) {
+ m_cpuArch = pInfo->description;
+
+ switch (pInfo->cputype) {
+ case CPU_TYPE_POWERPC:
+ switch(pInfo->cpusubtype){
+ case CPU_SUBTYPE_POWERPC_750:
+ case CPU_SUBTYPE_POWERPC_7400:
+ case CPU_SUBTYPE_POWERPC_7450:
+ m_cpuVendor = "Motorola";
+ break;
+ case CPU_SUBTYPE_POWERPC_970:
+ m_cpuVendor = "IBM";
+ break;
+ }
+ break;
+
case CPU_TYPE_I386:
m_cpuVendor = "Intel";
break;
- }
- }
+ }
+ }
# endif
initTime();
getStandardProcessorExtensions();
+
+ m_appDataDir = FilePath::parent(System::currentProgramFilename());
}
void getG3DVersion(std::string& s) {
+
+ const char* build =
+# ifdef G3D_64BIT
+ "64-bit";
+# else
+ "32-bit";
+# endif
+
+ const char* debug =
+# ifdef G3D_DEBUG
+ " (Debug)";
+# else
+ "";
+# endif
+
char cstr[100];
if ((G3D_VER % 100) != 0) {
- sprintf(cstr, "G3D %d.%02d beta %d",
+ sprintf(cstr, "G3D Innovation Engine %d.%02d beta %d, %s%s",
G3D_VER / 10000,
(G3D_VER / 100) % 100,
- G3D_VER % 100);
+ G3D_VER % 100,
+ build,
+ debug);
} else {
- sprintf(cstr, "G3D %d.%02d",
+ sprintf(cstr, "G3D Innovation Engine %d.%02d, %s%s",
G3D_VER / 10000,
- (G3D_VER / 100) % 100);
+ (G3D_VER / 100) % 100,
+ build,
+ debug);
}
+
s = cstr;
}
+// Places where specific files were most recently found. This is
+// used to cache seeking of common files.
+static Table<std::string, std::string> lastFound;
+
+// Places to look in findDataFile
+static Array<std::string> directoryArray;
+#define MARK_LOG()
+//#define MARK_LOG() logPrintf("%s(%d)\n", __FILE__, __LINE__)
std::string System::findDataFile
-(const std::string& full,
- bool errorIfNotFound) {
+(const std::string& _full,
+ bool errorIfNotFound,
+ bool caseSensitive) {
+MARK_LOG();
- // Places where specific files were most recently found. This is
- // used to cache seeking of common files.
- static Table<std::string, std::string> lastFound;
+ const std::string full = FilePath::expandEnvironmentVariables(_full);
// First check if the file exists as requested. This will go
// through the FileSystemCache, so most calls do not touch disk.
- if (FileSystem::exists(full)) {
+ if (FileSystem::exists(full, true, caseSensitive)) {
return full;
}
+MARK_LOG();
// Now check where we previously found this file.
std::string* last = lastFound.getPointer(full);
if (last != NULL) {
- if (FileSystem::exists(*last)) {
+ if (FileSystem::exists(*last, true, caseSensitive)) {
// Even if cwd has changed the file is still present.
// We won't notice if it has been deleted, however.
return *last;
@@ -369,11 +389,10 @@ std::string System::findDataFile
}
}
- // Places to look
- static Array<std::string> directoryArray;
+MARK_LOG();
- std::string initialAppDataDir(instance().m_appDataDir);
- const char* g3dPath = getenv("G3DDATA");
+ const std::string initialAppDataDir(instance().m_appDataDir);
+ const char* g3dPath = getenv("G3D9DATA");
if (directoryArray.size() == 0) {
// Initialize the directory array
@@ -381,18 +400,27 @@ std::string System::findDataFile
Array<std::string> baseDirArray;
- baseDirArray.append("");
+ baseDirArray.append(FileSystem::currentDirectory());
+MARK_LOG();
if (! initialAppDataDir.empty()) {
+MARK_LOG();
baseDirArray.append(initialAppDataDir);
+ baseDirArray.append(pathConcat(initialAppDataDir, "data"));
+ baseDirArray.append(pathConcat(initialAppDataDir, "data.zip"));
+ } else {
+MARK_LOG();
+ baseDirArray.append("data");
+ baseDirArray.append("data.zip");
}
+MARK_LOG();
-# ifdef G3D_WIN32
+# ifdef G3D_WINDOWS
if (g3dPath == NULL) {
// If running the demos under visual studio from the G3D.sln file,
// this will locate the data directory.
const char* paths[] = {"../data-files/", "../../data-files/", "../../../data-files/", NULL};
for (int i = 0; paths[i]; ++i) {
- if (FileSystem::exists(pathConcat(paths[i], "G3D-DATA-README.TXT"))) {
+ if (FileSystem::exists(pathConcat(paths[i], "G3D-DATA-README.TXT"), true, caseSensitive)) {
g3dPath = paths[i];
break;
}
@@ -405,96 +433,91 @@ std::string System::findDataFile
}
static const std::string subdirs[] =
- {"font", "gui", "SuperShader", "cubemap", "icon", "material", "image", "md2", "md3", "ifs", "3ds", "sky", ""};
+ {"font", "gui", "shader", "model", "cubemap", "icon", "material", "image", "md2", "md3", "ifs", "3ds", "sky", "music", "sound", "scene", ""};
for (int j = 0; j < baseDirArray.size(); ++j) {
std::string d = baseDirArray[j];
+//logPrintf("%s", d.c_str());
if ((d == "") || FileSystem::exists(d)) {
+//logPrintf(" exists\n");
directoryArray.append(d);
for (int i = 0; ! subdirs[i].empty(); ++i) {
const std::string& p = pathConcat(d, subdirs[i]);
- if (FileSystem::exists(p)) {
+ if (FileSystem::exists(p, true, caseSensitive)) {
directoryArray.append(p);
}
}
+ } else {
+//logPrintf(" does not exist\n");
}
}
logLazyPrintf("Initializing System::findDataFile took %fs\n", System::time() - t0);
+
}
+MARK_LOG();
for (int i = 0; i < directoryArray.size(); ++i) {
const std::string& p = pathConcat(directoryArray[i], full);
- if (FileSystem::exists(p)) {
+ if (FileSystem::exists(p, true, caseSensitive)) {
lastFound.set(full, p);
return p;
}
}
+MARK_LOG();
if (errorIfNotFound) {
- // Generate an error message
+ // Generate an error message. Delay this operation until we know that we need it;
+ // otherwise all of the string concatenation would run on each successful find.
std::string locations;
for (int i = 0; i < directoryArray.size(); ++i) {
locations += "\'" + pathConcat(directoryArray[i], full) + "'\n";
}
+MARK_LOG();
std::string msg = "Could not find '" + full + "'.\n\n";
- msg += "cwd = \'" + FileSystem::currentDirectory() + "\'\n";
+ msg += " cwd = '" + FileSystem::currentDirectory() + "'\n";
if (g3dPath) {
- msg += "G3DDATA = ";
- if (! FileSystem::exists(g3dPath)) {
- msg += "(illegal path!) ";
+ msg += " G3D9DATA = '" + std::string(g3dPath) + "'";
+ if (! FileSystem::exists(g3dPath, true, caseSensitive)) {
+ msg += " (illegal path!)";
}
- msg += std::string(g3dPath) + "\'\n";
+ msg += "\n";
} else {
- msg += "(G3DDATA environment variable is undefined)\n";
+ msg += " G3D9DATA = (environment variable is not defined)\n";
}
- msg += "GApp::Settings.dataDir = ";
- if (! FileSystem::exists(initialAppDataDir)) {
- msg += "(illegal path!) ";
+MARK_LOG();
+ msg += " GApp::Settings.dataDir = '" + initialAppDataDir + "'";
+ if (! FileSystem::exists(initialAppDataDir, true, caseSensitive)) {
+ msg += " (illegal path!)";
}
- msg += std::string(initialAppDataDir) + "\'\n";
+ msg += "\n";
- msg += "\nLocations searched:\n" + locations;
+ msg += "\nFilenames tested:\n" + locations;
+MARK_LOG();
+logPrintf("%s\n", msg.c_str());
+ throw FileNotFound(full, msg);
alwaysAssertM(false, msg);
}
+MARK_LOG();
// Not found
return "";
}
-
+#undef MARK_LOG
void System::setAppDataDir(const std::string& path) {
instance().m_appDataDir = path;
+
+ // Wipe the findDataFile cache
+ lastFound.clear();
+ directoryArray.clear();
}
-std::string demoFindData(bool errorIfNotFound) {
- static const char* g3dPath = getenv("G3DDATA");
- if (g3dPath) {
- return g3dPath;
-# ifdef G3D_WIN32
- } else if (FileSystem::exists("../data")) {
- // G3D install on Windows
- return "../data";
- } else if (FileSystem::exists("../data-files")) {
- // G3D source on Windows
- return "../data-files";
- } else if (FileSystem::exists("c:/libraries/G3D/data")) {
- return "c:/libraries/G3D/data";
-# else
- } else if (FileSystem::exists("../../../../data")) {
- // G3D install on Unix
- return "../../../../data";
- } else if (FileSystem::exists("../../../../data-files")) {
- // G3D source on Unix
- return "../../../../data-files";
- } else if (FileSystem::exists("/usr/local/G3D/data")) {
- return "/usr/local/G3D/data";
-# endif
- } else {
- return "";
- }
+void System::cleanup() {
+ lastFound.clear();
+ directoryArray.clear();
}
@@ -564,12 +587,15 @@ void System::getStandardProcessorExtensions() {
#endif
}
-#if defined(G3D_WIN32) && !defined(G3D_64BIT) && !defined(__MINGW32__) /* G3DFIX: Don't check if on 64-bit Windows platforms or using MinGW */
- #pragma message("Port System::memcpy SIMD to all platforms")
-/** Michael Herf's fast memcpy */
+#if defined(G3D_WINDOWS) && defined(_M_IX86) && !defined(__MINGW32__) /* G3DFIX: Don't check if on 64-bit Windows platforms or using MinGW */
+// 32-bit
+/** Michael Herf's fast memcpy. Assumes 16-byte alignment */
void memcpyMMX(void* dst, const void* src, int nbytes) {
int remainingBytes = nbytes;
+ alwaysAssertM((int)dst % 16 == 0, format("Must be on 16-byte boundary. dst = 0x%x", dst));
+ alwaysAssertM((int)src % 16 == 0, format("Must be on 16-byte boundary. src = 0x%x", src));
+
if (nbytes > 64) {
_asm {
mov esi, src
@@ -615,8 +641,13 @@ void memcpyMMX(void* dst, const void* src, int nbytes) {
#endif
void System::memcpy(void* dst, const void* src, size_t numBytes) {
-#if defined(G3D_WIN32) && !defined(G3D_64BIT) && !defined(__MINGW32__) /* G3DFIX: Don't check if on 64-bit Windows platforms or using MinGW */
- memcpyMMX(dst, src, numBytes);
+#if defined(G3D_WINDOWS) && defined(_M_IX86) && !defined(__MINGW32__) /* G3DFIX: Don't check if on 64-bit Windows platforms or using MinGW */
+ // The overhead of our memcpy seems to only be worthwhile on large arrays
+ if (((size_t)dst % 16 == 0) && ((size_t)src % 16 == 0) && (numBytes > 3400000)) {
+ memcpyMMX(dst, src, numBytes);
+ } else {
+ ::memcpy(dst, src, numBytes);
+ }
#else
::memcpy(dst, src, numBytes);
#endif
@@ -625,9 +656,7 @@ void System::memcpy(void* dst, const void* src, size_t numBytes) {
/** Michael Herf's fastest memset. n32 must be filled with the same
character repeated. */
-#if defined(G3D_WIN32) && !defined(G3D_64BIT) && !defined(__MINGW32__) /* G3DFIX: Don't check if on 64-bit Windows platforms or using MinGW */
- #pragma message("Port System::memfill SIMD to all platforms")
-
+#if defined(G3D_WINDOWS) && defined(_M_IX86) && !defined(__MINGW32__) /* G3DFIX: Don't check if on 64-bit Windows platforms or using MinGW */
// On x86 processors, use MMX
void memfill(void *dst, int n32, unsigned long i) {
@@ -664,10 +693,15 @@ void memfill(void *dst, int n32, unsigned long i) {
void System::memset(void* dst, uint8 value, size_t numBytes) {
-#if defined(G3D_WIN32) && !defined(G3D_64BIT) && !defined(__MINGW32__) /* G3DFIX: Don't check if on 64-bit Windows platforms or using MinGW */
- uint32 v = value;
- v = v + (v << 8) + (v << 16) + (v << 24);
- G3D::memfill(dst, v, numBytes);
+ alwaysAssertM(dst != NULL, "Cannot memset NULL address.");
+#if defined(G3D_WINDOWS) && defined(_M_IX86) && !defined(__MINGW32__) /* G3DFIX: Don't check if on 64-bit Windows platforms or using MinGW */
+ if ((((size_t)dst % 16) == 0) && (numBytes >= 512*1024)) {
+ uint32 v = value;
+ v = v + (v << 8) + (v << 16) + (v << 24);
+ G3D::memfill(dst, v, numBytes);
+ } else {
+ ::memset(dst, value, numBytes);
+ }
#else
::memset(dst, value, numBytes);
#endif
@@ -683,7 +717,7 @@ static std::string computeAppName(const std::string& start) {
if (start[start.size() - 1] == 'd') {
// Maybe remove the 'd'; see if ../ or ../../ has the same name
char tmp[1024];
- getcwd(tmp, sizeof(tmp));
+ (void)getcwd(tmp, sizeof(tmp));
std::string drive, base, ext;
Array<std::string> path;
parseFilename(tmp, drive, path, base, ext);
@@ -712,7 +746,7 @@ std::string& System::appName() {
std::string System::currentProgramFilename() {
char filename[2048];
-# ifdef G3D_WIN32
+# ifdef G3D_WINDOWS
{
GetModuleFileNameA(NULL, filename, sizeof(filename));
}
@@ -730,6 +764,7 @@ std::string System::currentProgramFilename() {
int s = fread(filename, 1, sizeof(filename), fd);
// filename will contain a newline. Overwrite it:
filename[s - 1] = '\0';
+ pclose(fd);
}
# else
{
@@ -784,7 +819,7 @@ void System::sleep(RealTime t) {
}
if (sleepTime >= 0) {
- #ifdef G3D_WIN32
+ #ifdef G3D_WINDOWS
// Translate to milliseconds
Sleep((int)(sleepTime * 1e3));
#else
@@ -800,16 +835,16 @@ void System::sleep(RealTime t) {
void System::consoleClearScreen() {
-# ifdef G3D_WIN32
- system("cls");
+# ifdef G3D_WINDOWS
+ (void)system("cls");
# else
- system("clear");
+ (void)system("clear");
# endif
}
bool System::consoleKeyPressed() {
- #ifdef G3D_WIN32
+ #ifdef G3D_WINDOWS
return _kbhit() != 0;
@@ -851,18 +886,18 @@ bool System::consoleKeyPressed() {
int System::consoleReadKey() {
-# ifdef G3D_WIN32
+# ifdef G3D_WINDOWS
return _getch();
# else
char c;
- read(0, &c, 1);
+ (void)read(0, &c, 1);
return c;
# endif
}
void System::initTime() {
- #ifdef G3D_WIN32
+ #ifdef G3D_WINDOWS
if (QueryPerformanceFrequency(&m_counterFrequency)) {
QueryPerformanceCounter(&m_start);
}
@@ -888,11 +923,7 @@ void System::initTime() {
if (localTimeVals) {
// tm_gmtoff is already corrected for daylight savings.
- #ifdef __CYGWIN__
- local = local + _timezone;
- #else
local = local + localTimeVals->tm_gmtoff;
- #endif
}
m_realWorldGetTickTime0 = local;
@@ -901,7 +932,7 @@ void System::initTime() {
RealTime System::time() {
-# ifdef G3D_WIN32
+# ifdef G3D_WINDOWS
LARGE_INTEGER now;
QueryPerformanceCounter(&now);
@@ -924,12 +955,11 @@ RealTime System::time() {
////////////////////////////////////////////////////////////////
-
-#define REALPTR_TO_USERPTR(x) ((uint8*)(x) + sizeof(uint32))
-#define USERPTR_TO_REALPTR(x) ((uint8*)(x) - sizeof(uint32))
-#define USERSIZE_TO_REALSIZE(x) ((x) + sizeof(uint32))
-#define REALSIZE_FROM_USERPTR(u) (*(uint32*)USERPTR_TO_REALPTR(ptr) + sizeof(uint32))
-#define USERSIZE_FROM_USERPTR(u) (*(uint32*)USERPTR_TO_REALPTR(ptr))
+#define REALPTR_TO_USERPTR(x) ((uint8*)(x) + sizeof(size_t))
+#define USERPTR_TO_REALPTR(x) ((uint8*)(x) - sizeof(size_t))
+#define USERSIZE_TO_REALSIZE(x) ((x) + sizeof(size_t))
+#define REALSIZE_FROM_USERPTR(u) (*(size_t*)USERPTR_TO_REALPTR(ptr) + sizeof(size_t))
+#define USERSIZE_FROM_USERPTR(u) (*(size_t*)USERPTR_TO_REALPTR(ptr))
class BufferPool {
public:
@@ -942,15 +972,20 @@ public:
Tiny buffers are 128 bytes long because that seems to align well with
cache sizes on many machines.
*/
+#ifdef G3D_64BIT
+ // 64-bit machines have larger pointers...and probably have more memory as well
+ enum {tinyBufferSize = 256, smallBufferSize = 2048, medBufferSize = 8192};
+#else
enum {tinyBufferSize = 128, smallBufferSize = 1024, medBufferSize = 4096};
+#endif
/**
Most buffers we're allowed to store.
- 250000 * 128 = 32 MB (preallocated)
- 10000 * 1024 = 10 MB (allocated on demand)
- 1024 * 4096 = 4 MB (allocated on demand)
+ 250000 * { 128 | 256} = {32 | 64} MB (preallocated)
+ 40000 * {1024 | 2048} = {40 | 80} MB (allocated on demand)
+ 5000 * {4096 | 8192} = {20 | 40} MB (allocated on demand)
*/
- enum {maxTinyBuffers = 250000, maxSmallBuffers = 10000, maxMedBuffers = 1024};
+ enum {maxTinyBuffers = 250000, maxSmallBuffers = 40000, maxMedBuffers = 5000};
private:
@@ -995,31 +1030,6 @@ private:
m_lock.unlock();
}
-#if 0 //-----------------------------------------------old mutex
-# ifdef G3D_WIN32
- CRITICAL_SECTION mutex;
-# else
- pthread_mutex_t mutex;
-# endif
-
- /** Provide synchronization between threads */
- void lock() {
-# ifdef G3D_WIN32
- EnterCriticalSection(&mutex);
-# else
- pthread_mutex_lock(&mutex);
-# endif
- }
-
- void unlock() {
-# ifdef G3D_WIN32
- LeaveCriticalSection(&mutex);
-# else
- pthread_mutex_unlock(&mutex);
-# endif
- }
-#endif //-------------------------------------------old mutex
-
/**
Malloc out of the tiny heap. Returns NULL if allocation failed.
*/
@@ -1133,7 +1143,7 @@ public:
of a buffer.
Primarily useful for detecting leaks.*/
// TODO: make me an atomic int!
- volatile int bytesAllocated;
+ volatile size_t bytesAllocated;
BufferPool() {
totalMallocs = 0;
@@ -1142,7 +1152,7 @@ public:
mallocsFromSmallPool = 0;
mallocsFromMedPool = 0;
- bytesAllocated = true;
+ bytesAllocated = 0;
tinyPoolSize = 0;
tinyHeap = NULL;
@@ -1161,7 +1171,7 @@ public:
tinyPoolSize = maxTinyBuffers;
#if 0 ///---------------------------------- old mutex
-# ifdef G3D_WIN32
+# ifdef G3D_WINDOWS
InitializeCriticalSection(&mutex);
# else
pthread_mutex_init(&mutex, NULL);
@@ -1175,7 +1185,7 @@ public:
flushPool(smallPool, smallPoolSize);
flushPool(medPool, medPoolSize);
#if 0 //-------------------------------- old mutex
-# ifdef G3D_WIN32
+# ifdef G3D_WINDOWS
DeleteCriticalSection(&mutex);
# else
// No destruction on pthreads
@@ -1274,6 +1284,11 @@ public:
RealPtr ptr = ::malloc(USERSIZE_TO_REALSIZE(bytes));
if (ptr == NULL) {
+# ifdef G3D_WINDOWS
+ // Check for memory corruption
+ alwaysAssertM(_CrtCheckMemory() == TRUE, "Heap corruption detected.");
+# endif
+
// Flush memory pools to try and recover space
flushPool(smallPool, smallPoolSize);
flushPool(medPool, medPoolSize);
@@ -1303,7 +1318,7 @@ public:
return NULL;
}
- *(uint32*)ptr = bytes;
+ ((size_t*)ptr)[0] = bytes;
return REALPTR_TO_USERPTR(ptr);
}
@@ -1324,7 +1339,7 @@ public:
return;
}
- uint32 bytes = USERSIZE_FROM_USERPTR(ptr);
+ size_t bytes = USERSIZE_FROM_USERPTR(ptr);
lock();
if (bytes <= smallBufferSize) {
@@ -1466,14 +1481,17 @@ void System::free(void* p) {
void* System::alignedMalloc(size_t bytes, size_t alignment) {
- alwaysAssertM(isPow2(alignment), "alignment must be a power of 2");
+ alwaysAssertM(isPow2((uint32)alignment), "alignment must be a power of 2");
// We must align to at least a word boundary.
- alignment = iMax(alignment, sizeof(void *));
+ alignment = max(alignment, sizeof(void *));
- // Pad the allocation size with the alignment size and the
- // size of the redirect pointer.
- size_t totalBytes = bytes + alignment + sizeof(void*);
+ // Pad the allocation size with the alignment size and the size of
+ // the redirect pointer. This is the worst-case size we'll need.
+ // Since the alignment size is at least teh word size, we don't
+ // need to allocate space for the redirect pointer. We repeat the max here
+ // for clarity.
+ size_t totalBytes = bytes + max(alignment, sizeof(void*));
size_t truePtr = (size_t)System::malloc(totalBytes);
@@ -1483,25 +1501,31 @@ void* System::alignedMalloc(size_t bytes, size_t alignment) {
}
debugAssert(isValidHeapPointer((void*)truePtr));
- #ifdef G3D_WIN32
+ #ifdef G3D_WINDOWS
// The blocks we return will not be valid Win32 debug heap
// pointers because they are offset
// debugAssert(_CrtIsValidPointer((void*)truePtr, totalBytes, TRUE) );
#endif
- // The return pointer will be the next aligned location (we must at least
- // leave space for the redirect pointer, however).
- size_t alignedPtr = truePtr + sizeof(void*);
- // 2^n - 1 has the form 1111... in binary.
- uint32 bitMask = (alignment - 1);
+ // We want alignedPtr % alignment == 0, which we'll compute with a
+ // binary AND because 2^n - 1 has the form 1111... in binary.
+ const size_t bitMask = (alignment - 1);
- // Advance forward until we reach an aligned location.
- while ((alignedPtr & bitMask) != 0) {
- alignedPtr += sizeof(void*);
- }
+ // The return pointer will be the next aligned location that is at
+ // least sizeof(void*) after the true pointer. We need the padding
+ // to have a place to write the redirect pointer.
+ size_t alignedPtr = truePtr + sizeof(void*);
- debugAssert(alignedPtr - truePtr + bytes <= totalBytes);
+ const size_t remainder = alignedPtr & bitMask;
+
+ // Add what we need to make it to the next alignment boundary, but
+ // if the remainder was zero, let it wrap to zero and don't add
+ // anything.
+ alignedPtr += ((alignment - remainder) & bitMask);
+
+ debugAssert((alignedPtr & bitMask) == 0);
+ debugAssert((alignedPtr - truePtr + bytes) <= totalBytes);
// Immediately before the aligned location, write the true array location
// so that we can free it correctly.
@@ -1510,8 +1534,10 @@ void* System::alignedMalloc(size_t bytes, size_t alignment) {
debugAssert(isValidHeapPointer((void*)truePtr));
- #ifdef G3D_WIN32
- debugAssert( _CrtIsValidPointer((void*)alignedPtr, bytes, TRUE) );
+ #if defined(G3D_WINDOWS) && defined(G3D_DEBUG)
+ if (bytes < 0xFFFFFFFF) {
+ debugAssert( _CrtIsValidPointer((void*)alignedPtr, (int)bytes, TRUE) );
+ }
#endif
return (void *)alignedPtr;
}
@@ -1539,7 +1565,7 @@ void System::alignedFree(void* _ptr) {
void System::setEnv(const std::string& name, const std::string& value) {
std::string cmd = name + "=" + value;
-# ifdef G3D_WIN32
+# ifdef G3D_WINDOWS
_putenv(cmd.c_str());
# else
// Many linux implementations of putenv expect char*
@@ -1590,7 +1616,7 @@ void System::describeSystem(
{
var(t, "Name", System::currentProgramFilename());
char cwd[1024];
- getcwd(cwd, 1024);
+ (void)getcwd(cwd, 1024);
var(t, "cwd", std::string(cwd));
}
t.popIndent();
@@ -1633,8 +1659,10 @@ void System::describeSystem(
t.writeNewline();
t.pushIndent();
{
+ const char* g3dPath = getenv("G3D9DATA");
var(t, "Link version", G3D_VER);
var(t, "Compile version", System::version());
+ var(t, "G3D9DATA", std::string(g3dPath ? g3dPath : ""));
}
t.popIndent();
t.writeSymbols("}");
@@ -1642,49 +1670,6 @@ void System::describeSystem(
t.writeNewline();
}
-
-void System::setClipboardText(const std::string& s) {
-# ifdef G3D_WIN32
- if (OpenClipboard(NULL)) {
- HGLOBAL hMem = GlobalAlloc(GHND | GMEM_DDESHARE, s.size() + 1);
- if (hMem) {
- char *pMem = (char*)GlobalLock(hMem);
- strcpy(pMem, s.c_str());
- GlobalUnlock(hMem);
-
- EmptyClipboard();
- SetClipboardData(CF_TEXT, hMem);
- }
-
- CloseClipboard();
- GlobalFree(hMem);
- }
-# endif
-}
-
-
-std::string System::getClipboardText() {
- std::string s;
-
-# ifdef G3D_WIN32
- if (OpenClipboard(NULL)) {
- HANDLE h = GetClipboardData(CF_TEXT);
-
- if (h) {
- char* temp = (char*)GlobalLock(h);
- if (temp) {
- s = temp;
- }
- temp = NULL;
- GlobalUnlock(h);
- }
- CloseClipboard();
- }
-# endif
- return s;
-}
-
-
std::string System::currentDateString() {
time_t t1;
::time(&t1);
@@ -1692,46 +1677,23 @@ std::string System::currentDateString() {
return format("%d-%02d-%02d", t->tm_year + 1900, t->tm_mon + 1, t->tm_mday);
}
-#ifdef _MSC_VER
-
-// VC on Intel
-void System::cpuid(CPUIDFunction func, uint32& areg, uint32& breg, uint32& creg, uint32& dreg) {
-#if !defined(G3D_64BIT) && !defined(__MINGW32__) /* G3DFIX: Don't check if on 64-bit platforms or using MinGW */
- // Can't copy from assembler direct to a function argument (which is on the stack) in VC.
- uint32 a,b,c,d;
-
- // Intel assembler syntax
- __asm {
- mov eax, func // eax <- func
- mov ecx, 0
- cpuid
- mov a, eax
- mov b, ebx
- mov c, ecx
- mov d, edx
- }
- areg = a;
- breg = b;
- creg = c;
- dreg = d;
-#else
- int CPUInfo[4];
- __cpuid(CPUInfo, func);
- memcpy(&areg, &CPUInfo[0], 4);
- memcpy(&breg, &CPUInfo[1], 4);
- memcpy(&creg, &CPUInfo[2], 4);
- memcpy(&dreg, &CPUInfo[3], 4);
-#endif
+std::string System::currentTimeString() {
+ time_t t1;
+ ::time(&t1);
+ tm* t = localtime(&t1);
+ return format("%02d:%02d:%02d", t->tm_hour, t->tm_min, t->tm_sec);
}
-#elif defined(G3D_OSX) && ! defined(G3D_OSX_INTEL)
+#if defined(_MSC_VER)
-// non-intel OS X; no CPUID
+// Windows 64-bit
void System::cpuid(CPUIDFunction func, uint32& eax, uint32& ebx, uint32& ecx, uint32& edx) {
- eax = 0;
- ebx = 0;
- ecx = 0;
- edx = 0;
+ int regs[4] = {eax, ebx, ecx, edx};
+ __cpuid(regs, func);
+ eax = regs[0];
+ ebx = regs[1];
+ ecx = regs[2];
+ edx = regs[3];
}
#else
diff --git a/dep/g3dlite/source/TextInput.cpp b/dep/g3dlite/source/TextInput.cpp
index 354d0de13c0..6f74d93381a 100644
--- a/dep/g3dlite/source/TextInput.cpp
+++ b/dep/g3dlite/source/TextInput.cpp
@@ -1,23 +1,22 @@
/**
- @file TextInput.cpp
+ \file G3D/source/TextInput.cpp
- @author Morgan McGuire, graphics3d.com
+ \author Morgan McGuire, http://graphics.cs.williams.edu
- @cite Based on a lexer written by Aaron Orenstein.
+ \cite Based on a lexer written by Aaron Orenstein.
- @created 2001-11-27
- @edited 2010-07-03
+ \created 2001-11-27
+ \edited 2012-07-22
*/
#include "G3D/fileutils.h"
#include "G3D/TextInput.h"
#include "G3D/BinaryInput.h"
+#include "G3D/FileSystem.h"
#include "G3D/stringutils.h"
#ifdef _MSC_VER
# pragma warning (push)
-// conversion from 'int' to 'char', possible loss of data (TODO: fix underlying problems)
-# pragma warning (disable: 4244)
#endif
namespace G3D {
@@ -46,15 +45,15 @@ bool TextInput::parseBoolean(const std::string& _string) {
double TextInput::parseNumber(const std::string& _string) {
std::string s = toLower(_string);
- if (s == "-1.#ind00" || s == "nan") {
+ if (s == "-1.#ind00" || s == "-1.#ind" || s == "nan" || s == "NaN") {
return nan();
}
- if (s == "1.#inf00" || s == "inf" || s == "+inf") {
+ if (s == "1.#inf00" || s == "1.#inf" || s == "inf" || s == "+inf" || s == "Infinity") {
return inf();
}
- if (s == "-1.#inf00" || s == "-inf") {
+ if (s == "-1.#inf00" || s == "-1.#inf" || s == "-inf" || s == "-Infinity") {
return -inf();
}
@@ -99,7 +98,8 @@ TextInput::Settings::Settings () :
Token TextInput::peek() {
if (stack.size() == 0) {
- Token t = nextToken();
+ Token t;
+ nextToken(t);
push(t);
}
@@ -118,18 +118,23 @@ int TextInput::peekCharacterNumber() {
Token TextInput::read() {
+ Token t;
+ read(t);
+ return t;
+}
+
+
+void TextInput::read(Token& t) {
if (stack.size() > 0) {
- Token t = stack.front();
+ t = stack.front();
stack.pop_front();
- return t;
} else {
- return nextToken();
+ nextToken(t);
}
}
-
-std::string TextInput::readUntilNewlineAsString() {
+std::string TextInput::readUntilDelimiterAsString(const char delimiter1, const char delimiter2) {
/*
// Reset the read position back to the start of that token
currentCharOffset = t.bytePosition();
@@ -144,11 +149,21 @@ std::string TextInput::readUntilNewlineAsString() {
*/
std::string s;
- // Read until newline or eof
- char c = '\0';
- do {
- c = buffer[currentCharOffset];
- if (c == '\r' || c == '\n') {
+ if (stack.size() > 0) {
+ // Need to back up. This only works if the stack is actually
+ // in proper order reflecting the real file, and doesn't
+ // contain incorrectly pushed elements.
+ Token t = stack.back();
+ stack.clear();
+ currentCharOffset = (int)t.bytePosition();
+ lineNumber = t.line();
+ charNumber = t.character();
+ }
+
+ // Read until delimiter or eof
+ while (currentCharOffset < buffer.size()) {
+ const char c = buffer[currentCharOffset];
+ if ((c == delimiter1) || (c == delimiter2)) {
// Done
break;
} else {
@@ -156,12 +171,17 @@ std::string TextInput::readUntilNewlineAsString() {
++currentCharOffset;
++charNumber;
}
- } while (currentCharOffset < buffer.size());
+ }
return s;
}
+std::string TextInput::readUntilNewlineAsString() {
+ return readUntilDelimiterAsString('\r', '\n');
+}
+
+
static void toUpper(Set<std::string>& set) {
Array<std::string> symbols;
set.getMembers(symbols);
@@ -240,8 +260,7 @@ int TextInput::peekInputChar(int distance) {
}
-Token TextInput::nextToken() {
- Token t;
+void TextInput::nextToken(Token& t) {
t._bytePosition = currentCharOffset;
t._line = lineNumber;
@@ -251,7 +270,7 @@ Token TextInput::nextToken() {
int c = peekInputChar();
if (c == EOF) {
- return t;
+ return;
}
// loop through white space, newlines and comments
@@ -276,7 +295,7 @@ Token TextInput::nextToken() {
}
eatInputChar();
- return t;
+ return;
} else {
// Consume the single whitespace
c = eatAndPeekInputChar();
@@ -288,8 +307,24 @@ Token TextInput::nextToken() {
t._character = charNumber;
t._bytePosition = currentCharOffset;
+ if (isDigit(c)) {
+ // This is an unsigned number. Jump ahead for fast number reading.
+ goto numLabel;
+ }
+
int c2 = peekInputChar(1);
+ if ((c == '-') && isDigit(c2) && options.signedNumbers) {
+ // This is a simple number. Jump ahead for fast number reading.
+ // We treat this case specially because large (i.e., slow) files
+ // are usually large because they are full of numbers.
+ t._string = "-";
+ c = c2;
+ // Consume the minus sign
+ eatInputChar();
+ goto numLabel;
+ }
+
// parse comments and generate tokens if enabled
std::string commentString;
@@ -327,7 +362,7 @@ Token TextInput::nextToken() {
t._type = Token::COMMENT;
t._extendedType = Token::LINE_COMMENT_TYPE;
t._string = commentString;
- return t;
+ return;
} else {
// There is whitespace after the comment (in particular, the
// newline that terminates the comment). There might also be
@@ -364,7 +399,7 @@ Token TextInput::nextToken() {
t._type = Token::COMMENT;
t._extendedType = Token::BLOCK_COMMENT_TYPE;
t._string = commentString;
- return t;
+ return;
} else {
// There is whitespace after the comment (in particular, the
// newline that terminates the comment). There might also be
@@ -381,7 +416,7 @@ Token TextInput::nextToken() {
// handle EOF
if (c == EOF) {
- return t;
+ return;
}
// Extended ASCII parses as itself, except for EOF
@@ -420,7 +455,7 @@ Token TextInput::nextToken() {
case '?':
case '%':
SETUP_SYMBOL(c);
- return t;
+ return;
case '-': // negative number, -, --, -=, or ->
SETUP_SYMBOL(c);
@@ -431,7 +466,7 @@ Token TextInput::nextToken() {
case '=': // -=
t._string += c;
eatInputChar();
- return t;
+ return;
}
if (options.signedNumbers) {
@@ -451,14 +486,14 @@ Token TextInput::nextToken() {
eatInputChar(); // i
eatInputChar(); // n
eatInputChar(); // f
- return t;
+ return;
}
}
}
// plain -
- return t;
+ return;
case '+': // positive number, +, ++, or +=
SETUP_SYMBOL(c);
@@ -468,7 +503,7 @@ Token TextInput::nextToken() {
case '=': // +=
t._string += c;
eatInputChar();
- return t;
+ return;
}
if (options.signedNumbers) {
@@ -488,12 +523,12 @@ Token TextInput::nextToken() {
eatInputChar(); // i
eatInputChar(); // n
eatInputChar(); // f
- return t;
+ return;
}
}
}
- return t;
+ return;
case ':': // : or :: or ::> or ::= or := or :>
SETUP_SYMBOL(c);
@@ -510,12 +545,11 @@ Token TextInput::nextToken() {
eatInputChar();
}
}
- }
- else if (options.proofSymbols && (c == '=' || c == '>')) {
+ } else if (options.proofSymbols && (c == '=' || c == '>')) {
t._string += c;
eatInputChar();
}
- return t;
+ return;
case '=': // = or == or =>
SETUP_SYMBOL(c);
@@ -523,13 +557,11 @@ Token TextInput::nextToken() {
if (c == '=') {
t._string += c;
eatInputChar();
- return t;
} else if (options.proofSymbols && (c == '>')) {
t._string += c;
eatInputChar();
- return t;
}
- return t;
+ return;
case '*': // * or *=
case '/': // / or /=
@@ -541,9 +573,8 @@ Token TextInput::nextToken() {
if (c == '=') {
t._string += c;
eatInputChar();
- return t;
}
- return t;
+ return;
case '>': // >, >>,or >=
case '<': // <<, <<, or <= or <- or <:
@@ -556,7 +587,6 @@ Token TextInput::nextToken() {
if ((c == '=') || (orig_c == c)) {
t._string += c;
eatInputChar();
- return t;
} else if (options.proofSymbols) {
if ((orig_c == '<') && (c == '-')) {
t._string += c;
@@ -576,7 +606,7 @@ Token TextInput::nextToken() {
}
}
}
- return t;
+ return;
case '\\': // backslash or escaped comment char.
SETUP_SYMBOL(c);
@@ -591,9 +621,9 @@ Token TextInput::nextToken() {
t._string = c;
eatInputChar();
- return t;
+ return;
}
- return t;
+ return;
case '.': // number, ., .., or ...
if (isDigit(peekInputChar(1))) {
@@ -611,10 +641,10 @@ Token TextInput::nextToken() {
t._string += c;
eatInputChar();
}
- return t;
+ return;
}
- return t;
+ return;
} // switch (c)
@@ -640,7 +670,7 @@ numLabel:
} else {
t._extendedType = Token::INTEGER_TYPE;
}
-
+
if ((c == '0') && (peekInputChar(1) == 'x')) {
// Hex number
t._string += "0x";
@@ -656,7 +686,7 @@ numLabel:
}
} else {
- // Non-hex number
+ // Non-hex number
// Read the part before the decimal.
while (isDigit(c)) {
@@ -681,6 +711,7 @@ numLabel:
isSpecial = true;
// We are reading a floating point special value
// of the form -1.#IND00, -1.#INF00, or 1.#INF00
+ // (with or without the trailing 00
c = eatAndPeekInputChar();
char test = c;
if (! options.caseSensitive) {
@@ -718,16 +749,25 @@ numLabel:
t.line(), charNumber);
}
t._string += c;
+
+ // On older systems, there may be an extra 00 tacked on.
for (int j = 0; j < 2; ++j) {
c = eatAndPeekInputChar();
- if (c != '0') {
- throw BadMSVCSpecial
+ if (c == '0') {
+ c = eatAndPeekInputChar();
+ if (c != '0') {
+ throw BadMSVCSpecial
(
- "Incorrect floating-point special (inf or"
- "nan) format.",
- t.line(), charNumber);
+ "Incorrect floating-point special (inf or nan) "
+ "format.",
+ t.line(), charNumber);
+ } else {
+ eatInputChar();
+ t._string += "00";
+ }
+ } else {
+ break;
}
- t._string += (char)c;
}
} else {
@@ -763,7 +803,7 @@ numLabel:
c = eatAndPeekInputChar();
}
}
- return t;
+ return;
} else if (isLetter(c) || (c == '_')) {
// Identifier or keyword
@@ -798,7 +838,7 @@ numLabel:
t._type = Token::NUMBER;
t._extendedType = Token::FLOATING_POINT_TYPE;
}
- return t;
+ return;
} else if (c == '\"') {
@@ -807,7 +847,7 @@ numLabel:
// Double quoted string
parseQuotedString('\"', t);
- return t;
+ return;
} else if (c == options.singleQuoteCharacter) {
@@ -822,22 +862,20 @@ numLabel:
t._type = Token::SYMBOL;
t._extendedType = Token::SYMBOL_TYPE;
}
- return t;
+ return;
} // end of special case tokens
- if (c == EOF) {
+ if ((c == EOF) || (c == '\0')) {
t._type = Token::END;
t._extendedType = Token::END_TYPE;
t._string = "";
- return t;
+ return;
}
// Some unknown token
- debugAssertM(false,
- format("Unrecognized token type beginning with character '%c' (ASCII %d)",
- c, c));
- return t;
+ throw format("Unrecognized token type beginning with character '%c' (ASCII %d)", c, c);
+ return;
}
@@ -915,8 +953,9 @@ void TextInput::parseQuotedString(unsigned char delimiter, Token& t) {
}
}
+
bool TextInput::readBoolean() {
- Token t(read());
+ const Token& t = read();
if (t._type == Token::BOOLEAN) {
return t.boolean();
@@ -930,10 +969,53 @@ bool TextInput::readBoolean() {
Token::BOOLEAN, t._type);
}
+
+int TextInput::readInteger() {
+ Token t;
+ read(t);
+
+ if (t._extendedType == Token::INTEGER_TYPE) { // common case
+ return int(t.number());
+ } else {
+ // Even if signedNumbers is disabled, readInteger attempts to
+ // read a signed number, so we handle that case here.
+ if (! options.signedNumbers
+ && (t._type == Token::SYMBOL)
+ && ((t._string == "-")
+ || (t._string == "+"))) {
+
+ Token t2;
+ read(t2);
+
+ if ((t2._extendedType == Token::INTEGER_TYPE)
+ && (t2._character == t._character + 1)) {
+
+ if (t._string == "-") {
+ return (int)-t2.number();
+ } else {
+ return (int)t2.number();
+ }
+ }
+
+ // push back the second token.
+ push(t2);
+ }
+
+ // Push initial token back, and throw an error. We intentionally
+ // indicate that the wrong type is the type of the initial token.
+ // Logically, the number started there.
+ push(t);
+ throw WrongTokenType(options.sourceFileName, t.line(), t.character(),
+ Token::NUMBER, t._type);
+ }
+}
+
+
double TextInput::readNumber() {
- Token t(read());
+ Token t;
+ read(t);
- if (t._type == Token::NUMBER) {
+ if (t._type == Token::NUMBER) { // common case
return t.number();
}
@@ -970,7 +1052,8 @@ double TextInput::readNumber() {
Token TextInput::readStringToken() {
- Token t(read());
+ Token t;
+ read(t);
if (t._type == Token::STRING) { // fast path
return t;
@@ -985,8 +1068,9 @@ std::string TextInput::readString() {
return readStringToken()._string;
}
+
void TextInput::readString(const std::string& s) {
- Token t(readStringToken());
+ const Token& t = readStringToken();
if (t._string == s) { // fast path
return;
@@ -997,8 +1081,10 @@ void TextInput::readString(const std::string& s) {
s, t._string);
}
+
Token TextInput::readCommentToken() {
- Token t(read());
+ Token t;
+ read(t);
if (t._type == Token::COMMENT) { // fast path
return t;
@@ -1009,12 +1095,14 @@ Token TextInput::readCommentToken() {
Token::COMMENT, t._type);
}
+
std::string TextInput::readComment() {
return readCommentToken()._string;
}
+
void TextInput::readComment(const std::string& s) {
- Token t(readCommentToken());
+ const Token& t = readCommentToken();
if (t._string == s) { // fast path
return;
@@ -1025,8 +1113,10 @@ void TextInput::readComment(const std::string& s) {
s, t._string);
}
+
Token TextInput::readNewlineToken() {
- Token t(read());
+ Token t;
+ read(t);
if (t._type == Token::NEWLINE) { // fast path
return t;
@@ -1042,7 +1132,7 @@ std::string TextInput::readNewline() {
}
void TextInput::readNewline(const std::string& s) {
- Token t(readNewlineToken());
+ const Token& t = readNewlineToken();
if (t._string == s) { // fast path
return;
@@ -1053,11 +1143,19 @@ void TextInput::readNewline(const std::string& s) {
s, t._string);
}
+
Token TextInput::readSymbolToken() {
- Token t(read());
+ Token t;
+ readSymbolToken(t);
+ return t;
+}
+
+
+void TextInput::readSymbolToken(Token& t) {
+ read(t);
if (t._type == Token::SYMBOL) { // fast path
- return t;
+ return;
}
push(t);
@@ -1070,10 +1168,12 @@ std::string TextInput::readSymbol() {
return readSymbolToken()._string;
}
+
void TextInput::readSymbol(const std::string& symbol) {
- Token t(readSymbolToken());
+ Token t;
+ readSymbolToken(t);
- if (t._string == symbol) { // fast path
+ if (t._string == symbol) { // fast path
return;
}
@@ -1085,29 +1185,53 @@ void TextInput::readSymbol(const std::string& symbol) {
TextInput::TextInput(const std::string& filename, const Settings& opt) : options(opt) {
init();
- std::string input = readWholeFile(filename);
-
if (options.sourceFileName.empty()) {
options.sourceFileName = filename;
}
- int n = input.size();
- buffer.resize(n);
- System::memcpy(buffer.getCArray(), input.c_str(), n);
+
+ std::string zipfile;
+ if (FileSystem::inZipfile(filename, zipfile)) {
+ // TODO: this could be faster if we directly read the zipfile
+ const std::string& input = readWholeFile(filename);
+ size_t n = input.size();
+ buffer.resize(n);
+ System::memcpy(buffer.getCArray(), input.c_str(), n);
+ } else {
+ // Read directly into the array
+ const uint64 n = FileSystem::size(filename);
+ alwaysAssertM(n != uint64(-1), std::string("File does not exist: ") + filename);
+ buffer.resize(size_t(n));
+ FILE* f = FileSystem::fopen(filename.c_str(), "rb");
+ fread(buffer.getCArray(), 1, size_t(n), f);
+ FileSystem::fclose(f);
+ }
}
-TextInput::TextInput(FS fs, const std::string& str, const Settings& opt) : options(opt) {
- (void)fs;
+void TextInput::initFromString(const char* str, int len, const Settings& settings) {
+ options = settings;
init();
if (options.sourceFileName.empty()) {
- if (str.length() < 14) {
- options.sourceFileName = std::string("\"") + str + "\"";
+ if (len < 14) {
+ options.sourceFileName = format("\"%.*s\"", len, str);
} else {
- options.sourceFileName = std::string("\"") + str.substr(0, 10) + "...\"";
+ options.sourceFileName = format("\"%.*s...\"", 10, str);
}
}
- buffer.resize(str.length()); // we don't bother copying trailing NUL.
- System::memcpy(buffer.getCArray(), str.c_str(), buffer.size());
+ buffer.resize(len);
+ System::memcpy(buffer.getCArray(), str, buffer.size());
+}
+
+
+TextInput::TextInput(FS fs, const std::string& str, const Settings& opt) {
+ (void)fs;
+ initFromString(str.c_str(), (int)str.size(), opt);
+}
+
+
+TextInput::TextInput(FS fs, const char* str, size_t len, const Settings& opt) : options(opt) {
+ (void)fs;
+ initFromString(str, (int)len, opt);
}
diff --git a/dep/g3dlite/source/TextOutput.cpp b/dep/g3dlite/source/TextOutput.cpp
index 3257f6fb9ce..e764b59c7d6 100644
--- a/dep/g3dlite/source/TextOutput.cpp
+++ b/dep/g3dlite/source/TextOutput.cpp
@@ -1,11 +1,11 @@
/**
- @file TextOutput.cpp
+ \file G3D.lib/source/TextOutput.cpp
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @created 2004-06-21
- @edited 2010-03-14
+ \maintainer Morgan McGuire, http://graphics.cs.williams.edu
+ \created 2004-06-21
+ \edited 2013-04-09
- Copyright 2000-2010, Morgan McGuire.
+ Copyright 2000-2013, Morgan McGuire.
All rights reserved.
*/
@@ -17,11 +17,12 @@
namespace G3D {
TextOutput::TextOutput(const TextOutput::Settings& opt) :
- startingNewLine(true),
+ startingNewLine(true),
currentColumn(0),
- inDQuote(false),
- filename(""),
- indentLevel(0)
+ inDQuote(false),
+ filename(""),
+ indentLevel(0),
+ m_currentLine(0)
{
setOptions(opt);
}
@@ -30,9 +31,10 @@ TextOutput::TextOutput(const TextOutput::Settings& opt) :
TextOutput::TextOutput(const std::string& fil, const TextOutput::Settings& opt) :
startingNewLine(true),
currentColumn(0),
- inDQuote(false),
- filename(fil),
- indentLevel(0)
+ inDQuote(false),
+ filename(fil),
+ indentLevel(0),
+ m_currentLine(0)
{
setOptions(opt);
@@ -106,9 +108,17 @@ static std::string escape(const std::string& string) {
return result;
}
+
void TextOutput::writeString(const std::string& string) {
+ // Never break a line in a string
+ const Settings::WordWrapMode old = option.wordWrap;
+
+ if (! option.allowWordWrapInsideDoubleQuotes) {
+ option.wordWrap = Settings::WRAP_NONE;
+ }
// Convert special characters to escape sequences
this->printf("\"%s\"", escape(string).c_str());
+ option.wordWrap = old;
}
@@ -117,7 +127,7 @@ void TextOutput::writeBoolean(bool b) {
}
void TextOutput::writeNumber(double n) {
- this->printf("%f ", n);
+ this->printf("%g ", n);
}
@@ -128,11 +138,14 @@ void TextOutput::writeNumber(int n) {
void TextOutput::writeSymbol(const std::string& string) {
if (string.size() > 0) {
- // TODO: check for legal symbols?
this->printf("%s ", string.c_str());
}
}
+void TextOutput::writeSymbol(char c) {
+ this->printf("%c ", c);
+}
+
void TextOutput::writeSymbols(
const std::string& a,
const std::string& b,
@@ -166,6 +179,17 @@ void TextOutput::printf(const char* formatString, ...) {
}
+bool TextOutput::deleteSpace() {
+ if ((currentColumn > 0) && (data.last() == ' ')) {
+ data.popDiscard();
+ --currentColumn;
+ return true;
+ } else {
+ return false;
+ }
+}
+
+
void TextOutput::convertNewlines(const std::string& in, std::string& out) {
// TODO: can be significantly optimized in cases where
// single characters are copied in order by walking through
@@ -256,20 +280,20 @@ void TextOutput::wordWrapIndentAppend(const std::string& str) {
// search backwards for a space, then execute case 2.
// Index of most recent space
- uint32 lastSpace = data.size() - 1;
+ size_t lastSpace = data.size() - 1;
// How far back we had to look for a space
- uint32 k = 0;
- uint32 maxLookBackward = currentColumn - indentSpaces;
+ size_t k = 0;
+ size_t maxLookBackward = currentColumn - indentSpaces;
// Search backwards (from current character), looking for a space.
while ((k < maxLookBackward) &&
- (lastSpace > 0) &&
- (! ((data[lastSpace] == ' ') && unquotedSpace))) {
+ (lastSpace > 0) &&
+ (! ((data[(int)lastSpace] == ' ') && unquotedSpace))) {
--lastSpace;
++k;
- if ((data[lastSpace] == '\"') && !option.allowWordWrapInsideDoubleQuotes) {
+ if ((data[(int)lastSpace] == '\"') && !option.allowWordWrapInsideDoubleQuotes) {
unquotedSpace = ! unquotedSpace;
}
}
@@ -296,10 +320,10 @@ void TextOutput::wordWrapIndentAppend(const std::string& str) {
// Find the start of the spaces. firstSpace is the index of the
// first non-space, looking backwards from lastSpace.
- uint32 firstSpace = lastSpace;
+ size_t firstSpace = lastSpace;
while ((k < maxLookBackward) &&
(firstSpace > 0) &&
- (data[firstSpace] == ' ')) {
+ (data[(int)firstSpace] == ' ')) {
--firstSpace;
++k;
}
@@ -323,8 +347,8 @@ void TextOutput::wordWrapIndentAppend(const std::string& str) {
// Copy over the characters that should be saved
Array<char> temp;
- for (uint32 j = lastSpace + 1; j < (uint32)data.size(); ++j) {
- char c = data[j];
+ for (size_t j = lastSpace + 1; j < (uint32)data.size(); ++j) {
+ char c = data[(int)j];
if (c == '\"') {
// Undo changes to quoting (they will be re-done
@@ -339,8 +363,8 @@ void TextOutput::wordWrapIndentAppend(const std::string& str) {
writeNewline();
// Write them back
- for (uint32 j = 0; j < (uint32)temp.size(); ++j) {
- indentAppend(temp[j]);
+ for (size_t j = 0; j < (uint32)temp.size(); ++j) {
+ indentAppend(temp[(int)j]);
}
// We are now free to continue adding from the
@@ -378,12 +402,13 @@ void TextOutput::indentAppend(char c) {
startingNewLine = (c == '\n');
if (startingNewLine) {
currentColumn = 0;
+ ++m_currentLine;
}
}
void TextOutput::vprintf(const char* formatString, va_list argPtr) {
- std::string str = vformat(formatString, argPtr);
+ const std::string& str = vformat(formatString, argPtr);
std::string clean;
convertNewlines(str, clean);
diff --git a/dep/g3dlite/source/ThreadSet.cpp b/dep/g3dlite/source/ThreadSet.cpp
index ee3895fe9de..df6fd4d4721 100644
--- a/dep/g3dlite/source/ThreadSet.cpp
+++ b/dep/g3dlite/source/ThreadSet.cpp
@@ -1,4 +1,5 @@
#include "G3D/ThreadSet.h"
+#include "G3D/GThread.h"
namespace G3D {
@@ -25,7 +26,7 @@ int ThreadSet::numStarted() const {
}
-void ThreadSet::start(GThread::SpawnBehavior lastBehavior) const {
+void ThreadSet::start(SpawnBehavior lastBehavior) const {
ThreadSet* me = const_cast<ThreadSet*>(this);
Array<GThreadRef> unstarted;
@@ -38,20 +39,22 @@ void ThreadSet::start(GThread::SpawnBehavior lastBehavior) const {
}
int last = unstarted.size();
- if (lastBehavior == GThread::USE_CURRENT_THREAD) {
+ if (lastBehavior == USE_CURRENT_THREAD) {
// Save the last unstarted for the current thread
--last;
}
+ // Start all threads
for (int i = 0; i < last; ++i) {
- unstarted[i]->start(GThread::USE_NEW_THREAD);
+ unstarted[i]->start(USE_NEW_THREAD);
}
me->m_lock.unlock();
// Start the last one on my thread
- if ((unstarted.size() > 0) && (lastBehavior == GThread::USE_CURRENT_THREAD)) {
- unstarted.last()->start(GThread::USE_CURRENT_THREAD);
+ if ((unstarted.size() > 0) && (lastBehavior == USE_CURRENT_THREAD)) {
+ unstarted.last()->start(USE_CURRENT_THREAD);
+ debugAssert(unstarted.last()->completed());
}
}
@@ -70,6 +73,7 @@ void ThreadSet::terminate() const {
void ThreadSet::waitForCompletion() const {
ThreadSet* me = const_cast<ThreadSet*>(this);
+
me->m_lock.lock();
for (int i = 0; i < m_thread.size(); ++i) {
if (m_thread[i]->started()) {
diff --git a/dep/g3dlite/source/Triangle.cpp b/dep/g3dlite/source/Triangle.cpp
index 253438ad5fb..e1b5f8e051b 100644
--- a/dep/g3dlite/source/Triangle.cpp
+++ b/dep/g3dlite/source/Triangle.cpp
@@ -172,7 +172,7 @@ bool Triangle::intersect(const Ray& ray, float& distance, float baryCoord[3]) co
// This is a new hit, closer than the previous one
distance = t;
- baryCoord[0] = 1.0 - u - v;
+ baryCoord[0] = 1.0f - u - v;
baryCoord[1] = u;
baryCoord[2] = v;
diff --git a/dep/g3dlite/source/UprightFrame.cpp b/dep/g3dlite/source/UprightFrame.cpp
index c80264bf4e8..80c7e24023d 100644
--- a/dep/g3dlite/source/UprightFrame.cpp
+++ b/dep/g3dlite/source/UprightFrame.cpp
@@ -1,11 +1,7 @@
/**
- @file UprightFrame.cpp
- Box class
+ \file UprightFrame.cpp
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2007-05-02
- @edited 2007-05-05
+ \maintainer Morgan McGuire, http://graphics.cs.williams.edu
*/
#include "G3D/UprightFrame.h"
@@ -17,12 +13,38 @@ namespace G3D {
UprightFrame::UprightFrame(const CoordinateFrame& cframe) {
Vector3 look = cframe.lookVector();
- yaw = G3D::pi() + atan2(look.x, look.z);
+ yaw = (float)(G3D::pi() + atan2(look.x, look.z));
pitch = asin(look.y);
translation = cframe.translation;
}
+
+UprightFrame::UprightFrame(const Any& any) {
+ any.verifyName("UprightFrame");
+ any.verifyType(Any::TABLE);
+
+ translation = any["translation"];
+ pitch = any["pitch"];
+ yaw = any["yaw"];
+}
+
+
+Any UprightFrame::toAny() const {
+ Any any(Any::TABLE, "UprightFrame");
+
+ any["translation"] = translation;
+ any["pitch"] = pitch;
+ any["yaw"] = yaw;
+
+ return any;
+}
+
+
+UprightFrame& UprightFrame::operator=(const Any& any) {
+ *this = UprightFrame(any);
+ return *this;
+}
CoordinateFrame UprightFrame::toCoordinateFrame() const {
CoordinateFrame cframe;
@@ -59,15 +81,15 @@ void UprightFrame::unwrapYaw(UprightFrame* a, int N) {
// to be interpolated the long way.
// Find canonical [0, 2pi] versions of these numbers
- float p = wrap(prev, twoPi());
- float c = wrap(cur, twoPi());
+ float p = (float)wrap(prev, twoPi());
+ float c = (float)wrap(cur, twoPi());
// Find the difference -pi < diff < pi between the current and previous values
float diff = c - p;
if (diff < -G3D::pi()) {
- diff += twoPi();
+ diff += (float)twoPi();
} else if (diff > G3D::pi()) {
- diff -= twoPi();
+ diff -= (float)twoPi();
}
// Offset the current from the previous by the difference
@@ -77,7 +99,6 @@ void UprightFrame::unwrapYaw(UprightFrame* a, int N) {
}
}
-
void UprightFrame::serialize(class BinaryOutput& b) const {
translation.serialize(b);
b.writeFloat32(pitch);
@@ -91,9 +112,70 @@ void UprightFrame::deserialize(class BinaryInput& b) {
yaw = b.readFloat32();
}
+///////////////////////////////////////////////////////////////////////////////////////////
+
+UprightSpline::UprightSpline() : Spline<UprightFrame>() {
+}
+
+
+UprightSpline::UprightSpline(const Any& any) {
+ any.verifyName("UprightSpline");
+ any.verifyType(Any::TABLE);
+
+ extrapolationMode = any["extrapolationMode"];
+
+ const Any& controlsAny = any["control"];
+ controlsAny.verifyType(Any::ARRAY);
+
+ control.resize(controlsAny.length());
+ for (int controlIndex = 0; controlIndex < control.length(); ++controlIndex) {
+ control[controlIndex] = controlsAny[controlIndex];
+ }
+
+ const Any& timesAny = any["time"];
+ timesAny.verifyType(Any::ARRAY);
+
+ time.resize(timesAny.length());
+ for (int timeIndex = 0; timeIndex < time.length(); ++timeIndex) {
+ time[timeIndex] = timesAny[timeIndex];
+ }
+}
+
+
+Any UprightSpline::toAny(const std::string& myName) const {
+ Any any(Any::TABLE, myName);
+
+ any["extrapolationMode"] = extrapolationMode;
+
+ Any controlsAny(Any::ARRAY);
+ for (int controlIndex = 0; controlIndex < control.length(); ++controlIndex) {
+ controlsAny.append(control[controlIndex]);
+ }
+ any["control"] = controlsAny;
+
+ Any timesAny(Any::ARRAY);
+ for (int timeIndex = 0; timeIndex < time.length(); ++timeIndex) {
+ timesAny.append(Any(time[timeIndex]));
+ }
+ any["time"] = timesAny;
+
+ return any;
+}
+
+
+Any UprightSpline::toAny() const {
+ return toAny("UprightSpline");
+}
+
+
+UprightSpline& UprightSpline::operator=(const Any& any) {
+ *this = UprightSpline(any);
+ return *this;
+}
+
void UprightSpline::serialize(class BinaryOutput& b) const {
- b.writeBool8(cyclic);
+ b.writeInt32(extrapolationMode);
b.writeInt32(control.size());
for (int i = 0; i < control.size(); ++i) {
@@ -107,7 +189,7 @@ void UprightSpline::serialize(class BinaryOutput& b) const {
void UprightSpline::deserialize(class BinaryInput& b) {
- cyclic = b.readBool8();
+ extrapolationMode = SplineExtrapolationMode(b.readInt32());
control.resize(b.readInt32());
for (int i = 0; i < control.size(); ++i) {
@@ -124,7 +206,7 @@ void UprightSpline::deserialize(class BinaryInput& b) {
// Import legacy path
time.resize(control.size());
for (int i = 0; i < time.size(); ++i) {
- time[i] = i;
+ time[i] = (float)i;
}
}
}
diff --git a/dep/g3dlite/source/Vector2.cpp b/dep/g3dlite/source/Vector2.cpp
index ec0737c3755..a6edea9a83f 100644
--- a/dep/g3dlite/source/Vector2.cpp
+++ b/dep/g3dlite/source/Vector2.cpp
@@ -9,12 +9,13 @@
at http://www.magic-software.com
@created 2001-06-02
- @edited 2009-11-16
+ @edited 2010-11-16
*/
#include "G3D/platform.h"
#include <stdlib.h>
#include "G3D/Vector2.h"
+#include "G3D/Vector2int32.h"
#include "G3D/g3dmath.h"
#include "G3D/format.h"
#include "G3D/BinaryInput.h"
@@ -25,9 +26,12 @@
namespace G3D {
+Vector2::Vector2(const Vector2int32& other) : x((float)other.x), y((float)other.y) {
+}
+
Vector2::Vector2(const Any& any) {
- any.verifyName("Vector2");
+ any.verifyName("Vector2", "Point2");
any.verifyType(Any::TABLE, Any::ARRAY);
any.verifySize(2);
@@ -42,7 +46,13 @@ Vector2::Vector2(const Any& any) {
}
-Vector2::operator Any() const {
+Vector2& Vector2::operator=(const Any& a) {
+ *this = Vector2(a);
+ return *this;
+}
+
+
+Any Vector2::toAny() const {
Any any(Any::ARRAY, "Vector2");
any.append(x, y);
return any;
@@ -70,26 +80,26 @@ const Vector2& Vector2::unitY() {
}
const Vector2& Vector2::inf() {
- static Vector2 v((float)G3D::finf(), (float)G3D::finf());
- return v;
+ static Vector2 v(G3D::finf(), G3D::finf());
+ return v;
}
const Vector2& Vector2::nan() {
- static Vector2 v((float)G3D::fnan(), (float)G3D::fnan());
- return v;
+ static Vector2 v(G3D::fnan(), G3D::fnan());
+ return v;
}
const Vector2& Vector2::minFinite() {
- static Vector2 v(-FLT_MAX, -FLT_MAX);
- return v;
+ static Vector2 v(-FLT_MAX, -FLT_MAX);
+ return v;
}
const Vector2& Vector2::maxFinite() {
- static Vector2 v(FLT_MAX, FLT_MAX);
- return v;
+ static Vector2 v(FLT_MAX, FLT_MAX);
+ return v;
}
@@ -145,9 +155,7 @@ Vector2 Vector2::random(G3D::Random& r) {
} while (result.squaredLength() >= 1.0f);
- result.unitize();
-
- return result;
+ return result.direction();
}
@@ -161,20 +169,6 @@ Vector2& Vector2::operator/= (float k) {
return *this;
}
-//----------------------------------------------------------------------------
-float Vector2::unitize (float fTolerance) {
- float fLength = length();
-
- if (fLength > fTolerance) {
- float fInvLength = 1.0f / fLength;
- x *= fInvLength;
- y *= fInvLength;
- } else {
- fLength = 0.0;
- }
-
- return fLength;
-}
//----------------------------------------------------------------------------
@@ -220,5 +214,12 @@ Vector4 Vector2::xyyy() const { return Vector4 (x, y, y, y); }
Vector4 Vector2::yyyy() const { return Vector4 (y, y, y, y); }
+void serialize(const Vector2& v, class BinaryOutput& b) {
+ v.serialize(b);
+}
+
+void deserialize(Vector2& v, class BinaryInput& b) {
+ v.deserialize(b);
+}
} // namespace
diff --git a/dep/g3dlite/source/Vector2int16.cpp b/dep/g3dlite/source/Vector2int16.cpp
index 2a4035a4d09..16893eb1752 100644
--- a/dep/g3dlite/source/Vector2int16.cpp
+++ b/dep/g3dlite/source/Vector2int16.cpp
@@ -1,10 +1,10 @@
/**
- @file Vector2int16.cpp
+ \file G3D/Vector2int16.cpp
- @author Morgan McGuire, http://graphics.cs.williams.edu
+ \author Morgan McGuire, http://graphics.cs.williams.edu
- @created 2003-08-09
- @edited 2006-01-29
+ \created 2003-08-09
+ \edited 2011-01-06
*/
#include "G3D/platform.h"
@@ -13,9 +13,41 @@
#include "G3D/Vector2.h"
#include "G3D/BinaryInput.h"
#include "G3D/BinaryOutput.h"
+#include "G3D/Any.h"
+#include "G3D/Vector2int32.h"
namespace G3D {
+Vector2int16::Vector2int16(const class Vector2int32& v) : x(v.x), y(v.y) {}
+
+Vector2int16::Vector2int16(const Any& any) {
+ any.verifyName("Vector2int16", "Point2int16");
+ any.verifyType(Any::TABLE, Any::ARRAY);
+ any.verifySize(2);
+
+ if (any.type() == Any::ARRAY) {
+ x = any[0];
+ y = any[1];
+ } else {
+ // Table
+ x = any["x"];
+ y = any["y"];
+ }
+}
+
+
+Vector2int16& Vector2int16::operator=(const Any& a) {
+ *this = Vector2int16(a);
+ return *this;
+}
+
+
+Any Vector2int16::toAny() const {
+ Any any(Any::ARRAY, "Vector2int16");
+ any.append(x, y);
+ return any;
+}
+
Vector2int16::Vector2int16(const class Vector2& v) {
x = (int16)iFloor(v.x + 0.5);
y = (int16)iFloor(v.y + 0.5);
diff --git a/dep/g3dlite/source/Vector3.cpp b/dep/g3dlite/source/Vector3.cpp
index 55343e96ece..e2d9643e5cc 100644
--- a/dep/g3dlite/source/Vector3.cpp
+++ b/dep/g3dlite/source/Vector3.cpp
@@ -1,14 +1,14 @@
/**
- @file Vector3.cpp
+ \file G3D.lib/source/Vector3.cpp
3D vector class
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
+ \maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @cite Portions based on Dave Eberly's Magic Software Library at http://www.magic-software.com
+ \cite Portions based on Dave Eberly's Magic Software Library at http://www.magic-software.com
- @created 2001-06-02
- @edited 2009-11-27
+ \created 2001-06-02
+ \edited 2011-11-27
*/
#include <limits>
@@ -31,8 +31,39 @@
namespace G3D {
+
+Vector3 Vector3::movedTowards(const Vector3& goal, float maxTranslation) const {
+ Vector3 t = *this;
+ t.moveTowards(goal, maxTranslation);
+ return t;
+}
+
+
+void Vector3::moveTowards(const Vector3& goal, float maxTranslation) {
+ // Apply clamped translation
+ Vector3 dX = goal - *this;
+ float length = dX.length();
+ if ((length < 0.00001f) || (length < maxTranslation)) {
+ *this = goal;
+ } else {
+ *this += G3D::min(1.0f, maxTranslation / length) * dX;
+ }
+}
+
+
Vector3::Vector3(const Any& any) {
- any.verifyName("Vector3");
+ if (any.name() == "Vector3::inf" || any.name() == "Point3::inf") {
+ *this = inf();
+ return;
+ } else if (any.name() == "Vector3::zero" || any.name() == "Point3::zero") {
+ *this = zero();
+ return;
+ } else if (any.name() == "Vector3::nan" || any.name() == "Point3::nan") {
+ *this = nan();
+ return;
+ }
+
+ any.verifyName("Vector3", "Point3");
any.verifyType(Any::TABLE, Any::ARRAY);
any.verifySize(3);
@@ -48,8 +79,25 @@ Vector3::Vector3(const Any& any) {
}
}
-Vector3::operator Any() const {
- Any any(Any::ARRAY, "Vector3");
+
+bool Vector3::isNaN() const {
+ return G3D::isNaN(x) || G3D::isNaN(y) || G3D::isNaN(z);
+}
+
+
+Vector3& Vector3::operator=(const Any& a) {
+ *this = Vector3(a);
+ return *this;
+}
+
+
+Any Vector3::toAny() const {
+ return toAny("Vector3");
+}
+
+
+Any Vector3::toAny(const std::string& name) const {
+ Any any(Any::ARRAY, name);
any.append(x, y, z);
return any;
}
@@ -105,7 +153,11 @@ Vector3::Axis Vector3::primaryAxis() const {
size_t Vector3::hashCode() const {
- return Vector4(*this, 0.0f).hashCode();
+ const uint32* u = (const uint32*)this;
+ return
+ HashTrait<uint32>::hashCode(u[0]) ^
+ HashTrait<uint32>::hashCode(~u[1]) ^
+ HashTrait<uint32>::hashCode((u[2] << 16) | ~(u[2] >> 16));
}
std::ostream& operator<<(std::ostream& os, const Vector3& v) {
@@ -120,7 +172,7 @@ double frand() {
}
Vector3::Vector3(TextInput& t) {
- deserialize(t);
+ deserialize(t);
}
Vector3::Vector3(BinaryInput& b) {
@@ -178,22 +230,6 @@ Vector3 Vector3::random(Random& r) {
}
-float Vector3::unitize(float fTolerance) {
- float fMagnitude = magnitude();
-
- if (fMagnitude > fTolerance) {
- float fInvMagnitude = 1.0f / fMagnitude;
- x *= fInvMagnitude;
- y *= fInvMagnitude;
- z *= fInvMagnitude;
- } else {
- fMagnitude = 0.0f;
- }
-
- return fMagnitude;
-}
-
-
Vector3 Vector3::reflectAbout(const Vector3& normal) const {
Vector3 out;
@@ -224,6 +260,26 @@ Vector3 Vector3::cosHemiRandom(const Vector3& normal, Random& r) {
}
+Vector3 Vector3::cosSphereRandom(const Vector3& normal, Random& r) {
+ debugAssertM(G3D::fuzzyEq(normal.length(), 1.0f),
+ "cosSphereRandom requires its argument to have unit length");
+
+ float x, y, z;
+ r.cosSphere(x, y, z);
+
+ // Make a coordinate system
+ const Vector3& Z = normal;
+
+ Vector3 X, Y;
+ normal.getTangents(X, Y);
+
+ return
+ x * X +
+ y * Y +
+ z * Z;
+}
+
+
Vector3 Vector3::cosPowHemiRandom(const Vector3& normal, const float k, Random& r) {
debugAssertM(G3D::fuzzyEq(normal.length(), 1.0f),
"cosPowHemiRandom requires its argument to have unit length");
@@ -310,40 +366,20 @@ void Vector3::orthonormalize (Vector3 akVector[3]) {
// product of vectors A and B.
// compute u0
- akVector[0].unitize();
+ akVector[0] = akVector[0].direction();
// compute u1
- float fDot0 = akVector[0].dot(akVector[1]);
+ float fDot0 = akVector[0].dot(akVector[1]);
akVector[1] -= akVector[0] * fDot0;
- akVector[1].unitize();
+ akVector[1] = akVector[1].direction();
// compute u2
- float fDot1 = akVector[1].dot(akVector[2]);
+ float fDot1 = akVector[1].dot(akVector[2]);
fDot0 = akVector[0].dot(akVector[2]);
akVector[2] -= akVector[0] * fDot0 + akVector[1] * fDot1;
- akVector[2].unitize();
+ akVector[2] = akVector[2].direction();
}
-//----------------------------------------------------------------------------
-void Vector3::generateOrthonormalBasis (Vector3& rkU, Vector3& rkV,
- Vector3& rkW, bool bUnitLengthW) {
- if ( !bUnitLengthW )
- rkW.unitize();
-
- if ( G3D::abs(rkW.x) >= G3D::abs(rkW.y)
- && G3D::abs(rkW.x) >= G3D::abs(rkW.z) ) {
- rkU.x = -rkW.y;
- rkU.y = + rkW.x;
- rkU.z = 0.0;
- } else {
- rkU.x = 0.0;
- rkU.y = + rkW.z;
- rkU.z = -rkW.y;
- }
-
- rkU.unitize();
- rkV = rkW.cross(rkU);
-}
//----------------------------------------------------------------------------
@@ -497,8 +533,12 @@ Vector4 Vector3::yzzz() const { return Vector4 (y, z, z, z); }
Vector4 Vector3::zzzz() const { return Vector4 (z, z, z, z); }
+void serialize(const Vector3& v, class BinaryOutput& b) {
+ v.serialize(b);
+}
-
-
+void deserialize(Vector3& v, class BinaryInput& b) {
+ v.deserialize(b);
+}
} // namespace
diff --git a/dep/g3dlite/source/Vector3int16.cpp b/dep/g3dlite/source/Vector3int16.cpp
index 44069b85d8c..3c9c5dc9295 100644
--- a/dep/g3dlite/source/Vector3int16.cpp
+++ b/dep/g3dlite/source/Vector3int16.cpp
@@ -46,4 +46,14 @@ std::string Vector3int16::toString() const {
return G3D::format("(%d, %d, %d)", x, y, z);
}
+
+Vector3int16 Vector3int16::floor(const Vector3& v) {
+ return Vector3int16(iFloor(v.x), iFloor(v.y), iFloor(v.z));
+}
+
+
+Vector3int16 Vector3int16::ceil(const Vector3& v) {
+ return Vector3int16(iCeil(v.x), iCeil(v.y), iCeil(v.z));
+}
+
}
diff --git a/dep/g3dlite/source/Vector3int32.cpp b/dep/g3dlite/source/Vector3int32.cpp
index 3bd8e9f2bc2..a4867ba01c0 100644
--- a/dep/g3dlite/source/Vector3int32.cpp
+++ b/dep/g3dlite/source/Vector3int32.cpp
@@ -4,7 +4,7 @@
@author Morgan McGuire, http://graphics.cs.williams.edu
@created 2008-07-01
- @edited 2008-07-01
+ @edited 2010-10-20
*/
#include "G3D/platform.h"
@@ -15,13 +15,76 @@
#include "G3D/BinaryInput.h"
#include "G3D/BinaryOutput.h"
#include "G3D/format.h"
+#include "G3D/Vector2int32.h"
+#include "G3D/Vector2int16.h"
+#include "G3D/Any.h"
namespace G3D {
+Vector3int32 iFloor(const Vector3& v) {
+ return Vector3int32(iFloor(v.x), iFloor(v.y), iFloor(v.z));
+}
+
+Vector3int32::Vector3int32(const Any& any) {
+ *this = Vector3int32();
+ any.verifyNameBeginsWith("Vector3int32", "Point3int32");
+
+ switch (any.type()) {
+ case Any::TABLE:
+
+ for (Any::AnyTable::Iterator it = any.table().begin(); it.isValid(); ++it) {
+ const std::string& key = toLower(it->key);
+
+ if (key == "x") {
+ x = it->value;
+ } else if (key == "y") {
+ y = it->value;
+ } else if (key == "z") {
+ z = it->value;
+ } else {
+ any.verify(false, "Illegal key: " + it->key);
+ }
+ }
+ break;
+
+ case Any::ARRAY:
+
+ (void)any.name();
+ if (any.size() == 1) {
+ x = y = z = any[0];
+ } else {
+ any.verifySize(3);
+ x = any[0];
+ y = any[1];
+ z = any[2];
+ }
+ break;
+
+ default:
+ any.verify(false, "Bad Vector3int32 constructor");
+ }
+}
+
+
+Any Vector3int32::toAny() const {
+ Any a(Any::ARRAY, "Vector3int32");
+ a.append(x, y, z);
+ return a;
+}
+
Vector3int32::Vector3int32(const class Vector3& v) {
- x = (int32)iFloor(v.x + 0.5);
- y = (int32)iFloor(v.y + 0.5);
- z = (int32)iFloor(v.z + 0.5);
+ x = (int32)(v.x + 0.5);
+ y = (int32)(v.y + 0.5);
+ z = (int32)(v.z + 0.5);
+}
+
+Vector3int32::Vector3int32(const class Vector2int32& v, int _z) : x(v.x), y(v.y), z(_z) {}
+
+Vector3int32::Vector3int32(const class Vector2int16& v, int _z) : x(v.x), y(v.y), z(_z) {}
+
+
+Vector3int32 Vector3int32::truncate(const class Vector3& v) {
+ return Vector3int32(int32(v.x), int32(v.y), int32(v.z));
}
@@ -54,4 +117,16 @@ std::string Vector3int32::toString() const {
return G3D::format("(%d, %d, %d)", x, y, z);
}
+//----------------------------------------------------------------------------
+// 2-char swizzles
+
+Vector2int32 Vector3int32::xx() const { return Vector2int32 (x, x); }
+Vector2int32 Vector3int32::yx() const { return Vector2int32 (y, x); }
+Vector2int32 Vector3int32::zx() const { return Vector2int32 (z, x); }
+Vector2int32 Vector3int32::xy() const { return Vector2int32 (x, y); }
+Vector2int32 Vector3int32::yy() const { return Vector2int32 (y, y); }
+Vector2int32 Vector3int32::zy() const { return Vector2int32 (z, y); }
+Vector2int32 Vector3int32::xz() const { return Vector2int32 (x, z); }
+Vector2int32 Vector3int32::yz() const { return Vector2int32 (y, z); }
+Vector2int32 Vector3int32::zz() const { return Vector2int32 (z, z); }
}
diff --git a/dep/g3dlite/source/Vector4.cpp b/dep/g3dlite/source/Vector4.cpp
index b5f23d69950..0b19fa5b803 100644
--- a/dep/g3dlite/source/Vector4.cpp
+++ b/dep/g3dlite/source/Vector4.cpp
@@ -4,7 +4,7 @@
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
@created 2001-07-09
- @edited 2010-07-05
+ @edited 2010-11-05
*/
#include <stdlib.h>
@@ -21,6 +21,12 @@
namespace G3D {
+Vector4& Vector4::operator=(const Any& a) {
+ *this = Vector4(a);
+ return *this;
+}
+
+
Vector4::Vector4(const Any& any) {
any.verifyName("Vector4");
any.verifyType(Any::TABLE, Any::ARRAY);
@@ -40,7 +46,8 @@ Vector4::Vector4(const Any& any) {
}
}
-Vector4::operator Any() const {
+
+Any Vector4::toAny() const {
Any any(Any::ARRAY, "Vector4");
any.append(x, y, z, w);
return any;
@@ -134,7 +141,7 @@ Vector4 Vector4::operator/ (float fScalar) const {
Vector4 kQuot;
if ( fScalar != 0.0 ) {
- float fInvScalar = 1.0f / fScalar;
+ float fInvScalar = 1.0f / fScalar;
kQuot.x = fInvScalar * x;
kQuot.y = fInvScalar * y;
kQuot.z = fInvScalar * z;
@@ -148,13 +155,13 @@ Vector4 Vector4::operator/ (float fScalar) const {
//----------------------------------------------------------------------------
Vector4& Vector4::operator/= (float fScalar) {
if (fScalar != 0.0f) {
- float fInvScalar = 1.0f / fScalar;
+ float fInvScalar = 1.0f / fScalar;
x *= fInvScalar;
y *= fInvScalar;
z *= fInvScalar;
w *= fInvScalar;
} else {
- *this = Vector4::inf();
+ *this = Vector4::inf();
}
return *this;
@@ -511,5 +518,12 @@ Vector4 Vector4::ywww() const { return Vector4 (y, w, w, w); }
Vector4 Vector4::zwww() const { return Vector4 (z, w, w, w); }
Vector4 Vector4::wwww() const { return Vector4 (w, w, w, w); }
+void serialize(const Vector4& v, class BinaryOutput& b) {
+ v.serialize(b);
+}
+
+void deserialize(Vector4& v, class BinaryInput& b) {
+ v.deserialize(b);
+}
}; // namespace
diff --git a/dep/g3dlite/source/Welder.cpp b/dep/g3dlite/source/Welder.cpp
index 2db47722e64..55a888590c3 100644
--- a/dep/g3dlite/source/Welder.cpp
+++ b/dep/g3dlite/source/Welder.cpp
@@ -1,10 +1,10 @@
/**
- @file Welder.cpp
+ \file Welder.cpp
- @author Morgan McGuire, Kyle Whitson, Corey Taylor
+ \author Morgan McGuire, Kyle Whitson, Corey Taylor
- @created 2008-07-30
- @edited 2009-11-29
+ \created 2008-07-30
+ \edited 2011-07-04
*/
#include "G3D/platform.h"
@@ -17,9 +17,14 @@
#include "G3D/AreaMemoryManager.h"
#include "G3D/Any.h"
#include "G3D/stringutils.h"
+#include "G3D/BinaryInput.h"
+#include "G3D/BinaryOutput.h"
namespace G3D { namespace _internal{
+// Uncomment to print information that can help with performance
+// profiling.
+//#define VERBOSE
/** Used by WeldHelper2::smoothNormals. */
class VN {
@@ -98,11 +103,11 @@ private:
*/
int getIndex(const Vector3& v, const Vector3& n, const Vector2& t) {
PointHashGrid<VNTi>::SphereIterator it =
- weldGrid.beginSphereIntersection(Sphere(v, vertexWeldRadius));
+ weldGrid.begin(Sphere(v, vertexWeldRadius));
if (n.isZero()) {
// Don't bother trying to match the surface normal, since this vertex has no surface normal.
- while (it.hasMore()) {
+ while (it.isValid()) {
if ((t - it->texCoord).squaredLength() <= texCoordWeldRadius2) {
// This is the vertex
return it->index;
@@ -110,7 +115,7 @@ private:
++it;
}
} else {
- while (it.hasMore()) {
+ while (it.isValid()) {
if (((n - it->normal).squaredLength() <= normalWeldRadius2) &&
((t - it->texCoord).squaredLength() <= texCoordWeldRadius2)) {
// This is the vertex
@@ -142,12 +147,16 @@ private:
Called from process()
*/
- void updateTriLists(
- Array<Array<int>*>& indexArrayArray,
- const Array<Vector3>& vertexArray,
- const Array<Vector3>& normalArray,
- const Array<Vector2>& texCoordArray) {
-
+ void updateTriLists
+ (Array<Array<int>*>& indexArrayArray,
+ const Array<Vector3>& vertexArray,
+ const Array<Vector3>& normalArray,
+ const Array<Vector2>& texCoordArray) {
+
+# ifdef VERBOSE
+ debugPrintf("WeldHelper::updateTriLists\n");
+# endif
+
// Compute a hash grid so that we can find neighbors quickly.
// It begins empty and is extended as the tri lists are iterated
// through.
@@ -183,13 +192,17 @@ private:
/** Expands the indexed triangle lists into a triangle list.
Called from process() */
- void unroll(
- const Array<Array<int>*>& indexArrayArray,
- const Array<Vector3>& vertexArray,
- const Array<Vector2>& texCoordArray,
- Array<Vector3>& unrolledVertexArray,
- Array<Vector2>& unrolledTexCoordArray) {
-
+ void unroll
+ (const Array<Array<int>*>& indexArrayArray,
+ const Array<Vector3>& vertexArray,
+ const Array<Vector2>& texCoordArray,
+ Array<Vector3>& unrolledVertexArray,
+ Array<Vector2>& unrolledTexCoordArray) {
+
+# ifdef VERBOSE
+ debugPrintf("WeldHelper::unroll\n");
+# endif
+
int numTriLists = indexArrayArray.size();
for (int t = 0; t < numTriLists; ++t) {
if (indexArrayArray[t] != NULL) {
@@ -206,9 +219,12 @@ private:
/** For every three vertices, compute the face normal and store it three times.
Sliver triangles have a zero surface normal, which we will later take to
match *any* surface normal. */
- void computeFaceNormals(
- const Array<Vector3>& vertexArray,
- Array<Vector3>& faceNormalArray) {
+ void computeFaceNormals
+ (const Array<Vector3>& vertexArray,
+ Array<Vector3>& faceNormalArray) {
+# ifdef VERBOSE
+ debugPrintf("WeldHelper::computeFaceNormals\n");
+# endif
debugAssertM(vertexArray.size() % 3 == 0, "Input is not a triangle soup");
debugAssertM(faceNormalArray.size() == 0, "Output must start empty.");
@@ -231,17 +247,19 @@ private:
Computes @a smoothNormalArray, whose elements are those of normalArray averaged
with neighbors within the angular cutoff.
*/
- void smoothNormals(
- const Array<Vector3>& vertexArray,
- const Array<Vector3>& normalArray,
- Array<Vector3>& smoothNormalArray) {
-
+ void smoothNormals
+ (const Array<Point3>& vertexArray,
+ const Array<Vector3>& normalArray,
+ Array<Vector3>& smoothNormalArray) {
if (normalSmoothingAngle <= 0) {
smoothNormalArray = normalArray;
return;
}
-
+# ifdef VERBOSE
+ debugPrintf("WeldHelper::smoothNormals\n");
+# endif
+
// Create an area memory manager for fast deallocation
MemoryManager::Ref mm = AreaMemoryManager::create(iRound(sizeof(VN) * normalArray.size() * 1.5));
@@ -250,53 +268,110 @@ private:
debugAssert(vertexArray.size() == normalArray.size());
smoothNormalArray.resize(normalArray.size());
- // Compute a hash grid so that we can find neighbors quickly.
- PointHashGrid<VN> grid(vertexWeldRadius, mm);
- for (int v = 0; v < normalArray.size(); ++v) {
- grid.insert(VN(vertexArray[v], normalArray[v]));
- }
+ if (vertexWeldRadius == 0) {
+ // Look for vertices with the exactly identical normal only
+# ifdef VERBOSE
+ debugPrintf("Taking fast path\n");
+# endif
+
+ // Maximum expected faces that meet at a vertex
+ static const int k = 8;
+
+ // Maps vertices to the indices of normals at that vertex
+ Table<Point3, SmallArray<Vector3, k> > normalTable;
+ for (int v = 0; v < vertexArray.size(); ++v) {
+ bool ignore = false;
+ SmallArray<Vector3, k>& list = normalTable.getCreate(vertexArray[v], ignore);
+ list.append(normalArray[v]);
+ }
- // TODO: this step could be done on multiple threads
- for (int v = 0; v < normalArray.size(); ++v) {
- // Compute the sum of all nearby normals within the cutoff angle.
- // Search within the vertexWeldRadius, since those are the vertices
- // that will collapse to the same point.
- PointHashGrid<VN>::SphereIterator it =
- grid.beginSphereIntersection(Sphere(vertexArray[v], vertexWeldRadius));
+ for (int v = 0; v < vertexArray.size(); ++v) {
+ Vector3 sum;
- Vector3 sum;
+ const Vector3& original = normalArray[v];
- const Vector3& original = normalArray[v];
- while (it.hasMore()) {
- const Vector3& N = it->normal;
- const float cosAngle = N.dot(original);
+ const SmallArray<Vector3, k>& list = normalTable[vertexArray[v]];
- if (cosAngle > cosThresholdAngle) {
- // This normal is close enough to consider. Avoid underflow by scaling up
- sum += (N * 256.0f);
- }
- ++it;
- }
+ for (int i = 0; i < list.size(); ++i) {
+ const Vector3& N = list[i];
+ const float cosAngle = N.dot(original);
- const Vector3& average = sum.directionOrZero();
+ if (cosAngle > cosThresholdAngle) {
+ // This normal is close enough to consider. Avoid underflow by scaling up
+ sum += (N * 256.0f);
+ }
+ }
- const bool indeterminate = average.isZero();
- // Never "smooth" a normal so far that it points backwards
- const bool backFacing = original.dot(average) < 0;
+ const Vector3& average = sum.directionOrZero();
+
+ const bool indeterminate = average.isZero();
+ // Never "smooth" a normal so far that it points backwards
+ const bool backFacing = original.dot(average) < 0;
+
+ if (indeterminate || backFacing) {
+ // Revert to the face normal
+ smoothNormalArray[v] = original;
+ } else {
+ // Average available normals
+ smoothNormalArray[v] = average;
+ }
+ }
- if (indeterminate || backFacing) {
- // Revert to the face normal
- smoothNormalArray[v] = original;
- } else {
- // Average available normals
- smoothNormalArray[v] = average;
+ } else {
+ // Non-zero vertex normal welding
+# ifdef VERBOSE
+ debugPrintf("Taking slower weld path because vertexWeldRadius = %f\n",
+ vertexWeldRadius);
+# endif
+
+ // Compute a hash grid so that we can find neighbors quickly.
+ alwaysAssertM(vertexWeldRadius > 0, "Cannot smooth with zero vertex weld radius");
+ PointHashGrid<VN> grid(vertexWeldRadius, mm);
+ for (int v = 0; v < normalArray.size(); ++v) {
+ grid.insert(VN(vertexArray[v], normalArray[v]));
+ }
+
+ // OPT: this step could be done on multiple threads
+ for (int v = 0; v < normalArray.size(); ++v) {
+ // Compute the sum of all nearby normals within the cutoff angle.
+ // Search within the vertexWeldRadius, since those are the vertices
+ // that will collapse to the same point.
+ PointHashGrid<VN>::SphereIterator it =
+ grid.begin(Sphere(vertexArray[v], vertexWeldRadius));
+
+ Vector3 sum;
+
+ const Vector3& original = normalArray[v];
+ while (it.isValid()) {
+ const Vector3& N = it->normal;
+ const float cosAngle = N.dot(original);
+
+ if (cosAngle > cosThresholdAngle) {
+ // This normal is close enough to consider. Avoid underflow by scaling up
+ sum += (N * 256.0f);
+ }
+ ++it;
+ }
+
+ const Vector3& average = sum.directionOrZero();
+
+ const bool indeterminate = average.isZero();
+ // Never "smooth" a normal so far that it points backwards
+ const bool backFacing = original.dot(average) < 0;
+
+ if (indeterminate || backFacing) {
+ // Revert to the face normal
+ smoothNormalArray[v] = original;
+ } else {
+ // Average available normals
+ smoothNormalArray[v] = average;
+ }
}
}
}
public:
-
/**
Algorithm:
@@ -311,14 +386,17 @@ public:
4. Generate output indexArrayArray. While doing so, merge all vertices where
the distance between position, texCoord, and normal is within the thresholds.
*/
- void process(
- Array<Vector3>& vertexArray,
- Array<Vector2>& texCoordArray,
- Array<Vector3>& normalArray,
- Array<Array<int>*>& indexArrayArray,
- float normAngle,
- float texRadius,
- float normRadius) {
+ void process
+ ( Array<Vector3>& vertexArray,
+ Array<Vector2>& texCoordArray,
+ Array<Vector3>& normalArray,
+ Array<Array<int>*>& indexArrayArray,
+ float normAngle,
+ float texRadius,
+ float normRadius) {
+# ifdef VERBOSE
+ debugPrintf("WeldHelper::process\n");
+# endif
normalSmoothingAngle = normAngle;
normalWeldRadius2 = square(normRadius);
@@ -331,11 +409,17 @@ public:
"Input arrays are not parallel.");
}
+ // Create an area memory manager for fast deallocation
Array<Vector3> unrolledVertexArray;
Array<Vector3> unrolledFaceNormalArray;
Array<Vector3> unrolledSmoothNormalArray;
Array<Vector2> unrolledTexCoordArray;
+ unrolledVertexArray.reserve(vertexArray.size());
+ unrolledFaceNormalArray.reserve(vertexArray.size());
+ unrolledSmoothNormalArray.reserve(vertexArray.size());
+ unrolledTexCoordArray.reserve(vertexArray.size());
+
if (! hasTexCoords) {
// Generate all zero texture coordinates
texCoordArray.resize(vertexArray.size());
@@ -373,23 +457,40 @@ public:
}
WeldHelper(float vertRadius) :
- weldGrid(vertRadius, AreaMemoryManager::create()),
+ weldGrid(max(vertRadius, 0.1f), AreaMemoryManager::create()),
vertexWeldRadius(vertRadius) {
}
};
} // Internal
-void Welder::weld(
- Array<Vector3>& vertexArray,
- Array<Vector2>& texCoordArray,
- Array<Vector3>& normalArray,
- Array<Array<int>*>& indexArrayArray,
- const Welder::Settings& settings) {
- _internal::WeldHelper(settings.vertexWeldRadius).process(
- vertexArray, texCoordArray, normalArray, indexArrayArray,
- settings.normalSmoothingAngle, settings.textureWeldRadius, settings.normalWeldRadius);
+void Welder::Settings::serialize(class BinaryOutput& b) const {
+ b.writeFloat32(normalSmoothingAngle);
+ b.writeFloat32(vertexWeldRadius);
+ b.writeFloat32(textureWeldRadius);
+ b.writeFloat32(normalWeldRadius);
+}
+
+
+void Welder::Settings::deserialize(class BinaryInput& b) {
+ normalSmoothingAngle = b.readFloat32();
+ vertexWeldRadius = b.readFloat32();
+ textureWeldRadius = b.readFloat32();
+ normalWeldRadius = b.readFloat32();
+}
+
+
+void Welder::weld
+(Array<Vector3>& vertexArray,
+ Array<Vector2>& texCoordArray,
+ Array<Vector3>& normalArray,
+ Array<Array<int>*>& indexArrayArray,
+ const Welder::Settings& settings) {
+
+ _internal::WeldHelper(settings.vertexWeldRadius).process
+ (vertexArray, texCoordArray, normalArray, indexArrayArray,
+ settings.normalSmoothingAngle, settings.textureWeldRadius, settings.normalWeldRadius);
}
@@ -397,7 +498,7 @@ void Welder::weld(
Welder::Settings::Settings(const Any& any) {
*this = Settings();
any.verifyName("Welder::Settings");
- for (Any::AnyTable::Iterator it = any.table().begin(); it.hasMore(); ++it) {
+ for (Any::AnyTable::Iterator it = any.table().begin(); it.isValid(); ++it) {
const std::string& key = toLower(it->key);
if (key == "normalsmoothingangle") {
normalSmoothingAngle = it->value;
@@ -413,12 +514,13 @@ Welder::Settings::Settings(const Any& any) {
}
}
-Welder::Settings::operator Any() const {
+
+Any Welder::Settings::toAny() const {
Any a(Any::TABLE, "Welder::Settings");
- a.set("normalSmoothingAngle", normalSmoothingAngle);
- a.set("vertexWeldRadius", vertexWeldRadius);
- a.set("textureWeldRadius", textureWeldRadius);
- a.set("normalWeldRadius", normalWeldRadius);
+ a["normalSmoothingAngle"] = normalSmoothingAngle;
+ a["vertexWeldRadius"] = vertexWeldRadius;
+ a["textureWeldRadius"] = textureWeldRadius;
+ a["normalWeldRadius"] = normalWeldRadius;
return a;
}
diff --git a/dep/g3dlite/source/WinMain.cpp b/dep/g3dlite/source/WinMain.cpp
index 3cee71084e4..197530060f5 100644
--- a/dep/g3dlite/source/WinMain.cpp
+++ b/dep/g3dlite/source/WinMain.cpp
@@ -6,7 +6,7 @@
#include "G3D/platform.h"
-#ifdef G3D_WIN32
+#ifdef G3D_WINDOWS
#include <stdio.h>
#include <stdlib.h>
diff --git a/dep/g3dlite/source/XML.cpp b/dep/g3dlite/source/XML.cpp
index 51f1a549ba0..f347548b2db 100644
--- a/dep/g3dlite/source/XML.cpp
+++ b/dep/g3dlite/source/XML.cpp
@@ -7,7 +7,7 @@
\created 2010-02-11
\edited 2010-02-24
- Copyright 2000-2010, Morgan McGuire.
+ Copyright 2000-2012, Morgan McGuire.
All rights reserved.
*/
@@ -68,7 +68,7 @@ void XML::serialize(TextOutput& t) const {
t.writeSymbol(m_value);
} else {
t.printf("<%s", m_name.c_str());
- for (AttributeTable::Iterator it = m_attribute.begin(); it.hasMore(); ++it) {
+ for (AttributeTable::Iterator it = m_attribute.begin(); it.isValid(); ++it) {
t.printf(" %s=\"%s\"", it->key.c_str(), it->value.m_value.c_str());
}
t.printf(">");
diff --git a/dep/g3dlite/source/constants.cpp b/dep/g3dlite/source/constants.cpp
index 9ee3eb8736b..53a33faa8ec 100644
--- a/dep/g3dlite/source/constants.cpp
+++ b/dep/g3dlite/source/constants.cpp
@@ -11,6 +11,34 @@
namespace G3D {
+ const char* PrimitiveType::toString(int i, Value& v) {
+ static const char* str[] = {"POINTS", "LINES", "LINE_STRIP", "TRIANGLES", "TRIANGLE_FAN", "QUADS", "QUAD_STRIP", NULL};
+ static const Value val[] = {POINTS, LINES, LINE_STRIP, TRIANGLES, TRIANGLE_FAN, QUADS, QUAD_STRIP};
+ const char* s = str[i];
+ if (s) {
+ v = val[i];
+ }
+ return s;
+ }
+ const char* RefractionQuality::toString(int i, Value& v) {
+ static const char* str[] = {"NONE", "STATIC_ENV", "DYNAMIC_FLAT", "DYNAMIC_FLAT_MULTILAYER", "DYNAMIC_ENV", "BEST", NULL};
+ static const Value val[] = {NONE, STATIC_ENV, DYNAMIC_FLAT, DYNAMIC_FLAT_MULTILAYER, DYNAMIC_ENV, BEST};
+ const char* s = str[i];
+ if (s) {
+ v = val[i];
+ }
+ return s;
+ }
+
+ const char* MirrorQuality::toString(int i, Value& v) {
+ static const char* str[] = {"NONE", "STATIC_ENV", "DYNAMIC_PLANAR", "DYNAMIC_ENV", "BEST", NULL};
+ static const Value val[] = {NONE, STATIC_ENV, DYNAMIC_PLANAR, DYNAMIC_ENV, BEST};
+ const char* s = str[i];
+ if (s) {
+ v = val[i];
+ }
+ return s;
+ }
} // G3D
diff --git a/dep/g3dlite/source/debugAssert.cpp b/dep/g3dlite/source/debugAssert.cpp
index 41aad02c640..92ce2376490 100644
--- a/dep/g3dlite/source/debugAssert.cpp
+++ b/dep/g3dlite/source/debugAssert.cpp
@@ -11,7 +11,7 @@
#include "G3D/debugAssert.h"
#include "G3D/platform.h"
-#ifdef G3D_WIN32
+#ifdef G3D_WINDOWS
#include <tchar.h>
#endif
#include "G3D/format.h"
@@ -44,7 +44,7 @@ AssertionHook _failureHook = _handleErrorCheck_;
#endif
-#ifdef G3D_WIN32
+#ifdef G3D_WINDOWS
static void postToClipboard(const char *text) {
if (OpenClipboard(NULL)) {
HGLOBAL hMem = GlobalAlloc(GHND | GMEM_DDESHARE, strlen(text) + 1);
@@ -77,7 +77,7 @@ static void createErrorMessage(
std::string le = "";
const char* newline = "\n";
- #ifdef G3D_WIN32
+ #ifdef G3D_WINDOWS
newline = "\r\n";
// The last error value. (Which is preserved across the call).
@@ -106,9 +106,9 @@ static void createErrorMessage(
realLastErr = _T("Last error code does not exist.");
}
- if (lastErr != 0) {
- le = G3D::format("Last Error (0x%08X): %s\r\n\r\n", lastErr, (LPCSTR)realLastErr);
- }
+ if (lastErr != 0) {
+ le = G3D::format("Last Error (0x%08X): %s\r\n\r\n", lastErr, (LPCSTR)realLastErr);
+ }
// Get rid of the allocated memory from FormatMessage.
if (NULL != formatMsg) {
@@ -142,7 +142,7 @@ bool _handleDebugAssert_(
std::string dialogText = "";
createErrorMessage(expression, message, filename, lineNumber, dialogTitle, dialogText);
- #ifdef G3D_WIN32
+ #ifdef G3D_WINDOWS
DWORD lastErr = GetLastError();
postToClipboard(dialogText.c_str());
debugPrintf("\n%s\n", dialogText.c_str());
@@ -159,7 +159,7 @@ bool _handleDebugAssert_(
int result = G3D::prompt(dialogTitle.c_str(), dialogText.c_str(), (const char**)choices, 3, useGuiPrompt);
-# ifdef G3D_WIN32
+# ifdef G3D_WINDOWS
// Put the incoming last error back.
SetLastError(lastErr);
# endif
@@ -200,7 +200,7 @@ bool _handleErrorCheck_(
// Log the error
Log::common()->print(std::string("\n**************************\n\n") + dialogTitle + "\n" + dialogText);
- #ifdef G3D_WIN32
+ #ifdef G3D_WINDOWS
DWORD lastErr = GetLastError();
(void)lastErr;
postToClipboard(dialogText.c_str());
@@ -212,7 +212,7 @@ bool _handleErrorCheck_(
const std::string& m =
std::string("An internal error has occured in this program and it will now close. "
"The specific error is below. More information has been saved in \"") +
- Log::getCommonLogFilename() + "\".\n" + dialogText;
+ Log::getCommonLogFilename() + "\".\n\n" + dialogText;
int result = G3D::prompt("Error", m.c_str(), (const char**)choices, 1, useGuiPrompt);
(void)result;
@@ -221,7 +221,7 @@ bool _handleErrorCheck_(
}
-#ifdef G3D_WIN32
+#ifdef G3D_WINDOWS
static HCURSOR oldCursor;
static RECT oldCursorRect;
static POINT oldCursorPos;
@@ -229,7 +229,7 @@ static int oldShowCursorCount;
#endif
void _releaseInputGrab_() {
- #ifdef G3D_WIN32
+ #ifdef G3D_WINDOWS
GetCursorPos(&oldCursorPos);
@@ -275,7 +275,7 @@ void _releaseInputGrab_() {
void _restoreInputGrab_() {
- #ifdef G3D_WIN32
+ #ifdef G3D_WINDOWS
// Restore the old clipping region
ClipCursor(&oldCursorRect);
@@ -307,7 +307,7 @@ void setAssertionHook(AssertionHook hook) {
}
AssertionHook assertionHook() {
- return G3D::_internal::_debugHook;
+ return G3D::_internal::_debugHook;
}
void setFailureHook(AssertionHook hook) {
@@ -329,7 +329,7 @@ ConsolePrintHook consolePrintHook() {
std::string __cdecl debugPrint(const std::string& s) {
-# ifdef G3D_WIN32
+# ifdef G3D_WINDOWS
const int MAX_STRING_LEN = 1024;
// Windows can't handle really long strings sent to
diff --git a/dep/g3dlite/source/fileutils.cpp b/dep/g3dlite/source/fileutils.cpp
index 1867bf3338e..966cca7d4bf 100644
--- a/dep/g3dlite/source/fileutils.cpp
+++ b/dep/g3dlite/source/fileutils.cpp
@@ -25,7 +25,7 @@
#include "zip.h"
#endif
-#ifdef G3D_WIN32
+#ifdef G3D_WINDOWS
// Needed for _getcwd
#include <direct.h>
#include <io.h>
@@ -63,7 +63,7 @@ std::string resolveFilename(const std::string& filename) {
return filename;
} else {
- #ifdef G3D_WIN32
+ #ifdef G3D_WINDOWS
if ((filename.size() >= 2) && (filename[1] == ':')) {
// There is a drive spec on the front.
if ((filename.size() >= 3) && ((filename[2] == '\\') ||
@@ -86,36 +86,43 @@ std::string resolveFilename(const std::string& filename) {
char buffer[1024];
// Prepend the working directory.
- _getcwd(buffer, 1024);
+ (void)_getcwd(buffer, 1024);
return format("%s/%s", buffer, filename.c_str());
}
bool zipfileExists(const std::string& filename) {
- std::string outZipfile;
- std::string outInternalFile;
+ std::string outZipfile;
+ std::string outInternalFile;
return zipfileExists(filename, outZipfile, outInternalFile);
}
-std::string readWholeFile(
- const std::string& filename) {
- _internal::currentFilesUsed.insert(filename);
+std::string readWholeFile(const std::string& filename) {
std::string s;
debugAssert(filename != "");
- debugAssertM(FileSystem::exists(filename), filename + " not found");
+ if (! FileSystem::exists(filename)) {
+ throw (filename + " not found");
+ }
+ FileSystem::markFileUsed(filename);
+ std::string zipfile;
+
+ if (! FileSystem::inZipfile(filename, zipfile)) {
+ // Not in zipfile
+ if (! FileSystem::exists(filename)) {
+ throw FileNotFound(filename, std::string("File not found in readWholeFile: ") + filename);
+ }
- if (! FileSystem::inZipfile(filename)) {
int64 length = FileSystem::size(filename);
char* buffer = (char*)System::alignedMalloc(length + 1, 16);
debugAssert(buffer);
FILE* f = FileSystem::fopen(filename.c_str(), "rb");
debugAssert(f);
- int ret = fread(buffer, 1, length, f);
- debugAssert(ret == length);(void)ret;
+ int64 ret = fread(buffer, 1, length, f);
+ debugAssert(ret == length);(void)ret;
FileSystem::fclose(f);
buffer[length] = '\0';
@@ -123,60 +130,43 @@ std::string readWholeFile(
System::alignedFree(buffer);
- } else if (zipfileExists(filename)) {
-
- void* zipBuffer;
- size_t length;
- zipRead(filename, zipBuffer, length);
-
- char* buffer = (char*)System::alignedMalloc(length + 1, 16);
- System::memcpy(buffer,zipBuffer, length + 1);
- zipClose(zipBuffer);
-
- buffer[length] = '\0';
- s = std::string(buffer);
- System::alignedFree(buffer);
- }
-
- return s;
-}
+ } else {
+ // In zipfile
+ FileSystem::markFileUsed(zipfile);
-void zipRead(const std::string& file,
- void*& data,
- size_t& length) {
- std::string zip, desiredFile;
#if _HAVE_ZIP /* G3DFIX: Use ZIP-library only if defined */
- if (zipfileExists(file, zip, desiredFile)) {
- struct zip *z = zip_open( zip.c_str(), ZIP_CHECKCONS, NULL );
+ // Zipfiles require Unix-style slashes
+ std::string internalFile = FilePath::canonicalize(filename.substr(zipfile.length() + 1));
+ struct zip* z = zip_open(zipfile.c_str(), ZIP_CHECKCONS, NULL);
{
struct zip_stat info;
zip_stat_init( &info ); // TODO: Docs unclear if zip_stat_init is required.
- zip_stat( z, desiredFile.c_str(), ZIP_FL_NOCASE, &info );
- length = info.size;
- // sets machines up to use MMX, if they want
- data = System::alignedMalloc(length, 16);
- struct zip_file *zf = zip_fopen( z, desiredFile.c_str(), ZIP_FL_NOCASE );
- {
- int test = zip_fread( zf, data, length );
- debugAssertM((size_t)test == length,
- desiredFile + " was corrupt because it unzipped to the wrong size.");
- (void)test;
+ zip_stat(z, internalFile.c_str(), ZIP_FL_NOCASE, &info);
+
+ // Add NULL termination
+ char* buffer = reinterpret_cast<char*>(System::alignedMalloc(info.size + 1, 16));
+ buffer[info.size] = '\0';
+
+ struct zip_file* zf = zip_fopen( z, internalFile.c_str(), ZIP_FL_NOCASE );
+ if (zf == NULL) {
+ throw std::string("\"") + internalFile + "\" inside \"" + zipfile + "\" could not be opened.";
+ } else {
+ const int64 bytesRead = zip_fread( zf, buffer, (info.size));
+ debugAssertM((int64)bytesRead == (int64)info.size,
+ internalFile + " was corrupt because it unzipped to the wrong size.");
+ (void)bytesRead;
+ zip_fclose( zf );
}
- zip_fclose( zf );
+ // Copy the string
+ s = buffer;
+ System::alignedFree(buffer);
}
zip_close( z );
- } else {
- data = NULL;
- }
-#else
- data = NULL;
#endif
-}
-
+ }
-void zipClose(void* data) {
- System::alignedFree(data);
+ return s;
}
@@ -186,25 +176,25 @@ int64 fileLength(const std::string& filename) {
if (result == -1) {
#if _HAVE_ZIP /* G3DFIX: Use ZIP-library only if defined */
- std::string zip, contents;
- if(zipfileExists(filename, zip, contents)){
- int64 requiredMem;
+ std::string zip, contents;
+ if(zipfileExists(filename, zip, contents)){
+ int64 requiredMem;
struct zip *z = zip_open( zip.c_str(), ZIP_CHECKCONS, NULL );
debugAssertM(z != NULL, zip + ": zip open failed.");
- {
+ {
struct zip_stat info;
zip_stat_init( &info ); // TODO: Docs unclear if zip_stat_init is required.
int success = zip_stat( z, contents.c_str(), ZIP_FL_NOCASE, &info );
- (void)success;
+ (void)success;
debugAssertM(success == 0, zip + ": " + contents + ": zip stat failed.");
requiredMem = info.size;
- }
+ }
zip_close( z );
- return requiredMem;
- } else {
+ return requiredMem;
+ } else {
return -1;
- }
+ }
#else
return -1;
#endif
@@ -251,9 +241,9 @@ void writeWholeFile(
void createDirectory(
const std::string& dir) {
- if (dir == "") {
- return;
- }
+ if (dir == "") {
+ return;
+ }
std::string d;
@@ -292,11 +282,11 @@ void createDirectory(
if (! FileSystem::exists(p)) {
// Windows only requires one argument to mkdir,
// where as unix also requires the permissions.
-# ifndef G3D_WIN32
+# ifndef G3D_WINDOWS
mkdir(p.c_str(), 0777);
-# else
+# else
_mkdir(p.c_str());
-# endif
+# endif
}
}
}
@@ -308,39 +298,40 @@ void createDirectory(
/* Helper methods for zipfileExists()*/
// Given a string (the drive) and an array (the path), computes the directory
static void _zip_resolveDirectory(std::string& completeDir, const std::string& drive, const Array<std::string>& path, const int length){
- completeDir = drive;
- int tempLength;
- // if the given length is longer than the array, we correct it
- if(length > path.length()){
- tempLength = path.length();
- } else{
- tempLength = length;
- }
-
- for(int t = 0; t < tempLength; ++t){
- if(t > 0){
- completeDir += "/";
- }
- completeDir += path[t];
- }
+ completeDir = drive;
+ int tempLength;
+ // if the given length is longer than the array, we correct it
+ if(length > path.length()){
+ tempLength = path.length();
+ } else{
+ tempLength = length;
+ }
+
+ for(int t = 0; t < tempLength; ++t){
+ if(t > 0){
+ completeDir += "/";
+ }
+ completeDir += path[t];
+ }
}
-// assumes that zipDir references a .zip file
+/** assumes that zipDir references a .zip file */
static bool _zip_zipContains(const std::string& zipDir, const std::string& desiredFile){
struct zip *z = zip_open( zipDir.c_str(), ZIP_CHECKCONS, NULL );
- //the last parameter, an int, determines case sensitivity:
- //1 is sensitive, 2 is not, 0 is default
+ //the last parameter, an int, determines case sensitivity:
+ //1 is sensitive, 2 is not, 0 is default
int test = zip_name_locate( z, desiredFile.c_str(), ZIP_FL_NOCASE );
zip_close( z );
- if(test == -1){
- return false;
- }
- return true;
+ if(test == -1){
+ return false;
+ }
+ return true;
}
#endif
-// If no zipfile exists, outZipfile and outInternalFile are unchanged
+
+/** If no zipfile exists, outZipfile and outInternalFile are unchanged */
bool zipfileExists(const std::string& filename, std::string& outZipfile,
std::string& outInternalFile){
#if _HAVE_ZIP /* G3DFIX: Use ZIP-library only if defined */
@@ -355,7 +346,7 @@ bool zipfileExists(const std::string& filename, std::string& outZipfile,
infile = base + ext;
}
- // Remove "." from path
+ // Remove all standalone single dots (".") from path
for (int i = 0; i < path.length(); ++i) {
if (path[i] == ".") {
path.remove(i);
@@ -363,7 +354,7 @@ bool zipfileExists(const std::string& filename, std::string& outZipfile,
}
}
- // Remove ".." from path
+ // Remove non-leading ".." from path
for (int i = 1; i < path.length(); ++i) {
if ((path[i] == "..") && (i > 0) && (path[i - 1] != "..")) {
// Remove both i and i - 1
@@ -409,7 +400,7 @@ bool zipfileExists(const std::string& filename, std::string& outZipfile,
// not a valid directory structure ever,
// obviously no .zip was found within the path
return false;
-}
+}
///////////////////////////////////////////////////////////////////////////////
@@ -418,11 +409,14 @@ std::string generateFilenameBase(const std::string& prefix, const std::string& s
// Note "template" is a reserved word in C++
std::string templat = prefix + System::currentDateString() + "_";
- FileSystem::getFiles(templat + "*", exist);
+ FileSystem::getFiles(templat + "*", exist, true);
// Remove extensions
for (int i = 0; i < exist.size(); ++i) {
- exist[i] = filenameBase(exist[i]);
+ const std::string ext = FilePath::ext(exist[i]);
+ if (ext.length() > 0) {
+ exist[i] = exist[i].substr(0, exist[i].length() - ext.length() - 1);
+ }
}
int num = 0;
@@ -442,7 +436,7 @@ void copyFile(
const std::string& source,
const std::string& dest) {
- #ifdef G3D_WIN32
+ #ifdef G3D_WINDOWS
CopyFileA(source.c_str(), dest.c_str(), FALSE);
#else
// TODO: don't use BinaryInput and BinaryOutput
@@ -512,7 +506,7 @@ void parseFilename(
if (i != std::string::npos) {
// Make sure it is after the last slash!
- size_t j = iMax(f.rfind('/'), f.rfind('\\'));
+ size_t j = maxNotNPOS(f.rfind('/'), f.rfind('\\'));
if ((j == std::string::npos) || (i > j)) {
ext = f.substr(i + 1, f.size() - i - 1);
f = f.substr(0, i);
@@ -523,7 +517,7 @@ void parseFilename(
// Pull the basename off
{
// Find the last slash
- size_t i = iMax(f.rfind('/'), f.rfind('\\'));
+ size_t i = maxNotNPOS(f.rfind('/'), f.rfind('\\'));
if (i == std::string::npos) {
@@ -556,7 +550,7 @@ void parseFilename(
j = f.size();
}
- cur = iMin(i, j);
+ cur = min(i, j);
if (cur == std::string::npos) {
cur = f.size();
@@ -576,9 +570,9 @@ void parseFilename(
@param includePath If true, the names include paths
*/
static void getFileOrDirListNormal
-(const std::string& filespec,
- Array<std::string>& files,
- bool wantFiles,
+(const std::string& filespec,
+ Array<std::string>& files,
+ bool wantFiles,
bool includePath) {
bool test = wantFiles ? true : false;
@@ -614,11 +608,11 @@ static void getFileOrDirListNormal
path = path.substr(0, path.size() - 1);
}
-# ifdef G3D_WIN32
+# ifdef G3D_WINDOWS
{
struct _finddata_t fileinfo;
- long handle = _findfirst(filespec.c_str(), &fileinfo);
+ long handle = (long)_findfirst(filespec.c_str(), &fileinfo);
int result = handle;
while (result != -1) {
@@ -695,10 +689,10 @@ static void getFileOrDirListNormal
*/
static void _zip_addEntry(const std::string& path,
const std::string& prefix,
- const std::string& file,
- Set<std::string>& files,
- bool wantFiles,
- bool includePath) {
+ const std::string& file,
+ Set<std::string>& files,
+ bool wantFiles,
+ bool includePath) {
// Make certain we are within the desired parent folder (prefix)
if (beginsWith(file, prefix)) {
@@ -740,6 +734,7 @@ static void _zip_addEntry(const std::string& path,
}
#endif
+
static void getFileOrDirListZip(const std::string& path,
const std::string& prefix,
Array<std::string>& files,
@@ -766,13 +761,13 @@ static void getFileOrDirListZip(const std::string& path,
static void determineFileOrDirList(
- const std::string& filespec,
- Array<std::string>& files,
- bool wantFiles,
- bool includePath) {
+ const std::string& filespec,
+ Array<std::string>& files,
+ bool wantFiles,
+ bool includePath) {
- // if it is a .zip, prefix will specify the folder within
- // whose contents we want to see
+ // if it is a .zip, prefix will specify the folder within
+ // whose contents we want to see
std::string prefix = "";
std::string path = filenamePath(filespec);
@@ -800,39 +795,39 @@ static void determineFileOrDirList(
}
-void getFiles(const std::string& filespec,
- Array<std::string>& files,
- bool includePath) {
+void getFiles(const std::string& filespec,
+ Array<std::string>& files,
+ bool includePath) {
determineFileOrDirList(filespec, files, true, includePath);
}
void getDirs(
- const std::string& filespec,
- Array<std::string>& files,
- bool includePath) {
+ const std::string& filespec,
+ Array<std::string>& files,
+ bool includePath) {
- determineFileOrDirList(filespec, files, false, includePath);
+ determineFileOrDirList(filespec, files, false, includePath);
}
std::string filenameBaseExt(const std::string& filename) {
- int i = filename.rfind("/");
- int j = filename.rfind("\\");
+ size_t i = filename.rfind("/");
+ size_t j = filename.rfind("\\");
- if ((j > i) && (j >= 0)) {
+ if ((j > i) && (j != std::string::npos)) {
i = j;
}
-# ifdef G3D_WIN32
+# ifdef G3D_WINDOWS
j = filename.rfind(":");
- if ((i == -1) && (j >= 0)) {
+ if ((i == std::string::npos) && (j != std::string::npos)) {
i = j;
}
# endif
- if (i == -1) {
+ if (i == std::string::npos) {
return filename;
} else {
return filename.substr(i + 1, filename.length() - i);
@@ -852,8 +847,8 @@ std::string filenameBase(const std::string& s) {
std::string filenameExt(const std::string& filename) {
- int i = filename.rfind(".");
- if (i >= 0) {
+ size_t i = filename.rfind(".");
+ if (i != std::string::npos) {
return filename.substr(i + 1, filename.length() - i);
} else {
return "";
@@ -862,21 +857,21 @@ std::string filenameExt(const std::string& filename) {
std::string filenamePath(const std::string& filename) {
- int i = filename.rfind("/");
- int j = filename.rfind("\\");
+ size_t i = filename.rfind("/");
+ size_t j = filename.rfind("\\");
- if ((j > i) && (j >= 0)) {
+ if ((j > i) && (j != std::string::npos)) {
i = j;
}
-# ifdef G3D_WIN32
+# ifdef G3D_WINDOWS
j = filename.rfind(":");
- if ((i == -1) && (j >= 0)) {
+ if ((i == std::string::npos) && (j != std::string::npos)) {
i = j;
}
# endif
- if (i == -1) {
+ if (i == std::string::npos) {
return "";
} else {
return filename.substr(0, i+1);
@@ -886,23 +881,23 @@ std::string filenamePath(const std::string& filename) {
bool isZipfile(const std::string& filename) {
- FILE* f = fopen(filename.c_str(), "r");
- if (f == NULL) {
- return false;
- }
- uint8 header[4];
- fread(header, 4, 1, f);
-
- const uint8 zipHeader[4] = {0x50, 0x4b, 0x03, 0x04};
- for (int i = 0; i < 4; ++i) {
- if (header[i] != zipHeader[i]) {
- fclose(f);
- return false;
- }
- }
-
- fclose(f);
- return true;
+ FILE* f = fopen(filename.c_str(), "r");
+ if (f == NULL) {
+ return false;
+ }
+ uint8 header[4];
+ (void)fread(header, 4, 1, f);
+
+ const uint8 zipHeader[4] = {0x50, 0x4b, 0x03, 0x04};
+ for (int i = 0; i < 4; ++i) {
+ if (header[i] != zipHeader[i]) {
+ fclose(f);
+ return false;
+ }
+ }
+
+ fclose(f);
+ return true;
}
@@ -928,15 +923,8 @@ bool fileIsNewer(const std::string& src, const std::string& dst) {
return sexists && ((! dexists) || (sts.st_mtime > dts.st_mtime));
}
-
-Array<std::string> filesUsed() {
- Array<std::string> f;
- _internal::currentFilesUsed.getMembers(f);
- return f;
-}
-
}
-#ifndef G3D_WIN32
+#ifndef G3D_WINDOWS
#undef _stat
#endif
diff --git a/dep/g3dlite/source/format.cpp b/dep/g3dlite/source/format.cpp
index d9d1b516393..b77b30c73bd 100644
--- a/dep/g3dlite/source/format.cpp
+++ b/dep/g3dlite/source/format.cpp
@@ -43,7 +43,7 @@ std::string vformat(const char *fmt, va_list argPtr) {
// allocate it on the stack because this saves
// the malloc/free time.
const int bufSize = 161;
- char stackBuffer[bufSize];
+ char stackBuffer[bufSize];
// MSVC does not support va_copy
int actualSize = _vscprintf(fmt, argPtr) + 1;
@@ -83,12 +83,12 @@ std::string vformat(const char *fmt, va_list argPtr) {
// allocate it on the stack because this saves
// the malloc/free time.
const int bufSize = 161;
- char stackBuffer[bufSize];
+ char stackBuffer[bufSize];
- // MSVC6 doesn't support va_copy, however it also seems to compile
- // correctly if we just pass our argument list along. Note that
- // this whole code block is only compiled if we're on MSVC6 anyway
- int actualWritten = _vsnprintf(stackBuffer, bufSize, fmt, argPtr);
+ // MSVC6 doesn't support va_copy, however it also seems to compile
+ // correctly if we just pass our argument list along. Note that
+ // this whole code block is only compiled if we're on MSVC6 anyway
+ int actualWritten = _vsnprintf(stackBuffer, bufSize, fmt, argPtr);
// Not a big enough buffer, bufSize characters written
if (actualWritten == -1) {
diff --git a/dep/g3dlite/source/g3dfnmatch.cpp b/dep/g3dlite/source/g3dfnmatch.cpp
index 2d24c4126e6..1902d71fc92 100644
--- a/dep/g3dlite/source/g3dfnmatch.cpp
+++ b/dep/g3dlite/source/g3dfnmatch.cpp
@@ -1,10 +1,10 @@
/* $Id: g3dfnmatch.cpp,v 1.3 2010/03/15 05:01:23 morgan3d Exp $ */
-/* $OpenBSD: fnmatch.c,v 1.7 2000/03/23 19:13:51 millert Exp $ */
+/* $OpenBSD: fnmatch.c,v 1.7 2000/03/23 19:13:51 millert Exp $ */
/*
* Copyright (c) 1989, 1993, 1994
- * The Regents of the University of California. All rights reserved.
+ * The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Guido van Rossum.
@@ -19,8 +19,8 @@
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
@@ -39,7 +39,7 @@
*/
#include "G3D/g3dfnmatch.h"
-#ifdef G3D_WIN32
+#ifdef G3D_WINDOWS
#include <ctype.h>
#include <string.h>
@@ -47,166 +47,166 @@
namespace G3D {
-#define EOS '\0'
+#define EOS '\0'
-#define RANGE_MATCH 1
-#define RANGE_NOMATCH 0
-#define RANGE_ERROR (-1)
+#define RANGE_MATCH 1
+#define RANGE_NOMATCH 0
+#define RANGE_ERROR (-1)
static int rangematch(const char *, char, int, char **);
int
g3dfnmatch(const char *pattern, const char *string, int flags)
{
- const char *stringstart;
- char *newp;
- char c, test;
-
- for (stringstart = string;;)
- switch (c = *pattern++) {
- case EOS:
- if ((flags & FNM_LEADING_DIR) && *string == '/')
- return (0);
- return (*string == EOS ? 0 : FNM_NOMATCH);
- case '?':
- if (*string == EOS)
- return (FNM_NOMATCH);
- if (*string == '/' && (flags & FNM_PATHNAME))
- return (FNM_NOMATCH);
- if (*string == '.' && (flags & FNM_PERIOD) &&
- (string == stringstart ||
- ((flags & FNM_PATHNAME) && *(string - 1) == '/')))
- return (FNM_NOMATCH);
- ++string;
- break;
- case '*':
- c = *pattern;
- /* Collapse multiple stars. */
- while (c == '*')
- c = *++pattern;
-
- if (*string == '.' && (flags & FNM_PERIOD) &&
- (string == stringstart ||
- ((flags & FNM_PATHNAME) && *(string - 1) == '/')))
- return (FNM_NOMATCH);
-
- /* Optimize for pattern with * at end or before /. */
- if (c == EOS) {
- if (flags & FNM_PATHNAME)
- return ((flags & FNM_LEADING_DIR) ||
- strchr(string, '/') == NULL ?
- 0 : FNM_NOMATCH);
- else
- return (0);
- } else if (c == '/' && (flags & FNM_PATHNAME)) {
- if ((string = strchr(string, '/')) == NULL)
- return (FNM_NOMATCH);
- break;
- }
-
- /* General case, use recursion. */
- while ((test = *string) != EOS) {
- if (!g3dfnmatch(pattern, string, flags & ~FNM_PERIOD))
- return (0);
- if (test == '/' && (flags & FNM_PATHNAME))
- break;
- ++string;
- }
- return (FNM_NOMATCH);
- case '[':
- if (*string == EOS)
- return (FNM_NOMATCH);
- if (*string == '/' && (flags & FNM_PATHNAME))
- return (FNM_NOMATCH);
- if (*string == '.' && (flags & FNM_PERIOD) &&
- (string == stringstart ||
- ((flags & FNM_PATHNAME) && *(string - 1) == '/')))
- return (FNM_NOMATCH);
-
- switch (rangematch(pattern, *string, flags, &newp)) {
- case RANGE_ERROR:
- /* not a good range, treat as normal text */
- goto normal;
- case RANGE_MATCH:
- pattern = newp;
- break;
- case RANGE_NOMATCH:
- return (FNM_NOMATCH);
- }
- ++string;
- break;
- case '\\':
- if (!(flags & FNM_NOESCAPE)) {
- if ((c = *pattern++) == EOS) {
- c = '\\';
- --pattern;
- }
- }
- /* FALLTHROUGH */
- default:
- normal:
- if (c != *string && !((flags & FNM_CASEFOLD) &&
- (tolower((unsigned char)c) ==
- tolower((unsigned char)*string))))
- return (FNM_NOMATCH);
- ++string;
- break;
- }
- /* NOTREACHED */
+ const char *stringstart;
+ char *newp;
+ char c, test;
+
+ for (stringstart = string;;)
+ switch (c = *pattern++) {
+ case EOS:
+ if ((flags & FNM_LEADING_DIR) && *string == '/')
+ return (0);
+ return (*string == EOS ? 0 : FNM_NOMATCH);
+ case '?':
+ if (*string == EOS)
+ return (FNM_NOMATCH);
+ if (*string == '/' && (flags & FNM_PATHNAME))
+ return (FNM_NOMATCH);
+ if (*string == '.' && (flags & FNM_PERIOD) &&
+ (string == stringstart ||
+ ((flags & FNM_PATHNAME) && *(string - 1) == '/')))
+ return (FNM_NOMATCH);
+ ++string;
+ break;
+ case '*':
+ c = *pattern;
+ /* Collapse multiple stars. */
+ while (c == '*')
+ c = *++pattern;
+
+ if (*string == '.' && (flags & FNM_PERIOD) &&
+ (string == stringstart ||
+ ((flags & FNM_PATHNAME) && *(string - 1) == '/')))
+ return (FNM_NOMATCH);
+
+ /* Optimize for pattern with * at end or before /. */
+ if (c == EOS) {
+ if (flags & FNM_PATHNAME)
+ return ((flags & FNM_LEADING_DIR) ||
+ strchr(string, '/') == NULL ?
+ 0 : FNM_NOMATCH);
+ else
+ return (0);
+ } else if (c == '/' && (flags & FNM_PATHNAME)) {
+ if ((string = strchr(string, '/')) == NULL)
+ return (FNM_NOMATCH);
+ break;
+ }
+
+ /* General case, use recursion. */
+ while ((test = *string) != EOS) {
+ if (!g3dfnmatch(pattern, string, flags & ~FNM_PERIOD))
+ return (0);
+ if (test == '/' && (flags & FNM_PATHNAME))
+ break;
+ ++string;
+ }
+ return (FNM_NOMATCH);
+ case '[':
+ if (*string == EOS)
+ return (FNM_NOMATCH);
+ if (*string == '/' && (flags & FNM_PATHNAME))
+ return (FNM_NOMATCH);
+ if (*string == '.' && (flags & FNM_PERIOD) &&
+ (string == stringstart ||
+ ((flags & FNM_PATHNAME) && *(string - 1) == '/')))
+ return (FNM_NOMATCH);
+
+ switch (rangematch(pattern, *string, flags, &newp)) {
+ case RANGE_ERROR:
+ /* not a good range, treat as normal text */
+ goto normal;
+ case RANGE_MATCH:
+ pattern = newp;
+ break;
+ case RANGE_NOMATCH:
+ return (FNM_NOMATCH);
+ }
+ ++string;
+ break;
+ case '\\':
+ if (!(flags & FNM_NOESCAPE)) {
+ if ((c = *pattern++) == EOS) {
+ c = '\\';
+ --pattern;
+ }
+ }
+ /* FALLTHROUGH */
+ default:
+ normal:
+ if (c != *string && !((flags & FNM_CASEFOLD) &&
+ (tolower((unsigned char)c) ==
+ tolower((unsigned char)*string))))
+ return (FNM_NOMATCH);
+ ++string;
+ break;
+ }
+ /* NOTREACHED */
}
static int
rangematch(const char *pattern, char test, int flags, char **newp)
{
- int negate, ok;
- char c, c2;
-
- /*
- * A bracket expression starting with an unquoted circumflex
- * character produces unspecified results (IEEE 1003.2-1992,
- * 3.13.2). This implementation treats it like '!', for
- * consistency with the regular expression syntax.
- * J.T. Conklin (conklin@ngai.kaleida.com)
- */
- if ((negate = (*pattern == '!' || *pattern == '^')))
- ++pattern;
-
- if (flags & FNM_CASEFOLD)
- test = tolower((unsigned char)test);
-
- /*
- * A right bracket shall lose its special meaning and represent
- * itself in a bracket expression if it occurs first in the list.
- * -- POSIX.2 2.8.3.2
- */
- ok = 0;
- c = *pattern++;
- do {
- if (c == '\\' && !(flags & FNM_NOESCAPE))
- c = *pattern++;
- if (c == EOS)
- return (RANGE_ERROR);
- if (c == '/' && (flags & FNM_PATHNAME))
- return (RANGE_NOMATCH);
- if ((flags & FNM_CASEFOLD))
- c = tolower((unsigned char)c);
- if (*pattern == '-'
- && (c2 = *(pattern+1)) != EOS && c2 != ']') {
- pattern += 2;
- if (c2 == '\\' && !(flags & FNM_NOESCAPE))
- c2 = *pattern++;
- if (c2 == EOS)
- return (RANGE_ERROR);
- if (flags & FNM_CASEFOLD)
- c2 = tolower((unsigned char)c2);
- if (c <= test && test <= c2)
- ok = 1;
- } else if (c == test)
- ok = 1;
- } while ((c = *pattern++) != ']');
-
- *newp = (char *)pattern;
- return (ok == negate ? RANGE_NOMATCH : RANGE_MATCH);
+ int negate, ok;
+ char c, c2;
+
+ /*
+ * A bracket expression starting with an unquoted circumflex
+ * character produces unspecified results (IEEE 1003.2-1992,
+ * 3.13.2). This implementation treats it like '!', for
+ * consistency with the regular expression syntax.
+ * J.T. Conklin (conklin@ngai.kaleida.com)
+ */
+ if ((negate = (*pattern == '!' || *pattern == '^')))
+ ++pattern;
+
+ if (flags & FNM_CASEFOLD)
+ test = tolower((unsigned char)test);
+
+ /*
+ * A right bracket shall lose its special meaning and represent
+ * itself in a bracket expression if it occurs first in the list.
+ * -- POSIX.2 2.8.3.2
+ */
+ ok = 0;
+ c = *pattern++;
+ do {
+ if (c == '\\' && !(flags & FNM_NOESCAPE))
+ c = *pattern++;
+ if (c == EOS)
+ return (RANGE_ERROR);
+ if (c == '/' && (flags & FNM_PATHNAME))
+ return (RANGE_NOMATCH);
+ if ((flags & FNM_CASEFOLD))
+ c = tolower((unsigned char)c);
+ if (*pattern == '-'
+ && (c2 = *(pattern+1)) != EOS && c2 != ']') {
+ pattern += 2;
+ if (c2 == '\\' && !(flags & FNM_NOESCAPE))
+ c2 = *pattern++;
+ if (c2 == EOS)
+ return (RANGE_ERROR);
+ if (flags & FNM_CASEFOLD)
+ c2 = tolower((unsigned char)c2);
+ if (c <= test && test <= c2)
+ ok = 1;
+ } else if (c == test)
+ ok = 1;
+ } while ((c = *pattern++) != ']');
+
+ *newp = (char *)pattern;
+ return (ok == negate ? RANGE_NOMATCH : RANGE_MATCH);
}
}
diff --git a/dep/g3dlite/source/g3dmath.cpp b/dep/g3dlite/source/g3dmath.cpp
index e846f8c6080..a6ce20d872f 100644
--- a/dep/g3dlite/source/g3dmath.cpp
+++ b/dep/g3dlite/source/g3dmath.cpp
@@ -10,6 +10,7 @@
#include "G3D/g3dmath.h"
#include <cstdlib>
#include <cstring>
+#include "G3D/BIN.h"
namespace G3D {
@@ -40,14 +41,27 @@ double inf() {
return std::numeric_limits<double>::infinity();
}
+// --fast-math breaks other methods of testing for NaN on g++ 4.x,
+// including isnan(x) and !(x == x)
+
bool isNaN(float x) {
- static const float n = fnan();
- return memcmp(&x, &n, sizeof(float)) == 0;
+ // Wipe out the sign bit
+ const uint32 y = *(uint32*)(&x) & BIN32(01111111,11111111,11111111,11111111);
+
+ // If the remaining number has all of the exponent bits set and atleast one
+ // fraction bit set, then it is NaN
+ return (y > 0x7F800000);
}
bool isNaN(double x) {
- static const double n = nan();
- return memcmp(&x, &n, sizeof(double)) == 0;
+ // Wipe out the sign bit
+ const uint64 y = *(uint64*)(&x) &
+ ((uint64(BIN32(01111111,11111111,11111111,11111111)) << 32) +
+ 0xFFFFFFFF);
+
+ // If the remaining number has all of the exponent bits set and atleast one
+ // fraction bit set, then it is NaN
+ return (y > (uint64(BIN32(01111111,11110000,00000000,00000000)) << 32));
}
@@ -75,7 +89,7 @@ int highestBit(uint32 x) {
// Binary search.
int base = 0;
- if (x & 0xffff0000) {
+ if (x & 0xffff0000) {
base = 16;
x >>= 16;
}
diff --git a/dep/g3dlite/source/license.cpp b/dep/g3dlite/source/license.cpp
index 5049184cf9b..e2b9f2583d5 100644
--- a/dep/g3dlite/source/license.cpp
+++ b/dep/g3dlite/source/license.cpp
@@ -24,7 +24,7 @@ std::string license() {
"%s"
"This program uses the G3D Library (http://g3d.sf.net), which\n"
"is licensed under the \"Modified BSD\" Open Source license. The G3D library\n"
-"source code is Copyright © 2000-2010, Morgan McGuire, All rights reserved.\n"
+"source code is Copyright © 2000-2011, Morgan McGuire, All rights reserved.\n"
"This program uses The OpenGL Extension Wrangler Library, which \n"
"is licensed under the \"Modified BSD\" Open Source license. \n"
"The OpenGL Extension Wrangler Library source code is\n"
@@ -59,7 +59,7 @@ std::string license() {
"\n\n"
"G3D VERSION %d\n",
-#ifdef G3D_WIN32
+#ifdef G3D_WINDOWS
"" // Win32 doesn't use SDL
#else
"This software uses the Simple DirectMedia Layer library (\"SDL\",\n"
diff --git a/dep/g3dlite/source/prompt.cpp b/dep/g3dlite/source/prompt.cpp
index d2c6f098033..ee520d85db7 100644
--- a/dep/g3dlite/source/prompt.cpp
+++ b/dep/g3dlite/source/prompt.cpp
@@ -14,7 +14,7 @@
#include <stdio.h>
-#ifdef G3D_WIN32
+#ifdef G3D_WINDOWS
# include <sstream>
# include <conio.h>
#else
@@ -29,7 +29,7 @@
#endif
*/
-# include <Carbon/Carbon.h>
+# include "G3D/prompt_cocoa.h"
/*
#ifdef G3D_64BIT
@@ -43,7 +43,7 @@
namespace G3D {
#if 0 /* G3DFIX: exclude GUI prompt code */
-#ifdef G3D_WIN32
+#ifdef G3D_WINDOWS
namespace _internal {
/**
@@ -360,8 +360,8 @@ static int guiPrompt(
const char** choice,
int numChoices) {
- int width = 280;
- int height = 128;
+ int width = 340;
+ int height = 220;
const int buttonSpacing = 2;
const int buttonWidth =
@@ -381,7 +381,7 @@ static int guiPrompt(
2, 2, width - 4, height - buttonHeight - 7, IDC_MESSAGE);
int i;
- for (i = 0; i < numChoices; i++) {
+ for (i = 0; i < numChoices; ++i) {
int x = buttonSpacing + i * (buttonWidth + buttonSpacing);
int y = height - buttonHeight - buttonSpacing;
@@ -429,7 +429,7 @@ static int guiPrompt(
params.title = windowTitle;
HMODULE module = GetModuleHandle(0);
- int ret = DialogBoxIndirectParam(module, dialogTemplate, NULL, (DLGPROC) PromptDlgProc, (DWORD)&params);
+ int ret = (int)DialogBoxIndirectParam(module, dialogTemplate, NULL, (DLGPROC) PromptDlgProc, (DWORD)&params);
free(newStr);
@@ -500,7 +500,7 @@ static int textPrompt(
while ((c < 0) || (c >= numChoices)) {
printf("\n");
- for (int i = 0; i < numChoices; i++) {
+ for (int i = 0; i < numChoices; ++i) {
if (numChoices <= 3) {
printf(" (%d) %s ", i, choice[i]);
} else {
@@ -536,167 +536,20 @@ static int textPrompt(
}
#if 0 /* G3DFIX: exclude GUI prompt code */
-
#ifdef G3D_OSX
-// See http://developer.apple.com/documentation/Carbon/Reference/Carbon_Event_Manager_Ref/index.html
-
-#define CARBON_COMMANDID_START 128
-#define CARBON_BUTTON_SPACING 12
-#define CARBON_BUTTON_HEIGHT 20
-#define CARBON_BUTTON_MINWIDTH 69
-#define CARBON_WINDOW_PADDING 20
-
-struct CallbackData {
- WindowRef refWindow;
-
- /** Index of this particular button */
- int myIndex;
-
- /** Buttons store their index into here when pressed. */
- int* whichButton;
-};
-
-/**
- Assumes that userData is a pointer to a carbon_evt_data_t.
-
- */
-static pascal OSStatus DoCommandEvent(EventHandlerCallRef handlerRef, EventRef event, void* userData) {
- // See http://developer.apple.com/documentation/Carbon/Conceptual/HandlingWindowsControls/index.html
-
- CallbackData& callbackData = *(CallbackData*)userData;
-
-# pragma unused(handlerRef)
-
- callbackData.whichButton[0] = callbackData.myIndex;
-
- // If we get here we can close the window
- ::QuitAppModalLoopForWindow(callbackData.refWindow);
-
- // Return noErr to indicate that we handled the event
- return noErr;
-}
-
static int guiPrompt
(const char* windowTitle,
const char* prompt,
const char** choice,
int numChoices) {
-
- WindowRef window;
-
- int iNumButtonRows = 0;
- int iButtonWidth = -1;
- OSStatus err = noErr;
-
- // Determine number of rows of buttons
- while (iButtonWidth < CARBON_BUTTON_MINWIDTH) {
- ++iNumButtonRows;
- iButtonWidth =
- (550 - (CARBON_WINDOW_PADDING*2 +
- (CARBON_BUTTON_SPACING*numChoices))) /
- (numChoices/iNumButtonRows);
- }
-
- // Window Variables
- Rect rectWin = {0, 0, 200 + ((iNumButtonRows-1) * (CARBON_BUTTON_HEIGHT+CARBON_BUTTON_SPACING)), 550}; // top, left, bottom, right
- CFStringRef szWindowTitle = CFStringCreateWithCString(kCFAllocatorDefault, windowTitle, kCFStringEncodingUTF8);
-
- window = NULL;
-
- err = CreateNewWindow(kMovableAlertWindowClass, kWindowStandardHandlerAttribute|kWindowCompositingAttribute, &rectWin, &window);
- err = SetWindowTitleWithCFString(window, szWindowTitle);
- err = SetThemeWindowBackground(window, kThemeBrushAlertBackgroundActive, false);
- assert(err == noErr);
-
- // Event Handler Variables
- EventTypeSpec buttonSpec[] = {{ kEventClassControl, kEventControlHit }, { kEventClassCommand, kEventCommandProcess }};
- EventHandlerUPP buttonHandler = NewEventHandlerUPP(DoCommandEvent);
-
- // Static Text Variables
- Rect rectStatic = {20, 20, 152, 530};
- CFStringRef szStaticText = CFStringCreateWithCString(kCFAllocatorDefault, prompt, kCFStringEncodingUTF8);
- ControlRef refStaticText = NULL;
- err = CreateStaticTextControl(window, &rectStatic, szStaticText, NULL, &refStaticText);
-
- // Button Variables
- Rect bounds[numChoices];
- CFStringRef caption[numChoices];
- ControlRef button[numChoices];
-
- int whichButton=-1;
- CallbackData callbackData[numChoices];
-
- // Create the Buttons and assign event handlers
- for (int i = 0; i < numChoices; ++i) {
- bounds[i].top = 160 + ((CARBON_BUTTON_HEIGHT+CARBON_BUTTON_SPACING)*(i%iNumButtonRows));
- bounds[i].right = 530 - ((iButtonWidth+CARBON_BUTTON_SPACING)*(i/iNumButtonRows));
- bounds[i].left = bounds[i].right - iButtonWidth;
- bounds[i].bottom = bounds[i].top + CARBON_BUTTON_HEIGHT;
-
- // Convert the button captions to Apple strings
- caption[i] = CFStringCreateWithCString(kCFAllocatorDefault, choice[i], kCFStringEncodingUTF8);
-
- err = CreatePushButtonControl(window, &bounds[i], caption[i], &button[i]);
- assert(err == noErr);
-
- err = SetControlCommandID(button[i], CARBON_COMMANDID_START + i);
- assert(err == noErr);
-
- callbackData[i].refWindow = window;
- callbackData[i].myIndex = i;
- callbackData[i].whichButton = &whichButton;
-
- err = InstallControlEventHandler(button[i], buttonHandler,
- GetEventTypeCount(buttonSpec), buttonSpec,
- &callbackData[i], NULL);
- assert(err == noErr);
- }
-
- // Show Dialog
- err = RepositionWindow(window, NULL, kWindowCenterOnMainScreen);
- ShowWindow(window);
- BringToFront(window);
- err = ActivateWindow(window, true);
-
- // Hack to get our window/process to the front...
- ProcessSerialNumber psn = { 0, kCurrentProcess};
- TransformProcessType(&psn, kProcessTransformToForegroundApplication);
- SetFrontProcess (&psn);
-
- // Run in Modal State
- err = RunAppModalLoopForWindow(window);
-
- // Dispose of Button Related Data
- for (int i = 0; i < numChoices; ++i) {
- // Dispose of controls
- DisposeControl(button[i]);
-
- // Release CFStrings
- CFRelease(caption[i]);
- }
-
- // Dispose of Other Controls
- DisposeControl(refStaticText);
-
- // Dispose of Event Handlers
- DisposeEventHandlerUPP(buttonHandler);
-
- // Dispose of Window
- DisposeWindow(window);
-
- // Release CFStrings
- CFRelease(szWindowTitle);
- CFRelease(szStaticText);
-
- // Return Selection
- return whichButton;
+
+ return prompt_cocoa(windowTitle, prompt, choice, numChoices);
}
#endif
#endif /* G3DFIX: exclude GUI prompt code */
-
int prompt(
const char* windowTitle,
const char* prompt,
@@ -704,7 +557,7 @@ int prompt(
int numChoices,
bool useGui) {
#if 0 /* G3DFIX: exclude GUI prompt code */
- #ifdef G3D_WIN32
+ #ifdef G3D_WINDOWS
if (useGui) {
// Build the message box
return guiPrompt(windowTitle, prompt, choice, numChoices);
@@ -713,8 +566,10 @@ int prompt(
#ifdef G3D_OSX
if (useGui){
- //Will default to text prompt if numChoices > 4
- return guiPrompt(windowTitle, prompt, choice, numChoices);
+ //Will default to text prompt if numChoices > 4
+ int result = guiPrompt(windowTitle, prompt, choice, numChoices);
+ fprintf(stderr, "%d\n", result);
+ return result;
}
#endif
#endif /* G3DFIX: exclude GUI prompt code */
@@ -730,9 +585,9 @@ void msgBox(
prompt(title.c_str(), message.c_str(), choice, 1, true);
}
-#ifndef G3D_WIN32
+#ifndef G3D_WINDOWS
#undef _getch
#endif
-};// namespace
+}// namespace
diff --git a/dep/g3dlite/source/stringutils.cpp b/dep/g3dlite/source/stringutils.cpp
index c3876ebb6a4..ff71851700c 100644
--- a/dep/g3dlite/source/stringutils.cpp
+++ b/dep/g3dlite/source/stringutils.cpp
@@ -1,10 +1,10 @@
/**
- @file stringutils.cpp
+ \file stringutils.cpp
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
+ \maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @created 2000-09-09
- @edited 2008-01-10
+ \created 2000-09-09
+ \edited 2011-08-20
*/
#include "G3D/platform.h"
@@ -12,6 +12,14 @@
#include "G3D/BinaryInput.h"
#include <algorithm>
+#ifdef G3D_WINDOWS
+extern "C" {
+ // Define functions for ffmpeg since we don't link in gcc's c library
+ extern int strncasecmp(const char *string1, const char *string2, size_t count) { return _strnicmp(string1, string2, count); }
+ extern int strcasecmp(const char *string1, const char *string2) { return _stricmp(string1, string2); }
+}
+#endif
+
namespace G3D {
#ifdef _MSC_VER
@@ -19,7 +27,7 @@ namespace G3D {
# pragma warning (push)
# pragma warning (disable : 4530)
#endif
-#ifdef G3D_WIN32
+#ifdef G3D_WINDOWS
const char* NEWLINE = "\r\n";
#else
const char* NEWLINE = "\n";
@@ -56,7 +64,7 @@ void parseCommaSeparated(const std::string s, Array<std::string>& array, bool st
if (stripQuotes) {
for (int i = 0; i < array.length(); ++i) {
std::string& t = array[i];
- int L = t.length();
+ size_t L = t.length();
if ((L > 1) && (t[0] == quote) && (t[L - 1] == quote)) {
if ((L > 6) && (t[1] == quote) && (t[2] == quote) && (t[L - 3] == quote) && (t[L - 2] == quote)) {
// Triple-quote
@@ -86,15 +94,44 @@ bool beginsWith(
}
}
+std::string replace(const std::string& s, const std::string& pattern, const std::string& replacement) {
+ if (pattern.length() == 0) {
+ return s;
+ }
+ std::string temp = "";
+ size_t lastindex = 0;
+ size_t nextindex = 0;
+ do {
+ nextindex = s.find(pattern, lastindex);
+ if (nextindex == std::string::npos) {
+ break;
+ }
+ temp += s.substr(lastindex, nextindex - lastindex) + replacement;
+ lastindex = nextindex + pattern.length();
+ } while (lastindex + pattern.length() <= s.length());
+ return temp + (lastindex < s.length() ? s.substr(lastindex) : "");
+}
+
+bool isValidIdentifier(const std::string& s) {
+ if (s.length() > 0 && (isLetter(s[0]) || s[0] == '_')) {
+ for (size_t i = 1; i < s.length() ; ++i) {
+ if (!( isLetter(s[i]) || (s[i] == '_') || isDigit(s[i]) )) {
+ return false;
+ }
+ }
+ return true;
+ }
+ return false;
+}
bool endsWith(
const std::string& test,
const std::string& pattern) {
if (test.size() >= pattern.size()) {
- int te = test.size() - 1;
- int pe = pattern.size() - 1;
- for (int i = pattern.size() - 1; i >= 0; --i) {
+ size_t te = test.size() - 1;
+ size_t pe = pattern.size() - 1;
+ for (int i = (int)pattern.size() - 1; i >= 0; --i) {
if (pattern[pe - i] != test[te - i]) {
return false;
}
@@ -151,7 +188,7 @@ std::string wordWrap(
if (c < input.size()) {
// Collapse multiple spaces.
while ((input[c] == ' ') && (c < input.size())) {
- c++;
+ ++c;
}
}
}
@@ -248,9 +285,11 @@ std::string stringJoin(
}
-std::string trimWhitespace(
- const std::string& s) {
+std::string trimWhitespace(const std::string& s) {
+ if (s.length() == 0) {
+ return s;
+ }
size_t left = 0;
// Trim from left
@@ -258,15 +297,16 @@ std::string trimWhitespace(
++left;
}
- int right = s.length() - 1;
+ size_t right = s.length() - 1;
// Trim from right
- while ((right > (int)left) && iswspace(s[right])) {
+ while ((right > left) && iswspace(s[right])) {
--right;
}
return s.substr(left, right - left + 1);
}
+
}; // namespace
#undef NEWLINE
diff --git a/dep/g3dlite/source/uint128.cpp b/dep/g3dlite/source/uint128.cpp
index 1f596fc3e51..2fd58a332cd 100644
--- a/dep/g3dlite/source/uint128.cpp
+++ b/dep/g3dlite/source/uint128.cpp
@@ -17,8 +17,8 @@ static void addAndCarry(const uint64& _a, const uint64& _b, uint64& carry, uint6
// Break each number into 4 32-bit chunks. Since we are using uints, right-shifting will fill with zeros.
// This eliminates the need to and with 0xFFFFFFFF.
- uint32 a [2] = {_a & 0xFFFFFFFF, _a >> 32};
- uint32 b [2] = {_b & 0xFFFFFFFF, _b >> 32};
+ uint32 a [2] = {static_cast<uint32>(_a & 0xFFFFFFFF), static_cast<uint32>(_a >> 32)};
+ uint32 b [2] = {static_cast<uint32>(_b & 0xFFFFFFFF), static_cast<uint32>(_b >> 32)};
uint64 tmp = uint64(a[0]) + b[0];
@@ -35,8 +35,8 @@ void multiplyAndCarry(const uint64& _a, const uint64& _b, uint64& carry, uint64&
// Break each number into 4 32-bit chunks. Since we are using uints, right-shifting will fill with zeros.
// This eliminates the need to and with 0xFFFFFFFF.
- uint32 a [2] = {_a & 0xFFFFFFFF, _a >> 32};
- uint32 b [2] = {_b & 0xFFFFFFFF, _b >> 32};
+ uint32 a [2] = {static_cast<uint32>(_a & 0xFFFFFFFF), static_cast<uint32>(_a >> 32)};
+ uint32 b [2] = {static_cast<uint32>(_b & 0xFFFFFFFF), static_cast<uint32>(_b >> 32)};
uint64 prod [2][2];
for(int i = 0; i < 2; ++i) {