| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481 |
- /*
- Copyright (C) 2011 by Ivan Safrin
-
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
-
- The above copyright notice and this permission notice shall be included in
- all copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- THE SOFTWARE.
- */
- #include "PolyParticleEmitter.h"
- #include "PolyCoreServices.h"
- #include "PolyParticle.h"
- #include "PolyPerlin.h"
- #include "PolyResource.h"
- #include "PolyScene.h"
- #include "PolyTimer.h"
- #include "PolyMaterialManager.h"
- #include "PolyResourceManager.h"
- #include "PolyRenderer.h"
- using namespace Polycode;
- SceneParticleEmitter::SceneParticleEmitter(const String& materialName, int particleType, int emitterType, Number lifespan, unsigned int numParticles, Vector3 direction, Vector3 gravity, Vector3 deviation, Vector3 emitterRadius, Mesh *particleMesh, SceneMesh *emitter)
- : Entity(),
- ParticleEmitter(materialName, particleMesh, particleType, emitterType, lifespan, numParticles, direction, gravity, deviation, emitterRadius)
- {
- isScreenEmitter = false;
- emitterMesh = emitter;
- createParticles();
-
- }
- SceneParticleEmitter::~SceneParticleEmitter() {
-
- }
- void SceneParticleEmitter::respawnSceneParticles() {
- for(int i=0; i < particles.size(); i++) {
- Particle *particle = particles[i];
- removeChild((Entity*)particle->particleBody);
- addParticleBody(particle->particleBody);
- resetParticle(particle);
- particle->life = lifespan * ((Number)rand()/RAND_MAX);
- }
- updateEmitter();
- }
- void SceneParticleEmitter::addParticleBody(Entity *particleBody) {
- addChild((Entity*)particleBody);
- particleBody->editorOnly = true;
- }
- void SceneParticleEmitter::dispatchTriggerCompleteEvent() {
- ((EventDispatcher*)this)->dispatchEvent(new Event(Event::COMPLETE_EVENT), Event::COMPLETE_EVENT);
- }
- Matrix4 SceneParticleEmitter::getBaseMatrix() {
- rebuildTransformMatrix();
- return getConcatenatedMatrix();
- }
- void SceneParticleEmitter::Update() {
- updateEmitter();
- }
- ParticleEmitter::ParticleEmitter(const String& imageFile, Mesh *particleMesh, int particleType, int emitterType, Number lifespan, unsigned int numParticles, Vector3 direction, Vector3 gravity, Vector3 deviation, Vector3 emitterRadius) {
-
- this->emitterRadius = emitterRadius;
- isScreenEmitter = false;
- dirVector = direction;
- gravVector = gravity;
- ignoreParentMatrix = false;
- this->emitterType = emitterType;
- // TODO: initialize emitSpeed
- this->deviation = deviation;
- pMesh = particleMesh;
- rotationFollowsPath = false;
- rotationSpeed = 100.0f;
- perlinEnabled = false;
- emitterRadius = Vector3(0.0f,0.0f,0.0f);
- perlinModSize = 0.002;
- brightnessDeviation = 0.0f;
- particleSpeedMod = 1.0f;
- isEmitterEnabled = true;
- allAtOnce = false;
-
- blendingMode = Renderer::BLEND_MODE_NORMAL;
-
- particleSize = 1.0;
-
- scaleCurve.addControlPoint2dWithHandles(-0.1, 0.5, 0.0, 0.5, 0.1, 0.5);
- scaleCurve.addControlPoint2dWithHandles(0.9, 0.5, 1.0, 0.5, 1.1, 0.5);
- colorCurveR.addControlPoint2dWithHandles(-0.1, 0.5, 0.0, 0.5, 0.1, 0.5);
- colorCurveR.addControlPoint2dWithHandles(0.9, 0.5, 1.0, 0.5, 1.1, 0.5);
- colorCurveG.addControlPoint2dWithHandles(-0.1, 0.5, 0.0, 0.5, 0.1, 0.5);
- colorCurveG.addControlPoint2dWithHandles(0.9, 0.5, 1.0, 0.5, 1.1, 0.5);
- colorCurveB.addControlPoint2dWithHandles(-0.1, 0.5, 0.0, 0.5, 0.1, 0.5);
- colorCurveB.addControlPoint2dWithHandles(0.9, 0.5, 1.0, 0.5, 1.1, 0.5);
- colorCurveA.addControlPoint2dWithHandles(-0.1, 0.5, 0.0, 0.5, 0.1, 0.5);
- colorCurveA.addControlPoint2dWithHandles(0.9, 0.5, 1.0, 0.5, 1.1, 0.5);
-
-
- this->particleType = particleType;
-
- this->numParticles = numParticles;
- this->lifespan = lifespan;
- timer = new Timer(true, 1);
- motionPerlin = new Perlin(3,5,1.0,rand());
-
- textureFile = imageFile;
-
- useColorCurves = false;
- useScaleCurves = false;
- }
- bool ParticleEmitter::getIgnoreParentMatrix() const {
- return ignoreParentMatrix;
- }
- void ParticleEmitter::setIgnoreParentMatrix(bool val) {
- ignoreParentMatrix = val;
- for(int i=0; i < particles.size(); i++) {
- particles[i]->particleBody->ignoreParentMatrix = ignoreParentMatrix;
- }
- }
- Texture *ParticleEmitter::getParticleTexture() const {
- return particleTexture;
- }
-
- void ParticleEmitter::createParticles() {
-
- if(isScreenEmitter)
- particleTexture = CoreServices::getInstance()->getMaterialManager()->createTextureFromFile(textureFile);
- else
- particleMaterial = (Material*)CoreServices::getInstance()->getResourceManager()->getResource(Resource::RESOURCE_MATERIAL, textureFile);
-
-
- Particle *particle;
- for(int i=0; i < numParticles; i++) {
- particle = new Particle(particleType, isScreenEmitter, particleMaterial, particleTexture, pMesh);
- particle->particleBody->ignoreParentMatrix = ignoreParentMatrix;
- particle->velVector = dirVector;
- particle->dirVector = dirVector;
- particle->deviation = deviation;
- particle->lifespan = lifespan;
- particles.push_back(particle);
- addParticleBody(particle->particleBody);
- resetParticle(particle);
- particle->life = lifespan * ((Number)rand()/RAND_MAX);
- }
- updateEmitter();
- }
- void ParticleEmitter::dispatchTriggerCompleteEvent() {
- }
- void ParticleEmitter::addParticleBody(Entity *particleBody) {
- }
-
- Matrix4 ParticleEmitter::getBaseMatrix() {
- return Matrix4();
- }
-
- void ParticleEmitter::setEmitterRadius(Vector3 rad) {
- emitterRadius = rad;
- }
- void ParticleEmitter::setRotationSpeed(Number speed) {
- rotationSpeed = speed;
- }
- void ParticleEmitter::setParticleVisibility(bool val) {
- for(int i=0;i < particles.size(); i++) {
- particles[i]->particleBody->visible = val;
- }
- }
- void ParticleEmitter::setParticleBlendingMode(int mode) {
- blendingMode = mode;
- for(int i=0;i < particles.size(); i++) {
- particles[i]->particleBody->setBlendingMode(mode);
- }
- }
- int ParticleEmitter::getParticleBlendingMode() const {
- return blendingMode;
- }
- void ParticleEmitter::setAlphaTest(bool val) {
- for(int i=0;i < particles.size(); i++) {
- particles[i]->particleBody->alphaTest = val;
- }
- }
- void ParticleEmitter::setDepthWrite(bool val) {
- for(int i=0;i < particles.size(); i++) {
- particles[i]->particleBody->depthWrite = val;
- }
- }
- void ParticleEmitter::setDepthTest(bool val) {
- for(int i=0;i < particles.size(); i++) {
- particles[i]->particleBody->depthTest= val;
- }
- }
- void ParticleEmitter::setBillboardMode(bool mode) {
- for(int i=0;i < particles.size(); i++) {
- particles[i]->particleBody->billboardMode = mode;
- }
- }
- void ParticleEmitter::enablePerlin(bool val) {
- perlinEnabled = val;
- }
- ParticleEmitter::~ParticleEmitter() {
-
- }
- void ParticleEmitter::setParticleCount(int count) {
- if(count > particles.size()) {
- int oldSize = count-particles.size();
- Particle *particle;
- for(int i=0; i < oldSize; i++) {
- particle = new Particle(particleType, isScreenEmitter, particleMaterial, particleTexture, pMesh);
- particle->particleBody->ignoreParentMatrix = ignoreParentMatrix;
- particle->velVector = dirVector;
- particle->dirVector = dirVector;
- particle->deviation = deviation;
- particle->lifespan = lifespan;
- particle->life = lifespan * ((Number)rand()/RAND_MAX);
- particles.push_back(particle);
- addParticleBody(particle->particleBody);
- }
- }
- numParticles = count;
- for(int i=0; i < particles.size(); i++) {
- if(i < numParticles)
- particles[i]->particleBody->visible =true;
- else
- particles[i]->particleBody->visible = false;
- }
- resetAll();
- }
- void ParticleEmitter::setPerlinModSize(Number size) {
- perlinModSize = size;
- }
- void ParticleEmitter::enableEmitter(bool val) {
- isEmitterEnabled = val;
- if(val) {
- for(int i=0;i < numParticles; i++) {
- particles[i]->life = particles[i]->lifespan * ((Number)rand()/RAND_MAX);
- }
- }
- }
- void ParticleEmitter::Trigger() {
- if(!isEmitterEnabled)
- return;
- for(int i=0;i < numParticles; i++) {
- resetParticle(particles[i]);
- }
- }
- bool ParticleEmitter::emitterEnabled() {
- return isEmitterEnabled;
- }
- void ParticleEmitter::resetParticle(Particle *particle) {
- // particle->particleBody->visible = true;
- particle->lifespan = lifespan;
- Matrix4 concatMatrix = getBaseMatrix();
-
- Vector3 startVector;
-
- Vector3 compoundScale(1.0, 1.0, 1.0);
- if(ignoreParentMatrix) {
- compoundScale = getParticleCompoundScale();
- }
-
- particle->dirVector = dirVector;
- // if(emitterMesh) {
- // Polygon *randPoly = emitterMesh->getMesh()->getPolygon(rand() % emitterMesh->getMesh()->getPolygonCount());
- // startVector = *randPoly->getVertex(rand() % 3);
- // startVector = emitterMesh->getConcatenatedMatrix() * startVector;
- // } else {
- startVector = Vector3(-(emitterRadius.x/2.0f)+emitterRadius.x*((Number)rand()/RAND_MAX),-(emitterRadius.y/2.0f)+emitterRadius.y*((Number)rand()/RAND_MAX),-(emitterRadius.z/2.0f)+emitterRadius.z*((Number)rand()/RAND_MAX));
- // }
-
-
- particle->Reset(emitterType != TRIGGERED_EMITTER);
- particle->velVector = particle->dirVector;
- Number dev = ((deviation.x/2.0f)*-1.0f) + ((deviation.x)*((Number)rand()/RAND_MAX));
- particle->velVector.x += dev;
- dev = (deviation.y/2.0f*-1.0f) + ((deviation.y)*((Number)rand()/RAND_MAX));
- particle->velVector.y += dev;
- dev = (deviation.z/2.0f*-1.0f) + ((deviation.z)*((Number)rand()/RAND_MAX));
- particle->velVector.z += dev;
-
- particle->brightnessDeviation = 1.0f - ( (-brightnessDeviation) + ((brightnessDeviation*2) * ((Number)rand()/RAND_MAX)));
-
- // particle->velVector = concatMatrix.rotateVector(particle->velVector);
- if(ignoreParentMatrix) {
- particle->particleBody->setPosition(concatMatrix.getPosition());
- } else {
- particle->particleBody->setPosition(0.0, 0.0, 0.0);
- }
-
- particle->particleBody->Translate(startVector);
- particle->particleBody->rebuildTransformMatrix();
-
- if(useScaleCurves) {
- particle->particleBody->setScale(scaleCurve.getHeightAt(0) * particleSize * compoundScale.x,
- scaleCurve.getHeightAt(0) * particleSize * compoundScale.y,
- scaleCurve.getHeightAt(0) * particleSize * compoundScale.z);
- } else {
- particle->particleBody->setScale(particleSize * compoundScale.x, particleSize * compoundScale.y, particleSize * compoundScale.z);
- }
-
- if(useColorCurves) {
- particle->particleBody->color.setColor(colorCurveR.getHeightAt(0),
- colorCurveG.getHeightAt(0),
- colorCurveB.getHeightAt(0),
- colorCurveA.getHeightAt(0));
- } else {
- particle->particleBody->color.setColor(1.0, 1.0, 1.0, 1.0);
- }
-
-
- }
- Vector3 SceneParticleEmitter::getParticleCompoundScale() {
- return getCompoundScale();
- }
- Vector3 ParticleEmitter::getParticleCompoundScale() {
- return Vector3();
- }
-
- void ParticleEmitter::resetAll() {
- for(int i=0;i < particles.size(); i++) {
- if(allAtOnce)
- particles[i]->life = 0;
- else
- particles[i]->life = particles[i]->lifespan * ((Number)rand()/RAND_MAX);
- }
- }
- void ParticleEmitter::setAllAtOnce(bool val) {
- allAtOnce = val;
- resetAll();
- }
- unsigned int ParticleEmitter::getNumParticles() const {
- return numParticles;
- }
- Particle *ParticleEmitter::getParticleAtIndex(unsigned int index) const {
- if(index < particles.size()) {
- return particles[index];
- } else {
- return NULL;
- }
- }
- void ParticleEmitter::updateEmitter() {
-
- Vector3 translationVector;
- Number elapsed = timer->getElapsedf();
-
- Particle *particle;
- Number normLife;
-
- Vector3 compoundScale(1.0, 1.0, 1.0);
- if(ignoreParentMatrix) {
- compoundScale = getParticleCompoundScale();
- }
-
- for(int i=0;i < numParticles; i++) {
- particle = particles[i];
-
- normLife = particle->life / particle->lifespan;
- Vector3 gVec = gravVector;
- particle->life += elapsed;
- particle->velVector -= gVec*elapsed*particleSpeedMod;
- translationVector = particle->velVector;
- translationVector = translationVector*elapsed*particleSpeedMod;
- if(perlinEnabled) {
- translationVector.x += ((perlinModSize * motionPerlin->Get((particle->life/particle->lifespan), particle->perlinPosX))*elapsed*particleSpeedMod);
- translationVector.y += ((perlinModSize * motionPerlin->Get((particle->life/particle->lifespan), particle->perlinPosY))*elapsed*particleSpeedMod);
- translationVector.z += ((perlinModSize * motionPerlin->Get((particle->life/particle->lifespan), particle->perlinPosZ))*elapsed*particleSpeedMod);
- }
-
- if(isScreenEmitter) {
- translationVector.z = 0;
- }
-
- particle->particleBody->Translate(translationVector);
-
-
- if(rotationFollowsPath) {
- if(isScreenEmitter) {
- Number angle = atan2(translationVector.x, translationVector.y);
- particle->particleBody->setRoll(360 - ((angle * TODEGREES)+180));
-
- } else {
- particle->particleBody->lookAt(particle->particleBody->getPosition() + translationVector, Vector3(1,0,0));
- }
- } else {
- if(isScreenEmitter) {
- particle->particleBody->Roll(rotationSpeed*elapsed);
- } else {
- particle->particleBody->Roll(rotationSpeed*elapsed);
- particle->particleBody->Pitch(rotationSpeed*elapsed);
- particle->particleBody->Yaw(rotationSpeed*elapsed);
- }
- }
-
- // if(isScreenEmitter)
- // particle->particleBody->setPositionZ(0);
-
- if(useColorCurves) {
- particle->particleBody->color.setColor(colorCurveR.getHeightAt(normLife)*particle->brightnessDeviation,
- colorCurveG.getHeightAt(normLife)*particle->brightnessDeviation,
- colorCurveB.getHeightAt(normLife)*particle->brightnessDeviation,
- colorCurveA.getHeightAt(normLife)*particle->brightnessDeviation);
- } else {
- particle->particleBody->color.setColor(particle->brightnessDeviation,
- particle->brightnessDeviation,
- particle->brightnessDeviation,
- 1.0);
- }
-
- if(useScaleCurves) {
- particle->particleBody->setScale(scaleCurve.getHeightAt(normLife) * particleSize * compoundScale.x,
- scaleCurve.getHeightAt(normLife) * particleSize * compoundScale.y,
- scaleCurve.getHeightAt(normLife) * particleSize * compoundScale.z);
-
- } else {
- particle->particleBody->setScale(particleSize*compoundScale.x, particleSize*compoundScale.y, particleSize*compoundScale.z);
- }
-
- if(particle->life > particle->lifespan && isEmitterEnabled) {
- if(emitterType == CONTINUOUS_EMITTER) {
- resetParticle(particle);
- } else {
- // dispatchTriggerCompleteEvent();
- // particle->particleBody->visible = false;
- }
- }
- }
- }
|