babylonjs-loaders
Version:
Babylon.js Loaders module =====================
1,017 lines (971 loc) • 1.78 MB
JavaScript
(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.