2011年1月25日火曜日

実はとても簡単な回転行列

 3D のプログラミングをする上でかかせない回転行列。この中に入っている数値の意味を知らずに使っている人、結構いるんじゃないでしょうか。実は僕もわりと最近まで、その中に何が入っているかなんてあまり考えずに使っていました。
 ググってみると、たいてい概念と計算式のみの説明だったり、DirectX 等に用意されている関数群を使ったサンプルのみだったりと、その中身について説明しているサイトは僕には見つけられませんでした。
 理解している人にとっては当たり前のことなんだと思いますが、知らない人がその計算式だけで中身を理解するのはなかなか難しいと思います。
 なので今回はこの行列の中身について解説したいと思います。

 前提として、ベクトルの計算程度は理解している必要があります。逆に言えば、ベクトルの計算を理解していれば行列の中身も理解しているも同然と言えます。

 まず、単位行列を見てみます。
この行列を、横に1行ずつ見て、それぞれ1行を1本のベクトルとして見てみます。3x3 行列ですから、3本のベクトルがあることになります。これを右手座標系の図で表すと、
こんな感じになります。上から1行目のベクトルが赤、2行目が緑、3行目が青になります。何か、よく見る図ですね。
 さて次は Y 軸中心に 30 度回転させる行列を作ってみます。そこらでググれば、Y 軸中心に回転させる行列は、
だということなので、30 度回転させる行列は、
となると思います。ではこれも上と同じように1行ずつベクトルとして解釈して図にしてみます。
こんな感じになります。
 …だいたいおわかりになるでしょうか?
 つまり、3x3 の回転行列とは3本の垂直な単位ベクトルを並べただけのものなんです。本当にただそれだけのものなので、3D のライブラリなんかに用意されている行列計算関数なんか使わなくても簡単に行列は作れるんです。
 例えば Z+ を向いているモデルを任意のベクトルの方向に向かせたければ、行列の3行目にそのベクトルを入れ、同ベクトルを XZ 平面上で 90 度回転させたベクトルを1行目に入れ、最後にこの2つのベクトルの外積を求めて2行目に入れればいいわけです。向かせたいベクトルが Y 軸方向に上下するならもうちょっと工夫が必要ですが、この理屈を理解していれば簡単に作れると思います。

2011年1月7日金曜日

続・確率の誤解 - 確率の数だけサイコロが

さて、前回書いた確率ですが、結構多くのプログラマが間違った使い方をしているので、また語ってみたいと思います。

ここに、1個のサイコロがあります。このサイコロは1~6までのそれぞれの数がでる頻度がまったく一緒で、6回ふれば必ず1~6までの数がそれぞれ1回ずつ出るものとします。
さて、このサイコロをAさんとBさんの二人が3回ずつ交互にふったとして、Aさん及びBさんが偶数の目を出す確率は何パーセントでしょうか?

答え:不定

確率50%ではありません。もし確率50%であるなら、Aさん及びBさんは必ず1~2回偶数の目を出すことになります。
しかし、ここではこれは保証されません。なぜなら、このサイコロが保証しているのは1~6までの数値が同じ頻度で出現するということだけであり、何回目に偶数が出るのかということについては何も保証していないからです。
ですから、Aさんが3回偶数を出してBさんが奇数を3回出してしまうことも、逆にBさんが3回偶数を出してしまうことも起こりうるわけです。

つまり、前回書いたような乱数発生器にも同じことが言えます。
1つの乱数発生器をアイテム出現率の他に、例えばアイテムの種類を選ぶための乱数としても利用していたとすると、アイテム出現の成功となるような値が発生する機会をアイテムの種類を選ぶ乱数を発生させる機会に奪われて、望まれる確率よりも低い出現率になってしまうこともあるわけです。

もしプログラマが乱数をこのような間違った使い方をしてしまった場合には、確率の数値はまるで当てになりません。そして、こういった理屈を理解していないプログラマが結構いるんですよね…。私も結構長い間、理解せずにやってましたしw
MHP は…どうなんでしょうね。ちゃんとわかってるプログラマが作ってるんでしょうか。前回書いたような要因もあるので、プレイしていても開発者の想定通りなのかどうかはまったくわかりませんw

2011年1月5日水曜日

確率の誤解 - 50/100 ≠ 500/1000

ここ最近、ずーーーっとモンハンばっかりやってました。
そう、先月発売した MHP3 です。
ようやっとレイア希少種を倒したのですが、もう今の装備では限界…。新しく装備を調えるために、レア素材求めてまた乱獲しなくっちゃなぁ…。

ということで、確率について少し語ってみます。

モンハンの攻略を乗っけてるサイトなんかを見てると、アイテムの手に入る確率なんかが書いてあります。たいていパーセントによる表記ですが、これってどうやって算出した値なんですかね?ざらっと見た限りではどうやら直接データを参照したもののようですが、おそらくプログラムの解析はやってないかと思います。
ともあれ、この数値に関しては、確率 50% もあるのに全然手に入らないだとかの文句がよく見られます。さて、この 50% という数値は果たして「100分の50」なんでしょうか。それとも「1000分の500」なんでしょうか。どちらも同じじゃないか、と思われるかもありませんがさにあらず。どんな単位で扱うかによって大きな違いがあるのです。
コンピュータで扱われる乱数はたいていの場合疑似乱数です。疑似乱数というのは、その名の通りでたらめな数値ではなく、でたらめな数値に見えるような数値を計算しているわけです。そして、質のいい乱数には条件があって、その一つに数値のばらつきというものがあります。例えば0~9の数値を発生させる乱数発生器なら、0~9までのそれぞれの数値が同じぐらいの頻度で出現する必要がある、ということです。まあ、一般的な乱数発生アルゴリズムならたいていこの条件はクリアしています。
さて、次に問題になるのはこの発生の周期です。先の例で言うと、例えば「1」という数値が出現してから何回乱数を回せば再度「1」が出現するか、という問題です。(知っている方に言っておきますが、ここで言う周期はアルゴリズムによる限界の周期ではなく、あくまでも目的の数値が出現する頻度の周期です。) だいたい10~20回程度で出現してほしいところですが、そうでない場合もあります。例えば乱数を100回発生させて開始から90回「1」が出現せずに最後の10回に連続して「1」が出現したとしても、先に言った出現頻度の条件はクリアしていますから仕様上問題ないことになります。
まあ、一般的な乱数発生アルゴリズムならここまで極端に偏ることはまずありません。しかし、前に言ったような「100分の50」あるいは「1000分の500」といった単位で考えるとこういった偏りが発生する可能性が非常に高くなります。
「100分の50」で考えると、乱数発生器が「0~99」までの数値を発生させるとして、「0~49」ならアイテムが出る、「50~99」ならアイテムが出ないとすると、100回乱数を発生させるうち最初の10回でアイテムが出ない可能性は決して低くありません。なぜなら乱数発生器が保証するのは「0~99」の各数値が出現する頻度がだいたい同じということであり、どんな順番で出現するかはいっさい保証していないからです。このため、確率が「100分の50」であったとしても、10回やって5回アイテムが手に入るとは限らないわけです。
そしてさらに「1000分の500」となるとこの可能性はさらに高くなります。先の「100分の50」なら最悪のケースでも51回やれば確実にアイテムが1つ手に入ることになりますが、「1000分の500」となると最悪の場合501回目までアイテムが手に入らない可能性があることになります。
つまり、「100分の50」と「1000分の500」とでは確率に大きな違いがある、と言えるわけです。

なので、攻略ページに出現率1%とか書いてあっても、実際プログラム側でどんな単位で扱っているかがわからなければ、手に入るまでに必要な回数もわからないということです。逆鱗とかけっこうな個数必要だったりするですが…いつになったら集まるかなぁ… orz

他にも、多くのプログラマが勘違いしている乱数の扱いがあるのですが、それはまた今度。