create-definedmotion 0.1.4 → 0.3.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/package.json +2 -2
- package/template/package-lock.json +313 -59
- package/template/package.json +1 -0
- package/template/src/assets/audio/testing_shadow_glow_song.mp3 +0 -0
- package/template/src/assets/for_tests/svg/gravity_text.svg +38 -0
- package/template/src/assets/for_tests/svg/grip_figure.svg +28 -0
- package/template/src/entry.ts +4 -5
- package/template/src/example_scenes/alternativesScene.ts +1 -1
- package/template/src/example_scenes/dependencyScene.ts +2 -4
- package/template/src/example_scenes/fourierSeriesScene.ts +10 -11
- package/template/src/example_scenes/keyboardScene.ts +14 -16
- package/template/src/example_scenes/latex_text_transitions_scene.ts +146 -0
- package/template/src/example_scenes/tests/animations/camera_movements/test_2d_camera_centers_labels.ts +53 -0
- package/template/src/example_scenes/tests/animations/camera_movements/test_2d_camera_hits_markers.ts +40 -0
- package/template/src/example_scenes/tests/animations/camera_movements/test_camera_rotate_quaternion.ts +17 -0
- package/template/src/example_scenes/tests/animations/camera_movements/test_camera_waypoints_sequential.ts +29 -0
- package/template/src/example_scenes/tests/animations/camera_movements/test_fly_camera_waypoints_verifiable.ts +87 -0
- package/template/src/example_scenes/tests/animations/camera_movements/test_zoom_perspective_sequential.ts +17 -0
- package/template/src/example_scenes/tests/animations/latex/test_latex_blue_particle_transition.ts +82 -0
- package/template/src/example_scenes/tests/animations/latex/test_latex_highlight_animation.ts +64 -0
- package/template/src/example_scenes/tests/animations/latex/test_latex_mark_animation.ts +42 -0
- package/template/src/example_scenes/tests/animations/latex/test_latex_particle_transition.ts +48 -0
- package/template/src/example_scenes/tests/animations/latex/test_latex_particle_transition_complex.ts +65 -0
- package/template/src/example_scenes/tests/animations/latex/test_latex_particle_transition_super_complex.ts +86 -0
- package/template/src/example_scenes/tests/animations/latex/test_with_environment_latex_particle_transition.ts +80 -0
- package/template/src/example_scenes/tests/animations/latex/test_write_latex_animation.ts +28 -0
- package/template/src/example_scenes/tests/animations/latex/test_write_latex_animation_2.ts +34 -0
- package/template/src/example_scenes/tests/animations/latex/test_write_latex_animation_3.ts +34 -0
- package/template/src/example_scenes/tests/animations/test_updater.ts +24 -0
- package/template/src/example_scenes/tests/audio/test_long_audio.ts +11 -0
- package/template/src/example_scenes/tests/audio/test_many_short_sounds.ts +50 -0
- package/template/src/example_scenes/tests/deferred_anims/testing_deferredAnims.ts +71 -0
- package/template/src/example_scenes/tests/deferred_anims/testing_deferredAnims2.ts +65 -0
- package/template/src/example_scenes/tests/environment/test_hdri_performance.ts +14 -0
- package/template/src/example_scenes/tests/svg/test_basic_latex_query.ts +59 -0
- package/template/src/example_scenes/tests/svg/test_basic_svg.ts +11 -0
- package/template/src/example_scenes/tests/svg/test_colored_latex_to_svg.ts +42 -0
- package/template/src/example_scenes/tests/svg/test_complex_latex_to_svg.ts +22 -0
- package/template/src/example_scenes/tests/svg/test_latex_to_svg.ts +17 -0
- package/template/src/example_scenes/tests/svg/test_material_on_latex.ts +43 -0
- package/template/src/example_scenes/tests/svg/test_query_latex_variables.ts +66 -0
- package/template/src/example_scenes/tests/svg/test_regular_text_latex.ts +21 -0
- package/template/src/example_scenes/tests/svg/test_super_complex_latex_to_svg.ts +98 -0
- package/template/src/example_scenes/tests/svg/test_transition_svgs.ts +33 -0
- package/template/src/example_scenes/tests/svg/test_update_svg_object.ts +19 -0
- package/template/src/example_scenes/tests/svg/test_yellow_grip_symbol_svg.ts +11 -0
- package/template/src/example_scenes/tutorials/easy1.ts +4 -4
- package/template/src/example_scenes/tutorials/easy3.ts +1 -1
- package/template/src/example_scenes/tutorials/medium1.ts +3 -5
- package/template/src/example_scenes/vectorField.ts +2 -4
- package/template/src/example_scenes/visulizingFunctions.ts +5 -7
- package/template/src/main/index.ts +59 -3
- package/template/src/main/rendering.ts +38 -21
- package/template/src/preload/index.ts +15 -1
- package/template/src/renderer/index.html +1 -1
- package/template/src/renderer/src/App.svelte +215 -32
- package/template/src/renderer/src/application_assets/360.svg +39 -0
- package/template/src/renderer/src/application_assets/move.svg +37 -0
- package/template/src/renderer/src/lib/animation/animations.ts +141 -88
- package/template/src/renderer/src/lib/animation/captureCanvas.ts +3 -17
- package/template/src/renderer/src/lib/animation/interpolations.ts +2 -1
- package/template/src/renderer/src/lib/animation/latexMarkAndHighlight.ts +349 -0
- package/template/src/renderer/src/lib/animation/latexTransitionsAndWrite.ts +558 -0
- package/template/src/renderer/src/lib/audio/manager.ts +185 -0
- package/template/src/renderer/src/lib/general/helpers.ts +16 -47
- package/template/src/renderer/src/lib/rendering/hdri.ts +273 -0
- package/template/src/renderer/src/lib/rendering/lighting3d.ts +0 -105
- package/template/src/renderer/src/lib/rendering/setup.ts +7 -1
- package/template/src/renderer/src/lib/rendering/svg/latexSVGQueries.ts +44 -0
- package/template/src/renderer/src/lib/rendering/svg/latexToSVG.ts +132 -0
- package/template/src/renderer/src/lib/rendering/svg/svgObjectHelpers.ts +59 -0
- package/template/src/renderer/src/lib/rendering/svg/svgRendering.ts +120 -0
- package/template/src/renderer/src/lib/scene/sceneClass.ts +180 -62
- package/template/src/renderer/src/lib/animation/helpers.ts +0 -7
- package/template/src/renderer/src/lib/audio/loader.ts +0 -104
- package/template/src/renderer/src/lib/rendering/materials.ts +0 -6
- package/template/src/renderer/src/lib/rendering/protocols.ts +0 -21
- package/template/src/renderer/src/lib/rendering/svg/drawing.ts +0 -213
- package/template/src/renderer/src/lib/rendering/svg/parsing.ts +0 -717
- package/template/src/renderer/src/lib/rendering/svg/rastered.ts +0 -42
- package/template/src/renderer/src/lib/rendering/svgObjects.ts +0 -1137
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { AnimatedScene, HotReloadSetting, SpaceSetting } from "$renderer/lib/scene/sceneClass";
|
|
2
|
+
import { createSVGShape } from "$renderer/lib/rendering/svg/svgRendering";
|
|
3
|
+
import { latexToSVG } from "$renderer/lib/rendering/svg/latexToSVG";
|
|
4
|
+
|
|
5
|
+
export const test_colored_latex_to_svg = (): AnimatedScene => {
|
|
6
|
+
return new AnimatedScene(1000, 1000, SpaceSetting.ThreeDim, HotReloadSetting.TraceFromStart, async (dm) => {
|
|
7
|
+
|
|
8
|
+
// 1) Inline colors via \style{color:...}
|
|
9
|
+
const eq1 = latexToSVG(String.raw`
|
|
10
|
+
\begin{aligned}
|
|
11
|
+
\style{color:#ff3b3b}{\nabla\cdot\vec{E}} &=
|
|
12
|
+
\style{color:rgba(255,59,59,0.5)}{\frac{\rho}{\varepsilon_0}}
|
|
13
|
+
|
|
14
|
+
\style{color:#3b82f6}{e^{i\theta}} &=
|
|
15
|
+
\style{color:#10b981}{\cos\theta} +
|
|
16
|
+
\style{color:#f59e0b}{i\sin\theta}
|
|
17
|
+
\end{aligned}
|
|
18
|
+
`, { display: true });
|
|
19
|
+
|
|
20
|
+
// 2) Mixed \textcolor and CSS rgba, plus a semi-transparent bbox
|
|
21
|
+
const eq2 = latexToSVG(String.raw`
|
|
22
|
+
\bbox[6px, border:1px solid rgba(0,255,255,0.5), background:rgba(0,0,0,0.25)]{
|
|
23
|
+
\textcolor{#22c55e}{\mathbb{E}[X]}
|
|
24
|
+
= \style{color:rgba(34,197,94,0.6)}{\int_{\mathbb{R}} x\, d\mathbb{P}(x)}
|
|
25
|
+
}
|
|
26
|
+
`, { display: true });
|
|
27
|
+
|
|
28
|
+
// 3) A palette inside a matrix
|
|
29
|
+
const eq3 = latexToSVG(String.raw`
|
|
30
|
+
\begin{bmatrix}
|
|
31
|
+
\style{color:#ef4444}{a} & \style{color:#f97316}{b} & \style{color:#eab308}{c}\\
|
|
32
|
+
\style{color:#22c55e}{d} & \style{color:#3b82f6}{e} & \style{color:#a855f7}{f}\\
|
|
33
|
+
\style{color:#ec4899}{g} & \style{color:#06b6d4}{h} & \style{color:#9ca3af}{i}
|
|
34
|
+
\end{bmatrix}
|
|
35
|
+
`, { display: true });
|
|
36
|
+
|
|
37
|
+
// Place them using your width normalization
|
|
38
|
+
const g1 = createSVGShape(eq1, 14); g1.position.set(0, 5, 0); dm.add(g1);
|
|
39
|
+
const g2 = createSVGShape(eq2, 12); g2.position.set(0, 0, 0); dm.add(g2);
|
|
40
|
+
const g3 = createSVGShape(eq3, 10); g3.position.set(0, -5, 0); dm.add(g3);
|
|
41
|
+
});
|
|
42
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { AnimatedScene, HotReloadSetting, SpaceSetting } from "$renderer/lib/scene/sceneClass";
|
|
2
|
+
import { createSVGShape } from "$renderer/lib/rendering/svg/svgRendering";
|
|
3
|
+
import { latexToSVG } from "$renderer/lib/rendering/svg/latexToSVG";
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
export const test_complex_latex_to_svg = (): AnimatedScene => {
|
|
7
|
+
return new AnimatedScene(1000, 1000, SpaceSetting.ThreeDim, HotReloadSetting.TraceFromStart, async (dm) => {
|
|
8
|
+
const raw = latexToSVG(String.raw`
|
|
9
|
+
\begin{aligned}
|
|
10
|
+
\hat{f}(\omega) &= \int_{-\infty}^{\infty} f(t)\,e^{-i\omega t}\,dt,\\
|
|
11
|
+
f(t) &= \frac{1}{2\pi}\int_{-\infty}^{\infty} \hat{f}(\omega)\,e^{i\omega t}\,d\omega,\\[6pt]
|
|
12
|
+
\Gamma(z) &= \int_{0}^{\infty} t^{z-1} e^{-t}\,dt,\qquad
|
|
13
|
+
\zeta(s) = \prod_{p\in\mathbb{P}} \frac{1}{1-p^{-s}}
|
|
14
|
+
\end{aligned}
|
|
15
|
+
`, { display: true });
|
|
16
|
+
|
|
17
|
+
console.log("RAW", raw)
|
|
18
|
+
|
|
19
|
+
const g = createSVGShape(raw, 12);
|
|
20
|
+
dm.add(g);
|
|
21
|
+
});
|
|
22
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { AnimatedScene, HotReloadSetting, SpaceSetting } from "$renderer/lib/scene/sceneClass";
|
|
2
|
+
import { createSVGShape } from "$renderer/lib/rendering/svg/svgRendering";
|
|
3
|
+
import { latexToSVG } from "$renderer/lib/rendering/svg/latexToSVG";
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
export const test_latex_to_svg = (): AnimatedScene => {
|
|
7
|
+
return new AnimatedScene(
|
|
8
|
+
1000, 1000,
|
|
9
|
+
SpaceSetting.ThreeDim,
|
|
10
|
+
HotReloadSetting.TraceFromStart,
|
|
11
|
+
async (dm) => {
|
|
12
|
+
const svg = latexToSVG(String.raw`\nabla \cdot \vec{E} = \frac{\rho}{\varepsilon_0}`);
|
|
13
|
+
const g = createSVGShape(svg, 10);
|
|
14
|
+
dm.add(g);
|
|
15
|
+
}
|
|
16
|
+
);
|
|
17
|
+
};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { createBumpMap } from "$renderer/lib/rendering/bumpMaps/noise";
|
|
2
|
+
import { addHDRI, HDRIs, loadHDRIData } from "$renderer/lib/rendering/hdri";
|
|
3
|
+
import { addSceneLighting, } from "$renderer/lib/rendering/lighting3d";
|
|
4
|
+
import { latexToSVG } from "$renderer/lib/rendering/svg/latexToSVG";
|
|
5
|
+
import { createSVGShape } from "$renderer/lib/rendering/svg/svgRendering";
|
|
6
|
+
import { AnimatedScene, HotReloadSetting, SpaceSetting } from "$renderer/lib/scene/sceneClass";
|
|
7
|
+
import * as THREE from 'three';
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
const hdriData = await loadHDRIData(HDRIs.outdoor1, 1)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
export const test_material_on_latex = (): AnimatedScene => {
|
|
14
|
+
return new AnimatedScene(
|
|
15
|
+
1000, 1000,
|
|
16
|
+
SpaceSetting.ThreeDim,
|
|
17
|
+
HotReloadSetting.TraceFromStart,
|
|
18
|
+
async (dm) => {
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
await addHDRI(dm, hdriData, 6)
|
|
22
|
+
const svg = latexToSVG(String.raw`\nabla \cdot \vec{E} = \frac{\rho}{\varepsilon_0}`);
|
|
23
|
+
const group = createSVGShape(svg, 20);
|
|
24
|
+
|
|
25
|
+
// the material you want to apply
|
|
26
|
+
const metalMaterial = new THREE.MeshStandardMaterial({
|
|
27
|
+
color: 0xffffff, // slightly darker red often looks nicer for metal
|
|
28
|
+
metalness: 0.9, // close to 1 = very metallic
|
|
29
|
+
roughness: 0.3, // lower = more shiny, higher = more matte
|
|
30
|
+
side: THREE.DoubleSide,
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
group.traverse((obj) => {
|
|
34
|
+
if ((obj as THREE.Mesh).isMesh) {
|
|
35
|
+
const mesh = obj as THREE.Mesh;
|
|
36
|
+
mesh.material = metalMaterial;
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
dm.add(group);
|
|
41
|
+
}
|
|
42
|
+
);
|
|
43
|
+
};
|
|
@@ -0,0 +1,66 @@
|
|
|
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 { queryLaTeXClass } from '$renderer/lib/rendering/svg/latexSVGQueries';
|
|
6
|
+
import { createAnim } from '$renderer/lib/animation/protocols';
|
|
7
|
+
import { easeInOutQuad } from '$renderer/lib/animation/interpolations';
|
|
8
|
+
|
|
9
|
+
export const test_latex_query_variables = (): AnimatedScene => {
|
|
10
|
+
return new AnimatedScene(
|
|
11
|
+
1000,
|
|
12
|
+
1000,
|
|
13
|
+
SpaceSetting.ThreeDim,
|
|
14
|
+
HotReloadSetting.TraceFromStart,
|
|
15
|
+
async (dm) => {
|
|
16
|
+
// 1) More complicated LaTeX expression with many variables
|
|
17
|
+
// Tag every variable occurrence with \dmClass{variable}{...}
|
|
18
|
+
const latex = String.raw`
|
|
19
|
+
f(\dmClass{variable}{x}, \dmClass{variable}{y})
|
|
20
|
+
= \int_{\dmClass{variable}{x_0}}^{\dmClass{variable}{x_1}}
|
|
21
|
+
\dmClass{variable}{y}(t)\, e^{-\dmClass{variable}{\alpha} t}
|
|
22
|
+
\, dt
|
|
23
|
+
`;
|
|
24
|
+
|
|
25
|
+
// 2) Convert LaTeX → SVG → THREE.Group
|
|
26
|
+
const svg = latexToSVG(latex);
|
|
27
|
+
const equationGroup = createSVGShape(svg, 20); // width ≈ 10 units
|
|
28
|
+
dm.add(equationGroup);
|
|
29
|
+
|
|
30
|
+
// 3) Query all meshes that belong to class "variable"
|
|
31
|
+
const hit = queryLaTeXClass(equationGroup, 'variable');
|
|
32
|
+
if (!hit) {
|
|
33
|
+
console.warn('No meshes found for LaTeX class "variable"');
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Somewhere when you build the meshes
|
|
38
|
+
const targetColor = new THREE.Color(0x00ff88); // the “variable” color
|
|
39
|
+
const white = new THREE.Color(0xffffff);
|
|
40
|
+
const tmpColor = new THREE.Color();
|
|
41
|
+
|
|
42
|
+
// Example: you have an array of meshes you want to tint
|
|
43
|
+
const variableMeshes: THREE.Mesh[] = hit.meshes;
|
|
44
|
+
|
|
45
|
+
// Make sure materials are independent if you plan to animate them
|
|
46
|
+
for (const mesh of variableMeshes) {
|
|
47
|
+
mesh.material = (mesh.material as THREE.Material).clone();
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const colorAnim = createAnim(easeInOutQuad(0, 1, 300), (t) => {
|
|
51
|
+
tmpColor.lerpColors(white, targetColor, t); // tmp = white * (1-t) + target * t
|
|
52
|
+
for (const mesh of variableMeshes) {
|
|
53
|
+
const mat = mesh.material as THREE.MeshBasicMaterial;
|
|
54
|
+
mat.color.copy(tmpColor);
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
for (let i = 0; i<20; i++) {
|
|
60
|
+
dm.addAnims(colorAnim.copy())
|
|
61
|
+
dm.addAnims(colorAnim.copy().reverse())
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
}
|
|
65
|
+
);
|
|
66
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { AnimatedScene, HotReloadSetting, SpaceSetting } from "$renderer/lib/scene/sceneClass";
|
|
2
|
+
import { createSVGShape } from "$renderer/lib/rendering/svg/svgRendering";
|
|
3
|
+
import { latexToSVG } from "$renderer/lib/rendering/svg/latexToSVG";
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
export const test_regular_text_latex = (): AnimatedScene => {
|
|
7
|
+
return new AnimatedScene(
|
|
8
|
+
1000, 1000,
|
|
9
|
+
SpaceSetting.ThreeDim,
|
|
10
|
+
HotReloadSetting.TraceFromStart,
|
|
11
|
+
async (dm) => {
|
|
12
|
+
const svg = latexToSVG(String.raw`\text{This library is "DefinedMotion"}`);
|
|
13
|
+
const g = createSVGShape(svg, 20);
|
|
14
|
+
g.position.y += 2
|
|
15
|
+
const svg2 = latexToSVG(String.raw`\text{\textsf{This library is "DefinedMotion"}}`);
|
|
16
|
+
const g2 = createSVGShape(svg2, 20);
|
|
17
|
+
g2.position.y -= 2
|
|
18
|
+
dm.add(g, g2);
|
|
19
|
+
}
|
|
20
|
+
);
|
|
21
|
+
};
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { AnimatedScene, HotReloadSetting, SpaceSetting } from "$renderer/lib/scene/sceneClass";
|
|
2
|
+
import { createSVGShape } from "$renderer/lib/rendering/svg/svgRendering";
|
|
3
|
+
import { latexToSVG } from "$renderer/lib/rendering/svg/latexToSVG";
|
|
4
|
+
|
|
5
|
+
export const test_super_complex_latex_to_svg = (): AnimatedScene => {
|
|
6
|
+
return new AnimatedScene(
|
|
7
|
+
1000, 1000,
|
|
8
|
+
SpaceSetting.ThreeDim,
|
|
9
|
+
HotReloadSetting.TraceFromStart,
|
|
10
|
+
async (dm) => {
|
|
11
|
+
|
|
12
|
+
// 1) Big "everything" block
|
|
13
|
+
const block1 = latexToSVG(String.raw`
|
|
14
|
+
\begin{aligned}
|
|
15
|
+
\textbf{Fourier:}\quad
|
|
16
|
+
\hat{f}(\omega) &= \int_{-\infty}^{\infty} f(t)\,e^{-i\omega t}\,dt,
|
|
17
|
+
& f(t) &= \frac{1}{2\pi}\int_{-\infty}^{\infty} \hat{f}(\omega)\,e^{i\omega t}\,d\omega \\[6pt]
|
|
18
|
+
\textbf{Gamma/Zeta:}\quad
|
|
19
|
+
\Gamma(z) &= \int_{0}^{\infty} t^{z-1} e^{-t}\,dt,
|
|
20
|
+
& \zeta(s) &= \prod_{p\in\mathbb{P}} \frac{1}{1-p^{-s}} \\[6pt]
|
|
21
|
+
\textbf{Cauchy–Schwarz:}\quad
|
|
22
|
+
\big|\langle \mathbf{x},\mathbf{y}\rangle\big| &\le \|\mathbf{x}\|_2\,\|\mathbf{y}\|_2 \\[6pt]
|
|
23
|
+
\textbf{Euler:}\quad
|
|
24
|
+
e^{i\theta} &= \cos\theta + i\sin\theta \\[6pt]
|
|
25
|
+
\textbf{Gradient step:}\quad
|
|
26
|
+
\theta_{t+1} &= \theta_t - \eta\,\nabla_\theta \mathcal{L}(\theta_t) \\[6pt]
|
|
27
|
+
\textbf{KL:}\quad
|
|
28
|
+
\mathrm{KL}\!\left(p\,\|\,q\right) &= \int p(x)\,\log\!\frac{p(x)}{q(x)}\,dx \\[6pt]
|
|
29
|
+
\textbf{Limits:}\quad
|
|
30
|
+
\limsup_{n\to\infty} a_n &\ge \liminf_{n\to\infty} a_n \\[6pt]
|
|
31
|
+
\textbf{Argmin:}\quad
|
|
32
|
+
\hat{\theta} &= \arg\min_{\theta\in\mathbb{R}^d} \; \frac{1}{n}\sum_{i=1}^n \ell\!\big(f_\theta(x_i), y_i\big) \\[6pt]
|
|
33
|
+
\textbf{Binomial:}\quad
|
|
34
|
+
(1+x)^n &= \sum_{k=0}^{n} \binom{n}{k} x^k
|
|
35
|
+
\end{aligned}
|
|
36
|
+
`);
|
|
37
|
+
|
|
38
|
+
const g1 = createSVGShape(block1, 16); // width in your world units
|
|
39
|
+
g1.position.set(0, 6, 0);
|
|
40
|
+
dm.add(g1);
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
// 2) Matrix / determinant / vector hats & bars / piecewise
|
|
44
|
+
const block2 = latexToSVG(String.raw`
|
|
45
|
+
\begin{aligned}
|
|
46
|
+
\textbf{Matrix:}\quad
|
|
47
|
+
A &= \begin{bmatrix}
|
|
48
|
+
a & b & c\\
|
|
49
|
+
d & e & f\\
|
|
50
|
+
g & h & i
|
|
51
|
+
\end{bmatrix},
|
|
52
|
+
&\quad \det(A) &=
|
|
53
|
+
\left|\begin{matrix}
|
|
54
|
+
a & b & c\\
|
|
55
|
+
d & e & f\\
|
|
56
|
+
g & h & i
|
|
57
|
+
\end{matrix}\right| \\[6pt]
|
|
58
|
+
\textbf{Vectors:}\quad
|
|
59
|
+
\hat{\mathbf{v}} &= \frac{\mathbf{v}}{\|\mathbf{v}\|},\qquad
|
|
60
|
+
\overline{x} = \frac{1}{n}\sum_{k=1}^{n} x_k,\qquad
|
|
61
|
+
\vec{\nabla}\cdot\vec{E} = \frac{\rho}{\varepsilon_0} \\[6pt]
|
|
62
|
+
\textbf{Piecewise:}\quad
|
|
63
|
+
\mathrm{ReLU}(x) &=
|
|
64
|
+
\begin{cases}
|
|
65
|
+
0, & x<0\\
|
|
66
|
+
x, & x\ge 0
|
|
67
|
+
\end{cases}
|
|
68
|
+
\end{aligned}
|
|
69
|
+
`);
|
|
70
|
+
|
|
71
|
+
const g2 = createSVGShape(block2, 14);
|
|
72
|
+
g2.position.set(0, -2, 0);
|
|
73
|
+
dm.add(g2);
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
// 3) Probability / expectation / covariance / set notation / sqrt
|
|
77
|
+
const block3 = latexToSVG(String.raw`
|
|
78
|
+
\begin{aligned}
|
|
79
|
+
\textbf{Probability:}\quad
|
|
80
|
+
\mathbb{P}(A\mid B) &= \frac{\mathbb{P}(A\cap B)}{\mathbb{P}(B)},\qquad
|
|
81
|
+
\mathbb{E}[X] = \int_{\mathbb{R}} x\, d\mathbb{P}(x) \\[6pt]
|
|
82
|
+
\textbf{Variance/Covariance:}\quad
|
|
83
|
+
\mathrm{Var}(X) &= \mathbb{E}[X^2] - (\mathbb{E}[X])^2,\qquad
|
|
84
|
+
\mathrm{Cov}(X,Y) = \mathbb{E}[XY]-\mathbb{E}[X]\mathbb{E}[Y] \\[6pt]
|
|
85
|
+
\textbf{Sets/Norms:}\quad
|
|
86
|
+
\mathcal{S} &= \{\,x\in\mathbb{R}^n : \|x\|_2 \le r\,\},\qquad
|
|
87
|
+
\sqrt[n]{1+x} \approx 1 + \frac{x}{n}
|
|
88
|
+
\end{aligned}
|
|
89
|
+
`);
|
|
90
|
+
|
|
91
|
+
const g3 = createSVGShape(block3, 12);
|
|
92
|
+
g3.position.set(0, -8.5, 0);
|
|
93
|
+
dm.add(g3);
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
}
|
|
97
|
+
);
|
|
98
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { AnimatedScene, HotReloadSetting, SpaceSetting } from "$renderer/lib/scene/sceneClass";
|
|
2
|
+
import gravityTextSVG from '$assets/for_tests/svg/gravity_text.svg?raw'
|
|
3
|
+
import gripSVG from '$assets/for_tests/svg/grip_figure.svg?raw'
|
|
4
|
+
import { createSVGShape } from "$renderer/lib/rendering/svg/svgRendering";
|
|
5
|
+
import { updateSVGShape } from "$renderer/lib/rendering/svg/svgObjectHelpers";
|
|
6
|
+
import { fadeOut, setOpacity, updateSVGAnim } from "$renderer/lib/animation/animations";
|
|
7
|
+
import { latexToSVG } from "$renderer/lib/rendering/svg/latexToSVG";
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
export const test_transition_svgs = ():AnimatedScene => {
|
|
11
|
+
return new AnimatedScene(1000, 1000, SpaceSetting.ThreeDim, HotReloadSetting.TraceFromStart, async (dm) => {
|
|
12
|
+
const svgObject = createSVGShape(gravityTextSVG, 15)
|
|
13
|
+
dm.add(svgObject)
|
|
14
|
+
|
|
15
|
+
dm.addWait(500)
|
|
16
|
+
const anim = updateSVGAnim(svgObject, gripSVG, 300, 10)
|
|
17
|
+
dm.addAnims(anim)
|
|
18
|
+
dm.addWait(500)
|
|
19
|
+
const raw = latexToSVG(String.raw`
|
|
20
|
+
\begin{aligned}
|
|
21
|
+
\hat{f}(\omega) &= \int_{-\infty}^{\infty} f(t)\,e^{-i\omega t}\,dt,\\
|
|
22
|
+
f(t) &= \frac{1}{2\pi}\int_{-\infty}^{\infty} \hat{f}(\omega)\,e^{i\omega t}\,d\omega,\\[6pt]
|
|
23
|
+
\Gamma(z) &= \int_{0}^{\infty} t^{z-1} e^{-t}\,dt,\qquad
|
|
24
|
+
\zeta(s) = \prod_{p\in\mathbb{P}} \frac{1}{1-p^{-s}}
|
|
25
|
+
\end{aligned}
|
|
26
|
+
`, { display: true });
|
|
27
|
+
const anim2 = updateSVGAnim(svgObject, raw, 300, 20)
|
|
28
|
+
dm.addAnims(anim2)
|
|
29
|
+
dm.addWait(500)
|
|
30
|
+
const anim3 = fadeOut(svgObject, 300)
|
|
31
|
+
dm.addAnims(anim3)
|
|
32
|
+
})
|
|
33
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { AnimatedScene, HotReloadSetting, SpaceSetting } from "$renderer/lib/scene/sceneClass";
|
|
2
|
+
import gravityTextSVG from '$assets/for_tests/svg/gravity_text.svg?raw'
|
|
3
|
+
import gripSVG from '$assets/for_tests/svg/grip_figure.svg?raw'
|
|
4
|
+
import { createSVGShape } from "$renderer/lib/rendering/svg/svgRendering";
|
|
5
|
+
import { updateSVGShape } from "$renderer/lib/rendering/svg/svgObjectHelpers";
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
export const test_update_svg_object = ():AnimatedScene => {
|
|
9
|
+
return new AnimatedScene(1000, 1000, SpaceSetting.ThreeDim, HotReloadSetting.TraceFromStart, async (dm) => {
|
|
10
|
+
const svgObject = createSVGShape(gravityTextSVG, 10)
|
|
11
|
+
dm.add(svgObject)
|
|
12
|
+
|
|
13
|
+
dm.addWait(500)
|
|
14
|
+
dm.do(() => {
|
|
15
|
+
updateSVGShape(svgObject, gripSVG)
|
|
16
|
+
})
|
|
17
|
+
dm.addWait(500)
|
|
18
|
+
})
|
|
19
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { AnimatedScene, HotReloadSetting, SpaceSetting } from "$renderer/lib/scene/sceneClass";
|
|
2
|
+
import gravityTextSVG from '$assets/for_tests/svg/grip_figure.svg?raw'
|
|
3
|
+
import { createSVGShape } from "$renderer/lib/rendering/svg/svgRendering";
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
export const test_yellow_grip_symbol_svg = ():AnimatedScene => {
|
|
7
|
+
return new AnimatedScene(1000, 1000, SpaceSetting.ThreeDim, HotReloadSetting.TraceFromStart, async (dm) => {
|
|
8
|
+
const shape = createSVGShape(gravityTextSVG, 10)
|
|
9
|
+
dm.add(shape)
|
|
10
|
+
})
|
|
11
|
+
}
|
|
@@ -37,18 +37,18 @@ export function tutorial_easy1(): AnimatedScene {
|
|
|
37
37
|
// And give a function that is called for each frame with the current interpolation value
|
|
38
38
|
const anim = createAnim(easeInOutQuad(-5, 5, 500), (value) => (circle.position.x = value))
|
|
39
39
|
|
|
40
|
-
// We use "
|
|
40
|
+
// We use "addAnims" to schedule an animation, it will run from the frame (tick) it was added at
|
|
41
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
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
43
|
// Then it just adds the animation with that offset
|
|
44
|
-
scene.
|
|
44
|
+
scene.addAnims(anim)
|
|
45
45
|
|
|
46
46
|
// To make the circle also go back, we can reverse the entire animation and add it again
|
|
47
47
|
// Notice that we are copying it, this is so that the reverse() doesn't affect the original variable "anim"
|
|
48
|
-
scene.
|
|
48
|
+
scene.addAnims(anim.copy().reverse())
|
|
49
49
|
|
|
50
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 "
|
|
51
|
+
// This doesn't push the tick forward like the "addAnims" does.
|
|
52
52
|
// It just declares a function that should be run at each frame
|
|
53
53
|
// For this animation, we want to set a color to the circle at each frame.
|
|
54
54
|
scene.onEachTick((tick) => {
|
|
@@ -12,12 +12,10 @@ import { AnimatedScene, HotReloadSetting, SpaceSetting } from '$renderer/lib/sce
|
|
|
12
12
|
// If your helpers live elsewhere, tweak these paths:
|
|
13
13
|
import {
|
|
14
14
|
addBackgroundGradient,
|
|
15
|
-
addHDRI,
|
|
16
|
-
loadHDRIData,
|
|
17
|
-
HDRIs
|
|
18
15
|
} from '$renderer/lib/rendering/lighting3d'
|
|
19
16
|
import { setOpacity } from '$renderer/lib/animation/animations'
|
|
20
17
|
import { createLine } from '$renderer/lib/rendering/objects2d'
|
|
18
|
+
import { addHDRI, HDRIs, loadHDRIData } from '$renderer/lib/rendering/hdri'
|
|
21
19
|
|
|
22
20
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
23
21
|
// Step 0: Scene constants and materials
|
|
@@ -67,8 +65,8 @@ export function tutorial_medium1(): AnimatedScene {
|
|
|
67
65
|
// Step 3: Lighting & background
|
|
68
66
|
// HDRI gives nice reflections/IBL; gradient provides a subtle backdrop.
|
|
69
67
|
// ───────────────────────────────────────────────────────────────────────
|
|
70
|
-
const hdriData = await loadHDRIData(HDRIs.photoStudio1, 2
|
|
71
|
-
await addHDRI(scene, hdriData, 0.3) // envMap intensity
|
|
68
|
+
const hdriData = await loadHDRIData(HDRIs.photoStudio1, 2) // (lods, intensity normalization)
|
|
69
|
+
await addHDRI(scene, hdriData, 0.3, 0.5) // envMap intensity
|
|
72
70
|
|
|
73
71
|
addBackgroundGradient({
|
|
74
72
|
scene,
|
|
@@ -1,11 +1,9 @@
|
|
|
1
|
+
import { addHDRI, HDRIs, loadHDRIData } from '$renderer/lib/rendering/hdri'
|
|
1
2
|
import { linspace } from '../renderer/src/lib/mathHelpers/vectors'
|
|
2
3
|
import { COLORS } from '../renderer/src/lib/rendering/helpers'
|
|
3
4
|
import {
|
|
4
5
|
addBackgroundGradient,
|
|
5
|
-
addHDRI,
|
|
6
6
|
addSceneLighting,
|
|
7
|
-
HDRIs,
|
|
8
|
-
loadHDRIData
|
|
9
7
|
} from '../renderer/src/lib/rendering/lighting3d'
|
|
10
8
|
import { createFastText } from '../renderer/src/lib/rendering/objects2d'
|
|
11
9
|
import { AnimatedScene, HotReloadSetting, SpaceSetting } from '../renderer/src/lib/scene/sceneClass'
|
|
@@ -41,7 +39,7 @@ export const field: VectorField3D = (x, y, z, time) => {
|
|
|
41
39
|
}
|
|
42
40
|
}
|
|
43
41
|
|
|
44
|
-
const hdriData = await loadHDRIData(HDRIs.outdoor1, 2
|
|
42
|
+
const hdriData = await loadHDRIData(HDRIs.outdoor1, 2)
|
|
45
43
|
|
|
46
44
|
export const vectorFieldScene = (): AnimatedScene => {
|
|
47
45
|
return new AnimatedScene(
|
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
import { COLORS } from '../renderer/src/lib/rendering/helpers'
|
|
2
2
|
import {
|
|
3
3
|
addBackgroundGradient,
|
|
4
|
-
addHDRI,
|
|
5
4
|
addSceneLighting,
|
|
6
|
-
HDRIs,
|
|
7
|
-
loadHDRIData
|
|
8
5
|
} from '../renderer/src/lib/rendering/lighting3d'
|
|
9
6
|
import { AnimatedScene, HotReloadSetting, SpaceSetting } from '../renderer/src/lib/scene/sceneClass'
|
|
10
7
|
import * as THREE from 'three'
|
|
@@ -19,6 +16,7 @@ import {
|
|
|
19
16
|
setOpacity
|
|
20
17
|
} from '../renderer/src/lib/animation/animations'
|
|
21
18
|
import { createFastText, updateText } from '../renderer/src/lib/rendering/objects2d'
|
|
19
|
+
import { addHDRI, HDRIs, loadHDRIData } from '$renderer/lib/rendering/hdri'
|
|
22
20
|
|
|
23
21
|
const functions: [string, (x: number) => number][] = [
|
|
24
22
|
// ──────────── Start Simple & Recognizable ────────────
|
|
@@ -95,9 +93,9 @@ const morphAnimation = (
|
|
|
95
93
|
line.setPoints(interpolate(vecFunc1, vecFunc2, value))
|
|
96
94
|
})
|
|
97
95
|
}
|
|
98
|
-
const hdriData = await loadHDRIData(HDRIs.outdoor1, 1
|
|
96
|
+
const hdriData = await loadHDRIData(HDRIs.outdoor1, 1)
|
|
99
97
|
|
|
100
|
-
export const
|
|
98
|
+
export const animatedFunctionsScene = (): AnimatedScene => {
|
|
101
99
|
return new AnimatedScene(
|
|
102
100
|
1080,
|
|
103
101
|
2160,
|
|
@@ -157,11 +155,11 @@ export const functionsAnimation = (): AnimatedScene => {
|
|
|
157
155
|
scene.addSequentialBackgroundAnims(
|
|
158
156
|
morphAnimation(plotLine, vecFuncs[i], vecFuncs[i + 1], 300)
|
|
159
157
|
)
|
|
160
|
-
scene.
|
|
158
|
+
scene.addAnims(fadeOut(textNode, 150))
|
|
161
159
|
scene.do(async () => {
|
|
162
160
|
await updateText(textNode, functions[i + 1][0])
|
|
163
161
|
})
|
|
164
|
-
scene.
|
|
162
|
+
scene.addAnims(fadeIn(textNode, 150))
|
|
165
163
|
scene.addWait(800)
|
|
166
164
|
}
|
|
167
165
|
|
|
@@ -1,18 +1,41 @@
|
|
|
1
|
-
import { app, shell, BrowserWindow, ipcMain } from 'electron'
|
|
1
|
+
import { app, shell, BrowserWindow, ipcMain, nativeTheme, screen } from 'electron'
|
|
2
2
|
import { join } from 'path'
|
|
3
3
|
import { electronApp, optimizer, is } from '@electron-toolkit/utils'
|
|
4
4
|
import icon from '../../resources/icon.png?asset'
|
|
5
5
|
import { renderVideo } from './rendering'
|
|
6
6
|
import { deleteRenderedContent } from './storage'
|
|
7
|
+
import ElectronStore from 'electron-store'
|
|
8
|
+
|
|
9
|
+
const store = new ElectronStore()
|
|
10
|
+
|
|
11
|
+
// Force light mode
|
|
12
|
+
nativeTheme.themeSource = 'light'
|
|
7
13
|
|
|
8
14
|
let mainWindow: BrowserWindow
|
|
9
15
|
|
|
16
|
+
function getHzForWebContents(wc: Electron.WebContents): number {
|
|
17
|
+
const win = BrowserWindow.fromWebContents(wc)
|
|
18
|
+
if (win) {
|
|
19
|
+
const b = win.getBounds()
|
|
20
|
+
const nearest = screen.getDisplayNearestPoint({ x: b.x, y: b.y })
|
|
21
|
+
return nearest.displayFrequency || 60
|
|
22
|
+
}
|
|
23
|
+
// Fallback to primary display
|
|
24
|
+
return screen.getPrimaryDisplay().displayFrequency || 60
|
|
25
|
+
}
|
|
26
|
+
|
|
10
27
|
function createWindow(): void {
|
|
11
28
|
// Create the browser window.
|
|
29
|
+
|
|
30
|
+
const defaultBounds = { width: 1000, height: 1300 }
|
|
31
|
+
const savedBounds: any = store.get('windowBounds', defaultBounds)
|
|
12
32
|
mainWindow = new BrowserWindow({
|
|
13
|
-
width:
|
|
14
|
-
height:
|
|
33
|
+
width: savedBounds.width,
|
|
34
|
+
height: savedBounds.height,
|
|
35
|
+
x: savedBounds.x,
|
|
36
|
+
y: savedBounds.y,
|
|
15
37
|
show: false,
|
|
38
|
+
title: "DefinedMotion",
|
|
16
39
|
autoHideMenuBar: true,
|
|
17
40
|
...(process.platform === 'linux' ? { icon } : {}),
|
|
18
41
|
webPreferences: {
|
|
@@ -26,6 +49,14 @@ function createWindow(): void {
|
|
|
26
49
|
}
|
|
27
50
|
})
|
|
28
51
|
|
|
52
|
+
mainWindow.on('resize', () => {
|
|
53
|
+
store.set('windowBounds', mainWindow.getBounds())
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
mainWindow.on('move', () => {
|
|
57
|
+
store.set('windowBounds', mainWindow.getBounds())
|
|
58
|
+
})
|
|
59
|
+
|
|
29
60
|
mainWindow.on('ready-to-show', () => {
|
|
30
61
|
mainWindow.show()
|
|
31
62
|
})
|
|
@@ -75,6 +106,31 @@ app.whenReady().then(() => {
|
|
|
75
106
|
// dock icon is clicked and there are no other windows open.
|
|
76
107
|
if (BrowserWindow.getAllWindows().length === 0) createWindow()
|
|
77
108
|
})
|
|
109
|
+
|
|
110
|
+
// RPC: renderer asks main for the current display refresh rate (Hz)
|
|
111
|
+
ipcMain.handle('get-display-hz', (event) => {
|
|
112
|
+
return getHzForWebContents(event.sender)
|
|
113
|
+
})
|
|
114
|
+
|
|
115
|
+
function broadcastHzToAllWindows() {
|
|
116
|
+
for (const w of BrowserWindow.getAllWindows()) {
|
|
117
|
+
const hz = getHzForWebContents(w.webContents)
|
|
118
|
+
w.webContents.send('display-hz-changed', hz)
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Display geometry / metrics changed (resolution/scale/mode changes, some moves)
|
|
123
|
+
screen.on('display-metrics-changed', () => {
|
|
124
|
+
broadcastHzToAllWindows()
|
|
125
|
+
})
|
|
126
|
+
|
|
127
|
+
// Displays added/removed (dock/undock, hot-plug)
|
|
128
|
+
screen.on('display-added', () => {
|
|
129
|
+
broadcastHzToAllWindows()
|
|
130
|
+
})
|
|
131
|
+
screen.on('display-removed', () => {
|
|
132
|
+
broadcastHzToAllWindows()
|
|
133
|
+
})
|
|
78
134
|
})
|
|
79
135
|
|
|
80
136
|
ipcMain.handle('start-video-render', async (event, options) => {
|