Skip to content

Instantly share code, notes, and snippets.

@TheMaverickProgrammer
Created September 7, 2018 14:07
Show Gist options
  • Save TheMaverickProgrammer/0c623551e14b0916dcf67d6b4b376ccd to your computer and use it in GitHub Desktop.
Save TheMaverickProgrammer/0c623551e14b0916dcf67d6b4b376ccd to your computer and use it in GitHub Desktop.
/******************************************************************************
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