#include "dxstdafx.h" #include ".\subentity.h" #include "Entity.h" #include "SubMesh.h" #include "Mesh.h" #include "PathMapEffect.h" #include "DepthRenderStrategy.h" #include "Radion.hpp" #include "Transformed.h" #include "L.h" #include #include #define NFINDNEARSAMPLES 100 SubEntity::SubEntity(Entity* parent, SubMesh* subMesh, int nNearClusters) { this->parent = parent; this->subMesh = subMesh; this->nNearClusters = nNearClusters; LPDIRECT3DDEVICE9 device = subMesh->parent->pathMapEffect->device; prmxres = subMesh->parent->prmAtlasSize * nNearClusters; prmyres = subMesh->parent->prmAtlasSize; while(prmxres > 4096) { prmxres /= 2; prmyres *= 2; if(prmyres > 4096) { MessageBoxA( NULL, "PRM too big", "Error", MB_OK); exit(-1); } } device->CreateTexture(prmxres, prmyres, 1, D3DUSAGE_RENDERTARGET,D3DFMT_A16B16G16R16F,D3DPOOL_DEFAULT,&prmTexture,NULL); prmTexture->GetSurfaceLevel(0,&prmSurface); createRayTraceEntity(); } SubEntity::~SubEntity(void) { prmTexture->Release(); prmSurface->Release(); delete rayTraceEntity; } void SubEntity::createRayTraceEntity() { if(subMesh->rayTraceMesh) { rayTraceEntity = new Transformed(subMesh->rayTraceMesh); rayTraceEntity->setTransforms(parent->modelWorldTransform, parent->inverseTransposedModelWorldTransform); } else rayTraceEntity = NULL; } void SubEntity::renderPRM( std::vector& clusterRadions, unsigned int clusterId ) { LPDIRECT3DDEVICE9 device = subMesh->parent->pathMapEffect->device; LPD3DXEFFECT effect = subMesh->parent->pathMapEffect->effect; HRESULT hr; UINT nPasses=1; //# clusterId -> nearestIdx int radinx = 0xffffff; for(int i=0; iSetRenderTarget(0, prmSurface); int tilex = radinx % (prmxres / subMesh->parent->prmAtlasSize); int tiley = radinx / (prmxres / subMesh->parent->prmAtlasSize); D3DVIEWPORT9 vp, defaultViewPort; vp.X = tilex * subMesh->parent->prmAtlasSize; vp.Y = tiley * subMesh->parent->prmAtlasSize; vp.Width = vp.Height = subMesh->parent->prmAtlasSize; vp.MinZ = 0.0; vp.MaxZ = 1.0; defaultViewPort.X = defaultViewPort.Y = 0; defaultViewPort.Width = defaultViewPort.Height = subMesh->parent->pathMapEffect->DEPTHMAPRES; //clear everything device->SetRenderTarget(0, prmSurface); device->SetDepthStencilSurface(NULL); device->SetViewport(&vp); DWORD ccol = D3DCOLOR_RGBA(0,0,0,0); device->Clear( 0, NULL, D3DCLEAR_TARGET, ccol, 1.0f, 0 ); unsigned int nRadions = clusterRadions.size(); for(int ir=0; ir < nRadions; ir++) { device->SetViewport(&defaultViewPort); DepthRenderStrategy depthRenderStrategy(subMesh->parent->pathMapEffect); depthRenderStrategy.camera.SetViewParams((D3DXVECTOR3*)&clusterRadions[ir].position, (D3DXVECTOR3*)&(clusterRadions[ir].position + clusterRadions[ir].normal)); depthRenderStrategy.camera.SetProjParams( D3DX_PI/1.9, 1.0f, 0.1f, 300.0f ); //#WARN scene size! subMesh->parent->pathMapEffect->renderScene(depthRenderStrategy); // blend-add contribution of virtual light source to PRM device->SetRenderTarget(0, prmSurface); device->SetDepthStencilSurface(NULL); device->SetViewport(&vp); device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); device->SetRenderState(D3DRS_ALPHABLENDENABLE, true); device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE); device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE); device->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD); device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE); if( SUCCEEDED( device->BeginScene() ) ) { Radion radion = clusterRadions[ir]; if( effect != NULL ){ D3DXHANDLE hTechnique = effect->GetTechniqueByName((LPSTR)"BushToAtlas"); if(hTechnique==NULL){ return; } effect->SetTechnique( hTechnique ); effect->Begin( &nPasses, 0 ); for(UINT j=0;jBeginPass(j); hr=effect->SetFloatArray("lightPos", (float*)&clusterRadions[ir].position, 3); hr=effect->SetFloatArray("lightDir", (float*)&clusterRadions[ir].normal, 3); static float opttme[9] = {0.5f, 0.0f, 0.0f, 0.0f, -0.5f, 0.0f, 0.5f + (0.5f / subMesh->parent->pathMapEffect->DEPTHMAPRES), 0.5f + (0.5f / subMesh->parent->pathMapEffect->DEPTHMAPRES), 1.0f}; effect->SetTexture("depthMap", subMesh->parent->pathMapEffect->depthMapTexture); float acs = 4096.0f / nRadions; effect->SetFloat("alphaCounterStep", acs); Vector bb0 = this->rayTraceEntity->bbox.minPoint; Vector bb1 = this->rayTraceEntity->bbox.maxPoint; float nne = 5.0f / clusterRadions[ir].probability; effect->SetFloat("cutNearness2", nne); //set global params effect->SetFloatArray("occProjToTexMatrix", opttme, 9); effect->SetMatrix("occWorldToProjMatrix", &(*depthRenderStrategy.camera.GetViewMatrix() * *depthRenderStrategy.camera.GetProjMatrix())); effect->SetMatrix("modelToWorldMatrix", &(parent->modelWorldTransform)); effect->SetMatrix("inverseTransposedModelToWorldMatrix", &(parent->inverseTransposedModelWorldTransform)); Vector scaledPower = clusterRadions[ir].radiance; hr=effect->SetFloatArray("lightPower", (float*)&scaledPower, 3); effect->CommitChanges(); subMesh->drawToAtlas(); effect->EndPass(); } effect->End(); } device->EndScene(); } device->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW); device->SetRenderState(D3DRS_ALPHABLENDENABLE, false); device->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE); } } void SubEntity::normalizePRM() { LPDIRECT3DDEVICE9 device = subMesh->parent->pathMapEffect->device; LPD3DXEFFECT effect = subMesh->parent->pathMapEffect->effect; device->SetRenderTarget(0, prmSurface); device->SetDepthStencilSurface(NULL); device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE); if( SUCCEEDED( device->BeginScene() ) ) { HRESULT dfdghr = effect->SetTechnique("NormalizePRM"); UINT nPasses; effect->Begin(&nPasses, 0); effect->BeginPass(0); dfdghr = effect->SetTexture("atlas", prmTexture); effect->CommitChanges(); subMesh->parent->pathMapEffect->renderFullScreen(); effect->EndPass(); effect->End(); device->EndScene(); } device->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE); } void SubEntity::clearPRM() { LPDIRECT3DDEVICE9 device = subMesh->parent->pathMapEffect->device; LPD3DXEFFECT effect = subMesh->parent->pathMapEffect->effect; device->SetRenderTarget(0, prmSurface); device->SetDepthStencilSurface(NULL); device->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_ARGB(0, 0, 0, 0), 1.0, 0); } struct ClusterDist2{ unsigned int index; double dist2; ClusterDist2(unsigned int index, double dist2) {this->index = index; this->dist2 = dist2;} bool operator<(const ClusterDist2& o) const {return dist2 > o.dist2;} bool operator>(const ClusterDist2& o) const {return dist2 < o.dist2;} bool operator<=(const ClusterDist2& o) const {return dist2 >= o.dist2;} bool operator>=(const ClusterDist2& o) const {return dist2 <= o.dist2;} }; void SubEntity::findNearClusters(const std::vector& starters, unsigned int nClusters) { D3DXVECTOR3 cc = (D3DXVECTOR3&)rayTraceEntity->bbox.getCentre(); Radion slabRadions[NFINDNEARSAMPLES]; for(int c=0; c < NFINDNEARSAMPLES; c++) { rayTraceEntity->sampleSurface(slabRadions[c]); } std::priority_queue nearestClusterDists; unsigned int iRadion = 0; for(unsigned int iCluster = 0; iCluster < subMesh->parent->pathMapEffect->NCLUSTERS; iCluster++) { unsigned int nRadionsPerCluster = subMesh->parent->pathMapEffect->clusterLenghts[iCluster]; double ffsum = 0.0; for(unsigned int iric=0; iric < nRadionsPerCluster; iric++, iRadion++) { for(int ci=0; cidraw(); } float SubEntity::getSurfaceArea() { return rayTraceEntity->getSurfaceArea(); } void SubEntity::savePRM() { char prmFileName[300]; sprintf(prmFileName, "%s_%d.hdr", parent->prmFileName, subMesh->subsetId); D3DXSaveSurfaceToFile(L::l+prmFileName, D3DXIFF_HDR, prmSurface, NULL, NULL); } void SubEntity::loadPRM() { char prmFileName[300]; sprintf(prmFileName, "%s_%d.hdr", parent->prmFileName, subMesh->subsetId); D3DXLoadSurfaceFromFile(prmSurface, NULL, NULL, L::l+prmFileName, NULL, D3DX_DEFAULT, 0, NULL); } Intersectable* SubEntity::getRayTraceEntity() { return rayTraceEntity; } const Material* SubEntity::sampleSurface(Radion& sample) { rayTraceEntity->sampleSurface(sample); return rayTraceEntity->getMaterial(); } void SubEntity::saveSceneInfo(std::ofstream& psf) { psf << "\t\tsubentity " << subMesh->subsetId << " clusters "; for(int buu=0; buu