Created
September 7, 2018 14:07
-
-
Save TheMaverickProgrammer/0c623551e14b0916dcf67d6b4b376ccd to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/****************************************************************************** | |
Swizzling demonstration | |
by James King (TheMaverickProgrammer on Github) | |
Uses strings and overloaded [] operator. | |
Malformed strings throw exception. | |
Supports any number of vectors by always returning the | |
biggest vector. | |
Relies on assignment operators to trim the larger vectors | |
********************************************************************************/ | |
#include <iostream> | |
#include <string> | |
#include <algorithm> | |
using namespace std; | |
template<class T> | |
class Vector4 { | |
template<class Y> friend class Vector3; // And down to Vector1 | |
protected: | |
T* vals; | |
void init(T _x, T _y, T _z, T _w) { | |
vals[0] = _x; vals[1] = _y; vals[2] = _z; vals[3] = _w; | |
} | |
public: | |
Vector4(T _x, T _y, T _z, T _w) { | |
vals = new T[4]; | |
init(_x, _y, _z, _w); | |
} | |
Vector4() { | |
vals = new T[4]; | |
init(0,0,0,0); | |
} | |
~Vector4() { | |
delete[] vals; | |
} | |
Vector4<T>& operator=(const Vector4<T>& rhs) { | |
vals[0] = rhs.vals[0]; vals[1] = rhs.vals[1]; vals[2] = rhs.vals[2]; vals[3] = rhs.vals[3]; | |
return *this; | |
} | |
Vector4<T> operator[](const char* swizzle) { | |
return this->operator[](std::string(swizzle)); | |
} | |
Vector4<T> operator[](std::string swizzle) | |
{ | |
Vector4<T> result; | |
std::transform(swizzle.begin(), swizzle.end(), swizzle.begin(), ::tolower); | |
for(int i = 0; i < swizzle.size() && i < 4; i++) { | |
if(swizzle[i] == 'x') { | |
result.vals[i] = this->vals[0]; | |
} else if(swizzle[i] == 'y') { | |
result.vals[i] = this->vals[1]; | |
} else if(swizzle[i] == 'z') { | |
result.vals[i] = this->vals[2]; | |
} else if(swizzle[i] == 'w') { | |
result.vals[i] = this->vals[3]; | |
} else { | |
throw std::runtime_error("No vector column " + swizzle[i]); | |
} | |
} | |
return result; | |
} | |
friend ostream& operator<<(ostream& os, const Vector4<T>& v) { | |
os << "(" << v.vals[0] << ',' << v.vals[1] << ',' << v.vals[2] << "," << v.vals[3] << ")"; | |
return os; | |
} | |
}; | |
template<class T> | |
class Vector3 { | |
protected: | |
T* vals; | |
void init(T _x, T _y, T _z) { | |
vals[0] = _x; vals[1] = _y; vals[2] = _z; | |
} | |
public: | |
Vector3(T _x, T _y, T _z) { | |
vals = new T[3]; | |
init(_x, _y, _z); | |
} | |
Vector3() { | |
vals = new T[3]; | |
init(0, 0, 0); | |
} | |
~Vector3() { | |
delete[] vals; | |
} | |
Vector3<T>& operator=(const Vector3<T>& rhs) { | |
vals[0] = rhs.vals[0]; vals[1] = rhs.vals[1]; vals[2] = rhs.vals[2]; | |
return *this; | |
} | |
// Trim w | |
Vector3<T>& operator=(const Vector4<T>& rhs) { | |
vals[0] = rhs.vals[0]; vals[1] = rhs.vals[1]; vals[2] = rhs.vals[2]; | |
return *this; | |
} | |
Vector4<T> operator[](const char* swizzle) { | |
return this->operator[](std::string(swizzle)); | |
} | |
// Support all vector sizes by returning largest vector type | |
// Let the assignment operator deal with reading only what this vector | |
// needs | |
Vector4<T> operator[](std::string swizzle) | |
{ | |
Vector4<T> result; | |
std::transform(swizzle.begin(), swizzle.end(), swizzle.begin(), ::tolower); | |
for(int i = 0; i < swizzle.size() && i < 4; i++) { | |
if(swizzle[i] == 'x') { | |
result.vals[i] = this->vals[0]; | |
} else if(swizzle[i] == 'y') { | |
result.vals[i] = this->vals[1]; | |
} else if(swizzle[i] == 'z') { | |
result.vals[i] = this->vals[2]; | |
} else { | |
throw std::runtime_error(std::string("No vector column '") + swizzle[i] + "'"); | |
} | |
} | |
return result; | |
} | |
friend ostream& operator<<(ostream& os, const Vector3<T>& v) { | |
os << "(" << v.vals[0] << ',' << v.vals[1] << ',' << v.vals[2] << ")"; | |
return os; | |
} | |
}; | |
int main() | |
{ | |
Vector3<int> vec3(34, 12, 1); | |
Vector4<int> vec4; | |
vec4 = vec3["xxyy"]; | |
std::cout << "vec4 = vec3[\"xxyy\"];" << std::endl; | |
std::cout << "vec3 = " << vec3 << std::endl; | |
std::cout << "vec4 = " << vec4 << std::endl << "\n"; | |
vec4 = vec3["zzzzzzzz"]; | |
std::cout << "vec4 = vec3[\"zzzzzzzz\"];" << std::endl; | |
std::cout << "vec3 = " << vec3 << std::endl; | |
std::cout << "vec4 = " << vec4 << std::endl << "\n"; | |
try { | |
vec4 = vec3["abcdefg"]; | |
std::cout << "vec4 = vec3[\"abcdefg\"];" << std::endl; | |
std::cout << "vec3 = " << vec3 << std::endl; | |
std::cout << "vec4 = " << vec4 << std::endl << "\n"; | |
} catch(std::exception& e) { | |
std::cout << e.what() << std::endl; | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment