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 &obj, ItemClassInfo::TYPE cType, Str 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(cskel, 1, true ) // 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(cskel, 1, true ) // 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(cskel, 1, true ) // 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(cskel, 1, true ) // 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(cskel, 1, true ) // 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(cskel, 1, true ) // 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(cskel, cskel.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(cskel, cskel.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(cskel, cskel.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(cskel, cskel.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(cskel, cskel.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(cskel, cskel.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(i, vtx_source_pos, &actor, response, local_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(i, vtx_source_pos, &actor, response, local_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(i, vtx_source_pos, &actor, response, local_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(i, vtx_source_pos, &actor, response, local_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(i, vtx_source_pos, &actor, response, local_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(i, vtx_source_pos, &actor, response, local_pos); // attach the vertex
}
break;
}
}
}
}
}
void Player::create(ClientChr &chr)
{
Game::ObjParams obj;
obj.matrix=chr.pos();
obj.base ( chr.obj);
obj.scale(true, chr.scale);
obj.type (true, L"OBJ_PLAYER");
__super::create(obj);
i_coat_cloth.del();
if(GetExt(i_coat) == "clothmesh"){createCloth(obj, ItemClassInfo::COAT, i_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(cskel, cskel.vel());}
i_coat_kinematic_ragdoll.pos(cskel.pos());
return true;
}
return false;
}