Exemplo n.º 1
0
		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;
		}