diff --git a/lib/createGltf.js b/lib/createGltf.js index bc1d77e..5d011b1 100644 --- a/lib/createGltf.js +++ b/lib/createGltf.js @@ -237,11 +237,10 @@ function addTexture(gltf, texture) { function getTexture(gltf, texture) { let textureIndex; - const name = texture.name; - const textures = gltf.textures; - const length = textures.length; + const images = gltf.images; + const length = images.length; for (let i = 0; i < length; ++i) { - if (textures[i].name === name) { + if (images[i].extras._obj2gltf === texture) { textureIndex = i; break; } diff --git a/lib/loadMtl.js b/lib/loadMtl.js index dc42545..e0380b5 100644 --- a/lib/loadMtl.js +++ b/lib/loadMtl.js @@ -8,6 +8,7 @@ const readLines = require('./readLines'); const Texture = require('./Texture'); const CesiumMath = Cesium.Math; +const clone = Cesium.clone; const combine = Cesium.combine; const defaultValue = Cesium.defaultValue; const defined = Cesium.defined; @@ -178,13 +179,30 @@ function loadMtl(mtlPath, options) { material.ambientTexture = undefined; } - loadMaterialTexture(material, 'diffuseTexture', diffuseAlphaTextureOptions, mtlDirectory, texturePromiseMap, texturePromises, options); - loadMaterialTexture(material, 'ambientTexture', ambientTextureOptions, mtlDirectory, texturePromiseMap, texturePromises, options); - loadMaterialTexture(material, 'emissiveTexture', emissiveTextureOptions, mtlDirectory, texturePromiseMap, texturePromises, options); - loadMaterialTexture(material, 'specularTexture', specularTextureOptions, mtlDirectory, texturePromiseMap, texturePromises, options); - loadMaterialTexture(material, 'specularShininessTexture', specularShinessTextureOptions, mtlDirectory, texturePromiseMap, texturePromises, options); - loadMaterialTexture(material, 'normalTexture', normalTextureOptions, mtlDirectory, texturePromiseMap, texturePromises, options); - loadMaterialTexture(material, 'alphaTexture', alphaTextureOptions, mtlDirectory, texturePromiseMap, texturePromises, options); + const textureNames = ['diffuseTexture', 'ambientTexture', 'emissiveTexture', 'specularTexture', 'specularShininessTexture', 'normalTexture', 'alphaTexture']; + const textureOptions = [diffuseAlphaTextureOptions, ambientTextureOptions, emissiveTextureOptions, specularTextureOptions, specularShinessTextureOptions, normalTextureOptions, alphaTextureOptions]; + + const sharedOptions = {}; + textureNames.forEach(function(name, index) { + const texturePath = material[name]; + const originalOptions = textureOptions[index]; + if (defined(texturePath) && defined(originalOptions)) { + if (!defined(sharedOptions[texturePath])) { + sharedOptions[texturePath] = clone(originalOptions); + } + const options = sharedOptions[texturePath]; + options.checkTransparency = options.checkTransparency || originalOptions.checkTransparency; + options.decode = options.decode || originalOptions.decode; + options.keepSource = options.keepSource || !originalOptions.decode || !originalOptions.checkTransparency; + } + }); + + textureNames.forEach(function(name) { + const texturePath = material[name]; + if (defined(texturePath)) { + loadMaterialTexture(material, name, sharedOptions[texturePath], mtlDirectory, texturePromiseMap, texturePromises, options); + } + }); } return readLines(mtlPath, parseLine) diff --git a/lib/loadTexture.js b/lib/loadTexture.js index d88fa36..768e5ff 100644 --- a/lib/loadTexture.js +++ b/lib/loadTexture.js @@ -19,6 +19,7 @@ module.exports = loadTexture; * @param {Object} [options] An object with the following properties: * @param {Boolean} [options.checkTransparency=false] Do a more exhaustive check for texture transparency by looking at the alpha channel of each pixel. * @param {Boolean} [options.decode=false] Whether to decode the texture. + * @param {Boolean} [options.keepSource=false] Whether to keep the source image contents in memory. * @returns {Promise} A promise resolving to a Texture object. * * @private @@ -27,6 +28,7 @@ function loadTexture(texturePath, options) { options = defaultValue(options, {}); options.checkTransparency = defaultValue(options.checkTransparency, false); options.decode = defaultValue(options.decode, false); + options.keepSource = defaultValue(options.keepSource, false); return fsExtra.readFile(texturePath) .then(function(source) { @@ -46,7 +48,10 @@ function loadTexture(texturePath, options) { } if (defined(decodePromise)) { - return decodePromise.thenReturn(texture); + return decodePromise + .then(function() { + return texture; + }); } return texture; @@ -109,7 +114,9 @@ function decodePng(texture, options) { texture.pixels = decodedResults.data; texture.width = decodedResults.width; texture.height = decodedResults.height; - texture.source = undefined; // Unload resources + if (!options.keepSource) { + texture.source = undefined; // Unload resources + } } }); } @@ -122,6 +129,8 @@ function decodeJpeg(texture, options) { texture.pixels = decodedResults.data; texture.width = decodedResults.width; texture.height = decodedResults.height; - texture.source = undefined; // Unload resources + if (!options.keepSource) { + texture.source = undefined; // Unload resources + } } } diff --git a/specs/data/box-shared-textures-2/box-shared-textures-2.mtl b/specs/data/box-shared-textures-2/box-shared-textures-2.mtl new file mode 100644 index 0000000..9b8063a --- /dev/null +++ b/specs/data/box-shared-textures-2/box-shared-textures-2.mtl @@ -0,0 +1,14 @@ +# Blender MTL File: 'box.blend' +# Material Count: 1 + +newmtl Material +Ns 96.078431 +Ka 0.000000 0.000000 0.000000 +Kd 0.640000 0.640000 0.640000 +Ks 0.500000 0.500000 0.500000 +Ke 0.000000 0.000000 0.000000 +Ni 1.000000 +d 1.000000 +illum 2 +map_Kd cesium.png +map_Ke cesium.png diff --git a/specs/data/box-diffuse-ambient-same/box-diffuse-ambient-same.obj b/specs/data/box-shared-textures-2/box-shared-textures-2.obj similarity index 96% rename from specs/data/box-diffuse-ambient-same/box-diffuse-ambient-same.obj rename to specs/data/box-shared-textures-2/box-shared-textures-2.obj index 5d52f28..68c9732 100644 --- a/specs/data/box-diffuse-ambient-same/box-diffuse-ambient-same.obj +++ b/specs/data/box-shared-textures-2/box-shared-textures-2.obj @@ -1,6 +1,6 @@ # Blender v2.78 (sub 0) OBJ File: 'box.blend' # www.blender.org -mtllib box-diffuse-ambient-same.mtl +mtllib box-shared-textures-2.mtl o Cube v -1.000000 -1.000000 1.000000 v -1.000000 1.000000 1.000000 diff --git a/specs/data/box-diffuse-ambient-same/cesium.png b/specs/data/box-shared-textures-2/cesium.png similarity index 100% rename from specs/data/box-diffuse-ambient-same/cesium.png rename to specs/data/box-shared-textures-2/cesium.png diff --git a/specs/data/box-diffuse-ambient-same/box-diffuse-ambient-same.mtl b/specs/data/box-shared-textures/box-shared-textures.mtl similarity index 93% rename from specs/data/box-diffuse-ambient-same/box-diffuse-ambient-same.mtl rename to specs/data/box-shared-textures/box-shared-textures.mtl index cb21081..f76d558 100644 --- a/specs/data/box-diffuse-ambient-same/box-diffuse-ambient-same.mtl +++ b/specs/data/box-shared-textures/box-shared-textures.mtl @@ -12,3 +12,4 @@ d 1.000000 illum 2 map_Kd cesium.png map_Ka cesium.png +map_Ks cesium.png diff --git a/specs/data/box-shared-textures/box-shared-textures.obj b/specs/data/box-shared-textures/box-shared-textures.obj new file mode 100644 index 0000000..ad7a6d4 --- /dev/null +++ b/specs/data/box-shared-textures/box-shared-textures.obj @@ -0,0 +1,46 @@ +# Blender v2.78 (sub 0) OBJ File: 'box.blend' +# www.blender.org +mtllib box-shared-textures.mtl +o Cube +v -1.000000 -1.000000 1.000000 +v -1.000000 1.000000 1.000000 +v -1.000000 -1.000000 -1.000000 +v -1.000000 1.000000 -1.000000 +v 1.000000 -1.000000 1.000000 +v 1.000000 1.000000 1.000000 +v 1.000000 -1.000000 -1.000000 +v 1.000000 1.000000 -1.000000 +vt 0.0000 0.0000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 0.0000 0.0000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 0.0000 0.0000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 0.0000 0.0000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 1.0000 +vt 1.0000 0.0000 +vt 1.0000 1.0000 +vt 0.0000 0.0000 +vt 0.0000 1.0000 +vn -1.0000 0.0000 0.0000 +vn 0.0000 0.0000 -1.0000 +vn 1.0000 0.0000 0.0000 +vn 0.0000 0.0000 1.0000 +vn 0.0000 -1.0000 0.0000 +vn 0.0000 1.0000 0.0000 +usemtl Material +s off +f 1/1/1 2/2/1 4/3/1 3/4/1 +f 3/5/2 4/6/2 8/7/2 7/8/2 +f 7/9/3 8/10/3 6/11/3 5/12/3 +f 5/13/4 6/14/4 2/15/4 1/16/4 +f 3/5/5 7/17/5 5/18/5 1/16/5 +f 8/19/6 4/6/6 2/15/6 6/20/6 diff --git a/specs/data/box-shared-textures/cesium.png b/specs/data/box-shared-textures/cesium.png new file mode 100644 index 0000000..3b8baee Binary files /dev/null and b/specs/data/box-shared-textures/cesium.png differ diff --git a/specs/lib/loadMtlSpec.js b/specs/lib/loadMtlSpec.js index 2af7f0a..567b045 100644 --- a/specs/lib/loadMtlSpec.js +++ b/specs/lib/loadMtlSpec.js @@ -15,7 +15,8 @@ const externalMaterialPath = 'specs/data/box-external-resources/box-external-res const resourcesInRootMaterialPath = 'specs/data/box-resources-in-root/box-resources-in-root.mtl'; const externalInRootMaterialPath = 'specs/data/box-external-resources-in-root/box-external-resources-in-root.mtl'; const transparentMaterialPath = 'specs/data/box-transparent/box-transparent.mtl'; -const diffuseAmbientSameMaterialPath = 'specs/data/box-diffuse-ambient-same/box-diffuse-ambient-same.mtl'; +const sharedTexturesMaterialPath = 'specs/data/box-shared-textures/box-shared-textures.mtl'; +const sharedTexturesMaterial2Path = 'specs/data/box-shared-textures-2/box-shared-textures-2.mtl'; const diffuseTexturePath = 'specs/data/box-textured/cesium.png'; const transparentDiffuseTexturePath = 'specs/data/box-complex-material/diffuse.png'; @@ -204,7 +205,7 @@ describe('loadMtl', () => { }); it('ambient texture is ignored if it is the same as the diffuse texture', async () => { - const materials = await loadMtl(diffuseAmbientSameMaterialPath, options); + const materials = await loadMtl(sharedTexturesMaterialPath, options); expect(materials.length).toBe(1); const material = materials[0]; const pbr = material.pbrMetallicRoughness; @@ -212,6 +213,27 @@ describe('loadMtl', () => { expect(pbr.occlusionTexture).toBeUndefined(); }); + it('texture referenced by specular is decoded', async () => { + const materials = await loadMtl(sharedTexturesMaterialPath, options); + expect(materials.length).toBe(1); + const material = materials[0]; + const pbr = material.pbrMetallicRoughness; + expect(pbr.baseColorTexture.pixels).toBeDefined(); + expect(pbr.baseColorTexture.source).toBeDefined(); + expect(pbr.metallicRoughnessTexture.pixels).toBeDefined(); + expect(pbr.metallicRoughnessTexture.source).toBeUndefined(); + }); + + it('texture referenced by diffuse and emission is not decoded', async() => { + const materials = await loadMtl(sharedTexturesMaterial2Path, options); + expect(materials.length).toBe(1); + const material = materials[0]; + const pbr = material.pbrMetallicRoughness; + expect(pbr.baseColorTexture).toBe(material.emissiveTexture); + expect(pbr.baseColorTexture.pixels).toBeUndefined(); + expect(pbr.baseColorTexture.source).toBeDefined(); + }); + describe('metallicRoughness', () => { it('creates default material', () => { const material = loadMtl._createMaterial(undefined, options);