From fbdde1aa766050447a324dad1cc2daa231e07b85 Mon Sep 17 00:00:00 2001 From: hikerstk Date: Mon, 1 Dec 2008 04:17:17 +0000 Subject: [PATCH] Added some smoke when skidding is used. git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/trunk/supertuxkart@2533 178a84e3-b1eb-0310-8ba1-8eac791a3b58 --- src/karts/kart.cpp | 35 +++--------- src/karts/kart.hpp | 3 +- src/particle_system.cpp | 118 ++++++++++++++++++++++++++-------------- src/particle_system.hpp | 11 +++- src/smoke.cpp | 102 +++++++++++++++++----------------- src/smoke.hpp | 10 ++-- 6 files changed, 152 insertions(+), 127 deletions(-) diff --git a/src/karts/kart.cpp b/src/karts/kart.cpp index f29a37e32..e9291c100 100644 --- a/src/karts/kart.cpp +++ b/src/karts/kart.cpp @@ -70,16 +70,13 @@ Kart::Kart (const std::string& kart_name, int position, #endif { m_kart_properties = kart_properties_manager->getKart(kart_name); - //m_grid_position = position; m_initial_position = position; m_collected_energy = 0; m_eliminated = false; m_finished_race = false; m_finish_time = 0.0f; m_wheelie_angle = 0.0f; - m_smokepuff = NULL; m_smoke_system = NULL; - m_exhaust_pipe = NULL; m_skidmark_left = NULL; m_skidmark_right = NULL; @@ -244,8 +241,7 @@ Kart::~Kart() sfx_manager->deleteSFX(m_crash_sound ); sfx_manager->deleteSFX(m_skid_sound ); - if(m_smokepuff) delete m_smokepuff; - if(m_smoke_system != NULL) delete m_smoke_system; + if(m_smoke_system) ssgDeRefDelete(m_smoke_system); ssgDeRefDelete(m_shadow); @@ -930,23 +926,11 @@ void Kart::processSkidMarks() } // processSkidMarks //----------------------------------------------------------------------------- +#include void Kart::loadData() { float r [ 2 ] = { -10.0f, 100.0f } ; - m_smokepuff = new ssgSimpleState (); - m_smokepuff->setTexture(material_manager->getMaterial("smoke.rgb")->getState()->getTexture()); - m_smokepuff -> setTranslucent () ; - m_smokepuff -> enable ( GL_TEXTURE_2D ) ; - m_smokepuff -> setShadeModel ( GL_SMOOTH ) ; - m_smokepuff -> enable ( GL_CULL_FACE ) ; - m_smokepuff -> enable ( GL_BLEND ) ; - m_smokepuff -> enable ( GL_LIGHTING ) ; - m_smokepuff -> setColourMaterial ( GL_EMISSION ) ; - m_smokepuff -> setMaterial ( GL_AMBIENT, 0, 0, 0, 1 ) ; - m_smokepuff -> setMaterial ( GL_DIFFUSE, 0, 0, 0, 1 ) ; - m_smokepuff -> setMaterial ( GL_SPECULAR, 0, 0, 0, 1 ) ; - m_smokepuff -> setShininess ( 0 ) ; ssgEntity *obj = m_kart_properties->getKartModel()->getRoot(); createPhysics(); @@ -960,16 +944,11 @@ void Kart::loadData() getModelTransform() -> addKid ( lod ) ; // Attach Particle System - //JH sgCoord pipe_pos = {{0, 0, .3}, {0, 0, 0}} ; - m_smoke_system = new Smoke(this, 50, 100.0f, true, 0.35f, 1000); - m_smoke_system -> init(5); - //JH m_smoke_system -> setState (getMaterial ("smoke.png")-> getState() ); - //m_smoke_system -> setState ( m_smokepuff ) ; - // m_exhaust_pipe = new ssgTransform (&pipe_pos); - // m_exhaust_pipe -> addKid (m_smoke_system) ; - // comp_model-> addKid (m_exhaust_pipe) ; - // + m_smoke_system = new Smoke(this); + m_smoke_system->ref(); + scene->add(m_smoke_system); + m_skidmark_left = new SkidMark(/* angle sign */ -1); m_skidmark_right = new SkidMark(/* angle sign */ 1); @@ -1018,6 +997,8 @@ void Kart::updateGraphics(const Vec3& off_xyz, const Vec3& off_hpr) center_shift.setZ(X); const float offset_pitch = DEGREE_TO_RAD(m_wheelie_angle); + if(m_smoke_system) + m_smoke_system->setCreationRate((m_skidding-1)*100.0f); float speed_ratio = getSpeed()/getMaxSpeed(); float offset_heading = getSteerPercent()*0.05f*3.1415926f * speed_ratio * m_skidding*m_skidding; diff --git a/src/karts/kart.hpp b/src/karts/kart.hpp index f24d7d3e5..e1090b960 100644 --- a/src/karts/kart.hpp +++ b/src/karts/kart.hpp @@ -71,10 +71,9 @@ protected: private: /** The amount of energy collected bu hitting coins. */ float m_collected_energy; - ssgSimpleState* m_smokepuff; + // don't delete the following 2 vars (they're kids in the hirarchy) Smoke *m_smoke_system; - ssgTransform* m_exhaust_pipe; float m_wheel_rotation; /** For each wheel it stores the suspension length after the karts are at diff --git a/src/particle_system.cpp b/src/particle_system.cpp index 11d6389ec..bac27d81f 100644 --- a/src/particle_system.cpp +++ b/src/particle_system.cpp @@ -22,64 +22,71 @@ #include "particle_system.hpp" -ParticleSystem::ParticleSystem ( int num, float _create_rate, int _ttf, - float sz, float bsphere_size) - : ssgVtxTable ( GL_QUADS, - new ssgVertexArray ( num * 4 /*, new sgVec3 [ num * 4 ]*/ ), - new ssgNormalArray ( num * 4 /*, new sgVec3 [ num * 4 ]*/ ), - new ssgTexCoordArray ( num * 4 /*, new sgVec2 [ num * 4 ]*/ ), - new ssgColourArray ( num * 4 /*, new sgVec4 [ num * 4 ]*/ ) - ) +#include +#include "vec3.hpp" + +ParticleSystem::ParticleSystem ( int num, float create_rate, int ttf, float sz) + : ssgVtxTable(GL_QUADS, + new ssgVertexArray (num*4, new sgVec3[num*4] ), + new ssgNormalArray (num*4, new sgVec3[num*4] ), + new ssgTexCoordArray(num*4, new sgVec2[num*4] ), + new ssgColourArray (num*4, new sgVec4[num*4] ) + ) { - m_turn_to_face = _ttf ; +#ifdef DEBUG + setName("particle-system"); +#endif + m_turn_to_face = ttf; m_create_error = 0 ; - m_create_rate = _create_rate ; + m_create_rate = create_rate; + m_size = sz; - m_size = sz ; - - bsphere . setRadius ( bsphere_size ) ; - bsphere . setCenter ( 0, 0, 0 ) ; + bsphere.setRadius(100); // a better value is computed in update + bsphere.setCenter(0, 0, 0); m_num_particles = num ; m_num_verts = num * 4 ; - m_particles = new Particle [ num ] ; + m_particles = new Particle[num]; int i ; for ( i = 0 ; i < m_num_verts ; i++ ) { - sgSetVec3 ( getNormal ( i ), 0, -1, 0 ) ; - sgSetVec4 ( getColour ( i ), 1, 1, 1, 1 ) ; - sgZeroVec3 ( getVertex ( i ) ) ; - } + sgSetVec3 (getNormal(i), 0, -1, 0 ); + sgSetVec4 (getColour(i), 1, 1, 1, 1 ); + sgZeroVec3(getVertex(i) ); + } + + for ( i = 0 ; i < m_num_particles ; i++ ) + { + sgSetVec2(getTexCoord(i*4+0), 0, 0 ); + sgSetVec2(getTexCoord(i*4+1), 1, 0 ); + sgSetVec2(getTexCoord(i*4+2), 1, 1 ); + sgSetVec2(getTexCoord(i*4+3), 0, 1 ); + } - for ( i = 0 ; i < m_num_particles ; i++ ) - { - sgSetVec2 ( getTexCoord ( i*4+0 ), 0, 0 ) ; - sgSetVec2 ( getTexCoord ( i*4+1 ), 1, 0 ) ; - sgSetVec2 ( getTexCoord ( i*4+2 ), 1, 1 ) ; - sgSetVec2 ( getTexCoord ( i*4+3 ), 0, 1 ) ; - } - - m_num_active = 0 ; -} + m_num_active = 0 ; +} // ParticleSystem //----------------------------------------------------------------------------- -void -ParticleSystem::init(int initial_num) +void ParticleSystem::init(int initial_num) { for ( int i = 0 ; i < initial_num ; i++ ) particle_create(i, & m_particles [ i ] ) ; -} +} // init //----------------------------------------------------------------------------- -void -ParticleSystem::recalcBSphere() +/** Update the bounding sphere for this particle system. This function is only + * called during setup, from then on the bounding sphere is always updated + * during update(), and so the correct value is always set. So no actual + * computation is done here. + */ +void ParticleSystem::recalcBSphere() { - bsphere . setRadius ( 1000.0f ) ; - bsphere . setCenter ( 0, 0, 0 ) ; -} + bsphere.setRadius( 1000.0f ); + bsphere.setCenter( 0, 0, 0 ); +} // recalcBSphere //----------------------------------------------------------------------------- void ParticleSystem::draw_geometry () @@ -144,13 +151,12 @@ void ParticleSystem::draw_geometry () { glDisable ( GL_CULL_FACE ) ; glDepthMask ( 0 ) ; - ssgVtxTable::draw_geometry () ; glDepthMask ( 1 ) ; glEnable ( GL_CULL_FACE ) ; } -} +} // draw_geometry //----------------------------------------------------------------------------- ParticleSystem::~ParticleSystem () @@ -159,7 +165,7 @@ ParticleSystem::~ParticleSystem () // the functions are virtual (illegal in destructor) delete[] m_particles ; -} +} // ~ParticleSystem //----------------------------------------------------------------------------- void ParticleSystem::update ( float t ) @@ -178,8 +184,10 @@ void ParticleSystem::update ( float t ) particle_update( t, i, & m_particles [ i ] ) ; } + Vec3 xyz_min(10000), xyz_max(-10000); /* Check for death of particles */ for ( i = 0 ; i < m_num_particles ; i++ ) + { if ( m_particles [ i ] . m_time_to_live <= 0.0 ) { particle_delete ( i, & m_particles [ i ] ) ; @@ -190,13 +198,39 @@ void ParticleSystem::update ( float t ) { particle_create( i, & m_particles [ i ] ) ; m_create_error -= 1.0f ; + Vec3 p(m_particles[i].m_pos); + xyz_min.min(p); + xyz_max.max(p); } } - else + else // m_time_to_live >0 { m_num_active++ ; + Vec3 p(m_particles[i].m_pos); + xyz_min.min(p); + xyz_max.max(p); } -} + } // for i + + // Update the bounding sphere + // ========================== + // Determine a bounding sphere by taking the medium of min and max as the + // center. Then use the longest distance along one axis(!) to get a maxium + // boundary box - the radius of a boundary sphere can then be estimated to + // be less then sqrt(x*x+y*y+z*z) = sqrt(3*max(x,y,z)^2) = max(xyz)*sqrt(3) + // (This avoids more expensive computations for the distance of each + // particle: a 2nd loop to determine the distance of each particle to the + // center to get the correct maximum distance, which is the radius). + Vec3 center = 0.5*(xyz_min+xyz_max); + bsphere.setCenter(center.toFloat()); + float radius = xyz_max.getX() - xyz_min.getX(); + radius = std::max(radius, xyz_max.getY() - xyz_min.getY()); + radius = std::max(radius, xyz_max.getZ() - xyz_min.getZ()); + if(radius<0) radius = 0; // happens if no particles exist. + // add the size of the actual quad to the radius on both ends + bsphere.setRadius((radius+2*m_size)*1.733f); // 1.733 approx. sqrt(3) + bsphere_is_invalid = 0; +} // update /* EOF */ diff --git a/src/particle_system.hpp b/src/particle_system.hpp index c7d881765..9d32fa94b 100644 --- a/src/particle_system.hpp +++ b/src/particle_system.hpp @@ -21,6 +21,10 @@ #include +/** This is basically the ssgaParticle, but this implementation supports + * methods to be used to create, update and delete the objects instead + * of function pointer as the original plib. + */ class Particle { public: @@ -56,7 +60,10 @@ public: } ; -class ParticleSystem ; +/** This is basically the ssgaParticleSystem, but this implementation supports + * methods to be used to create, update and delete the objects instead + * of function pointer as the original plib. + */ class ParticleSystem : public ssgVtxTable { @@ -74,7 +81,7 @@ class ParticleSystem : public ssgVtxTable public: ParticleSystem ( int num, float _create_rate, int _turn_to_face, - float sz, float bsphere_size); + float sz); virtual ~ParticleSystem () ; virtual void update ( float t ) ; diff --git a/src/smoke.cpp b/src/smoke.cpp index 11090c982..44b68b449 100755 --- a/src/smoke.cpp +++ b/src/smoke.cpp @@ -20,81 +20,83 @@ #include "smoke.hpp" #include "constants.hpp" +#include "material_manager.hpp" #include "karts/kart.hpp" -Smoke::Smoke(Kart* kart_, - int num, float _create_rate, int _ttf, - float sz, float bsphere_size) - : ParticleSystem (num, _create_rate, _ttf, sz, bsphere_size), - m_kart(kart_) +Smoke::Smoke(Kart* kart) + : ParticleSystem(200, 0.0f, true, 0.75f), + m_kart(kart) { - getBSphere () -> setCenter ( 0, 0, 0 ) ; - getBSphere () -> setRadius ( 1000.0f ) ; +#ifdef DEBUG + setName("smoke"); +#endif + bsphere.setCenter(0, 0, 0); + bsphere.setRadius(1000.0f); dirtyBSphere(); + + m_smokepuff = new ssgSimpleState (); + m_smokepuff->setTexture(material_manager->getMaterial("smoke.rgb")->getState()->getTexture()); + m_smokepuff -> setTranslucent () ; + m_smokepuff -> enable ( GL_TEXTURE_2D ) ; + m_smokepuff -> setShadeModel ( GL_SMOOTH ) ; + m_smokepuff -> disable ( GL_CULL_FACE ) ; + m_smokepuff -> enable ( GL_BLEND ) ; + m_smokepuff -> enable ( GL_LIGHTING ) ; + m_smokepuff -> setColourMaterial ( GL_EMISSION ) ; + m_smokepuff -> setMaterial ( GL_AMBIENT, 0, 0, 0, 1 ) ; + m_smokepuff -> setMaterial ( GL_DIFFUSE, 0, 0, 0, 1 ) ; + m_smokepuff -> setMaterial ( GL_SPECULAR, 0, 0, 0, 1 ) ; + m_smokepuff -> setShininess ( 0 ) ; + m_smokepuff->ref(); + + setState(m_smokepuff); + } // KartParticleSystem //----------------------------------------------------------------------------- -void Smoke::update ( float t ) +Smoke::~Smoke() { -#if 0 - std::cout << "BSphere: r:" << getBSphere()->radius - << " (" << getBSphere()->center[0] - << ", " << getBSphere()->center[1] - << ", " << getBSphere()->center[2] - << ")" - << std::endl; -#endif - getBSphere () -> setRadius ( 1000.0f ) ; + ssgDeRefDelete(m_smokepuff); +} // ~Smoke +//----------------------------------------------------------------------------- +void Smoke::update(float t) +{ + bsphere.setRadius(1000.0f); ParticleSystem::update(t); } // update //----------------------------------------------------------------------------- void Smoke::particle_create(int, Particle *p) { - sgSetVec4 ( p -> m_col, 1, 1, 1, 1 ) ; /* initially white */ - sgSetVec3 ( p -> m_pos, 0, 0, 0 ) ; /* start off on the ground */ - sgSetVec3 ( p -> m_vel, 0, 0, 0 ) ; - sgSetVec3 ( p -> m_acc, 0, 0, 2.0f ) ; /* Gravity */ - p -> m_size = .5f; - p -> m_time_to_live = 0.5 ; /* Droplets evaporate after 5 seconds */ + sgSetVec4(p->m_col, 1, 1, 1, 1 ); /* initially white */ + sgSetVec3(p->m_vel, 0, 0, 0 ); + sgSetVec3(p->m_acc, 0, 0, 2.0f ); /* Gravity */ + p->m_size = 0.5f; + p->m_time_to_live = 0.8f; - const Vec3& hpr = m_kart->getHPR(); - const Vec3& xyz = m_kart->getXYZ(); - const btVector3 VEL = m_kart->getVelocity(); - - const float X_DIRECTION = cos (hpr.getHeading() - M_PI*0.5f); // Point at the rear - const float Y_DIRECTION = sin (hpr.getHeading() - M_PI*0.5f); // Point at the rear + // The origin of the smoke depends on the turn direction: either rear + // left or rear right wheel - use the outer one. + int wheel_number = m_kart->getSteerPercent()>0 ? 2 : 3; + Vec3 xyz=m_kart->getVehicle()->getWheelInfo(wheel_number).m_raycastInfo.m_contactPointWS; sgCopyVec3 (p->m_pos, xyz.toFloat()); + p->m_vel[0] += cos(DEGREE_TO_RAD(rand()%180)); + p->m_vel[1] += sin(DEGREE_TO_RAD(rand()%180)); + p->m_vel[2] += sin(DEGREE_TO_RAD(rand()%100)); - p->m_pos[0] += X_DIRECTION * 0.7f; - p->m_pos[1] += Y_DIRECTION * 0.7f; - - const float ABS_VEL = sqrt((VEL.getX() * VEL.getX()) + (VEL.getY() * VEL.getY())); - - p->m_vel[0] = X_DIRECTION * -ABS_VEL/2; - p->m_vel[1] = Y_DIRECTION * -ABS_VEL/2; - - p->m_vel[0] += sgCos ((float)(rand()%180)); - p->m_vel[1] += sgSin ((float)(rand()%180)); - p->m_vel[2] += sgSin ((float)(rand()%100)); - - getBSphere()->setCenter ( xyz.getX(), xyz.getY(), xyz.getZ() ) ; + bsphere.setCenter ( xyz.getX(), xyz.getY(), xyz.getZ() ) ; } // particle_create //----------------------------------------------------------------------------- -void Smoke::particle_update (float delta, int, - Particle * particle) +void Smoke::particle_update(float delta, int, + Particle * particle) { - particle->m_size += delta*2.0f; + particle->m_size -= delta*.2f; particle->m_col[3] -= delta * 2.0f; - - particle->m_pos[0] += particle->m_vel[0] * delta; - particle->m_pos[1] += particle->m_vel[1] * delta; - particle->m_pos[2] += particle->m_vel[2] * delta; } // particle_update //----------------------------------------------------------------------------- void Smoke::particle_delete (int , Particle* ) -{} // particle_delete +{ +} // particle_delete diff --git a/src/smoke.hpp b/src/smoke.hpp index 6e38b552a..59db5662a 100755 --- a/src/smoke.hpp +++ b/src/smoke.hpp @@ -29,11 +29,13 @@ class Kart; class Smoke : public ParticleSystem { private: - Kart* m_kart; - + /** The kart to which this smoke belongs. */ + Kart *m_kart; + /** The texture to use. */ + ssgSimpleState *m_smokepuff; public: - Smoke(Kart* kart, int num, float _create_rate, - int _turn_to_face, float sz, float bsphere_size); + Smoke (Kart* kart); + ~Smoke (); virtual void update (float t ); virtual void particle_create(int index, Particle* p ); virtual void particle_update(float deltaTime, int index, Particle *p );