Moved exporters into new folder

This commit is contained in:
Lucas Dower 2022-04-14 23:35:23 +01:00
parent 98d7bb16cd
commit 8289ba6579
6 changed files with 136 additions and 187 deletions

View File

@ -1,5 +1,6 @@
import { UI } from './ui/layout'; import { UI } from './ui/layout';
import { Litematic, Schematic } from './schematic'; import { Schematic } from './exporters/schematic_exporter';
import { Litematic } from './exporters/litematic_exporter';
import { Renderer } from './renderer'; import { Renderer } from './renderer';
import { Mesh } from './mesh'; import { Mesh } from './mesh';
import { ObjImporter } from './importers/obj_importer'; import { ObjImporter } from './importers/obj_importer';

View File

@ -0,0 +1,39 @@
import { Vector3 } from '../vector';
import { BlockMesh } from '../block_mesh';
import { NBT, writeUncompressed } from 'prismarine-nbt';
import * as zlib from 'zlib';
import * as fs from 'fs';
export abstract class IExporter {
protected _sizeVector!: Vector3;
public abstract convertToNBT(blockMesh: BlockMesh): NBT
abstract getFormatFilter(): Electron.FileFilter;
abstract getFormatName(): string;
abstract getFileExtension(): string;
getFormatDisclaimer(): string | undefined {
return;
}
export(blockMesh: BlockMesh, filePath: string): boolean {
const bounds = blockMesh.getVoxelMesh()?.getBounds();
this._sizeVector = Vector3.sub(bounds.max, bounds.min).addScalar(1);
const nbt = this.convertToNBT(blockMesh);
const outBuffer = fs.createWriteStream(filePath);
const newBuffer = writeUncompressed(nbt, 'big');
zlib.gzip(newBuffer, (err, buffer) => {
if (!err) {
outBuffer.write(buffer);
outBuffer.end();
}
return err;
});
return false;
}
}

View File

@ -1,123 +1,8 @@
import * as zlib from 'zlib'; import { BlockMesh } from '../block_mesh';
import * as fs from 'fs'; import { Vector3 } from '../vector';
import path from 'path'; import { IExporter } from './base_exporter';
import { NBT, TagType, writeUncompressed } from 'prismarine-nbt';
import { Vector3 } from './vector';
import { BlockMesh } from './block_mesh';
import { RESOURCES_DIR } from './util';
import { StatusHandler } from './status';
export abstract class IExporter { import { NBT, TagType } from 'prismarine-nbt';
protected _sizeVector!: Vector3;
public abstract convertToNBT(blockMesh: BlockMesh): NBT
abstract getFormatFilter(): Electron.FileFilter;
abstract getFormatName(): string;
abstract getFileExtension(): string;
getFormatDisclaimer(): string | undefined {
return;
}
export(blockMesh: BlockMesh, filePath: string): boolean {
const bounds = blockMesh.getVoxelMesh()?.getBounds();
this._sizeVector = Vector3.sub(bounds.max, bounds.min).addScalar(1);
const nbt = this.convertToNBT(blockMesh);
const outBuffer = fs.createWriteStream(filePath);
const newBuffer = writeUncompressed(nbt, 'big');
zlib.gzip(newBuffer, (err, buffer) => {
if (!err) {
outBuffer.write(buffer);
outBuffer.end();
}
return err;
});
return false;
}
}
export class Schematic extends IExporter {
public override convertToNBT(blockMesh: BlockMesh) {
const bufferSize = this._sizeVector.x * this._sizeVector.y * this._sizeVector.z;
const blocksData = Array<number>(bufferSize);
const metaData = Array<number>(bufferSize);
const bounds = blockMesh.getVoxelMesh().getBounds();
const schematicBlocks: { [blockName: string]: { id: number, meta: number, name: string } } = JSON.parse(
fs.readFileSync(path.join(RESOURCES_DIR, './block_ids.json'), 'utf8'),
);
const blocks = blockMesh.getBlocks();
const unsupportedBlocks = new Set<string>();
let numBlocksUnsupported = 0;
for (const block of blocks) {
const indexVector = Vector3.sub(block.voxel.position, bounds.min);
const index = this._getBufferIndex(indexVector, this._sizeVector);
if (block.blockInfo.name in schematicBlocks) {
const schematicBlock = schematicBlocks[block.blockInfo.name];
blocksData[index] = new Int8Array([schematicBlock.id])[0];
metaData[index] = new Int8Array([schematicBlock.meta])[0];
} else {
blocksData[index] = 1; // Default to a Stone block
metaData[index] = 0;
unsupportedBlocks.add(block.blockInfo.name);
++numBlocksUnsupported;
}
}
if (unsupportedBlocks.size > 0) {
StatusHandler.Get.add(
'warning',
`${numBlocksUnsupported} blocks (${unsupportedBlocks.size} unique) are not supported by the .schematic format, Stone block are used in their place. Try using the schematic-friendly palette, or export using .litematica`,
);
}
const nbt: NBT = {
type: TagType.Compound,
name: 'Schematic',
value: {
Width: { type: TagType.Short, value: this._sizeVector.x },
Height: { type: TagType.Short, value: this._sizeVector.y },
Length: { type: TagType.Short, value: this._sizeVector.z },
Materials: { type: TagType.String, value: 'Alpha' },
Blocks: { type: TagType.ByteArray, value: blocksData },
Data: { type: TagType.ByteArray, value: metaData },
Entities: { type: TagType.List, value: { type: TagType.Int, value: Array(0) } },
TileEntities: { type: TagType.List, value: { type: TagType.Int, value: Array(0) } },
},
};
return nbt;
}
_getBufferIndex(vec: Vector3, sizeVector: Vector3) {
return (sizeVector.z * sizeVector.x * vec.y) + (sizeVector.x * vec.z) + vec.x;
}
getFormatFilter() {
return {
name: this.getFormatName(),
extensions: ['schematic'],
};
}
getFormatName() {
return 'Schematic';
}
getFormatDisclaimer() {
return 'Schematic files only support pre-1.13 blocks. As a result, all blocks will be exported as Stone. To export the blocks, use the .litematic format with the Litematica mod.';
}
getFileExtension(): string {
return 'schematic';
}
}
type BlockID = number; type BlockID = number;
type long = [number, number]; type long = [number, number];

View File

@ -0,0 +1,88 @@
import { BlockMesh } from '../block_mesh';
import { RESOURCES_DIR } from '../util';
import { IExporter } from './base_exporter';
import { Vector3 } from '../vector';
import { StatusHandler } from '../status';
import path from 'path';
import fs from 'fs';
import { NBT, TagType } from 'prismarine-nbt';
export class Schematic extends IExporter {
public override convertToNBT(blockMesh: BlockMesh) {
const bufferSize = this._sizeVector.x * this._sizeVector.y * this._sizeVector.z;
const blocksData = Array<number>(bufferSize);
const metaData = Array<number>(bufferSize);
const bounds = blockMesh.getVoxelMesh().getBounds();
const schematicBlocks: { [blockName: string]: { id: number, meta: number, name: string } } = JSON.parse(
fs.readFileSync(path.join(RESOURCES_DIR, './block_ids.json'), 'utf8'),
);
const blocks = blockMesh.getBlocks();
const unsupportedBlocks = new Set<string>();
let numBlocksUnsupported = 0;
for (const block of blocks) {
const indexVector = Vector3.sub(block.voxel.position, bounds.min);
const index = this._getBufferIndex(indexVector, this._sizeVector);
if (block.blockInfo.name in schematicBlocks) {
const schematicBlock = schematicBlocks[block.blockInfo.name];
blocksData[index] = new Int8Array([schematicBlock.id])[0];
metaData[index] = new Int8Array([schematicBlock.meta])[0];
} else {
blocksData[index] = 1; // Default to a Stone block
metaData[index] = 0;
unsupportedBlocks.add(block.blockInfo.name);
++numBlocksUnsupported;
}
}
if (unsupportedBlocks.size > 0) {
StatusHandler.Get.add(
'warning',
`${numBlocksUnsupported} blocks (${unsupportedBlocks.size} unique) are not supported by the .schematic format, Stone block are used in their place. Try using the schematic-friendly palette, or export using .litematica`,
);
}
const nbt: NBT = {
type: TagType.Compound,
name: 'Schematic',
value: {
Width: { type: TagType.Short, value: this._sizeVector.x },
Height: { type: TagType.Short, value: this._sizeVector.y },
Length: { type: TagType.Short, value: this._sizeVector.z },
Materials: { type: TagType.String, value: 'Alpha' },
Blocks: { type: TagType.ByteArray, value: blocksData },
Data: { type: TagType.ByteArray, value: metaData },
Entities: { type: TagType.List, value: { type: TagType.Int, value: Array(0) } },
TileEntities: { type: TagType.List, value: { type: TagType.Int, value: Array(0) } },
},
};
return nbt;
}
_getBufferIndex(vec: Vector3, sizeVector: Vector3) {
return (sizeVector.z * sizeVector.x * vec.y) + (sizeVector.x * vec.z) + vec.x;
}
getFormatFilter() {
return {
name: this.getFormatName(),
extensions: ['schematic'],
};
}
getFormatName() {
return 'Schematic';
}
getFormatDisclaimer() {
return 'Schematic files only support pre-1.13 blocks. As a result, all blocks will be exported as Stone. To export the blocks, use the .litematic format with the Litematica mod.';
}
getFileExtension(): string {
return 'schematic';
}
}

View File

@ -1,69 +1,3 @@
/*
export class Occlusion {
private _occlusionNeighboursIndices!: Array<Array<Array<number>>>; // Ew
public static calculateOcclusions(centre: Vector3, voxelMesh: VoxelMesh) {
// Cache local neighbours
const localNeighbourhoodCache = Array<number>(27);
for (let i = -1; i <= 1; ++i) {
for (let j = -1; j <= 1; ++j) {
for (let k = -1; k <= 1; ++k) {
const neighbour = new Vector3(i, j, k);
const neighbourIndex = Renderer._getNeighbourIndex(neighbour);
localNeighbourhoodCache[neighbourIndex] = voxelMesh.isVoxelAt(Vector3.add(centre, neighbour)) ? 1 : 0;
}
}
}
const occlusions = new Array<Array<number>>(6);
// For each face
for (let f = 0; f < 6; ++f) {
occlusions[f] = [1, 1, 1, 1];
// Only compute ambient occlusion if this face is visible
const faceNormal = Occlusion._faceNormals[f];
const faceNeighbourIndex = Occlusion._getNeighbourIndex(faceNormal);
const faceVisible = localNeighbourhoodCache[faceNeighbourIndex] === 0;
if (faceVisible) {
for (let v = 0; v < 4; ++v) {
let numNeighbours = 0;
for (let i = 0; i < 2; ++i) {
const neighbourIndex = this._occlusionNeighboursIndices[f][v][i];
numNeighbours += localNeighbourhoodCache[neighbourIndex];
}
// If both edge blocks along this vertex exist,
// assume corner exists (even if it doesnt)
// (This is a stylistic choice)
if (numNeighbours == 2 && AppConfig.AMBIENT_OCCLUSION_OVERRIDE_CORNER) {
++numNeighbours;
} else {
const neighbourIndex = this._occlusionNeighboursIndices[f][v][2];
numNeighbours += localNeighbourhoodCache[neighbourIndex];
}
// Convert from occlusion denoting the occlusion factor to the
// attenuation in light value: 0 -> 1.0, 1 -> 0.8, 2 -> 0.6, 3 -> 0.4
occlusions[f][v] = 1.0 - 0.2 * numNeighbours;
}
}
}
return occlusions;
}
private static _getNeighbourIndex(neighbour: Vector3) {
return 9 * (neighbour.x + 1) + 3 * (neighbour.y + 1) + (neighbour.z + 1);
}
private static _faceNormals = [
new Vector3(1, 0, 0), new Vector3(-1, 0, 0),
new Vector3(0, 1, 0), new Vector3(0, -1, 0),
new Vector3(0, 0, 1), new Vector3(0, 0, -1),
];
}
*/
import { AppConfig } from './config'; import { AppConfig } from './config';
import { ASSERT } from './util'; import { ASSERT } from './util';
import { Vector3 } from './vector'; import { Vector3 } from './vector';

View File

@ -3,7 +3,9 @@ import { ObjImporter } from '../src/importers/obj_importer';
import { IVoxeliser } from '../src/voxelisers/base-voxeliser'; import { IVoxeliser } from '../src/voxelisers/base-voxeliser';
import { VoxelMesh, VoxelMeshParams } from '../src/voxel_mesh'; import { VoxelMesh, VoxelMeshParams } from '../src/voxel_mesh';
import { BlockMesh, BlockMeshParams } from '../src/block_mesh'; import { BlockMesh, BlockMeshParams } from '../src/block_mesh';
import { IExporter, Litematic, Schematic } from '../src/schematic'; import { IExporter} from '../src/exporters/base_exporter';
import { Schematic } from '../src/exporters/schematic_exporter';
import { Litematic } from '../src/exporters/litematic_exporter';
import { RayVoxeliser } from '../src/voxelisers/ray-voxeliser'; import { RayVoxeliser } from '../src/voxelisers/ray-voxeliser';
import { NormalCorrectedRayVoxeliser } from '../src/voxelisers/normal-corrected-ray-voxeliser'; import { NormalCorrectedRayVoxeliser } from '../src/voxelisers/normal-corrected-ray-voxeliser';
import { TextureFiltering } from '../src/texture'; import { TextureFiltering } from '../src/texture';