mirror of
https://github.com/LucasDower/ObjToSchematic.git
synced 2025-04-12 15:00:22 +08:00
Moved many small class files into util
This commit is contained in:
parent
62f0ab181f
commit
64b8410aff
@ -1,17 +1,14 @@
|
||||
import { NBT, TagType } from 'prismarine-nbt';
|
||||
|
||||
import { AppConstants } from '../constants';
|
||||
import { ceilToNearest } from '../math';
|
||||
import { AppTypes } from '../util';
|
||||
import { ASSERT } from '../util/error_util';
|
||||
import { saveNBT } from '../util/nbt_util';
|
||||
import { Vector3 } from '../vector';
|
||||
import { AppConstants } from '../util/constants';
|
||||
import { Vector3 } from '../util/vector';
|
||||
import { IExporter, TStructureExport } from './base_exporter';
|
||||
import { OtS_BlockMesh } from '../ots_block_mesh';
|
||||
import { ASSERT, OtS_Util } from '../util/util';
|
||||
|
||||
type BlockID = number;
|
||||
type long = [number, number];
|
||||
type BlockMapping = Map<AppTypes.TNamespacedBlockName, BlockID>;
|
||||
type BlockMapping = Map<string, BlockID>;
|
||||
|
||||
export class Litematic extends IExporter {
|
||||
public override getFormatFilter() {
|
||||
@ -23,7 +20,7 @@ export class Litematic extends IExporter {
|
||||
|
||||
public override export(blockMesh: OtS_BlockMesh): TStructureExport {
|
||||
const nbt = this._convertToNBT(blockMesh);
|
||||
return { type: 'single', extension: '.litematic', content: saveNBT(nbt) };
|
||||
return { type: 'single', extension: '.litematic', content: OtS_Util.NBT.saveNBT(nbt) };
|
||||
}
|
||||
|
||||
/**
|
||||
@ -108,7 +105,7 @@ export class Litematic extends IExporter {
|
||||
stride = Math.max(2, stride);
|
||||
|
||||
const expectedLengthBits = blockBuffer.length * stride;
|
||||
const requiredLengthBits = ceilToNearest(expectedLengthBits, 64);
|
||||
const requiredLengthBits = OtS_Util.Numeric.ceilToNearest(expectedLengthBits, 64);
|
||||
const startOffsetBits = requiredLengthBits - expectedLengthBits;
|
||||
|
||||
const requiredLengthBytes = requiredLengthBits / 8;
|
||||
|
@ -1,12 +1,10 @@
|
||||
import { NBT, TagType } from 'prismarine-nbt';
|
||||
|
||||
import { AppConstants } from '../constants';
|
||||
import { AppUtil } from '../util';
|
||||
import { saveNBT } from '../util/nbt_util';
|
||||
import { Vector3 } from '../vector';
|
||||
import { AppConstants } from '../util/constants';
|
||||
import { Vector3 } from '../util/vector';
|
||||
import { IExporter, TStructureExport, TStructureRegion } from './base_exporter';
|
||||
import { ASSERT } from '../util/error_util';
|
||||
import { OtS_BlockMesh } from '../ots_block_mesh';
|
||||
import { ASSERT, OtS_Util } from '../util/util';
|
||||
|
||||
export class NBTExporter extends IExporter {
|
||||
public override getFormatFilter() {
|
||||
@ -78,7 +76,7 @@ export class NBTExporter extends IExporter {
|
||||
},
|
||||
};
|
||||
|
||||
return saveNBT(nbt);
|
||||
return OtS_Util.NBT.saveNBT(nbt);
|
||||
}
|
||||
|
||||
public override export(blockMesh: OtS_BlockMesh) {
|
||||
@ -98,7 +96,7 @@ export class NBTExporter extends IExporter {
|
||||
palette.push({
|
||||
Name: {
|
||||
type: TagType.String,
|
||||
value: AppUtil.Text.namespaceBlock(blockName),
|
||||
value: OtS_Util.Text.namespaceBlock(blockName),
|
||||
},
|
||||
});
|
||||
blockNameToIndex.set(blockName, palette.length - 1);
|
||||
|
@ -1,13 +1,10 @@
|
||||
import { NBT, TagType } from 'prismarine-nbt';
|
||||
|
||||
import { AppConstants } from '../constants';
|
||||
import { AppUtil } from '../util';
|
||||
import { LOG } from '../util/log_util';
|
||||
import { MathUtil } from '../util/math_util';
|
||||
import { saveNBT } from '../util/nbt_util';
|
||||
import { Vector3 } from '../vector';
|
||||
import { AppConstants } from '../util/constants';
|
||||
import { Vector3 } from '../util/vector';
|
||||
import { IExporter, TStructureExport } from './base_exporter';
|
||||
import { OtS_BlockMesh } from '../ots_block_mesh';
|
||||
import { OtS_Util } from '../util/util';
|
||||
|
||||
export class SchemExporter extends IExporter {
|
||||
private static SCHEMA_VERSION = 2;
|
||||
@ -31,19 +28,17 @@ export class SchemExporter extends IExporter {
|
||||
|
||||
let blockIndex = 1;
|
||||
for (const blockName of blockMesh.calcBlocksUsed()) {
|
||||
const namespacedBlockName = AppUtil.Text.namespaceBlock(blockName);
|
||||
const namespacedBlockName = OtS_Util.Text.namespaceBlock(blockName);
|
||||
|
||||
blockMapping[namespacedBlockName] = { type: TagType.Int, value: blockIndex };
|
||||
++blockIndex;
|
||||
}
|
||||
LOG(blockMapping);
|
||||
|
||||
// const paletteObject = SchemExporter._createBlockStatePalette(blockMapping);
|
||||
const blockData = new Array<number>(sizeVector.x * sizeVector.y * sizeVector.z).fill(0);
|
||||
for (const { position, name } of blockMesh.getBlocks()) {
|
||||
const indexVector = Vector3.sub(position, bounds.min);
|
||||
const bufferIndex = SchemExporter._getBufferIndex(sizeVector, indexVector);
|
||||
const namespacedBlockName = AppUtil.Text.namespaceBlock(name);
|
||||
const namespacedBlockName = OtS_Util.Text.namespaceBlock(name);
|
||||
blockData[bufferIndex] = blockMapping[namespacedBlockName].value;
|
||||
}
|
||||
|
||||
@ -59,7 +54,7 @@ export class SchemExporter extends IExporter {
|
||||
}
|
||||
|
||||
for (let i = 0; i < blockEncoding.length; ++i) {
|
||||
blockEncoding[i] = MathUtil.int8(blockEncoding[i]);
|
||||
blockEncoding[i] = OtS_Util.Numeric.int8(blockEncoding[i]);
|
||||
}
|
||||
|
||||
const nbt: NBT = {
|
||||
@ -77,7 +72,7 @@ export class SchemExporter extends IExporter {
|
||||
},
|
||||
};
|
||||
|
||||
return { type: 'single', extension: '.schem', content: saveNBT(nbt) };
|
||||
return { type: 'single', extension: '.schem', content: OtS_Util.NBT.saveNBT(nbt) };
|
||||
}
|
||||
|
||||
private static _getBufferIndex(dimensions: Vector3, vec: Vector3) {
|
||||
|
@ -1,10 +1,10 @@
|
||||
import { NBT, TagType } from 'prismarine-nbt';
|
||||
|
||||
import { BLOCK_IDS } from '../../../Editor/res/block_ids';
|
||||
import { saveNBT } from '../util/nbt_util';
|
||||
import { Vector3 } from '../vector';
|
||||
import { Vector3 } from '../util/vector';
|
||||
import { IExporter, TStructureExport } from './base_exporter';
|
||||
import { OtS_BlockMesh } from '../ots_block_mesh';
|
||||
import { OtS_Util } from '../util/util';
|
||||
|
||||
export class Schematic extends IExporter {
|
||||
public override getFormatFilter() {
|
||||
@ -16,7 +16,7 @@ export class Schematic extends IExporter {
|
||||
|
||||
public override export(blockMesh: OtS_BlockMesh): TStructureExport {
|
||||
const nbt = this._convertToNBT(blockMesh);
|
||||
return { type: 'single', extension: '.schematic', content: saveNBT(nbt) };
|
||||
return { type: 'single', extension: '.schematic', content: OtS_Util.NBT.saveNBT(nbt) };
|
||||
}
|
||||
|
||||
private _convertToNBT(blockMesh: OtS_BlockMesh): NBT {
|
||||
|
@ -1,12 +1,12 @@
|
||||
import { parse } from '@loaders.gl/core';
|
||||
import { GLTFLoader } from '@loaders.gl/gltf';
|
||||
|
||||
import { UV } from '../util';
|
||||
import { Vector3 } from '../vector';
|
||||
import { Vector3 } from '../util/vector';
|
||||
import { OtS_Mesh } from '../ots_mesh';
|
||||
import { OtS_Texture } from '../ots_texture';
|
||||
import { OtS_Importer } from './base_importer';
|
||||
import { OtS_Colours } from '../colour';
|
||||
import { OtS_Colours } from '../util/colour';
|
||||
import { UV } from '../util/types';
|
||||
|
||||
export type OtS_GltfImporterError =
|
||||
| { type: 'failed-to-parse' }
|
||||
|
@ -1,14 +1,11 @@
|
||||
import { OtS_Colours, RGBAUtil } from '../colour';
|
||||
import { OtS_Colours, RGBAUtil } from '../util/colour';
|
||||
import { OtS_Mesh } from '../ots_mesh';
|
||||
import { OtS_Texture } from '../ots_texture';
|
||||
import { Triangle } from '../triangle';
|
||||
import { UV } from '../util';
|
||||
import { ASSERT } from '../util/error_util';
|
||||
import { RegExpBuilder } from '../util/regex_util';
|
||||
import { REGEX_NZ_ANY } from '../util/regex_util';
|
||||
import { REGEX_NUMBER } from '../util/regex_util';
|
||||
import { Vector3 } from '../vector';
|
||||
import { Triangle } from '../util/triangle';
|
||||
import { Vector3 } from '../util/vector';
|
||||
import { OtS_Importer } from './base_importer';
|
||||
import { UV } from '../util/types';
|
||||
import { ASSERT, OtS_Util } from '../util/util';
|
||||
|
||||
export type OtS_ObjImporterError =
|
||||
| { type: 'invalid-encoding' }
|
||||
@ -39,41 +36,41 @@ export class OtS_Importer_Obj extends OtS_Importer {
|
||||
// Parser context
|
||||
private _linesToParse: string[] = [];
|
||||
|
||||
private static _REGEX_USEMTL = new RegExpBuilder()
|
||||
private static _REGEX_USEMTL = new OtS_Util.Regex.RegExpBuilder()
|
||||
.add(/^usemtl/)
|
||||
.add(/ /)
|
||||
.add(REGEX_NZ_ANY, 'name')
|
||||
.add(OtS_Util.Regex.REGEX_NZ_ANY, 'name')
|
||||
.toRegExp();
|
||||
|
||||
private static _REGEX_VERTEX = new RegExpBuilder()
|
||||
private static _REGEX_VERTEX = new OtS_Util.Regex.RegExpBuilder()
|
||||
.add(/^v/)
|
||||
.addNonzeroWhitespace()
|
||||
.add(REGEX_NUMBER, 'x')
|
||||
.add(OtS_Util.Regex.REGEX_NUMBER, 'x')
|
||||
.addNonzeroWhitespace()
|
||||
.add(REGEX_NUMBER, 'y')
|
||||
.add(OtS_Util.Regex.REGEX_NUMBER, 'y')
|
||||
.addNonzeroWhitespace()
|
||||
.add(REGEX_NUMBER, 'z')
|
||||
.add(OtS_Util.Regex.REGEX_NUMBER, 'z')
|
||||
.toRegExp();
|
||||
|
||||
private static _REGEX_NORMAL = new RegExpBuilder()
|
||||
private static _REGEX_NORMAL = new OtS_Util.Regex.RegExpBuilder()
|
||||
.add(/^vn/)
|
||||
.addNonzeroWhitespace()
|
||||
.add(REGEX_NUMBER, 'x')
|
||||
.add(OtS_Util.Regex.REGEX_NUMBER, 'x')
|
||||
.addNonzeroWhitespace()
|
||||
.add(REGEX_NUMBER, 'y')
|
||||
.add(OtS_Util.Regex.REGEX_NUMBER, 'y')
|
||||
.addNonzeroWhitespace()
|
||||
.add(REGEX_NUMBER, 'z')
|
||||
.add(OtS_Util.Regex.REGEX_NUMBER, 'z')
|
||||
.toRegExp();
|
||||
|
||||
private static _REGEX_TEXCOORD = new RegExpBuilder()
|
||||
private static _REGEX_TEXCOORD = new OtS_Util.Regex.RegExpBuilder()
|
||||
.add(/^vt/)
|
||||
.addNonzeroWhitespace()
|
||||
.add(REGEX_NUMBER, 'u')
|
||||
.add(OtS_Util.Regex.REGEX_NUMBER, 'u')
|
||||
.addNonzeroWhitespace()
|
||||
.add(REGEX_NUMBER, 'v')
|
||||
.add(OtS_Util.Regex.REGEX_NUMBER, 'v')
|
||||
.toRegExp();
|
||||
|
||||
private static _REGEX_FACE = new RegExpBuilder()
|
||||
private static _REGEX_FACE = new OtS_Util.Regex.RegExpBuilder()
|
||||
.add(/^f/)
|
||||
.addNonzeroWhitespace()
|
||||
.add(/.*/, 'line')
|
||||
|
@ -1,76 +0,0 @@
|
||||
export namespace AppMath {
|
||||
export const RADIANS_0 = degreesToRadians(0.0);
|
||||
export const RADIANS_90 = degreesToRadians(90.0);
|
||||
export const RADIANS_180 = degreesToRadians(180.0);
|
||||
export const RADIANS_270 = degreesToRadians(270.0);
|
||||
|
||||
export function lerp(value: number, start: number, end: number) {
|
||||
return (1 - value) * start + value * end;
|
||||
}
|
||||
|
||||
export function nearlyEqual(a: number, b: number, tolerance: number = 0.0001) {
|
||||
return Math.abs(a - b) < tolerance;
|
||||
}
|
||||
|
||||
export function degreesToRadians(degrees: number) {
|
||||
return degrees * (Math.PI / 180.0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a float in [0, 1] to an int in [0, 255]
|
||||
* @param decimal A number in [0, 1]
|
||||
*/
|
||||
export function uint8(decimal: number) {
|
||||
return Math.floor(decimal * 255);
|
||||
}
|
||||
|
||||
export function largestPowerOfTwoLessThanN(n: number) {
|
||||
return Math.floor(Math.log2(n));
|
||||
}
|
||||
}
|
||||
|
||||
export const argMax = (array: [number]) => {
|
||||
return array.map((x, i) => [x, i]).reduce((r, a) => (a[0] > r[0] ? a : r))[1];
|
||||
};
|
||||
|
||||
export const clamp = (value: number, min: number, max: number) => {
|
||||
return Math.max(Math.min(max, value), min);
|
||||
};
|
||||
|
||||
export const floorToNearest = (value: number, base: number) => {
|
||||
return Math.floor(value / base) * base;
|
||||
};
|
||||
|
||||
export const ceilToNearest = (value: number, base: number) => {
|
||||
return Math.ceil(value / base) * base;
|
||||
};
|
||||
|
||||
export const roundToNearest = (value: number, base: number) => {
|
||||
return Math.round(value / base) * base;
|
||||
};
|
||||
|
||||
export const between = (value: number, min: number, max: number) => {
|
||||
return min <= value && value <= max;
|
||||
};
|
||||
|
||||
export const mapRange = (value: number, fromMin: number, fromMax: number, toMin: number, toMax: number) => {
|
||||
return (value - fromMin) / (fromMax - fromMin) * (toMax - toMin) + toMin;
|
||||
};
|
||||
|
||||
export const wayThrough = (value: number, min: number, max: number) => {
|
||||
// ASSERT(value >= min && value <= max);
|
||||
return (value - min) / (max - min);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returs true if any number in args is NaN
|
||||
*/
|
||||
export const anyNaN = (...args: number[]) => {
|
||||
return args.some((arg) => {
|
||||
return isNaN(arg);
|
||||
});
|
||||
};
|
||||
|
||||
export const degreesToRadians = Math.PI / 180;
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { OtS_ColourAverager, OtS_Colours, RGBA } from "./colour";
|
||||
import { OtS_ColourAverager, RGBA } from "./util/colour";
|
||||
import { OtS_BlockData_PerBlock, OtS_BlockData_PerFace, OtS_FaceData } from "./ots_block_mesh_converter";
|
||||
|
||||
export class OtS_BlockDataBuilder {
|
||||
|
@ -4,7 +4,7 @@
|
||||
* 1.20.2 blocks.
|
||||
*/
|
||||
|
||||
import { RGBA } from "./colour";
|
||||
import { RGBA } from "./util/colour";
|
||||
import { OtS_BlockData_PerBlock } from "./ots_block_mesh_converter";
|
||||
|
||||
const PER_BLOCK: OtS_BlockData_PerBlock<RGBA> = [
|
||||
|
@ -1,7 +1,7 @@
|
||||
|
||||
import { Bounds } from "./bounds";
|
||||
import { UV } from "./util";
|
||||
import { Vector3 } from "./vector"
|
||||
import { Bounds } from "./util/bounds";
|
||||
import { UV } from "./util/types";
|
||||
import { Vector3 } from "./util/vector"
|
||||
|
||||
export interface TextureInfo {
|
||||
name: string,
|
||||
|
@ -1,10 +1,10 @@
|
||||
import { OtS_VoxelMesh } from './ots_voxel_mesh';
|
||||
import { OtS_BlockMesh } from './ots_block_mesh';
|
||||
import { OtS_FaceVisibility, OtS_VoxelMesh_Neighbourhood } from './ots_voxel_mesh_neighbourhood';
|
||||
import { ASSERT } from './util/error_util';
|
||||
import { Vector3 } from './vector';
|
||||
import { RGBA, OtS_Colours, RGBAUtil } from './colour';
|
||||
import { Vector3 } from './util/vector';
|
||||
import { RGBA, RGBAUtil } from './util/colour';
|
||||
import { BLOCK_DATA_DEFAULT } from './ots_block_data_default';
|
||||
import { ASSERT } from './util/util';
|
||||
|
||||
export type OtS_FaceData<T> = {
|
||||
up: T,
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { RGBA, RGBAUtil } from "./colour";
|
||||
//import { Material, OtS_Util } from "./materials";
|
||||
import { RGBA, RGBAUtil } from "./util/colour";
|
||||
import { OtS_Texture } from "./ots_texture";
|
||||
|
||||
export type OtS_MeshSection = { name: string, positionData: Float32Array, normalData: Float32Array, indexData: Uint32Array } & (
|
||||
@ -40,36 +39,4 @@ export namespace OtS_MeshUtil {
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
export class OtS_MaterialSlots {
|
||||
private _slots: Map<number, Material>;
|
||||
|
||||
private constructor() {
|
||||
this._slots = new Map();
|
||||
}
|
||||
|
||||
public static create() {
|
||||
return new OtS_MaterialSlots();
|
||||
}
|
||||
|
||||
public setSlot(index: number, material: Material) {
|
||||
this._slots.set(index, material);
|
||||
}
|
||||
|
||||
public getSlot(index: number) {
|
||||
return this._slots.get(index);
|
||||
}
|
||||
|
||||
public copy() {
|
||||
const clone = OtS_MaterialSlots.create();
|
||||
|
||||
this._slots.forEach((value, key) => {
|
||||
clone.setSlot(key, OtS_Util.copyMaterial(value));
|
||||
});
|
||||
|
||||
return clone;
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
@ -1,12 +1,10 @@
|
||||
import { Bounds } from './bounds';
|
||||
import { RGBA } from './colour';
|
||||
import { degreesToRadians } from './math';
|
||||
import { Bounds } from './util/bounds';
|
||||
import { RGBA } from './util/colour';
|
||||
import { OtS_MeshSection, OtS_MeshUtil } from './ots_materials';
|
||||
import { OtS_Texture } from './ots_texture';
|
||||
import { UV } from "./util";
|
||||
import { ASSERT } from './util/error_util';
|
||||
import { Result } from './util/type_util';
|
||||
import { Vector3 } from "./vector";
|
||||
import { Result, UV } from './util/types';
|
||||
import { Vector3 } from "./util/vector";
|
||||
import { ASSERT, OtS_Util } from './util/util';
|
||||
|
||||
type OtS_VertexData<T> = {
|
||||
v0: T,
|
||||
@ -116,14 +114,14 @@ export class OtS_Mesh {
|
||||
}
|
||||
|
||||
public rotate(pitch: number, roll: number, yaw: number) {
|
||||
const cosa = Math.cos(yaw * degreesToRadians);
|
||||
const sina = Math.sin(yaw * degreesToRadians);
|
||||
const cosa = Math.cos(OtS_Util.Numeric.degreesToRadians(yaw));
|
||||
const sina = Math.sin(OtS_Util.Numeric.degreesToRadians(yaw));
|
||||
|
||||
const cosb = Math.cos(pitch * degreesToRadians);
|
||||
const sinb = Math.sin(pitch * degreesToRadians);
|
||||
const cosb = Math.cos(OtS_Util.Numeric.degreesToRadians(pitch));
|
||||
const sinb = Math.sin(OtS_Util.Numeric.degreesToRadians(pitch));
|
||||
|
||||
const cosc = Math.cos(roll * degreesToRadians);
|
||||
const sinc = Math.sin(roll * degreesToRadians);
|
||||
const cosc = Math.cos(OtS_Util.Numeric.degreesToRadians(roll));
|
||||
const sinc = Math.sin(OtS_Util.Numeric.degreesToRadians(roll));
|
||||
|
||||
const Axx = cosa*cosb;
|
||||
const Axy = cosa*sinb*sinc - sina*cosc;
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { RGBA, RGBAUtil } from "./colour";
|
||||
import { clamp } from "./math";
|
||||
import { TTexelExtension, TTexelInterpolation } from "./util/type_util";
|
||||
import { RGBA, RGBAUtil } from "./util/colour";
|
||||
import { TTexelExtension, TTexelInterpolation } from "./util/types";
|
||||
import { OtS_Util } from "./util/util";
|
||||
|
||||
export class OtS_Texture {
|
||||
private _data: Uint8ClampedArray;
|
||||
@ -100,8 +100,8 @@ export class OtS_Texture {
|
||||
|
||||
// Expects `x` and `y` to be integers
|
||||
private _samplePixel(x: number, y: number): RGBA {
|
||||
const cx = clamp(x, 0, this._width - 1);
|
||||
const cy = clamp(y, 0, this._height - 1);
|
||||
const cx = OtS_Util.Numeric.clamp(x, 0, this._width - 1);
|
||||
const cy = OtS_Util.Numeric.clamp(y, 0, this._height - 1);
|
||||
|
||||
const index = 4 * (this._width * cy + cx);
|
||||
|
||||
@ -114,7 +114,7 @@ export class OtS_Texture {
|
||||
}
|
||||
|
||||
private _clampValue(x: number) {
|
||||
return clamp(x, 0.0, 1.0);
|
||||
return OtS_Util.Numeric.clamp(x, 0.0, 1.0);
|
||||
}
|
||||
|
||||
private _repeatValue(x: number) {
|
||||
|
@ -1,7 +1,7 @@
|
||||
|
||||
import { Bounds } from "./bounds";
|
||||
import { RGBA, RGBAUtil } from './colour';
|
||||
import { Vector3 } from "./vector"
|
||||
import { Bounds } from "./util/bounds";
|
||||
import { RGBA, RGBAUtil } from './util/colour';
|
||||
import { Vector3 } from "./util/vector"
|
||||
|
||||
export type OtS_Voxel = {
|
||||
position: Vector3,
|
||||
|
@ -1,12 +1,11 @@
|
||||
import { OtS_ReplaceMode, OtS_VoxelMesh } from './ots_voxel_mesh';
|
||||
import { TAxis } from './util/type_util';
|
||||
import { Vector3 } from './vector';
|
||||
import { Triangle } from './triangle';
|
||||
import { OtS_Colours, RGBA, RGBAUtil } from './colour';
|
||||
import { TAxis, UV } from './util/types';
|
||||
import { Vector3 } from './util/vector';
|
||||
import { Triangle } from './util/triangle';
|
||||
import { OtS_Colours, RGBA, RGBAUtil } from './util/colour';
|
||||
import { OtS_Mesh, OtS_Triangle } from './ots_mesh';
|
||||
import { UV } from './util';
|
||||
import { rayIntersectTriangleFastX, rayIntersectTriangleFastY, rayIntersectTriangleFastZ, RayIntersect } from './ray';
|
||||
import { OtS_ArrayUtil } from './util/array_util';
|
||||
import { rayIntersectTriangleFastX, rayIntersectTriangleFastY, rayIntersectTriangleFastZ, RayIntersect } from './util/ray';
|
||||
import { OtS_Util } from './util/util';
|
||||
|
||||
export type OtS_VoxelMesh_ConverterConfig = {
|
||||
constraintAxis: TAxis,
|
||||
@ -72,7 +71,7 @@ export class OtS_VoxelMesh_Converter {
|
||||
rayOrigin[a1] = y;
|
||||
let hasHit = false;
|
||||
|
||||
const start = OtS_ArrayUtil.findFirstTrueIndex(bounds.max[a2] - bounds.min[a2] + 1, (index: number) => {
|
||||
const start = OtS_Util.Array.findFirstTrueIndex(bounds.max[a2] - bounds.min[a2] + 1, (index: number) => {
|
||||
rayOrigin[a2] = bounds.min[a2] + index;
|
||||
return intersect(rayOrigin, triangle, edge1, edge2) !== undefined;
|
||||
});
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { OtS_VoxelMesh } from "./ots_voxel_mesh";
|
||||
import { Vector3 } from "./vector";
|
||||
import { Vector3 } from "./util/vector";
|
||||
|
||||
export type OtS_Offset = -1 | 0 | 1;
|
||||
export type OtS_NeighbourhoodMode = 'cardinal' | 'non-cardinal';
|
||||
|
@ -1,47 +0,0 @@
|
||||
import { AppMath } from "./math";
|
||||
import { TBrand } from "./util/type_util";
|
||||
|
||||
export namespace AppUtil {
|
||||
export namespace Text {
|
||||
export function capitaliseFirstLetter(text: string) {
|
||||
return text.charAt(0).toUpperCase() + text.slice(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Namespaces a block name if it is not already namespaced
|
||||
* For example `namespaceBlock('stone')` returns `'minecraft:stone'`
|
||||
*/
|
||||
export function namespaceBlock(blockName: string): AppTypes.TNamespacedBlockName {
|
||||
// https://minecraft.fandom.com/wiki/Resource_location#Namespaces
|
||||
return isNamespacedBlock(blockName) ? blockName : ('minecraft:' + blockName);
|
||||
}
|
||||
|
||||
export function isNamespacedBlock(blockName: string): boolean {
|
||||
return blockName.includes(':');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* eslint-disable */
|
||||
export enum EAction {
|
||||
Settings = 0,
|
||||
Import = 1,
|
||||
Materials = 2,
|
||||
Voxelise = 3,
|
||||
Assign = 4,
|
||||
Export = 5,
|
||||
MAX = 6,
|
||||
}
|
||||
/* eslint-enable */
|
||||
|
||||
export namespace AppTypes {
|
||||
export type TNamespacedBlockName = string;
|
||||
}
|
||||
|
||||
export type UV = { u: number, v: number };
|
||||
|
||||
export type TOptional<T> = T | undefined;
|
||||
|
||||
export function getRandomID(): string {
|
||||
return (Math.random() + 1).toString(36).substring(7);
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
import { AppMath } from "../math";
|
||||
|
||||
export namespace OtS_ArrayUtil {
|
||||
|
||||
export function findFirstTrueIndex(length: number, valueAt: (index: number) => boolean) {
|
||||
let low = 0;
|
||||
let high = length - 1;
|
||||
let result = -1;
|
||||
|
||||
while (low <= high) {
|
||||
const mid = Math.floor((low + high) / 2);
|
||||
|
||||
if (valueAt(mid) === true) {
|
||||
result = mid;
|
||||
high = mid - 1;
|
||||
} else {
|
||||
low = mid + 1;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* An optimised function for repeating a subarray contained within a buffer multiple times by
|
||||
* repeatedly doubling the subarray's length.
|
||||
*/
|
||||
export function repeatedFill(buffer: Float32Array, start: number, startLength: number, desiredCount: number) {
|
||||
const pow = AppMath.largestPowerOfTwoLessThanN(desiredCount);
|
||||
|
||||
let len = startLength;
|
||||
for (let i = 0; i < pow; ++i) {
|
||||
buffer.copyWithin(start + len, start, start + len);
|
||||
len *= 2;
|
||||
}
|
||||
|
||||
const finalLength = desiredCount * startLength;
|
||||
buffer.copyWithin(start + len, start, start + finalLength - len);
|
||||
}
|
||||
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
import { TBrand } from './util/type_util';
|
||||
import { TBrand } from './types';
|
||||
|
||||
export type RGBA = {
|
||||
r: number,
|
@ -1,5 +1,5 @@
|
||||
import { RGBA_255 } from './colour';
|
||||
import { ASSERT } from './util/error_util';
|
||||
import { ASSERT } from './util';
|
||||
import { Vector3 } from './vector';
|
||||
|
||||
export class Ditherer {
|
@ -1,6 +0,0 @@
|
||||
export function ASSERT(condition: any, errorMessage: string = 'Assertion Failed'): asserts condition {
|
||||
if (!condition) {
|
||||
Error(errorMessage);
|
||||
throw Error(errorMessage);
|
||||
}
|
||||
}
|
@ -1,184 +0,0 @@
|
||||
/**
|
||||
* Logs to console and file if logging `LOG` is enabled.
|
||||
* This should be used for verbose logs.
|
||||
* @see LOG_MAJOR
|
||||
*/
|
||||
export const LOG = (...data: any[]) => {
|
||||
if (Logger.Get.isLOGEnabled()) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(...data);
|
||||
}
|
||||
};
|
||||
|
||||
export const LOGF = LOG;
|
||||
|
||||
/**
|
||||
* Logs to console and file if logging `LOG_MAJOR` is enabled.
|
||||
* This is identical to `LOG` but can be enabled/disabled separately.
|
||||
* This should be used for important logs.
|
||||
* @see LOG
|
||||
*/
|
||||
export const LOG_MAJOR = (...data: any[]) => {
|
||||
if (Logger.Get.isLOGMAJOREnabled()) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(...data);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Logs a warning to the console and file if logging `LOG_WARN` is enabled.
|
||||
*/
|
||||
export const LOG_WARN = (...data: any[]) => {
|
||||
if (Logger.Get.isLOGWARNEnabled()) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.warn(...data);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Starts a timer.
|
||||
* @see `TIME_END` To stop the timer.
|
||||
* @param label The ID of this timer.
|
||||
*/
|
||||
export const TIME_START = (label: string) => {
|
||||
if (Logger.Get.isLOGTIMEEnabled()) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.time(label);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Stops a timer and prints the time elapsed. Not logged to file.
|
||||
* @see `TIME_START` To start the timer.
|
||||
* @param label The ID of this timer.
|
||||
*/
|
||||
export const TIME_END = (label: string) => {
|
||||
if (Logger.Get.isLOGTIMEEnabled()) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.timeEnd(label);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Logs an error to the console and file, always.
|
||||
*/
|
||||
export const LOG_ERROR = (...data: any[]) => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(...data);
|
||||
};
|
||||
|
||||
/**
|
||||
* Logger controls enable/disabling the logging functions above.
|
||||
*/
|
||||
export class Logger {
|
||||
/* Singleton */
|
||||
private static _instance: Logger;
|
||||
public static get Get() {
|
||||
return this._instance || (this._instance = new this());
|
||||
}
|
||||
|
||||
private _enabledLOG: boolean;
|
||||
private _enabledLOGMAJOR: boolean;
|
||||
private _enabledLOGWARN: boolean;
|
||||
private _enabledLOGTIME: boolean;
|
||||
|
||||
private _enabledLogToFile?: boolean;
|
||||
|
||||
private constructor() {
|
||||
this._enabledLOG = false;
|
||||
this._enabledLOGMAJOR = false;
|
||||
this._enabledLOGWARN = false;
|
||||
this._enabledLOGTIME = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow `LOG` calls to be printed to the console and to the log file if setup.
|
||||
*/
|
||||
public enableLOG() {
|
||||
this._enabledLOG = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent `LOG` calls to be printed to the console and to the log file if setup.
|
||||
*/
|
||||
public disableLOG() {
|
||||
this._enabledLOG = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow `LOG_MAJOR` calls to be printed to the console and to the log file if setup.
|
||||
*/
|
||||
public enableLOGMAJOR() {
|
||||
this._enabledLOGMAJOR = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent `LOG_MAJOR` calls to be printed to the console and to the log file if setup.
|
||||
*/
|
||||
public disableLOGMAJOR() {
|
||||
this._enabledLOGMAJOR = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow `LOG_WARN` calls to be printed to the console and to the log file if setup.
|
||||
*/
|
||||
public enableLOGWARN() {
|
||||
this._enabledLOGWARN = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent `LOG_WARN` calls to be printed to the console and to the log file if setup.
|
||||
*/
|
||||
public disableLOGWARN() {
|
||||
this._enabledLOGWARN = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow `TIME_START`/`TIME_END` calls to be printed to the console and to the log file if setup.
|
||||
*/
|
||||
public enableLOGTIME() {
|
||||
this._enabledLOGTIME = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent `TIME_START`/`TIME_END` calls to be printed to the console and to the log file if setup.
|
||||
*/
|
||||
public disableLOGTIME() {
|
||||
this._enabledLOGTIME = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent console log calls to logged to the log file if setup.
|
||||
*/
|
||||
public disableLogToFile() {
|
||||
this._enabledLogToFile = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not `LOG` calls should be printed to the console and log file.
|
||||
*/
|
||||
public isLOGEnabled() {
|
||||
return this._enabledLOG;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not `LOG_MAJOR` calls should be printed to the console and log file.
|
||||
*/
|
||||
public isLOGMAJOREnabled() {
|
||||
return this._enabledLOGMAJOR;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not `LOG_WARN` calls should be printed to the console and log file.
|
||||
*/
|
||||
public isLOGWARNEnabled() {
|
||||
return this._enabledLOGWARN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not `TIME_START`/`TIME_END` calls should be printed to the console and log file.
|
||||
*/
|
||||
public isLOGTIMEEnabled() {
|
||||
return this._enabledLOGTIME;
|
||||
}
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
export namespace MathUtil {
|
||||
|
||||
export function uint8(x: number) {
|
||||
return x & 0xFF;
|
||||
}
|
||||
|
||||
export function int8(x: number) {
|
||||
return uint8(x + 0x80) - 0x80;
|
||||
}
|
||||
|
||||
export function uint32(x: number) {
|
||||
return x >>> 0;
|
||||
}
|
||||
|
||||
export function int32(x: number) {
|
||||
return uint32(x + 0x80000000) - 0x80000000;
|
||||
}
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
import { NBT, writeUncompressed } from 'prismarine-nbt';
|
||||
import pako from 'pako';
|
||||
|
||||
export function saveNBT(nbt: NBT) {
|
||||
const uncompressedBuffer = writeUncompressed(nbt, 'big');
|
||||
return pako.gzip(uncompressedBuffer);
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
import { OtS_Triangle } from './ots_mesh';
|
||||
import { ASSERT } from './util/error_util';
|
||||
import { OtS_Triangle } from '../ots_mesh';
|
||||
import { ASSERT } from './util';
|
||||
import { Vector3 } from './vector';
|
||||
|
||||
const EPSILON = 0.0000001;
|
@ -1,71 +0,0 @@
|
||||
/** Regex for non-zero whitespace */
|
||||
export const REGEX_NZ_WS = /[ \t]+/;
|
||||
|
||||
/** Regex for number */
|
||||
export const REGEX_NUMBER = /[0-9eE+\.\-]+/;
|
||||
|
||||
export const REGEX_NZ_ANY = /.+/;
|
||||
|
||||
export function regexCapture(identifier: string, regex: RegExp) {
|
||||
return new RegExp(`(?<${identifier}>${regex.source}`);
|
||||
}
|
||||
|
||||
export function regexOptional(regex: RegExp) {
|
||||
return new RegExp(`(${regex})?`);
|
||||
}
|
||||
|
||||
export function buildRegex(...args: (string | RegExp)[]) {
|
||||
return new RegExp(args.map((r) => {
|
||||
if (r instanceof RegExp) {
|
||||
return r.source;
|
||||
}
|
||||
return r;
|
||||
}).join(''));
|
||||
}
|
||||
|
||||
export class RegExpBuilder {
|
||||
private _components: string[];
|
||||
|
||||
public constructor() {
|
||||
this._components = [];
|
||||
}
|
||||
|
||||
public add(item: string | RegExp, capture?: string, optional: boolean = false): RegExpBuilder {
|
||||
let regex: string;
|
||||
if (item instanceof RegExp) {
|
||||
regex = item.source;
|
||||
} else {
|
||||
regex = item;
|
||||
}
|
||||
if (capture) {
|
||||
regex = `(?<${capture}>${regex})`;
|
||||
}
|
||||
if (optional) {
|
||||
regex = `(${regex})?`;
|
||||
}
|
||||
this._components.push(regex);
|
||||
return this;
|
||||
}
|
||||
|
||||
public addMany(items: (string | RegExp)[], optional: boolean = false): RegExpBuilder {
|
||||
let toAdd: string = '';
|
||||
for (const item of items) {
|
||||
if (item instanceof RegExp) {
|
||||
toAdd += item.source;
|
||||
} else {
|
||||
toAdd += item;
|
||||
}
|
||||
}
|
||||
this._components.push(optional ? `(${toAdd})?` : toAdd);
|
||||
return this;
|
||||
}
|
||||
|
||||
public addNonzeroWhitespace(): RegExpBuilder {
|
||||
this.add(REGEX_NZ_WS);
|
||||
return this;
|
||||
}
|
||||
|
||||
public toRegExp(): RegExp {
|
||||
return new RegExp(this._components.join(''));
|
||||
}
|
||||
}
|
@ -21,4 +21,8 @@ export type BlockPalette = Set<string>;
|
||||
|
||||
export type Result<T, E = Error> =
|
||||
| { ok: true, value: T }
|
||||
| { ok: false, error: { code: E, message?: string } };
|
||||
| { ok: false, error: { code: E, message?: string } };
|
||||
|
||||
export type UV = { u: number, v: number };
|
||||
|
||||
export type TOptional<T> = T | undefined;
|
248
Core/src/util/util.ts
Normal file
248
Core/src/util/util.ts
Normal file
@ -0,0 +1,248 @@
|
||||
import { NBT, writeUncompressed } from 'prismarine-nbt';
|
||||
import pako from 'pako';
|
||||
|
||||
export function ASSERT(condition: any, errorMessage: string = 'Assertion Failed'): asserts condition {
|
||||
if (!condition) {
|
||||
Error(errorMessage);
|
||||
throw Error(errorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Move to Editor
|
||||
export enum EAction {
|
||||
Settings = 0,
|
||||
Import = 1,
|
||||
Materials = 2,
|
||||
Voxelise = 3,
|
||||
Assign = 4,
|
||||
Export = 5,
|
||||
MAX = 6,
|
||||
}
|
||||
|
||||
export namespace OtS_Util {
|
||||
|
||||
export namespace Regex {
|
||||
/** Regex for non-zero whitespace */
|
||||
export const REGEX_NZ_WS = /[ \t]+/;
|
||||
|
||||
/** Regex for number */
|
||||
export const REGEX_NUMBER = /[0-9eE+\.\-]+/;
|
||||
|
||||
export const REGEX_NZ_ANY = /.+/;
|
||||
|
||||
export function regexCapture(identifier: string, regex: RegExp) {
|
||||
return new RegExp(`(?<${identifier}>${regex.source}`);
|
||||
}
|
||||
|
||||
export function regexOptional(regex: RegExp) {
|
||||
return new RegExp(`(${regex})?`);
|
||||
}
|
||||
|
||||
export function buildRegex(...args: (string | RegExp)[]) {
|
||||
return new RegExp(args.map((r) => {
|
||||
if (r instanceof RegExp) {
|
||||
return r.source;
|
||||
}
|
||||
return r;
|
||||
}).join(''));
|
||||
}
|
||||
|
||||
export class RegExpBuilder {
|
||||
private _components: string[];
|
||||
|
||||
public constructor() {
|
||||
this._components = [];
|
||||
}
|
||||
|
||||
public add(item: string | RegExp, capture?: string, optional: boolean = false): RegExpBuilder {
|
||||
let regex: string;
|
||||
if (item instanceof RegExp) {
|
||||
regex = item.source;
|
||||
} else {
|
||||
regex = item;
|
||||
}
|
||||
if (capture) {
|
||||
regex = `(?<${capture}>${regex})`;
|
||||
}
|
||||
if (optional) {
|
||||
regex = `(${regex})?`;
|
||||
}
|
||||
this._components.push(regex);
|
||||
return this;
|
||||
}
|
||||
|
||||
public addMany(items: (string | RegExp)[], optional: boolean = false): RegExpBuilder {
|
||||
let toAdd: string = '';
|
||||
for (const item of items) {
|
||||
if (item instanceof RegExp) {
|
||||
toAdd += item.source;
|
||||
} else {
|
||||
toAdd += item;
|
||||
}
|
||||
}
|
||||
this._components.push(optional ? `(${toAdd})?` : toAdd);
|
||||
return this;
|
||||
}
|
||||
|
||||
public addNonzeroWhitespace(): RegExpBuilder {
|
||||
this.add(REGEX_NZ_WS);
|
||||
return this;
|
||||
}
|
||||
|
||||
public toRegExp(): RegExp {
|
||||
return new RegExp(this._components.join(''));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export namespace Text {
|
||||
export function capitaliseFirstLetter(text: string) {
|
||||
return text.charAt(0).toUpperCase() + text.slice(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Namespaces a block name if it is not already namespaced
|
||||
* For example `namespaceBlock('stone')` returns `'minecraft:stone'`
|
||||
*/
|
||||
export function namespaceBlock(blockName: string): string {
|
||||
// https://minecraft.fandom.com/wiki/Resource_location#Namespaces
|
||||
return isNamespacedBlock(blockName) ? blockName : ('minecraft:' + blockName);
|
||||
}
|
||||
|
||||
export function isNamespacedBlock(blockName: string): boolean {
|
||||
return blockName.includes(':');
|
||||
}
|
||||
}
|
||||
|
||||
export namespace Numeric {
|
||||
export const RADIANS_0 = 0.0;
|
||||
export const RADIANS_90 = 1.5708;
|
||||
export const RADIANS_180 = 3.14159;
|
||||
export const RADIANS_270 = 4.71239;
|
||||
|
||||
export function getRandomID(): string {
|
||||
return (Math.random() + 1).toString(36).substring(7);
|
||||
}
|
||||
|
||||
export function uint8(x: number) {
|
||||
return x & 0xFF;
|
||||
}
|
||||
|
||||
export function int8(x: number) {
|
||||
return uint8(x + 0x80) - 0x80;
|
||||
}
|
||||
|
||||
export function uint32(x: number) {
|
||||
return x >>> 0;
|
||||
}
|
||||
|
||||
export function int32(x: number) {
|
||||
return uint32(x + 0x80000000) - 0x80000000;
|
||||
}
|
||||
|
||||
export function lerp(value: number, start: number, end: number) {
|
||||
return (1 - value) * start + value * end;
|
||||
}
|
||||
|
||||
export function nearlyEqual(a: number, b: number, tolerance: number = 0.0001) {
|
||||
return Math.abs(a - b) < tolerance;
|
||||
}
|
||||
|
||||
export function degreesToRadians(degrees: number) {
|
||||
return degrees * (Math.PI / 180.0);
|
||||
}
|
||||
|
||||
export function largestPowerOfTwoLessThanN(n: number) {
|
||||
return Math.floor(Math.log2(n));
|
||||
}
|
||||
|
||||
|
||||
export const argMax = (array: [number]) => {
|
||||
return array.map((x, i) => [x, i]).reduce((r, a) => (a[0] > r[0] ? a : r))[1];
|
||||
};
|
||||
|
||||
export const clamp = (value: number, min: number, max: number) => {
|
||||
return Math.max(Math.min(max, value), min);
|
||||
};
|
||||
|
||||
export const floorToNearest = (value: number, base: number) => {
|
||||
return Math.floor(value / base) * base;
|
||||
};
|
||||
|
||||
export const ceilToNearest = (value: number, base: number) => {
|
||||
return Math.ceil(value / base) * base;
|
||||
};
|
||||
|
||||
export const roundToNearest = (value: number, base: number) => {
|
||||
return Math.round(value / base) * base;
|
||||
};
|
||||
|
||||
export const between = (value: number, min: number, max: number) => {
|
||||
return min <= value && value <= max;
|
||||
};
|
||||
|
||||
export const mapRange = (value: number, fromMin: number, fromMax: number, toMin: number, toMax: number) => {
|
||||
return (value - fromMin) / (fromMax - fromMin) * (toMax - toMin) + toMin;
|
||||
};
|
||||
|
||||
export const wayThrough = (value: number, min: number, max: number) => {
|
||||
// ASSERT(value >= min && value <= max);
|
||||
return (value - min) / (max - min);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returs true if any number in args is NaN
|
||||
*/
|
||||
export const anyNaN = (...args: number[]) => {
|
||||
return args.some((arg) => {
|
||||
return isNaN(arg);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export namespace Array {
|
||||
export function findFirstTrueIndex(length: number, valueAt: (index: number) => boolean) {
|
||||
let low = 0;
|
||||
let high = length - 1;
|
||||
let result = -1;
|
||||
|
||||
while (low <= high) {
|
||||
const mid = Math.floor((low + high) / 2);
|
||||
|
||||
if (valueAt(mid) === true) {
|
||||
result = mid;
|
||||
high = mid - 1;
|
||||
} else {
|
||||
low = mid + 1;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* An optimised function for repeating a subarray contained within a buffer multiple times by
|
||||
* repeatedly doubling the subarray's length.
|
||||
*/
|
||||
export function repeatedFill(buffer: Float32Array, start: number, startLength: number, desiredCount: number) {
|
||||
const pow = Numeric.largestPowerOfTwoLessThanN(desiredCount);
|
||||
|
||||
let len = startLength;
|
||||
for (let i = 0; i < pow; ++i) {
|
||||
buffer.copyWithin(start + len, start, start + len);
|
||||
len *= 2;
|
||||
}
|
||||
|
||||
const finalLength = desiredCount * startLength;
|
||||
buffer.copyWithin(start + len, start, start + finalLength - len);
|
||||
}
|
||||
}
|
||||
|
||||
export namespace NBT {
|
||||
export function saveNBT(nbt: NBT) {
|
||||
const uncompressedBuffer = writeUncompressed(nbt, 'big');
|
||||
return pako.gzip(uncompressedBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,5 +1,4 @@
|
||||
import { ASSERT } from './util/error_util';
|
||||
import { Vector3Hash } from './util/type_util';
|
||||
import { Vector3Hash } from './types';
|
||||
|
||||
export class Vector3 {
|
||||
public x: number;
|
||||
@ -25,8 +24,7 @@ export class Vector3 {
|
||||
}
|
||||
|
||||
static fromArray(arr: number[]) {
|
||||
ASSERT(arr.length === 3);
|
||||
return new Vector3(arr[0], arr[1], arr[2]);
|
||||
return new Vector3(arr[0] ?? 0, arr[1] ?? 0, arr[2] ?? 0);
|
||||
}
|
||||
|
||||
toArray() {
|
Loading…
x
Reference in New Issue
Block a user