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