minerender 2.1.0-alpha.73 → 2.1.0-alpha.75
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser/index.d.mts +9 -1
- package/dist/browser/index.d.ts +9 -1
- package/dist/browser/index.js +97 -19
- package/dist/browser/index.js.map +1 -1
- package/dist/browser/index.mjs +97 -19
- package/dist/browser/index.mjs.map +1 -1
- package/dist/bundle.js +97 -19
- package/dist/bundle.js.map +1 -1
- package/dist/node/index.d.mts +9 -1
- package/dist/node/index.d.ts +9 -1
- package/dist/node/index.js +97 -19
- package/dist/node/index.js.map +1 -1
- package/dist/node/index.mjs +97 -19
- package/dist/node/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/browser/index.d.mts
CHANGED
|
@@ -291,7 +291,7 @@ declare class Materials {
|
|
|
291
291
|
*/
|
|
292
292
|
static createEntityCanvasMaterial(canvas: HTMLCanvasElement, mode?: EntityRenderMode, tint?: ColorRepresentation): MeshBasicMaterial;
|
|
293
293
|
static createGuiCanvasMaterial(canvas: HTMLCanvasElement): MeshBasicMaterial;
|
|
294
|
-
static createShadedCanvasMaterial(canvas: HTMLCanvasElement, transparent?: boolean, shade?: boolean): Material;
|
|
294
|
+
static createShadedCanvasMaterial(canvas: HTMLCanvasElement, transparent?: boolean, shade?: boolean, boundUvs?: boolean): Material;
|
|
295
295
|
static getImage(key: MaterialKey): Material;
|
|
296
296
|
static needsUpdate(mat: Material): void;
|
|
297
297
|
}
|
|
@@ -693,6 +693,8 @@ declare class UVMapper {
|
|
|
693
693
|
static setCubeUvs(geometry: BoxGeometry, originalTextureSize: DoubleArray, actualTextureSize: DoubleArray, faces: ModelFaces): void;
|
|
694
694
|
static facesToUvArray(faces: ModelFaces, originalTextureSize: DoubleArray, actualTextureSize: DoubleArray): number[];
|
|
695
695
|
static facesToUv(faces: ModelFaces, originalTextureSize: DoubleArray, actualTextureSize: DoubleArray): Float32BufferAttribute;
|
|
696
|
+
/** Bounds texture sampling to texel centres without changing cropped face UVs. */
|
|
697
|
+
static setAtlasUvBounds(geometry: BoxGeometry, faces: ModelFaces, atlas: TextureAtlas): void;
|
|
696
698
|
static lockUvs(geometry: BoxGeometry, faces: ModelFaces, atlas: TextureAtlas, rotation: Euler): void;
|
|
697
699
|
static getAtlas(model: Model): Promise<Maybe<TextureAtlas>>;
|
|
698
700
|
static fillMissingTextureKeys<T>(textures: ModelTextures, target: {
|
|
@@ -2515,6 +2517,12 @@ declare class MineRenderWorld<SectionMeshing extends boolean = false> {
|
|
|
2515
2517
|
private placeBlocks;
|
|
2516
2518
|
/** Replaces one chunk column's blocks. Entity NBT remains available on the parsed chunk. */
|
|
2517
2519
|
placeChunk(chunk: AnvilChunk, executor?: BatchedExecutor): Promise<void>;
|
|
2520
|
+
/**
|
|
2521
|
+
* Removes all sections at integer chunk-column coordinates, then refreshes neighboring faces and fluids.
|
|
2522
|
+
* Coordinates match AnvilChunk.x/z, not block positions. Missing columns are ignored.
|
|
2523
|
+
*/
|
|
2524
|
+
unloadChunkColumn(x: number, z: number): Promise<void>;
|
|
2525
|
+
private clearChunkColumn;
|
|
2518
2526
|
clear(): Promise<void>;
|
|
2519
2527
|
private updateCulling;
|
|
2520
2528
|
private getOrCreateChunkAt;
|
package/dist/browser/index.d.ts
CHANGED
|
@@ -291,7 +291,7 @@ declare class Materials {
|
|
|
291
291
|
*/
|
|
292
292
|
static createEntityCanvasMaterial(canvas: HTMLCanvasElement, mode?: EntityRenderMode, tint?: ColorRepresentation): MeshBasicMaterial;
|
|
293
293
|
static createGuiCanvasMaterial(canvas: HTMLCanvasElement): MeshBasicMaterial;
|
|
294
|
-
static createShadedCanvasMaterial(canvas: HTMLCanvasElement, transparent?: boolean, shade?: boolean): Material;
|
|
294
|
+
static createShadedCanvasMaterial(canvas: HTMLCanvasElement, transparent?: boolean, shade?: boolean, boundUvs?: boolean): Material;
|
|
295
295
|
static getImage(key: MaterialKey): Material;
|
|
296
296
|
static needsUpdate(mat: Material): void;
|
|
297
297
|
}
|
|
@@ -693,6 +693,8 @@ declare class UVMapper {
|
|
|
693
693
|
static setCubeUvs(geometry: BoxGeometry, originalTextureSize: DoubleArray, actualTextureSize: DoubleArray, faces: ModelFaces): void;
|
|
694
694
|
static facesToUvArray(faces: ModelFaces, originalTextureSize: DoubleArray, actualTextureSize: DoubleArray): number[];
|
|
695
695
|
static facesToUv(faces: ModelFaces, originalTextureSize: DoubleArray, actualTextureSize: DoubleArray): Float32BufferAttribute;
|
|
696
|
+
/** Bounds texture sampling to texel centres without changing cropped face UVs. */
|
|
697
|
+
static setAtlasUvBounds(geometry: BoxGeometry, faces: ModelFaces, atlas: TextureAtlas): void;
|
|
696
698
|
static lockUvs(geometry: BoxGeometry, faces: ModelFaces, atlas: TextureAtlas, rotation: Euler): void;
|
|
697
699
|
static getAtlas(model: Model): Promise<Maybe<TextureAtlas>>;
|
|
698
700
|
static fillMissingTextureKeys<T>(textures: ModelTextures, target: {
|
|
@@ -2515,6 +2517,12 @@ declare class MineRenderWorld<SectionMeshing extends boolean = false> {
|
|
|
2515
2517
|
private placeBlocks;
|
|
2516
2518
|
/** Replaces one chunk column's blocks. Entity NBT remains available on the parsed chunk. */
|
|
2517
2519
|
placeChunk(chunk: AnvilChunk, executor?: BatchedExecutor): Promise<void>;
|
|
2520
|
+
/**
|
|
2521
|
+
* Removes all sections at integer chunk-column coordinates, then refreshes neighboring faces and fluids.
|
|
2522
|
+
* Coordinates match AnvilChunk.x/z, not block positions. Missing columns are ignored.
|
|
2523
|
+
*/
|
|
2524
|
+
unloadChunkColumn(x: number, z: number): Promise<void>;
|
|
2525
|
+
private clearChunkColumn;
|
|
2518
2526
|
clear(): Promise<void>;
|
|
2519
2527
|
private updateCulling;
|
|
2520
2528
|
private getOrCreateChunkAt;
|
package/dist/browser/index.js
CHANGED
|
@@ -982,7 +982,7 @@ var init_Materials = __esm({
|
|
|
982
982
|
};
|
|
983
983
|
return material;
|
|
984
984
|
}
|
|
985
|
-
static createShadedCanvasMaterial(canvas, transparent = false, shade = false) {
|
|
985
|
+
static createShadedCanvasMaterial(canvas, transparent = false, shade = false, boundUvs = false) {
|
|
986
986
|
const vertShader = `
|
|
987
987
|
uniform bool SHADE;
|
|
988
988
|
|
|
@@ -992,6 +992,10 @@ var init_Materials = __esm({
|
|
|
992
992
|
#else
|
|
993
993
|
varying vec2 vUv;
|
|
994
994
|
#endif
|
|
995
|
+
#ifdef BOUND_UVS
|
|
996
|
+
attribute vec4 uvBounds;
|
|
997
|
+
flat out vec4 vUvBounds;
|
|
998
|
+
#endif
|
|
995
999
|
varying vec3 vTint;
|
|
996
1000
|
varying float light;
|
|
997
1001
|
varying float lift;
|
|
@@ -1027,13 +1031,17 @@ var init_Materials = __esm({
|
|
|
1027
1031
|
}
|
|
1028
1032
|
|
|
1029
1033
|
vUv = uv;
|
|
1034
|
+
#ifdef BOUND_UVS
|
|
1035
|
+
vUvBounds = uvBounds;
|
|
1036
|
+
#endif
|
|
1030
1037
|
vTint = color;
|
|
1031
1038
|
|
|
1039
|
+
vec4 mvPosition = vec4(position, 1.0);
|
|
1032
1040
|
#ifdef USE_INSTANCING
|
|
1033
|
-
|
|
1034
|
-
#else
|
|
1035
|
-
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
|
|
1041
|
+
mvPosition = instanceMatrix * mvPosition;
|
|
1036
1042
|
#endif
|
|
1043
|
+
mvPosition = modelViewMatrix * mvPosition;
|
|
1044
|
+
gl_Position = projectionMatrix * mvPosition;
|
|
1037
1045
|
|
|
1038
1046
|
}
|
|
1039
1047
|
`;
|
|
@@ -1053,13 +1061,22 @@ var init_Materials = __esm({
|
|
|
1053
1061
|
#else
|
|
1054
1062
|
varying vec2 vUv;
|
|
1055
1063
|
#endif
|
|
1064
|
+
#ifdef BOUND_UVS
|
|
1065
|
+
flat in vec4 vUvBounds;
|
|
1066
|
+
#endif
|
|
1056
1067
|
varying vec3 vTint;
|
|
1057
1068
|
varying float light;
|
|
1058
1069
|
varying float lift;
|
|
1059
1070
|
|
|
1060
1071
|
void main(void)
|
|
1061
1072
|
{
|
|
1062
|
-
|
|
1073
|
+
#ifdef BOUND_UVS
|
|
1074
|
+
// Keep edge samples inside their texture even without centroid interpolation.
|
|
1075
|
+
vec2 mapUv = clamp(vUv, vUvBounds.xy, vUvBounds.zw);
|
|
1076
|
+
#else
|
|
1077
|
+
vec2 mapUv = vUv;
|
|
1078
|
+
#endif
|
|
1079
|
+
vec4 color = texture2D(map, mapUv);
|
|
1063
1080
|
color.rgb *= vTint;
|
|
1064
1081
|
|
|
1065
1082
|
if (color.a < 0.01) discard;
|
|
@@ -1080,7 +1097,8 @@ var init_Materials = __esm({
|
|
|
1080
1097
|
}
|
|
1081
1098
|
`;
|
|
1082
1099
|
try {
|
|
1083
|
-
|
|
1100
|
+
const material = new import_three5.ShaderMaterial({
|
|
1101
|
+
defines: boundUvs ? { BOUND_UVS: true } : {},
|
|
1084
1102
|
uniforms: {
|
|
1085
1103
|
SHADE: { value: true },
|
|
1086
1104
|
BRIGHTNESS: { value: 1 },
|
|
@@ -1098,6 +1116,8 @@ var init_Materials = __esm({
|
|
|
1098
1116
|
side: transparent ? import_three5.DoubleSide : import_three5.FrontSide,
|
|
1099
1117
|
alphaTest: 0.5
|
|
1100
1118
|
});
|
|
1119
|
+
Object.assign(material.defaultAttributeValues, { uvBounds: [0, 0, 1, 1] });
|
|
1120
|
+
return material;
|
|
1101
1121
|
} catch (e) {
|
|
1102
1122
|
console.warn(e);
|
|
1103
1123
|
}
|
|
@@ -2979,6 +2999,37 @@ var init_UVMapper = __esm({
|
|
|
2979
2999
|
static facesToUv(faces, originalTextureSize, actualTextureSize) {
|
|
2980
3000
|
return new import_three9.Float32BufferAttribute(this.facesToUvArray(faces, originalTextureSize, actualTextureSize), 2);
|
|
2981
3001
|
}
|
|
3002
|
+
/** Bounds texture sampling to texel centres without changing cropped face UVs. */
|
|
3003
|
+
static setAtlasUvBounds(geometry, faces, atlas) {
|
|
3004
|
+
const uv = geometry.getAttribute("uv");
|
|
3005
|
+
const bounds = new Float32Array(uv.count * 4);
|
|
3006
|
+
for (const [faceIndex, faceName] of CUBE_FACES.entries()) {
|
|
3007
|
+
const texture = faces[faceName]?.texture?.substring(1);
|
|
3008
|
+
const position = texture && atlas.positions[texture];
|
|
3009
|
+
const size = texture && atlas.sizes[texture];
|
|
3010
|
+
let minU = Infinity, minV = Infinity, maxU = -Infinity, maxV = -Infinity;
|
|
3011
|
+
if (position && size) {
|
|
3012
|
+
minU = position[0] / atlas.image.width;
|
|
3013
|
+
maxU = (position[0] + size[0]) / atlas.image.width;
|
|
3014
|
+
minV = 1 - (position[1] + size[1]) / atlas.image.height;
|
|
3015
|
+
maxV = 1 - position[1] / atlas.image.height;
|
|
3016
|
+
} else {
|
|
3017
|
+
for (let corner = 0; corner < 4; corner++) {
|
|
3018
|
+
const index = faceIndex * 4 + corner;
|
|
3019
|
+
minU = Math.min(minU, uv.getX(index));
|
|
3020
|
+
minV = Math.min(minV, uv.getY(index));
|
|
3021
|
+
maxU = Math.max(maxU, uv.getX(index));
|
|
3022
|
+
maxV = Math.max(maxV, uv.getY(index));
|
|
3023
|
+
}
|
|
3024
|
+
}
|
|
3025
|
+
const insetU = Math.min(0.5 / atlas.image.width, (maxU - minU) / 2);
|
|
3026
|
+
const insetV = Math.min(0.5 / atlas.image.height, (maxV - minV) / 2);
|
|
3027
|
+
for (let corner = 0; corner < 4; corner++) {
|
|
3028
|
+
bounds.set([minU + insetU, minV + insetV, maxU - insetU, maxV - insetV], (faceIndex * 4 + corner) * 4);
|
|
3029
|
+
}
|
|
3030
|
+
}
|
|
3031
|
+
geometry.setAttribute("uvBounds", new import_three9.Float32BufferAttribute(bounds, 4));
|
|
3032
|
+
}
|
|
2982
3033
|
static lockUvs(geometry, faces, atlas, rotation) {
|
|
2983
3034
|
const uv = geometry.getAttribute("uv");
|
|
2984
3035
|
for (let faceIndex = 0; faceIndex < CUBE_FACES.length; faceIndex++) {
|
|
@@ -5376,6 +5427,7 @@ var init_ModelObject = __esm({
|
|
|
5376
5427
|
if (this.options.uvLockRotation) {
|
|
5377
5428
|
UVMapper.lockUvs(elGeo, el.faces, this.atlas, new import_three25.Euler(...this.options.uvLockRotation));
|
|
5378
5429
|
}
|
|
5430
|
+
UVMapper.setAtlasUvBounds(elGeo, el.faces, this.atlas);
|
|
5379
5431
|
if (this.options.tints) {
|
|
5380
5432
|
const colors = new Float32Array(elGeo.getAttribute("position").count * 3).fill(1);
|
|
5381
5433
|
for (const [faceIndex, faceName] of CUBE_FACES.entries()) {
|
|
@@ -5441,7 +5493,7 @@ var init_ModelObject = __esm({
|
|
|
5441
5493
|
}
|
|
5442
5494
|
applyTextures() {
|
|
5443
5495
|
if (this.atlas) {
|
|
5444
|
-
const mat = Materials.createShadedCanvasMaterial(this.atlas.image.canvas, this.atlas.hasTransparency, false);
|
|
5496
|
+
const mat = Materials.createShadedCanvasMaterial(this.atlas.image.canvas, this.atlas.hasTransparency, false, true);
|
|
5445
5497
|
this.atlasMaterial = mat;
|
|
5446
5498
|
this.atlasTexture = mat.uniforms?.map?.value ?? mat.map;
|
|
5447
5499
|
this.iterateAllMeshes((mesh) => {
|
|
@@ -15355,13 +15407,7 @@ var MineRenderWorld = class {
|
|
|
15355
15407
|
async placeChunk(chunk, executor) {
|
|
15356
15408
|
const changes = /* @__PURE__ */ new Map();
|
|
15357
15409
|
try {
|
|
15358
|
-
|
|
15359
|
-
for (const [key, section] of previous) {
|
|
15360
|
-
this._chunks.delete(key);
|
|
15361
|
-
await section.clear(async (positions) => {
|
|
15362
|
-
for (const pos of positions) changes.set(pos.toArray().join(","), pos);
|
|
15363
|
-
});
|
|
15364
|
-
}
|
|
15410
|
+
await this.clearChunkColumn(chunk.x, chunk.z, changes);
|
|
15365
15411
|
for (const section of chunk.sections) {
|
|
15366
15412
|
const blocks = [];
|
|
15367
15413
|
for (let index = 0; index < 4096; index++) {
|
|
@@ -15381,6 +15427,31 @@ var MineRenderWorld = class {
|
|
|
15381
15427
|
await this.updateCulling([...changes.values()]);
|
|
15382
15428
|
}
|
|
15383
15429
|
}
|
|
15430
|
+
/**
|
|
15431
|
+
* Removes all sections at integer chunk-column coordinates, then refreshes neighboring faces and fluids.
|
|
15432
|
+
* Coordinates match AnvilChunk.x/z, not block positions. Missing columns are ignored.
|
|
15433
|
+
*/
|
|
15434
|
+
async unloadChunkColumn(x, z) {
|
|
15435
|
+
if (!Number.isInteger(x) || !Number.isInteger(z)) {
|
|
15436
|
+
throw new RangeError("Chunk column coordinates must be integers");
|
|
15437
|
+
}
|
|
15438
|
+
await this.culling;
|
|
15439
|
+
const changes = /* @__PURE__ */ new Map();
|
|
15440
|
+
try {
|
|
15441
|
+
await this.clearChunkColumn(x, z, changes);
|
|
15442
|
+
} finally {
|
|
15443
|
+
await this.updateCulling([...changes.values()]);
|
|
15444
|
+
}
|
|
15445
|
+
}
|
|
15446
|
+
async clearChunkColumn(x, z, changes) {
|
|
15447
|
+
const previous = [...this._chunks.entries()].filter(([, section]) => section.x === x && section.z === z);
|
|
15448
|
+
for (const [key, section] of previous) {
|
|
15449
|
+
this._chunks.delete(key);
|
|
15450
|
+
await section.clear(async (positions) => {
|
|
15451
|
+
for (const pos of positions) changes.set(pos.toArray().join(","), pos);
|
|
15452
|
+
});
|
|
15453
|
+
}
|
|
15454
|
+
}
|
|
15384
15455
|
async clear() {
|
|
15385
15456
|
await this.culling;
|
|
15386
15457
|
const chunks = [...this._chunks.values()];
|
|
@@ -15549,14 +15620,17 @@ var SectionMesh = class _SectionMesh extends import_three40.Group {
|
|
|
15549
15620
|
for (const { atlas, x, y } of page.placements) {
|
|
15550
15621
|
context.drawImage(atlas.image.canvas, x, y);
|
|
15551
15622
|
}
|
|
15552
|
-
const positions = [], normals = [], uvs = [], colors = [], indices = [];
|
|
15623
|
+
const positions = [], normals = [], uvs = [], uvBounds = [], colors = [], indices = [];
|
|
15553
15624
|
for (const { index, template, cullMask } of page.entries) {
|
|
15554
15625
|
const position = template.geometry.getAttribute("position");
|
|
15555
15626
|
const normal = template.geometry.getAttribute("normal");
|
|
15556
15627
|
const uv = template.geometry.getAttribute("uv");
|
|
15628
|
+
const bounds = template.geometry.getAttribute("uvBounds");
|
|
15557
15629
|
const color = template.geometry.getAttribute("color");
|
|
15558
15630
|
const sourceIndices = template.geometry.getIndex();
|
|
15559
15631
|
const placement = locations.get(template.atlas).placement;
|
|
15632
|
+
const mapU = (u) => (placement.x + u * template.atlas.image.width) / page.width;
|
|
15633
|
+
const mapV = (v) => 1 - (placement.y + (1 - v) * template.atlas.image.height) / page.height;
|
|
15560
15634
|
const offsetX = index % 16 * 16;
|
|
15561
15635
|
const offsetY = Math.floor(index / 256) * 16;
|
|
15562
15636
|
const offsetZ = Math.floor(index / 16) % 16 * 16;
|
|
@@ -15567,9 +15641,12 @@ var SectionMesh = class _SectionMesh extends import_three40.Group {
|
|
|
15567
15641
|
const vertex = face * 4 + corner;
|
|
15568
15642
|
positions.push(position.getX(vertex) + offsetX, position.getY(vertex) + offsetY, position.getZ(vertex) + offsetZ);
|
|
15569
15643
|
normals.push(normal.getX(vertex), normal.getY(vertex), normal.getZ(vertex));
|
|
15570
|
-
uvs.push(
|
|
15571
|
-
|
|
15572
|
-
|
|
15644
|
+
uvs.push(mapU(uv.getX(vertex)), mapV(uv.getY(vertex)));
|
|
15645
|
+
uvBounds.push(
|
|
15646
|
+
mapU(bounds?.getX(vertex) ?? 0),
|
|
15647
|
+
mapV(bounds?.getY(vertex) ?? 0),
|
|
15648
|
+
mapU(bounds?.getZ(vertex) ?? 1),
|
|
15649
|
+
mapV(bounds?.getW(vertex) ?? 1)
|
|
15573
15650
|
);
|
|
15574
15651
|
colors.push(color?.getX(vertex) ?? 1, color?.getY(vertex) ?? 1, color?.getZ(vertex) ?? 1);
|
|
15575
15652
|
}
|
|
@@ -15580,11 +15657,12 @@ var SectionMesh = class _SectionMesh extends import_three40.Group {
|
|
|
15580
15657
|
geometry.setAttribute("position", new import_three40.Float32BufferAttribute(positions, 3));
|
|
15581
15658
|
geometry.setAttribute("normal", new import_three40.Float32BufferAttribute(normals, 3));
|
|
15582
15659
|
geometry.setAttribute("uv", new import_three40.Float32BufferAttribute(uvs, 2));
|
|
15660
|
+
geometry.setAttribute("uvBounds", new import_three40.Float32BufferAttribute(uvBounds, 4));
|
|
15583
15661
|
geometry.setAttribute("color", new import_three40.Float32BufferAttribute(colors, 3));
|
|
15584
15662
|
geometry.setIndex(indices);
|
|
15585
15663
|
geometry.computeBoundingBox();
|
|
15586
15664
|
geometry.computeBoundingSphere();
|
|
15587
|
-
const material = Materials.createShadedCanvasMaterial(canvas, false);
|
|
15665
|
+
const material = Materials.createShadedCanvasMaterial(canvas, false, false, true);
|
|
15588
15666
|
material.vertexColors = true;
|
|
15589
15667
|
const texture = material.uniforms?.map?.value ?? material.map;
|
|
15590
15668
|
const mesh = new import_three40.Mesh(geometry, material);
|