画像の無限平面化
テクスチャなどに使う画像は有限の大きさを持つが、これを無限平面として扱えるようになると便利だ。
たとえば画像の任意のピクセルを参照するときX,Yでその位置を指定するが、X,Yの範囲値はそれぞれ
0 <= X < Width, 0 <= Y < Height (Width:画像の幅,Height:画像の高さ)
になる。
この範囲を超えてアクセスした場合、エラーとなってしまう。
画像を無限の空間を持つものとして処理できるようになれば、任意のX,Yでもアクセスできる。
これには任意のX,Yを画像の幅、高さに収める処理が必要となる。これをコレスポンダと呼ぶ。
コレスポンダには以下のようなものが挙げられる。
・リピート:繰り返す
・ミラー:端で折り返す
・クランプ:端を超えていたら端の値とする
コレスポンダは任意の位置xと幅wから0 <= x' < w になる値x'を返す関数が定義できればいよい。
上記のリピート、ミラー、クランプについては以下のよう定義できる。
int correspond_repeat (int x, int w){ int n = x%w; if(n>=0)return n; else return n+w; } int correspond_mirror (int x, int w){ if(x<0){x = -x-1;} int s = (x/w)&1; int n = correspond_repeat(x,w); if(s) return w-1-n; else return n; } int correspond_clamp (int x, int w){ if(x<0)return 0; if(w-1<x)return w-1; return x; }
さらに幅wが2の累乗であったときリピートとミラーは高速化できる。
bool is_powerof2(unsigned int x){ return ((x-1)&x)==0; }
int correspond_repeat_powerof2(int x, int w){ assert(is_powerof2(w));//w is 2x int n = x&(w-1);// rem return n; } int correspond_mirror_powerof2(int x, int w){ assert(is_powerof2(w));//w is 2x int n = x&(w-1); if(x&w) return w-1-n; else return n; }
あとは画像の参照にコレスポンダを埋め込んであげればよい。
template<class T> class repeaet_image:public image<T>{ public: T get(int x, int y){ x = correspond_repeat(x,get_width()); y = correspond_repeat(y,get_height()); return img->get(x,y);//内部のイメージにアクセス } //略 };