Materials

NOTE:The sample code in this topic is also presented in the ExportScene03/main.cxx sample program.

Creating a Material

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);
    }  
}

Example: Creating a Square Pyramid with Materials

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;
}