Package org.mt4j.components.visibleComponents.shapes.mesh

Source Code of org.mt4j.components.visibleComponents.shapes.mesh.Triangle

/***********************************************************************
* mt4j Copyright (c) 2008 - 2009, C.Ruff, Fraunhofer-Gesellschaft All rights reserved.
*   This program 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.
*
*   This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
*
***********************************************************************/
package org.mt4j.components.visibleComponents.shapes.mesh;

import org.mt4j.util.math.ToolsMath;
import org.mt4j.util.math.Ray;
import org.mt4j.util.math.ToolsGeometry;
import org.mt4j.util.math.Vector3D;
import org.mt4j.util.math.Vertex;

/**
* A triangle class used in meshes.
*
* @author Christopher Ruff
*/
public class Triangle {
 
  /** The v0. */
  public Vertex v0;
 
  /** The v1. */
  public Vertex v1;
 
  /** The v2. */
  public Vertex v2;
 
  //Pointers into the vertex array
  /** The P0. */
  public int P0;
 
  /** The P1. */
  public int P1;
 
  /** The P2. */
  public int P2;
 
  /** The normal. */
  private Vector3D normal;
 
  /** The normal unnormalized. */
  private Vector3D normalUnnormalized;
 
  /** The center. */
  private Vector3D center;
 
  /** The normal dirty. */
  private boolean normalDirty;
 
  /** The center dirty. */
  private boolean centerDirty;

 
//  private boolean useLocalObjectSpace;
 
 
  /**
* The Constructor.
*
* @param v0 the v0
* @param v1 the v1
* @param v2 the v2
* @param p0 the index p0
* @param p1 the index p1
* @param p2 the index p2
*/
  public Triangle(Vertex v0, Vertex v1, Vertex v2, int p0, int p1, int p2) {
    this.v0 = v0;
    this.v1 = v1;
    this.v2 = v2;
   
    this.P0 = p0;
    this.P1 = p1;
    this.P2 = p2;
   
    this.normalDirty = true;
//    this.normal     = this.getNormalLocal();
    this.normal     = null; //lazily initialize them to save memory
   
    this.centerDirty = true;
//    this.center    = this.getCenterPointLocal();
    this.center    = null;
   
//    this.useLocalObjectSpace = true;
  }
 
  /**
   * Sets the.
   *
   * @param v0 the v0
   * @param v1 the v1
   * @param v2 the v2
   */
  public void set(Vertex v0, Vertex v1, Vertex v2){
    this.v0 = v0;
    this.v1 = v1;
    this.v2 = v2;
    this.normalDirty = true;
    this.centerDirty = true;
  }
 
  /**
   * Gets the normal obj space.
   *
   * @return the normal obj space
   *
   * the normal vector of the plane of the triangle
   */
  public Vector3D getNormalLocal(){
    this.calcNormal();
    return this.normal;
  }
 
  /**
   * Calc normal.
   */
  private void calcNormal(){
    if (normalDirty || this.normal == null || this.normalUnnormalized == null){
      this.normal = ToolsGeometry.getNormal(v0, v1, v2, false);
     
      //Get unnormalized normal for triangle intersection tests (So degenerate tris get detected)
      this.normalUnnormalized = normal.getCopy();
     
      this.normal.normalizeLocal();
      normalDirty = false;
    }
  }

  /**
   * Gets the center point local.
   *
   * @return the center point local
   */
  public Vector3D getCenterPointLocal(){
    this.calcCenterLocal();
    return this.center;
  }

  /**
   * Calc center local.
   */
  private void calcCenterLocal(){
    if (centerDirty || center == null){
      center = this.v0.getCopy();
      center.addLocal(v1);
      center.addLocal(v2);
      center.scaleLocal(ToolsMath.ONE_THIRD);
      centerDirty = false;
    }
  }


  /**
   * Tests if the given ray intersects this triangle.
   * Returns the intersection point or null if there is none.
   *
   * @param r the r
   *
   * @return the ray triangle intersection
   *
   * intersection vector
   */
  public Vector3D getRayTriangleIntersection(Ray r){
    //Update unnormalized normal if neccessary
    this.calcNormal();
    return ToolsGeometry.getRayTriangleIntersection(r, v0, v1, v2, this.normalUnnormalized);
  }
 
 
  /**
   * Checks if point vector is inside the triangle created by the points a, b
   * and c. These points will create a plane and the point checked will have
   * to be on this plane in the region between a,b,c.
   *
   * Note: The triangle must be defined in clockwise order a,b,c
   *
   * @param p the p
   *
   * @return true, if point is in triangle.
   */
  public boolean containsPoint(Vector3D p) {
    Vector3D a = p.getSubtracted(v0);
    a.normalizeLocal();
    Vector3D b = p.getSubtracted(v1);
    b.normalizeLocal();
    Vector3D c = p.getSubtracted(v2);
    c.normalizeLocal();

    double total_angles = Math.acos(a.dot(b));
    total_angles += Math.acos(b.dot(c));
    total_angles += Math.acos(c.dot(a));

    return (ToolsMath.abs((float) total_angles - ToolsMath.TWO_PI) <= 0.005f);
  }


  /**
   * Finds and returns the closest point on any of the triangle edges to the
   * point given.
   *
   * @param p point to check
   *
   * @return closest point
   */
  public Vector3D getClosestVertexTo(Vector3D p) {
    Vector3D Rab = getClosestVecToVecOnSegment(p, v0, v1);
    Vector3D Rbc = getClosestVecToVecOnSegment(p, v1, v2);
    Vector3D Rca = getClosestVecToVecOnSegment(p, v2, v0);

    float dAB = p.getSubtracted(Rab).lengthSquared();
    float dBC = p.getSubtracted(Rbc).lengthSquared();
    float dCA = p.getSubtracted(Rca).lengthSquared();

    float min = dAB;
    Vector3D result = Rab;

    if (dBC < min) {
      min = dBC;
      result = Rbc;
    }

    if (dCA < min){
      result = Rca;
    }
    return result;
  }


  /**
   * Computes the the point on the surface of
   * triangle closest to the given vector.
   *
   * From Real-Time Collision Detection by Christer Ericson, published by
   * Morgan Kaufmann Publishers, Copyright 2005 Elsevier Inc
   *
   * @param p the p
   *
   * @return closest point on triangle (result may also be one of v0, v1 or v2)
   */
  public Vector3D getClosestPointOnSurface(Vector3D p) {
    Vector3D ab = v1.getSubtracted(v0);
    Vector3D ac = v2.getSubtracted(v0);
    Vector3D bc = v2.getSubtracted(v1);

    Vector3D pa = p.getSubtracted(v0);
    Vector3D pb = p.getSubtracted(v1);
    Vector3D pc = p.getSubtracted(v2);

    Vector3D ap = v0.getSubtracted(p);
    Vector3D bp = v1.getSubtracted(p);
    Vector3D cp = v2.getSubtracted(p);

    // Compute parametric position s for projection P' of P on AB,
    // P' = A + s*AB, s = snom/(snom+sdenom)
    float snom = pa.dot(ab);
    float sdenom = pb.dot(v0.getSubtracted(v1));

    // Compute parametric position t for projection P' of P on AC,
    // P' = A + t*AC, s = tnom/(tnom+tdenom)
    float tnom = pa.dot(ac);
    float tdenom = pc.dot(v0.getSubtracted(v2));

    if (snom <= 0.0f && tnom <= 0.0f)
      return v0; // Vertex region early out

    // Compute parametric position u for projection P' of P on BC,
    // P' = B + u*BC, u = unom/(unom+udenom)
    float unom = pb.dot(bc);
    float udenom = pc.dot(v1.getSubtracted(v2));

    if (sdenom <= 0.0f && unom <= 0.0f)
      return v1; // Vertex region early out
    if (tdenom <= 0.0f && udenom <= 0.0f)
      return v2; // Vertex region early out

    // P is outside (or on) AB if the triple scalar product [N PA PB] <= 0
    Vector3D n = ab.getCross(ac);
    float vc = n.dot(ap.crossLocal(bp));

    // If P outside AB and within feature region of AB,
    // return projection of P onto AB
    if (vc <= 0.0f && snom >= 0.0f && sdenom >= 0.0f) {
      // return a + snom / (snom + sdenom) * ab;
      return v0.getAdded(ab.scaleLocal(snom / (snom + sdenom)));
    }

    // P is outside (or on) BC if the triple scalar product [N PB PC] <= 0
    float va = n.dot(bp.crossLocal(cp));
    // If P outside BC and within feature region of BC,
    // return projection of P onto BC
    if (va <= 0.0f && unom >= 0.0f && udenom >= 0.0f) {
      // return b + unom / (unom + udenom) * bc;
      return v1.getAdded(bc.scaleLocal(unom / (unom + udenom)));
    }

    // P is outside (or on) CA if the triple scalar product [N PC PA] <= 0
    float vb = n.dot(cp.crossLocal(ap));
    // If P outside CA and within feature region of CA,
    // return projection of P onto CA
    if (vb <= 0.0f && tnom >= 0.0f && tdenom >= 0.0f) {
      // return a + tnom / (tnom + tdenom) * ac;
      return v0.getAdded(ac.scaleLocal(tnom / (tnom + tdenom)));
    }

    // P must project inside face region. Compute Q using barycentric
    // coordinates
    float u = va / (va + vb + vc);
    float v = vb / (va + vb + vc);
    float w = 1.0f - u - v; // = vc / (va + vb + vc)
    // return u * a + v * b + w * c;
    return v0.getScaled(u).addLocal(v1.getScaled(v)).addLocal(v2.getScaled(w));
  }



    /**
     * Checks if is clockwise in xy.
     *
     * @return true, if is clockwise in xy
     */
    public boolean isClockwiseInXY() {
      return Triangle.isClockwiseInXY(v0, v1, v2);
    }

    /**
     * Checks if is clockwise in xz.
     *
     * @return true, if is clockwise in xz
     */
    public boolean isClockwiseInXZ() {
      return Triangle.isClockwiseInXY(v0, v1, v2);
    }

    /**
     * Checks if is clockwise in yz.
     *
     * @return true, if is clockwise in yz
     */
    public boolean isClockwiseInYZ() {
      return Triangle.isClockwiseInXY(v0, v1, v2);
    }

    /**
     * Checks if is clockwise in xy.
     *
     * @param v0 the v0
     * @param v1 the v1
     * @param v2 the v2
     *
     * @return true, if is clockwise in xy
     */
    public static boolean isClockwiseInXY(Vector3D v0, Vector3D v1, Vector3D v2) {
      float determ = (v1.x - v0.x) * (v2.y - v0.y) - (v2.x - v0.x) * (v1.y - v0.y);
      return (determ < 0.0);
    }

    /**
     * Checks if is clockwise in xz.
     *
     * @param v0 the v0
     * @param v1 the v1
     * @param v2 the v2
     *
     * @return true, if is clockwise in xz
     */
    public static boolean isClockwiseInXZ(Vector3D v0, Vector3D v1, Vector3D v2) {
      float determ = (v1.x - v0.x) * (v2.z - v0.z) - (v2.x - v0.x) * (v1.z - v0.z);
      return (determ < 0.0);
    }


    /**
     * Checks if is clockwise in yz.
     *
     * @param v0 the v0
     * @param v1 the v1
     * @param v2 the v2
     *
     * @return true, if is clockwise in yz
     */
    public static boolean isClockwiseInYZ(Vector3D v0, Vector3D v1, Vector3D v2) {
      float determ = (v1.y - v0.y) * (v2.z - v0.z) - (v2.y - v0.y) * (v1.z - v0.z);
      return (determ < 0.0);
    }

   
    /**
   * Gets the closest vec to vec on segment.
   *
   * @param p the point to find the closest point on the segment for
   * @param segmentStart start point of line segment
   * @param segmentEnd end point of line segment
   *
   * @return closest point on the line segment a -> b
   */
  private Vector3D getClosestVecToVecOnSegment(Vector3D p, Vector3D segmentStart, Vector3D segmentEnd) {
          Vector3D c = p.getSubtracted(segmentStart);
          Vector3D v = segmentEnd.getSubtracted(segmentStart);
 
          float d = v.length();
          v.normalizeLocal();
 
          float t = v.dot(c);
 
          // Check to see if t is beyond the extents of the line segment
          if (t < 0.0f) {
                  return segmentStart;
          }
          if (t > d) {
                  return segmentEnd;
          }
 
          // Return the point between 'a' and 'b'
          // set length of V to t. V is normalized so this is easy
          v.scaleLocal(t);
          return segmentStart.getAdded(v);
  }
 

    /* code rewritten to do tests on the sign of the determinant */
  /* the division is before the test of the sign of the det    */
//  int intersect_triangle2(
//      double orig[3],
//      double dir[3],
//      double vert0[3],
//      double vert1[3],
//      double vert2[3],
//      double *t,
//      double *u,
//      double *v
//  ){
//     double edge1[3], edge2[3], tvec[3], pvec[3], qvec[3];
//     double det,inv_det;
//
//     /* find vectors for two edges sharing vert0 */
//     SUB(edge1, vert1, vert0);
//     SUB(edge2, vert2, vert0);
//
//     /* begin calculating determinant - also used to calculate U parameter */
//     CROSS(pvec, dir, edge2);
//
//     /* if determinant is near zero, ray lies in plane of triangle */
//     det = DOT(edge1, pvec);
//
//     /* calculate distance from vert0 to ray origin */
//     SUB(tvec, orig, vert0);
//     inv_det = 1.0 / det;
//    
//     if (det > EPSILON)
//     {
//        /* calculate U parameter and test bounds */
//        *u = DOT(tvec, pvec);
//        if (*u < 0.0 || *u > det)
//     return 0;
//       
//        /* prepare to test V parameter */
//        CROSS(qvec, tvec, edge1);
//       
//        /* calculate V parameter and test bounds */
//        *v = DOT(dir, qvec);
//        if (*v < 0.0 || *u + *v > det)
//     return 0;
//       
//     }
//     else if(det < -EPSILON)
//     {
//        /* calculate U parameter and test bounds */
//        *u = DOT(tvec, pvec);
//        if (*u > 0.0 || *u < det)
//     return 0;
//       
//        /* prepare to test V parameter */
//        CROSS(qvec, tvec, edge1);
//       
//        /* calculate V parameter and test bounds */
//        *v = DOT(dir, qvec) ;
//        if (*v > 0.0 || *u + *v < det)
//     return 0;
//     }
//     else return 0;  /* ray is parallell to the plane of the triangle */
//
//     /* calculate t, ray intersects triangle */
//     *t = DOT(edge2, qvec) * inv_det;
//     (*u) *= inv_det;
//     (*v) *= inv_det;
//
//     return 1;
//  }


 
 
 

}
TOP

Related Classes of org.mt4j.components.visibleComponents.shapes.mesh.Triangle

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.