Make the wooden tools wooden, and give the spade its handle

Three faults across two tools, and two of them come down to a model being
named after a material it was not made of.

The pitchfork had three steel tines, 0.24 m on a 1.5 m shaft -- 16% of the
tool against roughly 22% in the reference -- fanned out like a cultivator.
A hay fork has four or five, they are the working length of the thing, and
they stay close to parallel so a forkful stays on them. They are also
wood: the model is called wooden-pitchfork and a hay fork really was cut
and steamed from a branch, because iron is heavy at the end of a long shaft
and hay needs no edge. The socket stays iron, since that is the ferrule.

The shovel's blade was a sheet of polished steel. The strap that runs up
behind it has been modelled as an iron shoe all along -- a shoe for a board
that was being rendered as steel. A medieval digging shovel is a shaped
board with iron along its lip, so the blade moves to oak and the shoe
becomes the only metal on the head.

And it had no handle: the shaft simply ended in a swelled knob. A digging
spade is worked with both hands with the lower one round a crossbar, which
is what separates a spade from a stick with a plate on the end, and it sits
right at the end of the silhouette where the eye lands. The bar crosses the
grip swell rather than butting onto it.

Two notes for later. The wider tine spread pushed the fork past its size
guard at 0.35 m across; 30-40 cm is the head of a real hay fork, so the
limit moved rather than the geometry. And `createTinter` returns one Color
and mutates it while `steelTint` and `ironTint` allocate per call -- the
new code copies out of the first before the next call, but the two helpers
disagreeing about this is a trap in itself.

27 models, 18599 triangles, all checks pass, 0 floating cases, build clean.
This commit is contained in:
CRTkafa 2026-08-23 11:21:37 +07:00
parent 7d043cd141
commit 7e14d9b314
7 changed files with 161 additions and 71 deletions

View file

@ -9,13 +9,13 @@
* point, and none of them sits at exactly the same angle as its neighbour. All
* three were fixed here.
*/
import { type BufferGeometry } from 'three'
import { Color, type BufferGeometry } from 'three'
import {
chamferedBoxGeometry,
createKitModel,
createTinter,
ironTint,
steelTint,
jitter,
bendGeometry,
latheGeometry,
@ -40,20 +40,28 @@ export interface WoodenPitchforkConfig {
export const woodenPitchforkDefaults: WoodenPitchforkConfig = {
length: 1.5,
shaftRadius: 0.021,
tineCount: 3,
spread: 0.2,
tineLength: 0.24,
// Four tines and longer ones. Three is a garden fork; a hay fork has four
// or five, and the tines are the working length of the tool -- at 0.24 on a
// 1.5 m shaft they were 16% of it against roughly 22% in the reference, and
// read as stubs rather than as something you could lift a forkful with.
// Tines run close to parallel, splaying only a little. Fanned out like a
// claw they read as a garden cultivator; a hay fork's tines stay together
// so a forkful stays on them.
tineCount: 4,
spread: 0.15,
tineLength: 0.34,
seed: 37,
}
export type WoodenPitchforkParts = 'shaft' | 'socket' | 'tines'
export function createModel(overrides: Partial<WoodenPitchforkConfig> = {}) {
return createKitModel<WoodenPitchforkConfig, 'oak' | 'iron' | 'steel', WoodenPitchforkParts>({
return createKitModel<WoodenPitchforkConfig, 'oak' | 'iron', WoodenPitchforkParts>({
id: 'wooden-pitchfork',
defaults: woodenPitchforkDefaults,
slots: ['oak', 'iron', 'steel'],
slots: ['oak', 'iron'],
build: ({ config, random }) => {
const tint = createTinter(random)
const tineSpan = config.length * config.tineLength
const shaftLength = config.length - tineSpan * 0.86
const shaft = toolShaft({ length: shaftLength, radius: config.shaftRadius, random })
@ -95,9 +103,13 @@ export function createModel(overrides: Partial<WoodenPitchforkConfig> = {}) {
{ y: tineSpan * 0.9, radius: radius * 0.42 },
{ y: tineSpan, radius: radius * 0.12 }, // pointed but not zero
]
const tine = latheGeometry(profile, 6, [0, 0, 0], steelTint(random, -0.05), {
// Oak, not steel. The model is called wooden-pitchfork and the
// reference is exactly that: a hay fork was cut and steamed from wood,
// because iron tines are heavy at the end of a long shaft and hay does
// not need an edge. The socket stays iron -- that is the ferrule.
const tine = latheGeometry(profile, 6, [0, 0, 0], new Color(tint('oak', -0.03)), {
capTop: false,
colourTop: steelTint(random, 0.05),
colourTop: new Color(tint('oakEnd', 0.06)),
})
// Curve: a straight tine looks like a technical drawing. A real pitchfork
// tine is bent forward — so it does not drop the straw it has lifted.
@ -114,7 +126,7 @@ export function createModel(overrides: Partial<WoodenPitchforkConfig> = {}) {
return {
shaft: { slot: 'oak', geometry: shaft.geometry },
socket: { slot: 'iron', geometry: socket },
tines: { slot: 'steel', geometry: mergeColoured(pieces) },
tines: { slot: 'oak', geometry: mergeColoured(pieces) },
}
},
}, overrides)