type Vector3Tuple = readonly [number, number, number]; type MachineDifficulty = 'Beginner' | 'Intermediate' | 'Advanced'; type StructuralOtherCategory = 'Structural / Other'; interface DossierSpec { readonly label: string; readonly value: string; readonly note?: string; } interface EngineeringFact { readonly label: string; readonly value: string; readonly context: string; } interface DossierPart { readonly id: string; readonly name: string; readonly role: string; readonly description: string; readonly parentId?: string; readonly materialHint: string; readonly defaultVisible: boolean; readonly defaultOpacity: number; readonly explodeVector: Vector3Tuple; readonly labelPosition: Vector3Tuple; readonly replacementNodeNames: readonly string[]; readonly specs?: readonly DossierSpec[]; readonly animationNotes?: readonly string[]; } interface DossierCameraPreset { readonly id: string; readonly label: string; readonly position: Vector3Tuple; readonly target: Vector3Tuple; readonly fov: number; readonly description: string; } interface DossierLabel { readonly id: string; readonly partId: string; readonly text: string; readonly position: Vector3Tuple; readonly priority: 'primary' | 'secondary' | 'detail'; } interface DossierTourStep { readonly id: string; readonly title: string; readonly body: string; readonly durationSeconds: number; readonly cameraPreset: string; readonly focusPartIds: readonly string[]; readonly animationCue?: string; } interface DossierAnimation { readonly loopSeconds: number; readonly defaultRpm: number; readonly rpmRange: readonly [number, number]; readonly stepCount: number; readonly principalMotion: string; readonly physicallyBelievableNotes: readonly string[]; readonly moduleHooks: { readonly cyclePhase: string; readonly transformChannels: readonly string[]; }; } interface DossierExplodedView { readonly defaultDistance: number; readonly maxDistance: number; readonly groups: readonly { readonly id: string; readonly name: string; readonly partIds: readonly string[]; readonly direction: Vector3Tuple; readonly order: number; readonly note: string; }[]; } interface ProceduralVisualization { readonly assemblyStyle: string; readonly primitives: readonly string[]; readonly motionReference: string; readonly approximationNotes: readonly string[]; readonly swapReadyNodes: readonly string[]; } interface AssetReplacementPlan { readonly primaryGlbPath: string; readonly nodeNamingConvention: string; readonly scaleMetersPerUnit: number; readonly pivotRequirements: readonly string[]; readonly textureSets: readonly string[]; readonly validationChecklist: readonly string[]; } interface ThumbnailStrategy { readonly strategy: string; readonly cameraPreset: string; readonly highlightedPartIds: readonly string[]; readonly background: string; readonly filenameSuggestion: string; } interface StructuralOtherDossier { readonly machineId: string; readonly title: string; readonly category: StructuralOtherCategory; readonly difficulty: MachineDifficulty; readonly description: string; readonly learningObjectives: readonly string[]; readonly engineeringFacts: readonly EngineeringFact[]; readonly relatedMachines: readonly string[]; readonly components: readonly DossierPart[]; readonly cameraPresets: readonly DossierCameraPreset[]; readonly explodedView: DossierExplodedView; readonly labels: readonly DossierLabel[]; readonly guidedTour: readonly DossierTourStep[]; readonly animation: DossierAnimation; readonly proceduralVisualization: ProceduralVisualization; readonly assetReplacement: AssetReplacementPlan; readonly thumbnail: ThumbnailStrategy; readonly accessibilitySummary: string; } const bearingCameraPresets = [ { id: 'isometric', label: 'Isometric', position: [4.8, 3.2, 5], target: [0, 0, 0], fov: 40, description: 'Balanced bearing view showing races, rolling elements, cage, and load overlays.', }, { id: 'front', label: 'Front section', position: [0, 0.8, 6], target: [0, 0, 0], fov: 36, description: 'Axial view for counting rolling elements and reading load distribution.', }, { id: 'right', label: 'Side section', position: [6, 1.2, 0], target: [0, 0, 0], fov: 38, description: 'Radial side view emphasizing contact geometry and section cut.', }, { id: 'top', label: 'Top', position: [0, 6.2, 0.05], target: [0, 0, 0], fov: 42, description: 'Plan view for inspecting cage spacing and orbital motion.', }, { id: 'exploded', label: 'Exploded reference', position: [5.5, 3.8, 5.8], target: [0, 0, 0], fov: 45, description: 'Camera tuned for separated races and rolling elements.', }, ] as const satisfies readonly DossierCameraPreset[]; const brakeTurboCameraPresets = [ { id: 'isometric', label: 'Isometric', position: [5.6, 3.3, 5.4], target: [0, 0.2, 0], fov: 42, description: 'Premium product-style view showing the primary working faces and flow/force overlays.', }, { id: 'front', label: 'Front', position: [0, 1.4, 6.4], target: [0, 0.15, 0], fov: 38, description: 'Front view for reading symmetry and clamping or flow paths.', }, { id: 'right', label: 'Right side', position: [6.4, 1.5, 0], target: [0, 0.15, 0], fov: 40, description: 'Side view exposing axial stack-up and service components.', }, { id: 'top', label: 'Top', position: [0, 6.5, 0.05], target: [0, 0, 0], fov: 42, description: 'Top view for understanding port routing, caliper bridge, or volute shapes.', }, { id: 'exploded', label: 'Exploded reference', position: [6.2, 4.1, 6], target: [0, 0.15, 0], fov: 46, description: 'Wide view prepared for exploded assemblies and overlay labels.', }, ] as const satisfies readonly DossierCameraPreset[]; export const structuralOtherDossiers = [ { machineId: 'ball-bearing', title: 'Ball Bearing', category: 'Structural / Other', difficulty: 'Beginner', description: 'A ball bearing supports rotating shafts with low friction by separating inner and outer races using rolling balls held by a cage. The contact is small and efficient, making ball bearings well suited to high-speed radial loads.', learningObjectives: [ 'Identify inner race, outer race, rolling balls, cage, seals, and load path.', 'Understand rolling contact versus sliding friction.', 'See how load is distributed among only a subset of balls at a time.', 'Recognize why lubrication and contamination control are critical.', ], engineeringFacts: [ { label: 'Primary contact type', value: 'Point contact', context: 'Balls contact the raceways over small elliptical patches, reducing friction but limiting load compared with rollers.', }, { label: 'Common speed capability', value: 'High speed', context: 'Deep-groove ball bearings are common in motors, fans, wheels, and light machinery where speed matters.', }, { label: 'Load direction', value: 'Radial with moderate axial capacity', context: 'Deep-groove geometry can carry radial load and some thrust load in both directions.', }, { label: 'Key service issue', value: 'Lubrication and contamination', context: 'Small particles or lubricant breakdown can damage raceways and create noise or spalling.', }, ], relatedMachines: ['roller-bearing', 'manual-gearbox', 'jet-engine', 'turbocharger'], components: [ { id: 'outer-race', name: 'Outer race', role: 'Stationary bearing ring', description: 'The outer race provides the fixed raceway for the balls and transfers radial load into the housing.', materialHint: 'polished bearing steel outer ring', defaultVisible: true, defaultOpacity: 1, explodeVector: [0, 0, -0.65], labelPosition: [0, 1.75, 0.35], replacementNodeNames: ['OuterRace', 'OuterRing', 'BearingOuter'], specs: [ { label: 'Function', value: 'housing-side raceway' }, { label: 'Load path', value: 'balls to housing' }, ], }, { id: 'inner-race', name: 'Inner race', role: 'Rotating shaft-side ring', description: 'The inner race is mounted to the shaft and rotates with it, presenting a hardened groove to the balls.', parentId: 'rotation-axis', materialHint: 'brushed bearing steel inner ring', defaultVisible: true, defaultOpacity: 1, explodeVector: [0, 0, 0.65], labelPosition: [0, 0.9, 0.8], replacementNodeNames: ['InnerRace', 'InnerRing', 'BearingInner'], specs: [{ label: 'Motion', value: 'rotates with shaft' }], animationNotes: ['Rotate with shaft at commanded speed.'], }, { id: 'ball-set', name: 'Ball set', role: 'Rolling elements', description: 'The balls roll between the two raceways, carrying load through small contact patches. The procedural bearing uses instancing for performance.', parentId: 'cage', materialHint: 'mirror-polished steel balls', defaultVisible: true, defaultOpacity: 1, explodeVector: [0, 0.45, 0], labelPosition: [1.35, 1.15, 0.25], replacementNodeNames: ['BallSet', 'Balls', 'RollingElements'], specs: [ { label: 'Element count', value: '10 procedural balls', note: 'Replacement assets may use any count if IDs remain grouped.' }, { label: 'Contact', value: 'point/elliptical contact' }, ], animationNotes: ['Orbit around bearing center and counter-rotate for rolling impression.'], }, { id: 'cage', name: 'Cage / separator', role: 'Maintains ball spacing', description: 'The cage spaces the balls evenly, prevents rubbing between adjacent balls, and guides rolling elements through unloaded zones.', materialHint: 'warm brass or polymer cage', defaultVisible: true, defaultOpacity: 1, explodeVector: [0, 0.3, 0.25], labelPosition: [-1.35, 1.1, 0.35], replacementNodeNames: ['Cage', 'Separator', 'BallCage'], animationNotes: ['Rotate at an intermediate speed between inner and outer race.'], }, { id: 'seal-shield-front', name: 'Front seal shield', role: 'Keeps lubricant in and debris out', description: 'A thin shield or seal protects the rolling contact from contamination. It is semi-transparent in the procedural view.', parentId: 'outer-race', materialHint: 'smoked translucent seal', defaultVisible: true, defaultOpacity: 0.35, explodeVector: [0, 0, 1.1], labelPosition: [-1.15, -0.75, 0.95], replacementNodeNames: ['FrontSeal', 'SealShieldFront', 'Shield_Front'], }, { id: 'seal-shield-rear', name: 'Rear seal shield', role: 'Rear contamination barrier', description: 'The rear shield completes the sealed bearing context and can be hidden to inspect the rolling elements.', parentId: 'outer-race', materialHint: 'smoked translucent seal', defaultVisible: true, defaultOpacity: 0.28, explodeVector: [0, 0, -1.1], labelPosition: [1.1, -0.8, -0.95], replacementNodeNames: ['RearSeal', 'SealShieldRear', 'Shield_Rear'], }, { id: 'load-vectors', name: 'Load distribution vectors', role: 'Educational force overlay', description: 'Arrows show that only balls in the loaded zone carry significant force at any instant.', parentId: 'outer-race', materialHint: 'emissive blue-to-amber load arrows', defaultVisible: true, defaultOpacity: 0.86, explodeVector: [0, 0.75, 0.4], labelPosition: [0.9, 1.95, 0.65], replacementNodeNames: ['LoadVectors', 'LoadDistribution', 'ForceArrows'], animationNotes: ['Rotate or pulse with selected load direction; scale arrows by ball load share.'], }, { id: 'lubricant-film', name: 'Lubricant film', role: 'Reduces wear and heat', description: 'A subtle transparent film in the raceway communicates lubrication without obscuring the rolling elements.', parentId: 'outer-race', materialHint: 'transparent amber oil film', defaultVisible: true, defaultOpacity: 0.34, explodeVector: [0, 0.15, 0.35], labelPosition: [0.2, 1.35, 0.55], replacementNodeNames: ['LubricantFilm', 'OilFilm', 'GreaseFilm'], }, { id: 'cutaway-sector', name: 'Cutaway sector', role: 'Cross-section teaching aid', description: 'A removed sector exposes the race grooves, ball contact, cage pockets, and seals for inspection.', parentId: 'outer-race', materialHint: 'dark clipped-section surface', defaultVisible: true, defaultOpacity: 0.72, explodeVector: [-0.35, 0.35, 0.35], labelPosition: [-1.35, 1.55, 0.55], replacementNodeNames: ['CutawaySector', 'SectionCut', 'Cutaway'], }, { id: 'rotation-axis', name: 'Rotation axis', role: 'Shaft centerline overlay', description: 'A blue centerline shows the common axis of the inner race, cage, and rolling elements.', materialHint: 'emissive blue axis line', defaultVisible: true, defaultOpacity: 0.8, explodeVector: [0, 0, 0], labelPosition: [0, -1.4, 0.25], replacementNodeNames: ['RotationAxis', 'ShaftAxis', 'AxisOverlay'], }, ], cameraPresets: bearingCameraPresets, explodedView: { defaultDistance: 0.65, maxDistance: 2.6, groups: [ { id: 'race-rings', name: 'Race rings', partIds: ['outer-race', 'inner-race', 'cutaway-sector'], direction: [0, 0, -1], order: 1, note: 'Separates inner and outer race stack along the shaft axis.', }, { id: 'rolling-elements', name: 'Rolling elements and cage', partIds: ['ball-set', 'cage', 'lubricant-film'], direction: [0, 0.55, 0.25], order: 2, note: 'Lifts balls and cage to reveal pockets and lubrication path.', }, { id: 'seals-and-overlays', name: 'Seals and overlays', partIds: ['seal-shield-front', 'seal-shield-rear', 'load-vectors', 'rotation-axis'], direction: [0, 0.7, 0.65], order: 3, note: 'Moves shields and teaching overlays away from the raceway.', }, ], }, labels: [ { id: 'ball-bearing-label-outer', partId: 'outer-race', text: 'Outer race carries housing load', position: [0, 1.85, 0.45], priority: 'primary', }, { id: 'ball-bearing-label-balls', partId: 'ball-set', text: 'Rolling balls reduce friction', position: [1.35, 1.25, 0.35], priority: 'primary', }, { id: 'ball-bearing-label-cage', partId: 'cage', text: 'Cage spaces balls evenly', position: [-1.35, 1.2, 0.45], priority: 'primary', }, { id: 'ball-bearing-label-load', partId: 'load-vectors', text: 'Loaded zone', position: [0.9, 2.05, 0.75], priority: 'secondary', }, { id: 'ball-bearing-label-seal', partId: 'seal-shield-front', text: 'Seal keeps contaminants out', position: [-1.15, -0.65, 1.05], priority: 'detail', }, ], guidedTour: [ { id: 'raceways-and-balls', title: 'Rolling contact between raceways', body: 'The inner race rotates with the shaft while balls roll in the grooves. Rolling contact dramatically reduces friction compared with sliding support.', durationSeconds: 7, cameraPreset: 'front', focusPartIds: ['inner-race', 'outer-race', 'ball-set'], animationCue: 'slow rotation with alternating ball highlights', }, { id: 'cage-and-lubrication', title: 'Spacing and lubrication', body: 'The cage keeps balls separated, and a thin lubricant film prevents metal-to-metal damage at the contact patches.', durationSeconds: 6, cameraPreset: 'isometric', focusPartIds: ['cage', 'lubricant-film', 'seal-shield-front'], animationCue: 'fade seals to reveal cage pockets and oil film', }, { id: 'load-path', title: 'How load travels through the bearing', body: 'Radial load is not shared equally by every ball. The arrows show the loaded zone where the greatest contact forces occur.', durationSeconds: 7, cameraPreset: 'right', focusPartIds: ['load-vectors', 'ball-set', 'outer-race'], animationCue: 'pulse vectors over balls in the loaded arc', }, ], animation: { loopSeconds: 4, defaultRpm: 90, rpmRange: [5, 1200], stepCount: 12, principalMotion: 'Inner race rotates with the shaft; balls orbit in the cage and spin about their own axes; cage rotates at reduced speed; load vectors pulse in the loaded zone.', physicallyBelievableNotes: [ 'Ball orbital speed is lower than inner-race surface speed to evoke rolling kinematics.', 'Ball spin direction is opposite relative sliding direction at the race contact.', 'The outer race remains stationary by default to clarify shaft-side rotation.', ], moduleHooks: { cyclePhase: 'theta = TAU * normalizedCycleTime; cageTheta = theta * cageSpeedRatio', transformChannels: [ 'inner-race.rotation.z', 'cage.rotation.z', 'ball-set.instanceOrbit', 'ball-set.instanceSpin', 'load-vectors.intensity', 'lubricant-film.opacityPulse', ], }, }, proceduralVisualization: { assemblyStyle: 'Cutaway deep-groove bearing with instanced balls, transparent shields, load arrows, and lubricant overlay.', primitives: [ 'torus/ring meshes for inner and outer races', 'instanced spheres for balls', 'thin ring with pockets for cage', 'transparent disks for seals', 'arrow meshes for load distribution', 'axis and section overlay lines', ], motionReference: 'Use bearing pitch radius and ball count to place ball instances evenly and keep cage phase synchronized.', approximationNotes: [ 'Raceway curvature is simplified but visually communicates a deep-groove ball bearing.', 'Contact ellipses are represented by small glowing patches instead of deformation simulation.', ], swapReadyNodes: [ 'OuterRace', 'InnerRace', 'BallSet', 'Cage', 'FrontSeal', 'RearSeal', 'LoadVectors', 'LubricantFilm', 'CutawaySector', 'RotationAxis', ], }, assetReplacement: { primaryGlbPath: '/assets/machines/ball-bearing/ball-bearing.glb', nodeNamingConvention: 'Keep races, cage, seals, and rolling elements as independently named nodes; ball instances may be grouped under BallSet.', scaleMetersPerUnit: 1, pivotRequirements: [ 'InnerRace origin on shaft axis.', 'Cage origin on shaft axis.', 'BallSet group origin on bearing center with individual ball transforms available for instancing or child nodes.', 'LoadVectors origin on bearing center for rotating load-direction overlays.', ], textureSets: ['polished-bearing-steel', 'brass-cage', 'smoked-seal', 'transparent-lubricant'], validationChecklist: [ 'Inner race, cage, and ball orbit remain concentric.', 'Outer race stays fixed under default animation.', 'Seals can be hidden without hiding rolling elements.', 'Load vectors remain readable in cross-section mode.', ], }, thumbnail: { strategy: 'Render a cutaway isometric with polished balls visible, brass cage highlighted, and a blue radial load arrow entering the outer race.', cameraPreset: 'isometric', highlightedPartIds: ['ball-set', 'cage', 'load-vectors'], background: 'dark circular technical grid with subtle radial gradient', filenameSuggestion: 'ball-bearing-card.webp', }, accessibilitySummary: 'Accessible playback should announce stationary outer race, rotating inner race, orbiting balls, and loaded-zone direction; ball count should be exposed as text.', }, { machineId: 'roller-bearing', title: 'Roller Bearing', category: 'Structural / Other', difficulty: 'Intermediate', description: 'A tapered roller bearing supports heavier radial and axial loads by using conical rollers between matching cup and cone raceways. The line-contact geometry spreads load over a larger area than a ball bearing.', learningObjectives: [ 'Identify tapered rollers, cone, cup, cage, preload nut, and contact lines.', 'Understand why tapered geometry carries combined radial and thrust loads.', 'Compare line contact in roller bearings with point contact in ball bearings.', 'Recognize preload, lubrication, and alignment as critical setup variables.', ], engineeringFacts: [ { label: 'Primary contact type', value: 'Line contact', context: 'Rollers contact raceways along elongated patches, increasing load capacity but also friction and alignment sensitivity.', }, { label: 'Load capability', value: 'Combined radial + axial', context: 'Tapered rollers generate thrust reaction and are often paired opposed in wheel hubs and gearboxes.', }, { label: 'Setup variable', value: 'Preload / endplay', context: 'Correct adjustment controls stiffness, heat generation, and bearing life.', }, { label: 'Common applications', value: 'Wheel hubs, differentials, heavy gearboxes', context: 'High load capacity makes tapered rollers common wherever shafts see gear thrust or vehicle loads.', }, ], relatedMachines: ['ball-bearing', 'differential-gear', 'manual-gearbox', 'worm-gear-drive'], components: [ { id: 'outer-cup', name: 'Outer cup', role: 'Stationary tapered outer race', description: 'The cup contains the outer tapered raceway and transmits load into the housing.', materialHint: 'polished bearing steel cup', defaultVisible: true, defaultOpacity: 1, explodeVector: [0, 0, -0.75], labelPosition: [0, 1.75, 0.4], replacementNodeNames: ['OuterCup', 'Cup', 'OuterRace'], specs: [{ label: 'Raceway', value: 'tapered outer cone surface' }], }, { id: 'inner-cone', name: 'Inner cone', role: 'Shaft-side tapered race', description: 'The cone mounts to the shaft and supports the roller set. Its tapered raceway aligns with the roller apex geometry.', materialHint: 'brushed bearing steel cone', defaultVisible: true, defaultOpacity: 1, explodeVector: [0, 0, 0.75], labelPosition: [0, 0.85, 0.9], replacementNodeNames: ['InnerCone', 'Cone', 'InnerRace'], animationNotes: ['Rotate with shaft.'], }, { id: 'tapered-rollers', name: 'Tapered rollers', role: 'High-capacity rolling elements', description: 'Conical rollers create line contact with both raceways. Their projected axes meet near a common apex to minimize sliding.', parentId: 'cage', materialHint: 'polished steel rollers', defaultVisible: true, defaultOpacity: 1, explodeVector: [0, 0.5, 0.1], labelPosition: [1.35, 1.1, 0.35], replacementNodeNames: ['TaperedRollers', 'Rollers', 'RollingElements'], specs: [ { label: 'Contact', value: 'line contact' }, { label: 'Geometry', value: 'conical rollers' }, ], animationNotes: ['Orbit around bearing axis and spin around each roller axis.'], }, { id: 'cage', name: 'Roller cage', role: 'Spaces and guides rollers', description: 'The cage keeps tapered rollers evenly spaced and oriented while allowing oil flow through the bearing.', materialHint: 'warm brass cage', defaultVisible: true, defaultOpacity: 1, explodeVector: [0, 0.35, 0.28], labelPosition: [-1.35, 1.05, 0.45], replacementNodeNames: ['Cage', 'RollerCage', 'Separator'], animationNotes: ['Rotate at reduced cage speed.'], }, { id: 'contact-lines', name: 'Contact line overlay', role: 'Shows load-bearing line contacts', description: 'Thin highlighted strips identify where each roller contacts the cup and cone under load.', parentId: 'tapered-rollers', materialHint: 'emissive amber contact strips', defaultVisible: true, defaultOpacity: 0.9, explodeVector: [0, 0.65, 0.35], labelPosition: [0.95, 1.65, 0.55], replacementNodeNames: ['ContactLines', 'LineContactOverlay', 'ContactStrips'], animationNotes: ['Pulse on loaded rollers and fade on unloaded rollers.'], }, { id: 'preload-nut', name: 'Preload nut', role: 'Adjusts axial preload or endplay', description: 'The nut illustrates how tapered roller bearings are set. Too little preload creates looseness; too much creates heat and wear.', parentId: 'inner-cone', materialHint: 'dark zinc locknut', defaultVisible: true, defaultOpacity: 1, explodeVector: [0, 0, 1.15], labelPosition: [-1.1, -0.85, 1.05], replacementNodeNames: ['PreloadNut', 'AdjustingNut', 'LockNut'], specs: [{ label: 'Adjustment', value: 'preload / endplay' }], }, { id: 'load-vectors', name: 'Radial and axial load vectors', role: 'Educational load overlay', description: 'Combined radial and thrust arrows show why tapered rollers are frequently installed in opposed pairs.', parentId: 'outer-cup', materialHint: 'blue radial and amber axial arrows', defaultVisible: true, defaultOpacity: 0.86, explodeVector: [0, 0.75, 0.5], labelPosition: [1.1, 2, 0.7], replacementNodeNames: ['LoadVectors', 'RadialAxialLoadArrows', 'ForceOverlay'], }, { id: 'bearing-seat', name: 'Housing seat', role: 'Reference support surface', description: 'The seat shows where the outer cup is pressed into a housing and how load leaves the bearing.', parentId: 'outer-cup', materialHint: 'matte dark housing ring', defaultVisible: true, defaultOpacity: 0.72, explodeVector: [0, -0.2, -0.35], labelPosition: [0, -1.35, -0.45], replacementNodeNames: ['BearingSeat', 'HousingSeat', 'SupportHousing'], }, { id: 'lubrication-groove', name: 'Lubrication groove', role: 'Oil path teaching feature', description: 'A transparent groove indicates how oil or grease reaches the roller/raceway contacts.', parentId: 'outer-cup', materialHint: 'transparent amber lubricant path', defaultVisible: true, defaultOpacity: 0.42, explodeVector: [0, 0.3, 0.45], labelPosition: [-0.7, 1.45, 0.65], replacementNodeNames: ['LubricationGroove', 'OilPath', 'GreasePath'], }, { id: 'section-plane', name: 'Section plane', role: 'Cross-section aid', description: 'The cut plane exposes roller taper and the cup/cone relationship without requiring a full CAD section model.', parentId: 'outer-cup', materialHint: 'transparent blue section surface', defaultVisible: true, defaultOpacity: 0.36, explodeVector: [-0.45, 0.45, 0.45], labelPosition: [-1.45, 1.55, 0.65], replacementNodeNames: ['SectionPlane', 'CutPlane', 'SectionOverlay'], }, ], cameraPresets: bearingCameraPresets, explodedView: { defaultDistance: 0.68, maxDistance: 2.75, groups: [ { id: 'cup-and-seat', name: 'Cup and housing', partIds: ['outer-cup', 'bearing-seat', 'section-plane'], direction: [0, 0, -1], order: 1, note: 'Separates fixed outer support geometry from the rotating cone.', }, { id: 'cone-and-adjuster', name: 'Cone and preload adjuster', partIds: ['inner-cone', 'preload-nut'], direction: [0, 0, 1], order: 2, note: 'Moves shaft-side cone and adjustment nut forward.', }, { id: 'roller-pack', name: 'Roller pack', partIds: ['tapered-rollers', 'cage', 'contact-lines', 'lubrication-groove', 'load-vectors'], direction: [0, 0.65, 0.35], order: 3, note: 'Lifts the cage and rollers to reveal line contacts and oil path.', }, ], }, labels: [ { id: 'roller-bearing-label-cup', partId: 'outer-cup', text: 'Outer cup raceway', position: [0, 1.85, 0.5], priority: 'primary', }, { id: 'roller-bearing-label-rollers', partId: 'tapered-rollers', text: 'Tapered rollers carry line contact', position: [1.35, 1.2, 0.45], priority: 'primary', }, { id: 'roller-bearing-label-preload', partId: 'preload-nut', text: 'Preload controls endplay', position: [-1.1, -0.75, 1.15], priority: 'primary', }, { id: 'roller-bearing-label-contact', partId: 'contact-lines', text: 'Line-contact strips', position: [0.95, 1.75, 0.65], priority: 'secondary', }, { id: 'roller-bearing-label-load', partId: 'load-vectors', text: 'Radial + axial load', position: [1.1, 2.1, 0.8], priority: 'detail', }, ], guidedTour: [ { id: 'tapered-geometry', title: 'Why the rollers are tapered', body: 'The rollers, cup, and cone are all angled so their projected surfaces roll together while supporting both radial and thrust loads.', durationSeconds: 7, cameraPreset: 'right', focusPartIds: ['outer-cup', 'inner-cone', 'tapered-rollers', 'section-plane'], animationCue: 'show section plane and highlight taper apex lines', }, { id: 'line-contact-capacity', title: 'Line contact increases load capacity', body: 'Compared with a ball bearing, the elongated contact strips spread force over more area, improving load capacity at the cost of higher friction.', durationSeconds: 7, cameraPreset: 'isometric', focusPartIds: ['tapered-rollers', 'contact-lines', 'load-vectors'], animationCue: 'pulse contact strips under load vectors', }, { id: 'preload-setting', title: 'Preload matters', body: 'The preload nut sets endplay. Correct preload gives stiffness and long life; excessive preload overheats the bearing.', durationSeconds: 6, cameraPreset: 'front', focusPartIds: ['preload-nut', 'inner-cone', 'lubrication-groove'], animationCue: 'animate small axial adjustment and update preload gauge', }, ], animation: { loopSeconds: 4.5, defaultRpm: 75, rpmRange: [5, 900], stepCount: 12, principalMotion: 'Inner cone rotates; roller pack orbits and each tapered roller spins about its angled axis; line-contact overlays pulse with the load zone.', physicallyBelievableNotes: [ 'Roller axes remain angled toward the bearing apex to communicate tapered geometry.', 'Cage speed is reduced relative to inner cone rotation.', 'Preload demo is a guided-tour overlay and does not shift the geometry during normal playback.', ], moduleHooks: { cyclePhase: 'theta = TAU * normalizedCycleTime; cageTheta = theta * cageSpeedRatio', transformChannels: [ 'inner-cone.rotation.z', 'cage.rotation.z', 'tapered-rollers.instanceOrbit', 'tapered-rollers.instanceSpin', 'contact-lines.intensity', 'preload-nut.axialOffset', 'load-vectors.intensity', ], }, }, proceduralVisualization: { assemblyStyle: 'Sectioned tapered roller bearing with conical races, angled rollers, contact strips, preload adjuster, and load overlays.', primitives: [ 'truncated cones/rings for cup and cone', 'instanced tapered cylinders for rollers', 'ring cage with roller pockets', 'transparent section plane', 'locknut cylinder with grooves', 'radial and axial arrow overlays', ], motionReference: 'Use roller pitch radius, taper angle, and roller count to orient each roller toward the theoretical apex.', approximationNotes: [ 'Roller/race contact geometry is diagrammatic and prioritizes readable taper over exact bearing standards.', 'The preload nut is shown externally for education even though many assemblies use different retention hardware.', ], swapReadyNodes: [ 'OuterCup', 'InnerCone', 'TaperedRollers', 'Cage', 'ContactLines', 'PreloadNut', 'LoadVectors', 'BearingSeat', 'LubricationGroove', 'SectionPlane', ], }, assetReplacement: { primaryGlbPath: '/assets/machines/roller-bearing/roller-bearing.glb', nodeNamingConvention: 'Use bearing terminology Cup, Cone, Rollers, Cage, and PreloadNut in node names; group individual rollers if instancing is not used.', scaleMetersPerUnit: 1, pivotRequirements: [ 'InnerCone origin on bearing axis.', 'Cage origin on bearing axis.', 'TaperedRollers group origin on bearing center with per-roller angled local axes if possible.', 'PreloadNut origin on bearing axis and movable along axial Z for preload demonstration.', ], textureSets: ['polished-bearing-steel', 'brass-cage', 'dark-housing-seat', 'amber-contact-overlay'], validationChecklist: [ 'Rollers do not appear cylindrical in side section; taper should be visible.', 'ContactLines align with roller/race interfaces.', 'PreloadNut remains separate from InnerCone for guided tour animation.', 'Load vectors include both radial and axial components.', ], }, thumbnail: { strategy: 'Use a side-cut isometric that clearly shows tapered rollers, amber line contacts, and a blue/amber combined load arrow pair.', cameraPreset: 'isometric', highlightedPartIds: ['tapered-rollers', 'contact-lines', 'load-vectors'], background: 'dark circular grid with faint cone-angle construction lines', filenameSuggestion: 'roller-bearing-card.webp', }, accessibilitySummary: 'Step states should describe loaded roller zone, preload adjustment state, and whether the current view is radial, axial, or sectioned.', }, { machineId: 'disc-brake-caliper', title: 'Disc Brake Caliper', category: 'Structural / Other', difficulty: 'Intermediate', description: 'A disc brake caliper converts hydraulic pressure into clamping force on brake pads, squeezing a spinning rotor to create friction torque and heat. The model emphasizes piston actuation, pad contact, sliding supports, and thermal loading.', learningObjectives: [ 'Trace hydraulic pressure from line to piston to pad force.', 'Identify rotor, caliper body, pistons, pads, slide pins, seals, and bleed screw.', 'Understand friction torque and heat generation during braking.', 'Compare fixed and floating caliper behavior using the procedural floating-caliper layout.', ], engineeringFacts: [ { label: 'Force source', value: 'Hydraulic pressure × piston area', context: 'Brake fluid pressure acts on caliper pistons, producing clamping force on the pads.', }, { label: 'Energy conversion', value: 'Kinetic energy → heat', context: 'The brake slows the rotor by converting vehicle kinetic energy into heat at the pad/rotor interfaces.', }, { label: 'Service wear item', value: 'Pads and rotor faces', context: 'Friction material wears intentionally and rotors must dissipate heat without cracking or excessive runout.', }, { label: 'Critical maintenance', value: 'Air-free hydraulic circuit', context: 'Air compressibility causes a spongy pedal, so bleed screws allow trapped air to be removed.', }, ], relatedMachines: ['hydraulic-cylinder', 'ball-bearing', 'toggle-clamp', 'differential-gear'], components: [ { id: 'rotor', name: 'Brake rotor / disc', role: 'Rotating friction surface', description: 'The rotor spins with the wheel hub. Pads clamp both faces to create braking torque and heat.', materialHint: 'dark iron rotor with heat tint', defaultVisible: true, defaultOpacity: 1, explodeVector: [0, 0, -0.55], labelPosition: [0, 1.55, 0.35], replacementNodeNames: ['Rotor', 'BrakeDisc', 'Disc'], specs: [ { label: 'Function', value: 'rotating friction member' }, { label: 'Energy', value: 'kinetic to thermal' }, ], animationNotes: ['Rotate around axle axis; decelerate during braking cue.'], }, { id: 'caliper-body', name: 'Caliper body', role: 'Structural hydraulic clamp housing', description: 'The caliper body bridges over the rotor and supports the piston bores, pad abutments, and slide pins.', materialHint: 'blue anodized or painted caliper casting', defaultVisible: true, defaultOpacity: 1, explodeVector: [0.55, 0.12, 0.25], labelPosition: [1.25, 1.05, 0.55], replacementNodeNames: ['CaliperBody', 'Caliper', 'BridgeBody'], specs: [{ label: 'Type shown', value: 'floating single-sided piston concept' }], }, { id: 'pistons', name: 'Hydraulic pistons', role: 'Convert pressure into pad force', description: 'Pistons move outward from the caliper bore as fluid pressure rises, pressing the inner pad into the rotor.', parentId: 'caliper-body', materialHint: 'polished steel pistons', defaultVisible: true, defaultOpacity: 1, explodeVector: [0.75, 0.15, 0.45], labelPosition: [1.6, 0.55, 0.75], replacementNodeNames: ['Pistons', 'HydraulicPistons', 'CaliperPistons'], specs: [{ label: 'Clamp force', value: 'pressure × piston area' }], animationNotes: ['Translate toward rotor faces during braking phase.'], }, { id: 'inner-pad', name: 'Inner brake pad', role: 'Friction lining on piston side', description: 'The piston pushes the inner pad into the rotor. Friction material is intentionally replaceable.', parentId: 'caliper-body', materialHint: 'graphite friction material with steel backing', defaultVisible: true, defaultOpacity: 1, explodeVector: [0.25, 0, 0.45], labelPosition: [0.7, 0.25, 0.75], replacementNodeNames: ['InnerPad', 'PadInner', 'PistonSidePad'], animationNotes: ['Move slightly toward rotor and glow at contact during braking.'], }, { id: 'outer-pad', name: 'Outer brake pad', role: 'Friction lining on outer side', description: 'In a floating caliper, body reaction pulls the outer pad against the opposite rotor face.', parentId: 'caliper-body', materialHint: 'graphite friction material with steel backing', defaultVisible: true, defaultOpacity: 1, explodeVector: [0.25, 0, -0.45], labelPosition: [0.7, 0.25, -0.75], replacementNodeNames: ['OuterPad', 'PadOuter', 'ReactionSidePad'], animationNotes: ['Move slightly toward rotor from the opposite side.'], }, { id: 'hydraulic-line', name: 'Hydraulic line', role: 'Carries pressurized brake fluid', description: 'The line feeds pressure from the master cylinder or brake controller to the caliper piston chamber.', parentId: 'caliper-body', materialHint: 'dark braided hose with amber pressure pulse', defaultVisible: true, defaultOpacity: 1, explodeVector: [0.85, 0.45, 0.25], labelPosition: [1.85, 1.45, 0.45], replacementNodeNames: ['HydraulicLine', 'BrakeHose', 'FluidLine'], animationNotes: ['Pulse pressure color before piston travel begins.'], }, { id: 'slide-pins', name: 'Slide pins', role: 'Allow floating caliper movement', description: 'Slide pins let the caliper body shift so both pads clamp the rotor with balanced force.', parentId: 'caliper-body', materialHint: 'polished guide pins with dark boots', defaultVisible: true, defaultOpacity: 1, explodeVector: [0.65, -0.1, 0.25], labelPosition: [1.55, -0.35, 0.4], replacementNodeNames: ['SlidePins', 'GuidePins', 'CaliperSlides'], animationNotes: ['Small caliper body translation during clamping.'], }, { id: 'dust-boots', name: 'Dust boots and seals', role: 'Protect piston and slide interfaces', description: 'Rubber boots keep contamination out of moving joints while piston seals retract the pads slightly after pressure release.', parentId: 'caliper-body', materialHint: 'black rubber seals', defaultVisible: true, defaultOpacity: 1, explodeVector: [0.55, 0.25, 0.55], labelPosition: [1.35, 0.85, 0.85], replacementNodeNames: ['DustBoots', 'PistonBoots', 'Seals'], }, { id: 'heat-band', name: 'Heat band overlay', role: 'Thermal load visualization', description: 'A warm ring on the rotor faces indicates where friction work becomes heat during braking.', parentId: 'rotor', materialHint: 'emissive amber heat gradient', defaultVisible: true, defaultOpacity: 0.78, explodeVector: [0, 0.25, 0], labelPosition: [-0.95, 1.2, 0.55], replacementNodeNames: ['HeatBand', 'ThermalOverlay', 'RotorHeat'], animationNotes: ['Intensity rises as rotor decelerates and pad contact is active.'], }, { id: 'bleed-screw', name: 'Bleed screw', role: 'Removes air from hydraulic circuit', description: 'The bleed screw is a service feature used to purge trapped air and maintain firm hydraulic response.', parentId: 'caliper-body', materialHint: 'small zinc screw with blue cap', defaultVisible: true, defaultOpacity: 1, explodeVector: [0.7, 0.35, 0.3], labelPosition: [1.45, 1.35, 0.75], replacementNodeNames: ['BleedScrew', 'BleederValve', 'BleedNipple'], }, { id: 'force-arrows', name: 'Clamp force arrows', role: 'Educational force overlay', description: 'Opposed arrows show clamping force on both rotor faces and make the floating caliper reaction easy to understand.', parentId: 'caliper-body', materialHint: 'emissive blue clamp arrows', defaultVisible: true, defaultOpacity: 0.9, explodeVector: [0, 0.65, 0.45], labelPosition: [0.25, 1.95, 0.65], replacementNodeNames: ['ForceArrows', 'ClampForceArrows', 'PressureOverlay'], animationNotes: ['Scale with hydraulic pressure and pad contact force.'], }, ], cameraPresets: brakeTurboCameraPresets, explodedView: { defaultDistance: 0.6, maxDistance: 2.6, groups: [ { id: 'rotor-stack', name: 'Rotor and heat overlay', partIds: ['rotor', 'heat-band'], direction: [0, 0, -1], order: 1, note: 'Moves the rotor stack axially to expose both pad faces.', }, { id: 'caliper-hydraulics', name: 'Caliper hydraulic body', partIds: ['caliper-body', 'pistons', 'hydraulic-line', 'dust-boots', 'bleed-screw'], direction: [1, 0.25, 0.25], order: 2, note: 'Separates the piston and service components from the rotor.', }, { id: 'pads-and-guides', name: 'Pads and guide hardware', partIds: ['inner-pad', 'outer-pad', 'slide-pins', 'force-arrows'], direction: [0.45, 0.5, 0.45], order: 3, note: 'Lifts pad and slide hardware for inspection.', }, ], }, labels: [ { id: 'disc-brake-label-rotor', partId: 'rotor', text: 'Rotor spins with wheel', position: [0, 1.65, 0.45], priority: 'primary', }, { id: 'disc-brake-label-pistons', partId: 'pistons', text: 'Pressure moves pistons', position: [1.6, 0.65, 0.85], priority: 'primary', }, { id: 'disc-brake-label-pads', partId: 'inner-pad', text: 'Pads create friction torque', position: [0.7, 0.35, 0.85], priority: 'primary', }, { id: 'disc-brake-label-heat', partId: 'heat-band', text: 'Heat generated at rotor faces', position: [-0.95, 1.3, 0.65], priority: 'secondary', }, { id: 'disc-brake-label-bleed', partId: 'bleed-screw', text: 'Bleed screw removes air', position: [1.45, 1.45, 0.85], priority: 'detail', }, ], guidedTour: [ { id: 'pressure-to-force', title: 'Hydraulic pressure becomes clamp force', body: 'Pressure travels through the brake line, pushes the pistons outward, and squeezes the pads against the rotor faces.', durationSeconds: 7, cameraPreset: 'isometric', focusPartIds: ['hydraulic-line', 'pistons', 'inner-pad', 'outer-pad', 'force-arrows'], animationCue: 'pulse hydraulic line, then advance pistons and scale clamp arrows', }, { id: 'friction-and-heat', title: 'Friction slows the rotor', body: 'Pad friction applies torque opposite rotor motion. The heat overlay rises because kinetic energy is converted into thermal energy.', durationSeconds: 7, cameraPreset: 'front', focusPartIds: ['rotor', 'inner-pad', 'outer-pad', 'heat-band'], animationCue: 'decelerate rotor while increasing heat-band intensity', }, { id: 'floating-caliper', title: 'Floating caliper reaction', body: 'The slide pins allow the caliper body to move slightly so the outer pad clamps with equal reaction force.', durationSeconds: 6, cameraPreset: 'right', focusPartIds: ['slide-pins', 'caliper-body', 'outer-pad'], animationCue: 'show small caliper body translation on slide pins', }, ], animation: { loopSeconds: 6, defaultRpm: 120, rpmRange: [5, 1500], stepCount: 10, principalMotion: 'Rotor spins, hydraulic pressure pulses through the line, pistons advance, pads clamp the rotor, rotor speed dips, and heat overlay intensity rises before release.', physicallyBelievableNotes: [ 'Pad travel is intentionally small relative to rotor size, matching real brake clearances.', 'Caliper body translation is subtle and only active during the floating-caliper demonstration.', 'Rotor heat lingers after pressure release to reflect thermal inertia.', ], moduleHooks: { cyclePhase: 'phase = normalizedCycleTime; pressure = brakePressureEnvelope(phase)', transformChannels: [ 'rotor.rotation.z', 'rotor.angularVelocityMultiplier', 'hydraulic-line.pressurePulse', 'pistons.position.z', 'inner-pad.position.z', 'outer-pad.position.z', 'caliper-body.position.z', 'force-arrows.scale', 'heat-band.emissiveIntensity', ], }, }, proceduralVisualization: { assemblyStyle: 'Floating disc-brake assembly with transparent force and heat overlays, service hardware, and clamping animation.', primitives: [ 'cylinders and rings for rotor', 'rounded caliper body volumes', 'cylinders for pistons, slide pins, and bleed screw', 'thin pad blocks with friction material layers', 'curved tube for hydraulic line', 'arrow and heat-ring overlays', ], motionReference: 'Use hydraulic pressure envelope as the source for piston displacement, pad contact glow, force arrows, and rotor deceleration.', approximationNotes: [ 'The caliper casting is simplified to preserve readability and avoid hiding the pistons.', 'Thermal overlay is qualitative and not a finite-element heat simulation.', ], swapReadyNodes: [ 'Rotor', 'CaliperBody', 'Pistons', 'InnerPad', 'OuterPad', 'HydraulicLine', 'SlidePins', 'DustBoots', 'HeatBand', 'BleedScrew', 'ForceArrows', ], }, assetReplacement: { primaryGlbPath: '/assets/machines/disc-brake-caliper/disc-brake-caliper.glb', nodeNamingConvention: 'Keep friction pads, piston group, rotor, caliper body, hydraulic line, and service hardware separate; avoid baking pads into the caliper body.', scaleMetersPerUnit: 1, pivotRequirements: [ 'Rotor origin at axle center and braking rotation axis.', 'Pistons translate along rotor axial direction.', 'InnerPad and OuterPad local axes aligned for small clamp displacement.', 'SlidePins axis aligned with floating caliper translation.', ], textureSets: ['cast-iron-rotor', 'painted-caliper-blue', 'graphite-friction-pad', 'rubber-seal', 'thermal-overlay'], validationChecklist: [ 'Pads clamp both rotor faces without passing through the disc.', 'Piston travel is visible but small.', 'Heat overlay follows rotor faces and remains visible through the caliper opening.', 'BleedScrew and HydraulicLine are independently selectable.', ], }, thumbnail: { strategy: 'Capture the caliper clamping a spinning rotor with blue pressure arrows and warm heat band visible through the caliper bridge.', cameraPreset: 'isometric', highlightedPartIds: ['caliper-body', 'force-arrows', 'heat-band'], background: 'dark radial speed streaks behind the rotor', filenameSuggestion: 'disc-brake-caliper-card.webp', }, accessibilitySummary: 'Playback should expose named phases: free rotation, pressure rise, pad contact, heat generation, and release; reduced-motion mode should show those as static states.', }, { machineId: 'turbocharger', title: 'Turbocharger', category: 'Structural / Other', difficulty: 'Advanced', description: 'A turbocharger recovers energy from exhaust flow using a turbine wheel and uses it to drive a compressor wheel that pressurizes intake air. The shared shaft, bearings, volutes, wastegate, and oil/cooling circuits must survive very high speed and temperature.', learningObjectives: [ 'Trace exhaust flow through the turbine and intake flow through the compressor.', 'Identify turbine wheel, compressor wheel, shared shaft, bearing housing, volutes, wastegate, and oil/coolant ports.', 'Understand energy transfer from exhaust enthalpy to compressor pressure rise.', 'Recognize boost control, lag, heat management, and bearing lubrication concerns.', ], engineeringFacts: [ { label: 'Typical shaft speed', value: '80,000–200,000+ RPM', context: 'Small automotive turbochargers spin extremely fast, requiring precise balancing and reliable oil supply.', }, { label: 'Energy source', value: 'Exhaust enthalpy', context: 'Hot exhaust accelerates through the turbine housing and drives the turbine wheel.', }, { label: 'Compressor role', value: 'Raises intake pressure', context: 'The compressor wheel converts shaft power into airflow pressure and velocity for improved engine air charge.', }, { label: 'Boost control', value: 'Wastegate or variable geometry', context: 'A wastegate bypasses some exhaust around the turbine to regulate shaft speed and boost pressure.', }, ], relatedMachines: ['jet-engine', 'turbofan-engine', 'centrifugal-pump', 'diesel-engine', 'ball-bearing'], components: [ { id: 'turbine-wheel', name: 'Turbine wheel', role: 'Extracts energy from exhaust flow', description: 'Hot exhaust gas expands through the turbine housing and impinges on blades, spinning the shared shaft.', parentId: 'common-shaft', materialHint: 'dark high-temperature Inconel turbine', defaultVisible: true, defaultOpacity: 1, explodeVector: [-0.75, 0, 0], labelPosition: [-1.7, 0.85, 0.25], replacementNodeNames: ['TurbineWheel', 'Turbine', 'HotSideWheel'], specs: [ { label: 'Side', value: 'hot/exhaust' }, { label: 'Material', value: 'nickel alloy in real units' }, ], animationNotes: ['Rotate at shaft speed with compressor wheel.'], }, { id: 'compressor-wheel', name: 'Compressor wheel', role: 'Pressurizes intake air', description: 'The compressor wheel draws air axially, accelerates it radially, and sends it into the compressor volute.', parentId: 'common-shaft', materialHint: 'bright machined aluminum compressor', defaultVisible: true, defaultOpacity: 1, explodeVector: [0.75, 0, 0], labelPosition: [1.7, 0.85, 0.25], replacementNodeNames: ['CompressorWheel', 'Compressor', 'ColdSideWheel'], specs: [ { label: 'Side', value: 'cold/intake' }, { label: 'Flow', value: 'axial inlet to radial outlet' }, ], animationNotes: ['Rotate at shaft speed; intake flow arrows intensify with boost.'], }, { id: 'common-shaft', name: 'Common shaft', role: 'Transfers turbine power to compressor', description: 'A single shaft couples the turbine and compressor wheels. It must remain precisely balanced at extremely high speed.', parentId: 'bearing-housing', materialHint: 'polished high-strength steel shaft', defaultVisible: true, defaultOpacity: 1, explodeVector: [0, 0.15, 0], labelPosition: [0, 0.65, 0.35], replacementNodeNames: ['CommonShaft', 'TurboShaft', 'RotorShaft'], animationNotes: ['Rotate about turbo centerline; speed ramps with exhaust flow.'], }, { id: 'bearing-housing', name: 'Bearing housing / CHRA', role: 'Supports shaft and routes oil/coolant', description: 'The center housing rotating assembly holds bearings and seals between the hot turbine and cool compressor sides.', materialHint: 'dark cast center housing', defaultVisible: true, defaultOpacity: 1, explodeVector: [0, -0.1, 0], labelPosition: [0, -0.45, 0.45], replacementNodeNames: ['BearingHousing', 'CHRA', 'CenterHousing'], }, { id: 'turbine-volute', name: 'Turbine volute', role: 'Directs exhaust into turbine', description: 'The spiral hot-side housing accelerates and directs exhaust gas onto the turbine blades.', materialHint: 'dark heat-stained cast iron volute', defaultVisible: true, defaultOpacity: 0.92, explodeVector: [-1.05, 0.15, 0.15], labelPosition: [-2.15, 0.35, 0.5], replacementNodeNames: ['TurbineVolute', 'TurbineHousing', 'HotSideHousing'], }, { id: 'compressor-volute', name: 'Compressor volute', role: 'Collects compressed intake air', description: 'The compressor housing converts high-velocity air leaving the wheel into pressure and routes it toward the engine intake.', materialHint: 'satin aluminum compressor housing', defaultVisible: true, defaultOpacity: 0.92, explodeVector: [1.05, 0.15, 0.15], labelPosition: [2.15, 0.35, 0.5], replacementNodeNames: ['CompressorVolute', 'CompressorHousing', 'ColdSideHousing'], }, { id: 'wastegate-flap', name: 'Wastegate flap', role: 'Bypasses exhaust to control boost', description: 'Opening the wastegate lets part of the exhaust flow bypass the turbine, limiting shaft speed and compressor pressure.', parentId: 'turbine-volute', materialHint: 'dark steel flap with amber hinge', defaultVisible: true, defaultOpacity: 1, explodeVector: [-1.25, 0.35, 0.35], labelPosition: [-2.45, 0.95, 0.65], replacementNodeNames: ['WastegateFlap', 'WastegateValve', 'BypassFlap'], animationNotes: ['Rotate open as boost target is reached.'], }, { id: 'actuator', name: 'Wastegate actuator', role: 'Controls wastegate position', description: 'A pressure or electronic actuator moves a linkage that opens the wastegate flap under boost-control command.', parentId: 'turbine-volute', materialHint: 'brushed canister with blue linkage', defaultVisible: true, defaultOpacity: 1, explodeVector: [-0.85, 0.65, 0.35], labelPosition: [-1.65, 1.45, 0.65], replacementNodeNames: ['WastegateActuator', 'ActuatorCan', 'BoostActuator'], animationNotes: ['Rod extends when wastegate opens.'], }, { id: 'oil-feed', name: 'Oil feed and drain', role: 'Lubricates and cools shaft bearings', description: 'Pressurized oil supports the high-speed shaft bearings and drains back to the engine sump.', parentId: 'bearing-housing', materialHint: 'amber transparent oil line', defaultVisible: true, defaultOpacity: 0.85, explodeVector: [0, 0.55, 0.45], labelPosition: [0.25, 1.35, 0.65], replacementNodeNames: ['OilFeed', 'OilDrain', 'OilCircuit'], animationNotes: ['Pulse oil flow while shaft speed rises.'], }, { id: 'coolant-ports', name: 'Coolant ports', role: 'Removes heat from center housing', description: 'Water-cooled turbochargers circulate coolant through the center housing to reduce heat soak after shutdown.', parentId: 'bearing-housing', materialHint: 'transparent blue coolant paths', defaultVisible: true, defaultOpacity: 0.78, explodeVector: [0.35, 0.55, 0.35], labelPosition: [0.85, 1.1, 0.55], replacementNodeNames: ['CoolantPorts', 'WaterPorts', 'CoolantCircuit'], }, { id: 'exhaust-flow', name: 'Exhaust flow overlay', role: 'Hot-side energy path visualization', description: 'Amber streamlines show hot exhaust entering the turbine, spinning the wheel, and exiting through the downpipe.', parentId: 'turbine-volute', materialHint: 'emissive amber flow ribbons', defaultVisible: true, defaultOpacity: 0.88, explodeVector: [-1.35, 0.45, 0.5], labelPosition: [-2.5, 1.35, 0.8], replacementNodeNames: ['ExhaustFlow', 'HotFlow', 'TurbineFlow'], animationNotes: ['Scroll along turbine volute; intensity drives shaft acceleration.'], }, { id: 'intake-flow', name: 'Intake air flow overlay', role: 'Cold-side compression path visualization', description: 'Blue streamlines show air entering the compressor eye, moving outward through the wheel, and leaving under pressure.', parentId: 'compressor-volute', materialHint: 'emissive blue flow ribbons', defaultVisible: true, defaultOpacity: 0.88, explodeVector: [1.35, 0.45, 0.5], labelPosition: [2.5, 1.35, 0.8], replacementNodeNames: ['IntakeFlow', 'ColdFlow', 'CompressorFlow'], animationNotes: ['Scroll from inlet to outlet; width/opacity tracks boost.'], }, { id: 'center-housing', name: 'Center housing section overlay', role: 'Cutaway teaching layer', description: 'A semi-transparent section exposes the bearing cartridge and thermal separation between hot and cold sides.', parentId: 'bearing-housing', materialHint: 'transparent graphite section shell', defaultVisible: true, defaultOpacity: 0.38, explodeVector: [0, 0.25, 0.45], labelPosition: [-0.35, 0.95, 0.75], replacementNodeNames: ['CenterHousingSection', 'CHRACutaway', 'BearingSection'], }, ], cameraPresets: brakeTurboCameraPresets, explodedView: { defaultDistance: 0.7, maxDistance: 2.8, groups: [ { id: 'hot-side', name: 'Hot side turbine system', partIds: ['turbine-wheel', 'turbine-volute', 'wastegate-flap', 'actuator', 'exhaust-flow'], direction: [-1, 0.2, 0.2], order: 1, note: 'Separates the high-temperature turbine and boost-control hardware.', }, { id: 'center-section', name: 'Center housing and lubrication', partIds: ['common-shaft', 'bearing-housing', 'oil-feed', 'coolant-ports', 'center-housing'], direction: [0, 0.55, 0.3], order: 2, note: 'Lifts the bearing and fluid circuits between hot and cold sides.', }, { id: 'cold-side', name: 'Cold side compressor system', partIds: ['compressor-wheel', 'compressor-volute', 'intake-flow'], direction: [1, 0.2, 0.2], order: 3, note: 'Separates compressor wheel, volute, and intake streamlines.', }, ], }, labels: [ { id: 'turbo-label-turbine', partId: 'turbine-wheel', text: 'Exhaust drives turbine', position: [-1.7, 0.95, 0.35], priority: 'primary', }, { id: 'turbo-label-compressor', partId: 'compressor-wheel', text: 'Compressor boosts intake air', position: [1.7, 0.95, 0.35], priority: 'primary', }, { id: 'turbo-label-shaft', partId: 'common-shaft', text: 'Shared high-speed shaft', position: [0, 0.75, 0.45], priority: 'primary', }, { id: 'turbo-label-wastegate', partId: 'wastegate-flap', text: 'Wastegate controls boost', position: [-2.45, 1.05, 0.75], priority: 'secondary', }, { id: 'turbo-label-oil', partId: 'oil-feed', text: 'Oil protects bearings', position: [0.25, 1.45, 0.75], priority: 'detail', }, ], guidedTour: [ { id: 'energy-transfer', title: 'Exhaust energy drives boost', body: 'Amber exhaust flow accelerates through the turbine housing, spinning the turbine wheel and the shared shaft.', durationSeconds: 7, cameraPreset: 'isometric', focusPartIds: ['exhaust-flow', 'turbine-volute', 'turbine-wheel', 'common-shaft'], animationCue: 'ramp exhaust flow and shaft speed together', }, { id: 'compressor-path', title: 'The compressor pressurizes intake air', body: 'The compressor wheel draws blue intake air into its eye, throws it outward, and the volute converts velocity into pressure.', durationSeconds: 7, cameraPreset: 'front', focusPartIds: ['compressor-wheel', 'compressor-volute', 'intake-flow'], animationCue: 'scroll intake streamlines from eye to outlet and increase boost gauge', }, { id: 'boost-control-and-survival', title: 'Control and durability systems', body: 'The wastegate regulates boost, while oil and coolant circuits keep the high-speed shaft and bearing housing alive.', durationSeconds: 8, cameraPreset: 'exploded', focusPartIds: ['wastegate-flap', 'actuator', 'oil-feed', 'coolant-ports', 'bearing-housing'], animationCue: 'open wastegate, pulse oil/coolant circuits, and hold exploded center section', }, ], animation: { loopSeconds: 5.5, defaultRpm: 90000, rpmRange: [5000, 180000], stepCount: 12, principalMotion: 'Turbine and compressor wheels spin on the shared shaft; exhaust and intake flow ribbons scroll through their volutes; shaft speed ramps with exhaust flow; wastegate opens to limit boost.', physicallyBelievableNotes: [ 'Displayed RPM is scaled for visualization while UI values use realistic turbocharger ranges.', 'Wastegate opening reduces exhaust-flow intensity through the turbine and stabilizes compressor boost.', 'Oil flow is active before and during high shaft speed to reinforce bearing protection.', ], moduleHooks: { cyclePhase: 'phase = normalizedCycleTime; shaftSpeed = turboSpoolEnvelope(phase, wastegatePosition)', transformChannels: [ 'common-shaft.rotation.x', 'turbine-wheel.rotation.x', 'compressor-wheel.rotation.x', 'exhaust-flow.scrollOffset', 'intake-flow.scrollOffset', 'wastegate-flap.rotation.y', 'actuator.rodExtension', 'oil-feed.flowPulse', 'coolant-ports.flowPulse', ], }, }, proceduralVisualization: { assemblyStyle: 'Cutaway turbocharger with hot/cold color coding, volute housings, high-speed rotor, wastegate linkage, and fluid flow ribbons.', primitives: [ 'radial blade meshes or repeated fins for turbine and compressor wheels', 'spiral volute approximations from torus segments and tapered tubes', 'cylinders for shaft, actuator, and oil/coolant ports', 'transparent center housing section', 'animated ribbon/curve meshes for exhaust and intake flow', ], motionReference: 'Use shaftSpeed as the shared source for both wheels; use exhaust-flow envelope and wastegate position to drive boost and compressor flow intensity.', approximationNotes: [ 'Procedural volutes are diagrammatic spiral housings rather than CFD-accurate scroll geometry.', 'Blade pitch and count are stylized to read well at distance and in wireframe mode.', 'Thermal separation is represented by hot/cold materials rather than transient heat simulation.', ], swapReadyNodes: [ 'TurbineWheel', 'CompressorWheel', 'CommonShaft', 'BearingHousing', 'TurbineVolute', 'CompressorVolute', 'WastegateFlap', 'WastegateActuator', 'OilFeed', 'CoolantPorts', 'ExhaustFlow', 'IntakeFlow', 'CenterHousingSection', ], }, assetReplacement: { primaryGlbPath: '/assets/machines/turbocharger/turbocharger.glb', nodeNamingConvention: 'Preserve hot-side, center-section, and cold-side node separation; do not merge wheels with housings because animation requires independent rotor pivots.', scaleMetersPerUnit: 1, pivotRequirements: [ 'TurbineWheel, CompressorWheel, and CommonShaft origins share the shaft centerline.', 'WastegateFlap origin located at hinge axis.', 'Actuator rod aligned with its extension axis.', 'Flow ribbon helpers follow named inlet/outlet anchors if supplied.', ], textureSets: ['heat-stained-cast-iron', 'machined-aluminum-compressor', 'polished-shaft', 'amber-hot-flow', 'blue-cold-flow'], validationChecklist: [ 'Both wheels rotate in lockstep around the shaft axis.', 'Wastegate flap opens without clipping the turbine housing.', 'Oil and coolant overlays remain visible in center-section cutaway.', 'Hot and cold flow arrows are directionally correct and color-coded.', ], }, thumbnail: { strategy: 'Render a cutaway isometric with amber exhaust flow on the left, blue compressor flow on the right, and the shared shaft glowing subtly between wheels.', cameraPreset: 'isometric', highlightedPartIds: ['turbine-wheel', 'compressor-wheel', 'exhaust-flow', 'intake-flow'], background: 'dark split hot/cold gradient with radial speed streaks', filenameSuggestion: 'turbocharger-card.webp', }, accessibilitySummary: 'Accessible tour should narrate hot-side, center-section, and cold-side flow order; RPM values must be formatted with separators and not rely on rotor blur for meaning.', }, ] as const satisfies readonly StructuralOtherDossier[]; export type StructuralOtherDossierRecord = (typeof structuralOtherDossiers)[number]; export type StructuralOtherMachineId = StructuralOtherDossierRecord['machineId']; export const structuralOtherDossiersById = Object.fromEntries( structuralOtherDossiers.map((dossier) => [dossier.machineId, dossier]), ) as Record;