About Store Forum Documentation Contact



Post Reply 
Ragdoll cloth does not follow skeleton
Author Message
Skykill Offline
Member

Post: #1
Ragdoll cloth does not follow skeleton
Hello, when i create a cloth it work fine:
   

But, when the player move it do this:
   

In the wireframe view i have found it was the ragdoll cloth that won't follow correctly the skeleton
   

Here is my code:

PHP Code:
void Player::createClothParam()
{
    
// setup cloth parameters
    
ClothParam.flag               =0;
    
ClothParam.thickness          =0.15f;
    
ClothParam.bending            =0.6f;
    
ClothParam.stretching         =0.0f;
    
ClothParam.damping            =0.6f;
    
ClothParam.response           =0.0f;
    
ClothParam.attachment_response=0.0f;
}

void Player::createCloth(Game::ObjParams &objItemClassInfo::TYPE cTypeStr sCloth)
{
    
// now let's create the cloth and the helper ragdoll
    // let's start by creating the ragdoll
    
{
        switch(
cType)
        {
        case 
ItemClassInfo::HAT 
            
i_hat_kinematic_ragdoll.create(cskel1true      )  // create the helper ragdoll as kinematic
                
.group (AG_KINEMATIC_RAGDOLL)  // set desired actor group
                
.ray   (false               ); // disable ray-testing
            
break;
        case 
ItemClassInfo::SHIRT 
            
i_shirt_kinematic_ragdoll.create(cskel1true      )  // create the helper ragdoll as kinematic
                
.group (AG_KINEMATIC_RAGDOLL)  // set desired actor group
                
.ray   (false               ); // disable ray-testing
            
break;
        case 
ItemClassInfo::COAT
            
i_coat_kinematic_ragdoll.create(cskel1true      )  // create the helper ragdoll as kinematic
                
.group (AG_KINEMATIC_RAGDOLL)  // set desired actor group
                
.ray   (false               ); // disable ray-testing
            
break;
        case 
ItemClassInfo::GLOVES 
            
i_gloves_kinematic_ragdoll.create(cskel1true      )  // create the helper ragdoll as kinematic
                
.group (AG_KINEMATIC_RAGDOLL)  // set desired actor group
                
.ray   (false               ); // disable ray-testing
            
break;
        case 
ItemClassInfo::PANTS 
            
i_pants_kinematic_ragdoll.create(cskel1true      )  // create the helper ragdoll as kinematic
                
.group (AG_KINEMATIC_RAGDOLL)  // set desired actor group
                
.ray   (false               ); // disable ray-testing
            
break;
        case 
ItemClassInfo::SHOES 
            
i_shoes_kinematic_ragdoll.create(cskel1true      )  // create the helper ragdoll as kinematic
                
.group (AG_KINEMATIC_RAGDOLL)  // set desired actor group
                
.ray   (false               ); // disable ray-testing
            
break;
        }

        
// now we would like to create the cloth, however adding the cloth to the character works best when the ragdoll has its pose already set
        // manually setting ragdoll pose is done using 'Ragdoll::fromSkel' method which uses the character controlled skeleton
        // however since we're in 'Player::create' method the skeleton doesn't have a pose set either

        // so first we need to set even a basic skeleton pose
        
Matrix character_matrix=obj.matrixFinal();    // get the target character matrix
        
character_matrix.normalize      ();    // normalize it because matrixes for 'updateMatrix' method must be normalized
        
cskel.clear().updateMatrix(character_matrix); // clearing and updating the matrixes reset the skeleton to its default pose

        // now the skeleton is in its default pose (just the way you can see it in the Mesh Editor), so we can set the ragdoll pose from it
        
switch(cType)
        {
        case 
ItemClassInfo::HAT 
            
i_hat_kinematic_ragdoll.fromSkel(cskelcskel.vel(), true); // use 'true' for immediate pose setting at creation time, to ensure that the pose will be set immediately, please read comments on 'fromSkel' method for more information about it
            
break;
        case 
ItemClassInfo::SHIRT 
            
i_shirt_kinematic_ragdoll.fromSkel(cskelcskel.vel(), true); // use 'true' for immediate pose setting at creation time, to ensure that the pose will be set immediately, please read comments on 'fromSkel' method for more information about it
            
break;
        case 
ItemClassInfo::COAT
            
ConsoleM.newMsg(S+"SYSTEM: Create Coat ragdoll!");
            
i_coat_kinematic_ragdoll.fromSkel(cskelcskel.vel(), true); // use 'true' for immediate pose setting at creation time, to ensure that the pose will be set immediately, please read comments on 'fromSkel' method for more information about it
            
break;
        case 
ItemClassInfo::GLOVES 
            
i_gloves_kinematic_ragdoll.fromSkel(cskelcskel.vel(), true); // use 'true' for immediate pose setting at creation time, to ensure that the pose will be set immediately, please read comments on 'fromSkel' method for more information about it
            
break;
        case 
ItemClassInfo::PANTS 
            
i_pants_kinematic_ragdoll.fromSkel(cskelcskel.vel(), true); // use 'true' for immediate pose setting at creation time, to ensure that the pose will be set immediately, please read comments on 'fromSkel' method for more information about it
            
break;
        case 
ItemClassInfo::SHOES 
            
i_shoes_kinematic_ragdoll.fromSkel(cskelcskel.vel(), true); // use 'true' for immediate pose setting at creation time, to ensure that the pose will be set immediately, please read comments on 'fromSkel' method for more information about it
            
break;
        }
    }

    
// now both skeleton and ragdoll are in their default pose, so we can proceed to creating the cloth
    
{
        
// setup cloth parameters
        
createClothParam();
        
// create the cloth
        
switch(cType)
        {
        case 
ItemClassInfo::HAT 
            
//Chat.New(S+"SYSTEM: Create Armor Cloth!");
            //ClientSendChat(Server, S+"SYSTEM: Create Armor Cloth!");
            
i_hat_cloth.create(*ClothMeshes(sCloth), obj.matrixFinal(), ClothParam); // use ClothMesh file exported from Mesh Editor
            
i_hat_cloth.group (AG_CLOTH); // set desired actor group;
            
break;
        case 
ItemClassInfo::SHIRT 
            
//Chat.New(S+"SYSTEM: Create Pants Cloth!");
            //ClientSendChat(Server, S+"SYSTEM: Create Pants Cloth!");
            
i_shirt_cloth.create(*ClothMeshes(sCloth), obj.matrixFinal(), ClothParam); // use ClothMesh file exported from Mesh Editor
            
i_shirt_cloth.group (AG_CLOTH); // set desired actor group;
            
break;
        case 
ItemClassInfo::COAT
            
ConsoleM.newMsg(S+"SYSTEM: Create Coat Cloth!");
            
//ClientSendChat(Server, S+"SYSTEM: Create Boots Cloth!");
            
i_coat_cloth.create(*ClothMeshes(sCloth), obj.matrixFinal(), ClothParam); // use ClothMesh file exported from Mesh Editor
            
i_coat_cloth.group (AG_CLOTH); // set desired actor group;
            
break;
        case 
ItemClassInfo::GLOVES 
            
//Chat.New(S+"SYSTEM: Create Gauntlets Cloth!");
            //ClientSendChat(Server, S+"SYSTEM: Create Gauntlets Cloth!");
            
i_gloves_cloth.create(*ClothMeshes(sCloth), obj.matrixFinal(), ClothParam); // use ClothMesh file exported from Mesh Editor
            
i_gloves_cloth.group (AG_CLOTH); // set desired actor group;
            
break;
        case 
ItemClassInfo::PANTS 
            
//Chat.New(S+"SYSTEM: Create Gauntlets Cloth!");
            //ClientSendChat(Server, S+"SYSTEM: Create Gauntlets Cloth!");
            
i_pants_cloth.create(*ClothMeshes(sCloth), obj.matrixFinal(), ClothParam); // use ClothMesh file exported from Mesh Editor
            
i_pants_cloth.group (AG_CLOTH); // set desired actor group;
            
break;
        case 
ItemClassInfo::SHOES 
            
//Chat.New(S+"SYSTEM: Create Gauntlets Cloth!");
            //ClientSendChat(Server, S+"SYSTEM: Create Gauntlets Cloth!");
            
i_shoes_cloth.create(*ClothMeshes(sCloth), obj.matrixFinal(), ClothParam); // use ClothMesh file exported from Mesh Editor
            
i_shoes_cloth.group (AG_CLOTH); // set desired actor group;
            
break;
        }

        
// now the cloth is created and will be seen on the screen, but still we need to attach it to the ragdoll
        
if(ClothMesh *cloth_mesh=i_coat_cloth.clothMesh()) // access cloth mesh from which the cloth has been created
            
if(const Vec   *vtx_pos   =cloth_mesh->pos   ()) // access cloth mesh source vertex positions
                
if(const Byte  *vtx_flag  =cloth_mesh->flag  ()) // access cloth mesh source vertex flags
                    
if(const VecB4 *vtx_matrix=cloth_mesh->matrix()) // access cloth mesh source vertex matrix indexes
                    
{
                        
REP(cloth_mesh->vtxs()) // iterate through all cloth vertexes
                            
if(!FlagTest(vtx_flag[i], VTX_FLAG_CLOTH)) // if the vertex cloth shouldn't be physically simulated then attach it
                            
{
                                
Int ragdoll_bone_index;
                                switch(
cType)
                                {
                                case 
ItemClassInfo::HAT 
                                    
ragdoll_bone_index =i_hat_kinematic_ragdoll.findBoneIndexFromVtxMatrix(vtx_matrix[i].x); // get ragdoll bone index according to vertex matrix
                                    
if( ragdoll_bone_index!=-1// if the bone index is valid
                                    
{
                                        
Actor &actor          =i_hat_kinematic_ragdoll.bone(ragdoll_bone_index).actor// get ragdoll bone's actor
                                        
Vec    vtx_source_pos =vtx_pos[i]  ; // get original cloth mesh vertex position 
                                        
vtx_source_pos*=i_hat_cloth.scale(); // scale it according to current cloth instance scale
                                        
Bool   response       =false       // disable response in attachment
                                            
local_pos      =true        // use ragdoll local space to attach the cloth vertex regardless of the current ragdoll pose

                                        
i_hat_cloth.attachVtx(ivtx_source_pos, &actorresponselocal_pos); // attach the vertex
                                    
}
                                    break;
                                case 
ItemClassInfo::SHIRT 
                                    
ragdoll_bone_index =i_shirt_kinematic_ragdoll.findBoneIndexFromVtxMatrix(vtx_matrix[i].x); // get ragdoll bone index according to vertex matrix
                                    
if( ragdoll_bone_index!=-1// if the bone index is valid
                                    
{
                                        
Actor &actor          =i_shirt_kinematic_ragdoll.bone(ragdoll_bone_index).actor// get ragdoll bone's actor
                                        
Vec    vtx_source_pos =vtx_pos[i]  ; // get original cloth mesh vertex position 
                                        
vtx_source_pos*=i_shirt_cloth.scale(); // scale it according to current cloth instance scale
                                        
Bool   response       =false       // disable response in attachment
                                            
local_pos      =true        // use ragdoll local space to attach the cloth vertex regardless of the current ragdoll pose

                                        
i_shirt_cloth.attachVtx(ivtx_source_pos, &actorresponselocal_pos); // attach the vertex
                                    
}
                                    break;
                                case 
ItemClassInfo::COAT
                                    
ragdoll_bone_index =i_coat_kinematic_ragdoll.findBoneIndexFromVtxMatrix(vtx_matrix[i].x); // get ragdoll bone index according to vertex matrix
                                    
if( ragdoll_bone_index!=-1// if the bone index is valid
                                    
{
                                        
Actor &actor          =i_coat_kinematic_ragdoll.bone(ragdoll_bone_index).actor// get ragdoll bone's actor
                                        
Vec    vtx_source_pos =vtx_pos[i]  ; // get original cloth mesh vertex position 
                                        
vtx_source_pos*=i_coat_cloth.scale(); // scale it according to current cloth instance scale
                                        
Bool   response       =false       // disable response in attachment
                                            
local_pos      =true        // use ragdoll local space to attach the cloth vertex regardless of the current ragdoll pose

                                        
i_coat_cloth.attachVtx(ivtx_source_pos, &actorresponselocal_pos); // attach the vertex
                                    
}
                                    break;
                                case 
ItemClassInfo::GLOVES 
                                    
ragdoll_bone_index =i_gloves_kinematic_ragdoll.findBoneIndexFromVtxMatrix(vtx_matrix[i].x); // get ragdoll bone index according to vertex matrix
                                    
if( ragdoll_bone_index!=-1// if the bone index is valid
                                    
{
                                        
Actor &actor          =i_gloves_kinematic_ragdoll.bone(ragdoll_bone_index).actor// get ragdoll bone's actor
                                        
Vec    vtx_source_pos =vtx_pos[i]  ; // get original cloth mesh vertex position 
                                        
vtx_source_pos*=i_gloves_cloth.scale(); // scale it according to current cloth instance scale
                                        
Bool   response       =false       // disable response in attachment
                                            
local_pos      =true        // use ragdoll local space to attach the cloth vertex regardless of the current ragdoll pose

                                        
i_gloves_cloth.attachVtx(ivtx_source_pos, &actorresponselocal_pos); // attach the vertex
                                    
}
                                    break;
                                case 
ItemClassInfo::PANTS 
                                    
ragdoll_bone_index =i_pants_kinematic_ragdoll.findBoneIndexFromVtxMatrix(vtx_matrix[i].x); // get ragdoll bone index according to vertex matrix
                                    
if( ragdoll_bone_index!=-1// if the bone index is valid
                                    
{
                                        
Actor &actor          =i_pants_kinematic_ragdoll.bone(ragdoll_bone_index).actor// get ragdoll bone's actor
                                        
Vec    vtx_source_pos =vtx_pos[i]  ; // get original cloth mesh vertex position 
                                        
vtx_source_pos*=i_pants_cloth.scale(); // scale it according to current cloth instance scale
                                        
Bool   response       =false       // disable response in attachment
                                            
local_pos      =true        // use ragdoll local space to attach the cloth vertex regardless of the current ragdoll pose

                                        
i_pants_cloth.attachVtx(ivtx_source_pos, &actorresponselocal_pos); // attach the vertex
                                    
}
                                    break;
                                case 
ItemClassInfo::SHOES 
                                    
ragdoll_bone_index =i_shoes_kinematic_ragdoll.findBoneIndexFromVtxMatrix(vtx_matrix[i].x); // get ragdoll bone index according to vertex matrix
                                    
if( ragdoll_bone_index!=-1// if the bone index is valid
                                    
{
                                        
Actor &actor          =i_shoes_kinematic_ragdoll.bone(ragdoll_bone_index).actor// get ragdoll bone's actor
                                        
Vec    vtx_source_pos =vtx_pos[i]  ; // get original cloth mesh vertex position 
                                        
vtx_source_pos*=i_shoes_cloth.scale(); // scale it according to current cloth instance scale
                                        
Bool   response       =false       // disable response in attachment
                                            
local_pos      =true        // use ragdoll local space to attach the cloth vertex regardless of the current ragdoll pose

                                        
i_shoes_cloth.attachVtx(ivtx_source_pos, &actorresponselocal_pos); // attach the vertex
                                    
}
                                    break;
                                }

                            }
                    }
    }
}

void Player::create(ClientChr &chr)
{
   
Game::ObjParams obj;
   
obj.matrix=chr.pos();
   
obj.base (      chr.obj);
   
obj.scale(truechr.scale);
   
obj.type (trueL"OBJ_PLAYER");
   
   
__super::create(obj);

   
i_coat_cloth.del();

   if(
GetExt(i_coat) == "clothmesh"){createCloth(objItemClassInfo::COATi_coat);}
}

bool Player::update()
{
    if(
super::update())
    {
        
// after calling the default update the character skeleton is animated, so basing on that information we'll set the helper ragdoll to the skeleton pose using 'fromSkel' method
        
if(GetExt(i_coat) == "clothmesh"){i_coat_kinematic_ragdoll.fromSkel(cskelcskel.vel());}
        
i_coat_kinematic_ragdoll.pos(cskel.pos());
        return 
true;
    }
    return 
false;


I have found when i add
PHP Code:
i_coat_kinematic_ragdoll.pos(cskel.pos()); 
the ragdoll follow correctly the skeleton but i have the same bug with the cloth.
   
I think it's a problem with obj.matrixFinal() In the MMO code it work when added to Chr.cpp (but same bug in Neighbor.cpp)
Thank you.
(This post was last modified: 12-10-2011 12:52 PM by Skykill.)
12-10-2011 12:39 PM
Find all posts by this user Quote this message in a reply
Esenthel Offline
Administrator

Post: #2
RE: Ragdoll cloth does not follow skeleton
can you make a video of the issue? so I could see it from different angles
12-10-2011 01:29 PM
Find all posts by this user Quote this message in a reply
Skykill Offline
Member

Post: #3
RE: Ragdoll cloth does not follow skeleton
(This post was last modified: 12-10-2011 06:56 PM by Skykill.)
12-10-2011 04:16 PM
Find all posts by this user Quote this message in a reply
Esenthel Offline
Administrator

Post: #4
RE: Ragdoll cloth does not follow skeleton
Thanks, I think it's 1 frame delay issue.
did you configure your project according to cloth tutorial?

Code:
Bool Init()
{
  ..

   // in order to properly synchronize the physical clothing with the character, you must set the following engine options
   Game::World.update_objects_after_physics=false; // force updating the objects before updating physics
   Physics.timestep(PHYS_TIMESTEP_VARIABLE);       // set variable timestepping when updating physics
   D.sync(true);                                   // enable screen synchronization because variable timestepping works best in a constant framerate
12-15-2011 02:50 PM
Find all posts by this user Quote this message in a reply
Skykill Offline
Member

Post: #5
RE: Ragdoll cloth does not follow skeleton
My code is based from the tutorial, but i have forgot to add the drawPrepare() to my first post pfft
Here it's:
PHP Code:
uint Player::drawPrepare()
{
    
// in order to properly synchronize the physical clothing with the character, you must set the following engine options
    
Game::World.update_objects_after_physics=false// force updating the objects before updating physics 
    
Physics.timestep(PHYS_TIMESTEP_VARIABLE);       // set variable timestepping when updating physics
    
D.sync(true);                                   // enable screen synchronization because variable timestepping works best in a constant framerate

    // set collision groups
    
REP(32)if(i!=AG_CLOTH)Physics.ignore(iAG_KINEMATIC_RAGDOLL); // ignore collisions between AG_KINEMATIC_RAGDOLL and all other groups except AG_CAPE
    
Physics.ignore(AG_CLOTHAG_CONTROLLER ); // ignore collisions between capes and character controllers
   
if(!alive())
   {
      
scheduleDrawBlend(pos());
   }else
   if(
mesh)if(Frustum(Ball().setAnimated(mesh->boxcskel)))
   {
        
SetHighlight(DamageColor(damage_time));
        
bool hide_head=(ViewMode==VIEW_FPP && !Renderer.mirror());
        if(  
hide_head)mesh->hide("head"); mesh->draw(cskel); 
        if(  
hide_head)mesh->show("head");
        
SetHighlight();
        if(
GetExt(i_hat) == "mesh"Meshes(i_hat)->draw(cskel);
        if(
GetExt(i_shirt) == "mesh"Meshes(i_shirt)->draw(cskel);
        if(
GetExt(i_coat) == "mesh"Meshes(i_coat)->draw(cskel);
        if(
GetExt(i_gloves) == "mesh"Meshes(i_gloves)->draw(cskel);
        if(
GetExt(i_pants) == "mesh"Meshes(i_pants)->draw(cskel);
        if(
GetExt(i_shoes) == "mesh"Meshes(i_shoes)->draw(cskel);

        
//Only if the mesh is a cloth
        
if(GetExt(i_coat) == "clothmesh"){ i_coat_cloth.drawSkinned(cskel); i_coat_cloth.drawPhysical(); }
   }

   
REPAO(magic_bolts).draw();

   return 
0;

I tried to put the code you showed me in Player::create() and game.cpp InitGame() but this did not changed anything.
12-15-2011 05:13 PM
Find all posts by this user Quote this message in a reply
Esenthel Offline
Administrator

Post: #6
RE: Ragdoll cloth does not follow skeleton
Hi,

well I've checked the cloth tutorials (advanced/game basics/physical cloth and Esenthel RPG 2)
and they both work fine
so there must be something wrong with your codes.
please pay attention to the order of making function calls
12-19-2011 03:44 PM
Find all posts by this user Quote this message in a reply
Skykill Offline
Member

Post: #7
RE: Ragdoll cloth does not follow skeleton
Yes, as i have say it work with the MMO code but i can't get it to work with the Ineisis Lite code in Player.cpp.
(This post was last modified: 12-19-2011 04:30 PM by Skykill.)
12-19-2011 04:28 PM
Find all posts by this user Quote this message in a reply
Post Reply