/* 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/application.h" #include "core/gameinterface.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; 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", "1024", 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(const Camera &camera, const math::Color &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; } const float dust_distance = camera.distance() * camera.multiplier(); 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) * (dust_distance + core::localcontrol()->radius() * 2.0f); dust[i*3+1] = core::localcontrol()->location().y() + (math::randomf(2) - 1) * (dust_distance + core::localcontrol()->radius() * 2.0f); dust[i*3+2] = core::localcontrol()->location().z() + (math::randomf(2) - 1) * (dust_distance + core::localcontrol()->radius() * 2.0f); } } traillength = math::max(core::localcontrol()->speed() * 0.5f, 0.5f); traillength = traillength * TRAILLENGHT / LOWSPEEDLIMIT; math::Color color(dustcolor); alpha = math::min(core::localcontrol()->speed(), 1.0f); color.a = 0.25f * alpha; gl::begin(gl::Lines); gl::color(color); 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()->axis().forward()[j] * traillength; } if (dsquare > (2.0f * core::localcontrol()->radius() + dust_distance)*(2.0f * core::localcontrol()->radius() + dust_distance)) { for (size_t j = 0; j < 3; j++) { dust[i*3+j] = core::localcontrol()->location()[j] + (math::randomf(2) - 1) * (dust_distance + core::localcontrol()->radius() * 2.0f); v[j] = dust[i*3+j] - core::localcontrol()->axis().forward()[j] * traillength; } } gl::vertex(&dust[i*3]); gl::vertex(v); } gl::end(); } }