/********************************************************************* * 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; }
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; }