@adatechnology/game-items-three 0.3.2 → 0.4.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.js CHANGED
@@ -365,14 +365,19 @@ var destruction_default = {
365
365
  },
366
366
  tessellate: {
367
367
  cylinder: {
368
- heightSegments: 6,
369
- radialSegments: 20
368
+ heightSegments: 24,
369
+ radialSegments: 40,
370
+ capRings: 6
370
371
  },
371
372
  box: {
372
373
  widthSegments: 6,
373
374
  heightSegments: 1,
374
375
  depthSegments: 4
375
376
  }
377
+ },
378
+ wall: {
379
+ body: 1e-4,
380
+ ends: 25e-5
376
381
  }
377
382
  }
378
383
  },
@@ -396,14 +401,19 @@ var destruction_default = {
396
401
  },
397
402
  tessellate: {
398
403
  cylinder: {
399
- heightSegments: 6,
400
- radialSegments: 20
404
+ heightSegments: 24,
405
+ radialSegments: 40,
406
+ capRings: 6
401
407
  },
402
408
  box: {
403
409
  widthSegments: 6,
404
410
  heightSegments: 1,
405
411
  depthSegments: 4
406
412
  }
413
+ },
414
+ wall: {
415
+ body: 18e-5,
416
+ ends: 22e-5
407
417
  }
408
418
  }
409
419
  }
@@ -497,12 +507,53 @@ function volumeOf(mesh) {
497
507
  if (!box2) return 0;
498
508
  return (box2.max.x - box2.min.x) * (box2.max.y - box2.min.y) * (box2.max.z - box2.min.z);
499
509
  }
500
- function tessellated(geometry, rule) {
510
+ function ringedCylinder(T, p, radial, maxRows, rings) {
511
+ const half = p.height / 2;
512
+ const column = 2 * Math.PI * Math.max(p.radiusTop, p.radiusBottom, 1e-6) / radial;
513
+ const rows = Math.max(1, Math.min(maxRows, Math.round(p.height / column)));
514
+ const points = [];
515
+ if (!p.openEnded) for (let i = 0; i <= rings; i++) points.push(new T.Vector2(p.radiusBottom * i / rings, -half));
516
+ for (let j = 0; j <= rows; j++) points.push(new T.Vector2(p.radiusBottom + (p.radiusTop - p.radiusBottom) * j / rows, -half + p.height * j / rows));
517
+ if (!p.openEnded) for (let i = rings; i >= 0; i--) points.push(new T.Vector2(p.radiusTop * i / rings, half));
518
+ return lathed(T, points, radial, p.thetaStart, p.thetaLength);
519
+ }
520
+ function lathed(T, points, radial, phiStart, phiLength) {
521
+ const geometry = new T.LatheGeometry([...points], radial, phiStart, phiLength);
522
+ geometry.computeVertexNormals();
523
+ const position = geometry.getAttribute("position");
524
+ const normal = geometry.getAttribute("normal");
525
+ const middle = (Math.min(...points.map((point) => point.y)) + Math.max(...points.map((point) => point.y))) / 2;
526
+ for (let i = 0; i < normal.count; i++) {
527
+ if (Math.hypot(normal.getX(i), normal.getY(i), normal.getZ(i)) > 0.5) continue;
528
+ normal.setXYZ(i, 0, position.getY(i) >= middle ? 1 : -1, 0);
529
+ }
530
+ return geometry;
531
+ }
532
+ function finerProfile(T, points, step) {
533
+ const out = [];
534
+ points.forEach((point, index) => {
535
+ const next = points[index + 1];
536
+ out.push(point.clone());
537
+ if (!next) return;
538
+ const pieces = Math.max(1, Math.round(point.distanceTo(next) / step));
539
+ for (let k = 1; k < pieces; k++) out.push(point.clone().lerp(next, k / pieces));
540
+ });
541
+ return out;
542
+ }
543
+ function tessellated(geometry, rule, T) {
501
544
  const Shape = geometry.constructor;
502
545
  if (geometry.type === "CylinderGeometry" && rule.cylinder) {
503
- const { radiusTop, radiusBottom, height, openEnded, thetaStart, thetaLength } = geometry.parameters;
546
+ const parameters = geometry.parameters;
547
+ const { radiusTop, radiusBottom, height, openEnded, thetaStart, thetaLength } = parameters;
548
+ if (T && rule.cylinder.capRings !== void 0) return ringedCylinder(T, parameters, rule.cylinder.radialSegments, rule.cylinder.heightSegments, rule.cylinder.capRings);
504
549
  return new Shape(radiusTop, radiusBottom, height, rule.cylinder.radialSegments, rule.cylinder.heightSegments, openEnded, thetaStart, thetaLength);
505
550
  }
551
+ if (geometry.type === "LatheGeometry" && rule.cylinder && T && rule.cylinder.capRings !== void 0) {
552
+ const { points, segments, phiStart, phiLength } = geometry.parameters;
553
+ if (segments >= rule.cylinder.radialSegments) return void 0;
554
+ const widest = Math.max(...points.map((point) => point.x), 1e-6);
555
+ return lathed(T, finerProfile(T, points, 2 * Math.PI * widest / rule.cylinder.radialSegments), rule.cylinder.radialSegments, phiStart, phiLength);
556
+ }
506
557
  if (geometry.type === "BoxGeometry" && rule.box) {
507
558
  const { width, height, depth } = geometry.parameters;
508
559
  return new Shape(width, height, depth, rule.box.widthSegments, rule.box.heightSegments, rule.box.depthSegments);
@@ -510,14 +561,14 @@ function tessellated(geometry, rule) {
510
561
  return void 0;
511
562
  }
512
563
  var triangleCount = (geometry) => (geometry.index ? geometry.index.count : geometry.getAttribute("position").count) / 3;
513
- function tessellateShapes(root, rule) {
564
+ function tessellateShapes(root, rule, T) {
514
565
  const rebuilt = /* @__PURE__ */ new Map();
515
566
  root.traverse((object) => {
516
567
  const mesh = object;
517
568
  if (!mesh.isMesh) return;
518
569
  let fresh = rebuilt.get(mesh.geometry);
519
570
  if (!fresh) {
520
- fresh = tessellated(mesh.geometry, rule);
571
+ fresh = tessellated(mesh.geometry, rule, T);
521
572
  if (!fresh) return;
522
573
  rebuilt.set(mesh.geometry, fresh);
523
574
  }
@@ -531,10 +582,10 @@ function tessellateShapes(root, rule) {
531
582
  root.userData.tessellationTriangles = added;
532
583
  }
533
584
  function tagForDestruction(root, options = {}) {
534
- const { modelId, weight, size } = options;
585
+ const { modelId, weight, size, three } = options;
535
586
  if (weight !== void 0 && weight > 0) root.userData.destructionMass = weight;
536
587
  const rule = modelId === void 0 ? void 0 : itemDestruction(modelId);
537
- if (rule?.tessellate) tessellateShapes(root, rule.tessellate);
588
+ if (rule?.tessellate) tessellateShapes(root, rule.tessellate, three);
538
589
  const solid = [];
539
590
  root.traverse((object) => {
540
591
  const mesh = object;
@@ -554,6 +605,7 @@ function tagForDestruction(root, options = {}) {
554
605
  const anchor = solid.reduce((largest, mesh) => volumeOf(mesh) > volumeOf(largest) ? mesh : largest);
555
606
  solid.forEach((mesh, index) => {
556
607
  mesh.userData.destructionPart = mesh === anchor ? { id: SHELL_PART_ID } : { id: `shell_${index}`, parent: SHELL_PART_ID, kind: "weld" };
608
+ if (rule.wall) mesh.userData.destructionThickness = mesh === anchor ? rule.wall.body : rule.wall.ends;
557
609
  });
558
610
  const contents = size === void 0 ? void 0 : itemContents({ ...modelId === void 0 ? {} : { model: modelId }, size, ...weight === void 0 ? {} : { weight } });
559
611
  if (contents) anchor.userData.destructionContains = { fluid: contents.liquid, liters: contents.liters };
@@ -6674,7 +6726,7 @@ function buildItem(T, item, options = {}) {
6674
6726
  const materials = kit.materials.slice(first);
6675
6727
  if (options.wear) setWear(materials, options.wear);
6676
6728
  root.userData.wear = options.wear ?? 0;
6677
- if (options.destructible) tagForDestruction(root, { ...kind === "model" && item.model !== void 0 ? { modelId: item.model } : {}, ...item.weight === void 0 ? {} : { weight: item.weight }, size: item.size });
6729
+ if (options.destructible) tagForDestruction(root, { ...kind === "model" && item.model !== void 0 ? { modelId: item.model } : {}, ...item.weight === void 0 ? {} : { weight: item.weight }, size: item.size, three: T });
6678
6730
  markKitOrigin(root, { owner: "game-items-three", kind: "item", id: item.id, ...kind === "shape" ? { standIn: true } : {} });
6679
6731
  return { root, kind, ...shape ? { shape } : {}, size: item.size, materials };
6680
6732
  }
@@ -7417,6 +7469,7 @@ function createItemsTestModule(options) {
7417
7469
  const module = {
7418
7470
  id: "items_area",
7419
7471
  name: text.name,
7472
+ ground: { surface: "tile_floor" },
7420
7473
  group: text.group,
7421
7474
  state,
7422
7475
  placed: () => entries2.map((entry) => ({ id: entry.id, itemId: entry.itemId, group: entry.group, kind: entry.kind, size: entry.size, root: entry.root })),