void	KX_BulletPhysicsController::SuspendDynamics(bool ghost)
{
	btRigidBody *body = GetRigidBody();
	if (body && !m_suspended && !IsSensor())
	{
		btBroadphaseProxy* handle = body->getBroadphaseHandle();
		m_savedCollisionFlags = body->getCollisionFlags();
		m_savedMass = GetMass();
		m_savedDyna = m_bDyna;
		m_savedCollisionFilterGroup = handle->m_collisionFilterGroup;
		m_savedCollisionFilterMask = handle->m_collisionFilterMask;
		m_suspended = true;
		GetPhysicsEnvironment()->updateCcdPhysicsController(this, 
			0.0,
			btCollisionObject::CF_STATIC_OBJECT|((ghost)?btCollisionObject::CF_NO_CONTACT_RESPONSE:(m_savedCollisionFlags&btCollisionObject::CF_NO_CONTACT_RESPONSE)),
			btBroadphaseProxy::StaticFilter, 
			btBroadphaseProxy::AllFilter ^ btBroadphaseProxy::StaticFilter);
		m_bDyna = false;
	}
}
Example #2
0
void physics_system::contact_listener::BeginContact(b2Contact* contact) {
	auto& sys = get_sys();
	auto& cosmos = cosm;
	auto delta = cosm.get_fixed_delta();

	for (int i = 0; i < 2; ++i) {
		auto fix_a = contact->GetFixtureA();
		auto fix_b = contact->GetFixtureB();

		int numPoints = contact->GetManifold()->pointCount;
		b2WorldManifold worldManifold;
		contact->GetWorldManifold(&worldManifold);

		if (i == 1) {
			std::swap(fix_a, fix_b);
			if (numPoints > 1) {
				std::swap(worldManifold.points[0], worldManifold.points[1]);
				std::swap(worldManifold.separations[0], worldManifold.separations[1]);
			}
			worldManifold.normal *= -1;
		}

		auto body_a = fix_a->GetBody();
		auto body_b = fix_b->GetBody();

		messages::collision_message msg;

		if (fix_a->IsSensor() || fix_b->IsSensor())
			msg.one_is_sensor = true;

		msg.type = messages::collision_message::event_type::BEGIN_CONTACT;

		auto subject = cosmos[fix_a->GetUserData()];
		auto collider = cosmos[fix_b->GetUserData()];

		msg.subject = subject;
		msg.collider = collider;

		auto& subject_fixtures = subject.get<components::fixtures>();
		auto& collider_fixtures = collider.get<components::fixtures>();

		if (subject_fixtures.is_friction_ground()) {
#if FRICTION_FIELDS_COLLIDE
			if (!collider_fixtures.is_friction_ground)
#endif
			{
				auto& collider_physics = collider_fixtures.get_owner_body().get<components::special_physics>();

				bool found_suitable = false;

				// always accept my own children
				if (are_connected_by_friction(collider, subject)) {
					found_suitable = true;
				}
				else if (collider_physics.since_dropped.lasts(cosm.get_timestamp(), delta)) {
					collider_physics.since_dropped.unset();
					found_suitable = true;
				}
				else {
					for (int i = 0; i < 1; i++) {
						const b2Vec2 pointVelOther = body_b->GetLinearVelocityFromWorldPoint(worldManifold.points[i]);
						const auto velOtherPixels = vec2(pointVelOther) * METERS_TO_PIXELSf;

						if (velOtherPixels.length() > 1) {
							const auto angle = vec2(worldManifold.normal).degrees_between(velOtherPixels);

							if (angle > 90) {
								found_suitable = true;
							}
						}

						if (augs::renderer::get_current().debug_draw_friction_field_collisions_of_entering) {
							augs::renderer::get_current().blink_lines.draw_yellow(METERS_TO_PIXELSf*worldManifold.points[i], METERS_TO_PIXELSf* worldManifold.points[i] + vec2(worldManifold.normal).set_length(150));
							augs::renderer::get_current().blink_lines.draw_red(METERS_TO_PIXELSf*worldManifold.points[i], METERS_TO_PIXELSf* worldManifold.points[i] + velOtherPixels);
						}
					}
				}

				if (found_suitable) {
					auto new_owner = subject_fixtures.get_owner_body().get_id();
					auto& grounds = collider_physics.owner_friction_grounds;
					
					components::special_physics::friction_connection connection(new_owner);
					connection.fixtures_connected = 1;

					if (found_in(grounds, new_owner)) {
						auto found = find_in(grounds, new_owner);
						 LOG("Incr: %x", new_owner);

						connection.fixtures_connected = (*found).fixtures_connected + 1;
						grounds.erase(found);
					}
					else {
						 LOG("Reg: %x", new_owner);
					}
					
					grounds.push_back(connection);

					sys.rechoose_owner_friction_body(collider_fixtures.get_owner_body());
				}
			}
		}

		msg.point = worldManifold.points[0];
		msg.point *= METERS_TO_PIXELSf;

		msg.subject_impact_velocity = body_a->GetLinearVelocityFromWorldPoint(worldManifold.points[0]);
		msg.collider_impact_velocity = body_b->GetLinearVelocityFromWorldPoint(worldManifold.points[0]);
		sys.accumulated_messages.push_back(msg);
	}
}