1 /*
2      PLIB - A Suite of Portable Game Libraries
3      Copyright (C) 1998,2002  Steve Baker
4 
5      This library is free software; you can redistribute it and/or
6      modify it under the terms of the GNU Library General Public
7      License as published by the Free Software Foundation; either
8      version 2 of the License, or (at your option) any later version.
9 
10      This library is distributed in the hope that it will be useful,
11      but WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      Library General Public License for more details.
14 
15      You should have received a copy of the GNU Library General Public
16      License along with this library; if not, write to the Free Software
17      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
18 
19      For further information visit http://plib.sourceforge.net
20 
21 */
22 
23 #include "ssgAux.h"
24 
ssgaParticleSystem(int num,int initial_num,float _create_rate,int _ttf,float sz,float bsphere_size,ssgaParticleCreateFunc _particle_create,ssgaParticleUpdateFunc _particle_update,ssgaParticleDeleteFunc _particle_delete)25 ssgaParticleSystem::ssgaParticleSystem ( int num, int initial_num,
26                                  float _create_rate, int _ttf,
27                                  float sz, float bsphere_size,
28                                  ssgaParticleCreateFunc _particle_create,
29                                  ssgaParticleUpdateFunc _particle_update,
30                                  ssgaParticleDeleteFunc _particle_delete ) :
31          ssgVtxTable ( GL_QUADS,
32               new ssgVertexArray   ( num * 4, new sgVec3 [ num * 4 ] ),
33               new ssgNormalArray   ( num * 4, new sgVec3 [ num * 4 ] ),
34               new ssgTexCoordArray ( num * 4, new sgVec2 [ num * 4 ] ),
35               new ssgColourArray   ( num * 4, new sgVec4 [ num * 4 ] ) )
36 {
37   turn_to_face = _ttf ;
38   create_error = 0 ;
39   create_rate = _create_rate ;
40   particle_create = _particle_create ;
41   particle_update = _particle_update ;
42   particle_delete = _particle_delete ;
43 
44   size = sz ;
45 
46   num_particles = num ;
47   num_verts     = num * 4 ;
48 
49   getBSphere () -> setRadius ( bsphere_size ) ;
50   getBSphere () -> setCenter ( 0, 0, 0 ) ;
51 
52   particle = new ssgaParticle [ num ] ;
53 
54   int i ;
55 
56   for ( i = 0 ; i < num_verts ; i++ )
57   {
58     sgSetVec3  ( getNormal ( i ), 0, -1, 0 ) ;
59     sgSetVec4  ( getColour ( i ), 1, 1, 1, 1 ) ;
60     sgZeroVec3 ( getVertex ( i ) ) ;
61   }
62 
63   for ( i = 0 ; i < num_particles ; i++ )
64   {
65     sgSetVec2 ( getTexCoord ( i*4+0 ), 0, 0 ) ;
66     sgSetVec2 ( getTexCoord ( i*4+1 ), 1, 0 ) ;
67     sgSetVec2 ( getTexCoord ( i*4+2 ), 1, 1 ) ;
68     sgSetVec2 ( getTexCoord ( i*4+3 ), 0, 1 ) ;
69   }
70 
71   num_active = 0 ;
72 
73   if ( particle_create )
74     for ( i = 0 ; i < initial_num ; i++ )
75       (*particle_create) ( this, i, & particle [ i ] ) ;
76 }
77 
78 
draw_geometry()79 void ssgaParticleSystem::draw_geometry ()
80 {
81   sgVec3 nxny, xxny, xxyy, nxyy ;
82 
83   float sz = size / 2.0f ;
84 
85   if ( turn_to_face )
86   {
87     sgMat4 mat ;
88 
89     glGetFloatv ( GL_MODELVIEW_MATRIX, (float *) mat ) ;
90 
91     sgVec3 xx, yy ;
92 
93     sgSetVec3 ( xx, mat[0][0] * sz, mat[1][0] * sz, mat[2][0] * sz ) ;
94     sgSetVec3 ( yy, mat[0][1] * sz, mat[1][1] * sz, mat[2][1] * sz ) ;
95 
96     sgSetVec3 ( nxny, -xx[0]-yy[0], -xx[1]-yy[1], -xx[2]-yy[2] ) ;
97     sgSetVec3 ( nxyy, -xx[0]+yy[0], -xx[1]+yy[1], -xx[2]+yy[2] ) ;
98     sgSetVec3 ( xxny,  xx[0]-yy[0],  xx[1]-yy[1],  xx[2]-yy[2] ) ;
99     sgSetVec3 ( xxyy,  xx[0]+yy[0],  xx[1]+yy[1],  xx[2]+yy[2] ) ;
100   }
101   else
102   {
103     sgSetVec3 ( xxny ,  sz, 0, -sz ) ;
104     sgSetVec3 ( nxny , -sz, 0, -sz ) ;
105     sgSetVec3 ( nxyy , -sz, 0,  sz ) ;
106     sgSetVec3 ( xxyy,   sz, 0,  sz ) ;
107   }
108 
109   int j = 0 ;
110 
111   for ( int i = 0 ; i < num_particles ; i++ )
112   {
113     /* Make them disappear if not needed */
114 
115     if ( particle[i].time_to_live <= 0.0f )
116       continue ;
117 
118     sgCopyVec4 ( getColour ( j + 0 ), particle[i].col ) ;
119     sgCopyVec4 ( getColour ( j + 1 ), particle[i].col ) ;
120     sgCopyVec4 ( getColour ( j + 2 ), particle[i].col ) ;
121     sgCopyVec4 ( getColour ( j + 3 ), particle[i].col ) ;
122 
123     sgAddScaledVec3 ( getVertex ( j + 0 ), particle[i].pos,
124                                      nxny, particle[i].size ) ;
125     sgAddScaledVec3 ( getVertex ( j + 1 ), particle[i].pos,
126                                      xxny, particle[i].size ) ;
127     sgAddScaledVec3 ( getVertex ( j + 2 ), particle[i].pos,
128                                      xxyy, particle[i].size ) ;
129     sgAddScaledVec3 ( getVertex ( j + 3 ), particle[i].pos,
130                                      nxyy, particle[i].size ) ;
131 
132     j += 4 ;
133   }
134 
135   rawSetNumVertices ( j ) ; /* Avoid drawing more than 'j' vertices. */
136 
137   if ( j > 0 )
138   {
139     glDisable   ( GL_CULL_FACE ) ;
140     glDepthMask ( 0 ) ;
141 
142     ssgVtxTable::draw_geometry () ;
143 
144     glDepthMask ( 1 ) ;
145     glEnable ( GL_CULL_FACE ) ;
146   }
147 }
148 
149 
~ssgaParticleSystem()150 ssgaParticleSystem::~ssgaParticleSystem ()
151 {
152   if ( particle_delete )
153     for ( int i = 0 ; i < num_particles ; i++ )
154       if ( particle [ i ] . time_to_live >= 0.0 )
155   	(*particle_delete) ( this, i, & particle [ i ] ) ;
156 
157   delete [] particle ;
158 }
159 
160 
update(float t)161 void ssgaParticleSystem::update ( float t )
162 {
163   int i ;
164 
165   create_error += create_rate * t ;
166 
167   num_active = 0 ;
168 
169   /* Call the update routine for all the particles */
170 
171   if ( particle_update )
172   {
173     for ( i = 0 ; i < num_particles ; i++ )
174       if ( particle [ i ] . time_to_live > 0.0f )
175       {
176         particle [ i ] . update ( t ) ;
177         (*particle_update) ( t, this, i, & particle [ i ] ) ;
178       }
179   }
180   else
181     for ( i = 0 ; i < num_particles ; i++ )
182       if ( particle [ i ] . time_to_live > 0.0f )
183         particle [ i ] . update ( t ) ;
184 
185   /* Check for death of particles */
186 
187   for ( i = 0 ; i < num_particles ; i++ )
188     if ( particle [ i ] . time_to_live <= 0.0 )
189     {
190       if ( particle_delete )
191 	(*particle_delete) ( this, i, & particle [ i ] ) ;
192 
193       particle [ i ] . pos [ 2 ] = -1000000.0f ;
194 
195       if ( create_error >= 1.0f && particle_create )
196       {
197 	(*particle_create) ( this, i, & particle [ i ] ) ;
198 	create_error -= 1.0f ;
199       }
200     }
201     else
202       num_active++ ;
203 }
204 
205 
206