@hypersoniclabs/helix-cli 0.1.25-helix3.480 → 0.1.25-helix3.481
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/city/buildings/build.d.ts +130 -0
- package/dist/city/buildings/build.js +304 -0
- package/dist/city/buildings/build.js.map +1 -0
- package/dist/city/buildings/check.d.ts +64 -0
- package/dist/city/buildings/check.js +342 -0
- package/dist/city/buildings/check.js.map +1 -0
- package/dist/city/buildings/colliders.d.ts +30 -0
- package/dist/city/buildings/colliders.js +95 -0
- package/dist/city/buildings/colliders.js.map +1 -0
- package/dist/city/buildings/command.d.ts +4 -0
- package/dist/city/buildings/command.js +96 -0
- package/dist/city/buildings/command.js.map +1 -0
- package/dist/city/buildings/emit.d.ts +9 -0
- package/dist/city/buildings/emit.js +54 -0
- package/dist/city/buildings/emit.js.map +1 -0
- package/dist/city/buildings/facade.d.ts +60 -0
- package/dist/city/buildings/facade.js +214 -0
- package/dist/city/buildings/facade.js.map +1 -0
- package/dist/city/buildings/gallery.d.ts +3 -0
- package/dist/city/buildings/gallery.js +104 -0
- package/dist/city/buildings/gallery.js.map +1 -0
- package/dist/city/buildings/glb.d.ts +22 -0
- package/dist/city/buildings/glb.js +110 -0
- package/dist/city/buildings/glb.js.map +1 -0
- package/dist/city/buildings/ground.d.ts +11 -0
- package/dist/city/buildings/ground.js +87 -0
- package/dist/city/buildings/ground.js.map +1 -0
- package/dist/city/buildings/index.d.ts +7 -0
- package/dist/city/buildings/index.js +35 -0
- package/dist/city/buildings/index.js.map +1 -0
- package/dist/city/buildings/mesh.d.ts +35 -0
- package/dist/city/buildings/mesh.js +122 -0
- package/dist/city/buildings/mesh.js.map +1 -0
- package/dist/city/buildings/model.d.ts +64 -0
- package/dist/city/buildings/model.js +4 -0
- package/dist/city/buildings/model.js.map +1 -0
- package/dist/city/buildings/plan.d.ts +30 -0
- package/dist/city/buildings/plan.js +288 -0
- package/dist/city/buildings/plan.js.map +1 -0
- package/dist/city/buildings/poly.d.ts +56 -0
- package/dist/city/buildings/poly.js +240 -0
- package/dist/city/buildings/poly.js.map +1 -0
- package/dist/city/buildings/roofs.d.ts +47 -0
- package/dist/city/buildings/roofs.js +359 -0
- package/dist/city/buildings/roofs.js.map +1 -0
- package/dist/city/buildings/skeleton.d.ts +32 -0
- package/dist/city/buildings/skeleton.js +557 -0
- package/dist/city/buildings/skeleton.js.map +1 -0
- package/dist/city/buildings/street.d.ts +17 -0
- package/dist/city/buildings/street.js +132 -0
- package/dist/city/buildings/street.js.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/docs/city-buildings.md +130 -0
- package/package.json +3 -2
- package/plugins/beamng-vehicle/bin/__pycache__/beamng_abs.cpython-312.pyc +0 -0
- package/plugins/beamng-vehicle/bin/__pycache__/beamng_audio.cpython-312.pyc +0 -0
- package/plugins/beamng-vehicle/bin/__pycache__/beamng_engine.cpython-312.pyc +0 -0
- package/plugins/beamng-vehicle/bin/__pycache__/beamng_expression.cpython-312.pyc +0 -0
- package/plugins/beamng-vehicle/bin/__pycache__/beamng_jbeam.cpython-312.pyc +0 -0
- package/plugins/beamng-vehicle/bin/__pycache__/beamng_materials.cpython-312.pyc +0 -0
- package/plugins/beamng-vehicle/bin/__pycache__/beamng_stock_events.cpython-312.pyc +0 -0
- package/plugins/beamng-vehicle/bin/__pycache__/fmod_studio.cpython-312.pyc +0 -0
- package/plugins/beamng-vehicle/bin/__pycache__/fsb5.cpython-312.pyc +0 -0
- package/plugins/beamng-vehicle/bin/__pycache__/sim_audio.cpython-312.pyc +0 -0
- package/plugins/beamng-vehicle/bin/__pycache__/sim_audio_ac.cpython-312.pyc +0 -0
- package/plugins/beamng-vehicle/bin/__pycache__/sim_audio_beamng.cpython-312.pyc +0 -0
- package/plugins/beamng-vehicle/bin/__pycache__/sim_audio_fixtures.cpython-312.pyc +0 -0
- package/plugins/beamng-vehicle/bin/__pycache__/test_beamng_engine.cpython-312.pyc +0 -0
- package/plugins/beamng-vehicle/bin/__pycache__/test_sim_audio.cpython-312.pyc +0 -0
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { type CitySource, type Vec2 } from '../source';
|
|
2
|
+
import { type GroundFilter } from './ground';
|
|
3
|
+
import type { BuildingsStats } from './model';
|
|
4
|
+
/** Bump when a change to the generator changes any output byte (the digest gate in digest.spec.ts pins it). */
|
|
5
|
+
export declare const BUILDINGS_GENERATOR_VERSION = 1;
|
|
6
|
+
export declare const BUILDINGS_MANIFEST_SCHEMA: "helix.city-buildings/1";
|
|
7
|
+
export declare const BUILDINGS_MANIFEST_FILE = "buildings.json";
|
|
8
|
+
export declare const CELL_INDEX_SCHEMA: "helix.city-buildings-index/1";
|
|
9
|
+
export interface BuildBuildingsOptions {
|
|
10
|
+
out: string;
|
|
11
|
+
cellM?: number;
|
|
12
|
+
farCellM?: number;
|
|
13
|
+
groundFilter?: GroundFilter;
|
|
14
|
+
/** Plan only the first N buildings (by id): for smoke runs. */
|
|
15
|
+
limit?: number;
|
|
16
|
+
/** Nothing is written; everything else runs (timing and sizes). */
|
|
17
|
+
dryRun?: boolean;
|
|
18
|
+
}
|
|
19
|
+
export interface FileRef {
|
|
20
|
+
file: string;
|
|
21
|
+
sha256: string;
|
|
22
|
+
bytes: number;
|
|
23
|
+
}
|
|
24
|
+
export interface CellEntry {
|
|
25
|
+
key: string;
|
|
26
|
+
ix: number;
|
|
27
|
+
iz: number;
|
|
28
|
+
/** Scene metres of the cell origin the GLB and collider coordinates are relative to. */
|
|
29
|
+
origin: [number, number, number];
|
|
30
|
+
bounds: {
|
|
31
|
+
min: [number, number, number];
|
|
32
|
+
max: [number, number, number];
|
|
33
|
+
};
|
|
34
|
+
buildings: number;
|
|
35
|
+
meshBuildings: number;
|
|
36
|
+
near: (FileRef & {
|
|
37
|
+
triangles: number;
|
|
38
|
+
vertices: number;
|
|
39
|
+
}) | null;
|
|
40
|
+
box: FileRef & {
|
|
41
|
+
triangles: number;
|
|
42
|
+
vertices: number;
|
|
43
|
+
};
|
|
44
|
+
colliders: FileRef & {
|
|
45
|
+
boxes: number;
|
|
46
|
+
hulls: number;
|
|
47
|
+
};
|
|
48
|
+
index: FileRef;
|
|
49
|
+
}
|
|
50
|
+
export interface FarEntry extends FileRef {
|
|
51
|
+
key: string;
|
|
52
|
+
ix: number;
|
|
53
|
+
iz: number;
|
|
54
|
+
/** Cluster-local coordinates: positions are relative to this origin (the centre of the cluster, y = 0). */
|
|
55
|
+
origin: [number, number, number];
|
|
56
|
+
bounds: {
|
|
57
|
+
min: [number, number, number];
|
|
58
|
+
max: [number, number, number];
|
|
59
|
+
};
|
|
60
|
+
/** Fine cell keys in source order: `_HELIX_HLOD_SOURCE` value i is `cells[i]`. */
|
|
61
|
+
cells: string[];
|
|
62
|
+
triangles: number;
|
|
63
|
+
buildings: number;
|
|
64
|
+
quantizationErrorM: number;
|
|
65
|
+
}
|
|
66
|
+
export interface MeshBuildingEntry {
|
|
67
|
+
id: string;
|
|
68
|
+
cell: string;
|
|
69
|
+
kind: string;
|
|
70
|
+
ref: string;
|
|
71
|
+
baseY: number;
|
|
72
|
+
heightM: number;
|
|
73
|
+
}
|
|
74
|
+
export interface BuildingsManifest {
|
|
75
|
+
schema: typeof BUILDINGS_MANIFEST_SCHEMA;
|
|
76
|
+
generator: {
|
|
77
|
+
name: 'helix-city-buildings';
|
|
78
|
+
version: number;
|
|
79
|
+
};
|
|
80
|
+
source: {
|
|
81
|
+
id: string;
|
|
82
|
+
manifestSha256: string;
|
|
83
|
+
};
|
|
84
|
+
options: {
|
|
85
|
+
cellM: number;
|
|
86
|
+
farCellM: number;
|
|
87
|
+
groundFilter: string;
|
|
88
|
+
groundKind: string;
|
|
89
|
+
};
|
|
90
|
+
boundsXZ: [Vec2, Vec2];
|
|
91
|
+
cells: CellEntry[];
|
|
92
|
+
far: FarEntry[];
|
|
93
|
+
meshBuildings: MeshBuildingEntry[];
|
|
94
|
+
totals: {
|
|
95
|
+
buildings: number;
|
|
96
|
+
parts: number;
|
|
97
|
+
meshBuildings: number;
|
|
98
|
+
cells: number;
|
|
99
|
+
nearTriangles: number;
|
|
100
|
+
boxTriangles: number;
|
|
101
|
+
farTriangles: number;
|
|
102
|
+
nearBytes: number;
|
|
103
|
+
boxBytes: number;
|
|
104
|
+
colliderBytes: number;
|
|
105
|
+
indexBytes: number;
|
|
106
|
+
farBytes: number;
|
|
107
|
+
colliders: number;
|
|
108
|
+
nearBox: number;
|
|
109
|
+
nearPoly: number;
|
|
110
|
+
};
|
|
111
|
+
stats: BuildingsStats;
|
|
112
|
+
}
|
|
113
|
+
export interface BuildTimings {
|
|
114
|
+
readMs: number;
|
|
115
|
+
planMs: number;
|
|
116
|
+
emitMs: number;
|
|
117
|
+
encodeMs: number;
|
|
118
|
+
writeMs: number;
|
|
119
|
+
totalMs: number;
|
|
120
|
+
}
|
|
121
|
+
export interface BuildResult {
|
|
122
|
+
manifest: BuildingsManifest;
|
|
123
|
+
manifestSha256: string;
|
|
124
|
+
timings: BuildTimings;
|
|
125
|
+
out: string;
|
|
126
|
+
}
|
|
127
|
+
export declare function newStats(): BuildingsStats;
|
|
128
|
+
/** Builds from a folder on disk (overrides applied, hashes verified). */
|
|
129
|
+
export declare function buildBuildings(sourceDir: string, options: BuildBuildingsOptions): Promise<BuildResult>;
|
|
130
|
+
export declare function buildBuildingsFromSource(source: CitySource, manifestSha256: string, options: BuildBuildingsOptions): Promise<BuildResult>;
|
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// `helix city buildings build`: a helix.city-source/1 folder -> content-addressed building cells and a whole-map far layer.
|
|
3
|
+
//
|
|
4
|
+
// <out>/buildings.json manifest (helix.city-buildings/1): cells, far clusters, mesh buildings, numbers
|
|
5
|
+
// <out>/chunks/building/<sha256>.glb NEAR level of a 256 m cell (LOD0): chosen representation, roofs, parapets
|
|
6
|
+
// <out>/chunks/building-box/<sha256>.glb BOX level of a cell (LOD1): one oriented box per part, <= 12 triangles
|
|
7
|
+
// <out>/chunks/building-collider/<sha256>.bin one oriented box per part (colliders.ts)
|
|
8
|
+
// <out>/chunks/building-index/<sha256>.json building id -> triangle ranges, levels, use (the design's buildings/<cell> sidecar)
|
|
9
|
+
// <out>/chunks/building-far/<sha256>.glb the generator-written HLOD v2 "complete" layer: box masses per 1,024 m cluster
|
|
10
|
+
//
|
|
11
|
+
// A chunk's bytes are a pure function of the generator version, the cell and the source features it owns (plus the
|
|
12
|
+
// roads and shop POIs near them), so an edit touches only the cells it reaches and neighbours keep their names.
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
exports.CELL_INDEX_SCHEMA = exports.BUILDINGS_MANIFEST_FILE = exports.BUILDINGS_MANIFEST_SCHEMA = exports.BUILDINGS_GENERATOR_VERSION = void 0;
|
|
15
|
+
exports.newStats = newStats;
|
|
16
|
+
exports.buildBuildings = buildBuildings;
|
|
17
|
+
exports.buildBuildingsFromSource = buildBuildingsFromSource;
|
|
18
|
+
const promises_1 = require("node:fs/promises");
|
|
19
|
+
const node_path_1 = require("node:path");
|
|
20
|
+
const source_1 = require("../source");
|
|
21
|
+
const colliders_1 = require("./colliders");
|
|
22
|
+
const emit_1 = require("./emit");
|
|
23
|
+
const ground_1 = require("./ground");
|
|
24
|
+
const glb_1 = require("./glb");
|
|
25
|
+
const mesh_1 = require("./mesh");
|
|
26
|
+
const plan_1 = require("./plan");
|
|
27
|
+
const street_1 = require("./street");
|
|
28
|
+
/** Bump when a change to the generator changes any output byte (the digest gate in digest.spec.ts pins it). */
|
|
29
|
+
exports.BUILDINGS_GENERATOR_VERSION = 1;
|
|
30
|
+
exports.BUILDINGS_MANIFEST_SCHEMA = 'helix.city-buildings/1';
|
|
31
|
+
exports.BUILDINGS_MANIFEST_FILE = 'buildings.json';
|
|
32
|
+
exports.CELL_INDEX_SCHEMA = 'helix.city-buildings-index/1';
|
|
33
|
+
const key2 = (ix, iz) => `${ix},${iz}`;
|
|
34
|
+
function toMeshData(mb) {
|
|
35
|
+
return {
|
|
36
|
+
positions: Float32Array.from(mb.positions),
|
|
37
|
+
normals: Float32Array.from(mb.normals),
|
|
38
|
+
uvs: Float32Array.from(mb.uvs),
|
|
39
|
+
facade: Uint16Array.from(mb.facade),
|
|
40
|
+
colors: Uint8Array.from(mb.colors),
|
|
41
|
+
indices: Uint32Array.from(mb.indices),
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
function boundsOf(mb, origin) {
|
|
45
|
+
const min = [Infinity, Infinity, Infinity];
|
|
46
|
+
const max = [-Infinity, -Infinity, -Infinity];
|
|
47
|
+
for (let i = 0; i < mb.vertexCount; i += 1) {
|
|
48
|
+
const p = [mb.positions[i * 3] + origin[0], mb.positions[i * 3 + 1], mb.positions[i * 3 + 2] + origin[1]];
|
|
49
|
+
for (let a = 0; a < 3; a += 1) {
|
|
50
|
+
if (p[a] < min[a])
|
|
51
|
+
min[a] = p[a];
|
|
52
|
+
if (p[a] > max[a])
|
|
53
|
+
max[a] = p[a];
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return { min: min.map(source_1.roundMm), max: max.map(source_1.roundMm) };
|
|
57
|
+
}
|
|
58
|
+
async function store(out, dir, ext, bytes, dryRun) {
|
|
59
|
+
const sha256 = (0, source_1.sha256Hex)(bytes);
|
|
60
|
+
const file = `chunks/${dir}/${sha256}.${ext}`;
|
|
61
|
+
if (!dryRun) {
|
|
62
|
+
const path = (0, node_path_1.join)(out, file);
|
|
63
|
+
await (0, promises_1.mkdir)((0, node_path_1.dirname)(path), { recursive: true });
|
|
64
|
+
const exists = await (0, promises_1.stat)(path).then((s) => s.size === bytes.byteLength, () => false);
|
|
65
|
+
if (!exists)
|
|
66
|
+
await (0, promises_1.writeFile)(path, bytes);
|
|
67
|
+
}
|
|
68
|
+
return { file, sha256, bytes: bytes.byteLength };
|
|
69
|
+
}
|
|
70
|
+
function newStats() {
|
|
71
|
+
return { buildings: 0, parts: 0, meshBuildings: 0, refused: {}, notes: {}, nearBox: 0, nearPoly: 0, roofs: {} };
|
|
72
|
+
}
|
|
73
|
+
/** Builds from a folder on disk (overrides applied, hashes verified). */
|
|
74
|
+
async function buildBuildings(sourceDir, options) {
|
|
75
|
+
const t0 = performance.now();
|
|
76
|
+
const dir = (0, node_path_1.resolve)(sourceDir);
|
|
77
|
+
const loaded = await (0, source_1.readCitySource)(dir);
|
|
78
|
+
const { source } = (0, source_1.applyOverrides)(loaded);
|
|
79
|
+
const manifestSha256 = await (0, source_1.readCitySourceIdentity)(dir);
|
|
80
|
+
const readMs = performance.now() - t0;
|
|
81
|
+
const result = await buildBuildingsFromSource(source, manifestSha256, options);
|
|
82
|
+
result.timings.readMs = readMs;
|
|
83
|
+
result.timings.totalMs = performance.now() - t0;
|
|
84
|
+
return result;
|
|
85
|
+
}
|
|
86
|
+
async function buildBuildingsFromSource(source, manifestSha256, options) {
|
|
87
|
+
const t0 = performance.now();
|
|
88
|
+
const cellM = options.cellM ?? source_1.CITY_SOURCE_GRID_M;
|
|
89
|
+
const farCellM = options.farCellM ?? cellM * 4;
|
|
90
|
+
if (!(cellM > 0) || farCellM % cellM !== 0)
|
|
91
|
+
throw new Error(`--far-cell (${farCellM}) must be a multiple of --cell (${cellM})`);
|
|
92
|
+
const out = (0, node_path_1.resolve)(options.out);
|
|
93
|
+
const dryRun = options.dryRun === true;
|
|
94
|
+
const stats = newStats();
|
|
95
|
+
const timings = { readMs: 0, planMs: 0, emitMs: 0, encodeMs: 0, writeMs: 0, totalMs: 0 };
|
|
96
|
+
// ---- plan every building
|
|
97
|
+
const tPlan = performance.now();
|
|
98
|
+
const ground = (0, ground_1.createGroundModel)(source.terrain, options.groundFilter ?? 'auto');
|
|
99
|
+
const ctx = { ground, defaults: source.manifest.defaults, landUse: new plan_1.LandUseIndex(source.areas), cellM, stats };
|
|
100
|
+
const streets = new street_1.StreetIndex(source.roads, source.pois);
|
|
101
|
+
const rows = [...(source.buildings ?? [])].sort((a, b) => (a.id < b.id ? -1 : a.id > b.id ? 1 : 0));
|
|
102
|
+
const plans = [];
|
|
103
|
+
for (const row of options.limit !== undefined ? rows.slice(0, options.limit) : rows) {
|
|
104
|
+
const plan = (0, plan_1.planBuilding)(row, ctx);
|
|
105
|
+
if (!plan)
|
|
106
|
+
continue;
|
|
107
|
+
plans.push(plan);
|
|
108
|
+
stats.buildings += 1;
|
|
109
|
+
stats.parts += plan.parts.length;
|
|
110
|
+
if (plan.mesh)
|
|
111
|
+
stats.meshBuildings += 1;
|
|
112
|
+
for (const part of plan.parts) {
|
|
113
|
+
const key = part.roof.kind;
|
|
114
|
+
stats.roofs[key] = (stats.roofs[key] ?? 0) + 1;
|
|
115
|
+
if (!plan.mesh) {
|
|
116
|
+
if (part.rep === 'box')
|
|
117
|
+
stats.nearBox += 1;
|
|
118
|
+
else
|
|
119
|
+
stats.nearPoly += 1;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
timings.planMs = performance.now() - tPlan;
|
|
124
|
+
// ---- group by cell
|
|
125
|
+
const byCell = new Map();
|
|
126
|
+
for (const plan of plans) {
|
|
127
|
+
const key = key2(plan.cell[0], plan.cell[1]);
|
|
128
|
+
const list = byCell.get(key);
|
|
129
|
+
if (list)
|
|
130
|
+
list.push(plan);
|
|
131
|
+
else
|
|
132
|
+
byCell.set(key, [plan]);
|
|
133
|
+
}
|
|
134
|
+
const cellKeys = [...byCell.keys()].sort((a, b) => {
|
|
135
|
+
const [ax, az] = a.split(',').map(Number);
|
|
136
|
+
const [bx, bz] = b.split(',').map(Number);
|
|
137
|
+
return az - bz || ax - bx;
|
|
138
|
+
});
|
|
139
|
+
const cells = [];
|
|
140
|
+
const boxData = new Map();
|
|
141
|
+
const meshBuildings = [];
|
|
142
|
+
const totals = {
|
|
143
|
+
buildings: stats.buildings, parts: stats.parts, meshBuildings: stats.meshBuildings, cells: 0, nearTriangles: 0, boxTriangles: 0, farTriangles: 0,
|
|
144
|
+
nearBytes: 0, boxBytes: 0, colliderBytes: 0, indexBytes: 0, farBytes: 0, colliders: 0, nearBox: stats.nearBox, nearPoly: stats.nearPoly,
|
|
145
|
+
};
|
|
146
|
+
for (const key of cellKeys) {
|
|
147
|
+
const group = byCell.get(key);
|
|
148
|
+
const [ix, iz] = group[0].cell;
|
|
149
|
+
const origin = [ix * cellM, iz * cellM];
|
|
150
|
+
const tEmit = performance.now();
|
|
151
|
+
const near = new mesh_1.MeshBuilder(origin);
|
|
152
|
+
const box = new mesh_1.MeshBuilder(origin);
|
|
153
|
+
const nearRanges = [];
|
|
154
|
+
const boxRanges = [];
|
|
155
|
+
for (const plan of group) {
|
|
156
|
+
const n0 = near.triangleCount;
|
|
157
|
+
if (!plan.mesh)
|
|
158
|
+
(0, emit_1.emitBuilding)(near, plan, 'near', streets);
|
|
159
|
+
nearRanges.push(n0, near.triangleCount - n0);
|
|
160
|
+
const b0 = box.triangleCount;
|
|
161
|
+
(0, emit_1.emitBuilding)(box, plan, 'box', streets);
|
|
162
|
+
boxRanges.push(b0, box.triangleCount - b0);
|
|
163
|
+
if (plan.mesh)
|
|
164
|
+
meshBuildings.push({ id: plan.id, cell: key, kind: plan.mesh.kind, ref: plan.mesh.ref, baseY: (0, source_1.roundMm)(plan.baseY), heightM: (0, source_1.roundMm)(plan.heightM) });
|
|
165
|
+
}
|
|
166
|
+
timings.emitMs += performance.now() - tEmit;
|
|
167
|
+
const tEnc = performance.now();
|
|
168
|
+
const extras = { cell: [ix, iz], origin: [origin[0], 0, origin[1]], generator: exports.BUILDINGS_GENERATOR_VERSION };
|
|
169
|
+
const nearGlb = near.triangleCount > 0 ? await (0, glb_1.encodeBuildingGlb)(toMeshData(near), `buildings ${key} near`, { ...extras, level: 'near' }) : null;
|
|
170
|
+
const boxMesh = toMeshData(box);
|
|
171
|
+
const boxGlb = await (0, glb_1.encodeBuildingGlb)(boxMesh, `buildings ${key} box`, { ...extras, level: 'box' });
|
|
172
|
+
const colliders = (0, colliders_1.encodeColliders)(group, origin);
|
|
173
|
+
const index = {
|
|
174
|
+
schema: exports.CELL_INDEX_SCHEMA,
|
|
175
|
+
cell: [ix, iz],
|
|
176
|
+
ids: group.map((p) => p.id),
|
|
177
|
+
near: nearRanges,
|
|
178
|
+
box: boxRanges,
|
|
179
|
+
levels: group.map((p) => p.levels),
|
|
180
|
+
heightM: group.map((p) => (0, source_1.roundMm)(p.heightM)),
|
|
181
|
+
use: group.map((p) => p.use),
|
|
182
|
+
repr: group.map((p) => (p.mesh ? 'm' : p.parts.every((q) => q.rep === 'box') ? 'b' : 'p')).join(''),
|
|
183
|
+
family: group.map((p) => p.facade.familyName),
|
|
184
|
+
};
|
|
185
|
+
timings.encodeMs += performance.now() - tEnc;
|
|
186
|
+
const tWrite = performance.now();
|
|
187
|
+
const nearRef = nearGlb ? await store(out, 'building', 'glb', nearGlb.bytes, dryRun) : null;
|
|
188
|
+
const boxRef = await store(out, 'building-box', 'glb', boxGlb.bytes, dryRun);
|
|
189
|
+
const colliderRef = await store(out, 'building-collider', 'bin', colliders.bytes, dryRun);
|
|
190
|
+
const indexRef = await store(out, 'building-index', 'json', Buffer.from(`${JSON.stringify(index)}\n`, 'utf8'), dryRun);
|
|
191
|
+
timings.writeMs += performance.now() - tWrite;
|
|
192
|
+
const bounds = boundsOf(box, origin);
|
|
193
|
+
cells.push({
|
|
194
|
+
key, ix, iz, origin: [origin[0], 0, origin[1]], bounds, buildings: group.length, meshBuildings: group.filter((p) => p.mesh).length,
|
|
195
|
+
near: nearRef && nearGlb ? { ...nearRef, triangles: nearGlb.triangles, vertices: nearGlb.vertices } : null,
|
|
196
|
+
box: { ...boxRef, triangles: boxGlb.triangles, vertices: boxGlb.vertices },
|
|
197
|
+
colliders: { ...colliderRef, ...colliders.counts },
|
|
198
|
+
index: indexRef,
|
|
199
|
+
});
|
|
200
|
+
totals.cells += 1;
|
|
201
|
+
totals.nearTriangles += nearGlb?.triangles ?? 0;
|
|
202
|
+
totals.boxTriangles += boxGlb.triangles;
|
|
203
|
+
totals.nearBytes += nearRef?.bytes ?? 0;
|
|
204
|
+
totals.boxBytes += boxRef.bytes;
|
|
205
|
+
totals.colliderBytes += colliderRef.bytes;
|
|
206
|
+
totals.indexBytes += indexRef.bytes;
|
|
207
|
+
totals.colliders += colliders.counts.boxes + colliders.counts.hulls;
|
|
208
|
+
boxData.set(key, { mesh: boxMesh, origin, ix, iz, buildings: group.length });
|
|
209
|
+
}
|
|
210
|
+
// ---- the far layer: boxes of every cell, merged per coarse cluster, source = fine cell
|
|
211
|
+
const far = [];
|
|
212
|
+
const perFar = Math.round(farCellM / cellM);
|
|
213
|
+
const clusters = new Map();
|
|
214
|
+
for (const key of cellKeys) {
|
|
215
|
+
const d = boxData.get(key);
|
|
216
|
+
const fx = Math.floor(d.ix / perFar);
|
|
217
|
+
const fz = Math.floor(d.iz / perFar);
|
|
218
|
+
const ck = key2(fx, fz);
|
|
219
|
+
const list = clusters.get(ck);
|
|
220
|
+
if (list)
|
|
221
|
+
list.push(key);
|
|
222
|
+
else
|
|
223
|
+
clusters.set(ck, [key]);
|
|
224
|
+
}
|
|
225
|
+
const clusterKeys = [...clusters.keys()].sort((a, b) => {
|
|
226
|
+
const [ax, az] = a.split(',').map(Number);
|
|
227
|
+
const [bx, bz] = b.split(',').map(Number);
|
|
228
|
+
return az - bz || ax - bx;
|
|
229
|
+
});
|
|
230
|
+
for (const ck of clusterKeys) {
|
|
231
|
+
const members = clusters.get(ck); // already in (iz, ix) order
|
|
232
|
+
const [fx, fz] = ck.split(',').map(Number);
|
|
233
|
+
const origin = [(fx + 0.5) * farCellM, 0, (fz + 0.5) * farCellM];
|
|
234
|
+
const parts = members.map((k) => boxData.get(k));
|
|
235
|
+
const total = parts.reduce((s, d) => s + d.mesh.positions.length / 3, 0);
|
|
236
|
+
const merged = {
|
|
237
|
+
positions: new Float32Array(total * 3), normals: new Float32Array(total * 3), uvs: new Float32Array(total * 2),
|
|
238
|
+
facade: new Uint16Array(total * 4), colors: new Uint8Array(total * 4),
|
|
239
|
+
indices: new Uint32Array(parts.reduce((s, d) => s + d.mesh.indices.length, 0)), sources: new Uint16Array(total),
|
|
240
|
+
};
|
|
241
|
+
let v = 0;
|
|
242
|
+
let t = 0;
|
|
243
|
+
parts.forEach((d, source) => {
|
|
244
|
+
const n = d.mesh.positions.length / 3;
|
|
245
|
+
for (let i = 0; i < n; i += 1) {
|
|
246
|
+
merged.positions[(v + i) * 3] = d.mesh.positions[i * 3] + d.origin[0] - origin[0];
|
|
247
|
+
merged.positions[(v + i) * 3 + 1] = d.mesh.positions[i * 3 + 1] - origin[1];
|
|
248
|
+
merged.positions[(v + i) * 3 + 2] = d.mesh.positions[i * 3 + 2] + d.origin[1] - origin[2];
|
|
249
|
+
merged.sources[v + i] = source;
|
|
250
|
+
}
|
|
251
|
+
merged.normals.set(d.mesh.normals, v * 3);
|
|
252
|
+
merged.uvs.set(d.mesh.uvs, v * 2);
|
|
253
|
+
merged.facade.set(d.mesh.facade, v * 4);
|
|
254
|
+
merged.colors.set(d.mesh.colors, v * 4);
|
|
255
|
+
for (let i = 0; i < d.mesh.indices.length; i += 1)
|
|
256
|
+
merged.indices[t + i] = d.mesh.indices[i] + v;
|
|
257
|
+
v += n;
|
|
258
|
+
t += d.mesh.indices.length;
|
|
259
|
+
});
|
|
260
|
+
const tEnc = performance.now();
|
|
261
|
+
const glb = await (0, glb_1.encodeBuildingGlb)(merged, `buildings far ${ck}`, { cluster: [fx, fz], origin, generator: exports.BUILDINGS_GENERATOR_VERSION, level: 'far' });
|
|
262
|
+
timings.encodeMs += performance.now() - tEnc;
|
|
263
|
+
const tWrite = performance.now();
|
|
264
|
+
const ref = await store(out, 'building-far', 'glb', glb.bytes, dryRun);
|
|
265
|
+
timings.writeMs += performance.now() - tWrite;
|
|
266
|
+
const min = [Infinity, Infinity, Infinity];
|
|
267
|
+
const max = [-Infinity, -Infinity, -Infinity];
|
|
268
|
+
for (let i = 0; i < total; i += 1) {
|
|
269
|
+
for (let a = 0; a < 3; a += 1) {
|
|
270
|
+
const value = merged.positions[i * 3 + a] + origin[a];
|
|
271
|
+
if (value < min[a])
|
|
272
|
+
min[a] = value;
|
|
273
|
+
if (value > max[a])
|
|
274
|
+
max[a] = value;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
far.push({
|
|
278
|
+
...ref, key: ck, ix: fx, iz: fz, origin, bounds: { min: min.map(source_1.roundMm), max: max.map(source_1.roundMm) },
|
|
279
|
+
cells: members, triangles: glb.triangles, buildings: parts.reduce((s, d) => s + d.buildings, 0), quantizationErrorM: Number(glb.quantizationErrorM.toFixed(4)),
|
|
280
|
+
});
|
|
281
|
+
totals.farTriangles += glb.triangles;
|
|
282
|
+
totals.farBytes += ref.bytes;
|
|
283
|
+
}
|
|
284
|
+
const manifest = {
|
|
285
|
+
schema: exports.BUILDINGS_MANIFEST_SCHEMA,
|
|
286
|
+
generator: { name: 'helix-city-buildings', version: exports.BUILDINGS_GENERATOR_VERSION },
|
|
287
|
+
source: { id: source.manifest.id, manifestSha256 },
|
|
288
|
+
options: { cellM, farCellM, groundFilter: ground.filter, groundKind: ground.kind },
|
|
289
|
+
boundsXZ: source.manifest.frame.boundsXZ,
|
|
290
|
+
cells,
|
|
291
|
+
far,
|
|
292
|
+
meshBuildings,
|
|
293
|
+
totals,
|
|
294
|
+
stats,
|
|
295
|
+
};
|
|
296
|
+
const manifestBytes = Buffer.from((0, source_1.prettyCanonicalJson)(manifest), 'utf8');
|
|
297
|
+
if (!dryRun) {
|
|
298
|
+
await (0, promises_1.mkdir)(out, { recursive: true });
|
|
299
|
+
await (0, promises_1.writeFile)((0, node_path_1.join)(out, exports.BUILDINGS_MANIFEST_FILE), manifestBytes);
|
|
300
|
+
}
|
|
301
|
+
timings.totalMs = performance.now() - t0;
|
|
302
|
+
return { manifest, manifestSha256: (0, source_1.sha256Hex)(manifestBytes), timings, out };
|
|
303
|
+
}
|
|
304
|
+
//# sourceMappingURL=build.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build.js","sourceRoot":"","sources":["../../../src/city/buildings/build.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { CELL_INDEX_SCHEMA } from './build';
|
|
2
|
+
export interface DecodedMesh {
|
|
3
|
+
/** Cell-local (or cluster-local for the far layer) metres, node transform applied. */
|
|
4
|
+
positions: Float32Array;
|
|
5
|
+
normals: Float32Array;
|
|
6
|
+
indices: Uint32Array;
|
|
7
|
+
facade?: Uint16Array;
|
|
8
|
+
colors?: Uint8Array;
|
|
9
|
+
sources?: Uint16Array;
|
|
10
|
+
extensionsUsed: string[];
|
|
11
|
+
hasCityMaterialExtension: boolean;
|
|
12
|
+
}
|
|
13
|
+
export declare function decodeBuildingGlb(bytes: Uint8Array): Promise<DecodedMesh>;
|
|
14
|
+
export interface CellIndex {
|
|
15
|
+
schema: typeof CELL_INDEX_SCHEMA;
|
|
16
|
+
cell: [number, number];
|
|
17
|
+
ids: string[];
|
|
18
|
+
near: number[];
|
|
19
|
+
box: number[];
|
|
20
|
+
levels: number[];
|
|
21
|
+
heightM: number[];
|
|
22
|
+
use: string[];
|
|
23
|
+
repr: string;
|
|
24
|
+
family: string[];
|
|
25
|
+
}
|
|
26
|
+
export interface TriangleRange {
|
|
27
|
+
start: number;
|
|
28
|
+
count: number;
|
|
29
|
+
}
|
|
30
|
+
/** Closed-surface and winding facts of one building's triangles. */
|
|
31
|
+
export declare function surfaceFacts(mesh: DecodedMesh, range: TriangleRange): {
|
|
32
|
+
boundaryAboveBase: number;
|
|
33
|
+
boundaryTotal: number;
|
|
34
|
+
inverted: number;
|
|
35
|
+
degenerate: number;
|
|
36
|
+
minY: number;
|
|
37
|
+
};
|
|
38
|
+
export interface CheckReport {
|
|
39
|
+
buildings: number;
|
|
40
|
+
/** Source buildings that produced a mass at all. */
|
|
41
|
+
planned: number;
|
|
42
|
+
/** Planned buildings whose footprint is >= 85% covered by upward-facing generated triangles, box level. */
|
|
43
|
+
presentBox: number;
|
|
44
|
+
/** The same, near level (mesh buildings excluded). */
|
|
45
|
+
presentNear: number;
|
|
46
|
+
nearChecked: number;
|
|
47
|
+
presentPct: number;
|
|
48
|
+
missing: string[];
|
|
49
|
+
hollow: string[];
|
|
50
|
+
invertedBuildings: string[];
|
|
51
|
+
degenerateTriangles: number;
|
|
52
|
+
far: {
|
|
53
|
+
clusters: number;
|
|
54
|
+
cellsCovered: number;
|
|
55
|
+
cellsTotal: number;
|
|
56
|
+
triangles: number;
|
|
57
|
+
ok: boolean;
|
|
58
|
+
problems: string[];
|
|
59
|
+
};
|
|
60
|
+
manifestOk: boolean;
|
|
61
|
+
problems: string[];
|
|
62
|
+
}
|
|
63
|
+
export declare function checkBuildings(sourceDir: string, outDir: string): Promise<CheckReport>;
|
|
64
|
+
export declare function formatCheck(report: CheckReport): string;
|