Ray.java
package com.gwief.jTrace;
/*
Ray.java by Damian Newport
Stores a Ray, and implements behavior to trace it
*/
public class Ray {
Vector3D origin;
Vector3D direction;
public Ray(){
origin = new Vector3D(0,0,0);
direction = new Vector3D(0,0,0);
}
public Ray(Vector3D start, Vector3D dir){
origin = new Vector3D(start);
direction = new Vector3D(dir);
}
public Ray(Ray a){
origin = new Vector3D(a.origin);
direction = new Vector3D(a.direction);
}
public final Color3D trace(Scene3D scene,int deadray){
Color3D color = new Color3D();
Shape3D temp;
deadray--;
if (deadray < 1){
return scene.background;
}
/* get intersection */
Intersection point = traceRay(scene);
if (point == null){
return scene.background;
}
Shape3D hit = point.hit;
/* find intersection point and normal */
Vector3D intersect = new Vector3D(direction);
intersect.multiply(point.value);
intersect.add(origin);
Vector3D normal = hit.getNormal(intersect);
normal.unit();
if (point.stype == -1){
normal.negate();
}
/* Get unit vector to viewer */
Vector3D V = new Vector3D(origin);
V.minus(intersect);
V.unit();
/* find reflected ray - for use in reflection and specular lighting */
double Rangle = 2 * normal.dot(V);
Vector3D R = new Vector3D(normal);
R.multiply(Rangle);
R.minus(V);
R.unit();
/* Handles Transarency */
if (hit.material.transparency > rayTrace.TINY){
Ray tran = new Ray(intersect, direction);
Color3D transparent = tran.trace(scene, deadray);
transparent.multiply(hit.material.transparency);
color.add(transparent);
}
/* Handles reflection */
if (hit.material.reflect > rayTrace.TINY){
Ray ref = new Ray(intersect, R);
Color3D reflect = ref.trace(scene, deadray);
reflect.multiply(hit.material.reflect);
color.add(reflect);
}
/* Lighting */
int lcount = scene.getNumLights();
Light light;
Vector3D L;
Ray lightRay;
double modulus;
Intersection Check;
/* for each light */
for(int i = 0; i < lcount; i++){
/* get current light */
light = scene.getlight(i);
/* work out ray from intersect to curent light */
L = new Vector3D(light.position);
L.minus(intersect);
modulus = L.modulus();
L.divide(modulus);
if (normal.dot(L) > 0){
lightRay = new Ray(intersect, L);
/* check ray to light against all shapes */
Check = lightRay.traceRay(scene);
if (Check != null){ /* do you hit a shape? */
if (Check.value < modulus){ /* if you hit the shape before the light */
continue; /* skip current light */
}
}
/* If we got here we do this light */
double val;
/* Get intensity of light */
/* using 1/n rather than 1/(n^2) for efficiency */
double Ip = light.intensity / modulus;
/* Specular Lighting*/
/* Ip = source intensity */
/* Ks = specular coefficient */
/* Is = Ip * Ks * (V.R)^n */
double specular = hit.material.Ks * Ip * Math.pow(L.dot(R),hit.material.n);
Color3D Is = new Color3D(light.color);
Is.multiply(specular);
color.add(Is);
/* diffuse */
/* Id = (Ip - Is) * Kd * cos(b) */
/* Id = (Ip - Is) * Kd * (N . L) */
val = normal.dot(L);
if ((val > 0) && (val <= 1)){
double diffuse = (Ip - specular) * hit.material.Kd * val;
Color3D Id = new Color3D(hit.material.color);
Id.multiply(diffuse);
color.add(Id);
}
}
}
/* Ambient Lighting */
/* Ia = Ka * La */
/* Ka = ambient constant */
/* La = incident light */
Color3D Ia = new Color3D(scene.Ia);
Ia.multiply(hit.material.color);
color.add(Ia);
return color;
}
/* returns intersection of ray (null if none) */
public final Intersection traceRay(Scene3D scene){
Intersection[] answer = scene.trace(this);
int count = answer.length;
if(count != 0){
if (rayTrace.bugmode){
System.out.println("----------TRACERAY---------");
for(int i=0; i< count; i++){
System.out.println("answer[" + i + "].value = " + answer[i].value);
System.out.println("answer[" + i + "].type = " + answer[i].type);
System.out.println("answer[" + i + "].stype = " + answer[i].stype);
System.out.println("answer[" + i + "].name = " + answer[i].hit.name);
}
}
for(int i=0; i < count; i++){
if (answer[i].value > rayTrace.TINY){
if (answer[i].type == 1){
return answer[i];
}
}
}
/* if we get here all intersections are < 0 */
return null;
}else{
return null;
}
}
public final Color3D debug(Scene3D scene,int deadray){
System.out.println("---------START DEBUG---------");
Color3D color = new Color3D();
Shape3D temp;
deadray--;
if (deadray < 1){
return scene.background;
}
/* get intersection */
Intersection point = traceRay(scene);
if (point == null){
return scene.background;
}
Shape3D hit = point.hit;
/* find intersection point and normal */
Vector3D intersect = new Vector3D(direction);
intersect.multiply(point.value);
intersect.add(origin);
Vector3D normal = hit.getNormal(intersect);
normal.unit();
if (point.stype == -1){
normal.negate();
}
System.out.println("intersect=" + intersect.out());
System.out.println("normal=" + normal.out());
/* Get unit vector to viewer */
Vector3D V = new Vector3D(origin);
V.minus(intersect);
V.unit();
System.out.println("V=" + V.out());
/* find reflected ray - for use in reflection and specular lighting */
double Rangle = 2 * normal.dot(V);
Vector3D R = new Vector3D(normal);
R.multiply(Rangle);
R.minus(V);
R.unit();
System.out.println("R=" + R.out());
/* Handles Transarency */
if (hit.material.transparency > rayTrace.TINY){
Ray tran = new Ray(intersect, direction);
Color3D transparent = tran.trace(scene, deadray);
transparent.multiply(hit.material.transparency);
color.add(transparent);
}
/* Handles reflection */
if (hit.material.reflect > rayTrace.TINY){
Ray ref = new Ray(intersect, R);
Color3D reflect = ref.trace(scene, deadray);
reflect.multiply(hit.material.reflect);
color.add(reflect);
}
System.out.println("---------LIGHTING-------");
/* Lighting */
int lcount = scene.getNumLights();
Light light;
Vector3D L;
Ray lightRay;
double modulus;
Intersection Check;
/* for each light */
for(int i = 0; i < lcount; i++){
System.out.println("--------Light[" + i + "]---------");
/* get current light */
light = scene.getlight(i);
/* work out ray from intersect to curent light */
L = new Vector3D(light.position);
L.minus(intersect);
modulus = L.modulus();
L.divide(modulus);
System.out.println("L=" + L.out());
System.out.println("angle=" + normal.dot(L));
if (normal.dot(L) > 0){
lightRay = new Ray(intersect, L);
/* check ray to light against all shapes */
Check = lightRay.traceRay(scene);
if (Check != null){ /* do you hit a shape? */
if (Check.value < modulus){ /* if you hit the shape before the light */
continue; /* skip current light */
}
}
/* If we got here we do this light */
double val;
/* Get intensity of light */
/* using 1/n rather than 1/(n^2) for efficiency */
double Ip = light.intensity / modulus;
/* Specular Lighting*/
/* Ip = source intensity */
/* Ks = specular coefficient */
/* Is = Ip * Ks * (V.R)^n */
double specular = hit.material.Ks * Ip * Math.pow(L.dot(R),hit.material.n);
Color3D Is = new Color3D(light.color);
Is.multiply(specular);
color.add(Is);
/* diffuse */
/* Id = (Ip - Is) * Kd * cos(b) */
/* Id = (Ip - Is) * Kd * (N . L) */
val = normal.dot(L);
if ((val > 0) && (val <= 1)){
double diffuse = (Ip - specular) * hit.material.Kd * val;
Color3D Id = new Color3D(hit.material.color);
Id.multiply(diffuse);
color.add(Id);
}
}
}
/* Ambient Lighting */
/* Ia = Ka * La */
/* Ka = ambient constant */
/* La = incident light */
Color3D Ia = new Color3D(scene.Ia);
Ia.multiply(hit.material.color);
color.add(Ia);
return color;
}
}