From 00e7d75fda05a4460668ac5cd398bfa96b534664 Mon Sep 17 00:00:00 2001 From: Zack Buhman Date: Fri, 31 Jan 2025 15:49:48 -0600 Subject: [PATCH] add material and object structs --- generate_cpp.py | 33 +++++++++++++++++++++++++++------ obj.py | 24 +++++++++++++++++++++--- 2 files changed, 48 insertions(+), 9 deletions(-) diff --git a/generate_cpp.py b/generate_cpp.py index cd76c0b..62da5d4 100644 --- a/generate_cpp.py +++ b/generate_cpp.py @@ -4,14 +4,14 @@ import sys def generate_vec3(vs): for v in vs: - yield f"{{{v.x}f, {v.y}f, {v.z}f}}," + yield f"{{{v.x:.6f}f, {v.y:.6f}f, {v.z:.6f}f}}," def generate_vec2(vs): for v in vs: - yield f"{{{v.x}f, {v.y}f}}," + yield f"{{{v.x:.6f}f, {v.y:.6f}f}}," def generate_vec(name, type, func, vs): - yield f"vertex_{type} {name}_{type}[] = {{" + yield f"const vertex_{type} {name}_{type}[] = {{" yield from func(vs) yield "};" @@ -25,7 +25,7 @@ def generate_ptn(ptn): yield f"{{{p.position}, {p.texture}, {p.normal}}}," def generate_faces(group_name, model_name, faces, type, n): - yield f"union {type} {group_name}_{model_name}_triangles = {{" + yield f"const union {type} {group_name}_{model_name}_{type}[] = {{" for face in filter_n(faces, n): yield "{ .v = {" yield from generate_ptn(face.ptn) @@ -33,14 +33,32 @@ def generate_faces(group_name, model_name, faces, type, n): yield "};" def generate_object(group_name, object): - yield f"struct object {group_name}_{object.name} = {{" + yield f"const struct object {group_name}_{object.name} = {{" yield f".triangle = &{group_name}_{object.name}_triangle[0]," yield f".quadrilateral = &{group_name}_{object.name}_quadrilateral[0]," triangle_count = sum(1 for _ in filter_n(object.faces, 3)) quadrilateral_count = sum(1 for _ in filter_n(object.faces, 4)) yield f".triangle_count = {triangle_count}," yield f".quadrilateral_count = {quadrilateral_count}," - yield ".material = 0," + if object.material is None: + yield ".material = 0," + else: + yield f".material = {group_name}_{object.material.name}," + yield "};" + +def generate_object_array(group_name, obj_file): + yield f"const struct object * {group_name}_object[] = {{" + for object in obj_file.objects: + yield f"&{group_name}_{object.name}," + yield "};" + +def generate_model(group_name): + yield f"const struct model {group_name}_model = {{" + yield f".position = {group_name}_position," + yield f".texture = {group_name}_texture," + yield f".normal = {group_name}_normal," + yield f".object = {group_name}_object," + yield f".object_count = {len(obj_file.objects)}" yield "};" def generate_obj_file(group_name, obj_file): @@ -54,6 +72,9 @@ def generate_obj_file(group_name, obj_file): yield from generate_faces(group_name, object.name, object.faces, "quadrilateral", 4) yield from generate_object(group_name, object) + yield from generate_object_array(group_name, obj_file) + yield from generate_model(group_name) + if __name__ == "__main__": obj_file = parse_obj_file(sys.argv[1]) render, out = renderer(indent_length=4) diff --git a/obj.py b/obj.py index 7c0db1a..c36c5fb 100644 --- a/obj.py +++ b/obj.py @@ -33,14 +33,20 @@ class FacePTN: class Face: ptn: list[FacePTN] +@dataclass +class Material: + name: str + @dataclass class Object: name: str faces: list[Face] + material: Material def __init__(self, name): self.name = name self.faces = [] + self.material = None @dataclass class ObjFile: @@ -56,13 +62,15 @@ class ObjFile: self.objects = [] def parse_float(s): + sign = -1 if s.startswith("-") else 1 + s = s.removeprefix("-") if '.' not in s: - return int(s, 10) + return sign * int(s, 10) i, f = s.split('.') f_digits = len(f) i = int(i, 10) f = int(f, 10) - return i + (f / 10 ** f_digits) + return sign * (i + (f / 10 ** f_digits)) def parse_vertex(line, n, type): assert len(line) == n @@ -98,12 +106,17 @@ def parse_object_event(line): name, = line return ObjectEvent(name) +def parse_usemtl(line): + assert len(line) == 1 + name, = line + return Material(name) + def parse_line(line): t, *line = line.split(' ') if t == '#': return None if t == 'usemtl': - return None + return parse_usemtl(line) if t == 'mtllib': return None if t == 'o': @@ -141,6 +154,11 @@ def parse_obj_lines(lines): object = Object(x.name) elif type(x) is Face: object.faces.append(x) + elif type(x) is Material: + if object.material != None: + file.objects.append(object) + object = Object(object.name + "_mtl_" + x.name) + object.material = x else: assert False, x if object.faces: