はじめに
本記事は三重大学 計算研 Advent Calendar 2019 二日目です。
サークルでゲーム開発をする際に、Blenderで制作した3DモデルデータもGitでバージョン管理しました。
ゲーム開発でBlenderのファイルを使うためにはFBXにエクスポートしたものを使うほうが都合が良いです。
そこで今回Git Hookという機能を用いることで、Git Push
を実行した際に自動でサムネイル用画像レンダリング ・ FBXエクスポートが行われるようにしました。
これにより、作業が自動化できただけでなく、FBXエクスポートの設定ミスが無くなる、Blendファイルを編集した際のFBXファイルの更新忘れが無くなるというメリットもありました。
今回はGit Hookについての紹介と実際にBlenderにて自動エクスポートを行うための作業について紹介します。
Git Hookとは
Gitの標準の機能であり、特定のGitの作業を行った際にスクリプトを実行できるものです。
種類としては
- クライアント
- pre-commit : コミットメッセージ入力直前にスクリプト実行
- prepare-commit-msg : コミットメッセージ入力用エディタ起動直前にスクリプト実行。デフォルトメッセージを編集したりできる
- commit-msg : コミットメッセージ編集後にスクリプト実行
- pre-push : Push実行直前にスクリプト実行 ← 今回はこれを用いる
- pre-rebase : rebase実行直前にスクリプト実行。ゼロ以外を返せば処理を中断できる。
などがあります。
これらを使えば、
- コミットする前に自動でテスト等を行ったり(pre-commit)
- デフォルトのコミットメッセージを変更したり(prepare-commit-msg)
- 入力されたコミットメッセージが規定にそっているかを調べたり(commit-msg)
が出来ます。
他にもサーバーサイドのもありますが、今回はクライアントサイドのpre-pushを用いて、Git Push
を行った際に自動でレンダリング、エクスポートを行えるようにします。
今回実現すること
developブランチにて、Blendファイルを配置しGit Push
すると自動で
- 画像レンダリング
- FBX生成
- masterブランチに生成したFBXファイルを配置しコミット
が行われるようになります。
想定されるディレクトリ構成は以下のようなものです。
<Push前のDevelopブランチ>
├─Scripts : 自動レンダリング、FBXエクスポート用のスクリプトを置く。具体的な内容は後述する。
└─ProjectName
│
├─blend : blendファイルを置くディレクトリ
│ │ aaa.blend
│ │ bbb.blend
│ │ ccc.blend
│
└─Textures : テクスチャを置くディレクトリ
<Push後のDevelopブランチ>
├─Scripts
└─ProjectName
│ aaa.fbx : [自動生成]blend/aaa.blendをFBXエクスポートしたもの
│ bbb.fbx : [自動生成]blend/bbb.blendをFBXエクスポートしたもの
│ ccc.fbx : [自動生成]blend/ccc.blendをFBXエクスポートしたもの
│
├─blend
│ │ aaa.blend
│ │ bbb.blend
│ │ ccc.blend
│
├─image : [自動生成]レンダリング画像が置かれるディレクトリ
└─Textures : テクスチャを置くディレクトリ
<Push後のmasterブランチ>
└─ProjectName
│ aaa.fbx
│ bbb.fbx
│ ccc.fbx
│
└─Textures
developブランチにてBlendファイルとテクスチャファイルを配置し、Pushすると、
自動でレンダリング、FBX生成がされ、
FBXファイルとテクスチャファイルをmasterにCheckoutします。
開発環境
今回はWindows 10にて、
- Blender 2.8
- Git version 2.23.0.windows.1
で行いました。
作業手順
1. BlenderにPathを通す
まずは、Blender.exeにPathを通します。
環境変数のPathにBlenderのインストールディレクトリを追加します。
Blender公式サイトからインストーラーをダウンロードしてきてインストールした場合は、
"C:\Program Files\Blender Foundation\Blender"
がインストールディレクトリになると思います。
環境変数の編集方法は
https://qiita.com/sta/items/6d29da0dc7069ffaae60
が参考になると思います。
2. レンダリングを行うためのスクリプト
次に、レンダリングを行うためのスクリプトとして、Scripts/render.py
に以下の内容で保存します。
import bpy
bpy.context.scene.render.resolution_x = 1920
bpy.context.scene.render.resolution_y = 1080
bpy.context.scene.render.resolution_percentage = 25
path = bpy.context.blend_data.filepath.rstrip(bpy.path.basename(bpy.context.blend_data.filepath)) + "../image/" + bpy.path.basename(bpy.context.blend_data.filepath).split(".")[0] +".png"
bpy.data.scenes["Scene"].render.filepath = path
bpy.ops.render.render( write_still=True )
これにより、blend/aaa.blendであれば、image/aaa.pngにレンダリング結果が保存されます。
今回はサムネイル画像用のレンダリングなので解像度を1920x1080の25%に指定しています。
3. FBXエクスポートを行うためのスクリプト
次に、FBXエクスポートを行うためのスクリプトとして、Scripts/ExportFBX.py
に以下の内容で保存します。
import bpy,sys
def fbx_export_geometry(arg_filepath='./export.fbx'):
bpy.ops.export_scene.fbx(
filepath=arg_filepath,
object_types={'ARMATURE', 'MESH'},
bake_anim=False,
)
# 出力対象の種別
# 'EMPTY':エンプティ
# 'CAMERA':カメラ
# 'LAMP':ランプ
# 'ARMATURE':アーマチュア
# 'MESH':メッシュ
# 'OTHER':その他
return
# 関数の実行
path = bpy.context.blend_data.filepath.rstrip(bpy.path.basename(bpy.context.blend_data.filepath)) + "../" + bpy.path.basename(bpy.context.blend_data.filepath).split(".")[0] +".fbx"
fbx_export_geometry(path)
これにより、blend/aaa.blendであれば、aaa.fbxにFBXエクスポートされます。
また、ここでカメラやランプを除いて、アーマチュアとメッシュのみをFBXエクスポートしています。
4. 2つのPythonスクリプトを呼び出すためのスクリプト
それでは、この2つのPythonスクリプトを呼び出すためのスクリプトを用意します。
Scripts/convert.sh
に以下の内容で保存します。
#!/bin/bash
log=$(pwd)/gitPush.sh.log
echo "[$(date)] start" >> $log
echo "[Messeage by convert.sh]cd git top level dir(" `git rev-parse --show-toplevel` ")"
cd `git rev-parse --show-toplevel`
for raw in $(git log origin/develop..develop --stat | grep ".blend") ; do
if [ ${raw##*.} = "blend" ]; then
echo "[Messeage by convert.sh] blend file is ${raw}"
echo "[Messeage by convert.sh] Start Render.py"
blender --background ${raw} --python Scripts/Render.py
echo "[Messeage by convert.sh] Start ExportFBX.py"
blender --background ${raw} --python Scripts/ExportFBX.py
fi
done
echo '[Messeage by convert.sh] git commit -m "Auto Generate FBX/render image"'
git add *.fbx
git add *.png
git commit -am "Auto convert FBX and render image"
ログ用のechoの行が挟まっていますが、内容としては、
- Gitのトップレベルディレクトリに移動
- gitのlogから、変更が加わったblendファイルの名前を取得
- 変更が加わったblendファイルに対して、画像レンダリング(Render.py)、FBXエクスポート(ExportFBX.py)を実行する
- FBXファイルとレンダリングpng画像を
git add
する -
git commit
する
となっています。
Git Hook pre-pushの設定
最後に、これまで作成してきたスクリプトをGit Hook pre-pushにて実行されるようにします。
Gitリポジトリには.git
ディレクトリが存在しますが、.git/hooks/
に"pre-push"というファイル名でシェルスクリプトを保存します。
すると、Git Push実行直前にこのスクリプトが実行されるようになります。
直接ここにファイルを置いてもいいですが、.git/hooks/
はGit監視下では無いので、シンボリックリンクを置いて作業しました。
ちなみに、WindowsのPowerShellでのシンボリックリンクの貼り方は、下のコマンドになります。
New-Item -Type SymbolicLink .git/hooks/pre-push -Value Scripts/hooks/pre-push
pre-pushファイルには以下の内容で保存します。
#!/bin/sh
remote="$1"
url="$2"
z40=0000000000000000000000000000000000000000
while read local_ref local_sha remote_ref remote_sha
do
if [[ "${remote_ref##refs/heads/}" = "develop" ]]; then
`git rev-parse --show-toplevel`/Scripts/convert.sh
git checkout master
git checkout develop `git rev-parse --show-toplevel`'/ProjectName/*.fbx'
git checkout develop `git rev-parse --show-toplevel`'/ProjectName/Textures/*'
git commit -m "[Auto commit] Add FBX from develop"
git checkout develop
git push origin master
fi
done
- 作業しているブランチがdevelopかを調べる
-
<Gitのトップレベルディレクトリ>/Scripts/convert.sh
を実行。(ここで自動レンダリング、FBXエクスポートを行う) - テクスチャファイルと、自動生成したFBXファイルをMasterブランチにcheckout
- masterを
git commit
- masterを
git push
といった内容です。
以上により、developブランチにBlendファイルとテクスチャをpushするだけで、自動で
- レンダリング
- FBXエクスポート
- developブランチにレンダリング画像とFBXをcommit
- masterブランチにFBXとテクスチャをCheckout
- masterブランチの
git commit
&push
が行われるようになります。
さいごに
今回、blendファイルが更新されたら自動でFBXも更新するシステムを作ろうとして、Git Hookを使ってみました。
最初はCI/CDが必要なのかな...と思ってGitHub Actionsを試していたのですが、Blenderでレンダリングを行う際にサーバーサイドにGPUが必要なので悩んでいたところ、サークルの先輩にGit Hookを紹介してもらいました。
結果としてやりたかったことが実現でき、さらにクライアント側で完結するコンパクトなシステムになったと思います。
また、Git Hookで呼び出すためにBlender Pythonスクリプトも初めて使ってみましたが、これによりレンダリング・FBXエクスポートの設定ミスが無くなり、特にFBXエクスポートで誤ってランプやカメラを含んでしまいUnityで読み込んだ際におかしくなる問題が無くなりました。
これまでは自動化のモチベーションはあまりなかったのですが、自動化によるメリットをいくつも得れた良い機会でした。
Git Hookには他にもいろいろな発火タイミングがあるので、便利に使っていきたいと思います。