add material and object structs

This commit is contained in:
Zack Buhman 2025-01-31 15:49:48 -06:00
parent 61e2fb2c28
commit 00e7d75fda
2 changed files with 48 additions and 9 deletions

View File

@ -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)

24
obj.py
View File

@ -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: