zoukankan      html  css  js  c++  java
  • 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();
    

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

  • 相关阅读:
    Vue使用watch监听一个对象中的属性
    小程序 显示对话框 确定-取消
    【微信小程序】 wx:if 与 hidden(隐藏元素)区别
    vue项目移植tinymce踩坑
    XMLHttpRequest.withCredentials 解决跨域请求头无Cookie的问题
    appJSON["window"]["navigationBarTextStyle"] 字段需为 black 或 white
    Java写 插入 选择 冒泡 快排
    编码表理解
    Centos yum安装java jdk1.8
    Java Hibernate和.Net EntityFramework 如何在提交事务之前 就拿到需要新增实体的Id
  • 原文地址:https://www.cnblogs.com/kingBook/p/13344897.html
Copyright © 2011-2022 走看看