make c++ more like glsl

Started by
6 comments, last by Nypyren 8 years, 1 month ago

if i have


struct vec3
{
float x;
float y;
float z;
};

how could i do something like

vec3 a;

vec3 b;

b = a.xy; ?

Advertisement

Here's a long discussion on that topic with a couple of possible solutions.

http://www.cplusplus.com/forum/general/72912/

But the bottom line is that there is no good way to do it in C++ without extending the language.

https://github.com/gwiazdorrr/CxxSwizzle

Naively, something like this:


vec3 xy(){
    vec3 v;
    v.x=x;
    v.y=y;
    v.z=0; // or whatever you want for a non-asked-for swizzle
    return v;
}

It'd be kind of tedious, but you could write out whatever swizzles you want as functions like that - there are only so many permutations for a 3D vector, and with a decent constructor defined, they would be one-liners.

In C#, this would probably be something I'd do with some read-only properties, which is effectively the same thing, just lets you do it without writing parentheses.

Eric Richards

SlimDX tutorials - http://www.richardssoftware.net/

Twitter - @EricRichards22

The library linked above provides an exact match so the following is but a humble exercise.

The prior discussions in the thread below also seemed to avoid the "naive" approach so I thought I'd give it the 'ol newbie try...

http://www.gamedev.net/topic/650045-vector-swizzling-in-c/



#include 
#include 
#include 
#include 

enum axis {
	x = 0, y = 1, z = 2
};

template< typename T >
class vec3
{
public:
	vec3(){}
	vec3(T in_x, T in_y, T in_z)
	{
		_values[0] = in_x;
		_values[1] = in_y;
		_values[2] = in_z;
	}
	vec3(const vec3 &in)
	{
		*this = in;
	}
	vec3& operator=(const vec3 &in)
	{
		if(this != &in) {
			_values[0] = in._values[0];
			_values[1] = in._values[1];
			_values[2] = in._values[2];
		}
		return *this;
	}
	T& operator[](axis in_a);
	const T& operator[](axis in_a) const;
	constexpr vec3< T > operator()(axis in_01, axis in_1, axis in_2) const;
private:
	T _values[3] {
		std::numeric_limits::quiet_NaN(),
		std::numeric_limits::quiet_NaN(),
		std::numeric_limits::quiet_NaN()
	};
};

template< typename T >
T& vec3< T >::operator[](axis in_a)
{
	return _values[static_cast< size_t >(in_a)];
}

template< typename T >
const T& vec3< T >::operator[](axis in_a) const
{
	return _values[static_cast< size_t >(in_a)];
}

template< typename T >
constexpr vec3< T > vec3< T >::operator()(axis in_0, axis in_1, axis in_2) const
{
	return vec3< T >(
		_values[in_0],
		_values[in_1],
		_values[in_2]
	);
}

template< typename T >
void vec3_print(const char *in_name, const vec3< T > &in_v)
{
	std::cout << in_name << "{"
		<< in_v[x] << ", "
		<< in_v[y]<< ", "
		<< in_v[z]<< " }\n"
	;
}

int main()
{
	typedef vec3< float > vec3f;

	vec3f v1{1.1f, 1.2f, 1.3f};
	vec3f v2{2.1f, 2.2f, 2.3f};
	vec3f v3;
	
	vec3_print("v1", v1);
	vec3_print("v2", v2);
	vec3_print("v3", v3);

	v1[x] = v2[y];
	v2[z] = v1[y];

	std::cout << "> v1[x] = v2[y]; v2[z] = v1[y];\n";
	
	vec3_print("v1", v1);
	vec3_print("v2", v2);

	v3[y] = v2[z];

	std::cout << "> v3[y] = v2[z];\n";

	vec3_print("v3", v3);

	vec3_print("> v3(y, z, x)\n", v3(y, z, x));

	vec3_print("v3", v3);

	v3 = v2(z, y, x);

	std::cout << "> v3 = v2(z, y, x);\n";
	
	vec3_print("v3", v3);
	vec3_print("v2", v2);
	
	return 0;
}

Naively, something like this:


vec3 xy(){
    vec3 v;
    v.x=x;
    v.y=y;
    v.z=0; // or whatever you want for a non-asked-for swizzle
    return v;
}

It'd be kind of tedious, but you could write out whatever swizzles you want as functions like that - there are only so many permutations for a 3D vector, and with a decent constructor defined, they would be one-liners.

In C#, this would probably be something I'd do with some read-only properties, which is effectively the same thing, just lets you do it without writing parentheses.

Honestly the function variety makes things eight thousand percent easier. That's what I did in my code, rather than play the ridiculous games required to get native-looking swizzles.

SlimDX | Ventspace Blog | Twitter | Diverse teams make better games. I am currently hiring capable C++ engine developers in Baltimore, MD.

I'm assuming here that storage is not an issue, IE, you will not be storing this vector directly into a file.

class Ref2Floats
{
Ref2Floats(float& r0, float& r1) { ref0= r0; ref1 = r1; }
float& ref0;
float& ref1;
Ref2Floats& operator=(Ref2Floats& a, const Ref2Floats& b) { a.ref0 = b.ref0; a.ref1 = b.ref1; return a; }

(add other operators)
};


in vector class:
class Vec3
{
float x;
float y;
float z;
Ref2Floats xy;
Ref2Floats xz;
Ref2Floats yz;

}
in vector constructor:
Vec3::Vec3(): xy(x, y), xz(x, z), yz(y, z)
{

Didn't actually test, but should work, but will increase memory use of each Vec3 instance. I've done stuff along the same vein to simplify some situations.

EDIT: Sorry, just realized I misunderstood what you were trying to do. I'll leave the code because you might also find it useful.

https://github.com/gwiazdorrr/CxxSwizzle


Good god that is some voodoo right there... I pity the compiler.

Comment from the code:


//! Array needs to be like a steak - the rawest possible
//! (Wow - I managed to WTF myself upon reading the above after a week or two)

This topic is closed to new replies.

Advertisement