| 283 | } |
| 284 | |
| 285 | static void loadParticleSystem(Entity* entity, const EntityFactory::Context& context, const EntityFactory::VisContext& visContext, const VisObjectsComponentPtr& visObjectsComponent, const SimVisBindingsComponentPtr& simVisBindingComponent, const nlohmann::json& json) |
| 286 | { |
| 287 | NearestPlanetProvider nearestPlanetProvider = [world = context.simWorld] (const Vector3& position) { |
| 288 | return findNearestEntityWithComponent<sim::PlanetComponent>(world->getEntities(), position).get(); |
| 289 | }; |
| 290 | |
| 291 | ParticleEmitter::Params emitterParams; |
| 292 | emitterParams.emissionRate = json.at("emissionRate"); |
| 293 | emitterParams.radius = json.at("radius"); |
| 294 | emitterParams.positionable = entity->getFirstComponentRequired<Node>(); |
| 295 | emitterParams.elevationAngle = DoubleRangeInclusive(json.at("elevationAngleMin"), json.at("elevationAngleMax")); |
| 296 | emitterParams.speed = DoubleRangeInclusive(json.at("speedMin"), json.at("speedMax")); |
| 297 | emitterParams.upDirection = readVector3(json.at("upDirection")); |
| 298 | emitterParams.random = std::make_shared<Random>(/* seed */ 0); |
| 299 | emitterParams.temperatureDegreesCelcius = readOptionalOrDefault(json, "initialTemperatureDegreesCelcius", 0.0); |
| 300 | emitterParams.zeroAtmosphericDensityAlpha = readOptionalOrDefault(json, "zeroAtmosphericDensityAlpha", 1.0); |
| 301 | emitterParams.earthSeaLevelAtmosphericDensityAlpha = readOptionalOrDefault(json, "earthSeaLevelAtmosphericDensityAlpha", 1.0); |
| 302 | emitterParams.nearestPlanetProvider = nearestPlanetProvider; |
| 303 | |
| 304 | double lifetime = json.at("lifetime"); |
| 305 | |
| 306 | ParticleIntegrator::Params integratorParams; |
| 307 | integratorParams.lifetime = lifetime; |
| 308 | integratorParams.radiusLinearGrowthPerSecond = json.at("radiusLinearGrowthPerSecond"); |
| 309 | integratorParams.atmosphericSlowdownFactor = json.at("atmosphericSlowdownFactor"); |
| 310 | integratorParams.heatTransferCoefficent = readOptional<float>(json, "heatTransferCoefficent"); |
| 311 | integratorParams.nearestPlanetProvider = nearestPlanetProvider; |
| 312 | |
| 313 | auto particleSystem = std::make_shared<ParticleSystem>(ParticleSystem::Operations({ |
| 314 | std::make_shared<ParticleIntegrator>(integratorParams), // integrate before emission ensure new particles emitted at end of time step |
| 315 | std::make_shared<ParticleEmitter>(emitterParams), |
| 316 | std::make_shared<ParticleKiller>(lifetime) |
| 317 | })); |
| 318 | entity->addComponent(std::make_shared<ParticleSystemComponent>(particleSystem)); |
| 319 | |
| 320 | osg::ref_ptr<osg::Texture2D> texture = visContext.textureCache->getOrCreateTexture(json.at("albedoTexture"), [](const std::string& filename) { |
| 321 | return vis::createTilingSrgbTexture(osgDB::readImageFile(filename)); |
| 322 | }); |
| 323 | |
| 324 | auto program = visContext.programs->getRequiredProgram("particles"); |
| 325 | auto visParticles = std::make_shared<vis::Particles>(program, texture); |
| 326 | visObjectsComponent->addObject(visParticles); |
| 327 | |
| 328 | SimVisBindingPtr binding(new ParticlesVisBinding(particleSystem, visParticles)); |
| 329 | simVisBindingComponent->bindings.push_back(binding); |
| 330 | } |
| 331 | |
| 332 | struct PlanetStatsUpdater : vis::PlanetFeaturesListener, vis::QuadTreeTileLoaderListener, sim::Component |
| 333 | { |
nothing calls this directly
no test coverage detected