create-definedmotion 0.1.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 (98) hide show
  1. package/bin/index.js +3 -0
  2. package/package.json +37 -0
  3. package/src/cli.js +100 -0
  4. package/template/.editorconfig +9 -0
  5. package/template/.prettierignore +6 -0
  6. package/template/.prettierrc.yaml +10 -0
  7. package/template/_gitignore +10 -0
  8. package/template/build/entitlements.mac.plist +12 -0
  9. package/template/build/icon.icns +0 -0
  10. package/template/build/icon.ico +0 -0
  11. package/template/build/icon.png +0 -0
  12. package/template/electron-builder.yml +43 -0
  13. package/template/electron.vite.config.ts +50 -0
  14. package/template/eslint.config.mjs +24 -0
  15. package/template/package-lock.json +10299 -0
  16. package/template/package.json +64 -0
  17. package/template/resources/icon.png +0 -0
  18. package/template/src/assets/audio/fadeSound.mp3 +0 -0
  19. package/template/src/assets/audio/fadeSound2.mp3 +0 -0
  20. package/template/src/assets/audio/interstellar.mp3 +0 -0
  21. package/template/src/assets/audio/keyboard1.mp3 +0 -0
  22. package/template/src/assets/audio/keyboard2.mp3 +0 -0
  23. package/template/src/assets/audio/keyboard3.mp3 +0 -0
  24. package/template/src/assets/audio/tick_sound.mp3 +0 -0
  25. package/template/src/assets/base.css +67 -0
  26. package/template/src/assets/electron.svg +10 -0
  27. package/template/src/assets/fonts/Geo-Regular.woff +0 -0
  28. package/template/src/assets/fonts/Montserrat-Italic-VariableFont_wght.woff2 +0 -0
  29. package/template/src/assets/fonts/Montserrat-Medium.ttf +0 -0
  30. package/template/src/assets/fonts/Montserrat-Medium.woff +0 -0
  31. package/template/src/assets/fonts/Montserrat-VariableFont_wght.woff2 +0 -0
  32. package/template/src/assets/fonts/glitch.ttf +0 -0
  33. package/template/src/assets/hdri/indoor1.hdr +0 -0
  34. package/template/src/assets/hdri/metro1.hdr +0 -0
  35. package/template/src/assets/hdri/outdoor1.hdr +0 -0
  36. package/template/src/assets/hdri/photo-studio1.hdr +0 -0
  37. package/template/src/assets/hdri/photo-studio2.hdr +0 -0
  38. package/template/src/assets/hdri/photo-studio3.hdr +0 -0
  39. package/template/src/assets/objects/keyboardScene/ibm-keyboard.glb +0 -0
  40. package/template/src/assets/wavy-lines.svg +25 -0
  41. package/template/src/entry.ts +20 -0
  42. package/template/src/example_scenes/alternativesScene.ts +88 -0
  43. package/template/src/example_scenes/dependencyScene.ts +116 -0
  44. package/template/src/example_scenes/fourierMachineScene.ts +108 -0
  45. package/template/src/example_scenes/fourierSeriesScene.ts +678 -0
  46. package/template/src/example_scenes/keyboardScene.ts +447 -0
  47. package/template/src/example_scenes/surfaceScene.ts +88 -0
  48. package/template/src/example_scenes/tutorials/easy1.ts +59 -0
  49. package/template/src/example_scenes/tutorials/easy2.ts +141 -0
  50. package/template/src/example_scenes/tutorials/easy3.ts +133 -0
  51. package/template/src/example_scenes/tutorials/medium1.ts +154 -0
  52. package/template/src/example_scenes/vectorField.ts +209 -0
  53. package/template/src/example_scenes/visulizingFunctions.ts +246 -0
  54. package/template/src/main/index.ts +101 -0
  55. package/template/src/main/rendering.ts +219 -0
  56. package/template/src/main/storage.ts +35 -0
  57. package/template/src/preload/index.d.ts +8 -0
  58. package/template/src/preload/index.ts +36 -0
  59. package/template/src/renderer/index.html +17 -0
  60. package/template/src/renderer/src/App.svelte +130 -0
  61. package/template/src/renderer/src/app.css +24 -0
  62. package/template/src/renderer/src/env.d.ts +2 -0
  63. package/template/src/renderer/src/lib/animation/animations.ts +214 -0
  64. package/template/src/renderer/src/lib/animation/captureCanvas.ts +85 -0
  65. package/template/src/renderer/src/lib/animation/helpers.ts +7 -0
  66. package/template/src/renderer/src/lib/animation/interpolations.ts +155 -0
  67. package/template/src/renderer/src/lib/animation/protocols.ts +79 -0
  68. package/template/src/renderer/src/lib/audio/loader.ts +104 -0
  69. package/template/src/renderer/src/lib/fonts/Roboto_Regular.json +1 -0
  70. package/template/src/renderer/src/lib/fonts/montserrat-medium.json +1 -0
  71. package/template/src/renderer/src/lib/fonts/montserrat.json +1 -0
  72. package/template/src/renderer/src/lib/general/helpers.ts +77 -0
  73. package/template/src/renderer/src/lib/general/onDestory.ts +10 -0
  74. package/template/src/renderer/src/lib/mathHelpers/vectors.ts +18 -0
  75. package/template/src/renderer/src/lib/rendering/bumpMaps/noise.ts +84 -0
  76. package/template/src/renderer/src/lib/rendering/helpers.ts +35 -0
  77. package/template/src/renderer/src/lib/rendering/lighting3d.ts +387 -0
  78. package/template/src/renderer/src/lib/rendering/materials.ts +6 -0
  79. package/template/src/renderer/src/lib/rendering/objects/import.ts +148 -0
  80. package/template/src/renderer/src/lib/rendering/objects2d.ts +489 -0
  81. package/template/src/renderer/src/lib/rendering/objects3d.ts +89 -0
  82. package/template/src/renderer/src/lib/rendering/protocols.ts +21 -0
  83. package/template/src/renderer/src/lib/rendering/setup.ts +71 -0
  84. package/template/src/renderer/src/lib/rendering/svg/drawing.ts +213 -0
  85. package/template/src/renderer/src/lib/rendering/svg/parsing.ts +717 -0
  86. package/template/src/renderer/src/lib/rendering/svg/rastered.ts +42 -0
  87. package/template/src/renderer/src/lib/rendering/svgObjects.ts +1137 -0
  88. package/template/src/renderer/src/lib/scene/helpers.ts +89 -0
  89. package/template/src/renderer/src/lib/scene/sceneClass.ts +648 -0
  90. package/template/src/renderer/src/lib/shaders/background_gradient/frag.glsl +12 -0
  91. package/template/src/renderer/src/lib/shaders/background_gradient/vert.glsl +6 -0
  92. package/template/src/renderer/src/lib/shaders/hdri_blur/frag.glsl +45 -0
  93. package/template/src/renderer/src/lib/shaders/hdri_blur/vert.glsl +5 -0
  94. package/template/src/renderer/src/main.ts +9 -0
  95. package/template/svelte.config.mjs +7 -0
  96. package/template/tsconfig.json +4 -0
  97. package/template/tsconfig.node.json +10 -0
  98. package/template/tsconfig.web.json +32 -0
@@ -0,0 +1,447 @@
1
+ import {
2
+ addBackgroundGradient,
3
+ addHDRI,
4
+ addSceneLighting,
5
+ HDRIs,
6
+ loadHDRIData
7
+ } from '../renderer/src/lib/rendering/lighting3d'
8
+ import { loadGLB } from '../renderer/src/lib/rendering/objects/import'
9
+ import { AnimatedScene, HotReloadSetting, SpaceSetting } from '../renderer/src/lib/scene/sceneClass'
10
+ import * as THREE from 'three'
11
+ import ibmKeyboard from '$assets/objects/keyboardScene/ibm-keyboard.glb?url'
12
+ import { createBumpMap } from '../renderer/src/lib/rendering/bumpMaps/noise'
13
+ import { moveRotateCameraAnimation3D } from '../renderer/src/lib/animation/animations'
14
+ import { createAnim } from '../renderer/src/lib/animation/protocols'
15
+ import { easeLinear } from '../renderer/src/lib/animation/interpolations'
16
+ import { createFastText, createLine, updateText } from '../renderer/src/lib/rendering/objects2d'
17
+ import { COLORS } from '../renderer/src/lib/rendering/helpers'
18
+ import tickSound from '$assets/audio/tick_sound.mp3'
19
+ import keyboard1 from '$assets/audio/keyboard1.mp3'
20
+
21
+ const strokeColor = '#ff0000'
22
+ const backCharacter = 'Ď'
23
+
24
+ const keyPositions: { [key: string]: () => [[number, number, number], [number, number]] } = {
25
+ //Number row
26
+ '1': () => [
27
+ [-3.95, 0.95, -0.07],
28
+ [0.35, 0.35]
29
+ ],
30
+ '2': () => nextKeyX(keyPositions['1']()),
31
+ '3': () => nextKeyX(keyPositions['2']()),
32
+ '4': () => nextKeyX(keyPositions['3']()),
33
+ '5': () => nextKeyX(keyPositions['4']()),
34
+ '6': () => nextKeyX(keyPositions['5']()),
35
+ '7': () => nextKeyX(keyPositions['6']()),
36
+ '8': () => nextKeyX(keyPositions['7']()),
37
+ '9': () => nextKeyX(keyPositions['8']()),
38
+ '0': () => nextKeyX(keyPositions['9']()),
39
+ '-': () => nextKeyX(keyPositions['0']()),
40
+ '=': () => nextKeyX(keyPositions['-']()),
41
+
42
+ // First Row (QWERTYUIOP{})
43
+ Q: () => [
44
+ [-3.75, 0.85, 0.3],
45
+ [0.35, 0.35]
46
+ ],
47
+ W: () => nextKeyX(keyPositions['Q']()),
48
+ E: () => nextKeyX(keyPositions['W']()),
49
+ R: () => nextKeyX(keyPositions['E']()),
50
+ T: () => nextKeyX(keyPositions['R']()),
51
+ Y: () => nextKeyX(keyPositions['T']()),
52
+ U: () => nextKeyX(keyPositions['Y']()),
53
+ I: () => nextKeyX(keyPositions['U']()),
54
+ O: () => nextKeyX(keyPositions['I']()),
55
+ P: () => nextKeyX(keyPositions['O']()),
56
+ '{': () => nextKeyX(keyPositions['P']()),
57
+ '}': () => nextKeyX(keyPositions['{']()),
58
+
59
+ // Second Row (ASDFGHJKL;')
60
+ A: () => [
61
+ [-3.65, 0.78, 0.7],
62
+ [0.35, 0.35]
63
+ ], // Slightly offset right and lower than Q
64
+ S: () => nextKeyX(keyPositions['A']()),
65
+ D: () => nextKeyX(keyPositions['S']()),
66
+ F: () => nextKeyX(keyPositions['D']()),
67
+ G: () => nextKeyX(keyPositions['F']()),
68
+ H: () => nextKeyX(keyPositions['G']()),
69
+ J: () => nextKeyX(keyPositions['H']()),
70
+ K: () => nextKeyX(keyPositions['J']()),
71
+ L: () => nextKeyX(keyPositions['K']()),
72
+ ';': () => nextKeyX(keyPositions['L']()),
73
+ "'": () => nextKeyX(keyPositions[';']()),
74
+
75
+ // Third Row (ZXCVBNM,./)
76
+ Z: () => [
77
+ [-3.45, 0.71, 1.05],
78
+ [0.35, 0.35]
79
+ ], // Further offset right and lower than A
80
+ X: () => nextKeyX(keyPositions['Z']()),
81
+ C: () => nextKeyX(keyPositions['X']()),
82
+ V: () => nextKeyX(keyPositions['C']()),
83
+ B: () => nextKeyX(keyPositions['V']()),
84
+ N: () => nextKeyX(keyPositions['B']()),
85
+ M: () => nextKeyX(keyPositions['N']()),
86
+ ',': () => nextKeyX(keyPositions['M']()),
87
+ '.': () => nextKeyX(keyPositions[',']()),
88
+ '/': () => nextKeyX(keyPositions['.']()), // Last key, no trailing comma
89
+
90
+ Space: () => [
91
+ [-1.64, 0.7, 1.4],
92
+ [2.65, 0.35]
93
+ ],
94
+
95
+ [backCharacter]: () => [
96
+ [0.9, 0.93, -0.07],
97
+ [0.7, 0.35]
98
+ ]
99
+ }
100
+
101
+ const translateToKey = (char: string): string => {
102
+ const symbolToKey: { [key: string]: string } = {
103
+ '!': '1',
104
+ '@': '2',
105
+ '#': '3',
106
+ $: '4',
107
+ '%': '5',
108
+ '^': '6',
109
+ '&': '7',
110
+ '*': '8',
111
+ '(': '9',
112
+ ')': '0',
113
+ _: '-',
114
+ '+': '=',
115
+ '{': '[',
116
+ '}': ']',
117
+ '|': '\\',
118
+ ':': ';',
119
+ '"': "'",
120
+ '<': ',',
121
+ '>': '.',
122
+ '?': '/',
123
+ '~': '`',
124
+ ' ': 'Space' // Add "Space" to keyPositions if needed
125
+ }
126
+
127
+ if (char === backCharacter) return backCharacter
128
+
129
+ // Handle letters (convert to uppercase)
130
+ if (/^[a-z]$/i.test(char)) return char.toUpperCase()
131
+ // Handle symbols
132
+ return symbolToKey[char] || char // Fallback to the original char if no mapping
133
+ }
134
+
135
+ const nextKeyX = (
136
+ current: [[number, number, number], [number, number]]
137
+ ): [[number, number, number], [number, number]] => {
138
+ const newPos: [number, number, number] = [...current[0]]
139
+ newPos[0] += 0.385
140
+ return [newPos, current[1]]
141
+ }
142
+
143
+ let lastStroke: undefined | THREE.Mesh
144
+ let pointLight: undefined | THREE.PointLight
145
+
146
+ const setPosition = (scene: THREE.Scene, letter: string) => {
147
+ if (lastStroke !== undefined) {
148
+ scene.remove(lastStroke)
149
+ }
150
+ const position = keyPositions[letter]()[0]
151
+ const keyStroke = keyStrokePlane(...keyPositions[letter]()[1])
152
+ keyStroke.position.set(...position)
153
+
154
+ if (pointLight === undefined || !scene.children.includes(pointLight)) {
155
+ pointLight = new THREE.PointLight(strokeColor, 10)
156
+ pointLight.castShadow = true
157
+ scene.add(pointLight)
158
+ }
159
+ position[1] += 1.5
160
+ pointLight.position.set(...position)
161
+
162
+ scene.add(keyStroke)
163
+ lastStroke = keyStroke
164
+ return { keyStroke, pointLight }
165
+ }
166
+
167
+ const bumpMap = createBumpMap({
168
+ width: 5000,
169
+ height: 5000,
170
+ noiseAlgorithm: 'random',
171
+ intensity: 0.1
172
+ })
173
+
174
+ const keyboard = await loadGLB(ibmKeyboard)
175
+
176
+ const createPlane = (width: number, height: number, bumpMap?: THREE.CanvasTexture) => {
177
+ // Create the plane geometry
178
+ const geometry = new THREE.PlaneGeometry(width, height)
179
+
180
+ // Create a basic material
181
+ // Use MeshBasicMaterial if you do not need lighting or effects – this is ideal for 2D shapes
182
+ const material = new THREE.MeshStandardMaterial({
183
+ color: '#ffffff', // Green color
184
+ side: THREE.DoubleSide, // Render both sides
185
+ bumpMap,
186
+ metalness: 0.8,
187
+ roughness: 0.1
188
+ })
189
+
190
+ // Combine the geometry and material into a mesh
191
+ const plane = new THREE.Mesh(geometry, material)
192
+ plane.receiveShadow = true
193
+ plane.rotateX(Math.PI / 2)
194
+
195
+ return plane
196
+ }
197
+
198
+ const keyStrokePlane = (width: number, height: number, bumpMap?: THREE.CanvasTexture) => {
199
+ // Create the plane geometry
200
+ const geometry = new THREE.PlaneGeometry(width, height)
201
+
202
+ // Create a basic material
203
+ // Use MeshBasicMaterial if you do not need lighting or effects – this is ideal for 2D shapes
204
+ const material = new THREE.MeshBasicMaterial({
205
+ color: strokeColor, // Green color
206
+ side: THREE.DoubleSide, // Render both sides
207
+ transparent: true,
208
+ opacity: 0.5
209
+ })
210
+
211
+ // Combine the geometry and material into a mesh
212
+ const plane = new THREE.Mesh(geometry, material)
213
+ plane.receiveShadow = true
214
+ plane.rotateX(Math.PI / 2)
215
+
216
+ return plane
217
+ }
218
+
219
+ const setText = async (textNode: any, addedCharacter: string) => {
220
+ // Ensure historyTextStore is initialized
221
+ if (!textNode.historyTextStore) {
222
+ textNode.historyTextStore = ''
223
+ }
224
+
225
+ const numberVisible = 28
226
+
227
+ // Get visible text (without ellipsis if present)
228
+ const visibleText = textNode.text.startsWith('...') ? textNode.text.slice(3) : textNode.text
229
+
230
+ // Reconstruct full text from history and visible portion
231
+ let fullText = textNode.historyTextStore + visibleText
232
+
233
+ // Process the input character
234
+ if (addedCharacter === backCharacter) {
235
+ // Handle backspace: remove last character if exists
236
+ if (fullText.length > 0) {
237
+ fullText = fullText.slice(0, -1)
238
+ }
239
+ } else {
240
+ // Append new character normally
241
+ fullText += addedCharacter
242
+ }
243
+
244
+ // Update text storage and visible text
245
+ if (fullText.length > numberVisible) {
246
+ // Split into new history and visible portions
247
+ const newVisible = fullText.slice(-numberVisible)
248
+ textNode.historyTextStore = fullText.slice(0, fullText.length - numberVisible)
249
+ textNode.text = '...' + newVisible
250
+ } else {
251
+ // Show full text without ellipsis
252
+ textNode.text = fullText
253
+ textNode.historyTextStore = ''
254
+ }
255
+
256
+ // Update the text node
257
+ await updateText(textNode, textNode.text)
258
+ }
259
+ const typeAnimation = (scene: AnimatedScene, characters: string, textNode: any, speed: number) => {
260
+ let lastIndex = -1
261
+ let keyStroke: THREE.Mesh | undefined
262
+ let pointLight: THREE.PointLight | undefined
263
+ let lastCharacter
264
+ const animation = createAnim(
265
+ easeLinear(0, 1, characters.length * speed),
266
+ async (value, _, isLast) => {
267
+ const index = Math.round(value * (characters.length - 1))
268
+ const character = characters[index]
269
+
270
+ if (index !== lastIndex) {
271
+ lastIndex = index
272
+ ;({ keyStroke, pointLight } = setPosition(scene.scene, translateToKey(character)))
273
+ await setText(textNode, character)
274
+ if (lastCharacter === backCharacter && character === backCharacter) {
275
+ } else {
276
+ scene.playAudio(keyboard1, character === backCharacter || character === ' ' ? 0.5 : 0.2)
277
+ scene.playAudio(tickSound, character === ' ' ? 0.2 : 0.05)
278
+ }
279
+ lastCharacter = character
280
+ }
281
+
282
+ if (isLast) {
283
+ setTimeout(() => {
284
+ if (keyStroke) {
285
+ scene.scene.remove(keyStroke)
286
+ }
287
+ if (pointLight) {
288
+ scene.scene.remove(pointLight)
289
+ }
290
+ }, 500)
291
+ }
292
+ }
293
+ )
294
+
295
+ return animation
296
+ }
297
+
298
+ const hdriData = await loadHDRIData(HDRIs.photoStudio1, 2, 0.5)
299
+
300
+ export const keyboardScene = (): AnimatedScene => {
301
+ return new AnimatedScene(
302
+ 1080,
303
+ 2160,
304
+ SpaceSetting.ThreeDim,
305
+ HotReloadSetting.TraceFromStart,
306
+ async (scene) => {
307
+ scene.registerAudio(tickSound)
308
+ scene.registerAudio(keyboard1)
309
+ addSceneLighting(scene.scene, { intensity: 1, colorScheme: 'cool' })
310
+
311
+ scene.renderer.shadowMap.enabled = true
312
+ await addHDRI(scene, hdriData, 0.65)
313
+ addBackgroundGradient({
314
+ scene,
315
+ topColor: COLORS.blue,
316
+ bottomColor: COLORS.black,
317
+ lightingIntensity: 10
318
+ })
319
+ keyboard.scale.set(20, 20, 20)
320
+ scene.add(keyboard)
321
+
322
+ scene.do(() => {
323
+ scene.camera.position.set(-2.264274, 2.223899, 25.48552)
324
+ scene.camera.quaternion.set(-0.0590337, -0.005013175, -0.0002964671, 0.9982434)
325
+ })
326
+
327
+ const targetPos = new THREE.Vector3(-2.151799 - 1, 22.90854, 1.769867 + 1).multiplyScalar(
328
+ 0.65
329
+ )
330
+ const targetRot = new THREE.Quaternion(-0.6683053, -0.001480137, -0.001329754, 0.7438844)
331
+
332
+ scene.addAnim(
333
+ moveRotateCameraAnimation3D(
334
+ scene.camera,
335
+ scene.camera.position,
336
+ scene.camera.quaternion,
337
+ targetPos,
338
+ targetRot,
339
+ 1000
340
+ )
341
+ )
342
+
343
+ const rotateAnim = moveRotateCameraAnimation3D(
344
+ scene.camera,
345
+ targetPos,
346
+ targetRot,
347
+ new THREE.Vector3(-2.196693 - 1, 20.67784, 9.621079 + 1).multiplyScalar(0.65),
348
+ new THREE.Quaternion(-0.5668163, -0.003930429, -0.002704235, 0.8238304),
349
+ 4000
350
+ )
351
+
352
+ scene.addSequentialBackgroundAnims(
353
+ ...Array(10)
354
+ .fill(0)
355
+ .flatMap(() => [rotateAnim, rotateAnim.copy().reverse()])
356
+ )
357
+
358
+ const lightY = 5
359
+ const lightX = -2
360
+ const pointLight = new THREE.PointLight('#ffffff', 40) // color, intensity, distance
361
+ pointLight.position.y = lightY
362
+ pointLight.position.x = lightX
363
+ pointLight.position.z = -0.5
364
+ //pointLight.castShadow = true
365
+
366
+ // scene.add(pointLight)
367
+
368
+ const texturePlane = createPlane(80, 80, bumpMap)
369
+ const largePlane = createPlane(1000, 1000)
370
+ largePlane.position.y = -0.1
371
+ // Add the plane to the scene
372
+ scene.add(texturePlane)
373
+ scene.add(largePlane)
374
+ ;(scene.camera as THREE.PerspectiveCamera).setFocalLength(25)
375
+
376
+ //setPosition(scene.scene, translateToKey(' '))
377
+
378
+ const text = await createFastText('', 0.4)
379
+ text.rotateX(-Math.PI / 2)
380
+ text.position.y = 0.02
381
+
382
+ text.position.z = -3.5
383
+ text.position.x = -5
384
+
385
+ text.anchorX = 'left'
386
+ text.anchorY = 'bottom'
387
+ text.material.opacity = 0.8
388
+ scene.add(text)
389
+
390
+ const point1 = new THREE.Vector3(-5, 0.05, -3.4)
391
+ const line = createLine({ point1, point2: point1.clone().add(new THREE.Vector3(6, 0, 0)) })
392
+ scene.add(line)
393
+
394
+ const typeSpeed = 70
395
+ const deleteSpeed = 30
396
+
397
+ const line1 = 'Hello Instagram!'
398
+ scene.addAnim(typeAnimation(scene, line1, text, typeSpeed))
399
+ scene.addWait(1000)
400
+ scene.addAnim(
401
+ typeAnimation(scene, [...line1].map(() => backCharacter).join(''), text, deleteSpeed)
402
+ )
403
+
404
+ scene.addWait(300)
405
+ const line2 = 'I am just testing my programmatic animation library!'
406
+ scene.addAnim(typeAnimation(scene, line2, text, typeSpeed))
407
+ scene.addWait(1000)
408
+ scene.addAnim(
409
+ typeAnimation(scene, [...line2].map(() => backCharacter).join(''), text, deleteSpeed)
410
+ )
411
+
412
+ scene.addWait(300)
413
+ const line3 = `It is inspired by 3Blue1Brown's Manim and Motion Canvas. It is meant for technical and mathematical animations!`
414
+ scene.addAnim(typeAnimation(scene, line3, text, typeSpeed))
415
+ scene.addWait(1000)
416
+ scene.addAnim(
417
+ typeAnimation(scene, [...line3].map(() => backCharacter).join(''), text, deleteSpeed)
418
+ )
419
+
420
+ scene.addWait(300)
421
+ const line4 =
422
+ 'One of its features is that when you save your code, the animation updates immediately in the viewport. No need to render the video, open the file and then see the result!'
423
+ scene.addAnim(typeAnimation(scene, line4, text, typeSpeed))
424
+ scene.addWait(1000)
425
+ scene.addAnim(
426
+ typeAnimation(scene, [...line4].map(() => backCharacter).join(''), text, deleteSpeed)
427
+ )
428
+
429
+ scene.addWait(300)
430
+ const line5 = `Use the project by visiting "DefinedMotion" by Hugo Olsson on GitHub, thanks!`
431
+ scene.addAnim(typeAnimation(scene, line5, text, typeSpeed))
432
+ scene.addWait(1000)
433
+ scene.addAnim(
434
+ typeAnimation(scene, [...line5].map(() => backCharacter).join(''), text, deleteSpeed)
435
+ )
436
+
437
+ const initialZoom = scene.camera.zoom
438
+ scene.onEachTick(async (tick, time) => {
439
+ pointLight.position.y = lightY * (1 + Math.sin(time / 500) / 10)
440
+ pointLight.position.x = lightX * (1 + Math.sin(time / 500) / 10)
441
+ scene.camera.zoom = initialZoom * (1.3 + Math.sin(time / 1000) / 20)
442
+ //await barChart.updateData(frequencyMap)
443
+ })
444
+ scene.addWait(3000)
445
+ }
446
+ )
447
+ }
@@ -0,0 +1,88 @@
1
+ import { COLORS } from '../renderer/src/lib/rendering/helpers'
2
+ import { addBackgroundGradient } from '../renderer/src/lib/rendering/lighting3d'
3
+ import {
4
+ createFunctionSurface,
5
+ updateFunctionSurface
6
+ } from '../renderer/src/lib/rendering/objects3d'
7
+ import { AnimatedScene, HotReloadSetting, SpaceSetting } from '../renderer/src/lib/scene/sceneClass'
8
+ import * as THREE from 'three'
9
+
10
+ const surfaceMaterial = new THREE.MeshStandardMaterial({
11
+ color: 0xffffff,
12
+ metalness: 0.8,
13
+ roughness: 0.1,
14
+ side: THREE.DoubleSide
15
+ }) as any
16
+
17
+ const sphereMaterial = new THREE.MeshStandardMaterial({
18
+ color: 0x000000,
19
+ emissive: 0xffffff,
20
+ emissiveIntensity: 200.0
21
+ })
22
+
23
+ const sineTimeFunction = (time: number): ((a: number, b: number) => number) => {
24
+ return (a: number, b: number) =>
25
+ (5 * (Math.sin(a * 2 + time) * Math.cos(b * 2 + time))) /
26
+ (Math.pow(Math.abs(a) + Math.abs(b), 2) + 5) +
27
+ 3
28
+ }
29
+
30
+ export const surfaceScene = (): AnimatedScene => {
31
+ return new AnimatedScene(
32
+ 1500,
33
+ 1500,
34
+ SpaceSetting.ThreeDim,
35
+ HotReloadSetting.BeginFromCurrent,
36
+ async (scene) => {
37
+ const funcMinMaxes: [number, number, number, number] = [-7, 7, -7, 7]
38
+
39
+ addBackgroundGradient({
40
+ scene,
41
+ topColor: COLORS.blue,
42
+ bottomColor: COLORS.black,
43
+ lightingIntensity: 10
44
+ })
45
+
46
+ const gridHelper = new THREE.GridHelper(20, 20)
47
+ const axesHelper = new THREE.AxesHelper(20)
48
+
49
+ const sineSurface = createFunctionSurface(sineTimeFunction(0), ...funcMinMaxes)
50
+ sineSurface.material = surfaceMaterial
51
+
52
+ const geometry = new THREE.SphereGeometry(1, 32, 32)
53
+ const material = sphereMaterial
54
+
55
+ const sphere = new THREE.Mesh(geometry, material)
56
+ const pointLight = new THREE.PointLight(0xffffff, 50) // color, intensity, distance
57
+ pointLight.position.copy(sphere.position)
58
+ const group = new THREE.Group()
59
+ group.add(sphere, pointLight)
60
+
61
+ scene.add(gridHelper, axesHelper, sineSurface, group)
62
+
63
+ scene.camera.position.set(3.889329, 7.895859, 10.51772)
64
+ scene.camera.rotation.set(-0.6027059, 0.3079325, 0.2056132)
65
+ const centerPoint = new THREE.Vector3(0, 0, 0)
66
+ const distance = scene.camera.position.distanceTo(centerPoint)
67
+ let angle = 0
68
+
69
+ scene.onEachTick((tick) => {
70
+ const func = sineTimeFunction(tick / 20)
71
+ updateFunctionSurface(sineSurface, func, ...funcMinMaxes)
72
+
73
+ group.position.y = 6
74
+
75
+ angle += 0.005
76
+
77
+ // Set camera position in circular orbit
78
+ scene.camera.position.x = (Math.sin(angle) * distance * (Math.sin(tick / 50) + 2)) / 2
79
+ scene.camera.position.z = (Math.cos(angle) * distance * (Math.sin(tick / 50) + 2)) / 2
80
+
81
+ // Make camera look at center
82
+ scene.camera.lookAt(centerPoint)
83
+ })
84
+
85
+ scene.addWait(10_000)
86
+ }
87
+ )
88
+ }
@@ -0,0 +1,59 @@
1
+ import { concatInterpols, easeInOutQuad, posXSigmoid } from '$renderer/lib/animation/interpolations'
2
+ import { createAnim } from '$renderer/lib/animation/protocols'
3
+ import { createCircle } from '$renderer/lib/rendering/objects2d'
4
+ import { AnimatedScene, HotReloadSetting, SpaceSetting } from '$renderer/lib/scene/sceneClass'
5
+
6
+ import * as THREE from 'three'
7
+
8
+ // Goal for this animation:
9
+ // Move a circle back and forth and continually change its color
10
+
11
+ // Step 1: Create function that returns AnimatedScene
12
+ export function tutorial_easy1(): AnimatedScene {
13
+ // We return an animated scene that has some settings and lastly has a callback function
14
+ // The first two parameters are resolution, this will be a vertical clip
15
+ // The third argument sets if we want 3D or 2D
16
+ // The forth allows us to say how hot reload should be handled,
17
+ // With trace from start, at hot reload, the actions of all frames before the current, will be accounted for.
18
+ // If you don't have accumulative changes (or if its fine without for debug), then it's much faster to use "HotReloadSetting.BeginFromCurrent" since it will only have to calculate the current frames actions.
19
+
20
+ return new AnimatedScene(
21
+ 1080,
22
+ 1920,
23
+ SpaceSetting.TwoDim,
24
+ HotReloadSetting.TraceFromStart,
25
+ (scene) => {
26
+ // Helper function to create a "THREE.CircleGeometry"
27
+ // You can just use any Three.js code if you want
28
+ const circle = createCircle(5)
29
+
30
+ // Add our circle to the scene
31
+ scene.add(circle)
32
+
33
+ // Create an animation that makes it move from left to right
34
+ // This is very modular and easy to build on
35
+ // createAnim takes two argument, an interpolation (just calculated number[]), and a call back function where you can use each value
36
+ // So here we are creating the interpolation with easeInOutQuad: number[]
37
+ // And give a function that is called for each frame with the current interpolation value
38
+ const anim = createAnim(easeInOutQuad(-5, 5, 500), (value) => (circle.position.x = value))
39
+
40
+ // We use "addAnim" to schedule an animation, it will run from the frame (tick) it was added at
41
+ // Since this is our first added animation in this scene, we are currently at tick 0, So it will just add to the start.
42
+ // But say that we are in a complex animation and our previous buildings would mean that we are at frame 49878 for example (we wouldn't know this)
43
+ // Then it just adds the animation with that offset
44
+ scene.addAnim(anim)
45
+
46
+ // To make the circle also go back, we can reverse the entire animation and add it again
47
+ // Notice that we are copying it, this is so that the reverse() doesn't affect the original variable "anim"
48
+ scene.addAnim(anim.copy().reverse())
49
+
50
+ // We now finally add a function that will be called at each frame (tick) in our animation
51
+ // This doesn't push the tick forward like the "addAnim" does.
52
+ // It just declares a function that should be run at each frame
53
+ // For this animation, we want to set a color to the circle at each frame.
54
+ scene.onEachTick((tick) => {
55
+ circle.material.color = new THREE.Color().setRGB(posXSigmoid(circle.position.x / 4), 1, 1)
56
+ })
57
+ }
58
+ )
59
+ }