Created
November 26, 2025 11:26
-
-
Save tako2/3c35cebc6635cf87090669bc20b73822 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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