/*!********************************************************************************************
 @Function		convert_signs
 @Input			layer          The map layer to extract the texts from.
 @Input			atlas          The texture atlas used for uv-coordinate calculation.
 @Output		pivotquads     The generated pivotquad vertex data.
 @Output		triangles      Triangle indices used for rendering of the pivotquads. 
 @Description	Generates pivotquads for the signs which will be screen-space aligned when being 
                rendered.
***********************************************************************************************/
void convert_signs(const PVRTMapLayer &layer, const PVRTTextureAtlas &atlas, PVRTPivotQuadVertexVector &pivotquads, PVRTTriangleVector &triangles)
{
	unsigned int numTotalSigns = layer.indexset.signs.size();
	
	// Pre-allocate to prevent reallocations
	pivotquads.reserve(pivotquads.size() + numTotalSigns * 4);
	triangles.reserve(triangles.size() + numTotalSigns * 2);
	
	for (unsigned int j=0; j < numTotalSigns; j++)
	{	
		const unsigned int index = pivotquads.size();

		string name(layer.indexset.signs[j].szName);
		
		PVRTVec2 pos = layer.indexset.signs[j].position;

		if (!atlas.Contains(name))
		{
			cerr << "Error: Texture atlas does not contain " << name << endl;
			continue;
		}

		PVRTMat3 texmat = atlas.GetTextureMatrix(name);
		PVRTVec3 uvcoords;

		PVRTPivotQuadVertex vertex;
		vertex.origin = pos;
		

		uvcoords = texmat * PVRTVec3(0.0f, 0.0f, 255.0f);
		vertex.word_index = 0;
		vertex.height_index = 0;
		vertex.u = (PVRTuint8)(uvcoords.x);
		vertex.v = (PVRTuint8)(uvcoords.y);
		pivotquads.push_back(vertex);

		uvcoords = texmat * PVRTVec3(255.0f, 0.0f, 255.0f);
		vertex.word_index = 1;
		vertex.height_index = 0;
		vertex.u = (PVRTuint8)(uvcoords.x);
		vertex.v = (PVRTuint8)(uvcoords.y);
		pivotquads.push_back(vertex);

		uvcoords = texmat * PVRTVec3(0.0f, 255.0f, 255.0f);
		vertex.word_index = 0;
		vertex.height_index = 1;
		vertex.u = (PVRTuint8)(uvcoords.x);
		vertex.v = (PVRTuint8)(uvcoords.y);
		pivotquads.push_back(vertex);

		uvcoords = texmat * PVRTVec3(255.0f, 255.0f, 255.0f);
		vertex.word_index = 1;
		vertex.height_index = 1;
		vertex.u = (PVRTuint8)(uvcoords.x);
		vertex.v = (PVRTuint8)(uvcoords.y);
		pivotquads.push_back(vertex);

		PVRTTriangle t0 = { index, index + 1, index + 3 };
		PVRTTriangle t1 = { index, index + 3, index + 2 };

		triangles.push_back(t0);
		triangles.push_back(t1);
	}		
}
/*!********************************************************************************************
 @Function		convert_texts
 @Input			layer          The map layer to extract the texts from.
 @Input			atlas          The texture atlas used for uv-coordinate calculation.
 @Output		pivotquads     The generated pivotquad vertex data.
 @Output		triangles      Triangle indices used for rendering of the pivotquads. 
 @Description	Generates pivotquads for the text strings which will be screen-space aligned
                when being rendered.
***********************************************************************************************/
void convert_texts(const PVRTMapLayer &layer, const PVRTTextureAtlas &atlas, PVRTPivotQuadVertexVector &pivotquads, PVRTTriangleVector &triangles)
{
	unsigned int numTotalLetters = 0;
	for (unsigned int j=0; j < layer.indexset.texts.size(); j++)
	{
		numTotalLetters += strlen(layer.indexset.texts[j].szName);
	}
	
	// Pre-allocate to prevent reallocations
	pivotquads.reserve(pivotquads.size() + numTotalLetters * 4);
	triangles.reserve(triangles.size() + numTotalLetters * 2);

	for (unsigned int j=0; j < layer.indexset.texts.size(); j++)
	{							
		const PVRTLinestrip &linestrip = layer.indexset.linestrips[layer.indexset.texts[j].index];
	
		string name(layer.indexset.texts[j].szName);
		unsigned int numLetters = name.length();

		float rand_pos = rand() / (float)RAND_MAX;
		// transform it to the range [0.2, 0.8] so that the streetnames are more in the middle of the street
		rand_pos = 0.2f + rand_pos * 0.6f;

		PVRTVec3 pos_3d = InterpolateLinestrip(layer.coordinates, linestrip, rand_pos);
		PVRTVec2 pos = PVRTVec2(pos_3d.x, pos_3d.y);

		int adjustedIndex = 0;
		unsigned int triangle_index = pivotquads.size();

		// Calculate the total width
		unsigned int word_width = 0;		
		for (unsigned int i=0; i < numLetters; i++)
			word_width += get_letter_spacing(name.at(i));
		const int anchor_index = word_width / 2;		

		size_t ordinal_pos;
		bool has_ordinal = contains_ordinal(name, ordinal_pos);

		for (unsigned int i=0; i < numLetters; i++)
		{					
			if (name.at(i) == ' ')
			{
				adjustedIndex += get_letter_spacing(name.at(i));				
				continue;
			}

			triangle_index = pivotquads.size();
			const int startIndex = adjustedIndex;
			int starty, endy;			
			
			// If it contains an ordinal and the current letter is one
			if (has_ordinal && ((i == ordinal_pos) || i == (ordinal_pos + 1)))
			{
				adjustedIndex += 2;
				starty = 2;
				endy = 5;
			}
			else
			{
				adjustedIndex += get_letter_spacing(name.at(i));				
				get_height_indices(name.at(i), starty, endy);				
			}
		
			string letter = name.substr(i, 1);

			PVRTMat3 texmat = atlas.GetTextureMatrix(letter);

			PVRTPivotQuadVertex vertex;
			vertex.origin = pos;

			PVRTVec3 uvcoords = texmat * PVRTVec3(0.0f, 0.0f, 255.0f);
			vertex.word_index = startIndex - anchor_index;
			vertex.height_index = starty;
			vertex.u = (PVRTuint8)(uvcoords.x);
			vertex.v = (PVRTuint8)(uvcoords.y);
			pivotquads.push_back(vertex);

			uvcoords = texmat * PVRTVec3(255.0f, 0.0f, 255.0f);
			vertex.word_index = adjustedIndex - anchor_index;
			vertex.height_index = starty;
			vertex.u = (PVRTuint8)(uvcoords.x);
			vertex.v = (PVRTuint8)(uvcoords.y);
			pivotquads.push_back(vertex);

			uvcoords = texmat * PVRTVec3(0.0f, 255.0f, 255.0f);

			vertex.word_index = startIndex - anchor_index;
			vertex.height_index = endy;
			vertex.u = (PVRTuint8)(uvcoords.x);
			vertex.v = (PVRTuint8)(uvcoords.y);
			pivotquads.push_back(vertex);

			uvcoords = texmat * PVRTVec3(255.0f, 255.0f, 255.0f);
			vertex.word_index = adjustedIndex - anchor_index;
			vertex.height_index = endy;
			vertex.u = (PVRTuint8)(uvcoords.x);
			vertex.v = (PVRTuint8)(uvcoords.y);
			pivotquads.push_back(vertex);

			PVRTTriangle t0 = { triangle_index, triangle_index + 1, triangle_index + 3 };
			PVRTTriangle t1 = { triangle_index, triangle_index + 3, triangle_index + 2 };

			triangles.push_back(t0);
			triangles.push_back(t1);				
		}
	}
}