UNPKG

the-world-engine

Version:

three.js based, unity like game engine for browser

165 lines (160 loc) 5.3 kB
import { b2BroadPhase } from "../collision/b2_broad_phase.js"; import { b2TestOverlapAABB } from "../collision/b2_collision.js"; import { b2ContactFactory } from "./b2_contact_factory.js"; import { b2BodyType } from "./b2_body.js"; import { b2ContactFilter, b2ContactListener } from "./b2_world_callbacks.js"; export class b2ContactManager { constructor() { this.m_broadPhase = new b2BroadPhase; this.m_contactList = null; this.m_contactCount = 0; this.m_contactFilter = b2ContactFilter.b2_defaultFilter; this.m_contactListener = b2ContactListener.b2_defaultListener; this.m_contactFactory = new b2ContactFactory; } AddPair(t, i) { let s = t.fixture; let o = i.fixture; let n = t.childIndex; let c = i.childIndex; let e = s.GetBody(); let l = o.GetBody(); if (e === l) { return; } let r = l.GetContactList(); while (r) { if (r.other === e) { const t = r.contact.GetFixtureA(); const i = r.contact.GetFixtureB(); const e = r.contact.GetChildIndexA(); const l = r.contact.GetChildIndexB(); if (t === s && i === o && e === n && l === c) { return; } if (t === o && i === s && e === c && l === n) { return; } } r = r.next; } if (this.m_contactFilter && !this.m_contactFilter.ShouldCollide(s, o)) { return; } const h = this.m_contactFactory.Create(s, n, o, c); if (h === null) { return; } s = h.GetFixtureA(); o = h.GetFixtureB(); n = h.GetChildIndexA(); c = h.GetChildIndexB(); e = s.m_body; l = o.m_body; h.m_prev = null; h.m_next = this.m_contactList; if (this.m_contactList !== null) { this.m_contactList.m_prev = h; } this.m_contactList = h; h.m_nodeA.other = l; h.m_nodeA.prev = null; h.m_nodeA.next = e.m_contactList; if (e.m_contactList !== null) { e.m_contactList.prev = h.m_nodeA; } e.m_contactList = h.m_nodeA; h.m_nodeB.other = e; h.m_nodeB.prev = null; h.m_nodeB.next = l.m_contactList; if (l.m_contactList !== null) { l.m_contactList.prev = h.m_nodeB; } l.m_contactList = h.m_nodeB; ++this.m_contactCount; } FindNewContacts() { this.m_broadPhase.UpdatePairs(((t, i) => { this.AddPair(t, i); })); } Destroy(t) { const i = t.GetFixtureA(); const s = t.GetFixtureB(); const o = i.GetBody(); const n = s.GetBody(); if (this.m_contactListener && t.IsTouching()) { this.m_contactListener.EndContact(t); } if (t.m_prev) { t.m_prev.m_next = t.m_next; } if (t.m_next) { t.m_next.m_prev = t.m_prev; } if (t === this.m_contactList) { this.m_contactList = t.m_next; } if (t.m_nodeA.prev) { t.m_nodeA.prev.next = t.m_nodeA.next; } if (t.m_nodeA.next) { t.m_nodeA.next.prev = t.m_nodeA.prev; } if (t.m_nodeA === o.m_contactList) { o.m_contactList = t.m_nodeA.next; } if (t.m_nodeB.prev) { t.m_nodeB.prev.next = t.m_nodeB.next; } if (t.m_nodeB.next) { t.m_nodeB.next.prev = t.m_nodeB.prev; } if (t.m_nodeB === n.m_contactList) { n.m_contactList = t.m_nodeB.next; } if (t.m_manifold.pointCount > 0 && !i.IsSensor() && !s.IsSensor()) { i.GetBody().SetAwake(true); s.GetBody().SetAwake(true); } this.m_contactFactory.Destroy(t); --this.m_contactCount; } Collide() { let t = this.m_contactList; while (t) { const i = t.GetFixtureA(); const s = t.GetFixtureB(); const o = t.GetChildIndexA(); const n = t.GetChildIndexB(); const c = i.GetBody(); const e = s.GetBody(); if (t.m_filterFlag) { if (this.m_contactFilter && !this.m_contactFilter.ShouldCollide(i, s)) { const i = t; t = i.m_next; this.Destroy(i); continue; } t.m_filterFlag = false; } const l = c.IsAwake() && c.m_type !== b2BodyType.b2_staticBody; const r = e.IsAwake() && e.m_type !== b2BodyType.b2_staticBody; if (!l && !r) { t = t.m_next; continue; } const h = i.m_proxies[o].treeNode; const f = s.m_proxies[n].treeNode; const a = b2TestOverlapAABB(h.aabb, f.aabb); if (!a) { const i = t; t = i.m_next; this.Destroy(i); continue; } t.Update(this.m_contactListener); t = t.m_next; } } }