From 90b7392e229cc21d0de750e7fa6cd76d731832cd Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Sun, 31 May 2009 21:18:55 +0100 Subject: [PATCH] Tuning of smoke trail --- include/ISmokeTrail.hpp | 3 +++ src/SmokeTrail.cpp | 53 ++++++++++++++++++++++++++++++++--------- src/Train.cpp | 13 ++++++++-- 3 files changed, 56 insertions(+), 13 deletions(-) diff --git a/include/ISmokeTrail.hpp b/include/ISmokeTrail.hpp index 0ca3755..39d4141 100644 --- a/include/ISmokeTrail.hpp +++ b/include/ISmokeTrail.hpp @@ -33,6 +33,9 @@ struct ISmokeTrail { // Change the position where new particles are generated virtual void setPosition(float x, float y, float z) = 0; + // Change the initial velocity of new particles + virtual void setVelocity(float x, float y, float z) = 0; + // Change the rate at which particles are created // Delay is in milliseconds virtual void setDelay(int aDelay) = 0; diff --git a/src/SmokeTrail.cpp b/src/SmokeTrail.cpp index 3df8e47..5b276b5 100644 --- a/src/SmokeTrail.cpp +++ b/src/SmokeTrail.cpp @@ -35,10 +35,12 @@ public: void setPosition(float x, float y, float z); void update(int aDelta); void setDelay(int aDelay) { mySpawnDelay = aDelay; } + void setVelocity(float x, float y, float z); // A single smoke particle struct Particle { float x, y, z; + float xv, yv, zv; float scale; float r, g, b, a; }; @@ -53,11 +55,15 @@ private: // New particles are created every `mySpawnDelay` int mySpawnDelay, mySpawnCounter; + + // Velocity at which the emitter is moving + float myXSpeed, myYSpeed, myZSpeed; }; SmokeTrail::SmokeTrail() : myX(0.0f), myY(0.0f), myZ(0.0f), - mySpawnDelay(500), mySpawnCounter(0) + mySpawnDelay(500), mySpawnCounter(0), + myXSpeed(0.0f), myYSpeed(0.0f), myZSpeed(0.0f) { ITexturePtr particle(loadTexture("data/images/smoke_particle.png")); myBillboard = makeSphericalBillboard(particle); @@ -66,13 +72,23 @@ SmokeTrail::SmokeTrail() // Returns true if the particle is dead bool SmokeTrail::moveParticle(Particle& aParticle, int aDelta) { - const float ySpeed = 0.2f; - const float growth = 0.2f; + const float ySpeed = 0.3f; + const float growth = 0.3f; const float decay = 0.2f; - + const float slowdown = 0.1f; + const float xWind = 0.02f; + const float zWind = 0.01f; + const float time = static_cast(aDelta) / 1000.0f; - aParticle.y += ySpeed * time; + aParticle.x += aParticle.xv + (xWind * time); + aParticle.y += aParticle.yv + (ySpeed * time); + aParticle.z += aParticle.zv + (zWind * time); + + aParticle.xv = max(aParticle.xv - (slowdown * time), 0.0f); + aParticle.yv = max(aParticle.yv - (slowdown * time), 0.0f); + aParticle.zv = max(aParticle.zv - (slowdown * time), 0.0f); + aParticle.scale += growth * time; // Kill the particle if it becomes invisible @@ -101,15 +117,23 @@ void SmokeTrail::newParticle() { // Random number generator for colour variance static variate_generator > - colourRand(mt19937(time(NULL)), normal_distribution<>(0.0f, 0.05f)); + colourRand(mt19937(time(NULL)), normal_distribution<>(0.0f, 0.06f)); - const float col = 0.8f + colourRand(); + // Random number generator for position variance + static variate_generator > + posRand(mt19937(time(NULL)), normal_distribution<>(0.0f, 0.05f)); + + const float col = 0.75f + colourRand(); + + const float dx = posRand(); + const float dz = posRand(); Particle p = { - myX, myY, myZ, // Position - 0.2f, // Scale - col, col, col, // Colour - 0.9f, // Alpha + myX + dx, myY, myZ + dz, // Position + myXSpeed, myYSpeed, myZSpeed, // Speed + 0.2f, // Scale + col, col, col, // Colour + 0.8f, // Alpha }; myParticles.push_back(p); @@ -144,6 +168,13 @@ void SmokeTrail::setPosition(float x, float y, float z) myZ = z; } +void SmokeTrail::setVelocity(float x, float y, float z) +{ + myXSpeed = x; + myYSpeed = y; + myZSpeed = z; +} + ISmokeTrailPtr makeSmokeTrail() { return ISmokeTrailPtr(new SmokeTrail); diff --git a/src/Train.cpp b/src/Train.cpp index f5569f8..aa23bd7 100644 --- a/src/Train.cpp +++ b/src/Train.cpp @@ -69,6 +69,8 @@ private: IMapPtr myMap; ISmokeTrailPtr mySmokeTrail; + + Vector myVelocityVector; // Move part of the train across a connection void enterSegment(Part& aPart, const track::Connection& aConnection); @@ -80,7 +82,7 @@ private: const double Train::SEPARATION(0.1); Train::Train(IMapPtr aMap) - : myMap(aMap) + : myMap(aMap), myVelocityVector(makeVector(0.0f, 0.0f, 0.0f)) { myParts.push_front(Part(makeEngine())); @@ -161,6 +163,9 @@ void Train::updateSmokePosition(int aDelta) glPopMatrix(); mySmokeTrail->setPosition(matrix[12], matrix[13], matrix[14]); + mySmokeTrail->setVelocity(myVelocityVector.x, + myVelocityVector.y, + myVelocityVector.z); mySmokeTrail->update(aDelta); // Make the rate at which new particles are created proportional @@ -181,9 +186,13 @@ void Train::update(int aDelta) // How many metres does a tile correspond to? const double M_PER_UNIT = 5.0; + + const Vector oldPos = partPosition(engine()); const double deltaSeconds = static_cast(aDelta) / 1000.0f; move(engine().vehicle->speed() * deltaSeconds / M_PER_UNIT); + + myVelocityVector = partPosition(engine()) - oldPos; } // Called when the train enters a new segment @@ -231,7 +240,7 @@ Vector Train::partPosition(const Part& aPart) const // Call the transformer to compute the world location glPushMatrix(); glLoadIdentity(); - + aPart.transformer(aPart.segmentDelta); float matrix[16]; -- 2.39.2