示例#1
0
/*********************************************************************
 * This function returns a pointer to the sphere object that the
 * ray intersects first; NULL if no intersection. You should decide
 * which arguments to use for the function. For exmaple, note that you
 * should return the point of intersection to the calling function.
 **********************************************************************/
Spheres *intersect_scene(Point o, Vector u, Spheres *sph, Point *hit, int sindex) {
	Spheres *closest_sph = NULL;
	Point closest_hit;
	float min = -1;

	while (sph != NULL)
	{
		// skips this sphere (used for shadows)
		if (sph->index == sindex)
		{
			sph = sph->next;
			continue;
		}

		Point hit;
		float intersect;
		if (sph->index == 0)
			intersect = intersect_board(o, u, sph, &hit);
		else
			intersect = intersect_sphere(o, u, sph, &hit);

		if ( intersect > 0 && (intersect < min || min < 0) )
		{
			min = intersect;
			closest_sph = sph;
			closest_hit = hit;
		}

		sph = sph->next;
	}

	if (hit != NULL)
		*hit = closest_hit;
	return closest_sph;
}
示例#2
0
文件: pick.c 项目: dfyockey/vulcan
int
pick_square(struct position *pos, const struct board_state *state,
  const struct matrix *mv, int x, int y)
{
	struct ray ray_orig;	/* pick ray in world coordinates */
	struct ray ray_obj;	/* pick ray in object coordinates */
	struct matrix inv_mv;
	struct vector p;
	int i, j;
	struct position first_pos;
	const unsigned char *ps;
	struct hit hit;
	int no_hits, hit_level, hit_square;
	float closer_t;

	/* ray in world coordinates */

	get_pick_ray(&ray_orig, x, y);

	/* transform ray to game coordinates */

	mat_invert_copy(&inv_mv, mv);
	mat_transform_ray(&ray_obj, &inv_mv, &ray_orig);

	no_hits = 1;
	hit_level = hit_square = -1;
	closer_t = -1.f;

	for (i = 0; i < NUM_MAIN_BOARDS; i++) {
		/* intersection with main board */

		get_main_board_xyz(&p, i);
		get_main_board_position(&first_pos, i);

		ps = &state->board[first_pos.level][first_pos.square];

		if (intersect_board(&hit, &ray_obj, &p, ps, MAIN_BOARD_SIZE)) {
			if (no_hits || hit.t < closer_t) {
				closer_t = hit.t;
				hit_level = first_pos.level;
				hit_square = first_pos.square +
				  hit.row*BCOLS + hit.col;
				no_hits = 0;
			}
		}

		for (j = 0; j < 8; j++) {
			if (ATTACK_BOARD_IS_ACTIVE(state, i, j)) {
				/* intersection with attack board */

				hit.t = -1.f;

				get_attack_board_xyz(&p, i, j);
				get_attack_board_position(&first_pos, i, j);

				ps = &state->board
				  [first_pos.level][first_pos.square];

				if (intersect_board(&hit, &ray_obj, &p, ps,
				  ATTACK_BOARD_SIZE)) {
				  	if (no_hits || hit.t < closer_t) {
						closer_t = hit.t;
						hit_level = first_pos.level;
						hit_square = first_pos.square +
						  hit.row*BCOLS + hit.col;
						no_hits = 0;
					}
				}
			}
		}
	}

	if (no_hits)
		return 0;

	pos->level = hit_level;	
	pos->square = hit_square;

	return 1;
}