Ejemplo n.º 1
0
        /// <summary>
        /// Calculates the distance along the specified ray the first intersection with this object occurs.
        /// </summary>
        /// <param name="ray">The ray to test.</param>
        /// <returns>The distance along the ray the first intersection with this object occurs. If no intersection, returns a negative value.</returns>
        public override float IntersectDistance(Ray ray)
        {
            if (ray == null) {
              throw new ArgumentNullException("ray");
            }

            var P = ray.Start - Centre;
            var A = ray.Direction * ray.Direction;
            var B = 2 * P * ray.Direction;
            var C = P * P - Radius * Radius;
            var t = SolveQuadraticMinimumNonnegative(A, B, C);
            if (!t.HasValue) {
              return -1.0f;
            }
            return t.Value;
        }
Ejemplo n.º 2
0
 /// <summary>
 /// Calculates the distance along the specified ray the first intersection with this object occurs.
 /// </summary>
 /// <param name="ray">The ray to test.</param>
 /// <returns>The distance along the ray the first intersection with this object occurs. If no intersection, returns a negative value.</returns>
 public abstract float IntersectDistance(Ray ray);
Ejemplo n.º 3
0
        /// <summary>
        /// Calculates the distance along the specified ray the first intersection with this object occurs.
        /// </summary>
        /// <param name="ray">The ray to test.</param>
        /// <returns>The distance along the ray the first intersection with this object occurs. If no intersection, returns a negative value.</returns>
        public override float IntersectDistance(Ray ray)
        {
            if (ray == null) {
              throw new ArgumentNullException("ray");
            }

            var nd = normal * ray.Direction;
            if (nd == 0) {
              return -1.0f;
            }
            var start = new Vector(ray.Start.X, ray.Start.Y, ray.Start.Z);
            var t = (d - normal * start) / (nd);

            var q = ray.Start + t * ray.Direction;
            if (((P2 - P1) % (q - P1)) * normal < 0.0f) {
              return -1.0f;
            }
            if (((P3 - P2) % (q - P2)) * normal < 0.0f) {
              return -1.0f;
            }
            if (((P1 - P3) % (q - P3)) * normal < 0.0f) {
              return -1.0f;
            }
            return t;
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Shoot a ray into the scene and determine the colour at the impact point.
        /// </summary>
        /// <param name="ray">The ray to shoot into the scene.</param>
        /// <returns>The colour of the impacted point in the scene.</returns>
        private Colour ShootRay(Ray ray)
        {
            Colour finalOutput = new Colour(0.0f, 0.0f, 0.0f);
            float coefficient = 1.0f;
            uint count = 0u;

            do {
              Colour output = new Colour(0.0f, 0.0f, 0.0f);
              IObject closestObject = null;
              float closestDistance = float.MaxValue;
              foreach (var o in Objects) {
            float t = o.IntersectDistance(ray);
            if (t > 0.001f && t < closestDistance) {
              closestObject = o;
              closestDistance = t;
            }
              }
              if (closestObject == null) {
            break;
              }

              // Calculate the point of intersection.
              Point intersection = ray.Start + closestDistance * ray.Direction;

              // Get normal of object surface at impact of ray.
              Vector normal = closestObject.GetNormalAtPoint(intersection);

              foreach (var l in Lights) {
            Vector toLightSource = (l.Location - intersection).Normalise();
            float cosineLightAngle = normal * toLightSource;
            if (cosineLightAngle <= 0.0f) {
              // The light is below the surface.
              continue;
            }

            bool inShadow = false;
            foreach (var o in Objects) {
              if (o == closestObject) {
            continue;
              }
              if (o.IntersectDistance(new Ray(intersection, toLightSource)) > 0.0f) {
            inShadow = true;
            break;
              }
            }

            if (!inShadow) {
              var lambertianReflectance = (Colour)closestObject.Material.Colour * (Colour)l.Colour * cosineLightAngle;
              output += lambertianReflectance;

              var halfwayVector = (toLightSource - ray.Direction).Normalise();
              var halfwayNormalAngle = halfwayVector * normal;
              var blinnTerm = (Colour)l.Colour * closestObject.Material.SpecularTerm * (float)Math.Pow(Math.Max(halfwayNormalAngle, 0.0f), closestObject.Material.SpecularPower);
              output += blinnTerm;
            }
              }

              finalOutput += output * coefficient;

              var newRayDirection = (ray.Direction - 2 * normal * (normal * ray.Direction)).Normalise();
              ray = new Ray(intersection, newRayDirection);
              coefficient *= closestObject.Material.Reflectance;
            } while (++count < MAX_ITERATIONS && coefficient > 0.0f);
            return finalOutput;
        }