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.
- package/bin/index.js +3 -0
- package/package.json +37 -0
- package/src/cli.js +100 -0
- package/template/.editorconfig +9 -0
- package/template/.prettierignore +6 -0
- package/template/.prettierrc.yaml +10 -0
- package/template/_gitignore +10 -0
- package/template/build/entitlements.mac.plist +12 -0
- package/template/build/icon.icns +0 -0
- package/template/build/icon.ico +0 -0
- package/template/build/icon.png +0 -0
- package/template/electron-builder.yml +43 -0
- package/template/electron.vite.config.ts +50 -0
- package/template/eslint.config.mjs +24 -0
- package/template/package-lock.json +10299 -0
- package/template/package.json +64 -0
- package/template/resources/icon.png +0 -0
- package/template/src/assets/audio/fadeSound.mp3 +0 -0
- package/template/src/assets/audio/fadeSound2.mp3 +0 -0
- package/template/src/assets/audio/interstellar.mp3 +0 -0
- package/template/src/assets/audio/keyboard1.mp3 +0 -0
- package/template/src/assets/audio/keyboard2.mp3 +0 -0
- package/template/src/assets/audio/keyboard3.mp3 +0 -0
- package/template/src/assets/audio/tick_sound.mp3 +0 -0
- package/template/src/assets/base.css +67 -0
- package/template/src/assets/electron.svg +10 -0
- package/template/src/assets/fonts/Geo-Regular.woff +0 -0
- package/template/src/assets/fonts/Montserrat-Italic-VariableFont_wght.woff2 +0 -0
- package/template/src/assets/fonts/Montserrat-Medium.ttf +0 -0
- package/template/src/assets/fonts/Montserrat-Medium.woff +0 -0
- package/template/src/assets/fonts/Montserrat-VariableFont_wght.woff2 +0 -0
- package/template/src/assets/fonts/glitch.ttf +0 -0
- package/template/src/assets/hdri/indoor1.hdr +0 -0
- package/template/src/assets/hdri/metro1.hdr +0 -0
- package/template/src/assets/hdri/outdoor1.hdr +0 -0
- package/template/src/assets/hdri/photo-studio1.hdr +0 -0
- package/template/src/assets/hdri/photo-studio2.hdr +0 -0
- package/template/src/assets/hdri/photo-studio3.hdr +0 -0
- package/template/src/assets/objects/keyboardScene/ibm-keyboard.glb +0 -0
- package/template/src/assets/wavy-lines.svg +25 -0
- package/template/src/entry.ts +20 -0
- package/template/src/example_scenes/alternativesScene.ts +88 -0
- package/template/src/example_scenes/dependencyScene.ts +116 -0
- package/template/src/example_scenes/fourierMachineScene.ts +108 -0
- package/template/src/example_scenes/fourierSeriesScene.ts +678 -0
- package/template/src/example_scenes/keyboardScene.ts +447 -0
- package/template/src/example_scenes/surfaceScene.ts +88 -0
- package/template/src/example_scenes/tutorials/easy1.ts +59 -0
- package/template/src/example_scenes/tutorials/easy2.ts +141 -0
- package/template/src/example_scenes/tutorials/easy3.ts +133 -0
- package/template/src/example_scenes/tutorials/medium1.ts +154 -0
- package/template/src/example_scenes/vectorField.ts +209 -0
- package/template/src/example_scenes/visulizingFunctions.ts +246 -0
- package/template/src/main/index.ts +101 -0
- package/template/src/main/rendering.ts +219 -0
- package/template/src/main/storage.ts +35 -0
- package/template/src/preload/index.d.ts +8 -0
- package/template/src/preload/index.ts +36 -0
- package/template/src/renderer/index.html +17 -0
- package/template/src/renderer/src/App.svelte +130 -0
- package/template/src/renderer/src/app.css +24 -0
- package/template/src/renderer/src/env.d.ts +2 -0
- package/template/src/renderer/src/lib/animation/animations.ts +214 -0
- package/template/src/renderer/src/lib/animation/captureCanvas.ts +85 -0
- package/template/src/renderer/src/lib/animation/helpers.ts +7 -0
- package/template/src/renderer/src/lib/animation/interpolations.ts +155 -0
- package/template/src/renderer/src/lib/animation/protocols.ts +79 -0
- package/template/src/renderer/src/lib/audio/loader.ts +104 -0
- package/template/src/renderer/src/lib/fonts/Roboto_Regular.json +1 -0
- package/template/src/renderer/src/lib/fonts/montserrat-medium.json +1 -0
- package/template/src/renderer/src/lib/fonts/montserrat.json +1 -0
- package/template/src/renderer/src/lib/general/helpers.ts +77 -0
- package/template/src/renderer/src/lib/general/onDestory.ts +10 -0
- package/template/src/renderer/src/lib/mathHelpers/vectors.ts +18 -0
- package/template/src/renderer/src/lib/rendering/bumpMaps/noise.ts +84 -0
- package/template/src/renderer/src/lib/rendering/helpers.ts +35 -0
- package/template/src/renderer/src/lib/rendering/lighting3d.ts +387 -0
- package/template/src/renderer/src/lib/rendering/materials.ts +6 -0
- package/template/src/renderer/src/lib/rendering/objects/import.ts +148 -0
- package/template/src/renderer/src/lib/rendering/objects2d.ts +489 -0
- package/template/src/renderer/src/lib/rendering/objects3d.ts +89 -0
- package/template/src/renderer/src/lib/rendering/protocols.ts +21 -0
- package/template/src/renderer/src/lib/rendering/setup.ts +71 -0
- package/template/src/renderer/src/lib/rendering/svg/drawing.ts +213 -0
- package/template/src/renderer/src/lib/rendering/svg/parsing.ts +717 -0
- package/template/src/renderer/src/lib/rendering/svg/rastered.ts +42 -0
- package/template/src/renderer/src/lib/rendering/svgObjects.ts +1137 -0
- package/template/src/renderer/src/lib/scene/helpers.ts +89 -0
- package/template/src/renderer/src/lib/scene/sceneClass.ts +648 -0
- package/template/src/renderer/src/lib/shaders/background_gradient/frag.glsl +12 -0
- package/template/src/renderer/src/lib/shaders/background_gradient/vert.glsl +6 -0
- package/template/src/renderer/src/lib/shaders/hdri_blur/frag.glsl +45 -0
- package/template/src/renderer/src/lib/shaders/hdri_blur/vert.glsl +5 -0
- package/template/src/renderer/src/main.ts +9 -0
- package/template/svelte.config.mjs +7 -0
- package/template/tsconfig.json +4 -0
- package/template/tsconfig.node.json +10 -0
- 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
|
+
}
|