void CombatCamera::ViewportRay(double screen_x, double screen_y, double out_ray_origin[3], double out_ray_direction[3]) const { Matrix projection(4, 4); std::copy(m_camera.getProjectionMatrix()[0], m_camera.getProjectionMatrix()[0] + 16, projection.data().begin()); Matrix view(4, 4); std::copy(m_camera.getViewMatrix(true)[0], m_camera.getViewMatrix(true)[0] + 16, view.data().begin()); Matrix inverse_vp = Inverse4(prod(projection, view)); double nx = (2.0 * screen_x) - 1.0; double ny = 1.0 - (2.0 * screen_y); Matrix near_point(3, 1); near_point(0, 0) = nx; near_point(1, 0) = ny; near_point(2, 0) = -1.0; // Use mid_point rather than far point to avoid issues with infinite projection Matrix mid_point(3, 1); mid_point(0, 0) = nx; mid_point(1, 0) = ny; mid_point(2, 0) = 0.0; // Get ray origin and ray target on near plane in world space Matrix ray_origin = Matrix4xVector3(inverse_vp, near_point); Matrix ray_target = Matrix4xVector3(inverse_vp, mid_point); Matrix ray_direction = ray_target - ray_origin; ray_direction /= ray_direction(0, 0) * ray_direction(0, 0) + ray_direction(1, 0) * ray_direction(1, 0) + ray_direction(2, 0) * ray_direction(2, 0); std::copy(ray_origin.data().begin(), ray_origin.data().end(), out_ray_origin); std::copy(ray_direction.data().begin(), ray_direction.data().end(), out_ray_direction); }
/** * @name vertical_projection_point * * For one point on the outline, find the corresponding point on the * other side of the outline that is a likely projection for a split * point. This is done by iterating through the edge points until the * X value of the point being looked at is greater than the X value of * the split point. Ensure that the point being returned is not right * next to the split point. Return the edge point in *best_point as * a result, and any points that were newly created are also saved on * the new_points list. */ void Wordrec::vertical_projection_point(EDGEPT *split_point, EDGEPT *target_point, EDGEPT** best_point, EDGEPT_CLIST *new_points) { EDGEPT *p; /* Iterator */ EDGEPT *this_edgept; /* Iterator */ EDGEPT_C_IT new_point_it(new_points); int x = split_point->pos.x; /* X value of vertical */ int best_dist = LARGE_DISTANCE;/* Best point found */ if (*best_point != nullptr) best_dist = edgept_dist(split_point, *best_point); p = target_point; /* Look at each edge point */ do { if (((p->pos.x <= x && x <= p->next->pos.x) || (p->next->pos.x <= x && x <= p->pos.x)) && !same_point(split_point->pos, p->pos) && !same_point(split_point->pos, p->next->pos) && !p->IsChopPt() && (*best_point == nullptr || !same_point((*best_point)->pos, p->pos))) { if (near_point(split_point, p, p->next, &this_edgept)) { new_point_it.add_before_then_move(this_edgept); } if (*best_point == nullptr) best_dist = edgept_dist (split_point, this_edgept); this_edgept = pick_close_point(split_point, this_edgept, &best_dist); if (this_edgept) *best_point = this_edgept; } p = p->next; } while (p != target_point); }