X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=simgear%2Fmath%2FSGVec4.hxx;h=f854274dd37bbae282d665665f8062897112ab48;hb=f7c6a5bfa2140c1d5ef54f3212067cd286e525f1;hp=e5607ccd2f2f3068964a16a743f45fc7e707cd66;hpb=75f817b39c693b2679ebc4b95bf554e65307c067;p=simgear.git diff --git a/simgear/math/SGVec4.hxx b/simgear/math/SGVec4.hxx index e5607ccd..f854274d 100644 --- a/simgear/math/SGVec4.hxx +++ b/simgear/math/SGVec4.hxx @@ -1,9 +1,75 @@ +// Copyright (C) 2006 Mathias Froehlich - Mathias.Froehlich@web.de +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// + #ifndef SGVec4_H #define SGVec4_H -/// 3D Vector Class +#include +#include + template -class SGVec4 { +struct SGVec4Storage { + /// Readonly raw storage interface + const T (&data(void) const)[4] + { return _data; } + /// Readonly raw storage interface + T (&data(void))[4] + { return _data; } + + void osg() const + { } + +private: + T _data[4]; +}; + +template<> +struct SGVec4Storage : public osg::Vec4f { + /// Access raw data by index, the index is unchecked + const float (&data(void) const)[4] + { return osg::Vec4f::_v; } + /// Access raw data by index, the index is unchecked + float (&data(void))[4] + { return osg::Vec4f::_v; } + + const osg::Vec4f& osg() const + { return *this; } + osg::Vec4f& osg() + { return *this; } +}; + +template<> +struct SGVec4Storage : public osg::Vec4d { + /// Access raw data by index, the index is unchecked + const double (&data(void) const)[4] + { return osg::Vec4d::_v; } + /// Access raw data by index, the index is unchecked + double (&data(void))[4] + { return osg::Vec4d::_v; } + + const osg::Vec4d& osg() const + { return *this; } + osg::Vec4d& osg() + { return *this; } +}; + +/// 4D Vector Class +template +class SGVec4 : protected SGVec4Storage { public: typedef T value_type; @@ -16,75 +82,86 @@ public: /// uninitialized values in the debug build very fast ... #ifndef NDEBUG for (unsigned i = 0; i < 4; ++i) - _data[i] = SGLimits::quiet_NaN(); + data()[i] = SGLimits::quiet_NaN(); #endif } /// Constructor. Initialize by the given values SGVec4(T x, T y, T z, T w) - { _data[0] = x; _data[1] = y; _data[2] = z; _data[3] = w; } + { data()[0] = x; data()[1] = y; data()[2] = z; data()[3] = w; } /// Constructor. Initialize by the content of a plain array, /// make sure it has at least 3 elements explicit SGVec4(const T* d) - { _data[0] = d[0]; _data[1] = d[1]; _data[2] = d[2]; _data[3] = d[3]; } + { data()[0] = d[0]; data()[1] = d[1]; data()[2] = d[2]; data()[3] = d[3]; } + explicit SGVec4(const osg::Vec4f& d) + { data()[0] = d[0]; data()[1] = d[1]; data()[2] = d[2]; data()[3] = d[3]; } + explicit SGVec4(const osg::Vec4d& d) + { data()[0] = d[0]; data()[1] = d[1]; data()[2] = d[2]; data()[3] = d[3]; } + explicit SGVec4(const SGVec3& v3, const T& v4 = 0) + { data()[0] = v3[0]; data()[1] = v3[1]; data()[2] = v3[2]; data()[3] = v4; } /// Access by index, the index is unchecked const T& operator()(unsigned i) const - { return _data[i]; } + { return data()[i]; } /// Access by index, the index is unchecked T& operator()(unsigned i) - { return _data[i]; } + { return data()[i]; } + + /// Access raw data by index, the index is unchecked + const T& operator[](unsigned i) const + { return data()[i]; } + /// Access raw data by index, the index is unchecked + T& operator[](unsigned i) + { return data()[i]; } /// Access the x component const T& x(void) const - { return _data[0]; } + { return data()[0]; } /// Access the x component T& x(void) - { return _data[0]; } + { return data()[0]; } /// Access the y component const T& y(void) const - { return _data[1]; } + { return data()[1]; } /// Access the y component T& y(void) - { return _data[1]; } + { return data()[1]; } /// Access the z component const T& z(void) const - { return _data[2]; } + { return data()[2]; } /// Access the z component T& z(void) - { return _data[2]; } + { return data()[2]; } /// Access the x component const T& w(void) const - { return _data[3]; } + { return data()[3]; } /// Access the x component T& w(void) - { return _data[3]; } + { return data()[3]; } + /// Get the data pointer + using SGVec4Storage::data; - /// Get the data pointer, usefull for interfacing with plib's sg*Vec - const T* data(void) const - { return _data; } - /// Get the data pointer, usefull for interfacing with plib's sg*Vec - T* data(void) - { return _data; } - - /// Readonly interface function to ssg's sgVec3/sgdVec3 + /// Readonly interface function to ssg's sgVec4/sgdVec4 const T (&sg(void) const)[4] - { return _data; } - /// Interface function to ssg's sgVec3/sgdVec3 + { return data(); } + /// Interface function to ssg's sgVec4/sgdVec4 T (&sg(void))[4] - { return _data; } + { return data(); } + + /// Interface function to osg's Vec4* + using SGVec4Storage::osg; /// Inplace addition SGVec4& operator+=(const SGVec4& v) - { _data[0]+=v(0);_data[1]+=v(1);_data[2]+=v(2);_data[3]+=v(3);return *this; } + { data()[0]+=v(0);data()[1]+=v(1);data()[2]+=v(2);data()[3]+=v(3);return *this; } /// Inplace subtraction SGVec4& operator-=(const SGVec4& v) - { _data[0]-=v(0);_data[1]-=v(1);_data[2]-=v(2);_data[3]-=v(3);return *this; } + { data()[0]-=v(0);data()[1]-=v(1);data()[2]-=v(2);data()[3]-=v(3);return *this; } /// Inplace scalar multiplication template SGVec4& operator*=(S s) - { _data[0] *= s; _data[1] *= s; _data[2] *= s; _data[3] *= s; return *this; } + { data()[0] *= s; data()[1] *= s; data()[2] *= s; data()[3] *= s; return *this; } /// Inplace scalar multiplication by 1/s template SGVec4& operator/=(S s) @@ -102,10 +179,6 @@ public: { return SGVec4(0, 0, 1, 0); } static SGVec4 e4(void) { return SGVec4(0, 0, 0, 1); } - -private: - /// The actual data - T _data[4]; }; /// Unary +, do nothing ... @@ -150,6 +223,70 @@ SGVec4 operator*(const SGVec4& v, S s) { return SGVec4(s*v(0), s*v(1), s*v(2), s*v(3)); } +/// component wise min +template +inline +SGVec4 +min(const SGVec4& v1, const SGVec4& v2) +{ + return SGVec4(SGMisc::min(v1(0), v2(0)), + SGMisc::min(v1(1), v2(1)), + SGMisc::min(v1(2), v2(2)), + SGMisc::min(v1(3), v2(3))); +} +template +inline +SGVec4 +min(const SGVec4& v, S s) +{ + return SGVec4(SGMisc::min(s, v(0)), + SGMisc::min(s, v(1)), + SGMisc::min(s, v(2)), + SGMisc::min(s, v(3))); +} +template +inline +SGVec4 +min(S s, const SGVec4& v) +{ + return SGVec4(SGMisc::min(s, v(0)), + SGMisc::min(s, v(1)), + SGMisc::min(s, v(2)), + SGMisc::min(s, v(3))); +} + +/// component wise max +template +inline +SGVec4 +max(const SGVec4& v1, const SGVec4& v2) +{ + return SGVec4(SGMisc::max(v1(0), v2(0)), + SGMisc::max(v1(1), v2(1)), + SGMisc::max(v1(2), v2(2)), + SGMisc::max(v1(3), v2(3))); +} +template +inline +SGVec4 +max(const SGVec4& v, S s) +{ + return SGVec4(SGMisc::max(s, v(0)), + SGMisc::max(s, v(1)), + SGMisc::max(s, v(2)), + SGMisc::max(s, v(3))); +} +template +inline +SGVec4 +max(S s, const SGVec4& v) +{ + return SGVec4(SGMisc::max(s, v(0)), + SGMisc::max(s, v(1)), + SGMisc::max(s, v(2)), + SGMisc::max(s, v(3))); +} + /// Scalar dot product template inline @@ -179,6 +316,13 @@ T norm1(const SGVec4& v) { return fabs(v(0)) + fabs(v(1)) + fabs(v(2)) + fabs(v(3)); } +/// The inf-norm of the vector +template +inline +T +normI(const SGVec4& v) +{ return SGMisc::max(fabs(v(0)), fabs(v(1)), fabs(v(2)), fabs(v(2))); } + /// The euclidean norm of the vector, that is what most people call length template inline @@ -200,6 +344,47 @@ bool operator!=(const SGVec4& v1, const SGVec4& v2) { return ! (v1 == v2); } +/// Return true if smaller, good for putting that into a std::map +template +inline +bool +operator<(const SGVec4& v1, const SGVec4& v2) +{ + if (v1(0) < v2(0)) return true; + else if (v2(0) < v1(0)) return false; + else if (v1(1) < v2(1)) return true; + else if (v2(1) < v1(1)) return false; + else if (v1(2) < v2(2)) return true; + else if (v2(2) < v1(2)) return false; + else return (v1(3) < v2(3)); +} + +template +inline +bool +operator<=(const SGVec4& v1, const SGVec4& v2) +{ + if (v1(0) < v2(0)) return true; + else if (v2(0) < v1(0)) return false; + else if (v1(1) < v2(1)) return true; + else if (v2(1) < v1(1)) return false; + else if (v1(2) < v2(2)) return true; + else if (v2(2) < v1(2)) return false; + else return (v1(3) <= v2(3)); +} + +template +inline +bool +operator>(const SGVec4& v1, const SGVec4& v2) +{ return operator<(v2, v1); } + +template +inline +bool +operator>=(const SGVec4& v1, const SGVec4& v2) +{ return operator<=(v2, v1); } + /// Return true if equal to the relative tolerance tol template inline @@ -224,6 +409,20 @@ equivalent(const SGVec4& v1, const SGVec4& v2) return equivalent(v1, v2, tol, tol); } +/// The euclidean distance of the two vectors +template +inline +T +dist(const SGVec4& v1, const SGVec4& v2) +{ return norm(v1 - v2); } + +/// The squared euclidean distance of the two vectors +template +inline +T +distSqr(const SGVec4& v1, const SGVec4& v2) +{ SGVec4 tmp = v1 - v2; return dot(tmp, tmp); } + #ifndef NDEBUG template inline @@ -242,14 +441,10 @@ std::basic_ostream& operator<<(std::basic_ostream& s, const SGVec4& v) { return s << "[ " << v(0) << ", " << v(1) << ", " << v(2) << ", " << v(3) << " ]"; } -/// Two classes doing actually the same on different types -typedef SGVec4 SGVec4f; -typedef SGVec4 SGVec4d; - inline SGVec4f toVec4f(const SGVec4d& v) -{ return SGVec4f(v(0), v(1), v(2), v(3)); } +{ return SGVec4f((float)v(0), (float)v(1), (float)v(2), (float)v(3)); } inline SGVec4d