visibility.js 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. import * as THREE from 'https://cdn.jsdelivr.net/npm/[email protected]/build/three.module.js';
  2. import {math} from './math.js';
  3. export const visibility = (function() {
  4. return {
  5. VisibilityGrid: class {
  6. constructor(bounds, dimensions) {
  7. const [x, y] = dimensions;
  8. this._cells = [...Array(x)].map(_ => [...Array(y)].map(_ => ({})));
  9. this._dimensions = dimensions;
  10. this._bounds = bounds;
  11. this._cellSize = bounds[1].clone().sub(bounds[0]);
  12. this._cellSize.multiply(
  13. new THREE.Vector3(1.0 / dimensions[0], 0, 1.0 / dimensions[1]));
  14. this._globalItems = [];
  15. }
  16. AddGlobalItem(entity) {
  17. this._globalItems.push(entity);
  18. }
  19. GetGlobalItems() {
  20. return [...this._globalItems];
  21. }
  22. UpdateItem(uuid, entity, previous=null) {
  23. const [x, y] = this._GetCellIndex(entity.Position);
  24. if (previous) {
  25. const [prevX, prevY] = previous;
  26. if (prevX == x && prevY == y) {
  27. return [x, y];
  28. }
  29. delete this._cells[prevX][prevY][uuid];
  30. }
  31. this._cells[x][y][uuid] = entity;
  32. return [x, y];
  33. }
  34. GetLocalEntities(position, radius) {
  35. const [x, y] = this._GetCellIndex(position);
  36. const cellSize = Math.min(this._cellSize.x, this._cellSize.z);
  37. const cells = Math.ceil(radius / cellSize);
  38. let local = [];
  39. const xMin = Math.max(x - cells, 0);
  40. const yMin = Math.max(y - cells, 0);
  41. const xMax = Math.min(this._dimensions[0] - 1, x + cells);
  42. const yMax = Math.min(this._dimensions[1] - 1, y + cells);
  43. for (let xi = xMin; xi <= xMax; xi++) {
  44. for (let yi = yMin; yi <= yMax; yi++) {
  45. local.push(...Object.values(this._cells[xi][yi]));
  46. }
  47. }
  48. local = local.filter((e) => {
  49. const distance = e.Position.distanceTo(position);
  50. return distance != 0.0 && distance < radius;
  51. });
  52. return local;
  53. }
  54. _GetCellIndex(position) {
  55. const x = math.sat((this._bounds[0].x - position.x) / (
  56. this._bounds[0].x - this._bounds[1].x));
  57. const y = math.sat((this._bounds[0].z - position.z) / (
  58. this._bounds[0].z - this._bounds[1].z));
  59. const xIndex = Math.floor(x * (this._dimensions[0] - 1));
  60. const yIndex = Math.floor(y * (this._dimensions[1] - 1));
  61. return [xIndex, yIndex];
  62. }
  63. }
  64. };
  65. })();