minerender 2.1.0-alpha.87 → 2.1.0-alpha.88
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 +92 -3
- package/dist/browser/index.d.ts +92 -3
- package/dist/browser/index.js +502 -184
- package/dist/browser/index.js.map +1 -1
- package/dist/browser/index.mjs +502 -185
- package/dist/browser/index.mjs.map +1 -1
- package/dist/browser/section.worker.js +119 -0
- package/dist/browser/section.worker.js.map +1 -0
- package/dist/browser/section.worker.mjs +119 -0
- package/dist/browser/section.worker.mjs.map +1 -0
- package/dist/bundle.js +511 -187
- package/dist/bundle.js.map +1 -1
- package/dist/node/index.d.mts +91 -3
- package/dist/node/index.d.ts +91 -3
- package/dist/node/index.js +498 -184
- package/dist/node/index.js.map +1 -1
- package/dist/node/index.mjs +494 -184
- package/dist/node/index.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
// src/CubeFace.ts
|
|
2
|
+
var CubeFace = /* @__PURE__ */ ((CubeFace2) => {
|
|
3
|
+
CubeFace2["EAST"] = "east";
|
|
4
|
+
CubeFace2["WEST"] = "west";
|
|
5
|
+
CubeFace2["UP"] = "up";
|
|
6
|
+
CubeFace2["DOWN"] = "down";
|
|
7
|
+
CubeFace2["SOUTH"] = "south";
|
|
8
|
+
CubeFace2["NORTH"] = "north";
|
|
9
|
+
return CubeFace2;
|
|
10
|
+
})(CubeFace || {});
|
|
11
|
+
var CUBE_FACES = Object.values(CubeFace);
|
|
12
|
+
|
|
13
|
+
// src/world/SectionGeometry.ts
|
|
14
|
+
function buildSectionGeometry(input) {
|
|
15
|
+
const { count, indices, templates, cullMasks, templateData, atlases, maxAtlasSize } = input;
|
|
16
|
+
if (!Number.isInteger(maxAtlasSize) || maxAtlasSize < 1) throw new RangeError("Section atlas size must be a positive integer");
|
|
17
|
+
if (count > indices.length || count > templates.length || count > cullMasks.length) throw new RangeError("Section entry count exceeds its arrays");
|
|
18
|
+
const visible = [];
|
|
19
|
+
const visibleAtlases = /* @__PURE__ */ new Set();
|
|
20
|
+
for (let entry = 0; entry < count; entry++) {
|
|
21
|
+
const template = templateData[templates[entry]];
|
|
22
|
+
if (!template.cullFaces.some((direction) => !(cullMasks[entry] & direction))) continue;
|
|
23
|
+
visible.push(entry);
|
|
24
|
+
visibleAtlases.add(template.atlas);
|
|
25
|
+
}
|
|
26
|
+
const pages = [];
|
|
27
|
+
const locations = /* @__PURE__ */ new Map();
|
|
28
|
+
for (const atlas of [...visibleAtlases].sort((a, b) => atlases[b].height - atlases[a].height)) {
|
|
29
|
+
const { width, height } = atlases[atlas];
|
|
30
|
+
if (width > maxAtlasSize || height > maxAtlasSize) throw new RangeError("Model atlas exceeds the section atlas size limit");
|
|
31
|
+
let selected = -1;
|
|
32
|
+
for (let i = 0; i < pages.length; i++) {
|
|
33
|
+
const page2 = pages[i];
|
|
34
|
+
const nextRow = page2.x + width > maxAtlasSize;
|
|
35
|
+
if ((nextRow ? page2.y + page2.rowHeight : page2.y) + height > maxAtlasSize) continue;
|
|
36
|
+
if (nextRow) {
|
|
37
|
+
page2.y += page2.rowHeight;
|
|
38
|
+
page2.x = 0;
|
|
39
|
+
page2.rowHeight = 0;
|
|
40
|
+
}
|
|
41
|
+
selected = i;
|
|
42
|
+
break;
|
|
43
|
+
}
|
|
44
|
+
if (selected < 0) {
|
|
45
|
+
selected = pages.length;
|
|
46
|
+
pages.push({ placements: [], entries: [], x: 0, y: 0, rowHeight: 0, width: 0, height: 0 });
|
|
47
|
+
}
|
|
48
|
+
const page = pages[selected];
|
|
49
|
+
page.placements.push({ atlas, x: page.x, y: page.y });
|
|
50
|
+
locations.set(atlas, { page: selected, x: page.x, y: page.y });
|
|
51
|
+
page.x += width;
|
|
52
|
+
page.rowHeight = Math.max(page.rowHeight, height);
|
|
53
|
+
page.width = Math.max(page.width, page.x);
|
|
54
|
+
page.height = Math.max(page.height, page.y + height);
|
|
55
|
+
}
|
|
56
|
+
for (const entry of visible) pages[locations.get(templateData[templates[entry]].atlas).page].entries.push(entry);
|
|
57
|
+
return pages.map((page) => {
|
|
58
|
+
let faces = 0;
|
|
59
|
+
for (const entry of page.entries) {
|
|
60
|
+
const template = templateData[templates[entry]];
|
|
61
|
+
for (let face = 0; face < CUBE_FACES.length; face++) {
|
|
62
|
+
if (!(cullMasks[entry] & template.cullFaces[face])) faces++;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
const positions = new Float32Array(faces * 12), normals = new Float32Array(faces * 12);
|
|
66
|
+
const uvs = new Float32Array(faces * 8), uvBounds = new Float32Array(faces * 16), colors = new Float32Array(faces * 12);
|
|
67
|
+
const outputIndices = new Uint32Array(faces * 6);
|
|
68
|
+
let vertex = 0, indexOffset = 0;
|
|
69
|
+
for (const entry of page.entries) {
|
|
70
|
+
const template = templateData[templates[entry]];
|
|
71
|
+
const atlas = atlases[template.atlas];
|
|
72
|
+
const placement = locations.get(template.atlas);
|
|
73
|
+
const mapU = (u) => (placement.x + u * atlas.width) / page.width;
|
|
74
|
+
const mapV = (v) => 1 - (placement.y + (1 - v) * atlas.height) / page.height;
|
|
75
|
+
const offsetX = indices[entry] % 16 * 16;
|
|
76
|
+
const offsetY = Math.floor(indices[entry] / 256) * 16;
|
|
77
|
+
const offsetZ = Math.floor(indices[entry] / 16) % 16 * 16;
|
|
78
|
+
for (let face = 0; face < CUBE_FACES.length; face++) {
|
|
79
|
+
if (cullMasks[entry] & template.cullFaces[face]) continue;
|
|
80
|
+
const start = vertex;
|
|
81
|
+
for (let corner = 0; corner < 4; corner++, vertex++) {
|
|
82
|
+
const source = face * 4 + corner;
|
|
83
|
+
positions[vertex * 3] = template.positions[source * 3] + offsetX;
|
|
84
|
+
positions[vertex * 3 + 1] = template.positions[source * 3 + 1] + offsetY;
|
|
85
|
+
positions[vertex * 3 + 2] = template.positions[source * 3 + 2] + offsetZ;
|
|
86
|
+
normals[vertex * 3] = template.normals[source * 3];
|
|
87
|
+
normals[vertex * 3 + 1] = template.normals[source * 3 + 1];
|
|
88
|
+
normals[vertex * 3 + 2] = template.normals[source * 3 + 2];
|
|
89
|
+
uvs[vertex * 2] = mapU(template.uvs[source * 2]);
|
|
90
|
+
uvs[vertex * 2 + 1] = mapV(template.uvs[source * 2 + 1]);
|
|
91
|
+
uvBounds[vertex * 4] = mapU(template.uvBounds[source * 4]);
|
|
92
|
+
uvBounds[vertex * 4 + 1] = mapV(template.uvBounds[source * 4 + 1]);
|
|
93
|
+
uvBounds[vertex * 4 + 2] = mapU(template.uvBounds[source * 4 + 2]);
|
|
94
|
+
uvBounds[vertex * 4 + 3] = mapV(template.uvBounds[source * 4 + 3]);
|
|
95
|
+
colors[vertex * 3] = template.colors[source * 3];
|
|
96
|
+
colors[vertex * 3 + 1] = template.colors[source * 3 + 1];
|
|
97
|
+
colors[vertex * 3 + 2] = template.colors[source * 3 + 2];
|
|
98
|
+
}
|
|
99
|
+
for (let corner = 0; corner < 6; corner++) outputIndices[indexOffset++] = start + template.indices[face * 6 + corner] - face * 4;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return { width: page.width, height: page.height, placements: page.placements, positions, normals, uvs, uvBounds, colors, indices: outputIndices };
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
function sectionGeometryTransferables(pages) {
|
|
106
|
+
return pages.flatMap((page) => [page.positions.buffer, page.normals.buffer, page.uvs.buffer, page.uvBounds.buffer, page.colors.buffer, page.indices.buffer]);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// src/env/browser/section.worker.ts
|
|
110
|
+
addEventListener("message", (event) => {
|
|
111
|
+
const { id, input } = event.data;
|
|
112
|
+
try {
|
|
113
|
+
const pages = buildSectionGeometry(input);
|
|
114
|
+
postMessage({ id, type: "pages", pages }, { transfer: sectionGeometryTransferables(pages) });
|
|
115
|
+
} catch (error) {
|
|
116
|
+
postMessage({ id, type: "error", message: error instanceof Error ? error.message : String(error) });
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
//# sourceMappingURL=section.worker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/CubeFace.ts","../../src/world/SectionGeometry.ts","../../src/env/browser/section.worker.ts"],"sourcesContent":["export enum CubeFace {\n EAST = \"east\", // px\n WEST = \"west\", // nx\n UP = \"up\", // py\n DOWN = \"down\", // ny\n SOUTH = \"south\", // pz\n NORTH = \"north\", // nz\n}\n\nexport enum CubeFaceIndex {\n EAST,\n WEST,\n UP,\n DOWN,\n SOUTH,\n NORTH\n}\n\nexport const CUBE_FACES = Object.values(CubeFace);\n\nexport const CUBE_FACE_OFFSETS = [\n [1, 0, 0], [-1, 0, 0], [0, 1, 0], [0, -1, 0], [0, 0, 1], [0, 0, -1]\n] as const;\n","import { CUBE_FACES } from \"../CubeFace\";\n\n/** One cube template with four vertices per face in `CUBE_FACES` order. */\nexport interface SectionTemplateData {\n positions: Float32Array;\n normals: Float32Array;\n uvs: Float32Array;\n uvBounds: Float32Array;\n colors: Float32Array;\n indices: Uint16Array;\n cullFaces: Uint8Array;\n atlas: number;\n}\n\n/** The pixel dimensions of a template atlas. */\nexport interface SectionAtlasSize {\n width: number;\n height: number;\n}\n\n/** Section placements and their shared cube templates, ready for geometry building. */\nexport interface SectionGeometryInput {\n count: number;\n indices: Uint16Array;\n templates: Uint16Array;\n cullMasks: Uint8Array;\n templateData: SectionTemplateData[];\n atlases: SectionAtlasSize[];\n maxAtlasSize: number;\n}\n\n/** Merged cube faces and source-atlas placements for one atlas page. */\nexport interface SectionGeometryPage {\n width: number;\n height: number;\n placements: { atlas: number; x: number; y: number }[];\n positions: Float32Array;\n normals: Float32Array;\n uvs: Float32Array;\n uvBounds: Float32Array;\n colors: Float32Array;\n indices: Uint32Array;\n}\n\n/** Builds section-local geometry from visible cube faces, with bounded atlas pages. */\nexport function buildSectionGeometry(input: SectionGeometryInput): SectionGeometryPage[] {\n const { count, indices, templates, cullMasks, templateData, atlases, maxAtlasSize } = input;\n if (!Number.isInteger(maxAtlasSize) || maxAtlasSize < 1) throw new RangeError(\"Section atlas size must be a positive integer\");\n if (count > indices.length || count > templates.length || count > cullMasks.length) throw new RangeError(\"Section entry count exceeds its arrays\");\n const visible: number[] = [];\n const visibleAtlases = new Set<number>();\n for (let entry = 0; entry < count; entry++) {\n const template = templateData[templates[entry]];\n if (!template.cullFaces.some(direction => !(cullMasks[entry] & direction))) continue;\n visible.push(entry);\n visibleAtlases.add(template.atlas);\n }\n const pages: {\n placements: SectionGeometryPage[\"placements\"]; entries: number[];\n x: number; y: number; rowHeight: number; width: number; height: number;\n }[] = [];\n const locations = new Map<number, { page: number; x: number; y: number }>();\n for (const atlas of [...visibleAtlases].sort((a, b) => atlases[b].height - atlases[a].height)) {\n const { width, height } = atlases[atlas];\n if (width > maxAtlasSize || height > maxAtlasSize) throw new RangeError(\"Model atlas exceeds the section atlas size limit\");\n let selected = -1;\n for (let i = 0; i < pages.length; i++) {\n const page = pages[i];\n const nextRow = page.x + width > maxAtlasSize;\n if ((nextRow ? page.y + page.rowHeight : page.y) + height > maxAtlasSize) continue;\n if (nextRow) {\n page.y += page.rowHeight;\n page.x = 0;\n page.rowHeight = 0;\n }\n selected = i;\n break;\n }\n if (selected < 0) {\n selected = pages.length;\n pages.push({ placements: [], entries: [], x: 0, y: 0, rowHeight: 0, width: 0, height: 0 });\n }\n const page = pages[selected];\n page.placements.push({ atlas, x: page.x, y: page.y });\n locations.set(atlas, { page: selected, x: page.x, y: page.y });\n page.x += width;\n page.rowHeight = Math.max(page.rowHeight, height);\n page.width = Math.max(page.width, page.x);\n page.height = Math.max(page.height, page.y + height);\n }\n for (const entry of visible) pages[locations.get(templateData[templates[entry]].atlas)!.page].entries.push(entry);\n\n return pages.map(page => {\n let faces = 0;\n for (const entry of page.entries) {\n const template = templateData[templates[entry]];\n for (let face = 0; face < CUBE_FACES.length; face++) {\n if (!(cullMasks[entry] & template.cullFaces[face])) faces++;\n }\n }\n const positions = new Float32Array(faces * 12), normals = new Float32Array(faces * 12);\n const uvs = new Float32Array(faces * 8), uvBounds = new Float32Array(faces * 16), colors = new Float32Array(faces * 12);\n const outputIndices = new Uint32Array(faces * 6);\n let vertex = 0, indexOffset = 0;\n for (const entry of page.entries) {\n const template = templateData[templates[entry]];\n const atlas = atlases[template.atlas];\n const placement = locations.get(template.atlas)!;\n const mapU = (u: number) => (placement.x + u * atlas.width) / page.width;\n const mapV = (v: number) => 1 - (placement.y + (1 - v) * atlas.height) / page.height;\n const offsetX = (indices[entry] % 16) * 16;\n const offsetY = Math.floor(indices[entry] / 256) * 16;\n const offsetZ = (Math.floor(indices[entry] / 16) % 16) * 16;\n for (let face = 0; face < CUBE_FACES.length; face++) {\n if (cullMasks[entry] & template.cullFaces[face]) continue;\n const start = vertex;\n for (let corner = 0; corner < 4; corner++, vertex++) {\n const source = face * 4 + corner;\n positions[vertex * 3] = template.positions[source * 3] + offsetX;\n positions[vertex * 3 + 1] = template.positions[source * 3 + 1] + offsetY;\n positions[vertex * 3 + 2] = template.positions[source * 3 + 2] + offsetZ;\n normals[vertex * 3] = template.normals[source * 3];\n normals[vertex * 3 + 1] = template.normals[source * 3 + 1];\n normals[vertex * 3 + 2] = template.normals[source * 3 + 2];\n uvs[vertex * 2] = mapU(template.uvs[source * 2]);\n uvs[vertex * 2 + 1] = mapV(template.uvs[source * 2 + 1]);\n uvBounds[vertex * 4] = mapU(template.uvBounds[source * 4]);\n uvBounds[vertex * 4 + 1] = mapV(template.uvBounds[source * 4 + 1]);\n uvBounds[vertex * 4 + 2] = mapU(template.uvBounds[source * 4 + 2]);\n uvBounds[vertex * 4 + 3] = mapV(template.uvBounds[source * 4 + 3]);\n colors[vertex * 3] = template.colors[source * 3];\n colors[vertex * 3 + 1] = template.colors[source * 3 + 1];\n colors[vertex * 3 + 2] = template.colors[source * 3 + 2];\n }\n for (let corner = 0; corner < 6; corner++) outputIndices[indexOffset++] = start + template.indices[face * 6 + corner] - face * 4;\n }\n }\n return { width: page.width, height: page.height, placements: page.placements, positions, normals, uvs, uvBounds, colors, indices: outputIndices };\n });\n}\n\n/** Returns the buffers behind each page's typed arrays for transfer to another thread. */\nexport function sectionGeometryTransferables(pages: readonly SectionGeometryPage[]): ArrayBuffer[] {\n return pages.flatMap(page => [page.positions.buffer, page.normals.buffer, page.uvs.buffer, page.uvBounds.buffer, page.colors.buffer, page.indices.buffer]);\n}\n","import { buildSectionGeometry, sectionGeometryTransferables, SectionGeometryInput } from \"../../world/SectionGeometry\";\n\naddEventListener(\"message\", (event: MessageEvent<{ id: number; type: \"build\"; input: SectionGeometryInput }>) => {\n const { id, input } = event.data;\n try {\n const pages = buildSectionGeometry(input);\n postMessage({ id, type: \"pages\", pages }, { transfer: sectionGeometryTransferables(pages) });\n } catch (error) {\n postMessage({ id, type: \"error\", message: error instanceof Error ? error.message : String(error) });\n }\n});\n"],"mappings":";AAAO,IAAK,WAAL,kBAAKA,cAAL;AACH,EAAAA,UAAA,UAAO;AACP,EAAAA,UAAA,UAAO;AACP,EAAAA,UAAA,QAAK;AACL,EAAAA,UAAA,UAAO;AACP,EAAAA,UAAA,WAAQ;AACR,EAAAA,UAAA,WAAQ;AANA,SAAAA;AAAA,GAAA;AAkBL,IAAM,aAAa,OAAO,OAAO,QAAQ;;;AC2BzC,SAAS,qBAAqB,OAAoD;AACrF,QAAM,EAAE,OAAO,SAAS,WAAW,WAAW,cAAc,SAAS,aAAa,IAAI;AACtF,MAAI,CAAC,OAAO,UAAU,YAAY,KAAK,eAAe,EAAG,OAAM,IAAI,WAAW,+CAA+C;AAC7H,MAAI,QAAQ,QAAQ,UAAU,QAAQ,UAAU,UAAU,QAAQ,UAAU,OAAQ,OAAM,IAAI,WAAW,wCAAwC;AACjJ,QAAM,UAAoB,CAAC;AAC3B,QAAM,iBAAiB,oBAAI,IAAY;AACvC,WAAS,QAAQ,GAAG,QAAQ,OAAO,SAAS;AACxC,UAAM,WAAW,aAAa,UAAU,KAAK,CAAC;AAC9C,QAAI,CAAC,SAAS,UAAU,KAAK,eAAa,EAAE,UAAU,KAAK,IAAI,UAAU,EAAG;AAC5E,YAAQ,KAAK,KAAK;AAClB,mBAAe,IAAI,SAAS,KAAK;AAAA,EACrC;AACA,QAAM,QAGA,CAAC;AACP,QAAM,YAAY,oBAAI,IAAoD;AAC1E,aAAW,SAAS,CAAC,GAAG,cAAc,EAAE,KAAK,CAAC,GAAG,MAAM,QAAQ,CAAC,EAAE,SAAS,QAAQ,CAAC,EAAE,MAAM,GAAG;AAC3F,UAAM,EAAE,OAAO,OAAO,IAAI,QAAQ,KAAK;AACvC,QAAI,QAAQ,gBAAgB,SAAS,aAAc,OAAM,IAAI,WAAW,kDAAkD;AAC1H,QAAI,WAAW;AACf,aAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACnC,YAAMC,QAAO,MAAM,CAAC;AACpB,YAAM,UAAUA,MAAK,IAAI,QAAQ;AACjC,WAAK,UAAUA,MAAK,IAAIA,MAAK,YAAYA,MAAK,KAAK,SAAS,aAAc;AAC1E,UAAI,SAAS;AACT,QAAAA,MAAK,KAAKA,MAAK;AACf,QAAAA,MAAK,IAAI;AACT,QAAAA,MAAK,YAAY;AAAA,MACrB;AACA,iBAAW;AACX;AAAA,IACJ;AACA,QAAI,WAAW,GAAG;AACd,iBAAW,MAAM;AACjB,YAAM,KAAK,EAAE,YAAY,CAAC,GAAG,SAAS,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,WAAW,GAAG,OAAO,GAAG,QAAQ,EAAE,CAAC;AAAA,IAC7F;AACA,UAAM,OAAO,MAAM,QAAQ;AAC3B,SAAK,WAAW,KAAK,EAAE,OAAO,GAAG,KAAK,GAAG,GAAG,KAAK,EAAE,CAAC;AACpD,cAAU,IAAI,OAAO,EAAE,MAAM,UAAU,GAAG,KAAK,GAAG,GAAG,KAAK,EAAE,CAAC;AAC7D,SAAK,KAAK;AACV,SAAK,YAAY,KAAK,IAAI,KAAK,WAAW,MAAM;AAChD,SAAK,QAAQ,KAAK,IAAI,KAAK,OAAO,KAAK,CAAC;AACxC,SAAK,SAAS,KAAK,IAAI,KAAK,QAAQ,KAAK,IAAI,MAAM;AAAA,EACvD;AACA,aAAW,SAAS,QAAS,OAAM,UAAU,IAAI,aAAa,UAAU,KAAK,CAAC,EAAE,KAAK,EAAG,IAAI,EAAE,QAAQ,KAAK,KAAK;AAEhH,SAAO,MAAM,IAAI,UAAQ;AACrB,QAAI,QAAQ;AACZ,eAAW,SAAS,KAAK,SAAS;AAC9B,YAAM,WAAW,aAAa,UAAU,KAAK,CAAC;AAC9C,eAAS,OAAO,GAAG,OAAO,WAAW,QAAQ,QAAQ;AACjD,YAAI,EAAE,UAAU,KAAK,IAAI,SAAS,UAAU,IAAI,GAAI;AAAA,MACxD;AAAA,IACJ;AACA,UAAM,YAAY,IAAI,aAAa,QAAQ,EAAE,GAAG,UAAU,IAAI,aAAa,QAAQ,EAAE;AACrF,UAAM,MAAM,IAAI,aAAa,QAAQ,CAAC,GAAG,WAAW,IAAI,aAAa,QAAQ,EAAE,GAAG,SAAS,IAAI,aAAa,QAAQ,EAAE;AACtH,UAAM,gBAAgB,IAAI,YAAY,QAAQ,CAAC;AAC/C,QAAI,SAAS,GAAG,cAAc;AAC9B,eAAW,SAAS,KAAK,SAAS;AAC9B,YAAM,WAAW,aAAa,UAAU,KAAK,CAAC;AAC9C,YAAM,QAAQ,QAAQ,SAAS,KAAK;AACpC,YAAM,YAAY,UAAU,IAAI,SAAS,KAAK;AAC9C,YAAM,OAAO,CAAC,OAAe,UAAU,IAAI,IAAI,MAAM,SAAS,KAAK;AACnE,YAAM,OAAO,CAAC,MAAc,KAAK,UAAU,KAAK,IAAI,KAAK,MAAM,UAAU,KAAK;AAC9E,YAAM,UAAW,QAAQ,KAAK,IAAI,KAAM;AACxC,YAAM,UAAU,KAAK,MAAM,QAAQ,KAAK,IAAI,GAAG,IAAI;AACnD,YAAM,UAAW,KAAK,MAAM,QAAQ,KAAK,IAAI,EAAE,IAAI,KAAM;AACzD,eAAS,OAAO,GAAG,OAAO,WAAW,QAAQ,QAAQ;AACjD,YAAI,UAAU,KAAK,IAAI,SAAS,UAAU,IAAI,EAAG;AACjD,cAAM,QAAQ;AACd,iBAAS,SAAS,GAAG,SAAS,GAAG,UAAU,UAAU;AACjD,gBAAM,SAAS,OAAO,IAAI;AAC1B,oBAAU,SAAS,CAAC,IAAI,SAAS,UAAU,SAAS,CAAC,IAAI;AACzD,oBAAU,SAAS,IAAI,CAAC,IAAI,SAAS,UAAU,SAAS,IAAI,CAAC,IAAI;AACjE,oBAAU,SAAS,IAAI,CAAC,IAAI,SAAS,UAAU,SAAS,IAAI,CAAC,IAAI;AACjE,kBAAQ,SAAS,CAAC,IAAI,SAAS,QAAQ,SAAS,CAAC;AACjD,kBAAQ,SAAS,IAAI,CAAC,IAAI,SAAS,QAAQ,SAAS,IAAI,CAAC;AACzD,kBAAQ,SAAS,IAAI,CAAC,IAAI,SAAS,QAAQ,SAAS,IAAI,CAAC;AACzD,cAAI,SAAS,CAAC,IAAI,KAAK,SAAS,IAAI,SAAS,CAAC,CAAC;AAC/C,cAAI,SAAS,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,SAAS,IAAI,CAAC,CAAC;AACvD,mBAAS,SAAS,CAAC,IAAI,KAAK,SAAS,SAAS,SAAS,CAAC,CAAC;AACzD,mBAAS,SAAS,IAAI,CAAC,IAAI,KAAK,SAAS,SAAS,SAAS,IAAI,CAAC,CAAC;AACjE,mBAAS,SAAS,IAAI,CAAC,IAAI,KAAK,SAAS,SAAS,SAAS,IAAI,CAAC,CAAC;AACjE,mBAAS,SAAS,IAAI,CAAC,IAAI,KAAK,SAAS,SAAS,SAAS,IAAI,CAAC,CAAC;AACjE,iBAAO,SAAS,CAAC,IAAI,SAAS,OAAO,SAAS,CAAC;AAC/C,iBAAO,SAAS,IAAI,CAAC,IAAI,SAAS,OAAO,SAAS,IAAI,CAAC;AACvD,iBAAO,SAAS,IAAI,CAAC,IAAI,SAAS,OAAO,SAAS,IAAI,CAAC;AAAA,QAC3D;AACA,iBAAS,SAAS,GAAG,SAAS,GAAG,SAAU,eAAc,aAAa,IAAI,QAAQ,SAAS,QAAQ,OAAO,IAAI,MAAM,IAAI,OAAO;AAAA,MACnI;AAAA,IACJ;AACA,WAAO,EAAE,OAAO,KAAK,OAAO,QAAQ,KAAK,QAAQ,YAAY,KAAK,YAAY,WAAW,SAAS,KAAK,UAAU,QAAQ,SAAS,cAAc;AAAA,EACpJ,CAAC;AACL;AAGO,SAAS,6BAA6B,OAAsD;AAC/F,SAAO,MAAM,QAAQ,UAAQ,CAAC,KAAK,UAAU,QAAQ,KAAK,QAAQ,QAAQ,KAAK,IAAI,QAAQ,KAAK,SAAS,QAAQ,KAAK,OAAO,QAAQ,KAAK,QAAQ,MAAM,CAAC;AAC7J;;;AC9IA,iBAAiB,WAAW,CAAC,UAAoF;AAC7G,QAAM,EAAE,IAAI,MAAM,IAAI,MAAM;AAC5B,MAAI;AACA,UAAM,QAAQ,qBAAqB,KAAK;AACxC,gBAAY,EAAE,IAAI,MAAM,SAAS,MAAM,GAAG,EAAE,UAAU,6BAA6B,KAAK,EAAE,CAAC;AAAA,EAC/F,SAAS,OAAO;AACZ,gBAAY,EAAE,IAAI,MAAM,SAAS,SAAS,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,EAAE,CAAC;AAAA,EACtG;AACJ,CAAC;","names":["CubeFace","page"]}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
// src/CubeFace.ts
|
|
2
|
+
var CubeFace = /* @__PURE__ */ ((CubeFace2) => {
|
|
3
|
+
CubeFace2["EAST"] = "east";
|
|
4
|
+
CubeFace2["WEST"] = "west";
|
|
5
|
+
CubeFace2["UP"] = "up";
|
|
6
|
+
CubeFace2["DOWN"] = "down";
|
|
7
|
+
CubeFace2["SOUTH"] = "south";
|
|
8
|
+
CubeFace2["NORTH"] = "north";
|
|
9
|
+
return CubeFace2;
|
|
10
|
+
})(CubeFace || {});
|
|
11
|
+
var CUBE_FACES = Object.values(CubeFace);
|
|
12
|
+
|
|
13
|
+
// src/world/SectionGeometry.ts
|
|
14
|
+
function buildSectionGeometry(input) {
|
|
15
|
+
const { count, indices, templates, cullMasks, templateData, atlases, maxAtlasSize } = input;
|
|
16
|
+
if (!Number.isInteger(maxAtlasSize) || maxAtlasSize < 1) throw new RangeError("Section atlas size must be a positive integer");
|
|
17
|
+
if (count > indices.length || count > templates.length || count > cullMasks.length) throw new RangeError("Section entry count exceeds its arrays");
|
|
18
|
+
const visible = [];
|
|
19
|
+
const visibleAtlases = /* @__PURE__ */ new Set();
|
|
20
|
+
for (let entry = 0; entry < count; entry++) {
|
|
21
|
+
const template = templateData[templates[entry]];
|
|
22
|
+
if (!template.cullFaces.some((direction) => !(cullMasks[entry] & direction))) continue;
|
|
23
|
+
visible.push(entry);
|
|
24
|
+
visibleAtlases.add(template.atlas);
|
|
25
|
+
}
|
|
26
|
+
const pages = [];
|
|
27
|
+
const locations = /* @__PURE__ */ new Map();
|
|
28
|
+
for (const atlas of [...visibleAtlases].sort((a, b) => atlases[b].height - atlases[a].height)) {
|
|
29
|
+
const { width, height } = atlases[atlas];
|
|
30
|
+
if (width > maxAtlasSize || height > maxAtlasSize) throw new RangeError("Model atlas exceeds the section atlas size limit");
|
|
31
|
+
let selected = -1;
|
|
32
|
+
for (let i = 0; i < pages.length; i++) {
|
|
33
|
+
const page2 = pages[i];
|
|
34
|
+
const nextRow = page2.x + width > maxAtlasSize;
|
|
35
|
+
if ((nextRow ? page2.y + page2.rowHeight : page2.y) + height > maxAtlasSize) continue;
|
|
36
|
+
if (nextRow) {
|
|
37
|
+
page2.y += page2.rowHeight;
|
|
38
|
+
page2.x = 0;
|
|
39
|
+
page2.rowHeight = 0;
|
|
40
|
+
}
|
|
41
|
+
selected = i;
|
|
42
|
+
break;
|
|
43
|
+
}
|
|
44
|
+
if (selected < 0) {
|
|
45
|
+
selected = pages.length;
|
|
46
|
+
pages.push({ placements: [], entries: [], x: 0, y: 0, rowHeight: 0, width: 0, height: 0 });
|
|
47
|
+
}
|
|
48
|
+
const page = pages[selected];
|
|
49
|
+
page.placements.push({ atlas, x: page.x, y: page.y });
|
|
50
|
+
locations.set(atlas, { page: selected, x: page.x, y: page.y });
|
|
51
|
+
page.x += width;
|
|
52
|
+
page.rowHeight = Math.max(page.rowHeight, height);
|
|
53
|
+
page.width = Math.max(page.width, page.x);
|
|
54
|
+
page.height = Math.max(page.height, page.y + height);
|
|
55
|
+
}
|
|
56
|
+
for (const entry of visible) pages[locations.get(templateData[templates[entry]].atlas).page].entries.push(entry);
|
|
57
|
+
return pages.map((page) => {
|
|
58
|
+
let faces = 0;
|
|
59
|
+
for (const entry of page.entries) {
|
|
60
|
+
const template = templateData[templates[entry]];
|
|
61
|
+
for (let face = 0; face < CUBE_FACES.length; face++) {
|
|
62
|
+
if (!(cullMasks[entry] & template.cullFaces[face])) faces++;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
const positions = new Float32Array(faces * 12), normals = new Float32Array(faces * 12);
|
|
66
|
+
const uvs = new Float32Array(faces * 8), uvBounds = new Float32Array(faces * 16), colors = new Float32Array(faces * 12);
|
|
67
|
+
const outputIndices = new Uint32Array(faces * 6);
|
|
68
|
+
let vertex = 0, indexOffset = 0;
|
|
69
|
+
for (const entry of page.entries) {
|
|
70
|
+
const template = templateData[templates[entry]];
|
|
71
|
+
const atlas = atlases[template.atlas];
|
|
72
|
+
const placement = locations.get(template.atlas);
|
|
73
|
+
const mapU = (u) => (placement.x + u * atlas.width) / page.width;
|
|
74
|
+
const mapV = (v) => 1 - (placement.y + (1 - v) * atlas.height) / page.height;
|
|
75
|
+
const offsetX = indices[entry] % 16 * 16;
|
|
76
|
+
const offsetY = Math.floor(indices[entry] / 256) * 16;
|
|
77
|
+
const offsetZ = Math.floor(indices[entry] / 16) % 16 * 16;
|
|
78
|
+
for (let face = 0; face < CUBE_FACES.length; face++) {
|
|
79
|
+
if (cullMasks[entry] & template.cullFaces[face]) continue;
|
|
80
|
+
const start = vertex;
|
|
81
|
+
for (let corner = 0; corner < 4; corner++, vertex++) {
|
|
82
|
+
const source = face * 4 + corner;
|
|
83
|
+
positions[vertex * 3] = template.positions[source * 3] + offsetX;
|
|
84
|
+
positions[vertex * 3 + 1] = template.positions[source * 3 + 1] + offsetY;
|
|
85
|
+
positions[vertex * 3 + 2] = template.positions[source * 3 + 2] + offsetZ;
|
|
86
|
+
normals[vertex * 3] = template.normals[source * 3];
|
|
87
|
+
normals[vertex * 3 + 1] = template.normals[source * 3 + 1];
|
|
88
|
+
normals[vertex * 3 + 2] = template.normals[source * 3 + 2];
|
|
89
|
+
uvs[vertex * 2] = mapU(template.uvs[source * 2]);
|
|
90
|
+
uvs[vertex * 2 + 1] = mapV(template.uvs[source * 2 + 1]);
|
|
91
|
+
uvBounds[vertex * 4] = mapU(template.uvBounds[source * 4]);
|
|
92
|
+
uvBounds[vertex * 4 + 1] = mapV(template.uvBounds[source * 4 + 1]);
|
|
93
|
+
uvBounds[vertex * 4 + 2] = mapU(template.uvBounds[source * 4 + 2]);
|
|
94
|
+
uvBounds[vertex * 4 + 3] = mapV(template.uvBounds[source * 4 + 3]);
|
|
95
|
+
colors[vertex * 3] = template.colors[source * 3];
|
|
96
|
+
colors[vertex * 3 + 1] = template.colors[source * 3 + 1];
|
|
97
|
+
colors[vertex * 3 + 2] = template.colors[source * 3 + 2];
|
|
98
|
+
}
|
|
99
|
+
for (let corner = 0; corner < 6; corner++) outputIndices[indexOffset++] = start + template.indices[face * 6 + corner] - face * 4;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return { width: page.width, height: page.height, placements: page.placements, positions, normals, uvs, uvBounds, colors, indices: outputIndices };
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
function sectionGeometryTransferables(pages) {
|
|
106
|
+
return pages.flatMap((page) => [page.positions.buffer, page.normals.buffer, page.uvs.buffer, page.uvBounds.buffer, page.colors.buffer, page.indices.buffer]);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// src/env/browser/section.worker.ts
|
|
110
|
+
addEventListener("message", (event) => {
|
|
111
|
+
const { id, input } = event.data;
|
|
112
|
+
try {
|
|
113
|
+
const pages = buildSectionGeometry(input);
|
|
114
|
+
postMessage({ id, type: "pages", pages }, { transfer: sectionGeometryTransferables(pages) });
|
|
115
|
+
} catch (error) {
|
|
116
|
+
postMessage({ id, type: "error", message: error instanceof Error ? error.message : String(error) });
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
//# sourceMappingURL=section.worker.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/CubeFace.ts","../../src/world/SectionGeometry.ts","../../src/env/browser/section.worker.ts"],"sourcesContent":["export enum CubeFace {\n EAST = \"east\", // px\n WEST = \"west\", // nx\n UP = \"up\", // py\n DOWN = \"down\", // ny\n SOUTH = \"south\", // pz\n NORTH = \"north\", // nz\n}\n\nexport enum CubeFaceIndex {\n EAST,\n WEST,\n UP,\n DOWN,\n SOUTH,\n NORTH\n}\n\nexport const CUBE_FACES = Object.values(CubeFace);\n\nexport const CUBE_FACE_OFFSETS = [\n [1, 0, 0], [-1, 0, 0], [0, 1, 0], [0, -1, 0], [0, 0, 1], [0, 0, -1]\n] as const;\n","import { CUBE_FACES } from \"../CubeFace\";\n\n/** One cube template with four vertices per face in `CUBE_FACES` order. */\nexport interface SectionTemplateData {\n positions: Float32Array;\n normals: Float32Array;\n uvs: Float32Array;\n uvBounds: Float32Array;\n colors: Float32Array;\n indices: Uint16Array;\n cullFaces: Uint8Array;\n atlas: number;\n}\n\n/** The pixel dimensions of a template atlas. */\nexport interface SectionAtlasSize {\n width: number;\n height: number;\n}\n\n/** Section placements and their shared cube templates, ready for geometry building. */\nexport interface SectionGeometryInput {\n count: number;\n indices: Uint16Array;\n templates: Uint16Array;\n cullMasks: Uint8Array;\n templateData: SectionTemplateData[];\n atlases: SectionAtlasSize[];\n maxAtlasSize: number;\n}\n\n/** Merged cube faces and source-atlas placements for one atlas page. */\nexport interface SectionGeometryPage {\n width: number;\n height: number;\n placements: { atlas: number; x: number; y: number }[];\n positions: Float32Array;\n normals: Float32Array;\n uvs: Float32Array;\n uvBounds: Float32Array;\n colors: Float32Array;\n indices: Uint32Array;\n}\n\n/** Builds section-local geometry from visible cube faces, with bounded atlas pages. */\nexport function buildSectionGeometry(input: SectionGeometryInput): SectionGeometryPage[] {\n const { count, indices, templates, cullMasks, templateData, atlases, maxAtlasSize } = input;\n if (!Number.isInteger(maxAtlasSize) || maxAtlasSize < 1) throw new RangeError(\"Section atlas size must be a positive integer\");\n if (count > indices.length || count > templates.length || count > cullMasks.length) throw new RangeError(\"Section entry count exceeds its arrays\");\n const visible: number[] = [];\n const visibleAtlases = new Set<number>();\n for (let entry = 0; entry < count; entry++) {\n const template = templateData[templates[entry]];\n if (!template.cullFaces.some(direction => !(cullMasks[entry] & direction))) continue;\n visible.push(entry);\n visibleAtlases.add(template.atlas);\n }\n const pages: {\n placements: SectionGeometryPage[\"placements\"]; entries: number[];\n x: number; y: number; rowHeight: number; width: number; height: number;\n }[] = [];\n const locations = new Map<number, { page: number; x: number; y: number }>();\n for (const atlas of [...visibleAtlases].sort((a, b) => atlases[b].height - atlases[a].height)) {\n const { width, height } = atlases[atlas];\n if (width > maxAtlasSize || height > maxAtlasSize) throw new RangeError(\"Model atlas exceeds the section atlas size limit\");\n let selected = -1;\n for (let i = 0; i < pages.length; i++) {\n const page = pages[i];\n const nextRow = page.x + width > maxAtlasSize;\n if ((nextRow ? page.y + page.rowHeight : page.y) + height > maxAtlasSize) continue;\n if (nextRow) {\n page.y += page.rowHeight;\n page.x = 0;\n page.rowHeight = 0;\n }\n selected = i;\n break;\n }\n if (selected < 0) {\n selected = pages.length;\n pages.push({ placements: [], entries: [], x: 0, y: 0, rowHeight: 0, width: 0, height: 0 });\n }\n const page = pages[selected];\n page.placements.push({ atlas, x: page.x, y: page.y });\n locations.set(atlas, { page: selected, x: page.x, y: page.y });\n page.x += width;\n page.rowHeight = Math.max(page.rowHeight, height);\n page.width = Math.max(page.width, page.x);\n page.height = Math.max(page.height, page.y + height);\n }\n for (const entry of visible) pages[locations.get(templateData[templates[entry]].atlas)!.page].entries.push(entry);\n\n return pages.map(page => {\n let faces = 0;\n for (const entry of page.entries) {\n const template = templateData[templates[entry]];\n for (let face = 0; face < CUBE_FACES.length; face++) {\n if (!(cullMasks[entry] & template.cullFaces[face])) faces++;\n }\n }\n const positions = new Float32Array(faces * 12), normals = new Float32Array(faces * 12);\n const uvs = new Float32Array(faces * 8), uvBounds = new Float32Array(faces * 16), colors = new Float32Array(faces * 12);\n const outputIndices = new Uint32Array(faces * 6);\n let vertex = 0, indexOffset = 0;\n for (const entry of page.entries) {\n const template = templateData[templates[entry]];\n const atlas = atlases[template.atlas];\n const placement = locations.get(template.atlas)!;\n const mapU = (u: number) => (placement.x + u * atlas.width) / page.width;\n const mapV = (v: number) => 1 - (placement.y + (1 - v) * atlas.height) / page.height;\n const offsetX = (indices[entry] % 16) * 16;\n const offsetY = Math.floor(indices[entry] / 256) * 16;\n const offsetZ = (Math.floor(indices[entry] / 16) % 16) * 16;\n for (let face = 0; face < CUBE_FACES.length; face++) {\n if (cullMasks[entry] & template.cullFaces[face]) continue;\n const start = vertex;\n for (let corner = 0; corner < 4; corner++, vertex++) {\n const source = face * 4 + corner;\n positions[vertex * 3] = template.positions[source * 3] + offsetX;\n positions[vertex * 3 + 1] = template.positions[source * 3 + 1] + offsetY;\n positions[vertex * 3 + 2] = template.positions[source * 3 + 2] + offsetZ;\n normals[vertex * 3] = template.normals[source * 3];\n normals[vertex * 3 + 1] = template.normals[source * 3 + 1];\n normals[vertex * 3 + 2] = template.normals[source * 3 + 2];\n uvs[vertex * 2] = mapU(template.uvs[source * 2]);\n uvs[vertex * 2 + 1] = mapV(template.uvs[source * 2 + 1]);\n uvBounds[vertex * 4] = mapU(template.uvBounds[source * 4]);\n uvBounds[vertex * 4 + 1] = mapV(template.uvBounds[source * 4 + 1]);\n uvBounds[vertex * 4 + 2] = mapU(template.uvBounds[source * 4 + 2]);\n uvBounds[vertex * 4 + 3] = mapV(template.uvBounds[source * 4 + 3]);\n colors[vertex * 3] = template.colors[source * 3];\n colors[vertex * 3 + 1] = template.colors[source * 3 + 1];\n colors[vertex * 3 + 2] = template.colors[source * 3 + 2];\n }\n for (let corner = 0; corner < 6; corner++) outputIndices[indexOffset++] = start + template.indices[face * 6 + corner] - face * 4;\n }\n }\n return { width: page.width, height: page.height, placements: page.placements, positions, normals, uvs, uvBounds, colors, indices: outputIndices };\n });\n}\n\n/** Returns the buffers behind each page's typed arrays for transfer to another thread. */\nexport function sectionGeometryTransferables(pages: readonly SectionGeometryPage[]): ArrayBuffer[] {\n return pages.flatMap(page => [page.positions.buffer, page.normals.buffer, page.uvs.buffer, page.uvBounds.buffer, page.colors.buffer, page.indices.buffer]);\n}\n","import { buildSectionGeometry, sectionGeometryTransferables, SectionGeometryInput } from \"../../world/SectionGeometry\";\n\naddEventListener(\"message\", (event: MessageEvent<{ id: number; type: \"build\"; input: SectionGeometryInput }>) => {\n const { id, input } = event.data;\n try {\n const pages = buildSectionGeometry(input);\n postMessage({ id, type: \"pages\", pages }, { transfer: sectionGeometryTransferables(pages) });\n } catch (error) {\n postMessage({ id, type: \"error\", message: error instanceof Error ? error.message : String(error) });\n }\n});\n"],"mappings":"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","names":["CubeFace","page"]}
|