From 416662ad0a0c1e3f795ef93d0a81e6ce40a6711a Mon Sep 17 00:00:00 2001 From: Emmanuel Viala Date: Sun, 7 Feb 2021 23:56:51 +0100 Subject: [PATCH] Preliminary nodejs compatibility (#68) --- examples/package.json | 3 +- experiments/package-lock.json | 63 ++++++++++++++++- experiments/package.json | 5 ++ experiments/src/node/.eslintrc.js | 17 +++++ experiments/src/node/generateGLTF.js | 85 +++++++++++++++++++++++ library/src/LocalReader/ArchiveParser.js | 9 +++ library/src/T3DLib.js | 3 +- library/src/dataRenderer/HavokRenderer.js | 2 +- 8 files changed, 182 insertions(+), 5 deletions(-) create mode 100644 experiments/src/node/.eslintrc.js create mode 100644 experiments/src/node/generateGLTF.js diff --git a/examples/package.json b/examples/package.json index 7b5af16c..bdf39320 100644 --- a/examples/package.json +++ b/examples/package.json @@ -23,5 +23,6 @@ "prettier": "^2.1.2", "vinyl-buffer": "^1.0.1", "vinyl-source-stream": "^2.0.0" - } + }, + "dependencies": {} } diff --git a/experiments/package-lock.json b/experiments/package-lock.json index e2083fef..a6f112ca 100644 --- a/experiments/package-lock.json +++ b/experiments/package-lock.json @@ -115,6 +115,16 @@ "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", "dev": true }, + "@types/node": { + "version": "9.6.61", + "resolved": "https://registry.npmjs.org/@types/node/-/node-9.6.61.tgz", + "integrity": "sha512-/aKAdg5c8n468cYLy2eQrcR5k6chlbNwZNGUj3TboyPa2hcO2QAJcfymlqPzMiRj8B6nYKXjzQz36minFE0RwQ==" + }, + "@types/tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/@types/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha1-EHPEvIJHVK49EM+riKsCN7qWTk0=" + }, "JSONStream": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", @@ -791,8 +801,7 @@ "buffer-from": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", - "dev": true + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" }, "buffer-xor": { "version": "1.0.3", @@ -1776,6 +1785,11 @@ "integrity": "sha512-3Zmiobend8P9DjmKAty0Era4jV8oJ0yGYe2nJJAxgymF9+N8F2m0hhZiMoWtcfepExzNKZumFU3ksdQbInGWCg==", "dev": true }, + "eventtarget": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/eventtarget/-/eventtarget-0.1.0.tgz", + "integrity": "sha1-Hr3XKj3PuwIY4W1RRQlAzf/qTiY=" + }, "evp_bytestokey": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", @@ -4163,6 +4177,11 @@ "lcid": "^1.0.0" } }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" + }, "pako": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", @@ -4935,6 +4954,22 @@ "urix": "^0.1.0" } }, + "source-map-support": { + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, "source-map-url": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", @@ -5277,6 +5312,14 @@ "next-tick": "1" } }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "requires": { + "os-tmpdir": "~1.0.2" + } + }, "to-absolute-glob": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz", @@ -5595,6 +5638,17 @@ "integrity": "sha1-HCQ6ULWVwb5Up1S/7OhWO5/42BM=", "dev": true }, + "vblob": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/vblob/-/vblob-1.0.2.tgz", + "integrity": "sha512-7ZexHDhnlKNbySsYUxdlZCafvVLI8xpxOfjfSnW6HDooyJFjCF+Rw4vejhL3KeDWoDkuvoEhexRE+97GXTHW0g==", + "requires": { + "@types/node": "^9.4.0", + "@types/tmp": "0.0.33", + "eventtarget": "^0.1.0", + "tmp": "0.0.33" + } + }, "vinyl": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.0.tgz", @@ -5700,6 +5754,11 @@ "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==", "dev": true }, + "web-worker": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/web-worker/-/web-worker-1.0.0.tgz", + "integrity": "sha512-BzuMqeKVkKKwHV6tJuwePFcxYMxvC97D448mXTgh/CxXAB4sRtoV26gRPN+JDxsXRR7QZyioMV9O6NzQaASf7Q==" + }, "which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", diff --git a/experiments/package.json b/experiments/package.json index d4d96191..bfc81328 100644 --- a/experiments/package.json +++ b/experiments/package.json @@ -23,5 +23,10 @@ "prettier": "^2.1.2", "vinyl-buffer": "^1.0.1", "vinyl-source-stream": "^2.0.0" + }, + "dependencies": { + "source-map-support": "^0.5.19", + "vblob": "^1.0.2", + "web-worker": "^1.0.0" } } diff --git a/experiments/src/node/.eslintrc.js b/experiments/src/node/.eslintrc.js new file mode 100644 index 00000000..7c488ccd --- /dev/null +++ b/experiments/src/node/.eslintrc.js @@ -0,0 +1,17 @@ +module.exports = { + env: { + node: true, + }, + extends: ["eslint:recommended"], + parserOptions: { + ecmaVersion: 2018, + }, + rules: { + "no-tabs": "error", + camelcase: 0, + "no-var": "error", + eqeqeq: "error", + semi: ["error", "always"], + "prefer-const": "error", + }, +}; diff --git a/experiments/src/node/generateGLTF.js b/experiments/src/node/generateGLTF.js new file mode 100644 index 00000000..0f060a1c --- /dev/null +++ b/experiments/src/node/generateGLTF.js @@ -0,0 +1,85 @@ +/** + * cli example: + * - node ./src/node/generateGLTF.js "path/to/Gw2.dat" "outputPath" mapId + * (186397 - snowden drifts) + */ + +const DataStream = require("../../dist/static/DataStream"); +global.DataStream = DataStream; + +const { Blob, FileReader } = require("vblob"); +global.Blob = Blob; +global.FileReader = FileReader; +global.window = {}; +global.window.FileReader = FileReader; + +const THREE = require("../../dist/static/three"); +global.THREE = THREE; +require("../../dist/static/GLTFExporter"); + +const Worker = require("web-worker"); +global.Worker = Worker; + +const fs = require("fs"); +global.fs = fs; + +const T3D = require("../../../library/src/T3DLib"); +global.T3D = T3D; + +if (process.argv.length < 4) { + console.log("Missing arguments. Expected: filePath, outputFolder, mapId"); + process.exit(1); +} + +const filePath = process.argv[2]; +const outputFolder = process.argv[3]; +const mapId = Number.parseInt(process.argv[4]); +if (isNaN(mapId) || mapId < 0) { + console.log("The mapId is not valid"); + process.exit(1); +} + +T3D.getLocalReader( + filePath, + async (lr) => { + console.log("Loaded!"); + const renderers = [ + { + renderClass: T3D.EnvironmentRenderer, + settings: {}, + }, + { + renderClass: T3D.TerrainRenderer, + settings: { + export: true, + }, + }, + { + renderClass: T3D.HavokRenderer, + settings: { + export: true, + }, + }, + ]; + T3D.renderMapContentsAsync(lr, mapId, renderers, (context) => { + console.log("Map loaded !"); + const scene = new THREE.Scene(); + for (const elem of T3D.getContextValue(context, T3D.TerrainRenderer, "terrainTiles")) { + scene.add(elem); + } + for (const elem of T3D.getContextValue(context, T3D.HavokRenderer, "meshes")) { + scene.add(elem); + } + + console.log("Scene loaded !"); + + const exporter = new THREE.GLTFExporter(); + exporter.parse(scene, (gltf) => { + fs.writeFileSync(`${outputFolder}/${mapId}.gltf`, JSON.stringify(gltf)); + process.exit(0); + }); + }); + }, + "./dist/static/t3dworker.js", + false +); diff --git a/library/src/LocalReader/ArchiveParser.js b/library/src/LocalReader/ArchiveParser.js index 89055ab1..8c7c5001 100644 --- a/library/src/LocalReader/ArchiveParser.js +++ b/library/src/LocalReader/ArchiveParser.js @@ -193,6 +193,15 @@ function parseMFTIndex(ds, size) { * @returns {Promise<{ds: DataStream, len: number}>} */ function getFilePart(file, offset, length) { + // Node compatibility workaround + if (global.process && global.fs) { + const fd = global.fs.openSync(file); + const buffer = global.Buffer.alloc(length); + const readLen = global.fs.readSync(fd, buffer, 0, length, offset); + const ds = new DataStream(buffer); + ds.endianness = DataStream.LITTLE_ENDIAN; + return { ds, len: readLen }; + } return new Promise((resolve, reject) => { const reader = new FileReader(); diff --git a/library/src/T3DLib.js b/library/src/T3DLib.js index 023a0d33..072e4e30 100644 --- a/library/src/T3DLib.js +++ b/library/src/T3DLib.js @@ -274,13 +274,14 @@ const T3D = (module.exports = { * will not be fully initialized until the callback * is fired. */ - getLocalReader: function (file, callback, t3dtoolsWorker) { + getLocalReader: function (file, callback, t3dtoolsWorker, noIndexedDB) { const path = t3dtoolsWorker || _settings.t3dtoolsWorker; // Create the instance and init the threads const lrInstance = new LocalReader({ workerPath: path, workersNb: _settings.concurrentTasks, + noIndexedDB, }); /// Callback with the lrInstance diff --git a/library/src/dataRenderer/HavokRenderer.js b/library/src/dataRenderer/HavokRenderer.js index e748a267..25f92267 100644 --- a/library/src/dataRenderer/HavokRenderer.js +++ b/library/src/dataRenderer/HavokRenderer.js @@ -116,7 +116,7 @@ class HavokRenderer extends DataRenderer { } if (i < models.length) { - window.setTimeout( + setTimeout( this.parseAllModels.bind(this, models, mat, title, chunkSize, offset + chunkSize, callback), 10 /* time in ms to next call */ );