はじめに
過去の記事でルービックキューブのGUIを作りました。先日紹介した記事では、オブジェクトの設計、レンダリング、マウスカーソルとオブジェクトの接触判定など、そこそこ真面目に取り組みましたが、内容が少し難しいと思います。大学1年生レベルの数学をそこそこ使いこなせている必要があります。中高生が真似するのはちょっと難しいかもしれません。
ところで、私は似たような仕様のプログラムを高校生のときに作成したことがあります。当時の日付は2008/2/27でした。そのときのPCは、CPUがPentium 4の1コアで計算機資源としてはあまり潤沢ではありませんでした。それでもそこそこ動くプログラムにはなっていたのです。しかし、当時はまだ大学レベルの線形代数はわからず、様々な横着を盛り込んで作成していました。プログラミング言語はなでしこ1を選んでいました。黒歴史はここに供養しておきます。
当時の工夫は今でも通用する部分があるので、ここに紹介したいと思いました。
演算回数の削減
プログラム作成当時はPCのスペックが貧相であるだけでなく、プログラムの知識も乏しかったので、言語選定のセンスが謎でした。先日紹介したJavaScript版のように、3次元座標の回転変換を多用すると動作が重すぎて使い物になりませんでした。なので、ルービックキューブ全体を1つの立方体として管理して、基底を構成できる3頂点に対してだけ回転変換を作用させ、残りの5頂点は加減算で、頂点間の座標はそれぞれ3等分すればOKだよね、と計算量の削減をしていました。
この考え方は、ルービックキューブを1つのオブジェクトとして捉えるならアリだなと思いました。ただ、キューブをパーツごとのオブジェクトの集合として設計した先日の方法とは相容れないので、メリデメを理解した上で選択が必要だなと思いました。
マウスカーソルが当たっている面がわからない
この課題は正面突破を試みると結構大変です。先日紹介した通り、大学1年生レベルの線形代数をそこそこ使いこなせていないとできないのです。ただ、当時の私は面白い方法で回避していました。
画面に表示するルービックキューブとは別レイヤーに、ルービックキューブの表面9x6 = 54面を全て違う色で塗り分けたキューブを見えないように描画していたのです。マウスカーソルが当たっている位置の座標にある色をピックしてどの面にマウスカーソルが当たっているのかを識別していました。
論理的なif elseで解決できなかったので、まったく別方向から力業で何とかしたのです。
キューブをどの方向に動かしたいのかわからない
ここはちょっと線形代数を使っていました。キューブの基底とマウスカーソルの移動量との内積を取って分岐していました。ただ、ここは先ほど紹介した横着の強化版にすればよかったなと今更ながら思いました。キューブの1面を構成する9部品のうち1パーツの面を例えば5x5で刻んで塗り分けて、ピックした色の変化に応じて分岐すればよかったのです。
数学で解決しようとすると難しいのに、実際に描画されている絵から無理やり情報をもらってきてしまう方法は実は合理的なのかもしれません。
まとめ
正面突破する方法を解説する記事よりも、裏技の紹介の方が遥かにわかりやすくコンパクトになってしまいました。今でこそ正攻法で攻略できるように知識が充実しましたが、エンジニアの仕事は今持っている道具で目の前の難題を攻略しないといけません。正面突破が難しいかなと思ったら裏口がないかどうか探してみましょう。