package org.helioviewer.gl3d.scenegraph;

import org.helioviewer.gl3d.scenegraph.math.GL3DVec3d;
import org.helioviewer.gl3d.scenegraph.rt.GL3DRay;

/**
 * A representation of a triangle, basically used as the most basic primitive
 * when calculating hit points of a {@link GL3DMesh}. Every Mesh is also stored
 * as a set of {@link GL3DTriangle}s.
 * 
 * @author Simon Spoerri (simon.spoerri@fhnw.ch)
 * 
 */
public class GL3DTriangle {
    protected GL3DVec3d a;
    protected GL3DVec3d b;
    protected GL3DVec3d c;

    protected GL3DVec3d center;
    private boolean planarMode = true;

    public boolean isPlanarMode() {
        return planarMode;
    }

    public void setPlanarMode(boolean planarMode) {
        this.planarMode = planarMode;
    }

    public GL3DTriangle() {

    }

    public GL3DTriangle(GL3DVec3d a, GL3DVec3d b, GL3DVec3d c) {
        this.a = a;
        this.b = b;
        this.c = c;

        this.center = this.a.copy();
        this.center.add(c);
        this.center.add(b);
        this.center.divide(3);
    }

    private final static double EPSILON = 0.0001;

    public boolean intersects(GL3DRay ray) {
        GL3DVec3d e1, e2; // edge 1 and 2
        GL3DVec3d AO, K, Q;

        // find vectors for two edges sharing the triangle vertex A
        e1 = GL3DVec3d.subtract(this.b, this.a);
        e2 = GL3DVec3d.subtract(this.c, this.a);

        // begin calculating determinant - also used to calculate U parameter
        K = GL3DVec3d.cross(ray.getDirectionOS(), e2);

        // if determinant is near zero, ray lies in plane of triangle
        final double det = e1.dot(K);

        double inv_det, t, u, v;

        if (det < EPSILON && det > -EPSILON)
            return false;

        inv_det = 1.0f / det;

        // calculate distance from A to ray origin
        AO = GL3DVec3d.subtract(ray.getOriginOS(), a);

        // Calculate barycentric coordinates: u>0 && v>0 && u+v<=1
        u = AO.dot(K) * inv_det;
        if (!planarMode) {
            if (u < 0.0f || u > 1.0)
                return false;
        }
        // prepare to test v parameter
        Q = GL3DVec3d.cross(AO, e1);

        // calculate v parameter and test bounds
        if (!planarMode) {
            v = Q.dot(ray.getDirectionOS()) * inv_det;
            if (v < 0.0f || u + v > 1.0f)
                return false;
        }

        // calculate t, ray intersects triangle
        t = e2.dot(Q) * inv_det;

        // if intersection is closer replace ray intersection parameters
        if (t > ray.getLength() || t < 0.0f)
            return false;

        ray.setLength(t);

        return true;
    }
}

@@ -548,214 +548,8 @@
 ter;
-%0A    private boolean planarMode = true;%0A%0A    public boolean isPlanarMode() %7B%0A        return planarMode;%0A    %7D%0A%0A    public void setPlanarMode(boolean planarMode) %7B%0A        this.planarMode = planarMode;%0A    %7D
 %0A%0A  
@@ -1764,39 +1764,8 @@
 et;%0A
-        if (!planarMode) %7B%0A    
     
@@ -1797,36 +1797,32 @@
 .0)%0A            
-  
-  
 return false;%0A  
@@ -1819,25 +1819,16 @@
  false;%0A
-        %7D
 %0A       
@@ -1950,39 +1950,8 @@
 nds%0A
-        if (!planarMode) %7B%0A    
     
@@ -2001,28 +2001,24 @@
 et;%0A        
-    
 if (v %3C 0.0f
@@ -2039,36 +2039,32 @@
 0f)%0A            
-  
-  
 return false;%0A  
@@ -2064,18 +2064,8 @@
 lse;
-%0A        %7D
 %0A%0A  
@@ -2258,24 +2258,24 @@
 %7C t %3C 0.0f)%0A
-
             
@@ -2312,24 +2312,942 @@
 Length(t);%0A%0A
+        return true;%0A    %7D%0A%0A    public boolean intersectsPlanar(GL3DRay ray) %7B%0A        GL3DVec3d e1, e2; // edge 1 and 2%0A        GL3DVec3d AO, K, Q;%0A%0A        // find vectors for two edges sharing the triangle vertex A%0A        e1 = GL3DVec3d.subtract(this.b, this.a);%0A        e2 = GL3DVec3d.subtract(this.c, this.a);%0A%0A        // begin calculating determinant - also used to calculate U parameter%0A        K = GL3DVec3d.cross(ray.getDirectionOS(), e2);%0A%0A        // if determinant is near zero, ray lies in plane of triangle%0A        final double det = e1.dot(K);%0A%0A        double inv_det, t, u, v;%0A%0A        inv_det = 1.0f / det;%0A%0A        // calculate distance from A to ray origin%0A        AO = GL3DVec3d.subtract(ray.getOriginOS(), a);%0A%0A        // prepare to test v parameter%0A        Q = GL3DVec3d.cross(AO, e1);%0A%0A        // calculate t, ray intersects triangle%0A        t = e2.dot(Q) * inv_det;%0A%0A        ray.setLength(t);%0A%0A
         retu

create separate planar calculation