CurlFlow
threecn/curl-flowFreeComponent
Particles advected through a divergence-free curl-noise field into silky filaments, tinted --accent to --primary by height.
Install it
npx shadcn@latest add https://threecn.dev/r/curl-flow.jsonSource
1"use client"23import * as React from "react"4import { useFrame } from "@react-three/fiber"5import * as THREE from "three"67import {8 SceneContainer,9 type SceneContainerProps,10} from "@/components/threecn/scene-container"11import {12 useShadcnTheme,13 type ThemeMode,14} from "@/components/hooks/use-shadcn-theme"1516const BOUND = 3.41718/** A smooth scalar potential; three seeded copies form a vector potential. */19function potential(x: number, y: number, z: number, t: number, seed: number) {20 return (21 Math.sin(x * 0.7 + seed + t * 0.3) +22 Math.cos(y * 0.9 - seed * 1.3 + t * 0.2) +23 Math.sin(z * 0.8 + seed * 0.7 - t * 0.25)24 )25}2627function seedSphere(count: number, radius: number) {28 const arr = new Float32Array(count * 3)29 for (let i = 0; i < count; i++) {30 const r = Math.cbrt(Math.random()) * radius31 const theta = Math.random() * Math.PI * 232 const phi = Math.acos(2 * Math.random() - 1)33 arr[i * 3] = r * Math.sin(phi) * Math.cos(theta)34 arr[i * 3 + 1] = r * Math.sin(phi) * Math.sin(theta)35 arr[i * 3 + 2] = r * Math.cos(phi)36 }37 return arr38}3940function Filaments({41 count,42 speed,43 size,44 theme,45}: {46 count: number47 speed: number48 size: number49 theme: ThemeMode50}) {51 const { primaryColor, accentColor, isDark } = useShadcnTheme(theme)52 const geoRef = React.useRef<THREE.BufferGeometry>(null)5354 const positions = React.useMemo(55 () => seedSphere(count, BOUND * 0.9),56 [count]57 )58 const colors = React.useMemo(() => new Float32Array(count * 3), [count])5960 useFrame((state, delta) => {61 const geo = geoRef.current62 if (!geo) return63 const posAttr = geo.getAttribute("position") as THREE.BufferAttribute64 const colAttr = geo.getAttribute("color") as THREE.BufferAttribute65 const pos = posAttr.array as Float32Array66 const cols = colAttr.array as Float32Array67 const t = state.clock.getElapsedTime()68 const dt = Math.min(delta, 0.05) * speed69 const e = 0.170 const inv2e = 1 / (2 * e)71 const col = new THREE.Color()7273 for (let i = 0; i < count; i++) {74 const o = i * 375 const x = pos[o]76 const y = pos[o + 1]77 const z = pos[o + 2]7879 // curl of the vector potential (pa, pb, pc) → divergence-free flow.80 const dPc_dy =81 (potential(x, y + e, z, t, 9.7) - potential(x, y - e, z, t, 9.7)) * inv2e82 const dPb_dz =83 (potential(x, y, z + e, t, 5.2) - potential(x, y, z - e, t, 5.2)) * inv2e84 const dPa_dz =85// … truncated
What it pulls in
npm packages
Files it writes
More from threecn
All 28 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| AuroraRibbonsaurora-ribbons | threecn | Components | Free | 3 deps · 3 files | |
| Boidsboids | threecn | Components | Free | 3 deps · 3 files | |
| Clothcloth | threecn | Components | Free | 3 deps · 3 files | |
| Crystalcrystal | threecn | Components | Free | 3 deps · 3 files | |
| CubeWavecube-wave | threecn | Components | Free | 3 deps · 3 files | |
| DnaHelixdna-helix | threecn | Components | Free | 3 deps · 3 files | |
| FloatingCard3Dfloating-card-3d | threecn | Components | Free | 3 deps · 3 files | |
| Globeglobe | threecn | Components | Free | 3 deps · 3 files |
