import { makeCameraPresets, makeThumbnailStrategy } from './factory'; import type { MachineDossier } from './types'; export const ENGINE_DOSSIERS = [ { machineId: 'four-stroke-petrol-engine', slugAliases: ['four-stroke-engine', 'otto-cycle-engine', 'petrol-engine'], title: 'Four Stroke Petrol Engine', category: 'Engines', difficulty: 'Beginner', complexityScore: 4, registryKeywords: ['otto cycle', 'spark ignition', 'piston', 'crankshaft', 'camshaft', 'valves'], oneParagraphDescription: 'A four stroke petrol engine converts a fuel-air charge into rotary crankshaft torque through the intake, compression, combustion, and exhaust strokes. The procedural assembly emphasizes the crank-slider geometry, half-speed camshaft timing, poppet valve events, and spark ignition so learners can connect textbook cycle diagrams to visible component motion.', learningObjectives: [ 'Identify the four strokes and the crank angles at which they occur.', 'Explain why the camshaft rotates at half crankshaft speed.', 'Trace the load path from gas pressure on the piston crown to crankshaft torque.', 'Relate valve overlap and ignition timing to practical engine breathing.', ], facts: [ { label: 'Cycle', value: '720° crank rotation', details: 'A complete thermodynamic cycle takes two crankshaft revolutions and one camshaft revolution.', }, { label: 'Typical speed', value: '800–6500 rpm', details: 'Passenger-car spark ignition engines idle below 1000 rpm and often peak near 6000 rpm.', }, { label: 'Compression ratio', value: '9:1–13:1', details: 'Limited by knock resistance of the fuel and chamber thermal management.', }, { label: 'Invented', value: '1876', details: 'Nikolaus Otto demonstrated the practical four-stroke internal combustion cycle.', }, { label: 'Applications', value: 'Cars, motorcycles, generators', details: 'Chosen when compact size, throttle response, and broad speed range are important.', }, ], componentTree: [ { id: 'stationary-structure', name: 'Stationary structure', kind: 'assembly', description: 'The block, head, and jackets hold pressure, align the moving parts, and remove heat.', engineeringRole: 'Provides datum geometry for the cylinder bore, crank bearings, and valve train.', materialHint: 'cast aluminium or cast iron with dark machined edges', labelAnchor: [0, 0.1, 0], explodedOffset: [0, -0.25, 0], replacementNode: 'StationaryStructure', animationChannels: [], children: [ { id: 'engine-block', name: 'Engine block', kind: 'part', description: 'Rigid casting containing the cylinder bore, crankcase, and main bearing saddles.', engineeringRole: 'Carries combustion loads into the crankshaft bearings while maintaining bore alignment.', materialHint: 'satin cast metal', labelAnchor: [0, -0.15, 0], explodedOffset: [0, -0.42, 0], replacementNode: 'EngineBlock', animationChannels: [], }, { id: 'cylinder-head', name: 'Cylinder head', kind: 'part', description: 'Upper casting that closes the combustion chamber and supports valves and spark plug.', engineeringRole: 'Shapes the chamber, flow passages, and cooling routes above the piston.', materialHint: 'brushed aluminium', labelAnchor: [0, 0.9, 0], explodedOffset: [0, 0.58, 0], replacementNode: 'CylinderHead', animationChannels: [], }, { id: 'coolant-jacket', name: 'Coolant jacket', kind: 'effect', description: 'Transparent blue passage network showing the water jacket around hot cylinder regions.', engineeringRole: 'Removes heat from the bore and head to control detonation and material stress.', materialHint: 'transparent coolant blue', labelAnchor: [-0.52, 0.35, 0], explodedOffset: [-0.28, 0.1, 0], replacementNode: 'CoolantJacket', animationChannels: ['coolant-flow'], }, ], }, { id: 'reciprocating-assembly', name: 'Reciprocating assembly', kind: 'assembly', description: 'Piston, rings, rod, crank, and flywheel convert pressure into smooth rotary output.', engineeringRole: 'Transforms linear piston force into torque and stores kinetic energy between firing events.', materialHint: 'mixed forged steel and aluminium', labelAnchor: [0, 0.25, 0.1], explodedOffset: [0.32, 0, 0], replacementNode: 'ReciprocatingAssembly', animationChannels: ['crank-rotation', 'piston-reciprocation', 'rod-swing'], children: [ { id: 'piston', name: 'Piston', kind: 'part', description: 'Crowned sliding member that seals the combustion chamber and transmits gas pressure.', engineeringRole: 'Receives pressure force and pushes the connecting rod through the wrist pin.', materialHint: 'light forged aluminium with warm crown highlight', labelAnchor: [0, 0.35, 0], explodedOffset: [0.35, 0.08, 0], replacementNode: 'Piston', animationChannels: ['piston-reciprocation'], }, { id: 'piston-rings', name: 'Piston rings', kind: 'part', description: 'Thin spring rings around the piston that seal gas pressure and meter oil.', engineeringRole: 'Separate combustion gases from crankcase oil while allowing low-friction sliding.', materialHint: 'dark spring steel', labelAnchor: [0.24, 0.43, 0], explodedOffset: [0.45, 0.12, 0], replacementNode: 'PistonRings', animationChannels: ['piston-reciprocation'], }, { id: 'connecting-rod', name: 'Connecting rod', kind: 'part', description: 'Articulated forged link between piston pin and crank throw.', engineeringRole: 'Carries alternating compression and tension while permitting angular swing.', materialHint: 'shot-peened forged steel', labelAnchor: [0.14, -0.15, 0], explodedOffset: [0.55, 0, 0], replacementNode: 'ConnectingRod', animationChannels: ['rod-swing'], }, { id: 'crankshaft', name: 'Crankshaft', kind: 'part', description: 'Offset shaft with crank throw that converts rod force into torque.', engineeringRole: 'Combines reciprocating loads into a balanced rotary output.', materialHint: 'polished hardened steel', labelAnchor: [0, -0.72, 0], explodedOffset: [0.65, -0.08, 0], replacementNode: 'Crankshaft', animationChannels: ['crank-rotation'], }, { id: 'flywheel', name: 'Flywheel', kind: 'part', description: 'Heavy rotating disc attached to the crankshaft output.', engineeringRole: 'Stores angular momentum so the crank passes non-power strokes smoothly.', materialHint: 'dark iron rim with machined edge', labelAnchor: [0.74, -0.72, 0], explodedOffset: [0.92, -0.08, 0], replacementNode: 'Flywheel', animationChannels: ['crank-rotation'], }, ], }, { id: 'valve-and-ignition', name: 'Valve and ignition system', kind: 'assembly', description: 'Camshaft, valves, manifolds, and spark plug meter charge exchange and ignition.', engineeringRole: 'Coordinates air, fuel, exhaust, and spark timing against piston position.', materialHint: 'steel, ceramic, and translucent gas-flow effects', labelAnchor: [0, 1.1, 0], explodedOffset: [0, 0.42, 0.28], replacementNode: 'ValveAndIgnition', animationChannels: ['cam-rotation', 'intake-valve-lift', 'exhaust-valve-lift', 'spark-event'], children: [ { id: 'camshaft', name: 'Camshaft', kind: 'part', description: 'Lobed shaft whose profiles open the valves at precise crank angles.', engineeringRole: 'Runs at half crank speed to schedule one valve cycle per four-stroke cycle.', materialHint: 'polished steel with blue timing mark', labelAnchor: [-0.38, 1.02, 0], explodedOffset: [-0.25, 0.42, 0.22], replacementNode: 'Camshaft', animationChannels: ['cam-rotation'], }, { id: 'intake-valve', name: 'Intake valve', kind: 'part', description: 'Poppet valve admitting fresh mixture during the intake stroke.', engineeringRole: 'Opens near top dead centre and closes after bottom dead centre for cylinder filling.', materialHint: 'cool blue steel', labelAnchor: [-0.18, 0.72, 0.08], explodedOffset: [-0.22, 0.32, 0.28], replacementNode: 'IntakeValve', animationChannels: ['intake-valve-lift'], }, { id: 'exhaust-valve', name: 'Exhaust valve', kind: 'part', description: 'Heat-resistant valve releasing burned gases during the exhaust stroke.', engineeringRole: 'Opens before bottom dead centre to reduce pumping loss.', materialHint: 'warm nickel alloy', labelAnchor: [0.18, 0.72, 0.08], explodedOffset: [0.22, 0.32, 0.28], replacementNode: 'ExhaustValve', animationChannels: ['exhaust-valve-lift'], }, { id: 'spark-plug', name: 'Spark plug', kind: 'part', description: 'Ceramic-insulated electrode that initiates flame propagation in the chamber.', engineeringRole: 'Fires before top dead centre so peak pressure occurs just after TDC.', materialHint: 'white ceramic with warm spark emissive tip', labelAnchor: [0, 0.94, 0.14], explodedOffset: [0, 0.48, 0.36], replacementNode: 'SparkPlug', animationChannels: ['spark-event'], }, { id: 'intake-manifold', name: 'Intake manifold', kind: 'part', description: 'Runner delivering throttled air-fuel mixture to the intake port.', engineeringRole: 'Uses runner length and plenum volume to tune cylinder filling.', materialHint: 'matte black composite with blue flow arrows', labelAnchor: [-0.66, 0.72, 0], explodedOffset: [-0.55, 0.18, 0], replacementNode: 'IntakeManifold', animationChannels: ['intake-flow'], }, { id: 'exhaust-manifold', name: 'Exhaust manifold', kind: 'part', description: 'Hot runner carrying exhaust gas away from the exhaust port.', engineeringRole: 'Collects pressure pulses and directs them to catalyst or turbo hardware.', materialHint: 'dark heat-stained cast iron with amber flow', labelAnchor: [0.66, 0.72, 0], explodedOffset: [0.55, 0.18, 0], replacementNode: 'ExhaustManifold', animationChannels: ['exhaust-flow'], }, ], }, ], labels: [ { partId: 'piston', text: 'Piston follows crank-slider motion', position: [0, 0.52, 0.28], priority: 'primary' }, { partId: 'crankshaft', text: 'Crankshaft turns pressure into torque', position: [0, -0.86, 0.32], priority: 'primary' }, { partId: 'camshaft', text: 'Camshaft rotates at 1/2 crank speed', position: [-0.38, 1.16, 0.22], priority: 'secondary' }, { partId: 'spark-plug', text: 'Spark leads TDC for flame travel', position: [0.12, 1.08, 0.34], priority: 'detail' }, ], cameraPresets: makeCameraPresets(4.2, [0, 0.15, 0], { id: 'combustion-chamber', label: 'Combustion Chamber', position: [1.25, 1.25, 1.9], target: [0, 0.55, 0], description: 'Tight view into the head, valve faces, spark plug, and piston crown.', }), guidedTour: [ { id: 'cycle-overview', title: 'Four strokes in two revolutions', body: 'Watch the piston traverse intake, compression, combustion, and exhaust over 720 degrees of crank motion.', cameraPresetId: 'isometric', highlightedPartIds: ['piston', 'crankshaft', 'camshaft'], durationSeconds: 7, animationTimeScale: 0.8, setExplode: 0, }, { id: 'intake-event', title: 'Intake valve opens', body: 'The intake valve lifts while the piston descends, drawing mixture through the runner into the cylinder.', cameraPresetId: 'combustion-chamber', highlightedPartIds: ['intake-valve', 'intake-manifold', 'piston'], durationSeconds: 6, animationTimeScale: 0.55, setExplode: 0.12, crossSection: { axis: 'z', offset: 0.02 }, }, { id: 'compression-spark', title: 'Compression and spark timing', body: 'Both valves close, the mixture compresses, and the plug fires slightly before top dead centre.', cameraPresetId: 'combustion-chamber', highlightedPartIds: ['spark-plug', 'piston-rings', 'cylinder-head'], durationSeconds: 6, animationTimeScale: 0.45, setExplode: 0.08, }, { id: 'power-stroke', title: 'Power stroke load path', body: 'Expanding gas presses the piston, the rod swings, and the crank throw produces useful torque.', cameraPresetId: 'right', highlightedPartIds: ['piston', 'connecting-rod', 'crankshaft', 'flywheel'], durationSeconds: 7, animationTimeScale: 0.7, setExplode: 0.18, }, { id: 'exhaust-event', title: 'Exhaust gas leaves the cylinder', body: 'The exhaust valve opens and the rising piston pushes burned gas into the manifold.', cameraPresetId: 'front', highlightedPartIds: ['exhaust-valve', 'exhaust-manifold', 'piston'], durationSeconds: 6, animationTimeScale: 0.65, setExplode: 0.12, }, ], animationModel: { nominalRpm: 1200, cycleSecondsAtNominal: 0.1, loopMode: 'continuous', stepCount: 4, primaryDriver: 'crank-angle-degrees', engineeringNotes: 'Use a 720 degree normalized cycle. The crankshaft rotates twice, the camshaft once, and valve lift curves are eased lobes rather than square events.', channels: [ { id: 'crank-rotation', label: 'Crankshaft rotation', targetPartIds: ['crankshaft', 'flywheel'], transform: 'rotation', driver: 'crank angle θ', expression: 'rotate about output axis by θ, with θ spanning 0–720° per cycle', phaseDeg: 0, notes: 'Continuous rotation drives all dependent channels.', }, { id: 'piston-reciprocation', label: 'Piston reciprocation', targetPartIds: ['piston', 'piston-rings'], transform: 'translation', driver: 'crank slider', expression: 'y = r cos θ + sqrt(l² - r² sin² θ), normalized between TDC and BDC', phaseDeg: 0, notes: 'Use rod length at least 3.5 times crank radius for believable side motion.', }, { id: 'rod-swing', label: 'Connecting rod swing', targetPartIds: ['connecting-rod'], transform: 'oscillation', driver: 'piston pin to crank pin constraint', expression: 'orient rod between piston pin and crank throw each frame', phaseDeg: 0, notes: 'Rod should not be animated independently; solve it from endpoint positions.', }, { id: 'cam-rotation', label: 'Camshaft half-speed rotation', targetPartIds: ['camshaft'], transform: 'rotation', driver: 'crank angle θ', expression: 'cam angle = θ / 2', phaseDeg: 0, notes: 'One cam revolution per complete four-stroke cycle.', }, { id: 'intake-valve-lift', label: 'Intake valve lift', targetPartIds: ['intake-valve'], transform: 'translation', driver: 'cam lobe profile', expression: 'smooth lift from 340° to 570° crank angle with slight overlap around TDC', phaseDeg: 340, notes: 'Blue intake flow opacity follows the same envelope.', }, { id: 'exhaust-valve-lift', label: 'Exhaust valve lift', targetPartIds: ['exhaust-valve'], transform: 'translation', driver: 'cam lobe profile', expression: 'smooth lift from 130° to 370° crank angle', phaseDeg: 130, notes: 'Amber exhaust flow is strongest while piston rises.', }, { id: 'spark-event', label: 'Spark event', targetPartIds: ['spark-plug'], transform: 'material', driver: 'ignition timing', expression: 'brief emissive pulse near 700° crank angle before combustion stroke TDC', phaseDeg: 700, notes: 'Keep pulse short so it reads as ignition, not a constant lamp.', }, { id: 'coolant-flow', label: 'Coolant flow', targetPartIds: ['coolant-jacket'], transform: 'flow', driver: 'engine running state', expression: 'slow continuous scrolling blue particles through head and bore jackets', phaseDeg: 0, notes: 'Secondary effect remains visible at low opacity when cross-section is active.', }, ], }, explodedView: { defaultDistance: 0.34, maxDistance: 1.15, groups: [ { id: 'head-up', label: 'Head and valve train', partIds: ['cylinder-head', 'camshaft', 'intake-valve', 'exhaust-valve', 'spark-plug'], axis: 'y', direction: 1, order: 1, reason: 'Separates the combustion chamber and valve events from the moving piston.', }, { id: 'manifolds-side', label: 'Intake and exhaust manifolds', partIds: ['intake-manifold', 'exhaust-manifold'], axis: 'x', direction: 1, order: 2, reason: 'Opens both gas paths without hiding the valve faces.', }, { id: 'bottom-drive', label: 'Crank and flywheel', partIds: ['connecting-rod', 'crankshaft', 'flywheel'], axis: 'x', direction: 1, order: 3, reason: 'Reveals the crank-slider torque conversion below the bore.', }, ], }, crossSection: { defaultAxis: 'z', recommendedPlanes: [ { id: 'bore-centreline', label: 'Cylinder centreline', axis: 'z', offset: 0, description: 'Cuts through the bore, piston, valves, and spark plug for cycle teaching.', }, { id: 'crankcase-split', label: 'Crankcase split', axis: 'y', offset: -0.42, description: 'Exposes crank webs, rod big end, and oil volume under the piston.', }, ], }, thumbnail: makeThumbnailStrategy( ['engine-block', 'cylinder-head', 'flywheel'], ['piston', 'spark-plug', 'intake-valve'], 'Render with a cutaway cylinder window and a warm spark accent so the four-stroke identity is clear at card size.', ), assetReplacement: { proceduralBlueprintId: 'four-stroke-petrol-engine', preferredGlbPath: 'src/assets/machines/four-stroke-petrol-engine/four-stroke-petrol-engine.glb', rootNodeName: 'FourStrokePetrolEngine', requiredNamedNodes: [ 'EngineBlock', 'CylinderHead', 'Piston', 'PistonRings', 'ConnectingRod', 'Crankshaft', 'Flywheel', 'Camshaft', 'IntakeValve', 'ExhaustValve', 'SparkPlug', ], optionalNamedNodes: ['CoolantJacket', 'IntakeManifold', 'ExhaustManifold', 'TimingChain', 'OilSump'], materialSlots: ['cast-metal', 'machined-steel', 'aluminium', 'rubber-dark', 'flow-blue', 'flow-amber', 'spark-emissive'], coordinateSystem: 'Y up, crankshaft output along X, cylinder axis along Y, model origin at crankshaft main bearing centre.', replacementInstructions: 'Keep named nodes aligned to the procedural pivot conventions. Valve nodes translate along their stem axis and the crankshaft/flywheel rotate around local X.', }, relatedMachines: ['diesel-engine', 'two-stroke-engine', 'slider-crank'], }, { machineId: 'two-stroke-engine', slugAliases: ['two-stroke-petrol-engine', '2-stroke-engine', 'port-timed-engine'], title: 'Two Stroke Engine', category: 'Engines', difficulty: 'Beginner', complexityScore: 3, registryKeywords: ['two stroke', 'ports', 'crankcase compression', 'scavenging', 'piston port'], oneParagraphDescription: 'A two stroke engine completes a power cycle every crankshaft revolution by using piston-controlled ports and crankcase compression instead of a separate valve train. The visualization highlights the transfer, intake, and exhaust windows so learners can see how fresh charge enters while burned gas leaves during the brief scavenging interval.', learningObjectives: [ 'Recognize why a two stroke fires every revolution.', 'Trace charge flow from crankcase through transfer ports into the cylinder.', 'Explain the compromise between scavenging efficiency and short-circuiting losses.', 'Compare port timing to cam-operated valve timing.', ], facts: [ { label: 'Cycle', value: '360° crank rotation', details: 'Compression, combustion, exhaust, and intake events overlap in one crankshaft revolution.', }, { label: 'Typical speed', value: '3000–12000 rpm', details: 'Small two strokes operate at high speed because of light reciprocating parts and frequent firing.', }, { label: 'Power density', value: 'High', details: 'One firing event per revolution can produce high specific power for a given displacement.', }, { label: 'Common applications', value: 'Chainsaws, scooters, marine outboards', details: 'Used where low mass and simplicity outweigh emissions and fuel-consumption penalties.', }, { label: 'Lubrication', value: 'Oil mixed or injected', details: 'Many small engines carry lubricant with the incoming charge instead of a separate sump.', }, ], componentTree: [ { id: 'two-stroke-structure', name: 'Ported cylinder structure', kind: 'assembly', description: 'A cylinder and crankcase casting with windows that are uncovered by piston motion.', engineeringRole: 'Uses fixed port geometry to replace camshafts, pushrods, and poppet valves.', materialHint: 'cast aluminium with dark port openings', labelAnchor: [0, 0.2, 0], explodedOffset: [0, -0.18, 0], replacementNode: 'PortedCylinderStructure', animationChannels: [], children: [ { id: 'ported-cylinder', name: 'Ported cylinder', kind: 'part', description: 'Cylinder bore with exhaust and transfer openings cut into the liner.', engineeringRole: 'Times gas exchange by covering and uncovering ports as the piston travels.', materialHint: 'finned cast aluminium', labelAnchor: [0, 0.4, 0], explodedOffset: [0, -0.25, 0], replacementNode: 'PortedCylinder', animationChannels: [], }, { id: 'crankcase-pump', name: 'Crankcase pump volume', kind: 'part', description: 'Sealed lower chamber where descending piston pressurizes incoming mixture.', engineeringRole: 'Acts as a simple compressor that feeds the transfer passage.', materialHint: 'semi-transparent blue-grey chamber', labelAnchor: [0, -0.42, 0], explodedOffset: [0, -0.45, 0], replacementNode: 'CrankcasePumpVolume', animationChannels: ['crankcase-pressure'], }, { id: 'cooling-fins', name: 'Cooling fins', kind: 'part', description: 'External ribs increasing convective area around the hot cylinder.', engineeringRole: 'Removes heat without a liquid coolant circuit on small engines.', materialHint: 'dark brushed aluminium edges', labelAnchor: [-0.55, 0.48, 0], explodedOffset: [-0.25, 0, 0], replacementNode: 'CoolingFins', animationChannels: [], }, ], }, { id: 'two-stroke-moving-group', name: 'Crank and piston group', kind: 'assembly', description: 'Lightweight piston and crankshaft provide both compression and pumping action.', engineeringRole: 'Couples cylinder pressure to output torque and modulates crankcase volume.', materialHint: 'aluminium piston, steel rod and crank', labelAnchor: [0.2, -0.08, 0], explodedOffset: [0.42, 0, 0], replacementNode: 'CrankAndPistonGroup', animationChannels: ['crank-rotation', 'piston-reciprocation', 'rod-swing'], children: [ { id: 'two-stroke-piston', name: 'Deflector piston', kind: 'part', description: 'Sliding piston crown shaped to guide incoming mixture away from the exhaust stream.', engineeringRole: 'Seals the chamber and exposes ports at controlled crank angles.', materialHint: 'bright aluminium with carbon-dark crown', labelAnchor: [0, 0.27, 0.03], explodedOffset: [0.45, 0.08, 0], replacementNode: 'TwoStrokePiston', animationChannels: ['piston-reciprocation'], }, { id: 'two-stroke-rod', name: 'Connecting rod', kind: 'part', description: 'Short rod between piston pin and crank throw.', engineeringRole: 'Transmits alternating pressure and inertia loads at high rotational speed.', materialHint: 'polished forged steel', labelAnchor: [0.16, -0.15, 0], explodedOffset: [0.55, 0, 0], replacementNode: 'TwoStrokeConnectingRod', animationChannels: ['rod-swing'], }, { id: 'two-stroke-crankshaft', name: 'Crankshaft and flywheel', kind: 'part', description: 'Compact crankshaft with flywheel mass and sealed crank webs.', engineeringRole: 'Creates the pumping volume change and stores energy between power pulses.', materialHint: 'dark steel with machined rim', labelAnchor: [0, -0.62, 0], explodedOffset: [0.72, -0.05, 0], replacementNode: 'TwoStrokeCrankshaft', animationChannels: ['crank-rotation'], }, ], }, { id: 'port-and-flow-system', name: 'Ports and charge flow', kind: 'assembly', description: 'Intake reed, transfer passage, and exhaust port coordinate gas exchange.', engineeringRole: 'Controls scavenging without poppet valves or a dedicated camshaft.', materialHint: 'transparent blue and amber flow ribbons', labelAnchor: [0, 0.42, 0.25], explodedOffset: [0, 0.18, 0.35], replacementNode: 'PortAndFlowSystem', animationChannels: ['intake-flow', 'transfer-flow', 'exhaust-flow'], children: [ { id: 'reed-intake', name: 'Reed intake valve', kind: 'part', description: 'Flexible one-way reed admitting mixture into the crankcase when pressure drops.', engineeringRole: 'Prevents reverse flow from crankcase back into the carburettor.', materialHint: 'dark composite petals with blue highlight', labelAnchor: [-0.56, -0.22, 0], explodedOffset: [-0.48, 0, 0], replacementNode: 'ReedIntakeValve', animationChannels: ['reed-flutter'], }, { id: 'transfer-port', name: 'Transfer port', kind: 'part', description: 'Curved passage carrying compressed mixture from crankcase to cylinder.', engineeringRole: 'Directs fresh charge upward to scavenge exhaust without excessive short-circuiting.', materialHint: 'transparent blue flow channel', labelAnchor: [-0.36, 0.12, 0.12], explodedOffset: [-0.32, 0.12, 0.24], replacementNode: 'TransferPort', animationChannels: ['transfer-flow'], }, { id: 'exhaust-port', name: 'Exhaust port', kind: 'part', description: 'Window uncovered before transfer opens to release combustion products.', engineeringRole: 'Sets blowdown timing and strongly influences tuned-pipe performance.', materialHint: 'heat-stained amber port', labelAnchor: [0.5, 0.18, 0], explodedOffset: [0.45, 0.08, 0], replacementNode: 'ExhaustPort', animationChannels: ['exhaust-flow'], }, { id: 'spark-plug-two-stroke', name: 'Spark plug', kind: 'part', description: 'Ignites compressed mixture near top dead centre every crank revolution.', engineeringRole: 'Provides repeatable spark timing for one power event per revolution.', materialHint: 'white ceramic with amber emissive tip', labelAnchor: [0, 0.82, 0.1], explodedOffset: [0, 0.42, 0.22], replacementNode: 'TwoStrokeSparkPlug', animationChannels: ['spark-event'], }, ], }, ], labels: [ { partId: 'transfer-port', text: 'Transfer port refills the cylinder', position: [-0.52, 0.22, 0.34], priority: 'primary' }, { partId: 'exhaust-port', text: 'Exhaust opens first for blowdown', position: [0.64, 0.3, 0.2], priority: 'primary' }, { partId: 'crankcase-pump', text: 'Crankcase acts as a pump', position: [0, -0.52, 0.34], priority: 'secondary' }, { partId: 'reed-intake', text: 'Reed prevents reverse flow', position: [-0.76, -0.16, 0.18], priority: 'detail' }, ], cameraPresets: makeCameraPresets(3.9, [0, 0.05, 0], { id: 'port-window', label: 'Port Window', position: [1.25, 0.55, 1.55], target: [0, 0.18, 0.02], description: 'Close-up showing piston-controlled exhaust and transfer port timing.', }), guidedTour: [ { id: 'one-revolution-cycle', title: 'One firing cycle per revolution', body: 'The piston uncovers ports near bottom dead centre and compresses the next charge on the way up.', cameraPresetId: 'isometric', highlightedPartIds: ['two-stroke-piston', 'two-stroke-crankshaft'], durationSeconds: 6, animationTimeScale: 0.7, setExplode: 0, }, { id: 'crankcase-compression', title: 'Crankcase compression', body: 'As the piston descends, crankcase volume shrinks and the fresh mixture is pressurized.', cameraPresetId: 'front', highlightedPartIds: ['crankcase-pump', 'two-stroke-piston', 'reed-intake'], durationSeconds: 6, animationTimeScale: 0.55, setExplode: 0.1, crossSection: { axis: 'z', offset: 0 }, }, { id: 'scavenging', title: 'Scavenging interval', body: 'The exhaust port opens for blowdown, then transfer ports direct fresh mixture into the cylinder.', cameraPresetId: 'port-window', highlightedPartIds: ['transfer-port', 'exhaust-port', 'two-stroke-piston'], durationSeconds: 7, animationTimeScale: 0.45, setExplode: 0.16, }, { id: 'reed-action', title: 'Intake reed timing', body: 'When the piston rises and crankcase pressure drops, the reed opens and admits the next charge.', cameraPresetId: 'left', highlightedPartIds: ['reed-intake', 'crankcase-pump'], durationSeconds: 5, animationTimeScale: 0.6, setExplode: 0.22, }, ], animationModel: { nominalRpm: 3000, cycleSecondsAtNominal: 0.02, loopMode: 'continuous', stepCount: 4, primaryDriver: 'crank-angle-degrees', engineeringNotes: 'Use a 360 degree cycle. Flow opacity windows should overlap around bottom dead centre to show realistic scavenging rather than isolated events.', channels: [ { id: 'crank-rotation', label: 'Crankshaft rotation', targetPartIds: ['two-stroke-crankshaft'], transform: 'rotation', driver: 'crank angle θ', expression: 'rotate crank and flywheel 0–360° per cycle', phaseDeg: 0, notes: 'Flywheel mass should visually smooth the one-cylinder firing pulses.', }, { id: 'piston-reciprocation', label: 'Piston reciprocation', targetPartIds: ['two-stroke-piston'], transform: 'translation', driver: 'crank-slider relation', expression: 'single up-down stroke for each 360° crank revolution', phaseDeg: 0, notes: 'Port openings are visible when piston skirt clears their top edges.', }, { id: 'rod-swing', label: 'Connecting rod swing', targetPartIds: ['two-stroke-rod'], transform: 'oscillation', driver: 'pin constraints', expression: 'orient between crank pin and piston pin', phaseDeg: 0, notes: 'Rod angle demonstrates side thrust near mid-stroke.', }, { id: 'reed-flutter', label: 'Reed valve flutter', targetPartIds: ['reed-intake'], transform: 'deformation', driver: 'crankcase pressure', expression: 'open during rising piston interval, close during descending compression interval', phaseDeg: 210, notes: 'Use small angular bend at reed tip, not full rigid rotation.', }, { id: 'transfer-flow', label: 'Transfer flow', targetPartIds: ['transfer-port'], transform: 'flow', driver: 'port uncovered and crankcase pressure high', expression: 'blue flow opacity peaks from 115° to 250° crank angle', phaseDeg: 115, notes: 'Direction should curve upward toward the cylinder head.', }, { id: 'exhaust-flow', label: 'Exhaust flow', targetPartIds: ['exhaust-port'], transform: 'flow', driver: 'exhaust port uncovered', expression: 'amber flow begins before transfer flow and fades after piston covers port', phaseDeg: 95, notes: 'Shows blowdown leading the transfer event.', }, { id: 'spark-event', label: 'Spark event', targetPartIds: ['spark-plug-two-stroke'], transform: 'material', driver: 'ignition timing', expression: 'brief emissive pulse near 350° before top dead centre', phaseDeg: 350, notes: 'Pulse occurs once every revolution.', }, { id: 'crankcase-pressure', label: 'Crankcase pressure indicator', targetPartIds: ['crankcase-pump'], transform: 'material', driver: 'crankcase volume', expression: 'blue intensity rises as piston descends and crankcase volume shrinks', phaseDeg: 90, notes: 'Pressure volume is a teaching effect, not a solid component.', }, ], }, explodedView: { defaultDistance: 0.3, maxDistance: 1, groups: [ { id: 'flow-passages', label: 'Flow passages', partIds: ['reed-intake', 'transfer-port', 'exhaust-port'], axis: 'x', direction: 1, order: 1, reason: 'Separates the port timing elements from the cylinder wall.', }, { id: 'moving-group', label: 'Piston and crank', partIds: ['two-stroke-piston', 'two-stroke-rod', 'two-stroke-crankshaft'], axis: 'x', direction: 1, order: 2, reason: 'Reveals how the piston simultaneously drives torque and crankcase pumping.', }, { id: 'spark-top', label: 'Ignition', partIds: ['spark-plug-two-stroke'], axis: 'y', direction: 1, order: 3, reason: 'Lifts the plug clear of the cylinder head for the ignition callout.', }, ], }, crossSection: { defaultAxis: 'z', recommendedPlanes: [ { id: 'ports-centreline', label: 'Port centreline', axis: 'z', offset: 0, description: 'Cuts through transfer and exhaust ports to show uncovering by the piston skirt.', }, { id: 'crankcase-volume', label: 'Crankcase pump', axis: 'y', offset: -0.35, description: 'Exposes the sealed pumping volume below the piston.', }, ], }, thumbnail: makeThumbnailStrategy( ['ported-cylinder', 'cooling-fins', 'two-stroke-crankshaft'], ['transfer-port', 'exhaust-port', 'reed-intake'], 'Use a compact finned silhouette and glowing port windows to distinguish it from the four-stroke card.', ), assetReplacement: { proceduralBlueprintId: 'two-stroke-engine', preferredGlbPath: 'src/assets/machines/two-stroke-engine/two-stroke-engine.glb', rootNodeName: 'TwoStrokeEngine', requiredNamedNodes: [ 'PortedCylinder', 'CrankcasePumpVolume', 'TwoStrokePiston', 'TwoStrokeConnectingRod', 'TwoStrokeCrankshaft', 'TransferPort', 'ExhaustPort', 'TwoStrokeSparkPlug', ], optionalNamedNodes: ['CoolingFins', 'ReedIntakeValve', 'CarburettorStub', 'ExpansionChamberStub'], materialSlots: ['cast-aluminium', 'machined-steel', 'flow-blue', 'flow-amber', 'spark-emissive', 'carbon-dark'], coordinateSystem: 'Y up, crankshaft along X, cylinder axis along Y, exhaust port on positive X side for default labels.', replacementInstructions: 'Preserve port node names as separate selectable meshes. The piston must move far enough to visibly uncover the upper edges of the transfer and exhaust ports.', }, relatedMachines: ['four-stroke-petrol-engine', 'diesel-engine', 'slider-crank'], }, { machineId: 'diesel-engine', slugAliases: ['compression-ignition-engine', 'four-stroke-diesel-engine'], title: 'Diesel Engine', category: 'Engines', difficulty: 'Intermediate', complexityScore: 5, registryKeywords: ['diesel', 'compression ignition', 'injector', 'fuel rail', 'high compression', 'glow plug'], oneParagraphDescription: 'A diesel engine uses high compression temperature to ignite atomized fuel injected directly into the cylinder rather than relying on a spark. The diagrammatic assembly builds on the four-stroke crank-slider cycle while emphasizing the injector, high-pressure rail, stronger piston bowl, and compression-ignition timing.', learningObjectives: [ 'Contrast spark ignition and compression ignition.', 'Explain why diesel engines use higher compression ratios and robust components.', 'Identify injector spray timing during the end of compression.', 'Relate torque characteristics to slower combustion and higher expansion pressure.', ], facts: [ { label: 'Compression ratio', value: '14:1–22:1', details: 'High compression heats air enough for fuel auto-ignition after injection.', }, { label: 'Typical speed', value: '600–4500 rpm', details: 'Heavy-duty diesels run slower than many petrol engines but produce high torque.', }, { label: 'Ignition system', value: 'Compression ignition', details: 'No spark plug is required during normal hot operation; glow plugs assist cold starts.', }, { label: 'Efficiency', value: '35–45% brake thermal', details: 'Lean operation and high expansion ratios improve practical efficiency.', }, { label: 'Applications', value: 'Trucks, ships, generators, heavy equipment', details: 'Preferred where fuel economy, durability, and torque are primary requirements.', }, ], componentTree: [ { id: 'diesel-structure', name: 'Reinforced engine structure', kind: 'assembly', description: 'Heavy block, head, and bearing structure sized for high cylinder pressures.', engineeringRole: 'Maintains sealing and crank alignment under greater peak combustion load than petrol engines.', materialHint: 'dark cast iron with machined aluminium cut faces', labelAnchor: [0, 0.15, 0], explodedOffset: [0, -0.22, 0], replacementNode: 'DieselStructure', animationChannels: [], children: [ { id: 'diesel-block', name: 'Diesel block', kind: 'part', description: 'Deep-skirt casting with robust main bearing supports.', engineeringRole: 'Resists high combustion pressure and crankshaft bending loads.', materialHint: 'cast iron', labelAnchor: [0, -0.18, 0], explodedOffset: [0, -0.45, 0], replacementNode: 'DieselBlock', animationChannels: [], }, { id: 'diesel-cylinder-head', name: 'Cylinder head', kind: 'part', description: 'High-pressure head containing valve seats, injector bore, and cooling passages.', engineeringRole: 'Clamps the fire deck and positions the injector at the chamber centre.', materialHint: 'cast iron or aluminium with cool cutaway faces', labelAnchor: [0, 0.92, 0], explodedOffset: [0, 0.52, 0], replacementNode: 'DieselCylinderHead', animationChannels: [], }, { id: 'diesel-coolant-jacket', name: 'Coolant jacket', kind: 'effect', description: 'Transparent coolant volume surrounding the head bridge and cylinder wall.', engineeringRole: 'Controls thermal stress around injector and valve seat hot spots.', materialHint: 'transparent blue', labelAnchor: [-0.5, 0.35, 0], explodedOffset: [-0.24, 0.08, 0], replacementNode: 'DieselCoolantJacket', animationChannels: ['coolant-flow'], }, ], }, { id: 'diesel-reciprocating-group', name: 'High-compression crank group', kind: 'assembly', description: 'Piston bowl, heavy rod, crankshaft, and flywheel convert diesel pressure to torque.', engineeringRole: 'Survives high compression and spreads power pulses into smooth shaft rotation.', materialHint: 'forged steel and aluminium', labelAnchor: [0.16, -0.08, 0], explodedOffset: [0.4, 0, 0], replacementNode: 'DieselReciprocatingGroup', animationChannels: ['crank-rotation', 'piston-reciprocation', 'rod-swing'], children: [ { id: 'diesel-piston-bowl', name: 'Bowl-in-piston crown', kind: 'part', description: 'Concave piston crown that shapes air swirl and fuel spray mixing.', engineeringRole: 'Creates controlled turbulence and contains the combustion plume.', materialHint: 'aluminium with dark thermal barrier crown', labelAnchor: [0, 0.35, 0], explodedOffset: [0.42, 0.1, 0], replacementNode: 'DieselPistonBowl', animationChannels: ['piston-reciprocation'], }, { id: 'diesel-connecting-rod', name: 'Heavy connecting rod', kind: 'part', description: 'Large-section rod with strengthened big end.', engineeringRole: 'Carries high compression and combustion loads to the crank throw.', materialHint: 'forged steel', labelAnchor: [0.18, -0.18, 0], explodedOffset: [0.58, 0, 0], replacementNode: 'DieselConnectingRod', animationChannels: ['rod-swing'], }, { id: 'diesel-crankshaft', name: 'Diesel crankshaft', kind: 'part', description: 'Stiff crankshaft with large journals and counterweights.', engineeringRole: 'Transmits high torque at moderate speed while limiting torsional vibration.', materialHint: 'dark forged steel', labelAnchor: [0, -0.72, 0], explodedOffset: [0.72, -0.05, 0], replacementNode: 'DieselCrankshaft', animationChannels: ['crank-rotation'], }, { id: 'diesel-flywheel', name: 'Large flywheel', kind: 'part', description: 'High-inertia disc attached to the crankshaft output.', engineeringRole: 'Smooths compression pulses and helps carry the engine through starting.', materialHint: 'cast iron rim', labelAnchor: [0.72, -0.72, 0], explodedOffset: [0.96, -0.05, 0], replacementNode: 'DieselFlywheel', animationChannels: ['crank-rotation'], }, ], }, { id: 'diesel-air-fuel-system', name: 'Air and high-pressure fuel system', kind: 'assembly', description: 'Valves, injector, fuel rail, and glow plug manage air breathing and fuel delivery.', engineeringRole: 'Admits air, compresses it, injects fuel near TDC, and evacuates exhaust gas.', materialHint: 'steel, brass, ceramic, and translucent flow effects', labelAnchor: [0, 1.08, 0], explodedOffset: [0, 0.44, 0.3], replacementNode: 'DieselAirFuelSystem', animationChannels: ['injector-pulse', 'intake-valve-lift', 'exhaust-valve-lift', 'fuel-spray'], children: [ { id: 'diesel-injector', name: 'High-pressure injector', kind: 'part', description: 'Precision nozzle that atomizes diesel fuel into the hot compressed air.', engineeringRole: 'Controls injection timing, spray pattern, and fuel quantity.', materialHint: 'polished steel with amber spray cone', labelAnchor: [0, 1.02, 0.12], explodedOffset: [0, 0.55, 0.36], replacementNode: 'DieselInjector', animationChannels: ['injector-pulse', 'fuel-spray'], }, { id: 'common-rail', name: 'Common rail', kind: 'part', description: 'High-pressure accumulator feeding the injector.', engineeringRole: 'Decouples pressure generation from injection timing for precise metering.', materialHint: 'brushed steel tube with warm fuel line', labelAnchor: [-0.52, 1.1, 0], explodedOffset: [-0.5, 0.34, 0.12], replacementNode: 'CommonRail', animationChannels: ['fuel-pressure-pulse'], }, { id: 'diesel-intake-valve', name: 'Intake valve', kind: 'part', description: 'Valve admitting only air during the intake stroke.', engineeringRole: 'Allows unthrottled air charge for lean diesel operation.', materialHint: 'cool steel', labelAnchor: [-0.18, 0.72, 0.08], explodedOffset: [-0.2, 0.34, 0.28], replacementNode: 'DieselIntakeValve', animationChannels: ['intake-valve-lift'], }, { id: 'diesel-exhaust-valve', name: 'Exhaust valve', kind: 'part', description: 'Heat-resistant valve that releases combustion products.', engineeringRole: 'Opens under high thermal load and directs exhaust toward aftertreatment or turbocharging.', materialHint: 'heat-stained nickel alloy', labelAnchor: [0.18, 0.72, 0.08], explodedOffset: [0.2, 0.34, 0.28], replacementNode: 'DieselExhaustValve', animationChannels: ['exhaust-valve-lift'], }, { id: 'glow-plug', name: 'Glow plug', kind: 'part', description: 'Small heater that aids cold starting by warming the chamber.', engineeringRole: 'Improves ignition reliability when metal and intake air are cold.', materialHint: 'ceramic insulator with subtle red emissive tip', labelAnchor: [0.22, 0.98, 0.1], explodedOffset: [0.22, 0.48, 0.35], replacementNode: 'GlowPlug', animationChannels: ['glow-plug-heat'], }, ], }, ], labels: [ { partId: 'diesel-injector', text: 'Fuel injected into compressed hot air', position: [0.08, 1.18, 0.34], priority: 'primary' }, { partId: 'diesel-piston-bowl', text: 'Bowl shapes swirl and spray mixing', position: [0.18, 0.45, 0.32], priority: 'primary' }, { partId: 'common-rail', text: 'Common rail stores injection pressure', position: [-0.72, 1.24, 0.2], priority: 'secondary' }, { partId: 'diesel-crankshaft', text: 'Large journals handle high torque', position: [0.1, -0.86, 0.28], priority: 'detail' }, ], cameraPresets: makeCameraPresets(4.4, [0, 0.14, 0], { id: 'injector-spray', label: 'Injector Spray', position: [1.05, 1.35, 1.8], target: [0, 0.72, 0], description: 'Focused chamber view showing injector, piston bowl, and valves.', }), guidedTour: [ { id: 'diesel-cycle', title: 'Air first, fuel later', body: 'The diesel cycle compresses air alone, then injects fuel when temperature and pressure are high.', cameraPresetId: 'isometric', highlightedPartIds: ['diesel-piston-bowl', 'diesel-injector', 'diesel-crankshaft'], durationSeconds: 7, animationTimeScale: 0.65, setExplode: 0, }, { id: 'compression-ignition', title: 'Compression ignition', body: 'Near top dead centre, the injector sprays fuel into hot compressed air rather than using a spark.', cameraPresetId: 'injector-spray', highlightedPartIds: ['diesel-injector', 'diesel-piston-bowl', 'common-rail'], durationSeconds: 7, animationTimeScale: 0.45, setExplode: 0.12, crossSection: { axis: 'z', offset: 0 }, }, { id: 'robust-bottom-end', title: 'Stronger bottom end', body: 'High peak pressure requires a heavy rod, stiff crankshaft, and robust block structure.', cameraPresetId: 'right', highlightedPartIds: ['diesel-connecting-rod', 'diesel-crankshaft', 'diesel-block'], durationSeconds: 6, animationTimeScale: 0.55, setExplode: 0.24, }, { id: 'breathing', title: 'Air breathing and exhaust', body: 'The intake valve admits air only; the exhaust valve later releases high-energy gases.', cameraPresetId: 'front', highlightedPartIds: ['diesel-intake-valve', 'diesel-exhaust-valve'], durationSeconds: 5, animationTimeScale: 0.7, setExplode: 0.16, }, ], animationModel: { nominalRpm: 900, cycleSecondsAtNominal: 0.133, loopMode: 'continuous', stepCount: 4, primaryDriver: 'crank-angle-degrees', engineeringNotes: 'Use the same 720 degree mechanical rhythm as a four-stroke petrol engine, but replace spark timing with injector pulse and richer pressure visualization near TDC.', channels: [ { id: 'crank-rotation', label: 'Crankshaft and flywheel rotation', targetPartIds: ['diesel-crankshaft', 'diesel-flywheel'], transform: 'rotation', driver: 'crank angle θ', expression: 'rotate 0–720° per full four-stroke cycle', phaseDeg: 0, notes: 'Moderate nominal rpm communicates heavy-duty operation.', }, { id: 'piston-reciprocation', label: 'High compression piston motion', targetPartIds: ['diesel-piston-bowl'], transform: 'translation', driver: 'crank-slider relation', expression: 'same crank-slider motion as petrol engine with shorter clearance at TDC', phaseDeg: 0, notes: 'Visual clearance volume should be visibly small.', }, { id: 'rod-swing', label: 'Rod angularity', targetPartIds: ['diesel-connecting-rod'], transform: 'oscillation', driver: 'piston and crank pin constraints', expression: 'orient rod between piston pin and crank throw', phaseDeg: 0, notes: 'Big-end bearing should stay concentric with crank throw.', }, { id: 'injector-pulse', label: 'Injector needle pulse', targetPartIds: ['diesel-injector'], transform: 'material', driver: 'injection timing', expression: 'short amber pulse centred around 700° crank angle', phaseDeg: 700, notes: 'For teaching, render pilot-main-post pulses as three close opacity peaks when time scale is slow.', }, { id: 'fuel-spray', label: 'Fuel spray cone', targetPartIds: ['diesel-injector'], transform: 'flow', driver: 'injector pulse', expression: 'expand conical amber particle fan into piston bowl during injection', phaseDeg: 700, notes: 'Spray should fade before exhaust event.', }, { id: 'fuel-pressure-pulse', label: 'Rail pressure pulse', targetPartIds: ['common-rail'], transform: 'material', driver: 'injection event', expression: 'subtle warm travelling highlight from rail to injector before fuel spray', phaseDeg: 690, notes: 'Keeps high-pressure system legible.', }, { id: 'intake-valve-lift', label: 'Intake valve lift', targetPartIds: ['diesel-intake-valve'], transform: 'translation', driver: 'cam lobe', expression: 'smooth opening during intake stroke; flow is blue air only', phaseDeg: 340, notes: 'Diesel intake is unthrottled in the teaching model.', }, { id: 'exhaust-valve-lift', label: 'Exhaust valve lift', targetPartIds: ['diesel-exhaust-valve'], transform: 'translation', driver: 'cam lobe', expression: 'smooth opening around exhaust stroke', phaseDeg: 130, notes: 'Amber exhaust opacity increases after combustion.', }, { id: 'glow-plug-heat', label: 'Glow plug heat', targetPartIds: ['glow-plug'], transform: 'material', driver: 'cold-start demonstration toggle', expression: 'low red emissive glow when cold-start overlay is enabled', phaseDeg: 0, notes: 'Do not pulse continuously during normal running mode.', }, { id: 'coolant-flow', label: 'Coolant circulation', targetPartIds: ['diesel-coolant-jacket'], transform: 'flow', driver: 'running state', expression: 'slow blue circulation around head bridge and cylinder wall', phaseDeg: 0, notes: 'Useful with cross-section enabled.', }, ], }, explodedView: { defaultDistance: 0.32, maxDistance: 1.12, groups: [ { id: 'injector-up', label: 'Injector and fuel rail', partIds: ['diesel-injector', 'common-rail', 'glow-plug'], axis: 'y', direction: 1, order: 1, reason: 'Shows the high-pressure fuel system entering from the top of the chamber.', }, { id: 'head-and-valves', label: 'Head and valves', partIds: ['diesel-cylinder-head', 'diesel-intake-valve', 'diesel-exhaust-valve'], axis: 'y', direction: 1, order: 2, reason: 'Reveals air-only intake and exhaust valve placement around the injector.', }, { id: 'heavy-bottom-end', label: 'Heavy bottom end', partIds: ['diesel-piston-bowl', 'diesel-connecting-rod', 'diesel-crankshaft', 'diesel-flywheel'], axis: 'x', direction: 1, order: 3, reason: 'Separates robust moving parts from the block for load-path explanation.', }, ], }, crossSection: { defaultAxis: 'z', recommendedPlanes: [ { id: 'injector-bowl', label: 'Injector and piston bowl', axis: 'z', offset: 0, description: 'Cuts through the spray plume, piston bowl, and valves.', }, { id: 'main-bearing', label: 'Main bearing line', axis: 'y', offset: -0.68, description: 'Exposes large crank journals and deep-skirt block structure.', }, ], }, thumbnail: makeThumbnailStrategy( ['diesel-block', 'diesel-cylinder-head', 'diesel-flywheel'], ['diesel-injector', 'common-rail', 'diesel-piston-bowl'], 'Render with a strong vertical injector silhouette and warm spray cone over a dark heavy block.', ), assetReplacement: { proceduralBlueprintId: 'diesel-engine', preferredGlbPath: 'src/assets/machines/diesel-engine/diesel-engine.glb', rootNodeName: 'DieselEngine', requiredNamedNodes: [ 'DieselBlock', 'DieselCylinderHead', 'DieselPistonBowl', 'DieselConnectingRod', 'DieselCrankshaft', 'DieselFlywheel', 'DieselInjector', 'CommonRail', 'DieselIntakeValve', 'DieselExhaustValve', ], optionalNamedNodes: ['DieselCoolantJacket', 'GlowPlug', 'TurboFeedStub', 'FuelLines'], materialSlots: ['cast-iron', 'machined-steel', 'aluminium', 'flow-blue', 'flow-amber', 'heat-red'], coordinateSystem: 'Y up, crankshaft along X, cylinder axis along Y, injector centered above bore at positive Y.', replacementInstructions: 'Separate injector, rail, spray cone, piston bowl, valves, and crank components into named nodes so animation channels can bind without machine-specific viewer code.', }, relatedMachines: ['four-stroke-petrol-engine', 'turbocharger', 'piston-pump'], }, { machineId: 'v8-engine', slugAliases: ['v-eight-engine', 'v8-petrol-engine', 'eight-cylinder-v-engine'], title: 'V8 Engine', category: 'Engines', difficulty: 'Advanced', complexityScore: 8, registryKeywords: ['v8', 'firing order', 'cross-plane crank', 'cylinder banks', 'intake manifold'], oneParagraphDescription: 'A V8 engine packages eight four-stroke cylinders into two angled banks sharing a crankshaft. The procedural model uses grouped cylinders, phased pistons, exhaust pulse highlights, and a selectable firing-order overlay so users can understand bank angle, crank throws, firing intervals, and the balance advantages of multi-cylinder engines.', learningObjectives: [ 'Identify the left and right cylinder banks and shared crankcase.', 'Follow an eight-event firing order through a 720° cycle.', 'Explain how crank throws phase piston motion and exhaust pulses.', 'Compare the V8 layout to a single-cylinder four-stroke engine.', ], facts: [ { label: 'Cylinder layout', value: 'Two banks of four', details: 'Most V8s use a 90° bank angle for packaging and balance.', }, { label: 'Cycle', value: '8 firing events / 720°', details: 'With even firing, one cylinder fires every 90° of crank rotation.', }, { label: 'Typical speed', value: '600–7000 rpm', details: 'Operating range varies from truck engines to high-performance automotive engines.', }, { label: 'Crank styles', value: 'Cross-plane or flat-plane', details: 'Cross-plane designs improve smoothness; flat-plane designs reduce rotating mass and alter exhaust timing.', }, { label: 'Applications', value: 'Performance cars, trucks, marine engines', details: 'Used where high power density and smooth torque delivery are desirable.', }, ], componentTree: [ { id: 'v8-crankcase', name: 'V8 crankcase and banks', kind: 'assembly', description: 'Shared crankcase with two banks arranged in a V around the crankshaft.', engineeringRole: 'Supports eight cylinders while keeping overall length shorter than an inline-eight.', materialHint: 'dark cast aluminium with machined deck planes', labelAnchor: [0, 0.05, 0], explodedOffset: [0, -0.25, 0], replacementNode: 'V8Crankcase', animationChannels: [], children: [ { id: 'left-cylinder-bank', name: 'Left cylinder bank', kind: 'assembly', description: 'Four cylinders angled to the left side of the crankshaft centreline.', engineeringRole: 'Houses cylinders 1, 3, 5, and 7 in the teaching firing-order convention.', materialHint: 'satin aluminium left deck', labelAnchor: [-0.42, 0.55, 0], explodedOffset: [-0.52, 0.2, 0], replacementNode: 'LeftCylinderBank', animationChannels: [], }, { id: 'right-cylinder-bank', name: 'Right cylinder bank', kind: 'assembly', description: 'Four cylinders angled to the right side of the crankshaft centreline.', engineeringRole: 'Houses cylinders 2, 4, 6, and 8 in the teaching firing-order convention.', materialHint: 'satin aluminium right deck', labelAnchor: [0.42, 0.55, 0], explodedOffset: [0.52, 0.2, 0], replacementNode: 'RightCylinderBank', animationChannels: [], }, { id: 'v8-intake-manifold', name: 'Central intake manifold', kind: 'part', description: 'Plenum and runners feeding both cylinder banks from the valley.', engineeringRole: 'Distributes air evenly and uses runner geometry to tune torque.', materialHint: 'matte dark composite with blue flow accents', labelAnchor: [0, 1.05, 0], explodedOffset: [0, 0.55, 0], replacementNode: 'V8IntakeManifold', animationChannels: ['intake-pulse-flow'], }, ], }, { id: 'v8-rotating-assembly', name: 'Shared rotating assembly', kind: 'assembly', description: 'Cross-plane crankshaft, eight rods, and grouped pistons deliver phased power events.', engineeringRole: 'Combines eight cylinder pressure pulses into a single output torque.', materialHint: 'forged steel crank and aluminium piston banks', labelAnchor: [0, -0.45, 0], explodedOffset: [0, -0.2, 0.28], replacementNode: 'V8RotatingAssembly', animationChannels: ['v8-crank-rotation', 'v8-piston-bank-motion', 'firing-order-pulse'], children: [ { id: 'v8-crankshaft', name: 'Cross-plane crankshaft', kind: 'part', description: 'Shared crankshaft with throws arranged to phase eight pistons.', engineeringRole: 'Sets firing interval, balance characteristics, and exhaust pulse sequence.', materialHint: 'polished forged steel with blue throw markers', labelAnchor: [0, -0.72, 0], explodedOffset: [0, -0.46, 0.48], replacementNode: 'V8Crankshaft', animationChannels: ['v8-crank-rotation'], }, { id: 'left-piston-set', name: 'Left-bank piston set', kind: 'assembly', description: 'Four pistons and rods animated with the bank angle and crank phase offsets.', engineeringRole: 'Shows alternating compression and power strokes across one bank.', materialHint: 'aluminium pistons with left-bank blue highlights', labelAnchor: [-0.5, 0.25, 0.18], explodedOffset: [-0.72, 0.08, 0.28], replacementNode: 'LeftPistonSet', animationChannels: ['v8-piston-bank-motion', 'firing-order-pulse'], }, { id: 'right-piston-set', name: 'Right-bank piston set', kind: 'assembly', description: 'Four pistons and rods mirrored across the V angle.', engineeringRole: 'Demonstrates alternating bank contribution to smooth torque output.', materialHint: 'aluminium pistons with right-bank warm highlights', labelAnchor: [0.5, 0.25, 0.18], explodedOffset: [0.72, 0.08, 0.28], replacementNode: 'RightPistonSet', animationChannels: ['v8-piston-bank-motion', 'firing-order-pulse'], }, { id: 'v8-flywheel', name: 'Output flywheel', kind: 'part', description: 'Rotating mass at the output end of the crankshaft.', engineeringRole: 'Smooths torque ripple and provides drivetrain interface.', materialHint: 'dark steel disc', labelAnchor: [0, -0.72, 1.05], explodedOffset: [0, -0.1, 0.82], replacementNode: 'V8Flywheel', animationChannels: ['v8-crank-rotation'], }, ], }, { id: 'v8-valve-exhaust-system', name: 'Valve covers and exhaust headers', kind: 'assembly', description: 'Valve covers conceal the valve train while headers expose bank-to-bank pulse timing.', engineeringRole: 'Manages breathing and visualizes how firing order affects exhaust sound and scavenging.', materialHint: 'brushed covers, heat-stained tubular exhausts', labelAnchor: [0, 0.82, 0], explodedOffset: [0, 0.32, 0], replacementNode: 'V8ValveExhaustSystem', animationChannels: ['valve-train-bank-motion', 'exhaust-pulse-flow'], children: [ { id: 'left-valve-cover', name: 'Left valve cover', kind: 'part', description: 'Cover over cam, rocker, or overhead valve hardware on the left bank.', engineeringRole: 'Protects valve train and contains oil mist.', materialHint: 'dark satin cover with cool edge highlight', labelAnchor: [-0.72, 0.9, 0], explodedOffset: [-0.62, 0.34, 0], replacementNode: 'LeftValveCover', animationChannels: ['valve-train-bank-motion'], }, { id: 'right-valve-cover', name: 'Right valve cover', kind: 'part', description: 'Mirrored cover over the right-bank valve train.', engineeringRole: 'Protects valve train and provides selectable bank context.', materialHint: 'dark satin cover with warm edge highlight', labelAnchor: [0.72, 0.9, 0], explodedOffset: [0.62, 0.34, 0], replacementNode: 'RightValveCover', animationChannels: ['valve-train-bank-motion'], }, { id: 'left-exhaust-header', name: 'Left exhaust header', kind: 'part', description: 'Tubular runners collecting exhaust pulses from the left bank.', engineeringRole: 'Affects scavenging, sound, and heat rejection.', materialHint: 'heat-stained stainless tubes with amber pulse markers', labelAnchor: [-0.95, 0.2, 0], explodedOffset: [-0.85, 0.05, 0], replacementNode: 'LeftExhaustHeader', animationChannels: ['exhaust-pulse-flow'], }, { id: 'right-exhaust-header', name: 'Right exhaust header', kind: 'part', description: 'Tubular runners collecting exhaust pulses from the right bank.', engineeringRole: 'Shows bank-to-bank exhaust pulse alternation for the selected firing order.', materialHint: 'heat-stained stainless tubes with amber pulse markers', labelAnchor: [0.95, 0.2, 0], explodedOffset: [0.85, 0.05, 0], replacementNode: 'RightExhaustHeader', animationChannels: ['exhaust-pulse-flow'], }, { id: 'firing-order-overlay', name: 'Firing-order overlay', kind: 'effect', description: 'Numbered pulse markers that illuminate each cylinder in firing sequence.', engineeringRole: 'Connects crank angle, bank layout, and perceived smoothness.', materialHint: 'emissive blue and amber numbering', labelAnchor: [0, 1.35, 0], explodedOffset: [0, 0.75, 0], replacementNode: 'FiringOrderOverlay', animationChannels: ['firing-order-pulse'], }, ], }, ], labels: [ { partId: 'left-cylinder-bank', text: 'Four cylinders on the left bank', position: [-0.74, 0.66, 0.28], priority: 'primary' }, { partId: 'right-cylinder-bank', text: 'Four cylinders on the right bank', position: [0.74, 0.66, 0.28], priority: 'primary' }, { partId: 'v8-crankshaft', text: 'Shared crank phases all eight pistons', position: [0, -0.94, 0.32], priority: 'primary' }, { partId: 'firing-order-overlay', text: 'One firing event every 90°', position: [0, 1.5, 0.2], priority: 'secondary' }, ], cameraPresets: makeCameraPresets(6.1, [0, 0.25, 0], { id: 'bank-valley', label: 'Bank Valley', position: [1.8, 1.85, 2.35], target: [0, 0.72, 0], description: 'View into the intake valley and both cylinder banks.', }), guidedTour: [ { id: 'v-layout', title: 'Compact V layout', body: 'Two banks of four cylinders share one crankcase, creating a shorter package than an inline-eight.', cameraPresetId: 'front', highlightedPartIds: ['left-cylinder-bank', 'right-cylinder-bank', 'v8-crankcase'], durationSeconds: 7, animationTimeScale: 0.45, setExplode: 0.08, }, { id: 'shared-crank', title: 'One crankshaft, eight pistons', body: 'The shared crankshaft phases the left and right piston sets through their individual strokes.', cameraPresetId: 'right', highlightedPartIds: ['v8-crankshaft', 'left-piston-set', 'right-piston-set'], durationSeconds: 7, animationTimeScale: 0.55, setExplode: 0.18, crossSection: { axis: 'z', offset: 0 }, }, { id: 'firing-order', title: 'Firing order sequence', body: 'Pulse markers step through the eight cylinders so each firing event appears 90 degrees after the last.', cameraPresetId: 'top', highlightedPartIds: ['firing-order-overlay', 'left-cylinder-bank', 'right-cylinder-bank'], durationSeconds: 8, animationTimeScale: 0.35, setExplode: 0.1, }, { id: 'exhaust-pulses', title: 'Exhaust pulse routing', body: 'The header highlights show how bank phasing affects pulse spacing, sound, and scavenging.', cameraPresetId: 'back', highlightedPartIds: ['left-exhaust-header', 'right-exhaust-header'], durationSeconds: 6, animationTimeScale: 0.55, setExplode: 0.22, }, { id: 'intake-valley', title: 'Central intake distribution', body: 'A central plenum feeds runners to both banks, balancing packaging with airflow distribution.', cameraPresetId: 'bank-valley', highlightedPartIds: ['v8-intake-manifold'], durationSeconds: 5, animationTimeScale: 0.5, setExplode: 0.14, }, ], animationModel: { nominalRpm: 900, cycleSecondsAtNominal: 0.133, loopMode: 'continuous', stepCount: 8, primaryDriver: 'crank-angle-degrees-with-cylinder-phase-map', engineeringNotes: 'Use an eight-event 720 degree cycle. A default cross-plane teaching order of 1-8-4-3-6-5-7-2 gives clear alternating pulses without requiring exact manufacturer geometry.', channels: [ { id: 'v8-crank-rotation', label: 'Crankshaft rotation', targetPartIds: ['v8-crankshaft', 'v8-flywheel'], transform: 'rotation', driver: 'crank angle θ', expression: 'rotate 0–720° per complete four-stroke cycle', phaseDeg: 0, notes: 'All piston-bank channels derive from this master angle.', }, { id: 'v8-piston-bank-motion', label: 'Banked piston motion', targetPartIds: ['left-piston-set', 'right-piston-set'], transform: 'translation', driver: 'crank throw phase table', expression: 'each piston follows crank-slider motion rotated into its bank plane with phase offsets of 0°, 90°, 180°, and 270°', phaseDeg: 0, notes: 'Group animation can use instanced pistons when individual CAD assets are unavailable.', }, { id: 'firing-order-pulse', label: 'Firing order pulses', targetPartIds: ['firing-order-overlay', 'left-piston-set', 'right-piston-set'], transform: 'material', driver: 'cylinder firing table', expression: 'emissive pulse advances through 1-8-4-3-6-5-7-2 every 90°', phaseDeg: 0, notes: 'Pulse color alternates cool left-bank and warm right-bank for readability.', }, { id: 'valve-train-bank-motion', label: 'Bank valve-train rhythm', targetPartIds: ['left-valve-cover', 'right-valve-cover'], transform: 'oscillation', driver: 'cam phase abstraction', expression: 'subtle cover-transparent rocker motion at half crank speed for each bank', phaseDeg: 0, notes: 'Used as a diagrammatic cue when detailed rockers are not present.', }, { id: 'intake-pulse-flow', label: 'Intake runner pulses', targetPartIds: ['v8-intake-manifold'], transform: 'flow', driver: 'intake stroke table', expression: 'blue pulse travels from plenum to the cylinder currently on intake stroke', phaseDeg: 180, notes: 'Flow channel syncs with selected cylinder phase rather than all runners at once.', }, { id: 'exhaust-pulse-flow', label: 'Exhaust header pulses', targetPartIds: ['left-exhaust-header', 'right-exhaust-header'], transform: 'flow', driver: 'firing order table', expression: 'amber pulse follows each fired cylinder into its bank header', phaseDeg: 90, notes: 'Pulse spacing communicates firing order more clearly than constant flow.', }, ], }, explodedView: { defaultDistance: 0.36, maxDistance: 1.35, groups: [ { id: 'banks-outward', label: 'Cylinder banks', partIds: ['left-cylinder-bank', 'right-cylinder-bank', 'left-valve-cover', 'right-valve-cover'], axis: 'x', direction: 1, order: 1, reason: 'Opens the V layout and reveals the central crankcase.', }, { id: 'intake-up', label: 'Intake valley', partIds: ['v8-intake-manifold'], axis: 'y', direction: 1, order: 2, reason: 'Lifts the plenum to show how runners feed both banks.', }, { id: 'headers-outward', label: 'Exhaust headers', partIds: ['left-exhaust-header', 'right-exhaust-header'], axis: 'x', direction: 1, order: 3, reason: 'Separates headers from the banks for pulse-tracing callouts.', }, { id: 'rotating-down', label: 'Rotating assembly', partIds: ['v8-crankshaft', 'left-piston-set', 'right-piston-set', 'v8-flywheel'], axis: 'y', direction: -1, order: 4, reason: 'Pulls the crank group down to expose shared throw phasing.', }, ], }, crossSection: { defaultAxis: 'z', recommendedPlanes: [ { id: 'front-cylinder-pair', label: 'Front cylinder pair', axis: 'z', offset: 0.45, description: 'Cuts through one left and one right cylinder to compare bank geometry.', }, { id: 'crank-centreline', label: 'Crank centreline', axis: 'y', offset: -0.58, description: 'Exposes crank throws, counterweights, and flywheel connection.', }, ], }, thumbnail: makeThumbnailStrategy( ['v8-crankcase', 'left-cylinder-bank', 'right-cylinder-bank', 'v8-intake-manifold'], ['firing-order-overlay', 'left-exhaust-header', 'right-exhaust-header'], 'Use a wide heroic isometric angle with glowing alternating cylinder numbers to signal the firing-order feature.', ), assetReplacement: { proceduralBlueprintId: 'v8-engine', preferredGlbPath: 'src/assets/machines/v8-engine/v8-engine.glb', rootNodeName: 'V8Engine', requiredNamedNodes: [ 'V8Crankcase', 'LeftCylinderBank', 'RightCylinderBank', 'V8Crankshaft', 'LeftPistonSet', 'RightPistonSet', 'V8IntakeManifold', 'LeftExhaustHeader', 'RightExhaustHeader', ], optionalNamedNodes: ['LeftValveCover', 'RightValveCover', 'V8Flywheel', 'FiringOrderOverlay', 'AccessoryDrive'], materialSlots: ['cast-aluminium', 'machined-steel', 'rubber-dark', 'flow-blue', 'flow-amber', 'emissive-number'], coordinateSystem: 'Y up, crankshaft along Z or X is acceptable if the root provides normalized output-axis metadata; default procedural model uses Z length and Y height.', replacementInstructions: 'If individual cylinder meshes are supplied, name them Cylinder01 through Cylinder08 and keep the overlay table aligned with the 1-8-4-3-6-5-7-2 educational firing order.', }, relatedMachines: ['four-stroke-petrol-engine', 'diesel-engine', 'turbocharger'], }, { machineId: 'wankel-rotary-engine', slugAliases: ['wankel-engine', 'rotary-engine', 'epitrochoid-engine'], title: 'Wankel Rotary Engine', category: 'Engines', difficulty: 'Advanced', complexityScore: 7, registryKeywords: ['wankel', 'rotary', 'epitrochoid', 'apex seals', 'eccentric shaft', 'ports'], oneParagraphDescription: 'A Wankel rotary engine replaces reciprocating pistons with a triangular rotor orbiting inside an epitrochoid housing. The procedural visualization shows the rotor’s eccentric motion, three moving chambers, apex sealing, and port timing so users can understand how intake, compression, combustion, and exhaust occur without a crank-slider mechanism.', learningObjectives: [ 'Identify the rotor, eccentric shaft, apex seals, and epitrochoid housing.', 'Follow the three chambers through intake, compression, combustion, and exhaust.', 'Explain why the output shaft turns faster than the rotor orbit.', 'Recognize the sealing and heat-transfer challenges unique to rotary engines.', ], facts: [ { label: 'Moving chamber count', value: '3 per rotor', details: 'Each rotor face forms a chamber whose volume changes as the rotor orbits.', }, { label: 'Output relation', value: '3 shaft rotations per rotor rotation', details: 'The eccentric shaft completes three turns for one full rotor orientation cycle.', }, { label: 'Typical speed', value: '3000–9000 rpm', details: 'Rotary engines are smooth and compact but require careful thermal and sealing design.', }, { label: 'Patented', value: '1929', details: 'Felix Wankel developed the rotary combustion concept that later reached automotive production.', }, { label: 'Applications', value: 'Sports cars, aircraft prototypes, compact generators', details: 'Chosen for high power-to-size ratio and smooth rotation.', }, ], componentTree: [ { id: 'wankel-housing-assembly', name: 'Epitrochoid housing assembly', kind: 'assembly', description: 'Peanut-shaped housing, side plates, and ports define the rotor path and gas exchange.', engineeringRole: 'Forms the combustion chambers and provides the fixed sealing surface for apex seals.', materialHint: 'dark cast aluminium with polished inner trochoid surface', labelAnchor: [0, 0, 0], explodedOffset: [0, 0, -0.25], replacementNode: 'WankelHousingAssembly', animationChannels: [], children: [ { id: 'epitrochoid-housing', name: 'Epitrochoid housing', kind: 'part', description: 'Two-lobed chamber surface followed by the rotor apex seals.', engineeringRole: 'Controls chamber volume change and sealing contact path.', materialHint: 'brushed aluminium outside, polished chrome inner wall', labelAnchor: [0, 0.55, 0], explodedOffset: [0, 0.22, -0.35], replacementNode: 'EpitrochoidHousing', animationChannels: [], }, { id: 'front-side-plate', name: 'Front side plate', kind: 'part', description: 'Flat end plate sealing one side of the rotor cavity.', engineeringRole: 'Completes chamber sealing and carries side-seal contact.', materialHint: 'machined aluminium cut plate', labelAnchor: [0, 0, 0.28], explodedOffset: [0, 0, 0.58], replacementNode: 'FrontSidePlate', animationChannels: [], }, { id: 'intake-port-wankel', name: 'Intake port', kind: 'part', description: 'Port window opened and closed by the passing rotor flank.', engineeringRole: 'Admits fresh mixture as chamber volume expands.', materialHint: 'blue inset window', labelAnchor: [-0.72, -0.18, 0.05], explodedOffset: [-0.35, -0.08, 0.2], replacementNode: 'WankelIntakePort', animationChannels: ['intake-flow'], }, { id: 'exhaust-port-wankel', name: 'Exhaust port', kind: 'part', description: 'Port window releasing exhaust as a chamber approaches minimum volume.', engineeringRole: 'Times blowdown and exhaust evacuation without poppet valves.', materialHint: 'amber heat-stained window', labelAnchor: [0.72, -0.18, 0.05], explodedOffset: [0.35, -0.08, 0.2], replacementNode: 'WankelExhaustPort', animationChannels: ['exhaust-flow'], }, ], }, { id: 'wankel-rotor-assembly', name: 'Rotor and eccentric shaft', kind: 'assembly', description: 'Triangular rotor, apex seals, gear set, and eccentric output shaft.', engineeringRole: 'Creates changing chamber volumes while delivering smooth rotary output.', materialHint: 'warm anodized rotor, dark seals, polished shaft', labelAnchor: [0, 0, 0.12], explodedOffset: [0, 0, 0.42], replacementNode: 'WankelRotorAssembly', animationChannels: ['rotor-orbit', 'eccentric-shaft-rotation'], children: [ { id: 'triangular-rotor', name: 'Triangular rotor', kind: 'part', description: 'Curved triangular rotor whose three flanks act like piston faces.', engineeringRole: 'Changes chamber volume as it orbits eccentrically within the housing.', materialHint: 'warm satin metal with face numbers', labelAnchor: [0, 0.08, 0.18], explodedOffset: [0, 0, 0.62], replacementNode: 'TriangularRotor', animationChannels: ['rotor-orbit'], }, { id: 'apex-seals', name: 'Apex seals', kind: 'part', description: 'Sealing strips at each rotor apex sliding along the housing wall.', engineeringRole: 'Separate the three working chambers while tolerating heat and sliding wear.', materialHint: 'dark ceramic or carbon strips', labelAnchor: [0.52, 0.22, 0.22], explodedOffset: [0.15, 0.12, 0.72], replacementNode: 'ApexSeals', animationChannels: ['rotor-orbit'], }, { id: 'eccentric-shaft', name: 'Eccentric shaft', kind: 'part', description: 'Output shaft with offset lobe carrying the rotor bearing.', engineeringRole: 'Converts rotor orbit into output rotation through the internal gear relationship.', materialHint: 'polished hardened steel', labelAnchor: [0, -0.52, 0.08], explodedOffset: [0, -0.15, 0.72], replacementNode: 'EccentricShaft', animationChannels: ['eccentric-shaft-rotation'], }, { id: 'stationary-gear', name: 'Stationary gear', kind: 'part', description: 'Fixed gear meshing with rotor internal teeth to control orientation.', engineeringRole: 'Maintains rotor phasing so apexes follow the epitrochoid.', materialHint: 'blue steel gear teeth', labelAnchor: [-0.28, -0.35, 0.18], explodedOffset: [-0.14, -0.1, 0.74], replacementNode: 'StationaryGear', animationChannels: ['rotor-orbit'], }, ], }, { id: 'wankel-ignition-flow', name: 'Ignition and chamber flow', kind: 'assembly', description: 'Spark plugs and colored chamber overlays show where each face is in the four-stroke sequence.', engineeringRole: 'Makes simultaneous multi-chamber operation legible.', materialHint: 'transparent blue, amber, and warm emissive overlays', labelAnchor: [0, 0.72, 0.18], explodedOffset: [0, 0.35, 0.34], replacementNode: 'WankelIgnitionFlow', animationChannels: ['chamber-volume-color', 'spark-event'], children: [ { id: 'leading-spark-plug', name: 'Leading spark plug', kind: 'part', description: 'First plug initiating flame in the elongated rotary chamber.', engineeringRole: 'Begins combustion across a long, thin chamber.', materialHint: 'white ceramic with amber tip', labelAnchor: [0.15, 0.74, 0.16], explodedOffset: [0.08, 0.38, 0.48], replacementNode: 'LeadingSparkPlug', animationChannels: ['spark-event'], }, { id: 'trailing-spark-plug', name: 'Trailing spark plug', kind: 'part', description: 'Second plug completing burn in the stretched chamber shape.', engineeringRole: 'Improves combustion completeness in the long chamber.', materialHint: 'white ceramic with amber tip', labelAnchor: [0.42, 0.6, 0.16], explodedOffset: [0.2, 0.3, 0.48], replacementNode: 'TrailingSparkPlug', animationChannels: ['spark-event'], }, { id: 'chamber-overlays', name: 'Chamber phase overlays', kind: 'effect', description: 'Colored translucent regions representing intake, compression, power, and exhaust chambers.', engineeringRole: 'Teaches the cycle phases without hiding the rotor motion.', materialHint: 'transparent phase colors', labelAnchor: [0, 0.02, 0.26], explodedOffset: [0, 0, 0.85], replacementNode: 'ChamberOverlays', animationChannels: ['chamber-volume-color'], }, ], }, ], labels: [ { partId: 'triangular-rotor', text: 'Three rotor faces form moving chambers', position: [0, 0.15, 0.48], priority: 'primary' }, { partId: 'apex-seals', text: 'Apex seals separate the chambers', position: [0.66, 0.3, 0.42], priority: 'primary' }, { partId: 'eccentric-shaft', text: 'Eccentric shaft spins three times faster', position: [0, -0.7, 0.34], priority: 'secondary' }, { partId: 'intake-port-wankel', text: 'Ports replace poppet valves', position: [-0.88, -0.2, 0.28], priority: 'detail' }, ], cameraPresets: makeCameraPresets(4.1, [0, 0.02, 0.08], { id: 'rotor-cutaway', label: 'Rotor Cutaway', position: [0.95, 1.0, 2.25], target: [0, 0.05, 0.05], description: 'Close view of rotor, apex seals, chamber overlays, and side plate spacing.', }), guidedTour: [ { id: 'rotary-overview', title: 'No reciprocating piston', body: 'A triangular rotor orbits inside the epitrochoid housing, replacing the crank-slider mechanism.', cameraPresetId: 'isometric', highlightedPartIds: ['triangular-rotor', 'epitrochoid-housing', 'eccentric-shaft'], durationSeconds: 7, animationTimeScale: 0.45, setExplode: 0.08, }, { id: 'apex-sealing', title: 'Apex seals create chambers', body: 'Each apex must seal against the housing wall while sliding through a changing radius path.', cameraPresetId: 'rotor-cutaway', highlightedPartIds: ['apex-seals', 'epitrochoid-housing'], durationSeconds: 6, animationTimeScale: 0.3, setExplode: 0.12, crossSection: { axis: 'z', offset: 0 }, }, { id: 'three-chambers', title: 'Three phases at once', body: 'The colored overlays show different faces performing intake, compression, combustion, and exhaust simultaneously.', cameraPresetId: 'front', highlightedPartIds: ['chamber-overlays', 'triangular-rotor'], durationSeconds: 8, animationTimeScale: 0.35, setExplode: 0, }, { id: 'ports-and-spark', title: 'Port timing and twin plugs', body: 'Rotor motion opens ports, while leading and trailing plugs ignite the elongated chamber.', cameraPresetId: 'top', highlightedPartIds: ['intake-port-wankel', 'exhaust-port-wankel', 'leading-spark-plug', 'trailing-spark-plug'], durationSeconds: 7, animationTimeScale: 0.4, setExplode: 0.16, }, ], animationModel: { nominalRpm: 3000, cycleSecondsAtNominal: 0.02, loopMode: 'continuous', stepCount: 3, primaryDriver: 'eccentric-shaft-angle', engineeringNotes: 'Use a hypotrochoid-style approximation for rotor center orbit and counter-rotate rotor orientation at one third shaft speed so apexes remain visually tangent to the housing.', channels: [ { id: 'eccentric-shaft-rotation', label: 'Eccentric shaft rotation', targetPartIds: ['eccentric-shaft'], transform: 'rotation', driver: 'shaft angle θ', expression: 'rotate shaft 0–1080° while rotor orientation completes 360°', phaseDeg: 0, notes: 'The shaft is the master output and spins three times per rotor cycle.', }, { id: 'rotor-orbit', label: 'Rotor orbital motion', targetPartIds: ['triangular-rotor', 'apex-seals', 'stationary-gear'], transform: 'rotation', driver: 'eccentric shaft angle θ', expression: 'translate rotor center on eccentric circle and rotate body by -θ/3 plus gear phase', phaseDeg: 0, notes: 'Apex seals should appear to trace the housing wall without penetrating it.', }, { id: 'chamber-volume-color', label: 'Chamber phase color', targetPartIds: ['chamber-overlays'], transform: 'material', driver: 'rotor flank volume', expression: 'color each chamber blue for intake, pale for compression, amber for combustion, grey for exhaust based on angular sector', phaseDeg: 0, notes: 'Opacity should be low enough to keep rotor geometry visible.', }, { id: 'intake-flow', label: 'Intake port flow', targetPartIds: ['intake-port-wankel'], transform: 'flow', driver: 'chamber leading edge exposes intake port', expression: 'blue flow pulse enters expanding chamber during intake sector', phaseDeg: 210, notes: 'Port is opened by rotor position rather than valve lift.', }, { id: 'exhaust-flow', label: 'Exhaust port flow', targetPartIds: ['exhaust-port-wankel'], transform: 'flow', driver: 'chamber exposes exhaust port', expression: 'amber flow exits during chamber contraction near exhaust sector', phaseDeg: 45, notes: 'Exhaust and intake can overlap spatially in the side-port teaching model.', }, { id: 'spark-event', label: 'Leading and trailing spark', targetPartIds: ['leading-spark-plug', 'trailing-spark-plug'], transform: 'material', driver: 'combustion chamber reaches plug zone', expression: 'leading plug pulses first, trailing plug follows shortly after', phaseDeg: 330, notes: 'Two pulses show flame travel in the long chamber.', }, ], }, explodedView: { defaultDistance: 0.28, maxDistance: 1.05, groups: [ { id: 'side-plates', label: 'Side plates', partIds: ['front-side-plate'], axis: 'z', direction: 1, order: 1, reason: 'Pulls the cover away to reveal rotor and chamber overlays.', }, { id: 'rotor-forward', label: 'Rotor assembly', partIds: ['triangular-rotor', 'apex-seals', 'eccentric-shaft', 'stationary-gear'], axis: 'z', direction: 1, order: 2, reason: 'Separates the moving rotor from the epitrochoid housing.', }, { id: 'ports-outward', label: 'Port windows', partIds: ['intake-port-wankel', 'exhaust-port-wankel', 'leading-spark-plug', 'trailing-spark-plug'], axis: 'y', direction: 1, order: 3, reason: 'Makes port timing and plug placement clear around the housing wall.', }, ], }, crossSection: { defaultAxis: 'z', recommendedPlanes: [ { id: 'side-plate-removal', label: 'Side plate cutaway', axis: 'z', offset: 0.05, description: 'Removes the front side plate to expose rotor and chamber phase overlays.', }, { id: 'port-strip', label: 'Port strip', axis: 'y', offset: -0.1, description: 'Cuts through intake and exhaust port windows on the housing perimeter.', }, ], }, thumbnail: makeThumbnailStrategy( ['epitrochoid-housing', 'triangular-rotor'], ['apex-seals', 'chamber-overlays'], 'Use a front cutaway card with the rotor face visible inside the peanut-shaped housing.', ), assetReplacement: { proceduralBlueprintId: 'wankel-rotary-engine', preferredGlbPath: 'src/assets/machines/wankel-rotary-engine/wankel-rotary-engine.glb', rootNodeName: 'WankelRotaryEngine', requiredNamedNodes: [ 'EpitrochoidHousing', 'TriangularRotor', 'ApexSeals', 'EccentricShaft', 'WankelIntakePort', 'WankelExhaustPort', ], optionalNamedNodes: ['FrontSidePlate', 'StationaryGear', 'LeadingSparkPlug', 'TrailingSparkPlug', 'ChamberOverlays'], materialSlots: ['cast-aluminium', 'polished-chrome', 'warm-rotor', 'seal-dark', 'flow-blue', 'flow-amber', 'spark-emissive'], coordinateSystem: 'Y up, rotor plane in XY, side plates along Z, eccentric shaft along Z through model origin.', replacementInstructions: 'Rotor pivot must be parented to an eccentric orbit group. Keep apex seals separate or instanced so hover selection can explain seal wear and chamber separation.', }, relatedMachines: ['four-stroke-petrol-engine', 'two-stroke-engine', 'slider-crank'], }, { machineId: 'steam-engine', slugAliases: ['reciprocating-steam-engine', 'slide-valve-steam-engine'], title: 'Steam Engine', category: 'Engines', difficulty: 'Intermediate', complexityScore: 5, registryKeywords: ['steam', 'slide valve', 'piston', 'flywheel', 'governor', 'eccentric'], oneParagraphDescription: 'A reciprocating steam engine uses pressurized steam admitted by a slide valve to push a piston back and forth, then converts that motion into flywheel rotation through a connecting rod and crank. The model includes the eccentric valve drive and centrifugal governor so users can see power conversion and early automatic speed control in one assembly.', learningObjectives: [ 'Trace steam admission, expansion, and exhaust through the slide valve.', 'Relate piston reciprocation to crank and flywheel rotation.', 'Explain how an eccentric advances valve timing relative to the crank.', 'Understand how a centrifugal governor regulates steam flow.', ], facts: [ { label: 'Prime mover', value: 'External combustion', details: 'Heat is generated in a boiler and delivered as steam rather than burned inside the cylinder.', }, { label: 'Typical speed', value: '60–300 rpm', details: 'Large reciprocating steam engines run slowly and rely on large flywheels.', }, { label: 'Historic impact', value: 'Industrial Revolution', details: 'Steam engines powered factories, pumps, locomotives, and ships before widespread electric drives.', }, { label: 'Valve gear', value: 'Slide valve with eccentric', details: 'The eccentric drives valve motion ahead of piston position to admit steam at the correct time.', }, { label: 'Control', value: 'Centrifugal governor', details: 'Rising flyballs throttle steam admission as speed increases.', }, ], componentTree: [ { id: 'steam-cylinder-assembly', name: 'Cylinder and valve chest', kind: 'assembly', description: 'Steam cylinder, slide valve, ports, and exhaust chest route pressure to either side of the piston.', engineeringRole: 'Converts steam pressure into alternating piston force.', materialHint: 'dark cast iron with brass valve details', labelAnchor: [0, 0.25, 0], explodedOffset: [-0.25, 0, 0], replacementNode: 'SteamCylinderAssembly', animationChannels: ['piston-reciprocation', 'slide-valve-motion', 'steam-flow'], children: [ { id: 'steam-cylinder', name: 'Steam cylinder', kind: 'part', description: 'Pressure vessel in which the piston receives steam on alternating sides.', engineeringRole: 'Provides the expansion volume where steam does mechanical work.', materialHint: 'blackened cast iron with cutaway bore', labelAnchor: [-0.35, 0.15, 0], explodedOffset: [-0.45, 0, 0], replacementNode: 'SteamCylinder', animationChannels: [], }, { id: 'steam-piston', name: 'Double-acting piston', kind: 'part', description: 'Piston driven alternately from both sides by admitted steam.', engineeringRole: 'Produces power on both forward and return strokes.', materialHint: 'polished steel disc with dark rings', labelAnchor: [-0.15, 0.15, 0], explodedOffset: [-0.58, 0.05, 0], replacementNode: 'SteamPiston', animationChannels: ['piston-reciprocation'], }, { id: 'slide-valve', name: 'Slide valve', kind: 'part', description: 'Sliding valve that alternately connects steam inlet and exhaust ports.', engineeringRole: 'Times admission and exhaust relative to piston travel.', materialHint: 'brass or bronze block', labelAnchor: [-0.35, 0.58, 0], explodedOffset: [-0.42, 0.38, 0], replacementNode: 'SlideValve', animationChannels: ['slide-valve-motion'], }, { id: 'steam-ports', name: 'Steam ports', kind: 'part', description: 'Internal passages from valve chest to each end of the cylinder.', engineeringRole: 'Route high-pressure and exhaust steam as the slide valve uncovers openings.', materialHint: 'transparent blue and grey flow channels', labelAnchor: [-0.35, 0.38, 0.18], explodedOffset: [-0.38, 0.18, 0.28], replacementNode: 'SteamPorts', animationChannels: ['steam-flow'], }, ], }, { id: 'steam-crank-drive', name: 'Crank, rod, and flywheel drive', kind: 'assembly', description: 'Crosshead, connecting rod, crank, and flywheel convert reciprocation to rotation.', engineeringRole: 'Transforms linear piston force into rotary shaft work while guiding side loads.', materialHint: 'polished steel rods, dark flywheel, oiled bearings', labelAnchor: [0.45, 0, 0], explodedOffset: [0.35, 0, 0], replacementNode: 'SteamCrankDrive', animationChannels: ['flywheel-rotation', 'rod-swing', 'crosshead-motion'], children: [ { id: 'crosshead', name: 'Crosshead guide', kind: 'part', description: 'Slider that keeps the piston rod aligned and absorbs side thrust.', engineeringRole: 'Protects the cylinder from rod angularity loads.', materialHint: 'machined steel block in dark guide rails', labelAnchor: [0.05, 0.08, 0], explodedOffset: [0.15, 0.12, 0], replacementNode: 'Crosshead', animationChannels: ['crosshead-motion'], }, { id: 'steam-connecting-rod', name: 'Connecting rod', kind: 'part', description: 'Long rod connecting crosshead to crank pin.', engineeringRole: 'Carries tensile and compressive load into the crank.', materialHint: 'polished steel', labelAnchor: [0.42, 0.05, 0], explodedOffset: [0.4, 0.12, 0], replacementNode: 'SteamConnectingRod', animationChannels: ['rod-swing'], }, { id: 'steam-crank', name: 'Crank throw', kind: 'part', description: 'Offset crank pin on the flywheel shaft.', engineeringRole: 'Converts rod force into torque and provides return motion.', materialHint: 'forged steel', labelAnchor: [0.78, 0.03, 0], explodedOffset: [0.62, 0.12, 0], replacementNode: 'SteamCrank', animationChannels: ['flywheel-rotation'], }, { id: 'flywheel-steam', name: 'Flywheel', kind: 'part', description: 'Large spoked wheel storing energy across dead centres.', engineeringRole: 'Smooths torque and helps the crank pass positions where leverage is low.', materialHint: 'dark cast iron rim with machined spokes', labelAnchor: [0.95, 0, 0], explodedOffset: [0.85, 0.08, 0], replacementNode: 'SteamFlywheel', animationChannels: ['flywheel-rotation'], }, ], }, { id: 'steam-control-system', name: 'Timing and speed control', kind: 'assembly', description: 'Eccentric strap, valve rod, and flyball governor coordinate valve timing and throttle.', engineeringRole: 'Demonstrates mechanical feedback control before electronic governors.', materialHint: 'brass governor, steel eccentric strap, blue steam throttle', labelAnchor: [0.4, 0.75, 0], explodedOffset: [0.25, 0.38, 0.22], replacementNode: 'SteamControlSystem', animationChannels: ['eccentric-rotation', 'governor-flyball-motion', 'throttle-linkage'], children: [ { id: 'eccentric', name: 'Eccentric cam', kind: 'part', description: 'Off-centre disc on the main shaft driving the slide valve rod.', engineeringRole: 'Provides valve motion with phase lead relative to piston travel.', materialHint: 'polished steel eccentric with brass strap', labelAnchor: [0.72, 0.35, 0], explodedOffset: [0.58, 0.28, 0.12], replacementNode: 'Eccentric', animationChannels: ['eccentric-rotation'], }, { id: 'valve-rod', name: 'Valve rod', kind: 'part', description: 'Link transferring eccentric motion to the slide valve.', engineeringRole: 'Sets valve travel and timing phase.', materialHint: 'slender polished steel', labelAnchor: [0.12, 0.52, 0], explodedOffset: [0.18, 0.38, 0.12], replacementNode: 'ValveRod', animationChannels: ['slide-valve-motion'], }, { id: 'centrifugal-governor', name: 'Centrifugal governor', kind: 'assembly', description: 'Spinning flyballs rise with speed and act on the throttle linkage.', engineeringRole: 'Automatically reduces steam admission when shaft speed increases.', materialHint: 'brass balls, dark spindle, warm highlight', labelAnchor: [0.38, 1.02, 0], explodedOffset: [0.28, 0.72, 0.16], replacementNode: 'CentrifugalGovernor', animationChannels: ['governor-flyball-motion', 'throttle-linkage'], }, { id: 'steam-inlet-exhaust', name: 'Steam inlet and exhaust', kind: 'effect', description: 'Colored pipe effects showing live steam entering and exhaust steam leaving.', engineeringRole: 'Clarifies which side of the piston is receiving pressure.', materialHint: 'blue live-steam and grey exhaust vapor', labelAnchor: [-0.58, 0.62, 0], explodedOffset: [-0.42, 0.32, 0.24], replacementNode: 'SteamInletExhaust', animationChannels: ['steam-flow'], }, ], }, ], labels: [ { partId: 'slide-valve', text: 'Slide valve alternates inlet and exhaust', position: [-0.48, 0.72, 0.25], priority: 'primary' }, { partId: 'flywheel-steam', text: 'Flywheel carries the engine through dead centre', position: [1.1, 0.1, 0.28], priority: 'primary' }, { partId: 'eccentric', text: 'Eccentric leads valve timing', position: [0.84, 0.48, 0.2], priority: 'secondary' }, { partId: 'centrifugal-governor', text: 'Governor throttles steam with speed', position: [0.5, 1.18, 0.25], priority: 'secondary' }, ], cameraPresets: makeCameraPresets(5.2, [0.25, 0.22, 0], { id: 'valve-chest', label: 'Valve Chest', position: [0.5, 1.15, 2.3], target: [-0.32, 0.45, 0], description: 'Close-up on the slide valve, ports, and steam flow paths.', }), guidedTour: [ { id: 'steam-pressure-work', title: 'Steam pressure does work', body: 'Live steam enters one side of the cylinder, pushing the double-acting piston and crosshead.', cameraPresetId: 'front', highlightedPartIds: ['steam-cylinder', 'steam-piston', 'steam-ports'], durationSeconds: 7, animationTimeScale: 0.45, setExplode: 0.08, crossSection: { axis: 'z', offset: 0 }, }, { id: 'crank-and-flywheel', title: 'Reciprocation becomes rotation', body: 'The rod drives the crank throw while the flywheel stores energy across the dead centres.', cameraPresetId: 'right', highlightedPartIds: ['crosshead', 'steam-connecting-rod', 'steam-crank', 'flywheel-steam'], durationSeconds: 7, animationTimeScale: 0.55, setExplode: 0.16, }, { id: 'slide-valve-timing', title: 'Valve timing from an eccentric', body: 'The eccentric turns with the main shaft but is phased to move the slide valve before the piston reaches stroke end.', cameraPresetId: 'valve-chest', highlightedPartIds: ['eccentric', 'valve-rod', 'slide-valve'], durationSeconds: 7, animationTimeScale: 0.4, setExplode: 0.22, }, { id: 'governor-control', title: 'Mechanical feedback control', body: 'As speed rises, the governor flyballs lift and pull the throttle toward a reduced steam opening.', cameraPresetId: 'isometric', highlightedPartIds: ['centrifugal-governor', 'steam-inlet-exhaust'], durationSeconds: 6, animationTimeScale: 0.65, setExplode: 0.14, }, ], animationModel: { nominalRpm: 120, cycleSecondsAtNominal: 0.5, loopMode: 'reciprocating', stepCount: 4, primaryDriver: 'flywheel-angle', engineeringNotes: 'Use a single crank revolution for one double-acting mechanical cycle. Steam flow should swap cylinder sides every half turn, with slide valve lead from the eccentric.', channels: [ { id: 'flywheel-rotation', label: 'Flywheel and crank rotation', targetPartIds: ['flywheel-steam', 'steam-crank'], transform: 'rotation', driver: 'shaft angle θ', expression: 'rotate continuously 0–360° per double-acting cycle', phaseDeg: 0, notes: 'Large wheel should appear heavy, with smooth eased speed changes only when RPM slider changes.', }, { id: 'crosshead-motion', label: 'Crosshead and piston motion', targetPartIds: ['crosshead', 'steam-piston'], transform: 'translation', driver: 'crank-slider relation', expression: 'horizontal reciprocation constrained by guide rails', phaseDeg: 0, notes: 'Crosshead prevents rod angularity from entering the cylinder.', }, { id: 'rod-swing', label: 'Main rod swing', targetPartIds: ['steam-connecting-rod'], transform: 'oscillation', driver: 'crosshead and crank pin positions', expression: 'orient rod between crosshead pin and rotating crank pin', phaseDeg: 0, notes: 'Preserve rod length across the whole cycle.', }, { id: 'eccentric-rotation', label: 'Eccentric rotation', targetPartIds: ['eccentric'], transform: 'rotation', driver: 'shaft angle θ', expression: 'rotate with shaft plus valve-lead phase angle', phaseDeg: 90, notes: 'Phase lead makes the valve open before piston end travel.', }, { id: 'slide-valve-motion', label: 'Slide valve motion', targetPartIds: ['slide-valve', 'valve-rod'], transform: 'translation', driver: 'eccentric throw', expression: 'horizontal sinusoidal valve travel from eccentric strap', phaseDeg: 90, notes: 'Valve travel is shorter than piston stroke.', }, { id: 'steam-flow', label: 'Steam admission and exhaust', targetPartIds: ['steam-ports', 'steam-inlet-exhaust'], transform: 'flow', driver: 'slide valve overlap', expression: 'blue live-steam alternates cylinder ends; grey exhaust leaves opposite end', phaseDeg: 0, notes: 'Flow direction reverses every half revolution.', }, { id: 'governor-flyball-motion', label: 'Governor flyball motion', targetPartIds: ['centrifugal-governor'], transform: 'oscillation', driver: 'RPM slider', expression: 'flyball radius and height increase with normalized RPM', phaseDeg: 0, notes: 'Unlike the crank cycle, governor cone angle responds primarily to selected RPM.', }, { id: 'throttle-linkage', label: 'Throttle linkage', targetPartIds: ['centrifugal-governor'], transform: 'translation', driver: 'governor flyball height', expression: 'linkage closes throttle fraction as flyball height increases', phaseDeg: 0, notes: 'A visible lever gives learners a feedback-control cue.', }, ], }, explodedView: { defaultDistance: 0.34, maxDistance: 1.2, groups: [ { id: 'valve-chest-up', label: 'Valve chest', partIds: ['slide-valve', 'steam-ports', 'valve-rod'], axis: 'y', direction: 1, order: 1, reason: 'Shows how the slide valve routes steam to each cylinder end.', }, { id: 'drive-right', label: 'Crank drive', partIds: ['crosshead', 'steam-connecting-rod', 'steam-crank', 'flywheel-steam'], axis: 'x', direction: 1, order: 2, reason: 'Separates the motion conversion mechanism from the cylinder.', }, { id: 'control-up', label: 'Governor controls', partIds: ['eccentric', 'centrifugal-governor', 'steam-inlet-exhaust'], axis: 'y', direction: 1, order: 3, reason: 'Lifts timing and speed-control parts for the automation lesson.', }, ], }, crossSection: { defaultAxis: 'z', recommendedPlanes: [ { id: 'cylinder-bore', label: 'Cylinder and ports', axis: 'z', offset: 0, description: 'Cuts through the piston, slide valve, and ports.', }, { id: 'flywheel-plane', label: 'Flywheel plane', axis: 'x', offset: 0.9, description: 'Slices the crank and flywheel to show crank throw eccentricity.', }, ], }, thumbnail: makeThumbnailStrategy( ['steam-cylinder', 'flywheel-steam', 'centrifugal-governor'], ['slide-valve', 'steam-inlet-exhaust'], 'Use a long horizontal silhouette with a large spoked flywheel and brass governor as recognisable historic cues.', ), assetReplacement: { proceduralBlueprintId: 'steam-engine', preferredGlbPath: 'src/assets/machines/steam-engine/steam-engine.glb', rootNodeName: 'SteamEngine', requiredNamedNodes: [ 'SteamCylinder', 'SteamPiston', 'SlideValve', 'SteamPorts', 'Crosshead', 'SteamConnectingRod', 'SteamCrank', 'SteamFlywheel', 'Eccentric', 'CentrifugalGovernor', ], optionalNamedNodes: ['ValveRod', 'SteamInletExhaust', 'BoilerStub', 'BasePlate', 'ThrottleValve'], materialSlots: ['cast-iron', 'brass', 'machined-steel', 'flow-blue', 'vapor-grey', 'warm-highlight'], coordinateSystem: 'Y up, piston stroke along X, flywheel shaft along Z, origin near crankshaft centre.', replacementInstructions: 'Keep slide valve and piston as separate linearly animated nodes. Governor flyballs should be separate child nodes around a spindle for RPM-driven cone-angle animation.', }, relatedMachines: ['slider-crank', 'scotch-yoke', 'piston-pump'], }, { machineId: 'turbojet-engine', slugAliases: ['jet-engine', 'jet-engine-turbojet', 'gas-turbine-turbojet'], title: 'Jet Engine (Turbojet)', category: 'Engines', difficulty: 'Advanced', complexityScore: 8, registryKeywords: ['turbojet', 'gas turbine', 'compressor', 'combustor', 'turbine', 'nozzle', 'brayton cycle'], oneParagraphDescription: 'A turbojet engine accelerates air through a Brayton-cycle gas path: intake diffusion, compressor pressure rise, combustion heat addition, turbine work extraction, and nozzle expansion. The procedural model is a clean axial cutaway with rotating compressor and turbine stages, stator rows, fuel spray, flame tube glow, and velocity-color flow ribbons.', learningObjectives: [ 'Trace the axial gas path from intake to propulsive nozzle.', 'Distinguish compressor rotors, stators, combustor, turbine, and nozzle.', 'Explain turbine work extraction as the power source for the compressor.', 'Relate nozzle acceleration to thrust production.', ], facts: [ { label: 'Thermodynamic cycle', value: 'Brayton cycle', details: 'Continuous flow compression, heat addition, expansion through turbine, and nozzle acceleration.', }, { label: 'Typical shaft speed', value: '8000–30000 rpm', details: 'Small cores can spin much faster; speed depends on diameter and tip Mach limits.', }, { label: 'Thrust source', value: 'High-velocity exhaust jet', details: 'Momentum increase of core airflow generates forward thrust.', }, { label: 'First practical turbojet', value: '1930s–1940s', details: 'Frank Whittle and Hans von Ohain independently developed early practical turbojet engines.', }, { label: 'Best regime', value: 'High speed / high altitude', details: 'Pure turbojets are less efficient at low speed than turbofans but suit high-speed aircraft.', }, ], componentTree: [ { id: 'turbojet-casing-intake', name: 'Casing and intake', kind: 'assembly', description: 'Outer casing, inlet lip, and diffuser guide airflow toward the compressor face.', engineeringRole: 'Slows and straightens incoming air to improve compressor stability.', materialHint: 'dark titanium casing with blue inlet flow', labelAnchor: [-1.2, 0, 0], explodedOffset: [-0.25, 0, 0], replacementNode: 'TurbojetCasingIntake', animationChannels: ['core-airflow'], children: [ { id: 'intake-lip', name: 'Intake lip', kind: 'part', description: 'Rounded leading edge that admits freestream air with minimal separation.', engineeringRole: 'Conditions flow over a range of aircraft speeds and angles of attack.', materialHint: 'polished titanium rim', labelAnchor: [-1.85, 0.32, 0], explodedOffset: [-0.45, 0, 0], replacementNode: 'IntakeLip', animationChannels: ['core-airflow'], }, { id: 'diffuser', name: 'Inlet diffuser', kind: 'part', description: 'Expanding passage that converts inlet velocity into static pressure.', engineeringRole: 'Feeds the compressor with lower Mach, more uniform airflow.', materialHint: 'semi-transparent blue-grey duct', labelAnchor: [-1.35, 0.2, 0], explodedOffset: [-0.35, 0, 0], replacementNode: 'Diffuser', animationChannels: ['core-airflow'], }, { id: 'outer-engine-case', name: 'Outer engine case', kind: 'part', description: 'Structural shell holding bearing frames and stator rows.', engineeringRole: 'Maintains blade-tip clearance and contains pressure loads.', materialHint: 'dark metal with cutaway window', labelAnchor: [0, 0.62, 0], explodedOffset: [0, 0.35, 0], replacementNode: 'OuterEngineCase', animationChannels: [], }, ], }, { id: 'compressor-section', name: 'Compressor section', kind: 'assembly', description: 'Alternating rotor and stator stages progressively raise air pressure.', engineeringRole: 'Supplies high-pressure air for efficient combustion and turbine expansion.', materialHint: 'blue steel rotors with dark stators', labelAnchor: [-0.7, 0.2, 0], explodedOffset: [-0.15, 0.18, 0], replacementNode: 'CompressorSection', animationChannels: ['compressor-rotation', 'core-airflow'], children: [ { id: 'compressor-rotors', name: 'Compressor rotors', kind: 'assembly', description: 'Rows of airfoil blades attached to the main shaft.', engineeringRole: 'Add kinetic energy and pressure to the incoming air.', materialHint: 'cool polished blades with blue edge tint', labelAnchor: [-0.75, 0.38, 0], explodedOffset: [-0.18, 0.3, 0], replacementNode: 'CompressorRotors', animationChannels: ['compressor-rotation'], }, { id: 'compressor-stators', name: 'Compressor stators', kind: 'assembly', description: 'Fixed vanes between rotors that diffuse and redirect flow.', engineeringRole: 'Convert swirl into pressure and set angle for the next rotor.', materialHint: 'dark stationary vanes', labelAnchor: [-0.38, -0.35, 0], explodedOffset: [-0.08, -0.22, 0], replacementNode: 'CompressorStators', animationChannels: [], }, { id: 'main-shaft-turbojet', name: 'Main shaft', kind: 'part', description: 'Rotating shaft linking turbine work to compressor power.', engineeringRole: 'Transfers torque from turbine stages to compressor rotors.', materialHint: 'polished steel', labelAnchor: [0, -0.08, 0], explodedOffset: [0, -0.28, 0], replacementNode: 'TurbojetMainShaft', animationChannels: ['compressor-rotation', 'turbine-rotation'], }, ], }, { id: 'combustor-turbine-nozzle', name: 'Combustor, turbine, and nozzle', kind: 'assembly', description: 'Fuel injection, flame stabilization, turbine expansion, and nozzle acceleration complete the gas path.', engineeringRole: 'Adds heat, extracts shaft work, and converts remaining gas energy into thrust.', materialHint: 'warm heat-resistant alloys, amber flame, red turbine glow', labelAnchor: [0.75, 0.18, 0], explodedOffset: [0.18, 0.18, 0], replacementNode: 'CombustorTurbineNozzle', animationChannels: ['fuel-spray', 'combustion-glow', 'turbine-rotation', 'exhaust-jet'], children: [ { id: 'combustion-chamber-turbojet', name: 'Combustion chamber', kind: 'part', description: 'Annular or can combustor where fuel burns in compressed air.', engineeringRole: 'Raises gas temperature while maintaining stable flame and acceptable pressure loss.', materialHint: 'dark heat shield with amber translucent flame', labelAnchor: [0.28, 0.42, 0], explodedOffset: [0.08, 0.36, 0], replacementNode: 'TurbojetCombustionChamber', animationChannels: ['fuel-spray', 'combustion-glow'], }, { id: 'fuel-injectors-turbojet', name: 'Fuel injectors', kind: 'assembly', description: 'Nozzles spraying fuel into the combustor primary zone.', engineeringRole: 'Atomize fuel and support stable combustion over throttle range.', materialHint: 'small brass nozzles with amber spray cones', labelAnchor: [0.1, 0.56, 0.08], explodedOffset: [0.08, 0.55, 0.12], replacementNode: 'TurbojetFuelInjectors', animationChannels: ['fuel-spray'], }, { id: 'turbine-stages', name: 'Turbine stages', kind: 'assembly', description: 'High-temperature rotor and stator blades downstream of the combustor.', engineeringRole: 'Extract enough energy from hot gas to drive the compressor.', materialHint: 'heat-tinted nickel alloy blades', labelAnchor: [0.82, 0.3, 0], explodedOffset: [0.22, 0.28, 0], replacementNode: 'TurbineStages', animationChannels: ['turbine-rotation'], }, { id: 'exhaust-nozzle', name: 'Converging nozzle', kind: 'part', description: 'Rear nozzle accelerating hot gas into a high-velocity jet.', engineeringRole: 'Converts thermal and pressure energy into propulsive momentum.', materialHint: 'dark titanium nozzle with amber exhaust core', labelAnchor: [1.62, 0.22, 0], explodedOffset: [0.45, 0.1, 0], replacementNode: 'ExhaustNozzle', animationChannels: ['exhaust-jet'], }, ], }, ], labels: [ { partId: 'compressor-rotors', text: 'Compressor raises pressure stage by stage', position: [-0.75, 0.55, 0.3], priority: 'primary' }, { partId: 'combustion-chamber-turbojet', text: 'Combustor adds heat at near-constant pressure', position: [0.3, 0.62, 0.28], priority: 'primary' }, { partId: 'turbine-stages', text: 'Turbine powers the compressor', position: [0.86, 0.48, 0.28], priority: 'primary' }, { partId: 'exhaust-nozzle', text: 'Nozzle accelerates the thrust jet', position: [1.78, 0.34, 0.24], priority: 'secondary' }, ], cameraPresets: makeCameraPresets(6, [0, 0.05, 0], { id: 'axial-cutaway', label: 'Axial Cutaway', position: [1.25, 1.1, 3.2], target: [0.35, 0.12, 0], description: 'Cutaway view down the engine axis showing the complete Brayton gas path.', }), guidedTour: [ { id: 'brayton-path', title: 'Continuous Brayton-cycle flow', body: 'Air flows continuously from intake to nozzle instead of cycling in a sealed cylinder.', cameraPresetId: 'axial-cutaway', highlightedPartIds: ['intake-lip', 'diffuser', 'compressor-rotors', 'combustion-chamber-turbojet', 'turbine-stages', 'exhaust-nozzle'], durationSeconds: 8, animationTimeScale: 0.55, setExplode: 0.06, crossSection: { axis: 'z', offset: 0 }, }, { id: 'compression', title: 'Compressor pressure rise', body: 'Rotor blades add energy while stators redirect and diffuse the flow for the next stage.', cameraPresetId: 'left', highlightedPartIds: ['compressor-rotors', 'compressor-stators', 'main-shaft-turbojet'], durationSeconds: 7, animationTimeScale: 0.45, setExplode: 0.15, }, { id: 'combustion', title: 'Fuel burns in compressed air', body: 'Injectors spray fuel into the primary zone, where the flame is stabilized inside the combustor liner.', cameraPresetId: 'top', highlightedPartIds: ['fuel-injectors-turbojet', 'combustion-chamber-turbojet'], durationSeconds: 6, animationTimeScale: 0.4, setExplode: 0.18, }, { id: 'turbine-work', title: 'Turbine extracts shaft work', body: 'Only part of the hot gas energy is extracted; enough remains for the nozzle to create thrust.', cameraPresetId: 'right', highlightedPartIds: ['turbine-stages', 'main-shaft-turbojet', 'exhaust-nozzle'], durationSeconds: 7, animationTimeScale: 0.5, setExplode: 0.16, }, ], animationModel: { nominalRpm: 12000, cycleSecondsAtNominal: 0.005, loopMode: 'continuous', stepCount: 5, primaryDriver: 'spool-angle', engineeringNotes: 'The turbojet is continuous-flow. Use looping rotor rotation and animated flow ribbons rather than piston cycle phases. Turbine and compressor share shaft speed in this single-spool teaching model.', channels: [ { id: 'compressor-rotation', label: 'Compressor spool rotation', targetPartIds: ['compressor-rotors', 'main-shaft-turbojet'], transform: 'rotation', driver: 'spool angle θ', expression: 'rotate compressor rotors and shaft continuously about engine axis', phaseDeg: 0, notes: 'Stator nodes remain fixed and selectable.', }, { id: 'turbine-rotation', label: 'Turbine rotation', targetPartIds: ['turbine-stages', 'main-shaft-turbojet'], transform: 'rotation', driver: 'spool angle θ', expression: 'rotate turbine rotor in sync with compressor on the same shaft', phaseDeg: 0, notes: 'If separate turbine stators exist, keep them stationary.', }, { id: 'core-airflow', label: 'Core airflow', targetPartIds: ['intake-lip', 'diffuser', 'compressor-rotors'], transform: 'flow', driver: 'engine running state', expression: 'blue ribbons accelerate into intake then compress into denser stream through compressor', phaseDeg: 0, notes: 'Particle spacing should decrease through compressor to suggest pressure rise.', }, { id: 'fuel-spray', label: 'Fuel spray', targetPartIds: ['fuel-injectors-turbojet'], transform: 'flow', driver: 'throttle fraction', expression: 'amber spray cones pulse subtly but remain continuous while running', phaseDeg: 0, notes: 'Use throttle/RPM to scale intensity.', }, { id: 'combustion-glow', label: 'Combustion glow', targetPartIds: ['combustion-chamber-turbojet'], transform: 'material', driver: 'fuel spray intensity', expression: 'warm emissive flame core with low-frequency flicker', phaseDeg: 0, notes: 'Avoid harsh strobe; gas turbine combustion is steady.', }, { id: 'exhaust-jet', label: 'Exhaust jet velocity', targetPartIds: ['exhaust-nozzle'], transform: 'flow', driver: 'spool speed and combustion energy', expression: 'amber-to-white flow ribbons narrow and speed up through nozzle', phaseDeg: 0, notes: 'Nozzle flow should visually exceed inlet flow speed.', }, ], }, explodedView: { defaultDistance: 0.28, maxDistance: 1.1, groups: [ { id: 'case-up', label: 'Outer case cutaway', partIds: ['outer-engine-case'], axis: 'y', direction: 1, order: 1, reason: 'Lifts the casing to reveal the axial gas path.', }, { id: 'compressor-forward', label: 'Compressor section', partIds: ['compressor-rotors', 'compressor-stators', 'main-shaft-turbojet'], axis: 'y', direction: 1, order: 2, reason: 'Separates rotor and stator rows for pressure-rise explanation.', }, { id: 'hot-section-up', label: 'Hot section', partIds: ['combustion-chamber-turbojet', 'fuel-injectors-turbojet', 'turbine-stages'], axis: 'y', direction: 1, order: 3, reason: 'Highlights combustion and turbine work extraction.', }, { id: 'nozzle-rear', label: 'Nozzle', partIds: ['exhaust-nozzle'], axis: 'x', direction: 1, order: 4, reason: 'Pulls the nozzle rearward to show expansion after the turbine.', }, ], }, crossSection: { defaultAxis: 'z', recommendedPlanes: [ { id: 'engine-centreline', label: 'Engine centreline', axis: 'z', offset: 0, description: 'Longitudinal cutaway through compressor, combustor, turbine, and nozzle.', }, { id: 'compressor-stage', label: 'Compressor stage slice', axis: 'x', offset: -0.65, description: 'Radial slice through a representative rotor/stator stage.', }, ], }, thumbnail: makeThumbnailStrategy( ['intake-lip', 'outer-engine-case', 'exhaust-nozzle'], ['compressor-rotors', 'combustion-chamber-turbojet', 'turbine-stages'], 'Use a long cutaway silhouette with cool inlet and warm exhaust gradient for immediate turbojet recognition.', ), assetReplacement: { proceduralBlueprintId: 'turbojet-engine', preferredGlbPath: 'src/assets/machines/turbojet-engine/turbojet-engine.glb', rootNodeName: 'TurbojetEngine', requiredNamedNodes: [ 'IntakeLip', 'Diffuser', 'OuterEngineCase', 'CompressorRotors', 'CompressorStators', 'TurbojetMainShaft', 'TurbojetCombustionChamber', 'TurbineStages', 'ExhaustNozzle', ], optionalNamedNodes: ['TurbojetFuelInjectors', 'BearingFrames', 'FlameTube', 'CoreAirflowRibbons', 'AccessoryGearbox'], materialSlots: ['titanium-dark', 'polished-blades', 'heat-alloy', 'flow-blue', 'flow-amber', 'combustion-emissive'], coordinateSystem: 'Y up, engine axis along X from intake negative X to nozzle positive X, origin near compressor/turbine shaft centre.', replacementInstructions: 'Rotor rows must be grouped separately from stators. Keep the casing cutaway mesh selectable but independent from the internal gas-path components.', }, relatedMachines: ['turbofan-engine', 'turbocharger', 'centrifugal-pump'], }, { machineId: 'turbofan-engine', slugAliases: ['bypass-turbofan', 'high-bypass-turbofan-engine'], title: 'Turbofan Engine', category: 'Engines', difficulty: 'Advanced', complexityScore: 9, registryKeywords: ['turbofan', 'fan', 'bypass duct', 'compressor', 'combustor', 'turbine', 'nozzle', 'spools'], oneParagraphDescription: 'A turbofan engine surrounds a gas-turbine core with a large fan that accelerates a bypass stream around the core. The procedural cutaway distinguishes fan flow, bypass duct, core compressor, combustor, high and low turbines, and separate spool speeds so users can understand why turbofans are efficient for modern aircraft propulsion.', learningObjectives: [ 'Differentiate bypass airflow from core airflow.', 'Identify fan, splitter, compressors, combustor, turbines, shafts, and nozzles.', 'Explain how the turbine drives the fan and compressor spools.', 'Relate bypass ratio to propulsive efficiency and noise.', ], facts: [ { label: 'Bypass ratio', value: '2:1–12:1+', details: 'High-bypass engines move most air around the core rather than through combustion.', }, { label: 'Primary thrust', value: 'Fan/bypass stream', details: 'Modern high-bypass engines get much of their thrust from the fan accelerating a large mass of air.', }, { label: 'Spool architecture', value: 'Two or three concentric shafts', details: 'Separate low- and high-pressure spools rotate at different speeds for efficiency and stability.', }, { label: 'Typical use', value: 'Airliners and business jets', details: 'Favoured for subsonic cruise because of high propulsive efficiency and lower noise.', }, { label: 'Compared with turbojet', value: 'Lower jet velocity, higher mass flow', details: 'This improves efficiency at subsonic speeds.', }, ], componentTree: [ { id: 'fan-nacelle-assembly', name: 'Fan and nacelle assembly', kind: 'assembly', description: 'Large front fan, inlet nacelle, bypass duct, and splitter form the cold-flow propulsor.', engineeringRole: 'Accelerates a large mass of air at moderate velocity for efficient subsonic thrust.', materialHint: 'dark nacelle, polished composite fan, blue bypass flow', labelAnchor: [-1.45, 0, 0], explodedOffset: [-0.25, 0.05, 0], replacementNode: 'FanNacelleAssembly', animationChannels: ['fan-rotation', 'bypass-flow'], children: [ { id: 'fan-blades', name: 'Wide-chord fan blades', kind: 'assembly', description: 'Large low-pressure rotor at the engine inlet.', engineeringRole: 'Adds momentum to bypass and core inlet air.', materialHint: 'dark composite blades with blue leading-edge highlights', labelAnchor: [-1.75, 0.48, 0], explodedOffset: [-0.42, 0.22, 0], replacementNode: 'FanBlades', animationChannels: ['fan-rotation'], }, { id: 'nacelle-inlet', name: 'Nacelle inlet', kind: 'part', description: 'Aerodynamic outer shell and intake lip surrounding the fan.', engineeringRole: 'Conditions incoming air and reduces inlet losses and noise.', materialHint: 'dark painted nacelle with subtle reflections', labelAnchor: [-1.95, 0.18, 0], explodedOffset: [-0.52, 0.02, 0], replacementNode: 'NacelleInlet', animationChannels: ['bypass-flow'], }, { id: 'bypass-duct', name: 'Bypass duct', kind: 'part', description: 'Annular passage carrying fan air around the hot core.', engineeringRole: 'Allows high mass-flow thrust without burning all the air.', materialHint: 'transparent blue annular flow sleeve', labelAnchor: [-0.55, 0.75, 0], explodedOffset: [0, 0.45, 0], replacementNode: 'BypassDuct', animationChannels: ['bypass-flow'], }, { id: 'flow-splitter', name: 'Core/bypass splitter', kind: 'part', description: 'Aerodynamic lip dividing air between the core compressor and bypass duct.', engineeringRole: 'Sets mass-flow split and protects core inlet stability.', materialHint: 'polished titanium annulus', labelAnchor: [-1.05, 0.35, 0], explodedOffset: [-0.1, 0.18, 0], replacementNode: 'FlowSplitter', animationChannels: ['core-flow', 'bypass-flow'], }, ], }, { id: 'turbofan-core', name: 'Gas turbine core', kind: 'assembly', description: 'Compressor, combustor, and high-pressure turbine generate hot gas and spool power.', engineeringRole: 'Produces energy to drive the fan and high-pressure compressor while adding core thrust.', materialHint: 'cool compressor metals transitioning to warm hot-section alloys', labelAnchor: [0.15, 0.16, 0], explodedOffset: [0, 0.2, 0], replacementNode: 'TurbofanCore', animationChannels: ['hp-spool-rotation', 'core-flow', 'combustion-glow'], children: [ { id: 'low-pressure-compressor', name: 'Low-pressure compressor', kind: 'assembly', description: 'Front compressor stages connected to the fan/low-pressure spool.', engineeringRole: 'Pre-compresses core air before it reaches the high-pressure compressor.', materialHint: 'cool blue blades', labelAnchor: [-0.48, 0.28, 0], explodedOffset: [-0.08, 0.28, 0], replacementNode: 'LowPressureCompressor', animationChannels: ['lp-spool-rotation'], }, { id: 'high-pressure-compressor', name: 'High-pressure compressor', kind: 'assembly', description: 'Smaller rear compressor stages rotating at higher speed.', engineeringRole: 'Raises pressure high enough for efficient combustion.', materialHint: 'polished compressor blades', labelAnchor: [0.1, 0.32, 0], explodedOffset: [0.04, 0.32, 0], replacementNode: 'HighPressureCompressor', animationChannels: ['hp-spool-rotation'], }, { id: 'turbofan-combustor', name: 'Annular combustor', kind: 'part', description: 'Combustion chamber where fuel burns in the compressed core stream.', engineeringRole: 'Adds thermal energy to drive turbines and produce remaining core thrust.', materialHint: 'heat shield with amber emissive flame', labelAnchor: [0.62, 0.4, 0], explodedOffset: [0.12, 0.36, 0], replacementNode: 'TurbofanCombustor', animationChannels: ['combustion-glow', 'fuel-spray'], }, { id: 'high-pressure-turbine', name: 'High-pressure turbine', kind: 'assembly', description: 'Hot turbine stages immediately after the combustor.', engineeringRole: 'Extracts work to drive the high-pressure compressor.', materialHint: 'red-gold heat alloy', labelAnchor: [0.95, 0.32, 0], explodedOffset: [0.18, 0.3, 0], replacementNode: 'HighPressureTurbine', animationChannels: ['hp-spool-rotation'], }, ], }, { id: 'turbofan-rear-spool-nozzle', name: 'Low-pressure turbine and nozzles', kind: 'assembly', description: 'Rear turbine, concentric shafts, bypass nozzle, and core nozzle complete the propulsion system.', engineeringRole: 'Transfers work to the fan and expands both bypass and core streams to produce thrust.', materialHint: 'hot turbine alloy, dark nozzles, blue/amber flow split', labelAnchor: [1.25, 0.18, 0], explodedOffset: [0.2, 0.15, 0], replacementNode: 'TurbofanRearSpoolNozzle', animationChannels: ['lp-spool-rotation', 'core-flow', 'bypass-flow'], children: [ { id: 'low-pressure-turbine', name: 'Low-pressure turbine', kind: 'assembly', description: 'Larger rear turbine stages extracting energy for the fan and booster.', engineeringRole: 'Drives the low-pressure spool and fan at lower speed than the core spool.', materialHint: 'heat-tinted turbine blades', labelAnchor: [1.22, 0.3, 0], explodedOffset: [0.25, 0.28, 0], replacementNode: 'LowPressureTurbine', animationChannels: ['lp-spool-rotation'], }, { id: 'concentric-shafts', name: 'Concentric shafts', kind: 'part', description: 'Nested shafts connecting fan/LPT and HPC/HPT spools.', engineeringRole: 'Allows separate rotating systems to run at their most efficient speeds.', materialHint: 'polished nested steel tubes', labelAnchor: [0.35, -0.12, 0], explodedOffset: [0, -0.35, 0], replacementNode: 'ConcentricShafts', animationChannels: ['lp-spool-rotation', 'hp-spool-rotation'], }, { id: 'bypass-nozzle', name: 'Bypass nozzle', kind: 'part', description: 'Annular nozzle accelerating fan air around the core.', engineeringRole: 'Converts fan pressure rise into useful propulsive velocity.', materialHint: 'blue annular exit flow', labelAnchor: [1.7, 0.68, 0], explodedOffset: [0.42, 0.18, 0], replacementNode: 'BypassNozzle', animationChannels: ['bypass-flow'], }, { id: 'core-nozzle', name: 'Core nozzle', kind: 'part', description: 'Central nozzle expanding hot core gas after the turbines.', engineeringRole: 'Adds residual core thrust and mixes with bypass flow downstream.', materialHint: 'amber hot exhaust core', labelAnchor: [1.82, 0.18, 0], explodedOffset: [0.48, 0.05, 0], replacementNode: 'CoreNozzle', animationChannels: ['core-flow'], }, ], }, ], labels: [ { partId: 'fan-blades', text: 'Fan moves most of the air', position: [-1.82, 0.65, 0.32], priority: 'primary' }, { partId: 'bypass-duct', text: 'Bypass stream flows around the core', position: [-0.5, 0.95, 0.28], priority: 'primary' }, { partId: 'turbofan-core', text: 'Core burns fuel and powers the spools', position: [0.38, 0.58, 0.28], priority: 'primary' }, { partId: 'concentric-shafts', text: 'Separate shafts run at different speeds', position: [0.36, -0.32, 0.24], priority: 'secondary' }, ], cameraPresets: makeCameraPresets(6.4, [0, 0.1, 0], { id: 'flow-split', label: 'Flow Split', position: [1.25, 1.35, 3.35], target: [-0.65, 0.25, 0], description: 'Close cutaway on fan, splitter, bypass duct, and core inlet.', }), guidedTour: [ { id: 'fan-bypass', title: 'Fan and bypass stream', body: 'The fan accelerates a large annulus of air around the core, producing efficient subsonic thrust.', cameraPresetId: 'flow-split', highlightedPartIds: ['fan-blades', 'bypass-duct', 'flow-splitter'], durationSeconds: 8, animationTimeScale: 0.45, setExplode: 0.08, crossSection: { axis: 'z', offset: 0 }, }, { id: 'core-flow-path', title: 'Smaller hot core', body: 'A fraction of the air enters the compressor, combustor, and turbine core to create shaft power.', cameraPresetId: 'front', highlightedPartIds: ['low-pressure-compressor', 'high-pressure-compressor', 'turbofan-combustor', 'high-pressure-turbine'], durationSeconds: 8, animationTimeScale: 0.4, setExplode: 0.16, }, { id: 'two-spools', title: 'Two spool speeds', body: 'The low-pressure spool connects fan and rear turbine, while the high-pressure spool connects core compressor and turbine.', cameraPresetId: 'right', highlightedPartIds: ['fan-blades', 'low-pressure-turbine', 'high-pressure-compressor', 'high-pressure-turbine', 'concentric-shafts'], durationSeconds: 8, animationTimeScale: 0.35, setExplode: 0.22, }, { id: 'dual-nozzles', title: 'Bypass and core nozzles', body: 'Cool bypass air and hot core gas expand through separate nozzle regions before mixing downstream.', cameraPresetId: 'back', highlightedPartIds: ['bypass-nozzle', 'core-nozzle'], durationSeconds: 6, animationTimeScale: 0.55, setExplode: 0.16, }, ], animationModel: { nominalRpm: 3500, cycleSecondsAtNominal: 0.017, loopMode: 'continuous', stepCount: 5, primaryDriver: 'low-and-high-spool-angles', engineeringNotes: 'Turbofan animation is continuous-flow with two rotating systems. The low-pressure spool drives fan/LPC/LPT; the high-pressure spool drives HPC/HPT and rotates faster.', channels: [ { id: 'fan-rotation', label: 'Fan rotation', targetPartIds: ['fan-blades'], transform: 'rotation', driver: 'low-pressure spool angle θlp', expression: 'rotate fan about engine axis at low spool speed', phaseDeg: 0, notes: 'Use visible blade blur at high RPM while keeping hoverable root geometry.', }, { id: 'lp-spool-rotation', label: 'Low-pressure spool rotation', targetPartIds: ['fan-blades', 'low-pressure-compressor', 'low-pressure-turbine', 'concentric-shafts'], transform: 'rotation', driver: 'low-pressure spool angle θlp', expression: 'rotate fan, booster, LPT, and outer shaft together', phaseDeg: 0, notes: 'Low spool should be visibly slower than high spool.', }, { id: 'hp-spool-rotation', label: 'High-pressure spool rotation', targetPartIds: ['high-pressure-compressor', 'high-pressure-turbine', 'concentric-shafts'], transform: 'rotation', driver: 'high-pressure spool angle θhp', expression: 'rotate HPC, HPT, and inner shaft at approximately 2.5× low-spool speed', phaseDeg: 0, notes: 'Separate material highlights help users distinguish nested shafts.', }, { id: 'bypass-flow', label: 'Bypass airflow', targetPartIds: ['nacelle-inlet', 'fan-blades', 'bypass-duct', 'bypass-nozzle', 'flow-splitter'], transform: 'flow', driver: 'fan pressure ratio', expression: 'cool blue ribbons pass through fan, around core, and out the annular nozzle', phaseDeg: 0, notes: 'Bypass ribbon width should exceed core ribbon width to express high mass flow.', }, { id: 'core-flow', label: 'Core gas path', targetPartIds: ['flow-splitter', 'low-pressure-compressor', 'high-pressure-compressor', 'core-nozzle'], transform: 'flow', driver: 'core spool state', expression: 'blue core flow compresses, turns amber through combustor, and exits core nozzle', phaseDeg: 0, notes: 'Color gradient communicates temperature rise.', }, { id: 'fuel-spray', label: 'Fuel spray', targetPartIds: ['turbofan-combustor'], transform: 'flow', driver: 'throttle fraction', expression: 'subtle annular amber spray into combustor primary zone', phaseDeg: 0, notes: 'Steady rather than piston-like pulses.', }, { id: 'combustion-glow', label: 'Combustion glow', targetPartIds: ['turbofan-combustor'], transform: 'material', driver: 'fuel spray intensity', expression: 'warm stable glow with soft low-frequency flicker', phaseDeg: 0, notes: 'Glow intensity can scale with RPM slider.', }, ], }, explodedView: { defaultDistance: 0.3, maxDistance: 1.18, groups: [ { id: 'nacelle-open', label: 'Nacelle and bypass duct', partIds: ['nacelle-inlet', 'bypass-duct', 'bypass-nozzle'], axis: 'y', direction: 1, order: 1, reason: 'Lifts the outer duct to reveal core and flow split.', }, { id: 'fan-forward', label: 'Fan', partIds: ['fan-blades', 'flow-splitter'], axis: 'x', direction: -1, order: 2, reason: 'Separates the large fan from the core inlet.', }, { id: 'core-up', label: 'Core spool', partIds: ['low-pressure-compressor', 'high-pressure-compressor', 'turbofan-combustor', 'high-pressure-turbine'], axis: 'y', direction: 1, order: 3, reason: 'Shows compressor-combustor-turbine sequence inside the bypass duct.', }, { id: 'rear-hot-section', label: 'Rear turbine and shafts', partIds: ['low-pressure-turbine', 'concentric-shafts', 'core-nozzle'], axis: 'y', direction: -1, order: 4, reason: 'Exposes concentric shaft routing and low-pressure turbine drive.', }, ], }, crossSection: { defaultAxis: 'z', recommendedPlanes: [ { id: 'full-flow-split', label: 'Full flow split', axis: 'z', offset: 0, description: 'Longitudinal cutaway through fan, bypass duct, core, and nozzles.', }, { id: 'fan-disc', label: 'Fan disc', axis: 'x', offset: -1.7, description: 'Radial slice through the fan showing bypass annulus and core inlet.', }, ], }, thumbnail: makeThumbnailStrategy( ['nacelle-inlet', 'fan-blades', 'bypass-duct'], ['flow-splitter', 'turbofan-combustor', 'core-nozzle'], 'Show a large frontal fan with a transparent bypass duct and split blue/amber flow to distinguish it from the turbojet thumbnail.', ), assetReplacement: { proceduralBlueprintId: 'turbofan-engine', preferredGlbPath: 'src/assets/machines/turbofan-engine/turbofan-engine.glb', rootNodeName: 'TurbofanEngine', requiredNamedNodes: [ 'FanBlades', 'NacelleInlet', 'BypassDuct', 'FlowSplitter', 'LowPressureCompressor', 'HighPressureCompressor', 'TurbofanCombustor', 'HighPressureTurbine', 'LowPressureTurbine', 'ConcentricShafts', 'BypassNozzle', 'CoreNozzle', ], optionalNamedNodes: ['FanOutletGuideVanes', 'AccessoryGearbox', 'ThrustReverserSleeve', 'PylonStub', 'FuelManifold'], materialSlots: ['painted-nacelle', 'composite-fan', 'titanium', 'heat-alloy', 'flow-blue', 'flow-amber', 'combustion-emissive'], coordinateSystem: 'Y up, engine axis along X from fan at negative X to exhaust at positive X, origin at low-pressure shaft centre.', replacementInstructions: 'Separate fan, LP spool, HP spool, bypass duct, core nozzle, and bypass nozzle. Preserve annular duct geometry for clipping and selectable bypass-flow explanations.', }, relatedMachines: ['turbojet-engine', 'turbocharger', 'centrifugal-pump'], }, ] as const satisfies readonly MachineDossier[];