1 / 48

Ragdoll Physics

Ragdoll Physics. on the Nintendo DS. Eric Brown. Where was this used?. Ragdoll prerequisites. Animation system needs to be capable of procedural animation (ideal) employ callbacks that allow manipulation on a per bone basis (less-ideal) Ragdoll system hijacks the skeleton entirely

petula
Download Presentation

Ragdoll Physics

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Ragdoll Physics on the Nintendo DS Eric Brown

  2. Where was this used?

  3. Ragdoll prerequisites • Animation system needs to be capable of procedural animation • (ideal) employ callbacks that allow manipulation on a per bone basis • (less-ideal) Ragdoll system hijacks the skeleton entirely • NITROSystem has an animation system that employs per bone callbacks • Collision detection system

  4. A Simple Particle System • Nodes – points that get updated by physics • Constraints – apply further modification to the position of a node (or nodes) • (particle system demo)

  5. What is the basic idea? • Use a particle system to represent the skeleton • Apply appropriate constraints to ensure valid skeleton configurations • Derive rotation and translation info from the configuration of the nodes • Procedurally animate

  6. Nodes struct Node{Vec position;Vec lastPos;Vec accel;float invMass;};

  7. Updating Nodes • Accumulate Forces void AccumulateForce(Node* n, Vec* F){ n->accel += Scale(F, n->invMass);} void ApplyGlobalAcceleration(Vec* a){ (loop over all nodes n) { n->accel += *a; }}

  8. Updating Nodes • Use the Verlet Integration formula to update nodes • Xn+1 = 2Xn – Xn-1 + Ant2 • Xn+1 = Xn + (1-f)(Xn – Xn-1) + Ant2 • This formula has several advantages • Numerically stable • Easy to apply constraints

  9. Updating Nodes void Integrate(float t2, float f){ (loop over all nodes n) {Vec tmp = n->position; n->position += (1.0-f)*(n->position-n->lastPos); n->position += n->accel*t2; n->lastPos = tmp; n->accel = 0; }}

  10. Applying Constraints • Always apply constraints after updating the nodes • The underlying strategy for applying a constraint is • Determine where a node needs to be • Put it there • Verlet Integration takes care of the rest

  11. Constraints • Preventing floor penetration is an example of a global constraint void FloorConstraint(float height){ (loop over all nodes n) { if(n->position.y < height) { n->position.y = height; } }}

  12. Constraints • Examples of local constraints are enum ConstraintTypes{ ANCHOR, STICK, LINE, PLANE, SPLINE, …};

  13. Constraints struct Constraint{int type;Node* n1;Node* n2;Vec* anchor;float maxLength;float minLength; …}

  14. Constraints void ApplyAnchor(Constraint* c){ c->n1->position = *c->anchor;} • Code for applying a stick constraint is included in the handout • Note: Applying 2 constraints to the same node generally results in one of the constraints being violated

  15. Constraints void ApplyConstraints(int iterations){for(int i=0; i<iterations; i++) {//apply local constraints (loop over all constraints c) {switch(c->type) {case ANCHOR: ApplyAnchor(c);break;case STICK: ApplyStick(c);break; … } }//apply global constraints FloorConstraint(0.0f); }}

  16. Constraints • Some types of constraints require a change in velocity, i.e. Bounce • To change the velocity of the particle you can: • Modify the value of the lastPos (instantaneous impulse) • Accumulate a force on the particle that will change its velocity on the next frame (penalty force)

  17. The Verlet System • The Verlet System is a set of Nodes and Constraints struct VerletConfig{Vec gravAccel;int iterations;float airFriction; …};

  18. Updating the Verlet System void UpdateVerlet(VerletConfig* conf, float t){float t2 = t*t;//Accumulate ForcesApplyGlobalAcceleration(&conf->gravAccel); (Accumulate local forces)//IntegrateIntegrate(t2, conf->airFriction);//Apply ConstraintsApplyConstraints(conf->iterations);}

  19. Animation Primer

  20. What do we need in order to create an animation? • We need to calculate a model space representation of each bone of the animation • Translation information is carried by the position of the node • Rotation information can be derived by the positions of nearby nodes

  21. Future mechanism for obtaining information about rotations • Allow a Verlet Node to carry information about its orientation in the form of a quaternion struct Node{ …Quat rotation;Quat lastRot;Quat angularAccel; …}; • Update the quaternions using the Non-Abelian Verlet formula • Rn+1 = (Wt(Rn(Rn-1)-1)1/t)tRn

  22. Brads • A structure that contains all of the information necessary to calculate a full bone matrix from a set of 4 Verlet Nodes • A Brad is a brass fastener that attaches several sheets of paper together • Brad Moss is a designer that made a suggestion that motivated the idea of this object

  23. Brads struct Brad{Node* a;Node* b;Node* c1;Node* c2;Mtx43* bone;int bAxis; //0-X, 1-Y, 2-Zint cAxis;};

  24. Brads • Node A • Node B • B Axis • Node Ca • Node Cb • C Axis

  25. Revised Update Routine void UpdateVerlet(VerletConfig* conf, float t){float t2 = t*t;//Accumulate ForcesApplyGlobalAcceleration(&conf->gravAccel); (Accumulate local forces)//IntegrateIntegrate(t2, conf->airFriction);//Apply ConstraintsApplyConstraints(conf->iterations);//Update All BradsUpdateAllBrads();}

  26. Articulate Collision • We used a standard swept sphere collision for each node • Note: Node positions were in world space • The spheres were so small that the swept sphere routine would fail due to imprecission

  27. Fixed Point math primer 5.7 0.3 1.2 0.3 114 9 0 570 6.84 0.09

  28. FX32 • FX32 is a 32 bit Fixed Point data type with 12 bits of decimal precision • As a mnemonic device we will create a unit called FX=4096 • A decimal number like 5.7 can be represented in FX32 format as 5.7FX = 23347.2 -> 23347 • Every time you multiplying 2 FX32 numbers you accumulate an extra power of FX • Therefore you must divide by FX whenever you multiply • Basically, if ab=c then (aFX*bFX)/FX = cFX

  29. Sample multiplication routine fx32 FX_MUL(fx32 a, fx32 b){return (a*b)>>12;}

  30. FX32 • The range of FX32 is about +/-500000 • The smallest number is 1/FX = 0.00024 • The smallest FX32 number that can be multiplied by itself and get a non-zero result is 0.015FX = 64 • If you let 1FX represent 1 meter, then the precision limit is a few centimeters

  31. Sphere Intersection Test BOOL SphereIntersection(VecFx32* center, fx32 radius, VecFx32* point){fx32 r2, d2;VecFx32 diff; r2 = FX_MUL(radius, radius); VEC_Subtract(center, point, &diff); d2 = VEC_DotProduct(&diff, &diff);return (d2 < r2);} • Radius > 1 Meter – Good results • Radius < 1 Meter – Not so good • Radius < 0.5 Meters – Pretty crappy

  32. How do we get around this? • Create a new fixed point data type with higher precision • Fx32e has 27 bits of precision • Uncertainty of multiplication is on the order of microns rather than centimeters (a micron is 1000 times smaller than a millimeter) • Use a regular integer multiplication if you can get away with it (don’t divide by FX after you multiply)

  33. Example: • We start with 4 numbers that are related by ab > cd • If we try to evaluate this comparison using FX32 multiplication we have (aFX*bFX)/FX > (cFX*dFX)/FX • Truncation error might cause this comparison to evaluate incorrectly • If we try to evaluate this comparison using integer multiplication we have aFX*bFX > cFX*dFX • There is still truncation error, but it is significantly smaller. On the order of millimeters rather than ten centimeters

  34. A Better Sphere Intersection Test BOOL SphereIntersection(VecFx32* center, fx32 radius, VecFx32* point){fx32 r2, d2;VecFx32 diff; r2 = radius*radius; VEC_Subtract(center, point, &diff); d2 = diff.x*diff.x + diff.y*diff.y + diff.z*diff.z;return (d2 < r2);} • Radius > 1mm – Good results • Radius < 1mm – Not so good • Radius < 0.5mm – Pretty crappy

  35. More than 2 Mults • If you are going to perform more than 2 FX32 mults, you can get some extra mileage out of integer multiplies • If you want to multiply three numbers abcusing FX32 multiplication you have ((aFX*bFX)/FX)*cFX)/FX • Instead use integer mults and divide by FX2 at the end • This is (aFX*bFX*cFX)/(FX*FX)

  36. Sample 3 mult Routine fx32 FX_MUL3(fx32 a, fx32 b, fx32 c){return (a*b*c)>>24;}

  37. Philosophy of using integer multipy • fx32 numbers accumulate a power of FX for every integer multiply • An fx32 can endure 2 powers of FX before overflowing • An fx64 can endure 5 powers of FX before overflowing • Perform as many integer multiplies as possible before dividing out the powers of FX • If you are comparing two numbers that have accumulated the same powers of FX (homogeneous), perform the comparison without dividing out the powers of FX • If the numbers you are comparing are not homogeneous, multiply by FX until the powers are equal, then perform the comparison • Try not to overflow

  38. Rotation Math • In order for a matrix M to represent a rotation it must be OrthoNormal. This means that its inverse is equal to its transpose. • One direct result of a matrix being OrthoNormal is that det(M) = +/- 1 • If det(M) = 1 then the matrix represents a rotation • If det(M) = -1 then the matrix represents a reflection.

  39. Reflections and Rotations • If you multiply two OrthoNormal reflection matrices S1, S2, then the product is also OrthoNormal • The determinant of this product is:det(S1S2) = det(S1)det(S2) = (-1)(-1) = 1 • The short story? 2 consecutive reflections form a rotation.

  40. Reflection Rotations • Rotations are unique (almost) • If the result of 2 reflections places a vector where it needs to be, then the reflections are equivalent to the corresponding rotation • Goal: find a reflection algorithm to replace a rotation algorithm

  41. Find 2 Reflections

  42. Find 2 Reflections • Reflect about a line that bisects the initial and final vectors • Reflect about the final vector

  43. Reflection about a line • The component of the vector that is parallel to the line does not get reflected • Split the vector into 2 components V = Vline + Vreflect • The reflected vector is V’ = Vline - Vreflect • To find Vlineyou need the normal n in the direction of the line, then Vline = n*dot(V,n) • To find Vreflect, just take Vreflect = V – Vline • The reflected vector is V’ = 2*n*dot(V,n) - V

  44. Sample Reflection Function void ReflectOnLine(VecFx32* in, VecFx32* line, VecFx32* out){fx32 dp;VecFx32 tmp; dp = VEC_DotProduct(in, line); dp <<= 1; //dp *= 2VEC_Scale(line, &tmp, dp);VEC_Subtract(&tmp, in, out);}

  45. Sample 2 Reflection Function void ReflectOn2Lines(VecFx32* in, VecFx32* line1, VecFx32* line2, VecFx32* out){fx32 dp;VecFx32 tmp, result; dp = VEC_DotProduct(in, line1); dp <<= 1;VEC_Scale(line1, &tmp, dp);VEC_Subtract(&tmp, in, &result); dp = VEC_DotProduct(&result, line2); dp <<= 1;VEC_Scale(line2, &tmp, dp);VEC_Subtract(&tmp, &result, out);}

  46. Reflection Uses • Very good for applying a rotation to a small number of vectors • Use it to build rotation matrices, when you know the initial and final vectors. • Example: apply the minimum rotation to a matrix in order to get the “Look” component to point in the right direction • Source code for building orientation matrices is included in the handout

  47. The End • Thank you to: • Sensory Sweep • Brad Moss • Micah Neilson • GDC ‘08

More Related