/////////////////////////////////////////////////////////////////////////// // // Copyright (c) 2012-2013 DreamWorks Animation LLC // // All rights reserved. This software is distributed under the // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ ) // // Redistributions of source code must retain the above copyright // and license notice and the following restrictions and disclaimer. // // * Neither the name of DreamWorks Animation nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // 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 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY 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. // IN NO EVENT SHALL THE COPYRIGHT HOLDERS' AND CONTRIBUTORS' AGGREGATE // LIABILITY FOR ALL CLAIMS REGARDLESS OF THEIR BASIS EXCEED US$250.00. // /////////////////////////////////////////////////////////////////////////// #ifndef OPENVDB_MATH_VEC4_HAS_BEEN_INCLUDED #define OPENVDB_MATH_VEC4_HAS_BEEN_INCLUDED #include #include #include "Math.h" #include "Tuple.h" #include "Vec3.h" namespace openvdb { OPENVDB_USE_VERSION_NAMESPACE namespace OPENVDB_VERSION_NAME { namespace math { template class Mat3; template class Vec4: public Tuple<4, T> { public: typedef T value_type; typedef T ValueType; /// Trivial constructor, the vector is NOT initialized Vec4() {} /// Constructor with one argument, e.g. Vec4f v(0); explicit Vec4(T val) { this->mm[0] = this->mm[1] = this->mm[2] = this->mm[3] = val; } /// Constructor with three arguments, e.g. Vec4f v(1,2,3); Vec4(T x, T y, T z, T w) { this->mm[0] = x; this->mm[1] = y; this->mm[2] = z; this->mm[3] = w; } /// Constructor with array argument, e.g. float a[4]; Vec4f v(a); template Vec4(Source *a) { this->mm[0] = a[0]; this->mm[1] = a[1]; this->mm[2] = a[2]; this->mm[3] = a[3]; } /// Conversion constructor template explicit Vec4(const Tuple<4, Source> &v) { this->mm[0] = static_cast(v[0]); this->mm[1] = static_cast(v[1]); this->mm[2] = static_cast(v[2]); this->mm[3] = static_cast(v[3]); } /// Reference to the component, e.g. v.x() = 4.5f; T& x() { return this->mm[0]; } T& y() { return this->mm[1]; } T& z() { return this->mm[2]; } T& w() { return this->mm[3]; } /// Get the component, e.g. float f = v.y(); T x() const { return this->mm[0]; } T y() const { return this->mm[1]; } T z() const { return this->mm[2]; } T w() const { return this->mm[3]; } T* asPointer() { return this->mm; } const T* asPointer() const { return this->mm; } /// Alternative indexed reference to the elements T& operator()(int i) { return this->mm[i]; } /// Alternative indexed constant reference to the elements, T operator()(int i) const { return this->mm[i]; } /// Returns a Vec3 with the first three elements of the Vec4. Vec3 getVec3() const { return Vec3(this->mm[0], this->mm[1], this->mm[2]); } /// "this" vector gets initialized to [x, y, z, w], /// calling v.init(); has same effect as calling v = Vec4::zero(); const Vec4& init(T x=0, T y=0, T z=0, T w=0) { this->mm[0] = x; this->mm[1] = y; this->mm[2] = z; this->mm[3] = w; return *this; } /// Set "this" vector to zero const Vec4& setZero() { this->mm[0] = 0; this->mm[1] = 0; this->mm[2] = 0; this->mm[3] = 0; return *this; } /// Assignment operator template const Vec4& operator=(const Vec4 &v) { // note: don't static_cast because that suppresses warnings this->mm[0] = v[0]; this->mm[1] = v[1]; this->mm[2] = v[2]; this->mm[3] = v[3]; return *this; } /// Test if "this" vector is equivalent to vector v with tolerance /// of eps bool eq(const Vec4 &v, T eps=1.0e-8) const { return isApproxEqual(this->mm[0], v.mm[0], eps) && isApproxEqual(this->mm[1], v.mm[1], eps) && isApproxEqual(this->mm[2], v.mm[2], eps) && isApproxEqual(this->mm[3], v.mm[3], eps); } /// Negation operator, for e.g. v1 = -v2; Vec4 operator-() const { return Vec4( -this->mm[0], -this->mm[1], -this->mm[2], -this->mm[3]); } /// this = v1 + v2 /// "this", v1 and v2 need not be distinct objects, e.g. v.add(v1,v); template const Vec4& add(const Vec4 &v1, const Vec4 &v2) { this->mm[0] = v1[0] + v2[0]; this->mm[1] = v1[1] + v2[1]; this->mm[2] = v1[2] + v2[2]; this->mm[3] = v1[3] + v2[3]; return *this; } /// this = v1 - v2 /// "this", v1 and v2 need not be distinct objects, e.g. v.sub(v1,v); template const Vec4& sub(const Vec4 &v1, const Vec4 &v2) { this->mm[0] = v1[0] - v2[0]; this->mm[1] = v1[1] - v2[1]; this->mm[2] = v1[2] - v2[2]; this->mm[3] = v1[3] - v2[3]; return *this; } /// this = scalar*v, v need not be a distinct object from "this", /// e.g. v.scale(1.5,v1); template const Vec4& scale(T0 scale, const Vec4 &v) { this->mm[0] = scale * v[0]; this->mm[1] = scale * v[1]; this->mm[2] = scale * v[2]; this->mm[3] = scale * v[3]; return *this; } template const Vec4 &div(T0 scalar, const Vec4 &v) { this->mm[0] = v[0] / scalar; this->mm[1] = v[1] / scalar; this->mm[2] = v[2] / scalar; this->mm[3] = v[3] / scalar; return *this; } /// Dot product T dot(const Vec4 &v) const { return (this->mm[0]*v.mm[0] + this->mm[1]*v.mm[1] + this->mm[2]*v.mm[2] + this->mm[3]*v.mm[3]); } /// Length of the vector T length() const { return sqrt( this->mm[0]*this->mm[0] + this->mm[1]*this->mm[1] + this->mm[2]*this->mm[2] + this->mm[3]*this->mm[3]); } /// Squared length of the vector, much faster than length() as it /// does not involve square root T lengthSqr() const { return (this->mm[0]*this->mm[0] + this->mm[1]*this->mm[1] + this->mm[2]*this->mm[2] + this->mm[3]*this->mm[3]); } /// this = normalized this bool normalize(T eps=1.0e-8) { T d = length(); if (isApproxEqual(d, T(0), eps)) { return false; } *this *= (T(1) / d); return true; } /// return normalized this, throws if null vector Vec4 unit(T eps=0) const { T d; return unit(eps, d); } /// return normalized this and length, throws if null vector Vec4 unit(T eps, T& len) const { len = length(); if (isApproxEqual(len, T(0), eps)) { throw ArithmeticError("Normalizing null 4-vector"); } return *this / len; } /// Returns v, where \f$v_i *= scalar\f$ for \f$i \in [0, 3]\f$ template const Vec4 &operator*=(S scalar) { this->mm[0] *= scalar; this->mm[1] *= scalar; this->mm[2] *= scalar; this->mm[3] *= scalar; return *this; } /// Returns v0, where \f$v0_i *= v1_i\f$ for \f$i \in [0, 3]\f$ template const Vec4 &operator*=(const Vec4 &v1) { this->mm[0] *= v1[0]; this->mm[1] *= v1[1]; this->mm[2] *= v1[2]; this->mm[3] *= v1[3]; return *this; } /// Returns v, where \f$v_i /= scalar\f$ for \f$i \in [0, 3]\f$ template const Vec4 &operator/=(S scalar) { this->mm[0] /= scalar; this->mm[1] /= scalar; this->mm[2] /= scalar; this->mm[3] /= scalar; return *this; } /// Returns v0, where \f$v0_i /= v1_i\f$ for \f$i \in [0, 3]\f$ template const Vec4 &operator/=(const Vec4 &v1) { this->mm[0] /= v1[0]; this->mm[1] /= v1[1]; this->mm[2] /= v1[2]; this->mm[3] /= v1[3]; return *this; } /// Returns v, where \f$v_i += scalar\f$ for \f$i \in [0, 3]\f$ template const Vec4 &operator+=(S scalar) { this->mm[0] += scalar; this->mm[1] += scalar; this->mm[2] += scalar; this->mm[3] += scalar; return *this; } /// Returns v0, where \f$v0_i += v1_i\f$ for \f$i \in [0, 3]\f$ template const Vec4 &operator+=(const Vec4 &v1) { this->mm[0] += v1[0]; this->mm[1] += v1[1]; this->mm[2] += v1[2]; this->mm[3] += v1[3]; return *this; } /// Returns v, where \f$v_i += scalar\f$ for \f$i \in [0, 3]\f$ template const Vec4 &operator-=(S scalar) { this->mm[0] -= scalar; this->mm[1] -= scalar; this->mm[2] -= scalar; this->mm[3] -= scalar; return *this; } /// Returns v0, where \f$v0_i -= v1_i\f$ for \f$i \in [0, 3]\f$ template const Vec4 &operator-=(const Vec4 &v1) { this->mm[0] -= v1[0]; this->mm[1] -= v1[1]; this->mm[2] -= v1[2]; this->mm[3] -= v1[3]; return *this; } // Number of cols, rows, elements static unsigned numRows() { return 1; } static unsigned numColumns() { return 4; } static unsigned numElements() { return 4; } /// True if a Nan is present in vector bool isNan() const { return isnan(this->mm[0]) || isnan(this->mm[1]) || isnan(this->mm[2]) || isnan(this->mm[3]); } /// True if an Inf is present in vector bool isInfinite() const { return isinf(this->mm[0]) || isinf(this->mm[1]) || isinf(this->mm[2]) || isinf(this->mm[3]); } /// True if all no Nan or Inf values present bool isFinite() const { return finite(this->mm[0]) && finite(this->mm[1]) && finite(this->mm[2]) && finite(this->mm[3]); } /// Predefined constants, e.g. Vec4f v = Vec4f::xNegAxis(); static Vec4 zero() { return Vec4(0, 0, 0, 0); } static Vec4 origin() { return Vec4(0, 0, 0, 1); } }; /// Equality operator, does exact floating point comparisons template inline bool operator==(const Vec4 &v0, const Vec4 &v1) { return isExactlyEqual(v0[0], v1[0]) && isExactlyEqual(v0[1], v1[1]) && isExactlyEqual(v0[2], v1[2]) && isExactlyEqual(v0[3], v1[3]); } /// Inequality operator, does exact floating point comparisons template inline bool operator!=(const Vec4 &v0, const Vec4 &v1) { return !(v0==v1); } /// Returns V, where \f$V_i = v_i * scalar\f$ for \f$i \in [0, 3]\f$ template inline Vec4::type> operator*(S scalar, const Vec4 &v) { return v*scalar; } /// Returns V, where \f$V_i = v_i * scalar\f$ for \f$i \in [0, 3]\f$ template inline Vec4::type> operator*(const Vec4 &v, S scalar) { Vec4::type> result(v); result *= scalar; return result; } /// Returns V, where \f$V_i = v0_i * v1_i\f$ for \f$i \in [0, 3]\f$ template inline Vec4::type> operator*(const Vec4 &v0, const Vec4 &v1) { Vec4::type> result(v0[0]*v1[0], v0[1]*v1[1], v0[2]*v1[2], v0[3]*v1[3]); return result; } /// Returns V, where \f$V_i = scalar / v_i\f$ for \f$i \in [0, 3]\f$ template inline Vec4::type> operator/(S scalar, const Vec4 &v) { return Vec4::type>(scalar/v[0], scalar/v[1], scalar/v[2], scalar/v[3]); } /// Returns V, where \f$V_i = v_i / scalar\f$ for \f$i \in [0, 3]\f$ template inline Vec4::type> operator/(const Vec4 &v, S scalar) { Vec4::type> result(v); result /= scalar; return result; } /// Returns V, where \f$V_i = v0_i / v1_i\f$ for \f$i \in [0, 3]\f$ template inline Vec4::type> operator/(const Vec4 &v0, const Vec4 &v1) { Vec4::type> result(v0[0]/v1[0], v0[1]/v1[1], v0[2]/v1[2], v0[3]/v1[3]); return result; } /// Returns V, where \f$V_i = v0_i + v1_i\f$ for \f$i \in [0, 3]\f$ template inline Vec4::type> operator+(const Vec4 &v0, const Vec4 &v1) { Vec4::type> result(v0); result += v1; return result; } /// Returns V, where \f$V_i = v_i + scalar\f$ for \f$i \in [0, 3]\f$ template inline Vec4::type> operator+(const Vec4 &v, S scalar) { Vec4::type> result(v); result += scalar; return result; } /// Returns V, where \f$V_i = v0_i - v1_i\f$ for \f$i \in [0, 3]\f$ template inline Vec4::type> operator-(const Vec4 &v0, const Vec4 &v1) { Vec4::type> result(v0); result -= v1; return result; } /// Returns V, where \f$V_i = v_i - scalar\f$ for \f$i \in [0, 3]\f$ template inline Vec4::type> operator-(const Vec4 &v, S scalar) { Vec4::type> result(v); result -= scalar; return result; } /// @remark We are switching to a more explicit name because the semantics /// are different from std::min/max. In that case, the function returns a /// reference to one of the objects based on a comparator. Here, we must /// fabricate a new object which might not match either of the inputs. /// Return component-wise minimum of the two vectors. template inline Vec4 minComponent(const Vec4 &v1, const Vec4 &v2) { return Vec4( std::min(v1.x(), v2.x()), std::min(v1.y(), v2.y()), std::min(v1.z(), v2.z()), std::min(v1.w(), v2.w())); } /// Return component-wise maximum of the two vectors. template inline Vec4 maxComponent(const Vec4 &v1, const Vec4 &v2) { return Vec4( std::max(v1.x(), v2.x()), std::max(v1.y(), v2.y()), std::max(v1.z(), v2.z()), std::max(v1.w(), v2.w())); } typedef Vec4 Vec4i; typedef Vec4 Vec4ui; typedef Vec4 Vec4s; typedef Vec4 Vec4d; #if DWREAL_IS_DOUBLE == 1 typedef Vec4d Vec4f; #else typedef Vec4s Vec4f; #endif // DWREAL_IS_DOUBLE } // namespace math } // namespace OPENVDB_VERSION_NAME } // namespace openvdb #endif // OPENVDB_MATH_VEC4_HAS_BEEN_INCLUDED // Copyright (c) 2012-2013 DreamWorks Animation LLC // All rights reserved. This software is distributed under the // Mozilla Public License 2.0 ( http://www.mozilla.org/MPL/2.0/ )