Hi,
I'm trying to learn how a Raytracer works and so I figured I should find an example of how its done but found none in java. Because of that I followed a tutorial originally for Visual C++ 6.0 posted here:
[FlipCode - Raytracing|http://www.flipcode.com/archives/Raytracing_Topics_Techniques-Part_1_Introduction.shtml] and started to port it to Java.
But somehow I can't get it to shade my Spheres correctly and my whole scene is flipped to the left.
I've been trying to debug this for a while now and I need help, I can't understand what's wrong.
Please help me to find out what the problem is.
Here's some code, if you want my subclasses (Sphere, Vector3f etc.) just tell me.
I'll gladly give you the source.
import javax.swing.*;
import java.awt.*;
import java.awt.image.*;
import java.util.ArrayList;
import java.util.Date;
public class Raytracer
{
JPanel tracePanel;
int width = 640;
int height = 480;
Vector3f origin = new Vector3f(0,0,-5f);
Vector3f dir = new Vector3f(0,0,0);
BufferedImage traceImage = new BufferedImage(width,height,BufferedImage.TYPE_INT_ARGB);
ArrayList<Primitive> primitives = new ArrayList<Primitive>();
int red = 0, green = 0, blue = 0;
float myX = 0, myY = 0;
float myWidthX1 = -4, myWidthX2 = 4, myWidthY1 = myY = 3, myWidthY2 = -3;
float myDeltaX,myDeltaY;
Vector3f color = new Vector3f(0,0,0);
public void RayTrace(Ray ray, int depth)
{
float distance = 1000000.0f;
Vector3f pi;
Primitive prim = null;
int result;
int thisDepth = 0;
int currentSphere = -1;
for(int s = 0; s < primitives.size(); s++)
{
Primitive pr = primitives.get(s);
Object[] res;
res = pr.intersect(ray,distance);
if(((Integer) res[0]).intValue() != 0)
{
result = ((Integer) res[0]).intValue();
distance = ((Integer) res[0]).floatValue();
currentSphere = s;
}
}
if(currentSphere == -1) return;
if(primitives.get(currentSphere).getLight())
{
color = new Vector3f(1,1,1);
//System.out.println("LIGHT");
return;
}
pi = ray.getOrigin().add((ray.getDirection().multiply(distance)));
//System.out.println(pi.x+" "+pi.y+" "+pi.z);
for(Primitive p : primitives)
{
if(p.getLight())
{
Primitive light = p;
Vector3f L = pi.subtract(((Sphere) light).getCenter());
L = Common.NORMALIZE(L);
prim = primitives.get(currentSphere);
Vector3f N = prim.getNormal(pi);
if(prim.getMaterial().getDiffuse() > 0)
{
float dot = Common.DOT(N,L);
if( dot > 0)
{
float diff = prim.getMaterial().getDiffuse() * dot;
Vector3f toAdd = prim.getMaterial().getColor().multiply(light.getMaterial().getColor());
toAdd = toAdd.multiply(diff);
color = color.add(toAdd);
}
}
}
}
}
public Raytracer()
{
initRender();
addObjects();
JFrame jf = new JFrame("Raytracing");
jf.setSize(width+0,height+20);
jf.setLocation(600,300);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
tracePanel = new JPanel()
{
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.drawImage((Image) traceImage,0,0,tracePanel);
//g.setColor(Color.red);
//g.fillRect(0,0,400,400);
}
};
Container inFrame = jf.getContentPane();
tracePanel.setLocation(50,10);
inFrame.add(tracePanel);
tracePanel.repaint();
jf.validate();
//jf.setResizable(false);
//jf.setUndecorated(true);
jf.setVisible(true);
Date d1 = new Date();
for(int x = 0; x < width; x++)
{
myX = myWidthX1;
for(int y = 0; y < height; y++)
{
color = new Vector3f(0,0,0);
dir = new Vector3f(myX,myY,0).subtract(origin);
dir = Common.NORMALIZE( dir );
Ray ray = new Ray(origin,dir);
RayTrace(ray,10);
red = (int)(color.x *255);
green = (int)(color.y *255);
blue = (int)(color.z*255);
if (red > 255) red = 255;
if (green > 255) green = 255;
if (blue > 255) blue = 255;
myX += myDeltaX;
traceImage.setRGB(x,y,((255 << 24) | ((int)red << 16) | ((int)green << 8) | (int)blue));
}
myY += myDeltaY;
}
Date d2 = new Date();
long time = d2.getTime()-d1.getTime();
float fps = 1000f/time;
System.out.println("FPS: "+fps);
System.out.println("Time: "+time);
tracePanel.repaint();
}
public static void main(String[] args)
{
new Raytracer();
}
public void initRender()
{
// screen plane in world space coordinates
// calculate deltas for interpolation
myDeltaX = (myWidthX2 - myWidthX1) / width;
System.out.println(myDeltaX);
myDeltaY = (myWidthY2 - myWidthY1) / height;
}
}
Note - didn't include the addObjects() method as I didn't find it necessary.
Screenshot of my failed attempt:
[in Java|http://pici.se/pictures/mbLEDAojv.png]
Screenshot of built raytracer through visual c++ 2008:
[in C++|http://pici.se/pictures/bAEYCRVlk.png]
Note2 - i omitted the Plane in my scene as it covered half the scene.
Please help,
Thank you.
edit: sorry for double posting... I can't handle the insert URL button -.-'
edit2: I forgot to mention that i changed the line "Vector3f L = pi.subtract(((Sphere) light).getCenter());", it was the light's center that subtracted the pi but then the float dot ended up being < 0 :(
Edited by: Considerate on Apr 15, 2009 5:38 PM