Added Sandbox package for API examples

This commit is contained in:
Lucas Dower 2023-10-10 19:39:13 +01:00
parent a7838305ca
commit 06a915d3b7
8 changed files with 200 additions and 76 deletions

5
.gitignore vendored
View File

@ -10,4 +10,7 @@
/Editor/node_modules
/Editor/.firebase
/Editor/.firebaserc
/Editor/webpack/
/Editor/webpack/
# Sandbox
/Sandbox/node_modules

View File

@ -1,71 +0,0 @@
import fs from 'fs';
import path from 'path';
import { ObjImporter } from "../src/importers/obj_importer";
import { OtS_VoxelMesh_Converter } from '../src/ots_voxel_mesh_converter';
import { BlockMesh } from '../src/block_mesh';
import { PALETTE_ALL_RELEASE } from '../../Editor/res/palettes/all'; // TODO: Disallowed import
import { ExporterFactory } from '../src/exporters/exporters';
import { ASSERT } from '../src/util/error_util';
import { createReadableStream, createOtSTexture } from '../tools/util'; // TODO: Disallowed import
(async () => {
// 1. Import a mesh
const pathModel = path.join(__dirname, '../res/samples/skull.obj');
const readableStream = createReadableStream(pathModel);
const loader = new ObjImporter();
const mesh = await loader.import(readableStream);
// 2. Assign materials
const pathTexture = path.join(__dirname, '../res/samples/skull.jpg');
const texture = createOtSTexture(pathTexture);
ASSERT(texture !== undefined, `Could not parse ${pathTexture}`);
// Update the 'skull' material
const success = mesh.setMaterial({
type: 'textured',
name: 'skull',
texture: texture,
});
ASSERT(success, 'Could not update skull material');
// 3. Construct a voxel mesh from the mesh
const converter = new OtS_VoxelMesh_Converter();
converter.setConfig({
constraintAxis: 'y',
size: 380,
multisampling: false,
replaceMode: 'keep',
});
const voxelMesh = converter.process(mesh);
// 4. Construct a block mesh from the block
// NOTE: This will be placeholder and will be changed
const blockMesh = BlockMesh.createFromVoxelMesh(voxelMesh, {
atlasJSON: JSON.parse(fs.readFileSync(path.join(__dirname, '../res/atlases/vanilla.atlas'), 'utf8')),
blockPalette: new Set(PALETTE_ALL_RELEASE),
calculateLighting: false,
contextualAveraging: true,
dithering: 'off',
ditheringMagnitude: 0,
errorWeight: 0.02,
resolution: 16,
fallable: 'do-nothing',
lightThreshold: 0,
});
// 5. Export the block mesh to a file
// NOTE: This will be placeholder and will be changed
const exporter = ExporterFactory.GetExporter('litematic');
const exportData = exporter.export(blockMesh.blockMesh);
if (exportData.type === 'single') {
fs.writeFileSync('export' + exportData.extension, exportData.content);
} else {
exportData.regions.forEach((region) => {
fs.writeFileSync(region.name + exportData.extension, region.content);
});
}
})();

View File

@ -1,3 +1,12 @@
export function testExport(x: number, y: number) {
return x + y;
}
import { ImporterFactory } from './src/importers/importers';
import { OtS_Texture } from './src/ots_texture';
import { OtS_VoxelMesh } from './src/ots_voxel_mesh';
import { OtS_VoxelMesh_Converter } from './src/ots_voxel_mesh_converter';
export default {
getImporter: ImporterFactory.GetImporter,
texture: OtS_Texture,
voxelMeshConverter: OtS_VoxelMesh_Converter,
voxelMesh: OtS_VoxelMesh,
};

View File

@ -6,7 +6,7 @@ import { ObjImporter } from './obj_importer';
export type TImporters = 'obj' | 'gltf';
export class ImporterFactor {
export class ImporterFactory {
public static GetImporter(importer: TImporters): IImporter {
switch (importer) {
case 'obj':

44
Sandbox/index.ts Normal file
View File

@ -0,0 +1,44 @@
import { strict as assert } from 'node:assert';
import path from 'node:path';
import OTS from 'ots-core';
import { createOtSTexture, createReadableStream } from './src/util';
(async () => {
// 1. Import a mesh
const pathModel = path.join(__dirname, '../res/samples/skull.obj');
const readableStream = createReadableStream(pathModel);
const importer = OTS.getImporter('obj');
const mesh = await importer.import(readableStream);
// 2. Assign materials
const pathTexture = path.join(__dirname, '../res/samples/skull.jpg');
const texture = createOtSTexture(pathTexture);
assert(texture !== undefined, `Could not parse ${pathTexture}`);
// Update the 'skull' material
const success = mesh.setMaterial({
type: 'textured',
name: 'skull',
texture: texture,
});
assert(success, 'Could not update skull material');
// 3. Construct a voxel mesh from the mesh
const converter = new OTS.voxelMeshConverter();
converter.setConfig({
constraintAxis: 'y',
size: 380,
multisampling: false,
replaceMode: 'keep',
});
const voxelMesh = converter.process(mesh);
// 4. Construct a block mesh from the block
// TODO
// 5. Export the block mesh to a file
// TODO
})();

79
Sandbox/package-lock.json generated Normal file
View File

@ -0,0 +1,79 @@
{
"name": "ots-sandbox",
"version": "1.0.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "ots-sandbox",
"version": "1.0.0",
"license": "ISC",
"dependencies": {
"jpeg-js": "^0.4.4",
"ots-core": "file:../Core",
"pngjs": "^7.0.0"
}
},
"../Core": {
"name": "ots-core",
"version": "1.0.0",
"license": "ISC",
"dependencies": {
"@loaders.gl/core": "^3.4.14",
"@loaders.gl/gltf": "^3.4.14",
"@types/jest": "^29.5.5",
"pako": "^2.1.0",
"prismarine-nbt": "^2.2.1",
"ts-jest": "^29.1.1",
"typescript": "^5.2.2"
},
"devDependencies": {
"@types/pako": "^2.0.1",
"jest": "^29.7.0"
}
},
"node_modules/jpeg-js": {
"version": "0.4.4",
"resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.4.4.tgz",
"integrity": "sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg=="
},
"node_modules/ots-core": {
"resolved": "../Core",
"link": true
},
"node_modules/pngjs": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/pngjs/-/pngjs-7.0.0.tgz",
"integrity": "sha512-LKWqWJRhstyYo9pGvgor/ivk2w94eSjE3RGVuzLGlr3NmD8bf7RcYGze1mNdEHRP6TRP6rMuDHk5t44hnTRyow==",
"engines": {
"node": ">=14.19.0"
}
}
},
"dependencies": {
"jpeg-js": {
"version": "0.4.4",
"resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.4.4.tgz",
"integrity": "sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg=="
},
"ots-core": {
"version": "file:../Core",
"requires": {
"@loaders.gl/core": "^3.4.14",
"@loaders.gl/gltf": "^3.4.14",
"@types/jest": "^29.5.5",
"@types/pako": "^2.0.1",
"jest": "^29.7.0",
"pako": "^2.1.0",
"prismarine-nbt": "^2.2.1",
"ts-jest": "^29.1.1",
"typescript": "^5.2.2"
}
},
"pngjs": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/pngjs/-/pngjs-7.0.0.tgz",
"integrity": "sha512-LKWqWJRhstyYo9pGvgor/ivk2w94eSjE3RGVuzLGlr3NmD8bf7RcYGze1mNdEHRP6TRP6rMuDHk5t44hnTRyow=="
}
}
}

18
Sandbox/package.json Normal file
View File

@ -0,0 +1,18 @@
{
"name": "ots-sandbox",
"private": true,
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"jpeg-js": "^0.4.4",
"ots-core": "file:../Core",
"pngjs": "^7.0.0"
}
}

42
Sandbox/src/util.ts Normal file
View File

@ -0,0 +1,42 @@
import fs from 'node:fs';
import path from 'node:path';
import OTS from 'ots-core';
import { PNG } from 'pngjs';
import { decode as jpegDecode } from 'jpeg-js';
export function createReadableStream(p: fs.PathLike) {
return new ReadableStream({
async start(controller) {
const readStream = fs.createReadStream(p);
readStream.on('data', (chunk) => {
controller.enqueue(chunk);
});
readStream.on('end', () => {
controller.close();
});
readStream.on('error', (err) => {
throw err;
});
},
});
}
export function createOtSTexture(p: fs.PathLike) {
const ext = path.extname(p.toString());
switch (ext) {
case '.jpg':
case '.jpeg': {
var jpegData = fs.readFileSync(p);
const jpeg = jpegDecode(jpegData, {
maxMemoryUsageInMB: undefined,
formatAsRGBA: true,
});
return new OTS.texture(Uint8ClampedArray.from(jpeg.data), jpeg.width, jpeg.width, 'nearest', 'repeat');
}
}
}