ホーム < ゲームつくろー! < ゲームプログラマのためのBlender

ゲームプログラマのためのBlender スクリプト編
その3 外部テキストファイルの読み込み

[Blender Ver2.7.9]


 ゲーム制作では外部の何らかのデータを元にモデルを作成したり、既にあるモデルに対して外部からの情報を埋め込んだりとモデリングソフトに外部ファイル情報を適用する事があります。例えば地理情報からメッシュを作る時に、すべての高さ情報を手打ちしていたらデザイナさんが死んでしまいます(-_-;。ですから一定のフォーマットで外部ファイルに情報を置き、それをスクリプトで読み込んでメッシュにザーッと流し込む仕組みが必要になります。

 Blenderのスクリプト内でテキストを扱えれば、実に様々な所で潰しが効くようになります。



@ テキストファイルの読み込み

 Pythonでのテキストファイルの読み込みはとても簡単です:

import bpy

# create full path of data.txt
fullpath = bpy.path.abspath("//") + '\\data.txt'

# file open
f = open( fullpath, 'r' )

obj = bpy.context.scene.objects.active
values = f.readline().split(",")
obj.location = ( float( values[0] ), float( values[1] ), float( values[2] ) )

# close file
f.close()

data.txt
2, 5, 1

 上のコードはdata.txtというテキストファイルをオープンし、1行読み込み、それを","で分割、3つの値をオブジェクトの位置として設定しています。

 まず今開いているBlenderのプロジェクト(.blend)があるディレクトリを得る所から始めています。これは「bpy.path.abspath("//")」というコードが担っています。abspath関数は引数のパスから絶対パスを得るものです。この引数に「//」と入れるとBlenderプロジェクトファイルがあるディレクトリの位置になります。今data.txtテキストファイルをプロジェクトファイルと同じディレクトリに入れているとすると、上のように'\\data.txt'と文字列を結合すれば、data.txtへのフルパスが出来上がります。

 続いてそのフルパスを用いてテキストファイルをオープンします。open関数の第1引数にパスを、第2引数にはオープンモードを指定します。オープンモードには次の文字を指定できます:

'r' 読み込み用に開く (デフォルト)
'w' 書き込み用に開き、まずファイルを切り詰める
'x' 排他的な生成に開き、ファイルが存在する場合は失敗する
'a' 書き込み用に開き、ファイルが存在する場合は末尾に追記する
'b' バイナリモード
't' テキストモード (デフォルト)

 読み込みのみなら'r'、それがテキストファイルなら'rt'などと文字を続けます。時にはバイナリファイルも扱う事もあります。その時は'b'です。

 open関数の戻り値は「ファイルオブジェクト」というファイル内のデータを扱う型になります。ファイルオブジェクトの持つ関数を使うとファイル内のデータを読み書き出来ます。テキストデータで改行までの1行のテキストを読み込むのがreadline関数です。戻り値はその1行の文字列になります。さらに文字列も色々関数を持っていまして、その中のsplit関数は引数の文字で文字列を分割してくれて、戻り値に配列として返してくれます。以上から、上のvaluesにはdata.txtの1行目にある数値が['2', '5', '1']として格納されることになります。

 ここで気を付けたいのは、返ってくるのはあくまでも文字列の配列で数字ではありません。最後の行でオブジェクトの位置を設定する時には、数値のタプルにする必要があります。そのためfloat()というキャストを通さねばなりません。

 最後にファイルオブジェクトをclose関数で閉じてメモリを解放します。



A 複数行のデータを連続で読む

 data.txtに大量のデータがずらーっと並んでいる場合はforループを用いて読み込むのがセオリーです。テキストファイルとしてオープンした場合はfor〜in構文を用いてさらに楽ができます:

import bpy

# create full path of data.txt
fullpath = bpy.path.abspath("//") + '\\data.txt'

# file open
f = open( fullpath, 'r' )

obj = bpy.context.scene.objects.active

for record in f:
   values = record.split(",")
   obj.location = ( float( values[0] ), float( values[1] ), float( values[2] ) )

# close file
f.close()
data.txt
2, 5, 1
-3, 4, 2
5, -2, -1

 テキストファイルをオープンしてファイルオブジェクトを得る所までは一緒です。注目はfor〜inの所。これがPythonのfor文です。C言語系の人にはちょっと馴染みが無い書き方ですが、C#やJavaScriptの経験がある方なら「あ〜」という感じではないでしょうか。forの後ろには任意の変数を置け、そこにfor文で更新される値が入ってきます。更新される値の塊はinの後ろに置かれます。ここにテキストファイルのファイルオブジェクトを置くと、readline関数を毎回呼び出してくれます。これにより、ファイルの最後まで1行ずつデータが取り出されrecordに格納される、という便利な事がこの1行で行えるんです。で、すっごく忘れがちなのが文末のコロン[ : ]。必ず必要になります。

 Pythonの言語ルールとして、for文などの範囲は「インデント」で表現する決まりになっています。よって上のfor文の範囲は2行です。これも間違うと挙動がおかしくなるので注意です。

 上のスクリプトに大きな意味はありませんが、動かすとdata.txtの最後のレコード(5, -2, -1)がオブジェクトの位置として設定されます。



 このようにテキストファイルを扱うのはかなり簡単です。またPythonはテキストを扱う関数が充実していてテキストパースに強い言語でもあります。うまく活用すれば、人の手では作れないような幾何学で且つ複雑なモデルなども作れたりしますので、色々試してみて下さい(^-^)