UNPKG

the-world-engine

Version:

three.js based, unity like game engine for browser

411 lines (390 loc) 16.3 kB
import { b2_linearSlop, b2_angularSlop, b2_maxAngularCorrection, b2Maybe } from "../common/b2_settings.js"; import { b2Abs, b2Clamp, b2Vec2, b2Mat22, b2Rot, b2Max, b2Transform } from "../common/b2_math.js"; import { b2Joint, b2JointDef, b2JointType } from "./b2_joint.js"; import { b2Color } from "../common/b2_draw.js"; export class b2RevoluteJointDef extends b2JointDef { constructor() { super(b2JointType.e_revoluteJoint); this.localAnchorA = new b2Vec2(0, 0); this.localAnchorB = new b2Vec2(0, 0); this.referenceAngle = 0; this.enableLimit = false; this.lowerAngle = 0; this.upperAngle = 0; this.enableMotor = false; this.motorSpeed = 0; this.maxMotorTorque = 0; } Initialize(t, s, i) { this.bodyA = t; this.bodyB = s; this.bodyA.GetLocalPoint(i, this.localAnchorA); this.bodyB.GetLocalPoint(i, this.localAnchorB); this.referenceAngle = this.bodyB.GetAngle() - this.bodyA.GetAngle(); } } export class b2RevoluteJoint extends b2Joint { constructor(t) { super(t); this.m_localAnchorA = new b2Vec2; this.m_localAnchorB = new b2Vec2; this.m_impulse = new b2Vec2; this.m_motorImpulse = 0; this.m_lowerImpulse = 0; this.m_upperImpulse = 0; this.m_enableMotor = false; this.m_maxMotorTorque = 0; this.m_motorSpeed = 0; this.m_enableLimit = false; this.m_referenceAngle = 0; this.m_lowerAngle = 0; this.m_upperAngle = 0; this.m_indexA = 0; this.m_indexB = 0; this.m_rA = new b2Vec2; this.m_rB = new b2Vec2; this.m_localCenterA = new b2Vec2; this.m_localCenterB = new b2Vec2; this.m_invMassA = 0; this.m_invMassB = 0; this.m_invIA = 0; this.m_invIB = 0; this.m_K = new b2Mat22; this.m_angle = 0; this.m_axialMass = 0; this.m_qA = new b2Rot; this.m_qB = new b2Rot; this.m_lalcA = new b2Vec2; this.m_lalcB = new b2Vec2; this.m_localAnchorA.Copy(b2Maybe(t.localAnchorA, b2Vec2.ZERO)); this.m_localAnchorB.Copy(b2Maybe(t.localAnchorB, b2Vec2.ZERO)); this.m_referenceAngle = b2Maybe(t.referenceAngle, 0); this.m_impulse.SetZero(); this.m_motorImpulse = 0; this.m_lowerAngle = b2Maybe(t.lowerAngle, 0); this.m_upperAngle = b2Maybe(t.upperAngle, 0); this.m_maxMotorTorque = b2Maybe(t.maxMotorTorque, 0); this.m_motorSpeed = b2Maybe(t.motorSpeed, 0); this.m_enableLimit = b2Maybe(t.enableLimit, false); this.m_enableMotor = b2Maybe(t.enableMotor, false); } InitVelocityConstraints(t) { this.m_indexA = this.m_bodyA.m_islandIndex; this.m_indexB = this.m_bodyB.m_islandIndex; this.m_localCenterA.Copy(this.m_bodyA.m_sweep.localCenter); this.m_localCenterB.Copy(this.m_bodyB.m_sweep.localCenter); this.m_invMassA = this.m_bodyA.m_invMass; this.m_invMassB = this.m_bodyB.m_invMass; this.m_invIA = this.m_bodyA.m_invI; this.m_invIB = this.m_bodyB.m_invI; const s = t.positions[this.m_indexA].a; const i = t.velocities[this.m_indexA].v; let e = t.velocities[this.m_indexA].w; const h = t.positions[this.m_indexB].a; const o = t.velocities[this.m_indexB].v; let n = t.velocities[this.m_indexB].w; const b = this.m_qA.SetAngle(s), c = this.m_qB.SetAngle(h); b2Vec2.SubVV(this.m_localAnchorA, this.m_localCenterA, this.m_lalcA); b2Rot.MulRV(b, this.m_lalcA, this.m_rA); b2Vec2.SubVV(this.m_localAnchorB, this.m_localCenterB, this.m_lalcB); b2Rot.MulRV(c, this.m_lalcB, this.m_rB); const r = this.m_invMassA, l = this.m_invMassB; const a = this.m_invIA, u = this.m_invIB; this.m_K.ex.x = r + l + this.m_rA.y * this.m_rA.y * a + this.m_rB.y * this.m_rB.y * u; this.m_K.ey.x = -this.m_rA.y * this.m_rA.x * a - this.m_rB.y * this.m_rB.x * u; this.m_K.ex.y = this.m_K.ey.x; this.m_K.ey.y = r + l + this.m_rA.x * this.m_rA.x * a + this.m_rB.x * this.m_rB.x * u; this.m_axialMass = a + u; let V; if (this.m_axialMass > 0) { this.m_axialMass = 1 / this.m_axialMass; V = false; } else { V = true; } this.m_angle = h - s - this.m_referenceAngle; if (this.m_enableLimit === false || V) { this.m_lowerImpulse = 0; this.m_upperImpulse = 0; } if (this.m_enableMotor === false || V) { this.m_motorImpulse = 0; } if (t.step.warmStarting) { this.m_impulse.SelfMul(t.step.dtRatio); this.m_motorImpulse *= t.step.dtRatio; this.m_lowerImpulse *= t.step.dtRatio; this.m_upperImpulse *= t.step.dtRatio; const s = this.m_motorImpulse + this.m_lowerImpulse - this.m_upperImpulse; const h = b2RevoluteJoint.InitVelocityConstraints_s_P.Set(this.m_impulse.x, this.m_impulse.y); i.SelfMulSub(r, h); e -= a * (b2Vec2.CrossVV(this.m_rA, h) + s); o.SelfMulAdd(l, h); n += u * (b2Vec2.CrossVV(this.m_rB, h) + s); } else { this.m_impulse.SetZero(); this.m_motorImpulse = 0; this.m_lowerImpulse = 0; this.m_upperImpulse = 0; } t.velocities[this.m_indexA].w = e; t.velocities[this.m_indexB].w = n; } SolveVelocityConstraints(t) { const s = t.velocities[this.m_indexA].v; let i = t.velocities[this.m_indexA].w; const e = t.velocities[this.m_indexB].v; let h = t.velocities[this.m_indexB].w; const o = this.m_invMassA, n = this.m_invMassB; const b = this.m_invIA, c = this.m_invIB; const r = b + c === 0; if (this.m_enableMotor && !r) { const s = h - i - this.m_motorSpeed; let e = -this.m_axialMass * s; const o = this.m_motorImpulse; const n = t.step.dt * this.m_maxMotorTorque; this.m_motorImpulse = b2Clamp(this.m_motorImpulse + e, -n, n); e = this.m_motorImpulse - o; i -= b * e; h += c * e; } if (this.m_enableLimit && !r) { { const s = this.m_angle - this.m_lowerAngle; const e = h - i; let o = -this.m_axialMass * (e + b2Max(s, 0) * t.step.inv_dt); const n = this.m_lowerImpulse; this.m_lowerImpulse = b2Max(this.m_lowerImpulse + o, 0); o = this.m_lowerImpulse - n; i -= b * o; h += c * o; } { const s = this.m_upperAngle - this.m_angle; const e = i - h; let o = -this.m_axialMass * (e + b2Max(s, 0) * t.step.inv_dt); const n = this.m_upperImpulse; this.m_upperImpulse = b2Max(this.m_upperImpulse + o, 0); o = this.m_upperImpulse - n; i += b * o; h -= c * o; } } { const t = b2Vec2.SubVV(b2Vec2.AddVCrossSV(e, h, this.m_rB, b2Vec2.s_t0), b2Vec2.AddVCrossSV(s, i, this.m_rA, b2Vec2.s_t1), b2RevoluteJoint.SolveVelocityConstraints_s_Cdot_v2); const r = this.m_K.Solve(-t.x, -t.y, b2RevoluteJoint.SolveVelocityConstraints_s_impulse_v2); this.m_impulse.x += r.x; this.m_impulse.y += r.y; s.SelfMulSub(o, r); i -= b * b2Vec2.CrossVV(this.m_rA, r); e.SelfMulAdd(n, r); h += c * b2Vec2.CrossVV(this.m_rB, r); } t.velocities[this.m_indexA].w = i; t.velocities[this.m_indexB].w = h; } SolvePositionConstraints(t) { const s = t.positions[this.m_indexA].c; let i = t.positions[this.m_indexA].a; const e = t.positions[this.m_indexB].c; let h = t.positions[this.m_indexB].a; const o = this.m_qA.SetAngle(i), n = this.m_qB.SetAngle(h); let b = 0; let c = 0; const r = this.m_invIA + this.m_invIB === 0; if (this.m_enableLimit && !r) { const t = h - i - this.m_referenceAngle; let s = 0; if (b2Abs(this.m_upperAngle - this.m_lowerAngle) < 2 * b2_angularSlop) { s = b2Clamp(t - this.m_lowerAngle, -b2_maxAngularCorrection, b2_maxAngularCorrection); } else if (t <= this.m_lowerAngle) { s = b2Clamp(t - this.m_lowerAngle + b2_angularSlop, -b2_maxAngularCorrection, 0); } else if (t >= this.m_upperAngle) { s = b2Clamp(t - this.m_upperAngle - b2_angularSlop, 0, b2_maxAngularCorrection); } const e = -this.m_axialMass * s; i -= this.m_invIA * e; h += this.m_invIB * e; b = b2Abs(s); } { o.SetAngle(i); n.SetAngle(h); b2Vec2.SubVV(this.m_localAnchorA, this.m_localCenterA, this.m_lalcA); const t = b2Rot.MulRV(o, this.m_lalcA, this.m_rA); b2Vec2.SubVV(this.m_localAnchorB, this.m_localCenterB, this.m_lalcB); const b = b2Rot.MulRV(n, this.m_lalcB, this.m_rB); const r = b2Vec2.SubVV(b2Vec2.AddVV(e, b, b2Vec2.s_t0), b2Vec2.AddVV(s, t, b2Vec2.s_t1), b2RevoluteJoint.SolvePositionConstraints_s_C_v2); c = r.Length(); const l = this.m_invMassA, a = this.m_invMassB; const u = this.m_invIA, V = this.m_invIB; const f = this.m_K; f.ex.x = l + a + u * t.y * t.y + V * b.y * b.y; f.ex.y = -u * t.x * t.y - V * b.x * b.y; f.ey.x = f.ex.y; f.ey.y = l + a + u * t.x * t.x + V * b.x * b.x; const R = f.Solve(r.x, r.y, b2RevoluteJoint.SolvePositionConstraints_s_impulse).SelfNeg(); s.SelfMulSub(l, R); i -= u * b2Vec2.CrossVV(t, R); e.SelfMulAdd(a, R); h += V * b2Vec2.CrossVV(b, R); } t.positions[this.m_indexA].a = i; t.positions[this.m_indexB].a = h; return c <= b2_linearSlop && b <= b2_angularSlop; } GetAnchorA(t) { return this.m_bodyA.GetWorldPoint(this.m_localAnchorA, t); } GetAnchorB(t) { return this.m_bodyB.GetWorldPoint(this.m_localAnchorB, t); } GetReactionForce(t, s) { s.x = t * this.m_impulse.x; s.y = t * this.m_impulse.y; return s; } GetReactionTorque(t) { return t * (this.m_lowerImpulse - this.m_upperImpulse); } GetLocalAnchorA() { return this.m_localAnchorA; } GetLocalAnchorB() { return this.m_localAnchorB; } GetReferenceAngle() { return this.m_referenceAngle; } GetJointAngle() { return this.m_bodyB.m_sweep.a - this.m_bodyA.m_sweep.a - this.m_referenceAngle; } GetJointSpeed() { return this.m_bodyB.m_angularVelocity - this.m_bodyA.m_angularVelocity; } IsMotorEnabled() { return this.m_enableMotor; } EnableMotor(t) { if (t !== this.m_enableMotor) { this.m_bodyA.SetAwake(true); this.m_bodyB.SetAwake(true); this.m_enableMotor = t; } } GetMotorTorque(t) { return t * this.m_motorImpulse; } GetMotorSpeed() { return this.m_motorSpeed; } SetMaxMotorTorque(t) { if (t !== this.m_maxMotorTorque) { this.m_bodyA.SetAwake(true); this.m_bodyB.SetAwake(true); this.m_maxMotorTorque = t; } } GetMaxMotorTorque() { return this.m_maxMotorTorque; } IsLimitEnabled() { return this.m_enableLimit; } EnableLimit(t) { if (t !== this.m_enableLimit) { this.m_bodyA.SetAwake(true); this.m_bodyB.SetAwake(true); this.m_enableLimit = t; this.m_lowerImpulse = 0; this.m_upperImpulse = 0; } } GetLowerLimit() { return this.m_lowerAngle; } GetUpperLimit() { return this.m_upperAngle; } SetLimits(t, s) { if (t !== this.m_lowerAngle || s !== this.m_upperAngle) { this.m_bodyA.SetAwake(true); this.m_bodyB.SetAwake(true); this.m_lowerImpulse = 0; this.m_upperImpulse = 0; this.m_lowerAngle = t; this.m_upperAngle = s; } } SetMotorSpeed(t) { if (t !== this.m_motorSpeed) { this.m_bodyA.SetAwake(true); this.m_bodyB.SetAwake(true); this.m_motorSpeed = t; } } Dump(t) { const s = this.m_bodyA.m_islandIndex; const i = this.m_bodyB.m_islandIndex; t(" const jd: b2RevoluteJointDef = new b2RevoluteJointDef();\n"); t(" jd.bodyA = bodies[%d];\n", s); t(" jd.bodyB = bodies[%d];\n", i); t(" jd.collideConnected = %s;\n", this.m_collideConnected ? "true" : "false"); t(" jd.localAnchorA.Set(%.15f, %.15f);\n", this.m_localAnchorA.x, this.m_localAnchorA.y); t(" jd.localAnchorB.Set(%.15f, %.15f);\n", this.m_localAnchorB.x, this.m_localAnchorB.y); t(" jd.referenceAngle = %.15f;\n", this.m_referenceAngle); t(" jd.enableLimit = %s;\n", this.m_enableLimit ? "true" : "false"); t(" jd.lowerAngle = %.15f;\n", this.m_lowerAngle); t(" jd.upperAngle = %.15f;\n", this.m_upperAngle); t(" jd.enableMotor = %s;\n", this.m_enableMotor ? "true" : "false"); t(" jd.motorSpeed = %.15f;\n", this.m_motorSpeed); t(" jd.maxMotorTorque = %.15f;\n", this.m_maxMotorTorque); t(" joints[%d] = this.m_world.CreateJoint(jd);\n", this.m_index); } Draw(t) { const s = this.m_bodyA.GetTransform(); const i = this.m_bodyB.GetTransform(); const e = b2Transform.MulXV(s, this.m_localAnchorA, b2RevoluteJoint.Draw_s_pA); const h = b2Transform.MulXV(i, this.m_localAnchorB, b2RevoluteJoint.Draw_s_pB); const o = b2RevoluteJoint.Draw_s_c1; const n = b2RevoluteJoint.Draw_s_c2; const b = b2RevoluteJoint.Draw_s_c3; const c = b2RevoluteJoint.Draw_s_c4; const r = b2RevoluteJoint.Draw_s_c5; t.DrawPoint(e, 5, c); t.DrawPoint(h, 5, r); const l = this.m_bodyA.GetAngle(); const a = this.m_bodyB.GetAngle(); const u = a - l - this.m_referenceAngle; const V = .5; const f = b2RevoluteJoint.Draw_s_r.Set(V * Math.cos(u), V * Math.sin(u)); t.DrawSegment(h, b2Vec2.AddVV(h, f, b2Vec2.s_t0), o); t.DrawCircle(h, V, o); if (this.m_enableLimit) { const s = b2RevoluteJoint.Draw_s_rlo.Set(V * Math.cos(this.m_lowerAngle), V * Math.sin(this.m_lowerAngle)); const i = b2RevoluteJoint.Draw_s_rhi.Set(V * Math.cos(this.m_upperAngle), V * Math.sin(this.m_upperAngle)); t.DrawSegment(h, b2Vec2.AddVV(h, s, b2Vec2.s_t0), n); t.DrawSegment(h, b2Vec2.AddVV(h, i, b2Vec2.s_t0), b); } const R = b2RevoluteJoint.Draw_s_color_; t.DrawSegment(s.p, e, R); t.DrawSegment(e, h, R); t.DrawSegment(i.p, h, R); } } b2RevoluteJoint.InitVelocityConstraints_s_P = new b2Vec2; b2RevoluteJoint.SolveVelocityConstraints_s_Cdot_v2 = new b2Vec2; b2RevoluteJoint.SolveVelocityConstraints_s_impulse_v2 = new b2Vec2; b2RevoluteJoint.SolvePositionConstraints_s_C_v2 = new b2Vec2; b2RevoluteJoint.SolvePositionConstraints_s_impulse = new b2Vec2; b2RevoluteJoint.Draw_s_pA = new b2Vec2; b2RevoluteJoint.Draw_s_pB = new b2Vec2; b2RevoluteJoint.Draw_s_c1 = new b2Color(.7, .7, .7); b2RevoluteJoint.Draw_s_c2 = new b2Color(.3, .9, .3); b2RevoluteJoint.Draw_s_c3 = new b2Color(.9, .3, .3); b2RevoluteJoint.Draw_s_c4 = new b2Color(.3, .3, .9); b2RevoluteJoint.Draw_s_c5 = new b2Color(.4, .4, .4); b2RevoluteJoint.Draw_s_color_ = new b2Color(.5, .8, .8); b2RevoluteJoint.Draw_s_r = new b2Vec2; b2RevoluteJoint.Draw_s_rlo = new b2Vec2; b2RevoluteJoint.Draw_s_rhi = new b2Vec2;