MRが楽しい

MRやVRについて学習したことを書き残す

MMDでライティング(Lighting)の設定を行う その1

本日は MMD の技術調査枠です。
MMD でライティングの調整にチャレンジします。

ライティングは以下の記事で Unity と blender でも触れています。
bluebirdofoz.hatenablog.com
bluebirdofoz.hatenablog.com

今回は以下の解説動画を参考に実施してみます。
www.nicovideo.jp
www.nicovideo.jp

動画を参考に、事前に以下のツール類を取得してください。
・N2+CShader
・M4レイヤー
・dAdultsShader

因みに MMD のデフォルト時のライティングだとこんな感じです。
f:id:bluebirdofoz:20171013032846j:plain

まず事前準備として、MMDモデルのデータファイルである PMX ファイルの編集が必要となります。
利用する PMX ファイルのスフィアは全て無効化されている必要があります。
今回利用する N2+CShader はスフィアマップの登録欄を法線マップの登録欄として使っているためです。

PMX ファイルを編集するため、PMXEditer を起動します。
ファイル -> 開く から編集する PMX ファイルを読み込みます。
f:id:bluebirdofoz:20171013032857j:plain

モデルを読み込んだら「材質」タブを選択します。
材質の一覧が表示されるので任意の項目を選んで Ctrl+A を押します。
以下のように全ての材質が選択されている状態であることを確認します。
f:id:bluebirdofoz:20171013032908j:plain

スフィアの項目を「無効」に設定します。
f:id:bluebirdofoz:20171013032920j:plain

これで全ての材質のスフィアを無効に設定できました。
ファイル -> 名前を付けて保存 で PMX ファイルを保存します。
f:id:bluebirdofoz:20171013032928j:plain


更に今回は自作の hololens モデルも一緒に適用したいので、こちらも編集を行います。
この際、自作モデルは X ファイルで出力していましたが、PMX ファイルに変換する必要があります。
bluebirdofoz.hatenablog.com

X ファイルはPMXEditer で何も読み込んでいない状態で ファイル -> インポート で読み込み可能です。
f:id:bluebirdofoz:20171013032947j:plain

……のはずなのですが、自作のhololensモデルは読み込めませんでした。
どうもチラホラと発生する事象らしく。原因も様々なようで私のところは特定できず。
ch.nicovideo.jp

じゃあ、blender から mmd_tools のアドオンを介して直接出力すればいいかと試みましたが。。
こちらはこちらで以下のエラーが発生しました。
f:id:bluebirdofoz:20171013033003j:plain

調べてみたところ、mmd_toolsアドオンの問題のようなので別のアドオンを試してみることに。
www.nicovideo.jp

新たに追加した PMX_Model アドオンでエクスポートします。
f:id:bluebirdofoz:20171013033047j:plain

すると無事、PMX ファイルが出力され、PMXEditer で読み込めました。
f:id:bluebirdofoz:20171013033056j:plain

元のオブジェクトにボーンを設定していなかったためか、全ての親ボーンが設定されていませんでした。
f:id:bluebirdofoz:20171014174038j:plain

このままだとオブジェクトを移動させる際に不便なので 編集 -> ボーン -> 「全ての親」ボーンを追加 を選択します。
f:id:bluebirdofoz:20171014174046j:plain

全ての親ボーンが設定されました。MMD上で移動する際はこのボーンを移動させればよくなります。
f:id:bluebirdofoz:20171014174057j:plain

材質のスフィアマップを「無効」にして hololens オブジェクトの準備もOKです。
f:id:bluebirdofoz:20171013033104j:plain
この MMD の手探り感……久しい。が、平日の夜にやることじゃなかった。


追記。
hololens モデルのサイズが変わっており、スケールの調整が必要になったので手順を残して置きます。
モデル編集を行うため、「T」ボタンをクリックして TransformView ウィンドウを起動します。
f:id:bluebirdofoz:20171015043333j:plain

「全ての親」ボーンを選択した状態で「スケール」タブを開きます。
f:id:bluebirdofoz:20171015043344j:plain

スケール値を変更して「スケール」ボタンをクリックすると、表示パネルのモデルに変形が反映されます。
f:id:bluebirdofoz:20171015043351j:plain

変形に問題がなければ、ファイル -> 現在の変形状態でモデル形状を更新 をクリックします。
すると、モデルに変形が反映されます。
f:id:bluebirdofoz:20171015043359j:plain
変形したモデルを別名保存または上書き保存すれば修正完了です。


以降は次回です。次は MMD のプロジェクトにライティング用のエフェクトを追加します。
bluebirdofoz.hatenablog.com

blenderでブーリアンモディファイアを利用して3Dモデルのカットを行う

本日は blender の技術調査枠です。
blenderで3Dモデルを特定サイズでカットを行う方法についてまとめます。

一例ですが、以下の記事でParaViewでSliceの図を出力する方法について紹介しました。
bluebirdofoz.hatenablog.com

このとき、生成された3Dモデルをx3dファイルとして出力したところ、以下のような3Dモデルになりました。
f:id:bluebirdofoz:20171012012804j:plain
少し分かり辛いですが、飛行機のモデルに対して、かなり巨大な図がポリゴンとして出力されています。
必要なのは飛行機の周辺のみなので、図や飛行機の各オブジェクトを同じサイズで切り出したいところです。

以下を参考に実施します。
blender-cg.net

まずは 追加 -> メッシュ から切り出しを行いたい形を選択します。
f:id:bluebirdofoz:20171012012821j:plain
今回は立方体の形で切り出しを行います。
オブジェクトの形に合わせて切り出すので球体や円柱などの形でも同じ作業が可能です。

追加したオブジェクトの拡大縮小と移動を行い、切り出したい領域に合わせます。
f:id:bluebirdofoz:20171012012834j:plain

今回は飛行機の大きさに切り出し範囲を調整しました。
f:id:bluebirdofoz:20171012012843j:plain

ではオブジェクト毎に切り出しを行います。図のオブジェクトを選択します。
f:id:bluebirdofoz:20171012012852j:plain

モディファイアの追加から「ブーリアン」を選択します。
f:id:bluebirdofoz:20171012012901j:plain

ブーリアンモディファイア操作画面が表示されるので、オブジェクトに先ほど設定した領域用オブジェクトを設定します。
f:id:bluebirdofoz:20171012012909j:plain

設定すると領域オブジェクト外のポリゴンが削除されます。「適用」ボタンを押して変更を反映します。
f:id:bluebirdofoz:20171012012918j:plain

領域オブジェクトを非表示にすると……。
f:id:bluebirdofoz:20171012012926j:plain
成功です。図のオブジェクトを指定した範囲で切り出すことができました。
この方法を用いると、複数のオブジェクトを好みの形に合わせて切り出すことができます。

Sharingのメッセージでワールド座標を使ってTransformを共有する

本日は hololens の技術調査枠です。
Sharing でワールド座標を使って位置情報を共有する方法についてです。

以下の SharingTest シーンで作成したプロジェクトを前提とします。
bluebirdofoz.hatenablog.com

Sharing は以下のメッセージ拡張により、共有する情報を増やすことができます。
bluebirdofoz.hatenablog.com

複数人が同じものを同じ位置に見るアプリを作る場合、そのオブジェクトの Transform 情報を共有することになります。
しかし Sharing が行われる際、複数台の hololens 間では同一のワールド座標は共有されません。

これについては以下のページが詳しいです。
blog.xin9le.net
future-architect.github.io

記事に記載されている通り、HologramCollection の座標系が共通の座標系となります。
f:id:bluebirdofoz:20171011231108j:plain

よってそのまま Transform 情報を共有する場合、ワールド座標は使えません。
HologramCollection のローカル座標系を用いる必要があります。
docs.unity3d.com
docs.unity3d.com

ローカル座標系が利用できるのであればこちらがシンプルです。
しかし、アセットを流用する場合などワールド座標系を利用したい場合もあると思います。

そういった場合は各プロセス内の HologramCollection の座標で補正する仕組みを噛ませればワールド座標系で共有可能です。
・GameManager

  /// HologramCollection オブジェクトを指定
  [SerializeField, Tooltip("Sharingベースオブジェクト")]
  private GameObject p_SharingBaseObject;

  /// <summary>
  /// Position変換関数(ワールド座標→Sharing座標)
  /// </summary>
  /// <param name="a_worldPosition">ワールド座標Position</param>
  private Vector3 ChangePositionWorldToSharing(Vector3 a_worldPosition)
  {
    return new Vector3(
        a_worldPosition.x - p_SharingBaseObject.transform.position.x,
        a_worldPosition.y - p_SharingBaseObject.transform.position.y,
        a_worldPosition.z - p_SharingBaseObject.transform.position.z
    );
  }

  /// <summary>
  /// Position変換関数(Sharing座標→ワールド座標)
  /// </summary>
  /// <param name="a_sharingPosition">Sharing座標Position</param>
  private Vector3 ChangePositionSharingToWorld(Vector3 a_sharingPosition)
  {
    return new Vector3(
        a_sharingPosition.x + p_SharingBaseObject.transform.position.x,
        a_sharingPosition.y + p_SharingBaseObject.transform.position.y,
        a_sharingPosition.z + p_SharingBaseObject.transform.position.z
    );
  }

  /// <summary>
  /// Rotation変換関数(ワールド座標→Sharing座標)
  /// </summary>
  /// <param name="a_worldRotation">ワールド座標Rotation</param>
  private Quaternion ChangeRotationWorldToSharing(Quaternion a_worldRotation)
  {
    return Quaternion.Euler(
        a_worldRotation.eulerAngles.x - p_SharingBaseObject.transform.rotation.eulerAngles.x,
        a_worldRotation.eulerAngles.y - p_SharingBaseObject.transform.rotation.eulerAngles.y,
        a_worldRotation.eulerAngles.z - p_SharingBaseObject.transform.rotation.eulerAngles.z
    );
  }

  /// <summary>
  /// Rotation変換関数(Sharing座標→ワールド座標)
  /// </summary>
  /// <param name="a_sharingRotation">Sharing座標Rotation</param>
  private Quaternion ChangeRotationSharingToWorld(Quaternion a_sharingRotation)
  {
    return Quaternion.Euler(
        a_sharingRotation.eulerAngles.x + p_SharingBaseObject.transform.rotation.eulerAngles.x,
        a_sharingRotation.eulerAngles.y + p_SharingBaseObject.transform.rotation.eulerAngles.y,
        a_sharingRotation.eulerAngles.z + p_SharingBaseObject.transform.rotation.eulerAngles.z
    );
  }

hololensアプリ内でデバッグログを表示する

本日は Unity の技術調査枠です。
アプリ内でログを表示する方法について教えて貰えたのでまとめます。

ログの表示イベントをキャッチするには以下の Application.logMessageReceived を使います。
docs.unity3d.com

本イベントからは以下の情報が取得可能です。
logString:ログメッセージ
stackTrace:スタックトレースメッセージ
type:ログ種別(Error,Assert,Warning,Log,Execption)

実際に試してみます。以前、作成したタブレット3DモデルにTextオブジェクトを設定します。
f:id:bluebirdofoz:20171010002346j:plain

以下のようなスクリプトを作成してみました。
・LogMessageManager.cs

  public class LogMessageManager : MonoBehaviour
  {
    /// <summary>
    /// デバッグログ用テキストオブジェクト
    /// </summary>
    [SerializeField, Tooltip("デバッグログ用テキストオブジェクト")]
    private GameObject p_TargetDebugPanelObject;
    /// <summary>
    /// デバッグログ用テキスト
    /// </summary>
    private UnityEngine.UI.Text p_Text;

    /// <summary>
    /// 表示行数
    /// </summary>
    [SerializeField, Tooltip("表示行数")]
    private int p_LineNum = 17;

    /// <summary>
    /// 保持テキスト
    /// </summary>
    private string p_TextMessage;

    /// <summary>
    /// 初期化関数
    /// </summary>
    private void Start()
    {
      // Logメッセージイベント追加
      Application.logMessageReceived += LogMessageOutput;

      p_Text = p_TargetDebugPanelObject.GetComponent<UnityEngine.UI.Text>();
    }

    /// <summary>
    /// Logメッセージイベント処理
    /// </summary>
    private void LogMessageOutput(string condition, string stackTrace, LogType type)
    {
      string textmessage = p_TextMessage;
      textmessage += condition + System.Environment.NewLine;

      string newline = System.Environment.NewLine;
      string [] lines = textmessage.Split(new string[] { newline }, System.StringSplitOptions.RemoveEmptyEntries);
      if (lines.Length > p_LineNum)
      {
        textmessage = "";
        for (int line = lines.Length - p_LineNum; line < lines.Length; line ++)
        {
          textmessage += lines[line] + System.Environment.NewLine;
        }
      }

      p_TextMessage = textmessage;
      p_Text.text = textmessage;
    }
  }

デバッグログ用テキストオブジェクトにTextオブジェクトを設定して起動します。
アプリ内でタブレットを見てみると……。
f:id:bluebirdofoz:20171010002358j:plain
アプリ内でログが確認できました。
解像度の問題があるので、文字サイズは実際に試しながら調整するとよいです。

hololens内でアプリを動かしながらログが確認できるので、実際に動き回る必要があるデバッグの際に特に役立ちそうです。

ParaViewでTubeによる流線とSliceによる図を表示する

本日は ParaView の技術調査枠です。
今回はTubeを使った流線の表示とSliceによる図の表示についてまとめます。

File -> Open から対象のシミュレーションデータを読み込みます。
f:id:bluebirdofoz:20171009050311j:plain

ファイルを読み込んだら Propetries の設定を行い、Apply ボタンをクリックします。
流線と図の表示には internalMesh の表示のみで十分だと思います。
f:id:bluebirdofoz:20171009050325j:plain

まずは流線を表示する方法についてです。
シミュレーションデータを選択した状態で Filters -> Common -> StreamTrecer を選択します。
f:id:bluebirdofoz:20171009050335j:plain

StreamTracer が設定されたら、Properties を設定して Apply ボタンをクリックします。
主に設定するのは以下の項目です。
Point1,Point2:流線を表示するベクトルを設定する。このベクトルを通る流線が表示される。
Resolution:解像度を設定する。解像度が高いほど流線の密度が大きくなる。
f:id:bluebirdofoz:20171009050345j:plain

Apply ボタンを押すと以下のような表示になります。
f:id:bluebirdofoz:20171009050357j:plain
これでも流線の形は分かりますが、より分かりやすくするため、Tube を利用します。

StreamTracer を選択した状態で Filters -> Alphabetical -> Tube を選択します。
f:id:bluebirdofoz:20171009050408j:plain

Tube が設定されたら、Properties を設定して Apply ボタンをクリックします。
主に設定するのは以下の項目です。
Radius:流線の半径の大きさを設定する。
f:id:bluebirdofoz:20171009050417j:plain

Tube による流線の表示ができました。
表示したい流線情報を変更する場合は Display の Coloring からデータ種別を選択します。
f:id:bluebirdofoz:20171009050429j:plain

元となるモデルと一緒に表示したい場合はメッシュの対応を調べて表示する必要があります。
File -> Open から対象のシミュレーションデータを改めて読み込んで設定してみました。
f:id:bluebirdofoz:20171009050443j:plain

次に Slice による図を表示します。
シミュレーションデータを選択した状態で Filters -> Common -> Slice を選択します。
f:id:bluebirdofoz:20171009050450j:plain

Slice が設定されたら、Properties を設定して Apply ボタンをクリックします。
主に設定するのは以下の項目です。
Origin,Normal:図を表示する際の表示位置と法線方向を設定する。
f:id:bluebirdofoz:20171009050458j:plain

Display の Coloring からデータ種別を選択すると以下のように表示されます。
f:id:bluebirdofoz:20171009050506j:plain

BandicamとMovieStudioでHololensアプリ紹介動画を作成する その2(ワイプ・フェードアウト)

前回の続きです。
bluebirdofoz.hatenablog.com

MovieStudio に録画データを取り込みました。
真っ先に実施してみたいのは、2画面を同時に確認できるワイプ処理だと思います。

ワイプ処理の手順は以下の通りです。
まず、メインの動画を「ビデオ」ラインに、小窓側の動画を「ビデオオーバレイ」ラインに取り込みます。
f:id:bluebirdofoz:20171008042030j:plain

そのままだと「ビデオオーバレイ」側の動画が全面に表示されていると思います。
「ビデオオーバレイ」側のラインの右端にある「イベントのパン/クロップ」アイコンをクリックします。
f:id:bluebirdofoz:20171008042040j:plain
すると「イベントのパン/クロップ」ウィンドウが表示されます。

例えば、あるタイミングから「ビデオオーバレイ」側の画面が小さくワイプ表示される表現をしたいとします。
「位置」の縮小が始まる時刻を選択し、「キーフレームの作成」アイコンをクリックします。
f:id:bluebirdofoz:20171008042050j:plain

次にビューアウィンドウを操作してワイプ表示のサイズを決定し、後方のキーフレームに登録します。
f:id:bluebirdofoz:20171008042059j:plain
このとき、プレビューの画面サイズによってはワイプが表示されなくなることがありました。
レンダリングすると問題ないようなので無視して大丈夫です。

この状態で再生すると、キーフレーム間の動きが自動的に補完され、スムーズにワイプするようになります。
プレビューを見ると、ワイプとメイン画面が同時に表示されています。
ドラッグ操作でビデオの再生位置を調節し、2つの画面のタイミングを同期させます。
f:id:bluebirdofoz:20171008042112j:plain

ついでに不要な箇所も削除してしまいましょう。
動画を削除したい位置にカーソルを置き、編集 -> 分割 をクリックすると、ラインが分割されます。
f:id:bluebirdofoz:20171008042121j:plain

不要な箇所をDELETEキーで削除します。
f:id:bluebirdofoz:20171008042132j:plain

折角なので動画の終わり方もブツ切りではなく、フェードアウトしてそれっぽくしましょう。
ビデオラインの右端にマウスカーソルを合わせると、扇形のアイコンが表示されます。
f:id:bluebirdofoz:20171008042142j:plain

この状態でドラッグ操作すると、フェードアウトを設定できます。
f:id:bluebirdofoz:20171008042152j:plain
因みにビデオラインの左端にマウスカーソルを合わせれば、フェードインが設定できます。

以上で編集完了です。
後はレンダリングを行い、動画ファイルの出力を行います。
プロジェクト -> レンダリング をクリックして「名前を付けてレンダリング」ウィンドウを開きます。
f:id:bluebirdofoz:20171008042201j:plain

その1で述べた通り、hololens の動画はサイズが特殊です。
「テンプレートのカスタマイズ」を選択し、1216 × 684 のレンダリング設定を作成します。
f:id:bluebirdofoz:20171008042212j:plain

作成したレンダリングテンプレートを選択して「レンダリング」をクリックします。
f:id:bluebirdofoz:20171008042220j:plain

以上で動画ファイルが作成されます。
f:id:bluebirdofoz:20171007142934g:plain

BandicamとMovieStudioでHololensアプリ紹介動画を作成する その1

本日は Bandicam と MovieStudio を用いたHololensアプリ紹介動画の作成方法についてです。
以前、VRゲーム実況の環境構築として Bandicam と MovieStudio を紹介しました。
bluebirdofoz.hatenablog.com
bluebirdofoz.hatenablog.com

しかし普通に hololens アプリの紹介動画作成ツールとしても役立ったので記録しておきます。
MovieStudio を利用すれば、例えばこんな感じの紹介動画が作れちゃいます。
f:id:bluebirdofoz:20171007142934g:plain
なお、二つの視点から同時に撮影するには、前提条件として同じ3Dモデルを Sharing で同期表示するアプリが必要です。

さて、最初に元となる録画データを作成します。
hololens のメニュー画面の「Video」をクリックする。
f:id:bluebirdofoz:20171007002844j:plain
または、DevicePortal の MixedRealityCapture から録画可能です。
f:id:bluebirdofoz:20171007002852j:plain

2台の hololens で同時に録画を行い、アプリ操作を行います。
DevicePortal での操作だと、アプリ起動中に録画の開始/停止が操作できるため、使いやすいです。

録画が完了したら2台の hololens の DevicePortal から動画をダウンロードします。
f:id:bluebirdofoz:20171007002903j:plain

ここで早速、ダウンロードした mp4 を MovieStudio に取り込んでみました。
すると私の環境では以下のようにメディアオフラインのエラーが表示され、正常にインポートできませんでした。
f:id:bluebirdofoz:20171007002912j:plain

特殊なコーデックを利用しているのかもしれません。
私が利用している MovieStudio は 11 版なので最新のものだとそのまま読み込めるかも。

何せよ、そのままは無理なので一度 Bandicam を経由して読み込み可能な形式に変換することにしました。
幸い PC 上の WindowsMediaPlayer では苦も無く再生できるので、この画面を直接キャプチャします。
f:id:bluebirdofoz:20171007002924j:plain
凄い力業だけど、この際、気にしない。

このとき気付きましたが、hololens の録画データは 1216 × 684 という少し特殊なサイズになっています。
1280 × 720 の設定だと画質が荒くなってしまいますし、640 × 360 だとサイズが小さくなり過ぎてしまいます。
Bandicam のフォーマット設定のサイズをカスタムにしておくと良いです。
f:id:bluebirdofoz:20171007002932j:plain

これで無事、MovieStudio に動画ファイルを読み込むことができました。
f:id:bluebirdofoz:20171007002940j:plain


長くなりそうなので次回へ続きます。