2010/05/20

Blender - シーンの自動生成(5) 横断歩道を作るの巻き

前回は壁とガードレールを新設、コーナーを丸く、単位をメートルとするあたりをやりました。今回は、横断歩道を作ります。さらに、横断歩道の部分はガードレールを作らないようにします。



出来上がりの図

20100520_1

20100520_2

テクスチャを作ってないので分かりづらいですが、テクスチャを貼るために横断歩道の部分だけ独立したポリゴンになっているのが分かるかと思います。ガードレールの途切れ具合もこんな感じかと。



ガードレール生成部分

「作る予定だったガードレールポリゴンのうち横断歩道の部分だけを消す」ということをするために、Python の区間演算ライブラリであるInterval moduleを使いました。これを使うと区間集合 list of (float, float) 同士の差分が計算できるので、ガードレール区間 - 横断歩道区間を計算してポリゴンを作るということをしています。



横断歩道生成部分

今度は「作る予定だった路面ポリゴンのうち、横断歩道部分に頂点を追加する」ということをしたいのですが、interval module だと連続した区間は1つにまとめられてしまうので、区間の和をとる感じではできませんでした。路面と横断歩道の頂点集合をソートしつつマージ。



TODO

なんといってもテクスチャですね。これがないと地味すぎます。なんすかこれ、業務用ポリゴンですかみたいな。テクスチャを作って、UV座標をセットして貼り付けるみたいなことをする予定です。

2010/04/21

Blender - シーンの自動生成(4)

ゲーム開発の方、しばらく放置してしまいましたが、道路メッシュができないと進まない!ということで久しぶりに進めることにしました。

前回は、踊り場の形をちゃんとしたり、坂を滑らかにしたりする所までやりました。



成功イメージ

今回はこんなです。

20100421_0

20100421_1



壁を作る

壁がないとすぐに車が落ちてしまうので、あった方がいいだろうということで作りました。

長い道路の両側すべてに作りこんだ店を配置するわけにもいかないので、ほとんどの部分はテクスチャでハリボテを作ってそれっぽく見せる、という用途にも使えます。

ちなみに、せっかく作った convex hull コードですが、要らないというかうまくいかない場合があると分かったので外しました。素直に「道路部分の延長」と「踊り場」のそれぞれについてポリゴンを作ったらうまくいきました。

重複頂点が出るので、Blender の "Remove Doubles" 機能を最後に呼んでいます。



ガードレールを作る

今までは床と壁が1個ずつでしたが、壁を1個増やして小さくしてガードレールとしました。原理はたいしたことないですが、今まで1個だったローカル変数とかを2つにするのが面倒。



四角いコーナーをまあるくする

前回ので少し走らせてみたところ、コーナーが丸くないと曲がるときすぐ壁にぶつかってイライラすることが分かったので、角を取ってみました。

コードの変更は少ないですが、なんかもうぐちゃぐちゃになりつつあって、さらに横断歩道の部分はガードレールなしにしたいとか思ったらどこを変えればいいんだろうって感じになってます。む~ん。



単位をあわせる

単位をメートルとする。...とても地味ですが重要なポイントです。

車の大きさ、道路の幅、ガードレールの高さ、建物の高さ等単位を揃えておかないと、なんかサイズ感が違ったオブジェクトが集まってどれを調整したらいいかわかんなくなってしまいます。

スクリーンショットでは、道路の幅は 8m, 歩道の幅は 3m, ガードレールの高さは 1.2m という設定になっています。



おまけ

壁とガードレールを取り付けた時点でのスクリーンショットが残っていたので貼りつけておきます。

20100312

20100312

20100312



次回

triangle mesh の上で車(raycast vehicle)を走らせると、ポリゴンの継ぎ目で車にとんでもない力がかかって横転してしまう、という大きな問題があったので、Bullet 界隈のフォーラムを調べて解決した、という話を書こうかと思います。

オフラインでは進んでたりするんですが、記事化するのが面倒で書いてないネタもいくつかあったりします。

2010/02/05

SIO2でサウンドを鳴らす(2)

前回は、iPhone/iPad 向けゲームエンジンである SIO2 で音を出す方法を調べました。

今回は、Tutorial06 をベースに作っているオレオレゲームに、実際に BGM を追加するところまでやってみます。



動いている様子

いまのところこんな感じで動いています。




Blender でサウンドファイルを指定

前回調べた通り、適当なマテリアルの3番目のテクスチャに ogg ファイルを指定して、適当なオブジェクトにそのマテリアルを設定します。これで sio2_exporter.py を実行して .sio2 ファイルにエクスポートします。



ソースコードの変更

tutorial09 のサウンド関連っぽい行をそのままコピペしてくれば良いです。
初期化したあと、sio2 ファイルに含まれるサウンドを取り出したり登録したりする便利関数を呼びます。


//// Add to createFramebuffer (file EAGLView.mm)
sio2InitAL();


//// Add to templateLoading (file template.mm)
// Bind all unique sound buffer (.ogg) currently in
// the resource manager with to its appropriate material.
sio2ResourceBindAllSoundBuffers( sio2->_SIO2resource );

// Also generate the sound source buffer ID.
sio2ResourceGenId( sio2->_SIO2resource );

// Bind all the sound source to their respective
// sound buffer.
sio2ResourceBindAllSounds( sio2->_SIO2resource );

// Set the volume for the ambient (music) sound source.
sio2->_SIO2window->volume = 0.65f;

// Set the volume for the FX sound source.
sio2->_SIO2window->fx_volume = 0.85f;

// Affect the ambient volume to all ambient sound.
sio2ResourceSetAmbientVolume( sio2->_SIO2resource,
sio2->_SIO2window );

// Affect FX sound volume to all the FX sound.
sio2ResourceSetFxVolume( sio2->_SIO2resource,
sio2->_SIO2window );




Xcode のデバッガについて

当初、(sio2InitAL の呼び忘れで)クラッシュしていたのでデバッガで調べていましたが、変数の値とかいろいろ調べる UI が良かったです。マウスでポイントしていくだけで構造を辿れるのが便利。なんでも GUI でやろうとしないで、中断状態のまま CUI の gdb に移れるのもポイント高いと思いました。

2010/02/03

SIO2でサウンドを鳴らす

SIO2 を使った iPhone/iPad アプリでサウンドを再生する方法を調べました。
これといったドキュメントはないみたいですが、tutorial09, SIO2 source, SIO2 exporter を読んだ感じでは、以下のようになっているようです。


  • 内部で OpenAL を使っている。

  • Ogg 形式のサウンドファイルが再生できる。

  • Blender にて Material と ogg ファイルを関連付ける。

  • 具体的には、Material の 3 番目の texture に ogg ファイルを指定する。

  • (ちなみに、1 番目は Diffuse, 2 番目は Shadowmap として使われるらしい。)

  • sio2_exporter.py が .sio2 ファイルに ogg ファイルを入れてくれる。

  • sio2ResourceBindAllSounds() を呼ぶと、Object に ogg ファイルが関連付けられる。

  • 1 つの sound につき 1 つの SIO2sound インスタンス。

  • SIO2sound の属性として、AUTOPLAY, LOOP, AMBIENT, FX, STREAM がある。

  • AUTOPLAY は起動時に自動的に再生。Blender texture の MipMap 属性でセットされる。

  • LOOP はループ再生。Blender texture の Repeat 属性でセットされる。

  • FX はドップラー効果とか距離に応じた減衰の効果。Blender texture の Interpol 属性でセットされる。AMBIENT はそういう効果なし。

  • STREAM はストリーム再生。ネットとかからダウンロードしつつ再生できる。Blender texture の UseAlpha 属性でセットされる。

  • AUTOPLAY, LOOP, AMBIENT にすると BGM になる。

  • FX にして sio2SoundPlay を呼ぶと、単発のサウンドが再生される。



まだ自分のプロジェクトでやってみたわけじゃないですが、これで音が出せそうな気がします。



exporter と独自パラメータ

SIO2sound の属性のような独自のパラメータは Blender UI に項目がないので、AUTOPLAY: MipMap, LOOP: Repeat のようになんとかして対応付ける必要があります。自分も以前そういうことをやったことがあって、Blender から Collada export したファイルの Spe.R が photon の最大検索半径、Spe.G が云々... という感じで苦労しながら無理やり対応付けていました。SIO2 でも同じことをしているのを見ると共感を覚えます。LOOP: Repeat なんかは意味が通じるのでとても良いマッピングだと思います:)

2010/01/13

shortest path

人材獲得作戦・4 試験問題ほかに出てる問題、pythonで書いてみました。

1時間ちょいかかりました。30分とか速いな....

2010/01/08

Blender - シーンの自動生成(3)

20100108_1

前回は大まかに踊り場を作るところまでやりましたが、今回はさらに以下の変更を加えました。


  • (1)踊り場の形状をタンジェントとか使って厳密に計算した

  • (2)道路同士をなめらかに繋ぐようにした



と、さらっと書きましたが、実装は結構面倒でした。

(1)は、各頂点について、上から見た時の辺の角度(9時の方向を -PI として反時計回りに大きくなる)で辺をソートして、隣り合う辺から生成される道路同士の交点を計算した後に、各辺について左右の交点のうち手前の方に合わせて逆側の点を作って、これらの凸包を踊り場にする...という感じのことをやっています。

(2)は、水平面との角度が踊り場の 0 から坂の角度になるまで、坂と踊り場の間にちょっと傾いたポリゴンを作っていきます。ポリゴンを入れるたびに坂の角度がちょっとずつ急になるのに気付かずハマリ。


拡大図。

20100108_0

あと、よく考えたら道路がない部分に地面を作らないと。道路が全部平らなら地面ポリゴンを1枚置けばいいですが、傾斜があるのでうまいこと地面を生成しないといけないかもです。方針としては、元のグラフ構造からループ部分を検出してポリゴンを作る感じでしょうか。。あと、立体交差のときは地面いらないとか考えないといけなさそうです。む〜ん。

2010/01/02

2D Convex hull algorithm

Convex hull (凸包)を計算する Python コード

与えられた点をピンだと思って、最も左のピンから糸を上に引っ張って、次々と時計回りに巻いていく感じです。最初の点まで帰ってきたら終了です。この方式は、Gift wrapping algorithmと呼ばれているそうです。

リスト処理関数(map, reduce, filter)を使って意外と簡潔に書けたつもりですが、改行が入っちゃうとそんなに短く見えないですね。あと math.atan2 便利。

入力となる点集合は list of (x, y) の形ですが、v[0] で x, v[1] で y にアクセスできればよいので list of Blender.Mathutils.Vector でもよいです。


def convex_hull(vs):
def limit(max_rad, v): return max_rad < v and v - 2 * math.pi or v
def rad(v): return math.atan2(v[1], v[0])
def sub(a, b): return (a[0]-b[0], a[1]-b[1])

node = (reduce(lambda a, b: a[0] < b[0] and a or b, vs), math.pi / 2)
ch = [node[0]]
for i in range(len(vs)):
node = reduce(lambda a, b: a[1] > b[1] and a or b, map(lambda x: (x, limit(node[1], rad(sub(x, node[0])))), filter(lambda x: node[0] != x, vs)))
if ch[0] == node[0]: break
ch.append(node[0])
return ch

# Test code
def convex_hull_test():
vs = [ (0, 0), (0, 1), (1, 1), (1, 0) ]
for i in range(10): vs.append((random.uniform(0.3,0.6), random.uniform(0.3,0.6)))
print "convex hull:", convex_hull(vs)

2010/01/01

Blender - シーンの自動生成(2)

あけましておめでとうございますトラ。

道路同士をシームレスに繋げる

Blender - シーンの自動生成の TODO のうち、道路同士をシームレスに繋げるというのをやりました。(今回は実家のウィンドウズマシンで作業しました。)

20090101_seamless_road

最終版ではないかもしれませんが、こんな感じのメッシュが出来ていればさしあたってOKかな、というところです。


方法

これは意外と面倒で、単に道路の長さを調整するのではなく、踊り場を新たに作らないとうまくいきません。以下、図で説明します。Blender で作れよという感じですが。

(1) とりあえず線を太くして道路ポリゴンにしたもの。

20090101_seamless_road_fig0

(2) こんな風にすれば、シームレスに繋がりそうですが...

20090101_seamless_road_fig1

(3) 坂がある場合、上から見るとシームレスですが、坂の傾きがあるのでひび割れができてしまいます。これを無理やり合わせると、坂がねじれてしまって良くないです。

20090101_seamless_road_fig2

(4) こんな感じで踊り場を作ると、よい具合になります。坂の傾きは、踊り場の分、若干きつめになります。

20090101_seamless_road_fig3

いろいろなパターンに対応するために、実際の踊り場の形はいくつかの点の凸包(Convex hull)にしています。

点集合から Convex hull を求める洗練された python ルーチンはウェブにいくつもありますが、ちょっと(簡潔に)書いてみたかったのでこれもオレオレ版を書きました。これについては後ほど記事を書くかもしれません。


擬似コード


各頂点 A について
それにつながる各頂点 B について
A を道路の幅分ずらした点 FL, FR を計算
FL, FR をそれぞれちょっと B 側にずらした点 BL, BR を計算
A から出ている辺の数が 2 以上なら
点 FL, FR, BL, BR の集合の convex hull を計算
上記からなるポリゴンをつくる(三角形をいくつかつくる)
各辺について
2 つの頂点それぞれの BL, BR 点を元に四角形ポリゴンをつくる
重複する点を削除(Blender の "Remove doubles" 機能)