In the attachment are the 3 code files that I believe that contain all the ragdoll stuff.
But as I said before, the code is bad code xD
Ill try to explain the essential here:
Im my system I have 2 types of capsules(that always go together), one is for collision detection, the other for collision effects. The dynamic (they act like ghosts) is for detection, the kinematic for the effects.
Creating the capsules: (we will create capsules for the character corpse with right sizes)
Ogre::Skeleton::BoneIterator iterador = jgd::jog_luta[p]->ent->getSkeleton()->getBoneIterator(); // ent is the entity that has the character skeleton
char nomes[20];
Ogre::Bone *b;
while(iterador.hasMoreElements()) //move through all the skeletons bones
{
b = iterador.peekNext();
sprintf(nomes, "bone %d %d",i , p);
if( strcmp(b->getName().c_str() , NAME_OF_THE_BONE_YOU_WANT ) == 0) // here we will create the capsule between the bone we want and his parent
{
Vector3 posparent = jgd::jog_luta[p]->node->getPosition() + jgd::jog_luta[p]->node->getOrientation()*(b->getParent()->_getDerivedPosition())
Vector3 posbone = jgd::jog_luta[p]->node->getPosition() + jgd::jog_luta[p]->node->getOrientation()*(b->_getDerivedPosition());
Vector3 rel = posbone-posparent;
sprintf( nomes, "corpo %d %d",i ,p);
sys::mNxScene->createBody(nomes,new NxOgre::Capsule(tam,rel.length()-5), posparent+0.5*rel,"","mass:10");
sys::mNxScene->getActor(nomes)->raiseBodyFlag(NX_BF_DISABLE_GRAVITY);
sys::mNxScene->getActor(nomes)->raiseActorFlag(NX_AF_DISABLE_RESPONSE);
sys::mNxScene->getActor(nomes)->setLinearDamping(3);
sys::mNxScene->getActor(nomes)->setAngularDamping(3);
sys::mNxScene->getActor(nomes)->setGroup(jgd::jog_luta[p]->ag_corpo);
NxShape* const* s = sys::mNxScene->getActor(nomes)->getNxActor()->getShapes();
(*s)->setGroup(10+p);
(*s)->setMaterial( sys::mNxScene->getMaterialIndex("material_capsulas"));
sprintf( nomes, "corpok %d %d",i ,p);
sys::mNxScene->createBody(nomes,new NxOgre::Capsule(tam,rel.length()-5), posparent+0.5*rel,"","mass:10");
sys::mNxScene->getActor(nomes)->raiseBodyFlag(NX_BF_KINEMATIC);
sys::mNxScene->getActor(nomes)->setGroup(jgd::jog_luta[p]->ag_ossos);
NxShape* const* s2 = sys::mNxScene->getActor(nomes)->getNxActor()->getShapes();
(*s2)->setGroup(20+p);
}
Putting the capsules at the right place (called every loop):
char nomes[20];
int i=0;
Ogre::Bone *b;
while( i < jgd::jog_luta[p]->num_ossos ) //I have just numbered the bones and put them in a vector
{
b = jgd::jog_luta[p]->bones[i] ; // this vector
sprintf(nomes, "bone %d %d",i , p);
if( jgd::jog_luta[p]->ragdoll == 0 && jgd::jog_luta[p]->ragdoll_ant == 0) // lets put the capsules at right place if not in ragdoll mode
{
if(jgd::jog_luta[p]->osso_mao_direita == i || jgd::jog_luta[p]->osso_mao_esquerda == i || jgd::jog_luta[p]->osso_cotovelo_direito == i || jgd::jog_luta[p]->osso_cotovelo_esquerdo== i || jgd::jog_luta[p]->osso_joelho_direito == i || jgd::jog_luta[p]->osso_joelho_esquerdo == i || jgd::jog_luta[p]->osso_pe_direito == i || jgd::jog_luta[p]->osso_pe_esquerdo == i)
{
// Calculating the capsules position, putting them there, and them doing the right rotations
Vector3 posparent = jgd::jog_luta[p]->node->getPosition() + jgd::jog_luta[p]->node->getOrientation()*(b->getParent()->_getDerivedPosition()) ;
Vector3 posbone = jgd::jog_luta[p]->node->getPosition() + jgd::jog_luta[p]->node->getOrientation()*(b->_getDerivedPosition());
Vector3 rel = posbone-posparent;
sprintf( nomes, "corpo %d %d",i ,p);
sys::mNxScene->getActor(nomes)->setGlobalPosition( posparent + 0.5*rel);
Vector3 vecy( 0, 1, 0);
sys::mNxScene->getActor(nomes)->setGlobalOrientation( vecy.getRotationTo(rel) );
sys::mNxScene->getActor(nomes)->setLinearVelocity( Vector3(0,0,0));
sprintf( nomes, "corpok %d %d",i ,p);
sys::mNxScene->getActor(nomes)->moveGlobalPosition( posparent + 0.5*rel);
sys::mNxScene->getActor(nomes)->moveGlobalOrientation( vecy.getRotationTo(rel) );
}
When comes the time to activate the ragdoll, we create the joints and put the capsules in dynamic mode:
void Luta::set_dyn( int p )
{
char nomes[20];
int i=0;
while( i <jgd::jog_luta[p]->num_ossos )
{
if( jgd::jog_luta[p]->osso_mao_direita == i ||
jgd::jog_luta[p]->osso_mao_esquerda == i ||
jgd::jog_luta[p]->osso_cotovelo_direito == i ||
jgd::jog_luta[p]->osso_cotovelo_esquerdo== i ||
jgd::jog_luta[p]->osso_joelho_direito == i ||
jgd::jog_luta[p]->osso_joelho_esquerdo == i ||
jgd::jog_luta[p]->osso_pe_direito == i ||
jgd::jog_luta[p]->osso_pe_esquerdo == i ||
jgd::jog_luta[p]->osso_cabeca == i )
{
sprintf( nomes, "corpo %d %d",i ,p);
sys::mNxScene->getActor(nomes)->clearBodyFlag(NX_BF_DISABLE_GRAVITY);
sys::mNxScene->getActor(nomes)->clearActorFlag(NX_AF_DISABLE_RESPONSE);
}
if( jgd::jog_luta[p]->osso_mao_direita == i ||
jgd::jog_luta[p]->osso_mao_esquerda == i ||
jgd::jog_luta[p]->osso_cotovelo_direito == i ||
jgd::jog_luta[p]->osso_cotovelo_esquerdo== i ||
jgd::jog_luta[p]->osso_joelho_direito == i ||
jgd::jog_luta[p]->osso_joelho_esquerdo == i ||
jgd::jog_luta[p]->osso_pe_direito == i ||
jgd::jog_luta[p]->osso_pe_esquerdo == i)
{
sprintf( nomes, "corpok %d %d",i ,p);
sys::mNxScene->getActor(nomes)->raiseActorFlag(NX_AF_DISABLE_RESPONSE);
}
//example of creation of one of the joints between capsules, the other should be created similarly (choose the best joint to fit that place, spherical, revoltion, etc)
//my parameters here may not make much sense (I learned while doing it, so the initial garbage from tests may be still on)
void Luta::criar_juntas(int p)
{
char nomes[20];
char nomes2[20];
Ogre::Bone *b;
int i=0;
while( i <jgd::jog_luta[p]->num_ossos )
{
printf("%d\n",i);
NxOgre::JointParams jpr;
jpr.setToDefault();
jpr.mHasSwingSpring=1;
jpr.mSwingSpring_Damper=0.0;
jpr.mSwingSpring_Spring=100.0;
jpr.mSwingSpring_Target=0.0;
jpr.mHasSwingLimit=0;
b = jgd::jog_luta[p]->bones[i];
if( jgd::jog_luta[p]->osso_mao_direita == i)
{
printf("a\n");
Vector3 posparent = jgd::jog_luta[p]->node->getPosition() + jgd::jog_luta[p]->node->getOrientation()*(b->getParent()->_getDerivedPosition()) ;
Vector3 pos = jgd::jog_luta[p]->node->getPosition() + jgd::jog_luta[p]->node->getOrientation()*(b->_getDerivedPosition()) ;
Vector3 pos_avo = jgd::jog_luta[p]->node->getPosition() + jgd::jog_luta[p]->node->getOrientation()*(b->getParent()->getParent()->_getDerivedPosition()) ;
sprintf( nomes, "corpo %d %d",i ,p);
jpr.mHasLimits=1;
jpr.mUpperLimit=0.80*NxPi;
jpr.mUpperLimitRestitution=0.2;
jpr.mLowerLimit=0.00*NxPi;
jpr.mLowerLimitRestitution=0.2;
jgd::jog_luta[p]->joint_cotovelo_direito = sys::mNxScene->createSphericalJoint( sys::mNxScene->getActor(nomes), sys::mNxScene->getActor(nomes2), posparent ,jpr);
}
Now comes the dificult part: making the character entity go after the capsules
First you should release your entity of all kinds of animation. Set all its bones manually_controled(true).
Now you have to rotate the bones so the model fit the capsules.
//First i put the root bone in the right place/rotation
void Luta::anim_bones_pre(int p)
{
char nomes[20];
Ogre::Bone *b;
int i=0;
while( i <jgd::jog_luta[p]->num_ossos )
{
b = jgd::jog_luta[p]->bones[i];
b->setPosition( jgd::jog_luta[p]->initial_pos[i] );
b->setOrientation(jgd::jog_luta[p]->initial_ori[i] );
b->_update(1,0);
if(jgd::jog_luta[p]->osso_pai == i)
{
//Vector3 pos_cabeca = jgd::jog_luta[p]->node->getPosition() + jgd::jog_luta[p]->node->getOrientation()*b->_getDerivedPosition() ;
Vector3 pos_pai = jgd::jog_luta[p]->node->getPosition()+ jgd::jog_luta[p]->node->getOrientation()*b->getPosition();
Vector3 pos_node = jgd::jog_luta[p]->node->getPosition();
sprintf( nomes, "corpo %d %d", jgd::jog_luta[p]->osso_cabeca, p);
Vector3 pos_capsule = sys::mNxScene->getActor(nomes)->getGlobalPositionAsOgreVector3();
Vector3 joint1 = jgd::jog_luta[p]->joint_virilha_direita->getGlobalAnchor();
Vector3 joint2 = jgd::jog_luta[p]->joint_virilha_esquerda->getGlobalAnchor();
Vector3 pos_result = jgd::jog_luta[p]->node->getOrientation().Inverse() * ( 0.5*(joint1 + joint2) - pos_node) ;
b->setPosition( pos_result );
Quaternion qrot = sys::mNxScene->getActor(nomes)->getGlobalOrientationAsOgreQuaternion();
b->setOrientation( jgd::jog_luta[p]->node->getOrientation().Inverse() * qrot );
if(jgd::jog_profile[p]->index_personagem_escolhido==3)b->setOrientation( jgd::jog_luta[p]->node->getOrientation().Inverse() * Quaternion(cos(15*3.14/180.0),0,0,sin(15*3.14/180.0))* qrot );
b->_update(1,0);
}
i++;
}
//Then i put the other others in the right place (Put the ancestors in the right place before!)
void Luta::anim_bones( int p )
{
Ogre::Bone *b;
char nomes[20];
int i=0;
while( i <jgd::jog_luta[p]->num_ossos )
{
b = jgd::jog_luta[p]->bones[i];
if(jgd::jog_luta[p]->osso_cotovelo_direito == i)
{
Vector3 pos_anchor = jgd::jog_luta[p]->joint_cotovelo_direito->getGlobalAnchor();
Vector3 pos_parent = jgd::jog_luta[p]->node->getPosition() + jgd::jog_luta[p]->node->getOrientation()*b->getParent()->_getDerivedPosition() ;
Vector3 pos_i = jgd::jog_luta[p]->node->getPosition() + jgd::jog_luta[p]->node->getOrientation()*b->_getDerivedPosition() ;
Quaternion qinv = jgd::jog_luta[p]->node->getOrientation()*b->getParent()->_getDerivedOrientation();
Vector3 vi = qinv.Inverse()*(pos_i - pos_parent) ;
Vector3 vf = qinv.Inverse()*(pos_anchor - pos_parent);
Quaternion qrot = vi.getRotationTo(vf);
b->getParent()->setOrientation( b->getParent()->getOrientation()*qrot );
b->getParent()->_update(1,0);
/*Quaternion quat = jgd::jog_luta[p]->node->getOrientation()*b->getParent()->_getDerivedOrientation();
Vector3 pos_result = pos_anchor - pos_parent;
b->setPosition(quat.Inverse()*pos_result);*/
}
if(jgd::jog_luta[p]->osso_cotovelo_esquerdo == i)
{
Vector3 pos_anchor = jgd::jog_luta[p]->joint_cotovelo_esquerdo->getGlobalAnchor();
Vector3 pos_parent = jgd::jog_luta[p]->node->getPosition() + jgd::jog_luta[p]->node->getOrientation()*b->getParent()->_getDerivedPosition() ;
Vector3 pos_i = jgd::jog_luta[p]->node->getPosition() + jgd::jog_luta[p]->node->getOrientation()*b->_getDerivedPosition() ;
Quaternion qinv = jgd::jog_luta[p]->node->getOrientation()*b->getParent()->_getDerivedOrientation();
Vector3 vi = qinv.Inverse()*(pos_i - pos_parent) ;
Vector3 vf = qinv.Inverse()*(pos_anchor - pos_parent);
Quaternion qrot = vi.getRotationTo(vf);
b->getParent()->setOrientation( b->getParent()->getOrientation()*qrot);
b->getParent()->_update(1,0);
}
if(jgd::jog_luta[p]->osso_joelho_direito == i)
{
Vector3 pos_anchor = jgd::jog_luta[p]->joint_joelho_direito->getGlobalAnchor();
Vector3 pos_parent = jgd::jog_luta[p]->node->getPosition() + jgd::jog_luta[p]->node->getOrientation()*b->getParent()->_getDerivedPosition() ;
Vector3 pos_i = jgd::jog_luta[p]->node->getPosition() + jgd::jog_luta[p]->node->getOrientation()*b->_getDerivedPosition() ;
Quaternion qinv = jgd::jog_luta[p]->node->getOrientation()*b->getParent()->_getDerivedOrientation();
Vector3 vi = qinv.Inverse()*(pos_i - pos_parent) ;
Vector3 vf = qinv.Inverse()*(pos_anchor - pos_parent);
Quaternion qrot = vi.getRotationTo(vf);
b->getParent()->setOrientation( b->getParent()->getOrientation()*qrot);
b->getParent()->_update(1,0);
}
if(jgd::jog_luta[p]->osso_joelho_esquerdo == i)
{
Vector3 pos_anchor = jgd::jog_luta[p]->joint_joelho_esquerdo->getGlobalAnchor();
Vector3 pos_parent = jgd::jog_luta[p]->node->getPosition() + jgd::jog_luta[p]->node->getOrientation()*b->getParent()->_getDerivedPosition() ;
Vector3 pos_i = jgd::jog_luta[p]->node->getPosition() + jgd::jog_luta[p]->node->getOrientation()*b->_getDerivedPosition() ;
Quaternion qinv = jgd::jog_luta[p]->node->getOrientation()*b->getParent()->_getDerivedOrientation();
Vector3 vi = qinv.Inverse()*(pos_i - pos_parent) ;
Vector3 vf = qinv.Inverse()*(pos_anchor - pos_parent);
Quaternion qrot = vi.getRotationTo(vf);
b->getParent()->setOrientation( b->getParent()->getOrientation()*qrot);
b->getParent()->_update(1,0);
}
if( jgd::jog_luta[p]->osso_mao_direita == i ||
jgd::jog_luta[p]->osso_mao_esquerda == i ||
jgd::jog_luta[p]->osso_pe_direito == i ||
jgd::jog_luta[p]->osso_pe_esquerdo == i )
{
sprintf(nomes, "corpo %d %d", i , p);
Vector3 pos_capsule = sys::mNxScene->getActor(nomes)->getGlobalPositionAsOgreVector3();
Vector3 pos_parent = jgd::jog_luta[p]->node->getPosition() + jgd::jog_luta[p]->node->getOrientation()*b->getParent()->_getDerivedPosition() ;
Vector3 pos_i = jgd::jog_luta[p]->node->getPosition() + jgd::jog_luta[p]->node->getOrientation()*b->_getDerivedPosition() ;
Quaternion qinv = jgd::jog_luta[p]->node->getOrientation()*b->getParent()->_getDerivedOrientation();
Vector3 vi = qinv.Inverse()*(pos_i - pos_parent) ;
Vector3 vf = qinv.Inverse()*(pos_capsule - pos_parent);
Quaternion qrot = vi.getRotationTo(vf);
b->getParent()->setOrientation( b->getParent()->getOrientation()*qrot);
b->getParent()->_update(1,0);
/*Quaternion quat = jgd::jog_luta[p]->node->getOrientation()*b->getParent()->_getDerivedOrientation();
Vector3 pos_result = 2.0*(pos_capsule - pos_parent);
b->setPosition(quat.Inverse()*pos_result);*/
}
i++;
}
}
When the kinematic capsules of the character hit the other one in ragdoll mode, they will push his ragdoll capsules in the way the attack should do.
As you may notice, my code is a total mess, but i was totally inexperienced with everything about this project when I started it ( I just knew C before, not C++, so I took some time so I started to make classes with a better design).
Other thing you may notice is that my ragdoll may act weird some times!! ( I dont handle twisting!!!, thats too bad) ( I had problems with the twisting of the physic capsules, I was having dificulties to limit it accordingly, and after all I dint have time to remake it all)
If you're having a hard time trying to understand something, just ask!
(sorry for the bad code again
)
And if you want to know more about my project or more of its code just let me know too! I'm willing to post more stuff if someone is interested. (maybe the character movement handling can be interesting)