source: GTP/trunk/App/Demos/Illum/pathmap/PathMapEffect.cpp @ 2197

Revision 2197, 39.2 KB checked in by szirmay, 17 years ago (diff)
Line 
1#include "dxstdafx.h"
2#include ".\pathmapeffect.h"
3#include "Material.hpp"
4#include "TexturedMaterial.h"
5#include "WoodMaterial.hpp"
6#include "TriangleMesh.h"
7#include "Transformed.h"
8#include "Entity.h"
9#include "DepthRenderStrategy.h"
10#include "FinalCompositionRenderStrategy.h"
11#include "SubEntity.h"
12#include "Entity.h"
13#include "Mesh.h"
14#include "L.h"
15#include "shlwapi.h"
16#include <queue>
17#include <fstream>
18
19#define MAXNCLUSTERS 512
20//#define GENERATE_PATH_MAPS
21
22//! D3D vector-matrix multiplication
23D3DVECTOR operator *(const D3DVECTOR& v, const D3DMATRIX& m)
24{
25        D3DVECTOR r;
26        r.x = v.x * m._11 + v.y * m._21 + v.z * m._31 + m._41;
27        r.y = v.x * m._12 + v.y * m._22 + v.z * m._32 + m._42;
28        r.z = v.x * m._13 + v.y * m._23 + v.z * m._33 + m._43;
29        float h = v.x * m._14 + v.y * m._24 + v.z * m._34 + m._44;
30        if(h > 0.00001f || h < 0.00001f)
31        {
32                r.x /= h;
33                r.y /= h;
34                r.z /= h;
35        }
36        return r;
37}
38
39//! method name strings to be displayed on screen
40const wchar_t* PathMapEffect::Method::methodNames[10] =
41{
42        L"PRM",
43        L"PRM texture",
44        L"_",
45        L"_"
46        , NULL, NULL, NULL, NULL, NULL, NULL
47};
48
49//! method constants
50const PathMapEffect::Method PathMapEffect::Method::PRM(0);
51const PathMapEffect::Method PathMapEffect::Method::SHOWTEX(1);
52const PathMapEffect::Method PathMapEffect::Method::LAST(2);
53
54//! constructor
55PathMapEffect::PathMapEffect(LPDIRECT3DDEVICE9 device,
56                char* prmDirectory,
57                char* meshDirectory,
58                char* mediaDirectory,
59                char* levelFileName,
60                char* materialFileName,
61                bool segmentMeshes,
62                bool computePRM,
63                unsigned int nEntryPoints,
64                unsigned int nClusters,
65                unsigned int depthMapResolution
66                )
67:method(Method::PRM)
68{
69        testClusterId = 0;
70
71        NRADIONS = 4096 * (nEntryPoints / 4096);
72        NCLUSTERS = nClusters;
73        DEPTHMAPRES     = depthMapResolution;
74        this->SEGMENTMESHES = segmentMeshes;
75
76        weights = new float[NCLUSTERS];
77        clusterLenghts = new unsigned int[NCLUSTERS];
78
79        clusterSweepCurrentIndex = 0;
80
81        rayId = 1;
82        this->device = device;
83
84        //first person camera allows more freedom of movement
85        camera = new CFirstPersonCamera();
86        lightCamera = new CFirstPersonCamera();
87
88        HRESULT hr;
89        DWORD effectCompileFlag=0;
90       
91        LPD3DXBUFFER compilationErrors;
92        if(FAILED(
93                hr =
94                        D3DXCreateEffectFromFile(
95                                device,
96                                L"pathMap.fx",
97                                NULL,
98                                NULL,
99                                0,
100                                NULL,
101                                &effect,
102                                &compilationErrors) )){
103                MessageBoxA( NULL, (LPSTR)compilationErrors->GetBufferPointer(), "Failed to load effect file!", MB_OK);
104                exit(-1);
105        }
106
107        //store buffers so we can reset them after rendering to texture render targets
108        device->GetRenderTarget(0, &frameColorBuffer);
109        device->GetDepthStencilSurface(&frameDepthStencilBuffer);
110       
111        wcscpy(this->mediaDirectory, L::l+mediaDirectory);
112        wcscpy(this->meshDirectory, L::l+meshDirectory);
113        wcscpy(this->prmDirectory, L::l+prmDirectory);
114
115        //load empty texture
116        wcscpy(this->levelFileName, L::l+mediaDirectory);
117        wcscat(this->levelFileName, L"\\");
118        wcscat(this->levelFileName, L::l+levelFileName);
119
120        wcscpy(this->materialFileName, L::l+mediaDirectory);
121        wcscat(this->materialFileName, L"\\");
122        wcscat(this->materialFileName, L::l+materialFileName);
123
124        wchar_t emptyTextureName[256];
125        wcscpy(emptyTextureName, L::l+mediaDirectory);
126        wcscat(emptyTextureName, L"\\");
127        wcscat(emptyTextureName, L"empty.bmp");
128
129        D3DXCreateTextureFromFile(device, emptyTextureName, &emptyTexture);
130
131        //set up a scene
132
133        xMaterials = XMLNode::openFileHelper(this->materialFileName, L"materials");
134//      loadScene("media\\space.txt");
135        loadScene(LC::c-this->levelFileName);
136
137//      loadMesh( L"media\\fighter.x", 0, "", 1);
138
139        //compute the surface area of the complete geometry. useful for random sampling.
140        sumSurfaceArea = 0.0;
141        std::vector<Entity*>::iterator entityIterator = entities.begin();
142        while(entityIterator != entities.end())
143        {
144                sumSurfaceArea += (*entityIterator)->getSurfaceArea();
145                entityIterator++;
146        }
147
148        //initialize camera
149        camera->SetViewParams( &D3DXVECTOR3(0.0f, 0.0f, 4.0f), &D3DXVECTOR3(0.0f, 0.0f, 0.0f));
150        D3DSURFACE_DESC fbdesc;
151        frameColorBuffer->GetDesc(&fbdesc);
152        camera->SetProjParams( D3DX_PI/2, (float)fbdesc.Width / fbdesc.Height, 0.1f, 300.0f );
153
154        //set up spotlight
155        lightCamera->SetViewParams( &D3DXVECTOR3(5.0f, 0.0f, 0.0f), &D3DXVECTOR3(0.0f, 0.0f, 0.0f));
156        lightCamera->SetProjParams( D3DX_PI/1.9, 1.0f, 0.1f, 300.0f );
157
158        //create ray tracing kd-tree containing ray-traceable versions of entities
159        {
160                std::vector<Intersectable*> rayTraceEntities;
161                std::vector<Entity*>::iterator entityIterator = entities.begin();
162                while(entityIterator != entities.end())
163                {
164                        (*entityIterator)->gatherRayTraceEntities(rayTraceEntities);
165                        entityIterator++;
166                }
167                Intersectable** objs = (Intersectable**)&*rayTraceEntities.begin();
168                kdtree = new KDTree(objs, rayTraceEntities.size());
169        }
170
171        //create dummy render target texture for depth map rendering
172        device->CreateTexture(DEPTHMAPRES, DEPTHMAPRES, 1, D3DUSAGE_RENDERTARGET, D3DFMT_R32F, D3DPOOL_DEFAULT, &fakeTexture, NULL);
173        fakeTexture->GetSurfaceLevel(0, &fakeSurface);
174
175        //create a depthstencil texture for depth map rendering
176        device->CreateTexture(DEPTHMAPRES, DEPTHMAPRES, 1,
177                D3DUSAGE_DEPTHSTENCIL, D3DFMT_D24X8, D3DPOOL_DEFAULT, &depthMapTexture, NULL);
178        depthMapTexture->GetSurfaceLevel(0, &depthMapDepthStencilBuffer);
179
180        if(computePRM)
181                precompute();
182        else
183                loadPathMaps();
184
185        if(computePRM || segmentMeshes)
186                saveScene("processedMeshes\\processed.level");
187
188        //create a texture for radion data (will be used for weight computations on the GPU)
189        device->CreateTexture(2 * NRADIONS / 4096, 4096, 1, 0, D3DFMT_A32B32G32R32F, D3DPOOL_DEFAULT, &radionTexture, NULL);
190        radionTexture->GetSurfaceLevel(0, &radionSurface);
191
192        //fill texture with data
193        uploadRadions();
194
195        //create weights render target
196        device->CreateTexture(4096, NRADIONS / 4096, 1, D3DUSAGE_RENDERTARGET, D3DFMT_R32F, D3DPOOL_DEFAULT, &weightsTexture, NULL);
197        weightsTexture->GetSurfaceLevel(0, &weightsSurface);
198
199        //create a sytem memory duplicate of the weights render target to be able to read back weights data
200        device->CreateTexture(4096, NRADIONS / 4096, 1, 0, D3DFMT_R32F, D3DPOOL_SYSTEMMEM, &sysMemWeightsTexture, NULL);
201        sysMemWeightsTexture->GetSurfaceLevel(0, &sysMemWeightsSurface);
202
203        //create a vertex buffer to be able to visualize entry radion positions
204        device->CreateVertexBuffer(NRADIONS * sizeof(float) * 6, D3DUSAGE_WRITEONLY, D3DFVF_XYZ | D3DFVF_NORMAL, D3DPOOL_DEFAULT,
205                &starterVertexBuffer, NULL);
206        void* pData;
207        starterVertexBuffer->Lock(0, 0, &pData, 0);
208        fillRadionPosArray(pData);
209        starterVertexBuffer->Unlock();
210
211        if(computePRM)
212                savePathMaps();
213}
214
215PathMapEffect::~PathMapEffect(void)
216{
217        delete weights;
218        delete clusterLenghts;
219
220        //release all resources allocated in the constructor
221        starterVertexBuffer->Release();
222
223        depthMapTexture->Release();
224        depthMapDepthStencilBuffer->Release();
225        fakeTexture->Release();
226        fakeSurface->Release();
227
228        sysMemWeightsTexture->Release();
229        sysMemWeightsSurface->Release();
230        weightsTexture->Release();
231        weightsSurface->Release();
232        radionTexture->Release();
233        radionSurface->Release();
234
235        delete kdtree;
236        emptyTexture->Release();
237        releaseTextures();
238        releaseMeshes();
239        releaseEntities();
240
241        frameColorBuffer->Release();
242        frameDepthStencilBuffer->Release();
243
244        effect->Release();
245        delete camera;
246        delete lightCamera;
247}
248
249void PathMapEffect::loadMesh(DWORD fileType, LPCWSTR fileName, LPCWSTR ogreName, int prmAtlasSize, const char* name, int dividePcs, bool generateUV, bool generateTBN)
250{
251        wchar_t mFileName[512];
252        wcscpy(mFileName, this->mediaDirectory);
253        wcscat(mFileName, L"\\");
254        wcscat(mFileName, fileName);
255        Mesh* mesh = new Mesh(this, fileType, mFileName, ogreName, prmAtlasSize, name, dividePcs, generateUV, generateTBN);
256        meshes.push_back(mesh);
257}
258
259LPDIRECT3DTEXTURE9 PathMapEffect::loadTexture(LPCWSTR fileName, Material** rayTraceMaterial)
260{
261        if(fileName == NULL || wcscmp(fileName, L"") == 0)
262                return NULL;
263        int texIndex = 0;
264        std::vector<wchar_t*>::iterator nameIterator = materialTextureFileNames.begin();
265        while(nameIterator != materialTextureFileNames.end())
266        {
267                if(wcscmp( *nameIterator, fileName) == 0)
268                {
269                        *rayTraceMaterial = rayTraceMaterials.at(texIndex);
270                        return materialTextures.at(texIndex);
271                }
272                nameIterator++;
273                texIndex++;
274        }
275        wchar_t* mediaFileName = new wchar_t[wcslen(fileName) + 64];
276        //we assume the x file is the media folder
277        wcscpy(mediaFileName, this->mediaDirectory);
278        wcscat(mediaFileName, L"\\");
279        wcscat(mediaFileName, fileName);
280        LPDIRECT3DTEXTURE9 tex;
281
282        D3DXIMAGE_INFO bobo;
283        if(S_OK !=
284                D3DXCreateTextureFromFileEx(device, mediaFileName, D3DX_DEFAULT, D3DX_DEFAULT, 1, 0,
285                D3DFMT_FROM_FILE, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, &bobo, NULL, &tex
286                ))
287        {
288                 MessageBox(NULL, mediaFileName, L"Could not load texture file!", MB_OK);
289                 return NULL;
290        }
291
292        delete mediaFileName;
293
294        materialTextures.push_back(tex);
295        wchar_t* storedName = new wchar_t[wcslen(fileName)+1];
296        wcscpy(storedName, fileName);
297        materialTextureFileNames.push_back(storedName);
298
299        if(rayTraceMaterial != NULL)
300        {
301                D3DLOCKED_RECT lrect;
302                HRESULT hr = tex->LockRect(0, &lrect, NULL, D3DLOCK_READONLY);
303                LPDIRECT3DSURFACE9 texsurf;
304                tex->GetSurfaceLevel(0, &texsurf);
305                D3DSURFACE_DESC desc;
306                texsurf->GetDesc(&desc);
307                *rayTraceMaterial = new TexturedMaterial(lrect.pBits, lrect.Pitch, desc.Width);
308                texsurf->Release();
309                tex->UnlockRect(0);
310        }
311        rayTraceMaterials.push_back(*rayTraceMaterial);
312
313        return tex;
314}
315
316void PathMapEffect::releaseTextures()
317{
318        std::vector<LPDIRECT3DTEXTURE9>::iterator i = materialTextures.begin();
319        while(i != materialTextures.end())
320        {
321                (*i)->Release();
322                i++;
323        }
324
325        std::vector<Material*>::iterator z = rayTraceMaterials.begin();
326        while(z != rayTraceMaterials.end())
327        {
328                delete (*z);
329                z++;
330        }
331
332        std::vector<wchar_t*>::iterator c = materialTextureFileNames.begin();
333        while(c != materialTextureFileNames.end())
334        {
335                delete [] (*c);
336                c++;
337        }
338}
339
340void PathMapEffect::releaseMeshes()
341{
342        std::vector<Mesh*>::iterator i = meshes.begin();
343        while(i != meshes.end())
344        {
345                delete *i;
346                i++;
347        }
348}
349
350void PathMapEffect::renderWithPRM()
351{
352        // 1. pass: render depth
353        DepthRenderStrategy depthRenderStrategy(this);
354
355        depthRenderStrategy.camera = *lightCamera;
356        renderScene(depthRenderStrategy);
357
358        // 2. pass: compute weights
359
360        // simple parallel computation for all pixels: no 3D, depth, shadows, only a full-texture quad
361        HRESULT hr = device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
362        hr = device->SetRenderState(D3DRS_STENCILENABLE, false);
363        hr = device->SetRenderTarget(0,weightsSurface);
364        hr = device->SetDepthStencilSurface(NULL);
365        D3DXVECTOR3 lightPos = *lightCamera->GetEyePt();
366        D3DXVECTOR3 lightDir = *lightCamera->GetWorldAhead();
367        lightDir /= D3DXVec3Length( &lightDir );
368        float ffl = parameters->Get(fLightScale) * 10.0f;
369        D3DXVECTOR3 lightPower(ffl, ffl, ffl);
370
371        device->Clear( 0, NULL, D3DCLEAR_TARGET,        D3DCOLOR_XRGB(0,0,0), 1.0f, 0 );
372
373        if( SUCCEEDED( device->BeginScene() ) ){
374                if( effect != NULL ){
375                        D3DXHANDLE hTechnique = NULL;
376                        hTechnique = effect->GetTechniqueByName((LPSTR)"ComputeWeights");
377                        if(hTechnique==NULL){
378                                return;
379                        }
380                        effect->SetTechnique( hTechnique );
381
382                        UINT nPasses = 0;
383                        effect->Begin( &nPasses, 0 );
384                        for(UINT j=0;j<nPasses;j++){
385                                effect->BeginPass(j);
386                                hr = effect->SetTexture("radions", radionTexture);
387                                static float opttme[9] = {0.5f, 0.0f, 0.0f,
388                                                                                0.0f, -0.5f, 0.0f,
389                                                                                0.5f + (0.5f / DEPTHMAPRES), 0.5f + (0.5f / DEPTHMAPRES), 1.0f};
390
391                                //set global params
392                                effect->SetFloatArray("occProjToTexMatrix", opttme, 9);
393                                effect->SetMatrix("occWorldToProjMatrix", &(*lightCamera->GetViewMatrix() * *lightCamera->GetProjMatrix()));
394
395                                effect->SetTexture("depthMap", depthMapTexture);
396                                hr = effect->SetInt("nRadionColumns", NRADIONS / 4096);
397                                hr = effect->SetFloatArray("lightPower", (float*)&lightPower, 3);
398                                hr = effect->SetFloatArray("lightPos", (float*)&lightPos, 3);
399                                hr = effect->SetFloatArray("lightDir", (float*)&lightDir, 3);
400                                effect->CommitChanges();
401                                renderFullScreen();
402                                effect->EndPass();
403                        }
404                        effect->End();
405                }
406                device->EndScene();
407        }
408
409        // read the weights back
410
411        D3DLOCKED_RECT rData;
412        hr = device->GetRenderTargetData(weightsSurface, sysMemWeightsSurface);
413        hr =  sysMemWeightsSurface->LockRect(&rData, NULL, D3DLOCK_READONLY);
414        float* allEntryWeights = (float*)rData.pBits;
415
416        // average weights per cluster
417        float sumWeightsAll = 0.0;
418        unsigned int iRadion = 0;
419        for(int iCluster=0; iCluster < NCLUSTERS; iCluster++)
420        {
421                weights[iCluster] = 0.0;
422                float clusterrad = 0.0;
423                for(int clusterSummer=0; clusterSummer < clusterLenghts[iCluster]; clusterSummer++, iRadion++)
424                {
425                        float radrad = bushStarters[iRadion].radiance.sum();
426                        weights[iCluster] += allEntryWeights[iRadion] * radrad;
427                        clusterrad += radrad;
428                }
429                if(clusterrad > 0.01)
430                        weights[iCluster] /= clusterrad; //(double)clusterLenghts[iCluster];
431                else
432                        weights[iCluster] = 0.0f;
433//              if(iCluster != TEST_CLUST)
434//                      weights[iCluster] = 0.0;
435//              if(weights[iCluster] > 0.005)
436//                      weights[iCluster] = 0.005;
437                sumWeightsAll += weights[iCluster];
438        }
439        sysMemWeightsSurface->UnlockRect();
440
441        // use backface culling, depth test
442        hr = device->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
443        hr = device->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
444
445/*      for(int testi=0; testi < NCLUSTERS; testi++)
446                weights[testi] = 0.000;
447        weights[testClusterId] = 0.05;*/
448
449        // 3. pass: render scene using weights to combine PRM texture atlases
450
451        FinalCompositionRenderStrategy finalCompositionRenderStrategy(this);
452        finalCompositionRenderStrategy.lightDir = lightDir;
453        finalCompositionRenderStrategy.lightPos = lightPos;
454        finalCompositionRenderStrategy.lightPower = lightPower;
455
456        renderScene(finalCompositionRenderStrategy);
457
458
459/*      if(!parameters->Get(bLookFromLight))
460        if( SUCCEEDED( device->BeginScene() ) )
461        {
462                effect->SetTechnique("torch");
463                UINT nPasses;
464                effect->Begin(&nPasses, 0);
465                effect->BeginPass(0);
466
467                D3DXMATRIX scaleShip;
468                D3DXMatrixScaling(&scaleShip, 0.05f, 0.05f, 0.05f);
469
470                effect->SetTexture("brdfMap", meshes.at(meshes.size()-1)->->textures[0]);
471                effect->SetMatrix("modelToProjMatrix", &(scaleShip * *lightCamera->GetWorldMatrix() * *camera->GetViewMatrix()  * *camera->GetProjMatrix()  ));
472
473                effect->CommitChanges();
474                renderMeshes[renderMeshes.size()-1]->mesh->DrawSubset(0);
475
476                effect->EndPass();
477                effect->End();
478                device->EndScene();
479        }
480*/
481}
482
483void PathMapEffect::renderFullScreen(float depth)
484{
485        float fLeftU = 0.0f, fTopV = 0.0f, fRightU = 1.0f, fBottomV = 1.0f;
486
487    D3DSURFACE_DESC dtdsdRT;
488    PDIRECT3DSURFACE9 pSurfRT;
489
490    // Acquire render target width and height
491    device->GetRenderTarget(0, &pSurfRT);
492    pSurfRT->GetDesc(&dtdsdRT);
493    pSurfRT->Release();
494
495    // Ensure that we're directly mapping texels to pixels by offset by 0.5
496    // For more info see the doc page titled "Directly Mapping Texels to Pixels"
497    FLOAT fWidth5 = (FLOAT)dtdsdRT.Width - 0.5f;
498    FLOAT fHeight5 = (FLOAT)dtdsdRT.Height - 0.5f;
499
500    // Draw the quad
501        struct D3DVERTEXQUAD{
502                D3DXVECTOR3 pos;
503                D3DXVECTOR2 tex0;
504        };
505
506    D3DVERTEXQUAD svQuad[4];
507
508    svQuad[0].pos=D3DXVECTOR3(-1, 1, depth);
509    svQuad[0].tex0 = D3DXVECTOR2(fLeftU, fTopV);
510
511    svQuad[1].pos = D3DXVECTOR3(1, 1, depth);
512    svQuad[1].tex0 = D3DXVECTOR2(fRightU, fTopV);
513
514    svQuad[2].pos = D3DXVECTOR3(-1, -1, depth);
515    svQuad[2].tex0 = D3DXVECTOR2(fLeftU, fBottomV);
516
517    svQuad[3].pos = D3DXVECTOR3(1, -1, depth);
518    svQuad[3].tex0 = D3DXVECTOR2(fRightU, fBottomV);
519       
520        device->SetRenderState(D3DRS_CULLMODE,D3DCULL_NONE);
521        device->SetFVF(D3DFVF_XYZ | D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE2(0));
522    device->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, svQuad, sizeof(D3DVERTEXQUAD));
523}
524
525void PathMapEffect::move(float fElapsedTime)
526{
527        clusterSweepCurrentIndex += fElapsedTime * 2.0f;
528        if(clusterSweepCurrentIndex > NCLUSTERS)
529                clusterSweepCurrentIndex -= NCLUSTERS;
530        //apply some rotation to one of the entities
531        if(parameters->Get(bTurbo))
532        {
533                camera->FrameMove(fElapsedTime * 10.0f);
534                lightCamera->FrameMove(fElapsedTime * 10.0f);
535        }
536        else
537        {
538                camera->FrameMove(fElapsedTime);
539                lightCamera->FrameMove(fElapsedTime);
540        }
541}
542
543LRESULT PathMapEffect::handleMessage( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
544{
545        if(uMsg == WM_KEYDOWN)
546        {
547                switch(wParam)
548                {
549                        case 'C':
550                                testClusterId = (testClusterId + NCLUSTERS - 1) % NCLUSTERS;
551                                break;
552                        case 'Z':
553                                testClusterId = (testClusterId + 1) % NCLUSTERS;
554                                break;
555                }
556        }
557
558        if(parameters->Get(bMoveLight))
559                return lightCamera->HandleMessages(hWnd, uMsg, wParam, lParam);
560        else
561                return camera->HandleMessages(hWnd, uMsg, wParam, lParam);
562
563}
564
565void PathMapEffect::addUiParameters(Parameters* parameters)
566{
567        PathMapEffect::parameters = parameters;
568        parameters->Add( bLookFromLight, "Look from light", 1);
569        parameters->Add( bMoveLight, "Move light", 1);
570        parameters->Add( bDots, "Entry points", 1);
571        parameters->Add( bTurbo, "Turbo", 1);
572        parameters->Add( fLightScale, "Tone scale", 100, '1', '2', convertLightScale);
573        parameters->Add( fIndirectLightingMode, "Lighting mode", 3, '3', '4', convertInt4);
574        parameters->Add( fTorchDistance, "Torch distance", 100, '5', '6', convertTorchDistance);
575}
576
577void PathMapEffect::setUiParameterDefaults(Parameters* parameters)
578{
579}
580
581Parameters*     PathMapEffect::parameters = NULL;
582
583void PathMapEffect::render()
584{
585        renderWithPRM();
586        if(parameters->Get(bDots))
587        {
588                float psf = 8.0f;
589                HRESULT hr = device->SetRenderState(D3DRS_POINTSIZE, *((DWORD*)&psf));
590                hr = device->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
591                if( SUCCEEDED( device->BeginScene() ) )
592                {
593                        D3DXHANDLE hTechnique = NULL;
594                        hTechnique = effect->GetTechniqueByName((LPSTR)"Dots");
595                        effect->SetTechnique( hTechnique );
596                        UINT nPasses = 0;
597                        effect->Begin( &nPasses, 0 );
598                        for(UINT j=0;j<nPasses;j++){
599                                effect->BeginPass(j);
600                                        hr = effect->SetTexture("depthMap",depthMapTexture);
601                                        if(parameters->Get(bLookFromLight))
602                                                effect->SetMatrix("worldToProjMatrix", &(*lightCamera->GetViewMatrix()  * *lightCamera->GetProjMatrix()  ));
603                                        else
604                                                effect->SetMatrix("worldToProjMatrix", &(*camera->GetViewMatrix()  * *camera->GetProjMatrix()  ));
605
606                                                        static float opttme[9] = {0.5f, 0.0f, 0.0f,
607                                                                0.0f, -0.5f, 0.0f,
608                                                                0.5f + (0.5f / DEPTHMAPRES), 0.5f + (0.5f / DEPTHMAPRES), 1.0f};
609
610                                        effect->SetFloatArray("occProjToTexMatrix", opttme, 9);
611                                        D3DXVECTOR3 lightPos = *lightCamera->GetEyePt();
612                                        hr = effect->SetFloatArray("lightPos", (float*)&lightPos, 3);
613                                        effect->CommitChanges();
614                                        hr = device->SetFVF(D3DFVF_XYZ |  D3DFVF_NORMAL);
615                                        hr = device->SetStreamSource(0, starterVertexBuffer, 0, sizeof(float) * 6);
616                                        UINT offset = 0;
617                                        for(int iClusterDraw=0; iClusterDraw < NCLUSTERS; iClusterDraw++)
618                                        {
619//                                              hr = effect->SetFloat("aClusterWeight", weights[iClusterDraw] * 10.0);
620                                                hr = effect->SetFloat("aClusterWeight", (float)iClusterDraw);
621                                                effect->CommitChanges();
622//                                              if(iClusterDraw - clusterSweepCurrentIndex > -1.0 &&
623//                                                      iClusterDraw - clusterSweepCurrentIndex < 0.0   )
624//                                              if(iClusterDraw == testClusterId)
625                                                        device->DrawPrimitive(D3DPT_POINTLIST, offset, clusterLenghts[iClusterDraw]);
626                                                offset += clusterLenghts[iClusterDraw];
627                                        }
628                                effect->EndPass();
629                        }
630                        effect->End();
631                }
632                device->EndScene();
633        }
634}
635
636void PathMapEffect::releaseEntities()
637{
638        std::vector<Entity*>::iterator entityIterator = entities.begin();
639        while(entityIterator != entities.end())
640        {
641                delete *entityIterator;
642                entityIterator++;
643        }       
644}
645
646void PathMapEffect::sampleSphereDirection(Vector& outDir)
647{
648        do{
649        outDir = Vector(-1.0 + 2.0 * (float)rand() / RAND_MAX, -1.0 + 2.0 * (float)rand() / RAND_MAX, -1.0 + 2.0 * (float)rand() / RAND_MAX);
650        }while(outDir.norm2() > 1.0);
651        outDir.normalize();
652}
653
654void PathMapEffect::sampleShootingDiffuseDirection(int depth, const Vector& normal, Vector& outDir)
655{
656        Vector u, v;
657        if(fabsf(normal[0]) < 0.9f)
658        {
659                u.set(0.0f, -normal[2], normal[1]);
660                u *= 1.0f / sqrtf(normal[2] * normal[2] + normal[1] * normal[1]);
661        }
662        else
663        {
664                u.set(normal[2], 0.0f, -normal[0]);
665                u *= 1.0f / sqrtf(normal[2] * normal[2] + normal[0] * normal[0]);
666        }
667        v.setCrossProduct(normal, u);
668
669        float phi = 2.0f * 3.14159265358979323846f * (float)rand() / RAND_MAX;
670        float xi2 = (float)rand() / RAND_MAX;
671        float cosPhi = cos(phi);
672        float sinPhi = sin(phi);
673        float cosTheta = sqrtf(xi2);
674        float sinTheta = sqrtf(1.0f - xi2);
675
676        outDir.setScaled(sinTheta * cosPhi, v);
677        outDir.addScaled(sinTheta * sinPhi, u);
678        outDir.addScaled(cosTheta, normal);
679}
680
681void PathMapEffect::precompute()
682{
683        // generate entry points
684        for(unsigned int cRad=0; cRad < NRADIONS; cRad++)
685        {
686                Radion starter;
687                sampleSurfaceRadion(starter);
688                //sampleSurfaceRadionUniform(starter);
689                bushStarters.push_back(starter);
690        }
691
692        // sort entry radions into clusters
693        Radion* entryArray = (Radion*)&*bushStarters.begin();
694        clusterRadions(entryArray, bushStarters.size(), 0);
695        clusterRadionsKMeans();
696
697        // for every entity, find the most relevant clusters
698        srand(0xef23ab32);
699        std::vector<Entity*>::iterator entityIterator = entities.begin();
700        while(entityIterator != entities.end())
701        {
702                (*entityIterator)->findNearClusters(bushStarters, NCLUSTERS);
703                (*entityIterator)->clearPRM();
704                entityIterator++;
705        }
706
707        // for every entry radion, shoot a bush of radions, and add their
708        // contributions to all PRMs of all entities
709        unsigned int iCluster = 0;
710        std::vector<Radion> bushRadions;
711        for(int iStarter = 0; iStarter < NRADIONS; )
712        {
713                bushRadions.clear();
714                for(int iric=0; iric < clusterLenghts[iCluster]; iric++, iStarter++)
715                        shootRadionBush(bushStarters[iStarter], bushRadions);
716                std::vector<Entity*>::iterator entityIterator = entities.begin();
717                while(entityIterator != entities.end())
718                {
719                        (*entityIterator)->renderPRM(bushRadions, iCluster);
720                        entityIterator++;
721                }
722                iCluster++;
723        }
724
725        //scale down multiple pixel writes
726        entityIterator = entities.begin();
727        while(entityIterator != entities.end())
728        {
729                (*entityIterator)->normalizePRM();
730                entityIterator++;
731        }
732}
733
734int compareX(const void* a, const void* b)
735{
736        if( ((const Radion*)a)->position.x < ((const Radion*)b)->position.x )
737                return -1;
738        else
739                return 1;
740}
741
742int compareY(const void* a, const void* b)
743{
744        if( ((const Radion*)a)->position.y < ((const Radion*)b)->position.y )
745                return -1;
746        else
747                return 1;
748}
749
750int compareZ(const void* a, const void* b)
751{
752        if( ((const Radion*)a)->position.z < ((const Radion*)b)->position.z )
753                return -1;
754        else
755                return 1;
756}
757
758int compareDirX(const void* a, const void* b)
759{
760        if( ((const Radion*)a)->normal.x < ((const Radion*)b)->normal.x )
761                return -1;
762        else
763                return 1;
764}
765
766int compareDirY(const void* a, const void* b)
767{
768        if( ((const Radion*)a)->normal.y < ((const Radion*)b)->normal.y )
769                return -1;
770        else
771                return 1;
772}
773
774int compareDirZ(const void* a, const void* b)
775{
776        if( ((const Radion*)a)->normal.z < ((const Radion*)b)->normal.z )
777                return -1;
778        else
779                return 1;
780}
781
782
783void PathMapEffect::clusterRadionsKMeans()
784{
785        Radion centroids[MAXNCLUSTERS];
786        std::vector<Radion> clusters[MAXNCLUSTERS];
787        //initial clusters: uniform length
788        for(unsigned int i=0; i<NCLUSTERS; i++)
789                clusterLenghts[i] = NRADIONS / NCLUSTERS;
790        for(unsigned int iKMeans = 0; iKMeans < 128; iKMeans++)
791        {
792                //find centroids
793                unsigned int iRadion = 0;
794                for(unsigned int i=0; i<NCLUSTERS; i++)
795                {
796                        centroids[i].position = Vector::RGBBLACK;
797                        centroids[i].normal = Vector::RGBBLACK;
798                        for(unsigned int iRadionInCluster=0; iRadionInCluster < clusterLenghts[i]; iRadionInCluster++, iRadion++)
799                        {
800                                centroids[i].position += bushStarters.at(iRadion).position;
801                                centroids[i].normal += bushStarters.at(iRadion).normal;
802                        }
803                        centroids[i].position *= 1.0f / (float)clusterLenghts[i];
804                        centroids[i].normal.normalize();
805                }
806               
807                for(unsigned int i=0; i<NCLUSTERS; i++)
808                        clusters[i].clear();
809
810                //sort radions to centroids
811                iRadion = 0;
812                for(unsigned int i=0; i<NCLUSTERS; i++)
813                {
814                        for(unsigned int iRadionInCluster=0; iRadionInCluster < clusterLenghts[i]; iRadionInCluster++, iRadion++)
815                        {
816                                unsigned int minimumDistanceClusterIndex = 0;
817                                float minimumDistance = FLT_MAX;
818                                for(unsigned int u=0; u<NCLUSTERS; u++)
819                                {
820                                        float dirDist = (bushStarters.at(iRadion).normal * centroids[u].normal);
821                                        float dist = (bushStarters.at(iRadion).position - centroids[u].position).norm() * pow(6.0, 1.0 - (double)dirDist);
822                                        if(dist < minimumDistance)
823                                        {
824                                                minimumDistanceClusterIndex = u;
825                                                minimumDistance = dist;
826                                        }
827                                }
828                                clusters[minimumDistanceClusterIndex].push_back( bushStarters.at(iRadion) );
829                        }
830                }
831                //refill bushStarters, set cluster lengths
832                iRadion = 0;
833                for(unsigned int i=0; i<NCLUSTERS; i++)
834                {
835                        clusterLenghts[i] = clusters[i].size();
836                        for(unsigned int iRadionInCluster=0; iRadionInCluster < clusterLenghts[i]; iRadionInCluster++, iRadion++)
837                        {
838                                bushStarters.at(iRadion) = clusters[i].at(iRadionInCluster);
839                        }
840                }
841                //eliminate empty clusters
842                for(unsigned int i=1; i<NCLUSTERS; i++)
843                {
844                        if(clusterLenghts[i] == 0)
845                        {
846                                clusterLenghts[i] = clusterLenghts[i-1] >> 1;
847                                clusterLenghts[i-1] -= clusterLenghts[i-1] >> 1;
848                        }
849                }
850                for(int i=NCLUSTERS - 1; i >= 0; i--)
851                {
852                        if(clusterLenghts[i] == 0)
853                        {
854                                clusterLenghts[i] = clusterLenghts[i+1] >> 1;
855                                clusterLenghts[i+1] -= clusterLenghts[i+1] >> 1;
856                        }
857                }
858        }
859}
860
861int PathMapEffect::clusterRadions(Radion* partition, int psize, char axis)
862{
863/*      if(psize < 2)
864                return 1;
865        if(axis == 0)
866                qsort(partition, psize, sizeof(Radion), compareDirX);
867        else if(axis == 1)
868                qsort(partition, psize, sizeof(Radion), compareDirY);
869        else if(axis == 2)
870                qsort(partition, psize, sizeof(Radion), compareDirZ);
871        else if(axis == 3)
872                qsort(partition, psize, sizeof(Radion), compareX);
873        else if(axis == 4)
874                qsort(partition, psize, sizeof(Radion), compareY);
875        else if(axis == 5)
876                qsort(partition, psize, sizeof(Radion), compareZ);
877        clusterRadions(partition, psize >> 1, (axis+1)%6);
878        clusterRadions(partition + (psize >> 1), psize - (psize >> 1), (axis+1)%6);
879        return 1;
880/*/     if(psize < 2)
881                return 1;
882        if(axis == 0)
883                qsort(partition, psize, sizeof(Radion), compareX);
884        else if(axis == 1)
885                qsort(partition, psize, sizeof(Radion), compareY);
886        else if(axis == 2)
887                qsort(partition, psize, sizeof(Radion), compareZ);
888        clusterRadions(partition, psize >> 1, (axis+1)%3);
889        clusterRadions(partition + (psize >> 1), psize - (psize >> 1), (axis+1)%3);
890        return 1;//*/
891}
892
893
894void PathMapEffect::shootRadionBush(Radion& starter, std::vector<Radion>& bushRadions)
895{
896        bushRadions.push_back(starter);
897
898        int nPhotonsShotForLight = 1;   //branching factor
899        for(int iPhoton = 0; iPhoton < nPhotonsShotForLight; iPhoton++)
900        {
901                unsigned int depth = 0;
902                ray.id = rayId++;
903                ray.isShadowRay = false;
904                ray.origin = starter.position;
905                Vector power = starter.radiance;
906                float prob = starter.probability;
907                prob *= nPhotonsShotForLight;
908                power *= 1.0f / nPhotonsShotForLight;
909                sampleShootingDiffuseDirection(depth, starter.normal, ray.dir);
910
911                for(;;depth++)
912                {
913                        kdtree->traverse(ray, hitRec, 0.0f, FLT_MAX);
914                        if(hitRec.isIntersect)
915                        {
916                                Radion nr;
917                                nr.position = hitRec.point;
918                                nr.normal = hitRec.normal;
919                                nr.radiance = power;
920                                nr.radiance %= hitRec.material->getTextureDiffuseBrdf(hitRec.texUV);
921                                nr.probability = prob;
922                                bushRadions.push_back(nr);
923                        }
924                        else
925                                break;
926                        if(depth >= 3)
927                                break;
928                        float rrRandom = (float)rand() / RAND_MAX;
929                        float diffuseAlbedo = hitRec.material->getTextureDiffuseAlbedo(hitRec.texUV);
930                        float idealAlbedo = hitRec.material->getTextureIdealAlbedo(hitRec.texUV);
931                        float refractiveAlbedo = hitRec.material->getRefractiveAlbedo();
932                        if(rrRandom < diffuseAlbedo)
933                        {
934                                ray.id = rayId++;
935                                ray.isShadowRay = false;
936                                ray.origin = hitRec.point;
937                                power %= hitRec.material->getTextureDiffuseBrdf(hitRec.texUV);
938                                power *= 1.0f / diffuseAlbedo;
939                                prob *= diffuseAlbedo;
940                                sampleShootingDiffuseDirection(depth, hitRec.normal, ray.dir);
941                        }
942                        else
943                        {
944                                rrRandom -= diffuseAlbedo;
945                                if(rrRandom < idealAlbedo)
946                                {
947                                        ray.dir.setIdealReflectedDirection(ray.dir, hitRec.normal);
948                                        ray.id = rayId++;
949                                        ray.isShadowRay = false;
950                                        ray.origin = hitRec.point;
951                                        power %= hitRec.material->getIdealBrdf();
952                                        power *= 1.0f / idealAlbedo;
953                                        prob *= idealAlbedo;
954                                }
955                                else
956                                        break;
957                        }
958                }
959        }
960}
961
962void PathMapEffect::sampleSurfaceRadion(Radion& starter)
963{
964        float randa = ((double)rand() / RAND_MAX) * entities.size();
965//&     float randa = ((double)rand() / RAND_MAX) * sumSurfaceArea;
966        float uptonowSurfaceArea = 0.0;
967        Entity* e = NULL;
968        std::vector<Entity*>::iterator entityIterator = entities.begin();
969        while(entityIterator != entities.end())
970        {
971                uptonowSurfaceArea += 1.0f;
972//&             uptonowSurfaceArea += (*entityIterator)->getSurfaceArea();
973                if(uptonowSurfaceArea >= randa)
974                {
975                        e = *entityIterator;
976                        break;
977                }
978                entityIterator++;
979        }
980
981        const Material* m = e->sampleSurface(starter);
982
983        float surfa = starter.radiance.z;
984
985        Vector rtexc = starter.radiance;
986        starter.radiance = m->getTextureDiffuseBrdf(rtexc);
987        starter.radiance *= (surfa / NRADIONS) * entities.size();
988//&     starter.radiance *= sumSurfaceArea / NRADIONS;
989        starter.probability = (float)NRADIONS / (entities.size() * surfa );
990}
991
992void PathMapEffect::sampleSurfaceRadionUniform(Radion& starter)
993{
994        float randa = ((double)rand() / RAND_MAX) * sumSurfaceArea;
995        float uptonowSurfaceArea = 0.0;
996        Entity* e = NULL;
997        std::vector<Entity*>::iterator entityIterator = entities.begin();
998        while(entityIterator != entities.end())
999        {
1000                uptonowSurfaceArea += (*entityIterator)->getSurfaceArea();
1001                if(uptonowSurfaceArea >= randa)
1002                {
1003                        e = *entityIterator;
1004                        break;
1005                }
1006                entityIterator++;
1007        }
1008
1009        const Material* m = e->sampleSurface(starter);
1010
1011        float surfa = starter.radiance.z;
1012
1013        Vector rtexc = starter.radiance;
1014        starter.radiance = m->getTextureDiffuseBrdf(rtexc);
1015        starter.radiance *= sumSurfaceArea / NRADIONS;
1016        starter.probability = (float)NRADIONS / (entities.size() * surfa );
1017}
1018
1019void PathMapEffect::uploadRadions()
1020{
1021        int nRadions = bushStarters.size();
1022        struct TMR{
1023                float pos[4];
1024                float dir[4];
1025//              float pow[4];
1026        };
1027        TMR* tm = new TMR[nRadions];
1028        for(int i=0; i<nRadions; i++)
1029        {
1030//*
1031                tm[i].pos[0] = bushStarters[i].position[0];
1032                tm[i].pos[1] = bushStarters[i].position[1];
1033                tm[i].pos[2] = bushStarters[i].position[2];
1034                tm[i].pos[3] = 1.0;
1035                tm[i].dir[0] = bushStarters[i].normal[0];
1036                tm[i].dir[1] = bushStarters[i].normal[1];
1037                tm[i].dir[2] = bushStarters[i].normal[2];
1038                tm[i].dir[3] = 1.0;
1039//              tm[i].pow[0] = bushStarters[i].radiance[0];
1040//              tm[i].pow[1] = bushStarters[i].radiance[1];
1041//              tm[i].pow[2] = bushStarters[i].radiance[2];
1042//              tm[i].pow[3] = 1.0;
1043/*/
1044                tm[i].pos[0] = 0.9;
1045                tm[i].pos[1] = 0.2;
1046                tm[i].pos[2] = 0.2;
1047                tm[i].pos[3] = 1.0;
1048                tm[i].dir[0] = 0.2;
1049                tm[i].dir[1] = 0.9;
1050                tm[i].dir[2] = 0.2;
1051                tm[i].dir[3] = 1.0;
1052                tm[i].pow[0] = 0.2;
1053                tm[i].pow[1] = 0.2;
1054                tm[i].pow[2] = 0.9;     //blue
1055                tm[i].pow[3] = 0.99;
1056//*/
1057        }
1058
1059        RECT imgSize;
1060        imgSize.top = imgSize.left = 0;
1061        imgSize.bottom =  nRadions;
1062        imgSize.right = 2 * nRadions / 4096;
1063        D3DXLoadSurfaceFromMemory(radionSurface, NULL, NULL, tm, D3DFMT_A32B32G32R32F,
1064                imgSize.right * 4 * sizeof(float), NULL, &imgSize, D3DX_FILTER_NONE, 0);
1065
1066        delete [] tm;
1067}
1068
1069void PathMapEffect::fillRadionPosArray(void* pData)
1070{
1071        int nRadions = NRADIONS;
1072        struct TMR{
1073                float pos[3];
1074                float rad[3];
1075        };
1076        TMR* tm = (TMR*)pData;
1077        for(int i=0; i<nRadions; i++)
1078        {
1079                tm[i].pos[0] = bushStarters[i].position[0];
1080                tm[i].pos[1] = bushStarters[i].position[1];
1081                tm[i].pos[2] = bushStarters[i].position[2];
1082                tm[i].rad[0] = bushStarters[i].radiance[0];
1083                tm[i].rad[1] = bushStarters[i].radiance[1];
1084                tm[i].rad[2] = bushStarters[i].radiance[2];
1085        }
1086}
1087
1088const wchar_t* PathMapEffect::getWeightsString()
1089{
1090        static wchar_t ws[512];
1091        ws[0] = 0;
1092        char wan[64];
1093        float sumw = 0.0f;
1094        for(int i=0; i<33; i++)
1095        {
1096//              StrCpy(wan, L"%f ");
1097                if(i == 32)
1098                        sprintf(wan, "%.3f ", (double)sumw);
1099                else
1100                {
1101                        sumw += weights[i];
1102                        sprintf(wan, "%.3f ", (double)weights[i]);
1103                }
1104                wchar_t* wideValue = new wchar_t[MultiByteToWideChar(CP_ACP, 0, wan, -1, NULL, 0)];
1105                MultiByteToWideChar(CP_ACP, 0, wan, -1, wideValue, 511);
1106                StrCatW(ws, wideValue);
1107                delete wideValue;
1108        }
1109        return ws;
1110}
1111
1112
1113void PathMapEffect::savePathMaps()
1114{
1115//      std::fstream entryPointFile("prm\\prmEntryPoints.dat", std::ios::out | std::ios::binary);
1116        char eFileName[512];
1117        sprintf(eFileName, "%s\\prmEntryPoints.text", LC::c-this->prmDirectory);
1118        std::fstream entryPointFile(eFileName, std::ios::out);
1119
1120        entryPointFile << "nEntryPoints ";
1121        entryPointFile << NRADIONS;
1122        entryPointFile << "\n";
1123
1124        for(unsigned int u=0; u < NRADIONS; u++)
1125        {
1126                entryPointFile << bushStarters.at(u);
1127                entryPointFile << "\n";
1128        }
1129
1130        entryPointFile << "Clusters ";
1131        entryPointFile << NCLUSTERS;
1132        entryPointFile << "\n";
1133
1134        for(unsigned int c=0; c < NCLUSTERS; c++)
1135        {
1136//              entryPointFile.write((char*)&clusterLenghts[c], sizeof(unsigned int));
1137                entryPointFile << clusterLenghts[c] << '\n';
1138        }
1139        entryPointFile << "\n";
1140
1141        entryPointFile.flush();
1142        entryPointFile.close();
1143
1144        unsigned int iEntity = 0;
1145        std::vector<Entity*>::iterator entityIterator = entities.begin();
1146        while(entityIterator != entities.end())
1147        {
1148                (*entityIterator)->savePRM();
1149
1150                entityIterator++;
1151                iEntity++;
1152        }
1153}
1154
1155void PathMapEffect::loadPathMaps()
1156{
1157/*      std::fstream entryPointFile("prm\\prmEntryPoints.dat", std::ios::in | std::ios::binary);
1158
1159        bushStarters.clear();
1160
1161        for(unsigned int u=0; u < NRADIONS; u++)
1162        {
1163                Radion ri;
1164                entryPointFile >> ri;
1165                bushStarters.push_back(ri);
1166        }
1167       
1168        for(unsigned int c=0; c < NCLUSTERS; c++)
1169        {
1170                entryPointFile.read((char*)&clusterLenghts[c], sizeof(unsigned int));
1171        }
1172
1173        entryPointFile.close();*/
1174        char eFileName[512];
1175        sprintf(eFileName, "%s\\prmEntryPoints.text", LC::c-this->prmDirectory);
1176
1177        std::fstream entryPointFile(eFileName, std::ios::in);
1178
1179        char keyword[256];
1180
1181        unsigned int redrad;
1182        entryPointFile >> keyword;      //nradions
1183        entryPointFile >> redrad;
1184
1185        bushStarters.clear();
1186   
1187        for(unsigned int u=0; u < NRADIONS; u++)
1188        {
1189                Radion ri;
1190                entryPointFile >> ri;
1191                bushStarters.push_back(ri);
1192        }
1193
1194        entryPointFile >> keyword; //ncluster
1195        entryPointFile >> redrad;
1196       
1197        for(unsigned int c=0; c < NCLUSTERS; c++)
1198        {
1199                entryPointFile >> clusterLenghts[c];
1200        }
1201
1202        entryPointFile.close();
1203
1204        srand(0xef23ab32);
1205        unsigned int iEntity = 0;
1206        std::vector<Entity*>::iterator entityIterator = entities.begin();
1207        while(entityIterator != entities.end())
1208        {
1209                (*entityIterator)->findNearClusters(bushStarters, NCLUSTERS);
1210                (*entityIterator)->loadPRM();
1211
1212                entityIterator++;
1213                iEntity++;
1214        }
1215}
1216
1217void PathMapEffect::loadScene(const char* sceneFileName)
1218{
1219        std::fstream sceneFile(sceneFileName, std::ios::in);
1220
1221        char keyword[256];
1222        while(!sceneFile.eof())
1223        {
1224                sceneFile >> keyword;
1225                if(strcmp(keyword, "mesh") == 0)
1226                {
1227                        int meshAtlasSize = 128;
1228                        bool needsUV = true;
1229                        bool needsTBN = false;
1230                        int dividePcs = 1;
1231                        char meshname[256];
1232                        wchar_t* wide = NULL;
1233                        wchar_t* wideXML = NULL;
1234                        wchar_t* wideOgre = NULL;
1235                        Vector color = Vector::RGBWHITE;
1236
1237                        sceneFile >> meshname;
1238                        if(strcmp(meshname, "{") == 0)
1239                                strcpy(meshname, "mesh");
1240                        while(strcmp(keyword, "}") != 0 && !sceneFile.eof())
1241                        {
1242                                sceneFile >> keyword;
1243                                if(strcmp(keyword, "xfile") == 0)
1244                                {
1245                                        sceneFile >> keyword;
1246                                        if(keyword)
1247                                        {
1248                                                wide = L::clone(keyword);
1249                                        }
1250                                }
1251                                if(strcmp(keyword, "ogreXMLfile") == 0)
1252                                {
1253                                        sceneFile >> keyword;
1254                                        if(keyword)
1255                                        {
1256                                                wideXML = L::clone(keyword);
1257                                        }
1258                                }
1259                                if(strcmp(keyword, "ogrefile") == 0)
1260                                {
1261                                        sceneFile >> keyword;
1262                                        if(keyword)
1263                                        {
1264                                                wideOgre = L::clone(keyword);
1265                                        }
1266                                }
1267                                if(strcmp(keyword, "pathmapresolution") == 0)
1268                                {
1269                                        sceneFile >> meshAtlasSize;
1270                                }
1271                                if(strcmp(keyword, "divide") == 0)
1272                                {
1273                                        sceneFile >> dividePcs;
1274                                }
1275                        }
1276                        if(wideXML)
1277                        {
1278                                loadMesh(Mesh::OgreXMLMesh, wideXML, wideOgre, meshAtlasSize, meshname, dividePcs, needsUV, needsTBN);
1279                                delete [] wideXML;
1280                        }
1281                        else if(wide)
1282                        {
1283                                loadMesh(Mesh::DirectXMesh, wide, wideOgre, meshAtlasSize, meshname, dividePcs, needsUV, needsTBN);
1284                                delete [] wide;
1285                        }
1286                        else
1287                        if(wideOgre)
1288                                delete [] wideOgre;
1289                }
1290
1291                if(strcmp(keyword, "entity") == 0)
1292                {
1293                        char entityName[256];
1294                        char prmFileName[256];
1295                        Mesh* baseMesh = NULL;
1296                        D3DXMATRIX trafo;
1297                        D3DXMatrixIdentity(&trafo);
1298                        int nNearClusters = 16;
1299
1300                        sceneFile >> entityName;
1301                        if(strcmp(entityName, "{") == 0)
1302                                strcpy(entityName, "noname");
1303
1304                        while(strcmp(keyword, "}") != 0 && !sceneFile.eof())
1305                        {
1306                                sceneFile >> keyword;
1307                                if(strcmp(keyword, "pathmapfile") == 0)
1308                                {
1309                                        sceneFile >> keyword;
1310                                        strcpy(prmFileName, LC::c-this->prmDirectory);
1311                                        strcat(prmFileName, "\\");
1312                                        strcat(prmFileName, keyword);
1313                                }
1314                                if(strcmp(keyword, "mesh") == 0)
1315                                {
1316                                        sceneFile >> keyword;
1317
1318                                        std::vector<Mesh*>::iterator i = meshes.begin();
1319                                        while(i != meshes.end())
1320                                        {
1321                                                if(strcmp((*i)->getName(), keyword) == 0)
1322                                                {
1323                                                        baseMesh = *i;
1324                                                        break;
1325                                                }
1326                                                i++;
1327                                        }
1328                                }
1329                                if(strcmp(keyword, "transformation") == 0)
1330                                {
1331                                        for(int i=0; i<16; i++)
1332                                                sceneFile >> trafo.m[i%4][i/4];
1333                                }
1334                                if(strcmp(keyword, "pathmapclusters") == 0)
1335                                {
1336                                        sceneFile >> nNearClusters;
1337                                }
1338                        }
1339                        if(baseMesh)
1340                        {
1341                                Entity* e = new Entity(baseMesh, entityName, prmFileName, trafo, nNearClusters);
1342                                entities.push_back(e);
1343                        }
1344                }
1345        }
1346        sceneFile.close();
1347}
1348
1349
1350void PathMapEffect::renderScene(const RenderStrategy& renderStrategy)
1351{
1352        renderStrategy.applyTargets();
1353
1354        renderStrategy.applyRenderState();
1355
1356        if( SUCCEEDED( device->BeginScene() ) )
1357        {
1358                renderStrategy.applyTechnique();
1359                UINT nPasses;
1360                effect->Begin( &nPasses, 0 );
1361                for(UINT j=0;j<nPasses;j++)
1362                {
1363                        effect->BeginPass(j);
1364
1365                        //loop through all entities
1366                        std::vector<Entity*>::iterator entityIterator = entities.begin();
1367                        while(entityIterator != entities.end())
1368                        {
1369
1370                                (*entityIterator)->drawAllSubEntities(renderStrategy);
1371                                entityIterator++;
1372                        }
1373
1374                        effect->EndPass();
1375                }
1376                effect->End();
1377                device->EndScene();
1378        }
1379
1380        renderStrategy.resetRenderState();
1381
1382}
1383
1384void PathMapEffect::saveScene(const char* sceneFileName)
1385{
1386        std::ofstream psf(sceneFileName);
1387       
1388        std::vector<Mesh*>::iterator iMesh = meshes.begin();
1389        while(iMesh != meshes.end())
1390        {
1391                (*iMesh)->saveSceneInfo(psf);
1392                iMesh++;
1393        }
1394
1395        std::vector<Entity*>::iterator iEntity = entities.begin();
1396        while(iEntity != entities.end())
1397        {
1398                (*iEntity)->saveSceneInfo(psf);
1399                iEntity++;
1400        }
1401}
1402
1403const wchar_t* PathMapEffect::getCurrentMethodName()
1404{
1405        int lmode = parameters->GetInt(fIndirectLightingMode);
1406        if(lmode == 3)
1407                return L"PRM only";
1408        if(lmode == 2)
1409                return L"direct + PRM";
1410        if(lmode == 1)
1411                return L"direct + ambient";
1412        if(lmode == 0)
1413                return L"direct only";
1414}
Note: See TracBrowser for help on using the repository browser.