Exemple #1
0
UINT Converter::getMaterialIndex(FbxMesh *m)
{
	int triangleCount = m->GetPolygonCount();
	FbxLayerElementArrayTemplate<int> *indices;
	if (m->GetElementMaterial()) {
		indices = &(m->GetElementMaterial()->GetIndexArray());
		if (indices) {
			switch (m->GetElementMaterial()->GetMappingMode()) {
			case FbxGeometryElement::eByPolygon:
				if (indices->GetCount() == triangleCount)
					for (int i = 0; i < triangleCount; ++i) {
						return indices->GetAt(i);
					}
				break;
			case FbxGeometryElement::eAllSame:
				for (int i = 0; i < triangleCount; ++i) {
					return indices->GetAt(0);
				}
				break;
			default:
				throw std::exception("Material index mapping mode error.");
			}
		}
	}
	return 0;
}
Exemple #2
0
//===============================================================================================================================
void FBXLoader::AssociateMaterialToMesh(FbxNode* inNode)
{
	FbxLayerElementArrayTemplate<int>* materialIndices;
	FbxGeometryElement::EMappingMode materialMappingMode = FbxGeometryElement::eNone;
	FbxMesh* mesh = inNode->GetMesh();
	
	if (mesh->GetElementMaterial())
	{
		materialIndices = &(mesh->GetElementMaterial()->GetIndexArray());
		materialMappingMode = mesh->GetElementMaterial()->GetMappingMode();
		
		FBXSubsets* subset = mSubsets[iCurrentSubset];
		
		if (materialIndices)
		{
			switch (materialMappingMode)
			{
				case FbxGeometryElement::eByPolygon:
				{
					if (materialIndices->GetCount() == subset->mPolygonCount)
					{
						for (uint32 i = 0; i < subset->mPolygonCount; ++i)
						{
							uint32 materialIndex = materialIndices->GetAt(i);
							//subset->mTriangles[i].materialIndex = materialIndex;
							subset->mMaterialIndex = materialIndex;
						}
					}
				}
				break;
				case FbxGeometryElement::eAllSame:
				{
					uint32 materialIndex = materialIndices->GetAt(0);
					for (uint32 i = 0; i < subset->mPolygonCount; ++i)
					{
						//subset->mTriangles[i].materialIndex = materialIndex;
						subset->mMaterialIndex = materialIndex;
					}
				}
				break;
				default: throw std::exception("Invalid mapping mode for material\n");
			}
		}
	}
}
void GenerateLOD::Init_Buffer(fbxsdk::FbxMesh *pMesh, Model &model)
{
	model.SetVertexCount(static_cast<int>(ControlP->size()));
	model.SetPolygonCount(static_cast<int>(Triangles->size()));

	// Create the VertexBuffer
	model.CreateVertextBuffer();

	IDirect3DVertexBuffer9 *g_pVB = model.GetVertexBuffer();

	CUSTOMVERTEX *pVertices;
	g_pVB->Lock(0, 0, (void **)&pVertices, 0);
	FbxLayerElementArrayTemplate<FbxVector2> *pUVarray = NULL;
	bool hasUV = pMesh->GetTextureUV(&pUVarray);
	if (!hasUV) {
		printf("Has No Textures!\n");
	}

	WORD count = 0;
	std::unordered_map<int, WORD> RemainPoints;
	FbxVector4 *pControlPoints = pMesh->GetControlPoints();
	for (std::unordered_map<int, Point>::iterator it = (*ControlP).begin(); it != (*ControlP).end(); ++it) {
		const FbxVector4 &P = pControlPoints[it->first];
		pVertices[count].x = static_cast<FLOAT>(P[0]);
		pVertices[count].y = static_cast<FLOAT>(P[1]);
		pVertices[count].z = static_cast<FLOAT>(P[2]);

		// uv coordinate
		pVertices[count].tu = static_cast<FLOAT>((pUVarray->GetAt(*it->second.uvSet.begin()))[0]);
		pVertices[count].tv = static_cast<FLOAT>((pUVarray->GetAt(*it->second.uvSet.begin()))[1]);

		RemainPoints[it->first] = count;
		++count;
	}
	g_pVB->Unlock();

	
	// Create the IndexBuffer
	model.CreateIndexBuffer();

	IDirect3DIndexBuffer9 *g_pIB = model.GetIndexBuffer();

	WORD *index;
	int cnt = 0;
	g_pIB->Lock(0, 0, (void **)&index, 0);
	for (std::unordered_map<int, Face>::iterator it = (*Triangles).begin(); it != (*Triangles).end(); ++it) {
		index[cnt++] = RemainPoints[it->second.points[0]];
		index[cnt++] = RemainPoints[it->second.points[1]];
		index[cnt++] = RemainPoints[it->second.points[2]];
	}
	g_pIB->Unlock();
}
Exemple #4
0
void FBXImporter::ConnectMaterialsToMesh(FbxMesh* mesh, int triangleCount)
{
	// Get the material index list of current mesh.
	FbxLayerElementArrayTemplate<int>* materialIndices;
	FbxGeometryElement::EMappingMode materialMappingMode = FbxGeometryElement::eNone;

	if (mesh->GetElementMaterial() != nullptr)
	{
		// Get the material indices.
		materialIndices = &mesh->GetElementMaterial()->GetIndexArray();
		materialMappingMode = mesh->GetElementMaterial()->GetMappingMode();

		switch (materialMappingMode)
		{
		// 单mesh多材质的情况,我们需要按照三角形数量来遍历材质ID。
		case FbxLayerElement::eByPolygon:

			isByPolygon = true;
			isAllSame = false;

			if (materialIndices->GetCount() == triangleCount)
			{
				int materialId = materialIndices->GetAt(0);
				int polygonCount = 0;
				vector<MaterialIdOffset>& offsets = mMeshData->materialIdOffsets;

				MaterialIdOffset offset;
				offset.material = new Material();

				for (int triangleIndex = 0; triangleIndex < triangleCount; triangleIndex++)
				{
					int materialIndex = materialIndices->GetAt(triangleIndex);

					// 比较当前materialId和上次循环的materialId,
					// 如果相同的话说明我们在处理拥有同一个materialId的三角形集合,
					// 我们只需要增加三角形计数,保存materialId。
					if (materialId == materialIndex)
					{
						offset.polygonCount++;
						offset.material->materialId = materialIndex;

						// 如果已经遍历最后一个三角形,保存材质偏移信息。n
						if (triangleIndex == triangleCount - 1)
						{
							offsets.push_back(offset);
						}
					}
					// 如果当前materialId和上次循环的不同,说明开始了新的三角形集合
					// 那么我们就将旧的集合保存到容器,开始处理新集合。
					else
					{
						offsets.push_back(offset);
						offset.material = new Material();
						offset.material->materialId = materialIndex;
						offset.polygonCount = 0;
						offset.polygonCount++;
					}

					materialId = materialIndex;
				}
			}

			break;

		case FbxLayerElement::eAllSame:
		{
			isAllSame = true;
			isByPolygon = false;

			int materialIndex = materialIndices->GetAt(0);

			MaterialIdOffset offset;
			offset.material = new Material();

			vector<MaterialIdOffset>& offsets = mMeshData->materialIdOffsets;

			offset.material->materialId = materialIndex;
			offset.polygonCount = triangleCount;

			offsets.push_back(offset);
		}

			break;
		default:
			break;
		}
	}
}
Exemple #5
0
int Mesh::GetMaterialId(int polygon)
{
	FbxLayerElementArrayTemplate<int> *materials = nullptr;
	m_nativeMesh->GetMaterialIndices(&materials);
	return materials->GetAt(polygon);
}
Exemple #6
0
//ур╣╫ак
bool VBOMesh::Initialize(const FbxMesh *pMesh)
{
	if (!pMesh->GetNode())
		return false;

	const int lPolygonCount = pMesh->GetPolygonCount();

	// Count the polygon count of each material
	FbxLayerElementArrayTemplate<int>* lMaterialIndice = NULL;
	FbxGeometryElement::EMappingMode lMaterialMappingMode = FbxGeometryElement::eNone;
	if (pMesh->GetElementMaterial())
	{
		lMaterialIndice = &pMesh->GetElementMaterial()->GetIndexArray();
		lMaterialMappingMode = pMesh->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);
					if (mSubMeshes.GetCount() < lMaterialIndex + 1)
					{
						mSubMeshes.Resize(lMaterialIndex + 1);
					}
					if (mSubMeshes[lMaterialIndex] == NULL)
					{
						mSubMeshes[lMaterialIndex] = new SubMesh;
					}
					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 < mSubMeshes.GetCount(); i++)
				{
					if (mSubMeshes[i] == NULL)
						mSubMeshes[i] = new SubMesh;
				}

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

	// All faces will use the same material.
	if (mSubMeshes.GetCount() == 0)
	{
		mSubMeshes.Resize(1);
		mSubMeshes[0] = new SubMesh();
	}

	// 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.
	mHasNormal = pMesh->GetElementNormalCount() > 0;
	mHasUV = pMesh->GetElementUVCount() > 0;
	FbxGeometryElement::EMappingMode lNormalMappingMode = FbxGeometryElement::eNone;
	FbxGeometryElement::EMappingMode lUVMappingMode = FbxGeometryElement::eNone;
	if (mHasNormal)
	{
		lNormalMappingMode = pMesh->GetElementNormal(0)->GetMappingMode();
		if (lNormalMappingMode == FbxGeometryElement::eNone)
		{
			mHasNormal = false;
		}
		if (mHasNormal && lNormalMappingMode != FbxGeometryElement::eByControlPoint)
		{
			mAllByControlPoint = false;
		}
	}
	if (mHasUV)
	{
		lUVMappingMode = pMesh->GetElementUV(0)->GetMappingMode();
		if (lUVMappingMode == FbxGeometryElement::eNone)
		{
			mHasUV = false;
		}
		if (mHasUV && lUVMappingMode != FbxGeometryElement::eByControlPoint)
		{
			mAllByControlPoint = false;
		}
	}

	// Allocate the array memory, by control point or by polygon vertex.
	int lPolygonVertexCount = pMesh->GetControlPointsCount();
	if (!mAllByControlPoint)
	{
		lPolygonVertexCount = lPolygonCount * TRIANGLE_VERTEX_COUNT;
	}
	float * lVertices = new float[lPolygonVertexCount * VERTEX_STRIDE];
	unsigned int * lIndices = new unsigned int[lPolygonCount * TRIANGLE_VERTEX_COUNT];
	float * lNormals = NULL;
	if (mHasNormal)
	{
		lNormals = new float[lPolygonVertexCount * NORMAL_STRIDE];
	}
	float * lUVs = NULL;
	FbxStringList lUVNames;
	pMesh->GetUVSetNames(lUVNames);
	const char * lUVName = NULL;
	if (mHasUV && lUVNames.GetCount())
	{
		lUVs = new float[lPolygonVertexCount * UV_STRIDE];
		lUVName = lUVNames[0];
	}

	// Populate the array with vertex attribute, if by control point.
	const FbxVector4 * lControlPoints = pMesh->GetControlPoints();
	FbxVector4 lCurrentVertex;
	FbxVector4 lCurrentNormal;
	FbxVector2 lCurrentUV;
	if (mAllByControlPoint)
	{
		const FbxGeometryElementNormal * lNormalElement = NULL;
		const FbxGeometryElementUV * lUVElement = NULL;
		if (mHasNormal)
		{
			lNormalElement = pMesh->GetElementNormal(0);
		}
		if (mHasUV)
		{
			lUVElement = pMesh->GetElementUV(0);
		}
		for (int lIndex = 0; lIndex < lPolygonVertexCount; ++lIndex)
		{
			// Save the vertex position.
			lCurrentVertex = lControlPoints[lIndex];
			lVertices[lIndex * VERTEX_STRIDE] = static_cast<float>(lCurrentVertex[0]);
			lVertices[lIndex * VERTEX_STRIDE + 1] = static_cast<float>(lCurrentVertex[1]);
			lVertices[lIndex * VERTEX_STRIDE + 2] = static_cast<float>(lCurrentVertex[2]);
			lVertices[lIndex * VERTEX_STRIDE + 3] = 1;

			// Save the normal.
			if (mHasNormal)
			{
				int lNormalIndex = lIndex;
				if (lNormalElement->GetReferenceMode() == FbxLayerElement::eIndexToDirect)
				{
					lNormalIndex = lNormalElement->GetIndexArray().GetAt(lIndex);
				}
				lCurrentNormal = lNormalElement->GetDirectArray().GetAt(lNormalIndex);
				lNormals[lIndex * NORMAL_STRIDE] = static_cast<float>(lCurrentNormal[0]);
				lNormals[lIndex * NORMAL_STRIDE + 1] = static_cast<float>(lCurrentNormal[1]);
				lNormals[lIndex * NORMAL_STRIDE + 2] = static_cast<float>(lCurrentNormal[2]);
			}

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

	}

	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 = mSubMeshes[lMaterialIndex]->IndexOffset +
			mSubMeshes[lMaterialIndex]->TriangleCount * 3;
		for (int lVerticeIndex = 0; lVerticeIndex < TRIANGLE_VERTEX_COUNT; ++lVerticeIndex)
		{
			const int lControlPointIndex = pMesh->GetPolygonVertex(lPolygonIndex, lVerticeIndex);

			if (mAllByControlPoint)
			{
				lIndices[lIndexOffset + lVerticeIndex] = static_cast<unsigned int>(lControlPointIndex);
			}
			// Populate the array with vertex attribute, if by polygon vertex.
			else
			{
				lIndices[lIndexOffset + lVerticeIndex] = static_cast<unsigned int>(lVertexCount);

				lCurrentVertex = lControlPoints[lControlPointIndex];
				lVertices[lVertexCount * VERTEX_STRIDE] = static_cast<float>(lCurrentVertex[0]);
				lVertices[lVertexCount * VERTEX_STRIDE + 1] = static_cast<float>(lCurrentVertex[1]);
				lVertices[lVertexCount * VERTEX_STRIDE + 2] = static_cast<float>(lCurrentVertex[2]);
				lVertices[lVertexCount * VERTEX_STRIDE + 3] = 1;

				if (mHasNormal)
				{
					pMesh->GetPolygonVertexNormal(lPolygonIndex, lVerticeIndex, lCurrentNormal);
					lNormals[lVertexCount * NORMAL_STRIDE] = static_cast<float>(lCurrentNormal[0]);
					lNormals[lVertexCount * NORMAL_STRIDE + 1] = static_cast<float>(lCurrentNormal[1]);
					lNormals[lVertexCount * NORMAL_STRIDE + 2] = static_cast<float>(lCurrentNormal[2]);
				}

				if (mHasUV)
				{
					bool lUnmappedUV;
					pMesh->GetPolygonVertexUV(lPolygonIndex, lVerticeIndex, lUVName, lCurrentUV, lUnmappedUV);
					lUVs[lVertexCount * UV_STRIDE] = static_cast<float>(lCurrentUV[0]);
					lUVs[lVertexCount * UV_STRIDE + 1] = static_cast<float>(lCurrentUV[1]);
				}
			}
			++lVertexCount;
		}
		mSubMeshes[lMaterialIndex]->TriangleCount += 1;
	}

	// Create VBOs
	glGenBuffers(VBO_COUNT, mVBONames);

	// Save vertex attributes into GPU
	glBindBuffer(GL_ARRAY_BUFFER, mVBONames[VERTEX_VBO]);
	glBufferData(GL_ARRAY_BUFFER, lPolygonVertexCount * VERTEX_STRIDE * sizeof(float), lVertices, GL_STATIC_DRAW);
	delete[] lVertices;

	if (mHasNormal)
	{
		glBindBuffer(GL_ARRAY_BUFFER, mVBONames[NORMAL_VBO]);
		glBufferData(GL_ARRAY_BUFFER, lPolygonVertexCount * NORMAL_STRIDE * sizeof(float), lNormals, GL_STATIC_DRAW);
		delete[] lNormals;
	}

	if (mHasUV)
	{
		glBindBuffer(GL_ARRAY_BUFFER, mVBONames[UV_VBO]);
		glBufferData(GL_ARRAY_BUFFER, lPolygonVertexCount * UV_STRIDE * sizeof(float), lUVs, GL_STATIC_DRAW);
		delete[] lUVs;
	}

	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mVBONames[INDEX_VBO]);
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, lPolygonCount * TRIANGLE_VERTEX_COUNT * sizeof(unsigned int), lIndices, GL_STATIC_DRAW);
	delete[] lIndices;

	return true;
}
Exemple #7
0
//--------------------------------------------------------------
void ofxFBXMesh::setFBXMesh( FbxMesh* lMesh ) {
	fbxMesh = lMesh;
//	name = lMesh->GetName();
	mesh.clear();
    
    // from ViewScene Example included with the FBX SDK //
    if (!lMesh->GetNode()) {
        ofLogError("ofxFBXMesh") << " error setFBXMesh, lMesh->GetNode failed" << endl;
        return;
    }
    
    
    const int lPolygonCount = lMesh->GetPolygonCount();
    
    
    // Count the polygon count of each material
    FbxLayerElementArrayTemplate<int>* lMaterialIndice = NULL;
    FbxGeometryElement::EMappingMode lMaterialMappingMode = FbxGeometryElement::eNone;
    if (lMesh->GetElementMaterial()) {
        lMaterialIndice = &lMesh->GetElementMaterial()->GetIndexArray();
        lMaterialMappingMode = lMesh->GetElementMaterial()->GetMappingMode();
        if (lMaterialIndice && lMaterialMappingMode == FbxGeometryElement::eByPolygon) {
            FBX_ASSERT(lMaterialIndice->GetCount() == lPolygonCount);
            if (lMaterialIndice->GetCount() == lPolygonCount) {
                
                // make sure the vector is setup and we have the proper amount of materials ready //
                for (int lPolygonIndex = 0; lPolygonIndex < lPolygonCount; ++lPolygonIndex) {
                    const int lMaterialIndex = lMaterialIndice->GetAt(lPolygonIndex);
                    if(lMaterialIndex >= 0) {
                        if (subMeshes.size() < lMaterialIndex + 1) {
                            subMeshes.resize(lMaterialIndex + 1);
                        }
                    }
                }
                
                // Count the faces of each material
                for (int lPolygonIndex = 0; lPolygonIndex < lPolygonCount; ++lPolygonIndex) {
                    const int lMaterialIndex = lMaterialIndice->GetAt(lPolygonIndex);
//                    cout << "lMaterialIndex = " << lMaterialIndex << " submesh.size = " << subMeshes.size() << endl;
                    if(lMaterialIndex >= 0 ) {
                        subMeshes[lMaterialIndex].triangleCount += 1;
                    }
                }
                
                // Record the offset (how many vertex)
                const int lMaterialCount = subMeshes.size();
                int lOffset = 0;
                for (int lIndex = 0; lIndex < lMaterialCount; ++lIndex) {
                    subMeshes[lIndex].indexOffset = lOffset;
                    lOffset += subMeshes[lIndex].triangleCount * 3;
//                    subMeshes[lIndex].totalIndices = subMeshes[lIndex].triangleCount * 3;
//                    cout << "polygon: " << lIndex << " totalIndices = " << subMeshes[lIndex].totalIndices << endl;
                    // This will be used as counter in the following procedures, reset to zero
                    subMeshes[lIndex].triangleCount = 0;
                }
                FBX_ASSERT(lOffset == lPolygonCount * 3); // what?
            }
        }
    }
    
    if(subMeshes.size() == 0) {
        subMeshes.resize(1);
    }
    
    // TODO: Account for if all mapping modes are not by control point //
    
    bool bHasNormals = lMesh->GetElementNormalCount() > 0;
    bool bMapNormalsByControlPoint = true;
    bool bHasUvs = lMesh->GetElementUVCount() > 0;
    bool bMapUvsByControlPoint = true;
    
    // are the normals mapped by control point or by polygon?
    FbxGeometryElement::EMappingMode lNormalMappingMode = FbxGeometryElement::eNone;
    if(bHasNormals) {
        lNormalMappingMode = lMesh->GetElementNormal(0)->GetMappingMode();
        if (lNormalMappingMode == FbxGeometryElement::eNone) {
            bHasNormals = false;
        }
        if (bHasNormals && lNormalMappingMode != FbxGeometryElement::eByControlPoint) {
            bMapNormalsByControlPoint = false;
        }
    }
    
    FbxGeometryElement::EMappingMode lUVMappingMode = FbxGeometryElement::eNone;
    if (bHasUvs) {
        lUVMappingMode = lMesh->GetElementUV(0)->GetMappingMode();
        if (lUVMappingMode == FbxGeometryElement::eNone) {
            bHasUvs = false;
        }
        if (bHasUvs && lUVMappingMode != FbxGeometryElement::eByControlPoint) {
            bMapUvsByControlPoint = false;
        }
    }
    
    bAllMappedByControlPoint = (bMapNormalsByControlPoint && bMapUvsByControlPoint);
    
//    if(lMaterialMappingMode == FbxGeometryElement::eAllSame) {
//        
//    }
    
    int lPolygonVertexCount = lMesh->GetControlPointsCount();
    
    if( bAllMappedByControlPoint ) {
        const FbxVector4 * lControlPoints = lMesh->GetControlPoints();
        for(int i = 0; i < lMesh->GetControlPointsCount(); i++ ) {
            mesh.addVertex( ofVec3f( lControlPoints[i][0], lControlPoints[i][1], lControlPoints[i][2] ) );
        }
        
        for(int i = 0; i < lMesh->GetPolygonCount(); i++ ) {
            for (int lVerticeIndex = 0; lVerticeIndex < 3; ++lVerticeIndex) {
                const int lControlPointIndex = lMesh->GetPolygonVertex(i, lVerticeIndex);
                mesh.addIndex( lControlPointIndex );
            }
        }
        
        if(subMeshes.size() == 1) {
            subMeshes[0].totalIndices = mesh.getNumIndices();
        }
        
        // normals
        if(bHasNormals) {
            ofMesh normalsMesh;
            //cout << "ofxFBXMesh :: we have normals for " << getName() << endl;
            if(bMapNormalsByControlPoint) {
                //cout << "ofxFBXMesh :: normals by control point for " << getName() << endl;
                const FbxGeometryElementNormal * lNormalElement = lMesh->GetElementNormal(0);
                for(int i = 0; i < lMesh->GetControlPointsCount(); i++ ) {
                    int lNormalIndex = i;
                    if (lNormalElement->GetReferenceMode() == FbxLayerElement::eIndexToDirect) {
                        lNormalIndex = lNormalElement->GetIndexArray().GetAt(i);
                    }
                    FbxVector4 lCurrentNormal = lNormalElement->GetDirectArray().GetAt(lNormalIndex);
                    normalsMesh.addNormal( ofVec3f(lCurrentNormal[0], lCurrentNormal[1], lCurrentNormal[2]) );
                }
                mesh.addNormals( normalsMesh.getNormals() );
            }
        }
        
        // textures //
        if(bHasUvs) {
            //cout << "ofxFBXMesh :: we have tex coords for " << getName() << endl;
            if(bMapUvsByControlPoint) {
                //cout << "ofxFBXMesh :: tex coords by control point " << getName() << endl;
                const FbxGeometryElementUV * lUVElement = lMesh->GetElementUV(0);
                for(int i = 0; i < lMesh->GetControlPointsCount(); i++ ) {
                    int lUVIndex = i;
                    if (lUVElement->GetReferenceMode() == FbxLayerElement::eIndexToDirect) {
                        lUVIndex = lUVElement->GetIndexArray().GetAt(i);
                    }
                    FbxVector2 lCurrentUV = lUVElement->GetDirectArray().GetAt(lUVIndex);
                    mesh.addTexCoord( ofVec2f(lCurrentUV[0], lCurrentUV[1]) );
                }
            }
        }
    } else {
        
//        cout << "--- " << getName() << " mapped by polygons ---------------" << endl;
//        cout << "numSubMeshes = " << subMeshes.size() << " polygon count = " << lPolygonCount << " control points = " << fbxMesh->GetControlPointsCount() << endl;
        
//        if(lMaterialMappingMode == FbxGeometryElement::eNone) {
//            cout << "Material mapping mode = none" << endl;
//        } else if (lMaterialMappingMode == FbxGeometryElement::eByControlPoint) {
//            cout << "Material mapping mode = eByControlPoint" << endl;
//        } else if(lMaterialMappingMode == FbxGeometryElement::eByPolygonVertex) {
//            cout << "Material mapping mode = eByPolygonVertex" << endl;
//        } else if(lMaterialMappingMode == FbxGeometryElement::eByPolygon) {
//            cout << "Material mapping mode = eByPolygon" << endl;
//        } else if(lMaterialMappingMode == FbxGeometryElement::eByEdge) {
//            cout << "Material mapping mode = eByEdge" << endl;
//        } else if(lMaterialMappingMode == FbxGeometryElement::eAllSame) {
//            cout << "Material mapping mode = eAllSame" << endl;
//        }
//        
//        if(lMaterialIndice) {
//            cout << "lMaterialIndice size = " << lMaterialIndice->GetCount() << endl;
//        } else {
//            cout << "did not get the lMaterialIndice" << endl;
//        }
        
        const FbxVector4 * lControlPoints = fbxMesh->GetControlPoints();
        mesh.getVertices().resize( lPolygonCount * 3 );
        mesh.getIndices().resize( lPolygonCount * 3 );
        if(bHasNormals) {
            mesh.getNormals().resize( lPolygonCount * 3 );
        }
        
//        cout << "Polygon vertex count = " << fbxMesh->GetPolygonVertexCount() << endl;
        
        const char * lUVName = NULL;
        FbxStringList lUVNames;
        fbxMesh->GetUVSetNames(lUVNames);
        if(bHasUvs && lUVNames.GetCount() ) {
            mesh.getTexCoords().resize( lPolygonCount * 3 );
            lUVName = lUVNames[0];
        }
        for(int i = 0; i < lUVNames.GetCount(); i++ ) {
//            cout << "lUVName = " << lUVNames[0] << endl;
        }
        
        
        
        FbxVector4 lCurrentVertex;
        FbxVector4 lCurrentNormal;
        FbxVector2 lCurrentUV;
        
        const FbxGeometryElementUV * lUVElement = lMesh->GetElementUV(0);
        
        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);
                if(lMaterialIndex < 0) {
                    lMaterialIndex = 0;
                }
            }
            
            // Where should I save the vertex attribute index, according to the material
            const int lIndexOffset = subMeshes[lMaterialIndex].indexOffset + subMeshes[lMaterialIndex].triangleCount * 3;
//            const int lIndexOffset = fbxMesh->GetPolygonVertexIndex(lPolygonIndex);
            for (int lVerticeIndex = 0; lVerticeIndex < 3; ++lVerticeIndex) {
                const int lControlPointIndex = fbxMesh->GetPolygonVertex(lPolygonIndex, lVerticeIndex);
                
                // Populate the array with vertex attribute, if by polygon vertex.
                mesh.getIndices()[lIndexOffset + lVerticeIndex] = static_cast<unsigned int>(lVertexCount);
                
                lCurrentVertex = lControlPoints[ lControlPointIndex ];
                mesh.getVertices()[lVertexCount].set( lCurrentVertex[0], lCurrentVertex[1], lCurrentVertex[2] );
                
                if (bHasNormals) {
                    if(fbxMesh->GetPolygonVertexNormal( lPolygonIndex, lVerticeIndex, lCurrentNormal )) {
                        int normalIndex = lVertexCount;
                        mesh.getNormals()[normalIndex].set( lCurrentNormal[0], lCurrentNormal[1], lCurrentNormal[2] );
                    }
                }
                
                if (bHasUvs) {
                    bool lUnmappedUV;
                    fbxMesh->GetPolygonVertexUV(lPolygonIndex, lVerticeIndex, lUVName, lCurrentUV, lUnmappedUV);
                    int tcoordIndex = lVertexCount;
                    mesh.getTexCoords()[ tcoordIndex ].set( lCurrentUV[0], lCurrentUV[1] );
                }
                ++lVertexCount;
            }
            
            subMeshes[lMaterialIndex].triangleCount += 1;
            subMeshes[lMaterialIndex].totalIndices += 3;
            
//            cout << "materialIndex = " << lMaterialIndex << endl;
        }
        
    }
    
    // All faces will use the same material.
//    if ( subMeshes.size() == 1) {
//        //        meshMaterials.resize(1);
////        subMeshes[0].totalIndices = mesh.getNumIndices();
//    }
    for(int i = 0; i < subMeshes.size(); i++ ) {
//        cout << i << " submesh totalindicies = " << subMeshes[i].totalIndices << " total verts = " << mesh.getNumVertices() << " polygonos = " << lPolygonCount << endl;
    }
    
//    cout << "--------------------------------------- " << endl << endl;
    veebs.setMesh( mesh, GL_STREAM_DRAW );
    original = mesh;
    
}
Exemple #8
0
bool Mesh::init(FbxMesh* pFbxMesh)
{
    uint32_t normalCount = pFbxMesh->GetElementNormalCount();
    uint32_t uvCount = pFbxMesh->GetElementUVCount();
    FbxGeometryElement::EMappingMode normalMappingMode = normalCount ? pFbxMesh->GetElementNormal(0)->GetMappingMode()
                                                                     : FbxGeometryElement::eNone;
    FbxGeometryElement::EMappingMode uvMappingModel = uvCount ? pFbxMesh->GetElementUV(0)->GetMappingMode()
                                                              : FbxGeometryElement::eNone;

    bool hasNormal = normalMappingMode != FbxGeometryElement::eNone;
    bool hasUV = uvMappingModel != FbxGeometryElement::eNone;

    bool byControlPoint = hasNormal && normalMappingMode == FbxGeometryElement::eByControlPoint && hasUV && uvMappingModel == FbxGeometryElement::eByControlPoint;

    uint32_t polygonCount = pFbxMesh->GetPolygonCount();
    uint32_t controlPointCount = byControlPoint
        ? pFbxMesh->GetControlPointsCount()
        : polygonCount * TRIANGLE_VERTEX_COUNT;

    this->vertices.resize(controlPointCount * VERTEX_STRIDE);
    this->indices.resize(polygonCount * TRIANGLE_VERTEX_COUNT);
    if (hasNormal)
        this->normals.resize(controlPointCount * NORMAL_STRIDE);

    FbxStringList uvNames;
    pFbxMesh->GetUVSetNames(uvNames);
    const char* pUVName = nullptr;
    if (hasUV) {
        this->uvs.resize(controlPointCount * UV_STRIDE);
        pUVName = uvNames[0];
    }

    /* Vertex Attributes */
    const FbxVector4* pControlPoints = pFbxMesh->GetControlPoints();
    FbxVector4 currentVertex;
    FbxVector4 currentNormal;
    FbxVector2 currentUV;
    if (byControlPoint) {
        const FbxGeometryElementNormal* pNormalElement = nullptr;
        const FbxGeometryElementUV* pUVElement = nullptr;
        if (hasNormal)
            pNormalElement = pFbxMesh->GetElementNormal(0);
        if (hasUV)
            pUVElement = pFbxMesh->GetElementUV(0);

        for (uint32_t i = 0; i < controlPointCount; ++i) {
            currentVertex = pControlPoints[i];
            this->vertices[i * VERTEX_STRIDE] = static_cast<float>(currentVertex[0]);
            this->vertices[i * VERTEX_STRIDE + 1] = static_cast<float>(currentVertex[1]);
            this->vertices[i * VERTEX_STRIDE + 2] = static_cast<float>(currentVertex[2]);
            this->vertices[i * VERTEX_STRIDE + 3] = 1.0f;

            if (hasNormal) {
                int normalIndex = i;
                if (pNormalElement->GetReferenceMode() == FbxLayerElement::eIndexToDirect) {
                    normalIndex = pNormalElement->GetIndexArray().GetAt(i);
                }
                currentNormal = pNormalElement->GetDirectArray().GetAt(normalIndex);
                this->normals[i * NORMAL_STRIDE] = static_cast<float>(currentNormal[0]);
                this->normals[i * NORMAL_STRIDE + 1] = static_cast<float>(currentNormal[1]);
                this->normals[i * NORMAL_STRIDE + 2] = static_cast<float>(currentNormal[2]);
            }

            if (hasUV) {
                int uvIndex = i;
                if (pUVElement->GetReferenceMode() == FbxLayerElement::eIndexToDirect) {
                    uvIndex = pUVElement->GetIndexArray().GetAt(i);
                }
                currentUV = pUVElement->GetDirectArray().GetAt(uvIndex);
                this->uvs[i * UV_STRIDE] = static_cast<float>(currentUV[0]);
                this->uvs[i * UV_STRIDE + 1] = static_cast<float>(currentUV[1]);
            }
        }
    } // end of byControlPoint

    /* Slice the mesh according to materials */
    FbxLayerElementArrayTemplate<int>* pMaterialIndices = nullptr;
    FbxGeometryElement::EMappingMode materialMappingMode = FbxGeometryElement::eNone;
    if (pFbxMesh->GetElementMaterial()) {
        pMaterialIndices = &pFbxMesh->GetElementMaterial()->GetIndexArray();
        materialMappingMode = pFbxMesh->GetElementMaterial()->GetMappingMode();
        if (pMaterialIndices && materialMappingMode == FbxGeometryElement::eByPolygon) {
            FBX_ASSERT(pMaterialIndices->GetCount() == polygonCount);
            for (uint32_t i = 0; i < polygonCount; ++i) {
                const uint32_t materialIndex = pMaterialIndices->GetAt(i);
                if (materialIndex >= slices.size()) // we meet a new material
                {
                    slices.emplace_back(0, 0);
                }
                slices[materialIndex].triangleCount += 1;
            }

            int offset = 0;
            for (uint32_t i = 0; i < slices.size(); ++i) {
                slices[i].indexOffset = offset;
                offset += slices[i].triangleCount * 3;
                // this will be reused during per-Polygon processing
                slices[i].triangleCount = 0;
            }
            FBX_ASSERT(offset == polygonCount * 3);
        }
    }

    // There is only one material.
    if (slices.size() == 0) {
        slices.emplace_back(0, 0);
    }

    /* Indices */
    for (uint32_t vertexCount = 0, i = 0; i < polygonCount; ++i) {
        int materialIndex = 0;
        if (pMaterialIndices && materialMappingMode == FbxGeometryElement::eByPolygon) {
            materialIndex = pMaterialIndices->GetAt(i);
        }
        const int indexOffset = slices[materialIndex].indexOffset + slices[materialIndex].triangleCount * 3;
        for (int v = 0; v < TRIANGLE_VERTEX_COUNT; ++v) {
            const int controlPointIndex = pFbxMesh->GetPolygonVertex(i, v);

            if (byControlPoint) {
                this->indices[indexOffset + v] = static_cast<unsigned int>(controlPointIndex);
            } else {
                this->indices[indexOffset + v] = static_cast<unsigned int>(vertexCount);

                currentVertex = pControlPoints[controlPointIndex];
                this->vertices[vertexCount * VERTEX_STRIDE] = static_cast<float>(currentVertex[0]);
                this->vertices[vertexCount * VERTEX_STRIDE + 1] = static_cast<float>(currentVertex[1]);
                this->vertices[vertexCount * VERTEX_STRIDE + 2] = static_cast<float>(currentVertex[2]);
                this->vertices[vertexCount * VERTEX_STRIDE + 3] = 1.0f;

                if (hasNormal) {
                    pFbxMesh->GetPolygonVertexNormal(i, v, currentNormal);
                    this->normals[vertexCount * NORMAL_STRIDE] = static_cast<float>(currentNormal[0]);
                    this->normals[vertexCount * NORMAL_STRIDE + 1] = static_cast<float>(currentNormal[1]);
                    this->normals[vertexCount * NORMAL_STRIDE + 2] = static_cast<float>(currentNormal[2]);
                }

                if (hasUV) {
                    bool bUnmappedUV;
                    pFbxMesh->GetPolygonVertexUV(i, v, pUVName, currentUV, bUnmappedUV);
                    this->uvs[vertexCount * UV_STRIDE] = static_cast<float>(currentUV[0]);
                    this->uvs[vertexCount * UV_STRIDE] = static_cast<float>(currentUV[1]);
                }
            }
            ++vertexCount;
        }
        slices[materialIndex].triangleCount += 1;
    }

    return true;
}
Exemple #9
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;
}
Exemple #10
0
	Submesh *FBX::buildSubmeshFromFBX(FbxMesh *lMesh, int material_index, bool single_material) {
		int lPolygonCount=lMesh->GetPolygonCount();
		FbxLayerElementArrayTemplate<int>* lMaterialIndice = NULL;

		bool add=false;

		if (!single_material) {
			FbxGeometryElement::EMappingMode lMaterialMappingMode = FbxGeometryElement::eNone;
			if (lMesh->GetElementMaterial()) {
				lMaterialIndice = &lMesh->GetElementMaterial()->GetIndexArray();
				lMaterialMappingMode = lMesh->GetElementMaterial()->GetMappingMode();

				if (!lMaterialIndice) printf("Mesh has no material index element.\n");

				if (lMaterialIndice && lMaterialMappingMode == FbxGeometryElement::eByPolygon) {
					if (lMaterialIndice->GetCount() == lPolygonCount) {
						add = true;
					}
				}
			}
		}
		else add = true;
	
		if (add) {
			vector<Vertex *> new_vertices;
			vector<Vector3> new_faces;

			int control_points_count=lMesh->GetControlPointsCount();
			FbxVector4 *control_points=lMesh->GetControlPoints();

			int vertex_index = 0;
			for (int lPolygonIndex = 0; lPolygonIndex < lPolygonCount; ++lPolygonIndex) {
				if (lMaterialIndice) {
					const int lMaterialIndex = lMaterialIndice->GetAt(lPolygonIndex);
					if (lMaterialIndex != material_index) continue;
				}

				int polygon_size=lMesh->GetPolygonSize(lPolygonIndex);
				if (polygon_size == 3) {
					Vector3 face;

					for (int j=0; j<polygon_size; j++) {
						Vertex *vertex=new Vertex();

						int control_point_index=lMesh->GetPolygonVertex(lPolygonIndex, j);
						FbxVector4 control_point=control_points[control_point_index];
						vertex->setPosition(Vector3(control_point[0], control_point[2], -control_point[1]));

						// Get Normal for Vertex
						FbxVector4 normal;
						lMesh->GetPolygonVertexNormal(lPolygonIndex, j, normal);
						vertex->setNormal(Vector3(normal[0], normal[2], -normal[1]));

						// Get UVs for Vertex
						FbxStringList uv_sets;
						lMesh->GetUVSetNames(uv_sets);
						for (int set=0; set<uv_sets.GetCount(); set++) {
							if (set >= 4) break;
							FbxVector2 uv;
							bool no_uv;
							lMesh->GetPolygonVertexUV(lPolygonIndex, j, uv_sets[set].Buffer(), uv, no_uv);
							vertex->setUV(Vector2(uv[0], 1.0 - uv[1]), set);
						}

						// Get Vertex Color for Vertex
						FbxColor vtx_c(1.0, 1.0, 1.0, 1.0);
						for (int l = 0; l < lMesh->GetElementVertexColorCount(); l++) {
							FbxGeometryElementVertexColor* leVtxc = lMesh->GetElementVertexColor(l);

							if (leVtxc->GetMappingMode() == FbxGeometryElement::eByControlPoint) {
								if (leVtxc->GetReferenceMode() == FbxGeometryElement::eDirect) {
									vtx_c = leVtxc->GetDirectArray().GetAt(control_point_index);
								}
								else if (leVtxc->GetReferenceMode() == FbxGeometryElement::eIndexToDirect) {
									int id = leVtxc->GetIndexArray().GetAt(control_point_index);
									vtx_c = leVtxc->GetDirectArray().GetAt(id);
								}
							}
							else if (leVtxc->GetMappingMode() == FbxGeometryElement::eByPolygonVertex) {
								if (leVtxc->GetReferenceMode() == FbxGeometryElement::eDirect) {
									vtx_c = leVtxc->GetDirectArray().GetAt(vertex_index);
								}
								else if (leVtxc->GetReferenceMode() == FbxGeometryElement::eIndexToDirect) {
									int id = leVtxc->GetIndexArray().GetAt(vertex_index);
									vtx_c = leVtxc->GetDirectArray().GetAt(id);
								}
							}
						}

						vertex->setColor(Color(vtx_c.mRed, vtx_c.mGreen, vtx_c.mBlue, vtx_c.mAlpha));
						
						if (j == 0) face.x=new_vertices.size();
						if (j == 1) face.y=new_vertices.size();
						if (j == 2) face.z=new_vertices.size();

						new_vertices.push_back(vertex);
						vertex_index++;
					}
					new_faces.push_back(face);
					
				}
				else printf("Unsupported polygon size %d.\n", polygon_size);
			}

			printf("Building submesh with %d vertices and %d faces\n", new_vertices.size(), new_faces.size());

			if ((new_vertices.size() >= 3) && new_faces.size()) {
				Submesh *submesh=new Submesh();
				submesh->build(new_vertices, new_faces);
				submesh->addBone(0);

				VertexFormat *vertex_format=new VertexFormat(LIBGENS_VERTEX_FORMAT_PC);
				submesh->setVertexFormat(vertex_format);
				return submesh;
			}
		}

		return NULL;
	}
Exemple #11
0
FBXMesh::Builder::MeshMetaData::MeshMetaData(FbxMesh const* mesh, unsigned int vaoOffset) 
	: mesh(mesh),
	vaoOffset(vaoOffset),
	hasNormals(false),
	hasUvs(false)
{
	
	if (!mesh->GetNode())
		return;

	const int lPolygonCount = mesh->GetPolygonCount();

	// Count the polygon count of each material -> split up in submeshes
	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);
					if (subMeshMetaData.size() < lMaterialIndex + 1)
					{
						subMeshMetaData.resize(lMaterialIndex + 1);
					}

					subMeshMetaData[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 < subMeshMetaData.size(); i++)
				//{
				//    if (subMeshMetaData[i] == NULL)
				//        mSubMeshes[i] = new SubMesh;
				//}

				// Record the offset (how many vertex)
				const int lMaterialCount = (int)subMeshMetaData.size();
				int lOffset = 0;
				for (int lIndex = 0; lIndex < lMaterialCount; ++lIndex)
				{
					subMeshMetaData[lIndex].indexOffset = lOffset;
					lOffset += subMeshMetaData[lIndex].triangleCount * 3;
					// This will be used as counter in the following procedures, reset to zero
					subMeshMetaData[lIndex].triangleCount = 0;
				}
				FBX_ASSERT(lOffset == lPolygonCount * 3);
			}
		}
	}

	// All faces will use the same material.
	if (subMeshMetaData.size() == 0)
	{
		subMeshMetaData.resize(1);
	}
	
	hasNormals = mesh->GetElementNormalCount() > 0;
	hasUvs = mesh->GetElementUVCount() > 0;

	allByControlPoint = true;
	
	// Congregate all the data of a mesh to be cached.
	// If normal or UV is by polygon vertex, record all vertex attributes by polygon vertex.
	FbxGeometryElement::EMappingMode lNormalMappingMode = FbxGeometryElement::eNone;
	FbxGeometryElement::EMappingMode lUVMappingMode = FbxGeometryElement::eNone;
	if (hasNormals)
	{
		lNormalMappingMode = mesh->GetElementNormal(0)->GetMappingMode();
		if (lNormalMappingMode == FbxGeometryElement::eNone)
		{
			hasNormals = false;
		}
		if (hasNormals && lNormalMappingMode != FbxGeometryElement::eByControlPoint)
		{
			allByControlPoint = false;
		}
	}
	if (hasUvs)
	{
		lUVMappingMode = mesh->GetElementUV(0)->GetMappingMode();
		if (lUVMappingMode == FbxGeometryElement::eNone)
		{
			hasUvs = false;
		}
		if (hasUvs && lUVMappingMode != FbxGeometryElement::eByControlPoint)
		{
			allByControlPoint = false;
		}
	}
	// Allocate the array memory, by control point or by polygon vertex.
	int lPolygonVertexCount = mesh->GetControlPointsCount();
	if (!allByControlPoint)
	{
		lPolygonVertexCount = lPolygonCount * TRIANGLE_VERTEX_COUNT;
	}
	vertices.resize(lPolygonVertexCount);
	indices.resize(lPolygonCount * TRIANGLE_VERTEX_COUNT);


	float * lNormals = NULL;
	if (hasNormals)
	{
		normals.resize(lPolygonVertexCount);
	}
	float * lUVs = NULL;
	FbxStringList lUVNames;
	mesh->GetUVSetNames(lUVNames);
	const char * lUVName = NULL;
	if (hasUvs && lUVNames.GetCount())
	{
		uvs.resize(lPolygonVertexCount);
		lUVName = lUVNames[0];
	}


	// Populate the array with vertex attribute, if by control point.
	const FbxVector4 * lControlPoints = mesh->GetControlPoints();
	FbxVector4 lCurrentVertex;
	FbxVector4 lCurrentNormal;
	FbxVector2 lCurrentUV;
	if (allByControlPoint)
	{
		const FbxGeometryElementNormal * lNormalElement = NULL;
		const FbxGeometryElementUV * lUVElement = NULL;
		if (hasNormals)
		{
			lNormalElement = mesh->GetElementNormal(0);
		}
		if (hasUvs)
		{
			lUVElement = mesh->GetElementUV(0);
		}
		for (int lIndex = 0; lIndex < lPolygonVertexCount; ++lIndex)
		{
			// Save the vertex position.
			lCurrentVertex = lControlPoints[lIndex];

			vertices[lIndex] = glm::vec3(static_cast<float>(lCurrentVertex[0]),
										 static_cast<float>(lCurrentVertex[1]),
										 static_cast<float>(lCurrentVertex[2]));
			modelSpaceAABB.merge(vertices[lIndex]);

			// Save the normal.
			if (hasNormals)
			{
				int lNormalIndex = lIndex;
				if (lNormalElement->GetReferenceMode() == FbxLayerElement::eIndexToDirect)
				{
					lNormalIndex = lNormalElement->GetIndexArray().GetAt(lIndex);
				}
				lCurrentNormal = lNormalElement->GetDirectArray().GetAt(lNormalIndex);
				
				normals[lIndex] = glm::vec3(static_cast<float>(lCurrentNormal[0]),
											 static_cast<float>(lCurrentNormal[1]),
											 static_cast<float>(lCurrentNormal[2]));
			}

			// Save the UV.
			if (hasUvs)
			{
				int lUVIndex = lIndex;
				if (lUVElement->GetReferenceMode() == FbxLayerElement::eIndexToDirect)
				{
					lUVIndex = lUVElement->GetIndexArray().GetAt(lIndex);
				}
				lCurrentUV = lUVElement->GetDirectArray().GetAt(lUVIndex);

				uvs[lIndex] = glm::vec2(static_cast<float>(lCurrentUV[0]),
										static_cast<float>(lCurrentUV[1]));
			}
		}
	}


	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 = subMeshMetaData[lMaterialIndex].indexOffset +
			subMeshMetaData[lMaterialIndex].triangleCount * 3;
		for (int lVerticeIndex = 0; lVerticeIndex < TRIANGLE_VERTEX_COUNT; ++lVerticeIndex)
		{
			const int lControlPointIndex = mesh->GetPolygonVertex(lPolygonIndex, lVerticeIndex);

			if (allByControlPoint)
			{
				indices[lIndexOffset + lVerticeIndex] = static_cast<unsigned int>(lControlPointIndex);
			}
			// Populate the array with vertex attribute, if by polygon vertex.
			else
			{
				indices[lIndexOffset + lVerticeIndex] = static_cast<unsigned int>(lVertexCount);

				lCurrentVertex = lControlPoints[lControlPointIndex];

				vertices[lVertexCount] = glm::vec3(static_cast<float>(lCurrentVertex[0]),
												   static_cast<float>(lCurrentVertex[1]),
												   static_cast<float>(lCurrentVertex[2]));
				modelSpaceAABB.merge(vertices[lVertexCount]);

				if (hasNormals)
				{
					mesh->GetPolygonVertexNormal(lPolygonIndex, lVerticeIndex, lCurrentNormal);

					normals[lVertexCount] = glm::vec3(static_cast<float>(lCurrentNormal[0]),
													   static_cast<float>(lCurrentNormal[1]),
													   static_cast<float>(lCurrentNormal[2]));
				}

				if (hasUvs)
				{
					bool lUnmappedUV;
					mesh->GetPolygonVertexUV(lPolygonIndex, lVerticeIndex, lUVName, lCurrentUV, lUnmappedUV);
					
					uvs[lVertexCount] = glm::vec2(static_cast<float>(lCurrentUV[0]),
												  static_cast<float>(lCurrentUV[1]));
				}
			}
			++lVertexCount;
		}
		subMeshMetaData[lMaterialIndex].triangleCount += 1;
	}
}