component
Pillar
Column with a plinth, a tapered (optionally fluted) shaft, and a capital.
⌖ Explore the library in 3D → · View as Markdown
Add it
npx @runek/cli add pillar
Pulls @react-three/rapier@^2.2.0, @runek/core@^0.15.0.
Use it
import { Pillar } from './runek/Pillar'
<Pillar position={[0, 0, 0]} />
Or as a node in a world file (worlds as data):
{ "type": "Pillar", "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. | |
height |
number |
3 |
Height, in units. |
radius |
number |
0.28 |
Shaft radius at the base, in units. |
flutes |
number |
0 |
Vertical flutes around the shaft; 0 = smooth. |
color |
color |
palette stone |
Defaults to the world palette’s stone slot. |
Registry manifest
registry manifest /r/components/pillar.json Self-contained JSON: inlined source plus resolved dependencies, exactly whatrunek add pillar fetches.
Browse the whole catalog in the gallery →.
Source (Pillar.tsx)
import { CuboidCollider, RigidBody } from '@react-three/rapier'
import { useWorld, type Vec3 } from '@runek/core'
export interface PillarProps {
position?: Vec3
rotation?: Vec3
/** Accepted for the component contract; this component has no seeded variation yet. */
seed?: number
height?: number
/** Shaft radius at the base, in units. */
radius?: number
/** Vertical flutes around the shaft; 0 = smooth. */
flutes?: number
/** Defaults to the world palette's `stone` slot. */
color?: string
}
/** A column: square plinth, tapered shaft, square capital. `flutes` facets the
* shaft (a fluted look) when set; 0 leaves it smooth. Builds porches, colonnades,
* and ruins. */
export function Pillar({
position = [0, 0, 0],
rotation = [0, 0, 0],
height = 3,
radius = 0.28,
flutes = 0,
color,
}: PillarProps) {
const { unit, palette } = useWorld()
const stone = color ?? palette.stone
const r = radius * unit
const h = height * unit
const plinthH = 0.08 * h
const capH = 0.1 * h
const shaftH = h - plinthH - capH
const seg = flutes > 0 ? flutes : 24
return (
<RigidBody type="fixed" colliders={false} position={position} rotation={rotation}>
<CuboidCollider args={[r, h / 2, r]} position={[0, h / 2, 0]} />
<mesh castShadow receiveShadow position={[0, plinthH / 2, 0]}>
<boxGeometry args={[r * 2.4, plinthH, r * 2.4]} />
<meshStandardMaterial color={stone} roughness={0.92} />
</mesh>
<mesh castShadow receiveShadow position={[0, plinthH + shaftH / 2, 0]}>
<cylinderGeometry args={[r * 0.85, r, shaftH, seg]} />
<meshStandardMaterial color={stone} roughness={0.92} flatShading={flutes > 0} />
</mesh>
<mesh castShadow receiveShadow position={[0, h - capH, 0]}>
<cylinderGeometry args={[r * 1.05, r * 0.85, capH * 0.5, 24]} />
<meshStandardMaterial color={stone} roughness={0.92} />
</mesh>
<mesh castShadow receiveShadow position={[0, h - capH * 0.25, 0]}>
<boxGeometry args={[r * 2.3, capH * 0.5, r * 2.3]} />
<meshStandardMaterial color={stone} roughness={0.92} />
</mesh>
</RigidBody>
)
}
Pillar.groundSitting = true