diff --git a/x/gen.py b/x/gen.py index 8ac99d6..c0ade31 100644 --- a/x/gen.py +++ b/x/gen.py @@ -18,15 +18,38 @@ def obj_value(obj): def obj_type(obj): return type(obj_value(obj)) +visitors = None +def visit(func, obj): + global visitors + yield from visitors[obj_type(obj)](func, obj) + +def visit_none(func, obj): + return + yield # empty generator + def visit_objects(func, obj): - print("vo", func) - yield func(obj) + yield from func(obj) for o in obj_value(obj).objects: - yield func(o) + yield from visit(func, o) def visit_self(func, obj): - print("vs", func) - yield func(obj) + yield from func(obj) + +tagged = { + templates.Header, + templates.Material, + templates.TextureFilename, + templates.Frame, + templates.FrameTransformMatrix, + templates.Mesh, + templates.MeshMaterialList, + templates.MeshNormals, + templates.MeshTextureCoords, + templates.AnimationKey, + templates.AnimationOptions, + templates.Animation, + templates.AnimationSet, +} visitors = { templates.ColorRGBA : visit_self, @@ -35,7 +58,7 @@ visitors = { templates.Vector : visit_self, templates.MeshFace : visit_self, templates.Coords2D : visit_self, - templates.Reference : visit_self, + templates.Reference : visit_none, templates.FloatKeys : visit_self, templates.TimedFloatKeys : visit_self, @@ -80,75 +103,209 @@ type_map = { templates.AnimationSet : "animation_set", } -type_counter = Counter() -def name_gen(obj): - global type_counter - assert type(obj) is not tuple - i = type_counter[type(obj)] - type_counter[type(obj)] += 1 - return i - name_map = {} +obj_map = {} def add_name_map(obj): if type(obj) is not tuple: return name, obj = obj assert name not in name_map, name - name_map[name] = obj + name_map[id(obj)] = name.decode("utf-8") + obj_map[name] = obj yield None -def type_declaration(obj): +type_counter = Counter() +obj_names = {} +def name_gen(obj): + global type_counter + global obj_names + + assert type(obj) is not tuple + + if id(obj) in name_map: + return name_map[id(obj)] + elif id(obj) in obj_names: + return obj_names[id(obj)] + else: + i = type_counter[obj_type(obj)] + type_counter[obj_type(obj)] += 1 + obj_names[id(obj)] = i + return i + +def get_obj_name(obj): type_name = type_map[obj_type(obj)] if type(obj) is tuple: name, _ = obj string_name = name.decode('utf-8') else: string_name = name_gen(obj) - return f"const {type_name} {type_name}_{string_name}" + return f"{type_name}_{string_name}" -def generate_predeclaration(obj): - if type(obj) is not tuple: - return +def type_declaration(obj): + type_name = type_map[obj_type(obj)] + string_name = get_obj_name(obj) + return f"const {type_name} {string_name}" - yield f"{type_declaration(obj)};" - -def generate_header(obj): - yield f"{type_declaration(obj)} {{" +def generate_vec3(name, name2, vertices): + yield f"vec3 {name}_{name2}[] = {{" + for v in vertices: + coordinates = f"{v.x}, {v.y}, {v.z}" + yield f"{{{coordinates}}}," yield "};" -def generate_definition(obj): - if obj_type(obj) is templates.Header: - yield from generate_header(obj) - elif obj_type(obj) is templates.Material: - yield from generate_material(obj) - elif obj_type(obj) is templates.TextureFilename: - yield from generate_texture_filename(obj) - elif obj_type(obj) is templates.Frame: - yield from generate_frame(obj) - elif obj_type(obj) is templates.FrameTransformMatrix: - yield from generate_frame_transform_matrix(obj) - elif obj_type(obj) is templates.Mesh: - yield from generate_mesh(obj) - elif obj_type(obj) is templates.MeshMaterialList: - yield from generate_mesh_material_list(obj) - elif obj_type(obj) is templates.MeshNormals: - yield from generate_mesh_normals(obj) - elif obj_type(obj) is templates.MeshTextureCoords: - yield from generate_mesh_texture_coords(obj) - elif obj_type(obj) is templates.AnimationKey: - yield from generate_animation_key(obj) - elif obj_type(obj) is templates.AnimationOptions: - yield from generate_animation_options(obj) - elif obj_type(obj) is templates.Animation: - yield from generate_animation(obj) - elif obj_type(obj) is templates.AnimationSet: - yield from generate_animation_set(obj) - else: - assert False, (type(obj), obj) +def generate_faces(name, faces): + yield f"struct mesh_face {name}_faces[] = {{" + for f in faces: + assert f.nFaceVertexIndices == 3 + indices = f"{', '.join(map(str, f.faceVertexIndices))}" + yield f"{{{indices}}}," + yield "};" -def visit(func, obj): - yield from visitors[obj_type(obj)](func, obj) +def generate_face_indices(name, face_indices): + yield f"int {name}_face_indices[] = {{" + for i in face_indices: + yield f"{i}," + yield "};" + +def generate_predeclaration(obj): + name = get_obj_name(obj) + if obj_type(obj) is templates.Mesh: + yield from generate_vec3(name, "vertices", obj_value(obj).vertices) + yield from generate_faces(name, obj_value(obj).faces) + elif obj_type(obj) is templates.MeshMaterialList: + yield from generate_face_indices(name, obj_value(obj).faceIndices) + elif obj_type(obj) is templates.MeshNormals: + yield from generate_vec3(name, "normals", obj_value(obj).normals) + + yield f"extern {type_declaration(obj)};" + +def generate_header(obj): + yield f".major = {obj.major}," + yield f".minor = {obj.minor}," + yield f".flags = {obj.flags}," + +def generate_material(obj): + face_color = f"{obj.faceColor.r}f, {obj.faceColor.g}f, {obj.faceColor.b}f, {obj.faceColor.a}f" + specular_color = f"{obj.specularColor.r}f, {obj.specularColor.g}f, {obj.specularColor.b}f" + emissive_color = f"{obj.emissiveColor.r}f, {obj.emissiveColor.g}f, {obj.emissiveColor.b}f" + yield f".face_color = {{{face_color}}}," + yield f".power = {obj.power}f," + yield f".specular_color = {{{specular_color}}}," + yield f".emissive_color = {{{emissive_color}}}," + +def generate_texture_filename(obj): + yield "" + +def generate_frame(obj): + return + yield # empty generator function + +def generate_frame_transform_matrix(obj): + yield ".frame_matrix = {" + m = obj.frameMatrix.v + # transpose matrix from column-major to row-major + yield f"{m[0]}, {m[4]}, {m[8]}, {m[12]}," + yield f"{m[1]}, {m[5]}, {m[9]}, {m[13]}," + yield f"{m[2]}, {m[6]}, {m[10]}, {m[14]}," + yield f"{m[3]}, {m[7]}, {m[11]}, {m[15]}," + yield "}," + +def generate_mesh(obj): + name = get_obj_name(obj) + yield f".n_vertices = {obj.nVertices}," + yield f".vertices = {name}_vertices," + yield f".n_faces = {obj.nFaces}," + yield f".faces = {name}_faces," + +def generate_mesh_material_list(obj): + name = get_obj_name(obj) + yield f".n_materials = {obj.nMaterials}," + yield f".n_face_indices = {obj.nFaceIndices}," + yield f".face_indices = {name}_face_indices," + +def generate_mesh_normals(obj): + name = get_obj_name(obj) + yield f".n_normals = {obj.nNormals}," + yield f".normals = {name}_normals," + yield f".n_face_normals = {obj.nFaceNormals}," + +def generate_mesh_texture_coords(obj): + yield f".n_texture_coords = {obj.nTextureCoords}," + yield f".texture_coords = {{" + for tc in obj.textureCoords: + coordinates = f"{tc.u}, {tc.v}" + yield f"{{{coordinates}}}," + yield "}," + +def generate_animation_key(obj): + yield f".key_type = {obj.keyType}," + yield f".n_keys = {obj.nKeys}," + yield ".keys = {" + yield "// not implemented" + yield "}," + +def generate_animation_options(obj): + yield f".open_closed = {obj.openClosed}," + yield f".position_quality = {obj.positionQuality}," + +def generate_animation(obj): + return + yield + +def generate_animation_set(obj): + return + yield + +def generate_definition(obj): + yield f"{type_declaration(obj)} = {{" + + if obj_type(obj) in tagged: + yield f".tag = tag::{type_map[obj_type(obj)]}," + + if obj_type(obj) is templates.Header: + yield from generate_header(obj_value(obj)) + elif obj_type(obj) is templates.Material: + yield from generate_material(obj_value(obj)) + elif obj_type(obj) is templates.TextureFilename: + yield from generate_texture_filename(obj_value(obj)) + elif obj_type(obj) is templates.Frame: + yield from generate_frame(obj_value(obj)) + elif obj_type(obj) is templates.FrameTransformMatrix: + yield from generate_frame_transform_matrix(obj_value(obj)) + elif obj_type(obj) is templates.Mesh: + yield from generate_mesh(obj_value(obj)) + elif obj_type(obj) is templates.MeshMaterialList: + yield from generate_mesh_material_list(obj_value(obj)) + elif obj_type(obj) is templates.MeshNormals: + yield from generate_mesh_normals(obj_value(obj)) + elif obj_type(obj) is templates.MeshTextureCoords: + yield from generate_mesh_texture_coords(obj_value(obj)) + elif obj_type(obj) is templates.AnimationKey: + yield from generate_animation_key(obj_value(obj)) + elif obj_type(obj) is templates.AnimationOptions: + yield from generate_animation_options(obj_value(obj)) + elif obj_type(obj) is templates.Animation: + yield from generate_animation(obj_value(obj)) + elif obj_type(obj) is templates.AnimationSet: + yield from generate_animation_set(obj_value(obj)) + elif obj_type(obj) is templates.Reference: + # do nothing + pass + else: + assert False, (obj_type(obj), obj) + + if visitors[obj_type(obj)] is visit_objects: + yield "" + yield ".objects = {" + for o in obj_value(obj).objects: + if obj_type(o) == templates.Reference: + reference_name = obj_value(o).name + o = obj_map[reference_name] + yield f"reinterpret_cast(&{get_obj_name(o)})," + yield "}" + + yield "};" def visit_all(func, objects): for obj in objects: @@ -165,6 +322,5 @@ objects = list(parse_all(TokenReader(buf))) _ = list(visit_all(add_name_map, objects)) render, out = generate.renderer() -for i in gen(objects): - print("line", i) +render(gen(objects)) print(out.getvalue()) diff --git a/x/generate.py b/x/generate.py index 2871189..56b028d 100644 --- a/x/generate.py +++ b/x/generate.py @@ -7,15 +7,16 @@ def should_autonewline(line): and (len(line.split()) < 2 or line.split()[1] != '=') # hacky; meh ) -def _render(out, lines): +def _render(out, lines, level=0): indent = " " - level = 0 for l in lines: if l and (l[0] == "}" or l[0] == ")"): level -= 2 assert level >= 0, out.getvalue() - if len(l) == 0: + if type(l) is tuple: + line_fifo.append(l) + elif len(l) == 0: out.write("\n") else: out.write(indent * level + l + "\n") diff --git a/x/x.hpp b/x/x.hpp index 635e44a..1591f9d 100644 --- a/x/x.hpp +++ b/x/x.hpp @@ -1,7 +1,7 @@ /* primitives */ struct mesh_face { - int nfacevertexindices; - int facevertexindices[]; + //int n_face_vertex_indices; + int face_vertex_indices[3]; }; struct float_keys { @@ -42,11 +42,11 @@ struct header { struct material { enum tag tag; - vec4 facecolor; + vec4 face_color; float power; - vec3 specularcolor; - vec3 emissivecolor; - struct data_object * objects[]; + vec3 specular_color; + vec3 emissive_color; + const data_object * objects[]; }; struct texture_filename { @@ -56,21 +56,21 @@ struct texture_filename { struct frame { enum tag tag; - struct data_object * objects[]; + const data_object * objects[]; }; struct frame_transform_matrix { enum tag tag; - mat4x4 framematrix; + mat4x4 frame_matrix; }; struct mesh { enum tag tag; - int nvertices; + int n_vertices; vec3 * vertices; - int nfaces; + int n_faces; struct mesh_face * faces; - struct data_object * objects[]; + const data_object * objects[]; }; struct mesh_material_list { @@ -78,7 +78,7 @@ struct mesh_material_list { int n_materials; int n_face_indices; int * face_indices; - struct data_object * objects[]; + const data_object * objects[]; }; struct mesh_normals { @@ -110,12 +110,12 @@ struct animation_options { struct animation { enum tag tag; - struct data_object * objects[]; + const data_object * objects[]; }; struct animation_set { enum tag tag; - struct data_object * objects[]; + const data_object * objects[]; }; struct data_object {