Skip to content

Instantly share code, notes, and snippets.

@tako2
Created November 26, 2025 11:26
Show Gist options
  • Select an option

  • Save tako2/3c35cebc6635cf87090669bc20b73822 to your computer and use it in GitHub Desktop.

Select an option

Save tako2/3c35cebc6635cf87090669bc20b73822 to your computer and use it in GitHub Desktop.
import bpy
import os
import json
from mathutils import Vector, Matrix
# 選択したオブジェクトを取得
objects = bpy.context.selected_objects
if not objects or not any(obj.type == 'MESH' for obj in objects):
print("少なくとも1つのメッシュオブジェクトを選択してください")
exit()
# 全オブジェクトのデータを格納
data = {
"objects": []
}
# 各オブジェクトを処理
for obj in objects:
if obj.type != 'MESH':
continue
# モディファイアを適用したメッシュデータを取得
depsgraph = bpy.context.evaluated_depsgraph_get()
eval_obj = obj.evaluated_get(depsgraph)
mesh = eval_obj.to_mesh(preserve_all_data_layers=True, depsgraph=depsgraph)
# オブジェクトのワールド変換行列を取得
world_matrix = obj.matrix_world
# 頂点データを収集(トランスフォームを適用)
vertices = []
for vert in mesh.vertices:
# ローカル座標をワールド座標に変換
world_co = world_matrix @ vert.co
# vertices.append({
# "index": vert.index,
# "co": [world_co.x, world_co.y, world_co.z]
# })
vertices.append([world_co.x, world_co.y, world_co.z])
# エッジデータを収集
edges = []
for edge in mesh.edges:
# edges.append({
# "index": edge.index,
# "vertices": [edge.vertices[0], edge.vertices[1]]
# })
edges.append([edge.vertices[0], edge.vertices[1]])
# 面と法線
faces = []
normals = []
for p in mesh.polygons:
# 法線もワールド座標系に変換
n_world = obj.matrix_world.to_3x3() @ p.normal
n_world.normalize()
if len(p.vertices) == 3: # 三角形
faces.append(list(p.vertices))
normals.append([round(n_world.x, 6), round(n_world.y, 6), round(n_world.z, 6)])
else:
# 四角形以上を三角形分割
for i in range(1, len(p.vertices) - 1):
tri = [p.vertices[0], p.vertices[i], p.vertices[i + 1]]
faces.append(tri)
normals.append([round(n_world.x, 6), round(n_world.y, 6), round(n_world.z, 6)])
# オブジェクトのマテリアルカラー情報を取得(最初のマテリアルスロットを使用)
material_color = [1.0, 1.0, 1.0, 1.0] # デフォルトは白色(RGBA)
if obj.material_slots and obj.material_slots[0].material:
material = obj.material_slots[0].material
if material.use_nodes:
# プリンシプルBSDFノードのベースカラー(デフォルト)を取得
for node in material.node_tree.nodes:
if node.type == 'BSDF_PRINCIPLED':
base_color = node.inputs['Base Color'].default_value
material_color = [base_color[0], base_color[1], base_color[2], base_color[3]]
break
else:
# ノードを使用しない場合のマテリアルカラー
material_color = list(material.diffuse_color)
# オブジェクトデータを追加
data["objects"].append({
"name": obj.name,
"material_color": material_color,
"vertices": vertices,
"edges": edges,
"faces": faces,
"normals": normals
})
# 一時的なメッシュをクリア
eval_obj.to_mesh_clear()
# JSONファイルに出力
blend_name = bpy.path.basename(bpy.data.filepath)
base_name = os.path.splitext(blend_name)[0] # 拡張子を除いた部分
output_path = os.path.join(bpy.path.abspath("//"), f"{base_name}.json")
#output_path = "C:/path/to/output.json" # 出力パスを適宜変更
try:
with open(output_path, 'w', encoding='utf-8') as f:
json.dump(data, f, indent=4, ensure_ascii=False)
print(f"JSONファイルを出力しました: {output_path}")
except Exception as e:
print(f"ファイル出力エラー: {e}")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment