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;
}
}