create-definedmotion 0.2.0 → 0.3.1

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 (65) hide show
  1. package/package.json +2 -2
  2. package/template/src/assets/audio/testing_shadow_glow_song.mp3 +0 -0
  3. package/template/src/assets/for_tests/svg/gravity_text.svg +38 -0
  4. package/template/src/assets/for_tests/svg/grip_figure.svg +28 -0
  5. package/template/src/entry.ts +1 -1
  6. package/template/src/example_scenes/dependencyScene.ts +2 -4
  7. package/template/src/example_scenes/fourierSeriesScene.ts +7 -8
  8. package/template/src/example_scenes/keyboardScene.ts +3 -5
  9. package/template/src/example_scenes/latex_text_transitions_scene.ts +146 -0
  10. package/template/src/example_scenes/tests/animations/camera_movements/test_2d_camera_centers_labels.ts +53 -0
  11. package/template/src/example_scenes/tests/animations/camera_movements/test_2d_camera_hits_markers.ts +40 -0
  12. package/template/src/example_scenes/tests/animations/camera_movements/test_camera_rotate_quaternion.ts +17 -0
  13. package/template/src/example_scenes/tests/animations/camera_movements/test_camera_waypoints_sequential.ts +29 -0
  14. package/template/src/example_scenes/tests/animations/camera_movements/test_fly_camera_waypoints_verifiable.ts +87 -0
  15. package/template/src/example_scenes/tests/animations/camera_movements/test_zoom_perspective_sequential.ts +17 -0
  16. package/template/src/example_scenes/tests/animations/latex/test_latex_blue_particle_transition.ts +82 -0
  17. package/template/src/example_scenes/tests/animations/latex/test_latex_highlight_animation.ts +64 -0
  18. package/template/src/example_scenes/tests/animations/latex/test_latex_mark_animation.ts +42 -0
  19. package/template/src/example_scenes/tests/animations/latex/test_latex_particle_transition.ts +48 -0
  20. package/template/src/example_scenes/tests/animations/latex/test_latex_particle_transition_complex.ts +65 -0
  21. package/template/src/example_scenes/tests/animations/latex/test_latex_particle_transition_super_complex.ts +86 -0
  22. package/template/src/example_scenes/tests/animations/latex/test_with_environment_latex_particle_transition.ts +80 -0
  23. package/template/src/example_scenes/tests/animations/latex/test_write_latex_animation.ts +28 -0
  24. package/template/src/example_scenes/tests/animations/latex/test_write_latex_animation_2.ts +34 -0
  25. package/template/src/example_scenes/tests/animations/latex/test_write_latex_animation_3.ts +34 -0
  26. package/template/src/example_scenes/tests/audio/test_long_audio.ts +11 -0
  27. package/template/src/example_scenes/tests/audio/test_many_short_sounds.ts +50 -0
  28. package/template/src/example_scenes/tests/environment/test_hdri_performance.ts +14 -0
  29. package/template/src/example_scenes/tests/svg/test_basic_latex_query.ts +59 -0
  30. package/template/src/example_scenes/tests/svg/test_basic_svg.ts +11 -0
  31. package/template/src/example_scenes/tests/svg/test_colored_latex_to_svg.ts +42 -0
  32. package/template/src/example_scenes/tests/svg/test_complex_latex_to_svg.ts +22 -0
  33. package/template/src/example_scenes/tests/svg/test_latex_to_svg.ts +17 -0
  34. package/template/src/example_scenes/tests/svg/test_material_on_latex.ts +43 -0
  35. package/template/src/example_scenes/tests/svg/test_query_latex_variables.ts +66 -0
  36. package/template/src/example_scenes/tests/svg/test_regular_text_latex.ts +21 -0
  37. package/template/src/example_scenes/tests/svg/test_super_complex_latex_to_svg.ts +98 -0
  38. package/template/src/example_scenes/tests/svg/test_transition_svgs.ts +33 -0
  39. package/template/src/example_scenes/tests/svg/test_update_svg_object.ts +19 -0
  40. package/template/src/example_scenes/tests/svg/test_yellow_grip_symbol_svg.ts +11 -0
  41. package/template/src/example_scenes/tutorials/medium1.ts +3 -5
  42. package/template/src/example_scenes/vectorField.ts +2 -4
  43. package/template/src/example_scenes/visulizingFunctions.ts +3 -5
  44. package/template/src/main/rendering.ts +38 -21
  45. package/template/src/renderer/src/App.svelte +40 -12
  46. package/template/src/renderer/src/lib/animation/animations.ts +141 -88
  47. package/template/src/renderer/src/lib/animation/captureCanvas.ts +1 -15
  48. package/template/src/renderer/src/lib/animation/latexMarkAndHighlight.ts +349 -0
  49. package/template/src/renderer/src/lib/animation/latexTransitionsAndWrite.ts +558 -0
  50. package/template/src/renderer/src/lib/audio/manager.ts +185 -0
  51. package/template/src/renderer/src/lib/rendering/hdri.ts +273 -0
  52. package/template/src/renderer/src/lib/rendering/lighting3d.ts +0 -105
  53. package/template/src/renderer/src/lib/rendering/setup.ts +7 -1
  54. package/template/src/renderer/src/lib/rendering/svg/latexSVGQueries.ts +44 -0
  55. package/template/src/renderer/src/lib/rendering/svg/latexToSVG.ts +132 -0
  56. package/template/src/renderer/src/lib/rendering/svg/svgObjectHelpers.ts +59 -0
  57. package/template/src/renderer/src/lib/rendering/svg/svgRendering.ts +120 -0
  58. package/template/src/renderer/src/lib/scene/sceneClass.ts +93 -31
  59. package/template/src/renderer/src/lib/audio/loader.ts +0 -104
  60. package/template/src/renderer/src/lib/rendering/materials.ts +0 -6
  61. package/template/src/renderer/src/lib/rendering/protocols.ts +0 -21
  62. package/template/src/renderer/src/lib/rendering/svg/drawing.ts +0 -213
  63. package/template/src/renderer/src/lib/rendering/svg/parsing.ts +0 -717
  64. package/template/src/renderer/src/lib/rendering/svg/rastered.ts +0 -42
  65. package/template/src/renderer/src/lib/rendering/svgObjects.ts +0 -1137
@@ -0,0 +1,53 @@
1
+ // test_2d_camera_centers_labels.ts
2
+ import * as THREE from 'three'
3
+ import { AnimatedScene, HotReloadSetting, SpaceSetting } from '$renderer/lib/scene/sceneClass'
4
+ import { moveCameraToAnim } from '$renderer/lib/animation/animations'
5
+
6
+ function labeledSquare(text: string, color: string) {
7
+ const g = new THREE.Group()
8
+ const rect = new THREE.Mesh(new THREE.PlaneGeometry(3, 3), new THREE.MeshBasicMaterial({ color }))
9
+
10
+ g.add(rect)
11
+ return g
12
+ }
13
+
14
+ export const test_2d_camera_centers_labels = (): AnimatedScene =>
15
+ new AnimatedScene(1500, 1500, SpaceSetting.TwoDim, HotReloadSetting.TraceFromStart, async (dm) => {
16
+ // faint grid background
17
+ for (let x = -12; x <= 12; x += 3) {
18
+ const line = new THREE.Mesh(new THREE.PlaneGeometry(0.02, 30), new THREE.MeshBasicMaterial({ color: '#6b7280', transparent: true, opacity: 0.7}))
19
+ line.position.set(x, 0, -0.1); dm.add(line)
20
+ }
21
+ for (let y = -12; y <= 12; y += 3) {
22
+ const line = new THREE.Mesh(new THREE.PlaneGeometry(30, 0.02), new THREE.MeshBasicMaterial({ color: '#6b7280', transparent: true, opacity: 0.7 }))
23
+ line.position.set(0, y, -0.1); dm.add(line)
24
+ }
25
+
26
+ // center crosshair
27
+ const h = new THREE.Mesh(new THREE.PlaneGeometry(30, 0.03), new THREE.MeshBasicMaterial({ color: '#ffffff' }))
28
+ const v = new THREE.Mesh(new THREE.PlaneGeometry(0.03, 30), new THREE.MeshBasicMaterial({ color: '#ffffff' }))
29
+ dm.add(h, v)
30
+
31
+ // squares at exact grid points
32
+ const S1 = labeledSquare('A', '#f97316'); S1.position.set(-6, 6, 0); dm.add(S1)
33
+ const S2 = labeledSquare('B', '#22c55e'); S2.position.set( 6, 6, 0); dm.add(S2)
34
+ const S3 = labeledSquare('C', '#3b82f6'); S3.position.set( 6, -6, 0); dm.add(S3)
35
+ const S4 = labeledSquare('D', '#ef4444'); S4.position.set(-6, -6, 0); dm.add(S4)
36
+
37
+
38
+ dm.camera.zoom *= 1.5
39
+
40
+ const z = dm.camera.position.z
41
+ dm.camera.position.set(0, 0, z)
42
+
43
+ const zOffset = new THREE.Vector3(0,0,z)
44
+
45
+ dm.camera.position.copy(S1.position.clone().add(zOffset))
46
+
47
+ // center camera over each square in clockwise order
48
+ dm.addDeferredAnims( moveCameraToAnim(dm.camera, { position: S2.position.clone().add(zOffset) }, 600) )
49
+ dm.addDeferredAnims( moveCameraToAnim(dm.camera, { position: S3.position.clone().add(zOffset) }, 600) )
50
+ dm.addDeferredAnims( moveCameraToAnim(dm.camera, { position: S4.position.clone().add(zOffset) }, 600) )
51
+ dm.addDeferredAnims( moveCameraToAnim(dm.camera, { position: S1.position.clone().add(zOffset) }, 600) )
52
+
53
+ })
@@ -0,0 +1,40 @@
1
+ // test_2d_camera_hits_markers.ts
2
+ import * as THREE from 'three'
3
+ import { AnimatedScene, HotReloadSetting, SpaceSetting } from '$renderer/lib/scene/sceneClass'
4
+ import { moveCameraToAnim } from '$renderer/lib/animation/animations'
5
+
6
+ // tiny helper
7
+ const dot = (c: string) => new THREE.Mesh(
8
+ new THREE.CircleGeometry(0.5, 32),
9
+ new THREE.MeshBasicMaterial({ color: c })
10
+ )
11
+
12
+ export const test_2d_camera_hits_markers = (): AnimatedScene =>
13
+ new AnimatedScene(1000, 1000, SpaceSetting.TwoDim, HotReloadSetting.TraceFromStart, async (dm) => {
14
+ // Center crosshair (so we can see when a marker is exactly under the center)
15
+ const horiz = new THREE.Mesh(new THREE.PlaneGeometry(30, 0.1), new THREE.MeshBasicMaterial({ color: '#ffffff' }))
16
+ const vert = new THREE.Mesh(new THREE.PlaneGeometry(0.1, 30), new THREE.MeshBasicMaterial({ color: '#ffffff' }))
17
+ dm.add(horiz, vert)
18
+
19
+ // Markers at precise world coords
20
+ const A = dot('#ef4444'); A.position.set(-8, 6, 0); dm.add(A)
21
+ const B = dot('#3b82f6'); B.position.set( 9, -4, 0); dm.add(B)
22
+ const C = dot('#10b981'); C.position.set( 0, 0, 0); dm.add(C)
23
+
24
+ // Start camera (TwoDim => Orthographic camera with fixed Z; we keep its current Z)
25
+ const z = dm.camera.position.z
26
+ dm.camera.position.set(0, 0, z)
27
+
28
+ // Move center over A, then B, then C — one deferred call per step (sequential)
29
+ dm.addDeferredAnims(
30
+ moveCameraToAnim(dm.camera, { position: new THREE.Vector3(-8, 6, z) }, 700)
31
+ )
32
+ dm.addDeferredAnims(
33
+ moveCameraToAnim(dm.camera, { position: new THREE.Vector3( 9, -4, z) }, 700)
34
+ )
35
+ dm.addDeferredAnims(
36
+ moveCameraToAnim(dm.camera, { position: new THREE.Vector3( 0, 0, z) }, 700)
37
+ )
38
+
39
+ dm.addWait(400)
40
+ })
@@ -0,0 +1,17 @@
1
+ import * as THREE from 'three'
2
+ import { AnimatedScene, HotReloadSetting, SpaceSetting } from '$renderer/lib/scene/sceneClass'
3
+ import { rotateCameraToAnim } from '$renderer/lib/animation/animations'
4
+
5
+ export const test_camera_rotate_quaternion = (): AnimatedScene =>
6
+ new AnimatedScene(1000, 800, SpaceSetting.ThreeDim, HotReloadSetting.TraceFromStart, async (dm) => {
7
+ dm.add(new THREE.AxesHelper(6))
8
+ dm.camera.position.set(0, 4, 10)
9
+
10
+ const yawRight = new THREE.Quaternion().setFromEuler(new THREE.Euler(0, Math.PI/4, 0))
11
+ const pitchDown = new THREE.Quaternion().setFromEuler(new THREE.Euler(-Math.PI/6, 0, 0))
12
+
13
+ dm.addDeferredAnims(rotateCameraToAnim(dm.camera, { rotation: yawRight }, 800))
14
+ dm.addDeferredAnims(rotateCameraToAnim(dm.camera, { rotation: pitchDown }, 800))
15
+
16
+ dm.addWait(300)
17
+ })
@@ -0,0 +1,29 @@
1
+ import { moveCameraToAnim } from "$renderer/lib/animation/animations";
2
+ import { AnimatedScene, HotReloadSetting, SpaceSetting } from "$renderer/lib/scene/sceneClass";
3
+ import * as THREE from 'three'
4
+
5
+
6
+
7
+ export const test_camera_waypoints_sequential = (): AnimatedScene => {
8
+ return new AnimatedScene(1200, 800, SpaceSetting.ThreeDim, HotReloadSetting.TraceFromStart, async (dm) => {
9
+ dm.add(new THREE.GridHelper(40, 40))
10
+
11
+ // Visual markers
12
+ const red = new THREE.Mesh(new THREE.SphereGeometry(1.2), new THREE.MeshBasicMaterial({ color: '#ef4444' }))
13
+ const blue = new THREE.Mesh(new THREE.BoxGeometry(2,2,2), new THREE.MeshBasicMaterial({ color: '#3b82f6' }))
14
+ const green = new THREE.Mesh(new THREE.ConeGeometry(1.2,2,32), new THREE.MeshBasicMaterial({ color: '#10b981' }))
15
+ red.position.set(-8, 0, 0); blue.position.set(8, 0, 0); green.position.set(0, 0, -12)
16
+ dm.add(red, blue, green)
17
+
18
+ // Start camera
19
+ dm.camera.position.set(0, 8, 16)
20
+ dm.camera.lookAt(0, 0, 0)
21
+
22
+ // SEQUENTIAL: one call per addDeferredAnims
23
+ dm.addDeferredAnims(moveCameraToAnim(dm.camera, { position: new THREE.Vector3(-8, 6, 14) }, 900))
24
+ dm.addDeferredAnims(moveCameraToAnim(dm.camera, { position: new THREE.Vector3( 8, 6, 14) }, 900))
25
+ dm.addDeferredAnims(moveCameraToAnim(dm.camera, { position: new THREE.Vector3( 0, 7, 10) }, 900))
26
+
27
+ dm.addWait(400)
28
+ })
29
+ }
@@ -0,0 +1,87 @@
1
+ // test_fly_minimal_two_poses.ts
2
+ import * as THREE from 'three'
3
+ import { AnimatedScene, HotReloadSetting, SpaceSetting } from '$renderer/lib/scene/sceneClass'
4
+ import { flyCameraToAnim } from '$renderer/lib/animation/animations'
5
+
6
+ // ======================
7
+ // === EDIT HERE ========
8
+ // Marker positions (sphere & cube)
9
+ const SPHERE_POS = new THREE.Vector3(-6, 0, -6)
10
+ const CUBE_POS = new THREE.Vector3( 6, 0, -6)
11
+
12
+
13
+
14
+
15
+ // Camera pose A (position + quaternion)
16
+ const CAM_A_POS = new THREE.Vector3(-8.478426,
17
+ 2.932849,
18
+ -1.628103)
19
+
20
+ // Example: look slightly right & down
21
+ const CAM_A_QUAT = new THREE.Quaternion(-0.2782336,
22
+ -0.2736528,
23
+ -0.08303509,
24
+ 0.9169544)
25
+
26
+ // Camera pose B (position + quaternion)
27
+ const CAM_B_POS = new THREE.Vector3( 9.855000,
28
+ 2.759370,
29
+ -1.223401)
30
+ // Example: look slightly left & down
31
+ const CAM_B_QUAT = new THREE.Quaternion( -0.2497320,
32
+ 0.3230065,
33
+ 0.08878684,
34
+ 0.9085250)
35
+ // ======================
36
+
37
+ export const test_fly_minimal_two_poses = (): AnimatedScene =>
38
+ new AnimatedScene(1200, 800, SpaceSetting.ThreeDim, HotReloadSetting.TraceFromStart, async (dm) => {
39
+ // Grid floor
40
+ dm.add(new THREE.GridHelper(60, 60))
41
+
42
+ // Sphere marker
43
+ const sphere = new THREE.Mesh(
44
+ new THREE.SphereGeometry(1, 32, 16),
45
+ new THREE.MeshBasicMaterial({ color: '#3b82f6' })
46
+ )
47
+ sphere.position.copy(SPHERE_POS)
48
+ dm.add(sphere)
49
+
50
+ // Cube marker
51
+ const cube = new THREE.Mesh(
52
+ new THREE.BoxGeometry(2, 2, 2),
53
+ new THREE.MeshBasicMaterial({ color: '#ef4444' })
54
+ )
55
+ cube.position.copy(CUBE_POS)
56
+ dm.add(cube)
57
+
58
+
59
+ const startPos = new THREE.Vector3(0, 6, 18)
60
+ // Start camera (anything reasonable)
61
+ dm.camera.position.copy(startPos)
62
+ dm.camera.lookAt(0, 0, 0)
63
+
64
+ // Leg 1: fly to CAM_A
65
+ dm.addDeferredAnims(
66
+ flyCameraToAnim(dm.camera, { position: CAM_A_POS, rotation: CAM_A_QUAT }, 1000)
67
+ )
68
+
69
+ // Small pause to inspect
70
+ dm.addWait(200)
71
+
72
+ // Leg 2: fly to CAM_B
73
+ dm.addDeferredAnims(
74
+ flyCameraToAnim(dm.camera, { position: CAM_B_POS, rotation: CAM_B_QUAT }, 1000)
75
+ )
76
+
77
+ dm.addWait(200)
78
+
79
+ const from = startPos.clone()
80
+ const target = new THREE.Vector3(0, 0, 0)
81
+ const m = new THREE.Matrix4().lookAt(from, target, new THREE.Vector3(0, 1, 0))
82
+ const q = new THREE.Quaternion().setFromRotationMatrix(m)
83
+
84
+ dm.addDeferredAnims(
85
+ flyCameraToAnim(dm.camera, { position: startPos, rotation: q}, 1000)
86
+ )
87
+ })
@@ -0,0 +1,17 @@
1
+ import * as THREE from 'three'
2
+ import { AnimatedScene, HotReloadSetting, SpaceSetting } from '$renderer/lib/scene/sceneClass'
3
+ import { zoomCameraToAnim } from '$renderer/lib/animation/animations'
4
+
5
+ export const test_zoom_perspective_sequential = (): AnimatedScene =>
6
+ new AnimatedScene(1000, 700, SpaceSetting.ThreeDim, HotReloadSetting.TraceFromStart, async (dm) => {
7
+ dm.add(new THREE.GridHelper(40, 40))
8
+ dm.camera.position.set(0, 6, 16)
9
+ dm.camera.lookAt(0, 0, 0)
10
+
11
+ const initialFov = (dm.camera as THREE.PerspectiveCamera).fov
12
+
13
+ dm.addDeferredAnims(zoomCameraToAnim(dm.camera, { fov: 30 }, 900))
14
+ dm.addDeferredAnims(zoomCameraToAnim(dm.camera, { fov: initialFov }, 900))
15
+
16
+ dm.addWait(200)
17
+ })
@@ -0,0 +1,82 @@
1
+ // test_latex_particle_transition_blue.ts
2
+ import * as THREE from 'three'
3
+ import {
4
+ AnimatedScene,
5
+ HotReloadSetting,
6
+ SpaceSetting
7
+ } from '$renderer/lib/scene/sceneClass'
8
+ import { latexToSVG } from '$renderer/lib/rendering/svg/latexToSVG'
9
+ import { createSVGShape } from '$renderer/lib/rendering/svg/svgRendering'
10
+ import { setOpacity } from '$renderer/lib/animation/animations'
11
+ import { latexParticleTransitionAnim } from '$renderer/lib/animation/latexTransitionsAndWrite'
12
+
13
+ export const test_latex_blue_particle_transition = (): AnimatedScene => {
14
+ return new AnimatedScene(
15
+ 1000,
16
+ 1000,
17
+ SpaceSetting.ThreeDim,
18
+ HotReloadSetting.TraceFromStart,
19
+ async (dm) => {
20
+ // 1) Two related equations to morph between
21
+ const latexA = String.raw`\nabla \cdot \vec{E} = \frac{\rho}{\varepsilon_0}`
22
+ const latexB = String.raw`\nabla \cdot \vec{D} = \rho_{\mathrm{free}}`
23
+
24
+ // 2) LaTeX → SVG → THREE.Group
25
+ const svgA = latexToSVG(latexA)
26
+ const svgB = latexToSVG(latexB)
27
+
28
+ const groupA = createSVGShape(svgA, 20)
29
+ const groupB = createSVGShape(svgB, 20)
30
+
31
+ // 2.5) Tint both equations blue
32
+ const blue = new THREE.Color('#3b82f6')
33
+
34
+ const tintGroupBlue = (group: THREE.Group) => {
35
+ group.traverse(obj => {
36
+ const mesh = obj as THREE.Mesh
37
+ // @ts-ignore
38
+ if (!mesh.isMesh) return
39
+ const mat = mesh.material
40
+ if (Array.isArray(mat)) {
41
+ mat.forEach(m => {
42
+ const anyMat = m as any
43
+ if (anyMat && anyMat.color && anyMat.color.isColor) {
44
+ anyMat.color.copy(blue)
45
+ }
46
+ })
47
+ } else {
48
+ const anyMat = mat as any
49
+ if (anyMat && anyMat.color && anyMat.color.isColor) {
50
+ anyMat.color.copy(blue)
51
+ }
52
+ }
53
+ })
54
+ }
55
+
56
+ tintGroupBlue(groupA)
57
+ tintGroupBlue(groupB)
58
+
59
+ // 3) Place both at origin
60
+ groupA.position.set(0, 0, 0)
61
+ groupB.position.set(0, 0, 0)
62
+
63
+ // Add to scene
64
+ dm.add(groupA)
65
+ dm.add(groupB)
66
+
67
+ // 4) Make the target equation invisible initially
68
+ setOpacity(groupB, 0)
69
+
70
+ // 5) Simple camera setup so the equations are clearly visible
71
+ dm.camera.position.set(0, 0, 30)
72
+ dm.camera.lookAt(new THREE.Vector3(0, 0, 0))
73
+
74
+ // 6) Add the particle transition animation
75
+ // (particles will pick up the same blue via pickColorFromGroup)
76
+ dm.addDeferredAnims(latexParticleTransitionAnim(groupA, groupB))
77
+
78
+ // Optional pause after the morph
79
+ dm.addWait(300)
80
+ }
81
+ )
82
+ }
@@ -0,0 +1,64 @@
1
+ import * as THREE from 'three'
2
+ import { AnimatedScene, HotReloadSetting, SpaceSetting } from '$renderer/lib/scene/sceneClass'
3
+ import { latexToSVG } from '$renderer/lib/rendering/svg/latexToSVG'
4
+ import { createSVGShape } from '$renderer/lib/rendering/svg/svgRendering'
5
+ import { latexHighlightAnim } from '$renderer/lib/animation/latexMarkAndHighlight'
6
+
7
+
8
+ export const test_latex_highlight_animation = (): AnimatedScene =>
9
+ new AnimatedScene(
10
+ 1000,
11
+ 1000,
12
+ SpaceSetting.ThreeDim,
13
+ HotReloadSetting.TraceFromStart,
14
+ async (dm) => {
15
+ const latex = latexToSVG(String.raw`
16
+ \ell(\theta)
17
+ = - \sum_{i=1}^{n}
18
+ \Big(
19
+ \dmClass{pos}{y_i \log p_\theta(x_i)}
20
+ +
21
+ \dmClass{neg}{(1 - y_i) \log (1 - p_\theta(x_i))}
22
+ \Big)
23
+ `.trim())
24
+
25
+ const group = createSVGShape(latex, 36)
26
+ dm.add(group)
27
+
28
+ // 1) Highlight positive term
29
+ dm.addDeferredAnims(
30
+ latexHighlightAnim(group, 'pos', {
31
+ durationMs: 1800,
32
+ highlightColor: 0x22c55e,
33
+ pulses: 2,
34
+ minMix: 0.0,
35
+ maxMix: 1.0
36
+ })
37
+ )
38
+ dm.addWait(250)
39
+
40
+ // 2) Highlight negative term
41
+ dm.addDeferredAnims(
42
+ latexHighlightAnim(group, 'neg', {
43
+ durationMs: 1800,
44
+ highlightColor: 0xef4444,
45
+ pulses: 2,
46
+ minMix: 0.0,
47
+ maxMix: 1.0
48
+ })
49
+ )
50
+ dm.addWait(250)
51
+
52
+ // 3) Highlight both together with a stronger pulse
53
+ dm.addDeferredAnims(
54
+ latexHighlightAnim(group, ['pos', 'neg'], {
55
+ durationMs: 1800,
56
+ highlightColor: 0xfacc15,
57
+ pulses: 3,
58
+ minMix: 0.2,
59
+ maxMix: 1.0
60
+ })
61
+ )
62
+ dm.addWait(400)
63
+ }
64
+ )
@@ -0,0 +1,42 @@
1
+ // test_latex_mark_animation.ts
2
+ import * as THREE from 'three'
3
+ import { AnimatedScene, HotReloadSetting, SpaceSetting } from '$renderer/lib/scene/sceneClass'
4
+ import { latexToSVG } from '$renderer/lib/rendering/svg/latexToSVG'
5
+ import { createSVGShape } from '$renderer/lib/rendering/svg/svgRendering'
6
+ import { latexMarkAnim } from '$renderer/lib/animation/latexMarkAndHighlight'
7
+
8
+
9
+ export const test_latex_mark_animation = (): AnimatedScene =>
10
+ new AnimatedScene(
11
+ 1000,
12
+ 1000,
13
+ SpaceSetting.ThreeDim,
14
+ HotReloadSetting.TraceFromStart,
15
+ async (dm) => {
16
+ const latex = latexToSVG(String.raw`
17
+ \dmClass{lhs}{\int_0^\infty e^{-x^2}\,\mathrm{d}x}
18
+ = \dmClass{rhs}{\frac{\sqrt{\pi}}{2}}
19
+ `.trim())
20
+
21
+ const group = createSVGShape(latex, 28)
22
+ dm.add(group)
23
+
24
+ // 1) Mark the left-hand side only
25
+ dm.addDeferredAnims(
26
+ latexMarkAnim(group, 'lhs')
27
+ )
28
+ dm.addWait(300)
29
+
30
+ // 2) Mark the right-hand side only
31
+ dm.addDeferredAnims(
32
+ latexMarkAnim(group, 'rhs')
33
+ )
34
+ dm.addWait(300)
35
+
36
+ // 3) Mark both sides together using the multi-class path
37
+ dm.addDeferredAnims(
38
+ latexMarkAnim(group, ['lhs', 'rhs'])
39
+ )
40
+ dm.addWait(400)
41
+ }
42
+ )
@@ -0,0 +1,48 @@
1
+
2
+ import * as THREE from 'three'
3
+ import { AnimatedScene, HotReloadSetting, SpaceSetting } from '$renderer/lib/scene/sceneClass'
4
+ import { latexToSVG } from '$renderer/lib/rendering/svg/latexToSVG'
5
+ import { createSVGShape } from '$renderer/lib/rendering/svg/svgRendering'
6
+ import { setOpacity } from '$renderer/lib/animation/animations'
7
+ import { latexParticleTransitionAnim } from '$renderer/lib/animation/latexTransitionsAndWrite' // <- your new helper
8
+
9
+ export const test_latex_particle_transition = (): AnimatedScene => {
10
+ return new AnimatedScene(
11
+ 1000,
12
+ 1000,
13
+ SpaceSetting.ThreeDim,
14
+ HotReloadSetting.TraceFromStart,
15
+ async (dm) => {
16
+ // 1) Two related equations to morph between
17
+ const latexA = String.raw`\nabla \cdot \vec{E} = \frac{\rho}{\varepsilon_0}`
18
+ const latexB = String.raw`\nabla \cdot \vec{D} = \rho_{\mathrm{free}}`
19
+
20
+ // 2) LaTeX → SVG → THREE.Group
21
+ const svgA = latexToSVG(latexA)
22
+ const svgB = latexToSVG(latexB)
23
+
24
+ const groupA = createSVGShape(svgA, 20) // width ≈ 10 units
25
+ const groupB = createSVGShape(svgB, 20)
26
+
27
+ // Place both at origin
28
+ groupA.position.set(0, 0, 0)
29
+ groupB.position.set(0, 0, 0)
30
+
31
+ // Add to scene
32
+ dm.add(groupA)
33
+ dm.add(groupB)
34
+
35
+ // 3) Make the target equation invisible initially (required by your spec)
36
+ setOpacity(groupB, 0)
37
+
38
+ // 4) Simple camera setup so the equations are clearly visible
39
+ dm.camera.position.set(0, 0, 30)
40
+ dm.camera.lookAt(new THREE.Vector3(0, 0, 0))
41
+
42
+ dm.addDeferredAnims(latexParticleTransitionAnim(groupA, groupB))
43
+
44
+ // Optionally: leave a bit of time after the morph finishes
45
+ dm.addWait(300)
46
+ }
47
+ )
48
+ }
@@ -0,0 +1,65 @@
1
+ // test_latex_particle_transition_complex.ts
2
+ import * as THREE from 'three'
3
+ import {
4
+ AnimatedScene,
5
+ HotReloadSetting,
6
+ SpaceSetting
7
+ } from '$renderer/lib/scene/sceneClass'
8
+ import { latexToSVG } from '$renderer/lib/rendering/svg/latexToSVG'
9
+ import { createSVGShape } from '$renderer/lib/rendering/svg/svgRendering'
10
+ import { setOpacity } from '$renderer/lib/animation/animations'
11
+ import { latexParticleTransitionAnim } from '$renderer/lib/animation/latexTransitionsAndWrite'
12
+
13
+ export const test_latex_particle_transition_complex = (): AnimatedScene => {
14
+ return new AnimatedScene(
15
+ 1600,
16
+ 1600,
17
+ SpaceSetting.ThreeDim,
18
+ HotReloadSetting.TraceFromStart,
19
+ async (dm) => {
20
+ // 1) Two related, more complex LaTeX expressions
21
+ const latexA = String.raw`
22
+ \oint_{\partial V} \vec{D} \cdot d\vec{A}
23
+ \;=\;
24
+ \int_V \rho_{\mathrm{free}}\, dV
25
+ `
26
+
27
+ const latexB = String.raw`
28
+ \nabla \cdot \vec{D}(\vec{r})
29
+ \;=\;
30
+ \rho_{\mathrm{free}}(\vec{r})
31
+ `
32
+
33
+ // 2) LaTeX → SVG → THREE.Group
34
+ const svgA = latexToSVG(latexA)
35
+ const svgB = latexToSVG(latexB)
36
+
37
+ // Slightly wider target width to give the integral signs room
38
+ const groupA = createSVGShape(svgA, 28)
39
+ const groupB = createSVGShape(svgB, 28)
40
+
41
+ // Place both at origin
42
+ groupA.position.set(0, 0, 0)
43
+ groupB.position.set(0, 0, 0)
44
+
45
+ // Add to scene
46
+ dm.add(groupA)
47
+ dm.add(groupB)
48
+
49
+ // 3) Target expression starts invisible
50
+ setOpacity(groupB, 0)
51
+
52
+ // 4) Camera setup
53
+ dm.camera.position.set(0, 0, 35)
54
+ dm.camera.lookAt(new THREE.Vector3(0, 0, 0))
55
+
56
+ // 5) Particle transition:
57
+ // - 2000 ms duration
58
+ // - default particleCount from helper (tune inside helper if needed)
59
+ dm.addDeferredAnims(latexParticleTransitionAnim(groupA, groupB))
60
+
61
+ // A small pause after the morph
62
+ dm.addWait(400)
63
+ }
64
+ )
65
+ }
@@ -0,0 +1,86 @@
1
+ // test_latex_particle_transition_super_complex.ts
2
+ import * as THREE from 'three'
3
+ import {
4
+ AnimatedScene,
5
+ HotReloadSetting,
6
+ SpaceSetting
7
+ } from '$renderer/lib/scene/sceneClass'
8
+ import { latexToSVG } from '$renderer/lib/rendering/svg/latexToSVG'
9
+ import { createSVGShape } from '$renderer/lib/rendering/svg/svgRendering'
10
+ import { setOpacity } from '$renderer/lib/animation/animations'
11
+ import { latexParticleTransitionAnim } from '$renderer/lib/animation/latexTransitionsAndWrite'
12
+
13
+ export const test_latex_particle_transition_super_complex = (): AnimatedScene => {
14
+ return new AnimatedScene(
15
+ 1600,
16
+ 1600,
17
+ SpaceSetting.ThreeDim,
18
+ HotReloadSetting.TraceFromStart,
19
+ async (dm) => {
20
+ // --- 1) Two super duper complex LaTeX expressions ---
21
+
22
+ // A: Full softmax cross-entropy loss with explicit logits
23
+ const latexA = String.raw`
24
+ \begin{aligned}
25
+ \mathcal{L}(\theta)
26
+ &= - \sum_{i=1}^N \log p_\theta(y_i \mid x_i) \\
27
+ &= - \sum_{i=1}^N \log
28
+ \frac{\exp\big(f_\theta(x_i)_{y_i}\big)}
29
+ {\sum_{k=1}^K \exp\big(f_\theta(x_i)_k\big)} \\
30
+ &= - \sum_{i=1}^N
31
+ \left(
32
+ f_\theta(x_i)_{y_i}
33
+ - \log \sum_{k=1}^K \exp\big(f_\theta(x_i)_k\big)
34
+ \right)
35
+ \end{aligned}
36
+ `
37
+
38
+ // B: VI ELBO gradient with regularization and KL term
39
+ const latexB = String.raw`
40
+ \begin{aligned}
41
+ \nabla_\theta \mathcal{L}_{\mathrm{ELBO}}(\theta,\phi)
42
+ &= - \mathbb{E}_{q_\phi(z \mid x)}
43
+ \big[ \nabla_\theta \log p_\theta(x \mid z) \big] \\
44
+ &\quad +\;
45
+ \lambda \,\nabla_\theta \lVert \theta \rVert_2^2 \\
46
+ \mathcal{L}_{\mathrm{ELBO}}(\theta,\phi)
47
+ &= \mathbb{E}_{q_\phi(z \mid x)}
48
+ \big[ \log p_\theta(x \mid z) \big]
49
+ - \mathrm{KL}\!\big(q_\phi(z\mid x)\,\|\,p(z)\big)
50
+ \end{aligned}
51
+ `
52
+
53
+ // --- 2) LaTeX → SVG → THREE.Group ---
54
+
55
+ const svgA = latexToSVG(latexA)
56
+ const svgB = latexToSVG(latexB)
57
+
58
+ // Wider target width to fit the long equations nicely
59
+ const targetWidth = 32
60
+ const groupA = createSVGShape(svgA, targetWidth)
61
+ const groupB = createSVGShape(svgB, targetWidth)
62
+
63
+ // Center them around the origin
64
+ groupA.position.set(0, 0, 0)
65
+ groupB.position.set(0, 0, 0)
66
+
67
+ dm.add(groupA)
68
+ dm.add(groupB)
69
+
70
+ // --- 3) Make target invisible initially ---
71
+ setOpacity(groupB, 0)
72
+
73
+ // --- 4) Camera setup: small offset so everything is nicely framed ---
74
+ dm.camera.position.set(0, 0, 40)
75
+ dm.camera.lookAt(new THREE.Vector3(0, 0, 0))
76
+
77
+ // --- 5) Particle transition ---
78
+ // - 2200 ms duration
79
+ // - particleCount controlled inside helper (default 2000)
80
+ dm.addDeferredAnims(latexParticleTransitionAnim(groupA, groupB))
81
+
82
+ // Leave a short pause when done
83
+ dm.addWait(400)
84
+ }
85
+ )
86
+ }