GwieF.com : Project : Classes : Quadric
logo

Quadric.java


package com.gwief.jTrace;

/*
    Quadric.java by Damian Newport
    Given a Ray and some co-efficients can find intersection and normal of any
    quadratic of equation:
    AX^2 + BY^2 + CZ^2 + J = 0
    This is used by Cylinder, Cone, and Hyperboloid
*/

public class Quadric {

     /*
    General quadric surface equation:
    F(x, y, z) = Ax^2 + By^2 + Cz^2 + 2Dxy+ 2Exz + 2Fyz + Gx + Hy + Iz + J = 0
    
    ignore all but a,b,c,j for efficiency and cause were not doing a paraboloid
    and thus don't need them
    */
    
    /* takes a Ray, returns a array of length 0 if miss,
    length 2 filled with intersections if we hit */
    public static final double[] intersect(Ray i, double A, double B, double C, double J){
        double xo = i.origin.x;
        double yo = i.origin.y;
        double zo = i.origin.z;
        
        double xd = i.direction.x;
        double yd = i.direction.y;
        double zd = i.direction.z;
        
        double[] result = new double[0];
        
        /* work out coefficients */
        
        double a = A*xd*xd + B*yd*yd + C*zd*zd;
        
        double b = 2 * (A*xo*xd + B*yo*yd + C*zo*zd);
        
        double c = A*xo*xo + B*yo*yo + C*zo*zo + J;
        
        /*  if its a plane */
        if (a < rayTrace.TINY){ 
            result = new double[2];
            double temp = -c / b;
            result[0] = temp;
            result[1] = temp;
        }
        
        double check = b*b - 4*a*c;
        
        /* if we don't hit anything */
        if (check < 0){
            return result;
        }
        
        check = Math.sqrt(check);

        double temp1,temp2;
        
        temp2 = 2*a;
        temp1 = (-b - check)/temp2;
        temp2 = (-b + check)/temp2;

        result = new double[2];
        
        if (temp1 < temp2){
            result[0] = temp1;
            result[1] = temp2;
        }else{
            result[0] = temp2;
            result[1] = temp1;
        }

        if (result[1] < 0){
            return new double[0];
        }
        
        return result;
    }
    
    /* takes a intersection point as a Vector3D, and the co-efficiecients
    returns the normal as a vector3D */
    public static final Vector3D normal(Vector3D i, double A, double B, double C, double J){
        Vector3D n = new Vector3D();
        n.x = 2 * A*i.x;
        n.y = 2 * B*i.y;
        n.z = 2 * C*i.z;
        return n;
    }
}