1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/build/pgo/js-input/3d-raytrace.html Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,490 @@ 1.4 +<!DOCTYPE html> 1.5 +<head> 1.6 +<!-- 1.7 + Copyright (C) 2007 Apple Inc. All rights reserved. 1.8 + 1.9 + Redistribution and use in source and binary forms, with or without 1.10 + modification, are permitted provided that the following conditions 1.11 + are met: 1.12 + 1. Redistributions of source code must retain the above copyright 1.13 + notice, this list of conditions and the following disclaimer. 1.14 + 2. Redistributions in binary form must reproduce the above copyright 1.15 + notice, this list of conditions and the following disclaimer in the 1.16 + documentation and/or other materials provided with the distribution. 1.17 + 1.18 + THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 1.19 + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1.20 + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 1.21 + PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 1.22 + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 1.23 + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 1.24 + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 1.25 + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 1.26 + OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 1.27 + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 1.28 + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 1.29 +--> 1.30 + 1.31 +<title>SunSpider 3d-raytrace</title> 1.32 +</head> 1.33 + 1.34 +<body> 1.35 +<h3>3d-raytrace</h3> 1.36 +<div id="console"> 1.37 +</div> 1.38 + 1.39 +<script> 1.40 + 1.41 +var _sunSpiderStartDate = new Date(); 1.42 + 1.43 +/* 1.44 + * Copyright (C) 2007 Apple Inc. All rights reserved. 1.45 + * 1.46 + * Redistribution and use in source and binary forms, with or without 1.47 + * modification, are permitted provided that the following conditions 1.48 + * are met: 1.49 + * 1. Redistributions of source code must retain the above copyright 1.50 + * notice, this list of conditions and the following disclaimer. 1.51 + * 2. Redistributions in binary form must reproduce the above copyright 1.52 + * notice, this list of conditions and the following disclaimer in the 1.53 + * documentation and/or other materials provided with the distribution. 1.54 + * 1.55 + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 1.56 + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1.57 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 1.58 + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 1.59 + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 1.60 + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 1.61 + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 1.62 + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 1.63 + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 1.64 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 1.65 + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 1.66 + */ 1.67 + 1.68 +function createVector(x,y,z) { 1.69 + return new Array(x,y,z); 1.70 +} 1.71 + 1.72 +function sqrLengthVector(self) { 1.73 + return self[0] * self[0] + self[1] * self[1] + self[2] * self[2]; 1.74 +} 1.75 + 1.76 +function lengthVector(self) { 1.77 + return Math.sqrt(self[0] * self[0] + self[1] * self[1] + self[2] * self[2]); 1.78 +} 1.79 + 1.80 +function addVector(self, v) { 1.81 + self[0] += v[0]; 1.82 + self[1] += v[1]; 1.83 + self[2] += v[2]; 1.84 + return self; 1.85 +} 1.86 + 1.87 +function subVector(self, v) { 1.88 + self[0] -= v[0]; 1.89 + self[1] -= v[1]; 1.90 + self[2] -= v[2]; 1.91 + return self; 1.92 +} 1.93 + 1.94 +function scaleVector(self, scale) { 1.95 + self[0] *= scale; 1.96 + self[1] *= scale; 1.97 + self[2] *= scale; 1.98 + return self; 1.99 +} 1.100 + 1.101 +function normaliseVector(self) { 1.102 + var len = Math.sqrt(self[0] * self[0] + self[1] * self[1] + self[2] * self[2]); 1.103 + self[0] /= len; 1.104 + self[1] /= len; 1.105 + self[2] /= len; 1.106 + return self; 1.107 +} 1.108 + 1.109 +function add(v1, v2) { 1.110 + return new Array(v1[0] + v2[0], v1[1] + v2[1], v1[2] + v2[2]); 1.111 +} 1.112 + 1.113 +function sub(v1, v2) { 1.114 + return new Array(v1[0] - v2[0], v1[1] - v2[1], v1[2] - v2[2]); 1.115 +} 1.116 + 1.117 +function scalev(v1, v2) { 1.118 + return new Array(v1[0] * v2[0], v1[1] * v2[1], v1[2] * v2[2]); 1.119 +} 1.120 + 1.121 +function dot(v1, v2) { 1.122 + return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2]; 1.123 +} 1.124 + 1.125 +function scale(v, scale) { 1.126 + return [v[0] * scale, v[1] * scale, v[2] * scale]; 1.127 +} 1.128 + 1.129 +function cross(v1, v2) { 1.130 + return [v1[1] * v2[2] - v1[2] * v2[1], 1.131 + v1[2] * v2[0] - v1[0] * v2[2], 1.132 + v1[0] * v2[1] - v1[1] * v2[0]]; 1.133 + 1.134 +} 1.135 + 1.136 +function normalise(v) { 1.137 + var len = lengthVector(v); 1.138 + return [v[0] / len, v[1] / len, v[2] / len]; 1.139 +} 1.140 + 1.141 +function transformMatrix(self, v) { 1.142 + var vals = self; 1.143 + var x = vals[0] * v[0] + vals[1] * v[1] + vals[2] * v[2] + vals[3]; 1.144 + var y = vals[4] * v[0] + vals[5] * v[1] + vals[6] * v[2] + vals[7]; 1.145 + var z = vals[8] * v[0] + vals[9] * v[1] + vals[10] * v[2] + vals[11]; 1.146 + return [x, y, z]; 1.147 +} 1.148 + 1.149 +function invertMatrix(self) { 1.150 + var temp = new Array(16); 1.151 + var tx = -self[3]; 1.152 + var ty = -self[7]; 1.153 + var tz = -self[11]; 1.154 + for (h = 0; h < 3; h++) 1.155 + for (v = 0; v < 3; v++) 1.156 + temp[h + v * 4] = self[v + h * 4]; 1.157 + for (i = 0; i < 11; i++) 1.158 + self[i] = temp[i]; 1.159 + self[3] = tx * self[0] + ty * self[1] + tz * self[2]; 1.160 + self[7] = tx * self[4] + ty * self[5] + tz * self[6]; 1.161 + self[11] = tx * self[8] + ty * self[9] + tz * self[10]; 1.162 + return self; 1.163 +} 1.164 + 1.165 + 1.166 +// Triangle intersection using barycentric coord method 1.167 +function Triangle(p1, p2, p3) { 1.168 + var edge1 = sub(p3, p1); 1.169 + var edge2 = sub(p2, p1); 1.170 + var normal = cross(edge1, edge2); 1.171 + if (Math.abs(normal[0]) > Math.abs(normal[1])) 1.172 + if (Math.abs(normal[0]) > Math.abs(normal[2])) 1.173 + this.axis = 0; 1.174 + else 1.175 + this.axis = 2; 1.176 + else 1.177 + if (Math.abs(normal[1]) > Math.abs(normal[2])) 1.178 + this.axis = 1; 1.179 + else 1.180 + this.axis = 2; 1.181 + var u = (this.axis + 1) % 3; 1.182 + var v = (this.axis + 2) % 3; 1.183 + var u1 = edge1[u]; 1.184 + var v1 = edge1[v]; 1.185 + 1.186 + var u2 = edge2[u]; 1.187 + var v2 = edge2[v]; 1.188 + this.normal = normalise(normal); 1.189 + this.nu = normal[u] / normal[this.axis]; 1.190 + this.nv = normal[v] / normal[this.axis]; 1.191 + this.nd = dot(normal, p1) / normal[this.axis]; 1.192 + var det = u1 * v2 - v1 * u2; 1.193 + this.eu = p1[u]; 1.194 + this.ev = p1[v]; 1.195 + this.nu1 = u1 / det; 1.196 + this.nv1 = -v1 / det; 1.197 + this.nu2 = v2 / det; 1.198 + this.nv2 = -u2 / det; 1.199 + this.material = [0.7, 0.7, 0.7]; 1.200 +} 1.201 + 1.202 +Triangle.prototype.intersect = function(orig, dir, near, far) { 1.203 + var u = (this.axis + 1) % 3; 1.204 + var v = (this.axis + 2) % 3; 1.205 + var d = dir[this.axis] + this.nu * dir[u] + this.nv * dir[v]; 1.206 + var t = (this.nd - orig[this.axis] - this.nu * orig[u] - this.nv * orig[v]) / d; 1.207 + if (t < near || t > far) 1.208 + return null; 1.209 + var Pu = orig[u] + t * dir[u] - this.eu; 1.210 + var Pv = orig[v] + t * dir[v] - this.ev; 1.211 + var a2 = Pv * this.nu1 + Pu * this.nv1; 1.212 + if (a2 < 0) 1.213 + return null; 1.214 + var a3 = Pu * this.nu2 + Pv * this.nv2; 1.215 + if (a3 < 0) 1.216 + return null; 1.217 + 1.218 + if ((a2 + a3) > 1) 1.219 + return null; 1.220 + return t; 1.221 +} 1.222 + 1.223 +function Scene(a_triangles) { 1.224 + this.triangles = a_triangles; 1.225 + this.lights = []; 1.226 + this.ambient = [0,0,0]; 1.227 + this.background = [0.8,0.8,1]; 1.228 +} 1.229 +var zero = new Array(0,0,0); 1.230 + 1.231 +Scene.prototype.intersect = function(origin, dir, near, far) { 1.232 + var closest = null; 1.233 + for (i = 0; i < this.triangles.length; i++) { 1.234 + var triangle = this.triangles[i]; 1.235 + var d = triangle.intersect(origin, dir, near, far); 1.236 + if (d == null || d > far || d < near) 1.237 + continue; 1.238 + far = d; 1.239 + closest = triangle; 1.240 + } 1.241 + 1.242 + if (!closest) 1.243 + return [this.background[0],this.background[1],this.background[2]]; 1.244 + 1.245 + var normal = closest.normal; 1.246 + var hit = add(origin, scale(dir, far)); 1.247 + if (dot(dir, normal) > 0) 1.248 + normal = [-normal[0], -normal[1], -normal[2]]; 1.249 + 1.250 + var colour = null; 1.251 + if (closest.shader) { 1.252 + colour = closest.shader(closest, hit, dir); 1.253 + } else { 1.254 + colour = closest.material; 1.255 + } 1.256 + 1.257 + // do reflection 1.258 + var reflected = null; 1.259 + if (colour.reflection > 0.001) { 1.260 + var reflection = addVector(scale(normal, -2*dot(dir, normal)), dir); 1.261 + reflected = this.intersect(hit, reflection, 0.0001, 1000000); 1.262 + if (colour.reflection >= 0.999999) 1.263 + return reflected; 1.264 + } 1.265 + 1.266 + var l = [this.ambient[0], this.ambient[1], this.ambient[2]]; 1.267 + for (var i = 0; i < this.lights.length; i++) { 1.268 + var light = this.lights[i]; 1.269 + var toLight = sub(light, hit); 1.270 + var distance = lengthVector(toLight); 1.271 + scaleVector(toLight, 1.0/distance); 1.272 + distance -= 0.0001; 1.273 + if (this.blocked(hit, toLight, distance)) 1.274 + continue; 1.275 + var nl = dot(normal, toLight); 1.276 + if (nl > 0) 1.277 + addVector(l, scale(light.colour, nl)); 1.278 + } 1.279 + l = scalev(l, colour); 1.280 + if (reflected) { 1.281 + l = addVector(scaleVector(l, 1 - colour.reflection), scaleVector(reflected, colour.reflection)); 1.282 + } 1.283 + return l; 1.284 +} 1.285 + 1.286 +Scene.prototype.blocked = function(O, D, far) { 1.287 + var near = 0.0001; 1.288 + var closest = null; 1.289 + for (i = 0; i < this.triangles.length; i++) { 1.290 + var triangle = this.triangles[i]; 1.291 + var d = triangle.intersect(O, D, near, far); 1.292 + if (d == null || d > far || d < near) 1.293 + continue; 1.294 + return true; 1.295 + } 1.296 + 1.297 + return false; 1.298 +} 1.299 + 1.300 + 1.301 +// this camera code is from notes i made ages ago, it is from *somewhere* -- i cannot remember where 1.302 +// that somewhere is 1.303 +function Camera(origin, lookat, up) { 1.304 + var zaxis = normaliseVector(subVector(lookat, origin)); 1.305 + var xaxis = normaliseVector(cross(up, zaxis)); 1.306 + var yaxis = normaliseVector(cross(xaxis, subVector([0,0,0], zaxis))); 1.307 + var m = new Array(16); 1.308 + m[0] = xaxis[0]; m[1] = xaxis[1]; m[2] = xaxis[2]; 1.309 + m[4] = yaxis[0]; m[5] = yaxis[1]; m[6] = yaxis[2]; 1.310 + m[8] = zaxis[0]; m[9] = zaxis[1]; m[10] = zaxis[2]; 1.311 + invertMatrix(m); 1.312 + m[3] = 0; m[7] = 0; m[11] = 0; 1.313 + this.origin = origin; 1.314 + this.directions = new Array(4); 1.315 + this.directions[0] = normalise([-0.7, 0.7, 1]); 1.316 + this.directions[1] = normalise([ 0.7, 0.7, 1]); 1.317 + this.directions[2] = normalise([ 0.7, -0.7, 1]); 1.318 + this.directions[3] = normalise([-0.7, -0.7, 1]); 1.319 + this.directions[0] = transformMatrix(m, this.directions[0]); 1.320 + this.directions[1] = transformMatrix(m, this.directions[1]); 1.321 + this.directions[2] = transformMatrix(m, this.directions[2]); 1.322 + this.directions[3] = transformMatrix(m, this.directions[3]); 1.323 +} 1.324 + 1.325 +Camera.prototype.generateRayPair = function(y) { 1.326 + rays = new Array(new Object(), new Object()); 1.327 + rays[0].origin = this.origin; 1.328 + rays[1].origin = this.origin; 1.329 + rays[0].dir = addVector(scale(this.directions[0], y), scale(this.directions[3], 1 - y)); 1.330 + rays[1].dir = addVector(scale(this.directions[1], y), scale(this.directions[2], 1 - y)); 1.331 + return rays; 1.332 +} 1.333 + 1.334 +function renderRows(camera, scene, pixels, width, height, starty, stopy) { 1.335 + for (var y = starty; y < stopy; y++) { 1.336 + var rays = camera.generateRayPair(y / height); 1.337 + for (var x = 0; x < width; x++) { 1.338 + var xp = x / width; 1.339 + var origin = addVector(scale(rays[0].origin, xp), scale(rays[1].origin, 1 - xp)); 1.340 + var dir = normaliseVector(addVector(scale(rays[0].dir, xp), scale(rays[1].dir, 1 - xp))); 1.341 + var l = scene.intersect(origin, dir); 1.342 + pixels[y][x] = l; 1.343 + } 1.344 + } 1.345 +} 1.346 + 1.347 +Camera.prototype.render = function(scene, pixels, width, height) { 1.348 + var cam = this; 1.349 + var row = 0; 1.350 + renderRows(cam, scene, pixels, width, height, 0, height); 1.351 +} 1.352 + 1.353 + 1.354 + 1.355 +function raytraceScene() 1.356 +{ 1.357 + var startDate = new Date().getTime(); 1.358 + var numTriangles = 2 * 6; 1.359 + var triangles = new Array();//numTriangles); 1.360 + var tfl = createVector(-10, 10, -10); 1.361 + var tfr = createVector( 10, 10, -10); 1.362 + var tbl = createVector(-10, 10, 10); 1.363 + var tbr = createVector( 10, 10, 10); 1.364 + var bfl = createVector(-10, -10, -10); 1.365 + var bfr = createVector( 10, -10, -10); 1.366 + var bbl = createVector(-10, -10, 10); 1.367 + var bbr = createVector( 10, -10, 10); 1.368 + 1.369 + // cube!!! 1.370 + // front 1.371 + var i = 0; 1.372 + 1.373 + triangles[i++] = new Triangle(tfl, tfr, bfr); 1.374 + triangles[i++] = new Triangle(tfl, bfr, bfl); 1.375 + // back 1.376 + triangles[i++] = new Triangle(tbl, tbr, bbr); 1.377 + triangles[i++] = new Triangle(tbl, bbr, bbl); 1.378 + // triangles[i-1].material = [0.7,0.2,0.2]; 1.379 + // triangles[i-1].material.reflection = 0.8; 1.380 + // left 1.381 + triangles[i++] = new Triangle(tbl, tfl, bbl); 1.382 + // triangles[i-1].reflection = 0.6; 1.383 + triangles[i++] = new Triangle(tfl, bfl, bbl); 1.384 + // triangles[i-1].reflection = 0.6; 1.385 + // right 1.386 + triangles[i++] = new Triangle(tbr, tfr, bbr); 1.387 + triangles[i++] = new Triangle(tfr, bfr, bbr); 1.388 + // top 1.389 + triangles[i++] = new Triangle(tbl, tbr, tfr); 1.390 + triangles[i++] = new Triangle(tbl, tfr, tfl); 1.391 + // bottom 1.392 + triangles[i++] = new Triangle(bbl, bbr, bfr); 1.393 + triangles[i++] = new Triangle(bbl, bfr, bfl); 1.394 + 1.395 + //Floor!!!! 1.396 + var green = createVector(0.0, 0.4, 0.0); 1.397 + var grey = createVector(0.4, 0.4, 0.4); 1.398 + grey.reflection = 1.0; 1.399 + var floorShader = function(tri, pos, view) { 1.400 + var x = ((pos[0]/32) % 2 + 2) % 2; 1.401 + var z = ((pos[2]/32 + 0.3) % 2 + 2) % 2; 1.402 + if (x < 1 != z < 1) { 1.403 + //in the real world we use the fresnel term... 1.404 + // var angle = 1-dot(view, tri.normal); 1.405 + // angle *= angle; 1.406 + // angle *= angle; 1.407 + // angle *= angle; 1.408 + //grey.reflection = angle; 1.409 + return grey; 1.410 + } else 1.411 + return green; 1.412 + } 1.413 + var ffl = createVector(-1000, -30, -1000); 1.414 + var ffr = createVector( 1000, -30, -1000); 1.415 + var fbl = createVector(-1000, -30, 1000); 1.416 + var fbr = createVector( 1000, -30, 1000); 1.417 + triangles[i++] = new Triangle(fbl, fbr, ffr); 1.418 + triangles[i-1].shader = floorShader; 1.419 + triangles[i++] = new Triangle(fbl, ffr, ffl); 1.420 + triangles[i-1].shader = floorShader; 1.421 + 1.422 + var _scene = new Scene(triangles); 1.423 + _scene.lights[0] = createVector(20, 38, -22); 1.424 + _scene.lights[0].colour = createVector(0.7, 0.3, 0.3); 1.425 + _scene.lights[1] = createVector(-23, 40, 17); 1.426 + _scene.lights[1].colour = createVector(0.7, 0.3, 0.3); 1.427 + _scene.lights[2] = createVector(23, 20, 17); 1.428 + _scene.lights[2].colour = createVector(0.7, 0.7, 0.7); 1.429 + _scene.ambient = createVector(0.1, 0.1, 0.1); 1.430 + // _scene.background = createVector(0.7, 0.7, 1.0); 1.431 + 1.432 + var size = 30; 1.433 + var pixels = new Array(); 1.434 + for (var y = 0; y < size; y++) { 1.435 + pixels[y] = new Array(); 1.436 + for (var x = 0; x < size; x++) { 1.437 + pixels[y][x] = 0; 1.438 + } 1.439 + } 1.440 + 1.441 + var _camera = new Camera(createVector(-40, 40, 40), createVector(0, 0, 0), createVector(0, 1, 0)); 1.442 + _camera.render(_scene, pixels, size, size); 1.443 + 1.444 + return pixels; 1.445 +} 1.446 + 1.447 +function arrayToCanvasCommands(pixels) 1.448 +{ 1.449 + var s = '<canvas id="renderCanvas" width="30px" height="30px"></canvas><scr' + 'ipt>\nvar pixels = ['; 1.450 + var size = 30; 1.451 + for (var y = 0; y < size; y++) { 1.452 + s += "["; 1.453 + for (var x = 0; x < size; x++) { 1.454 + s += "[" + pixels[y][x] + "],"; 1.455 + } 1.456 + s+= "],"; 1.457 + } 1.458 + s += '];\n var canvas = document.getElementById("renderCanvas").getContext("2d");\n\ 1.459 +\n\ 1.460 +\n\ 1.461 + var size = 30;\n\ 1.462 + canvas.fillStyle = "red";\n\ 1.463 + canvas.fillRect(0, 0, size, size);\n\ 1.464 + canvas.scale(1, -1);\n\ 1.465 + canvas.translate(0, -size);\n\ 1.466 +\n\ 1.467 + if (!canvas.setFillColor)\n\ 1.468 + canvas.setFillColor = function(r, g, b, a) {\n\ 1.469 + this.fillStyle = "rgb("+[Math.floor(r * 255), Math.floor(g * 255), Math.floor(b * 255)]+")";\n\ 1.470 + }\n\ 1.471 +\n\ 1.472 +for (var y = 0; y < size; y++) {\n\ 1.473 + for (var x = 0; x < size; x++) {\n\ 1.474 + var l = pixels[y][x];\n\ 1.475 + canvas.setFillColor(l[0], l[1], l[2], 1);\n\ 1.476 + canvas.fillRect(x, y, 1, 1);\n\ 1.477 + }\n\ 1.478 +}</scr' + 'ipt>'; 1.479 + 1.480 + return s; 1.481 +} 1.482 + 1.483 +testOutput = arrayToCanvasCommands(raytraceScene()); 1.484 + 1.485 + 1.486 +var _sunSpiderInterval = new Date() - _sunSpiderStartDate; 1.487 + 1.488 +document.getElementById("console").innerHTML = _sunSpiderInterval; 1.489 +</script> 1.490 + 1.491 + 1.492 +</body> 1.493 +</html>