source: GTP/trunk/App/Demos/Illum/Standalone/explosion [DirectX]/ParticleSystem.cpp @ 1485

Revision 1485, 9.4 KB checked in by szirmay, 18 years ago (diff)
Line 
1#include "dxstdafx.h"
2#include ".\particlesystem.h"
3#include <fstream>
4#include <algorithm>
5
6
7#define D3DFVF_PARTICLEVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX2|D3DFVF_TEXCOORDSIZE4(0)|D3DFVF_TEXCOORDSIZE3(1))
8
9D3DXVECTOR3 cameraPosition;
10float time = 0;
11
12bool particleSortAscend(Particle* p1, Particle* p2)
13{
14        D3DXVECTOR3 t;
15        float dist1 = D3DXVec3Length(D3DXVec3Subtract(&t, &p1->position, &cameraPosition));
16        float dist2 = D3DXVec3Length(D3DXVec3Subtract(&t, &p2->position, &cameraPosition));
17
18        if (dist1 > dist2)
19                return true;
20       
21        return false;
22}
23
24bool particleSortDescend(Particle* p1, Particle* p2)
25{
26        return particleSortAscend(p1, p2);
27}
28
29double UnitRandom ()
30 {
31         return ((double)rand()) / RAND_MAX;
32 }
33   
34double RangeRandom (double fLow, double fHigh)
35 {
36     return (fHigh-fLow)*UnitRandom() + fLow;
37 }
38
39double SymmetricRandom ()
40 {
41        return 2.0f * UnitRandom() - 1.0f;
42 }
43
44
45ParticleSystem::ParticleSystem(void)
46{
47        int frameCount = 0;
48        int maxParticleCount = 0;       
49        int currentframe = -1;
50        allVertices = 0;
51        fireTemperature = 0.5;
52}
53
54ParticleSystem::~ParticleSystem(void)
55{
56        for(int i = 0; i < animFrames.size(); i++)
57        {
58                delete[] allVertices[i];
59                Frame* f = animFrames.at(i);
60                vector<Particle*>::iterator it;
61                for(it = f->begin(); it != f->end(); it++)
62                {
63                        Particle* p = *it;                     
64                        delete p;
65                }
66
67                f->clear();
68                delete f;
69               
70        }
71        animFrames.clear();
72
73       
74        delete[] allVertices;
75}
76
77
78void ParticleSystem::setCameraPosition(const D3DXVECTOR3& pos)
79{
80        cameraPosition = pos;
81}
82
83void ParticleSystem::addSystem(char* filename, bool fire, D3DCOLOR particleColor, float minSize, float maxSize)
84{
85        ifstream f;
86        f.open(filename, ios_base::in | ios_base::binary);
87
88        int frameCount;
89        f.read((char*) &frameCount, sizeof(int));
90
91        this->frameCount = frameCount;
92       
93        for(int frame = 0; frame < frameCount; frame++)
94        {
95                int particleCount;
96                f.read((char*) &particleCount, sizeof(int));
97
98                if(animFrames.size() < frame + 1)
99                        animFrames.push_back(new Frame());
100                Frame* thisFrame = animFrames.at(frame);
101
102                maxParticleCount += particleCount;
103
104                for(int p = 0; p < particleCount; p++)
105                {
106                        float* positions = new float[3];
107                        f.read((char*) positions, 3 * sizeof(float));
108
109                        float size=RangeRandom(minSize, maxSize) ;
110
111                        Particle* particle = new Particle();
112                        particle->color = particleColor;
113                        particle->position = D3DXVECTOR3(positions[0], positions[1], positions[2]);
114                        particle->size = maxSize;
115                        particle->fire = fire;
116
117                        delete positions;
118
119                        thisFrame->push_back(particle);
120                }
121        }
122       
123}
124
125void ParticleSystem::initBuffers()
126{
127       
128
129        if(allVertices == 0)
130        {
131                allVertices = new vertexFormat*[frameCount];
132                for(int i = 0; i < frameCount; i++)
133                        allVertices[i] = 0;
134        }
135
136        //sort particles
137        Frame* f = animFrames.at(currentframe);
138       
139        sort(f->begin(), f->end(), particleSortDescend);
140
141
142        //create buffer
143        float blockSize = 0.35;
144
145        int c = 0;
146
147        int i = currentframe;   
148               
149        int particleCount = f->size();
150       
151        if(allVertices[currentframe] == 0)
152                        allVertices[currentframe] = new vertexFormat[particleCount * 6];
153
154        for(int j = 0; j < particleCount; j++)
155        {
156                Particle* p = f->at(j);                 
157               
158                //TexCoords u1, v1
159                allVertices[i][6 * j].u1 = -1;
160                allVertices[i][6 * j].v1 = -1;
161                allVertices[i][6 * j + 1].u1 = 1;
162                allVertices[i][6 * j + 1].v1 = 1;
163                allVertices[i][6 * j + 2].u1 = -1;
164                allVertices[i][6 * j + 2].v1 = 1;
165                allVertices[i][6 * j + 3].u1 = -1;
166                allVertices[i][6 * j + 3].v1 = -1;
167                allVertices[i][6 * j + 4].u1 = 1;
168                allVertices[i][6 * j + 4].v1 = -1;
169                allVertices[i][6 * j + 5].u1 = 1;
170                allVertices[i][6 * j + 5].v1 = 1;
171
172                float randD = UnitRandom();
173                //vertex positions, radius and fire
174                for(int v = 0; v < 6; v++)
175                {
176                        allVertices[i][6 * j + v].color = p->color;
177                        allVertices[i][6 * j + v].x = p->position.x;
178                        allVertices[i][6 * j + v].y = p->position.y;
179                        allVertices[i][6 * j + v].z = -p->position.z;
180                        allVertices[i][6 * j + v].s1 = p->size;
181                        allVertices[i][6 * j + v].t1 = p->fire;
182                        allVertices[i][6 * j + v].s2 = randD;
183                }
184               
185
186                float randX, randY;
187                randX = RangeRandom(blockSize, 1 - blockSize);
188                randY = RangeRandom(blockSize, 1 - blockSize);
189               
190                //TexCoords u2, v2 : random block coordinate
191                allVertices[i][6 * j].u2 = randX - blockSize;
192                allVertices[i][6 * j].v2 = randY - blockSize;
193                allVertices[i][6 * j + 1].u2 = randX + blockSize;
194                allVertices[i][6 * j + 1].v2 = randY + blockSize;
195                allVertices[i][6 * j + 2].u2 = randX - blockSize;
196                allVertices[i][6 * j + 2].v2 = randY + blockSize;
197                allVertices[i][6 * j + 3].u2 = randX - blockSize;
198                allVertices[i][6 * j + 3].v2 = randY - blockSize;
199                allVertices[i][6 * j + 4].u2 = randX + blockSize;
200                allVertices[i][6 * j + 4].v2 = randY - blockSize;
201                allVertices[i][6 * j + 5].u2 = randX + blockSize;
202                allVertices[i][6 * j + 5].v2 = randY + blockSize;       
203               
204                c += 6;
205        }
206       
207}
208
209void ParticleSystem::OnCreateDevice( IDirect3DDevice9* pd3dDevice)
210{
211        this->pd3dDevice = pd3dDevice;
212
213        ID3DXBuffer* errBuff = NULL;
214        if( FAILED(D3DXCreateEffectFromFile( pd3dDevice, L"Media//Shaders/Explosion.fx", NULL, NULL, NULL,
215                NULL, &sbbEffect, &errBuff )))
216        {
217                int BufSize = errBuff->GetBufferSize();
218
219                // displaying error message of arbitrary length
220                wchar_t* wbuf = new wchar_t[BufSize];
221                mbstowcs( wbuf, (const char*)errBuff->GetBufferPointer(), BufSize );
222                MessageBox(NULL, wbuf, L".fx Compilation Error", MB_ICONERROR);         // show error message
223
224                delete wbuf;
225                exit(-1);
226        }
227}
228void ParticleSystem::OnDestroyDevice()
229{
230        SAFE_RELEASE( sbbEffect );
231}
232
233void ParticleSystem::OnResetDevice()
234{
235        if( sbbEffect )
236        sbbEffect->OnResetDevice();
237
238        D3DXCreateTextureFromFile( pd3dDevice, FIRE_ALPHA_PATH, &fireAlpha );
239        D3DXCreateTextureFromFile( pd3dDevice, SMOKE_ALPHA_PATH, &smokeAlpha );
240        D3DXCreateTextureFromFile( pd3dDevice, PLANCK_COLOR_PATH, &planckColors );
241        D3DXCreateTextureFromFile( pd3dDevice, NOISE_TEXTURE_PATH, &perlinNoise );
242        D3DXCreateTextureFromFile( pd3dDevice, GRAD_TEXTURE_PATH, &gradTex );
243}
244
245void ParticleSystem::OnLostDevice()
246{
247        if( sbbEffect )
248        sbbEffect->OnLostDevice();
249
250        SAFE_RELEASE(fireAlpha);
251        SAFE_RELEASE(smokeAlpha);
252        SAFE_RELEASE(planckColors);
253        SAFE_RELEASE(perlinNoise);
254        SAFE_RELEASE(gradTex);
255}
256
257void ParticleSystem::draw(IDirect3DTexture9* sceneTexture, IDirect3DTexture9* phaseTexture)
258{
259        initBuffers();
260        time += 0.001;
261        if(time > frameCount) time = 0;
262
263        V( sbbEffect->SetTexture( "FireAlpha", fireAlpha ) );
264        V( sbbEffect->SetTexture( "SmokeAlpha", smokeAlpha ) );
265        V( sbbEffect->SetTexture( "PlanckColors", planckColors ) );
266        V( sbbEffect->SetTexture( "NoiseTexture", perlinNoise ) );
267        V( sbbEffect->SetTexture( "SceneDepth", sceneTexture ) );
268        V( sbbEffect->SetTexture( "gradTexture", gradTex ) );
269        V( sbbEffect->SetTexture( "phaseTexture", phaseTexture ) );
270        fireTemperature = (params->Get(fFireColor) * 0.8);
271        V( sbbEffect->SetFloat( "fireTemperature", fireTemperature ) );
272        float densities[3];
273        densities[0] = params->Get(fFireIntensity) * 3;
274        densities[1] = params->Get(fSmokeIntensity) * 3;
275        densities[2] = params->Get(fDustIntensity) * 3;
276        V( sbbEffect->SetFloatArray("densityFactor", densities, 3) );
277        float lPos[] = {0,0,0};
278        V( sbbEffect->SetFloatArray("mLightPos", lPos, 3) );
279        V( sbbEffect->SetFloat( "time", time / (float)frameCount ) );
280        float halfPixel[] = { 1.0 / screenWidth * 0.5,
281                                                  1.0 / screenHeight * 0.5};
282        V( sbbEffect->SetFloatArray("halfPixel", halfPixel, 2) );
283        V( sbbEffect->CommitChanges() );
284
285        UINT p;
286        sbbEffect->SetTechnique("SBB");
287        sbbEffect->Begin(&p, 0 );
288        sbbEffect->BeginPass( 0 );     
289       
290                V(pd3dDevice->SetFVF(D3DFVF_PARTICLEVERTEX));
291               
292                Frame* f = animFrames.at(currentframe);
293                int particlecount = f->size();
294                pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
295                pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
296                pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
297                //pd3dDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
298                //pd3dDevice->SetRenderState(D3DRS_SRCBLENDALPHA, D3DBLEND_ONE);
299                //pd3dDevice->SetRenderState(D3DRS_DESTBLENDALPHA, D3DBLEND_ONE);
300                pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
301                pd3dDevice->SetRenderState(D3DRS_ZENABLE, FALSE);
302               
303                V(pd3dDevice->DrawPrimitiveUP(D3DPT_TRIANGLELIST,
304                                                                        particlecount * 2,
305                                                                        allVertices[currentframe],
306                                                                        sizeof(vertexFormat)));
307
308                pd3dDevice->SetRenderState(D3DRS_ZENABLE, TRUE);
309                pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
310                pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
311
312        sbbEffect->EndPass();
313        sbbEffect->End();
314}
315
316void ParticleSystem::SetWorldViewProj(D3DXMATRIXA16& mWorld, D3DXMATRIXA16& mView, D3DXMATRIXA16& mProj )
317{
318        D3DXMATRIXA16 mWorldView = mWorld * mView;
319        D3DXMATRIXA16 mWorldViewProjection = mWorldView * mProj;
320
321        D3DXMATRIXA16 mWorldViewI, mWorldViewIT;
322        D3DXMatrixInverse(&mWorldViewI, NULL, &mWorldView);
323        D3DXMatrixTranspose(&mWorldViewIT, &mWorldViewI);
324
325        V( sbbEffect->SetMatrix( "WorldView", &mWorldView ) );
326        V( sbbEffect->SetMatrix( "WorldViewIT", &mWorldViewIT ) );
327        V( sbbEffect->SetMatrix( "WorldViewProj", &mWorldViewProjection ) );
328        V( sbbEffect->SetMatrix( "Proj", &mProj ) );   
329       
330        V( sbbEffect->CommitChanges() );
331}
332
333void ParticleSystem::stepFrame()
334{
335        //currentframe = 2; return;
336        currentframe++;
337        if(currentframe == animFrames.size())
338                currentframe = 0;
339}
Note: See TracBrowser for help on using the repository browser.