// ------------------------------------------------------------------------------------------------
aiMatrix4x4 ReadMatrix(const Element& element)
{
    std::vector<float> values;
    ParseVectorDataArray(values,element);

    if(values.size() != 16) {
        ParseError("expected 16 matrix elements");
    }

    aiMatrix4x4 result;


    result.a1 = values[0];
    result.a2 = values[1];
    result.a3 = values[2];
    result.a4 = values[3];

    result.b1 = values[4];
    result.b2 = values[5];
    result.b3 = values[6];
    result.b4 = values[7];

    result.c1 = values[8];
    result.c2 = values[9];
    result.c3 = values[10];
    result.c4 = values[11];

    result.d1 = values[12];
    result.d2 = values[13];
    result.d3 = values[14];
    result.d4 = values[15];

    result.Transpose();
    return result;
}
void ResolveVertexDataArray(std::vector<T>& data_out, const Scope& source, 
	const std::string& MappingInformationType,
	const std::string& ReferenceInformationType,
	const char* dataElementName,
	const char* indexDataElementName,
	size_t vertex_count,
	const std::vector<unsigned int>& mapping_counts,
	const std::vector<unsigned int>& mapping_offsets,
	const std::vector<unsigned int>& mappings)
{
	std::vector<T> tempUV;
	ParseVectorDataArray(tempUV,GetRequiredElement(source,dataElementName));

	// handle permutations of Mapping and Reference type - it would be nice to
	// deal with this more elegantly and with less redundancy, but right
	// now it seems unavoidable.
	if (MappingInformationType == "ByVertice" && ReferenceInformationType == "Direct") {	
		data_out.resize(vertex_count);
		for (size_t i = 0, e = tempUV.size(); i < e; ++i) {

			const unsigned int istart = mapping_offsets[i], iend = istart + mapping_counts[i];
			for (unsigned int j = istart; j < iend; ++j) {
				data_out[mappings[j]] = tempUV[i];
			}
		}
	}
	else if (MappingInformationType == "ByVertice" && ReferenceInformationType == "IndexToDirect") {	
		data_out.resize(vertex_count);

		std::vector<int> uvIndices;
		ParseVectorDataArray(uvIndices,GetRequiredElement(source,indexDataElementName));

		for (size_t i = 0, e = uvIndices.size(); i < e; ++i) {

			const unsigned int istart = mapping_offsets[i], iend = istart + mapping_counts[i];
			for (unsigned int j = istart; j < iend; ++j) {
				if(static_cast<size_t>(uvIndices[i]) >= tempUV.size()) {
					DOMError("index out of range",&GetRequiredElement(source,indexDataElementName));
				}
				data_out[mappings[j]] = tempUV[uvIndices[i]];
			}
		}
	}
	else if (MappingInformationType == "ByPolygonVertex" && ReferenceInformationType == "Direct") {	
		if (tempUV.size() != vertex_count) {
			FBXImporter::LogError(Formatter::format("length of input data unexpected for ByPolygon mapping: ") 
				<< tempUV.size() << ", expected " << vertex_count
			);
			return;
		}

		data_out.swap(tempUV);
	}
	else if (MappingInformationType == "ByPolygonVertex" && ReferenceInformationType == "IndexToDirect") {	
		data_out.resize(vertex_count);

		std::vector<int> uvIndices;
		ParseVectorDataArray(uvIndices,GetRequiredElement(source,indexDataElementName));

		if (uvIndices.size() != vertex_count) {
			FBXImporter::LogError("length of input data unexpected for ByPolygonVertex mapping");
			return;
		}

		unsigned int next = 0;
		BOOST_FOREACH(int i, uvIndices) {
			if(static_cast<size_t>(i) >= tempUV.size()) {
				DOMError("index out of range",&GetRequiredElement(source,indexDataElementName));
			}

			data_out[next++] = tempUV[i];
		}
	}