概念性的描述
概述
- Ammo.js 使用Emscripten將 Bullet物理引擎 直接移植到JavaScript爱态。源代碼被直接翻譯成JavaScript秕岛,未進行人工重寫膘婶,因此功能與原始項目相同丸氛。
- Bullet Physics是一個開源的物理模擬引擎,世界三大物理引擎之一(另外兩種是Havok和PhysX)井辜。
ammo引擎相關示例資源查看
官方網址
基于ammon.js的演示應用程序基類和3D物理演示绎谦。支持多種場景圖,包括Three.js和SceneJS
官網示例地址 -
http://schteppe.github.io/ammo.js-demos/
物理引擎在github上的地址 -
https://github.com/kripken/ammo.js/#readme
注:
- github地址下載的demo比ammo官網demo多一些
- 這是來自Bullet的HelloWorld.cpp粥脚,翻譯成JavaScript窃肠。該目錄中的其他示例可能也很有用。特別請參閱中的WebGL
示例演示目錄 -ammo.js-main/examples
※ 下落的盒子 - ammo.js-main/examples/webgl_demo/ammo.wasm.html
※ 彩色的墻 - ammo.js-main/examples/webgl_demo_gimpact_chain/index.html
※ 柔軟的布料 - ammo.js-main/examples/webgl_demo_softbody_cloth/index.html
※ 繩子 - ammo.js-main/examples/webgl_demo_softbody_rope/index.html
※ 網格體積 - ammo.js-main/examples/webgl_demo_softbody_volume2/index.html
- (渲染很卡)
※ 建立地形 - ammo.js-main/examples/webgl_demo_terrain/index.html
※ 射線測試 - ammo.js-main/examples/webgl_demo_test_ray/index.html
※ 小車移動 - ammo.js-main/examples/webgl_demo_vehicle/index.html
- 使用ammo引擎開發(fā)示例帖子地址 -
https://juejin.cn/post/6985033373857579045
- (推薦!)
-
一個3d球體在平臺移動刷允,涉及物理控制冤留、移動端搖桿適配、場景內物品树灶、交互鏡頭使用....
項目截圖
其他物理引擎
3D引擎
- cannon引擎官網地址 -
https://pmndrs.github.io/cannon-es/
2D引擎
- matter -
https://brm.io/matter-js/docs/
- p2 -
https://github.com/schteppe/p2.js#demos
物理引擎基本綁定流程
創(chuàng)建一個帶物理屬性的模型的流程
一些關鍵詞說明
- mass -- 質量
- inertia -- 慣性
...
模型的物理形狀
- 學習的文檔來源:
http://www.dwenzhao.cn/profession/netbuild/ammoegine.html
物理模型的形狀構成
- 球體形狀
- 使用范圍: 任何球體使用的例子
- 創(chuàng)建參數(shù): 球體碰撞形狀構造器纤怒,radius為球半徑
Ammo.btSphereShape( ballRadius )
- 方法:
setMargin(margin) -- 設置碰撞形狀邊緣數(shù)
getMargin() -- 獲取碰撞形狀邊緣數(shù)
getRadius( ) -- 獲取球的半徑
- 長方體形狀
- 使用范圍: 用于盒子、箱子等規(guī)則物體
- 創(chuàng)建參數(shù): 構造器破托,boxHalfExtents表示立方體盒子的半區(qū)域
Ammo.btBoxShape(btVector3 boxHalfExtents)
- 方法:
setMargin(margin) -- 設置碰撞形狀邊緣數(shù)
getMargin() -- 獲取碰撞形狀邊緣數(shù)
- 圓柱形狀
- 使用范圍: 桿肪跋、金幣、石柱等都可以采用此類土砂,但碰撞計算量較大,不如膠囊
- 創(chuàng)建參數(shù): 圓柱對象構造器谜洽,halfExtents為圓柱的半區(qū)域萝映,三維分量,第1和3維表示圓柱的長短半徑阐虚,第2維是長度
Ammo.btCylinderShape(btVector3 halfExtents)
- 方法:
getRadius( ) -- 獲取圓柱的半徑
- 膠囊形狀
- 使用范圍: 碰撞計算量比圓柱小序臂,旗桿、鉛筆
- 創(chuàng)建參數(shù): 膠囊碰撞形狀對象構造器实束,參數(shù)radius為兩端球面的半徑奥秆,height為中間圓柱的長度
Ammo.btCapsuleShape(float radius, float height)
- 方法:
getRadius( ) -- 獲取膠囊截面的半徑
getHalfHeight( ) -- 獲取中間圓柱部分長度值的一半
- 圓錐形狀
- 使用范圍: 碰撞計算量比圓柱小,旗桿咸灿、鉛筆
- 創(chuàng)建參數(shù): 圓錐碰撞形狀對象構造器,參數(shù)radius為圓錐的半徑,height為圓錐的高度
Ammo.btConeShape(float radius, float height)
- 方法:
getRadius( ) -- 獲取膠囊截面的半徑
- 復合形狀
- 復合形狀構造器
btCompoundShape()
- 方法:
//-- 向組合形狀中添加子形狀嚎花,localTransform為子形狀的變換龟再,shape為添加的子形狀
addChildShape ( btTransform localTransform, btCollisionShape shape)
//-- 從組合形狀中刪除指定的子形狀囊榜, childShapeindex為子形狀索引
removeChildShape( childShapeindex)
//-- 獲取當前組合形狀中子形狀的數(shù)量
getNumChildShapes()
//-- 獲取組合形狀中指定索引編號的子形狀,index為子形狀索引
getChildShape(index)
模型的物理屬性配置以及受力方法
btRigidBody - 剛體 - 運動的方法
- 為剛體設置摩擦力
btRigidBody實例.setFriction(數(shù)字)
- 獲取剛體的加速度
btRigidBody實例.getAngularVelocity()
- 剛體設置線速度 - 使物體朝著某個坐標線性運動過去
- 先坐標變化亥宿,再使用setLinearVelocity卸勺,移動物體過去
//-- 三維向量
const pos = new THREE.Vector3(1,1,1);
//-- 設置(x,y,z)、三維中每個值乘以14
pos.multiplyScalar( 14 );
btRigidBody實例.setLinearVelocity( new Ammo.btVector3( pos ) );
- 獲取線速度
btRigidBody實例.getLinearVelocity()
線性速度實際使用過程中
- 為剛體添加摩擦力
- 通過Vector3上的copy方法烫扼,獲取上一時刻的坐標信息曙求,賦值給Vector3的實例pos
- 通過Vector3上的multiplyScalar方法,將pos坐標信息(x,y,z)乘以某個數(shù)值
- 通過給 剛體實例.setLinearVelocity( new Ammo.btVector3( pos.x, pos.y, pos.z ) ) 給剛體添加速度
- 通過getLinearVelocity查看實例的線性速度返回字符串格式為 -
{"hy":8466696}
- 通過getAngularVelocity獲取了加速度映企,發(fā)現(xiàn)值略比getLinearVelocity大一點 -
{"hy":8466712}
- 添加一個外力 - 參數(shù)(應用的力, 施加力的位置 )
- 參照cannon物理引擎悟狱,從空間中的一個特殊點對剛體施加力(不一定在剛體的表面)
- 如: 自然中的風
btRigidBody實例.applyForce(btVector3格式作用力, btVector3格式坐標點)
- 添加一個剛體局部坐標系中的力
btRigidBody實例.applyCentralLocalForce(btVector3格式坐標點)
物理世界啟動與渲染配置
物理世界啟動
- 物理世界的類型
-
為了模擬不同材質的物體,物理世界也對應出了不同的分支
物理世界的種類構成
- 物理世界的配置
- 創(chuàng)建物理世界卑吭,需要傳入不同參數(shù)芽淡,定制化其效果
- 剛體世界 示例代碼:
//完全碰撞檢測算法
let collisionConfiguration = new Ammo.btDefaultCollisionConfiguration();
// 重疊對/碰撞的調度計算
let dispatcher = new Ammo.btCollisionDispatcher(collisionConfiguration);
// 所有可能碰撞對的寬相位碰撞檢測列表
let broadphase = new Ammo.btDbvtBroadphase();
// 使物體正確地交互,考慮重力豆赏、力挣菲、碰撞等
let solver = new Ammo.btSequentialImpulseConstraintSolver();
physicsWorld = new Ammo.btDiscreteDynamicsWorld( dispatcher, broadphase, solver, collisionConfiguration);
-
物理世界中 碰撞參數(shù)與物理世界之間的對應關系
碰撞算法與物理世界
| 碰撞算法 | 物理世界 |
| btDefaultCollisionConfiguration | btDiscreteDynamicsWorld |
| btSoftBodyRigidBodyCollisionConfiguration | btSoftRigidDynamicsWorld | 既支持剛體也支持軟體的物理世界配置
基本代碼:
//-- 物理世界變量
const gravityConstant = - 9.8;
//-- 啟動物理世界
initPhysics();
function initPhysics() {
//-- 設置物理引擎的碰撞類型 - 軟體與剛體碰撞
const collisionConfiguration = new Ammo.btSoftBodyRigidBodyCollisionConfiguration();
//-- dispatcher為碰撞檢測算法分配器引用
const dispatcher = new Ammo.btCollisionDispatcher( collisionConfiguration );
//-- 為碰撞粗測算法接口
const broadphase = new Ammo.btDbvtBroadphase();
//-- 配置約束解決器 - (序列脈沖約束解決器)
//-- 使物體正確地交互,考慮重力掷邦、力白胀、碰撞等
const solver = new Ammo.btSequentialImpulseConstraintSolver();
//-- 配置約束解決器 - (軟體約束解決器)
const softBodySolver = new Ammo.btDefaultSoftBodySolver();
//-- 創(chuàng)建一個支持軟體、剛體的物理世界
physicsWorld = new Ammo.btSoftRigidDynamicsWorld( dispatcher, broadphase, solver, collisionConfiguration, softBodySolver );
//-- 設置物理世界的重力
physicsWorld.setGravity( new Ammo.btVector3( 0, gravityConstant, 0 ) );
physicsWorld.getWorldInfo().set_m_gravity( new Ammo.btVector3( 0, gravityConstant, 0 ) );
}
物理世界的渲染
- 說明:
模型配置了物理碰撞屬性抚岗,在物理世界里就擁有了運動軌跡或杠,可以實時查看位置
*知識點:
獲取運動狀態(tài)信息:
通過btTransform類:變換類
該類由位置和方向組合而成,用來表示剛體的變換宣蔚,如平移向抢、旋轉等通過剛體的getMotionState獲取
剛體形狀
getMotionState()
- 獲取剛體的形狀,返回值為獲取的形狀指針通過
剛體形狀
的getWorldTransform( btTransform實例transformAux1 )獲得最新的transformAux1信息通過transformAux1的getOrigin()獲取網格模型的位置坐標
通過transformAux1的getRotation()獲取網格模型的旋轉角度
渲染網格的最新位置與渲染姿態(tài)
ms.getWorldTransform( transformAux1 );
const p = transformAux1.getOrigin();
const q = transformAux1.getRotation();
objThree.position.set( p.x(), p.y(), p.z() );
objThree.quaternion.set( q.x(), q.y(), q.z(), q.w() );
- 示例代碼:
//-- 物理世界變量
const gravityConstant = - 9.8;
let transformAux1;
//-- 啟動物理世界
initPhysics();
animate();
function initPhysics() {
...
//-- 創(chuàng)建一個支持軟體胚委、剛體的物理世界
physicsWorld = new Ammo.btSoftRigidDynamicsWorld( dispatcher, broadphase, solver, collisionConfiguration, softBodySolver );
//-- 設置物理世界的重力
physicsWorld.setGravity( new Ammo.btVector3( 0, gravityConstant, 0 ) );
physicsWorld.getWorldInfo().set_m_gravity( new Ammo.btVector3( 0, gravityConstant, 0 ) );
//-- 剛體運動監(jiān)測對象
transformAux1 = new Ammo.btTransform();
}
//-- 添加網格模型挟鸠,掛載物理外形到自定義屬性physicsBody
function addRigidMass(){
...
//-- 創(chuàng)建一個與網格幾何模型形狀發(fā)相似的物理幾何模型
const body = new Ammo.btRigidBody( rbInfo );
threeObject.userData.physicsBody = body;
...
//-- 添加網格模型到場景
scene.add( threeObject );
//-- 有質量的物體會參與碰撞,將其添加到一個數(shù)組rigidBodies中
//-- 源碼中如果mass為0亩冬,則為地板類型剛體艘希,不參與運動計算
if ( mass > 0 ) {
rigidBodies.push( threeObject );
}
//-- 添加物理模型到物理世界
physicsWorld.addRigidBody( body );
}
function animate() {
//-- 渲染
const deltaTime = clock.getDelta();
//-- 渲染物理世界
updatePhysics( deltaTime );
renderer.render( scene, camera );
requestAnimationFrame( animate );
}
function updatePhysics( deltaTime ) {
// Step world
physicsWorld.stepSimulation( deltaTime, 10 );
//-- rigidBodies為帶有自定義屬性
for ( let i = 0, il = rigidBodies.length; i < il; i ++ ) {
const objThree = rigidBodies[ i ];
const objPhys = objThree.userData.physicsBody;
//-- 通過物理模型,獲取剛體的形狀
const ms = objPhys.getMotionState();
if ( ms ) {
//-- 獲取物理世界中的運動姿態(tài)
ms.getWorldTransform( transformAux1 );
const p = transformAux1.getOrigin();
const q = transformAux1.getRotation();
objThree.position.set( p.x(), p.y(), p.z() );
objThree.quaternion.set( q.x(), q.y(), q.z(), q.w() );
}
}
}
ammo.wasm.js待整理的方法
- set - 設置系列
* getLinearVelocity - 獲取線性速度
* setLinearVelocity - 設置線性速度
* setLinearFactor - 設置線性系數(shù)
* getAngularVelocity - 獲取角速度
* setAngularVelocity - 設置角速度
* setAngularFactor- 設置角度系數(shù)
* setCenterOfMassTransform - 設置質心變化
* setSleepingThresholds - ?
* setDamping - 設置阻尼
* setFriction - 設置摩擦力
* setRollingFriction - 設置滾動摩擦
* setAnisotropicFriction - 設置異性摩擦
* setMassProps - 設置道具質量
* setMotionState - 設置運動狀態(tài)
* setGravity - 設置重力
* setContactProcessingThreshold - ?
* setActivationState - 設置激活狀態(tài)
* setRestitution - ?
* setCollisionFlags - 設置碰撞標記
* setCollisionShape - 設置碰撞形狀
* setWorldTransform - 設置世界變化
* setCcdMotionThreshold - ?
* setCcdSweptSphereRadius - ?
* setUserIndex - 設置使用者索引
* setUserPointer - 設置用戶坐標
待學習
http://schteppe.github.io/ammo.js-demos/
- ammo引擎官方
https://juejin.cn/post/7200039970575941693
- 物理引擎差異文章( 優(yōu)先看!!! )
https://juejin.cn/post/7095621578976657421
- 動畫
https://www.cnblogs.com/lxiang/archive/2012/09/13/2683220.html
- ApplyForce硅急、ApplyImpulse覆享、SetLinearVelocity
https://pmndrs.github.io/cannon-es/docs/classes/Trimesh.html
- 模型添加碰撞形狀
http://threejs.org/examples/index.html#physics_ammo_volume
- 官方示例軟體模型與剛體模型
http://threejs.org/examples/physics_ammo_instancing.html
- 發(fā)射子彈與指定碰撞地點
http://threejs.org/examples/physics_ammo_break.html
- 物理屬性
未完待續(xù)....