From a2ee9cca487d735bd1b676d89fd5bcab114f040b Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Sun, 31 May 2009 18:42:55 +0100 Subject: [PATCH] Depth sort smoke particles --- include/IBillboard.hpp | 4 ++++ include/IRollingStock.hpp | 12 ++-------- include/Maths.hpp | 4 ++-- src/Billboard.cpp | 5 ++++ src/Engine.cpp | 11 ++------- src/SmokeTrail.cpp | 49 ++++++++++++++++++++++++++++----------- src/Train.cpp | 8 +++---- src/Waggon.cpp | 5 ++-- 8 files changed, 56 insertions(+), 42 deletions(-) diff --git a/include/IBillboard.hpp b/include/IBillboard.hpp index c2a0d5f..4b73944 100644 --- a/include/IBillboard.hpp +++ b/include/IBillboard.hpp @@ -42,4 +42,8 @@ IBillboardPtr makeSphericalBillboard(ITexturePtr aTexture); // in the correct orientation void setBillboardCameraOrigin(Vector aPosition); +// Billboards normally need to be depth sorted +// This calculates the distance of a point to the camera +float distanceToCamera(Vector aPosition); + #endif diff --git a/include/IRollingStock.hpp b/include/IRollingStock.hpp index 96dd33b..366b7d8 100644 --- a/include/IRollingStock.hpp +++ b/include/IRollingStock.hpp @@ -30,16 +30,8 @@ struct IRollingStock { // Update speed, fuel, etc. virtual void update(int aDelta) = 0; - // Display the base object - // This should also display any animation that is attached to - // the model - // Animation that is not attached to the model should use - // `renderEffects' below - virtual void renderModel() const = 0; - - // Display any effects that should occur with absolute - // co-ordinates (like smoke trails) - virtual void renderEffects() const = 0; + // Display the model + virtual void render() const = 0; // Return the controller for this vehicle (if it has one) virtual IControllerPtr controller() = 0; diff --git a/include/Maths.hpp b/include/Maths.hpp index 612b118..60e92ff 100644 --- a/include/Maths.hpp +++ b/include/Maths.hpp @@ -54,14 +54,14 @@ struct Vector { } // Magnitude - T magnitude() const + T length() const { return static_cast(sqrt(x*x + y*y + z*z)); } Vector& normalise() { - T m = magnitude(); + T m = length(); x /= m; y /= m; z /= m; diff --git a/src/Billboard.cpp b/src/Billboard.cpp index 4000be7..324f7bd 100644 --- a/src/Billboard.cpp +++ b/src/Billboard.cpp @@ -232,3 +232,8 @@ void setBillboardCameraOrigin(Vector aPosition) { theCameraPosition = aPosition; } + +float distanceToCamera(Vector aPosition) +{ + return (theCameraPosition - aPosition).length(); +} diff --git a/src/Engine.cpp b/src/Engine.cpp index 8c0a678..ba4a729 100644 --- a/src/Engine.cpp +++ b/src/Engine.cpp @@ -62,8 +62,7 @@ public: Engine(); // IRollingStock interface - void renderModel() const; - void renderEffects() const; + void render() const; void update(int aDelta); double speed() const { return mySpeed; } @@ -113,17 +112,11 @@ Engine::Engine() } // Draw the engine model -void Engine::renderModel() const +void Engine::render() const { myModel->render(); } -// Draw the smoke effects -void Engine::renderEffects() const -{ - -} - // Calculate the current tractive effort double Engine::tractiveEffort() const { diff --git a/src/SmokeTrail.cpp b/src/SmokeTrail.cpp index 83103ab..1ff2476 100644 --- a/src/SmokeTrail.cpp +++ b/src/SmokeTrail.cpp @@ -35,16 +35,17 @@ public: 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; float scale; }; - - list myParticles; + +private: + void newParticle(); + void moveParticle(Particle& aParticle, int aDelta); + + mutable list myParticles; // Need to sort particles in render() float myX, myY, myZ; IBillboardPtr myBillboard; @@ -60,8 +61,24 @@ SmokeTrail::SmokeTrail() myBillboard = makeSphericalBillboard(particle); } +void SmokeTrail::moveParticle(Particle& aParticle, int aDelta) +{ + const float ySpeed = 0.1f; + const float growth = 0.1f; + + const float time = static_cast(aDelta) / 1000.0f; + + aParticle.y += ySpeed * time; + aParticle.scale += growth * time; +} + void SmokeTrail::update(int aDelta) { + // Move the existing particles + for (list::iterator it = myParticles.begin(); + it != myParticles.end(); ++it) + moveParticle(*it, aDelta); + mySpawnCounter -= aDelta; if (mySpawnCounter <= 0) { @@ -69,26 +86,32 @@ void SmokeTrail::update(int aDelta) newParticle(); mySpawnCounter = mySpawnDelay; - } + } } void SmokeTrail::newParticle() { Particle p = { - // Position - myX, myY, myZ, - - // Scale - 0.1f, + myX, myY, myZ, // Position + 0.1f, // Scale }; - - debug() << makeVector(p.x, p.y, p.z); myParticles.push_back(p); } +struct CmpDistanceToCam { + bool operator()(const SmokeTrail::Particle& lhs, + const SmokeTrail::Particle& rhs) + { + return distanceToCamera(makeVector(lhs.x, lhs.y, lhs.z)) + > distanceToCamera(makeVector(rhs.x, rhs.y, rhs.z)); + } +}; + void SmokeTrail::render() const { + myParticles.sort(CmpDistanceToCam()); + for (list::const_iterator it = myParticles.begin(); it != myParticles.end(); ++it) { myBillboard->setPosition((*it).x, (*it).y, (*it).z); diff --git a/src/Train.cpp b/src/Train.cpp index f394541..fb8399d 100644 --- a/src/Train.cpp +++ b/src/Train.cpp @@ -151,8 +151,8 @@ void Train::updateSmokePosition(int aDelta) e.transformer(e.segmentDelta); - const float smokeOffX = 1.0f; - const float smokeOffY = 1.0f; + const float smokeOffX = 0.63f; + const float smokeOffY = 1.04f; glTranslatef(smokeOffX, smokeOffY, 0.0f); float matrix[16]; @@ -205,11 +205,9 @@ void Train::render() const (*it).transformer((*it).segmentDelta); glTranslatef(0.0f, track::RAIL_HEIGHT, 0.0f); - (*it).vehicle->renderModel(); + (*it).vehicle->render(); glPopMatrix(); - - (*it).vehicle->renderEffects(); } mySmokeTrail->render(); diff --git a/src/Waggon.cpp b/src/Waggon.cpp index 26e4eb0..761fb94 100644 --- a/src/Waggon.cpp +++ b/src/Waggon.cpp @@ -29,8 +29,7 @@ public: ~Waggon() {} void update(int aDelta); - void renderModel() const; - void renderEffects() const {} + void render() const; IControllerPtr controller(); double speed() const { return 0.0; } double length() const { return myModel->dimensions().x; } @@ -52,7 +51,7 @@ void Waggon::update(int aDelta) } -void Waggon::renderModel() const +void Waggon::render() const { myModel->render(); } -- 2.39.2