jiglibflash and AwayPhysics for car

来源:互联网 发布:java bufferreader 编辑:程序博客网 时间:2024/06/02 07:43
1、车体不能正确的接确到地面的问题:
       在away3d场景中,创建JCar的底盘刚体要正确包围整个模型,模型的轴点对应于刚体的中心点,中心点总是位于刚体中心,away3D和jiglib的坐标系统是一样的,只有away3d对象的坐标原点位于几何体的中心,jiglib的刚体才能正确包围这个对象,所以把模型轴点移动到模型的中心。也可以减小车体(chassis)的高度,同时把四个轮子都向下移动,使轮子接触到地面。

2、jiglib中设置轮子的参数
public function setupWheel(_name:String, pos:Vector3D,
            wheelSideFriction:Number = 2, wheelFwdFriction:Number = 2,
            wheelTravel:Number = 3, wheelRadius:Number = 10,
            wheelRestingFrac:Number = 0.5, wheelDampingFrac:Number = 0.5,
            wheelNumRays:int = 1):void
carBody.setupWheel("WheelFL", new Vector3D(-48, -20, 68), 1.3, 1.3, 6, 20, 0.5, 0.5, 2);
     每一个参数是车轮名字,第二个参数是轮子相对车子主体的位置,第三和第四个参数是轮子的侧滑,前滑摩擦系数,第五个是轮轴悬挂上下移动的距离,第六个是轮子半径,第七个是弹性系数,第八个是轮轴阻尼系数,一般后面几个可以不管,设为默认值就行了,关键是车子主体(chassis)的 sideLengths要和各个轮子的位置和半径相适应,否则主体可能会和地面接触,所以不能向前移动。wheeltravel一般设为2到5就行了,wheelnumrays影响轮子的碰撞精度,一般是1或2。可以增加setupWheel的第五个参数实现轮子的弹簧效果,不过这个设的太大容易使车体着地,所以需要把所有轮子位置向下移动一定距离。
public function setCar(maxSteerAngle:Number = 45, steerRate:Number = 1, driveTorque:Number = 500):void
     要使汽车更容易转弯,你可以增加setcar的第三个参数,就是增加驾驶扭矩,不过太灵活也不好。

3、jiglib和bullet中的单位问题
  米和像素当然不是一个概念,bullet是严格按照牛顿定律来模拟真实世界的,使用的基本单位都是真实的物理单位,在与3D模型绑定的时候需要设置物理世界的scale,这个决定了一米等于多少像素。但是jiglib并不像bullet这么严格,为了使用方便并且直观,所以直接使用了像素为基本单位,当然像素是一个2D的概念,用来表示3D世界并不是很贴切,可以理解为3D模型实际的尺寸单位。作者只是为方便当成像素。bullet的单位是米,jiglib用的单位是像素,所以jiglib必须按照实际像素大小设置尺寸,场景都要按相应比例放大。
     AwayPhysics(as3通过Alchemy调用bullet的c++库)已经默认设置scaling为100,也就是每单位对应bullet的0.01米,所以设置的刚体尺寸不宜过小,物理引擎的坐标系是与使用的图像引擎相关的,原始的bullet使用opengl渲染图形所以是右手坐标,在AwayPhysics中用fp11,自然就是左手坐标了。

4、怎么让车不容易翻
  可以把模型的轴点向下移到车体的中心,而不是整个模型的中心,同时减小chassis包围盒的高度,这样chassis只包围底下的车体,而不是整个模型,chassis的高度太高的话就容易翻。

5、射线检测
   bullet的射线检测还没有添加到awayphysics里,目前还用不了,jiglib中有。

6、多car的同步问题
  物理的网络同步确实比较复杂,如果实时传输transfrom信息,要注意server和client端是不同的坐标系问题,还有就是只传输各个客户端玩家的输入信息,依靠严格的时间频率控制物体移动,保证不同客户端物理模拟完全一致。因网络延迟问题,不管哪一种都不能保证每个客户端有完全一样的结果,所以需要每隔一定的时间传输一次位置信息修正每个玩家位置。

7、避免高速穿透
 awayphysics中,如果车的速度很快,比如60m/s或更大时,车会穿墙而过,如从很高的空中落下来也是这样,重力加速度使速度大到一定时,车会穿过地面,从比较小的高度落下来,车着地时,会有一点穿透,如有半个轮子穿透地面,弹几下慢慢的起来。
可以使用CCD(Continuous Collision Detection)检测避免高速穿透,在AwayPhysics中可以看basicTest那个例子,主要设两个参数,比如:
car.getRigidBody().ccdSweptSphereRadius = 0.5;
car.getRigidBody().ccdMotionThreshold = 1;
轮子穿透可以试试增加suspensionStiffness和suspensionRestLength1这两个参数的值。

8、公式
   算线速度的公式是 a=f/m; Vt=V0+a*t;  
  代码 _currState.linVelocity = _currState.linVelocity.add(JNumber3D.getScaleVector(_force, _invMass * dt));
invMass是mass的倒数,就是1/mass,invOrientation是方向矩阵的逆矩阵。对于旋转矩阵也是它的转置距阵。
旋转矩阵是正交矩阵,正交矩阵的特性是它的逆矩阵等于转置矩阵。
invOrientation = JMatrix3D.getTransposeMatrix(_currState.orientation);

角速度的公式:Wt=W0+a*t; a等于力矩乘转动惯量的逆矩阵,可以理解为角加速度。
分拆开来就可以写为下面三句:
var rac:Vector3D = JNumber3D.getScaleVector(_torque, dt);
 rac = _worldInvInertia.transformVector(rac);
 _currState.rotVelocity = _currState.rotVelocity.add(rac);








9、jiglib碰撞处理
  都在PhysicsSystem里,主要是这两个方法:processCollisionNormal,processCollisionAccumulated,根据不同的碰撞处理类型执行相应方法。

10、点到面的距离
参考JPlan中的算法:
public function pointPlaneDistance(pt:Vector3D):Number
{
    return _normal.dotProduct(pt) - _distance;
}

11、jiglig中的刚体RigidBody
   Jterrain,通过高度数据生成RigidBody
   JTriangleMesh 通过mesh的vertex和index生成RigidBody,用于赛道的物理