Ragdoll Physics

Member
Posts: 338
Joined: 2004.07
Post: #16
Another point- when you update your position, you add the velocity, when you should be adding the velocity * timeElapsed.

Justin Ficarrotta
http://www.justinfic.com
"It is better to be The Man than to work for The Man." - Alexander Seropian
Quote this message in a reply
Sage
Posts: 1,066
Joined: 2004.07
Post: #17
The link that Justin left me (about Verlet integration), that isn't the same thing that Najdorf was describing, was it? It doesn't seem that way. Considering all ups and downs, should I go with the position/velocity approach or position/lastposition approach? I don't want to rewrite all my code (even if it only sort of works) if it is a decent way to go.
Quote this message in a reply
Member
Posts: 749
Joined: 2003.01
Post: #18
Ok, that's good, only 1 problem, you write

shift[i].x += (circlePos[i+1].x - circlePos[i].x) / 4;

this tries to squeeze them all in 1 point!


I was wrong, you actually have to find the distance between the balls after all: the right code for the shifts is:


for(i = 1; i < NUM_CIRCLES - 1; i++)
{
distance=sqrt( (circlePos[i+1].x - circlePos[i].x)^2+(circlePos[i+1].y - circlePos[i].y)^2+(circlePos[i+1].z - circlePos[i].z)^2)

shift[i].x += (distance-2*radius) / 4*((circlePos[i+1].x - circlePos[i].x)/distance);
shift[i].y +=(distance-2*radius) / 4*((circlePos[i+1].y - circlePos[i].y)/distance);;
shift[i].z += (distance-2*radius) / 4*((circlePos[i+1].z - circlePos[i].z)/distance);

shift[i+1].x = -shift[i].x;
shift[i+1].y = -shift[i].y;
shift[i+1].z = -shift[i].z;
}


should work this way (hopefully...)


this way every ball is going to stay at a distance 2*radius from the linked balls(which is what you want)


edit: oh, and after all also I implicitely use the position-last position approach, since when you update v you are just using position-lastposition

©h€ck øut µy stuƒƒ åt ragdollsoft.com
New game in development Rubber Ninjas - Mac Games Downloads
Quote this message in a reply
Sage
Posts: 1,066
Joined: 2004.07
Post: #19
I put that code in and now I get some weird outcomes. They're too hard to describe so I uploaded the code to my site so someone can help.

Download Link

Edit: Scratch that. I forgot to fix the velocities based on the distance actually moved. You can still get the code if you want it (it doesn't work) though I don't know why you would.

Edit 2: I did update the file. There's just a weird glitch if you push a button or drag the mouse on the screen. I'm not sure why. I'm not sure what else to enhance my little system. Any ideas?

Edit 3: Forgot to mention, press P to pause/unpause the simulation.
Quote this message in a reply
Member
Posts: 749
Joined: 2003.01
Post: #20
Argh, I dunno... this is the nightmare of coding physics :-(

Ok, so if you're really into it you can work out how to handle collisions, rotations and everything of a rigid shape- not circle. I still havent go into that, my world is made by balls so far ;-)

or better try to turn your rope into a game

©h€ck øut µy stuƒƒ åt ragdollsoft.com
New game in development Rubber Ninjas - Mac Games Downloads
Quote this message in a reply
Sage
Posts: 1,066
Joined: 2004.07
Post: #21
I'd like to add more such as collisions and rotations and getting the rope to swing back and forth (as opposed to just falling and sitting straight up and down). I'm just not sure where to look for information as to how that all works.
Quote this message in a reply
Member
Posts: 749
Joined: 2003.01
Post: #22
hmmm, if the rope stays down instead of swinging you got something wrong... this algorithm should make a very realistic rope, you can also propagate waves in it.

Probably the velocity update is the problem

Or maybe try to delete the code that avoids the circles overlapping

©h€ck øut µy stuƒƒ åt ragdollsoft.com
New game in development Rubber Ninjas - Mac Games Downloads
Quote this message in a reply
Sage
Posts: 1,066
Joined: 2004.07
Post: #23
I'm not doing the check for overlaps anymore. Here's my entire circle updating code:
Code:
- (void)updateCircles
{
    int i,j;
    SEVector    shift[NUM_CIRCLES];
    SEVector    tempVector;
    SEVector    oldPos[NUM_CIRCLES];
    float        tempFloat,tempFloat2;
    
    //apply gravity to all of the circles except one
    for(i = 0; i < NUM_CIRCLES - 1; i++)
        circleVel[i].y -= GRAVITY * elapsedTime;
    
    //add the velocities to the circles
    for(i = 0; i < NUM_CIRCLES - 2; i++)
    {
        oldPos[i] = circlePos[i];
        circlePos[i].x += circleVel[i].x * elapsedTime;
        circlePos[i].y += circleVel[i].y * elapsedTime;
        circlePos[i].z += circleVel[i].z * elapsedTime;
    }
    
    //figure out shifts for circles
    for(i = 0; i < NUM_CIRCLES - 1; i++)
    {
        tempFloat = sqrt(pow(circlePos[i+1].x - circlePos[i].x,2) +
                         pow(circlePos[i+1].y - circlePos[i].y,2) +
                         pow(circlePos[i+1].z - circlePos[i].z,2));
        
        shift[i].x += ((tempFloat - (CIRCLE_RADIUS * 2)) / 4) * ((circlePos[i+1].x - circlePos[i].x) / tempFloat);
        shift[i].y += ((tempFloat - (CIRCLE_RADIUS * 2)) / 4) * ((circlePos[i+1].y - circlePos[i].y) / tempFloat);
        shift[i].z += ((tempFloat - (CIRCLE_RADIUS * 2)) / 4) * ((circlePos[i+1].z - circlePos[i].z) / tempFloat);
        
        shift[i+1].x = -shift[i].x;
        shift[i+1].y = -shift[i].y;
        shift[i+1].z = -shift[i].z;
    }
    
    //apply the shifts
    for(i = 0; i < NUM_CIRCLES - 2; i++)
    {
        circlePos[i].x += shift[i].x;
        circlePos[i].y += shift[i].y;
        circlePos[i].z += shift[i].z;
    }
    
    //reset the velocities based on actual movement
    for(i = 0; i < NUM_CIRCLES - 1; i++)
    {
        circleVel[i].x = circlePos[i].x - oldPos[i].x;
        circleVel[i].y = circlePos[i].y - oldPos[i].y;
        circleVel[i].z = circlePos[i].z - oldPos[i].z;
    }
}
Quote this message in a reply
Member
Posts: 749
Joined: 2003.01
Post: #24
hmmm... bad stuff...

So there are two ways of doing this, WITH the "elapsedTime" or WITHOUT, if you do it WITH you gotta be careful:

you wrote

circleVel[i].x = circlePos[i].x - oldPos[i].x;

while it should be

circleVel[i].x = (circlePos[i].x - oldPos[i].x)/elapsedTime;

(and of course the same for y and z)

(so either you do

x=x+xv and then xv=currentx-oldx

either

x=x+xv*elapsedtime and then xv=(currentx-oldx)/elapsedtime,

while you mixed, i.e. you did

x=x+xv*elapsedtime and then xv=currentx-oldx
)

hope you finally get it working :-)

(then try to put the ability of grabbing balls with the mouse)

©h€ck øut µy stuƒƒ åt ragdollsoft.com
New game in development Rubber Ninjas - Mac Games Downloads
Quote this message in a reply
Sage
Posts: 1,066
Joined: 2004.07
Post: #25
Try downloading the files once and changing that part. When I do it, I get a real big mess of things. It doesn't work as planned but I don't have time to upload a new version to show you because I have work in the morning (12:30 am here, my work starts at 7 Smile).
Quote this message in a reply
Member
Posts: 749
Joined: 2003.01
Post: #26
sorry, I dont have a mac here, post your code again and I'm sure I'll spot something else :/

©h€ck øut µy stuƒƒ åt ragdollsoft.com
New game in development Rubber Ninjas - Mac Games Downloads
Quote this message in a reply
Sage
Posts: 1,066
Joined: 2004.07
Post: #27
Ok. I've updated my code so you can grab it here and check it out.
Quote this message in a reply
Sage
Posts: 1,066
Joined: 2004.07
Post: #28
Here's the code in case you don't want to download anything. It still doesn't swing or sway like real rope. Just falls from horizontal to vertical and sits there.
Code:
- (void)updateCircles
{
    int i,j;
    SEVector    shift[NUM_CIRCLES];
    SEVector    tempVector;
    SEVector    oldPos[NUM_CIRCLES];
    float        tempFloat,tempFloat2;
    
    //apply gravity to all of the circles except one
    for(i = 0; i < NUM_CIRCLES - 1; i++)
        circleVel[i].y -= GRAVITY * elapsedTime;
    
    //add the velocities to the circles
    for(i = 0; i < NUM_CIRCLES - 1; i++)
    {
        oldPos[i] = circlePos[i];
        circlePos[i].x += circleVel[i].x * elapsedTime;
        circlePos[i].y += circleVel[i].y * elapsedTime;
        circlePos[i].z += circleVel[i].z * elapsedTime;
    }
    
    //figure out shifts for circles
    for(i = 0; i < NUM_CIRCLES - 1; i++)
    {
        tempFloat = sqrt(pow(circlePos[i+1].x - circlePos[i].x,2) +
                         pow(circlePos[i+1].y - circlePos[i].y,2) +
                         pow(circlePos[i+1].z - circlePos[i].z,2));
        
        shift[i].x += ((tempFloat - (CIRCLE_RADIUS * 2)) / 4) * ((circlePos[i+1].x - circlePos[i].x) / tempFloat);
        shift[i].y += ((tempFloat - (CIRCLE_RADIUS * 2)) / 4) * ((circlePos[i+1].y - circlePos[i].y) / tempFloat);
        shift[i].z += ((tempFloat - (CIRCLE_RADIUS * 2)) / 4) * ((circlePos[i+1].z - circlePos[i].z) / tempFloat);
        
        shift[i+1].x = -shift[i].x;
        shift[i+1].y = -shift[i].y;
        shift[i+1].z = -shift[i].z;
    }
    
    //apply the shifts
    for(i = 0; i < NUM_CIRCLES - 1; i++)
    {
        circlePos[i].x += shift[i].x;
        circlePos[i].y += shift[i].y;
        circlePos[i].z += shift[i].z;
    }
    
    //reset the velocities based on actual movement
    for(i = 0; i < NUM_CIRCLES - 1; i++)
    {
        circleVel[i].x = circlePos[i].x - oldPos[i].x;
        circleVel[i].y = circlePos[i].y - oldPos[i].y;
        circleVel[i].z = circlePos[i].z - oldPos[i].z;
    }
}

There's also some weird glitch where any keyboard input will cause the whole thing to jitter. Hard to explain. You'll just have to download the code and build it yourself. I think it might just be slowing the app down and causing the elapsedTime to jump a bit and cause the circles to move too much.

Thanks for all the help.
Quote this message in a reply
Member
Posts: 749
Joined: 2003.01
Post: #29
you wrote

circleVel[i].x = circlePos[i].x - oldPos[i].x;

while it should be

circleVel[i].x = (circlePos[i].x - oldPos[i].x)/elapsedTime;

(and of course the same for y and z)


If you say this does not work (it gets unstable), try deleting "elapsed time" from all the formulas (and also decreasing the gravity, o/w it would be too high), and see if that works, the system should be more stable.

(In this kind of stuff, if the elapsed time jumps from 1/60th of a second to 1/50th, you have big problems (caused by the velocity updating), that's why it's better to keep stuff "loop based", not "time based")\

If it's still unstable try putting

circleVel[i].x = (circlePos[i].x - oldPos[i].x)*0.99
(and of course the same for y and z)

And yes, probably the jumping thing is caused by the pressing buttons to change the "elapsed time"

©h€ck øut µy stuƒƒ åt ragdollsoft.com
New game in development Rubber Ninjas - Mac Games Downloads
Quote this message in a reply
Sage
Posts: 1,066
Joined: 2004.07
Post: #30
Hm. I deleted all of the elapsedTimes from the equations and lowered the gravity (from 3000 to 10 to 5 to 1 to .098) and none made it stable. I also tried the *.99 for the new velocities but still nothing. I'm confused as heck. I'll try some things and get back. If anyone else spots something, let me know. I'm on AIM all the time.
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  Ragdoll Physics merrill541 1 2,542 Feb 5, 2009 09:09 AM
Last Post: JustinFic
  Ragdoll Physic's: (For GML).. Master_Computer 0 2,398 Jan 27, 2008 11:55 AM
Last Post: Master_Computer
  Bullet Physics Library / COLLADA physics viewer erwincoumans 14 12,854 Aug 12, 2006 12:59 AM
Last Post: Fenris
  Ragdoll Physics Duane 3 3,999 Jul 7, 2005 09:55 AM
Last Post: Duane
  Ragdoll and cloth physics Skorche 28 13,280 Jun 10, 2003 03:12 PM
Last Post: Fenris