1a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The ray tracer code in this file is written by Adam Burmister. It 2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// is available in its original form from: 3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// http://labs.flog.nz.co/raytracer/ 5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// It has been modified slightly by Google to work as a standalone 7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// benchmark, but the all the computational code remains 8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// untouched. This file also contains a copy of parts of the Prototype 9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// JavaScript framework which is used by the ray tracer. 10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 110d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvar RayTrace = new BenchmarkSuite('RayTrace', 739989, [ 12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block new Benchmark('RayTrace', renderScene) 13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block]); 14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Variable used to hold a number that can be used to verify that 17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// the scene was ray traced correctly. 18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvar checkNumber; 19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ------------------------------------------------------------------------ 22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ------------------------------------------------------------------------ 23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The following is a copy of parts of the Prototype JavaScript library: 25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Prototype JavaScript framework, version 1.5.0 27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (c) 2005-2007 Sam Stephenson 28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Prototype is freely distributable under the terms of an MIT-style license. 30a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// For details, see the Prototype web site: http://prototype.conio.net/ 31a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvar Class = { 34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block create: function() { 35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return function() { 36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block this.initialize.apply(this, arguments); 37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockObject.extend = function(destination, source) { 43a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (var property in source) { 44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block destination[property] = source[property]; 45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return destination; 47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ------------------------------------------------------------------------ 51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// ------------------------------------------------------------------------ 52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// The rest of this file is the actual ray tracer written by Adam 54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Burmister. It's a concatenation of the following files: 55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// flog/color.js 57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// flog/light.js 58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// flog/vector.js 59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// flog/ray.js 60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// flog/scene.js 61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// flog/material/basematerial.js 62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// flog/material/solid.js 63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// flog/material/chessboard.js 64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// flog/shape/baseshape.js 65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// flog/shape/sphere.js 66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// flog/shape/plane.js 67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// flog/intersectioninfo.js 68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// flog/camera.js 69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// flog/background.js 70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// flog/engine.js 71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block/* Fake a Flog.* namespace */ 74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockif(typeof(Flog) == 'undefined') var Flog = {}; 75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockif(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {}; 76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockFlog.RayTracer.Color = Class.create(); 78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 79a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockFlog.RayTracer.Color.prototype = { 80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block red : 0.0, 81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block green : 0.0, 82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block blue : 0.0, 83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block initialize : function(r, g, b) { 85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if(!r) r = 0.0; 86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if(!g) g = 0.0; 87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if(!b) b = 0.0; 88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block this.red = r; 90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block this.green = g; 91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block this.blue = b; 92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block }, 93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block add : function(c1, c2){ 95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var result = new Flog.RayTracer.Color(0,0,0); 96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block result.red = c1.red + c2.red; 98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block result.green = c1.green + c2.green; 99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block result.blue = c1.blue + c2.blue; 100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return result; 102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block }, 103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block addScalar: function(c1, s){ 105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var result = new Flog.RayTracer.Color(0,0,0); 106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block result.red = c1.red + s; 108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block result.green = c1.green + s; 109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block result.blue = c1.blue + s; 110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block result.limit(); 112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return result; 114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block }, 115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block subtract: function(c1, c2){ 117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var result = new Flog.RayTracer.Color(0,0,0); 118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block result.red = c1.red - c2.red; 120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block result.green = c1.green - c2.green; 121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block result.blue = c1.blue - c2.blue; 122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return result; 124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block }, 125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block multiply : function(c1, c2) { 127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var result = new Flog.RayTracer.Color(0,0,0); 128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block result.red = c1.red * c2.red; 130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block result.green = c1.green * c2.green; 131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block result.blue = c1.blue * c2.blue; 132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return result; 134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block }, 135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block multiplyScalar : function(c1, f) { 137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var result = new Flog.RayTracer.Color(0,0,0); 138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block result.red = c1.red * f; 140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block result.green = c1.green * f; 141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block result.blue = c1.blue * f; 142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return result; 144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block }, 145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block divideFactor : function(c1, f) { 147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var result = new Flog.RayTracer.Color(0,0,0); 148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block result.red = c1.red / f; 150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block result.green = c1.green / f; 151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block result.blue = c1.blue / f; 152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return result; 154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block }, 155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block limit: function(){ 157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block this.red = (this.red > 0.0) ? ( (this.red > 1.0) ? 1.0 : this.red ) : 0.0; 158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block this.green = (this.green > 0.0) ? ( (this.green > 1.0) ? 1.0 : this.green ) : 0.0; 159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block this.blue = (this.blue > 0.0) ? ( (this.blue > 1.0) ? 1.0 : this.blue ) : 0.0; 160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block }, 161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block distance : function(color) { 163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var d = Math.abs(this.red - color.red) + Math.abs(this.green - color.green) + Math.abs(this.blue - color.blue); 164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return d; 165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block }, 166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block blend: function(c1, c2, w){ 168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var result = new Flog.RayTracer.Color(0,0,0); 169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block result = Flog.RayTracer.Color.prototype.add( 170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Flog.RayTracer.Color.prototype.multiplyScalar(c1, 1 - w), 171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Flog.RayTracer.Color.prototype.multiplyScalar(c2, w) 172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ); 173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return result; 174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block }, 175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block brightness : function() { 177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var r = Math.floor(this.red*255); 178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var g = Math.floor(this.green*255); 179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var b = Math.floor(this.blue*255); 180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return (r * 77 + g * 150 + b * 29) >> 8; 181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block }, 182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block toString : function () { 184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var r = Math.floor(this.red*255); 185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var g = Math.floor(this.green*255); 186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var b = Math.floor(this.blue*255); 187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return "rgb("+ r +","+ g +","+ b +")"; 189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block/* Fake a Flog.* namespace */ 192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockif(typeof(Flog) == 'undefined') var Flog = {}; 193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockif(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {}; 194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockFlog.RayTracer.Light = Class.create(); 196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockFlog.RayTracer.Light.prototype = { 198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block position: null, 199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block color: null, 200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block intensity: 10.0, 201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block initialize : function(pos, color, intensity) { 203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block this.position = pos; 204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block this.color = color; 205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block this.intensity = (intensity ? intensity : 10.0); 206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block }, 207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block toString : function () { 209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 'Light [' + this.position.x + ',' + this.position.y + ',' + this.position.z + ']'; 210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block/* Fake a Flog.* namespace */ 213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockif(typeof(Flog) == 'undefined') var Flog = {}; 214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockif(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {}; 215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockFlog.RayTracer.Vector = Class.create(); 217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockFlog.RayTracer.Vector.prototype = { 219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block x : 0.0, 220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block y : 0.0, 221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block z : 0.0, 222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block initialize : function(x, y, z) { 224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block this.x = (x ? x : 0); 225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block this.y = (y ? y : 0); 226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block this.z = (z ? z : 0); 227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block }, 228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block copy: function(vector){ 230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block this.x = vector.x; 231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block this.y = vector.y; 232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block this.z = vector.z; 233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block }, 234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block normalize : function() { 236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var m = this.magnitude(); 237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return new Flog.RayTracer.Vector(this.x / m, this.y / m, this.z / m); 238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block }, 239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block magnitude : function() { 241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return Math.sqrt((this.x * this.x) + (this.y * this.y) + (this.z * this.z)); 242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block }, 243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block cross : function(w) { 245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return new Flog.RayTracer.Vector( 246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block -this.z * w.y + this.y * w.z, 247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block this.z * w.x - this.x * w.z, 248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block -this.y * w.x + this.x * w.y); 249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block }, 250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block dot : function(w) { 252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return this.x * w.x + this.y * w.y + this.z * w.z; 253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block }, 254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block add : function(v, w) { 256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return new Flog.RayTracer.Vector(w.x + v.x, w.y + v.y, w.z + v.z); 257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block }, 258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block subtract : function(v, w) { 260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if(!w || !v) throw 'Vectors must be defined [' + v + ',' + w + ']'; 261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return new Flog.RayTracer.Vector(v.x - w.x, v.y - w.y, v.z - w.z); 262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block }, 263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block multiplyVector : function(v, w) { 265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return new Flog.RayTracer.Vector(v.x * w.x, v.y * w.y, v.z * w.z); 266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block }, 267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block multiplyScalar : function(v, w) { 269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return new Flog.RayTracer.Vector(v.x * w, v.y * w, v.z * w); 270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block }, 271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block toString : function () { 273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 'Vector [' + this.x + ',' + this.y + ',' + this.z + ']'; 274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block/* Fake a Flog.* namespace */ 277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockif(typeof(Flog) == 'undefined') var Flog = {}; 278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockif(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {}; 279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockFlog.RayTracer.Ray = Class.create(); 281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockFlog.RayTracer.Ray.prototype = { 283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block position : null, 284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block direction : null, 285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block initialize : function(pos, dir) { 286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block this.position = pos; 287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block this.direction = dir; 288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block }, 289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block toString : function () { 291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 'Ray [' + this.position + ',' + this.direction + ']'; 292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block/* Fake a Flog.* namespace */ 295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockif(typeof(Flog) == 'undefined') var Flog = {}; 296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockif(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {}; 297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockFlog.RayTracer.Scene = Class.create(); 299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockFlog.RayTracer.Scene.prototype = { 301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block camera : null, 302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block shapes : [], 303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block lights : [], 304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block background : null, 305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block initialize : function() { 307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block this.camera = new Flog.RayTracer.Camera( 308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block new Flog.RayTracer.Vector(0,0,-5), 309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block new Flog.RayTracer.Vector(0,0,1), 310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block new Flog.RayTracer.Vector(0,1,0) 311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ); 312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block this.shapes = new Array(); 313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block this.lights = new Array(); 314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block this.background = new Flog.RayTracer.Background(new Flog.RayTracer.Color(0,0,0.5), 0.2); 315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block/* Fake a Flog.* namespace */ 318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockif(typeof(Flog) == 'undefined') var Flog = {}; 319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockif(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {}; 320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockif(typeof(Flog.RayTracer.Material) == 'undefined') Flog.RayTracer.Material = {}; 321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockFlog.RayTracer.Material.BaseMaterial = Class.create(); 323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockFlog.RayTracer.Material.BaseMaterial.prototype = { 325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block gloss: 2.0, // [0...infinity] 0 = matt 327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block transparency: 0.0, // 0=opaque 328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block reflection: 0.0, // [0...infinity] 0 = no reflection 329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block refraction: 0.50, 330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block hasTexture: false, 331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block initialize : function() { 333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block }, 335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block getColor: function(u, v){ 337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block }, 339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block wrapUp: function(t){ 341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block t = t % 2.0; 342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if(t < -1) t += 2.0; 343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if(t >= 1) t -= 2.0; 344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return t; 345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block }, 346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block toString : function () { 348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 'Material [gloss=' + this.gloss + ', transparency=' + this.transparency + ', hasTexture=' + this.hasTexture +']'; 349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block/* Fake a Flog.* namespace */ 352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockif(typeof(Flog) == 'undefined') var Flog = {}; 353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockif(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {}; 354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockFlog.RayTracer.Material.Solid = Class.create(); 356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockFlog.RayTracer.Material.Solid.prototype = Object.extend( 358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block new Flog.RayTracer.Material.BaseMaterial(), { 359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block initialize : function(color, reflection, refraction, transparency, gloss) { 360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block this.color = color; 361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block this.reflection = reflection; 362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block this.transparency = transparency; 363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block this.gloss = gloss; 364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block this.hasTexture = false; 365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block }, 366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block getColor: function(u, v){ 368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return this.color; 369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block }, 370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block toString : function () { 372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 'SolidMaterial [gloss=' + this.gloss + ', transparency=' + this.transparency + ', hasTexture=' + this.hasTexture +']'; 373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block); 376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block/* Fake a Flog.* namespace */ 377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockif(typeof(Flog) == 'undefined') var Flog = {}; 378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockif(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {}; 379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockFlog.RayTracer.Material.Chessboard = Class.create(); 381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockFlog.RayTracer.Material.Chessboard.prototype = Object.extend( 383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block new Flog.RayTracer.Material.BaseMaterial(), { 384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block colorEven: null, 385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block colorOdd: null, 386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block density: 0.5, 387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block initialize : function(colorEven, colorOdd, reflection, transparency, gloss, density) { 389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block this.colorEven = colorEven; 390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block this.colorOdd = colorOdd; 391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block this.reflection = reflection; 392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block this.transparency = transparency; 393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block this.gloss = gloss; 394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block this.density = density; 395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block this.hasTexture = true; 396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block }, 397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block getColor: function(u, v){ 399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var t = this.wrapUp(u * this.density) * this.wrapUp(v * this.density); 400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if(t < 0.0) 402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return this.colorEven; 403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block else 404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return this.colorOdd; 405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block }, 406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block toString : function () { 408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 'ChessMaterial [gloss=' + this.gloss + ', transparency=' + this.transparency + ', hasTexture=' + this.hasTexture +']'; 409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block); 412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block/* Fake a Flog.* namespace */ 413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockif(typeof(Flog) == 'undefined') var Flog = {}; 414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockif(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {}; 415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockif(typeof(Flog.RayTracer.Shape) == 'undefined') Flog.RayTracer.Shape = {}; 416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockFlog.RayTracer.Shape.Sphere = Class.create(); 418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockFlog.RayTracer.Shape.Sphere.prototype = { 420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block initialize : function(pos, radius, material) { 421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block this.radius = radius; 422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block this.position = pos; 423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block this.material = material; 424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block }, 425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block intersect: function(ray){ 427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var info = new Flog.RayTracer.IntersectionInfo(); 428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block info.shape = this; 429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var dst = Flog.RayTracer.Vector.prototype.subtract(ray.position, this.position); 431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var B = dst.dot(ray.direction); 433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var C = dst.dot(dst) - (this.radius * this.radius); 434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var D = (B * B) - C; 435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if(D > 0){ // intersection! 437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block info.isHit = true; 438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block info.distance = (-B) - Math.sqrt(D); 439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block info.position = Flog.RayTracer.Vector.prototype.add( 440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ray.position, 441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Flog.RayTracer.Vector.prototype.multiplyScalar( 442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ray.direction, 443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block info.distance 444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ) 445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ); 446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block info.normal = Flog.RayTracer.Vector.prototype.subtract( 447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block info.position, 448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block this.position 449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ).normalize(); 450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block info.color = this.material.getColor(0,0); 452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block info.isHit = false; 454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return info; 456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block }, 457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block toString : function () { 459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 'Sphere [position=' + this.position + ', radius=' + this.radius + ']'; 460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block/* Fake a Flog.* namespace */ 463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockif(typeof(Flog) == 'undefined') var Flog = {}; 464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockif(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {}; 465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockif(typeof(Flog.RayTracer.Shape) == 'undefined') Flog.RayTracer.Shape = {}; 466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockFlog.RayTracer.Shape.Plane = Class.create(); 468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockFlog.RayTracer.Shape.Plane.prototype = { 470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block d: 0.0, 471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block initialize : function(pos, d, material) { 473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block this.position = pos; 474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block this.d = d; 475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block this.material = material; 476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block }, 477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block intersect: function(ray){ 479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var info = new Flog.RayTracer.IntersectionInfo(); 480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var Vd = this.position.dot(ray.direction); 482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if(Vd == 0) return info; // no intersection 483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var t = -(this.position.dot(ray.position) + this.d) / Vd; 485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if(t <= 0) return info; 486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block info.shape = this; 488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block info.isHit = true; 489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block info.position = Flog.RayTracer.Vector.prototype.add( 490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ray.position, 491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Flog.RayTracer.Vector.prototype.multiplyScalar( 492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ray.direction, 493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block t 494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ) 495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ); 496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block info.normal = this.position; 497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block info.distance = t; 498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if(this.material.hasTexture){ 500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var vU = new Flog.RayTracer.Vector(this.position.y, this.position.z, -this.position.x); 501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var vV = vU.cross(this.position); 502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var u = info.position.dot(vU); 503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var v = info.position.dot(vV); 504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block info.color = this.material.getColor(u,v); 505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block info.color = this.material.getColor(0,0); 507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return info; 510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block }, 511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block toString : function () { 513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 'Plane [' + this.position + ', d=' + this.d + ']'; 514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block/* Fake a Flog.* namespace */ 517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockif(typeof(Flog) == 'undefined') var Flog = {}; 518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockif(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {}; 519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockFlog.RayTracer.IntersectionInfo = Class.create(); 521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockFlog.RayTracer.IntersectionInfo.prototype = { 523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block isHit: false, 524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block hitCount: 0, 525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block shape: null, 526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block position: null, 527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block normal: null, 528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block color: null, 529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block distance: null, 530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block initialize : function() { 532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block this.color = new Flog.RayTracer.Color(0,0,0); 533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block }, 534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block toString : function () { 536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 'Intersection [' + this.position + ']'; 537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block/* Fake a Flog.* namespace */ 540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockif(typeof(Flog) == 'undefined') var Flog = {}; 541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockif(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {}; 542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockFlog.RayTracer.Camera = Class.create(); 544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockFlog.RayTracer.Camera.prototype = { 546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block position: null, 547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block lookAt: null, 548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block equator: null, 549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block up: null, 550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block screen: null, 551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block initialize : function(pos, lookAt, up) { 553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block this.position = pos; 554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block this.lookAt = lookAt; 555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block this.up = up; 556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block this.equator = lookAt.normalize().cross(this.up); 557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block this.screen = Flog.RayTracer.Vector.prototype.add(this.position, this.lookAt); 558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block }, 559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block getRay: function(vx, vy){ 561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var pos = Flog.RayTracer.Vector.prototype.subtract( 562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block this.screen, 563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Flog.RayTracer.Vector.prototype.subtract( 564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Flog.RayTracer.Vector.prototype.multiplyScalar(this.equator, vx), 565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Flog.RayTracer.Vector.prototype.multiplyScalar(this.up, vy) 566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ) 567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ); 568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pos.y = pos.y * -1; 569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var dir = Flog.RayTracer.Vector.prototype.subtract( 570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pos, 571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block this.position 572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ); 573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var ray = new Flog.RayTracer.Ray(pos, dir.normalize()); 575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return ray; 577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block }, 578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block toString : function () { 580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 'Ray []'; 581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block/* Fake a Flog.* namespace */ 584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockif(typeof(Flog) == 'undefined') var Flog = {}; 585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockif(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {}; 586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockFlog.RayTracer.Background = Class.create(); 588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockFlog.RayTracer.Background.prototype = { 590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block color : null, 591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ambience : 0.0, 592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block initialize : function(color, ambience) { 594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block this.color = color; 595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block this.ambience = ambience; 596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block/* Fake a Flog.* namespace */ 599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockif(typeof(Flog) == 'undefined') var Flog = {}; 600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockif(typeof(Flog.RayTracer) == 'undefined') Flog.RayTracer = {}; 601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockFlog.RayTracer.Engine = Class.create(); 603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockFlog.RayTracer.Engine.prototype = { 605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block canvas: null, /* 2d context we can render to */ 606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block initialize: function(options){ 608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block this.options = Object.extend({ 609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block canvasHeight: 100, 610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block canvasWidth: 100, 611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pixelWidth: 2, 612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pixelHeight: 2, 613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block renderDiffuse: false, 614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block renderShadows: false, 615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block renderHighlights: false, 616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block renderReflections: false, 617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block rayDepth: 2 618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block }, options || {}); 619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block this.options.canvasHeight /= this.options.pixelHeight; 621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block this.options.canvasWidth /= this.options.pixelWidth; 622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block /* TODO: dynamically include other scripts */ 624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block }, 625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block setPixel: function(x, y, color){ 627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var pxW, pxH; 628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pxW = this.options.pixelWidth; 629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pxH = this.options.pixelHeight; 630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (this.canvas) { 632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block this.canvas.fillStyle = color.toString(); 633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block this.canvas.fillRect (x * pxW, y * pxH, pxW, pxH); 634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (x === y) { 636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block checkNumber += color.brightness(); 637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // print(x * pxW, y * pxH, pxW, pxH); 639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block }, 641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block renderScene: function(scene, canvas){ 643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block checkNumber = 0; 644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block /* Get canvas */ 645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (canvas) { 646a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block this.canvas = canvas.getContext("2d"); 647a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 648a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block this.canvas = null; 649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 650a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var canvasHeight = this.options.canvasHeight; 652a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var canvasWidth = this.options.canvasWidth; 653a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 654a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for(var y=0; y < canvasHeight; y++){ 655a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for(var x=0; x < canvasWidth; x++){ 656a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var yp = y * 1.0 / canvasHeight * 2 - 1; 657a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var xp = x * 1.0 / canvasWidth * 2 - 1; 658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 659a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var ray = scene.camera.getRay(xp, yp); 660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var color = this.getPixelColor(ray, scene); 662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 663a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block this.setPixel(x, y, color); 664a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 665a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 666a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (checkNumber !== 2321) { 667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block throw new Error("Scene rendered incorrectly"); 668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 669a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block }, 670a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block getPixelColor: function(ray, scene){ 672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var info = this.testIntersection(ray, scene, null); 673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if(info.isHit){ 674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var color = this.rayTrace(info, ray, scene, 0); 675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return color; 676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 677a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return scene.background.color; 678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block }, 679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block testIntersection: function(ray, scene, exclude){ 681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var hits = 0; 682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var best = new Flog.RayTracer.IntersectionInfo(); 683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block best.distance = 2000; 684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for(var i=0; i<scene.shapes.length; i++){ 686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var shape = scene.shapes[i]; 687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if(shape != exclude){ 689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var info = shape.intersect(ray); 690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if(info.isHit && info.distance >= 0 && info.distance < best.distance){ 691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block best = info; 692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block hits++; 693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block best.hitCount = hits; 697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return best; 698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block }, 699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block getReflectionRay: function(P,N,V){ 701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var c1 = -N.dot(V); 702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var R1 = Flog.RayTracer.Vector.prototype.add( 703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Flog.RayTracer.Vector.prototype.multiplyScalar(N, 2*c1), 704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block V 705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ); 706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return new Flog.RayTracer.Ray(P, R1); 707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block }, 708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block rayTrace: function(info, ray, scene, depth){ 710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Calc ambient 711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var color = Flog.RayTracer.Color.prototype.multiplyScalar(info.color, scene.background.ambience); 712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var oldColor = color; 713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var shininess = Math.pow(10, info.shape.material.gloss + 1); 714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for(var i=0; i<scene.lights.length; i++){ 716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var light = scene.lights[i]; 717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Calc diffuse lighting 719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var v = Flog.RayTracer.Vector.prototype.subtract( 720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block light.position, 721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block info.position 722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ).normalize(); 723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if(this.options.renderDiffuse){ 725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var L = v.dot(info.normal); 726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if(L > 0.0){ 727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block color = Flog.RayTracer.Color.prototype.add( 728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block color, 729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Flog.RayTracer.Color.prototype.multiply( 730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block info.color, 731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Flog.RayTracer.Color.prototype.multiplyScalar( 732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block light.color, 733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block L 734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ) 735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ) 736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ); 737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The greater the depth the more accurate the colours, but 741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // this is exponentially (!) expensive 742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if(depth <= this.options.rayDepth){ 743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // calculate reflection ray 744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if(this.options.renderReflections && info.shape.material.reflection > 0) 745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var reflectionRay = this.getReflectionRay(info.position, info.normal, ray.direction); 747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var refl = this.testIntersection(reflectionRay, scene, info.shape); 748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (refl.isHit && refl.distance > 0){ 750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block refl.color = this.rayTrace(refl, reflectionRay, scene, depth + 1); 751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block refl.color = scene.background.color; 753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block color = Flog.RayTracer.Color.prototype.blend( 756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block color, 757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block refl.color, 758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block info.shape.material.reflection 759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ); 760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Refraction 763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block /* TODO */ 764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block /* Render shadows and highlights */ 767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var shadowInfo = new Flog.RayTracer.IntersectionInfo(); 769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if(this.options.renderShadows){ 771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var shadowRay = new Flog.RayTracer.Ray(info.position, v); 772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block shadowInfo = this.testIntersection(shadowRay, scene, info.shape); 774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if(shadowInfo.isHit && shadowInfo.shape != info.shape /*&& shadowInfo.shape.type != 'PLANE'*/){ 775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var vA = Flog.RayTracer.Color.prototype.multiplyScalar(color, 0.5); 776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var dB = (0.5 * Math.pow(shadowInfo.shape.material.transparency, 0.5)); 777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block color = Flog.RayTracer.Color.prototype.addScalar(vA,dB); 778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Phong specular highlights 782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if(this.options.renderHighlights && !shadowInfo.isHit && info.shape.material.gloss > 0){ 783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var Lv = Flog.RayTracer.Vector.prototype.subtract( 784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block info.shape.position, 785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block light.position 786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ).normalize(); 787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var E = Flog.RayTracer.Vector.prototype.subtract( 789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block scene.camera.position, 790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block info.shape.position 791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ).normalize(); 792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var H = Flog.RayTracer.Vector.prototype.subtract( 794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block E, 795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Lv 796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ).normalize(); 797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var glossWeight = Math.pow(Math.max(info.normal.dot(H), 0), shininess); 799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block color = Flog.RayTracer.Color.prototype.add( 800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Flog.RayTracer.Color.prototype.multiplyScalar(light.color, glossWeight), 801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block color 802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ); 803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block color.limit(); 806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return color; 807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockfunction renderScene(){ 812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var scene = new Flog.RayTracer.Scene(); 813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block scene.camera = new Flog.RayTracer.Camera( 815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block new Flog.RayTracer.Vector(0, 0, -15), 816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block new Flog.RayTracer.Vector(-0.2, 0, 5), 817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block new Flog.RayTracer.Vector(0, 1, 0) 818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ); 819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block scene.background = new Flog.RayTracer.Background( 821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block new Flog.RayTracer.Color(0.5, 0.5, 0.5), 822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 0.4 823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ); 824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var sphere = new Flog.RayTracer.Shape.Sphere( 826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block new Flog.RayTracer.Vector(-1.5, 1.5, 2), 827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1.5, 828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block new Flog.RayTracer.Material.Solid( 829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block new Flog.RayTracer.Color(0,0.5,0.5), 830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 0.3, 831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 0.0, 832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 0.0, 833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2.0 834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ) 835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ); 836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var sphere1 = new Flog.RayTracer.Shape.Sphere( 838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block new Flog.RayTracer.Vector(1, 0.25, 1), 839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 0.5, 840a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block new Flog.RayTracer.Material.Solid( 841a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block new Flog.RayTracer.Color(0.9,0.9,0.9), 842a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 0.1, 843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 0.0, 844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 0.0, 845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1.5 846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ) 847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ); 848a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var plane = new Flog.RayTracer.Shape.Plane( 850a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block new Flog.RayTracer.Vector(0.1, 0.9, -0.5).normalize(), 851a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1.2, 852a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block new Flog.RayTracer.Material.Chessboard( 853a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block new Flog.RayTracer.Color(1,1,1), 854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block new Flog.RayTracer.Color(0,0,0), 855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 0.2, 856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 0.0, 857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1.0, 858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 0.7 859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ) 860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ); 861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block scene.shapes.push(plane); 863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block scene.shapes.push(sphere); 864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block scene.shapes.push(sphere1); 865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var light = new Flog.RayTracer.Light( 867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block new Flog.RayTracer.Vector(5, 10, -1), 868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block new Flog.RayTracer.Color(0.8, 0.8, 0.8) 869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ); 870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var light1 = new Flog.RayTracer.Light( 872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block new Flog.RayTracer.Vector(-3, 5, -15), 873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block new Flog.RayTracer.Color(0.8, 0.8, 0.8), 874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 100 875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ); 876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block scene.lights.push(light); 878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block scene.lights.push(light1); 879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var imageWidth = 100; // $F('imageWidth'); 881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var imageHeight = 100; // $F('imageHeight'); 882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var pixelSize = "5,5".split(','); // $F('pixelSize').split(','); 883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var renderDiffuse = true; // $F('renderDiffuse'); 884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var renderShadows = true; // $F('renderShadows'); 885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var renderHighlights = true; // $F('renderHighlights'); 886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var renderReflections = true; // $F('renderReflections'); 887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var rayDepth = 2;//$F('rayDepth'); 888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block var raytracer = new Flog.RayTracer.Engine( 890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block { 891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block canvasWidth: imageWidth, 892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block canvasHeight: imageHeight, 893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pixelWidth: pixelSize[0], 894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block pixelHeight: pixelSize[1], 895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "renderDiffuse": renderDiffuse, 896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "renderHighlights": renderHighlights, 897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "renderShadows": renderShadows, 898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "renderReflections": renderReflections, 899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block "rayDepth": rayDepth 900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ); 902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block raytracer.renderScene(scene, null, 0); 904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 905