Made per-material particles almost a reality. Sadly now we have terrible problems with irrlicht's render order

git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@7321 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
auria 2011-01-07 01:32:46 +00:00
parent 18b3c91954
commit 9f4e949874
10 changed files with 392 additions and 139 deletions

View File

@ -26,6 +26,7 @@
#include "config/user_config.hpp"
#include "config/stk_config.hpp"
#include "graphics/irr_driver.hpp"
#include "graphics/particle_kind_manager.hpp"
#include "io/file_manager.hpp"
#include "io/xml_node.hpp"
#include "utils/string_utils.hpp"
@ -70,8 +71,6 @@ Material::Material(const XMLNode *node, int index)
node->get("graphical-effect", &s );
if(s=="water")
m_graphical_effect = GE_WATER;
else if(s=="smoke")
m_graphical_effect = GE_SMOKE;
else if (s!="")
fprintf(stderr,
"Invalid graphical effect specification: '%s' - ignored.\n",
@ -79,11 +78,13 @@ Material::Material(const XMLNode *node, int index)
else
m_graphical_effect = GE_NONE;
node->get("compositing", &s);
if (s == "blend") m_alpha_blending = true;
else if (s == "test") m_alpha_testing = true;
else if (s == "additive") m_add = true;
else if (s != "none") fprintf(stderr, "[Material] WARNING: Unknown alpha mode '%s'\n", s.c_str());
if (node->get("compositing", &s))
{
if (s == "blend") m_alpha_blending = true;
else if (s == "test") m_alpha_testing = true;
else if (s == "additive") m_add = true;
else if (s != "none") fprintf(stderr, "[Material] WARNING: Unknown compositing mode '%s'\n", s.c_str());
}
node->get("zipper", &m_zipper );
node->get("zipper-duration", &m_zipper_duration );
@ -92,22 +93,26 @@ Material::Material(const XMLNode *node, int index)
node->get("zipper-speed-gain", &m_zipper_speed_gain );
// Terrain-specifc sound effect
for(unsigned int i=0; i<node->getNumNodes(); i++)
const unsigned int children_count = node->getNumNodes();
for (unsigned int i=0; i<children_count; i++)
{
const XMLNode *sfx= node->getNode(i);
if(sfx->getName()!="sfx")
const XMLNode *child_node = node->getNode(i);
if (child_node->getName() == "sfx")
{
printf("Warning: unknown node type '%s' for texture '%s' - ignored.\n",
sfx->getName().c_str(), m_texname.c_str());
continue;
initCustomSFX(child_node);
}
if(m_sfx_name!="")
else if (child_node->getName() == "particles")
{
printf("Warning: more than one sfx specified for texture '%s' - ignored.\n",
m_texname.c_str());
continue;
initParticlesEffect(child_node);
}
initCustomSFX(sfx);
else
{
fprintf(stderr, "[Material] WARNING: unknown node type '%s' for texture '%s' - ignored.\n",
child_node->getName().c_str(), m_texname.c_str());
}
} // for i <node->getNumNodes()
install(/*is_full_path*/false);
} // Material
@ -157,6 +162,11 @@ void Material::init(unsigned int index)
m_zipper_fade_out_time = -1.0f;
m_zipper_max_speed_increase = -1.0f;
m_zipper_speed_gain = -1.0f;
for (int n=0; n<EMIT_KINDS_COUNT; n++)
{
m_particles_effects[n] = NULL;
}
} // init
//-----------------------------------------------------------------------------
@ -213,6 +223,62 @@ void Material::initCustomSFX(const XMLNode *sfx)
}
} // initCustomSFX
//-----------------------------------------------------------------------------
void Material::initParticlesEffect(const XMLNode *node)
{
ParticleKindManager* pkm = ParticleKindManager::get();
std::string base;
node->get("base", &base);
if (base.size() < 1)
{
fprintf(stderr, "[Material::initParticlesEffect] WARNING: Invalid particle settings for material '%s'\n",
m_texname.c_str());
return;
}
ParticleKind* particles = NULL;
try
{
particles = pkm->getParticles(base.c_str());
}
catch (...)
{
fprintf(stderr, "[Material::initParticlesEffect] WARNING: Cannot find particles '%s' for material '%s'\n",
base.c_str(), m_texname.c_str());
return;
}
std::vector<std::string> conditions;
node->get("condition", &conditions);
const int count = conditions.size();
if (count == 0)
{
fprintf(stderr, "[Material::initParticlesEffect] WARNING: Particles '%s' for material '%s' are declared but not used\n",
base.c_str(), m_texname.c_str());
}
for (int c=0; c<count; c++)
{
if (conditions[c] == "skid")
{
m_particles_effects[EMIT_ON_SKID] = particles;
}
else if (conditions[c] == "drive")
{
m_particles_effects[EMIT_ON_DRIVE] = particles;
}
else
{
fprintf(stderr, "[Material::initParticlesEffect] WARNING: Unknown condition '%s' for material '%s'\n",
conditions[c].c_str(), m_texname.c_str());
}
}
} // initParticlesEffect
//-----------------------------------------------------------------------------
/** Adjusts the pitch of the given sfx depending on the given speed.
* \param sfx The sound effect to adjust.

View File

@ -29,6 +29,7 @@ using namespace irr;
class XMLNode;
class SFXBase;
class ParticleKind;
/**
* \ingroup graphics
@ -36,8 +37,16 @@ class SFXBase;
class Material : public NoCopy
{
public:
enum GraphicalEffect {GE_NONE, GE_SMOKE, GE_WATER};
enum GraphicalEffect {GE_NONE, GE_WATER};
enum ParticleConditions
{
EMIT_ON_DRIVE = 0,
EMIT_ON_SKID,
EMIT_KINDS_COUNT
};
private:
video::ITexture *m_texture;
unsigned int m_index;
@ -51,6 +60,8 @@ private:
bool m_ignore;
bool m_add;
ParticleKind* m_particles_effects[EMIT_KINDS_COUNT];
/** Texture clamp bitmask */
unsigned int m_clamp_tex;
bool m_lighting;
@ -101,6 +112,8 @@ private:
void init (unsigned int index);
void install (bool is_full_path=false);
void initCustomSFX(const XMLNode *sfx);
void initParticlesEffect(const XMLNode *node);
public:
Material(const XMLNode *node, int index);
Material(const std::string& fname, int index,
@ -130,7 +143,7 @@ public:
float getSlowDownTime() const { return m_slowdown_time; }
// ------------------------------------------------------------------------
/** Returns true if this material should have smoke effect. */
bool hasSmoke () const { return m_graphical_effect==GE_SMOKE;}
//bool hasSmoke () const { return m_graphical_effect==GE_SMOKE;}
// ------------------------------------------------------------------------
/** Returns true if this material should have water splashes. */
bool hasWaterSplash () const { return m_graphical_effect==GE_WATER;}
@ -139,6 +152,13 @@ public:
* terrain. The string will be "" if no special sfx exists. */
const std::string &
getSFXName () const { return m_sfx_name; }
/**
* \brief Get the kind of particles that are to be used on this material, in the given conditions
* \return The particles to use, or NULL if none
*/
const ParticleKind* getParticlesWhen(ParticleConditions cond) const { return m_particles_effects[cond]; }
// ------------------------------------------------------------------------
/** Returns the zipper parametersfor the current material. */
void getZipperParameter(float *zipper_max_speed_increase,

View File

@ -26,97 +26,12 @@
#include "io/file_manager.hpp"
#include "utils/constants.hpp"
ParticleEmitter::ParticleEmitter(ParticleKind* type, core::vector3df position,
scene::ISceneNode* parent)
ParticleEmitter::ParticleEmitter(const ParticleKind* type, core::vector3df position,
scene::ISceneNode* parent) : m_position(position)
{
m_node = irr_driver->addParticleNode();
m_particle_type = type;
Material* material = type->getMaterial();
const float minSize = type->getMinSize();
const float maxSize = type->getMaxSize();
const int lifeTimeMin = type->getMinLifetime();
const int lifeTimeMax = type->getMaxLifetime();
assert(material->getTexture() != NULL);
assert(maxSize >= minSize);
assert(lifeTimeMax >= lifeTimeMin);
#ifdef DEBUG
std::string debug_name = std::string("particles(") + material->getTexture()->getName().getPath().c_str() + ")";
m_node->setName(debug_name.c_str());
#endif
if (parent != NULL)
{
m_node->setParent(parent);
}
m_node->setPosition(position);
material->setMaterialProperties(&(m_node->getMaterial(0)));
m_node->setMaterialTexture(0, material->getTexture());
//m_node->getMaterial(0).MaterialType = video::EMT_ONETEXTURE_BLEND ;
//m_node->getMaterial(0).MaterialTypeParam = pack_texureBlendFunc(video::EBF_SRC_ALPHA, video::EBF_ONE_MINUS_SRC_ALPHA,
// video::EMFN_MODULATE_1X, video::EAS_TEXTURE | video::EAS_VERTEX_COLOR);
m_node->getMaterial(0).ZWriteEnable = false; // disable z-buffer writes
switch (type->getShape())
{
case EMITTER_POINT:
{
m_emitter = m_node->createPointEmitter(core::vector3df(m_particle_type->getVelocityX(),
m_particle_type->getVelocityY(),
m_particle_type->getVelocityZ()), // velocity in m/ms
type->getMinRate(), type->getMaxRate(),
type->getMinColor(), type->getMaxColor(),
lifeTimeMin, lifeTimeMax,
m_particle_type->getAngleSpread() /* angle */
);
break;
}
case EMITTER_BOX:
{
const float box_size_x = type->getBoxSizeX()/2.0f;
const float box_size_y = type->getBoxSizeY()/2.0f;
const float box_size_z = type->getBoxSizeZ()/2.0f;
m_emitter = m_node->createBoxEmitter(core::aabbox3df(-box_size_x, -box_size_y, -box_size_z,
box_size_x, box_size_y, box_size_z),
core::vector3df(m_particle_type->getVelocityX(),
m_particle_type->getVelocityY(),
m_particle_type->getVelocityZ()), // velocity in m/ms
type->getMinRate(), type->getMaxRate(),
type->getMinColor(), type->getMaxColor(),
lifeTimeMin, lifeTimeMax,
m_particle_type->getAngleSpread() /* angle */
);
//irr_driver->getSceneManager()->addCubeSceneNode(2.0f, parent, -1, position, core::vector3df(0, 0, 0) /* rotation */,
// core::vector3df(box_size_x, box_size_y, box_size_z));
break;
}
default:
{
fprintf(stderr, "[ParticleEmitter] Unknown shape\n");
return;
}
}
m_emitter->setMinStartSize(core::dimension2df(minSize, minSize));
m_emitter->setMaxStartSize(core::dimension2df(maxSize, maxSize));
m_node->setEmitter(m_emitter); // this grabs the emitter
m_emitter->drop(); // so we can drop our references
// FIXME: this is ridiculous, the fadeout time should be equal to the lifetime, except that the
// lifetime is random...
scene::IParticleFadeOutAffector *af = m_node->createFadeOutParticleAffector(video::SColor(0, 255, 255, 255),
type->getFadeoutTime());
m_node->addAffector(af);
af->drop();
m_node = NULL;
m_parent = parent;
setParticleType(type);
} // KartParticleSystem
@ -162,3 +77,98 @@ void ParticleEmitter::setPosition(core::vector3df pos)
{
m_node->setPosition(pos);
}
//-----------------------------------------------------------------------------
void ParticleEmitter::setParticleType(const ParticleKind* type)
{
if (m_particle_type == type) return; // already the right type
if (m_node != NULL) m_node->remove();
m_node = irr_driver->addParticleNode();
m_particle_type = type;
Material* material = type->getMaterial();
const float minSize = type->getMinSize();
const float maxSize = type->getMaxSize();
const int lifeTimeMin = type->getMinLifetime();
const int lifeTimeMax = type->getMaxLifetime();
assert(material->getTexture() != NULL);
assert(maxSize >= minSize);
assert(lifeTimeMax >= lifeTimeMin);
#ifdef DEBUG
std::string debug_name = std::string("particles(") + material->getTexture()->getName().getPath().c_str() + ")";
m_node->setName(debug_name.c_str());
#endif
if (m_parent != NULL)
{
m_node->setParent(m_parent);
}
m_node->setPosition(m_position);
material->setMaterialProperties(&(m_node->getMaterial(0)));
m_node->setMaterialTexture(0, material->getTexture());
m_node->getMaterial(0).ZWriteEnable = false; // disable z-buffer writes
switch (type->getShape())
{
case EMITTER_POINT:
{
m_emitter = m_node->createPointEmitter(core::vector3df(m_particle_type->getVelocityX(),
m_particle_type->getVelocityY(),
m_particle_type->getVelocityZ()), // velocity in m/ms
type->getMinRate(), type->getMaxRate(),
type->getMinColor(), type->getMaxColor(),
lifeTimeMin, lifeTimeMax,
m_particle_type->getAngleSpread() /* angle */
);
break;
}
case EMITTER_BOX:
{
const float box_size_x = type->getBoxSizeX()/2.0f;
const float box_size_y = type->getBoxSizeY()/2.0f;
const float box_size_z = type->getBoxSizeZ()/2.0f;
m_emitter = m_node->createBoxEmitter(core::aabbox3df(-box_size_x, -box_size_y, -box_size_z,
box_size_x, box_size_y, box_size_z),
core::vector3df(m_particle_type->getVelocityX(),
m_particle_type->getVelocityY(),
m_particle_type->getVelocityZ()), // velocity in m/ms
type->getMinRate(), type->getMaxRate(),
type->getMinColor(), type->getMaxColor(),
lifeTimeMin, lifeTimeMax,
m_particle_type->getAngleSpread() /* angle */
);
//irr_driver->getSceneManager()->addCubeSceneNode(2.0f, parent, -1, position, core::vector3df(0, 0, 0) /* rotation */,
// core::vector3df(box_size_x, box_size_y, box_size_z));
break;
}
default:
{
fprintf(stderr, "[ParticleEmitter] Unknown shape\n");
return;
}
}
m_emitter->setMinStartSize(core::dimension2df(minSize, minSize));
m_emitter->setMaxStartSize(core::dimension2df(maxSize, maxSize));
m_node->setEmitter(m_emitter); // this grabs the emitter
m_emitter->drop(); // so we can drop our references
// FIXME: this is ridiculous, the fadeout time should be equal to the lifetime, except that the
// lifetime is random...
scene::IParticleFadeOutAffector *af = m_node->createFadeOutParticleAffector(video::SColor(0, 255, 255, 255),
type->getFadeoutTime());
m_node->addAffector(af);
af->drop();
}

View File

@ -39,15 +39,19 @@ private:
/** Irrlicht's particle systems. */
scene::IParticleSystemSceneNode *m_node; /* left wheel */
core::vector3df m_position;
scene::ISceneNode* m_parent;
/** The emitters. Access to these is needed to adjust the number of
* particles per second. */
scene::IParticleEmitter *m_emitter;
ParticleKind *m_particle_type;
const ParticleKind *m_particle_type;
public:
ParticleEmitter (ParticleKind* type, core::vector3df position,
ParticleEmitter (const ParticleKind* type, core::vector3df position,
scene::ISceneNode* parent = NULL);
virtual ~ParticleEmitter();
virtual void update ();
@ -55,7 +59,9 @@ public:
void setPosition(core::vector3df pos);
ParticleKind* getParticlesInfo() { return m_particle_type; }
const ParticleKind* getParticlesInfo() const { return m_particle_type; }
void setParticleType(const ParticleKind* p);
};
#endif

View File

@ -76,11 +76,15 @@ private:
public:
/**
* @brief Load a XML file describing a type of particles
* @param file Name of the file to load (no full path)
* @throw std::runtime_error If the file cannot be found or is heavily malformed
*/
ParticleKind(const std::string file);
virtual ~ParticleKind() {}
//float getParticleSize() const { return m_particle_size; }
float getMaxSize () const { return m_max_size; }
float getMinSize () const { return m_min_size; }

View File

@ -0,0 +1,63 @@
// $Id$
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2011 Joerg Henrichs, Marianne Gagnon
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "graphics/particle_kind_manager.hpp"
#include "io/file_manager.hpp"
// ----------------------------------------------------------------------------
ParticleKindManager* ParticleKindManager::singleton = NULL;
ParticleKindManager* ParticleKindManager::get()
{
if (singleton == NULL) singleton = new ParticleKindManager();
return singleton;
}
// ----------------------------------------------------------------------------
ParticleKindManager::ParticleKindManager()
{
}
// ----------------------------------------------------------------------------
ParticleKindManager::~ParticleKindManager()
{
// TODO: free items in map
}
// ----------------------------------------------------------------------------
ParticleKind* ParticleKindManager::getParticles(const char* name)
{
std::map<std::string, ParticleKind*>::iterator i = m_kinds.find(name);
if (i == m_kinds.end())
{
ParticleKind* newkind = new ParticleKind(file_manager->getDataFile(name));
m_kinds[name] = newkind;
return newkind;
}
else
{
return i->second;
}
}
// ----------------------------------------------------------------------------

View File

@ -0,0 +1,51 @@
// $Id$
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2011 Marianne Gagnon
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#ifndef HEADER_PARTICLE_KIND_MANAGER_HPP
#define HEADER_PARTICLE_KIND_MANAGER_HPP
#include "utils/no_copy.hpp"
#include "graphics/particle_kind.hpp"
#include <string>
#include <map>
/**
* \brief Holds and manages a list of all types of particles
* \ingroup graphics
*/
class ParticleKindManager : public NoCopy
{
private:
std::map<std::string, ParticleKind*> m_kinds;
static ParticleKindManager* singleton;
ParticleKindManager();
public:
virtual ~ParticleKindManager();
ParticleKind* getParticles(const char* name);
static ParticleKindManager* get();
};
#endif

View File

@ -35,6 +35,7 @@
95263DEF0FD7471900CF5F92 /* highscores.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 95263DE60FD7471900CF5F92 /* highscores.cpp */; };
95263DF00FD7471900CF5F92 /* history.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 95263DE80FD7471900CF5F92 /* history.cpp */; };
95263DF10FD7471900CF5F92 /* race_manager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 95263DEA0FD7471900CF5F92 /* race_manager.cpp */; };
9528C71612D69494006E9167 /* particle_kind_manager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9528C71412D69494006E9167 /* particle_kind_manager.cpp */; };
9528CC241291E7A10078A5EF /* binding.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9528CC221291E7A10078A5EF /* binding.cpp */; };
952A1545103F66D600B1895D /* camera.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 952A152D103F66D600B1895D /* camera.cpp */; };
952A1546103F66D600B1895D /* explosion.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 952A152F103F66D600B1895D /* explosion.cpp */; };
@ -388,6 +389,8 @@
95263DE90FD7471900CF5F92 /* history.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = history.hpp; path = ../../race/history.hpp; sourceTree = SOURCE_ROOT; };
95263DEA0FD7471900CF5F92 /* race_manager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = race_manager.cpp; path = ../../race/race_manager.cpp; sourceTree = SOURCE_ROOT; };
95263DEB0FD7471900CF5F92 /* race_manager.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = race_manager.hpp; path = ../../race/race_manager.hpp; sourceTree = SOURCE_ROOT; };
9528C71412D69494006E9167 /* particle_kind_manager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = particle_kind_manager.cpp; path = ../../graphics/particle_kind_manager.cpp; sourceTree = SOURCE_ROOT; };
9528C71512D69494006E9167 /* particle_kind_manager.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = particle_kind_manager.hpp; path = ../../graphics/particle_kind_manager.hpp; sourceTree = SOURCE_ROOT; };
9528CC221291E7A10078A5EF /* binding.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = binding.cpp; path = ../../input/binding.cpp; sourceTree = SOURCE_ROOT; };
9528CC231291E7A10078A5EF /* binding.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = binding.hpp; path = ../../input/binding.hpp; sourceTree = SOURCE_ROOT; };
952A152D103F66D600B1895D /* camera.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = camera.cpp; path = ../../graphics/camera.cpp; sourceTree = SOURCE_ROOT; };
@ -1253,6 +1256,8 @@
9542FC7612D3BDB000C00366 /* particle_emitter.hpp */,
9542FD4A12D3E0D700C00366 /* particle_kind.cpp */,
9542FD4B12D3E0D700C00366 /* particle_kind.hpp */,
9528C71412D69494006E9167 /* particle_kind_manager.cpp */,
9528C71512D69494006E9167 /* particle_kind_manager.hpp */,
952A153D103F66D600B1895D /* shadow.cpp */,
952A153E103F66D600B1895D /* shadow.hpp */,
952A153F103F66D600B1895D /* skid_marks.cpp */,
@ -2726,6 +2731,7 @@
9538A56012CD094200CE3220 /* addon.cpp in Sources */,
9542FC7712D3BDB000C00366 /* particle_emitter.cpp in Sources */,
9542FD4C12D3E0D700C00366 /* particle_kind.cpp in Sources */,
9528C71612D69494006E9167 /* particle_kind_manager.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@ -32,6 +32,7 @@
#include "graphics/material_manager.hpp"
#include "graphics/particle_emitter.hpp"
#include "graphics/particle_kind.hpp"
#include "graphics/particle_kind_manager.hpp"
#include "graphics/shadow.hpp"
#include "graphics/skid_marks.hpp"
#include "graphics/slip_stream.hpp"
@ -89,7 +90,7 @@ Kart::Kart (const std::string& ident, int position,
m_finish_time = 0.0f;
m_shadow_enabled = false;
m_shadow = NULL;
m_smoke_system = NULL;
m_terrain_particles = NULL;
m_water_splash_system = NULL;
m_nitro = NULL;
m_slipstream = NULL;
@ -317,7 +318,7 @@ Kart::~Kart()
sfx_manager->deleteSFX(m_beep_sound );
if(m_terrain_sound) sfx_manager->deleteSFX(m_terrain_sound);
if(m_previous_terrain_sound) sfx_manager->deleteSFX(m_previous_terrain_sound);
if(m_smoke_system) delete m_smoke_system;
if(m_terrain_particles) delete m_terrain_particles;
if(m_water_splash_system) delete m_water_splash_system;
if(m_nitro) delete m_nitro;
if(m_slipstream) delete m_slipstream;
@ -729,9 +730,9 @@ void Kart::update(float dt)
m_attachment->update(dt);
//smoke drawing control point
if ( UserConfigParams::m_graphical_effects )
if (UserConfigParams::m_graphical_effects && m_terrain_particles)
{
m_smoke_system->update();
m_terrain_particles->update();
m_water_splash_system->update(dt);
} // UserConfigParams::m_graphical_effects
@ -1449,9 +1450,8 @@ void Kart::loadData()
// So it's easier not to move the particle system with the kart, and set
// the position directly from the wheel coordinates.
core::vector3df position(-getKartWidth()*0.35f, 0.06f, -getKartLength()*0.5f);
m_smoke_system = new ParticleEmitter(
new ParticleKind(file_manager->getDataFile("smoke.xml")),
position);
m_terrain_particles = new ParticleEmitter(ParticleKindManager::get()->getParticles("smoke.xml"),
position);
}
catch (std::runtime_error& e)
{
@ -1553,24 +1553,51 @@ void Kart::updateGraphics(const Vec3& offset_xyz,
-m_kart_model->getWheelGraphicsPosition(0).getY() );
center_shift.setY(y);
if(m_smoke_system)
if (m_terrain_particles)
{
float f=0.0f;
if(getMaterial() && getMaterial()->hasSmoke() &&
fabsf(m_controls.m_steer) > 0.8 &&
isOnGround() )
f=250.0f;
m_smoke_system->setCreationRate((m_skidding-1)*f);
m_wheel_toggle = 1 - m_wheel_toggle;
const btWheelInfo &wi = getVehicle()->getWheelInfo(2 + m_wheel_toggle);
Vec3 c = wi.m_raycastInfo.m_contactPointWS;
// FIXME: the X position is not yet always accurate.
m_smoke_system->setPosition(core::vector3df(c.getX() + 0.06f * (m_wheel_toggle ? +1 : -1),
c.getY(),
c.getZ() + 0.06f));
float f = 0.0f;
const Material* material = getMaterial();
if (material != NULL)
{
if (m_skidding)
{
const ParticleKind* pk = material->getParticlesWhen(Material::EMIT_ON_SKID);
if (pk != NULL)
{
m_terrain_particles->setParticleType(pk);
if (fabsf(m_controls.m_steer) > 0.8 && isOnGround()) f = 250.0f;
m_terrain_particles->setCreationRate((m_skidding-1)*f);
m_wheel_toggle = 1 - m_wheel_toggle;
const btWheelInfo &wi = getVehicle()->getWheelInfo(2 + m_wheel_toggle);
Vec3 c = wi.m_raycastInfo.m_contactPointWS;
// FIXME: the X position is not yet always accurate.
m_terrain_particles->setPosition(core::vector3df(c.getX() + 0.06f * (m_wheel_toggle ? +1 : -1),
c.getY(),
c.getZ() + 0.06f));
}
else
{
m_terrain_particles->setCreationRate(0);
}
}
else // not skidding
{
const ParticleKind* pk = material->getParticlesWhen(Material::EMIT_ON_DRIVE);
if (pk != NULL)
{
m_terrain_particles->setParticleType(pk);
}
else
{
m_terrain_particles->setCreationRate(0);
}
}
}
}
if(m_water_splash_system)
{

View File

@ -135,8 +135,8 @@ private:
* stuck to the kart, i.e. the shadow would be flying, too). */
bool m_shadow_enabled;
/** Smoke from skidding. */
ParticleEmitter *m_smoke_system;
/** Particle emitter used for terrain-specific effects (including but not limited too skidding). */
ParticleEmitter *m_terrain_particles;
/** Water splash when driving in water. */
WaterSplash *m_water_splash_system;