webgL - apply wind effect on cloth simulation

269 Views Asked by At

I need to implement an easy effect of the wind force in a simulation of a cloth. My cloth is made by 10x10 vertices (100 indices given in the cloth_vertices array) connected using springs. The springs are defined as follow:

function initMassSpringSystem() {

    // adding springs
    for (let i = 0; i < cloth_size - 1; i++) {
        for (let j = 0; j < cloth_size - 1; j++) {
            let top = i * cloth_size + j;
            // vertical 1
            spring_start.push(top);
            spring_end.push(top + cloth_size);
            spring_rest.push(1.0 / (cloth_size - 1));
            // horizontal 1
            spring_start.push(top);
            spring_end.push(top + 1);
            spring_rest.push(1.0 / (cloth_size - 1));
            // vertical 2
            spring_start.push(top + 1);
            spring_end.push(top + 1 + cloth_size);
            spring_rest.push(1.0 / (cloth_size - 1));
            // horizontal 1
            spring_start.push(top + cloth_size);
            spring_end.push(top + 1 + cloth_size);
            spring_rest.push(1.0 / (cloth_size - 1));
            // diagonal 1
            spring_start.push(top);
            spring_end.push(top + 1 + cloth_size);
            spring_rest.push(Math.sqrt(2) * 1.0 / (cloth_size - 1));
            // diagonal 2
            spring_start.push(top + 1);
            spring_end.push(top + cloth_size);
            spring_rest.push(Math.sqrt(2) * 1.0 / (cloth_size - 1));
        }
    }

    // initializing velocities and forces
    for (i = 0; i < cloth_size * cloth_size; i++) {
        v.push(vec3.fromValues(0.0, 0.0, 0.0));
        f.push(vec3.fromValues(0.0, 0.0, 0.0));
    }

    time = Date.now();
}

In my function updateCloth() I already implemented the gravity, spring and damping force and they work properly, but the problem now is to apply the wind effect:

function updateCloth() {

    // ------------ Assignment ------------
    // You need to fill in the gaps in this function

    // initializing forces for every particle with gravity and any external forces
    for (i = 0; i < cloth_size * cloth_size; i++) {
    // gravity act on y direction. All forces are recalculated at each time stamp
        f[i][1] = - (mass * 9.8665);
    }

    // computing the forces exetrted by every spring and adding them to the forces acting on particles
    for (i = 0; i < spring_start.length; i++) {
        let p = spring_start[i]; // index of the particle/vertex which corresponds to one end of the spring
        let q = spring_end[i]; // index of the particle/vertex which corresponds to one end of the spring
        // positions of the two ends of the spring
        let x_p = vec3.fromValues(cloth_vertices[3 * p], cloth_vertices[3 * p + 1], cloth_vertices[3 * p + 2]);
        let x_q = vec3.fromValues(cloth_vertices[3 * q], cloth_vertices[3 * q + 1], cloth_vertices[3 * q + 2]);
        
        // Compute forces exert by the spring and the damping forces
        // Use the computed forces to update f[p] and f[q], i.e., accumulated forces which act on the particles
        
        

        
        // damping force
        let empty = vec3.fromValues(0, 0, 0);
        let e = vec3.fromValues(0,0,0);
        vec3.sub(e,x_q, x_p);
        let len_1 = vec3.distance(x_q,x_p);
        let c = vec3.fromValues(0, 0, 0);
        vec3.normalize(c,e);

        let b1 = vec3.fromValues(0,0,0);
        vec3.sub(b1,v[q], v[p]);
        vec3.divide(b1, b1, vec3.fromValues(spring_rest[i], spring_rest[i], spring_rest[i]));
        let b2 = c;
        let b = vec3.dot(b1, b2);

        let damping_force = damping * b * c[1];


        // hooke's law
        let second = (len_1/spring_rest[i])-1;
        let third = c[1];
        let hooke_law = k * second * third;

        // for f[p] y add forces, while subtract for [q] y because the force is in the opposite direction
        f[p][1] = f[p][1] + hooke_law + damping_force;
        f[q][1] = f[q][1] - hooke_law - damping_force;

        // WIND
        // take delta time
        const end_time = Date.now();
        const time_elapsed = end_time - time;
        // calculate wind force using a sinusoidal function (such that it oscillates)
        const wind = Math.sin(2 * Math.sin(time_elapsed)) + Math.sin(3.14 * Math.sin(time_elapsed));
        f[p][0] = wind;
        f[q][0] = -wind;


    }
    
    // updateing position an velocities of the particles based on forces and masses
    
    for (let i = 0; i < cloth_size * cloth_size; i++) {
        
        // fixed point to avoid cloth falling forever
        if ( i === 0 || i === cloth_size - 1) {
            
            // velocity of i-th particle
            v[i][0] = 0;
            v[i][1] = 0;
            v[i][2] = 0;
            
            // position of i-th particle
            cloth_vertices[3 * i] = cloth_vertices[3 * i];
            cloth_vertices[3 * i + 1] = cloth_vertices[3 * i + 1];
            cloth_vertices[3 * i + 2] = cloth_vertices[3 * i + 2];
        }
        else {

            // Here update the velocity and position of every particle
            // velocity of i-th particle
            v[i][1] = v[i][1] + (deltaT * (f[i][1] / mass));
            v[i][2] = 0;
            // wind
            v[i][0] = v[i][0] + (deltaT * (f[i][0] / mass));
            // console.log(v[i][0]);
            
            // position of i-th particle
            cloth_vertices[3*i + 1] = cloth_vertices[3*i + 1] + (deltaT * v[i][1]);
            // wind
            cloth_vertices[3*i+2] = cloth_vertices[3*i+2] + (deltaT * v[i][0]);
        }
    }

    // The three lines below will make sure that the buffer on the GPU,
    // which stores the positions of particles, will be updated.
    gl.bindBuffer(gl.ARRAY_BUFFER, clothVertexBuffer);
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(cloth_vertices), gl.DYNAMIC_DRAW);
    gl.bindBuffer(gl.ARRAY_BUFFER, null);
}

This function is called many times to have the animation effect on another run() method. I read that the wind effect is dependent on the time variable, then I took the difference between before the execution of the whole function (time variable defined just before calling updateCloth()) and everytime it is called.Then I used a simply equation found on internet that I called wind, that permit to have a small value that oscillates between negative and positive values (~-2 / ~+2). I applied this force to f[p], where p is the index of the vertex that starts the spring, and I applied its inverse to f[q] that ends the spring (I put the negative value because I know that in a spring a force to one vertex is the opposite one for the other vertex but I'm not sure that this idea can be applied also with the wind). I applied this force only on the x value (in fact I have f[p][0]) to have easier calculations, but I think it must be applied on all the three directions (I have a 3D simulation, then x,y,z). The result is that half of the cloth goes infinitely to one direction and half to the other one. The force value oscillates correctly and also the velocity, but the problem is that the position of the vertices continues to increase, some in positive and some in negative values. I don't know how to obtain the effect of the wind that increase but only until a certain value, and then remains unchanged. I read about the fact that its value depends on the position of the vertices (I have the left and right corner of the cloth fixed such that is doesn't fly away, then I suppose the wind effect must be bigger on the bottom of the cloth), but I don't have any idea about how to implement it.

Without the wind my cloth can be visualised as following:

enter image description here

While applying my wrong wind effect it behaves in this way:

enter image description here

I hope I gave all informations, otherwise don't hesitate to ask.

1

There are 1 best solutions below

4
On

With a spring system in place "wind" is just a matter of applying some force to the vertices and letting the spring system take care of leveling forces. You don't need to explicitly balance the forces, that's what you wrote the spring system for. "Wind" is not a specific simulation/formula, it's data you feed into your simulation (as forces).