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

se.llbit.math.primitive.TexturedTriangle Maven / Gradle / Ivy

There is a newer version: 1.4.5
Show newest version
/* Copyright (c) 2014 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.primitive;

import se.llbit.chunky.world.Material;
import se.llbit.math.AABB;
import se.llbit.math.Ray;
import se.llbit.math.Vector2;
import se.llbit.math.Vector3;

/**
 * A simple triangle primitive.
 *
 * @author Jesper Öqvist 
 */
public class TexturedTriangle implements Primitive {

  private static final double EPSILON = 0.000001;
  private final Vector3 e1 = new Vector3(0, 0, 0);
  private final Vector3 e2 = new Vector3(0, 0, 0);
  private final Vector3 o = new Vector3(0, 0, 0);
  private final Vector3 n = new Vector3(0, 0, 0);
  private final AABB bounds;
  private final Vector2 t1;
  private final Vector2 t2;
  private final Vector2 t3;
  private final Material material;

  /**
   * @param c1 first corner
   * @param c2 second corner
   * @param c3 third corner
   */
  public TexturedTriangle(Vector3 c1, Vector3 c2, Vector3 c3, Vector2 t1, Vector2 t2,
      Vector2 t3, Material material) {
    e1.sub(c2, c1);
    e2.sub(c3, c1);
    o.set(c1);
    n.cross(e2, e1);
    n.normalize();
    this.t1 = new Vector2(t2);
    this.t2 = new Vector2(t3);
    this.t3 = new Vector2(t1);
    this.material = material;

    bounds = AABB.bounds(c1, c2, c3);
  }

  @Override public boolean intersect(Ray ray) {
    // Möller-Trumbore triangle intersection algorithm!
    Vector3 pvec = new Vector3();
    Vector3 qvec = new Vector3();
    Vector3 tvec = new Vector3();

    pvec.cross(ray.d, e2);
    double det = e1.dot(pvec);
    if (det > -EPSILON && det < EPSILON) {
      return false;
    }
    double recip = 1 / det;

    tvec.sub(ray.o, o);

    double u = tvec.dot(pvec) * recip;

    if (u < 0 || u > 1) {
      return false;
    }

    qvec.cross(tvec, e1);

    double v = ray.d.dot(qvec) * recip;

    if (v < 0 || (u + v) > 1) {
      return false;
    }

    double t = e2.dot(qvec) * recip;

    if (t > EPSILON && t < ray.t) {
      double w = 1 - u - v;
      ray.u = t1.x * u + t2.x * v + t3.x * w;
      ray.v = t1.y * u + t2.y * v + t3.y * w;
      material.getColor(ray);
      ray.setCurrentMaterial(material, 0);
      ray.t = t;
      ray.n.set(n);
      return true;
    }
    return false;
  }

  @Override public AABB bounds() {
    return bounds;
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy