08/05/25それでは当初の目的通り、スカートを作ってみましょう。スカートを作るためには、布シムに足との衝突判定を組み込む必要があります。大量の格子点(重り)と足との接触を判定しなければならないので、なるべく計算の楽な方法を取る必要があります。今回は、重りを点、足をカプセルとみなして判定を行うことにします。カプセルとは円柱の両端に半球をくっつけたものです。カプセルは線分と半径rで定義されます。線分からの距離がr以内の部分がカプセルになるわけですね。キャラクタはボーンでアニメーションをつけます。腰から膝までのボーンと、膝からかかとまでのボーンを使って足を動かすことにします。ボーンを円柱の軸とみなせば簡単にカプセルの位置が計算できます。アニメーション関係のソースはこちらの記事のものを流用しています。衝突している重りに対しては足にめり込まないように足の外に押し出す力をかけます。物理シム業界ではペナルティ法と呼ばれる方法です。円柱の表面と重りとの間にバネを入れるだけで実現できます。要はめり込んだ重りをバネの力で押し返すわけです。ついでに重りのエネルギーを削るためにダンパを入れておくと動作が安定します。ペナルティ法を使うことで、衝突判定が入る以外は今までの布シムの枠組みをそのまま流用できます。カプセルと点の衝突判定についてWeb上に良い資料が見つからなかったので、補足しておきましょう。衝突は円柱状の部分と両端の半球部分に分けて考えます。衝突判定する点を点xとします。(以下、a,b,x,yは3次元ベクトル、sはスカラー)点xから線分に下ろした垂線の足yを求めます。線分の両端の座標をa,bとします。点yはa,bを通る線上にあるのでy=a+s(b-a)として表されます。(・は内積)を満たす必要があります。未知数はsだけなので、この式は簡単に解けます。sが分かれば点yが求まり、これで円柱との判定ができます。点yが線分上に存在して、かつ点xと点yの距離r'がrより小さければ円柱と衝突しています。r-r'が円柱表面から点xまでの距離になるので、この値をペナルティ法で使わせてもらいましょう。円柱と衝突していなかった場合は、点と球との判定を行います。こちらは点a,bと点xの距離がr以内であるかという判定をするだけなので簡単です。蛇足ですが、カプセルと球(半径r'')との判定も同じ原理です。上記のrをr+r''に置き換えるだけで済みます。この辺のお手軽さが、衝突判定においてカプセルが使われる理由なのでしょう。いうわけで、今回のソースです。足のシルエットが布越しに見える感じはなかなか良いんじゃないでしょうか?とは言え、スカートと言うには少し布がビロビロしている感じです。パラメータの設定が難しいですね。この布は重りの上下左右方向と対角方向の2種類のバネしか入れていないので、もしかすると3種類目を入れると改善するのかもしれません。スカートの形状が足に密着した長い円柱形状というのも宜しくないです。現実世界では、そんなタイトロングなスカートでは足を大きく動かせません。円錐形状にするか、膝の辺りまでスリットを入れるかすると、もう少しリアルになるかと。プログラムを簡単にするために、一本のバネについて同じ計算が2度行われています。実際にゲームで使う際には改良しておいたほうが無難でしょう。いつものことながら、エラーチェックは最低限であり、このサンプルの使用によるいかなる不幸も当方では責任を負いかねます。コンパイルし直した、バイナリ&ソースです。プロジェクトはVisualStudio2008用になります。--/--/--前回はオイラー法を使って布シムを作ってみました。オイラー法は誤差が大きいのでパラメータ設定を誤るとすぐに布が千切れ飛んでしまいます。誤差が出るのは仕方のないこととして、陽的公式でなるべく正確に計算しようとする努力がなされてきました。2次のルンゲ・クッタ法(RK2)、4次のルンゲ・クッタ法(RK4)と呼ばれる方法が有名です。数学的に言うと、ある関数をテイラー展開した式をいかに近似するか、という話になります。大学で理数系に進めば一年生のときに出てくる話です。オイラー法ではテイラー展開の1次項まで、RK4ではテイラー展開の4次項までの近似になります。布シムが4次まで微分可能なのかという疑問については...???です。RK2を使うよりはRK4を使う方が良いようです。難しい話は脇に置いて、シム業界ではRK4を使っておけば文句を言われないという不文律があるので従っておきましょう。RK4はオイラー法と同等の計算を4回行なって、それらの結果を足し合わせて用います。時間刻み幅のdtを大きくすることができ、総合的にはRK4が勝つと言えます。してとりあえずRK4を使っとけという風潮があるわけです。オイラー法が使い物にならないというわけではありません。Cloth』によるとオイラー法と後退オイラー法を同時に使う、FBオイラー法という方法があるそうです。ように現在の加速度に対してオイラー法を適用します。ように未来の速度に対して後退オイラー法を適用します。現在の状態のみから計算できる陽的公式の一種といえます。試してみるとこれが、意外と使えます。dtをRK4と同じくらいに大きくしても比較的安定した計算結果が得られます。それでいて計算が簡単というのはなかなか美味しいですね。難しく言うと1次のシンプレクティック法ということらしく、オイラー法に比べてエネルギーが保存されやすいんだとか。それなら、2次のシンプレクティック法を使えばもっと良い結果が得られるのでは?ということで、これまた前回紹介した『システム数理IV』を紐解くと、リープフロッグ公式というものが紹介されています。こちらのサイトの方が説明が簡単かもしれません。幾つかの式変形が見られますが、FBオイラー法そっくりな形が含まれています。時間の進め方の微妙な違いが精度に効いているんですね。長時間計算しても布が千切れ飛びにくい(多分...)ので便利な方法だと思います。シムの専門家ではないので、真偽のほどは分かりません。いうわけで、今回のソース。オイラー法とFBオイラー法、RK2、RK4、リープフロッグを切り替えたり、パラメータを書き換えたりしてお楽しみください。空気抵抗の計算にイカサマが入っています。いつものことながら、エラーチェックは最低限であり、このサンプルの使用によるいかなる不幸も当方では責任を負いかねます。いずれにしろ各計算方法の理解に怪しい部分があるので、参考程度ということで宜しくお願いします。間違っていたら、こっそりご指摘ください。simulation(布シム)を作ろうと思い立ったよ企画。ボーンベースのアニメーションだと柔らかい物体を表現するのが難しいので、どうしてもゲームキャラはタイトな服をまとう事が多くなります。野村XXさんはロングスカートがふわふわひらひらするのが大好きなご様子。大量のボーンをスカートに仕込んで手付けでアニメーションさせるという手もありますが、これは人力にものを言わせた荒業と言えるでしょう。他には3Dソフト上で布シムを計算して、結果をもらって来るという手もあります。他のモーションに遷移する際に、モーションをブレンドするのも計算量が馬鹿になりません。両者を合わせた技も考えられます。後者の結果に近づくようなボーンのパラメータを求めるという方法です。これは、大雑把な近似としてはうまく動きそうな気がします。ゲームで使う分には十分かもしれません。事前に計算されたモーションでは、風向きが変わるというような環境の変化に対応し切れません。風にはためいてこそのロングスカートです。前置きが長くなってしまいました。今回は、定番のバネマス系の布シムの話です。格子状に配置した重りをバネでつないでゆらすと、ビヨンビヨンする様が布に似ているという手法になります。まとまった説明としては、こちらのサイトが分かりやすいです。論文の一つでも読んでやろうかという剛毅な方はこちらとかこちらなんかどうでしょうか。重りを一つ飛ばして上下左右に接続するバネ(1のバネの二倍の距離で接続される)、の3つを用います。最低、1と2を使っておけば、布っぽく見えます。bendといっているのでフックの法則に従わないバネを想定しているようです。伸びる前のバネの長さですね。重りとバネを仕込み終わったら、シミュレーション開始です。シミュレーションとは、要するに時間を進めてあげるということです。布にまったく力がかからなければ、時間をいくら進めても変形しません。布にかかる力としては、重力、空気、他の物体との接触、布同士の接触、etc...と色々あります。前者2つを考えましょう。重力は常に一定の力を重りに与えます。世の中にはエネルギー保存の法則なるものが存在するので、重りとバネと重力だけでは、永遠に振動し続けます。本物の布はそんな動きはしないので、どうにかして振動を止めなければなりません。そこで空気抵抗(ダンパ)を導入します。ダンパは速度の逆向きに働く力です。速度バネ自身にダンパ項を導入するモデルも存在します。その辺りはお好みでといった感じです。これで、布に加わる力は分かりました。ある重りに対してバネと重力と空気によって働く力の総和をFとすると、ニュートンの運動方程式から加速度が計算できます。速度と位置が計算できます。中学の授業で習ったはずです。位置ここで、深遠な疑問にぶち当たります。『どうやってその積分を求めるの?』という問題です。あまりに難しいので偉い学者さん達が何年も研究しています。まとまった資料としてはこちらがお勧めです。基本になるのは、オイラー法と呼ばれる手法です。x(t)+v(t)dtで計算できるという考え方です。現在歩いている速度と、現在の位置からおおよそ推測が付くでしょ、ということですね。このように現在の状態の値を使って未来の状態を計算する方法を陽的公式といいます。ように速度の未来の状態を使って計算する方法もあります。こちらの一派は陰的公式と呼ばれます。大雑把に言うと、未来の状態を未知数とした方程式を解くことになります。計算が大変になるので、リアルタイムで処理をするのには向きません。陽的公式には少しずつ未来を計算していくうちに誤差が溜まるという問題があります。明日の自分から明後日の自分も大体予測が付きます。これを繰り返していけば10年後の自分だって予測が付くはずです。言え、まず間違いなくその予測は当たらないでしょう。布シムの場合、陽的公式では計算誤差で激しく揺れまくるという結果が出がちです。ちなみに陰的公式ではそのような羽目になりづらいという利点があります。いうわけで、今回のソース。パラメータを書き換えてお楽しみください。見た目を楽しくするために、布に対して風っぽいものが吹いています。いつものことながら、エラーチェックは最低限であり、このサンプルの使用によるいかなる不幸も当方では責任を負いかねます。オイラー法の精度の関係から、dtをかなり小さくしなければならず、動作は遅いです。これを実用的にするにはどうすれば良いのかという話が次回に続きます。--/--/--乗りかかった船ということで、BEEPでMIDIなドライバを書きました。基本的な部分はVorbis再生のドライバVoxと互換です。MIDI)になりました。相変わらず英語的には微妙...下の記事で5チャンネルくらいなら鳴らせるよね、と書いていますがチューンの結果、16チャンネル全て鳴らせるようになりました。ついでに95系のWindowsもサポートしました。95系はVirtualPCで動作確認しただけなので、実機だとちゃんと動くのか分かりません。試してみた方は、是非ご一報下さい。いうか、WinXP上でPCエミュレータを走らせて、Win95を動かし、そこで鳴っているBEEP音はサウンドカード上でエミュレートされていて、ピコポコ音のMIDIを奏でているという謎の状態が笑えます。MIDIはそれなりに聞けると思います。WindowsがマルチタスクOSである以上、タスク切り替えが発生するので、再生中に音が途切れるのは諦めてください。サウンドカードのようにバッファリングして鳴らせるわけではないのでコレばかりはどうにもなりません。ヘルプはVectorのサイトから拾ってください。BEEP再生を聞いてみたいだけの方には、超シンプルなプレイヤーを用意しました。--/--/--私の友人がここ数年に渡ってPC9801のエミュを書いていて、たまたまBEEP音楽の話が出てきました。PC88とかPC98ではお世話になった人も多いんじゃないでしょうか。FalcomとかT&Eあたりは結構、まともな音楽に聞こえていたような気がします。言う私はMSXユーザだったので、PSGの澄んだ音色の世界に居たわけですが。分かる人にしか分からないというか、分からない人にはまったく分からない、BEEP音楽の世界にいざなおうというのが今回の趣旨です。こちらにすでに立派なソフトがあるので、単にこの世界に浸りたいだけなら一発終了です。何かのソフトに組み込みたいという貴方は、引き続きお読み下さい。レトロ風味なゲームを作る際には、役立つんじゃないでしょうか。音ネタはMIDIを使います。MIDIフォーマットを調べてみたのですが、さすがに80年代の規格だけあって、微妙に貧乏臭いです。数値を可変長フォーマットで記述したり、連続して同じコマンドが発行される場合は、ステータスバイトを省略したりして、ファイルサイズの圧縮を図っています。そんなことをしても数十KByte程度のデータがちょっと小さくなるだけなんですけどね。MIDI規格については、こちらやこちらに分かりやすく書かれています。ビッグエンディアンであることにさえ気をつければ、フォーマットの解析は楽勝です。コマンドはありますが、今回必要なものはノートオンとノートオフ、あとはテンポの指定だけです。音色なんか指定されても、所詮BEEPなので再現のしようがありません。ノートオンで音を発生させ、ノートオフで音を止めます。ノートオンではノートナンバーが指定されます。この数字は60がC3、つまり"3オクターブ目のド"を表します。記述されているMIDIをBEEPで鳴らすために、周波数に変換しなければなりません。A3(ラ)が440Hzとして、これを基準に音階を作ります。西洋音楽世界では1オクターブ上がると周波数が2倍になります。1オクターブは12音階で作られるのですが、今回は1オクターブを等比で12分割してあげます。いわゆる平均律という奴ですね。調律には色々な主義主張があるので、暇な人はこのあたりのサイトでお勉強してみるのも良いかと。これでMIDIを鳴らす準備はできましたが、ここで問題になるのは和音の扱いです。BEEP自体は単音しか鳴らせません。そこで、単音を細かく区切って、音階を変えながら鳴らし続けると、なんとなく和音ぽく聞こえるというテクニックを使います。"ドミソ"の和音を"ドミソ"の3連符に置き換えるようなものですね。Windowsでそんなにシビアな時間管理はできません。この手のテクニックの究極、1bitDAによるWav再生なんて古典テクニックは、Windowsではまず再現不能でしょう。大雑把に試してみたところ、単音一つ当たり10ms程度が妥当のようです。5重和音まで出そうとすると、50ms必要になり、4分音符がざっと500ms相当なので、16〜32分音符程度までは表現できます。MIDIは16チャンネルまで再生できる規格なので、5重和音では表現力が足りないものの、メロディーラインは大抵、数字の低いチャンネルに入っているので、数字の低い順に5チャンネル分再生することにします。そんなこんなで、今回のソース。BEEPを鳴らすのに用いている関数が、NT系でないとまともに動作しないのでWin95やWin98は不可です。英語が破綻しているのでは?というツッコミは無視です。いつものことながら、エラーチェックは最低限であり、このサンプルの使用によるいかなる不幸も当方では責任を負いかねます。