Beispiel #1
0
Material* FBXScene::GetMaterialLinkedWithPolygon(FbxMesh* pFBXMesh, int nLayerIndex, int nPolygonIndex, int nPolygonVertexIndex, int nVertexIndex)
{
	if( nLayerIndex < 0 || nLayerIndex > pFBXMesh->GetLayerCount() )
		return NULL;

	FbxNode* pNode = pFBXMesh->GetNode();

	if( !pNode )
		return NULL;

	FbxLayerElementMaterial* pFBXMaterial = pFBXMesh->GetLayer(nLayerIndex)->GetMaterials();

	if( pFBXMaterial )
	{
		int nMappingIndex = GetMappingIndex( pFBXMaterial->GetMappingMode(), nPolygonIndex, 0, nVertexIndex );

		if( nMappingIndex < 0 )
			return NULL;

		FbxLayerElement::EReferenceMode referenceMode = pFBXMaterial->GetReferenceMode();

		
		if( referenceMode == FbxLayerElement::EReferenceMode::eDirect )
		{
			if( nMappingIndex < pNode->GetMaterialCount() )
			{
				return GetMaterial(pNode->GetMaterial(nMappingIndex));
			}
		}
		else if( referenceMode == FbxLayerElement::EReferenceMode::eIndexToDirect )
		{
			const FbxLayerElementArrayTemplate<int>& pMaterialIndexArray = pFBXMaterial->GetIndexArray();

			if( nMappingIndex < pMaterialIndexArray.GetCount() )
			{
				int nIndex = pMaterialIndexArray.GetAt(nMappingIndex);
				if( nIndex < pNode->GetMaterialCount() )
				{
					return GetMaterial(pNode->GetMaterial(nIndex));
				}
			}
		}
	}
	
	return NULL;
}
void MaterialHandler::MapMaterials(FbxNode * pNode, SceneMap * sceneMap)
{


	//Recursively extract the children
	for (int j = 0; j < pNode->GetChildCount(); j++)
		MapMaterials(pNode->GetChild(j), sceneMap);

	FbxGeometry* pGeometry = pNode->GetGeometry();
	int materialCount = 0;
	FbxNode* node = NULL;



	if (pGeometry) {

		node = pGeometry->GetNode();

		if (node)
			materialCount = pNode->GetMaterialCount();


		if (materialCount > 0)
		{

			for (int i = 0; i < materialCount; i++)
			{
				if (pNode->GetMaterial(i))
				{
					FbxSurfaceMaterial *pMaterial = node->GetMaterial(i);
					std::cout << pMaterial->GetName() << "\n";

						if (sceneMap->materialHash.find(pMaterial->GetName()) == sceneMap->materialHash.end()) {
							// not found
							std::cout << "New material found!  mapping..\n";
							sceneMap->materialHash[pMaterial->GetName()] = sceneMap->materialID;
							sceneMap->materialID += 1;
						}
						else {
							// found
							std::cout << "Material " << pMaterial->GetName() << " already exist .. skipping mapping of material" << std::endl;
						}

					//ProcessData(pMaterial, materialCount, outputMat);
				}

			}
		}


	}


}
// メッシュ情報処理(再帰関数)
void GetMeshData(FbxNode *parent, VertexDataArray& outVertexData)
{
	// メッシュだけ処理
	int numKids = parent->GetChildCount();
	for(int i = 0; i < numKids; i++)
	{
		FbxNode *child = parent->GetChild(i);

		// メッシュを見つけたら
		if(child->GetMesh())
		{
			FbxMesh* pMesh = child->GetMesh();// static_cast<FbxMesh*>(child->GetNodeAttribute());
			printf("メッシュ発見\n");

			printf("名前:%s\n", pMesh->GetName());
			printf("ポリゴン数:%d\n", pMesh->GetPolygonCount());
			printf("マテリアル数:%d\n", pMesh->GetElementMaterialCount());

			printf("コントロールポイント数(頂点座標):%d\n", pMesh->GetControlPointsCount());
			printf("UV数:%d\n", pMesh->GetTextureUVCount());

			FbxArray<FbxVector4> normals;
			pMesh->GetPolygonVertexNormals(normals);
			printf("法線数:%d\n", normals.GetCount());

			// 頂点情報取得
			GetFBXVertexData(pMesh, outVertexData);
		}

		// マテリアル
		int numMat = child->GetMaterialCount();
		for(int j = 0; j < numMat; ++j)
		{
			FbxSurfaceMaterial* mat = child->GetMaterial(j);
			if(mat)
			{
				GetMatrialData(mat);
			}
		}

		if(numMat == 0)
		{
			printf("マテリアルなし\n");
		}

		child->GetChild(0);

		// 更に子を処理
		GetMeshData(child, outVertexData);
	}
}
void MaterialHandler::GetMaterialData(FbxNode * pNode, MaterialExport* outputMat, SceneMap* sceneMap)
{
	//Recursively extract the children
	for (int j = 0; j < pNode->GetChildCount(); j++)
		GetMaterialData(pNode->GetChild(j),outputMat,sceneMap);

	if (outputMat == nullptr)		//If the first material is processed. create a new MaterialExport object
	{
		outputMat = new MaterialExport;
	}

	FbxGeometry* pGeometry = pNode->GetGeometry();
	int materialCount = 0;
	FbxNode* node = NULL;

	if (pGeometry) { //If the node has any geometry

		node = pGeometry->GetNode();

		if (node)
			materialCount = pNode->GetMaterialCount(); //Get the amount of materials the geometry has
				
	
		if (materialCount > 0)
		{
			
			for (int i = 0; i < materialCount; i++)
			{
				if (pNode->GetMaterial(i))
				{
					FbxSurfaceMaterial *pMaterial = node->GetMaterial(i);  //Get the material
					ProcessData(pMaterial, materialCount, outputMat,sceneMap); //process the data!
				}
				
			}
		}
		
	
	}
}
//-------------------------------------------------------------------------------------------------------------------------------------------
void transferMaterials(FbxGeometry* fbxMesh, Mesh* mesh){
    int numMaterials = 0;
    if (fbxMesh == NULL){
        throw new Exception("fbxMesh can not be NULL !");
    }

    FbxNode* fbxNode = NULL;
    fbxNode = fbxMesh->GetNode();
    if (fbxNode){
        numMaterials = fbxNode->GetMaterialCount();
    }

    LOG_DEBUG << "   Number of materials: " << numMaterials;

    if (numMaterials > 0)
    {
        FbxPropertyT<FbxDouble3> lKFbxDouble3;
        FbxPropertyT<FbxDouble> lKFbxDouble1;
        FbxColor theColor;

        for (int matId = 0; matId < numMaterials; matId++){
            Material* material = new Material();

            FbxSurfaceMaterial* fbxMaterial = fbxNode->GetMaterial(matId);

            // Get the implementation to see f it's a hardware shader
            const FbxImplementation* fbxImplementation = GetImplementation(fbxMaterial, FBXSDK_IMPLEMENTATION_HLSL);
            string fbxImplementationType = "HLSL";
            if (fbxImplementation != NULL){
                fbxImplementation = GetImplementation(fbxMaterial, FBXSDK_IMPLEMENTATION_CGFX);
                fbxImplementationType = "CFGX";
            }

            if (fbxImplementation)
            {
                // Handle hardware shader
                // TODO: transfer material using hardware shader
            }
            else if (fbxMaterial->GetClassId().Is(FbxSurfacePhong::ClassId))
            {
                // Handle phong shader

                // Transfer Ambient color
                lKFbxDouble3 = ((FbxSurfacePhong*)fbxMaterial)->Ambient;
                material->Ambient = Vector4s(lKFbxDouble3.Get()[0], lKFbxDouble3.Get()[1], lKFbxDouble3.Get()[2], 1);

                // Transfer Diffuse color
                lKFbxDouble3 = ((FbxSurfacePhong*)fbxMaterial)->Diffuse;
                material->Diffuse = Vector4s(lKFbxDouble3.Get()[0], lKFbxDouble3.Get()[1], lKFbxDouble3.Get()[2], 1);

                // Transfer Specular color
                lKFbxDouble3 = ((FbxSurfacePhong*)fbxMaterial)->Specular;
                material->Specular = Vector4s(lKFbxDouble3.Get()[0], lKFbxDouble3.Get()[1], lKFbxDouble3.Get()[2], 1);

                // Transfer Emissive color
                lKFbxDouble3 = ((FbxSurfacePhong*)fbxMaterial)->Emissive;
                material->Emissive = Vector4s(lKFbxDouble3.Get()[0], lKFbxDouble3.Get()[1], lKFbxDouble3.Get()[2], 1);

                // Transfer Transperency factor
                lKFbxDouble1 = ((FbxSurfacePhong*)fbxMaterial)->TransparencyFactor;
                material->Opacity = 1.0 - lKFbxDouble1.Get();

                // Transfer Shininess
                lKFbxDouble3 = ((FbxSurfacePhong*)fbxMaterial)->Shininess;
                material->Shininess = lKFbxDouble1.Get();
                
                // Transfer Reflectivity
                lKFbxDouble3 = ((FbxSurfacePhong*)fbxMaterial)->ReflectionFactor;
                material->Reflectivity = lKFbxDouble1.Get();
            }
            else if (fbxMaterial->GetClassId().Is(FbxSurfaceLambert::ClassId))
            {
                // Handle Lambert shader
                lKFbxDouble3 = ((FbxSurfaceLambert *)fbxMaterial)->Ambient;
                material->Ambient = Vector4s(lKFbxDouble3.Get()[0], lKFbxDouble3.Get()[1], lKFbxDouble3.Get()[2], 1);

                // Display the Diffuse Color
                lKFbxDouble3 = ((FbxSurfaceLambert *)fbxMaterial)->Diffuse;
                material->Diffuse = Vector4s(lKFbxDouble3.Get()[0], lKFbxDouble3.Get()[1], lKFbxDouble3.Get()[2], 1);

                // Display the Emissive
                lKFbxDouble3 = ((FbxSurfaceLambert *)fbxMaterial)->Emissive;
                material->Emissive = Vector4s(lKFbxDouble3.Get()[0], lKFbxDouble3.Get()[1], lKFbxDouble3.Get()[2], 1);

                // Display the Opacity
                lKFbxDouble1 = ((FbxSurfaceLambert *)fbxMaterial)->TransparencyFactor;
                material->Opacity = 1.0 - lKFbxDouble1.Get();
            }
            else
            {
                LOG_WARNING << "Unknown type of Material !";
            }

            FbxPropertyT<FbxString> fbxString;
            fbxString = fbxMaterial->ShadingModel;
            material->ShadingMode = fbxString.Get();

            mesh->Materials.push_back(material);
        }
    }

    LOG_DEBUG << "Transfer materials successfully! ";
}
void Tools::DisplayMaterial::DisplayMaterial( FbxGeometry *i_geometry )
{
	DisplayCommon::DisplayString( "\n\n--------------------\nMaterial\n--------------------" );
	int materialCount = 0;
	FbxNode *node = NULL;

	if( i_geometry )
	{
		node = i_geometry->GetNode();
		if( node )
			materialCount = node->GetMaterialCount();
	}

	if( materialCount > 0 )
	{
		FbxPropertyT<FbxDouble3> double3;
		FbxPropertyT<FbxDouble> double1;
		FbxColor theColor;

		for( int ctr = 0; ctr < materialCount; ctr++ )
		{
			DisplayCommon::DisplayInt( "        Material ", ctr );

			FbxSurfaceMaterial *material = node->GetMaterial( ctr );

			DisplayCommon::DisplayString( "            Name: \"", (char *) material->GetName(), "\"" ); 

#ifdef DISPLAY_HARDWARE_SHADER_INFORMATION
			//Get the implementation to see if it's a hardware shader.
			// Note:: this cause memory leak
			const FbxImplementation* implementation = GetImplementation( material, FBXSDK_IMPLEMENTATION_HLSL );
			FbxString implementationType = "HLSL";
			if( !implementation )
			{
				implementation = GetImplementation( material, FBXSDK_IMPLEMENTATION_CGFX );
				implementationType = "CGFX";
			}

			if( implementation )
			{
				//Now we have a hardware shader, let's read it
				FBXSDK_printf( "            Hardware Shader Type: %s\n", implemenationType.Buffer() );
				DisplayCommon::DisplayString( "            Hardware Shader Type: ", implemenationType );

				const FbxBindingTable* rootTable = implementation->GetRootTable();
				FbxString fileName = rootTable->DescAbsoluteURL.Get();
				FbxString techniqueName = rootTable->DescTAG.Get(); 

				const FbxBindingTable* table = implementation->GetRootTable();
				size_t entryNum = table->GetEntryCount();

				for( int i = 0; i < (int)entryNum; i++ )
				{
					const FbxBindingTableEntry& entry = table->GetEntry( i );
					const char *entrySrcType = entry.GetEntryType( true ); 
					FbxProperty fbxProp;

					FbxString test = entry.GetSource();
					FBXSDK_printf( "            Entry: %s\n", test.Buffer() );
					DisplayCommon::DisplayString( "            Entry: %s\n", test );

					if ( strcmp( FbxPropertyEntryView::sEntryType, entrySrcType ) == 0 )
					{
						fbxProp = material->FindPropertyHierarchical(entry.GetSource()); 
						if( !fbxProp.IsValid() )
						{
							fbxProp = material->RootProperty.FindHierarchical( entry.GetSource() );
						}
					}
					else if( strcmp( FbxConstantEntryView::sEntryType, entrySrcType ) == 0 )
					{
						fbxProp = implementation->GetConstants().FindHierarchical( entry.GetSource() );
					}
					if( fbxProp.IsValid() )
					{
						if( fbxProp.GetSrcObjectCount<FbxTexture>() > 0 )
						{
							//do what you want with the textures
							for( int j = 0; j < fbxProp.GetSrcObjectCount<FbxFileTexture>(); j++ )
							{
								FbxFileTexture *tex = fbxProp.GetSrcObject<FbxFileTexture>( j );
								FBXSDK_printf( "           File Texture: %s\n", tex->GetFileName() );
								DisplayCommon::DisplayString( "           File Texture: %s\n", tex->GetFileName() );
							}
							for( int j = 0; j < fbxProp.GetSrcObjectCount<FbxLayeredTexture>(); j++ )
							{
								FbxLayeredTexture *tex = fbxProp.GetSrcObject<FbxLayeredTexture>( j );
								FBXSDK_printf( "        Layered Texture: %s\n", tex->GetName() );
								DisplayCommon::DisplayString( "        Layered Texture: %s\n", tex->GetName() );
							}
							for( int j = 0; j < fbxProp.GetSrcObjectCount<FbxProceduralTexture>(); j++ )
							{
								FbxProceduralTexture *tex = fbxProp.GetSrcObject<FbxProceduralTexture>( j );
								FBXSDK_printf( "     Procedural Texture: %s\n", tex->GetName() );
								DisplayCommon::DisplayString( "     Procedural Texture: %s\n", tex->GetName() );
							}
						}
						else
						{
							FbxDataType fbxType = fbxProp.GetPropertyDataType();
							FbxString fbxName = fbxType.GetName();
							if( FbxBoolDT == fbxType )
							{
								DisplayCommon::DisplayBool( "                Bool: ", fbxProp.Get<FbxBool>() );
							}
							else if( FbxIntDT == fbxType ||  FbxEnumDT  == fbxType )
							{
								DisplayCommon::DisplayInt( "                Int: ", fbxProp.Get<FbxInt>() );
							}
							else if( FbxFloatDT == fbxType )
							{
								DisplayCommon::DisplayDouble( "                Float: ", fbxProp.Get<FbxFloat>() );
							}
							else if( FbxDoubleDT == fbxType )
							{
								DisplayCommon::DisplayDouble( "                Double: ", fbxProp.Get<FbxDouble>() );
							}
							else if( FbxStringDT == fbxType || FbxUrlDT  == fbxType || FbxXRefUrlDT  == fbxType )
							{
								DisplayCommon::DisplayString( "                String: ", fbxProp.Get<FbxString>().Buffer() );
							}
							else if( FbxDouble2DT == fbxType )
							{
								FbxDouble2 double2 = fbxProp.Get<FbxDouble2>();
								FbxVector2 vector;
								vector[0] = double2[0];
								vector[1] = double2[1];
								DisplayCommon::Display2DVector( "                2D vector: ", vector );
							}
							else if( (FbxDouble3DT == fbxType) || (FbxColor3DT == fbxType) )
							{
								FbxDouble3 double3 = fbxProp.Get<FbxDouble3>();
								FbxVector4 vector;
								vector[0] = double3[0];
								vector[1] = double3[1];
								vector[2] = double3[2];
								DisplayCommon::Display3DVector( "                3D vector: ", vector );
							}
							else if( (FbxDouble4DT == fbxType) || (FbxColor4DT == fbxType) )
							{
								FbxDouble4 double4 = fbxProp.Get<FbxDouble4>();
								FbxVector4 vector;
								vector[0] = double4[0];
								vector[1] = double4[1];
								vector[2] = double4[2];
								vector[3] = double4[3];
								DisplayCommon::Display4DVector( "                4D vector: ", vector );
							}
							else if( FbxDouble4x4DT == fbxType )
							{
								FbxDouble4x4 double44 = fbxProp.Get<FbxDouble4x4>();
								for( int j = 0; j < 4; j++ )
								{
									FbxVector4 vector;
									vector[0] = double44[j][0];
									vector[1] = double44[j][1];
									vector[2] = double44[j][2];
									vector[3] = double44[j][3];
									DisplayCommon::Display4DVector( "                4x4D vector: ", vector );
								}
							}
						}
					}
				}
			}
			else
#endif	// #ifdef DISPLAY_HARDWARE_SHADER_INFORMATION
			if( material->GetClassId().Is(FbxSurfacePhong::ClassId) )
			{
				// We found a Phong material.  Display its properties.

				// Display the Ambient Color
				double3 = ((FbxSurfacePhong *) material)->Ambient;
				theColor.Set( double3.Get()[0], double3.Get()[1], double3.Get()[2] );
				DisplayCommon::DisplayColor( "            Ambient: ", theColor );

				// Display the Diffuse Color
				double3 = ((FbxSurfacePhong *) material)->Diffuse;
				theColor.Set( double3.Get()[0], double3.Get()[1], double3.Get()[2] );
				DisplayCommon::DisplayColor( "            Diffuse: ", theColor );

				// Display the Specular Color (unique to Phong materials)
				double3 = ((FbxSurfacePhong *) material)->Specular;
				theColor.Set( double3.Get()[0], double3.Get()[1], double3.Get()[2] );
				DisplayCommon::DisplayColor( "            Specular: ", theColor );

				// Display the Emissive Color
				double3 = ((FbxSurfacePhong *) material)->Emissive;
				theColor.Set( double3.Get()[0], double3.Get()[1], double3.Get()[2] );
				DisplayCommon::DisplayColor( "            Emissive: ", theColor );

				//Opacity is Transparency factor now
				double1 = ((FbxSurfacePhong *) material)->TransparencyFactor;
				DisplayCommon::DisplayDouble( "            Opacity: ", 1.0-double1.Get() );

				// Display the Shininess
				double1 = ((FbxSurfacePhong *) material)->Shininess;
				DisplayCommon::DisplayDouble( "            Shininess: ", double1.Get() );

				// Display the Reflectivity
				double1 = ((FbxSurfacePhong *) material)->ReflectionFactor;
				DisplayCommon::DisplayDouble( "            Reflectivity: ", double1.Get() );
			}
			else if( material->GetClassId().Is(FbxSurfaceLambert::ClassId) )
			{
				// We found a Lambert material. Display its properties.
				// Display the Ambient Color
				double3 = ((FbxSurfaceLambert *)material)->Ambient;
				theColor.Set( double3.Get()[0], double3.Get()[1], double3.Get()[2] );
				DisplayCommon::DisplayColor( "            Ambient: ", theColor );

				// Display the Diffuse Color
				double3 = ((FbxSurfaceLambert *)material)->Diffuse;
				theColor.Set( double3.Get()[0], double3.Get()[1], double3.Get()[2] );
				DisplayCommon::DisplayColor( "            Diffuse: ", theColor );

				// Display the Emissive
				double3 = ((FbxSurfaceLambert *)material)->Emissive;
				theColor.Set( double3.Get()[0], double3.Get()[1], double3.Get()[2] );
				DisplayCommon::DisplayColor( "            Emissive: ", theColor );

				// Display the Opacity
				double1 = ((FbxSurfaceLambert *)material)->TransparencyFactor;
				DisplayCommon::DisplayDouble( "            Opacity: ", 1.0-double1.Get() );
			}
			else
				DisplayCommon::DisplayString( "Unknown type of Material" );

			FbxPropertyT<FbxString> string;
			string = material->ShadingModel;
			DisplayCommon::DisplayString( "            Shading Model: ", string.Get() );
		}
	}
}
Beispiel #7
0
//converts a FBX mesh to a CC mesh
static ccMesh* FromFbxMesh(FbxMesh* fbxMesh, FileIOFilter::LoadParameters& parameters)
{
	if (!fbxMesh)
		return 0;

	int polyCount = fbxMesh->GetPolygonCount();
	//fbxMesh->GetLayer(
	unsigned triCount = 0;
	unsigned polyVertCount = 0; //different from vertCount (vertices can be counted multiple times here!)
	//as we can't load all polygons (yet ;) we already look if we can load any!
	{
		unsigned skipped = 0;
		for (int i=0; i<polyCount; ++i)
		{
			int pSize = fbxMesh->GetPolygonSize(i);

			if (pSize == 3)
			{
				++triCount;
				polyVertCount += 3;
			}
			else if (pSize == 4)
			{
				triCount += 2;
				polyVertCount += 4;
			}
			else
			{
				++skipped;
			}
		}

		if (triCount == 0)
		{
			ccLog::Warning(QString("[FBX] No triangle or quad found in mesh '%1'! (polygons with more than 4 vertices are not supported for the moment)").arg(fbxMesh->GetName()));
			return 0;
		}
		else if (skipped != 0)
		{
			ccLog::Warning(QString("[FBX] Some polygons in mesh '%1' were ignored (%2): polygons with more than 4 vertices are not supported for the moment)").arg(fbxMesh->GetName()).arg(skipped));
			return 0;
		}
	}

	int vertCount = fbxMesh->GetControlPointsCount();
	if (vertCount <= 0)
	{
		ccLog::Warning(QString("[FBX] Mesh '%1' has no vetex or no polygon?!").arg(fbxMesh->GetName()));
		return 0;
	}

	ccPointCloud* vertices = new ccPointCloud("vertices");
	ccMesh* mesh = new ccMesh(vertices);
	mesh->setName(fbxMesh->GetName());
	mesh->addChild(vertices);
	vertices->setEnabled(false);
	
	if (!mesh->reserve(static_cast<unsigned>(triCount)) || !vertices->reserve(vertCount))
	{
		ccLog::Warning(QString("[FBX] Not enough memory to load mesh '%1'!").arg(fbxMesh->GetName()));
		delete mesh;
		return 0;
	}

	//colors
	{
		for (int l=0; l<fbxMesh->GetElementVertexColorCount(); l++)
		{
			FbxGeometryElementVertexColor* vertColor = fbxMesh->GetElementVertexColor(l);
			//CC can only handle per-vertex colors
			if (vertColor->GetMappingMode() == FbxGeometryElement::eByControlPoint)
			{
				if (vertColor->GetReferenceMode() == FbxGeometryElement::eDirect
					|| vertColor->GetReferenceMode() == FbxGeometryElement::eIndexToDirect)
				{
					if (vertices->reserveTheRGBTable())
					{
						switch (vertColor->GetReferenceMode())
						{
						case FbxGeometryElement::eDirect:
							{
								for (int i=0; i<vertCount; ++i)
								{
									FbxColor c = vertColor->GetDirectArray().GetAt(i);
									vertices->addRGBColor(	static_cast<colorType>(c.mRed	* ccColor::MAX),
															static_cast<colorType>(c.mGreen	* ccColor::MAX),
															static_cast<colorType>(c.mBlue	* ccColor::MAX) );
								}
							}
							break;
						case FbxGeometryElement::eIndexToDirect:
							{
								for (int i=0; i<vertCount; ++i)
								{
									int id = vertColor->GetIndexArray().GetAt(i);
									FbxColor c = vertColor->GetDirectArray().GetAt(id);
									vertices->addRGBColor(	static_cast<colorType>(c.mRed	* ccColor::MAX),
															static_cast<colorType>(c.mGreen	* ccColor::MAX),
															static_cast<colorType>(c.mBlue	* ccColor::MAX) );
								}
							}
							break;
						default:
							assert(false);
							break;
						}

						vertices->showColors(true);
						mesh->showColors(true);
						break; //no need to look for other color fields (we won't be able to handle them!
					}
					else
					{
						ccLog::Warning(QString("[FBX] Not enough memory to load mesh '%1' colors!").arg(fbxMesh->GetName()));
					}
				}
				else
				{
					ccLog::Warning(QString("[FBX] Color field #%i of mesh '%1' will be ignored (unhandled type)").arg(l).arg(fbxMesh->GetName()));
				}
			}
			else
			{
				ccLog::Warning(QString("[FBX] Color field #%i of mesh '%1' will be ignored (unhandled type)").arg(l).arg(fbxMesh->GetName()));
			}
		}
	}

	//normals can be per vertices or per-triangle
	int perPointNormals = -1;
	int perVertexNormals = -1;
	int perPolygonNormals = -1;
	{
		for (int j=0; j<fbxMesh->GetElementNormalCount(); j++)
		{
			FbxGeometryElementNormal* leNormals = fbxMesh->GetElementNormal(j);
			switch(leNormals->GetMappingMode())
			{
			case FbxGeometryElement::eByControlPoint:
				perPointNormals = j;
				break;
			case FbxGeometryElement::eByPolygonVertex:
				perVertexNormals = j;
				break;
			case FbxGeometryElement::eByPolygon:
				perPolygonNormals = j;
				break;
			default:
				//not handled
				break;
			}
		}
	}

	//per-point normals
	if (perPointNormals >= 0)
	{
		FbxGeometryElementNormal* leNormals = fbxMesh->GetElementNormal(perPointNormals);
		FbxLayerElement::EReferenceMode refMode = leNormals->GetReferenceMode();
		const FbxLayerElementArrayTemplate<FbxVector4>& normals = leNormals->GetDirectArray();
		assert(normals.GetCount() == vertCount);
		if (normals.GetCount() != vertCount)
		{
			ccLog::Warning(QString("[FBX] Wrong number of normals on mesh '%1'!").arg(fbxMesh->GetName()));
			perPointNormals = -1;
		}
		else if (!vertices->reserveTheNormsTable())
		{
			ccLog::Warning(QString("[FBX] Not enough memory to load mesh '%1' normals!").arg(fbxMesh->GetName()));
			perPointNormals = -1;
		}
		else
		{
			//import normals
			for (int i=0; i<vertCount; ++i)
			{
				int id = refMode != FbxGeometryElement::eDirect ? leNormals->GetIndexArray().GetAt(i) : i;
				FbxVector4 N = normals.GetAt(id);
				//convert to CC-structure
				CCVector3 Npc(	static_cast<PointCoordinateType>(N.Buffer()[0]),
								static_cast<PointCoordinateType>(N.Buffer()[1]),
								static_cast<PointCoordinateType>(N.Buffer()[2]) );
				vertices->addNorm(Npc);
			}
			vertices->showNormals(true);
			mesh->showNormals(true);
			//no need to import the other normals (if any)
			perVertexNormals = -1;
			perPolygonNormals = -1;
		}
	}

	//per-triangle normals
	NormsIndexesTableType* normsTable = 0;
	if (perVertexNormals >= 0 || perPolygonNormals >= 0)
	{
		normsTable = new NormsIndexesTableType();
		if (!normsTable->reserve(polyVertCount) || !mesh->reservePerTriangleNormalIndexes())
		{
			ccLog::Warning(QString("[FBX] Not enough memory to load mesh '%1' normals!").arg(fbxMesh->GetName()));
			normsTable->release();
			normsTable = 0;
		}
		else
		{
			mesh->setTriNormsTable(normsTable);
			vertices->showNormals(true);
			mesh->showNormals(true);
		}
	}

	//materials
	ccMaterialSet* materials = 0;
	{
		FbxNode* lNode = fbxMesh->GetNode();
		int lMaterialCount = lNode ? lNode->GetMaterialCount() : 0;
		for (int i=0; i<lMaterialCount; i++)
		{
			FbxSurfaceMaterial *lBaseMaterial = lNode->GetMaterial(i);

			bool isLambert = lBaseMaterial->GetClassId().Is(FbxSurfaceLambert::ClassId);
			bool isPhong = lBaseMaterial->GetClassId().Is(FbxSurfacePhong::ClassId);
			if (isLambert || isPhong)
			{
				ccMaterial::Shared mat(new ccMaterial(lBaseMaterial->GetName()));

				FbxSurfaceLambert* lLambertMat = static_cast<FbxSurfaceLambert*>(lBaseMaterial);
			
				float ambient[4];
				float diffuse[4];
				float emission[4];
				float specular[4];

				FbxSurfacePhong* lPhongMat = isPhong ? static_cast<FbxSurfacePhong*>(lBaseMaterial) : 0;

				for (int k=0; k<3; ++k)
				{
					ambient[k]  = static_cast<float>(lLambertMat->Ambient.Get()[k]);
					diffuse[k]  = static_cast<float>(lLambertMat->Diffuse.Get()[k]);
					emission[k] = static_cast<float>(lLambertMat->Emissive.Get()[k]);

					if (lPhongMat)
					{
						specular[k]		= static_cast<float>(lPhongMat->Specular.Get()[k]);
					}
				}

				mat->setAmbient(ambient);
				mat->setDiffuse(diffuse);
				mat->setEmission(emission);
				if (isPhong)
				{
					mat->setSpecular(specular);
					assert(lPhongMat);
					mat->setShininess(static_cast<float>(lPhongMat->Shininess));
				}

				//import associated texture (if any)
				{
					int lTextureIndex;
					FBXSDK_FOR_EACH_TEXTURE(lTextureIndex)
					{
						FbxProperty lProperty = lBaseMaterial->FindProperty(FbxLayerElement::sTextureChannelNames[lTextureIndex]);
						if( lProperty.IsValid() )
						{
							int lTextureCount = lProperty.GetSrcObjectCount<FbxTexture>();
							FbxTexture* texture = 0; //we can handle only one texture per material! We'll take the non layered one by default (if any)
							for (int j = 0; j < lTextureCount; ++j)
							{
								//Here we have to check if it's layeredtextures, or just textures:
								FbxLayeredTexture *lLayeredTexture = lProperty.GetSrcObject<FbxLayeredTexture>(j);
								if (lLayeredTexture)
								{
									//we don't handle layered textures!
									/*int lNbTextures = lLayeredTexture->GetSrcObjectCount<FbxTexture>();
									for (int k=0; k<lNbTextures; ++k)
									{
										FbxTexture* lTexture = lLayeredTexture->GetSrcObject<FbxTexture>(k);
										if(lTexture)
										{
										}
									}
									//*/
								}
								else
								{
									//non-layered texture
									FbxTexture* lTexture = lProperty.GetSrcObject<FbxTexture>(j);
									if(lTexture)
									{
										//we take the first non layered texture by default
										texture = lTexture;
										break;
									}
								}
							}

							if (texture)
							{
								FbxFileTexture *lFileTexture = FbxCast<FbxFileTexture>(texture);
								if (lFileTexture)
								{
									const char* texAbsoluteFilename = lFileTexture->GetFileName();
									ccLog::PrintDebug(QString("[FBX] Texture absolue filename: %1").arg(texAbsoluteFilename));
									if (texAbsoluteFilename != 0 && texAbsoluteFilename[0] != 0)
									{
										if (!mat->loadAndSetTexture(texAbsoluteFilename))
										{
											ccLog::Warning(QString("[FBX] Failed to load texture file: %1").arg(texAbsoluteFilename));
										}
									}
								}
							}
						}
					}
				}

				if (!materials)
				{
					materials = new ccMaterialSet("materials");
					mesh->addChild(materials);
				}
				materials->addMaterial(mat);
			}
			else
			{
				ccLog::Warning(QString("[FBX] Material '%1' has an unhandled type").arg(lBaseMaterial->GetName()));
			}
		}