From c7083edba3c12a345caa288a1fab772dbeac2d37 Mon Sep 17 00:00:00 2001 From: hikerstk Date: Mon, 30 Jan 2012 22:20:31 +0000 Subject: [PATCH] Moved terrain particle effectrs from kart into kart_gfx. git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@10766 178a84e3-b1eb-0310-8ba1-8eac791a3b58 --- src/karts/kart.cpp | 203 ++++++++++++++--------------------------- src/karts/kart.hpp | 6 -- src/karts/kart_gfx.cpp | 185 +++++++++++++++++++++++++++---------- src/karts/kart_gfx.hpp | 28 ++++-- 4 files changed, 220 insertions(+), 202 deletions(-) diff --git a/src/karts/kart.cpp b/src/karts/kart.cpp index 812be6df6..bf8e5c1b5 100644 --- a/src/karts/kart.cpp +++ b/src/karts/kart.cpp @@ -93,14 +93,12 @@ Kart::Kart (const std::string& ident, Track* track, int position, bool is_first_ m_race_position = position; m_collected_energy = 0; m_finished_race = false; - m_wheel_toggle = 1; m_finish_time = 0.0f; m_bubblegum_time = 0.0f; m_invulnerable_time = 0.0f; m_squash_time = 0.0f; m_shadow_enabled = false; m_shadow = NULL; - m_terrain_particles = NULL; m_collision_particles = NULL; m_slipstream = NULL; m_skidmarks = NULL; @@ -430,7 +428,6 @@ Kart::~Kart() delete m_kart_gfx; if(m_terrain_sound) sfx_manager->deleteSFX(m_terrain_sound); if(m_previous_terrain_sound) sfx_manager->deleteSFX(m_previous_terrain_sound); - if(m_terrain_particles) delete m_terrain_particles; if(m_collision_particles) delete m_collision_particles; if(m_slipstream) delete m_slipstream; if(m_rain) delete m_rain; @@ -906,7 +903,6 @@ void Kart::update(float dt) //smoke drawing control point if (UserConfigParams::m_graphical_effects) { - if (m_terrain_particles) m_terrain_particles->update(dt); if (m_rain) { m_rain->setPosition( getCamera()->getCameraSceneNode()->getPosition() ); @@ -1153,140 +1149,92 @@ void Kart::handleMaterialGFX() // on top of a surface (i.e. not falling), actually touching // something with the wheels, and the material has not the // below surface property set. - if (material && isOnGround() && !material->isBelowSurface() && m_kart_mode != EA_RESCUE) + if (material && isOnGround() && !material->isBelowSurface() && + m_kart_mode != EA_RESCUE && UserConfigParams::m_graphical_effects) { - if (m_terrain_particles) + + // Get the appropriate particle data depending on + // wether the kart is skidding or driving. + const ParticleKind* pk = + material->getParticlesWhen(m_skidding > 1.0f + ? Material::EMIT_ON_SKID + : Material::EMIT_ON_DRIVE); + if(!pk) { - Vec3 xyz; - m_wheel_toggle = 1 - m_wheel_toggle; - const btWheelInfo &wi = - getVehicle()->getWheelInfo(2 + m_wheel_toggle); - xyz = wi.m_raycastInfo.m_contactPointWS; - - // FIXME: the X position is not yet always accurate. - xyz += Vec3(0.06f * (m_wheel_toggle ? +1 : -1), - 0, - 0.06f); - - // Get the appropriate particle data depending on - // wether the kart is skidding or driving. - const ParticleKind* pk = - material->getParticlesWhen(m_skidding > 1.0f - ? Material::EMIT_ON_SKID - : Material::EMIT_ON_DRIVE); - if(!pk) - { - // Disable potentially running particle effects - m_terrain_particles->setCreationRateAbsolute(0); - return; // no particle effect, return - } - - // Now compute the particle creation rate: - float rate = 0; - const float speed = fabsf(getSpeed()); - - if (m_skidding > 1.0f) - { - rate = fabsf(m_controls.m_steer) > 0.8 ? m_skidding - 1 : 0; - } - else if (speed >= 0.5f) - { - rate = speed/m_kart_properties->getMaxSpeed(); - } - else - { - m_terrain_particles->setCreationRateAbsolute(0); - return; - } - - float create = pk->getMinRate()*(1-rate) + pk->getMaxRate()*rate; - m_terrain_particles->setParticleType(pk); - - // when particle type changes, the emitter is re-created at (0,0,0) so we need to - // set the position after setParticleType - m_terrain_particles->setPosition(xyz); - - m_terrain_particles->setCreationRateAbsolute(create); + // Disable potentially running particle effects + m_kart_gfx->setCreationRateAbsolute(KartGFX::KGFX_TERRAIN, 0); + return; // no particle effect, return } - + m_kart_gfx->updateTerrain(pk); return; } - // Now the kart is either falling, or driving on a terrain which // has the 'below surface' flag set. Detect if there is a surface // on top of the kart. + // -------------------------------------------------------------- if (m_camera && m_camera->getMode() != Camera::CM_FINAL) { if (material && material->hasFallingEffect() && !m_flying) { m_camera->setMode(Camera::CM_FALLING); } - else if (m_camera->getMode() != Camera::CM_NORMAL && m_camera->getMode() != Camera::CM_REVERSE) + else if (m_camera->getMode() != Camera::CM_NORMAL && + m_camera->getMode() != Camera::CM_REVERSE) { m_camera->setMode(Camera::CM_NORMAL); } - } + } // camera != final camera - if (m_terrain_particles) - { - // Use the middle of the contact points of the two rear wheels - // as the point from which to cast the ray upwards - const btWheelInfo::RaycastInfo &ri2 = - getVehicle()->getWheelInfo(2).m_raycastInfo; - const btWheelInfo::RaycastInfo &ri3 = - getVehicle()->getWheelInfo(3).m_raycastInfo; - Vec3 from = (ri2.m_contactPointWS + ri3.m_contactPointWS)*0.5f; - Vec3 xyz; - const Material *surface_material; - if(!getSurfaceInfo(from, &xyz, &surface_material)) - { - m_terrain_particles->setCreationRateAbsolute(0); - return; - } - const ParticleKind *pk = - surface_material->getParticlesWhen(Material::EMIT_ON_DRIVE); - if(pk && !m_flying && m_kart_mode != EA_RESCUE) - { - const float distance = xyz.distance2(from); - m_terrain_particles->setParticleType(pk); - m_terrain_particles->setPosition(xyz.toIrrVector()); - //const float speed = fabsf(getSpeed()); - //float rate = (speed>=0.5f) ? speed/m_kart_properties->getMaxSpeed() - // : 0; + if (!UserConfigParams::m_graphical_effects) + return; - float create; - if (distance < 2.0f) - { - create = (float)pk->getMaxRate(); - } - else if (distance < 4.0f) - { - create = pk->getMinRate() + (pk->getMaxRate() - pk->getMinRate())*(distance - 2.0f)/2.0f; - } - else - { - create = 0.0f; - } - m_terrain_particles->setCreationRateAbsolute(create); - - - const std::string s = surface_material->getSFXName(); - if (s != "" && m_kart_mode != EA_RESCUE && - (m_terrain_sound == NULL || m_terrain_sound->getStatus() == SFXManager::SFX_STOPPED)) - { - if (m_previous_terrain_sound) sfx_manager->deleteSFX(m_previous_terrain_sound); - m_previous_terrain_sound = m_terrain_sound; - if(m_previous_terrain_sound) - m_previous_terrain_sound->setLoop(false); - - m_terrain_sound = sfx_manager->createSoundSource(s); - m_terrain_sound->play(); - m_terrain_sound->setLoop(false); - } - - // handleMaterialSFX(surface_material); - } + // Use the middle of the contact points of the two rear wheels + // as the point from which to cast the ray upwards + const btWheelInfo::RaycastInfo &ri2 = + getVehicle()->getWheelInfo(2).m_raycastInfo; + const btWheelInfo::RaycastInfo &ri3 = + getVehicle()->getWheelInfo(3).m_raycastInfo; + Vec3 from = (ri2.m_contactPointWS + ri3.m_contactPointWS)*0.5f; + Vec3 xyz; + const Material *surface_material; + if(!getSurfaceInfo(from, &xyz, &surface_material)) + { + m_kart_gfx->setCreationRateAbsolute(KartGFX::KGFX_TERRAIN, 0); + return; + } + const ParticleKind *pk = + surface_material->getParticlesWhen(Material::EMIT_ON_DRIVE); + + if(!pk || m_flying || m_kart_mode == EA_RESCUE) + return; + + // Now the kart is under a surface, and there is a surface effect + // -------------------------------------------------------------- + m_kart_gfx->setParticleKind(KartGFX::KGFX_TERRAIN, pk); + m_kart_gfx->setXYZ(KartGFX::KGFX_TERRAIN, xyz); + + const float distance = xyz.distance2(from); + float ratio; + if (distance < 2.0f) ratio = 1.0f; + else if (distance < 4.0f) ratio = (4.0f-distance)*0.5f; + else ratio = -1.0f; // No more particles + m_kart_gfx->setCreationRateRelative(KartGFX::KGFX_TERRAIN, ratio); + + // Play special sound effects for this terrain + // ------------------------------------------- + const std::string s = surface_material->getSFXName(); + if (s != "" && m_kart_mode != EA_RESCUE && + (m_terrain_sound == NULL || m_terrain_sound->getStatus() == SFXManager::SFX_STOPPED)) + { + if (m_previous_terrain_sound) sfx_manager->deleteSFX(m_previous_terrain_sound); + m_previous_terrain_sound = m_terrain_sound; + if(m_previous_terrain_sound) + m_previous_terrain_sound->setLoop(false); + + m_terrain_sound = sfx_manager->createSoundSource(s); + m_terrain_sound->play(); + m_terrain_sound->setLoop(false); } } // handleMaterialGFX @@ -2028,25 +1976,6 @@ void Kart::loadData(RaceManager::KartType type, bool is_first_kart, createPhysics(); // Attach Particle System - - if (UserConfigParams::m_graphical_effects && !isWheeless()) - { - try - { - // Note: the smoke system is NOT child of the kart, since bullet - // gives the position of the wheels on the ground in world coordinates. - // So it's easier not to move the particle system with the kart, and set - // the position directly from the wheel coordinates. - Vec3 position(-getKartWidth()*0.35f, 0.06f, -getKartLength()*0.5f); - m_terrain_particles = new ParticleEmitter(ParticleKindManager::get()->getParticles("smoke.xml"), - position); - } - catch (std::runtime_error& e) - { - std::cerr << "[Kart::loadData] " << e.what() << std::endl; - } - } - if (type == RaceManager::KT_PLAYER && UserConfigParams::m_weather_effects && track->getSkyParticles() != NULL) diff --git a/src/karts/kart.hpp b/src/karts/kart.hpp index f630d44ff..88f9d1596 100644 --- a/src/karts/kart.hpp +++ b/src/karts/kart.hpp @@ -114,9 +114,6 @@ private: * determine startup boost. */ bool m_has_started; - /** For skidding smoke */ - int m_wheel_toggle; - /** -KartGFX::KartGFX(const Kart *kart) : m_current_skid(KGFX_SKID1) +KartGFX::KartGFX(const Kart *kart) { if(!UserConfigParams::m_graphical_effects) { for(unsigned int i=0; igetKartHeight()*0.35f, - -kart->getKartLength()*0.35f); + Vec3 rear_center(0, kart->getKartHeight()*0.35f, + -kart->getKartLength()*0.35f); // Create all effects. Note that they must be created // in the order of KartGFXType. - addEffect(KGFX_NITRO, "nitro.xml", position); - addEffect(KGFX_ZIPPER, "zipper_fire.xml", position); - addEffect(KGFX_SKID1, "skid1.xml", position); - addEffect(KGFX_SKID2, "skid2.xml", position); + addEffect(KGFX_NITRO, "nitro.xml", rear_center); + addEffect(KGFX_ZIPPER, "zipper_fire.xml", rear_center); + addEffect(KGFX_TERRAIN, "smoke.xml", Vec3(0,0,0)); + addEffect(KGFX_SKID1, "skid1.xml", rear_center); + addEffect(KGFX_SKID2, "skid2.xml", rear_center); } // KartGFX // ---------------------------------------------------------------------------- +/** Destructor. Frees all particle effects and kinds. + */ KartGFX::~KartGFX() { for(unsigned int i=0; igetGfxFile(file_name)); - if(type==KGFX_SKID2) - emitter = NULL; // skid2 is only used to store the emitter type + + kind = ParticleKindManager::get()->getParticles(file_name); + //kind = new ParticleKind(file_manager->getGfxFile(file_name)); + // Skid2 is only used to store the emitter type, and a wheeless + // kart has no terrain effects. + if(type==KGFX_SKID2 || (type==KGFX_TERRAIN && m_kart->isWheeless()) ) + emitter = NULL; + else if(type==KGFX_TERRAIN) + // Terrain is NOT a child of the kart, since bullet returns the + // raycast info in world coordinates + emitter = new ParticleEmitter(kind, position); else - emitter = new ParticleEmitter(kind, - position, - m_kart->getNode()); + emitter = new ParticleEmitter(kind, position, m_kart->getNode()); } catch (std::runtime_error& e) { @@ -99,13 +105,18 @@ void KartGFX::addEffect(KartGFXType type, const std::string &file_name, } assert(m_all_emitters.size()==type); m_all_emitters.push_back(emitter); - assert(m_all_particle_kinds.size()==type); - m_all_particle_kinds.push_back(kind); + if(type==KGFX_SKID1) + m_skid_kind1 = kind; + else if (type==KGFX_SKID2) + m_skid_kind2 = kind; } // addEffect // ---------------------------------------------------------------------------- +/** Resets all particle emitters. Used at the (re)start of a race. + */ void KartGFX::reset() { + m_wheel_toggle = 1; for(unsigned int i=0; i= 1); + assert(level <= 2); + const ParticleKind *pk = level==1 ? m_skid_kind1 : m_skid_kind2; if(m_all_emitters[KGFX_SKID1]) - m_all_emitters[KGFX_SKID1]->setParticleType( - m_all_particle_kinds[type]); + m_all_emitters[KGFX_SKID1]->setParticleType(pk); } // setSkidLevel // ---------------------------------------------------------------------------- -/** Updates all gfx. - * \param dt Time step size. +/** Sets a new particle type to be used. Note that the memory of this + * kind must be managed by the caller. + * \param type The emitter type for which to set the new particle type. + * \param pk The particle kind to use. */ -void KartGFX::update(float dt) +void KartGFX::setParticleKind(const KartGFXType type, const ParticleKind *pk) { - if(!UserConfigParams::m_graphical_effects) return; + ParticleEmitter *pe = m_all_emitters[KGFX_TERRAIN]; + if(pe) return; - for(unsigned int i=0; iupdate(dt); - } - -} // update + pe->setParticleType(pk); +} // setParticleKind // ---------------------------------------------------------------------------- -/** Sets the creation rate for the specified particle type relative to the - * given minimum and maximum particle rate. - * \param type The particle effect for which to set the - * creation rate. - * \param f The new relative creation rate. +/** Defines the new position of the specified emitter. + * \param type The emitter to set a new position for. + * \param xyz The new position of the emitter. */ -void KartGFX::setCreationRateRelative(KartGFXType type, float f) +void KartGFX::setXYZ(const KartGFXType type, const Vec3 &xyz) { - if(m_all_emitters[type]) - m_all_emitters[type]->setCreationRateRelative(f); -} // setCreationRate + ParticleEmitter *pe = m_all_emitters[KGFX_TERRAIN]; + if(!pe) return; + pe->setPosition(xyz); +} // setXYZ // ---------------------------------------------------------------------------- /** Sets the absolute creation rate for the specified particle type. @@ -170,7 +177,26 @@ void KartGFX::setCreationRateAbsolute(KartGFXType type, float f) { if(m_all_emitters[type]) m_all_emitters[type]->setCreationRateAbsolute(f); -} // setCreationRate +} // setCreationRateAbsolute + +// ---------------------------------------------------------------------------- +/** Sets the creation rate for the specified particle type relative to the + * given minimum and maximum particle rate. If a negative value is + * specified, the creation rate will be set to 0 (absolute). + * \param type The particle effect for which to set the + * creation rate (<0 means no more particles). + * \param f The new relative creation rate. + */ +void KartGFX::setCreationRateRelative(KartGFXType type, float f) +{ + if(m_all_emitters[type]) + { + if(f<0) + m_all_emitters[type]->setCreationRateAbsolute(0); + else + m_all_emitters[type]->setCreationRateRelative(f); + } +} // setCreationRateRelative // ---------------------------------------------------------------------------- /** Resize the area from which the particles are emitted: the emitter box @@ -185,4 +211,63 @@ void KartGFX::resizeBox(KartGFXType type, float speed, float dt) { if(m_all_emitters[type]) m_all_emitters[type]->resizeBox(std::max(0.25f, speed*dt)); -} // resizeBox \ No newline at end of file +} // resizeBox + +// ---------------------------------------------------------------------------- +/** If necessary defines a new particle type for the terrain emitter. Then + * adjusts the location of the terrain emitter to be in synch with the + * current wheel position, and defines the emission rate depending on speed, + * steering, and skidding. + * \param pk Particle type to use. + */ +void KartGFX::updateTerrain(const ParticleKind *pk) +{ + ParticleEmitter *pe = m_all_emitters[KGFX_TERRAIN]; + if(!pe) return; + + pe->setParticleType(pk); + + const btWheelInfo &wi = m_kart->getVehicle() + ->getWheelInfo(2+m_wheel_toggle); + Vec3 xyz = wi.m_raycastInfo.m_contactPointWS; + // FIXME: the X and Z position is not always accurate. + xyz.setX(xyz.getX()+ 0.06f * (m_wheel_toggle ? +1 : -1)); + xyz.setZ(xyz.getZ()+0.06f); + pe->setPosition(xyz); + + // Now compute the particle creation rate: + float rate = 0; + const float speed = fabsf(m_kart->getSpeed()); + const float skidding = m_kart->getSkidding(); + if (skidding > 1.0f) + rate = fabsf(m_kart->getControls().m_steer) > 0.8 ? skidding - 1 : 0; + else if (speed >= 0.5f) + rate = speed/m_kart->getKartProperties()->getMaxSpeed(); + else + { + pe->setCreationRateAbsolute(0); + return; + } + // m_skidding can be > 2, and speed > maxSpeed (if powerups are used). + if(rate>1.0f) rate = 1.0f; + pe->setCreationRateRelative(rate); +} // updateTerrain + +// ---------------------------------------------------------------------------- +/** Updates all gfx. + * \param dt Time step size. + */ +void KartGFX::update(float dt) +{ + if(!UserConfigParams::m_graphical_effects) return; + + m_wheel_toggle = 1 - m_wheel_toggle; + + for(unsigned int i=0; iupdate(dt); + } + +} // update + diff --git a/src/karts/kart_gfx.hpp b/src/karts/kart_gfx.hpp index 56af5c010..1e0355b31 100644 --- a/src/karts/kart_gfx.hpp +++ b/src/karts/kart_gfx.hpp @@ -34,18 +34,25 @@ class KartGFX { public: /** All particle effects supported by this object. - * Nitro, zipper, and skidding effects. KGFX_COUNT + * Nitro, zipper, terrain, and skidding effects. Two different + * skid types are supported, but only one emitter node will be + * created. So KGFX_SKID1/2 store the two types, and KGFX_SKID + * = KGFX_SKID1 stores the actual emitter node. KGFX_COUNT * is the number of entries and must therefore be last. */ enum KartGFXType { KGFX_NITRO=0, KGFX_ZIPPER, + KGFX_TERRAIN, KGFX_SKID, KGFX_SKID1=KGFX_SKID, KGFX_SKID2, KGFX_COUNT}; private: - /** Vector of all particle kinde. */ - std::vector m_all_particle_kinds; + /** The particle kind for skidding bonus level 1. */ + const ParticleKind *m_skid_kind1; + + /** The particle kind for skidding bonus level 2. */ + const ParticleKind *m_skid_kind2; /** Vector of all particle emitters. */ std::vector m_all_emitters; @@ -53,8 +60,8 @@ private: /** Pointer to the owner of this kart. */ const Kart *m_kart; - /** Indicates the current skidding level, either skid1 or skid2. */ - KartGFXType m_current_skid; + /** Used to alternate particle effects from the rear wheels. */ + int m_wheel_toggle; void addEffect(KartGFXType type, const std::string &file_name, const Vec3 &position); @@ -63,10 +70,13 @@ public: KartGFX(const Kart *kart); ~KartGFX(); void reset(); + void setSkidLevel(const unsigned int level); + void setParticleKind(const KartGFXType type, const ParticleKind *pk); + void setXYZ(const KartGFXType type, const Vec3 &xyz); + void setCreationRateAbsolute(const KartGFXType type, float f); + void setCreationRateRelative(const KartGFXType type, float f); + void resizeBox(const KartGFXType type, float speed, float dt); + void updateTerrain(const ParticleKind *pk); void update(float dt); - void setCreationRateAbsolute(KartGFXType type, float f); - void setCreationRateRelative(KartGFXType type, float f); - void resizeBox(KartGFXType type, float speed, float dt); - void setSkidLevel(unsigned int level); }; // KartWGFX #endif