00001 00005 /* Copyright © 2010 James Legg. 00006 This program is free software: you can redistribute it and/or modify 00007 it under the terms of the GNU General Public License as published by 00008 the Free Software Foundation, either version 3 of the License, or 00009 (at your option) any later version. 00010 */ 00011 00012 #include "SkyParticles.h" 00013 #include <cstdlib> 00014 #include <cmath> 00015 #include <GL/gl.h> 00016 00017 #include "../Engine/ResourceHandler.h" 00018 typedef Engine::ResourceHandler<Track::Texture, std::string, std::string> TextureStore; 00019 00020 namespace Graphics 00021 { 00022 00024 const btScalar covered_size = 64.0; 00025 const btScalar half_covered_size = covered_size / 2.0; 00026 const btScalar square_half_covered_size = half_covered_size * half_covered_size; 00027 00028 SkyParticles::SkyParticles() 00029 : phase (0) 00030 { 00031 for (int i = 0; i < m_num_particles; i++) 00032 { 00033 particles[i]=btVector3(float (std::rand()) / float(RAND_MAX) * covered_size, 00034 float (std::rand()) / float(RAND_MAX) * covered_size, 00035 float (std::rand()) / float(RAND_MAX) * covered_size); 00036 } 00037 00038 TextureStore & tex_store = TextureStore::get_instance(); 00039 #define tex_load(bind_name, file_name, variable)\ 00040 tex_store.check_load(bind_name, file_name);\ 00041 variable = tex_store.get(bind_name);\ 00042 variable->make_cache() 00043 tex_load("fire.particle.generic", "data/generic/particle_fire.png", m_texture); 00044 #undef tex_load 00045 } 00046 00047 void SkyParticles::update(unsigned int time) 00048 { 00049 // move particles. 00050 btScalar move = time * 0.004; 00051 btScalar side_move = time * 0.002; 00052 phase += float(time) * 0.005; 00053 00054 for (int i = 0; i < m_num_particles; i++) 00055 { 00056 particles[i].setZ(particles[i].getZ() + move); 00057 if (particles[i].getZ() > covered_size) particles[i].setZ(particles[i].getZ()-covered_size); 00058 // make them spiral. 00059 particles[i].setX(particles[i].x() + sin(phase + i) * side_move); 00060 particles[i].setY(particles[i].y() + cos(phase + i) * side_move); 00061 } 00062 } 00063 00064 void SkyParticles::draw(const Engine::CarCamera & camera) 00065 { 00066 // The scale to draw the particles horizontally. 00067 const float s = 0.1; 00068 00069 // Particles are drawn around the centre point. The position is wrapped so 00070 // that they form a 3d repeated pattern. 00071 // They are rotated to face the centre. 00072 const btVector3 & centre = camera.get_location(); 00073 00074 glEnable(GL_BLEND); 00075 glDepthMask(GL_FALSE); 00076 glBlendFunc(GL_SRC_ALPHA, GL_ONE); 00077 glDisable(GL_CULL_FACE); 00078 m_texture->bind(); 00079 00080 glBegin(GL_QUADS); 00081 btVector3 major_offset = centre * (1.0/covered_size); 00082 major_offset = btVector3(floor(major_offset.x() - 0.5), 00083 floor(major_offset.y() - 0.5), 00084 floor(major_offset.z() - 0.5)); 00085 major_offset *= covered_size; 00086 btScalar x_max = centre.x()+half_covered_size; 00087 btScalar y_max = centre.y()+half_covered_size; 00088 btScalar z_max = centre.z()+half_covered_size; 00089 btScalar x_min = centre.x()-half_covered_size; 00090 btScalar y_min = centre.y()-half_covered_size; 00091 btScalar z_min = centre.z()-half_covered_size; 00092 // offset the tail to make it look like it has moved during the exposure 00093 // of a regular camera. 00094 // 4 physics ticks = 40 msec = max exposure time for 25 fps. 00095 btVector3 a_offset = camera.get_velocity() * -4.0 + 00096 // component for particles' constant vertical motion. 00097 btVector3(0.0, 0.0, -0.16); 00098 btVector3 b_offset = a_offset; 00099 for (int i = 0; i < m_num_particles; i++) 00100 { 00101 btVector3 loc = particles[i]+major_offset; 00102 if (loc.x() > x_max) loc.setX(loc.x()-covered_size); 00103 if (loc.y() > y_max) loc.setY(loc.y()-covered_size); 00104 if (loc.z() > z_max) loc.setZ(loc.z()-covered_size); 00105 if (loc.x() < x_min) loc.setX(loc.x()+covered_size); 00106 if (loc.y() < y_min) loc.setY(loc.y()+covered_size); 00107 if (loc.z() < z_min) loc.setZ(loc.z()+covered_size); 00108 00109 b_offset.setX(sin(phase + i)*-0.08 + a_offset.x()); 00110 b_offset.setY(cos(phase + i)*-0.08 + a_offset.y()); 00111 00112 btScalar angle = std::atan2(loc.y() - centre.y(), loc.x() - centre.x()); 00113 // scale the width of particles so distance particles have 0 width. 00114 // This means that distant particles don't pop into existence. 00115 btScalar distance_measure = (1.0 - loc.distance2(centre) / square_half_covered_size) * 10.0; 00116 if (distance_measure > 1.0) distance_measure = 1.0; 00117 btScalar distance_scale = s * distance_measure; 00118 if (distance_scale < 0.0) continue; 00119 // find angular components so that particle faces the camera in xy. 00120 btScalar sin = std::sin(angle) * distance_scale; 00121 btScalar cos = std::cos(angle) * distance_scale; 00122 00123 glTexCoord2f(0.0, 0.0); 00124 glVertex3f(loc.getX() - sin, loc.getY() + cos, loc.getZ()); 00125 glTexCoord2f(0.0, 1.0); 00126 glVertex3f(loc.getX() - sin + b_offset.x(), loc.getY() + cos + b_offset.y(), loc.getZ() + b_offset.z()); 00127 glTexCoord2f(1.0, 1.0); 00128 glVertex3f(loc.getX() + sin + b_offset.x(), loc.getY() - cos + b_offset.y(), loc.getZ() + b_offset.z()); 00129 glTexCoord2f(1.0, 0.0); 00130 glVertex3f(loc.getX() + sin, loc.getY() - cos, loc.getZ()); 00131 } 00132 glEnd(); 00133 glDepthMask(GL_TRUE); 00134 glDisable(GL_BLEND); 00135 glEnable(GL_CULL_FACE); 00136 } 00137 00138 } // namespace Graphics
Generated at Mon Sep 6 00:41:13 2010 by Doxygen version 1.4.7 for Racer version svn335.