[Mathematics.. again] Catenary & Rope Slack.

Started by Calin Leafshade, Fri 08/01/2010 00:37:16

Previous topic - Next topic

Calin Leafshade

Ah another maths problem. Lucky you.

When a rope is anchored in two places it falls in a particular type of curve called a caternary (its a derivitive of a cosh curve)

If both anchor points at the same height its very easy to calculate the path of the caternary since the lowest point of the rope (the origin) will be equi-distant between the anchor points.

However if the anchor points are at different heights the origin is NOT equi-distant between the points and so its not possible to calculate the curve without first identifying where the origin is.

Any maths gurus care to help me plot that curve for the purposes of a basic rope simulator in AGS?


Snarky


Joe

#2
If you want what I'm thinking even using parabolas it would be really difficult. What's exactly what you want? What are the known variables? and what are the unknown?

Because if the known variables are the anchor points, the problem has no clue, since you should also know another parameter like the lenght of the rope or the function which defines the rope.
Knowing the length it would be very impossible to do it since the Lenght equation is:
L=(a/2)*(e^(c/a)+e^(-c/a)-e^(b/a)-e^(-b/a))
Where a is the lowest point, b and c are the anchor points and L is the lenght. But in that equation it's impossible to work out the value of a...
And the lenght equation of the parabola is also really complicated... so I really don't know how to help you with this...
Copinstar © Oficial Site

Kweepa

If you're doing a rope simulation, why not, err, simulate it?
You can approximate the initial position and run the simulation for a second to allow it to settle.
Still waiting for Purity of the Surf II

Jim Reed

I'm not very good at math, but looking at it from a logical perspective it seems simple.
The origin goes left or right from te middle distance of the poles in direct ratio of their height difference.
The height of the origin goes up and down in direct ratio of the poles distance considering the rope lenght.

Or maybe I'm wrong?

Kweepa

Here's an AGS 3.2 demo using verlet integration:
http://www.kweepa.com/step/ags/tech/RopeTest.zip
Included is my dev directory with a compiled game folder.

The core is:
Code: ags

function noloopcheck __Rope::Update()
{
  float dt = 1.0/IntToFloat(GetGameSpeed());
  
  // verlet step
  int i = 1;
  while (i < NSEG)
  {
    float x = rps[i].x;
    float y = rps[i].y;
    rps[i].x = ((2.0 - damping)*x - (1.0 - damping)*rps[i].ox);
    // gravity
    rps[i].y = ((2.0 - damping)*y - (1.0 - damping)*rps[i].oy) + gravity*dt*dt;
    rps[i].ox = x;
    rps[i].oy = y;
    i++;
  }
  
  // satisfy constraints
  int it = 0;
  while (it < 2)
  {
    i = 0;
    while (i < NSEG)
    {
      float dx = rps[i+1].x - rps[i].x;
      float dy = rps[i+1].y - rps[i].y;
      float dlen = Maths.Sqrt(dx*dx + dy*dy);
      float df = (dlen - elen)/dlen;
      rps[i].x = rps[i].x + 0.5*df*dx;
      rps[i+1].x = rps[i+1].x - 0.5*df*dx;
      rps[i].y = rps[i].y + 0.5*df*dy;
      rps[i+1].y = rps[i+1].y - 0.5*df*dy;
      i++;
    }
    it++;
  }
  
  // snap end points
  rps[0].x = x1;
  rps[0].y = y1;
  rps[NSEG].x = x2;
  rps[NSEG].y = y2;
}


Hope this helps!
Steve
Still waiting for Purity of the Surf II

Gilbert

#6
Heh neat! :D

I added the following line to the beginning of the room's rep. exec. for some nice moments:
Code: ags

Rope.SetStartPoint(IntToFloat(mouse.x), IntToFloat(mouse.y));


Edit:
For extra fun add also:
Code: ags
Rope.SetEndPoint(IntToFloat(player.x), IntToFloat(player.y));

Kweepa

Ah yes, I forgot to mention the rope parameters can be changed on the fly :=
This code could easily be extended to produce other loosely jointed stuff like rope ladders or rag dolls, but I leave that as an exercise for the reader.
Still waiting for Purity of the Surf II

Igor Hardy

#8
This is excellent. I needed something like this for my game too. Thanks, Steve.

Calin Leafshade

wow, nicely done Mr McCrea.

Now you just need to add weighted points and we have full rope sim :p

Then just add another dimension and you have cloth :p

Heh AGS is awesome.

Kweepa

Quote from: Calin Leafshade on Fri 08/01/2010 12:10:27
Heh AGS is awesome.
It's close to ideal for prototyping a lot of things (aside from its speed and lack of dynamic containers).
Still waiting for Purity of the Surf II

Joe

Steve you're a machine! I'd never have managed to create that physics code. It's awseome :D
Copinstar © Oficial Site

Vince Twelve

That's awesome Steve!  I programmed something like this for an underwater towing feature in a certain upcoming game designed by a certain red head, but yours is far more realistic!  Nice!

Kweepa

Quote from: Vince Twelve on Fri 08/01/2010 17:51:54
but yours is far more realistic!
And to think I contributed to your project on Kickstarter. :'(
You're welcome to take the guts of this and put them in Puzzle Bots.
Still waiting for Purity of the Surf II

Calin Leafshade

So now we have a fantastic rope sim I think someone should come up with an anti aliasing filter for it.

Since its a single line that should be within the realms of possibility. We can track the line and use an algorithm to choose points for pixels of varying tranparencies, thus antialiasing the line.

perhaps we could check if the rope has draw a pixel to the side and below the pixel we are checking and draw a semi transparent pixel there??

thoughts?

ddq

Quote from: Calin Leafshade on Fri 08/01/2010 22:44:15thoughts?
Damn.

Seriously, you're putting a lot of thought into something and I can't wait to see what comes of it.

Calin Leafshade

Dude, its going to be epic... and absolutly nothing to do with rope physics

but its always good to improve your understanding of stuff like this.

I plan to capture SteveMcCrea and keep him in a cupboard for later use.

tzachs

Quote from: Calin Leafshade on Fri 08/01/2010 23:26:08
I plan to capture SteveMcCrea and keep him in a cupboard for later use.
With a rope, perhaps?

Kweepa

My thoughts are to use standard line-antialiasing methods while drawing the line.
I'd get the bounds of the rope and create a new dynamic sprite, then go from there.
Bresenham line drawing includes enough secondary info (the fractional part of the dy) to determine the transparency of the main pixel and the neighbouring pixel.
Aha, here's some pseudo-code:
http://en.wikipedia.org/wiki/Xiaolin_Wu%27s_line_algorithm
As you say, this should run at a decent speed, even for a rope that stretches across the screen.
It might be good to just convert this to a module which draws an a-a line on a drawing surface.

Oh, and thanks for the offer, but this basement is plenty comfortable.
Still waiting for Purity of the Surf II

oren

you can also use the exact analytic solution of the problem:
y(x) = c3 + 1 / c1 * cosh( c1 * x + c2)

where the parameters c1, c2 and c3 are found using the rope length constraint:
L = \int\sqrt{1+y'(x)}dx
and its endpoints:
y(x1)=y1
y(x2)=y2

assuming x1=0 and y1=0, then c3=-1/c1*cosh(c2) and we ends up with the following two equations:
y2 = 1 / c1 * ( - cosh( c2 ) + cosh( c1 * x2 + x2 ) )
L = 1 / c1 * ( - sinh( c2 ) + sinh( c1 * x2 + x2 ) )
which can be solved numerically for c1 and c2 (in matlab or octave):

m-file for solving the equations set, called rope.m:
Code: ags

function f=rope(c,x2,y2,L)
f(1) = L  + 1 / c(1) * ( - sinh( x2 * c(1) + c(2) ) + sinh( c(2) ) );
f(2) = y2 + 1 / c(1) * ( - cosh( x2 * c(1) + c(2) ) + cosh( c(2) ) );


running the solver
Code: ags

% boundary and length
x2 = 1; y2 = 1; L = 5;

% initial guess
c0 = [1; 1];

% solver
c = fsolve(@(x) rope(x, x2, y2, L),c0)



now a lookup table can be calculated for all the desired x2, y2 and L values. for example:
x2 = 1.00, y2 = 1.00, L = 1.50 | c1 = 1.65, c2 = -0.022565
x2 = 1.00, y2 = 1.00, L = 2.00 | c1 = 3.83, c2 = -1.364008
x2 = 1.00, y2 = 1.00, L = 2.50 | c1 = 4.82, c2 = -1.986330
x2 = 1.00, y2 = 1.00, L = 3.00 | c1 = 5.50, c2 = -2.401198
x2 = 1.00, y2 = 1.00, L = 3.50 | c1 = 6.01, c2 = -2.712692
x2 = 1.00, y2 = 1.00, L = 4.00 | c1 = 6.43, c2 = -2.961918
x2 = 1.00, y2 = 1.00, L = 4.50 | c1 = 6.79, c2 = -3.169477
x2 = 1.00, y2 = 1.00, L = 5.00 | c1 = 7.10, c2 = -3.347194

plotting y(x) = - 1 / c1 * cosh( c2 ) + 1 / c1 * cosh( c1 * x + c2 ):







SMF spam blocked by CleanTalk