Repository

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;
    }
}