three.js cannon.js物理引擎之Heightfield

郭先生的部落格發表於2021-01-27

今天郭先生說一說cannon.js物理引擎之Heightfield高度場,學過場論的朋友都知道物理學中把某個物理量在空間的一個區域內的分佈稱為場,高度場就是與高度相關的場,而cannon.js物理引擎的Heightfield的高度就是關於兩個變數的函式,可以表達為HEIGHT(i,j)。當然知不知道場論不耽誤我們學習Heightfield,下面就是一個由Heightfield生成的高度場,線上案例請點選部落格原文。我們來說一說它的用法。

 

1. Heightfield的用法

說用法之前我們不妨看看他的API,文件對於它的說明是 – “高度資料以陣列形式給出。這些資料點以給定的距離均勻分佈”。建構函式如下。

Heightfield ( data , options )

data是一個Y值陣列,將用於構建地形。options是一個配置項,有三個可配置引數。minValue是資料陣列中資料點的最小值。如果未給出,將自動計算。maxValue最大值。elementSize是X方向上資料點之間的世界間距。他還有一些屬性和方法請大家自行觀看,我就不多說了。

高度場Heightfield本質和cannon.js一樣還是一種資料的表達形式,想要把它應用到three中仍然需要對應的圖形來表達(就像CANNON.Box資料需要THREE.BoxBuferGeometry幾何體一樣),對應的幾何體就是ParametricBufferGeometry,下面我們以一個案例來實際操作一下。

2. Heightfield案例

可以點選案例來觀看,下面我們直接上程式碼。

initCannon() {
        //這裡是生成高度場的程式碼
    var matrix = [];//建立構造高度場的陣列
    for (var i = 0; i < size; i++) {
        matrix.push([]);
        for (var j = 0; j < size; j++) {
                        //高度由兩個餘弦函式疊加形成
            var height = Math.cos(i / size * Math.PI * 8) * Math.cos(j / size * Math.PI * 8);
            matrix[i].push(height)
        }
    }
    var hfShape = new CANNON.Heightfield(matrix, {
        elementSize: 1 //資料點的距離設定為1
    });
    var hfBody = new CANNON.Body({ mass: 0, material: physicsMaterial});
    var q = new CANNON.Quaternion();
    q.setFromAxisAngle(new CANNON.Vec3(1, 0, 0), - Math.PI / 2);
    hfBody.addShape(hfShape, new CANNON.Vec3(-size / 2, 0, size / 2), q);//由於這個高度場是XOY平面第一象限上,所以需要旋轉和平移,addShape方法為我們提供了這個功能。
    world.addBody(hfBody);
},
initThree() {
        //使用ParametricBufferGeometry配合Heightfield形成網格
    var groundGeom = new THREE.ParametricBufferGeometry((u,v,target) => {
        var height = Math.cos(u * Math.PI * 8) * Math.cos(v * Math.PI * 8);//這裡的方法和生成高度場的方法是一樣的,不瞭解ParametricBufferGeometry幾何體的可以參考我之前發的部落格。
        target.set(u * size - size / 2, height, v * size - size / 2);
    }, size, size)
    let groundMate = new THREE.MeshPhongMaterial({color: 0x666666, side: THREE.DoubleSide});
    groundMesh = new THREE.Mesh(groundGeom, groundMate);
    scene.add(groundMesh);
},

Heightfield學習起來還是很簡單的,我們後面的案例可能會用到這個高度場作為地面,作為預備知識先了解一下。下一節我們講一下RaycastVehicle類。

 

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

 

相關文章