You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

KNWebGLUtil.js 31KB

5 years ago
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145
  1. /*
  2. * KNWebGLUtil.js
  3. * Keynote HTML Player
  4. *
  5. * Created by Tungwei Cheng
  6. * Copyright (c) 2016-2018 Apple Inc. All rights reserved.
  7. */
  8. var KNWebGLUtil = {};
  9. KNWebGLUtil.setupProgram = function(gl, programName) {
  10. var shader = KNWebGLShader[programName];
  11. var vertexShader = this.loadShader(gl, gl.VERTEX_SHADER, shader.vertex);
  12. var fragmentShader = this.loadShader(gl, gl.FRAGMENT_SHADER, shader.fragment);
  13. var shaderProgram = this.createShaderProgram(gl, vertexShader, fragmentShader);
  14. // creates uniforms and attribs but does not enable attribs.
  15. var attribs = {};
  16. var uniforms = {};
  17. for (var i = 0, length = shader.uniformNames.length; i < length; i++) {
  18. var uniformName = shader.uniformNames[i];
  19. uniforms[uniformName] = gl.getUniformLocation(shaderProgram, uniformName);
  20. }
  21. for (var i = 0, length = shader.attribNames.length; i < length; i++) {
  22. var attribName = shader.attribNames[i];
  23. attribs[attribName] = gl.getAttribLocation(shaderProgram, attribName);
  24. }
  25. // create a program object
  26. var program = {
  27. shaderProgram: shaderProgram,
  28. uniforms: uniforms,
  29. attribs: attribs
  30. };
  31. // use this program for rendering
  32. gl.useProgram(shaderProgram);
  33. return program;
  34. };
  35. KNWebGLUtil.loadShader = function(gl, type, shaderSource) {
  36. var shader = gl.createShader(type);
  37. gl.shaderSource(shader, shaderSource);
  38. gl.compileShader(shader);
  39. // Check the compile status
  40. var compiled = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
  41. if (!compiled) {
  42. // error during compilation
  43. var error = gl.getShaderInfoLog(shader);
  44. console.log("*** Error compiling shader '" + shader + "':" + error);
  45. gl.deleteShader(shader);
  46. return null;
  47. }
  48. return shader;
  49. };
  50. KNWebGLUtil.createShaderProgram = function(gl, vertexShader, fragmentShader) {
  51. // create shader program
  52. var shaderProgram = gl.createProgram();
  53. // Attach the shaders to the program
  54. gl.attachShader(shaderProgram, vertexShader);
  55. gl.attachShader(shaderProgram, fragmentShader);
  56. // Link the program
  57. gl.linkProgram(shaderProgram);
  58. var linked = gl.getProgramParameter(shaderProgram, gl.LINK_STATUS);
  59. if (!linked) {
  60. var error = gl.getProgramInfoLog(shaderProgram);
  61. console.log("Error in program linking:" + error);
  62. gl.deleteProgram(shaderProgram);
  63. }
  64. return shaderProgram;
  65. };
  66. KNWebGLUtil.createTexture = function(gl, image) {
  67. var texture = gl.createTexture();
  68. // bind WebGLTexture object to gl.TEXTURE_2D target
  69. gl.bindTexture(gl.TEXTURE_2D, texture);
  70. gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
  71. gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
  72. // upload texture data to GPU
  73. gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
  74. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
  75. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
  76. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
  77. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
  78. gl.bindTexture(gl.TEXTURE_2D, null);
  79. return texture;
  80. };
  81. KNWebGLUtil.bindTextureWithImage = function(gl, image) {
  82. var texture = gl.createTexture();
  83. // bind WebGLTexture object to gl.TEXTURE_2D target
  84. gl.bindTexture(gl.TEXTURE_2D, texture);
  85. gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
  86. gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
  87. gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
  88. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
  89. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
  90. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
  91. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
  92. gl.bindTexture(gl.TEXTURE_2D, null);
  93. return texture;
  94. };
  95. KNWebGLUtil.bindDynamicBufferWithData = function(gl, attribLoc, buffer, data, size) {
  96. gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
  97. gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(data), gl.DYNAMIC_DRAW);
  98. // we need to enable attrib loc to work with data buffer
  99. gl.enableVertexAttribArray(attribLoc);
  100. gl.vertexAttribPointer(attribLoc, size, gl.FLOAT, false, 0, 0);
  101. };
  102. KNWebGLUtil.bindBufferWithData = function(gl, attribLoc, buffer, data, size, bufferUsage) {
  103. gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
  104. gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(data), bufferUsage);
  105. // we need to enable attrib loc to work with data buffer
  106. gl.enableVertexAttribArray(attribLoc);
  107. gl.vertexAttribPointer(attribLoc, size, gl.FLOAT, false, 0, 0);
  108. };
  109. //attribute buffer insertion
  110. KNWebGLUtil.setPoint2DAtIndexForAttribute = function(point, index, attribute) {
  111. //attribute cannot become an object. we need to create an object where we can place this. BUMMER
  112. attribute[index*2] = point.x;
  113. attribute[index*2+1] = point.y;
  114. attribute.size = 2;
  115. };
  116. KNWebGLUtil.setPoint3DAtIndexForAttribute = function(point, index, attribute) {
  117. attribute[index*3] = point.x;
  118. attribute[index*3+1] = point.y;
  119. attribute[index*3+2] = point.z;
  120. attribute.size = 3;
  121. };
  122. KNWebGLUtil.setPoint4DAtIndexForAttribute = function(point, index, attribute) {
  123. attribute[index*4] = point.x;
  124. attribute[index*4+1] = point.y;
  125. attribute[index*4+2] = point.z;
  126. attribute[index*4+3] = point.w;
  127. attribute.size = 4;
  128. };
  129. KNWebGLUtil.setFloatAtIndexForAttribute = function(f, index, attribute) {
  130. attribute[index] = f;
  131. };
  132. KNWebGLUtil.getPoint2DForArrayAtIndex = function(attrib, index) {
  133. var point = {};
  134. point.x = attrib[index*2];
  135. point.y = attrib[index*2 + 1];
  136. return point;
  137. };
  138. KNWebGLUtil.getPoint3DForArrayAtIndex = function(attrib, index) {
  139. var point = {};
  140. point.x = attrib[index*3];
  141. point.y = attrib[index*3 + 1];
  142. point.z = attrib[index*3 + 2];
  143. return point;
  144. };
  145. KNWebGLUtil.getPoint4DForArrayAtIndex = function(attrib, index) {
  146. var point = {};
  147. point.x = attrib[index*4];
  148. point.y = attrib[index*4 + 1];
  149. point.z = attrib[index*4 + 2];
  150. point.w = attrib[index*4 + 3];
  151. return point;
  152. };
  153. KNWebGLUtil.bindAllAvailableAttributesToBuffers = function(gl, attribs, bufferdata, size, buffer, bufferUsage) {
  154. for (var obj in attribs) {
  155. var attribute = attribs[obj];
  156. if (buffer[obj] == undefined) {
  157. buffer[obj] = gl.createBuffer();
  158. }
  159. KNWebGLUtil.bindBufferWithData(gl, attribute, buffer[obj], bufferdata[obj], size[obj], bufferUsage);
  160. }
  161. };
  162. // We need to enable attribs before binding.
  163. // This also sets the program to the given program.
  164. // This never needs to be called in single program animations
  165. KNWebGLUtil.enableAttribs = function(gl, program) {
  166. var attribs = program.attribs;
  167. gl.useProgram(program.shaderProgram);
  168. for (var obj in attribs) {
  169. gl.enableVertexAttribArray(attribs[obj]);
  170. }
  171. };
  172. /*
  173. * WebGraphics is not a container for any data. It should only computer and return values.
  174. *
  175. * makePoint(x, y): returns a object with .x and .y properties attached
  176. *
  177. * randomBetween(a, b): returns a random number between a (lower bound) and b (upper bound)
  178. *
  179. * mix(x, y, a): returns a linear intern between x and y using a as a weight between them
  180. *
  181. * clamp(x, minVal, maxVal) : clamps x between a min and max value
  182. */
  183. var WebGraphics = {};
  184. WebGraphics.makePoint = function(x, y) {
  185. var obj = {};
  186. obj.x = x;
  187. obj.y = y;
  188. return obj;
  189. };
  190. WebGraphics.makePoint3D = function(x, y, z) {
  191. var obj = {};
  192. obj.x = x;
  193. obj.y = y;
  194. obj.z = z;
  195. return obj;
  196. };
  197. WebGraphics.makePoint4D = function(x, y, z, w) {
  198. var obj = {};
  199. obj.x = x;
  200. obj.y = y;
  201. obj.z = z;
  202. obj.w = w;
  203. return obj;
  204. };
  205. WebGraphics.makeRect = function(x,y, width, height) {
  206. var obj = {};
  207. obj.x = x;
  208. obj.y = y;
  209. obj.width = width;
  210. obj.height = height;
  211. return obj;
  212. };
  213. WebGraphics.makeSize = function(width, height) {
  214. var obj = {};
  215. obj.width = width;
  216. obj.height = height;
  217. return obj;
  218. };
  219. WebGraphics.setOrigin = function(obj, point) {
  220. obj.x = point.x;
  221. obj.y = point.y;
  222. return obj;
  223. };
  224. WebGraphics.multiplyPoint3DByScalar = function(point, scalar) {
  225. var obj = {};
  226. obj.x = point.x * scalar;
  227. obj.y = point.y * scalar;
  228. obj.z = point.z * scalar;
  229. return obj;
  230. };
  231. WebGraphics.multiplyPoint4DByScalar = function(point, scalar) {
  232. var obj = {};
  233. obj.x = point.x * scalar;
  234. obj.y = point.y * scalar;
  235. obj.z = point.z * scalar;
  236. obj.w = point.w * scalar;
  237. return obj;
  238. };
  239. WebGraphics.addPoint3DToPoint3D = function(a, b) {
  240. var obj = {};
  241. obj.x = a.x + b.x;
  242. obj.y = a.y + b.y;
  243. obj.z = a.z + b.z;
  244. return obj;
  245. };
  246. WebGraphics.point3DNormalize = function(pt3d) {
  247. var length = Math.sqrt(pt3d.x * pt3d.x + pt3d.y * pt3d.y + pt3d.z * pt3d.z);
  248. var obj = {};
  249. obj.z = pt3d.z / length;
  250. obj.y = pt3d.y / length;
  251. obj.x = pt3d.x / length;
  252. return obj;
  253. };
  254. WebGraphics.randomBetween = function(min, max) {
  255. var x = Math.random();
  256. x *= (max - min);
  257. x += min;
  258. return x;
  259. };
  260. WebGraphics.doubleBetween = function(randMin, randMax) {
  261. var result = 0;
  262. var bottom, top;
  263. if (randMin < randMax) {
  264. bottom = randMin;
  265. top = randMax;
  266. } else {
  267. bottom = randMax;
  268. top = randMin;
  269. }
  270. // rnd: random in range [0.0 -> 1.0)
  271. // RandBetween(bottom, top) = ((top - bottom) * rnd) + bottom
  272. // To avoid overflows, distribute the multiplication:
  273. // = top*rand - bottom*rand + bottom
  274. var rnd = Math.random();
  275. var topMult = top * rnd;
  276. var bottomMult = bottom * rnd;
  277. if ((bottom >= 0.0) == (top >= 0.0)) {
  278. // Both are the same sign, do the subtraction first to avoid overflow.
  279. result = topMult - bottomMult;
  280. result = result + bottom;
  281. } else {
  282. // The signs differ, add bottom in first to avoid overflow.
  283. result = topMult + bottom;
  284. result = result - bottomMult;
  285. }
  286. return result;
  287. }
  288. WebGraphics.mix = function(x, y, a) {
  289. return x * (1 - a) + (y * a);
  290. };
  291. WebGraphics.clamp = function(x, minVal, maxVal) {
  292. return Math.min(Math.max(x, minVal), maxVal);
  293. };
  294. WebGraphics.sineMap = function(x) {
  295. return (Math.sin(x * Math.PI - (Math.PI / 2)) + 1) * 0.5;
  296. };
  297. WebGraphics.createMatrix4 = function() {
  298. //creates and identity matrix, column-major matrix library, it is not necessary to use this to get an ortho matrix
  299. var obj = new Float32Array(16);
  300. obj[0] = 1;
  301. obj[1] = 0;
  302. obj[2] = 0;
  303. obj[3] = 0;
  304. obj[4] = 0;
  305. obj[5] = 1;
  306. obj[6] = 0;
  307. obj[7] = 0;
  308. obj[8] = 0;
  309. obj[9] = 0;
  310. obj[10] = 1;
  311. obj[11] = 0;
  312. obj[12] = 0;
  313. obj[13] = 0;
  314. obj[14] = 0;
  315. obj[15] = 1;
  316. return obj;
  317. };
  318. WebGraphics.makeIdentityMatrix4 = function() {
  319. return WebGraphics.createMatrix4();
  320. };
  321. WebGraphics.makeOrthoMatrix4 = function(left, right, bottom, top, near, far) {
  322. var matrix = new Float32Array(16);
  323. var rl = right - left;
  324. var tb = top - bottom;
  325. var fn = far - near;
  326. matrix[0] = 2 / rl;
  327. matrix[1] = 0;
  328. matrix[2] = 0;
  329. matrix[3] = 0;
  330. matrix[4] = 0;
  331. matrix[5] = 2 / tb;
  332. matrix[6] = 0;
  333. matrix[7] = 0;
  334. matrix[8] = 0;
  335. matrix[9] = 0;
  336. matrix[10] = -2 /fn;
  337. matrix[11] = 0;
  338. matrix[12] = -(right + left) / rl;
  339. matrix[13] = -(top - bottom) / tb;
  340. matrix[14] = -(far + near) / fn;
  341. matrix[15] = 1;
  342. return matrix;
  343. };
  344. WebGraphics.makeFrustumMatrix4 = function(left, right, bottom, top, near, far) {
  345. var rl = right - left;
  346. var tb = top - bottom;
  347. var fn = far - near;
  348. var m = new Float32Array(16);
  349. m[0] = (near * 2) / rl; //11
  350. m[1] = 0; //21
  351. m[2] = 0; //31
  352. m[3] = 0; //41
  353. m[4] = 0; //12
  354. m[5] = (near * 2) / tb; //22
  355. m[6] = 0; //32
  356. m[7] = 0; //42
  357. m[8] = (right + left) / rl;
  358. m[9] = (top + bottom) / tb;
  359. m[10] = -(far + near) / fn;
  360. m[11] = -1;
  361. m[12] = 0;
  362. m[13] = 0;
  363. m[14] = (-2 * far * near) / fn;
  364. m[15] = 0;
  365. return m;
  366. };
  367. WebGraphics.makePerspectiveMatrix4 = function(fovy, aspect, near, far) {
  368. var top = near * Math.tan(fovy * Math.PI / 360.0);
  369. var right = top * aspect;
  370. return WebGraphics.makeFrustumMatrix4(-right, right, -top, top, near, far);
  371. };
  372. WebGraphics.multiplyMatrix4 = function(a, b) {
  373. //a*b
  374. var m = new Float32Array(16);
  375. var a11 = a[0], a12 = a[4], a13 = a[8], a14 = a[12], a21 = a[1], a22 = a[5], a23 = a[9], a24 = a[13],
  376. a31 = a[2], a32 = a[6], a33 = a[10], a34 = a[14], a41 = a[3], a42 = a[7], a43 = a[11], a44 = a[15];
  377. var b11 = b[0], b12 = b[4], b13 = b[8], b14 = b[12], b21 = b[1], b22 = b[5], b23 = b[9], b24 = b[13],
  378. b31 = b[2], b32 = b[6], b33 = b[10], b34 = b[14], b41 = b[3], b42 = b[7], b43 = b[11], b44 = b[15];
  379. m[0] = a11 * b11 + a12 * b21 + a13 * b31 + a14 * b41;
  380. m[4] = a11 * b12 + a12 * b22 + a13 * b32 + a14 * b42;
  381. m[8] = a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43;
  382. m[12] = a11 * b14 + a12 * b24 + a13 * b34 + a14 * b44;
  383. m[1] = a21 * b11 + a22 * b21 + a23 * b31 + a24 * b41;
  384. m[5] = a21 * b12 + a22 * b22 + a23 * b32 + a24 * b42;
  385. m[9] = a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43;
  386. m[13] = a21 * b14 + a22 * b24 + a23 * b34 + a24 * b44;
  387. m[2] = a31 * b11 + a32 * b21 + a33 * b31 + a34 * b41;
  388. m[6] = a31 * b12 + a32 * b22 + a33 * b32 + a34 * b42;
  389. m[10] = a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43;
  390. m[14] = a31 * b14 + a32 * b24 + a33 * b34 + a34 * b44;
  391. m[3] = a41 * b11 + a42 * b21 + a43 * b31 + a44 * b41;
  392. m[7] = a41 * b12 + a42 * b22 + a43 * b32 + a44 * b42;
  393. m[11] = a41 * b13 + a42 * b23 + a43 * b33 + a44 * b43;
  394. m[15] = a41 * b14 + a42 * b24 + a43 * b34 + a44 * b44;
  395. return m;
  396. };
  397. WebGraphics.scaleMatrix4 = function(m4, sx, sy, sz) {
  398. var m = WebGraphics.createMatrix4();
  399. m[0] = sx;
  400. m[5] = sy;
  401. m[10] = sz;
  402. return WebGraphics.multiplyMatrix4(m4, m);
  403. };
  404. WebGraphics.translateMatrix4 = function(m4, tx, ty, tz) {
  405. var m = WebGraphics.createMatrix4();
  406. m[12] = tx;
  407. m[13] = ty;
  408. m[14] = tz;
  409. return WebGraphics.multiplyMatrix4(m4, m);
  410. };
  411. WebGraphics.rotateMatrix4AboutXYZ = function(m4, theta, x, y, z) {
  412. var point3d = WebGraphics.makePoint3D(x, y, z);
  413. point3d = WebGraphics.point3DNormalize(point3d);
  414. var ux = point3d.x;
  415. var uy = point3d.y;
  416. var uz = point3d.z;
  417. var cos = Math.cos(theta);
  418. var oneMinusCos = 1 - cos;
  419. var sin = Math.sin(theta);
  420. var m = WebGraphics.createMatrix4();
  421. m[0] = cos + (ux * ux) * oneMinusCos;
  422. m[1] = ux * uy * oneMinusCos + (uz * sin);
  423. m[2] = uz * ux * oneMinusCos - uy * sin;
  424. m[4] = ux * uy * oneMinusCos - uz * sin;
  425. m[5] = cos + (uy * uy) * oneMinusCos;
  426. m[6] = uz * uy * oneMinusCos + ux * sin;
  427. m[8] = ux * uy * oneMinusCos + uy * sin;
  428. m[9] = uy * uz * oneMinusCos - ux * sin;
  429. m[10] = cos + (uz * uz) * oneMinusCos;
  430. return WebGraphics.multiplyMatrix4(m4, m);
  431. };
  432. WebGraphics.colorWithHSBA = function(hue, saturation, brightness, alpha) {
  433. var hueTimesSix, frac, p1, p2, p3, red, blue, green;
  434. var obj = {"hue": hue, "saturation": saturation, "brightness": brightness, "alpha": alpha};
  435. if (hue == 1.0) {
  436. hue = 0.0;
  437. }
  438. hueTimesSix = hue * 6.0;
  439. frac = hueTimesSix - Math.floor(hueTimesSix);
  440. p1 = brightness * (1-saturation);
  441. p2 = brightness * (1.0 - (saturation * frac));
  442. p3 = brightness * (1.0 - (saturation * (1.0 - frac)));
  443. switch (parseInt(hueTimesSix)) {
  444. case 0:
  445. red = brightness;
  446. green = p3;
  447. blue = p1;
  448. break;
  449. case 1:
  450. red = p2;
  451. green = brightness;
  452. blue = p1;
  453. break;
  454. case 2:
  455. red = p1;
  456. green = brightness;
  457. blue = p3;
  458. break;
  459. case 3:
  460. red = p1;
  461. green = p2;
  462. blue = brightness;
  463. break;
  464. case 4:
  465. red = p3;
  466. green = p1;
  467. blue = brightness;
  468. break;
  469. case 5:
  470. red = brightness;
  471. green = p1;
  472. blue = p2;
  473. break;
  474. }
  475. obj.red = red;
  476. obj.blue = blue;
  477. obj.green = green;
  478. return obj;
  479. };
  480. WebGraphics.makeMat3WithAffineTransform = function(affineTransform) {
  481. var obj = new Float32Array(9);
  482. obj[0] = affineTransform[0];
  483. obj[1] = affineTransform[1];
  484. obj[2] = 0;
  485. obj[3] = affineTransform[2];
  486. obj[4] = affineTransform[3];
  487. obj[5] = 0;
  488. obj[6] = affineTransform[4];
  489. obj[7] = affineTransform[5];
  490. obj[8] = 1;
  491. return obj;
  492. };
  493. /*
  494. * High performance vector container for math
  495. * Copyright (c) 2011 Apple, Inc
  496. */
  497. vector3 = function(vec) {
  498. this.create(vec);
  499. };
  500. vector3.prototype = {
  501. create: function(vec) {
  502. var m = this.$matrix = {};
  503. if (!vec) {
  504. m.m11 = 0;
  505. m.m12 = 0;
  506. m.m13 = 0;
  507. } else {
  508. m.m11 = vec[0];
  509. m.m12 = vec[1];
  510. m.m13 = vec[2];
  511. }
  512. },
  513. subtract: function(vec) {
  514. var m = this.$matrix;
  515. var mm = vec.$matrix;
  516. m.m11 -= mm.m11;
  517. m.m12 -= mm.m12;
  518. m.m13 -= mm.m13;
  519. },
  520. add: function(vec) {
  521. var m = this.$matrix;
  522. var mm = vec.$matrix;
  523. m.m11 += mm.m11;
  524. m.m12 += mm.m12;
  525. m.m13 += mm.m13;
  526. },
  527. normalize: function() {
  528. var m = this.$matrix;
  529. var length = Math.sqrt((m.m11 * m.m11) + (m.m12 * m.m12) + (m.m13 * m.m13));
  530. if (length > 0) {
  531. m.m11 /= length;
  532. m.m12 /= length;
  533. m.m13 /= length;
  534. }
  535. },
  536. scale: function(scalar) {
  537. var m = this.$matrix;
  538. m.m11 *= scalar;
  539. m.m12 *= scalar;
  540. m.m13 *= scalar;
  541. },
  542. cross: function(vec) {
  543. var m = this.$matrix;
  544. var mm = vec.$matrix;
  545. var a1 = mm.m11, a2 = mm.m12, a3 = mm.m13;
  546. var m1 = m.m11, m2 = m.m12, m3 = m.m13;
  547. m.m11 = m2 * a3 - m3 * a2;
  548. m.m12 = m3 * a1 - m1 * a3;
  549. m.m13 = m1 * a2 - m2 * a1;
  550. },
  551. getArray: function() {
  552. var m = this.$matrix;
  553. return [m.m11, m.m12, m.m13];
  554. }
  555. };
  556. // Matrix3, 3x3 Matrix Class
  557. // Matrix3 stores row-major order, simply transverse to get a webGL acceptable array
  558. Matrix3 = function() {
  559. this.identity();
  560. };
  561. Matrix3.prototype = {
  562. identity: function() {
  563. this.$matrix = {
  564. m11: 1, m12: 0, m13: 0,
  565. m21: 0, m22: 1, m23: 0,
  566. m31: 0, m32: 0, m33: 1
  567. };
  568. },
  569. affineScale: function(sx, sy) {
  570. var m = this.$matrix;
  571. m.m11 = sx;
  572. m.m22 = sy;
  573. },
  574. affineTranslate: function(tx, ty) {
  575. var m = this.$matrix;
  576. m.m13 = tx;
  577. m.m23 = ty;
  578. },
  579. transformTranslate: function(tx, ty) {
  580. var matrix = new Matrix3();
  581. matrix.affineTranslate(tx, ty);
  582. this.multiply(matrix.getArray());
  583. },
  584. multiply: function(mat) {
  585. var m = this.$matrix;
  586. var m0 = m.m11, m1 = m.m12, m2 = m.m13, m3 = m.m21, m4 = m.m22, m5 = m.m23, m6 = m.m31, m7 = m.m32, m8 = m.m33;
  587. m.m11 = m0 * mat[0] + m1 * mat[3] + m2 * mat[6];
  588. m.m12 = m0 * mat[1] + m1 * mat[4] + m2 * mat[7];
  589. m.m13 = m0 * mat[2] + m1 * mat[5] + m2 * mat[8];
  590. m.m21 = m3 * mat[0] + m4 * mat[3] + m5 * mat[6];
  591. m.m22 = m3 * mat[1] + m4 * mat[4] + m5 * mat[7];
  592. m.m23 = m3 * mat[2] + m4 * mat[5] + m5 * mat[8];
  593. m.m31 = m6 * mat[0] + m7 * mat[3] + m8 * mat[6];
  594. m.m32 = m6 * mat[1] + m7 * mat[4] + m8 * mat[7];
  595. m.m33 = m6 * mat[2] + m7 * mat[5] + m8 * mat[8];
  596. },
  597. getArray: function() {
  598. // this is row major order, for WebGL you'll need to transverse this
  599. var m = this.$matrix;
  600. return [m.m11, m.m12, m.m13, m.m21, m.m22, m.m23, m.m31, m.m32, m.m33];
  601. },
  602. getFloat32Array: function() {
  603. return new Float32Array(this.getArray());
  604. },
  605. getColumnMajorArray: function() {
  606. // this is row major order, for WebGL you'll need to transverse this
  607. var m = this.$matrix;
  608. return [m.m11, m.m21, m.m31, m.m12, m.m22, m.m32, m.m13, m.m23, m.m33 ];
  609. },
  610. getColumnMajorFloat32Array: function() {
  611. return new Float32Array(this.getColumnMajorArray());
  612. }
  613. };
  614. Matrix4 = function() {
  615. this.identity();
  616. };
  617. Matrix4.prototype = {
  618. identity: function() {
  619. this.$matrix = {
  620. m11: 1, m12: 0, m13: 0, m14: 0,
  621. m21: 0, m22: 1, m23: 0, m24: 0,
  622. m31: 0, m32: 0, m33: 1, m34: 0,
  623. m41: 0, m42: 0, m43: 0, m44: 1
  624. };
  625. },
  626. translate: function(x, y, z) {
  627. var matrix = new Matrix4();
  628. var m = matrix.$matrix;
  629. m.m14 = x;
  630. m.m24 = y;
  631. m.m34 = z;
  632. this.multiply(matrix);
  633. /*
  634. * this.$matrix.m41 = this.$matrix.m11*x + this.$matrix.m21*y +
  635. * this.$matrix.m31*z + this.$matrix.m41; this.$matrix.m42 =
  636. * this.$matrix.m12*x + this.$matrix.m22*y + this.$matrix.m32*z +
  637. * this.$matrix.m42; this.$matrix.m43 = this.$matrix.m13*x +
  638. * this.$matrix.m23*y + this.$matrix.m33*z + this.$matrix.m43;
  639. * this.$matrix.m44 = this.$matrix.m14*x + this.$matrix.m24*y +
  640. * this.$matrix.m34*z + this.$matrix.m44;
  641. */
  642. },
  643. scale: function(x, y, z) {
  644. var matrix = new Matrix4();
  645. var m = matrix.$matrix;
  646. m.m11 = x;
  647. m.m22 = y;
  648. m.m33 = z;
  649. this.multiply(matrix);
  650. },
  651. multiply: function(mat) {
  652. var m = this.$matrix;
  653. var mm = mat.$matrix;
  654. var m11 = (mm.m11 * m.m11 + mm.m21 * m.m12 + mm.m31 * m.m13 + mm.m41 * m.m14);
  655. var m12 = (mm.m12 * m.m11 + mm.m22 * m.m12 + mm.m32 * m.m13 + mm.m42 * m.m14);
  656. var m13 = (mm.m13 * m.m11 + mm.m23 * m.m12 + mm.m33 * m.m13 + mm.m43 * m.m14);
  657. var m14 = (mm.m14 * m.m11 + mm.m24 * m.m12 + mm.m34 * m.m13 + mm.m44 * m.m14);
  658. var m21 = (mm.m11 * m.m21 + mm.m21 * m.m22 + mm.m31 * m.m23 + mm.m41 * m.m24);
  659. var m22 = (mm.m12 * m.m21 + mm.m22 * m.m22 + mm.m32 * m.m23 + mm.m42 * m.m24);
  660. var m23 = (mm.m13 * m.m21 + mm.m23 * m.m22 + mm.m33 * m.m23 + mm.m43 * m.m24);
  661. var m24 = (mm.m14 * m.m21 + mm.m24 * m.m22 + mm.m34 * m.m23 + mm.m44 * m.m24);
  662. var m31 = (mm.m11 * m.m31 + mm.m21 * m.m32 + mm.m31 * m.m33 + mm.m41 * m.m34);
  663. var m32 = (mm.m12 * m.m31 + mm.m22 * m.m32 + mm.m32 * m.m33 + mm.m42 * m.m34);
  664. var m33 = (mm.m13 * m.m31 + mm.m23 * m.m32 + mm.m33 * m.m33 + mm.m43 * m.m34);
  665. var m34 = (mm.m14 * m.m31 + mm.m24 * m.m32 + mm.m34 * m.m33 + mm.m44 * m.m34);
  666. var m41 = (mm.m11 * m.m41 + mm.m21 * m.m42 + mm.m31 * m.m43 + mm.m41 * m.m44);
  667. var m42 = (mm.m12 * m.m41 + mm.m22 * m.m42 + mm.m32 * m.m43 + mm.m42 * m.m44);
  668. var m43 = (mm.m13 * m.m41 + mm.m23 * m.m42 + mm.m33 * m.m43 + mm.m43 * m.m44);
  669. var m44 = (mm.m14 * m.m41 + mm.m24 * m.m42 + mm.m34 * m.m43 + mm.m44 * m.m44);
  670. m.m11 = m11;
  671. m.m12 = m12;
  672. m.m13 = m13;
  673. m.m14 = m14;
  674. m.m21 = m21;
  675. m.m22 = m22;
  676. m.m23 = m23;
  677. m.m24 = m24;
  678. m.m31 = m31;
  679. m.m32 = m32;
  680. m.m33 = m33;
  681. m.m34 = m34;
  682. m.m41 = m41;
  683. m.m42 = m42;
  684. m.m43 = m43;
  685. m.m44 = m44;
  686. },
  687. perspective: function(fovy, aspect, near, far) {
  688. var top = near * Math.tan(fovy * Math.PI / 360.0);
  689. var right = top * aspect;
  690. return this.frustum(-right, right, -top, top, near, far);
  691. },
  692. ortho: function(left, right, bottom, top, near, far) {
  693. var rl = right - left;
  694. var tb = top - bottom;
  695. var fn = far - near;
  696. var m = this.$matrix;
  697. m.m11 = 2 / rl;
  698. m.m12 = 0;
  699. m.m13 = 0;
  700. m.m14 = -(right + left) / rl;
  701. m.m21 = 0;
  702. m.m22 = 2 / tb;
  703. m.m23 = 0;
  704. m.m24 = -(top + bottom) / tb;
  705. m.m31 = 0;
  706. m.m32 = 0;
  707. m.m33 = -2 / fn;
  708. m.m34 = -(far + near) / fn;
  709. m.m41 = 0;
  710. m.m42 = 0;
  711. m.m43 = 0;
  712. m.m44 = 1;
  713. },
  714. frustum: function(left, right, bottom, top, near, far) {
  715. var rl = right - left;
  716. var tb = top - bottom;
  717. var fn = far - near;
  718. var m = this.$matrix;
  719. m.m11 = (near * 2) / rl;
  720. m.m12 = 0;
  721. m.m13 = (right + left) / rl;
  722. m.m14 = 0;
  723. m.m21 = 0;
  724. m.m22 = (near * 2) / tb;
  725. m.m23 = (top + bottom) / tb;
  726. m.m24 = 0;
  727. m.m31 = 0;
  728. m.m32 = 0;
  729. m.m33 = -(far + near) / fn;
  730. m.m34 = (-2 * far * near) / fn;
  731. m.m41 = 0;
  732. m.m42 = 0;
  733. m.m43 = -1;
  734. m.m44 = 0;
  735. },
  736. getArray: function() {
  737. // this is row major order, for WebGL you'll need to transverse this
  738. var m = this.$matrix;
  739. return [m.m11, m.m12, m.m13, m.m14,
  740. m.m21, m.m22, m.m23, m.m24,
  741. m.m31, m.m32, m.m33, m.m34,
  742. m.m41, m.m42, m.m43, m.m44];
  743. },
  744. getFloat32Array: function() {
  745. return new Float32Array(this.getArray());
  746. },
  747. getColumnMajorArray: function() {
  748. // this is row major order, for WebGL you'll need to transverse this
  749. var m = this.$matrix;
  750. return [m.m11, m.m21, m.m31, m.m41,
  751. m.m12, m.m22, m.m32, m.m42,
  752. m.m13, m.m23, m.m33, m.m43,
  753. m.m14, m.m24, m.m34, m.m44];
  754. },
  755. getColumnMajorFloat32Array: function() {
  756. return new Float32Array(this.getColumnMajorArray());
  757. }
  758. };
  759. function TSUMix(a, b, x) {
  760. return a + (b - a) * x;
  761. }
  762. //sinusoidal timing function
  763. function TSUSineMap(x) {
  764. return (Math.sin(x * Math.PI - (Math.PI / 2)) + 1) * 0.5;
  765. }
  766. //function for Twist sizing
  767. function TwistFX(location, percent) {
  768. var twist = 4.0 / 10.25;
  769. var x = (1 + twist) * percent - twist * location;
  770. if (x < 0) {
  771. return 0;
  772. }
  773. else if (x > 1) {
  774. return 1;
  775. }
  776. else {
  777. return TSUSineMap(x);
  778. }
  779. }
  780. //CGAffineTransformMakeRotation
  781. function CGAffineTransformMakeRotation(angle) {
  782. var sine, consine;
  783. sine = Math.sin(angle);
  784. cosine = Math.cos(angle);
  785. return [cosine, sine, -sine, cosine, 0, 0];
  786. }
  787. //CGAffineTransformEqualToTransform
  788. function CGAffineTransformEqualToTransform(t1, t2) {
  789. return t1.a === t2.a && t1.b === t2.b && t1.c === t2.c && t1.d === t2.d && t1.tx === t2.tx && t1.ty === t2.ty;
  790. }
  791. //CATransform3DEqualToTransform
  792. function CATransform3DEqualToTransform(a, b) {
  793. var result = a[0] === b[0] && a[1] === b[1] && a[2] === b[2] && a[3] === b[3] && a[4] === b[4] && a[5] === b[5] && a[6] === b[6] && a[7] === b[7] && a[8] === b[8] && a[9] === b[9] && a[10] === b[10] && a[11] === b[11] && a[12] === b[12] && a[13] === b[13] && a[14] === b[14] && a[15] === b[15];
  794. return result;
  795. }
  796. //CGPointMake
  797. function CGPointMake(x, y) {
  798. var p = {
  799. x: x,
  800. y: y
  801. };
  802. return p;
  803. }
  804. //CGRectIntersection
  805. function CGRectIntersection(r1, r2) {
  806. var r = {
  807. "origin": {
  808. "x": 0,
  809. "y": 0
  810. },
  811. "size": {
  812. "width": 0,
  813. "height": 0
  814. }
  815. };
  816. var x1, x2, y1, y2;
  817. x1 = Math.max(r1.origin.x, r2.origin.x);
  818. x2 = Math.min(r1.origin.x + r1.size.width, r2.origin.x + r2.size.width);
  819. if (x1 > x2) {
  820. return r;
  821. }
  822. y1 = Math.max(r1.origin.y, r2.origin.y);
  823. y2 = Math.min(r1.origin.y + r1.size.height, r2.origin.y + r2.size.height);
  824. if (y1 > y2) {
  825. return r;
  826. }
  827. r.origin.x = x1;
  828. r.size.width = x2 - x1;
  829. r.origin.y = y1;
  830. r.size.height = y2 - y1;
  831. return r;
  832. }
  833. // CGRectIntegral
  834. function CGRectIntegral(rect) {
  835. var r = {
  836. "origin": {
  837. "x": 0,
  838. "y": 0
  839. },
  840. "size": {
  841. "width": 0,
  842. "height": 0
  843. }
  844. };
  845. r.origin.x = Math.floor(rect.origin.x);
  846. r.origin.y = Math.floor(rect.origin.y);
  847. r.size.width = Math.ceil(rect.origin.x + rect.size.width) - r.origin.x;
  848. r.size.height = Math.ceil(rect.origin.y + rect.size.height) - r.origin.y;
  849. return r;
  850. }
  851. // CGRectGetMinX
  852. function CGRectGetMinX(rect) {
  853. return rect.origin.x;
  854. }
  855. // CGRectGetMinY
  856. function CGRectGetMinY(rect) {
  857. return rect.origin.y;
  858. }
  859. // CGRectGetMidX
  860. function CGRectGetMidX(rect) {
  861. return rect.origin.x + rect.size.width / 2;
  862. }
  863. // CGRectGetMidY
  864. function CGRectGetMidY(rect) {
  865. return rect.origin.y + rect.size.height / 2;
  866. }
  867. // CGRectGetMaxX
  868. function CGRectGetMaxX(rect) {
  869. return rect.origin.x + rect.size.width;
  870. }
  871. // CGRectGetMaxY
  872. function CGRectGetMaxY(rect) {
  873. return rect.origin.y + rect.size.height;
  874. }
  875. // CGRectEqualToRect
  876. function CGRectEqualToRect(rect1, rect2) {
  877. return (rect1.origin.x == rect2.origin.x) && (rect1.origin.y == rect2.origin.y) && (rect1.size.width == rect2.size.width) && (rect1.size.height == rect2.size.height);
  878. }
  879. // CGRectMake
  880. function CGRectMake(x, y, width, height) {
  881. var r = {
  882. "origin": {
  883. "x": x,
  884. "y": y
  885. },
  886. "size": {
  887. "width": width,
  888. "height": height
  889. }
  890. };
  891. return r;
  892. }
  893. // CGSizeMake
  894. function CGSizeMake(width, height) {
  895. var sizeOut = {};
  896. sizeOut.width = width;
  897. sizeOut.height = height;
  898. return sizeOut;
  899. }
  900. // CGSizeEqualToSize
  901. function CGSizeEqualToSize (size1, size2) {
  902. return size1.width === size2.width && size1.height === size2.height;
  903. }
  904. // CGSizeZero
  905. var CGSizeZero = {
  906. "width": 0,
  907. "height": 0
  908. };
  909. // CGRectZero
  910. var CGRectZero = {
  911. "origin": {
  912. "x": 0,
  913. "y": 0
  914. },
  915. "size": {
  916. "width": 0,
  917. "height": 0
  918. }
  919. };
  920. // TSDRectUnit
  921. var TSDRectUnit = {
  922. "origin": {
  923. "x": 0,
  924. "y": 0
  925. },
  926. "size": {
  927. "width": 1,
  928. "height": 1
  929. }
  930. };
  931. //TSDMixFloats
  932. function TSDMixFloats(a, b, fraction) {
  933. return a * (1.0 - fraction) + b * fraction;
  934. }
  935. // TSDCenterOfRect
  936. function TSDCenterOfRect(rect) {
  937. return WebGraphics.makePoint(CGRectGetMidX(rect), CGRectGetMidY(rect));
  938. }
  939. // TSDPointFromNormalizedRect
  940. function TSDPointFromNormalizedRect(pt, rect) {
  941. return WebGraphics.makePoint(rect.origin.x + pt.x * rect.size.width, rect.origin.y + pt.y * rect.size.height);
  942. }
  943. // TSDRectWithPoints
  944. function TSDRectWithPoints(a, b) {
  945. // smallest rect enclosing two points
  946. var minX = Math.min(a.x, b.x);
  947. var maxX = Math.max(a.x, b.x);
  948. var minY = Math.min(a.y, b.y);
  949. var maxY = Math.max(a.y, b.y);
  950. return CGRectMake(minX, minY, maxX - minX, maxY - minY);
  951. }
  952. function TSDGLColor(r, g, b, a) {
  953. var color = {
  954. r: r,
  955. g: g,
  956. b: b,
  957. a: a
  958. };
  959. return color;
  960. }
  961. var TSD8bitColorDenominator = 0.003906402593851;
  962. /// Creates a TSDGLColor4f from a 32-bit BGRA-encoded unsigned int
  963. function TSDGLColor4fMakeWithUInt(anInt) {
  964. var color = WebGraphics.makePoint4D(
  965. ((anInt & 0x00ff0000) >> 16) * TSD8bitColorDenominator,
  966. ((anInt & 0x0000ff00) >> 8) * TSD8bitColorDenominator,
  967. ((anInt & 0x000000ff)) * TSD8bitColorDenominator,
  968. ((anInt & 0xff000000) >> 24) * TSD8bitColorDenominator
  969. );
  970. return color;
  971. }
  972. // TSUReverseSquare
  973. function TSUReverseSquare(x) {
  974. var reverse = 1.0 - x;
  975. return 1.0 - reverse * reverse;
  976. }
  977. window.requestAnimFrame = (function() {
  978. return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame
  979. || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function(callback, element) {
  980. window.setTimeout(callback, 1000 / 60);
  981. };
  982. })();