1

I have the following mesh which is generated by random points and creating triangles using Delaunay triangulation. Then I apply spring force per triangle on each of its vertices. But for some reason the equilibrium is always shifted to the left.

Here is a video of the behaviour: https://youtu.be/gb5aj05zkIc

Why this is happening?

Here is the code for the physics:

for ( let i=0; i < mesh.geometry.faces.length; i++) {

    let face = mesh.geometry.faces[i];

    let a = mesh.geometry.vertices[face.a];
    let b = mesh.geometry.vertices[face.b];
    let c = mesh.geometry.vertices[face.c];

    let p1 = Vertcies[face.a];
    let p2 = Vertcies[face.b];
    let p3 = Vertcies[face.c];

    update_force_points(p1, p2, a, b);
    update_force_points(p1, p3, a, c);
    update_force_points(p2, p3, b, c);
  }

function update_force_points(p1, p2, p1p, p2p) {

  // get all the verticies
  var dx = (p1.x - p2.x);
  var dy = (p1.y - p2.y);

  var len = Math.sqrt(dx*dx + dy*dy);
  let fx = (ks * (len - r) * (dx/len)) + ((kd * p2.vx - p1.vx));
  let fy = (ks * (len - r) * (dy/len)) + ((kd * p2.vy - p1.vy));  

  if ( ! p1.fixed ) {
    p1.fx = (ks * (len - r) * (dx/len)) + ((kd * p2.vx - p1.vx));
    p1.fy = (ks * (len - r) * (dy/len)) + ((kd * p2.vy - p1.vy));
  }
  if ( ! p2.fixed ) {
    p2.fx = -1 * p1.fx;
    p2.fy = -1 * p1.fy;
  }

  p1.vx += p1.fx / mass;
  p1.vy += p1.fy / mass;

  p2.vx += p2.fx / mass;
  p2.vy += p2.fy / mass;

  p1.x += p1.vx;
  p1.y += p1.vy;
  p2.x += p2.vx;
  p2.y += p2.vy;

  p1p.x = p1.x;
  p1p.y = p1.y;
  p2p.x = p2.x;
  p2p.y = p2.y;

  p2p.z = 0.0;
  p1p.z = 0.0;
}
aaaidan
  • 7,093
  • 8
  • 66
  • 102
ArmenB
  • 2,125
  • 3
  • 23
  • 47
  • can you define ks and kd? Where is it defined which points are fixed? Is mass fixed for all vertices? If you randomize the vertex positions do you get the same result? (do all drift to the left bottom?) if not, then this isn't that weird. closely spaced segments will contract stronger than others, because you subtract a fixed amount (r), so there is more force there. There should be asymmetry – OtterFamily May 09 '17 at 14:33

1 Answers1

2

At the moment you're doing velocity calculations and assigning new positions at the same time, so the balance will change depending on the order that you cycle through points in. I would guess that points at the bottom left are either at the beginning of the vertex list, or at the end.

try doing all the p#.vx calculations linearly, then do a second pass where you just do p#.x += p#.vx

that way you calculate all necessary velocities based on a snapshot of where points were the previous frame, then you update their positions after all points have new velocities.

So do:

for(var i = 0; i < #; i++){
    updateforces(bla,bla,bla) //don't assign position in here, just add forces to the velocity
}

for(var i =0; i < #; i++){
    updateposition(bla,bla,bla)
}
OtterFamily
  • 803
  • 4
  • 10
  • your comment give me an idea which I tried and it worked. the call to `update_force_points` wasn't updating the forces in an equal manner. I updated to p1, p2 then p2, p3, and finally p3, p1 so the forces acting on each other are triangle shaped. – ArmenB May 09 '17 at 18:29
  • oh also i realized that what you've done is only a fix for a bigger problem - ```p1p.x = p1.x; p1p.y = p1.y; p2p.x = p2.x; p2p.y = p2.y; ``` this line overwrites vertex data, it doesn't modify it. That means that the last function called sets the vertex data - so all previous functions that include that vertex data point get overwritten by the last one called. ie in your original code: ```update_force_points(p2, p3, b, c);``` overwrites all previous work done on vertices except for ```a``` so now at least you're overwriting in a specific order, but it's just a fix for a bigger issue – OtterFamily May 10 '17 at 09:16
  • you should do vertex assignments (a = #, b = #, etc) only once your model (p1,p2,etc) is fixed - and to fix your model you need to seperate force assignments and position assignments. so you need: ```calculateforces();calculatemodelPositions();assignVertexpositions();``` as seperate steps – OtterFamily May 10 '17 at 09:20
  • it does get overwritten but I am incrementing it in `p1.y, x` so that value is the actual value being used. It's redundant I know but I figured I might want to do some data massaging with the data before assigning it. – ArmenB May 10 '17 at 17:37