スクリプト1つでvrmモデルを生成する

251 Views

September 23, 21

スライド概要

関連スライド

各ページのテキスト
1.

【Unity】スクリプト1つで vrmモデルを生成する 名工大B2 dokudami

2.

vrmとは ・あらゆるサービスで、3Dモデルを統一的に使えることを目的とされて作られた規格 ・今流行りの技術?(個人的感覚)

3.

vrmとは 完全に理解したい(小並感) ・あらゆるサービスで、3Dモデルを統一的に使えることを目的とされて作られた規格 ・今流行りの技術?(個人的感覚)

4.

ゼロ?から生成する

5.

①新規プロジェクトの作成 ・今回はUnity2019.4.16f1を使用 ・UnityHub等のインストールの説明は省略

6.

②UniVRMのインポート ・Unityでvrmファイルを扱うために必要 ・Assets > Import Package > Custom Package よりインポート

7.

③新規スクリプトの作成 ・Projectウィンドウで右クリック →Create > C# Script より新規スクリプトを作成

8.

準備は整った

9.

How to Export VRM on Runtime? ・そもそも、どうやって VRMってエクスポートするねん ・>「サンプルあるで」とのこと

10.

サンプルを見る(1) ExportButtonが押された時に 実行される関数 ・LoadとExportが行えるサンプル( Assets/VRM/Samples/RuntimeExporterSample) ・どうやらGameObjectを引数として、 byte配列を返している

11.

サンプルを見る(2) ・GameObject → gltf → byte配列 の順番で変換を行っている ・glTF (GL Transmission Format) はJSONによって3Dモデルやシーンを表現するフォーマットである。 「3DにおけるJPEG」と表現されることもある。 (Wikipediaより)

12.

つまり? VRMに エクスポートする関数 (サンプルにあったやつ) UnityEngine.GameObject byte[] GameObjectを用意して、サンプルにある関数にぶち込めばよい!!

13.

vrmの正体(余談) VRM勉強会03 VRMのバイナリを読もう -VRM一 覧表示を爆速にする - - Speaker Deck (https://speakerdeck.com/m2wasabi/vrmmian-qi ang-hui-03-vrmfalsebainariwodu-mou-vrm-lan-bi ao-shi-wobao-su-nisuru?slide=25) VRMのバイナリとかを見て遊んでた記録 - Kaikiの 雑なぼやき、大体技術 (https://colaiiiyahhou.hatenablog.com/entry/2018/1 0/28/224037) ・バイナリ (binary) とは、本来は二進法のことであるが、情報技術においては、コンピュータが直接的に処理 するために2進数で表現されるデータ(バイナリデータ)のことを指して用いられる (Wikipediaより)

14.

用意するGameObject https://vrm.dev/docs/univrm/humanoid/base_model/ ・ドキュメントを参照してみる ・Animatorがアタッチされていて、 HumanoidAvatarがセットされている必要があるらしい

15.

Unityでの3Dモデル(1) ・一般に人型モデルでは、姿勢制御用の位置情報であるボーンと見た目のメッシュがセットになっている ・メッシュの頂点一つ一つがどのボーンにどれだけ追従するか、というのが設定されている

16.

Unityでの3Dモデル(2) ボーン 位置情報(座標と回転)&親子関係で表現される 位置情報の配列として保持 transform[] transform.position transform.rotation transform.parent 頂点 座標として表現 座標の配列として保持 Vector3[] ポリゴン 頂点配列のインデックスを3つずつ指定することで表 現整数配列保持 int[]

17.

Unityでの3Dモデル(2) ボーン 位置情報(座標と回転)&親子関係で表現される 位置情報の配列として保持 何らかの手段でボーンを回転させる transform[] transform.position →親子構造により、子供のボーンの位置情報が変化 transform.rotation transform.parent →初期位置と現在位置の差分+ウェイト情報をもとに頂 頂点 点座標が移動 座標として表現 座標の配列として保持 Vector3[] →頂点間にポリゴンが描画 →曲がって見える! ポリゴン 頂点配列のインデックスを3つずつ指定することで表 現整数配列保持 int[]

18.

Animatorコンポーネント? https://docs.unity3d.com/ja/2018.4/Manual/class-Animator.html ・Unityでアニメーションをさせたいときに使うコンポーネント ・Controller(状態遷移図) と、Avatar(ボーンの対応付け辞書) を指定して利用する

19.

Animatorコンポーネント? Unityの関数でAvatarファイルを作る関数はあるが、 UniVRMのHumanoid.cs内にあるCreateAvatr()を利用する https://docs.unity3d.com/ja/2018.4/Manual/class-Animator.html ・Unityでアニメーションをさせたいときに使うコンポーネント ・Controller(状態遷移図) と、Avatar(ボーンの対応付け辞書) を指定して利用する

20.

役者はそろいました

21.

設計図を書く

22.

Unityのスクリプト using System.Collections; using System.Collections.Generic; using UnityEngine; public class MakeVRM : MonoBehaviour { // Start is called before the first frame update void Start() { ここに処理を書くだけ } // Update is called once per frame void Update() { } }

23.

①土台を作る // メッシュ用のオブジェクトを生成 GameObject MeshObject = new GameObject("MeshObject"); // 自身の子供にする MeshObject.transform.parent = this.gameObject.transform; // SkinnedMeshRendererをアタッチして取得 SkinnedMeshRenderer smr = MeshObject.AddComponent<SkinnedMeshRenderer>(); // Humanoid.cs(UniVRMのやつ)をアタッチして取得 Humanoid hum = this.gameObject.AddComponent<Humanoid>();

24.

②メッシュを生成 // メッシュを生成 Mesh mesh = new Mesh(); // 法線を再計算 mesh.vertices = new Vector3[]{...(省略)...}; // ポリゴン情報を定義 mesh.triangles = new int[]{...(省略)...}; // 法線を再計算 mesh.RecalculateNormals(); // 作成したメッシュを代入 smr.sharedMesh = mesh;

25.

③マテリアルを設定 // マテリアルを設定 smr.material = new Material(Shader.Find("VRM/MToon"));

26.
[beta]
④ボーンを設定(生成ではない) // 各頂点が何個のボーンに追従するかを定義 byte[] bonesPerVertex = new byte[53]; // 今回は全部1 for(int i=0;i<bonesPerVertex.Length;i++){ bonesPerVertex[i] = 1; } // 各頂点のウェイトとウェイト先を定義 BoneWeight1[] weights = new BoneWeight1[53]; // 各頂点のウェイトとウェイト先を一つずつ入力 weights[0].boneIndex = 0; weights[0].weight = 1; ...(省略)... weights[52].boneIndex = 0; weights[52].weight = 1; // ウェイト情報をメッシュにセット var bonesPerVertexArray = new NativeArray<byte>(bonesPerVertex, Allocator.Temp); var weightsArray = new NativeArray<BoneWeight1>(weights, Allocator.Temp); mesh.SetBoneWeights(bonesPerVertexArray, weightsArray);
27.
[beta]
⑤ボーンを生成 // ボーン配列を定義 Transform[] bones = new Transform[19]; // ボーンの初期位置情報を定義 Matrix4x4[] bindPoses = new Matrix4x4[19]; // 各部位のボーンを生成 bones[0] = new GameObject("Hips").transform; bones[0].position = new Vector3(0,0.4f); bones[0].parent = this.transform; hum.m_Hips = bones[0]; ...(省略)... bones[18] = new GameObject("LeftFoot").transform; bones[18].position = new Vector3(-0.1f,0.1f); bones[18].parent = bones[17]; hum.m_LeftFoot = bones[18]; for(int i=0;i<bindPoses.Length;i++){ bindPoses[i] = bones[i].worldToLocalMatrix * transform.localToWorldMatrix; } // 代入 mesh.bindposes = bindPoses; smr.bones = bones;
28.

⑥Avatarファイルを生成 // CreateAvatar()を実行 Avatar _ava = hum.CreateAvatar(); // Animatorをアタッチして取得 Animator _anim = this.gameObject.AddComponent<Animator>(); // AnimatorにAvatarを代入 _anim.avatar = _ava;

29.

⑦vrmにエクスポートし、保存 // パスを定義 var path = Application.dataPath + "/../export.vrm"; // vrmにエクスポート var vrm = VRMExporter.Export(new UniGLTF.GltfExportSettings(), this.gameObject, new RuntimeTextureSerializer()); // byte配列に変換 var bytes = vrm.ToGlbBytes(); // ファイルに書き込み File.WriteAllBytes(path, bytes);

30.

空のGameObjectを作りアタッチして実行

31.

生成!

32.

生成! 人型ボーン情報 ボーンの階層構造 メッシュとウェイト情報

33.

clusterに持っていく

34.

できました

35.

参考文献 アバターの Mapping タブ - Unity マニュアル[https://docs.unity3d.com/ja/2018.4/Manual/class-Avatar.html] How To Any way to Export VRM on Runtime? · Issue #602 · vrm-c/UniVRM[https://github.com/vrm-c/UniVRM/issues/602] vrm-c/UniVRM: UniVRM is a gltf-based VRM format implementation for Unity[https://github.com/vrm-c/UniVRM]