public void parseProjectorVertex(string line, ProjectorMesh pm) {
		string[] tokens = line.Trim ().Split (" ,():".ToCharArray (), StringSplitOptions.RemoveEmptyEntries);
		if (tokens.Length < 6) {
			throw new Exception ("Could not create a mesh because there weren't enough vertices. Not enough verts in this list.");
		}
		int xIndex = (int)int.Parse (tokens [0]);
		int yIndex = (int)int.Parse (tokens [1]);
		float cylinderX = (float)Double.Parse (tokens [2]);
		float cylinderY = (float)Double.Parse (tokens [3]);
		float cylinderU = (float)Double.Parse (tokens [4]);
		float cylinderV = (float)Double.Parse (tokens [5]);
		pm.SetCylinderPoint (xIndex, yIndex, new Vector2 (cylinderX, cylinderY), new Vector2 (cylinderU, cylinderV));
    
    }
    public void processProjectorVertices(TextReader file, bool skip, ProjectorMesh pm, int numVertices) {
		for (int i = 0; i < numVertices; i++) {
			// Read one line and create a vertex
			string line = file.ReadLine ();
			if (line == null) {
				throw new Exception ("Could not create a mesh because there weren't enough vertices. File has ended");
			}
			

			if (!skip) {
				this.parseProjectorVertex(line, pm);
			}
		}
    }
    private void fakeProjectorVertices(TextReader file, bool skip, ProjectorMesh pm, int numVertices) {
    	if (!skip) { //create fake projector vertices
//			Projector 12:
//			1 1 0.0 1.0
//			
//			
//			

			string a = "( 0, 0) -0.500000 -0.500000  0.000000  1.000000";
			string b = "( 1, 0)  0.500000 -0.500000  1.000000  1.000000";
			string c = "( 0, 1) -0.500000  0.500000  0.000000  0.000000";
			string d = "( 1, 1)  0.500000  0.500000  1.000000  0.000000";
			this.parseProjectorVertex(a, pm);
			this.parseProjectorVertex(b, pm);
			this.parseProjectorVertex(c, pm);
			this.parseProjectorVertex(d, pm);
    	
    	}
		
    	this.processProjectorVertices(file,true,pm, numVertices); //move file forward.
    }
    private bool ParseWarpMeshProjector(TextReader file) {
    	//returns if no entries remaining.
		string line = file.ReadLine ();
		if (line == null) {
			return true;
		}
		string[] tokens = line.Trim ().Split (" ,():".ToCharArray (), StringSplitOptions.RemoveEmptyEntries);
		if (tokens.Length == 2 && tokens [0] == "Projector") {
			int projectorId = int.Parse (tokens [1]);
			
			
			// Start line of a new projector's info
			line = file.ReadLine ();
			if (line == null) {
				throw new Exception ("Could not create a mesh. File has ended before vertices list.");
			}
			bool isBeingDisplayed = this.isSlaveDisplayed(projectorId);
			
			tokens = line.Trim ().Split (" ,():".ToCharArray (), StringSplitOptions.RemoveEmptyEntries);
			int gridWidth = Int32.Parse (tokens [0]);
			int gridHeight = Int32.Parse (tokens [1]);
			float projectorStart = (float)Double.Parse (tokens [2]);
			float projectorEnd = (float)Double.Parse (tokens [3]);
			int numVertices = (gridWidth + 1) * (gridHeight + 1);
			
			ProjectorMesh projectorMesh = null;
			if (isBeingDisplayed) {				
				if (doWarp) {
					projectorMesh = new ProjectorMesh (projectorId, gridWidth, gridHeight, projectorStart, projectorEnd);
					this.processProjectorVertices(file, !isBeingDisplayed, projectorMesh,numVertices);
				} else {
					this.getFakeProjStartEnd(projectorId, out projectorStart, out projectorEnd);
					projectorMesh = new ProjectorMesh (projectorId, 1, 1, projectorStart, projectorEnd);
					this.fakeProjectorVertices(file, !isBeingDisplayed, projectorMesh,numVertices);
				}
				_projectorMeshes.Add (projectorMesh);
			}
			
		}
		return false;
    
    }
        /**
         * Ctor.
         * @param id The projector id.
         * @param width width of the projector grid.
         * @param height height of the projector grid.
         * @param start start seam for the projector.
         * @param end end seam for the projector.
         */
        public ProjectorDescription(ProjectorMesh projectorMesh, 
            int renderTextureWidth,
            int renderTextureHeight,
            GameObject warpMeshPrefab,
            Transform clusterManager)
        {
            this.projectorMesh = projectorMesh;
            nodeNumber = projectorMesh.Id / 2;

            if (projectorMesh.Id % 2 == 0)
            {
                stereoType = ProjectorStereoType.Left;
            }
            else if (projectorMesh.Id % 2 == 1)
            {
                stereoType = ProjectorStereoType.Right;
            }
            meshVertices = new Vector3[projectorMesh.NumVertices];
            meshUVs = new Vector2[projectorMesh.NumVertices];
            triangles = new int[3 * 2 * projectorMesh.GridWidth * projectorMesh.GridHeight];

            _projectorObject = new GameObject("Ortho Camera Rig: " + projectorMesh.Id);

            //
            // Position this rig under the Cluster Manager
            // to make the scene browser clearer
            _projectorObject.transform.parent = clusterManager;

            /////////////////
            // Create Mesh //
            /////////////////
            Mesh mesh = this.CreateMesh();
            if (mesh == null)
            {
                // Create mesh failed, exit
                throw new Exception("Mesh Creation Failed.");
            }
            //            Debug.Log("Mesh Created.");

            // Projector is the left of the two assigned to this IG
            string warpMeshPrefix = "IG(" + (projectorMesh.Id / 2) + ").Projector(" + projectorMesh.Id + ")";
            GameObject warpMeshObject = GameObject.Instantiate(warpMeshPrefab) as GameObject;
            warpMeshObject.name = warpMeshPrefix + ".object";
            //GameObject warpMeshObject = new GameObject(warpMeshPrefix + ".object");
            warpMeshObject.transform.parent = this.ProjectorObject.transform;
            //warpMeshObject.AddComponent("MeshFilter");
            //warpMeshObject.AddComponent("MeshRenderer");
            (warpMeshObject.GetComponent("MeshFilter") as MeshFilter).mesh = mesh;
            MeshRenderer meshRenderer = warpMeshObject.GetComponent<MeshRenderer>();
            meshRenderer.castShadows = false;
            meshRenderer.receiveShadows = false;

            this.warpMeshObject = warpMeshObject;

            ///////////////////////////////////////////////////
            // Create a new render texture for the projector //
            ///////////////////////////////////////////////////
            int renderTextureDepth = 24;
            RenderTexture renderTexture = new RenderTexture(renderTextureWidth, renderTextureHeight, renderTextureDepth);
            this._targetRenderTexture = renderTexture;

            ///////////////////////////////////////////////////
            // Create a new blend texture for this projector //
            ///////////////////////////////////////////////////
            string path = "file:///" + CONFIG_PATH + "Avie/BlendTextures/blend" + projectorMesh.Id.ToString("00") + ".png";
            WWW www = new WWW(path);
            this._targetBlendTexture = www.texture;

            if (www.error != null)
                Debug.Log (www.error);

            ///////////////////////////////////////////////////
            // Add HSV/ Gamma adjust						 //
            ///////////////////////////////////////////////////
            icMaterial icm = this.warpMeshObject.AddComponent<icMaterial>();
            icm.multiplyByParentColour = false;

            RefreshTextureScript rts = this.warpMeshObject.AddComponent<RefreshTextureScript>();
            rts.toReplace = this._targetRenderTexture;
            ImageShaderScript iss = this.warpMeshObject.AddComponent<ImageShaderScript>();

            iss.separatePass = true;
            iss.enabled = false;
            //imageShaderScript needs to be enabled one frame later, or a white flash occurs...
        }
        /**
         * Ctor.
         * @param id The projector id.
         * @param width width of the projector grid.
         * @param height height of the projector grid.
         * @param start start seam for the projector.
         * @param end end seam for the projector.
         */
        public ProjectorDescription(ProjectorMesh projectorMesh,
                                    int renderTextureWidth,
                                    int renderTextureHeight,
                                    GameObject warpMeshPrefab,
                                    Transform clusterManager)
        {
            this.projectorMesh = projectorMesh;
            nodeNumber         = projectorMesh.Id / 2;

            if (projectorMesh.Id % 2 == 0)
            {
                stereoType = ProjectorStereoType.Left;
            }
            else if (projectorMesh.Id % 2 == 1)
            {
                stereoType = ProjectorStereoType.Right;
            }
            meshVertices = new Vector3[projectorMesh.NumVertices];
            meshUVs      = new Vector2[projectorMesh.NumVertices];
            triangles    = new int[3 * 2 * projectorMesh.GridWidth * projectorMesh.GridHeight];

            _projectorObject = new GameObject("Ortho Camera Rig: " + projectorMesh.Id);

            //
            // Position this rig under the Cluster Manager
            // to make the scene browser clearer
            _projectorObject.transform.parent = clusterManager;

            /////////////////
            // Create Mesh //
            /////////////////
            Mesh mesh = this.CreateMesh();

            if (mesh == null)
            {
                // Create mesh failed, exit
                throw new Exception("Mesh Creation Failed.");
            }
//            Debug.Log("Mesh Created.");

            // Projector is the left of the two assigned to this IG
            string     warpMeshPrefix = "IG(" + (projectorMesh.Id / 2) + ").Projector(" + projectorMesh.Id + ")";
            GameObject warpMeshObject = GameObject.Instantiate(warpMeshPrefab) as GameObject;

            warpMeshObject.name = warpMeshPrefix + ".object";
            //GameObject warpMeshObject = new GameObject(warpMeshPrefix + ".object");
            warpMeshObject.transform.parent = this.ProjectorObject.transform;
            //warpMeshObject.AddComponent("MeshFilter");
            //warpMeshObject.AddComponent("MeshRenderer");
            (warpMeshObject.GetComponent("MeshFilter") as MeshFilter).mesh = mesh;
            MeshRenderer meshRenderer = warpMeshObject.GetComponent <MeshRenderer>();

            meshRenderer.castShadows    = false;
            meshRenderer.receiveShadows = false;

            this.warpMeshObject = warpMeshObject;


            ///////////////////////////////////////////////////
            // Create a new render texture for the projector //
            ///////////////////////////////////////////////////
            int           renderTextureDepth = 24;
            RenderTexture renderTexture      = new RenderTexture(renderTextureWidth, renderTextureHeight, renderTextureDepth);

            this._targetRenderTexture = renderTexture;

            ///////////////////////////////////////////////////
            // Create a new blend texture for this projector //
            ///////////////////////////////////////////////////
            string path = "file:///" + CONFIG_PATH + "Avie/BlendTextures/blend" + projectorMesh.Id.ToString("00") + ".png";
            WWW    www  = new WWW(path);

            this._targetBlendTexture = www.texture;

            if (www.error != null)
            {
                Debug.Log(www.error);
            }

            ///////////////////////////////////////////////////
            // Add HSV/ Gamma adjust						 //
            ///////////////////////////////////////////////////
            icMaterial icm = this.warpMeshObject.AddComponent <icMaterial>();

            icm.multiplyByParentColour = false;


            RefreshTextureScript rts = this.warpMeshObject.AddComponent <RefreshTextureScript>();

            rts.toReplace = this._targetRenderTexture;
            ImageShaderScript iss = this.warpMeshObject.AddComponent <ImageShaderScript>();

            iss.separatePass = true;
            iss.enabled      = false;
            //imageShaderScript needs to be enabled one frame later, or a white flash occurs...
        }