はじめに

エンジニアの仁科です。
弊社では空間演出するにあたって、たびたびムービングライトを使用します。ただしあまり既存の照明機材やソフトを使うことはありません。
理由は主に2つあり、ひとつは照明オペレーターとしての経験があるメンバーがいないのと、もうひとつはプログラム環境やゲームエンジンなどを使ってシステムを構築する方が、弊社が得意とするインタラクティブなコンテンツと親和性が高いからです。
ただ多くの環境でDMXを扱うためのライブラリやプラグインが用意されてはいるものの、実際のデータをどう取り扱うかのフローは実装者次第となっています。
なので今回はUnreal Engine 5(以下UE5)を使ってDMXの出力とムービングライトを使うための実装方法の一例を紹介できたらと思います。

注意:本記事ではUE5の詳細な操作方法やDMXの規格の説明は省きます。

Imaginite at Sentosa Sensoryscape

DMX出力

UE5ではよくDMXの入力先としてよく使われます。用途としてはバーチャルプロダクションやバーチャルライブ、ショーのシミュレーションなどで、それらの環境を構築するための機能がたくさん準備されています。ほとんどのことはブループリント(以下BP)の作成なしで実装可能です。ただ今回はDMXの出力や照明機材の振る舞いをBPから制御したいので、カスタム可能なDMX出力BPの実装から始めたいと思います。

まず新規プロジェクトを作成し、プラグインを追加していきます。プラグインウィンドウを開き、サーチバーにDMXと打つとDMX関連のプラグインが出てきます。その中から今回はDMX EngineとDMX protocolにチェックマークを付け、再起動を促されるので一度エディターを再起動します。

再度開いたらコンテンツブラウザを右クリック→ブループリントクラス→アクタで新しいBPを作成します。名前は今回はBP_DMXManagerとしておきます。作成したBPをダブルクリックし、コンポーネントの追加からDMXコンポーネントを追加します。

次に新しく変数を作り、キーがIntegerで値がByteのマップに設定します。そのマップをConstruction Scriptでキーが1から512、値は0で初期化しておきます。

DMXの出力部分の実装に入る前に、一度プロジェクト設定の出力ポートの設定をしておきます。プロジェクト設定ウィンドウでdmxと検索するとDMX関連の設定が出てきます。そこの出力ポートの横の⊕をクリックし1つポートが追加されたことを確認します。ここでは出力に関する通信タイプやネットワークカードの選択などを行います。また外部のArtnet-DMX変換機で0ユニバースを使用する場合、プロトコルユニバース再マップを有効にし値を0にしないと送れないのでご注意ください。

またBP_DMXManagerに戻りイベントグラフを開きます。イベントグラフ上で右クリックし、Get DMXSubsystemというノードを探します。作成したらそこの出力ピンからドラッグアンドドロップでノード検索を出し、Send DMXTo Output Portというノードを作成します。Channel to Value Mapに先ほど作成したマップをゲットして繋ぎます。Output Port Referenceはドロップダウンメニューから先ほどプロジェクト設定で追加した出力ポートを設定します。最後にEvent TickからSend DMXTo Output Portへ実行ピンをつなぎます。以上でDMX出力の設定はほぼほぼ完了です。

あとは外部からマップの値を変更できるようにカスタムイベントを用意します。カスタムイベントのインプットにIntegerとByteを追加し、このイベントを通してマップの値を上書きできるようにします。

テストの値を用意して出力のテストをしてみます。下図は512チャンネルすべての値がTestValueで変更されるように組んでいます。

用意ができたらコンパイル、セーブしてレベルにBP_DMXManagerをドラッグアンドドロップして配置します。チャンネルの確認用に下図のDMXツールからチャンネルモニターを出しておきます。準備ができたら実行します。

↓簡単な照明を光らせてみた。

RGB スポットライト BP作成

続いて照明のBPを作成します。既存のスポットライトを使って簡単なRGB計3チャンネルの自作のスポットライトを作っていきます。

コンテンツブラウザで右クリック、ブループリントクラス→アクタで新しいBPを作成します。作成したらビューポートでシリンダーとスポットライトを追加します。シリンダーの名前は”Head”としておきます。

イベントグラフに移り、まずはEvent Begin Playで先ほど作ったDMXManagerを取得し変数にセットしておきます。

続いて下図のように組んでいきます。

  1. 変数を追加します。必要なものは以下です。
    • その照明機材のDMXチャンネルのマップ
    • その照明機材に設定するスタートアドレス
    • テスト用のカラー
  2. 先ほど作成したテスト用のカラーをスポットライトコンポーネントのカラーに適用します。
  3. 先ほど作成したDMXチャンネルのマップにカラーのRGBの値を追加します。
  4. 3で追加したDMXチャンネルをDMXManagerのDMXMapにカスタムイベントを通して追加していきます。

以上が組めたら一度コンパイルし挙動を確認していきます。

レベルに配置し、任意のStartAddressを設定(今回は1にします)し再生します。

先ほど追加したテスト用のカラーの変更に伴い、スポットライトのカラーに適用され、DMXのチャンネルモニターの先ほど設定したスタートアドレス以降の3チャンネル分変化していれば挙動としては大丈夫です。

ムービングライト BP作成

次に先ほど作ったスポットライトをベースに自作でムービングライトを作成します。スポットライトのBPを複製し、名前を”BP_MovingLight”としておきます。もちろん他のDCCツール等で作成したものをインポートしても大丈夫です。

作るうえで重要になるのは階層です。ムービングヘッドはアーム部分が横回転(pan)、ヘッド部分が縦回転(tilt)を担うのでモデリングする際は以下図のように階層付けしてください。

今回実装するにあたって角度とDMXの値の関係性は下記にしようと思います。実際は使用する機材の仕様に合わせてください。

モデルの準備ができたらPanとTiltの機能を追加します。イベントグラフに移動しPanとTiltの変数を追加します。値の範囲は先ほど決めた角度で設定しておきます。

続いて作成した変数をモデルに適用していきます。PanをArmコンポーネントのz(Yaw)、TiltをHeadコンポーネントのx(Roll)にそれぞれセットします。

次に変数の値をDMXのチャンネルに出力していきます。今回作るムービングライトは以下のようなチャンネル構成を想定しています。(実際にこんな単純なムービングライトは存在しないと思いますが、このブログでは基本的な部分だけお伝えするためにシンプルな構成にします。)

  1. Pan
  2. Tilt
  3. R
  4. G
  5. B

元々作っていたRGB部分ADDノードのキーをそれぞれ2, 3, 4に変更し、PanとTilt用にADDノードを作成します。まずPanをゲットし、そこからMap Range Clampedを使い角度をDMXの範囲にリマップします。リマップした値をキーが0のADDノードのバリューにつなぎます。Tiltも同様にしてキーが1のADDノードにつなぎます。できたらコンパイルして動作確認を行っていきます。

レベルに移り、BPを配置しスタートアドレスなどを設定していきます。今回はスタートアドレスを101に設定しています。

Pan、Tiltの値の変化によりDMXの値が変化していれば大丈夫です。

Look at

最後にルックアット機能を実装したいと思います。ルックアットとは指定したターゲットに対して常に正面に向くようにする機能です。この機能を持つことにより数値を変化させてアニメーションさせるよりターゲットとなるアクタを移動させるだけなので簡単にアニメーションを付けることができます。UE5のBPにはFindLookAtRotationという2つのLocationを渡すと一方がもう一方を向くための角度を返してくれるノードがあります。それを先ほど作ったBP_MovingLightに適用した結果がこちら↓

はい、おかしいですね。カメラなどならこれでも大丈夫ですが、ムービングライトは回転をPanとTiltを使って設定する必要があります。この章ではそれをするための計算方法をご紹介できたらと思います。

Pan

まずPanですが、Panはムービングライトにおいて水平方向の回転のみを担っています。

つまりPanを求めるには真上から見た二次元(高さ方向は無視)で角度を計算していきます。その角度を求める計算はatan2という関数を使って行います。atan2は2点のベクトルを渡すと角度を返してくれる関数です。

まずベクトルを求めます。 ベクトルは計算で求めてもよいのですが、今回は簡単に相対的な位置を取得するためにターゲットにアタッチするローカルなコンポーネントを追加します。アタッチをすることで先ほど作った相対座標がベクトルということになります。ここがみそでこれをすることによって設置状況が垂直方向でも水平方向でも対応可能になります。

次に取得した相対座標=ベクトル(dx, dy, dz)の縦方向以外(UE5ではz以外)をatan2の引数に渡し角度を取得します。UE5のatan2ノードは角度(Degree)とラジアン(Radians)を返すもの2種類あるので角度を選択します。

  • Pan = atan2(dy, dx)

これらをBP上でやると以下になります。

こちらをコンパイルして再生すると、

それっぽくなってますね。注意としてはモデルの正面方向の都合などで思ったようにターゲットに向かない場合があります。その場合はモデル側を調整するか角度にオフセットをかけるなどで対応してください。

Tilt

続いてTiltを求めていきます。Panですでに水平方向の回転を取得しているので垂直方向の回転のみで考えます。

Tiltに関してはASINdという関数を使っていきます。ASINdはターゲットの高さ(UE5ではz)を二点間の距離で割ったものを引数として渡します。

  • Tilt = ASINd(dz/d)

これをBP上でやると以下になります。

ここまで出来たらコンパイルして再生します。

垂直設置
水平設置

これでターゲットに対して向く方向のPanとTiltが計算されDMXに出力されるようになっていると思います。もしモデルの回転方向が違う場合は取得したPanとTiltの角度にオフセットをかけて調整してください。

実機に送ってみた

さいごに

今回はUE5でのDMXの出力の方法とムービングライトを扱うための一つの考え方をご紹介させていただきました。今回はUE5で実装しましたが、回転の計算の考え方は違う環境(UnityやTouchdesignerなど)であっても使用可能なものになってます。

また実際の機材においては今回ご紹介したカラーと回転以外にも、ズームやストロボ、ゴボなど様々な機能が搭載されています。コンテンツを制作するうえでそれらが必要になった場合、UE5ではBPやマテリアルなどを使って自由にカスタムが可能です。

今回ご紹介した回転の計算を作っておくと、あらゆるインプット(センシングやコントローラー)などで操作しやすくなります。もしムービングライトに触れる機会がありましたら、試していただければ幸いです。ありがとうございました。



■ワントゥーテンでは中途採用募集中です!

1→10(ワントゥーテン)のカルチャーや、作品のクリエイティブに共感し、自身のより高い成長を求めている方からのご応募をお待ちしています!