CocosCreator 物理引擎中的碰撞平面的法线

Posted kingbook

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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版的Box2DCollision2WorldManifold.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();

两个版本的反转法线的代码位置不一致,导致以上问题


以上是关于CocosCreator 物理引擎中的碰撞平面的法线的主要内容,如果未能解决你的问题,请参考以下文章

CocosCreator手记02——Examples中文注释目录

物理引擎开发

cocosCreator中的碰撞检测和触摸事件

Egret中使用P2物理引擎

Unity的物理引擎是如何实现碰撞的呢?

cocos creator基础-(二十)物理引擎碰撞检测