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

Revision 2197, 55.6 KB checked in by szirmay, 18 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 "SubEntity.h"
10#include "shlwapi.h"
11#include <queue>
12#include <fstream>
13
14
15//! D3D vector-matrix multiplication
16D3DVECTOR operator *(const D3DVECTOR& v, const D3DMATRIX& m)
17{
18        D3DVECTOR r;
19        r.x = v.x * m._11 + v.y * m._21 + v.z * m._31 + m._41;
20        r.y = v.x * m._12 + v.y * m._22 + v.z * m._32 + m._42;
21        r.z = v.x * m._13 + v.y * m._23 + v.z * m._33 + m._43;
22        float h = v.x * m._14 + v.y * m._24 + v.z * m._34 + m._44;
23        if(h > 0.00001f || h < 0.00001f)
24        {
25                r.x /= h;
26                r.y /= h;
27                r.z /= h;
28        }
29        return r;
30}
31
32//! method name strings to be displayed on screen
33const wchar_t* PathMapEffect::Method::methodNames[10] =
34{
35        L"PRM",
36        L"PRM texture",
37        L"_",
38        L"_"
39        , NULL, NULL, NULL, NULL, NULL, NULL
40};
41
42//! method constants
43const PathMapEffect::Method PathMapEffect::Method::PRM(0);
44const PathMapEffect::Method PathMapEffect::Method::SHOWTEX(1);
45const PathMapEffect::Method PathMapEffect::Method::LAST(2);
46
47//! constructor
48PathMapEffect::PathMapEffect(LPDIRECT3DDEVICE9 device)
49:method(Method::PRM)
50{
51        NRADIONS = (4096);
52        NCLUSTERS = 64;
53        DEPTHMAPRES     = 512;
54
55
56        float* weights = new float[NCLUSTERS];                 
57        unsigned int* clusterLenghts = new unsigned int[NCLUSTERS];
58
59        clusterSweepCurrentIndex = 0;
60
61        rayId = 1;
62        this->device = device;
63
64        //first person camera allows more freedom of movement
65        camera = new CFirstPersonCamera();
66        lightCamera = new CFirstPersonCamera();
67
68        HRESULT hr;
69        DWORD effectCompileFlag=0;
70       
71        LPD3DXBUFFER compilationErrors;
72        if(FAILED(
73                hr =
74                        D3DXCreateEffectFromFile(
75                                device,
76                                L"pathMap.fx",
77                                NULL,
78                                NULL,
79                                0,
80                                NULL,
81                                &effect,
82                                &compilationErrors) )){
83                MessageBoxA( NULL, (LPSTR)compilationErrors->GetBufferPointer(), "Failed to load effect file!", MB_OK);
84                exit(-1);
85        }
86
87        //store buffers so we can reset them after rendering to texture render targets
88        device->GetRenderTarget(0, &frameColorBuffer);
89        device->GetDepthStencilSurface(&frameDepthStencilBuffer);
90       
91        //load empty texture
92        D3DXCreateTextureFromFile(device, L"media\\empty.bmp", &emptyTexture);
93
94        //set up a scene
95
96        loadScene("media\\space.txt");
97
98        //load hangar mesh
99//      loadMesh( L"media\\hangar.x" );
100//      loadMesh( L"media\\fulltexchamber.x" );
101
102/*      //create hangar entity
103        Entity e1;
104        e1.owner = this;
105        e1.renderMesh = renderMeshes.at(0);
106        D3DXMatrixIdentity(&e1.modelWorldTransform);
107//      D3DXMatrixScaling(&e1.modelWorldTransform, 20.0f, 20.0f, 20.0f);
108        D3DXMatrixScaling(&e1.modelWorldTransform, 0.5f, 1.0f, 0.5f);
109        D3DXMatrixIdentity(&e1.inverseTransposedModelWorldTransform);
110//      D3DXMatrixScaling(&e1.inverseTransposedModelWorldTransform, 1.0f/20.0f, 1.0f/20.0f, 1.0f/20.0f);
111        D3DXMatrixScaling(&e1.inverseTransposedModelWorldTransform, 1.0f/0.5f, 1.0f, 1.0f/0.5f);
112
113        e1.createRayTraceEntity();
114       
115        entities.push_back(e1);
116
117
118        //load 'steps' mesh
119        loadMesh( L"media\\steps.x" );
120
121        //create step entities
122        for(int eitor=0; eitor < 4; eitor++)
123        {
124                D3DXMATRIX urr;
125                D3DXMATRIX rx;          D3DXMatrixRotationY(&rx, Vector::PI * 0.5f * eitor);
126                Entity e2;
127                e2.owner = this;
128                e2.renderMesh = renderMeshes.at(1);
129
130                D3DXMatrixTranslation(&urr, -15.0f, -14.0f, -7.0f);
131                D3DXMatrixMultiply( &e2.modelWorldTransform, &urr, &rx);
132                D3DXMatrixInverse(&e2.inverseTransposedModelWorldTransform, NULL, &e2.modelWorldTransform);
133
134                e2.createRayTraceEntity();
135                entities.push_back(e2);
136
137                D3DXMATRIX trasi, roti;
138                D3DXMatrixTranslation(&trasi, -15.0f + 7.0f, 14.0f, -7.0f -7.0f);               //7.25f, 13.5, -7.25); //rot 90 -90 90 trans 7.25 13.5 -7.25
139                D3DXMatrixRotationYawPitchRoll(&roti, -Vector::PI * 0.5, Vector::PI, 0.0);
140                D3DXMatrixMultiply(&urr, &roti, &trasi);
141
142                D3DXMatrixMultiply( &e2.modelWorldTransform, &urr, &rx);
143
144                D3DXMatrixInverse(&e2.inverseTransposedModelWorldTransform, NULL, &e2.modelWorldTransform);
145                e2.createRayTraceEntity();
146                entities.push_back(e2);
147        }
148*/
149
150        loadMesh( L"media\\fighter.x", 0, "", 1);
151
152        //compute the surface area of the complete geometry. useful for random sampling.
153        sumSurfaceArea = 0.0;
154        std::vector<Entity*>::iterator entityIterator = entities.begin();
155        while(entityIterator != entities.end())
156        {
157                sumSurfaceArea += (*entityIterator)->getSurfaceArea();
158                entityIterator++;
159        }
160
161        //initialize camera
162        camera->SetViewParams( &D3DXVECTOR3(0.0f, 0.0f, 4.0f), &D3DXVECTOR3(0.0f, 0.0f, 0.0f));
163        D3DSURFACE_DESC fbdesc;
164        frameColorBuffer->GetDesc(&fbdesc);
165        camera->SetProjParams( D3DX_PI/2, (float)fbdesc.Width / fbdesc.Height, 0.1f, 300.0f );
166
167        //create resources for entities
168        createPRMTextures();
169
170        //set up spotlight
171        lightCamera->SetViewParams( &D3DXVECTOR3(5.0f, 0.0f, 0.0f), &D3DXVECTOR3(0.0f, 0.0f, 0.0f));
172        lightCamera->SetProjParams( D3DX_PI/1.9, 1.0f, 0.1f, 300.0f );
173
174        //create ray tracing kd-tree containing ray-traceable versions of entities
175        Intersectable** objs = new Intersectable*[entities.size()];
176        for(int u=0; u<entities.size(); u++)
177                objs[u] = entities.at(u).rayTraceEntity;
178        kdtree = new KDTree(objs, entities.size());
179        delete [] objs;
180
181        //create dummy render target texture for depth map rendering
182        device->CreateTexture(DEPTHMAPRES, DEPTHMAPRES, 1, D3DUSAGE_RENDERTARGET, D3DFMT_R32F, D3DPOOL_DEFAULT, &fakeTexture, NULL);
183        fakeTexture->GetSurfaceLevel(0, &fakeSurface);
184
185        //create a depthstencil texture for depth map rendering
186        device->CreateTexture(DEPTHMAPRES, DEPTHMAPRES, 1,
187                D3DUSAGE_DEPTHSTENCIL, D3DFMT_D24X8, D3DPOOL_DEFAULT, &depthMapTexture, NULL);
188        depthMapTexture->GetSurfaceLevel(0, &depthMapDepthStencilBuffer);
189
190#ifdef GENERATE_PATH_MAPS
191        precompute();
192#else
193        loadPathMaps();
194#endif
195
196        //create a texture for radion data (will be used for weight computations on the GPU)
197        device->CreateTexture(2 * NRADIONS / 4096, 4096, 1, 0, D3DFMT_A32B32G32R32F, D3DPOOL_DEFAULT, &radionTexture, NULL);
198        radionTexture->GetSurfaceLevel(0, &radionSurface);
199
200        //fill texture with data
201        uploadRadions();
202
203        //create weights render target
204        device->CreateTexture(4096, NRADIONS / 4096, 1, D3DUSAGE_RENDERTARGET, D3DFMT_R32F, D3DPOOL_DEFAULT, &weightsTexture, NULL);
205        weightsTexture->GetSurfaceLevel(0, &weightsSurface);
206
207        //create a sytem memory duplicate of the weights render target to be able to read back weights data
208        device->CreateTexture(4096, NRADIONS / 4096, 1, 0, D3DFMT_R32F, D3DPOOL_SYSTEMMEM, &sysMemWeightsTexture, NULL);
209        sysMemWeightsTexture->GetSurfaceLevel(0, &sysMemWeightsSurface);
210
211        //create a vertex buffer to be able to visualize entry radion positions
212        device->CreateVertexBuffer(NRADIONS * sizeof(float) * 6, D3DUSAGE_WRITEONLY, D3DFVF_XYZ | D3DFVF_NORMAL, D3DPOOL_DEFAULT,
213                &starterVertexBuffer, NULL);
214        void* pData;
215        starterVertexBuffer->Lock(0, 0, &pData, 0);
216        fillRadionPosArray(pData);
217        starterVertexBuffer->Unlock();
218
219
220        exportEntityData();
221
222#ifdef GENERATE_PATH_MAPS
223        savePathMaps();
224#endif
225}
226
227PathMapEffect::~PathMapEffect(void)
228{
229        delete weights;
230        delete clusterLenghts;
231
232        //release all resources allocated in the constructor
233        starterVertexBuffer->Release();
234
235        depthMapTexture->Release();
236        depthMapDepthStencilBuffer->Release();
237        fakeTexture->Release();
238        fakeSurface->Release();
239
240        sysMemWeightsTexture->Release();
241        sysMemWeightsSurface->Release();
242        weightsTexture->Release();
243        weightsSurface->Release();
244        radionTexture->Release();
245        radionSurface->Release();
246
247        delete kdtree;
248        emptyTexture->Release();
249        releaseTextures();
250        releaseMeshes();
251        releaseEntities();
252
253        frameColorBuffer->Release();
254        frameDepthStencilBuffer->Release();
255
256        effect->Release();
257        delete camera;
258        delete lightCamera;
259}
260
261void PathMapEffect::loadMesh(LPCWSTR fileName, int prmAtlasSize, const char* name, int dividePcs, bool generateUV, bool generateTBN)
262{
263        Mesh* mesh = new Mesh(this, fileName, prmAtlasSize, name, dividePcs, generateUV, generateTBN);
264        meshes.push_back(mesh);
265
266/*      RenderMesh** slabs = new RenderMesh*[dividePcs];
267        int* slabNTris = new int[dividePcs];
268        int nTris = renderMesh->mesh->GetNumFaces();
269
270
271        if(dividePcs == 1)
272        {
273                renderMesh->slabIndex = 0;
274                slabs[0] = renderMesh;
275                slabNTris[0] = nTris;
276        }
277        else
278        {
279                LPDIRECT3DVERTEXBUFFER9 vertexBuffer;
280                renderMesh->mesh->GetVertexBuffer(&vertexBuffer);
281                D3DVERTEX* vertexData;
282                vertexBuffer->Lock(0,renderMesh->mesh->GetNumVertices()*renderMesh->mesh->GetNumBytesPerVertex(),(void**)&vertexData,0);
283                LPDIRECT3DINDEXBUFFER9 indexBuffer;
284                renderMesh->mesh->GetIndexBuffer(&indexBuffer);
285                unsigned short* indexData;
286                indexBuffer->Lock(0,nTris*3*sizeof(unsigned short),(void**)&indexData,0);
287
288                Tri* tris = new Tri[nTris];
289                //partition to small meshes
290                for(int g=0; g<nTris; g++)
291                {
292                        tris[g].origMeshIndex = g;
293                        tris[g].pos =   (vertexData[indexData[g * 3]].pos +
294                                                        vertexData[indexData[g * 3 + 1]].pos +
295                                                        vertexData[indexData[g * 3 + 2]].pos) * 0.33333333333333;
296                        tris[g].normal =        (vertexData[indexData[g * 3]].normal +
297                                                        vertexData[indexData[g * 3 + 1]].normal +
298                                                        vertexData[indexData[g * 3 + 2]].normal);
299                        tris[g].normal.normalize();
300                }
301
302
303                clusterTrisKMeans(tris, nTris, dividePcs, slabNTris);
304                int triClusterStart = 0;
305
306                for(int ict=0; ict<dividePcs; ict++)
307                {
308                        slabs[ict] = new RenderMesh();
309                        slabs[ict]->prmAtlasSize = renderMesh->prmAtlasSize;
310                        strcpy(slabs[ict]->name, renderMesh->name);
311                        slabs[ict]->slabIndex = ict;
312                        slabs[ict]->rayTraceMaterial = renderMesh->rayTraceMaterial;
313                        slabs[ict]->nSubsets = renderMesh->nSubsets;
314                        slabs[ict]->textures = new LPDIRECT3DTEXTURE9[renderMesh->nSubsets];
315                        for(int qu=0; qu < renderMesh->nSubsets; qu++)
316                                slabs[ict]->textures[qu] = renderMesh->textures[qu];
317                        // count vertices
318                        unsigned short* ill = new unsigned short[renderMesh->mesh->GetNumVertices()];
319                        for(int zzz=0; zzz<renderMesh->mesh->GetNumVertices(); zzz++)
320                                ill[zzz] = 0;
321                        for(int rmi = triClusterStart; rmi<triClusterStart + slabNTris[ict]; rmi++)
322                        {
323                                ill[indexData[tris[rmi].origMeshIndex*3]] = 1;
324                                ill[indexData[tris[rmi].origMeshIndex*3+1]] = 1;
325                                ill[indexData[tris[rmi].origMeshIndex*3+2]] = 1;
326                        }
327
328                        int nVertices = 0;
329                        for(int ccc=0; ccc<renderMesh->mesh->GetNumVertices(); ccc++)
330                                if(ill[ccc])
331                                        nVertices++;
332
333                        // create new mesh
334                        HRESULT dhre = D3DXCreateMeshFVF(
335                                slabNTris[ict],
336                                nVertices,
337                                0,
338                                D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX4 | D3DFVF_TEXCOORDSIZE2(0) | D3DFVF_TEXCOORDSIZE2(1) |
339                                D3DFVF_TEXCOORDSIZE3(2) | D3DFVF_TEXCOORDSIZE3(3),
340                                device,
341                                &slabs[ict]->mesh);
342                        // fill with tris
343                        LPDIRECT3DVERTEXBUFFER9 svertexBuffer;
344                        slabs[ict]->mesh->GetVertexBuffer(&svertexBuffer);
345                        D3DVERTEX* svertexData;
346                        svertexBuffer->Lock(0, nVertices*slabs[ict]->mesh->GetNumBytesPerVertex(),(void**)&svertexData,0);
347                        LPDIRECT3DINDEXBUFFER9 sindexBuffer;
348                        slabs[ict]->mesh->GetIndexBuffer(&sindexBuffer);
349                        unsigned short* sindexData;
350                        sindexBuffer->Lock(0,slabNTris[ict]*3*sizeof(unsigned short),(void**)&sindexData,0);
351
352                        int ufi = 0;
353                        for(int ifi=0; ifi<renderMesh->mesh->GetNumVertices(); ifi++)
354                                if(ill[ifi])
355                                {
356                                        svertexData[ufi] = vertexData[ifi];
357                                        ill[ifi] = ufi;
358                                        ufi++;
359                                }
360                                else
361                                        ill[ifi] = 0xffff;
362
363                        for(int trifi=0; trifi<slabNTris[ict]; trifi++)
364                        {
365                                sindexData[trifi*3] = ill[indexData[tris[trifi+triClusterStart].origMeshIndex*3]];
366                                sindexData[trifi*3+1] = ill[indexData[tris[trifi+triClusterStart].origMeshIndex*3+1]];
367                                sindexData[trifi*3+2] = ill[indexData[tris[trifi+triClusterStart].origMeshIndex*3+2]];
368                        }
369
370                        svertexBuffer->Unlock();
371                        sindexBuffer->Unlock();
372                        svertexBuffer->Release();
373                        sindexBuffer->Release();
374
375                        triClusterStart += slabNTris[ict];
376                }
377
378                vertexBuffer->Unlock();
379                indexBuffer->Unlock();
380                vertexBuffer->Release();
381                indexBuffer->Release();
382
383                renderMesh->mesh->Release();
384                delete renderMesh;
385        }
386
387        for(unsigned int fi=0; fi < dividePcs; fi++)
388        {
389                RenderMesh*& renderMesh = slabs[fi];
390
391                //lock the buffers and create ray tracing meshes from the data
392                LPDIRECT3DVERTEXBUFFER9 vertexBuffer;
393                renderMesh->mesh->GetVertexBuffer(&vertexBuffer);
394                D3DVERTEX* vertexData;
395                vertexBuffer->Lock(0,renderMesh->mesh->GetNumVertices()*renderMesh->mesh->GetNumBytesPerVertex(),(void**)&vertexData,0);
396                LPDIRECT3DINDEXBUFFER9 indexBuffer;
397                renderMesh->mesh->GetIndexBuffer(&indexBuffer);
398                unsigned short* indexData;
399                indexBuffer->Lock(0,renderMesh->mesh->GetNumFaces()*3*sizeof(unsigned short),(void**)&indexData,0);
400
401                //create a TriangleMesh for ray-tracing
402                renderMesh->rayTraceMesh = new TriangleMesh(renderMesh->rayTraceMaterial, indexData, renderMesh->mesh->GetNumFaces(),
403                        vertexData, renderMesh->mesh->GetNumVertices());
404
405                vertexBuffer->Unlock();
406                indexBuffer->Unlock();
407                vertexBuffer->Release();
408                indexBuffer->Release();
409
410                renderMesh->slabIndex = fi;
411                renderMesh->generateUVAtlas();
412                renderMesh->buildEdgeVertexBuffer(device);
413                renderMeshes.push_back(renderMesh);
414        }
415        delete [] slabs;*/
416}
417
418LPDIRECT3DTEXTURE9 PathMapEffect::loadTexture(LPCWSTR fileName, Material** rayTraceMaterial)
419{
420        if(fileName == NULL || wcscmp(fileName, L"") == 0)
421                return NULL;
422        wchar_t* mediaFileName = new wchar_t[wcslen(fileName) + 64];
423        //we assume the x file was in folder .\media
424        wcscpy(mediaFileName, L"media\\");
425        wcscat(mediaFileName, fileName);
426        LPDIRECT3DTEXTURE9 tex;
427
428        D3DXIMAGE_INFO bobo;
429        if(S_OK !=
430                D3DXCreateTextureFromFileEx(device, mediaFileName, D3DX_DEFAULT, D3DX_DEFAULT, 1, 0,
431                D3DFMT_FROM_FILE, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, &bobo, NULL, &tex
432                ))
433        {
434                 MessageBox(NULL, mediaFileName, L"Could not load texture file!", MB_OK);
435                 return NULL;
436        }
437       
438        materialTextures.push_back(tex);
439
440        if(rayTraceMaterial != NULL)
441        {
442                D3DLOCKED_RECT lrect;
443                HRESULT hr = tex->LockRect(0, &lrect, NULL, D3DLOCK_READONLY);
444                LPDIRECT3DSURFACE9 texsurf;
445                tex->GetSurfaceLevel(0, &texsurf);
446                D3DSURFACE_DESC desc;
447                texsurf->GetDesc(&desc);
448                *rayTraceMaterial = new TexturedMaterial(lrect.pBits, lrect.Pitch, desc.Width);
449                texsurf->Release();
450                tex->UnlockRect(0);
451        }
452        return tex;
453}
454
455void PathMapEffect::releaseTextures()
456{
457        std::vector<LPDIRECT3DTEXTURE9>::iterator i = materialTextures.begin();
458        while(i != materialTextures.end())
459        {
460                (*i)->Release();
461                i++;
462        }
463
464        std::vector<Material*>::iterator z = rayTraceMaterials.begin();
465        while(z != rayTraceMaterials.end())
466        {
467                delete (*z);
468                z++;
469        }
470}
471
472void PathMapEffect::releaseMeshes()
473{
474        std::vector<PathMapEffect::RenderMesh*>::iterator i = renderMeshes.begin();
475        while(i != renderMeshes.end())
476        {
477//              if((*i)->bumpTexture)
478//                      (*i)->bumpTexture->Release();
479                if((*i)->normalTexture)
480                        (*i)->normalTexture->Release();
481                (*i)->mesh->Release();
482                delete (*i)->rayTraceMesh;
483                if((*i)->edgeVertexBuffer)
484                        (*i)->edgeVertexBuffer->Release();
485                delete *i;
486                i++;
487        }
488}
489
490void PathMapEffect::renderWithPRM()
491{
492        // first pass: render depth
493
494        device->SetRenderTarget(0, fakeSurface);
495        device->SetDepthStencilSurface(depthMapDepthStencilBuffer);
496        device->Clear( 0, NULL, D3DCLEAR_ZBUFFER, D3DCOLOR_ARGB(255, 0, 0, 0), 1.0f, 0 );
497        //no color writes
498        device->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
499        //render back faces (avoids Z-fighting, no need for comparison bias)
500        device->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW);
501       
502        if( SUCCEEDED( device->BeginScene() ) )
503        {
504                effect->SetTechnique("Depth");
505                UINT nPasses;
506                effect->Begin(&nPasses, 0);
507                effect->BeginPass(0);
508                //loop through all entities, all mesh subsets, set proper transformations
509
510                std::vector<Entity*>::iterator entityIterator = entities.begin();
511                while(entityIterator != entities.end())
512                {
513                        effect->SetMatrix("modelToProjMatrix",
514                                &( entityIterator->modelWorldTransform * *lightCamera->GetViewMatrix() * *lightCamera->GetProjMatrix() ) );
515                        effect->CommitChanges();
516                        unsigned int nSubsets = entityIterator->renderMesh->nSubsets;
517                        for(int i = 0; i< nSubsets; i++)
518                        {
519                                entityIterator->renderMesh->mesh->DrawSubset(i);
520                        }
521                        entityIterator++;
522                }
523
524                effect->EndPass();
525                effect->End();
526                device->EndScene();
527        }
528
529        //reset front face rendering, color writes
530        device->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
531        HRESULT hr = S_OK;
532        hr = device->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA| D3DCOLORWRITEENABLE_BLUE| D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_RED);
533
534        // 2. pass: compute weights
535
536        // simple parallel computation for all pixels: no 3D, depth, shadows, only a full-texture quad
537        hr = device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
538        hr = device->SetRenderState(D3DRS_STENCILENABLE, false);
539        hr = device->SetRenderTarget(0,weightsSurface);
540        hr = device->SetDepthStencilSurface(NULL);
541        D3DXVECTOR3 lightPos = *lightCamera->GetEyePt();
542        D3DXVECTOR3 lightDir = *lightCamera->GetWorldAhead();
543        lightDir /= D3DXVec3Length( &lightDir );
544        float ffl = parameters->Get(fLightScale) * 10.0f;
545        D3DXVECTOR3 lightPower(ffl, ffl, ffl);
546
547        device->Clear( 0, NULL, D3DCLEAR_TARGET,        D3DCOLOR_XRGB(0,0,0), 1.0f, 0 );
548
549        if( SUCCEEDED( device->BeginScene() ) ){
550                if( effect != NULL ){
551                        D3DXHANDLE hTechnique = NULL;
552                        hTechnique = effect->GetTechniqueByName((LPSTR)"ComputeWeights");
553                        if(hTechnique==NULL){
554                                return;
555                        }
556                        effect->SetTechnique( hTechnique );
557
558                        UINT nPasses = 0;
559                        effect->Begin( &nPasses, 0 );
560                        for(UINT j=0;j<nPasses;j++){
561                                effect->BeginPass(j);
562                                hr = effect->SetTexture("radions", radionTexture);
563                                static float opttme[9] = {0.5f, 0.0f, 0.0f,
564                                                                                0.0f, -0.5f, 0.0f,
565                                                                                0.5f + (0.5f / DEPTHMAPRES), 0.5f + (0.5f / DEPTHMAPRES), 1.0f};
566
567                                //set global params
568                                effect->SetFloatArray("occProjToTexMatrix", opttme, 9);
569                                effect->SetMatrix("occWorldToProjMatrix", &(*lightCamera->GetViewMatrix() * *lightCamera->GetProjMatrix()));
570
571                                effect->SetTexture("depthMap", depthMapTexture);
572                                hr = effect->SetInt("nRadionColumns", NRADIONS / 4096);
573                                hr = effect->SetFloatArray("lightPower", (float*)&lightPower, 3);
574                                hr = effect->SetFloatArray("lightPos", (float*)&lightPos, 3);
575                                hr = effect->SetFloatArray("lightDir", (float*)&lightDir, 3);
576                                effect->CommitChanges();
577                                renderFullScreen();
578                                effect->EndPass();
579                        }
580                        effect->End();
581                }
582                device->EndScene();
583        }
584
585        // read the weights back
586
587        D3DLOCKED_RECT rData;
588        hr = device->GetRenderTargetData(weightsSurface, sysMemWeightsSurface);
589        hr =  sysMemWeightsSurface->LockRect(&rData, NULL, D3DLOCK_READONLY);
590        float* allEntryWeights = (float*)rData.pBits;
591
592        // average weights per cluster
593        float sumWeightsAll = 0.0;
594        unsigned int iRadion = 0;
595        for(int iCluster=0; iCluster < NCLUSTERS; iCluster++)
596        {
597                weights[iCluster] = 0.0;
598                float clusterrad = 0.0;
599                for(int clusterSummer=0; clusterSummer < clusterLenghts[iCluster]; clusterSummer++, iRadion++)
600                {
601                        float radrad = bushStarters[iRadion].radiance.sum();
602                        weights[iCluster] += allEntryWeights[iRadion] * radrad;
603                        clusterrad += radrad;
604                }
605                if(clusterrad > 0.01)
606                        weights[iCluster] /= clusterrad; //(double)clusterLenghts[iCluster];
607                else
608                        weights[iCluster] = 0.0f;
609//              if(iCluster != TEST_CLUST)
610//                      weights[iCluster] = 0.0;
611//              if(weights[iCluster] > 0.005)
612//                      weights[iCluster] = 0.005;
613                sumWeightsAll += weights[iCluster];
614        }
615        sysMemWeightsSurface->UnlockRect();
616
617        // 3. pass: render scene using weights to combine PRM texture atlases
618
619       
620        device->SetRenderTarget(0, frameColorBuffer);
621        device->SetDepthStencilSurface(frameDepthStencilBuffer);
622        // use backface culling, depth test
623        hr = device->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
624        hr = device->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
625
626        device->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,     D3DCOLOR_XRGB(0,0,0), 1.0f, 0 );
627       
628        if( SUCCEEDED( device->BeginScene() ) )
629        {
630                effect->SetTechnique("walk");
631                UINT nPasses;
632                effect->Begin(&nPasses, 0);
633                effect->BeginPass(0);
634
635                static float opttme[9] = {0.5f, 0.0f, 0.0f,
636                                                                0.0f, -0.5f, 0.0f,
637                                                                0.5f + (0.5f / DEPTHMAPRES), 0.5f + (0.5f / DEPTHMAPRES), 1.0f};
638
639                //set global params
640                effect->SetFloatArray("occProjToTexMatrix", opttme, 9);
641                effect->SetMatrix("occWorldToProjMatrix", &(*lightCamera->GetViewMatrix() * *lightCamera->GetProjMatrix()));
642
643                effect->SetTexture("depthMap", depthMapTexture);
644
645                //loop through entities
646                std::vector<PathMapEffect::Entity>::iterator entityIterator = entities.begin();
647                while(entityIterator != entities.end())
648                {
649                        //set entity params
650                        // nearestIdx -> bushId
651                        float* weightsa = new float[entityIterator->nNearClusters];
652                        for(unsigned int y=0; y<entityIterator->nNearClusters; y++)
653                        {
654//                              Entity e = *entityIterator;
655                                weightsa[y] = weights[entityIterator->nearClusterIndices[y]];
656                        }
657                        hr = effect->SetFloatArray("weightsa", weightsa, entityIterator->nNearClusters);
658                        effect->SetMatrix("modelToWorldMatrix", &entityIterator->modelWorldTransform);
659                        effect->SetMatrix("inverseTransposedModelToWorldMatrix", &entityIterator->inverseTransposedModelWorldTransform);
660                        D3DXMATRIX t = entityIterator->modelWorldTransform;
661                        if(parameters->Get(bLookFromLight))
662                                effect->SetMatrix("modelToProjMatrix", &(entityIterator->modelWorldTransform * *lightCamera->GetViewMatrix()  * *lightCamera->GetProjMatrix()  ));
663                        else
664                        {
665                                D3DXVECTOR3 wa = *camera->GetWorldAhead();
666                                wa = wa * (1.0 / D3DXVec3Length(&wa));
667                                D3DXVECTOR3 eye = *camera->GetEyePt();
668                                D3DXVECTOR3 shup = -eye * (1.0 / D3DXVec3Length(&eye));
669                                float angle = acos(D3DXVec3Dot(&wa, &shup));
670                                D3DXMATRIX maro;
671                                D3DXVECTOR3 rotax;
672                                D3DXVec3Cross(&rotax, &wa, &shup);
673                                D3DXMatrixRotationAxis(&maro, &rotax, angle);
674                                effect->SetMatrix("modelToProjMatrix", &(entityIterator->modelWorldTransform * maro * *camera->GetViewMatrix() * *camera->GetProjMatrix()  ));
675                        }
676
677                        effect->SetTexture("filteredAtlas", entityIterator->prmTexture);
678                        effect->SetTexture("bumpMap", entityIterator->renderMesh->bumpTexture);
679                        effect->SetTexture("normalMap", entityIterator->renderMesh->normalTexture);
680                        hr = effect->SetFloatArray("lightPower", (float*)&lightPower, 3);
681                        hr = effect->SetFloatArray("lightPos", (float*)&lightPos, 3);
682                        hr = effect->SetFloatArray("lightDir", (float*)&lightDir, 3);
683                       
684                        int prmnt[2] = {entityIterator->renderMesh->prmxres / entityIterator->renderMesh->prmAtlasSize,
685                                entityIterator->renderMesh->prmyres / entityIterator->renderMesh->prmAtlasSize};
686                        hr = effect->SetIntArray("prmAtlasTiles", prmnt, 2);
687                        hr = effect->SetFloatArray("atlasHalfPixel", (float*)&Vector(
688                                0.5 / entityIterator->renderMesh->prmxres, 0.5 / entityIterator->renderMesh->prmyres, 0.0), 2);
689
690                        unsigned int nSubsets = entityIterator->renderMesh->nSubsets;
691                        for(int i = 0; i< nSubsets; i++)
692                        {
693                                //set subset material texture
694                                if(entityIterator->renderMesh->textures[i])
695                                        effect->SetTexture("brdfMap", entityIterator->renderMesh->textures[i]);
696                                else
697                                        effect->SetTexture("brdfMap", emptyTexture);
698                                effect->CommitChanges();
699                                entityIterator->renderMesh->mesh->DrawSubset(i);
700                        }
701                        entityIterator++;
702
703                        delete weightsa;
704                }
705                effect->EndPass();
706                effect->End();
707                device->EndScene();
708        }
709
710        if(!parameters->Get(bLookFromLight))
711        if( SUCCEEDED( device->BeginScene() ) )
712        {
713                effect->SetTechnique("torch");
714                UINT nPasses;
715                effect->Begin(&nPasses, 0);
716                effect->BeginPass(0);
717
718                D3DXMATRIX scaleShip;
719                D3DXMatrixScaling(&scaleShip, 0.05f, 0.05f, 0.05f);
720
721                effect->SetTexture("brdfMap", renderMeshes[renderMeshes.size()-1]->textures[0]);
722                effect->SetMatrix("modelToProjMatrix", &(scaleShip * *lightCamera->GetWorldMatrix() * *camera->GetViewMatrix()  * *camera->GetProjMatrix()  ));
723
724                effect->CommitChanges();
725                renderMeshes[renderMeshes.size()-1]->mesh->DrawSubset(0);
726
727                effect->EndPass();
728                effect->End();
729                device->EndScene();
730        }
731
732}
733
734HRESULT PathMapEffect::RenderMesh::setVertexFormat(DWORD fvf, LPDIRECT3DDEVICE9 device)
735{
736        LPD3DXMESH tempMesh;
737
738        //clone the mesh to the appropriate format
739    HRESULT hr = mesh->CloneMeshFVF( mesh->GetOptions(),
740                                  fvf ,
741                                  device, &tempMesh );
742        if(hr == S_OK)
743        {
744                DWORD* padj = new DWORD[mesh->GetNumFaces() * 3];
745                mesh->GenerateAdjacency(0.00001f, padj);
746                delete padj;
747                //forget he old mesh
748                mesh->Release();
749                //use the cloned mesh
750                mesh = tempMesh;
751        }
752        return hr;
753}
754
755HRESULT PathMapEffect::RenderMesh::generateUVAtlas()
756{
757        LPD3DXMESH tempMesh;
758
759        float maxStretchApplied;
760        unsigned int nCharts;
761
762        HRESULT hr =
763                D3DXUVAtlasCreate(
764                        mesh,           //      LPD3DXMESH pMesh,
765                        0,                      //      UINT dwMaxChartNumber,
766                        1.0f,           //      FLOAT fMaxStretch,
767                        prmAtlasSize - 4,               //      UINT dwWidth,
768                        prmAtlasSize - 4,               //      UINT dwHeight,
769                        2.0f,           //      FLOAT fGutter,
770                        1,                      //      DWORD dwTextureIndex,
771                        NULL,           //      CONST DWORD * pdwAdjacency,
772                        NULL,           //      CONST CHAR * pcFalseEdges,
773                        NULL,           //      FLOAT * pfIMTArray,
774                        NULL,           //      LPD3DXUVATLASCB pCallback,
775                        0.001f,         //      FLOAT fCallbackFrequency,
776            NULL,               //      LPVOID pUserContent,
777                        &tempMesh,      //      LPD3DXMESH * ppMeshOut,
778                        NULL,           //      LPD3DXBUFFER * ppFacePartitioning,
779                        NULL,           //      LPD3DXBUFFER * ppVertexRemapArray,
780                        &maxStretchApplied,     //      FLOAT * pfMaxStretchOut,
781                        &nCharts                        //      UINT * pdwNumChartsOut
782                );
783
784        if(hr == S_OK)
785        {
786                //forget he old mesh
787                mesh->Release();
788        }
789
790        hr =
791                D3DXComputeTangentFrameEx(
792                        tempMesh,                                       //  ID3DXMesh * pMesh,
793                        D3DDECLUSAGE_TEXCOORD,  // DWORD dwTextureInSemantic,
794                        0,                                              //  DWORD dwTextureInIndex,
795                        D3DDECLUSAGE_TEXCOORD,  // DWORD dwUPartialOutSemantic,
796                        2,                                              // DWORD dwUPartialOutIndex,
797                        D3DDECLUSAGE_TEXCOORD,  // DWORD dwVPartialOutSemantic,
798                        3,                                              // DWORD dwVPartialOutIndex,
799                        D3DDECLUSAGE_NORMAL,    // DWORD dwNormalOutSemantic,
800                        0,                                              // DWORD dwNormalOutIndex,
801                        (D3DXTANGENT_WRAP_UV
802//                      | D3DXTANGENT_DONT_ORTHOGONALIZE | D3DXTANGENT_DONT_NORMALIZE_PARTIALS)
803                        )& !( D3DXTANGENT_CALCULATE_NORMALS ), // DWORD dwOptions,
804                        NULL,                                   // CONST DWORD * pdwAdjacency,
805                        0.2,                                    // FLOAT fPartialEdgeThreshold,
806                        0.0,                                    // FLOAT fSingularPointThreshold,
807                        0.2,                                    // FLOAT fNormalEdgeThreshold,
808                        &mesh,                                  // ID3DXMesh ** ppMeshOut,
809                        NULL                                    // ID3DXBuffer ** ppVertexMapping
810                );
811
812        if(hr == S_OK)
813        {
814                //forget he old mesh
815                tempMesh->Release();
816        }
817
818        LPDIRECT3DVERTEXBUFFER9 vertexBuffer;
819        mesh->GetVertexBuffer(&vertexBuffer);
820        D3DVERTEX* vertexData;
821        vertexBuffer->Lock(0,mesh->GetNumVertices()*mesh->GetNumBytesPerVertex(),(void**)&vertexData,0);
822
823        for(unsigned int u=0; u < mesh->GetNumVertices(); u++ )
824                vertexData[u].tex1 = (vertexData[u].tex1 * (prmAtlasSize - 4) + D3DXVECTOR2(2.0,2.0)) / (float)prmAtlasSize;
825
826        vertexBuffer->Unlock();
827        SAFE_RELEASE(vertexBuffer);
828
829       
830//      D3DXSaveMeshToX(L"media/om.x", mesh, NULL, NULL, 0, 0, 1 /*DXFILEFORMAT_TEXT*/);
831
832        return hr;
833}
834
835void PathMapEffect::renderFullScreen(float depth)
836{
837        float fLeftU = 0.0f, fTopV = 0.0f, fRightU = 1.0f, fBottomV = 1.0f;
838
839    D3DSURFACE_DESC dtdsdRT;
840    PDIRECT3DSURFACE9 pSurfRT;
841
842    // Acquire render target width and height
843    device->GetRenderTarget(0, &pSurfRT);
844    pSurfRT->GetDesc(&dtdsdRT);
845    pSurfRT->Release();
846
847    // Ensure that we're directly mapping texels to pixels by offset by 0.5
848    // For more info see the doc page titled "Directly Mapping Texels to Pixels"
849    FLOAT fWidth5 = (FLOAT)dtdsdRT.Width - 0.5f;
850    FLOAT fHeight5 = (FLOAT)dtdsdRT.Height - 0.5f;
851
852    // Draw the quad
853        struct D3DVERTEX{
854                D3DXVECTOR3 pos;
855                D3DXVECTOR2 tex0;
856        };
857
858    D3DVERTEX svQuad[4];
859
860    svQuad[0].pos=D3DXVECTOR3(-1, 1, depth);
861    svQuad[0].tex0 = D3DXVECTOR2(fLeftU, fTopV);
862
863    svQuad[1].pos = D3DXVECTOR3(1, 1, depth);
864    svQuad[1].tex0 = D3DXVECTOR2(fRightU, fTopV);
865
866    svQuad[2].pos = D3DXVECTOR3(-1, -1, depth);
867    svQuad[2].tex0 = D3DXVECTOR2(fLeftU, fBottomV);
868
869    svQuad[3].pos = D3DXVECTOR3(1, -1, depth);
870    svQuad[3].tex0 = D3DXVECTOR2(fRightU, fBottomV);
871       
872        device->SetRenderState(D3DRS_CULLMODE,D3DCULL_NONE);
873        device->SetFVF(D3DFVF_XYZ | D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE2(0));
874    device->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, svQuad, sizeof(D3DVERTEX));
875}
876
877void PathMapEffect::move(float fElapsedTime)
878{
879        clusterSweepCurrentIndex += fElapsedTime * 2.0f;
880        if(clusterSweepCurrentIndex > NCLUSTERS)
881                clusterSweepCurrentIndex -= NCLUSTERS;
882        //apply some rotation to one of the entities
883        if(parameters->Get(bTurbo))
884        {
885                camera->FrameMove(fElapsedTime * 10.0f);
886                lightCamera->FrameMove(fElapsedTime * 10.0f);
887        }
888        else
889        {
890                camera->FrameMove(fElapsedTime);
891                lightCamera->FrameMove(fElapsedTime);
892        }
893/*      D3DXMATRIX rot;
894        D3DXMatrixRotationY(&rot, fElapsedTime * 0.1f);
895        D3DXMatrixMultiply( &entities.at(0).modelWorldTransform,
896                                                &rot,
897                                                &entities.at(0).modelWorldTransform);
898        D3DXMatrixInverse(  &entities.at(0).inverseTransposedModelWorldTransform, NULL,
899                                                &entities.at(0).modelWorldTransform);
900        D3DXMatrixTranspose( &entities.at(0).inverseTransposedModelWorldTransform, &entities.at(0).inverseTransposedModelWorldTransform);
901
902        if(entities.size() > 1)
903        {
904                D3DXMatrixTranslation(&entities.at(1).modelWorldTransform, 0.0f, parameters->Get(fSecondModelHeight) * 5.0f , 0.0f);
905                D3DXMatrixTranslation(&entities.at(1).inverseTransposedModelWorldTransform, 0.0f, -parameters->Get(fSecondModelHeight) * 5.0f , 0.0f);
906        }*/
907}
908
909LRESULT PathMapEffect::handleMessage( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
910
911{
912        if(parameters->Get(bMoveLight))
913                return lightCamera->HandleMessages(hWnd, uMsg, wParam, lParam);
914        else
915                return camera->HandleMessages(hWnd, uMsg, wParam, lParam);
916}
917
918void PathMapEffect::addUiParameters(Parameters* parameters)
919{
920        PathMapEffect::parameters = parameters;
921        parameters->Add( bLookFromLight, "Look from light", 1);
922        parameters->Add( bMoveLight, "Move light", 1);
923        parameters->Add( bDots, "Entry points", 1);
924        parameters->Add( bTurbo, "Turbo", 1);
925        parameters->Add( fLightScale, "Tone scale", 100, 'V', 'B', convert100);
926}
927
928void PathMapEffect::setUiParameterDefaults(Parameters* parameters)
929{
930}
931
932Parameters*     PathMapEffect::parameters = NULL;
933
934void PathMapEffect::render()
935{
936        if(method == Method::PRM)
937                renderWithPRM();
938        else
939                showPRMTexture();
940        if(parameters->Get(bDots))
941        {
942                float psf = 8.0f;
943                HRESULT hr = device->SetRenderState(D3DRS_POINTSIZE, *((DWORD*)&psf));
944                hr = device->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
945                if( SUCCEEDED( device->BeginScene() ) )
946                {
947                        D3DXHANDLE hTechnique = NULL;
948                        hTechnique = effect->GetTechniqueByName((LPSTR)"Dots");
949                        effect->SetTechnique( hTechnique );
950                        UINT nPasses = 0;
951                        effect->Begin( &nPasses, 0 );
952                        for(UINT j=0;j<nPasses;j++){
953                                effect->BeginPass(j);
954                                        hr = effect->SetTexture("depthMap",depthMapTexture);
955                                        if(parameters->Get(bLookFromLight))
956                                                effect->SetMatrix("worldToProjMatrix", &(*lightCamera->GetViewMatrix()  * *lightCamera->GetProjMatrix()  ));
957                                        else
958                                                effect->SetMatrix("worldToProjMatrix", &(*camera->GetViewMatrix()  * *camera->GetProjMatrix()  ));
959
960                                                        static float opttme[9] = {0.5f, 0.0f, 0.0f,
961                                                                0.0f, -0.5f, 0.0f,
962                                                                0.5f + (0.5f / DEPTHMAPRES), 0.5f + (0.5f / DEPTHMAPRES), 1.0f};
963
964                                        effect->SetFloatArray("occProjToTexMatrix", opttme, 9);
965                                        D3DXVECTOR3 lightPos = *lightCamera->GetEyePt();
966                                        hr = effect->SetFloatArray("lightPos", (float*)&lightPos, 3);
967                                        effect->CommitChanges();
968                                        hr = device->SetFVF(D3DFVF_XYZ |  D3DFVF_NORMAL);
969                                        hr = device->SetStreamSource(0, starterVertexBuffer, 0, sizeof(float) * 6);
970                                        UINT offset = 0;
971                                        for(int iClusterDraw=0; iClusterDraw < NCLUSTERS; iClusterDraw++)
972                                        {
973//                                              hr = effect->SetFloat("aClusterWeight", weights[iClusterDraw] * 10.0);
974                                                hr = effect->SetFloat("aClusterWeight", (float)iClusterDraw);
975                                                effect->CommitChanges();
976//                                              if(iClusterDraw - clusterSweepCurrentIndex > -1.0 &&
977//                                                      iClusterDraw - clusterSweepCurrentIndex < 0.0   )
978                                                        device->DrawPrimitive(D3DPT_POINTLIST, offset, clusterLenghts[iClusterDraw]);
979                                                offset += clusterLenghts[iClusterDraw];
980                                        }
981                                effect->EndPass();
982                        }
983                        effect->End();
984                }
985                device->EndScene();
986        }
987}
988
989void PathMapEffect::releaseEntities()
990{
991        std::vector<PathMapEffect::Entity>::iterator entityIterator = entities.begin();
992        while(entityIterator != entities.end())
993        {
994                delete entityIterator->rayTraceEntity;
995                entityIterator->prmSurface->Release();
996                entityIterator->prmTexture->Release();
997                entityIterator++;
998        }       
999}
1000
1001void PathMapEffect::sampleSphereDirection(Vector& outDir)
1002{
1003        do{
1004        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);
1005        }while(outDir.norm2() > 1.0);
1006        outDir.normalize();
1007}
1008
1009void PathMapEffect::sampleShootingDiffuseDirection(int depth, const Vector& normal, Vector& outDir)
1010{
1011        Vector u, v;
1012        if(fabsf(normal[0]) < 0.9f)
1013        {
1014                u.set(0.0f, -normal[2], normal[1]);
1015                u *= 1.0f / sqrtf(normal[2] * normal[2] + normal[1] * normal[1]);
1016        }
1017        else
1018        {
1019                u.set(normal[2], 0.0f, -normal[0]);
1020                u *= 1.0f / sqrtf(normal[2] * normal[2] + normal[0] * normal[0]);
1021        }
1022        v.setCrossProduct(normal, u);
1023
1024        float phi = 2.0f * 3.14159265358979323846f * (float)rand() / RAND_MAX;
1025        float xi2 = (float)rand() / RAND_MAX;
1026        float cosPhi = cos(phi);
1027        float sinPhi = sin(phi);
1028        float cosTheta = sqrtf(xi2);
1029        float sinTheta = sqrtf(1.0f - xi2);
1030
1031        outDir.setScaled(sinTheta * cosPhi, v);
1032        outDir.addScaled(sinTheta * sinPhi, u);
1033        outDir.addScaled(cosTheta, normal);
1034}
1035
1036void PathMapEffect::precompute()
1037{
1038        // generate entry points
1039        for(unsigned int cRad=0; cRad < NRADIONS; cRad++)
1040        {
1041                Radion starter;
1042                sampleSurfaceRadion(starter);
1043                //sampleSurfaceRadionUniform(starter);
1044                bushStarters.push_back(starter);
1045        }
1046
1047        // sort entry radions into clusters
1048        Radion* entryArray = (Radion*)&*bushStarters.begin();
1049        clusterRadions(entryArray, bushStarters.size(), 0);
1050        clusterRadionsKMeans();
1051
1052        // for every entity, find the most relevant clusters
1053        std::vector<PathMapEffect::Entity>::iterator entityIterator = entities.begin();
1054        while(entityIterator != entities.end())
1055        {
1056                entityIterator->findNearClusters(bushStarters, NCLUSTERS);
1057                entityIterator++;
1058        }
1059
1060        // for every entry radion, shoot a bush of radions, and add their
1061        // contributions to all PRMs of all entities
1062        unsigned int iCluster = 0;
1063        std::vector<Radion> bushRadions;
1064        for(int iStarter = 0; iStarter < NRADIONS; )
1065        {
1066                bushRadions.clear();
1067                for(int iric=0; iric < clusterLenghts[iCluster]; iric++, iStarter++)
1068                        shootRadionBush(bushStarters[iStarter], bushRadions);
1069                std::vector<PathMapEffect::Entity>::iterator entityIterator = entities.begin();
1070                while(entityIterator != entities.end())
1071                {
1072                        entityIterator->renderPRM(bushRadions, iCluster);
1073                        entityIterator++;
1074                }
1075                iCluster++;
1076        }
1077
1078        //scale down multiple pixel writes
1079        entityIterator = entities.begin();
1080        while(entityIterator != entities.end())
1081        {
1082                entityIterator->normalizePRM();
1083                entityIterator++;
1084        }
1085}
1086
1087int compareX(const void* a, const void* b)
1088{
1089        if( ((const Radion*)a)->position.x < ((const Radion*)b)->position.x )
1090                return -1;
1091        else
1092                return 1;
1093}
1094
1095int compareY(const void* a, const void* b)
1096{
1097        if( ((const Radion*)a)->position.y < ((const Radion*)b)->position.y )
1098                return -1;
1099        else
1100                return 1;
1101}
1102
1103int compareZ(const void* a, const void* b)
1104{
1105        if( ((const Radion*)a)->position.z < ((const Radion*)b)->position.z )
1106                return -1;
1107        else
1108                return 1;
1109}
1110
1111int compareDirX(const void* a, const void* b)
1112{
1113        if( ((const Radion*)a)->normal.x < ((const Radion*)b)->normal.x )
1114                return -1;
1115        else
1116                return 1;
1117}
1118
1119int compareDirY(const void* a, const void* b)
1120{
1121        if( ((const Radion*)a)->normal.y < ((const Radion*)b)->normal.y )
1122                return -1;
1123        else
1124                return 1;
1125}
1126
1127int compareDirZ(const void* a, const void* b)
1128{
1129        if( ((const Radion*)a)->normal.z < ((const Radion*)b)->normal.z )
1130                return -1;
1131        else
1132                return 1;
1133}
1134
1135
1136void PathMapEffect::clusterRadionsKMeans()
1137{
1138        Radion centroids[NCLUSTERS];
1139        std::vector<Radion> clusters[NCLUSTERS];
1140        //initial clusters: uniform length
1141        for(unsigned int i=0; i<NCLUSTERS; i++)
1142                clusterLenghts[i] = NRADIONS / NCLUSTERS;
1143        for(unsigned int iKMeans = 0; iKMeans < 128; iKMeans++)
1144        {
1145                //find centroids
1146                unsigned int iRadion = 0;
1147                for(unsigned int i=0; i<NCLUSTERS; i++)
1148                {
1149                        centroids[i].position = Vector::RGBBLACK;
1150                        centroids[i].normal = Vector::RGBBLACK;
1151                        for(unsigned int iRadionInCluster=0; iRadionInCluster < clusterLenghts[i]; iRadionInCluster++, iRadion++)
1152                        {
1153                                centroids[i].position += bushStarters.at(iRadion).position;
1154                                centroids[i].normal += bushStarters.at(iRadion).normal;
1155                        }
1156                        centroids[i].position *= 1.0f / (float)clusterLenghts[i];
1157                        centroids[i].normal.normalize();
1158                }
1159               
1160                for(unsigned int i=0; i<NCLUSTERS; i++)
1161                        clusters[i].clear();
1162
1163                //sort radions to centroids
1164                iRadion = 0;
1165                for(unsigned int i=0; i<NCLUSTERS; i++)
1166                {
1167                        for(unsigned int iRadionInCluster=0; iRadionInCluster < clusterLenghts[i]; iRadionInCluster++, iRadion++)
1168                        {
1169                                unsigned int minimumDistanceClusterIndex = 0;
1170                                float minimumDistance = FLT_MAX;
1171                                for(unsigned int u=0; u<NCLUSTERS; u++)
1172                                {
1173                                        float dirDist = (bushStarters.at(iRadion).normal * centroids[u].normal);
1174                                        float dist = (bushStarters.at(iRadion).position - centroids[u].position).norm() * pow(6.0, 1.0 - (double)dirDist);
1175                                        if(dist < minimumDistance)
1176                                        {
1177                                                minimumDistanceClusterIndex = u;
1178                                                minimumDistance = dist;
1179                                        }
1180                                }
1181                                clusters[minimumDistanceClusterIndex].push_back( bushStarters.at(iRadion) );
1182                        }
1183                }
1184                //refill bushStarters, set cluster lengths
1185                iRadion = 0;
1186                for(unsigned int i=0; i<NCLUSTERS; i++)
1187                {
1188                        clusterLenghts[i] = clusters[i].size();
1189                        for(unsigned int iRadionInCluster=0; iRadionInCluster < clusterLenghts[i]; iRadionInCluster++, iRadion++)
1190                        {
1191                                bushStarters.at(iRadion) = clusters[i].at(iRadionInCluster);
1192                        }
1193                }
1194                //eliminate empty clusters
1195                for(unsigned int i=1; i<NCLUSTERS; i++)
1196                {
1197                        if(clusterLenghts[i] == 0)
1198                        {
1199                                clusterLenghts[i] = clusterLenghts[i-1] >> 1;
1200                                clusterLenghts[i-1] -= clusterLenghts[i-1] >> 1;
1201                        }
1202                }
1203                for(int i=NCLUSTERS - 1; i >= 0; i--)
1204                {
1205                        if(clusterLenghts[i] == 0)
1206                        {
1207                                clusterLenghts[i] = clusterLenghts[i+1] >> 1;
1208                                clusterLenghts[i+1] -= clusterLenghts[i+1] >> 1;
1209                        }
1210                }
1211        }
1212}
1213
1214/*void PathMapEffect::clusterTrisKMeans(Tri* triArray, int nTris, int nClusters, int* clusterLenghts)
1215{
1216        Tri* centroids = new Tri[nClusters];
1217        std::vector<Tri>* result = new std::vector<Tri>[nClusters];
1218
1219        //initial clusters: uniform length
1220        for(unsigned int i=0; i<nClusters; i++)
1221                clusterLenghts[i] = nTris / nClusters;
1222        for(unsigned int iKMeans = 0; iKMeans < 128; iKMeans++)
1223        {
1224                //find centroids
1225                unsigned int iTri = 0;
1226                for(unsigned int i=0; i<nClusters; i++)
1227                {
1228                        centroids[i].pos = Vector::RGBBLACK;
1229                        centroids[i].normal = Vector::RGBBLACK;
1230                        for(unsigned int iTriInCluster=0; iTriInCluster < clusterLenghts[i]; iTriInCluster++, iTri++)
1231                        {
1232                                centroids[i].pos += triArray[iTri].pos;
1233                                centroids[i].normal += triArray[iTri].normal;
1234                        }
1235                        centroids[i].pos *= 1.0f / (float)clusterLenghts[i];
1236                        centroids[i].normal.normalize();
1237                }
1238               
1239                for(unsigned int i=0; i<nClusters; i++)
1240                        result[i].clear();
1241
1242                //sort radions to centroids
1243                iTri = 0;
1244                for(unsigned int i=0; i<nClusters; i++)
1245                {
1246                        for(unsigned int iTriInCluster=0; iTriInCluster < clusterLenghts[i]; iTriInCluster++, iTri++)
1247                        {
1248                                unsigned int minimumDistanceClusterIndex = 0;
1249                                float minimumDistance = FLT_MAX;
1250                                for(unsigned int u=0; u<nClusters; u++)
1251                                {
1252                                        float dirDist = (triArray[iTri].normal * centroids[u].normal);
1253                                        float dist = (triArray[iTri].pos - centroids[u].pos).norm() * pow(6.0, 1.0 - (double)dirDist);
1254                                        if(dist < minimumDistance)
1255                                        {
1256                                                minimumDistanceClusterIndex = u;
1257                                                minimumDistance = dist;
1258                                        }
1259                                }
1260                                result[minimumDistanceClusterIndex].push_back( triArray[iTri] );
1261                        }
1262                }
1263                //refill bushStarters, set cluster lengths
1264                iTri = 0;
1265                for(unsigned int i=0; i<nClusters; i++)
1266                {
1267                        clusterLenghts[i] = result[i].size();
1268                        for(unsigned int iTriInCluster=0; iTriInCluster < clusterLenghts[i]; iTriInCluster++, iTri++)
1269                        {
1270                                triArray[iTri] = result[i].at(iTriInCluster);
1271                        }
1272                }
1273                //eliminate empty clusters
1274                for(unsigned int i=1; i<nClusters; i++)
1275                {
1276                        if(clusterLenghts[i] == 0)
1277                        {
1278                                clusterLenghts[i] = clusterLenghts[i-1] >> 1;
1279                                clusterLenghts[i-1] -= clusterLenghts[i-1] >> 1;
1280                        }
1281                }
1282                for(int i=nClusters - 1; i >= 0; i--)
1283                {
1284                        if(clusterLenghts[i] == 0)
1285                        {
1286                                clusterLenghts[i] = clusterLenghts[i+1] >> 1;
1287                                clusterLenghts[i+1] -= clusterLenghts[i+1] >> 1;
1288                        }
1289                }
1290        }
1291        delete [] centroids;
1292        delete [] result;
1293}
1294*/
1295
1296int PathMapEffect::clusterRadions(Radion* partition, int psize, char axis)
1297{
1298/*      if(psize < 2)
1299                return 1;
1300        if(axis == 0)
1301                qsort(partition, psize, sizeof(Radion), compareDirX);
1302        else if(axis == 1)
1303                qsort(partition, psize, sizeof(Radion), compareDirY);
1304        else if(axis == 2)
1305                qsort(partition, psize, sizeof(Radion), compareDirZ);
1306        else if(axis == 3)
1307                qsort(partition, psize, sizeof(Radion), compareX);
1308        else if(axis == 4)
1309                qsort(partition, psize, sizeof(Radion), compareY);
1310        else if(axis == 5)
1311                qsort(partition, psize, sizeof(Radion), compareZ);
1312        clusterRadions(partition, psize >> 1, (axis+1)%6);
1313        clusterRadions(partition + (psize >> 1), psize - (psize >> 1), (axis+1)%6);
1314        return 1;
1315/*/     if(psize < 2)
1316                return 1;
1317        if(axis == 0)
1318                qsort(partition, psize, sizeof(Radion), compareX);
1319        else if(axis == 1)
1320                qsort(partition, psize, sizeof(Radion), compareY);
1321        else if(axis == 2)
1322                qsort(partition, psize, sizeof(Radion), compareZ);
1323        clusterRadions(partition, psize >> 1, (axis+1)%3);
1324        clusterRadions(partition + (psize >> 1), psize - (psize >> 1), (axis+1)%3);
1325        return 1;//*/
1326}
1327
1328
1329void PathMapEffect::shootRadionBush(Radion& starter, std::vector<Radion>& bushRadions)
1330{
1331        bushRadions.push_back(starter);
1332
1333        int nPhotonsShotForLight = 1;   //branching factor
1334        for(int iPhoton = 0; iPhoton < nPhotonsShotForLight; iPhoton++)
1335        {
1336                unsigned int depth = 0;
1337                ray.id = rayId++;
1338                ray.isShadowRay = false;
1339                ray.origin = starter.position;
1340                Vector power = starter.radiance;
1341                float prob = starter.probability;
1342                prob *= nPhotonsShotForLight;
1343                power *= 1.0f / nPhotonsShotForLight;
1344                sampleShootingDiffuseDirection(depth, starter.normal, ray.dir);
1345
1346                for(;;depth++)
1347                {
1348                        kdtree->traverse(ray, hitRec, 0.0f, FLT_MAX);
1349                        if(hitRec.isIntersect)
1350                        {
1351                                Radion nr;
1352                                nr.position = hitRec.point;
1353                                nr.normal = hitRec.normal;
1354                                nr.radiance = power;
1355                                nr.radiance %= hitRec.material->getTextureDiffuseBrdf(hitRec.texUV);
1356                                nr.probability = prob;
1357                                bushRadions.push_back(nr);
1358                        }
1359                        else
1360                                break;
1361                        if(depth >= 3)
1362                                break;
1363                        float rrRandom = (float)rand() / RAND_MAX;
1364                        float diffuseAlbedo = hitRec.material->getTextureDiffuseAlbedo(hitRec.texUV);
1365                        float idealAlbedo = hitRec.material->getTextureIdealAlbedo(hitRec.texUV);
1366                        float refractiveAlbedo = hitRec.material->getRefractiveAlbedo();
1367                        if(rrRandom < diffuseAlbedo)
1368                        {
1369                                ray.id = rayId++;
1370                                ray.isShadowRay = false;
1371                                ray.origin = hitRec.point;
1372                                power %= hitRec.material->getTextureDiffuseBrdf(hitRec.texUV);
1373                                power *= 1.0f / diffuseAlbedo;
1374                                prob *= diffuseAlbedo;
1375                                sampleShootingDiffuseDirection(depth, hitRec.normal, ray.dir);
1376                        }
1377                        else
1378                        {
1379                                rrRandom -= diffuseAlbedo;
1380                                if(rrRandom < idealAlbedo)
1381                                {
1382                                        ray.dir.setIdealReflectedDirection(ray.dir, hitRec.normal);
1383                                        ray.id = rayId++;
1384                                        ray.isShadowRay = false;
1385                                        ray.origin = hitRec.point;
1386                                        power %= hitRec.material->getIdealBrdf();
1387                                        power *= 1.0f / idealAlbedo;
1388                                        prob *= idealAlbedo;
1389                                }
1390                                else
1391                                        break;
1392                        }
1393                }
1394        }
1395}
1396
1397void PathMapEffect::sampleSurfaceRadion(Radion& starter)
1398{
1399        float randa = ((double)rand() / RAND_MAX) * entities.size();
1400//&     float randa = ((double)rand() / RAND_MAX) * sumSurfaceArea;
1401        float uptonowSurfaceArea = 0.0;
1402        Entity* e = NULL;
1403        std::vector<Entity*>::iterator entityIterator = entities.begin();
1404        while(entityIterator != entities.end())
1405        {
1406                uptonowSurfaceArea += 1.0f;
1407//&             uptonowSurfaceArea += (*entityIterator)->getSurfaceArea();
1408                if(uptonowSurfaceArea >= randa)
1409                {
1410                        e = *entityIterator;
1411                        break;
1412                }
1413                entityIterator++;
1414        }
1415
1416        SubEntity* se = e->sampleSurface(starter);
1417
1418        float surfa = starter.radiance.z;
1419
1420        Vector rtexc = starter.radiance;
1421        starter.radiance = se->getRayTraceEntity()->getMaterial()->getTextureDiffuseBrdf(rtexc);
1422        starter.radiance *= (surfa / NRADIONS) * entities.size();
1423//&     starter.radiance *= sumSurfaceArea / NRADIONS;
1424        starter.probability = (float)NRADIONS / (entities.size() * surfa );
1425}
1426
1427void PathMapEffect::sampleSurfaceRadionUniform(Radion& starter)
1428{
1429        float randa = ((double)rand() / RAND_MAX) * sumSurfaceArea;
1430        float uptonowSurfaceArea = 0.0;
1431        Entity* e = NULL;
1432        std::vector<Entity*>::iterator entityIterator = entities.begin();
1433        while(entityIterator != entities.end())
1434        {
1435                uptonowSurfaceArea += (*entityIterator)->getSurfaceArea();
1436                if(uptonowSurfaceArea >= randa)
1437                {
1438                        e = *entityIterator;
1439                        break;
1440                }
1441                entityIterator++;
1442        }
1443
1444        SubEntity* se = e->sampleSurface(starter);
1445
1446        float surfa = starter.radiance.z;
1447
1448        Vector rtexc = starter.radiance;
1449        starter.radiance = se->getRayTraceEntity()->getMaterial()->getTextureDiffuseBrdf(rtexc);
1450        starter.radiance *= sumSurfaceArea / NRADIONS;
1451        starter.probability = (float)NRADIONS / (entities.size() * surfa );
1452}
1453
1454
1455/*
1456void PathMapEffect::showPRMTexture()
1457{
1458        device->SetRenderTarget(0, frameColorBuffer);
1459        device->SetDepthStencilSurface(frameDepthStencilBuffer);
1460
1461        device->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,     D3DCOLOR_XRGB(0,0,0), 1.0f, 0 );
1462
1463        if( SUCCEEDED( device->BeginScene() ) ){
1464                if( effect != NULL ){
1465                        D3DXHANDLE hTechnique = effect->GetTechniqueByName((LPSTR)"ShowTex");
1466                        if(hTechnique==NULL){
1467                                return;
1468                        }
1469                        effect->SetTechnique( hTechnique );
1470                        UINT nPasses = 0;
1471                        effect->Begin( &nPasses, 0 );
1472                        for(UINT j=0;j<nPasses;j++){
1473                                effect->BeginPass(j);
1474               
1475                                //loop through entities
1476                                std::vector<PathMapEffect::Entity>::iterator entityIterator = entities.begin();
1477                                //while(entityIterator != entities.end())
1478                                {
1479                                        //set entity params
1480                                        effect->SetMatrix("modelToWorldMatrix", &entityIterator->modelWorldTransform);
1481                                        effect->SetMatrix("inverseTransposedModelToWorldMatrix", &entityIterator->inverseTransposedModelWorldTransform);
1482                                        D3DXMATRIX t = entityIterator->modelWorldTransform;
1483                                        if(parameters->Get(bLookFromLight))
1484                                                effect->SetMatrix("modelToProjMatrix", &(entityIterator->modelWorldTransform * *lightCamera->GetViewMatrix()  * *lightCamera->GetProjMatrix()  ));
1485                                        else
1486                                                effect->SetMatrix("modelToProjMatrix", &(entityIterator->modelWorldTransform * *camera->GetViewMatrix()  * *camera->GetProjMatrix()  ));
1487
1488                                        effect->SetTexture("filteredAtlas", entityIterator->prmTexture);
1489
1490                                        unsigned int nSubsets = entityIterator->renderMesh->nSubsets;
1491                                        for(int i = 0; i< nSubsets; i++)
1492                                        {
1493                                                //set subset material texture
1494                                                effect->SetTexture("texToShow", entityIterator->prmTexture);
1495                                                effect->CommitChanges();
1496                                                renderFullScreen();
1497//                                              effect->CommitChanges();
1498//                                              entityIterator->renderMesh->mesh->DrawSubset(i);
1499                                        }
1500                                        entityIterator++;
1501                                }
1502                                effect->EndPass();
1503                        }
1504                        effect->End();
1505                }
1506                device->EndScene();
1507        }
1508
1509}
1510*/
1511
1512void PathMapEffect::uploadRadions()
1513{
1514        int nRadions = bushStarters.size();
1515        struct TMR{
1516                float pos[4];
1517                float dir[4];
1518//              float pow[4];
1519        };
1520        TMR* tm = new TMR[nRadions];
1521        for(int i=0; i<nRadions; i++)
1522        {
1523//*
1524                tm[i].pos[0] = bushStarters[i].position[0];
1525                tm[i].pos[1] = bushStarters[i].position[1];
1526                tm[i].pos[2] = bushStarters[i].position[2];
1527                tm[i].pos[3] = 1.0;
1528                tm[i].dir[0] = bushStarters[i].normal[0];
1529                tm[i].dir[1] = bushStarters[i].normal[1];
1530                tm[i].dir[2] = bushStarters[i].normal[2];
1531                tm[i].dir[3] = 1.0;
1532//              tm[i].pow[0] = bushStarters[i].radiance[0];
1533//              tm[i].pow[1] = bushStarters[i].radiance[1];
1534//              tm[i].pow[2] = bushStarters[i].radiance[2];
1535//              tm[i].pow[3] = 1.0;
1536/*/
1537                tm[i].pos[0] = 0.9;
1538                tm[i].pos[1] = 0.2;
1539                tm[i].pos[2] = 0.2;
1540                tm[i].pos[3] = 1.0;
1541                tm[i].dir[0] = 0.2;
1542                tm[i].dir[1] = 0.9;
1543                tm[i].dir[2] = 0.2;
1544                tm[i].dir[3] = 1.0;
1545                tm[i].pow[0] = 0.2;
1546                tm[i].pow[1] = 0.2;
1547                tm[i].pow[2] = 0.9;     //blue
1548                tm[i].pow[3] = 0.99;
1549//*/
1550        }
1551
1552        RECT imgSize;
1553        imgSize.top = imgSize.left = 0;
1554        imgSize.bottom =  nRadions;
1555        imgSize.right = 2 * nRadions / 4096;
1556        D3DXLoadSurfaceFromMemory(radionSurface, NULL, NULL, tm, D3DFMT_A32B32G32R32F,
1557                imgSize.right * 4 * sizeof(float), NULL, &imgSize, D3DX_FILTER_NONE, 0);
1558
1559        delete [] tm;
1560}
1561
1562void PathMapEffect::fillRadionPosArray(void* pData)
1563{
1564        int nRadions = NRADIONS;
1565        struct TMR{
1566                float pos[3];
1567                float rad[3];
1568        };
1569        TMR* tm = (TMR*)pData;
1570        for(int i=0; i<nRadions; i++)
1571        {
1572                tm[i].pos[0] = bushStarters[i].position[0];
1573                tm[i].pos[1] = bushStarters[i].position[1];
1574                tm[i].pos[2] = bushStarters[i].position[2];
1575                tm[i].rad[0] = bushStarters[i].radiance[0];
1576                tm[i].rad[1] = bushStarters[i].radiance[1];
1577                tm[i].rad[2] = bushStarters[i].radiance[2];
1578        }
1579}
1580
1581const wchar_t* PathMapEffect::getWeightsString()
1582{
1583        static wchar_t ws[512];
1584        ws[0] = 0;
1585        char wan[64];
1586        float sumw = 0.0f;
1587        for(int i=0; i<33; i++)
1588        {
1589//              StrCpy(wan, L"%f ");
1590                if(i == 32)
1591                        sprintf(wan, "%.3f ", (double)sumw);
1592                else
1593                {
1594                        sumw += weights[i];
1595                        sprintf(wan, "%.3f ", (double)weights[i]);
1596                }
1597                wchar_t* wideValue = new wchar_t[MultiByteToWideChar(CP_ACP, 0, wan, -1, NULL, 0)];
1598                MultiByteToWideChar(CP_ACP, 0, wan, -1, wideValue, 511);
1599                StrCatW(ws, wideValue);
1600                delete wideValue;
1601        }
1602        return ws;
1603}
1604
1605
1606void PathMapEffect::savePathMaps()
1607{
1608        std::fstream entryPointFile("prm\\prmEntryPoints.dat", std::ios::out | std::ios::binary);
1609
1610        for(unsigned int u=0; u < NRADIONS; u++)
1611        {
1612                entryPointFile << bushStarters.at(u);
1613        }
1614       
1615        for(unsigned int c=0; c < NCLUSTERS; c++)
1616        {
1617                entryPointFile.write((char*)&clusterLenghts[c], sizeof(unsigned int));
1618        }
1619
1620        entryPointFile.flush();
1621        entryPointFile.close();
1622
1623        unsigned int iEntity = 0;
1624        std::vector<Entity*>::iterator entityIterator = entities.begin();
1625        while(entityIterator != entities.end())
1626        {
1627                (*entityIterator)->savePRMs();
1628
1629                entityIterator++;
1630                iEntity++;
1631        }
1632
1633}
1634
1635void PathMapEffect::loadPathMaps()
1636{
1637        std::fstream entryPointFile("prm\\prmEntryPoints.dat", std::ios::in | std::ios::binary);
1638
1639        bushStarters.clear();
1640
1641        for(unsigned int u=0; u < NRADIONS; u++)
1642        {
1643                Radion ri;
1644                entryPointFile >> ri;
1645                bushStarters.push_back(ri);
1646        }
1647       
1648        for(unsigned int c=0; c < NCLUSTERS; c++)
1649        {
1650                entryPointFile.read((char*)&clusterLenghts[c], sizeof(unsigned int));           
1651        }
1652
1653        entryPointFile.close();
1654
1655        unsigned int iEntity = 0;
1656        std::vector<Entity*>::iterator entityIterator = entities.begin();
1657        while(entityIterator != entities.end())
1658        {
1659                entityIterator->findNearClusters(bushStarters, NCLUSTERS);
1660
1661                wchar_t prmFileName[256];
1662//              wsprintf(prmFileName, L"prm\\prm_%08d.hdr", iEntity);
1663                MultiByteToWideChar(CP_ACP, 0, entityIterator->prmfilename, -1, prmFileName, 255);
1664                D3DXLoadSurfaceFromFile(entityIterator->prmSurface, NULL, NULL, prmFileName, NULL, D3DX_DEFAULT, 0, NULL);
1665                entityIterator++;
1666                iEntity++;
1667        }
1668}
1669
1670void PathMapEffect::exportEntityData()
1671{
1672        std::fstream entryPointFile("media\\entityPathMapData.txt", std::ios::out);
1673
1674        unsigned int iEntity = 0;
1675        std::vector<PathMapEffect::Entity>::iterator entityIterator = entities.begin();
1676        while(entityIterator != entities.end())
1677        {
1678                entryPointFile << "entity " << entityIterator->name << '\n';
1679                entryPointFile << "{" << '\n';
1680                entryPointFile << " pathmapfile " << entityIterator->prmfilename << '\n';
1681                entryPointFile << " clusters ";
1682                for(int i=0; i<entityIterator->nNearClusters; i++)
1683                        entryPointFile << entityIterator->nearClusterIndices[i] << " ";
1684                entryPointFile << '\n';
1685                entryPointFile << "}" << '\n';
1686                entryPointFile << '\n';
1687
1688//              for(int i=0; i<16; i++)
1689//                      entryPointFile << entityIterator->modelWorldTransform.m[i%4][i/4] << " ";
1690                entryPointFile << '\n';
1691                entityIterator++;
1692                iEntity++;
1693        }
1694
1695        entryPointFile.flush();
1696        entryPointFile.close();
1697
1698}
1699
1700void PathMapEffect::loadScene(const char* sceneFileName)
1701{
1702        std::fstream sceneFile(sceneFileName, std::ios::in);
1703
1704        char keyword[256];
1705        while(!sceneFile.eof())
1706        {
1707                sceneFile >> keyword;
1708                if(strcmp(keyword, "mesh") == 0)
1709                {
1710                        int meshAtlasSize = 128;
1711                        bool needsUV = true;
1712                        bool needsTBN = false;
1713                        int dividePcs = 1;
1714                        double bumpScale = 1.0;
1715                        char meshname[256];
1716                        wchar_t* wide = NULL;
1717                        wchar_t* wBump = NULL;
1718                        Vector color = Vector::RGBWHITE;
1719
1720                        sceneFile >> meshname;
1721                        if(strcmp(meshname, "{") == 0)
1722                                strcpy(meshname, "mesh");
1723                        while(strcmp(keyword, "}") != 0 && !sceneFile.eof())
1724                        {
1725                                sceneFile >> keyword;
1726                                if(strcmp(keyword, "xfile") == 0)
1727                                {
1728                                        sceneFile >> keyword;
1729                                        if(keyword)
1730                                        {
1731                                                wide = L::l+keyword;
1732                                        }
1733
1734                                }
1735                                if(strcmp(keyword, "pathmapresolution") == 0)
1736                                {
1737                                        sceneFile >> meshAtlasSize;
1738                                }
1739                                if(strcmp(keyword, "divide") == 0)
1740                                {
1741                                        sceneFile >> dividePcs;
1742                                }
1743                        }
1744                        if(wide)
1745                        {
1746                                loadMesh(wide, meshAtlasSize, meshname, dividePcs, needsUV, needsTBN);
1747                                delete wide;
1748                        }
1749
1750                }
1751
1752                if(strcmp(keyword, "entity") == 0)
1753                {
1754                        Entity e;
1755                        e.owner = this;
1756
1757                        char entityname[256];
1758                        sceneFile >> entityname;
1759                        if(strcmp(entityname, "{") == 0)
1760                                strcpy(entityname, "noname");
1761
1762                        strcpy(e.name, entityname);
1763
1764                        while(strcmp(keyword, "}") != 0 && !sceneFile.eof())
1765                        {
1766                                sceneFile >> keyword;
1767                                if(strcmp(keyword, "pathmapfile") == 0)
1768                                {
1769                                        sceneFile >> keyword;
1770                                        strcpy(e.prmfilename, keyword);
1771                                }
1772                                if(strcmp(keyword, "mesh") == 0)
1773                                {
1774                                        sceneFile >> keyword;
1775
1776                                        std::vector<PathMapEffect::RenderMesh*>::iterator i = renderMeshes.begin();
1777                                        while(i != renderMeshes.end())
1778                                        {
1779                                                if(strcmp((*i)->name, keyword) == 0)
1780                                                {
1781                                                        e.renderMesh = *i;
1782                                                        break;
1783                                                }
1784                                                i++;
1785                                        }
1786                                }
1787                                if(strcmp(keyword, "transformation") == 0)
1788                                {
1789                                        for(int i=0; i<16; i++)
1790                                                sceneFile >> e.modelWorldTransform.m[i%4][i/4];
1791                                        D3DXMatrixInverse(&e.inverseTransposedModelWorldTransform, NULL, &e.modelWorldTransform);
1792                                }
1793                                if(strcmp(keyword, "pathmapclusters") == 0)
1794                                {
1795                                        sceneFile >> e.nNearClusters;
1796                                }
1797                        }
1798                        std::vector<PathMapEffect::RenderMesh*>::iterator i = renderMeshes.begin();
1799                        while(i != renderMeshes.end())
1800                        {
1801                                if(strcmp((*i)->name, e.renderMesh->name) == 0)
1802                                {
1803                                        Entity eslab;
1804                                        eslab.renderMesh = *i;
1805                                        sprintf(eslab.prmfilename, "%s_s%d.hdr", e.prmfilename, eslab.renderMesh->slabIndex);
1806                                        eslab.modelWorldTransform = e.modelWorldTransform;
1807                                        eslab.inverseTransposedModelWorldTransform = e.inverseTransposedModelWorldTransform;
1808                                        eslab.owner = this;
1809                                        eslab.nNearClusters = e.nNearClusters;
1810
1811                                        eslab.createRayTraceEntity();
1812                                        entities.push_back(eslab);
1813                                }
1814                                i++;
1815                        }
1816                }
1817        }
1818        sceneFile.close();
1819}
1820
1821
1822LPDIRECT3DSURFACE9 renderScene(const RenderStrategy& renderStrategy)
1823{
1824        renderStrategy.applyTargets(this);
1825
1826        renderStrategy.applyRenderState();
1827
1828        if( SUCCEEDED( device->BeginScene() ) )
1829        {
1830                renderStrategy.applyTechnique();
1831                UINT nPasses;
1832                effect->Begin( &nPasses, 0 );
1833                for(UINT j=0;j<nPasses;j++)
1834                {
1835                        effect->BeginPass(j);
1836
1837                        //loop through all entities
1838                        std::vector<Entity>::iterator entityIterator = pathMapEffect->entities.begin();
1839                        while(entityIterator != pathMapEffect->entities.end())
1840                        {
1841
1842                                (*entityIterator)->drawAllSubEntities(renderStrategy);
1843                                entityIterator++;
1844                        }
1845
1846                        effect->EndPass();
1847                }
1848                effect->End();
1849                device->EndScene();
1850        }
1851
1852        renderStrategy.resetRenderState();
1853
1854}
Note: See TracBrowser for help on using the repository browser.