UNPKG

the-world-engine

Version:

three.js based, unity like game engine for browser

172 lines (167 loc) 5.77 kB
import { b2_epsilon, b2_linearSlop, b2_maxLinearCorrection, b2MakeNumberArray, b2Maybe } from "../common/b2_settings.js"; import { b2Sq, b2Sqrt, b2Vec2 } from "../common/b2_math.js"; import { b2Joint, b2JointDef, b2JointType } from "./b2_joint.js"; import { b2DistanceJointDef } from "./b2_distance_joint.js"; export class b2AreaJointDef extends b2JointDef { constructor() { super(b2JointType.e_areaJoint); this.bodies = []; this.stiffness = 0; this.damping = 0; } AddBody(t) { this.bodies.push(t); if (this.bodies.length === 1) { this.bodyA = t; } else if (this.bodies.length === 2) { this.bodyB = t; } } } export class b2AreaJoint extends b2Joint { constructor(t) { super(t); this.m_stiffness = 0; this.m_damping = 0; this.m_impulse = 0; this.m_targetArea = 0; this.m_delta = new b2Vec2; this.m_bodies = t.bodies; this.m_stiffness = b2Maybe(t.stiffness, 0); this.m_damping = b2Maybe(t.damping, 0); this.m_targetLengths = b2MakeNumberArray(t.bodies.length); this.m_normals = b2Vec2.MakeArray(t.bodies.length); this.m_joints = []; this.m_deltas = b2Vec2.MakeArray(t.bodies.length); const s = new b2DistanceJointDef; s.stiffness = this.m_stiffness; s.damping = this.m_damping; this.m_targetArea = 0; for (let t = 0; t < this.m_bodies.length; ++t) { const i = this.m_bodies[t]; const o = this.m_bodies[(t + 1) % this.m_bodies.length]; const e = i.GetWorldCenter(); const n = o.GetWorldCenter(); this.m_targetLengths[t] = b2Vec2.DistanceVV(e, n); this.m_targetArea += b2Vec2.CrossVV(e, n); s.Initialize(i, o, e, n); this.m_joints[t] = i.GetWorld().CreateJoint(s); } this.m_targetArea *= .5; } GetAnchorA(t) { return t; } GetAnchorB(t) { return t; } GetReactionForce(t, s) { return s; } GetReactionTorque(t) { return 0; } SetStiffness(t) { this.m_stiffness = t; for (let s = 0; s < this.m_joints.length; ++s) { this.m_joints[s].SetStiffness(t); } } GetStiffness() { return this.m_stiffness; } SetDamping(t) { this.m_damping = t; for (let s = 0; s < this.m_joints.length; ++s) { this.m_joints[s].SetDamping(t); } } GetDamping() { return this.m_damping; } Dump(t) { t("Area joint dumping is not supported.\n"); } InitVelocityConstraints(t) { for (let s = 0; s < this.m_bodies.length; ++s) { const i = this.m_bodies[(s + this.m_bodies.length - 1) % this.m_bodies.length]; const o = this.m_bodies[(s + 1) % this.m_bodies.length]; const e = t.positions[i.m_islandIndex].c; const n = t.positions[o.m_islandIndex].c; const h = this.m_deltas[s]; b2Vec2.SubVV(n, e, h); } if (t.step.warmStarting) { this.m_impulse *= t.step.dtRatio; for (let s = 0; s < this.m_bodies.length; ++s) { const i = this.m_bodies[s]; const o = t.velocities[i.m_islandIndex].v; const e = this.m_deltas[s]; o.x += i.m_invMass * e.y * .5 * this.m_impulse; o.y += i.m_invMass * -e.x * .5 * this.m_impulse; } } else { this.m_impulse = 0; } } SolveVelocityConstraints(t) { let s = 0; let i = 0; for (let o = 0; o < this.m_bodies.length; ++o) { const e = this.m_bodies[o]; const n = t.velocities[e.m_islandIndex].v; const h = this.m_deltas[o]; s += h.LengthSquared() / e.GetMass(); i += b2Vec2.CrossVV(n, h); } const o = -2 * i / s; this.m_impulse += o; for (let s = 0; s < this.m_bodies.length; ++s) { const i = this.m_bodies[s]; const e = t.velocities[i.m_islandIndex].v; const n = this.m_deltas[s]; e.x += i.m_invMass * n.y * .5 * o; e.y += i.m_invMass * -n.x * .5 * o; } } SolvePositionConstraints(t) { let s = 0; let i = 0; for (let o = 0; o < this.m_bodies.length; ++o) { const e = this.m_bodies[o]; const n = this.m_bodies[(o + 1) % this.m_bodies.length]; const h = t.positions[e.m_islandIndex].c; const r = t.positions[n.m_islandIndex].c; const c = b2Vec2.SubVV(r, h, this.m_delta); let b = c.Length(); if (b < b2_epsilon) { b = 1; } this.m_normals[o].x = c.y / b; this.m_normals[o].y = -c.x / b; s += b; i += b2Vec2.CrossVV(h, r); } i *= .5; const o = this.m_targetArea - i; const e = .5 * o / s; let n = true; for (let s = 0; s < this.m_bodies.length; ++s) { const i = this.m_bodies[s]; const o = t.positions[i.m_islandIndex].c; const h = (s + 1) % this.m_bodies.length; const r = b2Vec2.AddVV(this.m_normals[s], this.m_normals[h], this.m_delta); r.SelfMul(e); const c = r.LengthSquared(); if (c > b2Sq(b2_maxLinearCorrection)) { r.SelfMul(b2_maxLinearCorrection / b2Sqrt(c)); } if (c > b2Sq(b2_linearSlop)) { n = false; } o.x += r.x; o.y += r.y; } return n; } }