void ParticleEmitter::setParticleType(const ParticleKind* type) { assert(m_magic_number == 0x58781325); bool is_new_type = (m_particle_type != type); if (is_new_type) { if (m_node != NULL) { m_node->removeAll(); m_node->removeAllAffectors(); m_emitter->drop(); } else { if (m_is_glsl) m_node = ParticleSystemProxy::addParticleNode(m_is_glsl, type->randomizeInitialY()); else m_node = irr_driver->addParticleNode(); if (m_is_glsl) { bool additive = (type->getMaterial()->getShaderType() == Material::SHADERTYPE_ADDITIVE); static_cast<ParticleSystemProxy *>(m_node)->setAlphaAdditive(additive); } } if (m_parent != NULL) { m_node->setParent(m_parent); } m_particle_type = type; } m_emission_decay_rate = type->getEmissionDecayRate(); 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(maxSize >= minSize); assert(lifeTimeMax >= lifeTimeMin); #ifdef DEBUG if (material != NULL) { video::ITexture* tex = material->getTexture(); assert(tex != NULL); const io::SNamedPath& name = tex->getName(); const io::path& tpath = name.getPath(); std::string debug_name = std::string("particles(") + tpath.c_str() + ")"; m_node->setName(debug_name.c_str()); } #endif m_min_rate = (float)type->getMinRate(); m_max_rate = (float)type->getMaxRate(); if (is_new_type) { video::SMaterial& mat0 = m_node->getMaterial(0); m_node->setPosition(m_position.toIrrVector()); if (material != NULL) { assert(material->getTexture() != NULL); material->setMaterialProperties(&mat0, NULL); m_node->setMaterialTexture(0, material->getTexture()); mat0.ZWriteEnable = !material->isTransparent(); // disable z-buffer writes if material is transparent // fallback for old render engine if (material->getShaderType() == Material::SHADERTYPE_ADDITIVE) mat0.MaterialType = video::EMT_TRANSPARENT_ADD_COLOR; else if (material->getShaderType() == Material::SHADERTYPE_ALPHA_BLEND) mat0.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL; else if (material->getShaderType() == Material::SHADERTYPE_ALPHA_TEST) mat0.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF; } else { std::string help = file_manager->getAsset(FileManager::GUI, "main_help.png"); m_node->setMaterialTexture(0, irr_driver->getTexture(help)); } // velocity in m/ms core::vector3df velocity(m_particle_type->getVelocityX(), m_particle_type->getVelocityY(), m_particle_type->getVelocityZ()); switch (type->getShape()) { case EMITTER_POINT: { m_emitter = m_node->createPointEmitter(velocity, type->getMinRate(), type->getMaxRate(), type->getMinColor(), type->getMinColor(), 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; m_emitter = m_node->createBoxEmitter(core::aabbox3df(-box_size_x, -box_size_y, -0.6f, box_size_x, box_size_y, -0.6f - type->getBoxSizeZ()), velocity, type->getMinRate(), type->getMaxRate(), type->getMinColor(), type->getMinColor(), lifeTimeMin, lifeTimeMax, m_particle_type->getAngleSpread() ); #if VISUALIZE_BOX_EMITTER if (m_parent != NULL) { for (int x=0; x<2; x++) { for (int y=0; y<2; y++) { for (int z=0; z<2; z++) { m_visualisation.push_back( irr_driver->getSceneManager()->addSphereSceneNode(0.05f, 16, m_parent, -1, core::vector3df((x ? box_size_x : -box_size_x), (y ? box_size_y : -box_size_y), -0.6 - (z ? 0 : type->getBoxSizeZ()))) ); } } } } #endif break; } case EMITTER_SPHERE: { m_emitter = m_node->createSphereEmitter(core::vector3df(0.0f,0.0f,0.0f) /* center */, m_particle_type->getSphereRadius(), velocity, type->getMinRate(), type->getMaxRate(), type->getMinColor(), type->getMinColor(), lifeTimeMin, lifeTimeMax, m_particle_type->getAngleSpread() ); break; } default: { Log::error("ParticleEmitter", "Unknown shape"); return; } } } else { m_emitter->setMinParticlesPerSecond(int(m_min_rate)); m_emitter->setMaxParticlesPerSecond(int(m_max_rate)); } m_emitter->setMinStartSize(core::dimension2df(minSize, minSize)); m_emitter->setMaxStartSize(core::dimension2df(maxSize, maxSize)); if (is_new_type) { m_node->setEmitter(m_emitter); // this grabs the emitter scene::IParticleFadeOutAffector *af = m_node->createFadeOutParticleAffector(video::SColor(0, 255, 255, 255), type->getFadeoutTime()); m_node->addAffector(af); af->drop(); if (type->getGravityStrength() != 0) { scene::IParticleGravityAffector *gaf = m_node->createGravityAffector(core::vector3df(00.0f, type->getGravityStrength(), 0.0f), type->getForceLostToGravityTime()); m_node->addAffector(gaf); gaf->drop(); } const float fas = type->getFadeAwayStart(); const float fae = type->getFadeAwayEnd(); if (fas > 0.0f && fae > 0.0f) { FadeAwayAffector* faa = new FadeAwayAffector(fas*fas, fae*fae); m_node->addAffector(faa); faa->drop(); } if (type->hasScaleAffector()) { if (m_is_glsl) { static_cast<ParticleSystemProxy *>(m_node)->setIncreaseFactor(type->getScaleAffectorFactorX()); } else { core::vector2df factor = core::vector2df(type->getScaleAffectorFactorX(), type->getScaleAffectorFactorY()); scene::IParticleAffector* scale_affector = new ScaleAffector(factor); m_node->addAffector(scale_affector); scale_affector->drop(); } } if (type->getMinColor() != type->getMaxColor()) { if (m_is_glsl) { video::SColor color_from = type->getMinColor(); static_cast<ParticleSystemProxy *>(m_node)->setColorFrom(color_from.getRed() / 255.0f, color_from.getGreen() / 255.0f, color_from.getBlue() / 255.0f); video::SColor color_to = type->getMaxColor(); static_cast<ParticleSystemProxy *>(m_node)->setColorTo(color_to.getRed() / 255.0f, color_to.getGreen() / 255.0f, color_to.getBlue() / 255.0f); } else { video::SColor color_from = type->getMinColor(); core::vector3df color_from_v = core::vector3df(float(color_from.getRed()), float(color_from.getGreen()), float(color_from.getBlue())); video::SColor color_to = type->getMaxColor(); core::vector3df color_to_v = core::vector3df(float(color_to.getRed()), float(color_to.getGreen()), float(color_to.getBlue())); ColorAffector* affector = new ColorAffector(color_from_v, color_to_v); m_node->addAffector(affector); affector->drop(); } } const float windspeed = type->getWindSpeed(); if (windspeed > 0.01f) { WindAffector *waf = new WindAffector(windspeed); m_node->addAffector(waf); waf->drop(); // TODO: wind affector for GLSL particles } const bool flips = type->getFlips(); if (flips) { if (m_is_glsl) static_cast<ParticleSystemProxy *>(m_node)->setFlip(); } } } // setParticleType
void ParticleEmitter::setParticleType(const ParticleKind* type) { assert(m_magic_number == 0x58781325); bool is_new_type = (m_particle_type != type); if (is_new_type) { if (m_node != NULL) { m_node->removeAll(); m_node->removeAllAffectors(); m_emitter->drop(); } else { m_node = irr_driver->addParticleNode(); } if (m_parent != NULL) { m_node->setParent(m_parent); } m_particle_type = type; } m_emission_decay_rate = type->getEmissionDecayRate(); 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(maxSize >= minSize); assert(lifeTimeMax >= lifeTimeMin); #ifdef DEBUG if (material != NULL) { video::ITexture* tex = material->getTexture(); assert(tex != NULL); const io::SNamedPath& name = tex->getName(); const io::path& tpath = name.getPath(); std::string debug_name = std::string("particles(") + tpath.c_str() + ")"; m_node->setName(debug_name.c_str()); } #endif m_min_rate = (float)type->getMinRate(); m_max_rate = (float)type->getMaxRate(); if (is_new_type) { video::SMaterial& mat0 = m_node->getMaterial(0); m_node->setPosition(m_position.toIrrVector()); if (material != NULL) { assert(material->getTexture() != NULL); material->setMaterialProperties(&mat0, NULL); m_node->setMaterialTexture(0, material->getTexture()); mat0.ZWriteEnable = !material->isTransparent(); // disable z-buffer writes if material is transparent } else { m_node->setMaterialTexture(0, irr_driver->getTexture((file_manager->getDataDir() + "/gui/main_help.png").c_str())); } 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; m_emitter = m_node->createBoxEmitter(core::aabbox3df(-box_size_x, -box_size_y, -0.6f, box_size_x, box_size_y, -0.6f - type->getBoxSizeZ()), 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 */ ); #if VISUALIZE_BOX_EMITTER if (m_parent != NULL) { for (int x=0; x<2; x++) { for (int y=0; y<2; y++) { for (int z=0; z<2; z++) { m_visualisation.push_back( irr_driver->getSceneManager()->addSphereSceneNode(0.05f, 16, m_parent, -1, core::vector3df((x ? box_size_x : -box_size_x), (y ? box_size_y : -box_size_y), -0.6 - (z ? 0 : type->getBoxSizeZ()))) ); } } } } #endif break; } default: { fprintf(stderr, "[ParticleEmitter] Unknown shape\n"); return; } } } else { m_emitter->setMinParticlesPerSecond(int(m_min_rate)); m_emitter->setMaxParticlesPerSecond(int(m_max_rate)); } m_emitter->setMinStartSize(core::dimension2df(minSize, minSize)); m_emitter->setMaxStartSize(core::dimension2df(maxSize, maxSize)); if (is_new_type) { m_node->setEmitter(m_emitter); // this grabs the emitter scene::IParticleFadeOutAffector *af = m_node->createFadeOutParticleAffector(video::SColor(0, 255, 255, 255), type->getFadeoutTime()); m_node->addAffector(af); af->drop(); if (type->getGravityStrength() != 0) { scene::IParticleGravityAffector *gaf = m_node->createGravityAffector(core::vector3df(00.0f, type->getGravityStrength(), 0.0f), type->getForceLostToGravityTime()); m_node->addAffector(gaf); gaf->drop(); } const float fas = type->getFadeAwayStart(); const float fae = type->getFadeAwayEnd(); if (fas > 0.0f && fae > 0.0f) { FadeAwayAffector* faa = new FadeAwayAffector(fas*fas, fae*fae); m_node->addAffector(faa); faa->drop(); } } } // setParticleType