This commit is contained in:
Sean Lilley 2017-05-04 17:58:13 -04:00
parent 44e9d5fa3b
commit c2af8f5098
14 changed files with 497 additions and 461 deletions

View File

@ -2,6 +2,13 @@
module.exports = Material; module.exports = Material;
/**
* A material definition which maps to the .mtl format.
*
* The default value for specularShininess varies depending on the material type, @see loadMtl.
*
* @private
*/
function Material() { function Material() {
this.name = ''; this.name = '';
this.ambientColor = [0.0, 0.0, 0.0, 1.0]; // Ka this.ambientColor = [0.0, 0.0, 0.0, 1.0]; // Ka

View File

@ -16,10 +16,10 @@ module.exports = createGltf;
* *
* @param {Object} objData Output of obj.js, containing an array of nodes containing geometry information, materials, and images. * @param {Object} objData Output of obj.js, containing an array of nodes containing geometry information, materials, and images.
* @param {Object} options An object with the following properties: * @param {Object} options An object with the following properties:
* @param {Boolean} [options.packOcclusion] Pack the occlusion texture in the red channel of metallic-roughness texture. * @param {Boolean} options.packOcclusion Pack the occlusion texture in the red channel of metallic-roughness texture.
* @param {Boolean} [options.metallicRoughness] The values in the mtl file are already metallic-roughness PBR values and no conversion step should be applied. Metallic is stored in the Ks and map_Ks slots and roughness is stored in the Ns and map_Ns slots. * @param {Boolean} options.metallicRoughness The values in the mtl file are already metallic-roughness PBR values and no conversion step should be applied. Metallic is stored in the Ks and map_Ks slots and roughness is stored in the Ns and map_Ns slots.
* @param {Boolean} [options.specularGlossiness] The values in the mtl file are already specular-glossiness PBR values and no conversion step should be applied. Specular is stored in the Ks and map_Ks slots and glossiness is stored in the Ns and map_Ns slots. The glTF will be saved with the KHR_materials_pbrSpecularGlossiness extension. * @param {Boolean} options.specularGlossiness The values in the mtl file are already specular-glossiness PBR values and no conversion step should be applied. Specular is stored in the Ks and map_Ks slots and glossiness is stored in the Ns and map_Ns slots. The glTF will be saved with the KHR_materials_pbrSpecularGlossiness extension.
* @param {Boolean} [options.materialsCommon] The glTF will be saved with the KHR_materials_common extension. * @param {Boolean} options.materialsCommon The glTF will be saved with the KHR_materials_common extension.
* @param {Boolean} options.logger A callback function for handling logged messages. Defaults to console.log. * @param {Boolean} options.logger A callback function for handling logged messages. Defaults to console.log.
* @returns {Object} A glTF asset. * @returns {Object} A glTF asset.
* *
@ -597,16 +597,17 @@ function convertTraditionalToMetallicRoughness(material) {
// Low specular intensity values should produce a rough material even if shininess is high. // Low specular intensity values should produce a rough material even if shininess is high.
if (specularIntensity < 0.1) { if (specularIntensity < 0.1) {
roughnessFactor *= specularIntensity; roughnessFactor *= (1.0 - specularIntensity);
} }
var metallicFactor = 0.0; var metallicFactor = 0.0;
material.specularTexture = undefined; // For now just ignore the specular texture
material.specularColor = [metallicFactor, metallicFactor, metallicFactor, 1.0]; material.specularColor = [metallicFactor, metallicFactor, metallicFactor, 1.0];
material.specularShiness = roughnessFactor; material.specularShininess = roughnessFactor;
} }
function createMaterialsCommonMaterial(gltf, images, material, hasNormals, options) { function createMaterialsCommonMaterial(gltf, images, material, hasNormals) {
var materialName = material.name; var materialName = material.name;
var ambientImage = getImage(images, material.ambientTexture); var ambientImage = getImage(images, material.ambientTexture);
@ -682,7 +683,7 @@ function addMaterial(gltf, images, material, hasNormals, options) {
} else if (options.metallicRoughness) { } else if (options.metallicRoughness) {
gltfMaterial = createMetallicRoughnessMaterial(gltf, images, material, options); gltfMaterial = createMetallicRoughnessMaterial(gltf, images, material, options);
} else if (options.materialsCommon) { } else if (options.materialsCommon) {
gltfMaterial = createMaterialsCommonMaterial(gltf, images, material, hasNormals, options); gltfMaterial = createMaterialsCommonMaterial(gltf, images, material, hasNormals);
} else { } else {
convertTraditionalToMetallicRoughness(material); convertTraditionalToMetallicRoughness(material);
gltfMaterial = createMetallicRoughnessMaterial(gltf, images, material, options); gltfMaterial = createMetallicRoughnessMaterial(gltf, images, material, options);
@ -693,26 +694,16 @@ function addMaterial(gltf, images, material, hasNormals, options) {
return materialIndex; return materialIndex;
} }
function getMaterialIndex(gltf, materialName) {
var materials = gltf.materials;
var length = materials.length;
for (var i = 0; i < length; ++i) {
if (materials[i].name === materialName) {
return i;
}
}
return undefined;
}
function getMaterial(gltf, materials, images, materialName, hasNormals, options) { function getMaterial(gltf, materials, images, materialName, hasNormals, options) {
if (!defined(materialName)) { if (!defined(materialName)) {
// Create a default material if the primitive does not specify one // Create a default material if the primitive does not specify one
materialName = 'default'; materialName = 'default';
} }
var i;
var material; var material;
var materialsLength = materials.length; var materialsLength = materials.length;
for (var i = 0; i < materialsLength; ++i) { for (i = 0; i < materialsLength; ++i) {
if (materials[i].name === materialName) { if (materials[i].name === materialName) {
material = materials[i]; material = materials[i];
} }
@ -723,7 +714,14 @@ function getMaterial(gltf, materials, images, materialName, hasNormals, options)
material.name = materialName; material.name = materialName;
} }
var materialIndex = getMaterialIndex(gltf, materialName); var materialIndex;
materialsLength = gltf.materials.length;
for (i = 0; i < materialsLength; ++i) {
if (gltf.materials[i].name === materialName) {
materialIndex = i;
break;
}
}
if (!defined(materialIndex)) { if (!defined(materialIndex)) {
materialIndex = addMaterial(gltf, images, material, hasNormals, options); materialIndex = addMaterial(gltf, images, material, hasNormals, options);
@ -732,13 +730,14 @@ function getMaterial(gltf, materials, images, materialName, hasNormals, options)
return materialIndex; return materialIndex;
} }
function addVertexAttribute(gltf, bufferState, array, components) { function addVertexAttribute(gltf, bufferState, array, components, name) {
var buffer = array.toFloatBuffer(); var buffer = array.toFloatBuffer();
var count = array.length / components; var count = array.length / components;
var minMax = array.getMinMax(components); var minMax = array.getMinMax(components);
var type = (components === 3 ? 'VEC3' : 'VEC2'); var type = (components === 3 ? 'VEC3' : 'VEC2');
var accessor = { var accessor = {
name : name,
bufferView : bufferState.vertexBufferViewIndex, bufferView : bufferState.vertexBufferViewIndex,
byteOffset : bufferState.vertexBufferByteOffset, byteOffset : bufferState.vertexBufferByteOffset,
componentType : WebGLConstants.FLOAT, componentType : WebGLConstants.FLOAT,
@ -756,13 +755,14 @@ function addVertexAttribute(gltf, bufferState, array, components) {
return accessorIndex; return accessorIndex;
} }
function addIndexArray(gltf, bufferState, array, uint32Indices) { function addIndexArray(gltf, bufferState, array, uint32Indices, name) {
var buffer = uint32Indices ? array.toUint32Buffer() : array.toUint16Buffer(); var buffer = uint32Indices ? array.toUint32Buffer() : array.toUint16Buffer();
var componentType = uint32Indices ? WebGLConstants.UNSIGNED_INT : WebGLConstants.UNSIGNED_SHORT; var componentType = uint32Indices ? WebGLConstants.UNSIGNED_INT : WebGLConstants.UNSIGNED_SHORT;
var count = array.length; var count = array.length;
var minMax = array.getMinMax(1); var minMax = array.getMinMax(1);
var accessor = { var accessor = {
name : name,
bufferView : bufferState.indexBufferViewIndex, bufferView : bufferState.indexBufferViewIndex,
byteOffset : bufferState.indexBufferByteOffset, byteOffset : bufferState.indexBufferByteOffset,
componentType : componentType, componentType : componentType,
@ -803,13 +803,13 @@ function addMesh(gltf, materials, images, bufferState, uint32Indices, mesh, opti
var attributes = {}; var attributes = {};
if (hasPositions) { if (hasPositions) {
attributes.POSITION = addVertexAttribute(gltf, bufferState, mesh.positions, 3); attributes.POSITION = addVertexAttribute(gltf, bufferState, mesh.positions, 3, mesh.name + '_positions');
} }
if (hasNormals) { if (hasNormals) {
attributes.NORMAL = addVertexAttribute(gltf, bufferState, mesh.normals, 3); attributes.NORMAL = addVertexAttribute(gltf, bufferState, mesh.normals, 3, mesh.name + '_normals');
} }
if (hasUVs) { if (hasUVs) {
attributes.TEXCOORD_0 = addVertexAttribute(gltf, bufferState, mesh.uvs, 2); attributes.TEXCOORD_0 = addVertexAttribute(gltf, bufferState, mesh.uvs, 2, mesh.name + '_texcoords');
} }
// Unload resources // Unload resources
@ -822,7 +822,7 @@ function addMesh(gltf, materials, images, bufferState, uint32Indices, mesh, opti
var primitivesLength = primitives.length; var primitivesLength = primitives.length;
for (var i = 0; i < primitivesLength; ++i) { for (var i = 0; i < primitivesLength; ++i) {
var primitive = primitives[i]; var primitive = primitives[i];
var indexAccessorIndex = addIndexArray(gltf, bufferState, primitive.indices, uint32Indices); var indexAccessorIndex = addIndexArray(gltf, bufferState, primitive.indices, uint32Indices, mesh.name + '_' + i + '_indices');
primitive.indices = undefined; // Unload resources primitive.indices = undefined; // Unload resources
var materialIndex = getMaterial(gltf, materials, images, primitive.material, hasNormals, options); var materialIndex = getMaterial(gltf, materials, images, primitive.material, hasNormals, options);

View File

@ -9,23 +9,31 @@ module.exports = loadMtl;
* Parse an mtl file. * Parse an mtl file.
* *
* @param {String} mtlPath Path to the mtl file. * @param {String} mtlPath Path to the mtl file.
* @param {Object} options An object with the following properties:
* @param {Boolean} options.metallicRoughness The values in the mtl file are already metallic-roughness PBR values and no conversion step should be applied. Metallic is stored in the Ks and map_Ks slots and roughness is stored in the Ns and map_Ns slots.
* @returns {Promise} A promise resolving to the materials. * @returns {Promise} A promise resolving to the materials.
* *
* @private * @private
*/ */
function loadMtl(mtlPath) { function loadMtl(mtlPath, options) {
var material; var material;
var values; var values;
var value; var value;
var mtlDirectory = path.dirname(mtlPath); var mtlDirectory = path.dirname(mtlPath);
var materials = []; var materials = [];
var defaultSpecularShininess = 0.0;
if (options.metallicRoughness) {
defaultSpecularShininess = 1.0; // Fully rough
}
function parseLine(line) { function parseLine(line) {
line = line.trim(); line = line.trim();
if (/^newmtl /i.test(line)) { if (/^newmtl /i.test(line)) {
var name = line.substring(7).trim(); var name = line.substring(7).trim();
material = new Material(); material = new Material();
material.name = name; material.name = name;
material.specularShininess = defaultSpecularShininess;
materials.push(material); materials.push(material);
} else if (/^Ka /i.test(line)) { } else if (/^Ka /i.test(line)) {
values = line.substring(3).trim().split(' '); values = line.substring(3).trim().split(' ');

View File

@ -337,7 +337,7 @@ function loadMaterials(mtlPaths, objPath, options) {
logger('Could not read mtl file at ' + mtlPath + ' because it is outside of the obj directory and the secure flag is true. Using default material instead.'); logger('Could not read mtl file at ' + mtlPath + ' because it is outside of the obj directory and the secure flag is true. Using default material instead.');
return; return;
} }
return loadMtl(mtlPath) return loadMtl(mtlPath, options)
.then(function(materialsInMtl) { .then(function(materialsInMtl) {
materials = materials.concat(materialsInMtl); materials = materials.concat(materialsInMtl);
}) })

View File

@ -100,7 +100,7 @@ function obj2gltf(objPath, gltfPath, options) {
} }
if (metallicRoughness + specularGlossiness + materialsCommon > 1) { if (metallicRoughness + specularGlossiness + materialsCommon > 1) {
throw new DeveloperError('Only one material type may be set from [--metallicRoughness, --specularGlossiness, --materialsCommon].'); return Promise.reject(new RuntimeError('Only one material type may be set from [--metallicRoughness, --specularGlossiness, --materialsCommon].'));
} }
gltfPath = path.join(path.dirname(gltfPath), modelName + extension); gltfPath = path.join(path.dirname(gltfPath), modelName + extension);

View File

@ -7,6 +7,7 @@ var Promise = require('bluebird');
var fsExtraOutputFile = Promise.promisify(fsExtra.outputFile); var fsExtraOutputFile = Promise.promisify(fsExtra.outputFile);
var defined = Cesium.defined;
var RuntimeError = Cesium.RuntimeError; var RuntimeError = Cesium.RuntimeError;
module.exports = writeUris; module.exports = writeUris;
@ -86,16 +87,18 @@ function deleteExtras(gltf) {
} }
} }
function cleanup(gltf) { function removeEmpty(json) {
// Remove empty arrays from top-level items Object.keys(json).forEach(function(key) {
for (var key in gltf) { if (!defined(json[key]) || (Array.isArray(json[key]) && json[key].length === 0)) {
if (gltf.hasOwnProperty(key)) { delete json[key]; // Delete values that are undefined or []
var property = gltf[key]; } else if (typeof json[key] === 'object') {
if (Array.isArray(property) && property.length === 0) { removeEmpty(json[key]);
delete gltf[key];
}
} }
} });
}
function cleanup(gltf) {
removeEmpty(gltf);
} }
function writeSeparateBuffer(gltf, resourcesDirectory, name) { function writeSeparateBuffer(gltf, resourcesDirectory, name) {

View File

@ -1,9 +1,9 @@
{ {
"accessors": { "accessors": [
"accessor_0": { {
"bufferView": "bufferView_vertex", "name": "Blue_positions",
"bufferView": 0,
"byteOffset": 0, "byteOffset": 0,
"byteStride": 0,
"componentType": 5126, "componentType": 5126,
"count": 24, "count": 24,
"min": [ "min": [
@ -18,10 +18,10 @@
], ],
"type": "VEC3" "type": "VEC3"
}, },
"accessor_1": { {
"bufferView": "bufferView_vertex", "name": "Blue_normals",
"bufferView": 0,
"byteOffset": 288, "byteOffset": 288,
"byteStride": 0,
"componentType": 5126, "componentType": 5126,
"count": 24, "count": 24,
"min": [ "min": [
@ -36,10 +36,10 @@
], ],
"type": "VEC3" "type": "VEC3"
}, },
"accessor_2": { {
"bufferView": "bufferView_vertex", "name": "Blue_texcoords",
"bufferView": 0,
"byteOffset": 576, "byteOffset": 576,
"byteStride": 0,
"componentType": 5126, "componentType": 5126,
"count": 24, "count": 24,
"min": [ "min": [
@ -52,10 +52,10 @@
], ],
"type": "VEC2" "type": "VEC2"
}, },
"accessor_3": { {
"bufferView": "bufferView_index", "name": "Blue_0_indices",
"bufferView": 1,
"byteOffset": 0, "byteOffset": 0,
"byteStride": 0,
"componentType": 5123, "componentType": 5123,
"count": 18, "count": 18,
"min": [ "min": [
@ -66,10 +66,10 @@
], ],
"type": "SCALAR" "type": "SCALAR"
}, },
"accessor_4": { {
"bufferView": "bufferView_index", "name": "Blue_1_indices",
"bufferView": 1,
"byteOffset": 36, "byteOffset": 36,
"byteStride": 0,
"componentType": 5123, "componentType": 5123,
"count": 18, "count": 18,
"min": [ "min": [
@ -80,10 +80,10 @@
], ],
"type": "SCALAR" "type": "SCALAR"
}, },
"accessor_5": { {
"bufferView": "bufferView_vertex", "name": "Green_positions",
"bufferView": 0,
"byteOffset": 768, "byteOffset": 768,
"byteStride": 0,
"componentType": 5126, "componentType": 5126,
"count": 24, "count": 24,
"min": [ "min": [
@ -98,10 +98,10 @@
], ],
"type": "VEC3" "type": "VEC3"
}, },
"accessor_6": { {
"bufferView": "bufferView_vertex", "name": "Green_normals",
"bufferView": 0,
"byteOffset": 1056, "byteOffset": 1056,
"byteStride": 0,
"componentType": 5126, "componentType": 5126,
"count": 24, "count": 24,
"min": [ "min": [
@ -116,10 +116,10 @@
], ],
"type": "VEC3" "type": "VEC3"
}, },
"accessor_7": { {
"bufferView": "bufferView_vertex", "name": "Green_texcoords",
"bufferView": 0,
"byteOffset": 1344, "byteOffset": 1344,
"byteStride": 0,
"componentType": 5126, "componentType": 5126,
"count": 24, "count": 24,
"min": [ "min": [
@ -132,10 +132,10 @@
], ],
"type": "VEC2" "type": "VEC2"
}, },
"accessor_8": { {
"bufferView": "bufferView_index", "name": "Green_0_indices",
"bufferView": 1,
"byteOffset": 72, "byteOffset": 72,
"byteStride": 0,
"componentType": 5123, "componentType": 5123,
"count": 18, "count": 18,
"min": [ "min": [
@ -146,10 +146,10 @@
], ],
"type": "SCALAR" "type": "SCALAR"
}, },
"accessor_9": { {
"bufferView": "bufferView_index", "name": "Green_1_indices",
"bufferView": 1,
"byteOffset": 108, "byteOffset": 108,
"byteStride": 0,
"componentType": 5123, "componentType": 5123,
"count": 18, "count": 18,
"min": [ "min": [
@ -160,10 +160,10 @@
], ],
"type": "SCALAR" "type": "SCALAR"
}, },
"accessor_10": { {
"bufferView": "bufferView_vertex", "name": "Red_positions",
"bufferView": 0,
"byteOffset": 1536, "byteOffset": 1536,
"byteStride": 0,
"componentType": 5126, "componentType": 5126,
"count": 24, "count": 24,
"min": [ "min": [
@ -178,10 +178,10 @@
], ],
"type": "VEC3" "type": "VEC3"
}, },
"accessor_11": { {
"bufferView": "bufferView_vertex", "name": "Red_normals",
"bufferView": 0,
"byteOffset": 1824, "byteOffset": 1824,
"byteStride": 0,
"componentType": 5126, "componentType": 5126,
"count": 24, "count": 24,
"min": [ "min": [
@ -196,10 +196,10 @@
], ],
"type": "VEC3" "type": "VEC3"
}, },
"accessor_12": { {
"bufferView": "bufferView_vertex", "name": "Red_texcoords",
"bufferView": 0,
"byteOffset": 2112, "byteOffset": 2112,
"byteStride": 0,
"componentType": 5126, "componentType": 5126,
"count": 24, "count": 24,
"min": [ "min": [
@ -212,10 +212,10 @@
], ],
"type": "VEC2" "type": "VEC2"
}, },
"accessor_13": { {
"bufferView": "bufferView_index", "name": "Red_0_indices",
"bufferView": 1,
"byteOffset": 144, "byteOffset": 144,
"byteStride": 0,
"componentType": 5123, "componentType": 5123,
"count": 18, "count": 18,
"min": [ "min": [
@ -226,10 +226,10 @@
], ],
"type": "SCALAR" "type": "SCALAR"
}, },
"accessor_14": { {
"bufferView": "bufferView_index", "name": "Red_1_indices",
"bufferView": 1,
"byteOffset": 180, "byteOffset": 180,
"byteStride": 0,
"componentType": 5123, "componentType": 5123,
"count": 18, "count": 18,
"min": [ "min": [
@ -240,253 +240,201 @@
], ],
"type": "SCALAR" "type": "SCALAR"
} }
}, ],
"asset": { "asset": {
"generator": "obj2gltf", "generator": "obj2gltf",
"profile": { "version": "2.0"
"api": "WebGL",
"version": "1.0"
},
"version": "1.0"
}, },
"buffers": { "buffers": [
"buffer": { {
"name": "buffer",
"byteLength": 2520, "byteLength": 2520,
"uri": "data:application/octet-stream;base64,AACAvwAAgL8AAIDAAACAvwAAgD8AAIDAAACAvwAAgD8AAMDAAACAvwAAgL8AAMDAAACAvwAAgL8AAMDAAACAvwAAgD8AAMDAAACAPwAAgD8AAMDAAACAPwAAgL8AAMDAAACAPwAAgL8AAMDAAACAPwAAgD8AAMDAAACAPwAAgD8AAIDAAACAPwAAgL8AAIDAAACAPwAAgL8AAIDAAACAPwAAgD8AAIDAAACAvwAAgD8AAIDAAACAvwAAgL8AAIDAAACAvwAAgL8AAMDAAACAPwAAgL8AAMDAAACAPwAAgL8AAIDAAACAvwAAgL8AAIDAAACAPwAAgD8AAMDAAACAvwAAgD8AAMDAAACAvwAAgD8AAIDAAACAPwAAgD8AAIDAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAIA/AACAPwAAgD8AAAAAAAAAAAAAAAAAAAAAAACAPwAAgD8AAIA/AACAPwAAAAAAAAAAAAAAAAAAAAAAAIA/AACAPwAAgD8AAIA/AAAAAAAAAAAAAAAAAAAAAAAAgD8AAIA/AACAPwAAgD8AAAAAAAAAAAAAAAAAAAAAAACAPwAAgD8AAIA/AACAPwAAAAAAAAAAAAAAAAAAAAAAAIA/AACAPwAAgD8AAIA/AAAAAAAAAAAAAAAAAACAQAAAgL8AAIA/AACAQAAAgD8AAIA/AACAQAAAgD8AAIC/AACAQAAAgL8AAIC/AACAQAAAgL8AAIC/AACAQAAAgD8AAIC/AADAQAAAgD8AAIC/AADAQAAAgL8AAIC/AADAQAAAgL8AAIC/AADAQAAAgD8AAIC/AADAQAAAgD8AAIA/AADAQAAAgL8AAIA/AADAQAAAgL8AAIA/AADAQAAAgD8AAIA/AACAQAAAgD8AAIA/AACAQAAAgL8AAIA/AACAQAAAgL8AAIC/AADAQAAAgL8AAIC/AADAQAAAgL8AAIA/AACAQAAAgL8AAIA/AADAQAAAgD8AAIC/AACAQAAAgD8AAIC/AACAQAAAgD8AAIA/AADAQAAAgD8AAIA/AACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAIA/AACAPwAAgD8AAAAAAAAAAAAAAAAAAAAAAACAPwAAgD8AAIA/AACAPwAAAAAAAAAAAAAAAAAAAAAAAIA/AACAPwAAgD8AAIA/AAAAAAAAAAAAAAAAAAAAAAAAgD8AAIA/AACAPwAAgD8AAAAAAAAAAAAAAAAAAAAAAACAPwAAgD8AAIA/AACAPwAAAAAAAAAAAAAAAAAAAAAAAIA/AACAPwAAgD8AAIA/AAAAAAAAAAAAAAAAAACAvwAAgL8AAIA/AACAvwAAgD8AAIA/AACAvwAAgD8AAIC/AACAvwAAgL8AAIC/AACAvwAAgL8AAIC/AACAvwAAgD8AAIC/AACAPwAAgD8AAIC/AACAPwAAgL8AAIC/AACAPwAAgL8AAIC/AACAPwAAgD8AAIC/AACAPwAAgD8AAIA/AACAPwAAgL8AAIA/AACAPwAAgL8AAIA/AACAPwAAgD8AAIA/AACAvwAAgD8AAIA/AACAvwAAgL8AAIA/AACAvwAAgL8AAIC/AACAPwAAgL8AAIC/AACAPwAAgL8AAIA/AACAvwAAgL8AAIA/AACAPwAAgD8AAIC/AACAvwAAgD8AAIC/AACAvwAAgD8AAIA/AACAPwAAgD8AAIA/AACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAIA/AACAPwAAgD8AAAAAAAAAAAAAAAAAAAAAAACAPwAAgD8AAIA/AACAPwAAAAAAAAAAAAAAAAAAAAAAAIA/AACAPwAAgD8AAIA/AAAAAAAAAAAAAAAAAAAAAAAAgD8AAIA/AACAPwAAgD8AAAAAAAAAAAAAAAAAAAAAAACAPwAAgD8AAIA/AACAPwAAAAAAAAAAAAAAAAAAAAAAAIA/AACAPwAAgD8AAIA/AAAAAAAAAAAAAAAAAAABAAIAAAACAAMABAAFAAYABAAGAAcACAAJAAoACAAKAAsADAANAA4ADAAOAA8AEAARABIAEAASABMAFAAVABYAFAAWABcAAAABAAIAAAACAAMABAAFAAYABAAGAAcACAAJAAoACAAKAAsADAANAA4ADAAOAA8AEAARABIAEAASABMAFAAVABYAFAAWABcAAAABAAIAAAACAAMABAAFAAYABAAGAAcACAAJAAoACAAKAAsADAANAA4ADAAOAA8AEAARABIAEAASABMAFAAVABYAFAAWABcA" "uri": "data:application/octet-stream;base64,AACAvwAAgL8AAIDAAACAvwAAgD8AAIDAAACAvwAAgD8AAMDAAACAvwAAgL8AAMDAAACAvwAAgL8AAMDAAACAvwAAgD8AAMDAAACAPwAAgD8AAMDAAACAPwAAgL8AAMDAAACAPwAAgL8AAMDAAACAPwAAgD8AAMDAAACAPwAAgD8AAIDAAACAPwAAgL8AAIDAAACAPwAAgL8AAIDAAACAPwAAgD8AAIDAAACAvwAAgD8AAIDAAACAvwAAgL8AAIDAAACAvwAAgL8AAMDAAACAPwAAgL8AAMDAAACAPwAAgL8AAIDAAACAvwAAgL8AAIDAAACAPwAAgD8AAMDAAACAvwAAgD8AAMDAAACAvwAAgD8AAIDAAACAPwAAgD8AAIDAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAIA/AACAPwAAgD8AAAAAAAAAAAAAAAAAAAAAAACAPwAAgD8AAIA/AACAPwAAAAAAAAAAAAAAAAAAAAAAAIA/AACAPwAAgD8AAIA/AAAAAAAAAAAAAAAAAAAAAAAAgD8AAIA/AACAPwAAgD8AAAAAAAAAAAAAAAAAAAAAAACAPwAAgD8AAIA/AACAPwAAAAAAAAAAAAAAAAAAAAAAAIA/AACAPwAAgD8AAIA/AAAAAAAAAAAAAAAAAACAQAAAgL8AAIA/AACAQAAAgD8AAIA/AACAQAAAgD8AAIC/AACAQAAAgL8AAIC/AACAQAAAgL8AAIC/AACAQAAAgD8AAIC/AADAQAAAgD8AAIC/AADAQAAAgL8AAIC/AADAQAAAgL8AAIC/AADAQAAAgD8AAIC/AADAQAAAgD8AAIA/AADAQAAAgL8AAIA/AADAQAAAgL8AAIA/AADAQAAAgD8AAIA/AACAQAAAgD8AAIA/AACAQAAAgL8AAIA/AACAQAAAgL8AAIC/AADAQAAAgL8AAIC/AADAQAAAgL8AAIA/AACAQAAAgL8AAIA/AADAQAAAgD8AAIC/AACAQAAAgD8AAIC/AACAQAAAgD8AAIA/AADAQAAAgD8AAIA/AACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAIA/AACAPwAAgD8AAAAAAAAAAAAAAAAAAAAAAACAPwAAgD8AAIA/AACAPwAAAAAAAAAAAAAAAAAAAAAAAIA/AACAPwAAgD8AAIA/AAAAAAAAAAAAAAAAAAAAAAAAgD8AAIA/AACAPwAAgD8AAAAAAAAAAAAAAAAAAAAAAACAPwAAgD8AAIA/AACAPwAAAAAAAAAAAAAAAAAAAAAAAIA/AACAPwAAgD8AAIA/AAAAAAAAAAAAAAAAAACAvwAAgL8AAIA/AACAvwAAgD8AAIA/AACAvwAAgD8AAIC/AACAvwAAgL8AAIC/AACAvwAAgL8AAIC/AACAvwAAgD8AAIC/AACAPwAAgD8AAIC/AACAPwAAgL8AAIC/AACAPwAAgL8AAIC/AACAPwAAgD8AAIC/AACAPwAAgD8AAIA/AACAPwAAgL8AAIA/AACAPwAAgL8AAIA/AACAPwAAgD8AAIA/AACAvwAAgD8AAIA/AACAvwAAgL8AAIA/AACAvwAAgL8AAIC/AACAPwAAgL8AAIC/AACAPwAAgL8AAIA/AACAvwAAgL8AAIA/AACAPwAAgD8AAIC/AACAvwAAgD8AAIC/AACAvwAAgD8AAIA/AACAPwAAgD8AAIA/AACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAIA/AACAPwAAgD8AAAAAAAAAAAAAAAAAAAAAAACAPwAAgD8AAIA/AACAPwAAAAAAAAAAAAAAAAAAAAAAAIA/AACAPwAAgD8AAIA/AAAAAAAAAAAAAAAAAAAAAAAAgD8AAIA/AACAPwAAgD8AAAAAAAAAAAAAAAAAAAAAAACAPwAAgD8AAIA/AACAPwAAAAAAAAAAAAAAAAAAAAAAAIA/AACAPwAAgD8AAIA/AAAAAAAAAAAAAAAAAAABAAIAAAACAAMABAAFAAYABAAGAAcACAAJAAoACAAKAAsADAANAA4ADAAOAA8AEAARABIAEAASABMAFAAVABYAFAAWABcAAAABAAIAAAACAAMABAAFAAYABAAGAAcACAAJAAoACAAKAAsADAANAA4ADAAOAA8AEAARABIAEAASABMAFAAVABYAFAAWABcAAAABAAIAAAACAAMABAAFAAYABAAGAAcACAAJAAoACAAKAAsADAANAA4ADAAOAA8AEAARABIAEAASABMAFAAVABYAFAAWABcA"
} }
}, ],
"bufferViews": { "bufferViews": [
"bufferView_vertex": { {
"buffer": "buffer", "name": "bufferView_vertex",
"buffer": 0,
"byteLength": 2304, "byteLength": 2304,
"byteOffset": 0, "byteOffset": 0,
"target": 34962 "target": 34962
}, },
"bufferView_index": { {
"buffer": "buffer", "name": "bufferView_index",
"buffer": 0,
"byteLength": 216, "byteLength": 216,
"byteOffset": 2304, "byteOffset": 2304,
"target": 34963 "target": 34963
} }
},
"extensionsUsed": [
"KHR_materials_common"
], ],
"images": {}, "materials": [
"materials": { {
"Blue": { "name": "Blue",
"extensions": { "pbrMetallicRoughness": {
"KHR_materials_common": { "baseColorFactor": [
"technique": "PHONG", 0,
"transparent": false, 0,
"doubleSided": false, 0.64,
"values": { 1
"ambient": [ ],
0, "metallicFactor": 0,
0, "roughnessFactor": 0.903921569
0, },
1 "emissiveFactor": [
], 0,
"diffuse": [ 0,
0, 0
0, ],
0.64, "alphaMode": "OPAQUE",
1 "doubleSided": false
],
"emission": [
0,
0,
0,
1
],
"specular": [
0.5,
0.5,
0.5,
1
],
"shininess": 96.078431,
"transparency": 1,
"transparent": false,
"doubleSided": false
}
}
}
}, },
"Green": { {
"extensions": { "name": "Green",
"KHR_materials_common": { "pbrMetallicRoughness": {
"technique": "PHONG", "baseColorFactor": [
"transparent": false, 0,
"doubleSided": false, 0.64,
"values": { 0,
"ambient": [ 1
0, ],
0, "metallicFactor": 0,
0, "roughnessFactor": 0.903921569
1 },
], "emissiveFactor": [
"diffuse": [ 0,
0, 0,
0.64, 0
0, ],
1 "alphaMode": "OPAQUE",
], "doubleSided": false
"emission": [
0,
0,
0,
1
],
"specular": [
0.5,
0.5,
0.5,
1
],
"shininess": 96.078431,
"transparency": 1,
"transparent": false,
"doubleSided": false
}
}
}
}, },
"Red": { {
"extensions": { "name": "Red",
"KHR_materials_common": { "pbrMetallicRoughness": {
"technique": "PHONG", "baseColorFactor": [
"transparent": false, 0.64,
"doubleSided": false, 0,
"values": { 0,
"ambient": [ 1
0, ],
0, "metallicFactor": 0,
0, "roughnessFactor": 0.903921569
1 },
], "emissiveFactor": [
"diffuse": [ 0,
0.64, 0,
0, 0
0, ],
1 "alphaMode": "OPAQUE",
], "doubleSided": false
"emission": [
0,
0,
0,
1
],
"specular": [
0.5,
0.5,
0.5,
1
],
"shininess": 96.078431,
"transparency": 1,
"transparent": false,
"doubleSided": false
}
}
}
} }
}, ],
"meshes": { "meshes": [
"CubeBlue_CubeBlue_Blue": { {
"name": "CubeBlue_CubeBlue_Blue", "name": "Blue",
"primitives": [ "primitives": [
{ {
"attributes": { "attributes": {
"POSITION": "accessor_0", "POSITION": 0,
"NORMAL": "accessor_1", "NORMAL": 1,
"TEXCOORD_0": "accessor_2" "TEXCOORD_0": 2
}, },
"indices": "accessor_3", "indices": 3,
"material": "Blue", "material": 0,
"mode": 4 "mode": 4
}, },
{ {
"attributes": { "attributes": {
"POSITION": "accessor_0", "POSITION": 0,
"NORMAL": "accessor_1", "NORMAL": 1,
"TEXCOORD_0": "accessor_2" "TEXCOORD_0": 2
}, },
"indices": "accessor_4", "indices": 4,
"material": "Green", "material": 1,
"mode": 4 "mode": 4
} }
] ]
}, },
"CubeGreen_CubeGreen_Green": { {
"name": "CubeGreen_CubeGreen_Green", "name": "Green",
"primitives": [ "primitives": [
{ {
"attributes": { "attributes": {
"POSITION": "accessor_5", "POSITION": 5,
"NORMAL": "accessor_6", "NORMAL": 6,
"TEXCOORD_0": "accessor_7" "TEXCOORD_0": 7
}, },
"indices": "accessor_8", "indices": 8,
"material": "Green", "material": 1,
"mode": 4 "mode": 4
}, },
{ {
"attributes": { "attributes": {
"POSITION": "accessor_5", "POSITION": 5,
"NORMAL": "accessor_6", "NORMAL": 6,
"TEXCOORD_0": "accessor_7" "TEXCOORD_0": 7
}, },
"indices": "accessor_9", "indices": 9,
"material": "Red", "material": 2,
"mode": 4 "mode": 4
} }
] ]
}, },
"CubeRed_CubeRed_Red": { {
"name": "CubeRed_CubeRed_Red", "name": "Red",
"primitives": [ "primitives": [
{ {
"attributes": { "attributes": {
"POSITION": "accessor_10", "POSITION": 10,
"NORMAL": "accessor_11", "NORMAL": 11,
"TEXCOORD_0": "accessor_12" "TEXCOORD_0": 12
}, },
"indices": "accessor_13", "indices": 13,
"material": "Red", "material": 2,
"mode": 4 "mode": 4
}, },
{ {
"attributes": { "attributes": {
"POSITION": "accessor_10", "POSITION": 10,
"NORMAL": "accessor_11", "NORMAL": 11,
"TEXCOORD_0": "accessor_12" "TEXCOORD_0": 12
}, },
"indices": "accessor_14", "indices": 14,
"material": "Blue", "material": 0,
"mode": 4 "mode": 4
} }
] ]
} }
}, ],
"nodes": { "nodes": [
"Cube": { {
"name": "Cube", "name": "Cube",
"meshes": [ "children": [
"CubeBlue_CubeBlue_Blue", 1,
"CubeGreen_CubeGreen_Green", 2,
"CubeRed_CubeRed_Red" 3
] ]
},
{
"name": "Blue",
"mesh": 0
},
{
"name": "Green",
"mesh": 1
},
{
"name": "Red",
"mesh": 2
} }
}, ],
"samplers": {}, "scene": 0,
"scene": "scene", "scenes": [
"scenes": { {
"scene": {
"nodes": [ "nodes": [
"Cube" 0
] ]
} }
}, ]
"textures": {}
} }

View File

@ -36,7 +36,7 @@ vn 1.0000 0.0000 0.0000
vn 0.0000 0.0000 1.0000 vn 0.0000 0.0000 1.0000
vn 0.0000 -1.0000 0.0000 vn 0.0000 -1.0000 0.0000
vn 0.0000 1.0000 0.0000 vn 0.0000 1.0000 0.0000
g CubeBlue_CubeBlue_Blue g Blue
usemtl Blue usemtl Blue
f 1/1/1 2/2/1 4/3/1 3/4/1 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 3/5/2 4/6/2 8/7/2 7/8/2
@ -79,7 +79,7 @@ vn 1.0000 0.0000 0.0000
vn 0.0000 0.0000 1.0000 vn 0.0000 0.0000 1.0000
vn 0.0000 -1.0000 0.0000 vn 0.0000 -1.0000 0.0000
vn 0.0000 1.0000 0.0000 vn 0.0000 1.0000 0.0000
g CubeGreen_CubeGreen_Green g Green
usemtl Green usemtl Green
f 9/21/7 10/22/7 12/23/7 11/24/7 f 9/21/7 10/22/7 12/23/7 11/24/7
f 11/25/8 12/26/8 16/27/8 15/28/8 f 11/25/8 12/26/8 16/27/8 15/28/8
@ -122,7 +122,7 @@ vn 1.0000 0.0000 0.0000
vn 0.0000 0.0000 1.0000 vn 0.0000 0.0000 1.0000
vn 0.0000 -1.0000 0.0000 vn 0.0000 -1.0000 0.0000
vn 0.0000 1.0000 0.0000 vn 0.0000 1.0000 0.0000
g CubeRed_CubeRed_Red g Red
usemtl Red usemtl Red
f 17/41/13 18/42/13 20/43/13 19/44/13 f 17/41/13 18/42/13 20/43/13 19/44/13
f 19/45/14 20/46/14 24/47/14 23/48/14 f 19/45/14 20/46/14 24/47/14 23/48/14

View File

@ -1,9 +1,9 @@
{ {
"accessors": { "accessors": [
"accessor_0": { {
"bufferView": "bufferView_vertex", "name": "Cube-Mesh_positions",
"bufferView": 0,
"byteOffset": 0, "byteOffset": 0,
"byteStride": 0,
"componentType": 5126, "componentType": 5126,
"count": 24, "count": 24,
"min": [ "min": [
@ -18,10 +18,10 @@
], ],
"type": "VEC3" "type": "VEC3"
}, },
"accessor_1": { {
"bufferView": "bufferView_vertex", "name": "Cube-Mesh_normals",
"bufferView": 0,
"byteOffset": 288, "byteOffset": 288,
"byteStride": 0,
"componentType": 5126, "componentType": 5126,
"count": 24, "count": 24,
"min": [ "min": [
@ -36,10 +36,10 @@
], ],
"type": "VEC3" "type": "VEC3"
}, },
"accessor_2": { {
"bufferView": "bufferView_vertex", "name": "Cube-Mesh_texcoords",
"bufferView": 0,
"byteOffset": 576, "byteOffset": 576,
"byteStride": 0,
"componentType": 5126, "componentType": 5126,
"count": 24, "count": 24,
"min": [ "min": [
@ -52,10 +52,10 @@
], ],
"type": "VEC2" "type": "VEC2"
}, },
"accessor_3": { {
"bufferView": "bufferView_index", "name": "Cube-Mesh_0_indices",
"bufferView": 1,
"byteOffset": 0, "byteOffset": 0,
"byteStride": 0,
"componentType": 5123, "componentType": 5123,
"count": 36, "count": 36,
"min": [ "min": [
@ -66,113 +66,85 @@
], ],
"type": "SCALAR" "type": "SCALAR"
} }
}, ],
"asset": { "asset": {
"generator": "obj2gltf", "generator": "obj2gltf",
"profile": { "version": "2.0"
"api": "WebGL",
"version": "1.0"
},
"version": "1.0"
}, },
"buffers": { "buffers": [
"buffer": { {
"name": "buffer",
"byteLength": 840, "byteLength": 840,
"uri": "data:application/octet-stream;base64,AACAvwAAgL8AAIA/AACAvwAAgD8AAIA/AACAvwAAgD8AAIC/AACAvwAAgL8AAIC/AACAvwAAgL8AAIC/AACAvwAAgD8AAIC/AACAPwAAgD8AAIC/AACAPwAAgL8AAIC/AACAPwAAgL8AAIC/AACAPwAAgD8AAIC/AACAPwAAgD8AAIA/AACAPwAAgL8AAIA/AACAPwAAgL8AAIA/AACAPwAAgD8AAIA/AACAvwAAgD8AAIA/AACAvwAAgL8AAIA/AACAvwAAgL8AAIC/AACAPwAAgL8AAIC/AACAPwAAgL8AAIA/AACAvwAAgL8AAIA/AACAPwAAgD8AAIC/AACAvwAAgD8AAIC/AACAvwAAgD8AAIA/AACAPwAAgD8AAIA/AACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAIA/AACAPwAAgD8AAAAAAAAAAAAAAAAAAAAAAACAPwAAgD8AAIA/AACAPwAAAAAAAAAAAAAAAAAAAAAAAIA/AACAPwAAgD8AAIA/AAAAAAAAAAAAAAAAAAAAAAAAgD8AAIA/AACAPwAAgD8AAAAAAAAAAAAAAAAAAAAAAACAPwAAgD8AAIA/AACAPwAAAAAAAAAAAAAAAAAAAAAAAIA/AACAPwAAgD8AAIA/AAAAAAAAAAAAAAAAAAABAAIAAAACAAMABAAFAAYABAAGAAcACAAJAAoACAAKAAsADAANAA4ADAAOAA8AEAARABIAEAASABMAFAAVABYAFAAWABcA" "uri": "data:application/octet-stream;base64,AACAvwAAgL8AAIA/AACAvwAAgD8AAIA/AACAvwAAgD8AAIC/AACAvwAAgL8AAIC/AACAvwAAgL8AAIC/AACAvwAAgD8AAIC/AACAPwAAgD8AAIC/AACAPwAAgL8AAIC/AACAPwAAgL8AAIC/AACAPwAAgD8AAIC/AACAPwAAgD8AAIA/AACAPwAAgL8AAIA/AACAPwAAgL8AAIA/AACAPwAAgD8AAIA/AACAvwAAgD8AAIA/AACAvwAAgL8AAIA/AACAvwAAgL8AAIC/AACAPwAAgL8AAIC/AACAPwAAgL8AAIA/AACAvwAAgL8AAIA/AACAPwAAgD8AAIC/AACAvwAAgD8AAIC/AACAvwAAgD8AAIA/AACAPwAAgD8AAIA/AACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAIA/AACAPwAAgD8AAAAAAAAAAAAAAAAAAAAAAACAPwAAgD8AAIA/AACAPwAAAAAAAAAAAAAAAAAAAAAAAIA/AACAPwAAgD8AAIA/AAAAAAAAAAAAAAAAAAAAAAAAgD8AAIA/AACAPwAAgD8AAAAAAAAAAAAAAAAAAAAAAACAPwAAgD8AAIA/AACAPwAAAAAAAAAAAAAAAAAAAAAAAIA/AACAPwAAgD8AAIA/AAAAAAAAAAAAAAAAAAABAAIAAAACAAMABAAFAAYABAAGAAcACAAJAAoACAAKAAsADAANAA4ADAAOAA8AEAARABIAEAASABMAFAAVABYAFAAWABcA"
} }
}, ],
"bufferViews": { "bufferViews": [
"bufferView_vertex": { {
"buffer": "buffer", "name": "bufferView_vertex",
"buffer": 0,
"byteLength": 768, "byteLength": 768,
"byteOffset": 0, "byteOffset": 0,
"target": 34962 "target": 34962
}, },
"bufferView_index": { {
"buffer": "buffer", "name": "bufferView_index",
"buffer": 0,
"byteLength": 72, "byteLength": 72,
"byteOffset": 768, "byteOffset": 768,
"target": 34963 "target": 34963
} }
},
"extensionsUsed": [
"KHR_materials_common"
], ],
"images": {}, "materials": [
"materials": { {
"Material": { "name": "Material",
"extensions": { "pbrMetallicRoughness": {
"KHR_materials_common": { "baseColorFactor": [
"technique": "PHONG", 0.64,
"transparent": false, 0.64,
"doubleSided": false, 0.64,
"values": { 1
"ambient": [ ],
0, "metallicFactor": 0,
0, "roughnessFactor": 0.903921569
0, },
1 "emissiveFactor": [
], 0,
"diffuse": [ 0,
0.64, 0
0.64, ],
0.64, "alphaMode": "OPAQUE",
1 "doubleSided": false
],
"emission": [
0,
0,
0,
1
],
"specular": [
0.5,
0.5,
0.5,
1
],
"shininess": 96.078431,
"transparency": 1,
"transparent": false,
"doubleSided": false
}
}
}
} }
}, ],
"meshes": { "meshes": [
"Cube-Mesh": { {
"name": "Cube-Mesh", "name": "Cube-Mesh",
"primitives": [ "primitives": [
{ {
"attributes": { "attributes": {
"POSITION": "accessor_0", "POSITION": 0,
"NORMAL": "accessor_1", "NORMAL": 1,
"TEXCOORD_0": "accessor_2" "TEXCOORD_0": 2
}, },
"indices": "accessor_3", "indices": 3,
"material": "Material", "material": 0,
"mode": 4 "mode": 4
} }
] ]
} }
}, ],
"nodes": { "nodes": [
"Cube": { {
"name": "Cube", "name": "Cube",
"meshes": [ "mesh": 0
"Cube-Mesh"
]
} }
}, ],
"samplers": {}, "scene": 0,
"scene": "scene", "scenes": [
"scenes": { {
"scene": {
"nodes": [ "nodes": [
"Cube" 0
] ]
} }
}, ]
"textures": {} }
}

View File

@ -26,9 +26,16 @@ var defaultOptions = obj2gltf.defaults;
var checkTransparencyOptions = clone(defaultOptions); var checkTransparencyOptions = clone(defaultOptions);
checkTransparencyOptions.checkTransparency = true; checkTransparencyOptions.checkTransparency = true;
function setDefaultMaterial(objData) {
var originalMaterial = objData.materials[0];
var defaultMaterial = new Material();
defaultMaterial.name = originalMaterial.name;
objData.materials[0] = defaultMaterial;
return defaultMaterial;
}
describe('createGltf', function() { describe('createGltf', function() {
var boxObjData; var boxObjData;
var duplicateBoxObjData;
var groupObjData; var groupObjData;
var boxGltf; var boxGltf;
var groupGltf; var groupGltf;
@ -41,10 +48,6 @@ describe('createGltf', function() {
.then(function(data) { .then(function(data) {
boxObjData = data; boxObjData = data;
}), }),
loadObj(boxObjUrl, defaultOptions)
.then(function(data) {
duplicateBoxObjData = data;
}),
loadObj(groupObjUrl, defaultOptions) loadObj(groupObjUrl, defaultOptions)
.then(function(data) { .then(function(data) {
groupObjData = data; groupObjData = data;
@ -82,25 +85,69 @@ describe('createGltf', function() {
expect(writeUris(gltf, groupGltfUrl, path.dirname(groupGltfUrl), defaultOptions) expect(writeUris(gltf, groupGltfUrl, path.dirname(groupGltfUrl), defaultOptions)
.then(function() { .then(function() {
expect(gltf).toEqual(groupGltf); expect(gltf).toEqual(groupGltf);
expect(Object.keys(gltf.materials).length).toBe(3); expect(gltf.materials.length).toBe(3);
expect(Object.keys(gltf.nodes).length).toBe(1); expect(gltf.nodes.length).toBe(4);
expect(Object.keys(gltf.meshes).length).toBe(3); expect(gltf.nodes[0].mesh).toBeUndefined();
expect(gltf.nodes[0].children.length).toBe(3);
expect(gltf.meshes.length).toBe(3);
// Check for two primitives in each mesh // Check for two primitives in each mesh
for (var id in gltf.meshes) { var length = gltf.meshes.length;
if (gltf.meshes.hasOwnProperty(id)) { for (var i = 0; i < length; ++i) {
var mesh = gltf.meshes[id]; var mesh = gltf.meshes[i];
expect(mesh.primitives.length).toBe(2); expect(mesh.primitives.length).toBe(2);
}
} }
}), done).toResolve(); }), done).toResolve();
}); });
it('sets default material values', function() { it('sets default material values', function() {
boxObjData.materials.Material = new Material(); // Will convert traditional material to metallic-roughness
setDefaultMaterial(boxObjData);
var gltf = createGltf(boxObjData, defaultOptions); var gltf = createGltf(boxObjData, defaultOptions);
var material = gltf.materials.Material; var material = gltf.materials[0];
var pbr = material.pbrMetallicRoughness;
expect(pbr.baseColorTexture).toBeUndefined();
expect(pbr.metallicRoughnessTexture).toBeUndefined();
expect(pbr.baseColorFactor).toEqual([0.5, 0.5, 0.5, 1.0]);
expect(pbr.metallicFactor).toBe(0.0); // No metallic
expect(pbr.roughnessFactor).toBe(1.0); // Fully rough
expect(material.emissiveTexture).toBe(undefined);
expect(material.normalTexture).toBe(undefined);
expect(material.occlusionTexture).toBe(undefined);
expect(material.emissiveFactor).toEqual([0.0, 0.0, 0.0]);
});
it('sets default material values for metallicRoughness', function() {
// No conversion applied when metallicRoughness flag is set
var options = clone(defaultOptions);
options.metallicRoughness = true;
var defaultMaterial = setDefaultMaterial(boxObjData);
defaultMaterial.specularShininess = 1.0; // This is the default set in loadMtl
var gltf = createGltf(boxObjData, options);
var material = gltf.materials[0];
var pbr = material.pbrMetallicRoughness;
expect(pbr.baseColorTexture).toBeUndefined();
expect(pbr.metallicRoughnessTexture).toBeUndefined();
expect(pbr.baseColorFactor).toEqual([0.5, 0.5, 0.5, 1.0]);
expect(pbr.metallicFactor).toBe(0.0); // No metallic
expect(pbr.roughnessFactor).toBe(1.0); // Fully rough
expect(material.emissiveTexture).toBe(undefined);
expect(material.normalTexture).toBe(undefined);
expect(material.occlusionTexture).toBe(undefined);
expect(material.emissiveFactor).toEqual([0.0, 0.0, 0.0]);
});
it('sets default material values for materialsCommon', function() {
var options = clone(defaultOptions);
options.materialsCommon = true;
setDefaultMaterial(boxObjData);
var gltf = createGltf(boxObjData, options);
var material = gltf.materials[0];
var kmc = material.extensions.KHR_materials_common; var kmc = material.extensions.KHR_materials_common;
var values = kmc.values; var values = kmc.values;
@ -110,12 +157,15 @@ describe('createGltf', function() {
expect(values.emission).toEqual([0.0, 0.0, 0.0, 1]); expect(values.emission).toEqual([0.0, 0.0, 0.0, 1]);
expect(values.specular).toEqual([0.0, 0.0, 0.0, 1]); expect(values.specular).toEqual([0.0, 0.0, 0.0, 1]);
expect(values.shininess).toEqual(0.0); expect(values.shininess).toEqual(0.0);
expect(values.transparency).toBe(1.0);
expect(values.transparent).toBe(false);
expect(values.doubleSided).toBe(false);
}); });
it('sets material for diffuse texture', function() { it('sets material for diffuse texture', function() {
var material = new Material(); var material = new Material();
material.diffuseTexture = diffuseTextureUrl; material.diffuseTexture = diffuseTextureUrl;
boxObjData.materials.Material = material; boxObjData.materials[0] = material;
boxObjData.images[diffuseTextureUrl] = diffuseTexture; boxObjData.images[diffuseTextureUrl] = diffuseTexture;
var gltf = createGltf(boxObjData, defaultOptions); var gltf = createGltf(boxObjData, defaultOptions);
@ -154,7 +204,7 @@ describe('createGltf', function() {
it('sets material for alpha less than 1', function() { it('sets material for alpha less than 1', function() {
var material = new Material(); var material = new Material();
material.alpha = 0.4; material.alpha = 0.4;
boxObjData.materials.Material = material; boxObjData.materials[0] = material;
var gltf = createGltf(boxObjData, defaultOptions); var gltf = createGltf(boxObjData, defaultOptions);
var kmc = gltf.materials.Material.extensions.KHR_materials_common; var kmc = gltf.materials.Material.extensions.KHR_materials_common;
@ -169,7 +219,7 @@ describe('createGltf', function() {
var material = new Material(); var material = new Material();
material.diffuseTexture = diffuseTextureUrl; material.diffuseTexture = diffuseTextureUrl;
material.alpha = 0.4; material.alpha = 0.4;
boxObjData.materials.Material = material; boxObjData.materials[0] = material;
boxObjData.images[diffuseTextureUrl] = diffuseTexture; boxObjData.images[diffuseTextureUrl] = diffuseTexture;
@ -185,7 +235,7 @@ describe('createGltf', function() {
it('sets material for transparent diffuse texture', function() { it('sets material for transparent diffuse texture', function() {
var material = new Material(); var material = new Material();
material.diffuseTexture = transparentDiffuseTextureUrl; material.diffuseTexture = transparentDiffuseTextureUrl;
boxObjData.materials.Material = material; boxObjData.materials[0] = material;
boxObjData.images[transparentDiffuseTextureUrl] = transparentDiffuseTexture; boxObjData.images[transparentDiffuseTextureUrl] = transparentDiffuseTexture;
@ -202,7 +252,7 @@ describe('createGltf', function() {
var material = new Material(); var material = new Material();
material.specularColor = [0.1, 0.1, 0.2, 1]; material.specularColor = [0.1, 0.1, 0.2, 1];
material.specularShininess = 0.1; material.specularShininess = 0.1;
boxObjData.materials.Material = material; boxObjData.materials[0] = material;
var gltf = createGltf(boxObjData, defaultOptions); var gltf = createGltf(boxObjData, defaultOptions);
var kmc = gltf.materials.Material.extensions.KHR_materials_common; var kmc = gltf.materials.Material.extensions.KHR_materials_common;
@ -217,7 +267,7 @@ describe('createGltf', function() {
var material = new Material(); var material = new Material();
material.diffuseTexture = diffuseTextureUrl; material.diffuseTexture = diffuseTextureUrl;
boxObjData.materials.Material = material; boxObjData.materials[0] = material;
boxObjData.images[diffuseTextureUrl] = diffuseTexture; boxObjData.images[diffuseTextureUrl] = diffuseTexture;
@ -231,10 +281,10 @@ describe('createGltf', function() {
it('sets default material when texture is missing', function() { it('sets default material when texture is missing', function() {
var material = new Material(); var material = new Material();
material.diffuseTexture = diffuseTextureUrl; material.diffuseTexture = diffuseTextureUrl;
boxObjData.materials.Material = material; boxObjData.materials[0] = material;
var gltf = createGltf(boxObjData, defaultOptions); var gltf = createGltf(boxObjData, defaultOptions);
var kmc = gltf.materials.Material.extensions.KHR_materials_common; var kmc = gltf.materials[0].extensions.KHR_materials_common;
expect(kmc.values.diffuse).toEqual([0.5, 0.5, 0.5, 1.0]); expect(kmc.values.diffuse).toEqual([0.5, 0.5, 0.5, 1.0]);
}); });
@ -244,8 +294,8 @@ describe('createGltf', function() {
// Creates a material called "default" // Creates a material called "default"
var gltf = createGltf(boxObjData, defaultOptions); var gltf = createGltf(boxObjData, defaultOptions);
expect(gltf.materials.default).toBeDefined(); expect(gltf.materials[0].name).toBe('default');
var kmc = gltf.materials.default.extensions.KHR_materials_common; var kmc = gltf.materials[0].extensions.KHR_materials_common;
expect(kmc.values.diffuse).toEqual([0.5, 0.5, 0.5, 1.0]); expect(kmc.values.diffuse).toEqual([0.5, 0.5, 0.5, 1.0]);
}); });
@ -254,37 +304,11 @@ describe('createGltf', function() {
// Uses the original name of the material // Uses the original name of the material
var gltf = createGltf(boxObjData, defaultOptions); var gltf = createGltf(boxObjData, defaultOptions);
var kmc = gltf.materials.Material.extensions.KHR_materials_common; var kmc = gltf.materials[0].extensions.KHR_materials_common;
expect(kmc.values.diffuse).toEqual([0.5, 0.5, 0.5, 1.0]); expect(kmc.values.diffuse).toEqual([0.5, 0.5, 0.5, 1.0]);
}); });
it('handles material used with and without normals (1)', function() {
// Two meshes - one with normals, and one without
boxObjData.nodes.push(duplicateBoxObjData.nodes[0]);
boxObjData.nodes[1].meshes[0].normals.length = 0;
var gltf = createGltf(boxObjData, defaultOptions);
var kmc1 = gltf.materials.Material.extensions.KHR_materials_common;
var kmc2 = gltf.materials.Material_constant.extensions.KHR_materials_common;
expect(kmc1.technique).toBe('PHONG');
expect(kmc2.technique).toBe('CONSTANT');
});
it('handles material used with and without normals (2)', function() {
// Now test in a different order
boxObjData.nodes.push(duplicateBoxObjData.nodes[0]);
boxObjData.nodes[0].meshes[0].normals.length = 0;
var gltf = createGltf(boxObjData, defaultOptions);
var kmc1 = gltf.materials.Material.extensions.KHR_materials_common;
var kmc2 = gltf.materials.Material_shaded.extensions.KHR_materials_common;
expect(kmc1.technique).toBe('CONSTANT');
expect(kmc2.technique).toBe('PHONG');
});
it('runs without normals', function() { it('runs without normals', function() {
boxObjData.nodes[0].meshes[0].normals.length = 0; boxObjData.nodes[0].meshes[0].normals.length = 0;

View File

@ -1,10 +1,7 @@
'use strict'; 'use strict';
var Cesium = require('cesium');
var obj2gltf = require('../../lib/obj2gltf'); var obj2gltf = require('../../lib/obj2gltf');
var loadImage = require('../../lib/loadImage'); var loadImage = require('../../lib/loadImage');
var clone = Cesium.clone;
var pngImage = 'specs/data/box-complex-material/shininess.png'; var pngImage = 'specs/data/box-complex-material/shininess.png';
var jpgImage = 'specs/data/box-complex-material/emission.jpg'; var jpgImage = 'specs/data/box-complex-material/emission.jpg';
var jpegImage = 'specs/data/box-complex-material/specular.jpeg'; var jpegImage = 'specs/data/box-complex-material/specular.jpeg';
@ -12,47 +9,58 @@ var gifImage = 'specs/data/box-complex-material/ambient.gif';
var grayscaleImage = 'specs/data/box-complex-material/alpha.png'; var grayscaleImage = 'specs/data/box-complex-material/alpha.png';
var transparentImage = 'specs/data/box-complex-material/diffuse.png'; var transparentImage = 'specs/data/box-complex-material/diffuse.png';
var defaultOptions = obj2gltf.defaults;
describe('loadImage', function() { describe('loadImage', function() {
it('loads png image', function(done) { it('loads png image', function(done) {
expect(loadImage(pngImage, defaultOptions) expect(loadImage(pngImage)
.then(function(info) { .then(function(info) {
expect(info.transparent).toBe(false); expect(info.transparent).toBe(false);
expect(info.source).toBeDefined(); expect(info.source).toBeDefined();
expect(info.extension).toBe('.png'); expect(info.extension).toBe('.png');
expect(info.path).toBe(pngImage);
expect(info.decoded).toBeUndefined();
expect(info.width).toBeUndefined();
expect(info.height).toBeUndefined();
}), done).toResolve(); }), done).toResolve();
}); });
it('loads jpg image', function(done) { it('loads jpg image', function(done) {
expect(loadImage(jpgImage, defaultOptions) expect(loadImage(jpgImage)
.then(function(info) { .then(function(info) {
expect(info.transparent).toBe(false); expect(info.transparent).toBe(false);
expect(info.source).toBeDefined(); expect(info.source).toBeDefined();
expect(info.extension).toBe('.jpg'); expect(info.extension).toBe('.jpg');
expect(info.decoded).toBeUndefined();
expect(info.width).toBeUndefined();
expect(info.height).toBeUndefined();
}), done).toResolve(); }), done).toResolve();
}); });
it('loads jpeg image', function(done) { it('loads jpeg image', function(done) {
expect(loadImage(jpegImage, defaultOptions) expect(loadImage(jpegImage)
.then(function(info) { .then(function(info) {
expect(info.transparent).toBe(false); expect(info.transparent).toBe(false);
expect(info.source).toBeDefined(); expect(info.source).toBeDefined();
expect(info.extension).toBe('.jpeg'); expect(info.extension).toBe('.jpeg');
expect(info.decoded).toBeUndefined();
expect(info.width).toBeUndefined();
expect(info.height).toBeUndefined();
}), done).toResolve(); }), done).toResolve();
}); });
it('loads gif image', function(done) { it('loads gif image', function(done) {
expect(loadImage(gifImage, defaultOptions) expect(loadImage(gifImage)
.then(function(info) { .then(function(info) {
expect(info.transparent).toBe(false); expect(info.transparent).toBe(false);
expect(info.source).toBeDefined(); expect(info.source).toBeDefined();
expect(info.extension).toBe('.gif'); expect(info.extension).toBe('.gif');
expect(info.decoded).toBeUndefined();
expect(info.width).toBeUndefined();
expect(info.height).toBeUndefined();
}), done).toResolve(); }), done).toResolve();
}); });
it('loads grayscale image', function(done) { it('loads grayscale image', function(done) {
expect(loadImage(grayscaleImage, defaultOptions) expect(loadImage(grayscaleImage)
.then(function(info) { .then(function(info) {
expect(info.transparent).toBe(false); expect(info.transparent).toBe(false);
expect(info.source).toBeDefined(); expect(info.source).toBeDefined();
@ -61,19 +69,46 @@ describe('loadImage', function() {
}); });
it('loads image with alpha channel', function(done) { it('loads image with alpha channel', function(done) {
expect(loadImage(transparentImage, defaultOptions) expect(loadImage(transparentImage)
.then(function(info) { .then(function(info) {
expect(info.transparent).toBe(false); expect(info.transparent).toBe(false);
}), done).toResolve(); }), done).toResolve();
}); });
it('loads image with checkTransparency flag', function(done) { it('loads image with checkTransparency flag', function(done) {
var options = clone(defaultOptions); var options = {
options.checkTransparency = true; checkTransparency : true
};
expect(loadImage(transparentImage, options) expect(loadImage(transparentImage, options)
.then(function(info) { .then(function(info) {
expect(info.transparent).toBe(true); expect(info.transparent).toBe(true);
}), done).toResolve(); }), done).toResolve();
}); });
it('loads and decodes png', function(done) {
var options = {
decode : true
};
expect(loadImage(pngImage, options)
.then(function(info) {
expect(info.decoded).toBeDefined();
expect(info.width).toBe(211);
expect(info.height).toBe(211);
}), done).toResolve();
});
it('loads and decodes jpeg', function(done) {
var options = {
decode : true
};
expect(loadImage(jpegImage, options)
.then(function(info) {
expect(info.decoded).toBeDefined();
expect(info.width).toBe(211);
expect(info.height).toBe(211);
}), done).toResolve();
});
}); });

View File

@ -1,6 +1,7 @@
'use strict'; 'use strict';
var path = require('path'); var path = require('path');
var loadMtl = require('../../lib/loadMtl'); var loadMtl = require('../../lib/loadMtl');
var obj2gltf = require('../../lib/obj2gltf');
var complexMaterialUrl = 'specs/data/box-complex-material/box-complex-material.mtl'; var complexMaterialUrl = 'specs/data/box-complex-material/box-complex-material.mtl';
var multipleMaterialsUrl = 'specs/data/box-multiple-materials/box-multiple-materials.mtl'; var multipleMaterialsUrl = 'specs/data/box-multiple-materials/box-multiple-materials.mtl';
@ -9,12 +10,14 @@ function getImagePath(objPath, relativePath) {
return path.resolve(path.dirname(objPath), relativePath); return path.resolve(path.dirname(objPath), relativePath);
} }
var defaultOptions = obj2gltf.defaults;
describe('loadMtl', function() { describe('loadMtl', function() {
it('loads complex material', function(done) { it('loads complex material', function(done) {
expect(loadMtl(complexMaterialUrl) expect(loadMtl(complexMaterialUrl, defaultOptions)
.then(function(materials) { .then(function(materials) {
var material = materials.Material; var material = materials[0];
expect(material).toBeDefined(); expect(material.name).toBe('Material');
expect(material.ambientColor).toEqual([0.2, 0.2, 0.2, 1.0]); expect(material.ambientColor).toEqual([0.2, 0.2, 0.2, 1.0]);
expect(material.emissiveColor).toEqual([0.1, 0.1, 0.1, 1.0]); expect(material.emissiveColor).toEqual([0.1, 0.1, 0.1, 1.0]);
expect(material.diffuseColor).toEqual([0.64, 0.64, 0.64, 1.0]); expect(material.diffuseColor).toEqual([0.64, 0.64, 0.64, 1.0]);
@ -32,12 +35,15 @@ describe('loadMtl', function() {
}); });
it('loads mtl with multiple materials', function(done) { it('loads mtl with multiple materials', function(done) {
expect(loadMtl(multipleMaterialsUrl) expect(loadMtl(multipleMaterialsUrl, defaultOptions)
.then(function(materials) { .then(function(materials) {
expect(Object.keys(materials).length).toBe(3); expect(materials.length).toBe(3);
expect(materials.Red.diffuseColor).toEqual([0.64, 0.0, 0.0, 1.0]); expect(materials[0].name).toBe('Blue');
expect(materials.Green.diffuseColor).toEqual([0.0, 0.64, 0.0, 1.0]); expect(materials[0].diffuseColor).toEqual([0.0, 0.0, 0.64, 1.0]);
expect(materials.Blue.diffuseColor).toEqual([0.0, 0.0, 0.64, 1.0]); expect(materials[1].name).toBe('Green');
expect(materials[1].diffuseColor).toEqual([0.0, 0.64, 0.0, 1.0]);
expect(materials[2].name).toBe('Red');
expect(materials[2].diffuseColor).toEqual([0.64, 0.0, 0.0, 1.0]);
}), done).toResolve(); }), done).toResolve();
}); });
}); });

View File

@ -77,8 +77,8 @@ describe('loadObj', function() {
var meshes = getMeshes(data); var meshes = getMeshes(data);
var primitives = getPrimitives(data); var primitives = getPrimitives(data);
expect(Object.keys(images).length).toBe(0); expect(images.length).toBe(0);
expect(materials.Material).toBeDefined(); expect(materials.length).toBe(1);
expect(nodes.length).toBe(1); expect(nodes.length).toBe(1);
expect(meshes.length).toBe(1); expect(meshes.length).toBe(1);
expect(primitives.length).toBe(1); expect(primitives.length).toBe(1);
@ -268,17 +268,26 @@ describe('loadObj', function() {
expect(loadObj(objMtllibUrl, defaultOptions) expect(loadObj(objMtllibUrl, defaultOptions)
.then(function(data) { .then(function(data) {
var materials = data.materials; var materials = data.materials;
expect(Object.keys(materials).length).toBe(3); expect(materials.length).toBe(3);
expect(materials.Red.diffuseColor).toEqual([0.64, 0.0, 0.0, 1.0]);
expect(materials.Green.diffuseColor).toEqual([0.0, 0.64, 0.0, 1.0]); // .mtl files are loaded in an arbitrary order, so sort for testing purposes
expect(materials.Blue.diffuseColor).toEqual([0.0, 0.0, 0.64, 1.0]); materials.sort(function(a, b){
return a.name.localeCompare(b.name);
});
expect(materials[0].name).toBe('Blue');
expect(materials[0].diffuseColor).toEqual([0.0, 0.0, 0.64, 1.0]);
expect(materials[1].name).toBe('Green');
expect(materials[1].diffuseColor).toEqual([0.0, 0.64, 0.0, 1.0]);
expect(materials[2].name).toBe('Red');
expect(materials[2].diffuseColor).toEqual([0.64, 0.0, 0.0, 1.0]);
}), done).toResolve(); }), done).toResolve();
}); });
it('loads obj with missing mtllib', function(done) { it('loads obj with missing mtllib', function(done) {
expect(loadObj(objMissingMtllibUrl, defaultOptions) expect(loadObj(objMissingMtllibUrl, defaultOptions)
.then(function(data) { .then(function(data) {
expect(data.materials).toEqual({}); expect(data.materials.length).toBe(0);
expect(console.log.calls.argsFor(0)[0].indexOf('Could not read mtl file') >= 0).toBe(true); expect(console.log.calls.argsFor(0)[0].indexOf('Could not read mtl file') >= 0).toBe(true);
}), done).toResolve(); }), done).toResolve();
}); });
@ -287,8 +296,14 @@ describe('loadObj', function() {
expect(loadObj(objExternalResourcesUrl, defaultOptions) expect(loadObj(objExternalResourcesUrl, defaultOptions)
.then(function(data) { .then(function(data) {
var imagePath = getImagePath(objTexturedUrl, 'cesium.png'); var imagePath = getImagePath(objTexturedUrl, 'cesium.png');
expect(data.images[imagePath]).toBeDefined(); expect(data.images[0].path).toBe(imagePath);
expect(data.materials.MaterialTextured.diffuseTexture).toEqual(imagePath);
var materials = data.materials;
expect(materials.length).toBe(2);
// .mtl files are loaded in an arbitrary order, so find the "MaterialTextured" material
var materialTextured = materials[0].name === 'MaterialTextured' ? materials[0] : materials[1];
expect(materialTextured.diffuseTexture).toEqual(imagePath);
}), done).toResolve(); }), done).toResolve();
}); });
@ -299,9 +314,8 @@ describe('loadObj', function() {
expect(loadObj(objExternalResourcesUrl, options) expect(loadObj(objExternalResourcesUrl, options)
.then(function(data) { .then(function(data) {
var imagePath = getImagePath(objMissingTextureUrl, 'cesium.png'); var imagePath = getImagePath(objMissingTextureUrl, 'cesium.png');
expect(data.images[imagePath]).toBeUndefined(); expect(data.images.length).toBe(0); // obj references an image file that is outside the input directory
expect(data.materials.MaterialTextured).toBeDefined(); expect(data.materials.length).toBe(1); // obj references 2 materials, one of which is outside the input directory
expect(data.materials.Material).toBeUndefined(); // Not in directory, so not included
expect(console.log.calls.argsFor(0)[0].indexOf('Could not read mtl file') >= 0).toBe(true); expect(console.log.calls.argsFor(0)[0].indexOf('Could not read mtl file') >= 0).toBe(true);
expect(console.log.calls.argsFor(1)[0].indexOf('Could not read image file') >= 0).toBe(true); expect(console.log.calls.argsFor(1)[0].indexOf('Could not read image file') >= 0).toBe(true);
}), done).toResolve(); }), done).toResolve();
@ -311,8 +325,8 @@ describe('loadObj', function() {
expect(loadObj(objTexturedUrl, defaultOptions) expect(loadObj(objTexturedUrl, defaultOptions)
.then(function(data) { .then(function(data) {
var imagePath = getImagePath(objTexturedUrl, 'cesium.png'); var imagePath = getImagePath(objTexturedUrl, 'cesium.png');
expect(data.images[imagePath]).toBeDefined(); expect(data.images[0].path).toBe(imagePath);
expect(data.materials.Material.diffuseTexture).toEqual(imagePath); expect(data.materials[0].diffuseTexture).toEqual(imagePath);
}), done).toResolve(); }), done).toResolve();
}); });
@ -320,8 +334,8 @@ describe('loadObj', function() {
expect(loadObj(objMissingTextureUrl, defaultOptions) expect(loadObj(objMissingTextureUrl, defaultOptions)
.then(function(data) { .then(function(data) {
var imagePath = getImagePath(objMissingTextureUrl, 'cesium.png'); var imagePath = getImagePath(objMissingTextureUrl, 'cesium.png');
expect(data.images[imagePath]).toBeUndefined(); expect(data.images.length).toBe(0);
expect(data.materials.Material.diffuseTexture).toEqual(imagePath); expect(data.materials[0].diffuseTexture).toEqual(imagePath);
expect(console.log.calls.argsFor(0)[0].indexOf('Could not read image file') >= 0).toBe(true); expect(console.log.calls.argsFor(0)[0].indexOf('Could not read image file') >= 0).toBe(true);
}), done).toResolve(); }), done).toResolve();
}); });
@ -330,8 +344,8 @@ describe('loadObj', function() {
expect(loadObj(objSubdirectoriesUrl, defaultOptions) expect(loadObj(objSubdirectoriesUrl, defaultOptions)
.then(function(data) { .then(function(data) {
var imagePath = getImagePath(objSubdirectoriesUrl, path.join('materials', 'images', 'cesium.png')); var imagePath = getImagePath(objSubdirectoriesUrl, path.join('materials', 'images', 'cesium.png'));
expect(data.images[imagePath]).toBeDefined(); expect(data.images[0].path).toBe(imagePath);
expect(data.materials.Material.diffuseTexture).toEqual(imagePath); expect(data.materials[0].diffuseTexture).toEqual(imagePath);
}), done).toResolve(); }), done).toResolve();
}); });
@ -339,7 +353,7 @@ describe('loadObj', function() {
expect(loadObj(objComplexMaterialUrl, defaultOptions) expect(loadObj(objComplexMaterialUrl, defaultOptions)
.then(function(data) { .then(function(data) {
var images = data.images; var images = data.images;
expect(Object.keys(images).length).toBe(4); // Only ambient, diffuse, emission, and specular maps are supported by the converter expect(images.length).toBe(6);
}), done).toResolve(); }), done).toResolve();
}); });

View File

@ -1,4 +1,5 @@
'use strict'; 'use strict';
var Cesium = require('Cesium');
var fsExtra = require('fs-extra'); var fsExtra = require('fs-extra');
var GltfPipeline = require('gltf-pipeline').Pipeline; var GltfPipeline = require('gltf-pipeline').Pipeline;
var os = require('os'); var os = require('os');
@ -7,6 +8,8 @@ var Promise = require('bluebird');
var obj2gltf = require('../../lib/obj2gltf'); var obj2gltf = require('../../lib/obj2gltf');
var writeUris = require('../../lib/writeUris'); var writeUris = require('../../lib/writeUris');
var RuntimeError = Cesium.RuntimeError;
var objPath = 'specs/data/box-textured/box-textured.obj'; var objPath = 'specs/data/box-textured/box-textured.obj';
var gltfPath = 'specs/data/box-textured/box-textured.gltf'; var gltfPath = 'specs/data/box-textured/box-textured.gltf';
var glbPath = 'specs/data/box-textured/box-textured.glb'; var glbPath = 'specs/data/box-textured/box-textured.glb';
@ -37,7 +40,7 @@ describe('obj2gltf', function() {
var options = args[2]; var options = args[2];
expect(path.normalize(outputPath)).toEqual(path.normalize(gltfPath)); expect(path.normalize(outputPath)).toEqual(path.normalize(gltfPath));
expect(gltf).toBeDefined(); expect(gltf).toBeDefined();
expect(gltf.images.cesium).toBeDefined(); expect(gltf.images.length).toBe(1);
expect(options).toEqual({ expect(options).toEqual({
basePath : tempDirectory, basePath : tempDirectory,
createDirectory : false, createDirectory : false,
@ -131,9 +134,25 @@ describe('obj2gltf', function() {
}).toThrowDeveloperError(); }).toThrowDeveloperError();
}); });
it('rejects if gltfPath is undefined', function() { it('throws if gltfPath is undefined', function() {
expect(function() { expect(function() {
obj2gltf(objPath, undefined); obj2gltf(objPath, undefined);
}).toThrowDeveloperError(); }).toThrowDeveloperError();
}); });
it('rejects if both bpypassPipeline and binary are true', function(done) {
var options = {
bypassPipeline : true,
binary : true
};
expect(obj2gltf(objPath, gltfPath, options), done).toRejectWith(RuntimeError);
});
it('rejects if more than one material type is set', function(done) {
var options = {
metallicRoughness : true,
specularGlossiness : true
};
expect(obj2gltf(objPath, gltfPath, options), done).toRejectWith(RuntimeError);
});
}); });