プチメタ3.0

刺激を受けた物事に対する感想や考察、資産運用や英語学習、自己成長に関することなど。


衝突判定に必要な3Dモデルの大きさを自動計算する仕組み


ゲームというものは2Dであれ3Dであれ
「何かと何かが衝突する」という状況が多く発生するが、
その判定には当然ながらそれぞれの大きさの情報が必要になる。


2Dゲームの場合は画像の幅や高さを使えばいいが、
3Dゲームの場合はどのようにしているのか、
そのあたりの仕組みを解説してみる。

3Dモデルは頂点の集合体


立体的なキャラクターや背景モデルは
「ポリゴン」と呼ばれる三角形の板で構成されており、
そのポリゴンは3つの頂点が1セットになっている。


平面を使って立体物を表現する手法は
ペーパークラフトに非常によく似ている。




つまりこういった複雑なモデルであっても



結局は多数の頂点が集まっているのだ。


形が複雑になればなるほどポリゴンが増えるのだが、
それらを使って真面目に衝突判定をしていると
計算負荷が大きくなってゲーム中に処理できない。


そこでいかにシンプルに考えるかが重要になる。

モデルを球体に見立てる


たとえばモデルの中心から各頂点までの距離を求め、
その中で一番遠い値を半径とする球体をイメージする。




一番遠い場所にある頂点を基準にしているので
すべての頂点がこの球体の中に収まるはずだ。
つまりこれが3Dモデルのおおよその大きさを表す球となる。


衝突する物体同士を球に見立てれば
2Dゲームと同様に三平方の定理で高速に判定することができる。
これは各作品で非常によく使われている方法だ。


ただし、モデルの形が球状から大きくかけ離れていると
当たっていないのに衝突したと見なされる違和感が出る。




そういう場合は複数の球体を埋め込む形で
ある程度、モデル全体の形に近づけて判定する。
球の個数が多くなるとやや計算回数も増えるが、
それでも三平方の定理だけで処理できるメリットは大きい。

モデルを直方体に見立てる


もうひとつの方法として、
各頂点の中でもっとも大きなX座標の値を調べる。
つまり一番右にせり出している頂点のX座標だ。


同様に、全頂点から最大のY座標と最大のZ座標を探す。
これは一番高い位置の頂点、一番奥にある頂点となる。
それらの値を組み合わせると
もっとも右・上・奥の角を表す座標となる。


さらに全頂点からXYZ座標の最小値も調べて
もっとも左・下・手前の角の座標を割り出す。




その2つの座標が対角に位置する直方体をイメージすると
3Dモデルがぴったり収まるボックスができあがる。


球体として扱いにくいもの、たとえば戦車などは
こういった直方体として考える方がよかったりする。

まとめ

ゲーム機のスペックはどんどん進化するが
その恩恵の大半はグラフィック部分に回されるため、
内部的な処理はできる限りシンプルで高速にする必要がある。


見た目は豪華でも計算上は実は簡略化して判定していることは多く、
最新のゲーム作品であっても
さまざまな工夫と原始的な理屈がベースになっている。



mclover.hateblo.jp

3Dモデルを作るときは無地の壁でもわざわざムラのあるテクスチャを貼る


3Dゲームを開発ときは、建物やステージといった
背景部分も立体モデルとして作っていく。
その際、同じ色の床や壁であっても
少し斑(むら)を用意するのがポイントだ。




たとえばコンクリートの床だからといって
こんな感じの無地のデザインにしてしまうと、



遠くの床も近くの床もまったく同じ見た目になるので
距離感がわからなくなるのだ。
凹凸のついた地面なら光が当たる向きで明暗がつくが、
平らな床面だとまったく区別がつかない。




そこで、たとえグレー一色の床であっても
汚れや傷みなどで濃淡に差をつけたテクスチャを貼る。




すると遠くに行くほど粗さが変わるので
近くなのか遠くなのかがわかりやすくなるのだ。


3Dゲーム作りに慣れていない学生だと
床一面を1色で塗ってしまったりするのだが、
このあたりの工夫も市販ゲームをよく観察して
気を配れるようになって欲しい。

プログラミングに暗記力は不要


ゲーム開発を学ぶ学生が授業に対するアンケートに
「しっかり覚えようと思います」とか
「内容を覚えるのが大変そうでした」などと書いていることがあるが、
プログラミングに対して「覚える」と表現するのは違和感を感じる。


もし「理解する」という意味で書いているだけなら
国語的な話なので大きな問題はないが、
言葉通り「記憶する」と考えているなら
そもそもプログラミングは覚えるものではない


プログラミングというのはある目的を達成するために
処理を組み合わせて新たに設計していく作業なので、
パソコンに向かってキーボードを叩いているプログラマーは
以前暗記した内容を打ち込んでいるわけではないのだ。


そういう意味では小説を書くような場合と似ている。
小説家は新しい話を生み出す作業をしているはずで
あらかじめ暗記しておいた文章を書いていくわけではない。
また、漢字や言葉は覚えている方がスムーズだが、
わからなければ調べれば済むという点でも同じだ。


以前作ったプログラムと同じものを作りたいなら
暗記しなくてもコピーペーストすればいいわけで、
プログラミング学習で大切なのは
「どういう組み方をすればどんなことができるか」
「どういう書き方なら問題が起きにくいか」
「なるべく効率のいい手順は何か」
などを学び取っていくことだ。


「プログラミング+暗記力」で調べても同様の答えばかりで、
暗記などしなくても必要なことはその都度調べればいいし、
プログラマーの本領は設計能力や論理的思考にある。


プログラミングを学ぼうとしている人は
くれぐれも力の入れどころを間違わないようにして欲しい。



mclover.hateblo.jp

褒める方が楽だし褒められる方が気持ちいいが、ダメ出しに慣れていかないと成長しない


最近の学生を見ていると
他人との衝突を極端に恐れていることが多く、
異なる意見を挙げることやネガティブな指摘をされることを
できるだけ避けようとしているように思う。


確かに自分に対する改善要求を聞くのは辛いし、
相手を目の前にして否定的な意見を言うのは勇気がいるが、
褒め合っているだけでは気持ちよくなるだけで成長しない。
高い成果を出すためには正しい評価を知る必要があるのだ。


特にゲームというものは自分が作ったものに対して
多くのユーザーがあれこれ感想を言うわけで、
これに耐えられないようだとゲーム作りなんてできない。


作品に対する批評をクレームや文句ではなく
新しい視点に気づかせてくれる助言だと考え、
むしろ積極的にいろいろな感想を集めていく方が
短期間でグッと改善できるし、自分の視野も広がる。


イエスマンにばかり感想を聞くのは楽だろうが、
成長効果がほとんどないことも知っておこう。

2ヶ所のキャラクターをどちらも画面内に収めるカメラ位置の求め方


対戦型の3Dゲームなどで
主人公と敵が常に画面に収まるよう、
カメラの距離を自動で調整したいことがある。




一番遠い距離で固定してしまうと
両者が接近したときに迫力がなくなるため、
離れているときだけ遠くから映し、
接近戦ではカメラを寄せるようにしたいわけだ。


格闘ゲームではよくある表現だが、
これを実現しようと思うと数学が絡んでくる。

カメラが見ている上下の距離を割り出す


3D世界を映すカメラの画角は自由に設定できるが、
これは一般的に縦方向の角度である(今回は60度とする)。
ゲーム画面は横長なので水平方向の画角はもう少し広くなる。




縦方向の画角を上半分だけで考えると30度になり、
カメラから前方に伸ばした直線を底辺とした
直角三角形をイメージすることができる。




たとえば底辺の長さが100だった場合、
この直角三角形の高さはいくらになるか。
これは三角関数のタンジェントで求めることができる。


 tan30^\circ\times100=57.74


これにより、三角形の高さは約57だとわかる。



この三角形が上下につながっているわけだから
ある場所から100離れたカメラが見渡している
上下方向の距離は約115ということだ。

カメラの水平方向の画角を求める


普通、ゲーム画面は横長サイズなので
縦方向に見渡せる範囲より横方向の方が広い。
一般的には16:9という比率(アスペクト比)になっているので


 115.48\times\dfrac{16}{9}=205.29


という計算で水平方向に見渡している距離がわかる。
ここから逆算する形でカメラの水平方向の画角を求める。




これまでの内容をまとめると
ある場所から100離れたカメラが見渡している
左右方向の距離は約205ということだ。




ここで直角三角形を見つけられるとベストだ。
右に90度回転して考えるとわかりやすいが、
底辺の長さが100、高さが約102の直角三角形になっている。


この2辺の長さから角度を割り出すには
タンジェントの逆関数であるアークタンジェントを使う。


 arctan\dfrac{102.64}{100}=45.44^\circ


実際には100倍や2倍する必要はないので、


 arctan\biggl(\tan30^\circ\times\dfrac{16}{9}\biggr)=45.44^\circ


とすれば一気に計算できる。


これは左半分の角度なので左右の画角では約91度になるが、
今後の計算の中では45度の方を使う。

キャラクターを頂点とする二等辺三角形を考える


カメラの画角は一定なので、
キャラクターをうまく視界に収めるには
対象者との距離で調整する必要があるわけだ。




2つのキャラクターがはみ出さないようにするには
両者を結んだ直線を底辺とする二等辺三角形をイメージすればよい。
(実際にはキャラクターのやや外側に頂点を置く方が綺麗)




ここでも直角三角形を見つけられただろうか。
とにかくゲームプログラミングは三角関数に頼る部分が多い。


今回も右に90度回転して考えるが、
キャラクター間の距離の半分を高さとする45度の直角三角形で、
この底辺の長さがカメラの理想的な距離というわけだ。


タンジェントというのはもともと


 tan\theta=\dfrac{高さ}{底辺の長さ}


と定義されているわけだから、これを変形すれば


 底辺の長さ=高さ ÷ tan\theta


となり、今回の値を当てはめれば


 理想的なカメラ距離=キャラ間の距離の半分 ÷ tan45^\circ


となる。



あとは2つのキャラクターのちょうど中間の座標を
注視点(カメラが見ている場所)に設定し、
そこから理想距離だけ離した場所にカメラ本体を置けばいい。


市販ゲームで使われている処理も
実は中学数学さえわかれば実現できたりする。



mclover.hateblo.jp

総アクセス数