All Downloads are FREE. Search and download functionalities are using the official Maven repository.

se.llbit.math.Triangle Maven / Gradle / Ivy

There is a newer version: 1.4.5
Show newest version
/* Copyright (c) 2012 Jesper Öqvist 
 *
 * This file is part of Chunky.
 *
 * Chunky is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Chunky is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * You should have received a copy of the GNU General Public License
 * along with Chunky.  If not, see .
 */
package se.llbit.math;

/**
 * A class to test intersection against a three-dimensional,
 * non-degenerate triangle.
 *
 * @author Jesper Öqvist 
 */
public class Triangle {

  /**
   * Normal vector
   */
  public final Vector3 n;

  private final Vector3 o;
  private final Vector3 u;
  private final Vector3 v;

  private final double d;
  private final double uv;
  private final double uu;
  private final double vv;
  private final double uv2;

  /**
   * Construct a new triangle.
   */
  public Triangle(Vector3 v0, Vector3 v1, Vector3 v2) {

    o = new Vector3(v0);

    n = new Vector3();
    u = new Vector3();
    v = new Vector3();

    u.sub(v1, o);
    v.sub(v2, o);

    n.cross(u, v);
    n.normalize();

    d = -n.dot(o);

    uv = u.dot(v);
    uu = u.dot(u);
    vv = v.dot(v);
    uv2 = uv * uv;
  }

  /**
   * Find intersection between the ray and this triangle
   *
   * @return true if the ray intersects the triangle
   */
  public boolean intersect(Ray ray) {
    double ix = ray.o.x - QuickMath.floor(ray.o.x + ray.d.x * Ray.OFFSET);
    double iy = ray.o.y - QuickMath.floor(ray.o.y + ray.d.y * Ray.OFFSET);
    double iz = ray.o.z - QuickMath.floor(ray.o.z + ray.d.z * Ray.OFFSET);

    // test that the ray is heading toward the plane
    double denom = ray.d.dot(n);
    if (QuickMath.abs(denom) > Ray.EPSILON) {

      // test for intersection with the plane at origin
      double t = -(ix * n.x + iy * n.y + iz * n.z + d) / denom;
      if (t > -Ray.EPSILON && t < ray.t) {

        // plane intersection confirmed
        // translate to get hit point relative to the triangle origin
        ix = ix + ray.d.x * t - o.x;
        iy = iy + ray.d.y * t - o.y;
        iz = iz + ray.d.z * t - o.z;

        double wu = ix * u.x + iy * u.y + iz * u.z;
        double wv = ix * v.x + iy * v.y + iz * v.z;
        double si = (uv * wv - vv * wu) / (uv2 - uu * vv);
        double ti = (uv * wu - uu * wv) / (uv2 - uu * vv);
        if ((si >= 0) && (ti >= 0) && (si + ti <= 1)) {
          ray.tNext = t;
          ray.u = si;
          ray.v = ti;
          return true;
        }
      }
    }

    return false;
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy