From 2cff908a2cba23c0f15155e813b93450711682d9 Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Sun, 31 May 2009 16:50:14 +0100 Subject: [PATCH] Add stub smoke trail implementation Also forgot some files last commit --- data/images/smoke_particle.png | Bin 0 -> 900 bytes include/IBillboard.hpp | 44 +++++++ include/ISmokeTrail.hpp | 35 +++++ src/Billboard.cpp | 225 +++++++++++++++++++++++++++++++++ src/SmokeTrail.cpp | 60 +++++++++ src/Train.cpp | 12 -- 6 files changed, 364 insertions(+), 12 deletions(-) create mode 100644 data/images/smoke_particle.png create mode 100644 include/IBillboard.hpp create mode 100644 include/ISmokeTrail.hpp create mode 100644 src/Billboard.cpp create mode 100644 src/SmokeTrail.cpp diff --git a/data/images/smoke_particle.png b/data/images/smoke_particle.png new file mode 100644 index 0000000000000000000000000000000000000000..14109fcbfcc54ae63f8ee059a9282637ed16ce57 GIT binary patch literal 900 zcmV-~1AF|5P)Px#24YJ`L;wH)0002_L%V+f000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iXN5 z4k|O_TCd6g000?uMObu0Z*6U5Zgc=ca%Ew3Wn>_CX>@2HM@dakSAh-}0008tNklSaL?H@g0lzyzxy$>%e@e}si*uh5jg=GfLZgF0rxUUg%03%=mjFeK-y#%0z_w?1> zQS>?(BVY&&s{)}a7TyC|HK*;^K&S$QdSs5j2HpZ^Paxa{;u~-UOm?ji>JeTy!n+lQ z`Yx&Q3%CS+R$U*8#P>zyyNKM${@8C3`6wdC+v<6-t$5%wkUpc=U6ulEpdlh(l~T8L zd441!GudDJD zYz+YDKhpuH>fPZDaJ&@&eb6br(Ie{vXGN({6anu&4*jB3Xm11{_i)o997}C`cRy<7L3_K>K!KPpp0a6gUbPKnis8=YqukFp$b$wj(S#*#^)e zd|T3K12~EVfHMM40uO(u&Lmd=V-UZ9U<#p$fHu&K2teC7Jc%s)^J&nG9YAB<`+z9y z0N?;%Zl*aQ7F+0z8Ne(Lz;tEAVmC_>pp=R(0?gm(i7PK+$$uNb7`Tf7z>-cIz%&v7 z(;@(qz|$aO-e|QN0lE;50#Ac6RzHz_5*z^k0tPSuZVQjXN-5KVHVxGKD{XbIXMqcS zPzcSOx>f)L8U;@8mpu($=$k^=5i;PsD5{+RbQE0L1;gXQcU9CxnXJ3f^Hf;t$U*@6 zTyXAjDlC3~Ss!uf8zG$vUp$0h#Q&(Ie>mz!NzWkEBi<7T^@_J3#Mv&d3*$gUGUmff z-VaP1MrJBVi8zO*)_{m-Y_0%Ae1nq(HKN1A=xmdRMhsU&#$t9jw_fAh=. +// + +#ifndef INC_IBILLBOARD_HPP +#define INC_IBILLBOARD_HPP + +#include "ITexture.hpp" +#include "Maths.hpp" + +#include + +// Generic quad billboard with a single texture +struct IBillboard { + virtual ~IBillboard() {} + + virtual void render() const = 0; + + virtual void setPosition(float x, float y, float z) = 0; +}; + +typedef std::shared_ptr IBillboardPtr; + +IBillboardPtr makeCylindricalBillboard(ITexturePtr aTexture); +IBillboardPtr makeSphericalBillboard(ITexturePtr aTexture); + +// This should be called once per frame to render all billboards +// in the correct orientation +void setBillboardCameraOrigin(Vector aPosition); + +#endif diff --git a/include/ISmokeTrail.hpp b/include/ISmokeTrail.hpp new file mode 100644 index 0000000..2b02f99 --- /dev/null +++ b/include/ISmokeTrail.hpp @@ -0,0 +1,35 @@ +// +// Copyright (C) 2009 Nick Gasson +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +#ifndef INC_ISMOKE_TRAIL_HPP +#define INC_ISMOKE_TRAIL_HPP + +#include + +// Smoke and steam effects +struct ISmokeTrail { + virtual ~ISmokeTrail() {} + + virtual void render() const = 0; + virtual void setPosition(float x, float y, float z) = 0; +}; + +typedef std::shared_ptr ISmokeTrailPtr; + +ISmokeTrailPtr makeSmokeTrail(); + +#endif diff --git a/src/Billboard.cpp b/src/Billboard.cpp new file mode 100644 index 0000000..381d9c8 --- /dev/null +++ b/src/Billboard.cpp @@ -0,0 +1,225 @@ +// +// Copyright (C) 2009 Nick Gasson +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +#include "IBillboard.hpp" + +#include + +using namespace std; + +namespace { + Vector theCameraPosition; +} + +// Common functions used by billboards +class BillboardCommon : public IBillboard { +public: + BillboardCommon(ITexturePtr aTexture) + : myTexture(aTexture), + myX(0.0f), myY(0.0f), myZ(0.0f) {} + virtual ~BillboardCommon() {} + + // IBillboard interface + void setPosition(float x, float y, float z); + +private: + const ITexturePtr myTexture; + +protected: + void drawTextureQuad() const; + void translate() const; + + float myX, myY, myZ; +}; + +void BillboardCommon::setPosition(float x, float y, float z) +{ + myX = x; + myY = y; + myZ = z; +} + +void BillboardCommon::translate() const +{ + glTranslatef(myX, myY, myZ); +} + +// Draw the actual quad containing the texture +void BillboardCommon::drawTextureQuad() const +{ + glPushAttrib(GL_ENABLE_BIT); + + glEnable(GL_BLEND); + glEnable(GL_TEXTURE_2D); + glDisable(GL_LIGHTING); + + glColor4f(1.0f, 1.0f, 1.0f, 1.0f); + + myTexture->bind(); + + glBegin(GL_QUADS); + glTexCoord2f(1.0f, 1.0f); + glVertex2f(0.5f, 0.5f); + glTexCoord2f(0.0f, 1.0f); + glVertex2f(-0.5f, 0.5f); + glTexCoord2f(0.0f, 0.0f); + glVertex2f(-0.5f, -0.5f); + glTexCoord2f(1.0f, 0.0f); + glVertex2f(0.5f, -0.5f); + glEnd(); + + glPopAttrib(); +} + +// A billboard which always faces the viewer in the xy and yz planes +// but not xz +class CylindricalBillboard : public BillboardCommon { +public: + CylindricalBillboard(ITexturePtr aTexture) + : BillboardCommon(aTexture) {} + + // IBillboard inteface + void render() const; +}; + +void CylindricalBillboard::render() const +{ + // Based on code from + // http://www.lighthouse3d.com/opengl/billboarding/index.php?billCheat1 + + float modelview[16]; + + glPushMatrix(); + + translate(); + + glGetFloatv(GL_MODELVIEW_MATRIX , modelview); + + for (int i = 0; i < 3; i += 2) + for (int j = 0; j < 3; j++) { + if (i == j) + modelview[i*4+j] = 1.0; + else + modelview[i*4+j] = 0.0; + } + + glLoadMatrixf(modelview); + + drawTextureQuad(); + + glPopMatrix(); +} + +// A billboard which always faces the viewer +class SphericalBillboard : public BillboardCommon { +public: + SphericalBillboard(ITexturePtr aTexture) + : BillboardCommon(aTexture) {} + + // IBillboard inteface + void render() const; +}; + +void SphericalBillboard::render() const +{ + // Based on code from + // http://www.lighthouse3d.com/opengl/billboarding/index.php?billSphe + Vector lookAt, objToCamProj, upAux, objToCam; + float angleCosine; + + glPushMatrix(); + + translate(); + + // objToCamProj is the vector in world coordinates from the + // local origin to the camera projected in the XZ plane + objToCamProj = makeVector(theCameraPosition.x - myX, + 0.0f, + theCameraPosition.z - myZ); + + // This is the original lookAt vector for the object + // in world coordinates + lookAt = makeVector(0.0f, 0.0f, 1.0f); + + // normalize both vectors to get the cosine directly afterwards + objToCamProj.normalise(); + + // easy fix to determine wether the angle is negative or positive + // for positive angles upAux will be a vector pointing in the + // positive y direction, otherwise upAux will point downwards + // effectively reversing the rotation. + + upAux = lookAt * objToCamProj; + + // compute the angle + angleCosine = lookAt.dot(objToCamProj); + + // perform the rotation. The if statement is used for stability reasons + // if the lookAt and objToCamProj vectors are too close together then + // |angleCosine| could be bigger than 1 due to lack of precision + if ((angleCosine < 0.99990) && (angleCosine > -0.9999)) + glRotatef(acos(angleCosine)*180/3.14, upAux.x, upAux.y, upAux.z); + + // so far it is just like the cylindrical billboard. The code for the + // second rotation comes now + // The second part tilts the object so that it faces the camera + + // objToCam is the vector in world coordinates from + // the local origin to the camera + objToCam = makeVector(theCameraPosition.x - myX, + theCameraPosition.y - myY, + theCameraPosition.z - myZ); + + // Normalize to get the cosine afterwards + objToCam.normalise(); + + // Compute the angle between objToCamProj and objToCam, + //i.e. compute the required angle for the lookup vector + + angleCosine = objToCamProj.dot(objToCam); + + + // Tilt the object. The test is done to prevent instability + // when objToCam and objToCamProj have a very small + // angle between them + + if ((angleCosine < 0.99990) && (angleCosine > -0.9999)) { + if (objToCam.y < 0) + glRotatef(acos(angleCosine)*180/M_PI,1,0,0); + else + glRotatef(acos(angleCosine)*180/M_PI,-1,0,0); + } + + drawTextureQuad(); + + glPopMatrix(); +} + +IBillboardPtr makeCylindricalBillboard(ITexturePtr aTexture) +{ + return IBillboardPtr(new CylindricalBillboard(aTexture)); +} + +IBillboardPtr makeSphericalBillboard(ITexturePtr aTexture) +{ + return IBillboardPtr(new SphericalBillboard(aTexture)); +} + +void setBillboardCameraOrigin(Vector aPosition) +{ + theCameraPosition = aPosition; +} diff --git a/src/SmokeTrail.cpp b/src/SmokeTrail.cpp new file mode 100644 index 0000000..67799ec --- /dev/null +++ b/src/SmokeTrail.cpp @@ -0,0 +1,60 @@ +// +// Copyright (C) 2009 Nick Gasson +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +#include "ISmokeTrail.hpp" +#include "IBillboard.hpp" + +using namespace std; + +// Concrete implementation of smoke trails +class SmokeTrail : public ISmokeTrail { +public: + SmokeTrail(); + ~SmokeTrail() {} + + // ISmokeTrail interface + void render() const; + void setPosition(float x, float y, float z); + +private: + float myX, myY, myZ; + IBillboardPtr myBillboard; +}; + +SmokeTrail::SmokeTrail() + : myX(0.0f), myY(0.0f), myZ(0.0f) +{ + ITexturePtr particle(loadTexture("data/images/smoke_particle.png")); + myBillboard = makeSphericalBillboard(particle); +} + +void SmokeTrail::render() const +{ + +} + +void SmokeTrail::setPosition(float x, float y, float z) +{ + myX = x; + myY = y; + myZ = z; +} + +ISmokeTrailPtr makeSmokeTrail() +{ + return ISmokeTrailPtr(new SmokeTrail); +} diff --git a/src/Train.cpp b/src/Train.cpp index 48fd547..2174ea1 100644 --- a/src/Train.cpp +++ b/src/Train.cpp @@ -20,9 +20,6 @@ #include "ILogger.hpp" #include "TrackCommon.hpp" -// REMOVE -#include "IBillboard.hpp" - #include #include @@ -74,9 +71,6 @@ private: // Seperation between waggons static const double SEPARATION; - - // REMOVE - IBillboardPtr bb; }; const double Train::SEPARATION(0.1); @@ -93,8 +87,6 @@ Train::Train(IMapPtr aMap) for (int i = 1; i <= 5; i++) addPart(makeWaggon()); - - bb = makeSphericalBillboard(loadTexture("data/images/smoke_particle.png")); } void Train::addPart(IRollingStockPtr aVehicle) @@ -188,10 +180,6 @@ void Train::render() const glPopMatrix(); } - - Vector p = front(); - bb->setPosition(p.x, p.y + 2.0f, p.z); - bb->render(); } Vector Train::front() const -- 2.39.2