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:
parent
7d043cd141
commit
7e14d9b314
7 changed files with 161 additions and 71 deletions
|
|
@ -18,15 +18,16 @@
|
|||
* the tip. A foot tread at the back — on a real shovel the top edge of the
|
||||
* blade is folded over, to press down on with the foot.
|
||||
*/
|
||||
import { type BufferGeometry } from 'three'
|
||||
import { Color, type BufferGeometry } from 'three'
|
||||
|
||||
import {
|
||||
chamferedBoxGeometry,
|
||||
createKitModel,
|
||||
createTinter,
|
||||
dishedSheetGeometry,
|
||||
ironTint,
|
||||
steelTint,
|
||||
mergeColoured,
|
||||
prismGeometry,
|
||||
toolShaft,
|
||||
toolSocket,
|
||||
type SheetLevel,
|
||||
|
|
@ -59,15 +60,38 @@ export const woodenShovelDefaults: WoodenShovelConfig = {
|
|||
export type WoodenShovelParts = 'shaft' | 'socket' | 'blade'
|
||||
|
||||
export function createModel(overrides: Partial<WoodenShovelConfig> = {}) {
|
||||
return createKitModel<WoodenShovelConfig, 'oak' | 'iron' | 'steel', WoodenShovelParts>({
|
||||
return createKitModel<WoodenShovelConfig, 'oak' | 'iron', WoodenShovelParts>({
|
||||
id: 'wooden-shovel',
|
||||
defaults: woodenShovelDefaults,
|
||||
slots: ['oak', 'iron', 'steel'],
|
||||
slots: ['oak', 'iron'],
|
||||
build: ({ config, random }) => {
|
||||
const tint = createTinter(random)
|
||||
const span = config.length * config.bladeLength
|
||||
const shaftLength = config.length - span * 0.82
|
||||
const shaft = toolShaft({ length: shaftLength, radius: config.shaftRadius, random })
|
||||
|
||||
// --- T-handle --------------------------------------------------------
|
||||
// The reference has one and this did not: the shaft simply ended in a
|
||||
// swelled knob. A digging spade is worked with both hands and the lower
|
||||
// one goes round a crossbar; it is the detail that separates a spade
|
||||
// from a stick with a plate on the end, and it is right at the end of
|
||||
// the silhouette where the eye lands.
|
||||
//
|
||||
// The bar crosses the grip swell rather than butting onto it, so the
|
||||
// joint is an overlap like every other in the kit.
|
||||
const gripSpan = config.shaftRadius * 8.6
|
||||
const grip = prismGeometry(
|
||||
config.shaftRadius * 0.95,
|
||||
config.shaftRadius * 0.82,
|
||||
gripSpan,
|
||||
7,
|
||||
[0, 0, 0],
|
||||
new Color(tint('oak', 0.05)),
|
||||
)
|
||||
// Built along Y; +90 degrees about Z lays it along X, across the blade.
|
||||
grip.rotateZ(Math.PI / 2)
|
||||
grip.translate(0, -shaft.top + config.shaftRadius * 0.9, 0)
|
||||
|
||||
const socketLength = config.length * 0.05
|
||||
const socket = toolSocket({
|
||||
y: shaft.top - socketLength * 0.3,
|
||||
|
|
@ -98,7 +122,12 @@ export function createModel(overrides: Partial<WoodenShovelConfig> = {}) {
|
|||
{ y: span, halfWidth: half * 0.44, thickness: t * 0.14, curve: curve * 0.48 },
|
||||
]
|
||||
|
||||
const sheet = dishedSheetGeometry(profile, 8, steelTint(random, -0.04), steelTint(random, 0.04))
|
||||
// Both colours copied out first: `createTinter` returns one Color and
|
||||
// mutates it, so two tints inside one call would resolve to the same
|
||||
// value.
|
||||
const boardLow = new Color(tint('oak', -0.05))
|
||||
const boardHigh = new Color(tint('oakEnd', 0.03))
|
||||
const sheet = dishedSheetGeometry(profile, 8, boardLow, boardHigh)
|
||||
|
||||
// Foot tread: the fold at the top edge of the blade, BEHIND the dish. It
|
||||
// must sit at shoulder height and be WIDE — this is where you step, and a
|
||||
|
|
@ -109,7 +138,7 @@ export function createModel(overrides: Partial<WoodenShovelConfig> = {}) {
|
|||
t * 1.8,
|
||||
t * 0.34,
|
||||
[0, 0, 0],
|
||||
steelTint(random, -0.07),
|
||||
new Color(tint('oak', -0.1)),
|
||||
)
|
||||
tread.rotateX(0.42)
|
||||
tread.translate(0, span * 0.12, -t * 1.7)
|
||||
|
|
@ -137,10 +166,14 @@ export function createModel(overrides: Partial<WoodenShovelConfig> = {}) {
|
|||
}
|
||||
|
||||
return {
|
||||
shaft: { slot: 'oak', geometry: shaft.geometry },
|
||||
shaft: { slot: 'oak', geometry: mergeColoured([shaft.geometry, grip]) },
|
||||
socket: { slot: 'iron', geometry: socket },
|
||||
blade: {
|
||||
slot: 'steel',
|
||||
// Oak, not steel. A medieval digging shovel is a shaped board with
|
||||
// an iron shoe along its lip -- the strap below is that shoe, and it
|
||||
// has been there all along while the board it protects was rendered
|
||||
// as a sheet of polished steel.
|
||||
slot: 'oak',
|
||||
geometry: blade,
|
||||
extras: [{ slot: 'iron', geometry: strap }],
|
||||
},
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue