grid-apps-cmms/js/moto-load-obj.js
2017-04-18 17:09:33 -04:00

239 lines
8.1 KiB
JavaScript

/**
* adapted from THREE.OBJLoader example
*
* https://en.wikipedia.org/wiki/Wavefront_.obj_file
*/
'use strict';
(function() {
if (!self.moto) self.moto = {};
self.moto.OBJ = {
parse : parse
};
/**
* @param {String} text
* @returns {Array}
*/
function parse(text) {
var object,
objects = [],
geometry,
material;
function parseVertexIndex(value) {
var index = parseInt(value);
return (index >= 0 ? index - 1 : index + vertices.length / 3) * 3;
}
function parseNormalIndex(value) {
var index = parseInt(value);
return (index >= 0 ? index - 1 : index + normals.length / 3) * 3;
}
function parseUVIndex(value) {
var index = parseInt(value);
return (index >= 0 ? index - 1 : index + uvs.length / 2) * 2;
}
function addVertex(a, b, c) {
geometry.vertices.push(
vertices[a], vertices[a + 1], vertices[a + 2],
vertices[b], vertices[b + 1], vertices[b + 2],
vertices[c], vertices[c + 1], vertices[c + 2]
);
}
function addNormal(a, b, c) {
geometry.normals.push(
normals[a], normals[a + 1], normals[a + 2],
normals[b], normals[b + 1], normals[b + 2],
normals[c], normals[c + 1], normals[c + 2]
);
}
function addUV(a, b, c) {
geometry.uvs.push(
uvs[a], uvs[a + 1],
uvs[b], uvs[b + 1],
uvs[c], uvs[c + 1]
);
}
function addFace(a, b, c, d, ua, ub, uc, ud, na, nb, nc, nd) {
var ia = parseVertexIndex(a);
var ib = parseVertexIndex(b);
var ic = parseVertexIndex(c);
var id;
if (d === undefined) {
addVertex(ia, ib, ic);
} else {
id = parseVertexIndex(d);
addVertex(ia, ib, id);
addVertex(ib, ic, id);
}
if (ua !== undefined) {
ia = parseUVIndex(ua);
ib = parseUVIndex(ub);
ic = parseUVIndex(uc);
if (d === undefined) {
addUV(ia, ib, ic);
} else {
id = parseUVIndex(ud);
addUV(ia, ib, id);
addUV(ib, ic, id);
}
}
if (na !== undefined) {
ia = parseNormalIndex(na);
ib = parseNormalIndex(nb);
ic = parseNormalIndex(nc);
if (d === undefined) {
addNormal(ia, ib, ic);
} else {
id = parseNormalIndex(nd);
addNormal(ia, ib, id);
addNormal(ib, ic, id);
}
}
}
// create mesh if no objects in text
if (/^o /gm.test(text) === false) {
geometry = {
vertices: [],
normals: [],
uvs: []
};
object = {
name: '',
geometry: geometry
};
objects.push(object);
}
var vertices = [],
normals = [],
uvs = [],
// v float float float
vertex_pattern = /v(+[\d|\.|\+|\-|e|E]+)(+[\d|\.|\+|\-|e|E]+)(+[\d|\.|\+|\-|e|E]+)/,
// vn float float float
normal_pattern = /vn(+[\d|\.|\+|\-|e|E]+)(+[\d|\.|\+|\-|e|E]+)(+[\d|\.|\+|\-|e|E]+)/,
// vt float float
uv_pattern = /vt(+[\d|\.|\+|\-|e|E]+)(+[\d|\.|\+|\-|e|E]+)/,
// f vertex vertex vertex ...
face_pattern1 = /f(+-?\d+)(+-?\d+)(+-?\d+)(+-?\d+)?/,
// f vertex/uv vertex/uv vertex/uv ...
face_pattern2 = /f(+(-?\d+)\/(-?\d+))(+(-?\d+)\/(-?\d+))(+(-?\d+)\/(-?\d+))(+(-?\d+)\/(-?\d+))?/,
// f vertex/uv/normal vertex/uv/normal vertex/uv/normal ...
face_pattern3 = /f(+(-?\d+)\/(-?\d+)\/(-?\d+))(+(-?\d+)\/(-?\d+)\/(-?\d+))(+(-?\d+)\/(-?\d+)\/(-?\d+))(+(-?\d+)\/(-?\d+)\/(-?\d+))?/,
// f vertex//normal vertex//normal vertex//normal ...
face_pattern4 = /f(+(-?\d+)\/\/(-?\d+))(+(-?\d+)\/\/(-?\d+))(+(-?\d+)\/\/(-?\d+))(+(-?\d+)\/\/(-?\d+))?/,
// split text into lines
lines = text.split('\n');
for (var i = 0; i < lines.length; i++) {
var line = lines[i];
line = line.trim();
var result;
if (line.length === 0 || line.charAt(0) === '#') {
continue;
} else if ((result = vertex_pattern.exec(line)) !== null) {
// ["v 1.0 2.0 3.0", "1.0", "2.0", "3.0"]
vertices.push(
parseFloat(result[1]),
parseFloat(result[2]),
parseFloat(result[3])
);
} else if ((result = normal_pattern.exec(line)) !== null) {
// ["vn 1.0 2.0 3.0", "1.0", "2.0", "3.0"]
normals.push(
parseFloat(result[1]),
parseFloat(result[2]),
parseFloat(result[3])
);
} else if ((result = uv_pattern.exec(line)) !== null) {
// ["vt 0.1 0.2", "0.1", "0.2"]
uvs.push(
parseFloat(result[1]),
parseFloat(result[2])
);
} else if ((result = face_pattern1.exec(line)) !== null) {
// ["f 1 2 3", "1", "2", "3", undefined]
addFace(
result[1], result[2], result[3], result[4]
);
} else if ((result = face_pattern2.exec(line)) !== null) {
// ["f 1/1 2/2 3/3", " 1/1", "1", "1", " 2/2", "2", "2", " 3/3", "3", "3", undefined, undefined, undefined]
addFace(
result[2], result[5], result[8], result[11],
result[3], result[6], result[9], result[12]
);
} else if ((result = face_pattern3.exec(line)) !== null) {
// ["f 1/1/1 2/2/2 3/3/3", " 1/1/1", "1", "1", "1", " 2/2/2", "2", "2", "2", " 3/3/3", "3", "3", "3", undefined, undefined, undefined, undefined]
addFace(
result[2], result[6], result[10], result[14],
result[3], result[7], result[11], result[15],
result[4], result[8], result[12], result[16]
);
} else if ((result = face_pattern4.exec(line)) !== null) {
// ["f 1//1 2//2 3//3", " 1//1", "1", "1", " 2//2", "2", "2", " 3//3", "3", "3", undefined, undefined, undefined]
addFace(
result[2], result[5], result[8], result[11],
undefined, undefined, undefined, undefined,
result[3], result[6], result[9], result[12]
);
} else if (/^o /.test(line)) {
geometry = {
vertices: [],
normals: [],
uvs: []
};
object = {
name: line.substring(2).trim(),
geometry: geometry
};
objects.push(object)
} else if (/^g /.test(line)) {
// group
} else if (/^usemtl /.test(line)) {
// material
material.name = line.substring(7).trim();
} else if (/^mtllib /.test(line)) {
// mtl file
} else if (/^s /.test(line)) {
// smooth shading
} else {
// unhandled
}
}
objects.forEach(function(object) {
object.geometry.vertices = new Float32Array(object.geometry.vertices);
object.geometry.normals = new Float32Array(object.geometry.normals);
object.geometry.uvs = new Float32Array(object.geometry.uvs);
});
return objects;
}
})();