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:
parent
18b3c91954
commit
9f4e949874
@ -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.
|
||||
|
@ -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,
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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; }
|
||||
|
||||
|
63
src/graphics/particle_kind_manager.cpp
Normal file
63
src/graphics/particle_kind_manager.cpp
Normal 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;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
51
src/graphics/particle_kind_manager.hpp
Normal file
51
src/graphics/particle_kind_manager.hpp
Normal 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
|
||||
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user