| boolean rendererd = false;int renderY = 0;
 int LineBuf[];
 
 
 float clamp(float val, float min, float max) {
 if (val < min) {
 return min;
 } else if (val > max) {
 return max;
 } else {
 return val;
 }
 }
 
 
 vec reflection(vec v, vec normal) {
 return v.add(normal.scale(-2 * v.dot(normal)));
 }
 
 int fcolor(float r, float g, float b) {
 int ir = (int)(clamp(r, 0, 1) * 255.99);
 int ig = (int)(clamp(g, 0, 1) * 255.99);
 int ib = (int)(clamp(b, 0, 1) * 255.99);
 return color(ir, ig, ib);
 }
 
 
 class Scene {
 ArrayList objs;
 ArrayList lights;
 
 Scene() {
 objs = new ArrayList();
 lights = new ArrayList();
 }
 
 void add_obj(Object obj) {
 objs.add(obj);
 }
 
 void add_light(PointLight light) {
 lights.add(light);
 }
 
 
 void find_nearest_intersect_with_ray(Intersect isect, vec orig, vec dir) {
 isect.t = -1;
 vec normal = new vec(0, 0, 0);
 for (int i=objs.size(); --i>=0; ) {
 Object obj = (Object)objs.get(i);
 float t = obj.intersect_line(normal, orig, dir);
 if (t >= 0 && (isect.t < 0 || t < isect.t)) {
 isect.t = t;
 isect.normal.set(normal);
 isect.obj = obj;
 }
 }
 }
 
 
 boolean intersect_anything(vec orig, vec target) {
 vec diff = target.sub(orig);
 float len = diff.length();
 vec dir = diff.scale(1.0 / len);
 vec normal = new vec(0, 0, 0);
 for (int i=objs.size(); --i>=0; ) {
 Object obj = (Object)objs.get(i);
 float t = obj.intersect_line(normal, orig, dir);
 if (t >= 0 && t < len) {
 return true;
 }
 }
 return false;
 }
 
 
 vec shading(vec pos, vec normal, Material material, vec raydir) {
 vec col = new vec(0, 0, 0);
 float a = material.reflection;
 if (a < 1) {
 col = col.add(calc_diffuse(pos, normal, material).scale(1 - a));
 }
 if (a > 0) {
 col = col.add(calc_reflection(pos, normal, raydir).scale(a));
 }
 return col;
 }
 vec calc_diffuse(vec pos, vec normal, Material material) {
 vec col = new vec(0, 0, 0);
 for (int i=lights.size(); --i>=0; ) {
 PointLight light = (PointLight)lights.get(i);
 if (visible(pos, light.pos)) {
 col = col.add(light.shading(pos, normal, material));
 }
 }
 return col;
 }
 vec calc_reflection(vec pos, vec normal, vec raydir) {
 vec refvec = reflection(raydir, normal);
 return raytrace(pos, refvec);
 }
 
 vec raytrace(vec orig, vec raydir) {
 Intersect isect = new Intersect();
 find_nearest_intersect_with_ray(isect, orig, raydir);
 if (isect.is_enable()) {
 vec pos = orig.add(raydir.scale(isect.t));
 return shading(pos, isect.normal, isect.obj.material, raydir);
 } else {
 return new vec(0, 0, 0);
 }
 }
 
 
 boolean visible(vec pos, vec target) {
 return !intersect_anything(pos, target);
 }
 }
 
 vec eyepos = new vec(0, 0, -1);
 Scene scene;
 
 void setup() {
 size(256, 256);
 LineBuf = new int[width];
 
 scene = new Scene();
 
 {
 Material material = new Material(1, 0, 0);
 material.reflection = 0.5;
 scene.add_obj(new Sphere(new vec(0, 0, 0), 0.5, material));
 }
 
 {
 Material material = new Material(0, 1, 0);
 material.grid = 0.25001;
 material.diffuse2.set(0, 0, 1);
 scene.add_obj(new Plane(0, 1, 0, 0.5, material));
 }
 scene.add_light(new PointLight(new vec(1000, 1000, -1000), new vec(2, 2, 2)));
 }
 
 void draw() {
 if (rendererd) { return; }
 
 render_line(LineBuf, width, height, renderY);
 copy_line(LineBuf, renderY);
 if (++renderY >= height) {
 rendererd = true;
 }
 }
 
 void copy_line(int[] img, int y) {
 loadPixels();
 for (int i = 0; i < width; ++i) {
 pixels[y * width + i] = img[i];
 }
 updatePixels();
 }
 
 void render_line(int[] img, int width, int height, int iy) {
 float w2 = width / 2;
 float h2 = height / 2;
 float xofs = w2 - 0.5;
 float yofs = h2 - 0.5;
 float py = -((iy - yofs) / h2);
 
 vec normal = new vec(0, 0, 0);
 for (int j=0; j<width; ++j) {
 float px = (j - xofs) / w2;
 vec raydir = (new vec(px, py, 1)).normal();
 vec col = scene.raytrace(eyepos, raydir);
 img[j] = fcolor(col.x, col.y, col.z);
 }
 }
 
 |