年後第一天上班,郭先生來說一說cannon.js的ConvexPolyhedron(多邊形),cannon.js是一個物理引擎,內部通過連續的計算得到各個時間點的資料的狀態,three.js的模型可以定時的應用這些狀態來達到運動的效果,但是在應用的時候cannon資料模型和three模型一般都是不同的(而且多數情況下都是不一樣的),因為更大的cannon資料模型會帶來更多的效能問題,並且有的時候是沒有必要的,比如說上一篇我們用圓柱來模擬保齡球瓶。但是有一些時候還是需要使用相對複雜的cannon多邊形來對應three模型的,比如使用一個比較大的模型,那麼它的細節就會很大程度的影響物理效果。那麼我們來製作一個這樣的場景,效果如下圖,線上案例請點選部落格原文。
1. cannon.js物理引擎多邊形ConvexPolyhedron的建構函式
ConvexPolyhedron ( points faces )
建構函式一共需要兩個引數,points是一個Vec3型別的陣列,也就是包含所有點的陣列,faces是一個組成每個小三角面的二維陣列,這個就和THREE.Face3比較類似,比如說我們像製作出一個四面體,
var points = [ new CANNON.Vec3(0,0,0), new CANNON.Vec3(2,0,0), new CANNON.Vec3(0,2,0), new CANNON.Vec3(0,0,2) ]; var faces = [ [0,3,2], [0,1,3], [0,2,1], [1,2,3], ] var convex = new CANNON.ConvexPolyhedron( points faces );
如果瞭解three.js,那麼這個東西是很好理解的。
2. 實現一個使用ConvexPolyhedron(多邊形)的場景
場景如上圖,包括一個ParametricGeometry、一個TorusGeometry和一個TorusKnotGeometry一共三個幾何體,首先我們用three.js先製作出來三個幾何體,我們既可以使用幾何體製作出網格,也可以製作出cannon.js多邊形
1. 製作three幾何體
parametricGeom = new THREE.ParametricGeometry( (u, v, target) => { let x = Math.sin(Math.PI * 2 * u) * 10 * Math.abs(Math.sin(Math.PI * v)); let y = v * 20 - 10; let z = Math.cos(Math.PI * 2 * u) * 10 * Math.abs(Math.cos(Math.PI * v)); target.set(x, y, z); }, 30, 12 ); torusGeom = new THREE.TorusGeometry(5, 2, 16, 8); torusKnotGeom = new THREE.TorusKnotGeometry(5, 1.5, 80, 8, 2, 3); for(let i=0; i<parametricGeom.faces.length; i++) { color.setHSL(Math.random(), 0.5, 0.5); parametricGeom.faces[i].color.copy(color); } for(let i=0; i<torusGeom.faces.length; i++) { color.setHSL(Math.random(), 0.5, 0.5); torusGeom.faces[i].color.copy(color); } for(let i=0; i<torusKnotGeom.faces.length; i++) { color.setHSL(Math.random(), 0.5, 0.5); torusKnotGeom.faces[i].color.copy(color); }
這裡就製作出了三個幾何體,併為每個小三角面上了色。
2. 用既有的three幾何體製作cannon多邊形
let parametricShape = this.createConvex(parametricGeom); let torusShape = this.createConvex(torusGeom); let torusKnotShape = this.createConvex(torusKnotGeom); parametricBody = new CANNON.Body({ mass: 0, position: new CANNON.Vec3(-20, 6, 0), material: new CANNON.Material({friction: 0, restitution: 1}), shape: parametricShape }) torusBody = new CANNON.Body({ mass: 0, position: new CANNON.Vec3(0, 6, 0), material: new CANNON.Material({friction: 0, restitution: 1}), shape: torusShape }) torusKnotBody = new CANNON.Body({ mass: 0, position: new CANNON.Vec3(20, 6, 0), material: new CANNON.Material({friction: 0, restitution: 1}), shape: torusKnotShape }) world.addBody(parametricBody); world.addBody(torusBody); world.addBody(torusKnotBody); createConvex(geometry) { let vertices = []; let faces = []; for(let i=0; i<geometry.vertices.length; i++) { vertices.push(new CANNON.Vec3(geometry.vertices[i].x, geometry.vertices[i].y, geometry.vertices[i].z)); } for(let i=0; i<geometry.faces.length; i++) { faces.push([geometry.faces[i].a, geometry.faces[i].b, geometry.faces[i].c]); } return new CANNON.ConvexPolyhedron(vertices, faces); }
three的點和faces面存在geometry.vertices中和geometry.faces中,我們需要取出來並整理成我們想要的形式。然後下一步就是建立three.js網格,我們就不贅述了。
主要程式碼就是這麼多。其實知道了cannon多邊形的構造方法,我們很容易就製作出想要的多邊形,這很大程度上豐富了物理世界。下一篇我們繼續說一說cannon.js的約束
轉載請註明地址:郭先生的部落格