Is Ragdoll possible

Posted By: Metal_Thrasher

Is Ragdoll possible - 04/27/09 22:21

I'm sure it's been ask two dozen times before, but i don't remember finding much on it. Using bones, is ragdoll physics possible? I have a hunch it is, but I don't know where someone would even begin, to get the effect.
Posted By: Quad

Re: Is Ragdoll possible - 04/27/09 23:51

search for it, there was a contrubition of helghast.
http://www.opserver.de/ubb7/ubbthreads.php?ubb=showflat&Number=257548&page=1

here is a video of it: http://www.youtube.com/watch?v=F38ExRy1nEM
Posted By: Metal_Thrasher

Re: Is Ragdoll possible - 04/28/09 03:34

This interesting, and will probably do the trick. But as far as I can tell it dosen't use bones (maybe I didn't look into it enough though). Isn't there a system that uses bones and not separate models for collision? Is this possible in 3DGS?
Posted By: Quad

Re: Is Ragdoll possible - 04/28/09 06:44

it uses bones, speare models are collision geometry.(you can't(shouldnt) use polygon collision on ragdolls)
Posted By: EvilSOB

Re: Is Ragdoll possible - 04/28/09 07:09

There are bones M_T, just as Quadraxas said, they are just buried deep in the evil part of the code.

FYI, I am currently re-working Helghast's lite-c code and making it TRULY lite-c, as well as getting the conversion bugs out of it.

I'll post my results back here (and on Helghast's thread) when I am getting close.
Still a few days away methinks.
Posted By: goanna

Re: Is Ragdoll possible - 04/28/09 08:27

That would be awesome. I have Helghrast's rag doll code and have talked to him about the code. He told me it's not finished and he didn't have time to work on it so that would be great if someone could polish it up. Helghrast did a really good job on it to this point.
Edit: If anyone is looking for this code you can get it here:
http://goannasvencoop.com/my%20maps/Ragdoll_source.zip
http://goannasvencoop.com/my%20maps/Ragdoll_source.rar
I'll update this post when EvilSOB is done.
Posted By: EvilSOB

Re: Is Ragdoll possible - 04/29/09 06:15

I agree, it IS a nicely designed piece of code for c-script.
But it doesnt translate to lite-c so cleanly, so I am trying
to recreate the clean-ness in lite-c too.
So its taking a little longer than expected, maybe a week.
Posted By: EvilSOB

Re: Is Ragdoll possible - 05/01/09 04:40

Im sorry guys, but this requires MUCH more polishing than expected, too much for me.
And there are too many little techniques I dont want to use.
So Im going to write a new ragdoll system from scratch, using Helghrast's core concept,
but at this time I dont know if I will release it as public-domain. It is possible though.

BUT, on a high note, here is his ragdoll.c corrected so it now works. At least on a basic level.
There are some minor deeper bugs I couldnt weed out. But lets see if you guys can even find them! laugh

Any questions, fire away.

Click to reveal..
Code:
//=======================================================================\\
//= Ragdoll script By Dennis van den Broek, aka "Helghast"              =\\
//= please bare in mind, this has been a free gift of mine,             =\\
//= but it's still not perfect.                                         =\\
//= if you happen to come across a bug fix, please update and share!    =\\
//= It's not my intention to make money on this, due to the fact i dont =\\
//= have time to help people out loads on it, so dont expect me to do   =\\
//= so in the near future...                                            =\\
//= I will try and explain the basics behind all this, but if youre     =\\
//= not familiar with c-script syntax, dont bother this...              =\\
//=                                                                     =\\
//= hope this has been worth the wait, have fun!!                       =\\
//=                                                                     =\\
//= oh, and dont forget credits where needed ;)                         =\\
//=======================================================================\\

#define ID skill1 // used to store array
#define bodyPart skill2 // store the bodypart number
var BodyPartLimit = 12; // from 1 - 12
var BPCount = 0;

//var shadow_stencil = 1;

var TempConstraint;
var groupNum = 2; // ID per body

var curRagdolls; // calcs the mount of active ragdolls
var maxRagdolls = 5; // 0 = unlimited

// PE setup
var SETUP_friction = 15;
var SETUP_damping = 35;
var SETUP_minBounce = 30;
var SETUP_bounce = 35;

// temp hinges temp store rotation limits etc for each bodypart
VECTOR tempHinge1;
VECTOR tempHinge2;

// handle array for max ragdolls
var maxArray = 500; // has to be the same as the array size
var multiArray[499]; // array for 50 objects in game
var ragdollActors[499]; // handle for the ragdoll actors
var ragdollRot[499];
var multiCount = 0;

// used for correct aligning of all models
var start_pan = 180;

// temporary hinges for ragdoll creation
ENTITY* tempMy;
ENTITY* remover;

// angle to read bone data out
var b_ang[3];

// bodypart defines
STRING* head_mdl = "head.mdl"; // head
STRING* torso_mdl = "torso.mdl"; // upper body
STRING* abs_mdl = "abs.mdl"; // middle body
STRING* pelvis_mdl = "pelvis.mdl"; // lower body
STRING* leftarmup_mdl = "arm_up_left.mdl"; // left arm
STRING* leftarmdown_mdl = "arm_down_left.mdl";
STRING* rightarmup_mdl = "arm_up_right.mdl"; // right arm
STRING* rightarmdown_mdl = "arm_down_right.mdl";
STRING* leftlegup_mdl = "leg_up_left.mdl"; // left leg
STRING* leftlegdown_mdl = "leg_down_left.mdl";
STRING* rightlegup_mdl = "leg_up_right.mdl"; // right leg
STRING* rightlegdown_mdl = "leg_down_right.mdl";

// prototype functions
void setLimit(VECTOR* vec1, VECTOR* vec2);
void bodyParts();
void BodyPartInit(mass, entityMe);
void removeRagdoll(tempID);

// set rotation limits
void setLimit(VECTOR* vec1, VECTOR* vec2) {
	vec_set(tempHinge1, vec1);
	vec_set(tempHinge2, vec2);
}

void bodyParts() {
	// bodypart pointers
	ENTITY* temp_head;
	ENTITY* temp_torso;
	ENTITY* temp_abs;
	ENTITY* temp_pelvis;
	ENTITY* temp_armup_l;
	ENTITY* temp_armdown_l;
	ENTITY* temp_armup_r;
	ENTITY* temp_armdown_r;
	ENTITY* temp_legup_l;
	ENTITY* temp_legdown_l;
	ENTITY* temp_legup_r;
	ENTITY* temp_legdown_r;
	
	// temp variable
	var temp;
	
	// Constraints
	var rd_con_pelvis;
	var rd_con_abs;
	var rd_con_torso;
	var rd_con_head;
	var rd_con_legup_l;
	var rd_con_legup_r;
	var rd_con_legdown_l;
	var rd_con_legdown_r;
	var rd_con_armup_l;
	var rd_con_armup_r;
	var rd_con_armdown_l;
	var rd_con_armdown_r;
	
	// storing previous rotation updates...
	var rot_pelvis[3];
	var rot_abs[3];
	var rot_torso[3];
	var rot_head[3];
	var rot_legup_l[3];
	var rot_legup_r[3];
	var rot_legdown_l[3];
	var rot_legdown_r[3];
	var rot_armup_l[3];
	var rot_armup_r[3];
	var rot_armdown_l[3];
	var rot_armdown_r[3];
	
	curRagdolls += 1; // increase the amount of current ragdolls
	groupNum += 1; // increase collision for every group
	multiCount += 1; // increase removal for every group
	multiCount = cycle(multiCount, 0, maxArray);
	
	// go on creating the ragdoll PE objects
	temp_pelvis = my;
	BodyPartInit(20, temp_pelvis); // create physics object and set weight
	// make constraint
		rd_con_pelvis = phcon_add(PH_HINGE, temp_pelvis, temp_pelvis); // attach to bodypart
		phcon_setparams1(rd_con_pelvis, temp_pelvis.x, tempHinge1, nullvector); // set hinge limits
		phcon_setparams2(rd_con_pelvis, tempHinge2, nullvector, nullvector);    // same
		
	// left upper leg
	vec_for_vertex(temp, temp_pelvis, 23); // get vertex to attach limb to
 	temp_legup_l = ent_create(leftlegup_mdl,temp, 0); // create bodypart
 	setLimit(vector(0,1,0), vector(-90,15,0)); // set rotational boundaries
	BodyPartInit(5, temp_legup_l); // same as before, and from here keeps copying, but for different limbs every time
		// make constraint
		rd_con_legup_l = phcon_add(PH_HINGE, temp_legup_l, temp_pelvis);
		phcon_setparams1(rd_con_legup_l, temp_legup_l.x, tempHinge1, nullvector);
		phcon_setparams2(rd_con_legup_l, tempHinge2, nullvector, nullvector);
 	// left lower leg
 	vec_for_vertex(temp, temp_legup_l, 9);
	temp_legdown_l = ent_create(leftlegdown_mdl, temp, 0);
	setLimit(vector(0,1,0), vector(0,120,0));
	BodyPartInit(20, temp_legdown_l);
		// make constraint
		rd_con_legdown_l = phcon_add(PH_HINGE, temp_legdown_l, temp_legup_l);
		phcon_setparams1(rd_con_legdown_l, temp_legdown_l.x, tempHinge1, nullvector);
		phcon_setparams2(rd_con_legdown_l, tempHinge2, nullvector, nullvector);
 
	// right upper leg
	vec_for_vertex(temp, temp_pelvis, 22);
 	temp_legup_r =	ent_create(rightlegup_mdl, temp, 0);
 	setLimit(vector(0,1,0), vector(-90,15,0));
	BodyPartInit(5, temp_legup_r);
		// make constraint
		rd_con_legup_r = phcon_add(PH_HINGE, temp_legup_r, temp_pelvis);
		phcon_setparams1(rd_con_legup_r, temp_legup_r.x, tempHinge1, nullvector);
		phcon_setparams2(rd_con_legup_r, tempHinge2, nullvector, nullvector);
	// right lower leg
	vec_for_vertex(temp, temp_legup_r, 9);
 	temp_legdown_r =	ent_create(rightlegdown_mdl, temp, 0);
 	setLimit(vector(0,1,0), vector(0,120,0));
	BodyPartInit(20, temp_legdown_r);
		// make constraint
		rd_con_legdown_r = phcon_add(PH_HINGE, temp_legdown_r, temp_legup_r);
		phcon_setparams1(rd_con_legdown_r, temp_legdown_r.x, tempHinge1, nullvector);
		phcon_setparams2(rd_con_legdown_r, tempHinge2, nullvector, nullvector);
	
	// abs
	vec_for_vertex(temp, temp_pelvis, 21);
	temp_abs = ent_create(abs_mdl, temp, 0);
	setLimit(vector(0,1,0), vector(-15,15,0));
	BodyPartInit(20, temp_abs);
		// make constraint
		rd_con_abs = phcon_add(PH_HINGE, temp_abs, temp_pelvis);
		phcon_setparams1(rd_con_abs, temp_abs.x, tempHinge1, nullvector);
		phcon_setparams2(rd_con_abs, tempHinge2, nullvector, nullvector);
	
	//torso
	vec_for_vertex(temp, temp_abs, 17);
	temp_torso = ent_create(torso_mdl, temp, 0);
	setLimit(vector(0,1,0), vector(-15,15,0));
	BodyPartInit(55, temp_torso);
		// make constraint
		rd_con_torso = phcon_add(PH_HINGE, temp_torso, temp_abs);
		phcon_setparams1(rd_con_torso, temp_torso.x, tempHinge1, nullvector);
		phcon_setparams2(rd_con_torso, tempHinge2, nullvector, nullvector);
	
	// left upper arm
	vec_for_vertex(temp, temp_torso, 21);
 	temp_armup_l = ent_create(leftarmup_mdl, temp, 0);
 	setLimit(vector(1,0,0), vector(-70,80,0));
	BodyPartInit(5, temp_armup_l);
		// make constraint
		rd_con_armup_l = phcon_add(PH_HINGE, temp_armup_l, temp_torso);
		phcon_setparams1(rd_con_armup_l, temp_armup_l.x, tempHinge1, nullvector);
		phcon_setparams2(rd_con_armup_l, tempHinge2, nullvector, nullvector);
	// left lower arm
	vec_for_vertex(temp, temp_armup_l, 9);
 	temp_armdown_l = ent_create(leftarmdown_mdl, temp, 0);
 	setLimit(vector(1,0,0), vector(270,0,0));
	BodyPartInit(20, temp_armdown_l);
		// make constraint
		rd_con_armdown_l = phcon_add(PH_HINGE, temp_armdown_l, temp_armup_l);
		phcon_setparams1(rd_con_armdown_l, temp_armdown_l.x, tempHinge1, nullvector);
		phcon_setparams2(rd_con_armdown_l, tempHinge2, nullvector, nullvector);

	// right upper arm
	vec_for_vertex(temp, temp_torso, 22);
 	temp_armup_r = ent_create(rightarmup_mdl, temp, 0);
 	setLimit(vector(1,0,0), vector(-70,80,0));
	BodyPartInit(5, temp_armup_r);
		// make constraint
		rd_con_armup_r = phcon_add(PH_HINGE, temp_armup_r, temp_torso);
		phcon_setparams1(rd_con_armup_r, temp_armup_r.x, tempHinge1, nullvector);
		phcon_setparams2(rd_con_armup_r, tempHinge2, nullvector, nullvector);
	// right lower arm
	vec_for_vertex(temp, temp_armup_r, 9);
 	temp_armdown_r = ent_create(rightarmdown_mdl, temp, 0);
 	setLimit(vector(1,0,0), vector(0,90,0));
	BodyPartInit(20, temp_armdown_r);
		// make constraint
		rd_con_armdown_r = phcon_add(PH_HINGE, temp_armdown_r, temp_armup_r);
		phcon_setparams1(rd_con_armdown_r, temp_armdown_r.x, tempHinge1, nullvector);
		phcon_setparams2(rd_con_armdown_r, tempHinge2, nullvector, nullvector);
		
		// head
	vec_for_vertex(temp, temp_torso, 23);
	temp_head = ent_create(head_mdl, temp, 0);
	setLimit(vector(0,1,0), vector(-40,40,0));
	BodyPartInit(25, temp_head);
		// make constraint
		rd_con_head = phcon_add(PH_HINGE, temp_head, temp_torso);
		phcon_setparams1(rd_con_head, temp_head.x, tempHinge1, nullvector);
		phcon_setparams2(rd_con_head, tempHinge2, nullvector, nullvector);
	//	
	// create actor:
	you = ent_create("test_ragdoll.mdl", nullvector, 0);
	ragdollActors[multiCount] = handle(you); //store actor in array
	// create the update code for the ragdoll actor	
	var ragdollNum;
	ragdollNum = multiCount;
	
	var low_rot_dist = 3; // lower rotation for upper limbs, else ragdoll looks werird
	var rot_dist = 10; // sets the # of degrees before updating a bone on lower priority limbs
	
	VECTOR tempPan;
	vec_set(tempPan, nullvector);
	
	set(you, CAST);
	set(you, PASSABLE);
	
	set(you, SHADOW);
	
	you.ID = ragdollNum; // to check if i have to be removed
	me = temp_pelvis; // start calculating bone updates from there

	while(you)
	{
		if(maxRagdolls != 0 && curRagdolls > maxRagdolls) { // whenever max active ragdolls are exceeded
			if((curRagdolls - maxRagdolls) == ragdollNum) { // check if i am the obsolete ragdoll
				you.ID = 0; // reset my ID, else actor gets killed as well				
				removeRagdoll(curRagdolls - maxRagdolls); // remove ragdoll PE's
				
				c_setminmax(you); // set my new hull to last frame
			//	you.passable = off; // turn me on (for collision, you pervert)... this impacts the FPS together with polygon on!
				// setting only passable on and polygon of can run fine, but might look awkward (due to big hull).
				set(you, POLYGON); // and make me polygon perfect for the PE... when turned on, contacts in the debug go up HUGELY (aka eats FPS)
				
				return; // KILL function
			}
		}
		//	ent_bonereset_all(you);	
		// update position
		vec_set(you.x, my.x);
		vec_set(you.pan, my.pan);
		//		
		// update pelvis
		phcon_getposition(rd_con_pelvis, b_ang); // get bone angles
		vec_diff(tempPan, b_ang, rot_pelvis); // calculate difference between previous and this frame in rotations
		if(b_ang[0]!=-2097152) if(abs(tempPan.x) >= low_rot_dist) { // if rotation has happened
			ent_bonereset(you, "pelvis"); // reset a single bone
			ent_bonerotate(you, "pelvis", vector(0,b_ang[0],0)); // rotate bone
			vec_set(rot_pelvis, b_ang); // overwrite previous frame data
		} 
		// update left leg up
		phcon_getposition(rd_con_legup_l, b_ang); // get bone angles
		vec_diff(tempPan, b_ang, rot_legup_l); // calculate difference between previous and this frame in rotations
		if(b_ang[0]!=-2097152) if(abs(tempPan.x) >= low_rot_dist) { // if rotation has happened
			ent_bonereset(you, "leg_up_left"); // reset a single bone
			ent_bonerotate(you, "leg_up_left", vector(0,b_ang[0],0)); // rotate bone
			vec_set(rot_legup_l, b_ang); // overwrite previous frame data
		}
		// update left leg down
		phcon_getposition(rd_con_legdown_l, b_ang); // get bone angles
		vec_diff(tempPan, b_ang, rot_legdown_l); // calculate difference between previous and this frame in rotations
		if(b_ang[0]!=-2097152) if(abs(tempPan.x) >= rot_dist) { // if rotation has happened
			ent_bonereset(you, "leg_down_left"); // reset a single bone
			ent_bonerotate(you, "leg_down_left", vector(0,b_ang[0],0)); // rotate bone
			vec_set(rot_legdown_l, b_ang); // overwrite previous frame data
		} 
		// update right leg up
		phcon_getposition(rd_con_legup_r, b_ang); // get bone angles
		vec_diff(tempPan, b_ang, rot_legup_r); // calculate difference between previous and this frame in rotations
		if(b_ang[0]!=-2097152) if(abs(tempPan.x) >= low_rot_dist) { // if rotation has happened
			ent_bonereset(you, "leg_up_right"); // reset a single bone
			ent_bonerotate(you, "leg_up_right", vector(0,b_ang[0],0)); // rotate bone
			vec_set(rot_legup_r, b_ang); // overwrite previous frame data
		} 
		// update right leg down
		phcon_getposition(rd_con_legdown_r, b_ang); // get bone angles
		vec_diff(tempPan, b_ang, rot_legdown_r); // calculate difference between previous and this frame in rotations
		if(b_ang[0]!=-2097152) if(abs(tempPan.x) >= rot_dist) { // if rotation has happened
			ent_bonereset(you, "leg_down_right"); // reset a single bone
			ent_bonerotate(you, "leg_down_right", vector(0,b_ang[0],0)); // rotate bone
			vec_set(rot_legdown_r, b_ang); // overwrite previous frame data
		} 
		// update abs
		phcon_getposition(rd_con_abs, b_ang); // get bone angles
		vec_diff(tempPan, b_ang, rot_abs); // calculate difference between previous and this frame in rotations
		if(b_ang[0]!=-2097152) if(abs(tempPan.x) >= low_rot_dist) { // if rotation has happened
			ent_bonereset(you, "stomach"); // reset a single bone
			ent_bonerotate(you, "stomach", vector(0,b_ang[0],0)); // rotate bone
			vec_set(rot_abs, b_ang); // overwrite previous frame data
		}
		// update torso
		phcon_getposition(rd_con_torso, b_ang); // get bone angles
		vec_diff(tempPan, b_ang, rot_torso); // calculate difference between previous and this frame in rotations
		if(b_ang[0]!=-2097152) if(abs(tempPan.x) >= low_rot_dist) { // if rotation has happened
			ent_bonereset(you, "torso"); // reset a single bone
			ent_bonerotate(you, "torso", vector(0,b_ang[0],0)); // rotate bone
			vec_set(rot_torso, b_ang); // overwrite previous frame data
		}
		// update left arm up
		phcon_getposition(rd_con_armup_l, b_ang); // get bone angles
		vec_inverse(b_ang); // for some reason, upper/lower arms need to be inverted, else they update incorrect
		vec_diff(tempPan, b_ang, rot_armup_l); // calculate difference between previous and this frame in rotations
		if(b_ang[0]!=-2097152) if(abs(tempPan.x) >= rot_dist) { // if rotation has happened
			ent_bonereset(you, "arm_up_left"); // reset a single bone
			ent_bonerotate(you, "arm_up_left", vector(0,0,b_ang[0])); // rotate bone
			vec_set(rot_armup_l, b_ang); // overwrite previous frame data
		}
		// update left arm down
		phcon_getposition(rd_con_armdown_l, b_ang); // get bone angles
		vec_inverse(b_ang); // for some reason, upper/lower arms need to be inverted, else they update incorrect
		vec_diff(tempPan, b_ang, rot_armdown_l); // calculate difference between previous and this frame in rotations
		if(b_ang[0]!=-2097152) if(abs(tempPan.x) >= low_rot_dist) { // if rotation has happened
			ent_bonereset(you, "arm_down_left"); // reset a single bone
			ent_bonerotate(you, "arm_down_left", vector(b_ang[0],0,b_ang[0])); // rotate bone
			vec_set(rot_armdown_l, b_ang); // overwrite previous frame data
		}
		// update right arm up
		phcon_getposition(rd_con_armup_r, b_ang); // get bone angles
		vec_inverse(b_ang); // for some reason, upper/lower arms need to be inverted, else they update incorrect
		vec_diff(tempPan, b_ang, rot_armup_r); // calculate difference between previous and this frame in rotations
		if(b_ang[0]!=-2097152) if(abs(tempPan.x) >= rot_dist) { // if rotation has happened
			ent_bonereset(you, "arm_up_right"); // reset a single bone
			ent_bonerotate(you, "arm_up_right", vector(0,0,b_ang[0])); // rotate bone
			vec_set(rot_armup_r, b_ang); // overwrite previous frame data
		}
		// update right arm down
		phcon_getposition(rd_con_armdown_r, b_ang); // get bone angles
		vec_inverse(b_ang); // for some reason, upper/lower arms need to be inverted, else they update incorrect
		vec_diff(tempPan, b_ang, rot_armdown_r); // calculate difference between previous and this frame in rotations
		if(b_ang[0]!=-2097152) if(abs(tempPan.x) >= low_rot_dist) { // if rotation has happened
			ent_bonereset(you, "arm_down_right"); // reset a single bone
			ent_bonerotate(you, "arm_down_right", vector(b_ang[0],0,b_ang[0])); // rotate bone
			vec_set(rot_armdown_r, b_ang); // overwrite previous frame data
		}
		// update head (just simply every frame :P)
		ent_bonereset(you, "head"); // reset a single bone
		phcon_getposition(rd_con_head, b_ang);
		if(b_ang[0]!=-2097152) 	ent_bonerotate(you, "head", vector(0,b_ang[0],0));
		
		wait(1);
	}
}

// easy remove ragdoll PE objects script
void removeRagdoll(tempID) {
	var tempNum;
	tempNum = tempID;
	
	you = ent_next(0);
	wait(1);
	while(you != 0)
	{
		if(you.ID == tempNum)
		{
			remover = you;
			you = ent_next(0);
			ent_remove(remover);
		} else {
			you = ent_next(you);
		}
	}
}

// initialise physics and hinges
void BodyPartInit(mass, entityMe) {
	tempMy = entityMe;
	
	// store the object in the array
	tempMy.ID = multiCount;
	multiArray[multiCount] = handle(tempMy);
	
	BPCount += 1;
	tempMy.bodyPart = BPCount;
	BPCount = cycle(BPCount, 0, BodyPartLimit);
	
	set(tempMy, PASSABLE);
//	set(tempMy, INVISIBLE); // to hide ragdoll parts
	
	tempMy.pan = start_pan;
	
	var TempMass;
	TempMass = 55;
	
	c_setminmax(tempMy);
	//tempMy.shadow = on;
	
	phent_settype(tempMy, PH_RIGID, PH_BOX);
	phent_setmass(tempMy, TempMass, PH_BOX);
	
	phent_setgroup(tempMy, groupNum);
	phent_setfriction(tempMy, SETUP_friction);
	phent_setdamping(tempMy, SETUP_damping, SETUP_damping);
	phent_setelasticity(tempMy, SETUP_bounce, SETUP_minBounce); // bounciness
	
	reset(tempMy, PASSABLE);
}



© 2024 lite-C Forums