js/Mobilizing/renderer/3D/three/shape/3D/parser/OBJ.js
import Mesh from "../../Mesh";
import Material from "../../../scene/Material";
import Vector3 from "../../../types/Vector3";
import Vector2 from "../../../types/Vector2";
import Color from "../../../types/Color";
import * as debug from "../../../../../../core/util/Debug";
/**
* OBJ class gives easy access to some calculations specific to OBJs. It is used to load an external .obj model file.
*/
export default class OBJ {
/**
* parse the MTL file associated to the obj file
* @static
* @param {Object} model The model to attach a texture to
* @param {Object} data The data to parse
*/
static parseMTL(data) {
const material = new Material({ type: "phong" });
const lines = data.toString().split("\n");
lines.forEach((line) => {
const words = line.split(" ");
//debug.log("WORDS:"+words);
switch (words[0]) {
//comment, we just ignore
case "#":
break;
//new material declared
case "newmtl":
break;
//ambient term
case "Ka":
material.setEmissiveColor(new Color(words[1], words[2], words[3]));
break;
case "Kd": //diffuse
material.setColor(new Color(words[1], words[2], words[3]));
break;
case "Ks": //specular
material.setSpecularColor(new Color(words[1], words[2], words[3]));
material._material.shininess = 20;
break;
case "Ns": //specular exponent
break;
case "d": //dissolved == opacity
break;
case "Tr": //Transparent
//d = 1-Tr;
break;
case "illum": //illumination model
break;
case "map_Kd": //Map diffuse
break;
default:
break;
}
});
return material;
}
/**
* parse the OBJ file
* @static
* @param {Object} data The data to parse
* @return {Mesh}
*/
static parseOBJ(data, material) {
const text = data;
let mat;
if (material) {
mat = material;
}
else {
mat = new Material({
"type": "phong",
"shading": "flat"
});
}
//our custom mesh to contain geometry
let objMesh;
objMesh = new Mesh({ "material": mat });
// console.log("mat", mat);
debug.log("parsing obj file...");
//OBJ parsing =====================================
const lines = text.toString().split("\n");
const uvs = [];
// let normals = [];
lines.forEach((line) => {
const words = line.split(" ");
//debug.log("LINE " + line);
switch (words[0]) {
case "mtllib":
break;
case "usemtl":
//debug.log("usemtl " + words[1]);
//to do : load mtl file
break;
case "o":
//debug.log("OBJ o " + words[1]);
break;
case "g":
//debug.log("OBJ g " + words[1]);
break;
case "v":
//debug.log("Vertice")
objMesh.pushVertex(new Vector3(words[1], words[2], words[3]));
break;
case "vt":
//debug.log("uv " + words[1] + " " + words[2]);
uvs.push(new Vector2(words[1], words[2]));
break;
case "vn":
//normals.push(new Vector3(words[1], words[2], words[3]));
//debug.log("normal")
break;
case "s":
//debug.log("Face")
break;
case "f": {//FACE definition
//debug.log(uvs);
//debug.log("Face")
const index1 = words[1].split("/");
const index2 = words[2].split("/");
const index3 = words[3].split("/");
objMesh.pushFace(index1[0] - 1, index2[0] - 1, index3[0] - 1);
objMesh.pushUV(uvs[index1[1] - 1], uvs[index2[1] - 1], uvs[index3[1] - 1]);
//debug.log(index1, index2, index3);
//objMesh.pushNormal(normals[index1[2]-1], normals[index2[2]-1], normals[index3[2]-1]); //NEW
//f.normal = new Vector3(normals[index1[2]-1], normals[index2[2]-1], normals[index3[2]-1]);
if (words.length > 4) {
//we have quads, we need to add an additionnal triangle
const index4 = words[4].split("/");
objMesh.pushFace(index1[0] - 1, index3[0] - 1, index4[0] - 1);
objMesh.pushUV(uvs[index1[1] - 1], uvs[index3[1] - 1], uvs[index4[1] - 1]);
}
break;
}
case "#":
break;
}
});
objMesh.updateMesh();
objMesh.computeNormals();
objMesh.genereateMesh();
return objMesh;
}
}