VoronoiShatter
threecn/voronoi-shatterFreeComponent
A sphere fractured into Voronoi shards that drift apart and snap back together, each facet shading --accent to --primary by height.
Install it
npx shadcn@latest add https://threecn.dev/r/voronoi-shatter.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 RADIUS = 1.617const THICKNESS = 0.341819type Vec = [number, number, number]2021type Shard = {22 geometry: THREE.BufferGeometry23 centroid: THREE.Vector324 axis: THREE.Vector325 spin: number26}2728/** Evenly spread N points on a sphere (Fibonacci lattice) as fracture sites. */29function fibonacciSites(n: number) {30 const sites: THREE.Vector3[] = []31 const golden = Math.PI * (3 - Math.sqrt(5))32 for (let i = 0; i < n; i++) {33 const y = n === 1 ? 0 : 1 - (i / (n - 1)) * 234 const r = Math.sqrt(Math.max(0, 1 - y * y))35 const t = golden * i36 sites.push(new THREE.Vector3(Math.cos(t) * r, y, Math.sin(t) * r))37 }38 return sites39}4041function pushTri(out: number[], a: Vec, b: Vec, c: Vec) {42 out.push(a[0], a[1], a[2], b[0], b[1], b[2], c[0], c[1], c[2])43}4445/**46 * Break an icosphere into Voronoi shards (faces assigned to their nearest47 * site), then give every shard real thickness by extruding it toward the48 * center — so each fragment reads as a solid chunk, not a paper-thin shell.49 */50function buildShards(count: number): Shard[] {51 const base = new THREE.IcosahedronGeometry(RADIUS, 3)52 const nonIndexed = base.toNonIndexed()53 base.dispose()54 const arr = (nonIndexed.getAttribute("position") as THREE.BufferAttribute)55 .array as Float32Array56 const sites = fibonacciSites(count)57 const buckets: number[][] = Array.from({ length: count }, () => [])58 const f = (RADIUS - THICKNESS) / RADIUS59 const c = new THREE.Vector3()6061 for (let i = 0; i < arr.length; i += 9) {62 // Nearest fracture site for this face (by its normalized centroid).63 c.set(64 (arr[i] + arr[i + 3] + arr[i + 6]) / 3,65 (arr[i + 1] + arr[i + 4] + arr[i + 7]) / 3,66 (arr[i + 2] + arr[i + 5] + arr[i + 8]) / 367 ).normalize()68 let best = 069 let bestDot = -Infinity70 for (let s = 0; s < sites.length; s++) {71 const d = c.dot(sites[s])72 if (d > bestDot) {73 bestDot = d74 best = s75 }76 }77 const out = buckets[best]7879 // Outer triangle (on the sphere) and its inward-extruded copy.80 const p: Vec[] = [81 [arr[i], arr[i + 1], arr[i + 2]],82 [arr[i + 3], arr[i + 4], arr[i + 5]],83// … 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 | |
| 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 |
