code: package org.sunflow.core;
  
  import org.sunflow.math.Matrix4;
  import org.sunflow.math.Point3;
  import org.sunflow.math.Vector3;
  
  /**
   * This class represents a ray as a oriented half line segment. The ray
   * direction is always normalized. The valid region is delimted by two distances
   * along the ray, tMin and tMax.
   */
  public final class Ray {
      public float ox, oy, oz;
      public float dx, dy, dz;
      private float tMin;
      private float tMax;
      private static final float EPSILON = 0;// 0.01f;
  
      private Ray() {
      }
  
      /**
       * Creates a new ray that points from the given origin to the given
       * direction. The ray has infinite length. The direction vector is
       * normalized.
       * 
       * @param ox ray origin x
       * @param oy ray origin y
       * @param oz ray origin z
       * @param dx ray direction x
       * @param dy ray direction y
       * @param dz ray direction z
       */
  
      public Ray(float ox, float oy, float oz, float dx, float dy, float dz) {
          this.ox = ox;
          this.oy = oy;
          this.oz = oz;
          this.dx = dx;
          this.dy = dy;
          this.dz = dz;
          float in = 1.0f / (float) Math.sqrt(dx * dx + dy * dy + dz * dz);
          this.dx *= in;
          this.dy *= in;
          this.dz *= in;
          tMin = EPSILON;
          tMax = Float.POSITIVE_INFINITY;
      }
  
      /**
       * Creates a new ray that points from the given origin to the given
       * direction. The ray has infinite length. The direction vector is
       * normalized.
       * 
       * @param o ray origin
       * @param d ray direction (need not be normalized)
       */
      public Ray(Point3 o, Vector3 d) {
          ox = o.x;
          oy = o.y;
          oz = o.z;
          dx = d.x;
          dy = d.y;
          dz = d.z;
          float in = 1.0f / (float) Math.sqrt(dx * dx + dy * dy + dz * dz);
          dx *= in;
          dy *= in;
          dz *= in;
          tMin = EPSILON;
          tMax = Float.POSITIVE_INFINITY;
      }
  
      /**
       * Creates a new ray that points from point a to point b. The created ray
       * will set tMin and tMax to limit the ray to the segment (a,b)
       * (non-inclusive of a and b). This is often used to create shadow rays.
       * 
       * @param a start point
       * @param b end point
       */
      public Ray(Point3 a, Point3 b) {
          ox = a.x;
          oy = a.y;
          oz = a.z;
          dx = b.x - ox;
          dy = b.y - oy;
          dz = b.z - oz;
          tMin = EPSILON;
          float n = (float) Math.sqrt(dx * dx + dy * dy + dz * dz);
          float in = 1.0f / n;
          dx *= in;
          dy *= in;
          dz *= in;
          tMax = n - EPSILON;
      }
  
      /**
       * Create a new ray by transforming the supplied one by the given matrix. If
       * the matrix is <code>null</code>, the original ray is returned.
       * 
       * @param m matrix to transform the ray by
       */
      public Ray transform(Matrix4 m) {
          if (m == null)
              return this;
          Ray r = new Ray();
          r.ox = m.transformPX(ox, oy, oz);
          r.oy = m.transformPY(ox, oy, oz);
          r.oz = m.transformPZ(ox, oy, oz);
          r.dx = m.transformVX(dx, dy, dz);
          r.dy = m.transformVY(dx, dy, dz);
          r.dz = m.transformVZ(dx, dy, dz);
          r.tMin = tMin;
          r.tMax = tMax;
          return r;
      }
  
      /**
       * Normalize the direction component of the ray.
       */
      public void normalize() {
          float in = 1.0f / (float) Math.sqrt(dx * dx + dy * dy + dz * dz);
          dx *= in;
          dy *= in;
          dz *= in;
      }
  
      /**
       * Gets the minimum distance along the ray - usually 0.
       * 
       * @return value of the smallest distance along the ray
       */
      public final float getMin() {
          return tMin;
      }
  
      /**
       * Gets the maximum distance along the ray. May be infinite.
       * 
       * @return value of the largest distance along the ray
       */
      public final float getMax() {
          return tMax;
      }
  
      /**
       * Creates a vector to represent the direction of the ray.
       * 
       * @return a vector equal to the direction of this ray
       */
      public final Vector3 getDirection() {
          return new Vector3(dx, dy, dz);
      }
  
      /**
       * Checks to see if the specified distance falls within the valid range on
       * this ray. This should always be used before an intersection with the ray
       * is detected.
       * 
       * @param t distance to be tested
       * @return <code>true</code> if t falls between the minimum and maximum
       *         distance of this ray, <code>false</code> otherwise
       */
      public final boolean isInside(float t) {
          return (tMin < t) && (t < tMax);
      }
  
      /**
       * Gets the end point of the ray. A reference to <code>dest</code> is
       * returned to support chaining.
       * 
       * @param dest reference to the point to store
       * @return reference to <code>dest</code>
       */
      public final Point3 getPoint(Point3 dest) {
          dest.x = ox + (tMax * dx);
          dest.y = oy + (tMax * dy);
          dest.z = oz + (tMax * dz);
          return dest;
      }
  
      /**
       * Computes the dot product of an arbitrary vector with the direction of the
       * ray. This method avoids having to call getDirection() which would
       * instantiate a new Vector object.
       * 
       * @param v vector
       * @return dot product of the ray direction and the specified vector
       */
      public final float dot(Vector3 v) {
          return dx * v.x + dy * v.y + dz * v.z;
      }
  
      /**
       * Computes the dot product of an arbitrary vector with the direction of the
       * ray. This method avoids having to call getDirection() which would
       * instantiate a new Vector object.
       * 
       * @param vx vector x coordinate
       * @param vy vector y coordinate
       * @param vz vector z coordinate
       * @return dot product of the ray direction and the specified vector
       */
      public final float dot(float vx, float vy, float vz) {
          return dx * vx + dy * vy + dz * vz;
      }
  
      /**
       * Updates the maximum to the specified distance if and only if the new
       * distance is smaller than the current one.
       * 
       * @param t new maximum distance
       */
      public final void setMax(float t) {
          tMax = t;
      }
  }