X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=src%2Fvector.hh;fp=src%2Fvector.hh;h=f5c18baad0798ea76b4f1605bcdbb9d97a6d73e7;hb=79b5f738f2e38acb60cda7e09f54802933a17105;hp=0000000000000000000000000000000000000000;hpb=a891a2dcbbb63d9e771da6efff00a33da614e737;p=chaz%2Fyoink diff --git a/src/vector.hh b/src/vector.hh new file mode 100644 index 0000000..f5c18ba --- /dev/null +++ b/src/vector.hh @@ -0,0 +1,372 @@ + +/******************************************************************************* + + Copyright (c) 2009, Charles McGarvey + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*******************************************************************************/ + +#ifndef _VECTOR_HH_ +#define _VECTOR_HH_ + +/** + * @file vector.hh + * Vector classes. + */ + +#include +#include + +#include "math.hh" +#include "random.hh" + + +// TODO: project, reflect, random, normal (of plane), orthonormal + +namespace dc { + +/** + * 2-dimensional vector. + */ + +struct vector2 +{ + vector2() {} + vector2(scalar X, scalar Y) : x(X), y(Y) {} + vector2(scalar v[2]) : x(v[0]), y(v[1]) {} + + const scalar& operator[](int i) const + { + assert(i >= 0 && i <= 1 && "Index into vector2 out of bounds."); + return array[i]; + } + scalar& operator[](int i) + { + assert(i >= 0 && i <= 1 && "Index into vector2 out of bounds."); + return array[i]; + } + + vector2 operator+(const vector2& v) const + { + return vector2(x + v.x, y + v.y); + } + vector2 operator-(const vector2& v) const + { + return vector2(x - v.x, y - v.y); + } + vector2 operator*(scalar s) const + { + return vector2(x * s, y * s); + } + vector2 operator/(scalar s) const + { + return vector2(x / s, y / s); + } + + vector2& operator+=(const vector2& v) + { + x += v.x; y += v.y; + return *this; + } + vector2& operator-=(const vector2& v) + { + x -= v.x; y -= v.y; + return *this; + } + vector2& operator*=(scalar s) + { + x *= s; y *= s; + return *this; + } + vector2& operator/=(scalar s) + { + x /= s; y /= s; + return *this; + } + + vector2 operator-() const + { + return vector2(-x, -y); + } + + scalar dot(const vector2& v) const /// dot product + { + return x * v.x + y * v.y; + } + scalar angleBetween(const vector2& v) const + { + scalar lens = length() * v.length(); + if (lens == 0.0) { return HUGE_VAL; } + return std::acos(dot(v) / lens); + } + + void normalize() /// scale such that length is one + { + scalar len = length(); + if (len != 0.0) { *this /= len; } + } + vector2 normalized() const + { + scalar len = length(); + if (len != 0.0) { return *this / len; } + return vector2(0.0, 0.0); + } + + scalar length2() const /// magnitude squared + { + return dot(*this); + } + scalar length() const /// magnitude + { + return std::sqrt(length2()); + } + + bool operator==(const vector2& v) const + { + return equals(x, v.x) && equals(y, v.y); + } + bool operator!=(const vector2& v) const + { + return !(*this == v); + } + + + static vector2 random() + { + vector2 v = random(-1.0, 1.0); + v.normalize(); + return v; + } + + static vector2 random(scalar lower, scalar upper) + { + return vector2(rng::get(lower, upper), + rng::get(lower, upper)); + } + + + union + { + struct + { + scalar x, y; ///< euler coordinates + }; + scalar array[2]; ///< array + }; + + static vector2 zero; ///< zero vector +}; + +inline vector2 operator*(scalar s, const vector2& v) +{ + return v * s; +} +inline vector2 operator/(scalar s, const vector2& v) +{ + return vector2(s / v.x, s / v.y); +} + +inline std::ostream& operator<<(std::ostream& output, const vector2& v) +{ + output << "(" << v.x << "," << v.y << ")"; + return output; +} + + +typedef vector2 point; + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +/** + * 3-dimensional vector. + */ + +struct vector3 +{ + vector3() {} + vector3(scalar X, scalar Y, scalar Z) : x(X), y(Y), z(Z) {} + vector3(scalar v[3]) : x(v[0]), y(v[1]), z(v[2]) {} + + const scalar& operator[](int i) const + { + assert(i >= 0 && i <= 2 && "Index into vector3 out of bounds."); + return array[i]; + } + scalar& operator[](int i) + { + assert(i >= 0 && i <= 2 && "Index into vector3 out of bounds."); + return array[i]; + } + + vector3 operator+(const vector3& v) const + { + return vector3(x + v.x, y + v.y, z + v.z); + } + vector3 operator-(const vector3& v) const + { + return vector3(x - v.x, y - v.y, z - v.z); + } + vector3 operator*(scalar s) const + { + return vector3(x * s, y * s, z * s); + } + vector3 operator/(scalar s) const + { + return vector3(x / s, y / s, z / s); + } + + vector3& operator+=(const vector3& v) + { + x += v.x; y += v.y; z += v.z; + return *this; + } + vector3& operator-=(const vector3& v) + { + x -= v.x; y -= v.y; z -= v.z; + return *this; + } + vector3& operator*=(scalar s) + { + x *= s; y *= s; z *= s; + return *this; + } + vector3& operator/=(scalar s) + { + x /= s; y /= s; z /= s; + return *this; + } + + vector3 operator-() const + { + return vector3(-x, -y, -z); + } + + scalar dot(const vector3& v) const /// dot product + { + return x * v.x + y * v.y + z * v.z; + } + vector3 cross(const vector3& v) const /// cross product + { + return vector3(y * v.z - z * v.y, + z * v.x - x * v.z, + x * v.y - y * v.x); + } + + scalar angleBetween(const vector3& v) const + { + scalar lens = length() * v.length(); + if (lens == 0.0) { return HUGE_VAL; } + return std::acos(dot(v) / lens); + } + + void normalize() /// scale such that length is one + { + scalar len = length(); + if (len != 0.0) { *this /= len; } + } + vector3 normalized() const + { + scalar len = length(); + if (len != 0.0) { return *this / len; } + return vector3(0.0, 0.0, 0.0); + } + + scalar length2() const /// magnitude squared + { + return dot(*this); + } + scalar length() const /// magnitude + { + return std::sqrt(length2()); + } + + bool operator==(const vector3& v) const + { + return equals(x, v.x) && equals(y, v.y) && equals(z, v.z); + } + bool operator!=(const vector3& v) const + { + return !(*this == v); + } + + + static vector3 random() + { + vector3 v = random(-1.0, 1.0); + v.normalize(); + return v; + } + + static vector3 random(scalar lower, scalar upper) + { + return vector3(rng::get(lower, upper), + rng::get(lower, upper), + rng::get(lower, upper)); + } + + + union + { + struct + { + scalar x, y, z; ///< euler coordinates + }; + struct + { + scalar u, v, w; ///< texture coordinates + }; + struct + { + scalar r, g, b; ///< color intensities + }; + scalar array[3]; ///< array + }; + + static vector3 zero; ///< zero vector +}; + +inline vector3 operator*(scalar s, const vector3& v) +{ + return v * s; +} +inline vector3 operator/(scalar s, const vector3& v) +{ + return vector3(s / v.x, s / v.y, s / v.z); +} + +inline std::ostream& operator<<(std::ostream& output, const vector3& v) +{ + output << "(" << v.x << "," << v.y << "," << v.z << ")"; + return output; +} + + +typedef vector3 color; + + +} // namespace dc + + +#endif // _VECTOR_HH_ +