diff --git a/src/render/BlockDefinition.ts b/src/render/BlockDefinition.ts index f9c15291..b3f15583 100644 --- a/src/render/BlockDefinition.ts +++ b/src/render/BlockDefinition.ts @@ -6,7 +6,7 @@ import { Cull } from './Cull.js' import { Mesh } from './Mesh.js' import type { TextureAtlasProvider } from './TextureAtlas.js' -type ModelVariant = { +export type ModelVariant = { model: string, x?: number, y?: number, @@ -62,7 +62,7 @@ export class BlockDefinition { throw new Error(`Cannot find block model ${variant.model}`) } const tint = name ? BlockColors[name.path]?.(props) : undefined - const variantMesh = blockModel.getMesh(atlas, newCull, tint) + const variantMesh = blockModel.getMesh(atlas, newCull, variant, tint) if (variant.x || variant.y) { const t = mat4.create() diff --git a/src/render/BlockModel.ts b/src/render/BlockModel.ts index a865d2f2..5b634c74 100644 --- a/src/render/BlockModel.ts +++ b/src/render/BlockModel.ts @@ -4,6 +4,7 @@ import type { Direction } from '../core/index.js' import { Identifier } from '../core/index.js' import { Vector } from '../math/index.js' import type { Color } from '../util/index.js' +import type { ModelVariant } from './BlockDefinition.js' import type { Cull } from './Cull.js' import { Mesh } from './Mesh.js' import { Quad } from './Quad.js' @@ -81,6 +82,7 @@ export class BlockModel { private elements: BlockModelElement[] | undefined, private display?: BlockModelDisplay | undefined, private guiLight?: BlockModelGuiLight | undefined, + private uvLock?: boolean | undefined, ) {} public getDisplayTransform(display: Display) { @@ -102,7 +104,7 @@ export class BlockModel { return t } - public getMesh(atlas: TextureAtlasProvider, cull: Cull, tint?: Color | ((index: number) => Color)) { + public getMesh(atlas: TextureAtlasProvider, cull: Cull, variant: ModelVariant | undefined, tint?: Color | ((index: number) => Color)) { const mesh = new Mesh() const getTint = (index?: number): Color => { if (tint === undefined) return [1, 1, 1] @@ -111,17 +113,24 @@ export class BlockModel { return tint } for (const e of this.elements ?? []) { - mesh.merge(this.getElementMesh(e, atlas, cull, getTint)) + mesh.merge(this.getElementMesh(e, atlas, cull, variant, getTint)) } return mesh } - public getElementMesh(e: BlockModelElement, atlas: TextureAtlasProvider, cull: Cull, getTint: (index?: number) => Color) { + public getElementMesh(e: BlockModelElement, atlas: TextureAtlasProvider, cull: Cull, variant: ModelVariant | undefined, getTint: (index?: number) => Color) { const mesh = new Mesh() const [x0, y0, z0] = e.from const [x1, y1, z1] = e.to - const addFace = (face: BlockModelFace, uv: UV, pos: number[]) => { + variant = variant ?? { + model: '', + uvlock: false, + x: 0, + y: 0, + } + + const addFace = (face: BlockModelFace, uv: UV, pos: number[], additionalRotate: number) => { const quad = Quad.fromPoints( new Vector(pos[0], pos[1], pos[2]), new Vector(pos[3], pos[4], pos[5]), @@ -138,7 +147,10 @@ export class BlockModel { uv[1] = (face.uv?.[1] ?? uv[1]) * dv uv[2] = (face.uv?.[2] ?? uv[2]) * du uv[3] = (face.uv?.[3] ?? uv[3]) * dv - const r = faceRotations[face.rotation ?? 0] + const newRotation = ( + (( (face.rotation ?? 0) + additionalRotate ) % 360 + 360) % 360 + ) as 0 | 90 | 180 | 270; + const r = faceRotations[newRotation] quad.setTexture([ u0 + uv[r[0]], v0 + uv[r[1]], u0 + uv[r[2]], v0 + uv[r[3]], @@ -150,27 +162,27 @@ export class BlockModel { if (e.faces?.up?.texture && (!e.faces.up.cullface || !cull[e.faces.up.cullface])) { addFace(e.faces.up, [x0, 16 - z1, x1, 16 - z0], - [x0, y1, z1, x1, y1, z1, x1, y1, z0, x0, y1, z0]) + [x0, y1, z1, x1, y1, z1, x1, y1, z0, x0, y1, z0], variant.uvlock ? -(variant.y ?? 0) : 0) } if (e.faces?.down?.texture && (!e.faces.down.cullface || !cull[e.faces.down.cullface])) { addFace(e.faces.down, [16 - z1, 16 - x1, 16 - z0, 16 - x0], - [x0, y0, z0, x1, y0, z0, x1, y0, z1, x0, y0, z1]) + [x0, y0, z0, x1, y0, z0, x1, y0, z1, x0, y0, z1], variant.uvlock ? -(variant.y ?? 0) : 0) } if (e.faces?.south?.texture && (!e.faces.south.cullface || !cull[e.faces.south.cullface])) { addFace(e.faces.south, [x0, 16 - y1, x1, 16 - y0], - [x0, y0, z1, x1, y0, z1, x1, y1, z1, x0, y1, z1]) + [x0, y0, z1, x1, y0, z1, x1, y1, z1, x0, y1, z1], 0) } if (e.faces?.north?.texture && (!e.faces.north.cullface || !cull[e.faces.north.cullface])) { addFace(e.faces.north, [16 - x1, 16 - y1, 16 - x0, 16 - y0], - [x1, y0, z0, x0, y0, z0, x0, y1, z0, x1, y1, z0]) + [x1, y0, z0, x0, y0, z0, x0, y1, z0, x1, y1, z0], 0) } if (e.faces?.east?.texture && (!e.faces.east.cullface || !cull[e.faces.east.cullface])) { addFace(e.faces.east, [16 - z1, 16 - y1, 16 - z0, 16 - y0], - [x1, y0, z1, x1, y0, z0, x1, y1, z0, x1, y1, z1]) + [x1, y0, z1, x1, y0, z0, x1, y1, z0, x1, y1, z1], variant.uvlock ? -(variant.x ?? 0) : 0) } if (e.faces?.west?.texture && (!e.faces.west.cullface || !cull[e.faces.west.cullface])) { addFace(e.faces.west, [z0, 16 - y1, z1, 16 - y0], - [x0, y0, z0, x0, y0, z1, x0, y1, z1, x0, y1, z0]) + [x0, y0, z0, x0, y0, z1, x0, y1, z1, x0, y1, z0], variant.uvlock ? -(variant.x ?? 0) : 0) } const t = mat4.create() diff --git a/src/render/ItemModel.ts b/src/render/ItemModel.ts index 0fcfe595..064482f0 100644 --- a/src/render/ItemModel.ts +++ b/src/render/ItemModel.ts @@ -98,7 +98,7 @@ export namespace ItemModel { } } - const mesh = model.getMesh(resources, Cull.none(), tint) + const mesh = model.getMesh(resources, Cull.none(), undefined, tint) mesh.transform(model.getDisplayTransform(context.display_context ?? 'gui')) return mesh } diff --git a/src/render/SpecialRenderer.ts b/src/render/SpecialRenderer.ts index 5e0fec9a..ebfad3ab 100644 --- a/src/render/SpecialRenderer.ts +++ b/src/render/SpecialRenderer.ts @@ -26,7 +26,7 @@ function liquidRenderer(type: string, level: number, atlas: TextureAtlasProvider south: { texture: '#flow', tintindex, cullface: Direction.SOUTH }, west: { texture: '#flow', tintindex, cullface: Direction.WEST }, }, - }]).getMesh(atlas, cull, BlockColors[type]?.({})) + }]).getMesh(atlas, cull, undefined, BlockColors[type]?.({})) } const DyeColors: Record = { @@ -90,7 +90,7 @@ export namespace SpecialRenderers { down: {uv: [0.75, 0, 1.25, 0.25], rotation: 180, texture: '#0'}, }, }, - ]).getMesh(atlas, Cull.none()) + ]).getMesh(atlas, Cull.none(), undefined) } } @@ -133,7 +133,7 @@ export namespace SpecialRenderers { down: {uv: [8, 0, 12, 4], texture: '#1'}, }, }, - ]).getMesh(atlas, Cull.none()) + ]).getMesh(atlas, Cull.none(), undefined) } export function shieldRenderer(atlas: TextureAtlasProvider) { @@ -152,7 +152,7 @@ export namespace SpecialRenderers { down: {uv: [3.25, 0, 6.25, 0.25], texture: '#0'}, }, }, - ]).getMesh(atlas, Cull.none()) + ]).getMesh(atlas, Cull.none(), undefined) } export function headRenderer(texture: Identifier, n: number) { @@ -173,7 +173,7 @@ export namespace SpecialRenderers { }, }, ]) - .getMesh(atlas, Cull.none()) + .getMesh(atlas, Cull.none(), undefined) } } @@ -272,7 +272,7 @@ export namespace SpecialRenderers { down: {uv: [7.5, 0, 7.375, 0.25], texture: '#0'}, }, }, - ]).getMesh(atlas, Cull.none()).transform(transformation) + ]).getMesh(atlas, Cull.none(), undefined).transform(transformation) } } @@ -355,7 +355,7 @@ export namespace SpecialRenderers { down: {uv: [14.25, 1.5, 14, 2.5], texture: '#0'}, }, }, - ]).getMesh(atlas, Cull.none()) + ]).getMesh(atlas, Cull.none(), undefined) } } @@ -388,7 +388,7 @@ export namespace SpecialRenderers { down: {uv: [1.5, 7, 1, 8], texture: '#0'}, }, }, - ]).getMesh(atlas, Cull.none()) + ]).getMesh(atlas, Cull.none(), undefined) } } @@ -409,7 +409,7 @@ export namespace SpecialRenderers { down: {uv: [12.5, 0, 6.5, 1], texture: '#0'}, }, }, - ]).getMesh(atlas, Cull.none()) + ]).getMesh(atlas, Cull.none(), undefined) } } @@ -439,7 +439,7 @@ export namespace SpecialRenderers { south: {uv: [3.5, 3, 6.5, 6], texture: '#0'}, }, }, - ]).getMesh(atlas, Cull.none()) + ]).getMesh(atlas, Cull.none(), undefined) } return new BlockModel(undefined, { 0: texture.withPrefix('entity/signs/hanging/').toString(), @@ -492,7 +492,7 @@ export namespace SpecialRenderers { west: {uv: [1.5, 3, 2.25, 6], texture: '#0'}, }, }, - ]).getMesh(atlas, Cull.none()) + ]).getMesh(atlas, Cull.none(), undefined) } } @@ -561,7 +561,7 @@ export namespace SpecialRenderers { west: {uv: [1.5, 3, 2.25, 6], texture: '#0'}, }, }, - ]).getMesh(atlas, Cull.none()) + ]).getMesh(atlas, Cull.none(), undefined) } } @@ -581,7 +581,7 @@ export namespace SpecialRenderers { down: {uv: [9, 0, 6, 6], texture: '#0'}, }, }, - ]).getMesh(atlas, Cull.none()) + ]).getMesh(atlas, Cull.none(), undefined) } export function shulkerBoxRenderer(texture: Identifier) { @@ -613,7 +613,7 @@ export namespace SpecialRenderers { down: {uv: [12, 0, 8, 4], texture: '#0'}, }, }, - ]).getMesh(atlas, Cull.none()) + ]).getMesh(atlas, Cull.none(), undefined) } } @@ -642,7 +642,7 @@ export namespace SpecialRenderers { }) return new BlockModel(undefined, textures, elements) - .getMesh(atlas, Cull.none(), (index: number) => DyeColors[colors[index]]) + .getMesh(atlas, Cull.none(), undefined, (index: number) => DyeColors[colors[index]]) } } @@ -740,7 +740,7 @@ export namespace SpecialRenderers { down: {uv: [12, 6.5, 8, 10.5], texture: '#0'}, }, }, - ]).getMesh(atlas, Cull.none()) + ]).getMesh(atlas, Cull.none(), undefined) } export function bedRenderer(texture: Identifier) { @@ -784,7 +784,7 @@ export namespace SpecialRenderers { down: {uv: [14, 3, 14.75, 3.75], texture: '#0'}, }, }, - ]).getMesh(atlas, Cull.none()) + ]).getMesh(atlas, Cull.none(), undefined) } return new BlockModel(undefined, { 0: texture.withPrefix('entity/bed/').toString(), @@ -824,7 +824,7 @@ export namespace SpecialRenderers { down: {uv: [14, 1.5, 14.75, 2.25], texture: '#0'}, }, }, - ]).getMesh(atlas, Cull.none()) + ]).getMesh(atlas, Cull.none(), undefined) } }