Verlet 3D Ball Breaking

时间:2017-08-09 22:36:56

标签: javascript three.js game-physics verlet-integration

我正在尝试使用verlet integration制作柔软的身体球。

我基本上创建一个网格并用弹簧连接每个顶点。我使用three.js来渲染球体。我相信一切正常,但我不确定如何获得理想的结果。如果连接太弱则我的球会坍塌,如果太僵硬则会爆炸。有些事似乎不对。问题发生在物体掉落并撞击地面的那一刻。我将发布我的代码的主要部分,但是我不确定我的方法是否有效并且可以用于产生我想要的结果。

function verletStick3D(p1, p2, distance, rigid){


    this.type = "stick";
    this.p1 = p1;
    this.p2 = p2; 
    this.distance = distance;
    this.rigid = rigid;
    this.update = function(){

        var dx = this.p1.x - this.p2.x;
        var dy = this.p1.y - this.p2.y;
        var dz = this.p1.z - this.p2.z;
        var distance = Math.sqrt(dx * dx + dy * dy + dz * dz);
        var difference = this.distance - distance;
        var percent = difference / distance / 2;
        var offsetX = dx * percent * this.rigid;
        var offsetY = dy * percent * this.rigid;
        var offsetZ = dz * percent * this.rigid;
        this.p1.x += offsetX;
        this.p1.y += offsetY;
        this.p1.z += offsetZ;
        this.p2.x -= offsetX;
        this.p2.y -= offsetY;
        this.p2.z -= offsetZ;

    }
}

function verletPoint3D(x, y,z, maxX, maxZ, bounce = 0.9, friction = 

1.0, gravity = {x:0, y:-0.03, z:0}){
    y = y + 10;
    this.type = "point";
    this.x=x; 
    this.y=y;
    this.z=z;
    this.xOld=x;
    this.yOld=y;
    this.zOld=z;
    this.bounce = bounce;
    this.friction = friction;
    this.gravity = gravity;
    this.update = function(){
        var vx = (this.x - this.xOld) * this.friction;
        var vy = (this.y - this.yOld) * this.friction;
        var vz = (this.z - this.zOld) * this.friction;
        this.xOld = this.x;
        this.yOld = this.y;
        this.zOld = this.z;
        this.x += vx;
        this.y += vy;
        this.z += vz;
        this.y += this.gravity.y;
        this.x += this.gravity.x;
        this.z += this.gravity.z;



    }
    this.setGravity = function(gravity){
        this.gravity = gravity;
    }
    this.constrain = function(){
        var vx = (this.x - this.xOld) ;
        var vy = (this.y - this.yOld) ;

        if(this.x  > this.maxX){
            this.x = width;
            this.xOld = this.x + vx * this.bounce;
        }
        if(this.x < this.minX){
            this.x ;
            this.xOld = this.x + vx * this.bounce;
        }
        if(this.z > this.maxZ ){
            this.z = height ;
            this.zOld = this.z + vz * this.bounce;

        }
        if(this.z  < this.minZ){
            this.z = 0;
            this.zOld = this.z + vz * this.bounce;
        }
        if(this.y  < 0){
            this.y = 0;
            this.yOld = this.y + vy * this.bounce;
        }

    }
}

function verletFromMesh(vertices, faces, maxX, maxY){
    var points  = [];
    for(var i = 0; i < vertices.length; i++){

        var p = new verletPoint3D(vertices[i].x, vertices[i].y, vertices[i].z, maxX, maxY, 0.9, 0.9);
        points.push(p);

    }

    var springs = []
    /*
    for(var i = 0; i < faces.length; i++){
        var face = faces[i];
        var p1 = face.a;
        var p2 = face.b;
        var p3 = face.c;
        springs.push(new verletStick( p1,p2, distance3D(p1, p2), 1.0) )
        springs.push(new verletStick( p2,p3, distance3D(p2, p3), 1.0) )
        springs.push(new verletStick( p3,p1, distance3D(p3, p1), 1.0) )
    }*/
    for(var i = 0; i < points.length; i++){
        var p1 = points[i];
        for(var j= i+1; j < points.length; j++){
            var p2 = points[j];
            if(p1.x == p2.x && p1.y == p2.y && p1.z == p2.z)
                continue;
            var dist = distance3D(p1, p2)

            springs.push(new verletStick3D( p1,p2, dist, 1.0) )


        }


    }


    return new verletObj(points, springs);
}

1 个答案:

答案 0 :(得分:1)

嗯,很难确切地看到你出错的地方,但对我而言,似乎你的弹簧可能无法扭转运动。这将导致爆炸/坍塌取决于他们的力量。我强烈建议尝试明确限制它们对球体的影响,并希望这将帮助您进一步调试此问题。

你的数学运算方式,特别是在设置偏移量dx * percent * this.rigid;时,似乎这些动态力量的行为是静态的,因此进展得太远了。

Ps:你有没看过这个post这是关于摩擦的,但我认为答案在这里很明显:

  

在移动的物体上引入一个小的,恒定的加速度   指向与运动相反的方向。并确保它不能   实际上扭转了运动;如果你在集成中检测到它   步骤,只需将速度设置为零。

希望这会让你以某种方式朝着正确的方向前进。