Пример #1
0
  @Override
  public Double intersect(Ray ray) {
    Vec3D o = worldToObject.multiplyPoint(ray.origin);
    o.setY(o.getY() + ymax + (ymin - ymax) * 0.5);
    Vec3D d = worldToObject.multiplyDirection(ray.direction);
    double sin2 = radius2 / (radius2 + height * height);
    double cos2 = 1 - sin2;
    double a = d.getX() * d.getX() * cos2 + d.getZ() * d.getZ() * cos2 - d.getY() * d.getY() * sin2;
    double b =
        2 * (o.getX() * d.getX() * cos2 + o.getZ() * d.getZ() * cos2 - o.getY() * d.getY() * sin2);
    double c = o.getX() * o.getX() * cos2 + o.getZ() * o.getZ() * cos2 - o.getY() * o.getY() * sin2;
    QuadraticRoots roots = Utils.solveQuadratic(a, b, c);
    boolean isect = false;
    double t0 = 0, t1 = 0, t = Double.POSITIVE_INFINITY;
    Vec3D n = new Vec3D();
    if (roots != null) {
      if (roots.x0 > roots.x1) {
        t0 = roots.x1;
        t1 = roots.x0;
      } else {
        t0 = roots.x0;
        t1 = roots.x1;
      }
      if (t0 < 0) {
        t0 = t1;
      }
      double y = o.getY() + t0 * d.getY();
      if (y > ymax || y < ymin) {
        t0 = t1;
        y = o.getY() + t0 * d.getY();
      }
      if (y >= ymin && y <= ymax && t0 >= 0) {
        isect = true;
        t = t0;
        Vec3D p = o.add(d.multiply(t0));
        Vec3D tangent = new Vec3D(0, 1, 0).crossProduct(new Vec3D(p.getX(), 0, p.getZ()));
        Vec3D bitangent = p.multiply(-1);
        n = objectToWorld.multiplyDirection(tangent.crossProduct(bitangent)).normalize();
      }
      t0 = (ymin - o.getY()) / d.getY();
      double xx = o.getX() + t0 * d.getX();
      double zz = o.getZ() + t0 * d.getZ();
      if (xx * xx + zz * zz <= radius2 && t0 < t && t0 >= 0) {
        isect = true;
        t = t0;
        n = objectToWorld.multiplyDirection(new Vec3D(0, -1, 0));
      }
      if (radius0 != 0) {
        t0 = (ymax - o.getY()) / d.getY();
        xx = o.getX() + t0 * d.getX();
        zz = o.getZ() + t0 * d.getZ();
        if (xx * xx + zz * zz <= radius0 * radius0 && t0 < t && t0 >= 0) {
          isect = true;
          t = t0;
          n = objectToWorld.multiplyDirection(new Vec3D(0, 1, 0));
        }
      }
    }
    if (isect) {
      normal = n;
      return t;
    }

    return null;
  }