夜風のMixedReality

xRと出会って変わった人生と出会った技術を書き残すためのGeekなHoloRangerの居場所

BlenderのPythonでサーバーを立てMessagePackでメッシュを送信する MixedRealityModelingToolsその②MessagePackを使用したデータの送信

本日はUnity枠です。

現在BlenderからUnity製アプリケーションに向けてネットワーク経由でメッシュ情報を双方向に通信するパッケージを開発しています。

MixedRealityModelingToolsという仮称で開発していますが今回は昨日に引き続きBlender側のコア機能を紹介します。

github.com

redhologerbera.hatenablog.com

〇MessagePackとは?

今回はデータのシリアル化、デシリアライズMessagePackを使用しています。

これはC#Pythonなど多くのプラットフォームで使用することができるバイナリデータの交換用フォーマットで、Json形式のデータとしてバイナリを格納することで非常にデータをコンパクトにすることができます。

msgpack.org

筆者の開発中のツールでは高速な通信を実現するためにMessagePackを使用しています。

〇メッシュをUnityに送信する関数

先述の通りUnity側とBlender側ではMessagePackでシリアライズ化したデータを送信して受け取ります。

これを実現する関数が以下になります。

import msgpack

・・・
def send_mesh_data_to_unity(mesh_data):
    vertices, triangles, normals = mesh_data

    # Convert numpy arrays to list
    vertices_list = np.array(vertices, dtype='<f4').flatten().tolist()
    triangles_list = np.array(triangles, dtype='<i4').flatten().tolist()
    normals_list = np.array(normals, dtype='<f4').flatten().tolist()

    # データを辞書として構築
    data_dict = {
        'vertices': vertices_list,
        'triangles': triangles_list,
        'normals': normals_list
    }

    # MessagePackでシリアライズ
    serialized_mesh_data = msgpack.packb(data_dict)

    #print(f"Serialized data (bytes): {serialized_mesh_data.hex()}")
    verification_mesh_data(serialized_mesh_data)  
    # ここでデシリアライズの確認を行う
    try:
        deserialized_data = msgpack.unpackb(serialized_mesh_data)
        print("Deserialization success!")
        #print(deserialized_data)  # もし必要ならば、デシリアライズされたデータを出力する
    except Exception as e:
        print(f"Deserialization error: {e}")
        return  # エラーが発生した場合、関数をここで終了する

    for client in server_thread.clients:
        try:
            client.sendall(serialized_mesh_data)
            #print(serialized_mesh_data)
          
        except Exception as e:
            print(f"Error while sending mesh data to client: {e}")

import msgpackにてmsgpackを使用しています。このためにはBelnder側にMessagePackを導入する必要があります。この点は別途説明します。

MessagePackは前述のとおりJson形式(正式にはJsonのような)でデータを格納しバイナリ化します。

これを定義しているのが以下です。

   data_dict = {
        'vertices': vertices_list,
        'triangles': triangles_list,
        'normals': normals_list
    }

ここでは頂点、メッシュのインデックス、法線の3つのデータを格納しています。

ここで辞書として追加したデータをMessagePackでシリアライズ化します。

 serialized_mesh_data = msgpack.packb(data_dict)

送信する前のデータ(=実際のデータ)は次のようになっています。

'vertices': [1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, -1.0], 'triangles': [4, 2, 0, 2, 7, 3, 6, 5, 7, 1, 7, 5, 0, 3, 1, 4, 1, 5, 4, 6, 2, 2, 6, 7, 6, 4, 5, 1, 3, 7, 0, 2, 3, 4, 0, 1], 'normals': [0.5773503184318542, 0.5773503184318542, 0.5773503184318542, 0.5773503184318542, 0.5773503184318542, -0.5773503184318542, 0.5773503184318542, -0.5773503184318542, 0.5773503184318542, 0.5773503184318542, -0.5773503184318542, -0.5773503184318542, -0.5773503184318542, 0.5773503184318542, 0.5773503184318542, -0.5773503184318542, 0.5773503184318542, -0.5773503184318542, -0.5773503184318542, -0.5773503184318542, 0.5773503184318542, -0.5773503184318542, -0.5773503184318542, -0.5773503184318542]

これをバイナリデータとして次のようになります。

\x83\xa8vertices\xdc\x00\x18\xcb?\xf0\x00\x00\x00\x00\x00\x00\xcb?\xf0\x00\x00\x00\x00\x00\x00\xcb?\xf0\x00\x00\x00\x00\x00\x00\xcb?\xf0\x00\x00\x00\x00\x00\x00\xcb?\xf0\x00\x00\x00\x00\x00\x00\xcb\xbf\xf0\x00\x00\x00\x00\x00\x00\xcb?\xf0\x00\x00\x00\x00\x00\x00\xcb\xbf\xf0\x00\x00\x00\x00\x00\x00\xcb?\xf0\x00\x00\x00\x00\x00\x00\xcb?\xf0\x00\x00\x00\x00\x00\x00\xcb\xbf\xf0\x00\x00\x00\x00\x00\x00\xcb\xbf\xf0\x00\x00\x00\x00\x00\x00\xcb\xbf\xf0\x00\x00\x00\x00\x00\x00\xcb?\xf0\x00\x00\x00\x00\x00\x00\xcb?\xf0\x00\x00\x00\x00\x00\x00\xcb\xbf\xf0\x00\x00\x00\x00\x00\x00\xcb?\xf0\x00\x00\x00\x00\x00\x00\xcb\xbf\xf0\x00\x00\x00\x00\x00\x00\xcb\xbf\xf0\x00\x00\x00\x00\x00\x00\xcb\xbf\xf0\x00\x00\x00\x00\x00\x00\xcb?\xf0\x00\x00\x00\x00\x00\x00\xcb\xbf\xf0\x00\x00\x00\x00\x00\x00\xcb\xbf\xf0\x00\x00\x00\x00\x00\x00\xcb\xbf\xf0\x00\x00\x00\x00\x00\x00\xa9triangles\xdc\x00$\x04\x02\x00\x02\x07\x03\x06\x05\x07\x01\x07\x05\x00\x03\x01\x04\x01\x05\x04\x06\x02\x02\x06\x07\x06\x04\x05\x01\x03\x07\x00\x02\x03\x04\x00\x01\xa7normals\xdc\x00\x18\xcb?\xe2y\xa7`\x00\x00\x00\xcb?\xe2y\xa7`\x00\x00\x00\xcb?\xe2y\xa7`\x00\x00\x00\xcb?\xe2y\xa7`\x00\x00\x00\xcb?\xe2y\xa7`\x00\x00\x00\xcb\xbf\xe2y\xa7`\x00\x00\x00\xcb?\xe2y\xa7`\x00\x00\x00\xcb\xbf\xe2y\xa7`\x00\x00\x00\xcb?\xe2y\xa7`\x00\x00\x00\xcb?\xe2y\xa7`\x00\x00\x00\xcb\xbf\xe2y\xa7`\x00\x00\x00\xcb\xbf\xe2y\xa7`\x00\x00\x00\xcb\xbf\xe2y\xa7`\x00\x00\x00\xcb?\xe2y\xa7`\x00\x00\x00\xcb?\xe2y\xa7`\x00\x00\x00\xcb\xbf\xe2y\xa7`\x00\x00\x00\xcb?\xe2y\xa7`\x00\x00\x00\xcb\xbf\xe2y\xa7`\x00\x00\x00\xcb\xbf\xe2y\xa7`\x00\x00\x00\xcb\xbf\xe2y\xa7`\x00\x00\x00\xcb?\xe2y\xa7`\x00\x00\x00\xcb\xbf\xe2y\xa7`\x00\x00\x00\xcb\xbf\xe2y\xa7`\x00\x00\x00\xcb\xbf\xe2y\xa7`\x00\x00\x00

\x○○という形式でデータが格納されており、○○部が16進数に変換したデータは以下になります。

131168220024203240000000203240000000203240000000203240000000203240000000203191240000000203240000000203191240000000203240000000203240000000203191240000000203191240000000203191240000000203240000000203240000000203191240000000203240000000203191240000000203191240000000203191240000000203240000000203191240000000203191240000000203191240000000169220042027365717503141546226764513702340116722002420322616700020322616700020322616700020322616700020322616700020319122616700020322616700020319122616700020322616700020322616700020319122616700020319122616700020319122616700020322616700020322616700020319122616700020322616700020319122616700020319122616700020319122616700020322616700020319122616700020319122616700020319122616700

このようにしてシリアライズしたデータを次のようにclient.sendall()でクライアントに送信します。

            client.sendall(serialized_mesh_data)

以上でBlenderからUnityにデータを渡す処理になります。

次回はUnity側について紹介します。