15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/* 25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2007 Apple Inc. All rights reserved. 35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Redistribution and use in source and binary forms, with or without 55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modification, are permitted provided that the following conditions 65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * are met: 75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 1. Redistributions of source code must retain the above copyright 85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * notice, this list of conditions and the following disclaimer. 95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 2. Redistributions in binary form must reproduce the above copyright 105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * notice, this list of conditions and the following disclaimer in the 115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * documentation and/or other materials provided with the distribution. 125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */ 255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function createVector(x,y,z) { 275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return new Array(x,y,z); 285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function sqrLengthVector(self) { 315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return self[0] * self[0] + self[1] * self[1] + self[2] * self[2]; 325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function lengthVector(self) { 355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return Math.sqrt(self[0] * self[0] + self[1] * self[1] + self[2] * self[2]); 365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function addVector(self, v) { 395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self[0] += v[0]; 405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self[1] += v[1]; 415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self[2] += v[2]; 425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return self; 435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function subVector(self, v) { 465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self[0] -= v[0]; 475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self[1] -= v[1]; 485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self[2] -= v[2]; 495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return self; 505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function scaleVector(self, scale) { 535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self[0] *= scale; 545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self[1] *= scale; 555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self[2] *= scale; 565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return self; 575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function normaliseVector(self) { 605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var len = Math.sqrt(self[0] * self[0] + self[1] * self[1] + self[2] * self[2]); 615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self[0] /= len; 625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self[1] /= len; 635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self[2] /= len; 645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return self; 655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function add(v1, v2) { 685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return new Array(v1[0] + v2[0], v1[1] + v2[1], v1[2] + v2[2]); 695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function sub(v1, v2) { 725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return new Array(v1[0] - v2[0], v1[1] - v2[1], v1[2] - v2[2]); 735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function scalev(v1, v2) { 765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return new Array(v1[0] * v2[0], v1[1] * v2[1], v1[2] * v2[2]); 775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function dot(v1, v2) { 805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2]; 815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function scale(v, scale) { 845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return [v[0] * scale, v[1] * scale, v[2] * scale]; 855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function cross(v1, v2) { 885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return [v1[1] * v2[2] - v1[2] * v2[1], 895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) v1[2] * v2[0] - v1[0] * v2[2], 905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) v1[0] * v2[1] - v1[1] * v2[0]]; 915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function normalise(v) { 955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var len = lengthVector(v); 965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return [v[0] / len, v[1] / len, v[2] / len]; 975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function transformMatrix(self, v) { 1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var vals = self; 1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var x = vals[0] * v[0] + vals[1] * v[1] + vals[2] * v[2] + vals[3]; 1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var y = vals[4] * v[0] + vals[5] * v[1] + vals[6] * v[2] + vals[7]; 1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var z = vals[8] * v[0] + vals[9] * v[1] + vals[10] * v[2] + vals[11]; 1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return [x, y, z]; 1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function invertMatrix(self) { 1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var temp = new Array(16); 1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var tx = -self[3]; 1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var ty = -self[7]; 1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var tz = -self[11]; 1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (h = 0; h < 3; h++) 1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (v = 0; v < 3; v++) 1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) temp[h + v * 4] = self[v + h * 4]; 1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (i = 0; i < 11; i++) 1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self[i] = temp[i]; 1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self[3] = tx * self[0] + ty * self[1] + tz * self[2]; 1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self[7] = tx * self[4] + ty * self[5] + tz * self[6]; 1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) self[11] = tx * self[8] + ty * self[9] + tz * self[10]; 1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return self; 1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Triangle intersection using barycentric coord method 1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function Triangle(p1, p2, p3) { 1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var edge1 = sub(p3, p1); 1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var edge2 = sub(p2, p1); 1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var normal = cross(edge1, edge2); 1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (Math.abs(normal[0]) > Math.abs(normal[1])) 1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (Math.abs(normal[0]) > Math.abs(normal[2])) 1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) this.axis = 0; 1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else 1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) this.axis = 2; 1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else 1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (Math.abs(normal[1]) > Math.abs(normal[2])) 1365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) this.axis = 1; 1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else 1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) this.axis = 2; 1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var u = (this.axis + 1) % 3; 1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var v = (this.axis + 2) % 3; 1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var u1 = edge1[u]; 1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var v1 = edge1[v]; 1435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var u2 = edge2[u]; 1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var v2 = edge2[v]; 1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) this.normal = normalise(normal); 1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) this.nu = normal[u] / normal[this.axis]; 1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) this.nv = normal[v] / normal[this.axis]; 1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) this.nd = dot(normal, p1) / normal[this.axis]; 1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var det = u1 * v2 - v1 * u2; 1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) this.eu = p1[u]; 1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) this.ev = p1[v]; 1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) this.nu1 = u1 / det; 1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) this.nv1 = -v1 / det; 1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) this.nu2 = v2 / det; 1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) this.nv2 = -u2 / det; 1575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) this.material = [0.7, 0.7, 0.7]; 1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Triangle.prototype.intersect = function(orig, dir, near, far) { 1615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var u = (this.axis + 1) % 3; 1625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var v = (this.axis + 2) % 3; 1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var d = dir[this.axis] + this.nu * dir[u] + this.nv * dir[v]; 1645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var t = (this.nd - orig[this.axis] - this.nu * orig[u] - this.nv * orig[v]) / d; 1655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (t < near || t > far) 1665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return null; 1675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var Pu = orig[u] + t * dir[u] - this.eu; 1685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var Pv = orig[v] + t * dir[v] - this.ev; 1695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var a2 = Pv * this.nu1 + Pu * this.nv1; 1705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (a2 < 0) 1715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return null; 1725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var a3 = Pu * this.nu2 + Pv * this.nv2; 1735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (a3 < 0) 1745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return null; 1755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if ((a2 + a3) > 1) 1775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return null; 1785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return t; 1795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function Scene(a_triangles) { 1825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) this.triangles = a_triangles; 1835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) this.lights = []; 1845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) this.ambient = [0,0,0]; 1855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) this.background = [0.8,0.8,1]; 1865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)var zero = new Array(0,0,0); 1885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Scene.prototype.intersect = function(origin, dir, near, far) { 1905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var closest = null; 1915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (i = 0; i < this.triangles.length; i++) { 1925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var triangle = this.triangles[i]; 1935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var d = triangle.intersect(origin, dir, near, far); 1945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (d == null || d > far || d < near) 1955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) continue; 1965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) far = d; 1975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) closest = triangle; 1985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!closest) 2015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return [this.background[0],this.background[1],this.background[2]]; 2025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var normal = closest.normal; 2045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var hit = add(origin, scale(dir, far)); 2055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (dot(dir, normal) > 0) 2065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) normal = [-normal[0], -normal[1], -normal[2]]; 2075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var colour = null; 2095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (closest.shader) { 2105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) colour = closest.shader(closest, hit, dir); 2115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else { 2125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) colour = closest.material; 2135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // do reflection 2165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var reflected = null; 2175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (colour.reflection > 0.001) { 2185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var reflection = addVector(scale(normal, -2*dot(dir, normal)), dir); 2195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) reflected = this.intersect(hit, reflection, 0.0001, 1000000); 2205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (colour.reflection >= 0.999999) 2215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return reflected; 2225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var l = [this.ambient[0], this.ambient[1], this.ambient[2]]; 2255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var i = 0; i < this.lights.length; i++) { 2265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var light = this.lights[i]; 2275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var toLight = sub(light, hit); 2285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var distance = lengthVector(toLight); 2295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) scaleVector(toLight, 1.0/distance); 2305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) distance -= 0.0001; 2315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (this.blocked(hit, toLight, distance)) 2325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) continue; 2335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var nl = dot(normal, toLight); 2345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (nl > 0) 2355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) addVector(l, scale(light.colour, nl)); 2365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) l = scalev(l, colour); 2385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (reflected) { 2395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) l = addVector(scaleVector(l, 1 - colour.reflection), scaleVector(reflected, colour.reflection)); 2405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return l; 2425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Scene.prototype.blocked = function(O, D, far) { 2455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var near = 0.0001; 2465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var closest = null; 2475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (i = 0; i < this.triangles.length; i++) { 2485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var triangle = this.triangles[i]; 2495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var d = triangle.intersect(O, D, near, far); 2505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (d == null || d > far || d < near) 2515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) continue; 2525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return true; 2535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 2565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// this camera code is from notes i made ages ago, it is from *somewhere* -- i cannot remember where 2605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// that somewhere is 2615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function Camera(origin, lookat, up) { 2625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var zaxis = normaliseVector(subVector(lookat, origin)); 2635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var xaxis = normaliseVector(cross(up, zaxis)); 2645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var yaxis = normaliseVector(cross(xaxis, subVector([0,0,0], zaxis))); 2655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var m = new Array(16); 2665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m[0] = xaxis[0]; m[1] = xaxis[1]; m[2] = xaxis[2]; 2675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m[4] = yaxis[0]; m[5] = yaxis[1]; m[6] = yaxis[2]; 2685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m[8] = zaxis[0]; m[9] = zaxis[1]; m[10] = zaxis[2]; 2695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) invertMatrix(m); 2705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m[3] = 0; m[7] = 0; m[11] = 0; 2715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) this.origin = origin; 2725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) this.directions = new Array(4); 2735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) this.directions[0] = normalise([-0.7, 0.7, 1]); 2745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) this.directions[1] = normalise([ 0.7, 0.7, 1]); 2755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) this.directions[2] = normalise([ 0.7, -0.7, 1]); 2765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) this.directions[3] = normalise([-0.7, -0.7, 1]); 2775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) this.directions[0] = transformMatrix(m, this.directions[0]); 2785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) this.directions[1] = transformMatrix(m, this.directions[1]); 2795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) this.directions[2] = transformMatrix(m, this.directions[2]); 2805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) this.directions[3] = transformMatrix(m, this.directions[3]); 2815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Camera.prototype.generateRayPair = function(y) { 2845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) rays = new Array(new Object(), new Object()); 2855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) rays[0].origin = this.origin; 2865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) rays[1].origin = this.origin; 2875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) rays[0].dir = addVector(scale(this.directions[0], y), scale(this.directions[3], 1 - y)); 2885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) rays[1].dir = addVector(scale(this.directions[1], y), scale(this.directions[2], 1 - y)); 2895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return rays; 2905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function renderRows(camera, scene, pixels, width, height, starty, stopy) { 2935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var y = starty; y < stopy; y++) { 2945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var rays = camera.generateRayPair(y / height); 2955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var x = 0; x < width; x++) { 2965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var xp = x / width; 2975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var origin = addVector(scale(rays[0].origin, xp), scale(rays[1].origin, 1 - xp)); 2985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var dir = normaliseVector(addVector(scale(rays[0].dir, xp), scale(rays[1].dir, 1 - xp))); 2995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var l = scene.intersect(origin, dir); 3005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) pixels[y][x] = l; 3015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 3045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)Camera.prototype.render = function(scene, pixels, width, height) { 3065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var cam = this; 3075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var row = 0; 3085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) renderRows(cam, scene, pixels, width, height, 0, height); 3095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 3105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function raytraceScene() 3145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 3155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var startDate = new Date().getTime(); 3165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var numTriangles = 2 * 6; 3175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var triangles = new Array();//numTriangles); 3185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var tfl = createVector(-10, 10, -10); 3195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var tfr = createVector( 10, 10, -10); 3205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var tbl = createVector(-10, 10, 10); 3215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var tbr = createVector( 10, 10, 10); 3225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var bfl = createVector(-10, -10, -10); 3235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var bfr = createVector( 10, -10, -10); 3245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var bbl = createVector(-10, -10, 10); 3255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var bbr = createVector( 10, -10, 10); 3265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // cube!!! 3285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // front 3295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var i = 0; 3305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) triangles[i++] = new Triangle(tfl, tfr, bfr); 3325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) triangles[i++] = new Triangle(tfl, bfr, bfl); 3335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // back 3345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) triangles[i++] = new Triangle(tbl, tbr, bbr); 3355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) triangles[i++] = new Triangle(tbl, bbr, bbl); 3365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // triangles[i-1].material = [0.7,0.2,0.2]; 3375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // triangles[i-1].material.reflection = 0.8; 3385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // left 3395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) triangles[i++] = new Triangle(tbl, tfl, bbl); 3405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // triangles[i-1].reflection = 0.6; 3415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) triangles[i++] = new Triangle(tfl, bfl, bbl); 3425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // triangles[i-1].reflection = 0.6; 3435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // right 3445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) triangles[i++] = new Triangle(tbr, tfr, bbr); 3455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) triangles[i++] = new Triangle(tfr, bfr, bbr); 3465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // top 3475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) triangles[i++] = new Triangle(tbl, tbr, tfr); 3485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) triangles[i++] = new Triangle(tbl, tfr, tfl); 3495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // bottom 3505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) triangles[i++] = new Triangle(bbl, bbr, bfr); 3515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) triangles[i++] = new Triangle(bbl, bfr, bfl); 3525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) //Floor!!!! 3545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var green = createVector(0.0, 0.4, 0.0); 3555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var grey = createVector(0.4, 0.4, 0.4); 3565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) grey.reflection = 1.0; 3575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var floorShader = function(tri, pos, view) { 3585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var x = ((pos[0]/32) % 2 + 2) % 2; 3595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var z = ((pos[2]/32 + 0.3) % 2 + 2) % 2; 3605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (x < 1 != z < 1) { 3615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) //in the real world we use the fresnel term... 3625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // var angle = 1-dot(view, tri.normal); 3635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // angle *= angle; 3645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // angle *= angle; 3655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // angle *= angle; 3665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) //grey.reflection = angle; 3675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return grey; 3685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else 3695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return green; 3705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var ffl = createVector(-1000, -30, -1000); 3725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var ffr = createVector( 1000, -30, -1000); 3735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var fbl = createVector(-1000, -30, 1000); 3745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var fbr = createVector( 1000, -30, 1000); 3755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) triangles[i++] = new Triangle(fbl, fbr, ffr); 3765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) triangles[i-1].shader = floorShader; 3775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) triangles[i++] = new Triangle(fbl, ffr, ffl); 3785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) triangles[i-1].shader = floorShader; 3795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var _scene = new Scene(triangles); 3815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) _scene.lights[0] = createVector(20, 38, -22); 3825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) _scene.lights[0].colour = createVector(0.7, 0.3, 0.3); 3835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) _scene.lights[1] = createVector(-23, 40, 17); 3845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) _scene.lights[1].colour = createVector(0.7, 0.3, 0.3); 3855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) _scene.lights[2] = createVector(23, 20, 17); 3865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) _scene.lights[2].colour = createVector(0.7, 0.7, 0.7); 3875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) _scene.ambient = createVector(0.1, 0.1, 0.1); 3885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // _scene.background = createVector(0.7, 0.7, 1.0); 3895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var size = 30; 3915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var pixels = new Array(); 3925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var y = 0; y < size; y++) { 3935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) pixels[y] = new Array(); 3945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var x = 0; x < size; x++) { 3955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) pixels[y][x] = 0; 3965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var _camera = new Camera(createVector(-40, 40, 40), createVector(0, 0, 0), createVector(0, 1, 0)); 4005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) _camera.render(_scene, pixels, size, size); 4015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return pixels; 4035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 4045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)function arrayToCanvasCommands(pixels) 4065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 4075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var s = '<canvas id="renderCanvas" width="30px" height="30px"></canvas><scr' + 'ipt>\nvar pixels = ['; 4085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var size = 30; 4095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var y = 0; y < size; y++) { 4105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) s += "["; 4115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var x = 0; x < size; x++) { 4125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) s += "[" + pixels[y][x] + "],"; 4135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 4145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) s+= "],"; 4155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 4165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) s += '];\n var canvas = document.getElementById("renderCanvas").getContext("2d");\n\ 4175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)\n\ 4185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)\n\ 4195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var size = 30;\n\ 4205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) canvas.fillStyle = "red";\n\ 4215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) canvas.fillRect(0, 0, size, size);\n\ 4225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) canvas.scale(1, -1);\n\ 4235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) canvas.translate(0, -size);\n\ 4245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)\n\ 4255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!canvas.setFillColor)\n\ 4265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) canvas.setFillColor = function(r, g, b, a) {\n\ 4275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) this.fillStyle = "rgb("+[Math.floor(r * 255), Math.floor(g * 255), Math.floor(b * 255)]+")";\n\ 4285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }\n\ 4295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)\n\ 4305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)for (var y = 0; y < size; y++) {\n\ 4315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (var x = 0; x < size; x++) {\n\ 4325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) var l = pixels[y][x];\n\ 4335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) canvas.setFillColor(l[0], l[1], l[2], 1);\n\ 4345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) canvas.fillRect(x, y, 1, 1);\n\ 4355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }\n\ 4365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}</scr' + 'ipt>'; 4375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return s; 4395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 4405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)testOutput = arrayToCanvasCommands(raytraceScene()); 442