tela.js 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (178) hide show
  1. package/.eslintrc.yml +8 -0
  2. package/LICENSE +201 -0
  3. package/README.md +54 -0
  4. package/assets/bunny.obj +7474 -0
  5. package/assets/expand.svg +1 -0
  6. package/assets/great.jpg +0 -0
  7. package/assets/kakashi.jpg +0 -0
  8. package/assets/spot.obj +11999 -0
  9. package/assets/spot.png +0 -0
  10. package/assets/torus.obj +3137 -0
  11. package/assets/x.svg +1 -0
  12. package/bun.lockb +0 -0
  13. package/bundle.js +39 -0
  14. package/dist/node/index.js +37048 -0
  15. package/dist/web/index.js +1511 -0
  16. package/index.css +129 -0
  17. package/index.html +19 -0
  18. package/index.js +534 -0
  19. package/package.json +40 -0
  20. package/src/Animation/Animation.js +61 -0
  21. package/src/Box/Box.js +105 -0
  22. package/src/Camera/Camera.js +133 -0
  23. package/src/Canvas/Canvas.js +203 -0
  24. package/src/Canvas/README.md +83 -0
  25. package/src/Color/Color.js +77 -0
  26. package/src/DomBuilder/DomBuilder.js +126 -0
  27. package/src/IO/IO.js +120 -0
  28. package/src/Image/Image.js +138 -0
  29. package/src/Image/README.md +33 -0
  30. package/src/Monads/Monads.js +28 -0
  31. package/src/Ray/Ray.js +7 -0
  32. package/src/Scene/Mesh.js +103 -0
  33. package/src/Scene/NaiveScene.js +77 -0
  34. package/src/Scene/Point.js +109 -0
  35. package/src/Scene/PointCloud.js +51 -0
  36. package/src/Scene/Scene.js +200 -0
  37. package/src/Stream/Stream.js +10 -0
  38. package/src/Utils/Constants.js +1 -0
  39. package/src/Utils/Math.js +65 -0
  40. package/src/Utils/Utils.js +39 -0
  41. package/src/Vector/Vector.js +495 -0
  42. package/src/index.js +32 -0
  43. package/src/index.node.js +5 -0
  44. package/test/node/amazing_shader.js +56 -0
  45. package/test/node/bunny.js +55 -0
  46. package/test/node/bunny_parallel.js +102 -0
  47. package/test/node/image2rgb.js +57 -0
  48. package/test/node/image_test.js +38 -0
  49. package/test/node/lorentz.js +0 -0
  50. package/test/web/amazing_shader.js +60 -0
  51. package/test/web/amazing_shader_2.js +54 -0
  52. package/test/web/bunny.js +72 -0
  53. package/test/web/image2rgb.js +77 -0
  54. package/test/web/interactive_wave.js +108 -0
  55. package/test/web/lorenz.js +60 -0
  56. package/test/web/mandelbrot.js +59 -0
  57. package/test/web/rotating_grid.js +62 -0
  58. package/test/web/signed_bunny.js +139 -0
  59. package/test/web/signed_distance.js +95 -0
  60. package/test/web/simple_animation.js +39 -0
  61. package/test/web/simple_shader.js +14 -0
  62. package/test/web/six_spheres.js +102 -0
  63. package/test/web/wave_equation.js +93 -0
  64. package/vs-monaco/package/LICENSE +21 -0
  65. package/vs-monaco/package/ThirdPartyNotices.txt +448 -0
  66. package/vs-monaco/package/min/vs/base/browser/ui/codicons/codicon/codicon.ttf +0 -0
  67. package/vs-monaco/package/min/vs/base/common/worker/simpleWorker.nls.de.js +8 -0
  68. package/vs-monaco/package/min/vs/base/common/worker/simpleWorker.nls.es.js +8 -0
  69. package/vs-monaco/package/min/vs/base/common/worker/simpleWorker.nls.fr.js +8 -0
  70. package/vs-monaco/package/min/vs/base/common/worker/simpleWorker.nls.it.js +8 -0
  71. package/vs-monaco/package/min/vs/base/common/worker/simpleWorker.nls.ja.js +8 -0
  72. package/vs-monaco/package/min/vs/base/common/worker/simpleWorker.nls.js +8 -0
  73. package/vs-monaco/package/min/vs/base/common/worker/simpleWorker.nls.ko.js +8 -0
  74. package/vs-monaco/package/min/vs/base/common/worker/simpleWorker.nls.ru.js +8 -0
  75. package/vs-monaco/package/min/vs/base/common/worker/simpleWorker.nls.zh-cn.js +8 -0
  76. package/vs-monaco/package/min/vs/base/common/worker/simpleWorker.nls.zh-tw.js +8 -0
  77. package/vs-monaco/package/min/vs/base/worker/workerMain.js +27 -0
  78. package/vs-monaco/package/min/vs/basic-languages/abap/abap.js +10 -0
  79. package/vs-monaco/package/min/vs/basic-languages/apex/apex.js +10 -0
  80. package/vs-monaco/package/min/vs/basic-languages/azcli/azcli.js +10 -0
  81. package/vs-monaco/package/min/vs/basic-languages/bat/bat.js +10 -0
  82. package/vs-monaco/package/min/vs/basic-languages/bicep/bicep.js +11 -0
  83. package/vs-monaco/package/min/vs/basic-languages/cameligo/cameligo.js +10 -0
  84. package/vs-monaco/package/min/vs/basic-languages/clojure/clojure.js +10 -0
  85. package/vs-monaco/package/min/vs/basic-languages/coffee/coffee.js +10 -0
  86. package/vs-monaco/package/min/vs/basic-languages/cpp/cpp.js +10 -0
  87. package/vs-monaco/package/min/vs/basic-languages/csharp/csharp.js +10 -0
  88. package/vs-monaco/package/min/vs/basic-languages/csp/csp.js +10 -0
  89. package/vs-monaco/package/min/vs/basic-languages/css/css.js +12 -0
  90. package/vs-monaco/package/min/vs/basic-languages/cypher/cypher.js +10 -0
  91. package/vs-monaco/package/min/vs/basic-languages/dart/dart.js +10 -0
  92. package/vs-monaco/package/min/vs/basic-languages/dockerfile/dockerfile.js +10 -0
  93. package/vs-monaco/package/min/vs/basic-languages/ecl/ecl.js +10 -0
  94. package/vs-monaco/package/min/vs/basic-languages/elixir/elixir.js +10 -0
  95. package/vs-monaco/package/min/vs/basic-languages/flow9/flow9.js +10 -0
  96. package/vs-monaco/package/min/vs/basic-languages/freemarker2/freemarker2.js +12 -0
  97. package/vs-monaco/package/min/vs/basic-languages/fsharp/fsharp.js +10 -0
  98. package/vs-monaco/package/min/vs/basic-languages/go/go.js +10 -0
  99. package/vs-monaco/package/min/vs/basic-languages/graphql/graphql.js +10 -0
  100. package/vs-monaco/package/min/vs/basic-languages/handlebars/handlebars.js +10 -0
  101. package/vs-monaco/package/min/vs/basic-languages/hcl/hcl.js +10 -0
  102. package/vs-monaco/package/min/vs/basic-languages/html/html.js +10 -0
  103. package/vs-monaco/package/min/vs/basic-languages/ini/ini.js +10 -0
  104. package/vs-monaco/package/min/vs/basic-languages/java/java.js +10 -0
  105. package/vs-monaco/package/min/vs/basic-languages/javascript/javascript.js +10 -0
  106. package/vs-monaco/package/min/vs/basic-languages/julia/julia.js +10 -0
  107. package/vs-monaco/package/min/vs/basic-languages/kotlin/kotlin.js +10 -0
  108. package/vs-monaco/package/min/vs/basic-languages/less/less.js +11 -0
  109. package/vs-monaco/package/min/vs/basic-languages/lexon/lexon.js +10 -0
  110. package/vs-monaco/package/min/vs/basic-languages/liquid/liquid.js +10 -0
  111. package/vs-monaco/package/min/vs/basic-languages/lua/lua.js +10 -0
  112. package/vs-monaco/package/min/vs/basic-languages/m3/m3.js +10 -0
  113. package/vs-monaco/package/min/vs/basic-languages/markdown/markdown.js +10 -0
  114. package/vs-monaco/package/min/vs/basic-languages/mdx/mdx.js +10 -0
  115. package/vs-monaco/package/min/vs/basic-languages/mips/mips.js +10 -0
  116. package/vs-monaco/package/min/vs/basic-languages/msdax/msdax.js +10 -0
  117. package/vs-monaco/package/min/vs/basic-languages/mysql/mysql.js +10 -0
  118. package/vs-monaco/package/min/vs/basic-languages/objective-c/objective-c.js +10 -0
  119. package/vs-monaco/package/min/vs/basic-languages/pascal/pascal.js +10 -0
  120. package/vs-monaco/package/min/vs/basic-languages/pascaligo/pascaligo.js +10 -0
  121. package/vs-monaco/package/min/vs/basic-languages/perl/perl.js +10 -0
  122. package/vs-monaco/package/min/vs/basic-languages/pgsql/pgsql.js +10 -0
  123. package/vs-monaco/package/min/vs/basic-languages/php/php.js +10 -0
  124. package/vs-monaco/package/min/vs/basic-languages/pla/pla.js +10 -0
  125. package/vs-monaco/package/min/vs/basic-languages/postiats/postiats.js +10 -0
  126. package/vs-monaco/package/min/vs/basic-languages/powerquery/powerquery.js +10 -0
  127. package/vs-monaco/package/min/vs/basic-languages/powershell/powershell.js +10 -0
  128. package/vs-monaco/package/min/vs/basic-languages/protobuf/protobuf.js +11 -0
  129. package/vs-monaco/package/min/vs/basic-languages/pug/pug.js +10 -0
  130. package/vs-monaco/package/min/vs/basic-languages/python/python.js +10 -0
  131. package/vs-monaco/package/min/vs/basic-languages/qsharp/qsharp.js +10 -0
  132. package/vs-monaco/package/min/vs/basic-languages/r/r.js +10 -0
  133. package/vs-monaco/package/min/vs/basic-languages/razor/razor.js +10 -0
  134. package/vs-monaco/package/min/vs/basic-languages/redis/redis.js +10 -0
  135. package/vs-monaco/package/min/vs/basic-languages/redshift/redshift.js +10 -0
  136. package/vs-monaco/package/min/vs/basic-languages/restructuredtext/restructuredtext.js +10 -0
  137. package/vs-monaco/package/min/vs/basic-languages/ruby/ruby.js +10 -0
  138. package/vs-monaco/package/min/vs/basic-languages/rust/rust.js +10 -0
  139. package/vs-monaco/package/min/vs/basic-languages/sb/sb.js +10 -0
  140. package/vs-monaco/package/min/vs/basic-languages/scala/scala.js +10 -0
  141. package/vs-monaco/package/min/vs/basic-languages/scheme/scheme.js +10 -0
  142. package/vs-monaco/package/min/vs/basic-languages/scss/scss.js +12 -0
  143. package/vs-monaco/package/min/vs/basic-languages/shell/shell.js +10 -0
  144. package/vs-monaco/package/min/vs/basic-languages/solidity/solidity.js +10 -0
  145. package/vs-monaco/package/min/vs/basic-languages/sophia/sophia.js +10 -0
  146. package/vs-monaco/package/min/vs/basic-languages/sparql/sparql.js +10 -0
  147. package/vs-monaco/package/min/vs/basic-languages/sql/sql.js +10 -0
  148. package/vs-monaco/package/min/vs/basic-languages/st/st.js +10 -0
  149. package/vs-monaco/package/min/vs/basic-languages/swift/swift.js +13 -0
  150. package/vs-monaco/package/min/vs/basic-languages/systemverilog/systemverilog.js +10 -0
  151. package/vs-monaco/package/min/vs/basic-languages/tcl/tcl.js +10 -0
  152. package/vs-monaco/package/min/vs/basic-languages/twig/twig.js +10 -0
  153. package/vs-monaco/package/min/vs/basic-languages/typescript/typescript.js +10 -0
  154. package/vs-monaco/package/min/vs/basic-languages/vb/vb.js +10 -0
  155. package/vs-monaco/package/min/vs/basic-languages/wgsl/wgsl.js +307 -0
  156. package/vs-monaco/package/min/vs/basic-languages/xml/xml.js +10 -0
  157. package/vs-monaco/package/min/vs/basic-languages/yaml/yaml.js +10 -0
  158. package/vs-monaco/package/min/vs/editor/editor.main.css +6 -0
  159. package/vs-monaco/package/min/vs/editor/editor.main.js +745 -0
  160. package/vs-monaco/package/min/vs/editor/editor.main.nls.de.js +31 -0
  161. package/vs-monaco/package/min/vs/editor/editor.main.nls.es.js +31 -0
  162. package/vs-monaco/package/min/vs/editor/editor.main.nls.fr.js +29 -0
  163. package/vs-monaco/package/min/vs/editor/editor.main.nls.it.js +29 -0
  164. package/vs-monaco/package/min/vs/editor/editor.main.nls.ja.js +31 -0
  165. package/vs-monaco/package/min/vs/editor/editor.main.nls.js +29 -0
  166. package/vs-monaco/package/min/vs/editor/editor.main.nls.ko.js +29 -0
  167. package/vs-monaco/package/min/vs/editor/editor.main.nls.ru.js +31 -0
  168. package/vs-monaco/package/min/vs/editor/editor.main.nls.zh-cn.js +31 -0
  169. package/vs-monaco/package/min/vs/editor/editor.main.nls.zh-tw.js +29 -0
  170. package/vs-monaco/package/min/vs/language/css/cssMode.js +13 -0
  171. package/vs-monaco/package/min/vs/language/css/cssWorker.js +81 -0
  172. package/vs-monaco/package/min/vs/language/html/htmlMode.js +13 -0
  173. package/vs-monaco/package/min/vs/language/html/htmlWorker.js +453 -0
  174. package/vs-monaco/package/min/vs/language/json/jsonMode.js +15 -0
  175. package/vs-monaco/package/min/vs/language/json/jsonWorker.js +36 -0
  176. package/vs-monaco/package/min/vs/language/typescript/tsMode.js +20 -0
  177. package/vs-monaco/package/min/vs/language/typescript/tsWorker.js +37016 -0
  178. package/vs-monaco/package/min/vs/loader.js +11 -0
@@ -0,0 +1,126 @@
1
+ const SVG_URL = "http://www.w3.org/2000/svg";
2
+ const SVG_TAGS = [
3
+ "svg",
4
+ "g",
5
+ "circle",
6
+ "ellipse",
7
+ "line",
8
+ "path",
9
+ "polygon",
10
+ "polyline",
11
+ "rect",
12
+ ];
13
+
14
+ class DomBuilder {
15
+ constructor(element) {
16
+ this.element = element;
17
+ }
18
+
19
+ attr(name, value) {
20
+ this.element.setAttribute(name, value);
21
+ return this;
22
+ }
23
+
24
+ style(styleStr) {
25
+ this.element.setAttribute("style", styleStr);
26
+ return this;
27
+ }
28
+ /**
29
+ *
30
+ * @param {Array<DOM | DOMBuilder>} element
31
+ */
32
+ appendChild(...elements) {
33
+ elements.forEach(e => {
34
+ if (isElement(e)) {
35
+ this.element.appendChild(e);
36
+ } else if (isPromise(e)) {
37
+ e.then(actualElem => this.appendChild(actualElem));
38
+ } else {
39
+ this.element.appendChild(e.build());
40
+ }
41
+ })
42
+ return this;
43
+ }
44
+
45
+ /**
46
+ *
47
+ * @param {String || Promise<String>} value
48
+ * @returns DOMBuilder
49
+ */
50
+ inner(value) {
51
+ if (isPromise(value)) {
52
+ value.then(v => this.element.innerHTML = v);
53
+ } else {
54
+ this.element.innerHTML = value;
55
+ }
56
+ return this;
57
+ }
58
+
59
+ removeChildren() {
60
+ while (this.element.firstChild) {
61
+ this.element.removeChild(this.element.lastChild);
62
+ }
63
+ return this;
64
+ }
65
+
66
+ html(value) {
67
+ return this.inner(value);
68
+ }
69
+
70
+ event(eventName, lambda) {
71
+ this.element.addEventListener(eventName, lambda);
72
+ return this;
73
+ }
74
+
75
+ build() {
76
+ return this.element;
77
+ }
78
+
79
+ addClass(className) {
80
+ if (!className || className === "") return this;
81
+ this.element.classList.add(...className.split(" "));
82
+ return this;
83
+ }
84
+
85
+ removeClass(className) {
86
+ this.element.classList.remove(className);
87
+ return this;
88
+ }
89
+
90
+
91
+ /**
92
+ * @param {String | DOM} elem
93
+ */
94
+ static of(elem) {
95
+ if (isElement(elem)) {
96
+ return new DomBuilder(elem);
97
+ }
98
+ const isSvg = SVG_TAGS.includes(elem);
99
+ const element = isSvg ?
100
+ document.createElementNS(SVG_URL, elem) :
101
+ document.createElement(elem);
102
+ // if (isSvg) element.setAttribute("xmlns", SVG_URL);
103
+ return new DomBuilder(element);
104
+ }
105
+
106
+ static ofId(id) {
107
+ return new DomBuilder(document.getElementById(id));
108
+ }
109
+ }
110
+
111
+ //Returns true if it is a DOM element
112
+ function isElement(o) {
113
+ return typeof HTMLElement === "object"
114
+ ? o instanceof HTMLElement //DOM2
115
+ : o &&
116
+ typeof o === "object" &&
117
+ o !== null &&
118
+ o.nodeType === 1 &&
119
+ typeof o.nodeName === "string";
120
+ }
121
+
122
+ function isPromise(o) {
123
+ return o instanceof Promise;
124
+ }
125
+
126
+ export default DomBuilder;
package/src/IO/IO.js ADDED
@@ -0,0 +1,120 @@
1
+ import { writeFileSync, unlinkSync } from "fs";
2
+ import { execSync, spawn } from "child_process";
3
+ import Jimp from "jimp";
4
+ import Image from "../Image/Image";
5
+ import Color from "../Color/Color";
6
+
7
+
8
+ export function saveImageToFile(fileAddress, image) {
9
+ const { fileName, extension } = getFileNameAndExtensionFromAddress(fileAddress);
10
+ const ppmName = `${fileName}.ppm`;
11
+ writeFileSync(ppmName, createPPMFromFromImage(image));
12
+ if (extension !== "ppm") {
13
+ execSync(`ffmpeg -i ${ppmName} ${fileName}.${extension}`);
14
+ unlinkSync(ppmName)
15
+ }
16
+ }
17
+
18
+ function getFileNameAndExtensionFromAddress(address) {
19
+ const lastDotIndex = address.lastIndexOf(".");
20
+ const fileName = address.slice(0, lastDotIndex);
21
+ const extension = address.slice(lastDotIndex + 1);
22
+ return { fileName, extension };
23
+ }
24
+
25
+ export function readImageFrom(src) {
26
+ const { fileName, extension } = getFileNameAndExtensionFromAddress(src);
27
+ execSync(`ffmpeg -i ${src} ${fileName}.${extension}`);
28
+ readFileSync()
29
+ return new Promise((resolve, reject) => {
30
+ Jimp.read(src, (error, image) => {
31
+ if (error) {
32
+ return reject(error);
33
+ }
34
+ const width = image.bitmap.width;
35
+ const height = image.bitmap.height;
36
+
37
+ const img = Image.ofSize(width, height);
38
+
39
+ img.map((i, j) => {
40
+
41
+ const color = Jimp.intToRGBA(image.getPixelColor(x, y));
42
+ return Color.ofRGB(color.r, color.g, color.b);
43
+ })
44
+ resolve(img);
45
+ })
46
+ });
47
+ }
48
+
49
+ export function createPPMFromFromImage(image) {
50
+ const width = image.width;
51
+ const height = image.height;
52
+ const pixelData = image.toArray();
53
+ const MAX_8_BIT = 255;
54
+ let file = `P3\n${width} ${height}\n${MAX_8_BIT}\n`;
55
+ for (let i = 0; i < pixelData.length; i += 4) {
56
+ file += `${pixelData[i]} ${pixelData[i + 1]} ${pixelData[i + 2]}\n`;
57
+ }
58
+ return file;
59
+ }
60
+
61
+ export function saveStreamToFile(fileAddress, streamWithImages, { imageGetter = s => s.image, fps }) {
62
+ const { fileName, extension } = getFileNameAndExtensionFromAddress(fileAddress);
63
+ let ite = 0;
64
+ let time = 0;
65
+ let timeCheck = performance.now();
66
+ return {
67
+ until: streamStatePredicate => {
68
+ let s = streamWithImages;
69
+ while (streamStatePredicate(s.head)) {
70
+ const image = imageGetter(s.head);
71
+ writeFileSync(`${fileName}_${ite++}.ppm`, createPPMFromFromImage(image));
72
+ const newTimeCheck = performance.now();
73
+ time += (newTimeCheck - timeCheck) * 1e-3;
74
+ timeCheck = performance.now();
75
+ s = s.tail;
76
+ }
77
+ if (!fps) fps = ite / time;
78
+ execSync(`ffmpeg -framerate ${fps} -i ${fileName}_%d.ppm ${fileName}.${extension}`);
79
+ for (let i = 0; i < ite; i++) {
80
+ unlinkSync(`${fileName}_${i}.ppm`);
81
+ }
82
+ }
83
+ }
84
+ }
85
+
86
+ export function saveParallelToFile(fileAddress, arrayWithImageProducers, { fps }) {
87
+ const { fileName, extension } = getFileNameAndExtensionFromAddress(fileAddress);
88
+ const times = [];
89
+ const promises = arrayWithImageProducers.map((imageProducers, i) => {
90
+ const spawnFile = "IO_parallel" + i + ".js";
91
+ writeFileSync(spawnFile, `
92
+ import { writeFileSync, unlinkSync } from "fs";
93
+ ${createPPMFromFromImage.toString()}
94
+ ${imageProducers}
95
+ images.forEach()
96
+
97
+ `);
98
+ return new Promise(resolve => {
99
+ const process = spawn(`bun ${spawnFile}`)
100
+ process.on("exit", () => {
101
+ resolve();
102
+ })
103
+ });
104
+ })
105
+ Promise.all(promises)
106
+ .then(groupOfImages => {
107
+ let n = 0;
108
+ groupOfImages.forEach(images =>
109
+ images.forEach(image => {
110
+ console.log("Image generated", n)
111
+ writeFileSync(`${fileName}_${n++}.ppm`, createPPMFromFromImage(image));
112
+ })
113
+ )
114
+ if (!fps) fps = Math.floor(1 / (times.reduce((e, t) => e + t, 0) / n));
115
+ execSync(`ffmpeg -framerate ${fps} -i ${fileName}_%d.ppm ${fileName}.${extension}`);
116
+ for (let i = 0; i < n; i++) {
117
+ unlinkSync(`${fileName}_${i}.ppm`);
118
+ }
119
+ })
120
+ }
@@ -0,0 +1,138 @@
1
+ import Color from "../Color/Color.js";
2
+ import Jimp from "jimp";
3
+
4
+ export default class Image {
5
+
6
+ constructor(width, height) {
7
+ this._width = width;
8
+ this._height = height;
9
+ this._image = new Array(this._width * this._height)
10
+ .fill(() => Color.ofRGB());
11
+ }
12
+
13
+ get width() {
14
+ return this._width;
15
+ }
16
+
17
+ get height() {
18
+ return this._height;
19
+ }
20
+
21
+ /**
22
+ * color: Color
23
+ */
24
+ fill(color) {
25
+ return this._image.map(() => color);
26
+ }
27
+
28
+ paint() {
29
+ // to implement the same interface as canvas
30
+ return this;
31
+ }
32
+
33
+ /**
34
+ * lambda: (x: Number, y: Number) => Color
35
+ */
36
+ map(lambda) {
37
+ const n = this._image.length;
38
+ const w = this._width;
39
+ const h = this._height;
40
+ for (let k = 0; k < n; k++) {
41
+ const i = Math.floor(k / w);
42
+ const j = k % w;
43
+ const x = j;
44
+ const y = h - 1 - i;
45
+ this._image[k] = lambda(x, y);
46
+ }
47
+ return this;
48
+ }
49
+
50
+ setPxl(x, y, color) {
51
+ const w = this._width;
52
+ const h = this._height;
53
+ const i = h - 1 - y;
54
+ const j = x;
55
+ let index = w * i + j;
56
+ this._image[index] = color;
57
+ return this;
58
+ }
59
+
60
+ getPxl(x, y) {
61
+ const w = this._width;
62
+ const h = this._height;
63
+ const i = h - 1 - y;
64
+ const j = x;
65
+ let index = w * i + j;
66
+ return this._image[index];
67
+ }
68
+
69
+ array() {
70
+ return this.toArray();
71
+ }
72
+
73
+ toArray() {
74
+ const w = this._width;
75
+ const h = this._height;
76
+ const imageData = new Uint8Array(this._width * this._height * 4);
77
+
78
+ for (let i = 0; i < h; i++) {
79
+ for (let j = 0; j < w; j++) {
80
+ let index = (w * i + j);
81
+ const color = this._image[index];
82
+ index <<= 2; // multiply by 4
83
+ imageData[index] = color.red * 255;
84
+ imageData[index + 1] = color.green * 255;
85
+ imageData[index + 2] = color.blue * 255;
86
+ imageData[index + 3] = 255;
87
+ }
88
+ }
89
+ return imageData;
90
+ }
91
+
92
+ static ofUrl(url) {
93
+ return new Promise((resolve, reject) => {
94
+ Jimp.read(src, (error, image) => {
95
+ if (error) {
96
+ return reject(error);
97
+ }
98
+ const width = image.bitmap.width;
99
+ const height = image.bitmap.height;
100
+
101
+ const img = Image.ofSize(width, height);
102
+
103
+ img.map((i, j) => {
104
+
105
+ const color = Jimp.intToRGBA(image.getPixelColor(x, y));
106
+ return Color.ofRGB(color.r, color.g, color.b);
107
+ })
108
+ resolve(img);
109
+ })
110
+ });
111
+ }
112
+
113
+ static ofSize(width, height) {
114
+ return new Image(width, height);
115
+ }
116
+
117
+ static ofDOM(canvasDOM) {
118
+ const ctx = canvasDOM.getContext("2d", { willReadFrequently: true });
119
+ const w = canvasDOM.width;
120
+ const h = canvasDOM.height;
121
+ const imageData = ctx.getImageData(0, 0, w, h);
122
+ const data = imageData.data;
123
+ const image = Image.ofSize(w, h)
124
+ for (let i = 0; i < data.length; i += 4) {
125
+ const color = Color.ofRGB(data[i] / 255, data[i + 1] / 255, data[i + 2] / 255);
126
+ image._image[Math.floor(i / 4)] = color;
127
+ }
128
+ }
129
+
130
+ static ofCanvas(canvas) {
131
+ const w = canvas.width;
132
+ const h = canvas.height;
133
+ return Image.ofSize(w, h)
134
+ .map((x, y) => {
135
+ return canvas.get(x, y);
136
+ })
137
+ }
138
+ }
@@ -0,0 +1,33 @@
1
+ # Image.js
2
+ Image is a object that represents a single image
3
+
4
+ ```
5
+ Image: Array<Color>
6
+ ```
7
+ Image original coordinates:
8
+
9
+ ```
10
+ 0 W-1
11
+ +-------------> y
12
+ |
13
+ |
14
+ | *
15
+ |
16
+ |
17
+ v x
18
+
19
+ H-1
20
+
21
+ ```
22
+
23
+ The client side coordinates are:
24
+
25
+ ```
26
+ ^ y H-1
27
+ |
28
+ | *
29
+ |
30
+ |
31
+ |
32
+ 0-------------> x W-1
33
+ ```
@@ -0,0 +1,28 @@
1
+ export function some(x) {
2
+ const object = {
3
+ map: f => maybe(f(x)),
4
+ orElse: () => x,
5
+ forEach: (f) => f(x),
6
+ flatMap: f => f(x),
7
+ isSome: () => true,
8
+ };
9
+ return object;
10
+ }
11
+
12
+ export function none() {
13
+ const object = {
14
+ map: () => object,
15
+ orElse: (f = () => { }) => f(),
16
+ forEach: () => { },
17
+ flatMap: () => object,
18
+ isSome: () => false,
19
+ };
20
+ return object
21
+ }
22
+
23
+ export function maybe(x) {
24
+ if (x) {
25
+ return some(x);
26
+ }
27
+ return none(x)
28
+ }
package/src/Ray/Ray.js ADDED
@@ -0,0 +1,7 @@
1
+ export default function Ray(init, dir) {
2
+ const ans = {};
3
+ ans.init = init;
4
+ ans.dir = dir;
5
+ ans.trace = t => init.add(dir.scale(t));
6
+ return ans;
7
+ }
@@ -0,0 +1,103 @@
1
+ import { Vec3, Vec2 } from "../Vector/Vector.js";
2
+ import Point from "./Point.js"
3
+ import Box from "../Box/Box.js";
4
+ import Color from "../Color/Color.js";
5
+
6
+ const RADIUS = 0.001;
7
+ export default class Mesh {
8
+ constructor({ vertices, normals, textureCoords, faces, colors }) {
9
+ this.vertices = vertices || [];
10
+ this.normals = normals || [];
11
+ this.textureCoords = textureCoords || [];
12
+ this.faces = faces || [];
13
+ this.colors = colors || [];
14
+ }
15
+
16
+ mapVertices(lambda) {
17
+ const newVertices = [];
18
+ for (let i = 0; i < this.vertices.length; i++) {
19
+ newVertices.push(lambda(this.vertices[i]));
20
+ }
21
+ return new Mesh({
22
+ vertices: newVertices,
23
+ normals: this.normals,
24
+ textureCoords: this.textureCoords,
25
+ faces: this.faces
26
+ })
27
+ }
28
+
29
+ mapColors(lambda) {
30
+ const newColors = [];
31
+ for (let i = 0; i < this.vertices.length; i++) {
32
+ newColors.push(lambda(this.vertices[i]));
33
+ }
34
+ return new Mesh({
35
+ vertices: this.vertices,
36
+ normals: this.normals,
37
+ textureCoords: this.textureCoords,
38
+ faces: this.faces,
39
+ colors: newColors
40
+ })
41
+ }
42
+
43
+ getBoundingBox() {
44
+ if (this.boundingBox) return this.boundingBox;
45
+ this.boundingBox = new Box();
46
+ for (let i = 0; i < this.vertices.length; i++) {
47
+ this.boundingBox = this.boundingBox.add(new Box(
48
+ this.vertices[i].add(Vec3(1, 1, 1).scale(RADIUS)),
49
+ this.vertices[i].add(Vec3(1, 1, 1).scale(RADIUS))
50
+ ));
51
+ }
52
+ return this.boundingBox;
53
+ }
54
+
55
+ asPoints(name, radius = RADIUS) {
56
+ const points = [];
57
+ for (let i = 0; i < this.vertices.length; i++) {
58
+ points.push(
59
+ Point
60
+ .builder()
61
+ .radius(radius)
62
+ .name(`${name}_${i}`)
63
+ .color(this.colors[i])
64
+ .position(this.vertices[i])
65
+ .normal(this.normals[i] || Vec3(1, 0, 0))
66
+ .build()
67
+ )
68
+ }
69
+ return points;
70
+ }
71
+
72
+
73
+ static readObj(objFile) {
74
+ const vertices = [];
75
+ const normals = [];
76
+ const texture = [];
77
+ const faces = [];
78
+ objFile.split("\n")
79
+ .forEach((lines) => {
80
+ const spaces = lines.split(" ")
81
+ const type = spaces[0];
82
+ if (type === "v") {
83
+ const v = spaces.slice(1, 4)
84
+ .map(x => Number.parseFloat(x));
85
+ vertices.push(Vec3(...v));
86
+ }
87
+ if (type === "vn") {
88
+ const v = spaces.slice(1, 4)
89
+ .map(x => Number.parseFloat(x));
90
+ normals.push(Vec3(...v));
91
+ }
92
+ if (type === "vt") {
93
+ const v = spaces.slice(1, 3)
94
+ .map(x => Number.parseFloat(x));
95
+ texture.push(Vec2(...v));
96
+ }
97
+ if (type === "f") {
98
+ // TODO
99
+ }
100
+ })
101
+ return new Mesh({ vertices, normals, texture, faces })
102
+ }
103
+ }
@@ -0,0 +1,77 @@
1
+
2
+ import { none, some } from "../Monads/Monads.js";
3
+ import Point from "./Point.js";
4
+ import Vec from "../Vector/Vector.js";
5
+ import { smin } from "../Utils/Math.js";
6
+
7
+ export default class NaiveScene {
8
+ constructor() {
9
+ this.id2ElemMap = {};
10
+ this.sceneElements = [];
11
+ }
12
+
13
+ add(...elements) {
14
+ return this.addList(elements);
15
+ }
16
+
17
+ addList(elements) {
18
+ for (let i = 0; i < elements.length; i++) {
19
+ const elem = elements[i];
20
+ const classes = [Point];
21
+ if (!classes.some((c) => elem instanceof c)) return this;
22
+ const { name } = elem;
23
+ this.id2ElemMap[name] = elem;
24
+ this.sceneElements.push(elem);
25
+ }
26
+ return this;
27
+ }
28
+
29
+ clear() {
30
+ this.id2ElemMap = {};
31
+ this.sceneElements = [];
32
+ }
33
+
34
+ getElements() {
35
+ return this.sceneElements;
36
+ }
37
+
38
+ distanceToPoint(p) {
39
+ const elements = this.sceneElements;
40
+ let distance = Number.MAX_VALUE;
41
+ for (let i = 0; i < elements.length; i++) {
42
+ distance = smin(distance, elements[i].distanceToPoint(p));
43
+ }
44
+ return
45
+ }
46
+
47
+ estimateNormal(p) {
48
+ const epsilon = 1e-3;
49
+ const n = p.dim;
50
+ const grad = [];
51
+ const d = this.distanceToPoint(p);
52
+ for (let i = 0; i < n; i++) {
53
+ grad.push(this.distanceToPoint(p.add(Vec.e(n)(i).scale(epsilon))) - d);
54
+ }
55
+ return Vec.fromArray(grad).scale(Math.sign(d)).normalize();
56
+ }
57
+
58
+ interceptWith(ray) {
59
+ const points = this.sceneElements;
60
+ let closestDistance = Number.MAX_VALUE;
61
+ let closest = none();
62
+ for (let i = 0; i < points.length; i++) {
63
+ points[i].interceptWith(ray)
64
+ .map(([pos, normal]) => {
65
+ const distance = ray
66
+ .init
67
+ .sub(pos)
68
+ .length();
69
+ if (distance < closestDistance) {
70
+ closest = some([pos, normal]);
71
+ closestDistance = distance;
72
+ }
73
+ })
74
+ }
75
+ return closest;
76
+ }
77
+ }