mirror of
https://github.com/LucasDower/ObjToSchematic.git
synced 2025-01-30 13:09:32 +08:00
Added export to schematic
This commit is contained in:
parent
34254b7a47
commit
b3580af8c3
43
index.html
43
index.html
@ -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>
|
||||
|
||||
|
1
main.js
1
main.js
@ -19,6 +19,7 @@ function createWindow () {
|
||||
mainWindow = new BrowserWindow({width, height, webPreferences: {
|
||||
nodeIntegration: true,
|
||||
contextIsolation: false,
|
||||
enableRemoteModule: true
|
||||
}});
|
||||
|
||||
// Load index.html
|
||||
|
@ -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
BIN
resources/minecraft.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 738 KiB |
@ -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
|
@ -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
62
src/schematic.js
Normal 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;
|
@ -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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user