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):
|
def generate_vec3(vs):
|
||||||
for v in 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):
|
def generate_vec2(vs):
|
||||||
for v in 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):
|
def generate_vec(name, type, func, vs):
|
||||||
yield f"const vertex_{type} {name}_{type}[] = {{"
|
yield f"const vertex_{type} {name}_{type}[] = {{"
|
||||||
|
56
obj.py
56
obj.py
@ -2,23 +2,36 @@ from dataclasses import dataclass
|
|||||||
import sys
|
import sys
|
||||||
import os
|
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)
|
@dataclass(frozen=True)
|
||||||
class VertexPosition:
|
class VertexPosition:
|
||||||
x: float
|
x: FixedPoint
|
||||||
y: float
|
y: FixedPoint
|
||||||
z: float
|
z: FixedPoint
|
||||||
|
|
||||||
@dataclass(frozen=True)
|
@dataclass(frozen=True)
|
||||||
class VertexNormal:
|
class VertexNormal:
|
||||||
x: float
|
x: FixedPoint
|
||||||
y: float
|
y: FixedPoint
|
||||||
z: float
|
z: FixedPoint
|
||||||
|
|
||||||
@dataclass(frozen=True)
|
@dataclass(frozen=True)
|
||||||
class VertexTexture:
|
class VertexTexture:
|
||||||
x: float
|
x: FixedPoint
|
||||||
y: float
|
y: FixedPoint
|
||||||
z: float
|
z: FixedPoint
|
||||||
|
|
||||||
@dataclass(frozen=True)
|
@dataclass(frozen=True)
|
||||||
class ObjectEvent:
|
class ObjectEvent:
|
||||||
@ -44,10 +57,10 @@ class Object:
|
|||||||
faces: list[Face]
|
faces: list[Face]
|
||||||
material: Material
|
material: Material
|
||||||
|
|
||||||
def __init__(self, name):
|
def __init__(self, name, faces=None, material=None):
|
||||||
self.name = name
|
self.name = name
|
||||||
self.faces = []
|
self.faces = [] if faces is None else faces
|
||||||
self.material = None
|
self.material = material
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class ObjFile:
|
class ObjFile:
|
||||||
@ -56,11 +69,11 @@ class ObjFile:
|
|||||||
texture: list[VertexTexture]
|
texture: list[VertexTexture]
|
||||||
objects: list[Object]
|
objects: list[Object]
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self, position=None, normal=None, texture=None, objects=None):
|
||||||
self.position = []
|
self.position = [] if position is None else position
|
||||||
self.normal = []
|
self.normal = [] if normal is None else normal
|
||||||
self.texture = []
|
self.texture = [] if texture is None else texture
|
||||||
self.objects = []
|
self.objects = [] if objects is None else objects
|
||||||
|
|
||||||
def parse_float(s):
|
def parse_float(s):
|
||||||
sign = -1 if s.startswith("-") else 1
|
sign = -1 if s.startswith("-") else 1
|
||||||
@ -72,14 +85,7 @@ def parse_float(s):
|
|||||||
i = int(i, 10)
|
i = int(i, 10)
|
||||||
f = int(f, 10)
|
f = int(f, 10)
|
||||||
|
|
||||||
if 'ROUND_PRECISION' in os.environ:
|
return FixedPoint(sign, i, f, f_digits)
|
||||||
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)
|
|
||||||
|
|
||||||
def parse_vertex(line, n, type):
|
def parse_vertex(line, n, type):
|
||||||
assert len(line) == n
|
assert len(line) == n
|
||||||
|
Loading…
x
Reference in New Issue
Block a user