Boids
threecn/boidsFreeComponent
A living flock steering by separation, alignment and cohesion; each agent tints --accent when slow to --primary at full speed.
Install it
npx shadcn@latest add https://threecn.dev/r/boids.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 = 4.217const PERCEPTION = 1.418const SEPARATION = 0.719const MAX_SPEED = 2.22021type Swarm = { pos: Float32Array; vel: Float32Array }2223function seedSwarm(count: number): Swarm {24 const pos = new Float32Array(count * 3)25 const vel = new Float32Array(count * 3)26 for (let i = 0; i < count; i++) {27 const r = Math.cbrt(Math.random()) * BOUND * 0.728 const theta = Math.random() * Math.PI * 229 const phi = Math.acos(2 * Math.random() - 1)30 pos[i * 3] = r * Math.sin(phi) * Math.cos(theta)31 pos[i * 3 + 1] = r * Math.sin(phi) * Math.sin(theta)32 pos[i * 3 + 2] = r * Math.cos(phi)33 vel[i * 3] = (Math.random() - 0.5) * 234 vel[i * 3 + 1] = (Math.random() - 0.5) * 235 vel[i * 3 + 2] = (Math.random() - 0.5) * 236 }37 return { pos, vel }38}3940function Flock({41 count,42 speed,43 theme,44}: {45 count: number46 speed: number47 theme: ThemeMode48}) {49 const { primaryColor, accentColor } = useShadcnTheme(theme)50 const meshRef = React.useRef<THREE.InstancedMesh>(null)51 const swarmRef = React.useRef<Swarm | null>(null)5253 // The swarm is mutated every frame, so it lives in a ref (never read during54 // render). Seed it whenever the agent count changes.55 React.useLayoutEffect(() => {56 swarmRef.current = seedSwarm(count)57 }, [count])5859 const dummy = React.useMemo(() => new THREE.Object3D(), [])60 const tmpColor = React.useMemo(() => new THREE.Color(), [])61 const up = React.useMemo(() => new THREE.Vector3(0, 1, 0), [])62 const dir = React.useMemo(() => new THREE.Vector3(), [])6364 useFrame((_, delta) => {65 const mesh = meshRef.current66 const swarm = swarmRef.current67 if (!mesh || !swarm) return68 const dt = Math.min(delta, 0.05) * speed69 const { pos, vel } = swarm7071 for (let i = 0; i < count; i++) {72 const io = i * 373 const px = pos[io]74 const py = pos[io + 1]75 const pz = pos[io + 2]7677 let ax = 078 let ay = 079 let az = 0 // alignment80 let cx = 081 let cy = 082 let cz = 0 // cohesion83 let sx = 084 let sy = 085 let sz = 0 // separation86 let n = 08788 for (let j = 0; j < count; j++) {89 if (j === i) continue90 const jo = j * 391// … 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 | |
| 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 | |
| CurlFlowcurl-flow | 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 |
