Added export to schematic

This commit is contained in:
Lucas Dower 2021-07-06 23:18:24 +01:00
parent 34254b7a47
commit b3580af8c3
8 changed files with 135 additions and 36 deletions

View File

@ -10,18 +10,37 @@
integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
</head>
<body>
<nav id="nav" class="navbar navbar-dark bg-dark">
<div class="input-group w-25 mx-auto">
<input type="file" class="form-control" id="objFile" aria-describedby="inputGroupFileAddon04" aria-label="Upload">
<button id="objBtn" class="btn btn-primary" type="button" id="inputGroupFileAddon04">Load</button>
</div>
<div class="input-group w-25 mx-auto">
<label class="input-group-text" for="inputGroupFileAddon03">Voxel size</label>
<input type="number" min="0.1" step="0.1" value="0.1" class="form-control" id="voxelInput" aria-describedby="inputGroupFileAddon03" aria-label="Voxel size" disabled>
<button id="voxelBtn" class="btn btn-primary" type="button" id="inputGroupFileAddon03" disabled>Voxelise</button>
</div>
</nav>
<body id="bootstrap-overrides">
<div class="container bg-dark">
<div class="row mb-2 mt-2">
<!-- LEFT -->
<div class="col">
<div class="input-group">
<input type="file" class="form-control" id="objFile" aria-describedby="inputGroupFileAddon04" aria-label="Upload">
<button id="objBtn" class="btn btn-primary" type="button" id="inputGroupFileAddon04">Load</button>
</div>
</div>
<!-- MIDDLE -->
<div class="col">
<div class="input-group">
<label class="input-group-text" for="inputGroupFileAddon03">Voxel size</label>
<input type="number" min="0.1" step="0.1" value="0.1" class="form-control" id="voxelInput" aria-describedby="inputGroupFileAddon03" aria-label="Voxel size" disabled>
<button id="voxelBtn" class="btn btn-primary" type="button" disabled>Voxelise</button>
</div>
</div>
<!-- RIGHT -->
<div class="col">
<div class="d-grid gap-2">
<button id="exportBtn" class="btn btn-danger" type="button" disabled>Export schematic</button>
</div>
</div>
</div>
</div>
<!-- CANVAS -->
<canvas id="c"></canvas>
</body>

View File

@ -19,6 +19,7 @@ function createWindow () {
mainWindow = new BrowserWindow({width, height, webPreferences: {
nodeIntegration: true,
contextIsolation: false,
enableRemoteModule: true
}});
// Load index.html

View File

@ -1,8 +1,9 @@
{
"name": "objtoschematic",
"version": "0.1.0",
"version": "0.2.0",
"description": "A tool to convert .obj files into voxels and then into Minecraft Schematic files",
"main": "main.js",
"engines": {"node": ">=14.0.0"},
"scripts": {
"start": "electron .",
"build": "electron-packager . ObjToSchematic --platform=win32 --arch=x64"
@ -22,6 +23,7 @@
"electron-packager": "^15.2.0",
"expand-vertex-data": "^1.1.2",
"load-wavefront-obj": "^0.8.0",
"prismarine-nbt": "^1.6.0",
"twgl.js": "^4.19.1",
"wavefront-obj-parser": "^2.0.1"
},

BIN
resources/minecraft.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 738 KiB

View File

@ -1,10 +0,0 @@
# Blender MTL File: 'None'
# Material Count: 1
newmtl None
Ns 500
Ka 0.8 0.8 0.8
Kd 0.8 0.8 0.8
Ks 0.8 0.8 0.8
d 1
illum 2

View File

@ -2,26 +2,22 @@ const { Renderer } = require('./src/renderer.js');
const { Mesh } = require('./src/mesh.js');
const { VoxelManager } = require('./src/voxel_manager.js');
const { Vector3 } = require('./src/vector.js');
const { Schematic } = require('./src/schematic.js');
//const voxelSize = document.querySelector("#voxelInput").value;
const voxelSize = 0.025;
const dialog = require('electron').remote.dialog;
const voxelSize = document.querySelector("#voxelInput").value;
let renderer = new Renderer(voxelSize);
const voxelManager = new VoxelManager(voxelSize);
const nav = document.querySelector("#nav");
let canvas = document.querySelector("#c");
const canvas = document.querySelector("#c");
const showMeshing = false;
const showFailedAABBs = true;
const showFailedAABBs = false;
function resizeCanvas() {
canvas.height = window.innerHeight - 54;
canvas.width = window.innerWidth;
}
resizeCanvas();
let loadedMesh = null;
// CHOOSE FILE
document.querySelector("#objBtn").addEventListener('click', () => {
const files = document.querySelector("#objFile").files;
@ -41,6 +37,7 @@ document.querySelector("#objBtn").addEventListener('click', () => {
});
// VOXELISE BUTTON
document.querySelector("#voxelBtn").addEventListener('click', () => {
const voxelSize = document.querySelector("#voxelInput").value;
@ -72,12 +69,36 @@ document.querySelector("#voxelBtn").addEventListener('click', () => {
renderer.registerBox(box.centre, box.size, true);
}
}
document.querySelector("#exportBtn").disabled = false;
renderer.compileRegister();
});
// EXPORT SCHEMATIC
document.querySelector("#exportBtn").addEventListener('click', async function() {
const {filePath} = await dialog.showSaveDialog({
title: "Save schematic",
buttonLabel: "Save",
filters: [{
name: 'Schematic',
extensions: ['schematic']
}]
});
const schematic = new Schematic(voxelManager);
schematic.exportSchematic(filePath);
});
//const suzanne = new Mesh('./resources/suzanne.obj');
//voxelManager.voxeliseMesh(suzanne);
//const schematic = new Schematic(voxelManager);
function render(time) {
resizeCanvas();
canvas.height = window.innerHeight - 54;
canvas.width = window.innerWidth;
renderer.begin();
renderer.end();

62
src/schematic.js Normal file
View File

@ -0,0 +1,62 @@
const zlib = require("zlib");
const fs = require('fs');
const { parse, writeUncompressed } = require('prismarine-nbt');
const { Vector3 } = require('./vector.js');
const dialog = require('electron').remote.dialog;
class Schematic {
_getBufferIndex(vec) {
return (this.sizeVector.z * this.sizeVector.x * vec.y) + (this.sizeVector.x * vec.z) + vec.x;
}
constructor(voxelManager) {
const minPos = voxelManager._voxelCentreToPosition(new Vector3(voxelManager.minX, voxelManager.minY, voxelManager.minZ));
const maxPos = voxelManager._voxelCentreToPosition(new Vector3(voxelManager.maxX, voxelManager.maxY, voxelManager.maxZ));
this.sizeVector = Vector3.addScalar(Vector3.sub(maxPos, minPos), 1);
const bufferSize = this.sizeVector.x * this.sizeVector.y * this.sizeVector.z;
this.schematic = {
type: 'compound',
name: 'Schematic',
value: {
Width: { type: 'short', value: this.sizeVector.x },
Height: { type: 'short', value: this.sizeVector.y },
Length: { type: 'short', value: this.sizeVector.z },
Materials: { type: 'string', value: 'Alpha' },
Blocks: { type: 'byteArray', value: new Array(bufferSize) },
Data: { type: 'byteArray', value: new Array(bufferSize).fill(0) },
Entities: { type: 'list', value: {type: "int", value: Array(0)} },
TileEntities: { type: 'list', value: {type: "int", value: Array(0)} }
}
};
for (let i = 0; i < voxelManager.voxels.length; ++i) {
const voxel = voxelManager.voxels[i];
const pos = voxelManager._voxelCentreToPosition(voxel);
const indexVector = Vector3.sub(pos, minPos);
const index = this._getBufferIndex(indexVector);
this.schematic.value.Blocks.value[index] = 1;
}
}
exportSchematic(filePath) {
const outBuffer = fs.createWriteStream(filePath);
const newBuffer = writeUncompressed(this.schematic, "big");
zlib.gzip(newBuffer, (err, buffer) => {
if (!err) {
outBuffer.write(buffer);
outBuffer.end(() => console.log('Written!'));
}
else {
console.log(err);
}
});
}
}
module.exports.Schematic = Schematic;

View File

@ -1,9 +1,9 @@
body {
margin: 0;
font-family: monospace;
background-color: red;
}
canvas {
display: block;
width: 100;
@ -29,4 +29,8 @@ div.hidden {
.rounded-pill-right {
border-top-right-radius: 50rem !important;
border-bottom-right-radius: 50rem !important;
}
#bootstrap-overrides {
background-color: #212529;
}