Пример #1
0
  /**
   * Tests this surface for intersection with ray. If an intersection is found record is filled out
   * with the information about the intersection and the method returns true. It returns false
   * otherwise and the information in outRecord is not modified.
   *
   * @param outRecord the output IntersectionRecord
   * @param ray the ray to intersect
   * @return true if the surface intersects the ray
   */
  public boolean intersect(IntersectionRecord outRecord, Ray rayIn) {
    // TODO(B): fill in this function.
    // Hint: This object can be transformed by a transformation matrix.
    // So the rayIn needs to be processed so that it is in the same
    // coordinate as the object.
    Ray ray = untransformRay(rayIn);

    double ax = owner.getVertex(index[0]).x;
    double ay = owner.getVertex(index[0]).y;
    double az = owner.getVertex(index[0]).z;
    double px = ray.origin.x;
    double py = ray.origin.y;
    double pz = ray.origin.z;
    double dx = ray.direction.x;
    double dy = ray.direction.y;
    double dz = ray.direction.z;

    // calculating t, gamma, and beta based on linear system presented in
    // Shirley and Marschner
    double ei_hf = e * dz - dy * f;
    double gf_di = dx * f - d * dz;
    double dh_eg = d * dy - e * dx;

    double ak_jb = a * (ay - py) - (ax - px) * b;
    double jc_al = (ax - px) * c - a * (az - pz);
    double bl_kc = b * (az - pz) - (ay - py) * c;

    double m = a * ei_hf + b * gf_di + c * dh_eg;

    double t = -(f * ak_jb + e * jc_al + d * bl_kc) / m;
    if (t < ray.start || t > ray.end) {
      return false;
    }

    double gamma = (dz * ak_jb + dy * jc_al + dx * bl_kc) / m;
    if (gamma < 0 || gamma > 1) {
      return false;
    }

    double beta = ((ax - px) * ei_hf + (ay - py) * gf_di + (az - pz) * dh_eg) / m;
    if (beta < 0 || beta > 1 - gamma) {
      return false;
    }

    if (outRecord != null) {
      outRecord.t = t;
      ray.evaluate(outRecord.location, t);
      outRecord.surface = this;

      if (norm == null) {
        // interpolate normal based on barycentric coords
        double alpha = 1.0 - gamma - beta;
        Vector3 an = owner.getNormal(index[0]);
        an.scale(alpha);
        Vector3 bn = owner.getNormal(index[1]);
        bn.scale(beta);
        Vector3 cn = owner.getNormal(index[2]);
        cn.scale(gamma);
        Vector3 n = new Vector3(an.x + bn.x + cn.x, an.y + bn.y + cn.y, an.z + bn.z + cn.z);
        outRecord.normal.set(n);
      } else {
        outRecord.normal.set(norm);
      }
      tMat.rightMultiply(outRecord.location);
      tMatTInv.rightMultiply(outRecord.normal);
      outRecord.normal.normalize();
    }
    return true;
  }