ThreeJS物理引擎
对于物理引擎ThreeJS是没有对其进行封装的,官方中给出案例中直接使用AmmoJS(使用 Emscripten将Bullet物理引擎的C++源码直接转换成JS),渲染引擎和物理引擎结合来实现碰撞检测、自由落体等物理现象,其核心实质就是将物理引擎的计算结果更新到渲染引擎中。
1.初始化物理引擎
var collisionConfiguration = new Ammo.btDefaultCollisionConfiguration();
var dispatcher = new Ammo.btCollisionDispatcher( collisionConfiguration );
var broadphase = new Ammo.btDbvtBroadphase();
var solver = new Ammo.btSequentialImpulseConstraintSolver();
var physicsWorld = new Ammo.btDiscreteDynamicsWorld( dispatcher, broadphase, solver, collisionConfiguration );// 创建物理世界
var physicsWorld.setGravity( new Ammo.btVector3( 0, - 6, 0 ) );// 重力
2.创建碰撞器和刚体
使用过Unity的同仁应该非常了解刚体和碰撞器,碰撞器包含很多种类型诸如立方体、球、胶囊体等等,在AmmoJS中也同样需要创建这些东西,这就是btBoxShape(碰撞器,可以有多种类型诸如btCylinderShape、btConeShape、btSphereShape)和btRigidBody(刚体)。
var sx = 50;
// 创建渲染对象
var threeObject = new THREE.Mesh( new THREE.BoxBufferGeometry( sx, sx, sx, 1, 1, 1 ),m
aterial);
// 创建碰撞器形状
var shape = new Ammo.btBoxShape( new Ammo.btVector3( sx * 0.5, sx * 0.5, sx * 0.5 ) );
shape.setMargin( margin );
var mass = objectSize * 5;// 质量
var localInertia = new Ammo.btVector3( 0, 0, 0 );// 惯性
shape.calculateLocalInertia( mass, localInertia );
var transform = new Ammo.btTransform();// 变换组件,控制碰撞器的旋转和位置
transform.setIdentity();// 单位矩阵
var pos = threeObject.position;
// 根据渲染对象设置碰撞器的位置
transform.setOrigin( new Ammo.btVector3( pos.x, pos.y, pos.z ) );
// 撞见运动状态
var motionState = new Ammo.btDefaultMotionState( transform );
// 刚体创建信息
var rbInfo = new Ammo.btRigidBodyConstructionInfo( mass, motionState, shape, localInertia );
// 创建刚体
var body = new Ammo.btRigidBody( rbInfo );
尤其需要说明的是btDefaultMotionState和btTransform,该刚体的运动状态包含在btDefaultMotionState中,可以从中获取到btTransform对象,里面存放着该碰撞器在物理世界中实时的计算结果;我们需要为某种渲染对象比如立方体创建一个与之匹配的btBoxShape对象,使用btTransform对象控制该shape的变换来紧紧包围渲染对象,切记:当通过渲染对象的旋转平移来设置btTransform时,一定要将渲染对象转换到世界坐标系下再设置btTransform。
3.同步物理引擎计算结果到渲染引擎
为渲染对象创建刚体之后,需要在帧函数中实时更新同步物理引擎计算结果到渲染引擎,即:将每个渲染对象的刚体对象运动状态实时更新到渲染对象上,获取刚体运动状态btDefaultMotionState中的btTransform对象,这个对象就是一个矩阵,里面包含着旋转平移缩放,从矩阵中解压出position、rotation为渲染对象赋值。
physicsWorld.stepSimulation( deltaTime, 10 );
var ms = objPhys.getMotionState();// 获取运动状态
var transformAux1 = new Ammo.btTransform();// 创建变换矩阵
if ( ms ) {
ms.getWorldTransform( transformAux1 );// 从运动状态获取变换矩阵
var p = transformAux1.getOrigin();// 获取位置
var q = transformAux1.getRotation();// 获取旋转
objThree.position.set( p.x(), p.y(), p.z() );// 设置渲染对象位置
objThree.quaternion.set( q.x(), q.y(), q.z(), q.w() );// 设置渲染对象旋转
}
通过不断同步物理引擎数据到渲染引擎,来实现对碰撞结果的实时展现,也可以这样说:物理引擎计算数据驱动渲染引擎显示。另外btRigidBody刚体对象还可以设置是否受重力影响、在某个方向为该刚体施加一个力、设置刚体的速度等等,打个断点看看API基本就会用了。
注:如文章中有任何错误,请一定批评勘正。