/* render/renderext.cc This file is part of the Osirion project and is distributed under the terms of the GNU General Public License version 2 */ #include #include #include "render/particlesystemscript.h" #include "math/functions.h" #include "core/application.h" #include "core/entity.h" #include "core/entityglobe.h" #include "core/range.h" #include "model/model.h" #include "render/camera.h" #include "render/renderext.h" #include "render/render.h" #include "render/textures.h" #include "sys/sys.h" namespace render { RenderExt::RenderExt(core::Entity *entity) : core::Extension(core::Extension::Render, entity) { state_visible = false; state_detailvisible = false; state_fuzz = math::randomf(); state_enginetime = state_fuzz * core::application()->time(); state_explosion = 0; if (!entity->model() && entity->modelname().size()) { entity->set_modelname(entity->modelname()); if (!entity->model()) entity->set_modelname(""); } if (entity->model()) { model::Model *model = entity->model(); for (model::Model::Lights::iterator lit = model->lights().begin(); lit != model->lights().end(); ++lit) { model::Light *light = (*lit); // load light texture std::stringstream flarename; flarename << "textures/fx/flare" << std::setfill('0') << std::setw(2) << light->flare(); light->set_texture(Textures::load(flarename.str())); } for (model::Model::Flares::iterator flit = model->flares().begin(); flit != model->flares().end(); ++flit) { model::Flare *flare = (*flit); // load flare texture std::stringstream flarename; flarename << "textures/fx/flare" << std::setfill('0') << std::setw(2) << flare->flare(); flare->set_texture(Textures::load(flarename.str())); } for (model::Model::ParticleSystems::const_iterator pit = model->particles().begin(); pit != model->particles().end(); ++pit) { // load particle systems const ParticleSystemScript *script = ParticleSystemScript::load((*pit)->script()); if (script) { ParticleSystem *ps = new ParticleSystem(script, entity, (*pit)); state_particles.push_back(ps); } } } else if (entity->type() == core::Entity::Globe) { core::EntityGlobe *globe = static_cast(entity); // load globe textures if (!globe->texture_id() && globe->texturename().size()) { globe->set_texture_id(Textures::load("textures/" + globe->texturename())); if (!globe->texture_id()) globe->set_texturename(""); } if (!globe->corona_id() && globe->coronaname().size()) { globe->set_corona_id(Textures::load("textures/" + globe->coronaname())); if (!globe->corona_id()) { globe->set_coronaname(""); } } if (!globe->rings_id() && globe->ringsname().size()) { globe->set_rings_id(Textures::load("textures/" + globe->ringsname())); if (!globe->rings_id()) { globe->set_ringsname(""); } } } } RenderExt::~RenderExt() { for (ParticleSystems::iterator it = state_particles.begin(); it != state_particles.end(); it++) { delete(*it); } state_particles.clear(); } void RenderExt::frame(float elapsed) { } void RenderExt::frame(float elapsed, const Camera & camera) { state_distance = math::distance(camera.location(), entity()->location()); state_visible = entity()->visible(); state_detailvisible = false; state_behind = false; state_power = true; state_thrust = 0.0f; if (!state_visible) { return; } int state = core::Entity::Normal; if ((entity()->type() == core::Entity::Dynamic) || (entity()->type() == core::Entity::Projectile)) { state = static_cast(entity())->state(); if ((state == core::Entity::NoPower) || (state == core::Entity::Destroyed)) { state_power = false; } state_enginetime += elapsed; } else if ((entity()->type() == core::Entity::Controlable)) { core::EntityControlable *controlable = static_cast(entity()); state = controlable->state(); if (controlable->state() == core::Entity::Docked) { state_visible = false; state_power = false; return; } if ((controlable == core::localcontrol()) && (camera.mode() == camera.Cockpit)) { state_visible = false; return; } if ((controlable->state() == core::Entity::NoPower) || (controlable->state() == core::Entity::Destroyed)) { state_power = false; } if ((controlable->state() == core::Entity::Impulse) || (controlable->state() == core::Entity::ImpulseInitiate)) { state_thrust = 1.0f; } else { state_thrust = controlable->thrust(); } state_enginetime += elapsed * state_thrust; } else { state_enginetime += elapsed; } if (state == core::Entity::Destroyed) { if (!state_explosion) { // add explosion const ParticleSystemScript *script = ParticleSystemScript::load("explosion"); if (script) { state_explosion = new ParticleSystem(script, entity(), 0); // forece all ejectors te explosion state for (ParticleSystem::Ejectors::iterator it = state_explosion->ejectors().begin(); it != state_explosion->ejectors().end(); ++it) { ParticleEjector *ejector = (*it); ejector->set_explosion(true); } state_particles.push_back(state_explosion); } } } else { if (state_explosion) { // remove explosion for (ParticleSystems::iterator it = particles().begin(); state_explosion && (it != particles().end());) { if ((*it) == state_explosion) { particles().erase(it++); state_explosion = 0; } else { ++it; } } } } if (entity()->model()) { if (distance() < core::range::fxdistance) { // entity within detail range state_visible = true; state_detailvisible = true; if ((entity()->type() == core::Entity::Controlable) || (entity()->type() == core::Entity::Dynamic)) { if (static_cast(entity())->state() == core::Entity::Destroyed) { state_visible = false; } } } else if (distance() < core::range::maxdistance) { // funky radius factor float r = entity()->model()->radius(); math::clamp(r, entity()->model()->radius(), core::range::maxdistance / core::range::fxdistance); if (distance() < core::range::fxdistance * r) { // entity within drawing distance, outside detail range state_visible = true; state_detailvisible = false; } else { // entity within drawing distance, outside detail range state_visible = true; state_detailvisible = false; } } else { // entity out of range state_visible = false; state_detailvisible = false; return; } } if (math::dotproduct(camera.axis().forward(), entity()->location() + camera.axis().forward() * entity()->radius() - camera.location()) < 0.0f) { state_behind = true; } } } // namespace render