diff --git a/app/scripts/glbopti.js b/app/scripts/glbopti.js new file mode 100644 index 00000000..7f66e45b --- /dev/null +++ b/app/scripts/glbopti.js @@ -0,0 +1,104 @@ +const { NodeIO, Extension } = require('@gltf-transform/core'); +const { KHRONOS_EXTENSIONS } = require('@gltf-transform/extensions'); +const { textureCompress, simplify, weld, draco } = require('@gltf-transform/functions'); +const { MeshoptSimplifier } = require('meshoptimizer'); +const draco3d = require('draco3dgltf'); + +class CesiumRTC extends Extension { + extensionName = 'CESIUM_RTC'; + static EXTENSION_NAME = 'CESIUM_RTC'; + + read(context) { + const rtc = context.jsonDoc.json.extensions?.CESIUM_RTC; + if (rtc) { + this.rtc = rtc; + } + } + + write(context) { + if (this.rtc){ + context.jsonDoc.json.extensions = context.jsonDoc.json.extensions || {}; + context.jsonDoc.json.extensions.CESIUM_RTC = this.rtc; + } + } +} + +async function main() { + const io = new NodeIO().registerExtensions(KHRONOS_EXTENSIONS) + .registerExtensions([CesiumRTC]) + .registerDependencies({ + 'draco3d.decoder': await draco3d.createDecoderModule(), + 'draco3d.encoder': await draco3d.createEncoderModule(), + }); + + const args = process.argv.slice(2); + let inputFile = ''; + let outputFile = ''; + let textureSize = 512; + let simplifyRatio = 1; + + for (let i = 0; i < args.length; i++) { + if (args[i] === '--input' && i + 1 < args.length) { + inputFile = args[i + 1]; + i++; + } else if (args[i] === '--output' && i + 1 < args.length) { + outputFile = args[i + 1]; + i++; + } else if (args[i] === '--texture-size' && i + 1 < args.length) { + textureSize = parseInt(args[i + 1]); + if (isNaN(textureSize) || textureSize < 1){ + console.log(`Invalid texture size: ${args[i + 1]}`); + process.exit(1); + } + i++; + } else if (args[i] === '--simplify-ratio' && i + 1 < args.length) { + simplifyRatio = parseFloat(args[i + 1]); + if (isNaN(simplifyRatio) || simplifyRatio < 0 || simplifyRatio > 1){ + console.log(`Invalid simplify ratio: ${args[i + 1]}`); + process.exit(1); + } + i++; + } + + } + + if (!inputFile || !outputFile){ + console.log('Usage: node glb_optimize.js --input --output [--texture-size ]'); + process.exit(1); + } + + const encoder = require('sharp'); + + let transforms = [ + textureCompress({ + encoder, + resize: [textureSize, textureSize], + targetFormat: undefined, + limitInputPixels: true, + }), + draco({ + quantizationVolume: "scene" + }) + ] + + if (simplifyRatio < 1){ + transforms.unshift( + simplify({ + simplifier: MeshoptSimplifier, + error: 0.0001, + ratio: simplifyRatio, + lockBorder: false, + }), + ); + transforms.unshift(weld()); + } + + const document = await io.read(inputFile); + await document.transform(...transforms); + await io.write(outputFile, document); +} + +main().catch((e) => { + console.error(e); + process.exit(1); +}); \ No newline at end of file diff --git a/package.json b/package.json index c37f73c4..9342ee58 100644 --- a/package.json +++ b/package.json @@ -27,15 +27,19 @@ "@babel/preset-env": "^7.0.0-beta.54", "@babel/preset-react": "^7.0.0-beta.54", "@babel/runtime": "^7.4.5", + "@gltf-transform/extensions": "^4.2.1", + "@gltf-transform/functions": "^4.2.1", "async": "^2.1.2", "babel-core": "^7.0.0-bridge.0", "babel-jest": "^23.4.0", "babel-loader": "^8.0.0-beta.4", + "buffer": "^6.0.3", + "cheerio": "1.0.0-rc.6", "clipboard": "^1.7.1", "css-loader": "^0.25.0", "d3": "^3.5.5", + "draco3dgltf": "^1.5.7", "enzyme": "^3.3.0", - "cheerio": "1.0.0-rc.6", "enzyme-adapter-react-16": "^1.15.1", "exifr": "^6.0.0", "fbemitter": "^2.1.1", @@ -48,6 +52,8 @@ "json-loader": "^0.5.4", "leaflet": "1.3.1", "leaflet-fullscreen": "^1.0.2", + "meshoptimizer": "^0.25.0", + "mini-css-extract-plugin": "1.6.2", "object.values": "^1.0.3", "proj4": "^2.4.3", "qrcode.react": "^0.7.2", @@ -69,8 +75,6 @@ "url-loader": "^0.5.7", "webpack": "5.89.0", "webpack-bundle-tracker": "0.4.3", - "webpack-livereload-plugin": "3.0.2", - "mini-css-extract-plugin": "1.6.2", - "buffer": "^6.0.3" + "webpack-livereload-plugin": "3.0.2" } }