@awayfl/awayfl-player
Version:
Flash Player emulator for executing SWF files (published for FP versions 6 and up) in javascript
281 lines (252 loc) • 11.2 kB
text/typescript
import { b2SimplexCache } from './b2SimplexCache';
import { b2DistanceProxy } from './b2DistanceProxy';
import { b2Transform, b2Vec2, b2Mat22, b2Math } from '../Common/Math';
import { b2Settings } from '../Common/b2Settings';
export class b2SeparationFunction {
//enum Type
public static readonly e_points: number /** int */ = 0x01;
public static readonly e_faceA: number /** int */ = 0x02;
public static readonly e_faceB: number /** int */ = 0x04;
public Initialize(cache: b2SimplexCache,
proxyA: b2DistanceProxy, transformA: b2Transform,
proxyB: b2DistanceProxy, transformB: b2Transform): void {
this.m_proxyA = proxyA;
this.m_proxyB = proxyB;
const count: number /** int */ = cache.count;
b2Settings.b2Assert(0 < count && count < 3);
let localPointA: b2Vec2;
let localPointA1: b2Vec2;
let localPointA2: b2Vec2;
let localPointB: b2Vec2;
let localPointB1: b2Vec2;
let localPointB2: b2Vec2;
let pointAX: number;
let pointAY: number;
let pointBX: number;
let pointBY: number;
let normalX: number;
let normalY: number;
let tMat: b2Mat22;
let tVec: b2Vec2;
let s: number;
let sgn: number;
if (count == 1) {
this.m_type = b2SeparationFunction.e_points;
localPointA = this.m_proxyA.GetVertex(cache.indexA[0]);
localPointB = this.m_proxyB.GetVertex(cache.indexB[0]);
//pointA = b2Math.b2MulX(transformA, localPointA);
tVec = localPointA;
tMat = transformA.R;
pointAX = transformA.position.x + (tMat.col1.x * tVec.x + tMat.col2.x * tVec.y);
pointAY = transformA.position.y + (tMat.col1.y * tVec.x + tMat.col2.y * tVec.y);
//pointB = b2Math.b2MulX(transformB, localPointB);
tVec = localPointB;
tMat = transformB.R;
pointBX = transformB.position.x + (tMat.col1.x * tVec.x + tMat.col2.x * tVec.y);
pointBY = transformB.position.y + (tMat.col1.y * tVec.x + tMat.col2.y * tVec.y);
//m_axis = b2Math.SubtractVV(pointB, pointA);
this.m_axis.x = pointBX - pointAX;
this.m_axis.y = pointBY - pointAY;
this.m_axis.Normalize();
} else if (cache.indexB[0] == cache.indexB[1]) {
// Two points on A and one on B
this.m_type = b2SeparationFunction.e_faceA;
localPointA1 = this.m_proxyA.GetVertex(cache.indexA[0]);
localPointA2 = this.m_proxyA.GetVertex(cache.indexA[1]);
localPointB = this.m_proxyB.GetVertex(cache.indexB[0]);
this.m_localPoint.x = 0.5 * (localPointA1.x + localPointA2.x);
this.m_localPoint.y = 0.5 * (localPointA1.y + localPointA2.y);
this.m_axis = b2Math.CrossVF(b2Math.SubtractVV(localPointA2, localPointA1), 1.0);
this.m_axis.Normalize();
//normal = b2Math.b2MulMV(transformA.R, this.m_axis);
tVec = this.m_axis;
tMat = transformA.R;
normalX = tMat.col1.x * tVec.x + tMat.col2.x * tVec.y;
normalY = tMat.col1.y * tVec.x + tMat.col2.y * tVec.y;
//pointA = b2Math.b2MulX(transformA, this.m_localPoint);
tVec = this.m_localPoint;
tMat = transformA.R;
pointAX = transformA.position.x + (tMat.col1.x * tVec.x + tMat.col2.x * tVec.y);
pointAY = transformA.position.y + (tMat.col1.y * tVec.x + tMat.col2.y * tVec.y);
//pointB = b2Math.b2MulX(transformB, localPointB);
tVec = localPointB;
tMat = transformB.R;
pointBX = transformB.position.x + (tMat.col1.x * tVec.x + tMat.col2.x * tVec.y);
pointBY = transformB.position.y + (tMat.col1.y * tVec.x + tMat.col2.y * tVec.y);
//float32 s = b2Dot(pointB - pointA, normal);
s = (pointBX - pointAX) * normalX + (pointBY - pointAY) * normalY;
if (s < 0.0) {
this.m_axis.NegativeSelf();
}
} else if (cache.indexA[0] == cache.indexA[0]) {
// Two points on B and one on A
this.m_type = b2SeparationFunction.e_faceB;
localPointB1 = this.m_proxyB.GetVertex(cache.indexB[0]);
localPointB2 = this.m_proxyB.GetVertex(cache.indexB[1]);
localPointA = this.m_proxyA.GetVertex(cache.indexA[0]);
this.m_localPoint.x = 0.5 * (localPointB1.x + localPointB2.x);
this.m_localPoint.y = 0.5 * (localPointB1.y + localPointB2.y);
this.m_axis = b2Math.CrossVF(b2Math.SubtractVV(localPointB2, localPointB1), 1.0);
this.m_axis.Normalize();
//normal = b2Math.b2MulMV(transformB.R, this.m_axis);
tVec = this.m_axis;
tMat = transformB.R;
normalX = tMat.col1.x * tVec.x + tMat.col2.x * tVec.y;
normalY = tMat.col1.y * tVec.x + tMat.col2.y * tVec.y;
//pointB = b2Math.b2MulX(transformB, this.m_localPoint);
tVec = this.m_localPoint;
tMat = transformB.R;
pointBX = transformB.position.x + (tMat.col1.x * tVec.x + tMat.col2.x * tVec.y);
pointBY = transformB.position.y + (tMat.col1.y * tVec.x + tMat.col2.y * tVec.y);
//pointA = b2Math.b2MulX(transformA, localPointA);
tVec = localPointA;
tMat = transformA.R;
pointAX = transformA.position.x + (tMat.col1.x * tVec.x + tMat.col2.x * tVec.y);
pointAY = transformA.position.y + (tMat.col1.y * tVec.x + tMat.col2.y * tVec.y);
//float32 s = b2Dot(pointA - pointB, normal);
s = (pointAX - pointBX) * normalX + (pointAY - pointBY) * normalY;
if (s < 0.0) {
this.m_axis.NegativeSelf();
}
} else {
// Two points on B and two points on A.
// The faces are parallel.
localPointA1 = this.m_proxyA.GetVertex(cache.indexA[0]);
localPointA2 = this.m_proxyA.GetVertex(cache.indexA[1]);
localPointB1 = this.m_proxyB.GetVertex(cache.indexB[0]);
localPointB2 = this.m_proxyB.GetVertex(cache.indexB[1]);
const pA: b2Vec2 = b2Math.MulX(transformA, localPointA);
const dA: b2Vec2 = b2Math.MulMV(transformA.R, b2Math.SubtractVV(localPointA2, localPointA1));
const pB: b2Vec2 = b2Math.MulX(transformB, localPointB);
const dB: b2Vec2 = b2Math.MulMV(transformB.R, b2Math.SubtractVV(localPointB2, localPointB1));
const a: number = dA.x * dA.x + dA.y * dA.y;
const e: number = dB.x * dB.x + dB.y * dB.y;
const r: b2Vec2 = b2Math.SubtractVV(dB, dA);
const c: number = dA.x * r.x + dA.y * r.y;
const f: number = dB.x * r.x + dB.y * r.y;
const b: number = dA.x * dB.x + dA.y * dB.y;
const denom: number = a * e - b * b;
s = 0.0;
if (denom != 0.0) {
s = b2Math.Clamp((b * f - c * e) / denom, 0.0, 1.0);
}
let t: number = (b * s + f) / e;
if (t < 0.0) {
t = 0.0;
s = b2Math.Clamp((b - c) / a, 0.0, 1.0);
}
//b2Vec2 localPointA = localPointA1 + s * (localPointA2 - localPointA1);
localPointA = new b2Vec2();
localPointA.x = localPointA1.x + s * (localPointA2.x - localPointA1.x);
localPointA.y = localPointA1.y + s * (localPointA2.y - localPointA1.y);
//b2Vec2 localPointB = localPointB1 + s * (localPointB2 - localPointB1);
localPointB = new b2Vec2();
localPointB.x = localPointB1.x + s * (localPointB2.x - localPointB1.x);
localPointB.y = localPointB1.y + s * (localPointB2.y - localPointB1.y);
if (s == 0.0 || s == 1.0) {
this.m_type = b2SeparationFunction.e_faceB;
this.m_axis = b2Math.CrossVF(b2Math.SubtractVV(localPointB2, localPointB1), 1.0);
this.m_axis.Normalize();
this.m_localPoint = localPointB;
//normal = b2Math.b2MulMV(transformB.R, this.m_axis);
tVec = this.m_axis;
tMat = transformB.R;
normalX = tMat.col1.x * tVec.x + tMat.col2.x * tVec.y;
normalY = tMat.col1.y * tVec.x + tMat.col2.y * tVec.y;
//pointB = b2Math.b2MulX(transformB, this.m_localPoint);
tVec = this.m_localPoint;
tMat = transformB.R;
pointBX = transformB.position.x + (tMat.col1.x * tVec.x + tMat.col2.x * tVec.y);
pointBY = transformB.position.y + (tMat.col1.y * tVec.x + tMat.col2.y * tVec.y);
//pointA = b2Math.b2MulX(transformA, localPointA);
tVec = localPointA;
tMat = transformA.R;
pointAX = transformA.position.x + (tMat.col1.x * tVec.x + tMat.col2.x * tVec.y);
pointAY = transformA.position.y + (tMat.col1.y * tVec.x + tMat.col2.y * tVec.y);
//float32 sgn = b2Dot(pointA - pointB, normal);
sgn = (pointAX - pointBX) * normalX + (pointAY - pointBY) * normalY;
if (s < 0.0) {
this.m_axis.NegativeSelf();
}
} else {
this.m_type = b2SeparationFunction.e_faceA;
this.m_axis = b2Math.CrossVF(b2Math.SubtractVV(localPointA2, localPointA1), 1.0);
this.m_localPoint = localPointA;
//normal = b2Math.b2MulMV(transformA.R, this.m_axis);
tVec = this.m_axis;
tMat = transformA.R;
normalX = tMat.col1.x * tVec.x + tMat.col2.x * tVec.y;
normalY = tMat.col1.y * tVec.x + tMat.col2.y * tVec.y;
//pointA = b2Math.b2MulX(transformA, this.m_localPoint);
tVec = this.m_localPoint;
tMat = transformA.R;
pointAX = transformA.position.x + (tMat.col1.x * tVec.x + tMat.col2.x * tVec.y);
pointAY = transformA.position.y + (tMat.col1.y * tVec.x + tMat.col2.y * tVec.y);
//pointB = b2Math.b2MulX(transformB, localPointB);
tVec = localPointB;
tMat = transformB.R;
pointBX = transformB.position.x + (tMat.col1.x * tVec.x + tMat.col2.x * tVec.y);
pointBY = transformB.position.y + (tMat.col1.y * tVec.x + tMat.col2.y * tVec.y);
//float32 sgn = b2Dot(pointB - pointA, normal);
sgn = (pointBX - pointAX) * normalX + (pointBY - pointAY) * normalY;
if (s < 0.0) {
this.m_axis.NegativeSelf();
}
}
}
}
public Evaluate(transformA: b2Transform, transformB: b2Transform): number {
let axisA: b2Vec2;
let axisB: b2Vec2;
let localPointA: b2Vec2;
let localPointB: b2Vec2;
let pointA: b2Vec2;
let pointB: b2Vec2;
let seperation: number;
let normal: b2Vec2;
switch (this.m_type) {
case b2SeparationFunction.e_points:
{
axisA = b2Math.MulTMV(transformA.R, this.m_axis);
axisB = b2Math.MulTMV(transformB.R, this.m_axis.GetNegative());
localPointA = this.m_proxyA.GetSupportVertex(axisA);
localPointB = this.m_proxyB.GetSupportVertex(axisB);
pointA = b2Math.MulX(transformA, localPointA);
pointB = b2Math.MulX(transformB, localPointB);
//float32 separation = b2Dot(pointB - pointA, this.m_axis);
seperation = (pointB.x - pointA.x) * this.m_axis.x + (pointB.y - pointA.y) * this.m_axis.y;
return seperation;
}
case b2SeparationFunction.e_faceA:
{
normal = b2Math.MulMV(transformA.R, this.m_axis);
pointA = b2Math.MulX(transformA, this.m_localPoint);
axisB = b2Math.MulTMV(transformB.R, normal.GetNegative());
localPointB = this.m_proxyB.GetSupportVertex(axisB);
pointB = b2Math.MulX(transformB, localPointB);
//float32 separation = b2Dot(pointB - pointA, normal);
seperation = (pointB.x - pointA.x) * normal.x + (pointB.y - pointA.y) * normal.y;
return seperation;
}
case b2SeparationFunction.e_faceB:
{
normal = b2Math.MulMV(transformB.R, this.m_axis);
pointB = b2Math.MulX(transformB, this.m_localPoint);
axisA = b2Math.MulTMV(transformA.R, normal.GetNegative());
localPointA = this.m_proxyA.GetSupportVertex(axisA);
pointA = b2Math.MulX(transformA, localPointA);
//float32 separation = b2Dot(pointA - pointB, normal);
seperation = (pointA.x - pointB.x) * normal.x + (pointA.y - pointB.y) * normal.y;
return seperation;
}
default:
b2Settings.b2Assert(false);
return 0.0;
}
}
public m_proxyA: b2DistanceProxy;
public m_proxyB: b2DistanceProxy;
public m_type: number /** int */;
public m_localPoint: b2Vec2 = new b2Vec2();
public m_axis: b2Vec2 = new b2Vec2();
}