Imported mathematics library.
authorethereal <ethereal.visage@gmail.com>
Tue, 16 Apr 2013 19:44:41 +0000 (13:44 -0600)
committerethereal <ethereal.visage@gmail.com>
Tue, 16 Apr 2013 19:44:41 +0000 (13:44 -0600)
src/CMakeLists.txt
src/math/Constants.h [new file with mode: 0644]
src/math/Matrix.cpp [new file with mode: 0644]
src/math/Matrix.h [new file with mode: 0644]
src/math/Quaternion.cpp [new file with mode: 0644]
src/math/Quaternion.h [new file with mode: 0644]
src/math/Vector.cpp [new file with mode: 0644]
src/math/Vector.h [new file with mode: 0644]

index d1fa897..d435692 100644 (file)
@@ -5,9 +5,11 @@ include_directories(.)
 
 aux_source_directory(. dotSources)
 aux_source_directory(config configSources)
+aux_source_directory(math mathSources)
 set(sources
     ${dotSources}
     ${configSources}
+    ${mathSources}
 )
 
 #find_package(Boost COMPONENTS )
diff --git a/src/math/Constants.h b/src/math/Constants.h
new file mode 100644 (file)
index 0000000..8268861
--- /dev/null
@@ -0,0 +1,19 @@
+#ifndef MATH__CONSTANTS_H
+#define MATH__CONSTANTS_H
+
+#include <cmath>
+
+namespace Math {
+
+namespace Constants {
+
+/* Used to represent numerical imprecision in floating-point results. */
+const double Epsilon = 1e-7;
+
+const double Pi = M_PI;
+
+};
+
+}  // namespace Math
+
+#endif
diff --git a/src/math/Matrix.cpp b/src/math/Matrix.cpp
new file mode 100644 (file)
index 0000000..eb87065
--- /dev/null
@@ -0,0 +1,91 @@
+#include "Matrix.h"
+
+namespace Math {
+
+Matrix::Matrix() {
+    for(int i = 0; i < 16; i ++) {
+        m_coefficients[i] = ((i % 5) == 0);
+    }
+}
+
+Matrix Matrix::operator+(const Matrix &other) const {
+    Matrix result;
+    for(int i = 0; i < 16; i ++) {
+        result.m_coefficients[i] = m_coefficients[i] + other.m_coefficients[i];
+    }
+    return result;
+}
+
+Matrix &Matrix::operator+=(const Matrix &other) {
+    for(int i = 0; i < 16; i ++) {
+        m_coefficients[i] += other.m_coefficients[i];
+    }
+    return *this;
+}
+
+Matrix Matrix::operator-(const Matrix &other) const {
+    Matrix result;
+    for(int i = 0; i < 16; i ++) {
+        result.m_coefficients[i] = m_coefficients[i] - other.m_coefficients[i];
+    }
+    return result;
+}
+
+Matrix &Matrix::operator-=(const Matrix &other) {
+    for(int i = 0; i < 16; i ++) {
+        m_coefficients[i] -= other.m_coefficients[i];
+    }
+    return *this;
+}
+
+Matrix Matrix::operator*(const Matrix &other) const {
+    Matrix m;
+    for(int i = 0; i < 4; i ++) {
+        for(int j = 0; j < 4; j ++) {
+            m(i, j) = (*this)(i, 0)*other(0, j)
+                + (*this)(i, 1)*other(1, j)
+                + (*this)(i, 2)*other(2, j)
+                + (*this)(i, 3)*other(3, j);
+        }
+    }
+    return m;
+}
+
+Matrix &Matrix::operator*=(const Matrix &other) {
+    *this = *this * other;
+    return *this;
+}
+
+Matrix Matrix::operator*(double factor) const {
+    Matrix result = *this;
+    for(int i = 0; i < 16; i ++) result.m_coefficients[i] *= factor;
+    return result;
+}
+
+Matrix &Matrix::operator*=(double factor) {
+    for(int i = 0; i < 16; i ++) m_coefficients[i] *= factor;
+    return *this;
+}
+
+Vector Matrix::operator*(const Vector &other) const {
+    Vector v;
+    for(int i = 0; i < 4; i ++) {
+        v[i] = m_coefficients[i*4+0]*other.x()
+            + m_coefficients[i*4+1]*other.y()
+            + m_coefficients[i*4+2]*other.z();
+    }
+    return v;
+}
+
+Point Matrix::operator*(const Point &other) const {
+    double pc[4];
+    for(int i = 0; i < 4; i ++) {
+        pc[i] = m_coefficients[i*4+0]*other.x()
+            + m_coefficients[i*4+1]*other.y()
+            + m_coefficients[i*4+2]*other.z()
+            + m_coefficients[i*4+3];
+    }
+    return Point(pc[0]/pc[3],pc[1]/pc[3],pc[2]/pc[3]);
+}
+
+}  // namespace Math
diff --git a/src/math/Matrix.h b/src/math/Matrix.h
new file mode 100644 (file)
index 0000000..0a64b3c
--- /dev/null
@@ -0,0 +1,41 @@
+#ifndef MATH__MATRIX_H
+#define MATH__MATRIX_H
+
+#include "Vector.h"
+
+namespace Math {
+
+class Matrix {
+private:
+    float m_coefficients[16];
+public:
+    Matrix();
+
+    const float * matrixData() const { return m_coefficients; }
+
+    float &operator()(int i, int j) {
+        return m_coefficients[i + j*4];
+    }
+
+    float operator()(int i, int j) const {
+        return m_coefficients[i + j*4];
+    }
+
+    Matrix operator+(const Matrix &other) const;
+    Matrix &operator+=(const Matrix &other);
+    Matrix operator-(const Matrix &other) const;
+    Matrix &operator-=(const Matrix &other);
+
+    Matrix operator*(const Matrix &other) const;
+    Matrix &operator*=(const Matrix &other);
+
+    Matrix operator*(double factor) const;
+    Matrix &operator*=(double factor);
+
+    Vector operator*(const Vector &other) const;
+    Point operator*(const Point &other) const;
+};
+
+}  // namespace Math
+
+#endif
diff --git a/src/math/Quaternion.cpp b/src/math/Quaternion.cpp
new file mode 100644 (file)
index 0000000..d291e21
--- /dev/null
@@ -0,0 +1,45 @@
+#include "Quaternion.h"
+
+namespace Math {
+
+Quaternion::Quaternion(const Vector &axis, double angle) {
+    m_s = std::cos(angle/2.0);
+    m_v = axis*std::sin(angle/2.0);
+}
+
+void Quaternion::toAxisAngle(Vector &axis, double &angle) const {
+    angle = 2*std::acos(m_s);
+    if(std::abs(angle) > Constants::Epsilon) {
+        axis = m_v / std::sin(angle/2.0);
+    }
+    /* No rotation, so there is no axis . . . */
+    else axis = Vector();
+}
+
+Matrix Quaternion::toMatrix() const {
+    Matrix matrix;
+
+    double x = m_v.x();
+    double y = m_v.y();
+    double z = m_v.z();
+    double s = m_s;
+    
+    matrix(0, 0) = 1 - 2*y*y - 2*z*z;
+    matrix(0, 1) = 2*x*y - 2*z*s;
+    matrix(0, 2) = 2*x*z + 2*y*s;
+    matrix(0, 3) = 0;
+
+    matrix(1, 0) = 2*x*y + 2*z*s;
+    matrix(1, 1) = 1 - 2*x*x - 2*z*z;
+    matrix(1, 2) = 2*y*z - 2*x*s;
+    matrix(1, 3) = 0;
+
+    matrix(2, 0)  = 2*x*z - 2*y*s;
+    matrix(2, 1)  = 2*y*z + 2*x*s;
+    matrix(2, 2) = 1 - 2*x*x - 2*y*y;
+    matrix(2, 3) = 0;
+
+    return matrix;
+}
+
+}  // namespace Math
diff --git a/src/math/Quaternion.h b/src/math/Quaternion.h
new file mode 100644 (file)
index 0000000..1fa0e43
--- /dev/null
@@ -0,0 +1,48 @@
+#ifndef MATH__QUATERNION_H
+#define MATH__QUATERNION_H
+
+#include "Vector.h"
+#include "Matrix.h"
+
+namespace Math {
+
+/** Unit quaternion class, used for rotations. */
+class Quaternion {
+private:
+    double m_s;
+    Vector m_v;
+private:
+    Quaternion(double s, Vector v) : m_s(s), m_v(v) {}
+public:
+    Quaternion() : m_s(1.0), m_v() {}
+    Quaternion(const Vector &axis, double angle);
+
+    void toAxisAngle(Vector &axis, double &angle) const;
+
+    Quaternion conjugate() const {
+        return Quaternion(m_s, -m_v);
+    }
+
+    /** Quaternion multiplication. */
+    Quaternion operator*(const Quaternion &other) const {
+        return Quaternion(
+            m_s*other.m_s - m_v.dot(other.m_v),
+            m_s*other.m_v + other.m_s*m_v + m_v.cross(other.m_v)
+        );
+    }
+
+    /** Quaternion-vector multiplication (rotation). */
+    Vector operator*(const Vector &other) const {
+        return ((*this) * Quaternion(0.0, other) * conjugate()).m_v;
+    }
+
+    Matrix toMatrix() const;
+};
+
+inline Vector operator*(const Vector &vec, const Quaternion &quat) {
+    return quat * vec;
+}
+
+}  // namespace Math
+
+#endif
diff --git a/src/math/Vector.cpp b/src/math/Vector.cpp
new file mode 100644 (file)
index 0000000..1c04cf5
--- /dev/null
@@ -0,0 +1,11 @@
+#include "Vector.h"
+
+#include "StreamAsString.h"
+
+namespace Math {
+
+std::string Vector::toString() const {
+    return StreamAsString() << "(" << m_x << "," << m_y << "," << m_z << ")";
+}
+
+}  // namespace Math
diff --git a/src/math/Vector.h b/src/math/Vector.h
new file mode 100644 (file)
index 0000000..89fc63c
--- /dev/null
@@ -0,0 +1,179 @@
+#ifndef MATH__VECTOR_H
+#define MATH__VECTOR_H
+
+#include <cmath>
+#include <string>
+
+#include "Constants.h"
+
+namespace Math {
+
+class Vector {
+private:
+    double m_x, m_y, m_z;
+public:
+    Vector(double x = 0.0, double y = 0.0, double z = 0.0)
+        : m_x(x), m_y(y), m_z(z) {}
+
+    double x() const { return m_x; }
+    double y() const { return m_y; }
+    double z() const { return m_z; }
+
+    void setX(double x) { m_x = x; }
+    void setY(double y) { m_y = y; }
+    void setZ(double z) { m_z = z; }
+
+    double &operator[](int which) {
+        switch(which) {
+        case 0:
+            return m_x;
+        case 1:
+            return m_y;
+        case 2:
+            return m_z;
+        default:
+            return m_x;
+        }
+    }
+
+    double length() const {
+        return std::sqrt(m_x*m_x + m_y*m_y + m_z*m_z);
+    }
+
+    double length2() const {
+        return m_x*m_x + m_y*m_y + m_z*m_z;
+    }
+
+    Vector normalized() const {
+        double len = length();
+        if(len > Constants::Epsilon) return Vector(m_x/len, m_y/len, m_z/len);
+        return Vector();
+    }
+
+    Vector operator+(const Vector &other) const {
+        return Vector(m_x + other.m_x, m_y + other.m_y, m_z + other.m_z);
+    }
+
+    Vector &operator+=(const Vector &other) {
+        m_x += other.m_x;
+        m_y += other.m_y;
+        m_z += other.m_z;
+        return *this;
+    }
+
+    Vector operator-(const Vector &other) const {
+        return Vector(m_x - other.m_x, m_y - other.m_y, m_z - other.m_z);
+    }
+
+    Vector &operator-=(const Vector &other) {
+        m_x -= other.m_x;
+        m_y -= other.m_y;
+        m_z -= other.m_z;
+        return *this;
+    }
+
+    Vector operator*(const Vector &other) const {
+        return Vector(m_x * other.m_x, m_y * other.m_y, m_z * other.m_z);
+    }
+
+    Vector operator*(double scalar) const {
+        return Vector(m_x * scalar, m_y * scalar, m_z * scalar);
+    }
+
+    void operator*=(double scalar) {
+        m_x *= scalar;
+        m_y *= scalar;
+        m_z *= scalar;
+    }
+
+    Vector operator/(double scalar) const {
+        return Vector(m_x / scalar, m_y / scalar, m_z / scalar);
+    }
+
+    void operator/=(double scalar) {
+        m_x /= scalar;
+        m_y /= scalar;
+        m_z /= scalar;
+    }
+
+    Vector operator-() const {
+        return Vector(-m_x, -m_y, -m_z);
+    }
+
+    Vector projectOnto(const Vector &u) const {
+        return *this * (u.dot(*this)/dot(*this));
+    }
+
+    double dot(const Vector &other) const {
+        return m_x*other.m_x + m_y*other.m_y + m_z*other.m_z;
+    }
+
+    Vector cross(const Vector &other) const {
+        return Vector(
+            m_y*other.m_z - m_z*other.m_y,
+            -(m_x*other.m_z - m_z*other.m_x),
+            m_x*other.m_y - m_y*other.m_x
+        );
+    }
+
+    Vector rotX(double angle) const {
+        double s = std::sin(angle);
+        double c = std::cos(angle);
+        return Vector(
+            m_x,
+            m_y*c + m_y*s,
+            -m_z*s + m_z*c
+        );
+    }
+
+    Vector rotY(double angle) const {
+        double s = std::sin(angle);
+        double c = std::cos(angle);
+        return Vector(
+            m_x*c - m_x*s,
+            m_y,
+            m_z*s + m_z*c
+        );
+    }
+
+    Vector rotZ(double angle) const {
+        double s = std::sin(angle);
+        double c = std::cos(angle);
+        return Vector(
+            m_x*c + m_y*s,
+            -m_x*s + m_y*c,
+            m_z
+        );
+    }
+
+    bool operator==(const Vector &other) const {
+        return m_x == other.m_x && m_y == other.m_y && m_z == other.m_z;
+    }
+
+    std::string toString() const;
+};
+
+inline Vector operator*(double scalar, const Vector &vector) {
+    return Vector(
+        vector.x() * scalar,
+        vector.y() * scalar,
+        vector.z() * scalar
+    );
+}
+
+inline Vector operator/(double scalar, const Vector &vector) {
+    return Vector(
+        scalar / vector.x(),
+        scalar / vector.y(),
+        scalar / vector.z()
+    );
+}
+
+class Point : public Vector {
+public:
+    Point(double x = 0.0, double y = 0.0, double z = 0.0) : Vector(x,y,z) {}
+};
+
+}  // namespace Math
+
+#endif