本日は現在開発しているMixedRealityModelingToolsの機能開発を行います。
昨日Blenderで現在選択しているオブジェクトのマテリアルを取得するコードを書いていきました。
本日はこれを利用してマテリアル情報をMessagePackでserializeする点までを実装します。
〇マテリアルを取得するコード
今回は次のようなBlenderアドオン用の関数を記述しました。
def get_material_data():
selected_objects = bpy.context.selected_objects #選択されているオブジェクトの取得
material_names = []//マテリアルスロットに複数のマテリアルを保持できるので配列で定義
for obj in selected_objects:
if obj.type == 'MESH': # メッシュオブジェクトのみ処理する
for slot in obj.material_slots: #Materialスロットの数処理
if slot.material:
material_names.append(slot.material.name)#material_nameにマテリアルの名前を格納
return material_names
〇マテリアル情報のシリアライズ化の処理
次にデータをシリアライズしてクライアントに送信するコードについて紹介します。
現在使用しているMessagePackではJsonのような形式でデータをシリアライズ化しています。
この時にPython側では辞書形式でデータを登録します。
今回の場合は次のようになります。
mat_data_dict = {
'header': MAT_HEADER,
'materialname': [selected_material_name],
'rgba': rgba_list
}
headerというのは今回送信するデータとすでに構築済みのメッシュを送信するデータではフォーマットは違うため、データを受け取った今回の場合Unity側でどのフォーマットで処理を行うかを変える必要があり、その際に参照するデータになります。
上記ではマテリアル名と、RGBA(色)を定義しています。
さて、次にこの各パラメータに取得したマテリアルからデータを代入します。
コードは次のようになります。
def send_material_data_to_unity(mat_data):
selected_material_index = 0
if selected_material_index < len(mat_data):
selected_material_name = mat_data[selected_material_index]
selected_material = bpy.data.materials.get(selected_material_name)
MAT_HEADER = "MATE" #データ受信先でデータのシリアライズ形式の選択のために使用 バイナリデータの冒頭部にMATEという文字列が入る。
if selected_material:
# プリンシパルBSDFシェーダーを使用している場合のみ
base_color_node = selected_material.node_tree.nodes.get("Principled BSDF")
if base_color_node: #シェーダーのノードを取得
base_color = base_color_node.inputs["Base Color"].default_value#BaseColorを取得
print(f"Material: {selected_material_name}")
print(f"Base Color (RGBA): ({base_color[0]}, {base_color[1]}, {base_color[2]}, {base_color[3]})")
rgba = list(base_color) #リストに代入
rgba_list = np.array(rgba, dtype='<f4').flatten().tolist()
# Build data as Dictionary
mat_data_dict = {
'header': MAT_HEADER,
'materialname': [selected_material_name],
'rgba': rgba_list
}
# MessagePackデシリアライズ
serialized_mat_data = msgpack.packb(mat_data_dict)
print("material_Send")
else:
print("Invalid material index")
for client in server_thread.clients:
try:
client.sendall(serialized_mat_data) #クライアントにデータを送信
except Exception as e:
print(f"Error while sending mesh data to client: {e}")
以上がマテリアルの取得および送信のコードになります。
本日は以上です。