@tileflow/core 0.1.0-alpha.40 → 0.1.0-alpha.41
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/3d.js +244 -98
- package/dist/browser.d.ts +14 -17
- package/dist/browser.js +247 -101
- package/dist/build.d.ts +2 -2
- package/dist/build.js +18 -10
- package/dist/config-reference.json +493 -566
- package/dist/{icon-composition-CcSHApUm.d.ts → icon-composition-HUh_Lj8Z.d.ts} +56 -18
- package/dist/index.d.ts +15 -16
- package/dist/index.js +128 -59
- package/dist/worker/camera-tile-worker.global.js +2 -2
- package/docs/buildings-3d.md +25 -11
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3802,19 +3802,19 @@ function deriveGlyph(glyph, metrics) {
|
|
|
3802
3802
|
const bitmap = new Uint8Array(width * rows);
|
|
3803
3803
|
for (let row = 0; row < rows; row++) {
|
|
3804
3804
|
const y = y0 + row + 0.5;
|
|
3805
|
-
for (let
|
|
3806
|
-
const x = x0 +
|
|
3805
|
+
for (let column2 = 0; column2 < width; column2++) {
|
|
3806
|
+
const x = x0 + column2 + 0.5;
|
|
3807
3807
|
const distance = Math.min(x - cell.x0, cell.x1 - x, y - cell.y0, cell.y1 - y);
|
|
3808
3808
|
const background = Math.min(CELL_VALUE, Math.max(0, CELL_EDGE + CELL_SLOPE * distance));
|
|
3809
3809
|
let letter = 0;
|
|
3810
3810
|
if (hasBitmap) {
|
|
3811
|
-
const sourceColumn = x0 +
|
|
3811
|
+
const sourceColumn = x0 + column2 - sourceX;
|
|
3812
3812
|
const sourceRow = y0 + row - sourceY;
|
|
3813
3813
|
if (sourceColumn >= 0 && sourceColumn < sourceWidth && sourceRow >= 0 && sourceRow < sourceHeight) {
|
|
3814
3814
|
letter = glyph.bitmap[sourceRow * sourceWidth + sourceColumn];
|
|
3815
3815
|
}
|
|
3816
3816
|
}
|
|
3817
|
-
bitmap[row * width +
|
|
3817
|
+
bitmap[row * width + column2] = Math.round(Math.max(letter, background));
|
|
3818
3818
|
}
|
|
3819
3819
|
}
|
|
3820
3820
|
return {
|
|
@@ -13573,6 +13573,12 @@ var tileflowModelParts = Object.freeze({
|
|
|
13573
13573
|
accent: 3,
|
|
13574
13574
|
roof: 4
|
|
13575
13575
|
});
|
|
13576
|
+
var tileflowModelArchitecturalPartNames = Object.freeze(
|
|
13577
|
+
Object.keys(tileflowModelParts)
|
|
13578
|
+
);
|
|
13579
|
+
function isTileflowModelPartName(value) {
|
|
13580
|
+
return typeof value === "string" && value.length <= 32 && /^[a-z][a-z0-9]*(?:[-_][a-z0-9]+)*$/u.test(value);
|
|
13581
|
+
}
|
|
13576
13582
|
var tileflowModelLightingRoles = Object.freeze({
|
|
13577
13583
|
unclassified: 0,
|
|
13578
13584
|
wall: 1,
|
|
@@ -13582,7 +13588,16 @@ var tileflowModelLightingRoles = Object.freeze({
|
|
|
13582
13588
|
lamp: 5,
|
|
13583
13589
|
logo: 6
|
|
13584
13590
|
});
|
|
13585
|
-
var
|
|
13591
|
+
var architecturalRoles = {
|
|
13592
|
+
surface: 1,
|
|
13593
|
+
secondary: 1,
|
|
13594
|
+
glass: 4,
|
|
13595
|
+
accent: 1,
|
|
13596
|
+
roof: 3
|
|
13597
|
+
};
|
|
13598
|
+
function tileflowModelDefaultLightingRole(part) {
|
|
13599
|
+
return Object.hasOwn(architecturalRoles, part) ? architecturalRoles[part] : tileflowModelLightingRoles.unclassified;
|
|
13600
|
+
}
|
|
13586
13601
|
var tileflowModelLimits = Object.freeze({
|
|
13587
13602
|
/** Levels of detail, nearest first. */
|
|
13588
13603
|
levels: 3,
|
|
@@ -13599,7 +13614,9 @@ var tileflowModelLimits = Object.freeze({
|
|
|
13599
13614
|
/** Models in one prepared file, as a landmark tile holds them. */
|
|
13600
13615
|
models: 512,
|
|
13601
13616
|
/** Bytes of one prepared file. */
|
|
13602
|
-
bytes: 16 * 1024 * 1024
|
|
13617
|
+
bytes: 16 * 1024 * 1024,
|
|
13618
|
+
/** Differently named parts of one level. */
|
|
13619
|
+
parts: 16
|
|
13603
13620
|
});
|
|
13604
13621
|
var tileflowModelVertexBytes = 16;
|
|
13605
13622
|
function tileflowInsideRings(rings, px, py) {
|
|
@@ -13887,8 +13904,8 @@ function modelsOf(value) {
|
|
|
13887
13904
|
function modelColorsOf(value) {
|
|
13888
13905
|
if (!isRecord7(value)) return {};
|
|
13889
13906
|
const colors = {};
|
|
13890
|
-
for (const part of Object.
|
|
13891
|
-
if (typeof
|
|
13907
|
+
for (const [part, color3] of Object.entries(value))
|
|
13908
|
+
if (isTileflowModelPartName(part) && typeof color3 === "string") colors[part] = color3;
|
|
13892
13909
|
return Object.keys(colors).length > 0 ? { modelColors: colors } : {};
|
|
13893
13910
|
}
|
|
13894
13911
|
function landmarksOf(value) {
|
|
@@ -14317,7 +14334,7 @@ function limitError(message) {
|
|
|
14317
14334
|
return new Error(site ? `${message} Called at ${site}.` : message);
|
|
14318
14335
|
}
|
|
14319
14336
|
function authoringCallSite(stack) {
|
|
14320
|
-
const locations = (stack ?? "").split("\n").slice(1).map((line) => /\(?([^()\s]+?):(\d+):(\d+)\)?$/.exec(line.trim())).filter((match3) => match3 !== null).map(([, file, line,
|
|
14337
|
+
const locations = (stack ?? "").split("\n").slice(1).map((line) => /\(?([^()\s]+?):(\d+):(\d+)\)?$/.exec(line.trim())).filter((match3) => match3 !== null).map(([, file, line, column2]) => ({ file: file.replace(/^file:\/\//, ""), line, column: column2 }));
|
|
14321
14338
|
const own = locations[0]?.file;
|
|
14322
14339
|
const site = locations.find(({ file }) => file !== own && !file.startsWith("node:"));
|
|
14323
14340
|
return site ? `${site.file}:${site.line}:${site.column}` : void 0;
|
|
@@ -17392,13 +17409,14 @@ var buildingsModuleSchema = z7.object({
|
|
|
17392
17409
|
}).optional()
|
|
17393
17410
|
}).strict()
|
|
17394
17411
|
).max(256).optional(),
|
|
17395
|
-
modelColors: z7.
|
|
17396
|
-
|
|
17397
|
-
|
|
17398
|
-
|
|
17399
|
-
|
|
17400
|
-
|
|
17401
|
-
|
|
17412
|
+
modelColors: z7.record(
|
|
17413
|
+
z7.string().refine(isTileflowModelPartName, {
|
|
17414
|
+
message: "A model part is named in lower-case words joined by hyphens or underscores, at most 32 characters."
|
|
17415
|
+
}),
|
|
17416
|
+
themeColorValueSchema
|
|
17417
|
+
).refine((colors) => Object.keys(colors).length <= 64, {
|
|
17418
|
+
message: "A map colours at most 64 model parts."
|
|
17419
|
+
}).optional(),
|
|
17402
17420
|
landmarks: z7.union([
|
|
17403
17421
|
z7.boolean(),
|
|
17404
17422
|
z7.object({
|
|
@@ -20622,7 +20640,7 @@ function placedModels(value, served) {
|
|
|
20622
20640
|
throw new Error(
|
|
20623
20641
|
`The buildings module places missing 3D models: ${missing.join(", ")}. Add ${missing.map((id2) => `${id2}.glb`).join(
|
|
20624
20642
|
", "
|
|
20625
|
-
)} to a map.models directory, with
|
|
20643
|
+
)} to a map.models directory, with each material named after its part, such as surface, glass, roof or water, and run the Node build so the directories are prepared.`
|
|
20626
20644
|
);
|
|
20627
20645
|
return {
|
|
20628
20646
|
models: placements.map((entry) => ({
|
|
@@ -22949,17 +22967,17 @@ function parseBoundaryLookupCsv(text) {
|
|
|
22949
22967
|
);
|
|
22950
22968
|
}
|
|
22951
22969
|
const row = {};
|
|
22952
|
-
header.forEach((
|
|
22970
|
+
header.forEach((column2, position) => {
|
|
22953
22971
|
const cell = record4[position];
|
|
22954
|
-
if (cell === "" || !lookupColumns.has(
|
|
22955
|
-
if (numericLookupColumns.has(
|
|
22972
|
+
if (cell === "" || !lookupColumns.has(column2)) return;
|
|
22973
|
+
if (numericLookupColumns.has(column2)) {
|
|
22956
22974
|
const number = Number(cell);
|
|
22957
22975
|
if (!Number.isSafeInteger(number)) {
|
|
22958
|
-
throw new Error(`Boundaries lookup CSV row ${index + 2} has a non-integer ${
|
|
22976
|
+
throw new Error(`Boundaries lookup CSV row ${index + 2} has a non-integer ${column2}.`);
|
|
22959
22977
|
}
|
|
22960
|
-
row[
|
|
22978
|
+
row[column2] = number;
|
|
22961
22979
|
} else {
|
|
22962
|
-
row[
|
|
22980
|
+
row[column2] = cell;
|
|
22963
22981
|
}
|
|
22964
22982
|
});
|
|
22965
22983
|
if (row.class_tier !== void 0 && !isClassTier(row.class_tier)) {
|
|
@@ -25196,6 +25214,7 @@ function checkTileflowModelSurface(surface, vertices, indices) {
|
|
|
25196
25214
|
const value = attributes[i];
|
|
25197
25215
|
if (!Number.isFinite(value) || Math.abs(value) > 65536) fail("unbounded vertex attributes");
|
|
25198
25216
|
if (i % 8 >= 4 && (value < 0 || value > 1)) fail("vertex RGBA must be zero to one");
|
|
25217
|
+
if ((i % 8 === 2 || i % 8 === 3) && (value < 0 || value > 1)) fail("UV1 must be zero to one");
|
|
25199
25218
|
}
|
|
25200
25219
|
if (!Array.isArray(materials) || materials.length < 1 || materials.length > tileflowModelSurfaceLimits.materials)
|
|
25201
25220
|
fail("material count exceeds the limit");
|
|
@@ -25277,7 +25296,7 @@ function checkTileflowModelSurface(surface, vertices, indices) {
|
|
|
25277
25296
|
fail("emitter count exceeds the limit");
|
|
25278
25297
|
for (const emitter of emitters) {
|
|
25279
25298
|
if (!emitter || typeof emitter !== "object") fail("invalid area emitter");
|
|
25280
|
-
if (!tuple(emitter.start, 3, -2e3, 2e3) || !tuple(emitter.end, 3, -2e3, 2e3) || !number(emitter.height, 0.01, 1e3) || emitter.depth !== void 0 && !number(emitter.depth, 0, 100) || !Object.hasOwn(tileflowModelLightingRoles, emitter.role) || !
|
|
25299
|
+
if (!tuple(emitter.start, 3, -2e3, 2e3) || !tuple(emitter.end, 3, -2e3, 2e3) || !number(emitter.height, 0.01, 1e3) || emitter.depth !== void 0 && !number(emitter.depth, 0, 100) || !Object.hasOwn(tileflowModelLightingRoles, emitter.role) || !isTileflowModelPartName(emitter.part))
|
|
25281
25300
|
fail("invalid area emitter");
|
|
25282
25301
|
if (Math.hypot(emitter.end[0] - emitter.start[0], emitter.end[1] - emitter.start[1]) < 1e-3 || Math.abs(emitter.end[2] - emitter.start[2]) > 0.01)
|
|
25283
25302
|
fail("an area emitter needs a horizontal lower edge");
|
|
@@ -25320,7 +25339,6 @@ var levelNames = ["near", "mid", "far"];
|
|
|
25320
25339
|
var meshopt = "EXT_meshopt_compression";
|
|
25321
25340
|
var quantisation = "KHR_mesh_quantization";
|
|
25322
25341
|
var steps = 32767;
|
|
25323
|
-
var partCount2 = Object.keys(tileflowModelParts).length;
|
|
25324
25342
|
var roleCount = Object.keys(tileflowModelLightingRoles).length;
|
|
25325
25343
|
var modelId2 = /^[a-z0-9]+(?:-[a-z0-9]+)*$/u;
|
|
25326
25344
|
var [glbMagic, jsonChunk, binChunk] = [1179937895, 1313821514, 5130562];
|
|
@@ -25459,20 +25477,33 @@ function encodeTileflowModels(models, compressor) {
|
|
|
25459
25477
|
let surface;
|
|
25460
25478
|
if (mesh.surface && level.attributes) {
|
|
25461
25479
|
const attributes = level.attributes;
|
|
25462
|
-
const data = new Uint8Array(
|
|
25463
|
-
attributes.buffer,
|
|
25464
|
-
attributes.byteOffset,
|
|
25465
|
-
attributes.byteLength
|
|
25466
|
-
);
|
|
25467
|
-
const view = addView(data, level.count, 32, true);
|
|
25468
25480
|
const uv = accessors.length;
|
|
25481
|
+
const rest = new Float32Array(level.count * 6);
|
|
25482
|
+
const second = new Uint16Array(level.count * 2);
|
|
25483
|
+
for (let vertex = 0; vertex < level.count; vertex++) {
|
|
25484
|
+
const at = vertex * 8;
|
|
25485
|
+
rest.set([attributes[at], attributes[at + 1]], vertex * 6);
|
|
25486
|
+
rest.set(attributes.subarray(at + 4, at + 8), vertex * 6 + 2);
|
|
25487
|
+
second[vertex * 2] = Math.round(attributes[at + 2] * 65535);
|
|
25488
|
+
second[vertex * 2 + 1] = Math.round(attributes[at + 3] * 65535);
|
|
25489
|
+
}
|
|
25490
|
+
const view = addView(new Uint8Array(rest.buffer), level.count, 24, true);
|
|
25491
|
+
const lightmap = addView(new Uint8Array(second.buffer), level.count, 4, true);
|
|
25469
25492
|
accessors.push(
|
|
25470
|
-
{ bufferView: view, byteOffset: 0, componentType: 5126, count: level.count, type: "
|
|
25471
|
-
{
|
|
25493
|
+
{ bufferView: view, byteOffset: 0, componentType: 5126, count: level.count, type: "VEC2" },
|
|
25494
|
+
{
|
|
25495
|
+
bufferView: lightmap,
|
|
25496
|
+
byteOffset: 0,
|
|
25497
|
+
componentType: 5123,
|
|
25498
|
+
normalized: true,
|
|
25499
|
+
count: level.count,
|
|
25500
|
+
type: "VEC2"
|
|
25501
|
+
},
|
|
25502
|
+
{ bufferView: view, byteOffset: 8, componentType: 5126, count: level.count, type: "VEC4" }
|
|
25472
25503
|
);
|
|
25473
25504
|
surface = {
|
|
25474
|
-
version:
|
|
25475
|
-
attributes: [uv, uv + 1],
|
|
25505
|
+
version: 2,
|
|
25506
|
+
attributes: [uv, uv + 1, uv + 2],
|
|
25476
25507
|
materials: mesh.surface.materials,
|
|
25477
25508
|
textures: mesh.surface.textures.map(({ bytes, ...texture }) => ({
|
|
25478
25509
|
...texture,
|
|
@@ -25489,7 +25520,7 @@ function encodeTileflowModels(models, compressor) {
|
|
|
25489
25520
|
mesh: meshes.length - 1,
|
|
25490
25521
|
translation: [...level.centre],
|
|
25491
25522
|
scale: [level.step, level.step, level.step],
|
|
25492
|
-
|
|
25523
|
+
extras: { tileflow: { parts: [...partNamesOf(mesh)], ...surface ? { surface } : {} } }
|
|
25493
25524
|
});
|
|
25494
25525
|
}
|
|
25495
25526
|
roots.push(nodes.length);
|
|
@@ -25559,7 +25590,7 @@ async function decodeTileflowModels(buffer, decompressor) {
|
|
|
25559
25590
|
if (source !== 0 || byteStride !== stride || count * byteStride !== length)
|
|
25560
25591
|
throw new Error();
|
|
25561
25592
|
if (filter !== void 0 && filter !== "NONE") throw new Error();
|
|
25562
|
-
if (mode !== (
|
|
25593
|
+
if (mode !== (view.target === 34963 ? "TRIANGLES" : "ATTRIBUTES")) throw new Error();
|
|
25563
25594
|
out = new Uint8Array(length);
|
|
25564
25595
|
decoder.decodeGltfBuffer(out, count, byteStride, slice(bin, byteOffset, byteLength), mode);
|
|
25565
25596
|
} else {
|
|
@@ -25598,6 +25629,7 @@ async function decodeTileflowModels(buffer, decompressor) {
|
|
|
25598
25629
|
}
|
|
25599
25630
|
levels.push({
|
|
25600
25631
|
vertices: level.vertices,
|
|
25632
|
+
partNames: level.partNames,
|
|
25601
25633
|
indices: level.indices,
|
|
25602
25634
|
centre: level.centre,
|
|
25603
25635
|
step: level.step,
|
|
@@ -25752,6 +25784,7 @@ function quantise(mesh, compressor) {
|
|
|
25752
25784
|
...low.map((value, axis) => Math.max(centre[axis] - value, high[axis] - centre[axis]))
|
|
25753
25785
|
);
|
|
25754
25786
|
const step2 = Math.max(reach, 1e-3) / steps;
|
|
25787
|
+
const names = partNamesOf(mesh);
|
|
25755
25788
|
const raw = new Uint8Array(count * tileflowModelVertexBytes);
|
|
25756
25789
|
const view = new DataView(raw.buffer);
|
|
25757
25790
|
for (let vertex = 0; vertex < count; vertex += 1) {
|
|
@@ -25773,12 +25806,12 @@ function quantise(mesh, compressor) {
|
|
|
25773
25806
|
for (let axis = 0; axis < 3; axis += 1)
|
|
25774
25807
|
view.setInt8(at + 8 + axis, clamp3(Math.round(normal[axis] * 127), -127, 127));
|
|
25775
25808
|
const part = mesh.parts[vertex];
|
|
25776
|
-
if (!Number.isInteger(part) || part < 0 || part >=
|
|
25809
|
+
if (!Number.isInteger(part) || part < 0 || part >= names.length)
|
|
25777
25810
|
throw new RangeError(`Vertex ${vertex} has no part.`);
|
|
25778
25811
|
raw[at + 12] = part;
|
|
25779
25812
|
raw[at + 13] = Math.round((clamp3(mesh.shades[vertex], -1, 1) + 1) / 2 * 255);
|
|
25780
25813
|
raw[at + 14] = Math.round(clamp3(mesh.occlusion[vertex], 0, 1) * 255);
|
|
25781
|
-
const role = mesh.lightingRoles?.[vertex] ??
|
|
25814
|
+
const role = mesh.lightingRoles?.[vertex] ?? tileflowModelDefaultLightingRole(names[part]);
|
|
25782
25815
|
if (!Number.isInteger(role) || role < 0 || role >= roleCount)
|
|
25783
25816
|
throw new RangeError(`Vertex ${vertex} has no lighting role.`);
|
|
25784
25817
|
raw[at + 15] = role;
|
|
@@ -25861,6 +25894,10 @@ function checkModel(model) {
|
|
|
25861
25894
|
throw new RangeError(`Every vertex of level ${at} needs a part, a shade and a light.`);
|
|
25862
25895
|
if (level.lightingRoles && level.lightingRoles.length !== count)
|
|
25863
25896
|
throw new RangeError(`Every vertex of level ${at} needs a lighting role.`);
|
|
25897
|
+
if (!isPartNames(partNamesOf(level)))
|
|
25898
|
+
throw new RangeError(
|
|
25899
|
+
`Level ${at} names 1 to ${tileflowModelLimits.parts} different parts, each in lower-case words joined by hyphens or underscores.`
|
|
25900
|
+
);
|
|
25864
25901
|
if (level.surface) checkTileflowModelSurface(level.surface, count, level.indices.length);
|
|
25865
25902
|
for (let index = 0; index < count; index += 1)
|
|
25866
25903
|
for (let axis = 0; axis < 3; axis += 1) {
|
|
@@ -25949,6 +25986,9 @@ function readLevelNode(json, node2, name, viewBytes, hasLightingRoles) {
|
|
|
25949
25986
|
const indexCount = index?.count;
|
|
25950
25987
|
if (!width || index.type !== "SCALAR" || (index.byteOffset ?? 0) !== 0 || !Number.isInteger(indexCount) || indexCount < 3 || indexCount % 3 !== 0 || indexCount / 3 > tileflowModelLimits.triangles)
|
|
25951
25988
|
throw new Error();
|
|
25989
|
+
const own = node2.extras?.tileflow?.parts;
|
|
25990
|
+
const partNames = own === void 0 ? tileflowModelArchitecturalPartNames : own;
|
|
25991
|
+
if (!isPartNames(partNames)) throw new Error();
|
|
25952
25992
|
const vertices = viewBytes(
|
|
25953
25993
|
position.bufferView,
|
|
25954
25994
|
tileflowModelVertexBytes,
|
|
@@ -25957,8 +25997,8 @@ function readLevelNode(json, node2, name, viewBytes, hasLightingRoles) {
|
|
|
25957
25997
|
for (let vertex = 0; vertex < count; vertex += 1) {
|
|
25958
25998
|
const at = vertex * tileflowModelVertexBytes;
|
|
25959
25999
|
const part = vertices[at + 12];
|
|
25960
|
-
if (part >=
|
|
25961
|
-
if (!hasLightingRoles) vertices[at + 15] =
|
|
26000
|
+
if (part >= partNames.length) throw new Error();
|
|
26001
|
+
if (!hasLightingRoles) vertices[at + 15] = tileflowModelDefaultLightingRole(partNames[part]);
|
|
25962
26002
|
else if (vertices[at + 15] >= roleCount) throw new Error();
|
|
25963
26003
|
}
|
|
25964
26004
|
const indexBytes = viewBytes(index.bufferView, width, indexCount * width);
|
|
@@ -25967,18 +26007,30 @@ function readLevelNode(json, node2, name, viewBytes, hasLightingRoles) {
|
|
|
25967
26007
|
const physical = node2.extras?.tileflow?.surface;
|
|
25968
26008
|
let surface;
|
|
25969
26009
|
if (physical !== void 0) {
|
|
25970
|
-
if (physical?.version !==
|
|
26010
|
+
if (physical?.version !== 2 || !Array.isArray(physical.attributes) || physical.attributes.length !== 3)
|
|
25971
26011
|
throw new Error();
|
|
25972
|
-
const uv =
|
|
25973
|
-
|
|
25974
|
-
if (!uv || !colour || (uv.byteOffset ?? 0) !== 0 || colour.byteOffset !== 16 || uv.bufferView !== colour.bufferView || [uv, colour].some(
|
|
25975
|
-
(value) => value.componentType !== 5126 || value.type !== "VEC4" || value.count !== count || value.normalized === true
|
|
25976
|
-
))
|
|
26012
|
+
const [uv, lightmap, colour] = physical.attributes.map(accessor);
|
|
26013
|
+
if (!uv || !lightmap || !colour || (uv.byteOffset ?? 0) !== 0 || colour.byteOffset !== 8 || (lightmap.byteOffset ?? 0) !== 0 || uv.bufferView !== colour.bufferView || uv.bufferView === lightmap.bufferView || uv.componentType !== 5126 || uv.type !== "VEC2" || colour.componentType !== 5126 || colour.type !== "VEC4" || lightmap.componentType !== 5123 || lightmap.type !== "VEC2" || lightmap.normalized !== true || [uv, lightmap, colour].some((value) => value.count !== count))
|
|
25977
26014
|
throw new Error();
|
|
25978
|
-
const
|
|
26015
|
+
const restBytes = viewBytes(uv.bufferView, 24, count * 24);
|
|
26016
|
+
const lightmapBytes = viewBytes(lightmap.bufferView, 4, count * 4);
|
|
26017
|
+
const rest = new Float32Array(
|
|
26018
|
+
restBytes.buffer.slice(restBytes.byteOffset, restBytes.byteOffset + count * 24)
|
|
26019
|
+
);
|
|
26020
|
+
const second = new Uint16Array(
|
|
26021
|
+
lightmapBytes.buffer.slice(lightmapBytes.byteOffset, lightmapBytes.byteOffset + count * 4)
|
|
26022
|
+
);
|
|
26023
|
+
const attributes = new Float32Array(count * 8);
|
|
26024
|
+
for (let vertex = 0; vertex < count; vertex++) {
|
|
26025
|
+
const at = vertex * 8;
|
|
26026
|
+
attributes[at] = rest[vertex * 6];
|
|
26027
|
+
attributes[at + 1] = rest[vertex * 6 + 1];
|
|
26028
|
+
attributes[at + 2] = second[vertex * 2] / 65535;
|
|
26029
|
+
attributes[at + 3] = second[vertex * 2 + 1] / 65535;
|
|
26030
|
+
attributes.set(rest.subarray(vertex * 6 + 2, vertex * 6 + 6), at + 4);
|
|
26031
|
+
}
|
|
25979
26032
|
if (!Array.isArray(physical.textures) || physical.textures.length > 32) throw new Error();
|
|
25980
|
-
|
|
25981
|
-
attributes: new Float32Array(attributeBytes.buffer, attributeBytes.byteOffset, count * 8),
|
|
26033
|
+
const read = {
|
|
25982
26034
|
materials: physical.materials,
|
|
25983
26035
|
ranges: physical.ranges,
|
|
25984
26036
|
textures: physical.textures.map((texture) => {
|
|
@@ -25989,10 +26041,12 @@ function readLevelNode(json, node2, name, viewBytes, hasLightingRoles) {
|
|
|
25989
26041
|
}),
|
|
25990
26042
|
...physical.emitters === void 0 ? {} : { emitters: physical.emitters }
|
|
25991
26043
|
};
|
|
25992
|
-
checkTileflowModelSurface(
|
|
26044
|
+
checkTileflowModelSurface({ ...read, attributes }, count, indexCount);
|
|
26045
|
+
surface = { ...read, uv: column(attributes, 0), rgba: column(attributes, 4) };
|
|
25993
26046
|
}
|
|
25994
26047
|
return {
|
|
25995
26048
|
vertices,
|
|
26049
|
+
partNames: [...partNames],
|
|
25996
26050
|
indices,
|
|
25997
26051
|
centre: [centre[0], centre[1], centre[2]],
|
|
25998
26052
|
step: scale[0],
|
|
@@ -26001,6 +26055,24 @@ function readLevelNode(json, node2, name, viewBytes, hasLightingRoles) {
|
|
|
26001
26055
|
surface
|
|
26002
26056
|
};
|
|
26003
26057
|
}
|
|
26058
|
+
function column(attributes, first) {
|
|
26059
|
+
const out = attributes.slice(first, first + 4);
|
|
26060
|
+
for (let at = 8 + first; at < attributes.length; at += 8)
|
|
26061
|
+
for (let component = 0; component < 4; component += 1)
|
|
26062
|
+
if (attributes[at + component] !== out[component]) {
|
|
26063
|
+
const all2 = new Float32Array(attributes.length / 2);
|
|
26064
|
+
for (let vertex = 0; vertex < all2.length / 4; vertex += 1)
|
|
26065
|
+
all2.set(attributes.subarray(vertex * 8 + first, vertex * 8 + first + 4), vertex * 4);
|
|
26066
|
+
return all2;
|
|
26067
|
+
}
|
|
26068
|
+
return out;
|
|
26069
|
+
}
|
|
26070
|
+
function partNamesOf(mesh) {
|
|
26071
|
+
return mesh.partNames ?? tileflowModelArchitecturalPartNames;
|
|
26072
|
+
}
|
|
26073
|
+
function isPartNames(names) {
|
|
26074
|
+
return Array.isArray(names) && names.length >= 1 && names.length <= tileflowModelLimits.parts && names.every(isTileflowModelPartName) && new Set(names).size === names.length;
|
|
26075
|
+
}
|
|
26004
26076
|
function readGlb(bytes) {
|
|
26005
26077
|
if (bytes.byteLength < 20 || bytes.byteLength > tileflowModelLimits.bytes) throw new Error();
|
|
26006
26078
|
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
@@ -26150,8 +26222,7 @@ function validFootprint(footprint) {
|
|
|
26150
26222
|
}
|
|
26151
26223
|
function readTileflowLandmarkRegion(json) {
|
|
26152
26224
|
if (!isRecord18(json)) return void 0;
|
|
26153
|
-
|
|
26154
|
-
if (!named && json.format !== "tileflow-landmark-region-v1") return void 0;
|
|
26225
|
+
if (json.format !== "tileflow-landmark-region-v2") return void 0;
|
|
26155
26226
|
const region = json.region;
|
|
26156
26227
|
if (json.zoom !== tileflowLandmarkTileZoom || !Array.isArray(region) || region.length !== 3 || region[0] !== tileflowLandmarkRegionZoom || !Array.isArray(json.tiles))
|
|
26157
26228
|
return void 0;
|
|
@@ -26159,17 +26230,13 @@ function readTileflowLandmarkRegion(json) {
|
|
|
26159
26230
|
if (!Number.isInteger(x) || !Number.isInteger(y)) return void 0;
|
|
26160
26231
|
const tiles = [];
|
|
26161
26232
|
for (const tile of json.tiles) {
|
|
26162
|
-
if (!Array.isArray(tile) || tile.length !==
|
|
26233
|
+
if (!Array.isArray(tile) || tile.length !== 4) return void 0;
|
|
26163
26234
|
const [tx, ty, hash, listed] = tile;
|
|
26164
26235
|
if (!Number.isInteger(tx) || !Number.isInteger(ty) || typeof hash !== "string")
|
|
26165
26236
|
return void 0;
|
|
26166
26237
|
if (!sha256.test(hash)) return void 0;
|
|
26167
26238
|
const [rx, ry] = tileflowLandmarkRegionOf([tx, ty]);
|
|
26168
26239
|
if (rx !== x || ry !== y) return void 0;
|
|
26169
|
-
if (!named) {
|
|
26170
|
-
tiles.push([tx, ty, hash]);
|
|
26171
|
-
continue;
|
|
26172
|
-
}
|
|
26173
26240
|
const landmarks = readLandmarks(listed, tx, ty);
|
|
26174
26241
|
if (!landmarks) return void 0;
|
|
26175
26242
|
tiles.push([tx, ty, hash, landmarks]);
|
|
@@ -26298,6 +26365,7 @@ export {
|
|
|
26298
26365
|
isTileflowCompilationPhase,
|
|
26299
26366
|
isTileflowIconSetSource,
|
|
26300
26367
|
isTileflowLocalDirectory,
|
|
26368
|
+
isTileflowModelPartName,
|
|
26301
26369
|
isTileflowPortableId,
|
|
26302
26370
|
isTileflowThemeName,
|
|
26303
26371
|
isTileflowTimeOfDay,
|
|
@@ -26473,8 +26541,9 @@ export {
|
|
|
26473
26541
|
tileflowMapDefaultMaxDepth,
|
|
26474
26542
|
tileflowMapIdSchema,
|
|
26475
26543
|
tileflowMaxPitch,
|
|
26544
|
+
tileflowModelArchitecturalPartNames,
|
|
26476
26545
|
tileflowModelContentType,
|
|
26477
|
-
|
|
26546
|
+
tileflowModelDefaultLightingRole,
|
|
26478
26547
|
tileflowModelFileName,
|
|
26479
26548
|
tileflowModelImageSize,
|
|
26480
26549
|
tileflowModelLightingRoles,
|