//// =========================================================================================================== //// Methods //// =========================================================================================================== public static IntersectionState Create(Intersection hit, Ray ray, IntersectionList intersections) { // Copy the intersection's properties for convenience. double t = hit.T; Shape shape = hit.Shape; // Precompute some useful values. Point point = ray.PositionAt(hit.T); Vector eye = -ray.Direction; Vector normal = shape.NormalAt(point, hit); bool isInside = false; if (normal.Dot(eye) < 0) { isInside = true; normal = -normal; } Point overPoint = point + (normal * NumberExtensions.Epsilon); Point underPoint = point - (normal * NumberExtensions.Epsilon); Vector reflection = ray.Direction.Reflect(normal); // Calculate the refraction values. var containers = new List <Shape>(); double n1 = 1.0; double n2 = 1.0; foreach (Intersection intersection in intersections) { if (intersection == hit) { n1 = containers.Count == 0 ? 1.0 : containers[^ 1].Material.RefractiveIndex;
public bool IsShadowed(Point point, Light light) { Vector pointToLightVector = light.Position - point; double distance = pointToLightVector.Magnitude; Vector direction = pointToLightVector.Normalize(); var ray = new Ray(point, direction); IntersectionList intersections = Intersect(ray); Intersection? hit = intersections.Hit; return(hit != null && hit.T < distance && !hit.Shape.IsShadowHidden); }
/// <summary> /// Iterates over all of the shapes in the world and returns all of the hits for the specified ray. /// </summary> /// <param name="ray">The ray to use for hit testing.</param> /// <returns>The list of all intersections for the specified ray.</returns> public IntersectionList Intersect(Ray ray) { var hits = new IntersectionList(); foreach (Shape shape in Shapes) { IntersectionList shapeHits = shape.Intersect(ray); hits.AddRange(shapeHits); } return(hits); }
/// <summary> /// Finds the color of the first shape that is hit for the given ray. /// </summary> /// <param name="ray">The ray to use for hit testing.</param> /// <param name="maxRecursion">The maximum number of additional rays to use for reflection.</param> /// <returns> /// The color for the part of the shape that the ray hits, or <see cref="Colors.Black"/> if no shape is hit. /// </returns> public Color ColorAt(Ray ray, int maxRecursion = MaxRecursion) { IntersectionList intersections = Intersect(ray); Intersection? hit = intersections.Hit; if (hit == null) { return(Colors.Black); } var state = IntersectionState.Create(hit, ray, intersections); Color color = ShadeHit(state, maxRecursion); return(color); }