zoukankan      html  css  js  c++  java
  • three.js cannon.js物理引擎之约束(二)

    今天郭先生继续讲cannon.js的物理约束,之前的一篇文章曾简单的提及过PointToPointConstraint约束,那么今天详细的说一说cannon.js的约束和使用方法。在线案例请点击博客原文

    1. cannon.js约束的种类

    1. PointToPointConstraint点对点约束

    它的构造函数如下(之前可能介绍过了,这次统一说)

    PointToPointConstraint ( bodyA  pivotA  bodyB  pivotB  maxForce )
    • bodyA — 刚体A。
    • pivotA — 相对于刚体A的质心的点,刚体A被约束到该点。
    • bodyB — 刚体B。
    • pivotB — 相对于刚体B的质心的点,刚体B被约束到该点。
    • maxForce — 约束物体应施加的最大力。

    点对点约束顾名思义就是A刚体的某一点和B刚体的某一点形成约束,刚体之间仅通过约束点相连,如下图。

    2. LockConstraint锁定约束

    它的构造函数如下

    LockConstraint ( bodyA  bodyB { maxForce } )
    • bodyA — 刚体A。
    • bodyB — 刚体B。
    • maxForce — 约束物体应施加的最大力。

    为什么不需要设置约束点的位置呢,因为锁定约束其实就是点对点约束的简化版本,他们pivotA和pivotB默认为刚体的中心,如下图。

    3. DistanceConstraint距离约束

    它的构造函数如下

    DistanceConstraint ( bodyA bodyB distance maxForce )
    • bodyA — 刚体A。
    • bodyB — 刚体B。
    • distance — 要保持的距离。如果未定义,它将被设置为刚体A和刚体B之间的当前距离。
    • maxForce — 约束物体应施加的最大力。

    距离约束将两个物体约束为彼此重心的距离恒定,如下图是相邻小球保持恒定距离。



    4. HingeConstraint铰链约束

    它的构造函数如下

    HingeConstraint ( bodyA  bodyB  { pivotA axisA pivotB axisB maxForce } )
    • bodyA — 刚体A。
    • bodyB — 刚体B。
    • pivotA — 相对于刚体A的质心的点,刚体A被约束到该点。
    • axisA — 在刚体A中局部定义的刚体A可以绕其旋转的轴。
    • pivotB — 相对于刚体B的质心的点,刚体B被约束到该点。
    • axisB — 在刚体B中局部定义的刚体B可以绕其旋转的轴。
    • maxForce — 约束物体应施加的最大力。

    铰链又称合页,这个约束就像门的铰链一样,让两个物理只能在各自的点沿着固定的轴旋转。如下图。

    2. 案例的主要代码

    下面是案例的主要代码

    var bodies = [], meshes = [];
    
    initPoint() {
        var size = 0.5;
        var boxShape = new CANNON.Box(new CANNON.Vec3(size,size,size));
        var mass = 0;
    
        var N=10, last;
    
        for(var i=0; i<N; i++){
            // Create a box
            var boxbody = new CANNON.Body({
                mass: mass,
                shape: boxShape,
                position: new CANNON.Vec3(i * 0.6, (N - i) * Math.sqrt(size * size * 3) * 2, 0),
                quaternion: new CANNON.Quaternion().setFromEuler(-Math.PI / 4, -Math.PI / 4, 0),
                material: pubMaterial
            });
            boxbody.angularDamping = 0.3;
            bodies.push(boxbody);
            world.addBody(boxbody);
    
            if(i == 0) {
                mass = 1;
            } else {
                var c = new CANNON.PointToPointConstraint(boxbody, new CANNON.Vec3(size, size ,size), last, new CANNON.Vec3(-size, -size ,-size));
                world.addConstraint(c);
            }
    
            last = boxbody;
        }
    
        for(let i=0; i<10; i++) {
            let mesh = new THREE.Mesh(new THREE.BoxBufferGeometry(1), new THREE.MeshNormalMaterial());
            meshes.push(mesh);
            scene.add(mesh);
        }
        console.log(world)
    }
    initLock() {
        var size = 0.5;
        var boxShape = new CANNON.Box(new CANNON.Vec3(size,size,size));
        var mass = 1;
        var space = 0.1*size;
    
        var N=10, last;
    
        for(var i=0; i<N; i++){
            // Create a box
            var boxbody = new CANNON.Body({
                mass: mass,
                shape: boxShape,
                position: new CANNON.Vec3((N-i-N/2)*(size*2+2*space), size*6+space, 0),
                sleepSpeedLimit: 0,
                material: pubMaterial
            });
            bodies.push(boxbody);
            world.addBody(boxbody);
    
    
            if(last){
            // Connect the current body to the last one
                var c = new CANNON.LockConstraint(boxbody, last);
                world.addConstraint(c);
            }
    
            // To keep track of which body was added last
            last = boxbody;
        }
        var bodyA = new CANNON.Body({
            mass: 0,
            shape: boxShape,
            position: new CANNON.Vec3((-N/2+1)*(size*2+2*space), size*3-1, 0),
            material: pubMaterial
        });
        bodies.push(bodyA);
        world.addBody(bodyA);
    
        var bodyB = new CANNON.Body({
            mass: 0,
            shape: boxShape,
            position: new CANNON.Vec3((N/2)*(size*2+2*space), size*3-1, 0),
            material: pubMaterial
        });
        bodies.push(bodyB);
        world.addBody(bodyB);
    
        for(let i=0; i<12; i++) {
            let mesh = new THREE.Mesh(new THREE.BoxBufferGeometry(1), new THREE.MeshNormalMaterial());
            meshes.push(mesh);
            scene.add(mesh);
        }
    }
    initCloth() {
        var size = 0.2;
        var dis = 0.5;
        var sphereShape = new CANNON.Sphere(size);
        var mass = 1;
    
        var Nrows = 15, Ncols = 15;
        for(let i=0; i<Nrows; i++) {
            for(let j=0; j<Ncols; j++) {
                let body = new CANNON.Body({
                    mass: mass,
                    shape: sphereShape,
                    position: new CANNON.Vec3((i - 0.5 * Nrows + 0.5) * dis, 9, (j - 0.5 * Ncols + 0.5) * dis),
                    material: pubMaterial
                })
                bodies.push(body);
                world.addBody(body);
            }
        }
    
        let spherebody = new CANNON.Body({
            mass: 0,
            shape: new CANNON.Sphere(4),
            position: new CANNON.Vec3(0,4,0),
            material: pubMaterial
        })
    
        bodies.push(spherebody);
        world.add(spherebody);
        
    
        for(let i=0; i<Nrows * Ncols; i++) {
            let r = Math.floor(i / Nrows);
            let c = i % Nrows;
            if(r < Nrows - 1) {
                world.addConstraint(new CANNON.DistanceConstraint(bodies[r * Nrows + c], b2, dis, 5));
            }
            if(c < Ncols - 1) {
                world.addConstraint(new CANNON.DistanceConstraint(bodies[r * Nrows + c], bodies[r * Nrows + c + 1], dis, 5));
            }
        }
    
        for(let i=0; i<Nrows * Ncols; i++) {
            let mesh = new THREE.Mesh(new THREE.SphereBufferGeometry(size), new THREE.MeshNormalMaterial());
            meshes.push(mesh);
            scene.add(mesh);
        }
        
        let mesh = new THREE.Mesh(new THREE.SphereBufferGeometry(4, 32, 16), new THREE.MeshNormalMaterial());
        meshes.push(mesh);
        scene.add(mesh);
    }
    initHinge() {
        let bodyA = new CANNON.Body({
            mass: 0,
            shape: new CANNON.Box(new CANNON.Vec3(0.2, 4, 0.2)),
            position: new CANNON.Vec3(-3.2, 5, 0),
            material: pubMaterial
        })
        let bodyB = new CANNON.Body({
            mass: 1,
            shape: new CANNON.Box(new CANNON.Vec3(3, 4, 0.2)),
            position: new CANNON.Vec3(0, 5, 0),
            // material: pubMaterial
        })
    
        bodyB.velocity.set(0, 0, -10);
    
        bodies.push(bodyA);
        bodies.push(bodyB);
        world.add(bodyA);
        world.add(bodyB);
    
        var c = new CANNON.HingeConstraint(bodyA, bodyB, { 
            pivotA: new CANNON.Vec3(0.3, 0, 0),
            axisA: new CANNON.Vec3(0, 1, 0),
            pivotB: new CANNON.Vec3(-3.1, 0, 0),
            axisB: new CANNON.Vec3(0, 1, 0),
            maxForce: 2
        });
        world.addConstraint(c);
    
        let meshA = new THREE.Mesh(new THREE.BoxBufferGeometry(0.4, 8, 0.4), new THREE.MeshNormalMaterial());
        let meshB = new THREE.Mesh(new THREE.BoxBufferGeometry(6, 8, 0.4), new THREE.MeshNormalMaterial());
        meshes.push(meshA);
        meshes.push(meshB);
        scene.add(meshA);
        scene.add(meshB);
    }

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

  • 相关阅读:
    17._4Csharp中正则表达式的匹配
    15.13DataGridView单元格自动填充
    C#安装,启动,停止,卸载Windows服务
    C# 如何判断系统是32位还是64位
    [转]Excel关闭进程
    利用.Net中Process类调用netstat命令来判断计算端口的使用情况
    转:C# 获取指定目录下所有文件信息、移动目录、拷贝目录
    做安装包,安装后自动运行程序
    ...
    SharpZIP Lib
  • 原文地址:https://www.cnblogs.com/vadim-web/p/14472737.html
Copyright © 2011-2022 走看看