wobbleRandomness

interpolates between noise and sine wave
This commit is contained in:
2026-01-25 10:02:51 +00:00
parent 853e024bf7
commit 13ef090e7b
5 changed files with 27 additions and 6 deletions

View File

@@ -70,6 +70,15 @@ function Index() {
onValueChange={([v]) => setState({ ...state, wobbleSpeed: v })}
/>
</div>
<div className="flex flex-col gap-2">
<span className="text-sm font-medium">Wobble Randomness</span>
<Slider
value={[state.wobbleRandomness]}
min={0}
max={100}
onValueChange={([v]) => setState({ ...state, wobbleRandomness: v })}
/>
</div>
</div>
);

View File

@@ -46,9 +46,10 @@ export default function MorphableShape({
const flatPoints = useMemo(() => {
const wobbleAmount = state.wobble * 0.3; // scale wobble to reasonable range
const wobbled = applyWobble(morphedPoints, time, wobbleAmount);
const randomness = state.wobbleRandomness / 100;
const wobbled = applyWobble(morphedPoints, time, wobbleAmount, randomness);
return wobbled.flatMap((p) => [p.x, p.y]);
}, [morphedPoints, time, state.wobble]);
}, [morphedPoints, time, state.wobble, state.wobbleRandomness]);
return (
<Group x={state.x} y={state.y} draggable onDragMove={handleDrag}>

View File

@@ -1,5 +1,5 @@
import { useState, useEffect, useRef } from "react";
import type { ShapeState } from "@/types/shape";
import { useEffect, useRef, useState } from "react";
const DEFAULT_STATE: ShapeState = {
x: 0,
@@ -9,6 +9,7 @@ const DEFAULT_STATE: ShapeState = {
size: 50, // medium
wobble: 20, // subtle
wobbleSpeed: 50, // medium
wobbleRandomness: 50, // medium
grain: 0, // none
color: "#FF0000", // red (C)
octave: 4, // middle octave
@@ -26,6 +27,7 @@ export function useShapeState(centerX: number, centerY: number) {
x: centerX,
y: centerY,
});
void initialStateRef;
// update center position when canvas resizes
useEffect(() => {

View File

@@ -2,14 +2,22 @@ import { noise2D } from "@/lib/noise";
import type { Point } from "./points";
// apply noise-based displacement to points. this gives a wobble effect. points are displaced radially
export function applyWobble(points: Point[], time: number, amount: number, noiseScale = 0.5): Point[] {
export function applyWobble(
points: Point[],
time: number,
amount: number,
randomness: number,
noiseScale = 0.5,
): Point[] {
if (amount === 0) return points;
return points.map((point, i) => {
// use point index and time for noise input
const noiseX = i * noiseScale;
const noiseY = time;
const displacement = noise2D(noiseX, noiseY) * amount;
const noiseValue = noise2D(noiseX, noiseY);
const sineValue = Math.sin(time * 2 + i * noiseScale);
const blended = sineValue * (1 - randomness) + noiseValue * randomness;
const displacement = blended * amount;
const angle = Math.atan2(point.y, point.x);

View File

@@ -8,6 +8,7 @@ export interface ShapeState {
size: number; // 0-100, controls volume
wobble: number; // 0-100, visual wobble amount
wobbleSpeed: number; // 0-100, wobble animation speed
wobbleRandomness: number; // 0-100, noise vs sine blend
grain: number; // 0-100, noise mix
color: string; // hex color from clavier keyboard
octave: number; // 1-8, frequency multiplier