@loaders.gl/obj
Version:
Framework-independent loader for the OBJ format
200 lines (183 loc) • 6.53 kB
JavaScript
// loaders.gl
// SPDX-License-Identifier: MIT
// Copyright (c) vis.gl contributors
// Forked from THREE.js under MIT license
// https://github.com/mrdoob/three.js/blob/master/examples/jsm/loaders/MTLLoader.js
const DELIMITER_PATTERN = /\s+/;
/**
* Parses a MTL file.
* Parses a Wavefront .mtl file specifying materials
* http://paulbourke.net/dataformats/mtl/
* https://www.loc.gov/preservation/digital/formats/fdd/fdd000508.shtml
*
* @param text - Content of MTL file
*/
// eslint-disable-next-line complexity
export function parseMTL(text, options) {
// const materialsInfo: Record<string, MTLMaterial> = {};
const materials = [];
let currentMaterial = { name: 'placeholder' };
const lines = text.split('\n');
for (let line of lines) {
line = line.trim();
if (line.length === 0 || line.charAt(0) === '#') {
// Blank line or comment ignore
continue; // eslint-disable-line no-continue
}
const pos = line.indexOf(' ');
let key = pos >= 0 ? line.substring(0, pos) : line;
key = key.toLowerCase();
let value = pos >= 0 ? line.substring(pos + 1) : '';
value = value.trim();
switch (key) {
case 'newmtl':
// New material
currentMaterial = { name: value };
// insert into map
materials.push(currentMaterial);
break;
case 'ka': // Ka
currentMaterial.ambientColor = parseColor(value);
break;
case 'kd':
// Kd: Diffuse color (color under white light) using RGB values
currentMaterial.diffuseColor = parseColor(value);
break;
case 'map_kd':
// Diffuse texture map
currentMaterial.diffuseTextureUrl = value;
// setMapForType('map', value);
break;
case 'ks':
// Specular color (color when light is reflected from shiny surface) using RGB values
currentMaterial.specularColor = parseColor(value);
break;
case 'map_ks':
// Specular map
currentMaterial.specularTextureUrl = value;
// setMapForType('specularMap', value);
break;
case 'ke':
// Emissive using RGB values
currentMaterial.emissiveColor = parseColor(value);
break;
case 'map_ke':
// Emissive map
currentMaterial.emissiveTextureUrl = value;
// setMapForType('emissiveMap', value);
break;
case 'ns':
// Ns is material specular exponent (defines the focus of the specular highlight)
// A high exponent results in a tight, concentrated highlight. Ns values normally range from 0 to 1000.
currentMaterial.shininess = parseFloat(value);
break;
case 'map_ns':
// Ns is material specular exponent
// TODO?
// currentMaterial.shininessMap = parseFloat(value);
break;
case 'ni':
currentMaterial.refraction = parseFloat(value);
break;
case 'illum':
currentMaterial.illumination = parseFloat(value);
break;
default:
// log unknown message?
break;
/*
case 'norm':
setMapForType('normalMap', value);
break;
case 'map_bump':
case 'bump':
// Bump texture map
setMapForType('bumpMap', value);
break;
case 'd':
n = parseFloat(value);
if (n < 1) {
params.opacity = n;
params.transparent = true;
}
break;
case 'map_d':
// Alpha map
setMapForType('alphaMap', value);
params.transparent = true;
break;
case 'tr':
n = parseFloat(value);
if (this.options && this.options.invertTrProperty) n = 1 - n;
if (n > 0) {
params.opacity = 1 - n;
params.transparent = true;
}
*/
}
}
return materials;
}
function parseColor(value, options) {
const rgb = value.split(DELIMITER_PATTERN, 3);
const color = [
parseFloat(rgb[0]),
parseFloat(rgb[1]),
parseFloat(rgb[2])
];
// TODO auto detect big values?
// if (this.options && this.options.normalizeRGB) {
// value = [ value[ 0 ] / 255, value[ 1 ] / 255, value[ 2 ] / 255 ];
// }
// if (this.options && this.options.ignoreZeroRGBs) {
// if (value[ 0 ] === 0 && value[ 1 ] === 0 && value[ 2 ] === 0) {
// // ignore
// save = false;
// }
// }
return color;
}
/* TODO parse url options
function parseTexture(value, matParams) {
const texParams = {
scale: new Vector2(1, 1),
offset: new Vector2(0, 0)
};
const items = value.split(/\s+/);
let pos;
pos = items.indexOf('-bm');
if (pos >= 0) {
matParams.bumpScale = parseFloat(items[ pos + 1 ]);
items.splice(pos, 2);
}
pos = items.indexOf('-s');
if (pos >= 0) {
texParams.scale.set(parseFloat(items[ pos + 1 ]), parseFloat(items[ pos + 2 ]));
items.splice(pos, 4); // we expect 3 parameters here!
}
pos = items.indexOf('-o');
if (pos >= 0) {
texParams.offset.set(parseFloat(items[ pos + 1 ]), parseFloat(items[ pos + 2 ]));
items.splice(pos, 4); // we expect 3 parameters here!
}
texParams.url = items.join(' ').trim();
return texParams;
}
*function resolveURL(baseUrl, url) {
* baseUrl?: string;
// Absolute URL
if (/^https?:\/\//i.test(url)) return url;
return baseUrl + url;
}
function setMapForType(mapType, value) {
if (params[ mapType ]) return; // Keep the first encountered texture
const texParams = scope.getTextureParams(value, params);
const map = scope.loadTexture(resolveURL(scope.baseUrl, texParams.url));
map.repeat.copy(texParams.scale);
map.offset.copy(texParams.offset);
map.wrapS = scope.wrap;
map.wrapT = scope.wrap;
params[ mapType ] = map;
}
*/
//# sourceMappingURL=parse-mtl.js.map