CocosCreator 物理引擎中的碰撞平面的法线
CocosCreator使用的是box2d.js物理引擎,碰撞平面法线方向必须取反
private onBeginContact(contact:cc.PhysicsContact,selfCollider:cc.PhysicsCollider,otherCollider:cc.PhysicsCollider):void{
let normal=contact.getWorldManifold().normal;
normal.mulSelf(-1);//CocosCreator中,normal的方向是由selfCollider指向otherCollider,所以正确的碰撞平台法线是相反的方向
cc.log(normal);
}
注意:在AS3版的Box2d中,只有当前刚体和contact的刚体A不同时,法线的方向才需要取反。
此问题应该是AS3版Box2d的Bug,查看AS3版的Box2D\Collision\b2WorldManifold.as的Initialize方法的以下代码:
case b2Manifold.e_faceB:{
//normal = b2Math.b2MulMV(xfB.R, manifold.m_localPlaneNormal);
tMat = xfB.R;
tVec = manifold.m_localPlaneNormal;
normalX = tMat.col1.x * tVec.x + tMat.col2.x * tVec.y;
normalY = tMat.col1.y * tVec.x + tMat.col2.y * tVec.y;
//planePoint = b2Math.b2MulX(xfB, manifold.m_localPoint);
tMat = xfB.R;
tVec = manifold.m_localPoint;
planePointX = xfB.position.x + tMat.col1.x * tVec.x + tMat.col2.x * tVec.y;
planePointY = xfB.position.y + tMat.col1.y * tVec.x + tMat.col2.y * tVec.y;
//此代码应放置到for循环之后
// Ensure normal points from A to B
m_normal.x = -normalX;
m_normal.y = -normalY;
//
for (i = 0; i < manifold.m_pointCount; i++)
{
//clipPoint = b2Math.b2MulX(xfA, manifold.m_points[i].m_localPoint);
tMat = xfA.R;
tVec = manifold.m_points[i].m_localPoint;
clipPointX = xfA.position.x + tMat.col1.x * tVec.x + tMat.col2.x * tVec.y;
clipPointY = xfA.position.y + tMat.col1.y * tVec.x + tMat.col2.y * tVec.y;
//b2Vec2 cA = clipPoint - radiusA * normal;
//b2Vec2 cB = clipPoint + (radiusB - b2Dot(clipPoint - planePoint, normal)) * normal;
//m_points[i] = 0.5f * (cA + cB);
m_points[i].x = clipPointX + 0.5 * (radiusB - (clipPointX - planePointX) * normalX - (clipPointY - planePointY) * normalY - radiusA ) * normalX;
m_points[i].y = clipPointY + 0.5 * (radiusB - (clipPointX - planePointX) * normalX - (clipPointY - planePointY) * normalY - radiusA ) * normalY;
}
}
JS版的Box2d,b2WorldManifold的Initialize方法:
case exports.b2ManifoldType.e_faceB: {
b2Rot.MulRV(xfB.q, manifold.localNormal, this.normal);
var planePoint = b2Transform.MulXV(xfB, manifold.localPoint, b2WorldManifold.Initialize_s_planePoint);
for (var i = 0; i < manifold.pointCount; ++i) {
var clipPoint = b2Transform.MulXV(xfA, manifold.points[i].localPoint, b2WorldManifold.Initialize_s_clipPoint);
var s = radiusB - b2Vec2.DotVV(b2Vec2.SubVV(clipPoint, planePoint, b2Vec2.s_t0), this.normal);
var cB = b2Vec2.AddVMulSV(clipPoint, s, this.normal, b2WorldManifold.Initialize_s_cB);
var cA = b2Vec2.SubVMulSV(clipPoint, radiusA, this.normal, b2WorldManifold.Initialize_s_cA);
b2Vec2.MidVV(cA, cB, this.points[i]);
this.separations[i] = b2Vec2.DotVV(b2Vec2.SubVV(cA, cB, b2Vec2.s_t0), this.normal); // b2Dot(cA - cB, normal);
}
// Ensure normal points from A to B.
this.normal.SelfNeg();
break;
}
AS3版:
// Ensure normal points from A to B
m_normal.x = -normalX;
m_normal.y = -normalY;
JS版:
// Ensure normal points from A to B.
this.normal.SelfNeg();
两个版本的反转法线的代码位置不一致,导致以上问题