GwieF.com : project.GrieF.com : Classes : Camera
logo

Camera.java


package com.gwief.jTrace;

/*  Camera.java by Damian Newport
    Implements a 'Camera' in 3D space.
    given the x,y co-ordinates of a pixel on the screen, will return the correct
    Ray to trace for that pixel.
*/  

public class Camera {
    
    private Vector3D zeroVector; //the vector to the top left of the screen
    private Vector3D xvec;       //the vector to move one pixel in the x direction
    private Vector3D yvec;       // the vector to move one pixel in the y direction
    
    Vector3D viewpoint;          // thevector from the origin to the viewpoint

    /** Creates new Camera */
    public Camera(Vector3D Viewpnt, Vector3D zero, Vector3D x, Vector3D y) {
        viewpoint = Viewpnt;
        zeroVector = zero;
        xvec = x;
        yvec = y;
    }

    public Camera(Vector3D viewpnt, Vector3D viewdir, Vector3D viewplane, double pixwidth, double pixheight, double fov) {
        viewpnt.x = -viewpnt.x;
        viewpnt.y = -viewpnt.y;
        Vector3D tempA, tempB;
        double temp;
        
        viewpoint = new Vector3D(viewpnt);
        fov = Math.tan(Math.toRadians(fov)/2);      
        temp = fov * viewdir.modulus();             // get width of 1/2 screen
        tempA = new Vector3D(viewplane);
        tempA.unit();
        tempA.multiply(temp/(pixwidth/2));              // get width of 1 pixel

        xvec = new Vector3D(tempA);
        xvec.x = -xvec.x;
        xvec.y = -xvec.y;
        
        tempB = new Vector3D(tempA);
        tempB.cross(viewdir);                       // get vertical direction
        tempB.unit();
        tempB.multiply(temp/(pixwidth/2));              // get height of 1 pixel
        
        yvec = new Vector3D(tempB);
        yvec.x = -yvec.x;
        yvec.y = -yvec.y;
        
        zeroVector = new Vector3D(viewpoint);       // work out top left corner
        zeroVector.add(viewdir);
        tempA.multiply((-1) * pixwidth/2);
        zeroVector.add(tempA);
        tempB.multiply((-1) * pixheight/2);
        zeroVector.add(tempB);
        zeroVector.x = - zeroVector.x;
        zeroVector.y = - zeroVector.y;
        
    }
    
    public Camera(Vector3D viewpnt, double rotatex, double rotatey, double rotatez, double pixwidth, double pixheight, double fov){
        viewpoint = new Vector3D(viewpnt);
        Transform3D camtransform = new Transform3D();
        camtransform.addRotate(rotatex, rotatey, rotatez);
        Vector3D viewdir = new Vector3D(0,0,10);
        viewdir = camtransform.Transform(viewdir); // get vector in viewing direction
        
        fov = Math.tan(Math.toRadians(fov)/2) * 10;      // get width of 1/2 screen
        
        Vector3D temp = new Vector3D(-fov, 0, 0);
        
        temp = camtransform.Transform(temp);
        
        zeroVector = new Vector3D(viewpnt);
        zeroVector.add(viewdir);
        zeroVector.add(temp);       // get left most point
        
        temp = new Vector3D(0,(fov*(pixheight/pixwidth)),0);
        temp = camtransform.Transform(temp);
        
        zeroVector.add(temp);   // get top left most point

        xvec = new Vector3D((fov/(pixwidth/2)), 0, 0);
        xvec = camtransform.Transform(xvec);

        yvec = new Vector3D(0, -(fov/(pixwidth/2)), 0);
        yvec = camtransform.Transform(yvec);

    }
    
    public final Ray getRay(int x, int y){
        Vector3D tempA, tempB;
        
        tempB = new Vector3D(zeroVector);
        tempA = new Vector3D(xvec);
        tempA.multiply(x);
        tempB.add(tempA);
        tempA = new Vector3D(yvec);
        tempA.multiply(y);
        tempB.add(tempA);
        tempA = new Vector3D(viewpoint);
        tempB.minus(tempA);
        tempB.unit();
        Ray tempRay = new Ray(viewpoint, tempB);
        return tempRay;
    }
}