diff --git a/convert.py b/convert.py index 01f302f..9707b90 100755 --- a/convert.py +++ b/convert.py @@ -5,6 +5,7 @@ import os import d3.model.tools as mt import functools as fc +from d3.model.basemodel import Vector def check_path(path, should_exist): """ Check that a path (file or folder) exists or not and return it. @@ -16,8 +17,17 @@ def check_path(path, should_exist): return path def main(args): + + if (args.from_up is None) != (args.to_up is None): + raise Exception("from-up and to-up args should be both present or both absent") + + up_conversion = None + if args.from_up is not None: + up_conversion = (args.from_up, args.to_up) + output = args.output if args.output is not None else '.' + args.type - result = mt.convert(args.input, output) + + result = mt.convert(args.input, output, up_conversion) if args.output is None: print(result) @@ -31,11 +41,15 @@ if __name__ == '__main__': parser.add_argument('-v', '--version', action='version', version='1.0') parser.add_argument('-i', '--input', metavar='input', type=fc.partial(check_path, should_exist=True), default=None, - help='Input file (.obj)') + help='Input file') parser.add_argument('-o', '--output', metavar='output', help='Output path') parser.add_argument('-t', '--type', metavar='type', help='Export type, useless if output is specified') + parser.add_argument('-fu', '--from-up', metavar='fup', default=None, + help="Initial up vector") + parser.add_argument('-tu', '--to-up', metavar='fup', default=None, + help="Output up vector") args = parser.parse_args() args.func(args) diff --git a/d3/model/basemodel.py b/d3/model/basemodel.py index 820148f..6c0a464 100644 --- a/d3/model/basemodel.py +++ b/d3/model/basemodel.py @@ -70,9 +70,11 @@ class Face: class ModelParser: """Represents a 3D model """ - def __init__(self): + def __init__(self, up_conversion = None): """Initializes the model """ + self.up_conversion = up_conversion + print(up_conversion) self.vertices = [] self.normals = [] self.tex_coords = [] @@ -98,8 +100,16 @@ class ModelParser: Will also update its bounding box """ - self.vertices.append(vertex) - self.bounding_box.add(vertex) + # Apply up_conversion to the vertex + new_vertex = vertex + if self.up_conversion is not None: + if self.up_conversion[0] == 'y' and self.up_conversion[1] == 'z': + new_vertex = Vector(vertex.y, vertex.z, vertex.x) + elif self.up_conversion[0] == 'z' and self.up_conversion[1] == 'y': + new_vertex = Vector(vertex.z, vertex.x, vertex.y) + + self.vertices.append(new_vertex) + self.bounding_box.add(new_vertex) def add_tex_coord(self, tex_coord): """Adds a texture coordinate element to the current model diff --git a/d3/model/obj.py b/d3/model/obj.py index 105c44b..767b05e 100644 --- a/d3/model/obj.py +++ b/d3/model/obj.py @@ -13,8 +13,8 @@ def is_obj(filename): class OBJParser(ModelParser): - def __init__(self): - super().__init__() + def __init__(self, up_conversion = None): + super().__init__(up_conversion) self.current_material = None self.mtl = None diff --git a/d3/model/ply.py b/d3/model/ply.py index a433c20..1580be0 100644 --- a/d3/model/ply.py +++ b/d3/model/ply.py @@ -7,8 +7,8 @@ def is_ply(filename): class PLYParser(ModelParser): - def __init__(self): - super().__init__() + def __init__(self, up_conversion = None): + super().__init__(up_conversion) self.counter = 0 self.elements = [] self.inner_parser = PLYHeaderParser(self) diff --git a/d3/model/stl.py b/d3/model/stl.py index 3ffda52..b803d9c 100644 --- a/d3/model/stl.py +++ b/d3/model/stl.py @@ -10,8 +10,8 @@ def is_stl(filename): class STLParser(ModelParser): - def __init__(self): - super().__init__() + def __init__(self, up_conversion = None): + super().__init__(up_conversion) self.parsing_solid = False self.parsing_face = False self.parsing_loop = False diff --git a/d3/model/tools.py b/d3/model/tools.py index c4548e8..00f6b1e 100644 --- a/d3/model/tools.py +++ b/d3/model/tools.py @@ -5,15 +5,15 @@ from .ply import is_ply, PLYParser, PLYExporter from .stl import is_stl, STLParser, STLExporter from .basemodel import ModelParser, Exporter -def load_model(path): +def load_model(path, up_conversion = None): parser = None if is_obj(path): - parser = OBJParser() + parser = OBJParser(up_conversion) elif is_ply(path): - parser = PLYParser() + parser = PLYParser(up_conversion) elif is_stl(path): - parser = STLParser() + parser = STLParser(up_conversion) else: raise Exception("File format not supported") @@ -35,8 +35,8 @@ def export_model(model, path): return exporter -def convert(input, output): - model = load_model(input) +def convert(input, output, up_conversion = None): + model = load_model(input, up_conversion) exporter = export_model(model, output) return str(exporter) diff --git a/viewer.py b/viewer.py index dcac59c..1e552e1 100755 --- a/viewer.py +++ b/viewer.py @@ -22,6 +22,14 @@ WINDOW_HEIGHT = 768 def main(args): + if (args.from_up is None) != (args.to_up is None): + raise Exception("from-up and to-up args should be both present or both absent") + + up_conversion = None + if args.from_up is not None: + up_conversion = (args.from_up, args.to_up) + + camera = Camera(Vector(0,0,5), Vector(0,0,0)) controls = OrbitControls() @@ -44,7 +52,7 @@ def main(args): running = True # Load and parse the model - model = load_model(args.input) + model = load_model(args.input, up_conversion) # Initializes OpenGL textures model.init_textures() @@ -99,5 +107,10 @@ if __name__ == '__main__': parser.set_defaults(func=main) parser.add_argument('-v', '--version', action='version', version='1.0') parser.add_argument('-i', '--input', metavar='input', default=None, help='Input model') + parser.add_argument('-fu', '--from-up', metavar='fup', default=None, + help="Initial up vector") + parser.add_argument('-tu', '--to-up', metavar='fup', default=None, + help="Output up vector") + args = parser.parse_args() args.func(args)