123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231 |
- import { Color3 } from "@babylonjs/core/Maths/math.color.js";
- import { Texture } from "@babylonjs/core/Materials/Textures/texture.js";
- import { StandardMaterial } from "@babylonjs/core/Materials/standardMaterial.js";
- /**
- * Class reading and parsing the MTL file bundled with the obj file.
- */
- export class MTLFileLoader {
- constructor() {
- /**
- * 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)
- */
- parseMTL(scene, data, rootUrl, assetContainer) {
- if (data instanceof ArrayBuffer) {
- return;
- }
- //Split the lines from the file
- const lines = data.split("\n");
- // whitespace char ie: [ \t\r\n\f]
- const delimiter_pattern = /\s+/;
- //Array with RGB colors
- let color;
- //New material
- let material = null;
- //Look at each line
- for (let i = 0; i < lines.length; i++) {
- const line = lines[i].trim();
- // Blank line or comment
- if (line.length === 0 || line.charAt(0) === "#") {
- continue;
- }
- //Get the first parameter (keyword)
- const pos = line.indexOf(" ");
- let key = pos >= 0 ? line.substring(0, pos) : line;
- key = key.toLowerCase();
- //Get the data following the key
- const 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 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 = 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 = 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 = Color3.FromArray(color);
- }
- else if (key === "ke" && material) {
- // Emissive color using RGB values
- color = value.split(delimiter_pattern, 3).map(parseFloat);
- material.emissiveColor = 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
- const values = value.split(delimiter_pattern);
- const bumpMultiplierIndex = values.indexOf("-bm");
- let 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
- */
- static _GetTexture(rootUrl, value, scene) {
- if (!value) {
- return null;
- }
- let url = rootUrl;
- // Load from input file.
- if (rootUrl === "file:") {
- let lastDelimiter = value.lastIndexOf("\\");
- if (lastDelimiter === -1) {
- lastDelimiter = value.lastIndexOf("/");
- }
- if (lastDelimiter > -1) {
- url += value.substr(lastDelimiter + 1);
- }
- else {
- url += value;
- }
- }
- // Not from input file.
- else {
- url += value;
- }
- return new Texture(url, scene, false, MTLFileLoader.INVERT_TEXTURE_Y);
- }
- }
- /**
- * Invert Y-Axis of referenced textures on load
- */
- MTLFileLoader.INVERT_TEXTURE_Y = true;
- //# sourceMappingURL=mtlFileLoader.js.map
|