public void If_the_ray_does_not_point_at_the_AABB_the_result_is_false_and_the_distance_is_set_to_infinity() { var box = new AxisAlignedBoundingBox(new Point(1, 1, 1), new Point(2, 2, 2)); var ray = new Ray(new Point(0.5, -1, 2), -Vector.UnitY); Assert.False(box.IntersectsRay(ray, 0, double.PositiveInfinity)); }
public void If_the_ray_points_at_the_AABB_the_result_is_true_and_the_distance_is_set_correctly() { var box = new AxisAlignedBoundingBox(new Point(0, 0, 0), new Point(2, 2, 2)); var ray = new Ray(new Point(-1, 1, 1), new Vector(1, 0.1, 0.2).ToUnitVector()); Assert.True(box.IntersectsRay(ray, 0, double.PositiveInfinity)); }
public void RenderScene(RenderingContext context) { Ensure.That("context", context).IsNotNull(); //// transforms from image space into camera space //var imageMatrix = Matrix.Scaling(1d / context.Target.Width, 1d / context.Target.Height, 1); foreach (var pixel in context.Target.GetPixels()) { var colorAccumulator = Color.Black; foreach (var pixelSpaceSample in _pixelSampleGenerator.GenerateSamples(context.SamplesPerPixel)) { var imageSpaceSample = new Point(pixel.X + pixelSpaceSample.X, pixel.Y + pixelSpaceSample.Y, 1); var projectionSpaceRay = new Ray(context.ImageMatrix * imageSpaceSample, Vector.UnitZ); var cameraSpaceRay = context.ProjectionMatrix * projectionSpaceRay; // TODO: transform camera space ray into world space colorAccumulator += _algorithm.DetermineRayColor(cameraSpaceRay, context.World); } context.Target.SetPixelColor(pixel, colorAccumulator / context.SamplesPerPixel); } }
public Intersection FindClosestIntersectionWith(Ray ray) { var intersection = Geometry.FindClosestIntersectionWith(ray); if (intersection == null) return null; return intersection.WithMaterial(Material); }
public void If_the_triangle_is_behind_the_ray_the_result_is_null() { var ray = new Ray(Point.Zero, -Vector.UnitX); var triangle = new Triangle( new Point(2, 2, 0), new Point(2, -2, 2), new Point(2, -2, -2) ); Assert.Null(triangle.FindClosestIntersectionWith(ray)); }
public void If_the_ray_points_at_the_triangle_the_correct_distance_is_set_on_the_result() { var ray = new Ray(Point.Zero, Vector.UnitX); var triangle = new Triangle( new Point(2, 2, 0), new Point(2, -2, 2), new Point(2, -2, -2) ); Assert.Equal(2d, triangle.FindClosestIntersectionWith(ray).Distance); }
public static void The_returned_distance_is_the_distance_from_the_ray_origin_to_the_closest_edge_of_the_sphere() { var sphere = new Sphere(new Point(0, 0, 2), 1); var ray = new Ray(Point.Zero, Vector.UnitZ); Assert.Equal(1, sphere.FindClosestIntersectionWith(ray).Distance); sphere = new Sphere(new Point(0, 0, -2), 1); ray = new Ray(Point.Zero, -Vector.UnitZ); Assert.Equal(1, sphere.FindClosestIntersectionWith(ray).Distance); sphere = new Sphere(new Point(15, 0, 0), 3); ray = new Ray(Point.Zero, Vector.UnitX); Assert.Equal(12, sphere.FindClosestIntersectionWith(ray).Distance); }
public Intersection FindClosestIntersectionWith(Ray ray) { Intersection closest = null; foreach(var intersectable in _geometry) { var intersection = intersectable.FindClosestIntersectionWith(ray); if (closest == null || (intersection != null && intersection.Distance < closest.Distance)) { closest = intersection; } } return closest; }
public Intersection FindClosestIntersectionWith(Ray ray) { Intersection closest = null; if (_left != null && _leftBounds.IntersectsRay(ray, 0, double.PositiveInfinity)) { closest = _left.FindClosestIntersectionWith(ray); } if (_right != null && _rightBounds.IntersectsRay(ray, 0, (closest != null) ? closest.Distance : double.PositiveInfinity)) { closest = Intersection.Closest(closest, _right.FindClosestIntersectionWith(ray)); } return closest; }
/// <summary> /// TODO: This method is BUTT SLOW. For now it just loops over all of the triangles in the mesh and returns the closest intersection... /// </summary> public Intersection FindClosestIntersectionWith(Ray ray) { if (_boundingBox == null) { _boundingBox = GetBoundingBox(); } if (!_boundingBox.IntersectsRay(ray, 0, double.PositiveInfinity)) { return null; } return Triangles .Select(triangle => triangle.FindClosestIntersectionWith(ray)) .WhereNotNull() .OrderBy(intersection => intersection.Distance) .FirstOrDefault(); }
public void For_ray_directions_with_zeros_the_result_is_still_true_for_valid_intersections() { var box = new AxisAlignedBoundingBox(new Point(0, 0, 0), new Point(2, 2, 2)); var ray = new Ray(new Point(-1, 1, 1), Vector.UnitX); Assert.True(box.IntersectsRay(ray, 0, double.PositiveInfinity)); box = new AxisAlignedBoundingBox(new Point(0, 0, 0), new Point(2, 2, 2)); ray = new Ray(new Point(1, -1, 1), Vector.UnitY); Assert.True(box.IntersectsRay(ray, 0, double.PositiveInfinity)); box = new AxisAlignedBoundingBox(new Point(0, 0, 0), new Point(2, 2, 2)); ray = new Ray(new Point(1, 1, -1), Vector.UnitZ); Assert.True(box.IntersectsRay(ray, 0, double.PositiveInfinity)); }
public Intersection FindClosestIntersectionWith(Ray ray) { var between = ray.Origin - Position; var b = Vector.DotProduct(between, ray.Direction); var c = between.SquaredLength - (Radius * Radius); var d = b * b - c; if (d <= 0) { return null; } var distance = (b > 0) ? -b + System.Math.Sqrt(d) : -b - System.Math.Sqrt(d); return new Intersection(ray, distance); }
/// <summary> /// Performs ray-triangle intersection based on Moller-Trubmore 97 /// </summary> public Intersection FindClosestIntersectionWith(Ray ray) { var translated = ray.Origin - _a; var edge1 = _b - _a; var edge2 = _c - _a; var p = Vector.CrossProduct(ray.Direction, edge2); var q = Vector.CrossProduct(translated, edge1); var determinant = Vector.DotProduct(p, edge1); if (determinant == 0) { return null; } var u = Vector.DotProduct(p, translated) / determinant; // u + v must be between 0 and 1, which means that u must also be if (u < 0d || u > 1d) { return null; } var v = Vector.DotProduct(q, ray.Direction) / determinant; if (v < 0d || u + v > 1d) { return null; } // distance = t in the original algorithm var distance = Vector.DotProduct(q, edge2) / determinant; if (distance < 0d) { return null; } return new Intersection(ray, distance); }
public static void If_the_ray_points_at_the_sphere_the_result_is_not_null() { var sphere = new Sphere(new Point(0, 0, 5), 1); var ray = new Ray(Point.Zero, Vector.UnitZ); Assert.NotNull(sphere.FindClosestIntersectionWith(ray)); }
public bool IntersectsRay(Ray ray, double min, double max) { double tmin, tmax, tYMin, tYMax, tZMin, tZMax; if (ray.Direction.X > 0) { tmin = (Min.X - ray.Origin.X) / ray.Direction.X; tmax = (Max.X - ray.Origin.X) / ray.Direction.X; } else if(ray.Direction.X < 0) { tmax = (Min.X - ray.Origin.X) / ray.Direction.X; tmin = (Max.X - ray.Origin.X) / ray.Direction.X; } else { tmin = double.NegativeInfinity; tmax = double.PositiveInfinity; } if (ray.Direction.Y > 0) { tYMin = (Min.Y - ray.Origin.Y) / ray.Direction.Y; tYMax = (Max.Y - ray.Origin.Y) / ray.Direction.Y; } else if (ray.Direction.Y < 0) { tYMax = (Min.Y - ray.Origin.Y) / ray.Direction.Y; tYMin = (Max.Y - ray.Origin.Y) / ray.Direction.Y; } else { tYMin = double.NegativeInfinity; tYMax = double.PositiveInfinity; } if(tmin > tYMax || tYMin > tmax) return false; if (tYMin > tmin) tmin = tYMin; if (tYMax < tmax) tmax = tYMax; if (ray.Direction.Z > 0) { tZMin = (Min.Z - ray.Origin.Z) / ray.Direction.Z; tZMax = (Max.Z - ray.Origin.Z) / ray.Direction.Z; } else if (ray.Direction.Z < 0) { tZMax = (Min.Z - ray.Origin.Z) / ray.Direction.Z; tZMin = (Max.Z - ray.Origin.Z) / ray.Direction.Z; } else { tZMin = double.NegativeInfinity; tZMax = double.PositiveInfinity; } if(tmin > tZMax || tZMin > tmax) return false; if (tZMin > tmin) tmin = tZMin; if (tZMax < tmax) tmax = tZMax; return (tmin < max) && (tmax > min); }
public Color DetermineRayColor(Ray ray, IIntersectable scene) { var intersection = scene.FindClosestIntersectionWith(ray); return intersection == null ? Color.Black : intersection.Color; }