matrix-engine-wgpu 1.3.16 → 1.3.18

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 (273) hide show
  1. package/.codesandbox/tasks.json +46 -0
  2. package/.devcontainer/devcontainer.json +22 -0
  3. package/.github/dependabot.yml +12 -0
  4. package/REFERENCE.md +59 -0
  5. package/app-worker.js +45 -0
  6. package/dev.md +541 -0
  7. package/empty.js +17 -0
  8. package/examples/camera-texture.js +60 -0
  9. package/examples/games/jamb/html-content.js +128 -0
  10. package/examples/games/jamb/jamb.js +1341 -0
  11. package/examples/games/jamb/readme.md +3 -0
  12. package/examples/load-jamb.js +6 -0
  13. package/examples/load-obj-file.js +95 -0
  14. package/examples/load-objs-sequence.js +68 -0
  15. package/examples/unlit-textures.js +31 -0
  16. package/examples/video-texture.js +61 -0
  17. package/examples.js +73 -0
  18. package/main.js +635 -0
  19. package/non-project-files/cubebuffer-example.js +51 -0
  20. package/non-project-files/dev.txt +21 -0
  21. package/non-project-files/image1.png +0 -0
  22. package/non-project-files/image6.png +0 -0
  23. package/package.json +2 -5
  24. package/public/ammojs/ammo.js +957 -0
  25. package/public/ammojs/ammo.wasm.js +921 -0
  26. package/public/ammojs/ammo.wasm.wasm +0 -0
  27. package/public/app-worker.js +47 -0
  28. package/public/app.js +12744 -0
  29. package/public/css/style.css +711 -0
  30. package/public/empty.html +25 -0
  31. package/public/empty.js +10453 -0
  32. package/public/examples.html +30 -0
  33. package/public/examples.js +11217 -0
  34. package/public/index.html +20 -0
  35. package/public/manifest copy.web +35 -0
  36. package/public/manifest.web +25 -0
  37. package/public/res/audios/block.mp3 +0 -0
  38. package/public/res/audios/dice-roll.mp3 +0 -0
  39. package/public/res/audios/dice1.mp3 +0 -0
  40. package/public/res/audios/dice2.mp3 +0 -0
  41. package/public/res/audios/kenney/Kenney.url +2 -0
  42. package/public/res/audios/kenney/License.txt +22 -0
  43. package/public/res/audios/kenney/Patreon.url +2 -0
  44. package/public/res/audios/kenney/audios/back_001.ogg +0 -0
  45. package/public/res/audios/kenney/audios/back_002.ogg +0 -0
  46. package/public/res/audios/kenney/audios/back_003.ogg +0 -0
  47. package/public/res/audios/kenney/audios/back_004.ogg +0 -0
  48. package/public/res/audios/kenney/audios/bong_001.ogg +0 -0
  49. package/public/res/audios/kenney/audios/click_001.ogg +0 -0
  50. package/public/res/audios/kenney/audios/click_002.ogg +0 -0
  51. package/public/res/audios/kenney/audios/click_003.ogg +0 -0
  52. package/public/res/audios/kenney/audios/click_004.ogg +0 -0
  53. package/public/res/audios/kenney/audios/click_005.ogg +0 -0
  54. package/public/res/audios/kenney/audios/close_001.ogg +0 -0
  55. package/public/res/audios/kenney/audios/close_002.ogg +0 -0
  56. package/public/res/audios/kenney/audios/close_003.ogg +0 -0
  57. package/public/res/audios/kenney/audios/close_004.ogg +0 -0
  58. package/public/res/audios/kenney/audios/confirmation_001.ogg +0 -0
  59. package/public/res/audios/kenney/audios/confirmation_002.ogg +0 -0
  60. package/public/res/audios/kenney/audios/confirmation_003.ogg +0 -0
  61. package/public/res/audios/kenney/audios/confirmation_004.ogg +0 -0
  62. package/public/res/audios/kenney/audios/drop_001.ogg +0 -0
  63. package/public/res/audios/kenney/audios/drop_002.ogg +0 -0
  64. package/public/res/audios/kenney/audios/drop_003.ogg +0 -0
  65. package/public/res/audios/kenney/audios/drop_004.ogg +0 -0
  66. package/public/res/audios/kenney/audios/error_001.ogg +0 -0
  67. package/public/res/audios/kenney/audios/error_002.ogg +0 -0
  68. package/public/res/audios/kenney/audios/error_003.ogg +0 -0
  69. package/public/res/audios/kenney/audios/error_004.ogg +0 -0
  70. package/public/res/audios/kenney/audios/error_005.ogg +0 -0
  71. package/public/res/audios/kenney/audios/error_006.ogg +0 -0
  72. package/public/res/audios/kenney/audios/error_007.ogg +0 -0
  73. package/public/res/audios/kenney/audios/error_008.ogg +0 -0
  74. package/public/res/audios/kenney/audios/glass_001.ogg +0 -0
  75. package/public/res/audios/kenney/audios/glass_002.ogg +0 -0
  76. package/public/res/audios/kenney/audios/glass_003.ogg +0 -0
  77. package/public/res/audios/kenney/audios/glass_004.ogg +0 -0
  78. package/public/res/audios/kenney/audios/glass_005.ogg +0 -0
  79. package/public/res/audios/kenney/audios/glass_006.ogg +0 -0
  80. package/public/res/audios/kenney/audios/glitch_001.ogg +0 -0
  81. package/public/res/audios/kenney/audios/glitch_002.ogg +0 -0
  82. package/public/res/audios/kenney/audios/glitch_003.ogg +0 -0
  83. package/public/res/audios/kenney/audios/glitch_004.ogg +0 -0
  84. package/public/res/audios/kenney/audios/maximize_001.ogg +0 -0
  85. package/public/res/audios/kenney/audios/maximize_002.ogg +0 -0
  86. package/public/res/audios/kenney/audios/maximize_003.ogg +0 -0
  87. package/public/res/audios/kenney/audios/maximize_004.ogg +0 -0
  88. package/public/res/audios/kenney/audios/maximize_005.ogg +0 -0
  89. package/public/res/audios/kenney/audios/maximize_006.ogg +0 -0
  90. package/public/res/audios/kenney/audios/maximize_007.ogg +0 -0
  91. package/public/res/audios/kenney/audios/maximize_008.ogg +0 -0
  92. package/public/res/audios/kenney/audios/maximize_009.ogg +0 -0
  93. package/public/res/audios/kenney/audios/minimize_001.ogg +0 -0
  94. package/public/res/audios/kenney/audios/minimize_002.ogg +0 -0
  95. package/public/res/audios/kenney/audios/minimize_003.ogg +0 -0
  96. package/public/res/audios/kenney/audios/minimize_004.ogg +0 -0
  97. package/public/res/audios/kenney/audios/minimize_005.ogg +0 -0
  98. package/public/res/audios/kenney/audios/minimize_006.ogg +0 -0
  99. package/public/res/audios/kenney/audios/minimize_007.ogg +0 -0
  100. package/public/res/audios/kenney/audios/minimize_008.ogg +0 -0
  101. package/public/res/audios/kenney/audios/minimize_009.ogg +0 -0
  102. package/public/res/audios/kenney/audios/open_001.ogg +0 -0
  103. package/public/res/audios/kenney/audios/open_002.ogg +0 -0
  104. package/public/res/audios/kenney/audios/open_003.ogg +0 -0
  105. package/public/res/audios/kenney/audios/open_004.ogg +0 -0
  106. package/public/res/audios/kenney/audios/pluck_001.ogg +0 -0
  107. package/public/res/audios/kenney/audios/pluck_002.ogg +0 -0
  108. package/public/res/audios/kenney/audios/question_001.ogg +0 -0
  109. package/public/res/audios/kenney/audios/question_002.ogg +0 -0
  110. package/public/res/audios/kenney/audios/question_003.ogg +0 -0
  111. package/public/res/audios/kenney/audios/question_004.ogg +0 -0
  112. package/public/res/audios/kenney/audios/scratch_001.ogg +0 -0
  113. package/public/res/audios/kenney/audios/scratch_002.ogg +0 -0
  114. package/public/res/audios/kenney/audios/scratch_003.ogg +0 -0
  115. package/public/res/audios/kenney/audios/scratch_004.ogg +0 -0
  116. package/public/res/audios/kenney/audios/scratch_005.ogg +0 -0
  117. package/public/res/audios/kenney/audios/scroll_001.ogg +0 -0
  118. package/public/res/audios/kenney/audios/scroll_002.ogg +0 -0
  119. package/public/res/audios/kenney/audios/scroll_003.ogg +0 -0
  120. package/public/res/audios/kenney/audios/scroll_004.ogg +0 -0
  121. package/public/res/audios/kenney/audios/scroll_005.ogg +0 -0
  122. package/public/res/audios/kenney/audios/select_001.ogg +0 -0
  123. package/public/res/audios/kenney/audios/select_002.ogg +0 -0
  124. package/public/res/audios/kenney/audios/select_003.ogg +0 -0
  125. package/public/res/audios/kenney/audios/select_004.ogg +0 -0
  126. package/public/res/audios/kenney/audios/select_005.ogg +0 -0
  127. package/public/res/audios/kenney/audios/select_006.ogg +0 -0
  128. package/public/res/audios/kenney/audios/select_007.ogg +0 -0
  129. package/public/res/audios/kenney/audios/select_008.ogg +0 -0
  130. package/public/res/audios/kenney/audios/switch_001.ogg +0 -0
  131. package/public/res/audios/kenney/audios/switch_002.ogg +0 -0
  132. package/public/res/audios/kenney/audios/switch_003.ogg +0 -0
  133. package/public/res/audios/kenney/audios/switch_004.ogg +0 -0
  134. package/public/res/audios/kenney/audios/switch_005.ogg +0 -0
  135. package/public/res/audios/kenney/audios/switch_006.ogg +0 -0
  136. package/public/res/audios/kenney/audios/switch_007.ogg +0 -0
  137. package/public/res/audios/kenney/audios/tick_001.ogg +0 -0
  138. package/public/res/audios/kenney/audios/tick_002.ogg +0 -0
  139. package/public/res/audios/kenney/audios/tick_004.ogg +0 -0
  140. package/public/res/audios/kenney/audios/toggle_001.ogg +0 -0
  141. package/public/res/audios/kenney/audios/toggle_002.ogg +0 -0
  142. package/public/res/audios/kenney/audios/toggle_003.ogg +0 -0
  143. package/public/res/audios/kenney/audios/toggle_004.ogg +0 -0
  144. package/public/res/audios/start.mp3 +0 -0
  145. package/public/res/audios/toggle_002.mp3 +0 -0
  146. package/public/res/fonts/Accuratist.ttf +0 -0
  147. package/public/res/fonts/Closeness.ttf +0 -0
  148. package/public/res/fonts/WARGAMES.TTF +0 -0
  149. package/public/res/fonts/readme.txt +5 -0
  150. package/public/res/fonts/stormfaze.ttf +0 -0
  151. package/public/res/icons/512.png +0 -0
  152. package/public/res/icons/webgpu-horizontal.svg +45 -0
  153. package/public/res/meshes/blender/cube.blend +0 -0
  154. package/public/res/meshes/blender/cube.blend1 +0 -0
  155. package/public/res/meshes/blender/cube.mtl +12 -0
  156. package/public/res/meshes/blender/cube.obj +46 -0
  157. package/public/res/meshes/blender/cube.png +0 -0
  158. package/public/res/meshes/blender/cubeSmartUV.blend +0 -0
  159. package/public/res/meshes/blender/cubeSmartUV.mtl +12 -0
  160. package/public/res/meshes/blender/cubeSmartUV.obj +46 -0
  161. package/public/res/meshes/blender/lopta.mtl +10 -0
  162. package/public/res/meshes/blender/lopta.obj +3402 -0
  163. package/public/res/meshes/blender/piramyd.blend +0 -0
  164. package/public/res/meshes/blender/piramyd.blend1 +0 -0
  165. package/public/res/meshes/blender/piramyd.js +42 -0
  166. package/public/res/meshes/blender/piramyd.mtl +10 -0
  167. package/public/res/meshes/blender/piramyd.obj +18696 -0
  168. package/public/res/meshes/blender/piramyd1.js +42 -0
  169. package/public/res/meshes/blender/sphepe.blend +0 -0
  170. package/public/res/meshes/blender/sphepe.blend1 +0 -0
  171. package/public/res/meshes/blender/sphere.mtl +10 -0
  172. package/public/res/meshes/blender/sphere.obj +3402 -0
  173. package/public/res/meshes/blender/welcomeTextblend.blend +0 -0
  174. package/public/res/meshes/dragon/stanfordDragonData.js +5 -0
  175. package/public/res/meshes/jamb/bg.blend +0 -0
  176. package/public/res/meshes/jamb/bg.blend1 +0 -0
  177. package/public/res/meshes/jamb/bg.mtl +12 -0
  178. package/public/res/meshes/jamb/bg.obj +17 -0
  179. package/public/res/meshes/jamb/bg.png +0 -0
  180. package/public/res/meshes/jamb/dice-default.png +0 -0
  181. package/public/res/meshes/jamb/dice-mark.png +0 -0
  182. package/public/res/meshes/jamb/dice.mtl +12 -0
  183. package/public/res/meshes/jamb/dice.obj +40 -0
  184. package/public/res/meshes/jamb/dice.png +0 -0
  185. package/public/res/meshes/jamb/jamb-title.mtl +12 -0
  186. package/public/res/meshes/jamb/jamb-title.obj +26008 -0
  187. package/public/res/meshes/jamb/jamb.blend +0 -0
  188. package/public/res/meshes/jamb/jamb.blend1 +0 -0
  189. package/public/res/meshes/jamb/logo.png +0 -0
  190. package/public/res/meshes/jamb/nidzaDice.blend +0 -0
  191. package/public/res/meshes/jamb/nidzaDice.blend1 +0 -0
  192. package/public/res/meshes/jamb/pile.blend +0 -0
  193. package/public/res/meshes/jamb/simpleCube.blend +0 -0
  194. package/public/res/meshes/jamb/simpleCube.blend1 +0 -0
  195. package/public/res/meshes/jamb/sounds/roll1.wav +0 -0
  196. package/public/res/meshes/jamb/text.png +0 -0
  197. package/public/res/meshes/obj/armor.obj +319 -0
  198. package/public/res/meshes/obj/armor.png +0 -0
  199. package/public/res/meshes/objs-sequence/swat-walk-pistol_000001.mtl +22 -0
  200. package/public/res/meshes/objs-sequence/swat-walk-pistol_000001.obj +23264 -0
  201. package/public/res/meshes/objs-sequence/swat-walk-pistol_000002.mtl +22 -0
  202. package/public/res/meshes/objs-sequence/swat-walk-pistol_000002.obj +23261 -0
  203. package/public/res/meshes/objs-sequence/swat-walk-pistol_000003.mtl +22 -0
  204. package/public/res/meshes/objs-sequence/swat-walk-pistol_000003.obj +23264 -0
  205. package/public/res/meshes/objs-sequence/swat-walk-pistol_000004.mtl +22 -0
  206. package/public/res/meshes/objs-sequence/swat-walk-pistol_000004.obj +23261 -0
  207. package/public/res/meshes/objs-sequence/swat-walk-pistol_000005.mtl +22 -0
  208. package/public/res/meshes/objs-sequence/swat-walk-pistol_000005.obj +23261 -0
  209. package/public/res/meshes/objs-sequence/swat-walk-pistol_000006.mtl +22 -0
  210. package/public/res/meshes/objs-sequence/swat-walk-pistol_000006.obj +23261 -0
  211. package/public/res/meshes/objs-sequence/swat-walk-pistol_000007.mtl +22 -0
  212. package/public/res/meshes/objs-sequence/swat-walk-pistol_000007.obj +23264 -0
  213. package/public/res/meshes/objs-sequence/swat-walk-pistol_000008.mtl +22 -0
  214. package/public/res/meshes/objs-sequence/swat-walk-pistol_000008.obj +23263 -0
  215. package/public/res/meshes/objs-sequence/swat-walk-pistol_000009.mtl +22 -0
  216. package/public/res/meshes/objs-sequence/swat-walk-pistol_000009.obj +23264 -0
  217. package/public/res/meshes/objs-sequence/swat-walk-pistol_000010.mtl +22 -0
  218. package/public/res/meshes/objs-sequence/swat-walk-pistol_000010.obj +23260 -0
  219. package/public/res/meshes/objs-sequence/swat-walk-pistol_000011.mtl +22 -0
  220. package/public/res/meshes/objs-sequence/swat-walk-pistol_000011.obj +23262 -0
  221. package/public/res/meshes/objs-sequence/swat-walk-pistol_000012.mtl +22 -0
  222. package/public/res/meshes/objs-sequence/swat-walk-pistol_000012.obj +23262 -0
  223. package/public/res/meshes/objs-sequence/swat-walk-pistol_000013.mtl +22 -0
  224. package/public/res/meshes/objs-sequence/swat-walk-pistol_000013.obj +23263 -0
  225. package/public/res/meshes/objs-sequence/swat-walk-pistol_000014.mtl +22 -0
  226. package/public/res/meshes/objs-sequence/swat-walk-pistol_000014.obj +23262 -0
  227. package/public/res/meshes/objs-sequence/swat-walk-pistol_000015.mtl +22 -0
  228. package/public/res/meshes/objs-sequence/swat-walk-pistol_000015.obj +23263 -0
  229. package/public/res/meshes/objs-sequence/swat-walk-pistol_000016.mtl +22 -0
  230. package/public/res/meshes/objs-sequence/swat-walk-pistol_000016.obj +23264 -0
  231. package/public/res/meshes/objs-sequence/swat-walk-pistol_000017.mtl +22 -0
  232. package/public/res/meshes/objs-sequence/swat-walk-pistol_000017.obj +23263 -0
  233. package/public/res/meshes/objs-sequence/swat-walk-pistol_000018.mtl +22 -0
  234. package/public/res/meshes/objs-sequence/swat-walk-pistol_000018.obj +23261 -0
  235. package/public/res/meshes/objs-sequence/swat-walk-pistol_000019.mtl +22 -0
  236. package/public/res/meshes/objs-sequence/swat-walk-pistol_000019.obj +23263 -0
  237. package/public/res/meshes/objs-sequence/swat-walk-pistol_000020.mtl +22 -0
  238. package/public/res/meshes/objs-sequence/swat-walk-pistol_000020.obj +23261 -0
  239. package/public/res/meshes/shapes/star1.obj +60 -0
  240. package/public/res/multilang/en.json +39 -0
  241. package/public/res/multilang/sr.json +39 -0
  242. package/public/res/textures/default.png +0 -0
  243. package/public/res/textures/rust.jpg +0 -0
  244. package/public/res/textures/tex1.jpg +0 -0
  245. package/public/res/videos/readme.txt +2 -0
  246. package/public/res/videos/tunel.mp4 +0 -0
  247. package/public/test.html +636 -0
  248. package/public/three-test.js +165 -0
  249. package/public/worker.html +25 -0
  250. package/src/engine/ball.js +482 -0
  251. package/src/engine/cube.js +496 -0
  252. package/src/engine/engine.js +404 -0
  253. package/src/engine/final/adaptJSON1.js +53 -0
  254. package/src/engine/final/utils2.js +63 -0
  255. package/src/engine/lights.js +153 -0
  256. package/src/engine/loader-obj.js +473 -0
  257. package/src/engine/materials.js +295 -0
  258. package/src/engine/matrix-class.js +252 -0
  259. package/src/engine/mesh-obj.js +574 -0
  260. package/src/engine/raycast.js +218 -0
  261. package/src/engine/utils.js +881 -0
  262. package/src/libs/mat.js +0 -0
  263. package/src/multilang/lang.js +35 -0
  264. package/src/physics/matrix-ammo.js +363 -0
  265. package/src/shaders/fragment.video.wgsl.js +83 -0
  266. package/src/shaders/fragment.wgsl.js +75 -0
  267. package/src/shaders/shaders.js +51 -0
  268. package/src/shaders/standard-matrix-engine-shaders/standard-matrix-engine-fs.glsl +56 -0
  269. package/src/shaders/standard-matrix-engine-shaders/standard-matrix-engine-vs.glsl +75 -0
  270. package/src/shaders/vertex.wgsl.js +54 -0
  271. package/src/shaders/vertexShadow.wgsl.js +20 -0
  272. package/src/sounds/sounds.js +69 -0
  273. package/src/world.js +474 -0
@@ -0,0 +1,404 @@
1
+ // Note: The code in this file does not use the 'dst' output parameter of functions in the
2
+ // 'wgpu-matrix' library, so produces many temporary vectors and matrices.
3
+ // This is intentional, as this sample prefers readability over performance.
4
+ import { mat4, vec3 } from 'wgpu-matrix';
5
+ import {LOG_INFO} from './utils';
6
+
7
+ // The common functionality between camera implementations
8
+ class CameraBase {
9
+ // The camera matrix
10
+ matrix_ = new Float32Array([
11
+ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1,
12
+ ]);
13
+
14
+ // The calculated view matrix readonly
15
+ view_ = mat4.create();
16
+
17
+ // Aliases to column vectors of the matrix
18
+ right_ = new Float32Array(this.matrix_.buffer, 4 * 0, 4);
19
+ up_ = new Float32Array(this.matrix_.buffer, 4 * 4, 4);
20
+ back_ = new Float32Array(this.matrix_.buffer, 4 * 8, 4);
21
+ position_ = new Float32Array(this.matrix_.buffer, 4 * 12, 4);
22
+
23
+ // Returns the camera matrix
24
+ get matrix() {
25
+ return this.matrix_;
26
+ }
27
+ // Assigns `mat` to the camera matrix
28
+ set matrix(mat) {
29
+ mat4.copy(mat, this.matrix_);
30
+ }
31
+
32
+ setProjection(fov = (2 * Math.PI) / 5, aspect = 1, near = 1, far = 1000) {
33
+ this.projectionMatrix = mat4.perspective(fov, aspect, near, far);
34
+ }
35
+
36
+ // Returns the camera view matrix
37
+ get view() {
38
+ return this.view_;
39
+ }
40
+ // Assigns `mat` to the camera view
41
+ set view(mat) {
42
+ mat4.copy(mat, this.view_);
43
+ }
44
+
45
+ // Returns column vector 0 of the camera matrix
46
+ get right() {
47
+ return this.right_;
48
+ }
49
+
50
+ // Assigns `vec` to the first 3 elements of column vector 0 of the camera matrix
51
+ set right(vec) {
52
+ vec3.copy(vec, this.right_);
53
+ }
54
+
55
+ // Returns column vector 1 of the camera matrix
56
+ get up() {
57
+ return this.up_;
58
+ }
59
+
60
+ // Assigns `vec` to the first 3 elements of column vector 1 of the camera matrix \ Vec3
61
+ set up(vec) {
62
+ vec3.copy(vec, this.up_);
63
+ }
64
+
65
+ // Returns column vector 2 of the camera matrix
66
+ get back() {
67
+ return this.back_;
68
+ }
69
+
70
+ // Assigns `vec` to the first 3 elements of column vector 2 of the camera matrix
71
+ set back(vec) {
72
+ vec3.copy(vec, this.back_);
73
+ }
74
+
75
+ // Returns column vector 3 of the camera matrix
76
+ get position() {
77
+ return this.position_;
78
+ }
79
+
80
+ // Assigns `vec` to the first 3 elements of column vector 3 of the camera matrix
81
+ set position(vec) {
82
+ vec3.copy(vec, this.position_);
83
+ }
84
+ }
85
+
86
+ // WASDCamera is a camera implementation that behaves similar to first-person-shooter PC games.
87
+ export class WASDCamera extends CameraBase {
88
+ // The camera absolute pitch angle
89
+ pitch = 0;
90
+ // The camera absolute yaw angle
91
+ yaw = 0;
92
+
93
+ // The movement veloicty readonly
94
+ velocity_ = vec3.create();
95
+
96
+ // Speed multiplier for camera movement
97
+ movementSpeed = 10;
98
+
99
+ // Speed multiplier for camera rotation
100
+ rotationSpeed = 1;
101
+
102
+ // Movement velocity drag coeffient [0 .. 1]
103
+ // 0: Continues forever
104
+ // 1: Instantly stops moving
105
+ frictionCoefficient = 0.99;
106
+
107
+ // Returns velocity vector
108
+ get velocity() {
109
+ return this.velocity_;
110
+ }
111
+ // Assigns `vec` to the velocity vector
112
+ set velocity(vec) {
113
+ vec3.copy(vec, this.velocity_);
114
+ }
115
+
116
+ constructor(options) {
117
+ super();
118
+ if (options && (options.position || options.target)) {
119
+ const position = options.position ?? vec3.create(0, 0, 0);
120
+ const target = options.target ?? vec3.create(0, 0, 0);
121
+ const forward = vec3.normalize(vec3.sub(target, position));
122
+ this.recalculateAngles(forward);
123
+ this.position = position;
124
+ this.setProjection()
125
+ // console.log(`%cCamera constructor : ${position}`, LOG_INFO);
126
+ }
127
+ }
128
+
129
+ // Returns the camera matrix
130
+ get matrix() {
131
+ return super.matrix;
132
+ }
133
+
134
+ // Assigns `mat` to the camera matrix, and recalcuates the camera angles
135
+ set matrix(mat) {
136
+ super.matrix = mat;
137
+ this.recalculateAngles(this.back);
138
+ }
139
+
140
+ update(deltaTime, input) {
141
+ const sign = (positive, negative) =>
142
+ (positive ? 1 : 0) - (negative ? 1 : 0);
143
+
144
+ // Apply the delta rotation to the pitch and yaw angles
145
+ this.yaw -= input.analog.x * deltaTime * this.rotationSpeed;
146
+ this.pitch -= input.analog.y * deltaTime * this.rotationSpeed;
147
+
148
+ // Wrap yaw between [0° .. 360°], just to prevent large accumulation.
149
+ this.yaw = mod(this.yaw, Math.PI * 2);
150
+ // Clamp pitch between [-90° .. +90°] to prevent somersaults.
151
+ this.pitch = clamp(this.pitch, -Math.PI / 2, Math.PI / 2);
152
+
153
+ // Save the current position, as we're about to rebuild the camera matrix.
154
+ const position = vec3.copy(this.position);
155
+
156
+ // Reconstruct the camera's rotation, and store into the camera matrix.
157
+ super.matrix = mat4.rotateX(mat4.rotationY(this.yaw), this.pitch);
158
+ // super.matrix = mat4.rotateX(mat4.rotationY(this.yaw), -this.pitch);
159
+ // super.matrix = mat4.rotateY(mat4.rotateX(this.pitch), this.yaw);
160
+
161
+ // Calculate the new target velocity
162
+ const digital = input.digital;
163
+ const deltaRight = sign(digital.right, digital.left);
164
+ const deltaUp = sign(digital.up, digital.down);
165
+ const targetVelocity = vec3.create();
166
+ const deltaBack = sign(digital.backward, digital.forward);
167
+ vec3.addScaled(targetVelocity, this.right, deltaRight, targetVelocity);
168
+ vec3.addScaled(targetVelocity, this.up, deltaUp, targetVelocity);
169
+ vec3.addScaled(targetVelocity, this.back, deltaBack, targetVelocity);
170
+ vec3.normalize(targetVelocity, targetVelocity);
171
+ vec3.mulScalar(targetVelocity, this.movementSpeed, targetVelocity);
172
+
173
+ // Mix new target velocity
174
+ this.velocity = lerp(
175
+ targetVelocity,
176
+ this.velocity,
177
+ Math.pow(1 - this.frictionCoefficient, deltaTime)
178
+ );
179
+
180
+ // Integrate velocity to calculate new position
181
+ this.position = vec3.addScaled(position, this.velocity, deltaTime);
182
+
183
+ // Invert the camera matrix to build the view matrix
184
+ this.view = mat4.invert(this.matrix);
185
+ return this.view;
186
+ }
187
+
188
+ // Recalculates the yaw and pitch values from a directional vector
189
+ recalculateAngles(dir) {
190
+ this.yaw = Math.atan2(dir[0], dir[2]);
191
+ this.pitch = -Math.asin(dir[1]);
192
+ }
193
+ }
194
+
195
+ // ArcballCamera implements a basic orbiting camera around the world origin
196
+ export class ArcballCamera extends CameraBase {
197
+ // The camera distance from the target
198
+ distance = 0;
199
+
200
+ // The current angular velocity
201
+ angularVelocity = 0;
202
+
203
+ // The current rotation axis
204
+ axis_ = vec3.create();
205
+
206
+ // Returns the rotation axis
207
+ get axis() {
208
+ return this.axis_;
209
+ }
210
+ // Assigns `vec` to the rotation axis
211
+ set axis(vec) {
212
+ vec3.copy(vec, this.axis_);
213
+ }
214
+
215
+ // Speed multiplier for camera rotation
216
+ rotationSpeed = 1;
217
+
218
+ // Speed multiplier for camera zoom
219
+ zoomSpeed = 0.1;
220
+
221
+ // Rotation velocity drag coeffient [0 .. 1]
222
+ // 0: Spins forever
223
+ // 1: Instantly stops spinning
224
+ frictionCoefficient = 0.999;
225
+
226
+ // Construtor
227
+ constructor(options) {
228
+ super();
229
+ if (options && options.position) {
230
+ this.position = options.position;
231
+ this.distance = vec3.len(this.position);
232
+ this.back = vec3.normalize(this.position);
233
+ this.recalcuateRight();
234
+ this.recalcuateUp();
235
+ }
236
+ }
237
+
238
+ // Returns the camera matrix
239
+ get matrix() {
240
+ return super.matrix;
241
+ }
242
+
243
+ // Assigns `mat` to the camera matrix, and recalcuates the distance
244
+ set matrix(mat) {
245
+ super.matrix = mat;
246
+ this.distance = vec3.len(this.position);
247
+ }
248
+
249
+ update(deltaTime, input) {
250
+ const epsilon = 0.0000001;
251
+
252
+ if (input.analog.touching) {
253
+ // Currently being dragged.
254
+ this.angularVelocity = 0;
255
+ } else {
256
+ // Dampen any existing angular velocity
257
+ this.angularVelocity *= Math.pow(1 - this.frictionCoefficient, deltaTime);
258
+ }
259
+
260
+ // Calculate the movement vector
261
+ const movement = vec3.create();
262
+ vec3.addScaled(movement, this.right, input.analog.x, movement);
263
+ vec3.addScaled(movement, this.up, -input.analog.y, movement);
264
+
265
+ // Cross the movement vector with the view direction to calculate the rotation axis x magnitude
266
+ const crossProduct = vec3.cross(movement, this.back);
267
+
268
+ // Calculate the magnitude of the drag
269
+ const magnitude = vec3.len(crossProduct);
270
+
271
+ if (magnitude > epsilon) {
272
+ // Normalize the crossProduct to get the rotation axis
273
+ this.axis = vec3.scale(crossProduct, 1 / magnitude);
274
+
275
+ // Remember the current angular velocity. This is used when the touch is released for a fling.
276
+ this.angularVelocity = magnitude * this.rotationSpeed;
277
+ }
278
+
279
+ // The rotation around this.axis to apply to the camera matrix this update
280
+ const rotationAngle = this.angularVelocity * deltaTime;
281
+ if (rotationAngle > epsilon) {
282
+ // Rotate the matrix around axis
283
+ // Note: The rotation is not done as a matrix-matrix multiply as the repeated multiplications
284
+ // will quickly introduce substantial error into the matrix.
285
+ this.back = vec3.normalize(rotate(this.back, this.axis, rotationAngle));
286
+ this.recalcuateRight();
287
+ this.recalcuateUp();
288
+ }
289
+
290
+ // recalculate `this.position` from `this.back` considering zoom
291
+ if (input.analog.zoom !== 0) {
292
+ this.distance *= 1 + input.analog.zoom * this.zoomSpeed;
293
+ }
294
+ this.position = vec3.scale(this.back, this.distance);
295
+
296
+ // Invert the camera matrix to build the view matrix
297
+ this.view = mat4.invert(this.matrix);
298
+ return this.view;
299
+ }
300
+
301
+ // Assigns `this.right` with the cross product of `this.up` and `this.back`
302
+ recalcuateRight() {
303
+ this.right = vec3.normalize(vec3.cross(this.up, this.back));
304
+ }
305
+
306
+ // Assigns `this.up` with the cross product of `this.back` and `this.right`
307
+ recalcuateUp() {
308
+ this.up = vec3.normalize(vec3.cross(this.back, this.right));
309
+ }
310
+ }
311
+
312
+ // Returns `x` clamped between [`min` .. `max`]
313
+ function clamp(x, min, max) {
314
+ return Math.min(Math.max(x, min), max);
315
+ }
316
+
317
+ // Returns `x` float-modulo `div`
318
+ function mod(x, div) {
319
+ return x - Math.floor(Math.abs(x) / div) * div * Math.sign(x);
320
+ }
321
+
322
+ // Returns `vec` rotated `angle` radians around `axis`
323
+ function rotate(vec, axis, angle) {
324
+ return vec3.transformMat4Upper3x3(vec, mat4.rotation(axis, angle));
325
+ }
326
+
327
+ // Returns the linear interpolation between 'a' and 'b' using 's'
328
+ function lerp(a, b, s) {
329
+ return vec3.addScaled(a, vec3.sub(b, a), s);
330
+ }
331
+
332
+ export function createInputHandler(window, canvas) {
333
+ let digital = {
334
+ forward: false,
335
+ backward: false,
336
+ left: false,
337
+ right: false,
338
+ up: false,
339
+ down: false,
340
+ };
341
+ let analog = {
342
+ x: 0,
343
+ y: 0,
344
+ zoom: 0,
345
+ };
346
+ let mouseDown = false;
347
+
348
+ const setDigital = (e, value) => {
349
+ switch (e.code) {
350
+ case 'KeyW': digital.forward = value; break;
351
+ case 'KeyS': digital.backward = value; break;
352
+ case 'KeyA': digital.left = value; break;
353
+ case 'KeyD': digital.right = value; break;
354
+ case 'Space': digital.up = value; break;
355
+ case 'ShiftLeft':
356
+ case 'ControlLeft':
357
+ case 'KeyC': digital.down = value; break;
358
+ }
359
+ e.preventDefault();
360
+ e.stopPropagation();
361
+ };
362
+
363
+ window.addEventListener('keydown', (e) => setDigital(e, true));
364
+ window.addEventListener('keyup', (e) => setDigital(e, false));
365
+
366
+ canvas.style.touchAction = 'pinch-zoom';
367
+ canvas.addEventListener('pointerdown', () => { mouseDown = true; });
368
+ canvas.addEventListener('pointerup', () => { mouseDown = false; });
369
+ canvas.addEventListener('pointermove', (e) => {
370
+ mouseDown = e.pointerType === 'mouse' ? (e.buttons & 1) !== 0 : true;
371
+ if (mouseDown) {
372
+ analog.x += e.movementX / 10;
373
+ analog.y += e.movementY / 10;
374
+ }
375
+ });
376
+
377
+ canvas.addEventListener('wheel', (e) => {
378
+ if ((e.buttons & 1) !== 0) {
379
+ analog.zoom += Math.sign(e.deltaY);
380
+ e.preventDefault();
381
+ e.stopPropagation();
382
+ }
383
+ }, { passive: false });
384
+
385
+ return () => {
386
+ // Guard: prevent zero deltas from breaking camera math
387
+ const safeX = analog.x || 0.0001;
388
+ const safeY = analog.y || 0.0001;
389
+ const out = {
390
+ digital,
391
+ analog: {
392
+ x: safeX,
393
+ y: safeY,
394
+ zoom: analog.zoom,
395
+ touching: mouseDown,
396
+ },
397
+ };
398
+ // Reset only the deltas for next frame
399
+ analog.x = 0;
400
+ analog.y = 0;
401
+ analog.zoom = 0;
402
+ return out;
403
+ };
404
+ }
@@ -0,0 +1,53 @@
1
+ import {computeSurfaceNormals, computeProjectedPlaneUVs} from './utils2.js';
2
+
3
+ export function adaptJSON1(dragonRawData) {
4
+
5
+ let mesh = {
6
+ positions: dragonRawData.positions,
7
+ triangles: dragonRawData.cells,
8
+ normals: [],
9
+ uvs: []
10
+ };
11
+
12
+ // Compute surface normals
13
+ mesh.normals = computeSurfaceNormals(mesh.positions, mesh.triangles);
14
+
15
+ // Compute some easy uvs for testing
16
+ mesh.uvs = computeProjectedPlaneUVs(mesh.positions, 'xy');
17
+
18
+ return mesh;
19
+ }
20
+
21
+ export function addVerticesNormalUvs(mesh) {
22
+
23
+ var meshAdapted = {
24
+ positions: [],
25
+ cells: [],
26
+ uvs: mesh.textures,
27
+ vertices: mesh.vertices
28
+ // normals: mesh.vertexNormals
29
+ };
30
+ // force syntese
31
+ for (var x = 0; x < mesh.vertices.length; x=x+3) {
32
+ var sub = [];
33
+ sub.push(mesh.vertices[x])
34
+ sub.push(mesh.vertices[x+1])
35
+ sub.push(mesh.vertices[x+2])
36
+ meshAdapted.positions.push(sub)
37
+ sub = [];
38
+ sub.push(mesh.indices[x])
39
+ sub.push(mesh.indices[x+1])
40
+ sub.push(mesh.indices[x+2])
41
+ meshAdapted.cells.push(sub)
42
+ }
43
+
44
+ // Compute surface normals
45
+ meshAdapted.normals = computeSurfaceNormals(meshAdapted.positions, meshAdapted.cells);
46
+ // Compute some easy uvs for testing
47
+ meshAdapted.uvs = computeProjectedPlaneUVs(meshAdapted.positions, 'xy');
48
+
49
+ meshAdapted.triangles = meshAdapted.cells
50
+ return meshAdapted;
51
+ }
52
+
53
+
@@ -0,0 +1,63 @@
1
+ import { vec3 } from 'wgpu-matrix';
2
+
3
+ export function computeSurfaceNormals(positions,triangles){
4
+ const normals = positions.map(() => {
5
+ // Initialize to zero.
6
+ return [0, 0, 0];
7
+ });
8
+ triangles.forEach(([i0, i1, i2]) => {
9
+ const p0 = positions[i0];
10
+ const p1 = positions[i1];
11
+ const p2 = positions[i2];
12
+
13
+ const v0 = vec3.subtract(p1, p0);
14
+ const v1 = vec3.subtract(p2, p0);
15
+
16
+ vec3.normalize(v0, v0);
17
+ vec3.normalize(v1, v1);
18
+ const norm = vec3.cross(v0, v1);
19
+
20
+ // Accumulate the normals.
21
+ vec3.add(normals[i0], norm, normals[i0]);
22
+ vec3.add(normals[i1], norm, normals[i1]);
23
+ vec3.add(normals[i2], norm, normals[i2]);
24
+ });
25
+ normals.forEach((n) => {
26
+ // Normalize accumulated normals.
27
+ vec3.normalize(n, n);
28
+ });
29
+
30
+ return normals;
31
+ }
32
+
33
+ // type ProjectedPlane = 'xy' | 'xz' | 'yz';
34
+ const projectedPlane2Ids = {
35
+ xy: [0, 1],
36
+ xz: [0, 2],
37
+ yz: [1, 2],
38
+ };
39
+
40
+ export function computeProjectedPlaneUVs(positions, projectedPlane) {
41
+ const idxs = projectedPlane2Ids[projectedPlane];
42
+ const uvs = positions.map(() => {
43
+ // Initialize to zero.
44
+ return [0, 0];
45
+ });
46
+ const extentMin = [Infinity, Infinity];
47
+ const extentMax = [-Infinity, -Infinity];
48
+ positions.forEach((pos, i) => {
49
+ // Simply project to the selected plane
50
+ uvs[i][0] = pos[idxs[0]];
51
+ uvs[i][1] = pos[idxs[1]];
52
+
53
+ extentMin[0] = Math.min(pos[idxs[0]], extentMin[0]);
54
+ extentMin[1] = Math.min(pos[idxs[1]], extentMin[1]);
55
+ extentMax[0] = Math.max(pos[idxs[0]], extentMax[0]);
56
+ extentMax[1] = Math.max(pos[idxs[1]], extentMax[1]);
57
+ });
58
+ uvs.forEach((uv) => {
59
+ uv[0] = (uv[0] - extentMin[0]) / (extentMax[0] - extentMin[0]);
60
+ uv[1] = (uv[1] - extentMin[1]) / (extentMax[1] - extentMin[1]);
61
+ });
62
+ return uvs;
63
+ }
@@ -0,0 +1,153 @@
1
+ import {mat4, vec3} from 'wgpu-matrix';
2
+
3
+ export class SpotLight {
4
+ // injected
5
+ camera;
6
+ inputHandler;
7
+
8
+ // Light
9
+ position;
10
+ target;
11
+ up;
12
+ direction;
13
+
14
+ viewMatrix;
15
+ projectionMatrix;
16
+ viewProjMatrix;
17
+
18
+ fov;
19
+ aspect;
20
+ near;
21
+ far;
22
+
23
+ innerCutoff;
24
+ outerCutoff;
25
+
26
+ spotlightUniformBuffer;
27
+
28
+ constructor(
29
+ camera,
30
+ inputHandler,
31
+ position = vec3.create(0, 5, -10),
32
+ target = vec3.create(0, 0, 0),
33
+ fov = 45,
34
+ aspect = 1.0,
35
+ near = 0.1,
36
+ far = 200
37
+ ) {
38
+ this.camera = camera;
39
+ this.inputHandler = inputHandler;
40
+
41
+ this.position = position;
42
+ this.target = target;
43
+ this.up = vec3.create(0, 1, 0);
44
+ this.direction = vec3.normalize(vec3.subtract(target, position));
45
+
46
+ this.viewMatrix = mat4.lookAt(position, target, this.up);
47
+ this.projectionMatrix = mat4.perspective(
48
+ (fov * Math.PI) / 180,
49
+ aspect,
50
+ near,
51
+ far
52
+ );
53
+ this.viewProjMatrix = mat4.multiply(this.projectionMatrix, this.viewMatrix);
54
+
55
+ this.fov = fov;
56
+ this.aspect = aspect;
57
+ this.near = near;
58
+ this.far = far;
59
+
60
+ this.innerCutoff = Math.cos((Math.PI / 180) * 12.5);
61
+ this.outerCutoff = Math.cos((Math.PI / 180) * 17.5);
62
+ }
63
+
64
+ update() {
65
+ // this.direction = vec3.normalize(vec3.subtract(this.target, this.position));
66
+ // this.viewMatrix = mat4.lookAt(this.position, this.target, this.up);
67
+ // this.viewProjMatrix = mat4.multiply(this.projectionMatrix, this.viewMatrix);
68
+ // console.log('test light update this.target : ', this.target)
69
+ // Use the existing direction
70
+ const target = vec3.add(this.position, this.direction);
71
+ this.viewMatrix = mat4.lookAt(this.position, target, this.up);
72
+ this.viewProjMatrix = mat4.multiply(this.projectionMatrix, this.viewMatrix);
73
+ }
74
+
75
+ updateSceneUniforms(mainRenderBundle) {
76
+ const now = Date.now();
77
+ // First frame safety
78
+ let dt = (now - this.lastFrameMS) / 1000;
79
+ if(!this.lastFrameMS) {dt = 16;}
80
+ this.lastFrameMS = now;
81
+ // engine, once per frame
82
+ this.camera.update(dt, this.inputHandler());
83
+ const camVP = mat4.multiply(this.camera.projectionMatrix, this.camera.view); // P * V
84
+
85
+ for(const mesh of mainRenderBundle) {
86
+ // scene buffer layout = 0..63 lightVP, 64..127 camVP, 128..143 lightPos(+pad)
87
+ this.device.queue.writeBuffer(
88
+ mesh.sceneUniformBuffer,
89
+ 64, // cameraViewProjMatrix offset
90
+ camVP.buffer,
91
+ camVP.byteOffset,
92
+ camVP.byteLength
93
+ );
94
+ }
95
+ // const camVP = mat4.multiply(camera.projectionMatrix, camera.view);
96
+ // const sceneData = new Float32Array(36); // 16 + 16 + 4
97
+ // sceneData.set(this.viewProjMatrix, 0);
98
+ // sceneData.set(camVP, 16);
99
+ // sceneData.set(this.position, 32);
100
+ // if(!this.device) {
101
+ // console.warn("Device not set for SpotLight");
102
+ // return;
103
+ // }
104
+ // this.device.queue.writeBuffer(
105
+ // sceneUniformBuffer,
106
+ // // this.spotlightUniformBuffer,
107
+ // 0,
108
+ // sceneData.buffer,
109
+ // sceneData.byteOffset,
110
+ // sceneData.byteLength
111
+ // );
112
+ }
113
+
114
+ prepareBuffer(device) {
115
+ if(!this.device) this.device = device;
116
+ this.spotlightUniformBuffer = this.device.createBuffer({
117
+ size: 16 * 4, // 64 bytes
118
+ usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST,
119
+ });
120
+
121
+ const spotlightData = this.getLightDataBuffer();
122
+ this.device.queue.writeBuffer(
123
+ this.spotlightUniformBuffer,
124
+ 0,
125
+ spotlightData.buffer,
126
+ spotlightData.byteOffset,
127
+ spotlightData.byteLength
128
+ );
129
+ }
130
+
131
+ updateLightBuffer() {
132
+ if(!this.device || !this.spotlightUniformBuffer) {return;}
133
+ const spotlightData = this.getLightDataBuffer();
134
+ this.device.queue.writeBuffer(
135
+ this.spotlightUniformBuffer,
136
+ 0,
137
+ spotlightData.buffer,
138
+ spotlightData.byteOffset,
139
+ spotlightData.byteLength
140
+ );
141
+ }
142
+
143
+ getLightDataBuffer() {
144
+ return new Float32Array([
145
+ ...this.position, 0.0,
146
+ ...this.direction, 0.0,
147
+ this.innerCutoff,
148
+ this.outerCutoff,
149
+ 0.0,
150
+ 0.0,
151
+ ]);
152
+ }
153
+ }