2

I am trying to use verlet integration for making a soft body sphere.

I basically create a mesh and attach each vertex by springs. I am using three.js to render the sphere. I believe everything is working correctly, but I am unsure about how to get the desired results. My ball collapses if the connections are too weak or explodes if too rigid. Something doesn't seem right. The problem occurs the moment the object falls and hits the ground. I will post the major parts of my code, however I am unsure if my approach is valid and can be used to produce the results I want.

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);
}
2pha
  • 9,798
  • 2
  • 29
  • 43
Luple
  • 481
  • 3
  • 21

1 Answers1

1

Hmm, it's hard to see exactly where you're going wrong, but to me, it seems like your springs might not be able to reverse the motion. That would cause the explosions/collapses depending on their strength. I'd highly suggest trying to explicitly limit their effect on the sphere and hopefully that'll help you further debug this issue.

The way your math works, especially when setting offsets dx * percent * this.rigid; makes it seems like these dynamic forces are behaving statically, and therefore going too far into play.

Ps: have you checked out this post? It's about friction, but I think the answer is pretty quotable here:

Just introduce a small, constant acceleration on moving objects that points in the direction opposite to the motion. And make sure it can't actually reverse the motion; if you detect that in an integration step, just set the velocity to zero.

Hope this sets you in the right direction somehow.

Loufs
  • 1,596
  • 1
  • 14
  • 22
  • 1
    Hey Lofus, thanks for the response. there were a few problems, but one of them was "var vz = (this.z - this.zOld) ;" and some other stuff in other parts of the code. i really just needed to come up with a better way of handling the connections between the points. I got it working though. https://desolate-coast-97190.herokuapp.com – Luple Aug 10 '17 at 20:27