aboutsummaryrefslogtreecommitdiff
path: root/dep/g3dlite/source/CoordinateFrame.cpp
diff options
context:
space:
mode:
authorclick <none@none>2010-08-27 01:52:05 +0200
committerclick <none@none>2010-08-27 01:52:05 +0200
commit7686d6ee57038e848f75130563fc78c1adebc1a2 (patch)
tree258a7a6db03e3479a0219ace8cfc3ec3ba53a1be /dep/g3dlite/source/CoordinateFrame.cpp
parent1d3deae555f0ec523d77875bd5a307ab9bd19742 (diff)
Core/Dependency: Upgrade G3d-library to v8.0-release (patched version!)
Note: Due to issues with G3D (normally requiring X11 and the ZIP-library), the sourcetree version contains a modified version. The applied patch is commited to the repository for future reference. --HG-- branch : trunk
Diffstat (limited to 'dep/g3dlite/source/CoordinateFrame.cpp')
-rw-r--r--dep/g3dlite/source/CoordinateFrame.cpp465
1 files changed, 465 insertions, 0 deletions
diff --git a/dep/g3dlite/source/CoordinateFrame.cpp b/dep/g3dlite/source/CoordinateFrame.cpp
new file mode 100644
index 00000000000..7f9a4c098a5
--- /dev/null
+++ b/dep/g3dlite/source/CoordinateFrame.cpp
@@ -0,0 +1,465 @@
+/**
+ @file CoordinateFrame.cpp
+
+ Coordinate frame class
+
+ @maintainer Morgan McGuire, http://graphics.cs.williams.edu
+
+ @created 2001-06-02
+ @edited 2010-03-13
+
+ Copyright 2000-2010, Morgan McGuire.
+ All rights reserved.
+*/
+
+#include "G3D/platform.h"
+#include "G3D/CoordinateFrame.h"
+#include "G3D/Quat.h"
+#include "G3D/Matrix4.h"
+#include "G3D/Box.h"
+#include "G3D/AABox.h"
+#include "G3D/Sphere.h"
+#include "G3D/Triangle.h"
+#include "G3D/Ray.h"
+#include "G3D/Capsule.h"
+#include "G3D/Cylinder.h"
+#include "G3D/UprightFrame.h"
+#include "G3D/Any.h"
+#include "G3D/stringutils.h"
+#include "G3D/PhysicsFrame.h"
+#include "G3D/UprightFrame.h"
+
+namespace G3D {
+
+
+std::string CoordinateFrame::toXYZYPRDegreesString() const {
+ UprightFrame uframe(*this);
+
+ return format("CFrame::fromXYZYPRDegrees(% 5.1ff, % 5.1ff, % 5.1ff, % 5.1ff, % 5.1ff, % 5.1ff)",
+ uframe.translation.x, uframe.translation.y, uframe.translation.z,
+ toDegrees(uframe.yaw), toDegrees(uframe.pitch), 0.0f);
+}
+
+
+CoordinateFrame::CoordinateFrame(const Any& any) {
+ *this = CFrame();
+
+ const std::string& n = toUpper(any.name());
+
+ if (beginsWith(n, "VECTOR3")) {
+ translation = any;
+ } else if (beginsWith(n, "MATRIX3")) {
+ rotation = any;
+ } else if ((n == "CFRAME") || (n == "COORDINATEFRAME")) {
+ any.verifyType(Any::TABLE, Any::ARRAY);
+ if (any.type() == Any::ARRAY) {
+ any.verifySize(2);
+ rotation = any[0];
+ translation = any[1];
+ } else {
+ for (Any::AnyTable::Iterator it = any.table().begin(); it.hasMore(); ++it) {
+ const std::string& n = toLower(it->key);
+ if (n == "translation") {
+ translation = Vector3(it->value);
+ } else if (n == "rotation") {
+ rotation = Matrix3(it->value);
+ } else {
+ any.verify(false, "Illegal table key: " + it->key);
+ }
+ }
+ }
+ } else if (beginsWith(n, "PHYSICSFRAME") || beginsWith(n, "PFRAME")) {
+ *this = PhysicsFrame(any);
+ } else {
+ any.verifyName("CFrame::fromXYZYPRDegrees", "CoordinateFrame::fromXYZYPRDegrees");
+ any.verifyType(Any::ARRAY);
+ any.verifySize(3, 6);
+
+ int s = any.size();
+
+ *this = fromXYZYPRDegrees(any[0], any[1], any[2],
+ (s > 3) ? any[3].number() : 0.0f,
+ (s > 4) ? any[4].number() : 0.0f,
+ (s > 5) ? any[5].number() : 0.0f);
+ }
+}
+
+
+CoordinateFrame::operator Any() const {
+ float x, y, z, yaw, pitch, roll;
+ getXYZYPRDegrees(x, y, z, yaw, pitch, roll);
+ Any a(Any::ARRAY, "CFrame::fromXYZYPRDegrees");
+ a.append(x, y, z, yaw);
+ if ( ! G3D::fuzzyEq(yaw, 0.0f) || ! G3D::fuzzyEq(pitch, 0.0f) || ! G3D::fuzzyEq(roll, 0.0f)) {
+ a.append(yaw);
+ if (! G3D::fuzzyEq(pitch, 0.0f) || ! G3D::fuzzyEq(roll, 0.0f)) {
+ a.append(pitch);
+ if (! G3D::fuzzyEq(roll, 0.0f)) {
+ a.append(roll);
+ }
+ }
+ }
+ return a;
+}
+
+
+CoordinateFrame::CoordinateFrame(const class UprightFrame& f) {
+ *this = f.toCoordinateFrame();
+}
+
+
+CoordinateFrame::CoordinateFrame() :
+ rotation(Matrix3::identity()), translation(Vector3::zero()) {
+}
+
+CoordinateFrame CoordinateFrame::fromXYZYPRRadians(float x, float y, float z, float yaw,
+ float pitch, float roll) {
+ Matrix3 rotation = Matrix3::fromAxisAngle(Vector3::unitY(), yaw);
+
+ rotation = Matrix3::fromAxisAngle(rotation.column(0), pitch) * rotation;
+ rotation = Matrix3::fromAxisAngle(rotation.column(2), roll) * rotation;
+
+ const Vector3 translation(x, y, z);
+
+ return CoordinateFrame(rotation, translation);
+}
+
+
+void CoordinateFrame::getXYZYPRRadians(float& x, float& y, float& z,
+ float& yaw, float& pitch, float& roll) const {
+ x = translation.x;
+ y = translation.y;
+ z = translation.z;
+
+ const Vector3& look = lookVector();
+
+ if (abs(look.y) > 0.99f) {
+ // Looking nearly straight up or down
+
+ yaw = G3D::pi() + atan2(look.x, look.z);
+ pitch = asin(look.y);
+ roll = 0.0f;
+
+ } else {
+
+ // Yaw cannot be affected by others, so pull it first
+ yaw = G3D::pi() + atan2(look.x, look.z);
+
+ // Pitch is the elevation of the yaw vector
+ pitch = asin(look.y);
+
+ Vector3 actualRight = rightVector();
+ Vector3 expectedRight = look.cross(Vector3::unitY());
+
+ roll = 0;//acos(actualRight.dot(expectedRight)); TODO
+ }
+}
+
+
+void CoordinateFrame::getXYZYPRDegrees(float& x, float& y, float& z,
+ float& yaw, float& pitch, float& roll) const {
+ getXYZYPRRadians(x, y, z, yaw, pitch, roll);
+ yaw = toDegrees(yaw);
+ pitch = toDegrees(pitch);
+ roll = toDegrees(roll);
+}
+
+
+CoordinateFrame CoordinateFrame::fromXYZYPRDegrees(float x, float y, float z,
+ float yaw, float pitch, float roll) {
+ return fromXYZYPRRadians(x, y, z, toRadians(yaw), toRadians(pitch), toRadians(roll));
+}
+
+
+Ray CoordinateFrame::lookRay() const {
+ return Ray::fromOriginAndDirection(translation, lookVector());
+}
+
+
+bool CoordinateFrame::fuzzyEq(const CoordinateFrame& other) const {
+
+ for (int c = 0; c < 3; ++c) {
+ for (int r = 0; r < 3; ++r) {
+ if (! G3D::fuzzyEq(other.rotation[r][c], rotation[r][c])) {
+ return false;
+ }
+ }
+ if (! G3D::fuzzyEq(translation[c], other.translation[c])) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+
+bool CoordinateFrame::fuzzyIsIdentity() const {
+ const Matrix3& I = Matrix3::identity();
+
+ for (int c = 0; c < 3; ++c) {
+ for (int r = 0; r < 3; ++r) {
+ if (fuzzyNe(I[r][c], rotation[r][c])) {
+ return false;
+ }
+ }
+ if (fuzzyNe(translation[c], 0)) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+
+bool CoordinateFrame::isIdentity() const {
+ return
+ (translation == Vector3::zero()) &&
+ (rotation == Matrix3::identity());
+}
+
+
+Matrix4 CoordinateFrame::toMatrix4() const {
+ return Matrix4(*this);
+}
+
+
+std::string CoordinateFrame::toXML() const {
+ return G3D::format(
+ "<COORDINATEFRAME>\n %lf,%lf,%lf,%lf,\n %lf,%lf,%lf,%lf,\n %lf,%lf,%lf,%lf,\n %lf,%lf,%lf,%lf\n</COORDINATEFRAME>\n",
+ rotation[0][0], rotation[0][1], rotation[0][2], translation.x,
+ rotation[1][0], rotation[1][1], rotation[1][2], translation.y,
+ rotation[2][0], rotation[2][1], rotation[2][2], translation.z,
+ 0.0, 0.0, 0.0, 1.0);
+}
+
+
+Plane CoordinateFrame::toObjectSpace(const Plane& p) const {
+ Vector3 N, P;
+ double d;
+ p.getEquation(N, d);
+ P = N * (float)d;
+ P = pointToObjectSpace(P);
+ N = normalToObjectSpace(N);
+ return Plane(N, P);
+}
+
+
+Plane CoordinateFrame::toWorldSpace(const Plane& p) const {
+ Vector3 N, P;
+ double d;
+ p.getEquation(N, d);
+ P = N * (float)d;
+ P = pointToWorldSpace(P);
+ N = normalToWorldSpace(N);
+ return Plane(N, P);
+}
+
+
+Triangle CoordinateFrame::toObjectSpace(const Triangle& t) const {
+ return Triangle(pointToObjectSpace(t.vertex(0)),
+ pointToObjectSpace(t.vertex(1)),
+ pointToObjectSpace(t.vertex(2)));
+}
+
+
+Triangle CoordinateFrame::toWorldSpace(const Triangle& t) const {
+ return Triangle(pointToWorldSpace(t.vertex(0)),
+ pointToWorldSpace(t.vertex(1)),
+ pointToWorldSpace(t.vertex(2)));
+}
+
+
+Cylinder CoordinateFrame::toWorldSpace(const Cylinder& c) const {
+ return Cylinder(
+ pointToWorldSpace(c.point(0)),
+ pointToWorldSpace(c.point(1)),
+ c.radius());
+}
+
+
+Capsule CoordinateFrame::toWorldSpace(const Capsule& c) const {
+ return Capsule(
+ pointToWorldSpace(c.point(0)),
+ pointToWorldSpace(c.point(1)),
+ c.radius());
+}
+
+
+Box CoordinateFrame::toWorldSpace(const AABox& b) const {
+ Box b2(b);
+ return toWorldSpace(b2);
+}
+
+
+Box CoordinateFrame::toWorldSpace(const Box& b) const {
+ Box out(b);
+
+ for (int i = 0; i < 8; ++i) {
+ out._corner[i] = pointToWorldSpace(b._corner[i]);
+ debugAssert(! isNaN(out._corner[i].x));
+ }
+
+ for (int i = 0; i < 3; ++i) {
+ out._axis[i] = vectorToWorldSpace(b._axis[i]);
+ }
+
+ out._center = pointToWorldSpace(b._center);
+
+ return out;
+}
+
+
+Box CoordinateFrame::toObjectSpace(const Box &b) const {
+ return inverse().toWorldSpace(b);
+}
+
+
+Box CoordinateFrame::toObjectSpace(const AABox& b) const {
+ return toObjectSpace(Box(b));
+}
+
+
+CoordinateFrame::CoordinateFrame(class BinaryInput& b) : rotation(Matrix3::zero()) {
+ deserialize(b);
+}
+
+
+void CoordinateFrame::deserialize(class BinaryInput& b) {
+ rotation.deserialize(b);
+ translation.deserialize(b);
+}
+
+
+void CoordinateFrame::serialize(class BinaryOutput& b) const {
+ rotation.serialize(b);
+ translation.serialize(b);
+}
+
+
+Sphere CoordinateFrame::toWorldSpace(const Sphere &b) const {
+ return Sphere(pointToWorldSpace(b.center), b.radius);
+}
+
+
+Sphere CoordinateFrame::toObjectSpace(const Sphere &b) const {
+ return Sphere(pointToObjectSpace(b.center), b.radius);
+}
+
+
+Ray CoordinateFrame::toWorldSpace(const Ray& r) const {
+ return Ray::fromOriginAndDirection(pointToWorldSpace(r.origin()), vectorToWorldSpace(r.direction()));
+}
+
+
+Ray CoordinateFrame::toObjectSpace(const Ray& r) const {
+ return Ray::fromOriginAndDirection(pointToObjectSpace(r.origin()), vectorToObjectSpace(r.direction()));
+}
+
+
+void CoordinateFrame::lookAt(const Vector3 &target) {
+ lookAt(target, Vector3::unitY());
+}
+
+
+void CoordinateFrame::lookAt(
+ const Vector3& target,
+ Vector3 up) {
+
+ up = up.direction();
+
+ Vector3 look = (target - translation).direction();
+ if (fabs(look.dot(up)) > .99f) {
+ up = Vector3::unitX();
+ if (fabs(look.dot(up)) > .99f) {
+ up = Vector3::unitY();
+ }
+ }
+
+ up -= look * look.dot(up);
+ up.unitize();
+
+ Vector3 z = -look;
+ Vector3 x = -z.cross(up);
+ x.unitize();
+
+ Vector3 y = z.cross(x);
+
+ rotation.setColumn(0, x);
+ rotation.setColumn(1, y);
+ rotation.setColumn(2, z);
+}
+
+
+CoordinateFrame CoordinateFrame::lerp(
+ const CoordinateFrame& other,
+ float alpha) const {
+
+ if (alpha == 1.0f) {
+ return other;
+ } else if (alpha == 0.0f) {
+ return *this;
+ } else {
+ const Quat q1(this->rotation);
+ const Quat q2(other.rotation);
+
+ return CoordinateFrame(
+ q1.slerp(q2, alpha).toRotationMatrix(),
+ translation * (1 - alpha) + other.translation * alpha);
+ }
+}
+
+
+void CoordinateFrame::pointToWorldSpace(const Array<Vector3>& v, Array<Vector3>& vout) const {
+ vout.resize(v.size());
+
+ for (int i = 0; i < v.size(); ++i) {
+ vout[i] = pointToWorldSpace(v[i]);
+ }
+}
+
+
+void CoordinateFrame::normalToWorldSpace(const Array<Vector3>& v, Array<Vector3>& vout) const {
+ vout.resize(v.size());
+
+ for (int i = 0; i < v.size(); ++i) {
+ vout[i] = normalToWorldSpace(v[i]);
+ }
+}
+
+
+void CoordinateFrame::vectorToWorldSpace(const Array<Vector3>& v, Array<Vector3>& vout) const {
+ vout.resize(v.size());
+
+ for (int i = v.size() - 1; i >= 0; --i) {
+ vout[i] = vectorToWorldSpace(v[i]);
+ }
+}
+
+
+void CoordinateFrame::pointToObjectSpace(const Array<Vector3>& v, Array<Vector3>& vout) const {
+ vout.resize(v.size());
+
+ for (int i = v.size() - 1; i >= 0; --i) {
+ vout[i] = pointToObjectSpace(v[i]);
+ }
+}
+
+
+void CoordinateFrame::normalToObjectSpace(const Array<Vector3>& v, Array<Vector3>& vout) const {
+ vout.resize(v.size());
+
+ for (int i = v.size() - 1; i >= 0; --i) {
+ vout[i] = normalToObjectSpace(v[i]);
+ }
+}
+
+
+void CoordinateFrame::vectorToObjectSpace(const Array<Vector3>& v, Array<Vector3>& vout) const {
+ vout.resize(v.size());
+
+ for (int i = v.size() - 1; i >= 0; --i) {
+ vout[i] = vectorToObjectSpace(v[i]);
+ }
+}
+
+} // namespace