iDevGames Forums
Ragdoll Physics - Printable Version

+- iDevGames Forums (http://www.idevgames.com/forums)
+-- Forum: Development Zone (/forum-3.html)
+--- Forum: Game Programming Fundamentals (/forum-7.html)
+--- Thread: Ragdoll Physics (/thread-5384.html)

Pages: 1 2 3 4


Ragdoll Physics - Nick - Jun 23, 2005 02:30 PM

Slightly inspired by ragdoll masters and my own desire to make an absurdly complex sidescroller, where might I find a good starting point to ragdoll physics? I know I need a skeletal structure (or at least break the body into masses) but what is an efficient way to do that? Where do I go from there? I would like to find answers to these questions. Any hints or links would be absolutely fantastic.


Ragdoll Physics - Jake - Jun 23, 2005 02:58 PM

Try searching, this has been covered multiple times. I did it for you in less than 30 seconds

Search -
http://www.idevgames.com/forum/search.php?searchid=86086

Relevant Thread
http://www.idevgames.com/forum/showthread.php?t=3651&highlight=ragdoll


Ragdoll Physics - Najdorf - Jun 23, 2005 03:11 PM

I'm sorry I dont have links to give, many programs just use the physics of some library, but I can tell you how I approached the thing (though I really dont know if it's the "right" way!)

imo, the basic of ragdoll is a chain of balls:

So first thing you need to do is be confident on how to put a number of balls on the screen and have them affected by gravity. ok, I assume you can do that ;-).

Then, you need to link the balls. There is THE fundamental trick here: you move the balls as if there was NO link between them, THEN through iterated steps, you link them back.

How to link the balls: with only 2 balls, it's easy, you shift one ball half way towards the other and the second half way towards the first, and you're done. Problem: you cant do this with 3 or more balls: or at lest you need more iterations of this procedure.

So my procedure is: consider all couples of linked balls: for every couple, compute a "virtual shift" that one ball induces on the other. This "virtual shift" must be proportional to the distance between the two balls (it does not have to be 1/2 of the distance (the natural way to do it), it can be less, like 1/4 of the distance or even less). It's "virtual" because you dont shift the balls right after you computed it, you calculate ALL virtual shifts applied to each ball (by all other balls to which it is linked), then you sum them up (vector sum), and finally you move the balls by this amount. And all this procedure must be iterated, about 1 iteration for every ball you put in.

Ok, that's most of it, the final trick is then to update the velocity vector of each ball, on the base of the actual distance it travelled in the frame.

Summing up the procedure is :


-balls have position x1,y1
-move balls based on their velocity vector (ie. x2=x1+vx, y2=y1+vy)
balls have position x2,y2,
-link back balls (changes their position to x3,y3)
balls have position x3,y3,
update velocity i.e. vx=(x3-x1), vy=(y3-y1)

That's it!

try to get a rope going on, it's pretty impressive by it's own.

Then you will need joint rigidities, but I'm not that happy with my algorithms to do that, so you should look for a better source.


Ragdoll Physics - Nick - Jun 23, 2005 03:19 PM

I did a search for ragdoll that came up with nothing (I did restrict to the game programming forums only figuring a safe bet but I guess not). Thanks.

Najdorf: I did notice that your game starts and you can see all the balls. What did you do to make them look like sticks? Just draw over them? (off topic but i guess I'll need it even for my rope).


Ragdoll Physics - Najdorf - Jun 23, 2005 03:22 PM

yeah just draw over it. the core are the balls really

Is the algorithm clear enough?


Ragdoll Physics - Nick - Jun 23, 2005 03:40 PM

Seems clear enough. I'm going to check it out either later tonight or tomorrow and see if I can get a little rope going.

Edit: For drawing balls did you just use a triangle fan or did you actually make balls somehow?

How did you draw over all the balls? Just put some textured quads using the balls' positions to base the vertices off? Seems like that'd work well enough.

Thanks for the help. If anyone else has any resources, they're still appreciated. I'll check back up and let you know how it's all going.


Ragdoll Physics - Fenris - Jun 24, 2005 12:44 AM

Why not just use the balls as simulation objects and draw the quads in their place? That way you don't have to do the overdraw?


Ragdoll Physics - Najdorf - Jun 24, 2005 07:57 AM

I draw also the balls to get smooth edges


Ragdoll Physics - Leisure Suit Lurie - Jun 24, 2005 07:59 AM

Najdorf Wrote:I draw also the balls to get smooth edges

That's a bit strange when taken out of context. Rasp


Ragdoll Physics - Nick - Jun 25, 2005 06:43 AM

Najdorf Wrote:So my procedure is: consider all couples of linked balls: for every couple, ...
Would the couples be like 1&2, 2&3, 3&4 or would it be 1&2, 1&3, 2&3? I'm just trying to figure out if I have to reference every ball to every ball or down the line like the first set.

Also could you help me with vector sums. I know that I add the components and convert to polar but won't that leave me with just an angle (one number)? Don't I still need a vector? Or did I miss something in math class... Either way thanks for the help.


Ragdoll Physics - Najdorf - Jun 25, 2005 07:51 AM

well if you want to do a chain of balls the couples linked are [1,2], [2,3], [3,4]

For other kind of figures the couples linked are different. [1,2],[2,3],[1,3] produces a circle.

(Just to show off, a man is:
joints[][]=[[1,2],[2,3],[3,4],[4,5],[5,6],[6,7],[7,8],[8,9],[9,10],[10,11],[6,12],[12,13],[13,14],[14,15],[15,16],[14,17],[17,18],[18,19],[19,20],[14,21],[21,22],[22,23],[23,24],[1,25],[11,26]]
Rasp )

suppose you moved the balls, and they end up like this (Ignore the dots, focus on the balls (the numbers) and the links (the lines)

....2
.../|
./..|
1...|
....|
4--3


You want to get the balls attached (i.e. you want to eliminate the space between them)

say ball1 has position x1,y1, ball2 has position x2,y2...

Consider ball 1:it's linked only to ball 2: Compute the "virtual shift" that ball 2 applies on ball1, i.e. ball 2 "pulls" ball1 in it's direction, say by 1/4 of the distance.

Then the virtual shift on ball1 is :

virtualShiftX1=(x2-x1)/4
virtualShiftY1=(y2-y1)/4

similarly ball2 is attracted by ball1

virtualShiftX2=-(x2-x1)/4
virtualShiftY2=-(y2-y1)/4

Now, ball2 is also attracted by ball3, so you "add" to the current the virtual shift (this is what I meant for vector sum)

virtualShiftX2=virtualShiftX2+(x3-x2)/4
virtualShiftY2=virtualShiftY2+(y3-y2)/4

then you do the same for all the chain of balls.

When you computed the virtual shifts for all balls, you apply them (i.e. you do x[i]=x[i]+virtualshiftX[i] and the same for y)

And you iterate the whole procedure for a number of times.

That's it!


Also, at the beginning of the main loop (not during this iterative procedure), you can put gravity, and say for instance that the position of ball1 must be that of the mouse, so you can drag the chain around.


Ragdoll Physics - Jake - Jun 25, 2005 09:16 AM

Heres an old demo I did to teach myself verlet integration -

http://nuclearnova.com/temp/Jakes Verlet Demo.sit

Code is included in if you have METAL, or use a text editor to read it, its very simple. I did this on a 45 minute car ride after reading tutorials Smile.


Ragdoll Physics - Nick - Jun 26, 2005 03:17 PM

I'm trying to get this all down. My rope is starting to act right but is falling apart and collapsing on itself. I've decided there are two factors: 1) my collision code (to keep circles from overlapping) is incorrect and 2) my shift calculations are bad. I also have realized that all my circles have broken away from the anchor (a circle that gets no shift nor gravity). Here's some of my code if anyone could look over it and offer suggestions:

Code:
//apply gravity to all of the circles except one
    for(i = 1; i < NUM_CIRCLES; i++)
        circleVel[i].y -= 9.8 * elapsedTime;
    
    //add the velocities to the circles
    for(i = 1; i < NUM_CIRCLES; i++)
    {
        circlePos[i].x += circleVel[i].x;
        circlePos[i].y += circleVel[i].y;
        circlePos[i].z += circleVel[i].z;
    }
    
    //figure out shifts for circles
    for(i = 1; i < NUM_CIRCLES; i++)
    {
        shift[i].x += (circlePos[i+1].x - circlePos[i].x) / 4;
        shift[i].y += (circlePos[i+1].y - circlePos[i].y) / 4;
        shift[i].z += (circlePos[i+1].z - circlePos[i].z) / 4;
        
        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 = 1; i < NUM_CIRCLES; i++)
    {
        circlePos[i].x += shift[i].x;
        circlePos[i].y += shift[i].y;
        circlePos[i].z += shift[i].z;
    }
    
    //prevent circles from overlapping
    for(i = 1; i < NUM_CIRCLES; i++)
    {
        if((tempFloat = (pow((circlePos[i].x - circlePos[i-1].x),2) +
                         pow((circlePos[i].y - circlePos[i-1].y),2) +
                         pow((circlePos[i].z - circlePos[i-1].z),2))) < (pow((CIRCLE_RADIUS * 2),2)))
        {
            tempVector.x = (circlePos[i].x - circlePos[i-1].x) / tempFloat;
            tempVector.y = (circlePos[i].y - circlePos[i-1].y) / tempFloat;
            tempVector.z = (circlePos[i].z - circlePos[i-1].z) / tempFloat;
            
            circlePos[i].x += tempVector.x;
            circlePos[i].y += tempVector.y;
            circlePos[i].z += tempVector.z;
            
            circlePos[i].x -= tempVector.x * CIRCLE_RADIUS * 2;
            circlePos[i].y -= tempVector.y * CIRCLE_RADIUS * 2;
            circlePos[i].z -= tempVector.z * CIRCLE_RADIUS * 2;
        }
    }



Ragdoll Physics - JustinFic - Jun 26, 2005 04:22 PM

Here's an article on physics simulations using Verlet Integration as Jake mentioned:

http://www.gamasutra.com/resource_guide/20030121/jacobson_pfv.htm

As far as your code it would help if you showed us via a build or screenshot what it was doing that was wonky. Just from looking at it though, it seems like you're going out of the bounds of your array when you access i+1 in the for loop with i going from 1 to NUM_CIRCLES.


Ragdoll Physics - Nick - Jun 26, 2005 05:03 PM

I changed the code a little bit. Here's the new code I'm using:
Code:
- (void)updateCircles
{
    int i;
    SEVector    shift[NUM_CIRCLES];
    SEVector    tempVector;
    float        tempFloat;
    
    //apply gravity to all of the circles except one
    for(i = 1; i < NUM_CIRCLES; i++)
        circleVel[i].y -= 9.8 * elapsedTime;
    
    //add the velocities to the circles
    for(i = 1; i < NUM_CIRCLES; i++)
    {
        circlePos[i].x += circleVel[i].x;
        circlePos[i].y += circleVel[i].y;
        circlePos[i].z += circleVel[i].z;
    }
    
    //figure out shifts for circles
    for(i = 1; i < NUM_CIRCLES - 1; i++)
    {
        shift[i].x += (circlePos[i+1].x - circlePos[i].x) / 4;
        shift[i].y += (circlePos[i+1].y - circlePos[i].y) / 4;
        shift[i].z += (circlePos[i+1].z - circlePos[i].z) / 4;
        
        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 = 1; i < NUM_CIRCLES; i++)
    {
        circlePos[i].x += shift[i].x;
        circlePos[i].y += shift[i].y;
        circlePos[i].z += shift[i].z;
    }
    
    //prevent circles from dropping off screen
    for(i = 1; i < NUM_CIRCLES; i++)
        if(circlePos[i].y < -70)
            circlePos[i].y = -70;
}
And here you can find images of the problem. The screens are just pics I took, in order, while the program was going. I hope someone can help me. Obviously there are no collisions but the particles all seem to gravitate to the wrong point. Perhaps there's a way I'm doing something backwards? Also if someone could help me write a quick little collision detection for() loop, I'd be really happy. I tried writing one (see the first post) but it just caused the particles to go crazy. Thanks for all the help. I plan to go read JustinFics link now.