UNPKG

raytrace-engine

Version:

A simple CPU-based ray tracer written in **vanilla JavaScript**, rendering directly to an HTML5 `<canvas>` element — no WebGL, no external libraries.

2 lines 22.3 kB
/*! For license information please see index.js.LICENSE.txt */ !function(t,n){"object"==typeof exports&&"object"==typeof module?module.exports=n():"function"==typeof define&&define.amd?define([],n):"object"==typeof exports?exports["raytrace-engine"]=n():t["raytrace-engine"]=n()}(self,()=>(()=>{"use strict";var t={d:(n,e)=>{for(var r in e)t.o(e,r)&&!t.o(n,r)&&Object.defineProperty(n,r,{enumerable:!0,get:e[r]})},o:(t,n)=>Object.prototype.hasOwnProperty.call(t,n),r:t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})}},n={};function e(t){return e="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},e(t)}function r(){var t,n,e="function"==typeof Symbol?Symbol:{},i=e.iterator||"@@iterator",a=e.toStringTag||"@@toStringTag";function c(e,r,i,a){var c=r&&r.prototype instanceof s?r:s,l=Object.create(c.prototype);return o(l,"_invoke",function(e,r,o){var i,a,c,s=0,l=o||[],f=!1,h={p:0,n:0,v:t,a:p,f:p.bind(t,4),d:function(n,e){return i=n,a=0,c=t,h.n=e,u}};function p(e,r){for(a=e,c=r,n=0;!f&&s&&!o&&n<l.length;n++){var o,i=l[n],p=h.p,v=i[2];e>3?(o=v===r)&&(c=i[(a=i[4])?5:(a=3,3)],i[4]=i[5]=t):i[0]<=p&&((o=e<2&&p<i[1])?(a=0,h.v=r,h.n=i[1]):p<v&&(o=e<3||i[0]>r||r>v)&&(i[4]=e,i[5]=r,h.n=v,a=0))}if(o||e>1)return u;throw f=!0,r}return function(o,l,v){if(s>1)throw TypeError("Generator is already running");for(f&&1===l&&p(l,v),a=l,c=v;(n=a<2?t:c)||!f;){i||(a?a<3?(a>1&&(h.n=-1),p(a,c)):h.n=c:h.v=c);try{if(s=2,i){if(a||(o="next"),n=i[o]){if(!(n=n.call(i,c)))throw TypeError("iterator result is not an object");if(!n.done)return n;c=n.value,a<2&&(a=0)}else 1===a&&(n=i.return)&&n.call(i),a<2&&(c=TypeError("The iterator does not provide a '"+o+"' method"),a=1);i=t}else if((n=(f=h.n<0)?c:e.call(r,h))!==u)break}catch(n){i=t,a=1,c=n}finally{s=1}}return{value:n,done:f}}}(e,i,a),!0),l}var u={};function s(){}function l(){}function f(){}n=Object.getPrototypeOf;var h=[][i]?n(n([][i]())):(o(n={},i,function(){return this}),n),p=f.prototype=s.prototype=Object.create(h);function v(t){return Object.setPrototypeOf?Object.setPrototypeOf(t,f):(t.__proto__=f,o(t,a,"GeneratorFunction")),t.prototype=Object.create(p),t}return l.prototype=f,o(p,"constructor",f),o(f,"constructor",l),l.displayName="GeneratorFunction",o(f,a,"GeneratorFunction"),o(p),o(p,a,"Generator"),o(p,i,function(){return this}),o(p,"toString",function(){return"[object Generator]"}),(r=function(){return{w:c,m:v}})()}function o(t,n,e,r){var i=Object.defineProperty;try{i({},"",{})}catch(t){i=0}o=function(t,n,e,r){if(n)i?i(t,n,{value:e,enumerable:!r,configurable:!r,writable:!r}):t[n]=e;else{var a=function(n,e){o(t,n,function(t){return this._invoke(n,e,t)})};a("next",0),a("throw",1),a("return",2)}},o(t,n,e,r)}function i(t,n,e,r,o,i,a){try{var c=t[i](a),u=c.value}catch(t){return void e(t)}c.done?n(u):Promise.resolve(u).then(r,o)}function a(t){return function(){var n=this,e=arguments;return new Promise(function(r,o){var a=t.apply(n,e);function c(t){i(a,r,o,c,u,"next",t)}function u(t){i(a,r,o,c,u,"throw",t)}c(void 0)})}}function c(t,n){for(var e=0;e<n.length;e++){var r=n[e];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(t,u(r.key),r)}}function u(t){var n=function(t){if("object"!=e(t)||!t)return t;var n=t[Symbol.toPrimitive];if(void 0!==n){var r=n.call(t,"string");if("object"!=e(r))return r;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(t)}(t);return"symbol"==e(n)?n:n+""}function s(t,n,e){l(t,n),n.set(t,e)}function l(t,n){if(n.has(t))throw new TypeError("Cannot initialize the same private elements twice on an object")}function f(t,n){return t.get(p(t,n))}function h(t,n,e){return t.set(p(t,n),e),e}function p(t,n,e){if("function"==typeof t?t===n:t.has(n))return arguments.length<3?n:e;throw new TypeError("Private element is not present on this object")}t.r(n),t.d(n,{CanvasManager:()=>Y,RaytracingManager:()=>M});var v=new WeakMap,y=new WeakMap,d=new WeakMap,m=new WeakMap,g=new WeakMap,b=new WeakMap,w=new WeakMap,V=new WeakMap,x=new WeakSet,M=function(){return t=function t(n){var e;!function(t,n){if(!(t instanceof n))throw new TypeError("Cannot call a class as a function")}(this,t),l(this,e=x),e.add(this),s(this,v,void 0),s(this,y,void 0),s(this,d,void 0),s(this,m,void 0),s(this,g,void 0),s(this,b,void 0),s(this,w,void 0),s(this,V,void 0),this.canvasHeight=n.canvasHeight,this.canvasWidth=n.canvasWidth,h(v,this,1),h(y,this,this.canvasWidth/this.canvasHeight*f(v,this)),this.distanceFromCameraToViewport=n.distanceFromCameraToViewport,this.cameraPosition=n.cameraPosition,this.reflectiveRecursionLimit=n.reflectiveRecursionLimit||0,this.putPixelCallback=n.putPixelCallback||function(){console.warn("putPixelCallback is not provided to Raytracing Manager")},this.shapeData=n.shapeData&&n.shapeData.length?n.shapeData:[],this.shapeData.length||console.warn("shapeData is not provided to Raytracing Manager"),this.lightData=n.lightData&&n.lightData.length?n.lightData:[],this.lightData.length||console.warn("lightData is not provided to Raytracing Manager"),this.noIntersectionColor=n.noIntersectionColor||{r:0,g:0,b:0},n.noIntersectionColor||console.warn("noIntersectionColor is not provided to Raytracing Manager. Default Value of {r:0, g:0, b:0} is used"),h(d,this,null),h(m,this,[]),h(g,this,this.canvasHeight*this.canvasWidth/100),h(b,this,10),h(w,this,null),h(V,this,0)},n=[{key:"lookAt",value:function(t){this.stop(),h(V,this,f(V,this)+t),this.start()}},{key:"start",value:function(){var t=this;return h(m,this,[]),new Promise(function(n){var e=-t.canvasWidth/2,o=t.canvasWidth/2,i=-t.canvasHeight/2,c=t.canvasHeight/2,u=0,s=f(b,t)*f(b,t),l=Array.from({length:s},function(t,n){return n});l.sort(function(){return Math.random()-.5});var v=p(x,t,j).call(t,f(b,t)),y=function(){var d=a(r().m(function a(){var d,g;return r().w(function(r){for(;;)switch(r.n){case 0:if(!(u>=s)){r.n=1;break}return p(x,t,I).call(t),t.putPixelCallback(f(m,t).slice(0)),n(),r.a(2);case 1:return d=l[u],g=p(x,t,k).call(t,e,o,i,c,v,d,f(b,t)),r.n=2,p(x,t,P).call(t,g);case 2:u++,h(w,t,requestAnimationFrame(y));case 3:return r.a(2)}},a)}));return function(){return d.apply(this,arguments)}}();y()})}},{key:"stop",value:function(){window.cancelAnimationFrame(f(w,this)),h(w,this,null),p(x,this,I).call(this)}}],n&&c(t.prototype,n),Object.defineProperty(t,"prototype",{writable:!1}),t;var t,n}();function S(t){var n=new Blob(['function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }\n!function (t, r) {\n if ("object" == (typeof exports === "undefined" ? "undefined" : _typeof(exports)) && "object" == (typeof module === "undefined" ? "undefined" : _typeof(module))) module.exports = r();else if ("function" == typeof define && define.amd) define([], r);else {\n var e = r();\n for (var o in e) ("object" == (typeof exports === "undefined" ? "undefined" : _typeof(exports)) ? exports : t)[o] = e[o];\n }\n}(self, function () {\n return function () {\n "use strict";\n\n var t = {\n subtractVectors: function subtractVectors(t, r) {\n return {\n x: t.x - r.x,\n y: t.y - r.y,\n z: t.z - r.z\n };\n },\n addVectors: function addVectors(t, r) {\n return {\n x: t.x + r.x,\n y: t.y + r.y,\n z: t.z + r.z\n };\n },\n dotProduct: function dotProduct(t, r) {\n return t.x * r.x + t.y * r.y + t.z * r.z;\n },\n scaleVector: function scaleVector(t, r) {\n return {\n x: t.x * r,\n y: t.y * r,\n z: t.z * r\n };\n },\n magnitudeOfVector: function magnitudeOfVector(t) {\n return Math.sqrt(Math.pow(t.x, 2) + Math.pow(t.y, 2) + Math.pow(t.z, 2));\n },\n normalizeVector: function normalizeVector(t) {\n var r = this.magnitudeOfVector(t);\n return 0 === r ? t : this.scaleVector(t, 1 / r);\n },\n transformVector: function transformVector(t, r) {\n var e = t.x,\n o = t.y,\n n = t.z;\n return {\n x: e * r[0][0] + o * r[1][0] + n * r[2][0],\n y: e * r[0][1] + o * r[1][1] + n * r[2][1],\n z: e * r[0][2] + o * r[1][2] + n * r[2][2]\n };\n },\n rotateVectorAroundYaxis: function rotateVectorAroundYaxis(t, r) {\n var e = [[Math.cos(r), 0, -Math.sin(r)], [0, 1, 0], [Math.sin(r), 0, Math.cos(r)]];\n return this.transformVector(t, e);\n },\n quadraticEquationRoots: function quadraticEquationRoots(t, r, e) {\n var o = Math.pow(r, 2) - 4 * t * e;\n return o < 0 ? {\n t1: null,\n t2: null\n } : {\n t1: (-r + Math.sqrt(o)) / (2 * t),\n t2: (-r - Math.sqrt(o)) / (2 * t)\n };\n }\n };\n function r(t, r) {\n var o = "undefined" != typeof Symbol && t[Symbol.iterator] || t["@@iterator"];\n if (!o) {\n if (Array.isArray(t) || (o = function (t, r) {\n if (t) {\n if ("string" == typeof t) return e(t, r);\n var o = {}.toString.call(t).slice(8, -1);\n return "Object" === o && t.constructor && (o = t.constructor.name), "Map" === o || "Set" === o ? Array.from(t) : "Arguments" === o || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(o) ? e(t, r) : void 0;\n }\n }(t)) || r && t && "number" == typeof t.length) {\n o && (t = o);\n var _n = 0,\n i = function i() {};\n return {\n s: i,\n n: function n() {\n return _n >= t.length ? {\n done: !0\n } : {\n done: !1,\n value: t[_n++]\n };\n },\n e: function e(t) {\n throw t;\n },\n f: i\n };\n }\n throw new TypeError("Invalid attempt to iterate non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");\n }\n var c,\n a = !0,\n u = !1;\n return {\n s: function s() {\n o = o.call(t);\n },\n n: function n() {\n var t = o.next();\n return a = t.done, t;\n },\n e: function e(t) {\n u = !0, c = t;\n },\n f: function f() {\n try {\n a || null == o["return"] || o["return"]();\n } finally {\n if (u) throw c;\n }\n }\n };\n }\n function e(t, r) {\n (null == r || r > t.length) && (r = t.length);\n for (var e = 0, o = Array(r); e < r; e++) o[e] = t[e];\n return o;\n }\n var o, n, i;\n function c(r, e) {\n return t.subtractVectors(t.scaleVector(t.scaleVector(e, 2), t.dotProduct(e, r)), r);\n }\n function a(e) {\n var n = e.color,\n i = e.intersectionPoint,\n a = e.normalToShapeSurface,\n s = e.reverseDirectionVector,\n l = e.specular;\n if (!i) return n;\n var f,\n d,\n V = 0,\n v = r(o);\n try {\n for (v.s(); !(d = v.n()).done;) {\n var y = d.value;\n if ("ambient" === y.type) V += y.intensity;else {\n var p = null;\n if ("point" === y.type ? (p = t.subtractVectors(y.position, i), f = 1) : "directional" === y.type && (p = y.direction, f = Number.POSITIVE_INFINITY), null !== u({\n tMin: .001,\n tMax: f,\n originVector: i,\n directionVector: p\n }).closestShape) continue;\n var m = t.dotProduct(p, a);\n if (m > 0) {\n var h = t.magnitudeOfVector(p),\n x = t.magnitudeOfVector(a);\n V += y.intensity * (m / (h * x));\n }\n if (-1 !== l) {\n var g = c(p, a),\n b = t.dotProduct(g, s);\n if (b > 0) {\n var I = t.magnitudeOfVector(g),\n M = t.magnitudeOfVector(s);\n V += y.intensity * Math.pow(b / (I * M), l);\n }\n }\n }\n }\n } catch (t) {\n v.e(t);\n } finally {\n v.f();\n }\n return {\n r: n.r * V,\n g: n.g * V,\n b: n.b * V\n };\n }\n function u(t) {\n var e,\n o = t.tMin,\n n = t.tMax,\n c = t.originVector,\n a = t.directionVector,\n u = Number.POSITIVE_INFINITY,\n s = null,\n f = r(i);\n try {\n for (f.s(); !(e = f.n()).done;) {\n var d = e.value,\n V = l({\n originVector: c,\n directionVector: a,\n shape: d\n }),\n v = V.t1,\n y = V.t2;\n v >= o && v <= n && v < u && (u = v, s = d), y >= o && y <= n && y < u && (u = y, s = d);\n }\n } catch (t) {\n f.e(t);\n } finally {\n f.f();\n }\n return {\n closestT: u,\n closestShape: s\n };\n }\n function s(r) {\n var e,\n o = r.tMin,\n i = r.tMax,\n l = r.originVector,\n f = r.directionVector,\n d = r.recursionLimit,\n V = u({\n tMin: o,\n tMax: i,\n originVector: l,\n directionVector: f\n }),\n v = V.closestShape,\n y = V.closestT;\n if (null === v) return n;\n var p,\n m = t.addVectors(l, t.scaleVector(f, y)),\n h = v.color,\n x = t.normalizeVector(t.subtractVectors(m, v.center)),\n g = t.subtractVectors({\n x: 0,\n y: 0,\n z: 0\n }, f);\n if (d <= 0 || !v.reflective || 0 === v.reflective || v.reflective <= 0) return a({\n color: h,\n intersectionPoint: m,\n normalToShapeSurface: x,\n reverseDirectionVector: g,\n specular: null !== (p = v.specular) && void 0 !== p ? p : -1\n });\n var b = c(g, x),\n I = s({\n tMin: .001,\n tMax: Number.POSITIVE_INFINITY,\n originVector: m,\n directionVector: b,\n recursionLimit: d - 1\n });\n return a({\n color: {\n r: h.r * (1 - v.reflective) + I.r * v.reflective,\n g: h.g * (1 - v.reflective) + I.g * v.reflective,\n b: h.b * (1 - v.reflective) + I.b * v.reflective\n },\n intersectionPoint: m,\n normalToShapeSurface: x,\n reverseDirectionVector: g,\n specular: null !== (e = v.specular) && void 0 !== e ? e : -1\n });\n }\n function l(r) {\n var e = r.directionVector,\n o = r.originVector,\n n = r.shape,\n i = n.radius,\n c = t.subtractVectors(o, n.center),\n a = t.dotProduct(e, e),\n u = 2 * t.dotProduct(c, e),\n s = t.dotProduct(c, c) - Math.pow(i, 2),\n l = t.quadraticEquationRoots(a, u, s),\n f = l.t1,\n d = l.t2;\n return {\n t1: null != f ? f : Number.POSITIVE_INFINITY,\n t2: null != d ? d : Number.POSITIVE_INFINITY\n };\n }\n return self.onmessage = function (r) {\n var e = r.data,\n c = e.shapeData,\n a = e.lightData,\n u = e.noIntersectionColor,\n l = e.tMin,\n f = e.tMax,\n d = e.originVector,\n V = e.pixels,\n v = e.ratioW,\n y = e.ratioH,\n p = e.distanceFromCameraToViewport,\n m = e.recursionLimit,\n h = e.cameraAngle;\n o = a, n = u, i = c;\n var x = V.map(function (r) {\n var e = r.x,\n o = r.y,\n n = t.subtractVectors({\n x: e * v,\n y: o * y,\n z: p\n }, d);\n return 0 !== h && (n = t.rotateVectorAroundYaxis(n, h)), {\n x: e,\n y: o,\n color: s({\n tMin: l,\n tMax: f,\n originVector: d,\n directionVector: n,\n recursionLimit: m\n })\n };\n });\n self.postMessage(x);\n }, {};\n }();\n});'],{type:"application/javascript"}),e=URL.createObjectURL(n);h(d,this,Array.from({length:t},function(){return new Worker(e,{type:"module"})}))}function I(){f(d,this)&&f(d,this).forEach(function(t){return t.terminate()}),h(d,this,null)}function P(t){return T.apply(this,arguments)}function T(){return(T=a(r().m(function t(n){var e,o,i,a,c,u=this;return r().w(function(t){for(;;)switch(t.n){case 0:return e=navigator.hardwareConcurrency||4,f(d,this)||p(x,this,S).call(this,e),o=f(y,this)/this.canvasWidth,i=f(v,this)/this.canvasHeight,a=Math.ceil(n.length/e),c=Array.from({length:e},function(t,e){return n.slice(e*a,(e+1)*a)}),t.n=1,Promise.all(c.map(function(t,n){return new Promise(function(e,r){var a=f(d,u)[n];a.onerror=function(t){return r(t)},a.onmessage=function(t){return e(t.data)},a.postMessage({shapeData:u.shapeData,lightData:u.lightData,noIntersectionColor:u.noIntersectionColor,tMin:1,tMax:Number.POSITIVE_INFINITY,originVector:u.cameraPosition,pixels:t,ratioW:o,ratioH:i,distanceFromCameraToViewport:u.distanceFromCameraToViewport,recursionLimit:u.reflectiveRecursionLimit,cameraAngle:f(V,u)})})}));case 1:t.v.flat().forEach(function(t){f(m,u).push(t);var n=f(m,u).length;n>=f(g,u)&&(u.putPixelCallback(f(m,u).slice(0,n)),h(m,u,f(m,u).slice(n)))});case 2:return t.a(2)}},t,this)}))).apply(this,arguments)}function k(t,n,e,r,o,i,a){for(var c=[],u=o[i],s=u.x,l=u.y,f=t;f<n;f++)for(var h=e;h<r;h++)(f-t)%a===s&&(h-e)%a===l&&c.push({x:f,y:h});return c}function j(t){for(var n=[],e=0;e<t;e++)for(var r=0;r<t;r++)n.push({x:r,y:e});return n}function O(t){return O="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},O(t)}function C(t,n){(null==n||n>t.length)&&(n=t.length);for(var e=0,r=Array(n);e<n;e++)r[e]=t[e];return r}function E(t,n){for(var e=0;e<n.length;e++){var r=n[e];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(t,D(r.key),r)}}function D(t){var n=function(t){if("object"!=O(t)||!t)return t;var n=t[Symbol.toPrimitive];if(void 0!==n){var e=n.call(t,"string");if("object"!=O(e))return e;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(t)}(t);return"symbol"==O(n)?n:n+""}function A(t,n,e){W(t,n),n.set(t,e)}function W(t,n){if(n.has(t))throw new TypeError("Cannot initialize the same private elements twice on an object")}function _(t,n){return t.get(N(t,n))}function z(t,n,e){return t.set(N(t,n),e),e}function N(t,n,e){if("function"==typeof t?t===n:t.has(n))return arguments.length<3?n:e;throw new TypeError("Private element is not present on this object")}var F=new WeakMap,R=new WeakMap,L=new WeakMap,q=new WeakMap,H=new WeakSet,Y=function(){return t=function t(n){var e,r=n.target,o=n.height,i=n.width;!function(t,n){if(!(t instanceof n))throw new TypeError("Cannot call a class as a function")}(this,t),W(this,e=H),e.add(this),A(this,F,void 0),A(this,R,void 0),A(this,L,void 0),A(this,q,void 0),z(R,this,null),z(F,this,null),this.height=o,this.width=i,this.target=r,z(L,this,null),z(q,this,null)},n=[{key:"changeDimensions",value:function(t,n){this.height=this.height,this.width=this.width}},{key:"changeTarget",value:function(t){this.target=t}},{key:"showCanvas",value:function(){z(R,this,document.createElement("canvas")),z(F,this,_(R,this).getContext("2d")),this.target.append(_(R,this)),_(R,this).height=this.height,_(R,this).width=this.width,_(R,this).style.height=this.height+"px",_(R,this).style.width=this.width+"px",z(L,this,_(F,this).getImageData(0,0,this.width,this.height))}},{key:"enablePointerMovements",value:function(t){_(R,this)&&(z(q,this,new AbortController),_(R,this).addEventListener("pointerdown",function(n){t.pointerdown(n)},{signal:_(q,this).signal}),_(R,this).addEventListener("pointermove",function(n){t.pointermove(n)},{signal:_(q,this).signal}),_(R,this).addEventListener("pointerup",function(n){t.pointerup(n)},{signal:_(q,this).signal}))}},{key:"disablePointerMovements",value:function(){_(q,this).abort(),z(q,this,null)}},{key:"putPixel",value:function(t){var n,e=function(t,n){var e="undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(!e){if(Array.isArray(t)||(e=function(t,n){if(t){if("string"==typeof t)return C(t,n);var e={}.toString.call(t).slice(8,-1);return"Object"===e&&t.constructor&&(e=t.constructor.name),"Map"===e||"Set"===e?Array.from(t):"Arguments"===e||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(e)?C(t,n):void 0}}(t))||n&&t&&"number"==typeof t.length){e&&(t=e);var r=0,o=function(){};return{s:o,n:function(){return r>=t.length?{done:!0}:{done:!1,value:t[r++]}},e:function(t){throw t},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var i,a=!0,c=!1;return{s:function(){e=e.call(t)},n:function(){var t=e.next();return a=t.done,t},e:function(t){c=!0,i=t},f:function(){try{a||null==e.return||e.return()}finally{if(c)throw i}}}}(t);try{for(e.s();!(n=e.n()).done;){var r=n.value,o=r.x,i=r.y,a=r.color,c=N(H,this,G).call(this,o,i),u=c.x,s=c.y,l=a.r,f=a.g,h=a.b,p=4*(s*this.width+u);_(L,this).data[p]=l,_(L,this).data[p+1]=f,_(L,this).data[p+2]=h,_(L,this).data[p+3]=255}}catch(t){e.e(t)}finally{e.f()}t.length&&_(F,this).putImageData(_(L,this),0,0)}},{key:"clearCanvas",value:function(){_(R,this)&&_(F,this).clearRect(0,0,this.width,this.height)}},{key:"destroyCanvas",value:function(){_(R,this)&&(_(R,this).remove(),this.disableMouseMovements()),z(R,this,null)}}],n&&E(t.prototype,n),Object.defineProperty(t,"prototype",{writable:!1}),t;var t,n}();function G(t,n){return{x:this.width/2+t,y:this.height/2-n}}return n})());