名前のない構造を使用する:
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];
};
};
また、なぜヒープ上に構造を作成するのですか(「新規」を使用)?スタックに割り当てませんか?
編集:ああ、わかりました。まあ、それは間違いなく実行可能ですが、GLSLとの互換性をできるだけ多くしたい場合にのみ価値があります。アイデアは、各コンポーネントのバリエーションの参照を格納する「プロキシ」を作成することです。トレードオフは、8バイトのメモリを使用する代わりにvec2が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
単純に派生させるには、各コンポーネントバリエーションのメンバーを作成および構造化して宣言します(27は27、は64のみ)。vec2
vec3
proxy3
proxy4
vec3
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エミュレーションライブラリ(スウィズリングを含む)を思いつきました。それでも興味がある場合は、ご覧ください。