From 2851081b66ef1914c9b69967a213c124f7868ea0 Mon Sep 17 00:00:00 2001 From: athile Date: Wed, 21 Sep 2011 16:49:42 -0400 Subject: [PATCH] Incremental work on improving swizzles. --- glm/core/_swizzle.hpp | 119 +++++++++++++++++++++++++++++------ test/core/core_type_vec3.cpp | 22 ++++--- 2 files changed, 115 insertions(+), 26 deletions(-) diff --git a/glm/core/_swizzle.hpp b/glm/core/_swizzle.hpp index 498d026f..b8bd3fff 100644 --- a/glm/core/_swizzle.hpp +++ b/glm/core/_swizzle.hpp @@ -56,21 +56,24 @@ namespace detail /*! Template parameters: - Type = type of scalar values (e.g. float, double) - Class = class the swizzle is applies to (e.g. vector3f) + ValueType = type of scalar values (e.g. float, double) + VecType = class the swizzle is applies to (e.g. vector3f) N = number of components in the vector (e.g. 3) E0...3 = what index the n-th element of this swizzle refers to */ - template + template struct swizzle_base { - typedef Derived derived_type; + typedef DerivedType derived_type; + typedef VecType vec_type; + typedef ValueType value_type; - swizzle_base& operator= (const Class& that) + swizzle_base& operator= (const VecType& that) { static const int offset_dst[4] = { E0, E1, E2, E3 }; - Type t[N]; + // Make a copy of the data in this == &that + ValueType t[N]; for (int i = 0; i < N; ++i) t[i] = that[i]; for (int i = 0; i < N; ++i) @@ -79,7 +82,7 @@ namespace detail return *this; } - swizzle_base& operator= (const Type& t) + swizzle_base& operator= (const ValueType& t) { static const int offset_dst[4] = { E0, E1, E2, E3 }; @@ -89,34 +92,80 @@ namespace detail return *this; } + void operator -= (const VecType& that) + { + static const int offset_dst[4] = { E0, E1, E2, E3 }; + + ValueType t[N]; + for (int i = 0; i < N; ++i) + t[i] = that[i]; + for (int i = 0; i < N; ++i) + elem(offset_dst[i]) -= t[i]; + } + + void operator += (const VecType& that) + { + static const int offset_dst[4] = { E0, E1, E2, E3 }; + + ValueType t[N]; + for (int i = 0; i < N; ++i) + t[i] = that[i]; + for (int i = 0; i < N; ++i) + elem(offset_dst[i]) += t[i]; + } + + void operator *= (const VecType& that) + { + static const int offset_dst[4] = { E0, E1, E2, E3 }; + + ValueType t[N]; + for (int i = 0; i < N; ++i) + t[i] = that[i]; + for (int i = 0; i < N; ++i) + elem(offset_dst[i]) *= t[i]; + } + + void operator /= (const VecType& that) + { + static const int offset_dst[4] = { E0, E1, E2, E3 }; + + ValueType t[N]; + for (int i = 0; i < N; ++i) + t[i] = that[i]; + for (int i = 0; i < N; ++i) + elem(offset_dst[i]) /= t[i]; + } + protected: - Type& elem (size_t i) { return (reinterpret_cast(_buffer))[i]; } - const Type& elem (size_t i) const { return (reinterpret_cast(_buffer))[i]; } + value_type& elem (size_t i) { return (reinterpret_cast(_buffer))[i]; } + const value_type& elem (size_t i) const { return (reinterpret_cast(_buffer))[i]; } // Use an opaque buffer to *ensure* the compiler doesn't call a constructor. // Otherwise, a vec4 containing all swizzles might end up with 1000s of // constructor calls - char _buffer[sizeof(Type) * N]; + char _buffer[sizeof(value_type) * N]; }; - template - struct swizzle_base + template + struct swizzle_base { - typedef Derived derived_type; + typedef DerivedType derived_type; + typedef VecType vec_type; + typedef ValueType value_type; struct Stub {}; swizzle_base& operator= (const Stub& that) {} protected: - Type& elem (size_t i) { return (reinterpret_cast(_buffer))[i]; } - const Type& elem (size_t i) const { return (reinterpret_cast(_buffer))[i]; } + value_type& elem (size_t i) { return (reinterpret_cast(_buffer))[i]; } + const value_type& elem (size_t i) const { return (reinterpret_cast(_buffer))[i]; } - char _buffer[sizeof(Type) * N]; + char _buffer[sizeof(value_type) * N]; }; //! Internal class for implementing swizzle operators template - struct swizzle2 : public swizzle_base, T,P,2,E0,E1,0,0,(E0 == E1)> + struct swizzle2 : public swizzle_base,T,P,2,E0,E1,0,0,(E0 == E1)> { using swizzle_base,T,P,2,E0,E1,0,0,(E0 == E1)>::operator=; P cast() const { return P(this->elem(E0), this->elem(E1)); } @@ -221,15 +270,49 @@ namespace detail return a OPERAND static_cast(b).cast(); \ } +#define _GLM_SWIZZLE_SCALAR_BINARY_OPERATOR_IMPLEMENTATION(OPERAND)\ + template \ + typename P operator OPERAND ( \ + const glm::detail::swizzle_base& a, \ + const typename T& b) \ + { \ + return static_cast(a).cast() OPERAND b; \ + } \ + \ + template \ + typename P operator OPERAND ( \ + const typename T& a, \ + const glm::detail::swizzle_base& b) \ + { \ + return a OPERAND static_cast(b).cast(); \ + } + +// +// To prevent the C++ syntax from getting *completely* overwhelming, define some alias macros +// +#define _GLM_SWIZZLE_TEMPLATE1 template +#define _GLM_SWIZZLE_TEMPLATE2 template +#define _GLM_SWIZZLE_TYPE1 glm::detail::swizzle_base +#define _GLM_SWIZZLE_TYPE2 glm::detail::swizzle_base + + _GLM_SWIZZLE_TEMPLATE1 typename S0::vec_type operator- (typename S0::value_type a, const _GLM_SWIZZLE_TYPE1& b) { return a - b; } + _GLM_SWIZZLE_BINARY_OPERATOR_IMPLEMENTATION(+) _GLM_SWIZZLE_BINARY_OPERATOR_IMPLEMENTATION(-) _GLM_SWIZZLE_BINARY_OPERATOR_IMPLEMENTATION(*) _GLM_SWIZZLE_BINARY_OPERATOR_IMPLEMENTATION(/) + _GLM_SWIZZLE_SCALAR_BINARY_OPERATOR_IMPLEMENTATION(*) + }//namespace detail }//namespace glm - +namespace glm +{ + /*_GLM_SWIZZLE_TEMPLATE2 typename S0::value_type dot (const _GLM_SWIZZLE_TYPE1& a, const _GLM_SWIZZLE_TYPE2& b) { return dot(a.cast(), b.cast()); } + _GLM_SWIZZLE_TEMPLATE1 typename S0::value_type dot (const _GLM_SWIZZLE_TYPE1& a, const typename S0::vec_type& b) { return dot(a.cast(), b); } + _GLM_SWIZZLE_TEMPLATE1 typename S0::value_type dot (const typename S0::vec_type& a, const _GLM_SWIZZLE_TYPE1& b) { return dot(a, b.cast()); }*/ +} #define _GLM_SWIZZLE2_2_MEMBERS(T,P,E0,E1) \ diff --git a/test/core/core_type_vec3.cpp b/test/core/core_type_vec3.cpp index b08b0c62..c4617582 100644 --- a/test/core/core_type_vec3.cpp +++ b/test/core/core_type_vec3.cpp @@ -239,14 +239,20 @@ vec4 grad4(float j, vec4 ip) const vec4 ones = vec4(1.0, 1.0, 1.0, -1.0); vec4 p,s; - p.xyz = floor( fract (vec3(j) * ip.xyz) * 7.0) * ip.z - 1.0; - p.w = 1.5 - dot(abs(p.xyz), ones.xyz); + auto t1 = abs(p.xyz); + auto t2 = ones.xyz; + auto t3 = dot(t1, t2); + auto t0 = dot(abs(p.xyz), ones.xyz); + + p.xyz = floor( fract (vec3(j) * ip.xyz) * 7.0f) * ip.z - 1.0f; + p.w = 1.5f - dot(abs(p.xyz), ones.xyz); s = vec4(lessThan(p, vec4(0.0))); - p.xyz = p.xyz + (s.xyz*2.0 - 1.0) * s.www; + p.xyz = p.xyz + (s.xyz*2.0f - 1.0f) * s.www; return p; } + float snoise(vec4 v) { const vec4 C = vec4( 0.138196601125011, // (5 - sqrt(5))/20 G4 @@ -269,12 +275,12 @@ float snoise(vec4 v) vec3 isYZ = step( x0.zww, x0.yyz ); // i0.x = dot( isX, vec3( 1.0 ) ); i0.x = isX.x + isX.y + isX.z; - i0.yzw = 1.0 - isX; + i0.yzw = 1.0f - isX; // i0.y += dot( isYZ.xy, vec2( 1.0 ) ); i0.y += isYZ.x + isYZ.y; - i0.zw += 1.0 - isYZ.xy; + i0.zw += 1.0f - isYZ.xy; i0.z += isYZ.z; - i0.w += 1.0 - isYZ.z; + i0.w += 1.0f - isYZ.z; // i0 now contains the unique values 0,1,2,3 in each channel vec4 i3 = clamp( i0, 0.0, 1.0 ); @@ -319,8 +325,8 @@ float snoise(vec4 v) p4 *= taylorInvSqrt(dot(p4,p4)); // Mix contributions from the five corners - vec3 m0 = max(0.6 - vec3(dot(x0,x0), dot(x1,x1), dot(x2,x2)), 0.0); - vec2 m1 = max(0.6 - vec2(dot(x3,x3), dot(x4,x4) ), 0.0); + vec3 m0 = max(0.6f - vec3(dot(x0,x0), dot(x1,x1), dot(x2,x2)), 0.0); + vec2 m1 = max(0.6f - vec2(dot(x3,x3), dot(x4,x4) ), 0.0); m0 = m0 * m0; m1 = m1 * m1; return 49.0 * ( dot(m0*m0, vec3( dot( p0, x0 ), dot( p1, x1 ), dot( p2, x2 )))