Войти
ПрограммированиеПодсказкиОбщее

Swizzle средствами C++

Внимание! Этот документ ещё не опубликован.

Автор:

Можно ли использовать в C++ swizzle так же, как это сделано в шейдерных языках?
Почему бы и нет.

struct vec2;

template<uint I1,uint I2>
struct vec2_swizz
{
  float    raw[2];

  vec2 operator = (const vec2 &V);

  operator vec2() const;
};

struct vec2
{
  union
  {
    struct
    {
      float  x,y;
    };
    vec2_swizz<0,0>    xx;
    vec2_swizz<0,1>    xy;
    vec2_swizz<1,0>    yx;
    vec2_swizz<1,1>    yy;
  };

  vec2(){}
  vec2(float X,float Y):x(X),y(Y){}
};

template<uint I1,uint I2>
vec2 vec2_swizz<I1,I2>::operator = (const vec2 &V)
{
  raw[I1] = V.x;
  raw[I2] = V.y;

  return V;
}

template<uint I1,uint I2>
vec2_swizz<I1,I2>::operator vec2() const
{
  return vec2(raw[I1],raw[I2]);
}

После этого можно пользоваться так

vec2  a(3,4);
vec2  b(0,0);

b.yx = a.xx;

Действительно, иногда это бывает очень удобно.

И завершая тему свизла.
Чтобы не писать вручную все комбинации, можно воспользоваться макросом:

#define DECLARE_XYZW(ix,iy,iz,iw,x,y,z,w)  vec4_swizz<ix,iy,iz,iw>   x##y##z##w;
#define DECLARE_XYZ(ix,iy,iz,x,y,z)        vec3_swizz<ix,iy,iz>      x##y##z;
#define DECLARE_XY(ix,iy,x,y)              vec2_swizz<ix,iy>         x##y;

#define DECLARE_V2     \
  DECLARE_XY(0,0,x,x)  \
  DECLARE_XY(0,1,x,y)  \
  DECLARE_XY(1,0,y,x)  \
  DECLARE_XY(1,1,y,y)

#define DECLARE_V3_YZ(iy,iz,sy,sz)  \
  DECLARE_XYZ(0,iy,iz,x,sy,sz)      \
  DECLARE_XYZ(1,iy,iz,y,sy,sz)      \
  DECLARE_XYZ(2,iy,iz,z,sy,sz)
#define DECLARE_V3_Z(iz,sz)         \
  DECLARE_V3_YZ(0,iz,x,sz)          \
  DECLARE_V3_YZ(1,iz,y,sz)          \
  DECLARE_V3_YZ(2,iz,z,sz)
#define DECLARE_V3        \
  DECLARE_V3_Z(0,x)       \
  DECLARE_V3_Z(1,y)       \
  DECLARE_V3_Z(2,z)

#define DECLARE_V4_YZW(iy,iz,iw,sy,sz,sw)  \
  DECLARE_XYZW(0,iy,iz,iw,x,sy,sz,sw)      \
  DECLARE_XYZW(1,iy,iz,iw,y,sy,sz,sw)      \
  DECLARE_XYZW(2,iy,iz,iw,z,sy,sz,sw)      \
  DECLARE_XYZW(3,iy,iz,iw,w,sy,sz,sw)
#define DECLARE_V4_ZW(iz,iw,sz,sw)         \
  DECLARE_V4_YZW(0,iz,iw,x,sz,sw)          \
  DECLARE_V4_YZW(1,iz,iw,y,sz,sw)          \
  DECLARE_V4_YZW(2,iz,iw,z,sz,sw)          \
  DECLARE_V4_YZW(3,iz,iw,w,sz,sw)
#define DECLARE_V4_W(iw,sw)     \
  DECLARE_V4_ZW(0,iw,x,sw)      \
  DECLARE_V4_ZW(1,iw,y,sw)      \
  DECLARE_V4_ZW(2,iw,z,sw)      \
  DECLARE_V4_ZW(3,iw,w,sw)
#define DECLARE_V4              \
  DECLARE_V4_W(0,x)             \
  DECLARE_V4_W(1,y)             \
  DECLARE_V4_W(2,z)             \
  DECLARE_V4_W(3,w)

И потом использовать так:

struct vec4
{
  union
  {
    struct
    {
      float  x,y,z,w;
    };
    DECLARE_V2;
    DECLARE_V3;
    DECLARE_V4;
  };

...

#C++, #swizzle

23 марта 2010