@adatechnology/game-crowd-three 0.2.0 → 0.3.1
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 +2092 -122
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/package.json +9 -9
package/dist/index.global.js
CHANGED
|
@@ -989,6 +989,379 @@ var GameCrowdThree = (() => {
|
|
|
989
989
|
var RED = 8000012;
|
|
990
990
|
var BLOOD_COLORS = [10361618, 7214096, 4860440, 1840658];
|
|
991
991
|
var OLD_HAIR = 9078656;
|
|
992
|
+
var pose_clips_default = {
|
|
993
|
+
clips: [
|
|
994
|
+
{
|
|
995
|
+
id: "grabbed_bitten_human",
|
|
996
|
+
source: {
|
|
997
|
+
file: "site/pages/zumbis-personagens/bestiario.html",
|
|
998
|
+
scene: "ataque (Agarr\xE3o e mordida)",
|
|
999
|
+
variable: "HK"
|
|
1000
|
+
},
|
|
1001
|
+
duration: 8,
|
|
1002
|
+
loop: false,
|
|
1003
|
+
channels: "full",
|
|
1004
|
+
keys: [
|
|
1005
|
+
{
|
|
1006
|
+
t: 0,
|
|
1007
|
+
pose: {
|
|
1008
|
+
lean: 0,
|
|
1009
|
+
headY: 0,
|
|
1010
|
+
armL: -0.1,
|
|
1011
|
+
armR: 0.05,
|
|
1012
|
+
elbL: -0.2,
|
|
1013
|
+
elbR: -0.2,
|
|
1014
|
+
drop: 0,
|
|
1015
|
+
kneeL: 0.05,
|
|
1016
|
+
kneeR: 0.05,
|
|
1017
|
+
legL: -0.05,
|
|
1018
|
+
legR: 0.05,
|
|
1019
|
+
headX: 0
|
|
1020
|
+
}
|
|
1021
|
+
},
|
|
1022
|
+
{
|
|
1023
|
+
t: 1.5,
|
|
1024
|
+
pose: {
|
|
1025
|
+
lean: -0.1,
|
|
1026
|
+
headY: -0.6,
|
|
1027
|
+
armL: -0.1,
|
|
1028
|
+
armR: 0.05,
|
|
1029
|
+
elbL: -0.2,
|
|
1030
|
+
elbR: -0.2,
|
|
1031
|
+
drop: 0,
|
|
1032
|
+
kneeL: 0.05,
|
|
1033
|
+
kneeR: 0.05,
|
|
1034
|
+
legL: -0.05,
|
|
1035
|
+
legR: 0.05,
|
|
1036
|
+
headX: -0.1
|
|
1037
|
+
}
|
|
1038
|
+
},
|
|
1039
|
+
{
|
|
1040
|
+
t: 2.1,
|
|
1041
|
+
pose: {
|
|
1042
|
+
lean: -0.3,
|
|
1043
|
+
headY: -0.2,
|
|
1044
|
+
armL: -1.3,
|
|
1045
|
+
armR: -1.2,
|
|
1046
|
+
elbL: -1.4,
|
|
1047
|
+
elbR: -1.5,
|
|
1048
|
+
drop: -0.04,
|
|
1049
|
+
kneeL: 0.25,
|
|
1050
|
+
kneeR: 0.2,
|
|
1051
|
+
legL: -0.3,
|
|
1052
|
+
legR: 0.25,
|
|
1053
|
+
headX: -0.25
|
|
1054
|
+
}
|
|
1055
|
+
},
|
|
1056
|
+
{
|
|
1057
|
+
t: 3.6,
|
|
1058
|
+
pose: {
|
|
1059
|
+
lean: -0.35,
|
|
1060
|
+
headY: 0.3,
|
|
1061
|
+
armL: -1.5,
|
|
1062
|
+
armR: -1,
|
|
1063
|
+
elbL: -0.6,
|
|
1064
|
+
elbR: -1.8,
|
|
1065
|
+
drop: -0.05,
|
|
1066
|
+
kneeL: 0.3,
|
|
1067
|
+
kneeR: 0.2,
|
|
1068
|
+
legL: -0.4,
|
|
1069
|
+
legR: 0.35,
|
|
1070
|
+
headX: -0.2
|
|
1071
|
+
}
|
|
1072
|
+
},
|
|
1073
|
+
{
|
|
1074
|
+
t: 4.3,
|
|
1075
|
+
pose: {
|
|
1076
|
+
lean: -0.2,
|
|
1077
|
+
headY: 0.7,
|
|
1078
|
+
headZ: -0.5,
|
|
1079
|
+
armL: -0.6,
|
|
1080
|
+
armR: -1.9,
|
|
1081
|
+
elbL: -0.4,
|
|
1082
|
+
elbR: -1.2,
|
|
1083
|
+
drop: -0.06,
|
|
1084
|
+
kneeL: 0.3,
|
|
1085
|
+
kneeR: 0.3,
|
|
1086
|
+
legL: -0.3,
|
|
1087
|
+
legR: 0.3,
|
|
1088
|
+
headX: -0.3
|
|
1089
|
+
}
|
|
1090
|
+
},
|
|
1091
|
+
{
|
|
1092
|
+
t: 5.6,
|
|
1093
|
+
pose: {
|
|
1094
|
+
lean: 0.55,
|
|
1095
|
+
headY: 0.4,
|
|
1096
|
+
headZ: -0.3,
|
|
1097
|
+
armL: -0.3,
|
|
1098
|
+
armR: -0.5,
|
|
1099
|
+
elbL: -0.6,
|
|
1100
|
+
elbR: -0.8,
|
|
1101
|
+
drop: -0.5,
|
|
1102
|
+
kneeL: 1.9,
|
|
1103
|
+
kneeR: 1.7,
|
|
1104
|
+
legL: -1.1,
|
|
1105
|
+
legR: -0.9,
|
|
1106
|
+
headX: 0.3
|
|
1107
|
+
}
|
|
1108
|
+
},
|
|
1109
|
+
{
|
|
1110
|
+
t: 8,
|
|
1111
|
+
pose: {
|
|
1112
|
+
lean: 0.6,
|
|
1113
|
+
headY: 0.4,
|
|
1114
|
+
headZ: -0.3,
|
|
1115
|
+
armL: -0.25,
|
|
1116
|
+
armR: -0.45,
|
|
1117
|
+
elbL: -0.6,
|
|
1118
|
+
elbR: -0.8,
|
|
1119
|
+
drop: -0.52,
|
|
1120
|
+
kneeL: 1.95,
|
|
1121
|
+
kneeR: 1.75,
|
|
1122
|
+
legL: -1.1,
|
|
1123
|
+
legR: -0.95,
|
|
1124
|
+
headX: 0.4
|
|
1125
|
+
}
|
|
1126
|
+
}
|
|
1127
|
+
],
|
|
1128
|
+
events: [
|
|
1129
|
+
{
|
|
1130
|
+
t: 0,
|
|
1131
|
+
type: "phase",
|
|
1132
|
+
data: {
|
|
1133
|
+
label: "pose_clip.grab_bite.phase.approach"
|
|
1134
|
+
}
|
|
1135
|
+
},
|
|
1136
|
+
{
|
|
1137
|
+
t: 1.7,
|
|
1138
|
+
type: "phase",
|
|
1139
|
+
data: {
|
|
1140
|
+
label: "pose_clip.grab_bite.phase.pounce"
|
|
1141
|
+
}
|
|
1142
|
+
},
|
|
1143
|
+
{
|
|
1144
|
+
t: 2.1,
|
|
1145
|
+
type: "phase",
|
|
1146
|
+
data: {
|
|
1147
|
+
label: "pose_clip.grab_bite.phase.grab"
|
|
1148
|
+
}
|
|
1149
|
+
},
|
|
1150
|
+
{
|
|
1151
|
+
t: 4.3,
|
|
1152
|
+
type: "phase",
|
|
1153
|
+
data: {
|
|
1154
|
+
label: "pose_clip.grab_bite.phase.bite"
|
|
1155
|
+
}
|
|
1156
|
+
},
|
|
1157
|
+
{
|
|
1158
|
+
t: 5.6,
|
|
1159
|
+
type: "phase",
|
|
1160
|
+
data: {
|
|
1161
|
+
label: "pose_clip.grab_bite.phase.fall"
|
|
1162
|
+
}
|
|
1163
|
+
},
|
|
1164
|
+
{
|
|
1165
|
+
t: 4.4,
|
|
1166
|
+
type: "impact",
|
|
1167
|
+
data: {
|
|
1168
|
+
kind: "bite",
|
|
1169
|
+
source: "bite.visible=T>4.4 in the scene's step()"
|
|
1170
|
+
}
|
|
1171
|
+
}
|
|
1172
|
+
]
|
|
1173
|
+
},
|
|
1174
|
+
{
|
|
1175
|
+
id: "grab_bite_zombie",
|
|
1176
|
+
source: {
|
|
1177
|
+
file: "site/pages/zumbis-personagens/bestiario.html",
|
|
1178
|
+
scene: "ataque (Agarr\xE3o e mordida)",
|
|
1179
|
+
variable: "ZK"
|
|
1180
|
+
},
|
|
1181
|
+
duration: 8,
|
|
1182
|
+
loop: false,
|
|
1183
|
+
channels: "full",
|
|
1184
|
+
keys: [
|
|
1185
|
+
{
|
|
1186
|
+
t: 0,
|
|
1187
|
+
pose: {
|
|
1188
|
+
x: -6,
|
|
1189
|
+
lean: 0.75,
|
|
1190
|
+
armL: -1.35,
|
|
1191
|
+
armR: -1.05,
|
|
1192
|
+
elbL: -0.08,
|
|
1193
|
+
elbR: -0.12,
|
|
1194
|
+
headX: -0.55,
|
|
1195
|
+
drop: -0.1,
|
|
1196
|
+
run: 1
|
|
1197
|
+
}
|
|
1198
|
+
},
|
|
1199
|
+
{
|
|
1200
|
+
t: 1.7,
|
|
1201
|
+
pose: {
|
|
1202
|
+
x: -0.9,
|
|
1203
|
+
lean: 0.75,
|
|
1204
|
+
armL: -1.35,
|
|
1205
|
+
armR: -1.05,
|
|
1206
|
+
elbL: -0.08,
|
|
1207
|
+
elbR: -0.12,
|
|
1208
|
+
headX: -0.55,
|
|
1209
|
+
drop: -0.1,
|
|
1210
|
+
run: 1
|
|
1211
|
+
}
|
|
1212
|
+
},
|
|
1213
|
+
{
|
|
1214
|
+
t: 2.1,
|
|
1215
|
+
pose: {
|
|
1216
|
+
x: -0.32,
|
|
1217
|
+
lean: 0.45,
|
|
1218
|
+
armL: -1.65,
|
|
1219
|
+
armR: -1.6,
|
|
1220
|
+
elbL: -0.25,
|
|
1221
|
+
elbR: -0.3,
|
|
1222
|
+
headX: -0.3,
|
|
1223
|
+
drop: -0.08,
|
|
1224
|
+
legL: -0.6,
|
|
1225
|
+
legR: 0.4,
|
|
1226
|
+
kneeL: 0.5,
|
|
1227
|
+
kneeR: 0.6,
|
|
1228
|
+
run: 0
|
|
1229
|
+
}
|
|
1230
|
+
},
|
|
1231
|
+
{
|
|
1232
|
+
t: 3.6,
|
|
1233
|
+
pose: {
|
|
1234
|
+
x: -0.2,
|
|
1235
|
+
lean: 0.35,
|
|
1236
|
+
armL: -1.5,
|
|
1237
|
+
armR: -1.45,
|
|
1238
|
+
elbL: -1.1,
|
|
1239
|
+
elbR: -1.2,
|
|
1240
|
+
headX: -0.2,
|
|
1241
|
+
drop: -0.06,
|
|
1242
|
+
legL: -0.4,
|
|
1243
|
+
legR: 0.3,
|
|
1244
|
+
kneeL: 0.4,
|
|
1245
|
+
kneeR: 0.4,
|
|
1246
|
+
run: 0
|
|
1247
|
+
}
|
|
1248
|
+
},
|
|
1249
|
+
{
|
|
1250
|
+
t: 4.3,
|
|
1251
|
+
pose: {
|
|
1252
|
+
x: -0.1,
|
|
1253
|
+
lean: 0.5,
|
|
1254
|
+
armL: -1.4,
|
|
1255
|
+
armR: -1.3,
|
|
1256
|
+
elbL: -1.5,
|
|
1257
|
+
elbR: -1.5,
|
|
1258
|
+
headX: 0.35,
|
|
1259
|
+
headY: 0.35,
|
|
1260
|
+
drop: -0.08,
|
|
1261
|
+
legL: -0.35,
|
|
1262
|
+
legR: 0.3,
|
|
1263
|
+
kneeL: 0.4,
|
|
1264
|
+
kneeR: 0.4,
|
|
1265
|
+
run: 0
|
|
1266
|
+
}
|
|
1267
|
+
},
|
|
1268
|
+
{
|
|
1269
|
+
t: 5.6,
|
|
1270
|
+
pose: {
|
|
1271
|
+
x: 0,
|
|
1272
|
+
lean: 0.95,
|
|
1273
|
+
armL: -1.2,
|
|
1274
|
+
armR: -1,
|
|
1275
|
+
elbL: -1.4,
|
|
1276
|
+
elbR: -1.3,
|
|
1277
|
+
headX: 0.5,
|
|
1278
|
+
headY: 0.3,
|
|
1279
|
+
drop: -0.45,
|
|
1280
|
+
legL: -1.2,
|
|
1281
|
+
legR: -0.8,
|
|
1282
|
+
kneeL: 1.8,
|
|
1283
|
+
kneeR: 1.5,
|
|
1284
|
+
run: 0
|
|
1285
|
+
}
|
|
1286
|
+
},
|
|
1287
|
+
{
|
|
1288
|
+
t: 8,
|
|
1289
|
+
pose: {
|
|
1290
|
+
x: 0,
|
|
1291
|
+
lean: 1,
|
|
1292
|
+
armL: -1.15,
|
|
1293
|
+
armR: -0.95,
|
|
1294
|
+
elbL: -1.4,
|
|
1295
|
+
elbR: -1.3,
|
|
1296
|
+
headX: 0.55,
|
|
1297
|
+
headY: 0.3,
|
|
1298
|
+
drop: -0.47,
|
|
1299
|
+
legL: -1.2,
|
|
1300
|
+
legR: -0.8,
|
|
1301
|
+
kneeL: 1.85,
|
|
1302
|
+
kneeR: 1.5,
|
|
1303
|
+
run: 0
|
|
1304
|
+
}
|
|
1305
|
+
}
|
|
1306
|
+
],
|
|
1307
|
+
events: [
|
|
1308
|
+
{
|
|
1309
|
+
t: 0,
|
|
1310
|
+
type: "phase",
|
|
1311
|
+
data: {
|
|
1312
|
+
label: "pose_clip.grab_bite.phase.approach"
|
|
1313
|
+
}
|
|
1314
|
+
},
|
|
1315
|
+
{
|
|
1316
|
+
t: 1.7,
|
|
1317
|
+
type: "phase",
|
|
1318
|
+
data: {
|
|
1319
|
+
label: "pose_clip.grab_bite.phase.pounce"
|
|
1320
|
+
}
|
|
1321
|
+
},
|
|
1322
|
+
{
|
|
1323
|
+
t: 2.1,
|
|
1324
|
+
type: "phase",
|
|
1325
|
+
data: {
|
|
1326
|
+
label: "pose_clip.grab_bite.phase.grab"
|
|
1327
|
+
}
|
|
1328
|
+
},
|
|
1329
|
+
{
|
|
1330
|
+
t: 4.3,
|
|
1331
|
+
type: "phase",
|
|
1332
|
+
data: {
|
|
1333
|
+
label: "pose_clip.grab_bite.phase.bite"
|
|
1334
|
+
}
|
|
1335
|
+
},
|
|
1336
|
+
{
|
|
1337
|
+
t: 5.6,
|
|
1338
|
+
type: "phase",
|
|
1339
|
+
data: {
|
|
1340
|
+
label: "pose_clip.grab_bite.phase.fall"
|
|
1341
|
+
}
|
|
1342
|
+
}
|
|
1343
|
+
]
|
|
1344
|
+
}
|
|
1345
|
+
],
|
|
1346
|
+
locales: {
|
|
1347
|
+
"pt-BR": {
|
|
1348
|
+
"pose_clip.grab_bite.phase.approach": "1. Aproxima\xE7\xE3o",
|
|
1349
|
+
"pose_clip.grab_bite.phase.pounce": "2. O bote",
|
|
1350
|
+
"pose_clip.grab_bite.phase.grab": "3. Agarr\xE3o: 3 s para se soltar",
|
|
1351
|
+
"pose_clip.grab_bite.phase.bite": "4. Mordida: infec\xE7\xE3o 100%",
|
|
1352
|
+
"pose_clip.grab_bite.phase.fall": "5. Queda"
|
|
1353
|
+
},
|
|
1354
|
+
en: {
|
|
1355
|
+
"pose_clip.grab_bite.phase.approach": "1. Approach",
|
|
1356
|
+
"pose_clip.grab_bite.phase.pounce": "2. The pounce",
|
|
1357
|
+
"pose_clip.grab_bite.phase.grab": "3. Grab: 3 s to break free",
|
|
1358
|
+
"pose_clip.grab_bite.phase.bite": "4. Bite: 100% infection",
|
|
1359
|
+
"pose_clip.grab_bite.phase.fall": "5. The fall"
|
|
1360
|
+
}
|
|
1361
|
+
}
|
|
1362
|
+
};
|
|
1363
|
+
var POSE_CLIPS = pose_clips_default.clips;
|
|
1364
|
+
var POSE_CLIP_LOCALES = pose_clips_default.locales;
|
|
992
1365
|
|
|
993
1366
|
// ../game-crowd/dist/index.js
|
|
994
1367
|
var defaults_default = {
|
|
@@ -1082,29 +1455,29 @@ var GameCrowdThree = (() => {
|
|
|
1082
1455
|
function createDoors(grid, options) {
|
|
1083
1456
|
const N = { ...DOOR_DEFAULTS, ...options.numbers };
|
|
1084
1457
|
const random = options.random;
|
|
1085
|
-
const
|
|
1458
|
+
const list2 = [];
|
|
1086
1459
|
const doorAt = new Int16Array(grid.n * grid.n).fill(-1);
|
|
1087
1460
|
const listeners = /* @__PURE__ */ new Map();
|
|
1088
1461
|
const emit = (event, payload) => {
|
|
1089
1462
|
for (const listener of listeners.get(event) ?? []) listener(payload);
|
|
1090
1463
|
};
|
|
1091
1464
|
const set = (index, open) => {
|
|
1092
|
-
const d =
|
|
1465
|
+
const d = list2[index];
|
|
1093
1466
|
if (!d) return;
|
|
1094
1467
|
d.open = open;
|
|
1095
1468
|
grid.fillRect(...d.rect, open || d.broken ? 3 : 5, N.height);
|
|
1096
1469
|
};
|
|
1097
1470
|
return {
|
|
1098
|
-
list,
|
|
1471
|
+
list: list2,
|
|
1099
1472
|
at: (cell) => cell < 0 ? -1 : doorAt[cell],
|
|
1100
1473
|
add(x, z, axis, width, data) {
|
|
1101
|
-
const i =
|
|
1474
|
+
const i = list2.length;
|
|
1102
1475
|
const t = N.thickness;
|
|
1103
1476
|
const x0 = axis === "x" ? x - width / 2 : x - t;
|
|
1104
1477
|
const x1 = axis === "x" ? x + width / 2 : x + t;
|
|
1105
1478
|
const z0 = axis === "x" ? z - t : z - width / 2;
|
|
1106
1479
|
const z1 = axis === "x" ? z + t : z + width / 2;
|
|
1107
|
-
|
|
1480
|
+
list2.push({ x, z, axis, width, hp: N.doorHp, hpMax: N.doorHp, open: false, broken: false, planks: 0, rect: [x0, z0, x1, z1], data });
|
|
1108
1481
|
grid.fillRect(x0, z0, x1, z1, 5, N.height);
|
|
1109
1482
|
const a = Math.floor((x0 + grid.half) / grid.cell);
|
|
1110
1483
|
const b = Math.ceil((x1 + grid.half) / grid.cell);
|
|
@@ -1115,7 +1488,7 @@ var GameCrowdThree = (() => {
|
|
|
1115
1488
|
},
|
|
1116
1489
|
set,
|
|
1117
1490
|
hit(index, damage) {
|
|
1118
|
-
const d =
|
|
1491
|
+
const d = list2[index];
|
|
1119
1492
|
if (!d || d.open || d.broken) return;
|
|
1120
1493
|
d.hp -= damage;
|
|
1121
1494
|
if (random() < N.soundChance) emit("sound", { sound: "wood", volume: N.soundVolume, position: [d.x, 1, d.z] });
|
|
@@ -1131,7 +1504,7 @@ var GameCrowdThree = (() => {
|
|
|
1131
1504
|
}
|
|
1132
1505
|
},
|
|
1133
1506
|
plank(index) {
|
|
1134
|
-
const d =
|
|
1507
|
+
const d = list2[index];
|
|
1135
1508
|
if (!d) return;
|
|
1136
1509
|
d.planks += 1;
|
|
1137
1510
|
d.hp += N.plankHp;
|
|
@@ -1366,8 +1739,8 @@ var GameCrowdThree = (() => {
|
|
|
1366
1739
|
function createCrowd(options) {
|
|
1367
1740
|
const random = options.random ?? createRng(options.seed ?? 1);
|
|
1368
1741
|
const R = random;
|
|
1369
|
-
const
|
|
1370
|
-
const types =
|
|
1742
|
+
const pack2 = options.pack;
|
|
1743
|
+
const types = pack2.types;
|
|
1371
1744
|
const N = { ...CROWD_DEFAULTS.numbers, ...options.numbers };
|
|
1372
1745
|
const BANDS = options.bands ?? CROWD_DEFAULTS.bands;
|
|
1373
1746
|
const HYST = N.hysteresis;
|
|
@@ -1411,14 +1784,14 @@ var GameCrowdThree = (() => {
|
|
|
1411
1784
|
{
|
|
1412
1785
|
let next = 0;
|
|
1413
1786
|
types.forEach((type) => {
|
|
1414
|
-
const
|
|
1415
|
-
for (let v = 0; v < (type.variants ?? 1); v++)
|
|
1416
|
-
variantsOf.push(
|
|
1787
|
+
const list2 = [];
|
|
1788
|
+
for (let v = 0; v < (type.variants ?? 1); v++) list2.push(next++);
|
|
1789
|
+
variantsOf.push(list2);
|
|
1417
1790
|
});
|
|
1418
1791
|
}
|
|
1419
1792
|
const typeIndexById = new Map(types.map((type, index) => [type.id, index]));
|
|
1420
1793
|
const noises = [];
|
|
1421
|
-
const
|
|
1794
|
+
const stats2 = { bands: [0, 0, 0, 0], slots: 0, kills: 0, heads: 0 };
|
|
1422
1795
|
const corpses = createCorpseLedger({ max: N.corpsesMax, seconds: N.corpseSeconds });
|
|
1423
1796
|
const trail = [];
|
|
1424
1797
|
let trailLast = { x: 1e9, z: 1e9 };
|
|
@@ -1443,14 +1816,14 @@ var GameCrowdThree = (() => {
|
|
|
1443
1816
|
if (target && Math.hypot(d.x - target.state.x, d.z - target.state.z) < N.doorMessageDistance) emit("message", { id: "door_broken", seconds: 2 });
|
|
1444
1817
|
});
|
|
1445
1818
|
const sound = (id, volume, x, y, z, d) => emit("sound", { sound: id, volume, position: [x, y, z], distance: d });
|
|
1446
|
-
const pick = (
|
|
1819
|
+
const pick = (list2) => {
|
|
1447
1820
|
const r = R();
|
|
1448
1821
|
let acc = 0;
|
|
1449
|
-
for (const it of
|
|
1822
|
+
for (const it of list2) {
|
|
1450
1823
|
acc += it.p;
|
|
1451
1824
|
if (r < acc) return it;
|
|
1452
1825
|
}
|
|
1453
|
-
return
|
|
1826
|
+
return list2[0];
|
|
1454
1827
|
};
|
|
1455
1828
|
const T = (i) => types[Z.type[i]];
|
|
1456
1829
|
const traits = (i) => T(i).traits ?? {};
|
|
@@ -1486,16 +1859,16 @@ var GameCrowdThree = (() => {
|
|
|
1486
1859
|
const i = Z.n++;
|
|
1487
1860
|
const c = catForce >= 0 ? catForce : catTable[Math.floor(R() * catTable.length)];
|
|
1488
1861
|
const C = types[c];
|
|
1489
|
-
const ai =
|
|
1862
|
+
const ai = pack2.ages.indexOf(pick(pack2.ages));
|
|
1490
1863
|
const maxAge = C.traits?.maxAge;
|
|
1491
|
-
const A =
|
|
1492
|
-
const ri =
|
|
1493
|
-
const RO =
|
|
1864
|
+
const A = pack2.ages[maxAge !== void 0 ? Math.min(ai, maxAge) : ai];
|
|
1865
|
+
const ri = pack2.outfits.indexOf(pick(pack2.outfits));
|
|
1866
|
+
const RO = pack2.outfits[ri];
|
|
1494
1867
|
Z.x[i] = x;
|
|
1495
1868
|
Z.z[i] = z;
|
|
1496
1869
|
Z.vx[i] = Z.vz[i] = 0;
|
|
1497
1870
|
Z.type[i] = c;
|
|
1498
|
-
Z.age[i] =
|
|
1871
|
+
Z.age[i] = pack2.ages.indexOf(A);
|
|
1499
1872
|
Z.outfit[i] = ri;
|
|
1500
1873
|
const g = (R() + R() + R() - 1.5) * 0.09;
|
|
1501
1874
|
Z.height[i] = clamp(1 + g, 0.9, 1.1) * (C.scale || 1);
|
|
@@ -1506,9 +1879,9 @@ var GameCrowdThree = (() => {
|
|
|
1506
1879
|
Z.chaseSpeed[i] = C.speed.chase * A.speed * (thin ? 1.05 : heavy ? 0.9 : 1) * (0.92 + R() * 0.16);
|
|
1507
1880
|
Z.wanderSpeed[i] = C.speed.wander * A.speed * (0.8 + R() * 0.4);
|
|
1508
1881
|
Z.hpMax[i] = Z.hp[i] = C.health * A.health * (thin ? 0.9 : heavy ? 1.15 : 1);
|
|
1509
|
-
Z.headHp[i] =
|
|
1510
|
-
Z.armHp[i * 2] = Z.armHp[i * 2 + 1] =
|
|
1511
|
-
Z.legHp[i * 2] = Z.legHp[i * 2 + 1] =
|
|
1882
|
+
Z.headHp[i] = pack2.segments.head;
|
|
1883
|
+
Z.armHp[i * 2] = Z.armHp[i * 2 + 1] = pack2.segments.arm;
|
|
1884
|
+
Z.legHp[i * 2] = Z.legHp[i * 2 + 1] = pack2.segments.leg;
|
|
1512
1885
|
Z.missing[i] = 0;
|
|
1513
1886
|
Z.helmet[i] = RO.helmet ? 1 : 0;
|
|
1514
1887
|
Z.crawl[i] = C.crawls ? 1 : 0;
|
|
@@ -1534,7 +1907,7 @@ var GameCrowdThree = (() => {
|
|
|
1534
1907
|
Z.next[i] = R() * 0.05;
|
|
1535
1908
|
Z.wx[i] = x;
|
|
1536
1909
|
Z.wz[i] = z;
|
|
1537
|
-
Z.color[i] = RO.color ||
|
|
1910
|
+
Z.color[i] = RO.color || pack2.palette[Math.floor(R() * pack2.palette.length)];
|
|
1538
1911
|
Z.skin[i] = R();
|
|
1539
1912
|
special(i);
|
|
1540
1913
|
emit("spawn", { agent: i, type: C.id });
|
|
@@ -1769,8 +2142,8 @@ var GameCrowdThree = (() => {
|
|
|
1769
2142
|
const blood = (x, y, z, age, amount, died, agent) => effect({ effect: "blood", point: [x, y, z], age, amount, died, ...agent === void 0 ? {} : { agent } });
|
|
1770
2143
|
const damage = (i, hit) => {
|
|
1771
2144
|
const C = T(i);
|
|
1772
|
-
const A =
|
|
1773
|
-
const RO =
|
|
2145
|
+
const A = pack2.ages[Z.age[i]];
|
|
2146
|
+
const RO = pack2.outfits[Z.outfit[i]];
|
|
1774
2147
|
const cal = hit.caliber ?? null;
|
|
1775
2148
|
const proj = !!cal;
|
|
1776
2149
|
const dano = hit.amount;
|
|
@@ -1808,7 +2181,7 @@ var GameCrowdThree = (() => {
|
|
|
1808
2181
|
const k = i * 2 + (perna ? lado : regiao === 3 ? 1 : 0);
|
|
1809
2182
|
segArr[k] -= dano * mm;
|
|
1810
2183
|
Z.hp[i] -= dano * mm * 0.5;
|
|
1811
|
-
const max = perna ?
|
|
2184
|
+
const max = perna ? pack2.segments.leg : pack2.segments.arm;
|
|
1812
2185
|
if (perna && segArr[k] <= max * 0.5) Z.limp[i] = 1;
|
|
1813
2186
|
if (segArr[k] <= 0) {
|
|
1814
2187
|
const arranca = corte >= 0.5 || dano * mm > max * 0.9;
|
|
@@ -1842,8 +2215,8 @@ var GameCrowdThree = (() => {
|
|
|
1842
2215
|
return { died: morreu };
|
|
1843
2216
|
};
|
|
1844
2217
|
function kill(i, headshot = false) {
|
|
1845
|
-
|
|
1846
|
-
if (headshot)
|
|
2218
|
+
stats2.kills++;
|
|
2219
|
+
if (headshot) stats2.heads++;
|
|
1847
2220
|
const tr = traits(i);
|
|
1848
2221
|
if (tr.burst) burstAt(i, Z.x[i], Z.z[i]);
|
|
1849
2222
|
const C = T(i);
|
|
@@ -1946,9 +2319,9 @@ var GameCrowdThree = (() => {
|
|
|
1946
2319
|
if (Z.stateTimer[i] <= 0) {
|
|
1947
2320
|
let best = -1;
|
|
1948
2321
|
let bd = ec2.grabRange;
|
|
1949
|
-
const
|
|
1950
|
-
for (let k = 0; k <
|
|
1951
|
-
const e = Math.hypot(
|
|
2322
|
+
const list2 = corpses.entries;
|
|
2323
|
+
for (let k = 0; k < list2.length; k++) {
|
|
2324
|
+
const e = Math.hypot(list2[k].data.x - Z.x[i], list2[k].data.z - Z.z[i]);
|
|
1952
2325
|
if (e < bd) {
|
|
1953
2326
|
bd = e;
|
|
1954
2327
|
best = k;
|
|
@@ -2032,9 +2405,9 @@ var GameCrowdThree = (() => {
|
|
|
2032
2405
|
if (ec && st === 0 && Z.eaten[i] < ec.max && Z.abilityTimer[i] <= 0 && corpses.count) {
|
|
2033
2406
|
let best = -1;
|
|
2034
2407
|
let bd = ec.search;
|
|
2035
|
-
const
|
|
2036
|
-
for (let k = 0; k <
|
|
2037
|
-
const e = Math.hypot(
|
|
2408
|
+
const list2 = corpses.entries;
|
|
2409
|
+
for (let k = 0; k < list2.length; k++) {
|
|
2410
|
+
const e = Math.hypot(list2[k].data.x - Z.x[i], list2[k].data.z - Z.z[i]);
|
|
2038
2411
|
if (e < bd) {
|
|
2039
2412
|
bd = e;
|
|
2040
2413
|
best = k;
|
|
@@ -2047,7 +2420,7 @@ var GameCrowdThree = (() => {
|
|
|
2047
2420
|
Z.vx[i] = Z.vz[i] = 0;
|
|
2048
2421
|
return true;
|
|
2049
2422
|
}
|
|
2050
|
-
const cp =
|
|
2423
|
+
const cp = list2[best].data;
|
|
2051
2424
|
const ex = cp.x - Z.x[i];
|
|
2052
2425
|
const ez = cp.z - Z.z[i];
|
|
2053
2426
|
const sp = Z.wanderSpeed[i] * ec.approach;
|
|
@@ -2179,7 +2552,7 @@ var GameCrowdThree = (() => {
|
|
|
2179
2552
|
hNext[i] = hHead[h];
|
|
2180
2553
|
hHead[h] = i;
|
|
2181
2554
|
}
|
|
2182
|
-
const B =
|
|
2555
|
+
const B = stats2.bands;
|
|
2183
2556
|
B[0] = B[1] = B[2] = B[3] = 0;
|
|
2184
2557
|
let slots = 0;
|
|
2185
2558
|
const F = flow.dir;
|
|
@@ -2223,13 +2596,13 @@ var GameCrowdThree = (() => {
|
|
|
2223
2596
|
Z.next[i] += tdt;
|
|
2224
2597
|
if (alive && b <= 1 && Z.state[i] <= 1) {
|
|
2225
2598
|
let sees = false;
|
|
2226
|
-
const A =
|
|
2599
|
+
const A = pack2.ages[Z.age[i]];
|
|
2227
2600
|
const vis = C.perception.sight * (1 - N.nightSight * nightF) * (P.state.crouch ? N.crouchSight : 1) * A.sight;
|
|
2228
2601
|
if (d < vis) {
|
|
2229
2602
|
const fx = Math.sin(Z.yaw[i]);
|
|
2230
2603
|
const fz = Math.cos(Z.yaw[i]);
|
|
2231
|
-
const
|
|
2232
|
-
if ((
|
|
2604
|
+
const cone2 = (-dx * fx - dz * fz) / (d || 1);
|
|
2605
|
+
if ((cone2 > N.sightCone || d < N.sightNear) && (Z.floor[i] === P.state.floor || d < 5) && (Z.floor[i] || P.state.floor || losClear(Z.x[i], Z.z[i], px, pz))) sees = true;
|
|
2233
2606
|
}
|
|
2234
2607
|
if (C.perception.smell && d < C.perception.smell * (P.state.bleeding || P.state.scentTimer > 0 ? 2 : 1)) sees = true;
|
|
2235
2608
|
if (sees) {
|
|
@@ -2247,7 +2620,7 @@ var GameCrowdThree = (() => {
|
|
|
2247
2620
|
}
|
|
2248
2621
|
for (let k = 0; k < noises.length && (Z.state[i] === 0 || Z.state[i] === STATE.SEEKING_SOUND); k++) {
|
|
2249
2622
|
const Nz = noises[k];
|
|
2250
|
-
const hear = Nz.r * (C.perception.hearing / N.hearingBase) *
|
|
2623
|
+
const hear = Nz.r * (C.perception.hearing / N.hearingBase) * pack2.ages[Z.age[i]].hearing;
|
|
2251
2624
|
if ((Z.x[i] - Nz.x) ** 2 + (Z.z[i] - Nz.z) ** 2 < hear * hear) {
|
|
2252
2625
|
if (tr.soundSeeker) {
|
|
2253
2626
|
Z.state[i] = STATE.SEEKING_SOUND;
|
|
@@ -2415,7 +2788,7 @@ var GameCrowdThree = (() => {
|
|
|
2415
2788
|
}
|
|
2416
2789
|
killQFlush();
|
|
2417
2790
|
noises.length = 0;
|
|
2418
|
-
|
|
2791
|
+
stats2.slots = slots;
|
|
2419
2792
|
};
|
|
2420
2793
|
const updateTrail = (dt, who = target) => {
|
|
2421
2794
|
for (const p2 of trail) p2.t += dt;
|
|
@@ -2478,12 +2851,12 @@ var GameCrowdThree = (() => {
|
|
|
2478
2851
|
};
|
|
2479
2852
|
const crowd = {
|
|
2480
2853
|
store: Z,
|
|
2481
|
-
pack,
|
|
2854
|
+
pack: pack2,
|
|
2482
2855
|
grid,
|
|
2483
2856
|
doors,
|
|
2484
2857
|
corpses,
|
|
2485
2858
|
numbers: N,
|
|
2486
|
-
stats,
|
|
2859
|
+
stats: stats2,
|
|
2487
2860
|
pile,
|
|
2488
2861
|
pileCount: () => pileN,
|
|
2489
2862
|
trail,
|
|
@@ -2629,7 +3002,7 @@ var GameCrowdThree = (() => {
|
|
|
2629
3002
|
if (Math.sign(a[a.length - 1][1]) !== Math.sign(b[0][1])) out.push([a[a.length - 1][0], b[0][1]]);
|
|
2630
3003
|
return out.concat(b);
|
|
2631
3004
|
};
|
|
2632
|
-
const
|
|
3005
|
+
const list2 = options.people.map((spec, k) => {
|
|
2633
3006
|
const b = casaDe(spec.home);
|
|
2634
3007
|
const p2 = pontos(b)[0];
|
|
2635
3008
|
return {
|
|
@@ -2654,7 +3027,7 @@ var GameCrowdThree = (() => {
|
|
|
2654
3027
|
agent: -1
|
|
2655
3028
|
};
|
|
2656
3029
|
});
|
|
2657
|
-
const byId = new Map(
|
|
3030
|
+
const byId = new Map(list2.map((c) => [c.id, c]));
|
|
2658
3031
|
const exposed = (n) => n.state !== "dead" && n.state !== "undead" && n.state !== "gone";
|
|
2659
3032
|
const target = () => crowd.target?.state ?? null;
|
|
2660
3033
|
const distToTarget = (x, z) => {
|
|
@@ -2701,7 +3074,7 @@ var GameCrowdThree = (() => {
|
|
|
2701
3074
|
if (Z.band[i] > 1) continue;
|
|
2702
3075
|
const k = Z.hunts[i];
|
|
2703
3076
|
if (k >= 0) {
|
|
2704
|
-
const n =
|
|
3077
|
+
const n = list2[k];
|
|
2705
3078
|
if (!exposed(n)) {
|
|
2706
3079
|
Z.hunts[i] = -1;
|
|
2707
3080
|
continue;
|
|
@@ -2730,7 +3103,7 @@ var GameCrowdThree = (() => {
|
|
|
2730
3103
|
}
|
|
2731
3104
|
}
|
|
2732
3105
|
} else if (Z.state[i] <= 1) {
|
|
2733
|
-
for (const n of
|
|
3106
|
+
for (const n of list2) {
|
|
2734
3107
|
if (!exposed(n) || n.state === "home") continue;
|
|
2735
3108
|
const dx = n.x - Z.x[i];
|
|
2736
3109
|
const dz = n.z - Z.z[i];
|
|
@@ -2746,7 +3119,7 @@ var GameCrowdThree = (() => {
|
|
|
2746
3119
|
}
|
|
2747
3120
|
};
|
|
2748
3121
|
crowd.setHunt((i) => {
|
|
2749
|
-
const n =
|
|
3122
|
+
const n = list2[Z.hunts[i]];
|
|
2750
3123
|
if (!n) return false;
|
|
2751
3124
|
const dx = n.x - Z.x[i];
|
|
2752
3125
|
const dz = n.z - Z.z[i];
|
|
@@ -2800,7 +3173,7 @@ var GameCrowdThree = (() => {
|
|
|
2800
3173
|
agentsAgainst(dt);
|
|
2801
3174
|
const h = hourNow();
|
|
2802
3175
|
const t = target();
|
|
2803
|
-
for (const n of
|
|
3176
|
+
for (const n of list2) {
|
|
2804
3177
|
if (n.state === "dead" || n.state === "undead" || n.state === "gone") continue;
|
|
2805
3178
|
if (n.biteTimer > 0) {
|
|
2806
3179
|
n.biteTimer -= dt;
|
|
@@ -2873,7 +3246,7 @@ var GameCrowdThree = (() => {
|
|
|
2873
3246
|
}
|
|
2874
3247
|
for (let i = 0; i < Z.n; i++)
|
|
2875
3248
|
if (Z.named[i] >= 0 && Z.state[i] === STATE.WANDER && R() < dt * N.patrolChance) {
|
|
2876
|
-
const n =
|
|
3249
|
+
const n = list2[Z.named[i]];
|
|
2877
3250
|
if (!n) continue;
|
|
2878
3251
|
const p2 = pontos(casaDe(n.spec.home));
|
|
2879
3252
|
const q = p2[Math.floor(R() * p2.length)];
|
|
@@ -2882,7 +3255,7 @@ var GameCrowdThree = (() => {
|
|
|
2882
3255
|
}
|
|
2883
3256
|
};
|
|
2884
3257
|
return {
|
|
2885
|
-
list,
|
|
3258
|
+
list: list2,
|
|
2886
3259
|
get: (id) => byId.get(id),
|
|
2887
3260
|
update,
|
|
2888
3261
|
join(id) {
|
|
@@ -2949,7 +3322,7 @@ var GameCrowdThree = (() => {
|
|
|
2949
3322
|
const R = crowd.random;
|
|
2950
3323
|
const Z = crowd.store;
|
|
2951
3324
|
const grid = crowd.grid;
|
|
2952
|
-
const
|
|
3325
|
+
const list2 = [];
|
|
2953
3326
|
let time = 0;
|
|
2954
3327
|
const listeners = /* @__PURE__ */ new Map();
|
|
2955
3328
|
const emit = (event, payload) => {
|
|
@@ -2992,7 +3365,7 @@ var GameCrowdThree = (() => {
|
|
|
2992
3365
|
const px = t?.x ?? 0;
|
|
2993
3366
|
const pz = t?.z ?? 0;
|
|
2994
3367
|
const v = view();
|
|
2995
|
-
for (const E of
|
|
3368
|
+
for (const E of list2) {
|
|
2996
3369
|
if (E.spec.sky) continue;
|
|
2997
3370
|
const dc = Math.hypot(E.x - v.x, E.z - v.z);
|
|
2998
3371
|
if (dc >= N.activeDistance || E.dead) continue;
|
|
@@ -3093,10 +3466,10 @@ var GameCrowdThree = (() => {
|
|
|
3093
3466
|
}
|
|
3094
3467
|
};
|
|
3095
3468
|
return {
|
|
3096
|
-
list,
|
|
3469
|
+
list: list2,
|
|
3097
3470
|
add(spec) {
|
|
3098
3471
|
const E = {
|
|
3099
|
-
index:
|
|
3472
|
+
index: list2.length,
|
|
3100
3473
|
spec,
|
|
3101
3474
|
x: spec.x,
|
|
3102
3475
|
z: spec.z,
|
|
@@ -3117,7 +3490,7 @@ var GameCrowdThree = (() => {
|
|
|
3117
3490
|
dead: !!spec.dead,
|
|
3118
3491
|
near: void 0
|
|
3119
3492
|
};
|
|
3120
|
-
|
|
3493
|
+
list2.push(E);
|
|
3121
3494
|
return E;
|
|
3122
3495
|
},
|
|
3123
3496
|
free,
|
|
@@ -3126,7 +3499,7 @@ var GameCrowdThree = (() => {
|
|
|
3126
3499
|
return time;
|
|
3127
3500
|
},
|
|
3128
3501
|
setCompanion(index, on) {
|
|
3129
|
-
const E =
|
|
3502
|
+
const E = list2[index];
|
|
3130
3503
|
if (!E) return;
|
|
3131
3504
|
E.companion = on;
|
|
3132
3505
|
E.homeX = E.x;
|
|
@@ -3230,16 +3603,16 @@ var GameCrowdThree = (() => {
|
|
|
3230
3603
|
const entry = tracked.get(i);
|
|
3231
3604
|
if (!entry || region !== void 0 && entry.region !== region) continue;
|
|
3232
3605
|
if (!opts.all && crowd.store.band[i] < band) continue;
|
|
3233
|
-
let
|
|
3234
|
-
if (!
|
|
3235
|
-
|
|
3606
|
+
let list2 = byRegion.get(entry.region);
|
|
3607
|
+
if (!list2) byRegion.set(entry.region, list2 = []);
|
|
3608
|
+
list2.push({ state: entry.state, seed: entry.seed });
|
|
3236
3609
|
tracked.delete(i);
|
|
3237
3610
|
crowd.remove(i);
|
|
3238
3611
|
}
|
|
3239
3612
|
let count = 0;
|
|
3240
|
-
for (const [r,
|
|
3241
|
-
model.giveBack(r,
|
|
3242
|
-
count +=
|
|
3613
|
+
for (const [r, list2] of byRegion) {
|
|
3614
|
+
model.giveBack(r, list2);
|
|
3615
|
+
count += list2.length;
|
|
3243
3616
|
}
|
|
3244
3617
|
return count;
|
|
3245
3618
|
},
|
|
@@ -3398,8 +3771,8 @@ var GameCrowdThree = (() => {
|
|
|
3398
3771
|
plain({ a: [C.x, C.z, C.yaw, C.seed], b: [C.height * fade, C.build, Math.min(1, t * N.corpseRise), pose.corpse], c, color: C.color, shade, eye: null, y: 0 });
|
|
3399
3772
|
}
|
|
3400
3773
|
},
|
|
3401
|
-
civilians(
|
|
3402
|
-
for (const n of
|
|
3774
|
+
civilians(list2, colorOf, sink) {
|
|
3775
|
+
for (const n of list2) {
|
|
3403
3776
|
if (n.state === "undead" || n.state === "gone" || n.state === "dead") continue;
|
|
3404
3777
|
const sp = Math.hypot(n.vx, n.vz);
|
|
3405
3778
|
const child = !!n.spec.child;
|
|
@@ -3417,6 +3790,1523 @@ var GameCrowdThree = (() => {
|
|
|
3417
3790
|
};
|
|
3418
3791
|
}
|
|
3419
3792
|
|
|
3793
|
+
// ../game-shapes/dist/chunk-R4RY23RH.js
|
|
3794
|
+
function canonicalJson(value) {
|
|
3795
|
+
if (value === null) return "null";
|
|
3796
|
+
if (typeof value === "number") return Object.is(value, -0) ? "-0" : Number.isFinite(value) ? String(value) : JSON.stringify(String(value));
|
|
3797
|
+
if (typeof value === "string") return JSON.stringify(value);
|
|
3798
|
+
if (typeof value === "boolean") return value ? "true" : "false";
|
|
3799
|
+
if (typeof value === "function") throw new Error("game-shapes: a function cannot be part of a shape (register it as a generator)");
|
|
3800
|
+
if (ArrayBuffer.isView(value)) return canonicalJson(Array.from(value));
|
|
3801
|
+
if (Array.isArray(value)) return `[${value.map((item) => item === void 0 ? "null" : canonicalJson(item)).join(",")}]`;
|
|
3802
|
+
if (typeof value === "object") {
|
|
3803
|
+
const record = value;
|
|
3804
|
+
const keys = Object.keys(record).filter((key) => record[key] !== void 0).sort();
|
|
3805
|
+
return `{${keys.map((key) => `${JSON.stringify(key)}:${canonicalJson(record[key])}`).join(",")}}`;
|
|
3806
|
+
}
|
|
3807
|
+
return "null";
|
|
3808
|
+
}
|
|
3809
|
+
function needsUint32(array) {
|
|
3810
|
+
for (let i = array.length - 1; i >= 0; --i) if (array[i] >= 65535) return true;
|
|
3811
|
+
return false;
|
|
3812
|
+
}
|
|
3813
|
+
var indexArray = (indices) => needsUint32(indices) ? new Uint32Array(indices) : new Uint16Array(indices);
|
|
3814
|
+
function pack(type, parameters, a) {
|
|
3815
|
+
return {
|
|
3816
|
+
type,
|
|
3817
|
+
parameters,
|
|
3818
|
+
positions: new Float32Array(a.vertices),
|
|
3819
|
+
normals: new Float32Array(a.normals),
|
|
3820
|
+
uvs: new Float32Array(a.uvs),
|
|
3821
|
+
...a.indices ? { indices: indexArray(a.indices) } : {},
|
|
3822
|
+
groups: a.groups
|
|
3823
|
+
};
|
|
3824
|
+
}
|
|
3825
|
+
var normalize3 = (x, y, z) => {
|
|
3826
|
+
const length = Math.sqrt(x * x + y * y + z * z);
|
|
3827
|
+
const s = 1 / (length || 1);
|
|
3828
|
+
return [x * s, y * s, z * s];
|
|
3829
|
+
};
|
|
3830
|
+
function box(width = 1, height = 1, depth = 1, widthSegments = 1, heightSegments = 1, depthSegments = 1) {
|
|
3831
|
+
const parameters = { width, height, depth, widthSegments, heightSegments, depthSegments };
|
|
3832
|
+
widthSegments = Math.floor(widthSegments);
|
|
3833
|
+
heightSegments = Math.floor(heightSegments);
|
|
3834
|
+
depthSegments = Math.floor(depthSegments);
|
|
3835
|
+
const indices = [];
|
|
3836
|
+
const vertices = [];
|
|
3837
|
+
const normals = [];
|
|
3838
|
+
const uvs = [];
|
|
3839
|
+
const groups = [];
|
|
3840
|
+
let numberOfVertices = 0;
|
|
3841
|
+
let groupStart = 0;
|
|
3842
|
+
const buildPlane = (u, v, w, udir, vdir, width2, height2, depth2, gridX, gridY, materialIndex) => {
|
|
3843
|
+
const segmentWidth = width2 / gridX;
|
|
3844
|
+
const segmentHeight = height2 / gridY;
|
|
3845
|
+
const widthHalf = width2 / 2;
|
|
3846
|
+
const heightHalf = height2 / 2;
|
|
3847
|
+
const depthHalf = depth2 / 2;
|
|
3848
|
+
const gridX1 = gridX + 1;
|
|
3849
|
+
const gridY1 = gridY + 1;
|
|
3850
|
+
let vertexCounter = 0;
|
|
3851
|
+
let groupCount = 0;
|
|
3852
|
+
const vector = { x: 0, y: 0, z: 0 };
|
|
3853
|
+
for (let iy = 0; iy < gridY1; iy++) {
|
|
3854
|
+
const y = iy * segmentHeight - heightHalf;
|
|
3855
|
+
for (let ix = 0; ix < gridX1; ix++) {
|
|
3856
|
+
const x = ix * segmentWidth - widthHalf;
|
|
3857
|
+
vector[u] = x * udir;
|
|
3858
|
+
vector[v] = y * vdir;
|
|
3859
|
+
vector[w] = depthHalf;
|
|
3860
|
+
vertices.push(vector.x, vector.y, vector.z);
|
|
3861
|
+
vector[u] = 0;
|
|
3862
|
+
vector[v] = 0;
|
|
3863
|
+
vector[w] = depth2 > 0 ? 1 : -1;
|
|
3864
|
+
normals.push(vector.x, vector.y, vector.z);
|
|
3865
|
+
uvs.push(ix / gridX);
|
|
3866
|
+
uvs.push(1 - iy / gridY);
|
|
3867
|
+
vertexCounter += 1;
|
|
3868
|
+
}
|
|
3869
|
+
}
|
|
3870
|
+
for (let iy = 0; iy < gridY; iy++) {
|
|
3871
|
+
for (let ix = 0; ix < gridX; ix++) {
|
|
3872
|
+
const a = numberOfVertices + ix + gridX1 * iy;
|
|
3873
|
+
const b = numberOfVertices + ix + gridX1 * (iy + 1);
|
|
3874
|
+
const c = numberOfVertices + (ix + 1) + gridX1 * (iy + 1);
|
|
3875
|
+
const d = numberOfVertices + (ix + 1) + gridX1 * iy;
|
|
3876
|
+
indices.push(a, b, d);
|
|
3877
|
+
indices.push(b, c, d);
|
|
3878
|
+
groupCount += 6;
|
|
3879
|
+
}
|
|
3880
|
+
}
|
|
3881
|
+
groups.push({ start: groupStart, count: groupCount, materialIndex });
|
|
3882
|
+
groupStart += groupCount;
|
|
3883
|
+
numberOfVertices += vertexCounter;
|
|
3884
|
+
};
|
|
3885
|
+
buildPlane("z", "y", "x", -1, -1, depth, height, width, depthSegments, heightSegments, 0);
|
|
3886
|
+
buildPlane("z", "y", "x", 1, -1, depth, height, -width, depthSegments, heightSegments, 1);
|
|
3887
|
+
buildPlane("x", "z", "y", 1, 1, width, depth, height, widthSegments, depthSegments, 2);
|
|
3888
|
+
buildPlane("x", "z", "y", 1, -1, width, depth, -height, widthSegments, depthSegments, 3);
|
|
3889
|
+
buildPlane("x", "y", "z", 1, -1, width, height, depth, widthSegments, heightSegments, 4);
|
|
3890
|
+
buildPlane("x", "y", "z", -1, -1, width, height, -depth, widthSegments, heightSegments, 5);
|
|
3891
|
+
return pack("BoxGeometry", parameters, { vertices, normals, uvs, indices, groups });
|
|
3892
|
+
}
|
|
3893
|
+
function cylinderArrays(radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength) {
|
|
3894
|
+
radialSegments = Math.floor(radialSegments);
|
|
3895
|
+
heightSegments = Math.floor(heightSegments);
|
|
3896
|
+
const indices = [];
|
|
3897
|
+
const vertices = [];
|
|
3898
|
+
const normals = [];
|
|
3899
|
+
const uvs = [];
|
|
3900
|
+
const groups = [];
|
|
3901
|
+
let index = 0;
|
|
3902
|
+
const indexArray2 = [];
|
|
3903
|
+
const halfHeight = height / 2;
|
|
3904
|
+
let groupStart = 0;
|
|
3905
|
+
const generateTorso = () => {
|
|
3906
|
+
let groupCount = 0;
|
|
3907
|
+
const slope = (radiusBottom - radiusTop) / height;
|
|
3908
|
+
for (let y = 0; y <= heightSegments; y++) {
|
|
3909
|
+
const indexRow = [];
|
|
3910
|
+
const v = y / heightSegments;
|
|
3911
|
+
const radius = v * (radiusBottom - radiusTop) + radiusTop;
|
|
3912
|
+
for (let x = 0; x <= radialSegments; x++) {
|
|
3913
|
+
const u = x / radialSegments;
|
|
3914
|
+
const theta = u * thetaLength + thetaStart;
|
|
3915
|
+
const sinTheta = Math.sin(theta);
|
|
3916
|
+
const cosTheta = Math.cos(theta);
|
|
3917
|
+
vertices.push(radius * sinTheta, -v * height + halfHeight, radius * cosTheta);
|
|
3918
|
+
const n = normalize3(sinTheta, slope, cosTheta);
|
|
3919
|
+
normals.push(n[0], n[1], n[2]);
|
|
3920
|
+
uvs.push(u, 1 - v);
|
|
3921
|
+
indexRow.push(index++);
|
|
3922
|
+
}
|
|
3923
|
+
indexArray2.push(indexRow);
|
|
3924
|
+
}
|
|
3925
|
+
for (let x = 0; x < radialSegments; x++) {
|
|
3926
|
+
for (let y = 0; y < heightSegments; y++) {
|
|
3927
|
+
const a = indexArray2[y][x];
|
|
3928
|
+
const b = indexArray2[y + 1][x];
|
|
3929
|
+
const c = indexArray2[y + 1][x + 1];
|
|
3930
|
+
const d = indexArray2[y][x + 1];
|
|
3931
|
+
indices.push(a, b, d);
|
|
3932
|
+
indices.push(b, c, d);
|
|
3933
|
+
groupCount += 6;
|
|
3934
|
+
}
|
|
3935
|
+
}
|
|
3936
|
+
groups.push({ start: groupStart, count: groupCount, materialIndex: 0 });
|
|
3937
|
+
groupStart += groupCount;
|
|
3938
|
+
};
|
|
3939
|
+
const generateCap = (top) => {
|
|
3940
|
+
const centerIndexStart = index;
|
|
3941
|
+
let groupCount = 0;
|
|
3942
|
+
const radius = top === true ? radiusTop : radiusBottom;
|
|
3943
|
+
const sign2 = top === true ? 1 : -1;
|
|
3944
|
+
for (let x = 1; x <= radialSegments; x++) {
|
|
3945
|
+
vertices.push(0, halfHeight * sign2, 0);
|
|
3946
|
+
normals.push(0, sign2, 0);
|
|
3947
|
+
uvs.push(0.5, 0.5);
|
|
3948
|
+
index++;
|
|
3949
|
+
}
|
|
3950
|
+
const centerIndexEnd = index;
|
|
3951
|
+
for (let x = 0; x <= radialSegments; x++) {
|
|
3952
|
+
const u = x / radialSegments;
|
|
3953
|
+
const theta = u * thetaLength + thetaStart;
|
|
3954
|
+
const cosTheta = Math.cos(theta);
|
|
3955
|
+
const sinTheta = Math.sin(theta);
|
|
3956
|
+
vertices.push(radius * sinTheta, halfHeight * sign2, radius * cosTheta);
|
|
3957
|
+
normals.push(0, sign2, 0);
|
|
3958
|
+
uvs.push(cosTheta * 0.5 + 0.5, sinTheta * 0.5 * sign2 + 0.5);
|
|
3959
|
+
index++;
|
|
3960
|
+
}
|
|
3961
|
+
for (let x = 0; x < radialSegments; x++) {
|
|
3962
|
+
const c = centerIndexStart + x;
|
|
3963
|
+
const i = centerIndexEnd + x;
|
|
3964
|
+
if (top === true) indices.push(i, i + 1, c);
|
|
3965
|
+
else indices.push(i + 1, i, c);
|
|
3966
|
+
groupCount += 3;
|
|
3967
|
+
}
|
|
3968
|
+
groups.push({ start: groupStart, count: groupCount, materialIndex: top === true ? 1 : 2 });
|
|
3969
|
+
groupStart += groupCount;
|
|
3970
|
+
};
|
|
3971
|
+
generateTorso();
|
|
3972
|
+
if (openEnded === false) {
|
|
3973
|
+
if (radiusTop > 0) generateCap(true);
|
|
3974
|
+
if (radiusBottom > 0) generateCap(false);
|
|
3975
|
+
}
|
|
3976
|
+
return { vertices, normals, uvs, indices, groups };
|
|
3977
|
+
}
|
|
3978
|
+
function cylinder(radiusTop = 1, radiusBottom = 1, height = 1, radialSegments = 32, heightSegments = 1, openEnded = false, thetaStart = 0, thetaLength = Math.PI * 2) {
|
|
3979
|
+
const parameters = { radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength };
|
|
3980
|
+
return pack("CylinderGeometry", parameters, cylinderArrays(radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength));
|
|
3981
|
+
}
|
|
3982
|
+
function cone(radius = 1, height = 1, radialSegments = 32, heightSegments = 1, openEnded = false, thetaStart = 0, thetaLength = Math.PI * 2) {
|
|
3983
|
+
const parameters = { radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength };
|
|
3984
|
+
return pack("ConeGeometry", parameters, cylinderArrays(0, radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength));
|
|
3985
|
+
}
|
|
3986
|
+
function sphere(radius = 1, widthSegments = 32, heightSegments = 16, phiStart = 0, phiLength = Math.PI * 2, thetaStart = 0, thetaLength = Math.PI) {
|
|
3987
|
+
const parameters = { radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength };
|
|
3988
|
+
widthSegments = Math.max(3, Math.floor(widthSegments));
|
|
3989
|
+
heightSegments = Math.max(2, Math.floor(heightSegments));
|
|
3990
|
+
const thetaEnd = Math.min(thetaStart + thetaLength, Math.PI);
|
|
3991
|
+
let index = 0;
|
|
3992
|
+
const grid = [];
|
|
3993
|
+
const indices = [];
|
|
3994
|
+
const vertices = [];
|
|
3995
|
+
const normals = [];
|
|
3996
|
+
const uvs = [];
|
|
3997
|
+
for (let iy = 0; iy <= heightSegments; iy++) {
|
|
3998
|
+
const verticesRow = [];
|
|
3999
|
+
const v = iy / heightSegments;
|
|
4000
|
+
let uOffset = 0;
|
|
4001
|
+
if (iy === 0 && thetaStart === 0) uOffset = 0.5 / widthSegments;
|
|
4002
|
+
else if (iy === heightSegments && thetaEnd === Math.PI) uOffset = -0.5 / widthSegments;
|
|
4003
|
+
for (let ix = 0; ix <= widthSegments; ix++) {
|
|
4004
|
+
const u = ix / widthSegments;
|
|
4005
|
+
const x = -radius * Math.cos(phiStart + u * phiLength) * Math.sin(thetaStart + v * thetaLength);
|
|
4006
|
+
const y = radius * Math.cos(thetaStart + v * thetaLength);
|
|
4007
|
+
const z = radius * Math.sin(phiStart + u * phiLength) * Math.sin(thetaStart + v * thetaLength);
|
|
4008
|
+
vertices.push(x, y, z);
|
|
4009
|
+
const n = normalize3(x, y, z);
|
|
4010
|
+
normals.push(n[0], n[1], n[2]);
|
|
4011
|
+
uvs.push(u + uOffset, 1 - v);
|
|
4012
|
+
verticesRow.push(index++);
|
|
4013
|
+
}
|
|
4014
|
+
grid.push(verticesRow);
|
|
4015
|
+
}
|
|
4016
|
+
for (let iy = 0; iy < heightSegments; iy++) {
|
|
4017
|
+
for (let ix = 0; ix < widthSegments; ix++) {
|
|
4018
|
+
const a = grid[iy][ix + 1];
|
|
4019
|
+
const b = grid[iy][ix];
|
|
4020
|
+
const c = grid[iy + 1][ix];
|
|
4021
|
+
const d = grid[iy + 1][ix + 1];
|
|
4022
|
+
if (iy !== 0 || thetaStart > 0) indices.push(a, b, d);
|
|
4023
|
+
if (iy !== heightSegments - 1 || thetaEnd < Math.PI) indices.push(b, c, d);
|
|
4024
|
+
}
|
|
4025
|
+
}
|
|
4026
|
+
return pack("SphereGeometry", parameters, { vertices, normals, uvs, indices, groups: [] });
|
|
4027
|
+
}
|
|
4028
|
+
function plane(width = 1, height = 1, widthSegments = 1, heightSegments = 1) {
|
|
4029
|
+
const parameters = { width, height, widthSegments, heightSegments };
|
|
4030
|
+
const widthHalf = width / 2;
|
|
4031
|
+
const heightHalf = height / 2;
|
|
4032
|
+
const gridX = Math.floor(widthSegments);
|
|
4033
|
+
const gridY = Math.floor(heightSegments);
|
|
4034
|
+
const gridX1 = gridX + 1;
|
|
4035
|
+
const gridY1 = gridY + 1;
|
|
4036
|
+
const segmentWidth = width / gridX;
|
|
4037
|
+
const segmentHeight = height / gridY;
|
|
4038
|
+
const indices = [];
|
|
4039
|
+
const vertices = [];
|
|
4040
|
+
const normals = [];
|
|
4041
|
+
const uvs = [];
|
|
4042
|
+
for (let iy = 0; iy < gridY1; iy++) {
|
|
4043
|
+
const y = iy * segmentHeight - heightHalf;
|
|
4044
|
+
for (let ix = 0; ix < gridX1; ix++) {
|
|
4045
|
+
const x = ix * segmentWidth - widthHalf;
|
|
4046
|
+
vertices.push(x, -y, 0);
|
|
4047
|
+
normals.push(0, 0, 1);
|
|
4048
|
+
uvs.push(ix / gridX);
|
|
4049
|
+
uvs.push(1 - iy / gridY);
|
|
4050
|
+
}
|
|
4051
|
+
}
|
|
4052
|
+
for (let iy = 0; iy < gridY; iy++) {
|
|
4053
|
+
for (let ix = 0; ix < gridX; ix++) {
|
|
4054
|
+
const a = ix + gridX1 * iy;
|
|
4055
|
+
const b = ix + gridX1 * (iy + 1);
|
|
4056
|
+
const c = ix + 1 + gridX1 * (iy + 1);
|
|
4057
|
+
const d = ix + 1 + gridX1 * iy;
|
|
4058
|
+
indices.push(a, b, d);
|
|
4059
|
+
indices.push(b, c, d);
|
|
4060
|
+
}
|
|
4061
|
+
}
|
|
4062
|
+
return pack("PlaneGeometry", parameters, { vertices, normals, uvs, indices, groups: [] });
|
|
4063
|
+
}
|
|
4064
|
+
function circle(radius = 1, segments = 32, thetaStart = 0, thetaLength = Math.PI * 2) {
|
|
4065
|
+
const parameters = { radius, segments, thetaStart, thetaLength };
|
|
4066
|
+
segments = Math.max(3, segments);
|
|
4067
|
+
const indices = [];
|
|
4068
|
+
const vertices = [];
|
|
4069
|
+
const normals = [];
|
|
4070
|
+
const uvs = [];
|
|
4071
|
+
vertices.push(0, 0, 0);
|
|
4072
|
+
normals.push(0, 0, 1);
|
|
4073
|
+
uvs.push(0.5, 0.5);
|
|
4074
|
+
for (let s = 0, i = 3; s <= segments; s++, i += 3) {
|
|
4075
|
+
const segment = thetaStart + s / segments * thetaLength;
|
|
4076
|
+
vertices.push(radius * Math.cos(segment), radius * Math.sin(segment), 0);
|
|
4077
|
+
normals.push(0, 0, 1);
|
|
4078
|
+
uvs.push((vertices[i] / radius + 1) / 2, (vertices[i + 1] / radius + 1) / 2);
|
|
4079
|
+
}
|
|
4080
|
+
for (let i = 1; i <= segments; i++) indices.push(i, i + 1, 0);
|
|
4081
|
+
return pack("CircleGeometry", parameters, { vertices, normals, uvs, indices, groups: [] });
|
|
4082
|
+
}
|
|
4083
|
+
function ring(innerRadius = 0.5, outerRadius = 1, thetaSegments = 32, phiSegments = 1, thetaStart = 0, thetaLength = Math.PI * 2) {
|
|
4084
|
+
const parameters = { innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength };
|
|
4085
|
+
thetaSegments = Math.max(3, thetaSegments);
|
|
4086
|
+
phiSegments = Math.max(1, phiSegments);
|
|
4087
|
+
const indices = [];
|
|
4088
|
+
const vertices = [];
|
|
4089
|
+
const normals = [];
|
|
4090
|
+
const uvs = [];
|
|
4091
|
+
let radius = innerRadius;
|
|
4092
|
+
const radiusStep = (outerRadius - innerRadius) / phiSegments;
|
|
4093
|
+
for (let j = 0; j <= phiSegments; j++) {
|
|
4094
|
+
for (let i = 0; i <= thetaSegments; i++) {
|
|
4095
|
+
const segment = thetaStart + i / thetaSegments * thetaLength;
|
|
4096
|
+
const x = radius * Math.cos(segment);
|
|
4097
|
+
const y = radius * Math.sin(segment);
|
|
4098
|
+
vertices.push(x, y, 0);
|
|
4099
|
+
normals.push(0, 0, 1);
|
|
4100
|
+
uvs.push((x / outerRadius + 1) / 2, (y / outerRadius + 1) / 2);
|
|
4101
|
+
}
|
|
4102
|
+
radius += radiusStep;
|
|
4103
|
+
}
|
|
4104
|
+
for (let j = 0; j < phiSegments; j++) {
|
|
4105
|
+
const thetaSegmentLevel = j * (thetaSegments + 1);
|
|
4106
|
+
for (let i = 0; i < thetaSegments; i++) {
|
|
4107
|
+
const segment = i + thetaSegmentLevel;
|
|
4108
|
+
const a = segment;
|
|
4109
|
+
const b = segment + thetaSegments + 1;
|
|
4110
|
+
const c = segment + thetaSegments + 2;
|
|
4111
|
+
const d = segment + 1;
|
|
4112
|
+
indices.push(a, b, d);
|
|
4113
|
+
indices.push(b, c, d);
|
|
4114
|
+
}
|
|
4115
|
+
}
|
|
4116
|
+
return pack("RingGeometry", parameters, { vertices, normals, uvs, indices, groups: [] });
|
|
4117
|
+
}
|
|
4118
|
+
function lathe(points, segments = 12, phiStart = 0, phiLength = Math.PI * 2) {
|
|
4119
|
+
const parameters = { points: points.map(([x, y]) => ({ x, y })), segments, phiStart, phiLength };
|
|
4120
|
+
segments = Math.floor(segments);
|
|
4121
|
+
phiLength = Math.max(0, Math.min(Math.PI * 2, phiLength));
|
|
4122
|
+
const indices = [];
|
|
4123
|
+
const vertices = [];
|
|
4124
|
+
const uvs = [];
|
|
4125
|
+
const initNormals = [];
|
|
4126
|
+
const normals = [];
|
|
4127
|
+
const inverseSegments = 1 / segments;
|
|
4128
|
+
const normal = { x: 0, y: 0, z: 0 };
|
|
4129
|
+
const curNormal = { x: 0, y: 0, z: 0 };
|
|
4130
|
+
const prevNormal = { x: 0, y: 0, z: 0 };
|
|
4131
|
+
let dx = 0;
|
|
4132
|
+
let dy = 0;
|
|
4133
|
+
const last = points.length - 1;
|
|
4134
|
+
const px = (j) => points[j][0];
|
|
4135
|
+
const py = (j) => points[j][1];
|
|
4136
|
+
const setNormalized = () => {
|
|
4137
|
+
const n = normalize3(normal.x, normal.y, normal.z);
|
|
4138
|
+
normal.x = n[0];
|
|
4139
|
+
normal.y = n[1];
|
|
4140
|
+
normal.z = n[2];
|
|
4141
|
+
};
|
|
4142
|
+
for (let j = 0; j <= last; j++) {
|
|
4143
|
+
if (j === 0) {
|
|
4144
|
+
dx = px(j + 1) - px(j);
|
|
4145
|
+
dy = py(j + 1) - py(j);
|
|
4146
|
+
normal.x = dy * 1;
|
|
4147
|
+
normal.y = -dx;
|
|
4148
|
+
normal.z = dy * 0;
|
|
4149
|
+
prevNormal.x = normal.x;
|
|
4150
|
+
prevNormal.y = normal.y;
|
|
4151
|
+
prevNormal.z = normal.z;
|
|
4152
|
+
setNormalized();
|
|
4153
|
+
initNormals.push(normal.x, normal.y, normal.z);
|
|
4154
|
+
} else if (j === last) {
|
|
4155
|
+
initNormals.push(prevNormal.x, prevNormal.y, prevNormal.z);
|
|
4156
|
+
} else {
|
|
4157
|
+
dx = px(j + 1) - px(j);
|
|
4158
|
+
dy = py(j + 1) - py(j);
|
|
4159
|
+
normal.x = dy * 1;
|
|
4160
|
+
normal.y = -dx;
|
|
4161
|
+
normal.z = dy * 0;
|
|
4162
|
+
curNormal.x = normal.x;
|
|
4163
|
+
curNormal.y = normal.y;
|
|
4164
|
+
curNormal.z = normal.z;
|
|
4165
|
+
normal.x += prevNormal.x;
|
|
4166
|
+
normal.y += prevNormal.y;
|
|
4167
|
+
normal.z += prevNormal.z;
|
|
4168
|
+
setNormalized();
|
|
4169
|
+
initNormals.push(normal.x, normal.y, normal.z);
|
|
4170
|
+
prevNormal.x = curNormal.x;
|
|
4171
|
+
prevNormal.y = curNormal.y;
|
|
4172
|
+
prevNormal.z = curNormal.z;
|
|
4173
|
+
}
|
|
4174
|
+
}
|
|
4175
|
+
for (let i = 0; i <= segments; i++) {
|
|
4176
|
+
const phi = phiStart + i * inverseSegments * phiLength;
|
|
4177
|
+
const sin = Math.sin(phi);
|
|
4178
|
+
const cos = Math.cos(phi);
|
|
4179
|
+
for (let j = 0; j <= last; j++) {
|
|
4180
|
+
vertices.push(px(j) * sin, py(j), px(j) * cos);
|
|
4181
|
+
uvs.push(i / segments, j / (points.length - 1));
|
|
4182
|
+
const x = initNormals[3 * j + 0] * sin;
|
|
4183
|
+
const y = initNormals[3 * j + 1];
|
|
4184
|
+
const z = initNormals[3 * j + 0] * cos;
|
|
4185
|
+
normals.push(x, y, z);
|
|
4186
|
+
}
|
|
4187
|
+
}
|
|
4188
|
+
for (let i = 0; i < segments; i++) {
|
|
4189
|
+
for (let j = 0; j < points.length - 1; j++) {
|
|
4190
|
+
const base = j + i * points.length;
|
|
4191
|
+
const a = base;
|
|
4192
|
+
const b = base + points.length;
|
|
4193
|
+
const c = base + points.length + 1;
|
|
4194
|
+
const d = base + 1;
|
|
4195
|
+
indices.push(a, b, d);
|
|
4196
|
+
indices.push(c, d, b);
|
|
4197
|
+
}
|
|
4198
|
+
}
|
|
4199
|
+
return pack("LatheGeometry", parameters, { vertices, normals, uvs, indices, groups: [] });
|
|
4200
|
+
}
|
|
4201
|
+
function torus(radius = 1, tube = 0.4, radialSegments = 12, tubularSegments = 48, arc = Math.PI * 2) {
|
|
4202
|
+
const parameters = { radius, tube, radialSegments, tubularSegments, arc };
|
|
4203
|
+
radialSegments = Math.floor(radialSegments);
|
|
4204
|
+
tubularSegments = Math.floor(tubularSegments);
|
|
4205
|
+
const indices = [];
|
|
4206
|
+
const vertices = [];
|
|
4207
|
+
const normals = [];
|
|
4208
|
+
const uvs = [];
|
|
4209
|
+
for (let j = 0; j <= radialSegments; j++) {
|
|
4210
|
+
for (let i = 0; i <= tubularSegments; i++) {
|
|
4211
|
+
const u = i / tubularSegments * arc;
|
|
4212
|
+
const v = j / radialSegments * Math.PI * 2;
|
|
4213
|
+
const x = (radius + tube * Math.cos(v)) * Math.cos(u);
|
|
4214
|
+
const y = (radius + tube * Math.cos(v)) * Math.sin(u);
|
|
4215
|
+
const z = tube * Math.sin(v);
|
|
4216
|
+
vertices.push(x, y, z);
|
|
4217
|
+
const cx = radius * Math.cos(u);
|
|
4218
|
+
const cy = radius * Math.sin(u);
|
|
4219
|
+
const n = normalize3(x - cx, y - cy, z - 0);
|
|
4220
|
+
normals.push(n[0], n[1], n[2]);
|
|
4221
|
+
uvs.push(i / tubularSegments);
|
|
4222
|
+
uvs.push(j / radialSegments);
|
|
4223
|
+
}
|
|
4224
|
+
}
|
|
4225
|
+
for (let j = 1; j <= radialSegments; j++) {
|
|
4226
|
+
for (let i = 1; i <= tubularSegments; i++) {
|
|
4227
|
+
const a = (tubularSegments + 1) * j + i - 1;
|
|
4228
|
+
const b = (tubularSegments + 1) * (j - 1) + i - 1;
|
|
4229
|
+
const c = (tubularSegments + 1) * (j - 1) + i;
|
|
4230
|
+
const d = (tubularSegments + 1) * j + i;
|
|
4231
|
+
indices.push(a, b, d);
|
|
4232
|
+
indices.push(b, c, d);
|
|
4233
|
+
}
|
|
4234
|
+
}
|
|
4235
|
+
return pack("TorusGeometry", parameters, { vertices, normals, uvs, indices, groups: [] });
|
|
4236
|
+
}
|
|
4237
|
+
function difference(size, subtract) {
|
|
4238
|
+
const [w, h, d] = size;
|
|
4239
|
+
const hw = w / 2;
|
|
4240
|
+
const hh = h / 2;
|
|
4241
|
+
const hd = d / 2;
|
|
4242
|
+
const holes = subtract.map((hole) => ({ x0: Math.max(-hw, Math.min(hole.min[0], hole.max[0])), x1: Math.min(hw, Math.max(hole.min[0], hole.max[0])), y0: Math.max(-hh, Math.min(hole.min[1], hole.max[1])), y1: Math.min(hh, Math.max(hole.min[1], hole.max[1])) })).filter((hole) => hole.x1 > hole.x0 && hole.y1 > hole.y0);
|
|
4243
|
+
const cuts = (lo, hi, values) => [.../* @__PURE__ */ new Set([lo, hi, ...values.filter((v) => v > lo && v < hi)])].sort((a, b) => a - b);
|
|
4244
|
+
const xs = cuts(-hw, hw, holes.flatMap((hole) => [hole.x0, hole.x1]));
|
|
4245
|
+
const ys = cuts(-hh, hh, holes.flatMap((hole) => [hole.y0, hole.y1]));
|
|
4246
|
+
const nx = xs.length - 1;
|
|
4247
|
+
const ny = ys.length - 1;
|
|
4248
|
+
const solid = (i, j) => {
|
|
4249
|
+
if (i < 0 || j < 0 || i >= nx || j >= ny) return false;
|
|
4250
|
+
const cx = (xs[i] + xs[i + 1]) / 2;
|
|
4251
|
+
const cy = (ys[j] + ys[j + 1]) / 2;
|
|
4252
|
+
return !holes.some((hole) => cx > hole.x0 && cx < hole.x1 && cy > hole.y0 && cy < hole.y1);
|
|
4253
|
+
};
|
|
4254
|
+
const positions = [];
|
|
4255
|
+
const normals = [];
|
|
4256
|
+
const uvs = [];
|
|
4257
|
+
const indices = [];
|
|
4258
|
+
const quad = (corners, normal, uv) => {
|
|
4259
|
+
const base = positions.length / 3;
|
|
4260
|
+
for (let k = 0; k < 4; k++) {
|
|
4261
|
+
positions.push(...corners[k]);
|
|
4262
|
+
normals.push(...normal);
|
|
4263
|
+
uvs.push(...uv[k]);
|
|
4264
|
+
}
|
|
4265
|
+
indices.push(base, base + 1, base + 2, base, base + 2, base + 3);
|
|
4266
|
+
};
|
|
4267
|
+
const fu = (x) => (x + hw) / w;
|
|
4268
|
+
const fv = (y) => (y + hh) / h;
|
|
4269
|
+
for (let j = 0; j < ny; j++) {
|
|
4270
|
+
for (let i = 0; i < nx; i++) {
|
|
4271
|
+
if (!solid(i, j)) continue;
|
|
4272
|
+
const x0 = xs[i];
|
|
4273
|
+
const x1 = xs[i + 1];
|
|
4274
|
+
const y0 = ys[j];
|
|
4275
|
+
const y1 = ys[j + 1];
|
|
4276
|
+
quad([[x0, y0, hd], [x1, y0, hd], [x1, y1, hd], [x0, y1, hd]], [0, 0, 1], [[fu(x0), fv(y0)], [fu(x1), fv(y0)], [fu(x1), fv(y1)], [fu(x0), fv(y1)]]);
|
|
4277
|
+
quad([[x1, y0, -hd], [x0, y0, -hd], [x0, y1, -hd], [x1, y1, -hd]], [0, 0, -1], [[1 - fu(x1), fv(y0)], [1 - fu(x0), fv(y0)], [1 - fu(x0), fv(y1)], [1 - fu(x1), fv(y1)]]);
|
|
4278
|
+
const zu = (z) => (z + hd) / d;
|
|
4279
|
+
if (!solid(i - 1, j)) quad([[x0, y0, -hd], [x0, y0, hd], [x0, y1, hd], [x0, y1, -hd]], [-1, 0, 0], [[zu(-hd), fv(y0)], [zu(hd), fv(y0)], [zu(hd), fv(y1)], [zu(-hd), fv(y1)]]);
|
|
4280
|
+
if (!solid(i + 1, j)) quad([[x1, y0, hd], [x1, y0, -hd], [x1, y1, -hd], [x1, y1, hd]], [1, 0, 0], [[zu(hd), fv(y0)], [zu(-hd), fv(y0)], [zu(-hd), fv(y1)], [zu(hd), fv(y1)]]);
|
|
4281
|
+
if (!solid(i, j - 1)) quad([[x0, y0, -hd], [x1, y0, -hd], [x1, y0, hd], [x0, y0, hd]], [0, -1, 0], [[fu(x0), zu(-hd)], [fu(x1), zu(-hd)], [fu(x1), zu(hd)], [fu(x0), zu(hd)]]);
|
|
4282
|
+
if (!solid(i, j + 1)) quad([[x0, y1, hd], [x1, y1, hd], [x1, y1, -hd], [x0, y1, -hd]], [0, 1, 0], [[fu(x0), zu(hd)], [fu(x1), zu(hd)], [fu(x1), zu(-hd)], [fu(x0), zu(-hd)]]);
|
|
4283
|
+
}
|
|
4284
|
+
}
|
|
4285
|
+
return {
|
|
4286
|
+
type: "BufferGeometry",
|
|
4287
|
+
parameters: { size: [w, h, d], subtract: holes.map((hole) => ({ min: [hole.x0, hole.y0], max: [hole.x1, hole.y1] })) },
|
|
4288
|
+
positions: new Float32Array(positions),
|
|
4289
|
+
normals: new Float32Array(normals),
|
|
4290
|
+
uvs: new Float32Array(uvs),
|
|
4291
|
+
indices: indexArray(indices),
|
|
4292
|
+
groups: []
|
|
4293
|
+
};
|
|
4294
|
+
}
|
|
4295
|
+
var Earcut = {
|
|
4296
|
+
triangulate: function(data, holeIndices, dim = 2) {
|
|
4297
|
+
const hasHoles = holeIndices && holeIndices.length;
|
|
4298
|
+
const outerLen = hasHoles ? holeIndices[0] * dim : data.length;
|
|
4299
|
+
let outerNode = linkedList(data, 0, outerLen, dim, true);
|
|
4300
|
+
const triangles = [];
|
|
4301
|
+
if (!outerNode || outerNode.next === outerNode.prev) return triangles;
|
|
4302
|
+
let minX, minY, maxX, maxY, x, y, invSize;
|
|
4303
|
+
if (hasHoles) outerNode = eliminateHoles(data, holeIndices, outerNode, dim);
|
|
4304
|
+
if (data.length > 80 * dim) {
|
|
4305
|
+
minX = maxX = data[0];
|
|
4306
|
+
minY = maxY = data[1];
|
|
4307
|
+
for (let i = dim; i < outerLen; i += dim) {
|
|
4308
|
+
x = data[i];
|
|
4309
|
+
y = data[i + 1];
|
|
4310
|
+
if (x < minX) minX = x;
|
|
4311
|
+
if (y < minY) minY = y;
|
|
4312
|
+
if (x > maxX) maxX = x;
|
|
4313
|
+
if (y > maxY) maxY = y;
|
|
4314
|
+
}
|
|
4315
|
+
invSize = Math.max(maxX - minX, maxY - minY);
|
|
4316
|
+
invSize = invSize !== 0 ? 32767 / invSize : 0;
|
|
4317
|
+
}
|
|
4318
|
+
earcutLinked(outerNode, triangles, dim, minX, minY, invSize, 0);
|
|
4319
|
+
return triangles;
|
|
4320
|
+
}
|
|
4321
|
+
};
|
|
4322
|
+
function linkedList(data, start, end, dim, clockwise) {
|
|
4323
|
+
let i, last;
|
|
4324
|
+
if (clockwise === signedArea(data, start, end, dim) > 0) {
|
|
4325
|
+
for (i = start; i < end; i += dim) last = insertNode(i, data[i], data[i + 1], last);
|
|
4326
|
+
} else {
|
|
4327
|
+
for (i = end - dim; i >= start; i -= dim) last = insertNode(i, data[i], data[i + 1], last);
|
|
4328
|
+
}
|
|
4329
|
+
if (last && equals(last, last.next)) {
|
|
4330
|
+
removeNode(last);
|
|
4331
|
+
last = last.next;
|
|
4332
|
+
}
|
|
4333
|
+
return last;
|
|
4334
|
+
}
|
|
4335
|
+
function filterPoints(start, end) {
|
|
4336
|
+
if (!start) return start;
|
|
4337
|
+
if (!end) end = start;
|
|
4338
|
+
let p2 = start, again;
|
|
4339
|
+
do {
|
|
4340
|
+
again = false;
|
|
4341
|
+
if (!p2.steiner && (equals(p2, p2.next) || area(p2.prev, p2, p2.next) === 0)) {
|
|
4342
|
+
removeNode(p2);
|
|
4343
|
+
p2 = end = p2.prev;
|
|
4344
|
+
if (p2 === p2.next) break;
|
|
4345
|
+
again = true;
|
|
4346
|
+
} else {
|
|
4347
|
+
p2 = p2.next;
|
|
4348
|
+
}
|
|
4349
|
+
} while (again || p2 !== end);
|
|
4350
|
+
return end;
|
|
4351
|
+
}
|
|
4352
|
+
function earcutLinked(ear, triangles, dim, minX, minY, invSize, pass) {
|
|
4353
|
+
if (!ear) return;
|
|
4354
|
+
if (!pass && invSize) indexCurve(ear, minX, minY, invSize);
|
|
4355
|
+
let stop = ear, prev, next;
|
|
4356
|
+
while (ear.prev !== ear.next) {
|
|
4357
|
+
prev = ear.prev;
|
|
4358
|
+
next = ear.next;
|
|
4359
|
+
if (invSize ? isEarHashed(ear, minX, minY, invSize) : isEar(ear)) {
|
|
4360
|
+
triangles.push(prev.i / dim | 0);
|
|
4361
|
+
triangles.push(ear.i / dim | 0);
|
|
4362
|
+
triangles.push(next.i / dim | 0);
|
|
4363
|
+
removeNode(ear);
|
|
4364
|
+
ear = next.next;
|
|
4365
|
+
stop = next.next;
|
|
4366
|
+
continue;
|
|
4367
|
+
}
|
|
4368
|
+
ear = next;
|
|
4369
|
+
if (ear === stop) {
|
|
4370
|
+
if (!pass) {
|
|
4371
|
+
earcutLinked(filterPoints(ear), triangles, dim, minX, minY, invSize, 1);
|
|
4372
|
+
} else if (pass === 1) {
|
|
4373
|
+
ear = cureLocalIntersections(filterPoints(ear), triangles, dim);
|
|
4374
|
+
earcutLinked(ear, triangles, dim, minX, minY, invSize, 2);
|
|
4375
|
+
} else if (pass === 2) {
|
|
4376
|
+
splitEarcut(ear, triangles, dim, minX, minY, invSize);
|
|
4377
|
+
}
|
|
4378
|
+
break;
|
|
4379
|
+
}
|
|
4380
|
+
}
|
|
4381
|
+
}
|
|
4382
|
+
function isEar(ear) {
|
|
4383
|
+
const a = ear.prev, b = ear, c = ear.next;
|
|
4384
|
+
if (area(a, b, c) >= 0) return false;
|
|
4385
|
+
const ax = a.x, bx = b.x, cx = c.x, ay = a.y, by = b.y, cy = c.y;
|
|
4386
|
+
const x0 = ax < bx ? ax < cx ? ax : cx : bx < cx ? bx : cx, y0 = ay < by ? ay < cy ? ay : cy : by < cy ? by : cy, x1 = ax > bx ? ax > cx ? ax : cx : bx > cx ? bx : cx, y1 = ay > by ? ay > cy ? ay : cy : by > cy ? by : cy;
|
|
4387
|
+
let p2 = c.next;
|
|
4388
|
+
while (p2 !== a) {
|
|
4389
|
+
if (p2.x >= x0 && p2.x <= x1 && p2.y >= y0 && p2.y <= y1 && pointInTriangle(ax, ay, bx, by, cx, cy, p2.x, p2.y) && area(p2.prev, p2, p2.next) >= 0) return false;
|
|
4390
|
+
p2 = p2.next;
|
|
4391
|
+
}
|
|
4392
|
+
return true;
|
|
4393
|
+
}
|
|
4394
|
+
function isEarHashed(ear, minX, minY, invSize) {
|
|
4395
|
+
const a = ear.prev, b = ear, c = ear.next;
|
|
4396
|
+
if (area(a, b, c) >= 0) return false;
|
|
4397
|
+
const ax = a.x, bx = b.x, cx = c.x, ay = a.y, by = b.y, cy = c.y;
|
|
4398
|
+
const x0 = ax < bx ? ax < cx ? ax : cx : bx < cx ? bx : cx, y0 = ay < by ? ay < cy ? ay : cy : by < cy ? by : cy, x1 = ax > bx ? ax > cx ? ax : cx : bx > cx ? bx : cx, y1 = ay > by ? ay > cy ? ay : cy : by > cy ? by : cy;
|
|
4399
|
+
const minZ = zOrder(x0, y0, minX, minY, invSize), maxZ = zOrder(x1, y1, minX, minY, invSize);
|
|
4400
|
+
let p2 = ear.prevZ, n = ear.nextZ;
|
|
4401
|
+
while (p2 && p2.z >= minZ && n && n.z <= maxZ) {
|
|
4402
|
+
if (p2.x >= x0 && p2.x <= x1 && p2.y >= y0 && p2.y <= y1 && p2 !== a && p2 !== c && pointInTriangle(ax, ay, bx, by, cx, cy, p2.x, p2.y) && area(p2.prev, p2, p2.next) >= 0) return false;
|
|
4403
|
+
p2 = p2.prevZ;
|
|
4404
|
+
if (n.x >= x0 && n.x <= x1 && n.y >= y0 && n.y <= y1 && n !== a && n !== c && pointInTriangle(ax, ay, bx, by, cx, cy, n.x, n.y) && area(n.prev, n, n.next) >= 0) return false;
|
|
4405
|
+
n = n.nextZ;
|
|
4406
|
+
}
|
|
4407
|
+
while (p2 && p2.z >= minZ) {
|
|
4408
|
+
if (p2.x >= x0 && p2.x <= x1 && p2.y >= y0 && p2.y <= y1 && p2 !== a && p2 !== c && pointInTriangle(ax, ay, bx, by, cx, cy, p2.x, p2.y) && area(p2.prev, p2, p2.next) >= 0) return false;
|
|
4409
|
+
p2 = p2.prevZ;
|
|
4410
|
+
}
|
|
4411
|
+
while (n && n.z <= maxZ) {
|
|
4412
|
+
if (n.x >= x0 && n.x <= x1 && n.y >= y0 && n.y <= y1 && n !== a && n !== c && pointInTriangle(ax, ay, bx, by, cx, cy, n.x, n.y) && area(n.prev, n, n.next) >= 0) return false;
|
|
4413
|
+
n = n.nextZ;
|
|
4414
|
+
}
|
|
4415
|
+
return true;
|
|
4416
|
+
}
|
|
4417
|
+
function cureLocalIntersections(start, triangles, dim) {
|
|
4418
|
+
let p2 = start;
|
|
4419
|
+
do {
|
|
4420
|
+
const a = p2.prev, b = p2.next.next;
|
|
4421
|
+
if (!equals(a, b) && intersects(a, p2, p2.next, b) && locallyInside(a, b) && locallyInside(b, a)) {
|
|
4422
|
+
triangles.push(a.i / dim | 0);
|
|
4423
|
+
triangles.push(p2.i / dim | 0);
|
|
4424
|
+
triangles.push(b.i / dim | 0);
|
|
4425
|
+
removeNode(p2);
|
|
4426
|
+
removeNode(p2.next);
|
|
4427
|
+
p2 = start = b;
|
|
4428
|
+
}
|
|
4429
|
+
p2 = p2.next;
|
|
4430
|
+
} while (p2 !== start);
|
|
4431
|
+
return filterPoints(p2);
|
|
4432
|
+
}
|
|
4433
|
+
function splitEarcut(start, triangles, dim, minX, minY, invSize) {
|
|
4434
|
+
let a = start;
|
|
4435
|
+
do {
|
|
4436
|
+
let b = a.next.next;
|
|
4437
|
+
while (b !== a.prev) {
|
|
4438
|
+
if (a.i !== b.i && isValidDiagonal(a, b)) {
|
|
4439
|
+
let c = splitPolygon(a, b);
|
|
4440
|
+
a = filterPoints(a, a.next);
|
|
4441
|
+
c = filterPoints(c, c.next);
|
|
4442
|
+
earcutLinked(a, triangles, dim, minX, minY, invSize, 0);
|
|
4443
|
+
earcutLinked(c, triangles, dim, minX, minY, invSize, 0);
|
|
4444
|
+
return;
|
|
4445
|
+
}
|
|
4446
|
+
b = b.next;
|
|
4447
|
+
}
|
|
4448
|
+
a = a.next;
|
|
4449
|
+
} while (a !== start);
|
|
4450
|
+
}
|
|
4451
|
+
function eliminateHoles(data, holeIndices, outerNode, dim) {
|
|
4452
|
+
const queue = [];
|
|
4453
|
+
let i, len, start, end, list2;
|
|
4454
|
+
for (i = 0, len = holeIndices.length; i < len; i++) {
|
|
4455
|
+
start = holeIndices[i] * dim;
|
|
4456
|
+
end = i < len - 1 ? holeIndices[i + 1] * dim : data.length;
|
|
4457
|
+
list2 = linkedList(data, start, end, dim, false);
|
|
4458
|
+
if (list2 === list2.next) list2.steiner = true;
|
|
4459
|
+
queue.push(getLeftmost(list2));
|
|
4460
|
+
}
|
|
4461
|
+
queue.sort(compareX);
|
|
4462
|
+
for (i = 0; i < queue.length; i++) {
|
|
4463
|
+
outerNode = eliminateHole(queue[i], outerNode);
|
|
4464
|
+
}
|
|
4465
|
+
return outerNode;
|
|
4466
|
+
}
|
|
4467
|
+
function compareX(a, b) {
|
|
4468
|
+
return a.x - b.x;
|
|
4469
|
+
}
|
|
4470
|
+
function eliminateHole(hole, outerNode) {
|
|
4471
|
+
const bridge = findHoleBridge(hole, outerNode);
|
|
4472
|
+
if (!bridge) {
|
|
4473
|
+
return outerNode;
|
|
4474
|
+
}
|
|
4475
|
+
const bridgeReverse = splitPolygon(bridge, hole);
|
|
4476
|
+
filterPoints(bridgeReverse, bridgeReverse.next);
|
|
4477
|
+
return filterPoints(bridge, bridge.next);
|
|
4478
|
+
}
|
|
4479
|
+
function findHoleBridge(hole, outerNode) {
|
|
4480
|
+
let p2 = outerNode, qx = -Infinity, m;
|
|
4481
|
+
const hx = hole.x, hy = hole.y;
|
|
4482
|
+
do {
|
|
4483
|
+
if (hy <= p2.y && hy >= p2.next.y && p2.next.y !== p2.y) {
|
|
4484
|
+
const x = p2.x + (hy - p2.y) * (p2.next.x - p2.x) / (p2.next.y - p2.y);
|
|
4485
|
+
if (x <= hx && x > qx) {
|
|
4486
|
+
qx = x;
|
|
4487
|
+
m = p2.x < p2.next.x ? p2 : p2.next;
|
|
4488
|
+
if (x === hx) return m;
|
|
4489
|
+
}
|
|
4490
|
+
}
|
|
4491
|
+
p2 = p2.next;
|
|
4492
|
+
} while (p2 !== outerNode);
|
|
4493
|
+
if (!m) return null;
|
|
4494
|
+
const stop = m, mx = m.x, my = m.y;
|
|
4495
|
+
let tanMin = Infinity, tan;
|
|
4496
|
+
p2 = m;
|
|
4497
|
+
do {
|
|
4498
|
+
if (hx >= p2.x && p2.x >= mx && hx !== p2.x && pointInTriangle(hy < my ? hx : qx, hy, mx, my, hy < my ? qx : hx, hy, p2.x, p2.y)) {
|
|
4499
|
+
tan = Math.abs(hy - p2.y) / (hx - p2.x);
|
|
4500
|
+
if (locallyInside(p2, hole) && (tan < tanMin || tan === tanMin && (p2.x > m.x || p2.x === m.x && sectorContainsSector(m, p2)))) {
|
|
4501
|
+
m = p2;
|
|
4502
|
+
tanMin = tan;
|
|
4503
|
+
}
|
|
4504
|
+
}
|
|
4505
|
+
p2 = p2.next;
|
|
4506
|
+
} while (p2 !== stop);
|
|
4507
|
+
return m;
|
|
4508
|
+
}
|
|
4509
|
+
function sectorContainsSector(m, p2) {
|
|
4510
|
+
return area(m.prev, m, p2.prev) < 0 && area(p2.next, m, m.next) < 0;
|
|
4511
|
+
}
|
|
4512
|
+
function indexCurve(start, minX, minY, invSize) {
|
|
4513
|
+
let p2 = start;
|
|
4514
|
+
do {
|
|
4515
|
+
if (p2.z === 0) p2.z = zOrder(p2.x, p2.y, minX, minY, invSize);
|
|
4516
|
+
p2.prevZ = p2.prev;
|
|
4517
|
+
p2.nextZ = p2.next;
|
|
4518
|
+
p2 = p2.next;
|
|
4519
|
+
} while (p2 !== start);
|
|
4520
|
+
p2.prevZ.nextZ = null;
|
|
4521
|
+
p2.prevZ = null;
|
|
4522
|
+
sortLinked(p2);
|
|
4523
|
+
}
|
|
4524
|
+
function sortLinked(list2) {
|
|
4525
|
+
let i, p2, q, e, tail, numMerges, pSize, qSize, inSize = 1;
|
|
4526
|
+
do {
|
|
4527
|
+
p2 = list2;
|
|
4528
|
+
list2 = null;
|
|
4529
|
+
tail = null;
|
|
4530
|
+
numMerges = 0;
|
|
4531
|
+
while (p2) {
|
|
4532
|
+
numMerges++;
|
|
4533
|
+
q = p2;
|
|
4534
|
+
pSize = 0;
|
|
4535
|
+
for (i = 0; i < inSize; i++) {
|
|
4536
|
+
pSize++;
|
|
4537
|
+
q = q.nextZ;
|
|
4538
|
+
if (!q) break;
|
|
4539
|
+
}
|
|
4540
|
+
qSize = inSize;
|
|
4541
|
+
while (pSize > 0 || qSize > 0 && q) {
|
|
4542
|
+
if (pSize !== 0 && (qSize === 0 || !q || p2.z <= q.z)) {
|
|
4543
|
+
e = p2;
|
|
4544
|
+
p2 = p2.nextZ;
|
|
4545
|
+
pSize--;
|
|
4546
|
+
} else {
|
|
4547
|
+
e = q;
|
|
4548
|
+
q = q.nextZ;
|
|
4549
|
+
qSize--;
|
|
4550
|
+
}
|
|
4551
|
+
if (tail) tail.nextZ = e;
|
|
4552
|
+
else list2 = e;
|
|
4553
|
+
e.prevZ = tail;
|
|
4554
|
+
tail = e;
|
|
4555
|
+
}
|
|
4556
|
+
p2 = q;
|
|
4557
|
+
}
|
|
4558
|
+
tail.nextZ = null;
|
|
4559
|
+
inSize *= 2;
|
|
4560
|
+
} while (numMerges > 1);
|
|
4561
|
+
return list2;
|
|
4562
|
+
}
|
|
4563
|
+
function zOrder(x, y, minX, minY, invSize) {
|
|
4564
|
+
x = (x - minX) * invSize | 0;
|
|
4565
|
+
y = (y - minY) * invSize | 0;
|
|
4566
|
+
x = (x | x << 8) & 16711935;
|
|
4567
|
+
x = (x | x << 4) & 252645135;
|
|
4568
|
+
x = (x | x << 2) & 858993459;
|
|
4569
|
+
x = (x | x << 1) & 1431655765;
|
|
4570
|
+
y = (y | y << 8) & 16711935;
|
|
4571
|
+
y = (y | y << 4) & 252645135;
|
|
4572
|
+
y = (y | y << 2) & 858993459;
|
|
4573
|
+
y = (y | y << 1) & 1431655765;
|
|
4574
|
+
return x | y << 1;
|
|
4575
|
+
}
|
|
4576
|
+
function getLeftmost(start) {
|
|
4577
|
+
let p2 = start, leftmost = start;
|
|
4578
|
+
do {
|
|
4579
|
+
if (p2.x < leftmost.x || p2.x === leftmost.x && p2.y < leftmost.y) leftmost = p2;
|
|
4580
|
+
p2 = p2.next;
|
|
4581
|
+
} while (p2 !== start);
|
|
4582
|
+
return leftmost;
|
|
4583
|
+
}
|
|
4584
|
+
function pointInTriangle(ax, ay, bx, by, cx, cy, px, py) {
|
|
4585
|
+
return (cx - px) * (ay - py) >= (ax - px) * (cy - py) && (ax - px) * (by - py) >= (bx - px) * (ay - py) && (bx - px) * (cy - py) >= (cx - px) * (by - py);
|
|
4586
|
+
}
|
|
4587
|
+
function isValidDiagonal(a, b) {
|
|
4588
|
+
return a.next.i !== b.i && a.prev.i !== b.i && !intersectsPolygon(a, b) && // dones't intersect other edges
|
|
4589
|
+
(locallyInside(a, b) && locallyInside(b, a) && middleInside(a, b) && // locally visible
|
|
4590
|
+
(area(a.prev, a, b.prev) || area(a, b.prev, b)) || // does not create opposite-facing sectors
|
|
4591
|
+
equals(a, b) && area(a.prev, a, a.next) > 0 && area(b.prev, b, b.next) > 0);
|
|
4592
|
+
}
|
|
4593
|
+
function area(p2, q, r) {
|
|
4594
|
+
return (q.y - p2.y) * (r.x - q.x) - (q.x - p2.x) * (r.y - q.y);
|
|
4595
|
+
}
|
|
4596
|
+
function equals(p1, p2) {
|
|
4597
|
+
return p1.x === p2.x && p1.y === p2.y;
|
|
4598
|
+
}
|
|
4599
|
+
function intersects(p1, q1, p2, q2) {
|
|
4600
|
+
const o1 = sign(area(p1, q1, p2));
|
|
4601
|
+
const o2 = sign(area(p1, q1, q2));
|
|
4602
|
+
const o3 = sign(area(p2, q2, p1));
|
|
4603
|
+
const o4 = sign(area(p2, q2, q1));
|
|
4604
|
+
if (o1 !== o2 && o3 !== o4) return true;
|
|
4605
|
+
if (o1 === 0 && onSegment(p1, p2, q1)) return true;
|
|
4606
|
+
if (o2 === 0 && onSegment(p1, q2, q1)) return true;
|
|
4607
|
+
if (o3 === 0 && onSegment(p2, p1, q2)) return true;
|
|
4608
|
+
if (o4 === 0 && onSegment(p2, q1, q2)) return true;
|
|
4609
|
+
return false;
|
|
4610
|
+
}
|
|
4611
|
+
function onSegment(p2, q, r) {
|
|
4612
|
+
return q.x <= Math.max(p2.x, r.x) && q.x >= Math.min(p2.x, r.x) && q.y <= Math.max(p2.y, r.y) && q.y >= Math.min(p2.y, r.y);
|
|
4613
|
+
}
|
|
4614
|
+
function sign(num2) {
|
|
4615
|
+
return num2 > 0 ? 1 : num2 < 0 ? -1 : 0;
|
|
4616
|
+
}
|
|
4617
|
+
function intersectsPolygon(a, b) {
|
|
4618
|
+
let p2 = a;
|
|
4619
|
+
do {
|
|
4620
|
+
if (p2.i !== a.i && p2.next.i !== a.i && p2.i !== b.i && p2.next.i !== b.i && intersects(p2, p2.next, a, b)) return true;
|
|
4621
|
+
p2 = p2.next;
|
|
4622
|
+
} while (p2 !== a);
|
|
4623
|
+
return false;
|
|
4624
|
+
}
|
|
4625
|
+
function locallyInside(a, b) {
|
|
4626
|
+
return area(a.prev, a, a.next) < 0 ? area(a, b, a.next) >= 0 && area(a, a.prev, b) >= 0 : area(a, b, a.prev) < 0 || area(a, a.next, b) < 0;
|
|
4627
|
+
}
|
|
4628
|
+
function middleInside(a, b) {
|
|
4629
|
+
let p2 = a, inside = false;
|
|
4630
|
+
const px = (a.x + b.x) / 2, py = (a.y + b.y) / 2;
|
|
4631
|
+
do {
|
|
4632
|
+
if (p2.y > py !== p2.next.y > py && p2.next.y !== p2.y && px < (p2.next.x - p2.x) * (py - p2.y) / (p2.next.y - p2.y) + p2.x)
|
|
4633
|
+
inside = !inside;
|
|
4634
|
+
p2 = p2.next;
|
|
4635
|
+
} while (p2 !== a);
|
|
4636
|
+
return inside;
|
|
4637
|
+
}
|
|
4638
|
+
function splitPolygon(a, b) {
|
|
4639
|
+
const a2 = new Node(a.i, a.x, a.y), b2 = new Node(b.i, b.x, b.y), an = a.next, bp = b.prev;
|
|
4640
|
+
a.next = b;
|
|
4641
|
+
b.prev = a;
|
|
4642
|
+
a2.next = an;
|
|
4643
|
+
an.prev = a2;
|
|
4644
|
+
b2.next = a2;
|
|
4645
|
+
a2.prev = b2;
|
|
4646
|
+
bp.next = b2;
|
|
4647
|
+
b2.prev = bp;
|
|
4648
|
+
return b2;
|
|
4649
|
+
}
|
|
4650
|
+
function insertNode(i, x, y, last) {
|
|
4651
|
+
const p2 = new Node(i, x, y);
|
|
4652
|
+
if (!last) {
|
|
4653
|
+
p2.prev = p2;
|
|
4654
|
+
p2.next = p2;
|
|
4655
|
+
} else {
|
|
4656
|
+
p2.next = last.next;
|
|
4657
|
+
p2.prev = last;
|
|
4658
|
+
last.next.prev = p2;
|
|
4659
|
+
last.next = p2;
|
|
4660
|
+
}
|
|
4661
|
+
return p2;
|
|
4662
|
+
}
|
|
4663
|
+
function removeNode(p2) {
|
|
4664
|
+
p2.next.prev = p2.prev;
|
|
4665
|
+
p2.prev.next = p2.next;
|
|
4666
|
+
if (p2.prevZ) p2.prevZ.nextZ = p2.nextZ;
|
|
4667
|
+
if (p2.nextZ) p2.nextZ.prevZ = p2.prevZ;
|
|
4668
|
+
}
|
|
4669
|
+
function Node(i, x, y) {
|
|
4670
|
+
this.i = i;
|
|
4671
|
+
this.x = x;
|
|
4672
|
+
this.y = y;
|
|
4673
|
+
this.prev = null;
|
|
4674
|
+
this.next = null;
|
|
4675
|
+
this.z = 0;
|
|
4676
|
+
this.prevZ = null;
|
|
4677
|
+
this.nextZ = null;
|
|
4678
|
+
this.steiner = false;
|
|
4679
|
+
}
|
|
4680
|
+
function signedArea(data, start, end, dim) {
|
|
4681
|
+
let sum = 0;
|
|
4682
|
+
for (let i = start, j = end - dim; i < end; i += dim) {
|
|
4683
|
+
sum += (data[j] - data[i]) * (data[i + 1] + data[j + 1]);
|
|
4684
|
+
j = i;
|
|
4685
|
+
}
|
|
4686
|
+
return sum;
|
|
4687
|
+
}
|
|
4688
|
+
var equals2 = (a, b) => a.x === b.x && a.y === b.y;
|
|
4689
|
+
var linePoint = (v1, v2, t) => t === 1 ? { x: v2.x, y: v2.y } : { x: (v2.x - v1.x) * t + v1.x, y: (v2.y - v1.y) * t + v1.y };
|
|
4690
|
+
function pathPoints(points) {
|
|
4691
|
+
const out = [];
|
|
4692
|
+
let last;
|
|
4693
|
+
for (let i = 1; i < points.length; i++) {
|
|
4694
|
+
const v1 = { x: points[i - 1][0], y: points[i - 1][1] };
|
|
4695
|
+
const v2 = { x: points[i][0], y: points[i][1] };
|
|
4696
|
+
for (let d = 0; d <= 1; d++) {
|
|
4697
|
+
const point = linePoint(v1, v2, d / 1);
|
|
4698
|
+
if (last && equals2(last, point)) continue;
|
|
4699
|
+
out.push(point);
|
|
4700
|
+
last = point;
|
|
4701
|
+
}
|
|
4702
|
+
}
|
|
4703
|
+
return out;
|
|
4704
|
+
}
|
|
4705
|
+
function area2(contour) {
|
|
4706
|
+
const n = contour.length;
|
|
4707
|
+
let a = 0;
|
|
4708
|
+
for (let p2 = n - 1, q = 0; q < n; p2 = q++) a += contour[p2].x * contour[q].y - contour[q].x * contour[p2].y;
|
|
4709
|
+
return a * 0.5;
|
|
4710
|
+
}
|
|
4711
|
+
var isClockWise = (pts) => area2(pts) < 0;
|
|
4712
|
+
function removeDupEndPts(points) {
|
|
4713
|
+
const l = points.length;
|
|
4714
|
+
if (l > 2 && equals2(points[l - 1], points[0])) points.pop();
|
|
4715
|
+
}
|
|
4716
|
+
function triangulateShape(contour, holes) {
|
|
4717
|
+
const vertices = [];
|
|
4718
|
+
const holeIndices = [];
|
|
4719
|
+
const faces = [];
|
|
4720
|
+
removeDupEndPts(contour);
|
|
4721
|
+
for (const p2 of contour) vertices.push(p2.x, p2.y);
|
|
4722
|
+
let holeIndex = contour.length;
|
|
4723
|
+
holes.forEach(removeDupEndPts);
|
|
4724
|
+
for (let i = 0; i < holes.length; i++) {
|
|
4725
|
+
holeIndices.push(holeIndex);
|
|
4726
|
+
holeIndex += holes[i].length;
|
|
4727
|
+
for (const p2 of holes[i]) vertices.push(p2.x, p2.y);
|
|
4728
|
+
}
|
|
4729
|
+
const triangles = Earcut.triangulate(vertices, holeIndices);
|
|
4730
|
+
for (let i = 0; i < triangles.length; i += 3) faces.push(triangles.slice(i, i + 3));
|
|
4731
|
+
return faces;
|
|
4732
|
+
}
|
|
4733
|
+
function computeVertexNormals(positions, indices) {
|
|
4734
|
+
const normals = new Float32Array(positions.length);
|
|
4735
|
+
const get = (array, i) => [array[i * 3], array[i * 3 + 1], array[i * 3 + 2]];
|
|
4736
|
+
const face = (vA, vB, vC) => {
|
|
4737
|
+
const pA = get(positions, vA);
|
|
4738
|
+
const pB = get(positions, vB);
|
|
4739
|
+
const pC = get(positions, vC);
|
|
4740
|
+
const cb = [pC[0] - pB[0], pC[1] - pB[1], pC[2] - pB[2]];
|
|
4741
|
+
const ab = [pA[0] - pB[0], pA[1] - pB[1], pA[2] - pB[2]];
|
|
4742
|
+
return [cb[1] * ab[2] - cb[2] * ab[1], cb[2] * ab[0] - cb[0] * ab[2], cb[0] * ab[1] - cb[1] * ab[0]];
|
|
4743
|
+
};
|
|
4744
|
+
const set = (i, x, y, z) => {
|
|
4745
|
+
normals[i * 3] = x;
|
|
4746
|
+
normals[i * 3 + 1] = y;
|
|
4747
|
+
normals[i * 3 + 2] = z;
|
|
4748
|
+
};
|
|
4749
|
+
if (indices) {
|
|
4750
|
+
for (let i = 0; i < indices.length; i += 3) {
|
|
4751
|
+
const vA = indices[i];
|
|
4752
|
+
const vB = indices[i + 1];
|
|
4753
|
+
const vC = indices[i + 2];
|
|
4754
|
+
const cb = face(vA, vB, vC);
|
|
4755
|
+
for (const v of [vA, vB, vC]) {
|
|
4756
|
+
const n = get(normals, v);
|
|
4757
|
+
set(v, n[0] + cb[0], n[1] + cb[1], n[2] + cb[2]);
|
|
4758
|
+
}
|
|
4759
|
+
}
|
|
4760
|
+
} else {
|
|
4761
|
+
for (let i = 0; i < positions.length / 3; i += 3) {
|
|
4762
|
+
const cb = face(i, i + 1, i + 2);
|
|
4763
|
+
set(i, cb[0], cb[1], cb[2]);
|
|
4764
|
+
set(i + 1, cb[0], cb[1], cb[2]);
|
|
4765
|
+
set(i + 2, cb[0], cb[1], cb[2]);
|
|
4766
|
+
}
|
|
4767
|
+
}
|
|
4768
|
+
for (let i = 0; i < normals.length / 3; i++) {
|
|
4769
|
+
const [x, y, z] = get(normals, i);
|
|
4770
|
+
const s = 1 / (Math.sqrt(x * x + y * y + z * z) || 1);
|
|
4771
|
+
set(i, x * s, y * s, z * s);
|
|
4772
|
+
}
|
|
4773
|
+
return normals;
|
|
4774
|
+
}
|
|
4775
|
+
function extrude(outline, depth = 1, steps = 1, bevel = void 0) {
|
|
4776
|
+
const parameters = { shape: outline, depth, steps, bevel: bevel ?? {} };
|
|
4777
|
+
const verticesArray = [];
|
|
4778
|
+
const uvArray = [];
|
|
4779
|
+
const groups = [];
|
|
4780
|
+
const placeholder = [];
|
|
4781
|
+
const bevelEnabled = bevel !== false;
|
|
4782
|
+
const spec = bevel === false || bevel === void 0 ? {} : bevel;
|
|
4783
|
+
let bevelThickness = spec.thickness !== void 0 ? spec.thickness : 0.2;
|
|
4784
|
+
let bevelSize = spec.size !== void 0 ? spec.size : bevelThickness - 0.1;
|
|
4785
|
+
let bevelOffset = spec.offset !== void 0 ? spec.offset : 0;
|
|
4786
|
+
let bevelSegments = spec.segments !== void 0 ? spec.segments : 3;
|
|
4787
|
+
if (!bevelEnabled) {
|
|
4788
|
+
bevelSegments = 0;
|
|
4789
|
+
bevelThickness = 0;
|
|
4790
|
+
bevelSize = 0;
|
|
4791
|
+
bevelOffset = 0;
|
|
4792
|
+
}
|
|
4793
|
+
let vertices = pathPoints(outline.outer);
|
|
4794
|
+
const holes = (outline.holes ?? []).map(pathPoints);
|
|
4795
|
+
const reverse = !isClockWise(vertices);
|
|
4796
|
+
if (reverse) {
|
|
4797
|
+
vertices = vertices.reverse();
|
|
4798
|
+
for (let h = 0; h < holes.length; h++) {
|
|
4799
|
+
const ahole = holes[h];
|
|
4800
|
+
if (isClockWise(ahole)) holes[h] = ahole.reverse();
|
|
4801
|
+
}
|
|
4802
|
+
}
|
|
4803
|
+
const faces = triangulateShape(vertices, holes);
|
|
4804
|
+
const contour = vertices;
|
|
4805
|
+
for (const ahole of holes) vertices = vertices.concat(ahole);
|
|
4806
|
+
const scalePt2 = (pt, vec, size) => ({ x: pt.x + vec.x * size, y: pt.y + vec.y * size });
|
|
4807
|
+
const vlen = vertices.length;
|
|
4808
|
+
const flen = faces.length;
|
|
4809
|
+
const getBevelVec = (inPt, inPrev, inNext) => {
|
|
4810
|
+
let vTransX;
|
|
4811
|
+
let vTransY;
|
|
4812
|
+
let shrinkBy;
|
|
4813
|
+
const vPrevX = inPt.x - inPrev.x;
|
|
4814
|
+
const vPrevY = inPt.y - inPrev.y;
|
|
4815
|
+
const vNextX = inNext.x - inPt.x;
|
|
4816
|
+
const vNextY = inNext.y - inPt.y;
|
|
4817
|
+
const vPrevLensq = vPrevX * vPrevX + vPrevY * vPrevY;
|
|
4818
|
+
const collinear0 = vPrevX * vNextY - vPrevY * vNextX;
|
|
4819
|
+
if (Math.abs(collinear0) > Number.EPSILON) {
|
|
4820
|
+
const vPrevLen = Math.sqrt(vPrevLensq);
|
|
4821
|
+
const vNextLen = Math.sqrt(vNextX * vNextX + vNextY * vNextY);
|
|
4822
|
+
const ptPrevShiftX = inPrev.x - vPrevY / vPrevLen;
|
|
4823
|
+
const ptPrevShiftY = inPrev.y + vPrevX / vPrevLen;
|
|
4824
|
+
const ptNextShiftX = inNext.x - vNextY / vNextLen;
|
|
4825
|
+
const ptNextShiftY = inNext.y + vNextX / vNextLen;
|
|
4826
|
+
const sf = ((ptNextShiftX - ptPrevShiftX) * vNextY - (ptNextShiftY - ptPrevShiftY) * vNextX) / (vPrevX * vNextY - vPrevY * vNextX);
|
|
4827
|
+
vTransX = ptPrevShiftX + vPrevX * sf - inPt.x;
|
|
4828
|
+
vTransY = ptPrevShiftY + vPrevY * sf - inPt.y;
|
|
4829
|
+
const vTransLensq = vTransX * vTransX + vTransY * vTransY;
|
|
4830
|
+
if (vTransLensq <= 2) return { x: vTransX, y: vTransY };
|
|
4831
|
+
shrinkBy = Math.sqrt(vTransLensq / 2);
|
|
4832
|
+
} else {
|
|
4833
|
+
let directionEq = false;
|
|
4834
|
+
if (vPrevX > Number.EPSILON) {
|
|
4835
|
+
if (vNextX > Number.EPSILON) directionEq = true;
|
|
4836
|
+
} else if (vPrevX < -Number.EPSILON) {
|
|
4837
|
+
if (vNextX < -Number.EPSILON) directionEq = true;
|
|
4838
|
+
} else if (Math.sign(vPrevY) === Math.sign(vNextY)) {
|
|
4839
|
+
directionEq = true;
|
|
4840
|
+
}
|
|
4841
|
+
if (directionEq) {
|
|
4842
|
+
vTransX = -vPrevY;
|
|
4843
|
+
vTransY = vPrevX;
|
|
4844
|
+
shrinkBy = Math.sqrt(vPrevLensq);
|
|
4845
|
+
} else {
|
|
4846
|
+
vTransX = vPrevX;
|
|
4847
|
+
vTransY = vPrevY;
|
|
4848
|
+
shrinkBy = Math.sqrt(vPrevLensq / 2);
|
|
4849
|
+
}
|
|
4850
|
+
}
|
|
4851
|
+
return { x: vTransX / shrinkBy, y: vTransY / shrinkBy };
|
|
4852
|
+
};
|
|
4853
|
+
const movements = (ring2) => {
|
|
4854
|
+
const out = [];
|
|
4855
|
+
for (let i = 0, il = ring2.length, j = il - 1, k = i + 1; i < il; i++, j++, k++) {
|
|
4856
|
+
if (j === il) j = 0;
|
|
4857
|
+
if (k === il) k = 0;
|
|
4858
|
+
out[i] = getBevelVec(ring2[i], ring2[j], ring2[k]);
|
|
4859
|
+
}
|
|
4860
|
+
return out;
|
|
4861
|
+
};
|
|
4862
|
+
const contourMovements = movements(contour);
|
|
4863
|
+
const holesMovements = [];
|
|
4864
|
+
let verticesMovements = contourMovements.concat();
|
|
4865
|
+
for (const ahole of holes) {
|
|
4866
|
+
const oneHoleMovements = movements(ahole);
|
|
4867
|
+
holesMovements.push(oneHoleMovements);
|
|
4868
|
+
verticesMovements = verticesMovements.concat(oneHoleMovements);
|
|
4869
|
+
}
|
|
4870
|
+
const v = (x, y, z) => {
|
|
4871
|
+
placeholder.push(x);
|
|
4872
|
+
placeholder.push(y);
|
|
4873
|
+
placeholder.push(z);
|
|
4874
|
+
};
|
|
4875
|
+
const bevelLayer = (b, zOf) => {
|
|
4876
|
+
const t = b / bevelSegments;
|
|
4877
|
+
const z = bevelThickness * Math.cos(t * Math.PI / 2);
|
|
4878
|
+
const bs2 = bevelSize * Math.sin(t * Math.PI / 2) + bevelOffset;
|
|
4879
|
+
for (let i = 0; i < contour.length; i++) {
|
|
4880
|
+
const vert = scalePt2(contour[i], contourMovements[i], bs2);
|
|
4881
|
+
v(vert.x, vert.y, zOf(z));
|
|
4882
|
+
}
|
|
4883
|
+
for (let h = 0; h < holes.length; h++) {
|
|
4884
|
+
const ahole = holes[h];
|
|
4885
|
+
const oneHoleMovements = holesMovements[h];
|
|
4886
|
+
for (let i = 0; i < ahole.length; i++) {
|
|
4887
|
+
const vert = scalePt2(ahole[i], oneHoleMovements[i], bs2);
|
|
4888
|
+
v(vert.x, vert.y, zOf(z));
|
|
4889
|
+
}
|
|
4890
|
+
}
|
|
4891
|
+
};
|
|
4892
|
+
for (let b = 0; b < bevelSegments; b++) bevelLayer(b, (z) => -z);
|
|
4893
|
+
const bs = bevelSize + bevelOffset;
|
|
4894
|
+
for (let i = 0; i < vlen; i++) {
|
|
4895
|
+
const vert = bevelEnabled ? scalePt2(vertices[i], verticesMovements[i], bs) : vertices[i];
|
|
4896
|
+
v(vert.x, vert.y, 0);
|
|
4897
|
+
}
|
|
4898
|
+
for (let s = 1; s <= steps; s++) {
|
|
4899
|
+
for (let i = 0; i < vlen; i++) {
|
|
4900
|
+
const vert = bevelEnabled ? scalePt2(vertices[i], verticesMovements[i], bs) : vertices[i];
|
|
4901
|
+
v(vert.x, vert.y, depth / steps * s);
|
|
4902
|
+
}
|
|
4903
|
+
}
|
|
4904
|
+
for (let b = bevelSegments - 1; b >= 0; b--) bevelLayer(b, (z) => depth + z);
|
|
4905
|
+
const addVertex = (index) => {
|
|
4906
|
+
verticesArray.push(placeholder[index * 3 + 0]);
|
|
4907
|
+
verticesArray.push(placeholder[index * 3 + 1]);
|
|
4908
|
+
verticesArray.push(placeholder[index * 3 + 2]);
|
|
4909
|
+
};
|
|
4910
|
+
const addUV = (x, y) => {
|
|
4911
|
+
uvArray.push(x);
|
|
4912
|
+
uvArray.push(y);
|
|
4913
|
+
};
|
|
4914
|
+
const at = (index, axis) => verticesArray[index * 3 + axis];
|
|
4915
|
+
const f3 = (a, b, c) => {
|
|
4916
|
+
addVertex(a);
|
|
4917
|
+
addVertex(b);
|
|
4918
|
+
addVertex(c);
|
|
4919
|
+
const nextIndex = verticesArray.length / 3;
|
|
4920
|
+
for (const index of [nextIndex - 3, nextIndex - 2, nextIndex - 1]) addUV(at(index, 0), at(index, 1));
|
|
4921
|
+
};
|
|
4922
|
+
const f4 = (a, b, c, d) => {
|
|
4923
|
+
addVertex(a);
|
|
4924
|
+
addVertex(b);
|
|
4925
|
+
addVertex(d);
|
|
4926
|
+
addVertex(b);
|
|
4927
|
+
addVertex(c);
|
|
4928
|
+
addVertex(d);
|
|
4929
|
+
const nextIndex = verticesArray.length / 3;
|
|
4930
|
+
const iA = nextIndex - 6;
|
|
4931
|
+
const iB = nextIndex - 3;
|
|
4932
|
+
const iC = nextIndex - 2;
|
|
4933
|
+
const iD = nextIndex - 1;
|
|
4934
|
+
const byX = Math.abs(at(iA, 1) - at(iB, 1)) < Math.abs(at(iA, 0) - at(iB, 0));
|
|
4935
|
+
const uv = (index) => [byX ? at(index, 0) : at(index, 1), 1 - at(index, 2)];
|
|
4936
|
+
const uvs = [uv(iA), uv(iB), uv(iC), uv(iD)];
|
|
4937
|
+
for (const k of [0, 1, 3, 1, 2, 3]) addUV(...uvs[k]);
|
|
4938
|
+
};
|
|
4939
|
+
let start = verticesArray.length / 3;
|
|
4940
|
+
if (bevelEnabled) {
|
|
4941
|
+
let offset = 0;
|
|
4942
|
+
for (let i = 0; i < flen; i++) {
|
|
4943
|
+
const face = faces[i];
|
|
4944
|
+
f3(face[2] + offset, face[1] + offset, face[0] + offset);
|
|
4945
|
+
}
|
|
4946
|
+
const layer = steps + bevelSegments * 2;
|
|
4947
|
+
offset = vlen * layer;
|
|
4948
|
+
for (let i = 0; i < flen; i++) {
|
|
4949
|
+
const face = faces[i];
|
|
4950
|
+
f3(face[0] + offset, face[1] + offset, face[2] + offset);
|
|
4951
|
+
}
|
|
4952
|
+
} else {
|
|
4953
|
+
for (let i = 0; i < flen; i++) {
|
|
4954
|
+
const face = faces[i];
|
|
4955
|
+
f3(face[2], face[1], face[0]);
|
|
4956
|
+
}
|
|
4957
|
+
for (let i = 0; i < flen; i++) {
|
|
4958
|
+
const face = faces[i];
|
|
4959
|
+
f3(face[0] + vlen * steps, face[1] + vlen * steps, face[2] + vlen * steps);
|
|
4960
|
+
}
|
|
4961
|
+
}
|
|
4962
|
+
groups.push({ start, count: verticesArray.length / 3 - start, materialIndex: 0 });
|
|
4963
|
+
start = verticesArray.length / 3;
|
|
4964
|
+
const sidewalls = (ring2, layeroffset2) => {
|
|
4965
|
+
let i = ring2.length;
|
|
4966
|
+
while (--i >= 0) {
|
|
4967
|
+
const j = i;
|
|
4968
|
+
let k = i - 1;
|
|
4969
|
+
if (k < 0) k = ring2.length - 1;
|
|
4970
|
+
for (let s = 0, sl = steps + bevelSegments * 2; s < sl; s++) {
|
|
4971
|
+
const slen1 = vlen * s;
|
|
4972
|
+
const slen2 = vlen * (s + 1);
|
|
4973
|
+
f4(layeroffset2 + j + slen1, layeroffset2 + k + slen1, layeroffset2 + k + slen2, layeroffset2 + j + slen2);
|
|
4974
|
+
}
|
|
4975
|
+
}
|
|
4976
|
+
};
|
|
4977
|
+
let layeroffset = 0;
|
|
4978
|
+
sidewalls(contour, layeroffset);
|
|
4979
|
+
layeroffset += contour.length;
|
|
4980
|
+
for (const ahole of holes) {
|
|
4981
|
+
sidewalls(ahole, layeroffset);
|
|
4982
|
+
layeroffset += ahole.length;
|
|
4983
|
+
}
|
|
4984
|
+
groups.push({ start, count: verticesArray.length / 3 - start, materialIndex: 1 });
|
|
4985
|
+
const positions = new Float32Array(verticesArray);
|
|
4986
|
+
return { type: "ExtrudeGeometry", parameters, positions, normals: computeVertexNormals(positions), uvs: new Float32Array(uvArray), groups };
|
|
4987
|
+
}
|
|
4988
|
+
var PARAMETER_KEYS = {
|
|
4989
|
+
box: ["size", "segments"],
|
|
4990
|
+
cylinder: ["radiusTop", "radiusBottom", "height", "radialSegments", "heightSegments", "openEnded", "thetaStart", "thetaLength"],
|
|
4991
|
+
cone: ["radius", "height", "radialSegments", "heightSegments", "openEnded", "thetaStart", "thetaLength"],
|
|
4992
|
+
sphere: ["radius", "widthSegments", "heightSegments", "phiStart", "phiLength", "thetaStart", "thetaLength"],
|
|
4993
|
+
plane: ["width", "height", "widthSegments", "heightSegments"],
|
|
4994
|
+
circle: ["radius", "segments", "thetaStart", "thetaLength"],
|
|
4995
|
+
ring: ["innerRadius", "outerRadius", "thetaSegments", "phiSegments", "thetaStart", "thetaLength"],
|
|
4996
|
+
lathe: ["points", "segments", "phiStart", "phiLength"],
|
|
4997
|
+
torus: ["radius", "tube", "radialSegments", "tubularSegments", "arc"],
|
|
4998
|
+
extrude: ["shape", "depth", "steps", "bevel"],
|
|
4999
|
+
difference: ["size", "subtract"],
|
|
5000
|
+
mesh: ["positions", "normals", "uvs", "indices"]
|
|
5001
|
+
};
|
|
5002
|
+
var SEGMENT_KEYS = {
|
|
5003
|
+
cylinder: ["radialSegments"],
|
|
5004
|
+
cone: ["radialSegments"],
|
|
5005
|
+
sphere: ["widthSegments", "heightSegments"],
|
|
5006
|
+
circle: ["segments"],
|
|
5007
|
+
ring: ["thetaSegments"],
|
|
5008
|
+
lathe: ["segments"],
|
|
5009
|
+
torus: ["radialSegments", "tubularSegments"]
|
|
5010
|
+
};
|
|
5011
|
+
var SEGMENT_DEFAULTS = { radialSegments: 32, widthSegments: 32, heightSegments: 16, segments: 12, thetaSegments: 32, tubularSegments: 48 };
|
|
5012
|
+
var segmentDefault = (kind, key) => kind === "circle" && key === "segments" ? 32 : kind === "torus" && key === "radialSegments" ? 12 : SEGMENT_DEFAULTS[key];
|
|
5013
|
+
function primitiveParameters(node, options = {}) {
|
|
5014
|
+
const out = {};
|
|
5015
|
+
const source = node;
|
|
5016
|
+
for (const key of PARAMETER_KEYS[node.kind]) if (source[key] !== void 0) out[key] = source[key];
|
|
5017
|
+
const detail = options.detail ?? 1;
|
|
5018
|
+
if (detail !== 1) {
|
|
5019
|
+
const floor = options.minSegments ?? 3;
|
|
5020
|
+
for (const key of SEGMENT_KEYS[node.kind] ?? []) {
|
|
5021
|
+
const given = out[key] ?? segmentDefault(node.kind, key);
|
|
5022
|
+
out[key] = Math.max(floor, Math.round(given * detail));
|
|
5023
|
+
}
|
|
5024
|
+
}
|
|
5025
|
+
return out;
|
|
5026
|
+
}
|
|
5027
|
+
function mesh(p2) {
|
|
5028
|
+
const positions = new Float32Array(p2.positions);
|
|
5029
|
+
const indices = p2.indices ? indexArray(p2.indices) : void 0;
|
|
5030
|
+
return {
|
|
5031
|
+
type: "BufferGeometry",
|
|
5032
|
+
parameters: {},
|
|
5033
|
+
positions,
|
|
5034
|
+
normals: p2.normals ? new Float32Array(p2.normals) : computeVertexNormals(positions, indices),
|
|
5035
|
+
uvs: p2.uvs ? new Float32Array(p2.uvs) : new Float32Array(positions.length / 3 * 2),
|
|
5036
|
+
...indices ? { indices } : {},
|
|
5037
|
+
groups: []
|
|
5038
|
+
};
|
|
5039
|
+
}
|
|
5040
|
+
function make(kind, p2) {
|
|
5041
|
+
switch (kind) {
|
|
5042
|
+
case "box": {
|
|
5043
|
+
const size = p2.size ?? [1, 1, 1];
|
|
5044
|
+
const segments = p2.segments ?? [1, 1, 1];
|
|
5045
|
+
return box(size[0], size[1], size[2], segments[0], segments[1], segments[2]);
|
|
5046
|
+
}
|
|
5047
|
+
case "cylinder":
|
|
5048
|
+
return cylinder(p2.radiusTop, p2.radiusBottom, p2.height, p2.radialSegments, p2.heightSegments, p2.openEnded, p2.thetaStart, p2.thetaLength);
|
|
5049
|
+
case "cone":
|
|
5050
|
+
return cone(p2.radius, p2.height, p2.radialSegments, p2.heightSegments, p2.openEnded, p2.thetaStart, p2.thetaLength);
|
|
5051
|
+
case "sphere":
|
|
5052
|
+
return sphere(p2.radius, p2.widthSegments, p2.heightSegments, p2.phiStart, p2.phiLength, p2.thetaStart, p2.thetaLength);
|
|
5053
|
+
case "plane":
|
|
5054
|
+
return plane(p2.width, p2.height, p2.widthSegments, p2.heightSegments);
|
|
5055
|
+
case "circle":
|
|
5056
|
+
return circle(p2.radius, p2.segments, p2.thetaStart, p2.thetaLength);
|
|
5057
|
+
case "ring":
|
|
5058
|
+
return ring(p2.innerRadius, p2.outerRadius, p2.thetaSegments, p2.phiSegments, p2.thetaStart, p2.thetaLength);
|
|
5059
|
+
case "lathe":
|
|
5060
|
+
return lathe(p2.points, p2.segments, p2.phiStart, p2.phiLength);
|
|
5061
|
+
case "torus":
|
|
5062
|
+
return torus(p2.radius, p2.tube, p2.radialSegments, p2.tubularSegments, p2.arc);
|
|
5063
|
+
case "extrude":
|
|
5064
|
+
return extrude(p2.shape, p2.depth, p2.steps, p2.bevel);
|
|
5065
|
+
case "difference":
|
|
5066
|
+
return difference(p2.size, p2.subtract ?? []);
|
|
5067
|
+
case "mesh":
|
|
5068
|
+
return mesh(p2);
|
|
5069
|
+
default:
|
|
5070
|
+
throw new Error(`game-shapes: unknown primitive kind "${String(kind)}"`);
|
|
5071
|
+
}
|
|
5072
|
+
}
|
|
5073
|
+
var templates = /* @__PURE__ */ new Map();
|
|
5074
|
+
var templateLimit = 4096;
|
|
5075
|
+
var stats = { hits: 0, misses: 0 };
|
|
5076
|
+
function buildPrimitive(node, options = {}) {
|
|
5077
|
+
const parameters = primitiveParameters(node, options);
|
|
5078
|
+
if (node.kind === "mesh" || templateLimit === 0) return make(node.kind, parameters);
|
|
5079
|
+
const key = `${node.kind}:${canonicalJson(parameters)}`;
|
|
5080
|
+
const cached = templates.get(key);
|
|
5081
|
+
if (cached) {
|
|
5082
|
+
stats.hits++;
|
|
5083
|
+
templates.delete(key);
|
|
5084
|
+
templates.set(key, cached);
|
|
5085
|
+
return cached;
|
|
5086
|
+
}
|
|
5087
|
+
stats.misses++;
|
|
5088
|
+
const built = make(node.kind, parameters);
|
|
5089
|
+
templates.set(key, built);
|
|
5090
|
+
if (templates.size > templateLimit) templates.delete(templates.keys().next().value);
|
|
5091
|
+
return built;
|
|
5092
|
+
}
|
|
5093
|
+
var num = (v) => typeof v === "number" && Number.isFinite(v) ? null : "expected a finite number";
|
|
5094
|
+
var bool = (v) => typeof v === "boolean" ? null : "expected a boolean";
|
|
5095
|
+
var str = (v) => typeof v === "string" ? null : "expected a string";
|
|
5096
|
+
var int = (min) => (v) => typeof v === "number" && Number.isInteger(v) && v >= min ? null : `expected an integer >= ${min}`;
|
|
5097
|
+
var range = (lo, hi, loOpen = false) => (v) => typeof v === "number" && (loOpen ? v > lo : v >= lo) && v <= hi ? null : `expected a number in ${loOpen ? "(" : "["}${lo}, ${hi}]`;
|
|
5098
|
+
var tuple = (n, item = num) => (v) => {
|
|
5099
|
+
if (!Array.isArray(v) || v.length !== n) return `expected an array of ${n}`;
|
|
5100
|
+
for (const x of v) if (item(x)) return `expected an array of ${n} numbers`;
|
|
5101
|
+
return null;
|
|
5102
|
+
};
|
|
5103
|
+
var list = (item, min = 0) => (v) => {
|
|
5104
|
+
if (!Array.isArray(v)) return "expected an array";
|
|
5105
|
+
if (v.length < min) return `expected at least ${min} items`;
|
|
5106
|
+
for (let i = 0; i < v.length; i++) {
|
|
5107
|
+
const e = item(v[i]);
|
|
5108
|
+
if (e) return `[${i}]: ${e}`;
|
|
5109
|
+
}
|
|
5110
|
+
return null;
|
|
5111
|
+
};
|
|
5112
|
+
var color = (v) => typeof v === "number" && Number.isInteger(v) && v >= 0 && v <= 16777215 || typeof v === "string" && /^#[0-9a-fA-F]{6}$/.test(v) ? null : 'expected 0xRRGGBB or "#rrggbb"';
|
|
5113
|
+
var oneOf = (values) => (v) => values.includes(v) ? null : `expected one of ${values.map((x) => JSON.stringify(x)).join(", ")}`;
|
|
5114
|
+
var object = (fields, required = []) => (v) => {
|
|
5115
|
+
if (!v || typeof v !== "object" || Array.isArray(v)) return "expected an object";
|
|
5116
|
+
const record = v;
|
|
5117
|
+
for (const key of required) if (record[key] === void 0) return `${key}: required`;
|
|
5118
|
+
for (const key of Object.keys(record)) {
|
|
5119
|
+
if (record[key] === void 0) continue;
|
|
5120
|
+
const check = fields[key];
|
|
5121
|
+
if (!check) return `${key}: unknown field`;
|
|
5122
|
+
const e = check(record[key]);
|
|
5123
|
+
if (e) return `${key}: ${e}`;
|
|
5124
|
+
}
|
|
5125
|
+
return null;
|
|
5126
|
+
};
|
|
5127
|
+
var ORDERS = ["XYZ", "YXZ", "ZXY", "ZYX", "YZX", "XZY"];
|
|
5128
|
+
var TRANSFORM = {
|
|
5129
|
+
position: tuple(3),
|
|
5130
|
+
rotation: tuple(3),
|
|
5131
|
+
rotationOrder: oneOf(ORDERS),
|
|
5132
|
+
scale: (v) => typeof v === "number" ? num(v) : tuple(3)(v),
|
|
5133
|
+
heading: num,
|
|
5134
|
+
matrix: tuple(16)
|
|
5135
|
+
};
|
|
5136
|
+
var UV = object({ u0: num, v0: num, u1: num, v1: num }, ["u0", "v0", "u1", "v1"]);
|
|
5137
|
+
var INSTANCE = object({ ...TRANSFORM, color });
|
|
5138
|
+
var COMMON = {
|
|
5139
|
+
...TRANSFORM,
|
|
5140
|
+
kind: str,
|
|
5141
|
+
name: str,
|
|
5142
|
+
part: str,
|
|
5143
|
+
material: str,
|
|
5144
|
+
color,
|
|
5145
|
+
uv: UV,
|
|
5146
|
+
instances: list(INSTANCE),
|
|
5147
|
+
minDetail: range(0, 1, true),
|
|
5148
|
+
tags: list(str)
|
|
5149
|
+
};
|
|
5150
|
+
var vec2 = tuple(2);
|
|
5151
|
+
var BEVEL = (v) => v === false ? null : object({ thickness: num, size: num, offset: num, segments: int(1) })(v);
|
|
5152
|
+
var KINDS = {
|
|
5153
|
+
group: { fields: {} },
|
|
5154
|
+
box: { fields: { size: tuple(3), segments: tuple(3, int(1)) } },
|
|
5155
|
+
cylinder: { fields: { radiusTop: num, radiusBottom: num, height: num, radialSegments: int(1), heightSegments: int(1), openEnded: bool, thetaStart: num, thetaLength: num } },
|
|
5156
|
+
cone: { fields: { radius: num, height: num, radialSegments: int(1), heightSegments: int(1), openEnded: bool, thetaStart: num, thetaLength: num } },
|
|
5157
|
+
sphere: { fields: { radius: num, widthSegments: int(3), heightSegments: int(2), phiStart: num, phiLength: num, thetaStart: num, thetaLength: num } },
|
|
5158
|
+
plane: { fields: { width: num, height: num, widthSegments: int(1), heightSegments: int(1) } },
|
|
5159
|
+
circle: { fields: { radius: num, segments: int(3), thetaStart: num, thetaLength: num } },
|
|
5160
|
+
ring: { fields: { innerRadius: num, outerRadius: num, thetaSegments: int(3), phiSegments: int(1), thetaStart: num, thetaLength: num } },
|
|
5161
|
+
lathe: { fields: { points: list(vec2, 2), segments: int(1), phiStart: num, phiLength: num }, required: ["points"] },
|
|
5162
|
+
torus: { fields: { radius: num, tube: num, radialSegments: int(1), tubularSegments: int(1), arc: num } },
|
|
5163
|
+
extrude: {
|
|
5164
|
+
fields: { shape: object({ outer: list(vec2, 3), holes: list(list(vec2, 3)) }, ["outer"]), depth: num, steps: int(1), bevel: BEVEL },
|
|
5165
|
+
required: ["shape"]
|
|
5166
|
+
},
|
|
5167
|
+
difference: { fields: { size: tuple(3), subtract: list(object({ min: vec2, max: vec2 }, ["min", "max"])) }, required: ["size", "subtract"] },
|
|
5168
|
+
mesh: {
|
|
5169
|
+
fields: {
|
|
5170
|
+
positions: (v) => list(num)(v) ?? (v.length % 3 === 0 ? null : "expected a multiple of 3 numbers"),
|
|
5171
|
+
normals: list(num),
|
|
5172
|
+
uvs: list(num),
|
|
5173
|
+
indices: list(int(0))
|
|
5174
|
+
},
|
|
5175
|
+
required: ["positions"]
|
|
5176
|
+
},
|
|
5177
|
+
point: { fields: { data: () => null } },
|
|
5178
|
+
custom: { fields: { generator: str, params: () => null }, required: ["generator"] }
|
|
5179
|
+
};
|
|
5180
|
+
|
|
5181
|
+
// ../game-shapes-three/dist/index.js
|
|
5182
|
+
var UV_BEFORE_NORMAL = /* @__PURE__ */ new Set(["LatheGeometry", "ExtrudeGeometry"]);
|
|
5183
|
+
var INDEX_FIRST = /* @__PURE__ */ new Set(["BoxGeometry", "CylinderGeometry", "ConeGeometry", "SphereGeometry", "PlaneGeometry", "CircleGeometry", "RingGeometry", "LatheGeometry", "TorusGeometry"]);
|
|
5184
|
+
var isPrimitive = (value) => typeof value.type === "string";
|
|
5185
|
+
function threeParameters(THREE, p2) {
|
|
5186
|
+
if (p2.type === "LatheGeometry") {
|
|
5187
|
+
const points = p2.parameters.points.map(({ x, y }) => new THREE.Vector2(x, y));
|
|
5188
|
+
return { ...p2.parameters, points };
|
|
5189
|
+
}
|
|
5190
|
+
return { ...p2.parameters };
|
|
5191
|
+
}
|
|
5192
|
+
function toGeometry(THREE, source, options = {}) {
|
|
5193
|
+
const copy = options.copy !== false;
|
|
5194
|
+
const primitive = isPrimitive(source) ? source : null;
|
|
5195
|
+
const ThreeClass = primitive && primitive.type !== "BufferGeometry" ? THREE[primitive.type] : void 0;
|
|
5196
|
+
const geometry = ThreeClass ? Reflect.construct(THREE.BufferGeometry, [], ThreeClass) : new THREE.BufferGeometry();
|
|
5197
|
+
if (primitive && ThreeClass) {
|
|
5198
|
+
Object.assign(geometry, { type: primitive.type, parameters: threeParameters(THREE, primitive) });
|
|
5199
|
+
}
|
|
5200
|
+
const attribute = (array, size) => copy ? new THREE.Float32BufferAttribute(array, size) : new THREE.BufferAttribute(array, size);
|
|
5201
|
+
const index = source.indices;
|
|
5202
|
+
const setIndex = () => {
|
|
5203
|
+
if (!index) return;
|
|
5204
|
+
geometry.setIndex(copy ? index instanceof Uint32Array ? new THREE.Uint32BufferAttribute(index, 1) : new THREE.Uint16BufferAttribute(index, 1) : new THREE.BufferAttribute(index, 1));
|
|
5205
|
+
};
|
|
5206
|
+
const type = primitive?.type ?? "BufferGeometry";
|
|
5207
|
+
if (INDEX_FIRST.has(type)) setIndex();
|
|
5208
|
+
geometry.setAttribute("position", attribute(source.positions, 3));
|
|
5209
|
+
if (UV_BEFORE_NORMAL.has(type)) {
|
|
5210
|
+
geometry.setAttribute("uv", attribute(source.uvs, 2));
|
|
5211
|
+
geometry.setAttribute("normal", attribute(source.normals, 3));
|
|
5212
|
+
} else {
|
|
5213
|
+
geometry.setAttribute("normal", attribute(source.normals, 3));
|
|
5214
|
+
geometry.setAttribute("uv", attribute(source.uvs, 2));
|
|
5215
|
+
}
|
|
5216
|
+
if (!primitive && source.colors) geometry.setAttribute("color", attribute(source.colors, 3));
|
|
5217
|
+
if (!INDEX_FIRST.has(type)) setIndex();
|
|
5218
|
+
if (primitive) for (const group of primitive.groups) geometry.addGroup(group.start, group.count, group.materialIndex);
|
|
5219
|
+
return geometry;
|
|
5220
|
+
}
|
|
5221
|
+
var SHAPE_GEOMETRY_TYPES = ["BoxGeometry", "CylinderGeometry", "ConeGeometry", "SphereGeometry", "PlaneGeometry", "CircleGeometry", "RingGeometry", "LatheGeometry", "TorusGeometry", "ExtrudeGeometry"];
|
|
5222
|
+
function linePoints(path) {
|
|
5223
|
+
if (path.autoClose || path.curves.length === 0) return null;
|
|
5224
|
+
const points = [];
|
|
5225
|
+
for (const [index, curve] of path.curves.entries()) {
|
|
5226
|
+
if (!curve.isLineCurve || !curve.v1 || !curve.v2) return null;
|
|
5227
|
+
if (index === 0) points.push([curve.v1.x, curve.v1.y]);
|
|
5228
|
+
else {
|
|
5229
|
+
const last = points[points.length - 1];
|
|
5230
|
+
if (last[0] !== curve.v1.x || last[1] !== curve.v1.y) return null;
|
|
5231
|
+
}
|
|
5232
|
+
points.push([curve.v2.x, curve.v2.y]);
|
|
5233
|
+
}
|
|
5234
|
+
return points;
|
|
5235
|
+
}
|
|
5236
|
+
function extrudeOf(shapes, options = {}) {
|
|
5237
|
+
if (Array.isArray(shapes) || !shapes || options.extrudePath !== void 0 || options.UVGenerator !== void 0) return null;
|
|
5238
|
+
const shape = shapes;
|
|
5239
|
+
const outer = linePoints(shape);
|
|
5240
|
+
if (!outer) return null;
|
|
5241
|
+
const holes = [];
|
|
5242
|
+
for (const hole of shape.holes ?? []) {
|
|
5243
|
+
const points = linePoints(hole);
|
|
5244
|
+
if (!points) return null;
|
|
5245
|
+
holes.push(points);
|
|
5246
|
+
}
|
|
5247
|
+
const outline = holes.length ? { outer, holes } : { outer };
|
|
5248
|
+
const bevel = options.bevelEnabled === false ? false : {
|
|
5249
|
+
...options.bevelThickness !== void 0 ? { thickness: options.bevelThickness } : {},
|
|
5250
|
+
...options.bevelSize !== void 0 ? { size: options.bevelSize } : {},
|
|
5251
|
+
...options.bevelOffset !== void 0 ? { offset: options.bevelOffset } : {},
|
|
5252
|
+
...options.bevelSegments !== void 0 ? { segments: options.bevelSegments } : {}
|
|
5253
|
+
};
|
|
5254
|
+
return extrude(outline, options.depth, options.steps, bevel);
|
|
5255
|
+
}
|
|
5256
|
+
var namespaces = /* @__PURE__ */ new WeakMap();
|
|
5257
|
+
var shims = /* @__PURE__ */ new WeakSet();
|
|
5258
|
+
function shapeGeometries(THREE, options = {}) {
|
|
5259
|
+
if (shims.has(THREE)) return THREE;
|
|
5260
|
+
const cache = options.cache !== false;
|
|
5261
|
+
const key = cache ? "cache" : "nocache";
|
|
5262
|
+
let byKey = namespaces.get(THREE);
|
|
5263
|
+
if (!byKey) {
|
|
5264
|
+
byKey = /* @__PURE__ */ new Map();
|
|
5265
|
+
namespaces.set(THREE, byKey);
|
|
5266
|
+
}
|
|
5267
|
+
const existing = byKey.get(key);
|
|
5268
|
+
if (existing) return existing;
|
|
5269
|
+
const made = (p2) => toGeometry(THREE, p2);
|
|
5270
|
+
const viaCache = (node, direct) => cache ? buildPrimitive(node) : direct();
|
|
5271
|
+
const defined = (o) => Object.fromEntries(Object.entries(o).filter(([, v]) => v !== void 0));
|
|
5272
|
+
const constructors = {
|
|
5273
|
+
BoxGeometry: (width, height, depth, ws = 1, hs = 1, ds = 1) => made(viaCache({ kind: "box", size: [width ?? 1, height ?? 1, depth ?? 1], segments: [ws, hs, ds] }, () => box(width, height, depth, ws, hs, ds))),
|
|
5274
|
+
CylinderGeometry: (radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength) => made(viaCache({ kind: "cylinder", ...defined({ radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength }) }, () => cylinder(radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength))),
|
|
5275
|
+
ConeGeometry: (radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength) => made(viaCache({ kind: "cone", ...defined({ radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength }) }, () => cone(radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength))),
|
|
5276
|
+
SphereGeometry: (radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength) => made(viaCache({ kind: "sphere", ...defined({ radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength }) }, () => sphere(radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength))),
|
|
5277
|
+
PlaneGeometry: (width, height, widthSegments, heightSegments) => made(viaCache({ kind: "plane", ...defined({ width, height, widthSegments, heightSegments }) }, () => plane(width, height, widthSegments, heightSegments))),
|
|
5278
|
+
CircleGeometry: (radius, segments, thetaStart, thetaLength) => made(viaCache({ kind: "circle", ...defined({ radius, segments, thetaStart, thetaLength }) }, () => circle(radius, segments, thetaStart, thetaLength))),
|
|
5279
|
+
RingGeometry: (innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength) => made(viaCache({ kind: "ring", ...defined({ innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength }) }, () => ring(innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength))),
|
|
5280
|
+
LatheGeometry: (points, segments, phiStart, phiLength) => {
|
|
5281
|
+
if (!points) return new THREE.LatheGeometry(void 0, segments, phiStart, phiLength);
|
|
5282
|
+
const profile = points.map((p2) => [p2.x, p2.y]);
|
|
5283
|
+
return made(viaCache({ kind: "lathe", points: profile, ...defined({ segments, phiStart, phiLength }) }, () => lathe(profile, segments, phiStart, phiLength)));
|
|
5284
|
+
},
|
|
5285
|
+
TorusGeometry: (radius, tube, radialSegments, tubularSegments, arc) => made(viaCache({ kind: "torus", ...defined({ radius, tube, radialSegments, tubularSegments, arc }) }, () => torus(radius, tube, radialSegments, tubularSegments, arc))),
|
|
5286
|
+
ExtrudeGeometry: (shapes, extrudeOptions) => {
|
|
5287
|
+
const buffers = shapes === void 0 ? null : extrudeOf(shapes, extrudeOptions);
|
|
5288
|
+
if (!buffers) return new THREE.ExtrudeGeometry(shapes, extrudeOptions);
|
|
5289
|
+
const geometry = toGeometry(THREE, buffers);
|
|
5290
|
+
geometry.parameters = { shapes, options: extrudeOptions ?? {} };
|
|
5291
|
+
return geometry;
|
|
5292
|
+
}
|
|
5293
|
+
};
|
|
5294
|
+
const namespace = { ...THREE };
|
|
5295
|
+
for (const type of SHAPE_GEOMETRY_TYPES) {
|
|
5296
|
+
const make2 = constructors[type];
|
|
5297
|
+
const Constructor = function(...args) {
|
|
5298
|
+
return make2(...args);
|
|
5299
|
+
};
|
|
5300
|
+
Constructor.prototype = THREE[type].prototype;
|
|
5301
|
+
Object.defineProperty(Constructor, "name", { value: type });
|
|
5302
|
+
namespace[type] = Constructor;
|
|
5303
|
+
}
|
|
5304
|
+
const result = namespace;
|
|
5305
|
+
byKey.set(key, result);
|
|
5306
|
+
shims.add(result);
|
|
5307
|
+
return result;
|
|
5308
|
+
}
|
|
5309
|
+
|
|
3420
5310
|
// ../game-audio/dist/index.js
|
|
3421
5311
|
var DISTANCE_CURVES = {
|
|
3422
5312
|
/** The game's `sfx`: `vol / (1 + d² × 0.004)`, cutoff `/ (1 + d × 0.01)`, silent below 0.01 (jogo L62091–62092, L62101). */
|
|
@@ -3728,13 +5618,13 @@ var GameCrowdThree = (() => {
|
|
|
3728
5618
|
return source;
|
|
3729
5619
|
};
|
|
3730
5620
|
var MERGED_ATTRIBUTES = [["position", 3], ["normal", 3], ["bone", 1], ["vcol", 4], ["pivot", 3], ["ppivot", 3]];
|
|
3731
|
-
var mergeBody = (
|
|
3732
|
-
const total =
|
|
5621
|
+
var mergeBody = (list2, three) => {
|
|
5622
|
+
const total = list2.reduce((sum, geometry) => sum + geometry.attributes.position.count, 0);
|
|
3733
5623
|
const merged = new three.BufferGeometry();
|
|
3734
5624
|
for (const [name, size] of MERGED_ATTRIBUTES) {
|
|
3735
5625
|
const array = new Float32Array(total * size);
|
|
3736
5626
|
let offset = 0;
|
|
3737
|
-
for (const geometry of
|
|
5627
|
+
for (const geometry of list2) {
|
|
3738
5628
|
const part = geometry.attributes[name].array;
|
|
3739
5629
|
array.set(part, offset);
|
|
3740
5630
|
offset += part.length;
|
|
@@ -3744,7 +5634,8 @@ var GameCrowdThree = (() => {
|
|
|
3744
5634
|
merged.computeBoundingSphere();
|
|
3745
5635
|
return merged;
|
|
3746
5636
|
};
|
|
3747
|
-
var buildInstancedBody = (
|
|
5637
|
+
var buildInstancedBody = (host, { segments, body = TEAM_GAME }) => {
|
|
5638
|
+
const three = shapeGeometries(host);
|
|
3748
5639
|
const joints = jointsOf(body);
|
|
3749
5640
|
const parts = [];
|
|
3750
5641
|
const half = Math.max(4, segments >> 1);
|
|
@@ -3868,15 +5759,15 @@ var GameCrowdThree = (() => {
|
|
|
3868
5759
|
copy.setAttribute(name, attribute);
|
|
3869
5760
|
attributes[name] = attribute;
|
|
3870
5761
|
}
|
|
3871
|
-
const
|
|
3872
|
-
|
|
3873
|
-
|
|
3874
|
-
|
|
3875
|
-
|
|
3876
|
-
|
|
5762
|
+
const mesh2 = new three.InstancedMesh(copy, createBodyMaterial(three, { time }), max);
|
|
5763
|
+
mesh2.customDepthMaterial = createBodyMaterial(three, { depth: true, time });
|
|
5764
|
+
mesh2.frustumCulled = false;
|
|
5765
|
+
mesh2.castShadow = castShadow;
|
|
5766
|
+
mesh2.receiveShadow = true;
|
|
5767
|
+
mesh2.count = 0;
|
|
3877
5768
|
let count = 0;
|
|
3878
5769
|
return {
|
|
3879
|
-
mesh,
|
|
5770
|
+
mesh: mesh2,
|
|
3880
5771
|
max,
|
|
3881
5772
|
get count() {
|
|
3882
5773
|
return count;
|
|
@@ -3884,7 +5775,7 @@ var GameCrowdThree = (() => {
|
|
|
3884
5775
|
begin() {
|
|
3885
5776
|
count = 0;
|
|
3886
5777
|
},
|
|
3887
|
-
push({ a, b, c, color, eye, y = 0 }) {
|
|
5778
|
+
push({ a, b, c, color: color2, eye, y = 0 }) {
|
|
3888
5779
|
if (count >= max) return;
|
|
3889
5780
|
const index = count++;
|
|
3890
5781
|
const fourOffset = index * 4;
|
|
@@ -3892,11 +5783,11 @@ var GameCrowdThree = (() => {
|
|
|
3892
5783
|
attributes.iA.array.set(a, fourOffset);
|
|
3893
5784
|
attributes.iB.array.set([b[0], b[1], b[2], b[3] + POSE_SLOTS * Math.round((Math.min(MAX_HEIGHT, Math.max(MIN_HEIGHT, y)) - MIN_HEIGHT) * HEIGHT_STEPS)], fourOffset);
|
|
3894
5785
|
attributes.iC.array.set(c, fourOffset);
|
|
3895
|
-
attributes.iCol.array.set([
|
|
5786
|
+
attributes.iCol.array.set([color2.r, color2.g, color2.b], threeOffset);
|
|
3896
5787
|
attributes.iEye.array.set(eye ? [eye.r, eye.g, eye.b] : [0, 0, 0], threeOffset);
|
|
3897
5788
|
},
|
|
3898
5789
|
end() {
|
|
3899
|
-
|
|
5790
|
+
mesh2.count = count;
|
|
3900
5791
|
for (const attribute of Object.values(attributes)) {
|
|
3901
5792
|
attribute.clearUpdateRanges();
|
|
3902
5793
|
attribute.addUpdateRange(0, count * attribute.itemSize);
|
|
@@ -3915,7 +5806,8 @@ var GameCrowdThree = (() => {
|
|
|
3915
5806
|
var FAR_LOD = 0.6;
|
|
3916
5807
|
var EYE_SCALE = 2.2;
|
|
3917
5808
|
var EYE_DEPTH_SCALE = 1.4;
|
|
3918
|
-
var bakeBody = (
|
|
5809
|
+
var bakeBody = (host, builders, spec, lod) => {
|
|
5810
|
+
const three = shapeGeometries(host);
|
|
3919
5811
|
const root = spec.retrato && builders.buildPortrait ? builders.buildPortrait(spec.retrato, lod) : builders.buildBest({ ...spec, pose: { ...BAKE_NEUTRAL_POSE, ...spec.pose ?? {} } }, lod);
|
|
3920
5812
|
const rig = root.userData.rig;
|
|
3921
5813
|
const P = rig.P;
|
|
@@ -3931,7 +5823,7 @@ var GameCrowdThree = (() => {
|
|
|
3931
5823
|
leg.kn.rotation.set(0, 0, 0);
|
|
3932
5824
|
}
|
|
3933
5825
|
root.updateMatrixWorld(true);
|
|
3934
|
-
const worldPosition2 = (
|
|
5826
|
+
const worldPosition2 = (object2) => object2.getWorldPosition(new three.Vector3()).toArray();
|
|
3935
5827
|
const bones = /* @__PURE__ */ new Map();
|
|
3936
5828
|
bones.set(rig.headG, [1, worldPosition2(rig.headG), [0, 0, 0]]);
|
|
3937
5829
|
for (const arm of rig.arms) {
|
|
@@ -3947,13 +5839,13 @@ var GameCrowdThree = (() => {
|
|
|
3947
5839
|
const trunk = [0, [0, 0.9 * P.s, 0], [0, 0, 0]];
|
|
3948
5840
|
const parts = [];
|
|
3949
5841
|
const topMaterial = spec.retrato ? null : builders.topMaterial();
|
|
3950
|
-
root.traverse((
|
|
3951
|
-
const
|
|
3952
|
-
const material =
|
|
3953
|
-
if (!
|
|
3954
|
-
for (let ancestor =
|
|
5842
|
+
root.traverse((object2) => {
|
|
5843
|
+
const mesh2 = object2;
|
|
5844
|
+
const material = mesh2.material;
|
|
5845
|
+
if (!mesh2.isMesh || !mesh2.geometry || material.transparent) return;
|
|
5846
|
+
for (let ancestor = object2; ancestor; ancestor = ancestor.parent) if (!ancestor.visible) return;
|
|
3955
5847
|
let tag = trunk;
|
|
3956
|
-
for (let ancestor =
|
|
5848
|
+
for (let ancestor = object2.parent; ancestor; ancestor = ancestor.parent) {
|
|
3957
5849
|
const found = bones.get(ancestor);
|
|
3958
5850
|
if (found) {
|
|
3959
5851
|
tag = found;
|
|
@@ -3961,21 +5853,21 @@ var GameCrowdThree = (() => {
|
|
|
3961
5853
|
}
|
|
3962
5854
|
}
|
|
3963
5855
|
let [bone, pivot, parentPivot] = tag;
|
|
3964
|
-
if (
|
|
5856
|
+
if (object2.userData.bone === 11) {
|
|
3965
5857
|
bone = 11;
|
|
3966
5858
|
pivot = bones.get(rig.headG)[1];
|
|
3967
5859
|
parentPivot = [0, 0, 0];
|
|
3968
5860
|
}
|
|
3969
|
-
const isEye2 = !!
|
|
3970
|
-
const
|
|
5861
|
+
const isEye2 = !!object2.userData.eye;
|
|
5862
|
+
const color2 = material.color;
|
|
3971
5863
|
const materialId = isEye2 ? 3 : material === topMaterial ? 1 : 6;
|
|
3972
5864
|
if (isEye2 && bone === 1) bone = 6;
|
|
3973
|
-
const geometry =
|
|
3974
|
-
geometry.applyMatrix4(
|
|
5865
|
+
const geometry = mesh2.geometry.clone();
|
|
5866
|
+
geometry.applyMatrix4(mesh2.matrixWorld);
|
|
3975
5867
|
const isBlood = material.polygonOffset && material.isMeshStandardMaterial;
|
|
3976
5868
|
if (isBlood) liftAlongNormals(geometry, lod < FAR_LOD ? BLOOD_LIFT_FAR : BLOOD_LIFT_NEAR);
|
|
3977
5869
|
if (isEye2) enlargeEye(three, geometry, lod < FAR_LOD ? 1 : 0.68);
|
|
3978
|
-
const colors = isBlood ? [Math.max(
|
|
5870
|
+
const colors = isBlood ? [Math.max(color2.r * 1.7, 0.3), Math.min(color2.g * 1.7, 0.04), Math.min(color2.b * 1.7, 0.04), materialId] : [color2.r, color2.g, color2.b, materialId];
|
|
3979
5871
|
parts.push({ g: geometry, bone, pv: pivot, pp: parentPivot, col: colors });
|
|
3980
5872
|
});
|
|
3981
5873
|
return { geo: mergeBaked(three, parts), s: P.s, bulk: P.bulk, verts: parts.reduce((sum, part) => sum + part.g.attributes.position.count, 0) };
|
|
@@ -4001,7 +5893,7 @@ var GameCrowdThree = (() => {
|
|
|
4001
5893
|
}
|
|
4002
5894
|
const position = new Float32Array(vertexTotal * 3);
|
|
4003
5895
|
const normal = new Float32Array(vertexTotal * 3);
|
|
4004
|
-
const
|
|
5896
|
+
const color2 = new Float32Array(vertexTotal * 4);
|
|
4005
5897
|
const bone = new Float32Array(vertexTotal);
|
|
4006
5898
|
const pivot = new Float32Array(vertexTotal * 3);
|
|
4007
5899
|
const parentPivot = new Float32Array(vertexTotal * 3);
|
|
@@ -4013,7 +5905,7 @@ var GameCrowdThree = (() => {
|
|
|
4013
5905
|
position.set(part.g.attributes.position.array, vertexOffset * 3);
|
|
4014
5906
|
normal.set(part.g.attributes.normal.array, vertexOffset * 3);
|
|
4015
5907
|
for (let vertex = 0; vertex < count; vertex++) {
|
|
4016
|
-
|
|
5908
|
+
color2.set(part.col, (vertexOffset + vertex) * 4);
|
|
4017
5909
|
bone[vertexOffset + vertex] = part.bone;
|
|
4018
5910
|
pivot.set(part.pv, (vertexOffset + vertex) * 3);
|
|
4019
5911
|
parentPivot.set(part.pp, (vertexOffset + vertex) * 3);
|
|
@@ -4028,7 +5920,7 @@ var GameCrowdThree = (() => {
|
|
|
4028
5920
|
const out = new three.BufferGeometry();
|
|
4029
5921
|
out.setAttribute("position", new three.BufferAttribute(position, 3));
|
|
4030
5922
|
out.setAttribute("normal", new three.BufferAttribute(normal, 3));
|
|
4031
|
-
out.setAttribute("vcol", new three.BufferAttribute(
|
|
5923
|
+
out.setAttribute("vcol", new three.BufferAttribute(color2, 4));
|
|
4032
5924
|
out.setAttribute("bone", new three.BufferAttribute(bone, 1));
|
|
4033
5925
|
out.setAttribute("pivot", new three.BufferAttribute(pivot, 3));
|
|
4034
5926
|
out.setAttribute("ppivot", new three.BufferAttribute(parentPivot, 3));
|
|
@@ -4061,8 +5953,8 @@ var GameCrowdThree = (() => {
|
|
|
4061
5953
|
add(U, Bx(0.1, 0.12, 0.09), m, -0.17, 0.95, -0.15);
|
|
4062
5954
|
return;
|
|
4063
5955
|
},
|
|
4064
|
-
belt: ({ U, m, ring }) => {
|
|
4065
|
-
|
|
5956
|
+
belt: ({ U, m, ring: ring2 }) => {
|
|
5957
|
+
ring2(U, 0.212, 0.07, m, 0.95, 1.12, 0.72);
|
|
4066
5958
|
return;
|
|
4067
5959
|
},
|
|
4068
5960
|
holster: ({ Bx, add, cmat, legs }) => {
|
|
@@ -4074,9 +5966,9 @@ var GameCrowdThree = (() => {
|
|
|
4074
5966
|
add(U, Bx(0.012, 0.1, 0.012), cmat(1710618), 0.17, 1.52, 0.18);
|
|
4075
5967
|
return;
|
|
4076
5968
|
},
|
|
4077
|
-
stripes: ({ THREE, U, add, arms, m, ring }) => {
|
|
4078
|
-
|
|
4079
|
-
|
|
5969
|
+
stripes: ({ THREE, U, add, arms, m, ring: ring2 }) => {
|
|
5970
|
+
ring2(U, 0.205, 0.05, m, 1.03, 1.13, 0.68);
|
|
5971
|
+
ring2(U, 0.268, 0.05, m, 1.42, 1.13, 0.67);
|
|
4080
5972
|
arms.forEach((a) => {
|
|
4081
5973
|
const r = add(a.el, new THREE.CylinderGeometry(0.058, 0.054, 0.05, 18), m, 0, -0.17, 0);
|
|
4082
5974
|
});
|
|
@@ -4186,17 +6078,17 @@ var GameCrowdThree = (() => {
|
|
|
4186
6078
|
add(arms[1].g, new THREE.CylinderGeometry(0.08, 0.078, 0.08, 18), m, 0, -0.12, 0);
|
|
4187
6079
|
return;
|
|
4188
6080
|
},
|
|
4189
|
-
tiedsleeves: ({ Bx, U, add, legs, m, ring }) => {
|
|
4190
|
-
|
|
6081
|
+
tiedsleeves: ({ Bx, U, add, legs, m, ring: ring2 }) => {
|
|
6082
|
+
ring2(U, 0.215, 0.1, m, 0.95, 1.12, 0.74);
|
|
4191
6083
|
legs.forEach((l) => add(l.g, Bx(0.1, 0.26, 0.05), m, l.s * 0.02, -0.1, 0.105));
|
|
4192
6084
|
return;
|
|
4193
6085
|
},
|
|
4194
|
-
labcoat: ({ Bx, THREE, U, add, arms, cmat, fem, legs, m, ring, torsoGeo }) => {
|
|
6086
|
+
labcoat: ({ Bx, THREE, U, add, arms, cmat, fem, legs, m, ring: ring2, torsoGeo }) => {
|
|
4195
6087
|
{
|
|
4196
6088
|
const g = torsoGeo(fem);
|
|
4197
6089
|
g.scale(1.06, 1, 1.12);
|
|
4198
6090
|
add(U, g, m, 0, 0, 0);
|
|
4199
|
-
|
|
6091
|
+
ring2(U, 0.22, 0.14, m, 0.9, 1.12, 0.76);
|
|
4200
6092
|
legs.forEach((l) => add(l.g, new THREE.CylinderGeometry(0.145, 0.165, 0.46, 20, 1, true).translate(0, -0.21, 0), m, 0, 0, 0));
|
|
4201
6093
|
add(U, Bx(0.025, 0.62, 0.012), cmat(10132114), 0, 1.2, 0.19);
|
|
4202
6094
|
arms.forEach((a) => {
|
|
@@ -4286,8 +6178,8 @@ var GameCrowdThree = (() => {
|
|
|
4286
6178
|
add(U, Bx(0.05, 0.75, 0.02), cmat(4864546), 0, 1.22, 0.195, 0, 0, -0.75);
|
|
4287
6179
|
return;
|
|
4288
6180
|
},
|
|
4289
|
-
scarf: ({ PI, THREE, U, add, m, ring }) => {
|
|
4290
|
-
|
|
6181
|
+
scarf: ({ PI, THREE, U, add, m, ring: ring2 }) => {
|
|
6182
|
+
ring2(U, 0.1, 0.08, m, 1.57, 1.3, 1.2);
|
|
4291
6183
|
add(U, new THREE.ConeGeometry(0.08, 0.14, 3), m, 0, 1.47, 0.15, PI, 0, 0);
|
|
4292
6184
|
return;
|
|
4293
6185
|
},
|
|
@@ -4330,12 +6222,12 @@ var GameCrowdThree = (() => {
|
|
|
4330
6222
|
return;
|
|
4331
6223
|
}
|
|
4332
6224
|
},
|
|
4333
|
-
refl: ({ Bx, THREE, U, add, cmat, m, ring }) => {
|
|
6225
|
+
refl: ({ Bx, THREE, U, add, cmat, m, ring: ring2 }) => {
|
|
4334
6226
|
{
|
|
4335
6227
|
const v = add(U, new THREE.CylinderGeometry(0.287, 0.252, 0.46, 20), m, 0, 1.3, 0);
|
|
4336
6228
|
v.scale.set(1.13, 1, 0.72);
|
|
4337
|
-
|
|
4338
|
-
|
|
6229
|
+
ring2(U, 0.29, 0.035, cmat(13159632, { metalness: 0.3, roughness: 0.4 }), 1.2, 1.13, 0.73);
|
|
6230
|
+
ring2(U, 0.3, 0.035, cmat(13159632, { metalness: 0.3, roughness: 0.4 }), 1.37, 1.13, 0.73);
|
|
4339
6231
|
add(U, Bx(0.17, 0.055, 0.02), cmat(1714794), 0, 1.47, 0.205);
|
|
4340
6232
|
return;
|
|
4341
6233
|
}
|
|
@@ -4583,6 +6475,84 @@ var GameCrowdThree = (() => {
|
|
|
4583
6475
|
var DATA = voices_default;
|
|
4584
6476
|
var UNDEAD_VOICES = DATA.types;
|
|
4585
6477
|
var UNDEAD_VOICE_SOURCES = DATA.sources;
|
|
6478
|
+
var player_avatar_default = {
|
|
6479
|
+
source: {
|
|
6480
|
+
file: "site/pages/jogo/zombiada-modo-livre.html",
|
|
6481
|
+
variable: "PB specs[0] ('voc\xEA') and PLAYER_COR",
|
|
6482
|
+
note: "The team game's player body: the Besti\xE1rio/Elenco human body. Overridable by `createPlayerAvatar(THREE, { spec, shirtColor })`."
|
|
6483
|
+
},
|
|
6484
|
+
spec: {
|
|
6485
|
+
type: "Lento",
|
|
6486
|
+
human: true,
|
|
6487
|
+
decay: 0,
|
|
6488
|
+
seed: 4242,
|
|
6489
|
+
skin: "b07a52",
|
|
6490
|
+
fem: false,
|
|
6491
|
+
life: 1,
|
|
6492
|
+
hs: "short",
|
|
6493
|
+
hair: "2a1e16",
|
|
6494
|
+
pose: {
|
|
6495
|
+
armL: 0,
|
|
6496
|
+
armR: 0,
|
|
6497
|
+
elbL: -0.12,
|
|
6498
|
+
elbR: -0.12,
|
|
6499
|
+
armOut: 0.11,
|
|
6500
|
+
lean: 0.04,
|
|
6501
|
+
headX: 0,
|
|
6502
|
+
headZ: 0
|
|
6503
|
+
}
|
|
6504
|
+
},
|
|
6505
|
+
shirtColor: "3d5a73"
|
|
6506
|
+
};
|
|
6507
|
+
var TWO_PI2 = Math.PI * 2;
|
|
6508
|
+
var first_person_arms_default = {
|
|
6509
|
+
source: {
|
|
6510
|
+
note: "Authored in the kit: no team delivered first-person arms. The rig is in metres in the camera's space (x right, y up, the view looks down -z); rest poses use the hand frame of HandPose in game-contracts, Euler [roll, yaw, pitch] in the order YZX (yaw pi/2 points the fingers forward)."
|
|
6511
|
+
},
|
|
6512
|
+
rig: {
|
|
6513
|
+
shoulder: [0.16, -0.36, 0.18],
|
|
6514
|
+
upper: 0.32,
|
|
6515
|
+
fore: 0.3,
|
|
6516
|
+
reachShift: 0.35,
|
|
6517
|
+
wrist: 0.07,
|
|
6518
|
+
elbowPole: [0.45, -1, 0.2],
|
|
6519
|
+
shoulderLeft: [-0.07, -0.46, 0.18],
|
|
6520
|
+
elbowPoleLeft: [-0.1, -1, 0.2],
|
|
6521
|
+
radius: { shoulder: 0.04, elbow: 0.034, wrist: 0.028, cuff: 0.031 },
|
|
6522
|
+
hip: [0.12, -0.82, 0.04],
|
|
6523
|
+
thigh: 0.46,
|
|
6524
|
+
shin: 0.46,
|
|
6525
|
+
kneePole: [0.1, 0.5, -1],
|
|
6526
|
+
foot: { p: [0.13, -0.85, -0.05], r: [0, 1.5708, 0] }
|
|
6527
|
+
},
|
|
6528
|
+
stances: {
|
|
6529
|
+
relaxed: {
|
|
6530
|
+
R: { p: [0.2, -0.22, -0.36], r: [0.05, 1.57, -0.05], grip: 0.2 },
|
|
6531
|
+
L: "mirror"
|
|
6532
|
+
},
|
|
6533
|
+
fists: {
|
|
6534
|
+
R: { p: [0.15, -0.12, -0.4], r: [0, 1.5, 0.15], grip: 1 },
|
|
6535
|
+
L: "mirror"
|
|
6536
|
+
},
|
|
6537
|
+
hold: { follow: true, fallback: "relaxed" }
|
|
6538
|
+
},
|
|
6539
|
+
bob: { frequency: 2.3, x: 6e-3, y: 8e-3, run: 1.5, fullSpeed: 4, crouch: 0.02 }
|
|
6540
|
+
};
|
|
6541
|
+
var FIRST_PERSON_STANCES = first_person_arms_default.stances;
|
|
6542
|
+
var FIRST_PERSON_RIG = first_person_arms_default.rig;
|
|
6543
|
+
var FIRST_PERSON_BOB = first_person_arms_default.bob;
|
|
6544
|
+
var hexOf2 = (value) => typeof value === "string" ? Number.parseInt(value, 16) : value;
|
|
6545
|
+
var scaleHex = (hex2, factor) => {
|
|
6546
|
+
const channel = (shift) => Math.round((hex2 >> shift & 255) * factor);
|
|
6547
|
+
return channel(16) << 16 | channel(8) << 8 | channel(0);
|
|
6548
|
+
};
|
|
6549
|
+
var FIRST_PERSON_COLORS = {
|
|
6550
|
+
skin: hexOf2(player_avatar_default.spec.skin),
|
|
6551
|
+
sleeve: hexOf2(player_avatar_default.shirtColor),
|
|
6552
|
+
cuff: scaleHex(hexOf2(player_avatar_default.shirtColor), 0.72),
|
|
6553
|
+
trouser: 2962496,
|
|
6554
|
+
shoe: 1841690
|
|
6555
|
+
};
|
|
4586
6556
|
|
|
4587
6557
|
// src/renderer.ts
|
|
4588
6558
|
var now = () => typeof performance === "undefined" ? Date.now() : performance.now();
|
|
@@ -4603,9 +6573,9 @@ var GameCrowdThree = (() => {
|
|
|
4603
6573
|
const shirt = new three.Color();
|
|
4604
6574
|
const eyeColors = /* @__PURE__ */ new Map();
|
|
4605
6575
|
const eyeOf = (hex) => {
|
|
4606
|
-
let
|
|
4607
|
-
if (!
|
|
4608
|
-
return
|
|
6576
|
+
let color2 = eyeColors.get(hex);
|
|
6577
|
+
if (!color2) eyeColors.set(hex, color2 = new three.Color(hex));
|
|
6578
|
+
return color2;
|
|
4609
6579
|
};
|
|
4610
6580
|
const push = (batch, instance) => {
|
|
4611
6581
|
if (!batch) return;
|
|
@@ -4613,7 +6583,7 @@ var GameCrowdThree = (() => {
|
|
|
4613
6583
|
batch.push({ a: instance.a, b: instance.b, c: instance.c, color: shirt, ...instance.eye !== null ? { eye: eyeOf(instance.eye) } : {}, y: instance.y });
|
|
4614
6584
|
};
|
|
4615
6585
|
const typeOfVariant = [];
|
|
4616
|
-
crowd.variantsOf.forEach((
|
|
6586
|
+
crowd.variantsOf.forEach((list2, c) => list2.forEach((g) => typeOfVariant[g] = c));
|
|
4617
6587
|
const baked = /* @__PURE__ */ new Set();
|
|
4618
6588
|
const ensurePlain = () => {
|
|
4619
6589
|
if (!plain) {
|
|
@@ -4667,8 +6637,8 @@ var GameCrowdThree = (() => {
|
|
|
4667
6637
|
instances.agents(crowd.store, variants, frame, (v, l, instance) => push(batches[v]?.[l], instance));
|
|
4668
6638
|
if (options.drawCorpses?.() !== false) instances.corpses(crowd.corpses.entries, variants, frame, crowd.numbers.corpseSeconds, (v, l, instance) => push(batches[v]?.[l], instance), (instance) => push(ensurePlain(), instance));
|
|
4669
6639
|
for (let l = 0; l < 3; l++) lodCounts[l] = batches.reduce((sum, set) => sum + (set?.[l]?.count ?? 0), 0);
|
|
4670
|
-
const
|
|
4671
|
-
if (
|
|
6640
|
+
const list2 = options.civilians?.list();
|
|
6641
|
+
if (list2) instances.civilians(list2, options.civilians?.color ?? ((n) => n.spec.color ?? 8421504), (n, instance) => push(personBatch(n), instance));
|
|
4672
6642
|
for (const batch of all()) batch.end();
|
|
4673
6643
|
},
|
|
4674
6644
|
get lodCounts() {
|
|
@@ -5133,7 +7103,7 @@ var GameCrowdThree = (() => {
|
|
|
5133
7103
|
sound("flesh", numbers.grabVolume);
|
|
5134
7104
|
emit("grabbed", { by, noJaw, drown });
|
|
5135
7105
|
};
|
|
5136
|
-
const front = (
|
|
7106
|
+
const front = (range2, cosMin, yaw, crowd = world.crowd) => {
|
|
5137
7107
|
const out = [];
|
|
5138
7108
|
if (!crowd) return out;
|
|
5139
7109
|
const fx = -Math.sin(yaw);
|
|
@@ -5144,7 +7114,7 @@ var GameCrowdThree = (() => {
|
|
|
5144
7114
|
const ex = crowd.x(i) - P.x;
|
|
5145
7115
|
const ez = crowd.z(i) - P.z;
|
|
5146
7116
|
const d = Math.hypot(ex, ez);
|
|
5147
|
-
if (d <
|
|
7117
|
+
if (d < range2 && (ex * fx + ez * fz) / (d || 1) > cosMin) out.push([d, i]);
|
|
5148
7118
|
}
|
|
5149
7119
|
return out.sort((a, b) => a[0] - b[0]);
|
|
5150
7120
|
};
|
|
@@ -5846,7 +7816,7 @@ var GameCrowdThree = (() => {
|
|
|
5846
7816
|
{ kind: "choice", id: "type", name: text.controls.type, hint: text.hints.type, options: typeOptions(), default: "mix" },
|
|
5847
7817
|
{ kind: "boolean", id: "night", name: text.controls.night, hint: text.hints.night, default: false },
|
|
5848
7818
|
{ kind: "number", id: "seed", name: text.controls.seed, min: 1, max: 9999, step: 1, default: settings.seed },
|
|
5849
|
-
{ kind: "action", id: "spawn", name: text.controls.spawn },
|
|
7819
|
+
{ kind: "action", id: "spawn", name: text.controls.spawn, slow: true },
|
|
5850
7820
|
{ kind: "action", id: "noise", name: text.controls.noise, hint: text.hints.noise },
|
|
5851
7821
|
{ kind: "action", id: "hit", name: text.controls.hit, hint: text.hints.hit },
|
|
5852
7822
|
{ kind: "action", id: "kill_all", name: text.controls.kill_all },
|
|
@@ -5855,7 +7825,7 @@ var GameCrowdThree = (() => {
|
|
|
5855
7825
|
...options.animals ? [{ kind: "action", id: "herd", name: text.controls.herd, hint: text.hints.herd }] : [],
|
|
5856
7826
|
...options.infection ? [{ kind: "action", id: "materialize", name: text.controls.materialize, hint: text.hints.materialize }] : [],
|
|
5857
7827
|
{ kind: "action", id: "push", name: text.controls.push, hint: text.hints.push },
|
|
5858
|
-
{ kind: "action", id: "reset", name: text.controls.reset }
|
|
7828
|
+
{ kind: "action", id: "reset", name: text.controls.reset, slow: true }
|
|
5859
7829
|
];
|
|
5860
7830
|
const benchLayers = () => [
|
|
5861
7831
|
{ id: "corpses", name: text.layers.corpses },
|