UNPKG

babylonjs-loaders

Version:

Babylon.js Loaders module =====================

1,017 lines (971 loc) 1.78 MB
(function webpackUniversalModuleDefinition(root, factory) { if(typeof exports === 'object' && typeof module === 'object') module.exports = factory(require("babylonjs")); else if(typeof define === 'function' && define.amd) define("babylonjs-loaders", ["babylonjs"], factory); else if(typeof exports === 'object') exports["babylonjs-loaders"] = factory(require("babylonjs")); else root["LOADERS"] = factory(root["BABYLON"]); })((typeof self !== "undefined" ? self : typeof global !== "undefined" ? global : this), (__WEBPACK_EXTERNAL_MODULE_babylonjs_Misc_tools__) => { return /******/ (() => { // webpackBootstrap /******/ "use strict"; /******/ var __webpack_modules__ = ({ /***/ "../../../dev/loaders/src/OBJ/index.ts": /*!*********************************************!*\ !*** ../../../dev/loaders/src/OBJ/index.ts ***! \*********************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ MTLFileLoader: () => (/* reexport safe */ _mtlFileLoader__WEBPACK_IMPORTED_MODULE_0__.MTLFileLoader), /* harmony export */ OBJFileLoader: () => (/* reexport safe */ _objFileLoader__WEBPACK_IMPORTED_MODULE_3__.OBJFileLoader), /* harmony export */ SolidParser: () => (/* reexport safe */ _solidParser__WEBPACK_IMPORTED_MODULE_2__.SolidParser) /* harmony export */ }); /* harmony import */ var _mtlFileLoader__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./mtlFileLoader */ "../../../dev/loaders/src/OBJ/mtlFileLoader.ts"); /* harmony import */ var _objLoadingOptions__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./objLoadingOptions */ "../../../dev/loaders/src/OBJ/objLoadingOptions.ts"); /* harmony import */ var _solidParser__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./solidParser */ "../../../dev/loaders/src/OBJ/solidParser.ts"); /* harmony import */ var _objFileLoader__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./objFileLoader */ "../../../dev/loaders/src/OBJ/objFileLoader.ts"); /***/ }), /***/ "../../../dev/loaders/src/OBJ/mtlFileLoader.ts": /*!*****************************************************!*\ !*** ../../../dev/loaders/src/OBJ/mtlFileLoader.ts ***! \*****************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ MTLFileLoader: () => (/* binding */ MTLFileLoader) /* harmony export */ }); /* harmony import */ var babylonjs_Maths_math_color__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Materials/standardMaterial */ "babylonjs/Misc/tools"); /* harmony import */ var babylonjs_Maths_math_color__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Maths_math_color__WEBPACK_IMPORTED_MODULE_0__); /** * Class reading and parsing the MTL file bundled with the obj file. */ var MTLFileLoader = /** @class */ (function () { function MTLFileLoader() { /** * All material loaded from the mtl will be set here */ this.materials = []; } /** * This function will read the mtl file and create each material described inside * This function could be improve by adding : * -some component missing (Ni, Tf...) * -including the specific options available * * @param scene defines the scene the material will be created in * @param data defines the mtl data to parse * @param rootUrl defines the rooturl to use in order to load relative dependencies * @param assetContainer defines the asset container to store the material in (can be null) */ MTLFileLoader.prototype.parseMTL = function (scene, data, rootUrl, assetContainer) { if (data instanceof ArrayBuffer) { return; } //Split the lines from the file var lines = data.split("\n"); // whitespace char ie: [ \t\r\n\f] var delimiter_pattern = /\s+/; //Array with RGB colors var color; //New material var material = null; //Look at each line for (var i = 0; i < lines.length; i++) { var line = lines[i].trim(); // Blank line or comment if (line.length === 0 || line.charAt(0) === "#") { continue; } //Get the first parameter (keyword) var pos = line.indexOf(" "); var key = pos >= 0 ? line.substring(0, pos) : line; key = key.toLowerCase(); //Get the data following the key var value = pos >= 0 ? line.substring(pos + 1).trim() : ""; //This mtl keyword will create the new material if (key === "newmtl") { //Check if it is the first material. // Materials specifications are described after this keyword. if (material) { //Add the previous material in the material array. this.materials.push(material); } //Create a new material. // value is the name of the material read in the mtl file scene._blockEntityCollection = !!assetContainer; material = new babylonjs_Maths_math_color__WEBPACK_IMPORTED_MODULE_0__.StandardMaterial(value, scene); material._parentContainer = assetContainer; scene._blockEntityCollection = false; } else if (key === "kd" && material) { // Diffuse color (color under white light) using RGB values //value = "r g b" color = value.split(delimiter_pattern, 3).map(parseFloat); //color = [r,g,b] //Set tghe color into the material material.diffuseColor = babylonjs_Maths_math_color__WEBPACK_IMPORTED_MODULE_0__.Color3.FromArray(color); } else if (key === "ka" && material) { // Ambient color (color under shadow) using RGB values //value = "r g b" color = value.split(delimiter_pattern, 3).map(parseFloat); //color = [r,g,b] //Set tghe color into the material material.ambientColor = babylonjs_Maths_math_color__WEBPACK_IMPORTED_MODULE_0__.Color3.FromArray(color); } else if (key === "ks" && material) { // Specular color (color when light is reflected from shiny surface) using RGB values //value = "r g b" color = value.split(delimiter_pattern, 3).map(parseFloat); //color = [r,g,b] //Set the color into the material material.specularColor = babylonjs_Maths_math_color__WEBPACK_IMPORTED_MODULE_0__.Color3.FromArray(color); } else if (key === "ke" && material) { // Emissive color using RGB values color = value.split(delimiter_pattern, 3).map(parseFloat); material.emissiveColor = babylonjs_Maths_math_color__WEBPACK_IMPORTED_MODULE_0__.Color3.FromArray(color); } else if (key === "ns" && material) { //value = "Integer" material.specularPower = parseFloat(value); } else if (key === "d" && material) { //d is dissolve for current material. It mean alpha for BABYLON material.alpha = parseFloat(value); //Texture //This part can be improved by adding the possible options of texture } else if (key === "map_ka" && material) { // ambient texture map with a loaded image //We must first get the folder of the image material.ambientTexture = MTLFileLoader._GetTexture(rootUrl, value, scene); } else if (key === "map_kd" && material) { // Diffuse texture map with a loaded image material.diffuseTexture = MTLFileLoader._GetTexture(rootUrl, value, scene); } else if (key === "map_ks" && material) { // Specular texture map with a loaded image //We must first get the folder of the image material.specularTexture = MTLFileLoader._GetTexture(rootUrl, value, scene); } else if (key === "map_ns") { //Specular //Specular highlight component //We must first get the folder of the image // //Not supported by BABYLON // // continue; } else if (key === "map_bump" && material) { //The bump texture var values = value.split(delimiter_pattern); var bumpMultiplierIndex = values.indexOf("-bm"); var bumpMultiplier = null; if (bumpMultiplierIndex >= 0) { bumpMultiplier = values[bumpMultiplierIndex + 1]; values.splice(bumpMultiplierIndex, 2); // remove } material.bumpTexture = MTLFileLoader._GetTexture(rootUrl, values.join(" "), scene); if (material.bumpTexture && bumpMultiplier !== null) { material.bumpTexture.level = parseFloat(bumpMultiplier); } } else if (key === "map_d" && material) { // The dissolve of the material material.opacityTexture = MTLFileLoader._GetTexture(rootUrl, value, scene); //Options for illumination } else if (key === "illum") { //Illumination if (value === "0") { //That mean Kd == Kd } else if (value === "1") { //Color on and Ambient on } else if (value === "2") { //Highlight on } else if (value === "3") { //Reflection on and Ray trace on } else if (value === "4") { //Transparency: Glass on, Reflection: Ray trace on } else if (value === "5") { //Reflection: Fresnel on and Ray trace on } else if (value === "6") { //Transparency: Refraction on, Reflection: Fresnel off and Ray trace on } else if (value === "7") { //Transparency: Refraction on, Reflection: Fresnel on and Ray trace on } else if (value === "8") { //Reflection on and Ray trace off } else if (value === "9") { //Transparency: Glass on, Reflection: Ray trace off } else if (value === "10") { //Casts shadows onto invisible surfaces } } else { // console.log("Unhandled expression at line : " + i +'\n' + "with value : " + line); } } //At the end of the file, add the last material if (material) { this.materials.push(material); } }; /** * Gets the texture for the material. * * If the material is imported from input file, * We sanitize the url to ensure it takes the texture from aside the material. * * @param rootUrl The root url to load from * @param value The value stored in the mtl * @param scene * @returns The Texture */ MTLFileLoader._GetTexture = function (rootUrl, value, scene) { if (!value) { return null; } var url = rootUrl; // Load from input file. if (rootUrl === "file:") { var lastDelimiter = value.lastIndexOf("\\"); if (lastDelimiter === -1) { lastDelimiter = value.lastIndexOf("/"); } if (lastDelimiter > -1) { url += value.substring(lastDelimiter + 1); } else { url += value; } } // Not from input file. else { url += value; } return new babylonjs_Maths_math_color__WEBPACK_IMPORTED_MODULE_0__.Texture(url, scene, false, MTLFileLoader.INVERT_TEXTURE_Y); }; /** * Invert Y-Axis of referenced textures on load */ MTLFileLoader.INVERT_TEXTURE_Y = true; return MTLFileLoader; }()); /***/ }), /***/ "../../../dev/loaders/src/OBJ/objFileLoader.metadata.ts": /*!**************************************************************!*\ !*** ../../../dev/loaders/src/OBJ/objFileLoader.metadata.ts ***! \**************************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ OBJFileLoaderMetadata: () => (/* binding */ OBJFileLoaderMetadata) /* harmony export */ }); var OBJFileLoaderMetadata = { name: "obj", extensions: ".obj", }; /***/ }), /***/ "../../../dev/loaders/src/OBJ/objFileLoader.ts": /*!*****************************************************!*\ !*** ../../../dev/loaders/src/OBJ/objFileLoader.ts ***! \*****************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ OBJFileLoader: () => (/* binding */ OBJFileLoader) /* harmony export */ }); /* harmony import */ var babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Materials/standardMaterial */ "babylonjs/Misc/tools"); /* harmony import */ var babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var _objFileLoader_metadata__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./objFileLoader.metadata */ "../../../dev/loaders/src/OBJ/objFileLoader.metadata.ts"); /* harmony import */ var _mtlFileLoader__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./mtlFileLoader */ "../../../dev/loaders/src/OBJ/mtlFileLoader.ts"); /* harmony import */ var _solidParser__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./solidParser */ "../../../dev/loaders/src/OBJ/solidParser.ts"); /** * OBJ file type loader. * This is a babylon scene loader plugin. */ var OBJFileLoader = /** @class */ (function () { /** * Creates loader for .OBJ files * * @param loadingOptions options for loading and parsing OBJ/MTL files. */ function OBJFileLoader(loadingOptions) { /** * Defines the name of the plugin. */ this.name = _objFileLoader_metadata__WEBPACK_IMPORTED_MODULE_1__.OBJFileLoaderMetadata.name; /** * Defines the extension the plugin is able to load. */ this.extensions = _objFileLoader_metadata__WEBPACK_IMPORTED_MODULE_1__.OBJFileLoaderMetadata.extensions; this._assetContainer = null; this._loadingOptions = loadingOptions || OBJFileLoader._DefaultLoadingOptions; } Object.defineProperty(OBJFileLoader, "INVERT_TEXTURE_Y", { /** * Invert Y-Axis of referenced textures on load */ get: function () { return _mtlFileLoader__WEBPACK_IMPORTED_MODULE_2__.MTLFileLoader.INVERT_TEXTURE_Y; }, set: function (value) { _mtlFileLoader__WEBPACK_IMPORTED_MODULE_2__.MTLFileLoader.INVERT_TEXTURE_Y = value; }, enumerable: false, configurable: true }); Object.defineProperty(OBJFileLoader, "_DefaultLoadingOptions", { get: function () { return { computeNormals: OBJFileLoader.COMPUTE_NORMALS, optimizeNormals: OBJFileLoader.OPTIMIZE_NORMALS, importVertexColors: OBJFileLoader.IMPORT_VERTEX_COLORS, invertY: OBJFileLoader.INVERT_Y, invertTextureY: OBJFileLoader.INVERT_TEXTURE_Y, // eslint-disable-next-line @typescript-eslint/naming-convention UVScaling: OBJFileLoader.UV_SCALING, materialLoadingFailsSilently: OBJFileLoader.MATERIAL_LOADING_FAILS_SILENTLY, optimizeWithUV: OBJFileLoader.OPTIMIZE_WITH_UV, skipMaterials: OBJFileLoader.SKIP_MATERIALS, useLegacyBehavior: OBJFileLoader.USE_LEGACY_BEHAVIOR, }; }, enumerable: false, configurable: true }); /** * Calls synchronously the MTL file attached to this obj. * Load function or importMesh function don't enable to load 2 files in the same time asynchronously. * Without this function materials are not displayed in the first frame (but displayed after). * In consequence it is impossible to get material information in your HTML file * * @param url The URL of the MTL file * @param rootUrl defines where to load data from * @param onSuccess Callback function to be called when the MTL file is loaded * @param onFailure */ OBJFileLoader.prototype._loadMTL = function (url, rootUrl, onSuccess, onFailure) { //The complete path to the mtl file var pathOfFile = rootUrl + url; // Loads through the babylon tools to allow fileInput search. babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__.Tools.LoadFile(pathOfFile, onSuccess, undefined, undefined, false, function (request, exception) { onFailure(pathOfFile, exception); }); }; /** * Instantiates a OBJ file loader plugin. * @returns the created plugin */ OBJFileLoader.prototype.createPlugin = function () { return new OBJFileLoader(OBJFileLoader._DefaultLoadingOptions); }; /** * If the data string can be loaded directly. * @returns if the data can be loaded directly */ OBJFileLoader.prototype.canDirectLoad = function () { return false; }; /** * Imports one or more meshes from the loaded OBJ data and adds them to the scene * @param meshesNames a string or array of strings of the mesh names that should be loaded from the file * @param scene the scene the meshes should be added to * @param data the OBJ data to load * @param rootUrl root url to load from * @returns a promise containing the loaded meshes, particles, skeletons and animations */ OBJFileLoader.prototype.importMeshAsync = function (meshesNames, scene, data, rootUrl) { //get the meshes from OBJ file return this._parseSolid(meshesNames, scene, data, rootUrl).then(function (meshes) { return { meshes: meshes, particleSystems: [], skeletons: [], animationGroups: [], transformNodes: [], geometries: [], lights: [], spriteManagers: [], }; }); }; /** * Imports all objects from the loaded OBJ data and adds them to the scene * @param scene the scene the objects should be added to * @param data the OBJ data to load * @param rootUrl root url to load from * @returns a promise which completes when objects have been loaded to the scene */ OBJFileLoader.prototype.loadAsync = function (scene, data, rootUrl) { //Get the 3D model return this.importMeshAsync(null, scene, data, rootUrl).then(function () { // return void }); }; /** * Load into an asset container. * @param scene The scene to load into * @param data The data to import * @param rootUrl The root url for scene and resources * @returns The loaded asset container */ OBJFileLoader.prototype.loadAssetContainerAsync = function (scene, data, rootUrl) { var _this = this; var container = new babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__.AssetContainer(scene); this._assetContainer = container; return this.importMeshAsync(null, scene, data, rootUrl) .then(function (result) { result.meshes.forEach(function (mesh) { return container.meshes.push(mesh); }); result.meshes.forEach(function (mesh) { var material = mesh.material; if (material) { // Materials if (container.materials.indexOf(material) == -1) { container.materials.push(material); // Textures var textures = material.getActiveTextures(); textures.forEach(function (t) { if (container.textures.indexOf(t) == -1) { container.textures.push(t); } }); } } }); _this._assetContainer = null; return container; }) .catch(function (ex) { _this._assetContainer = null; throw ex; }); }; /** * Read the OBJ file and create an Array of meshes. * Each mesh contains all information given by the OBJ and the MTL file. * i.e. vertices positions and indices, optional normals values, optional UV values, optional material * @param meshesNames defines a string or array of strings of the mesh names that should be loaded from the file * @param scene defines the scene where are displayed the data * @param data defines the content of the obj file * @param rootUrl defines the path to the folder * @returns the list of loaded meshes */ OBJFileLoader.prototype._parseSolid = function (meshesNames, scene, data, rootUrl) { var _this = this; var fileToLoad = ""; //The name of the mtlFile to load var materialsFromMTLFile = new _mtlFileLoader__WEBPACK_IMPORTED_MODULE_2__.MTLFileLoader(); var materialToUse = []; var babylonMeshesArray = []; //The mesh for babylon // Sanitize data data = data.replace(/#.*$/gm, "").trim(); // Main function var solidParser = new _solidParser__WEBPACK_IMPORTED_MODULE_3__.SolidParser(materialToUse, babylonMeshesArray, this._loadingOptions); solidParser.parse(meshesNames, data, scene, this._assetContainer, function (fileName) { fileToLoad = fileName; }); // load the materials var mtlPromises = []; // Check if we have a file to load if (fileToLoad !== "" && !this._loadingOptions.skipMaterials) { //Load the file synchronously mtlPromises.push(new Promise(function (resolve, reject) { _this._loadMTL(fileToLoad, rootUrl, function (dataLoaded) { try { //Create materials thanks MTLLoader function materialsFromMTLFile.parseMTL(scene, dataLoaded, rootUrl, _this._assetContainer); //Look at each material loaded in the mtl file for (var n = 0; n < materialsFromMTLFile.materials.length; n++) { //Three variables to get all meshes with the same material var startIndex = 0; var _indices = []; var _index = void 0; //The material from MTL file is used in the meshes loaded //Push the indice in an array //Check if the material is not used for another mesh while ((_index = materialToUse.indexOf(materialsFromMTLFile.materials[n].name, startIndex)) > -1) { _indices.push(_index); startIndex = _index + 1; } //If the material is not used dispose it if (_index === -1 && _indices.length === 0) { //If the material is not needed, remove it materialsFromMTLFile.materials[n].dispose(); } else { for (var o = 0; o < _indices.length; o++) { //Apply the material to the Mesh for each mesh with the material var mesh = babylonMeshesArray[_indices[o]]; var material = materialsFromMTLFile.materials[n]; mesh.material = material; if (!mesh.getTotalIndices()) { // No indices, we need to turn on point cloud material.pointsCloud = true; } } } } resolve(); } catch (e) { babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__.Tools.Warn("Error processing MTL file: '".concat(fileToLoad, "'")); if (_this._loadingOptions.materialLoadingFailsSilently) { resolve(); } else { reject(e); } } }, function (pathOfFile, exception) { babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__.Tools.Warn("Error downloading MTL file: '".concat(fileToLoad, "'")); if (_this._loadingOptions.materialLoadingFailsSilently) { resolve(); } else { reject(exception); } }); })); } //Return an array with all Mesh return Promise.all(mtlPromises).then(function () { var isLine = function (mesh) { var _a, _b; return Boolean((_b = (_a = mesh._internalMetadata) === null || _a === void 0 ? void 0 : _a["_isLine"]) !== null && _b !== void 0 ? _b : false); }; // Iterate over the mesh, determine if it is a line mesh, clone or modify the material to line rendering. babylonMeshesArray.forEach(function (mesh) { var _a, _b; if (isLine(mesh)) { var mat = (_a = mesh.material) !== null && _a !== void 0 ? _a : new babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__.StandardMaterial(mesh.name + "_line", scene); // If another mesh is using this material and it is not a line then we need to clone it. var needClone = mat.getBindedMeshes().filter(function (e) { return !isLine(e); }).length > 0; if (needClone) { mat = (_b = mat.clone(mat.name + "_line")) !== null && _b !== void 0 ? _b : mat; } mat.wireframe = true; mesh.material = mat; if (mesh._internalMetadata) { mesh._internalMetadata["_isLine"] = undefined; } } }); return babylonMeshesArray; }); }; /** * Defines if UVs are optimized by default during load. */ OBJFileLoader.OPTIMIZE_WITH_UV = true; /** * Invert model on y-axis (does a model scaling inversion) */ OBJFileLoader.INVERT_Y = false; /** * Include in meshes the vertex colors available in some OBJ files. This is not part of OBJ standard. */ OBJFileLoader.IMPORT_VERTEX_COLORS = false; /** * Compute the normals for the model, even if normals are present in the file. */ OBJFileLoader.COMPUTE_NORMALS = false; /** * Optimize the normals for the model. Lighting can be uneven if you use OptimizeWithUV = true because new vertices can be created for the same location if they pertain to different faces. * Using OptimizehNormals = true will help smoothing the lighting by averaging the normals of those vertices. */ OBJFileLoader.OPTIMIZE_NORMALS = false; /** * Defines custom scaling of UV coordinates of loaded meshes. */ OBJFileLoader.UV_SCALING = new babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__.Vector2(1, 1); /** * Skip loading the materials even if defined in the OBJ file (materials are ignored). */ OBJFileLoader.SKIP_MATERIALS = false; /** * When a material fails to load OBJ loader will silently fail and onSuccess() callback will be triggered. * * Defaults to true for backwards compatibility. */ OBJFileLoader.MATERIAL_LOADING_FAILS_SILENTLY = true; /** * Loads assets without handedness conversions. This flag is for compatibility. Use it only if absolutely required. Defaults to false. */ OBJFileLoader.USE_LEGACY_BEHAVIOR = false; return OBJFileLoader; }()); //Add this loader into the register plugin (0,babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__.registerSceneLoaderPlugin)(new OBJFileLoader()); /***/ }), /***/ "../../../dev/loaders/src/OBJ/objLoadingOptions.ts": /*!*********************************************************!*\ !*** ../../../dev/loaders/src/OBJ/objLoadingOptions.ts ***! \*********************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /***/ }), /***/ "../../../dev/loaders/src/OBJ/solidParser.ts": /*!***************************************************!*\ !*** ../../../dev/loaders/src/OBJ/solidParser.ts ***! \***************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ SolidParser: () => (/* binding */ SolidParser) /* harmony export */ }); /* harmony import */ var babylonjs_Buffers_buffer__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Misc/logger */ "babylonjs/Misc/tools"); /* harmony import */ var babylonjs_Buffers_buffer__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Buffers_buffer__WEBPACK_IMPORTED_MODULE_0__); /** * Class used to load mesh data from OBJ content */ var SolidParser = /** @class */ (function () { /** * Creates a new SolidParser * @param materialToUse defines the array to fill with the list of materials to use (it will be filled by the parse function) * @param babylonMeshesArray defines the array to fill with the list of loaded meshes (it will be filled by the parse function) * @param loadingOptions defines the loading options to use */ function SolidParser(materialToUse, babylonMeshesArray, loadingOptions) { this._positions = []; //values for the positions of vertices this._normals = []; //Values for the normals this._uvs = []; //Values for the textures this._colors = []; this._extColors = []; //Extension color this._meshesFromObj = []; //[mesh] Contains all the obj meshes this._indicesForBabylon = []; //The list of indices for VertexData this._wrappedPositionForBabylon = []; //The list of position in vectors this._wrappedUvsForBabylon = []; //Array with all value of uvs to match with the indices this._wrappedColorsForBabylon = []; // Array with all color values to match with the indices this._wrappedNormalsForBabylon = []; //Array with all value of normals to match with the indices this._tuplePosNorm = []; //Create a tuple with indice of Position, Normal, UV [pos, norm, uvs] this._curPositionInIndices = 0; this._hasMeshes = false; //Meshes are defined in the file this._unwrappedPositionsForBabylon = []; //Value of positionForBabylon w/o Vector3() [x,y,z] this._unwrappedColorsForBabylon = []; // Value of colorForBabylon w/o Color4() [r,g,b,a] this._unwrappedNormalsForBabylon = []; //Value of normalsForBabylon w/o Vector3() [x,y,z] this._unwrappedUVForBabylon = []; //Value of uvsForBabylon w/o Vector3() [x,y,z] this._triangles = []; //Indices from new triangles coming from polygons this._materialNameFromObj = ""; //The name of the current material this._objMeshName = ""; //The name of the current obj mesh this._increment = 1; //Id for meshes created by the multimaterial this._isFirstMaterial = true; this._grayColor = new babylonjs_Buffers_buffer__WEBPACK_IMPORTED_MODULE_0__.Color4(0.5, 0.5, 0.5, 1); this._hasLineData = false; //If this mesh has line segment(l) data this._materialToUse = materialToUse; this._babylonMeshesArray = babylonMeshesArray; this._loadingOptions = loadingOptions; } /** * Search for obj in the given array. * This function is called to check if a couple of data already exists in an array. * * If found, returns the index of the founded tuple index. Returns -1 if not found * @param arr Array<{ normals: Array<number>, idx: Array<number> }> * @param obj Array<number> * @returns {boolean} */ SolidParser.prototype._isInArray = function (arr, obj) { if (!arr[obj[0]]) { arr[obj[0]] = { normals: [], idx: [] }; } var idx = arr[obj[0]].normals.indexOf(obj[1]); return idx === -1 ? -1 : arr[obj[0]].idx[idx]; }; SolidParser.prototype._isInArrayUV = function (arr, obj) { if (!arr[obj[0]]) { arr[obj[0]] = { normals: [], idx: [], uv: [] }; } var idx = arr[obj[0]].normals.indexOf(obj[1]); if (idx != 1 && obj[2] === arr[obj[0]].uv[idx]) { return arr[obj[0]].idx[idx]; } return -1; }; /** * This function set the data for each triangle. * Data are position, normals and uvs * If a tuple of (position, normal) is not set, add the data into the corresponding array * If the tuple already exist, add only their indice * * @param indicePositionFromObj Integer The index in positions array * @param indiceUvsFromObj Integer The index in uvs array * @param indiceNormalFromObj Integer The index in normals array * @param positionVectorFromOBJ Vector3 The value of position at index objIndice * @param textureVectorFromOBJ Vector3 The value of uvs * @param normalsVectorFromOBJ Vector3 The value of normals at index objNormale * @param positionColorsFromOBJ */ SolidParser.prototype._setData = function (indicePositionFromObj, indiceUvsFromObj, indiceNormalFromObj, positionVectorFromOBJ, textureVectorFromOBJ, normalsVectorFromOBJ, positionColorsFromOBJ) { //Check if this tuple already exists in the list of tuples var _index; if (this._loadingOptions.optimizeWithUV) { _index = this._isInArrayUV(this._tuplePosNorm, [indicePositionFromObj, indiceNormalFromObj, indiceUvsFromObj]); } else { _index = this._isInArray(this._tuplePosNorm, [indicePositionFromObj, indiceNormalFromObj]); } //If it not exists if (_index === -1) { //Add an new indice. //The array of indices is only an array with his length equal to the number of triangles - 1. //We add vertices data in this order this._indicesForBabylon.push(this._wrappedPositionForBabylon.length); //Push the position of vertice for Babylon //Each element is a Vector3(x,y,z) this._wrappedPositionForBabylon.push(positionVectorFromOBJ); //Push the uvs for Babylon //Each element is a Vector2(u,v) //If the UVs are missing, set (u,v)=(0,0) textureVectorFromOBJ = textureVectorFromOBJ !== null && textureVectorFromOBJ !== void 0 ? textureVectorFromOBJ : new babylonjs_Buffers_buffer__WEBPACK_IMPORTED_MODULE_0__.Vector2(0, 0); this._wrappedUvsForBabylon.push(textureVectorFromOBJ); //Push the normals for Babylon //Each element is a Vector3(x,y,z) this._wrappedNormalsForBabylon.push(normalsVectorFromOBJ); if (positionColorsFromOBJ !== undefined) { //Push the colors for Babylon //Each element is a BABYLON.Color4(r,g,b,a) this._wrappedColorsForBabylon.push(positionColorsFromOBJ); } //Add the tuple in the comparison list this._tuplePosNorm[indicePositionFromObj].normals.push(indiceNormalFromObj); this._tuplePosNorm[indicePositionFromObj].idx.push(this._curPositionInIndices++); if (this._loadingOptions.optimizeWithUV) { this._tuplePosNorm[indicePositionFromObj].uv.push(indiceUvsFromObj); } } else { //The tuple already exists //Add the index of the already existing tuple //At this index we can get the value of position, normal, color and uvs of vertex this._indicesForBabylon.push(_index); } }; /** * Transform Vector() and BABYLON.Color() objects into numbers in an array */ SolidParser.prototype._unwrapData = function () { try { //Every array has the same length for (var l = 0; l < this._wrappedPositionForBabylon.length; l++) { //Push the x, y, z values of each element in the unwrapped array this._unwrappedPositionsForBabylon.push(this._wrappedPositionForBabylon[l].x * this._handednessSign, this._wrappedPositionForBabylon[l].y, this._wrappedPositionForBabylon[l].z); this._unwrappedNormalsForBabylon.push(this._wrappedNormalsForBabylon[l].x * this._handednessSign, this._wrappedNormalsForBabylon[l].y, this._wrappedNormalsForBabylon[l].z); this._unwrappedUVForBabylon.push(this._wrappedUvsForBabylon[l].x, this._wrappedUvsForBabylon[l].y); //z is an optional value not supported by BABYLON if (this._loadingOptions.importVertexColors) { //Push the r, g, b, a values of each element in the unwrapped array this._unwrappedColorsForBabylon.push(this._wrappedColorsForBabylon[l].r, this._wrappedColorsForBabylon[l].g, this._wrappedColorsForBabylon[l].b, this._wrappedColorsForBabylon[l].a); } } // Reset arrays for the next new meshes this._wrappedPositionForBabylon.length = 0; this._wrappedNormalsForBabylon.length = 0; this._wrappedUvsForBabylon.length = 0; this._wrappedColorsForBabylon.length = 0; this._tuplePosNorm.length = 0; this._curPositionInIndices = 0; } catch (e) { throw new Error("Unable to unwrap data while parsing OBJ data."); } }; /** * Create triangles from polygons * It is important to notice that a triangle is a polygon * We get 5 patterns of face defined in OBJ File : * facePattern1 = ["1","2","3","4","5","6"] * facePattern2 = ["1/1","2/2","3/3","4/4","5/5","6/6"] * facePattern3 = ["1/1/1","2/2/2","3/3/3","4/4/4","5/5/5","6/6/6"] * facePattern4 = ["1//1","2//2","3//3","4//4","5//5","6//6"] * facePattern5 = ["-1/-1/-1","-2/-2/-2","-3/-3/-3","-4/-4/-4","-5/-5/-5","-6/-6/-6"] * Each pattern is divided by the same method * @param faces Array[String] The indices of elements * @param v Integer The variable to increment */ SolidParser.prototype._getTriangles = function (faces, v) { //Work for each element of the array for (var faceIndex = v; faceIndex < faces.length - 1; faceIndex++) { //Add on the triangle variable the indexes to obtain triangles this._pushTriangle(faces, faceIndex); } //Result obtained after 2 iterations: //Pattern1 => triangle = ["1","2","3","1","3","4"]; //Pattern2 => triangle = ["1/1","2/2","3/3","1/1","3/3","4/4"]; //Pattern3 => triangle = ["1/1/1","2/2/2","3/3/3","1/1/1","3/3/3","4/4/4"]; //Pattern4 => triangle = ["1//1","2//2","3//3","1//1","3//3","4//4"]; //Pattern5 => triangle = ["-1/-1/-1","-2/-2/-2","-3/-3/-3","-1/-1/-1","-3/-3/-3","-4/-4/-4"]; }; /** * To get color between color and extension color * @param index Integer The index of the element in the array * @returns value of target color */ SolidParser.prototype._getColor = function (index) { var _a; if (this._loadingOptions.importVertexColors) { return (_a = this._extColors[index]) !== null && _a !== void 0 ? _a : this._colors[index]; } else { return undefined; } }; /** * Create triangles and push the data for each polygon for the pattern 1 * In this pattern we get vertice positions * @param face * @param v */ SolidParser.prototype._setDataForCurrentFaceWithPattern1 = function (face, v) { //Get the indices of triangles for each polygon this._getTriangles(face, v); //For each element in the triangles array. //This var could contains 1 to an infinity of triangles for (var k = 0; k < this._triangles.length; k++) { // Set position indice var indicePositionFromObj = parseInt(this._triangles[k]) - 1; this._setData(indicePositionFromObj, 0, 0, // In the pattern 1, normals and uvs are not defined this._positions[indicePositionFromObj], // Get the vectors data babylonjs_Buffers_buffer__WEBPACK_IMPORTED_MODULE_0__.Vector2.Zero(), babylonjs_Buffers_buffer__WEBPACK_IMPORTED_MODULE_0__.Vector3.Up(), // Create default vectors this._getColor(indicePositionFromObj)); } //Reset variable for the next line this._triangles.length = 0; }; /** * Create triangles and push the data for each polygon for the pattern 2 * In this pattern we get vertice positions and uvs * @param face * @param v */ SolidParser.prototype._setDataForCurrentFaceWithPattern2 = function (face, v) { var _a; //Get the indices of triangles for each polygon this._getTriangles(face, v); for (var k = 0; k < this._triangles.length; k++) { //triangle[k] = "1/1" //Split the data for getting position and uv var point = this._triangles[k].split("/"); // ["1", "1"] //Set position indice var indicePositionFromObj = parseInt(point[0]) - 1; //Set uv indice var indiceUvsFromObj = parseInt(point[1]) - 1; this._setData(indicePositionFromObj, indiceUvsFromObj, 0, //Default value for normals this._positions[indicePositionFromObj], //Get the values for each element (_a = this._uvs[indiceUvsFromObj]) !== null && _a !== void 0 ? _a : babylonjs_Buffers_buffer__WEBPACK_IMPORTED_MODULE_0__.Vector2.Zero(), babylonjs_Buffers_buffer__WEBPACK_IMPORTED_MODULE_0__.Vector3.Up(), //Default value for normals this._getColor(indicePositionFromObj)); } //Reset variable for the next line this._triangles.length = 0; }; /** * Create triangles and push the data for each polygon for the pattern 3 * In this pattern we get vertice positions, uvs and normals * @param face * @param v */ SolidParser.prototype._setDataForCurrentFaceWithPattern3 = function (face, v) { var _a, _b; //Get the indices of triangles for each polygon this._getTriangles(face, v); for (var k = 0; k < this._triangles.length; k++) { //triangle[k] = "1/1/1" //Split the data for getting position, uv, and normals var point = this._triangles[k].split("/"); // ["1", "1", "1"] // Set position indice var indicePositionFromObj = parseInt(point[0]) - 1; // Set uv indice var indiceUvsFromObj = parseInt(point[1]) - 1; // Set normal indice var indiceNormalFromObj = parseInt(point[2]) - 1; this._setData(indicePositionFromObj, indiceUvsFromObj, indiceNormalFromObj, this._positions[indicePositionFromObj], (_a = this._uvs[indiceUvsFromObj]) !== null && _a !== void 0 ? _a : babylonjs_Buffers_buffer__WEBPACK_IMPORTED_MODULE_0__.Vector2.Zero(), (_b = this._normals[indiceNormalFromObj]) !== null && _b !== void 0 ? _b : babylonjs_Buffers_buffer__WEBPACK_IMPORTED_MODULE_0__.Vector3.Up() //Set the vector for each component ); } //Reset variable for the next line this._triangles.length = 0; }; /** * Create triangles and push the data for each polygon for the pattern 4 * In this pattern we get vertice positions and normals * @param face * @param v */ SolidParser.prototype._setDataForCurrentFaceWithPattern4 = function (face, v) { this._getTriangles(face, v); for (var k = 0; k < this._triangles.length; k++) { //triangle[k] = "1//1" //Split the data for getting position and normals var point = this._triangles[k].split("//"); // ["1", "1"] // We check indices, and normals var indicePositionFromObj = parseInt(point[0]) - 1; var indiceNormalFromObj = parseInt(point[1]) - 1; this._setData(indicePositionFromObj, 1, //Default value for uv indiceNormalFromObj, this._positions[indicePositionFromObj], //Get each vector of data babylonjs_Buffers_buffer__WEBPACK_IMPORTED_MODULE_0__.Vector2.Zero(), this._normals[indiceNormalFromObj], this._getColor(indicePositionFromObj)); } //Reset variable for the next line this._triangles.length = 0; }; /* * Create triangles and push the data for each polygon for the pattern 3 * In this pattern we get vertice positions, uvs and normals * @param face * @param v */ SolidParser.prototype._setDataForCurrentFaceWithPattern5 = function (face, v) { //Get the indices of triangles for each polygon this._getTriangles(face, v); for (var k = 0; k < this._triangles.length; k++) { //triangle[k] = "-1/-1/-1" //Split the data for getting position, uv, and normals var point = this._triangles[k].split("/"); // ["-1", "-1", "-1"] // Set position indice var indicePositionFromObj = this._positions.length + parseInt(point[0]); // Set uv indice var indiceUvsFromObj = this._uvs.length + parseInt(point[1]); // Set normal indice var indiceNormalFromObj = this._normals.length + parseInt(point[2]); this._setData(indicePositionFromObj, indiceUvsFromObj, indiceNormalFromObj, this._positions[indicePositionFromObj], this._uvs[indiceUvsFromObj], this._normals[indiceNormalFromObj], //Set the vector for each component this._getColor(indicePositionFromObj)); } //Reset variable for the next line this._triangles.length = 0; }; SolidParser.prototype._addPreviousObjMesh = function () { //Check if it is not the first mesh. Otherwise we don't have data. if (this._meshesFromObj.length > 0) { //Get the previous mesh for applying the data about the faces //=> in obj file, faces definition append after the name of the mesh this._handledMesh = this._meshesFromObj[this._meshesFromObj.length - 1]; //Set the data into Array for the mesh this._unwrapData(); if (this._loadingOptions.useLegacyBehavior) { // Reverse tab. Otherwise face are displayed in the wrong sens this._indicesForBabylon.reverse(); } //Set the information for the mesh //Slice the array to avoid rewriting because of the fact this is the same var which be rewrited this._handledMesh.indices = this._indicesForBabylon.slice(); this._handledMesh.positions = this._unwrappedPositionsForBabylon.slice(); this._handledMesh.normals = this._unwrappedNormalsForBabylon.slice(); this._handledMesh.uvs = this._unwrappedUVForBabylon.slice(); this._handledMesh.hasLines = this._hasLineData; if (this._loadingOptions.importVertexColors) { this._handledMesh.colors = this._unwrappedColorsForBabylon.slice(); } //Reset the array for the next mesh this._indicesForBabylon.length = 0; this._unwrappedPositionsForBabylon.length = 0; this._unwrappedColorsForBabylon.length = 0; this._unwrappedNormalsForBabylon.length = 0; this.