blender.py: add polygon_edge_pairs and filter exports by render visibility

This commit is contained in:
Zack Buhman 2025-05-25 18:18:07 -05:00
parent 6734f06d37
commit 9f4d743dbb

View File

@ -1,5 +1,17 @@
import bpy import bpy
from os import path from os import path
from collections import defaultdict
def sprint(*text):
screen = bpy.data.screens['Scripting']
for area in screen.areas:
if area.type != "CONSOLE":
continue
override = {'screen': screen, 'area': area}
with bpy.context.temp_override(**override):
bpy.ops.console.scrollback_append(text=" ".join(map(str, text)))
print = sprint
def render_vec3(v): def render_vec3(v):
return f"{{{v.x:.6f}, {v.y:.6f}, {v.z:.6f}}}" return f"{{{v.x:.6f}, {v.y:.6f}, {v.z:.6f}}}"
@ -42,6 +54,23 @@ def render_polygons(f, name, polygons):
f.write(f" {{0, 0, 0, 0, -1}}, // {{{s}}}\n") f.write(f" {{0, 0, 0, 0, -1}}, // {{{s}}}\n")
f.write("};\n\n") f.write("};\n\n")
def render_polygon_edge_pairs(f, name, polygons):
by_edge = defaultdict(list)
for i, polygon in enumerate(polygons):
for edge in polygon.edge_keys:
by_edge[frozenset(edge)].append(i)
f.write(f"const edge_polygon {name}_edge_polygons[] = {{\n")
if all(len(p) == 2 for p in by_edge.values()):
for edge, polygons in by_edge.items():
edges = sorted(list(edge))
assert len(edges) == 2, edges
assert len(polygons) == 2, polygons
f.write(f" {{{{{edges[0]}, {edges[1]}}}, {{{polygons[0]}, {polygons[1]}}}}},\n")
else:
f.write("// non-solid polygon\n")
f.write("};\n\n")
def render_uv_map(f, name, name2, uvm): def render_uv_map(f, name, name2, uvm):
f.write(f"const vec2 {name}_{name2}_uvmap[] = {{\n") f.write(f"const vec2 {name}_{name2}_uvmap[] = {{\n")
for uv in uvm: for uv in uvm:
@ -84,21 +113,29 @@ def render_mesh(f, name, mesh):
f.write(f" .uv_layers_length = (sizeof ({name}_uv_layers)) / (sizeof ({name}_uv_layers[0])),\n") f.write(f" .uv_layers_length = (sizeof ({name}_uv_layers)) / (sizeof ({name}_uv_layers[0])),\n")
f.write(f" .materials = {name}_materials,\n") f.write(f" .materials = {name}_materials,\n")
f.write(f" .materials_length = (sizeof ({name}_materials)) / (sizeof ({name}_materials[0])),\n") f.write(f" .materials_length = (sizeof ({name}_materials)) / (sizeof ({name}_materials[0])),\n")
f.write(f" .edge_polygons = {name}_edge_polygons,\n");
f.write(f" .edge_polygons_length = (sizeof ({name}_edge_polygons)) / (sizeof ({name}_edge_polygons[0])),\n")
f.write( "};\n\n") f.write( "};\n\n")
def translate_name(name): def translate_name(name):
return name.replace(".", "_").replace("-", "_") return name.replace(".", "_").replace("-", "_")
def mesh_objects(objects): def mesh_objects(collections):
for object in objects: objects = set()
if object.hide_get(): for collection in collections:
if collection.hide_render:
continue
for object in collection.objects:
assert object.name not in objects, object.name
objects.add(object.name)
if object.hide_render:
continue continue
if object.type == "MESH": if object.type == "MESH":
yield object yield object
def mesh_meshes(objects): def mesh_meshes(collections):
mesh_names = set() mesh_names = set()
for object in mesh_objects(objects): for object in mesh_objects(collections):
mesh = object.data mesh = object.data
if mesh.name in mesh_names: if mesh.name in mesh_names:
continue continue
@ -135,7 +172,7 @@ def render_mesh_materials(f, name, materials):
f.write(f"const mesh_material {name}_materials[] = {{\n") f.write(f"const mesh_material {name}_materials[] = {{\n")
for material in materials: for material in materials:
image = get_texture(material) image = get_texture(material)
assert image is not None, material.name if image is not None:
f.write(f" {{ // {material.name} {image.name}\n") f.write(f" {{ // {material.name} {image.name}\n")
width, height = image.size width, height = image.size
offset = get_texture_offset(image) offset = get_texture_offset(image)
@ -143,22 +180,23 @@ def render_mesh_materials(f, name, materials):
f.write(f" .height = {height},\n") f.write(f" .height = {height},\n")
f.write(f" .offset = {offset},\n") f.write(f" .offset = {offset},\n")
f.write(" },\n") f.write(" },\n")
else:
f.write(" {},\n")
f.write("};\n") f.write("};\n")
def render_materials(f): def render_materials(f):
f.write("const material materials[] = {\n") f.write("const material materials[] = {\n")
for image_name, offset in texture_offsets.items(): for image_name, offset in texture_offsets.items():
name = texture_data_name(image_name) name = texture_data_name(image_name)
print(image_name)
f.write(" {\n") f.write(" {\n")
f.write(f" .start = (void *)&_binary_{name}_start,\n") f.write(f" .start = (void *)&_binary_{name}_start,\n")
f.write(f" .size = (int)&_binary_{name}_size,\n") f.write(f" .size = (int)&_binary_{name}_size,\n")
f.write(f" .offset = {offset},\n") f.write(f" .offset = {offset},\n")
f.write(" },\n") f.write(" },\n")
f.write("};\n"); f.write("};\n\n");
def export_meshes(f): def export_meshes(f):
for mesh in mesh_meshes(bpy.context.scene.objects): for mesh in mesh_meshes(bpy.data.collections):
#mesh.vertex_normals #mesh.vertex_normals
#mesh.vertex_colors #mesh.vertex_colors
#mesh.vertices #mesh.vertices
@ -175,6 +213,7 @@ def export_meshes(f):
render_vertex_normals(f, mesh_name, mesh.vertices) render_vertex_normals(f, mesh_name, mesh.vertices)
render_polygon_normals(f, mesh_name, mesh.polygon_normals) render_polygon_normals(f, mesh_name, mesh.polygon_normals)
render_polygons(f, mesh_name, mesh.polygons) render_polygons(f, mesh_name, mesh.polygons)
render_polygon_edge_pairs(f, mesh_name, mesh.polygons)
render_mesh_materials(f, mesh_name, mesh.materials) render_mesh_materials(f, mesh_name, mesh.materials)
render_mesh(f, mesh_name, mesh); render_mesh(f, mesh_name, mesh);
@ -193,7 +232,7 @@ def mesh_objects_sorted(objects):
def export_objects(f): def export_objects(f):
f.write("const object objects[] = {\n") f.write("const object objects[] = {\n")
for object in mesh_objects_sorted(bpy.context.scene.objects): for object in mesh_objects_sorted(bpy.data.collections):
#object.rotation_mode = 'AXIS_ANGLE' #object.rotation_mode = 'AXIS_ANGLE'
#object.name #object.name
@ -226,6 +265,7 @@ def export_scene(f):
export_objects(f) export_objects(f)
render_materials(f) render_materials(f)
with open("/home/bilbo/output.h", "w") as f: home = path.expanduser('~')
with open(path.join(home, "output.h"), "w") as f:
offset = 0 offset = 0
export_scene(f) export_scene(f)