pv3dではどうやってレンダリングしてるんだろう
と調べていたら
Face3Dにいきついた。
Face3D.renderに
var a1 :Number = this._a;
var b1 :Number = this._b;
var c1 :Number = this._c;
var d1 :Number = this._d;
var tx1 :Number = this._tx;
var ty1 :Number = this._ty;
var a2 :Number = x1 - x0;
var b2 :Number = y1 - y0;
var c2 :Number = x2 - x0;
var d2 :Number = y2 - y0;
var matrix :Matrix = _bitmapMatrix;
matrix.a = a1*a2 + b1*c2;
matrix.b = a1*b2 + b1*d2;
matrix.c = c1*a2 + d1*c2;
matrix.d = c1*b2 + d1*d2;
matrix.tx = tx1*a2 + ty1*c2 + x0;
matrix.ty = tx1*b2 + ty1*d2 + y0;
container.beginBitmapFill( texture, matrix, true, material.smooth );
という処理部分がある。
_a,_b,_c,_d,_tx,_ty
は
Face3D.transformUVであらかじめ計算されている。
x0,x1,x2,y0,y1,y2
は3つの頂点(vertices
)のx,y座標。
で、ここは結局なにをしているかというと
/ a1 b1 0 \
M0 = | c1 d1 0 |
\ tx1 ty1 1 /
/ a2 b2 0 \
M1 = | c2 d2 0 |
\ x0 y0 1 /
とした場合
M0 * M1
を計算した結果を、beginBitmapFillの引数に渡しているだけだ。
この M0 * M1
は
3つの頂点からなる三角形にビットマップを塗るための
変形を意味しているのだろう。
3つの頂点がobjectのx,y,z座標によって変化することで
三角形は変形する。
その変形に合わせて塗るビットマップを変形するために指定するのが
この行列ということだろう。
しかし
このM0,M1は
何を意味しているのだろうか。
M0はFace3D.transformUVを見ると
uvから行列をつくって
それを逆行列に変換している。
つまり
M0 * M1
は
実際には
なにかしらの行列の逆行列を
M1にかけていることになる。
どういうときに逆行列をかけるのか調べると
計算しやすいように
基本的な図形(例えば長方形なら正方形)に戻す
というときに使われることがあるようだ。
もしそうならば
M0は M1変換を行うための前準備にあたるのかもしれない。
そこで先にM1について考える。
三角形で基本的な図形というと
P0(0, 0), P1(0, 1), P2(1, 0)
の3点からなる直角二等辺三角形を
考えてみた。
/ a2 b2 0 \
M1 = | c2 d2 0 |
\ x0 y0 1 /
を詳しくかくと
/ x1 - x0 y1 - y0 0 \
M1 = | x2 - x0 y2 - y0 0 |
\ x0 y0 1 /
ということになる。
頂点P 3点にこのM1をかけるとどうなるか。
/ x1 - x0 y1 - y0 0 \
< 0 0 1 > * | x2 - x0 y2 - y0 0 |
\ x0 y0 1 /
= < x0 y0 1 >
/ x1 - x0 y1 - y0 0 \
< 1 0 1 > * | x2 - x0 y2 - y0 0 |
\ x0 y0 1 /
= < x1-x0+x0 y1-y0+y0 1 >
= < x1 y1 1 >
/ x1 - x0 y1 - y0 0 \
< 1 0 1 > * | x2 - x0 y2 - y0 0 |
\ x0 y0 1 /
= < x2-x0+x0 y2-y0+y0 1 >
= < x2 y2 1 >
となる。
これはつまり
M1は
P0(0, 0), P1(0, 1), P2(1, 0)
の3点からなる直角二等辺三角形を
Q0(x0, y0), Q1(x1, y1) Q2(x2, y2)
の任意の3点からなる三角形に変形する行列
ということになる。
では次に
M0は任意の三角形を
P0(0, 0), P1(0, 1), P2(1, 0)
に戻す変形を行っているのだろうか。
M1の逆行列は
Face3D.transformUVをみると
/ u1 - u0 v1 - v0 0 \
M0inv = | u2 - u0 v2 - v0 0 |
\ u0 v0 1 /
となっている。
(M1と同じ形だ)
u1,u2,u3
は
3つのuv
(三角形の3つの頂点のu,v値)
の
uにbitmap.widthを
vにbitmap.heightを
それぞれかけたものだ。
var w :Number = material.bitmap.width;
var h :Number = material.bitmap.height;
var u0 :Number = uv[0].u * w;
var v0 :Number = uv[0].v * h;
var u1 :Number = uv[1].u * w;
var v1 :Number = uv[1].v * h;
var u2 :Number = uv[2].u * w;
var v2 :Number = uv[2].v * h;
u,v
は0から1の値で
それにwidth,heightをかけることで
bitmapのどの位置とマップをとるかの
bitmap上の座標を得ることができる。
で
M1にM0invの逆行列をかけているということは
頂点P 3点からなる三角形に
M0inv変換を行うと
bitmap
(厳密にはbitmapを三角形にきりだした部分か?)
になる
ということを期待していることになる。
ここで例えば
10x10のビットマップがあって
それを対角線上に2つに分割し
B0(0,0), B1(10,0), B2(0,10)
からなる三角形を得た場合
それぞれのuvは
B0uv(0,0), B1uv(1,0), B2uv(0,1)
になるであろうから
これらにwidth,heightをかけて
M0invは M1と同じ形をしているので
頂点P 3点からなる直角二等辺三角形を
R0(0,0),R1(10,0),R2(0,10)
の3点からなる三角形へ変形する行列をあらわしていて
この三角形は
切り出したビットマップに一致する。
なるほど。
つまり
逆にいうと
uv値というのは
頂点P 3点からなる直角二等辺三角形から
もとのビットマップから切り出した三角形へ
復元できるような値を表している
ということか。