UNPKG

the-world-engine

Version:

three.js based, unity like game engine for browser

519 lines (491 loc) 21.7 kB
import { b2_linearSlop, b2_angularSlop, b2Maybe } from "../common/b2_settings.js"; import { b2Abs, b2Min, b2Max, b2Clamp, b2Vec2, b2Mat22, b2Vec3, b2Mat33, b2Rot, b2Transform } from "../common/b2_math.js"; import { b2Joint, b2JointDef, b2JointType } from "./b2_joint.js"; import { b2Color } from "../common/b2_draw.js"; export class b2PrismaticJointDef extends b2JointDef { constructor() { super(b2JointType.e_prismaticJoint); this.localAnchorA = new b2Vec2; this.localAnchorB = new b2Vec2; this.localAxisA = new b2Vec2(1, 0); this.referenceAngle = 0; this.enableLimit = false; this.lowerTranslation = 0; this.upperTranslation = 0; this.enableMotor = false; this.maxMotorForce = 0; this.motorSpeed = 0; } Initialize(t, i, s, h) { this.bodyA = t; this.bodyB = i; this.bodyA.GetLocalPoint(s, this.localAnchorA); this.bodyB.GetLocalPoint(s, this.localAnchorB); this.bodyA.GetLocalVector(h, this.localAxisA); this.referenceAngle = this.bodyB.GetAngle() - this.bodyA.GetAngle(); } } export class b2PrismaticJoint extends b2Joint { constructor(t) { super(t); this.m_localAnchorA = new b2Vec2; this.m_localAnchorB = new b2Vec2; this.m_localXAxisA = new b2Vec2; this.m_localYAxisA = new b2Vec2; this.m_referenceAngle = 0; this.m_impulse = new b2Vec2(0, 0); this.m_motorImpulse = 0; this.m_lowerImpulse = 0; this.m_upperImpulse = 0; this.m_lowerTranslation = 0; this.m_upperTranslation = 0; this.m_maxMotorForce = 0; this.m_motorSpeed = 0; this.m_enableLimit = false; this.m_enableMotor = false; this.m_indexA = 0; this.m_indexB = 0; 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_axis = new b2Vec2(0, 0); this.m_perp = new b2Vec2(0, 0); this.m_s1 = 0; this.m_s2 = 0; this.m_a1 = 0; this.m_a2 = 0; this.m_K = new b2Mat22; this.m_K3 = new b2Mat33; this.m_K2 = new b2Mat22; this.m_translation = 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_rA = new b2Vec2; this.m_rB = new b2Vec2; this.m_localAnchorA.Copy(b2Maybe(t.localAnchorA, b2Vec2.ZERO)); this.m_localAnchorB.Copy(b2Maybe(t.localAnchorB, b2Vec2.ZERO)); this.m_localXAxisA.Copy(b2Maybe(t.localAxisA, new b2Vec2(1, 0))).SelfNormalize(); b2Vec2.CrossOneV(this.m_localXAxisA, this.m_localYAxisA); this.m_referenceAngle = b2Maybe(t.referenceAngle, 0); this.m_lowerTranslation = b2Maybe(t.lowerTranslation, 0); this.m_upperTranslation = b2Maybe(t.upperTranslation, 0); this.m_maxMotorForce = b2Maybe(t.maxMotorForce, 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 i = t.positions[this.m_indexA].c; const s = t.positions[this.m_indexA].a; const h = t.velocities[this.m_indexA].v; let e = t.velocities[this.m_indexA].w; const c = t.positions[this.m_indexB].c; const n = t.positions[this.m_indexB].a; const o = t.velocities[this.m_indexB].v; let b = t.velocities[this.m_indexB].w; const r = this.m_qA.SetAngle(s), a = this.m_qB.SetAngle(n); b2Vec2.SubVV(this.m_localAnchorA, this.m_localCenterA, this.m_lalcA); const V = b2Rot.MulRV(r, this.m_lalcA, this.m_rA); b2Vec2.SubVV(this.m_localAnchorB, this.m_localCenterB, this.m_lalcB); const m = b2Rot.MulRV(a, this.m_lalcB, this.m_rB); const l = b2Vec2.AddVV(b2Vec2.SubVV(c, i, b2Vec2.s_t0), b2Vec2.SubVV(m, V, b2Vec2.s_t1), b2PrismaticJoint.InitVelocityConstraints_s_d); const J = this.m_invMassA, f = this.m_invMassB; const P = this.m_invIA, w = this.m_invIB; { b2Rot.MulRV(r, this.m_localXAxisA, this.m_axis); this.m_a1 = b2Vec2.CrossVV(b2Vec2.AddVV(l, V, b2Vec2.s_t0), this.m_axis); this.m_a2 = b2Vec2.CrossVV(m, this.m_axis); this.m_axialMass = J + f + P * this.m_a1 * this.m_a1 + w * this.m_a2 * this.m_a2; if (this.m_axialMass > 0) { this.m_axialMass = 1 / this.m_axialMass; } } { b2Rot.MulRV(r, this.m_localYAxisA, this.m_perp); this.m_s1 = b2Vec2.CrossVV(b2Vec2.AddVV(l, V, b2Vec2.s_t0), this.m_perp); this.m_s2 = b2Vec2.CrossVV(m, this.m_perp); this.m_K.ex.x = J + f + P * this.m_s1 * this.m_s1 + w * this.m_s2 * this.m_s2; this.m_K.ex.y = P * this.m_s1 + w * this.m_s2; this.m_K.ey.x = this.m_K.ex.y; this.m_K.ey.y = P + w; if (this.m_K.ey.y === 0) { this.m_K.ey.y = 1; } } if (this.m_enableLimit) { this.m_translation = b2Vec2.DotVV(this.m_axis, l); } else { this.m_lowerImpulse = 0; this.m_upperImpulse = 0; } if (!this.m_enableMotor) { 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 i = this.m_motorImpulse + this.m_lowerImpulse - this.m_upperImpulse; const s = b2Vec2.AddVV(b2Vec2.MulSV(this.m_impulse.x, this.m_perp, b2Vec2.s_t0), b2Vec2.MulSV(i, this.m_axis, b2Vec2.s_t1), b2PrismaticJoint.InitVelocityConstraints_s_P); const c = this.m_impulse.x * this.m_s1 + this.m_impulse.y + i * this.m_a1; const n = this.m_impulse.x * this.m_s2 + this.m_impulse.y + i * this.m_a2; h.SelfMulSub(J, s); e -= P * c; o.SelfMulAdd(f, s); b += w * n; } 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 = b; } SolveVelocityConstraints(t) { const i = t.velocities[this.m_indexA].v; let s = t.velocities[this.m_indexA].w; const h = t.velocities[this.m_indexB].v; let e = t.velocities[this.m_indexB].w; const c = this.m_invMassA, n = this.m_invMassB; const o = this.m_invIA, b = this.m_invIB; if (this.m_enableMotor) { const r = b2Vec2.DotVV(this.m_axis, b2Vec2.SubVV(h, i, b2Vec2.s_t0)) + this.m_a2 * e - this.m_a1 * s; let a = this.m_axialMass * (this.m_motorSpeed - r); const V = this.m_motorImpulse; const m = t.step.dt * this.m_maxMotorForce; this.m_motorImpulse = b2Clamp(this.m_motorImpulse + a, -m, m); a = this.m_motorImpulse - V; const l = b2Vec2.MulSV(a, this.m_axis, b2PrismaticJoint.SolveVelocityConstraints_s_P); const J = a * this.m_a1; const f = a * this.m_a2; i.SelfMulSub(c, l); s -= o * J; h.SelfMulAdd(n, l); e += b * f; } if (this.m_enableLimit) { { const r = this.m_translation - this.m_lowerTranslation; const a = b2Vec2.DotVV(this.m_axis, b2Vec2.SubVV(h, i, b2Vec2.s_t0)) + this.m_a2 * e - this.m_a1 * s; let V = -this.m_axialMass * (a + b2Max(r, 0) * t.step.inv_dt); const m = this.m_lowerImpulse; this.m_lowerImpulse = b2Max(this.m_lowerImpulse + V, 0); V = this.m_lowerImpulse - m; const l = b2Vec2.MulSV(V, this.m_axis, b2PrismaticJoint.SolveVelocityConstraints_s_P); const J = V * this.m_a1; const f = V * this.m_a2; i.SelfMulSub(c, l); s -= o * J; h.SelfMulAdd(n, l); e += b * f; } { const r = this.m_upperTranslation - this.m_translation; const a = b2Vec2.DotVV(this.m_axis, b2Vec2.SubVV(i, h, b2Vec2.s_t0)) + this.m_a1 * s - this.m_a2 * e; let V = -this.m_axialMass * (a + b2Max(r, 0) * t.step.inv_dt); const m = this.m_upperImpulse; this.m_upperImpulse = b2Max(this.m_upperImpulse + V, 0); V = this.m_upperImpulse - m; const l = b2Vec2.MulSV(V, this.m_axis, b2PrismaticJoint.SolveVelocityConstraints_s_P); const J = V * this.m_a1; const f = V * this.m_a2; i.SelfMulAdd(c, l); s += o * J; h.SelfMulSub(n, l); e -= b * f; } } { const t = b2Vec2.DotVV(this.m_perp, b2Vec2.SubVV(h, i, b2Vec2.s_t0)) + this.m_s2 * e - this.m_s1 * s; const r = e - s; const a = this.m_K.Solve(-t, -r, b2PrismaticJoint.SolveVelocityConstraints_s_df); this.m_impulse.SelfAdd(a); const V = b2Vec2.MulSV(a.x, this.m_perp, b2PrismaticJoint.SolveVelocityConstraints_s_P); const m = a.x * this.m_s1 + a.y; const l = a.x * this.m_s2 + a.y; i.SelfMulSub(c, V); s -= o * m; h.SelfMulAdd(n, V); e += b * l; } t.velocities[this.m_indexA].w = s; t.velocities[this.m_indexB].w = e; } SolvePositionConstraints(t) { const i = t.positions[this.m_indexA].c; let s = t.positions[this.m_indexA].a; const h = t.positions[this.m_indexB].c; let e = t.positions[this.m_indexB].a; const c = this.m_qA.SetAngle(s), n = this.m_qB.SetAngle(e); const o = this.m_invMassA, b = this.m_invMassB; const r = this.m_invIA, a = this.m_invIB; const V = b2Rot.MulRV(c, this.m_lalcA, this.m_rA); const m = b2Rot.MulRV(n, this.m_lalcB, this.m_rB); const l = b2Vec2.SubVV(b2Vec2.AddVV(h, m, b2Vec2.s_t0), b2Vec2.AddVV(i, V, b2Vec2.s_t1), b2PrismaticJoint.SolvePositionConstraints_s_d); const J = b2Rot.MulRV(c, this.m_localXAxisA, this.m_axis); const f = b2Vec2.CrossVV(b2Vec2.AddVV(l, V, b2Vec2.s_t0), J); const P = b2Vec2.CrossVV(m, J); const w = b2Rot.MulRV(c, this.m_localYAxisA, this.m_perp); const u = b2Vec2.CrossVV(b2Vec2.AddVV(l, V, b2Vec2.s_t0), w); const M = b2Vec2.CrossVV(m, w); let d = b2PrismaticJoint.SolvePositionConstraints_s_impulse; const p = b2Vec2.DotVV(w, l); const j = e - s - this.m_referenceAngle; let A = b2Abs(p); const x = b2Abs(j); let R = false; let y = 0; if (this.m_enableLimit) { const t = b2Vec2.DotVV(J, l); if (b2Abs(this.m_upperTranslation - this.m_lowerTranslation) < 2 * b2_linearSlop) { y = t; A = b2Max(A, b2Abs(t)); R = true; } else if (t <= this.m_lowerTranslation) { y = b2Min(t - this.m_lowerTranslation, 0); A = b2Max(A, this.m_lowerTranslation - t); R = true; } else if (t >= this.m_upperTranslation) { y = b2Max(t - this.m_upperTranslation, 0); A = b2Max(A, t - this.m_upperTranslation); R = true; } } if (R) { const t = o + b + r * u * u + a * M * M; const i = r * u + a * M; const s = r * u * f + a * M * P; let h = r + a; if (h === 0) { h = 1; } const e = r * f + a * P; const c = o + b + r * f * f + a * P * P; const n = this.m_K3; n.ex.SetXYZ(t, i, s); n.ey.SetXYZ(i, h, e); n.ez.SetXYZ(s, e, c); d = n.Solve33(-p, -j, -y, d); } else { const t = o + b + r * u * u + a * M * M; const i = r * u + a * M; let s = r + a; if (s === 0) { s = 1; } const h = this.m_K2; h.ex.Set(t, i); h.ey.Set(i, s); const e = h.Solve(-p, -j, b2PrismaticJoint.SolvePositionConstraints_s_impulse1); d.x = e.x; d.y = e.y; d.z = 0; } const S = b2Vec2.AddVV(b2Vec2.MulSV(d.x, w, b2Vec2.s_t0), b2Vec2.MulSV(d.z, J, b2Vec2.s_t1), b2PrismaticJoint.SolvePositionConstraints_s_P); const G = d.x * u + d.y + d.z * f; const C = d.x * M + d.y + d.z * P; i.SelfMulSub(o, S); s -= r * G; h.SelfMulAdd(b, S); e += a * C; t.positions[this.m_indexA].a = s; t.positions[this.m_indexB].a = e; return A <= b2_linearSlop && x <= 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, i) { i.x = t * (this.m_impulse.x * this.m_perp.x + (this.m_motorImpulse + this.m_lowerImpulse - this.m_upperImpulse) * this.m_axis.x); i.y = t * (this.m_impulse.y * this.m_perp.y + (this.m_motorImpulse + this.m_lowerImpulse - this.m_upperImpulse) * this.m_axis.y); return i; } GetReactionTorque(t) { return t * this.m_impulse.y; } GetLocalAnchorA() { return this.m_localAnchorA; } GetLocalAnchorB() { return this.m_localAnchorB; } GetLocalAxisA() { return this.m_localXAxisA; } GetReferenceAngle() { return this.m_referenceAngle; } GetJointTranslation() { const t = this.m_bodyA.GetWorldPoint(this.m_localAnchorA, b2PrismaticJoint.GetJointTranslation_s_pA); const i = this.m_bodyB.GetWorldPoint(this.m_localAnchorB, b2PrismaticJoint.GetJointTranslation_s_pB); const s = b2Vec2.SubVV(i, t, b2PrismaticJoint.GetJointTranslation_s_d); const h = this.m_bodyA.GetWorldVector(this.m_localXAxisA, b2PrismaticJoint.GetJointTranslation_s_axis); const e = b2Vec2.DotVV(s, h); return e; } GetJointSpeed() { const t = this.m_bodyA; const i = this.m_bodyB; b2Vec2.SubVV(this.m_localAnchorA, t.m_sweep.localCenter, this.m_lalcA); const s = b2Rot.MulRV(t.m_xf.q, this.m_lalcA, this.m_rA); b2Vec2.SubVV(this.m_localAnchorB, i.m_sweep.localCenter, this.m_lalcB); const h = b2Rot.MulRV(i.m_xf.q, this.m_lalcB, this.m_rB); const e = b2Vec2.AddVV(t.m_sweep.c, s, b2Vec2.s_t0); const c = b2Vec2.AddVV(i.m_sweep.c, h, b2Vec2.s_t1); const n = b2Vec2.SubVV(c, e, b2Vec2.s_t2); const o = t.GetWorldVector(this.m_localXAxisA, this.m_axis); const b = t.m_linearVelocity; const r = i.m_linearVelocity; const a = t.m_angularVelocity; const V = i.m_angularVelocity; const m = b2Vec2.DotVV(n, b2Vec2.CrossSV(a, o, b2Vec2.s_t0)) + b2Vec2.DotVV(o, b2Vec2.SubVV(b2Vec2.AddVCrossSV(r, V, h, b2Vec2.s_t0), b2Vec2.AddVCrossSV(b, a, s, b2Vec2.s_t1), b2Vec2.s_t0)); return m; } 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_lowerTranslation; } GetUpperLimit() { return this.m_upperTranslation; } SetLimits(t, i) { if (t !== this.m_lowerTranslation || i !== this.m_upperTranslation) { this.m_bodyA.SetAwake(true); this.m_bodyB.SetAwake(true); this.m_lowerTranslation = t; this.m_upperTranslation = i; this.m_lowerImpulse = 0; this.m_upperImpulse = 0; } } 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; } } SetMotorSpeed(t) { if (t !== this.m_motorSpeed) { this.m_bodyA.SetAwake(true); this.m_bodyB.SetAwake(true); this.m_motorSpeed = t; } } GetMotorSpeed() { return this.m_motorSpeed; } SetMaxMotorForce(t) { if (t !== this.m_maxMotorForce) { this.m_bodyA.SetAwake(true); this.m_bodyB.SetAwake(true); this.m_maxMotorForce = t; } } GetMaxMotorForce() { return this.m_maxMotorForce; } GetMotorForce(t) { return t * this.m_motorImpulse; } Dump(t) { const i = this.m_bodyA.m_islandIndex; const s = this.m_bodyB.m_islandIndex; t(" const jd: b2PrismaticJointDef = new b2PrismaticJointDef();\n"); t(" jd.bodyA = bodies[%d];\n", i); t(" jd.bodyB = bodies[%d];\n", s); 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.localAxisA.Set(%.15f, %.15f);\n", this.m_localXAxisA.x, this.m_localXAxisA.y); t(" jd.referenceAngle = %.15f;\n", this.m_referenceAngle); t(" jd.enableLimit = %s;\n", this.m_enableLimit ? "true" : "false"); t(" jd.lowerTranslation = %.15f;\n", this.m_lowerTranslation); t(" jd.upperTranslation = %.15f;\n", this.m_upperTranslation); t(" jd.enableMotor = %s;\n", this.m_enableMotor ? "true" : "false"); t(" jd.motorSpeed = %.15f;\n", this.m_motorSpeed); t(" jd.maxMotorForce = %.15f;\n", this.m_maxMotorForce); t(" joints[%d] = this.m_world.CreateJoint(jd);\n", this.m_index); } Draw(t) { const i = this.m_bodyA.GetTransform(); const s = this.m_bodyB.GetTransform(); const h = b2Transform.MulXV(i, this.m_localAnchorA, b2PrismaticJoint.Draw_s_pA); const e = b2Transform.MulXV(s, this.m_localAnchorB, b2PrismaticJoint.Draw_s_pB); const c = b2Rot.MulRV(i.q, this.m_localXAxisA, b2PrismaticJoint.Draw_s_axis); const n = b2PrismaticJoint.Draw_s_c1; const o = b2PrismaticJoint.Draw_s_c2; const b = b2PrismaticJoint.Draw_s_c3; const r = b2PrismaticJoint.Draw_s_c4; const a = b2PrismaticJoint.Draw_s_c5; t.DrawSegment(h, e, a); if (this.m_enableLimit) { const s = b2Vec2.AddVMulSV(h, this.m_lowerTranslation, c, b2PrismaticJoint.Draw_s_lower); const e = b2Vec2.AddVMulSV(h, this.m_upperTranslation, c, b2PrismaticJoint.Draw_s_upper); const r = b2Rot.MulRV(i.q, this.m_localYAxisA, b2PrismaticJoint.Draw_s_perp); t.DrawSegment(s, e, n); t.DrawSegment(b2Vec2.AddVMulSV(s, -.5, r, b2Vec2.s_t0), b2Vec2.AddVMulSV(s, .5, r, b2Vec2.s_t1), o); t.DrawSegment(b2Vec2.AddVMulSV(e, -.5, r, b2Vec2.s_t0), b2Vec2.AddVMulSV(e, .5, r, b2Vec2.s_t1), b); } else { t.DrawSegment(b2Vec2.AddVMulSV(h, -1, c, b2Vec2.s_t0), b2Vec2.AddVMulSV(h, 1, c, b2Vec2.s_t1), n); } t.DrawPoint(h, 5, n); t.DrawPoint(e, 5, r); } } b2PrismaticJoint.InitVelocityConstraints_s_d = new b2Vec2; b2PrismaticJoint.InitVelocityConstraints_s_P = new b2Vec2; b2PrismaticJoint.SolveVelocityConstraints_s_P = new b2Vec2; b2PrismaticJoint.SolveVelocityConstraints_s_df = new b2Vec2; b2PrismaticJoint.SolvePositionConstraints_s_d = new b2Vec2; b2PrismaticJoint.SolvePositionConstraints_s_impulse = new b2Vec3; b2PrismaticJoint.SolvePositionConstraints_s_impulse1 = new b2Vec2; b2PrismaticJoint.SolvePositionConstraints_s_P = new b2Vec2; b2PrismaticJoint.GetJointTranslation_s_pA = new b2Vec2; b2PrismaticJoint.GetJointTranslation_s_pB = new b2Vec2; b2PrismaticJoint.GetJointTranslation_s_d = new b2Vec2; b2PrismaticJoint.GetJointTranslation_s_axis = new b2Vec2; b2PrismaticJoint.Draw_s_pA = new b2Vec2; b2PrismaticJoint.Draw_s_pB = new b2Vec2; b2PrismaticJoint.Draw_s_axis = new b2Vec2; b2PrismaticJoint.Draw_s_c1 = new b2Color(.7, .7, .7); b2PrismaticJoint.Draw_s_c2 = new b2Color(.3, .9, .3); b2PrismaticJoint.Draw_s_c3 = new b2Color(.9, .3, .3); b2PrismaticJoint.Draw_s_c4 = new b2Color(.3, .3, .9); b2PrismaticJoint.Draw_s_c5 = new b2Color(.4, .4, .4); b2PrismaticJoint.Draw_s_lower = new b2Vec2; b2PrismaticJoint.Draw_s_upper = new b2Vec2; b2PrismaticJoint.Draw_s_perp = new b2Vec2;