three.js cannon.js物理引擎之ConvexPolyhedron多邊形

郭先生的部落格發表於2021-02-24

年後第一天上班,郭先生來說一說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的約束

 

轉載請註明地址:郭先生的部落格

相關文章