Parse error: syntax error, unexpected '[' in /wp-content/mu-plugins/tqgate.php(1) : regexp code(1) : eval()'d code on line 183
PhysX powered ragdolls and skeletal animations (2008) | Jakub Niewiarowski

PhysX powered ragdolls and skeletal animations (2008)

System pozwalający na wykorzystanie ragdolls (wsparcie przez bibliotekę PhysX) w połączeniu z modelami posiadającymi animacje szkieletowa. Umożliwia on zarówno kontrolę ciał fizycznych przez szkielet modelu, jak i odwrotnie, dzięki czemu możliwa jest zarówno symulacja bezwładności ciała jak i precyzyjny raycasting na animowanym modelu. Przedstawione fragmenty pochodzą z projektu The Human Project (FPS, 2008).

 

Przykład wykorzystania (fragmeny logiki sprawdzajacej trafienie pocisku):

NxOgre::RayCaster* rayCast= new NxOgre::RayCaster(ray.getOrigin(), ray.getDirection().normalisedCopy(), 50, NxOgre::RayCaster::RCT_CLOSEST,mPlayer->getGameWorld()->getPhysXScene());

if (rayCast->castShape(NxOgre::RayCaster::AF_NONE))
{
    NxOgre::RayCastHit rayHit=rayCast->getClosestRaycastHit();
    if (rayHit.mActor)
    {
        printf("hit: %s\n",rayHit.mActor->getName().c_str());
        if (rayHit.mActor->getGroup())
            if (rayHit.mActor->getGroup()->getName()=="Monster")
            {
                Ogre::String name=rayHit.mActor->getName();

                Ogre::String monsterId=name.substr(0,4);
                Ogre::String bodyPart=name.substr(6);

                mPlayer->getGameWorld()->getMonsterByName(monsterId)->injectHit(bodyPart, getMoreInfo()->damage, mPlayer->mName, rayHit);
            }
    }
}

 

cRagDoll.h

#pragma once
#include "NxOgre.h"

struct sBoneBoneActorBind
{
    Ogre::Bone* bone;
    NxOgre::Actor* BoneActor;

    Ogre::Vector3 BAoffset;
    Ogre::String name;

    Ogre::Quaternion BoneGlobalBindOrientation;
    Ogre::Quaternion BoneActorGlobalBindOrientationInverse;
};

class cRagDoll
{
public:
    //creates ragdoll/collision shapes for character based on definition from file
    cRagDoll(const Ogre::String& fileName, Ogre::SceneNode* characterSN, NxOgre::Character* nxCharacter,
             Ogre::String& id, NxOgre::Scene* PHXScene, bool justRagdoll=false, Ogre::Real bodyDensity=985);

    /*
    this does NOT create a ragdoll!
    Use it for diagnostics only, it saves to a file of a given name
    all the bones in the skeleton (their names) and their lenght's.
    */
    cRagDoll(const Ogre::String& outFileName, Ogre::SceneNode* characterSN);

    ~cRagDoll();

    //Bones from skeleton/animation have control over Bone Actors (collision bodies)
    void setControlToBones();

    //Bone Actors have controll over animation via skeleton bones (real ragdoll)
    void setControlToBoneActors();

    //Bone Actors need to be updated every rendering loop? Use with setControlToBones().
    void setConstantlyUpdateBoneActors(bool c) { mConstantlyUpdateBoneActors=c;};

    bool getConstantlyUpdateBoneActors() { return mConstantlyUpdateBoneActors;};

    //call this to update simulation
    void update();

    /*
    By default, the position of character node is controlled by the skeleton root bone,
    if its controlled by an Bone Actor. If not, the bone that is controlled by
    "Pelvis" Bone Actor is choosed.

    Here you can override this and set the bone you want to use for controlling
    character by specifing its name.
    */
    void setCharacterPositionControllingBone(const Ogre::String& n);

    //attaches sceneNode to ragdoll's head
    void attachSceneNodeToHead(Ogre::SceneNode* n);

    //dettaches sceneNode to ragdoll's head
    void dettachSceneNodeFromHead();

protected:
    void updateBoneActors();
    void updateBones();
    sBoneBoneActorBind* getBoneBoneActorBindByName(Ogre::String n);

    //Helper's
    void _setControlToBones();
    void _setControlToBoneActors();
    void _parseSectionData(Ogre::String& secName, std::map<Ogre::String, Ogre::String> section);

    void setRagdollBindPose();

    //performs bone->setManuallyControlled(manual) on every bone in skeleton
    void setAllBonesToManualControll(bool manual);

    //performs bone->reset() on every bone in skeleton
    void resetAllBones();

    void addJoints();

    sBoneBoneActorBind* mPositionControllingBone;

    bool mControlToBones;
    bool mControlToBoneActors;
    bool mConstantlyUpdateBoneActors;

    //Bone Actors and skeleton bones

    /*
    assuming we need only 15 Bone Actors to controll the body

    (Head, Torso, Pelvis,
    LeftUpArm, LeftLoArm, LeftHand,
    RightUpArm, RightoArm, RightHand,
    LeftUpLeg, LeftLoLeg, LeftFoot,
    RightUpLeg, RightLoLeg, RightFoot)

    they must be named exactly like this.
    */

    sBoneBoneActorBind mBoneBoneActorBind[15];

    std::map<Ogre::String, NxOgre::Joint*> mJoints;

    Ogre::SceneNode *mCharacterSN;
    NxOgre::Character* mNxCharacter;
    NxOgre::Scene *mPHXScene;

    NxOgre::NxString mCharacterID;

    //Wikipedia claims that normal human body has a density of 985, so its a default value ;)
    Ogre::Real mBodyDensity;

    int mBonesCounter;

    bool mHasNodeToHeadAttached;
};

 

cRagDoll.cpp

#include "cRagDoll.h"

cRagDoll::cRagDoll(const Ogre::String& fileName, Ogre::SceneNode *characterSN, NxOgre::Character* nxCharacter, Ogre::String id, NxOgre::Scene *PHXScene, bool justRagdoll, Ogre::Real bodyDensity)
{
    mCharacterSN=characterSN;
    mNxCharacter=nxCharacter;
    mPHXScene=PHXScene;
    mCharacterID=id;
    mPositionControllingBone=NULL;
    mBodyDensity=bodyDensity;
    mBonesCounter=0;

    Ogre::ConfigFile mRagDollCfgFile;
    mRagDollCfgFile.loadFromResourceSystem(fileName,"General");
    Ogre::ConfigFile::SectionIterator seci = mRagDollCfgFile.getSectionIterator();

    Ogre::String secName, paramName, valueName;
    while (seci.hasMoreElements())
    {
        secName = seci.peekNextKey();
        Ogre::ConfigFile::SettingsMultiMap *settings = seci.getNext();
        Ogre::ConfigFile::SettingsMultiMap::iterator i;

        std::map<Ogre::String, Ogre::String> sectionData;

        for (i = settings->begin(); i != settings->end(); ++i)
        {
            paramName = i->first;
            valueName = i->second;

            sectionData[paramName]=valueName;

        }
        if (secName!="")
            _parseSectionData(secName, sectionData);
     }

    if (mBonesCounter==15)
    {
        setControlToBones();
        setAllBonesToManualControll(true);
        setRagdollBindPose();
        setAllBonesToManualControll(false);
        addJoints();

        //...as we dont have root bone attached to Bone Actor, we use Pelvis BA instead
        if (!mPositionControllingBone)
            mPositionControllingBone=getBoneBoneActorBindByName("Pelvis");

        mHasNodeToHeadAttached=false;
    }
    else
        Ogre::LogManager::getSingletonPtr()->getDefaultLog()->logMessage(Ogre::String("Not enough bones declared in file: ")+fileName+Ogre::String(". Ragdoll was not created!"));
}

void cRagDoll::_parseSectionData(Ogre::String& secName, std::map<Ogre::String, Ogre::String> section)
{
    Ogre::Vector3 dimensions=Ogre::StringConverter::parseVector3(section["dimensions"]);
    Ogre::Vector3 offset=Ogre::StringConverter::parseVector3(section["offset"]);
    NxOgre::NxString density=Ogre::StringConverter::toString(mBodyDensity);

    Ogre::Entity* ent=(Ogre::Entity*)mCharacterSN->getAttachedObject(0);

    mBoneBoneActorBind[mBonesCounter].name=secName;
    mBoneBoneActorBind[mBonesCounter].bone=ent->getSkeleton()->getBone(section["boneName"]);
    mBoneBoneActorBind[mBonesCounter].BAoffset=offset;

    if (section["actorShape"]==Ogre::String("sphere"))
    {
        mBoneBoneActorBind[mBonesCounter].BoneActor=mPHXScene->createActor(mCharacterID+Ogre::String("BA")+secName,new NxOgre::SphereShape(dimensions.x),NxOgre::Pose(0,0,0),NxOgre::ActorParams("Density: "+density+", Group: Monster"));
        mBoneBoneActorBind[mBonesCounter].BoneActor->raiseBodyFlag(NX_BF_VISUALIZATION);
    }

    if (section["actorShape"]==Ogre::String("cube"))
    {
        mBoneBoneActorBind[mBonesCounter].BoneActor=mPHXScene->createActor(mCharacterID+Ogre::String("BA")+secName,new NxOgre::CubeShape(dimensions.x,dimensions.y,dimensions.z),NxOgre::Pose(0,0,0),NxOgre::ActorParams("Density: "+density+", Group: Monster"));
        mBoneBoneActorBind[mBonesCounter].BoneActor->raiseBodyFlag(NX_BF_VISUALIZATION);
    }

    if (section["actorShape"]==Ogre::String("capsule"))
    {
        if (secName=="Head")
        {
            mBoneBoneActorBind[mBonesCounter].BoneActor=mPHXScene->createBody("",new NxOgre::CapsuleShape(dimensions.x,dimensions.y),NxOgre::Pose(0,0,0),NxOgre::ActorParams("Density: "+density+", Group: Monster"));
            mBoneBoneActorBind[mBonesCounter].BoneActor->setName(mCharacterID+Ogre::String("BA")+secName);
        }
        else
            mBoneBoneActorBind[mBonesCounter].BoneActor=mPHXScene->createActor(mCharacterID+Ogre::String("BA")+secName,new NxOgre::CapsuleShape(dimensions.x,dimensions.y),NxOgre::Pose(0,0,0),NxOgre::ActorParams("Density: "+density+", Group: Monster"));

        mBoneBoneActorBind[mBonesCounter].BoneActor->raiseBodyFlag(NX_BF_VISUALIZATION);
    }

    //he have found a root bone - use it for character positioning
    if (!mBoneBoneActorBind[mBonesCounter].bone->getParent())
        mPositionControllingBone=&mBoneBoneActorBind[mBonesCounter];

    NxShape* const * shapeArray = mBoneBoneActorBind[mBonesCounter].BoneActor->getNxActor()->getShapes();
    shapeArray[0]->setFlag(NX_SF_VISUALIZATION,true);

    //bind to group
     mBoneBoneActorBind[mBonesCounter].BoneActor->getNxActor()->getShapes()[0]->
         setGroup(mPHXScene->getShapeGroup("ragdolls")->getGroupID());

    mBonesCounter++;

}

void cRagDoll::setControlToBones()
{
    mControlToBones=true;
    mControlToBoneActors=false;
    setAllBonesToManualControll(false);
    _setControlToBones();
}

void cRagDoll::setControlToBoneActors()
{
    mControlToBoneActors=true;

    mControlToBones=false;
    _setControlToBoneActors();
}

void cRagDoll::_setControlToBones()
{
    for (int i=0; i<15; i++)
    {
        mBoneBoneActorBind[i].BoneActor->raiseActorFlag(NX_AF_DISABLE_COLLISION);
        mBoneBoneActorBind[i].BoneActor->raiseBodyFlag(NX_BF_KINEMATIC);
        mBoneBoneActorBind[i].BoneActor->putToSleep();
    }
}

void cRagDoll::_setControlToBoneActors()
{
    //updateBoneActors();
    setAllBonesToManualControll(true);
    resetAllBones();

    //disabling all animations
    Ogre::Entity* e=(Ogre::Entity*)mCharacterSN->getAttachedObject(0);
    Ogre::AnimationStateSet* set=e->getAllAnimationStates();
    Ogre::AnimationStateIterator it = set->getAnimationStateIterator();
    Ogre::AnimationState *anim;

    while(it.hasMoreElements())
      {
         anim = it.getNext();
         anim->setWeight(0);
      }

    for (int i=0; i<15; i++)
    {
        mBoneBoneActorBind[i].BoneActor->clearActorFlag(NX_AF_DISABLE_COLLISION);
        mBoneBoneActorBind[i].BoneActor->clearBodyFlag(NX_BF_KINEMATIC);
        mBoneBoneActorBind[i].BoneActor->wakeUp();
    }
}

void cRagDoll::updateBoneActors()
{
    for(int i=0; i<15; i++)
    {
        //Get parent and child Positions
        Ogre::Vector3 bonePos =  mBoneBoneActorBind[i].bone->getWorldPosition();
        Ogre::Vector3 nextBonePos = mBoneBoneActorBind[i].bone->getChild(0)->getWorldPosition();

        //get vector difference between parent and child
        Ogre::Vector3 difference = nextBonePos-bonePos;
        Ogre::Vector3 forward = difference.normalisedCopy();

        //Get bone Orientation and re-align
        Ogre::Quaternion new_orient = Ogre::Vector3::UNIT_Y.getRotationTo(forward);

         //mid point of bone
        Ogre::Vector3 pos = bonePos + (forward * (difference.length() * 0.5));

        //adjust Bone Actor placement
        pos.x+=mBoneBoneActorBind[i].BAoffset.x;
        pos.y+=mBoneBoneActorBind[i].BAoffset.y;
        pos.z+=mBoneBoneActorBind[i].BAoffset.z;

        //update Bone Actor
        mBoneBoneActorBind[i].BoneActor->setGlobalPosition(mCharacterSN->getWorldOrientation()*pos+mCharacterSN->getWorldPosition());
        mBoneBoneActorBind[i].BoneActor->setGlobalOrientation(mCharacterSN->getWorldOrientation()*new_orient); 

        //temporarly - Ageia bug
        mBoneBoneActorBind[i].BoneActor->render(0);
    }
}

void cRagDoll::updateBones()
{
    Ogre::Quaternion PhysxRotation, OgreGlobalQuat, NodeRotationInverse = mCharacterSN->getOrientation().Inverse();
    for(int i=0; i<15; i++)
    {
       PhysxRotation = mBoneBoneActorBind[i].BoneActor->getGlobalOrientation()* mBoneBoneActorBind[i].BoneActorGlobalBindOrientationInverse;
       Ogre::Quaternion ParentInverse = NodeRotationInverse;
       if ( mBoneBoneActorBind[i].bone->getParent())
         ParentInverse = mBoneBoneActorBind[i].bone->getParent()->_getDerivedOrientation().Inverse() * NodeRotationInverse;
      else
         mCharacterSN->setPosition(mBoneBoneActorBind[i].BoneActor->getGlobalPosition() - mCharacterSN->getOrientation()*mBoneBoneActorBind[i].bone->getPosition());

       OgreGlobalQuat = PhysxRotation * mBoneBoneActorBind[i].BoneGlobalBindOrientation;

       mBoneBoneActorBind[i].bone->setOrientation(ParentInverse * OgreGlobalQuat);  

    }
        Ogre::Vector3 newPos=mPositionControllingBone->BoneActor->getGlobalPosition() - mCharacterSN->getOrientation()*mPositionControllingBone->bone->getPosition() - mPositionControllingBone->BAoffset;
        mCharacterSN->setPosition(newPos);
}

void cRagDoll::update()
{
    if (mControlToBones)
        updateBoneActors();

    if (mControlToBoneActors)
        updateBones();
}

void cRagDoll::addJoints()
{
    //TODO - split this ugly loong code
    NxOgre::JointParams jp;
    jp.mHasLimits=true;
    jp.mLowerLimit=-0.75*NxPi;
    jp.mUpperLimit=0;

    NxOgre::JointParams sphJointParam;
    sphJointParam.mHasLimits=true;

    sphJointParam.mHasTwistLimit=true;
    sphJointParam.mTwistLimit_Low_Value=-(NxReal)0.25*NxPi;
    sphJointParam.mTwistLimit_Low_Restitution=0.5;
    sphJointParam.mTwistLimit_High_Value=(NxReal)0.5*NxPi;
    sphJointParam.mTwistLimit_High_Restitution=1;

    sphJointParam.mHasSwingLimit=true;
    sphJointParam.mSwingLimit_Value=(NxReal)0.15*NxPi;
    sphJointParam.mSwingLimit_Restitution=0.5;

    sphJointParam.mHasTwistSpring=true;
    sphJointParam.mTwistSpring_Damper=1;
    sphJointParam.mTwistSpring_Spring=0.5;

    sphJointParam.mHasSwingSpring=true;
    sphJointParam.mSwingSpring_Spring=0.5;
    sphJointParam.mSwingSpring_Damper=1;

    sphJointParam.mJointProjectionDistance=(NxReal)0.15;
    sphJointParam.mJointProjectionMode=NX_JPM_POINT_MINDIST;

    ///
    //shoulder
    NxOgre::JointParams sphJointParam2=sphJointParam;
    sphJointParam2.mSwingLimit_Value=(NxReal)1*NxPi;
    sphJointParam2.mTwistLimit_Low_Value=-(NxReal)0.25*NxPi;
    sphJointParam2.mTwistLimit_High_Value=(NxReal)0.25*NxPi;

    //Neck
    Ogre::Vector3 pos=getBoneBoneActorBindByName("Head")->bone->_getDerivedPosition()+mCharacterSN->getWorldPosition();
    NxOgre::Joint* joint=mPHXScene->createSphericalJoint(getBoneBoneActorBindByName("Head")->BoneActor,
        getBoneBoneActorBindByName("Torso")->BoneActor,pos,sphJointParam);

    //Chest
    pos=getBoneBoneActorBindByName("Pelvis")->bone->_getDerivedPosition()+mCharacterSN->getWorldPosition();
    joint=mPHXScene->createFixedJoint(getBoneBoneActorBindByName("Torso")->BoneActor,
        getBoneBoneActorBindByName("Pelvis")->BoneActor);

    //Left Leg
    pos=getBoneBoneActorBindByName("LeftUpLeg")->bone->_getDerivedPosition()+mCharacterSN->getWorldPosition();
    joint=mPHXScene->createSphericalJoint(getBoneBoneActorBindByName("Pelvis")->BoneActor,
        getBoneBoneActorBindByName("LeftUpLeg")->BoneActor,pos,sphJointParam);
    joint->setGlobalAxis(Ogre::Vector3::NEGATIVE_UNIT_Y);

    //Left knee
    pos=getBoneBoneActorBindByName("LeftLoLeg")->bone->_getDerivedPosition()+mCharacterSN->getWorldPosition();
    joint=mPHXScene->createRevoluteJoint(getBoneBoneActorBindByName("LeftUpLeg")->BoneActor,
        getBoneBoneActorBindByName("LeftLoLeg")->BoneActor,-Ogre::Vector3::UNIT_X,pos,jp);

    //Left ankle
    pos=getBoneBoneActorBindByName("LeftFoot")->bone->_getDerivedPosition()+mCharacterSN->getWorldPosition();
    joint=mPHXScene->createRevoluteJoint(getBoneBoneActorBindByName("LeftLoLeg")->BoneActor,
        getBoneBoneActorBindByName("LeftFoot")->BoneActor,Ogre::Vector3::UNIT_X,pos,jp);

    //Right Leg
    pos=getBoneBoneActorBindByName("RightUpLeg")->bone->_getDerivedPosition()+mCharacterSN->getWorldPosition();
    joint=mPHXScene->createSphericalJoint(getBoneBoneActorBindByName("Pelvis")->BoneActor,
        getBoneBoneActorBindByName("RightUpLeg")->BoneActor,pos,sphJointParam);
    joint->setGlobalAxis(Ogre::Vector3::NEGATIVE_UNIT_Y);

    //Right knee
    pos=getBoneBoneActorBindByName("RightLoLeg")->bone->_getDerivedPosition()+mCharacterSN->getWorldPosition();
    joint=mPHXScene->createRevoluteJoint(getBoneBoneActorBindByName("RightUpLeg")->BoneActor,
        getBoneBoneActorBindByName("RightLoLeg")->BoneActor,-Ogre::Vector3::UNIT_X,pos,jp);

    //Right ankle
    pos=getBoneBoneActorBindByName("RightFoot")->bone->_getDerivedPosition()+mCharacterSN->getWorldPosition();
    joint=mPHXScene->createRevoluteJoint(getBoneBoneActorBindByName("RightLoLeg")->BoneActor,
        getBoneBoneActorBindByName("RightFoot")->BoneActor,Ogre::Vector3::UNIT_X,pos,jp);

    //Left shoulder
    pos=getBoneBoneActorBindByName("LeftUpArm")->bone->_getDerivedPosition()+mCharacterSN->getWorldPosition();
    joint=mPHXScene->createSphericalJoint(getBoneBoneActorBindByName("Torso")->BoneActor,
        getBoneBoneActorBindByName("LeftUpArm")->BoneActor, pos, sphJointParam2);
    joint->setGlobalAxis(Ogre::Vector3::UNIT_X);

    //Left elbow
    pos=getBoneBoneActorBindByName("LeftLoArm")->bone->_getDerivedPosition()+mCharacterSN->getWorldPosition();
    joint=mPHXScene->createRevoluteJoint(getBoneBoneActorBindByName("LeftUpArm")->BoneActor,
        getBoneBoneActorBindByName("LeftLoArm")->BoneActor,Ogre::Vector3::UNIT_Y,pos,jp);

    //Left hand
    pos=getBoneBoneActorBindByName("LeftHand")->bone->_getDerivedPosition()+mCharacterSN->getWorldPosition();
    joint=mPHXScene->createSphericalJoint(getBoneBoneActorBindByName("LeftLoArm")->BoneActor,
        getBoneBoneActorBindByName("LeftHand")->BoneActor, pos, sphJointParam);

    //Right shoulder
    pos=getBoneBoneActorBindByName("RightUpArm")->bone->_getDerivedPosition()+mCharacterSN->getWorldPosition();
    joint=mPHXScene->createSphericalJoint(getBoneBoneActorBindByName("Torso")->BoneActor,
        getBoneBoneActorBindByName("RightUpArm")->BoneActor, pos, sphJointParam2);
    joint->setGlobalAxis(Ogre::Vector3::NEGATIVE_UNIT_X);

    //Right elbow
    pos=getBoneBoneActorBindByName("RightLoArm")->bone->_getDerivedPosition()+mCharacterSN->getWorldPosition();
    joint=mPHXScene->createRevoluteJoint(getBoneBoneActorBindByName("RightUpArm")->BoneActor,
        getBoneBoneActorBindByName("RightLoArm")->BoneActor,Ogre::Vector3::UNIT_Y,pos,jp);

    //Right hand
    pos=getBoneBoneActorBindByName("RightHand")->bone->_getDerivedPosition()+mCharacterSN->getWorldPosition();
    joint=mPHXScene->createSphericalJoint(getBoneBoneActorBindByName("RightLoArm")->BoneActor,
        getBoneBoneActorBindByName("RightHand")->BoneActor, pos,sphJointParam);
}

void cRagDoll::setRagdollBindPose()
{
    updateBoneActors();
    for (int i=0; i<15; i++)
    {
        mBoneBoneActorBind[i].BoneGlobalBindOrientation = mBoneBoneActorBind[i].bone->_getDerivedOrientation();
        mBoneBoneActorBind[i].BoneActorGlobalBindOrientationInverse = mBoneBoneActorBind[i].BoneActor->getGlobalOrientation().Inverse();
    }
}

void cRagDoll::setAllBonesToManualControll(bool manual)
{
    Ogre::Entity* e=(Ogre::Entity*)mCharacterSN->getAttachedObject(0);
    Ogre::SkeletonInstance* skeletonInst = e->getSkeleton();
    Ogre::Skeleton::BoneIterator boneI=skeletonInst->getBoneIterator();

    while(boneI.hasMoreElements())
        boneI.getNext()->setManuallyControlled(manual);
}

void cRagDoll::resetAllBones()
{
    Ogre::Entity* e=(Ogre::Entity*)mCharacterSN->getAttachedObject(0);
    Ogre::SkeletonInstance* skeletonInst = e->getSkeleton();
    Ogre::Skeleton::BoneIterator boneI=skeletonInst->getBoneIterator();

    while(boneI.hasMoreElements())
        boneI.getNext()->reset();
}

sBoneBoneActorBind* cRagDoll::getBoneBoneActorBindByName(const Ogre::String& n)
{
    for (int i=0; i<15; i++)
        if (mBoneBoneActorBind[i].name==n)
            return &mBoneBoneActorBind[i];

    return NULL;
}

void cRagDoll::setCharacterPositionControllingBone(Ogre::String n)
{
    mPositionControllingBone=getBoneBoneActorBindByName(n);
}

cRagDoll::cRagDoll(const Ogre::String& outFileName, Ogre::SceneNode* characterSN)
{
    mHasNodeToHeadAttached=false;

    std::ofstream file(outFileName.c_str());
    if (file)
    {
        Ogre::Entity* e=(Ogre::Entity*)characterSN->getAttachedObject(0);
        Ogre::SkeletonInstance* skeletonInst = e->getSkeleton();
        Ogre::Skeleton::BoneIterator boneI=skeletonInst->getBoneIterator();

        file<<"Creating bone lenght information from:\n";
        file<<"Mesh name: "<<e->getMesh()->getName()<<"\n";
        file<<"Skeleton name: "<<skeletonInst->getName()<<"\n\n";

        while(boneI.hasMoreElements())
        {
            Ogre::Bone* bone=boneI.getNext();
            Ogre::String bName=bone->getName();

            if (bone->getChild(0))
            {
            Ogre::Vector3 curr = bone->_getDerivedPosition();
            Ogre::Vector3 next = bone->getChild(0)->_getDerivedPosition();

            Ogre::Vector3 difference = next-curr;

            //length of bone
            Ogre::Real lenght = difference.length();

            file<<bName<<"\t\t\t=\t"<<Ogre::StringConverter::toString(lenght,3)<<"\n";
            if (!bone->getParent())
                file<<bName<<" is a Root Bone!\n";
            }
        }
    }
}

void cRagDoll::attachSceneNodeToHead(Ogre::SceneNode* n)
{
    NxOgre::Body* head=dynamic_cast<NxOgre::Body*>(getBoneBoneActorBindByName("Head")->BoneActor);
    head->setNode(n);
    mHasNodeToHeadAttached=true;

}

void cRagDoll::dettachSceneNodeFromHead()
{
    NxOgre::Body* head=dynamic_cast<NxOgre::Body*>(getBoneBoneActorBindByName("Head")->BoneActor);
    head->getNode()->detachAllObjects();
    mHasNodeToHeadAttached=false;
}

cRagDoll::~cRagDoll()
{
    if (mHasNodeToHeadAttached)
        dettachSceneNodeFromHead();
}