From 4b39bb7643906e449ec3b78718873cfcb81a2b7f Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Sun, 31 May 2009 17:22:45 +0100 Subject: [PATCH] Render a really simple smoke trail --- include/IRollingStock.hpp | 7 +++++- include/ISmokeTrail.hpp | 6 +++++ src/Engine.cpp | 21 ++++++++++++++--- src/SmokeTrail.cpp | 49 +++++++++++++++++++++++++++++++++++++-- src/Train.cpp | 17 ++++++++++---- src/Waggon.cpp | 5 ++-- 6 files changed, 92 insertions(+), 13 deletions(-) diff --git a/include/IRollingStock.hpp b/include/IRollingStock.hpp index 40105db..c0c2f85 100644 --- a/include/IRollingStock.hpp +++ b/include/IRollingStock.hpp @@ -19,6 +19,7 @@ #define INC_IROLLING_STOCK_HPP #include "IController.hpp" +#include "Maths.hpp" #include @@ -27,11 +28,15 @@ struct IRollingStock { virtual ~IRollingStock() {} // Update speed, fuel, etc. - virtual void update(int aDelta) = 0; + virtual void update(int aDelta, Vector aPosition) = 0; // Display the object and any animiation virtual void render() const = 0; + // Display any effects that should occur with absolute + // co-ordinates (like smoke trails) + virtual void renderEffects() const = 0; + // Return the controller for this vehicle (if it has one) virtual IControllerPtr controller() = 0; diff --git a/include/ISmokeTrail.hpp b/include/ISmokeTrail.hpp index 2b02f99..5b25a8a 100644 --- a/include/ISmokeTrail.hpp +++ b/include/ISmokeTrail.hpp @@ -24,7 +24,13 @@ struct ISmokeTrail { virtual ~ISmokeTrail() {} + // Move and generate new particles + virtual void update(int aDelta) = 0; + + // Draw all the particles virtual void render() const = 0; + + // Change the position where new particles are generated virtual void setPosition(float x, float y, float z) = 0; }; diff --git a/src/Engine.cpp b/src/Engine.cpp index 3f29697..100be20 100644 --- a/src/Engine.cpp +++ b/src/Engine.cpp @@ -19,6 +19,7 @@ #include "IModel.hpp" #include "ILogger.hpp" #include "MovingAverage.hpp" +#include "ISmokeTrail.hpp" using namespace std; @@ -61,7 +62,8 @@ public: // IRollingStock interface void render() const; - void update(int aDelta); + void renderEffects() const; + void update(int aDelta, Vector aPosition); double speed() const { return mySpeed; } IControllerPtr controller() { return shared_from_this(); } @@ -87,6 +89,8 @@ private: // Boiler pressure lags behind temperature MovingAverage myBoilerDelay; + + ISmokeTrailPtr mySmokeTrail; static const double MODEL_SCALE; static const double TRACTIVE_EFFORT_KNEE; @@ -107,14 +111,21 @@ Engine::Engine() isBrakeOn(true), myThrottle(0) { myModel = loadModel("pclass.obj", MODEL_SCALE); + mySmokeTrail = makeSmokeTrail(); } -// Draw the engine, smoke, etc. +// Draw the engine model void Engine::render() const { myModel->render(); } +// Draw the smoke effects +void Engine::renderEffects() const +{ + mySmokeTrail->render(); +} + // Calculate the current tractive effort double Engine::tractiveEffort() const { @@ -142,7 +153,7 @@ double Engine::brakeForce() const } // Compute the next state of the engine -void Engine::update(int aDelta) +void Engine::update(int aDelta, Vector aPosition) { // Update the pressure of the boiler // The fire temperature is delayed and then used to increase it @@ -165,6 +176,10 @@ void Engine::update(int aDelta) << ", B=" << B << ", a=" << a << ", v=" << mySpeed << " (delta=" << aDelta << ")";*/ + + // Move the smoke trail + mySmokeTrail->setPosition(aPosition.x, aPosition.y + 1.0f, aPosition.z); + mySmokeTrail->update(aDelta); } // User interface to the engine diff --git a/src/SmokeTrail.cpp b/src/SmokeTrail.cpp index 67799ec..11a0bcc 100644 --- a/src/SmokeTrail.cpp +++ b/src/SmokeTrail.cpp @@ -18,6 +18,10 @@ #include "ISmokeTrail.hpp" #include "IBillboard.hpp" +#include "ILogger.hpp" // REMOVE + +#include + using namespace std; // Concrete implementation of smoke trails @@ -29,22 +33,63 @@ public: // ISmokeTrail interface void render() const; void setPosition(float x, float y, float z); + void update(int aDelta); private: + void newParticle(); + + // A single smoke particle + struct Particle { + float x, y, z; + }; + + list myParticles; float myX, myY, myZ; IBillboardPtr myBillboard; + + // New particles are created every `mySpawnDelay` + int mySpawnDelay, mySpawnCounter; }; SmokeTrail::SmokeTrail() - : myX(0.0f), myY(0.0f), myZ(0.0f) + : myX(0.0f), myY(0.0f), myZ(0.0f), + mySpawnDelay(1000), mySpawnCounter(0) { ITexturePtr particle(loadTexture("data/images/smoke_particle.png")); myBillboard = makeSphericalBillboard(particle); } -void SmokeTrail::render() const +void SmokeTrail::update(int aDelta) +{ + mySpawnCounter -= aDelta; + + if (mySpawnCounter <= 0) { + // Generate a new particle + newParticle(); + + mySpawnCounter = mySpawnDelay; + } +} + +void SmokeTrail::newParticle() { + Particle p = { + // Position + myX, myY, myZ + }; + + debug() << makeVector(p.x, p.y, p.z); + myParticles.push_back(p); +} + +void SmokeTrail::render() const +{ + for (list::const_iterator it = myParticles.begin(); + it != myParticles.end(); ++it) { + myBillboard->setPosition((*it).x, (*it).y, (*it).z); + myBillboard->render(); + } } void SmokeTrail::setPosition(float x, float y, float z) diff --git a/src/Train.cpp b/src/Train.cpp index 2174ea1..0dee3fb 100644 --- a/src/Train.cpp +++ b/src/Train.cpp @@ -63,6 +63,7 @@ private: Part& engine(); void move(double aDistance); void addPart(IRollingStockPtr aVehicle); + Vector partPosition(const Part& aPart) const; IMapPtr myMap; @@ -141,7 +142,7 @@ void Train::update(int aDelta) { for (list::iterator it = myParts.begin(); it != myParts.end(); ++it) - (*it).vehicle->update(aDelta); + (*it).vehicle->update(aDelta, partPosition(*it)); // How many metres does a tile correspond to? const double M_PER_UNIT = 5.0; @@ -179,18 +180,24 @@ void Train::render() const (*it).vehicle->render(); glPopMatrix(); + + (*it).vehicle->renderEffects(); } } Vector Train::front() const { - // Call the transformer to compute the world location of - // the front of the train + return partPosition(engine()); +} + +// Calculate the position of any train part +Vector Train::partPosition(const Part& aPart) const +{ + // Call the transformer to compute the world location glPushMatrix(); glLoadIdentity(); - const Part& e = engine(); - e.transformer(e.segmentDelta); + aPart.transformer(aPart.segmentDelta); float matrix[16]; glGetFloatv(GL_MODELVIEW_MATRIX, matrix); diff --git a/src/Waggon.cpp b/src/Waggon.cpp index 761fb94..cae3254 100644 --- a/src/Waggon.cpp +++ b/src/Waggon.cpp @@ -28,8 +28,9 @@ public: Waggon(); ~Waggon() {} - void update(int aDelta); + void update(int aDelta, Vector aPosition); void render() const; + void renderEffects() const {} IControllerPtr controller(); double speed() const { return 0.0; } double length() const { return myModel->dimensions().x; } @@ -46,7 +47,7 @@ Waggon::Waggon() myModel = loadModel("coal_truck.obj", MODEL_SCALE); } -void Waggon::update(int aDelta) +void Waggon::update(int aDelta, Vector aPosition) { } -- 2.39.2