//面面求交 Line plane_intersection(const Plane &u, const Plane &v) { Line ret; ret.a = (line_to_plane(Line(v.a, v.b), u) == 0) ? line_plane_intersection(Line(v.b, v.c), u) : line_plane_intersection(Line(v.a, v.b), u); ret.b = (line_to_plane(Line(v.c, v.a), u) == 0) ? line_plane_intersection(Line(v.b, v.c), u) : line_plane_intersection(Line(v.a, v.c), u); return ret; }
bool hitscan_sprite_mobs(const Vec3& position, const Vec3& direction, float range, SpriteMobID& id, float& distance, Vec3& collision_point) { SpriteMobID nearest_mob = NULL_SPRITE_MOB; float nearest_distance = 100000.0f; Vec3 nearest_collision_point = vec3_init(0); const float range_sq = range * range; const Vec3 up = vec3_init(0, 0, 1); for (size_t i=0, j=0; i<sprite_mob_list->max && j<sprite_mob_list->count; i++) { // TODO // do a line-plane intersection test against the mob, if its in frustum SpriteMob* m = sprite_mob_list->objects[i]; if (m == NULL) continue; j++; Vec3 p = m->get_center(); p = quadrant_translate_position(position, p); if (vec3_distance_squared(position, p) > range_sq) continue; float rad_sq = 10000.0f; Vec3 line_point = vec3_init(0); if (!sphere_line_distance(position, direction, p, line_point, rad_sq)) continue; Vec3 forward = vec3_sub(position, p); forward.z = 0.0f; if (unlikely(vec3_length_squared(forward) == 0)) continue; forward = vec3_normalize(forward); const Vec3 right = vec3_normalize(vec3_cross(forward, up)); float d = 1000000.0f; float width = get_mob_width(m->type) * 0.5f; float height = get_mob_height(m->type) * 0.5f; if (!line_plane_intersection(position, direction, p, width, height, forward, right, up, d)) continue; if (d >= nearest_distance) continue; nearest_distance = d; nearest_mob = m->id; nearest_collision_point = line_point; } id = nearest_mob; distance = nearest_distance; collision_point = translate_position(nearest_collision_point); return (nearest_mob != NULL_SPRITE_MOB); }