void Spawned() { physics = corpse->game_state->physics_world; // get bone pos/ori info vector<Mat4> mats = vector<Mat4>(); unsigned int count = character->skeleton->bones.size(); for(unsigned int i = 0; i < count; ++i) { Bone* bone = character->skeleton->bones[i]; bone_offsets.push_back(bone->rest_pos); mats.push_back(whole_xform * bone->GetTransformationMatrix()); } UberModel::BonePhysics** bone_physes = new UberModel::BonePhysics* [count]; // create rigid bodies for(unsigned int i = 0; i < count; ++i) { Bone* bone = character->skeleton->bones[i]; Mat4 mat = mats[i]; float ori_values[] = {mat[0], mat[1], mat[2], mat[4], mat[5], mat[6], mat[8], mat[9], mat[10]}; bone->ori = Quaternion::FromRotationMatrix(Mat3(ori_values)); Vec3 bone_pos = mat.TransformVec3(bone_offsets[i], 1); UberModel::BonePhysics* phys = NULL; for(unsigned int j = 0; j < model->bone_physics.size(); ++j) if(Bone::string_table[model->bone_physics[j].bone_name] == bone->name) phys = &model->bone_physics[j]; bone_physes[i] = phys; if(phys != NULL) { btCollisionShape* shape = phys->shape; if(shape != NULL) { RigidBodyInfo* rigid_body = new RigidBodyInfo(shape, MassInfo::FromCollisionShape(shape, phys->mass), bone_pos, bone->ori); rigid_body->SetLinearVelocity(initial_vel); // these constants taken from the ragdoll demo rigid_body->SetDamping(0.05f, 0.85f); rigid_body->SetDeactivationTime(0.8f); rigid_body->SetSleepingThresholds(1.6f, 2.5f); rigid_body->SetFriction(1.0f); rigid_body->SetRestitution(0.01f); physics->AddRigidBody(rigid_body); rigid_bodies.push_back(rigid_body); CorpseBoneShootable* shootable = new CorpseBoneShootable(corpse->game_state, corpse, rigid_body, blood_material); shootables.push_back(shootable); rigid_body->SetCustomCollisionEnabled(shootable); bone_indices.push_back(i); } } } // create constraints between bones for(unsigned int i = 0; i < rigid_bodies.size(); ++i) { unsigned int bone_index = bone_indices[i]; UberModel::BonePhysics* phys = bone_physes[bone_index]; if(phys != NULL) { Bone* bone = character->skeleton->bones[bone_index]; Bone* parent = bone->parent; if(parent != NULL) { // find index of parent (bone's index is the same as rigid body info's index) for(unsigned int j = 0; j < rigid_bodies.size(); ++j) { unsigned int j_index = bone_indices[j]; if(character->skeleton->bones[j_index] == parent) { if(bone_physes[j_index] != NULL) { RigidBodyInfo* my_body = rigid_bodies[i]; RigidBodyInfo* parent_body = rigid_bodies[j]; ConeTwistConstraint* c = new ConeTwistConstraint(my_body, parent_body, Quaternion::Identity(), Vec3(), phys->ori, phys->pos); c->SetLimit(phys->span); c->SetDamping(0.1f); // default is 0.01 constraints.push_back(c); physics->AddConstraint(c, true); // true = prevent them from colliding normally break; } } } } } } // emancipate bones for(unsigned int i = 0; i < count; ++i) { Bone* bone = character->skeleton->bones[i]; bone->parent = NULL; // orientation and position are no longer relative to a parent! } if(rigid_bodies.size() == 0) corpse->is_valid = false; delete[] bone_physes; }