FPSを作ってみる@wiki
07)
最終更新:
slice
-
view
(2013/07/30)
プログラム側に関してはとりあえず公開できそうな状態には出来た。が、debianパッケージの作り方を忘れる。
それとメインで使ってるコンパイラが今clang3.4なのだけどwindows用にクロスコンパイルするにはどうすればいいのかわからないので
ひとまずgcc4.81とmingwでやろうかなと試みるもgccではコンパイルが通らない。
まぁclangでクロスコンパイルも調べれば出来るとは思うが
githubで公開してるようなソースがgccでコンパイル出来ないのもアレなので直すことに。
それとメインで使ってるコンパイラが今clang3.4なのだけどwindows用にクロスコンパイルするにはどうすればいいのかわからないので
ひとまずgcc4.81とmingwでやろうかなと試みるもgccではコンパイルが通らない。
まぁclangでクロスコンパイルも調べれば出来るとは思うが
githubで公開してるようなソースがgccでコンパイル出来ないのもアレなので直すことに。
具体的にはclangで許容されていた書き方や新しい言語仕様がgccにはまだ無かったり
当方32bit環境な事もあってコンパイラの使用メモリが2GBを超えるとメモリ確保失敗エラーで落ちてしまうからファイルの分割をする等。
(今まではclangの方がメモリ消費が少ないから問題にならなかっただけ)
これからソースを修正しーの動作テストしーので8月までにアップ出来れば理想か。
当方32bit環境な事もあってコンパイラの使用メモリが2GBを超えるとメモリ確保失敗エラーで落ちてしまうからファイルの分割をする等。
(今まではclangの方がメモリ消費が少ないから問題にならなかっただけ)
これからソースを修正しーの動作テストしーので8月までにアップ出来れば理想か。
その後clang + mingwも調べるつもり。
(2013/07/29)
もうちょい
やっと安定してきた。
積分の公式なんて久しく使ってないしそこから復習だったんで随分時間かかった。
いや、正確には3Dな計算式は論文に書いてあるのだが2Dは自分で出す必要があったので。
積分の公式なんて久しく使ってないしそこから復習だったんで随分時間かかった。
いや、正確には3Dな計算式は論文に書いてあるのだが2Dは自分で出す必要があったので。
計算式がどこかが間違っているのか、それともアルゴリズムが不味いのかよく分からんが
当初は箱を地面に置いたら摩擦が強すぎて暴れだすし、箱を3つ以上積んだら吹っ飛ぶしで何度心が折れた事か。
とはいえ今まで3回か4回挫折して来てまた今回も諦めるという事態になれば
これは自分はもとより誰が見てもヘタレであるのは明白なので負けじと食い下がった。
当初は箱を地面に置いたら摩擦が強すぎて暴れだすし、箱を3つ以上積んだら吹っ飛ぶしで何度心が折れた事か。
とはいえ今まで3回か4回挫折して来てまた今回も諦めるという事態になれば
これは自分はもとより誰が見てもヘタレであるのは明白なので負けじと食い下がった。
最終的に摩擦力のトルクだけ0.1を掛けたら何故だか嘘のように安定しだして
それから箱を5、6個積もうが微動だにしないし
30個積んだら流石に精度の問題で崩れはするが残骸の積み重なり方がそれっぽい挙動を示すので自分としては満足している。
理由の追求をする気力はもう残っていないものの、とりあえずこれで何かしらのデモが出せる訳だし。
それから箱を5、6個積もうが微動だにしないし
30個積んだら流石に精度の問題で崩れはするが残骸の積み重なり方がそれっぽい挙動を示すので自分としては満足している。
理由の追求をする気力はもう残っていないものの、とりあえずこれで何かしらのデモが出せる訳だし。
現在はQtを使ったインタフェースの整備。
最後に触ったのは半年前ですっかり忘れてしまったがそんなのは些細な事、学び直せば良い。
少なくとも先の見えないシミュレーターの調整よりはずっとマシ。
最後に触ったのは半年前ですっかり忘れてしまったがそんなのは些細な事、学び直せば良い。
少なくとも先の見えないシミュレーターの調整よりはずっとマシ。
予定
7月末までに出来ればデモを、最低限動画をアップする。
8月に入ったら上旬は自前OpenGLエフェクトファイルの整備をしつつOpenGLに慣れる。それと各種シェーダー技法の選定と資料集め。
中旬から下旬にかけては例の「グラフィック強化期間(with OpenGL)」とし、見栄えのする動画やデモを続々とアップしていければと。
8月に入ったら上旬は自前OpenGLエフェクトファイルの整備をしつつOpenGLに慣れる。それと各種シェーダー技法の選定と資料集め。
中旬から下旬にかけては例の「グラフィック強化期間(with OpenGL)」とし、見栄えのする動画やデモを続々とアップしていければと。
(2013/07/24)
接触面
接触法線の計算まだしてなかった。
接触体積に基づくペナルティ法では物体が重なった体積を元に押し出す力を算出するのであるが
重なった部分の凸包だけ渡されても物体がどの方向から、どの角度で衝突したのかがわからず計算のしようがないので
「この面に対して衝突した」という指標が要る。
これが接触法線(または接触面?)。
物体が回転していたりすると場所によって衝突の力がマチマチになると思うが
そこまで詳細にやると計算が面倒という事で通常は全部接触面上で衝突したとみなして力を計算するようだ。
接触体積に基づくペナルティ法では物体が重なった体積を元に押し出す力を算出するのであるが
重なった部分の凸包だけ渡されても物体がどの方向から、どの角度で衝突したのかがわからず計算のしようがないので
「この面に対して衝突した」という指標が要る。
これが接触法線(または接触面?)。
物体が回転していたりすると場所によって衝突の力がマチマチになると思うが
そこまで詳細にやると計算が面倒という事で通常は全部接触面上で衝突したとみなして力を計算するようだ。
で、この接触面。
例えば平らな地面と箱の場合だったら接触面の位置は常に地面上のどこか、法線は地面の向き=上となるので
とりあえず決め打ちでハードコーディングしていて今までまじめに計算して来なかった。
当然これだと平らな地面に箱を1つ静止させるしか出来なくて使いものにならない為、今回ちゃんと実装した。
例えば平らな地面と箱の場合だったら接触面の位置は常に地面上のどこか、法線は地面の向き=上となるので
とりあえず決め打ちでハードコーディングしていて今までまじめに計算して来なかった。
当然これだと平らな地面に箱を1つ静止させるしか出来なくて使いものにならない為、今回ちゃんと実装した。
これからテストして箱を2つ以上出して無事に積み上げられたら動画でも上げてみようかと思っている。
(2013/07/20)
時間が過ぎる
おおっと、もうこんな日付。2D物理に時間費やしすぎじゃないか?
と思って履歴見たらそうでもなかったという。
と思って履歴見たらそうでもなかったという。
じゃあ何してたかといえばGLEffectで2D物理を表示したいけど実際はなんもその準備が出来てなかった!
-> リソースハンドル使ってOpenGLリソースや剛体の管理、あとバグ取り
う~ん・・・大した事してないかも。
-> リソースハンドル使ってOpenGLリソースや剛体の管理、あとバグ取り
う~ん・・・大した事してないかも。
物理シミュのステップ計算
安直にオイラー法で計算を進める分には特に何も考えず
姿勢更新 -> 衝突判定 -> 姿勢更新 ・・・とやっていけば良いのだが
如何せんオイラー法は安定しない。箱を地面に静止させるのも一苦労だ。
去年の年末に出したような動画が妙にスローモーだなと感じた人も居ると思うが、
あれは正にオイラー法で動かしていてあのくらい時間刻みを細かくしなければすぐに箱が吹っ飛んでしまうからなのであった。
姿勢更新 -> 衝突判定 -> 姿勢更新 ・・・とやっていけば良いのだが
如何せんオイラー法は安定しない。箱を地面に静止させるのも一苦労だ。
去年の年末に出したような動画が妙にスローモーだなと感じた人も居ると思うが、
あれは正にオイラー法で動かしていてあのくらい時間刻みを細かくしなければすぐに箱が吹っ飛んでしまうからなのであった。
ならばと、改良オイラー法や4次のルンゲクッタとか使おうとなる訳だが
こいつらは途中で何回か加速度すなわち衝突判定の結果が要る。
こいつらは途中で何回か加速度すなわち衝突判定の結果が要る。
例えば改良オイラー法では一旦オイラー法で次の位置や速度を出してそこで受ける加速度(物体の衝突で受ける力を含む)を計算、
それを踏まえて次ステップでの姿勢を出すわけなので
すべての動くオブジェクトはまず中間姿勢を計算したら一旦そこで止め、改めて衝突判定をして
後半の処理を行う・・という具合になる。・・・で、合ってるよね?多分
それを踏まえて次ステップでの姿勢を出すわけなので
すべての動くオブジェクトはまず中間姿勢を計算したら一旦そこで止め、改めて衝突判定をして
後半の処理を行う・・という具合になる。・・・で、合ってるよね?多分
勿論こういうのは決め打ちで組み込むんじゃなくて
処理負荷や安定性を見ながら複数のアルゴリズムをとっかえひっかえしたいというのは皆が思う事。
従って仮想関数の呼び出しコストがどうのと五月蝿い環境でも無し、インタフェースを決めて動的に切り替えられるようにした。
処理負荷や安定性を見ながら複数のアルゴリズムをとっかえひっかえしたいというのは皆が思う事。
従って仮想関数の呼び出しコストがどうのと五月蝿い環境でも無し、インタフェースを決めて動的に切り替えられるようにした。
ただ当然の如く衝突判定の負荷が改良オイラー法では倍、4次のルンゲクッタだと更にその倍にもなってしまうという。
確かに劇的に安定するのだが。
ちなみに衝突判定を手抜きで4次のルンゲクッタだけど加速度は最初の衝突結果を使いまわしたりなんてのも試したが精度がガタ落ち。
確かに劇的に安定するのだが。
ちなみに衝突判定を手抜きで4次のルンゲクッタだけど加速度は最初の衝突結果を使いまわしたりなんてのも試したが精度がガタ落ち。
ところでOpenDynamicsEngineは1次のオイラー法だと聞いたが、
自分の実装が不味かったのか、単に時間刻みを細かくしているのか
1次のオイラー法にも陰的と陽的があってその辺の違いなのか・・
自分の実装が不味かったのか、単に時間刻みを細かくしているのか
1次のオイラー法にも陰的と陽的があってその辺の違いなのか・・
その他
来る「グラフィック強化月間」に向けて実装したいアルゴリズムを物色。
前にも書いたけどLiSPSMとSSAO(のリベンジ)、それにSSDOやRLRにも挑戦したい。
いや。実はまだある。
DX10相当の機能を使った海レンダリングとか、プロシージャルな木の生成などなど。
Sphere harmonicsも気になったけど前提知識が足りてなさげなのでパス。
前にも書いたけどLiSPSMとSSAO(のリベンジ)、それにSSDOやRLRにも挑戦したい。
いや。実はまだある。
DX10相当の機能を使った海レンダリングとか、プロシージャルな木の生成などなど。
Sphere harmonicsも気になったけど前提知識が足りてなさげなのでパス。
(2013/07/08)
noseq_listの配列一本化
面倒だからと言いつつ気にはなる訳で、えいやっとやってしまった。
どうせvectorやmatrixクラスでboost使ってるんだから今更boost依存も何もない、boost::optionalとboost::variantも遠慮無く使った。
最初はソースちょっと変えればと高をくくってゴチョゴチョといじっていたら案の定訳がわからなくなり
200行にも満たないんだし結局1から組み直したらサクッと行けた。この辺が未だに初心者臭い。
どうせvectorやmatrixクラスでboost使ってるんだから今更boost依存も何もない、boost::optionalとboost::variantも遠慮無く使った。
最初はソースちょっと変えればと高をくくってゴチョゴチョといじっていたら案の定訳がわからなくなり
200行にも満たないんだし結局1から組み直したらサクッと行けた。この辺が未だに初心者臭い。
リファクタリングなので動作は変わらず。詳細はいつも通りgithub/spinner/noseq.hppにて。
GLEffect公開
リポジトリ作っておもむろにアップロード。この前言ってたOpenGLでDirectX9のエフェクトファイル風にシェーダーを書く仕組みである。
勿論途中なので実用性はなく、
このままコンパイルするとやはり前にアップロードしたようなチェッカー模様の四角ポリゴンが回るサンプルが出来上がるだけ。
一応EBNFでフォーマットを書き記してはみたが・・プログラム作りながらboost::spiritの勉強しながらだったので色々とフォーマット的に無駄がある。
そのうち直すと思う。
github/GLEffect
ちなみにコンパイルにはclangを使っているのでgccな人はqtglsl.proファイルを弄ってなんとかして下さい。
勿論途中なので実用性はなく、
このままコンパイルするとやはり前にアップロードしたようなチェッカー模様の四角ポリゴンが回るサンプルが出来上がるだけ。
一応EBNFでフォーマットを書き記してはみたが・・プログラム作りながらboost::spiritの勉強しながらだったので色々とフォーマット的に無駄がある。
そのうち直すと思う。
github/GLEffect
ちなみにコンパイルにはclangを使っているのでgccな人はqtglsl.proファイルを弄ってなんとかして下さい。
こんなとこか。
githubのリポジトリが増えるにつれ妙な満足感と自信が湧いてくる不思議
(2013/07/06)
要素の登録、削除、全走査(巡回)
オブジェクトをある集合に任意で追加や削除して、あるタイミングで全走査をしたいとなった場合のデータ構造について。
今まではstd::unordered_setを使ってテキトーに済ませていたが
自分がプログラミングする上で地味に現れるのでちゃんと実装せねばと前々から思っていた。
間近のケースで言えば「当たり判定のオブジェクト集合」とか。
今まではstd::unordered_setを使ってテキトーに済ませていたが
自分がプログラミングする上で地味に現れるのでちゃんと実装せねばと前々から思っていた。
間近のケースで言えば「当たり判定のオブジェクト集合」とか。
なんでunordered_setじゃ駄目かといえば
stdの実装はチェイン法なのでメモリが散らばるのが宜しくないし
ハッシュで格納場所を決めているわけだが、そもそも検索など必要ないというのもある。
要はオーバースペックなのではと。
巡回速度にしたってstd::mapよりはマシという情報もあるものの、そもそものstd::mapが遅すぎるんで・・
stdの実装はチェイン法なのでメモリが散らばるのが宜しくないし
ハッシュで格納場所を決めているわけだが、そもそも検索など必要ないというのもある。
要はオーバースペックなのではと。
巡回速度にしたってstd::mapよりはマシという情報もあるものの、そもそものstd::mapが遅すぎるんで・・
要求は以下
- メモリを散らかさない
- 追加と削除と巡回は速く
- 集合内における要素の順序はどうでも良い
- 巡回中は追加や削除をしない
1つ目の要求で配列ベースというのが決定。
その上で2つ目の要求に応える為に3つ目に書いた前提を使う。
といっても複雑な事をする必要は全くなく、要素を削除した時に後ろをずらさずに
削除した隙間へ最後尾の要素を突っ込んでやればいい。
追加は勿論最後尾へ。
4つ目はまぁ、読んでそのまま。これが汎用クラスと言い張るにはネックになりそう。
その上で2つ目の要求に応える為に3つ目に書いた前提を使う。
といっても複雑な事をする必要は全くなく、要素を削除した時に後ろをずらさずに
削除した隙間へ最後尾の要素を突っ込んでやればいい。
追加は勿論最後尾へ。
4つ目はまぁ、読んでそのまま。これが汎用クラスと言い張るにはネックになりそう。
ところで問題は追加と削除の時にどうやってオブジェクトの位置を特定するかだが・・
これについてはオブジェクトを登録した時にIDを返し、削除の際はそのIDを渡すようにする
従ってオブジェクト配列とは別に「IDとオブジェクトの位置」の対応付けをするもう一本の配列(UID配列)を用意。
更にUID配列の空き位置を保持するフリーリストを用意。(UID配列まで順序無しにしたら意味が無いので)
これについてはオブジェクトを登録した時にIDを返し、削除の際はそのIDを渡すようにする
従ってオブジェクト配列とは別に「IDとオブジェクトの位置」の対応付けをするもう一本の配列(UID配列)を用意。
更にUID配列の空き位置を保持するフリーリストを用意。(UID配列まで順序無しにしたら意味が無いので)
なんだ。合計配列3本も確保してたら遅いじゃないかと思われるかもしれないが
空き要素のフリーリストというのはUID配列の使ってない要素数分だけしか要らないので、UID配列に統合してしまえる。
更にオブジェクト配列とUID配列の長さは同じになるので、オブジェクト領域とセットで格納してしまえば最終的には1本に出来る・・筈。
空き要素のフリーリストというのはUID配列の使ってない要素数分だけしか要らないので、UID配列に統合してしまえる。
更にオブジェクト配列とUID配列の長さは同じになるので、オブジェクト領域とセットで格納してしまえば最終的には1本に出来る・・筈。
配列の一本化までは面倒くさくてやってないけど二本で済ませるとこまでは完了。
詳細はgithubリポジトリboomstickのnoseq.hppにて。(non-sequenceの意)
詳細はgithubリポジトリboomstickのnoseq.hppにて。(non-sequenceの意)
実装してから思ったがこれはオブジェクトに対してハンドル値を割り当てる、いわゆるリソースマネージャの様な物じゃないか。
違いといえば参照カウンタと弱参照ハンドル、エラーチェックのマジックナンバーの有無くらいか。
であれば前述の機能を追加してこのクラスに弱参照ハンドル生成をプラスしたリソースマネージャを作ればよりスマートな予感。
違いといえば参照カウンタと弱参照ハンドル、エラーチェックのマジックナンバーの有無くらいか。
であれば前述の機能を追加してこのクラスに弱参照ハンドル生成をプラスしたリソースマネージャを作ればよりスマートな予感。
(2013/07/02)
未遂
ううむ。結局2D物理が完成しないまま7月になってしまった。
現在の完成度はデバッガで追いかけて「まぁ、動いてるかなぁ?」くらいのレベル。
だがここに来て剛体の体積や質量のキャッシュ機構がおざなりな事が発覚し、設計中。
読んで字のごとく体積(2Dだと面積だが)や慣性モーメントを計算&キャッシュ&取得する関数を用意するだけなのだが
物によっては体積を求める過程で出る中間変数が、他の計算にも使える事はままある訳で、
そういった時に一旦破棄して再計算は無駄だから体積と重心は一緒に計算してしまってキャッシュのフラグも同じにするとか。
現在の完成度はデバッガで追いかけて「まぁ、動いてるかなぁ?」くらいのレベル。
だがここに来て剛体の体積や質量のキャッシュ機構がおざなりな事が発覚し、設計中。
読んで字のごとく体積(2Dだと面積だが)や慣性モーメントを計算&キャッシュ&取得する関数を用意するだけなのだが
物によっては体積を求める過程で出る中間変数が、他の計算にも使える事はままある訳で、
そういった時に一旦破棄して再計算は無駄だから体積と重心は一緒に計算してしまってキャッシュのフラグも同じにするとか。
これが終わったらシミュレーションは表示できてナンボなので
さっさと例のOpenGL-Effectな表示ルーチンを組み込みたい所ではある。
2D形状のインタフェースが割と固まってきたからきっと3Dになっても前のソースを参考にサクッと行けるはず!との期待を胸に・・
さっさと例のOpenGL-Effectな表示ルーチンを組み込みたい所ではある。
2D形状のインタフェースが割と固まってきたからきっと3Dになっても前のソースを参考にサクッと行けるはず!との期待を胸に・・
添付ファイル