mirror of
https://github.com/CesiumGS/obj2gltf.git
synced 2024-12-02 13:00:29 -05:00
Merge branch 'master' into remove-string-limitation
This commit is contained in:
commit
280a794a10
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"extends": "cesium/node",
|
"extends": "cesium/node",
|
||||||
"rules": {
|
"rules": {
|
||||||
"no-var": "off"
|
"no-unused-vars": ["error", {"args": "none"}]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="JavaScriptSettings">
|
<component name="JavaScriptSettings">
|
||||||
<option name="languageLevel" value="ES5" />
|
<option name="languageLevel" value="ES6" />
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
12
README.md
12
README.md
@ -24,11 +24,11 @@ npm install -g obj2gltf
|
|||||||
#### Converting an obj model to gltf:
|
#### Converting an obj model to gltf:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var obj2gltf = require('obj2gltf');
|
const obj2gltf = require('obj2gltf');
|
||||||
var fs = require('fs');
|
const fs = require('fs');
|
||||||
obj2gltf('model.obj')
|
obj2gltf('model.obj')
|
||||||
.then(function(gltf) {
|
.then(function(gltf) {
|
||||||
var data = Buffer.from(JSON.stringify(gltf));
|
const data = Buffer.from(JSON.stringify(gltf));
|
||||||
fs.writeFileSync('model.gltf', data);
|
fs.writeFileSync('model.gltf', data);
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
@ -36,9 +36,9 @@ obj2gltf('model.obj')
|
|||||||
#### Converting an obj model to glb
|
#### Converting an obj model to glb
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
var obj2gltf = require('obj2gltf');
|
const obj2gltf = require('obj2gltf');
|
||||||
var fs = require('fs');
|
const fs = require('fs');
|
||||||
var options = {
|
const options = {
|
||||||
binary : true
|
binary : true
|
||||||
}
|
}
|
||||||
obj2gltf('model.obj', options)
|
obj2gltf('model.obj', options)
|
||||||
|
@ -1,19 +1,19 @@
|
|||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
'use strict';
|
'use strict';
|
||||||
var Cesium = require('cesium');
|
const Cesium = require('cesium');
|
||||||
var fsExtra = require('fs-extra');
|
const fsExtra = require('fs-extra');
|
||||||
var path = require('path');
|
const path = require('path');
|
||||||
var yargs = require('yargs');
|
const yargs = require('yargs');
|
||||||
var obj2gltf = require('../lib/obj2gltf');
|
const obj2gltf = require('../lib/obj2gltf');
|
||||||
|
|
||||||
var defaultValue = Cesium.defaultValue;
|
const defaultValue = Cesium.defaultValue;
|
||||||
var defined = Cesium.defined;
|
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')
|
.usage('Usage: node $0 -i inputPath -o outputPath')
|
||||||
.example('node $0 -i ./specs/data/box/box.obj -o box.gltf')
|
.example('node $0 -i ./specs/data/box/box.obj -o box.gltf')
|
||||||
.help('h')
|
.help('h')
|
||||||
@ -135,18 +135,18 @@ if (defined(argv.metallicRoughnessOcclusionTexture) && defined(argv.specularGlos
|
|||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
var objPath = argv.input;
|
const objPath = argv.input;
|
||||||
var gltfPath = argv.output;
|
let gltfPath = argv.output;
|
||||||
|
|
||||||
var filename = defaultValue(gltfPath, objPath);
|
const filename = defaultValue(gltfPath, objPath);
|
||||||
var name = path.basename(filename, path.extname(filename));
|
const name = path.basename(filename, path.extname(filename));
|
||||||
var outputDirectory = path.dirname(filename);
|
const outputDirectory = path.dirname(filename);
|
||||||
var binary = argv.binary || path.extname(filename).toLowerCase() === '.glb';
|
const binary = argv.binary || path.extname(filename).toLowerCase() === '.glb';
|
||||||
var extension = binary ? '.glb' : '.gltf';
|
const extension = binary ? '.glb' : '.gltf';
|
||||||
|
|
||||||
gltfPath = path.join(outputDirectory, name + extension);
|
gltfPath = path.join(outputDirectory, name + extension);
|
||||||
|
|
||||||
var overridingTextures = {
|
const overridingTextures = {
|
||||||
metallicRoughnessOcclusionTexture : argv.metallicRoughnessOcclusionTexture,
|
metallicRoughnessOcclusionTexture : argv.metallicRoughnessOcclusionTexture,
|
||||||
specularGlossinessTexture : argv.specularGlossinessTexture,
|
specularGlossinessTexture : argv.specularGlossinessTexture,
|
||||||
occlusionTexture : argv.occlusionTexture,
|
occlusionTexture : argv.occlusionTexture,
|
||||||
@ -156,7 +156,7 @@ var overridingTextures = {
|
|||||||
alphaTexture : argv.alphaTexture
|
alphaTexture : argv.alphaTexture
|
||||||
};
|
};
|
||||||
|
|
||||||
var options = {
|
const options = {
|
||||||
binary : binary,
|
binary : binary,
|
||||||
separate : argv.separate,
|
separate : argv.separate,
|
||||||
separateTextures : argv.separateTextures,
|
separateTextures : argv.separateTextures,
|
||||||
@ -178,7 +178,7 @@ obj2gltf(objPath, options)
|
|||||||
// gltf is a glb buffer
|
// gltf is a glb buffer
|
||||||
return fsExtra.outputFile(gltfPath, gltf);
|
return fsExtra.outputFile(gltfPath, gltf);
|
||||||
}
|
}
|
||||||
var jsonOptions = {
|
const jsonOptions = {
|
||||||
spaces : 2
|
spaces : 2
|
||||||
};
|
};
|
||||||
return fsExtra.outputJson(gltfPath, gltf, jsonOptions);
|
return fsExtra.outputJson(gltfPath, gltf, jsonOptions);
|
||||||
|
38
gulpfile.js
38
gulpfile.js
@ -1,26 +1,26 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var Cesium = require('cesium');
|
const Cesium = require('cesium');
|
||||||
var Promise = require('bluebird');
|
const Promise = require('bluebird');
|
||||||
var child_process = require('child_process');
|
const child_process = require('child_process');
|
||||||
var fsExtra = require('fs-extra');
|
const fsExtra = require('fs-extra');
|
||||||
var gulp = require('gulp');
|
const gulp = require('gulp');
|
||||||
var Jasmine = require('jasmine');
|
const Jasmine = require('jasmine');
|
||||||
var JasmineSpecReporter = require('jasmine-spec-reporter').SpecReporter;
|
const JasmineSpecReporter = require('jasmine-spec-reporter').SpecReporter;
|
||||||
var open = require('open');
|
const open = require('open');
|
||||||
var path = require('path');
|
const path = require('path');
|
||||||
var yargs = require('yargs');
|
const yargs = require('yargs');
|
||||||
|
|
||||||
var defined = Cesium.defined;
|
const defined = Cesium.defined;
|
||||||
var argv = yargs.argv;
|
const argv = yargs.argv;
|
||||||
|
|
||||||
// Add third-party node module binaries to the system path
|
// Add third-party node module binaries to the system path
|
||||||
// since some tasks need to call them directly.
|
// since some tasks need to call them directly.
|
||||||
var environmentSeparator = process.platform === 'win32' ? ';' : ':';
|
const environmentSeparator = process.platform === 'win32' ? ';' : ':';
|
||||||
var nodeBinaries = path.join(__dirname, 'node_modules', '.bin');
|
const nodeBinaries = path.join(__dirname, 'node_modules', '.bin');
|
||||||
process.env.PATH += environmentSeparator + nodeBinaries;
|
process.env.PATH += environmentSeparator + nodeBinaries;
|
||||||
|
|
||||||
var specFiles = ['**/*.js', '!node_modules/**', '!coverage/**', '!doc/**', '!bin/**'];
|
const specFiles = ['**/*.js', '!node_modules/**', '!coverage/**', '!doc/**', '!bin/**'];
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
test: test,
|
test: test,
|
||||||
@ -30,7 +30,7 @@ module.exports = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
function test(done) {
|
function test(done) {
|
||||||
var jasmine = new Jasmine();
|
const jasmine = new Jasmine();
|
||||||
jasmine.loadConfigFile('specs/jasmine.json');
|
jasmine.loadConfigFile('specs/jasmine.json');
|
||||||
jasmine.addReporter(new JasmineSpecReporter({
|
jasmine.addReporter(new JasmineSpecReporter({
|
||||||
displaySuccessfulSpec: !defined(argv.suppressPassed) || !argv.suppressPassed
|
displaySuccessfulSpec: !defined(argv.suppressPassed) || !argv.suppressPassed
|
||||||
@ -70,11 +70,11 @@ async function coverage() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function cloc() {
|
function cloc() {
|
||||||
var cmdLine;
|
let cmdLine;
|
||||||
var clocPath = path.join('node_modules', 'cloc', 'lib', 'cloc');
|
const clocPath = path.join('node_modules', 'cloc', 'lib', 'cloc');
|
||||||
|
|
||||||
//Run cloc on primary Source files only
|
//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' +
|
cmdLine = 'perl ' + clocPath + ' --quiet --progress-rate=0' +
|
||||||
' lib/ bin/';
|
' lib/ bin/';
|
||||||
|
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
var Cesium = require('cesium');
|
const Cesium = require('cesium');
|
||||||
|
|
||||||
var ComponentDatatype = Cesium.ComponentDatatype;
|
const ComponentDatatype = Cesium.ComponentDatatype;
|
||||||
|
|
||||||
module.exports = ArrayStorage;
|
module.exports = ArrayStorage;
|
||||||
|
|
||||||
var initialLength = 1024; // 2^10
|
const initialLength = 1024; // 2^10
|
||||||
var doublingThreshold = 33554432; // 2^25 (~134 MB for a Float32Array)
|
const doublingThreshold = 33554432; // 2^25 (~134 MB for a Float32Array)
|
||||||
var fixedExpansionLength = 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
|
* 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) {
|
function resize(storage, length) {
|
||||||
var typedArray = ComponentDatatype.createTypedArray(storage.componentDatatype, length);
|
const typedArray = ComponentDatatype.createTypedArray(storage.componentDatatype, length);
|
||||||
typedArray.set(storage.typedArray);
|
typedArray.set(storage.typedArray);
|
||||||
storage.typedArray = typedArray;
|
storage.typedArray = typedArray;
|
||||||
}
|
}
|
||||||
|
|
||||||
ArrayStorage.prototype.push = function(value) {
|
ArrayStorage.prototype.push = function(value) {
|
||||||
var length = this.length;
|
const length = this.length;
|
||||||
var typedArrayLength = this.typedArray.length;
|
const typedArrayLength = this.typedArray.length;
|
||||||
|
|
||||||
if (length === 0) {
|
if (length === 0) {
|
||||||
resize(this, initialLength);
|
resize(this, initialLength);
|
||||||
@ -50,51 +50,51 @@ ArrayStorage.prototype.get = function(index) {
|
|||||||
return this.typedArray[index];
|
return this.typedArray[index];
|
||||||
};
|
};
|
||||||
|
|
||||||
var sizeOfUint16 = 2;
|
const sizeOfUint16 = 2;
|
||||||
var sizeOfUint32 = 4;
|
const sizeOfUint32 = 4;
|
||||||
var sizeOfFloat = 4;
|
const sizeOfFloat = 4;
|
||||||
|
|
||||||
ArrayStorage.prototype.toUint16Buffer = function() {
|
ArrayStorage.prototype.toUint16Buffer = function() {
|
||||||
var length = this.length;
|
const length = this.length;
|
||||||
var typedArray = this.typedArray;
|
const typedArray = this.typedArray;
|
||||||
var paddedLength = length + ((length % 2 === 0) ? 0 : 1); // Round to next multiple of 2
|
const paddedLength = length + ((length % 2 === 0) ? 0 : 1); // Round to next multiple of 2
|
||||||
var buffer = Buffer.alloc(paddedLength * sizeOfUint16);
|
const buffer = Buffer.alloc(paddedLength * sizeOfUint16);
|
||||||
for (var i = 0; i < length; ++i) {
|
for (let i = 0; i < length; ++i) {
|
||||||
buffer.writeUInt16LE(typedArray[i], i * sizeOfUint16);
|
buffer.writeUInt16LE(typedArray[i], i * sizeOfUint16);
|
||||||
}
|
}
|
||||||
return buffer;
|
return buffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
ArrayStorage.prototype.toUint32Buffer = function() {
|
ArrayStorage.prototype.toUint32Buffer = function() {
|
||||||
var length = this.length;
|
const length = this.length;
|
||||||
var typedArray = this.typedArray;
|
const typedArray = this.typedArray;
|
||||||
var buffer = Buffer.alloc(length * sizeOfUint32);
|
const buffer = Buffer.alloc(length * sizeOfUint32);
|
||||||
for (var i = 0; i < length; ++i) {
|
for (let i = 0; i < length; ++i) {
|
||||||
buffer.writeUInt32LE(typedArray[i], i * sizeOfUint32);
|
buffer.writeUInt32LE(typedArray[i], i * sizeOfUint32);
|
||||||
}
|
}
|
||||||
return buffer;
|
return buffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
ArrayStorage.prototype.toFloatBuffer = function() {
|
ArrayStorage.prototype.toFloatBuffer = function() {
|
||||||
var length = this.length;
|
const length = this.length;
|
||||||
var typedArray = this.typedArray;
|
const typedArray = this.typedArray;
|
||||||
var buffer = Buffer.alloc(length * sizeOfFloat);
|
const buffer = Buffer.alloc(length * sizeOfFloat);
|
||||||
for (var i = 0; i < length; ++i) {
|
for (let i = 0; i < length; ++i) {
|
||||||
buffer.writeFloatLE(typedArray[i], i * sizeOfFloat);
|
buffer.writeFloatLE(typedArray[i], i * sizeOfFloat);
|
||||||
}
|
}
|
||||||
return buffer;
|
return buffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
ArrayStorage.prototype.getMinMax = function(components) {
|
ArrayStorage.prototype.getMinMax = function(components) {
|
||||||
var length = this.length;
|
const length = this.length;
|
||||||
var typedArray = this.typedArray;
|
const typedArray = this.typedArray;
|
||||||
var count = length / components;
|
const count = length / components;
|
||||||
var min = new Array(components).fill(Number.POSITIVE_INFINITY);
|
const min = new Array(components).fill(Number.POSITIVE_INFINITY);
|
||||||
var max = new Array(components).fill(Number.NEGATIVE_INFINITY);
|
const max = new Array(components).fill(Number.NEGATIVE_INFINITY);
|
||||||
for (var i = 0; i < count; ++i) {
|
for (let i = 0; i < count; ++i) {
|
||||||
for (var j = 0; j < components; ++j) {
|
for (let j = 0; j < components; ++j) {
|
||||||
var index = i * components + j;
|
const index = i * components + j;
|
||||||
var value = typedArray[index];
|
const value = typedArray[index];
|
||||||
min[j] = Math.min(min[j], value);
|
min[j] = Math.min(min[j], value);
|
||||||
max[j] = Math.max(max[j], value);
|
max[j] = Math.max(max[j], value);
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
var Cesium = require('cesium');
|
const Cesium = require('cesium');
|
||||||
var getBufferPadded = require('./getBufferPadded');
|
const getBufferPadded = require('./getBufferPadded');
|
||||||
var getDefaultMaterial = require('./loadMtl').getDefaultMaterial;
|
const getDefaultMaterial = require('./loadMtl').getDefaultMaterial;
|
||||||
var Texture = require('./Texture');
|
const Texture = require('./Texture');
|
||||||
|
|
||||||
var defaultValue = Cesium.defaultValue;
|
const defaultValue = Cesium.defaultValue;
|
||||||
var defined = Cesium.defined;
|
const defined = Cesium.defined;
|
||||||
var WebGLConstants = Cesium.WebGLConstants;
|
const WebGLConstants = Cesium.WebGLConstants;
|
||||||
|
|
||||||
module.exports = createGltf;
|
module.exports = createGltf;
|
||||||
|
|
||||||
@ -20,14 +20,14 @@ module.exports = createGltf;
|
|||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
function createGltf(objData, options) {
|
function createGltf(objData, options) {
|
||||||
var nodes = objData.nodes;
|
const nodes = objData.nodes;
|
||||||
var materials = objData.materials;
|
let materials = objData.materials;
|
||||||
var name = objData.name;
|
const name = objData.name;
|
||||||
|
|
||||||
// Split materials used by primitives with different types of attributes
|
// Split materials used by primitives with different types of attributes
|
||||||
materials = splitIncompatibleMaterials(nodes, materials, options);
|
materials = splitIncompatibleMaterials(nodes, materials, options);
|
||||||
|
|
||||||
var gltf = {
|
const gltf = {
|
||||||
accessors : [],
|
accessors : [],
|
||||||
asset : {},
|
asset : {},
|
||||||
buffers : [],
|
buffers : [],
|
||||||
@ -53,7 +53,7 @@ function createGltf(objData, options) {
|
|||||||
nodes : []
|
nodes : []
|
||||||
});
|
});
|
||||||
|
|
||||||
var bufferState = {
|
const bufferState = {
|
||||||
positionBuffers : [],
|
positionBuffers : [],
|
||||||
normalBuffers : [],
|
normalBuffers : [],
|
||||||
uvBuffers : [],
|
uvBuffers : [],
|
||||||
@ -64,24 +64,23 @@ function createGltf(objData, options) {
|
|||||||
indexAccessors : []
|
indexAccessors : []
|
||||||
};
|
};
|
||||||
|
|
||||||
var uint32Indices = requiresUint32Indices(nodes);
|
const uint32Indices = requiresUint32Indices(nodes);
|
||||||
|
|
||||||
var nodesLength = nodes.length;
|
const nodesLength = nodes.length;
|
||||||
for (var i = 0; i < nodesLength; ++i) {
|
for (let i = 0; i < nodesLength; ++i) {
|
||||||
var node = nodes[i];
|
const node = nodes[i];
|
||||||
var meshes = node.meshes;
|
const meshes = node.meshes;
|
||||||
var meshesLength = meshes.length;
|
const meshesLength = meshes.length;
|
||||||
var meshIndex;
|
|
||||||
|
|
||||||
if (meshesLength === 1) {
|
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);
|
addNode(gltf, node.name, meshIndex, undefined);
|
||||||
} else {
|
} else {
|
||||||
// Add meshes as child nodes
|
// Add meshes as child nodes
|
||||||
var parentIndex = addNode(gltf, node.name);
|
const parentIndex = addNode(gltf, node.name);
|
||||||
for (var j = 0; j < meshesLength; ++j) {
|
for (let j = 0; j < meshesLength; ++j) {
|
||||||
var mesh = meshes[j];
|
const mesh = meshes[j];
|
||||||
meshIndex = addMesh(gltf, materials, bufferState, uint32Indices, mesh, options);
|
const meshIndex = addMesh(gltf, materials, bufferState, uint32Indices, mesh, options);
|
||||||
addNode(gltf, mesh.name, meshIndex, parentIndex);
|
addNode(gltf, mesh.name, meshIndex, parentIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -112,16 +111,16 @@ function createGltf(objData, options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function addBufferView(gltf, buffers, accessors, byteStride, target) {
|
function addBufferView(gltf, buffers, accessors, byteStride, target) {
|
||||||
var length = buffers.length;
|
const length = buffers.length;
|
||||||
if (length === 0) {
|
if (length === 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var bufferViewIndex = gltf.bufferViews.length;
|
const bufferViewIndex = gltf.bufferViews.length;
|
||||||
var previousBufferView = gltf.bufferViews[bufferViewIndex - 1];
|
const previousBufferView = gltf.bufferViews[bufferViewIndex - 1];
|
||||||
var byteOffset = defined(previousBufferView) ? previousBufferView.byteOffset + previousBufferView.byteLength : 0;
|
const byteOffset = defined(previousBufferView) ? previousBufferView.byteOffset + previousBufferView.byteLength : 0;
|
||||||
var byteLength = 0;
|
let byteLength = 0;
|
||||||
for (var i = 0; i < length; ++i) {
|
for (let i = 0; i < length; ++i) {
|
||||||
var accessor = gltf.accessors[accessors[i]];
|
const accessor = gltf.accessors[accessors[i]];
|
||||||
accessor.bufferView = bufferViewIndex;
|
accessor.bufferView = bufferViewIndex;
|
||||||
accessor.byteOffset = byteLength;
|
accessor.byteOffset = byteLength;
|
||||||
byteLength += buffers[i].length;
|
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.uvBuffers, bufferState.uvAccessors, 8, WebGLConstants.ARRAY_BUFFER);
|
||||||
addBufferView(gltf, bufferState.indexBuffers, bufferState.indexAccessors, undefined, WebGLConstants.ELEMENT_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);
|
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({
|
gltf.buffers.push({
|
||||||
name : name,
|
name : name,
|
||||||
@ -158,10 +157,10 @@ function addBuffers(gltf, bufferState, name) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function addTexture(gltf, texture) {
|
function addTexture(gltf, texture) {
|
||||||
var imageName = texture.name;
|
const imageName = texture.name;
|
||||||
var textureName = texture.name;
|
const textureName = texture.name;
|
||||||
var imageIndex = gltf.images.length;
|
const imageIndex = gltf.images.length;
|
||||||
var textureIndex = gltf.textures.length;
|
const textureIndex = gltf.textures.length;
|
||||||
|
|
||||||
gltf.images.push({
|
gltf.images.push({
|
||||||
name : imageName,
|
name : imageName,
|
||||||
@ -180,11 +179,11 @@ function addTexture(gltf, texture) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getTexture(gltf, texture) {
|
function getTexture(gltf, texture) {
|
||||||
var textureIndex;
|
let textureIndex;
|
||||||
var name = texture.name;
|
const name = texture.name;
|
||||||
var textures = gltf.textures;
|
const textures = gltf.textures;
|
||||||
var length = textures.length;
|
const length = textures.length;
|
||||||
for (var i = 0; i < length; ++i) {
|
for (let i = 0; i < length; ++i) {
|
||||||
if (textures[i].name === name) {
|
if (textures[i].name === name) {
|
||||||
textureIndex = i;
|
textureIndex = i;
|
||||||
break;
|
break;
|
||||||
@ -209,15 +208,15 @@ function cloneMaterial(material, removeTextures) {
|
|||||||
}
|
}
|
||||||
return material;
|
return material;
|
||||||
} else if (Array.isArray(material)) {
|
} else if (Array.isArray(material)) {
|
||||||
var length = material.length;
|
const length = material.length;
|
||||||
var clonedArray = new Array(length);
|
const clonedArray = new Array(length);
|
||||||
for (var i = 0; i < length; ++i) {
|
for (let i = 0; i < length; ++i) {
|
||||||
clonedArray[i] = cloneMaterial(material[i], removeTextures);
|
clonedArray[i] = cloneMaterial(material[i], removeTextures);
|
||||||
}
|
}
|
||||||
return clonedArray;
|
return clonedArray;
|
||||||
}
|
}
|
||||||
var clonedObject = {};
|
const clonedObject = {};
|
||||||
for (var name in material) {
|
for (const name in material) {
|
||||||
if (material.hasOwnProperty(name)) {
|
if (material.hasOwnProperty(name)) {
|
||||||
clonedObject[name] = cloneMaterial(material[name], removeTextures);
|
clonedObject[name] = cloneMaterial(material[name], removeTextures);
|
||||||
}
|
}
|
||||||
@ -226,9 +225,9 @@ function cloneMaterial(material, removeTextures) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function resolveTextures(gltf, material) {
|
function resolveTextures(gltf, material) {
|
||||||
for (var name in material) {
|
for (const name in material) {
|
||||||
if (material.hasOwnProperty(name)) {
|
if (material.hasOwnProperty(name)) {
|
||||||
var property = material[name];
|
const property = material[name];
|
||||||
if (property instanceof Texture) {
|
if (property instanceof Texture) {
|
||||||
material[name] = getTexture(gltf, property);
|
material[name] = getTexture(gltf, property);
|
||||||
} else if (!Array.isArray(property) && (typeof property === 'object')) {
|
} else if (!Array.isArray(property) && (typeof property === 'object')) {
|
||||||
@ -240,7 +239,7 @@ function resolveTextures(gltf, material) {
|
|||||||
|
|
||||||
function addGltfMaterial(gltf, material, options) {
|
function addGltfMaterial(gltf, material, options) {
|
||||||
resolveTextures(gltf, material);
|
resolveTextures(gltf, material);
|
||||||
var materialIndex = gltf.materials.length;
|
const materialIndex = gltf.materials.length;
|
||||||
if (options.unlit) {
|
if (options.unlit) {
|
||||||
if (!defined(material.extensions)) {
|
if (!defined(material.extensions)) {
|
||||||
material.extensions = {};
|
material.extensions = {};
|
||||||
@ -252,8 +251,8 @@ function addGltfMaterial(gltf, material, options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getMaterialByName(materials, materialName) {
|
function getMaterialByName(materials, materialName) {
|
||||||
var materialsLength = materials.length;
|
const materialsLength = materials.length;
|
||||||
for (var i = 0; i < materialsLength; ++i) {
|
for (let i = 0; i < materialsLength; ++i) {
|
||||||
if (materials[i].name === materialName) {
|
if (materials[i].name === materialName) {
|
||||||
return materials[i];
|
return materials[i];
|
||||||
}
|
}
|
||||||
@ -261,8 +260,8 @@ function getMaterialByName(materials, materialName) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getMaterialIndex(materials, materialName) {
|
function getMaterialIndex(materials, materialName) {
|
||||||
var materialsLength = materials.length;
|
const materialsLength = materials.length;
|
||||||
for (var i = 0; i < materialsLength; ++i) {
|
for (let i = 0; i < materialsLength; ++i) {
|
||||||
if (materials[i].name === materialName) {
|
if (materials[i].name === materialName) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
@ -270,8 +269,8 @@ function getMaterialIndex(materials, materialName) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getOrCreateGltfMaterial(gltf, materials, materialName, options) {
|
function getOrCreateGltfMaterial(gltf, materials, materialName, options) {
|
||||||
var material = getMaterialByName(materials, materialName);
|
const material = getMaterialByName(materials, materialName);
|
||||||
var materialIndex = getMaterialIndex(gltf.materials, materialName);
|
let materialIndex = getMaterialIndex(gltf.materials, materialName);
|
||||||
|
|
||||||
if (!defined(materialIndex)) {
|
if (!defined(materialIndex)) {
|
||||||
materialIndex = addGltfMaterial(gltf, material, options);
|
materialIndex = addGltfMaterial(gltf, material, options);
|
||||||
@ -286,8 +285,8 @@ function primitiveInfoMatch(a, b) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getSplitMaterialName(originalMaterialName, primitiveInfo, primitiveInfoByMaterial) {
|
function getSplitMaterialName(originalMaterialName, primitiveInfo, primitiveInfoByMaterial) {
|
||||||
var splitMaterialName = originalMaterialName;
|
let splitMaterialName = originalMaterialName;
|
||||||
var suffix = 2;
|
let suffix = 2;
|
||||||
while (defined(primitiveInfoByMaterial[splitMaterialName])) {
|
while (defined(primitiveInfoByMaterial[splitMaterialName])) {
|
||||||
if (primitiveInfoMatch(primitiveInfo, primitiveInfoByMaterial[splitMaterialName])) {
|
if (primitiveInfoMatch(primitiveInfo, primitiveInfoByMaterial[splitMaterialName])) {
|
||||||
break;
|
break;
|
||||||
@ -298,34 +297,34 @@ function getSplitMaterialName(originalMaterialName, primitiveInfo, primitiveInfo
|
|||||||
}
|
}
|
||||||
|
|
||||||
function splitIncompatibleMaterials(nodes, materials, options) {
|
function splitIncompatibleMaterials(nodes, materials, options) {
|
||||||
var splitMaterials = [];
|
const splitMaterials = [];
|
||||||
var primitiveInfoByMaterial = {};
|
const primitiveInfoByMaterial = {};
|
||||||
var nodesLength = nodes.length;
|
const nodesLength = nodes.length;
|
||||||
for (var i = 0; i < nodesLength; ++i) {
|
for (let i = 0; i < nodesLength; ++i) {
|
||||||
var meshes = nodes[i].meshes;
|
const meshes = nodes[i].meshes;
|
||||||
var meshesLength = meshes.length;
|
const meshesLength = meshes.length;
|
||||||
for (var j = 0; j < meshesLength; ++j) {
|
for (let j = 0; j < meshesLength; ++j) {
|
||||||
var primitives = meshes[j].primitives;
|
const primitives = meshes[j].primitives;
|
||||||
var primitivesLength = primitives.length;
|
const primitivesLength = primitives.length;
|
||||||
for (var k = 0; k < primitivesLength; ++k) {
|
for (let k = 0; k < primitivesLength; ++k) {
|
||||||
var primitive = primitives[k];
|
const primitive = primitives[k];
|
||||||
var hasUvs = primitive.uvs.length > 0;
|
const hasUvs = primitive.uvs.length > 0;
|
||||||
var hasNormals = primitive.normals.length > 0;
|
const hasNormals = primitive.normals.length > 0;
|
||||||
var primitiveInfo = {
|
const primitiveInfo = {
|
||||||
hasUvs : hasUvs,
|
hasUvs : hasUvs,
|
||||||
hasNormals : hasNormals
|
hasNormals : hasNormals
|
||||||
};
|
};
|
||||||
var originalMaterialName = defaultValue(primitive.material, 'default');
|
const originalMaterialName = defaultValue(primitive.material, 'default');
|
||||||
var splitMaterialName = getSplitMaterialName(originalMaterialName, primitiveInfo, primitiveInfoByMaterial);
|
const splitMaterialName = getSplitMaterialName(originalMaterialName, primitiveInfo, primitiveInfoByMaterial);
|
||||||
primitive.material = splitMaterialName;
|
primitive.material = splitMaterialName;
|
||||||
primitiveInfoByMaterial[splitMaterialName] = primitiveInfo;
|
primitiveInfoByMaterial[splitMaterialName] = primitiveInfo;
|
||||||
|
|
||||||
var splitMaterial = getMaterialByName(splitMaterials, splitMaterialName);
|
let splitMaterial = getMaterialByName(splitMaterials, splitMaterialName);
|
||||||
if (defined(splitMaterial)) {
|
if (defined(splitMaterial)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
var originalMaterial = getMaterialByName(materials, originalMaterialName);
|
const originalMaterial = getMaterialByName(materials, originalMaterialName);
|
||||||
if (defined(originalMaterial)) {
|
if (defined(originalMaterial)) {
|
||||||
splitMaterial = cloneMaterial(originalMaterial, !hasUvs);
|
splitMaterial = cloneMaterial(originalMaterial, !hasUvs);
|
||||||
} else {
|
} else {
|
||||||
@ -340,11 +339,11 @@ function splitIncompatibleMaterials(nodes, materials, options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function addVertexAttribute(gltf, array, components, name) {
|
function addVertexAttribute(gltf, array, components, name) {
|
||||||
var count = array.length / components;
|
const count = array.length / components;
|
||||||
var minMax = array.getMinMax(components);
|
const minMax = array.getMinMax(components);
|
||||||
var type = (components === 3 ? 'VEC3' : 'VEC2');
|
const type = (components === 3 ? 'VEC3' : 'VEC2');
|
||||||
|
|
||||||
var accessor = {
|
const accessor = {
|
||||||
name : name,
|
name : name,
|
||||||
componentType : WebGLConstants.FLOAT,
|
componentType : WebGLConstants.FLOAT,
|
||||||
count : count,
|
count : count,
|
||||||
@ -353,17 +352,17 @@ function addVertexAttribute(gltf, array, components, name) {
|
|||||||
type : type
|
type : type
|
||||||
};
|
};
|
||||||
|
|
||||||
var accessorIndex = gltf.accessors.length;
|
const accessorIndex = gltf.accessors.length;
|
||||||
gltf.accessors.push(accessor);
|
gltf.accessors.push(accessor);
|
||||||
return accessorIndex;
|
return accessorIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
function addIndexArray(gltf, array, uint32Indices, name) {
|
function addIndexArray(gltf, array, uint32Indices, name) {
|
||||||
var componentType = uint32Indices ? WebGLConstants.UNSIGNED_INT : WebGLConstants.UNSIGNED_SHORT;
|
const componentType = uint32Indices ? WebGLConstants.UNSIGNED_INT : WebGLConstants.UNSIGNED_SHORT;
|
||||||
var count = array.length;
|
const count = array.length;
|
||||||
var minMax = array.getMinMax(1);
|
const minMax = array.getMinMax(1);
|
||||||
|
|
||||||
var accessor = {
|
const accessor = {
|
||||||
name : name,
|
name : name,
|
||||||
componentType : componentType,
|
componentType : componentType,
|
||||||
count : count,
|
count : count,
|
||||||
@ -372,22 +371,22 @@ function addIndexArray(gltf, array, uint32Indices, name) {
|
|||||||
type : 'SCALAR'
|
type : 'SCALAR'
|
||||||
};
|
};
|
||||||
|
|
||||||
var accessorIndex = gltf.accessors.length;
|
const accessorIndex = gltf.accessors.length;
|
||||||
gltf.accessors.push(accessor);
|
gltf.accessors.push(accessor);
|
||||||
return accessorIndex;
|
return accessorIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
function requiresUint32Indices(nodes) {
|
function requiresUint32Indices(nodes) {
|
||||||
var nodesLength = nodes.length;
|
const nodesLength = nodes.length;
|
||||||
for (var i = 0; i < nodesLength; ++i) {
|
for (let i = 0; i < nodesLength; ++i) {
|
||||||
var meshes = nodes[i].meshes;
|
const meshes = nodes[i].meshes;
|
||||||
var meshesLength = meshes.length;
|
const meshesLength = meshes.length;
|
||||||
for (var j = 0; j < meshesLength; ++j) {
|
for (let j = 0; j < meshesLength; ++j) {
|
||||||
var primitives = meshes[j].primitives;
|
const primitives = meshes[j].primitives;
|
||||||
var primitivesLength = primitives.length;
|
const primitivesLength = primitives.length;
|
||||||
for (var k = 0; k < primitivesLength; ++k) {
|
for (let k = 0; k < primitivesLength; ++k) {
|
||||||
// Reserve the 65535 index for primitive restart
|
// Reserve the 65535 index for primitive restart
|
||||||
var vertexCount = primitives[k].positions.length / 3;
|
const vertexCount = primitives[k].positions.length / 3;
|
||||||
if (vertexCount > 65534) {
|
if (vertexCount > 65534) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -398,33 +397,32 @@ function requiresUint32Indices(nodes) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function addPrimitive(gltf, materials, bufferState, uint32Indices, mesh, primitive, index, options) {
|
function addPrimitive(gltf, materials, bufferState, uint32Indices, mesh, primitive, index, options) {
|
||||||
var hasPositions = primitive.positions.length > 0;
|
const hasPositions = primitive.positions.length > 0;
|
||||||
var hasNormals = primitive.normals.length > 0;
|
const hasNormals = primitive.normals.length > 0;
|
||||||
var hasUVs = primitive.uvs.length > 0;
|
const hasUVs = primitive.uvs.length > 0;
|
||||||
|
|
||||||
var accessorIndex;
|
const attributes = {};
|
||||||
var attributes = {};
|
|
||||||
if (hasPositions) {
|
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;
|
attributes.POSITION = accessorIndex;
|
||||||
bufferState.positionBuffers.push(primitive.positions.toFloatBuffer());
|
bufferState.positionBuffers.push(primitive.positions.toFloatBuffer());
|
||||||
bufferState.positionAccessors.push(accessorIndex);
|
bufferState.positionAccessors.push(accessorIndex);
|
||||||
}
|
}
|
||||||
if (hasNormals) {
|
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;
|
attributes.NORMAL = accessorIndex;
|
||||||
bufferState.normalBuffers.push(primitive.normals.toFloatBuffer());
|
bufferState.normalBuffers.push(primitive.normals.toFloatBuffer());
|
||||||
bufferState.normalAccessors.push(accessorIndex);
|
bufferState.normalAccessors.push(accessorIndex);
|
||||||
}
|
}
|
||||||
if (hasUVs) {
|
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;
|
attributes.TEXCOORD_0 = accessorIndex;
|
||||||
bufferState.uvBuffers.push(primitive.uvs.toFloatBuffer());
|
bufferState.uvBuffers.push(primitive.uvs.toFloatBuffer());
|
||||||
bufferState.uvAccessors.push(accessorIndex);
|
bufferState.uvAccessors.push(accessorIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
var indexAccessorIndex = addIndexArray(gltf, primitive.indices, uint32Indices, mesh.name + '_' + index + '_indices');
|
const indexAccessorIndex = addIndexArray(gltf, primitive.indices, uint32Indices, mesh.name + '_' + index + '_indices');
|
||||||
var indexBuffer = uint32Indices ? primitive.indices.toUint32Buffer() : primitive.indices.toUint16Buffer();
|
const indexBuffer = uint32Indices ? primitive.indices.toUint32Buffer() : primitive.indices.toUint16Buffer();
|
||||||
bufferState.indexBuffers.push(indexBuffer);
|
bufferState.indexBuffers.push(indexBuffer);
|
||||||
bufferState.indexAccessors.push(indexAccessorIndex);
|
bufferState.indexAccessors.push(indexAccessorIndex);
|
||||||
|
|
||||||
@ -434,7 +432,7 @@ function addPrimitive(gltf, materials, bufferState, uint32Indices, mesh, primiti
|
|||||||
primitive.uvs = undefined;
|
primitive.uvs = undefined;
|
||||||
primitive.indices = undefined;
|
primitive.indices = undefined;
|
||||||
|
|
||||||
var materialIndex = getOrCreateGltfMaterial(gltf, materials, primitive.material, options);
|
const materialIndex = getOrCreateGltfMaterial(gltf, materials, primitive.material, options);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
attributes : attributes,
|
attributes : attributes,
|
||||||
@ -445,34 +443,34 @@ function addPrimitive(gltf, materials, bufferState, uint32Indices, mesh, primiti
|
|||||||
}
|
}
|
||||||
|
|
||||||
function addMesh(gltf, materials, bufferState, uint32Indices, mesh, options) {
|
function addMesh(gltf, materials, bufferState, uint32Indices, mesh, options) {
|
||||||
var gltfPrimitives = [];
|
const gltfPrimitives = [];
|
||||||
var primitives = mesh.primitives;
|
const primitives = mesh.primitives;
|
||||||
var primitivesLength = primitives.length;
|
const primitivesLength = primitives.length;
|
||||||
for (var i = 0; i < primitivesLength; ++i) {
|
for (let i = 0; i < primitivesLength; ++i) {
|
||||||
gltfPrimitives.push(addPrimitive(gltf, materials, bufferState, uint32Indices, mesh, primitives[i], i, options));
|
gltfPrimitives.push(addPrimitive(gltf, materials, bufferState, uint32Indices, mesh, primitives[i], i, options));
|
||||||
}
|
}
|
||||||
|
|
||||||
var gltfMesh = {
|
const gltfMesh = {
|
||||||
name : mesh.name,
|
name : mesh.name,
|
||||||
primitives : gltfPrimitives
|
primitives : gltfPrimitives
|
||||||
};
|
};
|
||||||
|
|
||||||
var meshIndex = gltf.meshes.length;
|
const meshIndex = gltf.meshes.length;
|
||||||
gltf.meshes.push(gltfMesh);
|
gltf.meshes.push(gltfMesh);
|
||||||
return meshIndex;
|
return meshIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
function addNode(gltf, name, meshIndex, parentIndex) {
|
function addNode(gltf, name, meshIndex, parentIndex) {
|
||||||
var node = {
|
const node = {
|
||||||
name : name,
|
name : name,
|
||||||
mesh : meshIndex
|
mesh : meshIndex
|
||||||
};
|
};
|
||||||
|
|
||||||
var nodeIndex = gltf.nodes.length;
|
const nodeIndex = gltf.nodes.length;
|
||||||
gltf.nodes.push(node);
|
gltf.nodes.push(node);
|
||||||
|
|
||||||
if (defined(parentIndex)) {
|
if (defined(parentIndex)) {
|
||||||
var parentNode = gltf.nodes[parentIndex];
|
const parentNode = gltf.nodes[parentIndex];
|
||||||
if (!defined(parentNode.children)) {
|
if (!defined(parentNode.children)) {
|
||||||
parentNode.children = [];
|
parentNode.children = [];
|
||||||
}
|
}
|
||||||
|
@ -10,13 +10,13 @@ module.exports = getBufferPadded;
|
|||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
function getBufferPadded(buffer) {
|
function getBufferPadded(buffer) {
|
||||||
var boundary = 4;
|
const boundary = 4;
|
||||||
var byteLength = buffer.length;
|
const byteLength = buffer.length;
|
||||||
var remainder = byteLength % boundary;
|
const remainder = byteLength % boundary;
|
||||||
if (remainder === 0) {
|
if (remainder === 0) {
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
var padding = (remainder === 0) ? 0 : boundary - remainder;
|
const padding = (remainder === 0) ? 0 : boundary - remainder;
|
||||||
var emptyBuffer = Buffer.alloc(padding);
|
const emptyBuffer = Buffer.alloc(padding);
|
||||||
return Buffer.concat([buffer, emptyBuffer]);
|
return Buffer.concat([buffer, emptyBuffer]);
|
||||||
}
|
}
|
||||||
|
@ -13,14 +13,14 @@ module.exports = getJsonBufferPadded;
|
|||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
function getJsonBufferPadded(json) {
|
function getJsonBufferPadded(json) {
|
||||||
var string = JSON.stringify(json);
|
let string = JSON.stringify(json);
|
||||||
|
|
||||||
var boundary = 4;
|
const boundary = 4;
|
||||||
var byteLength = Buffer.byteLength(string);
|
const byteLength = Buffer.byteLength(string);
|
||||||
var remainder = byteLength % boundary;
|
const remainder = byteLength % boundary;
|
||||||
var padding = (remainder === 0) ? 0 : boundary - remainder;
|
const padding = (remainder === 0) ? 0 : boundary - remainder;
|
||||||
var whitespace = '';
|
let whitespace = '';
|
||||||
for (var i = 0; i < padding; ++i) {
|
for (let i = 0; i < padding; ++i) {
|
||||||
whitespace += ' ';
|
whitespace += ' ';
|
||||||
}
|
}
|
||||||
string += whitespace;
|
string += whitespace;
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
var Cesium = require('cesium');
|
const Cesium = require('cesium');
|
||||||
var getJsonBufferPadded = require('./getJsonBufferPadded');
|
const getJsonBufferPadded = require('./getJsonBufferPadded');
|
||||||
|
|
||||||
var defined = Cesium.defined;
|
const defined = Cesium.defined;
|
||||||
|
|
||||||
module.exports = gltfToGlb;
|
module.exports = gltfToGlb;
|
||||||
|
|
||||||
@ -18,20 +18,20 @@ module.exports = gltfToGlb;
|
|||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
function gltfToGlb(gltf, binaryBuffer) {
|
function gltfToGlb(gltf, binaryBuffer) {
|
||||||
var buffer = gltf.buffers[0];
|
const buffer = gltf.buffers[0];
|
||||||
if (defined(buffer.uri)) {
|
if (defined(buffer.uri)) {
|
||||||
binaryBuffer = Buffer.alloc(0);
|
binaryBuffer = Buffer.alloc(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create padded binary scene string
|
// 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)
|
// Allocate buffer (Global header) + (JSON chunk header) + (JSON chunk) + (Binary chunk header) + (Binary chunk)
|
||||||
var glbLength = 12 + 8 + jsonBuffer.length + 8 + binaryBuffer.length;
|
const glbLength = 12 + 8 + jsonBuffer.length + 8 + binaryBuffer.length;
|
||||||
var glb = Buffer.alloc(glbLength);
|
const glb = Buffer.alloc(glbLength);
|
||||||
|
|
||||||
// Write binary glTF header (magic, version, length)
|
// Write binary glTF header (magic, version, length)
|
||||||
var byteOffset = 0;
|
let byteOffset = 0;
|
||||||
glb.writeUInt32LE(0x46546C67, byteOffset);
|
glb.writeUInt32LE(0x46546C67, byteOffset);
|
||||||
byteOffset += 4;
|
byteOffset += 4;
|
||||||
glb.writeUInt32LE(2, byteOffset);
|
glb.writeUInt32LE(2, byteOffset);
|
||||||
|
322
lib/loadMtl.js
322
lib/loadMtl.js
@ -1,16 +1,16 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
var Cesium = require('cesium');
|
const Cesium = require('cesium');
|
||||||
var path = require('path');
|
const path = require('path');
|
||||||
var Promise = require('bluebird');
|
const Promise = require('bluebird');
|
||||||
var loadTexture = require('./loadTexture');
|
const loadTexture = require('./loadTexture');
|
||||||
var outsideDirectory = require('./outsideDirectory');
|
const outsideDirectory = require('./outsideDirectory');
|
||||||
var readLines = require('./readLines');
|
const readLines = require('./readLines');
|
||||||
var Texture = require('./Texture');
|
const Texture = require('./Texture');
|
||||||
|
|
||||||
var CesiumMath = Cesium.Math;
|
const CesiumMath = Cesium.Math;
|
||||||
var combine = Cesium.combine;
|
const combine = Cesium.combine;
|
||||||
var defaultValue = Cesium.defaultValue;
|
const defaultValue = Cesium.defaultValue;
|
||||||
var defined = Cesium.defined;
|
const defined = Cesium.defined;
|
||||||
|
|
||||||
module.exports = loadMtl;
|
module.exports = loadMtl;
|
||||||
|
|
||||||
@ -30,39 +30,39 @@ module.exports = loadMtl;
|
|||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
function loadMtl(mtlPath, options) {
|
function loadMtl(mtlPath, options) {
|
||||||
var material;
|
let material;
|
||||||
var values;
|
let values;
|
||||||
var value;
|
let value;
|
||||||
|
|
||||||
var mtlDirectory = path.dirname(mtlPath);
|
const mtlDirectory = path.dirname(mtlPath);
|
||||||
var materials = [];
|
const materials = [];
|
||||||
var texturePromiseMap = {}; // Maps texture paths to load promises so that no texture is loaded twice
|
const texturePromiseMap = {}; // Maps texture paths to load promises so that no texture is loaded twice
|
||||||
var texturePromises = [];
|
const texturePromises = [];
|
||||||
|
|
||||||
var overridingTextures = options.overridingTextures;
|
const overridingTextures = options.overridingTextures;
|
||||||
var overridingSpecularTexture = defaultValue(overridingTextures.metallicRoughnessOcclusionTexture, overridingTextures.specularGlossinessTexture);
|
const overridingSpecularTexture = defaultValue(overridingTextures.metallicRoughnessOcclusionTexture, overridingTextures.specularGlossinessTexture);
|
||||||
var overridingSpecularShininessTexture = defaultValue(overridingTextures.metallicRoughnessOcclusionTexture, overridingTextures.specularGlossinessTexture);
|
const overridingSpecularShininessTexture = defaultValue(overridingTextures.metallicRoughnessOcclusionTexture, overridingTextures.specularGlossinessTexture);
|
||||||
var overridingAmbientTexture = defaultValue(overridingTextures.metallicRoughnessOcclusionTexture, overridingTextures.occlusionTexture);
|
const overridingAmbientTexture = defaultValue(overridingTextures.metallicRoughnessOcclusionTexture, overridingTextures.occlusionTexture);
|
||||||
var overridingNormalTexture = overridingTextures.normalTexture;
|
const overridingNormalTexture = overridingTextures.normalTexture;
|
||||||
var overridingDiffuseTexture = overridingTextures.baseColorTexture;
|
const overridingDiffuseTexture = overridingTextures.baseColorTexture;
|
||||||
var overridingEmissiveTexture = overridingTextures.emissiveTexture;
|
const overridingEmissiveTexture = overridingTextures.emissiveTexture;
|
||||||
var overridingAlphaTexture = overridingTextures.alphaTexture;
|
const overridingAlphaTexture = overridingTextures.alphaTexture;
|
||||||
|
|
||||||
// Textures that are packed into PBR textures need to be decoded first
|
// Textures that are packed into PBR textures need to be decoded first
|
||||||
var decodeOptions = {
|
const decodeOptions = {
|
||||||
decode : true
|
decode : true
|
||||||
};
|
};
|
||||||
|
|
||||||
var diffuseTextureOptions = {
|
const diffuseTextureOptions = {
|
||||||
checkTransparency : options.checkTransparency
|
checkTransparency : options.checkTransparency
|
||||||
};
|
};
|
||||||
|
|
||||||
var ambientTextureOptions = defined(overridingAmbientTexture) ? undefined : (options.packOcclusion ? decodeOptions : undefined);
|
const ambientTextureOptions = defined(overridingAmbientTexture) ? undefined : (options.packOcclusion ? decodeOptions : undefined);
|
||||||
var specularTextureOptions = defined(overridingSpecularTexture) ? undefined : decodeOptions;
|
const specularTextureOptions = defined(overridingSpecularTexture) ? undefined : decodeOptions;
|
||||||
var specularShinessTextureOptions = defined(overridingSpecularShininessTexture) ? undefined : decodeOptions;
|
const specularShinessTextureOptions = defined(overridingSpecularShininessTexture) ? undefined : decodeOptions;
|
||||||
var emissiveTextureOptions;
|
const emissiveTextureOptions = undefined;
|
||||||
var normalTextureOptions;
|
const normalTextureOptions = undefined;
|
||||||
var alphaTextureOptions = {
|
const alphaTextureOptions = {
|
||||||
decode : true
|
decode : true
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -83,7 +83,7 @@ function loadMtl(mtlPath, options) {
|
|||||||
function normalizeTexturePath(texturePath, mtlDirectory) {
|
function normalizeTexturePath(texturePath, mtlDirectory) {
|
||||||
// Removes texture options from texture name
|
// Removes texture options from texture name
|
||||||
// Assumes no spaces in 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)) {
|
if (re.test(texturePath)) {
|
||||||
texturePath = texturePath.split(/\s+/).pop();
|
texturePath = texturePath.split(/\s+/).pop();
|
||||||
}
|
}
|
||||||
@ -94,7 +94,7 @@ function loadMtl(mtlPath, options) {
|
|||||||
function parseLine(line) {
|
function parseLine(line) {
|
||||||
line = line.trim();
|
line = line.trim();
|
||||||
if (/^newmtl /i.test(line)) {
|
if (/^newmtl /i.test(line)) {
|
||||||
var name = line.substring(7).trim();
|
const name = line.substring(7).trim();
|
||||||
createMaterial(name);
|
createMaterial(name);
|
||||||
} else if (/^Ka /i.test(line)) {
|
} else if (/^Ka /i.test(line)) {
|
||||||
values = line.substring(3).trim().split(' ');
|
values = line.substring(3).trim().split(' ');
|
||||||
@ -170,7 +170,7 @@ function loadMtl(mtlPath, options) {
|
|||||||
|
|
||||||
function loadMaterialTextures(material) {
|
function loadMaterialTextures(material) {
|
||||||
// If an alpha texture is present the diffuse texture needs to be decoded so they can be packed together
|
// 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) {
|
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
|
// 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)
|
return readLines(mtlPath, parseLine)
|
||||||
.then(function() {
|
.then(function() {
|
||||||
var length = materials.length;
|
const length = materials.length;
|
||||||
for (var i = 0; i < length; ++i) {
|
for (let i = 0; i < length; ++i) {
|
||||||
loadMaterialTextures(materials[i]);
|
loadMaterialTextures(materials[i]);
|
||||||
}
|
}
|
||||||
return Promise.all(texturePromises);
|
return Promise.all(texturePromises);
|
||||||
@ -232,14 +232,14 @@ loadMtl._createMaterial = function(materialOptions, options) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
function loadMaterialTexture(material, name, textureOptions, mtlDirectory, texturePromiseMap, texturePromises, options) {
|
function loadMaterialTexture(material, name, textureOptions, mtlDirectory, texturePromiseMap, texturePromises, options) {
|
||||||
var texturePath = material[name];
|
const texturePath = material[name];
|
||||||
if (!defined(texturePath)) {
|
if (!defined(texturePath)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var texturePromise = texturePromiseMap[texturePath];
|
let texturePromise = texturePromiseMap[texturePath];
|
||||||
if (!defined(texturePromise)) {
|
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)) {
|
if (options.secure && outsideDirectory(texturePath, mtlDirectory)) {
|
||||||
// Try looking for the texture in the same directory as the obj
|
// 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.');
|
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) {
|
function resizeChannel(sourcePixels, sourceWidth, sourceHeight, targetPixels, targetWidth, targetHeight) {
|
||||||
// Nearest neighbor sampling
|
// Nearest neighbor sampling
|
||||||
var widthRatio = sourceWidth / targetWidth;
|
const widthRatio = sourceWidth / targetWidth;
|
||||||
var heightRatio = sourceHeight / targetHeight;
|
const heightRatio = sourceHeight / targetHeight;
|
||||||
|
|
||||||
for (var y = 0; y < targetHeight; ++y) {
|
for (let y = 0; y < targetHeight; ++y) {
|
||||||
for (var x = 0; x < targetWidth; ++x) {
|
for (let x = 0; x < targetWidth; ++x) {
|
||||||
var targetIndex = y * targetWidth + x;
|
const targetIndex = y * targetWidth + x;
|
||||||
var sourceY = Math.round(y * heightRatio);
|
const sourceY = Math.round(y * heightRatio);
|
||||||
var sourceX = Math.round(x * widthRatio);
|
const sourceX = Math.round(x * widthRatio);
|
||||||
var sourceIndex = sourceY * sourceWidth + sourceX;
|
const sourceIndex = sourceY * sourceWidth + sourceX;
|
||||||
var sourceValue = sourcePixels.readUInt8(sourceIndex);
|
const sourceValue = sourcePixels.readUInt8(sourceIndex);
|
||||||
targetPixels.writeUInt8(sourceValue, targetIndex);
|
targetPixels.writeUInt8(sourceValue, targetIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return targetPixels;
|
return targetPixels;
|
||||||
}
|
}
|
||||||
|
|
||||||
var scratchResizeChannel;
|
let scratchResizeChannel;
|
||||||
|
|
||||||
function getTextureChannel(texture, index, targetWidth, targetHeight, targetChannel) {
|
function getTextureChannel(texture, index, targetWidth, targetHeight, targetChannel) {
|
||||||
var pixels = texture.pixels; // RGBA
|
const pixels = texture.pixels; // RGBA
|
||||||
var sourceWidth = texture.width;
|
const sourceWidth = texture.width;
|
||||||
var sourceHeight = texture.height;
|
const sourceHeight = texture.height;
|
||||||
var sourcePixelsLength = sourceWidth * sourceHeight;
|
const sourcePixelsLength = sourceWidth * sourceHeight;
|
||||||
var targetPixelsLength = targetWidth * targetHeight;
|
const targetPixelsLength = targetWidth * targetHeight;
|
||||||
|
|
||||||
// Allocate the scratchResizeChannel on demand if the texture needs to be resized
|
// Allocate the scratchResizeChannel on demand if the texture needs to be resized
|
||||||
var sourceChannel = targetChannel;
|
let sourceChannel = targetChannel;
|
||||||
if (sourcePixelsLength > targetPixelsLength) {
|
if (sourcePixelsLength > targetPixelsLength) {
|
||||||
if (!defined(scratchResizeChannel) || (sourcePixelsLength > scratchResizeChannel.length)) {
|
if (!defined(scratchResizeChannel) || (sourcePixelsLength > scratchResizeChannel.length)) {
|
||||||
scratchResizeChannel = Buffer.alloc(sourcePixelsLength);
|
scratchResizeChannel = Buffer.alloc(sourcePixelsLength);
|
||||||
@ -323,8 +323,8 @@ function getTextureChannel(texture, index, targetWidth, targetHeight, targetChan
|
|||||||
sourceChannel = scratchResizeChannel;
|
sourceChannel = scratchResizeChannel;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var i = 0; i < sourcePixelsLength; ++i) {
|
for (let i = 0; i < sourcePixelsLength; ++i) {
|
||||||
var value = pixels.readUInt8(i * 4 + index);
|
const value = pixels.readUInt8(i * 4 + index);
|
||||||
sourceChannel.writeUInt8(value, i);
|
sourceChannel.writeUInt8(value, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -336,28 +336,26 @@ function getTextureChannel(texture, index, targetWidth, targetHeight, targetChan
|
|||||||
}
|
}
|
||||||
|
|
||||||
function writeChannel(pixels, channel, index) {
|
function writeChannel(pixels, channel, index) {
|
||||||
var pixelsLength = pixels.length / 4;
|
const pixelsLength = pixels.length / 4;
|
||||||
for (var i = 0; i < pixelsLength; ++i) {
|
for (let i = 0; i < pixelsLength; ++i) {
|
||||||
var value = channel.readUInt8(i);
|
const value = channel.readUInt8(i);
|
||||||
pixels.writeUInt8(value, i * 4 + index);
|
pixels.writeUInt8(value, i * 4 + index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getMinimumDimensions(textures, options) {
|
function getMinimumDimensions(textures, options) {
|
||||||
var i;
|
let width = Number.POSITIVE_INFINITY;
|
||||||
var texture;
|
let height = Number.POSITIVE_INFINITY;
|
||||||
var width = Number.POSITIVE_INFINITY;
|
|
||||||
var height = Number.POSITIVE_INFINITY;
|
|
||||||
|
|
||||||
var length = textures.length;
|
const length = textures.length;
|
||||||
for (i = 0; i < length; ++i) {
|
for (let i = 0; i < length; ++i) {
|
||||||
texture = textures[i];
|
const texture = textures[i];
|
||||||
width = Math.min(texture.width, width);
|
width = Math.min(texture.width, width);
|
||||||
height = Math.min(texture.height, height);
|
height = Math.min(texture.height, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < length; ++i) {
|
for (let i = 0; i < length; ++i) {
|
||||||
texture = textures[i];
|
const texture = textures[i];
|
||||||
if (texture.width !== width || texture.height !== height) {
|
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 + '.');
|
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) {
|
function isChannelSingleColor(buffer) {
|
||||||
var first = buffer.readUInt8(0);
|
const first = buffer.readUInt8(0);
|
||||||
var length = buffer.length;
|
const length = buffer.length;
|
||||||
for (var i = 1; i < length; ++i) {
|
for (let i = 1; i < length; ++i) {
|
||||||
if (buffer[i] !== first) {
|
if (buffer[i] !== first) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -378,8 +376,8 @@ function isChannelSingleColor(buffer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function createDiffuseAlphaTexture(diffuseTexture, alphaTexture, options) {
|
function createDiffuseAlphaTexture(diffuseTexture, alphaTexture, options) {
|
||||||
var packDiffuse = defined(diffuseTexture);
|
const packDiffuse = defined(diffuseTexture);
|
||||||
var packAlpha = defined(alphaTexture);
|
const packAlpha = defined(alphaTexture);
|
||||||
|
|
||||||
if (!packDiffuse) {
|
if (!packDiffuse) {
|
||||||
return undefined;
|
return undefined;
|
||||||
@ -394,30 +392,30 @@ function createDiffuseAlphaTexture(diffuseTexture, alphaTexture, options) {
|
|||||||
return diffuseTexture;
|
return diffuseTexture;
|
||||||
}
|
}
|
||||||
|
|
||||||
var packedTextures = [diffuseTexture, alphaTexture];
|
const packedTextures = [diffuseTexture, alphaTexture];
|
||||||
var dimensions = getMinimumDimensions(packedTextures, options);
|
const dimensions = getMinimumDimensions(packedTextures, options);
|
||||||
var width = dimensions[0];
|
const width = dimensions[0];
|
||||||
var height = dimensions[1];
|
const height = dimensions[1];
|
||||||
var pixelsLength = width * height;
|
const pixelsLength = width * height;
|
||||||
var pixels = Buffer.alloc(pixelsLength * 4, 0xFF); // Initialize with 4 channels
|
const pixels = Buffer.alloc(pixelsLength * 4, 0xFF); // Initialize with 4 channels
|
||||||
var scratchChannel = Buffer.alloc(pixelsLength);
|
const scratchChannel = Buffer.alloc(pixelsLength);
|
||||||
|
|
||||||
// Write into the R, G, B channels
|
// 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);
|
writeChannel(pixels, redChannel, 0);
|
||||||
var greenChannel = getTextureChannel(diffuseTexture, 1, width, height, scratchChannel);
|
const greenChannel = getTextureChannel(diffuseTexture, 1, width, height, scratchChannel);
|
||||||
writeChannel(pixels, greenChannel, 1);
|
writeChannel(pixels, greenChannel, 1);
|
||||||
var blueChannel = getTextureChannel(diffuseTexture, 2, width, height, scratchChannel);
|
const blueChannel = getTextureChannel(diffuseTexture, 2, width, height, scratchChannel);
|
||||||
writeChannel(pixels, blueChannel, 2);
|
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.
|
// 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)) {
|
if (isChannelSingleColor(alphaChannel)) {
|
||||||
alphaChannel = getTextureChannel(alphaTexture, 0, width, height, scratchChannel);
|
alphaChannel = getTextureChannel(alphaTexture, 0, width, height, scratchChannel);
|
||||||
}
|
}
|
||||||
writeChannel(pixels, alphaChannel, 3);
|
writeChannel(pixels, alphaChannel, 3);
|
||||||
|
|
||||||
var texture = new Texture();
|
const texture = new Texture();
|
||||||
texture.name = diffuseTexture.name;
|
texture.name = diffuseTexture.name;
|
||||||
texture.extension = '.png';
|
texture.extension = '.png';
|
||||||
texture.pixels = pixels;
|
texture.pixels = pixels;
|
||||||
@ -433,9 +431,9 @@ function createMetallicRoughnessTexture(metallicTexture, roughnessTexture, occlu
|
|||||||
return metallicTexture;
|
return metallicTexture;
|
||||||
}
|
}
|
||||||
|
|
||||||
var packMetallic = defined(metallicTexture);
|
const packMetallic = defined(metallicTexture);
|
||||||
var packRoughness = defined(roughnessTexture);
|
const packRoughness = defined(roughnessTexture);
|
||||||
var packOcclusion = defined(occlusionTexture) && options.packOcclusion;
|
const packOcclusion = defined(occlusionTexture) && options.packOcclusion;
|
||||||
|
|
||||||
if (!packMetallic && !packRoughness) {
|
if (!packMetallic && !packRoughness) {
|
||||||
return undefined;
|
return undefined;
|
||||||
@ -456,43 +454,43 @@ function createMetallicRoughnessTexture(metallicTexture, roughnessTexture, occlu
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
var packedTextures = [metallicTexture, roughnessTexture, occlusionTexture].filter(function(texture) {
|
const packedTextures = [metallicTexture, roughnessTexture, occlusionTexture].filter(function(texture) {
|
||||||
return defined(texture) && defined(texture.pixels);
|
return defined(texture) && defined(texture.pixels);
|
||||||
});
|
});
|
||||||
|
|
||||||
var dimensions = getMinimumDimensions(packedTextures, options);
|
const dimensions = getMinimumDimensions(packedTextures, options);
|
||||||
var width = dimensions[0];
|
const width = dimensions[0];
|
||||||
var height = dimensions[1];
|
const height = dimensions[1];
|
||||||
var pixelsLength = width * height;
|
const pixelsLength = width * height;
|
||||||
var pixels = Buffer.alloc(pixelsLength * 4, 0xFF); // Initialize with 4 channels, unused channels will be white
|
const pixels = Buffer.alloc(pixelsLength * 4, 0xFF); // Initialize with 4 channels, unused channels will be white
|
||||||
var scratchChannel = Buffer.alloc(pixelsLength);
|
const scratchChannel = Buffer.alloc(pixelsLength);
|
||||||
|
|
||||||
if (packMetallic) {
|
if (packMetallic) {
|
||||||
// Write into the B channel
|
// 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);
|
writeChannel(pixels, metallicChannel, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (packRoughness) {
|
if (packRoughness) {
|
||||||
// Write into the G channel
|
// 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);
|
writeChannel(pixels, roughnessChannel, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (packOcclusion) {
|
if (packOcclusion) {
|
||||||
// Write into the R channel
|
// 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);
|
writeChannel(pixels, occlusionChannel, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
var length = packedTextures.length;
|
const length = packedTextures.length;
|
||||||
var names = new Array(length);
|
const names = new Array(length);
|
||||||
for (var i = 0; i < length; ++i) {
|
for (let i = 0; i < length; ++i) {
|
||||||
names[i] = packedTextures[i].name;
|
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.name = name;
|
||||||
texture.extension = '.png';
|
texture.extension = '.png';
|
||||||
texture.pixels = pixels;
|
texture.pixels = pixels;
|
||||||
@ -507,8 +505,8 @@ function createSpecularGlossinessTexture(specularTexture, glossinessTexture, opt
|
|||||||
return specularTexture;
|
return specularTexture;
|
||||||
}
|
}
|
||||||
|
|
||||||
var packSpecular = defined(specularTexture);
|
const packSpecular = defined(specularTexture);
|
||||||
var packGlossiness = defined(glossinessTexture);
|
const packGlossiness = defined(glossinessTexture);
|
||||||
|
|
||||||
if (!packSpecular && !packGlossiness) {
|
if (!packSpecular && !packGlossiness) {
|
||||||
return undefined;
|
return undefined;
|
||||||
@ -524,41 +522,41 @@ function createSpecularGlossinessTexture(specularTexture, glossinessTexture, opt
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
var packedTextures = [specularTexture, glossinessTexture].filter(function(texture) {
|
const packedTextures = [specularTexture, glossinessTexture].filter(function(texture) {
|
||||||
return defined(texture) && defined(texture.pixels);
|
return defined(texture) && defined(texture.pixels);
|
||||||
});
|
});
|
||||||
|
|
||||||
var dimensions = getMinimumDimensions(packedTextures, options);
|
const dimensions = getMinimumDimensions(packedTextures, options);
|
||||||
var width = dimensions[0];
|
const width = dimensions[0];
|
||||||
var height = dimensions[1];
|
const height = dimensions[1];
|
||||||
var pixelsLength = width * height;
|
const pixelsLength = width * height;
|
||||||
var pixels = Buffer.alloc(pixelsLength * 4, 0xFF); // Initialize with 4 channels, unused channels will be white
|
const pixels = Buffer.alloc(pixelsLength * 4, 0xFF); // Initialize with 4 channels, unused channels will be white
|
||||||
var scratchChannel = Buffer.alloc(pixelsLength);
|
const scratchChannel = Buffer.alloc(pixelsLength);
|
||||||
|
|
||||||
if (packSpecular) {
|
if (packSpecular) {
|
||||||
// Write into the R, G, B channels
|
// 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);
|
writeChannel(pixels, redChannel, 0);
|
||||||
var greenChannel = getTextureChannel(specularTexture, 1, width, height, scratchChannel);
|
const greenChannel = getTextureChannel(specularTexture, 1, width, height, scratchChannel);
|
||||||
writeChannel(pixels, greenChannel, 1);
|
writeChannel(pixels, greenChannel, 1);
|
||||||
var blueChannel = getTextureChannel(specularTexture, 2, width, height, scratchChannel);
|
const blueChannel = getTextureChannel(specularTexture, 2, width, height, scratchChannel);
|
||||||
writeChannel(pixels, blueChannel, 2);
|
writeChannel(pixels, blueChannel, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (packGlossiness) {
|
if (packGlossiness) {
|
||||||
// Write into the A channel
|
// 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);
|
writeChannel(pixels, glossinessChannel, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
var length = packedTextures.length;
|
const length = packedTextures.length;
|
||||||
var names = new Array(length);
|
const names = new Array(length);
|
||||||
for (var i = 0; i < length; ++i) {
|
for (let i = 0; i < length; ++i) {
|
||||||
names[i] = packedTextures[i].name;
|
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.name = name;
|
||||||
texture.extension = '.png';
|
texture.extension = '.png';
|
||||||
texture.pixels = pixels;
|
texture.pixels = pixels;
|
||||||
@ -569,20 +567,20 @@ function createSpecularGlossinessTexture(specularTexture, glossinessTexture, opt
|
|||||||
}
|
}
|
||||||
|
|
||||||
function createSpecularGlossinessMaterial(material, options) {
|
function createSpecularGlossinessMaterial(material, options) {
|
||||||
var emissiveTexture = material.emissiveTexture;
|
const emissiveTexture = material.emissiveTexture;
|
||||||
var normalTexture = material.normalTexture;
|
const normalTexture = material.normalTexture;
|
||||||
var occlusionTexture = material.ambientTexture;
|
const occlusionTexture = material.ambientTexture;
|
||||||
var diffuseTexture = material.diffuseTexture;
|
const diffuseTexture = material.diffuseTexture;
|
||||||
var alphaTexture = material.alphaTexture;
|
const alphaTexture = material.alphaTexture;
|
||||||
var specularTexture = material.specularTexture;
|
const specularTexture = material.specularTexture;
|
||||||
var glossinessTexture = material.specularShininessTexture;
|
const glossinessTexture = material.specularShininessTexture;
|
||||||
var specularGlossinessTexture = createSpecularGlossinessTexture(specularTexture, glossinessTexture, options);
|
const specularGlossinessTexture = createSpecularGlossinessTexture(specularTexture, glossinessTexture, options);
|
||||||
var diffuseAlphaTexture = createDiffuseAlphaTexture(diffuseTexture, alphaTexture, options);
|
const diffuseAlphaTexture = createDiffuseAlphaTexture(diffuseTexture, alphaTexture, options);
|
||||||
|
|
||||||
var emissiveFactor = material.emissiveColor.slice(0, 3);
|
let emissiveFactor = material.emissiveColor.slice(0, 3);
|
||||||
var diffuseFactor = material.diffuseColor;
|
let diffuseFactor = material.diffuseColor;
|
||||||
var specularFactor = material.specularColor.slice(0, 3);
|
let specularFactor = material.specularColor.slice(0, 3);
|
||||||
var glossinessFactor = material.specularShininess;
|
let glossinessFactor = material.specularShininess;
|
||||||
|
|
||||||
if (defined(emissiveTexture)) {
|
if (defined(emissiveTexture)) {
|
||||||
emissiveFactor = [1.0, 1.0, 1.0];
|
emissiveFactor = [1.0, 1.0, 1.0];
|
||||||
@ -600,11 +598,11 @@ function createSpecularGlossinessMaterial(material, options) {
|
|||||||
glossinessFactor = 1.0;
|
glossinessFactor = 1.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
var transparent = false;
|
let transparent = false;
|
||||||
if (defined(alphaTexture)) {
|
if (defined(alphaTexture)) {
|
||||||
transparent = true;
|
transparent = true;
|
||||||
} else {
|
} else {
|
||||||
var alpha = material.alpha;
|
const alpha = material.alpha;
|
||||||
diffuseFactor[3] = alpha;
|
diffuseFactor[3] = alpha;
|
||||||
transparent = alpha < 1.0;
|
transparent = alpha < 1.0;
|
||||||
}
|
}
|
||||||
@ -613,8 +611,8 @@ function createSpecularGlossinessMaterial(material, options) {
|
|||||||
transparent = transparent || diffuseTexture.transparent;
|
transparent = transparent || diffuseTexture.transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
var doubleSided = transparent;
|
const doubleSided = transparent;
|
||||||
var alphaMode = transparent ? 'BLEND' : 'OPAQUE';
|
const alphaMode = transparent ? 'BLEND' : 'OPAQUE';
|
||||||
|
|
||||||
return {
|
return {
|
||||||
name : material.name,
|
name : material.name,
|
||||||
@ -637,24 +635,24 @@ function createSpecularGlossinessMaterial(material, options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function createMetallicRoughnessMaterial(material, options) {
|
function createMetallicRoughnessMaterial(material, options) {
|
||||||
var emissiveTexture = material.emissiveTexture;
|
const emissiveTexture = material.emissiveTexture;
|
||||||
var normalTexture = material.normalTexture;
|
const normalTexture = material.normalTexture;
|
||||||
var occlusionTexture = material.ambientTexture;
|
let occlusionTexture = material.ambientTexture;
|
||||||
var baseColorTexture = material.diffuseTexture;
|
const baseColorTexture = material.diffuseTexture;
|
||||||
var alphaTexture = material.alphaTexture;
|
const alphaTexture = material.alphaTexture;
|
||||||
var metallicTexture = material.specularTexture;
|
const metallicTexture = material.specularTexture;
|
||||||
var roughnessTexture = material.specularShininessTexture;
|
const roughnessTexture = material.specularShininessTexture;
|
||||||
var metallicRoughnessTexture = createMetallicRoughnessTexture(metallicTexture, roughnessTexture, occlusionTexture, options);
|
const metallicRoughnessTexture = createMetallicRoughnessTexture(metallicTexture, roughnessTexture, occlusionTexture, options);
|
||||||
var diffuseAlphaTexture = createDiffuseAlphaTexture(baseColorTexture, alphaTexture, options);
|
const diffuseAlphaTexture = createDiffuseAlphaTexture(baseColorTexture, alphaTexture, options);
|
||||||
|
|
||||||
if (options.packOcclusion) {
|
if (options.packOcclusion) {
|
||||||
occlusionTexture = metallicRoughnessTexture;
|
occlusionTexture = metallicRoughnessTexture;
|
||||||
}
|
}
|
||||||
|
|
||||||
var emissiveFactor = material.emissiveColor.slice(0, 3);
|
let emissiveFactor = material.emissiveColor.slice(0, 3);
|
||||||
var baseColorFactor = material.diffuseColor;
|
let baseColorFactor = material.diffuseColor;
|
||||||
var metallicFactor = material.specularColor[0];
|
let metallicFactor = material.specularColor[0];
|
||||||
var roughnessFactor = material.specularShininess;
|
let roughnessFactor = material.specularShininess;
|
||||||
|
|
||||||
if (defined(emissiveTexture)) {
|
if (defined(emissiveTexture)) {
|
||||||
emissiveFactor = [1.0, 1.0, 1.0];
|
emissiveFactor = [1.0, 1.0, 1.0];
|
||||||
@ -672,11 +670,11 @@ function createMetallicRoughnessMaterial(material, options) {
|
|||||||
roughnessFactor = 1.0;
|
roughnessFactor = 1.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
var transparent = false;
|
let transparent = false;
|
||||||
if (defined(alphaTexture)) {
|
if (defined(alphaTexture)) {
|
||||||
transparent = true;
|
transparent = true;
|
||||||
} else {
|
} else {
|
||||||
var alpha = material.alpha;
|
const alpha = material.alpha;
|
||||||
baseColorFactor[3] = alpha;
|
baseColorFactor[3] = alpha;
|
||||||
transparent = alpha < 1.0;
|
transparent = alpha < 1.0;
|
||||||
}
|
}
|
||||||
@ -685,8 +683,8 @@ function createMetallicRoughnessMaterial(material, options) {
|
|||||||
transparent = transparent || baseColorTexture.transparent;
|
transparent = transparent || baseColorTexture.transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
var doubleSided = transparent;
|
const doubleSided = transparent;
|
||||||
var alphaMode = transparent ? 'BLEND' : 'OPAQUE';
|
const alphaMode = transparent ? 'BLEND' : 'OPAQUE';
|
||||||
|
|
||||||
return {
|
return {
|
||||||
name : material.name,
|
name : material.name,
|
||||||
@ -715,10 +713,10 @@ function convertTraditionalToMetallicRoughness(material) {
|
|||||||
// Roughness factor is a combination of specular intensity and shininess
|
// Roughness factor is a combination of specular intensity and shininess
|
||||||
// Metallic factor is 0.0
|
// Metallic factor is 0.0
|
||||||
// Textures are not converted for now
|
// 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.
|
// Transform from 0-1000 range to 0-1 range. Then invert.
|
||||||
var roughnessFactor = material.specularShininess;
|
let roughnessFactor = material.specularShininess;
|
||||||
roughnessFactor = roughnessFactor / 1000.0;
|
roughnessFactor = roughnessFactor / 1000.0;
|
||||||
roughnessFactor = 1.0 - roughnessFactor;
|
roughnessFactor = 1.0 - roughnessFactor;
|
||||||
roughnessFactor = CesiumMath.clamp(roughnessFactor, 0.0, 1.0);
|
roughnessFactor = CesiumMath.clamp(roughnessFactor, 0.0, 1.0);
|
||||||
@ -728,7 +726,7 @@ function convertTraditionalToMetallicRoughness(material) {
|
|||||||
roughnessFactor *= (1.0 - specularIntensity);
|
roughnessFactor *= (1.0 - specularIntensity);
|
||||||
}
|
}
|
||||||
|
|
||||||
var metallicFactor = 0.0;
|
const metallicFactor = 0.0;
|
||||||
|
|
||||||
material.specularColor = [metallicFactor, metallicFactor, metallicFactor, 1.0];
|
material.specularColor = [metallicFactor, metallicFactor, metallicFactor, 1.0];
|
||||||
material.specularShininess = roughnessFactor;
|
material.specularShininess = roughnessFactor;
|
||||||
|
293
lib/loadObj.js
293
lib/loadObj.js
@ -1,21 +1,21 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
var Cesium = require('cesium');
|
const Cesium = require('cesium');
|
||||||
var path = require('path');
|
const path = require('path');
|
||||||
var Promise = require('bluebird');
|
const Promise = require('bluebird');
|
||||||
|
|
||||||
var ArrayStorage = require('./ArrayStorage');
|
const ArrayStorage = require('./ArrayStorage');
|
||||||
var loadMtl = require('./loadMtl');
|
const loadMtl = require('./loadMtl');
|
||||||
var outsideDirectory = require('./outsideDirectory');
|
const outsideDirectory = require('./outsideDirectory');
|
||||||
var readLines = require('./readLines');
|
const readLines = require('./readLines');
|
||||||
|
|
||||||
var Cartesian3 = Cesium.Cartesian3;
|
const Cartesian3 = Cesium.Cartesian3;
|
||||||
var ComponentDatatype = Cesium.ComponentDatatype;
|
const ComponentDatatype = Cesium.ComponentDatatype;
|
||||||
var CoplanarPolygonGeometryLibrary = Cesium.CoplanarPolygonGeometryLibrary;
|
const CoplanarPolygonGeometryLibrary = Cesium.CoplanarPolygonGeometryLibrary;
|
||||||
var defaultValue = Cesium.defaultValue;
|
const defaultValue = Cesium.defaultValue;
|
||||||
var defined = Cesium.defined;
|
const defined = Cesium.defined;
|
||||||
var PolygonPipeline = Cesium.PolygonPipeline;
|
const PolygonPipeline = Cesium.PolygonPipeline;
|
||||||
var RuntimeError = Cesium.RuntimeError;
|
const RuntimeError = Cesium.RuntimeError;
|
||||||
var WindingOrder = Cesium.WindingOrder;
|
const WindingOrder = Cesium.WindingOrder;
|
||||||
|
|
||||||
module.exports = loadObj;
|
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)
|
// 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
|
const 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
|
const 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
|
const 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 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.
|
* Parse an obj file.
|
||||||
@ -58,36 +58,36 @@ var facePattern = /(-?\d+)\/?(-?\d*)\/?(-?\d*)/g;
|
|||||||
*/
|
*/
|
||||||
function loadObj(objPath, options) {
|
function loadObj(objPath, options) {
|
||||||
// Global store of vertex attributes listed in the obj file
|
// Global store of vertex attributes listed in the obj file
|
||||||
var positions = new ArrayStorage(ComponentDatatype.FLOAT);
|
let positions = new ArrayStorage(ComponentDatatype.FLOAT);
|
||||||
var normals = new ArrayStorage(ComponentDatatype.FLOAT);
|
let normals = new ArrayStorage(ComponentDatatype.FLOAT);
|
||||||
var uvs = new ArrayStorage(ComponentDatatype.FLOAT);
|
let uvs = new ArrayStorage(ComponentDatatype.FLOAT);
|
||||||
|
|
||||||
// The current node, mesh, and primitive
|
// The current node, mesh, and primitive
|
||||||
var node;
|
let node;
|
||||||
var mesh;
|
let mesh;
|
||||||
var primitive;
|
let primitive;
|
||||||
var activeMaterial;
|
let activeMaterial;
|
||||||
|
|
||||||
// All nodes seen in the obj
|
// All nodes seen in the obj
|
||||||
var nodes = [];
|
const nodes = [];
|
||||||
|
|
||||||
// Used to build the indices. The vertex cache is unique to each primitive.
|
// Used to build the indices. The vertex cache is unique to each primitive.
|
||||||
var vertexCache = {};
|
let vertexCache = {};
|
||||||
var vertexCacheLimit = 1000000;
|
const vertexCacheLimit = 1000000;
|
||||||
var vertexCacheCount = 0;
|
let vertexCacheCount = 0;
|
||||||
var vertexCount = 0;
|
let vertexCount = 0;
|
||||||
|
|
||||||
// All mtl paths seen in the obj
|
// All mtl paths seen in the obj
|
||||||
var mtlPaths = [];
|
let mtlPaths = [];
|
||||||
|
|
||||||
// Buffers for face data that spans multiple lines
|
// Buffers for face data that spans multiple lines
|
||||||
var lineBuffer = '';
|
let lineBuffer = '';
|
||||||
|
|
||||||
// Used for parsing face data
|
// Used for parsing face data
|
||||||
var faceVertices = [];
|
const faceVertices = [];
|
||||||
var facePositions = [];
|
const facePositions = [];
|
||||||
var faceUvs = [];
|
const faceUvs = [];
|
||||||
var faceNormals = [];
|
const faceNormals = [];
|
||||||
|
|
||||||
function clearVertexCache() {
|
function clearVertexCache() {
|
||||||
vertexCache = {};
|
vertexCache = {};
|
||||||
@ -123,9 +123,9 @@ function loadObj(objPath, options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function reusePrimitive(callback) {
|
function reusePrimitive(callback) {
|
||||||
var primitives = mesh.primitives;
|
const primitives = mesh.primitives;
|
||||||
var primitivesLength = primitives.length;
|
const primitivesLength = primitives.length;
|
||||||
for (var i = 0; i < primitivesLength; ++i) {
|
for (let i = 0; i < primitivesLength; ++i) {
|
||||||
if (primitives[i].material === activeMaterial) {
|
if (primitives[i].material === activeMaterial) {
|
||||||
if (!defined(callback) || callback(primitives[i])) {
|
if (!defined(callback) || callback(primitives[i])) {
|
||||||
primitive = primitives[i];
|
primitive = primitives[i];
|
||||||
@ -144,15 +144,15 @@ function loadObj(objPath, options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function faceAndPrimitiveMatch(uvs, normals, primitive) {
|
function faceAndPrimitiveMatch(uvs, normals, primitive) {
|
||||||
var faceHasUvs = uvs[0].length > 0;
|
const faceHasUvs = uvs[0].length > 0;
|
||||||
var faceHasNormals = normals[0].length > 0;
|
const faceHasNormals = normals[0].length > 0;
|
||||||
var primitiveHasUvs = primitive.uvs.length > 0;
|
const primitiveHasUvs = primitive.uvs.length > 0;
|
||||||
var primitiveHasNormals = primitive.normals.length > 0;
|
const primitiveHasNormals = primitive.normals.length > 0;
|
||||||
return primitiveHasUvs === faceHasUvs && primitiveHasNormals === faceHasNormals;
|
return primitiveHasUvs === faceHasUvs && primitiveHasNormals === faceHasNormals;
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkPrimitive(uvs, normals) {
|
function checkPrimitive(uvs, normals) {
|
||||||
var firstFace = primitive.indices.length === 0;
|
const firstFace = primitive.indices.length === 0;
|
||||||
if (!firstFace && !faceAndPrimitiveMatch(uvs, normals, primitive)) {
|
if (!firstFace && !faceAndPrimitiveMatch(uvs, normals, primitive)) {
|
||||||
reusePrimitive(function(primitive) {
|
reusePrimitive(function(primitive) {
|
||||||
return faceAndPrimitiveMatch(uvs, normals, primitive);
|
return faceAndPrimitiveMatch(uvs, normals, primitive);
|
||||||
@ -161,7 +161,7 @@ function loadObj(objPath, options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getOffset(a, attributeData, components) {
|
function getOffset(a, attributeData, components) {
|
||||||
var i = parseInt(a);
|
const i = parseInt(a);
|
||||||
if (i < 0) {
|
if (i < 0) {
|
||||||
// Negative vertex indexes reference the vertices immediately above it
|
// Negative vertex indexes reference the vertices immediately above it
|
||||||
return (attributeData.length / components + i) * components;
|
return (attributeData.length / components + i) * components;
|
||||||
@ -172,10 +172,10 @@ function loadObj(objPath, options) {
|
|||||||
function createVertex(p, u, n) {
|
function createVertex(p, u, n) {
|
||||||
// Positions
|
// Positions
|
||||||
if (p.length > 0) {
|
if (p.length > 0) {
|
||||||
var pi = getOffset(p, positions, 3);
|
const pi = getOffset(p, positions, 3);
|
||||||
var px = positions.get(pi + 0);
|
const px = positions.get(pi + 0);
|
||||||
var py = positions.get(pi + 1);
|
const py = positions.get(pi + 1);
|
||||||
var pz = positions.get(pi + 2);
|
const pz = positions.get(pi + 2);
|
||||||
primitive.positions.push(px);
|
primitive.positions.push(px);
|
||||||
primitive.positions.push(py);
|
primitive.positions.push(py);
|
||||||
primitive.positions.push(pz);
|
primitive.positions.push(pz);
|
||||||
@ -183,10 +183,10 @@ function loadObj(objPath, options) {
|
|||||||
|
|
||||||
// Normals
|
// Normals
|
||||||
if (n.length > 0) {
|
if (n.length > 0) {
|
||||||
var ni = getOffset(n, normals, 3);
|
const ni = getOffset(n, normals, 3);
|
||||||
var nx = normals.get(ni + 0);
|
const nx = normals.get(ni + 0);
|
||||||
var ny = normals.get(ni + 1);
|
const ny = normals.get(ni + 1);
|
||||||
var nz = normals.get(ni + 2);
|
const nz = normals.get(ni + 2);
|
||||||
primitive.normals.push(nx);
|
primitive.normals.push(nx);
|
||||||
primitive.normals.push(ny);
|
primitive.normals.push(ny);
|
||||||
primitive.normals.push(nz);
|
primitive.normals.push(nz);
|
||||||
@ -194,16 +194,16 @@ function loadObj(objPath, options) {
|
|||||||
|
|
||||||
// UVs
|
// UVs
|
||||||
if (u.length > 0) {
|
if (u.length > 0) {
|
||||||
var ui = getOffset(u, uvs, 2);
|
const ui = getOffset(u, uvs, 2);
|
||||||
var ux = uvs.get(ui + 0);
|
const ux = uvs.get(ui + 0);
|
||||||
var uy = uvs.get(ui + 1);
|
const uy = uvs.get(ui + 1);
|
||||||
primitive.uvs.push(ux);
|
primitive.uvs.push(ux);
|
||||||
primitive.uvs.push(uy);
|
primitive.uvs.push(uy);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function addVertex(v, p, u, n) {
|
function addVertex(v, p, u, n) {
|
||||||
var index = vertexCache[v];
|
let index = vertexCache[v];
|
||||||
if (!defined(index)) {
|
if (!defined(index)) {
|
||||||
index = vertexCount++;
|
index = vertexCount++;
|
||||||
vertexCache[v] = index;
|
vertexCache[v] = index;
|
||||||
@ -220,47 +220,47 @@ function loadObj(objPath, options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getPosition(index, result) {
|
function getPosition(index, result) {
|
||||||
var pi = getOffset(index, positions, 3);
|
const pi = getOffset(index, positions, 3);
|
||||||
var px = positions.get(pi + 0);
|
const px = positions.get(pi + 0);
|
||||||
var py = positions.get(pi + 1);
|
const py = positions.get(pi + 1);
|
||||||
var pz = positions.get(pi + 2);
|
const pz = positions.get(pi + 2);
|
||||||
return Cartesian3.fromElements(px, py, pz, result);
|
return Cartesian3.fromElements(px, py, pz, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getNormal(index, result) {
|
function getNormal(index, result) {
|
||||||
var ni = getOffset(index, normals, 3);
|
const ni = getOffset(index, normals, 3);
|
||||||
var nx = normals.get(ni + 0);
|
const nx = normals.get(ni + 0);
|
||||||
var ny = normals.get(ni + 1);
|
const ny = normals.get(ni + 1);
|
||||||
var nz = normals.get(ni + 2);
|
const nz = normals.get(ni + 2);
|
||||||
return Cartesian3.fromElements(nx, ny, nz, result);
|
return Cartesian3.fromElements(nx, ny, nz, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
var scratch1 = new Cartesian3();
|
const scratch1 = new Cartesian3();
|
||||||
var scratch2 = new Cartesian3();
|
const scratch2 = new Cartesian3();
|
||||||
var scratch3 = new Cartesian3();
|
const scratch3 = new Cartesian3();
|
||||||
var scratch4 = new Cartesian3();
|
const scratch4 = new Cartesian3();
|
||||||
var scratch5 = new Cartesian3();
|
const scratch5 = new Cartesian3();
|
||||||
var scratchCenter = new Cartesian3();
|
const scratchCenter = new Cartesian3();
|
||||||
var scratchAxis1 = new Cartesian3();
|
const scratchAxis1 = new Cartesian3();
|
||||||
var scratchAxis2 = new Cartesian3();
|
const scratchAxis2 = new Cartesian3();
|
||||||
var scratchNormal = new Cartesian3();
|
const scratchNormal = new Cartesian3();
|
||||||
var scratchPositions = [new Cartesian3(), new Cartesian3(), new Cartesian3(), new Cartesian3()];
|
const scratchPositions = [new Cartesian3(), new Cartesian3(), new Cartesian3(), new Cartesian3()];
|
||||||
var scratchVertexIndices = [];
|
const scratchVertexIndices = [];
|
||||||
var scratchPoints = [];
|
const scratchPoints = [];
|
||||||
|
|
||||||
function checkWindingCorrect(positionIndex1, positionIndex2, positionIndex3, normalIndex) {
|
function checkWindingCorrect(positionIndex1, positionIndex2, positionIndex3, normalIndex) {
|
||||||
if (normalIndex.length === 0) {
|
if (normalIndex.length === 0) {
|
||||||
// If no face normal, we have to assume the winding is correct.
|
// If no face normal, we have to assume the winding is correct.
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
var normal = getNormal(normalIndex, scratchNormal);
|
const normal = getNormal(normalIndex, scratchNormal);
|
||||||
var A = getPosition(positionIndex1, scratch1);
|
const A = getPosition(positionIndex1, scratch1);
|
||||||
var B = getPosition(positionIndex2, scratch2);
|
const B = getPosition(positionIndex2, scratch2);
|
||||||
var C = getPosition(positionIndex3, scratch3);
|
const C = getPosition(positionIndex3, scratch3);
|
||||||
|
|
||||||
var BA = Cartesian3.subtract(B, A, scratch4);
|
const BA = Cartesian3.subtract(B, A, scratch4);
|
||||||
var CA = Cartesian3.subtract(C, A, scratch5);
|
const CA = Cartesian3.subtract(C, A, scratch5);
|
||||||
var cross = Cartesian3.cross(BA, CA, scratch3);
|
const cross = Cartesian3.cross(BA, CA, scratch3);
|
||||||
|
|
||||||
return (Cartesian3.dot(normal, cross) >= 0);
|
return (Cartesian3.dot(normal, cross) >= 0);
|
||||||
}
|
}
|
||||||
@ -278,26 +278,23 @@ function loadObj(objPath, options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function addFace(vertices, positions, uvs, normals) {
|
function addFace(vertices, positions, uvs, normals) {
|
||||||
var i;
|
|
||||||
var isWindingCorrect;
|
|
||||||
|
|
||||||
checkPrimitive(uvs, normals);
|
checkPrimitive(uvs, normals);
|
||||||
|
|
||||||
if (vertices.length === 3) {
|
if (vertices.length === 3) {
|
||||||
isWindingCorrect = checkWindingCorrect(positions[0], positions[1], positions[2], normals[0]);
|
const isWindingCorrect = checkWindingCorrect(positions[0], positions[1], positions[2], normals[0]);
|
||||||
var index1 = addVertex(vertices[0], positions[0], uvs[0], normals[0]);
|
const index1 = addVertex(vertices[0], positions[0], uvs[0], normals[0]);
|
||||||
var index2 = addVertex(vertices[1], positions[1], uvs[1], normals[1]);
|
const index2 = addVertex(vertices[1], positions[1], uvs[1], normals[1]);
|
||||||
var index3 = addVertex(vertices[2], positions[2], uvs[2], normals[2]);
|
const index3 = addVertex(vertices[2], positions[2], uvs[2], normals[2]);
|
||||||
addTriangle(index1, index2, index3, isWindingCorrect);
|
addTriangle(index1, index2, index3, isWindingCorrect);
|
||||||
} else { // Triangulate if the face is not a triangle
|
} else { // Triangulate if the face is not a triangle
|
||||||
var points = scratchPoints;
|
const points = scratchPoints;
|
||||||
var vertexIndices = scratchVertexIndices;
|
const vertexIndices = scratchVertexIndices;
|
||||||
|
|
||||||
points.length = 0;
|
points.length = 0;
|
||||||
vertexIndices.length = 0;
|
vertexIndices.length = 0;
|
||||||
|
|
||||||
for (i = 0; i < vertices.length; ++i) {
|
for (let i = 0; i < vertices.length; ++i) {
|
||||||
var index = addVertex(vertices[i], positions[i], uvs[i], normals[i]);
|
const index = addVertex(vertices[i], positions[i], uvs[i], normals[i]);
|
||||||
vertexIndices.push(index);
|
vertexIndices.push(index);
|
||||||
if (i === scratchPositions.length) {
|
if (i === scratchPositions.length) {
|
||||||
scratchPositions.push(new Cartesian3());
|
scratchPositions.push(new Cartesian3());
|
||||||
@ -305,16 +302,16 @@ function loadObj(objPath, options) {
|
|||||||
points.push(getPosition(positions[i], scratchPositions[i]));
|
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) {
|
if (!validGeometry) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var projectPoints = CoplanarPolygonGeometryLibrary.createProjectPointsTo2DFunction(scratchCenter, scratchAxis1, scratchAxis2);
|
const projectPoints = CoplanarPolygonGeometryLibrary.createProjectPointsTo2DFunction(scratchCenter, scratchAxis1, scratchAxis2);
|
||||||
var points2D = projectPoints(points);
|
const points2D = projectPoints(points);
|
||||||
var indices = PolygonPipeline.triangulate(points2D);
|
const indices = PolygonPipeline.triangulate(points2D);
|
||||||
isWindingCorrect = PolygonPipeline.computeWindingOrder2D(points2D) !== WindingOrder.CLOCKWISE;
|
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);
|
addTriangle(vertexIndices[indices[i]], vertexIndices[indices[i+1]], vertexIndices[indices[i+2]], isWindingCorrect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -322,28 +319,28 @@ function loadObj(objPath, options) {
|
|||||||
|
|
||||||
function parseLine(line) {
|
function parseLine(line) {
|
||||||
line = line.trim();
|
line = line.trim();
|
||||||
var result;
|
let result;
|
||||||
|
|
||||||
if ((line.length === 0) || (line.charAt(0) === '#')) {
|
if ((line.length === 0) || (line.charAt(0) === '#')) {
|
||||||
// Don't process empty lines or comments
|
// Don't process empty lines or comments
|
||||||
} else if (/^o\s/i.test(line)) {
|
} else if (/^o\s/i.test(line)) {
|
||||||
var objectName = line.substring(2).trim();
|
const objectName = line.substring(2).trim();
|
||||||
addNode(objectName);
|
addNode(objectName);
|
||||||
} else if (/^g\s/i.test(line)) {
|
} else if (/^g\s/i.test(line)) {
|
||||||
var groupName = line.substring(2).trim();
|
const groupName = line.substring(2).trim();
|
||||||
addMesh(groupName);
|
addMesh(groupName);
|
||||||
} else if (/^usemtl\s/i.test(line)) {
|
} else if (/^usemtl\s/i.test(line)) {
|
||||||
var materialName = line.substring(7).trim();
|
const materialName = line.substring(7).trim();
|
||||||
useMaterial(materialName);
|
useMaterial(materialName);
|
||||||
} else if (/^mtllib/i.test(line)) {
|
} else if (/^mtllib/i.test(line)) {
|
||||||
var mtllibLine = line.substring(7).trim();
|
const mtllibLine = line.substring(7).trim();
|
||||||
mtlPaths = mtlPaths.concat(getMtlPaths(mtllibLine));
|
mtlPaths = mtlPaths.concat(getMtlPaths(mtllibLine));
|
||||||
} else if ((result = vertexPattern.exec(line)) !== null) {
|
} else if ((result = vertexPattern.exec(line)) !== null) {
|
||||||
positions.push(parseFloat(result[1]));
|
positions.push(parseFloat(result[1]));
|
||||||
positions.push(parseFloat(result[2]));
|
positions.push(parseFloat(result[2]));
|
||||||
positions.push(parseFloat(result[3]));
|
positions.push(parseFloat(result[3]));
|
||||||
} else if ((result = normalPattern.exec(line) ) !== null) {
|
} 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)) {
|
if (Cartesian3.equals(normal, Cartesian3.ZERO)) {
|
||||||
Cartesian3.clone(Cartesian3.UNIT_Z, normal);
|
Cartesian3.clone(Cartesian3.UNIT_Z, normal);
|
||||||
} else {
|
} else {
|
||||||
@ -404,15 +401,15 @@ function loadObj(objPath, options) {
|
|||||||
|
|
||||||
function getMtlPaths(mtllibLine) {
|
function getMtlPaths(mtllibLine) {
|
||||||
// Handle paths with spaces. E.g. mtllib my material file.mtl
|
// Handle paths with spaces. E.g. mtllib my material file.mtl
|
||||||
var mtlPaths = [];
|
const mtlPaths = [];
|
||||||
var splits = mtllibLine.split(' ');
|
const splits = mtllibLine.split(' ');
|
||||||
var length = splits.length;
|
const length = splits.length;
|
||||||
var startIndex = 0;
|
let startIndex = 0;
|
||||||
for (var i = 0; i < length; ++i) {
|
for (let i = 0; i < length; ++i) {
|
||||||
if (path.extname(splits[i]) !== '.mtl') {
|
if (path.extname(splits[i]) !== '.mtl') {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
var mtlPath = splits.slice(startIndex, i + 1).join(' ');
|
const mtlPath = splits.slice(startIndex, i + 1).join(' ');
|
||||||
mtlPaths.push(mtlPath);
|
mtlPaths.push(mtlPath);
|
||||||
startIndex = i + 1;
|
startIndex = i + 1;
|
||||||
}
|
}
|
||||||
@ -424,7 +421,7 @@ function finishLoading(nodes, mtlPaths, objPath, usesMaterials, options) {
|
|||||||
if (nodes.length === 0) {
|
if (nodes.length === 0) {
|
||||||
throw new RuntimeError(objPath + ' does not have any geometry data');
|
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)
|
return loadMtls(mtlPaths, objPath, options)
|
||||||
.then(function(materials) {
|
.then(function(materials) {
|
||||||
if (materials.length > 0 && !usesMaterials) {
|
if (materials.length > 0 && !usesMaterials) {
|
||||||
@ -444,8 +441,8 @@ function normalizeMtlPath(mtlPath, objDirectory) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function loadMtls(mtlPaths, objPath, options) {
|
function loadMtls(mtlPaths, objPath, options) {
|
||||||
var objDirectory = path.dirname(objPath);
|
const objDirectory = path.dirname(objPath);
|
||||||
var materials = [];
|
let materials = [];
|
||||||
|
|
||||||
// Remove duplicates
|
// Remove duplicates
|
||||||
mtlPaths = mtlPaths.filter(function(value, index, self) {
|
mtlPaths = mtlPaths.filter(function(value, index, self) {
|
||||||
@ -454,7 +451,7 @@ function loadMtls(mtlPaths, objPath, options) {
|
|||||||
|
|
||||||
return Promise.map(mtlPaths, function(mtlPath) {
|
return Promise.map(mtlPaths, function(mtlPath) {
|
||||||
mtlPath = normalizeMtlPath(mtlPath, objDirectory);
|
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)) {
|
if (options.secure && outsideDirectory(mtlPath, objDirectory)) {
|
||||||
// Try looking for the .mtl in the same directory as the obj
|
// 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.');
|
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.');
|
||||||
@ -489,16 +486,16 @@ function loadMtls(mtlPaths, objPath, options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function assignDefaultMaterial(nodes, materials) {
|
function assignDefaultMaterial(nodes, materials) {
|
||||||
var defaultMaterial = materials[0].name;
|
const defaultMaterial = materials[0].name;
|
||||||
var nodesLength = nodes.length;
|
const nodesLength = nodes.length;
|
||||||
for (var i = 0; i < nodesLength; ++i) {
|
for (let i = 0; i < nodesLength; ++i) {
|
||||||
var meshes = nodes[i].meshes;
|
const meshes = nodes[i].meshes;
|
||||||
var meshesLength = meshes.length;
|
const meshesLength = meshes.length;
|
||||||
for (var j = 0; j < meshesLength; ++j) {
|
for (let j = 0; j < meshesLength; ++j) {
|
||||||
var primitives = meshes[j].primitives;
|
const primitives = meshes[j].primitives;
|
||||||
var primitivesLength = primitives.length;
|
const primitivesLength = primitives.length;
|
||||||
for (var k = 0; k < primitivesLength; ++k) {
|
for (let k = 0; k < primitivesLength; ++k) {
|
||||||
var primitive = primitives[k];
|
const primitive = primitives[k];
|
||||||
primitive.material = defaultValue(primitive.material, defaultMaterial);
|
primitive.material = defaultValue(primitive.material, defaultMaterial);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -517,8 +514,8 @@ function removeEmptyMeshes(meshes) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function meshesHaveNames(meshes) {
|
function meshesHaveNames(meshes) {
|
||||||
var meshesLength = meshes.length;
|
const meshesLength = meshes.length;
|
||||||
for (var i = 0; i < meshesLength; ++i) {
|
for (let i = 0; i < meshesLength; ++i) {
|
||||||
if (defined(meshes[i].name)) {
|
if (defined(meshes[i].name)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -527,21 +524,21 @@ function meshesHaveNames(meshes) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function removeEmptyNodes(nodes) {
|
function removeEmptyNodes(nodes) {
|
||||||
var final = [];
|
const final = [];
|
||||||
var nodesLength = nodes.length;
|
const nodesLength = nodes.length;
|
||||||
for (var i = 0; i < nodesLength; ++i) {
|
for (let i = 0; i < nodesLength; ++i) {
|
||||||
var node = nodes[i];
|
const node = nodes[i];
|
||||||
var meshes = removeEmptyMeshes(node.meshes);
|
const meshes = removeEmptyMeshes(node.meshes);
|
||||||
if (meshes.length === 0) {
|
if (meshes.length === 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
node.meshes = meshes;
|
node.meshes = meshes;
|
||||||
if (!defined(node.name) && meshesHaveNames(meshes)) {
|
if (!defined(node.name) && meshesHaveNames(meshes)) {
|
||||||
// If the obj has groups (g) but not object groups (o) then convert meshes to nodes
|
// If the obj has groups (g) but not object groups (o) then convert meshes to nodes
|
||||||
var meshesLength = meshes.length;
|
const meshesLength = meshes.length;
|
||||||
for (var j = 0; j < meshesLength; ++j) {
|
for (let j = 0; j < meshesLength; ++j) {
|
||||||
var mesh = meshes[j];
|
const mesh = meshes[j];
|
||||||
var convertedNode = new Node();
|
const convertedNode = new Node();
|
||||||
convertedNode.name = mesh.name;
|
convertedNode.name = mesh.name;
|
||||||
convertedNode.meshes = [mesh];
|
convertedNode.meshes = [mesh];
|
||||||
final.push(convertedNode);
|
final.push(convertedNode);
|
||||||
@ -554,11 +551,11 @@ function removeEmptyNodes(nodes) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function setDefaultNames(items, defaultName, usedNames) {
|
function setDefaultNames(items, defaultName, usedNames) {
|
||||||
var itemsLength = items.length;
|
const itemsLength = items.length;
|
||||||
for (var i = 0; i < itemsLength; ++i) {
|
for (let i = 0; i < itemsLength; ++i) {
|
||||||
var item = items[i];
|
const item = items[i];
|
||||||
var name = defaultValue(item.name, defaultName);
|
let name = defaultValue(item.name, defaultName);
|
||||||
var occurrences = usedNames[name];
|
const occurrences = usedNames[name];
|
||||||
if (defined(occurrences)) {
|
if (defined(occurrences)) {
|
||||||
usedNames[name]++;
|
usedNames[name]++;
|
||||||
name = name + '_' + occurrences;
|
name = name + '_' + occurrences;
|
||||||
@ -570,11 +567,11 @@ function setDefaultNames(items, defaultName, usedNames) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function setDefaults(nodes) {
|
function setDefaults(nodes) {
|
||||||
var usedNames = {};
|
const usedNames = {};
|
||||||
setDefaultNames(nodes, 'Node', usedNames);
|
setDefaultNames(nodes, 'Node', usedNames);
|
||||||
var nodesLength = nodes.length;
|
const nodesLength = nodes.length;
|
||||||
for (var i = 0; i < nodesLength; ++i) {
|
for (let i = 0; i < nodesLength; ++i) {
|
||||||
var node = nodes[i];
|
const node = nodes[i];
|
||||||
setDefaultNames(node.meshes, node.name + '-Mesh', usedNames);
|
setDefaultNames(node.meshes, node.name + '-Mesh', usedNames);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
var Cesium = require('cesium');
|
const Cesium = require('cesium');
|
||||||
var fsExtra = require('fs-extra');
|
const fsExtra = require('fs-extra');
|
||||||
var jpeg = require('jpeg-js');
|
const jpeg = require('jpeg-js');
|
||||||
var path = require('path');
|
const path = require('path');
|
||||||
var PNG = require('pngjs').PNG;
|
const PNG = require('pngjs').PNG;
|
||||||
var Promise = require('bluebird');
|
const Promise = require('bluebird');
|
||||||
var Texture = require('./Texture');
|
const Texture = require('./Texture');
|
||||||
|
|
||||||
var defaultValue = Cesium.defaultValue;
|
const defaultValue = Cesium.defaultValue;
|
||||||
var defined = Cesium.defined;
|
const defined = Cesium.defined;
|
||||||
|
|
||||||
module.exports = loadTexture;
|
module.exports = loadTexture;
|
||||||
|
|
||||||
@ -30,15 +30,15 @@ function loadTexture(texturePath, options) {
|
|||||||
|
|
||||||
return fsExtra.readFile(texturePath)
|
return fsExtra.readFile(texturePath)
|
||||||
.then(function(source) {
|
.then(function(source) {
|
||||||
var name = path.basename(texturePath, path.extname(texturePath));
|
const name = path.basename(texturePath, path.extname(texturePath));
|
||||||
var extension = path.extname(texturePath).toLowerCase();
|
const extension = path.extname(texturePath).toLowerCase();
|
||||||
var texture = new Texture();
|
const texture = new Texture();
|
||||||
texture.source = source;
|
texture.source = source;
|
||||||
texture.name = name;
|
texture.name = name;
|
||||||
texture.extension = extension;
|
texture.extension = extension;
|
||||||
texture.path = texturePath;
|
texture.path = texturePath;
|
||||||
|
|
||||||
var decodePromise;
|
let decodePromise;
|
||||||
if (extension === '.png') {
|
if (extension === '.png') {
|
||||||
decodePromise = decodePng(texture, options);
|
decodePromise = decodePng(texture, options);
|
||||||
} else if (extension === '.jpg' || extension === '.jpeg') {
|
} else if (extension === '.jpg' || extension === '.jpeg') {
|
||||||
@ -54,8 +54,8 @@ function loadTexture(texturePath, options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function hasTransparency(pixels) {
|
function hasTransparency(pixels) {
|
||||||
var pixelsLength = pixels.length / 4;
|
const pixelsLength = pixels.length / 4;
|
||||||
for (var i = 0; i < pixelsLength; ++i) {
|
for (let i = 0; i < pixelsLength; ++i) {
|
||||||
if (pixels[i * 4 + 3] < 255) {
|
if (pixels[i * 4 + 3] < 255) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -92,12 +92,12 @@ function parsePng(data) {
|
|||||||
|
|
||||||
function decodePng(texture, options) {
|
function decodePng(texture, options) {
|
||||||
// Color type is encoded in the 25th bit of the png
|
// Color type is encoded in the 25th bit of the png
|
||||||
var source = texture.source;
|
const source = texture.source;
|
||||||
var colorType = source[25];
|
const colorType = source[25];
|
||||||
var channels = getChannels(colorType);
|
const channels = getChannels(colorType);
|
||||||
|
|
||||||
var checkTransparency = (channels === 4 && options.checkTransparency);
|
const checkTransparency = (channels === 4 && options.checkTransparency);
|
||||||
var decode = options.decode || checkTransparency;
|
const decode = options.decode || checkTransparency;
|
||||||
|
|
||||||
if (decode) {
|
if (decode) {
|
||||||
return parsePng(source)
|
return parsePng(source)
|
||||||
@ -117,8 +117,8 @@ function decodePng(texture, options) {
|
|||||||
|
|
||||||
function decodeJpeg(texture, options) {
|
function decodeJpeg(texture, options) {
|
||||||
if (options.decode) {
|
if (options.decode) {
|
||||||
var source = texture.source;
|
const source = texture.source;
|
||||||
var decodedResults = jpeg.decode(source);
|
const decodedResults = jpeg.decode(source);
|
||||||
texture.pixels = decodedResults.data;
|
texture.pixels = decodedResults.data;
|
||||||
texture.width = decodedResults.width;
|
texture.width = decodedResults.width;
|
||||||
texture.height = decodedResults.height;
|
texture.height = decodedResults.height;
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
var Cesium = require('cesium');
|
const Cesium = require('cesium');
|
||||||
var fsExtra = require('fs-extra');
|
const fsExtra = require('fs-extra');
|
||||||
var path = require('path');
|
const path = require('path');
|
||||||
var createGltf = require('./createGltf');
|
const createGltf = require('./createGltf');
|
||||||
var loadObj = require('./loadObj');
|
const loadObj = require('./loadObj');
|
||||||
var writeGltf = require('./writeGltf');
|
const writeGltf = require('./writeGltf');
|
||||||
|
|
||||||
var defaultValue = Cesium.defaultValue;
|
const defaultValue = Cesium.defaultValue;
|
||||||
var defined = Cesium.defined;
|
const defined = Cesium.defined;
|
||||||
var DeveloperError = Cesium.DeveloperError;
|
const DeveloperError = Cesium.DeveloperError;
|
||||||
|
|
||||||
module.exports = obj2gltf;
|
module.exports = obj2gltf;
|
||||||
|
|
||||||
@ -40,7 +40,7 @@ module.exports = obj2gltf;
|
|||||||
* @return {Promise} A promise that resolves to the glTF JSON or glb buffer.
|
* @return {Promise} A promise that resolves to the glTF JSON or glb buffer.
|
||||||
*/
|
*/
|
||||||
function obj2gltf(objPath, options) {
|
function obj2gltf(objPath, options) {
|
||||||
var defaults = obj2gltf.defaults;
|
const defaults = obj2gltf.defaults;
|
||||||
options = defaultValue(options, {});
|
options = defaultValue(options, {});
|
||||||
options.binary = defaultValue(options.binary, defaults.binary);
|
options.binary = defaultValue(options.binary, defaults.binary);
|
||||||
options.separate = defaultValue(options.separate, defaults.separate);
|
options.separate = defaultValue(options.separate, defaults.separate);
|
||||||
@ -100,7 +100,7 @@ function getDefaultLogger() {
|
|||||||
function getDefaultWriter(outputDirectory) {
|
function getDefaultWriter(outputDirectory) {
|
||||||
if (defined(outputDirectory)) {
|
if (defined(outputDirectory)) {
|
||||||
return function(file, data) {
|
return function(file, data) {
|
||||||
var outputFile = path.join(outputDirectory, file);
|
const outputFile = path.join(outputDirectory, file);
|
||||||
return fsExtra.outputFile(outputFile, data);
|
return fsExtra.outputFile(outputFile, data);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
var path = require('path');
|
const path = require('path');
|
||||||
|
|
||||||
module.exports = outsideDirectory;
|
module.exports = outsideDirectory;
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
var fsExtra = require('fs-extra');
|
const fsExtra = require('fs-extra');
|
||||||
var Promise = require('bluebird');
|
const Promise = require('bluebird');
|
||||||
var readline = require('readline');
|
const readline = require('readline');
|
||||||
|
|
||||||
module.exports = readLines;
|
module.exports = readLines;
|
||||||
|
|
||||||
@ -16,11 +16,11 @@ module.exports = readLines;
|
|||||||
*/
|
*/
|
||||||
function readLines(path, callback) {
|
function readLines(path, callback) {
|
||||||
return new Promise(function(resolve, reject) {
|
return new Promise(function(resolve, reject) {
|
||||||
var stream = fsExtra.createReadStream(path);
|
const stream = fsExtra.createReadStream(path);
|
||||||
stream.on('error', reject);
|
stream.on('error', reject);
|
||||||
stream.on('end', resolve);
|
stream.on('end', resolve);
|
||||||
|
|
||||||
var lineReader = readline.createInterface({
|
const lineReader = readline.createInterface({
|
||||||
input : stream
|
input : stream
|
||||||
});
|
});
|
||||||
lineReader.on('line', callback);
|
lineReader.on('line', callback);
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
var Cesium = require('cesium');
|
const Cesium = require('cesium');
|
||||||
var mime = require('mime');
|
const mime = require('mime');
|
||||||
var PNG = require('pngjs').PNG;
|
const PNG = require('pngjs').PNG;
|
||||||
var Promise = require('bluebird');
|
const Promise = require('bluebird');
|
||||||
var getBufferPadded = require('./getBufferPadded');
|
const getBufferPadded = require('./getBufferPadded');
|
||||||
var gltfToGlb = require('./gltfToGlb');
|
const gltfToGlb = require('./gltfToGlb');
|
||||||
|
|
||||||
var defined = Cesium.defined;
|
const defined = Cesium.defined;
|
||||||
var RuntimeError = Cesium.RuntimeError;
|
const RuntimeError = Cesium.RuntimeError;
|
||||||
|
|
||||||
module.exports = writeGltf;
|
module.exports = writeGltf;
|
||||||
|
|
||||||
@ -23,11 +23,11 @@ module.exports = writeGltf;
|
|||||||
function writeGltf(gltf, options) {
|
function writeGltf(gltf, options) {
|
||||||
return encodeTextures(gltf)
|
return encodeTextures(gltf)
|
||||||
.then(function() {
|
.then(function() {
|
||||||
var binary = options.binary;
|
const binary = options.binary;
|
||||||
var separate = options.separate;
|
const separate = options.separate;
|
||||||
var separateTextures = options.separateTextures;
|
const separateTextures = options.separateTextures;
|
||||||
|
|
||||||
var promises = [];
|
const promises = [];
|
||||||
if (separateTextures) {
|
if (separateTextures) {
|
||||||
promises.push(writeSeparateTextures(gltf, options));
|
promises.push(writeSeparateTextures(gltf, options));
|
||||||
} else {
|
} else {
|
||||||
@ -40,7 +40,7 @@ function writeGltf(gltf, options) {
|
|||||||
writeEmbeddedBuffer(gltf);
|
writeEmbeddedBuffer(gltf);
|
||||||
}
|
}
|
||||||
|
|
||||||
var binaryBuffer = gltf.buffers[0].extras._obj2gltf.source;
|
const binaryBuffer = gltf.buffers[0].extras._obj2gltf.source;
|
||||||
|
|
||||||
return Promise.all(promises)
|
return Promise.all(promises)
|
||||||
.then(function() {
|
.then(function() {
|
||||||
@ -56,10 +56,10 @@ function writeGltf(gltf, options) {
|
|||||||
|
|
||||||
function encodePng(texture) {
|
function encodePng(texture) {
|
||||||
// Constants defined by pngjs
|
// Constants defined by pngjs
|
||||||
var rgbColorType = 2;
|
const rgbColorType = 2;
|
||||||
var rgbaColorType = 6;
|
const rgbaColorType = 6;
|
||||||
|
|
||||||
var png = new PNG({
|
const png = new PNG({
|
||||||
width : texture.width,
|
width : texture.width,
|
||||||
height : texture.height,
|
height : texture.height,
|
||||||
colorType : texture.transparent ? rgbaColorType : rgbColorType,
|
colorType : texture.transparent ? rgbaColorType : rgbColorType,
|
||||||
@ -70,8 +70,8 @@ function encodePng(texture) {
|
|||||||
png.data = texture.pixels;
|
png.data = texture.pixels;
|
||||||
|
|
||||||
return new Promise(function(resolve, reject) {
|
return new Promise(function(resolve, reject) {
|
||||||
var chunks = [];
|
const chunks = [];
|
||||||
var stream = png.pack();
|
const stream = png.pack();
|
||||||
stream.on('data', function(chunk) {
|
stream.on('data', function(chunk) {
|
||||||
chunks.push(chunk);
|
chunks.push(chunk);
|
||||||
});
|
});
|
||||||
@ -93,22 +93,22 @@ function encodeTexture(texture) {
|
|||||||
|
|
||||||
function encodeTextures(gltf) {
|
function encodeTextures(gltf) {
|
||||||
// Dynamically generated PBR textures need to be encoded to png prior to being saved
|
// Dynamically generated PBR textures need to be encoded to png prior to being saved
|
||||||
var encodePromises = [];
|
const encodePromises = [];
|
||||||
var images = gltf.images;
|
const images = gltf.images;
|
||||||
var length = images.length;
|
const length = images.length;
|
||||||
for (var i = 0; i < length; ++i) {
|
for (let i = 0; i < length; ++i) {
|
||||||
encodePromises.push(encodeTexture(images[i].extras._obj2gltf));
|
encodePromises.push(encodeTexture(images[i].extras._obj2gltf));
|
||||||
}
|
}
|
||||||
return Promise.all(encodePromises);
|
return Promise.all(encodePromises);
|
||||||
}
|
}
|
||||||
|
|
||||||
function deleteExtras(gltf) {
|
function deleteExtras(gltf) {
|
||||||
var buffer = gltf.buffers[0];
|
const buffer = gltf.buffers[0];
|
||||||
delete buffer.extras;
|
delete buffer.extras;
|
||||||
|
|
||||||
var images = gltf.images;
|
const images = gltf.images;
|
||||||
var imagesLength = images.length;
|
const imagesLength = images.length;
|
||||||
for (var i = 0; i < imagesLength; ++i) {
|
for (let i = 0; i < imagesLength; ++i) {
|
||||||
delete images[i].extras;
|
delete images[i].extras;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -124,26 +124,26 @@ function removeEmpty(json) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function writeSeparateBuffer(gltf, options) {
|
function writeSeparateBuffer(gltf, options) {
|
||||||
var buffer = gltf.buffers[0];
|
const buffer = gltf.buffers[0];
|
||||||
var source = buffer.extras._obj2gltf.source;
|
const source = buffer.extras._obj2gltf.source;
|
||||||
var bufferUri = buffer.name + '.bin';
|
const bufferUri = buffer.name + '.bin';
|
||||||
buffer.uri = bufferUri;
|
buffer.uri = bufferUri;
|
||||||
return options.writer(bufferUri, source);
|
return options.writer(bufferUri, source);
|
||||||
}
|
}
|
||||||
|
|
||||||
function writeSeparateTextures(gltf, options) {
|
function writeSeparateTextures(gltf, options) {
|
||||||
var images = gltf.images;
|
const images = gltf.images;
|
||||||
return Promise.map(images, function(image) {
|
return Promise.map(images, function(image) {
|
||||||
var texture = image.extras._obj2gltf;
|
const texture = image.extras._obj2gltf;
|
||||||
var imageUri = image.name + texture.extension;
|
const imageUri = image.name + texture.extension;
|
||||||
image.uri = imageUri;
|
image.uri = imageUri;
|
||||||
return options.writer(imageUri, texture.source);
|
return options.writer(imageUri, texture.source);
|
||||||
}, {concurrency : 10});
|
}, {concurrency : 10});
|
||||||
}
|
}
|
||||||
|
|
||||||
function writeEmbeddedBuffer(gltf) {
|
function writeEmbeddedBuffer(gltf) {
|
||||||
var buffer = gltf.buffers[0];
|
const buffer = gltf.buffers[0];
|
||||||
var source = buffer.extras._obj2gltf.source;
|
const source = buffer.extras._obj2gltf.source;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
buffer.uri = 'data:application/octet-stream;base64,' + source.toString('base64');
|
buffer.uri = 'data:application/octet-stream;base64,' + source.toString('base64');
|
||||||
@ -154,19 +154,19 @@ function writeEmbeddedBuffer(gltf) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function writeEmbeddedTextures(gltf) {
|
function writeEmbeddedTextures(gltf) {
|
||||||
var buffer = gltf.buffers[0];
|
const buffer = gltf.buffers[0];
|
||||||
var bufferExtras = buffer.extras._obj2gltf;
|
const bufferExtras = buffer.extras._obj2gltf;
|
||||||
var bufferSource = bufferExtras.source;
|
const bufferSource = bufferExtras.source;
|
||||||
var images = gltf.images;
|
const images = gltf.images;
|
||||||
var imagesLength = images.length;
|
const imagesLength = images.length;
|
||||||
var sources = [bufferSource];
|
const sources = [bufferSource];
|
||||||
var byteOffset = bufferSource.length;
|
let byteOffset = bufferSource.length;
|
||||||
|
|
||||||
for (var i = 0; i < imagesLength; ++i) {
|
for (let i = 0; i < imagesLength; ++i) {
|
||||||
var image = images[i];
|
const image = images[i];
|
||||||
var texture = image.extras._obj2gltf;
|
const texture = image.extras._obj2gltf;
|
||||||
var textureSource = texture.source;
|
const textureSource = texture.source;
|
||||||
var textureByteLength = textureSource.length;
|
const textureByteLength = textureSource.length;
|
||||||
|
|
||||||
image.mimeType = mime.getType(texture.extension);
|
image.mimeType = mime.getType(texture.extension);
|
||||||
image.bufferView = gltf.bufferViews.length;
|
image.bufferView = gltf.bufferViews.length;
|
||||||
@ -179,7 +179,7 @@ function writeEmbeddedTextures(gltf) {
|
|||||||
sources.push(textureSource);
|
sources.push(textureSource);
|
||||||
}
|
}
|
||||||
|
|
||||||
var source = getBufferPadded(Buffer.concat(sources));
|
const source = getBufferPadded(Buffer.concat(sources));
|
||||||
bufferExtras.source = source;
|
bufferExtras.source = source;
|
||||||
buffer.byteLength = source.length;
|
buffer.byteLength = source.length;
|
||||||
}
|
}
|
||||||
|
20
package.json
20
package.json
@ -26,24 +26,24 @@
|
|||||||
"node": ">=4.0.0"
|
"node": ">=4.0.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bluebird": "^3.5.2",
|
"bluebird": "^3.5.3",
|
||||||
"cesium": "^1.50.0",
|
"cesium": "^1.54.0",
|
||||||
"fs-extra": "^7.0.0",
|
"fs-extra": "^7.0.1",
|
||||||
"jpeg-js": "^0.3.4",
|
"jpeg-js": "^0.3.4",
|
||||||
"mime": "^2.3.1",
|
"mime": "^2.4.0",
|
||||||
"pngjs": "^3.3.3",
|
"pngjs": "^3.3.3",
|
||||||
"yargs": "^12.0.2"
|
"yargs": "^12.0.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"cloc": "^2.3.4",
|
"cloc": "^2.4.0",
|
||||||
"coveralls": "^3.0.2",
|
"coveralls": "^3.0.2",
|
||||||
"eslint": "^5.6.1",
|
"eslint": "^5.13.0",
|
||||||
"eslint-config-cesium": "^6.0.0",
|
"eslint-config-cesium": "^6.0.1",
|
||||||
"gulp": "^4.0.0",
|
"gulp": "^4.0.0",
|
||||||
"jasmine": "^3.2.0",
|
"jasmine": "^3.3.1",
|
||||||
"jasmine-spec-reporter": "^4.2.1",
|
"jasmine-spec-reporter": "^4.2.1",
|
||||||
"jsdoc": "^3.5.5",
|
"jsdoc": "^3.5.5",
|
||||||
"nyc": "^13.0.1",
|
"nyc": "^13.2.0",
|
||||||
"open": "^0.0.5",
|
"open": "^0.0.5",
|
||||||
"requirejs": "^2.3.6"
|
"requirejs": "^2.3.6"
|
||||||
},
|
},
|
||||||
|
@ -2,5 +2,8 @@
|
|||||||
"extends": "../.eslintrc.json",
|
"extends": "../.eslintrc.json",
|
||||||
"env": {
|
"env": {
|
||||||
"jasmine": true
|
"jasmine": true
|
||||||
|
},
|
||||||
|
"rules": {
|
||||||
|
"no-restricted-globals": ["error", "fdescribe", "fit"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,8 +2,5 @@
|
|||||||
"spec_dir": "specs",
|
"spec_dir": "specs",
|
||||||
"spec_files": [
|
"spec_files": [
|
||||||
"**/*Spec.js"
|
"**/*Spec.js"
|
||||||
],
|
|
||||||
"helpers": [
|
|
||||||
"matchers/nodeHelper.js"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -1,61 +1,43 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
var Cesium = require('cesium');
|
const Cesium = require('cesium');
|
||||||
var Promise = require('bluebird');
|
const obj2gltf = require('../../lib/obj2gltf');
|
||||||
var obj2gltf = require('../../lib/obj2gltf');
|
const createGltf = require('../../lib/createGltf');
|
||||||
var createGltf = require('../../lib/createGltf');
|
const loadObj = require('../../lib/loadObj');
|
||||||
var loadObj = require('../../lib/loadObj');
|
const { getDefaultMaterial } = require('../../lib/loadMtl');
|
||||||
var getDefaultMaterial = require('../../lib/loadMtl').getDefaultMaterial;
|
|
||||||
|
|
||||||
var clone = Cesium.clone;
|
const clone = Cesium.clone;
|
||||||
var defined = Cesium.defined;
|
const defined = Cesium.defined;
|
||||||
var WebGLConstants = Cesium.WebGLConstants;
|
const WebGLConstants = Cesium.WebGLConstants;
|
||||||
|
|
||||||
var boxObjPath = 'specs/data/box/box.obj';
|
const boxObjPath = 'specs/data/box/box.obj';
|
||||||
var groupObjPath = 'specs/data/box-objects-groups-materials/box-objects-groups-materials.obj';
|
const groupObjPath = 'specs/data/box-objects-groups-materials/box-objects-groups-materials.obj';
|
||||||
var complexObjPath = 'specs/data/box-complex-material/box-complex-material.obj';
|
const complexObjPath = 'specs/data/box-complex-material/box-complex-material.obj';
|
||||||
var noMaterialsObjPath = 'specs/data/box-no-materials/box-no-materials.obj';
|
const noMaterialsObjPath = 'specs/data/box-no-materials/box-no-materials.obj';
|
||||||
var mixedAttributesObjPath = 'specs/data/box-mixed-attributes-2/box-mixed-attributes-2.obj';
|
const mixedAttributesObjPath = 'specs/data/box-mixed-attributes-2/box-mixed-attributes-2.obj';
|
||||||
|
|
||||||
var options;
|
let options;
|
||||||
|
|
||||||
describe('createGltf', function() {
|
describe('createGltf', () => {
|
||||||
var boxObjData;
|
let boxObjData;
|
||||||
var groupObjData;
|
let groupObjData;
|
||||||
var complexObjData;
|
let complexObjData;
|
||||||
var noMaterialsObjData;
|
let noMaterialsObjData;
|
||||||
var mixedAttributesObjData;
|
let mixedAttributesObjData;
|
||||||
|
|
||||||
beforeEach(function(done) {
|
beforeEach(async () => {
|
||||||
options = clone(obj2gltf.defaults);
|
options = clone(obj2gltf.defaults);
|
||||||
options.overridingTextures = {};
|
options.overridingTextures = {};
|
||||||
options.logger = function() {};
|
options.logger = () => {};
|
||||||
|
|
||||||
return Promise.all([
|
boxObjData = await loadObj(boxObjPath, options);
|
||||||
loadObj(boxObjPath, options)
|
groupObjData = await loadObj(groupObjPath, options);
|
||||||
.then(function(data) {
|
complexObjData = await loadObj(complexObjPath, options);
|
||||||
boxObjData = data;
|
noMaterialsObjData = await loadObj(noMaterialsObjPath, options);
|
||||||
}),
|
mixedAttributesObjData = await loadObj(mixedAttributesObjPath, options);
|
||||||
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);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('simple gltf', function() {
|
it('simple gltf', () => {
|
||||||
var gltf = createGltf(boxObjData, options);
|
const gltf = createGltf(boxObjData, options);
|
||||||
|
|
||||||
expect(gltf.materials.length).toBe(1);
|
expect(gltf.materials.length).toBe(1);
|
||||||
expect(gltf.scene).toBe(0);
|
expect(gltf.scene).toBe(0);
|
||||||
@ -63,13 +45,13 @@ describe('createGltf', function() {
|
|||||||
expect(gltf.nodes.length).toBe(1);
|
expect(gltf.nodes.length).toBe(1);
|
||||||
expect(gltf.meshes.length).toBe(1);
|
expect(gltf.meshes.length).toBe(1);
|
||||||
|
|
||||||
var primitives = gltf.meshes[0].primitives;
|
const primitives = gltf.meshes[0].primitives;
|
||||||
var primitive = primitives[0];
|
const primitive = primitives[0];
|
||||||
var attributes = primitive.attributes;
|
const attributes = primitive.attributes;
|
||||||
var positionAccessor = gltf.accessors[attributes.POSITION];
|
const positionAccessor = gltf.accessors[attributes.POSITION];
|
||||||
var normalAccessor = gltf.accessors[attributes.NORMAL];
|
const normalAccessor = gltf.accessors[attributes.NORMAL];
|
||||||
var uvAccessor = gltf.accessors[attributes.TEXCOORD_0];
|
const uvAccessor = gltf.accessors[attributes.TEXCOORD_0];
|
||||||
var indexAccessor = gltf.accessors[primitive.indices];
|
const indexAccessor = gltf.accessors[primitive.indices];
|
||||||
|
|
||||||
expect(primitives.length).toBe(1);
|
expect(primitives.length).toBe(1);
|
||||||
expect(positionAccessor.count).toBe(24);
|
expect(positionAccessor.count).toBe(24);
|
||||||
@ -78,8 +60,8 @@ describe('createGltf', function() {
|
|||||||
expect(indexAccessor.count).toBe(36);
|
expect(indexAccessor.count).toBe(36);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('multiple nodes, meshes, and primitives', function() {
|
it('multiple nodes, meshes, and primitives', () => {
|
||||||
var gltf = createGltf(groupObjData, options);
|
const gltf = createGltf(groupObjData, options);
|
||||||
|
|
||||||
expect(gltf.materials.length).toBe(3);
|
expect(gltf.materials.length).toBe(3);
|
||||||
expect(gltf.scene).toBe(0);
|
expect(gltf.scene).toBe(0);
|
||||||
@ -90,28 +72,28 @@ describe('createGltf', function() {
|
|||||||
expect(gltf.meshes.length).toBe(3);
|
expect(gltf.meshes.length).toBe(3);
|
||||||
|
|
||||||
// Check for two primitives in each mesh
|
// Check for two primitives in each mesh
|
||||||
var length = gltf.meshes.length;
|
const length = gltf.meshes.length;
|
||||||
for (var i = 0; i < length; ++i) {
|
for (let i = 0; i < length; ++i) {
|
||||||
var mesh = gltf.meshes[i];
|
const mesh = gltf.meshes[i];
|
||||||
expect(mesh.primitives.length).toBe(2);
|
expect(mesh.primitives.length).toBe(2);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
it('multiple textures', function() {
|
it('multiple textures', () => {
|
||||||
var gltf = createGltf(complexObjData, options);
|
const gltf = createGltf(complexObjData, options);
|
||||||
var material = gltf.materials[0];
|
const material = gltf.materials[0];
|
||||||
var pbr = material.pbrMetallicRoughness;
|
const pbr = material.pbrMetallicRoughness;
|
||||||
var textures = [pbr.metallicRoughnessTexture, pbr.baseColorTexture, material.emissiveTexture, material.normalTexture, material.occlusionTexture];
|
const textures = [pbr.metallicRoughnessTexture, pbr.baseColorTexture, material.emissiveTexture, material.normalTexture, material.occlusionTexture];
|
||||||
expect(textures.map(function(texture) {
|
expect(textures.map((texture) => {
|
||||||
return texture.index;
|
return texture.index;
|
||||||
}).sort()).toEqual([0, 1, 2, 3, 4]);
|
}).sort()).toEqual([0, 1, 2, 3, 4]);
|
||||||
expect(gltf.samplers[0]).toBeDefined();
|
expect(gltf.samplers[0]).toBeDefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('creates default material', function() {
|
it('creates default material', () => {
|
||||||
var gltf = createGltf(noMaterialsObjData, options);
|
const gltf = createGltf(noMaterialsObjData, options);
|
||||||
var material = gltf.materials[0];
|
const material = gltf.materials[0];
|
||||||
var pbr = material.pbrMetallicRoughness;
|
const pbr = material.pbrMetallicRoughness;
|
||||||
expect(material.name).toBe('default');
|
expect(material.name).toBe('default');
|
||||||
expect(pbr.baseColorTexture).toBeUndefined();
|
expect(pbr.baseColorTexture).toBeUndefined();
|
||||||
expect(pbr.metallicRoughnessTexture).toBeUndefined();
|
expect(pbr.metallicRoughnessTexture).toBeUndefined();
|
||||||
@ -126,70 +108,70 @@ describe('createGltf', function() {
|
|||||||
expect(material.doubleSided).toBe(false);
|
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;
|
options.specularGlossiness = true;
|
||||||
var gltf = createGltf(noMaterialsObjData, options);
|
const gltf = createGltf(noMaterialsObjData, options);
|
||||||
expect(gltf.extensionsUsed).toEqual(['KHR_materials_pbrSpecularGlossiness']);
|
expect(gltf.extensionsUsed).toEqual(['KHR_materials_pbrSpecularGlossiness']);
|
||||||
expect(gltf.extensionsRequired).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;
|
options.unlit = true;
|
||||||
var gltf = createGltf(noMaterialsObjData, options);
|
const gltf = createGltf(noMaterialsObjData, options);
|
||||||
expect(gltf.extensionsUsed).toEqual(['KHR_materials_unlit']);
|
expect(gltf.extensionsUsed).toEqual(['KHR_materials_unlit']);
|
||||||
expect(gltf.extensionsRequired).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;
|
boxObjData.nodes[0].meshes[0].primitives[0].normals.length = 0;
|
||||||
|
|
||||||
var gltf = createGltf(boxObjData, options);
|
const gltf = createGltf(boxObjData, options);
|
||||||
var attributes = gltf.meshes[0].primitives[0].attributes;
|
const attributes = gltf.meshes[0].primitives[0].attributes;
|
||||||
expect(attributes.POSITION).toBeDefined();
|
expect(attributes.POSITION).toBeDefined();
|
||||||
expect(attributes.NORMAL).toBeUndefined();
|
expect(attributes.NORMAL).toBeUndefined();
|
||||||
expect(attributes.TEXCOORD_0).toBeDefined();
|
expect(attributes.TEXCOORD_0).toBeDefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('runs without uvs', function() {
|
it('runs without uvs', () => {
|
||||||
boxObjData.nodes[0].meshes[0].primitives[0].uvs.length = 0;
|
boxObjData.nodes[0].meshes[0].primitives[0].uvs.length = 0;
|
||||||
|
|
||||||
var gltf = createGltf(boxObjData, options);
|
const gltf = createGltf(boxObjData, options);
|
||||||
var attributes = gltf.meshes[0].primitives[0].attributes;
|
const attributes = gltf.meshes[0].primitives[0].attributes;
|
||||||
expect(attributes.POSITION).toBeDefined();
|
expect(attributes.POSITION).toBeDefined();
|
||||||
expect(attributes.NORMAL).toBeDefined();
|
expect(attributes.NORMAL).toBeDefined();
|
||||||
expect(attributes.TEXCOORD_0).toBeUndefined();
|
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].normals.length = 0;
|
||||||
boxObjData.nodes[0].meshes[0].primitives[0].uvs.length = 0;
|
boxObjData.nodes[0].meshes[0].primitives[0].uvs.length = 0;
|
||||||
|
|
||||||
var gltf = createGltf(boxObjData, options);
|
const gltf = createGltf(boxObjData, options);
|
||||||
var attributes = gltf.meshes[0].primitives[0].attributes;
|
const attributes = gltf.meshes[0].primitives[0].attributes;
|
||||||
expect(attributes.POSITION).toBeDefined();
|
expect(attributes.POSITION).toBeDefined();
|
||||||
expect(attributes.NORMAL).toBeUndefined();
|
expect(attributes.NORMAL).toBeUndefined();
|
||||||
expect(attributes.TEXCOORD_0).toBeUndefined();
|
expect(attributes.TEXCOORD_0).toBeUndefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('splits incompatible materials', function() {
|
it('splits incompatible materials', () => {
|
||||||
var gltf = createGltf(mixedAttributesObjData, options);
|
const gltf = createGltf(mixedAttributesObjData, options);
|
||||||
var materials = gltf.materials;
|
const materials = gltf.materials;
|
||||||
var meshes = gltf.meshes;
|
const meshes = gltf.meshes;
|
||||||
|
|
||||||
var referenceMaterial = mixedAttributesObjData.materials[0];
|
const referenceMaterial = mixedAttributesObjData.materials[0];
|
||||||
delete referenceMaterial.name;
|
delete referenceMaterial.name;
|
||||||
referenceMaterial.pbrMetallicRoughness.baseColorTexture = {
|
referenceMaterial.pbrMetallicRoughness.baseColorTexture = {
|
||||||
index : 0
|
index : 0
|
||||||
};
|
};
|
||||||
|
|
||||||
var referenceMaterialNoTextures = clone(referenceMaterial, true);
|
const referenceMaterialNoTextures = clone(referenceMaterial, true);
|
||||||
referenceMaterialNoTextures.pbrMetallicRoughness.baseColorTexture = undefined;
|
referenceMaterialNoTextures.pbrMetallicRoughness.baseColorTexture = undefined;
|
||||||
|
|
||||||
var defaultMaterial = getDefaultMaterial(options);
|
const defaultMaterial = getDefaultMaterial(options);
|
||||||
delete defaultMaterial.name;
|
delete defaultMaterial.name;
|
||||||
|
|
||||||
var materialNames = materials.map(function(material) {
|
const materialNames = materials.map((material) => {
|
||||||
var name = material.name;
|
const name = material.name;
|
||||||
delete material.name;
|
delete material.name;
|
||||||
return name;
|
return name;
|
||||||
});
|
});
|
||||||
@ -222,14 +204,14 @@ describe('createGltf', function() {
|
|||||||
expect(materials[8]).toEqual(defaultMaterial);
|
expect(materials[8]).toEqual(defaultMaterial);
|
||||||
|
|
||||||
// Test that primitives without uvs reference materials without textures
|
// Test that primitives without uvs reference materials without textures
|
||||||
var meshesLength = meshes.length;
|
const meshesLength = meshes.length;
|
||||||
for (var i = 0; i < meshesLength; ++i) {
|
for (let i = 0; i < meshesLength; ++i) {
|
||||||
var mesh = meshes[i];
|
const mesh = meshes[i];
|
||||||
var primitives = mesh.primitives;
|
const primitives = mesh.primitives;
|
||||||
var primitivesLength = primitives.length;
|
const primitivesLength = primitives.length;
|
||||||
for (var j = 0; j < primitivesLength; ++j) {
|
for (let j = 0; j < primitivesLength; ++j) {
|
||||||
var primitive = primitives[j];
|
const primitive = primitives[j];
|
||||||
var material = materials[primitive.material];
|
const material = materials[primitive.material];
|
||||||
if (!defined(primitive.attributes.TEXCOORD_0)) {
|
if (!defined(primitive.attributes.TEXCOORD_0)) {
|
||||||
expect(material.pbrMetallicRoughness.baseColorTexture).toBeUndefined();
|
expect(material.pbrMetallicRoughness.baseColorTexture).toBeUndefined();
|
||||||
}
|
}
|
||||||
@ -238,17 +220,17 @@ describe('createGltf', function() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
function expandObjData(objData, duplicatesLength) {
|
function expandObjData(objData, duplicatesLength) {
|
||||||
var primitive = objData.nodes[0].meshes[0].primitives[0];
|
const primitive = objData.nodes[0].meshes[0].primitives[0];
|
||||||
var indices = primitive.indices;
|
const indices = primitive.indices;
|
||||||
var positions = primitive.positions;
|
const positions = primitive.positions;
|
||||||
var normals = primitive.normals;
|
const normals = primitive.normals;
|
||||||
var uvs = primitive.uvs;
|
const uvs = primitive.uvs;
|
||||||
|
|
||||||
var indicesLength = indices.length;
|
const indicesLength = indices.length;
|
||||||
var vertexCount = positions.length / 3;
|
const vertexCount = positions.length / 3;
|
||||||
|
|
||||||
for (var i = 1; i < duplicatesLength; ++i) {
|
for (let i = 1; i < duplicatesLength; ++i) {
|
||||||
for (var j = 0; j < vertexCount; ++j) {
|
for (let j = 0; j < vertexCount; ++j) {
|
||||||
positions.push(0.0);
|
positions.push(0.0);
|
||||||
positions.push(0.0);
|
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);
|
||||||
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);
|
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
|
expandObjData(boxObjData, 2731); // Right above 65536 limit
|
||||||
var primitive = boxObjData.nodes[0].meshes[0].primitives[0];
|
let primitive = boxObjData.nodes[0].meshes[0].primitives[0];
|
||||||
var indicesLength = primitive.indices.length;
|
const indicesLength = primitive.indices.length;
|
||||||
var vertexCount = primitive.positions.length / 3;
|
const vertexCount = primitive.positions.length / 3;
|
||||||
|
|
||||||
var gltf = createGltf(boxObjData, options);
|
const gltf = createGltf(boxObjData, options);
|
||||||
primitive = gltf.meshes[0].primitives[0];
|
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.count).toBe(indicesLength);
|
||||||
expect(indicesAccessor.max[0]).toBe(vertexCount - 1);
|
expect(indicesAccessor.max[0]).toBe(vertexCount - 1);
|
||||||
expect(indicesAccessor.componentType).toBe(WebGLConstants.UNSIGNED_INT);
|
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);
|
expect(positionAccessor.count).toBe(vertexCount);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,102 +1,74 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
var Cesium = require('cesium');
|
const Cesium = require('cesium');
|
||||||
var Promise = require('bluebird');
|
const fsExtra = require('fs-extra');
|
||||||
var fsExtra = require('fs-extra');
|
const loadMtl = require('../../lib/loadMtl');
|
||||||
var loadMtl = require('../../lib/loadMtl');
|
const loadTexture = require('../../lib/loadTexture');
|
||||||
var loadTexture = require('../../lib/loadTexture');
|
const obj2gltf = require('../../lib/obj2gltf');
|
||||||
var obj2gltf = require('../../lib/obj2gltf');
|
|
||||||
|
|
||||||
var clone = Cesium.clone;
|
const clone = Cesium.clone;
|
||||||
|
|
||||||
var coloredMaterialPath = 'specs/data/box/box.mtl';
|
const coloredMaterialPath = 'specs/data/box/box.mtl';
|
||||||
var texturedMaterialPath = 'specs/data/box-complex-material/box-complex-material.mtl';
|
const texturedMaterialPath = 'specs/data/box-complex-material/box-complex-material.mtl';
|
||||||
var texturedWithOptionsMaterialPath = 'specs/data/box-texture-options/box-texture-options.mtl';
|
const texturedWithOptionsMaterialPath = 'specs/data/box-texture-options/box-texture-options.mtl';
|
||||||
var multipleMaterialsPath = 'specs/data/box-multiple-materials/box-multiple-materials.mtl';
|
const multipleMaterialsPath = 'specs/data/box-multiple-materials/box-multiple-materials.mtl';
|
||||||
var externalMaterialPath = 'specs/data/box-external-resources/box-external-resources.mtl';
|
const externalMaterialPath = 'specs/data/box-external-resources/box-external-resources.mtl';
|
||||||
var resourcesInRootMaterialPath = 'specs/data/box-resources-in-root/box-resources-in-root.mtl';
|
const 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';
|
const externalInRootMaterialPath = 'specs/data/box-external-resources-in-root/box-external-resources-in-root.mtl';
|
||||||
var transparentMaterialPath = 'specs/data/box-transparent/box-transparent.mtl';
|
const transparentMaterialPath = 'specs/data/box-transparent/box-transparent.mtl';
|
||||||
var diffuseAmbientSameMaterialPath = 'specs/data/box-diffuse-ambient-same/box-diffuse-ambient-same.mtl';
|
const diffuseAmbientSameMaterialPath = 'specs/data/box-diffuse-ambient-same/box-diffuse-ambient-same.mtl';
|
||||||
|
|
||||||
var diffuseTexturePath = 'specs/data/box-textured/cesium.png';
|
const diffuseTexturePath = 'specs/data/box-textured/cesium.png';
|
||||||
var transparentDiffuseTexturePath = 'specs/data/box-complex-material/diffuse.png';
|
const transparentDiffuseTexturePath = 'specs/data/box-complex-material/diffuse.png';
|
||||||
var alphaTexturePath = 'specs/data/box-complex-material-alpha/alpha.png';
|
const alphaTexturePath = 'specs/data/box-complex-material-alpha/alpha.png';
|
||||||
var ambientTexturePath = 'specs/data/box-complex-material/ambient.gif';
|
const ambientTexturePath = 'specs/data/box-complex-material/ambient.gif';
|
||||||
var normalTexturePath = 'specs/data/box-complex-material/bump.png';
|
const normalTexturePath = 'specs/data/box-complex-material/bump.png';
|
||||||
var emissiveTexturePath = 'specs/data/box-complex-material/emission.jpg';
|
const emissiveTexturePath = 'specs/data/box-complex-material/emission.jpg';
|
||||||
var specularTexturePath = 'specs/data/box-complex-material/specular.jpeg';
|
const specularTexturePath = 'specs/data/box-complex-material/specular.jpeg';
|
||||||
var specularShininessTexturePath = 'specs/data/box-complex-material/shininess.png';
|
const specularShininessTexturePath = 'specs/data/box-complex-material/shininess.png';
|
||||||
|
|
||||||
var diffuseTexture;
|
let diffuseTexture;
|
||||||
var transparentDiffuseTexture;
|
let transparentDiffuseTexture;
|
||||||
var alphaTexture;
|
let alphaTexture;
|
||||||
var ambientTexture;
|
let ambientTexture;
|
||||||
var normalTexture;
|
let normalTexture;
|
||||||
var emissiveTexture;
|
let emissiveTexture;
|
||||||
var specularTexture;
|
let specularTexture;
|
||||||
var specularShininessTexture;
|
let specularShininessTexture;
|
||||||
|
|
||||||
var checkTransparencyOptions = {
|
const checkTransparencyOptions = {
|
||||||
checkTransparency : true
|
checkTransparency : true
|
||||||
};
|
};
|
||||||
var decodeOptions = {
|
const decodeOptions = {
|
||||||
decode : true
|
decode : true
|
||||||
};
|
};
|
||||||
|
|
||||||
var options;
|
let options;
|
||||||
|
|
||||||
describe('loadMtl', function() {
|
describe('loadMtl', () => {
|
||||||
beforeAll(function(done) {
|
beforeAll(async () => {
|
||||||
return Promise.all([
|
diffuseTexture = await loadTexture(diffuseTexturePath, decodeOptions);
|
||||||
loadTexture(diffuseTexturePath, decodeOptions)
|
transparentDiffuseTexture = await loadTexture(transparentDiffuseTexturePath, checkTransparencyOptions);
|
||||||
.then(function(texture) {
|
alphaTexture = await loadTexture(alphaTexturePath, decodeOptions);
|
||||||
diffuseTexture = texture;
|
ambientTexture = await loadTexture(ambientTexturePath);
|
||||||
}),
|
normalTexture = await loadTexture(normalTexturePath);
|
||||||
loadTexture(transparentDiffuseTexturePath, checkTransparencyOptions)
|
emissiveTexture = await loadTexture(emissiveTexturePath);
|
||||||
.then(function(texture) {
|
specularTexture = await loadTexture(specularTexturePath, decodeOptions);
|
||||||
transparentDiffuseTexture = texture;
|
specularShininessTexture = await loadTexture(specularShininessTexturePath, decodeOptions);
|
||||||
}),
|
|
||||||
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);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
beforeEach(function() {
|
beforeEach(() => {
|
||||||
options = clone(obj2gltf.defaults);
|
options = clone(obj2gltf.defaults);
|
||||||
options.overridingTextures = {};
|
options.overridingTextures = {};
|
||||||
options.logger = function() {};
|
options.logger = () => {};
|
||||||
options.hasNormals = true;
|
options.hasNormals = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
it('loads mtl', function(done) {
|
it('loads mtl', async () => {
|
||||||
options.metallicRoughness = true;
|
options.metallicRoughness = true;
|
||||||
expect(loadMtl(coloredMaterialPath, options)
|
const materials = await loadMtl(coloredMaterialPath, options);
|
||||||
.then(function(materials) {
|
|
||||||
expect(materials.length).toBe(1);
|
expect(materials.length).toBe(1);
|
||||||
var material = materials[0];
|
const material = materials[0];
|
||||||
var pbr = material.pbrMetallicRoughness;
|
const pbr = material.pbrMetallicRoughness;
|
||||||
expect(pbr.baseColorTexture).toBeUndefined();
|
expect(pbr.baseColorTexture).toBeUndefined();
|
||||||
expect(pbr.metallicRoughnessTexture).toBeUndefined();
|
expect(pbr.metallicRoughnessTexture).toBeUndefined();
|
||||||
expect(pbr.baseColorFactor).toEqual([0.64, 0.64, 0.64, 1.0]);
|
expect(pbr.baseColorFactor).toEqual([0.64, 0.64, 0.64, 1.0]);
|
||||||
@ -109,16 +81,14 @@ describe('loadMtl', function() {
|
|||||||
expect(material.emissiveFactor).toEqual([0.0, 0.0, 0.1]);
|
expect(material.emissiveFactor).toEqual([0.0, 0.0, 0.1]);
|
||||||
expect(material.alphaMode).toBe('OPAQUE');
|
expect(material.alphaMode).toBe('OPAQUE');
|
||||||
expect(material.doubleSided).toBe(false);
|
expect(material.doubleSided).toBe(false);
|
||||||
}), done).toResolve();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('loads mtl with textures', function(done) {
|
it('loads mtl with textures', async () => {
|
||||||
options.metallicRoughness = true;
|
options.metallicRoughness = true;
|
||||||
expect(loadMtl(texturedMaterialPath, options)
|
const materials = await loadMtl(texturedMaterialPath, options);
|
||||||
.then(function(materials) {
|
|
||||||
expect(materials.length).toBe(1);
|
expect(materials.length).toBe(1);
|
||||||
var material = materials[0];
|
const material = materials[0];
|
||||||
var pbr = material.pbrMetallicRoughness;
|
const pbr = material.pbrMetallicRoughness;
|
||||||
expect(pbr.baseColorTexture).toBeDefined();
|
expect(pbr.baseColorTexture).toBeDefined();
|
||||||
expect(pbr.metallicRoughnessTexture).toBeDefined();
|
expect(pbr.metallicRoughnessTexture).toBeDefined();
|
||||||
expect(pbr.baseColorFactor).toEqual([1.0, 1.0, 1.0, 0.9]);
|
expect(pbr.baseColorFactor).toEqual([1.0, 1.0, 1.0, 0.9]);
|
||||||
@ -131,16 +101,14 @@ describe('loadMtl', function() {
|
|||||||
expect(material.emissiveFactor).toEqual([1.0, 1.0, 1.0]);
|
expect(material.emissiveFactor).toEqual([1.0, 1.0, 1.0]);
|
||||||
expect(material.alphaMode).toBe('BLEND');
|
expect(material.alphaMode).toBe('BLEND');
|
||||||
expect(material.doubleSided).toBe(true);
|
expect(material.doubleSided).toBe(true);
|
||||||
}), done).toResolve();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('loads mtl with textures having options', function(done) {
|
it('loads mtl with textures having options', async () => {
|
||||||
options.metallicRoughness = true;
|
options.metallicRoughness = true;
|
||||||
expect(loadMtl(texturedWithOptionsMaterialPath, options)
|
const materials = await loadMtl(texturedWithOptionsMaterialPath, options);
|
||||||
.then(function(materials) {
|
|
||||||
expect(materials.length).toBe(1);
|
expect(materials.length).toBe(1);
|
||||||
var material = materials[0];
|
const material = materials[0];
|
||||||
var pbr = material.pbrMetallicRoughness;
|
const pbr = material.pbrMetallicRoughness;
|
||||||
expect(pbr.baseColorTexture).toBeDefined();
|
expect(pbr.baseColorTexture).toBeDefined();
|
||||||
expect(pbr.metallicRoughnessTexture).toBeDefined();
|
expect(pbr.metallicRoughnessTexture).toBeDefined();
|
||||||
expect(pbr.baseColorFactor).toEqual([1.0, 1.0, 1.0, 0.9]);
|
expect(pbr.baseColorFactor).toEqual([1.0, 1.0, 1.0, 0.9]);
|
||||||
@ -153,13 +121,11 @@ describe('loadMtl', function() {
|
|||||||
expect(material.emissiveFactor).toEqual([1.0, 1.0, 1.0]);
|
expect(material.emissiveFactor).toEqual([1.0, 1.0, 1.0]);
|
||||||
expect(material.alphaMode).toBe('BLEND');
|
expect(material.alphaMode).toBe('BLEND');
|
||||||
expect(material.doubleSided).toBe(true);
|
expect(material.doubleSided).toBe(true);
|
||||||
}), done).toResolve();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('loads mtl with multiple materials', function(done) {
|
it('loads mtl with multiple materials', async () => {
|
||||||
options.metallicRoughness = true;
|
options.metallicRoughness = true;
|
||||||
expect(loadMtl(multipleMaterialsPath, options)
|
const materials = await loadMtl(multipleMaterialsPath, options);
|
||||||
.then(function(materials) {
|
|
||||||
expect(materials.length).toBe(3);
|
expect(materials.length).toBe(3);
|
||||||
expect(materials[0].name).toBe('Blue');
|
expect(materials[0].name).toBe('Blue');
|
||||||
expect(materials[0].pbrMetallicRoughness.baseColorFactor).toEqual([0.0, 0.0, 0.64, 1.0]);
|
expect(materials[0].pbrMetallicRoughness.baseColorFactor).toEqual([0.0, 0.0, 0.64, 1.0]);
|
||||||
@ -167,105 +133,90 @@ describe('loadMtl', function() {
|
|||||||
expect(materials[1].pbrMetallicRoughness.baseColorFactor).toEqual([0.0, 0.64, 0.0, 1.0]);
|
expect(materials[1].pbrMetallicRoughness.baseColorFactor).toEqual([0.0, 0.64, 0.0, 1.0]);
|
||||||
expect(materials[2].name).toBe('Red');
|
expect(materials[2].name).toBe('Red');
|
||||||
expect(materials[2].pbrMetallicRoughness.baseColorFactor).toEqual([0.64, 0.0, 0.0, 1.0]);
|
expect(materials[2].pbrMetallicRoughness.baseColorFactor).toEqual([0.64, 0.0, 0.0, 1.0]);
|
||||||
}), done).toResolve();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('sets overriding textures', function(done) {
|
it('sets overriding textures', async () => {
|
||||||
spyOn(fsExtra, 'readFile').and.callThrough();
|
spyOn(fsExtra, 'readFile').and.callThrough();
|
||||||
options.overridingTextures = {
|
options.overridingTextures = {
|
||||||
metallicRoughnessOcclusionTexture : alphaTexturePath,
|
metallicRoughnessOcclusionTexture : alphaTexturePath,
|
||||||
baseColorTexture : alphaTexturePath,
|
baseColorTexture : alphaTexturePath,
|
||||||
emissiveTexture : emissiveTexturePath
|
emissiveTexture : emissiveTexturePath
|
||||||
};
|
};
|
||||||
expect(loadMtl(texturedMaterialPath, options)
|
const materials = await loadMtl(texturedMaterialPath, options);
|
||||||
.then(function(materials) {
|
const material = materials[0];
|
||||||
var material = materials[0];
|
const pbr = material.pbrMetallicRoughness;
|
||||||
var pbr = material.pbrMetallicRoughness;
|
|
||||||
expect(pbr.baseColorTexture.name).toBe('alpha');
|
expect(pbr.baseColorTexture.name).toBe('alpha');
|
||||||
expect(pbr.metallicRoughnessTexture.name).toBe('alpha');
|
expect(pbr.metallicRoughnessTexture.name).toBe('alpha');
|
||||||
expect(material.emissiveTexture.name).toBe('emission');
|
expect(material.emissiveTexture.name).toBe('emission');
|
||||||
expect(material.normalTexture.name).toBe('bump');
|
expect(material.normalTexture.name).toBe('bump');
|
||||||
expect(fsExtra.readFile.calls.count()).toBe(3);
|
expect(fsExtra.readFile.calls.count()).toBe(3);
|
||||||
}), done).toResolve();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('loads texture outside of the mtl directory', function(done) {
|
it('loads texture outside of the mtl directory', async () => {
|
||||||
expect(loadMtl(externalMaterialPath, options)
|
const materials = await loadMtl(externalMaterialPath, options);
|
||||||
.then(function(materials) {
|
const material = materials[0];
|
||||||
var material = materials[0];
|
const baseColorTexture = material.pbrMetallicRoughness.baseColorTexture;
|
||||||
var baseColorTexture = material.pbrMetallicRoughness.baseColorTexture;
|
|
||||||
expect(baseColorTexture.source).toBeDefined();
|
expect(baseColorTexture.source).toBeDefined();
|
||||||
expect(baseColorTexture.name).toBe('cesium');
|
expect(baseColorTexture.name).toBe('cesium');
|
||||||
}), done).toResolve();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('does not load texture outside of the mtl directory when secure is true', function(done) {
|
it('does not load texture outside of the mtl directory when secure is true', async () => {
|
||||||
var spy = jasmine.createSpy('logger');
|
const spy = jasmine.createSpy('logger');
|
||||||
options.logger = spy;
|
options.logger = spy;
|
||||||
options.secure = true;
|
options.secure = true;
|
||||||
|
|
||||||
expect(loadMtl(externalMaterialPath, options)
|
const materials = await loadMtl(externalMaterialPath, options);
|
||||||
.then(function(materials) {
|
const material = materials[0];
|
||||||
var material = materials[0];
|
const baseColorTexture = material.pbrMetallicRoughness.baseColorTexture;
|
||||||
var baseColorTexture = material.pbrMetallicRoughness.baseColorTexture;
|
|
||||||
expect(baseColorTexture).toBeUndefined();
|
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(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(1)[0].indexOf('ENOENT') >= 0).toBe(true);
|
||||||
expect(spy.calls.argsFor(2)[0].indexOf('Could not read texture file') >= 0).toBe(true);
|
expect(spy.calls.argsFor(2)[0].indexOf('Could not read texture file') >= 0).toBe(true);
|
||||||
}), done).toResolve();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('loads textures from root directory when the texture paths do not exist', function(done) {
|
it('loads textures from root directory when the texture paths do not exist', async () => {
|
||||||
expect(loadMtl(resourcesInRootMaterialPath, options)
|
const materials = await loadMtl(resourcesInRootMaterialPath, options);
|
||||||
.then(function(materials) {
|
const material = materials[0];
|
||||||
var material = materials[0];
|
const baseColorTexture = material.pbrMetallicRoughness.baseColorTexture;
|
||||||
var baseColorTexture = material.pbrMetallicRoughness.baseColorTexture;
|
|
||||||
expect(baseColorTexture.source).toBeDefined();
|
expect(baseColorTexture.source).toBeDefined();
|
||||||
expect(baseColorTexture.name).toBe('cesium');
|
expect(baseColorTexture.name).toBe('cesium');
|
||||||
}), done).toResolve();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
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;
|
options.secure = true;
|
||||||
|
|
||||||
expect(loadMtl(externalInRootMaterialPath, options)
|
const materials = await loadMtl(externalInRootMaterialPath, options);
|
||||||
.then(function(materials) {
|
const material = materials[0];
|
||||||
var material = materials[0];
|
const baseColorTexture = material.pbrMetallicRoughness.baseColorTexture;
|
||||||
var baseColorTexture = material.pbrMetallicRoughness.baseColorTexture;
|
|
||||||
expect(baseColorTexture.source).toBeDefined();
|
expect(baseColorTexture.source).toBeDefined();
|
||||||
expect(baseColorTexture.name).toBe('cesium');
|
expect(baseColorTexture.name).toBe('cesium');
|
||||||
}), done).toResolve();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('alpha of 0.0 is treated as 1.0', function(done) {
|
it('alpha of 0.0 is treated as 1.0', async () => {
|
||||||
expect(loadMtl(transparentMaterialPath, options)
|
const materials = await loadMtl(transparentMaterialPath, options);
|
||||||
.then(function(materials) {
|
|
||||||
expect(materials.length).toBe(1);
|
expect(materials.length).toBe(1);
|
||||||
var material = materials[0];
|
const material = materials[0];
|
||||||
var pbr = material.pbrMetallicRoughness;
|
const pbr = material.pbrMetallicRoughness;
|
||||||
expect(pbr.baseColorTexture).toBeUndefined();
|
expect(pbr.baseColorTexture).toBeUndefined();
|
||||||
expect(pbr.metallicRoughnessTexture).toBeUndefined();
|
expect(pbr.metallicRoughnessTexture).toBeUndefined();
|
||||||
expect(pbr.baseColorFactor[3]).toEqual(1.0);
|
expect(pbr.baseColorFactor[3]).toEqual(1.0);
|
||||||
expect(material.alphaMode).toBe('OPAQUE');
|
expect(material.alphaMode).toBe('OPAQUE');
|
||||||
expect(material.doubleSided).toBe(false);
|
expect(material.doubleSided).toBe(false);
|
||||||
}), done).toResolve();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('ambient texture is ignored if it is the same as the diffuse texture', function(done) {
|
it('ambient texture is ignored if it is the same as the diffuse texture', async () => {
|
||||||
expect(loadMtl(diffuseAmbientSameMaterialPath, options)
|
const materials = await loadMtl(diffuseAmbientSameMaterialPath, options);
|
||||||
.then(function(materials) {
|
|
||||||
expect(materials.length).toBe(1);
|
expect(materials.length).toBe(1);
|
||||||
var material = materials[0];
|
const material = materials[0];
|
||||||
var pbr = material.pbrMetallicRoughness;
|
const pbr = material.pbrMetallicRoughness;
|
||||||
expect(pbr.baseColorTexture).toBeDefined();
|
expect(pbr.baseColorTexture).toBeDefined();
|
||||||
expect(pbr.occlusionTexture).toBeUndefined();
|
expect(pbr.occlusionTexture).toBeUndefined();
|
||||||
}), done).toResolve();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('metallicRoughness', function() {
|
describe('metallicRoughness', () => {
|
||||||
it('creates default material', function() {
|
it('creates default material', () => {
|
||||||
var material = loadMtl._createMaterial(undefined, options);
|
const material = loadMtl._createMaterial(undefined, options);
|
||||||
var pbr = material.pbrMetallicRoughness;
|
const pbr = material.pbrMetallicRoughness;
|
||||||
expect(pbr.baseColorTexture).toBeUndefined();
|
expect(pbr.baseColorTexture).toBeUndefined();
|
||||||
expect(pbr.metallicRoughnessTexture).toBeUndefined();
|
expect(pbr.metallicRoughnessTexture).toBeUndefined();
|
||||||
expect(pbr.baseColorFactor).toEqual([0.5, 0.5, 0.5, 1.0]);
|
expect(pbr.baseColorFactor).toEqual([0.5, 0.5, 0.5, 1.0]);
|
||||||
@ -279,10 +230,10 @@ describe('loadMtl', function() {
|
|||||||
expect(material.doubleSided).toBe(false);
|
expect(material.doubleSided).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('creates material with textures', function() {
|
it('creates material with textures', () => {
|
||||||
options.metallicRoughness = true;
|
options.metallicRoughness = true;
|
||||||
|
|
||||||
var material = loadMtl._createMaterial({
|
const material = loadMtl._createMaterial({
|
||||||
diffuseTexture : diffuseTexture,
|
diffuseTexture : diffuseTexture,
|
||||||
ambientTexture : ambientTexture,
|
ambientTexture : ambientTexture,
|
||||||
normalTexture : normalTexture,
|
normalTexture : normalTexture,
|
||||||
@ -291,7 +242,7 @@ describe('loadMtl', function() {
|
|||||||
specularShininessTexture : specularShininessTexture
|
specularShininessTexture : specularShininessTexture
|
||||||
}, options);
|
}, options);
|
||||||
|
|
||||||
var pbr = material.pbrMetallicRoughness;
|
const pbr = material.pbrMetallicRoughness;
|
||||||
expect(pbr.baseColorTexture).toBeDefined();
|
expect(pbr.baseColorTexture).toBeDefined();
|
||||||
expect(pbr.metallicRoughnessTexture).toBeDefined();
|
expect(pbr.metallicRoughnessTexture).toBeDefined();
|
||||||
expect(pbr.baseColorFactor).toEqual([1.0, 1.0, 1.0, 1.0]);
|
expect(pbr.baseColorFactor).toEqual([1.0, 1.0, 1.0, 1.0]);
|
||||||
@ -305,63 +256,63 @@ describe('loadMtl', function() {
|
|||||||
expect(material.doubleSided).toBe(false);
|
expect(material.doubleSided).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('packs occlusion in metallic roughness texture', function() {
|
it('packs occlusion in metallic roughness texture', () => {
|
||||||
options.metallicRoughness = true;
|
options.metallicRoughness = true;
|
||||||
options.packOcclusion = true;
|
options.packOcclusion = true;
|
||||||
|
|
||||||
var material = loadMtl._createMaterial({
|
const material = loadMtl._createMaterial({
|
||||||
ambientTexture : alphaTexture,
|
ambientTexture : alphaTexture,
|
||||||
specularTexture : specularTexture,
|
specularTexture : specularTexture,
|
||||||
specularShininessTexture : specularShininessTexture
|
specularShininessTexture : specularShininessTexture
|
||||||
}, options);
|
}, options);
|
||||||
|
|
||||||
var pbr = material.pbrMetallicRoughness;
|
const pbr = material.pbrMetallicRoughness;
|
||||||
expect(pbr.metallicRoughnessTexture).toBeDefined();
|
expect(pbr.metallicRoughnessTexture).toBeDefined();
|
||||||
expect(pbr.metallicRoughnessTexture).toBe(material.occlusionTexture);
|
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.metallicRoughness = true;
|
||||||
options.packOcclusion = true;
|
options.packOcclusion = true;
|
||||||
|
|
||||||
var material = loadMtl._createMaterial({
|
const material = loadMtl._createMaterial({
|
||||||
ambientTexture : ambientTexture, // Is a .gif which can't be decoded
|
ambientTexture : ambientTexture, // Is a .gif which can't be decoded
|
||||||
specularTexture : specularTexture,
|
specularTexture : specularTexture,
|
||||||
specularShininessTexture : specularShininessTexture
|
specularShininessTexture : specularShininessTexture
|
||||||
}, options);
|
}, options);
|
||||||
|
|
||||||
var pbr = material.pbrMetallicRoughness;
|
const pbr = material.pbrMetallicRoughness;
|
||||||
expect(pbr.metallicRoughnessTexture).toBeUndefined();
|
expect(pbr.metallicRoughnessTexture).toBeUndefined();
|
||||||
expect(material.occlusionTexture).toBeUndefined();
|
expect(material.occlusionTexture).toBeUndefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('sets material for transparent diffuse texture', function() {
|
it('sets material for transparent diffuse texture', () => {
|
||||||
options.metallicRoughness = true;
|
options.metallicRoughness = true;
|
||||||
|
|
||||||
var material = loadMtl._createMaterial({
|
const material = loadMtl._createMaterial({
|
||||||
diffuseTexture : transparentDiffuseTexture
|
diffuseTexture : transparentDiffuseTexture
|
||||||
}, options);
|
}, options);
|
||||||
expect(material.alphaMode).toBe('BLEND');
|
expect(material.alphaMode).toBe('BLEND');
|
||||||
expect(material.doubleSided).toBe(true);
|
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;
|
options.metallicRoughness = true;
|
||||||
|
|
||||||
var material = loadMtl._createMaterial({
|
const material = loadMtl._createMaterial({
|
||||||
diffuseTexture : diffuseTexture,
|
diffuseTexture : diffuseTexture,
|
||||||
alphaTexture : alphaTexture
|
alphaTexture : alphaTexture
|
||||||
}, options);
|
}, options);
|
||||||
|
|
||||||
var pbr = material.pbrMetallicRoughness;
|
const pbr = material.pbrMetallicRoughness;
|
||||||
expect(pbr.baseColorTexture).toBeDefined();
|
expect(pbr.baseColorTexture).toBeDefined();
|
||||||
|
|
||||||
var hasBlack = false;
|
let hasBlack = false;
|
||||||
var hasWhite = false;
|
let hasWhite = false;
|
||||||
var pixels = pbr.baseColorTexture.pixels;
|
const pixels = pbr.baseColorTexture.pixels;
|
||||||
var pixelsLength = pixels.length / 4;
|
const pixelsLength = pixels.length / 4;
|
||||||
for (var i = 0; i < pixelsLength; ++i) {
|
for (let i = 0; i < pixelsLength; ++i) {
|
||||||
var alpha = pixels[i * 4 + 3];
|
const alpha = pixels[i * 4 + 3];
|
||||||
hasBlack = hasBlack || (alpha === 0);
|
hasBlack = hasBlack || (alpha === 0);
|
||||||
hasWhite = hasWhite || (alpha === 255);
|
hasWhite = hasWhite || (alpha === 255);
|
||||||
}
|
}
|
||||||
@ -373,11 +324,11 @@ describe('loadMtl', function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('specularGlossiness', function() {
|
describe('specularGlossiness', () => {
|
||||||
it('creates default material', function() {
|
it('creates default material', () => {
|
||||||
options.specularGlossiness = true;
|
options.specularGlossiness = true;
|
||||||
var material = loadMtl._createMaterial(undefined, options);
|
const material = loadMtl._createMaterial(undefined, options);
|
||||||
var pbr = material.extensions.KHR_materials_pbrSpecularGlossiness;
|
const pbr = material.extensions.KHR_materials_pbrSpecularGlossiness;
|
||||||
expect(pbr.diffuseTexture).toBeUndefined();
|
expect(pbr.diffuseTexture).toBeUndefined();
|
||||||
expect(pbr.specularGlossinessTexture).toBeUndefined();
|
expect(pbr.specularGlossinessTexture).toBeUndefined();
|
||||||
expect(pbr.diffuseFactor).toEqual([0.5, 0.5, 0.5, 1.0]);
|
expect(pbr.diffuseFactor).toEqual([0.5, 0.5, 0.5, 1.0]);
|
||||||
@ -391,10 +342,10 @@ describe('loadMtl', function() {
|
|||||||
expect(material.doubleSided).toBe(false);
|
expect(material.doubleSided).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('creates material with textures', function() {
|
it('creates material with textures', () => {
|
||||||
options.specularGlossiness = true;
|
options.specularGlossiness = true;
|
||||||
|
|
||||||
var material = loadMtl._createMaterial({
|
const material = loadMtl._createMaterial({
|
||||||
diffuseTexture : diffuseTexture,
|
diffuseTexture : diffuseTexture,
|
||||||
ambientTexture : ambientTexture,
|
ambientTexture : ambientTexture,
|
||||||
normalTexture : normalTexture,
|
normalTexture : normalTexture,
|
||||||
@ -403,7 +354,7 @@ describe('loadMtl', function() {
|
|||||||
specularShininessTexture : specularShininessTexture
|
specularShininessTexture : specularShininessTexture
|
||||||
}, options);
|
}, options);
|
||||||
|
|
||||||
var pbr = material.extensions.KHR_materials_pbrSpecularGlossiness;
|
const pbr = material.extensions.KHR_materials_pbrSpecularGlossiness;
|
||||||
expect(pbr.diffuseTexture).toBeDefined();
|
expect(pbr.diffuseTexture).toBeDefined();
|
||||||
expect(pbr.specularGlossinessTexture).toBeDefined();
|
expect(pbr.specularGlossinessTexture).toBeDefined();
|
||||||
expect(pbr.diffuseFactor).toEqual([1.0, 1.0, 1.0, 1.0]);
|
expect(pbr.diffuseFactor).toEqual([1.0, 1.0, 1.0, 1.0]);
|
||||||
@ -417,22 +368,22 @@ describe('loadMtl', function() {
|
|||||||
expect(material.doubleSided).toBe(false);
|
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;
|
options.specularGlossiness = true;
|
||||||
|
|
||||||
var material = loadMtl._createMaterial({
|
const material = loadMtl._createMaterial({
|
||||||
specularTexture : ambientTexture, // Is a .gif which can't be decoded
|
specularTexture : ambientTexture, // Is a .gif which can't be decoded
|
||||||
specularShininessTexture : specularShininessTexture
|
specularShininessTexture : specularShininessTexture
|
||||||
}, options);
|
}, options);
|
||||||
|
|
||||||
var pbr = material.extensions.KHR_materials_pbrSpecularGlossiness;
|
const pbr = material.extensions.KHR_materials_pbrSpecularGlossiness;
|
||||||
expect(pbr.specularGlossinessTexture).toBeUndefined();
|
expect(pbr.specularGlossinessTexture).toBeUndefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('sets material for transparent diffuse texture', function() {
|
it('sets material for transparent diffuse texture', () => {
|
||||||
options.specularGlossiness = true;
|
options.specularGlossiness = true;
|
||||||
|
|
||||||
var material = loadMtl._createMaterial({
|
const material = loadMtl._createMaterial({
|
||||||
diffuseTexture : transparentDiffuseTexture
|
diffuseTexture : transparentDiffuseTexture
|
||||||
}, options);
|
}, options);
|
||||||
|
|
||||||
@ -440,23 +391,23 @@ describe('loadMtl', function() {
|
|||||||
expect(material.doubleSided).toBe(true);
|
expect(material.doubleSided).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('packs alpha texture in diffuse texture', function() {
|
it('packs alpha texture in diffuse texture', () => {
|
||||||
options.specularGlossiness = true;
|
options.specularGlossiness = true;
|
||||||
|
|
||||||
var material = loadMtl._createMaterial({
|
const material = loadMtl._createMaterial({
|
||||||
diffuseTexture : diffuseTexture,
|
diffuseTexture : diffuseTexture,
|
||||||
alphaTexture : alphaTexture
|
alphaTexture : alphaTexture
|
||||||
}, options);
|
}, options);
|
||||||
|
|
||||||
var pbr = material.extensions.KHR_materials_pbrSpecularGlossiness;
|
const pbr = material.extensions.KHR_materials_pbrSpecularGlossiness;
|
||||||
expect(pbr.diffuseTexture).toBeDefined();
|
expect(pbr.diffuseTexture).toBeDefined();
|
||||||
|
|
||||||
var hasBlack = false;
|
let hasBlack = false;
|
||||||
var hasWhite = false;
|
let hasWhite = false;
|
||||||
var pixels = pbr.diffuseTexture.pixels;
|
const pixels = pbr.diffuseTexture.pixels;
|
||||||
var pixelsLength = pixels.length / 4;
|
const pixelsLength = pixels.length / 4;
|
||||||
for (var i = 0; i < pixelsLength; ++i) {
|
for (let i = 0; i < pixelsLength; ++i) {
|
||||||
var alpha = pixels[i * 4 + 3];
|
const alpha = pixels[i * 4 + 3];
|
||||||
hasBlack = hasBlack || (alpha === 0);
|
hasBlack = hasBlack || (alpha === 0);
|
||||||
hasWhite = hasWhite || (alpha === 255);
|
hasWhite = hasWhite || (alpha === 255);
|
||||||
}
|
}
|
||||||
|
@ -1,87 +1,86 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
var Cesium = require('cesium');
|
const Cesium = require('cesium');
|
||||||
var Promise = require('bluebird');
|
|
||||||
var loadObj = require('../../lib/loadObj');
|
|
||||||
var obj2gltf = require('../../lib/obj2gltf');
|
|
||||||
|
|
||||||
var Cartesian3 = Cesium.Cartesian3;
|
const loadObj = require('../../lib/loadObj');
|
||||||
var CesiumMath = Cesium.Math;
|
const obj2gltf = require('../../lib/obj2gltf');
|
||||||
var clone = Cesium.clone;
|
|
||||||
var RuntimeError = Cesium.RuntimeError;
|
|
||||||
|
|
||||||
var objPath = 'specs/data/box/box.obj';
|
const Cartesian3 = Cesium.Cartesian3;
|
||||||
var objNormalsPath = 'specs/data/box-normals/box-normals.obj';
|
const CesiumMath = Cesium.Math;
|
||||||
var objUvsPath = 'specs/data/box-uvs/box-uvs.obj';
|
const clone = Cesium.clone;
|
||||||
var objPositionsOnlyPath = 'specs/data/box-positions-only/box-positions-only.obj';
|
const RuntimeError = Cesium.RuntimeError;
|
||||||
var objNegativeIndicesPath = 'specs/data/box-negative-indices/box-negative-indices.obj';
|
|
||||||
var objTrianglesPath = 'specs/data/box-triangles/box-triangles.obj';
|
const objPath = 'specs/data/box/box.obj';
|
||||||
var objObjectsPath = 'specs/data/box-objects/box-objects.obj';
|
const objNormalsPath = 'specs/data/box-normals/box-normals.obj';
|
||||||
var objGroupsPath = 'specs/data/box-groups/box-groups.obj';
|
const objUvsPath = 'specs/data/box-uvs/box-uvs.obj';
|
||||||
var objObjectsGroupsPath = 'specs/data/box-objects-groups/box-objects-groups.obj';
|
const objPositionsOnlyPath = 'specs/data/box-positions-only/box-positions-only.obj';
|
||||||
var objObjectsGroupsMaterialsPath = 'specs/data/box-objects-groups-materials/box-objects-groups-materials.obj';
|
const objNegativeIndicesPath = 'specs/data/box-negative-indices/box-negative-indices.obj';
|
||||||
var objObjectsGroupsMaterialsPath2 = 'specs/data/box-objects-groups-materials-2/box-objects-groups-materials-2.obj';
|
const objTrianglesPath = 'specs/data/box-triangles/box-triangles.obj';
|
||||||
var objUsemtlPath = 'specs/data/box-usemtl/box-usemtl.obj';
|
const objObjectsPath = 'specs/data/box-objects/box-objects.obj';
|
||||||
var objNoMaterialsPath = 'specs/data/box-no-materials/box-no-materials.obj';
|
const objGroupsPath = 'specs/data/box-groups/box-groups.obj';
|
||||||
var objMultipleMaterialsPath = 'specs/data/box-multiple-materials/box-multiple-materials.obj';
|
const objObjectsGroupsPath = 'specs/data/box-objects-groups/box-objects-groups.obj';
|
||||||
var objUncleanedPath = 'specs/data/box-uncleaned/box-uncleaned.obj';
|
const objObjectsGroupsMaterialsPath = 'specs/data/box-objects-groups-materials/box-objects-groups-materials.obj';
|
||||||
var objMtllibPath = 'specs/data/box-mtllib/box-mtllib.obj';
|
const objObjectsGroupsMaterialsPath2 = 'specs/data/box-objects-groups-materials-2/box-objects-groups-materials-2.obj';
|
||||||
var objMtllibSpacesPath = 'specs/data/box-mtllib-spaces/box mtllib.obj';
|
const objUsemtlPath = 'specs/data/box-usemtl/box-usemtl.obj';
|
||||||
var objMissingMtllibPath = 'specs/data/box-missing-mtllib/box-missing-mtllib.obj';
|
const objNoMaterialsPath = 'specs/data/box-no-materials/box-no-materials.obj';
|
||||||
var objMissingUsemtlPath = 'specs/data/box-missing-usemtl/box-missing-usemtl.obj';
|
const objMultipleMaterialsPath = 'specs/data/box-multiple-materials/box-multiple-materials.obj';
|
||||||
var objExternalResourcesPath = 'specs/data/box-external-resources/box-external-resources.obj';
|
const objUncleanedPath = 'specs/data/box-uncleaned/box-uncleaned.obj';
|
||||||
var objResourcesInRootPath = 'specs/data/box-resources-in-root/box-resources-in-root.obj';
|
const objMtllibPath = 'specs/data/box-mtllib/box-mtllib.obj';
|
||||||
var objExternalResourcesInRootPath = 'specs/data/box-external-resources-in-root/box-external-resources-in-root.obj';
|
const objMtllibSpacesPath = 'specs/data/box-mtllib-spaces/box mtllib.obj';
|
||||||
var objTexturedPath = 'specs/data/box-textured/box-textured.obj';
|
const objMissingMtllibPath = 'specs/data/box-missing-mtllib/box-missing-mtllib.obj';
|
||||||
var objMissingTexturePath = 'specs/data/box-missing-texture/box-missing-texture.obj';
|
const objMissingUsemtlPath = 'specs/data/box-missing-usemtl/box-missing-usemtl.obj';
|
||||||
var objSubdirectoriesPath = 'specs/data/box-subdirectories/box-textured.obj';
|
const objExternalResourcesPath = 'specs/data/box-external-resources/box-external-resources.obj';
|
||||||
var objWindowsPaths = 'specs/data/box-windows-paths/box-windows-paths.obj';
|
const objResourcesInRootPath = 'specs/data/box-resources-in-root/box-resources-in-root.obj';
|
||||||
var objInvalidContentsPath = 'specs/data/box/box.mtl';
|
const objExternalResourcesInRootPath = 'specs/data/box-external-resources-in-root/box-external-resources-in-root.obj';
|
||||||
var objConcavePath = 'specs/data/concave/concave.obj';
|
const objTexturedPath = 'specs/data/box-textured/box-textured.obj';
|
||||||
var objUnnormalizedPath = 'specs/data/box-unnormalized/box-unnormalized.obj';
|
const objMissingTexturePath = 'specs/data/box-missing-texture/box-missing-texture.obj';
|
||||||
var objMixedAttributesPath = 'specs/data/box-mixed-attributes/box-mixed-attributes.obj';
|
const objSubdirectoriesPath = 'specs/data/box-subdirectories/box-textured.obj';
|
||||||
var objInvalidPath = 'invalid.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) {
|
function getMeshes(data) {
|
||||||
var meshes = [];
|
let meshes = [];
|
||||||
var nodes = data.nodes;
|
const nodes = data.nodes;
|
||||||
var nodesLength = nodes.length;
|
const nodesLength = nodes.length;
|
||||||
for (var i = 0; i < nodesLength; ++i) {
|
for (let i = 0; i < nodesLength; ++i) {
|
||||||
meshes = meshes.concat(nodes[i].meshes);
|
meshes = meshes.concat(nodes[i].meshes);
|
||||||
}
|
}
|
||||||
return meshes;
|
return meshes;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getPrimitives(data) {
|
function getPrimitives(data) {
|
||||||
var primitives = [];
|
let primitives = [];
|
||||||
var nodes = data.nodes;
|
const nodes = data.nodes;
|
||||||
var nodesLength = nodes.length;
|
const nodesLength = nodes.length;
|
||||||
for (var i = 0; i < nodesLength; ++i) {
|
for (let i = 0; i < nodesLength; ++i) {
|
||||||
var meshes = nodes[i].meshes;
|
const meshes = nodes[i].meshes;
|
||||||
var meshesLength = meshes.length;
|
const meshesLength = meshes.length;
|
||||||
for (var j = 0; j < meshesLength; ++j) {
|
for (let j = 0; j < meshesLength; ++j) {
|
||||||
primitives = primitives.concat(meshes[j].primitives);
|
primitives = primitives.concat(meshes[j].primitives);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return primitives;
|
return primitives;
|
||||||
}
|
}
|
||||||
|
|
||||||
var options;
|
let options;
|
||||||
|
|
||||||
describe('loadObj', function() {
|
describe('loadObj', () => {
|
||||||
beforeEach(function() {
|
beforeEach(() => {
|
||||||
options = clone(obj2gltf.defaults);
|
options = clone(obj2gltf.defaults);
|
||||||
options.overridingTextures = {};
|
options.overridingTextures = {};
|
||||||
options.logger = function() {};
|
options.logger = () => {};
|
||||||
});
|
});
|
||||||
|
|
||||||
it('loads obj with positions, normals, and uvs', function(done) {
|
it('loads obj with positions, normals, and uvs', async () => {
|
||||||
expect(loadObj(objPath, options)
|
const data = await loadObj(objPath, options);
|
||||||
.then(function(data) {
|
const materials = data.materials;
|
||||||
var materials = data.materials;
|
const nodes = data.nodes;
|
||||||
var nodes = data.nodes;
|
const name = data.name;
|
||||||
var name = data.name;
|
const meshes = getMeshes(data);
|
||||||
var meshes = getMeshes(data);
|
const primitives = getPrimitives(data);
|
||||||
var primitives = getPrimitives(data);
|
|
||||||
|
|
||||||
expect(name).toBe('box');
|
expect(name).toBe('box');
|
||||||
expect(materials.length).toBe(1);
|
expect(materials.length).toBe(1);
|
||||||
@ -89,9 +88,9 @@ describe('loadObj', function() {
|
|||||||
expect(meshes.length).toBe(1);
|
expect(meshes.length).toBe(1);
|
||||||
expect(primitives.length).toBe(1);
|
expect(primitives.length).toBe(1);
|
||||||
|
|
||||||
var node = nodes[0];
|
const node = nodes[0];
|
||||||
var mesh = meshes[0];
|
const mesh = meshes[0];
|
||||||
var primitive = primitives[0];
|
const primitive = primitives[0];
|
||||||
|
|
||||||
expect(node.name).toBe('Cube');
|
expect(node.name).toBe('Cube');
|
||||||
expect(mesh.name).toBe('Cube-Mesh');
|
expect(mesh.name).toBe('Cube-Mesh');
|
||||||
@ -100,134 +99,117 @@ describe('loadObj', function() {
|
|||||||
expect(primitive.uvs.length / 2).toBe(24);
|
expect(primitive.uvs.length / 2).toBe(24);
|
||||||
expect(primitive.indices.length).toBe(36);
|
expect(primitive.indices.length).toBe(36);
|
||||||
expect(primitive.material).toBe('Material');
|
expect(primitive.material).toBe('Material');
|
||||||
}), done).toResolve();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('loads obj with normals', function(done) {
|
it('loads obj with normals', async () => {
|
||||||
expect(loadObj(objNormalsPath, options)
|
const data = await loadObj(objNormalsPath, options);
|
||||||
.then(function(data) {
|
const primitive = getPrimitives(data)[0];
|
||||||
var primitive = getPrimitives(data)[0];
|
|
||||||
expect(primitive.positions.length / 3).toBe(24);
|
expect(primitive.positions.length / 3).toBe(24);
|
||||||
expect(primitive.normals.length / 3).toBe(24);
|
expect(primitive.normals.length / 3).toBe(24);
|
||||||
expect(primitive.uvs.length / 2).toBe(0);
|
expect(primitive.uvs.length / 2).toBe(0);
|
||||||
}), done).toResolve();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('normalizes normals', function(done) {
|
it('normalizes normals', async () => {
|
||||||
expect(loadObj(objUnnormalizedPath, options)
|
const data = await loadObj(objUnnormalizedPath, options);
|
||||||
.then(function(data) {
|
const scratchNormal = new Cesium.Cartesian3();
|
||||||
var scratchNormal = new Cesium.Cartesian3();
|
const primitive = getPrimitives(data)[0];
|
||||||
var primitive = getPrimitives(data)[0];
|
const normals = primitive.normals;
|
||||||
var normals = primitive.normals;
|
const normalsLength = normals.length / 3;
|
||||||
var normalsLength = normals.length / 3;
|
for (let i = 0; i < normalsLength; ++i) {
|
||||||
for (var i = 0; i < normalsLength; ++i) {
|
const normalX = normals.get(i * 3);
|
||||||
var normalX = normals.get(i * 3);
|
const normalY = normals.get(i * 3 + 1);
|
||||||
var normalY = normals.get(i * 3 + 1);
|
const normalZ = normals.get(i * 3 + 2);
|
||||||
var normalZ = normals.get(i * 3 + 2);
|
const normal = Cartesian3.fromElements(normalX, normalY, normalZ, scratchNormal);
|
||||||
var normal = Cartesian3.fromElements(normalX, normalY, normalZ, scratchNormal);
|
expect(CesiumMath.equalsEpsilon(Cartesian3.magnitude(normal), 1.0, CesiumMath.EPSILON5)).toBe(true);
|
||||||
expect(Cartesian3.magnitude(normal)).toEqualEpsilon(1.0, CesiumMath.EPSILON5);
|
|
||||||
}
|
}
|
||||||
}), done).toResolve();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('loads obj with uvs', function(done) {
|
it('loads obj with uvs', async () => {
|
||||||
expect(loadObj(objUvsPath, options)
|
const data = await loadObj(objUvsPath, options);
|
||||||
.then(function(data) {
|
const primitive = getPrimitives(data)[0];
|
||||||
var primitive = getPrimitives(data)[0];
|
|
||||||
expect(primitive.positions.length / 3).toBe(20);
|
expect(primitive.positions.length / 3).toBe(20);
|
||||||
expect(primitive.normals.length / 3).toBe(0);
|
expect(primitive.normals.length / 3).toBe(0);
|
||||||
expect(primitive.uvs.length / 2).toBe(20);
|
expect(primitive.uvs.length / 2).toBe(20);
|
||||||
}), done).toResolve();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('loads obj with negative indices', function(done) {
|
it('loads obj with negative indices', async () => {
|
||||||
expect(Promise.all([
|
const results = [
|
||||||
loadObj(objPositionsOnlyPath, options),
|
await loadObj(objPositionsOnlyPath, options),
|
||||||
loadObj(objNegativeIndicesPath, options)
|
await loadObj(objNegativeIndicesPath, options)
|
||||||
])
|
];
|
||||||
.then(function(results) {
|
const positionsReference = getPrimitives(results[0])[0].positions.toFloatBuffer();
|
||||||
var positionsReference = getPrimitives(results[0])[0].positions.toFloatBuffer();
|
const positions = getPrimitives(results[1])[0].positions.toFloatBuffer();
|
||||||
var positions = getPrimitives(results[1])[0].positions.toFloatBuffer();
|
|
||||||
expect(positions).toEqual(positionsReference);
|
expect(positions).toEqual(positionsReference);
|
||||||
}), done).toResolve();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('loads obj with triangle faces', function(done) {
|
it('loads obj with triangle faces', async () => {
|
||||||
expect(loadObj(objTrianglesPath, options)
|
const data = await loadObj(objTrianglesPath, options);
|
||||||
.then(function(data) {
|
const primitive = getPrimitives(data)[0];
|
||||||
var primitive = getPrimitives(data)[0];
|
|
||||||
expect(primitive.positions.length / 3).toBe(24);
|
expect(primitive.positions.length / 3).toBe(24);
|
||||||
expect(primitive.indices.length).toBe(36);
|
expect(primitive.indices.length).toBe(36);
|
||||||
}), done).toResolve();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('loads obj with objects', function(done) {
|
it('loads obj with objects', async () => {
|
||||||
expect(loadObj(objObjectsPath, options)
|
const data = await loadObj(objObjectsPath, options);
|
||||||
.then(function(data) {
|
const nodes = data.nodes;
|
||||||
var nodes = data.nodes;
|
|
||||||
expect(nodes.length).toBe(3);
|
expect(nodes.length).toBe(3);
|
||||||
expect(nodes[0].name).toBe('CubeBlue');
|
expect(nodes[0].name).toBe('CubeBlue');
|
||||||
expect(nodes[1].name).toBe('CubeGreen');
|
expect(nodes[1].name).toBe('CubeGreen');
|
||||||
expect(nodes[2].name).toBe('CubeRed');
|
expect(nodes[2].name).toBe('CubeRed');
|
||||||
|
|
||||||
var primitives = getPrimitives(data);
|
const primitives = getPrimitives(data);
|
||||||
expect(primitives.length).toBe(3);
|
expect(primitives.length).toBe(3);
|
||||||
expect(primitives[0].material).toBe('Blue');
|
expect(primitives[0].material).toBe('Blue');
|
||||||
expect(primitives[1].material).toBe('Green');
|
expect(primitives[1].material).toBe('Green');
|
||||||
expect(primitives[2].material).toBe('Red');
|
expect(primitives[2].material).toBe('Red');
|
||||||
}), done).toResolve();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('loads obj with groups', function(done) {
|
it('loads obj with groups', async () => {
|
||||||
expect(loadObj(objGroupsPath, options)
|
const data = await loadObj(objGroupsPath, options);
|
||||||
.then(function(data) {
|
const nodes = data.nodes;
|
||||||
var nodes = data.nodes;
|
|
||||||
expect(nodes.length).toBe(3);
|
expect(nodes.length).toBe(3);
|
||||||
expect(nodes[0].name).toBe('CubeBlue');
|
expect(nodes[0].name).toBe('CubeBlue');
|
||||||
expect(nodes[1].name).toBe('CubeGreen');
|
expect(nodes[1].name).toBe('CubeGreen');
|
||||||
expect(nodes[2].name).toBe('CubeRed');
|
expect(nodes[2].name).toBe('CubeRed');
|
||||||
|
|
||||||
var primitives = getPrimitives(data);
|
const primitives = getPrimitives(data);
|
||||||
expect(primitives.length).toBe(3);
|
expect(primitives.length).toBe(3);
|
||||||
expect(primitives[0].material).toBe('Blue');
|
expect(primitives[0].material).toBe('Blue');
|
||||||
expect(primitives[1].material).toBe('Green');
|
expect(primitives[1].material).toBe('Green');
|
||||||
expect(primitives[2].material).toBe('Red');
|
expect(primitives[2].material).toBe('Red');
|
||||||
}), done).toResolve();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('loads obj with objects and groups', function(done) {
|
it('loads obj with objects and groups', async () => {
|
||||||
expect(loadObj(objObjectsGroupsPath, options)
|
const data = await loadObj(objObjectsGroupsPath, options);
|
||||||
.then(function(data) {
|
const nodes = data.nodes;
|
||||||
var nodes = data.nodes;
|
|
||||||
expect(nodes.length).toBe(3);
|
expect(nodes.length).toBe(3);
|
||||||
expect(nodes[0].name).toBe('CubeBlue');
|
expect(nodes[0].name).toBe('CubeBlue');
|
||||||
expect(nodes[1].name).toBe('CubeGreen');
|
expect(nodes[1].name).toBe('CubeGreen');
|
||||||
expect(nodes[2].name).toBe('CubeRed');
|
expect(nodes[2].name).toBe('CubeRed');
|
||||||
|
|
||||||
var meshes = getMeshes(data);
|
const meshes = getMeshes(data);
|
||||||
expect(meshes.length).toBe(3);
|
expect(meshes.length).toBe(3);
|
||||||
expect(meshes[0].name).toBe('CubeBlue_CubeBlue_Blue');
|
expect(meshes[0].name).toBe('CubeBlue_CubeBlue_Blue');
|
||||||
expect(meshes[1].name).toBe('CubeGreen_CubeGreen_Green');
|
expect(meshes[1].name).toBe('CubeGreen_CubeGreen_Green');
|
||||||
expect(meshes[2].name).toBe('CubeRed_CubeRed_Red');
|
expect(meshes[2].name).toBe('CubeRed_CubeRed_Red');
|
||||||
|
|
||||||
var primitives = getPrimitives(data);
|
const primitives = getPrimitives(data);
|
||||||
expect(primitives.length).toBe(3);
|
expect(primitives.length).toBe(3);
|
||||||
expect(primitives[0].material).toBe('Blue');
|
expect(primitives[0].material).toBe('Blue');
|
||||||
expect(primitives[1].material).toBe('Green');
|
expect(primitives[1].material).toBe('Green');
|
||||||
expect(primitives[2].material).toBe('Red');
|
expect(primitives[2].material).toBe('Red');
|
||||||
}), done).toResolve();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
function loadsObjWithObjectsGroupsAndMaterials(data) {
|
function loadsObjWithObjectsGroupsAndMaterials(data) {
|
||||||
var nodes = data.nodes;
|
const nodes = data.nodes;
|
||||||
expect(nodes.length).toBe(1);
|
expect(nodes.length).toBe(1);
|
||||||
expect(nodes[0].name).toBe('Cube');
|
expect(nodes[0].name).toBe('Cube');
|
||||||
var meshes = getMeshes(data);
|
const meshes = getMeshes(data);
|
||||||
expect(meshes.length).toBe(3);
|
expect(meshes.length).toBe(3);
|
||||||
expect(meshes[0].name).toBe('Blue');
|
expect(meshes[0].name).toBe('Blue');
|
||||||
expect(meshes[1].name).toBe('Green');
|
expect(meshes[1].name).toBe('Green');
|
||||||
expect(meshes[2].name).toBe('Red');
|
expect(meshes[2].name).toBe('Red');
|
||||||
var primitives = getPrimitives(data);
|
const primitives = getPrimitives(data);
|
||||||
expect(primitives.length).toBe(6);
|
expect(primitives.length).toBe(6);
|
||||||
expect(primitives[0].material).toBe('Blue');
|
expect(primitives[0].material).toBe('Blue');
|
||||||
expect(primitives[1].material).toBe('Green');
|
expect(primitives[1].material).toBe('Green');
|
||||||
@ -237,70 +219,59 @@ describe('loadObj', function() {
|
|||||||
expect(primitives[5].material).toBe('Blue');
|
expect(primitives[5].material).toBe('Blue');
|
||||||
}
|
}
|
||||||
|
|
||||||
it('loads obj with objects, groups, and materials', function(done) {
|
it('loads obj with objects, groups, and materials', async () => {
|
||||||
expect(loadObj(objObjectsGroupsMaterialsPath, options)
|
const data = await loadObj(objObjectsGroupsMaterialsPath, options);
|
||||||
.then(function(data) {
|
|
||||||
loadsObjWithObjectsGroupsAndMaterials(data);
|
loadsObjWithObjectsGroupsAndMaterials(data);
|
||||||
}), done).toResolve();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
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
|
// The usemtl lines are placed in an unordered fashion but
|
||||||
// should produce the same result as the previous test
|
// should produce the same result as the previous test
|
||||||
expect(loadObj(objObjectsGroupsMaterialsPath2, options)
|
const data = await loadObj(objObjectsGroupsMaterialsPath2, options);
|
||||||
.then(function(data) {
|
|
||||||
loadsObjWithObjectsGroupsAndMaterials(data);
|
loadsObjWithObjectsGroupsAndMaterials(data);
|
||||||
}), done).toResolve();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('loads obj with concave face containing 5 vertices', function(done) {
|
it('loads obj with concave face containing 5 vertices', async () => {
|
||||||
expect(loadObj(objConcavePath, options)
|
const data = await loadObj(objConcavePath, options);
|
||||||
.then(function(data) {
|
const primitive = getPrimitives(data)[0];
|
||||||
var primitive = getPrimitives(data)[0];
|
|
||||||
expect(primitive.positions.length / 3).toBe(30);
|
expect(primitive.positions.length / 3).toBe(30);
|
||||||
expect(primitive.indices.length).toBe(48);
|
expect(primitive.indices.length).toBe(48);
|
||||||
}), done).toResolve();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('loads obj with usemtl only', function(done) {
|
it('loads obj with usemtl only', async () => {
|
||||||
expect(loadObj(objUsemtlPath, options)
|
const data = await loadObj(objUsemtlPath, options);
|
||||||
.then(function(data) {
|
const nodes = data.nodes;
|
||||||
var nodes = data.nodes;
|
|
||||||
expect(nodes.length).toBe(1);
|
expect(nodes.length).toBe(1);
|
||||||
expect(nodes[0].name).toBe('Node'); // default name
|
expect(nodes[0].name).toBe('Node'); // default name
|
||||||
|
|
||||||
var meshes = getMeshes(data);
|
const meshes = getMeshes(data);
|
||||||
expect(meshes.length).toBe(1);
|
expect(meshes.length).toBe(1);
|
||||||
expect(meshes[0].name).toBe('Node-Mesh');
|
expect(meshes[0].name).toBe('Node-Mesh');
|
||||||
|
|
||||||
var primitives = getPrimitives(data);
|
const primitives = getPrimitives(data);
|
||||||
expect(primitives.length).toBe(3);
|
expect(primitives.length).toBe(3);
|
||||||
expect(primitives[0].material).toBe('Blue');
|
expect(primitives[0].material).toBe('Blue');
|
||||||
expect(primitives[1].material).toBe('Green');
|
expect(primitives[1].material).toBe('Green');
|
||||||
expect(primitives[2].material).toBe('Red');
|
expect(primitives[2].material).toBe('Red');
|
||||||
}), done).toResolve();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('loads obj with no materials', function(done) {
|
it('loads obj with no materials', async () => {
|
||||||
expect(loadObj(objNoMaterialsPath, options)
|
const data = await loadObj(objNoMaterialsPath, options);
|
||||||
.then(function(data) {
|
const nodes = data.nodes;
|
||||||
var nodes = data.nodes;
|
|
||||||
expect(nodes.length).toBe(1);
|
expect(nodes.length).toBe(1);
|
||||||
expect(nodes[0].name).toBe('Node'); // default name
|
expect(nodes[0].name).toBe('Node'); // default name
|
||||||
|
|
||||||
var primitives = getPrimitives(data);
|
const primitives = getPrimitives(data);
|
||||||
expect(primitives.length).toBe(1);
|
expect(primitives.length).toBe(1);
|
||||||
}), done).toResolve();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
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
|
// The usemtl markers are interleaved, but should condense to just three primitives
|
||||||
expect(loadObj(objMultipleMaterialsPath, options)
|
const data = await loadObj(objMultipleMaterialsPath, options);
|
||||||
.then(function(data) {
|
const nodes = data.nodes;
|
||||||
var nodes = data.nodes;
|
|
||||||
expect(nodes.length).toBe(1);
|
expect(nodes.length).toBe(1);
|
||||||
|
|
||||||
var primitives = getPrimitives(data);
|
const primitives = getPrimitives(data);
|
||||||
expect(primitives.length).toBe(3);
|
expect(primitives.length).toBe(3);
|
||||||
|
|
||||||
expect(primitives[0].indices.length).toBe(12);
|
expect(primitives[0].indices.length).toBe(12);
|
||||||
@ -310,23 +281,21 @@ describe('loadObj', function() {
|
|||||||
expect(primitives[1].material).toBe('Green');
|
expect(primitives[1].material).toBe('Green');
|
||||||
expect(primitives[2].material).toBe('Blue');
|
expect(primitives[2].material).toBe('Blue');
|
||||||
|
|
||||||
for (var i = 0; i < 3; ++i) {
|
for (let i = 0; i < 3; ++i) {
|
||||||
var indices = primitives[i].indices;
|
const indices = primitives[i].indices;
|
||||||
for (var j = 0; j < indices.length; ++j) {
|
for (let j = 0; j < indices.length; ++j) {
|
||||||
expect(indices.get(j)).toBeLessThan(8);
|
expect(indices.get(j)).toBeLessThan(8);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}), done).toResolve();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('loads obj uncleaned', function(done) {
|
it('loads obj uncleaned', async () => {
|
||||||
// Obj with extraneous o, g, and usemtl lines
|
// Obj with extraneous o, g, and usemtl lines
|
||||||
// Also tests handling of o and g lines with the same names
|
// Also tests handling of o and g lines with the same names
|
||||||
expect(loadObj(objUncleanedPath, options)
|
const data = await loadObj(objUncleanedPath, options);
|
||||||
.then(function(data) {
|
const nodes = data.nodes;
|
||||||
var nodes = data.nodes;
|
const meshes = getMeshes(data);
|
||||||
var meshes = getMeshes(data);
|
const primitives = getPrimitives(data);
|
||||||
var primitives = getPrimitives(data);
|
|
||||||
|
|
||||||
expect(nodes.length).toBe(1);
|
expect(nodes.length).toBe(1);
|
||||||
expect(meshes.length).toBe(1);
|
expect(meshes.length).toBe(1);
|
||||||
@ -334,17 +303,15 @@ describe('loadObj', function() {
|
|||||||
|
|
||||||
expect(nodes[0].name).toBe('Cube');
|
expect(nodes[0].name).toBe('Cube');
|
||||||
expect(meshes[0].name).toBe('Cube_1');
|
expect(meshes[0].name).toBe('Cube_1');
|
||||||
}), done).toResolve();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('loads obj with multiple mtllibs', function(done) {
|
it('loads obj with multiple mtllibs', async () => {
|
||||||
expect(loadObj(objMtllibPath, options)
|
const data = await loadObj(objMtllibPath, options);
|
||||||
.then(function(data) {
|
const materials = data.materials;
|
||||||
var materials = data.materials;
|
|
||||||
expect(materials.length).toBe(3);
|
expect(materials.length).toBe(3);
|
||||||
|
|
||||||
// .mtl files are loaded in an arbitrary order, so sort for testing purposes
|
// .mtl files are loaded in an arbitrary order, so sort for testing purposes
|
||||||
materials.sort(function(a, b){
|
materials.sort((a, b) => {
|
||||||
return a.name.localeCompare(b.name);
|
return a.name.localeCompare(b.name);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -354,17 +321,15 @@ describe('loadObj', function() {
|
|||||||
expect(materials[1].pbrMetallicRoughness.baseColorFactor).toEqual([0.0, 0.64, 0.0, 1.0]);
|
expect(materials[1].pbrMetallicRoughness.baseColorFactor).toEqual([0.0, 0.64, 0.0, 1.0]);
|
||||||
expect(materials[2].name).toBe('Red');
|
expect(materials[2].name).toBe('Red');
|
||||||
expect(materials[2].pbrMetallicRoughness.baseColorFactor).toEqual([0.64, 0.0, 0.0, 1.0]);
|
expect(materials[2].pbrMetallicRoughness.baseColorFactor).toEqual([0.64, 0.0, 0.0, 1.0]);
|
||||||
}), done).toResolve();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('loads obj with mtllib paths with spaces', function(done) {
|
it('loads obj with mtllib paths with spaces', async () => {
|
||||||
expect(loadObj(objMtllibSpacesPath, options)
|
const data = await loadObj(objMtllibSpacesPath, options);
|
||||||
.then(function(data) {
|
const materials = data.materials;
|
||||||
var materials = data.materials;
|
|
||||||
expect(materials.length).toBe(3);
|
expect(materials.length).toBe(3);
|
||||||
|
|
||||||
// .mtl files are loaded in an arbitrary order, so sort for testing purposes
|
// .mtl files are loaded in an arbitrary order, so sort for testing purposes
|
||||||
materials.sort(function(a, b){
|
materials.sort((a, b) => {
|
||||||
return a.name.localeCompare(b.name);
|
return a.name.localeCompare(b.name);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -374,143 +339,132 @@ describe('loadObj', function() {
|
|||||||
expect(materials[1].pbrMetallicRoughness.baseColorFactor).toEqual([0.0, 0.64, 0.0, 1.0]);
|
expect(materials[1].pbrMetallicRoughness.baseColorFactor).toEqual([0.0, 0.64, 0.0, 1.0]);
|
||||||
expect(materials[2].name).toBe('Red');
|
expect(materials[2].name).toBe('Red');
|
||||||
expect(materials[2].pbrMetallicRoughness.baseColorFactor).toEqual([0.64, 0.0, 0.0, 1.0]);
|
expect(materials[2].pbrMetallicRoughness.baseColorFactor).toEqual([0.64, 0.0, 0.0, 1.0]);
|
||||||
}), done).toResolve();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('loads obj with missing mtllib', function(done) {
|
it('loads obj with missing mtllib', async () => {
|
||||||
var spy = jasmine.createSpy('logger');
|
const spy = jasmine.createSpy('logger');
|
||||||
options.logger = spy;
|
options.logger = spy;
|
||||||
|
|
||||||
expect(loadObj(objMissingMtllibPath, options)
|
const data = await loadObj(objMissingMtllibPath, options);
|
||||||
.then(function(data) {
|
|
||||||
expect(data.materials.length).toBe(0);
|
expect(data.materials.length).toBe(0);
|
||||||
expect(spy.calls.argsFor(0)[0].indexOf('ENOENT') >= 0).toBe(true);
|
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(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(2)[0].indexOf('ENOENT') >= 0).toBe(true);
|
||||||
expect(spy.calls.argsFor(3)[0].indexOf('Could not read material file') >= 0).toBe(true);
|
expect(spy.calls.argsFor(3)[0].indexOf('Could not read material file') >= 0).toBe(true);
|
||||||
}), done).toResolve();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('loads obj with missing usemtl', function(done) {
|
it('loads obj with missing usemtl', async () => {
|
||||||
expect(loadObj(objMissingUsemtlPath, options)
|
const data = await loadObj(objMissingUsemtlPath, options);
|
||||||
.then(function(data) {
|
|
||||||
expect(data.materials.length).toBe(1);
|
expect(data.materials.length).toBe(1);
|
||||||
expect(data.nodes[0].meshes[0].primitives[0].material).toBe('Material');
|
expect(data.nodes[0].meshes[0].primitives[0].material).toBe('Material');
|
||||||
}), done).toResolve();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('loads .mtl outside of the obj directory', function(done) {
|
it('loads .mtl outside of the obj directory', async () => {
|
||||||
expect(loadObj(objExternalResourcesPath, options)
|
const data = await loadObj(objExternalResourcesPath, options);
|
||||||
.then(function(data) {
|
const materials = data.materials;
|
||||||
var materials = data.materials;
|
|
||||||
expect(materials.length).toBe(2);
|
expect(materials.length).toBe(2);
|
||||||
|
|
||||||
// .mtl files are loaded in an arbitrary order, so find the "MaterialTextured" material
|
// .mtl files are loaded in an arbitrary order, so find the "MaterialTextured" material
|
||||||
var materialTextured = materials[0].name === 'MaterialTextured' ? materials[0] : materials[1];
|
const materialTextured = materials[0].name === 'MaterialTextured' ? materials[0] : materials[1];
|
||||||
var baseColorTexture = materialTextured.pbrMetallicRoughness.baseColorTexture;
|
const baseColorTexture = materialTextured.pbrMetallicRoughness.baseColorTexture;
|
||||||
expect(baseColorTexture.source).toBeDefined();
|
expect(baseColorTexture.source).toBeDefined();
|
||||||
expect(baseColorTexture.name).toEqual('cesium');
|
expect(baseColorTexture.name).toEqual('cesium');
|
||||||
}), done).toResolve();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('does not load .mtl outside of the obj directory when secure is true', function(done) {
|
it('does not load .mtl outside of the obj directory when secure is true', async () => {
|
||||||
var spy = jasmine.createSpy('logger');
|
const spy = jasmine.createSpy('logger');
|
||||||
options.logger = spy;
|
options.logger = spy;
|
||||||
options.secure = true;
|
options.secure = true;
|
||||||
|
|
||||||
expect(loadObj(objExternalResourcesPath, options)
|
const data = await 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(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(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(1)[0].indexOf('ENOENT') >= 0).toBe(true);
|
||||||
expect(spy.calls.argsFor(2)[0].indexOf('Could not read material file') >= 0).toBe(true);
|
expect(spy.calls.argsFor(2)[0].indexOf('Could not read material file') >= 0).toBe(true);
|
||||||
}), done).toResolve();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('loads .mtl from root directory when the .mtl path does not exist', function(done) {
|
it('loads .mtl from root directory when the .mtl path does not exist', async () => {
|
||||||
expect(loadObj(objResourcesInRootPath, options)
|
const data = await loadObj(objResourcesInRootPath, options);
|
||||||
.then(function(data) {
|
const baseColorTexture = data.materials[0].pbrMetallicRoughness.baseColorTexture;
|
||||||
var baseColorTexture = data.materials[0].pbrMetallicRoughness.baseColorTexture;
|
|
||||||
expect(baseColorTexture.name).toBe('cesium');
|
expect(baseColorTexture.name).toBe('cesium');
|
||||||
expect(baseColorTexture.source).toBeDefined();
|
expect(baseColorTexture.source).toBeDefined();
|
||||||
}), done).toResolve();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
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;
|
options.secure = true;
|
||||||
|
|
||||||
expect(loadObj(objExternalResourcesInRootPath, options)
|
const data = await loadObj(objExternalResourcesInRootPath, options);
|
||||||
.then(function(data) {
|
const materials = data.materials;
|
||||||
var materials = data.materials;
|
|
||||||
expect(materials.length).toBe(2);
|
expect(materials.length).toBe(2);
|
||||||
|
|
||||||
// .mtl files are loaded in an arbitrary order, so find the "MaterialTextured" material
|
// .mtl files are loaded in an arbitrary order, so find the "MaterialTextured" material
|
||||||
var materialTextured = materials[0].name === 'MaterialTextured' ? materials[0] : materials[1];
|
const materialTextured = materials[0].name === 'MaterialTextured' ? materials[0] : materials[1];
|
||||||
var baseColorTexture = materialTextured.pbrMetallicRoughness.baseColorTexture;
|
const baseColorTexture = materialTextured.pbrMetallicRoughness.baseColorTexture;
|
||||||
expect(baseColorTexture.source).toBeDefined();
|
expect(baseColorTexture.source).toBeDefined();
|
||||||
expect(baseColorTexture.name).toEqual('cesium');
|
expect(baseColorTexture.name).toEqual('cesium');
|
||||||
}), done).toResolve();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('loads obj with texture', function(done) {
|
it('loads obj with texture', async () => {
|
||||||
expect(loadObj(objTexturedPath, options)
|
const data = await loadObj(objTexturedPath, options);
|
||||||
.then(function(data) {
|
const baseColorTexture = data.materials[0].pbrMetallicRoughness.baseColorTexture;
|
||||||
var baseColorTexture = data.materials[0].pbrMetallicRoughness.baseColorTexture;
|
|
||||||
expect(baseColorTexture.name).toBe('cesium');
|
expect(baseColorTexture.name).toBe('cesium');
|
||||||
expect(baseColorTexture.source).toBeDefined();
|
expect(baseColorTexture.source).toBeDefined();
|
||||||
}), done).toResolve();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('loads obj with missing texture', function(done) {
|
it('loads obj with missing texture', async () => {
|
||||||
var spy = jasmine.createSpy('logger');
|
const spy = jasmine.createSpy('logger');
|
||||||
options.logger = spy;
|
options.logger = spy;
|
||||||
|
|
||||||
expect(loadObj(objMissingTexturePath, options)
|
const data = await loadObj(objMissingTexturePath, options);
|
||||||
.then(function(data) {
|
const baseColorTexture = data.materials[0].pbrMetallicRoughness.baseColorTexture;
|
||||||
var baseColorTexture = data.materials[0].pbrMetallicRoughness.baseColorTexture;
|
|
||||||
expect(baseColorTexture).toBeUndefined();
|
expect(baseColorTexture).toBeUndefined();
|
||||||
expect(spy.calls.argsFor(0)[0].indexOf('ENOENT') >= 0).toBe(true);
|
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(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(2)[0].indexOf('ENOENT') >= 0).toBe(true);
|
||||||
expect(spy.calls.argsFor(3)[0].indexOf('Could not read texture file') >= 0).toBe(true);
|
expect(spy.calls.argsFor(3)[0].indexOf('Could not read texture file') >= 0).toBe(true);
|
||||||
}), done).toResolve();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('loads obj with subdirectories', function(done) {
|
it('loads obj with subdirectories', async () => {
|
||||||
expect(loadObj(objSubdirectoriesPath, options)
|
const data = await loadObj(objSubdirectoriesPath, options);
|
||||||
.then(function(data) {
|
const baseColorTexture = data.materials[0].pbrMetallicRoughness.baseColorTexture;
|
||||||
var baseColorTexture = data.materials[0].pbrMetallicRoughness.baseColorTexture;
|
|
||||||
expect(baseColorTexture.name).toBe('cesium');
|
expect(baseColorTexture.name).toBe('cesium');
|
||||||
expect(baseColorTexture.source).toBeDefined();
|
expect(baseColorTexture.source).toBeDefined();
|
||||||
}), done).toResolve();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('loads obj with windows paths', function(done) {
|
it('loads obj with windows paths', async () => {
|
||||||
expect(loadObj(objWindowsPaths, options)
|
const data = await loadObj(objWindowsPaths, options);
|
||||||
.then(function(data) {
|
const baseColorTexture = data.materials[0].pbrMetallicRoughness.baseColorTexture;
|
||||||
var baseColorTexture = data.materials[0].pbrMetallicRoughness.baseColorTexture;
|
|
||||||
expect(baseColorTexture.name).toBe('cesium');
|
expect(baseColorTexture.name).toBe('cesium');
|
||||||
expect(baseColorTexture.source).toBeDefined();
|
expect(baseColorTexture.source).toBeDefined();
|
||||||
}), done).toResolve();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('separates faces that don\'t use the same attributes as other faces in the primitive', function(done) {
|
it('separates faces that don\'t use the same attributes as other faces in the primitive', async () => {
|
||||||
expect(loadObj(objMixedAttributesPath, options)
|
const data = await loadObj(objMixedAttributesPath, options);
|
||||||
.then(function(data) {
|
const primitives = getPrimitives(data);
|
||||||
var primitives = getPrimitives(data);
|
|
||||||
expect(primitives.length).toBe(4);
|
expect(primitives.length).toBe(4);
|
||||||
expect(primitives[0].indices.length).toBe(18); // 6 faces
|
expect(primitives[0].indices.length).toBe(18); // 6 faces
|
||||||
expect(primitives[1].indices.length).toBe(6); // 2 faces
|
expect(primitives[1].indices.length).toBe(6); // 2 faces
|
||||||
expect(primitives[2].indices.length).toBe(6); // 2 faces
|
expect(primitives[2].indices.length).toBe(6); // 2 faces
|
||||||
expect(primitives[3].indices.length).toBe(6); // 2 faces
|
expect(primitives[3].indices.length).toBe(6); // 2 faces
|
||||||
}), done).toResolve();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('throws when file has invalid contents', function(done) {
|
it('throws when file has invalid contents', async () => {
|
||||||
expect(loadObj(objInvalidContentsPath, options), done).toRejectWith(RuntimeError);
|
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) {
|
it('throw when reading invalid file', async () => {
|
||||||
expect(loadObj(objInvalidPath, options), done).toRejectWith(Error);
|
let thrownError;
|
||||||
|
try {
|
||||||
|
await loadObj(objInvalidPath, options);
|
||||||
|
} catch (e) {
|
||||||
|
thrownError = e;
|
||||||
|
}
|
||||||
|
expect(thrownError.message.startsWith('ENOENT: no such file or directory')).toBe(true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,17 +1,16 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
var loadTexture = require('../../lib/loadTexture');
|
const loadTexture = require('../../lib/loadTexture');
|
||||||
|
|
||||||
var pngTexturePath = 'specs/data/box-complex-material/shininess.png';
|
const pngTexturePath = 'specs/data/box-complex-material/shininess.png';
|
||||||
var jpgTexturePath = 'specs/data/box-complex-material/emission.jpg';
|
const jpgTexturePath = 'specs/data/box-complex-material/emission.jpg';
|
||||||
var jpegTexturePath = 'specs/data/box-complex-material/specular.jpeg';
|
const jpegTexturePath = 'specs/data/box-complex-material/specular.jpeg';
|
||||||
var gifTexturePath = 'specs/data/box-complex-material/ambient.gif';
|
const gifTexturePath = 'specs/data/box-complex-material/ambient.gif';
|
||||||
var grayscaleTexturePath = 'specs/data/box-complex-material-alpha/alpha.png';
|
const grayscaleTexturePath = 'specs/data/box-complex-material-alpha/alpha.png';
|
||||||
var transparentTexturePath = 'specs/data/box-complex-material/diffuse.png';
|
const transparentTexturePath = 'specs/data/box-complex-material/diffuse.png';
|
||||||
|
|
||||||
describe('loadTexture', function() {
|
describe('loadTexture', () => {
|
||||||
it('loads png texture', function(done) {
|
it('loads png texture', async () => {
|
||||||
expect(loadTexture(pngTexturePath)
|
const texture = await loadTexture(pngTexturePath);
|
||||||
.then(function(texture) {
|
|
||||||
expect(texture.transparent).toBe(false);
|
expect(texture.transparent).toBe(false);
|
||||||
expect(texture.source).toBeDefined();
|
expect(texture.source).toBeDefined();
|
||||||
expect(texture.name).toBe('shininess');
|
expect(texture.name).toBe('shininess');
|
||||||
@ -20,12 +19,10 @@ describe('loadTexture', function() {
|
|||||||
expect(texture.pixels).toBeUndefined();
|
expect(texture.pixels).toBeUndefined();
|
||||||
expect(texture.width).toBeUndefined();
|
expect(texture.width).toBeUndefined();
|
||||||
expect(texture.height).toBeUndefined();
|
expect(texture.height).toBeUndefined();
|
||||||
}), done).toResolve();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('loads jpg texture', function(done) {
|
it('loads jpg texture', async () => {
|
||||||
expect(loadTexture(jpgTexturePath)
|
const texture = await loadTexture(jpgTexturePath);
|
||||||
.then(function(texture) {
|
|
||||||
expect(texture.transparent).toBe(false);
|
expect(texture.transparent).toBe(false);
|
||||||
expect(texture.source).toBeDefined();
|
expect(texture.source).toBeDefined();
|
||||||
expect(texture.name).toBe('emission');
|
expect(texture.name).toBe('emission');
|
||||||
@ -34,12 +31,10 @@ describe('loadTexture', function() {
|
|||||||
expect(texture.pixels).toBeUndefined();
|
expect(texture.pixels).toBeUndefined();
|
||||||
expect(texture.width).toBeUndefined();
|
expect(texture.width).toBeUndefined();
|
||||||
expect(texture.height).toBeUndefined();
|
expect(texture.height).toBeUndefined();
|
||||||
}), done).toResolve();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('loads jpeg texture', function(done) {
|
it('loads jpeg texture', async () => {
|
||||||
expect(loadTexture(jpegTexturePath)
|
const texture = await loadTexture(jpegTexturePath);
|
||||||
.then(function(texture) {
|
|
||||||
expect(texture.transparent).toBe(false);
|
expect(texture.transparent).toBe(false);
|
||||||
expect(texture.source).toBeDefined();
|
expect(texture.source).toBeDefined();
|
||||||
expect(texture.name).toBe('specular');
|
expect(texture.name).toBe('specular');
|
||||||
@ -48,12 +43,10 @@ describe('loadTexture', function() {
|
|||||||
expect(texture.pixels).toBeUndefined();
|
expect(texture.pixels).toBeUndefined();
|
||||||
expect(texture.width).toBeUndefined();
|
expect(texture.width).toBeUndefined();
|
||||||
expect(texture.height).toBeUndefined();
|
expect(texture.height).toBeUndefined();
|
||||||
}), done).toResolve();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('loads gif texture', function(done) {
|
it('loads gif texture', async () => {
|
||||||
expect(loadTexture(gifTexturePath)
|
const texture = await loadTexture(gifTexturePath);
|
||||||
.then(function(texture) {
|
|
||||||
expect(texture.transparent).toBe(false);
|
expect(texture.transparent).toBe(false);
|
||||||
expect(texture.source).toBeDefined();
|
expect(texture.source).toBeDefined();
|
||||||
expect(texture.name).toBe('ambient');
|
expect(texture.name).toBe('ambient');
|
||||||
@ -62,56 +55,45 @@ describe('loadTexture', function() {
|
|||||||
expect(texture.pixels).toBeUndefined();
|
expect(texture.pixels).toBeUndefined();
|
||||||
expect(texture.width).toBeUndefined();
|
expect(texture.width).toBeUndefined();
|
||||||
expect(texture.height).toBeUndefined();
|
expect(texture.height).toBeUndefined();
|
||||||
}), done).toResolve();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('loads grayscale texture', function(done) {
|
it('loads grayscale texture', async () => {
|
||||||
expect(loadTexture(grayscaleTexturePath)
|
const texture = await loadTexture(grayscaleTexturePath);
|
||||||
.then(function(texture) {
|
|
||||||
expect(texture.transparent).toBe(false);
|
expect(texture.transparent).toBe(false);
|
||||||
expect(texture.source).toBeDefined();
|
expect(texture.source).toBeDefined();
|
||||||
expect(texture.extension).toBe('.png');
|
expect(texture.extension).toBe('.png');
|
||||||
}), done).toResolve();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('loads texture with alpha channel', function(done) {
|
it('loads texture with alpha channel', async () => {
|
||||||
expect(loadTexture(transparentTexturePath)
|
const texture = await loadTexture(transparentTexturePath);
|
||||||
.then(function(texture) {
|
|
||||||
expect(texture.transparent).toBe(false);
|
expect(texture.transparent).toBe(false);
|
||||||
}), done).toResolve();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('loads texture with checkTransparency flag', function(done) {
|
it('loads texture with checkTransparency flag', async () => {
|
||||||
var options = {
|
const options = {
|
||||||
checkTransparency : true
|
checkTransparency : true
|
||||||
};
|
};
|
||||||
expect(loadTexture(transparentTexturePath, options)
|
const texture = await loadTexture(transparentTexturePath, options);
|
||||||
.then(function(texture) {
|
|
||||||
expect(texture.transparent).toBe(true);
|
expect(texture.transparent).toBe(true);
|
||||||
}), done).toResolve();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('loads and decodes png', function(done) {
|
it('loads and decodes png', async () => {
|
||||||
var options = {
|
const options = {
|
||||||
decode : true
|
decode : true
|
||||||
};
|
};
|
||||||
expect(loadTexture(pngTexturePath, options)
|
const texture = await loadTexture(pngTexturePath, options);
|
||||||
.then(function(texture) {
|
|
||||||
expect(texture.pixels).toBeDefined();
|
expect(texture.pixels).toBeDefined();
|
||||||
expect(texture.width).toBe(211);
|
expect(texture.width).toBe(211);
|
||||||
expect(texture.height).toBe(211);
|
expect(texture.height).toBe(211);
|
||||||
}), done).toResolve();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('loads and decodes jpeg', function(done) {
|
it('loads and decodes jpeg', async () => {
|
||||||
var options = {
|
const options = {
|
||||||
decode : true
|
decode : true
|
||||||
};
|
};
|
||||||
expect(loadTexture(jpegTexturePath, options)
|
const texture = await loadTexture(jpegTexturePath, options);
|
||||||
.then(function(texture) {
|
|
||||||
expect(texture.pixels).toBeDefined();
|
expect(texture.pixels).toBeDefined();
|
||||||
expect(texture.width).toBe(211);
|
expect(texture.width).toBe(211);
|
||||||
expect(texture.height).toBe(211);
|
expect(texture.height).toBe(211);
|
||||||
}), done).toResolve();
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,79 +1,70 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
var fsExtra = require('fs-extra');
|
const { DeveloperError } = require('cesium');
|
||||||
var path = require('path');
|
const fsExtra = require('fs-extra');
|
||||||
var Promise = require('bluebird');
|
const path = require('path');
|
||||||
var obj2gltf = require('../../lib/obj2gltf');
|
const Promise = require('bluebird');
|
||||||
|
const obj2gltf = require('../../lib/obj2gltf');
|
||||||
|
|
||||||
var texturedObjPath = 'specs/data/box-textured/box-textured.obj';
|
const texturedObjPath = 'specs/data/box-textured/box-textured.obj';
|
||||||
var complexObjPath = 'specs/data/box-complex-material/box-complex-material.obj';
|
const complexObjPath = 'specs/data/box-complex-material/box-complex-material.obj';
|
||||||
var missingMtllibObjPath = 'specs/data/box-missing-mtllib/box-missing-mtllib.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() {
|
describe('obj2gltf', () => {
|
||||||
beforeEach(function() {
|
beforeEach(() => {
|
||||||
spyOn(fsExtra, 'outputFile').and.returnValue(Promise.resolve());
|
spyOn(fsExtra, 'outputFile').and.returnValue(Promise.resolve());
|
||||||
});
|
});
|
||||||
|
|
||||||
it('converts obj to gltf', function(done) {
|
it('converts obj to gltf', async () => {
|
||||||
expect(obj2gltf(texturedObjPath)
|
const gltf = await obj2gltf(texturedObjPath);
|
||||||
.then(function(gltf) {
|
|
||||||
expect(gltf).toBeDefined();
|
expect(gltf).toBeDefined();
|
||||||
expect(gltf.images.length).toBe(1);
|
expect(gltf.images.length).toBe(1);
|
||||||
}), done).toResolve();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('converts obj to glb', function(done) {
|
it('converts obj to glb', async () => {
|
||||||
var options = {
|
const options = {
|
||||||
binary : true
|
binary : true
|
||||||
};
|
};
|
||||||
expect(obj2gltf(texturedObjPath, options)
|
const glb = await obj2gltf(texturedObjPath, options);
|
||||||
.then(function(glb) {
|
const magic = glb.toString('utf8', 0, 4);
|
||||||
var magic = glb.toString('utf8', 0, 4);
|
|
||||||
expect(magic).toBe('glTF');
|
expect(magic).toBe('glTF');
|
||||||
}), done).toResolve();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('convert obj to gltf with separate resources', function(done) {
|
it('convert obj to gltf with separate resources', async () => {
|
||||||
var options = {
|
const options = {
|
||||||
separate : true,
|
separate : true,
|
||||||
separateTextures : true,
|
separateTextures : true,
|
||||||
outputDirectory : outputDirectory
|
outputDirectory : outputDirectory
|
||||||
};
|
};
|
||||||
expect(obj2gltf(texturedObjPath, options)
|
await obj2gltf(texturedObjPath, options);
|
||||||
.then(function() {
|
|
||||||
expect(fsExtra.outputFile.calls.count()).toBe(2); // Saves out .png and .bin
|
expect(fsExtra.outputFile.calls.count()).toBe(2); // Saves out .png and .bin
|
||||||
}), done).toResolve();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('converts obj to glb with separate resources', function(done) {
|
it('converts obj to glb with separate resources', async () => {
|
||||||
var options = {
|
const options = {
|
||||||
separate : true,
|
separate : true,
|
||||||
separateTextures : true,
|
separateTextures : true,
|
||||||
outputDirectory : outputDirectory,
|
outputDirectory : outputDirectory,
|
||||||
binary : true
|
binary : true
|
||||||
};
|
};
|
||||||
expect(obj2gltf(texturedObjPath, options)
|
await obj2gltf(texturedObjPath, options);
|
||||||
.then(function() {
|
|
||||||
expect(fsExtra.outputFile.calls.count()).toBe(2); // Saves out .png and .bin
|
expect(fsExtra.outputFile.calls.count()).toBe(2); // Saves out .png and .bin
|
||||||
}), done).toResolve();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('converts obj with multiple textures', function(done) {
|
it('converts obj with multiple textures', async () => {
|
||||||
var options = {
|
const options = {
|
||||||
separateTextures : true,
|
separateTextures : true,
|
||||||
outputDirectory : outputDirectory
|
outputDirectory : outputDirectory
|
||||||
};
|
};
|
||||||
expect(obj2gltf(complexObjPath, options)
|
await obj2gltf(complexObjPath, options);
|
||||||
.then(function() {
|
|
||||||
expect(fsExtra.outputFile.calls.count()).toBe(5); // baseColor, metallicRoughness, occlusion, emission, normal
|
expect(fsExtra.outputFile.calls.count()).toBe(5); // baseColor, metallicRoughness, occlusion, emission, normal
|
||||||
}), done).toResolve();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('sets overriding textures (1)', function(done) {
|
it('sets overriding textures (1)', async () => {
|
||||||
var options = {
|
const options = {
|
||||||
overridingTextures : {
|
overridingTextures : {
|
||||||
metallicRoughnessOcclusionTexture : textureUrl,
|
metallicRoughnessOcclusionTexture : textureUrl,
|
||||||
normalTexture : textureUrl,
|
normalTexture : textureUrl,
|
||||||
@ -84,18 +75,16 @@ describe('obj2gltf', function() {
|
|||||||
separateTextures : true,
|
separateTextures : true,
|
||||||
outputDirectory : outputDirectory
|
outputDirectory : outputDirectory
|
||||||
};
|
};
|
||||||
expect(obj2gltf(complexObjPath, options)
|
await obj2gltf(complexObjPath, options);
|
||||||
.then(function() {
|
const args = fsExtra.outputFile.calls.allArgs();
|
||||||
var args = fsExtra.outputFile.calls.allArgs();
|
const length = args.length;
|
||||||
var length = args.length;
|
for (let i = 0; i < length; ++i) {
|
||||||
for (var i = 0; i < length; ++i) {
|
|
||||||
expect(path.basename(args[i][0])).toBe(path.basename(textureUrl));
|
expect(path.basename(args[i][0])).toBe(path.basename(textureUrl));
|
||||||
}
|
}
|
||||||
}), done).toResolve();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('sets overriding textures (2)', function(done) {
|
it('sets overriding textures (2)', async () => {
|
||||||
var options = {
|
const options = {
|
||||||
overridingTextures : {
|
overridingTextures : {
|
||||||
specularGlossinessTexture : textureUrl,
|
specularGlossinessTexture : textureUrl,
|
||||||
occlusionTexture : textureUrl,
|
occlusionTexture : textureUrl,
|
||||||
@ -107,81 +96,94 @@ describe('obj2gltf', function() {
|
|||||||
separateTextures : true,
|
separateTextures : true,
|
||||||
outputDirectory : outputDirectory
|
outputDirectory : outputDirectory
|
||||||
};
|
};
|
||||||
expect(obj2gltf(complexObjPath, options)
|
await obj2gltf(complexObjPath, options);
|
||||||
.then(function() {
|
const args = fsExtra.outputFile.calls.allArgs();
|
||||||
var args = fsExtra.outputFile.calls.allArgs();
|
const length = args.length;
|
||||||
var length = args.length;
|
for (let i = 0; i < length; ++i) {
|
||||||
for (var i = 0; i < length; ++i) {
|
|
||||||
expect(path.basename(args[i][0])).toBe(path.basename(textureUrl));
|
expect(path.basename(args[i][0])).toBe(path.basename(textureUrl));
|
||||||
}
|
}
|
||||||
}), done).toResolve();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('uses a custom logger', function(done) {
|
it('uses a custom logger', async () => {
|
||||||
var lastMessage;
|
let lastMessage;
|
||||||
var options = {
|
const options = {
|
||||||
logger : function(message) {
|
logger : (message) => {
|
||||||
lastMessage = message;
|
lastMessage = message;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
expect(obj2gltf(missingMtllibObjPath, options)
|
await obj2gltf(missingMtllibObjPath, options);
|
||||||
.then(function() {
|
|
||||||
expect(lastMessage.indexOf('Could not read material file') >= 0).toBe(true);
|
expect(lastMessage.indexOf('Could not read material file') >= 0).toBe(true);
|
||||||
}), done).toResolve();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('uses a custom writer', function(done) {
|
it('uses a custom writer', async () => {
|
||||||
var filePaths = [];
|
const filePaths = [];
|
||||||
var fileContents = [];
|
const fileContents = [];
|
||||||
var options = {
|
const options = {
|
||||||
separate : true,
|
separate : true,
|
||||||
writer : function(relativePath, contents) {
|
writer : (relativePath, contents) => {
|
||||||
filePaths.push(relativePath);
|
filePaths.push(relativePath);
|
||||||
fileContents.push(contents);
|
fileContents.push(contents);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
expect(obj2gltf(texturedObjPath, options)
|
await obj2gltf(texturedObjPath, options);
|
||||||
.then(function() {
|
|
||||||
expect(filePaths).toEqual(['box-textured.bin', 'cesium.png']);
|
expect(filePaths).toEqual(['box-textured.bin', 'cesium.png']);
|
||||||
expect(fileContents[0]).toBeDefined();
|
expect(fileContents[0]).toBeDefined();
|
||||||
expect(fileContents[1]).toBeDefined();
|
expect(fileContents[1]).toBeDefined();
|
||||||
}), done).toResolve();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('throws if objPath is undefined', function() {
|
it('throws if objPath is undefined', () => {
|
||||||
expect(function() {
|
let thrownError;
|
||||||
|
try {
|
||||||
obj2gltf(undefined);
|
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() {
|
it('throws if both options.writer and options.outputDirectory are undefined when writing separate resources', () => {
|
||||||
var options = {
|
const options = {
|
||||||
separateTextures : true
|
separateTextures : true
|
||||||
};
|
};
|
||||||
expect(function() {
|
|
||||||
|
let thrownError;
|
||||||
|
try {
|
||||||
obj2gltf(texturedObjPath, options);
|
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() {
|
it('throws if more than one material type is set', () => {
|
||||||
var options = {
|
const options = {
|
||||||
metallicRoughness : true,
|
metallicRoughness : true,
|
||||||
specularGlossiness : true
|
specularGlossiness : true
|
||||||
};
|
};
|
||||||
expect(function() {
|
|
||||||
|
let thrownError;
|
||||||
|
try {
|
||||||
obj2gltf(texturedObjPath, options);
|
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() {
|
it('throws if metallicRoughnessOcclusionTexture and specularGlossinessTexture are both defined', () => {
|
||||||
var options = {
|
const options = {
|
||||||
overridingTextures : {
|
overridingTextures : {
|
||||||
metallicRoughnessOcclusionTexture : textureUrl,
|
metallicRoughnessOcclusionTexture : textureUrl,
|
||||||
specularGlossinessTexture : textureUrl
|
specularGlossinessTexture : textureUrl
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
expect(function() {
|
|
||||||
|
let thrownError;
|
||||||
|
try {
|
||||||
obj2gltf(texturedObjPath, options);
|
obj2gltf(texturedObjPath, options);
|
||||||
}).toThrowDeveloperError();
|
} catch (e) {
|
||||||
|
thrownError = e;
|
||||||
|
}
|
||||||
|
expect(thrownError).toEqual(new DeveloperError('metallicRoughnessOcclusionTexture and specularGlossinessTexture cannot both be defined.'));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -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));
|
|
||||||
};
|
|
||||||
};
|
|
||||||
});
|
|
@ -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);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
});
|
|
@ -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;
|
|
||||||
});
|
|
@ -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;
|
|
||||||
};
|
|
||||||
});
|
|
@ -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();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
@ -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);
|
|
||||||
};
|
|
Loading…
Reference in New Issue
Block a user