Materials
 
 
 
NoteThe sample code in this topic is also presented in the ExportScene03/main.cxx sample program.

Creating a Material

The KFbxSurfaceMaterial class is the base class for Lambertian (KFbxSurfaceLambert) and Phong (KFbxSurfacePhong) materials. In the following code sample, we create five materials and add them to the KFbxNode of a KFbxMesh via KFBxNode::AddMaterial(). Once materials are bound to a node, they can be mapped to the polygons of a mesh.

// Create materials for pyramid.
void CreateMaterials(KFbxScene* pScene, KFbxMesh* pMesh)
{
    int i;

    for (i = 0; i < 5; i++ )
    {
        KString lMaterialName = "material";
        KString lShadingName = "Phong";
        lMaterialName += i;
        fbxDouble3 lBlack(0.0, 0.0, 0.0);
        fbxDouble3 lRed(1.0, 0.0, 0.0);
        fbxDouble3 lColor;
        KFbxSurfacePhong *lMaterial = KFbxSurfacePhong::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.
        KFbxNode* 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. 
KFbxNode* CreatePyramidWithMaterials(KFbxScene* pScene, char* pName)
{
    int i, j;
    KFbxMesh* lMesh = KFbxMesh::Create(pScene, pName);

    KFbxVector4 lControlPoint0(-50, 0, 50);
    KFbxVector4 lControlPoint1(50, 0, 50);
    KFbxVector4 lControlPoint2(50, 0, -50);
    KFbxVector4 lControlPoint3(-50, 0, -50);
    KFbxVector4 lControlPoint4(0, 100, 0);

    KFbxVector4 lNormalP0(0, 1, 0);
    KFbxVector4 lNormalP1(0, 0.447, 0.894);
    KFbxVector4 lNormalP2(0.894, 0.447, 0);
    KFbxVector4 lNormalP3(0, 0.447, -0.894);
    KFbxVector4 lNormalP4(-0.894, 0.447, 0);

    // Create control points.
    lMesh->InitControlPoints(16);
    KFbxVector4* lControlPoints = lMesh->GetControlPoints();

    lControlPoints[0] = lControlPoint0;
    lControlPoints[1] = lControlPoint1;
    lControlPoints[2] = lControlPoint2;
    lControlPoints[3] = lControlPoint3;
    lControlPoints[4] = lControlPoint0;
    lControlPoints[5] = lControlPoint1;
    lControlPoints[6] = lControlPoint4;
    lControlPoints[7] = lControlPoint1;
    lControlPoints[8] = lControlPoint2;
    lControlPoints[9] = lControlPoint4;
    lControlPoints[10] = lControlPoint2;
    lControlPoints[11] = lControlPoint3;
    lControlPoints[12] = lControlPoint4;
    lControlPoints[13] = lControlPoint3;
    lControlPoints[14] = lControlPoint0;
    lControlPoints[15] = lControlPoint4;

    // specify normals per control point.

    KFbxGeometryElementNormal* lNormalElement= lMesh->CreateElementNormal();
    lNormalElement->SetMappingMode(KFbxGeometryElement::eBY_CONTROL_POINT);
    lNormalElement->SetReferenceMode(KFbxGeometryElement::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 (KFbxGeometryElementMaterial) within the mesh to specify that the materials are bound to the control points of the polygons in the mesh. The function KFbxMesh::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 KFbxNode.



    // 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.
    KFbxGeometryElementMaterial* lMaterialElement = lMesh->CreateElementMaterial();
    lMaterialElement->SetMappingMode(KFbxGeometryElement::eBY_POLYGON);
    lMaterialElement->SetReferenceMode(KFbxGeometryElement::eINDEX_TO_DIRECT);

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


    KFbxNode* lNode = KFbxNode::Create(pScene,pName);

    lNode->SetNodeAttribute(lMesh);

    CreateMaterials(pScene, lMesh);

    return lNode;
}