UNPKG

the-world-engine

Version:

three.js based, unity like game engine for browser

1,239 lines (1,182 loc) 39.9 kB
import { b2_epsilon, b2_maxSubSteps, b2_maxTOIContacts } from "../common/b2_settings.js"; import { b2Min, b2Vec2, b2Transform, b2Sweep } from "../common/b2_math.js"; import { b2Timer } from "../common/b2_timer.js"; import { b2Color, b2DrawFlags } from "../common/b2_draw.js"; import { b2AABB, b2RayCastInput, b2RayCastOutput, b2TestOverlapShape } from "../collision/b2_collision.js"; import { b2TimeOfImpact, b2TOIInput, b2TOIOutput, b2TOIOutputState } from "../collision/b2_time_of_impact.js"; import { b2ShapeType } from "../collision/b2_shape.js"; import { b2JointType } from "./b2_joint.js"; import { b2AreaJoint } from "./b2_area_joint.js"; import { b2DistanceJoint } from "./b2_distance_joint.js"; import { b2FrictionJoint } from "./b2_friction_joint.js"; import { b2GearJoint } from "./b2_gear_joint.js"; import { b2MotorJoint } from "./b2_motor_joint.js"; import { b2MouseJoint } from "./b2_mouse_joint.js"; import { b2PrismaticJoint } from "./b2_prismatic_joint.js"; import { b2PulleyJoint } from "./b2_pulley_joint.js"; import { b2RevoluteJoint } from "./b2_revolute_joint.js"; import { b2WeldJoint } from "./b2_weld_joint.js"; import { b2WheelJoint } from "./b2_wheel_joint.js"; import { b2Body, b2BodyType } from "./b2_body.js"; import { b2ContactManager } from "./b2_contact_manager.js"; import { b2Island } from "./b2_island.js"; import { b2Profile, b2TimeStep } from "./b2_time_step.js"; import { b2QueryCallback } from "./b2_world_callbacks.js"; import { b2RayCastCallback } from "./b2_world_callbacks.js"; import { b2_maxFloat } from "../common/b2_settings.js"; import { b2CalculateParticleIterations } from "../particle/b2_particle.js"; import { b2ParticleSystem } from "../particle/b2_particle_system.js"; export class b2World { constructor(t) { this.m_contactManager = new b2ContactManager; this.m_bodyList = null; this.m_jointList = null; this.m_particleSystemList = null; this.m_bodyCount = 0; this.m_jointCount = 0; this.m_gravity = new b2Vec2; this.m_allowSleep = true; this.m_destructionListener = null; this.m_debugDraw = null; this.m_inv_dt0 = 0; this.m_newContacts = false; this.m_locked = false; this.m_clearForces = true; this.m_warmStarting = true; this.m_continuousPhysics = true; this.m_subStepping = false; this.m_stepComplete = true; this.m_profile = new b2Profile; this.m_island = new b2Island; this.s_stack = []; this.m_controllerList = null; this.m_controllerCount = 0; this.m_gravity.Copy(t); } SetDestructionListener(t) { this.m_destructionListener = t; } SetContactFilter(t) { this.m_contactManager.m_contactFilter = t; } SetContactListener(t) { this.m_contactManager.m_contactListener = t; } SetDebugDraw(t) { this.m_debugDraw = t; } CreateBody(t = {}) { if (this.IsLocked()) { throw new Error; } const i = new b2Body(t, this); i.m_prev = null; i.m_next = this.m_bodyList; if (this.m_bodyList) { this.m_bodyList.m_prev = i; } this.m_bodyList = i; ++this.m_bodyCount; return i; } DestroyBody(t) { if (this.IsLocked()) { throw new Error; } let i = t.m_jointList; while (i) { const e = i; i = i.next; if (this.m_destructionListener) { this.m_destructionListener.SayGoodbyeJoint(e.joint); } this.DestroyJoint(e.joint); t.m_jointList = i; } t.m_jointList = null; let e = t.m_controllerList; while (e) { const i = e; e = e.nextController; i.controller.RemoveBody(t); } let s = t.m_contactList; while (s) { const t = s; s = s.next; this.m_contactManager.Destroy(t.contact); } t.m_contactList = null; let r = t.m_fixtureList; while (r) { const i = r; r = r.m_next; if (this.m_destructionListener) { this.m_destructionListener.SayGoodbyeFixture(i); } i.DestroyProxies(); i.Reset(); t.m_fixtureList = r; t.m_fixtureCount -= 1; } t.m_fixtureList = null; t.m_fixtureCount = 0; 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_bodyList) { this.m_bodyList = t.m_next; } --this.m_bodyCount; } static _Joint_Create(t) { switch (t.type) { case b2JointType.e_distanceJoint: return new b2DistanceJoint(t); case b2JointType.e_mouseJoint: return new b2MouseJoint(t); case b2JointType.e_prismaticJoint: return new b2PrismaticJoint(t); case b2JointType.e_revoluteJoint: return new b2RevoluteJoint(t); case b2JointType.e_pulleyJoint: return new b2PulleyJoint(t); case b2JointType.e_gearJoint: return new b2GearJoint(t); case b2JointType.e_wheelJoint: return new b2WheelJoint(t); case b2JointType.e_weldJoint: return new b2WeldJoint(t); case b2JointType.e_frictionJoint: return new b2FrictionJoint(t); case b2JointType.e_motorJoint: return new b2MotorJoint(t); case b2JointType.e_areaJoint: return new b2AreaJoint(t); } throw new Error; } static _Joint_Destroy(t) {} CreateJoint(t) { if (this.IsLocked()) { throw new Error; } const i = b2World._Joint_Create(t); i.m_prev = null; i.m_next = this.m_jointList; if (this.m_jointList) { this.m_jointList.m_prev = i; } this.m_jointList = i; ++this.m_jointCount; i.m_edgeA.prev = null; i.m_edgeA.next = i.m_bodyA.m_jointList; if (i.m_bodyA.m_jointList) { i.m_bodyA.m_jointList.prev = i.m_edgeA; } i.m_bodyA.m_jointList = i.m_edgeA; i.m_edgeB.prev = null; i.m_edgeB.next = i.m_bodyB.m_jointList; if (i.m_bodyB.m_jointList) { i.m_bodyB.m_jointList.prev = i.m_edgeB; } i.m_bodyB.m_jointList = i.m_edgeB; const e = i.m_bodyA; const s = i.m_bodyB; const r = i.m_collideConnected; if (!r) { let t = s.GetContactList(); while (t) { if (t.other === e) { t.contact.FlagForFiltering(); } t = t.next; } } return i; } DestroyJoint(t) { if (this.IsLocked()) { throw new Error; } 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_jointList) { this.m_jointList = t.m_next; } const i = t.m_bodyA; const e = t.m_bodyB; const s = t.m_collideConnected; i.SetAwake(true); e.SetAwake(true); if (t.m_edgeA.prev) { t.m_edgeA.prev.next = t.m_edgeA.next; } if (t.m_edgeA.next) { t.m_edgeA.next.prev = t.m_edgeA.prev; } if (t.m_edgeA === i.m_jointList) { i.m_jointList = t.m_edgeA.next; } t.m_edgeA.Reset(); if (t.m_edgeB.prev) { t.m_edgeB.prev.next = t.m_edgeB.next; } if (t.m_edgeB.next) { t.m_edgeB.next.prev = t.m_edgeB.prev; } if (t.m_edgeB === e.m_jointList) { e.m_jointList = t.m_edgeB.next; } t.m_edgeB.Reset(); b2World._Joint_Destroy(t); --this.m_jointCount; if (!s) { let t = e.GetContactList(); while (t) { if (t.other === i) { t.contact.FlagForFiltering(); } t = t.next; } } } CreateParticleSystem(t) { if (this.IsLocked()) { throw new Error; } const i = new b2ParticleSystem(t, this); i.m_prev = null; i.m_next = this.m_particleSystemList; if (this.m_particleSystemList) { this.m_particleSystemList.m_prev = i; } this.m_particleSystemList = i; return i; } DestroyParticleSystem(t) { if (this.IsLocked()) { throw new Error; } 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_particleSystemList) { this.m_particleSystemList = t.m_next; } } CalculateReasonableParticleIterations(t) { if (this.m_particleSystemList === null) { return 1; } function GetSmallestRadius(t) { let i = b2_maxFloat; for (let e = t.GetParticleSystemList(); e !== null; e = e.m_next) { i = b2Min(i, e.GetRadius()); } return i; } return b2CalculateParticleIterations(this.m_gravity.Length(), GetSmallestRadius(this), t); } Step(t, i, e, s = this.CalculateReasonableParticleIterations(t)) { const r = b2World.Step_s_stepTimer.Reset(); if (this.m_newContacts) { this.m_contactManager.FindNewContacts(); this.m_newContacts = false; } this.m_locked = true; const o = b2World.Step_s_step; o.dt = t; o.velocityIterations = i; o.positionIterations = e; o.particleIterations = s; if (t > 0) { o.inv_dt = 1 / t; } else { o.inv_dt = 0; } o.dtRatio = this.m_inv_dt0 * t; o.warmStarting = this.m_warmStarting; const n = b2World.Step_s_timer.Reset(); this.m_contactManager.Collide(); this.m_profile.collide = n.GetMilliseconds(); if (this.m_stepComplete && o.dt > 0) { const t = b2World.Step_s_timer.Reset(); for (let t = this.m_particleSystemList; t; t = t.m_next) { t.Solve(o); } this.Solve(o); this.m_profile.solve = t.GetMilliseconds(); } if (this.m_continuousPhysics && o.dt > 0) { const t = b2World.Step_s_timer.Reset(); this.SolveTOI(o); this.m_profile.solveTOI = t.GetMilliseconds(); } if (o.dt > 0) { this.m_inv_dt0 = o.inv_dt; } if (this.m_clearForces) { this.ClearForces(); } this.m_locked = false; this.m_profile.step = r.GetMilliseconds(); } ClearForces() { for (let t = this.m_bodyList; t; t = t.m_next) { t.m_force.SetZero(); t.m_torque = 0; } } DrawParticleSystem(t) { if (this.m_debugDraw === null) { return; } const i = t.GetParticleCount(); if (i) { const e = t.GetRadius(); const s = t.GetPositionBuffer(); if (t.m_colorBuffer.data) { const r = t.GetColorBuffer(); this.m_debugDraw.DrawParticles(s, e, r, i); } else { this.m_debugDraw.DrawParticles(s, e, null, i); } } } DebugDraw() { if (this.m_debugDraw === null) { return; } const t = this.m_debugDraw.GetFlags(); const i = b2World.DebugDraw_s_color.SetRGB(0, 0, 0); if (t & b2DrawFlags.e_shapeBit) { for (let t = this.m_bodyList; t; t = t.m_next) { const e = t.m_xf; this.m_debugDraw.PushTransform(e); for (let e = t.GetFixtureList(); e; e = e.m_next) { if (t.GetType() === b2BodyType.b2_dynamicBody && t.m_mass === 0) { this.DrawShape(e, new b2Color(1, 0, 0)); } else if (!t.IsEnabled()) { i.SetRGB(.5, .5, .3); this.DrawShape(e, i); } else if (t.GetType() === b2BodyType.b2_staticBody) { i.SetRGB(.5, .9, .5); this.DrawShape(e, i); } else if (t.GetType() === b2BodyType.b2_kinematicBody) { i.SetRGB(.5, .5, .9); this.DrawShape(e, i); } else if (!t.IsAwake()) { i.SetRGB(.6, .6, .6); this.DrawShape(e, i); } else { i.SetRGB(.9, .7, .7); this.DrawShape(e, i); } } this.m_debugDraw.PopTransform(e); } } if (t & b2DrawFlags.e_particleBit) { for (let t = this.m_particleSystemList; t; t = t.m_next) { this.DrawParticleSystem(t); } } if (t & b2DrawFlags.e_jointBit) { for (let t = this.m_jointList; t; t = t.m_next) { t.Draw(this.m_debugDraw); } } if (t & b2DrawFlags.e_pairBit) { i.SetRGB(.3, .9, .9); for (let t = this.m_contactManager.m_contactList; t; t = t.m_next) { const e = t.GetFixtureA(); const s = t.GetFixtureB(); const r = t.GetChildIndexA(); const o = t.GetChildIndexB(); const n = e.GetAABB(r).GetCenter(); const l = s.GetAABB(o).GetCenter(); this.m_debugDraw.DrawSegment(n, l, i); } } if (t & b2DrawFlags.e_aabbBit) { i.SetRGB(.9, .3, .9); const t = b2World.DebugDraw_s_vs; for (let e = this.m_bodyList; e; e = e.m_next) { if (!e.IsEnabled()) { continue; } for (let s = e.GetFixtureList(); s; s = s.m_next) { for (let e = 0; e < s.m_proxyCount; ++e) { const r = s.m_proxies[e]; const o = r.treeNode.aabb; t[0].Set(o.lowerBound.x, o.lowerBound.y); t[1].Set(o.upperBound.x, o.lowerBound.y); t[2].Set(o.upperBound.x, o.upperBound.y); t[3].Set(o.lowerBound.x, o.upperBound.y); this.m_debugDraw.DrawPolygon(t, 4, i); } } } } if (t & b2DrawFlags.e_centerOfMassBit) { for (let t = this.m_bodyList; t; t = t.m_next) { const i = b2World.DebugDraw_s_xf; i.q.Copy(t.m_xf.q); i.p.Copy(t.GetWorldCenter()); this.m_debugDraw.DrawTransform(i); } } if (t & b2DrawFlags.e_controllerBit) { for (let t = this.m_controllerList; t; t = t.m_next) { t.Draw(this.m_debugDraw); } } } QueryAABB(...t) { if (t[0] instanceof b2QueryCallback) { this._QueryAABB(t[0], t[1]); } else { this._QueryAABB(null, t[0], t[1]); } } _QueryAABB(t, i, e) { this.m_contactManager.m_broadPhase.Query(i, (i => { const s = i.userData; const r = s.fixture; if (t) { return t.ReportFixture(r); } else if (e) { return e(r); } return true; })); if (t instanceof b2QueryCallback) { for (let e = this.m_particleSystemList; e; e = e.m_next) { if (t.ShouldQueryParticleSystem(e)) { e.QueryAABB(t, i); } } } } QueryAllAABB(t, i = []) { this.QueryAABB(t, (t => { i.push(t); return true; })); return i; } QueryPointAABB(...t) { if (t[0] instanceof b2QueryCallback) { this._QueryPointAABB(t[0], t[1]); } else { this._QueryPointAABB(null, t[0], t[1]); } } _QueryPointAABB(t, i, e) { this.m_contactManager.m_broadPhase.QueryPoint(i, (i => { const s = i.userData; const r = s.fixture; if (t) { return t.ReportFixture(r); } else if (e) { return e(r); } return true; })); if (t instanceof b2QueryCallback) { for (let e = this.m_particleSystemList; e; e = e.m_next) { if (t.ShouldQueryParticleSystem(e)) { e.QueryPointAABB(t, i); } } } } QueryAllPointAABB(t, i = []) { this.QueryPointAABB(t, (t => { i.push(t); return true; })); return i; } QueryFixtureShape(...t) { if (t[0] instanceof b2QueryCallback) { this._QueryFixtureShape(t[0], t[1], t[2], t[3]); } else { this._QueryFixtureShape(null, t[0], t[1], t[2], t[3]); } } _QueryFixtureShape(t, i, e, s, r) { const o = b2World.QueryFixtureShape_s_aabb; i.ComputeAABB(o, s, e); this.m_contactManager.m_broadPhase.Query(o, (o => { const n = o.userData; const l = n.fixture; if (b2TestOverlapShape(i, e, l.GetShape(), n.childIndex, s, l.GetBody().GetTransform())) { if (t) { return t.ReportFixture(l); } else if (r) { return r(l); } } return true; })); if (t instanceof b2QueryCallback) { for (let i = this.m_particleSystemList; i; i = i.m_next) { if (t.ShouldQueryParticleSystem(i)) { i.QueryAABB(t, o); } } } } QueryAllFixtureShape(t, i, e, s = []) { this.QueryFixtureShape(t, i, e, (t => { s.push(t); return true; })); return s; } QueryFixturePoint(...t) { if (t[0] instanceof b2QueryCallback) { this._QueryFixturePoint(t[0], t[1]); } else { this._QueryFixturePoint(null, t[0], t[1]); } } _QueryFixturePoint(t, i, e) { this.m_contactManager.m_broadPhase.QueryPoint(i, (s => { const r = s.userData; const o = r.fixture; if (o.TestPoint(i)) { if (t) { return t.ReportFixture(o); } else if (e) { return e(o); } } return true; })); if (t) { for (let e = this.m_particleSystemList; e; e = e.m_next) { if (t.ShouldQueryParticleSystem(e)) { e.QueryPointAABB(t, i); } } } } QueryAllFixturePoint(t, i = []) { this.QueryFixturePoint(t, (t => { i.push(t); return true; })); return i; } RayCast(...t) { if (t[0] instanceof b2RayCastCallback) { this._RayCast(t[0], t[1], t[2]); } else { this._RayCast(null, t[0], t[1], t[2]); } } _RayCast(t, i, e, s) { const r = b2World.RayCast_s_input; r.maxFraction = 1; r.p1.Copy(i); r.p2.Copy(e); this.m_contactManager.m_broadPhase.RayCast(r, ((r, o) => { const n = o.userData; const l = n.fixture; const h = n.childIndex; const f = b2World.RayCast_s_output; const c = l.RayCast(f, r, h); if (c) { const r = f.fraction; const o = b2World.RayCast_s_point; o.Set((1 - r) * i.x + r * e.x, (1 - r) * i.y + r * e.y); if (t) { return t.ReportFixture(l, o, f.normal, r); } else if (s) { return s(l, o, f.normal, r); } } return r.maxFraction; })); if (t) { for (let s = this.m_particleSystemList; s; s = s.m_next) { if (t.ShouldQueryParticleSystem(s)) { s.RayCast(t, i, e); } } } } RayCastOne(t, i) { let e = null; let s = 1; this.RayCast(t, i, ((t, i, r, o) => { if (o < s) { s = o; e = t; } return s; })); return e; } RayCastAll(t, i, e = []) { this.RayCast(t, i, ((t, i, s, r) => { e.push(t); return 1; })); return e; } GetBodyList() { return this.m_bodyList; } GetJointList() { return this.m_jointList; } GetParticleSystemList() { return this.m_particleSystemList; } GetContactList() { return this.m_contactManager.m_contactList; } SetAllowSleeping(t) { if (t === this.m_allowSleep) { return; } this.m_allowSleep = t; if (!this.m_allowSleep) { for (let t = this.m_bodyList; t; t = t.m_next) { t.SetAwake(true); } } } GetAllowSleeping() { return this.m_allowSleep; } SetWarmStarting(t) { this.m_warmStarting = t; } GetWarmStarting() { return this.m_warmStarting; } SetContinuousPhysics(t) { this.m_continuousPhysics = t; } GetContinuousPhysics() { return this.m_continuousPhysics; } SetSubStepping(t) { this.m_subStepping = t; } GetSubStepping() { return this.m_subStepping; } GetProxyCount() { return this.m_contactManager.m_broadPhase.GetProxyCount(); } GetBodyCount() { return this.m_bodyCount; } GetJointCount() { return this.m_jointCount; } GetContactCount() { return this.m_contactManager.m_contactCount; } GetTreeHeight() { return this.m_contactManager.m_broadPhase.GetTreeHeight(); } GetTreeBalance() { return this.m_contactManager.m_broadPhase.GetTreeBalance(); } GetTreeQuality() { return this.m_contactManager.m_broadPhase.GetTreeQuality(); } SetGravity(t, i = true) { if (!b2Vec2.IsEqualToV(this.m_gravity, t)) { this.m_gravity.Copy(t); if (i) { for (let t = this.m_bodyList; t; t = t.m_next) { t.SetAwake(true); } } } } GetGravity() { return this.m_gravity; } IsLocked() { return this.m_locked; } SetAutoClearForces(t) { this.m_clearForces = t; } GetAutoClearForces() { return this.m_clearForces; } ShiftOrigin(t) { if (this.IsLocked()) { throw new Error; } for (let i = this.m_bodyList; i; i = i.m_next) { i.m_xf.p.SelfSub(t); i.m_sweep.c0.SelfSub(t); i.m_sweep.c.SelfSub(t); } for (let i = this.m_jointList; i; i = i.m_next) { i.ShiftOrigin(t); } this.m_contactManager.m_broadPhase.ShiftOrigin(t); } GetContactManager() { return this.m_contactManager; } GetProfile() { return this.m_profile; } Dump(t) { if (this.m_locked) { return; } t("const g: b2Vec2 = new b2Vec2(%.15f, %.15f);\n", this.m_gravity.x, this.m_gravity.y); t("this.m_world.SetGravity(g);\n"); t("const bodies: b2Body[] = [];\n"); t("const joints: b2Joint[] = [];\n"); let i = 0; for (let e = this.m_bodyList; e; e = e.m_next) { e.m_islandIndex = i; e.Dump(t); ++i; } i = 0; for (let t = this.m_jointList; t; t = t.m_next) { t.m_index = i; ++i; } for (let i = this.m_jointList; i; i = i.m_next) { if (i.m_type === b2JointType.e_gearJoint) { continue; } t("{\n"); i.Dump(t); t("}\n"); } for (let i = this.m_jointList; i; i = i.m_next) { if (i.m_type !== b2JointType.e_gearJoint) { continue; } t("{\n"); i.Dump(t); t("}\n"); } } DrawShape(t, i) { if (this.m_debugDraw === null) { return; } const e = t.GetShape(); switch (e.m_type) { case b2ShapeType.e_circleShape: { const t = e; const s = t.m_p; const r = t.m_radius; const o = b2Vec2.UNITX; this.m_debugDraw.DrawSolidCircle(s, r, o, i); break; } case b2ShapeType.e_edgeShape: { const t = e; const s = t.m_vertex1; const r = t.m_vertex2; this.m_debugDraw.DrawSegment(s, r, i); if (t.m_oneSided === false) { this.m_debugDraw.DrawPoint(s, 4, i); this.m_debugDraw.DrawPoint(r, 4, i); } break; } case b2ShapeType.e_chainShape: { const t = e; const s = t.m_count; const r = t.m_vertices; let o = r[0]; for (let t = 1; t < s; ++t) { const e = r[t]; this.m_debugDraw.DrawSegment(o, e, i); o = e; } break; } case b2ShapeType.e_polygonShape: { const t = e; const s = t.m_count; const r = t.m_vertices; this.m_debugDraw.DrawSolidPolygon(r, s, i); break; } } } Solve(t) { for (let t = this.m_bodyList; t; t = t.m_next) { t.m_xf0.Copy(t.m_xf); } for (let i = this.m_controllerList; i; i = i.m_next) { i.Step(t); } this.m_profile.solveInit = 0; this.m_profile.solveVelocity = 0; this.m_profile.solvePosition = 0; const i = this.m_island; i.Initialize(this.m_bodyCount, this.m_contactManager.m_contactCount, this.m_jointCount, this.m_contactManager.m_contactListener); for (let t = this.m_bodyList; t; t = t.m_next) { t.m_islandFlag = false; } for (let t = this.m_contactManager.m_contactList; t; t = t.m_next) { t.m_islandFlag = false; } for (let t = this.m_jointList; t; t = t.m_next) { t.m_islandFlag = false; } const e = this.s_stack; for (let s = this.m_bodyList; s; s = s.m_next) { if (s.m_islandFlag) { continue; } if (!s.IsAwake() || !s.IsEnabled()) { continue; } if (s.GetType() === b2BodyType.b2_staticBody) { continue; } i.Clear(); let r = 0; e[r++] = s; s.m_islandFlag = true; while (r > 0) { const t = e[--r]; if (!t) { throw new Error; } i.AddBody(t); if (t.GetType() === b2BodyType.b2_staticBody) { continue; } t.m_awakeFlag = true; for (let s = t.m_contactList; s; s = s.next) { const t = s.contact; if (t.m_islandFlag) { continue; } if (!t.IsEnabled() || !t.IsTouching()) { continue; } const o = t.m_fixtureA.m_isSensor; const n = t.m_fixtureB.m_isSensor; if (o || n) { continue; } i.AddContact(t); t.m_islandFlag = true; const l = s.other; if (l.m_islandFlag) { continue; } e[r++] = l; l.m_islandFlag = true; } for (let s = t.m_jointList; s; s = s.next) { if (s.joint.m_islandFlag) { continue; } const t = s.other; if (!t.IsEnabled()) { continue; } i.AddJoint(s.joint); s.joint.m_islandFlag = true; if (t.m_islandFlag) { continue; } e[r++] = t; t.m_islandFlag = true; } } const o = new b2Profile; i.Solve(o, t, this.m_gravity, this.m_allowSleep); this.m_profile.solveInit += o.solveInit; this.m_profile.solveVelocity += o.solveVelocity; this.m_profile.solvePosition += o.solvePosition; for (let t = 0; t < i.m_bodyCount; ++t) { const e = i.m_bodies[t]; if (e.GetType() === b2BodyType.b2_staticBody) { e.m_islandFlag = false; } } } for (let t = 0; t < e.length; ++t) { if (!e[t]) { break; } e[t] = null; } const s = new b2Timer; for (let t = this.m_bodyList; t; t = t.m_next) { if (!t.m_islandFlag) { continue; } if (t.GetType() === b2BodyType.b2_staticBody) { continue; } t.SynchronizeFixtures(); } this.m_contactManager.FindNewContacts(); this.m_profile.broadphase = s.GetMilliseconds(); } SolveTOI(t) { const i = this.m_island; i.Initialize(2 * b2_maxTOIContacts, b2_maxTOIContacts, 0, this.m_contactManager.m_contactListener); if (this.m_stepComplete) { for (let t = this.m_bodyList; t; t = t.m_next) { t.m_islandFlag = false; t.m_sweep.alpha0 = 0; } for (let t = this.m_contactManager.m_contactList; t; t = t.m_next) { t.m_toiFlag = false; t.m_islandFlag = false; t.m_toiCount = 0; t.m_toi = 1; } } for (;;) { let e = null; let s = 1; for (let t = this.m_contactManager.m_contactList; t; t = t.m_next) { if (!t.IsEnabled()) { continue; } if (t.m_toiCount > b2_maxSubSteps) { continue; } let i = 1; if (t.m_toiFlag) { i = t.m_toi; } else { const e = t.GetFixtureA(); const s = t.GetFixtureB(); if (e.IsSensor() || s.IsSensor()) { continue; } const r = e.GetBody(); const o = s.GetBody(); const n = r.m_type; const l = o.m_type; const h = r.IsAwake() && n !== b2BodyType.b2_staticBody; const f = o.IsAwake() && l !== b2BodyType.b2_staticBody; if (!h && !f) { continue; } const c = r.IsBullet() || n !== b2BodyType.b2_dynamicBody; const u = o.IsBullet() || l !== b2BodyType.b2_dynamicBody; if (!c && !u) { continue; } let b = r.m_sweep.alpha0; if (r.m_sweep.alpha0 < o.m_sweep.alpha0) { b = o.m_sweep.alpha0; r.m_sweep.Advance(b); } else if (o.m_sweep.alpha0 < r.m_sweep.alpha0) { b = r.m_sweep.alpha0; o.m_sweep.Advance(b); } const a = t.GetChildIndexA(); const p = t.GetChildIndexB(); const m = b2World.SolveTOI_s_toi_input; m.proxyA.SetShape(e.GetShape(), a); m.proxyB.SetShape(s.GetShape(), p); m.sweepA.Copy(r.m_sweep); m.sweepB.Copy(o.m_sweep); m.tMax = 1; const y = b2World.SolveTOI_s_toi_output; b2TimeOfImpact(y, m); const w = y.t; if (y.state === b2TOIOutputState.e_touching) { i = b2Min(b + (1 - b) * w, 1); } else { i = 1; } t.m_toi = i; t.m_toiFlag = true; } if (i < s) { e = t; s = i; } } if (e === null || 1 - 10 * b2_epsilon < s) { this.m_stepComplete = true; break; } const r = e.GetFixtureA(); const o = e.GetFixtureB(); const n = r.GetBody(); const l = o.GetBody(); const h = b2World.SolveTOI_s_backup1.Copy(n.m_sweep); const f = b2World.SolveTOI_s_backup2.Copy(l.m_sweep); n.Advance(s); l.Advance(s); e.Update(this.m_contactManager.m_contactListener); e.m_toiFlag = false; ++e.m_toiCount; if (!e.IsEnabled() || !e.IsTouching()) { e.SetEnabled(false); n.m_sweep.Copy(h); l.m_sweep.Copy(f); n.SynchronizeTransform(); l.SynchronizeTransform(); continue; } n.SetAwake(true); l.SetAwake(true); i.Clear(); i.AddBody(n); i.AddBody(l); i.AddContact(e); n.m_islandFlag = true; l.m_islandFlag = true; e.m_islandFlag = true; for (let t = 0; t < 2; ++t) { const e = t === 0 ? n : l; if (e.m_type === b2BodyType.b2_dynamicBody) { for (let t = e.m_contactList; t; t = t.next) { if (i.m_bodyCount === i.m_bodyCapacity) { break; } if (i.m_contactCount === i.m_contactCapacity) { break; } const r = t.contact; if (r.m_islandFlag) { continue; } const o = t.other; if (o.m_type === b2BodyType.b2_dynamicBody && !e.IsBullet() && !o.IsBullet()) { continue; } const n = r.m_fixtureA.m_isSensor; const l = r.m_fixtureB.m_isSensor; if (n || l) { continue; } const h = b2World.SolveTOI_s_backup.Copy(o.m_sweep); if (!o.m_islandFlag) { o.Advance(s); } r.Update(this.m_contactManager.m_contactListener); if (!r.IsEnabled()) { o.m_sweep.Copy(h); o.SynchronizeTransform(); continue; } if (!r.IsTouching()) { o.m_sweep.Copy(h); o.SynchronizeTransform(); continue; } r.m_islandFlag = true; i.AddContact(r); if (o.m_islandFlag) { continue; } o.m_islandFlag = true; if (o.m_type !== b2BodyType.b2_staticBody) { o.SetAwake(true); } i.AddBody(o); } } } const c = b2World.SolveTOI_s_subStep; c.dt = (1 - s) * t.dt; c.inv_dt = 1 / c.dt; c.dtRatio = 1; c.positionIterations = 20; c.velocityIterations = t.velocityIterations; c.particleIterations = t.particleIterations; c.warmStarting = false; i.SolveTOI(c, n.m_islandIndex, l.m_islandIndex); for (let t = 0; t < i.m_bodyCount; ++t) { const e = i.m_bodies[t]; e.m_islandFlag = false; if (e.m_type !== b2BodyType.b2_dynamicBody) { continue; } e.SynchronizeFixtures(); for (let t = e.m_contactList; t; t = t.next) { t.contact.m_toiFlag = false; t.contact.m_islandFlag = false; } } this.m_contactManager.FindNewContacts(); if (this.m_subStepping) { this.m_stepComplete = false; break; } } } AddController(t) { t.m_next = this.m_controllerList; t.m_prev = null; if (this.m_controllerList) { this.m_controllerList.m_prev = t; } this.m_controllerList = t; ++this.m_controllerCount; return t; } RemoveController(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 (this.m_controllerList === t) { this.m_controllerList = t.m_next; } --this.m_controllerCount; t.m_prev = null; t.m_next = null; return t; } } b2World.Step_s_step = new b2TimeStep; b2World.Step_s_stepTimer = new b2Timer; b2World.Step_s_timer = new b2Timer; b2World.DebugDraw_s_color = new b2Color(0, 0, 0); b2World.DebugDraw_s_vs = b2Vec2.MakeArray(4); b2World.DebugDraw_s_xf = new b2Transform; b2World.QueryFixtureShape_s_aabb = new b2AABB; b2World.RayCast_s_input = new b2RayCastInput; b2World.RayCast_s_output = new b2RayCastOutput; b2World.RayCast_s_point = new b2Vec2; b2World.SolveTOI_s_subStep = new b2TimeStep; b2World.SolveTOI_s_backup = new b2Sweep; b2World.SolveTOI_s_backup1 = new b2Sweep; b2World.SolveTOI_s_backup2 = new b2Sweep; b2World.SolveTOI_s_toi_input = new b2TOIInput; b2World.SolveTOI_s_toi_output = new b2TOIOutput;