Microsoft Meshのスペース内のオブジェクト管理を調べてみた

# Microsoft Meshのスペースの情報はどうなっているのか

Microsoft Meshは公式ドキュメントにある通り以下を実現することができます。

**「ユーザーは世界中のどこからでも、プレゼンスを使用して接続し、空間間で共有し、共同作業を行えます。 」**

https://docs.microsoft.com/ja-jp/mesh/overview


つまりコラボレーションプラットフォームとして利用することが可能です。実際にコラボレーションする際には、ホストと参加者が同じ「スペース」という単位でオブジェクト等を共有し様々な共有体験を通じて意見交換やディスカッションを行うことができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152548/6bf15400-2183-2072-5494-6bea74cd36dc.png)

このようにスペース内で3Dオブジェクト等を配置します。これらの情報は参加者すべてが共有されているのですが、どこでデータ管理されているか少しきになり、調査を行ってみました。

## データそのものはOneDrive下で管理される

Microsoft Meshで利用する情報はすべてMeshアプリでログインしたMSアカウントのOneDrive配下に格納されます。格納場所は「Apps\Microsoft Mesh App(Preview)」内に作成されています（2021/09時点）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152548/05575a38-8536-acdc-c4e7-698d5e4e7fbf.png)

### アプリ内のフォルダ情報(Microsoft Mesh App(Preview)直下)

Meshアプリフォルダの直下には2つの情報を格納するフォルダが存在します。

#### *.spaceフォルダ（各スペース内の情報を管理する）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152548/015a966d-e4a4-6ddc-915f-d9ddbc1ea0e2.png)


Microsoft Mesh内で利用するスペース毎の情報を管理するためのフォルダです。スペース内の情報はすべてこのフォルダ内に格納されています。スペース内でオブジェクトを配置した場合にはこのフォルダ内にその情報(後述)が格納されています。spaceフォルダは複数作成することができます。ログイン時にはHomeスペースにいるため最低限1つはspaceフォルダが存在することになります。

#### MyContent

Microsoft Mesh内でカスタムオブジェクトを格納するためのフォルダです。あらかじめよく使う3Dオブジェクト等をこのフォルダに格納しておくと、Meshアプリからオブジェクトを利用することができます。実際に配置すると以下のような形で一覧表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152548/09fd820c-39ea-89ec-679b-14cb8c21e667.png)

### アプリ内のファイル情報

Meshアプリとしての設定などについてはMicrosoft Mesh App(Preview)直下にいくつかのjsonファイルが用意されその中で情報が管理されています。

| ファイル名 | 説明 |
|:-:|:-:|
|avatar.json|アバター定義ファイル。Meshアプリ内で利用するアバターの設定（髪型や服装など）を記録|
|contacts.json|招待済みユーザのアカウント情報管理ファイル。過去招待したユーザアカウントの情報を記録|
|index.json|スペースの情報。このファイルは各spaceフォルダ内にも格納されています。対象のスペースがホームかどうか等を判別するための情報などが格納されています。|
|prefs.json|Meshの環境定義ファイル。Meshアプリの各機能の有効/無効を管理しています。例えば試験的な機能等の有効/無効もこのファイルで管理されています。|

### spaceフォルダ内直下のデータ

各spaceフォルダ配下には以下の様に実際に空間内に配置しているオブジェクトの各種情報が入っています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152548/0f21a079-9b81-9ffb-efdc-d0709591c3fc.png)

幾つかパターンに分かれてデータを持っています。基本的なデータ構成は以下の3つです。

* オブジェクト生データ(ない場合もあります）
* 空間情報(ない場合もあります）
* オブジェクトメタデータ

上記のうち一番上のオブジェクト生データはOneDriveやローカルからアップロードしたオブジェクトや画像です。Meshアプリ自体がプリセットで持っていないオブジェクトや画像はほかの参加者との共有が必要なため設置したスペースにオブジェクトがコピーされるようになっています。
例えば、OneDrive上で作成したカスタムオブジェクト「cube.glb」データをスペース内に配置した場合は以下のような構成になります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152548/1210cbbe-663f-890f-7f7e-c4f939ea09cb.png)

ここでよくわからないIDのファイルは設置したオブジェクトをGUIDで一意に管理しているようです。

Meshアプリではいくつかのデータタイプがありそれぞれデータの持ち方が少し違います。現在パターンとしてあるのは以下のものです。
まだ調査不足なところもあるので足りないものが見つかったら追加します。

1. オブジェクト型（3Dオブジェクト、画像）
1. インク型（空間にドラッグで描く線）
1. 付箋
1. マーク

※時々情報変わってる印象があります。おそらくメタデータを整理して集約する形になっていそう。

### データの反映

動きを見ている限りはOneDrive内のデータのロードはスペースへの参加時になっているようです。スペース内に入ってからOneDrive上にデータを外部から格納しても認識している様子はなかったです。スペース内での作業はリアルタイムで動的に行われており、その情報が一定のタイミングでOneDrive配下にスナップショットとして残っているような仕掛けになっていて、スペース参加時


#### 1. オブジェクト型（3Dオブジェクト、画像）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152548/9d17615f-e734-c615-01f8-9c13c0051acd.png)


空間に出力するオブジェクトです。3Dオブジェクトはプリセットの地球といったもの、MyContent内に置いたオリジナルのglbデータなどです。画像はHoloLensで撮ったスクリーンショットを含めた画像データが対象になります。

オブジェクトの描画に関するデータは以下のものがセットになります。

* 実データ（*glb,*png等）
* 空間情報（[GUID].obj)
* メタデータ（[GUID].obj.fenixmeta）

*[GUID]:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx形式の一意な文字列

ただ、ここ数日で空間情報をメタデータ側に寄せている修正が入っているのでこういうデータが入っているんだなぁ程度で見ておく方がいいかもしれないです。
（結構な頻度で変わっている気がします。）

##### 実データの格納

プリセット以外のオブジェクトを扱った場合は参加したスペース内にオリジナルのオブジェクトデータが格納される仕様になっているようです。

##### 空間情報
空間情報は[GUID].objファイルの中にバイナリで格納されています。ここにはオブジェクトの情報及び空間情報が格納されています。データはバイナリで格納されています。空間情報としてはUnityと同様の情報を扱っているようです。

* Rotation(x, y, z, w)
* Position(x, y, z)
* Scale(x, y, z)

データ構造は以下の様になっているようです。まだ不明瞭なデータがいくつかあります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152548/e82bf991-052e-3fe3-8b33-bced26e2f36f.png)


先頭4バイト:？？？？
ファイル名:配置したオブジェクトのファイル名
ストレージ:OneDrive(データファイルがOneDrive上) / Local(プリセット等ローカル上にあるデータ)
データ種別:Model(3Dオブジェクト） / Image(画像)
保存場所:CurrentSpaceContent(スペース内に配置) / Local(プリセット等ローカル上にあるデータ)
posision:float型でx,y,zの順
rotation:float型でx,y,z,wの順
scale:float型でx,y,zの順
末尾:0x00




##### メタデータ

メタデータはjson形式でオブジェクトの作成/更新時の情報が格納されています。例えば以下のような情報が格納されています。

```json
{
    "AccountId": "1:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "LastModified": "2021-09-14T23:29:41.5810494+00:00",
    "Type": "object",
    "Version": {
        "Major": 0,
        "Minor": 1,
        "Build": 0,
        "Revision": 0
    }
}
```



#### 2. 付箋

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152548/7183200b-b10a-92fe-11f8-a1dea978562e.png)


空間上に出力できる付箋です。付箋に関する情報は以下の1ファイルだけで構成されます。

* メタデータ（[GUID].sticky.fenixmeta）

##### メタデータ
付箋の場合は空間上の座標、付箋の色、文字列などが格納されています。

```json
{
    "AccountId": "1:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "LastModified": "2021-09-18T06:24:51.2642402+00:00",
    "Type": "sticky",
    "Version": {
        "Major": 0,
        "Minor": 1,
        "Build": 0,
        "Revision": 0
    },
    "Data": {
        "position": {
            "x": -0.06352273,
            "y": 1.5632565,
            "z": -0.312892616
        },
        "rotation": {
            "x": 0.179926217,
            "y": -0.646351,
            "z": 0.159610927,
            "w": 0.724141836
        },
        "localScale": {
            "x": 1,
            "y": 1,
            "z": 1
        },
        "color": {
            "a": 1,
            "r": 0.585000038,
            "g": 0,
            "b": 1
        },
        "text": "テスト",
        "locked": false
    }
}
```

#### 3. マーク

<img width = 500 src = https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152548/4824ff2d-d4e0-8be5-f4fb-7fe83f717ad5.png>

空間上に出力できるマークです。立方体や、いいね、顔などのマークを配置することができます。マークに関しても付箋と同様以下の1ファイルで管理されます。

* メタデータ（[GUID].blk.fenixmeta）

##### メタデータ

付箋の場合と同様空間上の座標、マークの色が定義されています。

```json
{
    "AccountId": "1:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "LastModified": "2021-09-18T06:27:21.7323473+00:00",
    "Type": "block",
    "Version": {
        "Major": 0,
        "Minor": 1,
        "Build": 0,
        "Revision": 0
    },
    "Data": {
        "blockType": "faceShock",
        "position": {
            "x": 0.5080601,
            "y": 1.695062,
            "z": -0.742124
        },
        "rotation": {
            "x": -0.000421320234,
            "y": -0.999877036,
            "z": -0.0006657745,
            "w": -0.0156615321
        },
        "localScale": {
            "x": 25.7182,
            "y": 25.7182,
            "z": 25.7182
        },
        "color": {
            "a": 1,
            "r": 0,
            "g": 1,
            "b": 0.5
        },
        "locked": false
    }
}
```

マークの種類はblockTypeに定義されていて以下の種類が今は提供されています。

| blockType | マーク |形状| blockType | マーク |形状|
|:-:|:-:|:-:|:-:|:-:|:-:|
| cube  | 立方体   | <img width = 100 src = https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152548/568a447c-a2de-ab44-d7f8-4e7f7c14ebd0.png> |circleArrow  | 円の中に矢印 |  <img width = 100 src = https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152548/9b9a3d98-0d66-544b-dad1-acdd033e6afb.png> |
| rectangle  | 直方体  |  <img width = 100 src = https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152548/8211ce09-fd27-b52c-8e67-7681f86baa8d.png> |circleInfo  | 円の中にi | <img width = 100 src = https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152548/3d04f45c-1dd3-4e67-0c3c-cc8af8f46970.png>  |
| cylinder  | 円柱  | <img width = 100 src = https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152548/04e774b5-a9dc-00f8-a0dd-46a80871fca8.png>  |circleX  | 円の中に× |  <img width = 100 src = https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152548/144edc3f-a987-2745-a492-2f2313a9394f.png> |
| sphere  | 球体  |  <img width = 100 src = https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152548/a77471d2-7b32-99bf-846e-e85c5f55faff.png> |flag  | 旗  | <img width = 100 src = https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152548/6e3e9e35-46e9-2464-fd19-0ef73b4e1c0a.png>  |
| disc  | 平たい円  |  <img width = 100 src = https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152548/ba6f04ac-e04f-b8b9-3abe-debe8e96e95f.png> |pin  | 虫ピン  | <img width = 100 src = https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152548/57ace8f8-9024-578e-225d-392c6f61af00.png>  |
| pyramid  | ピラミッド  |  <img width = 100 src = https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152548/bea6b68b-06fe-7e29-bad9-0ae172cf62cb.png> |bubble  | 吹き出し  | <img width = 100 src = https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152548/2a032ee7-7f36-2500-bd78-11a4dc6a5fc7.png>|
| arrow  | 矢印  |  <img width = 100 src = https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152548/d196364e-3c17-8cca-c3d5-133ea93d4e86.png> |heart  | ハート  | <img width = 100 src = https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152548/dcb6ab29-fd12-0d5f-f37e-891216a1c520.png>  |
| star  | 星  | <img width = 100 src = https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152548/b9cffd47-3807-aff3-3485-350a0cdd5e70.png>  |quote  | 引用  | <img width = 100 src = https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152548/288340a8-ae18-27e5-27dd-c629fc6edcd9.png>  |
| starShine  | 輝いた星  | <img width = 100 src = https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152548/b93d33d4-464d-3918-bc0d-d935c883d7f7.png>  |cloud  | 雲  | <img width = 100 src = https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152548/a87542d1-360f-a0e3-97ff-7b7aa7970a63.png>  |
| exclamation  | はてな  |  <img width = 100 src = https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152548/93866832-59aa-74b5-a4ea-c6e57edd3d44.png> |lightning  | 稲妻  | <img width = 100 src = https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152548/69d6e948-4289-82a4-9054-44a168f2b21e.png>  |
| question  | ビックリマーク  | <img width = 100 src = https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152548/fb9d2f4a-b6f2-c95f-5260-d8f1e3676d01.png>  |faceSmile  | 顔：笑顔  | <img width = 100 src = https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152548/a26c6e91-8cb7-2ad2-736b-33c4dc10b5d4.png> |
| thumbsUp  | いいね  | <img width = 100 src = https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152548/2be420f1-c5d3-bbfe-6514-3c2d45c18870.png> |faceNeutral  | 顔：素  |  <img width = 100 src = https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152548/3bb2d61a-2511-7e69-656a-98a7b31ed59d.png> |
| thumbsDown  | 悪い評価するあれ  | <img width = 100 src = https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152548/d1c9c912-32fb-0c71-4af3-ebbd8fcef613.png> |faceLaugh  | 顔：笑  | <img width = 100 src = https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152548/01870d5b-f583-a4bc-13c3-65ed605c43d1.png>  |
| circlePlus  | 円の中に+  | <img width = 100 src = https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152548/ab0b7ae4-f4e2-6a3e-10b6-d903adca8c91.png>  |faceFrown  | 顔：しかめっ面  | <img width = 100 src = https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152548/4eaa6d69-b392-9be8-e55d-b35fbbc9e3ed.png>  |
| circleExclamation  | 円の中にビックリマーク  | <img width = 100 src = https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152548/0cdf0a72-9e53-0c1d-76c3-3975c33da8db.png>  |faceAngry  | 顔：怒り  | <img width = 100 src = https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152548/ea78a662-e91a-8509-b5da-c183da4e57cf.png>  |


#### 4. インク型（空間にドラッグで描く線）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152548/f6a2b8bb-877d-fdc8-049b-1be473613559.png)

空間に自由に線を描くことができるオブジェクトです。一回のタップ＆ホールド操作が1つのオブジェクト単位なって管理されます。インクに関しても付箋と同様以下の1ファイルで管理されます。

* メタデータ（[GUID].ink.fenixmeta）

*[GUID]:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx形式の一意な文字列

##### メタデータ

データの中身はこのようになっていて他のメタデータとほぼ一緒です。ただ、インクの情報についてはBase64でエンコードされているcontentプロパティに入っています。この情報を展開するとバイナリデータが入っているので、空間に描いたインクの座標情報などが入っているようです。（3Dオブジェクトの様に単純な構造はしていなかったです）

```json
{
    "AccountId": "1:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "LastModified": "2021-09-18T06:30:04.7096225+00:00",
    "Type": "ink",
    "Version": {
        "Major": 0,
        "Minor": 1,
        "Build": 0,
        "Revision": 0
    },
    "Data": {
        "content": "KxoFAAAAAQAAAM3MTD/NzEw/zcxMPwAAgD/NzEw/zcxMP83MTD8AAIA/CtejPAAAAAALCQ0/lNPpP/yOVT4AAACAAAAAAAAAAAAXovZDKAr3QwAAAAALQXJ0X1JvdW5kZWQAAAAAAAEDAAAA2NK9PRDczT2GmH2/2NK9PRDczT2GmH2/6RcGP/uW7D8Ob08+TFoGP6Zu7D8a81A+r5wGP1JG7D8md1I+Et8GP/0d7D8y+1M+2NK9PRDczT2GmH2/0LTzPEJQNz7Zv3u/6RcGP/uW7D8Ob08+I08IP2I+6z+jYlw+QHIPPxFM5T95y2o+z6sSP9Rj5j/4yWg+0LTzPEJQNz7Zv3u/0LTzPEJQNz7Zv3u/z6sSP9Rj5j/4yWg+xfESP4l75j90nmg+EPcSP7uq5j8Q5Wc+sRwTPy7O5j+ccmc+"
    }
}
```

## まとめ

Microsoft Meshのデータ構造を少し調べてみました。現状はプレビュー版でもあり正式版の頃にはもっと使い勝手がよくなっている可能性もあります。調べている間も時々データが構造が変わっている（持っている場所が変わっていた。ただわかりやすい場所には移動してる）のでこういうデータが格納されているのか程度で知っておくと何かといいかもしれないです。例えば、付箋程度であればMesh内外で情報のやり取りは可能な気がします。