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