ThreeJS—物理引擎

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基本就會用了。

注:如文章中有任何錯誤,請一定批評勘正。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章