|
Is Ragdoll possible
#263115
04/27/09 22:21
04/27/09 22:21
|
Joined: Oct 2003
Posts: 2,194 Saturn
Metal_Thrasher
OP
Expert
|
OP
Expert
Joined: Oct 2003
Posts: 2,194
Saturn
|
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.
-Johnny Thrash
|
|
|
Re: Is Ragdoll possible
[Re: Quad]
#263153
04/28/09 03:34
04/28/09 03:34
|
Joined: Oct 2003
Posts: 2,194 Saturn
Metal_Thrasher
OP
Expert
|
OP
Expert
Joined: Oct 2003
Posts: 2,194
Saturn
|
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?
-Johnny Thrash
|
|
|
Re: Is Ragdoll possible
[Re: Metal_Thrasher]
#263169
04/28/09 06:44
04/28/09 06:44
|
Joined: Oct 2007
Posts: 5,210 İstanbul, Turkey
Quad
Senior Expert
|
Senior Expert
Joined: Oct 2007
Posts: 5,210
İstanbul, Turkey
|
it uses bones, speare models are collision geometry.(you can't(shouldnt) use polygon collision on ragdolls)
3333333333
|
|
|
Re: Is Ragdoll possible
[Re: Quad]
#263172
04/28/09 07:09
04/28/09 07:09
|
Joined: Feb 2008
Posts: 3,232 Australia
EvilSOB
Expert
|
Expert
Joined: Feb 2008
Posts: 3,232
Australia
|
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.
"There is no fate but what WE make." - CEO Cyberdyne Systems Corp. A8.30.5 Commercial
|
|
|
Re: Is Ragdoll possible
[Re: goanna]
#263324
04/29/09 06:15
04/29/09 06:15
|
Joined: Feb 2008
Posts: 3,232 Australia
EvilSOB
Expert
|
Expert
Joined: Feb 2008
Posts: 3,232
Australia
|
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.
"There is no fate but what WE make." - CEO Cyberdyne Systems Corp. A8.30.5 Commercial
|
|
|
Re: Is Ragdoll possible
[Re: EvilSOB]
#263650
05/01/09 04:40
05/01/09 04:40
|
Joined: Feb 2008
Posts: 3,232 Australia
EvilSOB
Expert
|
Expert
Joined: Feb 2008
Posts: 3,232
Australia
|
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! Any questions, fire away. //=======================================================================\\
//= 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);
}
"There is no fate but what WE make." - CEO Cyberdyne Systems Corp. A8.30.5 Commercial
|
|
|
|