component

Barrel

Staved barrel bellied at the middle, banded by metal hoops; convex-hull collider.

⌖ Explore the library in 3D → · View as Markdown

Tune every prop in the workshop →

Add it

npx @runek/cli add barrel

Pulls @react-three/rapier@^2.2.0, @runek/core@^0.15.0.

Use it

import { Barrel } from './runek/Barrel'

<Barrel position={[0, 0, 0]} />

Or as a node in a world file (worlds as data):

{ "type": "Barrel", "props": { "position": [0, 0, 0] } }

Props

Prop Type Default Description
position [x, y, z] [0, 0, 0] Position [x, y, z] in units (1 unit = 1 m, Y-up).
rotation [x, y, z] [0, 0, 0] Euler rotation [x, y, z] in radians.
seed number Accepted for the component contract; this component has no seeded variation yet.
radius number 0.35 Radius, in units.
height number 0.9 Height, in units.
color color palette wood Stave color; defaults to the world palette’s wood slot.
hoopColor color palette metal Hoop color; defaults to the world palette’s metal slot.

Registry manifest

registry manifest /r/components/barrel.json Self-contained JSON: inlined source plus resolved dependencies, exactly what runek add barrel fetches.

Browse the whole catalog in the gallery →.

Source (Barrel.tsx)
import { RigidBody } from '@react-three/rapier'
import { useWorld, type Vec3 } from '@runek/core'

export interface BarrelProps {
  position?: Vec3
  rotation?: Vec3
  /** Accepted for the component contract; this component has no seeded variation yet. */
  seed?: number
  radius?: number
  height?: number
  /** Stave color; defaults to the world palette's `wood` slot. */
  color?: string
  /** Hoop color; defaults to the world palette's `metal` slot. */
  hoopColor?: string
}

/** A staved barrel: two frustums bellied at the middle, banded by metal hoops.
 *  A convex-hull collider matches the bulge. Crate's round sibling. */
export function Barrel({
  position = [0, 0, 0],
  rotation = [0, 0, 0],
  radius = 0.35,
  height = 0.9,
  color,
  hoopColor,
}: BarrelProps) {
  const { unit, palette } = useWorld()
  const wood = color ?? palette.wood
  const hoop = hoopColor ?? palette.metal
  const r = radius * unit
  const h = height * unit
  const rEnd = r * 0.82
  const seg = 14

  return (
    <RigidBody type="fixed" colliders="hull" position={position} rotation={rotation}>
      <mesh castShadow receiveShadow position={[0, h / 4, 0]}>
        <cylinderGeometry args={[r, rEnd, h / 2, seg]} />
        <meshStandardMaterial color={wood} roughness={0.85} flatShading />
      </mesh>
      <mesh castShadow receiveShadow position={[0, (3 * h) / 4, 0]}>
        <cylinderGeometry args={[rEnd, r, h / 2, seg]} />
        <meshStandardMaterial color={wood} roughness={0.85} flatShading />
      </mesh>
      {[0.12, 0.5, 0.88].map((f) => (
        <mesh key={`hoop-${f}`} position={[0, h * f, 0]} rotation={[Math.PI / 2, 0, 0]} castShadow>
          <torusGeometry args={[f === 0.5 ? r * 1.03 : rEnd * 1.06, 0.02 * h, 6, seg]} />
          <meshStandardMaterial color={hoop} metalness={0.5} roughness={0.5} />
        </mesh>
      ))}
    </RigidBody>
  )
}

Barrel.groundSitting = true