The FbxSurfaceMaterial class is the base class for Lambertian (FbxSurfaceLambert) and Phong (FbxSurfacePhong) materials. In the following code sample, we create five materials and add them to the FbxNode of a FbxMesh via FbxNode::AddMaterial(). Once materials are bound to a node, they can be mapped to the polygons of a mesh.
// Create materials for pyramid. void CreateMaterials(FbxScene* pScene, FbxMesh* pMesh) { int i; for (i = 0; i < 5; i++ ) { FbxString lMaterialName = "material"; FbxString lShadingName = "Phong"; lMaterialName += i; FbxDouble3 lBlack(0.0, 0.0, 0.0); FbxDouble3 lRed(1.0, 0.0, 0.0); FbxDouble3 lColor; FbxSurfacePhong *lMaterial = FbxSurfacePhong::Create(pScene, lMaterialName.Buffer()); // Generate primary and secondary colors. lMaterial->Emissive.Set(lBlack); lMaterial->Ambient.Set(lRed); lColor = FbxDouble3(i > 2 ? 1.0 : 0.0, i > 0 && i < 4 ? 1.0 : 0.0, i % 2 ? 0.0 : 1.0); lMaterial->Diffuse.Set(lColor); lMaterial->TransparencyFactor.Set(0.0); lMaterial->ShadingModel.Set(lShadingName); lMaterial->Shininess.Set(0.5); //get the node of mesh, add material for it. FbxNode* lNode = pMesh->GetNode(); if(lNode) lNode->AddMaterial(lMaterial); } }
The following code sample uses the CreateMaterials() function defined above to bind five materials to the five faces of a square pyramid. We first begin by defining the control points and the normals of the pyramid.
// Create a pyramid with materials. FbxNode* CreatePyramidWithMaterials(FbxScene* pScene, char* pName) { int i, j; FbxMesh* lMesh = FbxMesh::Create(pScene, pName); FbxVector4 vertex0(-50, 0, 50); FbxVector4 vertex1(50, 0, 50); FbxVector4 vertex2(50, 0, -50); FbxVector4 vertex3(-50, 0, -50); FbxVector4 vertex4(0, 100, 0); FbxVector4 lNormalP0(0, 1, 0); FbxVector4 lNormalP1(0, 0.447, 0.894); FbxVector4 lNormalP2(0.894, 0.447, 0); FbxVector4 lNormalP3(0, 0.447, -0.894); FbxVector4 lNormalP4(-0.894, 0.447, 0); // Create control points. lMesh->InitControlPoints(16); FbxVector4* lControlPoints = lMesh->GetControlPoints(); lControlPoints[0] = vertex0; lControlPoints[1] = vertex1; lControlPoints[2] = vertex2; lControlPoints[3] = vertex3; lControlPoints[4] = vertex0; lControlPoints[5] = vertex1; lControlPoints[6] = vertex4; lControlPoints[7] = vertex1; lControlPoints[8] = vertex2; lControlPoints[9] = vertex4; lControlPoints[10] = vertex2; lControlPoints[11] = vertex3; lControlPoints[12] = vertex4; lControlPoints[13] = vertex3; lControlPoints[14] = vertex0; lControlPoints[15] = vertex4; // specify normals per control point. FbxGeometryElementNormal* lNormalElement= lMesh->CreateElementNormal(); lNormalElement->SetMappingMode(FbxGeometryElement::eByControlPoint); lNormalElement->SetReferenceMode(FbxGeometryElement::eDirect); lNormalElement->GetDirectArray().Add(lNormalP0); lNormalElement->GetDirectArray().Add(lNormalP0); lNormalElement->GetDirectArray().Add(lNormalP0); lNormalElement->GetDirectArray().Add(lNormalP0); lNormalElement->GetDirectArray().Add(lNormalP1); lNormalElement->GetDirectArray().Add(lNormalP1); lNormalElement->GetDirectArray().Add(lNormalP1); lNormalElement->GetDirectArray().Add(lNormalP2); lNormalElement->GetDirectArray().Add(lNormalP2); lNormalElement->GetDirectArray().Add(lNormalP2); lNormalElement->GetDirectArray().Add(lNormalP3); lNormalElement->GetDirectArray().Add(lNormalP3); lNormalElement->GetDirectArray().Add(lNormalP3); lNormalElement->GetDirectArray().Add(lNormalP4); lNormalElement->GetDirectArray().Add(lNormalP4); lNormalElement->GetDirectArray().Add(lNormalP4);
We then create a new material layer element (FbxGeometryElementMaterial) within the mesh to specify that the materials are bound to the control points of the polygons in the mesh. The function FbxMesh::BeginPolygon() uses an index to determine which material will be bound to the new polygon. This index refers to the position of the material stored in the FbxNode.
// Array of polygon vertices. int lPolygonVertices[] = { 0, 3, 2, 1, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; // Set material mapping. FbxGeometryElementMaterial* lMaterialElement = lMesh->CreateElementMaterial(); lMaterialElement->SetMappingMode(FbxGeometryElement::eByPolygon); lMaterialElement->SetReferenceMode(FbxGeometryElement::eIndexToDirect); // Create polygons. Assign material indices. // Pyramid base. lMesh->BeginPolygon(0); // Material index. for(j = 0; j < 4; j++) { lMesh->AddPolygon(lPolygonVertices[j]); // Control point index. } lMesh->EndPolygon (); // Pyramid sides. for(i = 1; i < 5; i++) { lMesh->BeginPolygon(i); // Material index. for(j = 0; j < 3; j++) { lMesh->AddPolygon(lPolygonVertices[4 + 3*(i - 1) + j]); // Control point index. } lMesh->EndPolygon (); } FbxNode* lNode = FbxNode::Create(pScene,pName); lNode->SetNodeAttribute(lMesh); CreateMaterials(pScene, lMesh); return lNode; }