diff --git a/include/vectorwrapper/vectorwrapper.hpp b/include/vectorwrapper/vectorwrapper.hpp index 8fc8482..ca4d983 100644 --- a/include/vectorwrapper/vectorwrapper.hpp +++ b/include/vectorwrapper/vectorwrapper.hpp @@ -104,9 +104,47 @@ namespace vwr { lower_vector_type yz ( void ) const; }; + template struct Vec4Demotion; + template struct Vec4Demotion {}; + template struct Vec4Demotion { + typedef Vec::lower_vector_type> lower_vector_type; + typedef typename VectorWrapperInfo::scalar_type scalar_type; + + static_assert(VectorWrapperInfo::lower_vector_type>::dimensions == 3, "Wrong demoted vector type"); + + lower_vector_type xyz ( void ) const; + lower_vector_type xyw ( void ) const; + lower_vector_type xzw ( void ) const; + lower_vector_type yzw ( void ) const; + }; + template struct VecAccessors; + template + struct VecAccessors : Vec4Demotion>::value> { + typedef typename VectorWrapperInfo::scalar_type scalar_type; + const Vec& xyzw ( void ) const { return *static_cast*>(this); } + const scalar_type& x ( void ) const; + const scalar_type& y ( void ) const; + const scalar_type& z ( void ) const; + const scalar_type& w ( void ) const; + scalar_type& x ( void ); + scalar_type& y ( void ); + scalar_type& z ( void ); + scalar_type& w ( void ); + +#if defined(VWR_EXTRA_ACCESSORS) + Vec xyz0 ( void ) const { return Vec(x(), y(), z(), scalar_type(0)); } + Vec xyz1 ( void ) const { return Vec(x(), y(), z(), scalar_type(1)); } + Vec x0zw ( void ) const { return Vec(x(), scalar_type(0), z(), w()); } + Vec x1zw ( void ) const { return Vec(x(), scalar_type(1), z(), w()); } + Vec _0yzw ( void ) const { return Vec(scalar_type(0), y(), z(), w()); } + Vec _1yzw ( void ) const { return Vec(scalar_type(1), y(), z(), w()); } + Vec wxyz ( void ) const { return Vec(w(), x(), y(), z()); } +#endif + }; + //Workaround for visual studio - VecAccessors should inherit from //both Vec3Promotion and Vec3Demotion, but when I do that, sizeof(Vec) //is wrong. I had to linearize the inheritance hierarchy so that the @@ -260,6 +298,37 @@ namespace vwr { Vec& operator= ( const vector_type& parOther ) { this->data() = parOther; return *this; } }; + template + class Vec : public implem::VecBase, public implem::VecAccessors { + static_assert(std::is_standard_layout>::value, "Base class must be a standard layout type"); + static_assert(std::is_standard_layout>::value, "Base class must be a standard layout type"); + public: + typedef typename implem::VecBase::scalar_type scalar_type; + typedef typename implem::VecBase::vector_type vector_type; + enum { + dimensions = 4 + }; + + static const Vec unit_x; + static const Vec unit_y; + static const Vec unit_z; + static const Vec unit_w; + + Vec ( void ) = default; + Vec ( const Vec& ) = default; + explicit Vec ( const vector_type& parIn ) : implem::VecBase(parIn) { } + explicit Vec ( const scalar_type parX ) : implem::VecBase(parX) { } + Vec ( scalar_type parX, scalar_type parY, scalar_type parZ, scalar_type parW ) : implem::VecBase(parX, parY, parZ, parW) { } +#if defined(VWR_WITH_IMPLICIT_CONVERSIONS) + template Vec ( const Vec& parOther ) { implem::assign(*this, parOther); } + template + Vec& operator= ( const Vec& parOther ) { return implem::assign(*this, parOther); } +#endif + + Vec& operator= ( const Vec& parOther ) { return implem::assign_same_type(*this, parOther); } + Vec& operator= ( const vector_type& parOther ) { this->data() = parOther; return *this; } + }; + template Vec mk_vec ( const V& parVec ); diff --git a/include/vectorwrapper/vectorwrapper.inl b/include/vectorwrapper/vectorwrapper.inl index be97a86..e0d3f8b 100644 --- a/include/vectorwrapper/vectorwrapper.inl +++ b/include/vectorwrapper/vectorwrapper.inl @@ -72,6 +72,30 @@ namespace vwr { return lower_vector_type(this_vec[1], this_vec[2]); } + template + auto Vec4Demotion::xyz() const -> lower_vector_type { + auto& this_vec = *static_cast*>(this); + return lower_vector_type(this_vec[0], this_vec[1], this_vec[2]); + } + + template + auto Vec4Demotion::xyw() const -> lower_vector_type { + auto& this_vec = *static_cast*>(this); + return lower_vector_type(this_vec[0], this_vec[1], this_vec[3]); + } + + template + auto Vec4Demotion::xzw() const -> lower_vector_type { + auto& this_vec = *static_cast*>(this); + return lower_vector_type(this_vec[0], this_vec[2], this_vec[3]); + } + + template + auto Vec4Demotion::yzw() const -> lower_vector_type { + auto& this_vec = *static_cast*>(this); + return lower_vector_type(this_vec[1], this_vec[2], this_vec[3]); + } + template auto Vec1Promotion::xn (const scalar_type& parN) const -> higher_vector_type { auto& this_vec = *static_cast*>(this); @@ -168,6 +192,54 @@ namespace vwr { return this_vec[2]; } + template + auto VecAccessors::x() -> scalar_type& { + auto& this_vec = *static_cast*>(this); + return this_vec[0]; + } + + template + auto VecAccessors::x() const -> const scalar_type& { + const auto& this_vec = *static_cast*>(this); + return this_vec[0]; + } + + template + auto VecAccessors::y() -> scalar_type& { + auto& this_vec = *static_cast*>(this); + return this_vec[1]; + } + + template + auto VecAccessors::y() const -> const scalar_type& { + const auto& this_vec = *static_cast*>(this); + return this_vec[1]; + } + + template + auto VecAccessors::z() -> scalar_type& { + auto& this_vec = *static_cast*>(this); + return this_vec[2]; + } + + template + auto VecAccessors::z() const -> const scalar_type& { + const auto& this_vec = *static_cast*>(this); + return this_vec[2]; + } + + template + auto VecAccessors::w() -> scalar_type& { + auto& this_vec = *static_cast*>(this); + return this_vec[3]; + } + + template + auto VecAccessors::w() const -> const scalar_type& { + const auto& this_vec = *static_cast*>(this); + return this_vec[3]; + } + template template offsets_array_wrapper::offsets_array_wrapper (const bt::number_seq&) : @@ -222,6 +294,10 @@ namespace vwr { template const Vec Vec::unit_x(scalar_type(1), scalar_type(0), scalar_type(0)); template const Vec Vec::unit_y(scalar_type(0), scalar_type(1), scalar_type(0)); template const Vec Vec::unit_z(scalar_type(0), scalar_type(0), scalar_type(1)); + template const Vec Vec::unit_x(scalar_type(1), scalar_type(0), scalar_type(0), scalar_type(0)); + template const Vec Vec::unit_y(scalar_type(0), scalar_type(1), scalar_type(0), scalar_type(0)); + template const Vec Vec::unit_z(scalar_type(0), scalar_type(0), scalar_type(1), scalar_type(0)); + template const Vec Vec::unit_w(scalar_type(0), scalar_type(0), scalar_type(0), scalar_type(1)); template Vec mk_vec (const V& parVec) {