@adatechnology/game-floorplan-three 0.9.0 → 0.9.2
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/index.global.js +245 -166
- package/dist/index.global.js.map +1 -1
- package/package.json +15 -15
package/dist/index.global.js
CHANGED
|
@@ -70,7 +70,7 @@ var GameFloorplanThree = (() => {
|
|
|
70
70
|
shade: () => shade
|
|
71
71
|
});
|
|
72
72
|
|
|
73
|
-
// ../game-shapes/dist/chunk-
|
|
73
|
+
// ../game-shapes/dist/chunk-M5N2SHNL.js
|
|
74
74
|
function canonicalJson(value) {
|
|
75
75
|
if (value === null) return "null";
|
|
76
76
|
if (typeof value === "number") return Object.is(value, -0) ? "-0" : Number.isFinite(value) ? String(value) : JSON.stringify(String(value));
|
|
@@ -1227,13 +1227,13 @@ var GameFloorplanThree = (() => {
|
|
|
1227
1227
|
uvArray.push(x);
|
|
1228
1228
|
uvArray.push(y);
|
|
1229
1229
|
};
|
|
1230
|
-
const
|
|
1230
|
+
const at2 = (index, axis) => verticesArray[index * 3 + axis];
|
|
1231
1231
|
const f3 = (a, b, c) => {
|
|
1232
1232
|
addVertex(a);
|
|
1233
1233
|
addVertex(b);
|
|
1234
1234
|
addVertex(c);
|
|
1235
1235
|
const nextIndex = verticesArray.length / 3;
|
|
1236
|
-
for (const index of [nextIndex - 3, nextIndex - 2, nextIndex - 1]) addUV(
|
|
1236
|
+
for (const index of [nextIndex - 3, nextIndex - 2, nextIndex - 1]) addUV(at2(index, 0), at2(index, 1));
|
|
1237
1237
|
};
|
|
1238
1238
|
const f4 = (a, b, c, d) => {
|
|
1239
1239
|
addVertex(a);
|
|
@@ -1247,8 +1247,8 @@ var GameFloorplanThree = (() => {
|
|
|
1247
1247
|
const iB = nextIndex - 3;
|
|
1248
1248
|
const iC = nextIndex - 2;
|
|
1249
1249
|
const iD = nextIndex - 1;
|
|
1250
|
-
const byX = Math.abs(
|
|
1251
|
-
const uv = (index) => [byX ?
|
|
1250
|
+
const byX = Math.abs(at2(iA, 1) - at2(iB, 1)) < Math.abs(at2(iA, 0) - at2(iB, 0));
|
|
1251
|
+
const uv = (index) => [byX ? at2(index, 0) : at2(index, 1), 1 - at2(index, 2)];
|
|
1252
1252
|
const uvs = [uv(iA), uv(iB), uv(iC), uv(iD)];
|
|
1253
1253
|
for (const k of [0, 1, 3, 1, 2, 3]) addUV(...uvs[k]);
|
|
1254
1254
|
};
|
|
@@ -1353,8 +1353,8 @@ var GameFloorplanThree = (() => {
|
|
|
1353
1353
|
groups: []
|
|
1354
1354
|
};
|
|
1355
1355
|
}
|
|
1356
|
-
function make(
|
|
1357
|
-
switch (kind) {
|
|
1356
|
+
function make(p) {
|
|
1357
|
+
switch (p.kind) {
|
|
1358
1358
|
case "box": {
|
|
1359
1359
|
const size = p.size ?? [1, 1, 1];
|
|
1360
1360
|
const segments = p.segments ?? [1, 1, 1];
|
|
@@ -1383,7 +1383,7 @@ var GameFloorplanThree = (() => {
|
|
|
1383
1383
|
case "mesh":
|
|
1384
1384
|
return mesh(p);
|
|
1385
1385
|
default:
|
|
1386
|
-
throw new Error(`game-shapes: unknown primitive kind "${String(kind)}"`);
|
|
1386
|
+
throw new Error(`game-shapes: unknown primitive kind "${String(p.kind)}"`);
|
|
1387
1387
|
}
|
|
1388
1388
|
}
|
|
1389
1389
|
var templates = /* @__PURE__ */ new Map();
|
|
@@ -1391,7 +1391,7 @@ var GameFloorplanThree = (() => {
|
|
|
1391
1391
|
var stats = { hits: 0, misses: 0 };
|
|
1392
1392
|
function buildPrimitive(node, options = {}) {
|
|
1393
1393
|
const parameters = primitiveParameters(node, options);
|
|
1394
|
-
if (node.kind === "mesh" || templateLimit === 0) return make(node
|
|
1394
|
+
if (node.kind === "mesh" || templateLimit === 0) return make({ ...node, ...parameters });
|
|
1395
1395
|
const key = `${node.kind}:${canonicalJson(parameters)}`;
|
|
1396
1396
|
const cached = templates.get(key);
|
|
1397
1397
|
if (cached) {
|
|
@@ -1401,7 +1401,7 @@ var GameFloorplanThree = (() => {
|
|
|
1401
1401
|
return cached;
|
|
1402
1402
|
}
|
|
1403
1403
|
stats.misses++;
|
|
1404
|
-
const built = make(node
|
|
1404
|
+
const built = make({ ...node, ...parameters });
|
|
1405
1405
|
templates.set(key, built);
|
|
1406
1406
|
if (templates.size > templateLimit) templates.delete(templates.keys().next().value);
|
|
1407
1407
|
return built;
|
|
@@ -1499,7 +1499,7 @@ var GameFloorplanThree = (() => {
|
|
|
1499
1499
|
const positions2 = new Float32Array(total * 3);
|
|
1500
1500
|
const normals = new Float32Array(total * 3);
|
|
1501
1501
|
const uvs = new Float32Array(total * 2);
|
|
1502
|
-
let
|
|
1502
|
+
let at2 = 0;
|
|
1503
1503
|
for (const piece2 of pieces) {
|
|
1504
1504
|
const e = piece2.matrix;
|
|
1505
1505
|
const nm = normalMatrix(e);
|
|
@@ -1513,15 +1513,15 @@ var GameFloorplanThree = (() => {
|
|
|
1513
1513
|
if (piece2.normals) n[k * 3 + c] = piece2.normals[i * 3 + c];
|
|
1514
1514
|
}
|
|
1515
1515
|
if (piece2.uvs) {
|
|
1516
|
-
uvs[(
|
|
1517
|
-
uvs[(
|
|
1516
|
+
uvs[(at2 + k) * 2] = piece2.uvs[i * 2];
|
|
1517
|
+
uvs[(at2 + k) * 2 + 1] = piece2.uvs[i * 2 + 1];
|
|
1518
1518
|
}
|
|
1519
1519
|
}
|
|
1520
1520
|
for (let k = 0; k < count; k++) {
|
|
1521
1521
|
const q = transformPoint(e, p[k * 3], p[k * 3 + 1], p[k * 3 + 2]);
|
|
1522
|
-
positions2[(
|
|
1523
|
-
positions2[(
|
|
1524
|
-
positions2[(
|
|
1522
|
+
positions2[(at2 + k) * 3] = q[0];
|
|
1523
|
+
positions2[(at2 + k) * 3 + 1] = q[1];
|
|
1524
|
+
positions2[(at2 + k) * 3 + 2] = q[2];
|
|
1525
1525
|
const x = n[k * 3];
|
|
1526
1526
|
const y = n[k * 3 + 1];
|
|
1527
1527
|
const z = n[k * 3 + 2];
|
|
@@ -1529,16 +1529,17 @@ var GameFloorplanThree = (() => {
|
|
|
1529
1529
|
const vy = nm[1] * x + nm[4] * y + nm[7] * z;
|
|
1530
1530
|
const vz = nm[2] * x + nm[5] * y + nm[8] * z;
|
|
1531
1531
|
const s = 1 / (Math.sqrt(vx * vx + vy * vy + vz * vz) || 1);
|
|
1532
|
-
normals[(
|
|
1533
|
-
normals[(
|
|
1534
|
-
normals[(
|
|
1532
|
+
normals[(at2 + k) * 3] = vx * s;
|
|
1533
|
+
normals[(at2 + k) * 3 + 1] = vy * s;
|
|
1534
|
+
normals[(at2 + k) * 3 + 2] = vz * s;
|
|
1535
1535
|
}
|
|
1536
|
-
|
|
1536
|
+
at2 += count;
|
|
1537
1537
|
}
|
|
1538
1538
|
return { positions: positions2, normals, uvs };
|
|
1539
1539
|
}
|
|
1540
1540
|
|
|
1541
1541
|
// ../game-contracts/dist/index.js
|
|
1542
|
+
var DEFAULT_BLAST_IMPULSE = { bodyArea: 0.7, lift: 0.15, minSpeed: 0.3, tntPerJoule: 0.24 / 2e5 };
|
|
1542
1543
|
var DEFAULT_COST_ALLOCATION_BYTES = 1024 * 1024;
|
|
1543
1544
|
var DEFAULT_IGNITION_RULES = {
|
|
1544
1545
|
fillCurve: [
|
|
@@ -3408,17 +3409,17 @@ var GameFloorplanThree = (() => {
|
|
|
3408
3409
|
const index = geometry2.index ? geometry2.index.array : null;
|
|
3409
3410
|
const count = index ? index.length : position.count;
|
|
3410
3411
|
for (let item = 0; item < count; item++) {
|
|
3411
|
-
const
|
|
3412
|
-
vertex.fromBufferAttribute(position,
|
|
3412
|
+
const at2 = index ? index[item] : item;
|
|
3413
|
+
vertex.fromBufferAttribute(position, at2).applyMatrix4(matrix);
|
|
3413
3414
|
positions2.push(vertex.x, vertex.y, vertex.z);
|
|
3414
|
-
if (normalAttribute) normal.fromBufferAttribute(normalAttribute,
|
|
3415
|
+
if (normalAttribute) normal.fromBufferAttribute(normalAttribute, at2).applyMatrix3(normalMatrix2).normalize();
|
|
3415
3416
|
else normal.set(0, 1, 0);
|
|
3416
3417
|
normals.push(normal.x, normal.y, normal.z);
|
|
3417
3418
|
color2.copy(material2.color || color2.set(1, 1, 1)).convertLinearToSRGB();
|
|
3418
3419
|
if (sample && uv && material2.map) {
|
|
3419
3420
|
const repeat = material2.map.repeat;
|
|
3420
|
-
const u = (uv.getX(
|
|
3421
|
-
const v = (uv.getY(
|
|
3421
|
+
const u = (uv.getX(at2) * repeat.x % 1 + 1) % 1;
|
|
3422
|
+
const v = (uv.getY(at2) * repeat.y % 1 + 1) % 1;
|
|
3422
3423
|
const pixelX = Math.min(sample.width - 1, u * sample.width | 0);
|
|
3423
3424
|
const pixelY = Math.min(sample.height - 1, (1 - v) * sample.height | 0);
|
|
3424
3425
|
const offset = (pixelY * sample.width + pixelX) * 4;
|
|
@@ -9871,8 +9872,10 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
9871
9872
|
// was `maquina`
|
|
9872
9873
|
});
|
|
9873
9874
|
var OWN_TYPES = Object.freeze({ lamp: true, gas_piped: true });
|
|
9875
|
+
var sourceOf = (result) => result;
|
|
9874
9876
|
var ADAPTER_VERSION = "0.3.0";
|
|
9875
9877
|
var r3 = (n) => Math.round(n * 1e3) / 1e3;
|
|
9878
|
+
var at = (it) => ({ x: it.x ?? 0, z: it.z ?? 0, ry: it.ry ?? 0 });
|
|
9876
9879
|
function mergeRegistry(base, extra) {
|
|
9877
9880
|
const out = { ...base };
|
|
9878
9881
|
if (extra) {
|
|
@@ -9891,14 +9894,15 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
9891
9894
|
});
|
|
9892
9895
|
function create2(options = {}) {
|
|
9893
9896
|
const opts = options || {};
|
|
9894
|
-
const GI = opts.GameInteractables;
|
|
9895
|
-
const HH = opts.GameInteractablesHousehold;
|
|
9896
9897
|
const locale = opts.locale || "pt-BR";
|
|
9897
9898
|
const msg = createTranslator2(locale, opts.messages);
|
|
9898
|
-
if (!
|
|
9899
|
+
if (!opts.GameInteractables || !opts.GameInteractablesHousehold) throw new Error(msg("error.missingKit"));
|
|
9900
|
+
const GI = opts.GameInteractables;
|
|
9901
|
+
const HH = opts.GameInteractablesHousehold;
|
|
9899
9902
|
const region = opts.region || "br";
|
|
9900
9903
|
const hh = HH.createHousehold({ locale, region });
|
|
9901
9904
|
const householdTypes = new Set(hh.types.map((t) => t.id));
|
|
9905
|
+
const recorderApi = () => HH.createRecorder().api;
|
|
9902
9906
|
const worlds = /* @__PURE__ */ new WeakMap();
|
|
9903
9907
|
const typeMap = mergeRegistry(TYPE_MAP, opts.typeMap);
|
|
9904
9908
|
const contentMap = mergeRegistry(CONTENT_MAP, opts.contentMap);
|
|
@@ -9934,7 +9938,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
9934
9938
|
function colorOf(res, color2) {
|
|
9935
9939
|
if (color2 == null) return void 0;
|
|
9936
9940
|
if (typeof color2 === "number") return color2;
|
|
9937
|
-
const v = res.colors && res.colors[color2];
|
|
9941
|
+
const v = res.colors && res.colors[String(color2)];
|
|
9938
9942
|
return typeof v === "number" ? v : void 0;
|
|
9939
9943
|
}
|
|
9940
9944
|
function paletteOf(res) {
|
|
@@ -9963,17 +9967,18 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
9963
9967
|
drawerItem: (s) => drawerItems.has(s.itemId)
|
|
9964
9968
|
};
|
|
9965
9969
|
const itemOfContent = (c) => {
|
|
9966
|
-
const
|
|
9970
|
+
const group = stackGroup(c);
|
|
9971
|
+
const id = contentMap[c.itemId] || (hh.items[c.itemId] ? c.itemId : null) || (group != null ? contentByGroup[group] : void 0) || contentFallback;
|
|
9967
9972
|
return hh.items[id] ? id : contentFallback;
|
|
9968
9973
|
};
|
|
9969
9974
|
const volume = (d) => d.size[0] * d.size[1] * d.size[2];
|
|
9970
9975
|
const candidates = (id, objectType) => {
|
|
9971
9976
|
const def = hh.items[id];
|
|
9972
|
-
const siblings = Object.values(hh.items).filter((i) => i.category === def
|
|
9977
|
+
const siblings = Object.values(hh.items).filter((i) => i.category === def?.category && i.id !== id).sort((a, b) => volume(a) - volume(b) || (a.id < b.id ? -1 : 1));
|
|
9973
9978
|
return [id].concat(siblings.map((i) => i.id), substitutes[objectType] || []);
|
|
9974
9979
|
};
|
|
9975
9980
|
function distribute(type, probeItem, stacks) {
|
|
9976
|
-
const spec = hh.build(type, probeItem,
|
|
9981
|
+
const spec = hh.build(type, probeItem, recorderApi());
|
|
9977
9982
|
const conts = spec.containers || [];
|
|
9978
9983
|
const contents = {};
|
|
9979
9984
|
for (const c of conts) contents[c.id] = c.slots.map(() => null);
|
|
@@ -10004,8 +10009,9 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
10004
10009
|
}
|
|
10005
10010
|
return { contents, rejected };
|
|
10006
10011
|
}
|
|
10007
|
-
function plan(
|
|
10008
|
-
|
|
10012
|
+
function plan(source, options2 = {}) {
|
|
10013
|
+
const res = sourceOf(source);
|
|
10014
|
+
const popts = options2 || {};
|
|
10009
10015
|
const o = { ox: popts.originX || 0, oz: popts.originZ || 0, inw: popts.inw || 1, base: popts.base || 0 };
|
|
10010
10016
|
const K = conv(o);
|
|
10011
10017
|
const floorSel = popts.floor;
|
|
@@ -10069,7 +10075,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
10069
10075
|
const item = {
|
|
10070
10076
|
x: K.x(m.x),
|
|
10071
10077
|
z: K.z(m.z),
|
|
10072
|
-
ry: m.frontU != null ? K.ry(m.frontU, m.frontV) : r3(m.ry || 0),
|
|
10078
|
+
ry: m.frontU != null ? K.ry(m.frontU, m.frontV ?? 0) : r3(m.ry || 0),
|
|
10073
10079
|
w: m.w,
|
|
10074
10080
|
d: m.d,
|
|
10075
10081
|
h: m.h,
|
|
@@ -10082,7 +10088,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
10082
10088
|
return item;
|
|
10083
10089
|
}
|
|
10084
10090
|
function entry2(id, type, item, origin, floor, extra) {
|
|
10085
|
-
|
|
10091
|
+
const e = { id, type, item, origin, floor, floorY: floorYOf(res, o, floor), connections: {} };
|
|
10092
|
+
return Object.assign(e, extra || {});
|
|
10086
10093
|
}
|
|
10087
10094
|
function store(targets, stacks) {
|
|
10088
10095
|
let rest2 = stacks || [];
|
|
@@ -10095,10 +10102,11 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
10095
10102
|
}
|
|
10096
10103
|
const hidden = [];
|
|
10097
10104
|
function distRect(c, x, z) {
|
|
10098
|
-
const
|
|
10099
|
-
const
|
|
10100
|
-
const
|
|
10101
|
-
const
|
|
10105
|
+
const ci = at(c.item);
|
|
10106
|
+
const dx = x - ci.x;
|
|
10107
|
+
const dz = z - ci.z;
|
|
10108
|
+
const s = Math.sin(ci.ry);
|
|
10109
|
+
const co = Math.cos(ci.ry);
|
|
10102
10110
|
const lx = dx * co - dz * s;
|
|
10103
10111
|
const lz = dx * s + dz * co;
|
|
10104
10112
|
return Math.hypot(Math.max(Math.abs(lx) - (c.item.w || 0) / 2, 0), Math.max(Math.abs(lz) - (c.item.d || 0) / 2, 0));
|
|
@@ -10106,9 +10114,10 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
10106
10114
|
function hideCylinders() {
|
|
10107
10115
|
for (const b of hidden) {
|
|
10108
10116
|
let target = null;
|
|
10117
|
+
const bi = at(b.item);
|
|
10109
10118
|
for (const c2 of result.items) {
|
|
10110
10119
|
if (c2.type !== "kitchen_cabinet_base" || c2.floor !== b.floor) continue;
|
|
10111
|
-
const dist = distRect(c2,
|
|
10120
|
+
const dist = distRect(c2, bi.x, bi.z);
|
|
10112
10121
|
if (!target || dist < target.dist) target = { c: c2, dist };
|
|
10113
10122
|
}
|
|
10114
10123
|
if (!target) {
|
|
@@ -10116,16 +10125,18 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
10116
10125
|
continue;
|
|
10117
10126
|
}
|
|
10118
10127
|
const c = target.c;
|
|
10119
|
-
const spec = hh.build(c.type, c.item,
|
|
10120
|
-
const
|
|
10121
|
-
const
|
|
10128
|
+
const spec = hh.build(c.type, c.item, recorderApi());
|
|
10129
|
+
const ci = at(c.item);
|
|
10130
|
+
const sn = Math.sin(ci.ry);
|
|
10131
|
+
const cs = Math.cos(ci.ry);
|
|
10122
10132
|
let door = null;
|
|
10123
10133
|
for (const it of spec.interactions || []) {
|
|
10124
|
-
const
|
|
10125
|
-
|
|
10126
|
-
|
|
10127
|
-
const
|
|
10128
|
-
const
|
|
10134
|
+
const action = it.action;
|
|
10135
|
+
const pt = action.do === "toggle_part" ? (spec.parts || []).find((q) => q.id === action.part) : null;
|
|
10136
|
+
if (!pt || !pt.motion || pt.motion.kind !== "hinge") continue;
|
|
10137
|
+
const wx = ci.x + it.pos[0] * cs + it.pos[2] * sn;
|
|
10138
|
+
const wz = ci.z - it.pos[0] * sn + it.pos[2] * cs;
|
|
10139
|
+
const dist = Math.hypot(wx - bi.x, wz - bi.z);
|
|
10129
10140
|
if (!door || dist < door.dist) door = { id: pt.id, dist };
|
|
10130
10141
|
}
|
|
10131
10142
|
if (!door) {
|
|
@@ -10155,9 +10166,10 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
10155
10166
|
const campCylinder = firstOfType("gas_canister");
|
|
10156
10167
|
function planFireplace(m, e, item) {
|
|
10157
10168
|
const def = hh.types.find((t) => t.id === "fireplace");
|
|
10158
|
-
const lack = (def.d - m.d) / 2;
|
|
10159
|
-
|
|
10160
|
-
item.
|
|
10169
|
+
const lack = ((def ? def.d : m.d) - m.d) / 2;
|
|
10170
|
+
const p = at(item);
|
|
10171
|
+
item.x = r3(p.x + Math.sin(p.ry) * lack);
|
|
10172
|
+
item.z = r3(p.z + Math.cos(p.ry) * lack);
|
|
10161
10173
|
const room = (res.rooms || []).find((c) => c.id === m.room && c.floor === m.floor);
|
|
10162
10174
|
const f = (res.floors || []).find((x) => x.index === m.floor);
|
|
10163
10175
|
item.h = r3(room && room.ceiling || f && f.ceiling || 2.6);
|
|
@@ -10185,7 +10197,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
10185
10197
|
e.connections.gas = m.gas || "cylinder";
|
|
10186
10198
|
e.connections.cylinder = m.cylinder || null;
|
|
10187
10199
|
}
|
|
10188
|
-
if (map.type === "gas_bottle") result.cylinders.push({ id: e.id, stove: m.link
|
|
10200
|
+
if (map.type === "gas_bottle") result.cylinders.push({ id: e.id, stove: typeof m.link === "string" ? m.link : null, place: m.placement || null });
|
|
10189
10201
|
if (map.type === "gas_canister") {
|
|
10190
10202
|
result.canisters.push(e.id);
|
|
10191
10203
|
if (campCylinder && campCylinder.id === m.id && campStove) result.cylinders.push({ id: e.id, stove: campStove.id, place: null });
|
|
@@ -10209,7 +10221,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
10209
10221
|
push(e);
|
|
10210
10222
|
}
|
|
10211
10223
|
function planCompound(m, kind) {
|
|
10212
|
-
const ry = m.frontU != null ? K.ry(m.frontU, m.frontV) : r3(m.ry || 0);
|
|
10224
|
+
const ry = m.frontU != null ? K.ry(m.frontU, m.frontV ?? 0) : r3(m.ry || 0);
|
|
10213
10225
|
const cx = K.x(m.x);
|
|
10214
10226
|
const cz = K.z(m.z);
|
|
10215
10227
|
const part = (id, type, w, d, h, y, lx, lz) => {
|
|
@@ -10261,11 +10273,12 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
10261
10273
|
} else {
|
|
10262
10274
|
const basin = part(m.id, "sink_bathroom", m.w, m.d, m.h + 0.2, 0, 0, 0);
|
|
10263
10275
|
list2.push(basin);
|
|
10264
|
-
|
|
10265
|
-
|
|
10276
|
+
const own = contents[m.id];
|
|
10277
|
+
if (own) {
|
|
10278
|
+
if (own.length) {
|
|
10266
10279
|
const cabinet = part(m.id + "#cabinet", "bathroom_cabinet", Math.max(0.45, Math.min(0.6, m.w)), 0.15, 0.75, 1.3, 0, -(m.d / 2) + 0.075);
|
|
10267
10280
|
list2.push(cabinet);
|
|
10268
|
-
store([["bathroom_cabinet", cabinet.item], ["sink_bathroom", basin.item]],
|
|
10281
|
+
store([["bathroom_cabinet", cabinet.item], ["sink_bathroom", basin.item]], own);
|
|
10269
10282
|
} else {
|
|
10270
10283
|
store([["sink_bathroom", basin.item]], []);
|
|
10271
10284
|
}
|
|
@@ -10305,7 +10318,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
10305
10318
|
result.chairs = [];
|
|
10306
10319
|
if (opts.chairs !== false && popts.chairs !== false) {
|
|
10307
10320
|
const blocked = blockedOf(res, { originX: o.ox, originZ: o.oz, inw: o.inw });
|
|
10308
|
-
const floorKind = (q) => !q.decor && !q.flat && (q.y || 0) < 0.9 && q.aabb;
|
|
10321
|
+
const floorKind = (q) => !q.decor && !q.flat && (q.y || 0) < 0.9 && !!q.aabb;
|
|
10309
10322
|
const placed = [];
|
|
10310
10323
|
const free = (m, cu, cv, half) => {
|
|
10311
10324
|
const a = [cu - half + 0.03, cv - half + 0.03, cu + half - 0.03, cv + half - 0.03];
|
|
@@ -10321,8 +10334,9 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
10321
10334
|
for (const m of res.items || []) {
|
|
10322
10335
|
const mode = chairTables[m.type];
|
|
10323
10336
|
if (!mode || !onFloor(m.floor, m.outdoor) || m.frontU == null) continue;
|
|
10324
|
-
const
|
|
10325
|
-
const
|
|
10337
|
+
const fv = m.frontV ?? 0;
|
|
10338
|
+
const f = [m.frontU, fv];
|
|
10339
|
+
const pp = [-fv, m.frontU];
|
|
10326
10340
|
const seats = [];
|
|
10327
10341
|
if (mode === "dining") {
|
|
10328
10342
|
const n = Math.max(1, Math.min(3, Math.floor((m.w - 0.1) / 0.55)));
|
|
@@ -10391,8 +10405,9 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
10391
10405
|
const item = { x: K.x(s.u), z: K.z(s.v), ry: K.ry(s.frontU, s.frontV), y: s.y, seed: seedOf2(s.id) };
|
|
10392
10406
|
item.controls = (s.controls || []).map((id) => id + ":lamp");
|
|
10393
10407
|
const e = entry2(s.id, "wall_switch", item, s.id, s.floor);
|
|
10394
|
-
|
|
10395
|
-
e.
|
|
10408
|
+
const controls = (s.controls || []).slice();
|
|
10409
|
+
e.connections.controls = controls;
|
|
10410
|
+
e.lit = controls.some((id) => result.items.find((x) => x.id === id)?.lit === true);
|
|
10396
10411
|
if (floorSel == null) {
|
|
10397
10412
|
for (const id of s.controls || []) if (!lights.has(id)) result.warnings.push(msg("warn.switchUnknownLamp", { id: s.id, lamp: id }));
|
|
10398
10413
|
}
|
|
@@ -10432,7 +10447,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
10432
10447
|
seed: seedOf2("panel"),
|
|
10433
10448
|
circuits: circuits.map((c) => ({ id: c.id, label: c.room }))
|
|
10434
10449
|
};
|
|
10435
|
-
if (!item.circuits
|
|
10450
|
+
if (!item.circuits?.length) delete item.circuits;
|
|
10436
10451
|
const e = entry2("panel", "electrical_panel", item, "panel", q.floor);
|
|
10437
10452
|
push(e);
|
|
10438
10453
|
result.panel = e.id;
|
|
@@ -10454,10 +10469,11 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
10454
10469
|
}
|
|
10455
10470
|
}
|
|
10456
10471
|
const piped = result.items.filter((e) => e.type === "stove" && e.connections.gas === "piped");
|
|
10457
|
-
|
|
10472
|
+
const firstPiped = piped[0];
|
|
10473
|
+
if (firstPiped) {
|
|
10458
10474
|
const med = utilities.gas && utilities.gas.meter;
|
|
10459
|
-
const ref = med ? { x: K.x(med.u), z: K.z(med.v), y: med.y || 1 } : { x:
|
|
10460
|
-
const e = entry2("piped_gas", "gas_piped", { x: ref.x, z: ref.z, ry: 0, y: ref.y, seed: seedOf2("piped_gas") }, "piped_gas",
|
|
10475
|
+
const ref = med ? { x: K.x(med.u), z: K.z(med.v), y: med.y || 1 } : { x: firstPiped.item.x, z: firstPiped.item.z, y: 0.3 };
|
|
10476
|
+
const e = entry2("piped_gas", "gas_piped", { x: ref.x, z: ref.z, ry: 0, y: ref.y, seed: seedOf2("piped_gas") }, "piped_gas", firstPiped.floor);
|
|
10461
10477
|
e.floorY = o.base;
|
|
10462
10478
|
push(e);
|
|
10463
10479
|
for (const f of piped) f.connections.fuel = "piped_gas:gas";
|
|
@@ -10504,9 +10520,10 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
10504
10520
|
for (const dv of spec.devices || []) if (L.outlet && dv.socket === "auto") dv.socket = L.outlet + ":socket";
|
|
10505
10521
|
} else {
|
|
10506
10522
|
const sh = L.shower || {};
|
|
10507
|
-
const
|
|
10523
|
+
const devices = spec.devices || [];
|
|
10524
|
+
const heater = devices.find((d) => d.id === "heater");
|
|
10508
10525
|
if (heater && sh.electric === false) {
|
|
10509
|
-
spec.devices =
|
|
10526
|
+
spec.devices = devices.filter((d) => d !== heater);
|
|
10510
10527
|
for (const f of spec.fixtures || []) if (f.heater === "heater") delete f.heater;
|
|
10511
10528
|
} else if (heater) {
|
|
10512
10529
|
if (sh.powerW) heater.watts = sh.powerW;
|
|
@@ -10517,7 +10534,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
10517
10534
|
for (const b of spec.burners || []) if (b.fuel === "auto") b.fuel = L.fuel;
|
|
10518
10535
|
}
|
|
10519
10536
|
if (entry2.type === "fireplace" && L.chimneyTop) {
|
|
10520
|
-
const it = entry2.item;
|
|
10537
|
+
const it = at(entry2.item);
|
|
10521
10538
|
const dx = L.chimneyTop[0] - it.x;
|
|
10522
10539
|
const dz = L.chimneyTop[2] - it.z;
|
|
10523
10540
|
const lx = Math.cos(it.ry) * dx - Math.sin(it.ry) * dz;
|
|
@@ -10536,8 +10553,9 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
10536
10553
|
}
|
|
10537
10554
|
return spec;
|
|
10538
10555
|
}
|
|
10539
|
-
function createWorld(
|
|
10540
|
-
|
|
10556
|
+
function createWorld(source, options2 = {}) {
|
|
10557
|
+
const res = sourceOf(source);
|
|
10558
|
+
const copts = options2 || {};
|
|
10541
10559
|
const info = { points: /* @__PURE__ */ new Map(), water: copts.water || null, lightsOn: copts.lightsOn };
|
|
10542
10560
|
const electrical = res.utilities && res.utilities.electrical;
|
|
10543
10561
|
const world = GI.createWorld({
|
|
@@ -10565,8 +10583,9 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
10565
10583
|
const info = worlds.get(world);
|
|
10566
10584
|
return info ? info.points.get(fixtureId) : void 0;
|
|
10567
10585
|
}
|
|
10568
|
-
function blockedOf(
|
|
10569
|
-
|
|
10586
|
+
function blockedOf(source, options2 = {}) {
|
|
10587
|
+
const res = sourceOf(source);
|
|
10588
|
+
const bopts = options2 || {};
|
|
10570
10589
|
const ox = bopts.originX || 0;
|
|
10571
10590
|
const oz = bopts.originZ || 0;
|
|
10572
10591
|
const inw = bopts.inw || 1;
|
|
@@ -10601,33 +10620,33 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
10601
10620
|
return false;
|
|
10602
10621
|
};
|
|
10603
10622
|
}
|
|
10604
|
-
function add(world, planned,
|
|
10605
|
-
aopts =
|
|
10623
|
+
function add(world, planned, options2 = {}) {
|
|
10624
|
+
const aopts = options2 || {};
|
|
10606
10625
|
const info = worlds.get(world);
|
|
10607
|
-
const build = aopts.build || ((type, item) => hh.build(type, item,
|
|
10626
|
+
const build = aopts.build || ((type, item) => hh.build(type, item, recorderApi()));
|
|
10608
10627
|
const isBlocked = aopts.isBlocked || null;
|
|
10609
10628
|
const out = { added: 0, parts: [], hinges: {}, moved: {}, warnings: [] };
|
|
10610
10629
|
const override = aopts.lightsOn !== void 0 ? aopts.lightsOn : info && info.lightsOn;
|
|
10611
10630
|
if (override !== void 0) {
|
|
10612
10631
|
for (const e of planned.items) if (e.type === "lamp") e.lit = typeof override === "function" ? !!override(e.id, e) : !!override;
|
|
10613
10632
|
for (const e of planned.items) if (e.type === "lantern_lamp") e.lit = typeof override === "function" ? !!override(e.id, e) : !!override;
|
|
10614
|
-
for (const e of planned.items) if (e.type === "wall_switch") e.lit = (e.connections.controls || []).some((id) =>
|
|
10633
|
+
for (const e of planned.items) if (e.type === "wall_switch") e.lit = (e.connections.controls || []).some((id) => planned.items.find((x) => x.id === id)?.lit === true);
|
|
10615
10634
|
}
|
|
10616
10635
|
for (const e of planned.items) if (e.type === "lantern_lamp") e.item.on = !!e.lit;
|
|
10617
10636
|
let scratch = null;
|
|
10618
|
-
function probe(e, hinge, setback) {
|
|
10637
|
+
function probe(e, hinge, setback, blockedAt) {
|
|
10619
10638
|
if (!scratch) scratch = GI.createWorld({ locale, strings: hh.strings, items: hh.items, loot: hh.loot, grid: false });
|
|
10620
|
-
const it = e.item;
|
|
10639
|
+
const it = at(e.item);
|
|
10621
10640
|
const x = it.x + Math.sin(it.ry) * setback;
|
|
10622
10641
|
const z = it.z + Math.cos(it.ry) * setback;
|
|
10623
|
-
const spec = hh.build(e.type, Object.assign({},
|
|
10642
|
+
const spec = hh.build(e.type, Object.assign({}, e.item, { hinge }), recorderApi());
|
|
10624
10643
|
scratch.add("__probe", spec, { x, y: e.floorY, z, ry: it.ry });
|
|
10625
|
-
const blocks = (px, pz) =>
|
|
10644
|
+
const blocks = (px, pz) => blockedAt(px, pz, e.floor);
|
|
10626
10645
|
let sum = 0;
|
|
10627
10646
|
let min = 1;
|
|
10628
10647
|
let n = 0;
|
|
10629
10648
|
for (const p of spec.parts || []) {
|
|
10630
|
-
if (p.motion.kind !== "hinge" || !(p.bounds || p.sweep)) continue;
|
|
10649
|
+
if (!p.motion || p.motion.kind !== "hinge" || !(p.bounds || p.sweep)) continue;
|
|
10631
10650
|
const t = scratch.fitSweep("__probe", p.id, blocks);
|
|
10632
10651
|
sum += t;
|
|
10633
10652
|
min = Math.min(min, t);
|
|
@@ -10639,12 +10658,12 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
10639
10658
|
const better = (a, b) => a.sum > b.sum + 1e-9 || Math.abs(a.sum - b.sum) <= 1e-9 && a.min > b.min + 1e-9;
|
|
10640
10659
|
function fitDoors(e) {
|
|
10641
10660
|
if (!isBlocked || !householdTypes.has(e.type)) return;
|
|
10642
|
-
const standard = probe(e, void 0, 0);
|
|
10661
|
+
const standard = probe(e, void 0, 0, isBlocked);
|
|
10643
10662
|
if (!standard.n || standard.min >= 1) return;
|
|
10644
10663
|
let bestSide;
|
|
10645
10664
|
let m = standard;
|
|
10646
10665
|
for (const side of ["left", "right"]) {
|
|
10647
|
-
const r = probe(e, side, 0);
|
|
10666
|
+
const r = probe(e, side, 0, isBlocked);
|
|
10648
10667
|
if (better(r, m)) {
|
|
10649
10668
|
m = r;
|
|
10650
10669
|
bestSide = side;
|
|
@@ -10657,13 +10676,14 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
10657
10676
|
if (m.min >= 1) return;
|
|
10658
10677
|
let target = { setback: 0, r: m };
|
|
10659
10678
|
for (const setback of [0.01, 0.02, 0.03, 0.04]) {
|
|
10660
|
-
const r = probe(e, bestSide, setback);
|
|
10679
|
+
const r = probe(e, bestSide, setback, isBlocked);
|
|
10661
10680
|
if (better(r, target.r)) target = { setback, r };
|
|
10662
10681
|
if (r.min >= 1) break;
|
|
10663
10682
|
}
|
|
10664
10683
|
if (target.setback > 0 && target.r.sum > m.sum + 0.2) {
|
|
10665
|
-
|
|
10666
|
-
e.item.
|
|
10684
|
+
const p = at(e.item);
|
|
10685
|
+
e.item.x = r3(p.x + Math.sin(p.ry) * target.setback);
|
|
10686
|
+
e.item.z = r3(p.z + Math.cos(p.ry) * target.setback);
|
|
10667
10687
|
e.moved = target.setback;
|
|
10668
10688
|
out.moved[e.id] = target.setback;
|
|
10669
10689
|
}
|
|
@@ -10686,7 +10706,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
10686
10706
|
}
|
|
10687
10707
|
}
|
|
10688
10708
|
connect(e, spec);
|
|
10689
|
-
|
|
10709
|
+
const pose = at(e.item);
|
|
10710
|
+
world.add(e.id, spec, { x: pose.x, y: e.floorY, z: pose.z, ry: pose.ry });
|
|
10690
10711
|
out.added++;
|
|
10691
10712
|
if (!isBlocked) continue;
|
|
10692
10713
|
for (const p of spec.parts || []) {
|
|
@@ -10926,22 +10947,22 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
10926
10947
|
A.stats.external = Ne;
|
|
10927
10948
|
let shadows = 0;
|
|
10928
10949
|
for (let i = 0; i < N; i++) {
|
|
10929
|
-
const g = asg[i],
|
|
10950
|
+
const g = asg[i], at2 = slotOf(i), b0 = LZU.uRB0.value, b1 = LZU.uRB1.value, b2 = LZU.uRB2.value, by = LZU.uRBY.value, ex = LZU.uREx.value;
|
|
10930
10951
|
A.crates[i] = g ? { k: g.k, rects: g.rects, y: g.y, exterior: !!g.exterior, exclusion: g.exclusion || null, d: g.d } : null;
|
|
10931
10952
|
if (!g) {
|
|
10932
10953
|
put(i, { intensity: 0 });
|
|
10933
|
-
for (const a of [b0, b1, b2, ex]) a.set(EMPTY,
|
|
10934
|
-
by.set([0, 0],
|
|
10954
|
+
for (const a of [b0, b1, b2, ex]) a.set(EMPTY, at2 * 4);
|
|
10955
|
+
by.set([0, 0], at2 * 2);
|
|
10935
10956
|
continue;
|
|
10936
10957
|
}
|
|
10937
10958
|
const lamp = g.exterior ? { intensity: g.lumens, distance: g.dist, decay: g.decay } : { intensity: (7 + g.range * 0.8) * lim(1 + 0.4 * (Math.sqrt(g.n) - 1), 1, 2.2), distance: Math.max(3, g.dm * 1.3 + 0.5), decay: 1.6 };
|
|
10938
10959
|
put(i, { position: g.pos, color: g.color, ...lamp });
|
|
10939
10960
|
const rs = g.rects;
|
|
10940
|
-
b0.set(rs[0] || EMPTY,
|
|
10941
|
-
b1.set(rs[1] || EMPTY,
|
|
10942
|
-
b2.set(rs[2] || EMPTY,
|
|
10943
|
-
by.set(g.y,
|
|
10944
|
-
ex.set(g.exclusion || EMPTY,
|
|
10961
|
+
b0.set(rs[0] || EMPTY, at2 * 4);
|
|
10962
|
+
b1.set(rs[1] || EMPTY, at2 * 4);
|
|
10963
|
+
b2.set(rs[2] || EMPTY, at2 * 4);
|
|
10964
|
+
by.set(g.y, at2 * 2);
|
|
10965
|
+
ex.set(g.exclusion || EMPTY, at2 * 4);
|
|
10945
10966
|
if (i < NS) {
|
|
10946
10967
|
shadows++;
|
|
10947
10968
|
const s2 = g.house.group.uuid + "|" + g.k + "|" + g.pos.map((v) => v.toFixed(2)).join(",");
|
|
@@ -11016,10 +11037,10 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
11016
11037
|
for (const p of list2 || []) {
|
|
11017
11038
|
if (isDoor && !(open.has(p.id) ? open.get(p.id) : !!p.open)) continue;
|
|
11018
11039
|
const alongU = p.axis === "u", y = house.y0(p.floor) + (isDoor ? 1 : ((p.y0 != null ? p.y0 : 0.9) + (p.y1 != null ? p.y1 : 2)) / 2);
|
|
11019
|
-
const
|
|
11020
|
-
if (
|
|
11040
|
+
const at2 = (side) => _p.set(alongU ? p.at : p.pos + side, y, alongU ? p.pos + side : p.at).applyMatrix4(M).clone();
|
|
11041
|
+
if (at2(0).distanceTo(P0) > OPENING_REACH) continue;
|
|
11021
11042
|
for (const side of [-OPENING_SIDE, OPENING_SIDE]) {
|
|
11022
|
-
const w =
|
|
11043
|
+
const w = at2(side), hit = boxAt(boxes, w.x, w.y, w.z);
|
|
11023
11044
|
if (hit) into.set(hit.c, hit);
|
|
11024
11045
|
}
|
|
11025
11046
|
}
|
|
@@ -11027,11 +11048,11 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
11027
11048
|
reach(house.r.doors, true);
|
|
11028
11049
|
reach(house.r.windows, false);
|
|
11029
11050
|
};
|
|
11030
|
-
const clear = (
|
|
11031
|
-
for (const key of ["uRB0", "uRB1", "uRB2", "uREx"]) LZU[key].value.set(EMPTY,
|
|
11032
|
-
LZU.uRBY.value.set([0, 0],
|
|
11051
|
+
const clear = (at2) => {
|
|
11052
|
+
for (const key of ["uRB0", "uRB1", "uRB2", "uREx"]) LZU[key].value.set(EMPTY, at2 * 4);
|
|
11053
|
+
LZU.uRBY.value.set([0, 0], at2 * 2);
|
|
11033
11054
|
};
|
|
11034
|
-
const write = (
|
|
11055
|
+
const write = (at2, into) => {
|
|
11035
11056
|
const rs = [];
|
|
11036
11057
|
let lo = 1e9, hi = -1e9;
|
|
11037
11058
|
for (const q of into.values()) {
|
|
@@ -11043,21 +11064,21 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
11043
11064
|
const r23 = rs.pop(), r1 = rs[rs.length - 1];
|
|
11044
11065
|
rs[rs.length - 1] = [Math.min(r1[0], r23[0]), Math.min(r1[1], r23[1]), Math.max(r1[2], r23[2]), Math.max(r1[3], r23[3])];
|
|
11045
11066
|
}
|
|
11046
|
-
LZU.uRB0.value.set(rs[0] || EMPTY,
|
|
11047
|
-
LZU.uRB1.value.set(rs[1] || EMPTY,
|
|
11048
|
-
LZU.uRB2.value.set(rs[2] || EMPTY,
|
|
11049
|
-
LZU.uRBY.value.set([lo, hi],
|
|
11050
|
-
LZU.uREx.value.set(EMPTY,
|
|
11067
|
+
LZU.uRB0.value.set(rs[0] || EMPTY, at2 * 4);
|
|
11068
|
+
LZU.uRB1.value.set(rs[1] || EMPTY, at2 * 4);
|
|
11069
|
+
LZU.uRB2.value.set(rs[2] || EMPTY, at2 * 4);
|
|
11070
|
+
LZU.uRBY.value.set([lo, hi], at2 * 2);
|
|
11071
|
+
LZU.uREx.value.set(EMPTY, at2 * 4);
|
|
11051
11072
|
};
|
|
11052
11073
|
const A = {
|
|
11053
11074
|
/** Once per frame, after the budget's `present`: points the mask of every lit slot that is not the house's at the rooms its light reaches. */
|
|
11054
11075
|
update(houses2) {
|
|
11055
11076
|
const indoors = cfg.effectLightsIndoors !== false, list2 = (Array.isArray(houses2) ? houses2 : [houses2]).filter(Boolean), cache2 = /* @__PURE__ */ new Map();
|
|
11056
|
-
for (let
|
|
11057
|
-
if (ours.has(
|
|
11058
|
-
const light = budget.group.children[
|
|
11077
|
+
for (let at2 = 0; at2 < size; at2++) {
|
|
11078
|
+
if (ours.has(at2)) continue;
|
|
11079
|
+
const light = budget.group.children[at2];
|
|
11059
11080
|
if (!indoors || !light || !light.isPointLight || !(light.intensity > 0) || !light.visible) {
|
|
11060
|
-
clear(
|
|
11081
|
+
clear(at2);
|
|
11061
11082
|
continue;
|
|
11062
11083
|
}
|
|
11063
11084
|
const into = /* @__PURE__ */ new Map();
|
|
@@ -11072,8 +11093,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
11072
11093
|
if (here) into.set(here.c, here);
|
|
11073
11094
|
openingSides(house, M, boxes, into);
|
|
11074
11095
|
}
|
|
11075
|
-
if (into.size) write(
|
|
11076
|
-
else clear(
|
|
11096
|
+
if (into.size) write(at2, into);
|
|
11097
|
+
else clear(at2);
|
|
11077
11098
|
}
|
|
11078
11099
|
}
|
|
11079
11100
|
};
|
|
@@ -11430,11 +11451,11 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
11430
11451
|
}
|
|
11431
11452
|
return pieces.slice(0, limit).map((p) => ({ center: p.c, size: [p.s[g], p.s[a], p.s[b]], q: frame(g, a, b), shape: "splinter", weight: p.s[0] * p.s[1] * p.s[2] }));
|
|
11432
11453
|
};
|
|
11433
|
-
var severAt = (inp, root,
|
|
11454
|
+
var severAt = (inp, root, at2, gap) => {
|
|
11434
11455
|
const dims = root.s;
|
|
11435
11456
|
const L = [0, 1, 2].sort((x, y) => dims[y] - dims[x])[0];
|
|
11436
11457
|
const half = dims[L] / 2;
|
|
11437
|
-
const lo = clamp(
|
|
11458
|
+
const lo = clamp(at2 - gap / 2, -half, half), hi = clamp(at2 + gap / 2, -half, half);
|
|
11438
11459
|
const out = [];
|
|
11439
11460
|
const stub = (from, to) => {
|
|
11440
11461
|
if (to - from < 0.02) return;
|
|
@@ -13816,7 +13837,13 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
13816
13837
|
const typed = listeners.get(e.type);
|
|
13817
13838
|
if (typed) for (const fn of [...typed]) fn(e);
|
|
13818
13839
|
};
|
|
13819
|
-
|
|
13840
|
+
let blow;
|
|
13841
|
+
const base = (o, source) => ({
|
|
13842
|
+
object: o.id,
|
|
13843
|
+
time,
|
|
13844
|
+
...source === void 0 ? {} : { source },
|
|
13845
|
+
...blow === void 0 ? {} : { blow }
|
|
13846
|
+
});
|
|
13820
13847
|
const pendingCollapse = /* @__PURE__ */ new Map();
|
|
13821
13848
|
let runDepth = 0;
|
|
13822
13849
|
const drainBlasts = () => {
|
|
@@ -14086,9 +14113,9 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
14086
14113
|
const [lo, hi] = contactBox(p, above);
|
|
14087
14114
|
return toWorld(p.pos, p.q, [(lo[0] + hi[0]) / 2, (lo[1] + hi[1]) / 2, (lo[2] + hi[2]) / 2]);
|
|
14088
14115
|
};
|
|
14089
|
-
const overSupportAt = (o, p,
|
|
14116
|
+
const overSupportAt = (o, p, at2, lower) => {
|
|
14090
14117
|
const g = p.bend;
|
|
14091
|
-
const local = toLocal(p.pos, p.q,
|
|
14118
|
+
const local = toLocal(p.pos, p.q, at2);
|
|
14092
14119
|
const depth = g.gravity >= 0 ? g.dims[g.gravity] : Math.min(...g.depthAxes.map((a) => g.dims[a]));
|
|
14093
14120
|
let best = -1;
|
|
14094
14121
|
let bestGap = depth;
|
|
@@ -14242,10 +14269,10 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
14242
14269
|
const incoming = new Array(n).fill(0);
|
|
14243
14270
|
const bending = new Array(n).fill(0);
|
|
14244
14271
|
const through = parts.map(() => []);
|
|
14245
|
-
const pass = (k,
|
|
14246
|
-
const over = overSupportAt(o, parts[k],
|
|
14272
|
+
const pass = (k, at2, mass) => {
|
|
14273
|
+
const over = overSupportAt(o, parts[k], at2, lowerOf.get(k) ?? []);
|
|
14247
14274
|
if (over < 0) bending[k] += mass;
|
|
14248
|
-
else through[k].push({ at, mass, over });
|
|
14275
|
+
else through[k].push({ at: at2, mass, over });
|
|
14249
14276
|
};
|
|
14250
14277
|
for (let h = queue.length - 1; h >= 0; h--) {
|
|
14251
14278
|
const i = queue[h];
|
|
@@ -14312,7 +14339,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
14312
14339
|
const terrain = cfg.terrains.get(cfg.terrain);
|
|
14313
14340
|
if (!terrain) throw new Error(`unknown wind terrain "${cfg.terrain}"`);
|
|
14314
14341
|
const inputs = [];
|
|
14315
|
-
const
|
|
14342
|
+
const at2 = /* @__PURE__ */ new Map();
|
|
14316
14343
|
const keep = [];
|
|
14317
14344
|
let ground = Infinity, foundationTop = -Infinity;
|
|
14318
14345
|
o.parts.forEach((p, i) => {
|
|
@@ -14321,7 +14348,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
14321
14348
|
const role = p.spec.structure?.role;
|
|
14322
14349
|
const e = p.mat.strength?.elasticGPa;
|
|
14323
14350
|
const kind = role === "wall" ? "wall" : role === "column" ? "column" : role === "beam" ? "beam" : role === "foundation" ? "foundation" : "other";
|
|
14324
|
-
|
|
14351
|
+
at2.set(i, inputs.length);
|
|
14325
14352
|
keep.push(i);
|
|
14326
14353
|
ground = Math.min(ground, box3.min[1]);
|
|
14327
14354
|
if (kind === "foundation") foundationTop = Math.max(foundationTop, box3.max[1]);
|
|
@@ -14332,7 +14359,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
14332
14359
|
const beams = [];
|
|
14333
14360
|
for (const j of o.byPart.get(o.parts[i].spec.id)) {
|
|
14334
14361
|
if (j.st.open) continue;
|
|
14335
|
-
const b =
|
|
14362
|
+
const b = at2.get(j.ia === i ? j.ib : j.ia);
|
|
14336
14363
|
if (b !== void 0 && inputs[b].kind === "beam") beams.push(b);
|
|
14337
14364
|
}
|
|
14338
14365
|
inputs[k].beams = beams;
|
|
@@ -15148,7 +15175,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
15148
15175
|
}
|
|
15149
15176
|
};
|
|
15150
15177
|
const tornToEdge = (o) => {
|
|
15151
|
-
const { p, cell, a, b, at, crater: crater2, reach, gone } = o;
|
|
15178
|
+
const { p, cell, a, b, at: at2, crater: crater2, reach, gone } = o;
|
|
15152
15179
|
const half = p.dims[a] / 2;
|
|
15153
15180
|
const lo = cell.center[a] - cell.size[a] / 2, hi = cell.center[a] + cell.size[a] / 2;
|
|
15154
15181
|
const free = (side, sign2) => {
|
|
@@ -15156,8 +15183,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
15156
15183
|
const probe = side + sign2 * 1e-3;
|
|
15157
15184
|
return gridOf(p).some((c, k) => gone(k) && Math.abs(probe - c.center[a]) <= c.size[a] / 2 && Math.abs(cell.center[b] - c.center[b]) <= c.size[b] / 2);
|
|
15158
15185
|
};
|
|
15159
|
-
if (
|
|
15160
|
-
if (hi -
|
|
15186
|
+
if (at2 - lo <= reach && free(lo, -1)) return [lo, Math.max(crater2[1], lo)];
|
|
15187
|
+
if (hi - at2 <= reach && free(hi, 1)) return [Math.min(crater2[0], hi), hi];
|
|
15161
15188
|
return crater2;
|
|
15162
15189
|
};
|
|
15163
15190
|
const craterAcross = (energy) => clamp2(0.03 + 12e-4 * Math.sqrt(Math.max(0, energy)), 0.03, 0.14);
|
|
@@ -15367,7 +15394,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
15367
15394
|
return;
|
|
15368
15395
|
}
|
|
15369
15396
|
if (ex) {
|
|
15370
|
-
emit({ ...base(o, src), type: "explode", part: p.spec.id, point: c, energy: ex.energy, radius: ex.radius, ...ex.lethalRadius !== void 0 ? { lethalRadius: ex.lethalRadius } : {}, ...ex.effect !== void 0 ? { effect: ex.effect } : {} });
|
|
15397
|
+
emit({ ...base(o, src), type: "explode", part: p.spec.id, point: c, energy: ex.energy, radius: ex.radius, ...ex.lethalRadius !== void 0 ? { lethalRadius: ex.lethalRadius } : {}, ...ex.tnt !== void 0 ? { tnt: ex.tnt } : {}, ...ex.effect !== void 0 ? { effect: ex.effect } : {} });
|
|
15371
15398
|
blasts.push({ point: c, energy: ex.energy, radius: ex.radius, ...ex.lethalRadius !== void 0 ? { lethalRadius: ex.lethalRadius } : {}, source: src });
|
|
15372
15399
|
}
|
|
15373
15400
|
partLost(o, p, src);
|
|
@@ -15961,7 +15988,17 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
15961
15988
|
res.events = cur.slice(start);
|
|
15962
15989
|
return res;
|
|
15963
15990
|
};
|
|
15964
|
-
const
|
|
15991
|
+
const withBlow = (type, fn) => () => {
|
|
15992
|
+
const outer = blow;
|
|
15993
|
+
blow = type;
|
|
15994
|
+
try {
|
|
15995
|
+
return fn();
|
|
15996
|
+
} finally {
|
|
15997
|
+
blow = outer;
|
|
15998
|
+
}
|
|
15999
|
+
};
|
|
16000
|
+
const doHit = (o, hit, only) => withBlow(hit.type, () => resolveHit(o, hit, only))();
|
|
16001
|
+
const resolveHit = (o, hit, only) => {
|
|
15965
16002
|
let point = hit.point;
|
|
15966
16003
|
let dir = hit.direction;
|
|
15967
16004
|
if (hit.space === "local") {
|
|
@@ -16400,6 +16437,44 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
16400
16437
|
blastProbe() {
|
|
16401
16438
|
return { ...blastProbe };
|
|
16402
16439
|
},
|
|
16440
|
+
blastReach(point, target, options2 = {}) {
|
|
16441
|
+
const L = vec.distance(point, target);
|
|
16442
|
+
if (L < 1e-4) return 1;
|
|
16443
|
+
const shelter = { ...SHELTER_DEFAULTS, ...options2.shelter };
|
|
16444
|
+
const ignore = new Set(options2.ignore ?? []);
|
|
16445
|
+
const d = vec.scale(vec.sub(target, point), 1 / L);
|
|
16446
|
+
let t = 1;
|
|
16447
|
+
for (const o of objects.values()) {
|
|
16448
|
+
if (ignore.has(o.id) || raySphereMiss(point, d, toWorld(o.st.position, o.st.rotation, o.bc), o.br, L)) continue;
|
|
16449
|
+
for (const p of o.parts) {
|
|
16450
|
+
if (isLost(p) || p.st.stripped) continue;
|
|
16451
|
+
const r = rayPart(o, p, point, d);
|
|
16452
|
+
if (!r) continue;
|
|
16453
|
+
const t0 = Math.max(r.t0, 0);
|
|
16454
|
+
const path = Math.min(r.t1, L) - t0;
|
|
16455
|
+
if (path < shelter.minPath) continue;
|
|
16456
|
+
if (p.st.opening && insideOpening(o, p, toLocal(o.st.position, o.st.rotation, vec.madd(point, d, t0 + path / 2)))) continue;
|
|
16457
|
+
t *= Math.exp(-(p.mat.hpPerKg * p.mat.density * path * (p.mat.damageScale?.shelter ?? 1)) / shelter.k);
|
|
16458
|
+
if (t < 1e-4) return 0;
|
|
16459
|
+
}
|
|
16460
|
+
}
|
|
16461
|
+
for (const im of impls.values()) {
|
|
16462
|
+
if (ignore.has(im.impl.id)) continue;
|
|
16463
|
+
for (const ps of im.impl.describe().parts) {
|
|
16464
|
+
const mat = materials.get(ps.material);
|
|
16465
|
+
if (!mat) continue;
|
|
16466
|
+
const ov = im.poses.get(ps.id);
|
|
16467
|
+
const r = rayPartRaw(im.position, im.rotation, ps, ov?.q ?? quatFromEuler(...ps.rotation ?? [0, 0, 0]), point, d, ov?.pos);
|
|
16468
|
+
if (!r || r.t1 < 0 || r.t0 > L) continue;
|
|
16469
|
+
let path = Math.min(r.t1, L) - Math.max(r.t0, 0);
|
|
16470
|
+
if (ps.thickness !== void 0 && ps.thickness > 0) path = Math.min(path, 2 * ps.thickness);
|
|
16471
|
+
else if (path < shelter.minPath) continue;
|
|
16472
|
+
t *= Math.exp(-(mat.hpPerKg * mat.density * path * (mat.damageScale?.shelter ?? 1)) / shelter.k);
|
|
16473
|
+
if (t < 1e-4) return 0;
|
|
16474
|
+
}
|
|
16475
|
+
}
|
|
16476
|
+
return t;
|
|
16477
|
+
},
|
|
16403
16478
|
explode(point, energy, radius, source, blast) {
|
|
16404
16479
|
blastProbe.partsTested = 0;
|
|
16405
16480
|
blastProbe.partsNear = 0;
|
|
@@ -16424,7 +16499,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
16424
16499
|
},
|
|
16425
16500
|
shoot(origin, direction, energy, caliber, source, round3) {
|
|
16426
16501
|
const extras = typeof round3 === "number" ? { piercing: round3 } : round3 ?? {};
|
|
16427
|
-
return withCollapses(run(() => {
|
|
16502
|
+
return withCollapses(run(withBlow("ballistic", () => {
|
|
16428
16503
|
const results = [];
|
|
16429
16504
|
const d = vec.normalize(direction);
|
|
16430
16505
|
const ignore = /* @__PURE__ */ new Set();
|
|
@@ -16435,10 +16510,12 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
16435
16510
|
if (!rh) break;
|
|
16436
16511
|
const im = impls.get(rh.object);
|
|
16437
16512
|
if (im) {
|
|
16438
|
-
const
|
|
16513
|
+
const scaled = extras.penetration && E < energy ? { ...extras, penetration: Object.fromEntries(Object.entries(extras.penetration).map(([k, mm]) => [k, mm * (E / energy)])) } : extras;
|
|
16514
|
+
const r = implHit(im, { type: "ballistic", point: rh.point, part: rh.part, normal: rh.normal, direction: d, energy: E, caliber, ...scaled, ...source !== void 0 ? { source } : {} });
|
|
16439
16515
|
r.part = rh.part;
|
|
16440
16516
|
r.point = rh.point;
|
|
16441
|
-
|
|
16517
|
+
const left = r.events.find((e) => e.type === "hole" && e.energyLeft !== void 0);
|
|
16518
|
+
r.exitEnergy = r.penetrated ? left?.energyLeft ?? E * 0.5 : 0;
|
|
16442
16519
|
results.push(r);
|
|
16443
16520
|
ignore.add(`${im.impl.id}\0${rh.part}`);
|
|
16444
16521
|
if (!r.penetrated) break;
|
|
@@ -16457,7 +16534,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
16457
16534
|
E = out.exitEnergy;
|
|
16458
16535
|
}
|
|
16459
16536
|
return results;
|
|
16460
|
-
}));
|
|
16537
|
+
})));
|
|
16461
16538
|
},
|
|
16462
16539
|
disassemble(objectId, jointId, tool, dt) {
|
|
16463
16540
|
const im = impls.get(objectId);
|
|
@@ -16765,8 +16842,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
16765
16842
|
list: () => defs,
|
|
16766
16843
|
get,
|
|
16767
16844
|
register(def) {
|
|
16768
|
-
const
|
|
16769
|
-
if (
|
|
16845
|
+
const at2 = defs.findIndex((a) => a.id === def.id);
|
|
16846
|
+
if (at2 >= 0) defs[at2] = def;
|
|
16770
16847
|
else defs.push(def);
|
|
16771
16848
|
},
|
|
16772
16849
|
part: (assemblyId, options) => buildAssemblyPart(get(assemblyId), assemblyId, options)
|
|
@@ -17837,9 +17914,10 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
17837
17914
|
}
|
|
17838
17915
|
if (context.isTimber && construction.roof.shape !== "slab") addCeilingJoists(context);
|
|
17839
17916
|
}
|
|
17917
|
+
var isStair = (item) => item.category === "stairs" && typeof item.link === "object" && item.link !== null;
|
|
17840
17918
|
function flightsOf(items) {
|
|
17841
17919
|
const flights = /* @__PURE__ */ new Map();
|
|
17842
|
-
for (const item of items.filter(
|
|
17920
|
+
for (const item of items.filter(isStair)) {
|
|
17843
17921
|
const key = `${item.link.from}_${item.link.to}`;
|
|
17844
17922
|
if (!flights.has(key) || item.floor === item.link.from) flights.set(key, item);
|
|
17845
17923
|
}
|
|
@@ -20219,17 +20297,17 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
20219
20297
|
for (const { c, part, units: units2, thick, mid } of shown) {
|
|
20220
20298
|
if (!near(c)) continue;
|
|
20221
20299
|
const centre = mask.start + (c.a + c.b) / 2, y = (c.y0 + c.y1) / 2, len = c.b - c.a, h = c.y1 - c.y0;
|
|
20222
|
-
const
|
|
20300
|
+
const at2 = (s, dy, d, colour) => {
|
|
20223
20301
|
const unit = clipToBox({ x: mask.alongU ? centre : mid, y, z: mask.alongU ? mid : centre, sx: mask.alongU ? s : d, sy: dy, sz: mask.alongU ? d : s, colour }, view.bounds);
|
|
20224
20302
|
if (unit) list2.push(unit);
|
|
20225
20303
|
};
|
|
20226
20304
|
const base = fragmentMaterial(part.material).color.getHex();
|
|
20227
20305
|
const n = noise2(centre * 3.1, y * 2.7, 0.07);
|
|
20228
20306
|
if (units2.mortar === "concrete") {
|
|
20229
|
-
|
|
20307
|
+
at2(len, h, thick - 2 * COVER2, tone(base, 0.9 + 0.04 * n));
|
|
20230
20308
|
} else {
|
|
20231
|
-
|
|
20232
|
-
|
|
20309
|
+
at2(len, h, thick - 2 * COVER2 - 0.012, 10327948);
|
|
20310
|
+
at2(len - 0.012, h - 0.012, thick - 2 * COVER2, tone(base, 0.8 + 0.35 * n));
|
|
20233
20311
|
}
|
|
20234
20312
|
}
|
|
20235
20313
|
if (view.units) {
|
|
@@ -20545,11 +20623,11 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
20545
20623
|
};
|
|
20546
20624
|
const extract = (it) => {
|
|
20547
20625
|
const g0 = it.mesh.geometry, src = it.mesh.userData._p0 || g0.attributes.position.array, g = new THREE.BufferGeometry();
|
|
20548
|
-
const
|
|
20549
|
-
|
|
20550
|
-
|
|
20551
|
-
|
|
20552
|
-
|
|
20626
|
+
const at2 = (name, k, arr) => g.setAttribute(name, new THREE.BufferAttribute((arr || g0.attributes[name].array).slice(it.v0 * k, it.v1 * k), k));
|
|
20627
|
+
at2("position", 3, src);
|
|
20628
|
+
at2("normal", 3);
|
|
20629
|
+
at2("color", 3);
|
|
20630
|
+
at2("uv", 2);
|
|
20553
20631
|
const ix = g0.index.array.slice(it.i0, it.i1);
|
|
20554
20632
|
for (let k = 0; k < ix.length; k++) ix[k] -= it.v0;
|
|
20555
20633
|
g.setIndex(new THREE.BufferAttribute(ix, 1));
|
|
@@ -21264,9 +21342,9 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
21264
21342
|
shared.vegMaterials.setActors(focus ? [{ x: focus.x, y: focus.y, z: focus.z, radius: 0.9 }] : []);
|
|
21265
21343
|
}
|
|
21266
21344
|
if (focus && cfg.lod !== false) {
|
|
21267
|
-
const L = Object.assign({ interior: 45, hide: 220 }, cfg.lod), d = distance2(focus),
|
|
21345
|
+
const L = Object.assign({ interior: 45, hide: 220 }, cfg.lod), d = distance2(focus), at2 = h.lodCurrent;
|
|
21268
21346
|
let n = d > L.hide ? 2 : d > L.interior ? 1 : 0;
|
|
21269
|
-
if (n <
|
|
21347
|
+
if (n < at2) n = d < (at2 === 2 ? L.hide : L.interior) * 0.92 ? n : at2;
|
|
21270
21348
|
applyLod(Math.max(n, h.lodMin));
|
|
21271
21349
|
}
|
|
21272
21350
|
},
|
|
@@ -22017,14 +22095,14 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
22017
22095
|
|
|
22018
22096
|
// src/test-area/scenarios.ts
|
|
22019
22097
|
var SPECIMEN_AT = [-5, 0, -11];
|
|
22020
|
-
function createHouseScenarios(text,
|
|
22098
|
+
function createHouseScenarios(text, at2 = SPECIMEN_AT) {
|
|
22021
22099
|
const T2 = text.steps;
|
|
22022
22100
|
const spawn = (room, item) => {
|
|
22023
|
-
const so = room.spawn(item, [
|
|
22101
|
+
const so = room.spawn(item, [at2[0], at2[1], at2[2]], 0);
|
|
22024
22102
|
const parts = so.root.userData.floorplanSpec.parts;
|
|
22025
22103
|
const centre = (id) => {
|
|
22026
22104
|
const p = parts.find((x) => x.id === id);
|
|
22027
|
-
return [p.position[0] +
|
|
22105
|
+
return [p.position[0] + at2[0], p.position[1] + at2[1], p.position[2] + at2[2]];
|
|
22028
22106
|
};
|
|
22029
22107
|
return { oid: so.objectId, parts, centre };
|
|
22030
22108
|
};
|
|
@@ -22399,9 +22477,9 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
22399
22477
|
};
|
|
22400
22478
|
const eyeOf = (p) => {
|
|
22401
22479
|
const camera = host?.camera;
|
|
22402
|
-
const
|
|
22480
|
+
const at2 = toLocal2(p, camera.position.x, camera.position.y, camera.position.z);
|
|
22403
22481
|
const forward = new THREE.Vector3(0, 0, -1).applyQuaternion(camera.quaternion).transformDirection(new THREE.Matrix4().copy(p.house.group.matrixWorld).invert());
|
|
22404
|
-
return { x:
|
|
22482
|
+
return { x: at2.x, y: at2.y, z: at2.z, floor: floorOf(p, camera.position.y), yaw: Math.atan2(forward.x, forward.z), pitch: Math.asin(Math.max(-1, Math.min(1, forward.y))) };
|
|
22405
22483
|
};
|
|
22406
22484
|
const blocked = (x, z, radius) => {
|
|
22407
22485
|
for (const p of placed) {
|
|
@@ -22469,7 +22547,7 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
22469
22547
|
const doorReach = (p, fo) => {
|
|
22470
22548
|
const g = fo.gs[0];
|
|
22471
22549
|
const pivot = fo.handles[0].pivot;
|
|
22472
|
-
const
|
|
22550
|
+
const at2 = (angle) => {
|
|
22473
22551
|
const c = Math.cos(angle);
|
|
22474
22552
|
const s = Math.sin(angle);
|
|
22475
22553
|
const v = new THREE.Vector3(pivot[0] * c + pivot[2] * s, pivot[1], -pivot[0] * s + pivot[2] * c).add(g.position);
|
|
@@ -22478,8 +22556,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
22478
22556
|
const camera = host?.camera;
|
|
22479
22557
|
const eye = new THREE.Vector3(camera.position.x, 0, camera.position.z);
|
|
22480
22558
|
const flat = (v) => Math.hypot(v.x - eye.x, v.z - eye.z);
|
|
22481
|
-
const closed =
|
|
22482
|
-
const open =
|
|
22559
|
+
const closed = at2(0);
|
|
22560
|
+
const open = at2(fo.rot);
|
|
22483
22561
|
const opening = !fo.open;
|
|
22484
22562
|
return {
|
|
22485
22563
|
handle: () => {
|
|
@@ -23187,8 +23265,9 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
23187
23265
|
facadeExtra: (f, rng2, w, d, op) => {
|
|
23188
23266
|
f.roof = "slab";
|
|
23189
23267
|
f.finish = rng2() < 0.55 ? "exposed_block" : "partial_plaster";
|
|
23190
|
-
|
|
23191
|
-
|
|
23268
|
+
const slab = { exposedRebar: true, waterTank: { u: r22(0.5 + rng2() * (w - 1.5)), v: r22(1 + rng2() * (d - 2)) }, annex: rng2() < 0.55 ? { rect: [0, 0, r22(w * (0.5 + rng2() * 0.3)), r22(d * 0.4)], state: "exposed_brick" } : null };
|
|
23269
|
+
f.slab = slab;
|
|
23270
|
+
if (floorsOf(op) > 1) slab.exposedRebar = rng2() < 0.6;
|
|
23192
23271
|
}
|
|
23193
23272
|
};
|
|
23194
23273
|
}
|
|
@@ -23900,13 +23979,13 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
23900
23979
|
function apartment(strip, floor, k, from, to, plate, ceiling, win) {
|
|
23901
23980
|
const wide = to - from, depth = strip.depth, facade = r22(depth * 0.56);
|
|
23902
23981
|
const id = (name) => `apt_${floor}_${strip.id}_${k}_${name}`;
|
|
23903
|
-
const
|
|
23982
|
+
const at2 = (f0, f1, b0, b1) => boxOf2(strip, r22(from + wide * f0), r22(from + wide * f1), b0, b1);
|
|
23904
23983
|
const rooms = [
|
|
23905
|
-
{ id: id("living"), type: "living", label: "living", library: "living_tower", rect:
|
|
23906
|
-
{ id: id("bedroom"), type: "bedroom", label: "bedroom", rect:
|
|
23907
|
-
{ id: id("kitchen"), type: "kitchen", label: "kitchen", library: "kitchen_integrated", rect:
|
|
23908
|
-
{ id: id("hall"), type: "hall", label: "hall", rect:
|
|
23909
|
-
{ id: id("bath"), type: "bathroom", label: "bathroom", library: "bathroom_wc", rect:
|
|
23984
|
+
{ id: id("living"), type: "living", label: "living", library: "living_tower", rect: at2(0, 0.58, 0, facade) },
|
|
23985
|
+
{ id: id("bedroom"), type: "bedroom", label: "bedroom", rect: at2(0.58, 1, 0, facade) },
|
|
23986
|
+
{ id: id("kitchen"), type: "kitchen", label: "kitchen", library: "kitchen_integrated", rect: at2(0, 0.4, facade, depth) },
|
|
23987
|
+
{ id: id("hall"), type: "hall", label: "hall", rect: at2(0.4, 0.78, facade, depth) },
|
|
23988
|
+
{ id: id("bath"), type: "bathroom", label: "bathroom", library: "bathroom_wc", rect: at2(0.78, 1, facade, depth) }
|
|
23910
23989
|
];
|
|
23911
23990
|
const doors = [
|
|
23912
23991
|
stripDoor(id("hall"), strip, floor, 0.95),
|
|
@@ -23939,8 +24018,8 @@ uniform mat4 uNodes[${nodes.length}]; attribute float aNodeIndex; attribute vec3
|
|
|
23939
24018
|
if (strip.id !== "south") return apartments(plan)(strip, context);
|
|
23940
24019
|
const { floor, plate, ceiling } = context;
|
|
23941
24020
|
const lobby = `lobby_${floor}_entrance`, concierge = `concierge_${floor}`, bikes = `bike_room_${floor}`;
|
|
23942
|
-
const
|
|
23943
|
-
const [left, middle, right] = [
|
|
24021
|
+
const at2 = (f0, f1) => boxOf2(strip, r22(strip.length * f0), r22(strip.length * f1), 0, strip.depth);
|
|
24022
|
+
const [left, middle, right] = [at2(0, 0.3), at2(0.3, 0.7), at2(0.7, 1)];
|
|
23944
24023
|
const rooms = [
|
|
23945
24024
|
{ id: concierge, type: "office", label: "concierge", rect: left },
|
|
23946
24025
|
{ id: lobby, type: "hall", label: "lobby_entrance", rect: middle },
|