openGL+VS2010的例程--特效(三维)

时间:2022-09-10 17:01:10

openGL+VS2010的例程--特效(三维)

效果图如上:

步骤:略。

实现代码如下:

main.cpp

 

  1 /**********************************************************************
  2 
  3   Particle Engine / Billboarding
  4 
  5   October, 21st, 2002
  6 
  7   This tutorial was written by Philipp Crocoll
  8   Contact: 
  9     philipp.crocoll@web.de
 10     www.codecolony.de
 11 
 12   Every comment would be appreciated.
 13 
 14   If you want to use parts of any code of mine:
 15     let me know and
 16     use it!
 17 
 18   If you get cool effects with this particle engine,
 19   I would be happy if you could send me the code. If you want to,
 20   I can upload it. This code is only a part of what you can do with 
 21   this engine.
 22 
 23 ***********************************************************************
 24 
 25 
 26   ESC                    : Exit
 27   w,a,s,d,r,f,x,y,c,v    : move / turn
 28 
 29 
 30 
 31 **********************************************************************/
 32    
 33 #include <GL\glut.h>        //includes gl.h and glu.h
 34 #include <GL\glaux.h>        //load the texture
 35 #include <stdlib.h>            //random function
 36 #include <math.h>            //sine and cosine functions
 37 
 38 #include "Camera.h"
 39 #include "particles.h"
 40 
 41 //Particle variables:
 42 CCCParticleSystem g_ParticleSystem1;
 43 CCCParticleSystem g_ParticleSystem2;
 44 CCCParticleSystem g_ParticleSystem3;
 45 CCCParticleSystem g_ParticleSystem4;
 46 CCCParticleSystem g_ParticleSystem5;
 47 CCCParticleSystem g_ParticleSystem6;
 48 
 49 //g_Camera:
 50 CCamera g_Camera;
 51 
 52 //Time handling (note: use QueryPerformanceCounter in "real" projects!)
 53 long unsigned int g_iLastRenderTime = 0; // 查询性能计数器
 54 
 55 
 56 //code from the camera tutorial: // 绘制网格
 57 void DrawNet(GLfloat size, GLint LinesX, GLint LinesZ)
 58 {
 59     glBegin(GL_LINES);
 60     for (int xc = 0; xc < LinesX; xc++)
 61     {
 62         glVertex3f(    -size / 2.0 + xc / (GLfloat)(LinesX-1)*size,
 63                     0.0,
 64                     size / 2.0);
 65         glVertex3f(    -size / 2.0 + xc / (GLfloat)(LinesX-1)*size,
 66                     0.0,
 67                     size / -2.0);
 68     }
 69     for (int zc = 0; zc < LinesX; zc++)
 70     {
 71         glVertex3f(    size / 2.0,
 72                     0.0,
 73                     -size / 2.0 + zc / (GLfloat)(LinesZ-1)*size);
 74         glVertex3f(    size / -2.0,
 75                     0.0,
 76                     -size / 2.0 + zc / (GLfloat)(LinesZ-1)*size);
 77     }
 78     glEnd();
 79 }
 80 
 81 
 82 void Display(void)
 83 {
 84     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 85     glLoadIdentity();    //Load a new modelview matrix -> we can apply new transformations
 86     // 加载一个新的视点矩阵- >我们可以应用新的转换
 87     //Update the scene:
 88     long unsigned int iNowTime = timeGetTime(); // 函数以毫秒计的系统时间。该时间为从系统开启算起所经过的时间。
 89     float timePassed = float(iNowTime-g_iLastRenderTime)/1000.0f;  //divide by 1000
 90     g_ParticleSystem1.UpdateSystem(timePassed);
 91     g_ParticleSystem2.UpdateSystem(timePassed);
 92     g_ParticleSystem3.UpdateSystem(timePassed);
 93     g_ParticleSystem4.UpdateSystem(timePassed);
 94     g_ParticleSystem5.UpdateSystem(timePassed);
 95     g_ParticleSystem6.UpdateSystem(timePassed);
 96     
 97     g_iLastRenderTime = iNowTime;
 98     
 99     //render everything:
100     g_Camera.Render();
101 
102     
103     
104     //render an opaque quadrangle:    (if you want to see how to do this...)
105     //glEnable(GL_DEPTH_TEST);
106     //glDisable(GL_TEXTURE_2D);
107     //glColor3f(1.0f,0.0,1.0f);
108 
109     //glBegin(GL_POLYGON);
110     //glVertex3f(0.0f,0.0f,0.0f);
111     //glVertex3f(1.0f,0.0f,0.0f);
112     //glVertex3f(1.0f,1.0f,0.0f);
113     //glVertex3f(0.0f,1.0f,0.0f);
114     //glEnd();
115 
116 
117     //render the nets, so switch off blending and texturing:
118     glDisable(GL_BLEND); // 关闭混合
119     glDisable(GL_TEXTURE_2D); // 关闭贴图
120     //enable depth testing (and z-buffer-writing)
121     glEnable(GL_DEPTH_TEST); // 启动深度测试
122     glDepthMask(GL_TRUE); // 可将深度缓冲区设置为可读可写形式
123     
124     GLfloat size = 2.0;
125     GLint LinesX = 30;
126     GLint LinesZ = 30;
127     
128     glColor3f(1.0,0.0,0.0);
129     glPushMatrix();
130         glTranslatef(0.0,0.0 ,0.0);
131         DrawNet(size,LinesX,LinesZ);
132         glTranslatef(0.0,size,0.0);
133         DrawNet(size,LinesX,LinesZ);
134     glPopMatrix();
135     
136     
137     //Render system 2 first, it's not textured:
138 
139     glEnable(GL_BLEND);
140     glDepthMask(GL_FALSE);
141     glEnable(GL_DEPTH_TEST);
142 
143     //Calculate the point size depending from the camera's distance to the emitter:
144     //(in order to be 100% exact we would have to pass the camera position to the
145     //particles' render function. This method would then have to calculate the point size for each particle!)
146     float zDist = g_Camera.GetPosition().z - g_ParticleSystem2.m_EmitterPosition.z;
147     float xDist = g_Camera.GetPosition().x - g_ParticleSystem2.m_EmitterPosition.x;
148     float CamDistToEmitter = sqrt(SQR(zDist)+SQR(xDist));
149     if (CamDistToEmitter < 0.2f) //avoid too big particles
150         CamDistToEmitter = 0.2f;
151     glPointSize(1.0f/CamDistToEmitter);
152     g_ParticleSystem2.Render();
153 
154     //Now enable texturing and render the other particle systems:
155     glEnable(GL_TEXTURE_2D);
156     g_ParticleSystem1.Render();
157     g_ParticleSystem3.Render();
158     g_ParticleSystem4.Render();
159     g_ParticleSystem5.Render();
160     g_ParticleSystem6.Render();
161     glDepthMask(GL_TRUE);
162 
163 
164     glFlush();            //Finish rendering
165     glutSwapBuffers();    //Swap the buffers ->make the result of rendering visible
166 }
167 void Reshape(int x, int y)
168 {
169     if (y == 0 || x == 0) return;  //Nothing is visible then, so return
170     //Set a new projection matrix
171     glMatrixMode(GL_PROJECTION);  
172     glLoadIdentity();
173     //Angle of view:40 degrees
174     //Near clipping plane distance: 0.5
175     //Far clipping plane distance: 20.0
176     gluPerspective(40.0,(GLdouble)x/(GLdouble)y,0.05,10.0);
177     glMatrixMode(GL_MODELVIEW);
178     glViewport(0,0,x,y);  //Use the whole window for rendering
179 
180 }
181 void KeyDown(unsigned char key, int x, int y)
182 {    
183     switch(key)
184     {
185     case 27:    //ESC
186         exit(0);
187         break;
188     case 'a':        
189         g_Camera.RotateY(5.0);
190         Display();
191         break;
192     case 'd':        
193         g_Camera.RotateY(-5.0);
194         Display();
195         break;
196     case 'w':        
197         g_Camera.MoveForwards( -0.1 ) ;
198         Display();
199         break;
200     case 's':        
201         g_Camera.MoveForwards( 0.1 ) ;
202         Display();
203         break;
204     case 'x':        
205         g_Camera.RotateX(5.0);
206         Display();
207         break;
208     case 'y':        
209         g_Camera.RotateX(-5.0);
210         Display();
211         break;
212     case 'c':        
213         g_Camera.StrafeRight(-0.1);
214         Display();
215         break;
216     case 'v':        
217         g_Camera.StrafeRight(0.1);
218         Display();
219         break;
220     case 'f':
221         g_Camera.Move(F3dVector(0.0,-0.3,0.0));
222         Display();
223         break;
224     case 'r':
225         g_Camera.Move(F3dVector(0.0,0.3,0.0));
226         Display();
227         break;
228 
229     }
230 }
231 
232 void InitParticles()  
233 {
234      
235 //INIT SYSTEM 1 (FIRE1)
236     g_ParticleSystem1.Initialize(300); // 同一时间显示的火焰个数
237     g_ParticleSystem1.m_iParticlesCreatedPerSec = 300;
238     g_ParticleSystem1.m_fCreationVariance = 3.0f; // 创建变异
239     g_ParticleSystem1.m_bRecreateWhenDied = true; // 当消亡时,是否再创造
240     g_ParticleSystem1.m_fMinDieAge = 1.5f;    // 移动的最小距离
241     g_ParticleSystem1.m_fMaxDieAge = 1.5f; // 移动的最大距离
242     g_ParticleSystem1.SetCreationColor(1.0f,0.0f,0.0f,
243                                     1.0f,0.5f,0.5f); // 创建时的颜色范围
244     g_ParticleSystem1.SetDieColor(0.0f,0.0f, 0.0f,
245                                   1.0f,0.5f,0.0f); //消亡时的颜色范围
246 
247     g_ParticleSystem1.SetAlphaValues(1.0f,1.0f,0.0f,0.0f); //透明度
248     g_ParticleSystem1.SetEmitter(0.0f,0.0f,0.5f,
249                                 0.1f,0.0f,0.1f); 
250     g_ParticleSystem1.SetAcceleration(F3dVector(0.0f,1.0f,0.0f),0.3f,0.4f); // 加速度
251     g_ParticleSystem1.SetSizeValues(0.11f,0.11f,0.13f,0.13f); //细胞的大小
252     g_ParticleSystem1.m_fMaxEmitSpeed = 1.0f; // 最大发射速度
253     g_ParticleSystem1.m_fMinEmitSpeed = 0.3f;// 最小发射速度
254     g_ParticleSystem1.SetEmissionDirection(0.0f,1.0f,0.0f,
255                                         0.08f,0.5f,0.08f); // 设置发射方向
256     g_ParticleSystem1.m_bParticlesLeaveSystem = true; // 粒子离开系统
257     g_ParticleSystem1.SetSpinSpeed(-0.82*PI,0.82*PI); // 设置旋转速度
258     g_ParticleSystem1.m_iBillboarding = BILLBOARDING_PERPTOVIEWDIR; // 布告板=调整粒子方向垂直于视图
259     g_ParticleSystem1.LoadTextureFromFile("particle1.tga");
260 
261 //INIT SYSTEM 2 (POINTS, FIREWORK) // 右后侧的白色喷泉
262     g_ParticleSystem2.Initialize(800);  //particle system must not have more than 800 particles
263     g_ParticleSystem2.m_iParticlesCreatedPerSec = 800;  //we create all particles in the first second of the system's life
264     g_ParticleSystem2.m_fMinDieAge = 2.5f;            //but the particles live longer than one second
265     g_ParticleSystem2.m_fMaxDieAge = 2.5f;            //-> this causes the system to "shoot" periodically
266         
267     g_ParticleSystem2.m_fCreationVariance = 1.0f;
268     g_ParticleSystem2.m_bRecreateWhenDied = true;
269     g_ParticleSystem2.SetCreationColor(1.0f,1.0f,1.0f,
270                                 0.5f,0.5f,0.5f);
271     g_ParticleSystem2.SetDieColor(0.0f,1.0f,0.0f,
272                                0.0f,0.1f,0.0f);
273     g_ParticleSystem2.SetAlphaValues(1.0f,1.0f,0.0f,0.0f);
274     g_ParticleSystem2.SetEmitter(0.8f,0.0f,0.0f,
275                                 0.02f,0.0f,0.02f);
276     g_ParticleSystem2.SetAcceleration(F3dVector(0.0f,-1.0f,0.0f),0.83f,1.4f);
277     g_ParticleSystem2.SetSizeValues(3.0f,3.0f,4.0f,4.0f);
278     g_ParticleSystem2.m_fMaxEmitSpeed = 0.82f;
279     g_ParticleSystem2.m_fMinEmitSpeed = 1.3f;
280     g_ParticleSystem2.SetEmissionDirection(-1.0f,2.0f,0.0f,
281                                         0.5f,0.5f,0.5f);
282 
283     g_ParticleSystem2.m_bParticlesLeaveSystem = true;
284      
285 //INIT SYSTEM 3 (RAIN)
286     g_ParticleSystem3.Initialize(7000);
287     g_ParticleSystem3.m_iParticlesCreatedPerSec = 2950;
288     g_ParticleSystem3.m_fCreationVariance = 0.0f;
289     g_ParticleSystem3.m_bRecreateWhenDied = false;
290     g_ParticleSystem3.m_fMinDieAge = 2.0f;
291     g_ParticleSystem3.m_fMaxDieAge = 2.0f;
292     g_ParticleSystem3.SetCreationColor(0.9f,0.9f,0.9f,
293                                     0.8f,0.8f,0.8f);
294     g_ParticleSystem3.SetDieColor(0.2f,0.4f,0.2f,
295                                0.0f,0.1f,0.0f);
296 
297     g_ParticleSystem3.SetAlphaValues(1.0f,1.0f,1.0f,1.0f);  
298     g_ParticleSystem3.SetEmitter(0.0f,2.0f,0.0f,
299                                  1.0f,0.0f,1.0f);
300     g_ParticleSystem3.SetAcceleration(NULL_VECTOR,0.0f,0.0f);
301     g_ParticleSystem3.SetSizeValues(0.01f,0.01f,0.01f,0.01f);
302     g_ParticleSystem3.m_fMaxEmitSpeed = 1.0f;
303     g_ParticleSystem3.m_fMinEmitSpeed = 1.0f;
304     g_ParticleSystem3.SetEmissionDirection(0.0f,-1.0f,0.0f,
305                                         0.00f,0.0f,0.00f);
306     g_ParticleSystem3.m_bParticlesLeaveSystem = true;
307     g_ParticleSystem3.m_iBillboarding = BILLBOARDING_PERPTOVIEWDIR_BUTVERTICAL;
308     g_ParticleSystem3.LoadTextureFromFile("particle2.tga");
309  
310 //INIT SYSTEM 4 (SMOKE)
311     g_ParticleSystem4.Initialize(150);
312     g_ParticleSystem4.m_iParticlesCreatedPerSec = 50;
313     g_ParticleSystem4.m_fCreationVariance = 0.0f;
314     g_ParticleSystem4.m_bRecreateWhenDied = false;
315     g_ParticleSystem4.m_fMinDieAge = 2.5f;
316     g_ParticleSystem4.m_fMaxDieAge = 3.5f;
317     g_ParticleSystem4.SetCreationColor(0.1f,0.1f,0.1f,
318                                     0.2f,0.2f,0.2f);
319     g_ParticleSystem4.SetDieColor(0.0f,0.0f,0.0f,
320                                0.0f,0.0f,0.0f);
321 
322     g_ParticleSystem4.SetAlphaValues(1.0f,1.0f,0.0f,0.0f);
323     g_ParticleSystem4.SetEmitter(-0.8f,0.0f,0.0f,
324                                 0.0f,0.0f,0.0f);
325     g_ParticleSystem4.SetAcceleration(F3dVector(0.0f,1.0f,0.0f),0.3f,0.4f);
326     g_ParticleSystem4.SetSizeValues(0.0f,0.0f,1.12f,1.22f);
327     g_ParticleSystem4.m_fMaxEmitSpeed = 0.01f;
328     g_ParticleSystem4.m_fMinEmitSpeed = 0.04f;
329     g_ParticleSystem4.SetEmissionDirection(0.0f,1.0f,0.0f,
330                                            0.08f,0.5f,0.08f);
331     g_ParticleSystem4.m_bParticlesLeaveSystem = true;
332     g_ParticleSystem4.m_iBillboarding = BILLBOARDING_PERPTOVIEWDIR;
333     g_ParticleSystem4.LoadTextureFromFile("particle3.tga");
334 
335 //INIT SYSTEM 5 ("ENGINE")
336     g_ParticleSystem5.Initialize(300);
337     g_ParticleSystem5.m_iParticlesCreatedPerSec = 200;
338     g_ParticleSystem5.m_fCreationVariance = 0.0f;
339     g_ParticleSystem5.m_bRecreateWhenDied = false;
340     g_ParticleSystem5.m_fMinDieAge = 1.0f;
341     g_ParticleSystem5.m_fMaxDieAge = 1.3f;
342     g_ParticleSystem5.SetCreationColor(0.5f,0.0f,0.0f,
343                                     0.5f,0.1f,0.1f);
344     g_ParticleSystem5.SetDieColor(0.2f,0.2f,0.0f,
345                                0.8f,0.8f,0.0f);
346 
347     g_ParticleSystem5.SetAlphaValues(1.0f,1.0f,0.3f,0.3f);
348     g_ParticleSystem5.SetEmitter(0.0f,0.0f,-1.0f,
349                                 0.02f,0.02f,0.0f);
350     g_ParticleSystem5.SetAcceleration(F3dVector(0.0f,1.0f,0.0f),0.0f,0.0f);
351     g_ParticleSystem5.SetSizeValues(0.12f,0.12f,0.06f,0.06f);
352     g_ParticleSystem5.m_fMaxEmitSpeed = 0.12f;
353     g_ParticleSystem5.m_fMinEmitSpeed = 0.14f;
354     g_ParticleSystem5.SetEmissionDirection(0.0f,0.0f,1.0f,
355                                            0.00f,0.0f,0.00f);
356     g_ParticleSystem5.m_bParticlesLeaveSystem = true;
357     g_ParticleSystem5.m_iBillboarding = BILLBOARDING_PERPTOVIEWDIR;
358     g_ParticleSystem5.LoadTextureFromFile("particle3.tga");
359 
360 //INIT SYSTEM 6 (FIRE2)
361     g_ParticleSystem6.Initialize(300);
362     g_ParticleSystem6.m_iParticlesCreatedPerSec = 300;
363 
364     g_ParticleSystem6.m_bRecreateWhenDied = false;
365     g_ParticleSystem6.m_fMinDieAge = 0.5f;
366     g_ParticleSystem6.m_fMaxDieAge = 1.0f;
367     g_ParticleSystem6.SetCreationColor(1.0f,0.0f,0.0f,
368                                     1.0f,0.5f,0.0f);
369     g_ParticleSystem6.SetDieColor(1.0f,1.0f,1.0f,
370                                   1.0f,0.5f,0.0f);
371 
372     g_ParticleSystem6.SetAlphaValues(1.0f,1.0f,0.0f,0.0f);
373     g_ParticleSystem6.SetEmitter(0.0f,0.0f,0.5f,
374                                 0.18f,0.0f,0.18f);
375     g_ParticleSystem6.SetAcceleration(F3dVector(0.0f,1.0f,0.0f),0.3f,0.4f);
376     g_ParticleSystem6.SetSizeValues(0.04f,0.08f,0.06f,0.12f);
377     g_ParticleSystem6.m_fMaxEmitSpeed = 0.12f;
378     g_ParticleSystem6.m_fMinEmitSpeed = 0.23f;
379     g_ParticleSystem6.SetEmissionDirection(0.0f,1.0f,0.0f,
380                                         0.08f,0.5f,0.08f);
381     g_ParticleSystem6.m_bParticlesLeaveSystem = true;
382     g_ParticleSystem6.SetSpinSpeed(-0.82*PI,0.82*PI);
383     g_ParticleSystem6.m_iBillboarding = BILLBOARDING_PERPTOVIEWDIR;
384     g_ParticleSystem6.LoadTextureFromFile("particle1.tga");
385   
386 }
387 
388 int main(int argc, char **argv)
389 {    
390     //Initialize GLUT
391     glutInit(&argc, argv);
392     //Lets use doublebuffering, RGB(A)-mode and a depth buffer
393     glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
394     glutInitWindowSize(800,600);
395     //Create a window with rendering context and everything else we need
396     glutCreateWindow("Particle Engine and Billboarding");
397     //Init some state variables:
398     glDisable(GL_DEPTH_TEST);
399     glClearColor(0.1,0.1,0.1,1.0);
400     glEnable(GL_POINT_SMOOTH);
401     glEnable(GL_BLEND);
402     glBlendFunc(GL_SRC_ALPHA, GL_ONE);
403     glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);    //also try GL_LINE
404     
405     g_Camera.Move(F3dVector(0.0f,0.3f,3.0f));
406     
407 
408     //INITIALIZE THE PARTICLE SYSTEM:
409     InitParticles();
410     
411     //Assign the event-handling routines
412     glutDisplayFunc(Display);
413     glutReshapeFunc(Reshape);
414     glutKeyboardFunc(KeyDown);
415     glutIdleFunc(Display);  //If there is no msg, we have to repaint
416 
417     g_iLastRenderTime = timeGetTime();
418     //Let GLUT get the msgs and tell us the ones we need
419     glutMainLoop();
420     return 0;
421 }

 

Particles.h

  1 /***************************************************************
  2 
  3   Particles.h
  4 
  5   Philipp Crocoll from www.codecolony.de
  6 
  7   Defines the classes used for the CodeColony Particle Engine:
  8 
  9    - CCCParticle: Class to store/update a particle
 10    - CCCParticleSystem: Class to store/update/render a complete particle system 
 11                         (including an emitter)
 12 
 13 ****************************************************************/
 14 
 15 //Include files needed:
 16 #include "camera.h"
 17 #include "textures.h"
 18 
 19 
 20 class CCCParticleSystem;
 21 
 22 
 23 /*******************
 24 CONSTANTS
 25 *******************/
 26 #define BILLBOARDING_NONE                            0
 27 #define BILLBOARDING_PERPTOVIEWDIR                    1  //align particles perpendicular to view direction
 28 #define BILLBOARDING_PERPTOVIEWDIR_BUTVERTICAL        2  //like PERPToViewDir, but Particles are vertically aligned
 29 
 30 /*******************
 31 CCCParticle
 32 *******************/
 33 
 34 class CCCParticle
 35 {
 36 private:
 37   //Position of the particle:  NOTE: This might be the global position or the local position (depending on the system's translating behavior)
 38     SF3dVector m_Position;
 39   //Moving the particle:
 40     //Particle's velocity:
 41     SF3dVector m_Velocity;
 42     //Particle's acceleration (per Sec):
 43     SF3dVector m_Acceleration;
 44   //Spinning the particle
 45     float       m_fSpinAngle; //radian measure
 46     //Particle's spin speed:
 47     float       m_fSpinSpeed;
 48   //Particle's spin acceleration:
 49     float      m_fSpinAcceleration;
 50   //Particle's alpha value (=transparency)
 51     float      m_fAlpha;
 52     float       m_fAlphaChange;  //how much is the alpha value changed per sec?
 53   //Particle's color:
 54     SF3dVector m_Color;   //x=r, y=g, z=b
 55     SF3dVector m_ColorChange;  //how to change to color per sec
 56   //Particle's size:  (the use of this value is dependent of m_bUseTexture in the parent!)
 57     float       m_fSize;
 58     float       m_fSizeChange;    
 59   //Handling the lifetime:
 60     float       m_fDieAge;    //At what "age" will the particle die?
 61     float       m_fAge;        //Age of the particle (is updated     
 62   //Needed to access the system's values:
 63     CCCParticleSystem * m_ParentSystem;
 64     
 65 public:
 66     bool       m_bIsAlive;  //Is the particle active or not? Must be visible for the System
 67     void Initialize(CCCParticleSystem * ParentSystem);
 68     void Update(float timePassed);    //called by UpdateSystem if particle is active
 69     void Render();  
 70 
 71 };
 72 
 73 
 74 /*******************
 75 CCCParticleSystem
 76 *******************/
 77 
 78 class CCCParticleSystem
 79 {
 80 public:  //The values how to emit a particle must be public because the particle    
 81          //must be able to access them in the creation function.
 82 //*************************************
 83 // EMISSION VALUES
 84 //*************************************
 85 
 86     //Position of the emitter:
 87     SF3dVector        m_EmitterPosition;
 88     //How far may the particles be created from the emitter?
 89     SF3dVector        m_MaxCreationDeviation;  //3 positive values. Declares the possible distance from the emitter
 90                                              // Distance can be between -m_MaxCreationDeviation.? and +m_MaxCreationDeviation.?
 91     //Which direction are the particles emitted to?
 92     SF3dVector        m_StandardEmitDirection;
 93     SF3dVector        m_MaxEmitDirectionDeviation; //Works like m_MaxCreationDeviation
 94 
 95     //Which speed do they have when they are emitted?
 96     //->Somewhere between these speeds:
 97     float            m_fMinEmitSpeed;
 98     float            m_fMaxEmitSpeed;
 99 
100     //How fast do they spin when being emitted? Speed here is angle speed (radian measure) per sec
101     float            m_fMinEmitSpinSpeed;
102     float            m_fMaxEmitSpinSpeed;
103     //Spinning acceleration:
104     float            m_fMinSpinAcceleration;
105     float            m_fMaxSpinAcceleration;
106 
107     //The acceleration vector always has the same direction (normally (0/-1/0) for gravity):
108     SF3dVector        m_AccelerationDirection;
109     //...but not the same amount:
110     float            m_fMinAcceleration;
111     float            m_fMaxAcceleration;
112     
113     //How translucent are the particles when they are created?
114     float            m_fMinEmitAlpha;
115     float            m_fMaxEmitAlpha;
116     //How translucent are the particles when they have reached their dying age?
117     float            m_fMinDieAlpha;
118     float            m_fMaxDieAlpha;
119 
120     //How big are the particles when they are created / when they die
121     float            m_fMinEmitSize;
122     float            m_fMaxEmitSize;
123     float            m_fMinDieSize;
124     float            m_fMaxDieSize;
125 
126 
127     //The same with the color:
128     SF3dVector        m_MinEmitColor;
129     SF3dVector        m_MaxEmitColor;
130     SF3dVector        m_MinDieColor;
131     SF3dVector        m_MaxDieColor;
132 
133 //*************************************
134 // OTHER PARTICLE INFORMATION
135 //*************************************
136 
137     //How long shall the particles live? Somewhere (randomly) between:
138     float            m_fMinDieAge;
139     float            m_fMaxDieAge;
140 
141     bool            m_bRecreateWhenDied;  //Set it true so a particle will be recreate itsself as soon
142                                           //as it died
143 
144 //*************************************
145 // RENDERING PROPERTIES
146 //*************************************    
147 
148     int                m_iBillboarding;    //See the constants above
149     
150     COGLTexture *    m_Texture;            //Pointer to the texture (which is only an "alpha texture")    
151     bool            m_bUseTexture;        //Set it false if you want to use GL_POINTS as particles!
152 
153     bool            m_bParticlesLeaveSystem;  //Switch it off if the particle's positions 
154                                              //shall be relative to the system's position (emitter position)
155         
156 //*************************************
157 // STORING THE PARTICLES
158 //*************************************    
159     //Particle array:
160     CCCParticle    *m_pParticles;
161     //Maximum number of particles (assigned when reserving mem for the particle array)
162     int                m_iMaxParticles;
163     //How many particles are currently in use?
164     int                m_iParticlesInUse;
165     //How many particles are created per second?
166     //Note that this is an average value and if you set it too high, there won't be
167     //dead particles that can be created unless the lifetime is very short and/or 
168     //the array of particles (m_pParticles) is big 
169     int                m_iParticlesCreatedPerSec;  //if bRecreateWhenDied is true, this is the ADDITIONAL number of created particles!
170     float            m_fCreationVariance; //Set it 0 if the number of particles created per sec 
171                                          //should be the same each second. Otherwise use a positive value:
172                                          //Example: 1.0 affects that the NumParticlesCreatedPerSec varies 
173                                          //between m_iParticlesCreatedPerSec/2 and 1.5*m_iParticlesCreatedPerSec
174 //Do not set these values:
175     float            m_fCurrentPointSize;  //required when rendering without particles
176     //If Billboarding is set to NONE, the following vectors are (1,0,0) and (0,1,0).
177     //If it is switched on, they are modified according to the viewdir/camera position (in Render of the System)
178     SF3dVector        m_BillboardedX;
179     SF3dVector        m_BillboardedY;            
180 
181 
182 //*************************************
183 // FUNCTIONS TO ASSIGN THESE MANY VECTORS MORE EASILY
184 //*************************************
185 
186     //Set the emitter position (you can pass a vector or x,y and z)
187     void            SetEmitter(float x, float y, float z, float EmitterDeviationX,float EmitterDeviationY,float EmitterDeviationZ);
188     void            SetEmitter(SF3dVector pos,SF3dVector dev);
189     
190     //Set the emission direction:
191     void            SetEmissionDirection(float x, float y, float z,         //direction
192                                          float MaxDeviationX, float MaxDeviationY, float MaxDeviationZ);  //max deviation
193     void            SetEmissionDirection(SF3dVector direction, SF3dVector Deviation);
194 
195     //Spin Speed
196     void            SetSpinSpeed(float min, float max);
197     
198     //Acceleration
199     void            SetAcceleration(float x, float y, float z, float Min, float Max);
200     void            SetAcceleration(SF3dVector acc, float Min, float Max);
201 
202     //Color (at creation and dying age):
203     void            SetCreationColor(float minr, float ming, float minb,
204                                         float maxr, float maxg, float maxb);
205     void            SetCreationColor(SF3dVector min, SF3dVector max);
206 
207     void            SetDieColor        (float minr, float ming, float minb,
208                                         float maxr, float maxg, float maxb);
209     void            SetDieColor        (SF3dVector min, SF3dVector max);
210     //alpha:
211     void            SetAlphaValues (float MinEmit, float MaxEmit, float MinDie, float MaxDie);
212     //size:
213     void            SetSizeValues (float EmitMin, float EmitMax, float DieMin, float DieMax);
214         
215 //*************************************
216 // FUNCTIONS TO INITIALIZE THE SYSTEM
217 //*************************************
218 
219     CCCParticleSystem();                                //constructor: sets default values
220 
221     bool            Initialize(int iNumParticles);        //reserves space for the particles
222 
223     bool            LoadTextureFromFile(char * Filename);
224 
225 //*************************************
226 // FUNCTIONS TO UPDATE/RENDER THE SYSTEM
227 //*************************************
228 
229     void            UpdateSystem(float timePassed);    //updates all particles alive
230     void            Render();                            //renders all particles alive
231 
232 };

 

particles.cpp

  1 #include "particles.h"
  2 #include "math.h"
  3 
  4 //Generates a random float in the range [0;1]
  5 #define RANDOM_FLOAT (((float)rand())/RAND_MAX)
  6 /*************************************
  7 
  8 METHODS OF CCCParticle class
  9 
 10 **************************************/
 11 
 12 void CCCParticle::Initialize(CCCParticleSystem *ParentSystem)
 13 {
 14 
 15   //Calculate the age, the particle will live:
 16     m_fDieAge = ParentSystem->m_fMinDieAge + 
 17                  ((ParentSystem->m_fMaxDieAge - ParentSystem->m_fMinDieAge)*RANDOM_FLOAT);
 18     if (m_fDieAge == 0.0f) return;  //make sure there is no div 0
 19     m_fAge = 0.0f;
 20 
 21   //set the position:
 22     if (ParentSystem->m_bParticlesLeaveSystem)
 23     {
 24         //start with "global" coordinates (the current coordinates of the emitter position)
 25         m_Position = ParentSystem->m_EmitterPosition;
 26     }
 27     else
 28     {
 29         //In this case we assume a local coordinate system:
 30         m_Position = NULL_VECTOR;
 31     }
 32     //Add the deviation from the emitter position:
 33     m_Position.x += ParentSystem->m_MaxCreationDeviation.x*(RANDOM_FLOAT*2.0f-1.0f);
 34     m_Position.y += ParentSystem->m_MaxCreationDeviation.y*(RANDOM_FLOAT*2.0f-1.0f);
 35     m_Position.z += ParentSystem->m_MaxCreationDeviation.z*(RANDOM_FLOAT*2.0f-1.0f);
 36   //set the emission velocity
 37     m_Velocity.x = ParentSystem->m_StandardEmitDirection.x + ParentSystem->m_MaxEmitDirectionDeviation.x*(RANDOM_FLOAT*2.0f-1.0f);
 38     m_Velocity.y = ParentSystem->m_StandardEmitDirection.y + ParentSystem->m_MaxEmitDirectionDeviation.y*(RANDOM_FLOAT*2.0f-1.0f);
 39     m_Velocity.z = ParentSystem->m_StandardEmitDirection.z + ParentSystem->m_MaxEmitDirectionDeviation.z*(RANDOM_FLOAT*2.0f-1.0f);
 40     m_Velocity = m_Velocity * ((ParentSystem->m_fMinEmitSpeed + 
 41                                  (ParentSystem->m_fMaxEmitSpeed - ParentSystem->m_fMinEmitSpeed)*RANDOM_FLOAT));
 42   //set the acceleration vector:
 43     m_Acceleration = ParentSystem->m_AccelerationDirection* 
 44                       (ParentSystem->m_fMinAcceleration + (ParentSystem->m_fMaxAcceleration-ParentSystem->m_fMinAcceleration)*RANDOM_FLOAT);
 45   //set the alpha / color values:
 46     m_Color = ParentSystem->m_MinEmitColor + 
 47            ((ParentSystem->m_MaxEmitColor-ParentSystem->m_MinEmitColor) * RANDOM_FLOAT);
 48     //calculate the "end color" (in order to get the ColorChange):
 49     SF3dVector EndColor = ParentSystem->m_MinDieColor + 
 50            ((ParentSystem->m_MaxDieColor-ParentSystem->m_MinDieColor) * RANDOM_FLOAT);
 51     m_ColorChange = (EndColor-m_Color) / m_fDieAge;
 52 
 53     m_fAlpha = ParentSystem->m_fMinEmitAlpha 
 54                + ((ParentSystem->m_fMaxEmitAlpha - ParentSystem->m_fMinEmitAlpha) * RANDOM_FLOAT);
 55     float fEndAlpha = ParentSystem->m_fMinDieAlpha 
 56                + ((ParentSystem->m_fMaxDieAlpha - ParentSystem->m_fMinDieAlpha) * RANDOM_FLOAT);
 57     m_fAlphaChange = (fEndAlpha - m_fAlpha) / m_fDieAge;
 58 
 59   //set the size values:
 60     m_fSize = ParentSystem->m_fMinEmitSize +
 61              ((ParentSystem->m_fMaxEmitSize - ParentSystem->m_fMinEmitSize) * RANDOM_FLOAT);
 62     float fEndSize = ParentSystem->m_fMinDieSize +
 63              ((ParentSystem->m_fMaxDieSize - ParentSystem->m_fMinDieSize) * RANDOM_FLOAT);
 64     m_fSizeChange = (fEndSize - m_fSize) / m_fDieAge;
 65 
 66   //spin values:
 67     m_fSpinAngle = 0.0f;
 68     m_fSpinSpeed = ParentSystem->m_fMinEmitSpinSpeed +
 69             ((ParentSystem->m_fMaxEmitSpinSpeed - ParentSystem->m_fMinEmitSpinSpeed) * RANDOM_FLOAT);
 70     m_fSpinAcceleration = ParentSystem->m_fMinSpinAcceleration +
 71             ((ParentSystem->m_fMaxSpinAcceleration - ParentSystem->m_fMinSpinAcceleration) * RANDOM_FLOAT);
 72     
 73   //Ok, we're done:
 74     m_bIsAlive = true;
 75     m_ParentSystem = ParentSystem;
 76 
 77 }
 78 
 79 void CCCParticle::Update(float timePassed)
 80 {
 81     //Update all time-dependent values:
 82     m_fAge += timePassed;
 83     if (m_fAge >= m_fDieAge) 
 84     {
 85         if (m_ParentSystem->m_bRecreateWhenDied) 
 86         {
 87             Initialize(m_ParentSystem);
 88             Update(RANDOM_FLOAT * timePassed);  //see comment in UpdateSystem
 89         }
 90         else
 91         {
 92             m_fAge = 0.0f;
 93             m_bIsAlive = false;
 94             m_ParentSystem->m_iParticlesInUse--;
 95         }
 96 
 97         return;
 98     }
 99 
100     m_fSize  += m_fSizeChange *timePassed;
101     m_fAlpha += m_fAlphaChange*timePassed;
102     m_Color = m_Color + m_ColorChange*timePassed;
103     m_Velocity = m_Velocity + m_Acceleration*timePassed;
104     //Note: exact would be: m_Position = 1/2*m_Acceleration*timePassed?+ m_VelocityOLD*timePassed;
105     //But this approach is ok, I think!
106     m_Position = m_Position + (m_Velocity*timePassed);
107 
108     m_fSpinSpeed += m_fSpinAcceleration*timePassed;
109     m_fSpinAngle += m_fSpinSpeed*timePassed;
110 
111     //That's all!
112 }
113 
114 void CCCParticle::Render()
115 {
116     if (!m_ParentSystem->m_bUseTexture) 
117     {
118         glPointSize(m_fSize*m_ParentSystem->m_fCurrentPointSize);
119         float color[4];
120         color[0] = m_Color.x;
121         color[1] = m_Color.y;
122         color[2] = m_Color.z;
123         color[3] = m_fAlpha;
124 
125         glColor4fv(&color[0]);
126 
127         glBegin(GL_POINTS);
128             glVertex3fv(&m_Position.x);
129         glEnd();
130     }
131     else
132     {
133         //render using texture: (texture was already set active by the Render method of the particle system)
134         
135         float color[4];
136         color[0] = m_Color.x;
137         color[1] = m_Color.y;
138         color[2] = m_Color.z;
139         color[3] = m_fAlpha;
140         glColor4fv(&color[0]);
141 
142         SF3dVector RotatedX = m_ParentSystem->m_BillboardedX;
143         SF3dVector RotatedY = m_ParentSystem->m_BillboardedY;
144 
145 
146        //If spinning is switched on, rotate the particle now:
147         if (m_fSpinAngle > 0.0f)
148         {
149             RotatedX = m_ParentSystem->m_BillboardedX * cos(m_fSpinAngle) 
150                        + m_ParentSystem->m_BillboardedY * sin(m_fSpinAngle);
151             RotatedY = m_ParentSystem->m_BillboardedY * cos(m_fSpinAngle) 
152                        - m_ParentSystem->m_BillboardedX * sin(m_fSpinAngle);
153         }
154     
155         
156         //Render a quadrangle with the size m_fSize
157         SF3dVector coords = m_Position - (RotatedX*(0.5f*m_fSize))
158                                        - (RotatedY*(0.5f*m_fSize));
159         glBegin(GL_POLYGON);
160           glVertex3fv(&coords.x);
161           glTexCoord2f(0.0f,1.0f);
162           coords = coords + RotatedY * m_fSize;
163           glVertex3fv(&coords.x);
164           glTexCoord2f(1.0f,1.0f);
165           coords = coords + RotatedX * m_fSize;          
166           glVertex3fv(&coords.x);
167           glTexCoord2f(1.0f,0.0f);
168           coords = coords - RotatedY * m_fSize;
169           glVertex3fv(&coords.x);
170           glTexCoord2f(0.0f,0.0f);
171         glEnd();
172 
173 
174     }
175 
176 }
177 
178 /*************************************
179 
180 METHODS OF CCCParticleSytem class
181 
182 **************************************/
183 
184 
185 CCCParticleSystem::CCCParticleSystem()
186 {
187     //Set default values:
188     
189     //motion:
190     this->m_EmitterPosition = NULL_VECTOR;
191     this->m_MaxCreationDeviation = NULL_VECTOR;
192 
193     this->m_StandardEmitDirection = NULL_VECTOR;
194     this->m_MaxEmitDirectionDeviation = NULL_VECTOR;
195     this->m_fMaxEmitSpeed = 0.0f;
196     this->m_fMinEmitSpeed = 0.0f;
197 
198     this->m_AccelerationDirection = NULL_VECTOR;
199     this->m_fMaxAcceleration = 0.0f;
200     this->m_fMinAcceleration = 0.0f;
201 
202     this->m_fMinEmitSpinSpeed = 0.0f;
203     this->m_fMaxEmitSpinSpeed = 0.0f;
204     
205     this->m_fMaxSpinAcceleration = 0.0f;
206     this->m_fMinSpinAcceleration = 0.0f;
207 
208 
209     //look:
210     this->m_fMaxEmitAlpha = 0.0f;
211     this->m_fMinEmitAlpha = 0.0f;
212     this->m_fMaxDieAlpha = 1.0f;
213     this->m_fMinDieAlpha = 1.0f;
214 
215     this->m_MaxEmitColor = NULL_VECTOR;
216     this->m_MinEmitColor = NULL_VECTOR;
217     this->m_MaxDieColor = NULL_VECTOR;
218     this->m_MinDieColor = NULL_VECTOR;
219 
220     this->m_Texture = NULL;
221     this->m_bUseTexture = false;
222     this->m_iBillboarding = BILLBOARDING_NONE;
223 
224     //size:
225     this->m_fMaxEmitSize = 0.0f;
226     this->m_fMinEmitSize = 0.0f;
227     this->m_fMaxDieSize = 0.0f;
228     this->m_fMinDieSize = 0.0f;
229 
230 
231     //behavior:
232     this->m_bRecreateWhenDied = false;
233     
234     this->m_fMaxDieAge = 1.0f;
235     this->m_fMinDieAge = 1.0f;
236 
237     this->m_iMaxParticles = 0;  //array is not yet created
238     this->m_iParticlesInUse = 0;
239 
240     this->m_iParticlesCreatedPerSec = 0;
241     this->m_fCreationVariance = 0.0f;
242     this->m_bParticlesLeaveSystem = false;
243     this->m_pParticles = NULL;
244 
245 }
246 //*********************************************************
247 void CCCParticleSystem::SetEmitter(float x, float y, float z, float EmitterDeviationX,float EmitterDeviationY,float EmitterDeviationZ)
248 {
249     SetEmitter(F3dVector(x,y,z),F3dVector(EmitterDeviationX,EmitterDeviationY,EmitterDeviationZ));
250 }
251 
252 void CCCParticleSystem::SetEmitter(SF3dVector pos, SF3dVector dev)
253 {
254     m_EmitterPosition = pos;
255     m_MaxCreationDeviation = dev;
256 }
257 
258 void CCCParticleSystem::SetEmissionDirection(float x, float y, float z,
259                                              float MaxDeviationX, float MaxDeviationY, float MaxDeviationZ)
260 {
261     SetEmissionDirection(F3dVector(x,y,z),F3dVector(MaxDeviationX,MaxDeviationY,MaxDeviationZ));
262 }
263 
264 
265 void CCCParticleSystem::SetEmissionDirection(SF3dVector direction, SF3dVector Deviation)
266 {
267     m_StandardEmitDirection = direction;
268     m_MaxEmitDirectionDeviation = Deviation;
269 }
270 
271 
272 
273 
274 void CCCParticleSystem::SetSpinSpeed(float min, float max)
275 {
276     m_fMinEmitSpinSpeed = min;
277     m_fMaxEmitSpinSpeed = max;
278 }
279 
280 
281 void CCCParticleSystem::SetAcceleration(float x, float y, float z, float Min, float Max)
282 {
283     SetAcceleration(F3dVector(x,y,z),Min,Max);
284 }
285 
286 void CCCParticleSystem::SetAcceleration(SF3dVector acc, float Min, float Max)
287 {
288     m_AccelerationDirection = acc;
289     m_fMaxAcceleration = Max;
290     m_fMinAcceleration = Min;
291 }
292 
293 void CCCParticleSystem::SetCreationColor(float minr, float ming, float minb,
294                                             float maxr, float maxg, float maxb)
295 {
296     SetCreationColor(F3dVector(minr,ming,minb),F3dVector(maxr,maxg,maxb));
297 }
298 
299 void CCCParticleSystem::SetCreationColor(SF3dVector min, SF3dVector max)
300 {
301     m_MinEmitColor = min;
302     m_MaxEmitColor = max;
303 }
304 
305 
306 void CCCParticleSystem::SetDieColor    (float minr, float ming, float minb,
307                                         float maxr, float maxg, float maxb)
308 {
309     SetDieColor(F3dVector(minr,ming,minb),F3dVector(maxr,maxg,maxb));
310 }
311 
312 void CCCParticleSystem::SetDieColor        (SF3dVector min, SF3dVector max)
313 {
314     m_MinDieColor = min;
315     m_MaxDieColor = max;
316 }
317 
318 void CCCParticleSystem::SetAlphaValues (float MinEmit, float MaxEmit, float MinDie, float MaxDie)
319 {
320     m_fMinEmitAlpha = MinEmit;
321     m_fMaxEmitAlpha = MaxEmit;
322     m_fMinDieAlpha = MinDie;
323     m_fMaxDieAlpha = MaxDie;
324 }
325 
326 void CCCParticleSystem::SetSizeValues (float EmitMin, float EmitMax, float DieMin, float DieMax)
327 {
328     m_fMinEmitSize = EmitMin;
329     m_fMaxEmitSize = EmitMax;
330     m_fMinDieSize = DieMin;
331     m_fMaxDieSize = DieMax;
332 }
333 //*********************************************************
334 
335 bool CCCParticleSystem::Initialize(int iNumParticles)
336 {
337     this->m_pParticles = new CCCParticle[iNumParticles];
338     if (m_pParticles == NULL) 
339     {
340         return false;
341         this->m_iMaxParticles = 0;
342         this->m_iParticlesInUse = 0;
343     }
344 
345     this->m_iMaxParticles = iNumParticles;
346     this->m_iParticlesInUse = 0;
347 
348     //Set the status of each particle to DEAD
349     for (int i = 0; i < iNumParticles; i++)
350     {
351         m_pParticles[i].m_bIsAlive = false;
352     }
353 
354     return true;
355 
356 
357     
358 }
359 
360 
361 void CCCParticleSystem::UpdateSystem(float timePassed)
362 {
363     //We have to 
364     //  -update the particles (= move the particles, change their alpha, color, speed values)
365     //  -create new particles, if desired and there are "free" particles
366 
367     //First get the number of particles we want to create (randomly in a certain dimension (dependent of m_CreationVariance)
368     // 我们必须
369     //  - 更新粒子(=移动粒子,改变他们的阿尔法,颜色,速度值)
370     //  - 创造新粒子,如果需要有“免费”粒子
371     // 首先得到粒子的数量我们想创建(随机在某些维度(m_CreationVariance依赖)
372 
373     int iParticlesToCreate = (int) ((float)m_iParticlesCreatedPerSec
374                                            *timePassed
375                                            *(1.0f+m_fCreationVariance*(RANDOM_FLOAT-0.5f)));
376     
377 
378     //loop through the particles and update / create them
379     for (int i = 0; i < m_iMaxParticles; i++)
380     {
381         if (m_pParticles[i].m_bIsAlive)
382         {
383             m_pParticles[i].Update(timePassed);
384         }
385 
386         //Should we create the particle?
387         if (iParticlesToCreate > 0)
388         {
389             if (!m_pParticles[i].m_bIsAlive)
390             {
391                 m_pParticles[i].Initialize(this);
392                 //Update the particle: This has an effect, as if the particle would have
393                 //been emitted some milliseconds ago. This is very useful on slow PCs:
394                 //Especially if you simulate something like rain, then you could see that 
395                 //many particles are emitted at the same time (same "UpdateSystem" call),
396                 //if you would not call this function:                
397                 m_pParticles[i].Update(RANDOM_FLOAT*timePassed);  
398                 iParticlesToCreate--;
399             }
400         }
401 
402     }
403     
404 }
405 
406 bool CCCParticleSystem::LoadTextureFromFile(char * Filename)
407 {
408     //Create the texture pointer:
409     m_Texture = new COGLTexture;
410 
411     if (m_Texture == NULL) return false;
412 
413     if (!m_Texture->LoadFromTGA(Filename,NULL,true)) return false;  //pass NULL as 2. param (only required if you want to combine rgb and alpha maps)
414 
415     m_Texture->SetActive();
416     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
417     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
418     
419     
420     m_bUseTexture = true;
421 
422 
423     return true;
424 
425 }
426 
427 
428 void CCCParticleSystem::Render()
429 {
430     //the calling method must switch on texturing!
431 
432     if (m_bUseTexture)
433     {
434         m_Texture->SetActive();
435         //Calculate the "billboarding vectors" (the particles only store their positions, but we need quadrangles!)
436         switch (m_iBillboarding)
437         {
438         case BILLBOARDING_NONE:
439             {
440                 //independent from camera / view direction
441                 m_BillboardedX = F3dVector(1.0f,0.0f,0.0f);
442                 m_BillboardedY = F3dVector(0.0f,1.0f,0.0f);
443                 break;
444             }
445         case BILLBOARDING_PERPTOVIEWDIR:
446             {
447                 //Retrieve the up and right vector from the modelview matrix:
448                 float fModelviewMatrix[16];
449                 glGetFloatv(GL_MODELVIEW_MATRIX, fModelviewMatrix);
450 
451                 //Assign the x-Vector for billboarding:
452                 m_BillboardedX = F3dVector(fModelviewMatrix[0], fModelviewMatrix[4], fModelviewMatrix[8]);
453 
454                 //Assign the y-Vector for billboarding:
455                 m_BillboardedY = F3dVector(fModelviewMatrix[1], fModelviewMatrix[5], fModelviewMatrix[9]);
456                 break;
457             }
458         case BILLBOARDING_PERPTOVIEWDIR_BUTVERTICAL:
459             {
460                 //Retrieve the right vector from the modelview matrix:
461                 float fModelviewMatrix[16];
462                 glGetFloatv(GL_MODELVIEW_MATRIX, fModelviewMatrix);
463 
464                 //Assign the x-Vector for billboarding:
465                 m_BillboardedX = F3dVector(fModelviewMatrix[0], fModelviewMatrix[4], fModelviewMatrix[8]);
466 
467                 //Assign the y-Vector:
468                 m_BillboardedY = F3dVector(0.0f,1.0f,0.0f);                
469                 break;
470             }
471         }
472     }
473     else
474     {
475         glGetFloatv(GL_POINT_SIZE,&m_fCurrentPointSize);
476     }
477     for (int i = 0; i < m_iMaxParticles; i++)
478     {
479         if (m_pParticles[i].m_bIsAlive)
480             m_pParticles[i].Render();
481     }
482 }

 

 

 

 

 

Textures.h

 1 #ifndef INCLUDE_TEXTURES_H
 2 #define INCLUDE_TEXTURES_H
 3 
 4 #include <GL\glaux.h>
 5 
 6 typedef struct
 7 {
 8     GLubyte    *Data;
 9     GLuint    BitsPerPixel;    
10     GLuint    Width;
11     GLuint    Height;    
12 } STGAData;
13 
14 class COGLTexture
15 {
16 public:
17     
18     _AUX_RGBImageRec *Image;
19     
20     unsigned int GetID();
21     void LoadFromFile(char *filename);
22     bool LoadFromTGA(const char *filename, const char* AlphaMap, bool bMipMaps);
23     void SetActive();
24     GLuint GetWidth();
25     GLuint GetHeight();
26     GLuint type;
27     char * m_TexFilename;
28     char * m_AlphaFilename;
29 private:
30     GLuint Width, Height;
31     unsigned int ID;
32     GLuint BitsPerPixel;
33 
34 };
35 
36 #endif

Textures.cpp

  1 #include "Textures.h"
  2 #include <stdio.h>
  3 
  4 #define EIGHT_BIT_FORMAT GL_ALPHA
  5 
  6 //**************
  7 //Only for loading bmps:
  8 void COGLTexture::LoadFromFile(char *filename)
  9 {
 10     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
 11     glGenTextures(1,&ID); 
 12     glBindTexture( GL_TEXTURE_2D, ID);
 13     Image = auxDIBImageLoadA( (const char*) filename );
 14     Width = Image->sizeX;
 15     Height = Image->sizeY;
 16 
 17     gluBuild2DMipmaps(    GL_TEXTURE_2D, 
 18                         3, 
 19                         Image->sizeX,
 20                         Image->sizeY,
 21                         GL_RGB,
 22                         GL_UNSIGNED_BYTE,
 23                         Image->data);
 24     delete Image;
 25 }
 26 ////////////////////////////////////////////////////////////////////////////
 27 ///
 28 ///            CODE FROM NEHE'S "LESSON 25": Loading a TGA
 29 ///            (modified)
 30 ///
 31 ////////////////////////////////////////////////////////////////////////////
 32 bool LoadTGA(STGAData *TGAData, const char *filename)            // Loads A TGA File Into Memory
 33 {    
 34     GLubyte        TGAheader1[12]={0,0,2,0,0,0,0,0,0,0,0,0};    // Uncompressed TGA Header for RGB / RGBA
 35     GLubyte        TGAheader2[12]={0,1,1,0,0,0,1,24,0,0,0,0};    // Uncompressed TGA Header for Grayscale
 36     GLubyte        TGAcompare[12];                                // Used To Compare TGA Header
 37     GLubyte        header[6];                                    // First 6 Useful Bytes From The Header
 38     GLuint        bytesPerPixel;                                // Holds Number Of Bytes Per Pixel Used In The TGA File
 39     GLuint        imageSize;                                    // Used To Store The Image Size When Setting Aside Ram
 40     GLuint        type=GL_RGBA;                                // Set The Default GL Mode To RBGA (32 BPP)
 41 
 42     FILE *file = fopen(filename, "rb");                        // Open The TGA File
 43 
 44     if(    file==NULL)
 45         return false;                                        // Does File Exist?
 46     
 47     if (fread(TGAcompare,1,sizeof(TGAcompare),file)!=sizeof(TGAcompare) ||    // Are There 12 Bytes To Read?
 48         (    memcmp(TGAheader1,TGAcompare,sizeof(TGAheader1))!=0
 49           &&memcmp(TGAheader2,TGAcompare,sizeof(TGAheader2)) ) ||    // Does The Header Match What We Want?
 50         fread(header,1,sizeof(header),file)!=sizeof(header))                // If So Read Next 6 Header Bytes
 51     {
 52         if (file == NULL)                                    // Did The File Even Exist? *Added Jim Strong*
 53             return false;                                    // Return False
 54         else
 55         {
 56             //fclose(file);                                    // If Anything Failed, Close The File
 57             //return false;                                    // Return False
 58         }
 59     }
 60 
 61     TGAData->Width  = header[1] * 256 + header[0];            // Determine The TGA Width    (highbyte*256+lowbyte)
 62     TGAData->Height = header[3] * 256 + header[2];            // Determine The TGA Height    (highbyte*256+lowbyte)
 63     
 64      //I don't need to check here for the bpp. This will be done by
 65     //the calling function.
 66 
 67 
 68 
 69     TGAData->BitsPerPixel    = header[4];                            // Grab The TGA's Bits Per Pixel
 70     bytesPerPixel    = TGAData->BitsPerPixel/8;                        // Divide By 8 To Get The Bytes Per Pixel
 71     imageSize        = TGAData->Width*TGAData->Height*bytesPerPixel;    // Calculate The Memory Required For The TGA Data
 72 
 73     if (bytesPerPixel == 1) 
 74     {
 75         GLubyte        DummyData[768];    
 76         fread(DummyData,1,768,file);
 77     }
 78 
 79     TGAData->Data=(GLubyte *)malloc(imageSize);        // Reserve Memory To Hold The TGA Data
 80 
 81     if(    TGAData->Data==NULL ||                            // Does The Storage Memory Exist?
 82         fread(TGAData->Data, 1, imageSize, file)!=imageSize)    // Does The Image Size Match The Memory Reserved?
 83     {
 84         if(TGAData->Data!=NULL)                        // Was Image Data Loaded
 85             free(TGAData->Data);                        // If So, Release The Image Data
 86 
 87         fclose(file);                                        // Close The File
 88         return false;                                        // Return False
 89     }
 90 
 91     //I also do not swap Red and Blue values (this may only be done
 92     //with 24/32-bpp-images). Again it's the calling routine's task.
 93 
 94     fclose (file);                                            // Close The File
 95 
 96     return true;                                            
 97 }
 98 
 99 
100 
101 bool COGLTexture::LoadFromTGA(const char *filename,const char *AlphaMap, bool bMipMaps)
102 {
103     STGAData TGAData;            //Used to load the TGA-Texture
104     STGAData AlphaData;            //Used to load the Alpha-Map (if specified)
105     
106     GLubyte * RGBAData = NULL;    //RGBA Data. This can be the TGA file (if it contains 32bpp)
107                                 //or it is the combination of TGA and alpha map.
108                                 //If no alpha map is requested, it contains RGB data
109     GLuint RGBADataLength;        //Length of RGBA Data
110 
111     type = GL_RGB;
112 
113     char * LogStr;    
114     
115     if (filename != NULL)
116         {
117         if (!LoadTGA(&TGAData,filename))  //Load the texture file into memory
118         {
119             LogStr = new char[2000];
120             sprintf(LogStr,"Failed to load Texture (%s, %s). Reason: Failed to load RGB file.");
121             return false;    //failed. Return false.
122         }
123 
124 
125         if (TGAData.BitsPerPixel == 32)
126         {
127             type = GL_RGBA;  //TGA is a 32 bit file (i.e. it contains the alpha information)
128             RGBAData = TGAData.Data;    //The TGA Data can be used to create the texture
129             RGBADataLength = TGAData.Height*TGAData.Height*TGAData.BitsPerPixel/8;
130         }
131         Width = TGAData.Width;
132         Height = TGAData.Height;
133     }
134     else
135         type = EIGHT_BIT_FORMAT;
136 
137     if (type != GL_RGBA)    //ignore Alphamap if TGA has 32 bpp
138     {
139         if (AlphaMap != NULL)  //Alphamap specified
140         {//AlphaMap requested:
141             if (!LoadTGA(&AlphaData,AlphaMap))    //Load alpha map from file into memory
142             {
143                 LogStr = new char[2000];
144                 sprintf(LogStr,"Failed to load Texture (%s, %s). Reason: Failed to load alpha file.");
145 
146                 return false;        //failed. Return false.
147             }
148                         
149             //Check if the TGA has 24 bpp: (if it even exists)
150             if ((type == GL_RGB) && (TGAData.BitsPerPixel != 24))
151             {
152                 LogStr = new char[2000];
153                 sprintf(LogStr,"Failed to load Texture (%s, %s). Reason: RGB file not in 8 Bit format!");
154                 return false;
155             }
156             //Check if the Alpha Map has 8 bpp (grayscale):
157             if (AlphaData.BitsPerPixel != 8)    
158             {
159                 LogStr = new char[2000];
160                 sprintf(LogStr,"Failed to load Texture (%s, %s). Reason: Alpha file not in 8 bit format.");
161                 return false;
162             }
163             //Check if the size of AlphaData and TGAData is equal: (if the TGA exists)
164             if ((type == GL_RGB) && ((AlphaData.Width != TGAData.Width)||(AlphaData.Height != TGAData.Height)))
165             {
166                 LogStr = new char[2000];
167                 sprintf(LogStr,"Failed to load Texture (%s, %s). Reason: Alpha size does not eqal RGB size.");
168                 return false;
169             }
170     
171             if (type == GL_RGB)
172             {
173                 type = GL_RGBA;
174                 Width = TGAData.Width;
175                 Height = TGAData.Height;
176                 //Now comes the tricky part: Combine the TGAData and the alpha map.
177                 RGBADataLength = TGAData.Width*TGAData.Height*4; //4 = (24+8)/8; we need RGBA!
178                 RGBAData=(GLubyte *)malloc(RGBADataLength);
179                 //Check if malloc succeeded:
180                 if (RGBAData==NULL)
181                 {
182                     LogStr = new char[2000];
183                     sprintf(LogStr,"Failed to load Texture (%s, %s). Reason: Out of memory.");
184                     return false;
185                 }
186 
187                 //Loop. Copy three bytes of the TGA, then one byte of the alpha map. 
188                 //We do not swap R and B here, this is done at the end.
189                 for (GLuint i = 0; i < RGBADataLength/4; i++)
190                 {
191                     RGBAData[i*4+0] = TGAData.Data[i*3+0];
192                     RGBAData[i*4+1] = TGAData.Data[i*3+1];
193                     RGBAData[i*4+2] = TGAData.Data[i*3+2];
194                     RGBAData[i*4+3] = AlphaData.Data[i];
195                 }
196             }
197             else  //if type == EIGHT_BIT_FORMAT
198             {
199                 RGBADataLength = AlphaData.Width*AlphaData.Height;
200                 RGBAData=(GLubyte *)malloc(RGBADataLength);
201                 for (GLuint i = 0; i < RGBADataLength; i++)
202                 {
203                 
204                     RGBAData[i] = AlphaData.Data[i];
205 
206                 }
207                 type = GL_ALPHA;
208                 Width = AlphaData.Width;
209                 Height = AlphaData.Height;
210             }
211 
212         }
213         else                    //No Alphamap specified
214         {
215             //Store the TGAData in the local variables. This is RGB Data!
216             RGBAData = TGAData.Data;
217             RGBADataLength = TGAData.Height*TGAData.Height*TGAData.BitsPerPixel/8;
218         }
219     }
220     
221     //Now swap the R and B values. Be careful. Do not forget to check if we have RGBA or RGB data!
222     GLuint SwapC;    //Counter for swapping
223     int TempR;    //To Swap we need a temporary variable. This var here will store the temp R value.
224     
225     int BytesPerPixel = 3;
226     if (type == GL_RGBA)
227         BytesPerPixel = 4;
228     if (type == EIGHT_BIT_FORMAT)
229         BytesPerPixel = 1;
230 
231     if (BytesPerPixel > 1) 
232     for (SwapC = 0; SwapC < RGBADataLength/BytesPerPixel;SwapC++)  
233     {
234         TempR = RGBAData[SwapC*BytesPerPixel+0];
235         RGBAData[SwapC*BytesPerPixel+0] = RGBAData[SwapC*BytesPerPixel+2];
236         RGBAData[SwapC*BytesPerPixel+2] = TempR;
237     }
238 
239     
240 
241     if (bMipMaps)
242     {
243         glGenTextures(1,&ID); 
244         glBindTexture( GL_TEXTURE_2D, ID);
245         GLuint res = gluBuild2DMipmaps(    GL_TEXTURE_2D, 
246                             BytesPerPixel, //computed earlier,
247                             Width,
248                             Height,
249                             type,
250                             GL_UNSIGNED_BYTE,
251                             RGBAData);
252         if (res != 0)
253         {
254             return false;
255 
256         }
257     }
258     else
259     {
260         glGenTextures(1, &ID);                    // Generate OpenGL texture IDs
261         glBindTexture(GL_TEXTURE_2D, ID);            // Bind Our Texture
262         glTexImage2D(GL_TEXTURE_2D, 0, BytesPerPixel, Width,Height, 0, type, GL_UNSIGNED_BYTE, RGBAData);
263     }
264 
265     //Store the filenames:
266     if (filename == NULL)
267         m_TexFilename = NULL;
268     else
269     {
270         m_TexFilename = new char[strlen(filename)+2];
271         strcpy(m_TexFilename,filename);
272     }
273     if (AlphaMap == NULL)
274         m_AlphaFilename = NULL;
275     else
276     {
277         m_AlphaFilename = new char[strlen(AlphaMap)+2];
278         strcpy(m_AlphaFilename,AlphaMap);
279     }
280 
281 
282     return true;
283 }
284 
285 
286 void COGLTexture::SetActive()
287 {
288     glBindTexture( GL_TEXTURE_2D, ID);
289 }
290 
291 unsigned int COGLTexture::GetID()
292 {
293     return ID;
294 }
295 
296 GLuint COGLTexture::GetWidth()
297 {
298     return Width;
299 }
300 GLuint COGLTexture::GetHeight()
301 {
302     return Height;
303 }