_FORCE_INLINE_ bool test_axis(const Vector3 &p_axis) {

		Vector3 axis = p_axis;

		if (Math::abs(axis.x) < CMP_EPSILON &&
				Math::abs(axis.y) < CMP_EPSILON &&
				Math::abs(axis.z) < CMP_EPSILON) {
			// strange case, try an upwards separator
			axis = Vector3(0.0, 1.0, 0.0);
		}

		real_t min_A, max_A, min_B, max_B;

		shape_A->project_range(axis, *transform_A, min_A, max_A);
		shape_B->project_range(axis, *transform_B, min_B, max_B);

		if (withMargin) {
			min_A -= margin_A;
			max_A += margin_A;
			min_B -= margin_B;
			max_B += margin_B;
		}

		min_B -= (max_A - min_A) * 0.5;
		max_B += (max_A - min_A) * 0.5;

		real_t dmin = min_B - (min_A + max_A) * 0.5;
		real_t dmax = max_B - (min_A + max_A) * 0.5;

		if (dmin > 0.0 || dmax < 0.0) {
			separator_axis = axis;
			return false; // doesn't contain 0
		}

		//use the smallest depth

		dmin = Math::abs(dmin);

		if (dmax < dmin) {
			if (dmax < best_depth) {
				best_depth = dmax;
				best_axis = axis;
			}
		} else {
			if (dmin < best_depth) {
				best_depth = dmin;
				best_axis = -axis; // keep it as A axis
			}
		}

		return true;
	}
	_FORCE_INLINE_ void generate_contacts() {

		// nothing to do, don't generate
		if (best_axis==Vector2(0.0,0.0))
			return;

		callback->collided=true;

		if (!callback->callback)
			return; //only collide, no callback
		static const int max_supports=2;

		Vector2 supports_A[max_supports];
		int support_count_A;
		if (castA) {
			shape_A->get_supports_transformed_cast(motion_A,-best_axis,*transform_A,supports_A,support_count_A);
		} else {
			shape_A->get_supports(transform_A->basis_xform_inv(-best_axis).normalized(),supports_A,support_count_A);
			for(int i=0;i<support_count_A;i++) {
				supports_A[i] = transform_A->xform(supports_A[i]);
			}
		}

		if (withMargin) {

			for(int i=0;i<support_count_A;i++) {
				supports_A[i]+=-best_axis*margin_A;
			}

		}



		Vector2 supports_B[max_supports];
		int support_count_B;
		if (castB) {
			shape_B->get_supports_transformed_cast(motion_B,best_axis,*transform_B,supports_B,support_count_B);
		} else {
			shape_B->get_supports(transform_B->basis_xform_inv(best_axis).normalized(),supports_B,support_count_B);
			for(int i=0;i<support_count_B;i++) {
				supports_B[i] = transform_B->xform(supports_B[i]);
			}
		}

		if (withMargin) {

			for(int i=0;i<support_count_B;i++) {
				supports_B[i]+=best_axis*margin_B;
			}

		}

/*


		print_line("**************************");
		printf("CBK: %p\n",callback->userdata);
		print_line("type A: "+itos(shape_A->get_type()));
		print_line("type B: "+itos(shape_B->get_type()));
		print_line("xform A: "+*transform_A);
		print_line("xform B: "+*transform_B);
		print_line("normal: "+best_axis);
		print_line("depth: "+rtos(best_depth));
		print_line("index: "+itos(best_axis_index));

		for(int i=0;i<support_count_A;i++) {

			print_line("A-"+itos(i)+": "+supports_A[i]);
		}

		for(int i=0;i<support_count_B;i++) {

			print_line("B-"+itos(i)+": "+supports_B[i]);
		}
//*/




		callback->normal=best_axis;
		_generate_contacts_from_supports(supports_A,support_count_A,supports_B,support_count_B,callback);

		if (callback && callback->sep_axis && *callback->sep_axis!=Vector2())
			*callback->sep_axis=Vector2(); //invalidate previous axis (no test)
		//CollisionSolver2DSW::CallbackResult cbk=NULL;
		//cbk(Vector2(),Vector2(),NULL);

	}
	_FORCE_INLINE_ bool test_axis(const Vector2& p_axis) {

		Vector2 axis=p_axis;


		if (	Math::abs(axis.x)<CMP_EPSILON &&
			Math::abs(axis.y)<CMP_EPSILON) {
			// strange case, try an upwards separator
			axis=Vector2(0.0,1.0);
		}

		real_t min_A,max_A,min_B,max_B;

		if (castA)
			shape_A->project_range_cast(motion_A,axis,*transform_A,min_A,max_A);
		else
			shape_A->project_range(axis,*transform_A,min_A,max_A);

		if (castB)
			shape_B->project_range_cast(motion_B,axis,*transform_B,min_B,max_B);
		else
			shape_B->project_range(axis,*transform_B,min_B,max_B);

		if (withMargin) {
			min_A-=margin_A;
			max_A+=margin_A;
			min_B-=margin_B;
			max_B+=margin_B;
		}

		min_B -= ( max_A - min_A ) * 0.5;
		max_B += ( max_A - min_A ) * 0.5;

		real_t dmin = min_B - ( min_A + max_A ) * 0.5;
		real_t dmax = max_B - ( min_A + max_A ) * 0.5;

		if (dmin > 0.0 || dmax < 0.0) {
			if (callback && callback->sep_axis)
				*callback->sep_axis=axis;
#ifdef DEBUG_ENABLED
			best_axis_count++;
#endif

			return false; // doesn't contain 0
		}

		//use the smallest depth

		dmin = Math::abs(dmin);

		if ( dmax < dmin ) {
			if ( dmax < best_depth ) {
				best_depth=dmax;
				best_axis=axis;
#ifdef DEBUG_ENABLED
				best_axis_index=best_axis_count;
#endif

			}
		} else {
			if ( dmin < best_depth ) {
				best_depth=dmin;
				best_axis=-axis; // keep it as A axis
#ifdef DEBUG_ENABLED
				best_axis_index=best_axis_count;
#endif
			}
		}

	//	print_line("test axis: "+p_axis+" depth: "+rtos(best_depth));
#ifdef DEBUG_ENABLED
		best_axis_count++;
#endif

		return true;
	}
	_FORCE_INLINE_ void generate_contacts() {

		// nothing to do, don't generate
		if (best_axis == Vector3(0.0, 0.0, 0.0))
			return;

		if (!callback->callback) {
			//just was checking intersection?
			callback->collided = true;
			if (callback->prev_axis)
				*callback->prev_axis = best_axis;
			return;
		}

		static const int max_supports = 16;

		Vector3 supports_A[max_supports];
		int support_count_A;
		shape_A->get_supports(transform_A->basis.xform_inv(-best_axis).normalized(), max_supports, supports_A, support_count_A);
		for (int i = 0; i < support_count_A; i++) {
			supports_A[i] = transform_A->xform(supports_A[i]);
		}

		if (withMargin) {

			for (int i = 0; i < support_count_A; i++) {
				supports_A[i] += -best_axis * margin_A;
			}
		}

		Vector3 supports_B[max_supports];
		int support_count_B;
		shape_B->get_supports(transform_B->basis.xform_inv(best_axis).normalized(), max_supports, supports_B, support_count_B);
		for (int i = 0; i < support_count_B; i++) {
			supports_B[i] = transform_B->xform(supports_B[i]);
		}

		if (withMargin) {

			for (int i = 0; i < support_count_B; i++) {
				supports_B[i] += best_axis * margin_B;
			}
		}
		/*
		print_line("best depth: "+rtos(best_depth));
		print_line("best axis: "+(best_axis));
		for(int i=0;i<support_count_A;i++) {

			print_line("A-"+itos(i)+": "+supports_A[i]);
		}
		for(int i=0;i<support_count_B;i++) {

			print_line("B-"+itos(i)+": "+supports_B[i]);
		}
*/
		callback->normal = best_axis;
		if (callback->prev_axis)
			*callback->prev_axis = best_axis;
		_generate_contacts_from_supports(supports_A, support_count_A, supports_B, support_count_B, callback);

		callback->collided = true;
		//CollisionSolverSW::CallbackResult cbk=NULL;
		//cbk(Vector3(),Vector3(),NULL);
	}