15ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen// The ray tracer code in this file is written by Adam Burmister. It
25ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen// is available in its original form from:
35ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen//
45ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen//   http://labs.flog.nz.co/raytracer/
55ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen//
65ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen// It has been modified slightly by Google to work as a standalone
75ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen// benchmark, but the all the computational code remains
85ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen// untouched. This file also contains a copy of parts of the Prototype
95ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen// JavaScript framework which is used by the ray tracer.
105ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
115ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen// Variable used to hold a number that can be used to verify that
125ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen// the scene was ray traced correctly.
135ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsenvar checkNumber;
145ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
155ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
165ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen// ------------------------------------------------------------------------
175ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen// ------------------------------------------------------------------------
185ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
195ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen// The following is a copy of parts of the Prototype JavaScript library:
205ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
215ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen// Prototype JavaScript framework, version 1.5.0
225ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen// (c) 2005-2007 Sam Stephenson
235ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen//
245ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen// Prototype is freely distributable under the terms of an MIT-style license.
255ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen// For details, see the Prototype web site: http://prototype.conio.net/
265ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
275ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
285ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsenvar Class = {
295ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen  create: function() {
305ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    return function() {
315ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen      this.initialize.apply(this, arguments);
325ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    }
335ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen  }
345ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen};
355ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
365ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
375ddde30071f639962dd557c453f2ad01f8f0fd00Kristian MonsenObject.extend = function(destination, source) {
385ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen  for (var property in source) {
395ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    destination[property] = source[property];
405ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen  }
415ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen  return destination;
425ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen};
435ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
445ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
455ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen// ------------------------------------------------------------------------
465ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen// ------------------------------------------------------------------------
475ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
485ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen// The rest of this file is the actual ray tracer written by Adam
495ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen// Burmister. It's a concatenation of the following files:
505ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen//
515ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen//   flog/color.js
525ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen//   flog/light.js
535ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen//   flog/vector.js
545ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen//   flog/ray.js
555ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen//   flog/scene.js
565ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen//   flog/material/basematerial.js
575ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen//   flog/material/solid.js
585ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen//   flog/material/chessboard.js
595ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen//   flog/shape/baseshape.js
605ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen//   flog/shape/sphere.js
615ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen//   flog/shape/plane.js
625ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen//   flog/intersectioninfo.js
635ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen//   flog/camera.js
645ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen//   flog/background.js
655ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen//   flog/engine.js
665ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
675ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
685ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen/* Fake a Flog.* namespace */
695ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsenif(typeof(Flog) == 'undefined') var Flog = {};
705ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsenif(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
715ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
725ddde30071f639962dd557c453f2ad01f8f0fd00Kristian MonsenFlog.RayTracer.Color = Class.create();
735ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
745ddde30071f639962dd557c453f2ad01f8f0fd00Kristian MonsenFlog.RayTracer.Color.prototype = {
755ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    red : 0.0,
765ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    green : 0.0,
775ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    blue : 0.0,
785ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
795ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    initialize : function(r, g, b) {
805ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        if(!r) r = 0.0;
815ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        if(!g) g = 0.0;
825ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        if(!b) b = 0.0;
835ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
845ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        this.red = r;
855ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        this.green = g;
865ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        this.blue = b;
875ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    },
885ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
895ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    add : function(c1, c2){
905ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        var result = new Flog.RayTracer.Color(0,0,0);
915ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
925ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        result.red = c1.red + c2.red;
935ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        result.green = c1.green + c2.green;
945ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        result.blue = c1.blue + c2.blue;
955ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
965ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        return result;
975ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    },
985ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
995ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    addScalar: function(c1, s){
1005ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        var result = new Flog.RayTracer.Color(0,0,0);
1015ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
1025ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        result.red = c1.red + s;
1035ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        result.green = c1.green + s;
1045ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        result.blue = c1.blue + s;
1055ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
1065ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        result.limit();
1075ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
1085ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        return result;
1095ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    },
1105ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
1115ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    subtract: function(c1, c2){
1125ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        var result = new Flog.RayTracer.Color(0,0,0);
1135ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
1145ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        result.red = c1.red - c2.red;
1155ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        result.green = c1.green - c2.green;
1165ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        result.blue = c1.blue - c2.blue;
1175ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
1185ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        return result;
1195ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    },
1205ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
1215ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    multiply : function(c1, c2) {
1225ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        var result = new Flog.RayTracer.Color(0,0,0);
1235ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
1245ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        result.red = c1.red * c2.red;
1255ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        result.green = c1.green * c2.green;
1265ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        result.blue = c1.blue * c2.blue;
1275ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
1285ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        return result;
1295ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    },
1305ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
1315ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    multiplyScalar : function(c1, f) {
1325ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        var result = new Flog.RayTracer.Color(0,0,0);
1335ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
1345ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        result.red = c1.red * f;
1355ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        result.green = c1.green * f;
1365ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        result.blue = c1.blue * f;
1375ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
1385ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        return result;
1395ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    },
1405ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
1415ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    divideFactor : function(c1, f) {
1425ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        var result = new Flog.RayTracer.Color(0,0,0);
1435ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
1445ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        result.red = c1.red / f;
1455ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        result.green = c1.green / f;
1465ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        result.blue = c1.blue / f;
1475ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
1485ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        return result;
1495ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    },
1505ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
1515ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    limit: function(){
1525ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        this.red = (this.red > 0.0) ? ( (this.red > 1.0) ? 1.0 : this.red ) : 0.0;
1535ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        this.green = (this.green > 0.0) ? ( (this.green > 1.0) ? 1.0 : this.green ) : 0.0;
1545ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        this.blue = (this.blue > 0.0) ? ( (this.blue > 1.0) ? 1.0 : this.blue ) : 0.0;
1555ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    },
1565ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
1575ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    distance : function(color) {
1585ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        var d = Math.abs(this.red - color.red) + Math.abs(this.green - color.green) + Math.abs(this.blue - color.blue);
1595ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        return d;
1605ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    },
1615ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
1625ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    blend: function(c1, c2, w){
1635ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        var result = new Flog.RayTracer.Color(0,0,0);
1645ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        result = Flog.RayTracer.Color.prototype.add(
1655ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                    Flog.RayTracer.Color.prototype.multiplyScalar(c1, 1 - w),
1665ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                    Flog.RayTracer.Color.prototype.multiplyScalar(c2, w)
1675ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                  );
1685ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        return result;
1695ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    },
1705ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
1715ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    brightness : function() {
1725ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        var r = Math.floor(this.red*255);
1735ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        var g = Math.floor(this.green*255);
1745ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        var b = Math.floor(this.blue*255);
1755ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        return (r * 77 + g * 150 + b * 29) >> 8;
1765ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    },
1775ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
1785ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    toString : function () {
1795ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        var r = Math.floor(this.red*255);
1805ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        var g = Math.floor(this.green*255);
1815ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        var b = Math.floor(this.blue*255);
1825ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
1835ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        return "rgb("+ r +","+ g +","+ b +")";
1845ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    }
1855ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen}
1865ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen/* Fake a Flog.* namespace */
1875ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsenif(typeof(Flog) == 'undefined') var Flog = {};
1885ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsenif(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
1895ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
1905ddde30071f639962dd557c453f2ad01f8f0fd00Kristian MonsenFlog.RayTracer.Light = Class.create();
1915ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
1925ddde30071f639962dd557c453f2ad01f8f0fd00Kristian MonsenFlog.RayTracer.Light.prototype = {
1935ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    position: null,
1945ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    color: null,
1955ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    intensity: 10.0,
1965ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
1975ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    initialize : function(pos, color, intensity) {
1985ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        this.position = pos;
1995ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        this.color = color;
2005ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        this.intensity = (intensity ? intensity : 10.0);
2015ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    },
2025ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
2035ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    toString : function () {
2045ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        return 'Light [' + this.position.x + ',' + this.position.y + ',' + this.position.z + ']';
2055ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    }
2065ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen}
2075ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen/* Fake a Flog.* namespace */
2085ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsenif(typeof(Flog) == 'undefined') var Flog = {};
2095ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsenif(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
2105ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
2115ddde30071f639962dd557c453f2ad01f8f0fd00Kristian MonsenFlog.RayTracer.Vector = Class.create();
2125ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
2135ddde30071f639962dd557c453f2ad01f8f0fd00Kristian MonsenFlog.RayTracer.Vector.prototype = {
2145ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    x : 0.0,
2155ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    y : 0.0,
2165ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    z : 0.0,
2175ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
2185ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    initialize : function(x, y, z) {
2195ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        this.x = (x ? x : 0);
2205ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        this.y = (y ? y : 0);
2215ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        this.z = (z ? z : 0);
2225ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    },
2235ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
2245ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    copy: function(vector){
2255ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        this.x = vector.x;
2265ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        this.y = vector.y;
2275ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        this.z = vector.z;
2285ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    },
2295ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
2305ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    normalize : function() {
2315ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        var m = this.magnitude();
2325ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        return new Flog.RayTracer.Vector(this.x / m, this.y / m, this.z / m);
2335ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    },
2345ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
2355ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    magnitude : function() {
2365ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        return Math.sqrt((this.x * this.x) + (this.y * this.y) + (this.z * this.z));
2375ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    },
2385ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
2395ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    cross : function(w) {
2405ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        return new Flog.RayTracer.Vector(
2415ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                                            -this.z * w.y + this.y * w.z,
2425ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                                           this.z * w.x - this.x * w.z,
2435ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                                          -this.y * w.x + this.x * w.y);
2445ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    },
2455ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
2465ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    dot : function(w) {
2475ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        return this.x * w.x + this.y * w.y + this.z * w.z;
2485ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    },
2495ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
2505ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    add : function(v, w) {
2515ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        return new Flog.RayTracer.Vector(w.x + v.x, w.y + v.y, w.z + v.z);
2525ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    },
2535ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
2545ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    subtract : function(v, w) {
2555ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        if(!w || !v) throw 'Vectors must be defined [' + v + ',' + w + ']';
2565ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        return new Flog.RayTracer.Vector(v.x - w.x, v.y - w.y, v.z - w.z);
2575ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    },
2585ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
2595ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    multiplyVector : function(v, w) {
2605ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        return new Flog.RayTracer.Vector(v.x * w.x, v.y * w.y, v.z * w.z);
2615ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    },
2625ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
2635ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    multiplyScalar : function(v, w) {
2645ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        return new Flog.RayTracer.Vector(v.x * w, v.y * w, v.z * w);
2655ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    },
2665ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
2675ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    toString : function () {
2685ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        return 'Vector [' + this.x + ',' + this.y + ',' + this.z + ']';
2695ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    }
2705ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen}
2715ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen/* Fake a Flog.* namespace */
2725ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsenif(typeof(Flog) == 'undefined') var Flog = {};
2735ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsenif(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
2745ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
2755ddde30071f639962dd557c453f2ad01f8f0fd00Kristian MonsenFlog.RayTracer.Ray = Class.create();
2765ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
2775ddde30071f639962dd557c453f2ad01f8f0fd00Kristian MonsenFlog.RayTracer.Ray.prototype = {
2785ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    position : null,
2795ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    direction : null,
2805ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    initialize : function(pos, dir) {
2815ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        this.position = pos;
2825ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        this.direction = dir;
2835ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    },
2845ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
2855ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    toString : function () {
2865ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        return 'Ray [' + this.position + ',' + this.direction + ']';
2875ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    }
2885ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen}
2895ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen/* Fake a Flog.* namespace */
2905ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsenif(typeof(Flog) == 'undefined') var Flog = {};
2915ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsenif(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
2925ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
2935ddde30071f639962dd557c453f2ad01f8f0fd00Kristian MonsenFlog.RayTracer.Scene = Class.create();
2945ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
2955ddde30071f639962dd557c453f2ad01f8f0fd00Kristian MonsenFlog.RayTracer.Scene.prototype = {
2965ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    camera : null,
2975ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    shapes : [],
2985ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    lights : [],
2995ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    background : null,
3005ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
3015ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    initialize : function() {
3025ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        this.camera = new Flog.RayTracer.Camera(
3035ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            new Flog.RayTracer.Vector(0,0,-5),
3045ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            new Flog.RayTracer.Vector(0,0,1),
3055ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            new Flog.RayTracer.Vector(0,1,0)
3065ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        );
3075ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        this.shapes = new Array();
3085ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        this.lights = new Array();
3095ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        this.background = new Flog.RayTracer.Background(new Flog.RayTracer.Color(0,0,0.5), 0.2);
3105ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    }
3115ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen}
3125ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen/* Fake a Flog.* namespace */
3135ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsenif(typeof(Flog) == 'undefined') var Flog = {};
3145ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsenif(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
3155ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsenif(typeof(Flog.RayTracer.Material) == 'undefined') Flog.RayTracer.Material = {};
3165ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
3175ddde30071f639962dd557c453f2ad01f8f0fd00Kristian MonsenFlog.RayTracer.Material.BaseMaterial = Class.create();
3185ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
3195ddde30071f639962dd557c453f2ad01f8f0fd00Kristian MonsenFlog.RayTracer.Material.BaseMaterial.prototype = {
3205ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
3215ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    gloss: 2.0,             // [0...infinity] 0 = matt
3225ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    transparency: 0.0,      // 0=opaque
3235ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    reflection: 0.0,        // [0...infinity] 0 = no reflection
3245ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    refraction: 0.50,
3255ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    hasTexture: false,
3265ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
3275ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    initialize : function() {
3285ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
3295ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    },
3305ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
3315ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    getColor: function(u, v){
3325ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
3335ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    },
3345ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
3355ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    wrapUp: function(t){
3365ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        t = t % 2.0;
3375ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        if(t < -1) t += 2.0;
3385ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        if(t >= 1) t -= 2.0;
3395ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        return t;
3405ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    },
3415ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
3425ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    toString : function () {
3435ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        return 'Material [gloss=' + this.gloss + ', transparency=' + this.transparency + ', hasTexture=' + this.hasTexture +']';
3445ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    }
3455ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen}
3465ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen/* Fake a Flog.* namespace */
3475ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsenif(typeof(Flog) == 'undefined') var Flog = {};
3485ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsenif(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
3495ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
3505ddde30071f639962dd557c453f2ad01f8f0fd00Kristian MonsenFlog.RayTracer.Material.Solid = Class.create();
3515ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
3525ddde30071f639962dd557c453f2ad01f8f0fd00Kristian MonsenFlog.RayTracer.Material.Solid.prototype = Object.extend(
3535ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    new Flog.RayTracer.Material.BaseMaterial(), {
3545ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        initialize : function(color, reflection, refraction, transparency, gloss) {
3555ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            this.color = color;
3565ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            this.reflection = reflection;
3575ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            this.transparency = transparency;
3585ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            this.gloss = gloss;
3595ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            this.hasTexture = false;
3605ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        },
3615ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
3625ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        getColor: function(u, v){
3635ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            return this.color;
3645ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        },
3655ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
3665ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        toString : function () {
3675ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            return 'SolidMaterial [gloss=' + this.gloss + ', transparency=' + this.transparency + ', hasTexture=' + this.hasTexture +']';
3685ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        }
3695ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    }
3705ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen);
3715ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen/* Fake a Flog.* namespace */
3725ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsenif(typeof(Flog) == 'undefined') var Flog = {};
3735ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsenif(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
3745ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
3755ddde30071f639962dd557c453f2ad01f8f0fd00Kristian MonsenFlog.RayTracer.Material.Chessboard = Class.create();
3765ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
3775ddde30071f639962dd557c453f2ad01f8f0fd00Kristian MonsenFlog.RayTracer.Material.Chessboard.prototype = Object.extend(
3785ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    new Flog.RayTracer.Material.BaseMaterial(), {
3795ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        colorEven: null,
3805ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        colorOdd: null,
3815ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        density: 0.5,
3825ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
3835ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        initialize : function(colorEven, colorOdd, reflection, transparency, gloss, density) {
3845ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            this.colorEven = colorEven;
3855ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            this.colorOdd = colorOdd;
3865ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            this.reflection = reflection;
3875ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            this.transparency = transparency;
3885ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            this.gloss = gloss;
3895ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            this.density = density;
3905ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            this.hasTexture = true;
3915ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        },
3925ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
3935ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        getColor: function(u, v){
3945ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            var t = this.wrapUp(u * this.density) * this.wrapUp(v * this.density);
3955ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
3965ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            if(t < 0.0)
3975ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                return this.colorEven;
3985ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            else
3995ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                return this.colorOdd;
4005ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        },
4015ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
4025ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        toString : function () {
4035ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            return 'ChessMaterial [gloss=' + this.gloss + ', transparency=' + this.transparency + ', hasTexture=' + this.hasTexture +']';
4045ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        }
4055ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    }
4065ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen);
4075ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen/* Fake a Flog.* namespace */
4085ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsenif(typeof(Flog) == 'undefined') var Flog = {};
4095ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsenif(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
4105ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsenif(typeof(Flog.RayTracer.Shape) == 'undefined') Flog.RayTracer.Shape = {};
4115ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
4125ddde30071f639962dd557c453f2ad01f8f0fd00Kristian MonsenFlog.RayTracer.Shape.Sphere = Class.create();
4135ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
4145ddde30071f639962dd557c453f2ad01f8f0fd00Kristian MonsenFlog.RayTracer.Shape.Sphere.prototype = {
4155ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    initialize : function(pos, radius, material) {
4165ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        this.radius = radius;
4175ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        this.position = pos;
4185ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        this.material = material;
4195ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    },
4205ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
4215ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    intersect: function(ray){
4225ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        var info = new Flog.RayTracer.IntersectionInfo();
4235ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        info.shape = this;
4245ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
4255ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        var dst = Flog.RayTracer.Vector.prototype.subtract(ray.position, this.position);
4265ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
4275ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        var B = dst.dot(ray.direction);
4285ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        var C = dst.dot(dst) - (this.radius * this.radius);
4295ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        var D = (B * B) - C;
4305ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
4315ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        if(D > 0){ // intersection!
4325ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            info.isHit = true;
4335ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            info.distance = (-B) - Math.sqrt(D);
4345ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            info.position = Flog.RayTracer.Vector.prototype.add(
4355ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                                                ray.position,
4365ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                                                Flog.RayTracer.Vector.prototype.multiplyScalar(
4375ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                                                    ray.direction,
4385ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                                                    info.distance
4395ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                                                )
4405ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                                            );
4415ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            info.normal = Flog.RayTracer.Vector.prototype.subtract(
4425ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                                            info.position,
4435ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                                            this.position
4445ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                                        ).normalize();
4455ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
4465ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            info.color = this.material.getColor(0,0);
4475ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        } else {
4485ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            info.isHit = false;
4495ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        }
4505ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        return info;
4515ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    },
4525ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
4535ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    toString : function () {
4545ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        return 'Sphere [position=' + this.position + ', radius=' + this.radius + ']';
4555ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    }
4565ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen}
4575ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen/* Fake a Flog.* namespace */
4585ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsenif(typeof(Flog) == 'undefined') var Flog = {};
4595ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsenif(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
4605ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsenif(typeof(Flog.RayTracer.Shape) == 'undefined') Flog.RayTracer.Shape = {};
4615ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
4625ddde30071f639962dd557c453f2ad01f8f0fd00Kristian MonsenFlog.RayTracer.Shape.Plane = Class.create();
4635ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
4645ddde30071f639962dd557c453f2ad01f8f0fd00Kristian MonsenFlog.RayTracer.Shape.Plane.prototype = {
4655ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    d: 0.0,
4665ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
4675ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    initialize : function(pos, d, material) {
4685ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        this.position = pos;
4695ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        this.d = d;
4705ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        this.material = material;
4715ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    },
4725ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
4735ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    intersect: function(ray){
4745ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        var info = new Flog.RayTracer.IntersectionInfo();
4755ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
4765ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        var Vd = this.position.dot(ray.direction);
4775ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        if(Vd == 0) return info; // no intersection
4785ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
4795ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        var t = -(this.position.dot(ray.position) + this.d) / Vd;
4805ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        if(t <= 0) return info;
4815ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
4825ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        info.shape = this;
4835ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        info.isHit = true;
4845ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        info.position = Flog.RayTracer.Vector.prototype.add(
4855ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                                            ray.position,
4865ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                                            Flog.RayTracer.Vector.prototype.multiplyScalar(
4875ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                                                ray.direction,
4885ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                                                t
4895ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                                            )
4905ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                                        );
4915ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        info.normal = this.position;
4925ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        info.distance = t;
4935ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
4945ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        if(this.material.hasTexture){
4955ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            var vU = new Flog.RayTracer.Vector(this.position.y, this.position.z, -this.position.x);
4965ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            var vV = vU.cross(this.position);
4975ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            var u = info.position.dot(vU);
4985ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            var v = info.position.dot(vV);
4995ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            info.color = this.material.getColor(u,v);
5005ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        } else {
5015ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            info.color = this.material.getColor(0,0);
5025ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        }
5035ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
5045ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        return info;
5055ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    },
5065ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
5075ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    toString : function () {
5085ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        return 'Plane [' + this.position + ', d=' + this.d + ']';
5095ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    }
5105ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen}
5115ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen/* Fake a Flog.* namespace */
5125ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsenif(typeof(Flog) == 'undefined') var Flog = {};
5135ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsenif(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
5145ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
5155ddde30071f639962dd557c453f2ad01f8f0fd00Kristian MonsenFlog.RayTracer.IntersectionInfo = Class.create();
5165ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
5175ddde30071f639962dd557c453f2ad01f8f0fd00Kristian MonsenFlog.RayTracer.IntersectionInfo.prototype = {
5185ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    isHit: false,
5195ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    hitCount: 0,
5205ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    shape: null,
5215ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    position: null,
5225ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    normal: null,
5235ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    color: null,
5245ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    distance: null,
5255ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
5265ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    initialize : function() {
5275ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        this.color = new Flog.RayTracer.Color(0,0,0);
5285ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    },
5295ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
5305ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    toString : function () {
5315ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        return 'Intersection [' + this.position + ']';
5325ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    }
5335ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen}
5345ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen/* Fake a Flog.* namespace */
5355ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsenif(typeof(Flog) == 'undefined') var Flog = {};
5365ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsenif(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
5375ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
5385ddde30071f639962dd557c453f2ad01f8f0fd00Kristian MonsenFlog.RayTracer.Camera = Class.create();
5395ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
5405ddde30071f639962dd557c453f2ad01f8f0fd00Kristian MonsenFlog.RayTracer.Camera.prototype = {
5415ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    position: null,
5425ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    lookAt: null,
5435ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    equator: null,
5445ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    up: null,
5455ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    screen: null,
5465ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
5475ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    initialize : function(pos, lookAt, up) {
5485ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        this.position = pos;
5495ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        this.lookAt = lookAt;
5505ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        this.up = up;
5515ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        this.equator = lookAt.normalize().cross(this.up);
5525ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        this.screen = Flog.RayTracer.Vector.prototype.add(this.position, this.lookAt);
5535ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    },
5545ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
5555ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    getRay: function(vx, vy){
5565ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        var pos = Flog.RayTracer.Vector.prototype.subtract(
5575ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            this.screen,
5585ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            Flog.RayTracer.Vector.prototype.subtract(
5595ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                Flog.RayTracer.Vector.prototype.multiplyScalar(this.equator, vx),
5605ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                Flog.RayTracer.Vector.prototype.multiplyScalar(this.up, vy)
5615ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            )
5625ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        );
5635ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        pos.y = pos.y * -1;
5645ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        var dir = Flog.RayTracer.Vector.prototype.subtract(
5655ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            pos,
5665ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            this.position
5675ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        );
5685ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
5695ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        var ray = new Flog.RayTracer.Ray(pos, dir.normalize());
5705ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
5715ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        return ray;
5725ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    },
5735ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
5745ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    toString : function () {
5755ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        return 'Ray []';
5765ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    }
5775ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen}
5785ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen/* Fake a Flog.* namespace */
5795ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsenif(typeof(Flog) == 'undefined') var Flog = {};
5805ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsenif(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
5815ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
5825ddde30071f639962dd557c453f2ad01f8f0fd00Kristian MonsenFlog.RayTracer.Background = Class.create();
5835ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
5845ddde30071f639962dd557c453f2ad01f8f0fd00Kristian MonsenFlog.RayTracer.Background.prototype = {
5855ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    color : null,
5865ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    ambience : 0.0,
5875ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
5885ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    initialize : function(color, ambience) {
5895ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        this.color = color;
5905ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        this.ambience = ambience;
5915ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    }
5925ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen}
5935ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen/* Fake a Flog.* namespace */
5945ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsenif(typeof(Flog) == 'undefined') var Flog = {};
5955ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsenif(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {};
5965ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
5975ddde30071f639962dd557c453f2ad01f8f0fd00Kristian MonsenFlog.RayTracer.Engine = Class.create();
5985ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
5995ddde30071f639962dd557c453f2ad01f8f0fd00Kristian MonsenFlog.RayTracer.Engine.prototype = {
6005ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    canvas: null, /* 2d context we can render to */
6015ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
6025ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    initialize: function(options){
6035ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        this.options = Object.extend({
6045ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                canvasHeight: 100,
6055ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                canvasWidth: 100,
6065ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                pixelWidth: 2,
6075ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                pixelHeight: 2,
6085ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                renderDiffuse: false,
6095ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                renderShadows: false,
6105ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                renderHighlights: false,
6115ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                renderReflections: false,
6125ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                rayDepth: 2
6135ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            }, options || {});
6145ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
6155ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        this.options.canvasHeight /= this.options.pixelHeight;
6165ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        this.options.canvasWidth /= this.options.pixelWidth;
6175ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
6185ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        /* TODO: dynamically include other scripts */
6195ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    },
6205ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
6215ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    setPixel: function(x, y, color){
6225ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        var pxW, pxH;
6235ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        pxW = this.options.pixelWidth;
6245ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        pxH = this.options.pixelHeight;
6255ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
6265ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        if (this.canvas) {
6275ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen          this.canvas.fillStyle = color.toString();
6285ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen          this.canvas.fillRect (x * pxW, y * pxH, pxW, pxH);
6295ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        } else {
6305ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen          if (x ===  y) {
6315ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            checkNumber += color.brightness();
6325ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen          }
6335ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen          // print(x * pxW, y * pxH, pxW, pxH);
6345ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        }
6355ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    },
6365ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
6375ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    renderScene: function(scene, canvas){
6385ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        checkNumber = 0;
6395ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        /* Get canvas */
6405ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        if (canvas) {
6415ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen          this.canvas = canvas.getContext("2d");
6425ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        } else {
6435ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen          this.canvas = null;
6445ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        }
6455ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
6465ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        var canvasHeight = this.options.canvasHeight;
6475ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        var canvasWidth = this.options.canvasWidth;
6485ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
6495ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        for(var y=0; y < canvasHeight; y++){
6505ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            for(var x=0; x < canvasWidth; x++){
6515ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                var yp = y * 1.0 / canvasHeight * 2 - 1;
6525ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen          		var xp = x * 1.0 / canvasWidth * 2 - 1;
6535ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
6545ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen          		var ray = scene.camera.getRay(xp, yp);
6555ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
6565ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen          		var color = this.getPixelColor(ray, scene);
6575ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
6585ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            	this.setPixel(x, y, color);
6595ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            }
6605ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        }
6615ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        if (checkNumber !== 2321) {
6625ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen          throw new Error("Scene rendered incorrectly");
6635ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        }
6645ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    },
6655ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
6665ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    getPixelColor: function(ray, scene){
6675ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        var info = this.testIntersection(ray, scene, null);
6685ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        if(info.isHit){
6695ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            var color = this.rayTrace(info, ray, scene, 0);
6705ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            return color;
6715ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        }
6725ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        return scene.background.color;
6735ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    },
6745ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
6755ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    testIntersection: function(ray, scene, exclude){
6765ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        var hits = 0;
6775ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        var best = new Flog.RayTracer.IntersectionInfo();
6785ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        best.distance = 2000;
6795ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
6805ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        for(var i=0; i<scene.shapes.length; i++){
6815ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            var shape = scene.shapes[i];
6825ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
6835ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            if(shape != exclude){
6845ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                var info = shape.intersect(ray);
6855ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                if(info.isHit && info.distance >= 0 && info.distance < best.distance){
6865ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                    best = info;
6875ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                    hits++;
6885ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                }
6895ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            }
6905ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        }
6915ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        best.hitCount = hits;
6925ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        return best;
6935ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    },
6945ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
6955ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    getReflectionRay: function(P,N,V){
6965ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        var c1 = -N.dot(V);
6975ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        var R1 = Flog.RayTracer.Vector.prototype.add(
6985ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            Flog.RayTracer.Vector.prototype.multiplyScalar(N, 2*c1),
6995ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            V
7005ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        );
7015ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        return new Flog.RayTracer.Ray(P, R1);
7025ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    },
7035ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
7045ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    rayTrace: function(info, ray, scene, depth){
7055ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        // Calc ambient
7065ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        var color = Flog.RayTracer.Color.prototype.multiplyScalar(info.color, scene.background.ambience);
7075ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        var oldColor = color;
7085ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        var shininess = Math.pow(10, info.shape.material.gloss + 1);
7095ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
7105ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        for(var i=0; i<scene.lights.length; i++){
7115ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            var light = scene.lights[i];
7125ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
7135ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            // Calc diffuse lighting
7145ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            var v = Flog.RayTracer.Vector.prototype.subtract(
7155ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                                light.position,
7165ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                                info.position
7175ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                            ).normalize();
7185ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
7195ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            if(this.options.renderDiffuse){
7205ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                var L = v.dot(info.normal);
7215ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                if(L > 0.0){
7225ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                    color = Flog.RayTracer.Color.prototype.add(
7235ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                                        color,
7245ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                                        Flog.RayTracer.Color.prototype.multiply(
7255ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                                            info.color,
7265ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                                            Flog.RayTracer.Color.prototype.multiplyScalar(
7275ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                                                light.color,
7285ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                                                L
7295ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                                            )
7305ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                                        )
7315ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                                    );
7325ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                }
7335ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            }
7345ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
7355ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            // The greater the depth the more accurate the colours, but
7365ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            // this is exponentially (!) expensive
7375ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            if(depth <= this.options.rayDepth){
7385ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen          // calculate reflection ray
7395ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen          if(this.options.renderReflections && info.shape.material.reflection > 0)
7405ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen          {
7415ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen              var reflectionRay = this.getReflectionRay(info.position, info.normal, ray.direction);
7425ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen              var refl = this.testIntersection(reflectionRay, scene, info.shape);
7435ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
7445ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen              if (refl.isHit && refl.distance > 0){
7455ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                  refl.color = this.rayTrace(refl, reflectionRay, scene, depth + 1);
7465ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen              } else {
7475ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                  refl.color = scene.background.color;
7485ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                        }
7495ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
7505ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                  color = Flog.RayTracer.Color.prototype.blend(
7515ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                    color,
7525ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                    refl.color,
7535ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                    info.shape.material.reflection
7545ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                  );
7555ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen          }
7565ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
7575ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                // Refraction
7585ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                /* TODO */
7595ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            }
7605ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
7615ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            /* Render shadows and highlights */
7625ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
7635ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            var shadowInfo = new Flog.RayTracer.IntersectionInfo();
7645ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
7655ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            if(this.options.renderShadows){
7665ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                var shadowRay = new Flog.RayTracer.Ray(info.position, v);
7675ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
7685ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                shadowInfo = this.testIntersection(shadowRay, scene, info.shape);
7695ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                if(shadowInfo.isHit && shadowInfo.shape != info.shape /*&& shadowInfo.shape.type != 'PLANE'*/){
7705ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                    var vA = Flog.RayTracer.Color.prototype.multiplyScalar(color, 0.5);
7715ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                    var dB = (0.5 * Math.pow(shadowInfo.shape.material.transparency, 0.5));
7725ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                    color = Flog.RayTracer.Color.prototype.addScalar(vA,dB);
7735ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                }
7745ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            }
7755ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
7765ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen      // Phong specular highlights
7775ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen      if(this.options.renderHighlights && !shadowInfo.isHit && info.shape.material.gloss > 0){
7785ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        var Lv = Flog.RayTracer.Vector.prototype.subtract(
7795ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                            info.shape.position,
7805ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                            light.position
7815ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                        ).normalize();
7825ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
7835ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        var E = Flog.RayTracer.Vector.prototype.subtract(
7845ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                            scene.camera.position,
7855ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                            info.shape.position
7865ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                        ).normalize();
7875ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
7885ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        var H = Flog.RayTracer.Vector.prototype.subtract(
7895ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                            E,
7905ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                            Lv
7915ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                        ).normalize();
7925ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
7935ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        var glossWeight = Math.pow(Math.max(info.normal.dot(H), 0), shininess);
7945ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        color = Flog.RayTracer.Color.prototype.add(
7955ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                            Flog.RayTracer.Color.prototype.multiplyScalar(light.color, glossWeight),
7965ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                            color
7975ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                        );
7985ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen      }
7995ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        }
8005ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        color.limit();
8015ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        return color;
8025ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    }
8035ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen};
8045ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
8055ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
8065ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsenfunction renderScene(){
8075ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    var scene = new Flog.RayTracer.Scene();
8085ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
8095ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    scene.camera = new Flog.RayTracer.Camera(
8105ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                        new Flog.RayTracer.Vector(0, 0, -15),
8115ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                        new Flog.RayTracer.Vector(-0.2, 0, 5),
8125ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                        new Flog.RayTracer.Vector(0, 1, 0)
8135ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                    );
8145ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
8155ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    scene.background = new Flog.RayTracer.Background(
8165ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                                new Flog.RayTracer.Color(0.5, 0.5, 0.5),
8175ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                                0.4
8185ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                            );
8195ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
8205ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    var sphere = new Flog.RayTracer.Shape.Sphere(
8215ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        new Flog.RayTracer.Vector(-1.5, 1.5, 2),
8225ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        1.5,
8235ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        new Flog.RayTracer.Material.Solid(
8245ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            new Flog.RayTracer.Color(0,0.5,0.5),
8255ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            0.3,
8265ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            0.0,
8275ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            0.0,
8285ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            2.0
8295ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        )
8305ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    );
8315ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
8325ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    var sphere1 = new Flog.RayTracer.Shape.Sphere(
8335ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        new Flog.RayTracer.Vector(1, 0.25, 1),
8345ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        0.5,
8355ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        new Flog.RayTracer.Material.Solid(
8365ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            new Flog.RayTracer.Color(0.9,0.9,0.9),
8375ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            0.1,
8385ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            0.0,
8395ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            0.0,
8405ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            1.5
8415ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        )
8425ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    );
8435ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
8445ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    var plane = new Flog.RayTracer.Shape.Plane(
8455ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                                new Flog.RayTracer.Vector(0.1, 0.9, -0.5).normalize(),
8465ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                                1.2,
8475ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                                new Flog.RayTracer.Material.Chessboard(
8485ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                                    new Flog.RayTracer.Color(1,1,1),
8495ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                                    new Flog.RayTracer.Color(0,0,0),
8505ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                                    0.2,
8515ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                                    0.0,
8525ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                                    1.0,
8535ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                                    0.7
8545ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                                )
8555ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen                            );
8565ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
8575ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    scene.shapes.push(plane);
8585ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    scene.shapes.push(sphere);
8595ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    scene.shapes.push(sphere1);
8605ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
8615ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    var light = new Flog.RayTracer.Light(
8625ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        new Flog.RayTracer.Vector(5, 10, -1),
8635ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        new Flog.RayTracer.Color(0.8, 0.8, 0.8)
8645ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    );
8655ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
8665ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    var light1 = new Flog.RayTracer.Light(
8675ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        new Flog.RayTracer.Vector(-3, 5, -15),
8685ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        new Flog.RayTracer.Color(0.8, 0.8, 0.8),
8695ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        100
8705ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    );
8715ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
8725ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    scene.lights.push(light);
8735ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    scene.lights.push(light1);
8745ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
8755ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    var imageWidth = 100; // $F('imageWidth');
8765ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    var imageHeight = 100; // $F('imageHeight');
8775ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    var pixelSize = "5,5".split(','); //  $F('pixelSize').split(',');
8785ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    var renderDiffuse = true; // $F('renderDiffuse');
8795ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    var renderShadows = true; // $F('renderShadows');
8805ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    var renderHighlights = true; // $F('renderHighlights');
8815ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    var renderReflections = true; // $F('renderReflections');
8825ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    var rayDepth = 2;//$F('rayDepth');
8835ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
8845ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    var raytracer = new Flog.RayTracer.Engine(
8855ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        {
8865ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            canvasWidth: imageWidth,
8875ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            canvasHeight: imageHeight,
8885ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            pixelWidth: pixelSize[0],
8895ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            pixelHeight: pixelSize[1],
8905ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            "renderDiffuse": renderDiffuse,
8915ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            "renderHighlights": renderHighlights,
8925ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            "renderShadows": renderShadows,
8935ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            "renderReflections": renderReflections,
8945ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen            "rayDepth": rayDepth
8955ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen        }
8965ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    );
8975ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
8985ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen    raytracer.renderScene(scene, null, 0);
8995ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen}
9005ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen
9015ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsenfor (var i = 0; i < 6; ++i)
9025ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen  renderScene();
903