void BulletPhysicsServer::area_clear_shapes(RID p_area) {
	AreaBullet *area = area_owner.get(p_area);
	ERR_FAIL_COND(!area);

	for (int i = area->get_shape_count(); 0 < i; --i)
		area->remove_shape(0);
}
ObjectID BulletPhysicsServer::area_get_object_instance_id(RID p_area) const {
	if (space_owner.owns(p_area)) {
		return 0;
	}
	AreaBullet *area = area_owner.get(p_area);
	ERR_FAIL_COND_V(!area, ObjectID());
	return area->get_instance_id();
}
void BulletPhysicsServer::area_attach_object_instance_id(RID p_area, ObjectID p_ID) {
	if (space_owner.owns(p_area)) {
		return;
	}
	AreaBullet *area = area_owner.get(p_area);
	ERR_FAIL_COND(!area);
	area->set_instance_id(p_ID);
}
void BulletPhysicsServer::area_set_shape(RID p_area, int p_shape_idx, RID p_shape) {
	AreaBullet *area = area_owner.get(p_area);
	ERR_FAIL_COND(!area);

	ShapeBullet *shape = shape_owner.get(p_shape);
	ERR_FAIL_COND(!shape);

	area->set_shape(p_shape_idx, shape);
}
void BulletPhysicsServer::area_add_shape(RID p_area, RID p_shape, const Transform &p_transform) {
	AreaBullet *area = area_owner.get(p_area);
	ERR_FAIL_COND(!area);

	ShapeBullet *shape = shape_owner.get(p_shape);
	ERR_FAIL_COND(!shape);

	area->add_shape(shape, p_transform);
}
void BulletPhysicsServer::area_set_space(RID p_area, RID p_space) {
	AreaBullet *area = area_owner.get(p_area);
	ERR_FAIL_COND(!area);
	SpaceBullet *space = NULL;
	if (p_space.is_valid()) {
		space = space_owner.get(p_space);
		ERR_FAIL_COND(!space);
	}
	area->set_space(space);
}
Variant BulletPhysicsServer::area_get_param(RID p_area, AreaParameter p_param) const {
	if (space_owner.owns(p_area)) {
		SpaceBullet *space = space_owner.get(p_area);
		return space->get_param(p_param);
	} else {
		AreaBullet *area = area_owner.get(p_area);
		ERR_FAIL_COND_V(!area, Variant());

		return area->get_param(p_param);
	}
}
void BulletPhysicsServer::area_set_param(RID p_area, AreaParameter p_param, const Variant &p_value) {
	if (space_owner.owns(p_area)) {
		SpaceBullet *space = space_owner.get(p_area);
		if (space) {
			space->set_param(p_param, p_value);
		}
	} else {

		AreaBullet *area = area_owner.get(p_area);
		ERR_FAIL_COND(!area);

		area->set_param(p_param, p_value);
	}
}
RID BulletPhysicsServer::area_create() {
	AreaBullet *area = bulletnew(AreaBullet);
	area->set_collision_layer(1);
	area->set_collision_mask(1);
	CreateThenReturnRID(area_owner, area)
}
bool BulletPhysicsServer::area_is_ray_pickable(RID p_area) const {
	AreaBullet *area = area_owner.get(p_area);
	ERR_FAIL_COND_V(!area, false);
	return area->is_ray_pickable();
}
void BulletPhysicsServer::area_set_area_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) {
	AreaBullet *area = area_owner.get(p_area);
	ERR_FAIL_COND(!area);

	area->set_event_callback(CollisionObjectBullet::TYPE_AREA, p_receiver ? p_receiver->get_instance_id() : 0, p_method);
}
Transform BulletPhysicsServer::area_get_transform(RID p_area) const {
	AreaBullet *area = area_owner.get(p_area);
	ERR_FAIL_COND_V(!area, Transform());
	return area->get_transform();
}
int BulletPhysicsServer::area_get_shape_count(RID p_area) const {
	AreaBullet *area = area_owner.get(p_area);
	ERR_FAIL_COND_V(!area, 0);

	return area->get_shape_count();
}
PhysicsServer::AreaSpaceOverrideMode BulletPhysicsServer::area_get_space_override_mode(RID p_area) const {
	AreaBullet *area = area_owner.get(p_area);
	ERR_FAIL_COND_V(!area, PhysicsServer::AREA_SPACE_OVERRIDE_DISABLED);

	return area->get_spOv_mode();
}
void BulletPhysicsServer::area_set_space_override_mode(RID p_area, AreaSpaceOverrideMode p_mode) {
	AreaBullet *area = area_owner.get(p_area);
	ERR_FAIL_COND(!area)

	area->set_spOv_mode(p_mode);
}
RID BulletPhysicsServer::area_get_space(RID p_area) const {
	AreaBullet *area = area_owner.get(p_area);
	return area->get_space()->get_self();
}
void BulletPhysicsServer::area_set_transform(RID p_area, const Transform &p_transform) {
	AreaBullet *area = area_owner.get(p_area);
	ERR_FAIL_COND(!area);
	area->set_transform(p_transform);
}
RID BulletPhysicsServer::area_get_shape(RID p_area, int p_shape_idx) const {
	AreaBullet *area = area_owner.get(p_area);
	ERR_FAIL_COND_V(!area, RID());

	return area->get_shape(p_shape_idx)->get_self();
}
void BulletPhysicsServer::area_set_collision_layer(RID p_area, uint32_t p_layer) {
	AreaBullet *area = area_owner.get(p_area);
	ERR_FAIL_COND(!area);
	area->set_collision_layer(p_layer);
}
void BulletPhysicsServer::area_remove_shape(RID p_area, int p_shape_idx) {
	AreaBullet *area = area_owner.get(p_area);
	ERR_FAIL_COND(!area);
	return area->remove_shape(p_shape_idx);
}
void BulletPhysicsServer::area_set_ray_pickable(RID p_area, bool p_enable) {
	AreaBullet *area = area_owner.get(p_area);
	ERR_FAIL_COND(!area);
	area->set_ray_pickable(p_enable);
}
void BulletPhysicsServer::area_set_shape_disabled(RID p_area, int p_shape_idx, bool p_disabled) {
	AreaBullet *area = area_owner.get(p_area);
	ERR_FAIL_COND(!area);

	area->set_shape_disabled(p_shape_idx, p_disabled);
}
Exemple #23
0
void RigidBodyBullet::reload_space_override_modificator() {

	// Make sure that kinematic bodies have their total gravity calculated
	if (!is_active() && PhysicsServer::BODY_MODE_KINEMATIC != mode)
		return;

	Vector3 newGravity(space->get_gravity_direction() * space->get_gravity_magnitude());
	real_t newLinearDamp(linearDamp);
	real_t newAngularDamp(angularDamp);

	AreaBullet *currentArea;
	// Variable used to calculate new gravity for gravity point areas, it is pointed by currentGravity pointer
	Vector3 support_gravity(0, 0, 0);

	int countCombined(0);
	for (int i = areaWhereIamCount - 1; 0 <= i; --i) {

		currentArea = areasWhereIam[i];

		if (PhysicsServer::AREA_SPACE_OVERRIDE_DISABLED == currentArea->get_spOv_mode()) {
			continue;
		}

		/// Here is calculated the gravity
		if (currentArea->is_spOv_gravityPoint()) {

			/// It calculates the direction of new gravity
			support_gravity = currentArea->get_transform().xform(currentArea->get_spOv_gravityVec()) - get_transform().get_origin();
			real_t distanceMag = support_gravity.length();
			// Normalized in this way to avoid the double call of function "length()"
			if (distanceMag == 0) {
				support_gravity.x = 0;
				support_gravity.y = 0;
				support_gravity.z = 0;
			} else {
				support_gravity.x /= distanceMag;
				support_gravity.y /= distanceMag;
				support_gravity.z /= distanceMag;
			}

			/// Here is calculated the final gravity
			if (currentArea->get_spOv_gravityPointDistanceScale() > 0) {
				// Scaled gravity by distance
				support_gravity *= currentArea->get_spOv_gravityMag() / Math::pow(distanceMag * currentArea->get_spOv_gravityPointDistanceScale() + 1, 2);
			} else {
				// Unscaled gravity
				support_gravity *= currentArea->get_spOv_gravityMag();
			}
		} else {
			support_gravity = currentArea->get_spOv_gravityVec() * currentArea->get_spOv_gravityMag();
		}

		switch (currentArea->get_spOv_mode()) {
			///case PhysicsServer::AREA_SPACE_OVERRIDE_DISABLED:
			/// This area does not affect gravity/damp. These are generally areas
			/// that exist only to detect collisions, and objects entering or exiting them.
			///    break;
			case PhysicsServer::AREA_SPACE_OVERRIDE_COMBINE:
				/// This area adds its gravity/damp values to whatever has been
				/// calculated so far. This way, many overlapping areas can combine
				/// their physics to make interesting
				newGravity += support_gravity;
				newLinearDamp += currentArea->get_spOv_linearDamp();
				newAngularDamp += currentArea->get_spOv_angularDamp();
				++countCombined;
				break;
			case PhysicsServer::AREA_SPACE_OVERRIDE_COMBINE_REPLACE:
				/// This area adds its gravity/damp values to whatever has been calculated
				/// so far. Then stops taking into account the rest of the areas, even the
				/// default one.
				newGravity += support_gravity;
				newLinearDamp += currentArea->get_spOv_linearDamp();
				newAngularDamp += currentArea->get_spOv_angularDamp();
				++countCombined;
				goto endAreasCycle;
			case PhysicsServer::AREA_SPACE_OVERRIDE_REPLACE:
				/// This area replaces any gravity/damp, even the default one, and
				/// stops taking into account the rest of the areas.
				newGravity = support_gravity;
				newLinearDamp = currentArea->get_spOv_linearDamp();
				newAngularDamp = currentArea->get_spOv_angularDamp();
				countCombined = 1;
				goto endAreasCycle;
			case PhysicsServer::AREA_SPACE_OVERRIDE_REPLACE_COMBINE:
				/// This area replaces any gravity/damp calculated so far, but keeps
				/// calculating the rest of the areas, down to the default one.
				newGravity = support_gravity;
				newLinearDamp = currentArea->get_spOv_linearDamp();
				newAngularDamp = currentArea->get_spOv_angularDamp();
				countCombined = 1;
				break;
		}
	}
endAreasCycle:

	if (1 < countCombined) {
		newGravity /= countCombined;
		newLinearDamp /= countCombined;
		newAngularDamp /= countCombined;
	}

	btVector3 newBtGravity;
	G_TO_B(newGravity * gravity_scale, newBtGravity);

	btBody->setGravity(newBtGravity);
	btBody->setDamping(newLinearDamp, newAngularDamp);
}
void BulletPhysicsServer::free(RID p_rid) {
	if (shape_owner.owns(p_rid)) {

		ShapeBullet *shape = shape_owner.get(p_rid);

		// Notify the shape is configured
		for (Map<ShapeOwnerBullet *, int>::Element *element = shape->get_owners().front(); element; element = element->next()) {
			static_cast<ShapeOwnerBullet *>(element->key())->remove_shape(shape);
		}

		shape_owner.free(p_rid);
		bulletdelete(shape);
	} else if (rigid_body_owner.owns(p_rid)) {

		RigidBodyBullet *body = rigid_body_owner.get(p_rid);

		body->set_space(NULL);

		body->remove_all_shapes(true);

		rigid_body_owner.free(p_rid);
		bulletdelete(body);

	} else if (soft_body_owner.owns(p_rid)) {

		SoftBodyBullet *body = soft_body_owner.get(p_rid);

		body->set_space(NULL);

		soft_body_owner.free(p_rid);
		bulletdelete(body);

	} else if (area_owner.owns(p_rid)) {

		AreaBullet *area = area_owner.get(p_rid);

		area->set_space(NULL);

		area->remove_all_shapes(true);

		area_owner.free(p_rid);
		bulletdelete(area);

	} else if (joint_owner.owns(p_rid)) {

		JointBullet *joint = joint_owner.get(p_rid);
		joint->destroy_internal_constraint();
		joint_owner.free(p_rid);
		bulletdelete(joint);

	} else if (space_owner.owns(p_rid)) {

		SpaceBullet *space = space_owner.get(p_rid);

		space->remove_all_collision_objects();

		space_set_active(p_rid, false);
		space_owner.free(p_rid);
		bulletdelete(space);
	} else {

		ERR_EXPLAIN("Invalid ID");
		ERR_FAIL();
	}
}