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;
/**
* 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() {
this.name = '';
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} 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.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.materialsCommon] The glTF will be saved with the KHR_materials_common extension.
* @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.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.logger A callback function for handling logged messages. Defaults to console.log.
* @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.
if (specularIntensity < 0.1) {
roughnessFactor *= specularIntensity;
roughnessFactor *= (1.0 - specularIntensity);
}
var metallicFactor = 0.0;
material.specularTexture = undefined; // For now just ignore the specular texture
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 ambientImage = getImage(images, material.ambientTexture);
@ -682,7 +683,7 @@ function addMaterial(gltf, images, material, hasNormals, options) {
} else if (options.metallicRoughness) {
gltfMaterial = createMetallicRoughnessMaterial(gltf, images, material, options);
} else if (options.materialsCommon) {
gltfMaterial = createMaterialsCommonMaterial(gltf, images, material, hasNormals, options);
gltfMaterial = createMaterialsCommonMaterial(gltf, images, material, hasNormals);
} else {
convertTraditionalToMetallicRoughness(material);
gltfMaterial = createMetallicRoughnessMaterial(gltf, images, material, options);
@ -693,26 +694,16 @@ function addMaterial(gltf, images, material, hasNormals, options) {
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) {
if (!defined(materialName)) {
// Create a default material if the primitive does not specify one
materialName = 'default';
}
var i;
var material;
var materialsLength = materials.length;
for (var i = 0; i < materialsLength; ++i) {
for (i = 0; i < materialsLength; ++i) {
if (materials[i].name === materialName) {
material = materials[i];
}
@ -723,7 +714,14 @@ function getMaterial(gltf, materials, images, materialName, hasNormals, options)
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)) {
materialIndex = addMaterial(gltf, images, material, hasNormals, options);
@ -732,13 +730,14 @@ function getMaterial(gltf, materials, images, materialName, hasNormals, options)
return materialIndex;
}
function addVertexAttribute(gltf, bufferState, array, components) {
function addVertexAttribute(gltf, bufferState, array, components, name) {
var buffer = array.toFloatBuffer();
var count = array.length / components;
var minMax = array.getMinMax(components);
var type = (components === 3 ? 'VEC3' : 'VEC2');
var accessor = {
name : name,
bufferView : bufferState.vertexBufferViewIndex,
byteOffset : bufferState.vertexBufferByteOffset,
componentType : WebGLConstants.FLOAT,
@ -756,13 +755,14 @@ function addVertexAttribute(gltf, bufferState, array, components) {
return accessorIndex;
}
function addIndexArray(gltf, bufferState, array, uint32Indices) {
function addIndexArray(gltf, bufferState, array, uint32Indices, name) {
var buffer = uint32Indices ? array.toUint32Buffer() : array.toUint16Buffer();
var componentType = uint32Indices ? WebGLConstants.UNSIGNED_INT : WebGLConstants.UNSIGNED_SHORT;
var count = array.length;
var minMax = array.getMinMax(1);
var accessor = {
name : name,
bufferView : bufferState.indexBufferViewIndex,
byteOffset : bufferState.indexBufferByteOffset,
componentType : componentType,
@ -803,13 +803,13 @@ function addMesh(gltf, materials, images, bufferState, uint32Indices, mesh, opti
var attributes = {};
if (hasPositions) {
attributes.POSITION = addVertexAttribute(gltf, bufferState, mesh.positions, 3);
attributes.POSITION = addVertexAttribute(gltf, bufferState, mesh.positions, 3, mesh.name + '_positions');
}
if (hasNormals) {
attributes.NORMAL = addVertexAttribute(gltf, bufferState, mesh.normals, 3);
attributes.NORMAL = addVertexAttribute(gltf, bufferState, mesh.normals, 3, mesh.name + '_normals');
}
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
@ -822,7 +822,7 @@ function addMesh(gltf, materials, images, bufferState, uint32Indices, mesh, opti
var primitivesLength = primitives.length;
for (var i = 0; i < primitivesLength; ++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
var materialIndex = getMaterial(gltf, materials, images, primitive.material, hasNormals, options);

View File

@ -9,23 +9,31 @@ module.exports = loadMtl;
* Parse an 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.
*
* @private
*/
function loadMtl(mtlPath) {
function loadMtl(mtlPath, options) {
var material;
var values;
var value;
var mtlDirectory = path.dirname(mtlPath);
var materials = [];
var defaultSpecularShininess = 0.0;
if (options.metallicRoughness) {
defaultSpecularShininess = 1.0; // Fully rough
}
function parseLine(line) {
line = line.trim();
if (/^newmtl /i.test(line)) {
var name = line.substring(7).trim();
material = new Material();
material.name = name;
material.specularShininess = defaultSpecularShininess;
materials.push(material);
} else if (/^Ka /i.test(line)) {
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.');
return;
}
return loadMtl(mtlPath)
return loadMtl(mtlPath, options)
.then(function(materialsInMtl) {
materials = materials.concat(materialsInMtl);
})

View File

@ -100,7 +100,7 @@ function obj2gltf(objPath, gltfPath, options) {
}
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);

View File

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

View File

@ -1,9 +1,9 @@
{
"accessors": {
"accessor_0": {
"bufferView": "bufferView_vertex",
"accessors": [
{
"name": "Blue_positions",
"bufferView": 0,
"byteOffset": 0,
"byteStride": 0,
"componentType": 5126,
"count": 24,
"min": [
@ -18,10 +18,10 @@
],
"type": "VEC3"
},
"accessor_1": {
"bufferView": "bufferView_vertex",
{
"name": "Blue_normals",
"bufferView": 0,
"byteOffset": 288,
"byteStride": 0,
"componentType": 5126,
"count": 24,
"min": [
@ -36,10 +36,10 @@
],
"type": "VEC3"
},
"accessor_2": {
"bufferView": "bufferView_vertex",
{
"name": "Blue_texcoords",
"bufferView": 0,
"byteOffset": 576,
"byteStride": 0,
"componentType": 5126,
"count": 24,
"min": [
@ -52,10 +52,10 @@
],
"type": "VEC2"
},
"accessor_3": {
"bufferView": "bufferView_index",
{
"name": "Blue_0_indices",
"bufferView": 1,
"byteOffset": 0,
"byteStride": 0,
"componentType": 5123,
"count": 18,
"min": [
@ -66,10 +66,10 @@
],
"type": "SCALAR"
},
"accessor_4": {
"bufferView": "bufferView_index",
{
"name": "Blue_1_indices",
"bufferView": 1,
"byteOffset": 36,
"byteStride": 0,
"componentType": 5123,
"count": 18,
"min": [
@ -80,10 +80,10 @@
],
"type": "SCALAR"
},
"accessor_5": {
"bufferView": "bufferView_vertex",
{
"name": "Green_positions",
"bufferView": 0,
"byteOffset": 768,
"byteStride": 0,
"componentType": 5126,
"count": 24,
"min": [
@ -98,10 +98,10 @@
],
"type": "VEC3"
},
"accessor_6": {
"bufferView": "bufferView_vertex",
{
"name": "Green_normals",
"bufferView": 0,
"byteOffset": 1056,
"byteStride": 0,
"componentType": 5126,
"count": 24,
"min": [
@ -116,10 +116,10 @@
],
"type": "VEC3"
},
"accessor_7": {
"bufferView": "bufferView_vertex",
{
"name": "Green_texcoords",
"bufferView": 0,
"byteOffset": 1344,
"byteStride": 0,
"componentType": 5126,
"count": 24,
"min": [
@ -132,10 +132,10 @@
],
"type": "VEC2"
},
"accessor_8": {
"bufferView": "bufferView_index",
{
"name": "Green_0_indices",
"bufferView": 1,
"byteOffset": 72,
"byteStride": 0,
"componentType": 5123,
"count": 18,
"min": [
@ -146,10 +146,10 @@
],
"type": "SCALAR"
},
"accessor_9": {
"bufferView": "bufferView_index",
{
"name": "Green_1_indices",
"bufferView": 1,
"byteOffset": 108,
"byteStride": 0,
"componentType": 5123,
"count": 18,
"min": [
@ -160,10 +160,10 @@
],
"type": "SCALAR"
},
"accessor_10": {
"bufferView": "bufferView_vertex",
{
"name": "Red_positions",
"bufferView": 0,
"byteOffset": 1536,
"byteStride": 0,
"componentType": 5126,
"count": 24,
"min": [
@ -178,10 +178,10 @@
],
"type": "VEC3"
},
"accessor_11": {
"bufferView": "bufferView_vertex",
{
"name": "Red_normals",
"bufferView": 0,
"byteOffset": 1824,
"byteStride": 0,
"componentType": 5126,
"count": 24,
"min": [
@ -196,10 +196,10 @@
],
"type": "VEC3"
},
"accessor_12": {
"bufferView": "bufferView_vertex",
{
"name": "Red_texcoords",
"bufferView": 0,
"byteOffset": 2112,
"byteStride": 0,
"componentType": 5126,
"count": 24,
"min": [
@ -212,10 +212,10 @@
],
"type": "VEC2"
},
"accessor_13": {
"bufferView": "bufferView_index",
{
"name": "Red_0_indices",
"bufferView": 1,
"byteOffset": 144,
"byteStride": 0,
"componentType": 5123,
"count": 18,
"min": [
@ -226,10 +226,10 @@
],
"type": "SCALAR"
},
"accessor_14": {
"bufferView": "bufferView_index",
{
"name": "Red_1_indices",
"bufferView": 1,
"byteOffset": 180,
"byteStride": 0,
"componentType": 5123,
"count": 18,
"min": [
@ -240,253 +240,201 @@
],
"type": "SCALAR"
}
},
],
"asset": {
"generator": "obj2gltf",
"profile": {
"api": "WebGL",
"version": "1.0"
},
"version": "1.0"
"version": "2.0"
},
"buffers": {
"buffer": {
"buffers": [
{
"name": "buffer",
"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"
}
},
"bufferViews": {
"bufferView_vertex": {
"buffer": "buffer",
],
"bufferViews": [
{
"name": "bufferView_vertex",
"buffer": 0,
"byteLength": 2304,
"byteOffset": 0,
"target": 34962
},
"bufferView_index": {
"buffer": "buffer",
{
"name": "bufferView_index",
"buffer": 0,
"byteLength": 216,
"byteOffset": 2304,
"target": 34963
}
},
"extensionsUsed": [
"KHR_materials_common"
],
"images": {},
"materials": {
"Blue": {
"extensions": {
"KHR_materials_common": {
"technique": "PHONG",
"transparent": false,
"doubleSided": false,
"values": {
"ambient": [
0,
0,
0,
1
],
"diffuse": [
0,
0,
0.64,
1
],
"emission": [
0,
0,
0,
1
],
"specular": [
0.5,
0.5,
0.5,
1
],
"shininess": 96.078431,
"transparency": 1,
"transparent": false,
"doubleSided": false
}
}
}
"materials": [
{
"name": "Blue",
"pbrMetallicRoughness": {
"baseColorFactor": [
0,
0,
0.64,
1
],
"metallicFactor": 0,
"roughnessFactor": 0.903921569
},
"emissiveFactor": [
0,
0,
0
],
"alphaMode": "OPAQUE",
"doubleSided": false
},
"Green": {
"extensions": {
"KHR_materials_common": {
"technique": "PHONG",
"transparent": false,
"doubleSided": false,
"values": {
"ambient": [
0,
0,
0,
1
],
"diffuse": [
0,
0.64,
0,
1
],
"emission": [
0,
0,
0,
1
],
"specular": [
0.5,
0.5,
0.5,
1
],
"shininess": 96.078431,
"transparency": 1,
"transparent": false,
"doubleSided": false
}
}
}
{
"name": "Green",
"pbrMetallicRoughness": {
"baseColorFactor": [
0,
0.64,
0,
1
],
"metallicFactor": 0,
"roughnessFactor": 0.903921569
},
"emissiveFactor": [
0,
0,
0
],
"alphaMode": "OPAQUE",
"doubleSided": false
},
"Red": {
"extensions": {
"KHR_materials_common": {
"technique": "PHONG",
"transparent": false,
"doubleSided": false,
"values": {
"ambient": [
0,
0,
0,
1
],
"diffuse": [
0.64,
0,
0,
1
],
"emission": [
0,
0,
0,
1
],
"specular": [
0.5,
0.5,
0.5,
1
],
"shininess": 96.078431,
"transparency": 1,
"transparent": false,
"doubleSided": false
}
}
}
{
"name": "Red",
"pbrMetallicRoughness": {
"baseColorFactor": [
0.64,
0,
0,
1
],
"metallicFactor": 0,
"roughnessFactor": 0.903921569
},
"emissiveFactor": [
0,
0,
0
],
"alphaMode": "OPAQUE",
"doubleSided": false
}
},
"meshes": {
"CubeBlue_CubeBlue_Blue": {
"name": "CubeBlue_CubeBlue_Blue",
],
"meshes": [
{
"name": "Blue",
"primitives": [
{
"attributes": {
"POSITION": "accessor_0",
"NORMAL": "accessor_1",
"TEXCOORD_0": "accessor_2"
"POSITION": 0,
"NORMAL": 1,
"TEXCOORD_0": 2
},
"indices": "accessor_3",
"material": "Blue",
"indices": 3,
"material": 0,
"mode": 4
},
{
"attributes": {
"POSITION": "accessor_0",
"NORMAL": "accessor_1",
"TEXCOORD_0": "accessor_2"
"POSITION": 0,
"NORMAL": 1,
"TEXCOORD_0": 2
},
"indices": "accessor_4",
"material": "Green",
"indices": 4,
"material": 1,
"mode": 4
}
]
},
"CubeGreen_CubeGreen_Green": {
"name": "CubeGreen_CubeGreen_Green",
{
"name": "Green",
"primitives": [
{
"attributes": {
"POSITION": "accessor_5",
"NORMAL": "accessor_6",
"TEXCOORD_0": "accessor_7"
"POSITION": 5,
"NORMAL": 6,
"TEXCOORD_0": 7
},
"indices": "accessor_8",
"material": "Green",
"indices": 8,
"material": 1,
"mode": 4
},
{
"attributes": {
"POSITION": "accessor_5",
"NORMAL": "accessor_6",
"TEXCOORD_0": "accessor_7"
"POSITION": 5,
"NORMAL": 6,
"TEXCOORD_0": 7
},
"indices": "accessor_9",
"material": "Red",
"indices": 9,
"material": 2,
"mode": 4
}
]
},
"CubeRed_CubeRed_Red": {
"name": "CubeRed_CubeRed_Red",
{
"name": "Red",
"primitives": [
{
"attributes": {
"POSITION": "accessor_10",
"NORMAL": "accessor_11",
"TEXCOORD_0": "accessor_12"
"POSITION": 10,
"NORMAL": 11,
"TEXCOORD_0": 12
},
"indices": "accessor_13",
"material": "Red",
"indices": 13,
"material": 2,
"mode": 4
},
{
"attributes": {
"POSITION": "accessor_10",
"NORMAL": "accessor_11",
"TEXCOORD_0": "accessor_12"
"POSITION": 10,
"NORMAL": 11,
"TEXCOORD_0": 12
},
"indices": "accessor_14",
"material": "Blue",
"indices": 14,
"material": 0,
"mode": 4
}
]
}
},
"nodes": {
"Cube": {
],
"nodes": [
{
"name": "Cube",
"meshes": [
"CubeBlue_CubeBlue_Blue",
"CubeGreen_CubeGreen_Green",
"CubeRed_CubeRed_Red"
"children": [
1,
2,
3
]
},
{
"name": "Blue",
"mesh": 0
},
{
"name": "Green",
"mesh": 1
},
{
"name": "Red",
"mesh": 2
}
},
"samplers": {},
"scene": "scene",
"scenes": {
"scene": {
],
"scene": 0,
"scenes": [
{
"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 -1.0000 0.0000
vn 0.0000 1.0000 0.0000
g CubeBlue_CubeBlue_Blue
g Blue
usemtl Blue
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
@ -79,7 +79,7 @@ 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
g CubeGreen_CubeGreen_Green
g Green
usemtl Green
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
@ -122,7 +122,7 @@ 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
g CubeRed_CubeRed_Red
g Red
usemtl Red
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

View File

@ -1,9 +1,9 @@
{
"accessors": {
"accessor_0": {
"bufferView": "bufferView_vertex",
"accessors": [
{
"name": "Cube-Mesh_positions",
"bufferView": 0,
"byteOffset": 0,
"byteStride": 0,
"componentType": 5126,
"count": 24,
"min": [
@ -18,10 +18,10 @@
],
"type": "VEC3"
},
"accessor_1": {
"bufferView": "bufferView_vertex",
{
"name": "Cube-Mesh_normals",
"bufferView": 0,
"byteOffset": 288,
"byteStride": 0,
"componentType": 5126,
"count": 24,
"min": [
@ -36,10 +36,10 @@
],
"type": "VEC3"
},
"accessor_2": {
"bufferView": "bufferView_vertex",
{
"name": "Cube-Mesh_texcoords",
"bufferView": 0,
"byteOffset": 576,
"byteStride": 0,
"componentType": 5126,
"count": 24,
"min": [
@ -52,10 +52,10 @@
],
"type": "VEC2"
},
"accessor_3": {
"bufferView": "bufferView_index",
{
"name": "Cube-Mesh_0_indices",
"bufferView": 1,
"byteOffset": 0,
"byteStride": 0,
"componentType": 5123,
"count": 36,
"min": [
@ -66,113 +66,85 @@
],
"type": "SCALAR"
}
},
],
"asset": {
"generator": "obj2gltf",
"profile": {
"api": "WebGL",
"version": "1.0"
},
"version": "1.0"
"version": "2.0"
},
"buffers": {
"buffer": {
"buffers": [
{
"name": "buffer",
"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"
}
},
"bufferViews": {
"bufferView_vertex": {
"buffer": "buffer",
],
"bufferViews": [
{
"name": "bufferView_vertex",
"buffer": 0,
"byteLength": 768,
"byteOffset": 0,
"target": 34962
},
"bufferView_index": {
"buffer": "buffer",
{
"name": "bufferView_index",
"buffer": 0,
"byteLength": 72,
"byteOffset": 768,
"target": 34963
}
},
"extensionsUsed": [
"KHR_materials_common"
],
"images": {},
"materials": {
"Material": {
"extensions": {
"KHR_materials_common": {
"technique": "PHONG",
"transparent": false,
"doubleSided": false,
"values": {
"ambient": [
0,
0,
0,
1
],
"diffuse": [
0.64,
0.64,
0.64,
1
],
"emission": [
0,
0,
0,
1
],
"specular": [
0.5,
0.5,
0.5,
1
],
"shininess": 96.078431,
"transparency": 1,
"transparent": false,
"doubleSided": false
}
}
}
"materials": [
{
"name": "Material",
"pbrMetallicRoughness": {
"baseColorFactor": [
0.64,
0.64,
0.64,
1
],
"metallicFactor": 0,
"roughnessFactor": 0.903921569
},
"emissiveFactor": [
0,
0,
0
],
"alphaMode": "OPAQUE",
"doubleSided": false
}
},
"meshes": {
"Cube-Mesh": {
],
"meshes": [
{
"name": "Cube-Mesh",
"primitives": [
{
"attributes": {
"POSITION": "accessor_0",
"NORMAL": "accessor_1",
"TEXCOORD_0": "accessor_2"
"POSITION": 0,
"NORMAL": 1,
"TEXCOORD_0": 2
},
"indices": "accessor_3",
"material": "Material",
"indices": 3,
"material": 0,
"mode": 4
}
]
}
},
"nodes": {
"Cube": {
],
"nodes": [
{
"name": "Cube",
"meshes": [
"Cube-Mesh"
]
"mesh": 0
}
},
"samplers": {},
"scene": "scene",
"scenes": {
"scene": {
],
"scene": 0,
"scenes": [
{
"nodes": [
"Cube"
0
]
}
},
"textures": {}
}
]
}

View File

@ -26,9 +26,16 @@ var defaultOptions = obj2gltf.defaults;
var checkTransparencyOptions = clone(defaultOptions);
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() {
var boxObjData;
var duplicateBoxObjData;
var groupObjData;
var boxGltf;
var groupGltf;
@ -41,10 +48,6 @@ describe('createGltf', function() {
.then(function(data) {
boxObjData = data;
}),
loadObj(boxObjUrl, defaultOptions)
.then(function(data) {
duplicateBoxObjData = data;
}),
loadObj(groupObjUrl, defaultOptions)
.then(function(data) {
groupObjData = data;
@ -82,25 +85,69 @@ describe('createGltf', function() {
expect(writeUris(gltf, groupGltfUrl, path.dirname(groupGltfUrl), defaultOptions)
.then(function() {
expect(gltf).toEqual(groupGltf);
expect(Object.keys(gltf.materials).length).toBe(3);
expect(Object.keys(gltf.nodes).length).toBe(1);
expect(Object.keys(gltf.meshes).length).toBe(3);
expect(gltf.materials.length).toBe(3);
expect(gltf.nodes.length).toBe(4);
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
for (var id in gltf.meshes) {
if (gltf.meshes.hasOwnProperty(id)) {
var mesh = gltf.meshes[id];
expect(mesh.primitives.length).toBe(2);
}
var length = gltf.meshes.length;
for (var i = 0; i < length; ++i) {
var mesh = gltf.meshes[i];
expect(mesh.primitives.length).toBe(2);
}
}), done).toResolve();
});
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 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 values = kmc.values;
@ -110,12 +157,15 @@ describe('createGltf', function() {
expect(values.emission).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.transparency).toBe(1.0);
expect(values.transparent).toBe(false);
expect(values.doubleSided).toBe(false);
});
it('sets material for diffuse texture', function() {
var material = new Material();
material.diffuseTexture = diffuseTextureUrl;
boxObjData.materials.Material = material;
boxObjData.materials[0] = material;
boxObjData.images[diffuseTextureUrl] = diffuseTexture;
var gltf = createGltf(boxObjData, defaultOptions);
@ -154,7 +204,7 @@ describe('createGltf', function() {
it('sets material for alpha less than 1', function() {
var material = new Material();
material.alpha = 0.4;
boxObjData.materials.Material = material;
boxObjData.materials[0] = material;
var gltf = createGltf(boxObjData, defaultOptions);
var kmc = gltf.materials.Material.extensions.KHR_materials_common;
@ -169,7 +219,7 @@ describe('createGltf', function() {
var material = new Material();
material.diffuseTexture = diffuseTextureUrl;
material.alpha = 0.4;
boxObjData.materials.Material = material;
boxObjData.materials[0] = material;
boxObjData.images[diffuseTextureUrl] = diffuseTexture;
@ -185,7 +235,7 @@ describe('createGltf', function() {
it('sets material for transparent diffuse texture', function() {
var material = new Material();
material.diffuseTexture = transparentDiffuseTextureUrl;
boxObjData.materials.Material = material;
boxObjData.materials[0] = material;
boxObjData.images[transparentDiffuseTextureUrl] = transparentDiffuseTexture;
@ -202,7 +252,7 @@ describe('createGltf', function() {
var material = new Material();
material.specularColor = [0.1, 0.1, 0.2, 1];
material.specularShininess = 0.1;
boxObjData.materials.Material = material;
boxObjData.materials[0] = material;
var gltf = createGltf(boxObjData, defaultOptions);
var kmc = gltf.materials.Material.extensions.KHR_materials_common;
@ -217,7 +267,7 @@ describe('createGltf', function() {
var material = new Material();
material.diffuseTexture = diffuseTextureUrl;
boxObjData.materials.Material = material;
boxObjData.materials[0] = material;
boxObjData.images[diffuseTextureUrl] = diffuseTexture;
@ -231,10 +281,10 @@ describe('createGltf', function() {
it('sets default material when texture is missing', function() {
var material = new Material();
material.diffuseTexture = diffuseTextureUrl;
boxObjData.materials.Material = material;
boxObjData.materials[0] = material;
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]);
});
@ -244,8 +294,8 @@ describe('createGltf', function() {
// Creates a material called "default"
var gltf = createGltf(boxObjData, defaultOptions);
expect(gltf.materials.default).toBeDefined();
var kmc = gltf.materials.default.extensions.KHR_materials_common;
expect(gltf.materials[0].name).toBe('default');
var kmc = gltf.materials[0].extensions.KHR_materials_common;
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
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]);
});
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() {
boxObjData.nodes[0].meshes[0].normals.length = 0;

View File

@ -1,10 +1,7 @@
'use strict';
var Cesium = require('cesium');
var obj2gltf = require('../../lib/obj2gltf');
var loadImage = require('../../lib/loadImage');
var clone = Cesium.clone;
var pngImage = 'specs/data/box-complex-material/shininess.png';
var jpgImage = 'specs/data/box-complex-material/emission.jpg';
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 transparentImage = 'specs/data/box-complex-material/diffuse.png';
var defaultOptions = obj2gltf.defaults;
describe('loadImage', function() {
it('loads png image', function(done) {
expect(loadImage(pngImage, defaultOptions)
expect(loadImage(pngImage)
.then(function(info) {
expect(info.transparent).toBe(false);
expect(info.source).toBeDefined();
expect(info.extension).toBe('.png');
expect(info.path).toBe(pngImage);
expect(info.decoded).toBeUndefined();
expect(info.width).toBeUndefined();
expect(info.height).toBeUndefined();
}), done).toResolve();
});
it('loads jpg image', function(done) {
expect(loadImage(jpgImage, defaultOptions)
expect(loadImage(jpgImage)
.then(function(info) {
expect(info.transparent).toBe(false);
expect(info.source).toBeDefined();
expect(info.extension).toBe('.jpg');
expect(info.decoded).toBeUndefined();
expect(info.width).toBeUndefined();
expect(info.height).toBeUndefined();
}), done).toResolve();
});
it('loads jpeg image', function(done) {
expect(loadImage(jpegImage, defaultOptions)
expect(loadImage(jpegImage)
.then(function(info) {
expect(info.transparent).toBe(false);
expect(info.source).toBeDefined();
expect(info.extension).toBe('.jpeg');
expect(info.decoded).toBeUndefined();
expect(info.width).toBeUndefined();
expect(info.height).toBeUndefined();
}), done).toResolve();
});
it('loads gif image', function(done) {
expect(loadImage(gifImage, defaultOptions)
expect(loadImage(gifImage)
.then(function(info) {
expect(info.transparent).toBe(false);
expect(info.source).toBeDefined();
expect(info.extension).toBe('.gif');
expect(info.decoded).toBeUndefined();
expect(info.width).toBeUndefined();
expect(info.height).toBeUndefined();
}), done).toResolve();
});
it('loads grayscale image', function(done) {
expect(loadImage(grayscaleImage, defaultOptions)
expect(loadImage(grayscaleImage)
.then(function(info) {
expect(info.transparent).toBe(false);
expect(info.source).toBeDefined();
@ -61,19 +69,46 @@ describe('loadImage', function() {
});
it('loads image with alpha channel', function(done) {
expect(loadImage(transparentImage, defaultOptions)
expect(loadImage(transparentImage)
.then(function(info) {
expect(info.transparent).toBe(false);
}), done).toResolve();
});
it('loads image with checkTransparency flag', function(done) {
var options = clone(defaultOptions);
options.checkTransparency = true;
var options = {
checkTransparency : true
};
expect(loadImage(transparentImage, options)
.then(function(info) {
expect(info.transparent).toBe(true);
}), 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';
var path = require('path');
var loadMtl = require('../../lib/loadMtl');
var obj2gltf = require('../../lib/obj2gltf');
var complexMaterialUrl = 'specs/data/box-complex-material/box-complex-material.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);
}
var defaultOptions = obj2gltf.defaults;
describe('loadMtl', function() {
it('loads complex material', function(done) {
expect(loadMtl(complexMaterialUrl)
expect(loadMtl(complexMaterialUrl, defaultOptions)
.then(function(materials) {
var material = materials.Material;
expect(material).toBeDefined();
var material = materials[0];
expect(material.name).toBe('Material');
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.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) {
expect(loadMtl(multipleMaterialsUrl)
expect(loadMtl(multipleMaterialsUrl, defaultOptions)
.then(function(materials) {
expect(Object.keys(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]);
expect(materials.Blue.diffuseColor).toEqual([0.0, 0.0, 0.64, 1.0]);
expect(materials.length).toBe(3);
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();
});
});

View File

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

View File

@ -1,4 +1,5 @@
'use strict';
var Cesium = require('Cesium');
var fsExtra = require('fs-extra');
var GltfPipeline = require('gltf-pipeline').Pipeline;
var os = require('os');
@ -7,6 +8,8 @@ var Promise = require('bluebird');
var obj2gltf = require('../../lib/obj2gltf');
var writeUris = require('../../lib/writeUris');
var RuntimeError = Cesium.RuntimeError;
var objPath = 'specs/data/box-textured/box-textured.obj';
var gltfPath = 'specs/data/box-textured/box-textured.gltf';
var glbPath = 'specs/data/box-textured/box-textured.glb';
@ -37,7 +40,7 @@ describe('obj2gltf', function() {
var options = args[2];
expect(path.normalize(outputPath)).toEqual(path.normalize(gltfPath));
expect(gltf).toBeDefined();
expect(gltf.images.cesium).toBeDefined();
expect(gltf.images.length).toBe(1);
expect(options).toEqual({
basePath : tempDirectory,
createDirectory : false,
@ -131,9 +134,25 @@ describe('obj2gltf', function() {
}).toThrowDeveloperError();
});
it('rejects if gltfPath is undefined', function() {
it('throws if gltfPath is undefined', function() {
expect(function() {
obj2gltf(objPath, undefined);
}).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);
});
});