UNPKG

@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
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(); }