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

年后第一天上班,郭先生来说一说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的约束

 

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

posted @ 2021-02-24 12:15  郭先生的博客  阅读(1115)  评论(0编辑  收藏  举报