Ejemplo n.º 1
0
reMesh* reFBXAsset::importMesh(FbxNode* fbxNode)
{
	qDebug() << "import mesh for" << fbxNode->GetName();
	reMesh* mesh = new reMesh;

	FbxMesh* fmesh = (FbxMesh*) fbxNode->GetNodeAttribute();
	FbxVector4* controlPoints = fmesh->GetControlPoints(); 

	for (int i=0; i<fmesh->GetPolygonCount(); i++) 
	{
		reFace* face = new reFace;
		for (int j=0; j<fmesh->GetPolygonSize(i); j++)
		{
			int vi = fmesh->GetPolygonVertex(i, j);
			reVertex vertex;
			vertex.pos = reVec3(controlPoints[vi][0], controlPoints[vi][1], controlPoints[vi][2]);
			FbxVector4 fNormal;
			fmesh->GetPolygonVertexNormal(i, j, fNormal);
			vertex.uv = getUV(fmesh, vi, i, j);
			vertex.normal = reVec3(fNormal[0], fNormal[1], fNormal[2]);
			face->vertices.push_back(vertex);	
		}
		reMaterial* mat =  getMaterial(fmesh, i, mesh->materialSet);
		mesh->addFace(face,mat ? mat->id: -1);
	}
	
	reMeshAsset* meshAsset = new reMeshAsset(meshes);
	meshAsset->mesh = mesh;
	meshes->children.push_back(meshAsset);
	meshAsset->setPath((dataDir().toStdString() + "/" + fbxNode->GetName() + ".mesh").c_str());
	mesh->save(dataDir().toStdString() + "/" + fbxNode->GetName() + ".mesh");
	return mesh;
}
	HRESULT FBXLoader::loadFBXFile(char* filePath, VertexBuffer** vBuf, IndexBuffer** iBuf, Renderer* renderer, bool centerShift)
	{
		if (g_pFbxSdkManager == nullptr)
		{
			g_pFbxSdkManager = FbxManager::Create();

			FbxIOSettings* pIOsettings = FbxIOSettings::Create(g_pFbxSdkManager, IOSROOT);
			g_pFbxSdkManager->SetIOSettings(pIOsettings);
		}

		this->shiftCenter = centerShift;

		FbxImporter* pImporter = FbxImporter::Create(g_pFbxSdkManager, "");
		FbxScene* pFbxScene = FbxScene::Create(g_pFbxSdkManager, "");

		bool bSuccess = pImporter->Initialize(filePath, -1, g_pFbxSdkManager->GetIOSettings());
		if (!bSuccess) return E_FAIL;

		bSuccess = pImporter->Import(pFbxScene);
		if (!bSuccess) return E_FAIL;

		FbxAxisSystem sceneAxisSystem = pFbxScene->GetGlobalSettings().GetAxisSystem();
		FbxAxisSystem DirectXAxisSystem(FbxAxisSystem::eYAxis, FbxAxisSystem::eParityOdd, FbxAxisSystem::eLeftHanded);

		if (sceneAxisSystem != DirectXAxisSystem)
		{
			DirectXAxisSystem.ConvertScene(pFbxScene);
		}

		pImporter->Destroy();

		FbxNode* pFbxRootNode = pFbxScene->GetRootNode();

		if (pFbxRootNode)
		{
			// Check if the getChildCount is > 1  TODO
			int test = pFbxRootNode->GetChildCount();

			for (int i = 0; i < pFbxRootNode->GetChildCount(); i++)
			{
				FbxNode* pFbxChildNode = pFbxRootNode->GetChild(i);

				if (pFbxChildNode->GetNodeAttribute() == NULL)
					continue;

				FbxNodeAttribute::EType AttributeType = pFbxChildNode->GetNodeAttribute()->GetAttributeType();

				if (AttributeType != FbxNodeAttribute::eMesh)
					continue;

				FbxMesh* pMesh = (FbxMesh*)pFbxChildNode->GetNodeAttribute();

				int numControlPoints = pMesh->GetControlPointsCount();
				bool initial = true;
				float xMin, yMin, zMin;
				float xMax, yMax, zMax;
				float xIn, yIn, zIn;

				float xCenter, yCenter, zCenter;

				if (this->shiftCenter){

					for (int c = 0; c < numControlPoints; c++) {
						xIn = (float)pMesh->GetControlPointAt(c).mData[0];
						yIn = (float)pMesh->GetControlPointAt(c).mData[1];
						zIn = (float)pMesh->GetControlPointAt(c).mData[2];

						if (initial) {
							xMin = xIn;
							yMin = yIn;
							zMin = zIn;

							xMax = xIn;
							yMax = yIn;
							zMax = zIn;

							initial = false;
						}
						else {
							if (xIn < xMin) {
								xMin = xIn;
							}

							if (yIn < yMin) {
								yMin = yIn;
							}

							if (zIn < zMin) {
								zMin = zIn;
							}

							if (xIn > xMax) {
								xMax = xIn;
							}

							if (yIn > yMax) {
								yMax = yIn;
							}

							if (zIn > zMax) {
								zMax = zIn;
							}
						}
					}
					xCenter = (xMin + xMax) / 2.0f;
					yCenter = (yMin + yMax) / 2.0f;
					zCenter = (zMin + zMax) / 2.0f;
				}
				else {
					xCenter = 0;
					yCenter = 0;
					zCenter = 0;
				}

				FbxVector4* pVertices = pMesh->GetControlPoints();
				int vertexCount = pMesh->GetPolygonVertexCount();

				//Vertex vertex;
				Vertex* vertexArray = new Vertex[vertexCount];
				//Vertex vertexArray[2592];


				int numIndices = vertexCount;
				unsigned int* indexArray = new unsigned int[numIndices];


				FbxVector4 fbxNorm(0, 0, 0, 0);
				FbxVector2 fbxUV(0, 0);
				bool isMapped;

				int vertexIndex = 0;

				// Loop iterates through the polygons and fills the vertex and index arrays for the buffers
				for (int j = 0; j < pMesh->GetPolygonCount(); j++)
				{
					int iNumVertices = pMesh->GetPolygonSize(j);

					assert(iNumVertices == 3);

					//1st vertex
					int controlIndex = pMesh->GetPolygonVertex(j, 2);
					pMesh->GetPolygonVertexUV(j, 2, "map1", fbxUV, isMapped);
					pMesh->GetPolygonVertexNormal(j, 2, fbxNorm);

					vertexArray[vertexIndex].point[0] = (float)pVertices[controlIndex].mData[0] - xCenter;
					vertexArray[vertexIndex].point[1] = (float)pVertices[controlIndex].mData[1] - yCenter;
					vertexArray[vertexIndex].point[2] = -(float)pVertices[controlIndex].mData[2] - zCenter;

					vertexArray[vertexIndex].texCoord[0] = (float)fbxUV[0];
					vertexArray[vertexIndex].texCoord[1] = 1.0f - (float)fbxUV[1];

					vertexArray[vertexIndex].normal[0] = (float)fbxNorm[0];
					vertexArray[vertexIndex].normal[1] = (float)fbxNorm[1];
					vertexArray[vertexIndex].normal[2] = -(float)fbxNorm[2];

					indexArray[vertexIndex] = vertexIndex;
					vertexIndex++;

					//2nd vertex
					controlIndex = pMesh->GetPolygonVertex(j, 1);
					pMesh->GetPolygonVertexUV(j, 1, "map1", fbxUV, isMapped);
					pMesh->GetPolygonVertexNormal(j, 1, fbxNorm);

					vertexArray[vertexIndex].point[0] = (float)pVertices[controlIndex].mData[0] - xCenter;
					vertexArray[vertexIndex].point[1] = (float)pVertices[controlIndex].mData[1] - yCenter;
					vertexArray[vertexIndex].point[2] = -(float)pVertices[controlIndex].mData[2] - zCenter;

					vertexArray[vertexIndex].texCoord[0] = (float)fbxUV[0];
					vertexArray[vertexIndex].texCoord[1] = 1.0f - (float)fbxUV[1];

					vertexArray[vertexIndex].normal[0] = (float)fbxNorm[0];
					vertexArray[vertexIndex].normal[1] = (float)fbxNorm[1];
					vertexArray[vertexIndex].normal[2] = -(float)fbxNorm[2];

					indexArray[vertexIndex] = vertexIndex;
					vertexIndex++;

					//3rd vertex
					controlIndex = pMesh->GetPolygonVertex(j, 0);
					pMesh->GetPolygonVertexUV(j, 0, "map1", fbxUV, isMapped);
					pMesh->GetPolygonVertexNormal(j, 0, fbxNorm);

					vertexArray[vertexIndex].point[0] = (float)pVertices[controlIndex].mData[0] - xCenter;
					vertexArray[vertexIndex].point[1] = (float)pVertices[controlIndex].mData[1] - yCenter;
					vertexArray[vertexIndex].point[2] = -(float)pVertices[controlIndex].mData[2] - zCenter;

					vertexArray[vertexIndex].texCoord[0] = (float)fbxUV[0];
					vertexArray[vertexIndex].texCoord[1] = 1.0f - (float)fbxUV[1];

					vertexArray[vertexIndex].normal[0] = (float)fbxNorm[0];
					vertexArray[vertexIndex].normal[1] = (float)fbxNorm[1];
					vertexArray[vertexIndex].normal[2] = -(float)fbxNorm[2];

					indexArray[vertexIndex] = vertexIndex;
					vertexIndex++;
				}

				// Generate vertex and index buffers from the vertex and index arrays
				*vBuf = renderer->createVertexBuffer(vertexArray, vertexCount);
				*iBuf = renderer->createIndexBuffer(indexArray, numIndices);

				delete[] vertexArray;
				delete[] indexArray;
			}
		}
		return S_OK;
	}
Ejemplo n.º 3
0
		void FbxLoader::ProcessMesh(FbxNode* node, Node& meshNode)
		{
			FbxMesh* currMesh = node->GetMesh();

			if(!currMesh)
				return;

			FbxLayerElementTangent* tangents = nullptr;

			if(useNormalMap) {
				if(currMesh->GetElementTangentCount() < 1) {
					currMesh->GenerateTangentsDataForAllUVSets();
					tangents = currMesh->GetElementTangent();
				}
			}

			std::map<int, std::vector<Vertex>> subMeshes;

			int vertCounter = 0;
			const int polygonCount = currMesh->GetPolygonCount();

			for(int i = 0; i < polygonCount; i++) {
				const int polySize = currMesh->GetPolygonSize(i);
				int nMaterials = node->GetMaterialCount();
				auto elementMaterial = currMesh->GetElementMaterial();
				int mi = 0;
				if(elementMaterial)
					mi = currMesh->GetElementMaterial()->GetIndexArray()[i];

				for(int j = 2; j >= 0; --j) {
					int ctrlIndex = currMesh->GetPolygonVertex(i, j);
					auto& currCtrlPoint = meshNode.controlPoints[ctrlIndex];
					FbxVector4 v4;

					auto& pos = currCtrlPoint.position * factor;
					currMesh->GetPolygonVertexNormal(i, j, v4);
					Vector3 normal = { (float)v4[0], (float)v4[1], (float)v4[2] };
					Vector3 tangent = { 0, 0, 0 };
					if(useNormalMap) {
						ReadTangent(tangents, ctrlIndex, vertCounter, v4);
						tangent = { (float)v4[0], (float)v4[1], (float)v4[2] };
					}
				
					Vector2 uv;
					FbxStringList uvSetNames;
					currMesh->GetUVSetNames(uvSetNames);
					bool unmapped = false;
					// supports one uv set only
					if(uvSetNames.GetCount() > 0) {
						FbxVector2 UV;
						currMesh->GetPolygonVertexUV(i, j, uvSetNames[0], UV, unmapped);
						uv = { (float)UV[0], (float)UV[1] };
					}
				
					if(axismode == eLeftHanded) {
						pos.x *= -1; uv.y = 1 - uv.y;
						normal.x *= -1; tangent.x *= -1;
					}

					Vector4 weights = { 0, 0, 0, 0 };
					Byte4 indices = { 0, 0, 0, 0 };

					int blendCount = (int)min(currCtrlPoint.blendWeigths.size(), 4);
					if(blendCount > 0) {
						meshNode.useSkinnedMesh = true;
						if(currCtrlPoint.blendWeigths.size() > 4)
							sort(currCtrlPoint.blendWeigths.begin(), currCtrlPoint.blendWeigths.end());
						for(int i = 0; i < blendCount; i++) {
							weights[i] = currCtrlPoint.blendWeigths[i].weight;
							indices.m[i] = currCtrlPoint.blendWeigths[i].boneIndex;
						}
					}
	
					Vertex temp = { pos, uv, normal, tangent, indices, weights };
					subMeshes[mi].push_back(temp);
				}
				++vertCounter;
			}

			if(subMeshes.size() > 0) {
				int index = 0;
				meshNode.meshes.reserve(vertCounter);
				meshNode.vertIndices.reserve(vertCounter);
				meshNode.vertexCountOfSubMesh.reserve(subMeshes.size());
				for(auto& pair : subMeshes) {
					auto& m = pair.second;
					for(int i = 0; i < m.size(); ++i)
						meshNode.vertIndices.emplace_back(index++);
					meshNode.vertexCountOfSubMesh.push_back((int)m.size());
					meshNode.meshes.insert(meshNode.meshes.end(), m.begin(), m.end());
				}
			}
			subMeshes.clear();
		}
Ejemplo n.º 4
0
FBXLoader::FBXLoader(const char *filename)
{
  m_error = true;
  if (m_fbx_sdk_manager == nullptr)
  {
    m_fbx_sdk_manager = FbxManager::Create();
    m_fbx_sdk_manager->SetIOSettings(FbxIOSettings::Create(m_fbx_sdk_manager, IOSROOT));
  }
  FbxImporter *importer = FbxImporter::Create(m_fbx_sdk_manager, "");
  FbxScene *scene = FbxScene::Create(m_fbx_sdk_manager, "");
  if (!importer->Initialize(filename, -1, m_fbx_sdk_manager->GetIOSettings()))
    return;
  if (!importer->Import(scene))
    return;
  importer->Destroy();

  FbxNode *root_node = scene->GetRootNode();
  if (root_node)
  {
    for (int i = 0; i < root_node->GetChildCount(); i++)
    {
      FbxNode *child_node = root_node->GetChild(i);
      if (child_node->GetNodeAttribute() == NULL)
        continue;

      FbxNodeAttribute::EType type = child_node->GetNodeAttribute()->GetAttributeType();
      if (type != FbxNodeAttribute::eMesh)
        continue;

      FbxMesh *mesh = (FbxMesh *) child_node->GetNodeAttribute();
      FbxVector4 *vertices = mesh->GetControlPoints();
      for (int j = 0; j < mesh->GetPolygonCount(); j++)
      {
        int num_verts = mesh->GetPolygonSize(j);
        assert(num_verts == 3);
        DirectX::XMFLOAT3 vertex[3];
        FbxVector4 polygon_normal(0, 0, 0);

        for (int k = 0; k < num_verts; k++)
        {
          int control_point_idx = mesh->GetPolygonVertex(j, k);
          FbxVector4 vertex_normal;
          mesh->GetPolygonVertexNormal(j, k, vertex_normal);
          polygon_normal += vertex_normal;
          vertex[k].x = (float) vertices[control_point_idx].mData[0];
          vertex[k].y = (float) vertices[control_point_idx].mData[1];
          vertex[k].z = (float) vertices[control_point_idx].mData[2];
        }

        if (IsClockwise(vertex, num_verts, polygon_normal))
        {
          for (int i = 0; i < num_verts; i++)
            m_vertices.push_back(ToD3DCoordinateSystem(vertex[i]));
        }
        else
        {
          for (int i = 0; i < num_verts; i++)
            m_vertices.push_back(ToD3DCoordinateSystem(vertex[num_verts - 1 - i]));
        }
      }
    }
  }

  for (size_t i = 0; i < m_vertices.size(); i++)
    m_indices.push_back(i);

  m_error = false;
}
Ejemplo n.º 5
0
bool FillData(ModelData* someData,FbxNode* aNode, AnimationData* aAnimation)
{
	FbxMesh* mesh = aNode->GetMesh();
	if (mesh == nullptr || !aNode)
		return false;

	const int lPolygonCount = mesh->GetPolygonCount();

	// Count the polygon count of each material
	FbxLayerElementArrayTemplate<int>* lMaterialIndice = NULL;
	FbxGeometryElement::EMappingMode lMaterialMappingMode = FbxGeometryElement::eNone;
	if (mesh->GetElementMaterial())
	{
		lMaterialIndice = &mesh->GetElementMaterial()->GetIndexArray();
		lMaterialMappingMode = mesh->GetElementMaterial()->GetMappingMode();
		if (lMaterialIndice && lMaterialMappingMode == FbxGeometryElement::eByPolygon)
		{
			FBX_ASSERT(lMaterialIndice->GetCount() == lPolygonCount);
			if (lMaterialIndice->GetCount() == lPolygonCount)
			{
				// Count the faces of each material
				for (int lPolygonIndex = 0; lPolygonIndex < lPolygonCount; ++lPolygonIndex)
				{
					const int lMaterialIndex = lMaterialIndice->GetAt(lPolygonIndex);
					lMaterialIndex;
					/*if (someData->mSubMeshes[lMaterialIndex] == NULL)
					{
						someData->mSubMeshes[lMaterialIndex] = new ModelData::SubMesh;
					}
					someData->mSubMeshes[lMaterialIndex]->TriangleCount += 1;*/
				}

				// Make sure we have no "holes" (NULL) in the mSubMeshes table. This can happen
				// if, in the loop above, we resized the mSubMeshes by more than one slot.
					
				/*for (int i = 0; i < someData->mSubMeshes.Count(); i++)
				{
					if (someData->mSubMeshes[i] == NULL)
						someData->mSubMeshes[i] = new ModelData::SubMesh;
				}*/

				// Record the offset (how many vertex)
				const int lMaterialCount = someData->mSubMeshes.Size();
				lMaterialCount;
				int lOffset = 0;
				/*for (int lIndex = 0; lIndex < lMaterialCount; ++lIndex)
				{
					someData->mSubMeshes[lIndex]->IndexOffset = lOffset;
					lOffset += someData->mSubMeshes[lIndex]->TriangleCount * 3;
					// This will be used as counter in the following procedures, reset to zero
					someData->mSubMeshes[lIndex]->TriangleCount = 0;
				}*/
				FBX_ASSERT(lOffset == lPolygonCount * 3);
			}
		}
	}

	// All faces will use the same material.
	if (someData->mSubMeshes.Size() == 0)
	{
		if (someData->mSubMeshes.GetCapacity() == 0)
		{
			someData->mSubMeshes.Init(1);
		}
		someData->mSubMeshes.RemoveAll();
		someData->mSubMeshes.AddEmptyObject();
		someData->mSubMeshes[0] = new ModelData::SubMesh();
	}

		

	bool hasNormalMap = false;

	const int lMaterialCount = aNode->GetMaterialCount();
	for (int lMaterialIndex = 0; lMaterialIndex < lMaterialCount; ++lMaterialIndex)
	{
		FbxSurfaceMaterial * lMaterial = aNode->GetMaterial(lMaterialIndex);
		if (lMaterial && !lMaterial->GetUserDataPtr())
		{
			TextureInfo diffuseInfo;
			GetMaterialProperty(lMaterial,FbxSurfaceMaterial::sDiffuse,FbxSurfaceMaterial::sDiffuseFactor,diffuseInfo.myFileName);
			diffuseInfo.myType = DIFFUSE;
			if(diffuseInfo.myFileName.empty() == false)
			{
				someData->myTextures.push_back(diffuseInfo);
			}

			TextureInfo normalInfo;
			GetMaterialProperty(lMaterial,FbxSurfaceMaterial::sNormalMap,FbxSurfaceMaterial::sBumpFactor,normalInfo.myFileName);
			hasNormalMap = normalInfo.myFileName.empty() == false;
			normalInfo.myType = NORMALMAP;
			if(normalInfo.myFileName.empty() == false)
			{
				someData->myTextures.push_back(normalInfo);
				hasNormalMap = true;
			}

			TextureInfo roughnessInfo;
			GetMaterialProperty(lMaterial,FbxSurfaceMaterial::sSpecular,FbxSurfaceMaterial::sSpecularFactor,roughnessInfo.myFileName);
			roughnessInfo.myType = ROUGHNESS;
			if(roughnessInfo.myFileName.empty() == false)
			{
				someData->myTextures.push_back(roughnessInfo);
			}

			TextureInfo substanceInfo;
			GetMaterialProperty(lMaterial,FbxSurfaceMaterial::sReflection,FbxSurfaceMaterial::sReflectionFactor,substanceInfo.myFileName);
			substanceInfo.myType = SUBSTANCE;
			if(substanceInfo.myFileName.empty() == false)
			{
				someData->myTextures.push_back(substanceInfo);
			}

			TextureInfo ambientInfo;
			GetMaterialProperty(lMaterial, FbxSurfaceMaterial::sAmbient, FbxSurfaceMaterial::sAmbientFactor, ambientInfo.myFileName);
			ambientInfo.myType = AO;
			if (substanceInfo.myFileName.empty() == false)
			{
				someData->myTextures.push_back(ambientInfo);
			}
		}
	}

	// Congregate all the data of a mesh to be cached in VBOs.
	// If normal or UV is by polygon vertex, record all vertex attributes by polygon vertex.'
		
	someData->mHasNormal = mesh->GetElementNormalCount() > 0;
	someData->mHasUV = mesh->GetElementUVCount() > 0;
	someData->myHasBiNormal = mesh->GetElementBinormalCount() > 0;

	FbxSkin * lSkinDeformer = (FbxSkin *)mesh->GetDeformer(0, FbxDeformer::eSkin);
	someData->myHasSkinweights = lSkinDeformer != nullptr;

	if(hasNormalMap && someData->myHasBiNormal == false)
	{
		mesh->GenerateTangentsDataForAllUVSets();
		someData->myHasBiNormal = mesh->GetElementBinormalCount() > 0;
	}
	someData->myHasTangents = mesh->GetElementTangentCount() > 0;
		
	FbxGeometryElement::EMappingMode lNormalMappingMode = FbxGeometryElement::eNone;
	FbxGeometryElement::EMappingMode lUVMappingMode = FbxGeometryElement::eNone;
	if (someData->mHasNormal)
	{
		lNormalMappingMode = mesh->GetElementNormal(0)->GetMappingMode();
		if (lNormalMappingMode == FbxGeometryElement::eNone)
		{
			someData->mHasNormal = false;
		}
		if (someData->mHasNormal && lNormalMappingMode != FbxGeometryElement::eByControlPoint)
		{
			someData->mAllByControlPoint = false;
		}
	}
	if (someData->mHasUV)
	{
		lUVMappingMode = mesh->GetElementUV(0)->GetMappingMode();
		if (lUVMappingMode == FbxGeometryElement::eNone)
		{
			someData->mHasUV = false;
		}
		if (someData->mHasUV && lUVMappingMode != FbxGeometryElement::eByControlPoint)
		{
			someData->mAllByControlPoint = false;
		}
	}

	// Allocate the array memory, by control point or by polygon vertex.
	int lPolygonVertexCount = mesh->GetControlPointsCount();
	//if (!someData->my)
	{
		ModelData::Layout newLayout;
		newLayout.myType = ModelData::VERTEX_POS;
		newLayout.mySize = VERTEX_STRIDE;
		newLayout.myOffset = 0;
		someData->myLayout.Add(newLayout);
		lPolygonVertexCount = lPolygonCount * TRIANGLE_VERTEX_COUNT;
	}
	int stride = VERTEX_STRIDE;
	size_t size = lPolygonVertexCount * VERTEX_STRIDE;
	//float * lVertices = new float[lPolygonVertexCount * VERTEX_STRIDE];
	unsigned int * lIndices = new unsigned int[lPolygonCount * TRIANGLE_VERTEX_COUNT];
	someData->myIndexCount = lPolygonCount * TRIANGLE_VERTEX_COUNT;
	//float * lNormals = NULL;
	if (someData->mHasNormal)
	{
		ModelData::Layout newLayout;
		newLayout.myType = ModelData::VERTEX_NORMAL;
		newLayout.mySize = NORMAL_STRIDE;
		newLayout.myOffset = stride*4;
		someData->myLayout.Add(newLayout);

		stride += NORMAL_STRIDE;
		size += lPolygonVertexCount * NORMAL_STRIDE;
		//lNormals = new float[lPolygonVertexCount * NORMAL_STRIDE];
	}
	//float * lUVs = NULL;
	FbxStringList lUVNames;
	mesh->GetUVSetNames(lUVNames);
	const char * lUVName = NULL;
	if (someData->mHasUV && lUVNames.GetCount())
	{
		ModelData::Layout newLayout;
		newLayout.myType = ModelData::VERTEX_UV;
		newLayout.mySize = UV_STRIDE;
		newLayout.myOffset = stride*4;
		someData->myLayout.Add(newLayout);

		stride += UV_STRIDE;
		size += lPolygonVertexCount * UV_STRIDE;
		//lUVs = new float[lPolygonVertexCount * UV_STRIDE];
		lUVName = lUVNames[0];
	}

	if (someData->myHasBiNormal)
	{
		ModelData::Layout newLayout;
		newLayout.myType = ModelData::VERTEX_BINORMAL;
		newLayout.mySize = BINORMAL_STRIDE;
		newLayout.myOffset = stride*4;
		someData->myLayout.Add(newLayout);

		stride += BINORMAL_STRIDE;
		size += lPolygonVertexCount * BINORMAL_STRIDE;
		//lUVs = new float[lPolygonVertexCount * UV_STRIDE];
	}

	if (someData->myHasTangents)
	{
		ModelData::Layout newLayout;
		newLayout.myType = ModelData::VERTEX_TANGENT;
		newLayout.mySize = TANGENT_STRIDE;
		newLayout.myOffset = stride*4;
		someData->myLayout.Add(newLayout);

		stride += TANGENT_STRIDE;
		size += lPolygonVertexCount * TANGENT_STRIDE;
		//lUVs = new float[lPolygonVertexCount * UV_STRIDE];
	}

	if (someData->myHasSkinweights)
	{
		ModelData::Layout newLayout;
		newLayout.myType = ModelData::VERTEX_SKINWEIGHTS;
		newLayout.mySize = SKINWEIGHT_STRIDE;
		newLayout.myOffset = stride*4;
		someData->myLayout.Add(newLayout);

		stride += SKINWEIGHT_STRIDE;
		size += lPolygonVertexCount * SKINWEIGHT_STRIDE;

		newLayout.myType = ModelData::VERTEX_BONEID;
		newLayout.mySize = BONEID_STRIDE;
		newLayout.myOffset = stride*4;
		someData->myLayout.Add(newLayout);

		stride += BONEID_STRIDE;
		size += lPolygonVertexCount * BONEID_STRIDE;
		//lUVs = new float[lPolygonVertexCount * UV_STRIDE];
	}

	float * lVertices = new float[size];

	FbxAMatrix globalPos;
	FbxVector4* weights = nullptr;
	FbxVectorTemplate4<int>* bones = nullptr;
	FbxTime time = static_cast<FbxTime>(0.0f);
	if(someData->myHasSkinweights)
	{
		weights = new FbxVector4[mesh->GetControlPointsCount()];
		bones = new FbxVectorTemplate4<int>[mesh->GetControlPointsCount()];
		ComputeLinearDeformation(globalPos,mesh,weights,bones,aAnimation);
	}

	const FbxGeometryElementBinormal * lBiNormalElement = NULL;
	const FbxGeometryElementTangent * lTangentElement = NULL;

	if (someData->myHasBiNormal)
	{
		lBiNormalElement = mesh->GetElementBinormal(0);
	}
	if (someData->myHasTangents)
	{
		lTangentElement = mesh->GetElementTangent(0);
	}

	// Populate the array with vertex attribute, if by control point.
	const FbxVector4 * lControlPoints = mesh->GetControlPoints();
	FbxVector4 lCurrentVertex;
	FbxVector4 lCurrentNormal;
	FbxVector4 lCurrentBiNormal;
	FbxVector4 lCurrentTangent;
	FbxVector2 lCurrentUV;
	if (someData->mAllByControlPoint)
	{
		const FbxGeometryElementNormal * lNormalElement = NULL;
		const FbxGeometryElementUV * lUVElement = NULL;
		if (someData->mHasNormal)
		{
			lNormalElement = mesh->GetElementNormal(0);
		}
		if (someData->mHasUV)
		{
			lUVElement = mesh->GetElementUV(0);
		}

		for (int lIndex = 0; lIndex < lPolygonVertexCount; ++lIndex)
		{
			int currentIndex = lIndex * stride;
			int addedSize = VERTEX_STRIDE;
			// Save the vertex position.
			lCurrentVertex = lControlPoints[lIndex];
				
			CU::Vector4f position(static_cast<float>(lCurrentVertex[0]),
					static_cast<float>(lCurrentVertex[1]),
					static_cast<float>(lCurrentVertex[2]),
					1);

			CU::Matrix44f fixMatrix;
			fixMatrix = CU::Matrix44<float>::CreateReflectionMatrixAboutAxis(CU::Vector3f(1,0,0));
			position = position*fixMatrix;

			lVertices[currentIndex] = position.x;
			lVertices[currentIndex + 1] = position.y;
			lVertices[currentIndex + 2] = position.z;
			lVertices[currentIndex + 3] = 1;


			// Save the normal.
			if (someData->mHasNormal)
			{
				int lNormalIndex = lIndex;
				if (lNormalElement->GetReferenceMode() == FbxLayerElement::eIndexToDirect)
				{
					lNormalIndex = lNormalElement->GetIndexArray().GetAt(lIndex);
				}
				lCurrentNormal = lNormalElement->GetDirectArray().GetAt(lNormalIndex);

				CU::Vector3f normal( static_cast<float>(lCurrentNormal[0]), static_cast<float>(lCurrentNormal[1]), static_cast<float>(lCurrentNormal[2]));
				normal = normal*CU::Matrix33<float>::CreateReflectionMatrixAboutAxis(CU::Vector3f(1, 0, 0));

				lVertices[currentIndex + addedSize] = normal.x;
				lVertices[currentIndex + addedSize + 1] = normal.y;
				lVertices[currentIndex + addedSize + 2] = normal.z;
				lVertices[currentIndex + addedSize + 3] = 0;
				addedSize += NORMAL_STRIDE;
			}

			// Save the UV.
			if (someData->mHasUV)
			{
				int lUVIndex = lIndex;
				if (lUVElement->GetReferenceMode() == FbxLayerElement::eIndexToDirect)
				{
					lUVIndex = lUVElement->GetIndexArray().GetAt(lIndex);
				}
				lCurrentUV = lUVElement->GetDirectArray().GetAt(lUVIndex);
				lVertices[currentIndex + addedSize] = static_cast<float>(lCurrentUV[0]);
				lVertices[currentIndex + addedSize + 1] = static_cast<float>(lCurrentUV[1])*-1.0f;
				addedSize += 2;
			}

			if (someData->myHasBiNormal)
				{
					int lBinormIndexIndex = lIndex;
					if (lBiNormalElement->GetReferenceMode() == FbxLayerElement::eIndexToDirect)
					{
						lBinormIndexIndex = lBiNormalElement->GetIndexArray().GetAt(lIndex);
					}

					lCurrentBiNormal = lBiNormalElement->GetDirectArray().GetAt(lBinormIndexIndex);
					//mesh->GetElementBinormal(lPolygonIndex, lVerticeIndex, lCurrentNormal);
					//lCurrentNormal = lCurrentNormal
					CU::Vector3f normal( static_cast<float>(lCurrentBiNormal[0]), static_cast<float>(lCurrentBiNormal[1]), static_cast<float>(lCurrentBiNormal[2]));
					normal = normal*CU::Matrix33<float>::CreateReflectionMatrixAboutAxis(CU::Vector3f(1, 0, 0));
					if (CU::Length(normal) != 0.f)
						CU::Normalize(normal);
					lVertices[currentIndex + addedSize] = normal.x;
					lVertices[currentIndex + addedSize + 1] = normal.y;
					lVertices[currentIndex + addedSize + 2] = normal.z;
					lVertices[currentIndex + addedSize + 3] = 0;
					addedSize += BINORMAL_STRIDE;
				}

				if (someData->myHasTangents)
				{
					int lBinormIndexIndex = lIndex;
					if (lTangentElement->GetReferenceMode() == FbxLayerElement::eIndexToDirect)
					{
						lBinormIndexIndex = lTangentElement->GetIndexArray().GetAt(lIndex);
					}

					lCurrentTangent = lTangentElement->GetDirectArray().GetAt(lBinormIndexIndex);

					//lCurrentNormal = lCurrentNormal
					CU::Vector3f normal( static_cast<float>(lCurrentTangent[0]), static_cast<float>(lCurrentTangent[1]), static_cast<float>(lCurrentTangent[2]));
					normal = normal*CU::Matrix33<float>::CreateReflectionMatrixAboutAxis(CU::Vector3f(1, 0, 0));
					if (CU::Length(normal) != 0.f)
						CU::Normalize(normal);
					lVertices[currentIndex + addedSize] = normal.x;
					lVertices[currentIndex + addedSize + 1] = normal.y;
					lVertices[currentIndex + addedSize + 2] = normal.z;
					lVertices[currentIndex + addedSize + 3] = 0;
					addedSize += TANGENT_STRIDE;
				}

				if(someData->myHasSkinweights)
				{
					FbxVector4 currentWeights = weights[lIndex];
					//currentWeights.Normalize();

					lVertices[currentIndex + addedSize] = static_cast<float>(currentWeights[0]);
					lVertices[currentIndex + addedSize + 1] = static_cast<float>(currentWeights[1]);
					lVertices[currentIndex + addedSize + 2] = static_cast<float>(currentWeights[2]);
					lVertices[currentIndex + addedSize + 3] = static_cast<float>(currentWeights[3]);
					addedSize += SKINWEIGHT_STRIDE;

					FbxVectorTemplate4<int> currentBones = bones[lIndex];

					lVertices[currentIndex + addedSize] = static_cast<float>(currentBones[0]);
					lVertices[currentIndex + addedSize + 1] = static_cast<float>(currentBones[1]);
					lVertices[currentIndex + addedSize + 2] = static_cast<float>(currentBones[2]);
					lVertices[currentIndex + addedSize + 3] = static_cast<float>(currentBones[3]);
					addedSize += BONEID_STRIDE;
				}
		}

	}

	int lVertexCount = 0;
	for (int lPolygonIndex = 0; lPolygonIndex < lPolygonCount; ++lPolygonIndex)
	{
		// The material for current face.
		int lMaterialIndex = 0;
		if (lMaterialIndice && lMaterialMappingMode == FbxGeometryElement::eByPolygon)
		{
			lMaterialIndex = lMaterialIndice->GetAt(lPolygonIndex);
		}

		// Where should I save the vertex attribute index, according to the material
		const int lIndexOffset = someData->mSubMeshes[lMaterialIndex]->IndexOffset +
			someData->mSubMeshes[lMaterialIndex]->TriangleCount * 3;
		for (int lVerticeIndex = TRIANGLE_VERTEX_COUNT-1; lVerticeIndex > -1; --lVerticeIndex)
		{
			const int lControlPointIndex = mesh->GetPolygonVertex(lPolygonIndex, lVerticeIndex);
				
			int vertexIndex = lIndexOffset + (TRIANGLE_VERTEX_COUNT-1) - lVerticeIndex;
			if (someData->mAllByControlPoint)
			{
				lIndices[vertexIndex] = static_cast<unsigned int>(lControlPointIndex);
			}
			// Populate the array with vertex attribute, if by polygon vertex.
			else
			{
				lIndices[vertexIndex] = static_cast<unsigned int>(lVertexCount);

				lCurrentVertex = lControlPoints[lControlPointIndex];
				int addedSize = VERTEX_STRIDE;
				int currentIndex = lVertexCount * stride;

				CU::Vector4f position(static_cast<float>(lCurrentVertex[0]),
					static_cast<float>(lCurrentVertex[1]),
					static_cast<float>(lCurrentVertex[2]),
					1);

				//fixMatrix
				CU::Matrix44f fixMatrix;
				fixMatrix = CU::Matrix44<float>::CreateReflectionMatrixAboutAxis(CU::Vector3f(1, 0, 0));
				position = position*fixMatrix;

				lVertices[currentIndex] = position.x;
				lVertices[currentIndex + 1] = position.y;
				lVertices[currentIndex + 2] = position.z;
				lVertices[currentIndex + 3] = 0;

				if (someData->mHasNormal)
				{
					mesh->GetPolygonVertexNormal(lPolygonIndex, lVerticeIndex, lCurrentNormal);
					CU::Vector3f normal( static_cast<float>(lCurrentNormal[0]), static_cast<float>(lCurrentNormal[1]), static_cast<float>(lCurrentNormal[2]));
					normal = normal*CU::Matrix33<float>::CreateReflectionMatrixAboutAxis(CU::Vector3f(1, 0, 0));
					if (CU::Length(normal) != 0.f)
						CU::Normalize(normal);

					lVertices[currentIndex + addedSize] = normal.x;
					lVertices[currentIndex + addedSize + 1] = normal.y;
					lVertices[currentIndex + addedSize + 2] = normal.z;
					lVertices[currentIndex + addedSize + 3] = 0;
					addedSize += NORMAL_STRIDE;
				}

				if (someData->mHasUV)
				{
					bool lUnmappedUV;
					mesh->GetPolygonVertexUV(lPolygonIndex, lVerticeIndex, lUVName, lCurrentUV, lUnmappedUV);
					lVertices[currentIndex + addedSize] = static_cast<float>(lCurrentUV[0]);
					lVertices[currentIndex + addedSize + 1] = static_cast<float>(lCurrentUV[1])*-1.0f;
					addedSize += UV_STRIDE;
				}
					
				if (someData->myHasBiNormal)
				{
					int lBinormIndexIndex = lVerticeIndex;
					if (lBiNormalElement->GetReferenceMode() == FbxLayerElement::eIndexToDirect)
					{
						lBinormIndexIndex = lBiNormalElement->GetIndexArray().GetAt(lVerticeIndex);
					}

					lCurrentBiNormal = lBiNormalElement->GetDirectArray().GetAt(lBinormIndexIndex);

					CU::Vector3f normal( static_cast<float>(lCurrentBiNormal[0]), static_cast<float>(lCurrentBiNormal[1]), static_cast<float>(lCurrentBiNormal[2]));
					normal = normal*CU::Matrix33<float>::CreateReflectionMatrixAboutAxis(CU::Vector3f(1, 0, 0));
					if (CU::Length(normal) != 0.f)
						CU::Normalize(normal);
					lVertices[currentIndex + addedSize] = normal.x;
					lVertices[currentIndex + addedSize + 1] = normal.y;
					lVertices[currentIndex + addedSize + 2] = normal.z;
					lVertices[currentIndex + addedSize + 3] = 0;
					addedSize += BINORMAL_STRIDE;
				}

				if (someData->myHasTangents)
				{
					int lBinormIndexIndex = lVerticeIndex;
					if (lTangentElement->GetReferenceMode() == FbxLayerElement::eIndexToDirect)
					{
						lBinormIndexIndex = lTangentElement->GetIndexArray().GetAt(lVerticeIndex);
					}

					lCurrentTangent = lTangentElement->GetDirectArray().GetAt(lBinormIndexIndex);

					mesh->GetPolygonVertexNormal(lPolygonIndex, lVerticeIndex, lCurrentNormal);

					CU::Vector3f normal( static_cast<float>(lCurrentTangent[0]), static_cast<float>(lCurrentTangent[1]), static_cast<float>(lCurrentTangent[2]));
					normal = normal*CU::Matrix33<float>::CreateReflectionMatrixAboutAxis(CU::Vector3f(1, 0, 0));
					if (CU::Length(normal) != 0.f)
						CU::Normalize(normal);
					lVertices[currentIndex + addedSize] = normal.x;
					lVertices[currentIndex + addedSize + 1] = normal.y;
					lVertices[currentIndex + addedSize + 2] = normal.z;
					lVertices[currentIndex + addedSize + 3] = 0;
					addedSize += TANGENT_STRIDE;
				}

				if(someData->myHasSkinweights)
				{
					FbxVector4 currentWeights = weights[lControlPointIndex];
					FbxVectorTemplate4<int> currentBones = bones[lControlPointIndex];
					for(int l = 0;l < 4;++l)
					{
						if(currentBones[l] == -1)
						{
							currentWeights[l] = 0.0f;
						}
					}
					currentWeights.Normalize();

					lVertices[currentIndex + addedSize] = static_cast<float>(currentWeights[0]);
					lVertices[currentIndex + addedSize + 1] = static_cast<float>(currentWeights[1]);
					lVertices[currentIndex + addedSize + 2] = static_cast<float>(currentWeights[2]);
					lVertices[currentIndex + addedSize + 3] = static_cast<float>(currentWeights[3]);
					addedSize += SKINWEIGHT_STRIDE;

						

					lVertices[currentIndex + addedSize] = *(float*)&currentBones[0];
					lVertices[currentIndex + addedSize + 1] = *(float*)&currentBones[1];
					lVertices[currentIndex + addedSize + 2] = *(float*)&currentBones[2];
					lVertices[currentIndex + addedSize + 3] = *(float*)&currentBones[3];
					addedSize += BONEID_STRIDE;
				}
			}
			++lVertexCount;
		}
		someData->mSubMeshes[lMaterialIndex]->TriangleCount += 1;
	}

	someData->myVertexCount = lVertexCount;
	someData->myVertexStride = stride;

	someData->myVertexBuffer = lVertices;
	someData->myIndicies = lIndices;

	if(weights)
	{
		delete [] weights;
		delete [] bones;
	}

	return true;
}