chore: import upstream snapshot with attribution
This commit is contained in:
+5
@@ -0,0 +1,5 @@
|
||||
# ChangeLOG
|
||||
|
||||
## 1.0.0
|
||||
|
||||
- 发包正式包
|
||||
Vendored
+21
@@ -0,0 +1,21 @@
|
||||
The MIT License
|
||||
|
||||
Copyright © 2026 MANYCORE, INC.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
Vendored
+22
@@ -0,0 +1,22 @@
|
||||
# splat-dev-server
|
||||
|
||||
A 3DGS dev server
|
||||
|
||||
## Requirement
|
||||
|
||||
- node >= 22.22.1
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
npm install @manycore/aholo-splat-dev-server -g
|
||||
|
||||
splat-dev-server [options] <dir>
|
||||
|
||||
Options:
|
||||
--help Show help [boolean]
|
||||
--version Show version number [boolean]
|
||||
-a, --address Address to listen [string] [default: "127.0.0.1"]
|
||||
-p, --port Port to listen [number] [default: 3000]
|
||||
```
|
||||
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import yargs from 'yargs/yargs';
|
||||
import { hideBin } from 'yargs/helpers';
|
||||
import { merge } from '../src/merge.js';
|
||||
import packageJson from '../package.json' with { type: 'json' }
|
||||
|
||||
const argv = yargs(hideBin(process.argv))
|
||||
.version(packageJson.version)
|
||||
.usage('merge-lod -i <meta-files...> -o <output_dir>')
|
||||
.option('input', {
|
||||
alias: 'i',
|
||||
array: true,
|
||||
type: 'string',
|
||||
demandOption: true,
|
||||
description: 'Input lod meta files(lod-meta.json)'
|
||||
})
|
||||
.option('output', {
|
||||
alias: 'o',
|
||||
type: 'string',
|
||||
demandOption: true,
|
||||
description: 'Output directory'
|
||||
})
|
||||
.argv;
|
||||
|
||||
merge(argv.input, argv.output);
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import yargs from 'yargs/yargs';
|
||||
import { hideBin } from 'yargs/helpers';
|
||||
import { start } from '../src/server.js';
|
||||
import packageJson from '../package.json' with { type: 'json' }
|
||||
|
||||
const argv = yargs(hideBin(process.argv))
|
||||
.version(packageJson.version)
|
||||
.usage('splat-dev-server [options] <dir>')
|
||||
.option('address', {
|
||||
alias: 'a',
|
||||
type: 'string',
|
||||
default: '127.0.0.1',
|
||||
describe: 'Address to listen'
|
||||
})
|
||||
.option('port', {
|
||||
alias: 'p',
|
||||
type: 'number',
|
||||
default: 3000,
|
||||
description: 'Port to listen'
|
||||
})
|
||||
.argv;
|
||||
|
||||
start(argv.address, argv.port, argv._[0]);
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"name": "@manycore/aholo-splat-dev-server",
|
||||
"version": "1.0.1",
|
||||
"description": "",
|
||||
"author": "egs",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/manycoretech/aholo-viewer.git",
|
||||
"directory": "external/splat-dev-server"
|
||||
},
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 22.22.1"
|
||||
},
|
||||
"keywords": [
|
||||
"aholo",
|
||||
"cli",
|
||||
"3d-gaussian-splatting",
|
||||
"gaussian-splatting",
|
||||
"server"
|
||||
],
|
||||
"type": "module",
|
||||
"bin": {
|
||||
"splat-dev-server": "bin/server.js",
|
||||
"merge-lod": "bin/merge.js"
|
||||
},
|
||||
"files": [
|
||||
"src/",
|
||||
"CHANGELOG.md"
|
||||
],
|
||||
"dependencies": {
|
||||
"express": "^5.2.1",
|
||||
"yargs": "^18.0.0"
|
||||
},
|
||||
"binary": {
|
||||
"napi_versions": [
|
||||
8
|
||||
]
|
||||
}
|
||||
}
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
import path from 'node:path';
|
||||
import fs from 'node:fs/promises';
|
||||
|
||||
function mergeBounds(bounds) {
|
||||
if (!bounds || bounds.length === 0) return { min: [0, 0, 0], max: [0, 0, 0] };
|
||||
const min = [
|
||||
Math.min(...bounds.map(b => b.min[0])),
|
||||
Math.min(...bounds.map(b => b.min[1])),
|
||||
Math.min(...bounds.map(b => b.min[2]))
|
||||
];
|
||||
|
||||
const max = [
|
||||
Math.max(...bounds.map(b => b.max[0])),
|
||||
Math.max(...bounds.map(b => b.max[1])),
|
||||
Math.max(...bounds.map(b => b.max[2]))
|
||||
];
|
||||
return { min, max };
|
||||
}
|
||||
|
||||
|
||||
export async function merge(input, output) {
|
||||
try {
|
||||
await fs.stat(output);
|
||||
} catch {
|
||||
await fs.mkdir(output, { recursive: true });
|
||||
}
|
||||
const meta = {
|
||||
magicCode: 0x262834,
|
||||
type: 'lod-splat',
|
||||
version: '1.0',
|
||||
counts: 0,
|
||||
shDegree: 0,
|
||||
levels: 5,
|
||||
forwardBox: { min: [0, 0, 0], max: [0, 0, 0] },
|
||||
files: [],
|
||||
permanentFiles: [],
|
||||
tree: [],
|
||||
};
|
||||
const inputMetaList = input.map(i => ({
|
||||
basedir: path.dirname(i),
|
||||
file: i,
|
||||
output: []
|
||||
}));
|
||||
let index = 0;
|
||||
for (const inputMeta of inputMetaList) {
|
||||
const data = JSON.parse(await fs.readFile(inputMeta.file, 'utf-8'));
|
||||
meta.counts += data.counts;
|
||||
meta.shDegree = Math.max(meta.shDegree, data.shDegree);
|
||||
meta.forwardBox = mergeBounds([meta.forwardBox, data.forwardBox]);
|
||||
const copyTasks = [];
|
||||
for (const file of data.files) {
|
||||
const name = `chunk_${index}${path.extname(file)}`;
|
||||
inputMeta.output.push(index);
|
||||
meta.files.push(name);
|
||||
index++;
|
||||
const i = path.join(inputMeta.basedir, file);
|
||||
const o = path.join(path.join(output, name));
|
||||
console.log(`${i} -> ${o}`);
|
||||
copyTasks.push(fs.copyFile(i, o));
|
||||
}
|
||||
for (const permanentFile of data.permanentFiles) {
|
||||
meta.permanentFiles.push(inputMeta.output[permanentFile]);
|
||||
}
|
||||
for (const node of data.tree) {
|
||||
meta.tree.push({
|
||||
bound: node.bound,
|
||||
lods: node.lods.map(l => ({
|
||||
...l,
|
||||
file: inputMeta.output[l.file]
|
||||
}))
|
||||
});
|
||||
}
|
||||
await Promise.all(copyTasks);
|
||||
}
|
||||
await fs.writeFile(path.join(output, 'lod-meta.json'), JSON.stringify(meta), 'utf-8');
|
||||
}
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
import fs from 'node:fs/promises';
|
||||
import path from 'node:path';
|
||||
import express from 'express';
|
||||
|
||||
|
||||
function createApp(address, port, publicPath) {
|
||||
const app = express();
|
||||
const rootDir = path.resolve(publicPath);
|
||||
app.use((req, res, next) => {
|
||||
res.header('Access-Control-Allow-Origin', '*');
|
||||
res.header('Access-Control-Allow-Methods', 'GET, HEAD, OPTIONS');
|
||||
res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept, Range');
|
||||
|
||||
if (req.method === 'OPTIONS') {
|
||||
return res.sendStatus(204);
|
||||
}
|
||||
|
||||
return next();
|
||||
});
|
||||
|
||||
app.get(/lod-meta.json$/, async (req, res, next) => {
|
||||
const file = path.join(rootDir, req.path);
|
||||
try {
|
||||
const content = JSON.parse(await fs.readFile(file, 'utf-8'));
|
||||
const dirname = path.dirname(req.path);
|
||||
content.files = content.files.map(f => `http://${address}:${port}${dirname}/${f}`)
|
||||
res.header('Cache-Control', 'no-cache');
|
||||
return res.json(content);
|
||||
} catch {
|
||||
return next();
|
||||
}
|
||||
});
|
||||
app.use(express.static(rootDir, {
|
||||
setHeaders: res => {
|
||||
res.header('Cache-Control', 'no-cache');
|
||||
}
|
||||
}));
|
||||
return app;
|
||||
}
|
||||
|
||||
export function start(address, port, publicPath) {
|
||||
const app = createApp(address, port, publicPath);
|
||||
app.listen(port, address, () => {
|
||||
console.log('\n========================================');
|
||||
console.log('Splat dev server started');
|
||||
console.log(`Host: ${address}:${port}`);
|
||||
console.log(`Root: ${publicPath}`);
|
||||
console.log(`Base URL: http://${address}:${port}`);
|
||||
console.log('========================================\n');
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user