obj2gltf/lib/convert.js

170 lines
6.0 KiB
JavaScript
Raw Normal View History

2017-03-13 15:28:51 -04:00
'use strict';
var Cesium = require('cesium');
var fsExtra = require('fs-extra');
var GltfPipeline = require('gltf-pipeline').Pipeline;
2017-03-13 15:28:51 -04:00
var path = require('path');
var Promise = require('bluebird');
2016-06-09 13:33:08 -04:00
var createGltf = require('./gltf');
2017-03-13 15:28:51 -04:00
var loadObj = require('./obj');
var fsExtraOutputFile = Promise.promisify(fsExtra.outputFile);
2017-03-13 15:28:51 -04:00
var fsExtraOutputJson = Promise.promisify(fsExtra.outputJson);
2016-06-09 13:33:08 -04:00
var defaultValue = Cesium.defaultValue;
2017-03-13 15:28:51 -04:00
var defined = Cesium.defined;
var DeveloperError = Cesium.DeveloperError;
2016-06-09 13:33:08 -04:00
module.exports = convert;
2017-03-13 15:28:51 -04:00
/**
* Converts an obj file to a glTF file.
*
* @param {String} objPath Path to the obj file.
* @param {String} gltfPath Path of the converted glTF file.
* @param {Object} [options] An object with the following properties:
* @param {Boolean} [options.binary=false] Save as binary glTF.
* @param {Boolean} [options.separate=false] Writes out separate geometry data files, shader files, and textures instead of embedding them in the glTF.
2017-03-13 15:28:51 -04:00
* @param {Boolean} [options.separateTextures=false] Write out separate textures only.
* @param {Boolean} [options.compress=false] Quantize positions, compress texture coordinates, and oct-encode normals.
* @param {Boolean} [options.optimize=false] Use the optimization stages in the glTF pipeline.
* @param {Boolean} [options.optimizeForCesium=false] Optimize the glTF for Cesium by using the sun as a default light source.
* @param {Boolean} [options.generateNormals=false] Generate normals if they are missing.
* @param {Boolean} [options.ao=false] Apply ambient occlusion to the converted model.
* @param {Boolean} [options.textureCompressionOptions] Options sent to the compressTextures stage of gltf-pipeline.
* @param {Boolean} [options.bypassPipeline=false] Bypass the gltf-pipeline for debugging purposes. This option overrides many of the options above and will save the glTF with the KHR_materials_common extension.
*/
function convert(objPath, gltfPath, options) {
options = defaultValue(options, defaultValue.EMPTY_OBJECT);
2016-06-09 13:33:08 -04:00
var binary = defaultValue(options.binary, false);
2017-03-13 15:28:51 -04:00
var separate = defaultValue(options.separate, false);
var separateTextures = defaultValue(options.separateTextures, false) || separate;
var compress = defaultValue(options.compress, false);
2017-03-13 15:28:51 -04:00
var optimize = defaultValue(options.optimize, false);
var optimizeForCesium = defaultValue(options.optimizeForCesium, false);
2017-03-13 15:28:51 -04:00
var generateNormals = defaultValue(options.generateNormals, false);
var ao = defaultValue(options.ao, false);
var textureCompressionOptions = options.textureCompressionOptions;
var bypassPipeline = defaultValue(options.bypassPipeline, false);
2016-06-09 13:33:08 -04:00
2017-03-13 15:28:51 -04:00
if (!defined(objPath)) {
throw new DeveloperError('objPath is required');
2016-06-09 13:33:08 -04:00
}
2017-03-13 15:28:51 -04:00
if (!defined(gltfPath)) {
throw new DeveloperError('gltfPath is required');
2016-06-09 13:33:08 -04:00
}
2017-03-13 15:28:51 -04:00
var basePath = path.dirname(objPath);
var modelName = path.basename(objPath, path.extname(objPath));
var extension = path.extname(gltfPath);
if (extension === '.glb') {
binary = true;
2016-06-09 13:33:08 -04:00
}
2017-03-13 15:28:51 -04:00
gltfPath = path.join(path.dirname(gltfPath), modelName + extension);
var aoOptions = ao ? {} : undefined;
2016-06-09 13:33:08 -04:00
2017-03-13 15:28:51 -04:00
var pipelineOptions = {
createDirectory : false,
basePath : basePath,
binary : binary,
embed : !separate,
embedImage : !separateTextures,
2017-03-13 15:28:51 -04:00
quantize : compress,
compressTextureCoordinates : compress,
encodeNormals : compress,
preserve : !optimize,
optimizeForCesium : optimizeForCesium,
smoothNormals : generateNormals,
aoOptions : aoOptions,
textureCompressionOptions : textureCompressionOptions
};
2016-06-09 13:33:08 -04:00
2017-03-13 15:28:51 -04:00
return loadObj(objPath)
.then(function(objData) {
return createGltf(objData);
2016-07-22 14:09:13 -04:00
})
.then(function(gltf) {
return writeSeparateResources(gltf, gltfPath, separate, separateTextures);
2017-03-13 15:28:51 -04:00
})
.then(function(gltf) {
if (bypassPipeline) {
return convert._outputJson(gltfPath, gltf);
} else {
return GltfPipeline.processJSONToDisk(gltf, gltfPath, pipelineOptions);
}
});
}
function deleteExtras(gltf) {
2017-03-13 15:28:51 -04:00
var buffer = gltf.buffers[Object.keys(gltf.buffers)[0]];
delete buffer.extras;
var images = gltf.images;
for (var id in images) {
if (images.hasOwnProperty(id)) {
var image = images[id];
delete image.extras;
}
2017-03-13 15:28:51 -04:00
}
}
2017-03-13 15:28:51 -04:00
function writeSeparateBuffer(gltf, gltfPath) {
var buffer = gltf.buffers[Object.keys(gltf.buffers)[0]];
var source = buffer.extras._obj2gltf.source;
2017-03-13 15:28:51 -04:00
var bufferName = path.basename(gltfPath, path.extname(gltfPath));
var bufferUri = bufferName + '.bin';
buffer.uri = bufferUri;
var bufferPath = path.join(path.dirname(gltfPath), bufferUri);
return convert._outputFile(bufferPath, source);
}
function writeSeparateTextures(gltf, gltfPath) {
var promises = [];
var images = gltf.images;
for (var id in images) {
if (images.hasOwnProperty(id)) {
var image = images[id];
var extras = image.extras._obj2gltf;
var imageUri = image.name + extras.extension;
image.uri = imageUri;
var imagePath = path.join(path.dirname(gltfPath), imageUri);
promises.push(convert._outputFile(imagePath, extras.source));
}
}
return Promise.all(promises);
}
function writeSeparateResources(gltf, gltfPath, separate, separateTextures) {
var promises = [];
var buffer = gltf.buffers[Object.keys(gltf.buffers)[0]];
if (separate || !defined(buffer.uri)) {
promises.push(writeSeparateBuffer(gltf, gltfPath));
}
if (separateTextures) {
promises.push(writeSeparateTextures(gltf, gltfPath));
}
deleteExtras(gltf);
return Promise.all(promises)
2017-03-13 15:28:51 -04:00
.then(function() {
return gltf;
2016-06-09 13:33:08 -04:00
});
}
/**
* Exposed for testing
*
* @private
*/
convert._outputJson = fsExtraOutputJson;
/**
* Exposed for testing
*
* @private
*/
convert._outputFile = fsExtraOutputFile;