Merge branch 'master' into newmtl-without-name

This commit is contained in:
Sean Lilley 2019-02-10 09:45:46 -05:00
commit d979a93745
31 changed files with 1439 additions and 1975 deletions

View File

@ -1,6 +1,6 @@
{
"extends": "cesium/node",
"rules": {
"no-var": "off"
"no-unused-vars": ["error", {"args": "none"}]
}
}

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="JavaScriptSettings">
<option name="languageLevel" value="ES5" />
<option name="languageLevel" value="ES6" />
</component>
</project>

View File

@ -24,11 +24,11 @@ npm install -g obj2gltf
#### Converting an obj model to gltf:
```javascript
var obj2gltf = require('obj2gltf');
var fs = require('fs');
const obj2gltf = require('obj2gltf');
const fs = require('fs');
obj2gltf('model.obj')
.then(function(gltf) {
var data = Buffer.from(JSON.stringify(gltf));
const data = Buffer.from(JSON.stringify(gltf));
fs.writeFileSync('model.gltf', data);
});
```
@ -36,9 +36,9 @@ obj2gltf('model.obj')
#### Converting an obj model to glb
```javascript
var obj2gltf = require('obj2gltf');
var fs = require('fs');
var options = {
const obj2gltf = require('obj2gltf');
const fs = require('fs');
const options = {
binary : true
}
obj2gltf('model.obj', options)

View File

@ -1,19 +1,19 @@
#!/usr/bin/env node
'use strict';
var Cesium = require('cesium');
var fsExtra = require('fs-extra');
var path = require('path');
var yargs = require('yargs');
var obj2gltf = require('../lib/obj2gltf');
const Cesium = require('cesium');
const fsExtra = require('fs-extra');
const path = require('path');
const yargs = require('yargs');
const obj2gltf = require('../lib/obj2gltf');
var defaultValue = Cesium.defaultValue;
var defined = Cesium.defined;
const defaultValue = Cesium.defaultValue;
const defined = Cesium.defined;
var defaults = obj2gltf.defaults;
const defaults = obj2gltf.defaults;
var args = process.argv;
const args = process.argv;
var argv = yargs
const argv = yargs
.usage('Usage: node $0 -i inputPath -o outputPath')
.example('node $0 -i ./specs/data/box/box.obj -o box.gltf')
.help('h')
@ -135,18 +135,18 @@ if (defined(argv.metallicRoughnessOcclusionTexture) && defined(argv.specularGlos
process.exit(1);
}
var objPath = argv.input;
var gltfPath = argv.output;
const objPath = argv.input;
let gltfPath = argv.output;
var filename = defaultValue(gltfPath, objPath);
var name = path.basename(filename, path.extname(filename));
var outputDirectory = path.dirname(filename);
var binary = argv.binary || path.extname(filename).toLowerCase() === '.glb';
var extension = binary ? '.glb' : '.gltf';
const filename = defaultValue(gltfPath, objPath);
const name = path.basename(filename, path.extname(filename));
const outputDirectory = path.dirname(filename);
const binary = argv.binary || path.extname(filename).toLowerCase() === '.glb';
const extension = binary ? '.glb' : '.gltf';
gltfPath = path.join(outputDirectory, name + extension);
var overridingTextures = {
const overridingTextures = {
metallicRoughnessOcclusionTexture : argv.metallicRoughnessOcclusionTexture,
specularGlossinessTexture : argv.specularGlossinessTexture,
occlusionTexture : argv.occlusionTexture,
@ -156,7 +156,7 @@ var overridingTextures = {
alphaTexture : argv.alphaTexture
};
var options = {
const options = {
binary : binary,
separate : argv.separate,
separateTextures : argv.separateTextures,
@ -178,7 +178,7 @@ obj2gltf(objPath, options)
// gltf is a glb buffer
return fsExtra.outputFile(gltfPath, gltf);
}
var jsonOptions = {
const jsonOptions = {
spaces : 2
};
return fsExtra.outputJson(gltfPath, gltf, jsonOptions);

View File

@ -1,26 +1,26 @@
'use strict';
var Cesium = require('cesium');
var Promise = require('bluebird');
var child_process = require('child_process');
var fsExtra = require('fs-extra');
var gulp = require('gulp');
var Jasmine = require('jasmine');
var JasmineSpecReporter = require('jasmine-spec-reporter').SpecReporter;
var open = require('open');
var path = require('path');
var yargs = require('yargs');
const Cesium = require('cesium');
const Promise = require('bluebird');
const child_process = require('child_process');
const fsExtra = require('fs-extra');
const gulp = require('gulp');
const Jasmine = require('jasmine');
const JasmineSpecReporter = require('jasmine-spec-reporter').SpecReporter;
const open = require('open');
const path = require('path');
const yargs = require('yargs');
var defined = Cesium.defined;
var argv = yargs.argv;
const defined = Cesium.defined;
const argv = yargs.argv;
// Add third-party node module binaries to the system path
// since some tasks need to call them directly.
var environmentSeparator = process.platform === 'win32' ? ';' : ':';
var nodeBinaries = path.join(__dirname, 'node_modules', '.bin');
const environmentSeparator = process.platform === 'win32' ? ';' : ':';
const nodeBinaries = path.join(__dirname, 'node_modules', '.bin');
process.env.PATH += environmentSeparator + nodeBinaries;
var specFiles = ['**/*.js', '!node_modules/**', '!coverage/**', '!doc/**', '!bin/**'];
const specFiles = ['**/*.js', '!node_modules/**', '!coverage/**', '!doc/**', '!bin/**'];
module.exports = {
test: test,
@ -30,7 +30,7 @@ module.exports = {
};
function test(done) {
var jasmine = new Jasmine();
const jasmine = new Jasmine();
jasmine.loadConfigFile('specs/jasmine.json');
jasmine.addReporter(new JasmineSpecReporter({
displaySuccessfulSpec: !defined(argv.suppressPassed) || !argv.suppressPassed
@ -70,11 +70,11 @@ async function coverage() {
}
function cloc() {
var cmdLine;
var clocPath = path.join('node_modules', 'cloc', 'lib', 'cloc');
let cmdLine;
const clocPath = path.join('node_modules', 'cloc', 'lib', 'cloc');
//Run cloc on primary Source files only
var source = new Promise(function(resolve, reject) {
const source = new Promise(function(resolve, reject) {
cmdLine = 'perl ' + clocPath + ' --quiet --progress-rate=0' +
' lib/ bin/';

View File

@ -1,13 +1,13 @@
'use strict';
var Cesium = require('cesium');
const Cesium = require('cesium');
var ComponentDatatype = Cesium.ComponentDatatype;
const ComponentDatatype = Cesium.ComponentDatatype;
module.exports = ArrayStorage;
var initialLength = 1024; // 2^10
var doublingThreshold = 33554432; // 2^25 (~134 MB for a Float32Array)
var fixedExpansionLength = 33554432; // 2^25 (~134 MB for a Float32Array)
const initialLength = 1024; // 2^10
const doublingThreshold = 33554432; // 2^25 (~134 MB for a Float32Array)
const fixedExpansionLength = 33554432; // 2^25 (~134 MB for a Float32Array)
/**
* Provides expandable typed array storage for geometry data. This is preferable to JS arrays which are
@ -24,14 +24,14 @@ function ArrayStorage(componentDatatype) {
}
function resize(storage, length) {
var typedArray = ComponentDatatype.createTypedArray(storage.componentDatatype, length);
const typedArray = ComponentDatatype.createTypedArray(storage.componentDatatype, length);
typedArray.set(storage.typedArray);
storage.typedArray = typedArray;
}
ArrayStorage.prototype.push = function(value) {
var length = this.length;
var typedArrayLength = this.typedArray.length;
const length = this.length;
const typedArrayLength = this.typedArray.length;
if (length === 0) {
resize(this, initialLength);
@ -50,51 +50,51 @@ ArrayStorage.prototype.get = function(index) {
return this.typedArray[index];
};
var sizeOfUint16 = 2;
var sizeOfUint32 = 4;
var sizeOfFloat = 4;
const sizeOfUint16 = 2;
const sizeOfUint32 = 4;
const sizeOfFloat = 4;
ArrayStorage.prototype.toUint16Buffer = function() {
var length = this.length;
var typedArray = this.typedArray;
var paddedLength = length + ((length % 2 === 0) ? 0 : 1); // Round to next multiple of 2
var buffer = Buffer.alloc(paddedLength * sizeOfUint16);
for (var i = 0; i < length; ++i) {
const length = this.length;
const typedArray = this.typedArray;
const paddedLength = length + ((length % 2 === 0) ? 0 : 1); // Round to next multiple of 2
const buffer = Buffer.alloc(paddedLength * sizeOfUint16);
for (let i = 0; i < length; ++i) {
buffer.writeUInt16LE(typedArray[i], i * sizeOfUint16);
}
return buffer;
};
ArrayStorage.prototype.toUint32Buffer = function() {
var length = this.length;
var typedArray = this.typedArray;
var buffer = Buffer.alloc(length * sizeOfUint32);
for (var i = 0; i < length; ++i) {
const length = this.length;
const typedArray = this.typedArray;
const buffer = Buffer.alloc(length * sizeOfUint32);
for (let i = 0; i < length; ++i) {
buffer.writeUInt32LE(typedArray[i], i * sizeOfUint32);
}
return buffer;
};
ArrayStorage.prototype.toFloatBuffer = function() {
var length = this.length;
var typedArray = this.typedArray;
var buffer = Buffer.alloc(length * sizeOfFloat);
for (var i = 0; i < length; ++i) {
const length = this.length;
const typedArray = this.typedArray;
const buffer = Buffer.alloc(length * sizeOfFloat);
for (let i = 0; i < length; ++i) {
buffer.writeFloatLE(typedArray[i], i * sizeOfFloat);
}
return buffer;
};
ArrayStorage.prototype.getMinMax = function(components) {
var length = this.length;
var typedArray = this.typedArray;
var count = length / components;
var min = new Array(components).fill(Number.POSITIVE_INFINITY);
var max = new Array(components).fill(Number.NEGATIVE_INFINITY);
for (var i = 0; i < count; ++i) {
for (var j = 0; j < components; ++j) {
var index = i * components + j;
var value = typedArray[index];
const length = this.length;
const typedArray = this.typedArray;
const count = length / components;
const min = new Array(components).fill(Number.POSITIVE_INFINITY);
const max = new Array(components).fill(Number.NEGATIVE_INFINITY);
for (let i = 0; i < count; ++i) {
for (let j = 0; j < components; ++j) {
const index = i * components + j;
const value = typedArray[index];
min[j] = Math.min(min[j], value);
max[j] = Math.max(max[j], value);
}

View File

@ -1,12 +1,12 @@
'use strict';
var Cesium = require('cesium');
var getBufferPadded = require('./getBufferPadded');
var getDefaultMaterial = require('./loadMtl').getDefaultMaterial;
var Texture = require('./Texture');
const Cesium = require('cesium');
const getBufferPadded = require('./getBufferPadded');
const getDefaultMaterial = require('./loadMtl').getDefaultMaterial;
const Texture = require('./Texture');
var defaultValue = Cesium.defaultValue;
var defined = Cesium.defined;
var WebGLConstants = Cesium.WebGLConstants;
const defaultValue = Cesium.defaultValue;
const defined = Cesium.defined;
const WebGLConstants = Cesium.WebGLConstants;
module.exports = createGltf;
@ -20,14 +20,14 @@ module.exports = createGltf;
* @private
*/
function createGltf(objData, options) {
var nodes = objData.nodes;
var materials = objData.materials;
var name = objData.name;
const nodes = objData.nodes;
let materials = objData.materials;
const name = objData.name;
// Split materials used by primitives with different types of attributes
materials = splitIncompatibleMaterials(nodes, materials, options);
var gltf = {
const gltf = {
accessors : [],
asset : {},
buffers : [],
@ -53,7 +53,7 @@ function createGltf(objData, options) {
nodes : []
});
var bufferState = {
const bufferState = {
positionBuffers : [],
normalBuffers : [],
uvBuffers : [],
@ -64,24 +64,23 @@ function createGltf(objData, options) {
indexAccessors : []
};
var uint32Indices = requiresUint32Indices(nodes);
const uint32Indices = requiresUint32Indices(nodes);
var nodesLength = nodes.length;
for (var i = 0; i < nodesLength; ++i) {
var node = nodes[i];
var meshes = node.meshes;
var meshesLength = meshes.length;
var meshIndex;
const nodesLength = nodes.length;
for (let i = 0; i < nodesLength; ++i) {
const node = nodes[i];
const meshes = node.meshes;
const meshesLength = meshes.length;
if (meshesLength === 1) {
meshIndex = addMesh(gltf, materials, bufferState, uint32Indices, meshes[0], options);
const meshIndex = addMesh(gltf, materials, bufferState, uint32Indices, meshes[0], options);
addNode(gltf, node.name, meshIndex, undefined);
} else {
// Add meshes as child nodes
var parentIndex = addNode(gltf, node.name);
for (var j = 0; j < meshesLength; ++j) {
var mesh = meshes[j];
meshIndex = addMesh(gltf, materials, bufferState, uint32Indices, mesh, options);
const parentIndex = addNode(gltf, node.name);
for (let j = 0; j < meshesLength; ++j) {
const mesh = meshes[j];
const meshIndex = addMesh(gltf, materials, bufferState, uint32Indices, mesh, options);
addNode(gltf, mesh.name, meshIndex, parentIndex);
}
}
@ -112,16 +111,16 @@ function createGltf(objData, options) {
}
function addBufferView(gltf, buffers, accessors, byteStride, target) {
var length = buffers.length;
const length = buffers.length;
if (length === 0) {
return;
}
var bufferViewIndex = gltf.bufferViews.length;
var previousBufferView = gltf.bufferViews[bufferViewIndex - 1];
var byteOffset = defined(previousBufferView) ? previousBufferView.byteOffset + previousBufferView.byteLength : 0;
var byteLength = 0;
for (var i = 0; i < length; ++i) {
var accessor = gltf.accessors[accessors[i]];
const bufferViewIndex = gltf.bufferViews.length;
const previousBufferView = gltf.bufferViews[bufferViewIndex - 1];
const byteOffset = defined(previousBufferView) ? previousBufferView.byteOffset + previousBufferView.byteLength : 0;
let byteLength = 0;
for (let i = 0; i < length; ++i) {
const accessor = gltf.accessors[accessors[i]];
accessor.bufferView = bufferViewIndex;
accessor.byteOffset = byteLength;
byteLength += buffers[i].length;
@ -142,9 +141,9 @@ function addBuffers(gltf, bufferState, name) {
addBufferView(gltf, bufferState.uvBuffers, bufferState.uvAccessors, 8, WebGLConstants.ARRAY_BUFFER);
addBufferView(gltf, bufferState.indexBuffers, bufferState.indexAccessors, undefined, WebGLConstants.ELEMENT_ARRAY_BUFFER);
var buffers = [];
let buffers = [];
buffers = buffers.concat(bufferState.positionBuffers, bufferState.normalBuffers, bufferState.uvBuffers, bufferState.indexBuffers);
var buffer = getBufferPadded(Buffer.concat(buffers));
const buffer = getBufferPadded(Buffer.concat(buffers));
gltf.buffers.push({
name : name,
@ -158,10 +157,10 @@ function addBuffers(gltf, bufferState, name) {
}
function addTexture(gltf, texture) {
var imageName = texture.name;
var textureName = texture.name;
var imageIndex = gltf.images.length;
var textureIndex = gltf.textures.length;
const imageName = texture.name;
const textureName = texture.name;
const imageIndex = gltf.images.length;
const textureIndex = gltf.textures.length;
gltf.images.push({
name : imageName,
@ -180,11 +179,11 @@ function addTexture(gltf, texture) {
}
function getTexture(gltf, texture) {
var textureIndex;
var name = texture.name;
var textures = gltf.textures;
var length = textures.length;
for (var i = 0; i < length; ++i) {
let textureIndex;
const name = texture.name;
const textures = gltf.textures;
const length = textures.length;
for (let i = 0; i < length; ++i) {
if (textures[i].name === name) {
textureIndex = i;
break;
@ -209,15 +208,15 @@ function cloneMaterial(material, removeTextures) {
}
return material;
} else if (Array.isArray(material)) {
var length = material.length;
var clonedArray = new Array(length);
for (var i = 0; i < length; ++i) {
const length = material.length;
const clonedArray = new Array(length);
for (let i = 0; i < length; ++i) {
clonedArray[i] = cloneMaterial(material[i], removeTextures);
}
return clonedArray;
}
var clonedObject = {};
for (var name in material) {
const clonedObject = {};
for (const name in material) {
if (material.hasOwnProperty(name)) {
clonedObject[name] = cloneMaterial(material[name], removeTextures);
}
@ -226,9 +225,9 @@ function cloneMaterial(material, removeTextures) {
}
function resolveTextures(gltf, material) {
for (var name in material) {
for (const name in material) {
if (material.hasOwnProperty(name)) {
var property = material[name];
const property = material[name];
if (property instanceof Texture) {
material[name] = getTexture(gltf, property);
} else if (!Array.isArray(property) && (typeof property === 'object')) {
@ -240,7 +239,7 @@ function resolveTextures(gltf, material) {
function addGltfMaterial(gltf, material, options) {
resolveTextures(gltf, material);
var materialIndex = gltf.materials.length;
const materialIndex = gltf.materials.length;
if (options.unlit) {
if (!defined(material.extensions)) {
material.extensions = {};
@ -252,8 +251,8 @@ function addGltfMaterial(gltf, material, options) {
}
function getMaterialByName(materials, materialName) {
var materialsLength = materials.length;
for (var i = 0; i < materialsLength; ++i) {
const materialsLength = materials.length;
for (let i = 0; i < materialsLength; ++i) {
if (materials[i].name === materialName) {
return materials[i];
}
@ -261,8 +260,8 @@ function getMaterialByName(materials, materialName) {
}
function getMaterialIndex(materials, materialName) {
var materialsLength = materials.length;
for (var i = 0; i < materialsLength; ++i) {
const materialsLength = materials.length;
for (let i = 0; i < materialsLength; ++i) {
if (materials[i].name === materialName) {
return i;
}
@ -270,8 +269,8 @@ function getMaterialIndex(materials, materialName) {
}
function getOrCreateGltfMaterial(gltf, materials, materialName, options) {
var material = getMaterialByName(materials, materialName);
var materialIndex = getMaterialIndex(gltf.materials, materialName);
const material = getMaterialByName(materials, materialName);
let materialIndex = getMaterialIndex(gltf.materials, materialName);
if (!defined(materialIndex)) {
materialIndex = addGltfMaterial(gltf, material, options);
@ -286,8 +285,8 @@ function primitiveInfoMatch(a, b) {
}
function getSplitMaterialName(originalMaterialName, primitiveInfo, primitiveInfoByMaterial) {
var splitMaterialName = originalMaterialName;
var suffix = 2;
let splitMaterialName = originalMaterialName;
let suffix = 2;
while (defined(primitiveInfoByMaterial[splitMaterialName])) {
if (primitiveInfoMatch(primitiveInfo, primitiveInfoByMaterial[splitMaterialName])) {
break;
@ -298,34 +297,34 @@ function getSplitMaterialName(originalMaterialName, primitiveInfo, primitiveInfo
}
function splitIncompatibleMaterials(nodes, materials, options) {
var splitMaterials = [];
var primitiveInfoByMaterial = {};
var nodesLength = nodes.length;
for (var i = 0; i < nodesLength; ++i) {
var meshes = nodes[i].meshes;
var meshesLength = meshes.length;
for (var j = 0; j < meshesLength; ++j) {
var primitives = meshes[j].primitives;
var primitivesLength = primitives.length;
for (var k = 0; k < primitivesLength; ++k) {
var primitive = primitives[k];
var hasUvs = primitive.uvs.length > 0;
var hasNormals = primitive.normals.length > 0;
var primitiveInfo = {
const splitMaterials = [];
const primitiveInfoByMaterial = {};
const nodesLength = nodes.length;
for (let i = 0; i < nodesLength; ++i) {
const meshes = nodes[i].meshes;
const meshesLength = meshes.length;
for (let j = 0; j < meshesLength; ++j) {
const primitives = meshes[j].primitives;
const primitivesLength = primitives.length;
for (let k = 0; k < primitivesLength; ++k) {
const primitive = primitives[k];
const hasUvs = primitive.uvs.length > 0;
const hasNormals = primitive.normals.length > 0;
const primitiveInfo = {
hasUvs : hasUvs,
hasNormals : hasNormals
};
var originalMaterialName = defaultValue(primitive.material, 'default');
var splitMaterialName = getSplitMaterialName(originalMaterialName, primitiveInfo, primitiveInfoByMaterial);
const originalMaterialName = defaultValue(primitive.material, 'default');
const splitMaterialName = getSplitMaterialName(originalMaterialName, primitiveInfo, primitiveInfoByMaterial);
primitive.material = splitMaterialName;
primitiveInfoByMaterial[splitMaterialName] = primitiveInfo;
var splitMaterial = getMaterialByName(splitMaterials, splitMaterialName);
let splitMaterial = getMaterialByName(splitMaterials, splitMaterialName);
if (defined(splitMaterial)) {
continue;
}
var originalMaterial = getMaterialByName(materials, originalMaterialName);
const originalMaterial = getMaterialByName(materials, originalMaterialName);
if (defined(originalMaterial)) {
splitMaterial = cloneMaterial(originalMaterial, !hasUvs);
} else {
@ -340,11 +339,11 @@ function splitIncompatibleMaterials(nodes, materials, options) {
}
function addVertexAttribute(gltf, array, components, name) {
var count = array.length / components;
var minMax = array.getMinMax(components);
var type = (components === 3 ? 'VEC3' : 'VEC2');
const count = array.length / components;
const minMax = array.getMinMax(components);
const type = (components === 3 ? 'VEC3' : 'VEC2');
var accessor = {
const accessor = {
name : name,
componentType : WebGLConstants.FLOAT,
count : count,
@ -353,17 +352,17 @@ function addVertexAttribute(gltf, array, components, name) {
type : type
};
var accessorIndex = gltf.accessors.length;
const accessorIndex = gltf.accessors.length;
gltf.accessors.push(accessor);
return accessorIndex;
}
function addIndexArray(gltf, array, uint32Indices, name) {
var componentType = uint32Indices ? WebGLConstants.UNSIGNED_INT : WebGLConstants.UNSIGNED_SHORT;
var count = array.length;
var minMax = array.getMinMax(1);
const componentType = uint32Indices ? WebGLConstants.UNSIGNED_INT : WebGLConstants.UNSIGNED_SHORT;
const count = array.length;
const minMax = array.getMinMax(1);
var accessor = {
const accessor = {
name : name,
componentType : componentType,
count : count,
@ -372,22 +371,22 @@ function addIndexArray(gltf, array, uint32Indices, name) {
type : 'SCALAR'
};
var accessorIndex = gltf.accessors.length;
const accessorIndex = gltf.accessors.length;
gltf.accessors.push(accessor);
return accessorIndex;
}
function requiresUint32Indices(nodes) {
var nodesLength = nodes.length;
for (var i = 0; i < nodesLength; ++i) {
var meshes = nodes[i].meshes;
var meshesLength = meshes.length;
for (var j = 0; j < meshesLength; ++j) {
var primitives = meshes[j].primitives;
var primitivesLength = primitives.length;
for (var k = 0; k < primitivesLength; ++k) {
const nodesLength = nodes.length;
for (let i = 0; i < nodesLength; ++i) {
const meshes = nodes[i].meshes;
const meshesLength = meshes.length;
for (let j = 0; j < meshesLength; ++j) {
const primitives = meshes[j].primitives;
const primitivesLength = primitives.length;
for (let k = 0; k < primitivesLength; ++k) {
// Reserve the 65535 index for primitive restart
var vertexCount = primitives[k].positions.length / 3;
const vertexCount = primitives[k].positions.length / 3;
if (vertexCount > 65534) {
return true;
}
@ -398,33 +397,32 @@ function requiresUint32Indices(nodes) {
}
function addPrimitive(gltf, materials, bufferState, uint32Indices, mesh, primitive, index, options) {
var hasPositions = primitive.positions.length > 0;
var hasNormals = primitive.normals.length > 0;
var hasUVs = primitive.uvs.length > 0;
const hasPositions = primitive.positions.length > 0;
const hasNormals = primitive.normals.length > 0;
const hasUVs = primitive.uvs.length > 0;
var accessorIndex;
var attributes = {};
const attributes = {};
if (hasPositions) {
accessorIndex = addVertexAttribute(gltf, primitive.positions, 3, mesh.name + '_' + index + '_positions');
const accessorIndex = addVertexAttribute(gltf, primitive.positions, 3, mesh.name + '_' + index + '_positions');
attributes.POSITION = accessorIndex;
bufferState.positionBuffers.push(primitive.positions.toFloatBuffer());
bufferState.positionAccessors.push(accessorIndex);
}
if (hasNormals) {
accessorIndex = addVertexAttribute(gltf, primitive.normals, 3, mesh.name + '_' + index + '_normals');
const accessorIndex = addVertexAttribute(gltf, primitive.normals, 3, mesh.name + '_' + index + '_normals');
attributes.NORMAL = accessorIndex;
bufferState.normalBuffers.push(primitive.normals.toFloatBuffer());
bufferState.normalAccessors.push(accessorIndex);
}
if (hasUVs) {
accessorIndex = addVertexAttribute(gltf, primitive.uvs, 2, mesh.name + '_' + index + '_texcoords');
const accessorIndex = addVertexAttribute(gltf, primitive.uvs, 2, mesh.name + '_' + index + '_texcoords');
attributes.TEXCOORD_0 = accessorIndex;
bufferState.uvBuffers.push(primitive.uvs.toFloatBuffer());
bufferState.uvAccessors.push(accessorIndex);
}
var indexAccessorIndex = addIndexArray(gltf, primitive.indices, uint32Indices, mesh.name + '_' + index + '_indices');
var indexBuffer = uint32Indices ? primitive.indices.toUint32Buffer() : primitive.indices.toUint16Buffer();
const indexAccessorIndex = addIndexArray(gltf, primitive.indices, uint32Indices, mesh.name + '_' + index + '_indices');
const indexBuffer = uint32Indices ? primitive.indices.toUint32Buffer() : primitive.indices.toUint16Buffer();
bufferState.indexBuffers.push(indexBuffer);
bufferState.indexAccessors.push(indexAccessorIndex);
@ -434,7 +432,7 @@ function addPrimitive(gltf, materials, bufferState, uint32Indices, mesh, primiti
primitive.uvs = undefined;
primitive.indices = undefined;
var materialIndex = getOrCreateGltfMaterial(gltf, materials, primitive.material, options);
const materialIndex = getOrCreateGltfMaterial(gltf, materials, primitive.material, options);
return {
attributes : attributes,
@ -445,34 +443,34 @@ function addPrimitive(gltf, materials, bufferState, uint32Indices, mesh, primiti
}
function addMesh(gltf, materials, bufferState, uint32Indices, mesh, options) {
var gltfPrimitives = [];
var primitives = mesh.primitives;
var primitivesLength = primitives.length;
for (var i = 0; i < primitivesLength; ++i) {
const gltfPrimitives = [];
const primitives = mesh.primitives;
const primitivesLength = primitives.length;
for (let i = 0; i < primitivesLength; ++i) {
gltfPrimitives.push(addPrimitive(gltf, materials, bufferState, uint32Indices, mesh, primitives[i], i, options));
}
var gltfMesh = {
const gltfMesh = {
name : mesh.name,
primitives : gltfPrimitives
};
var meshIndex = gltf.meshes.length;
const meshIndex = gltf.meshes.length;
gltf.meshes.push(gltfMesh);
return meshIndex;
}
function addNode(gltf, name, meshIndex, parentIndex) {
var node = {
const node = {
name : name,
mesh : meshIndex
};
var nodeIndex = gltf.nodes.length;
const nodeIndex = gltf.nodes.length;
gltf.nodes.push(node);
if (defined(parentIndex)) {
var parentNode = gltf.nodes[parentIndex];
const parentNode = gltf.nodes[parentIndex];
if (!defined(parentNode.children)) {
parentNode.children = [];
}

View File

@ -10,13 +10,13 @@ module.exports = getBufferPadded;
* @private
*/
function getBufferPadded(buffer) {
var boundary = 4;
var byteLength = buffer.length;
var remainder = byteLength % boundary;
const boundary = 4;
const byteLength = buffer.length;
const remainder = byteLength % boundary;
if (remainder === 0) {
return buffer;
}
var padding = (remainder === 0) ? 0 : boundary - remainder;
var emptyBuffer = Buffer.alloc(padding);
const padding = (remainder === 0) ? 0 : boundary - remainder;
const emptyBuffer = Buffer.alloc(padding);
return Buffer.concat([buffer, emptyBuffer]);
}

View File

@ -13,14 +13,14 @@ module.exports = getJsonBufferPadded;
* @private
*/
function getJsonBufferPadded(json) {
var string = JSON.stringify(json);
let string = JSON.stringify(json);
var boundary = 4;
var byteLength = Buffer.byteLength(string);
var remainder = byteLength % boundary;
var padding = (remainder === 0) ? 0 : boundary - remainder;
var whitespace = '';
for (var i = 0; i < padding; ++i) {
const boundary = 4;
const byteLength = Buffer.byteLength(string);
const remainder = byteLength % boundary;
const padding = (remainder === 0) ? 0 : boundary - remainder;
let whitespace = '';
for (let i = 0; i < padding; ++i) {
whitespace += ' ';
}
string += whitespace;

View File

@ -1,8 +1,8 @@
'use strict';
var Cesium = require('cesium');
var getJsonBufferPadded = require('./getJsonBufferPadded');
const Cesium = require('cesium');
const getJsonBufferPadded = require('./getJsonBufferPadded');
var defined = Cesium.defined;
const defined = Cesium.defined;
module.exports = gltfToGlb;
@ -18,20 +18,20 @@ module.exports = gltfToGlb;
* @private
*/
function gltfToGlb(gltf, binaryBuffer) {
var buffer = gltf.buffers[0];
const buffer = gltf.buffers[0];
if (defined(buffer.uri)) {
binaryBuffer = Buffer.alloc(0);
}
// Create padded binary scene string
var jsonBuffer = getJsonBufferPadded(gltf);
const jsonBuffer = getJsonBufferPadded(gltf);
// Allocate buffer (Global header) + (JSON chunk header) + (JSON chunk) + (Binary chunk header) + (Binary chunk)
var glbLength = 12 + 8 + jsonBuffer.length + 8 + binaryBuffer.length;
var glb = Buffer.alloc(glbLength);
const glbLength = 12 + 8 + jsonBuffer.length + 8 + binaryBuffer.length;
const glb = Buffer.alloc(glbLength);
// Write binary glTF header (magic, version, length)
var byteOffset = 0;
let byteOffset = 0;
glb.writeUInt32LE(0x46546C67, byteOffset);
byteOffset += 4;
glb.writeUInt32LE(2, byteOffset);

View File

@ -1,16 +1,16 @@
'use strict';
var Cesium = require('cesium');
var path = require('path');
var Promise = require('bluebird');
var loadTexture = require('./loadTexture');
var outsideDirectory = require('./outsideDirectory');
var readLines = require('./readLines');
var Texture = require('./Texture');
const Cesium = require('cesium');
const path = require('path');
const Promise = require('bluebird');
const loadTexture = require('./loadTexture');
const outsideDirectory = require('./outsideDirectory');
const readLines = require('./readLines');
const Texture = require('./Texture');
var CesiumMath = Cesium.Math;
var combine = Cesium.combine;
var defaultValue = Cesium.defaultValue;
var defined = Cesium.defined;
const CesiumMath = Cesium.Math;
const combine = Cesium.combine;
const defaultValue = Cesium.defaultValue;
const defined = Cesium.defined;
module.exports = loadMtl;
@ -30,39 +30,39 @@ module.exports = loadMtl;
* @private
*/
function loadMtl(mtlPath, options) {
var material;
var values;
var value;
let material;
let values;
let value;
var mtlDirectory = path.dirname(mtlPath);
var materials = [];
var texturePromiseMap = {}; // Maps texture paths to load promises so that no texture is loaded twice
var texturePromises = [];
const mtlDirectory = path.dirname(mtlPath);
const materials = [];
const texturePromiseMap = {}; // Maps texture paths to load promises so that no texture is loaded twice
const texturePromises = [];
var overridingTextures = options.overridingTextures;
var overridingSpecularTexture = defaultValue(overridingTextures.metallicRoughnessOcclusionTexture, overridingTextures.specularGlossinessTexture);
var overridingSpecularShininessTexture = defaultValue(overridingTextures.metallicRoughnessOcclusionTexture, overridingTextures.specularGlossinessTexture);
var overridingAmbientTexture = defaultValue(overridingTextures.metallicRoughnessOcclusionTexture, overridingTextures.occlusionTexture);
var overridingNormalTexture = overridingTextures.normalTexture;
var overridingDiffuseTexture = overridingTextures.baseColorTexture;
var overridingEmissiveTexture = overridingTextures.emissiveTexture;
var overridingAlphaTexture = overridingTextures.alphaTexture;
const overridingTextures = options.overridingTextures;
const overridingSpecularTexture = defaultValue(overridingTextures.metallicRoughnessOcclusionTexture, overridingTextures.specularGlossinessTexture);
const overridingSpecularShininessTexture = defaultValue(overridingTextures.metallicRoughnessOcclusionTexture, overridingTextures.specularGlossinessTexture);
const overridingAmbientTexture = defaultValue(overridingTextures.metallicRoughnessOcclusionTexture, overridingTextures.occlusionTexture);
const overridingNormalTexture = overridingTextures.normalTexture;
const overridingDiffuseTexture = overridingTextures.baseColorTexture;
const overridingEmissiveTexture = overridingTextures.emissiveTexture;
const overridingAlphaTexture = overridingTextures.alphaTexture;
// Textures that are packed into PBR textures need to be decoded first
var decodeOptions = {
const decodeOptions = {
decode : true
};
var diffuseTextureOptions = {
const diffuseTextureOptions = {
checkTransparency : options.checkTransparency
};
var ambientTextureOptions = defined(overridingAmbientTexture) ? undefined : (options.packOcclusion ? decodeOptions : undefined);
var specularTextureOptions = defined(overridingSpecularTexture) ? undefined : decodeOptions;
var specularShinessTextureOptions = defined(overridingSpecularShininessTexture) ? undefined : decodeOptions;
var emissiveTextureOptions;
var normalTextureOptions;
var alphaTextureOptions = {
const ambientTextureOptions = defined(overridingAmbientTexture) ? undefined : (options.packOcclusion ? decodeOptions : undefined);
const specularTextureOptions = defined(overridingSpecularTexture) ? undefined : decodeOptions;
const specularShinessTextureOptions = defined(overridingSpecularShininessTexture) ? undefined : decodeOptions;
const emissiveTextureOptions = undefined;
const normalTextureOptions = undefined;
const alphaTextureOptions = {
decode : true
};
@ -83,7 +83,7 @@ function loadMtl(mtlPath, options) {
function normalizeTexturePath(texturePath, mtlDirectory) {
// Removes texture options from texture name
// Assumes no spaces in texture name
var re = /-(bm|t|s|o|blendu|blendv|boost|mm|texres|clamp|imfchan|type)/;
const re = /-(bm|t|s|o|blendu|blendv|boost|mm|texres|clamp|imfchan|type)/;
if (re.test(texturePath)) {
texturePath = texturePath.split(/\s+/).pop();
}
@ -94,7 +94,7 @@ function loadMtl(mtlPath, options) {
function parseLine(line) {
line = line.trim();
if (/^newmtl/i.test(line)) {
var name = line.substring(7).trim();
const name = line.substring(7).trim();
createMaterial(name);
} else if (/^Ka /i.test(line)) {
values = line.substring(3).trim().split(' ');
@ -170,7 +170,7 @@ function loadMtl(mtlPath, options) {
function loadMaterialTextures(material) {
// If an alpha texture is present the diffuse texture needs to be decoded so they can be packed together
var diffuseAlphaTextureOptions = defined(material.alphaTexture) ? alphaTextureOptions : diffuseTextureOptions;
const diffuseAlphaTextureOptions = defined(material.alphaTexture) ? alphaTextureOptions : diffuseTextureOptions;
if (material.diffuseTexture === material.ambientTexture) {
// OBJ models are often exported with the same texture in the diffuse and ambient slots but this is typically not desirable, particularly
@ -189,8 +189,8 @@ function loadMtl(mtlPath, options) {
return readLines(mtlPath, parseLine)
.then(function() {
var length = materials.length;
for (var i = 0; i < length; ++i) {
const length = materials.length;
for (let i = 0; i < length; ++i) {
loadMaterialTextures(materials[i]);
}
return Promise.all(texturePromises);
@ -232,14 +232,14 @@ loadMtl._createMaterial = function(materialOptions, options) {
};
function loadMaterialTexture(material, name, textureOptions, mtlDirectory, texturePromiseMap, texturePromises, options) {
var texturePath = material[name];
const texturePath = material[name];
if (!defined(texturePath)) {
return;
}
var texturePromise = texturePromiseMap[texturePath];
let texturePromise = texturePromiseMap[texturePath];
if (!defined(texturePromise)) {
var shallowPath = path.join(mtlDirectory, path.basename(texturePath));
const shallowPath = path.join(mtlDirectory, path.basename(texturePath));
if (options.secure && outsideDirectory(texturePath, mtlDirectory)) {
// Try looking for the texture in the same directory as the obj
options.logger('Texture file is outside of the mtl directory and the secure flag is true. Attempting to read the texture file from within the obj directory instead.');
@ -289,33 +289,33 @@ function convertMaterials(materials, options) {
function resizeChannel(sourcePixels, sourceWidth, sourceHeight, targetPixels, targetWidth, targetHeight) {
// Nearest neighbor sampling
var widthRatio = sourceWidth / targetWidth;
var heightRatio = sourceHeight / targetHeight;
const widthRatio = sourceWidth / targetWidth;
const heightRatio = sourceHeight / targetHeight;
for (var y = 0; y < targetHeight; ++y) {
for (var x = 0; x < targetWidth; ++x) {
var targetIndex = y * targetWidth + x;
var sourceY = Math.round(y * heightRatio);
var sourceX = Math.round(x * widthRatio);
var sourceIndex = sourceY * sourceWidth + sourceX;
var sourceValue = sourcePixels.readUInt8(sourceIndex);
for (let y = 0; y < targetHeight; ++y) {
for (let x = 0; x < targetWidth; ++x) {
const targetIndex = y * targetWidth + x;
const sourceY = Math.round(y * heightRatio);
const sourceX = Math.round(x * widthRatio);
const sourceIndex = sourceY * sourceWidth + sourceX;
const sourceValue = sourcePixels.readUInt8(sourceIndex);
targetPixels.writeUInt8(sourceValue, targetIndex);
}
}
return targetPixels;
}
var scratchResizeChannel;
let scratchResizeChannel;
function getTextureChannel(texture, index, targetWidth, targetHeight, targetChannel) {
var pixels = texture.pixels; // RGBA
var sourceWidth = texture.width;
var sourceHeight = texture.height;
var sourcePixelsLength = sourceWidth * sourceHeight;
var targetPixelsLength = targetWidth * targetHeight;
const pixels = texture.pixels; // RGBA
const sourceWidth = texture.width;
const sourceHeight = texture.height;
const sourcePixelsLength = sourceWidth * sourceHeight;
const targetPixelsLength = targetWidth * targetHeight;
// Allocate the scratchResizeChannel on demand if the texture needs to be resized
var sourceChannel = targetChannel;
let sourceChannel = targetChannel;
if (sourcePixelsLength > targetPixelsLength) {
if (!defined(scratchResizeChannel) || (sourcePixelsLength > scratchResizeChannel.length)) {
scratchResizeChannel = Buffer.alloc(sourcePixelsLength);
@ -323,8 +323,8 @@ function getTextureChannel(texture, index, targetWidth, targetHeight, targetChan
sourceChannel = scratchResizeChannel;
}
for (var i = 0; i < sourcePixelsLength; ++i) {
var value = pixels.readUInt8(i * 4 + index);
for (let i = 0; i < sourcePixelsLength; ++i) {
const value = pixels.readUInt8(i * 4 + index);
sourceChannel.writeUInt8(value, i);
}
@ -336,28 +336,26 @@ function getTextureChannel(texture, index, targetWidth, targetHeight, targetChan
}
function writeChannel(pixels, channel, index) {
var pixelsLength = pixels.length / 4;
for (var i = 0; i < pixelsLength; ++i) {
var value = channel.readUInt8(i);
const pixelsLength = pixels.length / 4;
for (let i = 0; i < pixelsLength; ++i) {
const value = channel.readUInt8(i);
pixels.writeUInt8(value, i * 4 + index);
}
}
function getMinimumDimensions(textures, options) {
var i;
var texture;
var width = Number.POSITIVE_INFINITY;
var height = Number.POSITIVE_INFINITY;
let width = Number.POSITIVE_INFINITY;
let height = Number.POSITIVE_INFINITY;
var length = textures.length;
for (i = 0; i < length; ++i) {
texture = textures[i];
const length = textures.length;
for (let i = 0; i < length; ++i) {
const texture = textures[i];
width = Math.min(texture.width, width);
height = Math.min(texture.height, height);
}
for (i = 0; i < length; ++i) {
texture = textures[i];
for (let i = 0; i < length; ++i) {
const texture = textures[i];
if (texture.width !== width || texture.height !== height) {
options.logger('Texture ' + texture.path + ' will be scaled from ' + texture.width + 'x' + texture.height + ' to ' + width + 'x' + height + '.');
}
@ -367,9 +365,9 @@ function getMinimumDimensions(textures, options) {
}
function isChannelSingleColor(buffer) {
var first = buffer.readUInt8(0);
var length = buffer.length;
for (var i = 1; i < length; ++i) {
const first = buffer.readUInt8(0);
const length = buffer.length;
for (let i = 1; i < length; ++i) {
if (buffer[i] !== first) {
return false;
}
@ -378,8 +376,8 @@ function isChannelSingleColor(buffer) {
}
function createDiffuseAlphaTexture(diffuseTexture, alphaTexture, options) {
var packDiffuse = defined(diffuseTexture);
var packAlpha = defined(alphaTexture);
const packDiffuse = defined(diffuseTexture);
const packAlpha = defined(alphaTexture);
if (!packDiffuse) {
return undefined;
@ -394,30 +392,30 @@ function createDiffuseAlphaTexture(diffuseTexture, alphaTexture, options) {
return diffuseTexture;
}
var packedTextures = [diffuseTexture, alphaTexture];
var dimensions = getMinimumDimensions(packedTextures, options);
var width = dimensions[0];
var height = dimensions[1];
var pixelsLength = width * height;
var pixels = Buffer.alloc(pixelsLength * 4, 0xFF); // Initialize with 4 channels
var scratchChannel = Buffer.alloc(pixelsLength);
const packedTextures = [diffuseTexture, alphaTexture];
const dimensions = getMinimumDimensions(packedTextures, options);
const width = dimensions[0];
const height = dimensions[1];
const pixelsLength = width * height;
const pixels = Buffer.alloc(pixelsLength * 4, 0xFF); // Initialize with 4 channels
const scratchChannel = Buffer.alloc(pixelsLength);
// Write into the R, G, B channels
var redChannel = getTextureChannel(diffuseTexture, 0, width, height, scratchChannel);
const redChannel = getTextureChannel(diffuseTexture, 0, width, height, scratchChannel);
writeChannel(pixels, redChannel, 0);
var greenChannel = getTextureChannel(diffuseTexture, 1, width, height, scratchChannel);
const greenChannel = getTextureChannel(diffuseTexture, 1, width, height, scratchChannel);
writeChannel(pixels, greenChannel, 1);
var blueChannel = getTextureChannel(diffuseTexture, 2, width, height, scratchChannel);
const blueChannel = getTextureChannel(diffuseTexture, 2, width, height, scratchChannel);
writeChannel(pixels, blueChannel, 2);
// First try reading the alpha component from the alpha channel, but if it is a single color read from the red channel instead.
var alphaChannel = getTextureChannel(alphaTexture, 3, width, height, scratchChannel);
let alphaChannel = getTextureChannel(alphaTexture, 3, width, height, scratchChannel);
if (isChannelSingleColor(alphaChannel)) {
alphaChannel = getTextureChannel(alphaTexture, 0, width, height, scratchChannel);
}
writeChannel(pixels, alphaChannel, 3);
var texture = new Texture();
const texture = new Texture();
texture.name = diffuseTexture.name;
texture.extension = '.png';
texture.pixels = pixels;
@ -433,9 +431,9 @@ function createMetallicRoughnessTexture(metallicTexture, roughnessTexture, occlu
return metallicTexture;
}
var packMetallic = defined(metallicTexture);
var packRoughness = defined(roughnessTexture);
var packOcclusion = defined(occlusionTexture) && options.packOcclusion;
const packMetallic = defined(metallicTexture);
const packRoughness = defined(roughnessTexture);
const packOcclusion = defined(occlusionTexture) && options.packOcclusion;
if (!packMetallic && !packRoughness) {
return undefined;
@ -456,43 +454,43 @@ function createMetallicRoughnessTexture(metallicTexture, roughnessTexture, occlu
return undefined;
}
var packedTextures = [metallicTexture, roughnessTexture, occlusionTexture].filter(function(texture) {
const packedTextures = [metallicTexture, roughnessTexture, occlusionTexture].filter(function(texture) {
return defined(texture) && defined(texture.pixels);
});
var dimensions = getMinimumDimensions(packedTextures, options);
var width = dimensions[0];
var height = dimensions[1];
var pixelsLength = width * height;
var pixels = Buffer.alloc(pixelsLength * 4, 0xFF); // Initialize with 4 channels, unused channels will be white
var scratchChannel = Buffer.alloc(pixelsLength);
const dimensions = getMinimumDimensions(packedTextures, options);
const width = dimensions[0];
const height = dimensions[1];
const pixelsLength = width * height;
const pixels = Buffer.alloc(pixelsLength * 4, 0xFF); // Initialize with 4 channels, unused channels will be white
const scratchChannel = Buffer.alloc(pixelsLength);
if (packMetallic) {
// Write into the B channel
var metallicChannel = getTextureChannel(metallicTexture, 0, width, height, scratchChannel);
const metallicChannel = getTextureChannel(metallicTexture, 0, width, height, scratchChannel);
writeChannel(pixels, metallicChannel, 2);
}
if (packRoughness) {
// Write into the G channel
var roughnessChannel = getTextureChannel(roughnessTexture, 0, width, height, scratchChannel);
const roughnessChannel = getTextureChannel(roughnessTexture, 0, width, height, scratchChannel);
writeChannel(pixels, roughnessChannel, 1);
}
if (packOcclusion) {
// Write into the R channel
var occlusionChannel = getTextureChannel(occlusionTexture, 0, width, height, scratchChannel);
const occlusionChannel = getTextureChannel(occlusionTexture, 0, width, height, scratchChannel);
writeChannel(pixels, occlusionChannel, 0);
}
var length = packedTextures.length;
var names = new Array(length);
for (var i = 0; i < length; ++i) {
const length = packedTextures.length;
const names = new Array(length);
for (let i = 0; i < length; ++i) {
names[i] = packedTextures[i].name;
}
var name = names.join('_');
const name = names.join('_');
var texture = new Texture();
const texture = new Texture();
texture.name = name;
texture.extension = '.png';
texture.pixels = pixels;
@ -507,8 +505,8 @@ function createSpecularGlossinessTexture(specularTexture, glossinessTexture, opt
return specularTexture;
}
var packSpecular = defined(specularTexture);
var packGlossiness = defined(glossinessTexture);
const packSpecular = defined(specularTexture);
const packGlossiness = defined(glossinessTexture);
if (!packSpecular && !packGlossiness) {
return undefined;
@ -524,41 +522,41 @@ function createSpecularGlossinessTexture(specularTexture, glossinessTexture, opt
return undefined;
}
var packedTextures = [specularTexture, glossinessTexture].filter(function(texture) {
const packedTextures = [specularTexture, glossinessTexture].filter(function(texture) {
return defined(texture) && defined(texture.pixels);
});
var dimensions = getMinimumDimensions(packedTextures, options);
var width = dimensions[0];
var height = dimensions[1];
var pixelsLength = width * height;
var pixels = Buffer.alloc(pixelsLength * 4, 0xFF); // Initialize with 4 channels, unused channels will be white
var scratchChannel = Buffer.alloc(pixelsLength);
const dimensions = getMinimumDimensions(packedTextures, options);
const width = dimensions[0];
const height = dimensions[1];
const pixelsLength = width * height;
const pixels = Buffer.alloc(pixelsLength * 4, 0xFF); // Initialize with 4 channels, unused channels will be white
const scratchChannel = Buffer.alloc(pixelsLength);
if (packSpecular) {
// Write into the R, G, B channels
var redChannel = getTextureChannel(specularTexture, 0, width, height, scratchChannel);
const redChannel = getTextureChannel(specularTexture, 0, width, height, scratchChannel);
writeChannel(pixels, redChannel, 0);
var greenChannel = getTextureChannel(specularTexture, 1, width, height, scratchChannel);
const greenChannel = getTextureChannel(specularTexture, 1, width, height, scratchChannel);
writeChannel(pixels, greenChannel, 1);
var blueChannel = getTextureChannel(specularTexture, 2, width, height, scratchChannel);
const blueChannel = getTextureChannel(specularTexture, 2, width, height, scratchChannel);
writeChannel(pixels, blueChannel, 2);
}
if (packGlossiness) {
// Write into the A channel
var glossinessChannel = getTextureChannel(glossinessTexture, 0, width, height, scratchChannel);
const glossinessChannel = getTextureChannel(glossinessTexture, 0, width, height, scratchChannel);
writeChannel(pixels, glossinessChannel, 3);
}
var length = packedTextures.length;
var names = new Array(length);
for (var i = 0; i < length; ++i) {
const length = packedTextures.length;
const names = new Array(length);
for (let i = 0; i < length; ++i) {
names[i] = packedTextures[i].name;
}
var name = names.join('_');
const name = names.join('_');
var texture = new Texture();
const texture = new Texture();
texture.name = name;
texture.extension = '.png';
texture.pixels = pixels;
@ -569,20 +567,20 @@ function createSpecularGlossinessTexture(specularTexture, glossinessTexture, opt
}
function createSpecularGlossinessMaterial(material, options) {
var emissiveTexture = material.emissiveTexture;
var normalTexture = material.normalTexture;
var occlusionTexture = material.ambientTexture;
var diffuseTexture = material.diffuseTexture;
var alphaTexture = material.alphaTexture;
var specularTexture = material.specularTexture;
var glossinessTexture = material.specularShininessTexture;
var specularGlossinessTexture = createSpecularGlossinessTexture(specularTexture, glossinessTexture, options);
var diffuseAlphaTexture = createDiffuseAlphaTexture(diffuseTexture, alphaTexture, options);
const emissiveTexture = material.emissiveTexture;
const normalTexture = material.normalTexture;
const occlusionTexture = material.ambientTexture;
const diffuseTexture = material.diffuseTexture;
const alphaTexture = material.alphaTexture;
const specularTexture = material.specularTexture;
const glossinessTexture = material.specularShininessTexture;
const specularGlossinessTexture = createSpecularGlossinessTexture(specularTexture, glossinessTexture, options);
const diffuseAlphaTexture = createDiffuseAlphaTexture(diffuseTexture, alphaTexture, options);
var emissiveFactor = material.emissiveColor.slice(0, 3);
var diffuseFactor = material.diffuseColor;
var specularFactor = material.specularColor.slice(0, 3);
var glossinessFactor = material.specularShininess;
let emissiveFactor = material.emissiveColor.slice(0, 3);
let diffuseFactor = material.diffuseColor;
let specularFactor = material.specularColor.slice(0, 3);
let glossinessFactor = material.specularShininess;
if (defined(emissiveTexture)) {
emissiveFactor = [1.0, 1.0, 1.0];
@ -600,11 +598,11 @@ function createSpecularGlossinessMaterial(material, options) {
glossinessFactor = 1.0;
}
var transparent = false;
let transparent = false;
if (defined(alphaTexture)) {
transparent = true;
} else {
var alpha = material.alpha;
const alpha = material.alpha;
diffuseFactor[3] = alpha;
transparent = alpha < 1.0;
}
@ -613,8 +611,8 @@ function createSpecularGlossinessMaterial(material, options) {
transparent = transparent || diffuseTexture.transparent;
}
var doubleSided = transparent;
var alphaMode = transparent ? 'BLEND' : 'OPAQUE';
const doubleSided = transparent;
const alphaMode = transparent ? 'BLEND' : 'OPAQUE';
return {
name : material.name,
@ -637,24 +635,24 @@ function createSpecularGlossinessMaterial(material, options) {
}
function createMetallicRoughnessMaterial(material, options) {
var emissiveTexture = material.emissiveTexture;
var normalTexture = material.normalTexture;
var occlusionTexture = material.ambientTexture;
var baseColorTexture = material.diffuseTexture;
var alphaTexture = material.alphaTexture;
var metallicTexture = material.specularTexture;
var roughnessTexture = material.specularShininessTexture;
var metallicRoughnessTexture = createMetallicRoughnessTexture(metallicTexture, roughnessTexture, occlusionTexture, options);
var diffuseAlphaTexture = createDiffuseAlphaTexture(baseColorTexture, alphaTexture, options);
const emissiveTexture = material.emissiveTexture;
const normalTexture = material.normalTexture;
let occlusionTexture = material.ambientTexture;
const baseColorTexture = material.diffuseTexture;
const alphaTexture = material.alphaTexture;
const metallicTexture = material.specularTexture;
const roughnessTexture = material.specularShininessTexture;
const metallicRoughnessTexture = createMetallicRoughnessTexture(metallicTexture, roughnessTexture, occlusionTexture, options);
const diffuseAlphaTexture = createDiffuseAlphaTexture(baseColorTexture, alphaTexture, options);
if (options.packOcclusion) {
occlusionTexture = metallicRoughnessTexture;
}
var emissiveFactor = material.emissiveColor.slice(0, 3);
var baseColorFactor = material.diffuseColor;
var metallicFactor = material.specularColor[0];
var roughnessFactor = material.specularShininess;
let emissiveFactor = material.emissiveColor.slice(0, 3);
let baseColorFactor = material.diffuseColor;
let metallicFactor = material.specularColor[0];
let roughnessFactor = material.specularShininess;
if (defined(emissiveTexture)) {
emissiveFactor = [1.0, 1.0, 1.0];
@ -672,11 +670,11 @@ function createMetallicRoughnessMaterial(material, options) {
roughnessFactor = 1.0;
}
var transparent = false;
let transparent = false;
if (defined(alphaTexture)) {
transparent = true;
} else {
var alpha = material.alpha;
const alpha = material.alpha;
baseColorFactor[3] = alpha;
transparent = alpha < 1.0;
}
@ -685,8 +683,8 @@ function createMetallicRoughnessMaterial(material, options) {
transparent = transparent || baseColorTexture.transparent;
}
var doubleSided = transparent;
var alphaMode = transparent ? 'BLEND' : 'OPAQUE';
const doubleSided = transparent;
const alphaMode = transparent ? 'BLEND' : 'OPAQUE';
return {
name : material.name,
@ -715,10 +713,10 @@ function convertTraditionalToMetallicRoughness(material) {
// Roughness factor is a combination of specular intensity and shininess
// Metallic factor is 0.0
// Textures are not converted for now
var specularIntensity = luminance(material.specularColor);
const specularIntensity = luminance(material.specularColor);
// Transform from 0-1000 range to 0-1 range. Then invert.
var roughnessFactor = material.specularShininess;
let roughnessFactor = material.specularShininess;
roughnessFactor = roughnessFactor / 1000.0;
roughnessFactor = 1.0 - roughnessFactor;
roughnessFactor = CesiumMath.clamp(roughnessFactor, 0.0, 1.0);
@ -728,7 +726,7 @@ function convertTraditionalToMetallicRoughness(material) {
roughnessFactor *= (1.0 - specularIntensity);
}
var metallicFactor = 0.0;
const metallicFactor = 0.0;
material.specularColor = [metallicFactor, metallicFactor, metallicFactor, 1.0];
material.specularShininess = roughnessFactor;

View File

@ -1,21 +1,21 @@
'use strict';
var Cesium = require('cesium');
var path = require('path');
var Promise = require('bluebird');
const Cesium = require('cesium');
const path = require('path');
const Promise = require('bluebird');
var ArrayStorage = require('./ArrayStorage');
var loadMtl = require('./loadMtl');
var outsideDirectory = require('./outsideDirectory');
var readLines = require('./readLines');
const ArrayStorage = require('./ArrayStorage');
const loadMtl = require('./loadMtl');
const outsideDirectory = require('./outsideDirectory');
const readLines = require('./readLines');
var Cartesian3 = Cesium.Cartesian3;
var ComponentDatatype = Cesium.ComponentDatatype;
var CoplanarPolygonGeometryLibrary = Cesium.CoplanarPolygonGeometryLibrary;
var defaultValue = Cesium.defaultValue;
var defined = Cesium.defined;
var PolygonPipeline = Cesium.PolygonPipeline;
var RuntimeError = Cesium.RuntimeError;
var WindingOrder = Cesium.WindingOrder;
const Cartesian3 = Cesium.Cartesian3;
const ComponentDatatype = Cesium.ComponentDatatype;
const CoplanarPolygonGeometryLibrary = Cesium.CoplanarPolygonGeometryLibrary;
const defaultValue = Cesium.defaultValue;
const defined = Cesium.defined;
const PolygonPipeline = Cesium.PolygonPipeline;
const RuntimeError = Cesium.RuntimeError;
const WindingOrder = Cesium.WindingOrder;
module.exports = loadObj;
@ -42,10 +42,10 @@ function Primitive() {
}
// OBJ regex patterns are modified from ThreeJS (https://github.com/mrdoob/three.js/blob/master/examples/js/loaders/OBJLoader.js)
var vertexPattern = /v( +[\d|\.|\+|\-|e|E]+)( +[\d|\.|\+|\-|e|E]+)( +[\d|\.|\+|\-|e|E]+)/; // v float float float
var normalPattern = /vn( +[\d|\.|\+|\-|e|E]+)( +[\d|\.|\+|\-|e|E]+)( +[\d|\.|\+|\-|e|E]+)/; // vn float float float
var uvPattern = /vt( +[\d|\.|\+|\-|e|E]+)( +[\d|\.|\+|\-|e|E]+)/; // vt float float
var facePattern = /(-?\d+)\/?(-?\d*)\/?(-?\d*)/g; // for any face format "f v", "f v/v", "f v//v", "f v/v/v"
const vertexPattern = /v( +[\d|\.|\+|\-|e|E]+)( +[\d|\.|\+|\-|e|E]+)( +[\d|\.|\+|\-|e|E]+)/; // v float float float
const normalPattern = /vn( +[\d|\.|\+|\-|e|E]+)( +[\d|\.|\+|\-|e|E]+)( +[\d|\.|\+|\-|e|E]+)/; // vn float float float
const uvPattern = /vt( +[\d|\.|\+|\-|e|E]+)( +[\d|\.|\+|\-|e|E]+)/; // vt float float
const facePattern = /(-?\d+)\/?(-?\d*)\/?(-?\d*)/g; // for any face format "f v", "f v/v", "f v//v", "f v/v/v"
/**
* Parse an obj file.
@ -58,36 +58,36 @@ var facePattern = /(-?\d+)\/?(-?\d*)\/?(-?\d*)/g;
*/
function loadObj(objPath, options) {
// Global store of vertex attributes listed in the obj file
var positions = new ArrayStorage(ComponentDatatype.FLOAT);
var normals = new ArrayStorage(ComponentDatatype.FLOAT);
var uvs = new ArrayStorage(ComponentDatatype.FLOAT);
let positions = new ArrayStorage(ComponentDatatype.FLOAT);
let normals = new ArrayStorage(ComponentDatatype.FLOAT);
let uvs = new ArrayStorage(ComponentDatatype.FLOAT);
// The current node, mesh, and primitive
var node;
var mesh;
var primitive;
var activeMaterial;
let node;
let mesh;
let primitive;
let activeMaterial;
// All nodes seen in the obj
var nodes = [];
const nodes = [];
// Used to build the indices. The vertex cache is unique to each primitive.
var vertexCache = {};
var vertexCacheLimit = 1000000;
var vertexCacheCount = 0;
var vertexCount = 0;
let vertexCache = {};
const vertexCacheLimit = 1000000;
let vertexCacheCount = 0;
let vertexCount = 0;
// All mtl paths seen in the obj
var mtlPaths = [];
let mtlPaths = [];
// Buffers for face data that spans multiple lines
var lineBuffer = '';
let lineBuffer = '';
// Used for parsing face data
var faceVertices = [];
var facePositions = [];
var faceUvs = [];
var faceNormals = [];
const faceVertices = [];
const facePositions = [];
const faceUvs = [];
const faceNormals = [];
function clearVertexCache() {
vertexCache = {};
@ -123,9 +123,9 @@ function loadObj(objPath, options) {
}
function reusePrimitive(callback) {
var primitives = mesh.primitives;
var primitivesLength = primitives.length;
for (var i = 0; i < primitivesLength; ++i) {
const primitives = mesh.primitives;
const primitivesLength = primitives.length;
for (let i = 0; i < primitivesLength; ++i) {
if (primitives[i].material === activeMaterial) {
if (!defined(callback) || callback(primitives[i])) {
primitive = primitives[i];
@ -144,15 +144,15 @@ function loadObj(objPath, options) {
}
function faceAndPrimitiveMatch(uvs, normals, primitive) {
var faceHasUvs = uvs[0].length > 0;
var faceHasNormals = normals[0].length > 0;
var primitiveHasUvs = primitive.uvs.length > 0;
var primitiveHasNormals = primitive.normals.length > 0;
const faceHasUvs = uvs[0].length > 0;
const faceHasNormals = normals[0].length > 0;
const primitiveHasUvs = primitive.uvs.length > 0;
const primitiveHasNormals = primitive.normals.length > 0;
return primitiveHasUvs === faceHasUvs && primitiveHasNormals === faceHasNormals;
}
function checkPrimitive(uvs, normals) {
var firstFace = primitive.indices.length === 0;
const firstFace = primitive.indices.length === 0;
if (!firstFace && !faceAndPrimitiveMatch(uvs, normals, primitive)) {
reusePrimitive(function(primitive) {
return faceAndPrimitiveMatch(uvs, normals, primitive);
@ -161,7 +161,7 @@ function loadObj(objPath, options) {
}
function getOffset(a, attributeData, components) {
var i = parseInt(a);
const i = parseInt(a);
if (i < 0) {
// Negative vertex indexes reference the vertices immediately above it
return (attributeData.length / components + i) * components;
@ -172,10 +172,10 @@ function loadObj(objPath, options) {
function createVertex(p, u, n) {
// Positions
if (p.length > 0) {
var pi = getOffset(p, positions, 3);
var px = positions.get(pi + 0);
var py = positions.get(pi + 1);
var pz = positions.get(pi + 2);
const pi = getOffset(p, positions, 3);
const px = positions.get(pi + 0);
const py = positions.get(pi + 1);
const pz = positions.get(pi + 2);
primitive.positions.push(px);
primitive.positions.push(py);
primitive.positions.push(pz);
@ -183,10 +183,10 @@ function loadObj(objPath, options) {
// Normals
if (n.length > 0) {
var ni = getOffset(n, normals, 3);
var nx = normals.get(ni + 0);
var ny = normals.get(ni + 1);
var nz = normals.get(ni + 2);
const ni = getOffset(n, normals, 3);
const nx = normals.get(ni + 0);
const ny = normals.get(ni + 1);
const nz = normals.get(ni + 2);
primitive.normals.push(nx);
primitive.normals.push(ny);
primitive.normals.push(nz);
@ -194,16 +194,16 @@ function loadObj(objPath, options) {
// UVs
if (u.length > 0) {
var ui = getOffset(u, uvs, 2);
var ux = uvs.get(ui + 0);
var uy = uvs.get(ui + 1);
const ui = getOffset(u, uvs, 2);
const ux = uvs.get(ui + 0);
const uy = uvs.get(ui + 1);
primitive.uvs.push(ux);
primitive.uvs.push(uy);
}
}
function addVertex(v, p, u, n) {
var index = vertexCache[v];
let index = vertexCache[v];
if (!defined(index)) {
index = vertexCount++;
vertexCache[v] = index;
@ -220,47 +220,47 @@ function loadObj(objPath, options) {
}
function getPosition(index, result) {
var pi = getOffset(index, positions, 3);
var px = positions.get(pi + 0);
var py = positions.get(pi + 1);
var pz = positions.get(pi + 2);
const pi = getOffset(index, positions, 3);
const px = positions.get(pi + 0);
const py = positions.get(pi + 1);
const pz = positions.get(pi + 2);
return Cartesian3.fromElements(px, py, pz, result);
}
function getNormal(index, result) {
var ni = getOffset(index, normals, 3);
var nx = normals.get(ni + 0);
var ny = normals.get(ni + 1);
var nz = normals.get(ni + 2);
const ni = getOffset(index, normals, 3);
const nx = normals.get(ni + 0);
const ny = normals.get(ni + 1);
const nz = normals.get(ni + 2);
return Cartesian3.fromElements(nx, ny, nz, result);
}
var scratch1 = new Cartesian3();
var scratch2 = new Cartesian3();
var scratch3 = new Cartesian3();
var scratch4 = new Cartesian3();
var scratch5 = new Cartesian3();
var scratchCenter = new Cartesian3();
var scratchAxis1 = new Cartesian3();
var scratchAxis2 = new Cartesian3();
var scratchNormal = new Cartesian3();
var scratchPositions = [new Cartesian3(), new Cartesian3(), new Cartesian3(), new Cartesian3()];
var scratchVertexIndices = [];
var scratchPoints = [];
const scratch1 = new Cartesian3();
const scratch2 = new Cartesian3();
const scratch3 = new Cartesian3();
const scratch4 = new Cartesian3();
const scratch5 = new Cartesian3();
const scratchCenter = new Cartesian3();
const scratchAxis1 = new Cartesian3();
const scratchAxis2 = new Cartesian3();
const scratchNormal = new Cartesian3();
const scratchPositions = [new Cartesian3(), new Cartesian3(), new Cartesian3(), new Cartesian3()];
const scratchVertexIndices = [];
const scratchPoints = [];
function checkWindingCorrect(positionIndex1, positionIndex2, positionIndex3, normalIndex) {
if (normalIndex.length === 0) {
// If no face normal, we have to assume the winding is correct.
return true;
}
var normal = getNormal(normalIndex, scratchNormal);
var A = getPosition(positionIndex1, scratch1);
var B = getPosition(positionIndex2, scratch2);
var C = getPosition(positionIndex3, scratch3);
const normal = getNormal(normalIndex, scratchNormal);
const A = getPosition(positionIndex1, scratch1);
const B = getPosition(positionIndex2, scratch2);
const C = getPosition(positionIndex3, scratch3);
var BA = Cartesian3.subtract(B, A, scratch4);
var CA = Cartesian3.subtract(C, A, scratch5);
var cross = Cartesian3.cross(BA, CA, scratch3);
const BA = Cartesian3.subtract(B, A, scratch4);
const CA = Cartesian3.subtract(C, A, scratch5);
const cross = Cartesian3.cross(BA, CA, scratch3);
return (Cartesian3.dot(normal, cross) >= 0);
}
@ -278,26 +278,23 @@ function loadObj(objPath, options) {
}
function addFace(vertices, positions, uvs, normals) {
var i;
var isWindingCorrect;
checkPrimitive(uvs, normals);
if (vertices.length === 3) {
isWindingCorrect = checkWindingCorrect(positions[0], positions[1], positions[2], normals[0]);
var index1 = addVertex(vertices[0], positions[0], uvs[0], normals[0]);
var index2 = addVertex(vertices[1], positions[1], uvs[1], normals[1]);
var index3 = addVertex(vertices[2], positions[2], uvs[2], normals[2]);
const isWindingCorrect = checkWindingCorrect(positions[0], positions[1], positions[2], normals[0]);
const index1 = addVertex(vertices[0], positions[0], uvs[0], normals[0]);
const index2 = addVertex(vertices[1], positions[1], uvs[1], normals[1]);
const index3 = addVertex(vertices[2], positions[2], uvs[2], normals[2]);
addTriangle(index1, index2, index3, isWindingCorrect);
} else { // Triangulate if the face is not a triangle
var points = scratchPoints;
var vertexIndices = scratchVertexIndices;
const points = scratchPoints;
const vertexIndices = scratchVertexIndices;
points.length = 0;
vertexIndices.length = 0;
for (i = 0; i < vertices.length; ++i) {
var index = addVertex(vertices[i], positions[i], uvs[i], normals[i]);
for (let i = 0; i < vertices.length; ++i) {
const index = addVertex(vertices[i], positions[i], uvs[i], normals[i]);
vertexIndices.push(index);
if (i === scratchPositions.length) {
scratchPositions.push(new Cartesian3());
@ -305,16 +302,16 @@ function loadObj(objPath, options) {
points.push(getPosition(positions[i], scratchPositions[i]));
}
var validGeometry = CoplanarPolygonGeometryLibrary.computeProjectTo2DArguments(points, scratchCenter, scratchAxis1, scratchAxis2);
const validGeometry = CoplanarPolygonGeometryLibrary.computeProjectTo2DArguments(points, scratchCenter, scratchAxis1, scratchAxis2);
if (!validGeometry) {
return;
}
var projectPoints = CoplanarPolygonGeometryLibrary.createProjectPointsTo2DFunction(scratchCenter, scratchAxis1, scratchAxis2);
var points2D = projectPoints(points);
var indices = PolygonPipeline.triangulate(points2D);
isWindingCorrect = PolygonPipeline.computeWindingOrder2D(points2D) !== WindingOrder.CLOCKWISE;
const projectPoints = CoplanarPolygonGeometryLibrary.createProjectPointsTo2DFunction(scratchCenter, scratchAxis1, scratchAxis2);
const points2D = projectPoints(points);
const indices = PolygonPipeline.triangulate(points2D);
const isWindingCorrect = PolygonPipeline.computeWindingOrder2D(points2D) !== WindingOrder.CLOCKWISE;
for (i = 0; i < indices.length - 2; i += 3) {
for (let i = 0; i < indices.length - 2; i += 3) {
addTriangle(vertexIndices[indices[i]], vertexIndices[indices[i+1]], vertexIndices[indices[i+2]], isWindingCorrect);
}
}
@ -322,28 +319,28 @@ function loadObj(objPath, options) {
function parseLine(line) {
line = line.trim();
var result;
let result;
if ((line.length === 0) || (line.charAt(0) === '#')) {
// Don't process empty lines or comments
} else if (/^o\s/i.test(line)) {
var objectName = line.substring(2).trim();
const objectName = line.substring(2).trim();
addNode(objectName);
} else if (/^g\s/i.test(line)) {
var groupName = line.substring(2).trim();
const groupName = line.substring(2).trim();
addMesh(groupName);
} else if (/^usemtl/i.test(line)) {
var materialName = line.substring(7).trim();
const materialName = line.substring(7).trim();
useMaterial(materialName);
} else if (/^mtllib/i.test(line)) {
var mtllibLine = line.substring(7).trim();
const mtllibLine = line.substring(7).trim();
mtlPaths = mtlPaths.concat(getMtlPaths(mtllibLine));
} else if ((result = vertexPattern.exec(line)) !== null) {
positions.push(parseFloat(result[1]));
positions.push(parseFloat(result[2]));
positions.push(parseFloat(result[3]));
} else if ((result = normalPattern.exec(line) ) !== null) {
var normal = Cartesian3.fromElements(parseFloat(result[1]), parseFloat(result[2]), parseFloat(result[3]), scratchNormal);
const normal = Cartesian3.fromElements(parseFloat(result[1]), parseFloat(result[2]), parseFloat(result[3]), scratchNormal);
if (Cartesian3.equals(normal, Cartesian3.ZERO)) {
Cartesian3.clone(Cartesian3.UNIT_Z, normal);
} else {
@ -404,15 +401,15 @@ function loadObj(objPath, options) {
function getMtlPaths(mtllibLine) {
// Handle paths with spaces. E.g. mtllib my material file.mtl
var mtlPaths = [];
var splits = mtllibLine.split(' ');
var length = splits.length;
var startIndex = 0;
for (var i = 0; i < length; ++i) {
const mtlPaths = [];
const splits = mtllibLine.split(' ');
const length = splits.length;
let startIndex = 0;
for (let i = 0; i < length; ++i) {
if (path.extname(splits[i]) !== '.mtl') {
continue;
}
var mtlPath = splits.slice(startIndex, i + 1).join(' ');
const mtlPath = splits.slice(startIndex, i + 1).join(' ');
mtlPaths.push(mtlPath);
startIndex = i + 1;
}
@ -424,7 +421,7 @@ function finishLoading(nodes, mtlPaths, objPath, usesMaterials, options) {
if (nodes.length === 0) {
throw new RuntimeError(objPath + ' does not have any geometry data');
}
var name = path.basename(objPath, path.extname(objPath));
const name = path.basename(objPath, path.extname(objPath));
return loadMtls(mtlPaths, objPath, options)
.then(function(materials) {
if (materials.length > 0 && !usesMaterials) {
@ -445,8 +442,8 @@ function normalizeMtlPath(mtlPath, objDirectory) {
}
function loadMtls(mtlPaths, objPath, options) {
var objDirectory = path.dirname(objPath);
var materials = [];
const objDirectory = path.dirname(objPath);
let materials = [];
// Remove duplicates
mtlPaths = mtlPaths.filter(function(value, index, self) {
@ -455,7 +452,7 @@ function loadMtls(mtlPaths, objPath, options) {
return Promise.map(mtlPaths, function(mtlPath) {
mtlPath = normalizeMtlPath(mtlPath, objDirectory);
var shallowPath = path.join(objDirectory, path.basename(mtlPath));
const shallowPath = path.join(objDirectory, path.basename(mtlPath));
if (options.secure && outsideDirectory(mtlPath, objDirectory)) {
// Try looking for the .mtl in the same directory as the obj
options.logger('The material file is outside of the obj directory and the secure flag is true. Attempting to read the material file from within the obj directory instead.');
@ -490,16 +487,16 @@ function loadMtls(mtlPaths, objPath, options) {
}
function assignDefaultMaterial(nodes, materials) {
var defaultMaterial = materials[0].name;
var nodesLength = nodes.length;
for (var i = 0; i < nodesLength; ++i) {
var meshes = nodes[i].meshes;
var meshesLength = meshes.length;
for (var j = 0; j < meshesLength; ++j) {
var primitives = meshes[j].primitives;
var primitivesLength = primitives.length;
for (var k = 0; k < primitivesLength; ++k) {
var primitive = primitives[k];
const defaultMaterial = materials[0].name;
const nodesLength = nodes.length;
for (let i = 0; i < nodesLength; ++i) {
const meshes = nodes[i].meshes;
const meshesLength = meshes.length;
for (let j = 0; j < meshesLength; ++j) {
const primitives = meshes[j].primitives;
const primitivesLength = primitives.length;
for (let k = 0; k < primitivesLength; ++k) {
const primitive = primitives[k];
primitive.material = defaultValue(primitive.material, defaultMaterial);
}
}
@ -509,7 +506,7 @@ function assignDefaultMaterial(nodes, materials) {
function assignUnnamedMaterial(nodes, materials) {
// If there is a material that doesn't have a name, assign that
// material to any primitives whose material is undefined.
var unnamedMaterial = materials.find(function(material) {
const unnamedMaterial = materials.find(function(material) {
return material.name.length === 0;
});
@ -517,15 +514,15 @@ function assignUnnamedMaterial(nodes, materials) {
return;
}
var nodesLength = nodes.length;
for (var i = 0; i < nodesLength; ++i) {
var meshes = nodes[i].meshes;
var meshesLength = meshes.length;
for (var j = 0; j < meshesLength; ++j) {
var primitives = meshes[j].primitives;
var primitivesLength = primitives.length;
for (var k = 0; k < primitivesLength; ++k) {
var primitive = primitives[k];
const nodesLength = nodes.length;
for (let i = 0; i < nodesLength; ++i) {
const meshes = nodes[i].meshes;
const meshesLength = meshes.length;
for (let j = 0; j < meshesLength; ++j) {
const primitives = meshes[j].primitives;
const primitivesLength = primitives.length;
for (let k = 0; k < primitivesLength; ++k) {
const primitive = primitives[k];
if (!defined(primitive.material)) {
primitive.material = unnamedMaterial.name;
}
@ -546,8 +543,8 @@ function removeEmptyMeshes(meshes) {
}
function meshesHaveNames(meshes) {
var meshesLength = meshes.length;
for (var i = 0; i < meshesLength; ++i) {
const meshesLength = meshes.length;
for (let i = 0; i < meshesLength; ++i) {
if (defined(meshes[i].name)) {
return true;
}
@ -556,21 +553,21 @@ function meshesHaveNames(meshes) {
}
function removeEmptyNodes(nodes) {
var final = [];
var nodesLength = nodes.length;
for (var i = 0; i < nodesLength; ++i) {
var node = nodes[i];
var meshes = removeEmptyMeshes(node.meshes);
const final = [];
const nodesLength = nodes.length;
for (let i = 0; i < nodesLength; ++i) {
const node = nodes[i];
const meshes = removeEmptyMeshes(node.meshes);
if (meshes.length === 0) {
continue;
}
node.meshes = meshes;
if (!defined(node.name) && meshesHaveNames(meshes)) {
// If the obj has groups (g) but not object groups (o) then convert meshes to nodes
var meshesLength = meshes.length;
for (var j = 0; j < meshesLength; ++j) {
var mesh = meshes[j];
var convertedNode = new Node();
const meshesLength = meshes.length;
for (let j = 0; j < meshesLength; ++j) {
const mesh = meshes[j];
const convertedNode = new Node();
convertedNode.name = mesh.name;
convertedNode.meshes = [mesh];
final.push(convertedNode);
@ -583,11 +580,11 @@ function removeEmptyNodes(nodes) {
}
function setDefaultNames(items, defaultName, usedNames) {
var itemsLength = items.length;
for (var i = 0; i < itemsLength; ++i) {
var item = items[i];
var name = defaultValue(item.name, defaultName);
var occurrences = usedNames[name];
const itemsLength = items.length;
for (let i = 0; i < itemsLength; ++i) {
const item = items[i];
let name = defaultValue(item.name, defaultName);
const occurrences = usedNames[name];
if (defined(occurrences)) {
usedNames[name]++;
name = name + '_' + occurrences;
@ -599,11 +596,11 @@ function setDefaultNames(items, defaultName, usedNames) {
}
function setDefaults(nodes) {
var usedNames = {};
const usedNames = {};
setDefaultNames(nodes, 'Node', usedNames);
var nodesLength = nodes.length;
for (var i = 0; i < nodesLength; ++i) {
var node = nodes[i];
const nodesLength = nodes.length;
for (let i = 0; i < nodesLength; ++i) {
const node = nodes[i];
setDefaultNames(node.meshes, node.name + '-Mesh', usedNames);
}
}

View File

@ -1,14 +1,14 @@
'use strict';
var Cesium = require('cesium');
var fsExtra = require('fs-extra');
var jpeg = require('jpeg-js');
var path = require('path');
var PNG = require('pngjs').PNG;
var Promise = require('bluebird');
var Texture = require('./Texture');
const Cesium = require('cesium');
const fsExtra = require('fs-extra');
const jpeg = require('jpeg-js');
const path = require('path');
const PNG = require('pngjs').PNG;
const Promise = require('bluebird');
const Texture = require('./Texture');
var defaultValue = Cesium.defaultValue;
var defined = Cesium.defined;
const defaultValue = Cesium.defaultValue;
const defined = Cesium.defined;
module.exports = loadTexture;
@ -30,15 +30,15 @@ function loadTexture(texturePath, options) {
return fsExtra.readFile(texturePath)
.then(function(source) {
var name = path.basename(texturePath, path.extname(texturePath));
var extension = path.extname(texturePath).toLowerCase();
var texture = new Texture();
const name = path.basename(texturePath, path.extname(texturePath));
const extension = path.extname(texturePath).toLowerCase();
const texture = new Texture();
texture.source = source;
texture.name = name;
texture.extension = extension;
texture.path = texturePath;
var decodePromise;
let decodePromise;
if (extension === '.png') {
decodePromise = decodePng(texture, options);
} else if (extension === '.jpg' || extension === '.jpeg') {
@ -54,8 +54,8 @@ function loadTexture(texturePath, options) {
}
function hasTransparency(pixels) {
var pixelsLength = pixels.length / 4;
for (var i = 0; i < pixelsLength; ++i) {
const pixelsLength = pixels.length / 4;
for (let i = 0; i < pixelsLength; ++i) {
if (pixels[i * 4 + 3] < 255) {
return true;
}
@ -92,12 +92,12 @@ function parsePng(data) {
function decodePng(texture, options) {
// Color type is encoded in the 25th bit of the png
var source = texture.source;
var colorType = source[25];
var channels = getChannels(colorType);
const source = texture.source;
const colorType = source[25];
const channels = getChannels(colorType);
var checkTransparency = (channels === 4 && options.checkTransparency);
var decode = options.decode || checkTransparency;
const checkTransparency = (channels === 4 && options.checkTransparency);
const decode = options.decode || checkTransparency;
if (decode) {
return parsePng(source)
@ -117,8 +117,8 @@ function decodePng(texture, options) {
function decodeJpeg(texture, options) {
if (options.decode) {
var source = texture.source;
var decodedResults = jpeg.decode(source);
const source = texture.source;
const decodedResults = jpeg.decode(source);
texture.pixels = decodedResults.data;
texture.width = decodedResults.width;
texture.height = decodedResults.height;

View File

@ -1,14 +1,14 @@
'use strict';
var Cesium = require('cesium');
var fsExtra = require('fs-extra');
var path = require('path');
var createGltf = require('./createGltf');
var loadObj = require('./loadObj');
var writeGltf = require('./writeGltf');
const Cesium = require('cesium');
const fsExtra = require('fs-extra');
const path = require('path');
const createGltf = require('./createGltf');
const loadObj = require('./loadObj');
const writeGltf = require('./writeGltf');
var defaultValue = Cesium.defaultValue;
var defined = Cesium.defined;
var DeveloperError = Cesium.DeveloperError;
const defaultValue = Cesium.defaultValue;
const defined = Cesium.defined;
const DeveloperError = Cesium.DeveloperError;
module.exports = obj2gltf;
@ -40,7 +40,7 @@ module.exports = obj2gltf;
* @return {Promise} A promise that resolves to the glTF JSON or glb buffer.
*/
function obj2gltf(objPath, options) {
var defaults = obj2gltf.defaults;
const defaults = obj2gltf.defaults;
options = defaultValue(options, {});
options.binary = defaultValue(options.binary, defaults.binary);
options.separate = defaultValue(options.separate, defaults.separate);
@ -100,7 +100,7 @@ function getDefaultLogger() {
function getDefaultWriter(outputDirectory) {
if (defined(outputDirectory)) {
return function(file, data) {
var outputFile = path.join(outputDirectory, file);
const outputFile = path.join(outputDirectory, file);
return fsExtra.outputFile(outputFile, data);
};
}

View File

@ -1,5 +1,5 @@
'use strict';
var path = require('path');
const path = require('path');
module.exports = outsideDirectory;

View File

@ -1,7 +1,7 @@
'use strict';
var fsExtra = require('fs-extra');
var Promise = require('bluebird');
var readline = require('readline');
const fsExtra = require('fs-extra');
const Promise = require('bluebird');
const readline = require('readline');
module.exports = readLines;
@ -16,11 +16,11 @@ module.exports = readLines;
*/
function readLines(path, callback) {
return new Promise(function(resolve, reject) {
var stream = fsExtra.createReadStream(path);
const stream = fsExtra.createReadStream(path);
stream.on('error', reject);
stream.on('end', resolve);
var lineReader = readline.createInterface({
const lineReader = readline.createInterface({
input : stream
});
lineReader.on('line', callback);

View File

@ -1,13 +1,13 @@
'use strict';
var Cesium = require('cesium');
var mime = require('mime');
var PNG = require('pngjs').PNG;
var Promise = require('bluebird');
var getBufferPadded = require('./getBufferPadded');
var gltfToGlb = require('./gltfToGlb');
const Cesium = require('cesium');
const mime = require('mime');
const PNG = require('pngjs').PNG;
const Promise = require('bluebird');
const getBufferPadded = require('./getBufferPadded');
const gltfToGlb = require('./gltfToGlb');
var defined = Cesium.defined;
var RuntimeError = Cesium.RuntimeError;
const defined = Cesium.defined;
const RuntimeError = Cesium.RuntimeError;
module.exports = writeGltf;
@ -23,11 +23,11 @@ module.exports = writeGltf;
function writeGltf(gltf, options) {
return encodeTextures(gltf)
.then(function() {
var binary = options.binary;
var separate = options.separate;
var separateTextures = options.separateTextures;
const binary = options.binary;
const separate = options.separate;
const separateTextures = options.separateTextures;
var promises = [];
const promises = [];
if (separateTextures) {
promises.push(writeSeparateTextures(gltf, options));
} else {
@ -40,7 +40,7 @@ function writeGltf(gltf, options) {
writeEmbeddedBuffer(gltf);
}
var binaryBuffer = gltf.buffers[0].extras._obj2gltf.source;
const binaryBuffer = gltf.buffers[0].extras._obj2gltf.source;
return Promise.all(promises)
.then(function() {
@ -56,10 +56,10 @@ function writeGltf(gltf, options) {
function encodePng(texture) {
// Constants defined by pngjs
var rgbColorType = 2;
var rgbaColorType = 6;
const rgbColorType = 2;
const rgbaColorType = 6;
var png = new PNG({
const png = new PNG({
width : texture.width,
height : texture.height,
colorType : texture.transparent ? rgbaColorType : rgbColorType,
@ -70,8 +70,8 @@ function encodePng(texture) {
png.data = texture.pixels;
return new Promise(function(resolve, reject) {
var chunks = [];
var stream = png.pack();
const chunks = [];
const stream = png.pack();
stream.on('data', function(chunk) {
chunks.push(chunk);
});
@ -93,22 +93,22 @@ function encodeTexture(texture) {
function encodeTextures(gltf) {
// Dynamically generated PBR textures need to be encoded to png prior to being saved
var encodePromises = [];
var images = gltf.images;
var length = images.length;
for (var i = 0; i < length; ++i) {
const encodePromises = [];
const images = gltf.images;
const length = images.length;
for (let i = 0; i < length; ++i) {
encodePromises.push(encodeTexture(images[i].extras._obj2gltf));
}
return Promise.all(encodePromises);
}
function deleteExtras(gltf) {
var buffer = gltf.buffers[0];
const buffer = gltf.buffers[0];
delete buffer.extras;
var images = gltf.images;
var imagesLength = images.length;
for (var i = 0; i < imagesLength; ++i) {
const images = gltf.images;
const imagesLength = images.length;
for (let i = 0; i < imagesLength; ++i) {
delete images[i].extras;
}
}
@ -124,26 +124,26 @@ function removeEmpty(json) {
}
function writeSeparateBuffer(gltf, options) {
var buffer = gltf.buffers[0];
var source = buffer.extras._obj2gltf.source;
var bufferUri = buffer.name + '.bin';
const buffer = gltf.buffers[0];
const source = buffer.extras._obj2gltf.source;
const bufferUri = buffer.name + '.bin';
buffer.uri = bufferUri;
return options.writer(bufferUri, source);
}
function writeSeparateTextures(gltf, options) {
var images = gltf.images;
const images = gltf.images;
return Promise.map(images, function(image) {
var texture = image.extras._obj2gltf;
var imageUri = image.name + texture.extension;
const texture = image.extras._obj2gltf;
const imageUri = image.name + texture.extension;
image.uri = imageUri;
return options.writer(imageUri, texture.source);
}, {concurrency : 10});
}
function writeEmbeddedBuffer(gltf) {
var buffer = gltf.buffers[0];
var source = buffer.extras._obj2gltf.source;
const buffer = gltf.buffers[0];
const source = buffer.extras._obj2gltf.source;
// Buffers larger than ~192MB cannot be base64 encoded due to a NodeJS limitation. Source: https://github.com/nodejs/node/issues/4266
if (source.length > 201326580) {
@ -154,19 +154,19 @@ function writeEmbeddedBuffer(gltf) {
}
function writeEmbeddedTextures(gltf) {
var buffer = gltf.buffers[0];
var bufferExtras = buffer.extras._obj2gltf;
var bufferSource = bufferExtras.source;
var images = gltf.images;
var imagesLength = images.length;
var sources = [bufferSource];
var byteOffset = bufferSource.length;
const buffer = gltf.buffers[0];
const bufferExtras = buffer.extras._obj2gltf;
const bufferSource = bufferExtras.source;
const images = gltf.images;
const imagesLength = images.length;
const sources = [bufferSource];
let byteOffset = bufferSource.length;
for (var i = 0; i < imagesLength; ++i) {
var image = images[i];
var texture = image.extras._obj2gltf;
var textureSource = texture.source;
var textureByteLength = textureSource.length;
for (let i = 0; i < imagesLength; ++i) {
const image = images[i];
const texture = image.extras._obj2gltf;
const textureSource = texture.source;
const textureByteLength = textureSource.length;
image.mimeType = mime.getType(texture.extension);
image.bufferView = gltf.bufferViews.length;
@ -179,7 +179,7 @@ function writeEmbeddedTextures(gltf) {
sources.push(textureSource);
}
var source = getBufferPadded(Buffer.concat(sources));
const source = getBufferPadded(Buffer.concat(sources));
bufferExtras.source = source;
buffer.byteLength = source.length;
}

View File

@ -26,24 +26,24 @@
"node": ">=4.0.0"
},
"dependencies": {
"bluebird": "^3.5.2",
"cesium": "^1.50.0",
"fs-extra": "^7.0.0",
"bluebird": "^3.5.3",
"cesium": "^1.54.0",
"fs-extra": "^7.0.1",
"jpeg-js": "^0.3.4",
"mime": "^2.3.1",
"mime": "^2.4.0",
"pngjs": "^3.3.3",
"yargs": "^12.0.2"
"yargs": "^12.0.5"
},
"devDependencies": {
"cloc": "^2.3.4",
"cloc": "^2.4.0",
"coveralls": "^3.0.2",
"eslint": "^5.6.1",
"eslint-config-cesium": "^6.0.0",
"eslint": "^5.13.0",
"eslint-config-cesium": "^6.0.1",
"gulp": "^4.0.0",
"jasmine": "^3.2.0",
"jasmine": "^3.3.1",
"jasmine-spec-reporter": "^4.2.1",
"jsdoc": "^3.5.5",
"nyc": "^13.0.1",
"nyc": "^13.2.0",
"open": "^0.0.5",
"requirejs": "^2.3.6"
},

View File

@ -2,5 +2,8 @@
"extends": "../.eslintrc.json",
"env": {
"jasmine": true
},
"rules": {
"no-restricted-globals": ["error", "fdescribe", "fit"]
}
}

View File

@ -2,8 +2,5 @@
"spec_dir": "specs",
"spec_files": [
"**/*Spec.js"
],
"helpers": [
"matchers/nodeHelper.js"
]
}

View File

@ -1,61 +1,43 @@
'use strict';
var Cesium = require('cesium');
var Promise = require('bluebird');
var obj2gltf = require('../../lib/obj2gltf');
var createGltf = require('../../lib/createGltf');
var loadObj = require('../../lib/loadObj');
var getDefaultMaterial = require('../../lib/loadMtl').getDefaultMaterial;
const Cesium = require('cesium');
const obj2gltf = require('../../lib/obj2gltf');
const createGltf = require('../../lib/createGltf');
const loadObj = require('../../lib/loadObj');
const { getDefaultMaterial } = require('../../lib/loadMtl');
var clone = Cesium.clone;
var defined = Cesium.defined;
var WebGLConstants = Cesium.WebGLConstants;
const clone = Cesium.clone;
const defined = Cesium.defined;
const WebGLConstants = Cesium.WebGLConstants;
var boxObjPath = 'specs/data/box/box.obj';
var groupObjPath = 'specs/data/box-objects-groups-materials/box-objects-groups-materials.obj';
var complexObjPath = 'specs/data/box-complex-material/box-complex-material.obj';
var noMaterialsObjPath = 'specs/data/box-no-materials/box-no-materials.obj';
var mixedAttributesObjPath = 'specs/data/box-mixed-attributes-2/box-mixed-attributes-2.obj';
const boxObjPath = 'specs/data/box/box.obj';
const groupObjPath = 'specs/data/box-objects-groups-materials/box-objects-groups-materials.obj';
const complexObjPath = 'specs/data/box-complex-material/box-complex-material.obj';
const noMaterialsObjPath = 'specs/data/box-no-materials/box-no-materials.obj';
const mixedAttributesObjPath = 'specs/data/box-mixed-attributes-2/box-mixed-attributes-2.obj';
var options;
let options;
describe('createGltf', function() {
var boxObjData;
var groupObjData;
var complexObjData;
var noMaterialsObjData;
var mixedAttributesObjData;
describe('createGltf', () => {
let boxObjData;
let groupObjData;
let complexObjData;
let noMaterialsObjData;
let mixedAttributesObjData;
beforeEach(function(done) {
beforeEach(async () => {
options = clone(obj2gltf.defaults);
options.overridingTextures = {};
options.logger = function() {};
options.logger = () => {};
return Promise.all([
loadObj(boxObjPath, options)
.then(function(data) {
boxObjData = data;
}),
loadObj(groupObjPath, options)
.then(function(data) {
groupObjData = data;
}),
loadObj(complexObjPath, options)
.then(function(data) {
complexObjData = data;
}),
loadObj(noMaterialsObjPath, options)
.then(function(data) {
noMaterialsObjData = data;
}),
loadObj(mixedAttributesObjPath, options)
.then(function(data) {
mixedAttributesObjData = data;
})
]).then(done);
boxObjData = await loadObj(boxObjPath, options);
groupObjData = await loadObj(groupObjPath, options);
complexObjData = await loadObj(complexObjPath, options);
noMaterialsObjData = await loadObj(noMaterialsObjPath, options);
mixedAttributesObjData = await loadObj(mixedAttributesObjPath, options);
});
it('simple gltf', function() {
var gltf = createGltf(boxObjData, options);
it('simple gltf', () => {
const gltf = createGltf(boxObjData, options);
expect(gltf.materials.length).toBe(1);
expect(gltf.scene).toBe(0);
@ -63,13 +45,13 @@ describe('createGltf', function() {
expect(gltf.nodes.length).toBe(1);
expect(gltf.meshes.length).toBe(1);
var primitives = gltf.meshes[0].primitives;
var primitive = primitives[0];
var attributes = primitive.attributes;
var positionAccessor = gltf.accessors[attributes.POSITION];
var normalAccessor = gltf.accessors[attributes.NORMAL];
var uvAccessor = gltf.accessors[attributes.TEXCOORD_0];
var indexAccessor = gltf.accessors[primitive.indices];
const primitives = gltf.meshes[0].primitives;
const primitive = primitives[0];
const attributes = primitive.attributes;
const positionAccessor = gltf.accessors[attributes.POSITION];
const normalAccessor = gltf.accessors[attributes.NORMAL];
const uvAccessor = gltf.accessors[attributes.TEXCOORD_0];
const indexAccessor = gltf.accessors[primitive.indices];
expect(primitives.length).toBe(1);
expect(positionAccessor.count).toBe(24);
@ -78,8 +60,8 @@ describe('createGltf', function() {
expect(indexAccessor.count).toBe(36);
});
it('multiple nodes, meshes, and primitives', function() {
var gltf = createGltf(groupObjData, options);
it('multiple nodes, meshes, and primitives', () => {
const gltf = createGltf(groupObjData, options);
expect(gltf.materials.length).toBe(3);
expect(gltf.scene).toBe(0);
@ -90,28 +72,28 @@ describe('createGltf', function() {
expect(gltf.meshes.length).toBe(3);
// Check for two primitives in each mesh
var length = gltf.meshes.length;
for (var i = 0; i < length; ++i) {
var mesh = gltf.meshes[i];
const length = gltf.meshes.length;
for (let i = 0; i < length; ++i) {
const mesh = gltf.meshes[i];
expect(mesh.primitives.length).toBe(2);
}
});
it('multiple textures', function() {
var gltf = createGltf(complexObjData, options);
var material = gltf.materials[0];
var pbr = material.pbrMetallicRoughness;
var textures = [pbr.metallicRoughnessTexture, pbr.baseColorTexture, material.emissiveTexture, material.normalTexture, material.occlusionTexture];
expect(textures.map(function(texture) {
it('multiple textures', () => {
const gltf = createGltf(complexObjData, options);
const material = gltf.materials[0];
const pbr = material.pbrMetallicRoughness;
const textures = [pbr.metallicRoughnessTexture, pbr.baseColorTexture, material.emissiveTexture, material.normalTexture, material.occlusionTexture];
expect(textures.map((texture) => {
return texture.index;
}).sort()).toEqual([0, 1, 2, 3, 4]);
expect(gltf.samplers[0]).toBeDefined();
});
it('creates default material', function() {
var gltf = createGltf(noMaterialsObjData, options);
var material = gltf.materials[0];
var pbr = material.pbrMetallicRoughness;
it('creates default material', () => {
const gltf = createGltf(noMaterialsObjData, options);
const material = gltf.materials[0];
const pbr = material.pbrMetallicRoughness;
expect(material.name).toBe('default');
expect(pbr.baseColorTexture).toBeUndefined();
expect(pbr.metallicRoughnessTexture).toBeUndefined();
@ -126,70 +108,70 @@ describe('createGltf', function() {
expect(material.doubleSided).toBe(false);
});
it('adds KHR_materials_pbrSpecularGlossiness extension when specularGlossiness is set', function() {
it('adds KHR_materials_pbrSpecularGlossiness extension when specularGlossiness is set', () => {
options.specularGlossiness = true;
var gltf = createGltf(noMaterialsObjData, options);
const gltf = createGltf(noMaterialsObjData, options);
expect(gltf.extensionsUsed).toEqual(['KHR_materials_pbrSpecularGlossiness']);
expect(gltf.extensionsRequired).toEqual(['KHR_materials_pbrSpecularGlossiness']);
});
it('adds KHR_materials_unlit extension when unlit is set', function() {
it('adds KHR_materials_unlit extension when unlit is set', () => {
options.unlit = true;
var gltf = createGltf(noMaterialsObjData, options);
const gltf = createGltf(noMaterialsObjData, options);
expect(gltf.extensionsUsed).toEqual(['KHR_materials_unlit']);
expect(gltf.extensionsRequired).toEqual(['KHR_materials_unlit']);
});
it('runs without normals', function() {
it('runs without normals', () => {
boxObjData.nodes[0].meshes[0].primitives[0].normals.length = 0;
var gltf = createGltf(boxObjData, options);
var attributes = gltf.meshes[0].primitives[0].attributes;
const gltf = createGltf(boxObjData, options);
const attributes = gltf.meshes[0].primitives[0].attributes;
expect(attributes.POSITION).toBeDefined();
expect(attributes.NORMAL).toBeUndefined();
expect(attributes.TEXCOORD_0).toBeDefined();
});
it('runs without uvs', function() {
it('runs without uvs', () => {
boxObjData.nodes[0].meshes[0].primitives[0].uvs.length = 0;
var gltf = createGltf(boxObjData, options);
var attributes = gltf.meshes[0].primitives[0].attributes;
const gltf = createGltf(boxObjData, options);
const attributes = gltf.meshes[0].primitives[0].attributes;
expect(attributes.POSITION).toBeDefined();
expect(attributes.NORMAL).toBeDefined();
expect(attributes.TEXCOORD_0).toBeUndefined();
});
it('runs without uvs and normals', function() {
it('runs without uvs and normals', () => {
boxObjData.nodes[0].meshes[0].primitives[0].normals.length = 0;
boxObjData.nodes[0].meshes[0].primitives[0].uvs.length = 0;
var gltf = createGltf(boxObjData, options);
var attributes = gltf.meshes[0].primitives[0].attributes;
const gltf = createGltf(boxObjData, options);
const attributes = gltf.meshes[0].primitives[0].attributes;
expect(attributes.POSITION).toBeDefined();
expect(attributes.NORMAL).toBeUndefined();
expect(attributes.TEXCOORD_0).toBeUndefined();
});
it('splits incompatible materials', function() {
var gltf = createGltf(mixedAttributesObjData, options);
var materials = gltf.materials;
var meshes = gltf.meshes;
it('splits incompatible materials', () => {
const gltf = createGltf(mixedAttributesObjData, options);
const materials = gltf.materials;
const meshes = gltf.meshes;
var referenceMaterial = mixedAttributesObjData.materials[0];
const referenceMaterial = mixedAttributesObjData.materials[0];
delete referenceMaterial.name;
referenceMaterial.pbrMetallicRoughness.baseColorTexture = {
index : 0
};
var referenceMaterialNoTextures = clone(referenceMaterial, true);
const referenceMaterialNoTextures = clone(referenceMaterial, true);
referenceMaterialNoTextures.pbrMetallicRoughness.baseColorTexture = undefined;
var defaultMaterial = getDefaultMaterial(options);
const defaultMaterial = getDefaultMaterial(options);
delete defaultMaterial.name;
var materialNames = materials.map(function(material) {
var name = material.name;
const materialNames = materials.map((material) => {
const name = material.name;
delete material.name;
return name;
});
@ -222,14 +204,14 @@ describe('createGltf', function() {
expect(materials[8]).toEqual(defaultMaterial);
// Test that primitives without uvs reference materials without textures
var meshesLength = meshes.length;
for (var i = 0; i < meshesLength; ++i) {
var mesh = meshes[i];
var primitives = mesh.primitives;
var primitivesLength = primitives.length;
for (var j = 0; j < primitivesLength; ++j) {
var primitive = primitives[j];
var material = materials[primitive.material];
const meshesLength = meshes.length;
for (let i = 0; i < meshesLength; ++i) {
const mesh = meshes[i];
const primitives = mesh.primitives;
const primitivesLength = primitives.length;
for (let j = 0; j < primitivesLength; ++j) {
const primitive = primitives[j];
const material = materials[primitive.material];
if (!defined(primitive.attributes.TEXCOORD_0)) {
expect(material.pbrMetallicRoughness.baseColorTexture).toBeUndefined();
}
@ -238,17 +220,17 @@ describe('createGltf', function() {
});
function expandObjData(objData, duplicatesLength) {
var primitive = objData.nodes[0].meshes[0].primitives[0];
var indices = primitive.indices;
var positions = primitive.positions;
var normals = primitive.normals;
var uvs = primitive.uvs;
const primitive = objData.nodes[0].meshes[0].primitives[0];
const indices = primitive.indices;
const positions = primitive.positions;
const normals = primitive.normals;
const uvs = primitive.uvs;
var indicesLength = indices.length;
var vertexCount = positions.length / 3;
const indicesLength = indices.length;
const vertexCount = positions.length / 3;
for (var i = 1; i < duplicatesLength; ++i) {
for (var j = 0; j < vertexCount; ++j) {
for (let i = 1; i < duplicatesLength; ++i) {
for (let j = 0; j < vertexCount; ++j) {
positions.push(0.0);
positions.push(0.0);
positions.push(0.0);
@ -258,26 +240,26 @@ describe('createGltf', function() {
uvs.push(0.0);
uvs.push(0.0);
}
for (var k = 0; k < indicesLength; ++k) {
for (let k = 0; k < indicesLength; ++k) {
indices.push(indices.get(k) + vertexCount * i);
}
}
}
it('detects need to use uint32 indices', function() {
it('detects need to use uint32 indices', () => {
expandObjData(boxObjData, 2731); // Right above 65536 limit
var primitive = boxObjData.nodes[0].meshes[0].primitives[0];
var indicesLength = primitive.indices.length;
var vertexCount = primitive.positions.length / 3;
let primitive = boxObjData.nodes[0].meshes[0].primitives[0];
const indicesLength = primitive.indices.length;
const vertexCount = primitive.positions.length / 3;
var gltf = createGltf(boxObjData, options);
const gltf = createGltf(boxObjData, options);
primitive = gltf.meshes[0].primitives[0];
var indicesAccessor = gltf.accessors[primitive.indices];
const indicesAccessor = gltf.accessors[primitive.indices];
expect(indicesAccessor.count).toBe(indicesLength);
expect(indicesAccessor.max[0]).toBe(vertexCount - 1);
expect(indicesAccessor.componentType).toBe(WebGLConstants.UNSIGNED_INT);
var positionAccessor = gltf.accessors[primitive.attributes.POSITION];
const positionAccessor = gltf.accessors[primitive.attributes.POSITION];
expect(positionAccessor.count).toBe(vertexCount);
});
});

View File

@ -1,271 +1,222 @@
'use strict';
var Cesium = require('cesium');
var Promise = require('bluebird');
var fsExtra = require('fs-extra');
var loadMtl = require('../../lib/loadMtl');
var loadTexture = require('../../lib/loadTexture');
var obj2gltf = require('../../lib/obj2gltf');
const Cesium = require('cesium');
const fsExtra = require('fs-extra');
const loadMtl = require('../../lib/loadMtl');
const loadTexture = require('../../lib/loadTexture');
const obj2gltf = require('../../lib/obj2gltf');
var clone = Cesium.clone;
const clone = Cesium.clone;
var coloredMaterialPath = 'specs/data/box/box.mtl';
var texturedMaterialPath = 'specs/data/box-complex-material/box-complex-material.mtl';
var texturedWithOptionsMaterialPath = 'specs/data/box-texture-options/box-texture-options.mtl';
var multipleMaterialsPath = 'specs/data/box-multiple-materials/box-multiple-materials.mtl';
var externalMaterialPath = 'specs/data/box-external-resources/box-external-resources.mtl';
var resourcesInRootMaterialPath = 'specs/data/box-resources-in-root/box-resources-in-root.mtl';
var externalInRootMaterialPath = 'specs/data/box-external-resources-in-root/box-external-resources-in-root.mtl';
var transparentMaterialPath = 'specs/data/box-transparent/box-transparent.mtl';
var diffuseAmbientSameMaterialPath = 'specs/data/box-diffuse-ambient-same/box-diffuse-ambient-same.mtl';
const coloredMaterialPath = 'specs/data/box/box.mtl';
const texturedMaterialPath = 'specs/data/box-complex-material/box-complex-material.mtl';
const texturedWithOptionsMaterialPath = 'specs/data/box-texture-options/box-texture-options.mtl';
const multipleMaterialsPath = 'specs/data/box-multiple-materials/box-multiple-materials.mtl';
const externalMaterialPath = 'specs/data/box-external-resources/box-external-resources.mtl';
const resourcesInRootMaterialPath = 'specs/data/box-resources-in-root/box-resources-in-root.mtl';
const externalInRootMaterialPath = 'specs/data/box-external-resources-in-root/box-external-resources-in-root.mtl';
const transparentMaterialPath = 'specs/data/box-transparent/box-transparent.mtl';
const diffuseAmbientSameMaterialPath = 'specs/data/box-diffuse-ambient-same/box-diffuse-ambient-same.mtl';
var diffuseTexturePath = 'specs/data/box-textured/cesium.png';
var transparentDiffuseTexturePath = 'specs/data/box-complex-material/diffuse.png';
var alphaTexturePath = 'specs/data/box-complex-material-alpha/alpha.png';
var ambientTexturePath = 'specs/data/box-complex-material/ambient.gif';
var normalTexturePath = 'specs/data/box-complex-material/bump.png';
var emissiveTexturePath = 'specs/data/box-complex-material/emission.jpg';
var specularTexturePath = 'specs/data/box-complex-material/specular.jpeg';
var specularShininessTexturePath = 'specs/data/box-complex-material/shininess.png';
const diffuseTexturePath = 'specs/data/box-textured/cesium.png';
const transparentDiffuseTexturePath = 'specs/data/box-complex-material/diffuse.png';
const alphaTexturePath = 'specs/data/box-complex-material-alpha/alpha.png';
const ambientTexturePath = 'specs/data/box-complex-material/ambient.gif';
const normalTexturePath = 'specs/data/box-complex-material/bump.png';
const emissiveTexturePath = 'specs/data/box-complex-material/emission.jpg';
const specularTexturePath = 'specs/data/box-complex-material/specular.jpeg';
const specularShininessTexturePath = 'specs/data/box-complex-material/shininess.png';
var diffuseTexture;
var transparentDiffuseTexture;
var alphaTexture;
var ambientTexture;
var normalTexture;
var emissiveTexture;
var specularTexture;
var specularShininessTexture;
let diffuseTexture;
let transparentDiffuseTexture;
let alphaTexture;
let ambientTexture;
let normalTexture;
let emissiveTexture;
let specularTexture;
let specularShininessTexture;
var checkTransparencyOptions = {
const checkTransparencyOptions = {
checkTransparency : true
};
var decodeOptions = {
const decodeOptions = {
decode : true
};
var options;
let options;
describe('loadMtl', function() {
beforeAll(function(done) {
return Promise.all([
loadTexture(diffuseTexturePath, decodeOptions)
.then(function(texture) {
diffuseTexture = texture;
}),
loadTexture(transparentDiffuseTexturePath, checkTransparencyOptions)
.then(function(texture) {
transparentDiffuseTexture = texture;
}),
loadTexture(alphaTexturePath, decodeOptions)
.then(function(texture) {
alphaTexture = texture;
}),
loadTexture(ambientTexturePath)
.then(function(texture) {
ambientTexture = texture;
}),
loadTexture(normalTexturePath)
.then(function(texture) {
normalTexture = texture;
}),
loadTexture(emissiveTexturePath)
.then(function(texture) {
emissiveTexture = texture;
}),
loadTexture(specularTexturePath, decodeOptions)
.then(function(texture) {
specularTexture = texture;
}),
loadTexture(specularShininessTexturePath, decodeOptions)
.then(function(texture) {
specularShininessTexture = texture;
})
]).then(done);
describe('loadMtl', () => {
beforeAll(async () => {
diffuseTexture = await loadTexture(diffuseTexturePath, decodeOptions);
transparentDiffuseTexture = await loadTexture(transparentDiffuseTexturePath, checkTransparencyOptions);
alphaTexture = await loadTexture(alphaTexturePath, decodeOptions);
ambientTexture = await loadTexture(ambientTexturePath);
normalTexture = await loadTexture(normalTexturePath);
emissiveTexture = await loadTexture(emissiveTexturePath);
specularTexture = await loadTexture(specularTexturePath, decodeOptions);
specularShininessTexture = await loadTexture(specularShininessTexturePath, decodeOptions);
});
beforeEach(function() {
beforeEach(() => {
options = clone(obj2gltf.defaults);
options.overridingTextures = {};
options.logger = function() {};
options.logger = () => {};
options.hasNormals = true;
});
it('loads mtl', function(done) {
it('loads mtl', async () => {
options.metallicRoughness = true;
expect(loadMtl(coloredMaterialPath, options)
.then(function(materials) {
expect(materials.length).toBe(1);
var material = materials[0];
var pbr = material.pbrMetallicRoughness;
expect(pbr.baseColorTexture).toBeUndefined();
expect(pbr.metallicRoughnessTexture).toBeUndefined();
expect(pbr.baseColorFactor).toEqual([0.64, 0.64, 0.64, 1.0]);
expect(pbr.metallicFactor).toBe(0.5);
expect(pbr.roughnessFactor).toBe(96.078431);
expect(material.name).toBe('Material');
expect(material.emissiveTexture).toBeUndefined();
expect(material.normalTexture).toBeUndefined();
expect(material.ambientTexture).toBeUndefined();
expect(material.emissiveFactor).toEqual([0.0, 0.0, 0.1]);
expect(material.alphaMode).toBe('OPAQUE');
expect(material.doubleSided).toBe(false);
}), done).toResolve();
const materials = await loadMtl(coloredMaterialPath, options);
expect(materials.length).toBe(1);
const material = materials[0];
const pbr = material.pbrMetallicRoughness;
expect(pbr.baseColorTexture).toBeUndefined();
expect(pbr.metallicRoughnessTexture).toBeUndefined();
expect(pbr.baseColorFactor).toEqual([0.64, 0.64, 0.64, 1.0]);
expect(pbr.metallicFactor).toBe(0.5);
expect(pbr.roughnessFactor).toBe(96.078431);
expect(material.name).toBe('Material');
expect(material.emissiveTexture).toBeUndefined();
expect(material.normalTexture).toBeUndefined();
expect(material.ambientTexture).toBeUndefined();
expect(material.emissiveFactor).toEqual([0.0, 0.0, 0.1]);
expect(material.alphaMode).toBe('OPAQUE');
expect(material.doubleSided).toBe(false);
});
it('loads mtl with textures', function(done) {
it('loads mtl with textures', async () => {
options.metallicRoughness = true;
expect(loadMtl(texturedMaterialPath, options)
.then(function(materials) {
expect(materials.length).toBe(1);
var material = materials[0];
var pbr = material.pbrMetallicRoughness;
expect(pbr.baseColorTexture).toBeDefined();
expect(pbr.metallicRoughnessTexture).toBeDefined();
expect(pbr.baseColorFactor).toEqual([1.0, 1.0, 1.0, 0.9]);
expect(pbr.metallicFactor).toBe(1.0);
expect(pbr.roughnessFactor).toBe(1.0);
expect(material.name).toBe('Material');
expect(material.emissiveTexture).toBeDefined();
expect(material.normalTexture).toBeDefined();
expect(material.occlusionTexture).toBeDefined();
expect(material.emissiveFactor).toEqual([1.0, 1.0, 1.0]);
expect(material.alphaMode).toBe('BLEND');
expect(material.doubleSided).toBe(true);
}), done).toResolve();
const materials = await loadMtl(texturedMaterialPath, options);
expect(materials.length).toBe(1);
const material = materials[0];
const pbr = material.pbrMetallicRoughness;
expect(pbr.baseColorTexture).toBeDefined();
expect(pbr.metallicRoughnessTexture).toBeDefined();
expect(pbr.baseColorFactor).toEqual([1.0, 1.0, 1.0, 0.9]);
expect(pbr.metallicFactor).toBe(1.0);
expect(pbr.roughnessFactor).toBe(1.0);
expect(material.name).toBe('Material');
expect(material.emissiveTexture).toBeDefined();
expect(material.normalTexture).toBeDefined();
expect(material.occlusionTexture).toBeDefined();
expect(material.emissiveFactor).toEqual([1.0, 1.0, 1.0]);
expect(material.alphaMode).toBe('BLEND');
expect(material.doubleSided).toBe(true);
});
it('loads mtl with textures having options', function(done) {
it('loads mtl with textures having options', async () => {
options.metallicRoughness = true;
expect(loadMtl(texturedWithOptionsMaterialPath, options)
.then(function(materials) {
expect(materials.length).toBe(1);
var material = materials[0];
var pbr = material.pbrMetallicRoughness;
expect(pbr.baseColorTexture).toBeDefined();
expect(pbr.metallicRoughnessTexture).toBeDefined();
expect(pbr.baseColorFactor).toEqual([1.0, 1.0, 1.0, 0.9]);
expect(pbr.metallicFactor).toBe(1.0);
expect(pbr.roughnessFactor).toBe(1.0);
expect(material.name).toBe('Material');
expect(material.emissiveTexture).toBeDefined();
expect(material.normalTexture).toBeDefined();
expect(material.occlusionTexture).toBeDefined();
expect(material.emissiveFactor).toEqual([1.0, 1.0, 1.0]);
expect(material.alphaMode).toBe('BLEND');
expect(material.doubleSided).toBe(true);
}), done).toResolve();
const materials = await loadMtl(texturedWithOptionsMaterialPath, options);
expect(materials.length).toBe(1);
const material = materials[0];
const pbr = material.pbrMetallicRoughness;
expect(pbr.baseColorTexture).toBeDefined();
expect(pbr.metallicRoughnessTexture).toBeDefined();
expect(pbr.baseColorFactor).toEqual([1.0, 1.0, 1.0, 0.9]);
expect(pbr.metallicFactor).toBe(1.0);
expect(pbr.roughnessFactor).toBe(1.0);
expect(material.name).toBe('Material');
expect(material.emissiveTexture).toBeDefined();
expect(material.normalTexture).toBeDefined();
expect(material.occlusionTexture).toBeDefined();
expect(material.emissiveFactor).toEqual([1.0, 1.0, 1.0]);
expect(material.alphaMode).toBe('BLEND');
expect(material.doubleSided).toBe(true);
});
it('loads mtl with multiple materials', function(done) {
it('loads mtl with multiple materials', async () => {
options.metallicRoughness = true;
expect(loadMtl(multipleMaterialsPath, options)
.then(function(materials) {
expect(materials.length).toBe(3);
expect(materials[0].name).toBe('Blue');
expect(materials[0].pbrMetallicRoughness.baseColorFactor).toEqual([0.0, 0.0, 0.64, 1.0]);
expect(materials[1].name).toBe('Green');
expect(materials[1].pbrMetallicRoughness.baseColorFactor).toEqual([0.0, 0.64, 0.0, 1.0]);
expect(materials[2].name).toBe('Red');
expect(materials[2].pbrMetallicRoughness.baseColorFactor).toEqual([0.64, 0.0, 0.0, 1.0]);
}), done).toResolve();
const materials = await loadMtl(multipleMaterialsPath, options);
expect(materials.length).toBe(3);
expect(materials[0].name).toBe('Blue');
expect(materials[0].pbrMetallicRoughness.baseColorFactor).toEqual([0.0, 0.0, 0.64, 1.0]);
expect(materials[1].name).toBe('Green');
expect(materials[1].pbrMetallicRoughness.baseColorFactor).toEqual([0.0, 0.64, 0.0, 1.0]);
expect(materials[2].name).toBe('Red');
expect(materials[2].pbrMetallicRoughness.baseColorFactor).toEqual([0.64, 0.0, 0.0, 1.0]);
});
it('sets overriding textures', function(done) {
it('sets overriding textures', async () => {
spyOn(fsExtra, 'readFile').and.callThrough();
options.overridingTextures = {
metallicRoughnessOcclusionTexture : alphaTexturePath,
baseColorTexture : alphaTexturePath,
emissiveTexture : emissiveTexturePath
};
expect(loadMtl(texturedMaterialPath, options)
.then(function(materials) {
var material = materials[0];
var pbr = material.pbrMetallicRoughness;
expect(pbr.baseColorTexture.name).toBe('alpha');
expect(pbr.metallicRoughnessTexture.name).toBe('alpha');
expect(material.emissiveTexture.name).toBe('emission');
expect(material.normalTexture.name).toBe('bump');
expect(fsExtra.readFile.calls.count()).toBe(3);
}), done).toResolve();
const materials = await loadMtl(texturedMaterialPath, options);
const material = materials[0];
const pbr = material.pbrMetallicRoughness;
expect(pbr.baseColorTexture.name).toBe('alpha');
expect(pbr.metallicRoughnessTexture.name).toBe('alpha');
expect(material.emissiveTexture.name).toBe('emission');
expect(material.normalTexture.name).toBe('bump');
expect(fsExtra.readFile.calls.count()).toBe(3);
});
it('loads texture outside of the mtl directory', function(done) {
expect(loadMtl(externalMaterialPath, options)
.then(function(materials) {
var material = materials[0];
var baseColorTexture = material.pbrMetallicRoughness.baseColorTexture;
expect(baseColorTexture.source).toBeDefined();
expect(baseColorTexture.name).toBe('cesium');
}), done).toResolve();
it('loads texture outside of the mtl directory', async () => {
const materials = await loadMtl(externalMaterialPath, options);
const material = materials[0];
const baseColorTexture = material.pbrMetallicRoughness.baseColorTexture;
expect(baseColorTexture.source).toBeDefined();
expect(baseColorTexture.name).toBe('cesium');
});
it('does not load texture outside of the mtl directory when secure is true', function(done) {
var spy = jasmine.createSpy('logger');
it('does not load texture outside of the mtl directory when secure is true', async () => {
const spy = jasmine.createSpy('logger');
options.logger = spy;
options.secure = true;
expect(loadMtl(externalMaterialPath, options)
.then(function(materials) {
var material = materials[0];
var baseColorTexture = material.pbrMetallicRoughness.baseColorTexture;
expect(baseColorTexture).toBeUndefined();
expect(spy.calls.argsFor(0)[0].indexOf('Texture file is outside of the mtl directory and the secure flag is true. Attempting to read the texture file from within the obj directory instead') >= 0).toBe(true);
expect(spy.calls.argsFor(1)[0].indexOf('ENOENT') >= 0).toBe(true);
expect(spy.calls.argsFor(2)[0].indexOf('Could not read texture file') >= 0).toBe(true);
}), done).toResolve();
const materials = await loadMtl(externalMaterialPath, options);
const material = materials[0];
const baseColorTexture = material.pbrMetallicRoughness.baseColorTexture;
expect(baseColorTexture).toBeUndefined();
expect(spy.calls.argsFor(0)[0].indexOf('Texture file is outside of the mtl directory and the secure flag is true. Attempting to read the texture file from within the obj directory instead') >= 0).toBe(true);
expect(spy.calls.argsFor(1)[0].indexOf('ENOENT') >= 0).toBe(true);
expect(spy.calls.argsFor(2)[0].indexOf('Could not read texture file') >= 0).toBe(true);
});
it('loads textures from root directory when the texture paths do not exist', function(done) {
expect(loadMtl(resourcesInRootMaterialPath, options)
.then(function(materials) {
var material = materials[0];
var baseColorTexture = material.pbrMetallicRoughness.baseColorTexture;
expect(baseColorTexture.source).toBeDefined();
expect(baseColorTexture.name).toBe('cesium');
}), done).toResolve();
it('loads textures from root directory when the texture paths do not exist', async () => {
const materials = await loadMtl(resourcesInRootMaterialPath, options);
const material = materials[0];
const baseColorTexture = material.pbrMetallicRoughness.baseColorTexture;
expect(baseColorTexture.source).toBeDefined();
expect(baseColorTexture.name).toBe('cesium');
});
it('loads textures from root directory when texture is outside of the mtl directory and secure is true', function(done) {
it('loads textures from root directory when texture is outside of the mtl directory and secure is true', async () => {
options.secure = true;
expect(loadMtl(externalInRootMaterialPath, options)
.then(function(materials) {
var material = materials[0];
var baseColorTexture = material.pbrMetallicRoughness.baseColorTexture;
expect(baseColorTexture.source).toBeDefined();
expect(baseColorTexture.name).toBe('cesium');
}), done).toResolve();
const materials = await loadMtl(externalInRootMaterialPath, options);
const material = materials[0];
const baseColorTexture = material.pbrMetallicRoughness.baseColorTexture;
expect(baseColorTexture.source).toBeDefined();
expect(baseColorTexture.name).toBe('cesium');
});
it('alpha of 0.0 is treated as 1.0', function(done) {
expect(loadMtl(transparentMaterialPath, options)
.then(function(materials) {
expect(materials.length).toBe(1);
var material = materials[0];
var pbr = material.pbrMetallicRoughness;
expect(pbr.baseColorTexture).toBeUndefined();
expect(pbr.metallicRoughnessTexture).toBeUndefined();
expect(pbr.baseColorFactor[3]).toEqual(1.0);
expect(material.alphaMode).toBe('OPAQUE');
expect(material.doubleSided).toBe(false);
}), done).toResolve();
it('alpha of 0.0 is treated as 1.0', async () => {
const materials = await loadMtl(transparentMaterialPath, options);
expect(materials.length).toBe(1);
const material = materials[0];
const pbr = material.pbrMetallicRoughness;
expect(pbr.baseColorTexture).toBeUndefined();
expect(pbr.metallicRoughnessTexture).toBeUndefined();
expect(pbr.baseColorFactor[3]).toEqual(1.0);
expect(material.alphaMode).toBe('OPAQUE');
expect(material.doubleSided).toBe(false);
});
it('ambient texture is ignored if it is the same as the diffuse texture', function(done) {
expect(loadMtl(diffuseAmbientSameMaterialPath, options)
.then(function(materials) {
expect(materials.length).toBe(1);
var material = materials[0];
var pbr = material.pbrMetallicRoughness;
expect(pbr.baseColorTexture).toBeDefined();
expect(pbr.occlusionTexture).toBeUndefined();
}), done).toResolve();
it('ambient texture is ignored if it is the same as the diffuse texture', async () => {
const materials = await loadMtl(diffuseAmbientSameMaterialPath, options);
expect(materials.length).toBe(1);
const material = materials[0];
const pbr = material.pbrMetallicRoughness;
expect(pbr.baseColorTexture).toBeDefined();
expect(pbr.occlusionTexture).toBeUndefined();
});
describe('metallicRoughness', function() {
it('creates default material', function() {
var material = loadMtl._createMaterial(undefined, options);
var pbr = material.pbrMetallicRoughness;
describe('metallicRoughness', () => {
it('creates default material', () => {
const material = loadMtl._createMaterial(undefined, options);
const pbr = material.pbrMetallicRoughness;
expect(pbr.baseColorTexture).toBeUndefined();
expect(pbr.metallicRoughnessTexture).toBeUndefined();
expect(pbr.baseColorFactor).toEqual([0.5, 0.5, 0.5, 1.0]);
@ -279,10 +230,10 @@ describe('loadMtl', function() {
expect(material.doubleSided).toBe(false);
});
it('creates material with textures', function() {
it('creates material with textures', () => {
options.metallicRoughness = true;
var material = loadMtl._createMaterial({
const material = loadMtl._createMaterial({
diffuseTexture : diffuseTexture,
ambientTexture : ambientTexture,
normalTexture : normalTexture,
@ -291,7 +242,7 @@ describe('loadMtl', function() {
specularShininessTexture : specularShininessTexture
}, options);
var pbr = material.pbrMetallicRoughness;
const pbr = material.pbrMetallicRoughness;
expect(pbr.baseColorTexture).toBeDefined();
expect(pbr.metallicRoughnessTexture).toBeDefined();
expect(pbr.baseColorFactor).toEqual([1.0, 1.0, 1.0, 1.0]);
@ -305,63 +256,63 @@ describe('loadMtl', function() {
expect(material.doubleSided).toBe(false);
});
it('packs occlusion in metallic roughness texture', function() {
it('packs occlusion in metallic roughness texture', () => {
options.metallicRoughness = true;
options.packOcclusion = true;
var material = loadMtl._createMaterial({
const material = loadMtl._createMaterial({
ambientTexture : alphaTexture,
specularTexture : specularTexture,
specularShininessTexture : specularShininessTexture
}, options);
var pbr = material.pbrMetallicRoughness;
const pbr = material.pbrMetallicRoughness;
expect(pbr.metallicRoughnessTexture).toBeDefined();
expect(pbr.metallicRoughnessTexture).toBe(material.occlusionTexture);
});
it('does not create metallic roughness texture if decoded texture data is not available', function() {
it('does not create metallic roughness texture if decoded texture data is not available', () => {
options.metallicRoughness = true;
options.packOcclusion = true;
var material = loadMtl._createMaterial({
const material = loadMtl._createMaterial({
ambientTexture : ambientTexture, // Is a .gif which can't be decoded
specularTexture : specularTexture,
specularShininessTexture : specularShininessTexture
}, options);
var pbr = material.pbrMetallicRoughness;
const pbr = material.pbrMetallicRoughness;
expect(pbr.metallicRoughnessTexture).toBeUndefined();
expect(material.occlusionTexture).toBeUndefined();
});
it('sets material for transparent diffuse texture', function() {
it('sets material for transparent diffuse texture', () => {
options.metallicRoughness = true;
var material = loadMtl._createMaterial({
const material = loadMtl._createMaterial({
diffuseTexture : transparentDiffuseTexture
}, options);
expect(material.alphaMode).toBe('BLEND');
expect(material.doubleSided).toBe(true);
});
it('packs alpha texture in base color texture', function() {
it('packs alpha texture in base color texture', () => {
options.metallicRoughness = true;
var material = loadMtl._createMaterial({
const material = loadMtl._createMaterial({
diffuseTexture : diffuseTexture,
alphaTexture : alphaTexture
}, options);
var pbr = material.pbrMetallicRoughness;
const pbr = material.pbrMetallicRoughness;
expect(pbr.baseColorTexture).toBeDefined();
var hasBlack = false;
var hasWhite = false;
var pixels = pbr.baseColorTexture.pixels;
var pixelsLength = pixels.length / 4;
for (var i = 0; i < pixelsLength; ++i) {
var alpha = pixels[i * 4 + 3];
let hasBlack = false;
let hasWhite = false;
const pixels = pbr.baseColorTexture.pixels;
const pixelsLength = pixels.length / 4;
for (let i = 0; i < pixelsLength; ++i) {
const alpha = pixels[i * 4 + 3];
hasBlack = hasBlack || (alpha === 0);
hasWhite = hasWhite || (alpha === 255);
}
@ -373,11 +324,11 @@ describe('loadMtl', function() {
});
});
describe('specularGlossiness', function() {
it('creates default material', function() {
describe('specularGlossiness', () => {
it('creates default material', () => {
options.specularGlossiness = true;
var material = loadMtl._createMaterial(undefined, options);
var pbr = material.extensions.KHR_materials_pbrSpecularGlossiness;
const material = loadMtl._createMaterial(undefined, options);
const pbr = material.extensions.KHR_materials_pbrSpecularGlossiness;
expect(pbr.diffuseTexture).toBeUndefined();
expect(pbr.specularGlossinessTexture).toBeUndefined();
expect(pbr.diffuseFactor).toEqual([0.5, 0.5, 0.5, 1.0]);
@ -391,10 +342,10 @@ describe('loadMtl', function() {
expect(material.doubleSided).toBe(false);
});
it('creates material with textures', function() {
it('creates material with textures', () => {
options.specularGlossiness = true;
var material = loadMtl._createMaterial({
const material = loadMtl._createMaterial({
diffuseTexture : diffuseTexture,
ambientTexture : ambientTexture,
normalTexture : normalTexture,
@ -403,7 +354,7 @@ describe('loadMtl', function() {
specularShininessTexture : specularShininessTexture
}, options);
var pbr = material.extensions.KHR_materials_pbrSpecularGlossiness;
const pbr = material.extensions.KHR_materials_pbrSpecularGlossiness;
expect(pbr.diffuseTexture).toBeDefined();
expect(pbr.specularGlossinessTexture).toBeDefined();
expect(pbr.diffuseFactor).toEqual([1.0, 1.0, 1.0, 1.0]);
@ -417,22 +368,22 @@ describe('loadMtl', function() {
expect(material.doubleSided).toBe(false);
});
it('does not create specular glossiness texture if decoded texture data is not available', function() {
it('does not create specular glossiness texture if decoded texture data is not available', () => {
options.specularGlossiness = true;
var material = loadMtl._createMaterial({
const material = loadMtl._createMaterial({
specularTexture : ambientTexture, // Is a .gif which can't be decoded
specularShininessTexture : specularShininessTexture
}, options);
var pbr = material.extensions.KHR_materials_pbrSpecularGlossiness;
const pbr = material.extensions.KHR_materials_pbrSpecularGlossiness;
expect(pbr.specularGlossinessTexture).toBeUndefined();
});
it('sets material for transparent diffuse texture', function() {
it('sets material for transparent diffuse texture', () => {
options.specularGlossiness = true;
var material = loadMtl._createMaterial({
const material = loadMtl._createMaterial({
diffuseTexture : transparentDiffuseTexture
}, options);
@ -440,23 +391,23 @@ describe('loadMtl', function() {
expect(material.doubleSided).toBe(true);
});
it('packs alpha texture in diffuse texture', function() {
it('packs alpha texture in diffuse texture', () => {
options.specularGlossiness = true;
var material = loadMtl._createMaterial({
const material = loadMtl._createMaterial({
diffuseTexture : diffuseTexture,
alphaTexture : alphaTexture
}, options);
var pbr = material.extensions.KHR_materials_pbrSpecularGlossiness;
const pbr = material.extensions.KHR_materials_pbrSpecularGlossiness;
expect(pbr.diffuseTexture).toBeDefined();
var hasBlack = false;
var hasWhite = false;
var pixels = pbr.diffuseTexture.pixels;
var pixelsLength = pixels.length / 4;
for (var i = 0; i < pixelsLength; ++i) {
var alpha = pixels[i * 4 + 3];
let hasBlack = false;
let hasWhite = false;
const pixels = pbr.diffuseTexture.pixels;
const pixelsLength = pixels.length / 4;
for (let i = 0; i < pixelsLength; ++i) {
const alpha = pixels[i * 4 + 3];
hasBlack = hasBlack || (alpha === 0);
hasWhite = hasWhite || (alpha === 255);
}

View File

@ -1,234 +1,216 @@
'use strict';
var Cesium = require('cesium');
var Promise = require('bluebird');
var loadObj = require('../../lib/loadObj');
var obj2gltf = require('../../lib/obj2gltf');
const Cesium = require('cesium');
var Cartesian3 = Cesium.Cartesian3;
var CesiumMath = Cesium.Math;
var clone = Cesium.clone;
var RuntimeError = Cesium.RuntimeError;
const loadObj = require('../../lib/loadObj');
const obj2gltf = require('../../lib/obj2gltf');
var objPath = 'specs/data/box/box.obj';
var objNormalsPath = 'specs/data/box-normals/box-normals.obj';
var objUvsPath = 'specs/data/box-uvs/box-uvs.obj';
var objPositionsOnlyPath = 'specs/data/box-positions-only/box-positions-only.obj';
var objNegativeIndicesPath = 'specs/data/box-negative-indices/box-negative-indices.obj';
var objTrianglesPath = 'specs/data/box-triangles/box-triangles.obj';
var objObjectsPath = 'specs/data/box-objects/box-objects.obj';
var objGroupsPath = 'specs/data/box-groups/box-groups.obj';
var objObjectsGroupsPath = 'specs/data/box-objects-groups/box-objects-groups.obj';
var objObjectsGroupsMaterialsPath = 'specs/data/box-objects-groups-materials/box-objects-groups-materials.obj';
var objObjectsGroupsMaterialsPath2 = 'specs/data/box-objects-groups-materials-2/box-objects-groups-materials-2.obj';
var objUsemtlPath = 'specs/data/box-usemtl/box-usemtl.obj';
var objNoMaterialsPath = 'specs/data/box-no-materials/box-no-materials.obj';
var objMultipleMaterialsPath = 'specs/data/box-multiple-materials/box-multiple-materials.obj';
var objUncleanedPath = 'specs/data/box-uncleaned/box-uncleaned.obj';
var objMtllibPath = 'specs/data/box-mtllib/box-mtllib.obj';
var objMtllibSpacesPath = 'specs/data/box-mtllib-spaces/box mtllib.obj';
var objMissingMtllibPath = 'specs/data/box-missing-mtllib/box-missing-mtllib.obj';
var objMissingUsemtlPath = 'specs/data/box-missing-usemtl/box-missing-usemtl.obj';
var objUnnamedMaterialPath = 'specs/data/box-unnamed-material/box-unnamed-material.obj';
var objExternalResourcesPath = 'specs/data/box-external-resources/box-external-resources.obj';
var objResourcesInRootPath = 'specs/data/box-resources-in-root/box-resources-in-root.obj';
var objExternalResourcesInRootPath = 'specs/data/box-external-resources-in-root/box-external-resources-in-root.obj';
var objTexturedPath = 'specs/data/box-textured/box-textured.obj';
var objMissingTexturePath = 'specs/data/box-missing-texture/box-missing-texture.obj';
var objSubdirectoriesPath = 'specs/data/box-subdirectories/box-textured.obj';
var objWindowsPaths = 'specs/data/box-windows-paths/box-windows-paths.obj';
var objInvalidContentsPath = 'specs/data/box/box.mtl';
var objConcavePath = 'specs/data/concave/concave.obj';
var objUnnormalizedPath = 'specs/data/box-unnormalized/box-unnormalized.obj';
var objMixedAttributesPath = 'specs/data/box-mixed-attributes/box-mixed-attributes.obj';
var objInvalidPath = 'invalid.obj';
const Cartesian3 = Cesium.Cartesian3;
const CesiumMath = Cesium.Math;
const clone = Cesium.clone;
const RuntimeError = Cesium.RuntimeError;
const objPath = 'specs/data/box/box.obj';
const objNormalsPath = 'specs/data/box-normals/box-normals.obj';
const objUvsPath = 'specs/data/box-uvs/box-uvs.obj';
const objPositionsOnlyPath = 'specs/data/box-positions-only/box-positions-only.obj';
const objNegativeIndicesPath = 'specs/data/box-negative-indices/box-negative-indices.obj';
const objTrianglesPath = 'specs/data/box-triangles/box-triangles.obj';
const objObjectsPath = 'specs/data/box-objects/box-objects.obj';
const objGroupsPath = 'specs/data/box-groups/box-groups.obj';
const objObjectsGroupsPath = 'specs/data/box-objects-groups/box-objects-groups.obj';
const objObjectsGroupsMaterialsPath = 'specs/data/box-objects-groups-materials/box-objects-groups-materials.obj';
const objObjectsGroupsMaterialsPath2 = 'specs/data/box-objects-groups-materials-2/box-objects-groups-materials-2.obj';
const objUsemtlPath = 'specs/data/box-usemtl/box-usemtl.obj';
const objNoMaterialsPath = 'specs/data/box-no-materials/box-no-materials.obj';
const objMultipleMaterialsPath = 'specs/data/box-multiple-materials/box-multiple-materials.obj';
const objUncleanedPath = 'specs/data/box-uncleaned/box-uncleaned.obj';
const objMtllibPath = 'specs/data/box-mtllib/box-mtllib.obj';
const objMtllibSpacesPath = 'specs/data/box-mtllib-spaces/box mtllib.obj';
const objMissingMtllibPath = 'specs/data/box-missing-mtllib/box-missing-mtllib.obj';
const objMissingUsemtlPath = 'specs/data/box-missing-usemtl/box-missing-usemtl.obj';
const objUnnamedMaterialPath = 'specs/data/box-unnamed-material/box-unnamed-material.obj';
const objExternalResourcesPath = 'specs/data/box-external-resources/box-external-resources.obj';
const objResourcesInRootPath = 'specs/data/box-resources-in-root/box-resources-in-root.obj';
const objExternalResourcesInRootPath = 'specs/data/box-external-resources-in-root/box-external-resources-in-root.obj';
const objTexturedPath = 'specs/data/box-textured/box-textured.obj';
const objMissingTexturePath = 'specs/data/box-missing-texture/box-missing-texture.obj';
const objSubdirectoriesPath = 'specs/data/box-subdirectories/box-textured.obj';
const objWindowsPaths = 'specs/data/box-windows-paths/box-windows-paths.obj';
const objInvalidContentsPath = 'specs/data/box/box.mtl';
const objConcavePath = 'specs/data/concave/concave.obj';
const objUnnormalizedPath = 'specs/data/box-unnormalized/box-unnormalized.obj';
const objMixedAttributesPath = 'specs/data/box-mixed-attributes/box-mixed-attributes.obj';
const objInvalidPath = 'invalid.obj';
function getMeshes(data) {
var meshes = [];
var nodes = data.nodes;
var nodesLength = nodes.length;
for (var i = 0; i < nodesLength; ++i) {
let meshes = [];
const nodes = data.nodes;
const nodesLength = nodes.length;
for (let i = 0; i < nodesLength; ++i) {
meshes = meshes.concat(nodes[i].meshes);
}
return meshes;
}
function getPrimitives(data) {
var primitives = [];
var nodes = data.nodes;
var nodesLength = nodes.length;
for (var i = 0; i < nodesLength; ++i) {
var meshes = nodes[i].meshes;
var meshesLength = meshes.length;
for (var j = 0; j < meshesLength; ++j) {
let primitives = [];
const nodes = data.nodes;
const nodesLength = nodes.length;
for (let i = 0; i < nodesLength; ++i) {
const meshes = nodes[i].meshes;
const meshesLength = meshes.length;
for (let j = 0; j < meshesLength; ++j) {
primitives = primitives.concat(meshes[j].primitives);
}
}
return primitives;
}
var options;
let options;
describe('loadObj', function() {
beforeEach(function() {
describe('loadObj', () => {
beforeEach(() => {
options = clone(obj2gltf.defaults);
options.overridingTextures = {};
options.logger = function() {};
options.logger = () => {};
});
it('loads obj with positions, normals, and uvs', function(done) {
expect(loadObj(objPath, options)
.then(function(data) {
var materials = data.materials;
var nodes = data.nodes;
var name = data.name;
var meshes = getMeshes(data);
var primitives = getPrimitives(data);
it('loads obj with positions, normals, and uvs', async () => {
const data = await loadObj(objPath, options);
const materials = data.materials;
const nodes = data.nodes;
const name = data.name;
const meshes = getMeshes(data);
const primitives = getPrimitives(data);
expect(name).toBe('box');
expect(materials.length).toBe(1);
expect(nodes.length).toBe(1);
expect(meshes.length).toBe(1);
expect(primitives.length).toBe(1);
expect(name).toBe('box');
expect(materials.length).toBe(1);
expect(nodes.length).toBe(1);
expect(meshes.length).toBe(1);
expect(primitives.length).toBe(1);
var node = nodes[0];
var mesh = meshes[0];
var primitive = primitives[0];
const node = nodes[0];
const mesh = meshes[0];
const primitive = primitives[0];
expect(node.name).toBe('Cube');
expect(mesh.name).toBe('Cube-Mesh');
expect(primitive.positions.length / 3).toBe(24);
expect(primitive.normals.length / 3).toBe(24);
expect(primitive.uvs.length / 2).toBe(24);
expect(primitive.indices.length).toBe(36);
expect(primitive.material).toBe('Material');
}), done).toResolve();
expect(node.name).toBe('Cube');
expect(mesh.name).toBe('Cube-Mesh');
expect(primitive.positions.length / 3).toBe(24);
expect(primitive.normals.length / 3).toBe(24);
expect(primitive.uvs.length / 2).toBe(24);
expect(primitive.indices.length).toBe(36);
expect(primitive.material).toBe('Material');
});
it('loads obj with normals', function(done) {
expect(loadObj(objNormalsPath, options)
.then(function(data) {
var primitive = getPrimitives(data)[0];
expect(primitive.positions.length / 3).toBe(24);
expect(primitive.normals.length / 3).toBe(24);
expect(primitive.uvs.length / 2).toBe(0);
}), done).toResolve();
it('loads obj with normals', async () => {
const data = await loadObj(objNormalsPath, options);
const primitive = getPrimitives(data)[0];
expect(primitive.positions.length / 3).toBe(24);
expect(primitive.normals.length / 3).toBe(24);
expect(primitive.uvs.length / 2).toBe(0);
});
it('normalizes normals', function(done) {
expect(loadObj(objUnnormalizedPath, options)
.then(function(data) {
var scratchNormal = new Cesium.Cartesian3();
var primitive = getPrimitives(data)[0];
var normals = primitive.normals;
var normalsLength = normals.length / 3;
for (var i = 0; i < normalsLength; ++i) {
var normalX = normals.get(i * 3);
var normalY = normals.get(i * 3 + 1);
var normalZ = normals.get(i * 3 + 2);
var normal = Cartesian3.fromElements(normalX, normalY, normalZ, scratchNormal);
expect(Cartesian3.magnitude(normal)).toEqualEpsilon(1.0, CesiumMath.EPSILON5);
}
}), done).toResolve();
it('normalizes normals', async () => {
const data = await loadObj(objUnnormalizedPath, options);
const scratchNormal = new Cesium.Cartesian3();
const primitive = getPrimitives(data)[0];
const normals = primitive.normals;
const normalsLength = normals.length / 3;
for (let i = 0; i < normalsLength; ++i) {
const normalX = normals.get(i * 3);
const normalY = normals.get(i * 3 + 1);
const normalZ = normals.get(i * 3 + 2);
const normal = Cartesian3.fromElements(normalX, normalY, normalZ, scratchNormal);
expect(CesiumMath.equalsEpsilon(Cartesian3.magnitude(normal), 1.0, CesiumMath.EPSILON5)).toBe(true);
}
});
it('loads obj with uvs', function(done) {
expect(loadObj(objUvsPath, options)
.then(function(data) {
var primitive = getPrimitives(data)[0];
expect(primitive.positions.length / 3).toBe(20);
expect(primitive.normals.length / 3).toBe(0);
expect(primitive.uvs.length / 2).toBe(20);
}), done).toResolve();
it('loads obj with uvs', async () => {
const data = await loadObj(objUvsPath, options);
const primitive = getPrimitives(data)[0];
expect(primitive.positions.length / 3).toBe(20);
expect(primitive.normals.length / 3).toBe(0);
expect(primitive.uvs.length / 2).toBe(20);
});
it('loads obj with negative indices', function(done) {
expect(Promise.all([
loadObj(objPositionsOnlyPath, options),
loadObj(objNegativeIndicesPath, options)
])
.then(function(results) {
var positionsReference = getPrimitives(results[0])[0].positions.toFloatBuffer();
var positions = getPrimitives(results[1])[0].positions.toFloatBuffer();
expect(positions).toEqual(positionsReference);
}), done).toResolve();
it('loads obj with negative indices', async () => {
const results = [
await loadObj(objPositionsOnlyPath, options),
await loadObj(objNegativeIndicesPath, options)
];
const positionsReference = getPrimitives(results[0])[0].positions.toFloatBuffer();
const positions = getPrimitives(results[1])[0].positions.toFloatBuffer();
expect(positions).toEqual(positionsReference);
});
it('loads obj with triangle faces', function(done) {
expect(loadObj(objTrianglesPath, options)
.then(function(data) {
var primitive = getPrimitives(data)[0];
expect(primitive.positions.length / 3).toBe(24);
expect(primitive.indices.length).toBe(36);
}), done).toResolve();
it('loads obj with triangle faces', async () => {
const data = await loadObj(objTrianglesPath, options);
const primitive = getPrimitives(data)[0];
expect(primitive.positions.length / 3).toBe(24);
expect(primitive.indices.length).toBe(36);
});
it('loads obj with objects', function(done) {
expect(loadObj(objObjectsPath, options)
.then(function(data) {
var nodes = data.nodes;
expect(nodes.length).toBe(3);
expect(nodes[0].name).toBe('CubeBlue');
expect(nodes[1].name).toBe('CubeGreen');
expect(nodes[2].name).toBe('CubeRed');
it('loads obj with objects', async () => {
const data = await loadObj(objObjectsPath, options);
const nodes = data.nodes;
expect(nodes.length).toBe(3);
expect(nodes[0].name).toBe('CubeBlue');
expect(nodes[1].name).toBe('CubeGreen');
expect(nodes[2].name).toBe('CubeRed');
var primitives = getPrimitives(data);
expect(primitives.length).toBe(3);
expect(primitives[0].material).toBe('Blue');
expect(primitives[1].material).toBe('Green');
expect(primitives[2].material).toBe('Red');
}), done).toResolve();
const primitives = getPrimitives(data);
expect(primitives.length).toBe(3);
expect(primitives[0].material).toBe('Blue');
expect(primitives[1].material).toBe('Green');
expect(primitives[2].material).toBe('Red');
});
it('loads obj with groups', function(done) {
expect(loadObj(objGroupsPath, options)
.then(function(data) {
var nodes = data.nodes;
expect(nodes.length).toBe(3);
expect(nodes[0].name).toBe('CubeBlue');
expect(nodes[1].name).toBe('CubeGreen');
expect(nodes[2].name).toBe('CubeRed');
it('loads obj with groups', async () => {
const data = await loadObj(objGroupsPath, options);
const nodes = data.nodes;
expect(nodes.length).toBe(3);
expect(nodes[0].name).toBe('CubeBlue');
expect(nodes[1].name).toBe('CubeGreen');
expect(nodes[2].name).toBe('CubeRed');
var primitives = getPrimitives(data);
expect(primitives.length).toBe(3);
expect(primitives[0].material).toBe('Blue');
expect(primitives[1].material).toBe('Green');
expect(primitives[2].material).toBe('Red');
}), done).toResolve();
const primitives = getPrimitives(data);
expect(primitives.length).toBe(3);
expect(primitives[0].material).toBe('Blue');
expect(primitives[1].material).toBe('Green');
expect(primitives[2].material).toBe('Red');
});
it('loads obj with objects and groups', function(done) {
expect(loadObj(objObjectsGroupsPath, options)
.then(function(data) {
var nodes = data.nodes;
expect(nodes.length).toBe(3);
expect(nodes[0].name).toBe('CubeBlue');
expect(nodes[1].name).toBe('CubeGreen');
expect(nodes[2].name).toBe('CubeRed');
it('loads obj with objects and groups', async () => {
const data = await loadObj(objObjectsGroupsPath, options);
const nodes = data.nodes;
expect(nodes.length).toBe(3);
expect(nodes[0].name).toBe('CubeBlue');
expect(nodes[1].name).toBe('CubeGreen');
expect(nodes[2].name).toBe('CubeRed');
var meshes = getMeshes(data);
expect(meshes.length).toBe(3);
expect(meshes[0].name).toBe('CubeBlue_CubeBlue_Blue');
expect(meshes[1].name).toBe('CubeGreen_CubeGreen_Green');
expect(meshes[2].name).toBe('CubeRed_CubeRed_Red');
const meshes = getMeshes(data);
expect(meshes.length).toBe(3);
expect(meshes[0].name).toBe('CubeBlue_CubeBlue_Blue');
expect(meshes[1].name).toBe('CubeGreen_CubeGreen_Green');
expect(meshes[2].name).toBe('CubeRed_CubeRed_Red');
var primitives = getPrimitives(data);
expect(primitives.length).toBe(3);
expect(primitives[0].material).toBe('Blue');
expect(primitives[1].material).toBe('Green');
expect(primitives[2].material).toBe('Red');
}), done).toResolve();
const primitives = getPrimitives(data);
expect(primitives.length).toBe(3);
expect(primitives[0].material).toBe('Blue');
expect(primitives[1].material).toBe('Green');
expect(primitives[2].material).toBe('Red');
});
function loadsObjWithObjectsGroupsAndMaterials(data) {
var nodes = data.nodes;
const nodes = data.nodes;
expect(nodes.length).toBe(1);
expect(nodes[0].name).toBe('Cube');
var meshes = getMeshes(data);
const meshes = getMeshes(data);
expect(meshes.length).toBe(3);
expect(meshes[0].name).toBe('Blue');
expect(meshes[1].name).toBe('Green');
expect(meshes[2].name).toBe('Red');
var primitives = getPrimitives(data);
const primitives = getPrimitives(data);
expect(primitives.length).toBe(6);
expect(primitives[0].material).toBe('Blue');
expect(primitives[1].material).toBe('Green');
@ -238,288 +220,258 @@ describe('loadObj', function() {
expect(primitives[5].material).toBe('Blue');
}
it('loads obj with objects, groups, and materials', function(done) {
expect(loadObj(objObjectsGroupsMaterialsPath, options)
.then(function(data) {
loadsObjWithObjectsGroupsAndMaterials(data);
}), done).toResolve();
it('loads obj with objects, groups, and materials', async () => {
const data = await loadObj(objObjectsGroupsMaterialsPath, options);
loadsObjWithObjectsGroupsAndMaterials(data);
});
it('loads obj with objects, groups, and materials (2)', function(done) {
it('loads obj with objects, groups, and materials (2)', async () => {
// The usemtl lines are placed in an unordered fashion but
// should produce the same result as the previous test
expect(loadObj(objObjectsGroupsMaterialsPath2, options)
.then(function(data) {
loadsObjWithObjectsGroupsAndMaterials(data);
}), done).toResolve();
const data = await loadObj(objObjectsGroupsMaterialsPath2, options);
loadsObjWithObjectsGroupsAndMaterials(data);
});
it('loads obj with concave face containing 5 vertices', function(done) {
expect(loadObj(objConcavePath, options)
.then(function(data) {
var primitive = getPrimitives(data)[0];
expect(primitive.positions.length / 3).toBe(30);
expect(primitive.indices.length).toBe(48);
}), done).toResolve();
it('loads obj with concave face containing 5 vertices', async () => {
const data = await loadObj(objConcavePath, options);
const primitive = getPrimitives(data)[0];
expect(primitive.positions.length / 3).toBe(30);
expect(primitive.indices.length).toBe(48);
});
it('loads obj with usemtl only', function(done) {
expect(loadObj(objUsemtlPath, options)
.then(function(data) {
var nodes = data.nodes;
expect(nodes.length).toBe(1);
expect(nodes[0].name).toBe('Node'); // default name
it('loads obj with usemtl only', async () => {
const data = await loadObj(objUsemtlPath, options);
const nodes = data.nodes;
expect(nodes.length).toBe(1);
expect(nodes[0].name).toBe('Node'); // default name
var meshes = getMeshes(data);
expect(meshes.length).toBe(1);
expect(meshes[0].name).toBe('Node-Mesh');
const meshes = getMeshes(data);
expect(meshes.length).toBe(1);
expect(meshes[0].name).toBe('Node-Mesh');
var primitives = getPrimitives(data);
expect(primitives.length).toBe(3);
expect(primitives[0].material).toBe('Blue');
expect(primitives[1].material).toBe('Green');
expect(primitives[2].material).toBe('Red');
}), done).toResolve();
const primitives = getPrimitives(data);
expect(primitives.length).toBe(3);
expect(primitives[0].material).toBe('Blue');
expect(primitives[1].material).toBe('Green');
expect(primitives[2].material).toBe('Red');
});
it('loads obj with no materials', function(done) {
expect(loadObj(objNoMaterialsPath, options)
.then(function(data) {
var nodes = data.nodes;
expect(nodes.length).toBe(1);
expect(nodes[0].name).toBe('Node'); // default name
it('loads obj with no materials', async () => {
const data = await loadObj(objNoMaterialsPath, options);
const nodes = data.nodes;
expect(nodes.length).toBe(1);
expect(nodes[0].name).toBe('Node'); // default name
var primitives = getPrimitives(data);
expect(primitives.length).toBe(1);
}), done).toResolve();
const primitives = getPrimitives(data);
expect(primitives.length).toBe(1);
});
it('loads obj with multiple materials', function(done) {
it('loads obj with multiple materials', async () => {
// The usemtl markers are interleaved, but should condense to just three primitives
expect(loadObj(objMultipleMaterialsPath, options)
.then(function(data) {
var nodes = data.nodes;
expect(nodes.length).toBe(1);
const data = await loadObj(objMultipleMaterialsPath, options);
const nodes = data.nodes;
expect(nodes.length).toBe(1);
var primitives = getPrimitives(data);
expect(primitives.length).toBe(3);
const primitives = getPrimitives(data);
expect(primitives.length).toBe(3);
expect(primitives[0].indices.length).toBe(12);
expect(primitives[1].indices.length).toBe(12);
expect(primitives[2].indices.length).toBe(12);
expect(primitives[0].material).toBe('Red');
expect(primitives[1].material).toBe('Green');
expect(primitives[2].material).toBe('Blue');
expect(primitives[0].indices.length).toBe(12);
expect(primitives[1].indices.length).toBe(12);
expect(primitives[2].indices.length).toBe(12);
expect(primitives[0].material).toBe('Red');
expect(primitives[1].material).toBe('Green');
expect(primitives[2].material).toBe('Blue');
for (var i = 0; i < 3; ++i) {
var indices = primitives[i].indices;
for (var j = 0; j < indices.length; ++j) {
expect(indices.get(j)).toBeLessThan(8);
}
}
}), done).toResolve();
for (let i = 0; i < 3; ++i) {
const indices = primitives[i].indices;
for (let j = 0; j < indices.length; ++j) {
expect(indices.get(j)).toBeLessThan(8);
}
}
});
it('loads obj uncleaned', function(done) {
it('loads obj uncleaned', async () => {
// Obj with extraneous o, g, and usemtl lines
// Also tests handling of o and g lines with the same names
expect(loadObj(objUncleanedPath, options)
.then(function(data) {
var nodes = data.nodes;
var meshes = getMeshes(data);
var primitives = getPrimitives(data);
const data = await loadObj(objUncleanedPath, options);
const nodes = data.nodes;
const meshes = getMeshes(data);
const primitives = getPrimitives(data);
expect(nodes.length).toBe(1);
expect(meshes.length).toBe(1);
expect(primitives.length).toBe(1);
expect(nodes.length).toBe(1);
expect(meshes.length).toBe(1);
expect(primitives.length).toBe(1);
expect(nodes[0].name).toBe('Cube');
expect(meshes[0].name).toBe('Cube_1');
}), done).toResolve();
expect(nodes[0].name).toBe('Cube');
expect(meshes[0].name).toBe('Cube_1');
});
it('loads obj with multiple mtllibs', function(done) {
expect(loadObj(objMtllibPath, options)
.then(function(data) {
var materials = data.materials;
expect(materials.length).toBe(3);
it('loads obj with multiple mtllibs', async () => {
const data = await loadObj(objMtllibPath, options);
const materials = data.materials;
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);
});
// .mtl files are loaded in an arbitrary order, so sort for testing purposes
materials.sort((a, b) => {
return a.name.localeCompare(b.name);
});
expect(materials[0].name).toBe('Blue');
expect(materials[0].pbrMetallicRoughness.baseColorFactor).toEqual([0.0, 0.0, 0.64, 1.0]);
expect(materials[1].name).toBe('Green');
expect(materials[1].pbrMetallicRoughness.baseColorFactor).toEqual([0.0, 0.64, 0.0, 1.0]);
expect(materials[2].name).toBe('Red');
expect(materials[2].pbrMetallicRoughness.baseColorFactor).toEqual([0.64, 0.0, 0.0, 1.0]);
}), done).toResolve();
expect(materials[0].name).toBe('Blue');
expect(materials[0].pbrMetallicRoughness.baseColorFactor).toEqual([0.0, 0.0, 0.64, 1.0]);
expect(materials[1].name).toBe('Green');
expect(materials[1].pbrMetallicRoughness.baseColorFactor).toEqual([0.0, 0.64, 0.0, 1.0]);
expect(materials[2].name).toBe('Red');
expect(materials[2].pbrMetallicRoughness.baseColorFactor).toEqual([0.64, 0.0, 0.0, 1.0]);
});
it('loads obj with mtllib paths with spaces', function(done) {
expect(loadObj(objMtllibSpacesPath, options)
.then(function(data) {
var materials = data.materials;
expect(materials.length).toBe(3);
it('loads obj with mtllib paths with spaces', async () => {
const data = await loadObj(objMtllibSpacesPath, options);
const materials = data.materials;
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);
});
// .mtl files are loaded in an arbitrary order, so sort for testing purposes
materials.sort((a, b) => {
return a.name.localeCompare(b.name);
});
expect(materials[0].name).toBe('Blue');
expect(materials[0].pbrMetallicRoughness.baseColorFactor).toEqual([0.0, 0.0, 0.64, 1.0]);
expect(materials[1].name).toBe('Green');
expect(materials[1].pbrMetallicRoughness.baseColorFactor).toEqual([0.0, 0.64, 0.0, 1.0]);
expect(materials[2].name).toBe('Red');
expect(materials[2].pbrMetallicRoughness.baseColorFactor).toEqual([0.64, 0.0, 0.0, 1.0]);
}), done).toResolve();
expect(materials[0].name).toBe('Blue');
expect(materials[0].pbrMetallicRoughness.baseColorFactor).toEqual([0.0, 0.0, 0.64, 1.0]);
expect(materials[1].name).toBe('Green');
expect(materials[1].pbrMetallicRoughness.baseColorFactor).toEqual([0.0, 0.64, 0.0, 1.0]);
expect(materials[2].name).toBe('Red');
expect(materials[2].pbrMetallicRoughness.baseColorFactor).toEqual([0.64, 0.0, 0.0, 1.0]);
});
it('loads obj with missing mtllib', function(done) {
var spy = jasmine.createSpy('logger');
it('loads obj with missing mtllib', async () => {
const spy = jasmine.createSpy('logger');
options.logger = spy;
expect(loadObj(objMissingMtllibPath, options)
.then(function(data) {
expect(data.materials.length).toBe(0);
expect(spy.calls.argsFor(0)[0].indexOf('ENOENT') >= 0).toBe(true);
expect(spy.calls.argsFor(1)[0].indexOf('Attempting to read the material file from within the obj directory instead.') >= 0).toBe(true);
expect(spy.calls.argsFor(2)[0].indexOf('ENOENT') >= 0).toBe(true);
expect(spy.calls.argsFor(3)[0].indexOf('Could not read material file') >= 0).toBe(true);
}), done).toResolve();
const data = await loadObj(objMissingMtllibPath, options);
expect(data.materials.length).toBe(0);
expect(spy.calls.argsFor(0)[0].indexOf('ENOENT') >= 0).toBe(true);
expect(spy.calls.argsFor(1)[0].indexOf('Attempting to read the material file from within the obj directory instead.') >= 0).toBe(true);
expect(spy.calls.argsFor(2)[0].indexOf('ENOENT') >= 0).toBe(true);
expect(spy.calls.argsFor(3)[0].indexOf('Could not read material file') >= 0).toBe(true);
});
it('loads obj with missing usemtl', function(done) {
expect(loadObj(objMissingUsemtlPath, options)
.then(function(data) {
expect(data.materials.length).toBe(1);
expect(data.nodes[0].meshes[0].primitives[0].material).toBe('Material');
}), done).toResolve();
it('loads obj with missing usemtl', async () => {
const data = await loadObj(objMissingUsemtlPath, options);
expect(data.materials.length).toBe(1);
expect(data.nodes[0].meshes[0].primitives[0].material).toBe('Material');
});
it('loads obj with unnamed material', function(done) {
expect(loadObj(objUnnamedMaterialPath, options)
.then(function(data) {
expect(data.materials.length).toBe(1);
expect(data.nodes[0].meshes[0].primitives[0].material).toBe('');
}), done).toResolve();
it('loads obj with unnamed material', async () => {
const data = await loadObj(objUnnamedMaterialPath, options);
expect(data.materials.length).toBe(1);
expect(data.nodes[0].meshes[0].primitives[0].material).toBe('');
});
it('loads .mtl outside of the obj directory', function(done) {
expect(loadObj(objExternalResourcesPath, options)
.then(function(data) {
var materials = data.materials;
expect(materials.length).toBe(2);
it('loads .mtl outside of the obj directory', async () => {
const data = await loadObj(objExternalResourcesPath, options);
const 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];
var baseColorTexture = materialTextured.pbrMetallicRoughness.baseColorTexture;
expect(baseColorTexture.source).toBeDefined();
expect(baseColorTexture.name).toEqual('cesium');
}), done).toResolve();
// .mtl files are loaded in an arbitrary order, so find the "MaterialTextured" material
const materialTextured = materials[0].name === 'MaterialTextured' ? materials[0] : materials[1];
const baseColorTexture = materialTextured.pbrMetallicRoughness.baseColorTexture;
expect(baseColorTexture.source).toBeDefined();
expect(baseColorTexture.name).toEqual('cesium');
});
it('does not load .mtl outside of the obj directory when secure is true', function(done) {
var spy = jasmine.createSpy('logger');
it('does not load .mtl outside of the obj directory when secure is true', async () => {
const spy = jasmine.createSpy('logger');
options.logger = spy;
options.secure = true;
expect(loadObj(objExternalResourcesPath, options)
.then(function(data) {
expect(data.materials.length).toBe(1); // obj references 2 materials, one of which is outside the input directory
expect(spy.calls.argsFor(0)[0].indexOf('The material file is outside of the obj directory and the secure flag is true. Attempting to read the material file from within the obj directory instead.') >= 0).toBe(true);
expect(spy.calls.argsFor(1)[0].indexOf('ENOENT') >= 0).toBe(true);
expect(spy.calls.argsFor(2)[0].indexOf('Could not read material file') >= 0).toBe(true);
}), done).toResolve();
const data = await loadObj(objExternalResourcesPath, options);
expect(data.materials.length).toBe(1); // obj references 2 materials, one of which is outside the input directory
expect(spy.calls.argsFor(0)[0].indexOf('The material file is outside of the obj directory and the secure flag is true. Attempting to read the material file from within the obj directory instead.') >= 0).toBe(true);
expect(spy.calls.argsFor(1)[0].indexOf('ENOENT') >= 0).toBe(true);
expect(spy.calls.argsFor(2)[0].indexOf('Could not read material file') >= 0).toBe(true);
});
it('loads .mtl from root directory when the .mtl path does not exist', function(done) {
expect(loadObj(objResourcesInRootPath, options)
.then(function(data) {
var baseColorTexture = data.materials[0].pbrMetallicRoughness.baseColorTexture;
expect(baseColorTexture.name).toBe('cesium');
expect(baseColorTexture.source).toBeDefined();
}), done).toResolve();
it('loads .mtl from root directory when the .mtl path does not exist', async () => {
const data = await loadObj(objResourcesInRootPath, options);
const baseColorTexture = data.materials[0].pbrMetallicRoughness.baseColorTexture;
expect(baseColorTexture.name).toBe('cesium');
expect(baseColorTexture.source).toBeDefined();
});
it('loads .mtl from root directory when the .mtl path is outside of the obj directory and secure is true', function(done) {
it('loads .mtl from root directory when the .mtl path is outside of the obj directory and secure is true', async () => {
options.secure = true;
expect(loadObj(objExternalResourcesInRootPath, options)
.then(function(data) {
var materials = data.materials;
expect(materials.length).toBe(2);
const data = await loadObj(objExternalResourcesInRootPath, options);
const 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];
var baseColorTexture = materialTextured.pbrMetallicRoughness.baseColorTexture;
expect(baseColorTexture.source).toBeDefined();
expect(baseColorTexture.name).toEqual('cesium');
}), done).toResolve();
// .mtl files are loaded in an arbitrary order, so find the "MaterialTextured" material
const materialTextured = materials[0].name === 'MaterialTextured' ? materials[0] : materials[1];
const baseColorTexture = materialTextured.pbrMetallicRoughness.baseColorTexture;
expect(baseColorTexture.source).toBeDefined();
expect(baseColorTexture.name).toEqual('cesium');
});
it('loads obj with texture', function(done) {
expect(loadObj(objTexturedPath, options)
.then(function(data) {
var baseColorTexture = data.materials[0].pbrMetallicRoughness.baseColorTexture;
expect(baseColorTexture.name).toBe('cesium');
expect(baseColorTexture.source).toBeDefined();
}), done).toResolve();
it('loads obj with texture', async () => {
const data = await loadObj(objTexturedPath, options);
const baseColorTexture = data.materials[0].pbrMetallicRoughness.baseColorTexture;
expect(baseColorTexture.name).toBe('cesium');
expect(baseColorTexture.source).toBeDefined();
});
it('loads obj with missing texture', function(done) {
var spy = jasmine.createSpy('logger');
it('loads obj with missing texture', async () => {
const spy = jasmine.createSpy('logger');
options.logger = spy;
expect(loadObj(objMissingTexturePath, options)
.then(function(data) {
var baseColorTexture = data.materials[0].pbrMetallicRoughness.baseColorTexture;
expect(baseColorTexture).toBeUndefined();
expect(spy.calls.argsFor(0)[0].indexOf('ENOENT') >= 0).toBe(true);
expect(spy.calls.argsFor(1)[0].indexOf('Attempting to read the texture file from within the obj directory instead.') >= 0).toBe(true);
expect(spy.calls.argsFor(2)[0].indexOf('ENOENT') >= 0).toBe(true);
expect(spy.calls.argsFor(3)[0].indexOf('Could not read texture file') >= 0).toBe(true);
}), done).toResolve();
const data = await loadObj(objMissingTexturePath, options);
const baseColorTexture = data.materials[0].pbrMetallicRoughness.baseColorTexture;
expect(baseColorTexture).toBeUndefined();
expect(spy.calls.argsFor(0)[0].indexOf('ENOENT') >= 0).toBe(true);
expect(spy.calls.argsFor(1)[0].indexOf('Attempting to read the texture file from within the obj directory instead.') >= 0).toBe(true);
expect(spy.calls.argsFor(2)[0].indexOf('ENOENT') >= 0).toBe(true);
expect(spy.calls.argsFor(3)[0].indexOf('Could not read texture file') >= 0).toBe(true);
});
it('loads obj with subdirectories', function(done) {
expect(loadObj(objSubdirectoriesPath, options)
.then(function(data) {
var baseColorTexture = data.materials[0].pbrMetallicRoughness.baseColorTexture;
expect(baseColorTexture.name).toBe('cesium');
expect(baseColorTexture.source).toBeDefined();
}), done).toResolve();
it('loads obj with subdirectories', async () => {
const data = await loadObj(objSubdirectoriesPath, options);
const baseColorTexture = data.materials[0].pbrMetallicRoughness.baseColorTexture;
expect(baseColorTexture.name).toBe('cesium');
expect(baseColorTexture.source).toBeDefined();
});
it('loads obj with windows paths', function(done) {
expect(loadObj(objWindowsPaths, options)
.then(function(data) {
var baseColorTexture = data.materials[0].pbrMetallicRoughness.baseColorTexture;
expect(baseColorTexture.name).toBe('cesium');
expect(baseColorTexture.source).toBeDefined();
}), done).toResolve();
it('loads obj with windows paths', async () => {
const data = await loadObj(objWindowsPaths, options);
const baseColorTexture = data.materials[0].pbrMetallicRoughness.baseColorTexture;
expect(baseColorTexture.name).toBe('cesium');
expect(baseColorTexture.source).toBeDefined();
});
it('separates faces that don\'t use the same attributes as other faces in the primitive', function(done) {
expect(loadObj(objMixedAttributesPath, options)
.then(function(data) {
var primitives = getPrimitives(data);
expect(primitives.length).toBe(4);
expect(primitives[0].indices.length).toBe(18); // 6 faces
expect(primitives[1].indices.length).toBe(6); // 2 faces
expect(primitives[2].indices.length).toBe(6); // 2 faces
expect(primitives[3].indices.length).toBe(6); // 2 faces
}), done).toResolve();
it('separates faces that don\'t use the same attributes as other faces in the primitive', async () => {
const data = await loadObj(objMixedAttributesPath, options);
const primitives = getPrimitives(data);
expect(primitives.length).toBe(4);
expect(primitives[0].indices.length).toBe(18); // 6 faces
expect(primitives[1].indices.length).toBe(6); // 2 faces
expect(primitives[2].indices.length).toBe(6); // 2 faces
expect(primitives[3].indices.length).toBe(6); // 2 faces
});
it('throws when file has invalid contents', function(done) {
expect(loadObj(objInvalidContentsPath, options), done).toRejectWith(RuntimeError);
it('throws when file has invalid contents', async () => {
let thrownError;
try {
await loadObj(objInvalidContentsPath, options);
} catch (e) {
thrownError = e;
}
expect(thrownError).toEqual(new RuntimeError(objInvalidContentsPath + ' does not have any geometry data'));
});
it('throw when reading invalid file', function(done) {
expect(loadObj(objInvalidPath, options), done).toRejectWith(Error);
it('throw when reading invalid file', async () => {
let thrownError;
try {
await loadObj(objInvalidPath, options);
} catch (e) {
thrownError = e;
}
expect(thrownError.message.startsWith('ENOENT: no such file or directory')).toBe(true);
});
});

View File

@ -1,117 +1,99 @@
'use strict';
var loadTexture = require('../../lib/loadTexture');
const loadTexture = require('../../lib/loadTexture');
var pngTexturePath = 'specs/data/box-complex-material/shininess.png';
var jpgTexturePath = 'specs/data/box-complex-material/emission.jpg';
var jpegTexturePath = 'specs/data/box-complex-material/specular.jpeg';
var gifTexturePath = 'specs/data/box-complex-material/ambient.gif';
var grayscaleTexturePath = 'specs/data/box-complex-material-alpha/alpha.png';
var transparentTexturePath = 'specs/data/box-complex-material/diffuse.png';
const pngTexturePath = 'specs/data/box-complex-material/shininess.png';
const jpgTexturePath = 'specs/data/box-complex-material/emission.jpg';
const jpegTexturePath = 'specs/data/box-complex-material/specular.jpeg';
const gifTexturePath = 'specs/data/box-complex-material/ambient.gif';
const grayscaleTexturePath = 'specs/data/box-complex-material-alpha/alpha.png';
const transparentTexturePath = 'specs/data/box-complex-material/diffuse.png';
describe('loadTexture', function() {
it('loads png texture', function(done) {
expect(loadTexture(pngTexturePath)
.then(function(texture) {
expect(texture.transparent).toBe(false);
expect(texture.source).toBeDefined();
expect(texture.name).toBe('shininess');
expect(texture.extension).toBe('.png');
expect(texture.path).toBe(pngTexturePath);
expect(texture.pixels).toBeUndefined();
expect(texture.width).toBeUndefined();
expect(texture.height).toBeUndefined();
}), done).toResolve();
describe('loadTexture', () => {
it('loads png texture', async () => {
const texture = await loadTexture(pngTexturePath);
expect(texture.transparent).toBe(false);
expect(texture.source).toBeDefined();
expect(texture.name).toBe('shininess');
expect(texture.extension).toBe('.png');
expect(texture.path).toBe(pngTexturePath);
expect(texture.pixels).toBeUndefined();
expect(texture.width).toBeUndefined();
expect(texture.height).toBeUndefined();
});
it('loads jpg texture', function(done) {
expect(loadTexture(jpgTexturePath)
.then(function(texture) {
expect(texture.transparent).toBe(false);
expect(texture.source).toBeDefined();
expect(texture.name).toBe('emission');
expect(texture.extension).toBe('.jpg');
expect(texture.path).toBe(jpgTexturePath);
expect(texture.pixels).toBeUndefined();
expect(texture.width).toBeUndefined();
expect(texture.height).toBeUndefined();
}), done).toResolve();
it('loads jpg texture', async () => {
const texture = await loadTexture(jpgTexturePath);
expect(texture.transparent).toBe(false);
expect(texture.source).toBeDefined();
expect(texture.name).toBe('emission');
expect(texture.extension).toBe('.jpg');
expect(texture.path).toBe(jpgTexturePath);
expect(texture.pixels).toBeUndefined();
expect(texture.width).toBeUndefined();
expect(texture.height).toBeUndefined();
});
it('loads jpeg texture', function(done) {
expect(loadTexture(jpegTexturePath)
.then(function(texture) {
expect(texture.transparent).toBe(false);
expect(texture.source).toBeDefined();
expect(texture.name).toBe('specular');
expect(texture.extension).toBe('.jpeg');
expect(texture.path).toBe(jpegTexturePath);
expect(texture.pixels).toBeUndefined();
expect(texture.width).toBeUndefined();
expect(texture.height).toBeUndefined();
}), done).toResolve();
it('loads jpeg texture', async () => {
const texture = await loadTexture(jpegTexturePath);
expect(texture.transparent).toBe(false);
expect(texture.source).toBeDefined();
expect(texture.name).toBe('specular');
expect(texture.extension).toBe('.jpeg');
expect(texture.path).toBe(jpegTexturePath);
expect(texture.pixels).toBeUndefined();
expect(texture.width).toBeUndefined();
expect(texture.height).toBeUndefined();
});
it('loads gif texture', function(done) {
expect(loadTexture(gifTexturePath)
.then(function(texture) {
expect(texture.transparent).toBe(false);
expect(texture.source).toBeDefined();
expect(texture.name).toBe('ambient');
expect(texture.extension).toBe('.gif');
expect(texture.path).toBe(gifTexturePath);
expect(texture.pixels).toBeUndefined();
expect(texture.width).toBeUndefined();
expect(texture.height).toBeUndefined();
}), done).toResolve();
it('loads gif texture', async () => {
const texture = await loadTexture(gifTexturePath);
expect(texture.transparent).toBe(false);
expect(texture.source).toBeDefined();
expect(texture.name).toBe('ambient');
expect(texture.extension).toBe('.gif');
expect(texture.path).toBe(gifTexturePath);
expect(texture.pixels).toBeUndefined();
expect(texture.width).toBeUndefined();
expect(texture.height).toBeUndefined();
});
it('loads grayscale texture', function(done) {
expect(loadTexture(grayscaleTexturePath)
.then(function(texture) {
expect(texture.transparent).toBe(false);
expect(texture.source).toBeDefined();
expect(texture.extension).toBe('.png');
}), done).toResolve();
it('loads grayscale texture', async () => {
const texture = await loadTexture(grayscaleTexturePath);
expect(texture.transparent).toBe(false);
expect(texture.source).toBeDefined();
expect(texture.extension).toBe('.png');
});
it('loads texture with alpha channel', function(done) {
expect(loadTexture(transparentTexturePath)
.then(function(texture) {
expect(texture.transparent).toBe(false);
}), done).toResolve();
it('loads texture with alpha channel', async () => {
const texture = await loadTexture(transparentTexturePath);
expect(texture.transparent).toBe(false);
});
it('loads texture with checkTransparency flag', function(done) {
var options = {
it('loads texture with checkTransparency flag', async () => {
const options = {
checkTransparency : true
};
expect(loadTexture(transparentTexturePath, options)
.then(function(texture) {
expect(texture.transparent).toBe(true);
}), done).toResolve();
const texture = await loadTexture(transparentTexturePath, options);
expect(texture.transparent).toBe(true);
});
it('loads and decodes png', function(done) {
var options = {
it('loads and decodes png', async () => {
const options = {
decode : true
};
expect(loadTexture(pngTexturePath, options)
.then(function(texture) {
expect(texture.pixels).toBeDefined();
expect(texture.width).toBe(211);
expect(texture.height).toBe(211);
}), done).toResolve();
const texture = await loadTexture(pngTexturePath, options);
expect(texture.pixels).toBeDefined();
expect(texture.width).toBe(211);
expect(texture.height).toBe(211);
});
it('loads and decodes jpeg', function(done) {
var options = {
it('loads and decodes jpeg', async () => {
const options = {
decode : true
};
expect(loadTexture(jpegTexturePath, options)
.then(function(texture) {
expect(texture.pixels).toBeDefined();
expect(texture.width).toBe(211);
expect(texture.height).toBe(211);
}), done).toResolve();
const texture = await loadTexture(jpegTexturePath, options);
expect(texture.pixels).toBeDefined();
expect(texture.width).toBe(211);
expect(texture.height).toBe(211);
});
});

View File

@ -1,79 +1,70 @@
'use strict';
var fsExtra = require('fs-extra');
var path = require('path');
var Promise = require('bluebird');
var obj2gltf = require('../../lib/obj2gltf');
const { DeveloperError } = require('cesium');
const fsExtra = require('fs-extra');
const path = require('path');
const Promise = require('bluebird');
const obj2gltf = require('../../lib/obj2gltf');
var texturedObjPath = 'specs/data/box-textured/box-textured.obj';
var complexObjPath = 'specs/data/box-complex-material/box-complex-material.obj';
var missingMtllibObjPath = 'specs/data/box-missing-mtllib/box-missing-mtllib.obj';
const texturedObjPath = 'specs/data/box-textured/box-textured.obj';
const complexObjPath = 'specs/data/box-complex-material/box-complex-material.obj';
const missingMtllibObjPath = 'specs/data/box-missing-mtllib/box-missing-mtllib.obj';
var outputDirectory = 'output';
const outputDirectory = 'output';
var textureUrl = 'specs/data/box-textured/cesium.png';
const textureUrl = 'specs/data/box-textured/cesium.png';
describe('obj2gltf', function() {
beforeEach(function() {
describe('obj2gltf', () => {
beforeEach(() => {
spyOn(fsExtra, 'outputFile').and.returnValue(Promise.resolve());
});
it('converts obj to gltf', function(done) {
expect(obj2gltf(texturedObjPath)
.then(function(gltf) {
expect(gltf).toBeDefined();
expect(gltf.images.length).toBe(1);
}), done).toResolve();
it('converts obj to gltf', async () => {
const gltf = await obj2gltf(texturedObjPath);
expect(gltf).toBeDefined();
expect(gltf.images.length).toBe(1);
});
it('converts obj to glb', function(done) {
var options = {
it('converts obj to glb', async () => {
const options = {
binary : true
};
expect(obj2gltf(texturedObjPath, options)
.then(function(glb) {
var magic = glb.toString('utf8', 0, 4);
expect(magic).toBe('glTF');
}), done).toResolve();
const glb = await obj2gltf(texturedObjPath, options);
const magic = glb.toString('utf8', 0, 4);
expect(magic).toBe('glTF');
});
it('convert obj to gltf with separate resources', function(done) {
var options = {
it('convert obj to gltf with separate resources', async () => {
const options = {
separate : true,
separateTextures : true,
outputDirectory : outputDirectory
};
expect(obj2gltf(texturedObjPath, options)
.then(function() {
expect(fsExtra.outputFile.calls.count()).toBe(2); // Saves out .png and .bin
}), done).toResolve();
await obj2gltf(texturedObjPath, options);
expect(fsExtra.outputFile.calls.count()).toBe(2); // Saves out .png and .bin
});
it('converts obj to glb with separate resources', function(done) {
var options = {
it('converts obj to glb with separate resources', async () => {
const options = {
separate : true,
separateTextures : true,
outputDirectory : outputDirectory,
binary : true
};
expect(obj2gltf(texturedObjPath, options)
.then(function() {
expect(fsExtra.outputFile.calls.count()).toBe(2); // Saves out .png and .bin
}), done).toResolve();
await obj2gltf(texturedObjPath, options);
expect(fsExtra.outputFile.calls.count()).toBe(2); // Saves out .png and .bin
});
it('converts obj with multiple textures', function(done) {
var options = {
it('converts obj with multiple textures', async () => {
const options = {
separateTextures : true,
outputDirectory : outputDirectory
};
expect(obj2gltf(complexObjPath, options)
.then(function() {
expect(fsExtra.outputFile.calls.count()).toBe(5); // baseColor, metallicRoughness, occlusion, emission, normal
}), done).toResolve();
await obj2gltf(complexObjPath, options);
expect(fsExtra.outputFile.calls.count()).toBe(5); // baseColor, metallicRoughness, occlusion, emission, normal
});
it('sets overriding textures (1)', function(done) {
var options = {
it('sets overriding textures (1)', async () => {
const options = {
overridingTextures : {
metallicRoughnessOcclusionTexture : textureUrl,
normalTexture : textureUrl,
@ -84,18 +75,16 @@ describe('obj2gltf', function() {
separateTextures : true,
outputDirectory : outputDirectory
};
expect(obj2gltf(complexObjPath, options)
.then(function() {
var args = fsExtra.outputFile.calls.allArgs();
var length = args.length;
for (var i = 0; i < length; ++i) {
expect(path.basename(args[i][0])).toBe(path.basename(textureUrl));
}
}), done).toResolve();
await obj2gltf(complexObjPath, options);
const args = fsExtra.outputFile.calls.allArgs();
const length = args.length;
for (let i = 0; i < length; ++i) {
expect(path.basename(args[i][0])).toBe(path.basename(textureUrl));
}
});
it('sets overriding textures (2)', function(done) {
var options = {
it('sets overriding textures (2)', async () => {
const options = {
overridingTextures : {
specularGlossinessTexture : textureUrl,
occlusionTexture : textureUrl,
@ -107,81 +96,94 @@ describe('obj2gltf', function() {
separateTextures : true,
outputDirectory : outputDirectory
};
expect(obj2gltf(complexObjPath, options)
.then(function() {
var args = fsExtra.outputFile.calls.allArgs();
var length = args.length;
for (var i = 0; i < length; ++i) {
expect(path.basename(args[i][0])).toBe(path.basename(textureUrl));
}
}), done).toResolve();
await obj2gltf(complexObjPath, options);
const args = fsExtra.outputFile.calls.allArgs();
const length = args.length;
for (let i = 0; i < length; ++i) {
expect(path.basename(args[i][0])).toBe(path.basename(textureUrl));
}
});
it('uses a custom logger', function(done) {
var lastMessage;
var options = {
logger : function(message) {
it('uses a custom logger', async () => {
let lastMessage;
const options = {
logger : (message) => {
lastMessage = message;
}
};
expect(obj2gltf(missingMtllibObjPath, options)
.then(function() {
expect(lastMessage.indexOf('Could not read material file') >= 0).toBe(true);
}), done).toResolve();
await obj2gltf(missingMtllibObjPath, options);
expect(lastMessage.indexOf('Could not read material file') >= 0).toBe(true);
});
it('uses a custom writer', function(done) {
var filePaths = [];
var fileContents = [];
var options = {
it('uses a custom writer', async () => {
const filePaths = [];
const fileContents = [];
const options = {
separate : true,
writer : function(relativePath, contents) {
writer : (relativePath, contents) => {
filePaths.push(relativePath);
fileContents.push(contents);
}
};
expect(obj2gltf(texturedObjPath, options)
.then(function() {
expect(filePaths).toEqual(['box-textured.bin', 'cesium.png']);
expect(fileContents[0]).toBeDefined();
expect(fileContents[1]).toBeDefined();
}), done).toResolve();
await obj2gltf(texturedObjPath, options);
expect(filePaths).toEqual(['box-textured.bin', 'cesium.png']);
expect(fileContents[0]).toBeDefined();
expect(fileContents[1]).toBeDefined();
});
it('throws if objPath is undefined', function() {
expect(function() {
it('throws if objPath is undefined', () => {
let thrownError;
try {
obj2gltf(undefined);
}).toThrowDeveloperError();
} catch (e) {
thrownError = e;
}
expect(thrownError).toEqual(new DeveloperError('objPath is required'));
});
it('throws if both options.writer and options.outputDirectory are undefined when writing separate resources', function() {
var options = {
it('throws if both options.writer and options.outputDirectory are undefined when writing separate resources', () => {
const options = {
separateTextures : true
};
expect(function() {
let thrownError;
try {
obj2gltf(texturedObjPath, options);
}).toThrowDeveloperError();
} catch (e) {
thrownError = e;
}
expect(thrownError).toEqual(new DeveloperError('Either options.writer or options.outputDirectory must be defined when writing separate resources.'));
});
it('throws if more than one material type is set', function() {
var options = {
it('throws if more than one material type is set', () => {
const options = {
metallicRoughness : true,
specularGlossiness : true
};
expect(function() {
let thrownError;
try {
obj2gltf(texturedObjPath, options);
}).toThrowDeveloperError();
} catch (e) {
thrownError = e;
}
expect(thrownError).toEqual(new DeveloperError('Only one material type may be set from [metallicRoughness, specularGlossiness, unlit].'));
});
it('throws if metallicRoughnessOcclusionTexture and specularGlossinessTexture are both defined', function() {
var options = {
it('throws if metallicRoughnessOcclusionTexture and specularGlossinessTexture are both defined', () => {
const options = {
overridingTextures : {
metallicRoughnessOcclusionTexture : textureUrl,
specularGlossinessTexture : textureUrl
}
};
expect(function() {
let thrownError;
try {
obj2gltf(texturedObjPath, options);
}).toThrowDeveloperError();
} catch (e) {
thrownError = e;
}
expect(thrownError).toEqual(new DeveloperError('metallicRoughnessOcclusionTexture and specularGlossinessTexture cannot both be defined.'));
});
});

View File

@ -1,216 +0,0 @@
//This file is a copy of https://github.com/AnalyticalGraphicsInc/cesium/blob/master/Specs/addDefaultMatchers.js
/*eslint strict: ["error", "function"]*/
/*eslint-env amd*/
/*eslint-disable no-unused-vars*/
define([
'./equals',
'Cesium/Core/defined',
'Cesium/Core/DeveloperError',
'Cesium/Core/RuntimeError'
], function(
equals,
defined,
DeveloperError,
RuntimeError) {
'use strict';
function createMissingFunctionMessageFunction(item, actualPrototype, expectedInterfacePrototype) {
return function() {
return 'Expected function \'' + item + '\' to exist on ' + actualPrototype.constructor.name + ' because it should implement interface ' + expectedInterfacePrototype.constructor.name + '.';
};
}
function makeThrowFunction(debug, Type, name) {
if (debug) {
return function(util, customEqualityTesters) {
return {
compare : function(actual, expected) {
// based on the built-in Jasmine toThrow matcher
var result = false;
var exception;
if (typeof actual !== 'function') {
throw new Error('Actual is not a function');
}
try {
actual();
} catch (e) {
exception = e;
}
if (exception) {
result = exception instanceof Type;
}
var message;
if (result) {
message = ['Expected function not to throw ' + name + ' , but it threw', exception.message || exception].join(' ');
if (defined(expected)) {
expect(expected).toEqual(exception.message);
}
} else {
message = 'Expected function to throw ' + name + '.';
}
return {
pass : result,
message : message
};
}
};
};
}
return function() {
return {
compare : function(actual, expected) {
return { pass : true };
},
negativeCompare : function(actual, expected) {
return { pass : true };
}
};
};
}
function createDefaultMatchers(debug) {
return {
toBeGreaterThanOrEqualTo : function(util, customEqualityTesters) {
return {
compare: function(actual, expected) {
return { pass : actual >= expected };
}
};
},
toBeLessThanOrEqualTo : function(util, customEqualityTesters) {
return {
compare: function(actual, expected) {
return { pass : actual <= expected };
}
};
},
toBeBetween : function(util, customEqualityTesters) {
return {
compare: function(actual, lower, upper) {
if (lower > upper) {
var tmp = upper;
upper = lower;
lower = tmp;
}
return { pass : actual >= lower && actual <= upper };
}
};
},
toStartWith : function(util, customEqualityTesters) {
return {
compare: function(actual, expected) {
return { pass : actual.slice(0, expected.length) === expected };
}
};
},
toEndWith : function(util, customEqualityTesters) {
return {
compare: function(actual, expected) {
return { pass : actual.slice(-expected.length) === expected };
}
};
},
toEqual : function(util, customEqualityTesters) {
return {
compare: function(actual, expected) {
return { pass : equals(util, customEqualityTesters, actual, expected) };
}
};
},
toEqualEpsilon : function(util, customEqualityTesters) {
return {
compare: function(actual, expected, epsilon) {
function equalityTester(a, b) {
var to_run;
if (defined(a)) {
if (typeof a.equalsEpsilon === 'function') {
return a.equalsEpsilon(b, epsilon);
} else if (a instanceof Object) {
// Check if the current object has a static function named 'equalsEpsilon'
to_run = Object.getPrototypeOf(a).constructor.equalsEpsilon;
if (typeof to_run === 'function') {
return to_run(a, b, epsilon);
}
}
}
if (defined(b)) {
if (typeof b.equalsEpsilon === 'function') {
return b.equalsEpsilon(a, epsilon);
} else if (b instanceof Object) {
// Check if the current object has a static function named 'equalsEpsilon'
to_run = Object.getPrototypeOf(b).constructor.equalsEpsilon;
if (typeof to_run === 'function') {
return to_run(b, a, epsilon);
}
}
}
if (typeof a === 'number' || typeof b === 'number') {
return Math.abs(a - b) <= epsilon;
}
return undefined;
}
var result = equals(util, [equalityTester], actual, expected);
return { pass : result };
}
};
},
toConformToInterface : function(util, customEqualityTesters) {
return {
compare : function(actual, expectedInterface) {
// All function properties on the prototype should also exist on the actual's prototype.
var actualPrototype = actual.prototype;
var expectedInterfacePrototype = expectedInterface.prototype;
for ( var item in expectedInterfacePrototype) {
if (expectedInterfacePrototype.hasOwnProperty(item) && typeof expectedInterfacePrototype[item] === 'function' && !actualPrototype.hasOwnProperty(item)) {
return { pass : false, message : createMissingFunctionMessageFunction(item, actualPrototype, expectedInterfacePrototype) };
}
}
return { pass : true };
}
};
},
toBeInstanceOf : function(util, customEqualityTesters) {
return {
compare : function(actual, expectedConstructor) {
return { pass : actual instanceof expectedConstructor };
}
};
},
toThrow : function(expectedConstructor) {
throw new Error('Do not use toThrow. Use toThrowDeveloperError or toThrowRuntimeError instead.');
},
toThrowDeveloperError : makeThrowFunction(debug, DeveloperError, 'DeveloperError'),
toThrowRuntimeError : makeThrowFunction(true, RuntimeError, 'RuntimeError')
};
}
return function(debug) {
return function() {
this.addMatchers(createDefaultMatchers(debug));
};
};
});

View File

@ -1,16 +0,0 @@
/*eslint strict: ["error", "function"]*/
/*eslint-env amd*/
define([
'./addDefaultMatchers',
'./equalsMethodEqualityTester'
], function (addDefaultMatchers,
equalsMethodEqualityTester) {
'use strict';
return function (env) {
env.beforeEach(function () {
addDefaultMatchers(true).call(env);
env.addCustomEqualityTester(equalsMethodEqualityTester);
});
};
});

View File

@ -1,46 +0,0 @@
//This file is a copy of https://github.com/AnalyticalGraphicsInc/cesium/blob/master/Specs/equals.js
/*eslint strict: ["error", "function"]*/
/*eslint-env amd*/
define([
'Cesium/Core/FeatureDetection'
], function(
FeatureDetection) {
'use strict';
/*global CanvasPixelArray*/
var typedArrayTypes = [];
// Earlier versions of IE do not support typed arrays
if (FeatureDetection.supportsTypedArrays()) {
typedArrayTypes.push(Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array);
if (typeof Uint8ClampedArray !== 'undefined') {
typedArrayTypes.push(Uint8ClampedArray);
}
if (typeof CanvasPixelArray !== 'undefined') {
typedArrayTypes.push(CanvasPixelArray);
}
}
function isTypedArray(o) {
return typedArrayTypes.some(function(type) {
return o instanceof type;
});
}
function typedArrayToArray(array) {
if (array !== null && typeof array === 'object' && isTypedArray(array)) {
return Array.prototype.slice.call(array, 0);
}
return array;
}
function equals(util, customEqualiyTesters, a, b) {
a = typedArrayToArray(a);
b = typedArrayToArray(b);
return util.equals(a, b, customEqualiyTesters);
}
return equals;
});

View File

@ -1,40 +0,0 @@
//This file is a copy of https://github.com/AnalyticalGraphicsInc/cesium/blob/master/Specs/equalsMethodEqualityTester.js
/*eslint strict: ["error", "function"]*/
/*eslint-env amd*/
define([
'Cesium/Core/defined'
], function(
defined) {
'use strict';
return function(a, b) {
var to_run;
// if either a or b have an equals method, call it.
if (a !== null && defined(a)) {
if (typeof a.equals === 'function') {
return a.equals(b);
} else if(a instanceof Object) {
// Check if the current object has a static function named 'equals'
to_run = Object.getPrototypeOf(a).constructor.equals;
if( typeof to_run === 'function') {
return to_run(a, b);
}
}
}
if (b !== null && defined(b)) {
if (typeof b.equals === 'function') {
return b.equals(a);
} else if(b instanceof Object) {
// Check if the current object has a static function named 'equals'
to_run = Object.getPrototypeOf(b).constructor.equals;
if( typeof to_run === 'function') {
return to_run(b, a);
}
}
}
// fall back to default equality checks.
return undefined;
};
});

View File

@ -1,47 +0,0 @@
'use strict';
var Cesium = require('cesium');
var defined = Cesium.defined;
var defaultValue = Cesium.defaultValue;
module.exports = function expectPrommise(promise, done) {
return {
toResolve: function toResolve() {
return promise
.then(done)
.catch(function(err){
done.fail('Expected promise to resolve' + err);
});
},
toResolveWith: function toResolveWith(expectedValue) {
return promise
.then(function (result) {
expect(result).toEqual(expectedValue);
done();
})
.catch(function(err){
done.fail('Expected promise to resolve' + err);
});
},
toRejectWith: function toRejectWith(ErrorType, errorMessage) {
var typeName = defaultValue(ErrorType.displayName, ErrorType.name);
promise
.then(function () {
done.fail('expected promise to reject with ' + typeName);
})
.catch(function (error) {
if (!(error instanceof ErrorType)) {
done.fail(defaultValue(defaultValue(error.displayName, error.name), ErrorType) + ' to be instance of ' + typeName);
console.log(error);
}
if (defined(errorMessage)) {
expect(error.message).toEqual(errorMessage);
}
done();
});
}
};
};

View File

@ -1,33 +0,0 @@
'use strict';
var path = require('path');
var requirejs = require('requirejs');
var expectPromise = require('./expectPromise');
//Since Jasmine matchers are shared between client and server code
//We need to use requirejs to bring them into node.
requirejs.config({
baseUrl: path.join(__dirname, '../..'),
paths: {
'Cesium': 'node_modules/cesium/source'
},
nodeRequire: require
});
var customizeJasmine = requirejs('./specs/matchers/customizeJasmine');
var env = jasmine.getEnv();
customizeJasmine(env);
var oldExpect = global.expect;
global.expect = function (promise, done) {
//We can't use instanceof Promise here because promise
//may not be a bluebird-defined Promise
if (promise && promise.then && done) {
return expectPromise(promise, done);
}
//If it wasn't a promise, call original implementation
return oldExpect.apply(global, arguments);
};