2008/05/19(月)Direct3D Sprite の罠
この間のDirectSoundといい、DirectXには罠がいっぱい。
回転とか拡大縮小とか簡単にやりたいなーと思ってDraw2Dを使ってみるもどうも直感的じゃない(個人的に)。
そう、これ描画先座標が拡縮回転前指定なんですよね。
つまり、平行移動、拡大縮小、回転 の順番。
どっちかと言えば、2倍に拡大したものをどこどこへって指定したいけど、↑だと描画先に1/2しなきゃいけないし。その上、Viewport+Transformで原点自由に変えられてこりゃいいやーとか思ってたら、ちょっとちょっと、Draw2DたんはTransform弄っちゃうじゃないですか!
Draw2Dはつかえねー……。とゆーかかなり使いにくい。こりゃもー自前でTransformするしかないよねー。
でも行列って計算コスト高いしなぁ……、そもそも、どこを描画時のパラメータにしてどこを描画前に予め与えておくのよ。前が見えなくて先週一週間ずっと胃を痛めていた。とか
今日あらためて、結局やらないかんことって何? と整理してみる。
チップ単位での 拡大縮小・回転・平行移動。そしてViewport+原点弄くるための、平行移動……
あれ、これローカル座標系とワールド座標系の行列計算してるだけじゃーん! ってことに気づく。
ついでに、計算コストの高い行列同士の計算は、予め手計算してみたら案外すっきり。
というわけで、今日やったこと。
拡縮→回転→平行移動 の順番で噛ました行列を作って返してくれるメソッドを作った。
えおなゆ様にすぺしゃるさんくす!
今回は、前回のQoFで避けていた地雷をどんどこ踏みつつ、いろんな人にお世話になりまくっているなぁ!
/// 省略 public Matrix CreateTransformMatrix2D( float scaleX, float scaleY, int degree, float transX, float transY) { Matrix m = new Matrix(); m.M11 = cosineTable[degree % cosineTable.Length] * scaleX; m.M12 = sineTable[degree % sineTable.Length] * scaleX; m.M21 = sineTable[degree % sineTable.Length] * -scaleY; m.M22 = cosineTable[degree % cosineTable.Length] * scaleY; m.M41 = transX; m.M42 = transY; m.M44 = 1f; return m; } /// 省略 public void SetGlobalTransform( float scaleX, float scaleY, int degree, float transX, float transY) { device.Transform.World = CreateTransformMatrix2D(scaleX, scaleY, degree, transX, transY); } /// 省略 public void SetLocalTransform( float scaleX, float scaleY, int degree, float transX, float transY) { sprite.Transform = CreateTransformMatrix2D(scaleX, scaleY, degree, transX, transY); }
あぁ、これで便利に使えそう。+αな補足としては、
Sprite.Begin~End間にdevice.Transform弄るのはいいけど、
SpriteさんはBeginするとき、device.Transformの逆行列(のよーなもの?)をTransformにセットして描画位置を戻してる(?)みたいなので、
Begin時のdevice.Transformによっては、変な行列が入っちゃって(?)弄りよーにも弄りにくい。
ので、Sprite.Beginするとき、必ず device.Transform.World = Matrix.Identity; しとくといいかなー。
と言ったところ。
ああ、いろいろと自分でやろうと思ったらお節介すぎるのねー。
これでキャラごとの回転ができる。弾幕も作れるネ!
まだまだ作りかけ。やらなきゃいけないことが多すぎる。
でも、今週は応用確率論の中間があるので、続きはそれ以降になりそう。
今年はQoFとはまた違った意味で、QoF以上の修羅場になりそう。
あぁ、怖いなぁ……