当前位置 博文首页 > 郭先生的博客:three.js cannon.js物理引擎之Heightfield

    郭先生的博客:three.js cannon.js物理引擎之Heightfield

    作者:郭先生的博客 时间:2021-01-30 15:23

    今天郭先生说一说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类。

     

    转载请注明地址:郭先生的博客

     

    下一篇:没有了