9.13.2016

SiriでArduinoを操作する

TL;DR (目次も兼ねる)

  • SiriでArduinoを操作する
  • しかしSiriとArduinoを直接結ぶのは困難
  • そこでSiri-Arduino間にRaspberry Piを仲介人として置く
  • Raspberry Pi上ではHomebridge(Node.jsベース)を走らせる
  • HomebridgeがSiriのコマンドを扱いやすい通信に変えてくれる
  • Homebridgeはプラグイン(npmよりインストール可能)により種種の通信へ対応できる
  • 今回はRPiとArduino間をHTTPで通信させる
  • Arduinoのスケッチはここのものを使う(少し変更を加える).
  • おまけはHomebridgeのDaemon化

iOSのSiriでArduinoに取り付けられたLED(以後Lightと呼ぶ)を操作してみたいと思い立った. 調べてみたところ,どうやらHomeKit経由で操作すると良いようだ. HomeKitは家電を管理/制御するためのiOS向けフレームワーク(データベースでもある). HomeKitならばSiriによる家電制御も可能であることから,ArduinoをHomeKitに準拠した家電として認識させることが出来れば勝ちとなる. しかしAppleはHomeKitの仕様をオープンには公開していない. そこで今回は非公式ながらもHomeKitを忠実に実装したHomebridgeと呼ばれるAPIを利用し,iOSとArduinoの仲介人になってもらう. ArchLinuxをインストールしたRaspberry Pi Model B+(以後RPi)があるので,HomebridgeはこのRPi上で動かすことにした(ArchLinuxのインストール方法はここを参照).
iPhoneが家電を制御する時に出す信号を"HomeKit"と記したものが上の接続図. HomeKit信号はLANを通ってRPiに入る. RPiで走っているHomebridgeサーバーが信号の意味を解釈して,それに対応する処理を行う. 今回は同LANに繋がる機器(今回はArduino)へHTTPリクエストを送るようセットアップする. これはHomebridgeのプラグインの一である"homebridge-http"により実現できる. 送り先はIPアドレスで指定する. ArduinoはEthernetシールドを追加することでWebサーバーとして機能するので,RPi-Arduino間はHTTP通信とした. Homebridgeのプラグインは種種あるのでArduino以外の機器とでも比較的簡単に通信させることが出来る. 例えばスマートTVへXMLを送信することが出来るので,LAN経由の操作が出来たり,Siriのコマンドに対応したシェルスクリプトをRPi上で実行させることも出来る. もちろんRPiのGPIOを操作することも意味する. これらはnpm(Node.js Package Manager)よりプラグインとして提供されているので好みのプラグインをインストールすることでお望みの通信を実現できる. 可能性は大きい. さて,概念の説明はこのくらいにして実際にセットアップをして行こう. まずはRPiを起動させよう. 私は手元のMacからSSH接続でRPiをセットアップする.
ssh ユーザー名@ホスト名.local
パスワードを入力してログインしよう. まずはパッケージの更新から.
sudo pacman -Syu
次にC++コンパイラ(C++14対応のもの)をインストールする.
sudo pacman -S clang
インストールを終えたら次のコマンドを入力して確認.
g++ -v
出力最後の行に"gcc version 6.1.1 ..."などと表示されればOK. 続けてgitとmake,avahiもインストールしよう.
sudo pacman -S git make avahi
これで準備は完了. お次はHomebridgeのベースであるNode.jsをインストール(参考元).
wget https://nodejs.org/dist/v6.2.2/node-v6.2.2-linux-armv6l.tar.gz
tar -xvf node-v6.2.2-linux-armv6l.tar.gz
cd node-v6.2.2-linux-armv6l
sudo cp -R * /usr/local/
RPi2のモデルBとRPi3の場合は"armv6l"の部分を"armv7l"へ変更する.
node -v
とし"v6.2.2"と表示されればNode.jsとnpmのインストール完了. 次はHomebridge本体とHTTP通信を行うためのプラグインをインストールする.
sudo npm update -g npm
sudo npm install -g homebridge --unsafe-perm
sudo npm install -g homebridge-http
最後はHomebridgeの設定ファイルを用意,編集する.
cd /usr/local/lib/node_module/homebridge
cp config-sample.json ~/.homebridge/config.json
cd ~/.homebridge
nano config.json
次のように編集する.
{
    "bridge": {
        "name": "Homebridge",
        "username": "CC:22:3D:E3:CE:30",
        "port": 51826,
        "pin": "031-45-154"
    },
   
    "description": "This is an example configuration file with one fake accessory and one fake platform. You can use this as a template for creating your own configuration file containing devices you actually own.",
   
    "accessories": [
        {
            "accessory": "Http",
            "name": "Light",
            "switchHandling": "yes",
            "http_method": "GET",
            "on_url": "http://192.168.11.5?9=ON",
            "off_url": "http://192.168.11.5?9=OFF",
            "status_url": "http://192.168.11.5",
            "service": "Light",
            "brightnessHandling": "",
            "brightness_url": "",
            "brightnesslvl_url": "",
            "sendimmediately": "",
            "username": "",
            "password": ""
        }
    ],
   
    "platforms": []
}
bridgeのpinはiOSデバイスとペアリングする時に入力するPIN番号. デフォルト値で問題無いが,気になる方は任意の数字へ変更しよう. accessoriesの中にはプラグインの設定を入力して行く. プラグインごとに設定例があるためそれを参考にする(今回はhomebridge-httpというプラグインなのでこちらを参考にした). "on_url","off_url","status_url"にあるIPアドレスはArduinoのIPアドレスと合わせる. Ctrl+Xを押し,Yを押したらEnterで保存. これで"Light"(ArduinoにつながったLEDを想定)という名前のアクセサリが追加される. Siriに"Turn on the Light(Lightをオンにして)"と言うとon_urlへHTTPリクエストが送られ,"Turn off the Light(Lightをオフにして)"と言えばoff_urlをリクエストする. 設定ファイルに間違いが無ければ次のコマンドでHomebridgeを立ち上げよう.
homebridge
数行の*** WARNING ***が表示されるが無視して問題ない. 枠で囲われた8桁の数字がPINコードになる(設定ファイルの6行目で設定した値).
Sep 11 11:44:00 RPi homebridge[1638]: Scan this code with your HomeKit App on your iOS device to pair with Homebridge:
Sep 11 11:44:00 RPi homebridge[1638]:
Sep 11 11:44:00 RPi homebridge[1638]:     ┌────────────┐
Sep 11 11:44:00 RPi homebridge[1638]:     │ 031-45-154 │
Sep 11 11:44:00 RPi homebridge[1638]:     └────────────┘
Sep 11 11:44:00 RPi homebridge[1638]:
Sep 11 11:44:00 RPi homebridge[1638]: [9/11/2016, 11:44:00 AM] Homebridge is running on port 51826.
このPINコードをiOSのHomeアプリに入力することでペアリングが完了する.
iOSデバイス上でHomeアプリを立ち上げたら"Add Accessory(アクセサリーの追加)"をタップ. 同一LAN上にあるHomebridgeサーバー(RPi)が表示されるのでそれをタップ. Homebridge自体が非公式APIなので認証されていない旨のアラートが出るが"Add Anyway(追加)"を選択する. ここでPINコードの入力を行う. カメラを使った文字認識も使えるが,相手がディスプレイなので上手く認識されない可能性があるため"Enter Code Manually(手動でコードを入力)"をタップ. 8桁のPINコードを入力し,合っていればペアリングは完了する. 追加したアクセサリ(Homebridge)の詳細が表示されるがデフォルトで"Next(次へ)". 続いてLight(homebridge-httpプラグイン)が表示されるのでデフォルトのまま"Done(完了)"をタップ. 以上でHomeKitサイドの設定は完了. 後はHomebridgeとArduino間の通信を上手くやれば良い.

HomeアプリでLightをオンにすると"http://192.168.11.5?9=ON"へアクセスされるようになった. Webサーバーとして動作しているArduino(IPアドレスは192.168.11.5とする)がこれの意味を解釈し,指定されたピンの状態を変えられれば良い. これには以前ここでつくったスケッチがそのまま使える. スケッチ内のIPアドレスをHomebridgeで設定したものに合わせよう. このスケッチではGETメソッドのキーと値により対応するピンの状態を変更させる. "?9=ON"は9番ピンをHIGHに,"?9=OFF"は9番ピンをLOWにする. 今回はsendBackHttpResponse()に変更を加え,ピンの状態をHomeアプリから確認出来るようにしよう.
void sendBackHttpResponse(EthernetClient client)
{
  // HTTPヘッダ
  client.println("HTTP/1.1 200 OK");
  client.println("Content-Type: text/html; charset=UTF-8");
  client.println("Connection: close");
  client.println();
 
  // ペイロード
  int pinState = digitalRead(ledPin);
  client.println(pinState);
}
HTTPレスポンスとして1か0を送ることによりhomebridge-httpは通信先の状態がONかOFFかを判断出来る(status_urlはこの判断を行うためのアドレス). これでArduinoにつながったLEDの状態を返してやればHomeアプリで確認出来るようになる寸法. ArduinoとRPiとiOSデバイスが同一LAN上にあることを確認したらSiriを立ち上げて一言"Turn on the Light(Lightをオンにして)". Siriの信号がRPi上のHomebridgeへ届き,HomebridgeがLightという名前のアクセサリーに対応した処理を行い(指定のURLにアクセスし),ArduinoはHTTPアクセスを受け取ってピンの状態を変化させる. 夢がかなった.
もちろんHomeアプリやコントロールセンターの3ページ目からも操作可能.
HomeアプリのスイッチをタップでLEDを点灯/消灯
スイッチを深くタップすると大きなスライドスイッチが現れる
コントロールセンターの3ページ目からも同様の操作が可能

RPiの電源ONでHomebridgeを走らせる

停電や障害が発生してRPiが再起動した場合,今のままではHomebridgeは勝手に起動してくれない. 次の手順でHomebridgeをDaemon化すればHomebridgeは勝手に起動するようになるので稼働率がだいぶ高まる. 参考元はこちら. 以後"ユーザー名"とあるところはログイン中のユーザー名に置き換えよう. 大まかな手順は次の通り.
  1. /var/内にhomebridgeフォルダを作成
  2. homebridge設定ファイルを上フォルダ内へコピー
  3. /etc/default/内に設定ファイルの在り処を書く
  4. /etc/systemd/system/内にhomebridgeをサービスとして設定
  5. homebridgeサービスを起動して状態を確認
sudo mkdir /var/homebridge
sudo chown ユーザー名 /var/homebridge/
cp ~/.homebridge/config.json /var/homebridge/
sudo nano /etc/default/homebridge
最後のコマンドは手順3にあたる. ここには次の内容を書き込む.
# Defaults / Configuration options for homebridge
# The following settings tells homebridge where to find the config.json file and where to persist the data (i.e. pairing and others)
HOMEBRIDGE_OPTS=-U /var/homebridge

# If you uncomment the following line, homebridge will log more
# You can display this via systemd's journalctl: journalctl -f -u homebridge
# DEBUG=*
重要なのは3行目. Homebridgeの設定ファイル(config.json)の在り処を書き記しておく. 続いてHomebridgeをサービスとして設定して行こう.
sudo nano /etc/systemd/system/homebridge.service
次の内容を書き込む.
[Unit]
Description=Node.js HomeKit Server
After=syslog.target network-online.target

[Service]
Type=simple
User=ユーザー名
EnvironmentFile=/etc/default/homebridge
ExecStart=/usr/local/bin/homebridge $HOMEBRIDGE_OPTS
Restart=on-failure
RestartSec=10
KillMode=process

[Install]
WantedBy=multi-user.target
これで自動起動するサービス,すなわちHomebridgeについて設定することが出来た. 後は次のコマンドでサービスを有効化し起動させれば良い.
sudo systemctl daemon-reload
sudo systemctl enable homebridge
sudo systemctl start homebridge
以後,Homebridgeの設定を変更するには/var/homebridge/config.jsonを編集すれば良い. 編集後は次のコマンドでサービスを再起動して設定を適用する.
sudo systemctl restart homebridge
次のコマンドでサービスの状態を知ることが出来る.
systemctl status homebridge
Homebridgeが出力するログは次のコマンドで読むことができる.
journalctl -f -u homebridge

再追加するときHomeアプリでHomebridgeが見つからない場合は...

都合により再度HomeアプリにHomebridgeを追加する際,Homebridgeが見つからない場合がある. その場合は/var/homebridge/persist/を削除すると上手く行く.
rm -R /var/homebridge/persist/
sudo systemctl restart homebridge
もう一度Homeアプリの"Add Accessory"をタップすればHomebridgeが表示されるようになるはず.
以上!
8.25.2016

レンダリング | Cycles Renderを試す 03

Cycles Renderを試す,最終回の今回はレンダリングが主題です. 手順として,シミュレーション結果から好きなタイミングの水を選び,その水を綺麗に整形してから,よりドラマティックな画になるよう背景を作成して行きます. 最後にレンダリング設定を簡単に行って実際にレンダリングをします.

好きな瞬間を選ぶ

前回のシミュレーションによって次のようなアニメーションを得ることができました.
この中から好きな瞬間をタイムラインを動かして選んでみましょう. 私は水が注がれた直後に見せる,水のダイナミックな瞬間を選びました.
水を選択したらShift+Dで複製します. 複製した水はマウスカーソルにくっついて移動できますが,今回は同じ位置に複製したいのでEscキーを押します. インスペクタのModifierタブを見るとFluidというモディファイアがあるので,Applyをクリックして適用します.
Applyすることでタイムラインに関係無く,その瞬間の形を保持したオブジェクトとなります. 念のためCtrl+Sでセーブしておきましょう. 現状だと複製した(静止した)水と元の(シミュレーション結果の)水が重なっているので,元の水を非表示にします. アウトライナーの目とカメラアイコンをクリックして非表示にしましょう.
目のアイコンはクリックするたびに表示/非表示が切り替わります. しかし目アイコンだけだとワークスペース内での表示/非表示しか切り替わらず,レンダリング結果には表示されてしまうため,カメラアイコンも非表示にしておきます. これで好きな瞬間だけを切り出すことができました. 次は流体シミュレーションの問題点を改善して行きます.

水の形を整える

グラスオブジェクトの目アイコンをクリックして,グラスだけ非表示にしてみましょう. すると,水がギザギザしていることに気づくと思われます.
流体シミュレーションは空間を細分化して計算(シミュレート)しているため,細分化の解像度がこのように結果に現れてしまうのです. 水がゴツゴツしていては現実味がないため,スカルプチャモードにし,水の表面を滑らかにして行きましょう.
ツールパネルからブラシを選択できます.
画像のアイコン部分をクリックするとブラシ一覧が表示されます.
"F Smooth"を選択しましょう. このブラシを使うとオブジェクトの表面を滑らかに出来ます. ギザギザの気になる部分でドラッグすると表面が滑らかになります.
上の画像のように滑らかになったところで,グラスを表示させ,大きさを確認します. グラスから水がはみ出している場合もあると思います. この場合は水をスケールして小さくするか,グラスをスケールで大きくし,水がすべてグラスの中に収まるように位置も含めて修正します.
気になる方はグラスの外に飛び散っている水を消すことも出来ます. Tabキーを押し編集モードにしたらAキーを数回押してどのオブジェクトも選択されていない状況にします. Bキーを押すと範囲選択が出来ます. ドラッグで水しぶきだけを選択しましょう. Ctrl+Lを押すと選択された部分と繋がっている点すべてが選択されます. この状態でXキーを押し,"Vertices"をクリックすると,選択した水しぶきだけを削除することが出来ます.
以上でグラスと水は準備完了です. 後は背景を用意すれば素晴らしい画をレンダリング出来ることでしょう.

背景を作る

グラスと水だけでも綺麗ですが,床と背景を加える事で,よりドラマチックになります. 今回は平面の四角形を2枚用意してマテリアルを設定,それぞれを床と背景にしましょう. まずはShift+Aでオブジェクトを追加します. "Mesh > Plane"を選択します. 追加したらスケールで拡大し,床にしましょう.
次はこの平面をコピー(複製)してから90度回転させ,それを背景にします. まず先ほど追加した床(Planeオブジェクト)だけを選択し,Shift+Dを押します. これでPlaneオブジェクトが複製されます. 続けてRを押すと複製したオブジェクトを回転(Rotate)出来るようになります. 更に続けてXを押すと回転軸をX軸に固定出来ます. この状態で90と入力すると複製したオブジェクトがX軸周りに90度回転します. 正しく回転していることを確認したらEnterで決定しましょう. 後はグラスの背景になるように位置を調整して配置完了です.
上の画像の様に床と背景を設置出来たら,それぞれのマテリアルを設定して行きましょう. まずは背景オブジェクトを選択してからインスペクタのマテリアルタブを開いて"New"をクリック,マテリアルを追加します. "Diffuse BSDF"をクリックし,"Emission"へと変更し直します. "Strength"は3.0にしましょう.
これで背景が光る様になります. この結果を見やすくするため,インスペクタのワールドタブにあるSurface設定のColorを黒へと変更しましょう.
Shift+Zで現状のレンダリング結果を確認します.
狙い通り,背景が光っている様子を確認出来ました. しかし,このままではまぶし過ぎてグラスがよく見えません. そこで,背景の光り方にグラデーションをつけてみます. 今回は下にある画像(テクスチャ)を背景オブジェクトに貼り付け,光り方のグラデーションにしてみます.
上の画像はクリックするとフルサイズの物が表示されるので,ご自由にダウンロードして利用いただけます. まずは背景が選択されていることを確認してインスペクタのマテリアルタブを開きます. "Color"の欄,右端にボタンがあるので,それをクリックします.
するとメニューが表示されるので,Texture欄にある"Image Texture"を選択します.
するとマテリアルタブの"Color"が下の画像の様になります.
"Open"をクリックして,先ほどダウンロードした画像を選択しましょう.
後は"Vector"を設定するだけです. インスペクタのVector欄をクリックしましょう. するとメニューが表示されます. "Generated"を選択します.
以上で光り方にテクスチャ通りのグラデーションが付きました. 再度,レンダリング結果を確認すると次の様になっていることでしょう.
だいぶドラマチックになりました. もしも明るさが十分で無い場合は背景マテリアルの"Strength"を3.0よりも大きな数値へ変更すると良いでしょう. さて,折角なので床も少し凝ったマテリアルにしてみましょう. 床を選択したらマテリアルタブを開きます. いつも通り"New"をクリックしてマテリアルを追加します. "Diffuse BSDF"でも良いのですが,もう少し光沢感が欲しいので"Glossy BSDF"とミックスして使ってみましょう. まずはマテリアルを"Mix Shader"へと変更します. するとShaderという欄が2つ出てきます. 上の欄に"Glossy BSDF",下に"Diffuse BSDF"を選択しましょう. "Factor"という欄は2つのマテリアルの調合率です. 初期値は0.5で半分づつですが,少し光沢感が強すぎるので(好みの問題ですが),今回は0.3へ変更してみました. この数値はレンダリング結果を見ながら好みで決めてみましょう.
さて以上で床のマテリアルも設定し終えました. 最終的なレンダリング結果を見てみましょう.
床は"Diffuse BSDF"ならではのざらつき感に"Glossy BSDF"の光沢感が混ざって,グラスが程よく反射して見えます. さて,次はいよいよ最後の工程です. カメラを好みの位置にセットしてレンダリングをしてみましょう.

レンダリングする

レンダリングをするにはカメラが必要です. カメラがワークスペース内に無い場合はShift+Aで"Camera"を追加しましょう.
ワークスペースの視点を動かして好みのアングルを見つけます. 私は注がれた水が良く見え,かつダイナミックに見えるよう,グラスを少し見上げるようなアングルを選びました. 好きなアングルを見つけたら,Ctrl+Alt+Num0もしくはメニューバーより"View > Align View > Align Active Camera to View"を選択します. これでカメラが現在のアングルと全く同じ位置にセッティングされます.
Num0キーでカメラ視点と通常視点の切り替えが出来ます. カメラ視点の時に現れる四角い点線がカメラに写る範囲を示します. カメラ自体を選択してからインスペクタのカメラタブを開くとカメラの詳細な設定を確認出来ます.
"Focal Length"を変えるとカメラの画角が変化します. これが小さな値になればなるほど広い範囲が写るようになりますが,その代わり歪みが大きくなります. 逆に大きな値にすると歪みが小さくなり,写る範囲が狭くなります(所謂ズームインです). 私は52mmへ変更しました. お好みで調整してみましょう.
Focal Lengthを52mmに調整した後,少しカメラの位置を調整した画が上の画像です. カメラの位置に合わせて,床と背景のサイズにも注意しましょう. もし床や背景の端が見えるようでしたら,床や背景をスケール(拡大)します. さて,これで写真を撮る(レンダリングをする)準備が整いました. 後はレンダリング設定を行って,実際にレンダリングあるのみです. インスペクタのレンダリングタブを開きましょう.
GPUを使ってレンダリングする場合はRender設定のDeviceをGPU Computeへ変更しましょう. GPUの性能にも依りますが,基本的にはCPUよりも高速にレンダリング出来るようになります. Resolution(解像度)設定は出力画像のサイズです. HD画質(1920x1080ピクセル)がデフォルトですが,50%だと半分のサイズでしか出力されません. 今回は1920x1080ピクセルで出力したいので100%へ変更しましょう. Sampling設定のClamp DirectとIndirectを3.00へと変更します(Indirectだけでも問題ありませんが念のため). またSamplesのRenderを32へ変更しサンプル数を増やしましょう(解像度を細かくしましょう). こうすることでレンダリング結果に現れてしまう白い点(ごま塩ノイズのような点々で通称ホタル)が減ります(参考:Blender Guru). Light Path設定のBouncesで光の反射回数の上限値を設定出来ます. 理想的には無限回の反射にしたいのですが,それでは永遠にレンダリングが終わらないので,実際はもう少し現実的な数値にします. 今回はBouncesのMaxを32,DiffuseとGlossyとTransmissionを128へと変更しました.
  • Render:
    • Device: GPU Compute
  • Resolution:
    • X: 1920
    • Y: 1080
    • 100%
  • Frame Range / Frame Rate:
    • Start Frame: 1
    • End Frame: 48
    • Frame Rate: 24
  • Sampling:
    • Clamp Direct: 3.00
    • Clamp Indirect: 3.00
    • Render: 32
  • Volume Sampling:
    • Step Size: 0.05
    • Max Steps: 1024
  • Light Path:
    • Bounces Max: 32
    • Bounces Min: 3
    • Diffuse: 128
    • Glossy: 128
    • Transmission: 128
  • Performance:
    • Tiles X: 64
    • Tiles Y: 64
参考までにレンダリング設定を完了したインスペクタの画像を下に載せます.
以上で全ての設定が完了しました. レンダリングタブ上部にあるカメラボタン(Render)をクリックしてレンダリングを実行しましょう.
上の画像のようにレンダリングタブ内Performance設定のTilesに設定した大きさ(今回は64x64ピクセルの正方形)ごとに区分けされながらレンダリング(光の軌道計算)が行われます. GPUやCPUにはそれぞれ得意とするTileの大きさがあります. 適切なTileの大きさを設定することでレンダリング時間を削減することが出来ます(参考:Blender Guru). デフォルトの64x64ならばCPU,GPU関係無しにある程度速いようです. レンダリングがすべて終了したらF3キーもしくは"Image > Save As Image"でレンダリング結果を画像(デフォルトではPNG形式)として保存出来ます.
以上でBlenderのCycles Renderを用いたフォトリアルなレンダリングチュートリアルは終了です. Cycles Renderの長所は何と言ってもマテリアルを設定するだけでリアルな画を得られる所です. 本チュートリアルで紹介した内容は次のステップアップにも欠かせない,Blenderを扱う上でも基本となる知識ばかりです. Blenderの公式サイトやフォーラム,Wikiなどを参考に,CG製作に磨きをかけてみては如何でしょうか.
7.08.2016

流体シミュレーション | Cycles Renderを試す 02

今回は前回作ったグラスに水を注いでみたいと思います. Blenderの流体シミュレーションを用いることで,水の複雑な動きから,細かく飛び散った水しぶきまでを簡単に再現することが出来ます. まるでピッチャーから水を注いでいるような場面を作って行きましょう.

水を注ぐには

知っておくこと
  • 範囲: Domain
  • 障害物: Obstacle
  • 水源: Fluid, Inflow
"範囲(Domain)"はシミュレーションをする範囲を決めるオブジェクトです. 一般的には立方体や直方体が用いられます. CGの世界の水槽だと考えると良いかもしれません. 小さな水槽ならばシミュレーションに要する時間は短くなりますが,入る水の量は少なくなります. 大きな水槽を用意すれば,より規模の大きなシミュレーションを行えますが,計算にかかる時間はその分増えます. 適切な大きさの水槽を用意することが肝心です. "障害物(Obstacle)"とは水がぶつかるオブジェクトのことです. 水がぶつかる物,すなわち前回作ったグラスになります. "水源(Inflow)"とはその名の通り水の出所です. どんなオブジェクトでも良いのですが,今回は球(UV Sphere)を水源にします.

範囲

まずはシミュレーションする範囲(Domain)を決めます. オブジェクトモード(Tabキーで切り替え),ワイヤフレーム表示(Zキーで切り替え)にしたら,Shift+AキーのMeshからCubeを選択して立方体を追加しましょう. 立方体を適当な大きさまでスケール(Sキー)したら,グラスが収まるように位置を合わせましょう(Gキーを押すか,矢印をドラッグして位置を調整しましょう).
投影法は平行投影(Num5キーで切り替え)にし,Num1キーで正面からの眺めにすると位置を合わせやすいです. 下の画像の様に,グラスの底が水槽(Domain)の底に乗っているような位置がベストです.
Sキーに続けてYキーを押すことで,Y軸に沿ってのみスケール出来るようになります. 今回使う水槽に奥行きはそれほど必要ではないため,下の画像の様に可能な限り小さくしておくことでシミュレーションに要する時間を削減出来ます.
さて,適当な大きさの直方体を用意できたので,これを水槽(Domain)として使うために必要な設定を行ってみましょう. 直方体を右クリックで選択して,インスペクタのフィジックス(Physics)タブを開きましょう. ボールが跳ねているマークのタブです.
Blenderで物理シミュレーションを行う時にはこのタブから各種設定を行います. 今回は流体(Fluid)シミュレーションを行いたいので"Fluid"を選択します.
Type:の欄にある"None"をクリックすると,現在選択中のオブジェクトにどの役割を与えるかを選択するための一覧が表示されます.
"役割"と書きましたが,これは最初に説明した"範囲","障害物","水源"のどれかを指します. 今選択している直方体は"範囲(Domain)"にしたいので,"Domain"を選択しましょう.
Domainの設定項目を調整することで,どのような流体シミュレーションを行うのかを細かく設定することが出来ます. 各項目をすべて展開(▶をクリック)したら次の設定を変更しましょう. 太字の数値は変更が必要な部分です.
  • Resolution:
    • Final: 180
    • Preview: 100
  • Time:
    • Start: 0.000
    • End: 2.000
  • Viscosity Presetes: Water
  • Real World Size: 0.500
  • Surface:
    • Smooth: 2.000
    • Subdivisions: 2
  • Generate: 0.100
解像度(Resolution)やシミュレーションの再生時間(Time)などを変更しました. "Real World Size"とは実世界での水槽の大きさをメートルで指定する設定項目です. オブジェクトのスケール(大きさ)に関わらず,シミュレーションする流体の規模を設定出来ます. 今回は0.5メートルですが,5メートルなどに変更すると水の動き方がグラスからプールのようになります. 念のため,下に各種設定後のインスペクタを画像で載せます. 合わせて参照ください.
もうひとつ. シミュレーションの再生時間を0から2秒までに変更したので,タイムラインもそれに応じて変更しましょう. Blenderは初期状態では1秒間に24フレームの動画を作成するよう設定されています(インスペクタから変更可能です). 今回は2秒間のシミュレーションが収まれば良いので,24フレーム×2秒=計48フレームあれば丁度良い計算になります. タイムラインのEnd:を48へと変更しましょう.
これで正しい再生速度のシミュレーションを得ることが出来るようになります. 以上で範囲(Domain)の設定は終わりです. 次は障害物の設定を行いましょう.

障害物

障害物は前回作ったグラスです. グラスを右クリックで選択したら,Domainと同様,PhysicsインスペクタからFluidを選択しましょう. 今回Type:は"Obstacle(障害物)"を選択します.
変更の必要な設定項目は下記です.
  • Volume Initialization: Both
以上で障害物の設定は終わりです. 次は水源をセットしましょう.

水源

今回,水源には球体を用います. 球から横方向に水がこぼれてゆけば,まるでピッチャーから水が注がれているように見えることでしょう. 下に完成イメージを載せました. 水の出ているピンポン球が水源(Inflow)です.
Shift+AキーのMeshからUV Sphereを選択して球を追加しましょう. 球をグラスの斜め上まで移動させたら,スケールで球を小さくします. この時の球の大きさが,そのまま水の大きさ(こぼれ落ちる太さ)になります. 上の画像を参考に,球の大きさを決めましょう.
さて,お好みの大きさになった所で,PhysicsインスペクタからFluidを選択し,この球を水源(Inflow)として設定して行きます.
変更の必要な設定項目は下記です.
  • Inflow Velocity:
    • X: 0.700
    • Y: 0.000
    • Z: 0.000
この設定(初期速度)をすべて0.000にすると,水は球から真下に向かって落ちて行きます(重力だけが水に加わる力になります). Xだけ0.700にすることで,上の完成イメージのように横方向(X方向)に速度を持って水が落ちて行くようになります. 大きな値にすれば,それだけ横へ向かって(X方向へ向かって)こぼれる力が増します. この値は球の位置に依って変わるため,シミュレーション結果を見て微調整すると良いでしょう. 以上で流体シミュレーションに必要な設定は完了しました. 次は実際にシミュレーションを実行してみましょう.

Bake - シミュレーションの実行

Domain(範囲)を右クリックで選択して,Physicsインスペクタを表示すると"Bake"と書かれたボタンが見えます.
このボタンを押すと,シミュレーションに必要な計算が実行されます. このレンダリング前の計算(下処理)をBakeと呼びます. Bakeボタンにはこの処理に必要なメモリ容量も記されています. 上画像の場合,326.7MBのメモリが必要とあります. もし,この数値が大きすぎる場合にはDomainの直方体をスケールで小さくするか,Resolutionの値を小さくし,適切なメモリ容量になるよう微調整します.
準備が整ったらCmd+S(WindowsはCtrl+S)キーで念のため保存をしてからBakeボタンをクリックしましょう. するとヘッダー(レンダリングエンジン表示欄横)にプログレスバーが表示されます. 水が1フレームずつ計算され,その結果がワークスペースに順次表示されて行きます. Bakeが完了すると,次のようなシミュレーション結果を得られます.
以上で,流体シミュレーションは完了です! 水のこぼれ方が気に入らない場合はDomainのReal World Sizeや水源の位置,大きさを調整したり,初期速度のX値を0.700から変更してBakeしてみましょう. 次は流体の見た目を設定してみましょう.

流体を水にする

BakeするとDomainが流体になります. Domain(流体)を右クリックで選択したらインスペクタのマテリアルを開きましょう.
"New"をクリックするとマテリアルが表示されます. "Diffuse BSDF"を"Glass BSDF"へと変更したら,IOR(屈折率)を1.333に設定しましょう. これでほぼ常温の水の屈折率を再現出来ます.
色も白へと変更すると良いでしょう. 試しにShift+Zキーでレンダリングを行ってみると,シミュレートした流体がまさに水のように見えるはずです.
上の画像では見やすさのため,背景に青いパネルを置きました. さて,次回は水が落ちる一瞬を切り取って,レンダリングするまでを記録する予定です.