SkyParticles.cpp

Go to the documentation of this file.
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

Get Racer at SourceForge.net. Fast, secure and Free Open Source software downloads

Generated at Mon Sep 6 00:41:13 2010 by Doxygen version 1.4.7 for Racer version svn335.