2011-01-04 17:14:51 -05:00
|
|
|
// $Id$
|
2009-01-09 15:40:07 -05:00
|
|
|
//
|
|
|
|
// SuperTuxKart - a fun racing game with go-kart
|
2011-01-04 17:14:51 -05:00
|
|
|
// Copyright (C) 2011 Joerg Henrichs, Marianne Gagnon
|
2009-01-09 15:40:07 -05:00
|
|
|
//
|
|
|
|
// 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.
|
|
|
|
|
2011-01-04 17:14:51 -05:00
|
|
|
#include "graphics/particle_emitter.hpp"
|
2009-06-02 08:06:35 -04:00
|
|
|
|
2011-01-04 17:14:51 -05:00
|
|
|
#include "graphics/material.hpp"
|
2009-06-02 20:39:20 -04:00
|
|
|
#include "graphics/material_manager.hpp"
|
2011-01-04 20:39:18 -05:00
|
|
|
#include "graphics/particle_kind.hpp"
|
2009-06-02 08:06:35 -04:00
|
|
|
#include "graphics/irr_driver.hpp"
|
|
|
|
#include "io/file_manager.hpp"
|
2009-06-02 20:39:20 -04:00
|
|
|
#include "utils/constants.hpp"
|
2009-01-09 15:40:07 -05:00
|
|
|
|
2011-01-04 20:39:18 -05:00
|
|
|
ParticleEmitter::ParticleEmitter(ParticleKind* type, core::vector3df position,
|
|
|
|
scene::ISceneNode* parent)
|
2009-06-02 21:49:57 -04:00
|
|
|
{
|
2009-06-10 09:04:30 -04:00
|
|
|
m_node = irr_driver->addParticleNode();
|
2011-01-04 20:39:18 -05:00
|
|
|
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);
|
2011-01-04 17:14:51 -05:00
|
|
|
|
2010-08-08 18:54:04 -04:00
|
|
|
#ifdef DEBUG
|
2011-01-04 17:14:51 -05:00
|
|
|
std::string debug_name = std::string("particles(") + material->getTexture()->getName().getPath().c_str() + ")";
|
2010-08-08 18:54:04 -04:00
|
|
|
m_node->setName(debug_name.c_str());
|
|
|
|
#endif
|
2011-01-04 17:14:51 -05:00
|
|
|
|
2011-01-04 21:38:24 -05:00
|
|
|
|
2011-01-04 17:14:51 -05:00
|
|
|
if (parent != NULL)
|
|
|
|
{
|
|
|
|
m_node->setParent(parent);
|
|
|
|
}
|
|
|
|
|
|
|
|
m_node->setPosition(position);
|
2011-01-05 19:07:58 -05:00
|
|
|
material->setMaterialProperties(&(m_node->getMaterial(0)));
|
2011-01-04 17:14:51 -05:00
|
|
|
m_node->setMaterialTexture(0, material->getTexture());
|
2011-01-05 15:54:36 -05:00
|
|
|
|
2011-01-05 19:07:58 -05:00
|
|
|
//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);
|
2011-01-05 18:49:50 -05:00
|
|
|
m_node->getMaterial(0).ZWriteEnable = false; // disable z-buffer writes
|
|
|
|
|
2011-01-05 15:54:36 -05:00
|
|
|
switch (type->getShape())
|
|
|
|
{
|
|
|
|
case EMITTER_POINT:
|
2011-01-05 15:57:05 -05:00
|
|
|
{
|
2011-01-05 15:54:36 -05:00
|
|
|
// FIXME: does the maxAngle param work at all??
|
|
|
|
// FIXME: the min and max color params don't appear to work
|
2011-01-05 21:37:55 -05:00
|
|
|
m_emitter = m_node->createPointEmitter(core::vector3df(m_particle_type->getVelocityX(),
|
|
|
|
m_particle_type->getVelocityY(),
|
|
|
|
m_particle_type->getVelocityZ()), // velocity in m/ms
|
2011-01-05 15:54:36 -05:00
|
|
|
type->getMinRate(), type->getMaxRate(),
|
|
|
|
type->getMinColor(), type->getMaxColor(),
|
|
|
|
lifeTimeMin, lifeTimeMax,
|
2011-01-05 21:37:55 -05:00
|
|
|
m_particle_type->getAngleSpreadX() /* angle */
|
2011-01-05 15:54:36 -05:00
|
|
|
);
|
|
|
|
break;
|
2011-01-05 15:57:05 -05:00
|
|
|
}
|
|
|
|
|
2011-01-05 15:54:36 -05:00
|
|
|
case EMITTER_BOX:
|
2011-01-05 15:57:05 -05:00
|
|
|
{
|
2011-01-05 15:54:36 -05:00
|
|
|
// FIXME: does the maxAngle param work at all??
|
|
|
|
// FIXME: the min and max color params don't appear to work
|
2011-01-05 20:58:45 -05:00
|
|
|
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),
|
2011-01-05 21:37:55 -05:00
|
|
|
core::vector3df(m_particle_type->getVelocityX(),
|
|
|
|
m_particle_type->getVelocityY(),
|
|
|
|
m_particle_type->getVelocityZ()), // velocity in m/ms
|
2011-01-05 15:54:36 -05:00
|
|
|
type->getMinRate(), type->getMaxRate(),
|
|
|
|
type->getMinColor(), type->getMaxColor(),
|
|
|
|
lifeTimeMin, lifeTimeMax,
|
2011-01-05 21:37:55 -05:00
|
|
|
m_particle_type->getAngleSpreadX() /* angle */
|
2011-01-05 15:54:36 -05:00
|
|
|
);
|
2011-01-05 20:58:45 -05:00
|
|
|
|
2011-01-05 21:39:34 -05:00
|
|
|
//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));
|
2011-01-05 20:58:45 -05:00
|
|
|
|
2011-01-05 15:54:36 -05:00
|
|
|
break;
|
2011-01-05 15:57:05 -05:00
|
|
|
}
|
2011-01-04 21:57:17 -05:00
|
|
|
|
2011-01-05 15:54:36 -05:00
|
|
|
default:
|
2011-01-05 15:57:05 -05:00
|
|
|
{
|
2011-01-05 15:54:36 -05:00
|
|
|
fprintf(stderr, "[ParticleEmitter] Unknown shape\n");
|
|
|
|
return;
|
2011-01-05 15:57:05 -05:00
|
|
|
}
|
2011-01-05 15:54:36 -05:00
|
|
|
}
|
|
|
|
|
2011-01-04 17:14:51 -05:00
|
|
|
m_emitter->setMinStartSize(core::dimension2df(minSize, minSize));
|
|
|
|
m_emitter->setMaxStartSize(core::dimension2df(maxSize, maxSize));
|
2009-06-10 09:04:30 -04:00
|
|
|
m_node->setEmitter(m_emitter); // this grabs the emitter
|
2009-08-16 20:24:47 -04:00
|
|
|
m_emitter->drop(); // so we can drop our references
|
2011-01-04 17:14:51 -05:00
|
|
|
|
2011-01-04 20:39:18 -05:00
|
|
|
// FIXME: this is ridiculous, the fadeout time should be equal to the lifetime, except that the
|
|
|
|
// lifetime is random...
|
2011-01-05 20:01:12 -05:00
|
|
|
scene::IParticleFadeOutAffector *af = m_node->createFadeOutParticleAffector(video::SColor(0, 255, 255, 255),
|
2011-01-04 20:39:18 -05:00
|
|
|
type->getFadeoutTime());
|
2009-06-10 09:04:30 -04:00
|
|
|
m_node->addAffector(af);
|
|
|
|
af->drop();
|
2011-01-04 17:14:51 -05:00
|
|
|
|
2009-01-09 15:40:07 -05:00
|
|
|
} // KartParticleSystem
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
2009-06-02 08:06:35 -04:00
|
|
|
/** Destructor, removes
|
|
|
|
*/
|
2011-01-04 17:14:51 -05:00
|
|
|
ParticleEmitter::~ParticleEmitter()
|
2009-01-09 15:40:07 -05:00
|
|
|
{
|
2009-06-10 09:04:30 -04:00
|
|
|
irr_driver->removeNode(m_node);
|
2011-01-04 17:14:51 -05:00
|
|
|
} // ~ParticleEmitter
|
2009-06-02 08:06:35 -04:00
|
|
|
|
2009-01-09 15:40:07 -05:00
|
|
|
//-----------------------------------------------------------------------------
|
2011-01-04 17:14:51 -05:00
|
|
|
void ParticleEmitter::update()
|
2009-01-09 15:40:07 -05:00
|
|
|
{
|
2009-06-02 20:39:20 -04:00
|
|
|
// No particles to emit, no need to change the speed
|
2011-01-04 17:14:51 -05:00
|
|
|
if (m_emitter->getMinParticlesPerSecond() == 0) return;
|
2011-01-05 20:25:46 -05:00
|
|
|
|
2009-06-02 20:39:20 -04:00
|
|
|
// There seems to be no way to randomise the velocity for particles,
|
|
|
|
// so we have to do this manually, by changing the default velocity.
|
|
|
|
// Irrlicht expects velocity (called 'direction') in m/ms!!
|
2011-01-05 21:37:55 -05:00
|
|
|
/*
|
2011-01-05 20:58:45 -05:00
|
|
|
const int x = m_particle_type->getAngleSpreadX();
|
|
|
|
const int y = m_particle_type->getAngleSpreadY();
|
|
|
|
const int z = m_particle_type->getAngleSpreadZ();
|
|
|
|
Vec3 dir(cos(DEGREE_TO_RAD*(rand()%x - x/2))*m_particle_type->getVelocityX(),
|
|
|
|
sin(DEGREE_TO_RAD*(rand()%y - x/2))*m_particle_type->getVelocityY(),
|
|
|
|
sin(DEGREE_TO_RAD*(rand()%z - x/2))*m_particle_type->getVelocityZ());
|
2009-06-10 09:04:30 -04:00
|
|
|
m_emitter->setDirection(dir.toIrrVector());
|
2011-01-05 21:37:55 -05:00
|
|
|
*/
|
2009-01-09 15:40:07 -05:00
|
|
|
} // update
|
2009-06-10 09:04:30 -04:00
|
|
|
|
2009-01-09 15:40:07 -05:00
|
|
|
//-----------------------------------------------------------------------------
|
2011-01-04 17:14:51 -05:00
|
|
|
|
|
|
|
void ParticleEmitter::setCreationRate(float f)
|
2009-01-09 15:40:07 -05:00
|
|
|
{
|
2009-06-10 09:04:30 -04:00
|
|
|
m_emitter->setMinParticlesPerSecond(int(f));
|
|
|
|
m_emitter->setMaxParticlesPerSecond(int(f));
|
2009-06-02 08:06:35 -04:00
|
|
|
} // setCreationRate
|
2011-01-04 17:14:51 -05:00
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
void ParticleEmitter::setPosition(core::vector3df pos)
|
|
|
|
{
|
|
|
|
m_node->setPosition(pos);
|
|
|
|
}
|