Index: GTP/trunk/App/Demos/Illum/PathMap/media/hangar.x
===================================================================
--- GTP/trunk/App/Demos/Illum/PathMap/media/hangar.x	(revision 896)
+++ GTP/trunk/App/Demos/Illum/PathMap/media/hangar.x	(revision 1480)
@@ -230,4 +230,8 @@
      0.400000;0.400000;0.400000;;
      0.000000;0.000000;0.000000;;
+
+     TextureFilename {
+      "hangar2.bmp";
+     } 
     }
    }
Index: GTP/trunk/App/Demos/Illum/PathMap/PathMapEffect.h
===================================================================
--- GTP/trunk/App/Demos/Illum/PathMap/PathMapEffect.h	(revision 896)
+++ GTP/trunk/App/Demos/Illum/PathMap/PathMapEffect.h	(revision 1480)
@@ -10,5 +10,5 @@
 #define DBLATLASSIZE (ATLASSIZE * 2.0)
 
-#define NRADIONS	4096
+#define NRADIONS		(4096)
 #define NCLUSTERS	32
 #define DEPTHMAPRES	512
@@ -93,4 +93,6 @@
 	struct RenderMesh
 	{
+		char				name[256];
+
 		unsigned int		nSubsets;	//!< number of submeshes (with possible different material)
 		LPD3DXMESH			mesh;		//!< D3D mesh
@@ -132,4 +134,9 @@
 	struct Entity
 	{
+		char				name[256];
+		char				prmfilename[256];
+		int					nNearClusters;
+		int					rpmAtlasSize;
+
 		PathMapEffect* owner;	//!< enclosing class instance
 
@@ -152,5 +159,5 @@
 
 		//! array of cluster indices storing which clusters are relevant. PRM tiles correspond to these clusters
-		unsigned int nearClusterIndices[NCLUSTERSPERENTITY];
+		unsigned int nearClusterIndices[32];
 
 		//! fill the nearClusterIndices array
@@ -245,3 +252,7 @@
 	//! restore all precomputed data for the scene from folder prm
 	void loadPathMaps();
+
+	void exportEntityData();
+
+	void loadScene(const char* sceneFileName);
 };
Index: GTP/trunk/App/Demos/Illum/PathMap/Transformed.cpp
===================================================================
--- GTP/trunk/App/Demos/Illum/PathMap/Transformed.cpp	(revision 896)
+++ GTP/trunk/App/Demos/Illum/PathMap/Transformed.cpp	(revision 1480)
@@ -93,5 +93,8 @@
 void Transformed::setTransforms(D3DXMATRIX& mw, D3DXMATRIX& itmw)
 {
-	modelToWorld.fill(mw[0], mw[1], mw[2], mw[4], mw[5], mw[6], mw[8], mw[9], mw[10], mw[12], mw[13], mw[14]); 
+	modelToWorld.fill(mw[0]/(mw[3]+mw[15]), mw[1]/(mw[3]+mw[15]), mw[2]/(mw[3]+mw[15]),
+		mw[4]/(mw[7]+mw[15]), mw[5]/(mw[7]+mw[15]), mw[6]/(mw[7]+mw[15]),
+		mw[8]/(mw[11]+mw[15]), mw[9]/(mw[11]+mw[15]), mw[10]/(mw[11]+mw[15]),
+		mw[12]/mw[15], mw[13]/mw[15], mw[14]/mw[15]);
 	worldToModel.setInvert(modelToWorld);
 }
@@ -102,5 +105,5 @@
 	Vector su;
 	worldToModel.transformDirection(si, su);
-	return object->getSurfaceArea();// * su.norm2();
+	return object->getSurfaceArea() * su.norm2();
 }
 
@@ -114,3 +117,7 @@
 	radion.normal = trnorm;
 	radion.normal.normalize();
+	Vector si(1.0f, 0.0f, 0.0f);
+	Vector su;
+	worldToModel.transformDirection(si, su);
+	radion.radiance.z /= su.norm2();
 }
Index: GTP/trunk/App/Demos/Illum/PathMap/bushToAtlas.fx
===================================================================
--- GTP/trunk/App/Demos/Illum/PathMap/bushToAtlas.fx	(revision 896)
+++ GTP/trunk/App/Demos/Illum/PathMap/bushToAtlas.fx	(revision 1480)
@@ -29,5 +29,5 @@
   
     output.worldPos = mul(input.pos, modelToWorldMatrix);
-    output.normal = mul(input.normal, inverseTransposedModelToWorldMatrix);
+    output.normal = mul(inverseTransposedModelToWorldMatrix, float4(input.normal, 0));
 	output.occProjPos = mul(output.worldPos, occWorldToProjMatrix);	    
     output.tex = input.tex;
Index: GTP/trunk/App/Demos/Illum/PathMap/PathMapEffect.cpp
===================================================================
--- GTP/trunk/App/Demos/Illum/PathMap/PathMapEffect.cpp	(revision 896)
+++ GTP/trunk/App/Demos/Illum/PathMap/PathMapEffect.cpp	(revision 1480)
@@ -84,15 +84,20 @@
 	//set up a scene
 
+	loadScene("media\\level.txt");
+
 	//load hangar mesh
-	loadMesh( L"media\\fulltexchamber.x" );
-
-	//create hangar entity
+	loadMesh( L"media\\hangar.x" );
+//	loadMesh( L"media\\fulltexchamber.x" );
+
+/*	//create hangar entity
 	Entity e1;
 	e1.owner = this;
 	e1.renderMesh = renderMeshes.at(0);
 	D3DXMatrixIdentity(&e1.modelWorldTransform);
-//	D3DXMatrixScaling(&e1.modelWorldTransform, 0.5f, 1.0f, 0.5f);
+//	D3DXMatrixScaling(&e1.modelWorldTransform, 20.0f, 20.0f, 20.0f);
+	D3DXMatrixScaling(&e1.modelWorldTransform, 0.5f, 1.0f, 0.5f);
 	D3DXMatrixIdentity(&e1.inverseTransposedModelWorldTransform);
-//	D3DXMatrixScaling(&e1.inverseTransposedModelWorldTransform, 1.0f/0.5f, 1.0f, 1.0f/0.5f);
+//	D3DXMatrixScaling(&e1.inverseTransposedModelWorldTransform, 1.0f/20.0f, 1.0f/20.0f, 1.0f/20.0f);
+	D3DXMatrixScaling(&e1.inverseTransposedModelWorldTransform, 1.0f/0.5f, 1.0f, 1.0f/0.5f);
 
 	e1.createRayTraceEntity();
@@ -102,27 +107,34 @@
 
 	//load 'steps' mesh
-/*	loadMesh( L"media\\steps.x" );
+	loadMesh( L"media\\steps.x" );
 
 	//create step entities
-	//for(int eitor=0; eitor < 6; eitor++)
-	{
+	for(int eitor=0; eitor < 4; eitor++)
+	{
+		D3DXMATRIX urr;
+		D3DXMATRIX rx;		D3DXMatrixRotationY(&rx, Vector::PI * 0.5f * eitor);
 		Entity e2;
 		e2.owner = this;
 		e2.renderMesh = renderMeshes.at(1);
-		D3DXMatrixTranslation(&e2.modelWorldTransform, 0.0f, -14.0f, 0.0f);
+
+		D3DXMatrixTranslation(&urr, -15.0f, -14.0f, -7.0f);
+		D3DXMatrixMultiply( &e2.modelWorldTransform, &urr, &rx);
+		D3DXMatrixInverse(&e2.inverseTransposedModelWorldTransform, NULL, &e2.modelWorldTransform);
+
+		e2.createRayTraceEntity();
+		entities.push_back(e2);
+
+		D3DXMATRIX trasi, roti;
+		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
+		D3DXMatrixRotationYawPitchRoll(&roti, -Vector::PI * 0.5, Vector::PI, 0.0);
+		D3DXMatrixMultiply(&urr, &roti, &trasi);
+
+		D3DXMatrixMultiply( &e2.modelWorldTransform, &urr, &rx);
+
 		D3DXMatrixInverse(&e2.inverseTransposedModelWorldTransform, NULL, &e2.modelWorldTransform);
 		e2.createRayTraceEntity();
 		entities.push_back(e2);
-
-		D3DXMATRIX trasi, roti;
-		D3DXMatrixTranslation(&trasi, 7.0f, 14.0f, -7.0f);//7.25f, 13.5, -7.25); //rot 90 -90 90 trans 7.25 13.5 -7.25
-		D3DXMatrixRotationYawPitchRoll(&roti, -Vector::PI * 0.5, Vector::PI, 0.0);
-//		D3DXMatrixIdentity(&roti);
-		D3DXMatrixMultiply(&e2.modelWorldTransform, &roti, &trasi);
-		D3DXMatrixInverse(&e2.inverseTransposedModelWorldTransform, NULL, &e2.modelWorldTransform);
-		e2.createRayTraceEntity();
-		entities.push_back(e2);
-	}*/
-
+	}
+*/
 /*	for(int eitor=0; eitor < 6; eitor++)
 	{
@@ -143,4 +155,6 @@
 	}*/
 
+	loadMesh( L"media\\torch.x" );
+
 	//compute the surface area of the complete geometry. useful for random sampling.
 	sumSurfaceArea = 0.0;
@@ -165,5 +179,5 @@
 	lightCamera->SetProjParams( D3DX_PI/1.9, 1.0f, 0.1f, 300.0f );
 
-	//create ray tracing kd-tree containg ray-traceable versions of entities 
+	//create ray tracing kd-tree containing ray-traceable versions of entities 
 	Intersectable** objs = new Intersectable*[entities.size()];
 	for(int u=0; u<entities.size(); u++)
@@ -212,4 +226,7 @@
 	fillRadionPosArray(pData);
 	starterVertexBuffer->Unlock();
+
+
+	exportEntityData();
 
 #ifdef GENERATE_PATH_MAPS
@@ -437,5 +454,5 @@
 	D3DXVECTOR3 lightDir = *lightCamera->GetWorldAhead();
 	lightDir /= D3DXVec3Length( &lightDir );
-	float ffl = parameters->Get(fLightScale) * 1.0f;
+	float ffl = parameters->Get(fLightScale) * 100.0f;
 	D3DXVECTOR3 lightPower(ffl, ffl, ffl);
 
@@ -544,8 +561,5 @@
 			for(unsigned int y=0; y<NCLUSTERSPERENTITY; y++)
 				weightsa[y] = weights[entityIterator->nearClusterIndices[y]];
-			//## could sort weightsa, indicesa and use first few
 			hr = effect->SetFloatArray("weightsa", weightsa, NCLUSTERSPERENTITY);
-			INT* pr = (INT*)entityIterator->nearClusterIndices;
-			hr = effect->SetIntArray("indicesa", (INT*)entityIterator->nearClusterIndices, NCLUSTERSPERENTITY);
 			effect->SetMatrix("modelToWorldMatrix", &entityIterator->modelWorldTransform);
 			effect->SetMatrix("inverseTransposedModelToWorldMatrix", &entityIterator->inverseTransposedModelWorldTransform);
@@ -578,4 +592,23 @@
 		device->EndScene();
 	}
+
+	if(!parameters->Get(bLookFromLight))
+	if( SUCCEEDED( device->BeginScene() ) )
+	{
+		effect->SetTechnique("torch");
+		UINT nPasses;
+		effect->Begin(&nPasses, 0);
+		effect->BeginPass(0);
+
+		effect->SetMatrix("modelToProjMatrix", &(*lightCamera->GetWorldMatrix() * *camera->GetViewMatrix()  * *camera->GetProjMatrix()  ));
+
+		effect->CommitChanges();
+		renderMeshes[renderMeshes.size()-1]->mesh->DrawSubset(0);
+
+		effect->EndPass();
+		effect->End();
+		device->EndScene();
+	}
+
 }
 
@@ -913,5 +946,5 @@
 	for(unsigned int i=0; i<NCLUSTERS; i++)
 		clusterLenghts[i] = NRADIONS / NCLUSTERS;
-	for(unsigned int iKMeans = 0; iKMeans < 10; iKMeans++)
+	for(unsigned int iKMeans = 0; iKMeans < 128; iKMeans++)
 	{
 		//find centroids
@@ -943,6 +976,6 @@
 				for(unsigned int u=0; u<NCLUSTERS; u++)
 				{
-					float dirDist = 2.0f - (bushStarters.at(iRadion).normal * centroids[u].normal);
-					float dist = (bushStarters.at(iRadion).position - centroids[u].position).norm() * dirDist;
+					float dirDist = (bushStarters.at(iRadion).normal * centroids[u].normal);
+					float dist = (bushStarters.at(iRadion).position - centroids[u].position).norm() * pow(6.0, 1.0 - (double)dirDist);
 					if(dist < minimumDistance)
 					{
@@ -1654,5 +1687,5 @@
 	for(unsigned int i=0; i<32; i++)
 	{
-		nearClusterIndices[i] = i;// nearestClusterDists.top().index;
+		nearClusterIndices[i] = 31 - i;// nearestClusterDists.top().index;
 		nearestClusterDists.pop();
 	}
@@ -1683,5 +1716,7 @@
 	{
 		wchar_t prmFileName[256];
-		wsprintf(prmFileName, L"prm\\prm_%08d.hdr", iEntity);
+//		wsprintf(prmFileName, L"prm\\prm_%08d.hdr", iEntity);
+		MultiByteToWideChar(CP_ACP, 0, entityIterator->prmfilename, -1, prmFileName, 255);
+
 		D3DXSaveSurfaceToFile(prmFileName, D3DXIFF_HDR, entityIterator->prmSurface, NULL, NULL);
 		entityIterator++;
@@ -1717,5 +1752,6 @@
 
 		wchar_t prmFileName[256];
-		wsprintf(prmFileName, L"prm\\prm_%08d.hdr", iEntity);
+//		wsprintf(prmFileName, L"prm\\prm_%08d.hdr", iEntity);
+		MultiByteToWideChar(CP_ACP, 0, entityIterator->prmfilename, -1, prmFileName, 255);
 		D3DXLoadSurfaceFromFile(entityIterator->prmSurface, NULL, NULL, prmFileName, NULL, D3DX_DEFAULT, 0, NULL);
 		entityIterator++;
@@ -1723,2 +1759,115 @@
 	}
 }
+
+void PathMapEffect::exportEntityData()
+{
+	std::fstream entryPointFile("media\\entityPathMapData.txt", std::ios::out);
+
+	unsigned int iEntity = 0;
+	std::vector<PathMapEffect::Entity>::iterator entityIterator = entities.begin();
+	while(entityIterator != entities.end())
+	{
+		entryPointFile << "entity " << entityIterator->name << '\n';
+		entryPointFile << "{" << '\n';
+		entryPointFile << " pathmapfile " << entityIterator->prmfilename << '\n';
+		entryPointFile << " clusters ";
+		for(int i=0; i<NCLUSTERSPERENTITY; i++)
+			entryPointFile << entityIterator->nearClusterIndices[i] << " ";
+		entryPointFile << '\n';
+		entryPointFile << "}" << '\n';
+		entryPointFile << '\n';
+
+//		for(int i=0; i<16; i++)
+//			entryPointFile << entityIterator->modelWorldTransform.m[i%4][i/4] << " ";
+		entryPointFile << '\n';
+		entityIterator++;
+		iEntity++;
+	}
+
+	entryPointFile.flush();
+	entryPointFile.close();
+
+}
+
+void PathMapEffect::loadScene(const char* sceneFileName)
+{
+	std::fstream sceneFile(sceneFileName, std::ios::in);
+
+	char keyword[256];
+	while(!sceneFile.eof())
+	{
+		sceneFile >> keyword;
+		if(strcmp(keyword, "mesh") == 0)
+		{
+			char meshname[256];
+			sceneFile >> meshname;
+			if(strcmp(meshname, "{") == 0)
+				strcpy(meshname, "mesh");
+			while(strcmp(keyword, "}") != 0 && !sceneFile.eof())
+			{
+				sceneFile >> keyword;
+				if(strcmp(keyword, "xfile") == 0)
+				{
+					sceneFile >> keyword;
+					wchar_t* wide = NULL;
+					if(keyword)
+					{
+						wide = new wchar_t[MultiByteToWideChar(CP_ACP, 0, keyword, -1, NULL, 0)];
+						MultiByteToWideChar(CP_ACP, 0, keyword, -1, wide, 511);
+					}
+					loadMesh(wide);
+					strcpy(renderMeshes[renderMeshes.size()-1]->name, meshname);
+					delete wide;
+				}
+			}
+		}
+
+		if(strcmp(keyword, "entity") == 0)
+		{
+			Entity e;
+			e.owner = this;
+
+			char entityname[256];
+			sceneFile >> entityname;
+			if(strcmp(entityname, "{") == 0)
+				strcpy(entityname, "noname");
+
+			strcpy(e.name, entityname);
+
+			while(strcmp(keyword, "}") != 0 && !sceneFile.eof())
+			{
+				sceneFile >> keyword;
+				if(strcmp(keyword, "pathmapfile") == 0)
+				{
+					sceneFile >> keyword;
+					strcpy(e.prmfilename, keyword);
+				}
+				if(strcmp(keyword, "mesh") == 0)
+				{
+					sceneFile >> keyword;
+
+					std::vector<PathMapEffect::RenderMesh*>::iterator i = renderMeshes.begin();
+					while(i != renderMeshes.end())
+					{
+						if(strcmp((*i)->name, keyword) == 0)
+						{
+							e.renderMesh = *i;
+							break;
+						}
+						i++;
+					}
+				}
+				if(strcmp(keyword, "transformation") == 0)
+				{
+					for(int i=0; i<16; i++)
+						sceneFile >> e.modelWorldTransform.m[i%4][i/4];
+					D3DXMatrixInverse(&e.inverseTransposedModelWorldTransform, NULL, &e.modelWorldTransform);
+				}
+			}
+
+			e.createRayTraceEntity();
+			entities.push_back(e);
+		}
+	}
+	sceneFile.close();
+}
Index: GTP/trunk/App/Demos/Illum/PathMap/Transformation.hpp
===================================================================
--- GTP/trunk/App/Demos/Illum/PathMap/Transformation.hpp	(revision 896)
+++ GTP/trunk/App/Demos/Illum/PathMap/Transformation.hpp	(revision 1480)
@@ -37,5 +37,5 @@
 					float m20, float m21, float m22,
 					float t0, float t1, float t2){
-		m[0][0] = m00;
+/*		m[0][0] = m00;
 		m[0][1] = m01;
 		m[0][2] = m02;
@@ -47,6 +47,18 @@
 		m[2][0] = m20;
 		m[2][1] = m21;
+		m[2][2] = m22;*/
+		
+		m[0][0] = m00;
+		m[1][0] = m01;
+		m[2][0] = m02;
+
+		m[0][1] = m10;
+		m[1][1] = m11;
+		m[2][1] = m12;
+
+		m[0][2] = m20;
+		m[1][2] = m21;
 		m[2][2] = m22;
-		
+
 		t[0] = t0;
 		t[1] = t1;
Index: GTP/trunk/App/Demos/Illum/PathMap/pathMap.fx
===================================================================
--- GTP/trunk/App/Demos/Illum/PathMap/pathMap.fx	(revision 896)
+++ GTP/trunk/App/Demos/Illum/PathMap/pathMap.fx	(revision 1480)
@@ -43,5 +43,4 @@
 
 float4		weightsa[8];
-int4		indicesa[8];
 
 struct vsInputWalk
@@ -71,5 +70,5 @@
 	output.occProjPos = mul(output.worldPos, occWorldToProjMatrix);	
 	
-	output.normal = mul(float4(input.normal.xyz, 0.0), inverseTransposedModelToWorldMatrix);
+	output.normal = mul(inverseTransposedModelToWorldMatrix, float4(input.normal.xyz, 0.0));
 	output.tex = input.tex;
 	
@@ -84,23 +83,28 @@
 	
 	float3 col = 0;
-	for(int iCluster=0; iCluster<8; iCluster++)
+	for(int iCluster=0; iCluster<32; iCluster++)
 	{
-		int4 index = indicesa[iCluster];
-		float4 weight = weightsa[iCluster];
+		float4 weight = weightsa[iCluster/4];
 		float3 val = tex2D(filteredAtlasSampler, float2(
-			input.tex.x / 32.0 + 1.0 / 32.0 * (index.x % 32) + 0.0 / 4096.0, 1.0 - input.tex.y + 0.0 / 128.0));
+			input.tex.x / 32.0 + 1.0 / 32.0 * (iCluster % 32) + 0.0 / 4096.0, 1.0 - input.tex.y + 0.0 / 128.0));
 		col += val.xyz * weight.x;
+		iCluster++;
+		
 		val = tex2D(filteredAtlasSampler, float2(
-			input.tex.x / 32.0 + 1.0 / 32.0 * (index.y % 32) + 0.0 / 4096.0, 1.0 - input.tex.y  + 0.0 / 128.0));
+			input.tex.x / 32.0 + 1.0 / 32.0 * (iCluster % 32) + 0.0 / 4096.0, 1.0 - input.tex.y  + 0.0 / 128.0));
 		col += val.xyz * weight.y;
+		iCluster++;
+		
 		val = tex2D(filteredAtlasSampler, float2(
-			input.tex.x / 32.0 + 1.0 / 32.0 * (index.z % 32) + 0.0 / 4096.0, 1.0 - input.tex.y  + 0.0 / 128.0));
+			input.tex.x / 32.0 + 1.0 / 32.0 * (iCluster % 32) + 0.0 / 4096.0, 1.0 - input.tex.y  + 0.0 / 128.0));
 		col += val.xyz * weight.z;
+		iCluster++;
+		
 		val = tex2D(filteredAtlasSampler, float2(
- 			input.tex.x / 32.0 + 1.0 / 32.0 * (index.w % 32) + 0.0 / 4096.0, 1.0 - input.tex.y  + 0.0 / 128.0));
+ 			input.tex.x / 32.0 + 1.0 / 32.0 * (iCluster % 32) + 0.0 / 4096.0, 1.0 - input.tex.y  + 0.0 / 128.0));
 		col += val.xyz * weight.w;
 	}
 //	col *= 1000.01; 
-//	col *= 0.0001;
+//	col *= 0.8;
 //	col = 0;
 
@@ -133,2 +137,3 @@
 #include "depthMap.fx"
 #include "dots.fx"
+#include "torch.tx"
Index: GTP/trunk/App/Demos/Illum/PathMap/ReadMe.txt
===================================================================
--- GTP/trunk/App/Demos/Illum/PathMap/ReadMe.txt	(revision 1470)
+++ GTP/trunk/App/Demos/Illum/PathMap/ReadMe.txt	(revision 1480)
@@ -1,16 +1,64 @@
-The Path Map standalone module implements the Light Path Map approach for indirect lighting.Its purpose is to add realism to computer games by computing dynamically changing indirect illumination. It is an improvement over ambient lighting or static light maps. Not unlike light maps, global illumination computations are performed in a precomputing step, using ray casting and indirect photon mapping (the virtual light sources method). The contributions of virtual light samples are computed on the GPU, with depth mapping. However, instead of computing a single light map, multiple texture atlases (constituting the PRM) are generated for the scene objects, all corresponding to a cluster of indirect lighting samples. Then these atlases are combined according to actual lighting conditions. Weighting factors depend on how much light actually arrives at the sample points used for PRM generation. This computation is also performed in a GPU pass.
+GameTools standalone tool:
+
+Real-time global illumination
+#############################
 
 
-Run
----
-Copy PathMap.exe (from the Debug or Release directory) to the solution'S directory and run.
+Provided effect:
+#################
 
-Build
------
-Simply load and build the solution file (PathMap_2003.sln)
+Indirect illumination with Precomputed Radiance Maps (PRM)
 
-Usage
------
+Standalone final rendering (real time GI) application without or with [if
+GENERATE_PATH_MAPS is defined in PathMapEffect.cpp] PRM precomputing
 
-There is a number of on-screen controls available to navigate the scene and adjust lighting. Use the mouse to look around, the A, S, D, W keys to move. If the Move light box is checked, the same controls move the light source. If Look from light is checked, the scene is rendered as seen from the light source instead of the camera. It is convenient to check both boxes when positioning the light source. Selecting the Entry points checkbox will add small squares to the scene to indicate entry points. Colors indicate weights. The clustering also becomes visible. The Turbo checkbox toggles camera movement speed. Pressing the Tab button will display a PRM texture, or revert to scene rendering. The technique ShowTex may be modified to display other internal textures for illustration. The slider Tone scale allows scaling the resulting image, which can also be viewed as changing the light source intensity.
- 
+
+Algorithm benefits:
+###################
+Provides real-time indirect illumination. As opposed to static light maps,
+actual lighting conditions influence indirect illumination. The effect is
+achieved by combining multiple 'PRM panes' (partial "light maps") according to
+current illumination of 'entry point clusters'.
+
+As opposed to PRT (precomputed radiance transfer), no tessellation (finite
+elements) is needed, and near light sources are handled. (We do not assume
+infinitely distant
+environment lighting.)
+
+Accuracy of PRMs depends on the number of entry points used, influencing
+preocessing time only.
+
+Final rendering requires a compositing of PRMs, where performance depends on the
+number of 'entry point clusters' considered for an object. As many texture
+fetches as clusters are needed. A lower number of clusters will result in
+indirect illumination which is less responsive to actual lighting, but still
+plausible. (A single cluster would reproduce a static light map which is scaled
+according to the total direct illumination.)
+
+
+Build:
+######
+This is a standalone DirectX 9.0 application, compiles under Visual C++ 2003
+with DirectX SDK April 2006 (identical to June 2006).
+
+Parameters (PRM resolution, shadow map resolution, #entry points, #clusters,
+etc.) are hardcoded as #define directives in PathMapEffect.h.
+
+GENERATE_PATH_MAPS in PathMapEffect.cpp must be defined to perform precomputing,
+outputting textures to the PRM subfolder. Otherwise, PRM textures are loaded
+from the PRM subfolder.
+
+
+Usage notes:
+############
+- as precomputing is used, this tool should be used for static level geometry
+- multiple static objects are supported and encouraged: every object will use a
+set of most important PRM panes
+- models must have unique texture mapping (just like light maps)
+
+- there is no support for any particular 'level geometry' discription format.
+DirectX .x files and referenced textures are loaded from code.
+- To include the method in a particular engine, the level geometry should be
+used to compose the scene which is used to generate the PRM textures. Final
+compositing must be implemented in the shader system of the game engine,
+assigning the computed PRMs to the respective objects as textures.
Index: GTP/trunk/App/Demos/Illum/PathMap/.params0
===================================================================
--- GTP/trunk/App/Demos/Illum/PathMap/.params0	(revision 896)
+++ GTP/trunk/App/Demos/Illum/PathMap/.params0	(revision 1480)
@@ -1,8 +1,8 @@
 ----- RayTraceEffects: Saved parameters of the algorithm -----
 Bool values:
-000
-(Show Help; ; ; )
+01101
+(Show Help; Move light; Look from light; Entry points; Turbo; )
 Float values:
+75 	(Tone scale, 0..100)
 0 	(, 0..0)
 0 	(, 0..0)
-0 	(, 0..0)
Index: GTP/trunk/App/Demos/Illum/PathMap/.params
===================================================================
--- GTP/trunk/App/Demos/Illum/PathMap/.params	(revision 896)
+++ GTP/trunk/App/Demos/Illum/PathMap/.params	(revision 1480)
@@ -1,8 +1,8 @@
 ----- RayTraceEffects: Saved parameters of the algorithm -----
 Bool values:
-00001
+01101
 (Show Help; Move light; Look from light; Entry points; Turbo; )
 Float values:
-64 	(Tone scale, 0..100)
+75 	(Tone scale, 0..100)
 0 	(, 0..0)
 0 	(, 0..0)
Index: GTP/trunk/App/Demos/Illum/PathMap/PathMap_2003.vcproj
===================================================================
--- GTP/trunk/App/Demos/Illum/PathMap/PathMap_2003.vcproj	(revision 896)
+++ GTP/trunk/App/Demos/Illum/PathMap/PathMap_2003.vcproj	(revision 1480)
@@ -385,4 +385,7 @@
 			RelativePath=".\showTex.fx">
 		</File>
+		<File
+			RelativePath=".\torch.tx">
+		</File>
 	</Files>
 	<Globals>
