예제 #1
0
파일: vector.c 프로젝트: Allanis/SpaceJam
// Collision detection of two boxs with arbitrary angles.
// Does only one side (a->b) of the collision.
//  -- If no collision, then no collision..
//  -- If returns collision, check the other side (b<-a)
//  -- A vector will be returned to displace 'a' so that there is no
//     no collision anymore. The vector returned is one of the normals of 'b'.
static vec_t box_o_o_collision(box_t a, box_t b) {
  // We will perform the collision using b's point of view and axes because
  // those will be consided the surface normals, and we want to return 'a's'
  // displacement in terms of 'a's' orientation vectors. -- So this may at times look reveresed.
  vec_t dist = vec_diff(b.pos, a.pos);

  // Normalized axis of box b. One of those axes will be the surface normal.
  vec_t axn[2]; // = { b.axis0, b.axis1 };
  float axl[2]; // Half axis length.
  // Half axis.
  vec_t ahx0 = vec_scale(a.axis0, a.size.x);
  vec_t ahx1 = vec_scale(a.axis1, a.size.y);

  // Distance we need to displace 'a' to remove the collision.
  //  -- (0, 0) => no collision.
  float col_vec[2] = { 0.0, 0.0 };
  int i = 2;
  axn[0] = b.axis0;
  axn[1] = b.axis1;
  axl[0] = b.size.x;
  axl[1] = b.size.y;
  while(i--) {
    float a1, a2, d;
    // We check if the distance from center to center is smaller
    // than the sum of the distance from center to box edge
    // and that projection along each vector normal.
    // If it is false for one normal, we have no collision.
    // Otherwise we have the displacement distance to remove the collision.
    
    a1 = vec_absdot(axn[i], ahx0);
    a2 = vec_absdot(axn[i], ahx1);
    d  = vec_absdot(axn[i], dist);
    col_vec[i] = a1 + a2 + axl[i] - d;

    if(col_vec[i] <= 0) {
      // Then there was no intersection.
      return vec_new(0, 0);
    }
  }
  if(col_vec[0] < col_vec[1]) {
    if(vec_dot(dist, axn[0]) > 0) {
      return vec_scale(axn[0], col_vec[0]);
    } else {
      return vec_scale(axn[0], -col_vec[0]);
    }
  } else {
    if(vec_dot(dist, axn[1]) > 0) {
      return vec_scale(axn[1], col_vec[1]);
    } else {
      return vec_scale(axn[1], -col_vec[1]);
    }
  }
}
예제 #2
0
파일: vector.c 프로젝트: brownman/bastos85
/**
 * Collision detection of two box with arbitrary angles. Does
 * only one side (a->b) of the collision. 
 * if it returns no collision -> no collision
 * if it returns a collision -> check the other side (b<-a)
 * It will return a vector to displace a so that there is no collision
 * anymore. the vector returned is one of the normals of b.
*/
static vec_t box_o_o_collision(box_t a, box_t b){
	/* we will perform the collision using b point of view and axis 
	 * because those will be considered the surface normals, and we
	 * want to return 'a' displacement in terms of 'b' surface normals 
	 * and not in terms of 'a' orientation vectors. 
	 * 	that's why the logic looks reverse at times 
	 * */
	vec_t dist = vec_diff(b.pos,a.pos);
	/* normalized axis of the box b. One of those axis will be the
	 * surface normal. */
	vec_t axn[2];	/* = {b.axis0, b.axis1}; */
	float axl[2];	/* half axis length	*/
	/* a half axis */
	vec_t ahx0 = vec_scale(a.axis0,a.size.x);
	vec_t ahx1 = vec_scale(a.axis1,a.size.y);
	/*distance we need to displace a to remove the collision. 
	 * (0,0) => no collision*/
	float col_vec[2] = { 0.0, 0.0 };
	int i = 2;
	axn[0] = b.axis0;
	axn[1] = b.axis1;
	axl[0] = b.size.x;
	axl[1] = b.size.y;

	while(i--){
		float a1,a2,d;
		/* we check if the distance from center to center is smaller
		 * than the sum of the distance from center to box edges.
		 * and that projected along each vector normal. 
		 * If it is false for one normal, we have no collision. 
		 * otherwise we have the displacement distance to remove 
		 * the collision.
		 */
		a1 = vec_absdot(axn[i],ahx0);
		a2 = vec_absdot(axn[i],ahx1);
		d =  vec_absdot(axn[i],dist);
		col_vec[i] =      a1 + a2 + axl[i] - d;
		if(col_vec[i] <= 0){	/* No intersection ! */
			return vec_new(0,0);
		}
		/*printf("a1:%f\t,a2:%f\t,b1:%f\t,d:%f\tr:%f\n",
				a1,a2,axl[i],d,col_vec[i] );*/
	}
	/* col_vec has the distance we need to displace 'a' along axn[0],axn[1]
	 * to remove the collision. We now need to pick the shortest 
	 * distance and the right direction.
	 * This is just choosing smallest dist and flipping normals if 
	 * necessary.
	 */
	if(col_vec[0] < col_vec[1]){
		if(vec_dot(dist,axn[0]) > 0 ){
			return vec_scale(axn[0], col_vec[0]);
		}else{
			return vec_scale(axn[0],-col_vec[0]);
		}
	}else{
		if(vec_dot(dist,axn[1]) > 0){
			return vec_scale(axn[1], col_vec[1]);
		}else{
			return vec_scale(axn[1],-col_vec[1]);
		}
	}
}