diff --git a/party-stage/src/scene/party-guests.js b/party-stage/src/scene/party-guests.js index 04d69cf..264a995 100644 --- a/party-stage/src/scene/party-guests.js +++ b/party-stage/src/scene/party-guests.js @@ -152,6 +152,21 @@ export class PartyGuests extends SceneFeature { const time = state.clock.getElapsedTime(); const minDistance = 0.8; // Minimum distance to maintain + const minDistSq = minDistance * minDistance; + + // --- Spatial Grid Optimization --- + const cellSize = 2.0; + const grid = {}; + + // Populate grid + for (let i = 0; i < this.guests.length; i++) { + const g = this.guests[i]; + const cx = Math.floor(g.mesh.position.x / cellSize); + const cz = Math.floor(g.mesh.position.z / cellSize); + const key = cx + ':' + cz; + if (!grid[key]) grid[key] = []; + grid[key].push(i); + } this.guests.forEach((guestObj, i) => { const { mesh, leftArm, rightArm } = guestObj; @@ -160,19 +175,31 @@ export class PartyGuests extends SceneFeature { let separationX = 0; let separationZ = 0; - for (let j = 0; j < this.guests.length; j++) { - if (i === j) continue; - const otherMesh = this.guests[j].mesh; - - const dx = mesh.position.x - otherMesh.position.x; - const dz = mesh.position.z - otherMesh.position.z; - const distSq = dx*dx + dz*dz; - - if (distSq < minDistance * minDistance && distSq > 0.0001) { - const dist = Math.sqrt(distSq); - const force = (minDistance - dist) / minDistance; - separationX += (dx / dist) * force; - separationZ += (dz / dist) * force; + const cx = Math.floor(mesh.position.x / cellSize); + const cz = Math.floor(mesh.position.z / cellSize); + + for (let ox = -1; ox <= 1; ox++) { + for (let oz = -1; oz <= 1; oz++) { + const key = (cx + ox) + ':' + (cz + oz); + const cell = grid[key]; + if (!cell) continue; + + for (let k = 0; k < cell.length; k++) { + const j = cell[k]; + if (i === j) continue; + + const otherMesh = this.guests[j].mesh; + const dx = mesh.position.x - otherMesh.position.x; + const dz = mesh.position.z - otherMesh.position.z; + const distSq = dx*dx + dz*dz; + + if (distSq < minDistSq && distSq > 0.0001) { + const dist = Math.sqrt(distSq); + const force = (minDistance - dist) / minDistance; + separationX += (dx / dist) * force; + separationZ += (dz / dist) * force; + } + } } }