the-world-engine
Version:
three.js based, unity like game engine for browser
165 lines (160 loc) • 5.3 kB
JavaScript
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;
}
}
}