Merge pull request #62 from AnalyticalGraphicsInc/single-bin

Don't save out two bins
This commit is contained in:
Ed Mackey 2017-04-25 16:27:31 -04:00 committed by GitHub
commit f9c0e130aa
6 changed files with 69 additions and 39 deletions

View File

@ -2,8 +2,10 @@
var Cesium = require('cesium'); var Cesium = require('cesium');
var fsExtra = require('fs-extra'); var fsExtra = require('fs-extra');
var GltfPipeline = require('gltf-pipeline').Pipeline; var GltfPipeline = require('gltf-pipeline').Pipeline;
var os = require('os');
var path = require('path'); var path = require('path');
var Promise = require('bluebird'); var Promise = require('bluebird');
var uuid = require('uuid');
var createGltf = require('./createGltf'); var createGltf = require('./createGltf');
var loadObj = require('./loadObj'); var loadObj = require('./loadObj');
var writeUris = require('./writeUris'); var writeUris = require('./writeUris');
@ -77,7 +79,6 @@ function obj2gltf(objPath, gltfPath, options) {
} }
var extension = path.extname(gltfPath).toLowerCase(); var extension = path.extname(gltfPath).toLowerCase();
var basePath = path.dirname(gltfPath);
var modelName = path.basename(gltfPath, path.extname(gltfPath)); var modelName = path.basename(gltfPath, path.extname(gltfPath));
if (extension === '.glb') { if (extension === '.glb') {
binary = true; binary = true;
@ -88,13 +89,14 @@ function obj2gltf(objPath, gltfPath, options) {
} }
gltfPath = path.join(path.dirname(gltfPath), modelName + extension); gltfPath = path.join(path.dirname(gltfPath), modelName + extension);
var resourcesDirectory = options.bypassPipeline ? path.dirname(gltfPath) : obj2gltf._getTempDirectory();
var aoOptions = ao ? {} : undefined; var aoOptions = ao ? {} : undefined;
var kmcOptions = kmc ? {} : undefined; var kmcOptions = kmc ? {} : undefined;
var pipelineOptions = { var pipelineOptions = {
createDirectory : false, createDirectory : false,
basePath : basePath, basePath : resourcesDirectory,
binary : binary, binary : binary,
embed : !separate, embed : !separate,
embedImage : !separateTextures, embedImage : !separateTextures,
@ -114,7 +116,7 @@ function obj2gltf(objPath, gltfPath, options) {
return createGltf(objData); return createGltf(objData);
}) })
.then(function(gltf) { .then(function(gltf) {
return writeUris(gltf, gltfPath, options); return writeUris(gltf, gltfPath, resourcesDirectory, options);
}) })
.then(function(gltf) { .then(function(gltf) {
if (bypassPipeline) { if (bypassPipeline) {
@ -122,9 +124,21 @@ function obj2gltf(objPath, gltfPath, options) {
} else { } else {
return GltfPipeline.processJSONToDisk(gltf, gltfPath, pipelineOptions); return GltfPipeline.processJSONToDisk(gltf, gltfPath, pipelineOptions);
} }
})
.finally(function() {
return cleanup(resourcesDirectory, options);
}); });
} }
function cleanup(resourcesDirectory, options) {
if (!options.bypassPipeline && options.separate) {
fsExtra.remove(resourcesDirectory, function () {
// Don't fail simply because we couldn't
// clean up the temporary files.
});
}
}
/** /**
* Default values that will be used when calling obj2gltf(options) unless specified in the options object. * Default values that will be used when calling obj2gltf(options) unless specified in the options object.
*/ */
@ -229,6 +243,15 @@ obj2gltf.defaults = {
*/ */
obj2gltf._outputJson = fsExtraOutputJson; obj2gltf._outputJson = fsExtraOutputJson;
/**
* Exposed for testing
*
* @private
*/
obj2gltf._getTempDirectory = function () {
return path.join(os.tmpdir(), uuid());
};
/** /**
* A callback function that logs messages. * A callback function that logs messages.
* @callback Logger * @callback Logger

View File

@ -16,6 +16,7 @@ module.exports = writeUris;
* *
* @param {Object} gltf The glTF asset. * @param {Object} gltf The glTF asset.
* @param {String} gltfPath Path where the glTF will be saved. * @param {String} gltfPath Path where the glTF will be saved.
* @param {String} resourcesDirectory Path where separate resources will be saved.
* @param {Object} options An object with the following properties: * @param {Object} options An object with the following properties:
* @param {Boolean} options.separate Writes out separate buffers. * @param {Boolean} options.separate Writes out separate buffers.
* @param {Boolean} options.separateTextures Write out separate textures only. * @param {Boolean} options.separateTextures Write out separate textures only.
@ -23,7 +24,7 @@ module.exports = writeUris;
* *
* @private * @private
*/ */
function writeUris(gltf, gltfPath, options) { function writeUris(gltf, gltfPath, resourcesDirectory, options) {
var separate = options.separate; var separate = options.separate;
var separateTextures = options.separateTextures; var separateTextures = options.separateTextures;
@ -44,17 +45,19 @@ function writeUris(gltf, gltfPath, options) {
var exceedsMaximum = (texturesByteLength + bufferByteLength > 201326580); var exceedsMaximum = (texturesByteLength + bufferByteLength > 201326580);
if (exceedsMaximum && !separate) { if (exceedsMaximum && !separate) {
return Promise.reject(new RuntimeError('Buffers and textures are too large to encode in the glTF, saving as separate resources.')); return Promise.reject(new RuntimeError('Buffers and textures are too large to encode in the glTF. Use the --separate flag instead.'));
} }
var name = path.basename(gltfPath, path.extname(gltfPath));
if (separate) { if (separate) {
promises.push(writeSeparateBuffer(gltf, gltfPath)); promises.push(writeSeparateBuffer(gltf, resourcesDirectory, name));
} else { } else {
writeEmbeddedBuffer(gltf); writeEmbeddedBuffer(gltf);
} }
if (separateTextures) { if (separateTextures) {
promises.push(writeSeparateTextures(gltf, gltfPath)); promises.push(writeSeparateTextures(gltf, resourcesDirectory));
} else { } else {
writeEmbeddedTextures(gltf); writeEmbeddedTextures(gltf);
} }
@ -79,24 +82,23 @@ function deleteExtras(gltf) {
} }
} }
function writeSeparateBuffer(gltf, gltfPath) { function writeSeparateBuffer(gltf, resourcesDirectory, name) {
var buffer = gltf.buffers[Object.keys(gltf.buffers)[0]]; var buffer = gltf.buffers[Object.keys(gltf.buffers)[0]];
var source = buffer.extras._obj2gltf.source; var source = buffer.extras._obj2gltf.source;
var bufferName = path.basename(gltfPath, path.extname(gltfPath)); var bufferUri = name + '.bin';
var bufferUri = bufferName + '.bin';
buffer.uri = bufferUri; buffer.uri = bufferUri;
var bufferPath = path.join(path.dirname(gltfPath), bufferUri); var bufferPath = path.join(resourcesDirectory, bufferUri);
return writeUris._outputFile(bufferPath, source); return writeUris._outputFile(bufferPath, source);
} }
function writeSeparateTextures(gltf, gltfPath) { function writeSeparateTextures(gltf, resourcesDirectory) {
var images = gltf.images; var images = gltf.images;
return Promise.map(Object.keys(images), function(id) { return Promise.map(Object.keys(images), function(id) {
var image = images[id]; var image = images[id];
var extras = image.extras._obj2gltf; var extras = image.extras._obj2gltf;
var imageUri = image.name + extras.extension; var imageUri = image.name + extras.extension;
image.uri = imageUri; image.uri = imageUri;
var imagePath = path.join(path.dirname(gltfPath), imageUri); var imagePath = path.join(resourcesDirectory, imageUri);
return writeUris._outputFile(imagePath, extras.source); return writeUris._outputFile(imagePath, extras.source);
}, {concurrency : 10}); }, {concurrency : 10});
} }

View File

@ -33,6 +33,7 @@
"gltf-pipeline": "^0.1.0-alpha11", "gltf-pipeline": "^0.1.0-alpha11",
"mime": "^1.3.4", "mime": "^1.3.4",
"pngjs": "^3.0.1", "pngjs": "^3.0.1",
"uuid": "^3.0.1",
"yargs": "^7.0.1" "yargs": "^7.0.1"
}, },
"devDependencies": { "devDependencies": {

View File

@ -70,7 +70,7 @@ describe('createGltf', function() {
it('simple gltf', function(done) { it('simple gltf', function(done) {
var gltf = createGltf(boxObjData); var gltf = createGltf(boxObjData);
expect(writeUris(gltf, boxGltfUrl, defaultOptions) expect(writeUris(gltf, boxGltfUrl, path.dirname(boxGltfUrl), defaultOptions)
.then(function() { .then(function() {
expect(gltf).toEqual(boxGltf); expect(gltf).toEqual(boxGltf);
}), done).toResolve(); }), done).toResolve();
@ -79,7 +79,7 @@ describe('createGltf', function() {
it('multiple nodes, meshes, and primitives', function(done) { it('multiple nodes, meshes, and primitives', function(done) {
var gltf = createGltf(groupObjData); var gltf = createGltf(groupObjData);
expect(writeUris(gltf, groupGltfUrl, defaultOptions) expect(writeUris(gltf, groupGltfUrl, path.dirname(groupGltfUrl), defaultOptions)
.then(function() { .then(function() {
expect(gltf).toEqual(groupGltf); expect(gltf).toEqual(groupGltf);
expect(Object.keys(gltf.materials).length).toBe(3); expect(Object.keys(gltf.materials).length).toBe(3);

View File

@ -64,6 +64,10 @@ function getImagePath(objPath, relativePath) {
var defaultOptions = obj2gltf.defaults; var defaultOptions = obj2gltf.defaults;
describe('loadObj', function() { describe('loadObj', function() {
beforeEach(function() {
spyOn(console, 'log');
});
it('loads obj with positions, normals, and uvs', function(done) { it('loads obj with positions, normals, and uvs', function(done) {
expect(loadObj(objUrl, defaultOptions) expect(loadObj(objUrl, defaultOptions)
.then(function(data) { .then(function(data) {
@ -272,7 +276,6 @@ describe('loadObj', function() {
}); });
it('loads obj with missing mtllib', function(done) { it('loads obj with missing mtllib', function(done) {
spyOn(console, 'log');
expect(loadObj(objMissingMtllibUrl, defaultOptions) expect(loadObj(objMissingMtllibUrl, defaultOptions)
.then(function(data) { .then(function(data) {
expect(data.materials).toEqual({}); expect(data.materials).toEqual({});
@ -290,8 +293,6 @@ describe('loadObj', function() {
}); });
it('does not load resources outside of the obj directory when secure is true', function(done) { it('does not load resources outside of the obj directory when secure is true', function(done) {
spyOn(console, 'log');
var options = clone(defaultOptions); var options = clone(defaultOptions);
options.secure = true; options.secure = true;
@ -316,7 +317,6 @@ describe('loadObj', function() {
}); });
it('loads obj with missing texture', function(done) { it('loads obj with missing texture', function(done) {
spyOn(console, 'log');
expect(loadObj(objMissingTextureUrl, defaultOptions) expect(loadObj(objMissingTextureUrl, defaultOptions)
.then(function(data) { .then(function(data) {
var imagePath = getImagePath(objMissingTextureUrl, 'cesium.png'); var imagePath = getImagePath(objMissingTextureUrl, 'cesium.png');

View File

@ -1,6 +1,9 @@
'use strict'; 'use strict';
var fsExtra = require('fs-extra');
var GltfPipeline = require('gltf-pipeline').Pipeline; var GltfPipeline = require('gltf-pipeline').Pipeline;
var os = require('os');
var path = require('path'); var path = require('path');
var Promise = require('bluebird');
var obj2gltf = require('../../lib/obj2gltf'); var obj2gltf = require('../../lib/obj2gltf');
var writeUris = require('../../lib/writeUris'); var writeUris = require('../../lib/writeUris');
@ -10,28 +13,34 @@ var glbPath = 'specs/data/box-textured/box-textured.glb';
var objPathNonExistent = 'specs/data/non-existent.obj'; var objPathNonExistent = 'specs/data/non-existent.obj';
describe('obj2gltf', function() { describe('obj2gltf', function() {
var tempDirectory;
beforeAll(function() {
expect(obj2gltf._getTempDirectory()).toContain(os.tmpdir());
tempDirectory = path.join(os.tmpdir(), 'testPath');
spyOn(obj2gltf, '_getTempDirectory').and.returnValue(tempDirectory);
spyOn(obj2gltf, '_outputJson');
spyOn(writeUris, '_outputFile');
spyOn(fsExtra, 'remove');
});
beforeEach(function() {
spyOn(GltfPipeline, 'processJSONToDisk').and.returnValue(Promise.resolve());
});
it('converts an obj to gltf', function(done) { it('converts an obj to gltf', function(done) {
var spy = spyOn(GltfPipeline, 'processJSONToDisk');
expect(obj2gltf(objPath, gltfPath) expect(obj2gltf(objPath, gltfPath)
.then(function() { .then(function() {
var args = spy.calls.first().args; var args = GltfPipeline.processJSONToDisk.calls.first().args;
var gltf = args[0]; var gltf = args[0];
var outputPath = args[1]; var outputPath = args[1];
var options = args[2];
expect(path.normalize(outputPath)).toEqual(path.normalize(gltfPath)); expect(path.normalize(outputPath)).toEqual(path.normalize(gltfPath));
expect(gltf).toBeDefined(); expect(gltf).toBeDefined();
expect(gltf.images.cesium).toBeDefined(); expect(gltf.images.cesium).toBeDefined();
}), done).toResolve();
});
it('uses default gltf-pipeline options', function(done) {
var spy = spyOn(GltfPipeline, 'processJSONToDisk');
expect(obj2gltf(objPath, gltfPath)
.then(function() {
var args = spy.calls.first().args;
var options = args[2];
expect(options).toEqual({ expect(options).toEqual({
basePath : tempDirectory,
createDirectory : false, createDirectory : false,
basePath : path.dirname(objPath),
binary : false, binary : false,
embed : true, embed : true,
embedImage : true, embedImage : true,
@ -49,8 +58,6 @@ describe('obj2gltf', function() {
}); });
it('sets options', function(done) { it('sets options', function(done) {
var spy = spyOn(GltfPipeline, 'processJSONToDisk');
spyOn(writeUris, '_outputFile');
var textureCompressionOptions = { var textureCompressionOptions = {
format : 'dxt1', format : 'dxt1',
quality : 10 quality : 10
@ -75,11 +82,11 @@ describe('obj2gltf', function() {
expect(obj2gltf(objPath, gltfPath, options) expect(obj2gltf(objPath, gltfPath, options)
.then(function() { .then(function() {
var args = spy.calls.first().args; var args = GltfPipeline.processJSONToDisk.calls.first().args;
var options = args[2]; var options = args[2];
expect(options).toEqual({ expect(options).toEqual({
basePath : tempDirectory,
createDirectory : false, createDirectory : false,
basePath : path.dirname(objPath),
binary : true, binary : true,
embed : false, embed : false,
embedImage : false, embedImage : false,
@ -98,18 +105,15 @@ describe('obj2gltf', function() {
}); });
it('saves as binary if gltfPath has a .glb extension', function(done) { it('saves as binary if gltfPath has a .glb extension', function(done) {
var spy = spyOn(GltfPipeline, 'processJSONToDisk');
expect(obj2gltf(objPath, glbPath) expect(obj2gltf(objPath, glbPath)
.then(function() { .then(function() {
var args = spy.calls.first().args; var args = GltfPipeline.processJSONToDisk.calls.first().args;
var options = args[2]; var options = args[2];
expect(options.binary).toBe(true); expect(options.binary).toBe(true);
}), done).toResolve(); }), done).toResolve();
}); });
it('bypassPipeline flag bypasses gltf-pipeline', function(done) { it('bypassPipeline flag bypasses gltf-pipeline', function(done) {
spyOn(obj2gltf, '_outputJson');
spyOn(GltfPipeline, 'processJSONToDisk');
var options = { var options = {
bypassPipeline : true bypassPipeline : true
}; };