使用未命名的结构:
union Vector
{
struct
{
float x;
float y;
float z;
};
float xyz[3];
};
然后您可以访问组件而无需隐式引用包含结构:
int main()
{
Vector* vec = new Vector();
vec->x = 50;
vec->y = 30;
vec->xyz[2] = vec->xyz[0] + vec->xyz[1]; // vec->z == 80
delete vec;
return 0;
}
当然,你可以用另一个结构/类包装这个联合,达到同样的效果:
class MyClass
{
public:
union
{
struct
{
float x;
float y;
float z;
};
float xyz[3];
};
};
另外,为什么要在堆上创建结构(使用“new”)?不会在堆栈上分配吗?
编辑:哦,我明白了。好吧,这绝对是可行的,但只有在您希望尽可能多地与 GLSL 兼容时才值得。这个想法是创建一个“代理”来存储每个组件变体的引用。权衡是 vec2,而不是占用 8 个字节的内存将占用 40 个字节。对于 vec3 和 vec4 显然会变得更糟
class vec2
{
// private proxy, auto-convertible into vec2
struct proxy2
{
// store references, not values!
proxy2(float &x, float &y) : x(x), y(y) {}
// implicit conversion to vec2
operator vec2() { return vec2(x, y); }
// support assignments from vec2
proxy2& operator=(const vec2& vec)
{
x = vec.x;
y = vec.y;
return *this;
}
private:
// hide copy and assignment operators
proxy2(const proxy2&);
proxy2& operator=(const proxy2&);
// hide member variables
float& x;
float& y;
};
public:
vec2(float _x, float _y)
: x(_x), y(_y)
, xx(x, x), xy(x, y), yx(y, x), yy(y, y)
{}
vec2(const vec2& vec)
: x(vec.x), y(vec.y)
, xx(x, x), xy(x, y), yx(y, x) , yy(y, y)
{}
float x;
float y;
proxy2 xx;
proxy2 xy;
proxy2 yx;
proxy2 yy;
};
通过这个类,您可以获得非常接近 GLSL 提供的语法:
vec2 v(1.0f, 2.0f);
vec2 vxx = v.xx; // 1, 1
vec2 vyx = v.yx; // 2, 1
vec2 vxy = v.xy; // 1, 2
vec2 vyy = v.yy; // 2, 2
v.yx = vec2(3, 4); // 4, 3
v.y = 5; // 4, 5
vec2::proxy2 proxy = v.xx; // compile error
v.xx = vec2::proxy2(v.x, v.y); // compile error
要将其扩展为支持vec3
并vec4
简单地从vec2
和派生vec3
,请为每个组件变体创建proxy3
和proxy4
构造并声明成员(27vec3
个,仅 64 个vec4
)。
EDIT2:新版本,根本不占用额外空间。再次,工会来救援!转换proxy2
为模板并添加与vec2
组件匹配的数据成员,您可以安全地将其放入联合中。
class vec2
{
// private proxy, auto-convertible into vec2
template <int x, int y>
struct proxy2
{
// implicit conversion to vec2
operator vec2()
{
return vec2(arr[x], arr[y]);
}
// support assignments from vec2
proxy2& operator=(const vec2& vec)
{
arr[x] = vec.x;
arr[y] = vec.y;
return *this;
}
private:
float arr[2];
};
public:
vec2(float _x, float _y)
: x(_x), y(_y)
{}
vec2(const vec2& vec)
: x(vec.x), y(vec.y)
{}
union
{
struct
{
float x;
float y;
};
proxy2<0, 0> xx;
proxy2<0, 1> xy;
proxy2<1, 0> yx;
proxy2<1, 1> yy;
};
};
希望这就是你所追求的。
EDIT3:我花了一段时间,但我想出了一个有效的 GLSL 仿真库(包括 swizzling),让您无需修改即可运行片段着色器。如果你仍然感兴趣,你应该看看。