1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/browser/devtools/tilt/TiltWorkerCrafter.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,280 @@ 1.4 +/* -*- Mode: javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* vim: set ts=2 et sw=2 tw=80: */ 1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 +"use strict"; 1.10 + 1.11 +/** 1.12 + * Given the initialization data (sizes and information about 1.13 + * each DOM node) this worker sends back the arrays representing 1.14 + * vertices, texture coords, colors, indices and all the needed data for 1.15 + * rendering the DOM visualization mesh. 1.16 + * 1.17 + * Used in the TiltVisualization.Presenter object. 1.18 + */ 1.19 +self.onmessage = function TWC_onMessage(event) 1.20 +{ 1.21 + let data = event.data; 1.22 + let maxGroupNodes = parseInt(data.maxGroupNodes); 1.23 + let style = data.style; 1.24 + let texWidth = data.texWidth; 1.25 + let texHeight = data.texHeight; 1.26 + let nodesInfo = data.nodesInfo; 1.27 + 1.28 + let mesh = { 1.29 + allVertices: [], 1.30 + groups: [], 1.31 + width: 0, 1.32 + height: 0 1.33 + }; 1.34 + 1.35 + let vertices; 1.36 + let texCoord; 1.37 + let color; 1.38 + let stacksIndices; 1.39 + let wireframeIndices; 1.40 + let index; 1.41 + 1.42 + // seed the random function to get the same values each time 1.43 + // we're doing this to avoid ugly z-fighting with overlapping nodes 1.44 + self.random.seed(0); 1.45 + 1.46 + // go through all the dom nodes and compute the verts, texcoord etc. 1.47 + for (let n = 0, len = nodesInfo.length; n < len; n++) { 1.48 + 1.49 + // check if we need to start creating a new group 1.50 + if (n % maxGroupNodes === 0) { 1.51 + vertices = []; // recreate the arrays used to construct the 3D mesh data 1.52 + texCoord = []; 1.53 + color = []; 1.54 + stacksIndices = []; 1.55 + wireframeIndices = []; 1.56 + index = 0; 1.57 + } 1.58 + 1.59 + let info = nodesInfo[n]; 1.60 + let coord = info.coord; 1.61 + 1.62 + // calculate the stack x, y, z, width and height coordinates 1.63 + let z = coord.depth + coord.thickness; 1.64 + let y = coord.top; 1.65 + let x = coord.left; 1.66 + let w = coord.width; 1.67 + let h = coord.height; 1.68 + 1.69 + // the maximum texture size slices the visualization mesh where needed 1.70 + if (x + w > texWidth) { 1.71 + w = texWidth - x; 1.72 + } 1.73 + if (y + h > texHeight) { 1.74 + h = texHeight - y; 1.75 + } 1.76 + 1.77 + x += self.random.next(); 1.78 + y += self.random.next(); 1.79 + w -= self.random.next() * 0.1; 1.80 + h -= self.random.next() * 0.1; 1.81 + 1.82 + let xpw = x + w; 1.83 + let yph = y + h; 1.84 + let zmt = coord.depth; 1.85 + 1.86 + let xotw = x / texWidth; 1.87 + let yoth = y / texHeight; 1.88 + let xpwotw = xpw / texWidth; 1.89 + let yphoth = yph / texHeight; 1.90 + 1.91 + // calculate the margin fill color 1.92 + let fill = style[info.name] || style.highlight.defaultFill; 1.93 + 1.94 + let r = fill[0]; 1.95 + let g = fill[1]; 1.96 + let b = fill[2]; 1.97 + let g10 = r * 1.1; 1.98 + let g11 = g * 1.1; 1.99 + let g12 = b * 1.1; 1.100 + let g20 = r * 0.6; 1.101 + let g21 = g * 0.6; 1.102 + let g22 = b * 0.6; 1.103 + 1.104 + // compute the vertices 1.105 + vertices.push(x, y, z, /* front */ // 0 1.106 + x, yph, z, // 1 1.107 + xpw, yph, z, // 2 1.108 + xpw, y, z, // 3 1.109 + // we don't duplicate vertices for the left and right faces, because 1.110 + // they can be reused from the bottom and top faces; we do, however, 1.111 + // duplicate some vertices from front face, because it has custom 1.112 + // texture coordinates which are not shared by the other faces 1.113 + x, y, z, /* front */ // 4 1.114 + x, yph, z, // 5 1.115 + xpw, yph, z, // 6 1.116 + xpw, y, z, // 7 1.117 + x, y, zmt, /* back */ // 8 1.118 + x, yph, zmt, // 9 1.119 + xpw, yph, zmt, // 10 1.120 + xpw, y, zmt); // 11 1.121 + 1.122 + // compute the texture coordinates 1.123 + texCoord.push(xotw, yoth, 1.124 + xotw, yphoth, 1.125 + xpwotw, yphoth, 1.126 + xpwotw, yoth, 1.127 + -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0); 1.128 + 1.129 + // compute the colors for each vertex in the mesh 1.130 + color.push(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.131 + g10, g11, g12, 1.132 + g10, g11, g12, 1.133 + g10, g11, g12, 1.134 + g10, g11, g12, 1.135 + g20, g21, g22, 1.136 + g20, g21, g22, 1.137 + g20, g21, g22, 1.138 + g20, g21, g22); 1.139 + 1.140 + let i = index; // number of vertex points, used to create the indices array 1.141 + let ip1 = i + 1; 1.142 + let ip2 = ip1 + 1; 1.143 + let ip3 = ip2 + 1; 1.144 + let ip4 = ip3 + 1; 1.145 + let ip5 = ip4 + 1; 1.146 + let ip6 = ip5 + 1; 1.147 + let ip7 = ip6 + 1; 1.148 + let ip8 = ip7 + 1; 1.149 + let ip9 = ip8 + 1; 1.150 + let ip10 = ip9 + 1; 1.151 + let ip11 = ip10 + 1; 1.152 + 1.153 + // compute the stack indices 1.154 + stacksIndices.unshift(i, ip1, ip2, i, ip2, ip3, 1.155 + ip8, ip9, ip5, ip8, ip5, ip4, 1.156 + ip7, ip6, ip10, ip7, ip10, ip11, 1.157 + ip8, ip4, ip7, ip8, ip7, ip11, 1.158 + ip5, ip9, ip10, ip5, ip10, ip6); 1.159 + 1.160 + // compute the wireframe indices 1.161 + if (coord.thickness !== 0) { 1.162 + wireframeIndices.unshift(i, ip1, ip1, ip2, 1.163 + ip2, ip3, ip3, i, 1.164 + ip8, i, ip9, ip1, 1.165 + ip11, ip3, ip10, ip2); 1.166 + } 1.167 + 1.168 + // there are 12 vertices in a stack representing a node 1.169 + index += 12; 1.170 + 1.171 + // set the maximum mesh width and height to calculate the center offset 1.172 + mesh.width = Math.max(w, mesh.width); 1.173 + mesh.height = Math.max(h, mesh.height); 1.174 + 1.175 + // check if we need to save the currently active group; this happens after 1.176 + // we filled all the "slots" in a group or there aren't any remaining nodes 1.177 + if (((n + 1) % maxGroupNodes === 0) || (n === len - 1)) { 1.178 + mesh.groups.push({ 1.179 + vertices: vertices, 1.180 + texCoord: texCoord, 1.181 + color: color, 1.182 + stacksIndices: stacksIndices, 1.183 + wireframeIndices: wireframeIndices 1.184 + }); 1.185 + mesh.allVertices = mesh.allVertices.concat(vertices); 1.186 + } 1.187 + } 1.188 + 1.189 + self.postMessage(mesh); 1.190 + close(); 1.191 +}; 1.192 + 1.193 +/** 1.194 + * Utility functions for generating random numbers using the Alea algorithm. 1.195 + */ 1.196 +self.random = { 1.197 + 1.198 + /** 1.199 + * The generator function, automatically created with seed 0. 1.200 + */ 1.201 + _generator: null, 1.202 + 1.203 + /** 1.204 + * Returns a new random number between [0..1) 1.205 + */ 1.206 + next: function RNG_next() 1.207 + { 1.208 + return this._generator(); 1.209 + }, 1.210 + 1.211 + /** 1.212 + * From http://baagoe.com/en/RandomMusings/javascript 1.213 + * Johannes Baagoe <baagoe@baagoe.com>, 2010 1.214 + * 1.215 + * Seeds a random generator function with a set of passed arguments. 1.216 + */ 1.217 + seed: function RNG_seed() 1.218 + { 1.219 + let s0 = 0; 1.220 + let s1 = 0; 1.221 + let s2 = 0; 1.222 + let c = 1; 1.223 + 1.224 + if (arguments.length === 0) { 1.225 + return this.seed(+new Date()); 1.226 + } else { 1.227 + s0 = this.mash(" "); 1.228 + s1 = this.mash(" "); 1.229 + s2 = this.mash(" "); 1.230 + 1.231 + for (let i = 0, len = arguments.length; i < len; i++) { 1.232 + s0 -= this.mash(arguments[i]); 1.233 + if (s0 < 0) { 1.234 + s0 += 1; 1.235 + } 1.236 + s1 -= this.mash(arguments[i]); 1.237 + if (s1 < 0) { 1.238 + s1 += 1; 1.239 + } 1.240 + s2 -= this.mash(arguments[i]); 1.241 + if (s2 < 0) { 1.242 + s2 += 1; 1.243 + } 1.244 + } 1.245 + 1.246 + let random = function() { 1.247 + let t = 2091639 * s0 + c * 2.3283064365386963e-10; // 2^-32 1.248 + s0 = s1; 1.249 + s1 = s2; 1.250 + return (s2 = t - (c = t | 0)); 1.251 + }; 1.252 + random.uint32 = function() { 1.253 + return random() * 0x100000000; // 2^32 1.254 + }; 1.255 + random.fract53 = function() { 1.256 + return random() + 1.257 + (random() * 0x200000 | 0) * 1.1102230246251565e-16; // 2^-53 1.258 + }; 1.259 + return (this._generator = random); 1.260 + } 1.261 + }, 1.262 + 1.263 + /** 1.264 + * From http://baagoe.com/en/RandomMusings/javascript 1.265 + * Johannes Baagoe <baagoe@baagoe.com>, 2010 1.266 + */ 1.267 + mash: function RNG_mash(data) 1.268 + { 1.269 + let h, n = 0xefc8249d; 1.270 + 1.271 + for (let i = 0, data = data.toString(), len = data.length; i < len; i++) { 1.272 + n += data.charCodeAt(i); 1.273 + h = 0.02519603282416938 * n; 1.274 + n = h >>> 0; 1.275 + h -= n; 1.276 + h *= n; 1.277 + n = h >>> 0; 1.278 + h -= n; 1.279 + n += h * 0x100000000; // 2^32 1.280 + } 1.281 + return (n >>> 0) * 2.3283064365386963e-10; // 2^-32 1.282 + } 1.283 +};