From node to python

This commit is contained in:
Thomas FORGIONE 2016-11-21 14:31:09 +01:00
parent 1c1340d812
commit cbee001720
2 changed files with 156 additions and 175 deletions

View File

@ -1,175 +0,0 @@
const fs = require('fs');
class Vertex {
constructor(x,y,z) {
this.x = x;
this.y = y;
this.z = z;
}
fromArray(arr) {
this.x = arr[0];
this.y = arr[1];
this.z = arr[2];
return this;
}
}
const Normal = Vertex;
const TexCoord = Vertex;
class Face {
constructor(a,b,c,aTex,bTex,cTex,aNorm,bNorm,cNorm,mtl) {
this.a = a;
this.b = b;
this.c = c;
this.aTex = aTex;
this.bTex = bTex;
this.cTex = cTex;
this.aNorm = aNorm;
this.bNorm = bNorm;
this.cNorm = cNorm;
this.mtl = mtl;
}
fromArray(arr) {
this.a = arr[0];
this.aTex = arr[1];
this.aNorm = arr[2];
this.b = arr[3];
this.bTex = arr[4];
this.bNorm = arr[5];
this.c = arr[6];
this.cTex = arr[7];
this.cNorm = arr[8];
;
this.mtl = arr[9];
return this;
}
}
class ModelParser {
constructor() {
if (this.constructor === ModelParser) {
throw new Error("Can't instanciate abstract class ModelParser");
}
this.vertices = [];
this.normals = [];
this.texCoords = [];
this.faces = [];
}
addVertex(vertex) {
this.vertices.push(vertex);
}
addTexCoord(texCoord) {
this.texCoords.push(texCoord);
}
addNormal(normal) {
this.normals.push(normal);
}
addFace(face) {
this.faces.push(face);
}
parseLine(string) {
if (this.constructor === ModelParser) {
throw new Error("Can't call abstract method ModelParser.parseLine");
}
}
parseFile(path) {
fs
.readFileSync(path, 'utf-8')
.split('\n')
// .map((l) => l.slice(0,-1))
.map((a) => this.parseLine(a));
}
}
class OBJParser extends ModelParser {
constructor() {
super();
this.materials = [];
}
parseLine(string) {
let split = string.split(' ');
switch (split.shift()) {
case 'usemtl': this.currentMaterial = split[0]; break;
case 'v': this.addVertex (new Vertex(). fromArray(split)); break;
case 'vn': this.addNormal (new Normal(). fromArray(split)); break;
case 'vt': this.addTexCoord(new TexCoord().fromArray(split)); break;
case 'f': this.addFace (new Face() .fromArray(split.map(s => s.split('/')).reduce((a,b) => a.concat(b), [])));
}
}
}
class Exporter {
constructor(model) {
this.model = model;
}
}
class OBJExporter extends Exporter {
constructor(model) {
super(model);
}
toString() {
let string = "";
for (let vertex of this.model.vertices) {
string += "n " + [vertex.x, vertex.y, vertex.z].join(' ') + "\n";
}
string += "\n";
for (let texCoord of this.model.texCoords) {
string += "vt " + [texCoord.x, texCoord.y].join(' ') + "\n";
}
string += "\n"
for (let normal of this.model.normals) {
string += "vn " + [normal.x, normal.y, normal.z].join(' ') + "\n";
}
string += "\n";
for (let face of this.model.faces) {
string += "f ";
string += ['a', 'b', 'c'].map(a => [face[a], face[a + 'Tex'], face[a + 'Norm']].join('/')).join(' ');
string += '\n';
}
return string;
}
}
if (require.main === module) {
let parser = new OBJParser();
parser.parseFile('./examples/cube.obj');
let exporter = new OBJExporter(parser);
let string = exporter.toString();
console.log(string);
}

156
ModelConverter.py Executable file
View File

@ -0,0 +1,156 @@
#!/usr/bin/env python3
import sys
from functools import reduce
class Vertex:
def __init__(self, x = None, y = None, z = None):
self.x = x
self.y = y
self.z = z
def from_array(self, arr):
self.x = arr[0] if len(arr) > 0 else None
self.y = arr[1] if len(arr) > 1 else None
self.z = arr[2] if len(arr) > 2 else None
return self
Normal = Vertex
TexCoord = Vertex
class FaceVertex:
def __init__(self, vertex = None, texture = None, normal = None):
self.vertex = vertex
self.texture = texture
self.normal = normal
def from_array(self, arr):
self.vertex = arr[0] if len(arr) > 0 else None
self.texture = arr[1] if len(arr) > 1 else None
self.normal = arr[2] if len(arr) > 2 else None
return self
class Face:
def __init__(self, a = None, b = None, c = None, mtl = None):
self.a = a
self.b = b
self.c = c
self.mtl = mtl
# Expects array of array
def from_array(self, arr):
self.a = FaceVertex().from_array(arr[0])
self.b = FaceVertex().from_array(arr[1])
self.c = FaceVertex().from_array(arr[2])
return self
class ModelParser:
def __init__(self):
self.vertices = []
self.normals = []
self.tex_coords = []
self.faces = []
def add_vertex(self, vertex):
self.vertices.append(vertex)
def add_tex_coord(self, tex_coord):
self.tex_coords.append(tex_coord)
def add_normal(self, normal):
self.normals.append(normal)
def addFace(self, face):
self.faces.append(face)
def parse_line(self, string):
pass
def parse_file(self, path):
with open(path) as f:
for line in f.readlines():
line = line.rstrip()
self.parse_line(line)
class OBJParser(ModelParser):
def __init__(self):
super().__init__()
self.materials = []
def parse_line(self, string):
split = string.split(' ')
first = split[0]
split = split[1:]
if first == 'usemtl':
self.currentMaterial = split[0]
elif first == 'v':
self.add_vertex(Vertex().from_array(split))
elif first == 'vn':
self.add_normal(Normal().from_array(split))
elif first == 'vt':
self.add_tex_coord(TexCoord().from_array(split))
elif first == 'f':
splits = list(map(lambda x: x.split('/'), split))
self.addFace(Face().from_array(splits))
class Exporter:
def __init__(self, model):
self.model = model
class OBJExporter(Exporter):
def __init__(self, model):
super().__init__(model)
def __str__(self):
str = ""
for vertex in self.model.vertices:
str += "n " + ' '.join([vertex.x, vertex.y, vertex.z]) + "\n"
str += "\n"
for tex_coord in self.model.tex_coords:
str += "vt " + ' '.join([tex_coord.x, tex_coord.y]) + "\n"
str += "\n"
for normal in self.model.normals:
str += "vn " + ' '.join([normal.x, normal.y, normal.z]) + "\n"
str += "\n"
for face in self.model.faces:
str += "f "
arr = []
for v in [face.a, face.b, face.c]:
sub_arr = []
sub_arr.append(v.vertex)
if v.normal is None:
if v.texture is not None:
sub_arr.append('')
sub_arr.append(v.texture)
elif v.texture is not None:
sub_arr.append(v.texture)
if v.normal is not None:
sub_arr.append(v.normal)
arr.append('/'.join(sub_arr))
str += ' '.join(arr) + '\n'
return str
if __name__ == '__main__':
parser = OBJParser()
parser.parse_file('./examples/cube.obj')
exporter = OBJExporter(parser)
str = str(exporter)
print(str)