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 |
|
---|
9 | D3DXVECTOR3 cameraPosition;
|
---|
10 | float time = 0;
|
---|
11 |
|
---|
12 | bool 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 |
|
---|
24 | bool particleSortDescend(Particle* p1, Particle* p2)
|
---|
25 | {
|
---|
26 | return particleSortAscend(p1, p2);
|
---|
27 | }
|
---|
28 |
|
---|
29 | double UnitRandom ()
|
---|
30 | {
|
---|
31 | return ((double)rand()) / RAND_MAX;
|
---|
32 | }
|
---|
33 |
|
---|
34 | double RangeRandom (double fLow, double fHigh)
|
---|
35 | {
|
---|
36 | return (fHigh-fLow)*UnitRandom() + fLow;
|
---|
37 | }
|
---|
38 |
|
---|
39 | double SymmetricRandom ()
|
---|
40 | {
|
---|
41 | return 2.0f * UnitRandom() - 1.0f;
|
---|
42 | }
|
---|
43 |
|
---|
44 |
|
---|
45 | ParticleSystem::ParticleSystem(void)
|
---|
46 | {
|
---|
47 | int frameCount = 0;
|
---|
48 | int maxParticleCount = 0;
|
---|
49 | int currentframe = -1;
|
---|
50 | allVertices = 0;
|
---|
51 | fireTemperature = 0.5;
|
---|
52 | }
|
---|
53 |
|
---|
54 | ParticleSystem::~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 |
|
---|
78 | void ParticleSystem::setCameraPosition(const D3DXVECTOR3& pos)
|
---|
79 | {
|
---|
80 | cameraPosition = pos;
|
---|
81 | }
|
---|
82 |
|
---|
83 | void 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 |
|
---|
125 | void 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 |
|
---|
209 | void 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 | }
|
---|
228 | void ParticleSystem::OnDestroyDevice()
|
---|
229 | {
|
---|
230 | SAFE_RELEASE( sbbEffect );
|
---|
231 | }
|
---|
232 |
|
---|
233 | void 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 |
|
---|
245 | void 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 |
|
---|
257 | void 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 |
|
---|
316 | void 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 |
|
---|
333 | void ParticleSystem::stepFrame()
|
---|
334 | {
|
---|
335 | //currentframe = 2; return;
|
---|
336 | currentframe++;
|
---|
337 | if(currentframe == animFrames.size())
|
---|
338 | currentframe = 0;
|
---|
339 | }
|
---|