@nadicodeai/ui 8.5.0 → 9.0.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/AGENTS.md +1 -1
- package/LICENSES/THINKING-ORBS-MIT.txt +21 -0
- package/NOTICE +7 -10
- package/dist/components/agent-orb-appearance.d.ts +54 -0
- package/dist/components/agent-orb-appearance.d.ts.map +1 -0
- package/dist/components/agent-orb-appearance.js +87 -0
- package/dist/components/agent-orb.d.ts +5 -3
- package/dist/components/agent-orb.d.ts.map +1 -1
- package/dist/eslint/index.js +4 -0
- package/dist/eslint/rules/expect-chain.js +60 -0
- package/dist/eslint/rules/no-existence-only-assertion.js +89 -0
- package/dist/eslint/rules/no-subject-derived-expectation.js +129 -0
- package/dist/index.d.ts +0 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -2
- package/dist/internal/agent-orb-motion.d.ts +3 -3
- package/dist/internal/agent-orb-motion.d.ts.map +1 -1
- package/dist/internal/agent-orb-motion.js +1 -0
- package/dist/internal/agent-orb.d.ts +11 -1
- package/dist/internal/agent-orb.d.ts.map +1 -1
- package/dist/internal/agent-orb.js +80 -5
- package/docs/agent-orb.md +47 -14
- package/docs/contract.md +8 -29
- package/docs/migration/9.0.0.md +35 -0
- package/package.json +2 -3
- package/LICENSES/PAPER-SHADERS-APACHE-2.0.txt +0 -186
- package/dist/components/agent-visual.d.ts +0 -17
- package/dist/components/agent-visual.d.ts.map +0 -1
- package/dist/components/agent-visual.js +0 -63
- package/dist/components/forma-appearance.d.ts +0 -13
- package/dist/components/forma-appearance.d.ts.map +0 -1
- package/dist/components/forma-appearance.js +0 -11
- package/dist/components/forma-avatar.d.ts +0 -23
- package/dist/components/forma-avatar.d.ts.map +0 -1
- package/dist/components/forma-avatar.js +0 -95
- package/dist/internal/agent-visual/color.d.ts +0 -4
- package/dist/internal/agent-visual/color.d.ts.map +0 -1
- package/dist/internal/agent-visual/color.js +0 -78
- package/dist/internal/agent-visual/poster.d.ts +0 -6
- package/dist/internal/agent-visual/poster.d.ts.map +0 -1
- package/dist/internal/agent-visual/poster.js +0 -35
- package/dist/internal/agent-visual/recipes.d.ts +0 -15
- package/dist/internal/agent-visual/recipes.d.ts.map +0 -1
- package/dist/internal/agent-visual/recipes.js +0 -72
- package/dist/internal/agent-visual/renderer.d.ts +0 -10
- package/dist/internal/agent-visual/renderer.d.ts.map +0 -1
- package/dist/internal/agent-visual/renderer.js +0 -112
- package/dist/internal/agent-visual/shader.d.ts +0 -2
- package/dist/internal/agent-visual/shader.d.ts.map +0 -1
- package/dist/internal/agent-visual/shader.js +0 -158
- package/dist/internal/forma/frame.d.ts +0 -10
- package/dist/internal/forma/frame.d.ts.map +0 -1
- package/dist/internal/forma/frame.js +0 -211
- package/dist/internal/forma/geometry.d.ts +0 -41
- package/dist/internal/forma/geometry.d.ts.map +0 -1
- package/dist/internal/forma/geometry.js +0 -235
- package/dist/internal/forma/hallmark.d.ts +0 -5
- package/dist/internal/forma/hallmark.d.ts.map +0 -1
- package/dist/internal/forma/hallmark.js +0 -4
- package/dist/internal/forma/model.d.ts +0 -53
- package/dist/internal/forma/model.d.ts.map +0 -1
- package/dist/internal/forma/model.js +0 -70
- package/dist/internal/forma/motion.d.ts +0 -42
- package/dist/internal/forma/motion.d.ts.map +0 -1
- package/dist/internal/forma/motion.js +0 -194
- package/dist/internal/forma/rig.d.ts +0 -10
- package/dist/internal/forma/rig.d.ts.map +0 -1
- package/dist/internal/forma/rig.js +0 -211
- package/dist/internal/forma/still.d.ts +0 -4
- package/dist/internal/forma/still.d.ts.map +0 -1
- package/dist/internal/forma/still.js +0 -8
- package/dist/internal/forma/stored-appearance.d.ts +0 -29
- package/dist/internal/forma/stored-appearance.d.ts.map +0 -1
- package/dist/internal/forma/stored-appearance.js +0 -53
- package/docs/agent-visual.md +0 -114
- package/docs/forma-avatar.md +0 -110
|
@@ -1,158 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Modified from Paper Shaders 0.0.78 Metaballs (Apache-2.0).
|
|
3
|
-
* The metaball field, motion, colour blending, and edge calculation remain
|
|
4
|
-
* Paper's construction. `surfacePattern` clips the four approved NadicodeAI
|
|
5
|
-
* identity materials inside that generated form. Attribution ships in NOTICE.
|
|
6
|
-
*/
|
|
7
|
-
export const AGENT_VISUAL_SHADER = `#version 300 es
|
|
8
|
-
precision mediump float;
|
|
9
|
-
|
|
10
|
-
uniform float u_time;
|
|
11
|
-
uniform sampler2D u_noiseTexture;
|
|
12
|
-
uniform vec4 u_colorBack;
|
|
13
|
-
uniform vec4 u_colors[8];
|
|
14
|
-
uniform float u_colorsCount;
|
|
15
|
-
uniform float u_size;
|
|
16
|
-
uniform float u_count;
|
|
17
|
-
uniform float u_material;
|
|
18
|
-
uniform float u_detail;
|
|
19
|
-
uniform vec2 u_resolution;
|
|
20
|
-
|
|
21
|
-
in vec2 v_objectUV;
|
|
22
|
-
out vec4 fragColor;
|
|
23
|
-
|
|
24
|
-
#define TWO_PI 6.28318530718
|
|
25
|
-
|
|
26
|
-
float randomR(vec2 p) {
|
|
27
|
-
vec2 uv = floor(p) / 100. + .5;
|
|
28
|
-
return texture(u_noiseTexture, fract(uv)).r;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
float noise(float x) {
|
|
32
|
-
float i = floor(x);
|
|
33
|
-
float f = fract(x);
|
|
34
|
-
float u = f * f * (3.0 - 2.0 * f);
|
|
35
|
-
return mix(randomR(vec2(i, 0.0)), randomR(vec2(i + 1.0, 0.0)), u);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
float getBallShape(vec2 uv, vec2 c, float p) {
|
|
39
|
-
float s = .5 * length(uv - c);
|
|
40
|
-
s = 1. - clamp(s, 0., 1.);
|
|
41
|
-
return pow(s, p);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
float hash21(vec2 p) {
|
|
45
|
-
p = fract(p * vec2(123.34, 456.21));
|
|
46
|
-
p += dot(p, p + 45.32);
|
|
47
|
-
return fract(p.x * p.y);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
float orderedPoints(vec2 surfaceUV, float depth) {
|
|
51
|
-
float density = clamp(min(u_resolution.x, u_resolution.y) / 12.0 * u_detail, 6.0, 34.0);
|
|
52
|
-
vec2 pointUV = fract(surfaceUV * density) - 0.5;
|
|
53
|
-
float radius = mix(0.14, 0.23, depth);
|
|
54
|
-
return 1.0 - smoothstep(radius * 0.7, radius, length(pointUV));
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
float triangularWire(vec2 surfaceUV, float depth) {
|
|
58
|
-
float density = clamp(min(u_resolution.x, u_resolution.y) / 16.0 * u_detail, 5.0, 26.0);
|
|
59
|
-
vec2 grid = surfaceUV * density;
|
|
60
|
-
float horizontal = abs(fract(grid.y) - 0.5);
|
|
61
|
-
float diagonalA = abs(fract(grid.x + grid.y * 0.5) - 0.5);
|
|
62
|
-
float diagonalB = abs(fract(grid.x - grid.y * 0.5) - 0.5);
|
|
63
|
-
float nearestLine = min(horizontal, min(diagonalA, diagonalB));
|
|
64
|
-
float width = mix(0.032, 0.072, depth);
|
|
65
|
-
return 1.0 - smoothstep(width * 0.55, width, nearestLine);
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
float particleLayer(vec2 surfaceUV, float density, float depth, float time, float layerSeed, float threshold) {
|
|
69
|
-
vec2 gridUV = surfaceUV * density + layerSeed;
|
|
70
|
-
vec2 cell = floor(gridUV);
|
|
71
|
-
vec2 local = fract(gridUV) - 0.5;
|
|
72
|
-
float seed = hash21(cell + layerSeed);
|
|
73
|
-
vec2 jitter = vec2(hash21(cell + layerSeed + 3.17), hash21(cell + layerSeed + 8.41)) - 0.5;
|
|
74
|
-
jitter *= 0.72;
|
|
75
|
-
jitter += 0.08 * vec2(sin(time * 0.42 + seed * 18.0 + layerSeed), cos(time * 0.31 + seed * 14.0 - layerSeed));
|
|
76
|
-
float radius = mix(0.055, 0.175, hash21(cell + layerSeed + 14.3)) * mix(0.78, 1.35, depth);
|
|
77
|
-
float particle = 1.0 - smoothstep(radius * 0.68, radius, length(local - jitter));
|
|
78
|
-
float brightness = mix(0.45, 1.0, hash21(cell + layerSeed + 24.7));
|
|
79
|
-
return particle * step(threshold, seed) * brightness;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
float livingParticles(vec2 surfaceUV, float depth, float time) {
|
|
83
|
-
float density = clamp(min(u_resolution.x, u_resolution.y) / 6.5 * u_detail, 13.0, 68.0);
|
|
84
|
-
float dust = particleLayer(surfaceUV, density, depth, time, 0.0, 0.16);
|
|
85
|
-
float motes = particleLayer(surfaceUV, density * 0.46, depth, time * 0.72, 19.7, 0.62);
|
|
86
|
-
return max(dust * 0.78, motes);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
float surfacePattern(vec2 surfaceUV, float depth, float material, float time) {
|
|
90
|
-
if (material < 0.5) return 1.0;
|
|
91
|
-
if (material < 1.5) return orderedPoints(surfaceUV, depth);
|
|
92
|
-
if (material < 2.5) return triangularWire(surfaceUV, depth);
|
|
93
|
-
return livingParticles(surfaceUV, depth, time);
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
void main() {
|
|
97
|
-
vec2 shape_uv = v_objectUV + .5;
|
|
98
|
-
const float firstFrameOffset = 2503.4;
|
|
99
|
-
float t = .2 * (u_time + firstFrameOffset);
|
|
100
|
-
vec3 totalColor = vec3(0.);
|
|
101
|
-
float totalShape = 0.;
|
|
102
|
-
float totalOpacity = 0.;
|
|
103
|
-
vec2 weightedCenter = vec2(0.);
|
|
104
|
-
vec2 weightedOrientation = vec2(0.);
|
|
105
|
-
float centerWeight = 0.;
|
|
106
|
-
|
|
107
|
-
for (int i = 0; i < 20; i++) {
|
|
108
|
-
if (i >= int(ceil(u_count))) break;
|
|
109
|
-
float idxFract = float(i) / 20.0;
|
|
110
|
-
float angle = TWO_PI * idxFract;
|
|
111
|
-
float speed = 1. - .2 * idxFract;
|
|
112
|
-
vec2 pos = vec2(.5) + 1e-4 + .9 * (vec2(noise(angle * 10. + float(i) + t * speed), noise(angle * 20. + float(i) - t * speed)) - .5);
|
|
113
|
-
int safeIndex = i % int(u_colorsCount + 0.5);
|
|
114
|
-
vec4 ballColor = u_colors[safeIndex];
|
|
115
|
-
ballColor.rgb *= ballColor.a;
|
|
116
|
-
float sizeFrac = 1.;
|
|
117
|
-
if (float(i) > floor(u_count - 1.)) sizeFrac *= fract(u_count);
|
|
118
|
-
float shape = getBallShape(shape_uv, pos, 45. - 30. * u_size * sizeFrac);
|
|
119
|
-
shape *= pow(u_size, .2);
|
|
120
|
-
shape = smoothstep(0., 1., shape);
|
|
121
|
-
totalColor += ballColor.rgb * shape;
|
|
122
|
-
totalShape += shape;
|
|
123
|
-
totalOpacity += ballColor.a * shape;
|
|
124
|
-
float centerContribution = shape * shape;
|
|
125
|
-
weightedCenter += pos * centerContribution;
|
|
126
|
-
weightedOrientation += vec2(cos(angle), sin(angle)) * centerContribution;
|
|
127
|
-
centerWeight += centerContribution;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
totalColor /= max(totalShape, 1e-4);
|
|
131
|
-
totalOpacity /= max(totalShape, 1e-4);
|
|
132
|
-
float edgeWidth = fwidth(totalShape);
|
|
133
|
-
float finalShape = smoothstep(.4, .4 + edgeWidth, totalShape);
|
|
134
|
-
vec2 fieldCenter = weightedCenter / max(centerWeight, 1e-4);
|
|
135
|
-
vec2 fieldVector = shape_uv - fieldCenter;
|
|
136
|
-
float depth = smoothstep(0.4, 1.45, totalShape);
|
|
137
|
-
float fieldRotation = 0.18 * atan(weightedOrientation.y, weightedOrientation.x);
|
|
138
|
-
float rotationCos = cos(fieldRotation);
|
|
139
|
-
float rotationSin = sin(fieldRotation);
|
|
140
|
-
vec2 surfaceUV = fieldCenter + mat2(rotationCos, rotationSin, -rotationSin, rotationCos) * fieldVector * (1.0 + 0.1 * depth);
|
|
141
|
-
vec2 gradient = vec2(dFdx(totalShape), dFdy(totalShape));
|
|
142
|
-
vec2 gradientDirection = gradient / max(length(gradient), 1e-4);
|
|
143
|
-
surfaceUV += gradientDirection * 0.008 * sin(totalShape * 4.0);
|
|
144
|
-
float feature = surfacePattern(surfaceUV, depth, u_material, t);
|
|
145
|
-
vec3 normal = normalize(vec3(-gradient * 36.0, 1.0));
|
|
146
|
-
vec3 lightDirection = normalize(vec3(-0.45, 0.65, 0.8));
|
|
147
|
-
float surfaceLight = 0.62 + 0.38 * max(dot(normal, lightDirection), 0.0);
|
|
148
|
-
float baseSurface = mix(0.012, 0.06, depth);
|
|
149
|
-
float surface = u_material < 0.5 ? 1.0 : mix(baseSurface, surfaceLight, feature);
|
|
150
|
-
vec3 color = totalColor * finalShape * surface;
|
|
151
|
-
float opacity = totalOpacity * finalShape * surface;
|
|
152
|
-
vec3 bgColor = u_colorBack.rgb * u_colorBack.a;
|
|
153
|
-
color = color + bgColor * (1. - opacity);
|
|
154
|
-
opacity = opacity + u_colorBack.a * (1. - opacity);
|
|
155
|
-
color += 1. / 256. * (fract(sin(dot(.014 * gl_FragCoord.xy, vec2(12.9898, 78.233))) * 43758.5453123) - .5);
|
|
156
|
-
fragColor = vec4(color, opacity);
|
|
157
|
-
}
|
|
158
|
-
`;
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { type FormaMotion, type Pose } from "./motion.js";
|
|
2
|
-
export type PartAttributes = Record<string, string>;
|
|
3
|
-
export type Frame = Record<string, PartAttributes>;
|
|
4
|
-
export declare const SHELL_LAYERS: readonly ["tone", "form", "floor", "key", "rim"];
|
|
5
|
-
export declare const ORBIT_DOTS = 20;
|
|
6
|
-
export declare const RIBBON_BEADS = 8;
|
|
7
|
-
export declare function computeFrame(motion: FormaMotion, pose: Pose, now: number): Frame;
|
|
8
|
-
export declare const RIBBON_TILTS: (48 | -22 | -64)[];
|
|
9
|
-
export declare const ORBIT_TILTS: readonly [-0.36, 0.49];
|
|
10
|
-
//# sourceMappingURL=frame.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"frame.d.ts","sourceRoot":"","sources":["../../../src/internal/forma/frame.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAsB,KAAK,WAAW,EAAE,KAAK,IAAI,EAAE,MAAM,UAAU,CAAC;AAE3E,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AACpD,MAAM,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;AAanD,eAAO,MAAM,YAAY,kDAAmD,CAAC;AAY7E,eAAO,MAAM,UAAU,KAAK,CAAC;AAC7B,eAAO,MAAM,YAAY,IAAI,CAAC;AAE9B,wBAAgB,YAAY,CAAC,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,GAAG,KAAK,CAyGhF;AAOD,eAAO,MAAM,YAAY,oBAAuC,CAAC;AACjE,eAAO,MAAM,WAAW,wBAAyB,CAAC"}
|
|
@@ -1,211 +0,0 @@
|
|
|
1
|
-
import { TAU, bodies, closedPath, eyeProfiles, f3, project, shellPath, smooth, stripePath, superellipse, visorPoints, } from "./geometry.js";
|
|
2
|
-
import { HALLMARK_LONGITUDE, HALLMARK_SIZE, ITALY_BOX } from "./hallmark.js";
|
|
3
|
-
import { formDetails } from "./model.js";
|
|
4
|
-
import { easeInOut, easeOut } from "./motion.js";
|
|
5
|
-
const eyeShapes = new Map();
|
|
6
|
-
function eyeShape(form) {
|
|
7
|
-
let shape = eyeShapes.get(form);
|
|
8
|
-
if (!shape) {
|
|
9
|
-
const profile = eyeProfiles[form];
|
|
10
|
-
shape = closedPath(superellipse(profile.width, profile.height, profile.power, 32));
|
|
11
|
-
eyeShapes.set(form, shape);
|
|
12
|
-
}
|
|
13
|
-
return shape;
|
|
14
|
-
}
|
|
15
|
-
export const SHELL_LAYERS = ["tone", "form", "floor", "key", "rim"];
|
|
16
|
-
const VISOR_LAYERS = [
|
|
17
|
-
"visor",
|
|
18
|
-
"visorClip",
|
|
19
|
-
"bezel",
|
|
20
|
-
"bezelLight",
|
|
21
|
-
"visorShade",
|
|
22
|
-
"glass",
|
|
23
|
-
"streak",
|
|
24
|
-
"sole",
|
|
25
|
-
"visorEdge",
|
|
26
|
-
];
|
|
27
|
-
export const ORBIT_DOTS = 20;
|
|
28
|
-
export const RIBBON_BEADS = 8;
|
|
29
|
-
export function computeFrame(motion, pose, now) {
|
|
30
|
-
const body = bodies[motion.form];
|
|
31
|
-
const nadia = motion.form === "nadia";
|
|
32
|
-
const t = (now - motion.entered) / 1000;
|
|
33
|
-
const morph = pose.morph < 0.00005 ? 0 : pose.morph > 0.99995 ? 1 : pose.morph;
|
|
34
|
-
const { yaw, pitch } = pose;
|
|
35
|
-
const frame = {};
|
|
36
|
-
const shell = shellPath(body, morph);
|
|
37
|
-
frame.shell = { d: shell };
|
|
38
|
-
frame.shellClip = { d: shell };
|
|
39
|
-
for (const layer of SHELL_LAYERS)
|
|
40
|
-
frame[layer] = { d: shell };
|
|
41
|
-
frame.tube = { d: shell, opacity: f3(morph) };
|
|
42
|
-
frame.hot = { opacity: f3(1 - morph * 0.6) };
|
|
43
|
-
frame.fade = { d: shell, opacity: f3(nadia ? 0 : morph * 0.28) };
|
|
44
|
-
frame.object = {
|
|
45
|
-
transform: `translate(0 ${f3(pose.lift)}) rotate(${f3((pose.roll * 180) / Math.PI)}) scale(${f3(1 / Math.sqrt(pose.stretch))} ${f3(pose.stretch)})`,
|
|
46
|
-
};
|
|
47
|
-
frame.blockedBar = { opacity: f3(morph > 0.42 ? smooth((morph - 0.42) / 0.4) : 0) };
|
|
48
|
-
if (nadia) {
|
|
49
|
-
frame.bandW = { d: stripePath(body, yaw, -0.36, 0.36) };
|
|
50
|
-
frame.bandR = { d: stripePath(body, yaw, 0.36, Math.PI) };
|
|
51
|
-
frame.bandSand = { d: frame.bandW.d, opacity: f3(morph * 0.28) };
|
|
52
|
-
}
|
|
53
|
-
const faceOpacity = 1 - smooth(morph / 0.52);
|
|
54
|
-
frame.face = { opacity: f3(faceOpacity), display: faceOpacity > 0.001 ? "" : "none" };
|
|
55
|
-
const visor = closedPath(visorPoints.map(([x, y]) => {
|
|
56
|
-
const p = project(body, x, y, yaw, pitch);
|
|
57
|
-
return [p.x, p.y];
|
|
58
|
-
}));
|
|
59
|
-
for (const layer of VISOR_LAYERS)
|
|
60
|
-
frame[layer] = { d: visor };
|
|
61
|
-
if (nadia) {
|
|
62
|
-
const hm = project(body, Math.sin(HALLMARK_LONGITUDE), -0.12, yaw, pitch);
|
|
63
|
-
const scale = HALLMARK_SIZE / ITALY_BOX;
|
|
64
|
-
frame.hallmark = {
|
|
65
|
-
display: hm.front && faceOpacity > 0.001 ? "" : "none",
|
|
66
|
-
transform: `translate(${f3(hm.x)} ${f3(hm.y)}) scale(${f3(hm.sx * scale)} ${f3(-hm.sy * scale)}) translate(${-ITALY_BOX / 2} ${-ITALY_BOX / 2})`,
|
|
67
|
-
};
|
|
68
|
-
}
|
|
69
|
-
const happiness = smooth(pose.done);
|
|
70
|
-
const pauseAmount = smooth((pose.waiting - 0.15) / 0.85);
|
|
71
|
-
const blinkPhase = ((t % 5.2) - 3.4) / 0.16;
|
|
72
|
-
const blink = !motion.still &&
|
|
73
|
-
motion.state !== "blocked" &&
|
|
74
|
-
motion.state !== "waiting" &&
|
|
75
|
-
blinkPhase > 0 &&
|
|
76
|
-
blinkPhase < 1
|
|
77
|
-
? 1 - Math.sin(blinkPhase * Math.PI)
|
|
78
|
-
: 1;
|
|
79
|
-
const eyeOpen = Math.max(0.055, pose.open * blink);
|
|
80
|
-
const profile = eyeProfiles[motion.form];
|
|
81
|
-
const glow = formDetails[motion.form].eyes === "ink" ? 0 : profile.signature ? 0.95 : 0.65;
|
|
82
|
-
const shape = eyeShape(motion.form);
|
|
83
|
-
for (const [name, side] of [
|
|
84
|
-
["L", -1],
|
|
85
|
-
["R", 1],
|
|
86
|
-
]) {
|
|
87
|
-
const x = side * ((1 - pauseAmount) * profile.spacing + pauseAmount * 0.125) + pose.gazeX;
|
|
88
|
-
const y = profile.y + pose.gazeY;
|
|
89
|
-
const p = project(body, x, y, yaw, pitch);
|
|
90
|
-
frame[`eye${name}`] = {
|
|
91
|
-
display: p.front ? "" : "none",
|
|
92
|
-
transform: `translate(${f3(p.x)} ${f3(p.y)}) scale(${f3(p.sx)} ${f3(p.sy)})`,
|
|
93
|
-
};
|
|
94
|
-
frame[`light${name}`] = {
|
|
95
|
-
d: shape,
|
|
96
|
-
transform: `scale(1 ${f3(eyeOpen)})`,
|
|
97
|
-
opacity: f3((1 - happiness) * (1 - pauseAmount)),
|
|
98
|
-
};
|
|
99
|
-
frame[`glint${name}`] = frame[`light${name}`];
|
|
100
|
-
frame[`halo${name}`] = {
|
|
101
|
-
rx: f3(profile.width * 2.8),
|
|
102
|
-
ry: f3(profile.height * (1.1 + 0.9 * eyeOpen)),
|
|
103
|
-
opacity: f3(glow * (1 - pauseAmount) * (1 - happiness)),
|
|
104
|
-
};
|
|
105
|
-
if (profile.signature)
|
|
106
|
-
frame[`flick${name}`] = {
|
|
107
|
-
transform: `scale(${side} ${f3(eyeOpen)})`,
|
|
108
|
-
opacity: f3((1 - happiness) * (1 - pauseAmount)),
|
|
109
|
-
};
|
|
110
|
-
frame[`happy${name}`] = {
|
|
111
|
-
opacity: f3(happiness * (1 - pauseAmount)),
|
|
112
|
-
transform: `rotate(${f3(side * pose.done * 1.7)})`,
|
|
113
|
-
};
|
|
114
|
-
frame[`pause${name}`] = { opacity: f3(pauseAmount) };
|
|
115
|
-
frame[`pauseHalo${name}`] = { opacity: f3(pauseAmount * 0.7) };
|
|
116
|
-
}
|
|
117
|
-
for (let i = 0; i < 3; i++) {
|
|
118
|
-
const pulse = motion.still ? 0.6 : 0.18 + (0.82 * (Math.sin(t * 5.6 - i * 1.25) + 1)) / 2;
|
|
119
|
-
const p = project(body, (i - 1) * 0.086, -0.266, yaw, pitch);
|
|
120
|
-
frame[`tick${i}`] = {
|
|
121
|
-
transform: `translate(${f3(p.x - 0.0235 * p.sx)} ${f3(p.y - 0.012)}) scale(${f3(p.sx)} 1)`,
|
|
122
|
-
opacity: f3(pose.working * pulse * 0.75 + pose.thinking * pulse * 0.35),
|
|
123
|
-
};
|
|
124
|
-
}
|
|
125
|
-
writeEffects(frame, motion, pose, now);
|
|
126
|
-
return frame;
|
|
127
|
-
}
|
|
128
|
-
const RIBBONS = [
|
|
129
|
-
{ tilt: -22, aspect: 0.62, radius: 1.2, span: 2.85, phase: 0.2, direction: 1 },
|
|
130
|
-
{ tilt: 48, aspect: 0.5, radius: 1.19, span: 2.5, phase: 2.1, direction: -1 },
|
|
131
|
-
{ tilt: -64, aspect: 0.72, radius: 1.24, span: 2.3, phase: 4.0, direction: 1 },
|
|
132
|
-
];
|
|
133
|
-
export const RIBBON_TILTS = RIBBONS.map((ribbon) => ribbon.tilt);
|
|
134
|
-
export const ORBIT_TILTS = [-0.36, 0.49];
|
|
135
|
-
function writeEffects(frame, motion, pose, now) {
|
|
136
|
-
const morph = pose.morph < 0.00005 ? 0 : pose.morph > 0.99995 ? 1 : pose.morph;
|
|
137
|
-
const clock = motion.still ? 0.6 : (now - motion.started) / 1000;
|
|
138
|
-
const celebrationAge = (now - motion.celebratedAt) / 1000;
|
|
139
|
-
const celebrating = !motion.still && celebrationAge > 0.14 && celebrationAge < 2.4;
|
|
140
|
-
const workAmount = pose.working * (1 - morph);
|
|
141
|
-
const thoughtAmount = pose.thinking * (1 - morph);
|
|
142
|
-
const ribbonOpacity = celebrating ? pose.done * (1 - morph) : 0;
|
|
143
|
-
const active = workAmount > 0.003 || thoughtAmount > 0.003 || ribbonOpacity > 0.003;
|
|
144
|
-
frame.effectsBack = { display: active ? "" : "none" };
|
|
145
|
-
frame.effectsFront = {
|
|
146
|
-
display: active ? "" : "none",
|
|
147
|
-
transform: `translate(0 ${f3(pose.lift * 0.45)})`,
|
|
148
|
-
};
|
|
149
|
-
ORBIT_TILTS.forEach((tilt, index) => {
|
|
150
|
-
for (let i = 0; i < ORBIT_DOTS; i++) {
|
|
151
|
-
const tail = i % 10;
|
|
152
|
-
const offset = i < 10 ? 0 : Math.PI;
|
|
153
|
-
const a = clock * (index === 0 ? 2.8 : -2.2) + index * 2.2 + offset - tail * 0.065;
|
|
154
|
-
const x = 1.2 * Math.cos(a);
|
|
155
|
-
const y = 0.49 * Math.sin(a);
|
|
156
|
-
const front = Math.sin(a) > 0;
|
|
157
|
-
const dot = {
|
|
158
|
-
cx: f3(x * Math.cos(tilt) - y * Math.sin(tilt)),
|
|
159
|
-
cy: f3(x * Math.sin(tilt) + y * Math.cos(tilt) - 0.04),
|
|
160
|
-
opacity: f3(workAmount * (tail === 0 ? 0.94 : 0.47 * (1 - tail / 10))),
|
|
161
|
-
};
|
|
162
|
-
frame[`orbit${index}Back${i}`] = { ...dot, display: front ? "none" : "" };
|
|
163
|
-
frame[`orbit${index}Front${i}`] = { ...dot, display: front ? "" : "none" };
|
|
164
|
-
}
|
|
165
|
-
});
|
|
166
|
-
for (let i = 0; i < 3; i++) {
|
|
167
|
-
const pulse = motion.still ? 0.72 : 0.23 + (0.77 * (Math.sin(clock * 2.4 - i * 0.9) + 1)) / 2;
|
|
168
|
-
frame[`thought${i}`] = {
|
|
169
|
-
transform: `translate(${f3(0.68 + i * 0.23)} ${f3(0.79 + i * 0.13 + (motion.still ? 0 : 0.025 * Math.sin(clock * 2.4 - i * 0.9)))})`,
|
|
170
|
-
opacity: f3(thoughtAmount * pulse),
|
|
171
|
-
};
|
|
172
|
-
}
|
|
173
|
-
RIBBONS.forEach((ribbon, index) => {
|
|
174
|
-
const name = `ribbon${index}`;
|
|
175
|
-
if (ribbonOpacity <= 0.003) {
|
|
176
|
-
frame[`${name}Plane`] = { opacity: "0", display: "none" };
|
|
177
|
-
return;
|
|
178
|
-
}
|
|
179
|
-
const age = celebrationAge - 0.14 - index * 0.06;
|
|
180
|
-
const reveal = easeOut(age / 0.46);
|
|
181
|
-
const dissolve = easeInOut((age - 1.1) / 0.95);
|
|
182
|
-
const fade = easeOut(age / 0.2) * (1 - easeOut((age - 1.76) / 0.44)) * ribbonOpacity;
|
|
183
|
-
const a0 = dissolve * ribbon.span;
|
|
184
|
-
const a1 = Math.max(a0, reveal * ribbon.span);
|
|
185
|
-
const points = [];
|
|
186
|
-
for (let i = 0; i <= 24; i++) {
|
|
187
|
-
const a = a0 + ((a1 - a0) * i) / 24;
|
|
188
|
-
points.push(`${i ? "L" : "M"}${f3(Math.cos(a) * ribbon.radius)} ${f3(Math.sin(a) * ribbon.radius * ribbon.aspect)}`);
|
|
189
|
-
}
|
|
190
|
-
frame[`${name}Plane`] = { opacity: f3(fade * 0.88), display: "" };
|
|
191
|
-
frame[`${name}Sweep`] = {
|
|
192
|
-
transform: `rotate(${f3(((ribbon.phase + ribbon.direction * TAU * easeInOut(Math.min(1, Math.max(0, age / 2.12)))) * 180) / Math.PI)})`,
|
|
193
|
-
};
|
|
194
|
-
frame[`${name}Arc`] = { d: a1 > a0 + 0.01 ? points.join("") : "M0 0" };
|
|
195
|
-
frame[`${name}Head`] = {
|
|
196
|
-
cx: f3(Math.cos(a1) * ribbon.radius),
|
|
197
|
-
cy: f3(Math.sin(a1) * ribbon.radius * ribbon.aspect),
|
|
198
|
-
};
|
|
199
|
-
for (let i = 0; i < RIBBON_BEADS; i++) {
|
|
200
|
-
const u = i / 7;
|
|
201
|
-
const angle = a0 - u * (0.95 + 0.48 * dissolve);
|
|
202
|
-
const radial = ribbon.radius + ((i % 3) - 1) * (0.014 + 0.034 * u) + dissolve * u * 0.06;
|
|
203
|
-
frame[`${name}Bead${i}`] = {
|
|
204
|
-
cx: f3(Math.cos(angle) * radial),
|
|
205
|
-
cy: f3(Math.sin(angle) * radial * ribbon.aspect),
|
|
206
|
-
r: f3(0.006 + 0.012 * (1 - u)),
|
|
207
|
-
opacity: f3(dissolve > 0.01 ? 0.78 : 0),
|
|
208
|
-
};
|
|
209
|
-
}
|
|
210
|
-
});
|
|
211
|
-
}
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import type { FormaForm } from "./model.js";
|
|
2
|
-
export declare const TAU: number;
|
|
3
|
-
export declare const clamp: (value: number, low: number, high: number) => number;
|
|
4
|
-
export declare const mix: (a: number, b: number, t: number) => number;
|
|
5
|
-
export declare const smooth: (t: number) => number;
|
|
6
|
-
export declare const f3: (value: number) => string;
|
|
7
|
-
export type Point = readonly [number, number];
|
|
8
|
-
export interface Body {
|
|
9
|
-
height: number;
|
|
10
|
-
width: number;
|
|
11
|
-
hw: (y: number) => number;
|
|
12
|
-
outline: readonly Point[];
|
|
13
|
-
core: {
|
|
14
|
-
cy: number;
|
|
15
|
-
r: number;
|
|
16
|
-
};
|
|
17
|
-
}
|
|
18
|
-
export declare const bodies: Record<FormaForm, Body>;
|
|
19
|
-
export interface EyeProfile {
|
|
20
|
-
power: number;
|
|
21
|
-
width: number;
|
|
22
|
-
height: number;
|
|
23
|
-
spacing: number;
|
|
24
|
-
y: number;
|
|
25
|
-
signature?: boolean;
|
|
26
|
-
}
|
|
27
|
-
export declare const eyeProfiles: Record<FormaForm, EyeProfile>;
|
|
28
|
-
export declare function superellipse(hw: number, hh: number, power: number, n: number): Point[];
|
|
29
|
-
export declare const visorPoints: readonly Point[];
|
|
30
|
-
export declare function closedPath(pts: readonly Point[]): string;
|
|
31
|
-
export interface Projected {
|
|
32
|
-
x: number;
|
|
33
|
-
y: number;
|
|
34
|
-
sx: number;
|
|
35
|
-
sy: number;
|
|
36
|
-
front: boolean;
|
|
37
|
-
}
|
|
38
|
-
export declare function project(body: Body, xs: number, ys: number, yaw: number, pitch: number): Projected;
|
|
39
|
-
export declare function shellPath(body: Body, morph: number): string;
|
|
40
|
-
export declare function stripePath(body: Body, yaw: number, a: number, b: number): string;
|
|
41
|
-
//# sourceMappingURL=geometry.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"geometry.d.ts","sourceRoot":"","sources":["../../../src/internal/forma/geometry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEzC,eAAO,MAAM,GAAG,QAAc,CAAC;AAE/B,eAAO,MAAM,KAAK,GAAI,OAAO,MAAM,EAAE,KAAK,MAAM,EAAE,MAAM,MAAM,KAAG,MAC3B,CAAC;AACvC,eAAO,MAAM,GAAG,GAAI,GAAG,MAAM,EAAE,GAAG,MAAM,EAAE,GAAG,MAAM,KAAG,MAAyB,CAAC;AAChF,eAAO,MAAM,MAAM,GAAI,GAAG,MAAM,KAAG,MAGlC,CAAC;AAGF,eAAO,MAAM,EAAE,GAAI,OAAO,MAAM,KAAG,MAAsD,CAAC;AAE1F,MAAM,MAAM,KAAK,GAAG,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAE9C,MAAM,WAAW,IAAI;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,EAAE,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IAC1B,OAAO,EAAE,SAAS,KAAK,EAAE,CAAC;IAC1B,IAAI,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CACjC;AAuGD,eAAO,MAAM,MAAM,EAAE,MAAM,CAAC,SAAS,EAAE,IAAI,CAgD1C,CAAC;AAIF,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,CAAC,EAAE,MAAM,CAAC;IACV,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,eAAO,MAAM,WAAW,EAAE,MAAM,CAAC,SAAS,EAAE,UAAU,CASrD,CAAC;AAEF,wBAAgB,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,KAAK,EAAE,CAOtF;AAED,eAAO,MAAM,WAAW,EAAE,SAAS,KAAK,EAKD,CAAC;AAExC,wBAAgB,UAAU,CAAC,GAAG,EAAE,SAAS,KAAK,EAAE,GAAG,MAAM,CAYxD;AAED,MAAM,WAAW,SAAS;IACxB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,wBAAgB,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,CAkBjG;AAgCD,wBAAgB,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAU3D;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAWhF"}
|
|
@@ -1,235 +0,0 @@
|
|
|
1
|
-
export const TAU = Math.PI * 2;
|
|
2
|
-
const CAMERA_DISTANCE = 5.2;
|
|
3
|
-
export const clamp = (value, low, high) => Math.max(low, Math.min(high, value));
|
|
4
|
-
export const mix = (a, b, t) => a + (b - a) * t;
|
|
5
|
-
export const smooth = (t) => {
|
|
6
|
-
const u = clamp(t, 0, 1);
|
|
7
|
-
return u * u * (3 - 2 * u);
|
|
8
|
-
};
|
|
9
|
-
const signedPow = (value, power) => Math.sign(value) * Math.pow(Math.abs(value), power);
|
|
10
|
-
export const f3 = (value) => (Math.round(value * 1000) / 1000).toString();
|
|
11
|
-
function lut(pts) {
|
|
12
|
-
const table = pts
|
|
13
|
-
.filter((p) => p[0] >= -0.001)
|
|
14
|
-
.map((p) => [Math.abs(p[0]), p[1]])
|
|
15
|
-
.sort((a, b) => a[1] - b[1]);
|
|
16
|
-
const height = Math.max(...pts.map((p) => Math.abs(p[1])));
|
|
17
|
-
const width = Math.max(...pts.map((p) => Math.abs(p[0])));
|
|
18
|
-
const first = table[0];
|
|
19
|
-
const last = table[table.length - 1];
|
|
20
|
-
const hw = (y) => {
|
|
21
|
-
if (!first || !last || y <= first[1] || y >= last[1])
|
|
22
|
-
return 0.02;
|
|
23
|
-
let best = 0.02;
|
|
24
|
-
for (let i = 1; i < table.length; i++) {
|
|
25
|
-
const b = table[i];
|
|
26
|
-
const a = table[i - 1];
|
|
27
|
-
if (b && a && b[1] >= y) {
|
|
28
|
-
const u = (y - a[1]) / Math.max(1e-6, b[1] - a[1]);
|
|
29
|
-
best = Math.max(best, mix(a[0], b[0], u));
|
|
30
|
-
break;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
return best;
|
|
34
|
-
};
|
|
35
|
-
return { height, width, hw, outline: pts };
|
|
36
|
-
}
|
|
37
|
-
function superBody(spec) {
|
|
38
|
-
const { power, width, height, taper = 0 } = spec;
|
|
39
|
-
const radial = (y) => Math.sqrt(Math.max(0.03, 1 - (taper * y) / height));
|
|
40
|
-
const hw = (y) => {
|
|
41
|
-
const v = clamp(Math.abs(y / height), 0, 1);
|
|
42
|
-
return width * radial(y) * Math.pow(Math.max(0, 1 - Math.pow(v, power)), 1 / power);
|
|
43
|
-
};
|
|
44
|
-
const outline = [];
|
|
45
|
-
for (let i = 0; i < 96; i++) {
|
|
46
|
-
const t = (i / 96) * TAU;
|
|
47
|
-
const y = height * signedPow(Math.sin(t), 2 / power);
|
|
48
|
-
outline.push([width * radial(y) * signedPow(Math.cos(t), 2 / power), y]);
|
|
49
|
-
}
|
|
50
|
-
return { height, width, hw, outline };
|
|
51
|
-
}
|
|
52
|
-
function polyBody(vertices, rounds, cut) {
|
|
53
|
-
let pts = [...vertices];
|
|
54
|
-
for (let r = 0; r < rounds; r++) {
|
|
55
|
-
const next = [];
|
|
56
|
-
for (let i = 0; i < pts.length; i++) {
|
|
57
|
-
const a = pts[i];
|
|
58
|
-
const b = pts[(i + 1) % pts.length];
|
|
59
|
-
next.push([mix(a[0], b[0], cut), mix(a[1], b[1], cut)], [mix(a[0], b[0], 1 - cut), mix(a[1], b[1], 1 - cut)]);
|
|
60
|
-
}
|
|
61
|
-
pts = next;
|
|
62
|
-
}
|
|
63
|
-
return lut(pts);
|
|
64
|
-
}
|
|
65
|
-
function cloudBody(circles, bottom = -Infinity) {
|
|
66
|
-
const pts = [];
|
|
67
|
-
for (let i = 0; i < 144; i++) {
|
|
68
|
-
const a = (i / 144) * TAU;
|
|
69
|
-
const dx = Math.cos(a);
|
|
70
|
-
const dy = Math.sin(a);
|
|
71
|
-
let r = 0;
|
|
72
|
-
for (const [cx, cy, cr] of circles) {
|
|
73
|
-
const b = -2 * (dx * cx + dy * cy);
|
|
74
|
-
const c = cx * cx + cy * cy - cr * cr;
|
|
75
|
-
const disc = b * b - 4 * c;
|
|
76
|
-
if (disc >= 0)
|
|
77
|
-
r = Math.max(r, (-b + Math.sqrt(disc)) / 2);
|
|
78
|
-
}
|
|
79
|
-
if (dy < 0 && bottom > -Infinity)
|
|
80
|
-
r = Math.min(r, bottom / dy);
|
|
81
|
-
pts.push([dx * r, dy * r]);
|
|
82
|
-
}
|
|
83
|
-
return lut(pts);
|
|
84
|
-
}
|
|
85
|
-
function stadiumBody(halfLength, r) {
|
|
86
|
-
const pts = [];
|
|
87
|
-
for (let i = 0; i <= 40; i++) {
|
|
88
|
-
const a = -Math.PI / 2 + (i / 40) * Math.PI;
|
|
89
|
-
pts.push([halfLength + r * Math.cos(a), r * Math.sin(a)]);
|
|
90
|
-
}
|
|
91
|
-
for (let i = 0; i <= 40; i++) {
|
|
92
|
-
const a = Math.PI / 2 + (i / 40) * Math.PI;
|
|
93
|
-
pts.push([-halfLength + r * Math.cos(a), r * Math.sin(a)]);
|
|
94
|
-
}
|
|
95
|
-
return lut(pts);
|
|
96
|
-
}
|
|
97
|
-
const withCore = (body, core) => ({ ...body, core });
|
|
98
|
-
export const bodies = {
|
|
99
|
-
nadia: withCore(superBody({ power: 2.3, width: 1, height: 0.965 }), { cy: 0, r: 1 }),
|
|
100
|
-
goccia: withCore(superBody({ power: 2, width: 1, height: 1.16, taper: 0.94 }), {
|
|
101
|
-
cy: -0.18,
|
|
102
|
-
r: 0.92,
|
|
103
|
-
}),
|
|
104
|
-
nuvola: withCore(cloudBody([
|
|
105
|
-
[0, -0.08, 0.8],
|
|
106
|
-
[-0.46, 0.34, 0.5],
|
|
107
|
-
[0.4, 0.42, 0.56],
|
|
108
|
-
[-0.72, -0.1, 0.42],
|
|
109
|
-
[0.74, -0.14, 0.4],
|
|
110
|
-
], -0.86), { cy: -0.06, r: 0.84 }),
|
|
111
|
-
triangolo: withCore(polyBody([
|
|
112
|
-
[0, 1.42],
|
|
113
|
-
[1.28, -0.86],
|
|
114
|
-
[-1.28, -0.86],
|
|
115
|
-
], 4, 0.22), { cy: -0.26, r: 0.8 }),
|
|
116
|
-
esagono: withCore(polyBody([0, 1, 2, 3, 4, 5].map((k) => {
|
|
117
|
-
const a = Math.PI / 2 + (k * Math.PI) / 3;
|
|
118
|
-
return [Math.cos(a) * 1.02, Math.sin(a) * 1.12];
|
|
119
|
-
}), 3, 0.16), { cy: 0, r: 0.84 }),
|
|
120
|
-
quadrato: withCore(superBody({ power: 3.6, width: 0.92, height: 0.97 }), { cy: 0, r: 0.9 }),
|
|
121
|
-
pillola: withCore(stadiumBody(0.4, 0.68), { cy: 0, r: 0.68 }),
|
|
122
|
-
uovo: withCore(superBody({ power: 2.2, width: 0.84, height: 1.06, taper: 0.5 }), {
|
|
123
|
-
cy: -0.16,
|
|
124
|
-
r: 0.84,
|
|
125
|
-
}),
|
|
126
|
-
};
|
|
127
|
-
const visorMask = { width: 0.86, height: 0.505, y: 0.055, power: 4.6 };
|
|
128
|
-
export const eyeProfiles = {
|
|
129
|
-
nadia: { power: 2, width: 0.065, height: 0.151, spacing: 0.247, y: 0.069, signature: true },
|
|
130
|
-
goccia: { power: 4, width: 0.108, height: 0.054, spacing: 0.23, y: 0.015 },
|
|
131
|
-
nuvola: { power: 2, width: 0.108, height: 0.108, spacing: 0.23, y: 0.068 },
|
|
132
|
-
triangolo: { power: 3.8, width: 0.069, height: 0.12, spacing: 0.247, y: 0.054 },
|
|
133
|
-
esagono: { power: 2.6, width: 0.077, height: 0.116, spacing: 0.22, y: 0.068 },
|
|
134
|
-
quadrato: { power: 1.6, width: 0.095, height: 0.135, spacing: 0.245, y: 0.08 },
|
|
135
|
-
pillola: { power: 2, width: 0.108, height: 0.108, spacing: 0.23, y: 0.068 },
|
|
136
|
-
uovo: { power: 3.8, width: 0.069, height: 0.12, spacing: 0.247, y: 0.054 },
|
|
137
|
-
};
|
|
138
|
-
export function superellipse(hw, hh, power, n) {
|
|
139
|
-
const pts = [];
|
|
140
|
-
for (let i = 0; i < n; i++) {
|
|
141
|
-
const t = (i / n) * TAU;
|
|
142
|
-
pts.push([hw * signedPow(Math.cos(t), 2 / power), hh * signedPow(Math.sin(t), 2 / power)]);
|
|
143
|
-
}
|
|
144
|
-
return pts;
|
|
145
|
-
}
|
|
146
|
-
export const visorPoints = superellipse(visorMask.width, visorMask.height, visorMask.power, 48).map(([x, y]) => [x, y + visorMask.y]);
|
|
147
|
-
export function closedPath(pts) {
|
|
148
|
-
const n = pts.length;
|
|
149
|
-
let d = "";
|
|
150
|
-
for (let i = 0; i < n; i++) {
|
|
151
|
-
const p0 = pts[(i + n - 1) % n];
|
|
152
|
-
const p1 = pts[i];
|
|
153
|
-
const p2 = pts[(i + 1) % n];
|
|
154
|
-
const p3 = pts[(i + 2) % n];
|
|
155
|
-
if (i === 0)
|
|
156
|
-
d += `M${f3(p1[0])} ${f3(p1[1])}`;
|
|
157
|
-
d += `C${f3(p1[0] + (p2[0] - p0[0]) / 6)} ${f3(p1[1] + (p2[1] - p0[1]) / 6)} ${f3(p2[0] - (p3[0] - p1[0]) / 6)} ${f3(p2[1] - (p3[1] - p1[1]) / 6)} ${f3(p2[0])} ${f3(p2[1])}`;
|
|
158
|
-
}
|
|
159
|
-
return `${d}Z`;
|
|
160
|
-
}
|
|
161
|
-
export function project(body, xs, ys, yaw, pitch) {
|
|
162
|
-
const { core } = body;
|
|
163
|
-
let lon = Math.asin(clamp(xs, -1, 1)) + yaw;
|
|
164
|
-
let lat = Math.asin(clamp(ys, -1, 1)) - pitch;
|
|
165
|
-
lon = Math.atan2(Math.sin(lon), Math.cos(lon)); // a full turn brings the face home
|
|
166
|
-
const front = Math.cos(lon) > 0 && Math.cos(lat) > 0;
|
|
167
|
-
lon = clamp(lon, -Math.PI / 2, Math.PI / 2);
|
|
168
|
-
lat = clamp(lat, -Math.PI / 2, Math.PI / 2);
|
|
169
|
-
const depth = Math.cos(lon) * Math.cos(lat) * core.r;
|
|
170
|
-
const perspective = CAMERA_DISTANCE / (CAMERA_DISTANCE - depth);
|
|
171
|
-
const foreshorten = Math.sqrt(perspective);
|
|
172
|
-
return {
|
|
173
|
-
x: Math.sin(lon) * Math.cos(lat) * core.r * perspective,
|
|
174
|
-
y: core.cy + Math.sin(lat) * core.r * 0.965 * perspective,
|
|
175
|
-
sx: Math.max(0.02, Math.cos(lon)) * core.r * foreshorten,
|
|
176
|
-
sy: Math.max(0.02, Math.cos(lat)) * core.r * foreshorten,
|
|
177
|
-
front,
|
|
178
|
-
};
|
|
179
|
-
}
|
|
180
|
-
const RING_OUTER = 1;
|
|
181
|
-
const RING_INNER = 0.64;
|
|
182
|
-
const RING_SAMPLES = 96;
|
|
183
|
-
const radialProfiles = new WeakMap();
|
|
184
|
-
function radialProfile(body) {
|
|
185
|
-
let profile = radialProfiles.get(body);
|
|
186
|
-
if (profile)
|
|
187
|
-
return profile;
|
|
188
|
-
const polar = body.outline
|
|
189
|
-
.map(([x, y]) => ({ angle: Math.atan2(y, x), radius: Math.hypot(x, y) }))
|
|
190
|
-
.sort((a, b) => a.angle - b.angle);
|
|
191
|
-
profile = [];
|
|
192
|
-
for (let i = 0; i < RING_SAMPLES; i++) {
|
|
193
|
-
let angle = (i / RING_SAMPLES) * TAU;
|
|
194
|
-
if (angle > Math.PI)
|
|
195
|
-
angle -= TAU;
|
|
196
|
-
let next = polar.findIndex((p) => p.angle >= angle);
|
|
197
|
-
if (next === -1)
|
|
198
|
-
next = 0;
|
|
199
|
-
const b = polar[next];
|
|
200
|
-
const a = polar[(next + polar.length - 1) % polar.length];
|
|
201
|
-
let span = b.angle - a.angle;
|
|
202
|
-
let offset = angle - a.angle;
|
|
203
|
-
if (span <= 0)
|
|
204
|
-
span += TAU;
|
|
205
|
-
if (offset < 0)
|
|
206
|
-
offset += TAU;
|
|
207
|
-
profile.push(mix(a.radius, b.radius, span > 0 ? offset / span : 0));
|
|
208
|
-
}
|
|
209
|
-
radialProfiles.set(body, profile);
|
|
210
|
-
return profile;
|
|
211
|
-
}
|
|
212
|
-
export function shellPath(body, morph) {
|
|
213
|
-
if (morph <= 0)
|
|
214
|
-
return closedPath(body.outline);
|
|
215
|
-
const profile = radialProfile(body);
|
|
216
|
-
const outer = profile.map((radius, i) => {
|
|
217
|
-
const angle = (i / RING_SAMPLES) * TAU;
|
|
218
|
-
const r = mix(radius, RING_OUTER, morph);
|
|
219
|
-
return [Math.cos(angle) * r, Math.sin(angle) * r];
|
|
220
|
-
});
|
|
221
|
-
const inner = outer.map(([x, y]) => [x * RING_INNER * morph, y * RING_INNER * morph]);
|
|
222
|
-
return closedPath(outer) + closedPath(inner);
|
|
223
|
-
}
|
|
224
|
-
export function stripePath(body, yaw, a, b) {
|
|
225
|
-
let d = "";
|
|
226
|
-
const base = Math.atan2(Math.sin(a + yaw), Math.cos(a + yaw));
|
|
227
|
-
const length = b - a;
|
|
228
|
-
for (const k of [-1, 0, 1]) {
|
|
229
|
-
const low = Math.max(base + k * TAU, -Math.PI / 2);
|
|
230
|
-
const high = Math.min(base + k * TAU + length, Math.PI / 2);
|
|
231
|
-
if (high > low)
|
|
232
|
-
d += `M${f3(Math.sin(low) * body.width)} -1.3H${f3(Math.sin(high) * body.width)}V1.3H${f3(Math.sin(low) * body.width)}Z`;
|
|
233
|
-
}
|
|
234
|
-
return d || "M0 0";
|
|
235
|
-
}
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
export declare const ITALY_PATH = "M188.4,46.1L207.3,52.6L210.9,43.9L241.6,36L248.6,51.8L293.1,63.5L289.7,85.7L297.1,104.7L272.4,98.2L247.1,114L248.8,135.9L245,148.4L255.2,170.5L284.4,192.2L300,227.5L334.6,261.4L359,261.1L366.6,270.4L357.8,278.7L385.7,293.6L408.5,306.1L435.2,327.5L438.4,335.1L432.6,349.6L415.4,330.7L388.3,324L375.2,350.3L397.7,365.2L394,386.2L381,388.5L364.4,422.6L351.5,425.6L351.6,413.5L357.9,392.2L364.7,383.7L352.5,360.4L343,340L330.1,334.9L321,317.3L301,309.9L287.5,293.3L264.5,290.6L240.2,271.9L211.7,244.6L190.6,220.2L180.9,177.9L165.4,172.9L140.1,158.6L125.8,164.4L107.8,184.5L94.9,187.7L98.4,168.9L81.6,163.4L73.6,129.6L84.3,116.1L75.2,99.5L76.5,86.9L89.9,96.4L104.9,94.3L122.3,79.1L127.7,86.2L142.5,84.8L149.2,66.7L172.3,72.3L186,64.7ZM322.8,416.3L346.4,412.9L335.2,443.9L339.8,456L333.3,476L309.5,461.4L293.7,457.2L250.3,437.3L254.6,417L291,420.6ZM134.5,305.2L150.1,292.4L168.7,321.6L164.4,375.2L150.2,372.6L137.5,386L125.8,375.4L124.5,326.6L117.4,303.1Z";
|
|
2
|
-
export declare const ITALY_BOX = 512;
|
|
3
|
-
export declare const HALLMARK_SIZE = 0.39;
|
|
4
|
-
export declare const HALLMARK_LONGITUDE = 1.24;
|
|
5
|
-
//# sourceMappingURL=hallmark.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"hallmark.d.ts","sourceRoot":"","sources":["../../../src/internal/forma/hallmark.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,UAAU,07BACk6B,CAAC;AAE17B,eAAO,MAAM,SAAS,MAAM,CAAC;AAC7B,eAAO,MAAM,aAAa,OAAO,CAAC;AAClC,eAAO,MAAM,kBAAkB,OAAO,CAAC"}
|