[3255] | 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 | }
|
---|