Load engines from TOML and improve scenario audio and carb tuning
Migrate 32 engine definitions into validated startup-loaded TOML files and separate configuration and snapshots from scenario assembly. Add camera-based stereo propagation from shared pipe geometry, preserve exhaust character, tune carburetor mixtures and idle, use ignition cuts for carb engines, and support returning to the scenario menu. Validation: full Windows build and all 14 CTest checks passed.
This commit is contained in:
@@ -1,83 +1,28 @@
|
||||
#pragma once
|
||||
#include "FluidSim/Scenario.hpp"
|
||||
#include "FluidSim/EngineConfig.hpp"
|
||||
#include "FluidSim/Silencer.hpp"
|
||||
#include "FluidSim/TwoStrokeConfig.hpp"
|
||||
#include <filesystem>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace fluidsim::port {
|
||||
struct ScenarioExample {
|
||||
std::string id,title,description;
|
||||
ScenarioKind kind;
|
||||
ScenarioKind kind{ScenarioKind::Twin};
|
||||
TwoStrokeConfig two{};
|
||||
ExhaustConfig exhaust{};
|
||||
V8ExhaustConfig v8{};
|
||||
JunctionConfig junctions{};
|
||||
EngineConfig engine{};
|
||||
std::string category;
|
||||
int order{};
|
||||
};
|
||||
inline std::vector<ScenarioExample> scenario_examples() {
|
||||
std::vector<ScenarioExample> examples;
|
||||
auto add=[&](const char* id,const char* title,const char* description,ScenarioKind kind)->ScenarioExample& {
|
||||
examples.push_back({id,title,description,kind,{},{},{},{},{}});return examples.back();
|
||||
};
|
||||
add("twin","600 cc parallel twin","EFI motorcycle baseline",ScenarioKind::Twin);
|
||||
add("yz-racing","YZ125 / expansion chamber","Racing pipe, fixed 4.5% carb idle",ScenarioKind::TwoStroke);
|
||||
add("yz-straight","YZ125 / straight exhaust","Same engine and carb, straight exhaust comparison",ScenarioKind::TwoStroke).two.exhaust=TwoStrokeExhaust::Straight;
|
||||
add("saab-straight","Saab B205 / straight-through","6 L resonator and 18 L straight-through rear muffler",ScenarioKind::SaabB205);
|
||||
auto& chambered=add("saab-chambered","Saab B205 / chambered","Expansion resonator and two-chamber rear muffler",ScenarioKind::SaabB205);
|
||||
chambered.exhaust.resonator.type=SilencerType::ExpansionResonator;
|
||||
chambered.exhaust.muffler.type=SilencerType::Chambered;chambered.exhaust.muffler.chambers=2;
|
||||
auto& resonator=add("saab-expansion","Saab B205 / expansion silencers","Two single expansion chambers, same body volumes",ScenarioKind::SaabB205);
|
||||
resonator.exhaust.resonator.type=SilencerType::ExpansionResonator;resonator.exhaust.muffler.type=SilencerType::ExpansionResonator;
|
||||
add("saab-open","Saab B205 / open exhaust","Silencers bypassed; naturally aspirated baseline",ScenarioKind::SaabB205).exhaust.enabled=false;
|
||||
add("v8-h","American 5.0 / 4-2-1 + H","750 mm primaries, 50 cc junctions, H crossover",ScenarioKind::AmericanV8);
|
||||
add("v8-dual","American 5.0 / independent banks","Same 4-2-1 headers with H crossover disconnected",ScenarioKind::AmericanV8).v8.h_pipe=false;
|
||||
add("v8-short","American 5.0 / short headers","600 mm primaries with H crossover",ScenarioKind::AmericanV8).v8.primary_length=.60f;
|
||||
add("v8-long","American 5.0 / long headers","900 mm primaries with H crossover",ScenarioKind::AmericanV8).v8.primary_length=.90f;
|
||||
add("v8-large","American 5.0 / larger primaries","42 mm x 750 mm primaries with H crossover",ScenarioKind::AmericanV8).v8.primary_diameter=.042f;
|
||||
for(auto& e:examples) e.category=e.kind==ScenarioKind::TwoStroke?"Two-stroke / 125 cc":e.kind==ScenarioKind::SaabB205?"Inline four / Saab":e.kind==ScenarioKind::AmericanV8?"V8 / American 5.0":"Twins / parallel";
|
||||
auto chamber=[&](const char* id,const char* title,float length,float width) {
|
||||
auto& e=add(id,title,"Estimated chamber geometry / same 125 cc engine",ScenarioKind::TwoStroke);
|
||||
e.category="Two-stroke / 125 cc";
|
||||
for(auto& section:e.two.racing_pipe) {section.length*=length;section.inlet_diameter*=width;section.outlet_diameter*=width;}
|
||||
};
|
||||
chamber("yz-torque","125 / long torque chamber",1.18f,1.f);
|
||||
chamber("yz-short","125 / short high-RPM chamber",.82f,1.f);
|
||||
chamber("yz-fat","125 / wide belly chamber",1.f,1.18f);
|
||||
auto two=[&](const char* id,const char* title,const char* category,float bore,float stroke,float carb) {
|
||||
auto& e=add(id,title,"Concept single / transported carb fuel",ScenarioKind::TwoStroke);e.category=category;
|
||||
const float scale=std::cbrt((bore*bore*stroke)/(.054f*.054f*.0545f));
|
||||
e.two.jet_scale=bore<.05f?.5f:1.f;
|
||||
e.two.bore=bore;e.two.stroke=stroke;e.two.rod*=scale;e.two.carburetor_diameter=carb;
|
||||
e.two.transfer_width*=scale;e.two.exhaust_width*=scale;e.two.crankcase_clearance*=scale*scale*scale;
|
||||
e.two.minimum_burn_seconds*=scale;
|
||||
for(auto& section:e.two.racing_pipe) {section.length*=scale;section.inlet_diameter*=scale;section.outlet_diameter*=scale;}
|
||||
e.two.exhaust_cell_length=.015f;
|
||||
};
|
||||
two("fifty","50 cc / little screamer","Two-stroke / 50 cc",.040f,.0398f,.019f);
|
||||
two("fivehundred","500 cc / big single","Two-stroke / 500 cc",.086f,.086f,.041f);
|
||||
auto custom=[&](const char* id,const char* title,const char* category,int count,EngineLayout layout,float bore,float stroke)->ScenarioExample& {
|
||||
auto& e=add(id,title,"Estimated concept calibration / EFI",ScenarioKind::Twin);e.category=category;
|
||||
e.engine.cylinders=count;e.engine.layout=layout;e.engine.bore=bore;e.engine.stroke=stroke;
|
||||
e.engine.rod=std::max(.11f,stroke*1.8f);return e;
|
||||
};
|
||||
custom("single-450","450 cc / four-stroke thumper","Singles / four-stroke",1,EngineLayout::Inline,.096f,.062f);
|
||||
custom("single-650","650 cc / big thumper","Singles / four-stroke",1,EngineLayout::Inline,.100f,.083f).engine.rev_limit=6500;
|
||||
auto& twin270=custom("twin-270","700 cc / 270-degree parallel twin","Twins / parallel",2,EngineLayout::Inline,.080f,.068f);
|
||||
twin270.engine.custom_phases=true;twin270.engine.phase_degrees[1]=450;
|
||||
auto& ducati=custom("ltwin","916-inspired / 90-degree V twin","Twins / V",2,EngineLayout::V,.094f,.066f);
|
||||
ducati.engine.bank_angle=90;ducati.engine.custom_phases=true;ducati.engine.phase_degrees[1]=450;
|
||||
custom("triple","1.0 litre / inline triple","Inline three",3,EngineLayout::Inline,.079f,.068f);
|
||||
auto& four=custom("f20","F20C-inspired / 2.0 high-rev four","Inline four / specials",4,EngineLayout::Inline,.087f,.084f);four.engine.rev_limit=9000;
|
||||
custom("five","Audi-inspired / 2.2 inline five","Inline five",5,EngineLayout::Inline,.081f,.0864f);
|
||||
custom("rb26","RB26-inspired / 2.6 inline six NA","Inline six",6,EngineLayout::Inline,.086f,.0737f);
|
||||
custom("six-long","3.0 litre / long-stroke inline six","Inline six",6,EngineLayout::Inline,.086f,.086f);
|
||||
custom("busso","Busso-inspired / 3.0 V6","V6",6,EngineLayout::V,.093f,.0726f);
|
||||
auto& flat4=custom("ej20","EJ20-inspired / 2.0 flat four NA","Boxer / flat four",4,EngineLayout::Boxer,.092f,.075f);
|
||||
flat4.engine.bank_angle=180;
|
||||
custom("flat6","911-inspired / 3.0 flat six","Boxer / flat six",6,EngineLayout::Boxer,.095f,.0704f).engine.bank_angle=180;
|
||||
auto& big=custom("big-carb","8.0 litre / carbureted big-block","V8 / big-block",8,EngineLayout::V,.1143f,.098f);
|
||||
big.engine.carb_pilot_scale=.4f;big.engine.carb_jet_scale=.47f;big.engine.bank_angle=90;big.engine.compression=9;big.engine.carbureted=true;big.engine.idle_rpm=800;big.engine.idle_opening=.08f;
|
||||
big.description="Carb fuel transport / fixed configurable idle stop";
|
||||
custom("v10","5.0 litre / even-fire V10","V10",10,EngineLayout::V,.092f,.0752f).engine.bank_angle=72;
|
||||
custom("v12","250-inspired / 3.0 V12","V12",12,EngineLayout::V,.073f,.0588f).engine.bank_angle=60;
|
||||
return examples;
|
||||
}
|
||||
ScenarioExample load_engine_file(const std::filesystem::path& path);
|
||||
std::vector<ScenarioExample> load_engine_directory(const std::filesystem::path& directory);
|
||||
// FLUIDSIM_ENGINE_DIR overrides discovery. Otherwise search the working directory,
|
||||
// beside the executable, then the source tree for developer tools.
|
||||
std::filesystem::path engine_directory();
|
||||
const std::vector<ScenarioExample>& scenario_examples();
|
||||
const ScenarioExample& scenario_example(const std::string& id);
|
||||
const ScenarioExample& preset_engine_definition(FourStrokePreset preset);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user