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

Revision 2197, 9.4 KB checked in by szirmay, 18 years ago (diff)
Line 
1#include "dxstdafx.h"
2#include ".\subentity.h"
3#include "Entity.h"
4#include "SubMesh.h"
5#include "Mesh.h"
6#include "PathMapEffect.h"
7#include "DepthRenderStrategy.h"
8#include "Radion.hpp"
9#include "Transformed.h"
10#include "L.h"
11#include <queue>
12#include <fstream>
13
14#define NFINDNEARSAMPLES 100
15
16SubEntity::SubEntity(Entity* parent, SubMesh* subMesh, int nNearClusters)
17{
18        this->parent = parent;
19        this->subMesh = subMesh;
20        this->nNearClusters = nNearClusters;
21
22        LPDIRECT3DDEVICE9 device = subMesh->parent->pathMapEffect->device;
23
24        prmxres = subMesh->parent->prmAtlasSize * nNearClusters;
25        prmyres = subMesh->parent->prmAtlasSize;
26        while(prmxres > 4096)
27        {
28                prmxres /= 2;
29                prmyres *= 2;
30                if(prmyres > 4096)
31                {
32                        MessageBoxA( NULL, "PRM too big", "Error", MB_OK);
33                        exit(-1);
34                }
35        }
36
37        device->CreateTexture(prmxres,  prmyres, 1, D3DUSAGE_RENDERTARGET,D3DFMT_A16B16G16R16F,D3DPOOL_DEFAULT,&prmTexture,NULL);
38        prmTexture->GetSurfaceLevel(0,&prmSurface);
39
40        createRayTraceEntity();
41}
42
43SubEntity::~SubEntity(void)
44{
45        prmTexture->Release();
46        prmSurface->Release();
47        delete rayTraceEntity;
48}
49
50void SubEntity::createRayTraceEntity()
51{
52        if(subMesh->rayTraceMesh)
53        {
54                rayTraceEntity = new Transformed(subMesh->rayTraceMesh);
55                rayTraceEntity->setTransforms(parent->modelWorldTransform, parent->inverseTransposedModelWorldTransform);
56        }
57        else
58                rayTraceEntity = NULL;
59
60}
61
62void SubEntity::renderPRM(      std::vector<Radion>& clusterRadions, unsigned int clusterId     )
63{
64        LPDIRECT3DDEVICE9 device = subMesh->parent->pathMapEffect->device;
65        LPD3DXEFFECT effect = subMesh->parent->pathMapEffect->effect;
66
67        HRESULT hr;     UINT nPasses=1;
68
69        //# clusterId -> nearestIdx
70        int radinx = 0xffffff;
71        for(int i=0; i<nNearClusters; i++)
72                if(nearClusterIndices[i] == clusterId)
73                        radinx = i;
74        if(radinx == 0xffffff)
75                return;
76
77/*      if(clusterId != 0)
78                return;*/
79
80        hr = device->SetRenderTarget(0, prmSurface);
81        int tilex = radinx % (prmxres / subMesh->parent->prmAtlasSize);
82        int tiley = radinx / (prmxres / subMesh->parent->prmAtlasSize);
83
84        D3DVIEWPORT9 vp, defaultViewPort;
85        vp.X = tilex * subMesh->parent->prmAtlasSize;                   vp.Y = tiley * subMesh->parent->prmAtlasSize;
86        vp.Width = vp.Height = subMesh->parent->prmAtlasSize;
87        vp.MinZ = 0.0; vp.MaxZ = 1.0;
88
89        defaultViewPort.X = defaultViewPort.Y = 0;
90        defaultViewPort.Width = defaultViewPort.Height = subMesh->parent->pathMapEffect->DEPTHMAPRES;
91
92        //clear everything
93        device->SetRenderTarget(0, prmSurface);
94        device->SetDepthStencilSurface(NULL);
95        device->SetViewport(&vp);
96
97        DWORD ccol = D3DCOLOR_RGBA(0,0,0,0);
98        device->Clear( 0, NULL, D3DCLEAR_TARGET,
99                                                ccol, 1.0f, 0 );
100
101        unsigned int nRadions = clusterRadions.size();
102        for(int ir=0; ir < nRadions; ir++)
103        {
104                device->SetViewport(&defaultViewPort);
105                DepthRenderStrategy depthRenderStrategy(subMesh->parent->pathMapEffect);
106
107                depthRenderStrategy.camera.SetViewParams((D3DXVECTOR3*)&clusterRadions[ir].position, (D3DXVECTOR3*)&(clusterRadions[ir].position + clusterRadions[ir].normal));
108                depthRenderStrategy.camera.SetProjParams( D3DX_PI/1.9, 1.0f, 0.1f, 300.0f ); //#WARN scene size!
109
110                subMesh->parent->pathMapEffect->renderScene(depthRenderStrategy);
111
112                // blend-add contribution of virtual light source to PRM
113                device->SetRenderTarget(0, prmSurface);
114                device->SetDepthStencilSurface(NULL);
115                device->SetViewport(&vp);
116                device->SetRenderState(D3DRS_CULLMODE,  D3DCULL_NONE);
117                device->SetRenderState(D3DRS_ALPHABLENDENABLE,  true);
118                device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
119                device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
120                device->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
121                device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
122
123                if( SUCCEEDED( device->BeginScene() ) )
124                {
125                        Radion radion = clusterRadions[ir];
126
127                        if( effect != NULL ){
128                                D3DXHANDLE hTechnique = effect->GetTechniqueByName((LPSTR)"BushToAtlas");
129                                if(hTechnique==NULL){
130                                        return;
131                                }
132                                effect->SetTechnique( hTechnique );
133                               
134                                effect->Begin( &nPasses, 0 );
135                                for(UINT j=0;j<nPasses;j++){
136                                        effect->BeginPass(j);
137
138                                        hr=effect->SetFloatArray("lightPos", (float*)&clusterRadions[ir].position, 3);
139                                        hr=effect->SetFloatArray("lightDir", (float*)&clusterRadions[ir].normal, 3);
140                                        static float opttme[9] = {0.5f, 0.0f, 0.0f,
141                                                                                        0.0f, -0.5f, 0.0f,
142                                                                                        0.5f + (0.5f / subMesh->parent->pathMapEffect->DEPTHMAPRES), 0.5f + (0.5f / subMesh->parent->pathMapEffect->DEPTHMAPRES), 1.0f};
143                                        effect->SetTexture("depthMap", subMesh->parent->pathMapEffect->depthMapTexture);
144
145                                        float acs = 4096.0f / nRadions;
146                                        effect->SetFloat("alphaCounterStep", acs);
147
148                                        Vector bb0 = this->rayTraceEntity->bbox.minPoint;
149                                        Vector bb1 = this->rayTraceEntity->bbox.maxPoint;
150                                        float nne = 5.0f / clusterRadions[ir].probability;
151                                        effect->SetFloat("cutNearness2", nne);
152                                       
153                                        //set global params
154                                        effect->SetFloatArray("occProjToTexMatrix", opttme, 9);
155                                        effect->SetMatrix("occWorldToProjMatrix", &(*depthRenderStrategy.camera.GetViewMatrix() * *depthRenderStrategy.camera.GetProjMatrix()));
156                                        effect->SetMatrix("modelToWorldMatrix", &(parent->modelWorldTransform));
157                                        effect->SetMatrix("inverseTransposedModelToWorldMatrix", &(parent->inverseTransposedModelWorldTransform));
158                                        Vector scaledPower = clusterRadions[ir].radiance;
159                                        hr=effect->SetFloatArray("lightPower", (float*)&scaledPower, 3);
160                                       
161                                        effect->CommitChanges();
162                                        subMesh->drawToAtlas();
163
164                                        effect->EndPass();
165                                }
166                                effect->End();
167                        }
168                        device->EndScene();
169
170                }
171                device->SetRenderState(D3DRS_CULLMODE,  D3DCULL_CCW);
172                device->SetRenderState(D3DRS_ALPHABLENDENABLE,  false);
173                device->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
174        }
175}
176
177void SubEntity::normalizePRM()
178{
179        LPDIRECT3DDEVICE9 device = subMesh->parent->pathMapEffect->device;
180        LPD3DXEFFECT effect = subMesh->parent->pathMapEffect->effect;
181
182        device->SetRenderTarget(0, prmSurface);
183        device->SetDepthStencilSurface(NULL);
184
185        device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
186        if( SUCCEEDED( device->BeginScene() ) )
187        {
188                HRESULT dfdghr = effect->SetTechnique("NormalizePRM");
189                UINT nPasses;
190                effect->Begin(&nPasses, 0);
191                effect->BeginPass(0);
192
193                dfdghr = effect->SetTexture("atlas", prmTexture);
194                effect->CommitChanges();
195
196                subMesh->parent->pathMapEffect->renderFullScreen();
197
198                effect->EndPass();
199                effect->End();
200                device->EndScene();
201        }
202        device->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
203}
204
205void SubEntity::clearPRM()
206{
207        LPDIRECT3DDEVICE9 device = subMesh->parent->pathMapEffect->device;
208        LPD3DXEFFECT effect = subMesh->parent->pathMapEffect->effect;
209
210        device->SetRenderTarget(0, prmSurface);
211        device->SetDepthStencilSurface(NULL);
212
213        device->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0, 0, 0, 0), 1.0, 0);
214}
215
216struct ClusterDist2{
217        unsigned int index;
218        double dist2;
219        ClusterDist2(unsigned int index, double dist2) {this->index = index; this->dist2 = dist2;}
220        bool operator<(const ClusterDist2& o) const {return dist2 > o.dist2;}
221        bool operator>(const ClusterDist2& o) const {return dist2 < o.dist2;}
222        bool operator<=(const ClusterDist2& o) const {return dist2 >= o.dist2;}
223        bool operator>=(const ClusterDist2& o) const {return dist2 <= o.dist2;}
224};
225
226
227void SubEntity::findNearClusters(const std::vector<Radion>& starters, unsigned int nClusters)
228{
229        D3DXVECTOR3 cc = (D3DXVECTOR3&)rayTraceEntity->bbox.getCentre();
230
231        Radion slabRadions[NFINDNEARSAMPLES];
232        for(int c=0; c < NFINDNEARSAMPLES; c++)
233        {
234                rayTraceEntity->sampleSurface(slabRadions[c]);
235        }
236
237        std::priority_queue<ClusterDist2> nearestClusterDists;
238
239        unsigned int iRadion = 0;
240        for(unsigned int iCluster = 0; iCluster < subMesh->parent->pathMapEffect->NCLUSTERS; iCluster++)
241        {
242                unsigned int nRadionsPerCluster = subMesh->parent->pathMapEffect->clusterLenghts[iCluster];
243                double ffsum = 0.0;
244                for(unsigned int iric=0; iric < nRadionsPerCluster; iric++, iRadion++)
245                {
246                        for(int ci=0; ci<NFINDNEARSAMPLES; ci++)
247                        {
248                                //ffsum += starters[iRadion].getFormFactorTo(slabRadions[ci]);
249                                ffsum += 1.0 / (starters[iRadion].position - slabRadions[ci].position).norm2();
250                        }
251                }
252                nearestClusterDists.push( ClusterDist2(iCluster, nRadionsPerCluster / ffsum) );
253        }
254        for(unsigned int i=0; i<nNearClusters; i++)
255        {
256//              nearClusterIndices[i] = nNearClusters - 1 - i;
257                nearClusterIndices[i] = nearestClusterDists.top().index;
258                nearestClusterDists.pop();
259        }
260}
261
262void SubEntity::draw(const RenderStrategy& renderStrategy)
263{
264        renderStrategy.applyTextures(this);
265        subMesh->draw();
266}
267
268float SubEntity::getSurfaceArea()
269{
270        return rayTraceEntity->getSurfaceArea();
271}
272
273void SubEntity::savePRM()
274{
275        char prmFileName[300];
276        sprintf(prmFileName, "%s_%d.hdr", parent->prmFileName, subMesh->subsetId);
277        D3DXSaveSurfaceToFile(L::l+prmFileName, D3DXIFF_HDR, prmSurface, NULL, NULL);
278}
279
280void SubEntity::loadPRM()
281{
282        char prmFileName[300];
283        sprintf(prmFileName, "%s_%d.hdr", parent->prmFileName, subMesh->subsetId);
284        D3DXLoadSurfaceFromFile(prmSurface, NULL, NULL, L::l+prmFileName, NULL, D3DX_DEFAULT, 0, NULL);
285}
286
287Intersectable* SubEntity::getRayTraceEntity()
288{
289        return rayTraceEntity;
290}
291
292const Material* SubEntity::sampleSurface(Radion& sample)
293{
294        rayTraceEntity->sampleSurface(sample);
295        return rayTraceEntity->getMaterial();
296}
297
298void SubEntity::saveSceneInfo(std::ofstream& psf)
299{
300        psf << "\t\tsubentity " << subMesh->subsetId << " clusters ";
301        for(int buu=0; buu<nNearClusters; buu++)
302                psf << nearClusterIndices[buu] << ' ';
303        psf << '\n';
304}
Note: See TracBrowser for help on using the repository browser.