/* render/dust.cc This file is part of the Osirion project and is distributed under the terms of the GNU General Public License version 2 */ #include "render/camera.h" #include "render/dust.h" #include "render/gl.h" #include "core/cvar.h" #include "core/core.h" #include "math/functions.h" #include "sys/sys.h" namespace render { core::Cvar *r_dust; core::Cvar *r_dustsize; const float LOWSPEEDLIMIT = 5.0f; const float TRAILLENGHT = 0.25f; const float DUSTMAXALPHA = 0.8f; const float DUSTDISTANCE = 8.0f; float *dust = 0; size_t dustsize = 0; void Dust::init() { r_dust = core::Cvar::get("r_dust", "1", core::Cvar::Archive); r_dust->set_info("[bool] render dust"); r_dustsize = core::Cvar::get("r_dustsize", "128", core::Cvar::Archive); r_dustsize->set_info("[int] number of dust particles"); dust = 0; dustsize = (size_t) r_dustsize->value(); } void Dust::shutdown() { if (dust) { free(dust); dust = 0; dustsize = 0; } } void Dust::reset() { if (dust) { free(dust); dust = 0; } } void Dust::draw(math::Color const &dustcolor) { float alpha = 0.0f; float traillength = 0.0f; if (!r_dust->value()) { if (dust) { free(dust); dust = 0; } dustsize = 0; return; } if ((size_t) r_dustsize->value() != dustsize) { con_debug << " changing dust size..." << std::endl; if (dust) { free(dust); dust = 0; } dustsize = (size_t) r_dustsize->value(); } if (dustsize <= 0) { if (dust) { free(dust); dust = 0; } dustsize = 0; return; } if (!core::localcontrol()) { return; } alpha = math::max(core::localcontrol()->movement()*0.5f, core::localcontrol()->speed()); math::clamp(alpha, 0.0f, 1.0f); alpha = 0.2f + alpha * 0.7f; if (!dust) { con_debug << " generating dust..." << std::endl; dust = (float *) malloc(sizeof(float) * dustsize* 3); for (size_t i = 0; i < dustsize; i++) { dust[i*3] = core::localcontrol()->location().x + (math::randomf(2) - 1) * (DUSTDISTANCE + core::localcontrol()->radius()); dust[i*3+1] = core::localcontrol()->location().y + (math::randomf(2) - 1) * (DUSTDISTANCE + core::localcontrol()->radius()); dust[i*3+2] = core::localcontrol()->location().z + (math::randomf(2) - 1) * (DUSTDISTANCE + core::localcontrol()->radius()); } } math::Color color(dustcolor); color.a = alpha; traillength = math::max(math::max(core::localcontrol()->movement(), core::localcontrol()->speed()), 0.5f); traillength = traillength * TRAILLENGHT / LOWSPEEDLIMIT; gl::color(color); gl::begin(gl::Lines); math::Vector3f v; for (size_t i = 0; i < dustsize; i++) { float dsquare = 0; for (size_t j = 0; j < 3; j++) { dsquare += (core::localcontrol()->location()[j] - dust[i*3+j]) * (core::localcontrol()->location()[j] - dust[i*3+j]); v[j] = dust[i*3+j] - core::localcontrol()->state()->axis().forward()[j] * traillength; } if (dsquare > (core::localcontrol()->radius() + DUSTDISTANCE)*(core::localcontrol()->radius() + DUSTDISTANCE)) { for (size_t j = 0; j < 3; j++) { dust[i*3+j] = core::localcontrol()->location()[j] + (math::randomf(2) - 1) * (DUSTDISTANCE + core::localcontrol()->radius()); v[j] = dust[i*3+j] - core::localcontrol()->state()->axis().forward()[j] * traillength; } } glVertex3fv(&dust[i*3]); gl::vertex(v); } gl::end(); } }