// MouseToWorldRay // // This takes the view matricies, and a window-local mouse coordinate, and returns a ray in world space. public static SSRay MouseToWorldRay( Matrix4 projection, Matrix4 view, System.Drawing.Size viewport, Vector2 mouse) { // these mouse.Z values are NOT scientific. // Near plane needs to be < -1.5f or we have trouble selecting objects right in front of the camera. (why?) Vector3 pos1 = UnProject(ref projection, view, viewport, new Vector3(mouse.X, mouse.Y, -1.5f)); // near Vector3 pos2 = UnProject(ref projection, view, viewport, new Vector3(mouse.X, mouse.Y, 1.0f)); // far return(SSRay.FromTwoPoints(pos1, pos2)); }
/// <summary> /// Distance from a ray to a point at the closest spot. The ray is assumed to be infinite length. /// </summary> /// <param name="ray"></param> /// <param name="point"></param> /// <returns></returns> public static float DistanceToLine(SSRay ray, Vector3 point, out float distanceAlongRay) { // http://en.wikipedia.org/wiki/Distance_from_a_point_to_a_line Vector3 a = ray.pos; Vector3 n = ray.dir; Vector3 p = point; var t = Vector3.Dot((a - p), n); distanceAlongRay = -t; return(((a - p) - t * n).Length); }
// Ray to AABB (AxisAlignedBoundingBox) // http://gamedev.stackexchange.com/questions/18436/most-efficient-aabb-vs-ray-collision-algorithms public static bool intersectRayAABox2(SSRay ray, SSAABB box, ref float tnear, ref float tfar) { Vector3d T_1 = new Vector3d(); Vector3d T_2 = new Vector3d(); // vectors to hold the T-values for every direction double t_near = double.MinValue; // maximums defined in float.h double t_far = double.MaxValue; for (int i = 0; i < 3; i++) { //we test slabs in every direction if (ray.dir[i] == 0) { // ray parallel to planes in this direction if ((ray.pos[i] < box.Min[i]) || (ray.pos[i] > box.Max[i])) { return(false); // parallel AND outside box : no intersection possible } } else { // ray not parallel to planes in this direction T_1[i] = (box.Min[i] - ray.pos[i]) / ray.dir[i]; T_2[i] = (box.Max[i] - ray.pos[i]) / ray.dir[i]; if (T_1[i] > T_2[i]) { // we want T_1 to hold values for intersection with near plane var swp = T_2; // swap T_1 = swp; T_2 = T_1; } if (T_1[i] > t_near) { t_near = T_1[i]; } if (T_2[i] < t_far) { t_far = T_2[i]; } if ((t_near > t_far) || (t_far < 0)) { return(false); } } } tnear = (float)t_near; tfar = (float)t_far; // put return values in place return(true); // if we made it here, there was an intersection - YAY }
} // fn public static bool intersectRayAABox1(SSRay ray, SSAABB box, ref float tnear, ref float tfar) { // r.dir is unit direction vector of ray Vector3 dirfrac = new Vector3(); float t; dirfrac.X = 1.0f / ray.dir.X; dirfrac.Y = 1.0f / ray.dir.Y; dirfrac.Z = 1.0f / ray.dir.Z; // lb is the corner of AABB with minimal coordinates - left bottom, rt is maximal corner // r.org is origin of ray float t1 = (box.Min.X - ray.pos.X) * dirfrac.X; float t2 = (box.Max.X - ray.pos.X) * dirfrac.X; float t3 = (box.Min.Y - ray.pos.Y) * dirfrac.Y; float t4 = (box.Max.Y - ray.pos.Y) * dirfrac.Y; float t5 = (box.Min.Z - ray.pos.Z) * dirfrac.Z; float t6 = (box.Max.Z - ray.pos.Z) * dirfrac.Z; float tmin = Math.Max(Math.Max(Math.Min(t1, t2), Math.Min(t3, t4)), Math.Min(t5, t6)); float tmax = Math.Min(Math.Min(Math.Max(t1, t2), Math.Max(t3, t4)), Math.Max(t5, t6)); // if tmax < 0, ray (line) is intersecting AABB, but whole AABB is behing us if (tmax < 0) { t = tmax; return(false); } // if tmin > tmax, ray doesn't intersect AABB if (tmin > tmax) { t = tmax; return(false); } t = tmin; return(true); }
public static float DistanceToLine_2(SSRay ray, Vector3 point) { return(Vector3.Cross(ray.dir, point - ray.pos).Length); }