the-world-engine
Version:
three.js based, unity like game engine for browser
173 lines (168 loc) • 6.17 kB
JavaScript
import { b2_maxFloat, b2MakeArray } from "../common/b2_settings.js";
import { b2Vec2 } from "../common/b2_math.js";
import { b2StackQueue } from "./b2_stack_queue.js";
export class b2VoronoiDiagram {
constructor(t) {
this.m_generatorCapacity = 0;
this.m_generatorCount = 0;
this.m_countX = 0;
this.m_countY = 0;
this.m_diagram = [];
this.m_generatorBuffer = b2MakeArray(t, (t => new b2VoronoiDiagram_Generator));
this.m_generatorCapacity = t;
}
AddGenerator(t, s, o) {
const i = this.m_generatorBuffer[this.m_generatorCount++];
i.center.Copy(t);
i.tag = s;
i.necessary = o;
}
Generate(t, s) {
const o = 1 / t;
const i = new b2Vec2(+b2_maxFloat, +b2_maxFloat);
const n = new b2Vec2(-b2_maxFloat, -b2_maxFloat);
let a = 0;
for (let t = 0; t < this.m_generatorCount; t++) {
const s = this.m_generatorBuffer[t];
if (s.necessary) {
b2Vec2.MinV(i, s.center, i);
b2Vec2.MaxV(n, s.center, n);
++a;
}
}
if (a === 0) {
this.m_countX = 0;
this.m_countY = 0;
return;
}
i.x -= s;
i.y -= s;
n.x += s;
n.y += s;
this.m_countX = 1 + Math.floor(o * (n.x - i.x));
this.m_countY = 1 + Math.floor(o * (n.y - i.y));
this.m_diagram = [];
const h = new b2StackQueue(4 * this.m_countX * this.m_countY);
for (let t = 0; t < this.m_generatorCount; t++) {
const s = this.m_generatorBuffer[t];
s.center.SelfSub(i).SelfMul(o);
const n = Math.floor(s.center.x);
const a = Math.floor(s.center.y);
if (n >= 0 && a >= 0 && n < this.m_countX && a < this.m_countY) {
h.Push(new b2VoronoiDiagram_Task(n, a, n + a * this.m_countX, s));
}
}
while (!h.Empty()) {
const t = h.Front();
const s = t.m_x;
const o = t.m_y;
const i = t.m_i;
const n = t.m_generator;
h.Pop();
if (!this.m_diagram[i]) {
this.m_diagram[i] = n;
if (s > 0) {
h.Push(new b2VoronoiDiagram_Task(s - 1, o, i - 1, n));
}
if (o > 0) {
h.Push(new b2VoronoiDiagram_Task(s, o - 1, i - this.m_countX, n));
}
if (s < this.m_countX - 1) {
h.Push(new b2VoronoiDiagram_Task(s + 1, o, i + 1, n));
}
if (o < this.m_countY - 1) {
h.Push(new b2VoronoiDiagram_Task(s, o + 1, i + this.m_countX, n));
}
}
}
for (let t = 0; t < this.m_countY; t++) {
for (let s = 0; s < this.m_countX - 1; s++) {
const o = s + t * this.m_countX;
const i = this.m_diagram[o];
const n = this.m_diagram[o + 1];
if (i !== n) {
h.Push(new b2VoronoiDiagram_Task(s, t, o, n));
h.Push(new b2VoronoiDiagram_Task(s + 1, t, o + 1, i));
}
}
}
for (let t = 0; t < this.m_countY - 1; t++) {
for (let s = 0; s < this.m_countX; s++) {
const o = s + t * this.m_countX;
const i = this.m_diagram[o];
const n = this.m_diagram[o + this.m_countX];
if (i !== n) {
h.Push(new b2VoronoiDiagram_Task(s, t, o, n));
h.Push(new b2VoronoiDiagram_Task(s, t + 1, o + this.m_countX, i));
}
}
}
while (!h.Empty()) {
const t = h.Front();
const s = t.m_x;
const o = t.m_y;
const i = t.m_i;
const n = t.m_generator;
h.Pop();
const a = this.m_diagram[i];
const r = n;
if (a !== r) {
const t = a.center.x - s;
const n = a.center.y - o;
const e = r.center.x - s;
const c = r.center.y - o;
const b = t * t + n * n;
const m = e * e + c * c;
if (b > m) {
this.m_diagram[i] = r;
if (s > 0) {
h.Push(new b2VoronoiDiagram_Task(s - 1, o, i - 1, r));
}
if (o > 0) {
h.Push(new b2VoronoiDiagram_Task(s, o - 1, i - this.m_countX, r));
}
if (s < this.m_countX - 1) {
h.Push(new b2VoronoiDiagram_Task(s + 1, o, i + 1, r));
}
if (o < this.m_countY - 1) {
h.Push(new b2VoronoiDiagram_Task(s, o + 1, i + this.m_countX, r));
}
}
}
}
}
GetNodes(t) {
for (let s = 0; s < this.m_countY - 1; s++) {
for (let o = 0; o < this.m_countX - 1; o++) {
const i = o + s * this.m_countX;
const n = this.m_diagram[i];
const a = this.m_diagram[i + 1];
const h = this.m_diagram[i + this.m_countX];
const r = this.m_diagram[i + 1 + this.m_countX];
if (a !== h) {
if (n !== a && n !== h && (n.necessary || a.necessary || h.necessary)) {
t(n.tag, a.tag, h.tag);
}
if (r !== a && r !== h && (n.necessary || a.necessary || h.necessary)) {
t(a.tag, r.tag, h.tag);
}
}
}
}
}
}
export class b2VoronoiDiagram_Generator {
constructor() {
this.center = new b2Vec2;
this.tag = 0;
this.necessary = false;
}
}
export class b2VoronoiDiagram_Task {
constructor(t, s, o, i) {
this.m_x = t;
this.m_y = s;
this.m_i = o;
this.m_generator = i;
}
}