@awayfl/awayfl-player
Version:
Flash Player emulator for executing SWF files (published for FP versions 6 and up) in javascript
339 lines (304 loc) • 15.3 kB
JavaScript
import { __extends } from "tslib";
import { b2Contact } from '../Contacts';
import { b2Settings } from '../../Common/b2Settings';
import { b2Shape } from '../../Collision/Shapes/b2Shape';
/**
* @private
*/
var b2PolyAndEdgeContact = /** @class */ (function (_super) {
__extends(b2PolyAndEdgeContact, _super);
function b2PolyAndEdgeContact() {
return _super !== null && _super.apply(this, arguments) || this;
}
b2PolyAndEdgeContact.Create = function (allocator) {
return new b2PolyAndEdgeContact();
};
b2PolyAndEdgeContact.Destroy = function (contact, allocator) {
};
b2PolyAndEdgeContact.prototype.Reset = function (fixtureA, fixtureB) {
_super.prototype.Reset.call(this, fixtureA, fixtureB);
b2Settings.b2Assert(fixtureA.GetType() == b2Shape.e_polygonShape);
b2Settings.b2Assert(fixtureB.GetType() == b2Shape.e_edgeShape);
};
//~b2PolyAndEdgeContact() {}
b2PolyAndEdgeContact.prototype.Evaluate = function () {
var bA = this.m_fixtureA.GetBody();
var bB = this.m_fixtureB.GetBody();
this.b2CollidePolyAndEdge(this.m_manifold, this.m_fixtureA.GetShape(), bA.m_xf, this.m_fixtureB.GetShape(), bB.m_xf);
};
b2PolyAndEdgeContact.prototype.b2CollidePolyAndEdge = function (manifold, polygon, xf1, edge, xf2) {
//TODO_BORIS
/*
manifold.pointCount = 0;
var tMat: b2Mat22;
var tVec1: b2Vec2;
var tVec2: b2Vec2;
var tX: Number;
var tY: Number;
var tPoint:b2ManifoldPoint;
var ratio: Number;
//b2Vec2 v1 = b2Mul(xf2, edge->GetVertex1());
tMat = xf2.R;
tVec1 = edge.m_v1;
var v1X: Number = xf2.position.x + (tMat.col1.x * tVec1.x + tMat.col2.x * tVec1.y);
var v1Y: Number = xf2.position.y + (tMat.col1.y * tVec1.x + tMat.col2.y * tVec1.y);
//b2Vec2 v2 = b2Mul(xf2, edge->GetVertex2());
tVec1 = edge.m_v2;
var v2X: Number = xf2.position.x + (tMat.col1.x * tVec1.x + tMat.col2.x * tVec1.y);
var v2Y: Number = xf2.position.y + (tMat.col1.y * tVec1.x + tMat.col2.y * tVec1.y);
//b2Vec2 n = b2Mul(xf2.R, edge->GetNormalVector());
tVec1 = edge.m_normal;
var nX: Number = (tMat.col1.x * tVec1.x + tMat.col2.x * tVec1.y);
var nY: Number = (tMat.col1.y * tVec1.x + tMat.col2.y * tVec1.y);
//b2Vec2 v1Local = b2MulT(xf1, v1);
tMat = xf1.R;
tX = v1X - xf1.position.x;
tY = v1Y - xf1.position.y;
var v1LocalX: Number = (tX * tMat.col1.x + tY * tMat.col1.y );
var v1LocalY: Number = (tX * tMat.col2.x + tY * tMat.col2.y );
//b2Vec2 v2Local = b2MulT(xf1, v2);
tX = v2X - xf1.position.x;
tY = v2Y - xf1.position.y;
var v2LocalX: Number = (tX * tMat.col1.x + tY * tMat.col1.y );
var v2LocalY: Number = (tX * tMat.col2.x + tY * tMat.col2.y );
//b2Vec2 nLocal = b2MulT(xf1.R, n);
var nLocalX: Number = (nX * tMat.col1.x + nY * tMat.col1.y );
var nLocalY: Number = (nX * tMat.col2.x + nY * tMat.col2.y );
var separation1: Number;
var separationIndex1: int = -1; // which normal on the poly found the shallowest depth?
var separationMax1: Number = -Number.MAX_VALUE; // the shallowest depth of edge in poly
var separation2: Number;
var separationIndex2: int = -1; // which normal on the poly found the shallowest depth?
var separationMax2: Number = -Number.MAX_VALUE; // the shallowest depth of edge in poly
var separationMax: Number = -Number.MAX_VALUE; // the shallowest depth of edge in poly
var separationV1: Boolean = false; // is the shallowest depth from edge's v1 or v2 vertex?
var separationIndex: int = -1; // which normal on the poly found the shallowest depth?
var vertexCount: int = polygon.m_vertexCount;
var vertices: Array = polygon.m_vertices;
var normals: Array = polygon.m_normals;
var enterStartIndex: int = -1; // the last poly vertex above the edge
var enterEndIndex: int = -1; // the first poly vertex below the edge
var exitStartIndex: int = -1; // the last poly vertex below the edge
var exitEndIndex: int = -1; // the first poly vertex above the edge
// the "N" in the following variables refers to the edge's normal.
// these are projections of poly vertices along the edge's normal,
// a.k.a. they are the separation of the poly from the edge.
var prevSepN: Number = 0.0;
var nextSepN: Number = 0.0;
var enterSepN: Number = 0.0; // the depth of enterEndIndex under the edge (stored as a separation, so it's negative)
var exitSepN: Number = 0.0; // the depth of exitStartIndex under the edge (stored as a separation, so it's negative)
var deepestSepN: Number = Number.MAX_VALUE; // the depth of the deepest poly vertex under the end (stored as a separation, so it's negative)
// for each poly normal, get the edge's depth into the poly.
// for each poly vertex, get the vertex's depth into the edge.
// use these calculations to define the remaining variables declared above.
tVec1 = vertices[vertexCount-1];
prevSepN = (tVec1.x - v1LocalX) * nLocalX + (tVec1.y - v1LocalY) * nLocalY;
for (var i: int = 0; i < vertexCount; i++)
{
tVec1 = vertices[i];
tVec2 = normals[i];
separation1 = (v1LocalX - tVec1.x) * tVec2.x + (v1LocalY - tVec1.y) * tVec2.y;
separation2 = (v2LocalX - tVec1.x) * tVec2.x + (v2LocalY - tVec1.y) * tVec2.y;
if (separation2 < separation1) {
if (separation2 > separationMax) {
separationMax = separation2;
separationV1 = false;
separationIndex = i;
}
} else {
if (separation1 > separationMax) {
separationMax = separation1;
separationV1 = true;
separationIndex = i;
}
}
if (separation1 > separationMax1) {
separationMax1 = separation1;
separationIndex1 = i;
}
if (separation2 > separationMax2) {
separationMax2 = separation2;
separationIndex2 = i;
}
nextSepN = (tVec1.x - v1LocalX) * nLocalX + (tVec1.y - v1LocalY) * nLocalY;
if (nextSepN >= 0.0 && prevSepN < 0.0) {
exitStartIndex = (i == 0) ? vertexCount-1 : i-1;
exitEndIndex = i;
exitSepN = prevSepN;
} else if (nextSepN < 0.0 && prevSepN >= 0.0) {
enterStartIndex = (i == 0) ? vertexCount-1 : i-1;
enterEndIndex = i;
enterSepN = nextSepN;
}
if (nextSepN < deepestSepN) {
deepestSepN = nextSepN;
}
prevSepN = nextSepN;
}
if (enterStartIndex == -1) {
// poly is entirely below or entirely above edge, return with no contact:
return;
}
if (separationMax > 0.0) {
// poly is laterally disjoint with edge, return with no contact:
return;
}
// if the poly is near a convex corner on the edge
if ((separationV1 && edge.m_cornerConvex1) || (!separationV1 && edge.m_cornerConvex2)) {
// if shallowest depth was from edge into poly,
// use the edge's vertex as the contact point:
if (separationMax > deepestSepN + b2Settings.b2_linearSlop) {
// if -normal angle is closer to adjacent edge than this edge,
// let the adjacent edge handle it and return with no contact:
if (separationV1) {
tMat = xf2.R;
tVec1 = edge.m_cornerDir1;
tX = (tMat.col1.x * tVec1.x + tMat.col2.x * tVec1.y);
tY = (tMat.col1.y * tVec1.x + tMat.col2.y * tVec1.y);
tMat = xf1.R;
v1X = (tMat.col1.x * tX + tMat.col2.x * tY); // note abuse of v1...
v1Y = (tMat.col1.y * tX + tMat.col2.y * tY);
tVec2 = normals[separationIndex1];
if (tVec2.x * v1X + tVec2.y * v1Y >= 0.0) {
return;
}
} else {
tMat = xf2.R;
tVec1 = edge.m_cornerDir2;
tX = (tMat.col1.x * tVec1.x + tMat.col2.x * tVec1.y);
tY = (tMat.col1.y * tVec1.x + tMat.col2.y * tVec1.y);
tMat = xf1.R;
v1X = (tMat.col1.x * tX + tMat.col2.x * tY); // note abuse of v1...
v1Y = (tMat.col1.y * tX + tMat.col2.y * tY);
tVec2 = normals[separationIndex2];
if (tVec2.x * v1X + tVec2.y * v1Y <= 0.0) {
return;
}
}
tPoint = manifold.points[0];
manifold.pointCount = 1;
//manifold->normal = b2Mul(xf1.R, normals[separationIndex]);
tMat = xf1.R;
tVec2 = normals[separationIndex];
manifold.normal.x = (tMat.col1.x * tVec2.x + tMat.col2.x * tVec2.y);
manifold.normal.y = (tMat.col1.y * tVec2.x + tMat.col2.y * tVec2.y);
tPoint.separation = separationMax;
tPoint.id.features.incidentEdge = separationIndex;
tPoint.id.features.incidentVertex = b2Collision.b2_nullFeature;
tPoint.id.features.referenceEdge = 0;
tPoint.id.features.flip = 0;
if (separationV1) {
tPoint.localPoint1.x = v1LocalX;
tPoint.localPoint1.y = v1LocalY;
tPoint.localPoint2.x = edge.m_v1.x;
tPoint.localPoint2.y = edge.m_v1.y;
} else {
tPoint.localPoint1.x = v2LocalX;
tPoint.localPoint1.y = v2LocalY;
tPoint.localPoint2.x = edge.m_v2.x;
tPoint.localPoint2.y = edge.m_v2.y;
}
return;
}
}
// We're going to use the edge's normal now.
manifold.normal.x = -nX;
manifold.normal.y = -nY;
// Check whether we only need one contact point.
if (enterEndIndex == exitStartIndex) {
tPoint = manifold.points[0];
manifold.pointCount = 1;
tPoint.id.features.incidentEdge = enterEndIndex;
tPoint.id.features.incidentVertex = b2Collision.b2_nullFeature;
tPoint.id.features.referenceEdge = 0;
tPoint.id.features.flip = 0;
tVec1 = vertices[enterEndIndex];
tPoint.localPoint1.x = tVec1.x;
tPoint.localPoint1.y = tVec1.y;
tMat = xf1.R;
tX = xf1.position.x + (tMat.col1.x * tVec1.x + tMat.col2.x * tVec1.y) - xf2.position.x;
tY = xf1.position.y + (tMat.col1.y * tVec1.x + tMat.col2.y * tVec1.y) - xf2.position.y;
tMat = xf2.R;
tPoint.localPoint2.x = (tX * tMat.col1.x + tY * tMat.col1.y );
tPoint.localPoint2.y = (tX * tMat.col2.x + tY * tMat.col2.y );
tPoint.separation = enterSepN;
return;
}
manifold.pointCount = 2;
// the edge's direction vector, but in the frame of the polygon:
tX = -nLocalY;
tY = nLocalX;
tVec1 = vertices[enterEndIndex];
var dirProj1: Number = tX * (tVec1.x - v1LocalX) + tY * (tVec1.y - v1LocalY);
var dirProj2: Number;
// The contact resolution is more robust if the two manifold points are
// adjacent to each other on the polygon. So pick the first two poly
// vertices that are under the edge:
exitEndIndex = (enterEndIndex == vertexCount - 1) ? 0 : enterEndIndex + 1;
tVec1 = vertices[exitStartIndex];
if (exitEndIndex != exitStartIndex) {
exitStartIndex = exitEndIndex;
exitSepN = nLocalX * (tVec1.x - v1LocalX) + nLocalY * (tVec1.y - v1LocalY);
}
dirProj2 = tX * (tVec1.x - v1LocalX) + tY * (tVec1.y - v1LocalY);
tPoint = manifold.points[0];
tPoint.id.features.incidentEdge = enterEndIndex;
tPoint.id.features.incidentVertex = b2Collision.b2_nullFeature;
tPoint.id.features.referenceEdge = 0;
tPoint.id.features.flip = 0;
if (dirProj1 > edge.m_length) {
tPoint.localPoint1.x = v2LocalX;
tPoint.localPoint1.y = v2LocalY;
tPoint.localPoint2.x = edge.m_v2.x;
tPoint.localPoint2.y = edge.m_v2.y;
ratio = (edge.m_length - dirProj2) / (dirProj1 - dirProj2);
if (ratio > 100.0 * Number.MIN_VALUE && ratio < 1.0) {
tPoint.separation = exitSepN * (1.0 - ratio) + enterSepN * ratio;
} else {
tPoint.separation = enterSepN;
}
} else {
tVec1 = vertices[enterEndIndex];
tPoint.localPoint1.x = tVec1.x;
tPoint.localPoint1.y = tVec1.y;
tMat = xf1.R;
tX = xf1.position.x + (tMat.col1.x * tVec1.x + tMat.col2.x * tVec1.y) - xf2.position.x;
tY = xf1.position.y + (tMat.col1.y * tVec1.x + tMat.col2.y * tVec1.y) - xf2.position.y;
tMat = xf2.R;
tPoint.localPoint2.x = (tX * tMat.col1.x + tY * tMat.col1.y);
tPoint.localPoint2.y = (tX * tMat.col2.x + tY * tMat.col2.y);
tPoint.separation = enterSepN;
}
tPoint = manifold.points[1];
tPoint.id.features.incidentEdge = exitStartIndex;
tPoint.id.features.incidentVertex = b2Collision.b2_nullFeature;
tPoint.id.features.referenceEdge = 0;
tPoint.id.features.flip = 0;
if (dirProj2 < 0.0) {
tPoint.localPoint1.x = v1LocalX;
tPoint.localPoint1.y = v1LocalY;
tPoint.localPoint2.x = edge.m_v1.x;
tPoint.localPoint2.y = edge.m_v1.y;
ratio = (-dirProj1) / (dirProj2 - dirProj1);
if (ratio > 100.0 * Number.MIN_VALUE && ratio < 1.0) {
tPoint.separation = enterSepN * (1.0 - ratio) + exitSepN * ratio;
} else {
tPoint.separation = exitSepN;
}
} else {
tVec1 = vertices[exitStartIndex];
tPoint.localPoint1.x = tVec1.x;
tPoint.localPoint1.y = tVec1.y;
tMat = xf1.R;
tX = xf1.position.x + (tMat.col1.x * tVec1.x + tMat.col2.x * tVec1.y) - xf2.position.x;
tY = xf1.position.y + (tMat.col1.y * tVec1.x + tMat.col2.y * tVec1.y) - xf2.position.y;
tMat = xf2.R;
tPoint.localPoint2.x = (tX * tMat.col1.x + tY * tMat.col1.y);
tPoint.localPoint2.y = (tX * tMat.col2.x + tY * tMat.col2.y);
tPoint.separation = exitSepN;
}
*/
};
return b2PolyAndEdgeContact;
}(b2Contact));
export { b2PolyAndEdgeContact };