add combine_obj
This commit is contained in:
parent
0b4d41f42e
commit
3c775a0f86
83
combine_obj.py
Normal file
83
combine_obj.py
Normal file
@ -0,0 +1,83 @@
|
||||
from collections import defaultdict
|
||||
import sys
|
||||
from obj import parse_obj_file
|
||||
from obj import VertexPosition
|
||||
from obj import VertexNormal
|
||||
from obj import VertexTexture
|
||||
from obj import ObjFile
|
||||
from obj import Object
|
||||
from obj import Face
|
||||
from obj import FacePTN
|
||||
from generate import renderer
|
||||
from generate_cpp import generate_obj_file
|
||||
|
||||
global_vertex = {
|
||||
VertexPosition: {},
|
||||
VertexNormal: {},
|
||||
VertexTexture: {},
|
||||
}
|
||||
|
||||
global_names = defaultdict(int)
|
||||
|
||||
def merge_vertex(vertex, type):
|
||||
d = global_vertex[type]
|
||||
if vertex not in d:
|
||||
d[vertex] = len(d)
|
||||
|
||||
def merge_vertices(vertices, type):
|
||||
for vertex in vertices:
|
||||
merge_vertex(vertex, type)
|
||||
|
||||
def rewrite_ptn(obj_file, ptn):
|
||||
return FacePTN(
|
||||
position=global_vertex[VertexPosition][obj_file.position[ptn.position]],
|
||||
normal=global_vertex[VertexNormal][obj_file.normal[ptn.normal]],
|
||||
texture=global_vertex[VertexTexture][obj_file.texture[ptn.texture]],
|
||||
)
|
||||
|
||||
def rewrite_face(obj_file, face):
|
||||
return Face(
|
||||
ptn=[rewrite_ptn(obj_file, face_ptn) for face_ptn in face.ptn]
|
||||
)
|
||||
|
||||
def rewrite_object(obj_file, object):
|
||||
global global_names
|
||||
global_names[object.name] += 1
|
||||
name_suffix = global_names[object.name]
|
||||
return Object(
|
||||
name=f"{object.name}_{name_suffix}",
|
||||
faces=[rewrite_face(obj_file, face) for face in object.faces],
|
||||
material=object.material,
|
||||
)
|
||||
|
||||
def rewrite_objects(obj_files):
|
||||
for obj_file in obj_files:
|
||||
for object in obj_file.objects:
|
||||
yield rewrite_object(obj_file, object)
|
||||
|
||||
def reorder_vertices(type):
|
||||
d = global_vertex[type]
|
||||
dd = {v: k for k, v in d.items()}
|
||||
for i in range(len(dd)):
|
||||
yield dd[i]
|
||||
|
||||
def rewrite_obj_file(obj_files):
|
||||
for obj_file in obj_files:
|
||||
merge_vertices(obj_file.position, VertexPosition)
|
||||
merge_vertices(obj_file.normal, VertexNormal)
|
||||
merge_vertices(obj_file.texture, VertexTexture)
|
||||
|
||||
return ObjFile(
|
||||
position=reorder_vertices(VertexPosition),
|
||||
normal=reorder_vertices(VertexNormal),
|
||||
texture=reorder_vertices(VertexTexture),
|
||||
objects=list(rewrite_objects(obj_files))
|
||||
)
|
||||
|
||||
if __name__ == "__main__":
|
||||
filenames = sys.argv[2:]
|
||||
obj_files = [parse_obj_file(fn) for fn in filenames]
|
||||
obj_file = rewrite_obj_file(obj_files)
|
||||
render, out = renderer(indent_length=4)
|
||||
render(generate_obj_file(sys.argv[1], obj_file))
|
||||
sys.stdout.write(out.getvalue())
|
@ -4,11 +4,11 @@ import sys
|
||||
|
||||
def generate_vec3(vs):
|
||||
for v in vs:
|
||||
yield f"{{{v.x:.6f}f, {v.y:.6f}f, {v.z:.6f}f}},"
|
||||
yield f"{{{v.x.to_string()}f, {v.y.to_string()}f, {v.z.to_string()}f}},"
|
||||
|
||||
def generate_vec2(vs):
|
||||
for v in vs:
|
||||
yield f"{{{v.x:.6f}f, {v.y:.6f}f}},"
|
||||
yield f"{{{v.x.to_string()}f, {v.y.to_string()}f}},"
|
||||
|
||||
def generate_vec(name, type, func, vs):
|
||||
yield f"const vertex_{type} {name}_{type}[] = {{"
|
||||
|
56
obj.py
56
obj.py
@ -2,23 +2,36 @@ from dataclasses import dataclass
|
||||
import sys
|
||||
import os
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class FixedPoint:
|
||||
s: int # sign
|
||||
w: int # whole
|
||||
f: int # fraction
|
||||
b: int # base
|
||||
|
||||
def to_string(self):
|
||||
s_s = "-" if self.s < 0 else ""
|
||||
w_s = f"{self.w}"
|
||||
f_s = f"{self.f}".rjust(self.b, '0')
|
||||
return f"{s_s}{w_s}.{f_s}"
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class VertexPosition:
|
||||
x: float
|
||||
y: float
|
||||
z: float
|
||||
x: FixedPoint
|
||||
y: FixedPoint
|
||||
z: FixedPoint
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class VertexNormal:
|
||||
x: float
|
||||
y: float
|
||||
z: float
|
||||
x: FixedPoint
|
||||
y: FixedPoint
|
||||
z: FixedPoint
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class VertexTexture:
|
||||
x: float
|
||||
y: float
|
||||
z: float
|
||||
x: FixedPoint
|
||||
y: FixedPoint
|
||||
z: FixedPoint
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class ObjectEvent:
|
||||
@ -44,10 +57,10 @@ class Object:
|
||||
faces: list[Face]
|
||||
material: Material
|
||||
|
||||
def __init__(self, name):
|
||||
def __init__(self, name, faces=None, material=None):
|
||||
self.name = name
|
||||
self.faces = []
|
||||
self.material = None
|
||||
self.faces = [] if faces is None else faces
|
||||
self.material = material
|
||||
|
||||
@dataclass
|
||||
class ObjFile:
|
||||
@ -56,11 +69,11 @@ class ObjFile:
|
||||
texture: list[VertexTexture]
|
||||
objects: list[Object]
|
||||
|
||||
def __init__(self):
|
||||
self.position = []
|
||||
self.normal = []
|
||||
self.texture = []
|
||||
self.objects = []
|
||||
def __init__(self, position=None, normal=None, texture=None, objects=None):
|
||||
self.position = [] if position is None else position
|
||||
self.normal = [] if normal is None else normal
|
||||
self.texture = [] if texture is None else texture
|
||||
self.objects = [] if objects is None else objects
|
||||
|
||||
def parse_float(s):
|
||||
sign = -1 if s.startswith("-") else 1
|
||||
@ -72,14 +85,7 @@ def parse_float(s):
|
||||
i = int(i, 10)
|
||||
f = int(f, 10)
|
||||
|
||||
if 'ROUND_PRECISION' in os.environ:
|
||||
max_digits = 4
|
||||
if f_digits > max_digits:
|
||||
f = int(f / (f_digits - max_digits))
|
||||
f_digits = max_digits
|
||||
|
||||
f_10 = (f / 10 ** f_digits)
|
||||
return sign * (i + f_10)
|
||||
return FixedPoint(sign, i, f, f_digits)
|
||||
|
||||
def parse_vertex(line, n, type):
|
||||
assert len(line) == n
|
||||
|
Loading…
x
Reference in New Issue
Block a user