Jump to content

Physx3 ragdoll progress continues, slowly...


chriscalef

Recommended Posts

Hey, just thought I'd update this forum too, in case people aren't tracking the other one... nothing too exciting, not game ready yet (for one thing, you can't create a ragdoll anywhere except the origin at the moment :-P ) but at least there is a working dude you can kick around now:


(And btw, does this forum support vimeo/youtube/etc videos directly?)




In case anyone doesn't have them already from the thread on gg.com, the relevant repos are:


github.com/ChrisCalef/Torque3D/tree/physx3_advanced_WIP


and for the game directory,


github.com/ChrisCalef/physx3_advanced_game


Obviously there are joint limits / stability issues, but the biggest problem is whatever I'm doing wrong with the base node transform. When you move it away from the origin the physics bodies get moved twice as far, or something. It should be a fairly simple fix but I have other work coming up now so I gotta put it down. Suggestions welcome (cough cough, Timmy, cough). :-)


Anyway, that's where it stands for now. Good luck on all your Torque projects!



EDIT: oh yeah, if you should bother to download and play with it, "alt g" is hooked up to give him a vertical impulse, the guy is named $m4 (for michael4) and there is a function called applyImpulseToPart() or aitp() for short, which is used like this:


$m4.aitp(2,"0 0 0","0 0 1500");


where "2" is the bodypart index (going from 0 at the hip to 4 at the head, and then arms and then legs), "0 0 0" is the origin of the force relative to the bodypart origin, and "0 0 1500" is the force vector.

Link to comment
Share on other sites

hey chris thats cool,

i would bet that gmk`s ragdolls might contain a solution and btw it looks like that the ragdoll itself isnt really exposed to script so thats another thing that needs to be checked/added.

Will take a look at your work, as i did played around with gmk ragdolls and fixed those more or less (stretching issue for example) i might be able to get somewhere with your base.

t3d would certainly benefit from ragdolls physx and bullet based ones ofc.

Link to comment
Share on other sites

Thanks everybody


Re: GMK, yeah, I think I've dug my own hole here by now though. It shouldn't take that long to figure out what's going wrong when I get a good solid day on it, but I happen to be out of time at the moment.


Re: script access, for my current build the way you create ragdolls is by adding a regular physics shape, only with two new members added to the datablock: bool isArticulated = true and S32 shapeID = a valid PhysicsShape ID in your sqlite database (physicsData.db).


When I first started down this path I made all the bodyparts and joints in script, with datablocks, but it quickly escalated into a totally ridiculous number of datablocks being used up on physics, so I switched everything over to sqlite. I included a little free software sqlite frontend called sqlitestudio in the game repo - it's a little clunky but is a lot better than nothing.


In the database, there are three useful tables so far: physicsShape, which is basically just a name and an ID to link all the parts together; physicsShapePart, which contains all the rigid body properties for one bodypart, plus a link to the joint; and px3Joint, which defines the properties of a joint that could be reused many times in the same skeleton.


Debug draw mode is turned on and off with physicsDebugDraw(bool), or pdd(bool) for short.


I haven't exposed different debug draw modes to script yet, but they're easily found in the source code, in Px3World::onDebugDraw. You can define whether it draws joint limits, bodypart axes, bodypart collision shapes, and set the overall scale of the axes/joint limit rendering here.


Anyway, that's the basic lowdown on how to use it, as it currently exists. I'll make this thread my announcement area for future progress.

Link to comment
Share on other sites

I think so... unless there's some deeper problem somewhere waiting for me. Got tomorrow free so I should be able to hit it pretty hard.


Looking to add joint motor forces very soon as well, and then I also need to write the kinematic part of the equation - when the body is animating, it needs to drive the physics parts in kinematic mode, so they can find collisions, etc. and also to start ragdolling in mid action sequence instead of only from a standing position. Shouldn't be very difficult though.

Link to comment
Share on other sites

To get the correct pose i solved this by passing in the dead player object id via script to the ragdoll class (obviously server side) and than resolving the ghost and copy the transforms, this saves copying the transforms over the network which would be horrible. Once this is done it's safe to delete the player. Bare in mind i did it this way because i have no need for ragdolls unless they are spawned from a dead player.


I really regret not creating a GUI tool to help create the ragdolls, boy it's a slow, boring and tedious job setting everything up by hand.

Link to comment
Share on other sites

I will also say it's a been a long battle getting the joints and the drive parameters right but i finally got it right just yesterday. I just added in support for aggregates into the PhysicsBody class too, hopefully this keeps performance under check in a heavily populated physics scene. I also found upping the joint solver iterations helped stability of the ragdolls too. Hope that helps but looks like from the video you not far away nailing it anyway :mrgreen:

Link to comment
Share on other sites

Would be interesting to see how you hooked up the joints to the animation system. I did some work a few months back on importing MikuMikuDance models into torque and had to add a whole bunch of override code to correctly handle their constraint system so animations would work correctly.

Link to comment
Share on other sites

Okay, no further progress to report except code cleaned up and committed, so grab updates if you're interested.


@Mango, not sure what you mean, were you bringing in models with animations or was physics involved? I shouldn't have to worry about constraints (until we get to the next phase, that is) since all I'm looking at is driving kinematic rigid bodies with the animation data.


The really fun part (I've done this already in Ecstasy Motion, just not here in stock Torque physx) is when you start driving joint forces with animation data. It looks pretty weird and is definitely a very different product from the original animation, but if you're planning for that it can be really cool.

Link to comment
Share on other sites

And, WHEW. Was an all weekend project, but they are now working from any direction. Still the same joint limits, iterations, etc. issues, but the key transform problems appear to all be solved at this point.




EDIT: Oh yeah, also I moved gravity out to a pref in scripts/client/prefs.cs, but I took that file out of the repo so you'll have to add this yourself if you want a non default gravity:



$pref::Physics::gravity = "0 0 -1.0";


The above is very light gravity, handy for fine tuning joints, but normal is more like -9.8.

Link to comment
Share on other sites

  • 2 weeks later...

Minor improvements: got setDynamic(bool) and setHasGravity(bool) functioning, as well as setPartDynamic and setPartHasGravity.




Still WIP status, remaining most immediate issues are:


1) we still have an offset problem, when actors start out kinematic and later change to dynamic, they are rendering the shape mesh out at double the main body transform


2) knee/elbow joints reveal an apparent bug in physx3 (?), or else some fundamental misunderstanding on my part, because: I have succeeded in rotating the physx view of my joint limit cone to exactly where I want it, judging by the debug render view anyway, but in practice the limit cone is always right down the center, and the knees and elbows bend backward exactly as much as they bend forward. Will probably try limit planes next.


3) finally, I also haven't set up the kinematic side yet to drive the physx bodyparts with the nodeTransforms.

Link to comment
Share on other sites

Ah, there we go...




Now we can drive kinematic bodyparts around as expected.


Remaining goals:


1) start moving actors around the world in realtime, making sure above still works


2) build a game with a player in it and hook up the rifle to effectively shoot them


3) fix all the single-player-game assumptions


4) eventually figure out what's up with the knee/elbow joint orientations. Possibly move on up to latest greatest physx, currently still on version 3.3.1.

Link to comment
Share on other sites

So... if the video's still processing then come back in a few minutes, but... I successfully addressed the most entertaining point on the above list:




Yes, you can shoot them now! Although I haven't committed the script side yet because it's part of a new project, which as you can see merges my terrain pager and physx3 projects into one game build... master plan coming together... all it took on the script side is the following addition to WeaponImage::onFire (put it right after the "create the projectile object" block)

 

	...

     //Add this for physics raycasting
     //TEMP! Hard coding it for basic pistol and rifle for first pass, but this  
     //  should be maybe a projectile property(?)
     if ((%this.getName() $= "RyderWeaponImage")||(%this.getName() $= "LurkerWeaponImage"))
     {
        %start = %obj.getEyePoint();
        %start = VectorAdd(%start,VectorScale(%muzzleVector,2));  
        %vec = VectorScale(%muzzleVector,100);

        //TEMP! Define this in the (weapon or the projectile datablock)?
        if (%this.getName() $= "RyderWeaponImage")
           %weaponForce = 70.0;
        else
           %weaponForce = 95.0;

        //echo("casting ray from: " @ %start @ " in direction of " @ %vec);
        %id = physx3CastRay(%start,%vec,1);//0=static,1=dynamic,2=player,3=all
        if ((%id)&&(%id.getClassName() $= "PhysicsShape")) 
        {
           %id.setDynamic(1);
           %id.aitp(%id.getContactBody(),VectorScale(%muzzleVector,%weaponForce));
        }
        //end physics raycasting

 

(Sorry if that is too confusing, here is the full function for reference)

 


// ----------------------------------------------------------------------------
// A "generic" weaponimage onFire handler for most weapons.  Can be overridden
// with an appropriate namespace method for any weapon that requires a custom
// firing solution.

// projectileSpread is a dynamic property declared in the weaponImage datablock
// for those weapons in which bullet skew is desired.  Must be greater than 0,
// otherwise the projectile goes straight ahead as normal.  lower values give
// greater accuracy, higher values increase the spread pattern.
// ----------------------------------------------------------------------------

function WeaponImage::onFire(%this, %obj, %slot)
{
  //echo("\c4WeaponImage::onFire( "@%this.getName()@", "@%obj.client.nameBase@", "@%slot@" )");

  // Make sure we have valid data
  if (!isObject(%this.projectile))
  {
     error("WeaponImage::onFire() - Invalid projectile datablock");
     return;
  }

  // Decrement inventory ammo. The image's ammo state is updated
  // automatically by the ammo inventory hooks.
  if ( !%this.infiniteAmmo )
     %obj.decInventory(%this.ammo, 1);

  // Get the player's velocity, we'll then add it to that of the projectile
  %objectVelocity = %obj.getVelocity();

  %numProjectiles = %this.projectileNum;
  if (%numProjectiles == 0)
     %numProjectiles = 1;

  for (%i = 0; %i < %numProjectiles; %i++)
  {
     if (%this.projectileSpread)
     {
        // We'll need to "skew" this projectile a little bit.  We start by
        // getting the straight ahead aiming point of the gun
        %vec = %obj.getMuzzleVector(%slot);

        // Then we'll create a spread matrix by randomly generating x, y, and z
        // points in a circle
        %matrix = "";
        for(%j = 0; %j < 3; %j++)
           %matrix = %matrix @ (getRandom() - 0.5) * 2 * 3.1415926 * %this.projectileSpread @ " ";
        %mat = MatrixCreateFromEuler(%matrix);

        // Which we'll use to alter the projectile's initial vector with
        %muzzleVector = MatrixMulVector(%mat, %vec);
     }
     else
     {
        // Weapon projectile doesn't have a spread factor so we fire it using
        // the straight ahead aiming point of the gun
        %muzzleVector = %obj.getMuzzleVector(%slot);
     }

     // Add player's velocity
     %muzzleVelocity = VectorAdd(
        VectorScale(%muzzleVector, %this.projectile.muzzleVelocity),
        VectorScale(%objectVelocity, %this.projectile.velInheritFactor));

     // Create the projectile object
     %p = new (%this.projectileType)()
     {
        dataBlock = %this.projectile;
        initialVelocity = %muzzleVelocity;
        initialPosition = %obj.getMuzzlePoint(%slot);
        sourceObject = %obj;
        sourceSlot = %slot;
        client = %obj.client;
        sourceClass = %obj.getClassName();
     };
     MissionCleanup.add(%p);

     //Physics: do a castRay, IF this is a weapon which should do this.
     //TEMP! Hard coding it for basic pistol and rifle for first pass, but this  
     //  should be maybe a projectile property(?)
     if ((%this.getName() $= "RyderWeaponImage")||(%this.getName() $= "LurkerWeaponImage"))
     {
        %start = %obj.getEyePoint();
        %start = VectorAdd(%start,VectorScale(%muzzleVector,2));  
        %vec = VectorScale(%muzzleVector,100);

        //TEMP! Define this in the (weapon or the projectile datablock)?
        if (%this.getName() $= "RyderWeaponImage")
           %weaponForce = 70.0;
        else
           %weaponForce = 95.0;

        //echo("casting ray from: " @ %start @ " in direction of " @ %vec);
        %id = physx3CastRay(%start,%vec,1);//0=static,1=dynamic,2=player,3=all
        if ((%id)&&(%id.getClassName() $= "PhysicsShape")) 
        {
           %id.setDynamic(1);
           %id.aitp(%id.getContactBody(),VectorScale(%muzzleVector,%weaponForce));
        }
     }
  }
}

 

Obviously it's still in its raw and cluttered state of "just barely got it working this morning", but it seems to be on the right track anyway.

Link to comment
Share on other sites

  • 2 months later...

Thanks, Dan!


Yeah, sorry, somehow April-May-June just flew by, I did get a fair bit of work done on other areas (most notably, airplanes!) but haven't gotten the time to dig in hard on the physics again. (Summer = work IRL) Hoping to get a break in the next couple of months and hit it again.

Link to comment
Share on other sites

  • 1 month later...

This reminds me, I'm gunna have to in the near-ish future chase down both you and Timmy and we'll see about hashing this stuff out to work for both PhysX and Bullet and get it all purdy'd up and stable.


Been hemming and hawwing about how to do it in the e/c stuff, so when I've got a notion for it, we'll have to try and hash out a plot. I've got some ideas to try and minimize how much of a pain the configuration side of things is (while effective, needing a whole database just to manage bone/joint data strikes me as less than ideal in the long run) so once I get a bit more of a concrete idea, we can try and plot out the physics-y stuff and try and get it ratcheted down.


Gotta get muh physics bro! ;)

Link to comment
Share on other sites

Awesome, good to hear from you on this! I've actually finally been able to carve out a little time on my own here recently to push my stuff forward (look for near future OpenSimEarth updates) but I've been very much wanting to set out the whole physics project up for an in depth critique by the steering committee. I'd like to set it up for a pull request, but I agree, an sqlite database is not a good general solution. I initially used datablocks for all the joints, and for most practical applications that would probably work, but for my own (Ecstasy Motion) use case I wanted to provide too many potential joints at the same time and the load of having them all be datablocks became excessive. For my current work I've gotten so used to having a db handy that anything else is just a PITA and I don't have time :-) but it would be great if an optimal solution could be agreed upon at least, and then potentially could be picked up by a volunteer if I don't ever get around to setting it up.

.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...