GwieF.com : Project : Classes : Shape3D
logo

Shape3D.java


package com.gwief.jTrace;

/*
    Shape3D.java by Damian Newport
    Stores and implements behavior of a shape
*/

public class Shape3D extends CSGnode{
    
    /* constants */
    final int DEFAULT = 0;
    
    String name;
    int shape;          // 0 = sphere, 1 = cube, 2 = cylinder, 3 = cone, 4 = hyperboloid, 5 = plane
    Transform3D transform;
    Material material;
    
    Transform3D ntransform;

    public Shape3D(String Name){
        name = Name;
        shape = DEFAULT;
        transform = new Transform3D();
        material = new Material();
    }
    
    public Shape3D(String Name, int type){
        name = Name;
        shape = type;
        transform = new Transform3D();
        material = new Material();
    }
    
    final public void setshape(int a){shape = a;}
    final public void settransform(Transform3D a){transform = a;}
    final public void setmaterial(Material a){material = a; }
    
    final public int getshape(){return shape;}
    final public Transform3D gettransform(){return transform; }
    final public Material getmaterial(){return material; }
    
    public final void build(Transform3D ntrans){
        ntransform = new Transform3D(ntrans);
        ntransform.multiply(transform);
    }
    
    final Intersection[] getBranch(Ray ray){
        Ray temp = ntransform.Transform(ray);
        double[] result;
        temp.direction.unit();
        
        if (rayTrace.bugmode){
            System.out.println("---------"+name+"---------------");
            System.out.println(ntransform.out());
            System.out.println(name + ".ray.org=" + ray.origin.out());
            System.out.println(name + ".ray.dir=" + ray.direction.out());
            System.out.println(name + ".temp.org=" + temp.origin.out());
            System.out.println(name + ".temp.dir=" + temp.direction.out());
        }
        
        switch(shape){
            case 0 :    // sphere
                    result = Sphere.intersect(temp);
                break;
            case 1 :    // cube
                    result = Box.intersect(temp);
                break;
            case 2 :    // cylinder
                    result = Cylinder.intersect(temp);
                break;
            case 3 :    // cone
                    result = Cone.intersect(temp);
                break;
            case 4 :    // hyperboloid
                    result = Hyperboloid.intersect(temp);
            case 5 :    // plane
                    result = Plane.intersect(temp);
                break;
            default :
                    result = new double[0];
        }
        int length = result.length;
        if (length > 0){
            
            int type = 1;
            Intersection[] inters = new Intersection[length];

            for (int i = 0; i < length; i++){
                
                Vector3D work = new Vector3D(temp.direction);
                work.multiply(result[i]);
                work.add(temp.origin);
                work = ntransform.iTransform(work);
                work.minus(ray.origin);
                if (result[i] < 0){ // to keep original sign
                    result[i] = -1;
                }else{
                    result[i] = 1;
                }
                result[i] *= work.modulus();
                inters[i] = new Intersection(type, result[i], this);
                type *= -1;
                
                if (rayTrace.bugmode){
                    System.out.println(name + ".result["+i+"]="+result[i]);
                }
            }
            return inters;
        }else{
           return new Intersection[0];
        }
    }
    
    public final Vector3D getNormal(Vector3D a){
        switch(shape){
            case 0 :    // sphere
                    return sphereNormal(a);
            case 1 :    // box
                    return boxNormal(a);
            case 2 :    // cylinder
                    return cylinderNormal(a);
            case 3 :    // cone
                    return coneNormal(a);
            case 4 :    // hyperboloid
                    return hyperboloidNormal(a);
            case 5 :    // hyperboloid
                    return planeNormal(a);
            default :
                    System.out.println("Error! Unknown shape '" + shape + "'");
                    System.exit(1);
                    return a;
        }
    }
    
    private final Vector3D sphereNormal(Vector3D a){
        Vector3D temp = ntransform.Transform(a);
        temp = Sphere.normal(temp);
        temp = ntransform.piTransform(temp);
        temp.unit();
        return temp;
    }
    
    private final Vector3D boxNormal(Vector3D a){
        Vector3D temp = ntransform.Transform(a);
        temp = Box.normal(temp);
        temp = ntransform.piTransform(temp);
        temp.unit();
        return temp;
    }
    
    private final Vector3D cylinderNormal(Vector3D a){
        Vector3D temp = ntransform.Transform(a);
        temp = Cylinder.normal(temp);
        temp = ntransform.piTransform(temp);
        temp.unit();
        return temp;
    }
    
    private final Vector3D coneNormal(Vector3D a){
        Vector3D temp = ntransform.Transform(a);
        temp = Cone.normal(temp);
        temp = ntransform.piTransform(temp);
        temp.unit();
        return temp;
    }
    
    private final Vector3D hyperboloidNormal(Vector3D a){
        Vector3D temp = ntransform.Transform(a);
        temp = Hyperboloid.normal(temp);
        temp = ntransform.piTransform(temp);
        temp.unit();
        return temp;
    }
    
    private final Vector3D planeNormal(Vector3D a){
        Vector3D temp = ntransform.Transform(a);
        temp = Plane.normal(temp);
        temp = ntransform.piTransform(temp);
        temp.unit();
        return temp;
    }
}